diff mbox

[U-Boot,01/15] pinctrl: uniphier: add UniPhier pinctrl core support

Message ID 1441115432-12810-2-git-send-email-yamada.masahiro@socionext.com
State Superseded
Delegated to: Masahiro Yamada
Headers show

Commit Message

Masahiro Yamada Sept. 1, 2015, 1:50 p.m. UTC
The core support for the pinctrl drivers for all the UniPhier SoCs.

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

 drivers/pinctrl/Kconfig                          |   2 +
 drivers/pinctrl/Makefile                         |   2 +
 drivers/pinctrl/uniphier/Kconfig                 |   6 +
 drivers/pinctrl/uniphier/Makefile                |   1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 134 +++++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  57 ++++++++++
 6 files changed, 202 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

Comments

Simon Glass Sept. 2, 2015, 2:48 a.m. UTC | #1
Hi Masahiro,

On 1 September 2015 at 07:50, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> The core support for the pinctrl drivers for all the UniPhier SoCs.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
>  drivers/pinctrl/Kconfig                          |   2 +
>  drivers/pinctrl/Makefile                         |   2 +
>  drivers/pinctrl/uniphier/Kconfig                 |   6 +
>  drivers/pinctrl/uniphier/Makefile                |   1 +
>  drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 134 +++++++++++++++++++++++
>  drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  57 ++++++++++
>  6 files changed, 202 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

Reviewed-by: Simon Glass <sjg@chromium.org>

A few comments below.

>
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 30b8e45..9c12429 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -106,4 +106,6 @@ config PINCTRL_SANDBOX
>
>  endif
>
> +source "drivers/pinctrl/uniphier/Kconfig"
> +
>  endmenu
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 35decf4..d0eb263 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -2,3 +2,5 @@ obj-y                                   += pinctrl-uclass.o
>  obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC)   += pinctrl-generic.o
>
>  obj-$(CONFIG_PINCTRL_SANDBOX)  += pinctrl-sandbox.o
> +
> +obj-$(CONFIG_ARCH_UNIPHIER)    += uniphier/
> diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
> new file mode 100644
> index 0000000..29a623d
> --- /dev/null
> +++ b/drivers/pinctrl/uniphier/Kconfig
> @@ -0,0 +1,6 @@
> +if ARCH_UNIPHIER
> +
> +config PINCTRL_UNIPHIER_CORE
> +       bool
> +
> +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..f008aea
> --- /dev/null
> +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@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"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +
> +       return priv->socdata->groups_count;
> +}
> +
> +static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
> +                                                  unsigned selector)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +
> +       return priv->socdata->groups[selector].name;
> +}
> +
> +static int uniphier_pinmux_get_functions_count(struct udevice *dev)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +
> +       return priv->socdata->functions_count;
> +}
> +
> +static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
> +                                                    unsigned selector)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +
> +       return priv->socdata->functions[selector];
> +}
> +
> +static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
> +                                   unsigned muxval)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +       unsigned mux_bits = priv->socdata->mux_bits;
> +       unsigned reg_stride = priv->socdata->reg_stride;
> +       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_group_set(struct udevice *dev,
> +                                    unsigned group_selector,
> +                                    unsigned func_selector)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +       const struct uniphier_pinctrl_group *group =
> +                                       &priv->socdata->groups[group_selector];
> +       const struct uniphier_pmx_data *pmx_data = group->pmx_data;
> +       const unsigned num_pmx_data = group->num_pmx_data;
> +       int i;
> +
> +       for (i = 0; i < num_pmx_data; i++)
> +               uniphier_pinmux_set_one(dev, pmx_data[i].pin,
> +                                       pmx_data[i].muxval);
> +
> +       return 0;
> +}
> +
> +const struct pinctrl_ops uniphier_pinctrl_ops = {
> +       .get_groups_count = uniphier_pinctrl_get_groups_count,
> +       .get_group_name = uniphier_pinctrl_get_group_name,
> +       .get_functions_count = uniphier_pinmux_get_functions_count,
> +       .get_function_name = uniphier_pinmux_get_function_name,
> +       .pinmux_group_set = uniphier_pinmux_group_set,
> +       .set_state = pinctrl_generic_set_state,
> +};
> +
> +int uniphier_pinctrl_probe(struct udevice *dev,
> +                          struct uniphier_pinctrl_socdata *socdata)
> +{
> +       struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
> +       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..db74838
> --- /dev/null
> +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
> @@ -0,0 +1,57 @@
> +/*
> + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#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

Since this is local data you don't really need the UNIPHIER prefix,
but it's up to you.

> +
> +struct uniphier_pmx_data {

comments please on these structures.

> +       unsigned pin;
> +       unsigned muxval;
> +};
> +
> +struct uniphier_pinctrl_group {
> +       const char *name;
> +       const struct uniphier_pmx_data *pmx_data;
> +       unsigned num_pmx_data;
> +};
> +
> +struct uniphier_pinctrl_socdata {
> +       const struct uniphier_pinctrl_group *groups;
> +       int groups_count;
> +       const char * const *functions;
> +       int functions_count;
> +       unsigned mux_bits;
> +       unsigned reg_stride;
> +       bool load_pinctrl;
> +};
> +
> +#define UNIPHIER_PINCTRL_GROUP(grp)                    \
> +       {                                               \
> +               .name = #grp,                           \
> +               .pmx_data = grp##_pmx,                  \
> +               .num_pmx_data = ARRAY_SIZE(grp##_pmx),  \
> +       }
> +
> +struct uniphier_pinctrl_priv {
> +       void __iomem *base;
> +       struct uniphier_pinctrl_socdata *socdata;
> +};
> +
> +extern const struct pinctrl_ops uniphier_pinctrl_ops;

It's a shame this cannot be static...

> +
> +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
>

Regards,
Simon
Masahiro Yamada Sept. 2, 2015, 3:30 a.m. UTC | #2
2015-09-02 11:48 GMT+09:00 Simon Glass <sjg@chromium.org>:

>> diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
>> new file mode 100644
>> index 0000000..db74838
>> --- /dev/null
>> +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
>> @@ -0,0 +1,57 @@
>> +/*
>> + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#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
>
> Since this is local data you don't really need the UNIPHIER prefix,
> but it's up to you.

I want to make sure that these macros are not global ones, but our
SoC-specific ones.

I prefer to add some prefixes.


>> +
>> +struct uniphier_pmx_data {
>
> comments please on these structures.

I will think of that, but I believe this is also up to me.

These are driver-local structures,
so comments for each structure are not the requirement.
Moreover, most of them have clear names.

At least, when I sent some driver patches to Linux, I was never told
to add comment blocks to driver-specific structures.



>> +       unsigned pin;
>> +       unsigned muxval;
>> +};
>> +
>> +struct uniphier_pinctrl_group {
>> +       const char *name;
>> +       const struct uniphier_pmx_data *pmx_data;
>> +       unsigned num_pmx_data;
>> +};
>> +
>> +struct uniphier_pinctrl_socdata {
>> +       const struct uniphier_pinctrl_group *groups;
>> +       int groups_count;
>> +       const char * const *functions;
>> +       int functions_count;
>> +       unsigned mux_bits;
>> +       unsigned reg_stride;
>> +       bool load_pinctrl;
>> +};
>> +
>> +#define UNIPHIER_PINCTRL_GROUP(grp)                    \
>> +       {                                               \
>> +               .name = #grp,                           \
>> +               .pmx_data = grp##_pmx,                  \
>> +               .num_pmx_data = ARRAY_SIZE(grp##_pmx),  \
>> +       }
>> +
>> +struct uniphier_pinctrl_priv {
>> +       void __iomem *base;
>> +       struct uniphier_pinctrl_socdata *socdata;
>> +};
>> +
>> +extern const struct pinctrl_ops uniphier_pinctrl_ops;
>
> It's a shame this cannot be static...


Indeed.
Simon Glass Sept. 2, 2015, 3:46 a.m. UTC | #3
Hi Masahiro,

On 1 September 2015 at 21:30, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> 2015-09-02 11:48 GMT+09:00 Simon Glass <sjg@chromium.org>:
>
>>> diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
>>> new file mode 100644
>>> index 0000000..db74838
>>> --- /dev/null
>>> +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
>>> @@ -0,0 +1,57 @@
>>> +/*
>>> + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#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
>>
>> Since this is local data you don't really need the UNIPHIER prefix,
>> but it's up to you.
>
> I want to make sure that these macros are not global ones, but our
> SoC-specific ones.
>
> I prefer to add some prefixes.
>
>
>>> +
>>> +struct uniphier_pmx_data {
>>
>> comments please on these structures.
>
> I will think of that, but I believe this is also up to me.
>
> These are driver-local structures,
> so comments for each structure are not the requirement.
> Moreover, most of them have clear names.
>
> At least, when I sent some driver patches to Linux, I was never told
> to add comment blocks to driver-specific structures.

That might be because Linux is allergic to comments. Everyone is
supposed to know already (presumably from birth) how things work :-)

Some of them I can guess, but others are not clear - e.g. mux_bits,
reg_stride, load_pinctrl... I think it is better that our coding
standard requires comments.

>
>
>
>>> +       unsigned pin;
>>> +       unsigned muxval;
>>> +};
>>> +
>>> +struct uniphier_pinctrl_group {
>>> +       const char *name;
>>> +       const struct uniphier_pmx_data *pmx_data;
>>> +       unsigned num_pmx_data;
>>> +};
>>> +
>>> +struct uniphier_pinctrl_socdata {
>>> +       const struct uniphier_pinctrl_group *groups;
>>> +       int groups_count;
>>> +       const char * const *functions;
>>> +       int functions_count;
>>> +       unsigned mux_bits;
>>> +       unsigned reg_stride;
>>> +       bool load_pinctrl;
>>> +};
>>> +
>>> +#define UNIPHIER_PINCTRL_GROUP(grp)                    \
>>> +       {                                               \
>>> +               .name = #grp,                           \
>>> +               .pmx_data = grp##_pmx,                  \
>>> +               .num_pmx_data = ARRAY_SIZE(grp##_pmx),  \
>>> +       }
>>> +
>>> +struct uniphier_pinctrl_priv {
>>> +       void __iomem *base;
>>> +       struct uniphier_pinctrl_socdata *socdata;
>>> +};
>>> +
>>> +extern const struct pinctrl_ops uniphier_pinctrl_ops;
>>
>> It's a shame this cannot be static...
>
>
> Indeed.

Regards,
Simon
diff mbox

Patch

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 30b8e45..9c12429 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -106,4 +106,6 @@  config PINCTRL_SANDBOX
 
 endif
 
+source "drivers/pinctrl/uniphier/Kconfig"
+
 endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 35decf4..d0eb263 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -2,3 +2,5 @@  obj-y					+= pinctrl-uclass.o
 obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC)	+= pinctrl-generic.o
 
 obj-$(CONFIG_PINCTRL_SANDBOX)	+= pinctrl-sandbox.o
+
+obj-$(CONFIG_ARCH_UNIPHIER)	+= uniphier/
diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
new file mode 100644
index 0000000..29a623d
--- /dev/null
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -0,0 +1,6 @@ 
+if ARCH_UNIPHIER
+
+config PINCTRL_UNIPHIER_CORE
+	bool
+
+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..f008aea
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -0,0 +1,134 @@ 
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@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"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->socdata->groups_count;
+}
+
+static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
+						   unsigned selector)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->socdata->groups[selector].name;
+}
+
+static int uniphier_pinmux_get_functions_count(struct udevice *dev)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->socdata->functions_count;
+}
+
+static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
+						     unsigned selector)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+	return priv->socdata->functions[selector];
+}
+
+static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
+				    unsigned muxval)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	unsigned mux_bits = priv->socdata->mux_bits;
+	unsigned reg_stride = priv->socdata->reg_stride;
+	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_group_set(struct udevice *dev,
+				     unsigned group_selector,
+				     unsigned func_selector)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct uniphier_pinctrl_group *group =
+					&priv->socdata->groups[group_selector];
+	const struct uniphier_pmx_data *pmx_data = group->pmx_data;
+	const unsigned num_pmx_data = group->num_pmx_data;
+	int i;
+
+	for (i = 0; i < num_pmx_data; i++)
+		uniphier_pinmux_set_one(dev, pmx_data[i].pin,
+					pmx_data[i].muxval);
+
+	return 0;
+}
+
+const struct pinctrl_ops uniphier_pinctrl_ops = {
+	.get_groups_count = uniphier_pinctrl_get_groups_count,
+	.get_group_name = uniphier_pinctrl_get_group_name,
+	.get_functions_count = uniphier_pinmux_get_functions_count,
+	.get_function_name = uniphier_pinmux_get_function_name,
+	.pinmux_group_set = uniphier_pinmux_group_set,
+	.set_state = pinctrl_generic_set_state,
+};
+
+int uniphier_pinctrl_probe(struct udevice *dev,
+			   struct uniphier_pinctrl_socdata *socdata)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	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..db74838
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -0,0 +1,57 @@ 
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#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_pmx_data {
+	unsigned pin;
+	unsigned muxval;
+};
+
+struct uniphier_pinctrl_group {
+	const char *name;
+	const struct uniphier_pmx_data *pmx_data;
+	unsigned num_pmx_data;
+};
+
+struct uniphier_pinctrl_socdata {
+	const struct uniphier_pinctrl_group *groups;
+	int groups_count;
+	const char * const *functions;
+	int functions_count;
+	unsigned mux_bits;
+	unsigned reg_stride;
+	bool load_pinctrl;
+};
+
+#define UNIPHIER_PINCTRL_GROUP(grp)			\
+	{						\
+		.name = #grp,				\
+		.pmx_data = grp##_pmx,			\
+		.num_pmx_data = ARRAY_SIZE(grp##_pmx),	\
+	}
+
+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__ */