diff options
-rw-r--r-- | Documentation/devicetree/bindings/net/can/atmel-can.txt | 14 | ||||
-rw-r--r-- | drivers/net/can/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/can/at91_can.c | 76 | ||||
-rw-r--r-- | drivers/net/can/bfin_can.c | 4 | ||||
-rw-r--r-- | drivers/net/can/mcp251x.c | 35 |
5 files changed, 88 insertions, 43 deletions
diff --git a/Documentation/devicetree/bindings/net/can/atmel-can.txt b/Documentation/devicetree/bindings/net/can/atmel-can.txt new file mode 100644 index 0000000..72cf0c5 --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/atmel-can.txt @@ -0,0 +1,14 @@ +* AT91 CAN * + +Required properties: + - compatible: Should be "atmel,at91sam9263-can" or "atmel,at91sam9x5-can" + - reg: Should contain CAN controller registers location and length + - interrupts: Should contain IRQ line for the CAN controller + +Example: + + can0: can@f000c000 { + compatbile = "atmel,at91sam9x5-can"; + reg = <0xf000c000 0x300>; + interrupts = <40 4 5> + }; diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 9862b2e..e456b70 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -65,7 +65,7 @@ config CAN_LEDS config CAN_AT91 tristate "Atmel AT91 onchip CAN controller" - depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5 + depends on ARM ---help--- This is a driver for the SoC CAN controller in Atmel's AT91SAM9263 and AT91SAM9X5 processors. diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 44f3637..db52f441 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -27,6 +27,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/netdevice.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/rtnetlink.h> #include <linux/skbuff.h> @@ -155,19 +156,20 @@ struct at91_priv { canid_t mb0_id; }; -static const struct at91_devtype_data at91_devtype_data[] = { - [AT91_DEVTYPE_SAM9263] = { - .rx_first = 1, - .rx_split = 8, - .rx_last = 11, - .tx_shift = 2, - }, - [AT91_DEVTYPE_SAM9X5] = { - .rx_first = 0, - .rx_split = 4, - .rx_last = 5, - .tx_shift = 1, - }, +static const struct at91_devtype_data at91_at91sam9263_data = { + .rx_first = 1, + .rx_split = 8, + .rx_last = 11, + .tx_shift = 2, + .type = AT91_DEVTYPE_SAM9263, +}; + +static const struct at91_devtype_data at91_at91sam9x5_data = { + .rx_first = 0, + .rx_split = 4, + .rx_last = 5, + .tx_shift = 1, + .type = AT91_DEVTYPE_SAM9X5, }; static const struct can_bittiming_const at91_bittiming_const = { @@ -1249,10 +1251,42 @@ static struct attribute_group at91_sysfs_attr_group = { .attrs = at91_sysfs_attrs, }; +#if defined(CONFIG_OF) +static const struct of_device_id at91_can_dt_ids[] = { + { + .compatible = "atmel,at91sam9x5-can", + .data = &at91_at91sam9x5_data, + }, { + .compatible = "atmel,at91sam9263-can", + .data = &at91_at91sam9263_data, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, at91_can_dt_ids); +#else +#define at91_can_dt_ids NULL +#endif + +static const struct at91_devtype_data *at91_can_get_driver_data(struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + + match = of_match_node(at91_can_dt_ids, pdev->dev.of_node); + if (!match) { + dev_err(&pdev->dev, "no matching node found in dtb\n"); + return NULL; + } + return (const struct at91_devtype_data *)match->data; + } + return (const struct at91_devtype_data *) + platform_get_device_id(pdev)->driver_data; +} + static int at91_can_probe(struct platform_device *pdev) { const struct at91_devtype_data *devtype_data; - enum at91_devtype devtype; struct net_device *dev; struct at91_priv *priv; struct resource *res; @@ -1260,8 +1294,12 @@ static int at91_can_probe(struct platform_device *pdev) void __iomem *addr; int err, irq; - devtype = pdev->id_entry->driver_data; - devtype_data = &at91_devtype_data[devtype]; + devtype_data = at91_can_get_driver_data(pdev); + if (!devtype_data) { + dev_err(&pdev->dev, "no driver data\n"); + err = -ENODEV; + goto exit; + } clk = clk_get(&pdev->dev, "can_clk"); if (IS_ERR(clk)) { @@ -1310,7 +1348,6 @@ static int at91_can_probe(struct platform_device *pdev) priv->dev = dev; priv->reg_base = addr; priv->devtype_data = *devtype_data; - priv->devtype_data.type = devtype; priv->clk = clk; priv->pdata = pdev->dev.platform_data; priv->mb0_id = 0x7ff; @@ -1373,10 +1410,10 @@ static int at91_can_remove(struct platform_device *pdev) static const struct platform_device_id at91_can_id_table[] = { { .name = "at91_can", - .driver_data = AT91_DEVTYPE_SAM9263, + .driver_data = (kernel_ulong_t)&at91_at91sam9x5_data, }, { .name = "at91sam9x5_can", - .driver_data = AT91_DEVTYPE_SAM9X5, + .driver_data = (kernel_ulong_t)&at91_at91sam9263_data, }, { /* sentinel */ } @@ -1389,6 +1426,7 @@ static struct platform_driver at91_can_driver = { .driver = { .name = KBUILD_MODNAME, .owner = THIS_MODULE, + .of_match_table = at91_can_dt_ids, }, .id_table = at91_can_id_table, }; diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 6a05321..d4a15e8 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -412,7 +412,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) return 0; } -irqreturn_t bfin_can_interrupt(int irq, void *dev_id) +static irqreturn_t bfin_can_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct bfin_can_priv *priv = netdev_priv(dev); @@ -504,7 +504,7 @@ static int bfin_can_close(struct net_device *dev) return 0; } -struct net_device *alloc_bfin_candev(void) +static struct net_device *alloc_bfin_candev(void) { struct net_device *dev; struct bfin_can_priv *priv; diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index f32b9fc..2b620c8 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -1138,9 +1138,11 @@ static int mcp251x_can_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP + +static int mcp251x_can_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct mcp251x_platform_data *pdata = spi->dev.platform_data; struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); struct net_device *net = priv->net; @@ -1170,8 +1172,9 @@ static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state) return 0; } -static int mcp251x_can_resume(struct spi_device *spi) +static int mcp251x_can_resume(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct mcp251x_platform_data *pdata = spi->dev.platform_data; struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); @@ -1191,9 +1194,13 @@ static int mcp251x_can_resume(struct spi_device *spi) enable_irq(spi->irq); return 0; } + +static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend, + mcp251x_can_resume); +#define MCP251X_PM_OPS (&mcp251x_can_pm_ops) + #else -#define mcp251x_can_suspend NULL -#define mcp251x_can_resume NULL +#define MCP251X_PM_OPS NULL #endif static const struct spi_device_id mcp251x_id_table[] = { @@ -1207,29 +1214,15 @@ MODULE_DEVICE_TABLE(spi, mcp251x_id_table); static struct spi_driver mcp251x_can_driver = { .driver = { .name = DEVICE_NAME, - .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = MCP251X_PM_OPS, }, .id_table = mcp251x_id_table, .probe = mcp251x_can_probe, .remove = mcp251x_can_remove, - .suspend = mcp251x_can_suspend, - .resume = mcp251x_can_resume, }; - -static int __init mcp251x_can_init(void) -{ - return spi_register_driver(&mcp251x_can_driver); -} - -static void __exit mcp251x_can_exit(void) -{ - spi_unregister_driver(&mcp251x_can_driver); -} - -module_init(mcp251x_can_init); -module_exit(mcp251x_can_exit); +module_spi_driver(mcp251x_can_driver); MODULE_AUTHOR("Chris Elston <celston@katalix.com>, " "Christian Pellegrin <chripell@evolware.org>"); |