GNU Linux-libre 4.9.333-gnu1
[releases.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         if (!ci)
119                 return -EINVAL;
120
121         priv->ci = ci;
122         mm = &ci->misc_map;
123
124         INIT_LIST_HEAD(&priv->list_dev);
125
126         if (mm->size) {
127                 ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
128                 r = devm_request_region(&pdev->dev, ioaddr, mm->size,
129                                         "com20020-pci");
130                 if (!r) {
131                         pr_err("IO region %xh-%xh already allocated.\n",
132                                ioaddr, ioaddr + mm->size - 1);
133                         return -EBUSY;
134                 }
135                 priv->misc = ioaddr;
136         }
137
138         for (i = 0; i < ci->devcount; i++) {
139                 struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
140                 struct com20020_dev *card;
141
142                 dev = alloc_arcdev(device);
143                 if (!dev) {
144                         ret = -ENOMEM;
145                         goto out_port;
146                 }
147                 dev->dev_port = i;
148
149                 dev->netdev_ops = &com20020_netdev_ops;
150
151                 lp = netdev_priv(dev);
152
153                 arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
154                 ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
155
156                 r = devm_request_region(&pdev->dev, ioaddr, cm->size,
157                                         "com20020-pci");
158                 if (!r) {
159                         pr_err("IO region %xh-%xh already allocated\n",
160                                ioaddr, ioaddr + cm->size - 1);
161                         ret = -EBUSY;
162                         goto out_port;
163                 }
164
165                 /* Dummy access after Reset
166                  * ARCNET controller needs
167                  * this access to detect bustype
168                  */
169                 arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
170                 arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
171
172                 dev->base_addr = ioaddr;
173                 dev->dev_addr[0] = node;
174                 dev->irq = pdev->irq;
175                 lp->card_name = "PCI COM20020";
176                 lp->card_flags = ci->flags;
177                 lp->backplane = backplane;
178                 lp->clockp = clockp & 7;
179                 lp->clockm = clockm & 3;
180                 lp->timeout = timeout;
181                 lp->hw.owner = THIS_MODULE;
182
183                 /* Get the dev_id from the PLX rotary coder */
184                 if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
185                         dev->dev_id = 0xc;
186                 dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4;
187
188                 snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
189
190                 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
191                         pr_err("IO address %Xh is empty!\n", ioaddr);
192                         ret = -EIO;
193                         goto out_port;
194                 }
195                 if (com20020_check(dev)) {
196                         ret = -EIO;
197                         goto out_port;
198                 }
199
200                 card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
201                                     GFP_KERNEL);
202                 if (!card)
203                         return -ENOMEM;
204
205                 card->index = i;
206                 card->pci_priv = priv;
207                 card->tx_led.brightness_set = led_tx_set;
208                 card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
209                                                 GFP_KERNEL, "arc%d-%d-tx",
210                                                 dev->dev_id, i);
211                 card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
212                                                 "pci:green:tx:%d-%d",
213                                                 dev->dev_id, i);
214
215                 card->tx_led.dev = &dev->dev;
216                 card->recon_led.brightness_set = led_recon_set;
217                 card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
218                                                 GFP_KERNEL, "arc%d-%d-recon",
219                                                 dev->dev_id, i);
220                 card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
221                                                 "pci:red:recon:%d-%d",
222                                                 dev->dev_id, i);
223                 card->recon_led.dev = &dev->dev;
224                 card->dev = dev;
225
226                 ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
227                 if (ret)
228                         goto out_port;
229
230                 ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
231                 if (ret)
232                         goto out_port;
233
234                 dev_set_drvdata(&dev->dev, card);
235
236                 ret = com20020_found(dev, IRQF_SHARED);
237                 if (ret)
238                         goto out_port;
239
240                 devm_arcnet_led_init(dev, dev->dev_id, i);
241
242                 list_add(&card->list, &priv->list_dev);
243         }
244
245         pci_set_drvdata(pdev, priv);
246
247         return 0;
248
249 out_port:
250         com20020pci_remove(pdev);
251         return ret;
252 }
253
254 static void com20020pci_remove(struct pci_dev *pdev)
255 {
256         struct com20020_dev *card, *tmpcard;
257         struct com20020_priv *priv;
258
259         priv = pci_get_drvdata(pdev);
260
261         list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
262                 struct net_device *dev = card->dev;
263
264                 unregister_netdev(dev);
265                 free_irq(dev->irq, dev);
266                 free_netdev(dev);
267         }
268 }
269
270 static struct com20020_pci_card_info card_info_10mbit = {
271         .name = "ARC-PCI",
272         .devcount = 1,
273         .chan_map_tbl = {
274                 {
275                         .bar = 2,
276                         .offset = 0x00,
277                         .size = 0x08,
278                 },
279         },
280         .flags = ARC_CAN_10MBIT,
281 };
282
283 static struct com20020_pci_card_info card_info_5mbit = {
284         .name = "ARC-PCI",
285         .devcount = 1,
286         .chan_map_tbl = {
287                 {
288                         .bar = 2,
289                         .offset = 0x00,
290                         .size = 0x08,
291                 },
292         },
293         .flags = ARC_IS_5MBIT,
294 };
295
296 static struct com20020_pci_card_info card_info_sohard = {
297         .name = "PLX-PCI",
298         .devcount = 1,
299         /* SOHARD needs PCI base addr 4 */
300         .chan_map_tbl = {
301                 {
302                         .bar = 4,
303                         .offset = 0x00,
304                         .size = 0x08
305                 },
306         },
307         .flags = ARC_CAN_10MBIT,
308 };
309
310 static struct com20020_pci_card_info card_info_eae_arc1 = {
311         .name = "EAE PLX-PCI ARC1",
312         .devcount = 1,
313         .chan_map_tbl = {
314                 {
315                         .bar = 2,
316                         .offset = 0x00,
317                         .size = 0x08,
318                 },
319         },
320         .misc_map = {
321                 .bar = 2,
322                 .offset = 0x10,
323                 .size = 0x04,
324         },
325         .leds = {
326                 {
327                         .green = 0x0,
328                         .red = 0x1,
329                 },
330         },
331         .rotary = 0x0,
332         .flags = ARC_CAN_10MBIT,
333 };
334
335 static struct com20020_pci_card_info card_info_eae_ma1 = {
336         .name = "EAE PLX-PCI MA1",
337         .devcount = 2,
338         .chan_map_tbl = {
339                 {
340                         .bar = 2,
341                         .offset = 0x00,
342                         .size = 0x08,
343                 }, {
344                         .bar = 2,
345                         .offset = 0x08,
346                         .size = 0x08,
347                 }
348         },
349         .misc_map = {
350                 .bar = 2,
351                 .offset = 0x10,
352                 .size = 0x04,
353         },
354         .leds = {
355                 {
356                         .green = 0x0,
357                         .red = 0x1,
358                 }, {
359                         .green = 0x2,
360                         .red = 0x3,
361                 },
362         },
363         .rotary = 0x0,
364         .flags = ARC_CAN_10MBIT,
365 };
366
367 static const struct pci_device_id com20020pci_id_table[] = {
368         {
369                 0x1571, 0xa001,
370                 PCI_ANY_ID, PCI_ANY_ID,
371                 0, 0,
372                 0,
373         },
374         {
375                 0x1571, 0xa002,
376                 PCI_ANY_ID, PCI_ANY_ID,
377                 0, 0,
378                 0,
379         },
380         {
381                 0x1571, 0xa003,
382                 PCI_ANY_ID, PCI_ANY_ID,
383                 0, 0,
384                 0
385         },
386         {
387                 0x1571, 0xa004,
388                 PCI_ANY_ID, PCI_ANY_ID,
389                 0, 0,
390                 0,
391         },
392         {
393                 0x1571, 0xa005,
394                 PCI_ANY_ID, PCI_ANY_ID,
395                 0, 0,
396                 0
397         },
398         {
399                 0x1571, 0xa006,
400                 PCI_ANY_ID, PCI_ANY_ID,
401                 0, 0,
402                 0
403         },
404         {
405                 0x1571, 0xa007,
406                 PCI_ANY_ID, PCI_ANY_ID,
407                 0, 0,
408                 0
409         },
410         {
411                 0x1571, 0xa008,
412                 PCI_ANY_ID, PCI_ANY_ID,
413                 0, 0,
414                 0
415         },
416         {
417                 0x1571, 0xa009,
418                 PCI_ANY_ID, PCI_ANY_ID,
419                 0, 0,
420                 (kernel_ulong_t)&card_info_5mbit
421         },
422         {
423                 0x1571, 0xa00a,
424                 PCI_ANY_ID, PCI_ANY_ID,
425                 0, 0,
426                 (kernel_ulong_t)&card_info_5mbit
427         },
428         {
429                 0x1571, 0xa00b,
430                 PCI_ANY_ID, PCI_ANY_ID,
431                 0, 0,
432                 (kernel_ulong_t)&card_info_5mbit
433         },
434         {
435                 0x1571, 0xa00c,
436                 PCI_ANY_ID, PCI_ANY_ID,
437                 0, 0,
438                 (kernel_ulong_t)&card_info_5mbit
439         },
440         {
441                 0x1571, 0xa00d,
442                 PCI_ANY_ID, PCI_ANY_ID,
443                 0, 0,
444                 (kernel_ulong_t)&card_info_5mbit
445         },
446         {
447                 0x1571, 0xa00e,
448                 PCI_ANY_ID, PCI_ANY_ID,
449                 0, 0,
450                 (kernel_ulong_t)&card_info_5mbit
451         },
452         {
453                 0x1571, 0xa201,
454                 PCI_ANY_ID, PCI_ANY_ID,
455                 0, 0,
456                 (kernel_ulong_t)&card_info_10mbit
457         },
458         {
459                 0x1571, 0xa202,
460                 PCI_ANY_ID, PCI_ANY_ID,
461                 0, 0,
462                 (kernel_ulong_t)&card_info_10mbit
463         },
464         {
465                 0x1571, 0xa203,
466                 PCI_ANY_ID, PCI_ANY_ID,
467                 0, 0,
468                 (kernel_ulong_t)&card_info_10mbit
469         },
470         {
471                 0x1571, 0xa204,
472                 PCI_ANY_ID, PCI_ANY_ID,
473                 0, 0,
474                 (kernel_ulong_t)&card_info_10mbit
475         },
476         {
477                 0x1571, 0xa205,
478                 PCI_ANY_ID, PCI_ANY_ID,
479                 0, 0,
480                 (kernel_ulong_t)&card_info_10mbit
481         },
482         {
483                 0x1571, 0xa206,
484                 PCI_ANY_ID, PCI_ANY_ID,
485                 0, 0,
486                 (kernel_ulong_t)&card_info_10mbit
487         },
488         {
489                 0x10B5, 0x9030,
490                 0x10B5, 0x2978,
491                 0, 0,
492                 (kernel_ulong_t)&card_info_sohard
493         },
494         {
495                 0x10B5, 0x9050,
496                 0x10B5, 0x2273,
497                 0, 0,
498                 (kernel_ulong_t)&card_info_sohard
499         },
500         {
501                 0x10B5, 0x9050,
502                 0x10B5, 0x3263,
503                 0, 0,
504                 (kernel_ulong_t)&card_info_eae_arc1
505         },
506         {
507                 0x10B5, 0x9050,
508                 0x10B5, 0x3292,
509                 0, 0,
510                 (kernel_ulong_t)&card_info_eae_ma1
511         },
512         {
513                 0x14BA, 0x6000,
514                 PCI_ANY_ID, PCI_ANY_ID,
515                 0, 0,
516                 (kernel_ulong_t)&card_info_10mbit
517         },
518         {
519                 0x10B5, 0x2200,
520                 PCI_ANY_ID, PCI_ANY_ID,
521                 0, 0,
522                 (kernel_ulong_t)&card_info_10mbit
523         },
524         { 0, }
525 };
526
527 MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
528
529 static struct pci_driver com20020pci_driver = {
530         .name           = "com20020",
531         .id_table       = com20020pci_id_table,
532         .probe          = com20020pci_probe,
533         .remove         = com20020pci_remove,
534 };
535
536 static int __init com20020pci_init(void)
537 {
538         if (BUGLVL(D_NORMAL))
539                 pr_info("%s\n", "COM20020 PCI support");
540         return pci_register_driver(&com20020pci_driver);
541 }
542
543 static void __exit com20020pci_cleanup(void)
544 {
545         pci_unregister_driver(&com20020pci_driver);
546 }
547
548 module_init(com20020pci_init)
549 module_exit(com20020pci_cleanup)