On the A523 the main PIO has the power mode registers at 0x380/0x388,
the R_PIO at 0x340/0x348 like the H6. The select encoding is inverted:
1 means 3.3V, while the value register still reads 1 for 1.8V, so a
plain copy at the new offsets would select the wrong mode. Linux fixed
the same in commit ef56085dfd1d ("pinctrl: sunxi: A523: fix voltage
withstand encoding").Set the select bits from the inverted value bits. Only the per-port bits are written; the VCC-IO bit and GPIO_POW_MS_CTL keep their reset values. Also drop the misspelled NCAT2 guard, which never matched. Link: https://lore.kernel.org/u-boot/[email protected]/ Signed-off-by: Vinicius Pedrosa <[email protected]> --- Changes in v2: - Set up the A523 instead of enabling the copy on the R528 (Andre) - Merge the two H6 blocks Sören Hantel found the misspelled guard and posted the patch linked above. This replaces it, at his request. The offsets and the encoding are from the A523 user manual V1.4, the A527 manual V0.97 says the same. Changing only the offsets is not enough because of the inverted select bits, so the A523 gets its own branch. Build-tested only, I don't have A523 hardware. In reproducible builds on main ab4dc5aacf only the SPLs of the four A523 boards change (avaota-a1, orangepi_4a, radxa-cubie-a5e, x96q_pro_plus). All other H6 and NCAT2 SPLs are byte-identical. If someone with an A523 board can test it: at the U-Boot prompt, "md.l 0x02000380 3" and "md.l 0x07022340 3". Within 0x77e (main PIO) and 0x3 (R_PIO), the first word (SEL) should be the inverse of the third (VAL). arch/arm/mach-sunxi/board.c | 19 ++++++++++++++----- include/sunxi_gpio.h | 5 +++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 432b1c10f9..f517014873 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -198,15 +198,24 @@ static int gpio_init(void) * Update PIO power bias configuration by copying the hardware * detected value. */ - if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || - IS_ENABLED(CONFIG_SUN50I_GEN_NCAT2)) { + if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) { val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL); - /* TODO: A523: keep only the lower two bits? */ writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL); - } - if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) { val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL); writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL); + } else if (IS_ENABLED(CONFIG_MACH_SUN55I_A523)) { + /* + * The main PIO has the registers at other offsets, and the + * select encoding is inverted: a SEL bit of 1 means 3.3V. + */ + val = readl(SUNXI_PIO_BASE + SUN55I_A523_GPIO_POW_MOD_VAL); + clrsetbits_le32(SUNXI_PIO_BASE + SUN55I_A523_GPIO_POW_MOD_SEL, + SUN55I_A523_GPIO_POW_MOD_MASK, + ~val & SUN55I_A523_GPIO_POW_MOD_MASK); + val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL); + clrsetbits_le32(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL, + SUN55I_A523_R_GPIO_POW_MOD_MASK, + ~val & SUN55I_A523_R_GPIO_POW_MOD_MASK); } return 0; diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h index 12b54c8dda..66aa2f1b32 100644 --- a/include/sunxi_gpio.h +++ b/include/sunxi_gpio.h @@ -63,6 +63,11 @@ #define SUN50I_H6_GPIO_POW_MOD_SEL 0x340 #define SUN50I_H6_GPIO_POW_MOD_VAL 0x348 +#define SUN55I_A523_GPIO_POW_MOD_SEL 0x380 +#define SUN55I_A523_GPIO_POW_MOD_VAL 0x388 +/* PB-PG and PI-PK in the main PIO, PL and PM in the R_PIO */ +#define SUN55I_A523_GPIO_POW_MOD_MASK (GENMASK(10, 8) | GENMASK(6, 1)) +#define SUN55I_A523_R_GPIO_POW_MOD_MASK GENMASK(1, 0) #define SUNXI_GPIOS_PER_BANK 32 -- 2.43.0
