Add hotplug support to mcp251x driver

Chip model can now be selected directly by matching the modalias name
(instead of filling the .model field in platform_data), and allows the
module to be auto-loaded. Previous behaviour is of course still supported.

Convert the two in-tree users to this feature (icontrol & zeus).
Tested on an Zeus platform (mcp2515).

Signed-off-by: Marc Zyngier <maz@misterjones.org>
Acked-by: Christian Pellegrin <chripell@fsfe.org>
Cc: Edwin Peer <epeer@tmtservices.co.za>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Marc Zyngier 2010-03-29 08:57:56 +00:00 committed by David S. Miller
parent 598ed9367a
commit e446630c96
4 changed files with 21 additions and 10 deletions

View file

@ -73,7 +73,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = {
static struct mcp251x_platform_data mcp251x_info = {
.oscillator_frequency = 16E6,
.model = CAN_MCP251X_MCP2515,
.board_specific_setup = NULL,
.power_enable = NULL,
.transceiver_enable = NULL
@ -81,7 +80,7 @@ static struct mcp251x_platform_data mcp251x_info = {
static struct spi_board_info mcp251x_board_info[] = {
{
.modalias = "mcp251x",
.modalias = "mcp2515",
.max_speed_hz = 6500000,
.bus_num = 3,
.chip_select = 0,
@ -90,7 +89,7 @@ static struct spi_board_info mcp251x_board_info[] = {
.irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ1)
},
{
.modalias = "mcp251x",
.modalias = "mcp2515",
.max_speed_hz = 6500000,
.bus_num = 3,
.chip_select = 1,
@ -99,7 +98,7 @@ static struct spi_board_info mcp251x_board_info[] = {
.irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ2)
},
{
.modalias = "mcp251x",
.modalias = "mcp2515",
.max_speed_hz = 6500000,
.bus_num = 4,
.chip_select = 0,
@ -108,7 +107,7 @@ static struct spi_board_info mcp251x_board_info[] = {
.irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ3)
},
{
.modalias = "mcp251x",
.modalias = "mcp2515",
.max_speed_hz = 6500000,
.bus_num = 4,
.chip_select = 1,

View file

@ -414,15 +414,13 @@ static int zeus_mcp2515_transceiver_enable(int enable)
static struct mcp251x_platform_data zeus_mcp2515_pdata = {
.oscillator_frequency = 16*1000*1000,
.model = CAN_MCP251X_MCP2515,
.board_specific_setup = zeus_mcp2515_setup,
.transceiver_enable = zeus_mcp2515_transceiver_enable,
.power_enable = zeus_mcp2515_transceiver_enable,
};
static struct spi_board_info zeus_spi_board_info[] = {
[0] = {
.modalias = "mcp251x",
.modalias = "mcp2515",
.platform_data = &zeus_mcp2515_pdata,
.irq = gpio_to_irq(ZEUS_CAN_GPIO),
.max_speed_hz = 1*1000*1000,

View file

@ -922,12 +922,16 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
struct net_device *net;
struct mcp251x_priv *priv;
struct mcp251x_platform_data *pdata = spi->dev.platform_data;
int model = spi_get_device_id(spi)->driver_data;
int ret = -ENODEV;
if (!pdata)
/* Platform data is required for osc freq */
goto error_out;
if (model)
pdata->model = model;
/* Allocate can/net device */
net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
if (!net) {
@ -1117,6 +1121,15 @@ static int mcp251x_can_resume(struct spi_device *spi)
#define mcp251x_can_resume NULL
#endif
static struct spi_device_id mcp251x_id_table[] = {
{ "mcp251x", 0 /* Use pdata.model */ },
{ "mcp2510", CAN_MCP251X_MCP2510 },
{ "mcp2515", CAN_MCP251X_MCP2515 },
{ },
};
MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
static struct spi_driver mcp251x_can_driver = {
.driver = {
.name = DEVICE_NAME,
@ -1124,6 +1137,7 @@ static struct spi_driver mcp251x_can_driver = {
.owner = THIS_MODULE,
},
.id_table = mcp251x_id_table,
.probe = mcp251x_can_probe,
.remove = __devexit_p(mcp251x_can_remove),
.suspend = mcp251x_can_suspend,

View file

@ -26,8 +26,8 @@
struct mcp251x_platform_data {
unsigned long oscillator_frequency;
int model;
#define CAN_MCP251X_MCP2510 0
#define CAN_MCP251X_MCP2515 1
#define CAN_MCP251X_MCP2510 0x2510
#define CAN_MCP251X_MCP2515 0x2515
int (*board_specific_setup)(struct spi_device *spi);
int (*transceiver_enable)(int enable);
int (*power_enable) (int enable);