pinctrl: add new pinconf attrs "output-high" and "output-low"
authorXingyu Chen <xingyu.chen@amlogic.com>
Fri, 23 Mar 2018 08:22:11 +0000 (16:22 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Mon, 26 Mar 2018 06:00:22 +0000 (22:00 -0800)
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 <xingyu.chen@amlogic.com>
drivers/amlogic/pinctrl/pinconf-meson-g12a.c
drivers/amlogic/pinctrl/pinctrl-meson.c
drivers/amlogic/pinctrl/pinctrl-meson.h

index 25edb88..2d7302a 100644 (file)
@@ -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);
index ef44998..53facea 100644 (file)
@@ -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,
+                                          &reg, &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,
+                                          &reg, &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, &reg, &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, &reg, &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);
 
index 5ba442b..e598066 100644 (file)
@@ -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);