All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded
@ 2019-07-31  7:01 Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 02/16] clk: use clk_dev_binded Peng Fan
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

When support Clock Common Framework, U-Boot use dev for
clk tree information, there is no clk->parent. When
support composite clk, it contains mux/gate/divider,
but the mux/gate/divider is not binded with device.
So we could not use dev_get_uclass_priv to get the correct
clk_mux/gate/divider. So add clk_dev_binded to let
choose the correct method.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk.c | 8 ++++++++
 include/clk.h     | 9 +++++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 7d748c9fc7..39b3087067 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw)
 {
 	return hw->dev->name;
 }
+
+bool clk_dev_binded(struct clk *clk)
+{
+	if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
+		return true;
+
+	return false;
+}
diff --git a/include/clk.h b/include/clk.h
index f8f56d9cf0..2ebc905e04 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
  * @return zero on success, or -ENOENT on error
  */
 int clk_get_by_id(ulong id, struct clk **clkp);
+
+/**
+ * clk_dev_binded() - Check whether the clk has a device binded
+ *
+ * @clk		A pointer to the clk
+ *
+ * @return true on binded, or false on no
+ */
+bool clk_dev_binded(struct clk *clk);
 #endif
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 02/16] clk: use clk_dev_binded
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 03/16] clk: mux: add set parent support Peng Fan
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Preparing to support composite clk.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk-divider.c | 4 ++--
 drivers/clk/clk-mux.c     | 6 ++++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6921c76a48..2ed9ed6ab8 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -69,8 +69,8 @@ unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate,
 
 static ulong clk_divider_recalc_rate(struct clk *clk)
 {
-	struct clk_divider *divider =
-		to_clk_divider(dev_get_clk_ptr(clk->dev));
+	struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
 	unsigned long parent_rate = clk_get_parent_rate(clk);
 	unsigned int val;
 
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 3c075aa09e..81d1e7ebee 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -35,7 +35,8 @@
 int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags,
 			 unsigned int val)
 {
-	struct clk_mux *mux = to_clk_mux(clk);
+	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
 	int num_parents = mux->num_parents;
 
 	if (table) {
@@ -61,7 +62,8 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags,
 
 static u8 clk_mux_get_parent(struct clk *clk)
 {
-	struct clk_mux *mux = to_clk_mux(clk);
+	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
 	u32 val;
 
 #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 03/16] clk: mux: add set parent support
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 02/16] clk: use clk_dev_binded Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 04/16] clk: export mux/divider ops Peng Fan
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Add set parent support for clk mux

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk-mux.c        | 70 ++++++++++++++++++++++++++++++++++++++++++--
 include/linux/clk-provider.h |  2 ++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 81d1e7ebee..5acc0b8cbd 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -60,7 +60,24 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags,
 	return val;
 }
 
-static u8 clk_mux_get_parent(struct clk *clk)
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
+{
+	unsigned int val = index;
+
+	if (table) {
+		val = table[index];
+	} else {
+		if (flags & CLK_MUX_INDEX_BIT)
+			val = 1 << index;
+
+		if (flags & CLK_MUX_INDEX_ONE)
+			val++;
+	}
+
+	return val;
+}
+
+u8 clk_mux_get_parent(struct clk *clk)
 {
 	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
 			dev_get_clk_ptr(clk->dev) : clk);
@@ -77,8 +94,57 @@ static u8 clk_mux_get_parent(struct clk *clk)
 	return clk_mux_val_to_index(clk, mux->table, mux->flags, val);
 }
 
+static int clk_fetch_parent_index(struct clk *clk,
+				  struct clk *parent)
+{
+	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
+
+	int i;
+
+	if (!parent)
+		return -EINVAL;
+
+	for (i = 0; i < mux->num_parents; i++) {
+		if (!strcmp(parent->dev->name, mux->parent_names[i]))
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
+	int index;
+	u32 val;
+	u32 reg;
+
+	index = clk_fetch_parent_index(clk, parent);
+	if (index < 0) {
+		printf("Could not fetch index\n");
+		return index;
+	}
+
+	val = clk_mux_index_to_val(mux->table, mux->flags, index);
+
+	if (mux->flags & CLK_MUX_HIWORD_MASK) {
+		reg = mux->mask << (mux->shift + 16);
+	} else {
+		reg = readl(mux->reg);
+		reg &= ~(mux->mask << mux->shift);
+	}
+	val = val << mux->shift;
+	reg |= val;
+	writel(reg, mux->reg);
+
+	return 0;
+}
+
 const struct clk_ops clk_mux_ops = {
-		.get_rate = clk_generic_get_rate,
+	.get_rate = clk_generic_get_rate,
+	.set_parent = clk_mux_set_parent,
 };
 
 struct clk *clk_hw_register_mux_table(struct device *dev, const char *name,
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 43a25e9c6a..7e44045c16 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -66,6 +66,8 @@ struct clk_mux {
 };
 
 #define to_clk_mux(_clk) container_of(_clk, struct clk_mux, clk)
+extern const struct clk_ops clk_mux_ops;
+u8 clk_mux_get_parent(struct clk *clk);
 
 struct clk_div_table {
 	unsigned int	val;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 04/16] clk: export mux/divider ops
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 02/16] clk: use clk_dev_binded Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 03/16] clk: mux: add set parent support Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 05/16] clk: add clk-gate support Peng Fan
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Export mux/divider ops and divider_recalc_rate for composite usage

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase
 Export divider_recalc_rate

 include/linux/clk-provider.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7e44045c16..6d62f862d2 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -96,6 +96,11 @@ struct clk_divider {
 #define CLK_DIVIDER_ROUND_CLOSEST	BIT(4)
 #define CLK_DIVIDER_READ_ONLY		BIT(5)
 #define CLK_DIVIDER_MAX_AT_ZERO		BIT(6)
+extern const struct clk_ops clk_divider_ops;
+unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate,
+				  unsigned int val,
+				  const struct clk_div_table *table,
+				  unsigned long flags, unsigned long width);
 
 struct clk_fixed_factor {
 	struct clk	clk;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 05/16] clk: add clk-gate support
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (2 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 04/16] clk: export mux/divider ops Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 06/16] clk: divider set rate supporrt Peng Fan
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Import clk-gate support from Linux Kernel 5.1-rc5

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V2:
 None
V3:
 Rebase

 drivers/clk/Makefile         |   2 +-
 drivers/clk/clk-gate.c       | 148 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  18 ++++++
 3 files changed, 167 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-gate.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index b7fec605c6..39154eca59 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -7,7 +7,7 @@
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o
-obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o
 
 obj-y += analogbits/
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644
index 0000000000..a3a1fdd3b2
--- /dev/null
+++ b/drivers/clk/clk-gate.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ * Copyright 2019 NXP
+ *
+ * Gated clock implementation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <clk.h>
+#include "clk.h"
+
+#define UBOOT_DM_CLK_GATE "clk_gate"
+
+/**
+ * DOC: basic gatable clock which can gate and ungate it's output
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/*
+ * It works on following logic:
+ *
+ * For enabling clock, enable = 1
+ *	set2dis = 1	-> clear bit	-> set = 0
+ *	set2dis = 0	-> set bit	-> set = 1
+ *
+ * For disabling clock, enable = 0
+ *	set2dis = 1	-> set bit	-> set = 1
+ *	set2dis = 0	-> clear bit	-> set = 0
+ *
+ * So, result is always: enable xor set2dis.
+ */
+static void clk_gate_endisable(struct clk *clk, int enable)
+{
+	struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	u32 reg;
+
+	set ^= enable;
+
+	if (gate->flags & CLK_GATE_HIWORD_MASK) {
+		reg = BIT(gate->bit_idx + 16);
+		if (set)
+			reg |= BIT(gate->bit_idx);
+	} else {
+		reg = readl(gate->reg);
+
+		if (set)
+			reg |= BIT(gate->bit_idx);
+		else
+			reg &= ~BIT(gate->bit_idx);
+	}
+
+	writel(reg, gate->reg);
+}
+
+static int clk_gate_enable(struct clk *clk)
+{
+	clk_gate_endisable(clk, 1);
+
+	return 0;
+}
+
+static int clk_gate_disable(struct clk *clk)
+{
+	clk_gate_endisable(clk, 0);
+
+	return 0;
+}
+
+int clk_gate_is_enabled(struct clk *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
+	u32 reg;
+
+	reg = readl(gate->reg);
+
+	/* if a set bit disables this clk, flip it before masking */
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		reg ^= BIT(gate->bit_idx);
+
+	reg &= BIT(gate->bit_idx);
+
+	return reg ? 1 : 0;
+}
+
+const struct clk_ops clk_gate_ops = {
+	.enable = clk_gate_enable,
+	.disable = clk_gate_disable,
+	.get_rate = clk_generic_get_rate,
+};
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+			      const char *parent_name, unsigned long flags,
+			      void __iomem *reg, u8 bit_idx,
+			      u8 clk_gate_flags, spinlock_t *lock)
+{
+	struct clk_gate *gate;
+	struct clk *clk;
+	int ret;
+
+	if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
+		if (bit_idx > 15) {
+			pr_err("gate bit exceeds LOWORD field\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/* allocate the gate */
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	/* struct clk_gate assignments */
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+
+	clk = &gate->clk;
+
+	ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name);
+	if (ret) {
+		kfree(gate);
+		return ERR_PTR(ret);
+	}
+
+	return clk;
+}
+
+U_BOOT_DRIVER(clk_gate) = {
+	.name	= UBOOT_DM_CLK_GATE,
+	.id	= UCLASS_CLK,
+	.ops	= &clk_gate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 6d62f862d2..8b04ecd7a5 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -69,6 +69,24 @@ struct clk_mux {
 extern const struct clk_ops clk_mux_ops;
 u8 clk_mux_get_parent(struct clk *clk);
 
+struct clk_gate {
+	struct clk	clk;
+	void __iomem	*reg;
+	u8		bit_idx;
+	u8		flags;
+};
+
+#define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk)
+
+#define CLK_GATE_SET_TO_DISABLE		BIT(0)
+#define CLK_GATE_HIWORD_MASK		BIT(1)
+
+extern const struct clk_ops clk_gate_ops;
+struct clk *clk_register_gate(struct device *dev, const char *name,
+			      const char *parent_name, unsigned long flags,
+			      void __iomem *reg, u8 bit_idx,
+			      u8 clk_gate_flags, spinlock_t *lock);
+
 struct clk_div_table {
 	unsigned int	val;
 	unsigned int	div;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 06/16] clk: divider set rate supporrt
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (3 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 05/16] clk: add clk-gate support Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 07/16] clk: fixed_rate: export clk_fixed_rate Peng Fan
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk-divider.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 2ed9ed6ab8..822e09b084 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -18,6 +18,7 @@
 #include <dm/lists.h>
 #include <dm/device-internal.h>
 #include <linux/clk-provider.h>
+#include <linux/log2.h>
 #include <div64.h>
 #include <clk.h>
 #include "clk.h"
@@ -86,8 +87,95 @@ static ulong clk_divider_recalc_rate(struct clk *clk)
 				   divider->flags, divider->width);
 }
 
+static bool _is_valid_table_div(const struct clk_div_table *table,
+				unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static bool _is_valid_div(const struct clk_div_table *table, unsigned int div,
+			  unsigned long flags)
+{
+	if (flags & CLK_DIVIDER_POWER_OF_TWO)
+		return is_power_of_2(div);
+	if (table)
+		return _is_valid_table_div(table, div);
+	return true;
+}
+
+static unsigned int _get_table_val(const struct clk_div_table *table,
+				   unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned int _get_val(const struct clk_div_table *table,
+			     unsigned int div, unsigned long flags, u8 width)
+{
+	if (flags & CLK_DIVIDER_ONE_BASED)
+		return div;
+	if (flags & CLK_DIVIDER_POWER_OF_TWO)
+		return __ffs(div);
+	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
+		return (div == clk_div_mask(width) + 1) ? 0 : div;
+	if (table)
+		return  _get_table_val(table, div);
+	return div - 1;
+}
+int divider_get_val(unsigned long rate, unsigned long parent_rate,
+		    const struct clk_div_table *table, u8 width,
+		    unsigned long flags)
+{
+	unsigned int div, value;
+
+	div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+
+	if (!_is_valid_div(table, div, flags))
+		return -EINVAL;
+
+	value = _get_val(table, div, flags, width);
+
+	return min_t(unsigned int, value, clk_div_mask(width));
+}
+
+static ulong clk_divider_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ?
+			dev_get_clk_ptr(clk->dev) : clk);
+	unsigned long parent_rate = clk_get_parent_rate(clk);
+	int value;
+	u32 val;
+
+	value = divider_get_val(rate, parent_rate, divider->table,
+				divider->width, divider->flags);
+	if (value < 0)
+		return value;
+
+	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
+		val = clk_div_mask(divider->width) << (divider->shift + 16);
+	} else {
+		val = readl(divider->reg);
+		val &= ~(clk_div_mask(divider->width) << divider->shift);
+	}
+	val |= (u32)value << divider->shift;
+	writel(val, divider->reg);
+
+	return clk_get_rate(clk);
+}
+
 const struct clk_ops clk_divider_ops = {
 	.get_rate = clk_divider_recalc_rate,
+	.set_rate = clk_divider_set_rate,
 };
 
 static struct clk *_register_divider(struct device *dev, const char *name,
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 07/16] clk: fixed_rate: export clk_fixed_rate
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (4 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 06/16] clk: divider set rate supporrt Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 08/16] clk: imx: import clk heplers Peng Fan
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Export the structure for others to use.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk_fixed_rate.c | 8 +-------
 include/linux/clk-provider.h | 7 +++++++
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 1fdf8c4e54..08cce0d79b 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -6,13 +6,7 @@
 #include <common.h>
 #include <clk-uclass.h>
 #include <dm.h>
-
-struct clk_fixed_rate {
-	struct clk clk;
-	unsigned long fixed_rate;
-};
-
-#define to_clk_fixed_rate(dev)	((struct clk_fixed_rate *)dev_get_platdata(dev))
+#include <linux/clk-provider.h>
 
 static ulong clk_fixed_rate_get_rate(struct clk *clk)
 {
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 8b04ecd7a5..f42df9b90f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -129,6 +129,13 @@ struct clk_fixed_factor {
 #define to_clk_fixed_factor(_clk) container_of(_clk, struct clk_fixed_factor,\
 					       clk)
 
+struct clk_fixed_rate {
+	struct clk clk;
+	unsigned long fixed_rate;
+};
+
+#define to_clk_fixed_rate(dev)	((struct clk_fixed_rate *)dev_get_platdata(dev))
+
 int clk_register(struct clk *clk, const char *drv_name, const char *name,
 		 const char *parent_name);
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 08/16] clk: imx: import clk heplers
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (5 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 07/16] clk: fixed_rate: export clk_fixed_rate Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 09/16] clk: imx: gate2 add set rate Peng Fan
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Import some clk helpers from Linux Kernel for i.MX8MM usage

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/imx/clk.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index e6d51830e8..1d480d8722 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -36,6 +36,23 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
 			shift, 0x3, 0);
 }
 
+static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate2(NULL, name, parent,
+			CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+			reg, shift, 0x3, 0);
+}
+
+static inline struct clk *imx_clk_gate4_flags(const char *name,
+		const char *parent, void __iomem *reg, u8 shift,
+		unsigned long flags)
+{
+	return clk_register_gate2(NULL, name, parent,
+			flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+			reg, shift, 0x3, 0);
+}
+
 static inline struct clk *imx_clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div)
 {
@@ -50,6 +67,14 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 			reg, shift, width, 0);
 }
 
+static inline struct clk *imx_clk_divider2(const char *name, const char *parent,
+		void __iomem *reg, u8 shift, u8 width)
+{
+	return clk_register_divider(NULL, name, parent,
+			CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+			reg, shift, width, 0);
+}
+
 struct clk *imx_clk_pfd(const char *name, const char *parent_name,
 			void __iomem *reg, u8 idx);
 
@@ -57,6 +82,16 @@ struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
 			      u8 shift, u8 width, const char * const *parents,
 			      int num_parents, void (*fixup)(u32 *val));
 
+static inline struct clk *imx_clk_mux_flags(const char *name,
+			void __iomem *reg, u8 shift, u8 width,
+			const char * const *parents, int num_parents,
+			unsigned long flags)
+{
+	return clk_register_mux(NULL, name, parents, num_parents,
+				flags | CLK_SET_RATE_NO_REPARENT, reg, shift,
+				width, 0);
+}
+
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 			u8 shift, u8 width, const char * const *parents,
 			int num_parents)
@@ -66,4 +101,50 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 			width, 0);
 }
 
+static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
+			u8 shift, u8 width, const char * const *parents,
+			int num_parents)
+{
+	return clk_register_mux(NULL, name, parents, num_parents,
+			CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE,
+			reg, shift, width, 0);
+}
+
+static inline struct clk *imx_clk_gate(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, 0, NULL);
+}
+
+static inline struct clk *imx_clk_gate_flags(const char *name, const char *parent,
+		void __iomem *reg, u8 shift, unsigned long flags)
+{
+	return clk_register_gate(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
+			shift, 0, NULL);
+}
+
+static inline struct clk *imx_clk_gate3(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate(NULL, name, parent,
+			CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+			reg, shift, 0, NULL);
+}
+
+struct clk *imx8m_clk_composite_flags(const char *name,
+		const char * const *parent_names,
+		int num_parents, void __iomem *reg, unsigned long flags);
+
+#define __imx8m_clk_composite(name, parent_names, reg, flags) \
+	imx8m_clk_composite_flags(name, parent_names, \
+		ARRAY_SIZE(parent_names), reg, \
+		flags | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
+
+#define imx8m_clk_composite(name, parent_names, reg) \
+	__imx8m_clk_composite(name, parent_names, reg, 0)
+
+#define imx8m_clk_composite_critical(name, parent_names, reg) \
+	__imx8m_clk_composite(name, parent_names, reg, CLK_IS_CRITICAL)
+
 #endif /* __MACH_IMX_CLK_H */
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 09/16] clk: imx: gate2 add set rate
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (6 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 08/16] clk: imx: import clk heplers Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 10/16] dm: clk: ignore default settings when node not valid Peng Fan
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Add set rate for imx clk-gate2

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/imx/clk-gate2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index 571be32088..1b9db6e791 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -60,7 +60,18 @@ static int clk_gate2_disable(struct clk *clk)
 	return 0;
 }
 
+static ulong clk_gate2_set_rate(struct clk *clk, ulong rate)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (parent)
+		return clk_set_rate(parent, rate);
+
+	return -ENODEV;
+}
+
 static const struct clk_ops clk_gate2_ops = {
+	.set_rate = clk_gate2_set_rate,
 	.enable = clk_gate2_enable,
 	.disable = clk_gate2_disable,
 	.get_rate = clk_generic_get_rate,
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 10/16] dm: clk: ignore default settings when node not valid
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (7 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 09/16] clk: imx: gate2 add set rate Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 11/16] clk-provider: include clk-uclass.h Peng Fan
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

When the device not binded with a node, we need ignore
the parents and rate settings.

Cc: Simon Glass <sjg@chromium.org>
Cc: Jagan Teki <jagan@amarulasolutions.com>
Cc: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Andreas Dannenberg <dannenberg@ti.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk-uclass.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 85dfe712f5..cee4d912b0 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -285,6 +285,9 @@ int clk_set_defaults(struct udevice *dev)
 {
 	int ret;
 
+	if (!dev_of_valid(dev))
+		return 0;
+
 	/* If this not in SPL and pre-reloc state, don't take any action. */
 	if (!(IS_ENABLED(CONFIG_SPL_BUILD) || (gd->flags & GD_FLG_RELOC)))
 		return 0;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 11/16] clk-provider: include clk-uclass.h
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (8 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 10/16] dm: clk: ignore default settings when node not valid Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 12/16] clk: add composite clk support Peng Fan
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Because clk-provider use clk_ops, so let's include clk-uclass.h

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 patch moved to before adding composite clock
V2:
 Rebase

 include/linux/clk-provider.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index f42df9b90f..522e73e851 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -8,6 +8,7 @@
  */
 #ifndef __LINUX_CLK_PROVIDER_H
 #define __LINUX_CLK_PROVIDER_H
+#include <clk-uclass.h>
 
 static inline void clk_dm(ulong id, struct clk *clk)
 {
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 12/16] clk: add composite clk support
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (9 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 11/16] clk-provider: include clk-uclass.h Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 13/16] clk: gate: support sandbox Peng Fan
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Import clk composite clk support from Linux Kernel 5.1-rc5

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/Kconfig          |  14 ++++
 drivers/clk/Makefile         |   1 +
 drivers/clk/clk-composite.c  | 160 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  22 ++++++
 4 files changed, 197 insertions(+)
 create mode 100644 drivers/clk/clk-composite.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 5e92446c18..a3f0171b45 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -53,6 +53,13 @@ config SPL_CLK_CCF
 	  Enable this option if you want to (re-)use the Linux kernel's Common
 	  Clock Framework [CCF] code in U-Boot's SPL.
 
+config SPL_CLK_COMPOSITE_CCF
+	bool "SPL Common Clock Framework [CCF] composite clk support "
+	depends on SPL_CLK_CCF
+	help
+	  Enable this option if you want to (re-)use the Linux kernel's Common
+	  Clock Framework [CCF] composite code in U-Boot's SPL.
+
 config CLK_CCF
 	bool "Common Clock Framework [CCF] support "
 	depends on CLK_IMX6Q || SANDBOX_CLK_CCF
@@ -60,6 +67,13 @@ config CLK_CCF
 	  Enable this option if you want to (re-)use the Linux kernel's Common
 	  Clock Framework [CCF] code in U-Boot's clock driver.
 
+config CLK_COMPOSITE_CCF
+	bool "Common Clock Framework [CCF] composite clk support "
+	depends on CLK_CCF
+	help
+	  Enable this option if you want to (re-)use the Linux kernel's Common
+	  Clock Framework [CCF] composite code in U-Boot's clock driver.
+
 config CLK_STM32F
 	bool "Enable clock driver support for STM32F family"
 	depends on CLK && (STM32F7 || STM32F4)
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 39154eca59..68aabe1ca9 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o
 obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o
 
 obj-y += analogbits/
 obj-y += imx/
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
new file mode 100644
index 0000000000..a5626c33d1
--- /dev/null
+++ b/drivers/clk/clk-composite.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2013 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <clk.h>
+
+#include "clk.h"
+
+#define UBOOT_DM_CLK_COMPOSITE "clk_composite"
+
+static u8 clk_composite_get_parent(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	struct clk *mux = composite->mux;
+
+	return clk_mux_get_parent(mux);
+}
+
+static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk *mux = composite->mux;
+
+	return mux_ops->set_parent(mux, parent);
+}
+
+static unsigned long clk_composite_recalc_rate(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	struct clk *rate = composite->rate;
+
+	return rate_ops->get_rate(rate);
+}
+
+static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	struct clk *clk_rate = composite->rate;
+
+	return rate_ops->set_rate(clk_rate, rate);
+}
+
+static int clk_composite_enable(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk *gate = composite->gate;
+
+	return gate_ops->enable(gate);
+}
+
+static int clk_composite_disable(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk *gate = composite->gate;
+
+	gate_ops->disable(gate);
+
+	return 0;
+}
+
+struct clk_ops clk_composite_ops = {
+	/* This will be set according to clk_register_composite */
+};
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+				   const char * const *parent_names,
+				   int num_parents, struct clk *mux,
+				   const struct clk_ops *mux_ops,
+				   struct clk *rate,
+				   const struct clk_ops *rate_ops,
+				   struct clk *gate,
+				   const struct clk_ops *gate_ops,
+				   unsigned long flags)
+{
+	struct clk *clk;
+	struct clk_composite *composite;
+	int ret;
+	struct clk_ops *composite_ops = &clk_composite_ops;
+
+	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
+	if (!composite)
+		return ERR_PTR(-ENOMEM);
+
+	if (mux && mux_ops) {
+		composite->mux = mux;
+		composite->mux_ops = mux_ops;
+		if (mux_ops->set_parent)
+			composite_ops->set_parent = clk_composite_set_parent;
+		mux->data = (ulong)composite;
+	}
+
+	if (rate && rate_ops) {
+		if (!rate_ops->get_rate) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+		composite_ops->get_rate = clk_composite_recalc_rate;
+
+		/* .set_rate requires either .round_rate or .determine_rate */
+		if (rate_ops->set_rate)
+			composite_ops->set_rate = clk_composite_set_rate;
+
+		composite->rate = rate;
+		composite->rate_ops = rate_ops;
+		rate->data = (ulong)composite;
+	}
+
+	if (gate && gate_ops) {
+		if (!gate_ops->enable || !gate_ops->disable) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		composite->gate = gate;
+		composite->gate_ops = gate_ops;
+		composite_ops->enable = clk_composite_enable;
+		composite_ops->disable = clk_composite_disable;
+		gate->data = (ulong)composite;
+	}
+
+	clk = &composite->clk;
+	ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
+			   parent_names[clk_composite_get_parent(clk)]);
+	if (ret) {
+		clk = ERR_PTR(ret);
+		goto err;
+	}
+
+	return clk;
+
+err:
+	kfree(composite);
+	return clk;
+}
+
+U_BOOT_DRIVER(clk_composite) = {
+	.name	= UBOOT_DM_CLK_COMPOSITE,
+	.id	= UCLASS_CLK,
+	.ops	= &clk_composite_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 522e73e851..b9547736ee 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -137,6 +137,28 @@ struct clk_fixed_rate {
 
 #define to_clk_fixed_rate(dev)	((struct clk_fixed_rate *)dev_get_platdata(dev))
 
+struct clk_composite {
+	struct clk	clk;
+	struct clk_ops	ops;
+
+	struct clk	*mux;
+	struct clk	*rate;
+	struct clk	*gate;
+
+	const struct clk_ops	*mux_ops;
+	const struct clk_ops	*rate_ops;
+	const struct clk_ops	*gate_ops;
+};
+
+#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk)
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+		const char * const *parent_names, int num_parents,
+		struct clk *mux_clk, const struct clk_ops *mux_ops,
+		struct clk *rate_clk, const struct clk_ops *rate_ops,
+		struct clk *gate_clk, const struct clk_ops *gate_ops,
+		unsigned long flags);
+
 int clk_register(struct clk *clk, const char *drv_name, const char *name,
 		 const char *parent_name);
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 13/16] clk: gate: support sandbox
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (10 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 12/16] clk: add composite clk support Peng Fan
@ 2019-07-31  7:01 ` Peng Fan
  2019-07-31  7:02 ` [U-Boot] [PATCH V3 14/16] configs: sandbox: Enable composite clk Peng Fan
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:01 UTC (permalink / raw)
  To: u-boot

Introduce io_gate_val for sandbox clk gate test usage

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk-gate.c       | 11 +++++++++++
 include/linux/clk-provider.h |  3 +++
 2 files changed, 14 insertions(+)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index a3a1fdd3b2..70b8794554 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -55,7 +55,11 @@ static void clk_gate_endisable(struct clk *clk, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
+		reg = gate->io_gate_val;
+#else
 		reg = readl(gate->reg);
+#endif
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -86,7 +90,11 @@ int clk_gate_is_enabled(struct clk *clk)
 			dev_get_clk_ptr(clk->dev) : clk);
 	u32 reg;
 
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
+	reg = gate->io_gate_val;
+#else
 	reg = readl(gate->reg);
+#endif
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
@@ -128,6 +136,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	gate->reg = reg;
 	gate->bit_idx = bit_idx;
 	gate->flags = clk_gate_flags;
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
+	gate->io_gate_val = *(u32 *)reg;
+#endif
 
 	clk = &gate->clk;
 
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b9547736ee..02ff1a311a 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -75,6 +75,9 @@ struct clk_gate {
 	void __iomem	*reg;
 	u8		bit_idx;
 	u8		flags;
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
+	u32		io_gate_val;
+#endif
 };
 
 #define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk)
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 14/16] configs: sandbox: Enable composite clk
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (11 preceding siblings ...)
  2019-07-31  7:01 ` [U-Boot] [PATCH V3 13/16] clk: gate: support sandbox Peng Fan
@ 2019-07-31  7:02 ` Peng Fan
  2019-07-31  7:02 ` [U-Boot] [PATCH V3 15/16] clk: sandbox: add " Peng Fan
  2019-07-31  7:02 ` [U-Boot] [PATCH V3 16/16] test: dm: clk_ccf: test " Peng Fan
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:02 UTC (permalink / raw)
  To: u-boot

Enable composite clk for sandbox test

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 Moved patch order earlier
V2:
 Rebase

 configs/sandbox_defconfig          | 1 +
 configs/sandbox_flattree_defconfig | 1 +
 2 files changed, 2 insertions(+)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index aa09c4571a..7355e3aa1e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -93,6 +93,7 @@ CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_DM_BOOTCOUNT=y
 CONFIG_DM_BOOTCOUNT_RTC=y
 CONFIG_CLK=y
+CONFIG_CLK_COMPOSITE_CCF=y
 CONFIG_SANDBOX_CLK_CCF=y
 CONFIG_CPU=y
 CONFIG_DM_DEMO=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index a70793b7ad..898815fe53 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -66,6 +66,7 @@ CONFIG_DEBUG_DEVRES=y
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
 CONFIG_CLK=y
+CONFIG_CLK_COMPOSITE_CCF=y
 CONFIG_SANDBOX_CLK_CCF=y
 CONFIG_CPU=y
 CONFIG_DM_DEMO=y
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 15/16] clk: sandbox: add composite clk
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (12 preceding siblings ...)
  2019-07-31  7:02 ` [U-Boot] [PATCH V3 14/16] configs: sandbox: Enable composite clk Peng Fan
@ 2019-07-31  7:02 ` Peng Fan
  2019-07-31  7:02 ` [U-Boot] [PATCH V3 16/16] test: dm: clk_ccf: test " Peng Fan
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:02 UTC (permalink / raw)
  To: u-boot

Add composite clk to sandbox driver

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/clk_sandbox_ccf.c | 80 +++++++++++++++++++++++++++++++++++++++++++
 include/sandbox-clk.h         |  1 +
 2 files changed, 81 insertions(+)

diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index edeb0f2cf3..e126f18d8e 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -130,6 +130,80 @@ U_BOOT_DRIVER(sandbox_clk_gate2) = {
 	.ops	= &clk_gate2_ops,
 };
 
+static unsigned long sandbox_clk_composite_divider_recalc_rate(struct clk *clk)
+{
+	struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
+	struct clk_composite *composite = (struct clk_composite *)clk->data;
+	ulong parent_rate = clk_get_parent_rate(&composite->clk);
+	unsigned int val;
+
+	val = divider->io_divider_val;
+	val >>= divider->shift;
+	val &= clk_div_mask(divider->width);
+
+	return divider_recalc_rate(clk, parent_rate, val, divider->table,
+				   divider->flags, divider->width);
+}
+
+static const struct clk_ops sandbox_clk_composite_divider_ops = {
+	.get_rate = sandbox_clk_composite_divider_recalc_rate,
+};
+
+struct clk *sandbox_clk_composite(const char *name,
+				  const char * const *parent_names,
+				  int num_parents, void __iomem *reg,
+				  unsigned long flags)
+{
+	struct clk *clk = ERR_PTR(-ENOMEM);
+	struct clk_divider *div = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_mux *mux = NULL;
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		goto fail;
+
+	mux->reg = reg;
+	mux->shift = 24;
+	mux->mask = 0x7;
+	mux->num_parents = num_parents;
+	mux->flags = flags;
+	mux->parent_names = parent_names;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		goto fail;
+
+	div->reg = reg;
+	div->shift = 16;
+	div->width = 3;
+	div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		goto fail;
+
+	gate->reg = reg;
+	gate->bit_idx = 28;
+	gate->flags = flags;
+
+	clk = clk_register_composite(NULL, name,
+				     parent_names, num_parents,
+				     &mux->clk, &clk_mux_ops, &div->clk,
+				     &sandbox_clk_composite_divider_ops,
+				     &gate->clk, &clk_gate_ops, flags);
+	if (IS_ERR(clk))
+		goto fail;
+
+	return clk;
+
+fail:
+	kfree(gate);
+	kfree(div);
+	kfree(mux);
+	return ERR_CAST(clk);
+}
+
 /* --- Sandbox Gate --- */
 /* The CCF core driver itself */
 static const struct udevice_id sandbox_clk_ccf_test_ids[] = {
@@ -138,6 +212,7 @@ static const struct udevice_id sandbox_clk_ccf_test_ids[] = {
 };
 
 static const char *const usdhc_sels[] = { "pll3_60m", "pll3_80m", };
+static const char *const i2c_sels[] = { "pll3_60m", "pll3_80m", };
 
 static int sandbox_clk_ccf_probe(struct udevice *dev)
 {
@@ -174,6 +249,11 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
 	       sandbox_clk_mux("usdhc2_sel", &reg, 17, 1, usdhc_sels,
 			       ARRAY_SIZE(usdhc_sels)));
 
+	reg = BIT(28) | BIT(24) | BIT(16);
+	clk_dm(SANDBOX_CLK_I2C,
+	       sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels),
+				     &reg, 0));
+
 	return 0;
 }
 
diff --git a/include/sandbox-clk.h b/include/sandbox-clk.h
index 37c9838f76..f449de1364 100644
--- a/include/sandbox-clk.h
+++ b/include/sandbox-clk.h
@@ -19,6 +19,7 @@ enum {
 	SANDBOX_CLK_ECSPI1,
 	SANDBOX_CLK_USDHC1_SEL,
 	SANDBOX_CLK_USDHC2_SEL,
+	SANDBOX_CLK_I2C,
 };
 
 enum sandbox_pllv3_type {
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 16/16] test: dm: clk_ccf: test composite clk
  2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
                   ` (13 preceding siblings ...)
  2019-07-31  7:02 ` [U-Boot] [PATCH V3 15/16] clk: sandbox: add " Peng Fan
@ 2019-07-31  7:02 ` Peng Fan
  14 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-07-31  7:02 UTC (permalink / raw)
  To: u-boot

Test composite clk with dm ccf

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 test/dm/clk_ccf.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index 8d397593a3..bbc4b500e8 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -56,6 +56,14 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 	pclk = clk_get_parent(clk);
 	ut_asserteq_str("pll3_80m", pclk->dev->name);
 
+	/* Test the composite of CCF */
+	ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk);
+	ut_assertok(ret);
+	ut_asserteq_str("i2c", clk->dev->name);
+
+	rate = clk_get_rate(clk);
+	ut_asserteq(rate, 60000000);
+
 	return 1;
 }
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-07-31  7:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 02/16] clk: use clk_dev_binded Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 03/16] clk: mux: add set parent support Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 04/16] clk: export mux/divider ops Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 05/16] clk: add clk-gate support Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 06/16] clk: divider set rate supporrt Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 07/16] clk: fixed_rate: export clk_fixed_rate Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 08/16] clk: imx: import clk heplers Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 09/16] clk: imx: gate2 add set rate Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 10/16] dm: clk: ignore default settings when node not valid Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 11/16] clk-provider: include clk-uclass.h Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 12/16] clk: add composite clk support Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 13/16] clk: gate: support sandbox Peng Fan
2019-07-31  7:02 ` [U-Boot] [PATCH V3 14/16] configs: sandbox: Enable composite clk Peng Fan
2019-07-31  7:02 ` [U-Boot] [PATCH V3 15/16] clk: sandbox: add " Peng Fan
2019-07-31  7:02 ` [U-Boot] [PATCH V3 16/16] test: dm: clk_ccf: test " Peng Fan

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.