[10/20] clk: uniphier: rework for better clock tree structure

Message ID 1507890129-1543-11-git-send-email-yamada.masahiro@socionext.com
State Accepted
Commit d6c7ee7d281e1bace42d5981b35a98322b994bc1
Headers show
Series
  • ARM: uniphier: various refactoring for v2017.11-rc2
Related show

Commit Message

Masahiro Yamada Oct. 13, 2017, 10:21 a.m.
U-Boot does not support fancy clock tree structures like the Linux
common clock framework.  Implement a simple clock tree model at the
driver level.  With this, the clock data will be simplified.

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

 drivers/clk/uniphier/clk-uniphier-core.c | 267 ++++++++++++++++++++++---------
 drivers/clk/uniphier/clk-uniphier-mio.c  | 118 +++++++-------
 drivers/clk/uniphier/clk-uniphier-sys.c  |  42 +++--
 drivers/clk/uniphier/clk-uniphier.h      |  79 +++++----
 4 files changed, 323 insertions(+), 183 deletions(-)

Patch

diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index 722cd6b..3d1d411 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (C) 2016 Socionext Inc.
+ * Copyright (C) 2016-2017 Socionext Inc.
  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -21,104 +21,224 @@ 
  * @data: SoC specific data
  */
 struct uniphier_clk_priv {
+	struct udevice *dev;
 	void __iomem *base;
 	const struct uniphier_clk_data *data;
 };
 
-static int uniphier_clk_enable(struct clk *clk)
+static void uniphier_clk_gate_enable(struct uniphier_clk_priv *priv,
+				     const struct uniphier_clk_gate_data *gate)
 {
-	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
-	unsigned long id = clk->id;
-	const struct uniphier_clk_gate_data *p;
+	u32 val;
 
-	for (p = priv->data->gate; p->id != UNIPHIER_CLK_ID_END; p++) {
-		u32 val;
+	val = readl(priv->base + gate->reg);
+	val |= BIT(gate->bit);
+	writel(val, priv->base + gate->reg);
+}
 
-		if (p->id != id)
-			continue;
+static void uniphier_clk_mux_set_parent(struct uniphier_clk_priv *priv,
+					const struct uniphier_clk_mux_data *mux,
+					u8 id)
+{
+	u32 val;
+	int i;
 
-		val = readl(priv->base + p->reg);
-		val |= BIT(p->bit);
-		writel(val, priv->base + p->reg);
+	for (i = 0; i < mux->num_parents; i++) {
+		if (mux->parent_ids[i] != id)
+			continue;
 
-		return 0;
+		val = readl(priv->base + mux->reg);
+		val &= ~mux->masks[i];
+		val |= mux->vals[i];
+		writel(val, priv->base + mux->reg);
+		return;
 	}
 
-	dev_err(priv->dev, "clk_id=%lu was not handled\n", id);
-	return -EINVAL;
+	WARN_ON(1);
 }
 
-static const struct uniphier_clk_mux_data *
-uniphier_clk_get_mux_data(struct uniphier_clk_priv *priv, unsigned long id)
+static u8 uniphier_clk_mux_get_parent(struct uniphier_clk_priv *priv,
+				      const struct uniphier_clk_mux_data *mux)
 {
-	const struct uniphier_clk_mux_data *p;
+	u32 val;
+	int i;
 
-	for (p = priv->data->mux; p->id != UNIPHIER_CLK_ID_END; p++) {
-		if (p->id == id)
-			return p;
-	}
+	val = readl(priv->base + mux->reg);
+
+	for (i = 0; i < mux->num_parents; i++)
+		if ((mux->masks[i] & val) == mux->vals[i])
+			return mux->parent_ids[i];
+
+	dev_err(priv->dev, "invalid mux setting\n");
+
+	return UNIPHIER_CLK_ID_INVALID;
+}
+
+static const struct uniphier_clk_data *uniphier_clk_get_data(
+					struct uniphier_clk_priv *priv, u8 id)
+{
+	const struct uniphier_clk_data *data;
+
+	for (data = priv->data; data->type != UNIPHIER_CLK_TYPE_END; data++)
+		if (data->id == id)
+			return data;
+
+	dev_err(priv->dev, "id=%u not found\n", id);
 
 	return NULL;
 }
 
-static ulong uniphier_clk_get_rate(struct clk *clk)
+static const struct uniphier_clk_data *uniphier_clk_get_parent_data(
+					struct uniphier_clk_priv *priv,
+					const struct uniphier_clk_data *data)
 {
-	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
-	const struct uniphier_clk_mux_data *mux;
-	u32 val;
-	int i;
+	const struct uniphier_clk_data *parent_data;
+	u8 parent_id = UNIPHIER_CLK_ID_INVALID;
+
+	switch (data->type) {
+	case UNIPHIER_CLK_TYPE_GATE:
+		parent_id = data->data.gate.parent_id;
+		break;
+	case UNIPHIER_CLK_TYPE_MUX:
+		parent_id = uniphier_clk_mux_get_parent(priv, &data->data.mux);
+		break;
+	default:
+		break;
+	}
 
-	mux = uniphier_clk_get_mux_data(priv, clk->id);
-	if (!mux)
-		return 0;
+	if (parent_id == UNIPHIER_CLK_ID_INVALID)
+		return NULL;
 
-	if (!mux->nr_muxs)		/* fixed-rate */
-		return mux->rates[0];
+	parent_data = uniphier_clk_get_data(priv, parent_id);
 
-	val = readl(priv->base + mux->reg);
+	WARN_ON(!parent_data);
 
-	for (i = 0; i < mux->nr_muxs; i++)
-		if ((mux->masks[i] & val) == mux->vals[i])
-			return mux->rates[i];
+	return parent_data;
+}
+
+static void __uniphier_clk_enable(struct uniphier_clk_priv *priv,
+				  const struct uniphier_clk_data *data)
+{
+	const struct uniphier_clk_data *parent_data;
 
-	return -EINVAL;
+	if (data->type == UNIPHIER_CLK_TYPE_GATE)
+		uniphier_clk_gate_enable(priv, &data->data.gate);
+
+	parent_data = uniphier_clk_get_parent_data(priv, data);
+	if (!parent_data)
+		return;
+
+	return __uniphier_clk_enable(priv, parent_data);
 }
 
-static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate)
+static int uniphier_clk_enable(struct clk *clk)
 {
 	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
-	const struct uniphier_clk_mux_data *mux;
-	u32 val;
-	int i, best_rate_id = -1;
-	ulong best_rate = 0;
+	const struct uniphier_clk_data *data;
+
+	data = uniphier_clk_get_data(priv, clk->id);
+	if (!data)
+		return -ENODEV;
+
+	__uniphier_clk_enable(priv, data);
+
+	return 0;
+}
+
+static unsigned long __uniphier_clk_get_rate(
+					struct uniphier_clk_priv *priv,
+					const struct uniphier_clk_data *data)
+{
+	const struct uniphier_clk_data *parent_data;
 
-	mux = uniphier_clk_get_mux_data(priv, clk->id);
-	if (!mux)
+	if (data->type == UNIPHIER_CLK_TYPE_FIXED_RATE)
+		return data->data.rate.fixed_rate;
+
+	parent_data = uniphier_clk_get_parent_data(priv, data);
+	if (!parent_data)
 		return 0;
 
-	if (!mux->nr_muxs)		/* fixed-rate */
-		return mux->rates[0];
+	return __uniphier_clk_get_rate(priv, parent_data);
+}
 
-	/* first, decide the best match rate */
-	for (i = 0; i < mux->nr_muxs; i++) {
-		if (mux->rates[i] > best_rate && mux->rates[i] <= rate) {
-			best_rate = mux->rates[i];
-			best_rate_id = i;
+static unsigned long uniphier_clk_get_rate(struct clk *clk)
+{
+	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct uniphier_clk_data *data;
+
+	data = uniphier_clk_get_data(priv, clk->id);
+	if (!data)
+		return -ENODEV;
+
+	return __uniphier_clk_get_rate(priv, data);
+}
+
+static unsigned long __uniphier_clk_set_rate(
+					struct uniphier_clk_priv *priv,
+					const struct uniphier_clk_data *data,
+					unsigned long rate, bool set)
+{
+	const struct uniphier_clk_data *best_parent_data = NULL;
+	const struct uniphier_clk_data *parent_data;
+	unsigned long best_rate = 0;
+	unsigned long parent_rate;
+	u8 parent_id;
+	int i;
+
+	if (data->type == UNIPHIER_CLK_TYPE_FIXED_RATE)
+		return data->data.rate.fixed_rate;
+
+	if (data->type == UNIPHIER_CLK_TYPE_GATE) {
+		parent_data = uniphier_clk_get_parent_data(priv, data);
+		if (!parent_data)
+			return 0;
+
+		return __uniphier_clk_set_rate(priv, parent_data, rate, set);
+	}
+
+	if (WARN_ON(data->type != UNIPHIER_CLK_TYPE_MUX))
+		return -EINVAL;
+
+	for (i = 0; i < data->data.mux.num_parents; i++) {
+		parent_id = data->data.mux.parent_ids[i];
+		parent_data = uniphier_clk_get_data(priv, parent_id);
+		if (WARN_ON(!parent_data))
+			return -EINVAL;
+
+		parent_rate = __uniphier_clk_set_rate(priv, parent_data, rate,
+						      false);
+
+		if (parent_rate <= rate && best_rate < parent_rate) {
+			best_rate = parent_rate;
+			best_parent_data = parent_data;
 		}
 	}
 
-	if (best_rate_id < 0)
+	dev_dbg(priv->dev, "id=%u, best_rate=%lu\n", data->id, best_rate);
+
+	if (!best_parent_data)
 		return -EINVAL;
 
-	val = readl(priv->base + mux->reg);
-	val &= ~mux->masks[best_rate_id];
-	val |= mux->vals[best_rate_id];
-	writel(val, priv->base + mux->reg);
+	if (!set)
+		return best_rate;
+
+	uniphier_clk_mux_set_parent(priv, &data->data.mux,
+				    best_parent_data->id);
+
+	return best_rate = __uniphier_clk_set_rate(priv, best_parent_data,
+						   rate, true);
+}
+
+static unsigned long uniphier_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct uniphier_clk_data *data;
 
-	debug("%s: requested rate = %lu, set rate = %lu\n", __func__,
-	      rate, best_rate);
+	data = uniphier_clk_get_data(priv, clk->id);
+	if (!data)
+		return -ENODEV;
 
-	return best_rate;
+	return __uniphier_clk_set_rate(priv, data, rate, true);
 }
 
 static const struct clk_ops uniphier_clk_ops = {
@@ -140,6 +260,7 @@  static int uniphier_clk_probe(struct udevice *dev)
 	if (!priv->base)
 		return -ENOMEM;
 
+	priv->dev = dev;
 	priv->data = (void *)dev_get_driver_data(dev);
 
 	return 0;
@@ -149,60 +270,60 @@  static const struct udevice_id uniphier_clk_match[] = {
 	/* System clock */
 	{
 		.compatible = "socionext,uniphier-ld4-clock",
-		.data = (ulong)&uniphier_pxs2_sys_clk_data,
+		.data = (ulong)uniphier_pxs2_sys_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-pro4-clock",
-		.data = (ulong)&uniphier_pxs2_sys_clk_data,
+		.data = (ulong)uniphier_pxs2_sys_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-sld8-clock",
-		.data = (ulong)&uniphier_pxs2_sys_clk_data,
+		.data = (ulong)uniphier_pxs2_sys_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-pro5-clock",
-		.data = (ulong)&uniphier_pxs2_sys_clk_data,
+		.data = (ulong)uniphier_pxs2_sys_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-pxs2-clock",
-		.data = (ulong)&uniphier_pxs2_sys_clk_data,
+		.data = (ulong)uniphier_pxs2_sys_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-ld11-clock",
-		.data = (ulong)&uniphier_ld20_sys_clk_data,
+		.data = (ulong)uniphier_ld20_sys_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-ld20-clock",
-		.data = (ulong)&uniphier_ld20_sys_clk_data,
+		.data = (ulong)uniphier_ld20_sys_clk_data,
 	},
 	/* Media I/O clock */
 	{
 		.compatible = "socionext,uniphier-ld4-mio-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-pro4-mio-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-sld8-mio-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-pro5-sd-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-pxs2-sd-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-ld11-mio-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{
 		.compatible = "socionext,uniphier-ld20-sd-clock",
-		.data = (ulong)&uniphier_mio_clk_data,
+		.data = (ulong)uniphier_mio_clk_data,
 	},
 	{ /* sentinel */ }
 };
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
index 9c13dcd..5c73848 100644
--- a/drivers/clk/uniphier/clk-uniphier-mio.c
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -7,59 +7,71 @@ 
 
 #include "clk-uniphier.h"
 
-#define UNIPHIER_MIO_CLK_SD_GATE(id, ch)				\
-	UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 8)
+#define UNIPHIER_MIO_CLK_SD_FIXED					\
+	UNIPHIER_CLK_RATE(128, 44444444),				\
+	UNIPHIER_CLK_RATE(129, 33333333),				\
+	UNIPHIER_CLK_RATE(130, 50000000),				\
+	UNIPHIER_CLK_RATE(131, 66666667),				\
+	UNIPHIER_CLK_RATE(132, 100000000),				\
+	UNIPHIER_CLK_RATE(133, 40000000),				\
+	UNIPHIER_CLK_RATE(134, 25000000),				\
+	UNIPHIER_CLK_RATE(135, 22222222)
+
+#define UNIPHIER_MIO_CLK_SD(_id, ch)					\
+	{								\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.id = (_id) + 32,					\
+		.data.mux = {						\
+			.parent_ids = {					\
+				128,					\
+				129,					\
+				130,					\
+				131,					\
+				132,					\
+				133,					\
+				134,					\
+				135,					\
+			},						\
+			.num_parents = 8,				\
+			.reg = 0x30 + 0x200 * (ch),			\
+			.masks = {					\
+				0x00031000,				\
+				0x00031000,				\
+				0x00031000,				\
+				0x00031000,				\
+				0x00001300,				\
+				0x00001300,				\
+				0x00001300,				\
+				0x00001300,				\
+			},						\
+			.vals = {					\
+				0x00000000,				\
+				0x00010000,				\
+				0x00020000,				\
+				0x00030000,				\
+				0x00001000,				\
+				0x00001100,				\
+				0x00001200,				\
+				0x00001300,				\
+			},						\
+		},							\
+	},								\
+	UNIPHIER_CLK_GATE((_id), (_id) + 32, 0x20 + 0x200 * (ch), 8)
 
 #define UNIPHIER_MIO_CLK_USB2(id, ch)					\
-	UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 28)
+	UNIPHIER_CLK_GATE_SIMPLE((id), 0x20 + 0x200 * (ch), 28)
 
 #define UNIPHIER_MIO_CLK_USB2_PHY(id, ch)				\
-	UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 29)
+	UNIPHIER_CLK_GATE_SIMPLE((id), 0x20 + 0x200 * (ch), 29)
 
 #define UNIPHIER_MIO_CLK_DMAC(id)					\
-	UNIPHIER_CLK_GATE((id), 0x20, 25)
-
-#define UNIPHIER_MIO_CLK_SD_MUX(_id, ch)				\
-	{								\
-		.id = (_id),						\
-		.nr_muxs = 8,						\
-		.reg = 0x30 + 0x200 * (ch),				\
-		.masks = {						\
-			0x00031000,					\
-			0x00031000,					\
-			0x00031000,					\
-			0x00031000,					\
-			0x00001300,					\
-			0x00001300,					\
-			0x00001300,					\
-			0x00001300,					\
-		},							\
-		.vals = {						\
-			0x00000000,					\
-			0x00010000,					\
-			0x00020000,					\
-			0x00030000,					\
-			0x00001000,					\
-			0x00001100,					\
-			0x00001200,					\
-			0x00001300,					\
-		},							\
-		.rates = {						\
-			44444444,					\
-			33333333,					\
-			50000000,					\
-			66666666,					\
-			100000000,					\
-			40000000,					\
-			25000000,					\
-			22222222,					\
-		},							\
-	}
+	UNIPHIER_CLK_GATE_SIMPLE((id), 0x20, 25)
 
-static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
-	UNIPHIER_MIO_CLK_SD_GATE(0, 0),
-	UNIPHIER_MIO_CLK_SD_GATE(1, 1),
-	UNIPHIER_MIO_CLK_SD_GATE(2, 2),		/* for PH1-Pro4 only */
+const struct uniphier_clk_data uniphier_mio_clk_data[] = {
+	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_DMAC(7),
 	UNIPHIER_MIO_CLK_USB2(8, 0),
 	UNIPHIER_MIO_CLK_USB2(9, 1),
@@ -67,17 +79,5 @@  static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
 	UNIPHIER_MIO_CLK_USB2_PHY(12, 0),
 	UNIPHIER_MIO_CLK_USB2_PHY(13, 1),
 	UNIPHIER_MIO_CLK_USB2_PHY(14, 2),
-	UNIPHIER_CLK_END
-};
-
-static const struct uniphier_clk_mux_data uniphier_mio_clk_mux[] = {
-	UNIPHIER_MIO_CLK_SD_MUX(0, 0),
-	UNIPHIER_MIO_CLK_SD_MUX(1, 1),
-	UNIPHIER_MIO_CLK_SD_MUX(2, 2),		/* for PH1-Pro4 only */
-	UNIPHIER_CLK_END
-};
-
-const struct uniphier_clk_data uniphier_mio_clk_data = {
-	.gate = uniphier_mio_clk_gate,
-	.mux = uniphier_mio_clk_mux,
+	{ /* sentinel */ }
 };
diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c
index 709fa50..e9df885 100644
--- a/drivers/clk/uniphier/clk-uniphier-sys.c
+++ b/drivers/clk/uniphier/clk-uniphier-sys.c
@@ -7,28 +7,26 @@ 
 
 #include "clk-uniphier.h"
 
-const struct uniphier_clk_gate_data uniphier_pxs2_sys_clk_gate[] = {
-	UNIPHIER_CLK_GATE(8, 0x2104, 10),	/* stdmac */
-	UNIPHIER_CLK_GATE(12, 0x2104, 6),	/* gio (Pro4, Pro5) */
-	UNIPHIER_CLK_GATE(14, 0x2104, 16),	/* usb30 (Pro4, Pro5, PXs2) */
-	UNIPHIER_CLK_GATE(15, 0x2104, 17),	/* usb31 (Pro4, Pro5, PXs2) */
-	UNIPHIER_CLK_GATE(16, 0x2104, 19),	/* usb30-phy (PXs2) */
-	UNIPHIER_CLK_GATE(20, 0x2104, 20),	/* usb31-phy (PXs2) */
-	UNIPHIER_CLK_END
+const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
+#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_SLD8) ||\
+    defined(CONFIG_ARCH_UNIPHIER_PRO4) || defined(CONFIG_ARCH_UNIPHIER_PRO5) ||\
+    defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
+	UNIPHIER_CLK_GATE_SIMPLE(8, 0x2104, 10),	/* stdmac */
+	UNIPHIER_CLK_GATE_SIMPLE(12, 0x2104, 6),	/* gio (Pro4, Pro5) */
+	UNIPHIER_CLK_GATE_SIMPLE(14, 0x2104, 16),	/* usb30 (Pro4, Pro5, PXs2) */
+	UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17),	/* usb31 (Pro4, Pro5, PXs2) */
+	UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19),	/* usb30-phy (PXs2) */
+	UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20),	/* usb31-phy (PXs2) */
+	{ /* sentinel */ }
+#endif
 };
 
-const struct uniphier_clk_data uniphier_pxs2_sys_clk_data = {
-	.gate = uniphier_pxs2_sys_clk_gate,
-};
-
-const struct uniphier_clk_gate_data uniphier_ld20_sys_clk_gate[] = {
-	UNIPHIER_CLK_GATE(8, 0x210c, 8),	/* stdmac */
-	UNIPHIER_CLK_GATE(14, 0x210c, 14),	/* usb30 (LD20) */
-	UNIPHIER_CLK_GATE(16, 0x210c, 12),	/* usb30-phy0 (LD20) */
-	UNIPHIER_CLK_GATE(17, 0x210c, 13),	/* usb30-phy1 (LD20) */
-	UNIPHIER_CLK_END
-};
-
-const struct uniphier_clk_data uniphier_ld20_sys_clk_data = {
-	.gate = uniphier_ld20_sys_clk_gate,
+const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
+#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
+	UNIPHIER_CLK_GATE_SIMPLE(8, 0x210c, 8),		/* stdmac */
+	UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14),	/* usb30 (LD20) */
+	UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12),	/* usb30-phy0 (LD20) */
+	UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13),	/* usb30-phy1 (LD20) */
+	{ /* sentinel */ }
+#endif
 };
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
index 770a322..9b6c94f 100644
--- a/drivers/clk/uniphier/clk-uniphier.h
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -9,49 +9,70 @@ 
 #define __CLK_UNIPHIER_H__
 
 #include <linux/kernel.h>
+#include <linux/types.h>
 
-#define UNIPHIER_CLK_MAX_NR_MUXS	8
+#define UNIPHIER_CLK_MUX_MAX_PARENTS		8
+
+#define UNIPHIER_CLK_TYPE_END			0
+#define UNIPHIER_CLK_TYPE_FIXED_RATE		2
+#define UNIPHIER_CLK_TYPE_GATE			3
+#define UNIPHIER_CLK_TYPE_MUX			4
+
+#define UNIPHIER_CLK_ID_INVALID			(U8_MAX)
+
+struct uniphier_clk_fixed_rate_data {
+	unsigned long fixed_rate;
+};
 
 struct uniphier_clk_gate_data {
-	unsigned int id;
-	unsigned int reg;
-	unsigned int bit;
+	u8 parent_id;
+	u16 reg;
+	u8 bit;
 };
 
 struct uniphier_clk_mux_data {
-	unsigned int id;
-	unsigned int nr_muxs;
-	unsigned int reg;
-	unsigned int masks[UNIPHIER_CLK_MAX_NR_MUXS];
-	unsigned int vals[UNIPHIER_CLK_MAX_NR_MUXS];
-	unsigned long rates[UNIPHIER_CLK_MAX_NR_MUXS];
+	u8 parent_ids[UNIPHIER_CLK_MUX_MAX_PARENTS];
+	u8 num_parents;
+	u16 reg;
+	u32 masks[UNIPHIER_CLK_MUX_MAX_PARENTS];
+	u32 vals[UNIPHIER_CLK_MUX_MAX_PARENTS];
 };
 
 struct uniphier_clk_data {
-	const struct uniphier_clk_gate_data *gate;
-	const struct uniphier_clk_mux_data *mux;
+	u8 type;
+	u8 id;
+	union {
+		struct uniphier_clk_fixed_rate_data rate;
+		struct uniphier_clk_gate_data gate;
+		struct uniphier_clk_mux_data mux;
+	} data;
 };
 
-#define UNIPHIER_CLK_ID_END		(unsigned int)(-1)
-
-#define UNIPHIER_CLK_END				\
-	{ .id = UNIPHIER_CLK_ID_END }
-
-#define UNIPHIER_CLK_GATE(_id, _reg, _bit)		\
-	{						\
-		.id = (_id),				\
-		.reg = (_reg),				\
-		.bit = (_bit),				\
+#define UNIPHIER_CLK_RATE(_id, _rate)				\
+	{							\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,		\
+		.id = (_id),					\
+		.data.rate = {					\
+			.fixed_rate = (_rate),			\
+		},						\
 	}
 
-#define UNIPHIER_CLK_FIXED_RATE(_id, _rate)		\
-	{						\
-		.id = (_id),				\
-		.rates = {(_reg),},			\
+#define UNIPHIER_CLK_GATE(_id, _parent, _reg, _bit)		\
+	{							\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.id = (_id),					\
+		.data.gate = {					\
+			.parent_id = (_parent),			\
+			.reg = (_reg),				\
+			.bit = (_bit),				\
+		},						\
 	}
 
-extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data;
-extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data;
-extern const struct uniphier_clk_data uniphier_mio_clk_data;
+#define UNIPHIER_CLK_GATE_SIMPLE(_id, _reg, _bit)		\
+	UNIPHIER_CLK_GATE(_id, UNIPHIER_CLK_ID_INVALID, _reg, _bit)
+
+extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[];
+extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data[];
+extern const struct uniphier_clk_data uniphier_mio_clk_data[];
 
 #endif /* __CLK_UNIPHIER_H__ */