pinctrl: airoha: add EcoNet EN7528 pin controller support
Subsystems (5)
cover pinctrl: airoha: add EcoNet EN7528 pin controller support
The EcoNet EN7528 is a MIPS SoC that uses the same pin controller and GPIO IP as the Airoha SoCs, so it reuses the shared driver code introduced by the split into per-SoC drivers. Its register layout differs from every existing variant though: all IOMUX mode bits live in a single CHIP SCU register plus a few spill-over bits in IOMUX Control 3, EJTAG has its own enable register, and every pin configuration register is at a different offset than on EN7523.
It also differs in a way the shared code did not model: only GPIO0-GPIO15 are wired to the interrupt controller, while the driver assumed all AIROHA_NUM_PINS GPIOs could raise an interrupt. Patch 1 adds a num_irq_pins field to the per-SoC match data to describe that, bounds the interrupt callbacks and handler with it, and feeds it to gpiolib through gpio_irq_chip::init_valid_mask so gpiod_to_irq() fails up front for a pin that can never be an interrupt source. All existing SoCs pass AIROHA_NUM_PINS and are unaffected.
Patch 2 documents the binding, patch 3 adds the driver.
The series is based on linux-pinctrl/for-next, as it depends on the per-SoC driver split and on the CHIP SCU lookup by "airoha,chip-scu" phandle that landed there.
Tested on a DASAN H660GM-A (EN7528, Airtel), booting OpenWrt.
Ahmed Naseef (2):
pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
Benjamin Larsson (1):
pinctrl: airoha: add support of en7528 SoC
.../pinctrl/econet,en7528-pinctrl.yaml | 190 +++ drivers/pinctrl/airoha/Kconfig | 15 +- drivers/pinctrl/airoha/Makefile | 1 + 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 + drivers/pinctrl/airoha/pinctrl-en7528.c | 1204 +++++++++++++++++ 10 files changed, 1443 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml create mode 100644 drivers/pinctrl/airoha/pinctrl-en7528.c
base-commit: 87e787e591a82b9b324aa0968795b256f789d287
Signature · 1 line
2.34.1
PATCH 1/3 pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
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().
--- 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(-)
drivers/pinctrl/airoha/airoha-common.h +3 -0
@@ -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);
drivers/pinctrl/airoha/pinctrl-airoha.c +28 -5
@@ -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); +} +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)
drivers/pinctrl/airoha/pinctrl-an7563.c +1 -0
@@ -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,
drivers/pinctrl/airoha/pinctrl-an7581.c +1 -0
@@ -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,
drivers/pinctrl/airoha/pinctrl-an7583.c +1 -0
@@ -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,
drivers/pinctrl/airoha/pinctrl-en7523.c +1 -0
@@ -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,
Signature · 1 line
2.34.1
[email protected]
AI reviewRe: [PATCH 1/3] pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Pre-existing issues:
- [High] The shared parent interrupt is requested before the gpiochip and its IRQ domain are fully registered, creating a race condition that loses hardware interrupts during probe.
- [High] The interrupt handler manually clears the hardware status bit after the child handler completes, creating a race condition that drops edge-triggered interrupts.
- [High] The driver acquires a sleepable spinlock inside IRQ chip callbacks while holding a raw_spinlock_t, violating PREEMPT_RT lock nesting rules.
- [High] The interrupt handler loops over banks bounded by num_irq_pins but fails to mask out unbacked bits within the final bank, neutralizing spurious interrupt mitigation. --
--- Patch [1]: [PATCH 1/3] pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins --- commit 540e2cd0ad7d06a01aca006b216ac539740ee038
Author: Ahmed Naseef <[email protected]>
pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
This patch limits GPIO interrupts to interrupt-capable pins by introducing a num_irq_pins field to the SoC match data. It restricts the interrupt callbacks and the loop in the interrupt handler, and feeds the count to gpiolib to prevent requesting invalid interrupts.
Quoted 13 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +1
-1@@ -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));
drivers/pinctrl/airoha/pinctrl-airoha.c
Quoted 7 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +0
-0switch (irqd_get_trigger_type (data)) {case IRQ_TYPE_LEVEL_LOW : val = val <<1 ; fallthrough;case IRQ_TYPE_LEVEL_HIGH :regmap_update_bits (pinctrl->regmap, gpio_regs->level[index], mask, val);
[Severity: High]
This isn't a bug introduced by this patch, but does calling regmap_update_bits() here cause a lock nesting violation on PREEMPT_RT kernels?
The IRQ chip callbacks like airoha_irq_unmask() are invoked by the IRQ core with the descriptor lock (desc->lock) held, which is a raw_spinlock_t.
The syscon regmap (pinctrl->regmap) uses a standard spinlock_t that becomes a sleepable RT-mutex on PREEMPT_RT. Acquiring a sleepable lock under a raw spinlock leads to a kernel panic.
[ ... ]
Quoted 16 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +3
-1@@ -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;drivers/pinctrl/airoha/pinctrl-airoha.c +0
-0int irq; if (regmap_read(pinctrl->regmap, pinctrl->gpio_regs->status[i],
drivers/pinctrl/airoha/pinctrl-airoha.c
Quoted 10 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +0
-0®map))continue ; status = regmap;for_each_set_bit (irq, &status,AIROHA_PIN_BANK_SIZE ) {u32 offset = irq + i *AIROHA_PIN_BANK_SIZE ;generic_handle_domain_irq (girq->domain, offset);regmap_write (pinctrl->regmap, pinctrl->gpio_regs->status[i],BIT (irq));
[Severity: High]
This isn't a bug introduced by this patch, but does clearing the hardware status bit after the child handler completes cause edge-triggered interrupts to be dropped?
In airoha_irq_handler(), after generic_handle_domain_irq() returns, the handler manually clears the hardware status bit using regmap_write(). However, the IRQ core (such as handle_edge_irq) already invokes the chip's irq_ack callback to clear this bit before executing the child handler.
By clearing the bit a second time after the child handler returns, any new edge-triggered interrupts that arrived while the child handler was executing would be silently erased.
drivers/pinctrl/airoha/pinctrl-airoha.c
Quoted 2 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +0
-0} handled |= !!status;
[Severity: High]
This is a pre-existing issue, but does failing to mask out unbacked bits in the final bank neutralize the spurious interrupt mitigation?
While nbanks limits the outer loop, on EN7528 num_irq_pins is 16, so nbanks is 1. The loop reads status[0] and for_each_set_bit() iterates over all 32 bits.
If any unbacked hardware bit (16-31) reads as 1, generic_handle_domain_irq() is called (and safely returns -EINVAL), but handled incorrectly evaluates to true. This would cause IRQ_HANDLED to be returned for spurious interrupts on the shared line, defeating the kernel's spurious interrupt storm mitigation.
[ ... ]
Quoted 8 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +1
-0@@ -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 );
drivers/pinctrl/airoha/pinctrl-airoha.c
Quoted 10 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +0
-0if (irq <0 )return irq; err =devm_request_irq (dev, irq, airoha_irq_handler,IRQF_SHARED ,dev_name (dev), pinctrl);if (err)return err;return devm_gpiochip_add_data (dev, gc, pinctrl); }
[Severity: High]
This isn't a bug introduced by this patch, but does requesting the shared parent interrupt before registering the gpiochip cause a race condition during probe?
The driver requests the shared parent IRQ via devm_request_irq() before calling devm_gpiochip_add_data().
If the shared IRQ line is asserted by another device before devm_gpiochip_add_data() completes, airoha_irq_handler() will run, read the hardware status, and call generic_handle_domain_irq() with an uninitialized girq->domain. The core lookup fails, but the handler proceeds to clear the hardware status and returns IRQ_HANDLED, dropping the interrupt.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCH 1/3] pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
In reply to Ahmed NaseefHi.
Quoted 111 lines · Ahmed Naseef
The driver assumes that every one of the
AIROHA_NUM_PINSGPIOs 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_pinsfield 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 throughgpio_irq_chip::init_valid_maskas well, so thatgpiod_to_irq()fails for a pin that cannot be an interrupt source instead of deferring the failure torequest_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(-)drivers/pinctrl/airoha/airoha-common.h +3
-0@@ -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);drivers/pinctrl/airoha/pinctrl-airoha.c +15
-5@@ -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. +*/
drivers/pinctrl/airoha/pinctrl-airoha.c static const struct irq_chip airoha_gpio_irq_chip = { · line 362
Quoted 10 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +10
-0+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:
Quoted 68 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +3
-0+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)drivers/pinctrl/airoha/pinctrl-an7563.c +1
-0@@ -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,drivers/pinctrl/airoha/pinctrl-an7581.c +1
-0@@ -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,drivers/pinctrl/airoha/pinctrl-an7583.c +1
-0@@ -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,drivers/pinctrl/airoha/pinctrl-en7523.c +1
-0@@ -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,
Re: [PATCH 1/3] pinctrl: airoha: limit GPIO interrupts to interrupt-capable pins
Quoted 11 lines
drivers/pinctrl/airoha/pinctrl-airoha.c static const struct irq_chip airoha_gpio_irq_chip = { · line 362
Quoted 7 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +7
-0+{ +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?
Quoted 2 lines
Either way:
Reviewed-by Benjamin Larsson <[email protected]>
Nothing logs the limit itself, the -ENXIO only surfaces at the consumer.
However Most of the gpio_irq_chip::init_valid_mask implementations in the tree log nothing at all. Only pinctrl-baytrail does, and not for the valid range.
Happy to make it explicit if you prefer, at probe:
if (pinctrl->num_irq_pins < AIROHA_NUM_PINS)
dev_dbg(dev, "GPIO%u and above cannot be used as interrupts\n",
pinctrl->num_irq_pins);Thanks for the review!
Linus, since the merge window is open. Is this still worth taking for v7.3, or would you rather it soaked in for v7.4? 2/3 has no DT ack yet either.
Ahmed
Quoted 66 lines
Quoted 66 lines
drivers/pinctrl/airoha/pinctrl-airoha.c +3
-0+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)drivers/pinctrl/airoha/pinctrl-an7563.c +1
-0@@ -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,drivers/pinctrl/airoha/pinctrl-an7581.c +1
-0@@ -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,drivers/pinctrl/airoha/pinctrl-an7583.c +1
-0@@ -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,drivers/pinctrl/airoha/pinctrl-en7523.c +1
-0@@ -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,
PATCH 2/3 dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
In reply to Ahmed NaseefAdd the binding for the pin controller found on the EcoNet EN7528 MIPS SoC. It shares the IP with the Airoha pin controllers, but its IOMUX and pin configuration registers have a different layout, so it gets its own compatible.
The CHIP SCU holding those registers is referenced by the airoha,chip-scu phandle.
--- .../pinctrl/econet,en7528-pinctrl.yaml | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +190 -0
@@ -0,0 +1,190 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/econet,en7528-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: EcoNet EN7528 Pin Controller + +maintainers: + - Lorenzo Bianconi <[email protected]> + +description: + The EcoNet EN7528 pin controller is used to control SoC pins. It shares the + IP with the Airoha pin controllers, but its IOMUX and pin configuration + registers have a different layout. + +properties: + compatible: + const: econet,en7528-pinctrl + + airoha,chip-scu: + description: phandle to the chip SCU syscon + $ref: /schemas/types.yaml#/definitions/phandle + + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + gpio-ranges: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +allOf: + - $ref: pinctrl.yaml# + +required: + - compatible + - airoha,chip-scu + - interrupts + - gpio-controller + - gpio-ranges + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + +patternProperties: + '-pins$': + type: object + + patternProperties: + '^mux(-|$)': + type: object + + description: + pinmux configuration nodes. + + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [gpio, jtag, pcie_reset, pcm, pcm_spi, phy1_led0, + phy1_led1, phy2_led0, phy2_led1, phy3_led0, phy3_led1, + phy4_led0, phy4_led1, pnand, pon, pwm, sipo, spi, uart] + + groups: + description: + An array of strings. Each string contains the name of a group. + items: + enum: [pon, sipo, sipo_rclk, uart2, uart2_cts_rts, uart3, + ejtag, pcm1, pcm2, spi_quad, spi_cs1, pcm_spi, + pcm_spi_int, pcm_spi_rst, pcm_spi_cs1, pcm_spi_cs2, + pcm_spi_cs3, pcm_spi_cs4, pcm_spi_cs5, pcm_spi_cs6, + pcm_spi_cs7, pnand, gpio0, gpio1, gpio2, gpio3, gpio4, + gpio5, gpio6, gpio7, gpio8, gpio9, gpio10, gpio11, + gpio12, gpio13, gpio14, gpio15, gpio16, gpio17, + gpio18, gpio19, gpio20, gpio21, gpio22, gpio23, + gpio24, gpio25, gpio26, gpio27, gpio28, gpio29, + gpio30, gpio31, gpio32, gpio33, gpio34, gpio35, + gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, + pcie_reset0, pcie_reset1] + + required: + - function + - groups + + additionalProperties: false + + '^conf(-|$)': + type: object + + description: + pinconf configuration nodes. + + $ref: /schemas/pinctrl/pincfg-node.yaml + + properties: + pins: + description: + An array of strings. Each string contains the name of a pin. + items: + enum: [gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, + gpio7, gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, + gpio14, gpio15, gpio16, gpio17, gpio18, gpio19, + gpio20, gpio21, gpio22, gpio23, gpio24, gpio25, + gpio26, gpio27, gpio28, gpio29, gpio30, gpio31, + gpio32, gpio33, gpio34, gpio35, gpio36, gpio37, + gpio38, gpio39, pcie_reset0, pcie_reset1, i2c_sda, + i2c_scl, uart_txd, uart_rxd, spi_cs0, spi_clk, + spi_mosi, spi_miso] + minItems: 1 + maxItems: 50 + + bias-disable: true + + bias-pull-up: true + + bias-pull-down: true + + input-enable: true + + output-enable: true + + output-low: true + + output-high: true + + drive-strength: + description: + Selects the drive strength for the pin, in mA. + enum: [2, 4] + + required: + - pins + + additionalProperties: false + + additionalProperties: false + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/mips-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + pinctrl { + compatible = "econet,en7528-pinctrl"; + + airoha,chip-scu = <&chip_scu>; + + interrupt-parent = <&gic>; + interrupts = <GIC_SHARED 10 IRQ_TYPE_LEVEL_HIGH>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + gpio-ranges = <&pinctrl 0 0 42>; + + uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + + conf { + pins = "gpio28", "gpio29"; + bias-pull-up; + }; + }; + + pwm-pins { + mux { + function = "pwm"; + groups = "gpio30"; + }; + }; + };
Signature · 1 line
2.34.1
[email protected]
AI reviewRe: [PATCH 2/3] dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Low] Top-level `additionalProperties: false` incorrectly used instead of `unevaluatedProperties: false`…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] Top-level additionalProperties: false incorrectly used instead of unevaluatedProperties: false, violating schema inheritance rules.
- [Low] Missing node labels for &pinctrl, &chip_scu, and &gic phandles in the DT binding example.
--
--- Patch [2]: [PATCH 2/3] dt-bindings: pinctrl: Add EcoNet EN7528 pin controller --- commit 416526d5ba1573bed48e64c8f0fa2557dff04dcd
Author: Ahmed Naseef <[email protected]>
dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
Add the binding for the pin controller found on the EcoNet EN7528 MIPS SoC. It shares the IP with the Airoha pin controllers, but its IOMUX and pin configuration registers have a different layout, so it gets its own compatible.
Quoted 13 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +7
-0@@ -0,0 +1,190 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/econet,en7528-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: EcoNet EN7528 Pin Controller
[ ... ]
Quoted 5 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +5
-0+allOf: + - $ref: pinctrl.yaml# + +required: + - compatible
[ ... ]
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 150
Quoted 9 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +9
-0+ required: + - pins + + additionalProperties: false + + additionalProperties: false + +additionalProperties: false +
[Severity: Low]
Does this prevent the use of common pinctrl properties? Since this schema includes a reference to pinctrl.yaml# earlier in the file, using
additionalProperties: false at the top level will incorrectly reject valid properties inherited from the referenced schema.
Should this be unevaluatedProperties: false instead?
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+examples: + - | + #include <dt-bindings/interrupt-controller/mips-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + pinctrl { + compatible = "econet,en7528-pinctrl"; + + airoha,chip-scu = <&chip_scu>; +
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 170
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+ interrupt-parent = <&gic>; + interrupts = <GIC_SHARED 10 IRQ_TYPE_LEVEL_HIGH>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + gpio-ranges = <&pinctrl 0 0 42>;
[Severity: Low]
Will this example fail dt_binding_check compilation due to missing labels? The phandles &chip_scu, &gic, and &pinctrl are referenced here, but they are not defined as labels within the example snippet.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Re: [PATCH 2/3] dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
Quoted 3 lines · On Sun, Aug 09, 2026 at 08:15:52AM +0000, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] Top-leveladditionalProperties: falseincorrectly used instead ofunevaluatedProperties: false, violating schema inheritance rules.
- [Low] Missing node labels for&pinctrl,&chip_scu, and&gicphandles in the DT binding example.
Both can be ignored.
Best regards,
Krzysztof
Re: [PATCH 2/3] dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
In reply to Ahmed NaseefQuoted 5 lines · Ahmed Naseef
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +5
-0+maintainers: + - Lorenzo Bianconi <[email protected]> + +description: + The EcoNet EN7528 pin controller is used to control SoC pins. It shares the
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 23
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+ IP with the Airoha pin controllers, but its IOMUX and pin configuration + registers have a different layout. + +properties: + compatible: + const: econet,en7528-pinctrl + + airoha,chip-scu: + description: phandle to the chip SCU syscon + $ref: /schemas/types.yaml#/definitions/phandle
If the entire address space is part of the SCU, then this device should be part of the SCU, e.g. its subnode.
Quoted 8 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +8
-0+ + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 41
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+ + gpio-ranges: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +allOf:
This goes to the end of the file, before the additionalProperties.
Quoted 5 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +5
-0+ - $ref: pinctrl.yaml# + +required: + - compatible + - airoha,chip-scu
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 56
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+ - interrupts + - gpio-controller + - gpio-ranges + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + +patternProperties: + '-pins$': + type: object
"patternProperties" should follow "properties"
Quoted 7 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +7
-0+ + patternProperties: + '^mux(-|$)': + type: object + + description: + pinmux configuration nodes.
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 73
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+ + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [gpio, jtag, pcie_reset, pcm, pcm_spi, phy1_led0, + phy1_led1, phy2_led0, phy2_led1, phy3_led0, phy3_led1, + phy4_led0, phy4_led1, pnand, pon, pwm, sipo, spi, uart]
Best regards,
Krzysztof
Re: [PATCH 2/3] dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
Quoted 11 lines · Krzysztof Kozlowski
Quoted 10 lines · Ahmed Naseef
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+maintainers: + - Lorenzo Bianconi <[email protected]> + +description: + The EcoNet EN7528 pin controller is used to control SoC pins. It shares the + IP with the Airoha pin controllers, but its IOMUX and pin configuration + registers have a different layout. + +properties: + compatible:
Quoted 8 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 23
Quoted 5 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +5
-0+ const: econet,en7528-pinctrl + + airoha,chip-scu: + description: phandle to the chip SCU syscon + $ref: /schemas/types.yaml#/definitions/phandleIf the entire address space is part of the SCU, then this device should be part of the SCU, e.g. its subnode.
It is not: the registers are split over two blocks. The GPIO, interrupt and PWM flash-mode registers are in the block the node sits under, and the IOMUX and pin configuration registers are in the SCU. Both are needed, so whichever of the two is the parent, the other one has to come in by phandle.
Quoted 13 lines
Quoted 13 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +12
-0+ + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + gpio-ranges: + maxItems: 1 +
Quoted 9 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 41
Quoted 6 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +6
-0+ interrupt-controller: true + + '#interrupt-cells': + const: 2 + +allOf:This goes to the end of the file, before the additionalProperties.
Will address in v2.
Quoted 9 lines
Quoted 9 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +9
-0+ - $ref: pinctrl.yaml# + +required: + - compatible + - airoha,chip-scu + - interrupts + - gpio-controller + - gpio-ranges + - "#gpio-cells"
Quoted 9 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 56
Quoted 6 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +6
-0+ - interrupt-controller + - "#interrupt-cells" + +patternProperties: + '-pins$': + type: object"patternProperties" should follow "properties"
Will address in v2.
Thanks for the review!
Ahmed
Quoted 20 lines
Quoted 7 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +7
-0+ + patternProperties: + '^mux(-|$)': + type: object + + description: + pinmux configuration nodes.Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 73
Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+ + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [gpio, jtag, pcie_reset, pcm, pcm_spi, phy1_led0, + phy1_led1, phy2_led0, phy2_led1, phy3_led0, phy3_led1, + phy4_led0, phy4_led1, pnand, pon, pwm, sipo, spi, uart]Best regards,
Krzysztof
Re: [PATCH 2/3] dt-bindings: pinctrl: Add EcoNet EN7528 pin controller
Quoted 21 lines · Ahmed Naseef
Quoted 11 lines · Krzysztof Kozlowski
Quoted 10 lines · Ahmed Naseef
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +10
-0+maintainers: + - Lorenzo Bianconi <[email protected]> + +description: + The EcoNet EN7528 pin controller is used to control SoC pins. It shares the + IP with the Airoha pin controllers, but its IOMUX and pin configuration + registers have a different layout. + +properties: + compatible:Quoted 8 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml line 23
Quoted 5 lines
Documentation/devicetree/bindings/pinctrl/econet,en7528-pinctrl.yaml new file +5
-0+ const: econet,en7528-pinctrl + + airoha,chip-scu: + description: phandle to the chip SCU syscon + $ref: /schemas/types.yaml#/definitions/phandleIf the entire address space is part of the SCU, then this device should be part of the SCU, e.g. its subnode.
Quoted 5 lines
It is not: the registers are split over two blocks. The GPIO, interrupt and PWM flash-mode registers are in the block the node sits under, and the IOMUX and pin configuration registers are in the SCU. Both are needed, so whichever of the two is the parent, the other one has to come in by phandle.
Sure, one is parent and other is sibling. This is standard. But non-standard is to claim to have no MMIO but then get that MMIO from someone else...
Best regards,
Krzysztof
PATCH 3/3 pinctrl: airoha: add support of en7528 SoC
In reply to Ahmed NaseefFrom: Benjamin Larsson <[email protected]>
The EcoNet EN7528 MIPS SoC uses the same pin controller and GPIO IP as the Airoha SoCs, so it can reuse the shared driver code. Its register layout differs from every existing variant though: all IOMUX mode bits live in a single CHIP SCU register (RG_PON_I2C_MODE at 0x15c) plus the spill-over bits in IOMUX Control 3 (0x224), EJTAG has its own enable register at 0x1ac, the LED mapping registers sit at 0x1b0/0x1b4 and all pin configuration registers are at different offsets than on EN7523.
Pin numbering follows the GPIO line numbering, so pins 0-41 map to GPIO0-GPIO41. Pins 42-49 are the standalone I2C/UART/SPI pads, which have no GPIO function and are only referenced by the pinconf tables.
Only GPIO0-GPIO15 are wired to the interrupt controller, so num_irq_pins is 16. EN7528 has no PCIe reset open drain register, so AIROHA_PINCTRL_CONFS_PCIE_RST_OD is left empty and PIN_CONFIG_DRIVE_OPEN_DRAIN is rejected for all pins.
--- drivers/pinctrl/airoha/Kconfig | 15 +- drivers/pinctrl/airoha/Makefile | 1 + drivers/pinctrl/airoha/pinctrl-en7528.c | 1204 +++++++++++++++++++++++ 3 files changed, 1218 insertions(+), 2 deletions(-) create mode 100644 drivers/pinctrl/airoha/pinctrl-en7528.c
drivers/pinctrl/airoha/Kconfig +13 -2
@@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Airoha pinctrl drivers" - depends on ARCH_AIROHA || COMPILE_TEST + depends on ARCH_AIROHA || ECONET || COMPILE_TEST config PINCTRL_AIROHA tristate "Airoha pin control" depends on OF - depends on ARCH_AIROHA || COMPILE_TEST + depends on ARCH_AIROHA || ECONET || COMPILE_TEST select PINMUX select GENERIC_PINCONF select GENERIC_PINCTRL_GROUPS
@@ -17,6 +17,7 @@ config PINCTRL_AIROHA imply PINCTRL_AIROHA_AN7581 imply PINCTRL_AIROHA_AN7583 imply PINCTRL_AIROHA_EN7523 + imply PINCTRL_AIROHA_EN7528 help Shared pin controller and gpio driver code for different Airoha SoCs.
@@ -53,4 +54,14 @@ config PINCTRL_AIROHA_EN7523 Say yes here to support pin controller and gpio driver on Airoha EN7523, EN7529, EN7562 and other compatible SoCs. +config PINCTRL_AIROHA_EN7528 + tristate "EN7528 pinctrl" + depends on ECONET || COMPILE_TEST + depends on PINCTRL_AIROHA + help + Say yes here to support pin controller and gpio driver + on EcoNet EN7528 and other compatible SoCs. Unlike the + other variants, only the first sixteen GPIOs of this SoC + are wired to the interrupt controller. + endmenu
drivers/pinctrl/airoha/Makefile +1 -0
@@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_AIROHA_AN7563) += pinctrl-an7563.o obj-$(CONFIG_PINCTRL_AIROHA_AN7581) += pinctrl-an7581.o obj-$(CONFIG_PINCTRL_AIROHA_AN7583) += pinctrl-an7583.o obj-$(CONFIG_PINCTRL_AIROHA_EN7523) += pinctrl-en7523.o +obj-$(CONFIG_PINCTRL_AIROHA_EN7528) += pinctrl-en7528.o
drivers/pinctrl/airoha/pinctrl-en7528.c new file +1204 -0
1,204 lines not on this page · raw message
Signature · 1 line
2.34.1
Linus Walleij
maintainerHi Ahmed,
thanks for your patches!
Quoted 3 lines · Ahmed Naseef
The series is based on linux-pinctrl/for-next, as it depends on the per-SoC driver split and on the CHIP SCU lookup by "airoha,chip-scu" phandle that landed there.
If we can get a speedy review on these patches I don't mind merging them for v7.3 already, it's nice to get some movement on all the nice Airoha silicon.
Yours,
Linus Walleij
Il giorno lun 10 ago 2026 alle ore 09:23 Linus Walleij <[email protected]> ha scritto:
Quoted 7 lines
Hi Ahmed,
thanks for your patches!
On Sun, Aug 9, 2026 at 10:05 AM Ahmed Naseef <[email protected]> wrote:
Quoted 8 lines
Quoted 3 lines
The series is based on linux-pinctrl/for-next, as it depends on the per-SoC driver split and on the CHIP SCU lookup by "airoha,chip-scu" phandle that landed there.
If we can get a speedy review on these patches I don't mind merging them for v7.3 already, it's nice to get some movement on all the nice Airoha silicon.
Hi Linus,
I wonder if the same speed treatment can be done also for the clock driver and also dts?
There are a few patch there that are currently blocking usb phy and pcie...
Linus Walleij
maintainerQuoted 10 lines · Christian Marangi (Ansuel)
Il giorno lun 10 ago 2026 alle ore 09:23 Linus Walleij <[email protected]> ha scritto:
Quoted 3 lines
If we can get a speedy review on these patches I don't mind merging them for v7.3 already, it's nice to get some movement on all the nice Airoha silicon.
I wonder if the same speed treatment can be done also for the clock driver and also dts?
There are a few patch there that are currently blocking usb phy and pcie...
Heh not my department. I think the SoC maintainers can merge some late DTS patches, the clock driver is up to the clock maintainers.
Yours,
Linus Walleij