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