diff options
author | Wolfgang Grandegger <wg@grandegger.com> | 2011-11-23 18:58:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-29 18:35:51 -0500 |
commit | 1839a6c6f1eb8c0e20dc87d57024a85707f1a2f8 (patch) | |
tree | 0c00692dd88faf21efe74716fe4781c7bb15df29 /drivers/net/can | |
parent | e92036a6516d07f61d4c214970a35ff05b919c25 (diff) |
can: sja1000_isa: convert to platform driver to support x86_64 systems
This driver is currently not supported on x86_64 systems because the
"isa_driver" interface is used (CONFIG_ISA=y). To overcome this
limitation, the driver is converted to a platform driver, similar to
the serial 8250 driver.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/sja1000/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000_isa.c | 94 |
2 files changed, 65 insertions, 30 deletions
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index fe9e64d476eb..36e9d594069d 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig | |||
@@ -6,7 +6,6 @@ if CAN_SJA1000 | |||
6 | 6 | ||
7 | config CAN_SJA1000_ISA | 7 | config CAN_SJA1000_ISA |
8 | tristate "ISA Bus based legacy SJA1000 driver" | 8 | tristate "ISA Bus based legacy SJA1000 driver" |
9 | depends on ISA | ||
10 | ---help--- | 9 | ---help--- |
11 | This driver adds legacy support for SJA1000 chips connected to | 10 | This driver adds legacy support for SJA1000 chips connected to |
12 | the ISA bus using I/O port, memory mapped or indirect access. | 11 | the ISA bus using I/O port, memory mapped or indirect access. |
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index f0840d55ab72..90c5c2dfd2fd 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/isa.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
@@ -75,6 +75,8 @@ MODULE_PARM_DESC(ocr, "Output control register " | |||
75 | #define SJA1000_IOSIZE 0x20 | 75 | #define SJA1000_IOSIZE 0x20 |
76 | #define SJA1000_IOSIZE_INDIRECT 0x02 | 76 | #define SJA1000_IOSIZE_INDIRECT 0x02 |
77 | 77 | ||
78 | static struct platform_device *sja1000_isa_devs[MAXDEV]; | ||
79 | |||
78 | static u8 sja1000_isa_mem_read_reg(const struct sja1000_priv *priv, int reg) | 80 | static u8 sja1000_isa_mem_read_reg(const struct sja1000_priv *priv, int reg) |
79 | { | 81 | { |
80 | return readb(priv->reg_base + reg); | 82 | return readb(priv->reg_base + reg); |
@@ -115,26 +117,18 @@ static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv, | |||
115 | outb(val, base + 1); | 117 | outb(val, base + 1); |
116 | } | 118 | } |
117 | 119 | ||
118 | static int __devinit sja1000_isa_match(struct device *pdev, unsigned int idx) | 120 | static int __devinit sja1000_isa_probe(struct platform_device *pdev) |
119 | { | ||
120 | if (port[idx] || mem[idx]) { | ||
121 | if (irq[idx]) | ||
122 | return 1; | ||
123 | } else if (idx) | ||
124 | return 0; | ||
125 | |||
126 | dev_err(pdev, "insufficient parameters supplied\n"); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int __devinit sja1000_isa_probe(struct device *pdev, unsigned int idx) | ||
131 | { | 121 | { |
132 | struct net_device *dev; | 122 | struct net_device *dev; |
133 | struct sja1000_priv *priv; | 123 | struct sja1000_priv *priv; |
134 | void __iomem *base = NULL; | 124 | void __iomem *base = NULL; |
135 | int iosize = SJA1000_IOSIZE; | 125 | int iosize = SJA1000_IOSIZE; |
126 | int idx = pdev->id; | ||
136 | int err; | 127 | int err; |
137 | 128 | ||
129 | dev_dbg(&pdev->dev, "probing idx=%d: port=%#lx, mem=%#lx, irq=%d\n", | ||
130 | idx, port[idx], mem[idx], irq[idx]); | ||
131 | |||
138 | if (mem[idx]) { | 132 | if (mem[idx]) { |
139 | if (!request_mem_region(mem[idx], iosize, DRV_NAME)) { | 133 | if (!request_mem_region(mem[idx], iosize, DRV_NAME)) { |
140 | err = -EBUSY; | 134 | err = -EBUSY; |
@@ -203,17 +197,17 @@ static int __devinit sja1000_isa_probe(struct device *pdev, unsigned int idx) | |||
203 | else | 197 | else |
204 | priv->cdr = CDR_DEFAULT; | 198 | priv->cdr = CDR_DEFAULT; |
205 | 199 | ||
206 | dev_set_drvdata(pdev, dev); | 200 | dev_set_drvdata(&pdev->dev, dev); |
207 | SET_NETDEV_DEV(dev, pdev); | 201 | SET_NETDEV_DEV(dev, &pdev->dev); |
208 | 202 | ||
209 | err = register_sja1000dev(dev); | 203 | err = register_sja1000dev(dev); |
210 | if (err) { | 204 | if (err) { |
211 | dev_err(pdev, "registering %s failed (err=%d)\n", | 205 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", |
212 | DRV_NAME, err); | 206 | DRV_NAME, err); |
213 | goto exit_unmap; | 207 | goto exit_unmap; |
214 | } | 208 | } |
215 | 209 | ||
216 | dev_info(pdev, "%s device registered (reg_base=0x%p, irq=%d)\n", | 210 | dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n", |
217 | DRV_NAME, priv->reg_base, dev->irq); | 211 | DRV_NAME, priv->reg_base, dev->irq); |
218 | return 0; | 212 | return 0; |
219 | 213 | ||
@@ -229,13 +223,14 @@ static int __devinit sja1000_isa_probe(struct device *pdev, unsigned int idx) | |||
229 | return err; | 223 | return err; |
230 | } | 224 | } |
231 | 225 | ||
232 | static int __devexit sja1000_isa_remove(struct device *pdev, unsigned int idx) | 226 | static int __devexit sja1000_isa_remove(struct platform_device *pdev) |
233 | { | 227 | { |
234 | struct net_device *dev = dev_get_drvdata(pdev); | 228 | struct net_device *dev = dev_get_drvdata(&pdev->dev); |
235 | struct sja1000_priv *priv = netdev_priv(dev); | 229 | struct sja1000_priv *priv = netdev_priv(dev); |
230 | int idx = pdev->id; | ||
236 | 231 | ||
237 | unregister_sja1000dev(dev); | 232 | unregister_sja1000dev(dev); |
238 | dev_set_drvdata(pdev, NULL); | 233 | dev_set_drvdata(&pdev->dev, NULL); |
239 | 234 | ||
240 | if (mem[idx]) { | 235 | if (mem[idx]) { |
241 | iounmap(priv->reg_base); | 236 | iounmap(priv->reg_base); |
@@ -251,29 +246,70 @@ static int __devexit sja1000_isa_remove(struct device *pdev, unsigned int idx) | |||
251 | return 0; | 246 | return 0; |
252 | } | 247 | } |
253 | 248 | ||
254 | static struct isa_driver sja1000_isa_driver = { | 249 | static struct platform_driver sja1000_isa_driver = { |
255 | .match = sja1000_isa_match, | ||
256 | .probe = sja1000_isa_probe, | 250 | .probe = sja1000_isa_probe, |
257 | .remove = __devexit_p(sja1000_isa_remove), | 251 | .remove = __devexit_p(sja1000_isa_remove), |
258 | .driver = { | 252 | .driver = { |
259 | .name = DRV_NAME, | 253 | .name = DRV_NAME, |
254 | .owner = THIS_MODULE, | ||
260 | }, | 255 | }, |
261 | }; | 256 | }; |
262 | 257 | ||
263 | static int __init sja1000_isa_init(void) | 258 | static int __init sja1000_isa_init(void) |
264 | { | 259 | { |
265 | int err = isa_register_driver(&sja1000_isa_driver, MAXDEV); | 260 | int idx, err; |
261 | |||
262 | for (idx = 0; idx < MAXDEV; idx++) { | ||
263 | if ((port[idx] || mem[idx]) && irq[idx]) { | ||
264 | sja1000_isa_devs[idx] = | ||
265 | platform_device_alloc(DRV_NAME, idx); | ||
266 | if (!sja1000_isa_devs[idx]) { | ||
267 | err = -ENOMEM; | ||
268 | goto exit_free_devices; | ||
269 | } | ||
270 | err = platform_device_add(sja1000_isa_devs[idx]); | ||
271 | if (err) { | ||
272 | platform_device_put(sja1000_isa_devs[idx]); | ||
273 | goto exit_free_devices; | ||
274 | } | ||
275 | pr_debug("%s: platform device %d: port=%#lx, mem=%#lx, " | ||
276 | "irq=%d\n", | ||
277 | DRV_NAME, idx, port[idx], mem[idx], irq[idx]); | ||
278 | } else if (idx == 0 || port[idx] || mem[idx]) { | ||
279 | pr_err("%s: insufficient parameters supplied\n", | ||
280 | DRV_NAME); | ||
281 | err = -EINVAL; | ||
282 | goto exit_free_devices; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | err = platform_driver_register(&sja1000_isa_driver); | ||
287 | if (err) | ||
288 | goto exit_free_devices; | ||
289 | |||
290 | pr_info("Legacy %s driver for max. %d devices registered\n", | ||
291 | DRV_NAME, MAXDEV); | ||
292 | |||
293 | return 0; | ||
294 | |||
295 | exit_free_devices: | ||
296 | while (--idx >= 0) { | ||
297 | if (sja1000_isa_devs[idx]) | ||
298 | platform_device_unregister(sja1000_isa_devs[idx]); | ||
299 | } | ||
266 | 300 | ||
267 | if (!err) | ||
268 | printk(KERN_INFO | ||
269 | "Legacy %s driver for max. %d devices registered\n", | ||
270 | DRV_NAME, MAXDEV); | ||
271 | return err; | 301 | return err; |
272 | } | 302 | } |
273 | 303 | ||
274 | static void __exit sja1000_isa_exit(void) | 304 | static void __exit sja1000_isa_exit(void) |
275 | { | 305 | { |
276 | isa_unregister_driver(&sja1000_isa_driver); | 306 | int idx; |
307 | |||
308 | platform_driver_unregister(&sja1000_isa_driver); | ||
309 | for (idx = 0; idx < MAXDEV; idx++) { | ||
310 | if (sja1000_isa_devs[idx]) | ||
311 | platform_device_unregister(sja1000_isa_devs[idx]); | ||
312 | } | ||
277 | } | 313 | } |
278 | 314 | ||
279 | module_init(sja1000_isa_init); | 315 | module_init(sja1000_isa_init); |