]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
pinctrl: uniphier: support pin configuration
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Sun, 12 Feb 2017 09:21:15 +0000 (18:21 +0900)
committerMasahiro Yamada <yamada.masahiro@socionext.com>
Wed, 22 Feb 2017 23:37:56 +0000 (08:37 +0900)
Support the following DT properties:
  "bias-disable"
  "bias-pull-up"
  "bias-pull-down"
  "bias-pull-pin-default"
  "input-enable"
  "input-disable"

My main motivation is to support pull up/down biasing.  For Pro5 and
later SoCs, the pupdctrl register number is the same as the pinmux
number, so this feature can be supported without having big pin
tables.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
drivers/pinctrl/uniphier/pinctrl-uniphier.h

index 51144b8e73238aee3d4babd05ebe5972a0ff7d75..d8e9948ee7cc994ac29db581ec117257d7103a2d 100644 (file)
@@ -5,6 +5,7 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include <common.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/sizes.h>
@@ -15,6 +16,7 @@
 
 #define UNIPHIER_PINCTRL_PINMUX_BASE   0x1000
 #define UNIPHIER_PINCTRL_LOAD_PINMUX   0x1700
+#define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00
 #define UNIPHIER_PINCTRL_IECTRL                0x1d00
 
 static const char *uniphier_pinctrl_dummy_name = "_dummy";
@@ -55,8 +57,8 @@ static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
        return priv->socdata->functions[selector];
 }
 
-static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
-                                                unsigned pin)
+static int uniphier_pinconf_input_enable_perpin(struct udevice *dev,
+                                               unsigned int pin, int enable)
 {
        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
        unsigned reg;
@@ -66,18 +68,30 @@ static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
        mask = BIT(pin % 32);
 
        tmp = readl(priv->base + reg);
-       tmp |= mask;
+       if (enable)
+               tmp |= mask;
+       else
+               tmp &= ~mask;
        writel(tmp, priv->base + reg);
+
+       return 0;
 }
 
-static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
-                                                unsigned pin)
+static int uniphier_pinconf_input_enable_legacy(struct udevice *dev,
+                                               unsigned int pin, int enable)
 {
        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
        int pins_count = priv->socdata->pins_count;
        const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
        int i;
 
+       /*
+        * Multiple pins share one input enable, per-pin disabling is
+        * impossible.
+        */
+       if (!enable)
+               return -EINVAL;
+
        for (i = 0; i < pins_count; i++) {
                if (pins[i].number == pin) {
                        unsigned int iectrl;
@@ -89,18 +103,115 @@ static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
                        writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
                }
        }
+
+       return 0;
 }
 
-static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
+static int uniphier_pinconf_input_enable(struct udevice *dev,
+                                        unsigned int pin, int enable)
 {
        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 
        if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
-               uniphier_pinconf_input_enable_perpin(dev, pin);
+               return uniphier_pinconf_input_enable_perpin(dev, pin, enable);
+       else
+               return uniphier_pinconf_input_enable_legacy(dev, pin, enable);
+}
+
+#if CONFIG_IS_ENABLED(PINCONF)
+
+static const struct pinconf_param uniphier_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 },
+       { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+       { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+       { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
+};
+
+static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
+                                    unsigned int param, unsigned int arg)
+{
+       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+       unsigned int enable = 1;
+       unsigned int reg;
+       u32 mask, tmp;
+
+       if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE))
+               return -ENOTSUPP;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               enable = 0;
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               if (arg == 0)   /* total bias is not supported */
+                       return -EINVAL;
+               break;
+       case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+               if (arg == 0)   /* configuration ignored */
+                       return 0;
+       default:
+               BUG();
+       }
+
+       reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4;
+       mask = BIT(pin % 32);
+
+       tmp = readl(priv->base + reg);
+       if (enable)
+               tmp |= mask;
        else
-               uniphier_pinconf_input_enable_legacy(dev, pin);
+               tmp &= ~mask;
+       writel(tmp, priv->base + reg);
+
+       return 0;
+}
+
+static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin,
+                                   unsigned int param, unsigned int arg)
+{
+       int ret;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+       case PIN_CONFIG_BIAS_PULL_UP:
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+       case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+               ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
+               break;
+       case PIN_CONFIG_INPUT_ENABLE:
+               ret = uniphier_pinconf_input_enable(dev, pin, arg);
+               break;
+       default:
+               printf("unsupported configuration parameter %u\n", param);
+               return -EINVAL;
+       }
+
+       return ret;
 }
 
+static int uniphier_pinconf_group_set(struct udevice *dev,
+                                     unsigned int group_selector,
+                                     unsigned int param, unsigned int arg)
+{
+       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+       const struct uniphier_pinctrl_group *grp =
+                                       &priv->socdata->groups[group_selector];
+       int i, ret;
+
+       for (i = 0; i < grp->num_pins; i++) {
+               ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_IS_ENABLED(PINCONF) */
+
 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
                                    int muxval)
 {
@@ -112,7 +223,7 @@ static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
        u32 tmp;
 
        /* some pins need input-enabling */
-       uniphier_pinconf_input_enable(dev, pin);
+       uniphier_pinconf_input_enable(dev, pin, 1);
 
        if (muxval < 0)
                return;         /* dedicated pin; nothing to do for pin-mux */
@@ -174,6 +285,11 @@ const struct pinctrl_ops uniphier_pinctrl_ops = {
        .get_functions_count = uniphier_pinmux_get_functions_count,
        .get_function_name = uniphier_pinmux_get_function_name,
        .pinmux_group_set = uniphier_pinmux_group_set,
+#if CONFIG_IS_ENABLED(PINCONF)
+       .pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
+       .pinconf_params = uniphier_pinconf_params,
+       .pinconf_group_set = uniphier_pinconf_group_set,
+#endif
        .set_state = pinctrl_generic_set_state,
 };
 
index 1d318d824c017f10467af944dfe542d1fce6cf39..53c37cda7adc0ce14a6723c630bf55790d9ed2c3 100644 (file)
@@ -92,7 +92,8 @@ static struct uniphier_pinctrl_socdata uniphier_ld11_pinctrl_socdata = {
        .groups_count = ARRAY_SIZE(uniphier_ld11_groups),
        .functions = uniphier_ld11_functions,
        .functions_count = ARRAY_SIZE(uniphier_ld11_functions),
-       .caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
+       .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE |
+               UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
 };
 
 static int uniphier_ld11_pinctrl_probe(struct udevice *dev)
index 0c46450d367fba047ae0ae4bd7c3b9cca5ccb0c6..5a7d142865f2b86feffc12b1d99707b0aa645390 100644 (file)
@@ -106,7 +106,8 @@ static struct uniphier_pinctrl_socdata uniphier_ld20_pinctrl_socdata = {
        .groups_count = ARRAY_SIZE(uniphier_ld20_groups),
        .functions = uniphier_ld20_functions,
        .functions_count = ARRAY_SIZE(uniphier_ld20_functions),
-       .caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
+       .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE |
+               UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
 };
 
 static int uniphier_ld20_pinctrl_probe(struct udevice *dev)
index 80d782c8d6b1b97d1ff74201a61368caca7bb590..b25c7ea16ea5a467da7ac335cafd86087598100c 100644 (file)
@@ -140,6 +140,7 @@ static struct uniphier_pinctrl_socdata uniphier_ld6b_pinctrl_socdata = {
        .groups_count = ARRAY_SIZE(uniphier_ld6b_groups),
        .functions = uniphier_ld6b_functions,
        .functions_count = ARRAY_SIZE(uniphier_ld6b_functions),
+       .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE,
 };
 
 static int uniphier_ld6b_pinctrl_probe(struct udevice *dev)
index 9670f254e20d767b0e07054295fd7248fe004ce3..70c90bae54027574e43ccb2dace9218cac529355 100644 (file)
@@ -147,7 +147,8 @@ static struct uniphier_pinctrl_socdata uniphier_pro5_pinctrl_socdata = {
        .groups_count = ARRAY_SIZE(uniphier_pro5_groups),
        .functions = uniphier_pro5_functions,
        .functions_count = ARRAY_SIZE(uniphier_pro5_functions),
-       .caps = UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE,
+       .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE |
+               UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE,
 };
 
 static int uniphier_pro5_pinctrl_probe(struct udevice *dev)
index 1d291703f46363727e94bb5ee1a548c532b1a750..60777c3045a6745961a32558f1df2995dd09257a 100644 (file)
@@ -140,6 +140,7 @@ static struct uniphier_pinctrl_socdata uniphier_pxs2_pinctrl_socdata = {
        .groups_count = ARRAY_SIZE(uniphier_pxs2_groups),
        .functions = uniphier_pxs2_functions,
        .functions_count = ARRAY_SIZE(uniphier_pxs2_functions),
+       .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE,
 };
 
 static int uniphier_pxs2_pinctrl_probe(struct udevice *dev)
index 21e2d377b4c453176280ce781dd00103ed8a266c..a0eccf8d4a80c7145ac6943e52cc03e833471258 100644 (file)
@@ -67,6 +67,7 @@ struct uniphier_pinctrl_socdata {
        const char * const *functions;
        int functions_count;
        unsigned caps;
+#define UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE      BIT(3)
 #define UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL    BIT(2)
 #define UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE  BIT(1)
 #define UNIPHIER_PINCTRL_CAPS_MUX_4BIT         BIT(0)