From: Enzo Adriano <enzo.adriano.code@gmail.com>
To: Andre Przywara <andre.przywara@arm.com>
Cc: linux-sunxi@lists.linux.dev, Enzo Adriano <enzo.adriano.code@gmail.com>
Subject: [PATCH] pinctrl: sunxi: fix EINT bank indexing for SoCs with empty leading banks
Date: Fri, 3 Jul 2026 23:08:21 -0400 [thread overview]
Message-ID: <20260704030821.561389-1-enzo.adriano.code@gmail.com> (raw)
The DT-table init assigns interrupt bank indices by incrementing on
every bank transition, starting from bank 0 - correct only when bank
A actually has pins. On the A733 bank A is empty, so every EINT bank
got an index one too high: the per-bank parent interrupt was taken
from the next bank's slot in the DT list (bank K falling off the end
entirely), while the EINT registers were still addressed correctly
only because the shifted index happened to coincide with the pin-bank
number under the NCAT3 layout.
Assign 0-based indices over the IRQ-capable banks that actually have
pins, record the pin bank each index refers to in an irq_bank_map,
and honour that map in the NCAT3 register-base formula the same way
the legacy layout already does.
On the Cubie A7S this makes a PB EINT consumer raise its events on
GPIOB's interrupt line instead of GPIOC's - the previously observed
'bank-B IRQ storm' with gpio-keys was the unclaimed GPIOB line
screaming while the handler listened one bank up.
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Enzo Adriano <enzo.adriano.code@gmail.com>
---
Andre,
This sits on top of your (as-yet unmerged) A733/NCAT3 pinctrl series -
it does not apply to mainline on its own, so it is offered for you to
fold into your v2 rather than as a standalone submission. I found the
off-by-one while bringing up EINTs on the Cubie A7S; it retroactively
explains the bank-B "IRQ storm" you may have seen with gpio-keys.
Not marked Tested-by: the register-addressing and DT-list reasoning is
confirmed by inspection and the IRQ-line behaviour was observed on
hardware, but a clean end-to-end EINT boot is still blocked on an
unrelated DVFS-lane instability on my tree, so I do not want to
overclaim. Take it, adapt it, or drop it as you see fit for v2.
drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c | 34 +++++++++++++++++-------
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 5 ++--
2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
index 50a16f3bd..e0036df81 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
@@ -143,12 +143,14 @@ static struct sunxi_desc_pin *init_pins_table(struct device *dev,
*/
static int prepare_function_table(struct device *dev, struct device_node *pnode,
struct sunxi_desc_pin *pins, int npins,
- unsigned pin_base, const u8 *irq_bank_muxes)
+ unsigned int pin_base, const u8 *irq_bank_muxes,
+ struct sunxi_pinctrl_desc *desc)
{
struct device_node *node;
struct property *prop;
struct sunxi_desc_function *func;
- int num_funcs, irq_bank, last_bank, i;
+ unsigned int *irq_bank_map;
+ int num_funcs, irq_bank, last_irq_bank, i;
/*
* We need at least three functions per pin:
@@ -207,8 +209,20 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode,
* Assign the function's memory and fill in GPIOs, IRQ and a sentinel.
* The extra functions will be filled in later.
*/
- irq_bank = 0;
- last_bank = 0;
+ /*
+ * The interrupt bank index selects both the per-bank parent
+ * interrupt (the DT lists one per IRQ-capable bank, in order)
+ * and, through irq_bank_map, the pin bank holding the EINT
+ * registers. The first IRQ-capable bank with any pins must get
+ * index 0 even when lower banks (like PA here) have no pins.
+ */
+ irq_bank_map = devm_kcalloc(dev, SUNXI_PINCTRL_MAX_BANKS,
+ sizeof(*irq_bank_map), GFP_KERNEL);
+ if (!irq_bank_map)
+ return -ENOMEM;
+
+ irq_bank = -1;
+ last_irq_bank = -1;
for (i = 0; i < npins; i++) {
struct sunxi_desc_pin *pin = &pins[i];
int bank = (pin->pin.number - pin_base) / PINS_PER_BANK;
@@ -221,17 +235,17 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode,
func[1].muxval = 1;
if (irq_mux) {
- if (bank > last_bank)
+ if (bank != last_irq_bank) {
irq_bank++;
+ irq_bank_map[irq_bank] = bank;
+ last_irq_bank = bank;
+ }
func[lastfunc].muxval = irq_mux;
func[lastfunc].irqbank = irq_bank;
func[lastfunc].irqnum = pin->pin.number % PINS_PER_BANK;
func[lastfunc].name = "irq";
}
- if (bank > last_bank)
- last_bank = bank;
-
pin->functions = func;
/* Skip over the other needed functions and the sentinel. */
@@ -244,6 +258,8 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode,
pin->variant = 2;
}
+ desc->irq_bank_map = irq_bank_map;
+
return 0;
}
@@ -352,7 +368,7 @@ int sunxi_pinctrl_dt_table_init(struct platform_device *pdev,
return PTR_ERR(pins);
ret = prepare_function_table(&pdev->dev, pnode, pins, desc->npins,
- desc->pin_base, irq_bank_muxes);
+ desc->pin_base, irq_bank_muxes, desc);
if (ret)
return ret;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 699ae8850..9aab94601 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -252,8 +252,9 @@ static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc,
static inline u32 sunxi_irq_base_reg(const struct sunxi_pinctrl *pctl, u16 bank)
{
if (pctl->flags & SUNXI_PINCTRL_NCAT3_REG_LAYOUT)
- return pctl->bank_offset + bank * pctl->bank_mem_size +
- A733_IRQ_REGS_OFFSET;
+ return pctl->bank_offset +
+ sunxi_irq_hw_bank_num(pctl->desc, bank) *
+ pctl->bank_mem_size + A733_IRQ_REGS_OFFSET;
return IRQ_REGS_OFFSET +
sunxi_irq_hw_bank_num(pctl->desc, bank) * IRQ_MEM_SIZE;
--
2.53.0
reply other threads:[~2026-07-04 3:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260704030821.561389-1-enzo.adriano.code@gmail.com \
--to=enzo.adriano.code@gmail.com \
--cc=andre.przywara@arm.com \
--cc=linux-sunxi@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox