pinctrl: renesas: rzg2l: Add support for selecting power source for {WDT,AWO,ISO}

The RZ/G3L SoC has support for setting power source that are not
controlled by the following voltage control registers:
  - SD_CH{0,1,2}_POC, XSPI_POC, ETH{0,1}_POC, I3C_SET.POC

Add support for selecting voltages using OTHER_POC register for
setting I/O domain voltage for WDT, ISO and AWO by extending
rzg2l_caps_to_pwr_reg() with a mask output parameter so that callers
callers can identify which bit(s) within OTHER_POC correspond to the
requested domain. Update rzg2l_get_power_source() to extract the
relevant bit field via field_get() when reading OTHER_POC, and update
rzg2l_set_power_source() to perform a read-modify-write under the
spinlock when writing to OTHER_POC, since multiple domains share the
same register.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20260430093422.74812-4-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
Biju Das
2026-04-30 10:34:08 +01:00
committed by Geert Uytterhoeven
parent 55793d3ddf
commit bbe2277ded

View File

@@ -63,10 +63,18 @@
#define PIN_CFG_SMT BIT(16) /* Schmitt-trigger input control */
#define PIN_CFG_ELC BIT(17)
#define PIN_CFG_IOLH_RZV2H BIT(18)
#define PIN_CFG_PVDD1833_OTH_AWO_POC BIT(19) /* known on RZ/G3L only */
#define PIN_CFG_PVDD1833_OTH_ISO_POC BIT(20) /* known on RZ/G3L only */
#define PIN_CFG_WDTOVF_N_POC BIT(21) /* known on RZ/G3L only */
#define RZG2L_SINGLE_PIN BIT_ULL(63) /* Dedicated pin */
#define RZG2L_VARIABLE_CFG BIT_ULL(62) /* Variable cfg for port pins */
#define PIN_CFG_OTHER_POC_MASK \
(PIN_CFG_PVDD1833_OTH_AWO_POC | \
PIN_CFG_PVDD1833_OTH_ISO_POC | \
PIN_CFG_WDTOVF_N_POC)
#define RZG2L_MPXED_COMMON_PIN_FUNCS(group) \
(PIN_CFG_IOLH_##group | \
PIN_CFG_PUPD | \
@@ -146,6 +154,7 @@
#define SD_CH(off, ch) ((off) + (ch) * 4)
#define ETH_POC(off, ch) ((off) + (ch) * 4)
#define QSPI (0x3008) /* known on RZ/{G2L,G2LC,G2UL,Five} only */
#define OTHER_POC (0x3028) /* known on RZ/G3L only */
#define PVDD_2500 2 /* I/O domain voltage 2.5V */
#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */
@@ -900,7 +909,8 @@ static void rzg2l_rmw_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset,
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs, u32 caps)
static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs,
u32 caps, u8 *mask)
{
if (caps & PIN_CFG_IO_VMC_SD0)
return SD_CH(regs->sd_ch, 0);
@@ -912,6 +922,16 @@ static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs, u32
return ETH_POC(regs->eth_poc, 1);
if (caps & PIN_CFG_IO_VMC_QSPI)
return QSPI;
if (caps & PIN_CFG_OTHER_POC_MASK) {
if (caps & PIN_CFG_PVDD1833_OTH_AWO_POC)
*mask = BIT(0);
else if (caps & PIN_CFG_PVDD1833_OTH_ISO_POC)
*mask = BIT(1);
else
*mask = BIT(2);
return OTHER_POC;
}
return -EINVAL;
}
@@ -920,17 +940,20 @@ static int rzg2l_get_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps
{
const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg;
const struct rzg2l_register_offsets *regs = &hwcfg->regs;
u8 val, mask;
int pwr_reg;
u8 val;
if (caps & PIN_CFG_SOFT_PS)
return pctrl->settings[pin].power_source;
pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps);
pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps, &mask);
if (pwr_reg < 0)
return pwr_reg;
val = readb(pctrl->base + pwr_reg);
if (pwr_reg == OTHER_POC)
val = field_get(mask, val);
switch (val) {
case PVDD_1800:
return 1800;
@@ -948,8 +971,8 @@ static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps
{
const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg;
const struct rzg2l_register_offsets *regs = &hwcfg->regs;
u8 poc_val, val, mask;
int pwr_reg;
u8 val;
if (caps & PIN_CFG_SOFT_PS) {
pctrl->settings[pin].power_source = ps;
@@ -958,25 +981,37 @@ static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps
switch (ps) {
case 1800:
val = PVDD_1800;
poc_val = PVDD_1800;
break;
case 2500:
if (!(caps & (PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1)))
return -EINVAL;
val = PVDD_2500;
poc_val = PVDD_2500;
break;
case 3300:
val = PVDD_3300;
poc_val = PVDD_3300;
break;
default:
return -EINVAL;
}
pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps);
pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps, &mask);
if (pwr_reg < 0)
return pwr_reg;
writeb(val, pctrl->base + pwr_reg);
if (pwr_reg == OTHER_POC) {
scoped_guard(raw_spinlock, &pctrl->lock) {
val = readb(pctrl->base + pwr_reg);
if (poc_val)
val |= mask;
else
val &= ~mask;
writeb(val, pctrl->base + pwr_reg);
}
} else {
writeb(poc_val, pctrl->base + pwr_reg);
}
pctrl->settings[pin].power_source = ps;
return 0;