diff options
Diffstat (limited to 'drivers/pinctrl/renesas/pinctrl.c')
-rw-r--r-- | drivers/pinctrl/renesas/pinctrl.c | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/drivers/pinctrl/renesas/pinctrl.c b/drivers/pinctrl/renesas/pinctrl.c index 212a4a9c3a8f..ac542d278a38 100644 --- a/drivers/pinctrl/renesas/pinctrl.c +++ b/drivers/pinctrl/renesas/pinctrl.c @@ -26,9 +26,8 @@ #include "../pinconf.h" struct sh_pfc_pin_config { - unsigned int mux_mark; - bool mux_set; - bool gpio_enabled; + u16 gpio_enabled:1; + u16 mux_mark:15; }; struct sh_pfc_pinctrl { @@ -371,12 +370,11 @@ static int sh_pfc_func_set_mux(struct pinctrl_dev *pctldev, unsigned selector, goto done; } - /* All group pins are configured, mark the pins as mux_set */ + /* All group pins are configured, mark the pins as muxed */ for (i = 0; i < grp->nr_pins; ++i) { int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]); struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; - cfg->mux_set = true; cfg->mux_mark = grp->mux[i]; } @@ -399,7 +397,7 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, spin_lock_irqsave(&pfc->lock, flags); if (!pfc->gpio) { - /* If GPIOs are handled externally the pin mux type need to be + /* If GPIOs are handled externally the pin mux type needs to be * set to GPIO here. */ const struct sh_pfc_pin *pin = &pfc->info->pins[idx]; @@ -432,11 +430,12 @@ static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev, spin_lock_irqsave(&pfc->lock, flags); cfg->gpio_enabled = false; /* If mux is already set, this configures it here */ - if (cfg->mux_set) + if (cfg->mux_mark) sh_pfc_config_mux(pfc, cfg->mux_mark, PINMUX_TYPE_FUNCTION); spin_unlock_irqrestore(&pfc->lock, flags); } +#ifdef CONFIG_PINCTRL_SH_PFC_GPIO static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input) @@ -450,8 +449,8 @@ static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev, unsigned int dir; int ret; - /* Check if the requested direction is supported by the pin. Not all SoC - * provide pin config data, so perform the check conditionally. + /* Check if the requested direction is supported by the pin. Not all + * SoCs provide pin config data, so perform the check conditionally. */ if (pin->configs) { dir = input ? SH_PFC_PIN_CFG_INPUT : SH_PFC_PIN_CFG_OUTPUT; @@ -460,15 +459,13 @@ static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev, } spin_lock_irqsave(&pfc->lock, flags); - ret = sh_pfc_config_mux(pfc, pin->enum_id, new_type); - if (ret < 0) - goto done; - -done: spin_unlock_irqrestore(&pfc->lock, flags); return ret; } +#else +#define sh_pfc_gpio_set_direction NULL +#endif static const struct pinmux_ops sh_pfc_pinmux_ops = { .get_functions_count = sh_pfc_get_functions_count, @@ -830,3 +827,46 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc) return pinctrl_enable(pmx->pctl); } + +unsigned int rcar_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) +{ + const struct pinmux_bias_reg *reg; + unsigned int bit; + + reg = sh_pfc_pin_to_bias_reg(pfc, pin, &bit); + if (!reg) + return PIN_CONFIG_BIAS_DISABLE; + + if (!(sh_pfc_read(pfc, reg->puen) & BIT(bit))) + return PIN_CONFIG_BIAS_DISABLE; + else if (!reg->pud || (sh_pfc_read(pfc, reg->pud) & BIT(bit))) + return PIN_CONFIG_BIAS_PULL_UP; + else + return PIN_CONFIG_BIAS_PULL_DOWN; +} + +void rcar_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, + unsigned int bias) +{ + const struct pinmux_bias_reg *reg; + u32 enable, updown; + unsigned int bit; + + reg = sh_pfc_pin_to_bias_reg(pfc, pin, &bit); + if (!reg) + return; + + enable = sh_pfc_read(pfc, reg->puen) & ~BIT(bit); + if (bias != PIN_CONFIG_BIAS_DISABLE) + enable |= BIT(bit); + + if (reg->pud) { + updown = sh_pfc_read(pfc, reg->pud) & ~BIT(bit); + if (bias == PIN_CONFIG_BIAS_PULL_UP) + updown |= BIT(bit); + + sh_pfc_write(pfc, reg->pud, updown); + } + + sh_pfc_write(pfc, reg->puen, enable); +} |