diff options
| -rw-r--r-- | drivers/pinctrl/renesas/pinctrl-rzg2l.c | 162 |
1 files changed, 108 insertions, 54 deletions
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index c17983aafcf5..6696e32909c3 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -182,9 +182,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 */ @@ -289,12 +286,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, @@ -445,7 +444,85 @@ 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, \ + } + +static const struct rzg2l_pinctrl_ps_desc available_ps[] = { + /* Ethernet I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1, + RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(2500, 2, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1, + RZG2L_IOLH_IDX_2V5), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1, + RZG2L_IOLH_IDX_3V3), + + /* SD I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_IO_VMC_SD0 | PIN_CFG_IO_VMC_SD1 | + PIN_CFG_IO_VMC_SD2, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_IO_VMC_SD0 | PIN_CFG_IO_VMC_SD1 | + PIN_CFG_IO_VMC_SD2, RZG2L_IOLH_IDX_3V3), + + /* QSPI I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_IO_VMC_QSPI, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_IO_VMC_QSPI, RZG2L_IOLH_IDX_3V3), + + /* AWO I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_PVDD1833_OTH_AWO_POC, + RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_PVDD1833_OTH_AWO_POC, + RZG2L_IOLH_IDX_3V3), + + /* ISO I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_PVDD1833_OTH_ISO_POC, + RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_PVDD1833_OTH_ISO_POC, + RZG2L_IOLH_IDX_3V3), + + /* WDTOVF I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_WDTOVF_N_POC, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_WDTOVF_N_POC, RZG2L_IOLH_IDX_3V3), + + /* Software voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 0, PIN_CFG_SOFT_PS, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(2500, 0, PIN_CFG_SOFT_PS, RZG2L_IOLH_IDX_2V5), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_SOFT_PS, 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) \ +{ \ + for (unsigned int i = 0; i < ARRAY_SIZE(available_ps); i++) { \ + if (available_ps[i]._desc_member != _desc_member) \ + continue; \ + \ + if (available_ps[i].caps & _caps) \ + return &available_ps[i]; \ + } \ + \ + return NULL; \ +} + +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, @@ -1126,34 +1203,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) @@ -1212,32 +1281,11 @@ 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 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) - return true; - } - - return false; -} - -static enum rzg2l_iolh_index rzg2l_ps_to_iolh_idx(u16 ps) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(available_ps); i++) { - if (available_ps[i] == ps) - break; - } - - /* - * 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 ? desc->iolh_index : RZG2L_IOLH_IDX_NA; } static u16 rzg2l_iolh_val_to_ua(const struct rzg2l_hwcfg *hwcfg, u32 caps, u8 val) @@ -1622,7 +1670,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; @@ -1818,8 +1870,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); - if (!ret) + if (!rzg2l_ps_to_desc(settings.power_source, cfg)) return -EINVAL; /* Apply power source. */ @@ -1833,7 +1884,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) |
