linux/drivers/gpio/gpio-104-idio-16.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * GPIO driver for the ACCES 104-IDIO-16 family
   4 * Copyright (C) 2015 William Breathitt Gray
   5 *
   6 * This driver supports the following ACCES devices: 104-IDIO-16,
   7 * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
   8 */
   9#include <linux/bitops.h>
  10#include <linux/device.h>
  11#include <linux/errno.h>
  12#include <linux/gpio/driver.h>
  13#include <linux/io.h>
  14#include <linux/ioport.h>
  15#include <linux/interrupt.h>
  16#include <linux/irqdesc.h>
  17#include <linux/isa.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/moduleparam.h>
  21#include <linux/spinlock.h>
  22
  23#define IDIO_16_EXTENT 8
  24#define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
  25
  26static unsigned int base[MAX_NUM_IDIO_16];
  27static unsigned int num_idio_16;
  28module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
  29MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
  30
  31static unsigned int irq[MAX_NUM_IDIO_16];
  32module_param_hw_array(irq, uint, irq, NULL, 0);
  33MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
  34
  35/**
  36 * struct idio_16_gpio - GPIO device private data structure
  37 * @chip:       instance of the gpio_chip
  38 * @lock:       synchronization lock to prevent I/O race conditions
  39 * @irq_mask:   I/O bits affected by interrupts
  40 * @base:       base port address of the GPIO device
  41 * @out_state:  output bits state
  42 */
  43struct idio_16_gpio {
  44        struct gpio_chip chip;
  45        raw_spinlock_t lock;
  46        unsigned long irq_mask;
  47        unsigned base;
  48        unsigned out_state;
  49};
  50
  51static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
  52{
  53        if (offset > 15)
  54                return GPIO_LINE_DIRECTION_IN;
  55
  56        return GPIO_LINE_DIRECTION_OUT;
  57}
  58
  59static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  60{
  61        return 0;
  62}
  63
  64static int idio_16_gpio_direction_output(struct gpio_chip *chip,
  65        unsigned offset, int value)
  66{
  67        chip->set(chip, offset, value);
  68        return 0;
  69}
  70
  71static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
  72{
  73        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
  74        const unsigned mask = BIT(offset-16);
  75
  76        if (offset < 16)
  77                return -EINVAL;
  78
  79        if (offset < 24)
  80                return !!(inb(idio16gpio->base + 1) & mask);
  81
  82        return !!(inb(idio16gpio->base + 5) & (mask>>8));
  83}
  84
  85static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
  86        unsigned long *mask, unsigned long *bits)
  87{
  88        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
  89
  90        *bits = 0;
  91        if (*mask & GENMASK(23, 16))
  92                *bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
  93        if (*mask & GENMASK(31, 24))
  94                *bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
  95
  96        return 0;
  97}
  98
  99static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 100{
 101        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 102        const unsigned mask = BIT(offset);
 103        unsigned long flags;
 104
 105        if (offset > 15)
 106                return;
 107
 108        raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 109
 110        if (value)
 111                idio16gpio->out_state |= mask;
 112        else
 113                idio16gpio->out_state &= ~mask;
 114
 115        if (offset > 7)
 116                outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
 117        else
 118                outb(idio16gpio->out_state, idio16gpio->base);
 119
 120        raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 121}
 122
 123static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 124        unsigned long *mask, unsigned long *bits)
 125{
 126        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 127        unsigned long flags;
 128
 129        raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 130
 131        idio16gpio->out_state &= ~*mask;
 132        idio16gpio->out_state |= *mask & *bits;
 133
 134        if (*mask & 0xFF)
 135                outb(idio16gpio->out_state, idio16gpio->base);
 136        if ((*mask >> 8) & 0xFF)
 137                outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
 138
 139        raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 140}
 141
 142static void idio_16_irq_ack(struct irq_data *data)
 143{
 144}
 145
 146static void idio_16_irq_mask(struct irq_data *data)
 147{
 148        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
 149        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 150        const unsigned long mask = BIT(irqd_to_hwirq(data));
 151        unsigned long flags;
 152
 153        idio16gpio->irq_mask &= ~mask;
 154
 155        if (!idio16gpio->irq_mask) {
 156                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 157
 158                outb(0, idio16gpio->base + 2);
 159
 160                raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 161        }
 162}
 163
 164static void idio_16_irq_unmask(struct irq_data *data)
 165{
 166        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
 167        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 168        const unsigned long mask = BIT(irqd_to_hwirq(data));
 169        const unsigned long prev_irq_mask = idio16gpio->irq_mask;
 170        unsigned long flags;
 171
 172        idio16gpio->irq_mask |= mask;
 173
 174        if (!prev_irq_mask) {
 175                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 176
 177                inb(idio16gpio->base + 2);
 178
 179                raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 180        }
 181}
 182
 183static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type)
 184{
 185        /* The only valid irq types are none and both-edges */
 186        if (flow_type != IRQ_TYPE_NONE &&
 187                (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
 188                return -EINVAL;
 189
 190        return 0;
 191}
 192
 193static struct irq_chip idio_16_irqchip = {
 194        .name = "104-idio-16",
 195        .irq_ack = idio_16_irq_ack,
 196        .irq_mask = idio_16_irq_mask,
 197        .irq_unmask = idio_16_irq_unmask,
 198        .irq_set_type = idio_16_irq_set_type
 199};
 200
 201static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 202{
 203        struct idio_16_gpio *const idio16gpio = dev_id;
 204        struct gpio_chip *const chip = &idio16gpio->chip;
 205        int gpio;
 206
 207        for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 208                generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
 209
 210        raw_spin_lock(&idio16gpio->lock);
 211
 212        outb(0, idio16gpio->base + 1);
 213
 214        raw_spin_unlock(&idio16gpio->lock);
 215
 216        return IRQ_HANDLED;
 217}
 218
 219#define IDIO_16_NGPIO 32
 220static const char *idio_16_names[IDIO_16_NGPIO] = {
 221        "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
 222        "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
 223        "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
 224        "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
 225};
 226
 227static int idio_16_irq_init_hw(struct gpio_chip *gc)
 228{
 229        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
 230
 231        /* Disable IRQ by default */
 232        outb(0, idio16gpio->base + 2);
 233        outb(0, idio16gpio->base + 1);
 234
 235        return 0;
 236}
 237
 238static int idio_16_probe(struct device *dev, unsigned int id)
 239{
 240        struct idio_16_gpio *idio16gpio;
 241        const char *const name = dev_name(dev);
 242        struct gpio_irq_chip *girq;
 243        int err;
 244
 245        idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
 246        if (!idio16gpio)
 247                return -ENOMEM;
 248
 249        if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
 250                dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
 251                        base[id], base[id] + IDIO_16_EXTENT);
 252                return -EBUSY;
 253        }
 254
 255        idio16gpio->chip.label = name;
 256        idio16gpio->chip.parent = dev;
 257        idio16gpio->chip.owner = THIS_MODULE;
 258        idio16gpio->chip.base = -1;
 259        idio16gpio->chip.ngpio = IDIO_16_NGPIO;
 260        idio16gpio->chip.names = idio_16_names;
 261        idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
 262        idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
 263        idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 264        idio16gpio->chip.get = idio_16_gpio_get;
 265        idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
 266        idio16gpio->chip.set = idio_16_gpio_set;
 267        idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 268        idio16gpio->base = base[id];
 269        idio16gpio->out_state = 0xFFFF;
 270
 271        girq = &idio16gpio->chip.irq;
 272        girq->chip = &idio_16_irqchip;
 273        /* This will let us handle the parent IRQ in the driver */
 274        girq->parent_handler = NULL;
 275        girq->num_parents = 0;
 276        girq->parents = NULL;
 277        girq->default_type = IRQ_TYPE_NONE;
 278        girq->handler = handle_edge_irq;
 279        girq->init_hw = idio_16_irq_init_hw;
 280
 281        raw_spin_lock_init(&idio16gpio->lock);
 282
 283        err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 284        if (err) {
 285                dev_err(dev, "GPIO registering failed (%d)\n", err);
 286                return err;
 287        }
 288
 289        err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
 290                idio16gpio);
 291        if (err) {
 292                dev_err(dev, "IRQ handler registering failed (%d)\n", err);
 293                return err;
 294        }
 295
 296        return 0;
 297}
 298
 299static struct isa_driver idio_16_driver = {
 300        .probe = idio_16_probe,
 301        .driver = {
 302                .name = "104-idio-16"
 303        },
 304};
 305
 306module_isa_driver(idio_16_driver, num_idio_16);
 307
 308MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 309MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
 310MODULE_LICENSE("GPL v2");
 311