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