2022-11-06 07:29:52

by William Breathitt Gray

[permalink] [raw]
Subject: [PATCH 1/3] gpio: 104-dio-48e: Migrate to regmap API

The regmap API supports IO port accessors so we can take advantage of
regmap abstractions rather than handling access to the device registers
directly in the driver.

Signed-off-by: William Breathitt Gray <[email protected]>
---
drivers/gpio/gpio-104-dio-48e.c | 95 ++++++++++++++++++++++-----------
1 file changed, 64 insertions(+), 31 deletions(-)

diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 7b8829c8e423..134e3dd12ae9 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -8,9 +8,9 @@
*/
#include <linux/bits.h>
#include <linux/device.h>
+#include <linux/err.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
-#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irqdesc.h>
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <linux/types.h>

@@ -38,30 +39,25 @@ static unsigned int num_irq;
module_param_hw_array(irq, uint, irq, &num_irq, 0);
MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");

+#define DIO48E_NAME "104-dio-48e"
+
+#define DIO48E_REGS_OFFSET 0x8
+#define DIO48E_ENABLE_BUFFER_GRP0 0x0
+#define DIO48E_ENABLE_BUFFER_GRP1 0x1
+#define DIO48E_ENABLE_INTERRUPT 0x3
+#define DIO48E_DISABLE_INTERRUPT 0x3
+#define DIO48E_ENABLE_COUNTER 0x5
+#define DIO48E_DISABLE_COUNTER 0x5
+#define DIO48E_CLEAR_INTERRUPT 0x7
+
#define DIO48E_NUM_PPI 2

/**
* struct dio48e_reg - device register structure
* @ppi: Programmable Peripheral Interface groups
- * @enable_buffer: Enable/Disable Buffer groups
- * @unused1: Unused
- * @enable_interrupt: Write: Enable Interrupt
- * Read: Disable Interrupt
- * @unused2: Unused
- * @enable_counter: Write: Enable Counter/Timer Addressing
- * Read: Disable Counter/Timer Addressing
- * @unused3: Unused
- * @clear_interrupt: Clear Interrupt
*/
struct dio48e_reg {
struct i8255 ppi[DIO48E_NUM_PPI];
- u8 enable_buffer[DIO48E_NUM_PPI];
- u8 unused1;
- u8 enable_interrupt;
- u8 unused2;
- u8 enable_counter;
- u8 unused3;
- u8 clear_interrupt;
};

/**
@@ -70,6 +66,7 @@ struct dio48e_reg {
* @ppi_state: PPI device states
* @lock: synchronization lock to prevent I/O race conditions
* @reg: I/O address offset for the device registers
+ * @map: device register map
* @irq_mask: I/O bits affected by interrupts
*/
struct dio48e_gpio {
@@ -77,6 +74,7 @@ struct dio48e_gpio {
struct i8255_state ppi_state[DIO48E_NUM_PPI];
raw_spinlock_t lock;
struct dio48e_reg __iomem *reg;
+ struct regmap *map;
unsigned char irq_mask;
};

@@ -154,6 +152,7 @@ static void dio48e_irq_mask(struct irq_data *data)
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned long offset = irqd_to_hwirq(data);
unsigned long flags;
+ unsigned int val;

/* only bit 3 on each respective Port C supports interrupts */
if (offset != 19 && offset != 43)
@@ -168,8 +167,7 @@ static void dio48e_irq_mask(struct irq_data *data)
gpiochip_disable_irq(chip, offset);

if (!dio48egpio->irq_mask)
- /* disable interrupts */
- ioread8(&dio48egpio->reg->enable_interrupt);
+ regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val);

raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
}
@@ -188,9 +186,8 @@ static void dio48e_irq_unmask(struct irq_data *data)
raw_spin_lock_irqsave(&dio48egpio->lock, flags);

if (!dio48egpio->irq_mask) {
- /* enable interrupts */
- iowrite8(0x00, &dio48egpio->reg->clear_interrupt);
- iowrite8(0x00, &dio48egpio->reg->enable_interrupt);
+ regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00);
+ regmap_write(dio48egpio->map, DIO48E_ENABLE_INTERRUPT, 0x00);
}

gpiochip_enable_irq(chip, offset);
@@ -217,7 +214,7 @@ static int dio48e_irq_set_type(struct irq_data *data, unsigned int flow_type)
}

static const struct irq_chip dio48e_irqchip = {
- .name = "104-dio-48e",
+ .name = DIO48E_NAME,
.irq_ack = dio48e_irq_ack,
.irq_mask = dio48e_irq_mask,
.irq_unmask = dio48e_irq_unmask,
@@ -239,7 +236,7 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)

raw_spin_lock(&dio48egpio->lock);

- iowrite8(0x00, &dio48egpio->reg->clear_interrupt);
+ regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00);

raw_spin_unlock(&dio48egpio->lock);

@@ -269,11 +266,9 @@ static const char *dio48e_names[DIO48E_NGPIO] = {
static int dio48e_irq_init_hw(struct gpio_chip *gc)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(gc);
+ unsigned int val;

- /* Disable IRQ by default */
- ioread8(&dio48egpio->reg->enable_interrupt);
-
- return 0;
+ return regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val);
}

static void dio48e_init_ppi(struct i8255 __iomem *const ppi,
@@ -291,10 +286,42 @@ static void dio48e_init_ppi(struct i8255 __iomem *const ppi,
}
}

+static const struct regmap_range dio48e_wr_ranges[] = {
+ regmap_reg_range(0x0, 0x1),
+ regmap_reg_range(0x3, 0x3),
+ regmap_reg_range(0x5, 0x5),
+ regmap_reg_range(0x7, 0x7),
+};
+static const struct regmap_range dio48e_rd_ranges[] = {
+ regmap_reg_range(0x3, 0x3),
+ regmap_reg_range(0x5, 0x5),
+ regmap_reg_range(0x7, 0x7),
+};
+static const struct regmap_access_table dio48e_wr_table = {
+ .yes_ranges = dio48e_wr_ranges,
+ .n_yes_ranges = ARRAY_SIZE(dio48e_wr_ranges),
+};
+static const struct regmap_access_table dio48e_rd_table = {
+ .yes_ranges = dio48e_rd_ranges,
+ .n_yes_ranges = ARRAY_SIZE(dio48e_rd_ranges),
+};
+
+static const struct regmap_config dio48e_regmap_config = {
+ .name = DIO48E_NAME,
+ .reg_bits = 8,
+ .val_bits = 8,
+ .reg_stride = 1,
+ .io_port = true,
+ .max_register = 0x7,
+ .wr_table = &dio48e_wr_table,
+ .rd_table = &dio48e_rd_table,
+};
+
static int dio48e_probe(struct device *dev, unsigned int id)
{
struct dio48e_gpio *dio48egpio;
const char *const name = dev_name(dev);
+ void __iomem *regs;
struct gpio_irq_chip *girq;
int err;

@@ -308,9 +335,15 @@ static int dio48e_probe(struct device *dev, unsigned int id)
return -EBUSY;
}

- dio48egpio->reg = devm_ioport_map(dev, base[id], DIO48E_EXTENT);
- if (!dio48egpio->reg)
+ regs = devm_ioport_map(dev, base[id], DIO48E_EXTENT);
+ if (!regs)
return -ENOMEM;
+ dio48egpio->reg = regs;
+
+ dio48egpio->map = devm_regmap_init_mmio(dev, regs + DIO48E_REGS_OFFSET,
+ &dio48e_regmap_config);
+ if (IS_ERR(dio48egpio->map))
+ return PTR_ERR(dio48egpio->map);

dio48egpio->chip.label = name;
dio48egpio->chip.parent = dev;
@@ -360,7 +393,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
static struct isa_driver dio48e_driver = {
.probe = dio48e_probe,
.driver = {
- .name = "104-dio-48e"
+ .name = DIO48E_NAME,
},
};
module_isa_driver_with_irq(dio48e_driver, num_dio48e, num_irq);
--
2.37.3



2022-11-07 11:40:45

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH 1/3] gpio: 104-dio-48e: Migrate to regmap API

On Thu, Nov 03, 2022 at 07:20:47AM -0400, William Breathitt Gray wrote:
> The regmap API supports IO port accessors so we can take advantage of
> regmap abstractions rather than handling access to the device registers
> directly in the driver.

I'm wondering if gpio-regmap can be used for these...

--
With Best Regards,
Andy Shevchenko



2022-11-09 21:02:14

by William Breathitt Gray

[permalink] [raw]
Subject: Re: [PATCH 1/3] gpio: 104-dio-48e: Migrate to regmap API

On Mon, Nov 07, 2022 at 12:38:47PM +0200, Andy Shevchenko wrote:
> On Thu, Nov 03, 2022 at 07:20:47AM -0400, William Breathitt Gray wrote:
> > The regmap API supports IO port accessors so we can take advantage of
> > regmap abstractions rather than handling access to the device registers
> > directly in the driver.
>
> I'm wondering if gpio-regmap can be used for these...
>
> --
> With Best Regards,
> Andy Shevchenko

I might be able to update the gpio-i8255 functions to take advantage of
gpio-regmap, but the changes in the precursor patches are primarily to
handle the device interrupts. Currently, I call gpio_irq_chip_set_chip()
to assign the struct irq_chip structure to the struct gpio_irq_chip
structure. What would be the equivalent for gpio-regmap?

William Breathitt Gray


Attachments:
(No filename) (809.00 B)
signature.asc (235.00 B)
Download all attachments