[U-Boot] [RFC PATCH 2/7] pinctrl: UniPhier: add UniPhier pinctrl core support

Masahiro Yamada yamada.masahiro at socionext.com
Wed Jul 15 10:16:17 CEST 2015


The core support for the pinctrl drivers for all the UniPhier SoCs.

Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
---

 drivers/pinctrl/Kconfig                          |   2 +
 drivers/pinctrl/Makefile                         |   2 +
 drivers/pinctrl/uniphier/Kconfig                 |   7 ++
 drivers/pinctrl/uniphier/Makefile                |   1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 127 +++++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  51 +++++++++
 6 files changed, 190 insertions(+)
 create mode 100644 drivers/pinctrl/uniphier/Kconfig
 create mode 100644 drivers/pinctrl/uniphier/Makefile
 create mode 100644 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
 create mode 100644 drivers/pinctrl/uniphier/pinctrl-uniphier.h

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index cae4d55..758b5c7 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -1,2 +1,4 @@
 config PINCTRL
 	bool
+
+source "drivers/pinctrl/uniphier/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a775a4c..2af6887 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -1 +1,3 @@
 obj-y				+= pinctrl-uclass.o
+
+obj-$(CONFIG_ARCH_UNIPHIER)	+= uniphier/
diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
new file mode 100644
index 0000000..d458394
--- /dev/null
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -0,0 +1,7 @@
+if ARCH_UNIPHIER
+
+config PINCTRL_UNIPHIER_CORE
+	bool
+	select PINCTRL
+
+endif
diff --git a/drivers/pinctrl/uniphier/Makefile b/drivers/pinctrl/uniphier/Makefile
new file mode 100644
index 0000000..748aa1b
--- /dev/null
+++ b/drivers/pinctrl/uniphier/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PINCTRL_UNIPHIER_CORE)		+= pinctrl-uniphier-core.o
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
new file mode 100644
index 0000000..6436a30
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static void uniphier_pinmux_set_one(struct udevice *dev,
+				    const struct uniphier_mux *mux)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	unsigned mux_bits = priv->socdata->mux_bits;
+	unsigned reg_stride = priv->socdata->reg_stride;
+	unsigned pin = mux->pin;
+	unsigned muxval = mux->muxval;
+	unsigned reg, reg_end, shift, mask;
+	u32 tmp;
+
+	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
+	reg_end = reg + reg_stride;
+	shift = pin * mux_bits % 32;
+	mask = (1U << mux_bits) - 1;
+
+	/*
+	 * If reg_stride is greater than 4, the MSB of each pinsel shall be
+	 * stored in the offset+4.
+	 */
+	for (; reg < reg_end; reg += 4) {
+		tmp = readl(priv->base + reg);
+		tmp &= ~(mask << shift);
+		tmp |= (mask & muxval) << shift;
+		writel(tmp, priv->base + reg);
+
+		muxval >>= mux_bits;
+	}
+
+	if (priv->socdata->load_pinctrl)
+		writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
+}
+
+static int uniphier_pinmux_set(struct udevice *dev, const char *group,
+			       const char *function)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct uniphier_pinmux_data *pinmux_data =
+						priv->socdata->pinmux_data;
+	const unsigned num_pinmux_data = priv->socdata->num_pinmux_data;
+	const struct uniphier_mux *mux;
+	unsigned nmux;
+	int i;
+
+	for (i = 0; i < num_pinmux_data; i++) {
+		if (strcmp(pinmux_data[i].function, function))
+			continue;
+
+		if (!group || !strcmp(pinmux_data[i].group, group))
+			break;
+	}
+
+	if (i >= num_pinmux_data) {
+		printf("unsupported pinmux: group = %s, functions = %s\n",
+		       group, function);
+		return -EINVAL;
+	}
+
+	mux = pinmux_data[i].muxdata;
+	nmux = pinmux_data[i].num_muxdata;
+
+	for (i = 0; i < nmux; i++)
+		uniphier_pinmux_set_one(dev, &mux[i]);
+
+	return 0;
+}
+
+static int uniphier_pinconf_set(struct udevice *dev, const char *group,
+				const char *conf_param, unsigned conf_arg)
+{
+	/* not implemented yet: just debug message */
+	printf("%s: pinconf_set, group = %s, conf_param = %s, conf_arg = %d\n",
+	       dev->name, group, conf_param, conf_arg);
+
+	return 0;
+}
+
+const struct pinctrl_ops uniphier_pinctrl_ops = {
+	.pinmux_set = uniphier_pinmux_set,
+	.pinconf_set = uniphier_pinconf_set,
+};
+
+int uniphier_pinctrl_probe(struct udevice *dev,
+			   struct uniphier_pinctrl_socdata *socdata)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	DECLARE_GLOBAL_DATA_PTR;
+	fdt_addr_t addr;
+	fdt_size_t size;
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg",
+				    &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->base = map_sysmem(addr, size);
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->socdata = socdata;
+
+	return 0;
+}
+
+int uniphier_pinctrl_remove(struct udevice *dev)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+	unmap_sysmem(priv->base);
+
+	return 0;
+}
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
new file mode 100644
index 0000000..681158b
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -0,0 +1,51 @@
+#ifndef __PINCTRL_UNIPHIER_H__
+#define __PINCTRL_UNIPHIER_H__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#define UNIPHIER_PINCTRL_PINMUX_BASE	0x0
+#define UNIPHIER_PINCTRL_LOAD_PINMUX	0x700
+#define UNIPHIER_PINCTRL_IECTRL		0xd00
+
+struct uniphier_mux {
+	unsigned pin;
+	unsigned muxval;
+};
+
+struct uniphier_pinmux_data {
+	const char *group;
+	const char *function;
+	const struct uniphier_mux *muxdata;
+	unsigned num_muxdata;
+};
+
+struct uniphier_pinctrl_socdata {
+	const struct uniphier_pinmux_data *pinmux_data;
+	unsigned num_pinmux_data;
+	unsigned mux_bits;
+	unsigned reg_stride;
+	bool load_pinctrl;
+};
+
+#define UNIPHIER_PINMUX_DATA(grp, func)			\
+	{						\
+		.group = #grp,				\
+		.function = #func,			\
+		.muxdata = grp##_mux,			\
+		.num_muxdata = ARRAY_SIZE(grp##_mux),	\
+	}
+
+struct uniphier_pinctrl_priv {
+	void __iomem *base;
+	struct uniphier_pinctrl_socdata *socdata;
+};
+
+extern const struct pinctrl_ops uniphier_pinctrl_ops;
+
+int uniphier_pinctrl_probe(struct udevice *dev,
+			   struct uniphier_pinctrl_socdata *socdata);
+
+int uniphier_pinctrl_remove(struct udevice *dev);
+
+#endif /* __PINCTRL_UNIPHIER_H__ */
-- 
1.9.1



More information about the U-Boot mailing list