]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - 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
CommitLineData
1da177e4
LT
1/*
2 * Linux ARCnet driver - COM20020 PCI support
3 * Contemporary Controls PCI20 and SOHARD SH-ARC PCI
cb334648 4 *
1da177e4
LT
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 */
05a24b23
JP
29
30#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
31
1da177e4
LT
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>
1da177e4
LT
37#include <linux/errno.h>
38#include <linux/netdevice.h>
39#include <linux/init.h>
a6b7a407 40#include <linux/interrupt.h>
1da177e4 41#include <linux/pci.h>
c51da42a 42#include <linux/list.h>
5e7ef913 43#include <linux/io.h>
8890624a 44#include <linux/leds.h>
1da177e4 45
26c6d281
JP
46#include "arcdevice.h"
47#include "com20020.h"
48
1da177e4
LT
49/* Module parameters */
50
51static int node;
52static char device[9]; /* use eg. device="arc1" to change name */
53static int timeout = 3;
54static int backplane;
55static int clockp;
56static int clockm;
57
58module_param(node, int, 0);
59module_param_string(device, device, sizeof(device), 0);
60module_param(timeout, int, 0);
61module_param(backplane, int, 0);
62module_param(clockp, int, 0);
63module_param(clockm, int, 0);
64MODULE_LICENSE("GPL");
65
8890624a
MG
66static 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
81static 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
c51da42a
MG
96static void com20020pci_remove(struct pci_dev *pdev);
97
d6d7d3ed
JP
98static int com20020pci_probe(struct pci_dev *pdev,
99 const struct pci_device_id *id)
1da177e4 100{
8c14f9c7 101 struct com20020_pci_card_info *ci;
5ef216c1 102 struct com20020_pci_channel_map *mm;
1da177e4
LT
103 struct net_device *dev;
104 struct arcnet_local *lp;
c51da42a
MG
105 struct com20020_priv *priv;
106 int i, ioaddr, ret;
107 struct resource *r;
1da177e4
LT
108
109 if (pci_enable_device(pdev))
110 return -EIO;
a1799af4 111
c51da42a
MG
112 priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
113 GFP_KERNEL);
e8a308af
KP
114 if (!priv)
115 return -ENOMEM;
116
8c14f9c7 117 ci = (struct com20020_pci_card_info *)id->driver_data;
c51da42a 118 priv->ci = ci;
5ef216c1 119 mm = &ci->misc_map;
c51da42a
MG
120
121 INIT_LIST_HEAD(&priv->list_dev);
122
5ef216c1
MG
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
c51da42a
MG
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;
cb108619 138 int dev_id_mask = 0xf;
c51da42a
MG
139
140 dev = alloc_arcdev(device);
141 if (!dev) {
142 ret = -ENOMEM;
143 goto out_port;
144 }
ae8ede6a 145 dev->dev_port = i;
c51da42a
MG
146
147 dev->netdev_ops = &com20020_netdev_ops;
148
149 lp = netdev_priv(dev);
150
a34c0932 151 arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
c51da42a
MG
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) {
05a24b23 157 pr_err("IO region %xh-%xh already allocated\n",
c51da42a
MG
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 */
0fec6513
JP
167 arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
168 arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
c51da42a 169
2a0ea04c 170 SET_NETDEV_DEV(dev, &pdev->dev);
c51da42a
MG
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
5ef216c1
MG
182 /* Get the dev_id from the PLX rotary coder */
183 if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
cb108619
MG
184 dev_id_mask = 0x3;
185 dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
5ef216c1
MG
186
187 snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
188
0fec6513 189 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
c51da42a
MG
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);
5628d98f 201 if (!card)
c51da42a 202 return -ENOMEM;
c51da42a
MG
203
204 card->index = i;
205 card->pci_priv = priv;
8890624a
MG
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;
c51da42a
MG
223 card->dev = dev;
224
8890624a
MG
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
c51da42a
MG
233 dev_set_drvdata(&dev->dev, card);
234
235 ret = com20020_found(dev, IRQF_SHARED);
236 if (ret)
237 goto out_port;
238
8890624a
MG
239 devm_arcnet_led_init(dev, dev->dev_id, i);
240
c51da42a 241 list_add(&card->list, &priv->list_dev);
1da177e4
LT
242 }
243
c51da42a 244 pci_set_drvdata(pdev, priv);
1da177e4
LT
245
246 return 0;
247
248out_port:
c51da42a
MG
249 com20020pci_remove(pdev);
250 return ret;
1da177e4
LT
251}
252
7c47bab6 253static void com20020pci_remove(struct pci_dev *pdev)
1da177e4 254{
c51da42a
MG
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 }
1da177e4
LT
267}
268
8c14f9c7
MG
269static struct com20020_pci_card_info card_info_10mbit = {
270 .name = "ARC-PCI",
271 .devcount = 1,
272 .chan_map_tbl = {
54a84c61
MG
273 {
274 .bar = 2,
275 .offset = 0x00,
276 .size = 0x08,
277 },
8c14f9c7
MG
278 },
279 .flags = ARC_CAN_10MBIT,
280};
281
282static struct com20020_pci_card_info card_info_5mbit = {
283 .name = "ARC-PCI",
284 .devcount = 1,
285 .chan_map_tbl = {
54a84c61
MG
286 {
287 .bar = 2,
288 .offset = 0x00,
289 .size = 0x08,
290 },
8c14f9c7
MG
291 },
292 .flags = ARC_IS_5MBIT,
293};
294
295static 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 = {
54a84c61
MG
300 {
301 .bar = 4,
302 .offset = 0x00,
303 .size = 0x08
304 },
8c14f9c7
MG
305 },
306 .flags = ARC_CAN_10MBIT,
307};
308
d95e2fe0
MG
309static struct com20020_pci_card_info card_info_eae_arc1 = {
310 .name = "EAE PLX-PCI ARC1",
311 .devcount = 1,
312 .chan_map_tbl = {
54a84c61
MG
313 {
314 .bar = 2,
315 .offset = 0x00,
316 .size = 0x08,
317 },
d95e2fe0 318 },
5ef216c1
MG
319 .misc_map = {
320 .bar = 2,
321 .offset = 0x10,
322 .size = 0x04,
323 },
8890624a
MG
324 .leds = {
325 {
326 .green = 0x0,
327 .red = 0x1,
328 },
329 },
5ef216c1 330 .rotary = 0x0,
d95e2fe0
MG
331 .flags = ARC_CAN_10MBIT,
332};
333
334static struct com20020_pci_card_info card_info_eae_ma1 = {
335 .name = "EAE PLX-PCI MA1",
5b85bad2
MG
336 .devcount = 2,
337 .chan_map_tbl = {
54a84c61
MG
338 {
339 .bar = 2,
340 .offset = 0x00,
341 .size = 0x08,
342 }, {
343 .bar = 2,
344 .offset = 0x08,
345 .size = 0x08,
346 }
5b85bad2 347 },
5ef216c1
MG
348 .misc_map = {
349 .bar = 2,
350 .offset = 0x10,
351 .size = 0x04,
352 },
8890624a
MG
353 .leds = {
354 {
355 .green = 0x0,
356 .red = 0x1,
357 }, {
358 .green = 0x2,
359 .red = 0x3,
360 },
361 },
5ef216c1 362 .rotary = 0x0,
5b85bad2
MG
363 .flags = ARC_CAN_10MBIT,
364};
365
9baa3c34 366static const struct pci_device_id com20020pci_id_table[] = {
8c14f9c7
MG
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 },
d95e2fe0
MG
499 {
500 0x10B5, 0x9050,
501 0x10B5, 0x3263,
502 0, 0,
503 (kernel_ulong_t)&card_info_eae_arc1
504 },
5b85bad2
MG
505 {
506 0x10B5, 0x9050,
507 0x10B5, 0x3292,
508 0, 0,
d95e2fe0 509 (kernel_ulong_t)&card_info_eae_ma1
5b85bad2 510 },
8c14f9c7
MG
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, }
1da177e4
LT
524};
525
526MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
527
528static struct pci_driver com20020pci_driver = {
529 .name = "com20020",
530 .id_table = com20020pci_id_table,
531 .probe = com20020pci_probe,
7c47bab6 532 .remove = com20020pci_remove,
1da177e4
LT
533};
534
535static int __init com20020pci_init(void)
536{
72aeea48 537 if (BUGLVL(D_NORMAL))
05a24b23 538 pr_info("%s\n", "COM20020 PCI support");
29917620 539 return pci_register_driver(&com20020pci_driver);
1da177e4
LT
540}
541
542static void __exit com20020pci_cleanup(void)
543{
544 pci_unregister_driver(&com20020pci_driver);
545}
546
547module_init(com20020pci_init)
548module_exit(com20020pci_cleanup)