OSDN Git Service

gpio: pci-idio-16: Utilize the idio-16 GPIO library
authorWilliam Breathitt Gray <william.gray@linaro.org>
Sun, 18 Sep 2022 16:50:45 +0000 (12:50 -0400)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Tue, 25 Oct 2022 07:58:27 +0000 (09:58 +0200)
The ACCES PCI-IDIO-16 device is part of the ACCES IDIO-16 family, so the
idio-16 GPIO library module is selected and utilized to consolidate
code.

Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/Kconfig
drivers/gpio/gpio-pci-idio-16.c

index 3b0a030..5a04990 100644 (file)
@@ -1563,6 +1563,7 @@ config GPIO_PCH
 config GPIO_PCI_IDIO_16
        tristate "ACCES PCI-IDIO-16 GPIO support"
        select GPIOLIB_IRQCHIP
+       select GPIO_IDIO_16
        help
          Enables GPIO support for the ACCES PCI-IDIO-16. An interrupt is
          generated when any of the inputs change state (low to high or high to
index 71a13a3..a86ce74 100644 (file)
@@ -3,8 +3,7 @@
  * GPIO driver for the ACCES PCI-IDIO-16
  * Copyright (C) 2017 William Breathitt Gray
  */
-#include <linux/bitmap.h>
-#include <linux/bitops.h>
+#include <linux/bits.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/gpio/driver.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-/**
- * struct idio_16_gpio_reg - GPIO device registers structure
- * @out0_7:    Read: FET Drive Outputs 0-7
- *             Write: FET Drive Outputs 0-7
- * @in0_7:     Read: Isolated Inputs 0-7
- *             Write: Clear Interrupt
- * @irq_ctl:   Read: Enable IRQ
- *             Write: Disable IRQ
- * @filter_ctl:        Read: Activate Input Filters 0-15
- *             Write: Deactivate Input Filters 0-15
- * @out8_15:   Read: FET Drive Outputs 8-15
- *             Write: FET Drive Outputs 8-15
- * @in8_15:    Read: Isolated Inputs 8-15
- *             Write: Unused
- * @irq_status:        Read: Interrupt status
- *             Write: Unused
- */
-struct idio_16_gpio_reg {
-       u8 out0_7;
-       u8 in0_7;
-       u8 irq_ctl;
-       u8 filter_ctl;
-       u8 out8_15;
-       u8 in8_15;
-       u8 irq_status;
-};
+#include "gpio-idio-16.h"
 
 /**
  * struct idio_16_gpio - GPIO device private data structure
  * @chip:      instance of the gpio_chip
  * @lock:      synchronization lock to prevent I/O race conditions
  * @reg:       I/O address offset for the GPIO device registers
+ * @state:     ACCES IDIO-16 device state
  * @irq_mask:  I/O bits affected by interrupts
  */
 struct idio_16_gpio {
        struct gpio_chip chip;
        raw_spinlock_t lock;
-       struct idio_16_gpio_reg __iomem *reg;
+       struct idio_16 __iomem *reg;
+       struct idio_16_state state;
        unsigned long irq_mask;
 };
 
 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
        unsigned int offset)
 {
-       if (offset > 15)
+       if (idio_16_get_direction(offset))
                return GPIO_LINE_DIRECTION_IN;
 
        return GPIO_LINE_DIRECTION_OUT;
@@ -82,43 +58,16 @@ static int idio_16_gpio_direction_output(struct gpio_chip *chip,
 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
 {
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-       unsigned long mask = BIT(offset);
-
-       if (offset < 8)
-               return !!(ioread8(&idio16gpio->reg->out0_7) & mask);
-
-       if (offset < 16)
-               return !!(ioread8(&idio16gpio->reg->out8_15) & (mask >> 8));
-
-       if (offset < 24)
-               return !!(ioread8(&idio16gpio->reg->in0_7) & (mask >> 16));
 
-       return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
+       return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset);
 }
 
 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
        unsigned long *mask, unsigned long *bits)
 {
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-       unsigned long offset;
-       unsigned long gpio_mask;
-       void __iomem *ports[] = {
-               &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
-               &idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
-       };
-       void __iomem *port_addr;
-       unsigned long port_state;
-
-       /* clear bits array to a clean slate */
-       bitmap_zero(bits, chip->ngpio);
-
-       for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
-               port_addr = ports[offset / 8];
-               port_state = ioread8(port_addr) & gpio_mask;
-
-               bitmap_set_value8(bits, port_state, offset);
-       }
 
+       idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
        return 0;
 }
 
@@ -126,61 +75,16 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
        int value)
 {
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-       unsigned int mask = BIT(offset);
-       void __iomem *base;
-       unsigned long flags;
-       unsigned int out_state;
-
-       if (offset > 15)
-               return;
-
-       if (offset > 7) {
-               mask >>= 8;
-               base = &idio16gpio->reg->out8_15;
-       } else
-               base = &idio16gpio->reg->out0_7;
-
-       raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
-       if (value)
-               out_state = ioread8(base) | mask;
-       else
-               out_state = ioread8(base) & ~mask;
-
-       iowrite8(out_state, base);
-
-       raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
+       idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value);
 }
 
 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
        unsigned long *mask, unsigned long *bits)
 {
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-       unsigned long offset;
-       unsigned long gpio_mask;
-       void __iomem *ports[] = {
-               &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
-       };
-       size_t index;
-       void __iomem *port_addr;
-       unsigned long bitmask;
-       unsigned long flags;
-       unsigned long out_state;
 
-       for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
-               index = offset / 8;
-               port_addr = ports[index];
-
-               bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
-
-               raw_spin_lock_irqsave(&idio16gpio->lock, flags);
-
-               out_state = ioread8(port_addr) & ~gpio_mask;
-               out_state |= bitmask;
-               iowrite8(out_state, port_addr);
-
-               raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
-       }
+       idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
 }
 
 static void idio_16_irq_ack(struct irq_data *data)
@@ -335,6 +239,8 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        idio16gpio->chip.set = idio_16_gpio_set;
        idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 
+       idio_16_state_init(&idio16gpio->state);
+
        girq = &idio16gpio->chip.irq;
        girq->chip = &idio_16_irqchip;
        /* This will let us handle the parent IRQ in the driver */
@@ -379,3 +285,4 @@ module_pci_driver(idio_16_driver);
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(GPIO_IDIO_16);