diff options
author | Wolfgang Grandegger <wg@grandegger.com> | 2009-05-15 19:39:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-18 18:41:42 -0400 |
commit | f534e52f091a7b9f51fb6726710bdf731b663e94 (patch) | |
tree | f1faad4e595abf44eae5a4942401f1fac14f1494 /drivers/net/can/sja1000 | |
parent | 429da1cc841bc9f2e762fd7272fc2b80314b890a (diff) |
can: SJA1000 generic platform bus driver
This driver adds support for the SJA1000 chips connected to the
"platform bus", which can be found on various embedded systems.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can/sja1000')
-rw-r--r-- | drivers/net/can/sja1000/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000_platform.c | 164 |
2 files changed, 165 insertions, 0 deletions
diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index 893ab2cfe244..5115cc90ab51 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile | |||
@@ -3,5 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_CAN_SJA1000) += sja1000.o | 5 | obj-$(CONFIG_CAN_SJA1000) += sja1000.o |
6 | obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o | ||
6 | 7 | ||
7 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | 8 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG |
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c new file mode 100644 index 000000000000..8017229d6fd6 --- /dev/null +++ b/drivers/net/can/sja1000/sja1000_platform.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Sascha Hauer, Pengutronix | ||
3 | * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the version 2 of the GNU General Public License | ||
7 | * as published by the Free Software Foundation | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/can.h> | ||
28 | #include <linux/can/dev.h> | ||
29 | #include <linux/can/platform/sja1000.h> | ||
30 | #include <linux/io.h> | ||
31 | |||
32 | #include "sja1000.h" | ||
33 | |||
34 | #define DRV_NAME "sja1000_platform" | ||
35 | |||
36 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
37 | MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus"); | ||
38 | MODULE_LICENSE("GPL v2"); | ||
39 | |||
40 | static u8 sp_read_reg(const struct net_device *dev, int reg) | ||
41 | { | ||
42 | return ioread8((void __iomem *)(dev->base_addr + reg)); | ||
43 | } | ||
44 | |||
45 | static void sp_write_reg(const struct net_device *dev, int reg, u8 val) | ||
46 | { | ||
47 | iowrite8(val, (void __iomem *)(dev->base_addr + reg)); | ||
48 | } | ||
49 | |||
50 | static int sp_probe(struct platform_device *pdev) | ||
51 | { | ||
52 | int err; | ||
53 | void __iomem *addr; | ||
54 | struct net_device *dev; | ||
55 | struct sja1000_priv *priv; | ||
56 | struct resource *res_mem, *res_irq; | ||
57 | struct sja1000_platform_data *pdata; | ||
58 | |||
59 | pdata = pdev->dev.platform_data; | ||
60 | if (!pdata) { | ||
61 | dev_err(&pdev->dev, "No platform data provided!\n"); | ||
62 | err = -ENODEV; | ||
63 | goto exit; | ||
64 | } | ||
65 | |||
66 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
67 | res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
68 | if (!res_mem || !res_irq) { | ||
69 | err = -ENODEV; | ||
70 | goto exit; | ||
71 | } | ||
72 | |||
73 | if (!request_mem_region(res_mem->start, resource_size(res_mem), | ||
74 | DRV_NAME)) { | ||
75 | err = -EBUSY; | ||
76 | goto exit; | ||
77 | } | ||
78 | |||
79 | addr = ioremap_nocache(res_mem->start, resource_size(res_mem)); | ||
80 | if (!addr) { | ||
81 | err = -ENOMEM; | ||
82 | goto exit_release; | ||
83 | } | ||
84 | |||
85 | dev = alloc_sja1000dev(0); | ||
86 | if (!dev) { | ||
87 | err = -ENOMEM; | ||
88 | goto exit_iounmap; | ||
89 | } | ||
90 | priv = netdev_priv(dev); | ||
91 | |||
92 | dev->base_addr = (unsigned long)addr; | ||
93 | dev->irq = res_irq->start; | ||
94 | priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; | ||
95 | priv->read_reg = sp_read_reg; | ||
96 | priv->write_reg = sp_write_reg; | ||
97 | priv->can.clock.freq = pdata->clock; | ||
98 | priv->ocr = pdata->ocr; | ||
99 | priv->cdr = pdata->cdr; | ||
100 | |||
101 | dev_set_drvdata(&pdev->dev, dev); | ||
102 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
103 | |||
104 | err = register_sja1000dev(dev); | ||
105 | if (err) { | ||
106 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", | ||
107 | DRV_NAME, err); | ||
108 | goto exit_free; | ||
109 | } | ||
110 | |||
111 | dev_info(&pdev->dev, "%s device registered (base_addr=%#lx, irq=%d)\n", | ||
112 | DRV_NAME, dev->base_addr, dev->irq); | ||
113 | return 0; | ||
114 | |||
115 | exit_free: | ||
116 | free_sja1000dev(dev); | ||
117 | exit_iounmap: | ||
118 | iounmap(addr); | ||
119 | exit_release: | ||
120 | release_mem_region(res_mem->start, resource_size(res_mem)); | ||
121 | exit: | ||
122 | return err; | ||
123 | } | ||
124 | |||
125 | static int sp_remove(struct platform_device *pdev) | ||
126 | { | ||
127 | struct net_device *dev = dev_get_drvdata(&pdev->dev); | ||
128 | struct resource *res; | ||
129 | |||
130 | unregister_sja1000dev(dev); | ||
131 | dev_set_drvdata(&pdev->dev, NULL); | ||
132 | |||
133 | if (dev->base_addr) | ||
134 | iounmap((void __iomem *)dev->base_addr); | ||
135 | |||
136 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
137 | release_mem_region(res->start, resource_size(res)); | ||
138 | |||
139 | free_sja1000dev(dev); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static struct platform_driver sp_driver = { | ||
145 | .probe = sp_probe, | ||
146 | .remove = sp_remove, | ||
147 | .driver = { | ||
148 | .name = DRV_NAME, | ||
149 | .owner = THIS_MODULE, | ||
150 | }, | ||
151 | }; | ||
152 | |||
153 | static int __init sp_init(void) | ||
154 | { | ||
155 | return platform_driver_register(&sp_driver); | ||
156 | } | ||
157 | |||
158 | static void __exit sp_exit(void) | ||
159 | { | ||
160 | platform_driver_unregister(&sp_driver); | ||
161 | } | ||
162 | |||
163 | module_init(sp_init); | ||
164 | module_exit(sp_exit); | ||