smack: mark 'smack_enabled' global variable as __initdata
[linux-2.6-microblaze.git] / drivers / ipack / carriers / tpci200.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * driver for the TEWS TPCI-200 device
4  *
5  * Copyright (C) 2009-2012 CERN (www.cern.ch)
6  * Author: Nicolas Serafini, EIC2 SA
7  * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
8  */
9
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include "tpci200.h"
13
14 static const u16 tpci200_status_timeout[] = {
15         TPCI200_A_TIMEOUT,
16         TPCI200_B_TIMEOUT,
17         TPCI200_C_TIMEOUT,
18         TPCI200_D_TIMEOUT,
19 };
20
21 static const u16 tpci200_status_error[] = {
22         TPCI200_A_ERROR,
23         TPCI200_B_ERROR,
24         TPCI200_C_ERROR,
25         TPCI200_D_ERROR,
26 };
27
28 static const size_t tpci200_space_size[IPACK_SPACE_COUNT] = {
29         [IPACK_IO_SPACE]    = TPCI200_IO_SPACE_SIZE,
30         [IPACK_ID_SPACE]    = TPCI200_ID_SPACE_SIZE,
31         [IPACK_INT_SPACE]   = TPCI200_INT_SPACE_SIZE,
32         [IPACK_MEM8_SPACE]  = TPCI200_MEM8_SPACE_SIZE,
33         [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_SIZE,
34 };
35
36 static const size_t tpci200_space_interval[IPACK_SPACE_COUNT] = {
37         [IPACK_IO_SPACE]    = TPCI200_IO_SPACE_INTERVAL,
38         [IPACK_ID_SPACE]    = TPCI200_ID_SPACE_INTERVAL,
39         [IPACK_INT_SPACE]   = TPCI200_INT_SPACE_INTERVAL,
40         [IPACK_MEM8_SPACE]  = TPCI200_MEM8_SPACE_INTERVAL,
41         [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_INTERVAL,
42 };
43
44 static struct tpci200_board *check_slot(struct ipack_device *dev)
45 {
46         struct tpci200_board *tpci200;
47
48         if (dev == NULL)
49                 return NULL;
50
51
52         tpci200 = dev_get_drvdata(dev->bus->parent);
53
54         if (tpci200 == NULL) {
55                 dev_info(&dev->dev, "carrier board not found\n");
56                 return NULL;
57         }
58
59         if (dev->slot >= TPCI200_NB_SLOT) {
60                 dev_info(&dev->dev,
61                          "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
62                          dev->bus->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
63                 return NULL;
64         }
65
66         return tpci200;
67 }
68
69 static void tpci200_clear_mask(struct tpci200_board *tpci200,
70                                __le16 __iomem *addr, u16 mask)
71 {
72         unsigned long flags;
73         spin_lock_irqsave(&tpci200->regs_lock, flags);
74         iowrite16(ioread16(addr) & (~mask), addr);
75         spin_unlock_irqrestore(&tpci200->regs_lock, flags);
76 }
77
78 static void tpci200_set_mask(struct tpci200_board *tpci200,
79                              __le16 __iomem *addr, u16 mask)
80 {
81         unsigned long flags;
82         spin_lock_irqsave(&tpci200->regs_lock, flags);
83         iowrite16(ioread16(addr) | mask, addr);
84         spin_unlock_irqrestore(&tpci200->regs_lock, flags);
85 }
86
87 static void tpci200_unregister(struct tpci200_board *tpci200)
88 {
89         free_irq(tpci200->info->pdev->irq, (void *) tpci200);
90
91         pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
92         pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
93
94         pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
95         pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
96         pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
97         pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
98         pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
99
100         pci_disable_device(tpci200->info->pdev);
101         pci_dev_put(tpci200->info->pdev);
102 }
103
104 static void tpci200_enable_irq(struct tpci200_board *tpci200,
105                                int islot)
106 {
107         tpci200_set_mask(tpci200,
108                         &tpci200->info->interface_regs->control[islot],
109                         TPCI200_INT0_EN | TPCI200_INT1_EN);
110 }
111
112 static void tpci200_disable_irq(struct tpci200_board *tpci200,
113                                 int islot)
114 {
115         tpci200_clear_mask(tpci200,
116                         &tpci200->info->interface_regs->control[islot],
117                         TPCI200_INT0_EN | TPCI200_INT1_EN);
118 }
119
120 static irqreturn_t tpci200_slot_irq(struct slot_irq *slot_irq)
121 {
122         irqreturn_t ret;
123
124         if (!slot_irq)
125                 return -ENODEV;
126         ret = slot_irq->handler(slot_irq->arg);
127
128         return ret;
129 }
130
131 static irqreturn_t tpci200_interrupt(int irq, void *dev_id)
132 {
133         struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id;
134         struct slot_irq *slot_irq;
135         irqreturn_t ret;
136         u16 status_reg;
137         int i;
138
139         /* Read status register */
140         status_reg = ioread16(&tpci200->info->interface_regs->status);
141
142         /* Did we cause the interrupt? */
143         if (!(status_reg & TPCI200_SLOT_INT_MASK))
144                 return IRQ_NONE;
145
146         /* callback to the IRQ handler for the corresponding slot */
147         rcu_read_lock();
148         for (i = 0; i < TPCI200_NB_SLOT; i++) {
149                 if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i))))
150                         continue;
151                 slot_irq = rcu_dereference(tpci200->slots[i].irq);
152                 ret = tpci200_slot_irq(slot_irq);
153                 if (ret == -ENODEV) {
154                         dev_info(&tpci200->info->pdev->dev,
155                                  "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
156                                  tpci200->number, i);
157                         tpci200_disable_irq(tpci200, i);
158                 }
159         }
160         rcu_read_unlock();
161
162         return IRQ_HANDLED;
163 }
164
165 static int tpci200_free_irq(struct ipack_device *dev)
166 {
167         struct slot_irq *slot_irq;
168         struct tpci200_board *tpci200;
169
170         tpci200 = check_slot(dev);
171         if (tpci200 == NULL)
172                 return -EINVAL;
173
174         if (mutex_lock_interruptible(&tpci200->mutex))
175                 return -ERESTARTSYS;
176
177         if (tpci200->slots[dev->slot].irq == NULL) {
178                 mutex_unlock(&tpci200->mutex);
179                 return -EINVAL;
180         }
181
182         tpci200_disable_irq(tpci200, dev->slot);
183         slot_irq = tpci200->slots[dev->slot].irq;
184         /* uninstall handler */
185         RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL);
186         synchronize_rcu();
187         kfree(slot_irq);
188         mutex_unlock(&tpci200->mutex);
189         return 0;
190 }
191
192 static int tpci200_request_irq(struct ipack_device *dev,
193                                irqreturn_t (*handler)(void *), void *arg)
194 {
195         int res = 0;
196         struct slot_irq *slot_irq;
197         struct tpci200_board *tpci200;
198
199         tpci200 = check_slot(dev);
200         if (tpci200 == NULL)
201                 return -EINVAL;
202
203         if (mutex_lock_interruptible(&tpci200->mutex))
204                 return -ERESTARTSYS;
205
206         if (tpci200->slots[dev->slot].irq != NULL) {
207                 dev_err(&dev->dev,
208                         "Slot [%d:%d] IRQ already registered !\n",
209                         dev->bus->bus_nr,
210                         dev->slot);
211                 res = -EINVAL;
212                 goto out_unlock;
213         }
214
215         slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
216         if (slot_irq == NULL) {
217                 dev_err(&dev->dev,
218                         "Slot [%d:%d] unable to allocate memory for IRQ !\n",
219                         dev->bus->bus_nr, dev->slot);
220                 res = -ENOMEM;
221                 goto out_unlock;
222         }
223
224         /*
225          * WARNING: Setup Interrupt Vector in the IndustryPack device
226          * before an IRQ request.
227          * Read the User Manual of your IndustryPack device to know
228          * where to write the vector in memory.
229          */
230         slot_irq->handler = handler;
231         slot_irq->arg = arg;
232         slot_irq->holder = dev;
233
234         rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq);
235         tpci200_enable_irq(tpci200, dev->slot);
236
237 out_unlock:
238         mutex_unlock(&tpci200->mutex);
239         return res;
240 }
241
242 static int tpci200_register(struct tpci200_board *tpci200)
243 {
244         int i;
245         int res;
246         phys_addr_t ioidint_base;
247         unsigned short slot_ctrl;
248
249         if (pci_enable_device(tpci200->info->pdev) < 0)
250                 return -ENODEV;
251
252         /* Request IP interface register (Bar 2) */
253         res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR,
254                                  "Carrier IP interface registers");
255         if (res) {
256                 dev_err(&tpci200->info->pdev->dev,
257                         "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
258                         tpci200->info->pdev->bus->number,
259                         tpci200->info->pdev->devfn);
260                 goto out_disable_pci;
261         }
262
263         /* Request IO ID INT space (Bar 3) */
264         res = pci_request_region(tpci200->info->pdev,
265                                  TPCI200_IO_ID_INT_SPACES_BAR,
266                                  "Carrier IO ID INT space");
267         if (res) {
268                 dev_err(&tpci200->info->pdev->dev,
269                         "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
270                         tpci200->info->pdev->bus->number,
271                         tpci200->info->pdev->devfn);
272                 goto out_release_ip_space;
273         }
274
275         /* Request MEM8 space (Bar 5) */
276         res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
277                                  "Carrier MEM8 space");
278         if (res) {
279                 dev_err(&tpci200->info->pdev->dev,
280                         "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
281                         tpci200->info->pdev->bus->number,
282                         tpci200->info->pdev->devfn);
283                 goto out_release_ioid_int_space;
284         }
285
286         /* Request MEM16 space (Bar 4) */
287         res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR,
288                                  "Carrier MEM16 space");
289         if (res) {
290                 dev_err(&tpci200->info->pdev->dev,
291                         "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
292                         tpci200->info->pdev->bus->number,
293                         tpci200->info->pdev->devfn);
294                 goto out_release_mem8_space;
295         }
296
297         /* Map internal tpci200 driver user space */
298         tpci200->info->interface_regs =
299                 ioremap(pci_resource_start(tpci200->info->pdev,
300                                            TPCI200_IP_INTERFACE_BAR),
301                         TPCI200_IFACE_SIZE);
302         if (!tpci200->info->interface_regs) {
303                 dev_err(&tpci200->info->pdev->dev,
304                         "(bn 0x%X, sn 0x%X) failed to map driver user space!",
305                         tpci200->info->pdev->bus->number,
306                         tpci200->info->pdev->devfn);
307                 res = -ENOMEM;
308                 goto out_release_mem8_space;
309         }
310
311         /* Initialize lock that protects interface_regs */
312         spin_lock_init(&tpci200->regs_lock);
313
314         ioidint_base = pci_resource_start(tpci200->info->pdev,
315                                           TPCI200_IO_ID_INT_SPACES_BAR);
316         tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF;
317         tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF;
318         tpci200->mod_mem[IPACK_INT_SPACE] =
319                 ioidint_base + TPCI200_INT_SPACE_OFF;
320         tpci200->mod_mem[IPACK_MEM8_SPACE] =
321                 pci_resource_start(tpci200->info->pdev,
322                                    TPCI200_MEM8_SPACE_BAR);
323         tpci200->mod_mem[IPACK_MEM16_SPACE] =
324                 pci_resource_start(tpci200->info->pdev,
325                                    TPCI200_MEM16_SPACE_BAR);
326
327         /* Set the default parameters of the slot
328          * INT0 disabled, level sensitive
329          * INT1 disabled, level sensitive
330          * error interrupt disabled
331          * timeout interrupt disabled
332          * recover time disabled
333          * clock rate 8 MHz
334          */
335         slot_ctrl = 0;
336         for (i = 0; i < TPCI200_NB_SLOT; i++)
337                 writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
338
339         res = request_irq(tpci200->info->pdev->irq,
340                           tpci200_interrupt, IRQF_SHARED,
341                           KBUILD_MODNAME, (void *) tpci200);
342         if (res) {
343                 dev_err(&tpci200->info->pdev->dev,
344                         "(bn 0x%X, sn 0x%X) unable to register IRQ !",
345                         tpci200->info->pdev->bus->number,
346                         tpci200->info->pdev->devfn);
347                 goto out_release_ioid_int_space;
348         }
349
350         return 0;
351
352 out_release_mem8_space:
353         pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
354 out_release_ioid_int_space:
355         pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
356 out_release_ip_space:
357         pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
358 out_disable_pci:
359         pci_disable_device(tpci200->info->pdev);
360         return res;
361 }
362
363 static int tpci200_get_clockrate(struct ipack_device *dev)
364 {
365         struct tpci200_board *tpci200 = check_slot(dev);
366         __le16 __iomem *addr;
367
368         if (!tpci200)
369                 return -ENODEV;
370
371         addr = &tpci200->info->interface_regs->control[dev->slot];
372         return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
373 }
374
375 static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
376 {
377         struct tpci200_board *tpci200 = check_slot(dev);
378         __le16 __iomem *addr;
379
380         if (!tpci200)
381                 return -ENODEV;
382
383         addr = &tpci200->info->interface_regs->control[dev->slot];
384
385         switch (mherz) {
386         case 8:
387                 tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
388                 break;
389         case 32:
390                 tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
391                 break;
392         default:
393                 return -EINVAL;
394         }
395         return 0;
396 }
397
398 static int tpci200_get_error(struct ipack_device *dev)
399 {
400         struct tpci200_board *tpci200 = check_slot(dev);
401         __le16 __iomem *addr;
402         u16 mask;
403
404         if (!tpci200)
405                 return -ENODEV;
406
407         addr = &tpci200->info->interface_regs->status;
408         mask = tpci200_status_error[dev->slot];
409         return (ioread16(addr) & mask) ? 1 : 0;
410 }
411
412 static int tpci200_get_timeout(struct ipack_device *dev)
413 {
414         struct tpci200_board *tpci200 = check_slot(dev);
415         __le16 __iomem *addr;
416         u16 mask;
417
418         if (!tpci200)
419                 return -ENODEV;
420
421         addr = &tpci200->info->interface_regs->status;
422         mask = tpci200_status_timeout[dev->slot];
423
424         return (ioread16(addr) & mask) ? 1 : 0;
425 }
426
427 static int tpci200_reset_timeout(struct ipack_device *dev)
428 {
429         struct tpci200_board *tpci200 = check_slot(dev);
430         __le16 __iomem *addr;
431         u16 mask;
432
433         if (!tpci200)
434                 return -ENODEV;
435
436         addr = &tpci200->info->interface_regs->status;
437         mask = tpci200_status_timeout[dev->slot];
438
439         iowrite16(mask, addr);
440         return 0;
441 }
442
443 static void tpci200_uninstall(struct tpci200_board *tpci200)
444 {
445         tpci200_unregister(tpci200);
446         kfree(tpci200->slots);
447 }
448
449 static const struct ipack_bus_ops tpci200_bus_ops = {
450         .request_irq = tpci200_request_irq,
451         .free_irq = tpci200_free_irq,
452         .get_clockrate = tpci200_get_clockrate,
453         .set_clockrate = tpci200_set_clockrate,
454         .get_error     = tpci200_get_error,
455         .get_timeout   = tpci200_get_timeout,
456         .reset_timeout = tpci200_reset_timeout,
457 };
458
459 static int tpci200_install(struct tpci200_board *tpci200)
460 {
461         int res;
462
463         tpci200->slots = kcalloc(TPCI200_NB_SLOT, sizeof(struct tpci200_slot),
464                                  GFP_KERNEL);
465         if (tpci200->slots == NULL)
466                 return -ENOMEM;
467
468         res = tpci200_register(tpci200);
469         if (res) {
470                 kfree(tpci200->slots);
471                 tpci200->slots = NULL;
472                 return res;
473         }
474
475         mutex_init(&tpci200->mutex);
476         return 0;
477 }
478
479 static void tpci200_release_device(struct ipack_device *dev)
480 {
481         kfree(dev);
482 }
483
484 static int tpci200_create_device(struct tpci200_board *tpci200, int i)
485 {
486         int ret;
487         enum ipack_space space;
488         struct ipack_device *dev =
489                 kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
490         if (!dev)
491                 return -ENOMEM;
492         dev->slot = i;
493         dev->bus = tpci200->info->ipack_bus;
494         dev->release = tpci200_release_device;
495
496         for (space = 0; space < IPACK_SPACE_COUNT; space++) {
497                 dev->region[space].start =
498                         tpci200->mod_mem[space]
499                         + tpci200_space_interval[space] * i;
500                 dev->region[space].size = tpci200_space_size[space];
501         }
502
503         ret = ipack_device_init(dev);
504         if (ret < 0) {
505                 ipack_put_device(dev);
506                 return ret;
507         }
508
509         ret = ipack_device_add(dev);
510         if (ret < 0)
511                 ipack_put_device(dev);
512
513         return ret;
514 }
515
516 static int tpci200_pci_probe(struct pci_dev *pdev,
517                              const struct pci_device_id *id)
518 {
519         int ret, i;
520         struct tpci200_board *tpci200;
521         u32 reg32;
522
523         tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
524         if (!tpci200)
525                 return -ENOMEM;
526
527         tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
528         if (!tpci200->info) {
529                 ret = -ENOMEM;
530                 goto out_err_info;
531         }
532
533         pci_dev_get(pdev);
534
535         /* Obtain a mapping of the carrier's PCI configuration registers */
536         ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
537                                  KBUILD_MODNAME " Configuration Memory");
538         if (ret) {
539                 dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
540                 ret = -EBUSY;
541                 goto out_err_pci_request;
542         }
543         tpci200->info->cfg_regs = ioremap(
544                         pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
545                         pci_resource_len(pdev, TPCI200_CFG_MEM_BAR));
546         if (!tpci200->info->cfg_regs) {
547                 dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
548                 ret = -EFAULT;
549                 goto out_err_ioremap;
550         }
551
552         /* Disable byte swapping for 16 bit IP module access. This will ensure
553          * that the Industrypack big endian byte order is preserved by the
554          * carrier. */
555         reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
556         reg32 |= 1 << LAS_BIT_BIGENDIAN;
557         iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
558
559         reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC);
560         reg32 |= 1 << LAS_BIT_BIGENDIAN;
561         iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC);
562
563         /* Save struct pci_dev pointer */
564         tpci200->info->pdev = pdev;
565         tpci200->info->id_table = (struct pci_device_id *)id;
566
567         /* register the device and initialize it */
568         ret = tpci200_install(tpci200);
569         if (ret) {
570                 dev_err(&pdev->dev, "error during tpci200 install\n");
571                 ret = -ENODEV;
572                 goto out_err_install;
573         }
574
575         /* Register the carrier in the industry pack bus driver */
576         tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
577                                                       TPCI200_NB_SLOT,
578                                                       &tpci200_bus_ops,
579                                                       THIS_MODULE);
580         if (!tpci200->info->ipack_bus) {
581                 dev_err(&pdev->dev,
582                         "error registering the carrier on ipack driver\n");
583                 ret = -EFAULT;
584                 goto out_err_bus_register;
585         }
586
587         /* save the bus number given by ipack to logging purpose */
588         tpci200->number = tpci200->info->ipack_bus->bus_nr;
589         dev_set_drvdata(&pdev->dev, tpci200);
590
591         for (i = 0; i < TPCI200_NB_SLOT; i++)
592                 tpci200_create_device(tpci200, i);
593         return 0;
594
595 out_err_bus_register:
596         tpci200_uninstall(tpci200);
597         /* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */
598         tpci200->info->cfg_regs = NULL;
599 out_err_install:
600         if (tpci200->info->cfg_regs)
601                 iounmap(tpci200->info->cfg_regs);
602 out_err_ioremap:
603         pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
604 out_err_pci_request:
605         pci_dev_put(pdev);
606         kfree(tpci200->info);
607 out_err_info:
608         kfree(tpci200);
609         return ret;
610 }
611
612 static void __tpci200_pci_remove(struct tpci200_board *tpci200)
613 {
614         ipack_bus_unregister(tpci200->info->ipack_bus);
615         tpci200_uninstall(tpci200);
616
617         kfree(tpci200->info);
618         kfree(tpci200);
619 }
620
621 static void tpci200_pci_remove(struct pci_dev *dev)
622 {
623         struct tpci200_board *tpci200 = pci_get_drvdata(dev);
624
625         __tpci200_pci_remove(tpci200);
626 }
627
628 static const struct pci_device_id tpci200_idtable[] = {
629         { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
630           TPCI200_SUBDEVICE_ID },
631         { 0, },
632 };
633
634 MODULE_DEVICE_TABLE(pci, tpci200_idtable);
635
636 static struct pci_driver tpci200_pci_drv = {
637         .name = "tpci200",
638         .id_table = tpci200_idtable,
639         .probe = tpci200_pci_probe,
640         .remove = tpci200_pci_remove,
641 };
642
643 module_pci_driver(tpci200_pci_drv);
644
645 MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
646 MODULE_LICENSE("GPL");