From 6e0c76302d056c64e406547b0487e3dbfb2ffd0b Mon Sep 17 00:00:00 2001 From: Xingyu Chen Date: Fri, 23 Mar 2018 16:22:11 +0800 Subject: [PATCH] pinctrl: add new pinconf attrs "output-high" and "output-low" PD#162858: pinctrl: add new pinconf attrs "output-high" and "output-low" we can refer the following example to use: mux { groups = "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5"; function = "gpio_periphs"; output-high; // or output-low } output-high: GPIO_EN_N[pin]=<0> and GPIO_O[pin]=<1> output-low : GPIO_EN_N[pin]=<0> and GPIO_O[pin]=<0> Change-Id: I3f8ec1bd1eff7c7d6e7416b608e4c5d6c7b15955 Signed-off-by: Xingyu Chen --- drivers/amlogic/pinctrl/pinconf-meson-g12a.c | 40 +++++-------- drivers/amlogic/pinctrl/pinctrl-meson.c | 86 ++++++++++++++++++++++++---- drivers/amlogic/pinctrl/pinctrl-meson.h | 7 ++- 3 files changed, 93 insertions(+), 40 deletions(-) diff --git a/drivers/amlogic/pinctrl/pinconf-meson-g12a.c b/drivers/amlogic/pinctrl/pinconf-meson-g12a.c index 25edb88..2d7302a 100644 --- a/drivers/amlogic/pinctrl/pinconf-meson-g12a.c +++ b/drivers/amlogic/pinctrl/pinconf-meson-g12a.c @@ -112,22 +112,14 @@ static int meson_g12a_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: - case PIN_CONFIG_BIAS_PULL_UP: - case PIN_CONFIG_BIAS_PULL_DOWN: - case PIN_CONFIG_INPUT_ENABLE: - ret = meson_pinconf_set_pull(pc, pin, param); + if (param == PIN_CONFIG_DRIVE_STRENGTH) { + ret = meson_pinconf_set_drive_strength(pc, pin, arg); if (ret) return ret; - break; - case PIN_CONFIG_DRIVE_STRENGTH: - ret = meson_pinconf_set_drive_strength(pc, pin, arg); + } else { + ret = meson_pinconf_common_set(pc, pin, param, arg); if (ret) return ret; - break; - default: - return -ENOTSUPP; } } @@ -139,23 +131,17 @@ static int meson_g12a_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, { struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); enum pin_config_param param = pinconf_to_config_param(*config); + int ret; u16 arg; - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: - case PIN_CONFIG_BIAS_PULL_DOWN: - case PIN_CONFIG_BIAS_PULL_UP: - if (meson_pinconf_get_pull(pc, pin) == param) - arg = 1; - else - return -EINVAL; - break; - case PIN_CONFIG_DRIVE_STRENGTH: - if (meson_pinconf_get_drive_strength(pc, pin, &arg)) - return -EINVAL; - break; - default: - return -ENOTSUPP; + if (param == PIN_CONFIG_DRIVE_STRENGTH) { + ret = meson_pinconf_get_drive_strength(pc, pin, &arg); + if (ret) + return ret; + } else { + ret = meson_pinconf_common_get(pc, pin, param, &arg); + if (ret) + return ret; } *config = pinconf_to_config_packed(param, arg); diff --git a/drivers/amlogic/pinctrl/pinctrl-meson.c b/drivers/amlogic/pinctrl/pinctrl-meson.c index ef44998..53facea 100644 --- a/drivers/amlogic/pinctrl/pinctrl-meson.c +++ b/drivers/amlogic/pinctrl/pinctrl-meson.c @@ -178,8 +178,8 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev, return 0; } -int meson_pinconf_set_pull(struct meson_pinctrl *pc, unsigned int pin, - enum pin_config_param param) +int meson_pinconf_common_set(struct meson_pinctrl *pc, unsigned int pin, + enum pin_config_param param, u16 arg) { struct meson_bank *bank; unsigned int reg, bit; @@ -242,6 +242,21 @@ int meson_pinconf_set_pull(struct meson_pinctrl *pc, unsigned int pin, if (ret) return ret; break; + case PIN_CONFIG_OUTPUT: + dev_dbg(pc->dev, "pin %u: output %s\n", pin, + arg ? "high" : "low"); + meson_calc_reg_and_bit(bank, pin, REG_DIR, + ®, &bit); + ret = regmap_update_bits(pc->reg_gpio, reg, + BIT(bit), 0); + if (ret) + return ret; + meson_calc_reg_and_bit(bank, pin, REG_OUT, + ®, &bit); + ret = regmap_update_bits(pc->reg_gpio, reg, + BIT(bit), arg ? BIT(bit) : 0); + if (ret) + return ret; default: return -ENOTSUPP; } @@ -260,7 +275,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); - ret = meson_pinconf_set_pull(pc, pin, param); + ret = meson_pinconf_common_set(pc, pin, param, arg); if (ret) return ret; } @@ -268,7 +283,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, return 0; } -int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin) +static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin) { struct meson_bank *bank; unsigned int reg, bit, val; @@ -302,26 +317,77 @@ int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin) return conf; } -static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, - unsigned long *config) +static int meson_pinconf_get_pio(struct meson_pinctrl *pc, unsigned int pin, + u16 *arg) { - struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); - enum pin_config_param param = pinconf_to_config_param(*config); - u16 arg; + struct meson_bank *bank; + unsigned int reg, bit, val; + int ret, conf; + + ret = meson_get_bank(pc, pin, &bank); + if (ret) + return ret; + meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); + reg = regmap_read(pc->reg_gpio, reg, &val); + if (ret) + return ret; + if (val & BIT(bit)) { + conf = PIN_CONFIG_INPUT_ENABLE; + *arg = 1; + } else { + meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); + + ret = regmap_read(pc->reg_gpio, reg, &val); + if (ret) + return ret; + + if (val & BIT(bit)) + *arg = 1; + else + *arg = 0; + conf = PIN_CONFIG_OUTPUT; + } + + return conf; +} + +int meson_pinconf_common_get(struct meson_pinctrl *pc, unsigned int pin, + enum pin_config_param param, u16 *arg) +{ switch (param) { case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_UP: if (meson_pinconf_get_pull(pc, pin) == param) - arg = 1; + *arg = 1; else return -EINVAL; break; + case PIN_CONFIG_INPUT_ENABLE: + case PIN_CONFIG_OUTPUT: + if (meson_pinconf_get_pio(pc, pin, arg) != param) + return -EINVAL; + break; default: return -ENOTSUPP; } + return 0; +} + +static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, + unsigned long *config) +{ + struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); + enum pin_config_param param = pinconf_to_config_param(*config); + u16 arg; + int ret; + + ret = meson_pinconf_common_get(pc, pin, param, &arg); + if (ret) + return ret; + *config = pinconf_to_config_packed(param, arg); dev_dbg(pc->dev, "pinconf for pin %u is %lu\n", pin, *config); diff --git a/drivers/amlogic/pinctrl/pinctrl-meson.h b/drivers/amlogic/pinctrl/pinctrl-meson.h index 5ba442b..e598066 100644 --- a/drivers/amlogic/pinctrl/pinctrl-meson.h +++ b/drivers/amlogic/pinctrl/pinctrl-meson.h @@ -178,7 +178,8 @@ extern int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned int * const num_groups); /* Common pinconf functions */ -extern int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin); +extern int meson_pinconf_common_get(struct meson_pinctrl *pc, unsigned int pin, + enum pin_config_param param, u16 *arg); -extern int meson_pinconf_set_pull(struct meson_pinctrl *pc, unsigned int pin, - enum pin_config_param param); +extern int meson_pinconf_common_set(struct meson_pinctrl *pc, unsigned int pin, + enum pin_config_param param, u16 arg); -- 2.7.4