root/drivers/gpio/gpio-104-idio-16.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. idio_16_gpio_get_direction
  2. idio_16_gpio_direction_input
  3. idio_16_gpio_direction_output
  4. idio_16_gpio_get
  5. idio_16_gpio_get_multiple
  6. idio_16_gpio_set
  7. idio_16_gpio_set_multiple
  8. idio_16_irq_ack
  9. idio_16_irq_mask
  10. idio_16_irq_unmask
  11. idio_16_irq_set_type
  12. idio_16_irq_handler
  13. idio_16_probe

   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 
  26 static unsigned int base[MAX_NUM_IDIO_16];
  27 static unsigned int num_idio_16;
  28 module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
  29 MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
  30 
  31 static unsigned int irq[MAX_NUM_IDIO_16];
  32 module_param_hw_array(irq, uint, irq, NULL, 0);
  33 MODULE_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  */
  43 struct 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 
  51 static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
  52 {
  53         if (offset > 15)
  54                 return 1;
  55 
  56         return 0;
  57 }
  58 
  59 static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  60 {
  61         return 0;
  62 }
  63 
  64 static 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 
  71 static 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 
  85 static 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 
  99 static 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 
 123 static 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 
 142 static void idio_16_irq_ack(struct irq_data *data)
 143 {
 144 }
 145 
 146 static 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 
 164 static 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 
 183 static 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 
 193 static 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 
 201 static 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
 220 static 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 
 227 static int idio_16_probe(struct device *dev, unsigned int id)
 228 {
 229         struct idio_16_gpio *idio16gpio;
 230         const char *const name = dev_name(dev);
 231         int err;
 232 
 233         idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
 234         if (!idio16gpio)
 235                 return -ENOMEM;
 236 
 237         if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
 238                 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
 239                         base[id], base[id] + IDIO_16_EXTENT);
 240                 return -EBUSY;
 241         }
 242 
 243         idio16gpio->chip.label = name;
 244         idio16gpio->chip.parent = dev;
 245         idio16gpio->chip.owner = THIS_MODULE;
 246         idio16gpio->chip.base = -1;
 247         idio16gpio->chip.ngpio = IDIO_16_NGPIO;
 248         idio16gpio->chip.names = idio_16_names;
 249         idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
 250         idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
 251         idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 252         idio16gpio->chip.get = idio_16_gpio_get;
 253         idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
 254         idio16gpio->chip.set = idio_16_gpio_set;
 255         idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 256         idio16gpio->base = base[id];
 257         idio16gpio->out_state = 0xFFFF;
 258 
 259         raw_spin_lock_init(&idio16gpio->lock);
 260 
 261         err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 262         if (err) {
 263                 dev_err(dev, "GPIO registering failed (%d)\n", err);
 264                 return err;
 265         }
 266 
 267         /* Disable IRQ by default */
 268         outb(0, base[id] + 2);
 269         outb(0, base[id] + 1);
 270 
 271         err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
 272                 handle_edge_irq, IRQ_TYPE_NONE);
 273         if (err) {
 274                 dev_err(dev, "Could not add irqchip (%d)\n", err);
 275                 return err;
 276         }
 277 
 278         err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
 279                 idio16gpio);
 280         if (err) {
 281                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
 282                 return err;
 283         }
 284 
 285         return 0;
 286 }
 287 
 288 static struct isa_driver idio_16_driver = {
 289         .probe = idio_16_probe,
 290         .driver = {
 291                 .name = "104-idio-16"
 292         },
 293 };
 294 
 295 module_isa_driver(idio_16_driver, num_idio_16);
 296 
 297 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 298 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
 299 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */