[v3, 3/3] pinctrl: mediatek: add support for different types of IO pins

Sam Shih
2022-04-01T08:56:35Z

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>
---
v3: fix v2 patch series misapplied
v2: fix build fail caused by patch [2/3]
---
drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 46 +++++++++++++++++--
drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 38 ++++++++++++++-
2 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index ebab43e50a..6f9b85871e 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -219,6 +219,23 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field,
return 0;
}

+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;
+}
+
static int mtk_get_groups_count(struct udevice *dev)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
@@ -416,16 +433,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 +473,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 +536,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;
}
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
index 91a8c0581f..0d9596fa72 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -12,10 +12,15 @@
#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;
--
2.18.0