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