linux/drivers/gpio/gpio-thunderx.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2016, 2017 Cavium Inc.
   7 */
   8
   9#include <linux/bitops.h>
  10#include <linux/gpio/driver.h>
  11#include <linux/interrupt.h>
  12#include <linux/io.h>
  13#include <linux/irq.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/pci.h>
  17#include <linux/spinlock.h>
  18#include <asm-generic/msi.h>
  19
  20
  21#define GPIO_RX_DAT     0x0
  22#define GPIO_TX_SET     0x8
  23#define GPIO_TX_CLR     0x10
  24#define GPIO_CONST      0x90
  25#define  GPIO_CONST_GPIOS_MASK 0xff
  26#define GPIO_BIT_CFG    0x400
  27#define  GPIO_BIT_CFG_TX_OE             BIT(0)
  28#define  GPIO_BIT_CFG_PIN_XOR           BIT(1)
  29#define  GPIO_BIT_CFG_INT_EN            BIT(2)
  30#define  GPIO_BIT_CFG_INT_TYPE          BIT(3)
  31#define  GPIO_BIT_CFG_FIL_MASK          GENMASK(11, 4)
  32#define  GPIO_BIT_CFG_FIL_CNT_SHIFT     4
  33#define  GPIO_BIT_CFG_FIL_SEL_SHIFT     8
  34#define  GPIO_BIT_CFG_TX_OD             BIT(12)
  35#define  GPIO_BIT_CFG_PIN_SEL_MASK      GENMASK(25, 16)
  36#define GPIO_INTR       0x800
  37#define  GPIO_INTR_INTR                 BIT(0)
  38#define  GPIO_INTR_INTR_W1S             BIT(1)
  39#define  GPIO_INTR_ENA_W1C              BIT(2)
  40#define  GPIO_INTR_ENA_W1S              BIT(3)
  41#define GPIO_2ND_BANK   0x1400
  42
  43#define GLITCH_FILTER_400NS ((4u << GPIO_BIT_CFG_FIL_SEL_SHIFT) | \
  44                             (9u << GPIO_BIT_CFG_FIL_CNT_SHIFT))
  45
  46struct thunderx_gpio;
  47
  48struct thunderx_line {
  49        struct thunderx_gpio    *txgpio;
  50        unsigned int            line;
  51        unsigned int            fil_bits;
  52};
  53
  54struct thunderx_gpio {
  55        struct gpio_chip        chip;
  56        u8 __iomem              *register_base;
  57        struct msix_entry       *msix_entries;  /* per line MSI-X */
  58        struct thunderx_line    *line_entries;  /* per line irq info */
  59        raw_spinlock_t          lock;
  60        unsigned long           invert_mask[2];
  61        unsigned long           od_mask[2];
  62        int                     base_msi;
  63};
  64
  65static unsigned int bit_cfg_reg(unsigned int line)
  66{
  67        return 8 * line + GPIO_BIT_CFG;
  68}
  69
  70static unsigned int intr_reg(unsigned int line)
  71{
  72        return 8 * line + GPIO_INTR;
  73}
  74
  75static bool thunderx_gpio_is_gpio_nowarn(struct thunderx_gpio *txgpio,
  76                                         unsigned int line)
  77{
  78        u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
  79
  80        return (bit_cfg & GPIO_BIT_CFG_PIN_SEL_MASK) == 0;
  81}
  82
  83/*
  84 * Check (and WARN) that the pin is available for GPIO.  We will not
  85 * allow modification of the state of non-GPIO pins from this driver.
  86 */
  87static bool thunderx_gpio_is_gpio(struct thunderx_gpio *txgpio,
  88                                  unsigned int line)
  89{
  90        bool rv = thunderx_gpio_is_gpio_nowarn(txgpio, line);
  91
  92        WARN_RATELIMIT(!rv, "Pin %d not available for GPIO\n", line);
  93
  94        return rv;
  95}
  96
  97static int thunderx_gpio_request(struct gpio_chip *chip, unsigned int line)
  98{
  99        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 100
 101        return thunderx_gpio_is_gpio(txgpio, line) ? 0 : -EIO;
 102}
 103
 104static int thunderx_gpio_dir_in(struct gpio_chip *chip, unsigned int line)
 105{
 106        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 107
 108        if (!thunderx_gpio_is_gpio(txgpio, line))
 109                return -EIO;
 110
 111        raw_spin_lock(&txgpio->lock);
 112        clear_bit(line, txgpio->invert_mask);
 113        clear_bit(line, txgpio->od_mask);
 114        writeq(txgpio->line_entries[line].fil_bits,
 115               txgpio->register_base + bit_cfg_reg(line));
 116        raw_spin_unlock(&txgpio->lock);
 117        return 0;
 118}
 119
 120static void thunderx_gpio_set(struct gpio_chip *chip, unsigned int line,
 121                              int value)
 122{
 123        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 124        int bank = line / 64;
 125        int bank_bit = line % 64;
 126
 127        void __iomem *reg = txgpio->register_base +
 128                (bank * GPIO_2ND_BANK) + (value ? GPIO_TX_SET : GPIO_TX_CLR);
 129
 130        writeq(BIT_ULL(bank_bit), reg);
 131}
 132
 133static int thunderx_gpio_dir_out(struct gpio_chip *chip, unsigned int line,
 134                                 int value)
 135{
 136        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 137        u64 bit_cfg = txgpio->line_entries[line].fil_bits | GPIO_BIT_CFG_TX_OE;
 138
 139        if (!thunderx_gpio_is_gpio(txgpio, line))
 140                return -EIO;
 141
 142        raw_spin_lock(&txgpio->lock);
 143
 144        thunderx_gpio_set(chip, line, value);
 145
 146        if (test_bit(line, txgpio->invert_mask))
 147                bit_cfg |= GPIO_BIT_CFG_PIN_XOR;
 148
 149        if (test_bit(line, txgpio->od_mask))
 150                bit_cfg |= GPIO_BIT_CFG_TX_OD;
 151
 152        writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line));
 153
 154        raw_spin_unlock(&txgpio->lock);
 155        return 0;
 156}
 157
 158static int thunderx_gpio_get_direction(struct gpio_chip *chip, unsigned int line)
 159{
 160        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 161        u64 bit_cfg;
 162
 163        if (!thunderx_gpio_is_gpio_nowarn(txgpio, line))
 164                /*
 165                 * Say it is input for now to avoid WARNing on
 166                 * gpiochip_add_data().  We will WARN if someone
 167                 * requests it or tries to use it.
 168                 */
 169                return 1;
 170
 171        bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
 172
 173        if (bit_cfg & GPIO_BIT_CFG_TX_OE)
 174                return GPIO_LINE_DIRECTION_OUT;
 175
 176        return GPIO_LINE_DIRECTION_IN;
 177}
 178
 179static int thunderx_gpio_set_config(struct gpio_chip *chip,
 180                                    unsigned int line,
 181                                    unsigned long cfg)
 182{
 183        bool orig_invert, orig_od, orig_dat, new_invert, new_od;
 184        u32 arg, sel;
 185        u64 bit_cfg;
 186        int bank = line / 64;
 187        int bank_bit = line % 64;
 188        int ret = -ENOTSUPP;
 189        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 190        void __iomem *reg = txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET;
 191
 192        if (!thunderx_gpio_is_gpio(txgpio, line))
 193                return -EIO;
 194
 195        raw_spin_lock(&txgpio->lock);
 196        orig_invert = test_bit(line, txgpio->invert_mask);
 197        new_invert  = orig_invert;
 198        orig_od = test_bit(line, txgpio->od_mask);
 199        new_od = orig_od;
 200        orig_dat = ((readq(reg) >> bank_bit) & 1) ^ orig_invert;
 201        bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
 202        switch (pinconf_to_config_param(cfg)) {
 203        case PIN_CONFIG_DRIVE_OPEN_DRAIN:
 204                /*
 205                 * Weird, setting open-drain mode causes signal
 206                 * inversion.  Note this so we can compensate in the
 207                 * dir_out function.
 208                 */
 209                set_bit(line, txgpio->invert_mask);
 210                new_invert  = true;
 211                set_bit(line, txgpio->od_mask);
 212                new_od = true;
 213                ret = 0;
 214                break;
 215        case PIN_CONFIG_DRIVE_PUSH_PULL:
 216                clear_bit(line, txgpio->invert_mask);
 217                new_invert  = false;
 218                clear_bit(line, txgpio->od_mask);
 219                new_od  = false;
 220                ret = 0;
 221                break;
 222        case PIN_CONFIG_INPUT_DEBOUNCE:
 223                arg = pinconf_to_config_argument(cfg);
 224                if (arg > 1228) { /* 15 * 2^15 * 2.5nS maximum */
 225                        ret = -EINVAL;
 226                        break;
 227                }
 228                arg *= 400; /* scale to 2.5nS clocks. */
 229                sel = 0;
 230                while (arg > 15) {
 231                        sel++;
 232                        arg++; /* always round up */
 233                        arg >>= 1;
 234                }
 235                txgpio->line_entries[line].fil_bits =
 236                        (sel << GPIO_BIT_CFG_FIL_SEL_SHIFT) |
 237                        (arg << GPIO_BIT_CFG_FIL_CNT_SHIFT);
 238                bit_cfg &= ~GPIO_BIT_CFG_FIL_MASK;
 239                bit_cfg |= txgpio->line_entries[line].fil_bits;
 240                writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line));
 241                ret = 0;
 242                break;
 243        default:
 244                break;
 245        }
 246        raw_spin_unlock(&txgpio->lock);
 247
 248        /*
 249         * If currently output and OPEN_DRAIN changed, install the new
 250         * settings
 251         */
 252        if ((new_invert != orig_invert || new_od != orig_od) &&
 253            (bit_cfg & GPIO_BIT_CFG_TX_OE))
 254                ret = thunderx_gpio_dir_out(chip, line, orig_dat ^ new_invert);
 255
 256        return ret;
 257}
 258
 259static int thunderx_gpio_get(struct gpio_chip *chip, unsigned int line)
 260{
 261        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 262        int bank = line / 64;
 263        int bank_bit = line % 64;
 264        u64 read_bits = readq(txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_RX_DAT);
 265        u64 masked_bits = read_bits & BIT_ULL(bank_bit);
 266
 267        if (test_bit(line, txgpio->invert_mask))
 268                return masked_bits == 0;
 269        else
 270                return masked_bits != 0;
 271}
 272
 273static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
 274                                       unsigned long *mask,
 275                                       unsigned long *bits)
 276{
 277        int bank;
 278        u64 set_bits, clear_bits;
 279        struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
 280
 281        for (bank = 0; bank <= chip->ngpio / 64; bank++) {
 282                set_bits = bits[bank] & mask[bank];
 283                clear_bits = ~bits[bank] & mask[bank];
 284                writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET);
 285                writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR);
 286        }
 287}
 288
 289static void thunderx_gpio_irq_ack(struct irq_data *d)
 290{
 291        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 292        struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
 293
 294        writeq(GPIO_INTR_INTR,
 295               txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
 296}
 297
 298static void thunderx_gpio_irq_mask(struct irq_data *d)
 299{
 300        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 301        struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
 302
 303        writeq(GPIO_INTR_ENA_W1C,
 304               txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
 305}
 306
 307static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
 308{
 309        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 310        struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
 311
 312        writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
 313               txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
 314}
 315
 316static void thunderx_gpio_irq_unmask(struct irq_data *d)
 317{
 318        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 319        struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
 320
 321        writeq(GPIO_INTR_ENA_W1S,
 322               txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
 323}
 324
 325static int thunderx_gpio_irq_set_type(struct irq_data *d,
 326                                      unsigned int flow_type)
 327{
 328        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 329        struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
 330        struct thunderx_line *txline =
 331                &txgpio->line_entries[irqd_to_hwirq(d)];
 332        u64 bit_cfg;
 333
 334        irqd_set_trigger_type(d, flow_type);
 335
 336        bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
 337
 338        if (flow_type & IRQ_TYPE_EDGE_BOTH) {
 339                irq_set_handler_locked(d, handle_fasteoi_ack_irq);
 340                bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
 341        } else {
 342                irq_set_handler_locked(d, handle_fasteoi_mask_irq);
 343        }
 344
 345        raw_spin_lock(&txgpio->lock);
 346        if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) {
 347                bit_cfg |= GPIO_BIT_CFG_PIN_XOR;
 348                set_bit(txline->line, txgpio->invert_mask);
 349        } else {
 350                clear_bit(txline->line, txgpio->invert_mask);
 351        }
 352        clear_bit(txline->line, txgpio->od_mask);
 353        writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(txline->line));
 354        raw_spin_unlock(&txgpio->lock);
 355
 356        return IRQ_SET_MASK_OK;
 357}
 358
 359static void thunderx_gpio_irq_enable(struct irq_data *data)
 360{
 361        irq_chip_enable_parent(data);
 362        thunderx_gpio_irq_unmask(data);
 363}
 364
 365static void thunderx_gpio_irq_disable(struct irq_data *data)
 366{
 367        thunderx_gpio_irq_mask(data);
 368        irq_chip_disable_parent(data);
 369}
 370
 371/*
 372 * Interrupts are chained from underlying MSI-X vectors.  We have
 373 * these irq_chip functions to be able to handle level triggering
 374 * semantics and other acknowledgment tasks associated with the GPIO
 375 * mechanism.
 376 */
 377static struct irq_chip thunderx_gpio_irq_chip = {
 378        .name                   = "GPIO",
 379        .irq_enable             = thunderx_gpio_irq_enable,
 380        .irq_disable            = thunderx_gpio_irq_disable,
 381        .irq_ack                = thunderx_gpio_irq_ack,
 382        .irq_mask               = thunderx_gpio_irq_mask,
 383        .irq_mask_ack           = thunderx_gpio_irq_mask_ack,
 384        .irq_unmask             = thunderx_gpio_irq_unmask,
 385        .irq_eoi                = irq_chip_eoi_parent,
 386        .irq_set_affinity       = irq_chip_set_affinity_parent,
 387        .irq_set_type           = thunderx_gpio_irq_set_type,
 388
 389        .flags                  = IRQCHIP_SET_TYPE_MASKED
 390};
 391
 392static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
 393                                               unsigned int child,
 394                                               unsigned int child_type,
 395                                               unsigned int *parent,
 396                                               unsigned int *parent_type)
 397{
 398        struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
 399        struct irq_data *irqd;
 400        unsigned int irq;
 401
 402        irq = txgpio->msix_entries[child].vector;
 403        irqd = irq_domain_get_irq_data(gc->irq.parent_domain, irq);
 404        if (!irqd)
 405                return -EINVAL;
 406        *parent = irqd_to_hwirq(irqd);
 407        *parent_type = IRQ_TYPE_LEVEL_HIGH;
 408        return 0;
 409}
 410
 411static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip,
 412                                                      unsigned int parent_hwirq,
 413                                                      unsigned int parent_type)
 414{
 415        msi_alloc_info_t *info;
 416
 417        info = kmalloc(sizeof(*info), GFP_KERNEL);
 418        if (!info)
 419                return NULL;
 420
 421        info->hwirq = parent_hwirq;
 422        return info;
 423}
 424
 425static int thunderx_gpio_probe(struct pci_dev *pdev,
 426                               const struct pci_device_id *id)
 427{
 428        void __iomem * const *tbl;
 429        struct device *dev = &pdev->dev;
 430        struct thunderx_gpio *txgpio;
 431        struct gpio_chip *chip;
 432        struct gpio_irq_chip *girq;
 433        int ngpio, i;
 434        int err = 0;
 435
 436        txgpio = devm_kzalloc(dev, sizeof(*txgpio), GFP_KERNEL);
 437        if (!txgpio)
 438                return -ENOMEM;
 439
 440        raw_spin_lock_init(&txgpio->lock);
 441        chip = &txgpio->chip;
 442
 443        pci_set_drvdata(pdev, txgpio);
 444
 445        err = pcim_enable_device(pdev);
 446        if (err) {
 447                dev_err(dev, "Failed to enable PCI device: err %d\n", err);
 448                goto out;
 449        }
 450
 451        err = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME);
 452        if (err) {
 453                dev_err(dev, "Failed to iomap PCI device: err %d\n", err);
 454                goto out;
 455        }
 456
 457        tbl = pcim_iomap_table(pdev);
 458        txgpio->register_base = tbl[0];
 459        if (!txgpio->register_base) {
 460                dev_err(dev, "Cannot map PCI resource\n");
 461                err = -ENOMEM;
 462                goto out;
 463        }
 464
 465        if (pdev->subsystem_device == 0xa10a) {
 466                /* CN88XX has no GPIO_CONST register*/
 467                ngpio = 50;
 468                txgpio->base_msi = 48;
 469        } else {
 470                u64 c = readq(txgpio->register_base + GPIO_CONST);
 471
 472                ngpio = c & GPIO_CONST_GPIOS_MASK;
 473                txgpio->base_msi = (c >> 8) & 0xff;
 474        }
 475
 476        txgpio->msix_entries = devm_kcalloc(dev,
 477                                            ngpio, sizeof(struct msix_entry),
 478                                            GFP_KERNEL);
 479        if (!txgpio->msix_entries) {
 480                err = -ENOMEM;
 481                goto out;
 482        }
 483
 484        txgpio->line_entries = devm_kcalloc(dev,
 485                                            ngpio,
 486                                            sizeof(struct thunderx_line),
 487                                            GFP_KERNEL);
 488        if (!txgpio->line_entries) {
 489                err = -ENOMEM;
 490                goto out;
 491        }
 492
 493        for (i = 0; i < ngpio; i++) {
 494                u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(i));
 495
 496                txgpio->msix_entries[i].entry = txgpio->base_msi + (2 * i);
 497                txgpio->line_entries[i].line = i;
 498                txgpio->line_entries[i].txgpio = txgpio;
 499                /*
 500                 * If something has already programmed the pin, use
 501                 * the existing glitch filter settings, otherwise go
 502                 * to 400nS.
 503                 */
 504                txgpio->line_entries[i].fil_bits = bit_cfg ?
 505                        (bit_cfg & GPIO_BIT_CFG_FIL_MASK) : GLITCH_FILTER_400NS;
 506
 507                if ((bit_cfg & GPIO_BIT_CFG_TX_OE) && (bit_cfg & GPIO_BIT_CFG_TX_OD))
 508                        set_bit(i, txgpio->od_mask);
 509                if (bit_cfg & GPIO_BIT_CFG_PIN_XOR)
 510                        set_bit(i, txgpio->invert_mask);
 511        }
 512
 513
 514        /* Enable all MSI-X for interrupts on all possible lines. */
 515        err = pci_enable_msix_range(pdev, txgpio->msix_entries, ngpio, ngpio);
 516        if (err < 0)
 517                goto out;
 518
 519        chip->label = KBUILD_MODNAME;
 520        chip->parent = dev;
 521        chip->owner = THIS_MODULE;
 522        chip->request = thunderx_gpio_request;
 523        chip->base = -1; /* System allocated */
 524        chip->can_sleep = false;
 525        chip->ngpio = ngpio;
 526        chip->get_direction = thunderx_gpio_get_direction;
 527        chip->direction_input = thunderx_gpio_dir_in;
 528        chip->get = thunderx_gpio_get;
 529        chip->direction_output = thunderx_gpio_dir_out;
 530        chip->set = thunderx_gpio_set;
 531        chip->set_multiple = thunderx_gpio_set_multiple;
 532        chip->set_config = thunderx_gpio_set_config;
 533        girq = &chip->irq;
 534        girq->chip = &thunderx_gpio_irq_chip;
 535        girq->fwnode = of_node_to_fwnode(dev->of_node);
 536        girq->parent_domain =
 537                irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
 538        girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
 539        girq->populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info;
 540        girq->handler = handle_bad_irq;
 541        girq->default_type = IRQ_TYPE_NONE;
 542
 543        err = devm_gpiochip_add_data(dev, chip, txgpio);
 544        if (err)
 545                goto out;
 546
 547        /* Push on irq_data and the domain for each line. */
 548        for (i = 0; i < ngpio; i++) {
 549                struct irq_fwspec fwspec;
 550
 551                fwspec.fwnode = of_node_to_fwnode(dev->of_node);
 552                fwspec.param_count = 2;
 553                fwspec.param[0] = i;
 554                fwspec.param[1] = IRQ_TYPE_NONE;
 555                err = irq_domain_push_irq(girq->domain,
 556                                          txgpio->msix_entries[i].vector,
 557                                          &fwspec);
 558                if (err < 0)
 559                        dev_err(dev, "irq_domain_push_irq: %d\n", err);
 560        }
 561
 562        dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
 563                 ngpio, chip->base);
 564        return 0;
 565out:
 566        pci_set_drvdata(pdev, NULL);
 567        return err;
 568}
 569
 570static void thunderx_gpio_remove(struct pci_dev *pdev)
 571{
 572        int i;
 573        struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
 574
 575        for (i = 0; i < txgpio->chip.ngpio; i++)
 576                irq_domain_pop_irq(txgpio->chip.irq.domain,
 577                                   txgpio->msix_entries[i].vector);
 578
 579        irq_domain_remove(txgpio->chip.irq.domain);
 580
 581        pci_set_drvdata(pdev, NULL);
 582}
 583
 584static const struct pci_device_id thunderx_gpio_id_table[] = {
 585        { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xA00A) },
 586        { 0, }  /* end of table */
 587};
 588
 589MODULE_DEVICE_TABLE(pci, thunderx_gpio_id_table);
 590
 591static struct pci_driver thunderx_gpio_driver = {
 592        .name = KBUILD_MODNAME,
 593        .id_table = thunderx_gpio_id_table,
 594        .probe = thunderx_gpio_probe,
 595        .remove = thunderx_gpio_remove,
 596};
 597
 598module_pci_driver(thunderx_gpio_driver);
 599
 600MODULE_DESCRIPTION("Cavium Inc. ThunderX/OCTEON-TX GPIO Driver");
 601MODULE_LICENSE("GPL");
 602