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(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                res = -ENOMEM;
 310                goto out_release_mem8_space;
 311        }
 312
 313        /* Initialize lock that protects interface_regs */
 314        spin_lock_init(&tpci200->regs_lock);
 315
 316        ioidint_base = pci_resource_start(tpci200->info->pdev,
 317                                          TPCI200_IO_ID_INT_SPACES_BAR);
 318        tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF;
 319        tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF;
 320        tpci200->mod_mem[IPACK_INT_SPACE] =
 321                ioidint_base + TPCI200_INT_SPACE_OFF;
 322        tpci200->mod_mem[IPACK_MEM8_SPACE] =
 323                pci_resource_start(tpci200->info->pdev,
 324                                   TPCI200_MEM8_SPACE_BAR);
 325        tpci200->mod_mem[IPACK_MEM16_SPACE] =
 326                pci_resource_start(tpci200->info->pdev,
 327                                   TPCI200_MEM16_SPACE_BAR);
 328
 329        /* Set the default parameters of the slot
 330         * INT0 disabled, level sensitive
 331         * INT1 disabled, level sensitive
 332         * error interrupt disabled
 333         * timeout interrupt disabled
 334         * recover time disabled
 335         * clock rate 8 MHz
 336         */
 337        slot_ctrl = 0;
 338        for (i = 0; i < TPCI200_NB_SLOT; i++)
 339                writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
 340
 341        res = request_irq(tpci200->info->pdev->irq,
 342                          tpci200_interrupt, IRQF_SHARED,
 343                          KBUILD_MODNAME, (void *) tpci200);
 344        if (res) {
 345                dev_err(&tpci200->info->pdev->dev,
 346                        "(bn 0x%X, sn 0x%X) unable to register IRQ !",
 347                        tpci200->info->pdev->bus->number,
 348                        tpci200->info->pdev->devfn);
 349                goto out_release_ioid_int_space;
 350        }
 351
 352        return 0;
 353
 354out_release_mem8_space:
 355        pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
 356out_release_ioid_int_space:
 357        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
 358out_release_ip_space:
 359        pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
 360out_disable_pci:
 361        pci_disable_device(tpci200->info->pdev);
 362        return res;
 363}
 364
 365static int tpci200_get_clockrate(struct ipack_device *dev)
 366{
 367        struct tpci200_board *tpci200 = check_slot(dev);
 368        __le16 __iomem *addr;
 369
 370        if (!tpci200)
 371                return -ENODEV;
 372
 373        addr = &tpci200->info->interface_regs->control[dev->slot];
 374        return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
 375}
 376
 377static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
 378{
 379        struct tpci200_board *tpci200 = check_slot(dev);
 380        __le16 __iomem *addr;
 381
 382        if (!tpci200)
 383                return -ENODEV;
 384
 385        addr = &tpci200->info->interface_regs->control[dev->slot];
 386
 387        switch (mherz) {
 388        case 8:
 389                tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
 390                break;
 391        case 32:
 392                tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
 393                break;
 394        default:
 395                return -EINVAL;
 396        }
 397        return 0;
 398}
 399
 400static int tpci200_get_error(struct ipack_device *dev)
 401{
 402        struct tpci200_board *tpci200 = check_slot(dev);
 403        __le16 __iomem *addr;
 404        u16 mask;
 405
 406        if (!tpci200)
 407                return -ENODEV;
 408
 409        addr = &tpci200->info->interface_regs->status;
 410        mask = tpci200_status_error[dev->slot];
 411        return (ioread16(addr) & mask) ? 1 : 0;
 412}
 413
 414static int tpci200_get_timeout(struct ipack_device *dev)
 415{
 416        struct tpci200_board *tpci200 = check_slot(dev);
 417        __le16 __iomem *addr;
 418        u16 mask;
 419
 420        if (!tpci200)
 421                return -ENODEV;
 422
 423        addr = &tpci200->info->interface_regs->status;
 424        mask = tpci200_status_timeout[dev->slot];
 425
 426        return (ioread16(addr) & mask) ? 1 : 0;
 427}
 428
 429static int tpci200_reset_timeout(struct ipack_device *dev)
 430{
 431        struct tpci200_board *tpci200 = check_slot(dev);
 432        __le16 __iomem *addr;
 433        u16 mask;
 434
 435        if (!tpci200)
 436                return -ENODEV;
 437
 438        addr = &tpci200->info->interface_regs->status;
 439        mask = tpci200_status_timeout[dev->slot];
 440
 441        iowrite16(mask, addr);
 442        return 0;
 443}
 444
 445static void tpci200_uninstall(struct tpci200_board *tpci200)
 446{
 447        tpci200_unregister(tpci200);
 448        kfree(tpci200->slots);
 449}
 450
 451static const struct ipack_bus_ops tpci200_bus_ops = {
 452        .request_irq = tpci200_request_irq,
 453        .free_irq = tpci200_free_irq,
 454        .get_clockrate = tpci200_get_clockrate,
 455        .set_clockrate = tpci200_set_clockrate,
 456        .get_error     = tpci200_get_error,
 457        .get_timeout   = tpci200_get_timeout,
 458        .reset_timeout = tpci200_reset_timeout,
 459};
 460
 461static int tpci200_install(struct tpci200_board *tpci200)
 462{
 463        int res;
 464
 465        tpci200->slots = kcalloc(TPCI200_NB_SLOT, sizeof(struct tpci200_slot),
 466                                 GFP_KERNEL);
 467        if (tpci200->slots == NULL)
 468                return -ENOMEM;
 469
 470        res = tpci200_register(tpci200);
 471        if (res) {
 472                kfree(tpci200->slots);
 473                tpci200->slots = NULL;
 474                return res;
 475        }
 476
 477        mutex_init(&tpci200->mutex);
 478        return 0;
 479}
 480
 481static void tpci200_release_device(struct ipack_device *dev)
 482{
 483        kfree(dev);
 484}
 485
 486static int tpci200_create_device(struct tpci200_board *tpci200, int i)
 487{
 488        int ret;
 489        enum ipack_space space;
 490        struct ipack_device *dev =
 491                kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
 492        if (!dev)
 493                return -ENOMEM;
 494        dev->slot = i;
 495        dev->bus = tpci200->info->ipack_bus;
 496        dev->release = tpci200_release_device;
 497
 498        for (space = 0; space < IPACK_SPACE_COUNT; space++) {
 499                dev->region[space].start =
 500                        tpci200->mod_mem[space]
 501                        + tpci200_space_interval[space] * i;
 502                dev->region[space].size = tpci200_space_size[space];
 503        }
 504
 505        ret = ipack_device_init(dev);
 506        if (ret < 0) {
 507                ipack_put_device(dev);
 508                return ret;
 509        }
 510
 511        ret = ipack_device_add(dev);
 512        if (ret < 0)
 513                ipack_put_device(dev);
 514
 515        return ret;
 516}
 517
 518static int tpci200_pci_probe(struct pci_dev *pdev,
 519                             const struct pci_device_id *id)
 520{
 521        int ret, i;
 522        struct tpci200_board *tpci200;
 523        u32 reg32;
 524
 525        tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
 526        if (!tpci200)
 527                return -ENOMEM;
 528
 529        tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
 530        if (!tpci200->info) {
 531                ret = -ENOMEM;
 532                goto out_err_info;
 533        }
 534
 535        pci_dev_get(pdev);
 536
 537        /* Obtain a mapping of the carrier's PCI configuration registers */
 538        ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
 539                                 KBUILD_MODNAME " Configuration Memory");
 540        if (ret) {
 541                dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
 542                ret = -EBUSY;
 543                goto out_err_pci_request;
 544        }
 545        tpci200->info->cfg_regs = ioremap(
 546                        pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
 547                        pci_resource_len(pdev, TPCI200_CFG_MEM_BAR));
 548        if (!tpci200->info->cfg_regs) {
 549                dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
 550                ret = -EFAULT;
 551                goto out_err_ioremap;
 552        }
 553
 554        /* Disable byte swapping for 16 bit IP module access. This will ensure
 555         * that the Industrypack big endian byte order is preserved by the
 556         * carrier. */
 557        reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
 558        reg32 |= 1 << LAS_BIT_BIGENDIAN;
 559        iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
 560
 561        reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC);
 562        reg32 |= 1 << LAS_BIT_BIGENDIAN;
 563        iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC);
 564
 565        /* Save struct pci_dev pointer */
 566        tpci200->info->pdev = pdev;
 567        tpci200->info->id_table = (struct pci_device_id *)id;
 568
 569        /* register the device and initialize it */
 570        ret = tpci200_install(tpci200);
 571        if (ret) {
 572                dev_err(&pdev->dev, "error during tpci200 install\n");
 573                ret = -ENODEV;
 574                goto out_err_install;
 575        }
 576
 577        /* Register the carrier in the industry pack bus driver */
 578        tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
 579                                                      TPCI200_NB_SLOT,
 580                                                      &tpci200_bus_ops,
 581                                                      THIS_MODULE);
 582        if (!tpci200->info->ipack_bus) {
 583                dev_err(&pdev->dev,
 584                        "error registering the carrier on ipack driver\n");
 585                ret = -EFAULT;
 586                goto out_err_bus_register;
 587        }
 588
 589        /* save the bus number given by ipack to logging purpose */
 590        tpci200->number = tpci200->info->ipack_bus->bus_nr;
 591        dev_set_drvdata(&pdev->dev, tpci200);
 592
 593        for (i = 0; i < TPCI200_NB_SLOT; i++)
 594                tpci200_create_device(tpci200, i);
 595        return 0;
 596
 597out_err_bus_register:
 598        tpci200_uninstall(tpci200);
 599out_err_install:
 600        iounmap(tpci200->info->cfg_regs);
 601out_err_ioremap:
 602        pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
 603out_err_pci_request:
 604        pci_dev_put(pdev);
 605        kfree(tpci200->info);
 606out_err_info:
 607        kfree(tpci200);
 608        return ret;
 609}
 610
 611static void __tpci200_pci_remove(struct tpci200_board *tpci200)
 612{
 613        ipack_bus_unregister(tpci200->info->ipack_bus);
 614        tpci200_uninstall(tpci200);
 615
 616        kfree(tpci200->info);
 617        kfree(tpci200);
 618}
 619
 620static void tpci200_pci_remove(struct pci_dev *dev)
 621{
 622        struct tpci200_board *tpci200 = pci_get_drvdata(dev);
 623
 624        __tpci200_pci_remove(tpci200);
 625}
 626
 627static const struct pci_device_id tpci200_idtable[] = {
 628        { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
 629          TPCI200_SUBDEVICE_ID },
 630        { 0, },
 631};
 632
 633MODULE_DEVICE_TABLE(pci, tpci200_idtable);
 634
 635static struct pci_driver tpci200_pci_drv = {
 636        .name = "tpci200",
 637        .id_table = tpci200_idtable,
 638        .probe = tpci200_pci_probe,
 639        .remove = tpci200_pci_remove,
 640};
 641
 642module_pci_driver(tpci200_pci_drv);
 643
 644MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
 645MODULE_LICENSE("GPL");
 646