All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V2 1/4] clk: introduce enable_count
@ 2019-08-16  9:51 Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 2/4] clk: prograte clk enable/disable to parent Peng Fan
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Peng Fan @ 2019-08-16  9:51 UTC (permalink / raw)
  To: u-boot

As what Linux Kernel 5.3.0 provides when enable/disable clk,
there is an enable_count in clk_core_disable/enable. Introduce
enable_count to track the clk enable/disable count when
clk_enable/disable for CCF. And Initialize enable_count to 0 when
register the clk.

And clk tree dump with enable_count will be supported, it will
be easy for us to check the clk status with enable_count

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

V2:
 Improve commit log
 Rename enable_cnt to enable_count following Linux Kernel

 drivers/clk/clk.c            | 1 +
 drivers/clk/clk_fixed_rate.c | 1 +
 include/clk.h                | 1 +
 3 files changed, 3 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 39b3087067..1cf9987f6c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -40,6 +40,7 @@ int clk_register(struct clk *clk, const char *drv_name,
 		return ret;
 	}
 
+	clk->enable_count = 0;
 	/* Store back pointer to clk from udevice */
 	clk->dev->uclass_priv = clk;
 
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 08cce0d79b..f51126793e 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -27,6 +27,7 @@ static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
 	/* Make fixed rate clock accessible from higher level struct clk */
 	dev->uclass_priv = clk;
 	clk->dev = dev;
+	clk->enable_count = 0;
 
 	return 0;
 }
diff --git a/include/clk.h b/include/clk.h
index 2ebc905e04..212c249385 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -61,6 +61,7 @@ struct clk {
 	struct udevice *dev;
 	long long rate;	/* in HZ */
 	u32 flags;
+	int enable_count;
 	/*
 	 * Written by of_xlate. In the future, we might add more fields here.
 	 */
-- 
2.16.4

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

* [U-Boot] [PATCH V2 2/4] clk: prograte clk enable/disable to parent
  2019-08-16  9:51 [U-Boot] [PATCH V2 1/4] clk: introduce enable_count Peng Fan
@ 2019-08-16  9:55 ` Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 3/4] clk: support clk tree dump Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 4/4] sandbox: clk: add clk enable/disable test code Peng Fan
  2 siblings, 0 replies; 4+ messages in thread
From: Peng Fan @ 2019-08-16  9:55 UTC (permalink / raw)
  To: u-boot

On i.MX8MM, thinking such as clk path
OSC->PLL->PLL GATE->CCM ROOT->CCGR GATE->Device

Only enabling CCGR GATE is not enough, we also need to enable PLL GATE
to make sure the clk path work. So when enabling CCGR GATE,
we could prograte to enabling PLL GATE to make life easier.

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

V2:
 Improve commit log
 Check enable_count when enable/disable to avoid touch hardware
 following Linux

 drivers/clk/clk-uclass.c | 77 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 71 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index cee4d912b0..d083d43727 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -449,13 +449,45 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 int clk_enable(struct clk *clk)
 {
 	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	struct clk *clkp = NULL;
+	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
 
-	if (!ops->enable)
-		return -ENOSYS;
+	if (CONFIG_IS_ENABLED(CLK_CCF)) {
+		/* Take id 0 as a non-valid clk, such as dummy */
+		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
+			if (clkp->enable_count) {
+				clkp->enable_count++;
+				return 0;
+			}
+			if (clkp->dev->parent &&
+			    device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
+				ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent));
+				if (ret) {
+					printf("Enable %s failed\n",
+					       clkp->dev->parent->name);
+					return ret;
+				}
+			}
+		}
 
-	return ops->enable(clk);
+		if (ops->enable) {
+			ret = ops->enable(clk);
+			if (ret) {
+				printf("Enable %s failed\n", clk->dev->name);
+				return ret;
+			}
+		}
+		if (clkp)
+			clkp->enable_count++;
+	} else {
+		if (!ops->enable)
+			return -ENOSYS;
+		return ops->enable(clk);
+	}
+
+	return 0;
 }
 
 int clk_enable_bulk(struct clk_bulk *bulk)
@@ -474,13 +506,46 @@ int clk_enable_bulk(struct clk_bulk *bulk)
 int clk_disable(struct clk *clk)
 {
 	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	struct clk *clkp = NULL;
+	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
 
-	if (!ops->disable)
-		return -ENOSYS;
+	if (CONFIG_IS_ENABLED(CLK_CCF)) {
+		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
+			if (clkp->enable_count == 0) {
+				printf("clk %s already disabled\n",
+				       clkp->dev->name);
+				return 0;
+			}
 
-	return ops->disable(clk);
+			if (--clkp->enable_count > 0)
+				return 0;
+		}
+
+		if (ops->disable) {
+			ret = ops->disable(clk);
+			if (ret)
+				return ret;
+		}
+
+		if (clkp && clkp->dev->parent &&
+		    device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
+			ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent));
+			if (ret) {
+				printf("Disable %s failed\n",
+				       clkp->dev->parent->name);
+				return ret;
+			}
+		}
+	} else {
+		if (!ops->disable)
+			return -ENOSYS;
+
+		return ops->disable(clk);
+	}
+
+	return 0;
 }
 
 int clk_disable_bulk(struct clk_bulk *bulk)
-- 
2.16.4

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

* [U-Boot] [PATCH V2 3/4] clk: support clk tree dump
  2019-08-16  9:51 [U-Boot] [PATCH V2 1/4] clk: introduce enable_count Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 2/4] clk: prograte clk enable/disable to parent Peng Fan
@ 2019-08-16  9:55 ` Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 4/4] sandbox: clk: add clk enable/disable test code Peng Fan
  2 siblings, 0 replies; 4+ messages in thread
From: Peng Fan @ 2019-08-16  9:55 UTC (permalink / raw)
  To: u-boot

The previous code only dump the clk list. This patch is
to support clk tree dump, and also dump the enable_cnt.

The code used in patch is similar to dm_dump_all, but
the code here only filter out the UCLASS_CLK devices.

On i.MX8MM, Partial output:
u-boot=> clk dump
 Rate               Usecnt      Name
------------------------------------------
 24000000             0        |-- clock-osc-24m
 24000000             0        |   |-- dram_pll_ref_sel
 750000000            0        |   |   `-- dram_pll
 750000000            0        |   |       `-- dram_pll_bypass
 750000000            0        |   |           `-- dram_pll_out
 24000000             0        |   |-- arm_pll_ref_sel
 1200000000           0        |   |   `-- arm_pll
 1200000000           0        |   |       `-- arm_pll_bypass
 1200000000           0        |   |           `-- arm_pll_out
 1200000000           0        |   |               `-- arm_a53_src
 1200000000           0        |   |                   `-- arm_a53_cg
 1200000000           0        |   |                       `-- arm_a53_div
 24000000             4        |   |-- sys_pll1_ref_sel
 800000000            4        |   |   `-- sys_pll1
 800000000            4        |   |       `-- sys_pll1_bypass
 800000000            4        |   |           `-- sys_pll1_out
 40000000             0        |   |               |-- sys_pll1_40m

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

V2:
 Improve commit log

 cmd/clk.c | 77 ++++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 44 insertions(+), 33 deletions(-)

diff --git a/cmd/clk.c b/cmd/clk.c
index 5402c87de7..c0a64ff770 100644
--- a/cmd/clk.c
+++ b/cmd/clk.c
@@ -7,50 +7,61 @@
 #include <clk.h>
 #if defined(CONFIG_DM) && defined(CONFIG_CLK)
 #include <dm.h>
+#include <dm/device.h>
+#include <dm/root.h>
 #include <dm/device-internal.h>
+#include <linux/clk-provider.h>
 #endif
 
-int __weak soc_clk_dump(void)
+static void show_clks(struct udevice *dev, int depth, int last_flag)
 {
-#if defined(CONFIG_DM) && defined(CONFIG_CLK)
-	struct udevice *dev;
-	struct uclass *uc;
-	struct clk clk;
-	int ret;
-	ulong rate;
-
-	/* Device addresses start at 1 */
-	ret = uclass_get(UCLASS_CLK, &uc);
-	if (ret)
-		return ret;
-
-	uclass_foreach_dev(dev, uc) {
-		memset(&clk, 0, sizeof(clk));
-		ret = device_probe(dev);
-		if (ret)
-			goto noclk;
+	int i, is_last;
+	struct udevice *child;
+	struct clk *clkp;
+	u32 rate;
+
+	clkp = dev_get_clk_ptr(dev);
+	if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) {
+		rate = clk_get_rate(clkp);
+
+	printf(" %-12u  %8d        ", rate, clkp->enable_count);
+
+	for (i = depth; i >= 0; i--) {
+		is_last = (last_flag >> i) & 1;
+		if (i) {
+			if (is_last)
+				printf("    ");
+			else
+				printf("|   ");
+		} else {
+			if (is_last)
+				printf("`-- ");
+			else
+				printf("|-- ");
+		}
+	}
 
-		ret = clk_request(dev, &clk);
-		if (ret)
-			goto noclk;
+	printf("%s\n", dev->name);
+	}
 
-		rate = clk_get_rate(&clk);
-		clk_free(&clk);
+	list_for_each_entry(child, &dev->child_head, sibling_node) {
+		is_last = list_is_last(&child->sibling_node, &dev->child_head);
+		show_clks(child, depth + 1, (last_flag << 1) | is_last);
+	}
+}
 
-		if (rate == -ENODEV)
-			goto noclk;
+int __weak soc_clk_dump(void)
+{
+	struct udevice *root;
 
-		printf("%-30.30s : %lu Hz\n", dev->name, rate);
-		continue;
-	noclk:
-		printf("%-30.30s : ? Hz\n", dev->name);
+	root = dm_root();
+	if (root) {
+		printf(" Rate               Usecnt      Name\n");
+		printf("------------------------------------------\n");
+		show_clks(root, -1, 0);
 	}
 
 	return 0;
-#else
-	puts("Not implemented\n");
-	return 1;
-#endif
 }
 
 static int do_clk_dump(cmd_tbl_t *cmdtp, int flag, int argc,
-- 
2.16.4

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

* [U-Boot] [PATCH V2 4/4] sandbox: clk: add clk enable/disable test code
  2019-08-16  9:51 [U-Boot] [PATCH V2 1/4] clk: introduce enable_count Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 2/4] clk: prograte clk enable/disable to parent Peng Fan
  2019-08-16  9:55 ` [U-Boot] [PATCH V2 3/4] clk: support clk tree dump Peng Fan
@ 2019-08-16  9:55 ` Peng Fan
  2 siblings, 0 replies; 4+ messages in thread
From: Peng Fan @ 2019-08-16  9:55 UTC (permalink / raw)
  To: u-boot

Since we added clk enable_count and prograte clk child enabling
operation to clk parent, so add a new function sandbox_clk_enable_count
to get enable_count for test usage.

And add test code to get the enable_count after we enable/disable
the device clk.

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

V2:
 New patch

 drivers/clk/clk_sandbox_ccf.c | 15 +++++++++++++++
 include/sandbox-clk.h         |  3 +++
 test/dm/clk_ccf.c             | 26 ++++++++++++++++++++++++++
 3 files changed, 44 insertions(+)

diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index e126f18d8e..9fa27229e1 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -25,6 +25,18 @@ struct clk_pllv3 {
 	u32		div_shift;
 };
 
+int sandbox_clk_enable_count(struct clk *clk)
+{
+	struct clk *clkp = NULL;
+	int ret;
+
+	ret = clk_get_by_id(clk->id, &clkp);
+	if (ret)
+		return 0;
+
+	return clkp->enable_count;
+}
+
 static ulong clk_pllv3_get_rate(struct clk *clk)
 {
 	unsigned long parent_rate = clk_get_parent_rate(clk);
@@ -254,6 +266,9 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
 	       sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels),
 				     &reg, 0));
 
+	clk_dm(SANDBOX_CLK_I2C_ROOT,
+	       sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0));
+
 	return 0;
 }
 
diff --git a/include/sandbox-clk.h b/include/sandbox-clk.h
index f449de1364..296cddfbb0 100644
--- a/include/sandbox-clk.h
+++ b/include/sandbox-clk.h
@@ -20,6 +20,7 @@ enum {
 	SANDBOX_CLK_USDHC1_SEL,
 	SANDBOX_CLK_USDHC2_SEL,
 	SANDBOX_CLK_I2C,
+	SANDBOX_CLK_I2C_ROOT,
 };
 
 enum sandbox_pllv3_type {
@@ -74,4 +75,6 @@ static inline struct clk *sandbox_clk_mux(const char *name, void __iomem *reg,
 				width, 0);
 }
 
+int sandbox_clk_enable_count(struct clk *clk);
+
 #endif /* __SANDBOX_CLK_H__ */
diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index bbc4b500e8..f2a8905af5 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -64,6 +64,32 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 	rate = clk_get_rate(clk);
 	ut_asserteq(rate, 60000000);
 
+	/* Test clk tree enable/disable */
+	ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, &clk);
+	ut_assertok(ret);
+	ut_asserteq_str("i2c_root", clk->dev->name);
+
+	ret = clk_enable(clk);
+	ut_assertok(ret);
+
+	ret = sandbox_clk_enable_count(clk);
+	ut_asserteq(ret, 1);
+
+	ret = clk_get_by_id(SANDBOX_CLK_I2C, &pclk);
+	ut_assertok(ret);
+
+	ret = sandbox_clk_enable_count(pclk);
+	ut_asserteq(ret, 1);
+
+	ret = clk_disable(clk);
+	ut_assertok(ret);
+
+	ret = sandbox_clk_enable_count(clk);
+	ut_asserteq(ret, 0);
+
+	ret = sandbox_clk_enable_count(pclk);
+	ut_asserteq(ret, 0);
+
 	return 1;
 }
 
-- 
2.16.4

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

end of thread, other threads:[~2019-08-16  9:55 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-16  9:51 [U-Boot] [PATCH V2 1/4] clk: introduce enable_count Peng Fan
2019-08-16  9:55 ` [U-Boot] [PATCH V2 2/4] clk: prograte clk enable/disable to parent Peng Fan
2019-08-16  9:55 ` [U-Boot] [PATCH V2 3/4] clk: support clk tree dump Peng Fan
2019-08-16  9:55 ` [U-Boot] [PATCH V2 4/4] sandbox: clk: add clk enable/disable test code 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.