]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/arcnet/com20020-pci.c
arcnet: com20020-pci: add missing pdev setup in netdev structure
[mirror_ubuntu-artful-kernel.git] / drivers / net / arcnet / com20020-pci.c
1 /*
2 * Linux ARCnet driver - COM20020 PCI support
3 * Contemporary Controls PCI20 and SOHARD SH-ARC PCI
4 *
5 * Written 1994-1999 by Avery Pennarun,
6 * based on an ISA version by David Woodhouse.
7 * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
8 * Derived from skeleton.c by Donald Becker.
9 *
10 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
11 * for sponsoring the further development of this driver.
12 *
13 * **********************
14 *
15 * The original copyright of skeleton.c was as follows:
16 *
17 * skeleton.c Written 1993 by Donald Becker.
18 * Copyright 1993 United States Government as represented by the
19 * Director, National Security Agency. This software may only be used
20 * and distributed according to the terms of the GNU General Public License as
21 * modified by SRC, incorporated herein by reference.
22 *
23 * **********************
24 *
25 * For more details, see drivers/net/arcnet.c
26 *
27 * **********************
28 */
29
30 #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
31
32 #include <linux/module.h>
33 #include <linux/moduleparam.h>
34 #include <linux/kernel.h>
35 #include <linux/types.h>
36 #include <linux/ioport.h>
37 #include <linux/errno.h>
38 #include <linux/netdevice.h>
39 #include <linux/init.h>
40 #include <linux/interrupt.h>
41 #include <linux/pci.h>
42 #include <linux/list.h>
43 #include <linux/io.h>
44 #include <linux/leds.h>
45
46 #include "arcdevice.h"
47 #include "com20020.h"
48
49 /* Module parameters */
50
51 static int node;
52 static char device[9]; /* use eg. device="arc1" to change name */
53 static int timeout = 3;
54 static int backplane;
55 static int clockp;
56 static int clockm;
57
58 module_param(node, int, 0);
59 module_param_string(device, device, sizeof(device), 0);
60 module_param(timeout, int, 0);
61 module_param(backplane, int, 0);
62 module_param(clockp, int, 0);
63 module_param(clockm, int, 0);
64 MODULE_LICENSE("GPL");
65
66 static void led_tx_set(struct led_classdev *led_cdev,
67 enum led_brightness value)
68 {
69 struct com20020_dev *card;
70 struct com20020_priv *priv;
71 struct com20020_pci_card_info *ci;
72
73 card = container_of(led_cdev, struct com20020_dev, tx_led);
74
75 priv = card->pci_priv;
76 ci = priv->ci;
77
78 outb(!!value, priv->misc + ci->leds[card->index].green);
79 }
80
81 static void led_recon_set(struct led_classdev *led_cdev,
82 enum led_brightness value)
83 {
84 struct com20020_dev *card;
85 struct com20020_priv *priv;
86 struct com20020_pci_card_info *ci;
87
88 card = container_of(led_cdev, struct com20020_dev, recon_led);
89
90 priv = card->pci_priv;
91 ci = priv->ci;
92
93 outb(!!value, priv->misc + ci->leds[card->index].red);
94 }
95
96 static void com20020pci_remove(struct pci_dev *pdev);
97
98 static int com20020pci_probe(struct pci_dev *pdev,
99 const struct pci_device_id *id)
100 {
101 struct com20020_pci_card_info *ci;
102 struct com20020_pci_channel_map *mm;
103 struct net_device *dev;
104 struct arcnet_local *lp;
105 struct com20020_priv *priv;
106 int i, ioaddr, ret;
107 struct resource *r;
108
109 if (pci_enable_device(pdev))
110 return -EIO;
111
112 priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
113 GFP_KERNEL);
114 if (!priv)
115 return -ENOMEM;
116
117 ci = (struct com20020_pci_card_info *)id->driver_data;
118 priv->ci = ci;
119 mm = &ci->misc_map;
120
121 INIT_LIST_HEAD(&priv->list_dev);
122
123 if (mm->size) {
124 ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
125 r = devm_request_region(&pdev->dev, ioaddr, mm->size,
126 "com20020-pci");
127 if (!r) {
128 pr_err("IO region %xh-%xh already allocated.\n",
129 ioaddr, ioaddr + mm->size - 1);
130 return -EBUSY;
131 }
132 priv->misc = ioaddr;
133 }
134
135 for (i = 0; i < ci->devcount; i++) {
136 struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
137 struct com20020_dev *card;
138 int dev_id_mask = 0xf;
139
140 dev = alloc_arcdev(device);
141 if (!dev) {
142 ret = -ENOMEM;
143 goto out_port;
144 }
145 dev->dev_port = i;
146
147 dev->netdev_ops = &com20020_netdev_ops;
148
149 lp = netdev_priv(dev);
150
151 arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
152 ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
153
154 r = devm_request_region(&pdev->dev, ioaddr, cm->size,
155 "com20020-pci");
156 if (!r) {
157 pr_err("IO region %xh-%xh already allocated\n",
158 ioaddr, ioaddr + cm->size - 1);
159 ret = -EBUSY;
160 goto out_port;
161 }
162
163 /* Dummy access after Reset
164 * ARCNET controller needs
165 * this access to detect bustype
166 */
167 arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
168 arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
169
170 SET_NETDEV_DEV(dev, &pdev->dev);
171 dev->base_addr = ioaddr;
172 dev->dev_addr[0] = node;
173 dev->irq = pdev->irq;
174 lp->card_name = "PCI COM20020";
175 lp->card_flags = ci->flags;
176 lp->backplane = backplane;
177 lp->clockp = clockp & 7;
178 lp->clockm = clockm & 3;
179 lp->timeout = timeout;
180 lp->hw.owner = THIS_MODULE;
181
182 /* Get the dev_id from the PLX rotary coder */
183 if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
184 dev_id_mask = 0x3;
185 dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
186
187 snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
188
189 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
190 pr_err("IO address %Xh is empty!\n", ioaddr);
191 ret = -EIO;
192 goto out_port;
193 }
194 if (com20020_check(dev)) {
195 ret = -EIO;
196 goto out_port;
197 }
198
199 card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
200 GFP_KERNEL);
201 if (!card)
202 return -ENOMEM;
203
204 card->index = i;
205 card->pci_priv = priv;
206 card->tx_led.brightness_set = led_tx_set;
207 card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
208 GFP_KERNEL, "arc%d-%d-tx",
209 dev->dev_id, i);
210 card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
211 "pci:green:tx:%d-%d",
212 dev->dev_id, i);
213
214 card->tx_led.dev = &dev->dev;
215 card->recon_led.brightness_set = led_recon_set;
216 card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
217 GFP_KERNEL, "arc%d-%d-recon",
218 dev->dev_id, i);
219 card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
220 "pci:red:recon:%d-%d",
221 dev->dev_id, i);
222 card->recon_led.dev = &dev->dev;
223 card->dev = dev;
224
225 ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
226 if (ret)
227 goto out_port;
228
229 ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
230 if (ret)
231 goto out_port;
232
233 dev_set_drvdata(&dev->dev, card);
234
235 ret = com20020_found(dev, IRQF_SHARED);
236 if (ret)
237 goto out_port;
238
239 devm_arcnet_led_init(dev, dev->dev_id, i);
240
241 list_add(&card->list, &priv->list_dev);
242 }
243
244 pci_set_drvdata(pdev, priv);
245
246 return 0;
247
248 out_port:
249 com20020pci_remove(pdev);
250 return ret;
251 }
252
253 static void com20020pci_remove(struct pci_dev *pdev)
254 {
255 struct com20020_dev *card, *tmpcard;
256 struct com20020_priv *priv;
257
258 priv = pci_get_drvdata(pdev);
259
260 list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
261 struct net_device *dev = card->dev;
262
263 unregister_netdev(dev);
264 free_irq(dev->irq, dev);
265 free_netdev(dev);
266 }
267 }
268
269 static struct com20020_pci_card_info card_info_10mbit = {
270 .name = "ARC-PCI",
271 .devcount = 1,
272 .chan_map_tbl = {
273 {
274 .bar = 2,
275 .offset = 0x00,
276 .size = 0x08,
277 },
278 },
279 .flags = ARC_CAN_10MBIT,
280 };
281
282 static struct com20020_pci_card_info card_info_5mbit = {
283 .name = "ARC-PCI",
284 .devcount = 1,
285 .chan_map_tbl = {
286 {
287 .bar = 2,
288 .offset = 0x00,
289 .size = 0x08,
290 },
291 },
292 .flags = ARC_IS_5MBIT,
293 };
294
295 static struct com20020_pci_card_info card_info_sohard = {
296 .name = "PLX-PCI",
297 .devcount = 1,
298 /* SOHARD needs PCI base addr 4 */
299 .chan_map_tbl = {
300 {
301 .bar = 4,
302 .offset = 0x00,
303 .size = 0x08
304 },
305 },
306 .flags = ARC_CAN_10MBIT,
307 };
308
309 static struct com20020_pci_card_info card_info_eae_arc1 = {
310 .name = "EAE PLX-PCI ARC1",
311 .devcount = 1,
312 .chan_map_tbl = {
313 {
314 .bar = 2,
315 .offset = 0x00,
316 .size = 0x08,
317 },
318 },
319 .misc_map = {
320 .bar = 2,
321 .offset = 0x10,
322 .size = 0x04,
323 },
324 .leds = {
325 {
326 .green = 0x0,
327 .red = 0x1,
328 },
329 },
330 .rotary = 0x0,
331 .flags = ARC_CAN_10MBIT,
332 };
333
334 static struct com20020_pci_card_info card_info_eae_ma1 = {
335 .name = "EAE PLX-PCI MA1",
336 .devcount = 2,
337 .chan_map_tbl = {
338 {
339 .bar = 2,
340 .offset = 0x00,
341 .size = 0x08,
342 }, {
343 .bar = 2,
344 .offset = 0x08,
345 .size = 0x08,
346 }
347 },
348 .misc_map = {
349 .bar = 2,
350 .offset = 0x10,
351 .size = 0x04,
352 },
353 .leds = {
354 {
355 .green = 0x0,
356 .red = 0x1,
357 }, {
358 .green = 0x2,
359 .red = 0x3,
360 },
361 },
362 .rotary = 0x0,
363 .flags = ARC_CAN_10MBIT,
364 };
365
366 static const struct pci_device_id com20020pci_id_table[] = {
367 {
368 0x1571, 0xa001,
369 PCI_ANY_ID, PCI_ANY_ID,
370 0, 0,
371 0,
372 },
373 {
374 0x1571, 0xa002,
375 PCI_ANY_ID, PCI_ANY_ID,
376 0, 0,
377 0,
378 },
379 {
380 0x1571, 0xa003,
381 PCI_ANY_ID, PCI_ANY_ID,
382 0, 0,
383 0
384 },
385 {
386 0x1571, 0xa004,
387 PCI_ANY_ID, PCI_ANY_ID,
388 0, 0,
389 0,
390 },
391 {
392 0x1571, 0xa005,
393 PCI_ANY_ID, PCI_ANY_ID,
394 0, 0,
395 0
396 },
397 {
398 0x1571, 0xa006,
399 PCI_ANY_ID, PCI_ANY_ID,
400 0, 0,
401 0
402 },
403 {
404 0x1571, 0xa007,
405 PCI_ANY_ID, PCI_ANY_ID,
406 0, 0,
407 0
408 },
409 {
410 0x1571, 0xa008,
411 PCI_ANY_ID, PCI_ANY_ID,
412 0, 0,
413 0
414 },
415 {
416 0x1571, 0xa009,
417 PCI_ANY_ID, PCI_ANY_ID,
418 0, 0,
419 (kernel_ulong_t)&card_info_5mbit
420 },
421 {
422 0x1571, 0xa00a,
423 PCI_ANY_ID, PCI_ANY_ID,
424 0, 0,
425 (kernel_ulong_t)&card_info_5mbit
426 },
427 {
428 0x1571, 0xa00b,
429 PCI_ANY_ID, PCI_ANY_ID,
430 0, 0,
431 (kernel_ulong_t)&card_info_5mbit
432 },
433 {
434 0x1571, 0xa00c,
435 PCI_ANY_ID, PCI_ANY_ID,
436 0, 0,
437 (kernel_ulong_t)&card_info_5mbit
438 },
439 {
440 0x1571, 0xa00d,
441 PCI_ANY_ID, PCI_ANY_ID,
442 0, 0,
443 (kernel_ulong_t)&card_info_5mbit
444 },
445 {
446 0x1571, 0xa00e,
447 PCI_ANY_ID, PCI_ANY_ID,
448 0, 0,
449 (kernel_ulong_t)&card_info_5mbit
450 },
451 {
452 0x1571, 0xa201,
453 PCI_ANY_ID, PCI_ANY_ID,
454 0, 0,
455 (kernel_ulong_t)&card_info_10mbit
456 },
457 {
458 0x1571, 0xa202,
459 PCI_ANY_ID, PCI_ANY_ID,
460 0, 0,
461 (kernel_ulong_t)&card_info_10mbit
462 },
463 {
464 0x1571, 0xa203,
465 PCI_ANY_ID, PCI_ANY_ID,
466 0, 0,
467 (kernel_ulong_t)&card_info_10mbit
468 },
469 {
470 0x1571, 0xa204,
471 PCI_ANY_ID, PCI_ANY_ID,
472 0, 0,
473 (kernel_ulong_t)&card_info_10mbit
474 },
475 {
476 0x1571, 0xa205,
477 PCI_ANY_ID, PCI_ANY_ID,
478 0, 0,
479 (kernel_ulong_t)&card_info_10mbit
480 },
481 {
482 0x1571, 0xa206,
483 PCI_ANY_ID, PCI_ANY_ID,
484 0, 0,
485 (kernel_ulong_t)&card_info_10mbit
486 },
487 {
488 0x10B5, 0x9030,
489 0x10B5, 0x2978,
490 0, 0,
491 (kernel_ulong_t)&card_info_sohard
492 },
493 {
494 0x10B5, 0x9050,
495 0x10B5, 0x2273,
496 0, 0,
497 (kernel_ulong_t)&card_info_sohard
498 },
499 {
500 0x10B5, 0x9050,
501 0x10B5, 0x3263,
502 0, 0,
503 (kernel_ulong_t)&card_info_eae_arc1
504 },
505 {
506 0x10B5, 0x9050,
507 0x10B5, 0x3292,
508 0, 0,
509 (kernel_ulong_t)&card_info_eae_ma1
510 },
511 {
512 0x14BA, 0x6000,
513 PCI_ANY_ID, PCI_ANY_ID,
514 0, 0,
515 (kernel_ulong_t)&card_info_10mbit
516 },
517 {
518 0x10B5, 0x2200,
519 PCI_ANY_ID, PCI_ANY_ID,
520 0, 0,
521 (kernel_ulong_t)&card_info_10mbit
522 },
523 { 0, }
524 };
525
526 MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
527
528 static struct pci_driver com20020pci_driver = {
529 .name = "com20020",
530 .id_table = com20020pci_id_table,
531 .probe = com20020pci_probe,
532 .remove = com20020pci_remove,
533 };
534
535 static int __init com20020pci_init(void)
536 {
537 if (BUGLVL(D_NORMAL))
538 pr_info("%s\n", "COM20020 PCI support");
539 return pci_register_driver(&com20020pci_driver);
540 }
541
542 static void __exit com20020pci_cleanup(void)
543 {
544 pci_unregister_driver(&com20020pci_driver);
545 }
546
547 module_init(com20020pci_init)
548 module_exit(com20020pci_cleanup)