linux/drivers/gpio/gpio-pci-idio-16.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * GPIO driver for the ACCES PCI-IDIO-16
   4 * Copyright (C) 2017 William Breathitt Gray
   5 */
   6#include <linux/bitmap.h>
   7#include <linux/bitops.h>
   8#include <linux/device.h>
   9#include <linux/errno.h>
  10#include <linux/gpio/driver.h>
  11#include <linux/interrupt.h>
  12#include <linux/irqdesc.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/pci.h>
  16#include <linux/spinlock.h>
  17#include <linux/types.h>
  18
  19/**
  20 * struct idio_16_gpio_reg - GPIO device registers structure
  21 * @out0_7:     Read: FET Drive Outputs 0-7
  22 *              Write: FET Drive Outputs 0-7
  23 * @in0_7:      Read: Isolated Inputs 0-7
  24 *              Write: Clear Interrupt
  25 * @irq_ctl:    Read: Enable IRQ
  26 *              Write: Disable IRQ
  27 * @filter_ctl: Read: Activate Input Filters 0-15
  28 *              Write: Deactivate Input Filters 0-15
  29 * @out8_15:    Read: FET Drive Outputs 8-15
  30 *              Write: FET Drive Outputs 8-15
  31 * @in8_15:     Read: Isolated Inputs 8-15
  32 *              Write: Unused
  33 * @irq_status: Read: Interrupt status
  34 *              Write: Unused
  35 */
  36struct idio_16_gpio_reg {
  37        u8 out0_7;
  38        u8 in0_7;
  39        u8 irq_ctl;
  40        u8 filter_ctl;
  41        u8 out8_15;
  42        u8 in8_15;
  43        u8 irq_status;
  44};
  45
  46/**
  47 * struct idio_16_gpio - GPIO device private data structure
  48 * @chip:       instance of the gpio_chip
  49 * @lock:       synchronization lock to prevent I/O race conditions
  50 * @reg:        I/O address offset for the GPIO device registers
  51 * @irq_mask:   I/O bits affected by interrupts
  52 */
  53struct idio_16_gpio {
  54        struct gpio_chip chip;
  55        raw_spinlock_t lock;
  56        struct idio_16_gpio_reg __iomem *reg;
  57        unsigned long irq_mask;
  58};
  59
  60static int idio_16_gpio_get_direction(struct gpio_chip *chip,
  61        unsigned int offset)
  62{
  63        if (offset > 15)
  64                return GPIO_LINE_DIRECTION_IN;
  65
  66        return GPIO_LINE_DIRECTION_OUT;
  67}
  68
  69static int idio_16_gpio_direction_input(struct gpio_chip *chip,
  70        unsigned int offset)
  71{
  72        return 0;
  73}
  74
  75static int idio_16_gpio_direction_output(struct gpio_chip *chip,
  76        unsigned int offset, int value)
  77{
  78        chip->set(chip, offset, value);
  79        return 0;
  80}
  81
  82static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
  83{
  84        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
  85        unsigned long mask = BIT(offset);
  86
  87        if (offset < 8)
  88                return !!(ioread8(&idio16gpio->reg->out0_7) & mask);
  89
  90        if (offset < 16)
  91                return !!(ioread8(&idio16gpio->reg->out8_15) & (mask >> 8));
  92
  93        if (offset < 24)
  94                return !!(ioread8(&idio16gpio->reg->in0_7) & (mask >> 16));
  95
  96        return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
  97}
  98
  99static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
 100        unsigned long *mask, unsigned long *bits)
 101{
 102        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 103        unsigned long offset;
 104        unsigned long gpio_mask;
 105        void __iomem *ports[] = {
 106                &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
 107                &idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
 108        };
 109        void __iomem *port_addr;
 110        unsigned long port_state;
 111
 112        /* clear bits array to a clean slate */
 113        bitmap_zero(bits, chip->ngpio);
 114
 115        for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
 116                port_addr = ports[offset / 8];
 117                port_state = ioread8(port_addr) & gpio_mask;
 118
 119                bitmap_set_value8(bits, port_state, offset);
 120        }
 121
 122        return 0;
 123}
 124
 125static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
 126        int value)
 127{
 128        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 129        unsigned int mask = BIT(offset);
 130        void __iomem *base;
 131        unsigned long flags;
 132        unsigned int out_state;
 133
 134        if (offset > 15)
 135                return;
 136
 137        if (offset > 7) {
 138                mask >>= 8;
 139                base = &idio16gpio->reg->out8_15;
 140        } else
 141                base = &idio16gpio->reg->out0_7;
 142
 143        raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 144
 145        if (value)
 146                out_state = ioread8(base) | mask;
 147        else
 148                out_state = ioread8(base) & ~mask;
 149
 150        iowrite8(out_state, base);
 151
 152        raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 153}
 154
 155static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 156        unsigned long *mask, unsigned long *bits)
 157{
 158        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 159        unsigned long offset;
 160        unsigned long gpio_mask;
 161        void __iomem *ports[] = {
 162                &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
 163        };
 164        size_t index;
 165        void __iomem *port_addr;
 166        unsigned long bitmask;
 167        unsigned long flags;
 168        unsigned long out_state;
 169
 170        for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
 171                index = offset / 8;
 172                port_addr = ports[index];
 173
 174                bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
 175
 176                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 177
 178                out_state = ioread8(port_addr) & ~gpio_mask;
 179                out_state |= bitmask;
 180                iowrite8(out_state, port_addr);
 181
 182                raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 183        }
 184}
 185
 186static void idio_16_irq_ack(struct irq_data *data)
 187{
 188}
 189
 190static void idio_16_irq_mask(struct irq_data *data)
 191{
 192        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
 193        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 194        const unsigned long mask = BIT(irqd_to_hwirq(data));
 195        unsigned long flags;
 196
 197        idio16gpio->irq_mask &= ~mask;
 198
 199        if (!idio16gpio->irq_mask) {
 200                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 201
 202                iowrite8(0, &idio16gpio->reg->irq_ctl);
 203
 204                raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 205        }
 206}
 207
 208static void idio_16_irq_unmask(struct irq_data *data)
 209{
 210        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
 211        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 212        const unsigned long mask = BIT(irqd_to_hwirq(data));
 213        const unsigned long prev_irq_mask = idio16gpio->irq_mask;
 214        unsigned long flags;
 215
 216        idio16gpio->irq_mask |= mask;
 217
 218        if (!prev_irq_mask) {
 219                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 220
 221                ioread8(&idio16gpio->reg->irq_ctl);
 222
 223                raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 224        }
 225}
 226
 227static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
 228{
 229        /* The only valid irq types are none and both-edges */
 230        if (flow_type != IRQ_TYPE_NONE &&
 231                (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
 232                return -EINVAL;
 233
 234        return 0;
 235}
 236
 237static struct irq_chip idio_16_irqchip = {
 238        .name = "pci-idio-16",
 239        .irq_ack = idio_16_irq_ack,
 240        .irq_mask = idio_16_irq_mask,
 241        .irq_unmask = idio_16_irq_unmask,
 242        .irq_set_type = idio_16_irq_set_type
 243};
 244
 245static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 246{
 247        struct idio_16_gpio *const idio16gpio = dev_id;
 248        unsigned int irq_status;
 249        struct gpio_chip *const chip = &idio16gpio->chip;
 250        int gpio;
 251
 252        raw_spin_lock(&idio16gpio->lock);
 253
 254        irq_status = ioread8(&idio16gpio->reg->irq_status);
 255
 256        raw_spin_unlock(&idio16gpio->lock);
 257
 258        /* Make sure our device generated IRQ */
 259        if (!(irq_status & 0x3) || !(irq_status & 0x4))
 260                return IRQ_NONE;
 261
 262        for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 263                generic_handle_domain_irq(chip->irq.domain, gpio);
 264
 265        raw_spin_lock(&idio16gpio->lock);
 266
 267        /* Clear interrupt */
 268        iowrite8(0, &idio16gpio->reg->in0_7);
 269
 270        raw_spin_unlock(&idio16gpio->lock);
 271
 272        return IRQ_HANDLED;
 273}
 274
 275#define IDIO_16_NGPIO 32
 276static const char *idio_16_names[IDIO_16_NGPIO] = {
 277        "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
 278        "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
 279        "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
 280        "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
 281};
 282
 283static int idio_16_irq_init_hw(struct gpio_chip *gc)
 284{
 285        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
 286
 287        /* Disable IRQ by default and clear any pending interrupt */
 288        iowrite8(0, &idio16gpio->reg->irq_ctl);
 289        iowrite8(0, &idio16gpio->reg->in0_7);
 290
 291        return 0;
 292}
 293
 294static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 295{
 296        struct device *const dev = &pdev->dev;
 297        struct idio_16_gpio *idio16gpio;
 298        int err;
 299        const size_t pci_bar_index = 2;
 300        const char *const name = pci_name(pdev);
 301        struct gpio_irq_chip *girq;
 302
 303        idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
 304        if (!idio16gpio)
 305                return -ENOMEM;
 306
 307        err = pcim_enable_device(pdev);
 308        if (err) {
 309                dev_err(dev, "Failed to enable PCI device (%d)\n", err);
 310                return err;
 311        }
 312
 313        err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
 314        if (err) {
 315                dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
 316                return err;
 317        }
 318
 319        idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
 320
 321        /* Deactivate input filters */
 322        iowrite8(0, &idio16gpio->reg->filter_ctl);
 323
 324        idio16gpio->chip.label = name;
 325        idio16gpio->chip.parent = dev;
 326        idio16gpio->chip.owner = THIS_MODULE;
 327        idio16gpio->chip.base = -1;
 328        idio16gpio->chip.ngpio = IDIO_16_NGPIO;
 329        idio16gpio->chip.names = idio_16_names;
 330        idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
 331        idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
 332        idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 333        idio16gpio->chip.get = idio_16_gpio_get;
 334        idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
 335        idio16gpio->chip.set = idio_16_gpio_set;
 336        idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 337
 338        girq = &idio16gpio->chip.irq;
 339        girq->chip = &idio_16_irqchip;
 340        /* This will let us handle the parent IRQ in the driver */
 341        girq->parent_handler = NULL;
 342        girq->num_parents = 0;
 343        girq->parents = NULL;
 344        girq->default_type = IRQ_TYPE_NONE;
 345        girq->handler = handle_edge_irq;
 346        girq->init_hw = idio_16_irq_init_hw;
 347
 348        raw_spin_lock_init(&idio16gpio->lock);
 349
 350        err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 351        if (err) {
 352                dev_err(dev, "GPIO registering failed (%d)\n", err);
 353                return err;
 354        }
 355
 356        err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
 357                name, idio16gpio);
 358        if (err) {
 359                dev_err(dev, "IRQ handler registering failed (%d)\n", err);
 360                return err;
 361        }
 362
 363        return 0;
 364}
 365
 366static const struct pci_device_id idio_16_pci_dev_id[] = {
 367        { PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
 368};
 369MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id);
 370
 371static struct pci_driver idio_16_driver = {
 372        .name = "pci-idio-16",
 373        .id_table = idio_16_pci_dev_id,
 374        .probe = idio_16_probe
 375};
 376
 377module_pci_driver(idio_16_driver);
 378
 379MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 380MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
 381MODULE_LICENSE("GPL v2");
 382