linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support
@ 2025-08-21  0:42 Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 1/9] pinctrl: sunxi: rename SUNXI_PINCTRL_NEW_REG_LAYOUT Andre Przywara
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

This series adds support for the pinctrl and GPIO IP in the new
Allwinner A733 SoC.
With all our abstractions and data structure driven code, life could
have been so easy, but Allwinner decided to change the layout of the
MMIO register frame, which requires all kinds of special handling and
code changes here and there. Hopefully this new layout (which admittedly
looks more future proof) will stay around for a while, but I am not
holding my breath on this.

In summary, the changes are:
- Each GPIO bank now occupies 128 bytes instead of just 36 or 48.
- PortA (not implemented on the A733) starts at offset 0x80, not at 0.
- The non-bank specific registers are moved into this gap at the
  beginning.
- There are two new registers per bank, to set or clear bits in the GPIO
  data register, to allow for single-write, lockless GPIO settings.
- The drive level register is moved (to make room for the set/clr regs).
- The IRQ registers are moved into the now bigger respective bank control
  registers part, instead of being grouped separately, as before.

The series follows the usual pattern of refactoring first, to prepare
for the new MMIO frame layout (patches 1-4), then using the changed code
to enable support for this new generation, in patch 5/9.
Patch 6/9 adds support for the one new feature of this SoC's pinctrl IP,
the lockless GPIO settings feature.
Patch 7/9 adds the new DT bindings, patch 8/9 enables the secondary
controller, which curiously is not using the new layout, but looks very
similar to the secondary A523 pin controller.
The final patch 9/9 then adds the driver stub file, which just describes
the GPIO bank configuration and lists the two quirk bits that engage the
code changes added for the new layout.

Based on v6.17-rc1.

I am marking this as RFC, as I don't have suitable hardware for testing.
Also I am not 100% convinced the IRQ number to pin mapping, as needed by
the new IRQ register location, works correctly.
Please have a look, check whether the changes look sane, and test it if
you have access to hardware.

A branch (together with the AXP318W PMIC code) is available at:
https://github.com/apritzel/linux/commits/a733-rfc

Cheers,
Andre

Andre Przywara (9):
  pinctrl: sunxi: rename SUNXI_PINCTRL_NEW_REG_LAYOUT
  pinctrl: sunxi: pass down flags to pinctrl routines
  pinctrl: sunxi: only use PortK special handling on A523
  pinctrl: sunxi: refactor IRQ register accessors
  pinctrl: sunxi: support A733 generation MMIO register layout
  pinctrl: sunxi: add support for set/clear regs
  dt-bindings: pinctrl: add compatible for Allwinner A733
  pinctrl: sunxi: a523-r: add a733-r compatible string
  pinctrl: sunxi: Add support for the Allwinner A733

 .../allwinner,sun55i-a523-pinctrl.yaml        |  6 +-
 drivers/pinctrl/sunxi/Kconfig                 |  5 ++
 drivers/pinctrl/sunxi/Makefile                |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c     |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c |  3 +-
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c   | 51 +++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 85 +++++++++++--------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         | 76 +++++++++++------
 9 files changed, 169 insertions(+), 62 deletions(-)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c

-- 
2.46.3



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC PATCH 1/9] pinctrl: sunxi: rename SUNXI_PINCTRL_NEW_REG_LAYOUT
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 2/9] pinctrl: sunxi: pass down flags to pinctrl routines Andre Przywara
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

After keeping the pinctrl IP mostly register compatible for almost a
decade, in 2021 Allwinner introduced some changes to the register
layout, which made us use a flag called SUNXI_PINCTRL_NEW_REG_LAYOUT.
Now with their latest SoC (A733), Allwinner changed the pinctrl IP
again, so "NEW" isn't really a fitting name anymore.

Rename the symbol to SUNXI_PINCTRL_NCAT2_REG_LAYOUT, with "NCAT2" being
a name often used in vendor source code to signify this "new" generation
of SoCs.

Just a rename of the symbol, no actual code changes.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c     | 2 +-
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c | 2 +-
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c   | 2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
index 8efe35b77af4d..37a60e5d1163b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
@@ -821,7 +821,7 @@ static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
 static int d1_pinctrl_probe(struct platform_device *pdev)
 {
 	return sunxi_pinctrl_init_with_flags(pdev, &d1_pinctrl_data,
-					     SUNXI_PINCTRL_NEW_REG_LAYOUT);
+					     SUNXI_PINCTRL_NCAT2_REG_LAYOUT);
 }
 
 static const struct of_device_id d1_pinctrl_match[] = {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
index 69cd2b4ebd7d7..86a12bce0e335 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
@@ -36,7 +36,7 @@ static int a523_r_pinctrl_probe(struct platform_device *pdev)
 	return sunxi_pinctrl_dt_table_init(pdev, a523_r_nr_bank_pins,
 					   a523_r_irq_bank_muxes,
 					   &a523_r_pinctrl_data,
-					   SUNXI_PINCTRL_NEW_REG_LAYOUT);
+					   SUNXI_PINCTRL_NCAT2_REG_LAYOUT);
 }
 
 static const struct of_device_id a523_r_pinctrl_match[] = {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
index 7d2308c37d29e..0f703cacfe5e3 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
@@ -35,7 +35,7 @@ static int a523_pinctrl_probe(struct platform_device *pdev)
 	return sunxi_pinctrl_dt_table_init(pdev, a523_nr_bank_pins,
 					   a523_irq_bank_muxes,
 					   &a523_pinctrl_data,
-					   SUNXI_PINCTRL_NEW_REG_LAYOUT |
+					   SUNXI_PINCTRL_NCAT2_REG_LAYOUT |
 					   SUNXI_PINCTRL_ELEVEN_BANKS);
 }
 
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 0fb057a07dccb..0a5acbd978da9 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1521,7 +1521,7 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
 	pctl->variant = flags & SUNXI_PINCTRL_VARIANT_MASK;
-	if (flags & SUNXI_PINCTRL_NEW_REG_LAYOUT) {
+	if (flags & SUNXI_PINCTRL_NCAT2_REG_LAYOUT) {
 		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
 		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
 		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index ad26e4de16a85..fb17fae2dab69 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -88,7 +88,7 @@
 #define SUN4I_FUNC_IRQ		6
 
 #define SUNXI_PINCTRL_VARIANT_MASK	GENMASK(7, 0)
-#define SUNXI_PINCTRL_NEW_REG_LAYOUT	BIT(8)
+#define SUNXI_PINCTRL_NCAT2_REG_LAYOUT	BIT(8)
 #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
 #define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
 
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 2/9] pinctrl: sunxi: pass down flags to pinctrl routines
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 1/9] pinctrl: sunxi: rename SUNXI_PINCTRL_NEW_REG_LAYOUT Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 3/9] pinctrl: sunxi: only use PortK special handling on A523 Andre Przywara
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

Recent changes in the Allwinner pinctrl/GPIO IP made us add some quirks,
which the new SoCs (A523 family) need to use. We now have a comfortable
"flags" field on the per-SoC setup side, to tag those quirks we need, but
were translating those flag bits into specific fields for runtime use, in
the init routine.
Now the newest Allwinner GPIO IP adds even more quirks and exceptions,
some of a boolean nature.
To avoid inventing various new boolean flags for the runtime struct
sunxi_pinctrl, let's just directly pass on the flags variable used by the
setup code, so runtime can check for those various quirk bits directly.

Rename the "variant" member to "flags", and directly copy the value from
the setup code into there. Move the variant masking from the init
routine to the functions which actually use the "variant" value.

This mostly paves the way for the new A733 IP generation, which needs
more quirks to be checked at runtime.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 19 +++++++++++--------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  2 +-
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 0a5acbd978da9..a5e390c7ba0ba 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -157,6 +157,7 @@ sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
 					 const char *pin_name,
 					 const char *func_name)
 {
+	unsigned long variant = pctl->flags & SUNXI_PINCTRL_VARIANT_MASK;
 	int i;
 
 	for (i = 0; i < pctl->desc->npins; i++) {
@@ -168,7 +169,7 @@ sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
 			while (func->name) {
 				if (!strcmp(func->name, func_name) &&
 					(!func->variant ||
-					func->variant & pctl->variant))
+					func->variant & variant))
 					return func;
 
 				func++;
@@ -1288,6 +1289,7 @@ static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
 static int sunxi_pinctrl_build_state(struct platform_device *pdev)
 {
 	struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
+	unsigned long variant = pctl->flags & SUNXI_PINCTRL_VARIANT_MASK;
 	void *ptr;
 	int i;
 
@@ -1312,7 +1314,7 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
 		const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
 		struct sunxi_pinctrl_group *group = pctl->groups + pctl->ngroups;
 
-		if (pin->variant && !(pctl->variant & pin->variant))
+		if (pin->variant && !(variant & pin->variant))
 			continue;
 
 		group->name = pin->pin.name;
@@ -1339,11 +1341,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
 		const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
 		struct sunxi_desc_function *func;
 
-		if (pin->variant && !(pctl->variant & pin->variant))
+		if (pin->variant && !(variant & pin->variant))
 			continue;
 
 		for (func = pin->functions; func->name; func++) {
-			if (func->variant && !(pctl->variant & func->variant))
+			if (func->variant && !(variant & func->variant))
 				continue;
 
 			/* Create interrupt mapping while we're at it */
@@ -1371,14 +1373,14 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
 		const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
 		struct sunxi_desc_function *func;
 
-		if (pin->variant && !(pctl->variant & pin->variant))
+		if (pin->variant && !(variant & pin->variant))
 			continue;
 
 		for (func = pin->functions; func->name; func++) {
 			struct sunxi_pinctrl_function *func_item;
 			const char **func_grp;
 
-			if (func->variant && !(pctl->variant & func->variant))
+			if (func->variant && !(variant & func->variant))
 				continue;
 
 			func_item = sunxi_pinctrl_find_function_by_name(pctl,
@@ -1520,7 +1522,7 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
-	pctl->variant = flags & SUNXI_PINCTRL_VARIANT_MASK;
+	pctl->flags = flags;
 	if (flags & SUNXI_PINCTRL_NCAT2_REG_LAYOUT) {
 		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
 		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
@@ -1556,8 +1558,9 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 
 	for (i = 0, pin_idx = 0; i < pctl->desc->npins; i++) {
 		const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
+		unsigned long variant = pctl->flags & SUNXI_PINCTRL_VARIANT_MASK;
 
-		if (pin->variant && !(pctl->variant & pin->variant))
+		if (pin->variant && !(variant & pin->variant))
 			continue;
 
 		pins[pin_idx++] = pin->pin;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index fb17fae2dab69..77a08ccde095a 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -174,7 +174,7 @@ struct sunxi_pinctrl {
 	unsigned			*irq_array;
 	raw_spinlock_t			lock;
 	struct pinctrl_dev		*pctl_dev;
-	unsigned long			variant;
+	unsigned long			flags;
 	u32				bank_mem_size;
 	u32				pull_regs_offset;
 	u32				dlevel_field_width;
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 3/9] pinctrl: sunxi: only use PortK special handling on A523
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 1/9] pinctrl: sunxi: rename SUNXI_PINCTRL_NEW_REG_LAYOUT Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 2/9] pinctrl: sunxi: pass down flags to pinctrl routines Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 4/9] pinctrl: sunxi: refactor IRQ register accessors Andre Przywara
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

The Allwinner A523 pinctrl IP requires an exception for addressing PortK,
since the registers for this GPIO bank did not fit anymore in the
existing MMIO frame. Since the A523 was also the first SoC to actually
implement PortK, we just enabled this quirk unconditionally.
Now the new Allwinner A733 changed the MMIO frame layout, so PortK can
and must be handled without any special code.

Mark the special casing for PortK with the ELEVEN_BANKS quirk flag we
introduced, so that it will only be used on SoCs using the A523 pinctrl
IP.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index a5e390c7ba0ba..2af6ebef7a10b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -67,7 +67,7 @@ static u32 sunxi_bank_offset(const struct sunxi_pinctrl *pctl, u32 pin)
 {
 	u32 offset = 0;
 
-	if (pin >= PK_BASE) {
+	if (pin >= PK_BASE && (pctl->flags & SUNXI_PINCTRL_ELEVEN_BANKS)) {
 		pin -= PK_BASE;
 		offset = PIO_BANK_K_OFFSET;
 	}
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 4/9] pinctrl: sunxi: refactor IRQ register accessors
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
                   ` (2 preceding siblings ...)
  2025-08-21  0:42 ` [RFC PATCH 3/9] pinctrl: sunxi: only use PortK special handling on A523 Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 5/9] pinctrl: sunxi: support A733 generation MMIO register layout Andre Przywara
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

So far on Allwinner SoCs the registers for controlling the IRQ
capabilities of each bank are grouped separately, behind all the pinmux
related register for all banks:
    0x000   0x024      0x144       0x200  0x220     0x320
    PortA   PortB  ... PortJ <gap> IRQ-A  IRQ-B ... IRQ-J

The newest SoCs now group the IRQ registers together with the other
per-bank registers, so we need to change the accessor functions to
account for that:
    0x080 0x0c0   0x100 0x140      0x580 0x5c0
    PortA IRQ-A   PortB IRQ-B  ... PortK IRQ-K

In preparation for supporting those newer SoCs, pass in the pointer to
"struct sunxi_pinctrl" instead of just its member "desc", so that we gain
access to the flags, to later determine which of the layout variants we
need to use. To simplify that, add a new sunxi_irq_base_reg() function
that returns the respective IRQ register base address.
Also split off the IRQ control register base offset (0x200) from each
IRQ register's offset, so that the individual offsets can be added later
separately, to that base address.

No functional change at this point, just refactoring.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 21 +++++-----
 drivers/pinctrl/sunxi/pinctrl-sunxi.h | 55 ++++++++++++++++-----------
 2 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 2af6ebef7a10b..540fa6c285cfc 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -734,9 +734,10 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		else
 			val = 0xD; /* 3.3V */
 
-		reg = readl(pctl->membase + sunxi_grp_config_reg(pin));
+		reg = readl(pctl->membase + sunxi_grp_config_reg(pctl, pin));
 		reg &= ~IO_BIAS_MASK;
-		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
+		writel(reg | val, pctl->membase +
+		       sunxi_grp_config_reg(pctl, pin));
 		return 0;
 	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
 		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
@@ -1072,7 +1073,7 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
 static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-	u32 reg = sunxi_irq_cfg_reg(pctl->desc, d->hwirq);
+	u32 reg = sunxi_irq_cfg_reg(pctl, d->hwirq);
 	u8 index = sunxi_irq_cfg_offset(d->hwirq);
 	unsigned long flags;
 	u32 regval;
@@ -1119,7 +1120,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
 static void sunxi_pinctrl_irq_ack(struct irq_data *d)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-	u32 status_reg = sunxi_irq_status_reg(pctl->desc, d->hwirq);
+	u32 status_reg = sunxi_irq_status_reg(pctl, d->hwirq);
 	u8 status_idx = sunxi_irq_status_offset(d->hwirq);
 
 	/* Clear the IRQ */
@@ -1129,7 +1130,7 @@ static void sunxi_pinctrl_irq_ack(struct irq_data *d)
 static void sunxi_pinctrl_irq_mask(struct irq_data *d)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-	u32 reg = sunxi_irq_ctrl_reg(pctl->desc, d->hwirq);
+	u32 reg = sunxi_irq_ctrl_reg(pctl, d->hwirq);
 	u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
 	unsigned long flags;
 	u32 val;
@@ -1146,7 +1147,7 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
 static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-	u32 reg = sunxi_irq_ctrl_reg(pctl->desc, d->hwirq);
+	u32 reg = sunxi_irq_ctrl_reg(pctl, d->hwirq);
 	u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
 	unsigned long flags;
 	u32 val;
@@ -1250,7 +1251,7 @@ static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
 
 	chained_irq_enter(chip, desc);
 
-	reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank);
+	reg = sunxi_irq_status_reg_from_bank(pctl, bank);
 	val = readl(pctl->membase + reg);
 
 	if (val) {
@@ -1491,7 +1492,7 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
 
 		writel(src | div << 4,
 		       pctl->membase +
-		       sunxi_irq_debounce_reg_from_bank(pctl->desc, i));
+		       sunxi_irq_debounce_reg_from_bank(pctl, i));
 	}
 
 	return 0;
@@ -1678,10 +1679,10 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 	for (i = 0; i < pctl->desc->irq_banks; i++) {
 		/* Mask and clear all IRQs before registering a handler */
 		writel(0, pctl->membase +
-			  sunxi_irq_ctrl_reg_from_bank(pctl->desc, i));
+			  sunxi_irq_ctrl_reg_from_bank(pctl, i));
 		writel(0xffffffff,
 		       pctl->membase +
-		       sunxi_irq_status_reg_from_bank(pctl->desc, i));
+		       sunxi_irq_status_reg_from_bank(pctl, i));
 
 		irq_set_chained_handler_and_data(pctl->irq[i],
 						 sunxi_pinctrl_irq_handler,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 77a08ccde095a..252cf58387e33 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -57,20 +57,21 @@
 
 #define IRQ_PER_BANK		32
 
-#define IRQ_CFG_REG		0x200
+#define IRQ_REGS_OFFSET		0x200
+#define IRQ_CFG_REG_OFFSET	0x00
 #define IRQ_CFG_IRQ_PER_REG		8
 #define IRQ_CFG_IRQ_BITS		4
 #define IRQ_CFG_IRQ_MASK		((1 << IRQ_CFG_IRQ_BITS) - 1)
-#define IRQ_CTRL_REG		0x210
+#define IRQ_CTRL_REG_OFFSET	0x10
 #define IRQ_CTRL_IRQ_PER_REG		32
 #define IRQ_CTRL_IRQ_BITS		1
 #define IRQ_CTRL_IRQ_MASK		((1 << IRQ_CTRL_IRQ_BITS) - 1)
-#define IRQ_STATUS_REG		0x214
+#define IRQ_STATUS_REG_OFFSET	0x14
 #define IRQ_STATUS_IRQ_PER_REG		32
 #define IRQ_STATUS_IRQ_BITS		1
 #define IRQ_STATUS_IRQ_MASK		((1 << IRQ_STATUS_IRQ_BITS) - 1)
 
-#define IRQ_DEBOUNCE_REG	0x218
+#define IRQ_DEBOUNCE_REG_OFFSET	0x18
 
 #define IRQ_MEM_SIZE		0x20
 
@@ -224,7 +225,8 @@ struct sunxi_pinctrl {
 		.irqnum = _irq,					\
 	}
 
-static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc, u8 bank)
+static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc,
+					u8 bank)
 {
 	if (!desc->irq_bank_map)
 		return bank;
@@ -232,68 +234,77 @@ static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc, u
 		return desc->irq_bank_map[bank];
 }
 
-static inline u32 sunxi_irq_cfg_reg(const struct sunxi_pinctrl_desc *desc,
+static inline u32 sunxi_irq_base_reg(const struct sunxi_pinctrl *pctl, u16 bank)
+{
+	return IRQ_REGS_OFFSET +
+	       sunxi_irq_hw_bank_num(pctl->desc, bank) * IRQ_MEM_SIZE;
+}
+
+static inline u32 sunxi_irq_cfg_reg(const struct sunxi_pinctrl *pctl,
 				    u16 irq)
 {
 	u8 bank = irq / IRQ_PER_BANK;
 	u8 reg = (irq % IRQ_PER_BANK) / IRQ_CFG_IRQ_PER_REG * 0x04;
 
-	return IRQ_CFG_REG +
-	       sunxi_irq_hw_bank_num(desc, bank) * IRQ_MEM_SIZE + reg;
+	return sunxi_irq_base_reg(pctl, bank) + IRQ_CFG_REG_OFFSET + reg;
 }
 
 static inline u32 sunxi_irq_cfg_offset(u16 irq)
 {
 	u32 irq_num = irq % IRQ_CFG_IRQ_PER_REG;
+
 	return irq_num * IRQ_CFG_IRQ_BITS;
 }
 
-static inline u32 sunxi_irq_ctrl_reg_from_bank(const struct sunxi_pinctrl_desc *desc, u8 bank)
+static inline u32 sunxi_irq_ctrl_reg_from_bank(const struct sunxi_pinctrl *pctl,
+					       u8 bank)
 {
-	return IRQ_CTRL_REG + sunxi_irq_hw_bank_num(desc, bank) * IRQ_MEM_SIZE;
+	return sunxi_irq_base_reg(pctl, bank) + IRQ_CTRL_REG_OFFSET;
 }
 
-static inline u32 sunxi_irq_ctrl_reg(const struct sunxi_pinctrl_desc *desc,
-				     u16 irq)
+static inline u32 sunxi_irq_ctrl_reg(const struct sunxi_pinctrl *pctl, u16 irq)
 {
 	u8 bank = irq / IRQ_PER_BANK;
 
-	return sunxi_irq_ctrl_reg_from_bank(desc, bank);
+	return sunxi_irq_ctrl_reg_from_bank(pctl, bank);
 }
 
 static inline u32 sunxi_irq_ctrl_offset(u16 irq)
 {
 	u32 irq_num = irq % IRQ_CTRL_IRQ_PER_REG;
+
 	return irq_num * IRQ_CTRL_IRQ_BITS;
 }
 
-static inline u32 sunxi_irq_debounce_reg_from_bank(const struct sunxi_pinctrl_desc *desc, u8 bank)
+static inline
+u32 sunxi_irq_debounce_reg_from_bank(const struct sunxi_pinctrl *pctl, u8 bank)
 {
-	return IRQ_DEBOUNCE_REG +
-	       sunxi_irq_hw_bank_num(desc, bank) * IRQ_MEM_SIZE;
+	return sunxi_irq_base_reg(pctl, bank) + IRQ_DEBOUNCE_REG_OFFSET;
 }
 
-static inline u32 sunxi_irq_status_reg_from_bank(const struct sunxi_pinctrl_desc *desc, u8 bank)
+static inline
+u32 sunxi_irq_status_reg_from_bank(const struct sunxi_pinctrl *pctl, u8 bank)
 {
-	return IRQ_STATUS_REG +
-	       sunxi_irq_hw_bank_num(desc, bank) * IRQ_MEM_SIZE;
+	return sunxi_irq_base_reg(pctl, bank) + IRQ_STATUS_REG_OFFSET;
 }
 
-static inline u32 sunxi_irq_status_reg(const struct sunxi_pinctrl_desc *desc,
+static inline u32 sunxi_irq_status_reg(const struct sunxi_pinctrl *pctl,
 				       u16 irq)
 {
 	u8 bank = irq / IRQ_PER_BANK;
 
-	return sunxi_irq_status_reg_from_bank(desc, bank);
+	return sunxi_irq_status_reg_from_bank(pctl, bank);
 }
 
 static inline u32 sunxi_irq_status_offset(u16 irq)
 {
 	u32 irq_num = irq % IRQ_STATUS_IRQ_PER_REG;
+
 	return irq_num * IRQ_STATUS_IRQ_BITS;
 }
 
-static inline u32 sunxi_grp_config_reg(u16 pin)
+static inline u32 sunxi_grp_config_reg(const struct sunxi_pinctrl *pctl,
+				       u16 pin)
 {
 	u8 bank = pin / PINS_PER_BANK;
 
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 5/9] pinctrl: sunxi: support A733 generation MMIO register layout
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
                   ` (3 preceding siblings ...)
  2025-08-21  0:42 ` [RFC PATCH 4/9] pinctrl: sunxi: refactor IRQ register accessors Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 6/9] pinctrl: sunxi: add support for set/clear regs Andre Przywara
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

After Allwinner changed the layout of the pinctrl/GPIO IP MMIO register
frame only a few years back, the new SoC generation (starting with the
A733) changes the layout again: each port now uses 128 instead of 36 or 48
bytes, and the drive level registers move to make space for the new
set/clear data registers. Also the PortA registers start at offset 0x80
instead of 0x0 as before, to make room for non-bank specific registers,
like the pow_mod_sel registers, at the beginning of the MMIO frame. Finally
the IRQ registers move into each bank's region.

Add yet another quirk bit to mark this case, and set the existing register
offset values to match the new layout. This also requires to add new
members to struct sunxi_pinctrl, to accommodate the extra changes. The
actual runtime code changes are fortunately minor.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 14 ++++++++++++--
 drivers/pinctrl/sunxi/pinctrl-sunxi.h | 14 ++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 540fa6c285cfc..ff7c5439a458e 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -65,7 +65,7 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip;
  */
 static u32 sunxi_bank_offset(const struct sunxi_pinctrl *pctl, u32 pin)
 {
-	u32 offset = 0;
+	u32 offset = pctl->bank_offset;
 
 	if (pin >= PK_BASE && (pctl->flags & SUNXI_PINCTRL_ELEVEN_BANKS)) {
 		pin -= PK_BASE;
@@ -102,7 +102,7 @@ static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
 {
 	u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width;
 
-	*reg   = sunxi_bank_offset(pctl, pin) + DLEVEL_REGS_OFFSET +
+	*reg   = sunxi_bank_offset(pctl, pin) + pctl->drv_regs_offset +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(pctl->dlevel_field_width) - 1) << *shift;
@@ -1526,15 +1526,25 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 	pctl->flags = flags;
 	if (flags & SUNXI_PINCTRL_NCAT2_REG_LAYOUT) {
 		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
+		pctl->drv_regs_offset = DLEVEL_REGS_OFFSET;
 		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
 		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
+	} else if (flags & SUNXI_PINCTRL_NCAT3_REG_LAYOUT) {
+		pctl->bank_mem_size = A733_BANK_MEM_SIZE;
+		pctl->bank_offset = A733_BANK_OFFSET;
+		pctl->drv_regs_offset = A733_DLEVEL_REGS_OFFSET;
+		pctl->pull_regs_offset = A733_PULL_REGS_OFFSET;
+		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
 	} else {
 		pctl->bank_mem_size = BANK_MEM_SIZE;
+		pctl->drv_regs_offset = DLEVEL_REGS_OFFSET;
 		pctl->pull_regs_offset = PULL_REGS_OFFSET;
 		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
 	}
 	if (flags & SUNXI_PINCTRL_ELEVEN_BANKS)
 		pctl->pow_mod_sel_offset = PIO_11B_POW_MOD_SEL_REG;
+	else if (flags & SUNXI_PINCTRL_NCAT3_REG_LAYOUT)
+		pctl->pow_mod_sel_offset = PIO_NCAT3_POW_MOD_SEL_REG;
 	else
 		pctl->pow_mod_sel_offset = PIO_POW_MOD_SEL_REG;
 
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 252cf58387e33..2b9e93972a5d3 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -53,6 +53,12 @@
 #define D1_DLEVEL_FIELD_WIDTH	4
 #define D1_PULL_REGS_OFFSET	0x24
 
+#define A733_BANK_MEM_SIZE	0x80
+#define A733_BANK_OFFSET	0x80
+#define A733_DLEVEL_REGS_OFFSET	0x20
+#define A733_PULL_REGS_OFFSET	0x30
+#define A733_IRQ_REGS_OFFSET	0x40
+
 #define PINS_PER_BANK		32
 
 #define IRQ_PER_BANK		32
@@ -92,7 +98,9 @@
 #define SUNXI_PINCTRL_NCAT2_REG_LAYOUT	BIT(8)
 #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
 #define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
+#define SUNXI_PINCTRL_NCAT3_REG_LAYOUT	BIT(11)
 
+#define PIO_NCAT3_POW_MOD_SEL_REG	0x040
 #define PIO_POW_MOD_SEL_REG		0x340
 #define PIO_11B_POW_MOD_SEL_REG		0x380
 #define PIO_POW_MOD_CTL_OFS		0x004
@@ -177,6 +185,8 @@ struct sunxi_pinctrl {
 	struct pinctrl_dev		*pctl_dev;
 	unsigned long			flags;
 	u32				bank_mem_size;
+	u32				bank_offset;
+	u32				drv_regs_offset;
 	u32				pull_regs_offset;
 	u32				dlevel_field_width;
 	u32				pow_mod_sel_offset;
@@ -236,6 +246,10 @@ 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 IRQ_REGS_OFFSET +
 	       sunxi_irq_hw_bank_num(pctl->desc, bank) * IRQ_MEM_SIZE;
 }
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 6/9] pinctrl: sunxi: add support for set/clear regs
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
                   ` (4 preceding siblings ...)
  2025-08-21  0:42 ` [RFC PATCH 5/9] pinctrl: sunxi: support A733 generation MMIO register layout Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21 12:35   ` Linus Walleij
  2025-08-21  0:42 ` [RFC PATCH 7/9] dt-bindings: pinctrl: add compatible for Allwinner A733 Andre Przywara
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

The Allwinner pinctrl/GPIO IP so far features just a single GPIO data
register, which holds the logic level for every output pin on each port.
To set or clear the level of a single pin, we need to do a
read/modify/write operation, which needs to be protected by a lock.

The new pinctrl IP introduced with the Allwinner A733 now supports two
extra registers, the value of which will be ORed in respectively NANDed
out from the current value when being written. This allows for lockless
single writes to set or clear GPIO pins.

Add support for this feature to the sunxi pinctrl code, by adding a quirk
bit and checking this when writing to the data register. If the new
registers are available, skip the lock and read/modify/write operation,
and just write the mask directly to the respective register.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 27 +++++++++++++++------------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  3 +++
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index ff7c5439a458e..0d08c48b57b65 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -971,18 +971,21 @@ static int sunxi_pinctrl_gpio_set(struct gpio_chip *chip, unsigned int offset,
 
 	sunxi_data_reg(pctl, offset, &reg, &shift, &mask);
 
-	raw_spin_lock_irqsave(&pctl->lock, flags);
-
-	val = readl(pctl->membase + reg);
-
-	if (value)
-		val |= mask;
-	else
-		val &= ~mask;
-
-	writel(val, pctl->membase + reg);
-
-	raw_spin_unlock_irqrestore(&pctl->lock, flags);
+	if (pctl->flags & SUNXI_PINCTRL_HAS_SET_CLEAR_REGS) {
+		if (value)
+			writel(mask, pctl->membase + reg + DATA_SET_OFFSET);
+		else
+			writel(mask, pctl->membase + reg + DATA_CLR_OFFSET);
+	} else {
+		raw_spin_lock_irqsave(&pctl->lock, flags);
+		val = readl(pctl->membase + reg);
+		if (value)
+			val |= mask;
+		else
+			val &= ~mask;
+		writel(val, pctl->membase + reg);
+		raw_spin_unlock_irqrestore(&pctl->lock, flags);
+	}
 
 	return 0;
 }
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 2b9e93972a5d3..96f1cb9d6c89c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -43,6 +43,8 @@
 #define MUX_REGS_OFFSET		0x0
 #define MUX_FIELD_WIDTH		4
 #define DATA_REGS_OFFSET	0x10
+#define DATA_SET_OFFSET			0x04
+#define DATA_CLR_OFFSET			0x08
 #define DATA_FIELD_WIDTH	1
 #define DLEVEL_REGS_OFFSET	0x14
 #define DLEVEL_FIELD_WIDTH	2
@@ -99,6 +101,7 @@
 #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
 #define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
 #define SUNXI_PINCTRL_NCAT3_REG_LAYOUT	BIT(11)
+#define SUNXI_PINCTRL_HAS_SET_CLEAR_REGS	BIT(12)
 
 #define PIO_NCAT3_POW_MOD_SEL_REG	0x040
 #define PIO_POW_MOD_SEL_REG		0x340
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 7/9] dt-bindings: pinctrl: add compatible for Allwinner A733
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
                   ` (5 preceding siblings ...)
  2025-08-21  0:42 ` [RFC PATCH 6/9] pinctrl: sunxi: add support for set/clear regs Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-21 18:14   ` Conor Dooley
  2025-08-21  0:42 ` [RFC PATCH 8/9] pinctrl: sunxi: a523-r: add a733-r compatible string Andre Przywara
  2025-08-21  0:42 ` [RFC PATCH 9/9] pinctrl: sunxi: Add support for the Allwinner A733 Andre Przywara
  8 siblings, 1 reply; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

The A733 contains a pin controller similar to previous SoCs, although
with a change in the MMIO register frame layout.
This SoC uses the new style of DT binding, where the pinmux values for
each pin group are stored in the new "allwinner,pinmux" property in the
DT node.

Add the new compatible to the existing A523 binding, since they share a
lot of features, including the number of banks and clocks.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 .../bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml     | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml
index 154e03da8ce98..c04b04acf6e45 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/pinctrl/allwinner,sun55i-a523-pinctrl.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Allwinner A523 Pin Controller
+title: Allwinner A523 & A733 Pin Controller
 
 maintainers:
   - Andre Przywara <andre.przywara@arm.com>
@@ -28,6 +28,8 @@ properties:
     enum:
       - allwinner,sun55i-a523-pinctrl
       - allwinner,sun55i-a523-r-pinctrl
+      - allwinner,sun60i-a733-pinctrl
+      - allwinner,sun60i-a733-r-pinctrl
 
   reg:
     maxItems: 1
@@ -126,6 +128,7 @@ allOf:
         compatible:
           enum:
             - allwinner,sun55i-a523-pinctrl
+            - allwinner,sun60i-a733-pinctrl
 
     then:
       properties:
@@ -138,6 +141,7 @@ allOf:
         compatible:
           enum:
             - allwinner,sun55i-a523-r-pinctrl
+            - allwinner,sun60i-a733-r-pinctrl
 
     then:
       properties:
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 8/9] pinctrl: sunxi: a523-r: add a733-r compatible string
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
                   ` (6 preceding siblings ...)
  2025-08-21  0:42 ` [RFC PATCH 7/9] dt-bindings: pinctrl: add compatible for Allwinner A733 Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  2025-08-23 23:09   ` Julian Calaby
  2025-08-21  0:42 ` [RFC PATCH 9/9] pinctrl: sunxi: Add support for the Allwinner A733 Andre Przywara
  8 siblings, 1 reply; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

The secondary Allwinner A733 pincontroller ("-r") is interestingly not
using the same new MMIO frame layout as the main controller, but is in
fact very similar to the A523-r one: it has two banks, with 14 and 6 pins
each. From the driver's perspective, this is all we care about, so we can
re-use the a523-r pinctrl driver for the a733-r, too.

The individual pinmux settings are different, so we must not use the
a523-r compatible string as a fallback, but we can surely let the same
driver care for both the a523-r and a733-r IP, as the pinmux values will
be provided by the DT.

Add the a733-r compatible string to the match list, without further
distinguishing between the two. Should differences be discovered later,
we can easily split this up then.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
index 86a12bce0e335..437c955463bac 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
@@ -41,6 +41,7 @@ static int a523_r_pinctrl_probe(struct platform_device *pdev)
 
 static const struct of_device_id a523_r_pinctrl_match[] = {
 	{ .compatible = "allwinner,sun55i-a523-r-pinctrl", },
+	{ .compatible = "allwinner,sun60i-a733-r-pinctrl", },
 	{}
 };
 
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 9/9] pinctrl: sunxi: Add support for the Allwinner A733
  2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
                   ` (7 preceding siblings ...)
  2025-08-21  0:42 ` [RFC PATCH 8/9] pinctrl: sunxi: a523-r: add a733-r compatible string Andre Przywara
@ 2025-08-21  0:42 ` Andre Przywara
  8 siblings, 0 replies; 13+ messages in thread
From: Andre Przywara @ 2025-08-21  0:42 UTC (permalink / raw)
  To: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

The Allwinner A733 changes the layout of the pinctrl MMIO register
frame, but stays otherwise rather close to the previous IP.
The main PIO looks similar to the one in the A523, with ports B-K being
implemented, each also with the same number of pins per port as on the
A523.

Use the DT based pinctrl driver to describe just the generic pinctrl
properties, so advertise the number of pins per bank, interrupt
capabilities and the new quirks. The actual function/mux assignment will
be taken from the devicetree.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/Kconfig               |  5 ++
 drivers/pinctrl/sunxi/Makefile              |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c | 51 +++++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index dc62eba96348e..831bb1dc93738 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -141,4 +141,9 @@ config PINCTRL_SUN55I_A523_R
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN60I_A733
+	bool "Support for the Allwinner A733 PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 951b3f1e4b4f1..3658c9d06b498 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -29,5 +29,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
 obj-$(CONFIG_PINCTRL_SUN55I_A523)	+= pinctrl-sun55i-a523.o
 obj-$(CONFIG_PINCTRL_SUN55I_A523_R)	+= pinctrl-sun55i-a523-r.o
+obj-$(CONFIG_PINCTRL_SUN60I_A733)	+= pinctrl-sun60i-a733.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c b/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c
new file mode 100644
index 0000000000000..1eafbf2ab3c97
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A733 SoC pinctrl driver.
+ *
+ * Copyright (C) 2025 Arm Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const u8 a733_nr_bank_pins[SUNXI_PINCTRL_MAX_BANKS] =
+/*	  PA  PB  PC  PD  PE  PF  PG  PH  PI  PJ  PK */
+	{  0, 11, 17, 24, 16,  7, 15, 20, 17, 28, 26 };
+
+static const u8 a733_irq_bank_muxes[SUNXI_PINCTRL_MAX_BANKS] =
+/*	  PA  PB  PC  PD  PE  PF  PG  PH  PI  PJ  PK */
+	{  0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
+
+static struct sunxi_pinctrl_desc a733_pinctrl_data = {
+	.irq_banks = 10,
+	.irq_read_needs_mux = true,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int a733_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_dt_table_init(pdev, a733_nr_bank_pins,
+					   a733_irq_bank_muxes,
+					   &a733_pinctrl_data,
+					   SUNXI_PINCTRL_NCAT3_REG_LAYOUT |
+					   SUNXI_PINCTRL_HAS_SET_CLEAR_REGS);
+}
+
+static const struct of_device_id a733_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun60i-a733-pinctrl", },
+	{}
+};
+
+static struct platform_driver a733_pinctrl_driver = {
+	.probe	= a733_pinctrl_probe,
+	.driver	= {
+		.name		= "sun60i-a733-pinctrl",
+		.of_match_table	= a733_pinctrl_match,
+	},
+};
+builtin_platform_driver(a733_pinctrl_driver);
-- 
2.46.3



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 6/9] pinctrl: sunxi: add support for set/clear regs
  2025-08-21  0:42 ` [RFC PATCH 6/9] pinctrl: sunxi: add support for set/clear regs Andre Przywara
@ 2025-08-21 12:35   ` Linus Walleij
  0 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2025-08-21 12:35 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Chen-Yu Tsai, Samuel Holland, Jernej Skrabec, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, linux-gpio,
	devicetree, linux-arm-kernel, linux-sunxi

Hi Andre,

thanks for your patch!

On Thu, Aug 21, 2025 at 2:45 AM Andre Przywara <andre.przywara@arm.com> wrote:

> -       raw_spin_unlock_irqrestore(&pctl->lock, flags);
> +       if (pctl->flags & SUNXI_PINCTRL_HAS_SET_CLEAR_REGS) {
> +               if (value)
> +                       writel(mask, pctl->membase + reg + DATA_SET_OFFSET);
> +               else
> +                       writel(mask, pctl->membase + reg + DATA_CLR_OFFSET);
> +       } else {
> +               raw_spin_lock_irqsave(&pctl->lock, flags);
> +               val = readl(pctl->membase + reg);
> +               if (value)
> +                       val |= mask;
> +               else
> +                       val &= ~mask;
> +               writel(val, pctl->membase + reg);
> +               raw_spin_unlock_irqrestore(&pctl->lock, flags);
> +       }

This is now starting to re-implement the generic MMIO GPIO chip,
which I'm not so happy about, this is simply the difference between
passing just a single data register to the generic config or
passing a set and clear register.

        ret = bgpio_init(&g->gc, dev, 4,
                         g->base + GPIO_DATA_IN,
                         g->base + GPIO_DATA_SET,
                         g->base + GPIO_DATA_CLR,
                         g->base + GPIO_DIR,
                         NULL,
                         0);

...

I also notice:
pctl->chip->of_gpio_n_cells = 3;

Is Allwinner one of those drivers that could actually start using
select GPIO_GENERIC nowadays?

Please look at
commit bd3ce71078bde4ecbfc60d49c96d1c55de0635cc
"gpiolib: of: Handle threecell GPIO chips"

And the example user:
drivers/gpio/gpio-spacemit-k1.c
esp how it uses spacemit_of_node_instance_match().

If it's possible to switch over to GPIO_GENERIC this hopeless
maintainer would love if that could be done first so the picture
gets more clear.

Yours,
Linus Walleij



Yours,
Linus Walleij


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 7/9] dt-bindings: pinctrl: add compatible for Allwinner A733
  2025-08-21  0:42 ` [RFC PATCH 7/9] dt-bindings: pinctrl: add compatible for Allwinner A733 Andre Przywara
@ 2025-08-21 18:14   ` Conor Dooley
  0 siblings, 0 replies; 13+ messages in thread
From: Conor Dooley @ 2025-08-21 18:14 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

[-- Attachment #1: Type: text/plain, Size: 609 bytes --]

On Thu, Aug 21, 2025 at 01:42:30AM +0100, Andre Przywara wrote:
> The A733 contains a pin controller similar to previous SoCs, although
> with a change in the MMIO register frame layout.
> This SoC uses the new style of DT binding, where the pinmux values for
> each pin group are stored in the new "allwinner,pinmux" property in the
> DT node.
> 
> Add the new compatible to the existing A523 binding, since they share a
> lot of features, including the number of banks and clocks.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>

Acked-by: Conor Dooley <conor.dooley@microchip.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 8/9] pinctrl: sunxi: a523-r: add a733-r compatible string
  2025-08-21  0:42 ` [RFC PATCH 8/9] pinctrl: sunxi: a523-r: add a733-r compatible string Andre Przywara
@ 2025-08-23 23:09   ` Julian Calaby
  0 siblings, 0 replies; 13+ messages in thread
From: Julian Calaby @ 2025-08-23 23:09 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Linus Walleij, Chen-Yu Tsai, Samuel Holland, Jernej Skrabec,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	linux-gpio, devicetree, linux-arm-kernel, linux-sunxi

Hi Andre,

On Thu, Aug 21, 2025 at 10:46 AM Andre Przywara <andre.przywara@arm.com> wrote:
>
> The secondary Allwinner A733 pincontroller ("-r") is interestingly not
> using the same new MMIO frame layout as the main controller, but is in
> fact very similar to the A523-r one: it has two banks, with 14 and 6 pins
> each. From the driver's perspective, this is all we care about, so we can
> re-use the a523-r pinctrl driver for the a733-r, too.
>
> The individual pinmux settings are different, so we must not use the
> a523-r compatible string as a fallback, but we can surely let the same
> driver care for both the a523-r and a733-r IP, as the pinmux values will
> be provided by the DT.

If the bank and pin counts are the same and the pinmux values are
provided by the DT, that means they _are_ compatible, right?

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-08-23 23:12 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-21  0:42 [RFC PATCH 0/9] pinctrl: sunxi: Allwinner A733 support Andre Przywara
2025-08-21  0:42 ` [RFC PATCH 1/9] pinctrl: sunxi: rename SUNXI_PINCTRL_NEW_REG_LAYOUT Andre Przywara
2025-08-21  0:42 ` [RFC PATCH 2/9] pinctrl: sunxi: pass down flags to pinctrl routines Andre Przywara
2025-08-21  0:42 ` [RFC PATCH 3/9] pinctrl: sunxi: only use PortK special handling on A523 Andre Przywara
2025-08-21  0:42 ` [RFC PATCH 4/9] pinctrl: sunxi: refactor IRQ register accessors Andre Przywara
2025-08-21  0:42 ` [RFC PATCH 5/9] pinctrl: sunxi: support A733 generation MMIO register layout Andre Przywara
2025-08-21  0:42 ` [RFC PATCH 6/9] pinctrl: sunxi: add support for set/clear regs Andre Przywara
2025-08-21 12:35   ` Linus Walleij
2025-08-21  0:42 ` [RFC PATCH 7/9] dt-bindings: pinctrl: add compatible for Allwinner A733 Andre Przywara
2025-08-21 18:14   ` Conor Dooley
2025-08-21  0:42 ` [RFC PATCH 8/9] pinctrl: sunxi: a523-r: add a733-r compatible string Andre Przywara
2025-08-23 23:09   ` Julian Calaby
2025-08-21  0:42 ` [RFC PATCH 9/9] pinctrl: sunxi: Add support for the Allwinner A733 Andre Przywara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).