[PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling
From: Claudiu Beznea
Date: Wed Aug 19 2026 - 10:41:47 EST
From: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx>
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@xxxxxxxxxxxxxx>
---
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