[U-Boot] [PATCH 1/2] pinctrl: rmobile: Add Renesas RCar pincontrol driver

Add pinconf support to the PFC driver, so that it can handle DT props bias-disable, bias-pull-up, bias-pull-down, drive-strength and power-source.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org --- drivers/pinctrl/renesas/pfc.c | 176 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+)
diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c index 63e2eeb449..53139d7a26 100644 --- a/drivers/pinctrl/renesas/pfc.c +++ b/drivers/pinctrl/renesas/pfc.c @@ -477,6 +477,177 @@ static int sh_pfc_pinctrl_group_set(struct udevice *dev, unsigned group_selector done: return ret; } +#if CONFIG_IS_ENABLED(PINCONF) +static const struct pinconf_param sh_pfc_pinconf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, + { "power-source", PIN_CONFIG_POWER_SOURCE, 3300 }, +}; + +static void __iomem * +sh_pfc_pinconf_find_drive_strength_reg(struct sh_pfc *pfc, unsigned int pin, + unsigned int *offset, unsigned int *size) +{ + const struct pinmux_drive_reg_field *field; + const struct pinmux_drive_reg *reg; + unsigned int i; + + for (reg = pfc->info->drive_regs; reg->reg; ++reg) { + for (i = 0; i < ARRAY_SIZE(reg->fields); ++i) { + field = ®->fields[i]; + + if (field->size && field->pin == pin) { + *offset = field->offset; + *size = field->size; + + return (void __iomem *)(uintptr_t)reg->reg; + } + } + } + + return NULL; +} + +static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc, + unsigned int pin, u16 strength) +{ + unsigned int offset; + unsigned int size; + unsigned int step; + void __iomem *reg; + u32 val; + + reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size); + if (!reg) + return -EINVAL; + + step = size == 2 ? 6 : 3; + + if (strength < step || strength > 24) + return -EINVAL; + + /* Convert the value from mA based on a full drive strength value of + * 24mA. We can make the full value configurable later if needed. + */ + strength = strength / step - 1; + + val = sh_pfc_read_raw_reg(reg, 32); + val &= ~GENMASK(offset + size - 1, offset); + val |= strength << offset; + + sh_pfc_write_raw_reg(reg, 32, val); + + return 0; +} + +/* Check whether the requested parameter is supported for a pin. */ +static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin, + unsigned int param) +{ + int idx = sh_pfc_get_pin_index(pfc, _pin); + const struct sh_pfc_pin *pin = &pfc->info->pins[idx]; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + return pin->configs & + (SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN); + + case PIN_CONFIG_BIAS_PULL_UP: + return pin->configs & SH_PFC_PIN_CFG_PULL_UP; + + case PIN_CONFIG_BIAS_PULL_DOWN: + return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN; + + case PIN_CONFIG_DRIVE_STRENGTH: + return pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH; + + case PIN_CONFIG_POWER_SOURCE: + return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE; + + default: + return false; + } +} + +static int sh_pfc_pinconf_set(struct sh_pfc_pinctrl *pmx, unsigned _pin, + unsigned int param, unsigned int arg) +{ + struct sh_pfc *pfc = pmx->pfc; + void __iomem *pocctrl; + u32 addr, val; + int bit, ret; + + if (!sh_pfc_pinconf_validate(pfc, _pin, param)) + return -ENOTSUPP; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_DISABLE: + if (!pfc->info->ops || !pfc->info->ops->set_bias) + return -ENOTSUPP; + + pfc->info->ops->set_bias(pfc, _pin, param); + + break; + + case PIN_CONFIG_DRIVE_STRENGTH: + ret = sh_pfc_pinconf_set_drive_strength(pfc, _pin, arg); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_POWER_SOURCE: + if (!pfc->info->ops || !pfc->info->ops->pin_to_pocctrl) + return -ENOTSUPP; + + bit = pfc->info->ops->pin_to_pocctrl(pfc, _pin, &addr); + if (bit < 0) { + printf("invalid pin %#x", _pin); + return bit; + } + + if (arg != 1800 && arg != 3300) + return -EINVAL; + + pocctrl = (void __iomem *)(uintptr_t)addr; + + val = sh_pfc_read_raw_reg(pocctrl, 32); + if (arg == 3300) + val |= BIT(bit); + else + val &= ~BIT(bit); + sh_pfc_write_raw_reg(pocctrl, 32, val); + + break; + + default: + return -ENOTSUPP; + } + + return 0; +} + + +static int sh_pfc_pinconf_group_set(struct udevice *dev, + unsigned int group_selector, + unsigned int param, unsigned int arg) +{ + struct sh_pfc_pinctrl_priv *priv = dev_get_priv(dev); + struct sh_pfc_pinctrl *pmx = &priv->pmx; + struct sh_pfc *pfc = &priv->pfc; + const struct sh_pfc_pin_group *grp = &pfc->info->groups[group_selector]; + unsigned int i; + + for (i = 0; i < grp->nr_pins; i++) + sh_pfc_pinconf_set(pmx, grp->pins[i], param, arg); + + return 0; +} +#endif
static struct pinctrl_ops sh_pfc_pinctrl_ops = { .get_pins_count = sh_pfc_pinctrl_get_pins_count, @@ -486,6 +657,11 @@ static struct pinctrl_ops sh_pfc_pinctrl_ops = { .get_functions_count = sh_pfc_pinctrl_get_functions_count, .get_function_name = sh_pfc_pinctrl_get_function_name,
+#if CONFIG_IS_ENABLED(PINCONF) + .pinconf_num_params = ARRAY_SIZE(sh_pfc_pinconf_params), + .pinconf_params = sh_pfc_pinconf_params, + .pinconf_group_set = sh_pfc_pinconf_group_set, +#endif .pinmux_group_set = sh_pfc_pinctrl_group_set, .set_state = pinctrl_generic_set_state, };

Enable pinconf since it's now implemented and used in the DTs.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org --- configs/r8a7795_salvator-x_defconfig | 1 + configs/r8a7795_ulcb_defconfig | 1 + configs/r8a7796_salvator-x_defconfig | 1 + configs/r8a7796_ulcb_defconfig | 1 + 4 files changed, 4 insertions(+)
diff --git a/configs/r8a7795_salvator-x_defconfig b/configs/r8a7795_salvator-x_defconfig index 4b7a2d4572..1ff5dd6475 100644 --- a/configs/r8a7795_salvator-x_defconfig +++ b/configs/r8a7795_salvator-x_defconfig @@ -42,6 +42,7 @@ CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y CONFIG_RENESAS_RAVB=y CONFIG_PINCTRL=y +CONFIG_PINCONF=y CONFIG_PINCTRL_PFC=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y diff --git a/configs/r8a7795_ulcb_defconfig b/configs/r8a7795_ulcb_defconfig index 1aa2e69ac6..58ba3fdf2a 100644 --- a/configs/r8a7795_ulcb_defconfig +++ b/configs/r8a7795_ulcb_defconfig @@ -35,6 +35,7 @@ CONFIG_MMC_UNIPHIER=y CONFIG_DM_ETH=y CONFIG_RENESAS_RAVB=y CONFIG_PINCTRL=y +CONFIG_PINCONF=y CONFIG_PINCTRL_PFC=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y diff --git a/configs/r8a7796_salvator-x_defconfig b/configs/r8a7796_salvator-x_defconfig index 083a832c56..e71b37fa97 100644 --- a/configs/r8a7796_salvator-x_defconfig +++ b/configs/r8a7796_salvator-x_defconfig @@ -43,6 +43,7 @@ CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y CONFIG_RENESAS_RAVB=y CONFIG_PINCTRL=y +CONFIG_PINCONF=y CONFIG_PINCTRL_PFC=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y diff --git a/configs/r8a7796_ulcb_defconfig b/configs/r8a7796_ulcb_defconfig index cbeda77bfd..5ea832ff49 100644 --- a/configs/r8a7796_ulcb_defconfig +++ b/configs/r8a7796_ulcb_defconfig @@ -36,6 +36,7 @@ CONFIG_MMC_UNIPHIER=y CONFIG_DM_ETH=y CONFIG_RENESAS_RAVB=y CONFIG_PINCTRL=y +CONFIG_PINCONF=y CONFIG_PINCTRL_PFC=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y

On 09/25/2017 10:52 PM, Marek Vasut wrote:
Add pinconf support to the PFC driver, so that it can handle DT props bias-disable, bias-pull-up, bias-pull-down, drive-strength and power-source.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org
Please ignore, V2 is coming.
drivers/pinctrl/renesas/pfc.c | 176 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+)
diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c index 63e2eeb449..53139d7a26 100644 --- a/drivers/pinctrl/renesas/pfc.c +++ b/drivers/pinctrl/renesas/pfc.c @@ -477,6 +477,177 @@ static int sh_pfc_pinctrl_group_set(struct udevice *dev, unsigned group_selector done: return ret; } +#if CONFIG_IS_ENABLED(PINCONF) +static const struct pinconf_param sh_pfc_pinconf_params[] = {
- { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
- { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
- { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
- { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
- { "power-source", PIN_CONFIG_POWER_SOURCE, 3300 },
+};
+static void __iomem * +sh_pfc_pinconf_find_drive_strength_reg(struct sh_pfc *pfc, unsigned int pin,
unsigned int *offset, unsigned int *size)
+{
- const struct pinmux_drive_reg_field *field;
- const struct pinmux_drive_reg *reg;
- unsigned int i;
- for (reg = pfc->info->drive_regs; reg->reg; ++reg) {
for (i = 0; i < ARRAY_SIZE(reg->fields); ++i) {
field = ®->fields[i];
if (field->size && field->pin == pin) {
*offset = field->offset;
*size = field->size;
return (void __iomem *)(uintptr_t)reg->reg;
}
}
- }
- return NULL;
+}
+static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc,
unsigned int pin, u16 strength)
+{
- unsigned int offset;
- unsigned int size;
- unsigned int step;
- void __iomem *reg;
- u32 val;
- reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size);
- if (!reg)
return -EINVAL;
- step = size == 2 ? 6 : 3;
- if (strength < step || strength > 24)
return -EINVAL;
- /* Convert the value from mA based on a full drive strength value of
* 24mA. We can make the full value configurable later if needed.
*/
- strength = strength / step - 1;
- val = sh_pfc_read_raw_reg(reg, 32);
- val &= ~GENMASK(offset + size - 1, offset);
- val |= strength << offset;
- sh_pfc_write_raw_reg(reg, 32, val);
- return 0;
+}
+/* Check whether the requested parameter is supported for a pin. */ +static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
unsigned int param)
+{
- int idx = sh_pfc_get_pin_index(pfc, _pin);
- const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
- switch (param) {
- case PIN_CONFIG_BIAS_DISABLE:
return pin->configs &
(SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN);
- case PIN_CONFIG_BIAS_PULL_UP:
return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
- case PIN_CONFIG_BIAS_PULL_DOWN:
return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
- case PIN_CONFIG_DRIVE_STRENGTH:
return pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH;
- case PIN_CONFIG_POWER_SOURCE:
return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE;
- default:
return false;
- }
+}
+static int sh_pfc_pinconf_set(struct sh_pfc_pinctrl *pmx, unsigned _pin,
unsigned int param, unsigned int arg)
+{
- struct sh_pfc *pfc = pmx->pfc;
- void __iomem *pocctrl;
- u32 addr, val;
- int bit, ret;
- if (!sh_pfc_pinconf_validate(pfc, _pin, param))
return -ENOTSUPP;
- switch (param) {
- case PIN_CONFIG_BIAS_PULL_UP:
- case PIN_CONFIG_BIAS_PULL_DOWN:
- case PIN_CONFIG_BIAS_DISABLE:
if (!pfc->info->ops || !pfc->info->ops->set_bias)
return -ENOTSUPP;
pfc->info->ops->set_bias(pfc, _pin, param);
break;
- case PIN_CONFIG_DRIVE_STRENGTH:
ret = sh_pfc_pinconf_set_drive_strength(pfc, _pin, arg);
if (ret < 0)
return ret;
break;
- case PIN_CONFIG_POWER_SOURCE:
if (!pfc->info->ops || !pfc->info->ops->pin_to_pocctrl)
return -ENOTSUPP;
bit = pfc->info->ops->pin_to_pocctrl(pfc, _pin, &addr);
if (bit < 0) {
printf("invalid pin %#x", _pin);
return bit;
}
if (arg != 1800 && arg != 3300)
return -EINVAL;
pocctrl = (void __iomem *)(uintptr_t)addr;
val = sh_pfc_read_raw_reg(pocctrl, 32);
if (arg == 3300)
val |= BIT(bit);
else
val &= ~BIT(bit);
sh_pfc_write_raw_reg(pocctrl, 32, val);
break;
- default:
return -ENOTSUPP;
- }
- return 0;
+}
+static int sh_pfc_pinconf_group_set(struct udevice *dev,
unsigned int group_selector,
unsigned int param, unsigned int arg)
+{
- struct sh_pfc_pinctrl_priv *priv = dev_get_priv(dev);
- struct sh_pfc_pinctrl *pmx = &priv->pmx;
- struct sh_pfc *pfc = &priv->pfc;
- const struct sh_pfc_pin_group *grp = &pfc->info->groups[group_selector];
- unsigned int i;
- for (i = 0; i < grp->nr_pins; i++)
sh_pfc_pinconf_set(pmx, grp->pins[i], param, arg);
- return 0;
+} +#endif
static struct pinctrl_ops sh_pfc_pinctrl_ops = { .get_pins_count = sh_pfc_pinctrl_get_pins_count, @@ -486,6 +657,11 @@ static struct pinctrl_ops sh_pfc_pinctrl_ops = { .get_functions_count = sh_pfc_pinctrl_get_functions_count, .get_function_name = sh_pfc_pinctrl_get_function_name,
+#if CONFIG_IS_ENABLED(PINCONF)
- .pinconf_num_params = ARRAY_SIZE(sh_pfc_pinconf_params),
- .pinconf_params = sh_pfc_pinconf_params,
- .pinconf_group_set = sh_pfc_pinconf_group_set,
+#endif .pinmux_group_set = sh_pfc_pinctrl_group_set, .set_state = pinctrl_generic_set_state, };
participants (1)
-
Marek Vasut