pinctrl: mediatek: add support for different types of IO pins
authorSam Shih <sam.shih@mediatek.com>
Thu, 21 Apr 2022 06:23:53 +0000 (14:23 +0800)
committerTom Rini <trini@konsulko.com>
Thu, 5 May 2022 13:29:58 +0000 (09:29 -0400)
There are many pins in an SoC, and register usage may vary by pins.
This patch introduces a concept of "io type" and "io type group"
to mediatek pinctrl drivers. This can provide different pinconf
handlers implementation (eg: "bias-pull-up/down", "driving" and
"input-enable") for IO pins that belong to different types.

Signed-off-by: Sam Shih <sam.shih@mediatek.com>
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.h

index ebab43e..47e2d67 100644 (file)
@@ -219,6 +219,25 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field,
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(PINCONF)
+static int mtk_get_pin_io_type(struct udevice *dev, int pin,
+                              struct mtk_io_type_desc *io_type)
+{
+       struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+       u8 io_n = priv->soc->pins[pin].io_n;
+
+       if (io_n >= priv->soc->ntype)
+               return -EINVAL;
+
+       io_type->name = priv->soc->io_type[io_n].name;
+       io_type->bias_set = priv->soc->io_type[io_n].bias_set;
+       io_type->drive_set = priv->soc->io_type[io_n].drive_set;
+       io_type->input_enable = priv->soc->io_type[io_n].input_enable;
+
+       return 0;
+}
+#endif
+
 static int mtk_get_groups_count(struct udevice *dev)
 {
        struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
@@ -416,16 +435,25 @@ int mtk_pinconf_bias_set(struct udevice *dev, u32 pin, u32 arg, u32 val)
 {
        int err;
        struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+       struct mtk_io_type_desc io_type;
        int rev = priv->soc->rev;
        bool disable, pullup;
 
        disable = (arg == PIN_CONFIG_BIAS_DISABLE);
        pullup = (arg == PIN_CONFIG_BIAS_PULL_UP);
 
-       if (rev == MTK_PINCTRL_V0)
+       if (!mtk_get_pin_io_type(dev, pin, &io_type)) {
+               if (io_type.bias_set)
+                       err = io_type.bias_set(dev, pin, disable, pullup,
+                                              val);
+               else
+                       err = -EINVAL;
+
+       } else if (rev == MTK_PINCTRL_V0) {
                err = mtk_pinconf_bias_set_v0(dev, pin, disable, pullup, val);
-       else
+       } else {
                err = mtk_pinconf_bias_set_v1(dev, pin, disable, pullup, val);
+       }
 
        return err;
 }
@@ -447,8 +475,13 @@ int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg)
 int mtk_pinconf_input_enable(struct udevice *dev, u32 pin, u32 arg)
 {
        struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+       struct mtk_io_type_desc io_type;
+
        int rev = priv->soc->rev;
 
+       if (!mtk_get_pin_io_type(dev, pin, &io_type))
+               if (io_type.input_enable)
+                       return io_type.input_enable(dev, pin, arg);
        if (rev == MTK_PINCTRL_V1)
                return mtk_pinconf_input_enable_v1(dev, pin, arg);
 
@@ -505,12 +538,19 @@ int mtk_pinconf_drive_set(struct udevice *dev, u32 pin, u32 arg)
 {
        int err;
        struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
+       struct mtk_io_type_desc io_type;
        int rev = priv->soc->rev;
 
-       if (rev == MTK_PINCTRL_V0)
+       if (!mtk_get_pin_io_type(dev, pin, &io_type)) {
+               if (io_type.drive_set)
+                       err = io_type.drive_set(dev, pin, arg);
+               else
+                       err = -EINVAL;
+       } else if (rev == MTK_PINCTRL_V0) {
                err = mtk_pinconf_drive_set_v0(dev, pin, arg);
-       else
+       } else {
                err = mtk_pinconf_drive_set_v1(dev, pin, arg);
+       }
 
        return err;
 }
index 91a8c05..0d9596f 100644 (file)
 #define MAX_BASE_CALC 10
 
 #define MTK_RANGE(_a)          { .range = (_a), .nranges = ARRAY_SIZE(_a), }
-#define MTK_PIN(_number, _name, _drv_n) {                              \
+
+#define MTK_PIN(_number, _name, _drv_n)                                        \
+       MTK_TYPED_PIN(_number, _name, _drv_n, IO_TYPE_DEFAULT)
+
+#define MTK_TYPED_PIN(_number, _name, _drv_n, _io_n) {                 \
                .number = _number,                                      \
                .name = _name,                                          \
                .drv_n = _drv_n,                                        \
+               .io_n = _io_n,                                          \
        }
 
 #define PINCTRL_PIN_GROUP(name, id)                                    \
@@ -75,6 +80,18 @@ enum {
        DRV_GRP4,
 };
 
+/* Group the pins by the io type */
+enum {
+       IO_TYPE_DEFAULT,
+       IO_TYPE_GRP0,
+       IO_TYPE_GRP1,
+       IO_TYPE_GRP2,
+       IO_TYPE_GRP3,
+       IO_TYPE_GRP4,
+       IO_TYPE_GRP5,
+       IO_TYPE_GRP6,
+};
+
 /**
  * struct mtk_pin_field - the structure that holds the information of the field
  *                       used to describe the attribute for the pin
@@ -139,11 +156,13 @@ struct mtk_pin_reg_calc {
  * @number:            unique pin number from the global pin number space
  * @name:              name for this pin
  * @drv_n:             the index with the driving group
+ * @io_n:              the index with the io type
  */
 struct mtk_pin_desc {
        unsigned int number;
        const char *name;
        u8 drv_n;
+       u8 io_n;
 };
 
 /**
@@ -172,6 +191,21 @@ struct mtk_function_desc {
        int num_group_names;
 };
 
+/**
+ * struct mtk_io_type_desc - io class descriptor for specific pins
+ * @name: name of the io class
+ */
+struct mtk_io_type_desc {
+       const char *name;
+#if CONFIG_IS_ENABLED(PINCONF)
+       /* Specific pinconfig operations */
+       int (*bias_set)(struct udevice *dev, u32 pin, bool disable,
+                       bool pullup, u32 val);
+       int (*drive_set)(struct udevice *dev, u32 pin, u32 arg);
+       int (*input_enable)(struct udevice *dev, u32 pin, u32 arg);
+#endif
+};
+
 /* struct mtk_pin_soc - the structure that holds SoC-specific data */
 struct mtk_pinctrl_soc {
        const char *name;
@@ -182,6 +216,8 @@ struct mtk_pinctrl_soc {
        int ngrps;
        const struct mtk_function_desc *funcs;
        int nfuncs;
+       const struct mtk_io_type_desc *io_type;
+       u8 ntype;
        int gpio_mode;
        const char * const *base_names;
        unsigned int nbase_names;