RE: [PATCH v4 4/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source

From: Biju Das

Date: Sun Jul 12 2026 - 10:55:24 EST


Hi Claudiu,

Thanks for the patch.

> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea+renesas@xxxxxxxxx>
> Sent: 10 July 2026 12:37
> Subject: [PATCH v4 4/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source
>
> From: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx>
>
> The Renesas RZ/G3S I3C pins can be powered at either 1.8V or 1.2V. The pin controller provides a register
> to select between these two options.
> Update the Renesas RZ/G2L pin controller driver to allow selecting the I3C power source on RZ/G3S SoC.
>
> Reviewed-by: Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx>
> Tested-by: Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx>
> ---
>
> Changes in v4:
> - none
>
> Changes in v3:
> - collected tags
>
> Changes in v2:
> - none
>
> drivers/pinctrl/renesas/pinctrl-rzg2l.c | 73 +++++++++++++++++++++++--
> 1 file changed, 68 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> index b52a85066f63..9a0706fea220 100644
> --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> @@ -69,6 +69,7 @@
> #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 PIN_CFG_IO_VMC_I3C BIT(22)
>
> #define RZG2L_SINGLE_PIN BIT_ULL(63) /* Dedicated pin */
> #define RZG2L_VARIABLE_CFG BIT_ULL(62) /* Variable cfg for port pins */
> @@ -186,6 +187,9 @@
> #define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
> #define PVDD_MASK 0x3
>
> +#define PVDD_I3C_1200 1 /* I3C I/O domain voltage 1.2V */
> +#define PVDD_I3C_1800 0 /* I3C I/O domain voltage 1.8V */
> +
> #define PWPR_B0WI BIT(7) /* Bit Write Disable */
> #define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
> #define PWPR_REGWE_A BIT(6) /* PFC and PMC Register Write Enable on RZ/V2H(P) */
> @@ -257,6 +261,7 @@ static const struct pin_config_item renesas_rzv2h_conf_items[] = {
> * @oen: OEN register offset
> * @qspi: QSPI register offset
> * @other_poc: OTHER_POC register offset
> + * @i3c_set: I3C_SET register offset
> */
> struct rzg2l_register_offsets {
> u16 pwpr;
> @@ -265,6 +270,7 @@ struct rzg2l_register_offsets {
> u16 oen;
> u16 qspi;
> u16 other_poc;
> + u16 i3c_set;


> };
>
> /**
> @@ -272,6 +278,7 @@ struct rzg2l_register_offsets {
> * @other_poc_pvdd1833_oth_awo_poc: PVDD1833_OTH_AWO_POC mask
> * @other_poc_pvdd1833_oth_iso_poc: PVDD1833_OTH_ISO_POC mask
> * @other_poc_wdtovf_n_poc: WDTOVF_N_POC mask
> + * @i3c_set_poc: I3C_SET_POC mask
> */
> struct rzg2l_register_masks {
> union {
> @@ -281,6 +288,11 @@ struct rzg2l_register_masks {
> u8 other_poc_pvdd1833_oth_iso_poc;
> u8 other_poc_wdtovf_n_poc;
> };
> +
> + /* RZ/G3S masks */
> + struct {
> + u8 i3c_set_poc;

How this POC is different from Ethernet, SDHI and XSPI POC?
For consistency, can't we handle like others?

Cheers,
Biju

> + };
> };
> };
>
> @@ -391,6 +403,7 @@ struct rzg2l_pinctrl_pin_settings {
> * @oen: Output Enable register cache
> * @other_poc: OTHER_POC register cache
> * @qspi: QSPI registers cache
> + * @i3c_set: I3C_SET register cache
> */
> struct rzg2l_pinctrl_reg_cache {
> u8 *p;
> @@ -409,6 +422,7 @@ struct rzg2l_pinctrl_reg_cache {
> u8 oen;
> u8 other_poc;
> u8 qspi;
> + u8 i3c_set;
> };
>
> struct rzg2l_pinctrl {
> @@ -441,6 +455,7 @@ struct rzg2l_pinctrl { };
>
> static const u16 available_ps[] = { 1800, 2500, 3300 };
> +static const u16 available_i3c_ps[] = { 1200, 1800 };
>
> static u64 rzg2l_pinctrl_get_variable_pin_cfg(struct rzg2l_pinctrl *pctrl,
> u64 pincfg,
> @@ -1101,12 +1116,28 @@ static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs,
> *mask = masks->other_poc_wdtovf_n_poc;
> return 0;
> }
> + if (caps & PIN_CFG_IO_VMC_I3C) {
> + *offset = regs->i3c_set;
> + *mask = masks->i3c_set_poc;
> + return 0;
> + }
>
> return -EINVAL;
> }
>
> static int rzg2l_pwr_reg_val_to_ps(u8 val, u32 caps) {
> + if (caps & PIN_CFG_IO_VMC_I3C) {
> + switch (val) {
> + case PVDD_I3C_1200:
> + return 1200;
> + case PVDD_I3C_1800:
> + return 1800;
> + }
> +
> + return -EINVAL;
> + }
> +
> switch (val) {
> case PVDD_1800:
> return 1800;
> @@ -1121,6 +1152,19 @@ static int rzg2l_pwr_reg_val_to_ps(u8 val, u32 caps)
>
> static int rzg2l_ps_to_pwr_reg_val(u8 *val, u32 ps, u32 caps) {
> + if (caps & PIN_CFG_IO_VMC_I3C) {
> + switch (ps) {
> + case 1200:
> + *val = PVDD_I3C_1200;
> + return 0;
> + case 1800:
> + *val = PVDD_I3C_1800;
> + return 0;
> + }
> +
> + return -EINVAL;
> + }
> +
> switch (ps) {
> case 1800:
> *val = PVDD_1800;
> @@ -1194,12 +1238,21 @@ static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps
> return 0;
> }
>
> -static bool rzg2l_ps_is_supported(u16 ps)
> +static bool rzg2l_ps_is_supported(u16 ps, u32 caps)
> {
> - unsigned int i;
> + unsigned int i, len;
> + const u16 *array;
>
> - for (i = 0; i < ARRAY_SIZE(available_ps); i++) {
> - if (available_ps[i] == ps)
> + if (caps & PIN_CFG_IO_VMC_I3C) {
> + array = available_i3c_ps;
> + len = ARRAY_SIZE(available_i3c_ps);
> + } else {
> + array = available_ps;
> + len = ARRAY_SIZE(available_ps);
> + }
> +
> + for (i = 0; i < len; i++) {
> + if (array[i] == ps)
> return true;
> }
>
> @@ -1800,7 +1853,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
>
> /* Apply power source. */
> if (settings.power_source != pctrl->settings[_pin].power_source) {
> - ret = rzg2l_ps_is_supported(settings.power_source);
> + ret = rzg2l_ps_is_supported(settings.power_source, cfg);
> if (!ret)
> return -EINVAL;
>
> @@ -2498,6 +2551,8 @@ static const struct rzg2l_dedicated_configs rzg3s_dedicated_pins[] = {
> { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x2, 0, PIN_CFG_IEN) },
> { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x2, 1, PIN_CFG_IEN) },
> { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0x6, 0, PIN_CFG_IOLH_A | PIN_CFG_SOFT_PS) },
> + { "I3C_SDA", RZG2L_SINGLE_PIN_PACK(0x9, 0, (PIN_CFG_IEN | PIN_CFG_IO_VMC_I3C)) },
> + { "I3C_SCL", RZG2L_SINGLE_PIN_PACK(0x9, 1, (PIN_CFG_IEN |
> +PIN_CFG_IO_VMC_I3C)) },
> { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x10, 0, (PIN_CFG_IOLH_B | PIN_CFG_IO_VMC_SD0)) },
> { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x10, 1, (PIN_CFG_IOLH_B | PIN_CFG_IEN |
> PIN_CFG_IO_VMC_SD0)) },
> @@ -3717,6 +3772,8 @@ static int rzg2l_pinctrl_suspend_noirq(struct device *dev)
> cache->oen = readb(pctrl->base + pctrl->data->hwcfg->regs.oen);
> if (regs->other_poc)
> cache->other_poc = readb(pctrl->base + regs->other_poc);
> + if (regs->i3c_set)
> + cache->i3c_set = readb(pctrl->base + regs->i3c_set);
>
> if (pctrl->syscon) {
> int ret;
> @@ -3759,6 +3816,8 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev)
> writeb(cache->qspi, pctrl->base + regs->qspi);
> if (regs->other_poc)
> writeb(cache->other_poc, pctrl->base + regs->other_poc);
> + if (regs->i3c_set)
> + writeb(cache->i3c_set, pctrl->base + regs->i3c_set);
>
> raw_spin_lock_irqsave(&pctrl->lock, flags);
> rzg2l_oen_write_with_pwpr(pctrl, cache->oen); @@ -3871,8 +3930,12 @@ static const struct
> rzg2l_hwcfg rzg3s_hwcfg = {
> .pwpr = 0x3000,
> .sd_ch = 0x3004,
> .eth_poc = 0x3010,
> + .i3c_set = 0x301c,
> .oen = 0x3018,
> },
> + .masks = {
> + .i3c_set_poc = BIT(2),
> + },
> .iolh_groupa_ua = {
> /* 1v8 power source */
> [RZG2L_IOLH_IDX_1V8] = 2200, 4400, 9000, 10000,
> --
> 2.43.0
>