Re: [PATCH 1/3] pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
Benjamin Larsson <[email protected]>
| Newsgroups | org.kernel.vger.linux-gpio,org.infradead.lists.linux-mediatek,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Hi. On 09/08/2026 10:04, Ahmed Naseef wrote: > The driver assumes that every one of the AIROHA_NUM_PINS GPIOs can raise > an interrupt. That holds for the SoCs supported so far, but not for every > member of the family: on EN7528 only GPIO0-GPIO15 are wired to the > interrupt controller. > > Without this the driver hands out interrupts for GPIOs that can never > fire, and the interrupt handler reads status registers that are not > backed by any pin. > > Add a num_irq_pins field to the per-SoC match data and use it to bound > the interrupt callbacks and to size the loop in the interrupt handler. > Feed it to gpiolib through gpio_irq_chip::init_valid_mask as well, so > that gpiod_to_irq() fails for a pin that cannot be an interrupt source > instead of deferring the failure to request_irq(). > > Signed-off-by: Ahmed Naseef <[email protected]> > --- > drivers/pinctrl/airoha/airoha-common.h | 3 +++ > drivers/pinctrl/airoha/pinctrl-airoha.c | 33 +++++++++++++++++++++---- > drivers/pinctrl/airoha/pinctrl-an7563.c | 1 + > drivers/pinctrl/airoha/pinctrl-an7581.c | 1 + > drivers/pinctrl/airoha/pinctrl-an7583.c | 1 + > drivers/pinctrl/airoha/pinctrl-en7523.c | 1 + > 6 files changed, 35 insertions(+), 5 deletions(-) > > diff --git a/drivers/pinctrl/airoha/airoha-common.h b/drivers/pinctrl/airoha/airoha-common.h > index c1acbfb7426e..16f7abcdfb83 100644 > --- a/drivers/pinctrl/airoha/airoha-common.h > +++ b/drivers/pinctrl/airoha/airoha-common.h > @@ -127,6 +127,7 @@ struct airoha_pinctrl { > > struct gpio_chip gpiochip; > struct airoha_gpiochip_regs *gpio_regs; > + unsigned int num_irq_pins; > }; > > struct airoha_pinctrl_match_data { > @@ -140,6 +141,8 @@ struct airoha_pinctrl_match_data { > const struct airoha_pinctrl_func *funcs; > const unsigned int num_funcs; > const struct airoha_pinctrl_confs_info confs_info[AIROHA_PINCTRL_CONFS_MAX]; > + /* number of GPIOs wired to the interrupt controller */ > + const unsigned int num_irq_pins; > }; > > int airoha_pinctrl_probe(struct platform_device *pdev); > diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c > index f505a3f69c5d..52a768c859b7 100644 > --- a/drivers/pinctrl/airoha/pinctrl-airoha.c > +++ b/drivers/pinctrl/airoha/pinctrl-airoha.c > @@ -213,7 +213,7 @@ static void airoha_irq_unmask(struct irq_data *data) > u32 mask = GENMASK(2 * offset + 1, 2 * offset); > u32 val = BIT(2 * offset); > > - if (WARN_ON_ONCE(data->hwirq >= AIROHA_NUM_PINS)) > + if (WARN_ON_ONCE(data->hwirq >= pinctrl->num_irq_pins)) > return; > > gpiochip_enable_irq(gc, irqd_to_hwirq(data)); > @@ -249,7 +249,7 @@ static void airoha_irq_mask(struct irq_data *data) > u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN; > u32 mask = GENMASK(2 * offset + 1, 2 * offset); > > - if (data->hwirq >= AIROHA_NUM_PINS) > + if (data->hwirq >= pinctrl->num_irq_pins) > return; > > regmap_clear_bits(pinctrl->regmap, gpio_regs->level[index], mask); > @@ -265,7 +265,7 @@ static void airoha_irq_ack(struct irq_data *data) > u8 offset = data->hwirq % AIROHA_PIN_BANK_SIZE; > u8 index = data->hwirq / AIROHA_PIN_BANK_SIZE; > > - if (data->hwirq >= AIROHA_NUM_PINS) > + if (data->hwirq >= pinctrl->num_irq_pins) > return; > > regmap_write(pinctrl->regmap, gpio_regs->status[index], BIT(offset)); > @@ -273,7 +273,10 @@ static void airoha_irq_ack(struct irq_data *data) > > static int airoha_irq_type(struct irq_data *data, unsigned int type) > { > - if (data->hwirq >= AIROHA_NUM_PINS) > + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); > + struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc); > + > + if (data->hwirq >= pinctrl->num_irq_pins) > return -EINVAL; > > if (type == IRQ_TYPE_NONE) { > @@ -304,9 +307,11 @@ static irqreturn_t airoha_irq_handler(int irq, void *data) > { > struct airoha_pinctrl *pinctrl = data; > bool handled = false; > + unsigned int nbanks; > int i; > > - for (i = 0; i < ARRAY_SIZE(irq_status_regs); i++) { > + nbanks = DIV_ROUND_UP(pinctrl->num_irq_pins, AIROHA_PIN_BANK_SIZE); > + for (i = 0; i < nbanks; i++) { > struct gpio_irq_chip *girq = &pinctrl->gpiochip.irq; > u32 regmap; > unsigned long status; > @@ -340,6 +345,22 @@ static const struct irq_chip airoha_gpio_irq_chip = { > GPIOCHIP_IRQ_RESOURCE_HELPERS, > }; > > +/* > + * Mark the GPIOs that are not wired to the interrupt controller as not > + * valid, so that gpiod_to_irq() fails for them with -ENXIO instead of > + * handing out an interrupt that can never fire. > + */ > +static void airoha_gpio_init_valid_mask(struct gpio_chip *gc, > + unsigned long *valid_mask, > + unsigned int ngpios) > +{ > + struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc); > + unsigned int num_irq_pins = pinctrl->num_irq_pins; > + > + if (num_irq_pins < ngpios) > + bitmap_clear(valid_mask, num_irq_pins, ngpios - num_irq_pins); > +} I'm not sure if there is something that gives a sane error log if this trigger. Maybe make it explicit? Either way: Reviewed-by: Benjamin Larsson <[email protected]> > + > static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, > struct platform_device *pdev) > { > @@ -362,6 +383,7 @@ static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, > > girq->default_type = IRQ_TYPE_NONE; > girq->handler = handle_bad_irq; > + girq->init_valid_mask = airoha_gpio_init_valid_mask; > gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip); > > irq = platform_get_irq(pdev, 0); > @@ -848,6 +870,7 @@ int airoha_pinctrl_probe(struct platform_device *pdev) > pinctrl->grps = data->grps; > pinctrl->funcs = data->funcs; > pinctrl->confs_info = data->confs_info; > + pinctrl->num_irq_pins = data->num_irq_pins; > > err = pinctrl_enable(pinctrl->ctrl); > if (err) > diff --git a/drivers/pinctrl/airoha/pinctrl-an7563.c b/drivers/pinctrl/airoha/pinctrl-an7563.c > index 40cbbe90cc46..f011c6c9ccce 100644 > --- a/drivers/pinctrl/airoha/pinctrl-an7563.c > +++ b/drivers/pinctrl/airoha/pinctrl-an7563.c > @@ -1069,6 +1069,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { > .num_grps = ARRAY_SIZE(pinctrl_groups), > .funcs = pinctrl_funcs, > .num_funcs = ARRAY_SIZE(pinctrl_funcs), > + .num_irq_pins = AIROHA_NUM_PINS, > .confs_info = { > [AIROHA_PINCTRL_CONFS_PULLUP] = { > .confs = pinctrl_pullup_conf, > diff --git a/drivers/pinctrl/airoha/pinctrl-an7581.c b/drivers/pinctrl/airoha/pinctrl-an7581.c > index 2fcf88106e11..bfb777594811 100644 > --- a/drivers/pinctrl/airoha/pinctrl-an7581.c > +++ b/drivers/pinctrl/airoha/pinctrl-an7581.c > @@ -1441,6 +1441,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { > .num_grps = ARRAY_SIZE(pinctrl_groups), > .funcs = pinctrl_funcs, > .num_funcs = ARRAY_SIZE(pinctrl_funcs), > + .num_irq_pins = AIROHA_NUM_PINS, > .confs_info = { > [AIROHA_PINCTRL_CONFS_PULLUP] = { > .confs = pinctrl_pullup_conf, > diff --git a/drivers/pinctrl/airoha/pinctrl-an7583.c b/drivers/pinctrl/airoha/pinctrl-an7583.c > index 2c3a75c35915..1cd0f442ddc1 100644 > --- a/drivers/pinctrl/airoha/pinctrl-an7583.c > +++ b/drivers/pinctrl/airoha/pinctrl-an7583.c > @@ -1471,6 +1471,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { > .num_grps = ARRAY_SIZE(pinctrl_groups), > .funcs = pinctrl_funcs, > .num_funcs = ARRAY_SIZE(pinctrl_funcs), > + .num_irq_pins = AIROHA_NUM_PINS, > .confs_info = { > [AIROHA_PINCTRL_CONFS_PULLUP] = { > .confs = pinctrl_pullup_conf, > diff --git a/drivers/pinctrl/airoha/pinctrl-en7523.c b/drivers/pinctrl/airoha/pinctrl-en7523.c > index 5aa39bacf460..b0c5e60f0aeb 100644 > --- a/drivers/pinctrl/airoha/pinctrl-en7523.c > +++ b/drivers/pinctrl/airoha/pinctrl-en7523.c > @@ -1113,6 +1113,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { > .num_grps = ARRAY_SIZE(pinctrl_groups), > .funcs = pinctrl_funcs, > .num_funcs = ARRAY_SIZE(pinctrl_funcs), > + .num_irq_pins = AIROHA_NUM_PINS, > .confs_info = { > [AIROHA_PINCTRL_CONFS_PULLUP] = { > .confs = pinctrl_pullup_conf,