]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
pinctrl: renesas: rzg2l: Add support for selecting power source for {WDT,AWO,ISO}
authorBiju Das <biju.das.jz@bp.renesas.com>
Thu, 30 Apr 2026 09:34:08 +0000 (10:34 +0100)
committerGeert Uytterhoeven <geert+renesas@glider.be>
Mon, 11 May 2026 09:07:07 +0000 (11:07 +0200)
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>
drivers/pinctrl/renesas/pinctrl-rzg2l.c

index ca9d4a3ec73715fd7b67185777b22cf67386e186..7b1bb66d4ff6ff214908dc9271844bbc14e3b5e5 100644 (file)
 #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 | \
 #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;