Devicetree
 help / color / mirror / Atom feed
* [PATCH v5 0/5]  pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C
@ 2026-08-19 14:35 Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 1/5] pinctrl: renesas: rzg2l: Generalize the power source code Claudiu Beznea
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Claudiu Beznea @ 2026-08-19 14:35 UTC (permalink / raw)
  To: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	prabhakar.mahadev-lad.rj
  Cc: claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Hi,

Series adds pinctrl support for the I3C on Renesas RZ/G3S SoC. For a
clean I3C support, cleanup patches for the pinctrl driver were also
included.

Thank you,
Claudiu

Changes in v5:
- collected tags
- addressed the improvements review comments
- added patch "pinctrl: renesas: rzg2l: Unify the power source handling";
  as a result, patch "  pinctrl: renesas: rzg2l: Add RZ/G3S support for
  selecting the I3C power source" was changed
- dropped device tree patch since it was already applied

Changes in v4:
- dropped patch 1 from v3 as it was already applied

Changes in v3:
- collected tags
- added a fixes patch (patch 1/6)
- dropped already applied patches

Changes in v2:
- collected tags
- dropped patches for configuring I3C standby

Claudiu Beznea (5):
  pinctrl: renesas: rzg2l: Generalize the power source code
  pinctrl: renesas: rzg2l: Drop defines present in struct rzg2l_hwcfg
  pinctrl: renesas: rzg2l: Unify the power source handling
  dt-bindings: pinctrl: renesas,rzg2l-pinctrl: Document the missing I3C
    power source option
  pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C
    power source

 .../pinctrl/renesas,rzg2l-pinctrl.yaml        |   2 +-
 drivers/pinctrl/renesas/pinctrl-rzg2l.c       | 313 ++++++++++++------
 2 files changed, 216 insertions(+), 99 deletions(-)

-- 
2.43.0


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

* [PATCH v5 1/5] pinctrl: renesas: rzg2l: Generalize the power source code
  2026-08-19 14:35 [PATCH v5 0/5] pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C Claudiu Beznea
@ 2026-08-19 14:35 ` Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 2/5] pinctrl: renesas: rzg2l: Drop defines present in struct rzg2l_hwcfg Claudiu Beznea
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Claudiu Beznea @ 2026-08-19 14:35 UTC (permalink / raw)
  To: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	prabhakar.mahadev-lad.rj
  Cc: claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The current functions used to get/set the pin power source check the
OTHER_POC register, which is specific to the RZ/G3L SoC only. To allow the
code to be extended for other power source functionalities (e.g. I3C on
RZ/G3S), generalize the functions used to get/set the pin power source.

For this, introduce the struct rzg2l_register_masks data structure whose
purpose is to store SoC specific register bit masks. The members of this
structure are then used in rzg2l_caps_to_pwr_reg() to retrieve the bitmask
corresponding to a SoC specific power source capability.

The conversion between HW specific power source values and SW specific
power source values is now handled through rzg2l_pwr_reg_val_to_ps() and
rzg2l_ps_to_pwr_reg_val().

Finally, to keep the code generic, the register update in
rzg2l_set_power_source() was changed to a read-modify-write approach to
cover all cases.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---

Changes in v5:
- in function rzg2l_ps_to_pwr_reg_val() return power source register
  value or negative error; due to this, in rzg2l_set_power_source()
  dropped the val local variable and use ret instead; due to this,
  to be able to use ret on register setup, moved the rzg2l_ps_to_pwr_reg_val()
  call after rzg2l_caps_to_pwr_reg()
- dropped the tags

- collected tags

Changes in v4:
- none

Changes in v3:
- collected tags

Changes in v2:
- none

 drivers/pinctrl/renesas/pinctrl-rzg2l.c | 174 +++++++++++++++---------
 1 file changed, 109 insertions(+), 65 deletions(-)

diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index be52d47d77ae..72e0783d5845 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -186,6 +186,7 @@
 #define PVDD_2500		2	/* I/O domain voltage 2.5V */
 #define PVDD_1800		1	/* I/O domain voltage <= 1.8V */
 #define PVDD_3300		0	/* I/O domain voltage >= 3.3V */
+#define PVDD_MASK		0x3
 
 #define PWPR_B0WI		BIT(7)	/* Bit Write Disable */
 #define PWPR_PFCWE		BIT(6)	/* PFC Register Write Enable */
@@ -268,6 +269,23 @@ struct rzg2l_register_offsets {
 	u16 other_poc;
 };
 
+/**
+ * struct rzg2l_register_masks - Masks for different RZ/G2L pinctrl functionalities
+ * @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
+ */
+struct rzg2l_register_masks {
+	union {
+		/* RZ/G3L masks */
+		struct {
+			u8 other_poc_pvdd1833_oth_awo_poc;
+			u8 other_poc_pvdd1833_oth_iso_poc;
+			u8 other_poc_wdtovf_n_poc;
+		};
+	};
+};
+
 /**
  * enum rzg2l_iolh_index - starting indices in IOLH specific arrays
  * @RZG2L_IOLH_IDX_1V8: starting index for 1V8 power source
@@ -288,6 +306,8 @@ enum rzg2l_iolh_index {
 /**
  * struct rzg2l_hwcfg - hardware configuration data structure
  * @regs: hardware specific register offsets
+ * @masks: hardware specific masks for various functionalities available in
+ * the registers described by regs
  * @iolh_groupa_ua: IOLH group A uA specific values
  * @iolh_groupb_ua: IOLH group B uA specific values
  * @iolh_groupc_ua: IOLH group C uA specific values
@@ -301,6 +321,7 @@ enum rzg2l_iolh_index {
  */
 struct rzg2l_hwcfg {
 	const struct rzg2l_register_offsets regs;
+	const struct rzg2l_register_masks masks;
 	u16 iolh_groupa_ua[RZG2L_IOLH_IDX_MAX];
 	u16 iolh_groupb_ua[RZG2L_IOLH_IDX_MAX];
 	u16 iolh_groupc_ua[RZG2L_IOLH_IDX_MAX];
@@ -1047,27 +1068,70 @@ static void rzg2l_rmw_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset,
 }
 
 static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs,
-				 u32 caps, u8 *mask)
+				 const struct rzg2l_register_masks *masks,
+				 u32 caps, u16 *offset, u8 *mask)
 {
-	if (caps & PIN_CFG_IO_VMC_SD0)
-		return SD_CH(regs->sd_ch, 0);
-	if (caps & PIN_CFG_IO_VMC_SD1)
-		return SD_CH(regs->sd_ch, 1);
-	if (caps & PIN_CFG_IO_VMC_ETH0)
-		return ETH_POC(regs->eth_poc, 0);
-	if (caps & PIN_CFG_IO_VMC_ETH1)
-		return ETH_POC(regs->eth_poc, 1);
-	if (caps & PIN_CFG_IO_VMC_QSPI)
-		return QSPI;
+	*mask = PVDD_MASK;
+
+	if (caps & PIN_CFG_IO_VMC_SD0) {
+		*offset = SD_CH(regs->sd_ch, 0);
+		return 0;
+	}
+	if (caps & PIN_CFG_IO_VMC_SD1) {
+		*offset = SD_CH(regs->sd_ch, 1);
+		return 0;
+	}
+	if (caps & PIN_CFG_IO_VMC_ETH0) {
+		*offset = ETH_POC(regs->eth_poc, 0);
+		return 0;
+	}
+	if (caps & PIN_CFG_IO_VMC_ETH1) {
+		*offset = ETH_POC(regs->eth_poc, 1);
+		return 0;
+	}
+	if (caps & PIN_CFG_IO_VMC_QSPI) {
+		*offset = regs->qspi;
+		return 0;
+	}
 	if (caps & PIN_CFG_OTHER_POC_MASK) {
+		*offset = regs->other_poc;
 		if (caps & PIN_CFG_PVDD1833_OTH_AWO_POC)
-			*mask = BIT(0);
+			*mask = masks->other_poc_pvdd1833_oth_awo_poc;
 		else if (caps & PIN_CFG_PVDD1833_OTH_ISO_POC)
-			*mask = BIT(1);
+			*mask = masks->other_poc_pvdd1833_oth_iso_poc;
 		else
-			*mask = BIT(2);
+			*mask = masks->other_poc_wdtovf_n_poc;
+		return 0;
+	}
 
-		return OTHER_POC;
+	return -EINVAL;
+}
+
+static int rzg2l_pwr_reg_val_to_ps(u8 val, u32 caps)
+{
+	switch (val) {
+	case PVDD_1800:
+		return 1800;
+	case PVDD_2500:
+		return 2500;
+	case PVDD_3300:
+		return 3300;
+	}
+
+	return -EINVAL;
+}
+
+static int rzg2l_ps_to_pwr_reg_val(u32 ps, u32 caps)
+{
+	switch (ps) {
+	case 1800:
+		return PVDD_1800;
+	case 2500:
+		if (!(caps & (PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1)))
+			return -EINVAL;
+		return PVDD_2500;
+	case 3300:
+		return PVDD_3300;
 	}
 
 	return -EINVAL;
@@ -1077,76 +1141,51 @@ 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;
+	const struct rzg2l_register_masks *masks = &hwcfg->masks;
+	u8 mask, val;
+	u16 offset;
+	int ret;
 
 	if (caps & PIN_CFG_SOFT_PS)
 		return pctrl->settings[pin].power_source;
 
-	pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps, &mask);
-	if (pwr_reg < 0)
-		return pwr_reg;
+	ret = rzg2l_caps_to_pwr_reg(regs, masks, caps, &offset, &mask);
+	if (ret)
+		return ret;
 
-	val = readb(pctrl->base + pwr_reg);
-	if (pwr_reg == OTHER_POC)
-		val = field_get(mask, val);
+	val = readb(pctrl->base + offset);
 
-	switch (val) {
-	case PVDD_1800:
-		return 1800;
-	case PVDD_2500:
-		return 2500;
-	case PVDD_3300:
-		return 3300;
-	default:
-		/* Should not happen. */
-		return -EINVAL;
-	}
+	return rzg2l_pwr_reg_val_to_ps(field_get(mask, val), caps);
 }
 
 static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps, u32 ps)
 {
 	const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg;
 	const struct rzg2l_register_offsets *regs = &hwcfg->regs;
-	u8 poc_val, val, mask;
-	int pwr_reg;
+	const struct rzg2l_register_masks *masks = &hwcfg->masks;
+	u16 offset;
+	u8 mask;
+	int ret;
 
 	if (caps & PIN_CFG_SOFT_PS) {
 		pctrl->settings[pin].power_source = ps;
 		return 0;
 	}
 
-	switch (ps) {
-	case 1800:
-		poc_val = PVDD_1800;
-		break;
-	case 2500:
-		if (!(caps & (PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1)))
-			return -EINVAL;
-		poc_val = PVDD_2500;
-		break;
-	case 3300:
-		poc_val = PVDD_3300;
-		break;
-	default:
-		return -EINVAL;
-	}
+	ret = rzg2l_caps_to_pwr_reg(regs, masks, caps, &offset, &mask);
+	if (ret)
+		return ret;
 
-	pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps, &mask);
-	if (pwr_reg < 0)
-		return pwr_reg;
+	ret = rzg2l_ps_to_pwr_reg_val(ps, caps);
+	if (ret < 0)
+		return ret;
 
-	if (pwr_reg == OTHER_POC) {
-		scoped_guard(raw_spinlock_irqsave, &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);
+	scoped_guard(raw_spinlock_irqsave, &pctrl->lock) {
+		u8 tmp = readb(pctrl->base + offset);
+
+		tmp &= ~mask;
+		tmp |= field_prep(mask, ret);
+		writeb(tmp, pctrl->base + offset);
 	}
 
 	pctrl->settings[pin].power_source = ps;
@@ -3795,6 +3834,11 @@ static const struct rzg2l_hwcfg rzg3l_hwcfg = {
 		.oen = 0x3018,
 		.other_poc = OTHER_POC,
 	},
+	.masks = {
+		.other_poc_pvdd1833_oth_awo_poc = BIT(0),
+		.other_poc_pvdd1833_oth_iso_poc = BIT(1),
+		.other_poc_wdtovf_n_poc = BIT(2),
+	},
 	.iolh_groupa_ua = {
 		/* 1v8 power source */
 		[RZG2L_IOLH_IDX_1V8] = 2200, 4400, 9000, 10000,
-- 
2.43.0


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

* [PATCH v5 2/5] pinctrl: renesas: rzg2l: Drop defines present in struct rzg2l_hwcfg
  2026-08-19 14:35 [PATCH v5 0/5] pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 1/5] pinctrl: renesas: rzg2l: Generalize the power source code Claudiu Beznea
@ 2026-08-19 14:35 ` Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling Claudiu Beznea
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Claudiu Beznea @ 2026-08-19 14:35 UTC (permalink / raw)
  To: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	prabhakar.mahadev-lad.rj
  Cc: claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea, Wolfram Sang

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Drop the QSPI and OTHER_POC register defines, which are SoC specific and
accessible through struct rzg2l_hwcfg::{qspi, other_poc}. While at it
move the assignement of rzg2l_hwcfg->regs->qspi upper to have the
initializations as sorted (by offsets) as possible.

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---

Changes in v5:
- collected tags

Changes in v4:
- none

Changes in v3:
- updated patch description
- collected tags

Changes in v2:
- none

 drivers/pinctrl/renesas/pinctrl-rzg2l.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 72e0783d5845..9c935dc47555 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -180,8 +180,6 @@
 #define SMT(off)		(0x3400 + (off) * 8)
 #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 */
@@ -3813,9 +3811,9 @@ static const struct rzg2l_hwcfg rzg2l_hwcfg = {
 	.regs = {
 		.pwpr = 0x3014,
 		.sd_ch = 0x3000,
+		.qspi = 0x3008,
 		.eth_poc = 0x300c,
 		.oen = 0x3018,
-		.qspi = QSPI,
 	},
 	.iolh_groupa_ua = {
 		/* 3v3 power source */
@@ -3832,7 +3830,7 @@ static const struct rzg2l_hwcfg rzg3l_hwcfg = {
 		.sd_ch = 0x3004,
 		.eth_poc = 0x3010,
 		.oen = 0x3018,
-		.other_poc = OTHER_POC,
+		.other_poc = 0x3028,
 	},
 	.masks = {
 		.other_poc_pvdd1833_oth_awo_poc = BIT(0),
-- 
2.43.0


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

* [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling
  2026-08-19 14:35 [PATCH v5 0/5] pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 1/5] pinctrl: renesas: rzg2l: Generalize the power source code Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 2/5] pinctrl: renesas: rzg2l: Drop defines present in struct rzg2l_hwcfg Claudiu Beznea
@ 2026-08-19 14:35 ` Claudiu Beznea
  2026-08-19 14:49   ` sashiko-bot
  2026-08-19 14:35 ` [PATCH v5 4/5] dt-bindings: pinctrl: renesas,rzg2l-pinctrl: Document the missing I3C power source option Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source Claudiu Beznea
  4 siblings, 1 reply; 8+ messages in thread
From: Claudiu Beznea @ 2026-08-19 14:35 UTC (permalink / raw)
  To: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	prabhakar.mahadev-lad.rj
  Cc: claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The previous code handled power sources using a mixture of power
source specific definitions and lookups in the available_ps[] array.
Unify the power source handling by introducing
struct rzg2l_pinctrl_ps_desc, whose purpose is to describe a power
source through its power source value, associated register value,
associated capabilities (e.g. Ethernet), and associated IOLH index.

Introduce two new functions, rzg2l_ps_to_desc() and
rzg2l_pwr_reg_val_to_desc(), using the
RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC() macro, as their
implementations are similar.

These functions retrieve a power source descriptor based on either a
power source value or a power source register value. Other functions
that need to perform power source specific operations can call them to
retrieve the corresponding power source descriptor.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---

Changes in v5:
- none, this patch is new

 drivers/pinctrl/renesas/pinctrl-rzg2l.c | 141 ++++++++++++++++--------
 1 file changed, 93 insertions(+), 48 deletions(-)

diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 9c935dc47555..6329742fda94 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -181,9 +181,6 @@
 #define SD_CH(off, ch)		((off) + (ch) * 4)
 #define ETH_POC(off, ch)	((off) + (ch) * 4)
 
-#define PVDD_2500		2	/* I/O domain voltage 2.5V */
-#define PVDD_1800		1	/* I/O domain voltage <= 1.8V */
-#define PVDD_3300		0	/* I/O domain voltage >= 3.3V */
 #define PVDD_MASK		0x3
 
 #define PWPR_B0WI		BIT(7)	/* Bit Write Disable */
@@ -286,12 +283,14 @@ struct rzg2l_register_masks {
 
 /**
  * enum rzg2l_iolh_index - starting indices in IOLH specific arrays
+ * @RZG2L_IOLH_IDX_NA: index N/A (to be used for error checking)
  * @RZG2L_IOLH_IDX_1V8: starting index for 1V8 power source
  * @RZG2L_IOLH_IDX_2V5: starting index for 2V5 power source
  * @RZG2L_IOLH_IDX_3V3: starting index for 3V3 power source
  * @RZG2L_IOLH_IDX_MAX: maximum index
  */
 enum rzg2l_iolh_index {
+	RZG2L_IOLH_IDX_NA = -1,
 	RZG2L_IOLH_IDX_1V8 = 0,
 	RZG2L_IOLH_IDX_2V5 = 4,
 	RZG2L_IOLH_IDX_3V3 = 8,
@@ -440,7 +439,65 @@ struct rzg2l_pinctrl {
 	u32				clone_offset;
 };
 
-static const u16 available_ps[] = { 1800, 2500, 3300 };
+/**
+ * struct rzg2l_pinctrl_ps_desc - RZ/G2L power source descriptor
+ * @caps: Capabilities that applies to the power source
+ * @iolh_index: IOLH index
+ * @ps: Power source value
+ * @pwr_reg_val: Power source register value
+ */
+struct rzg2l_pinctrl_ps_desc {
+	u32 caps;
+	enum rzg2l_iolh_index iolh_index;
+	u16 ps;
+	u16 pwr_reg_val;
+};
+
+#define RZG2L_PINCTRL_PS_DESC(_ps, _pwr_reg_val, _caps, _iolh_index) \
+	{ \
+		.ps = _ps, \
+		.pwr_reg_val = _pwr_reg_val, \
+		.caps = _caps, \
+		.iolh_index = _iolh_index, \
+	}
+
+/* Keep the entries with .caps set in the first positions. */
+static const struct rzg2l_pinctrl_ps_desc available_ps[] = {
+	/* Ethernet I/O domain voltage 2.5V */
+	RZG2L_PINCTRL_PS_DESC(2500, 2, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1,
+			      RZG2L_IOLH_IDX_2V5),
+	/* I/O domain voltage 1.8V */
+	RZG2L_PINCTRL_PS_DESC(1800, 1, 0, RZG2L_IOLH_IDX_1V8),
+	/* I/O domain voltage 3.3V */
+	RZG2L_PINCTRL_PS_DESC(3300, 0, 0, RZG2L_IOLH_IDX_3V3),
+};
+
+#define RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(_name, _desc_member, _caps)	\
+static const struct rzg2l_pinctrl_ps_desc *_name(u16 _desc_member, u32 _caps)	\
+{										\
+	const struct rzg2l_pinctrl_ps_desc *desc = NULL;			\
+										\
+	for (unsigned int i = 0; i < ARRAY_SIZE(available_ps); i++) {		\
+		if (available_ps[i]._desc_member == _desc_member) {		\
+			if (available_ps[i].caps) {				\
+				if (available_ps[i].caps & caps) {		\
+					desc = &available_ps[i];		\
+					break;					\
+				} else {					\
+					continue;				\
+				}						\
+			} else {						\
+				desc = &available_ps[i];			\
+				break;						\
+			}							\
+		}								\
+	}									\
+										\
+	return desc;								\
+}
+
+RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(rzg2l_ps_to_desc, ps, caps)
+RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(rzg2l_pwr_reg_val_to_desc, pwr_reg_val, caps)
 
 static u64 rzg2l_pinctrl_get_variable_pin_cfg(struct rzg2l_pinctrl *pctrl,
 					      u64 pincfg,
@@ -1105,34 +1162,26 @@ static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs,
 	return -EINVAL;
 }
 
-static int rzg2l_pwr_reg_val_to_ps(u8 val, u32 caps)
+static int rzg2l_pwr_reg_val_to_ps(u16 pwr_reg_val, u32 caps)
 {
-	switch (val) {
-	case PVDD_1800:
-		return 1800;
-	case PVDD_2500:
-		return 2500;
-	case PVDD_3300:
-		return 3300;
-	}
+	const struct rzg2l_pinctrl_ps_desc *desc;
 
-	return -EINVAL;
+	desc = rzg2l_pwr_reg_val_to_desc(pwr_reg_val, caps);
+	if (!desc)
+		return -EINVAL;
+
+	return desc->ps;
 }
 
-static int rzg2l_ps_to_pwr_reg_val(u32 ps, u32 caps)
+static int rzg2l_ps_to_pwr_reg_val(u16 ps, u32 caps)
 {
-	switch (ps) {
-	case 1800:
-		return PVDD_1800;
-	case 2500:
-		if (!(caps & (PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1)))
-			return -EINVAL;
-		return PVDD_2500;
-	case 3300:
-		return PVDD_3300;
-	}
+	const struct rzg2l_pinctrl_ps_desc *desc;
 
-	return -EINVAL;
+	desc = rzg2l_ps_to_desc(ps, caps);
+	if (!desc)
+		return -EINVAL;
+
+	return desc->pwr_reg_val;
 }
 
 static int rzg2l_get_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps)
@@ -1191,32 +1240,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;
+	const struct rzg2l_pinctrl_ps_desc *desc = rzg2l_ps_to_desc(ps, caps);
 
-	for (i = 0; i < ARRAY_SIZE(available_ps); i++) {
-		if (available_ps[i] == ps)
-			return true;
-	}
-
-	return false;
+	return !!desc;
 }
 
-static enum rzg2l_iolh_index rzg2l_ps_to_iolh_idx(u16 ps)
+static enum rzg2l_iolh_index rzg2l_ps_to_iolh_idx(u16 ps, u32 caps)
 {
-	unsigned int i;
+	const struct rzg2l_pinctrl_ps_desc *desc = rzg2l_ps_to_desc(ps, caps);
 
-	for (i = 0; i < ARRAY_SIZE(available_ps); i++) {
-		if (available_ps[i] == ps)
-			break;
-	}
+	if (!desc)
+		return RZG2L_IOLH_IDX_NA;
 
-	/*
-	 * We multiply with RZG2L_IOLH_MAX_DS_ENTRIES as we have
-	 * RZG2L_IOLH_MAX_DS_ENTRIES DS values per power source
-	 */
-	return i * RZG2L_IOLH_MAX_DS_ENTRIES;
+	return desc->iolh_index;
 }
 
 static u16 rzg2l_iolh_val_to_ua(const struct rzg2l_hwcfg *hwcfg, u32 caps, u8 val)
@@ -1601,7 +1639,11 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev,
 		ret = rzg2l_get_power_source(pctrl, _pin, cfg);
 		if (ret < 0)
 			return ret;
-		iolh_idx = rzg2l_ps_to_iolh_idx(ret);
+
+		iolh_idx = rzg2l_ps_to_iolh_idx(ret, cfg);
+		if (iolh_idx == RZG2L_IOLH_IDX_NA)
+			return -EINVAL;
+
 		val = rzg2l_read_pin_config(pctrl, IOLH(off), bit, IOLH_MASK);
 		arg = rzg2l_iolh_val_to_ua(hwcfg, cfg, iolh_idx + val);
 		break;
@@ -1797,7 +1839,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;
 
@@ -1812,7 +1854,10 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
 		enum rzg2l_iolh_index iolh_idx;
 		int val;
 
-		iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source);
+		iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source, cfg);
+		if (iolh_idx == RZG2L_IOLH_IDX_NA)
+			return -EINVAL;
+
 		ret = rzg2l_ds_is_supported(pctrl, cfg, iolh_idx,
 					    settings.drive_strength_ua);
 		if (!ret)
-- 
2.43.0


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

* [PATCH v5 4/5] dt-bindings: pinctrl: renesas,rzg2l-pinctrl: Document the missing I3C power source option
  2026-08-19 14:35 [PATCH v5 0/5] pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C Claudiu Beznea
                   ` (2 preceding siblings ...)
  2026-08-19 14:35 ` [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling Claudiu Beznea
@ 2026-08-19 14:35 ` Claudiu Beznea
  2026-08-19 14:35 ` [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source Claudiu Beznea
  4 siblings, 0 replies; 8+ messages in thread
From: Claudiu Beznea @ 2026-08-19 14:35 UTC (permalink / raw)
  To: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	prabhakar.mahadev-lad.rj
  Cc: claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea, Conor Dooley, Wolfram Sang

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The I3C pins on the Renesas RZ/G3S SoC can be powered at either 1.2V or
1.8V. Document the missing 1.2V power source option.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---

Changes in v5:
- collected tags

Changes in v4:
- none

Changes in v3:
- collected tags

Changes in v2:
- collected tags

 .../devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
index fb1fe1ea759f..32864c9add4a 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
@@ -129,7 +129,7 @@ additionalProperties:
           enum: [ 33, 50, 66, 100 ]
         power-source:
           description: I/O voltage in millivolt.
-          enum: [ 1800, 2500, 3300 ]
+          enum: [ 1200, 1800, 2500, 3300 ]
         slew-rate: true
         gpio-hog: true
         gpios: true
-- 
2.43.0


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

* [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source
  2026-08-19 14:35 [PATCH v5 0/5] pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C Claudiu Beznea
                   ` (3 preceding siblings ...)
  2026-08-19 14:35 ` [PATCH v5 4/5] dt-bindings: pinctrl: renesas,rzg2l-pinctrl: Document the missing I3C power source option Claudiu Beznea
@ 2026-08-19 14:35 ` Claudiu Beznea
  2026-08-19 14:49   ` sashiko-bot
  4 siblings, 1 reply; 8+ messages in thread
From: Claudiu Beznea @ 2026-08-19 14:35 UTC (permalink / raw)
  To: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	prabhakar.mahadev-lad.rj
  Cc: claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

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.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---

Changes in v5:
- due to patch 3 from this series:
-- dropped the definitions for PVDD_I3C_1200, PVDD_I3C_1800
-- dropped available_i3c_ps[] array and fill everything in available_ps[]
-- dropped the adjustments from rzg2l_pwr_reg_val_to_ps() and
   rzg2l_ps_to_pwr_reg_val(), rzg2l_ps_is_supported() and
   rzg2l_pinctrl_pinconf_set()
-- dropped the tags

Changes in v4:
- none

Changes in v3:
- collected tags

Changes in v2:
- none

 drivers/pinctrl/renesas/pinctrl-rzg2l.c | 30 +++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 6329742fda94..4866896fff78 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 */
@@ -254,6 +255,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;
@@ -262,6 +264,7 @@ struct rzg2l_register_offsets {
 	u16 oen;
 	u16 qspi;
 	u16 other_poc;
+	u16 i3c_set;
 };
 
 /**
@@ -269,6 +272,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 {
@@ -278,6 +282,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;
+		};
 	};
 };
 
@@ -390,6 +399,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;
@@ -408,6 +418,7 @@ struct rzg2l_pinctrl_reg_cache {
 	u8	oen;
 	u8	other_poc;
 	u8	qspi;
+	u8	i3c_set;
 };
 
 struct rzg2l_pinctrl {
@@ -463,6 +474,10 @@ struct rzg2l_pinctrl_ps_desc {
 
 /* Keep the entries with .caps set in the first positions. */
 static const struct rzg2l_pinctrl_ps_desc available_ps[] = {
+	/* I3C I/O domain voltage 1.2V */
+	RZG2L_PINCTRL_PS_DESC(1200, 1, PIN_CFG_IO_VMC_I3C, RZG2L_IOLH_IDX_NA),
+	/* I3C I/O domain voltage 1.8V */
+	RZG2L_PINCTRL_PS_DESC(1800, 0, PIN_CFG_IO_VMC_I3C, RZG2L_IOLH_IDX_NA),
 	/* Ethernet I/O domain voltage 2.5V */
 	RZG2L_PINCTRL_PS_DESC(2500, 2, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1,
 			      RZG2L_IOLH_IDX_2V5),
@@ -1158,6 +1173,11 @@ 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;
 }
@@ -2540,6 +2560,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)) },
@@ -3759,6 +3781,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;
@@ -3801,6 +3825,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);
@@ -3913,8 +3939,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


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

* Re: [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling
  2026-08-19 14:35 ` [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling Claudiu Beznea
@ 2026-08-19 14:49   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-08-19 14:49 UTC (permalink / raw)
  To: Claudiu Beznea; +Cc: wsa+renesas, devicetree, conor+dt, robh

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Regression preventing software-configured (`PIN_CFG_SOFT_PS`) pins from using a 2.5V power source.
- [Medium] Wildcard capability matching in `RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC` can cause silent hardware misconfiguration.
- [Low] Macro hygiene violation in `RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC` forces callers to use a specific identifier.

Pre-existing issues:
- [High] Drive strength hardware register (`IOLH`) is not updated when the pin's power source changes.
--

--- Patch [3]: [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling ---
commit 359b67b0750f9cab682964830c50121ec1ab0ad9
Author: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Subject: pinctrl: renesas: rzg2l: Unify the power source handling

The previous code handled power sources using a mixture of power
source specific definitions and lookups in the available_ps[] array.
Unify the power source handling by introducing
struct rzg2l_pinctrl_ps_desc.

> diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> index 9c935dc475557..bab7bd73a4328 100644
> --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
[ ... ]
> @@ -440,7 +439,65 @@ struct rzg2l_pinctrl {
>  	u32				clone_offset;
>  };
>  
[ ... ]
> +#define RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(_name, _desc_member, _caps)	\
> +static const struct rzg2l_pinctrl_ps_desc *_name(u16 _desc_member, u32 _caps)	\
> +{										\
> +	const struct rzg2l_pinctrl_ps_desc *desc = NULL;			\
> +										\
> +	for (unsigned int i = 0; i < ARRAY_SIZE(available_ps); i++) {		\
> +		if (available_ps[i]._desc_member == _desc_member) {		\
> +			if (available_ps[i].caps) {				\
> +				if (available_ps[i].caps & caps) {		\

[Severity: Low]
This isn't a bug, but does this use the wrong variable? The macro takes
_caps as a parameter, but caps is used here. Will this cause compilation
failures if callers use a different variable name?

> +					desc = &available_ps[i];		\
> +					break;					\
> +				} else {					\
> +					continue;				\
> +				}						\
> +			} else {						\
> +				desc = &available_ps[i];			\
> +				break;						\

[Severity: Medium]
Does this else block act as a wildcard for capabilities equal to 0? If a
caller requests an unsupported voltage for a restricted domain (like an
anticipated I3C domain that does not support 3.3V), will the lookup
falsely match the generic descriptor and return its register value
(e.g., 0)? Could this silently misconfigure the hardware to an incorrect
voltage instead of safely returning -EINVAL?

> +			}							\
> +		}								\
> +	}									\
> +										\
> +	return desc;								\
> +}
[ ... ]
> @@ -1797,7 +1839,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;

[Severity: High]
Does this check inadvertently break pins configured via software
(PIN_CFG_SOFT_PS) that require a 2.5V power source?

The only available 2.5V descriptor explicitly requires Ethernet capabilities:

    RZG2L_PINCTRL_PS_DESC(2500, 2, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1,
                          RZG2L_IOLH_IDX_2V5)

Would a PIN_CFG_SOFT_PS pin requesting 2500 fail this capability check and
be rejected with -EINVAL, breaking backward compatibility?

[ ... ]
> @@ -1812,7 +1854,10 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
>  		enum rzg2l_iolh_index iolh_idx;
>  		int val;
>  
> -		iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source);
> +		iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source, cfg);
> +		if (iolh_idx == RZG2L_IOLH_IDX_NA)
> +			return -EINVAL;
> +
>  		ret = rzg2l_ds_is_supported(pctrl, cfg, iolh_idx,
>  					    settings.drive_strength_ua);
>  		if (!ret)

[Severity: High]
This is a pre-existing issue, but is the drive strength hardware register
(IOLH) left out of sync if only the power source changes?

Looking at rzg2l_pinctrl_pinconf_set(), the hardware register update is
skipped if the requested drive strength has not changed:

    if (settings.drive_strength_ua != pctrl->settings[_pin].drive_strength_ua) {
        ...
        iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source, cfg);

Because the physical mapping between the IOLH register index and the actual
microamp output depends heavily on the selected power source, will keeping
the old IOLH index at a new voltage yield an incorrect drive strength?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260819143553.2478984-1-claudiu.beznea+renesas@tuxon.dev?part=3

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

* Re: [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source
  2026-08-19 14:35 ` [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source Claudiu Beznea
@ 2026-08-19 14:49   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-08-19 14:49 UTC (permalink / raw)
  To: Claudiu Beznea; +Cc: wsa+renesas, robh, devicetree, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Requesting an unsupported 3.3V power source for an I3C pin is silently accepted and misconfigures the hardware to 1.8V.
--

--- Patch [5]: [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source ---
commit 0ea5cf7346d186b66e9a09433c5157725bc0936d
Author: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source

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.

> diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> index bab7bd73a4328..41ca18aeeb0fa 100644
> --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
[ ... ]
> @@ -463,6 +474,10 @@ struct rzg2l_pinctrl_ps_desc {
>  
>  /* Keep the entries with .caps set in the first positions. */
>  static const struct rzg2l_pinctrl_ps_desc available_ps[] = {
> +	/* I3C I/O domain voltage 1.2V */
> +	RZG2L_PINCTRL_PS_DESC(1200, 1, PIN_CFG_IO_VMC_I3C, RZG2L_IOLH_IDX_NA),
> +	/* I3C I/O domain voltage 1.8V */
> +	RZG2L_PINCTRL_PS_DESC(1800, 0, PIN_CFG_IO_VMC_I3C, RZG2L_IOLH_IDX_NA),
>  	/* Ethernet I/O domain voltage 2.5V */
>  	RZG2L_PINCTRL_PS_DESC(2500, 2, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1,
>  			      RZG2L_IOLH_IDX_2V5),
>  	/* I/O domain voltage 1.8V */
>  	RZG2L_PINCTRL_PS_DESC(1800, 1, 0, RZG2L_IOLH_IDX_1V8),
>  	/* I/O domain voltage 3.3V */
>  	RZG2L_PINCTRL_PS_DESC(3300, 0, 0, RZG2L_IOLH_IDX_3V3),
>  };

[Severity: Medium]
If a device tree incorrectly requests a 3.3V power source for an I3C pin,
will this silently accept the configuration and set the hardware to 1.8V
instead of returning an error?

Looking at RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(), it treats entries
with .caps == 0 as wildcards:

drivers/pinctrl/renesas/pinctrl-rzg2l.c:RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC() {
	...
			if (available_ps[i].caps) {
				if (available_ps[i].caps & _caps) {
					desc = &available_ps[i];
					break;
				}
			} else {
				desc = &available_ps[i];
				break;
			}
	...
}

Since the 3.3V entry above has .caps = 0, it seems rzg2l_ps_to_desc() would
match it for an I3C pin requesting 3300mV, returning pwr_reg_val = 0, which
configures the hardware to 1.8V.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260819143553.2478984-1-claudiu.beznea+renesas@tuxon.dev?part=5

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

end of thread, other threads:[~2026-08-19 14:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-19 14:35 [PATCH v5 0/5] pinctrl: renesas: rzg2l: Add support for RZ/G3S I3C Claudiu Beznea
2026-08-19 14:35 ` [PATCH v5 1/5] pinctrl: renesas: rzg2l: Generalize the power source code Claudiu Beznea
2026-08-19 14:35 ` [PATCH v5 2/5] pinctrl: renesas: rzg2l: Drop defines present in struct rzg2l_hwcfg Claudiu Beznea
2026-08-19 14:35 ` [PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling Claudiu Beznea
2026-08-19 14:49   ` sashiko-bot
2026-08-19 14:35 ` [PATCH v5 4/5] dt-bindings: pinctrl: renesas,rzg2l-pinctrl: Document the missing I3C power source option Claudiu Beznea
2026-08-19 14:35 ` [PATCH v5 5/5] pinctrl: renesas: rzg2l: Add RZ/G3S support for selecting the I3C power source Claudiu Beznea
2026-08-19 14:49   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox