root/drivers/gpio/gpio-pci-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 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  */
  36 struct 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  */
  53 struct 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 
  60 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
  61         unsigned int offset)
  62 {
  63         if (offset > 15)
  64                 return 1;
  65 
  66         return 0;
  67 }
  68 
  69 static int idio_16_gpio_direction_input(struct gpio_chip *chip,
  70         unsigned int offset)
  71 {
  72         return 0;
  73 }
  74 
  75 static 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 
  82 static 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 
  99 static 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         size_t i;
 104         const unsigned int gpio_reg_size = 8;
 105         unsigned int bits_offset;
 106         size_t word_index;
 107         unsigned int word_offset;
 108         unsigned long word_mask;
 109         const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
 110         unsigned long port_state;
 111         void __iomem *ports[] = {
 112                 &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
 113                 &idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
 114         };
 115 
 116         /* clear bits array to a clean slate */
 117         bitmap_zero(bits, chip->ngpio);
 118 
 119         /* get bits are evaluated a gpio port register at a time */
 120         for (i = 0; i < ARRAY_SIZE(ports); i++) {
 121                 /* gpio offset in bits array */
 122                 bits_offset = i * gpio_reg_size;
 123 
 124                 /* word index for bits array */
 125                 word_index = BIT_WORD(bits_offset);
 126 
 127                 /* gpio offset within current word of bits array */
 128                 word_offset = bits_offset % BITS_PER_LONG;
 129 
 130                 /* mask of get bits for current gpio within current word */
 131                 word_mask = mask[word_index] & (port_mask << word_offset);
 132                 if (!word_mask) {
 133                         /* no get bits in this port so skip to next one */
 134                         continue;
 135                 }
 136 
 137                 /* read bits from current gpio port */
 138                 port_state = ioread8(ports[i]);
 139 
 140                 /* store acquired bits at respective bits array offset */
 141                 bits[word_index] |= (port_state << word_offset) & word_mask;
 142         }
 143 
 144         return 0;
 145 }
 146 
 147 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
 148         int value)
 149 {
 150         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 151         unsigned int mask = BIT(offset);
 152         void __iomem *base;
 153         unsigned long flags;
 154         unsigned int out_state;
 155 
 156         if (offset > 15)
 157                 return;
 158 
 159         if (offset > 7) {
 160                 mask >>= 8;
 161                 base = &idio16gpio->reg->out8_15;
 162         } else
 163                 base = &idio16gpio->reg->out0_7;
 164 
 165         raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 166 
 167         if (value)
 168                 out_state = ioread8(base) | mask;
 169         else
 170                 out_state = ioread8(base) & ~mask;
 171 
 172         iowrite8(out_state, base);
 173 
 174         raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 175 }
 176 
 177 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 178         unsigned long *mask, unsigned long *bits)
 179 {
 180         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 181         unsigned long flags;
 182         unsigned int out_state;
 183 
 184         raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 185 
 186         /* process output lines 0-7 */
 187         if (*mask & 0xFF) {
 188                 out_state = ioread8(&idio16gpio->reg->out0_7) & ~*mask;
 189                 out_state |= *mask & *bits;
 190                 iowrite8(out_state, &idio16gpio->reg->out0_7);
 191         }
 192 
 193         /* shift to next output line word */
 194         *mask >>= 8;
 195 
 196         /* process output lines 8-15 */
 197         if (*mask & 0xFF) {
 198                 *bits >>= 8;
 199                 out_state = ioread8(&idio16gpio->reg->out8_15) & ~*mask;
 200                 out_state |= *mask & *bits;
 201                 iowrite8(out_state, &idio16gpio->reg->out8_15);
 202         }
 203 
 204         raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 205 }
 206 
 207 static void idio_16_irq_ack(struct irq_data *data)
 208 {
 209 }
 210 
 211 static void idio_16_irq_mask(struct irq_data *data)
 212 {
 213         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
 214         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 215         const unsigned long mask = BIT(irqd_to_hwirq(data));
 216         unsigned long flags;
 217 
 218         idio16gpio->irq_mask &= ~mask;
 219 
 220         if (!idio16gpio->irq_mask) {
 221                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 222 
 223                 iowrite8(0, &idio16gpio->reg->irq_ctl);
 224 
 225                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 226         }
 227 }
 228 
 229 static void idio_16_irq_unmask(struct irq_data *data)
 230 {
 231         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
 232         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 233         const unsigned long mask = BIT(irqd_to_hwirq(data));
 234         const unsigned long prev_irq_mask = idio16gpio->irq_mask;
 235         unsigned long flags;
 236 
 237         idio16gpio->irq_mask |= mask;
 238 
 239         if (!prev_irq_mask) {
 240                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 241 
 242                 ioread8(&idio16gpio->reg->irq_ctl);
 243 
 244                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 245         }
 246 }
 247 
 248 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
 249 {
 250         /* The only valid irq types are none and both-edges */
 251         if (flow_type != IRQ_TYPE_NONE &&
 252                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
 253                 return -EINVAL;
 254 
 255         return 0;
 256 }
 257 
 258 static struct irq_chip idio_16_irqchip = {
 259         .name = "pci-idio-16",
 260         .irq_ack = idio_16_irq_ack,
 261         .irq_mask = idio_16_irq_mask,
 262         .irq_unmask = idio_16_irq_unmask,
 263         .irq_set_type = idio_16_irq_set_type
 264 };
 265 
 266 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 267 {
 268         struct idio_16_gpio *const idio16gpio = dev_id;
 269         unsigned int irq_status;
 270         struct gpio_chip *const chip = &idio16gpio->chip;
 271         int gpio;
 272 
 273         raw_spin_lock(&idio16gpio->lock);
 274 
 275         irq_status = ioread8(&idio16gpio->reg->irq_status);
 276 
 277         raw_spin_unlock(&idio16gpio->lock);
 278 
 279         /* Make sure our device generated IRQ */
 280         if (!(irq_status & 0x3) || !(irq_status & 0x4))
 281                 return IRQ_NONE;
 282 
 283         for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 284                 generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
 285 
 286         raw_spin_lock(&idio16gpio->lock);
 287 
 288         /* Clear interrupt */
 289         iowrite8(0, &idio16gpio->reg->in0_7);
 290 
 291         raw_spin_unlock(&idio16gpio->lock);
 292 
 293         return IRQ_HANDLED;
 294 }
 295 
 296 #define IDIO_16_NGPIO 32
 297 static const char *idio_16_names[IDIO_16_NGPIO] = {
 298         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
 299         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
 300         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
 301         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
 302 };
 303 
 304 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 305 {
 306         struct device *const dev = &pdev->dev;
 307         struct idio_16_gpio *idio16gpio;
 308         int err;
 309         const size_t pci_bar_index = 2;
 310         const char *const name = pci_name(pdev);
 311 
 312         idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
 313         if (!idio16gpio)
 314                 return -ENOMEM;
 315 
 316         err = pcim_enable_device(pdev);
 317         if (err) {
 318                 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
 319                 return err;
 320         }
 321 
 322         err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
 323         if (err) {
 324                 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
 325                 return err;
 326         }
 327 
 328         idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
 329 
 330         /* Deactivate input filters */
 331         iowrite8(0, &idio16gpio->reg->filter_ctl);
 332 
 333         idio16gpio->chip.label = name;
 334         idio16gpio->chip.parent = dev;
 335         idio16gpio->chip.owner = THIS_MODULE;
 336         idio16gpio->chip.base = -1;
 337         idio16gpio->chip.ngpio = IDIO_16_NGPIO;
 338         idio16gpio->chip.names = idio_16_names;
 339         idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
 340         idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
 341         idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 342         idio16gpio->chip.get = idio_16_gpio_get;
 343         idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
 344         idio16gpio->chip.set = idio_16_gpio_set;
 345         idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 346 
 347         raw_spin_lock_init(&idio16gpio->lock);
 348 
 349         err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 350         if (err) {
 351                 dev_err(dev, "GPIO registering failed (%d)\n", err);
 352                 return err;
 353         }
 354 
 355         /* Disable IRQ by default and clear any pending interrupt */
 356         iowrite8(0, &idio16gpio->reg->irq_ctl);
 357         iowrite8(0, &idio16gpio->reg->in0_7);
 358 
 359         err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
 360                 handle_edge_irq, IRQ_TYPE_NONE);
 361         if (err) {
 362                 dev_err(dev, "Could not add irqchip (%d)\n", err);
 363                 return err;
 364         }
 365 
 366         err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
 367                 name, idio16gpio);
 368         if (err) {
 369                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
 370                 return err;
 371         }
 372 
 373         return 0;
 374 }
 375 
 376 static const struct pci_device_id idio_16_pci_dev_id[] = {
 377         { PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
 378 };
 379 MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id);
 380 
 381 static struct pci_driver idio_16_driver = {
 382         .name = "pci-idio-16",
 383         .id_table = idio_16_pci_dev_id,
 384         .probe = idio_16_probe
 385 };
 386 
 387 module_pci_driver(idio_16_driver);
 388 
 389 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 390 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
 391 MODULE_LICENSE("GPL v2");

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