All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masahiro Yamada <yamada.masahiro@socionext.com>
To: linux-clk@vger.kernel.org
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@codeaurora.org>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs
Date: Mon, 28 Dec 2015 19:20:58 +0900	[thread overview]
Message-ID: <1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com> (raw)

This is the initial commit for the UniPhier clock drivers, including
support for PH1-sLD3, PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5, and
ProXstream2/PH1-LD6b.

To improve the code maintainability, the driver consists of common
functions (clk-uniphier-core.c) and clock data arrays needed to
support each SoC.

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

Changes in v2:
  - split emmc_hw_reset
  - make SD clock rate-controllable
  - add CLK_SET_RATE_PARENT flag to mux, gate, fixed-factor clocks

 MAINTAINERS                              |   1 +
 drivers/clk/Kconfig                      |   1 +
 drivers/clk/Makefile                     |   1 +
 drivers/clk/uniphier/Kconfig             |  35 ++++
 drivers/clk/uniphier/Makefile            |  10 +
 drivers/clk/uniphier/clk-ph1-ld4.c       | 117 ++++++++++++
 drivers/clk/uniphier/clk-ph1-pro4.c      | 117 ++++++++++++
 drivers/clk/uniphier/clk-ph1-pro5.c      | 107 +++++++++++
 drivers/clk/uniphier/clk-ph1-sld3.c      | 117 ++++++++++++
 drivers/clk/uniphier/clk-ph1-sld8.c      | 107 +++++++++++
 drivers/clk/uniphier/clk-proxstream2.c   |  88 +++++++++
 drivers/clk/uniphier/clk-uniphier-core.c | 151 +++++++++++++++
 drivers/clk/uniphier/clk-uniphier-mio.c  | 315 +++++++++++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier-peri.c | 175 +++++++++++++++++
 drivers/clk/uniphier/clk-uniphier.h      |  68 +++++++
 15 files changed, 1410 insertions(+)
 create mode 100644 drivers/clk/uniphier/Kconfig
 create mode 100644 drivers/clk/uniphier/Makefile
 create mode 100644 drivers/clk/uniphier/clk-ph1-ld4.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-pro4.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-pro5.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-sld3.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-sld8.c
 create mode 100644 drivers/clk/uniphier/clk-proxstream2.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-core.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-mio.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-peri.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index fc08493..6c10e9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1644,6 +1644,7 @@ F:	arch/arm/mach-uniphier/
 F:	arch/arm/mm/cache-uniphier.c
 F:	arch/arm64/boot/dts/socionext/
 F:	drivers/bus/uniphier-system-bus.c
+F:	drivers/clk/uniphier/
 F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/pinctrl/uniphier/
 F:	drivers/tty/serial/8250/8250_uniphier.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c3e3a02..7580323 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -191,6 +191,7 @@ config COMMON_CLK_CDCE706
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/qcom/Kconfig"
+source "drivers/clk/uniphier/Kconfig"
 
 endmenu
 
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 820714c..ab9d1bd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
+obj-$(CONFIG_CLK_UNIPHIER)		+= uniphier/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
 obj-$(CONFIG_X86)			+= x86/
diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
new file mode 100644
index 0000000..7606f27
--- /dev/null
+++ b/drivers/clk/uniphier/Kconfig
@@ -0,0 +1,35 @@
+menuconfig CLK_UNIPHIER
+	bool "Clock drivers for UniPhier SoCs"
+	depends on ARCH_UNIPHIER
+	depends on OF
+	default y
+	help
+	  Supports clock drivers for UniPhier SoCs.
+
+if CLK_UNIPHIER
+
+config CLK_UNIPHIER_PH1_SLD3
+	bool "Clock driver for UniPhier PH1-sLD3 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_LD4
+	bool "Clock driver for UniPhier PH1-LD4 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_PRO4
+	bool "Clock driver for UniPhier PH1-Pro4 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_SLD8
+	bool "Clock driver for UniPhier PH1-sLD8 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_PRO5
+	bool "Clock driver for UniPhier PH1-Pro5 SoC"
+	default y
+
+config CLK_UNIPHIER_PROXSTREAM2
+	bool "Clock driver for UniPhier ProXstream2/PH1-LD6b SoC"
+	default y
+
+endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
new file mode 100644
index 0000000..3be1a17
--- /dev/null
+++ b/drivers/clk/uniphier/Makefile
@@ -0,0 +1,10 @@
+obj-y += clk-uniphier-core.o
+obj-y += clk-uniphier-peri.o
+obj-y += clk-uniphier-mio.o
+
+obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD3)	+= clk-ph1-sld3.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_LD4)	+= clk-ph1-ld4.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO4)	+= clk-ph1-pro4.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD8)	+= clk-ph1-sld8.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO5)	+= clk-ph1-pro5.o
+obj-$(CONFIG_CLK_UNIPHIER_PROXSTREAM2)	+= clk-proxstream2.o
diff --git a/drivers/clk/uniphier/clk-ph1-ld4.c b/drivers/clk/uniphier/clk-ph1-ld4.c
new file mode 100644
index 0000000..48d342f
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-ld4.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_ld4_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 65,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288000,
+			.div = 24576,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 24,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_ld4_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_ld4_clk_idata);
+}
+CLK_OF_DECLARE(ph1_ld4_clk, "socionext,ph1-ld4-sysctrl", ph1_ld4_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-pro4.c b/drivers/clk/uniphier/clk-ph1-pro4.c
new file mode 100644
index 0000000..052813a
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-pro4.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_pro4_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 64,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288,
+			.div = 25,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 256,
+			.div = 125,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 8,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_pro4_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro4_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro4_clk, "socionext,ph1-pro4-sysctrl", ph1_pro4_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-pro5.c b/drivers/clk/uniphier/clk-ph1-pro5.c
new file mode 100644
index 0000000..9f782d9
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-pro5.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_pro5_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 120,
+			.div = 1,
+		},
+	},
+	{
+		.name = "dapll1",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 128,
+			.div = 125,
+		},
+	},
+	{
+		.name = "dapll2",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 144,
+			.div = 5,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "dapll2",
+			.mult = 1,
+			.div = 8,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_pro5_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro5_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro5_clk, "socionext,ph1-pro5-sysctrl", ph1_pro5_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-sld3.c b/drivers/clk/uniphier/clk-ph1-sld3.c
new file mode 100644
index 0000000..7249a81
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-sld3.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_sld3_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 65,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288000,
+			.div = 24576,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 24,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_sld3_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_sld3_clk_idata);
+}
+CLK_OF_DECLARE(ph1_sld3_clk, "socionext,ph1-sld3-sysctrl", ph1_sld3_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-sld8.c b/drivers/clk/uniphier/clk-ph1-sld8.c
new file mode 100644
index 0000000..bfebd38
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-sld8.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_sld8_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 64,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288,
+			.div = 25,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 20,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_sld8_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_sld8_clk_idata);
+}
+CLK_OF_DECLARE(ph1_sld8_clk, "socionext,ph1-sld8-sysctrl", ph1_sld8_clk_init);
diff --git a/drivers/clk/uniphier/clk-proxstream2.c b/drivers/clk/uniphier/clk-proxstream2.c
new file mode 100644
index 0000000..b3ffedc
--- /dev/null
+++ b/drivers/clk/uniphier/clk-proxstream2.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data proxstream2_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 96,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 27,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init proxstream2_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, proxstream2_clk_idata);
+}
+CLK_OF_DECLARE(proxstream2_clk, "socionext,proxstream2-sysctrl",
+	       proxstream2_clk_init);
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
new file mode 100644
index 0000000..8680101
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)		"uniphier-clk: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk-uniphier.h"
+
+static void __init uniphier_clk_update_parent_name(struct device_node *np,
+						   const char **parent_name)
+{
+	const char *new_name;
+	int index;
+
+	if (!parent_name || !*parent_name)
+		return;
+
+	if (strncmp(*parent_name, UNIPHIER_CLK_EXT, strlen(UNIPHIER_CLK_EXT)))
+		return;
+
+	index = of_property_match_string(np, "clock-names",
+				*parent_name + strlen(UNIPHIER_CLK_EXT));
+	new_name = of_clk_get_parent_name(np, index);
+	if (new_name)
+		*parent_name = new_name;
+}
+
+static struct clk * __init uniphier_clk_register(struct device_node *np,
+						 void __iomem *regbase,
+					  struct uniphier_clk_init_data *idata)
+{
+	int i;
+
+	switch (idata->type) {
+	case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
+		uniphier_clk_update_parent_name(np,
+					&idata->data.factor.parent_name);
+		return clk_register_fixed_factor(NULL, idata->name,
+						 idata->data.factor.parent_name,
+						 CLK_SET_RATE_PARENT,
+						 idata->data.factor.mult,
+						 idata->data.factor.div);
+	case UNIPHIER_CLK_TYPE_FIXED_RATE:
+		return clk_register_fixed_rate(NULL, idata->name, NULL,
+					       CLK_IS_ROOT,
+					       idata->data.rate.fixed_rate);
+	case UNIPHIER_CLK_TYPE_GATE:
+		uniphier_clk_update_parent_name(np,
+						&idata->data.gate.parent_name);
+		return clk_register_gate(NULL, idata->name,
+					 idata->data.gate.parent_name,
+					 idata->data.gate.parent_name ?
+					 CLK_SET_RATE_PARENT : CLK_IS_ROOT,
+					 regbase + idata->data.gate.reg,
+					 idata->data.gate.bit_idx, 0, NULL);
+	case UNIPHIER_CLK_TYPE_MUX:
+		for (i = 0; i < idata->data.mux.num_parents; i++)
+			uniphier_clk_update_parent_name(np,
+					&idata->data.mux.parent_names[i]);
+		return clk_register_mux(NULL, idata->name,
+					idata->data.mux.parent_names,
+					idata->data.mux.num_parents,
+					CLK_SET_RATE_PARENT,
+					regbase + idata->data.mux.reg,
+					idata->data.mux.shift,
+					ilog2(idata->data.mux.num_parents),
+					0, NULL);
+	default:
+		WARN(1, "unsupported clock type\n");
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+int __init uniphier_clk_init(struct device_node *np,
+			     struct uniphier_clk_init_data *idata)
+{
+	struct clk_onecell_data *clk_data;
+	struct uniphier_clk_init_data *p;
+	void __iomem *regbase;
+	int max_index = 0;
+	int ret;
+
+	regbase = of_iomap(np, 0);
+	if (!regbase)
+		return -ENOMEM;
+
+	for (p = idata; p->name; p++)
+		max_index = max(max_index, p->output_index);
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->clk_num = max_index + 1;
+	clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
+				 GFP_KERNEL);
+	if (!clk_data->clks) {
+		ret = -ENOMEM;
+		goto free_clk_data;
+	}
+
+	for (p = idata; p->name; p++) {
+		pr_debug("register %s (%s[%d])\n", p->name, np->name,
+			 p->output_index);
+		p->clk = uniphier_clk_register(np, regbase, p);
+		if (IS_ERR(p->clk)) {
+			pr_err("failed to register %s\n", p->name);
+			ret = PTR_ERR(p->clk);
+			goto unregister;
+		}
+
+		if (p->output_index >= 0)
+			clk_data->clks[p->output_index] = p->clk;
+	}
+
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	if (ret)
+		goto unregister;
+
+	return ret;
+unregister:
+	for (p--; p >= idata; p--) {
+		pr_debug("unregister %s (%s[%d])\n", p->name, np->name,
+			 p->output_index);
+		clk_unregister(p->clk);
+		p->clk = NULL;
+	}
+	kfree(clk_data->clks);
+free_clk_data:
+	kfree(clk_data);
+
+	pr_err("%s: init failed with error %d\n", np->full_name, ret);
+
+	return ret;
+}
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
new file mode 100644
index 0000000..ad6491b
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_MIO_CLK_SD_FIXED					\
+	{								\
+		.name = "sd-44m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 44444444,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-33m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 33333333,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-50m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 50000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-67m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 66666666,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-100m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 100000000,			\
+		},							\
+	},								\
+	{								\
+		.name = "sd-40m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 40000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-25m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 25000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-22m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 22222222,				\
+		},							\
+	}
+
+
+#define UNIPHIER_MIO_CLK_SD(ch, index)					\
+	{								\
+		.name = "sd" #ch "-clksel0",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd-44m",				\
+				"sd-33m",				\
+				"sd-50m",				\
+				"sd-67m",				\
+			},						\
+			.num_parents = 4,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.shift = 16,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-clksel1",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd-100m",				\
+				"sd-40m",				\
+				"sd-25m",				\
+				"sd-22m",				\
+			},						\
+			.num_parents = 4,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.shift = 8,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-clkmode",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd" #ch "-clksel0",			\
+				"sd" #ch "-clksel1",			\
+			},						\
+			.num_parents = 2,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.shift = 12,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-clken",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-clkmode",		\
+			.reg = 0x20 + 0x200 * ch,			\
+			.bit_idx = 8,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-bridge-reset",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-clken",		\
+			.reg = 0x110 + 0x200 * ch,			\
+			.bit_idx = 26,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch,					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-bridge-reset",	\
+			.reg = 0x110 + 0x200 * ch,			\
+			.bit_idx = 0,					\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_SD_HW_RESET(ch, index)				\
+	{								\
+		.name = "sd" #ch "-hw-reset",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = NULL,				\
+			.reg = 0x80 + 0x200 * ch,			\
+			.bit_idx = 0,					\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_EHCI(ch, index)				\
+	{								\
+		.name = "ehci" #ch "-phy-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = UNIPHIER_CLK_EXT "ehci",		\
+			.reg = 0x20 + 0x200 * ch,			\
+			.bit_idx = 29,					\
+		},							\
+	},								\
+	{								\
+		.name = "ehci" #ch "-link-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "ehci" #ch "-phy-clken",		\
+			.reg = 0x20 + 0x200 * ch,			\
+			.bit_idx = 28,					\
+		},							\
+	},								\
+	{								\
+		.name = "ehci" #ch "-bridge-reset",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "ehci" #ch "-link-clken",	\
+			.reg = 0x110 + 0x200 * ch,			\
+			.bit_idx = 24,					\
+		},							\
+	},								\
+	{								\
+		.name = "ehci" #ch,					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "ehci" #ch "-bridge-reset",	\
+			.reg = 0x114 + 0x200 * ch,			\
+			.bit_idx = 0,					\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_DMAC(index)					\
+	{								\
+		.name = "miodmac-clken",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = UNIPHIER_CLK_EXT "stdmac",	\
+			.reg = 0x20,					\
+			.bit_idx = 25,					\
+		},							\
+	},								\
+	{								\
+		.name = "miodmac",					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "miodmac-clken",			\
+			.reg = 0x110,					\
+			.bit_idx = 17,					\
+		},							\
+	}
+
+static struct uniphier_clk_init_data ph1_sld3_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(0, 3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_EHCI(2, 6),
+	UNIPHIER_MIO_CLK_EHCI(3, 7),
+	UNIPHIER_MIO_CLK_DMAC(8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_ld4_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_EHCI(2, 6),
+	UNIPHIER_MIO_CLK_DMAC(8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro4_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD(2, 2),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_DMAC(8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro5_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3),
+	{ /* sentinel */ }
+};
+
+static void __init ph1_sld3_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_sld3_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_sld3_mio_clk, "socionext,ph1-sld3-mioctrl",
+	       ph1_sld3_mio_clk_init);
+
+static void __init ph1_ld4_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_ld4_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_ld4_mio_clk, "socionext,ph1-ld4-mioctrl",
+	       ph1_ld4_mio_clk_init);
+CLK_OF_DECLARE(ph1_sld8_mio_clk, "socionext,ph1-sld8-mioctrl",
+	       ph1_ld4_mio_clk_init);
+
+static void __init ph1_pro4_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro4_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro4_mio_clk, "socionext,ph1-pro4-mioctrl",
+	       ph1_pro4_mio_clk_init);
+
+static void __init ph1_pro5_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro5_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro5_mio_clk, "socionext,ph1-pro5-mioctrl",
+	       ph1_pro5_mio_clk_init);
+CLK_OF_DECLARE(proxstream2_mio_clk, "socionext,proxstream2-mioctrl",
+	       ph1_pro5_mio_clk_init);
diff --git a/drivers/clk/uniphier/clk-uniphier-peri.c b/drivers/clk/uniphier/clk-uniphier-peri.c
new file mode 100644
index 0000000..adaae8e
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-peri.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_PERI_CLK_UART(ch, index)			\
+	{							\
+		.name = "uart" #ch "-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = UNIPHIER_CLK_EXT "uart",	\
+			.reg = 0x24,				\
+			.bit_idx = 19 + ch,			\
+		},						\
+	},							\
+	{							\
+		.name = "uart" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "uart" #ch "-clken",	\
+			.reg = 0x114,				\
+			.bit_idx = 19 + ch,			\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_I2C_COMMON				\
+	{							\
+		.name = "i2c-clken",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = UNIPHIER_CLK_EXT "i2c",	\
+			.reg = 0x20,				\
+			.bit_idx = 1,				\
+		},						\
+	},							\
+	{							\
+		.name = "i2c-reset",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = "i2c-clken",		\
+			.reg = 0x110,				\
+			.bit_idx = 1,				\
+		},						\
+	}
+
+
+#define UNIPHIER_PERI_CLK_I2C(ch, index)			\
+	{							\
+		.name = "i2c" #ch "-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = "i2c-reset",		\
+			.reg = 0x24,				\
+			.bit_idx = 5 + ch,			\
+		},						\
+	},							\
+	{							\
+		.name = "i2c" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "i2c" #ch "-clken",	\
+			.reg = 0x114,				\
+			.bit_idx = 5 + ch,			\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_FI2C(ch, index)			\
+	{							\
+		.name = "fi2c" #ch "-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = UNIPHIER_CLK_EXT "fi2c",	\
+			.reg = 0x24,				\
+			.bit_idx = 24 + ch,			\
+		},						\
+	},							\
+	{							\
+		.name = "fi2c" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = index,				\
+		.data.gate = {					\
+			.parent_name = "fi2c" #ch "-clken",	\
+			.reg = 0x114,				\
+			.bit_idx = 24 + ch,			\
+		},						\
+	}
+
+static struct uniphier_clk_init_data ph1_ld4_peri_clk_idata[] __initdata = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_I2C_COMMON,
+	UNIPHIER_PERI_CLK_I2C(0, 4),
+	UNIPHIER_PERI_CLK_I2C(1, 5),
+	UNIPHIER_PERI_CLK_I2C(2, 6),
+	UNIPHIER_PERI_CLK_I2C(3, 7),
+	UNIPHIER_PERI_CLK_I2C(4, 8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro4_peri_clk_idata[] __initdata = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_FI2C(0, 4),
+	UNIPHIER_PERI_CLK_FI2C(1, 5),
+	UNIPHIER_PERI_CLK_FI2C(2, 6),
+	UNIPHIER_PERI_CLK_FI2C(3, 7),
+	/* no I2C ch4 */
+	UNIPHIER_PERI_CLK_FI2C(5, 9),
+	UNIPHIER_PERI_CLK_FI2C(6, 10),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro5_peri_clk_idata[] __initdata = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_FI2C(0, 4),
+	UNIPHIER_PERI_CLK_FI2C(1, 5),
+	UNIPHIER_PERI_CLK_FI2C(2, 6),
+	UNIPHIER_PERI_CLK_FI2C(3, 7),
+	UNIPHIER_PERI_CLK_FI2C(4, 8),
+	UNIPHIER_PERI_CLK_FI2C(5, 9),
+	UNIPHIER_PERI_CLK_FI2C(6, 10),
+	{ /* sentinel */ }
+};
+
+static void __init ph1_ld4_peri_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_ld4_peri_clk_idata);
+}
+CLK_OF_DECLARE(ph1_ld4_peri_clk, "socionext,ph1-ld4-perictrl",
+	       ph1_ld4_peri_clk_init);
+CLK_OF_DECLARE(ph1_sld8_peri_clk, "socionext,ph1-sld8-perictrl",
+	       ph1_ld4_peri_clk_init);
+
+static void __init ph1_pro4_peri_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro4_peri_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro4_peri_clk, "socionext,ph1-pro4-perictrl",
+	       ph1_pro4_peri_clk_init);
+
+static void __init ph1_pro5_peri_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro5_peri_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro5_peri_clk, "socionext,ph1-pro5-perictrl",
+	       ph1_pro5_peri_clk_init);
+CLK_OF_DECLARE(proxstream2_peri_clk, "socionext,proxstream2-perictrl",
+	       ph1_pro5_peri_clk_init);
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
new file mode 100644
index 0000000..05277b6
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CLK_UNIPHIER_H__
+#define __CLK_UNIPHIER_H__
+
+#include <linux/kernel.h>
+
+#define UNIPHIER_CLK_EXT	"[EXT]"
+
+enum uniphier_clk_type {
+	UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+	UNIPHIER_CLK_TYPE_FIXED_RATE,
+	UNIPHIER_CLK_TYPE_GATE,
+	UNIPHIER_CLK_TYPE_MUX,
+};
+
+struct uniphier_clk_fixed_factor_data {
+	const char *parent_name;
+	unsigned int mult;
+	unsigned int div;
+};
+
+struct uniphier_clk_fixed_rate_data {
+	unsigned long fixed_rate;
+};
+
+struct uniphier_clk_gate_data {
+	const char *parent_name;
+	unsigned int reg;
+	u8 bit_idx;
+};
+
+struct uniphier_clk_mux_data {
+	const char *parent_names[4];
+	u8 num_parents;
+	unsigned int reg;
+	u8 shift;
+};
+
+struct uniphier_clk_init_data {
+	const char *name;
+	enum uniphier_clk_type type;
+	int output_index;
+	union {
+		struct uniphier_clk_fixed_factor_data factor;
+		struct uniphier_clk_fixed_rate_data rate;
+		struct uniphier_clk_gate_data gate;
+		struct uniphier_clk_mux_data mux;
+	} data;
+	struct clk *clk;
+};
+
+int uniphier_clk_init(struct device_node *np,
+		      struct uniphier_clk_init_data *idata);
+
+#endif /* __CLK_UNIPHIER_H__ */
-- 
1.9.1


WARNING: multiple messages have this Message-ID (diff)
From: yamada.masahiro@socionext.com (Masahiro Yamada)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs
Date: Mon, 28 Dec 2015 19:20:58 +0900	[thread overview]
Message-ID: <1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com> (raw)

This is the initial commit for the UniPhier clock drivers, including
support for PH1-sLD3, PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5, and
ProXstream2/PH1-LD6b.

To improve the code maintainability, the driver consists of common
functions (clk-uniphier-core.c) and clock data arrays needed to
support each SoC.

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

Changes in v2:
  - split emmc_hw_reset
  - make SD clock rate-controllable
  - add CLK_SET_RATE_PARENT flag to mux, gate, fixed-factor clocks

 MAINTAINERS                              |   1 +
 drivers/clk/Kconfig                      |   1 +
 drivers/clk/Makefile                     |   1 +
 drivers/clk/uniphier/Kconfig             |  35 ++++
 drivers/clk/uniphier/Makefile            |  10 +
 drivers/clk/uniphier/clk-ph1-ld4.c       | 117 ++++++++++++
 drivers/clk/uniphier/clk-ph1-pro4.c      | 117 ++++++++++++
 drivers/clk/uniphier/clk-ph1-pro5.c      | 107 +++++++++++
 drivers/clk/uniphier/clk-ph1-sld3.c      | 117 ++++++++++++
 drivers/clk/uniphier/clk-ph1-sld8.c      | 107 +++++++++++
 drivers/clk/uniphier/clk-proxstream2.c   |  88 +++++++++
 drivers/clk/uniphier/clk-uniphier-core.c | 151 +++++++++++++++
 drivers/clk/uniphier/clk-uniphier-mio.c  | 315 +++++++++++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier-peri.c | 175 +++++++++++++++++
 drivers/clk/uniphier/clk-uniphier.h      |  68 +++++++
 15 files changed, 1410 insertions(+)
 create mode 100644 drivers/clk/uniphier/Kconfig
 create mode 100644 drivers/clk/uniphier/Makefile
 create mode 100644 drivers/clk/uniphier/clk-ph1-ld4.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-pro4.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-pro5.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-sld3.c
 create mode 100644 drivers/clk/uniphier/clk-ph1-sld8.c
 create mode 100644 drivers/clk/uniphier/clk-proxstream2.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-core.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-mio.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-peri.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index fc08493..6c10e9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1644,6 +1644,7 @@ F:	arch/arm/mach-uniphier/
 F:	arch/arm/mm/cache-uniphier.c
 F:	arch/arm64/boot/dts/socionext/
 F:	drivers/bus/uniphier-system-bus.c
+F:	drivers/clk/uniphier/
 F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/pinctrl/uniphier/
 F:	drivers/tty/serial/8250/8250_uniphier.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c3e3a02..7580323 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -191,6 +191,7 @@ config COMMON_CLK_CDCE706
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/qcom/Kconfig"
+source "drivers/clk/uniphier/Kconfig"
 
 endmenu
 
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 820714c..ab9d1bd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
+obj-$(CONFIG_CLK_UNIPHIER)		+= uniphier/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
 obj-$(CONFIG_X86)			+= x86/
diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
new file mode 100644
index 0000000..7606f27
--- /dev/null
+++ b/drivers/clk/uniphier/Kconfig
@@ -0,0 +1,35 @@
+menuconfig CLK_UNIPHIER
+	bool "Clock drivers for UniPhier SoCs"
+	depends on ARCH_UNIPHIER
+	depends on OF
+	default y
+	help
+	  Supports clock drivers for UniPhier SoCs.
+
+if CLK_UNIPHIER
+
+config CLK_UNIPHIER_PH1_SLD3
+	bool "Clock driver for UniPhier PH1-sLD3 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_LD4
+	bool "Clock driver for UniPhier PH1-LD4 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_PRO4
+	bool "Clock driver for UniPhier PH1-Pro4 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_SLD8
+	bool "Clock driver for UniPhier PH1-sLD8 SoC"
+	default y
+
+config CLK_UNIPHIER_PH1_PRO5
+	bool "Clock driver for UniPhier PH1-Pro5 SoC"
+	default y
+
+config CLK_UNIPHIER_PROXSTREAM2
+	bool "Clock driver for UniPhier ProXstream2/PH1-LD6b SoC"
+	default y
+
+endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
new file mode 100644
index 0000000..3be1a17
--- /dev/null
+++ b/drivers/clk/uniphier/Makefile
@@ -0,0 +1,10 @@
+obj-y += clk-uniphier-core.o
+obj-y += clk-uniphier-peri.o
+obj-y += clk-uniphier-mio.o
+
+obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD3)	+= clk-ph1-sld3.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_LD4)	+= clk-ph1-ld4.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO4)	+= clk-ph1-pro4.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD8)	+= clk-ph1-sld8.o
+obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO5)	+= clk-ph1-pro5.o
+obj-$(CONFIG_CLK_UNIPHIER_PROXSTREAM2)	+= clk-proxstream2.o
diff --git a/drivers/clk/uniphier/clk-ph1-ld4.c b/drivers/clk/uniphier/clk-ph1-ld4.c
new file mode 100644
index 0000000..48d342f
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-ld4.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_ld4_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 65,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288000,
+			.div = 24576,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 24,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_ld4_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_ld4_clk_idata);
+}
+CLK_OF_DECLARE(ph1_ld4_clk, "socionext,ph1-ld4-sysctrl", ph1_ld4_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-pro4.c b/drivers/clk/uniphier/clk-ph1-pro4.c
new file mode 100644
index 0000000..052813a
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-pro4.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_pro4_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 64,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288,
+			.div = 25,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 256,
+			.div = 125,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 8,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_pro4_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro4_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro4_clk, "socionext,ph1-pro4-sysctrl", ph1_pro4_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-pro5.c b/drivers/clk/uniphier/clk-ph1-pro5.c
new file mode 100644
index 0000000..9f782d9
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-pro5.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_pro5_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 120,
+			.div = 1,
+		},
+	},
+	{
+		.name = "dapll1",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 128,
+			.div = 125,
+		},
+	},
+	{
+		.name = "dapll2",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 144,
+			.div = 5,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "dapll2",
+			.mult = 1,
+			.div = 8,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_pro5_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro5_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro5_clk, "socionext,ph1-pro5-sysctrl", ph1_pro5_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-sld3.c b/drivers/clk/uniphier/clk-ph1-sld3.c
new file mode 100644
index 0000000..7249a81
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-sld3.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_sld3_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 65,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288000,
+			.div = 24576,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 24,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_sld3_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_sld3_clk_idata);
+}
+CLK_OF_DECLARE(ph1_sld3_clk, "socionext,ph1-sld3-sysctrl", ph1_sld3_clk_init);
diff --git a/drivers/clk/uniphier/clk-ph1-sld8.c b/drivers/clk/uniphier/clk-ph1-sld8.c
new file mode 100644
index 0000000..bfebd38
--- /dev/null
+++ b/drivers/clk/uniphier/clk-ph1-sld8.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data ph1_sld8_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 64,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 288,
+			.div = 25,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 20,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 18,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init ph1_sld8_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_sld8_clk_idata);
+}
+CLK_OF_DECLARE(ph1_sld8_clk, "socionext,ph1-sld8-sysctrl", ph1_sld8_clk_init);
diff --git a/drivers/clk/uniphier/clk-proxstream2.c b/drivers/clk/uniphier/clk-proxstream2.c
new file mode 100644
index 0000000..b3ffedc
--- /dev/null
+++ b/drivers/clk/uniphier/clk-proxstream2.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+static struct uniphier_clk_init_data proxstream2_clk_idata[] __initdata = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = UNIPHIER_CLK_EXT "ref",
+			.mult = 96,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 3,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 27,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 4,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "arm-scu",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 7,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "stdmac-clken",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = -1,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.bit_idx = 10,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 10,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.bit_idx = 10,
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static void __init proxstream2_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, proxstream2_clk_idata);
+}
+CLK_OF_DECLARE(proxstream2_clk, "socionext,proxstream2-sysctrl",
+	       proxstream2_clk_init);
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
new file mode 100644
index 0000000..8680101
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)		"uniphier-clk: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk-uniphier.h"
+
+static void __init uniphier_clk_update_parent_name(struct device_node *np,
+						   const char **parent_name)
+{
+	const char *new_name;
+	int index;
+
+	if (!parent_name || !*parent_name)
+		return;
+
+	if (strncmp(*parent_name, UNIPHIER_CLK_EXT, strlen(UNIPHIER_CLK_EXT)))
+		return;
+
+	index = of_property_match_string(np, "clock-names",
+				*parent_name + strlen(UNIPHIER_CLK_EXT));
+	new_name = of_clk_get_parent_name(np, index);
+	if (new_name)
+		*parent_name = new_name;
+}
+
+static struct clk * __init uniphier_clk_register(struct device_node *np,
+						 void __iomem *regbase,
+					  struct uniphier_clk_init_data *idata)
+{
+	int i;
+
+	switch (idata->type) {
+	case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
+		uniphier_clk_update_parent_name(np,
+					&idata->data.factor.parent_name);
+		return clk_register_fixed_factor(NULL, idata->name,
+						 idata->data.factor.parent_name,
+						 CLK_SET_RATE_PARENT,
+						 idata->data.factor.mult,
+						 idata->data.factor.div);
+	case UNIPHIER_CLK_TYPE_FIXED_RATE:
+		return clk_register_fixed_rate(NULL, idata->name, NULL,
+					       CLK_IS_ROOT,
+					       idata->data.rate.fixed_rate);
+	case UNIPHIER_CLK_TYPE_GATE:
+		uniphier_clk_update_parent_name(np,
+						&idata->data.gate.parent_name);
+		return clk_register_gate(NULL, idata->name,
+					 idata->data.gate.parent_name,
+					 idata->data.gate.parent_name ?
+					 CLK_SET_RATE_PARENT : CLK_IS_ROOT,
+					 regbase + idata->data.gate.reg,
+					 idata->data.gate.bit_idx, 0, NULL);
+	case UNIPHIER_CLK_TYPE_MUX:
+		for (i = 0; i < idata->data.mux.num_parents; i++)
+			uniphier_clk_update_parent_name(np,
+					&idata->data.mux.parent_names[i]);
+		return clk_register_mux(NULL, idata->name,
+					idata->data.mux.parent_names,
+					idata->data.mux.num_parents,
+					CLK_SET_RATE_PARENT,
+					regbase + idata->data.mux.reg,
+					idata->data.mux.shift,
+					ilog2(idata->data.mux.num_parents),
+					0, NULL);
+	default:
+		WARN(1, "unsupported clock type\n");
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+int __init uniphier_clk_init(struct device_node *np,
+			     struct uniphier_clk_init_data *idata)
+{
+	struct clk_onecell_data *clk_data;
+	struct uniphier_clk_init_data *p;
+	void __iomem *regbase;
+	int max_index = 0;
+	int ret;
+
+	regbase = of_iomap(np, 0);
+	if (!regbase)
+		return -ENOMEM;
+
+	for (p = idata; p->name; p++)
+		max_index = max(max_index, p->output_index);
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->clk_num = max_index + 1;
+	clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
+				 GFP_KERNEL);
+	if (!clk_data->clks) {
+		ret = -ENOMEM;
+		goto free_clk_data;
+	}
+
+	for (p = idata; p->name; p++) {
+		pr_debug("register %s (%s[%d])\n", p->name, np->name,
+			 p->output_index);
+		p->clk = uniphier_clk_register(np, regbase, p);
+		if (IS_ERR(p->clk)) {
+			pr_err("failed to register %s\n", p->name);
+			ret = PTR_ERR(p->clk);
+			goto unregister;
+		}
+
+		if (p->output_index >= 0)
+			clk_data->clks[p->output_index] = p->clk;
+	}
+
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	if (ret)
+		goto unregister;
+
+	return ret;
+unregister:
+	for (p--; p >= idata; p--) {
+		pr_debug("unregister %s (%s[%d])\n", p->name, np->name,
+			 p->output_index);
+		clk_unregister(p->clk);
+		p->clk = NULL;
+	}
+	kfree(clk_data->clks);
+free_clk_data:
+	kfree(clk_data);
+
+	pr_err("%s: init failed with error %d\n", np->full_name, ret);
+
+	return ret;
+}
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
new file mode 100644
index 0000000..ad6491b
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_MIO_CLK_SD_FIXED					\
+	{								\
+		.name = "sd-44m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 44444444,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-33m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 33333333,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-50m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 50000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-67m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 66666666,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-100m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 100000000,			\
+		},							\
+	},								\
+	{								\
+		.name = "sd-40m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 40000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-25m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 25000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-22m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 22222222,				\
+		},							\
+	}
+
+
+#define UNIPHIER_MIO_CLK_SD(ch, index)					\
+	{								\
+		.name = "sd" #ch "-clksel0",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd-44m",				\
+				"sd-33m",				\
+				"sd-50m",				\
+				"sd-67m",				\
+			},						\
+			.num_parents = 4,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.shift = 16,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-clksel1",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd-100m",				\
+				"sd-40m",				\
+				"sd-25m",				\
+				"sd-22m",				\
+			},						\
+			.num_parents = 4,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.shift = 8,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-clkmode",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd" #ch "-clksel0",			\
+				"sd" #ch "-clksel1",			\
+			},						\
+			.num_parents = 2,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.shift = 12,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-clken",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-clkmode",		\
+			.reg = 0x20 + 0x200 * ch,			\
+			.bit_idx = 8,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch "-bridge-reset",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-clken",		\
+			.reg = 0x110 + 0x200 * ch,			\
+			.bit_idx = 26,					\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch,					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-bridge-reset",	\
+			.reg = 0x110 + 0x200 * ch,			\
+			.bit_idx = 0,					\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_SD_HW_RESET(ch, index)				\
+	{								\
+		.name = "sd" #ch "-hw-reset",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = NULL,				\
+			.reg = 0x80 + 0x200 * ch,			\
+			.bit_idx = 0,					\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_EHCI(ch, index)				\
+	{								\
+		.name = "ehci" #ch "-phy-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = UNIPHIER_CLK_EXT "ehci",		\
+			.reg = 0x20 + 0x200 * ch,			\
+			.bit_idx = 29,					\
+		},							\
+	},								\
+	{								\
+		.name = "ehci" #ch "-link-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "ehci" #ch "-phy-clken",		\
+			.reg = 0x20 + 0x200 * ch,			\
+			.bit_idx = 28,					\
+		},							\
+	},								\
+	{								\
+		.name = "ehci" #ch "-bridge-reset",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = "ehci" #ch "-link-clken",	\
+			.reg = 0x110 + 0x200 * ch,			\
+			.bit_idx = 24,					\
+		},							\
+	},								\
+	{								\
+		.name = "ehci" #ch,					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "ehci" #ch "-bridge-reset",	\
+			.reg = 0x114 + 0x200 * ch,			\
+			.bit_idx = 0,					\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_DMAC(index)					\
+	{								\
+		.name = "miodmac-clken",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = -1,					\
+		.data.gate = {						\
+			.parent_name = UNIPHIER_CLK_EXT "stdmac",	\
+			.reg = 0x20,					\
+			.bit_idx = 25,					\
+		},							\
+	},								\
+	{								\
+		.name = "miodmac",					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "miodmac-clken",			\
+			.reg = 0x110,					\
+			.bit_idx = 17,					\
+		},							\
+	}
+
+static struct uniphier_clk_init_data ph1_sld3_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(0, 3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_EHCI(2, 6),
+	UNIPHIER_MIO_CLK_EHCI(3, 7),
+	UNIPHIER_MIO_CLK_DMAC(8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_ld4_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_EHCI(2, 6),
+	UNIPHIER_MIO_CLK_DMAC(8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro4_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD(2, 2),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_DMAC(8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro5_mio_clk_idata[] __initdata = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3),
+	{ /* sentinel */ }
+};
+
+static void __init ph1_sld3_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_sld3_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_sld3_mio_clk, "socionext,ph1-sld3-mioctrl",
+	       ph1_sld3_mio_clk_init);
+
+static void __init ph1_ld4_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_ld4_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_ld4_mio_clk, "socionext,ph1-ld4-mioctrl",
+	       ph1_ld4_mio_clk_init);
+CLK_OF_DECLARE(ph1_sld8_mio_clk, "socionext,ph1-sld8-mioctrl",
+	       ph1_ld4_mio_clk_init);
+
+static void __init ph1_pro4_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro4_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro4_mio_clk, "socionext,ph1-pro4-mioctrl",
+	       ph1_pro4_mio_clk_init);
+
+static void __init ph1_pro5_mio_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro5_mio_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro5_mio_clk, "socionext,ph1-pro5-mioctrl",
+	       ph1_pro5_mio_clk_init);
+CLK_OF_DECLARE(proxstream2_mio_clk, "socionext,proxstream2-mioctrl",
+	       ph1_pro5_mio_clk_init);
diff --git a/drivers/clk/uniphier/clk-uniphier-peri.c b/drivers/clk/uniphier/clk-uniphier-peri.c
new file mode 100644
index 0000000..adaae8e
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-peri.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_PERI_CLK_UART(ch, index)			\
+	{							\
+		.name = "uart" #ch "-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = UNIPHIER_CLK_EXT "uart",	\
+			.reg = 0x24,				\
+			.bit_idx = 19 + ch,			\
+		},						\
+	},							\
+	{							\
+		.name = "uart" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "uart" #ch "-clken",	\
+			.reg = 0x114,				\
+			.bit_idx = 19 + ch,			\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_I2C_COMMON				\
+	{							\
+		.name = "i2c-clken",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = UNIPHIER_CLK_EXT "i2c",	\
+			.reg = 0x20,				\
+			.bit_idx = 1,				\
+		},						\
+	},							\
+	{							\
+		.name = "i2c-reset",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = "i2c-clken",		\
+			.reg = 0x110,				\
+			.bit_idx = 1,				\
+		},						\
+	}
+
+
+#define UNIPHIER_PERI_CLK_I2C(ch, index)			\
+	{							\
+		.name = "i2c" #ch "-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = "i2c-reset",		\
+			.reg = 0x24,				\
+			.bit_idx = 5 + ch,			\
+		},						\
+	},							\
+	{							\
+		.name = "i2c" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "i2c" #ch "-clken",	\
+			.reg = 0x114,				\
+			.bit_idx = 5 + ch,			\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_FI2C(ch, index)			\
+	{							\
+		.name = "fi2c" #ch "-clken",			\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = UNIPHIER_CLK_EXT "fi2c",	\
+			.reg = 0x24,				\
+			.bit_idx = 24 + ch,			\
+		},						\
+	},							\
+	{							\
+		.name = "fi2c" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = index,				\
+		.data.gate = {					\
+			.parent_name = "fi2c" #ch "-clken",	\
+			.reg = 0x114,				\
+			.bit_idx = 24 + ch,			\
+		},						\
+	}
+
+static struct uniphier_clk_init_data ph1_ld4_peri_clk_idata[] __initdata = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_I2C_COMMON,
+	UNIPHIER_PERI_CLK_I2C(0, 4),
+	UNIPHIER_PERI_CLK_I2C(1, 5),
+	UNIPHIER_PERI_CLK_I2C(2, 6),
+	UNIPHIER_PERI_CLK_I2C(3, 7),
+	UNIPHIER_PERI_CLK_I2C(4, 8),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro4_peri_clk_idata[] __initdata = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_FI2C(0, 4),
+	UNIPHIER_PERI_CLK_FI2C(1, 5),
+	UNIPHIER_PERI_CLK_FI2C(2, 6),
+	UNIPHIER_PERI_CLK_FI2C(3, 7),
+	/* no I2C ch4 */
+	UNIPHIER_PERI_CLK_FI2C(5, 9),
+	UNIPHIER_PERI_CLK_FI2C(6, 10),
+	{ /* sentinel */ }
+};
+
+static struct uniphier_clk_init_data ph1_pro5_peri_clk_idata[] __initdata = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_FI2C(0, 4),
+	UNIPHIER_PERI_CLK_FI2C(1, 5),
+	UNIPHIER_PERI_CLK_FI2C(2, 6),
+	UNIPHIER_PERI_CLK_FI2C(3, 7),
+	UNIPHIER_PERI_CLK_FI2C(4, 8),
+	UNIPHIER_PERI_CLK_FI2C(5, 9),
+	UNIPHIER_PERI_CLK_FI2C(6, 10),
+	{ /* sentinel */ }
+};
+
+static void __init ph1_ld4_peri_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_ld4_peri_clk_idata);
+}
+CLK_OF_DECLARE(ph1_ld4_peri_clk, "socionext,ph1-ld4-perictrl",
+	       ph1_ld4_peri_clk_init);
+CLK_OF_DECLARE(ph1_sld8_peri_clk, "socionext,ph1-sld8-perictrl",
+	       ph1_ld4_peri_clk_init);
+
+static void __init ph1_pro4_peri_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro4_peri_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro4_peri_clk, "socionext,ph1-pro4-perictrl",
+	       ph1_pro4_peri_clk_init);
+
+static void __init ph1_pro5_peri_clk_init(struct device_node *np)
+{
+	uniphier_clk_init(np, ph1_pro5_peri_clk_idata);
+}
+CLK_OF_DECLARE(ph1_pro5_peri_clk, "socionext,ph1-pro5-perictrl",
+	       ph1_pro5_peri_clk_init);
+CLK_OF_DECLARE(proxstream2_peri_clk, "socionext,proxstream2-perictrl",
+	       ph1_pro5_peri_clk_init);
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
new file mode 100644
index 0000000..05277b6
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CLK_UNIPHIER_H__
+#define __CLK_UNIPHIER_H__
+
+#include <linux/kernel.h>
+
+#define UNIPHIER_CLK_EXT	"[EXT]"
+
+enum uniphier_clk_type {
+	UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+	UNIPHIER_CLK_TYPE_FIXED_RATE,
+	UNIPHIER_CLK_TYPE_GATE,
+	UNIPHIER_CLK_TYPE_MUX,
+};
+
+struct uniphier_clk_fixed_factor_data {
+	const char *parent_name;
+	unsigned int mult;
+	unsigned int div;
+};
+
+struct uniphier_clk_fixed_rate_data {
+	unsigned long fixed_rate;
+};
+
+struct uniphier_clk_gate_data {
+	const char *parent_name;
+	unsigned int reg;
+	u8 bit_idx;
+};
+
+struct uniphier_clk_mux_data {
+	const char *parent_names[4];
+	u8 num_parents;
+	unsigned int reg;
+	u8 shift;
+};
+
+struct uniphier_clk_init_data {
+	const char *name;
+	enum uniphier_clk_type type;
+	int output_index;
+	union {
+		struct uniphier_clk_fixed_factor_data factor;
+		struct uniphier_clk_fixed_rate_data rate;
+		struct uniphier_clk_gate_data gate;
+		struct uniphier_clk_mux_data mux;
+	} data;
+	struct clk *clk;
+};
+
+int uniphier_clk_init(struct device_node *np,
+		      struct uniphier_clk_init_data *idata);
+
+#endif /* __CLK_UNIPHIER_H__ */
-- 
1.9.1

             reply	other threads:[~2015-12-28 10:21 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-28 10:20 Masahiro Yamada [this message]
2015-12-28 10:20 ` [PATCH v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs Masahiro Yamada
2015-12-31  1:35 ` Michael Turquette
2015-12-31  1:35   ` [PATCH v2, RESEND] " Michael Turquette
2015-12-31  1:35   ` [PATCH v2,RESEND] " Michael Turquette
2016-01-02  1:26   ` Masahiro Yamada
2016-01-02  1:26     ` [PATCH v2, RESEND] " Masahiro Yamada
2016-01-04  8:36     ` [PATCH v2,RESEND] " Michael Turquette
2016-01-04  8:36       ` [PATCH v2, RESEND] " Michael Turquette
2016-05-02 15:56       ` Masahiro Yamada
2016-05-02 15:56         ` Masahiro Yamada

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com \
    --to=yamada.masahiro@socionext.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=sboyd@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.