Skip to contentSkip to conversation

Migrate i8255 GPIO drivers to regmap API

PATCH Superseded William Breathitt Gray 5 participants 27 messages Nov 13, 2022 – Nov 22, 2022

Subsystems (8)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v2 cover Migrate i8255 GPIO drivers to regmap API

Changes in v2:
- Leveraged gpio_regmap to support GPIO functionality in 104-idi-48 driver and i8255 library
- Leveraged regmap_irq to support IRQ functionality in 104-idi-48 and 104-dio-48e drivers
- Removed i8255 dependency from 104-idi-48; simpler to just use gpio_regmap directly in this case
- Adjust gpio_regmap to always set gpio_chip get_direction
- Introduce handle_mask_sync() callback to regmap_irq API
- i8255 library is simplified to a registration function, a configuration structure, and a helper macro

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. The 104-dio-48e and gpio-mm modules depend on the i8255 library and are thus updated accordingly.

The 104-IDI-48 is hardwired as an input-only device. Because the i8255 control registers are not exposed on the 104-IDI-48, the i8255 library doesn't provide much benefit here. In this case it's simpler to utilize the gpio_regmap API directly, so this patch series does such and removes the i8255 library dependency from the 104-idi-48 module.

The first patch in this series adjusts gpio_regmap to always set gpio_chip get_direction. This patch is larger independent of the rest of the patches in the series and can be picked up separately if desired. I'm including it here because it allows the input-only 104-idi-48 driver to continue reporting offset directions after migrating to gpio_regmap.

A handle_mask_sync() callback is introduced for the regmap_irq API. This is used by the 104-dio-48e driver to handle its enable/disable interrupt functionality. The 104-DIO-48E has a single register to handle enabling/disabling interrupts: a write of any value to this register enables interrupts, while any read disables interrupts.

By leveraging the gpio_regmap API, the i8255 library is reduced to simply a devm_i8255_regmap_register() function, a configuration structure struct i8255_regmap_config, and a helper macro i8255_volatile_regmap_range() provided to simplify volatile PPI register hinting for the regmap.

The regmap_irq API is leveraged by the 104-idi-48 and 104-dio-48e modules to support their IRQ functionality. Do their respective regmap configurations need use_hwlock set to true in this case, or is adequate locking already handled by the regmap_irq API?

William Breathitt Gray (4):
gpio: regmap: Always set gpio_chip get_direction
regmap-irq: Add handle_mask_sync() callback
gpio: 104-idi-48: Migrate to regmap API
gpio: i8255: Migrate to regmap API

 drivers/base/regmap/regmap-irq.c |  44 +++-
 drivers/gpio/Kconfig             |   5 +-
 drivers/gpio/gpio-104-dio-48e.c  | 397 ++++++++++------------------
 drivers/gpio/gpio-104-idi-48.c   | 329 ++++++++----------------
 drivers/gpio/gpio-gpio-mm.c      | 151 ++---------
 drivers/gpio/gpio-i8255.c        | 429 ++++++++++---------------------
 drivers/gpio/gpio-i8255.h        |  80 +++---
 drivers/gpio/gpio-regmap.c       |   7 +-
 include/linux/regmap.h           |   5 +
 9 files changed, 483 insertions(+), 964 deletions(-)

rewrite drivers/gpio/gpio-i8255.c (89%)
rewrite drivers/gpio/gpio-i8255.h (89%)

base-commit: 8dab99c9eab3162bfb4326c35579a3388dbf68f2

Signature · 1 line
2.38.1
#1 lore raw

PATCH v2 1/4 gpio: regmap: Always set gpio_chip get_direction

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

---
 drivers/gpio/gpio-regmap.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpio/gpio-regmap.c +6 -1
index 6383136cbe59..f907c9c19fce 100644
@@ -111,6 +111,11 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip,
 	unsigned int base, val, reg, mask;
 	int invert, ret;
 
+	if (gpio->reg_dat_base && !gpio->reg_set_base)
+		return GPIO_LINE_DIRECTION_IN;
+	if (gpio->reg_set_base && !gpio->reg_dat_base)
+		return GPIO_LINE_DIRECTION_OUT;
+
 	if (gpio->reg_dir_out_base) {
 		base = gpio_regmap_addr(gpio->reg_dir_out_base);
 		invert = 0;
@@ -265,8 +270,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
 	else if (gpio->reg_set_base)
 		chip->set = gpio_regmap_set;
 
+	chip->get_direction = gpio_regmap_get_direction;
 	if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) {
-		chip->get_direction = gpio_regmap_get_direction;
 		chip->direction_input = gpio_regmap_direction_input;
 		chip->direction_output = gpio_regmap_direction_output;
 	}
Signature · 1 line
2.38.1
Reviewed-by on v2 1/4
#2 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

Quoted 5 lines · William Breathitt Gray

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

Seems legit to me. Have you checked if we have any gpio-regmap drivers that have something like this in their configuration already? In such cases we need to be sure they behave as expected.

From the code perspective:

Quoted 34 lines
---
 drivers/gpio/gpio-regmap.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpio/gpio-regmap.c +6 -1
index 6383136cbe59..f907c9c19fce 100644
@@ -111,6 +111,11 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip,
 	unsigned int base, val, reg, mask;
 	int invert, ret;
 
+	if (gpio->reg_dat_base && !gpio->reg_set_base)
+		return GPIO_LINE_DIRECTION_IN;
+	if (gpio->reg_set_base && !gpio->reg_dat_base)
+		return GPIO_LINE_DIRECTION_OUT;
+
 	if (gpio->reg_dir_out_base) {
 		base = gpio_regmap_addr(gpio->reg_dir_out_base);
 		invert = 0;
@@ -265,8 +270,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
 	else if (gpio->reg_set_base)
 		chip->set = gpio_regmap_set;
 
+	chip->get_direction = gpio_regmap_get_direction;
 	if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) {
-		chip->get_direction = gpio_regmap_get_direction;
 		chip->direction_input = gpio_regmap_direction_input;
 		chip->direction_output = gpio_regmap_direction_output;
 	}
Signature · 1 line
2.38.1
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#3 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

Quoted 7 lines · Andy Shevchenko
Quoted 5 lines · William Breathitt Gray

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

Quoted 6 lines

Seems legit to me. Have you checked if we have any gpio-regmap drivers that have something like this in their configuration already? In such cases we need to be sure they behave as expected.

From the code perspective:

I see gpio-sl28cpld has two device types SL28CPLD_GPO (output-only) and SL28CPLD_GPI (input-only); gpio-tn48m similarly has two device types TN48M_GPO (output-only) and TN48M_GPI (input-only). It doesn't look like the change in this patch will cause problems for them, but I'll let Michael Walle and Robert Marko comment if they see issues here.

William Breathitt Gray

Quoted 40 lines
Quoted 34 lines
---
 drivers/gpio/gpio-regmap.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpio/gpio-regmap.c +6 -1
index 6383136cbe59..f907c9c19fce 100644
@@ -111,6 +111,11 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip,
 	unsigned int base, val, reg, mask;
 	int invert, ret;
 
+	if (gpio->reg_dat_base && !gpio->reg_set_base)
+		return GPIO_LINE_DIRECTION_IN;
+	if (gpio->reg_set_base && !gpio->reg_dat_base)
+		return GPIO_LINE_DIRECTION_OUT;
+
 	if (gpio->reg_dir_out_base) {
 		base = gpio_regmap_addr(gpio->reg_dir_out_base);
 		invert = 0;
@@ -265,8 +270,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
 	else if (gpio->reg_set_base)
 		chip->set = gpio_regmap_set;
 
+	chip->get_direction = gpio_regmap_get_direction;
 	if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) {
-		chip->get_direction = gpio_regmap_get_direction;
 		chip->direction_input = gpio_regmap_direction_input;
 		chip->direction_output = gpio_regmap_direction_output;
 	}
Signature · 1 line
2.38.1
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#4 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

Quoted 13 lines · William Breathitt Gray
Quoted 11 lines · Andy Shevchenko
Quoted 5 lines · William Breathitt Gray

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

Seems legit to me. Have you checked if we have any gpio-regmap drivers that have something like this in their configuration already? In such cases we need to be sure they behave as expected.

Quoted 8 lines
Quoted 2 lines

From the code perspective:

I see gpio-sl28cpld has two device types SL28CPLD_GPO (output-only) and SL28CPLD_GPI (input-only); gpio-tn48m similarly has two device types TN48M_GPO (output-only) and TN48M_GPI (input-only). It doesn't look like the change in this patch will cause problems for them, but I'll let Michael Walle and Robert Marko comment if they see issues here.

Hi, sorry for the late reply.
This should work fine for TN48M.

Regards,
Robert

Quoted 43 lines

William Breathitt Gray

Quoted 40 lines
Quoted 32 lines
---
 drivers/gpio/gpio-regmap.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpio/gpio-regmap.c +6 -2
index 6383136cbe59..f907c9c19fce 100644
@@ -111,6 +111,11 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip,
    unsigned int base, val, reg, mask;
    int invert, ret;
 
+   if (gpio->reg_dat_base && !gpio->reg_set_base)
+           return GPIO_LINE_DIRECTION_IN;
+   if (gpio->reg_set_base && !gpio->reg_dat_base)
+           return GPIO_LINE_DIRECTION_OUT;
+
    if (gpio->reg_dir_out_base) {
            base = gpio_regmap_addr(gpio->reg_dir_out_base);
            invert = 0;
@@ -265,8 +270,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
    else if (gpio->reg_set_base)
            chip->set = gpio_regmap_set;
 
+   chip->get_direction = gpio_regmap_get_direction;
    if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) {
-           chip->get_direction = gpio_regmap_get_direction;
            chip->direction_input = gpio_regmap_direction_input;
            chip->direction_output = gpio_regmap_direction_output;
    }
--
Quoted 2 lines

2.38.1

--
With Best Regards,
Andy Shevchenko

Signature · 7 lines
Robert Marko
Staff Embedded Linux Engineer
Sartura Ltd.
Lendavska ulica 16a
10000 Zagreb, Croatia
Email: [email protected]
Web: www.sartura.hr
Acked-by
#5 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

In reply to William Breathitt Gray

Am 2022-11-13 14:21, schrieb William Breathitt Gray:

Quoted 12 lines · Andy Shevchenko
Quoted 11 lines · William Breathitt Gray
Quoted 5 lines

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

Seems legit to me. Have you checked if we have any gpio-regmap drivers that have something like this in their configuration already? In such cases we need to be sure they behave as expected.

Quoted 8 lines
Quoted 2 lines

From the code perspective:

I see gpio-sl28cpld has two device types SL28CPLD_GPO (output-only) and SL28CPLD_GPI (input-only); gpio-tn48m similarly has two device types TN48M_GPO (output-only) and TN48M_GPI (input-only). It doesn't look like the change in this patch will cause problems for them, but I'll let Michael Walle and Robert Marko comment if they see issues here.

For the sl28cpld driver this shouldn't be a problem. So for that

But back when I wrote gpio-regmap the bgpio served as a blue print. There is the same handling. If you look at gpiolib-sysfs.c there is a comment about the direction property:

* MAY BE OMITTED if kernel won't allow direction changes

So from a gpiolib/sysfs POV I'm not sure about this change. Does get_direction == NULL means setting the direction isn't possible? OTHO there is a fat "MAY" :)

Which brings me to the question of "why this change?". The commit message doesn't mention it. Just out of curiosity.

-michael

#6 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

Quoted 32 lines · Michael Walle

Am 2022-11-13 14:21, schrieb William Breathitt Gray:

Quoted 15 lines · Andy Shevchenko
Quoted 14 lines
Quoted 5 lines · William Breathitt Gray

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

Seems legit to me. Have you checked if we have any gpio-regmap drivers that
have something like this in their configuration already? In such cases we need
to be sure they behave as expected.

Quoted 8 lines
Quoted 2 lines

From the code perspective:

I see gpio-sl28cpld has two device types SL28CPLD_GPO (output-only) and SL28CPLD_GPI (input-only); gpio-tn48m similarly has two device types TN48M_GPO (output-only) and TN48M_GPI (input-only). It doesn't look like the change in this patch will cause problems for them, but I'll let Michael Walle and Robert Marko comment if they see issues here.

For the sl28cpld driver this shouldn't be a problem. So for that

But back when I wrote gpio-regmap the bgpio served as a blue print. There is the same handling. If you look at gpiolib-sysfs.c there is a comment about the direction property:

Quoted 8 lines

* MAY BE OMITTED if kernel won't allow direction changes

So from a gpiolib/sysfs POV I'm not sure about this change. Does get_direction == NULL means setting the direction isn't possible? OTHO there is a fat "MAY" :)

Which brings me to the question of "why this change?". The commit message doesn't mention it. Just out of curiosity.

Sysfs shouldn't be considered nowadays as anything but deprecated and not-to-use interface. Hence, I don't care what it tells there.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#7 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

In reply to Michael Walle
Quoted 34 lines · Michael Walle

Am 2022-11-13 14:21, schrieb William Breathitt Gray:

Quoted 15 lines · Andy Shevchenko
Quoted 14 lines
Quoted 5 lines · William Breathitt Gray

If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration.

Seems legit to me. Have you checked if we have any gpio-regmap drivers that
have something like this in their configuration already? In such cases we need
to be sure they behave as expected.

Quoted 8 lines
Quoted 2 lines

From the code perspective:

I see gpio-sl28cpld has two device types SL28CPLD_GPO (output-only) and SL28CPLD_GPI (input-only); gpio-tn48m similarly has two device types TN48M_GPO (output-only) and TN48M_GPI (input-only). It doesn't look like the change in this patch will cause problems for them, but I'll let Michael Walle and Robert Marko comment if they see issues here.

For the sl28cpld driver this shouldn't be a problem. So for that

But back when I wrote gpio-regmap the bgpio served as a blue print. There is the same handling. If you look at gpiolib-sysfs.c there is a comment about the direction property:

* MAY BE OMITTED if kernel won't allow direction changes

Quoted 8 lines

So from a gpiolib/sysfs POV I'm not sure about this change. Does get_direction == NULL means setting the direction isn't possible? OTHO there is a fat "MAY" :)

Which brings me to the question of "why this change?". The commit message doesn't mention it. Just out of curiosity.

-michael

Currently, the 104-idi-48 module implements a get_direction() callback that is executed in situations such as gpiod_get_direction() which aren't necessarily related to sysfs. In this patch series, the 104-idi-48 module is migrated to the gpio_regmap API, but loses this get_direction() support because it's an input-only configuration. The purpose of this patch is to prevent that regression by supporting get_direction() for input-only/output-only configurations.

William Breathitt Gray

#8 lore raw

Re: [PATCH v2 1/4] gpio: regmap: Always set gpio_chip get_direction

Am 2022-11-17 15:22, schrieb William Breathitt Gray:

Quoted 5 lines
Quoted 4 lines

Which brings me to the question of "why this change?". The commit message doesn't mention it. Just out of curiosity.

-michael

Quoted 7 lines

Currently, the 104-idi-48 module implements a get_direction() callback that is executed in situations such as gpiod_get_direction() which aren't necessarily related to sysfs. In this patch series, the 104-idi-48 module is migrated to the gpio_regmap API, but loses this get_direction() support because it's an input-only configuration. The purpose of this patch is to prevent that regression by supporting get_direction() for input-only/output-only configurations.

I see, thanks for the explanation.

As said before, I'm fine with the change and apparently we don't care for sysfs changes ;)

-michael

#9 lore raw

PATCH v2 2/4 regmap-irq: Add handle_mask_sync() callback

In reply to William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

---
 drivers/base/regmap/regmap-irq.c | 44 ++++++++++++++++++++++----------
 include/linux/regmap.h           |  5 ++++
 2 files changed, 36 insertions(+), 13 deletions(-)
drivers/base/regmap/regmap-irq.c +31 -13
index 4ef9488d05cd..968681fa8d09 100644
@@ -115,12 +115,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
 	 */
 	for (i = 0; i < d->chip->num_regs; i++) {
 		if (d->mask_base) {
-			reg = d->get_irq_reg(d, d->mask_base, i);
-			ret = regmap_update_bits(d->map, reg,
-					d->mask_buf_def[i], d->mask_buf[i]);
-			if (ret)
-				dev_err(d->map->dev, "Failed to sync masks in %x\n",
-					reg);
+			if (d->chip->handle_mask_sync)
+				d->chip->handle_mask_sync(d->map, i,
+							  d->mask_buf_def[i],
+							  d->mask_buf[i],
+							  d->chip->irq_drv_data);
+			else {
+				reg = d->get_irq_reg(d, d->mask_base, i);
+				ret = regmap_update_bits(d->map, reg,
+						d->mask_buf_def[i],
+						d->mask_buf[i]);
+				if (ret)
+					dev_err(d->map->dev, "Failed to sync masks in %x\n",
+						reg);
+			}
 		}
 
 		if (d->unmask_base) {
@@ -917,13 +925,23 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
 		d->mask_buf[i] = d->mask_buf_def[i];
 
 		if (d->mask_base) {
-			reg = d->get_irq_reg(d, d->mask_base, i);
-			ret = regmap_update_bits(d->map, reg,
-					d->mask_buf_def[i], d->mask_buf[i]);
-			if (ret) {
-				dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
-					reg, ret);
-				goto err_alloc;
+			if (chip->handle_mask_sync) {
+				ret = chip->handle_mask_sync(d->map, i,
+							     d->mask_buf_def[i],
+							     d->mask_buf[i],
+							     chip->irq_drv_data);
+				if (ret)
+					goto err_alloc;
+			} else {
+				reg = d->get_irq_reg(d, d->mask_base, i);
+				ret = regmap_update_bits(d->map, reg,
+						d->mask_buf_def[i],
+						d->mask_buf[i]);
+				if (ret) {
+					dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
+						reg, ret);
+					goto err_alloc;
+				}
 			}
 		}
 
include/linux/regmap.h +5 -0
index ca3434dca3a0..62ede456af99 100644
@@ -1542,6 +1542,8 @@ struct regmap_irq_chip_data;
  *		     before regmap_irq_handler process the interrupts.
  * @handle_post_irq: Driver specific callback to handle interrupt from device
  *		     after handling the interrupts in regmap_irq_handler().
+ * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index will be
+ *		      in the range [0, num_regs[
  * @set_type_virt:   Driver specific callback to extend regmap_irq_set_type()
  *		     and configure virt regs. Deprecated, use @set_type_config
  *		     callback and config registers instead.
@@ -1603,6 +1605,9 @@ struct regmap_irq_chip {
 
 	int (*handle_pre_irq)(void *irq_drv_data);
 	int (*handle_post_irq)(void *irq_drv_data);
+	int (*handle_mask_sync)(struct regmap *map, int index,
+				unsigned int mask_buf_def,
+				unsigned int mask_buf, void *irq_drv_data);
 	int (*set_type_virt)(unsigned int **buf, unsigned int type,
 			     unsigned long hwirq, int reg);
 	int (*set_type_config)(unsigned int **buf, unsigned int type,
Signature · 1 line
2.38.1
#10 lore raw

Re: [PATCH v2 2/4] regmap-irq: Add handle_mask_sync() callback

Quoted 4 lines · William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

...

Quoted 2 lines

+ * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index will be
+ * in the range [0, num_regs[

Not sure if it's a typo ([ vs. ]), but if you want to say "not including the last", use mathematical notation, i.e. "[0, num_regs)".

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#11 lore raw

Re: [PATCH v2 2/4] regmap-irq: Add handle_mask_sync() callback

Quoted 6 lines · Andy Shevchenko
Quoted 4 lines · William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

Quoted 7 lines

...

Quoted 2 lines

+ * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index will be
+ * in the range [0, num_regs[

Not sure if it's a typo ([ vs. ]), but if you want to say "not including the last", use mathematical notation, i.e. "[0, num_regs)".

I was following the convention used in the @get_irq_reg description, but I agree that mathematical notation would be much clearer.

William Breathitt Gray

#12 lore raw

Re: [PATCH v2 2/4] regmap-irq: Add handle_mask_sync() callback

Quoted 6 lines · William Breathitt Gray
Quoted 5 lines · Andy Shevchenko
Quoted 4 lines · William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

...

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

+ * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index will be
+ * in the range [0, num_regs[

Not sure if it's a typo ([ vs. ]), but if you want to say "not including the last", use mathematical notation, i.e. "[0, num_regs)".

I was following the convention used in the @get_irq_reg description, but I agree that mathematical notation would be much clearer.

Ah, maybe cleaning up the rest then?

Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#13 lore raw

Re: [PATCH v2 2/4] regmap-irq: Add handle_mask_sync() callback

In reply to William Breathitt Gray
Quoted 4 lines · William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

Can you provide examples of something that would make sense to open code in a driver rather than factoring out? It looks like this has been added due to one of the devices you're looking at for some reason disabling it's upstream interrupt when all of the downstream interrupts are masked, while weird that doesn't seem especally device specific.

#14 lore raw

Re: [PATCH v2 2/4] regmap-irq: Add handle_mask_sync() callback

Quoted 7 lines · Mark Brown
Quoted 4 lines · William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

Quoted 6 lines

Can you provide examples of something that would make sense to open code in a driver rather than factoring out? It looks like this has been added due to one of the devices you're looking at for some reason disabling it's upstream interrupt when all of the downstream interrupts are masked, while weird that doesn't seem especally device specific.

Sure, I actually intend to use this callback for the 104-idi-48 module as well in the v3 submission so I'll describe that situations well.

For the 104-dio-48e we have the following:

Base Address +B (Write): Enable Interrupt
Base Address +B (Read): Disable Interrupt
Base Address +F (Read/Write): Clear Interrupt

So for 104-dio-48e, any write to 0xB will enable interrupts, while any read will disable interrupts; interrupts are with either a read or any write to 0xF. There's no status register either so software just has to assume that if an interrupt is raised then it was for the 104-dio-48e device.

For the 104-idi-48, we do get a status register and some basic masking but it's broken down by banks rather than individual GPIO; there are six 8-bit banks (Port 0 Low Byte, Port 0 Mid Byte, Port 0 High Byte, Port 1 Low Byte, Port 1 Mid Byte, Port 1 High Byte):

Base Address + 0 (Read/Write): Port 0 Low Byte Base Address + 1 (Read/Write): Port 0 Mid Byte Base Address + 2 (Read/Write): Port 0 High Byte Base Address + 3: N/A
Base Address + 4 (Read/Write): Port 1 Low Byte Base Address + 5 (Read/Write): Port 1 Mid Byte Base Address + 6 (Read/Write): Port 1 High Byte Base Address + 7 (Read): IRQ Status Register/IRQ Clear
Bit 0-5: Respective Bank IRQ Statuses
Bit 6: IRQ Status (Active Low)
Bit 7: IRQ Enable Status
Base Address + 7 (Write): IRQ Enable/Disable
Bit 0-5: Respective Bank IRQ Enable/Disable

In this case, masking a bank will mask all 8 GPIO within that bank; so ideally I want a way to only mask a bank when all GPIO are masked, and unmasking when at least one is unmasked.

Are there existing ways to support these kinds of configuration in regmap_irq?

William Breathitt Gray

#15 lore raw

Re: [PATCH v2 2/4] regmap-irq: Add handle_mask_sync() callback

Quoted 49 lines · William Breathitt Gray
Quoted 7 lines · Mark Brown
Quoted 4 lines · William Breathitt Gray

Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback.

Quoted 6 lines

Can you provide examples of something that would make sense to open code in a driver rather than factoring out? It looks like this has been added due to one of the devices you're looking at for some reason disabling it's upstream interrupt when all of the downstream interrupts are masked, while weird that doesn't seem especally device specific.

Sure, I actually intend to use this callback for the 104-idi-48 module as well in the v3 submission so I'll describe that situations well.

For the 104-dio-48e we have the following:

Base Address +B (Write): Enable Interrupt
Base Address +B (Read): Disable Interrupt
Base Address +F (Read/Write): Clear Interrupt

So for 104-dio-48e, any write to 0xB will enable interrupts, while any read will disable interrupts; interrupts are with either a read or any write to 0xF. There's no status register either so software just has to assume that if an interrupt is raised then it was for the 104-dio-48e device.

For the 104-idi-48, we do get a status register and some basic masking but it's broken down by banks rather than individual GPIO; there are six 8-bit banks (Port 0 Low Byte, Port 0 Mid Byte, Port 0 High Byte, Port 1 Low Byte, Port 1 Mid Byte, Port 1 High Byte):

Base Address + 0 (Read/Write): Port 0 Low Byte Base Address + 1 (Read/Write): Port 0 Mid Byte Base Address + 2 (Read/Write): Port 0 High Byte Base Address + 3: N/A
Base Address + 4 (Read/Write): Port 1 Low Byte Base Address + 5 (Read/Write): Port 1 Mid Byte Base Address + 6 (Read/Write): Port 1 High Byte Base Address + 7 (Read): IRQ Status Register/IRQ Clear
Bit 0-5: Respective Bank IRQ Statuses
Bit 6: IRQ Status (Active Low)
Bit 7: IRQ Enable Status
Base Address + 7 (Write): IRQ Enable/Disable
Bit 0-5: Respective Bank IRQ Enable/Disable

Quoted 8 lines

In this case, masking a bank will mask all 8 GPIO within that bank; so ideally I want a way to only mask a bank when all GPIO are masked, and unmasking when at least one is unmasked.

Are there existing ways to support these kinds of configuration in regmap_irq?

William Breathitt Gray

After trying to implement a handle_mask_sync() callback for the 104-idi-48 I discovered that it's not so straight-forward a task. The mask_buf parameter is unsigned int so I can only represent 32 GPIO at a time.

I could set the struct regmap_irq_chip num_regs member to '2' to increase the number of mask_buf elements, but that creates side effects because the regmap-irq API believes there there are more registers than the device actually has.

For now with the 104-idi-48 module utilizing the regmap-irq API, we'll have to leave it where masking one GPIO line masks the entire bank, and vice versa for unmasking.

William Breathitt Gray

#16 lore raw

PATCH v2 3/4 gpio: 104-idi-48: Migrate to regmap API

In reply to William Breathitt Gray

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. Despite the underlying interface being based on i8255, it is simpler to use the gpio_regmap API directly because the 104-IDI-48 device features only input signals. Therefore, the dependence on the i8255 GPIO library is removed in this patch.

---
 drivers/gpio/Kconfig           |   3 +-
 drivers/gpio/gpio-104-idi-48.c | 329 ++++++++++-----------------------
 2 files changed, 104 insertions(+), 228 deletions(-)
drivers/gpio/Kconfig +2 -1
index ec7cfd4f52b1..a9852782566d 100644
@@ -871,7 +871,8 @@ config GPIO_104_IDI_48
 	depends on PC104
 	select ISA_BUS_API
 	select GPIOLIB_IRQCHIP
-	select GPIO_I8255
+	select REGMAP_IRQ
+	select GPIO_REGMAP
 	help
 	  Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
 	  104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for
drivers/gpio/gpio-104-idi-48.c +102 -227

385 lines not on this page · raw message

Signature · 1 line
2.38.1
#17 lore raw

PATCH v2 4/4 gpio: i8255: Migrate to regmap API

In reply to William Breathitt Gray

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. The 104-dio-48e and gpio-mm modules depend on the i8255 library and are thus updated accordingly.

By leveraging the gpio_regmap API, the i8255 library is reduced to simply a devm_i8255_regmap_register() function, a configuration structure struct i8255_regmap_config, and a helper macro i8255_volatile_regmap_range() provided to simplify volatile PPI register hinting for the regmap.

---
 drivers/gpio/Kconfig            |   2 +
 drivers/gpio/gpio-104-dio-48e.c | 397 ++++++++++-------------------
 drivers/gpio/gpio-gpio-mm.c     | 151 +++--------
 drivers/gpio/gpio-i8255.c       | 429 +++++++++++---------------------
 drivers/gpio/gpio-i8255.h       |  80 +++---
 5 files changed, 337 insertions(+), 722 deletions(-)

rewrite drivers/gpio/gpio-i8255.c (89%)
rewrite drivers/gpio/gpio-i8255.h (89%)

drivers/gpio/Kconfig +2 -0
index a9852782566d..7e1c89c4cb17 100644
@@ -831,6 +831,7 @@ menu "Port-mapped I/O GPIO drivers"
 
 config GPIO_I8255
 	tristate
+	select GPIO_REGMAP
 	help
 	  Enables support for the i8255 interface library functions. The i8255
 	  interface library provides functions to facilitate communication with
@@ -846,6 +847,7 @@ config GPIO_104_DIO_48E
 	depends on PC104
 	select ISA_BUS_API
 	select GPIOLIB_IRQCHIP
+	select REGMAP_IRQ
 	select GPIO_I8255
 	help
 	  Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
drivers/gpio/gpio-104-dio-48e.c +131 -266

454 lines not on this page · raw message

drivers/gpio/gpio-gpio-mm.c +28 -123

188 lines not on this page · raw message

drivers/gpio/gpio-i8255.c +142 -287

429 lines not on this page · raw message

drivers/gpio/gpio-i8255.h +34 -46

80 lines not on this page · raw message

Signature · 1 line
2.38.1
#18 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 5 lines · William Breathitt Gray

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. The 104-dio-48e and gpio-mm modules depend on the i8255 library and are thus updated accordingly.

Quoted 7 lines

By leveraging the gpio_regmap API, the i8255 library is reduced to simply a devm_i8255_regmap_register() function, a configuration structure struct i8255_regmap_config, and a helper macro i8255_volatile_regmap_range() provided to simplify volatile PPI register hinting for the regmap.

Cc Andy Shevchenko <[email protected]>

Suggested-by?
(I'm not insisting, just consider if it's appropriate to use here or in the
other patches)

Quoted 7 lines
---
 drivers/gpio/Kconfig            |   2 +
 drivers/gpio/gpio-104-dio-48e.c | 397 ++++++++++-------------------
 drivers/gpio/gpio-gpio-mm.c     | 151 +++--------
 drivers/gpio/gpio-i8255.c       | 429 +++++++++++---------------------
 drivers/gpio/gpio-i8255.h       |  80 +++---

Can we actually split this to a few steps:
- providing gpio-i8255-regmap
- providing gpio-mm-regmap
- converting the driver
- removing not used modules (one by one)
?

In this case if any regression somewhere appears, we can always perform a (semi-)revert for a certain driver.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#19 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 12 lines · Andy Shevchenko
Quoted 10 lines · William Breathitt Gray

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. The 104-dio-48e and gpio-mm modules depend on the i8255 library and are thus updated accordingly.

By leveraging the gpio_regmap API, the i8255 library is reduced to simply a devm_i8255_regmap_register() function, a configuration structure struct i8255_regmap_config, and a helper macro i8255_volatile_regmap_range() provided to simplify volatile PPI register hinting for the regmap.

Quoted 5 lines
Quoted 1 line
Cc Andy Shevchenko <[email protected]>

Suggested-by?
(I'm not insisting, just consider if it's appropriate to use here or in the
other patches)

No problem, I'll make sure your Suggested-by lines are properly added for the patches. ;-)

Quoted 15 lines
Quoted 7 lines
---
 drivers/gpio/Kconfig            |   2 +
 drivers/gpio/gpio-104-dio-48e.c | 397 ++++++++++-------------------
 drivers/gpio/gpio-gpio-mm.c     | 151 +++--------
 drivers/gpio/gpio-i8255.c       | 429 +++++++++++---------------------
 drivers/gpio/gpio-i8255.h       |  80 +++---

Can we actually split this to a few steps:
- providing gpio-i8255-regmap
- providing gpio-mm-regmap
- converting the driver
- removing not used modules (one by one)
?

Quoted 2 lines

In this case if any regression somewhere appears, we can always perform a (semi-)revert for a certain driver.

Sure, I can split the regmap_irq migration for 104-dio-48e into a separate precursor patch to reduce the amount of changes we see here and provide a revert path for these IRQ changes. I can do a similar change for 104-idi-48 as well.

The rest of the changes for 104-dio-48 and gpio-mm are essentially just the regmap configurations, so the patch will be largely identical even if we migrate gpio-i8255 to regmap API first before migrating again to the gpio_regmap in a second patch.

I believe the reason the changes look ugly in this patch is because the large number of lines deleted is confusing the match heuristic for diff so the changes aren't lining up nicely into distinct deletion/creation blocks. I can play around with the git diff "--break-rewrites" option to get it to produce a nicer diff; I think gpio-mm looks much easier to review as a rewrite rather than inline diffs [0].

[0] https://gitlab.com/vilhelmgray/gpio/-/raw/61327a67cc308af413471a69a4810b2785e53e8e/drivers/gpio/gpio-gpio-mm.c

William Breathitt Gray

#20 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 23 lines · William Breathitt Gray
Quoted 14 lines · Andy Shevchenko
Quoted 5 lines · William Breathitt Gray
 drivers/gpio/Kconfig            |   2 +
 drivers/gpio/gpio-104-dio-48e.c | 397 ++++++++++-------------------
 drivers/gpio/gpio-gpio-mm.c     | 151 +++--------
 drivers/gpio/gpio-i8255.c       | 429 +++++++++++---------------------
 drivers/gpio/gpio-i8255.h       |  80 +++---

Can we actually split this to a few steps:
- providing gpio-i8255-regmap
- providing gpio-mm-regmap
- converting the driver
- removing not used modules (one by one)
?

Quoted 2 lines

In this case if any regression somewhere appears, we can always perform a (semi-)revert for a certain driver.

Sure, I can split the regmap_irq migration for 104-dio-48e into a separate precursor patch to reduce the amount of changes we see here and provide a revert path for these IRQ changes. I can do a similar change for 104-idi-48 as well.

Quoted 4 lines

The rest of the changes for 104-dio-48 and gpio-mm are essentially just the regmap configurations, so the patch will be largely identical even if we migrate gpio-i8255 to regmap API first before migrating again to the gpio_regmap in a second patch.

Sorry, I realize now that you meant to split the i8255 gpio_regmap additions to their own patch, perform the driver migrations in the own respective patches, and then finally remove the dangling unused i8255 functions and structures. Yes I think that would make for a cleaner patch series so I'll split it up that way.

William Breathitt Gray

#21 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 3 lines · William Breathitt Gray
Quoted 2 lines · William Breathitt Gray
Quoted 1 line · Andy Shevchenko

On Thu, Nov 10, 2022 at 08:55:53PM -0500, William Breathitt Gray wrote:

...

Quoted 25 lines
Quoted 20 lines
Quoted 12 lines
Quoted 4 lines
 drivers/gpio/gpio-104-dio-48e.c | 397 ++++++++++-------------------
 drivers/gpio/gpio-gpio-mm.c     | 151 +++--------
 drivers/gpio/gpio-i8255.c       | 429 +++++++++++---------------------
 drivers/gpio/gpio-i8255.h       |  80 +++---

Can we actually split this to a few steps:
- providing gpio-i8255-regmap
- providing gpio-mm-regmap
- converting the driver
- removing not used modules (one by one)
?

Quoted 2 lines

In this case if any regression somewhere appears, we can always perform a (semi-)revert for a certain driver.

Sure, I can split the regmap_irq migration for 104-dio-48e into a separate precursor patch to reduce the amount of changes we see here and provide a revert path for these IRQ changes. I can do a similar change for 104-idi-48 as well.

Quoted 4 lines

The rest of the changes for 104-dio-48 and gpio-mm are essentially just the regmap configurations, so the patch will be largely identical even if we migrate gpio-i8255 to regmap API first before migrating again to the gpio_regmap in a second patch.

Quoted 5 lines

Sorry, I realize now that you meant to split the i8255 gpio_regmap additions to their own patch, perform the driver migrations in the own respective patches, and then finally remove the dangling unused i8255 functions and structures. Yes I think that would make for a cleaner patch series so I'll split it up that way.

Yes, that's what I meant. Thank you!

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#22 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

In reply to William Breathitt Gray

Hi,

Am 2022-11-11 02:55, schrieb William Breathitt Gray:

drivers/gpio/gpio-gpio-mm.c static int gpiomm_probe(struct device *dev, unsigned int id) · line 80

Quoted 4 lines

+ config.map = devm_regmap_init_mmio(dev, regs,
&gpiomm_regmap_config);

drivers/gpio/gpio-gpio-mm.c +2 -0
+    if (IS_ERR(config.map))
+        return PTR_ERR(config.map);

I've just skimmed over your patch and noticed you're using an mmio regmap. Please note that for now, gpio-regmap unconditionally sets .can_sleep to true in the gpiochip [1]. So the users would need to use the _cansleep() variants. See a proposal below.

Quoted 14 lines
drivers/gpio/gpio-i8255.c +14 -0
+int devm_i8255_regmap_register(struct device *const dev,
+			       const struct i8255_regmap_config *const config)
+{
+	struct gpio_regmap_config gpio_config = {0};
+	unsigned long i;
+	int err;
+
+	if (!config->parent)
+		return -EINVAL;
+
+	if (!config->map)
+		return -EINVAL;
+
+	if (!config->num_ppi)

drivers/gpio/gpio-i8255.c line 126

Quoted 10 lines
drivers/gpio/gpio-i8255.c +10 -0
+		return -EINVAL;
+
+	for (i = 0; i < config->num_ppi; i++) {
+		err = i8255_ppi_init(config->map, i * 4);
+		if (err)
+			return err;
+	}
+
+	gpio_config.parent = config->parent;
+	gpio_config.regmap = config->map;

I'd propose to add a new config flag to indicate that accesses to the device will be fast:

gpio_config.regmap_has_fast_io = true;

which will then set gpio->can_sleep = false.

-michael

drivers/gpio/gpio-i8255.c line 138

Quoted 13 lines
drivers/gpio/gpio-i8255.c +5 -0
+	gpio_config.ngpio = I8255_NGPIO * config->num_ppi;
+	gpio_config.names = config->names;
+	gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(I8255_REG_DAT_BASE);
+	gpio_config.reg_set_base = GPIO_REGMAP_ADDR(I8255_REG_DAT_BASE);
+	gpio_config.reg_dir_in_base = 

GPIO_REGMAP_ADDR(I8255_REG_DIR_IN_BASE);

drivers/gpio/gpio-i8255.c +7 -0
+	gpio_config.ngpio_per_reg = I8255_NGPIO_PER_REG;
+	gpio_config.irq_domain = config->domain;
+	gpio_config.reg_mask_xlate = i8255_reg_mask_xlate;
+
+	return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
+}
+EXPORT_SYMBOL_NS_GPL(devm_i8255_regmap_register, I8255);

[1] https://elixir.bootlin.com/linux/v6.1-rc5/source/drivers/gpio/gpio-regmap.c#L260

maintainer
#23 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 11 lines · Michael Walle

Am 2022-11-11 02:55, schrieb William Breathitt Gray:

drivers/gpio/gpio-i8255.c line 126

Quoted 2 lines
drivers/gpio/gpio-i8255.c +2 -0
+	gpio_config.parent = config->parent;
+	gpio_config.regmap = config->map;

I'd propose to add a new config flag to indicate that accesses to the device will be fast:

gpio_config.regmap_has_fast_io = true;

which will then set gpio->can_sleep = false.

It's probably useful to provide a query function in the regmap API for generic regmap users like this.

#24 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Am 2022-11-17 17:21, schrieb Mark Brown:

Quoted 9 lines · Michael Walle
Quoted 7 lines

Am 2022-11-11 02:55, schrieb William Breathitt Gray:

drivers/gpio/gpio-i8255.c line 126

Quoted 2 lines
drivers/gpio/gpio-i8255.c +2 -0
+	gpio_config.parent = config->parent;
+	gpio_config.regmap = config->map;

I'd propose to add a new config flag to indicate that accesses to the device will be fast:

Quoted 6 lines
Quoted 3 lines

gpio_config.regmap_has_fast_io = true;

which will then set gpio->can_sleep = false.

It's probably useful to provide a query function in the regmap API for generic regmap users like this.

Now I'm confused. Last time, I've proposed that, there was push back from you:
https://lore.kernel.org/linux-gpio/[email protected]/

That being said, I'd prefer to have such a query API :)

-michael

maintainer
#25 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 10 lines · Michael Walle

Am 2022-11-17 17:21, schrieb Mark Brown:

Quoted 2 lines

It's probably useful to provide a query function in the regmap API for generic regmap users like this.

Now I'm confused. Last time, I've proposed that, there was push back from you:
https://lore.kernel.org/linux-gpio/[email protected]/

That being said, I'd prefer to have such a query API :)

Now we have a generic user which cares about the distinction.

#26 lore raw

Re: [PATCH v2 4/4] gpio: i8255: Migrate to regmap API

Quoted 6 lines · Mark Brown
Quoted 4 lines · Michael Walle

Am 2022-11-17 17:21, schrieb Mark Brown:

Quoted 2 lines

It's probably useful to provide a query function in the regmap API for generic regmap users like this.

Quoted 7 lines
Quoted 5 lines

Now I'm confused. Last time, I've proposed that, there was push back from you:
https://lore.kernel.org/linux-gpio/[email protected]/

That being said, I'd prefer to have such a query API :)

Now we have a generic user which cares about the distinction.

I plan on adding more drivers in future patch sets so I expect this to actually grow in users. Having a query function in the regmap API would be useful after all I think.

Michael, if you resubmit your proposal for such a function, please CC me so I can be kept aware of this as well.

Thanks,

William Breathitt Gray