diff options
Diffstat (limited to 'drivers/net/can/sja1000/sja1000_isa.c')
-rw-r--r-- | drivers/net/can/sja1000/sja1000_isa.c | 124 |
1 files changed, 44 insertions, 80 deletions
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index 5c8da466148..496223e9e2f 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/platform_device.h> | 20 | #include <linux/isa.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> |
@@ -42,11 +42,11 @@ MODULE_LICENSE("GPL v2"); | |||
42 | 42 | ||
43 | static unsigned long port[MAXDEV]; | 43 | static unsigned long port[MAXDEV]; |
44 | static unsigned long mem[MAXDEV]; | 44 | static unsigned long mem[MAXDEV]; |
45 | static int irq[MAXDEV]; | 45 | static int __devinitdata irq[MAXDEV]; |
46 | static int clk[MAXDEV]; | 46 | static int __devinitdata clk[MAXDEV]; |
47 | static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; | 47 | static char __devinitdata cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; |
48 | static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; | 48 | static char __devinitdata ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; |
49 | static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; | 49 | static char __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; |
50 | 50 | ||
51 | module_param_array(port, ulong, NULL, S_IRUGO); | 51 | module_param_array(port, ulong, NULL, S_IRUGO); |
52 | MODULE_PARM_DESC(port, "I/O port number"); | 52 | MODULE_PARM_DESC(port, "I/O port number"); |
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(port, "I/O port number"); | |||
54 | module_param_array(mem, ulong, NULL, S_IRUGO); | 54 | module_param_array(mem, ulong, NULL, S_IRUGO); |
55 | MODULE_PARM_DESC(mem, "I/O memory address"); | 55 | MODULE_PARM_DESC(mem, "I/O memory address"); |
56 | 56 | ||
57 | module_param_array(indirect, int, NULL, S_IRUGO); | 57 | module_param_array(indirect, byte, NULL, S_IRUGO); |
58 | MODULE_PARM_DESC(indirect, "Indirect access via address and data port"); | 58 | MODULE_PARM_DESC(indirect, "Indirect access via address and data port"); |
59 | 59 | ||
60 | module_param_array(irq, int, NULL, S_IRUGO); | 60 | module_param_array(irq, int, NULL, S_IRUGO); |
@@ -75,8 +75,6 @@ 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 | |||
80 | static u8 sja1000_isa_mem_read_reg(const struct sja1000_priv *priv, int reg) | 78 | static u8 sja1000_isa_mem_read_reg(const struct sja1000_priv *priv, int reg) |
81 | { | 79 | { |
82 | return readb(priv->reg_base + reg); | 80 | return readb(priv->reg_base + reg); |
@@ -117,18 +115,26 @@ static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv, | |||
117 | outb(val, base + 1); | 115 | outb(val, base + 1); |
118 | } | 116 | } |
119 | 117 | ||
120 | static int sja1000_isa_probe(struct platform_device *pdev) | 118 | static int __devinit sja1000_isa_match(struct device *pdev, unsigned int idx) |
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) | ||
121 | { | 131 | { |
122 | struct net_device *dev; | 132 | struct net_device *dev; |
123 | struct sja1000_priv *priv; | 133 | struct sja1000_priv *priv; |
124 | void __iomem *base = NULL; | 134 | void __iomem *base = NULL; |
125 | int iosize = SJA1000_IOSIZE; | 135 | int iosize = SJA1000_IOSIZE; |
126 | int idx = pdev->id; | ||
127 | int err; | 136 | int err; |
128 | 137 | ||
129 | dev_dbg(&pdev->dev, "probing idx=%d: port=%#lx, mem=%#lx, irq=%d\n", | ||
130 | idx, port[idx], mem[idx], irq[idx]); | ||
131 | |||
132 | if (mem[idx]) { | 138 | if (mem[idx]) { |
133 | if (!request_mem_region(mem[idx], iosize, DRV_NAME)) { | 139 | if (!request_mem_region(mem[idx], iosize, DRV_NAME)) { |
134 | err = -EBUSY; | 140 | err = -EBUSY; |
@@ -183,31 +189,31 @@ static int sja1000_isa_probe(struct platform_device *pdev) | |||
183 | else | 189 | else |
184 | priv->can.clock.freq = CLK_DEFAULT / 2; | 190 | priv->can.clock.freq = CLK_DEFAULT / 2; |
185 | 191 | ||
186 | if (ocr[idx] != 0xff) | 192 | if (ocr[idx] != -1) |
187 | priv->ocr = ocr[idx]; | 193 | priv->ocr = ocr[idx] & 0xff; |
188 | else if (ocr[0] != 0xff) | 194 | else if (ocr[0] != -1) |
189 | priv->ocr = ocr[0]; | 195 | priv->ocr = ocr[0] & 0xff; |
190 | else | 196 | else |
191 | priv->ocr = OCR_DEFAULT; | 197 | priv->ocr = OCR_DEFAULT; |
192 | 198 | ||
193 | if (cdr[idx] != 0xff) | 199 | if (cdr[idx] != -1) |
194 | priv->cdr = cdr[idx]; | 200 | priv->cdr = cdr[idx] & 0xff; |
195 | else if (cdr[0] != 0xff) | 201 | else if (cdr[0] != -1) |
196 | priv->cdr = cdr[0]; | 202 | priv->cdr = cdr[0] & 0xff; |
197 | else | 203 | else |
198 | priv->cdr = CDR_DEFAULT; | 204 | priv->cdr = CDR_DEFAULT; |
199 | 205 | ||
200 | dev_set_drvdata(&pdev->dev, dev); | 206 | dev_set_drvdata(pdev, dev); |
201 | SET_NETDEV_DEV(dev, &pdev->dev); | 207 | SET_NETDEV_DEV(dev, pdev); |
202 | 208 | ||
203 | err = register_sja1000dev(dev); | 209 | err = register_sja1000dev(dev); |
204 | if (err) { | 210 | if (err) { |
205 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", | 211 | dev_err(pdev, "registering %s failed (err=%d)\n", |
206 | DRV_NAME, err); | 212 | DRV_NAME, err); |
207 | goto exit_unmap; | 213 | goto exit_unmap; |
208 | } | 214 | } |
209 | 215 | ||
210 | dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n", | 216 | dev_info(pdev, "%s device registered (reg_base=0x%p, irq=%d)\n", |
211 | DRV_NAME, priv->reg_base, dev->irq); | 217 | DRV_NAME, priv->reg_base, dev->irq); |
212 | return 0; | 218 | return 0; |
213 | 219 | ||
@@ -223,14 +229,13 @@ static int sja1000_isa_probe(struct platform_device *pdev) | |||
223 | return err; | 229 | return err; |
224 | } | 230 | } |
225 | 231 | ||
226 | static int sja1000_isa_remove(struct platform_device *pdev) | 232 | static int __devexit sja1000_isa_remove(struct device *pdev, unsigned int idx) |
227 | { | 233 | { |
228 | struct net_device *dev = dev_get_drvdata(&pdev->dev); | 234 | struct net_device *dev = dev_get_drvdata(pdev); |
229 | struct sja1000_priv *priv = netdev_priv(dev); | 235 | struct sja1000_priv *priv = netdev_priv(dev); |
230 | int idx = pdev->id; | ||
231 | 236 | ||
232 | unregister_sja1000dev(dev); | 237 | unregister_sja1000dev(dev); |
233 | dev_set_drvdata(&pdev->dev, NULL); | 238 | dev_set_drvdata(pdev, NULL); |
234 | 239 | ||
235 | if (mem[idx]) { | 240 | if (mem[idx]) { |
236 | iounmap(priv->reg_base); | 241 | iounmap(priv->reg_base); |
@@ -246,70 +251,29 @@ static int sja1000_isa_remove(struct platform_device *pdev) | |||
246 | return 0; | 251 | return 0; |
247 | } | 252 | } |
248 | 253 | ||
249 | static struct platform_driver sja1000_isa_driver = { | 254 | static struct isa_driver sja1000_isa_driver = { |
255 | .match = sja1000_isa_match, | ||
250 | .probe = sja1000_isa_probe, | 256 | .probe = sja1000_isa_probe, |
251 | .remove = sja1000_isa_remove, | 257 | .remove = __devexit_p(sja1000_isa_remove), |
252 | .driver = { | 258 | .driver = { |
253 | .name = DRV_NAME, | 259 | .name = DRV_NAME, |
254 | .owner = THIS_MODULE, | ||
255 | }, | 260 | }, |
256 | }; | 261 | }; |
257 | 262 | ||
258 | static int __init sja1000_isa_init(void) | 263 | static int __init sja1000_isa_init(void) |
259 | { | 264 | { |
260 | int idx, err; | 265 | int err = isa_register_driver(&sja1000_isa_driver, MAXDEV); |
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 | } | ||
300 | 266 | ||
267 | if (!err) | ||
268 | printk(KERN_INFO | ||
269 | "Legacy %s driver for max. %d devices registered\n", | ||
270 | DRV_NAME, MAXDEV); | ||
301 | return err; | 271 | return err; |
302 | } | 272 | } |
303 | 273 | ||
304 | static void __exit sja1000_isa_exit(void) | 274 | static void __exit sja1000_isa_exit(void) |
305 | { | 275 | { |
306 | int idx; | 276 | isa_unregister_driver(&sja1000_isa_driver); |
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 | } | ||
313 | } | 277 | } |
314 | 278 | ||
315 | module_init(sja1000_isa_init); | 279 | module_init(sja1000_isa_init); |