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