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