gpio: 104-idio-16: Utilize the idio-16 GPIO library
authorWilliam Breathitt Gray <william.gray@linaro.org>
Tue, 25 Oct 2022 07:57:57 +0000 (09:57 +0200)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Tue, 25 Oct 2022 07:57:57 +0000 (09:57 +0200)
The ACCES 104-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-104-idio-16.c

index 3f8cf6e..3b0a030 100644 (file)
@@ -858,6 +858,7 @@ config GPIO_104_IDIO_16
        depends on PC104
        select ISA_BUS_API
        select GPIOLIB_IRQCHIP
+       select GPIO_IDIO_16
        help
          Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
          104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, 104-IDO-8). The
index 718bd54..098fbef 100644 (file)
@@ -6,7 +6,7 @@
  * This driver supports the following ACCES devices: 104-IDIO-16,
  * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
  */
-#include <linux/bits.h>
+#include <linux/bitmap.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/gpio/driver.h>
@@ -21,6 +21,8 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
+#include "gpio-idio-16.h"
+
 #define IDIO_16_EXTENT 8
 #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
 
@@ -34,49 +36,26 @@ static unsigned int num_irq;
 module_param_hw_array(irq, uint, irq, &num_irq, 0);
 MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
 
-/**
- * struct idio_16_reg - device registers structure
- * @out0_7:    Read: N/A
- *             Write: FET Drive Outputs 0-7
- * @in0_7:     Read: Isolated Inputs 0-7
- *             Write: Clear Interrupt
- * @irq_ctl:   Read: Enable IRQ
- *             Write: Disable IRQ
- * @unused:    N/A
- * @out8_15:   Read: N/A
- *             Write: FET Drive Outputs 8-15
- * @in8_15:    Read: Isolated Inputs 8-15
- *             Write: N/A
- */
-struct idio_16_reg {
-       u8 out0_7;
-       u8 in0_7;
-       u8 irq_ctl;
-       u8 unused;
-       u8 out8_15;
-       u8 in8_15;
-};
-
 /**
  * struct idio_16_gpio - GPIO device private data structure
  * @chip:      instance of the gpio_chip
  * @lock:      synchronization lock to prevent I/O race conditions
  * @irq_mask:  I/O bits affected by interrupts
  * @reg:       I/O address offset for the device registers
- * @out_state: output bits state
+ * @state:     ACCES IDIO-16 device state
  */
 struct idio_16_gpio {
        struct gpio_chip chip;
        raw_spinlock_t lock;
        unsigned long irq_mask;
-       struct idio_16_reg __iomem *reg;
-       unsigned int out_state;
+       struct idio_16 __iomem *reg;
+       struct idio_16_state state;
 };
 
 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;
@@ -98,15 +77,8 @@ 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);
-       const unsigned int mask = BIT(offset-16);
 
-       if (offset < 16)
-               return -EINVAL;
-
-       if (offset < 24)
-               return !!(ioread8(&idio16gpio->reg->in0_7) & mask);
-
-       return !!(ioread8(&idio16gpio->reg->in8_15) & (mask>>8));
+       return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset);
 }
 
 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
@@ -114,11 +86,7 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
 {
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 
-       *bits = 0;
-       if (*mask & GENMASK(23, 16))
-               *bits |= (unsigned long)ioread8(&idio16gpio->reg->in0_7) << 16;
-       if (*mask & GENMASK(31, 24))
-               *bits |= (unsigned long)ioread8(&idio16gpio->reg->in8_15) << 24;
+       idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
 
        return 0;
 }
@@ -127,44 +95,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);
-       const unsigned int mask = BIT(offset);
-       unsigned long flags;
 
-       if (offset > 15)
-               return;
-
-       raw_spin_lock_irqsave(&idio16gpio->lock, flags);
-
-       if (value)
-               idio16gpio->out_state |= mask;
-       else
-               idio16gpio->out_state &= ~mask;
-
-       if (offset > 7)
-               iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
-       else
-               iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
-
-       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 flags;
 
-       raw_spin_lock_irqsave(&idio16gpio->lock, flags);
-
-       idio16gpio->out_state &= ~*mask;
-       idio16gpio->out_state |= *mask & *bits;
-
-       if (*mask & 0xFF)
-               iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
-       if ((*mask >> 8) & 0xFF)
-               iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
-
-       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)
@@ -301,7 +241,10 @@ static int idio_16_probe(struct device *dev, unsigned int id)
        idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
        idio16gpio->chip.set = idio_16_gpio_set;
        idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
-       idio16gpio->out_state = 0xFFFF;
+
+       idio_16_state_init(&idio16gpio->state);
+       /* FET off states are represented by bit values of "1" */
+       bitmap_fill(idio16gpio->state.out_state, IDIO_16_NOUT);
 
        girq = &idio16gpio->chip.irq;
        gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
@@ -343,3 +286,4 @@ module_isa_driver_with_irq(idio_16_driver, num_idio_16, num_irq);
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(GPIO_IDIO_16);