Merge remote-tracking branches 'asoc/topic/cs4271', 'asoc/topic/cs53l30', 'asoc/topic...
[sfrench/cifs-2.6.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         priv->ci = ci;
119         mm = &ci->misc_map;
120
121         INIT_LIST_HEAD(&priv->list_dev);
122
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
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;
138                 int dev_id_mask = 0xf;
139
140                 dev = alloc_arcdev(device);
141                 if (!dev) {
142                         ret = -ENOMEM;
143                         goto out_port;
144                 }
145                 dev->dev_port = i;
146
147                 dev->netdev_ops = &com20020_netdev_ops;
148
149                 lp = netdev_priv(dev);
150
151                 arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
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) {
157                         pr_err("IO region %xh-%xh already allocated\n",
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                  */
167                 arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
168                 arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
169
170                 SET_NETDEV_DEV(dev, &pdev->dev);
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
182                 /* Get the dev_id from the PLX rotary coder */
183                 if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
184                         dev_id_mask = 0x3;
185                 dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
186
187                 snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
188
189                 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
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);
201                 if (!card)
202                         return -ENOMEM;
203
204                 card->index = i;
205                 card->pci_priv = priv;
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;
223                 card->dev = dev;
224
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
233                 dev_set_drvdata(&dev->dev, card);
234
235                 ret = com20020_found(dev, IRQF_SHARED);
236                 if (ret)
237                         goto out_port;
238
239                 devm_arcnet_led_init(dev, dev->dev_id, i);
240
241                 list_add(&card->list, &priv->list_dev);
242         }
243
244         pci_set_drvdata(pdev, priv);
245
246         return 0;
247
248 out_port:
249         com20020pci_remove(pdev);
250         return ret;
251 }
252
253 static void com20020pci_remove(struct pci_dev *pdev)
254 {
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         }
267 }
268
269 static struct com20020_pci_card_info card_info_10mbit = {
270         .name = "ARC-PCI",
271         .devcount = 1,
272         .chan_map_tbl = {
273                 {
274                         .bar = 2,
275                         .offset = 0x00,
276                         .size = 0x08,
277                 },
278         },
279         .flags = ARC_CAN_10MBIT,
280 };
281
282 static struct com20020_pci_card_info card_info_5mbit = {
283         .name = "ARC-PCI",
284         .devcount = 1,
285         .chan_map_tbl = {
286                 {
287                         .bar = 2,
288                         .offset = 0x00,
289                         .size = 0x08,
290                 },
291         },
292         .flags = ARC_IS_5MBIT,
293 };
294
295 static 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 = {
300                 {
301                         .bar = 4,
302                         .offset = 0x00,
303                         .size = 0x08
304                 },
305         },
306         .flags = ARC_CAN_10MBIT,
307 };
308
309 static struct com20020_pci_card_info card_info_eae_arc1 = {
310         .name = "EAE PLX-PCI ARC1",
311         .devcount = 1,
312         .chan_map_tbl = {
313                 {
314                         .bar = 2,
315                         .offset = 0x00,
316                         .size = 0x08,
317                 },
318         },
319         .misc_map = {
320                 .bar = 2,
321                 .offset = 0x10,
322                 .size = 0x04,
323         },
324         .leds = {
325                 {
326                         .green = 0x0,
327                         .red = 0x1,
328                 },
329         },
330         .rotary = 0x0,
331         .flags = ARC_CAN_10MBIT,
332 };
333
334 static struct com20020_pci_card_info card_info_eae_ma1 = {
335         .name = "EAE PLX-PCI MA1",
336         .devcount = 2,
337         .chan_map_tbl = {
338                 {
339                         .bar = 2,
340                         .offset = 0x00,
341                         .size = 0x08,
342                 }, {
343                         .bar = 2,
344                         .offset = 0x08,
345                         .size = 0x08,
346                 }
347         },
348         .misc_map = {
349                 .bar = 2,
350                 .offset = 0x10,
351                 .size = 0x04,
352         },
353         .leds = {
354                 {
355                         .green = 0x0,
356                         .red = 0x1,
357                 }, {
358                         .green = 0x2,
359                         .red = 0x3,
360                 },
361         },
362         .rotary = 0x0,
363         .flags = ARC_CAN_10MBIT,
364 };
365
366 static const struct pci_device_id com20020pci_id_table[] = {
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         },
499         {
500                 0x10B5, 0x9050,
501                 0x10B5, 0x3263,
502                 0, 0,
503                 (kernel_ulong_t)&card_info_eae_arc1
504         },
505         {
506                 0x10B5, 0x9050,
507                 0x10B5, 0x3292,
508                 0, 0,
509                 (kernel_ulong_t)&card_info_eae_ma1
510         },
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, }
524 };
525
526 MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
527
528 static struct pci_driver com20020pci_driver = {
529         .name           = "com20020",
530         .id_table       = com20020pci_id_table,
531         .probe          = com20020pci_probe,
532         .remove         = com20020pci_remove,
533 };
534
535 static int __init com20020pci_init(void)
536 {
537         if (BUGLVL(D_NORMAL))
538                 pr_info("%s\n", "COM20020 PCI support");
539         return pci_register_driver(&com20020pci_driver);
540 }
541
542 static void __exit com20020pci_cleanup(void)
543 {
544         pci_unregister_driver(&com20020pci_driver);
545 }
546
547 module_init(com20020pci_init)
548 module_exit(com20020pci_cleanup)