[PATCH v5 3/5] pinctrl: renesas: rzg2l: Unify the power source handling
Claudiu Beznea <[email protected]>
| Newsgroups | org.kernel.vger.linux-gpio,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc |
|---|---|
| Message-ID | <[email protected]> |
From: Claudiu Beznea <[email protected]> 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 <[email protected]> --- 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