All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment
@ 2019-10-22 12:00 Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 1/5] drivers: clk: Handle gracefully NULL pointers Jean-Jacques Hiblot
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Jean-Jacques Hiblot @ 2019-10-22 12:00 UTC (permalink / raw)
  To: u-boot


This is the second of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about clocks. It adds a managed API, using
the same API as linux. It also fix a use-case where the clock is
initialized (rate and/or mux) when it is probed using the
assigned-clocks-* properties.


Changes in v2:
- Add clk_prepare_enable/clk_disable_unprepare
- remove conflicting implmentations from brcmnand_compat.{c,h}

Jean-Jacques Hiblot (5):
  drivers: clk: Handle gracefully NULL pointers
  drivers: clk: Add a managed API to get clocks from the device-tree
  test: clk: Update tests to also check the managed API
  drivers: clk: Fix using assigned-clocks in the node of the clock it
    sets up
  test: clk: test clock self assignment

 arch/sandbox/dts/test.dts                     |   8 +-
 arch/sandbox/include/asm/clk.h                |  33 +++++
 drivers/clk/clk-uclass.c                      | 139 ++++++++++++++++--
 drivers/clk/clk_sandbox.c                     |  56 +++++++
 drivers/clk/clk_sandbox_test.c                |  66 +++++++--
 drivers/core/device.c                         |   2 +-
 .../mtd/nand/raw/brcmnand/brcmnand_compat.c   |  30 ----
 .../mtd/nand/raw/brcmnand/brcmnand_compat.h   |   4 -
 include/clk.h                                 |  56 ++++++-
 test/dm/clk.c                                 |  36 ++++-
 10 files changed, 367 insertions(+), 63 deletions(-)

-- 
2.17.1

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

* [U-Boot] [PATCH v2 1/5] drivers: clk: Handle gracefully NULL pointers
  2019-10-22 12:00 [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment Jean-Jacques Hiblot
@ 2019-10-22 12:00 ` Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 2/5] drivers: clk: Add a managed API to get clocks from the device-tree Jean-Jacques Hiblot
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jean-Jacques Hiblot @ 2019-10-22 12:00 UTC (permalink / raw)
  To: u-boot

Prepare the way for a managed CLK API by handling NULL pointers without
crashing nor failing.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---

Changes in v2: None

 drivers/clk/clk-uclass.c | 43 +++++++++++++++++++++++++++++++++-------
 include/clk.h            |  2 +-
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 64c181f4ad..dff395fedb 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -349,9 +349,12 @@ int clk_release_all(struct clk *clk, int count)
 
 int clk_request(struct udevice *dev, struct clk *clk)
 {
-	const struct clk_ops *ops = clk_dev_ops(dev);
+	const struct clk_ops *ops;
 
 	debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(dev);
 
 	clk->dev = dev;
 
@@ -363,9 +366,12 @@ int clk_request(struct udevice *dev, struct clk *clk)
 
 int clk_free(struct clk *clk)
 {
-	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops;
 
 	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(clk->dev);
 
 	if (!ops->free)
 		return 0;
@@ -375,9 +381,12 @@ int clk_free(struct clk *clk)
 
 ulong clk_get_rate(struct clk *clk)
 {
-	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops;
 
 	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(clk->dev);
 
 	if (!ops->get_rate)
 		return -ENOSYS;
@@ -391,6 +400,8 @@ struct clk *clk_get_parent(struct clk *clk)
 	struct clk *pclk;
 
 	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk)
+		return NULL;
 
 	pdev = dev_get_parent(clk->dev);
 	pclk = dev_get_clk_ptr(pdev);
@@ -406,6 +417,8 @@ long long clk_get_parent_rate(struct clk *clk)
 	struct clk *pclk;
 
 	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk)
+		return 0;
 
 	pclk = clk_get_parent(clk);
 	if (IS_ERR(pclk))
@@ -424,9 +437,12 @@ long long clk_get_parent_rate(struct clk *clk)
 
 ulong clk_set_rate(struct clk *clk, ulong rate)
 {
-	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops;
 
 	debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(clk->dev);
 
 	if (!ops->set_rate)
 		return -ENOSYS;
@@ -436,9 +452,12 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
-	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops;
 
 	debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(clk->dev);
 
 	if (!ops->set_parent)
 		return -ENOSYS;
@@ -448,11 +467,14 @@ 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);
+	const struct clk_ops *ops;
 	struct clk *clkp = NULL;
 	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(clk->dev);
 
 	if (CONFIG_IS_ENABLED(CLK_CCF)) {
 		/* Take id 0 as a non-valid clk, such as dummy */
@@ -505,11 +527,14 @@ int clk_enable_bulk(struct clk_bulk *bulk)
 
 int clk_disable(struct clk *clk)
 {
-	const struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops;
 	struct clk *clkp = NULL;
 	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk)
+		return 0;
+	ops = clk_dev_ops(clk->dev);
 
 	if (CONFIG_IS_ENABLED(CLK_CCF)) {
 		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
@@ -589,6 +614,10 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
 	if (p == q)
 		return true;
 
+	/* trivial case #2: on the clk pointer is NULL */
+	if (!p || !q)
+		return false;
+
 	/* same device, id and data */
 	if (p->dev == q->dev && p->id == q->id && p->data == q->data)
 		return true;
diff --git a/include/clk.h b/include/clk.h
index 18b2e3ca54..6568865d40 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -356,7 +356,7 @@ int soc_clk_dump(void);
  */
 static inline bool clk_valid(struct clk *clk)
 {
-	return !!clk->dev;
+	return clk && !!clk->dev;
 }
 
 /**
-- 
2.17.1

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

* [U-Boot] [PATCH v2 2/5] drivers: clk: Add a managed API to get clocks from the device-tree
  2019-10-22 12:00 [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 1/5] drivers: clk: Handle gracefully NULL pointers Jean-Jacques Hiblot
@ 2019-10-22 12:00 ` Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 3/5] test: clk: Update tests to also check the managed API Jean-Jacques Hiblot
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jean-Jacques Hiblot @ 2019-10-22 12:00 UTC (permalink / raw)
  To: u-boot

Add devm_clk_get(), devm_clk_get_optional() to get clocks from the
device-tree. The clocks is automatically released and the data structure
freed when the device is unbound.
Also add devm_clk_put() to release the clock and free the data structure
manually.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>

---

Changes in v2:
- Add clk_prepare_enable/clk_disable_unprepare
- remove conflicting implmentations from brcmnand_compat.{c,h}

 drivers/clk/clk-uclass.c                      | 48 +++++++++++++++++++
 .../mtd/nand/raw/brcmnand/brcmnand_compat.c   | 30 ------------
 .../mtd/nand/raw/brcmnand/brcmnand_compat.h   |  4 --
 include/clk.h                                 | 47 ++++++++++++++++++
 4 files changed, 95 insertions(+), 34 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dff395fedb..e7ec6347de 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -625,6 +625,54 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
 	return false;
 }
 
+static void devm_clk_release(struct udevice *dev, void *res)
+{
+	clk_free(res);
+}
+
+static int devm_clk_match(struct udevice *dev, void *res, void *data)
+{
+	return res == data;
+}
+
+struct clk *devm_clk_get(struct udevice *dev, const char *id)
+{
+	int rc;
+	struct clk *clk;
+
+	clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO);
+	if (unlikely(!clk))
+		return ERR_PTR(-ENOMEM);
+
+	rc = clk_get_by_name(dev, id, clk);
+	if (rc)
+		return ERR_PTR(rc);
+
+	devres_add(dev, clk);
+	return clk;
+}
+
+struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)
+{
+	struct clk *clk = devm_clk_get(dev, id);
+
+	if (IS_ERR(clk))
+		return NULL;
+
+	return clk;
+}
+
+void devm_clk_put(struct udevice *dev, struct clk *clk)
+{
+	int rc;
+
+	if (!clk)
+		return;
+
+	rc = devres_release(dev, devm_clk_release, devm_clk_match, clk);
+	WARN_ON(rc);
+}
+
 UCLASS_DRIVER(clk) = {
 	.id		= UCLASS_CLK,
 	.name		= "clk",
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c
index 96b27e6e5a..883948355c 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c
@@ -3,36 +3,6 @@
 #include <common.h>
 #include "brcmnand_compat.h"
 
-struct clk *devm_clk_get(struct udevice *dev, const char *id)
-{
-	struct clk *clk;
-	int ret;
-
-	clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
-	if (!clk) {
-		debug("%s: can't allocate clock\n", __func__);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	ret = clk_get_by_name(dev, id, clk);
-	if (ret < 0) {
-		debug("%s: can't get clock (ret = %d)!\n", __func__, ret);
-		return ERR_PTR(ret);
-	}
-
-	return clk;
-}
-
-int clk_prepare_enable(struct clk *clk)
-{
-	return clk_enable(clk);
-}
-
-void clk_disable_unprepare(struct clk *clk)
-{
-	clk_disable(clk);
-}
-
 static char *devm_kvasprintf(struct udevice *dev, gfp_t gfp, const char *fmt,
 			     va_list ap)
 {
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h
index 02cab0f828..6f9bec7085 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h
@@ -6,10 +6,6 @@
 #include <clk.h>
 #include <dm.h>
 
-struct clk *devm_clk_get(struct udevice *dev, const char *id);
-int clk_prepare_enable(struct clk *clk);
-void clk_disable_unprepare(struct clk *clk);
-
 char *devm_kasprintf(struct udevice *dev, gfp_t gfp, const char *fmt, ...);
 
 #endif /* __BRCMNAND_COMPAT_H */
diff --git a/include/clk.h b/include/clk.h
index 6568865d40..9be3264113 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -154,6 +154,37 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk);
  */
 int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
 
+/**
+ * devm_clk_get - lookup and obtain a managed reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno.  The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer.  (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * devm_clk_get should not be called from within interrupt context.
+ *
+ * The clock will automatically be freed when the device is unbound
+ * from the bus.
+ */
+struct clk *devm_clk_get(struct udevice *dev, const char *id);
+
+/**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *			   clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as devm_clk_get() except where there is no clock producer.
+ * In this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct udevice *dev, const char *id);
+
 /**
  * clk_release_all() - Disable (turn off)/Free an array of previously
  * requested clocks.
@@ -168,6 +199,19 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
  */
 int clk_release_all(struct clk *clk, int count);
 
+/**
+ * devm_clk_put	- "free" a managed clock source
+ * @dev: device used to acquire the clock
+ * @clk: clock source acquired with devm_clk_get()
+ *
+ * Note: drivers must ensure that all clk_enable calls made on this
+ * clock source are balanced by clk_disable calls prior to calling
+ * this function.
+ *
+ * clk_put should not be called from within interrupt context.
+ */
+void devm_clk_put(struct udevice *dev, struct clk *clk);
+
 #else
 static inline int clk_get_by_index(struct udevice *dev, int index,
 				   struct clk *clk)
@@ -379,3 +423,6 @@ int clk_get_by_id(ulong id, struct clk **clkp);
  */
 bool clk_dev_binded(struct clk *clk);
 #endif
+
+#define clk_prepare_enable(clk) clk_enable(clk)
+#define clk_disable_unprepare(clk) clk_disable(clk)
-- 
2.17.1

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

* [U-Boot] [PATCH v2 3/5] test: clk: Update tests to also check the managed API
  2019-10-22 12:00 [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 1/5] drivers: clk: Handle gracefully NULL pointers Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 2/5] drivers: clk: Add a managed API to get clocks from the device-tree Jean-Jacques Hiblot
@ 2019-10-22 12:00 ` Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 4/5] drivers: clk: Fix using assigned-clocks in the node of the clock it sets up Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 5/5] test: clk: test clock self assignment Jean-Jacques Hiblot
  4 siblings, 0 replies; 6+ messages in thread
From: Jean-Jacques Hiblot @ 2019-10-22 12:00 UTC (permalink / raw)
  To: u-boot

Add a few more clocks the clk_sandbox clock provider and get them using
the managed API.
Make sure they are released when the device is removed.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---

Changes in v2: None

 arch/sandbox/dts/test.dts      |  6 ++--
 arch/sandbox/include/asm/clk.h | 33 +++++++++++++++++
 drivers/clk/clk_sandbox.c      | 34 ++++++++++++++++++
 drivers/clk/clk_sandbox_test.c | 66 +++++++++++++++++++++++++++++-----
 test/dm/clk.c                  | 36 ++++++++++++++++++-
 5 files changed, 163 insertions(+), 12 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5d9ab3724f..0ee86a74ed 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -232,8 +232,10 @@
 		compatible = "sandbox,clk-test";
 		clocks = <&clk_fixed>,
 			 <&clk_sandbox 1>,
-			 <&clk_sandbox 0>;
-		clock-names = "fixed", "i2c", "spi";
+			 <&clk_sandbox 0>,
+			 <&clk_sandbox 3>,
+			 <&clk_sandbox 2>;
+		clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
 	};
 
 	ccf: clk-ccf {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index 2b1c49f783..1573e4a134 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -19,6 +19,8 @@ struct udevice;
 enum sandbox_clk_id {
 	SANDBOX_CLK_ID_SPI,
 	SANDBOX_CLK_ID_I2C,
+	SANDBOX_CLK_ID_UART1,
+	SANDBOX_CLK_ID_UART2,
 
 	SANDBOX_CLK_ID_COUNT,
 };
@@ -33,10 +35,15 @@ enum sandbox_clk_test_id {
 	SANDBOX_CLK_TEST_ID_FIXED,
 	SANDBOX_CLK_TEST_ID_SPI,
 	SANDBOX_CLK_TEST_ID_I2C,
+	SANDBOX_CLK_TEST_ID_DEVM1,
+	SANDBOX_CLK_TEST_ID_DEVM2,
+	SANDBOX_CLK_TEST_ID_DEVM_NULL,
 
 	SANDBOX_CLK_TEST_ID_COUNT,
 };
 
+#define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
+
 /**
  * sandbox_clk_query_rate - Query the current rate of a sandbox clock.
  *
@@ -53,6 +60,14 @@ ulong sandbox_clk_query_rate(struct udevice *dev, int id);
  * @return:	The rate of the clock.
  */
 int sandbox_clk_query_enable(struct udevice *dev, int id);
+/**
+ * sandbox_clk_query_requested - Query the requested state of a sandbox clock.
+ *
+ * @dev:	The sandbox clock provider device.
+ * @id:		The clock to query.
+ * @return:	The rate of the clock.
+ */
+int sandbox_clk_query_requested(struct udevice *dev, int id);
 
 /**
  * sandbox_clk_test_get - Ask the sandbox clock test device to request its
@@ -62,6 +77,16 @@ int sandbox_clk_query_enable(struct udevice *dev, int id);
  * @return:	0 if OK, or a negative error code.
  */
 int sandbox_clk_test_get(struct udevice *dev);
+
+/**
+ * sandbox_clk_test_devm_get - Ask the sandbox clock test device to request its
+ * clocks using the managed API.
+ *
+ * @dev:	The sandbox clock test (client) devivce.
+ * @return:	0 if OK, or a negative error code.
+ */
+int sandbox_clk_test_devm_get(struct udevice *dev);
+
 /**
  * sandbox_clk_test_get_bulk - Ask the sandbox clock test device to request its
  * clocks with the bulk clk API.
@@ -146,5 +171,13 @@ int sandbox_clk_test_release_bulk(struct udevice *dev);
  * @return:	0 if OK, or a negative error code.
  */
 int sandbox_clk_test_valid(struct udevice *dev);
+/**
+ * sandbox_clk_test_valid - Ask the sandbox clock test device to check its
+ * clocks are valid.
+ *
+ * @dev:	The sandbox clock test (client) devivce.
+ * @return:	0 if OK, or a negative error code.
+ */
+struct clk *sandbox_clk_test_get_devm_clk(struct udevice *dev, int id);
 
 #endif
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index 1d5cbb589a..d152fd7e5b 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -12,6 +12,7 @@
 struct sandbox_clk_priv {
 	ulong rate[SANDBOX_CLK_ID_COUNT];
 	bool enabled[SANDBOX_CLK_ID_COUNT];
+	bool requested[SANDBOX_CLK_ID_COUNT];
 };
 
 static ulong sandbox_clk_get_rate(struct clk *clk)
@@ -65,11 +66,35 @@ static int sandbox_clk_disable(struct clk *clk)
 	return 0;
 }
 
+static int sandbox_clk_request(struct clk *clk)
+{
+	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+	if (clk->id >= SANDBOX_CLK_ID_COUNT)
+		return -EINVAL;
+
+	priv->requested[clk->id] = true;
+	return 0;
+}
+
+static int sandbox_clk_free(struct clk *clk)
+{
+	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+	if (clk->id >= SANDBOX_CLK_ID_COUNT)
+		return -EINVAL;
+
+	priv->requested[clk->id] = false;
+	return 0;
+}
+
 static struct clk_ops sandbox_clk_ops = {
 	.get_rate	= sandbox_clk_get_rate,
 	.set_rate	= sandbox_clk_set_rate,
 	.enable		= sandbox_clk_enable,
 	.disable	= sandbox_clk_disable,
+	.request	= sandbox_clk_request,
+	.free		= sandbox_clk_free,
 };
 
 static const struct udevice_id sandbox_clk_ids[] = {
@@ -104,3 +129,12 @@ int sandbox_clk_query_enable(struct udevice *dev, int id)
 
 	return priv->enabled[id];
 }
+
+int sandbox_clk_query_requested(struct udevice *dev, int id)
+{
+	struct sandbox_clk_priv *priv = dev_get_priv(dev);
+
+	if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
+		return -EINVAL;
+	return priv->requested[id];
+}
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index e8465dbfad..41954660ea 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -9,7 +9,8 @@
 #include <asm/clk.h>
 
 struct sandbox_clk_test {
-	struct clk clks[SANDBOX_CLK_TEST_ID_COUNT];
+	struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
+	struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
 	struct clk_bulk bulk;
 };
 
@@ -24,7 +25,7 @@ int sandbox_clk_test_get(struct udevice *dev)
 	struct sandbox_clk_test *sbct = dev_get_priv(dev);
 	int i, ret;
 
-	for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+	for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
 		ret = clk_get_by_name(dev, sandbox_clk_test_names[i],
 				      &sbct->clks[i]);
 		if (ret)
@@ -34,6 +35,37 @@ int sandbox_clk_test_get(struct udevice *dev)
 	return 0;
 }
 
+int sandbox_clk_test_devm_get(struct udevice *dev)
+{
+	struct sandbox_clk_test *sbct = dev_get_priv(dev);
+	struct clk *clk;
+
+	clk = devm_clk_get(dev, "no-an-existing-clock");
+	if (!IS_ERR(clk)) {
+		dev_err(dev, "devm_clk_get() should have failed\n");
+		return -EINVAL;
+	}
+
+	clk = devm_clk_get(dev, "uart2");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+	sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1] = clk;
+
+	clk = devm_clk_get_optional(dev, "uart1");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+	sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM2] = clk;
+
+	sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM_NULL] = NULL;
+	clk = devm_clk_get_optional(dev, "not_an_existing_clock");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+	if (clk)
+		return -EINVAL;
+
+	return 0;
+}
+
 int sandbox_clk_test_get_bulk(struct udevice *dev)
 {
 	struct sandbox_clk_test *sbct = dev_get_priv(dev);
@@ -48,7 +80,7 @@ ulong sandbox_clk_test_get_rate(struct udevice *dev, int id)
 	if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
 		return -EINVAL;
 
-	return clk_get_rate(&sbct->clks[id]);
+	return clk_get_rate(sbct->clkps[id]);
 }
 
 ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
@@ -58,7 +90,7 @@ ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
 	if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
 		return -EINVAL;
 
-	return clk_set_rate(&sbct->clks[id], rate);
+	return clk_set_rate(sbct->clkps[id], rate);
 }
 
 int sandbox_clk_test_enable(struct udevice *dev, int id)
@@ -68,7 +100,7 @@ int sandbox_clk_test_enable(struct udevice *dev, int id)
 	if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
 		return -EINVAL;
 
-	return clk_enable(&sbct->clks[id]);
+	return clk_enable(sbct->clkps[id]);
 }
 
 int sandbox_clk_test_enable_bulk(struct udevice *dev)
@@ -85,7 +117,7 @@ int sandbox_clk_test_disable(struct udevice *dev, int id)
 	if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
 		return -EINVAL;
 
-	return clk_disable(&sbct->clks[id]);
+	return clk_disable(sbct->clkps[id]);
 }
 
 int sandbox_clk_test_disable_bulk(struct udevice *dev)
@@ -100,7 +132,8 @@ int sandbox_clk_test_free(struct udevice *dev)
 	struct sandbox_clk_test *sbct = dev_get_priv(dev);
 	int i, ret;
 
-	for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+	devm_clk_put(dev, sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1]);
+	for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
 		ret = clk_free(&sbct->clks[i]);
 		if (ret)
 			return ret;
@@ -122,13 +155,27 @@ int sandbox_clk_test_valid(struct udevice *dev)
 	int i;
 
 	for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
-		if (!clk_valid(&sbct->clks[i]))
-			return -EINVAL;
+		if (!clk_valid(sbct->clkps[i]))
+			if (i != SANDBOX_CLK_TEST_ID_DEVM_NULL)
+				return -EINVAL;
 	}
 
 	return 0;
 }
 
+static int sandbox_clk_test_probe(struct udevice *dev)
+{
+	struct sandbox_clk_test *sbct = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < SANDBOX_CLK_TEST_ID_DEVM1; i++)
+		sbct->clkps[i] = &sbct->clks[i];
+	for (i = SANDBOX_CLK_TEST_ID_DEVM1; i < SANDBOX_CLK_TEST_ID_COUNT; i++)
+		sbct->clkps[i] = NULL;
+
+	return 0;
+}
+
 static const struct udevice_id sandbox_clk_test_ids[] = {
 	{ .compatible = "sandbox,clk-test" },
 	{ }
@@ -138,5 +185,6 @@ U_BOOT_DRIVER(sandbox_clk_test) = {
 	.name = "sandbox_clk_test",
 	.id = UCLASS_MISC,
 	.of_match = sandbox_clk_test_ids,
+	.probe = sandbox_clk_test_probe,
 	.priv_auto_alloc_size = sizeof(struct sandbox_clk_test),
 };
diff --git a/test/dm/clk.c b/test/dm/clk.c
index 676ef217f0..3ad0ad8ca3 100644
--- a/test/dm/clk.c
+++ b/test/dm/clk.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <asm/clk.h>
 #include <dm/test.h>
+#include <dm/device-internal.h>
 #include <linux/err.h>
 #include <test/ut.h>
 
@@ -53,8 +54,19 @@ static int dm_test_clk(struct unit_test_state *uts)
 	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test",
 					      &dev_test));
 	ut_assertok(sandbox_clk_test_get(dev_test));
+	ut_assertok(sandbox_clk_test_devm_get(dev_test));
 	ut_assertok(sandbox_clk_test_valid(dev_test));
 
+	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
+						 SANDBOX_CLK_TEST_ID_DEVM_NULL));
+	ut_asserteq(0, sandbox_clk_test_set_rate(dev_test,
+						 SANDBOX_CLK_TEST_ID_DEVM_NULL,
+						 0));
+	ut_asserteq(0, sandbox_clk_test_enable(dev_test,
+					       SANDBOX_CLK_TEST_ID_DEVM_NULL));
+	ut_asserteq(0, sandbox_clk_test_disable(dev_test,
+						SANDBOX_CLK_TEST_ID_DEVM_NULL));
+
 	ut_asserteq(1234,
 		    sandbox_clk_test_get_rate(dev_test,
 					      SANDBOX_CLK_TEST_ID_FIXED));
@@ -62,6 +74,10 @@ static int dm_test_clk(struct unit_test_state *uts)
 						 SANDBOX_CLK_TEST_ID_SPI));
 	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 						 SANDBOX_CLK_TEST_ID_I2C));
+	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
+						 SANDBOX_CLK_TEST_ID_DEVM1));
+	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
+						 SANDBOX_CLK_TEST_ID_DEVM2));
 
 	rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_FIXED,
 					 12345);
@@ -121,8 +137,25 @@ static int dm_test_clk(struct unit_test_state *uts)
 	ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
 	ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
 
+	ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_SPI));
+	ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_I2C));
+	ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_UART2));
 	ut_assertok(sandbox_clk_test_free(dev_test));
-
+	ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_SPI));
+	ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_I2C));
+	ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_UART2));
+
+	ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_UART1));
+	ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL));
+	ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+						   SANDBOX_CLK_ID_UART1));
 	return 0;
 }
 DM_TEST(dm_test_clk, DM_TESTF_SCAN_FDT);
@@ -159,6 +192,7 @@ static int dm_test_clk_bulk(struct unit_test_state *uts)
 	ut_assertok(sandbox_clk_test_release_bulk(dev_test));
 	ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
 	ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
+	ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL));
 
 	return 0;
 }
-- 
2.17.1

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

* [U-Boot] [PATCH v2 4/5] drivers: clk: Fix using assigned-clocks in the node of the clock it sets up
  2019-10-22 12:00 [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment Jean-Jacques Hiblot
                   ` (2 preceding siblings ...)
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 3/5] test: clk: Update tests to also check the managed API Jean-Jacques Hiblot
@ 2019-10-22 12:00 ` Jean-Jacques Hiblot
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 5/5] test: clk: test clock self assignment Jean-Jacques Hiblot
  4 siblings, 0 replies; 6+ messages in thread
From: Jean-Jacques Hiblot @ 2019-10-22 12:00 UTC (permalink / raw)
  To: u-boot

This fixes the case where assigned-clocks is used to define a clock
defaults inside this same clock's node. This is used sometimes to setup a
default parents and/or rate for a clock.

example:
muxed_clock: muxed_clock {
	clocks = <&clk_provider 0>, <&clk_provider 1>;
	#clock-cells = <0>;
	assigned-clocks = <&muxed_clock>;
	assigned-clock-parents = <&clk_provider 1>;
};

It doesn't work in u-boot because the assigned-clocks are setup *before*
the clock is probed. (clk_set_parent() will likely crash or fail if called
before the device probe function)
Making it work by handling "assigned-clocks" in 2 steps: first before the
clk device is probed, and then after the clk device is probed.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---

Changes in v2: None

 drivers/clk/clk-uclass.c | 48 +++++++++++++++++++++++++++++++++++-----
 drivers/core/device.c    |  2 +-
 include/clk.h            |  7 ++++--
 3 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index e7ec6347de..75d618a47b 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -178,7 +178,7 @@ bulk_get_err:
 	return ret;
 }
 
-static int clk_set_default_parents(struct udevice *dev)
+static int clk_set_default_parents(struct udevice *dev, int stage)
 {
 	struct clk clk, parent_clk;
 	int index;
@@ -214,8 +214,18 @@ static int clk_set_default_parents(struct udevice *dev)
 			return ret;
 		}
 
-		ret = clk_set_parent(&clk, &parent_clk);
+		/* This is clk provider device trying to reparent itself
+		 * It cannot be done right now but need to wait after the
+		 * device is probed
+		 */
+		if (stage == 0 && clk.dev == dev)
+			continue;
+
+		if (stage > 0 && clk.dev != dev)
+			/* do not setup twice the parent clocks */
+			continue;
 
+		ret = clk_set_parent(&clk, &parent_clk);
 		/*
 		 * Not all drivers may support clock-reparenting (as of now).
 		 * Ignore errors due to this.
@@ -233,7 +243,7 @@ static int clk_set_default_parents(struct udevice *dev)
 	return 0;
 }
 
-static int clk_set_default_rates(struct udevice *dev)
+static int clk_set_default_rates(struct udevice *dev, int stage)
 {
 	struct clk clk;
 	int index;
@@ -268,7 +278,19 @@ static int clk_set_default_rates(struct udevice *dev)
 			continue;
 		}
 
+		/* This is clk provider device trying to program itself
+		 * It cannot be done right now but need to wait after the
+		 * device is probed
+		 */
+		if (stage == 0 && clk.dev == dev)
+			continue;
+
+		if (stage > 0 && clk.dev != dev)
+			/* do not setup twice the parent clocks */
+			continue;
+
 		ret = clk_set_rate(&clk, rates[index]);
+
 		if (ret < 0) {
 			debug("%s: failed to set rate on clock index %d (%ld) for %s\n",
 			      __func__, index, clk.id, dev_read_name(dev));
@@ -281,7 +303,7 @@ fail:
 	return ret;
 }
 
-int clk_set_defaults(struct udevice *dev)
+int clk_set_defaults(struct udevice *dev, int stage)
 {
 	int ret;
 
@@ -294,11 +316,11 @@ int clk_set_defaults(struct udevice *dev)
 
 	debug("%s(%s)\n", __func__, dev_read_name(dev));
 
-	ret = clk_set_default_parents(dev);
+	ret = clk_set_default_parents(dev, stage);
 	if (ret)
 		return ret;
 
-	ret = clk_set_default_rates(dev);
+	ret = clk_set_default_rates(dev, stage);
 	if (ret < 0)
 		return ret;
 
@@ -673,7 +695,21 @@ void devm_clk_put(struct udevice *dev, struct clk *clk)
 	WARN_ON(rc);
 }
 
+int clk_uclass_post_probe(struct udevice *dev)
+{
+	/*
+	 * when a clock provider is probed. Call clk_set_defaults()
+	 * also after the device is probed. This takes care of cases
+	 * where the DT is used to setup default parents and rates
+	 * using assigned-clocks
+	 */
+	clk_set_defaults(dev, 1);
+
+	return 0;
+}
+
 UCLASS_DRIVER(clk) = {
 	.id		= UCLASS_CLK,
 	.name		= "clk",
+	.post_probe	= clk_uclass_post_probe,
 };
diff --git a/drivers/core/device.c b/drivers/core/device.c
index ce66c72e5e..854aa91bbf 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -417,7 +417,7 @@ int device_probe(struct udevice *dev)
 		 * Process 'assigned-{clocks/clock-parents/clock-rates}'
 		 * properties
 		 */
-		ret = clk_set_defaults(dev);
+		ret = clk_set_defaults(dev, 0);
 		if (ret)
 			goto fail;
 	}
diff --git a/include/clk.h b/include/clk.h
index 9be3264113..a5ee53d94a 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -244,10 +244,13 @@ static inline int clk_release_all(struct clk *clk, int count)
  *
  * @dev:        A device to process (the ofnode associated with this device
  *              will be processed).
+ * @stage:	A integer. 0 indicates that this is called before the device
+ *		is probed. 1 indicates that this is called just after the
+ *		device has been probed
  */
-int clk_set_defaults(struct udevice *dev);
+int clk_set_defaults(struct udevice *dev, int stage);
 #else
-static inline int clk_set_defaults(struct udevice *dev)
+static inline int clk_set_defaults(struct udevice *dev, int stage)
 {
 	return 0;
 }
-- 
2.17.1

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

* [U-Boot] [PATCH v2 5/5] test: clk: test clock self assignment
  2019-10-22 12:00 [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment Jean-Jacques Hiblot
                   ` (3 preceding siblings ...)
  2019-10-22 12:00 ` [U-Boot] [PATCH v2 4/5] drivers: clk: Fix using assigned-clocks in the node of the clock it sets up Jean-Jacques Hiblot
@ 2019-10-22 12:00 ` Jean-Jacques Hiblot
  4 siblings, 0 replies; 6+ messages in thread
From: Jean-Jacques Hiblot @ 2019-10-22 12:00 UTC (permalink / raw)
  To: u-boot

Make sure that the clock self-assignment works by having a clock of
clk-sbox be configured automatically when clk-sbox is probed.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>

---

Changes in v2: None

 arch/sandbox/dts/test.dts |  2 ++
 drivers/clk/clk_sandbox.c | 22 ++++++++++++++++++++++
 test/dm/clk.c             |  4 ++--
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 0ee86a74ed..c118125169 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -226,6 +226,8 @@
 	clk_sandbox: clk-sbox {
 		compatible = "sandbox,clk";
 		#clock-cells = <1>;
+		assigned-clocks = <&clk_sandbox 3>;
+		assigned-clock-rates = <321>;
 	};
 
 	clk-test {
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index d152fd7e5b..de6b2f7c82 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -10,6 +10,7 @@
 #include <asm/clk.h>
 
 struct sandbox_clk_priv {
+	bool probed;
 	ulong rate[SANDBOX_CLK_ID_COUNT];
 	bool enabled[SANDBOX_CLK_ID_COUNT];
 	bool requested[SANDBOX_CLK_ID_COUNT];
@@ -19,6 +20,9 @@ static ulong sandbox_clk_get_rate(struct clk *clk)
 {
 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+	if (!priv->probed)
+		return -ENODEV;
+
 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
 		return -EINVAL;
 
@@ -30,6 +34,9 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 	ulong old_rate;
 
+	if (!priv->probed)
+		return -ENODEV;
+
 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
 		return -EINVAL;
 
@@ -46,6 +53,9 @@ static int sandbox_clk_enable(struct clk *clk)
 {
 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+	if (!priv->probed)
+		return -ENODEV;
+
 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
 		return -EINVAL;
 
@@ -58,6 +68,9 @@ static int sandbox_clk_disable(struct clk *clk)
 {
 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+	if (!priv->probed)
+		return -ENODEV;
+
 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
 		return -EINVAL;
 
@@ -97,6 +110,14 @@ static struct clk_ops sandbox_clk_ops = {
 	.free		= sandbox_clk_free,
 };
 
+static int sandbox_clk_probe(struct udevice *dev)
+{
+	struct sandbox_clk_priv *priv = dev_get_priv(dev);
+
+	priv->probed = true;
+	return 0;
+}
+
 static const struct udevice_id sandbox_clk_ids[] = {
 	{ .compatible = "sandbox,clk" },
 	{ }
@@ -107,6 +128,7 @@ U_BOOT_DRIVER(clk_sandbox) = {
 	.id		= UCLASS_CLK,
 	.of_match	= sandbox_clk_ids,
 	.ops		= &sandbox_clk_ops,
+	.probe		= sandbox_clk_probe,
 	.priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
 };
 
diff --git a/test/dm/clk.c b/test/dm/clk.c
index 3ad0ad8ca3..31335a543f 100644
--- a/test/dm/clk.c
+++ b/test/dm/clk.c
@@ -74,8 +74,8 @@ static int dm_test_clk(struct unit_test_state *uts)
 						 SANDBOX_CLK_TEST_ID_SPI));
 	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 						 SANDBOX_CLK_TEST_ID_I2C));
-	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
-						 SANDBOX_CLK_TEST_ID_DEVM1));
+	ut_asserteq(321, sandbox_clk_test_get_rate(dev_test,
+						   SANDBOX_CLK_TEST_ID_DEVM1));
 	ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 						 SANDBOX_CLK_TEST_ID_DEVM2));
 
-- 
2.17.1

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

end of thread, other threads:[~2019-10-22 12:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-22 12:00 [U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment Jean-Jacques Hiblot
2019-10-22 12:00 ` [U-Boot] [PATCH v2 1/5] drivers: clk: Handle gracefully NULL pointers Jean-Jacques Hiblot
2019-10-22 12:00 ` [U-Boot] [PATCH v2 2/5] drivers: clk: Add a managed API to get clocks from the device-tree Jean-Jacques Hiblot
2019-10-22 12:00 ` [U-Boot] [PATCH v2 3/5] test: clk: Update tests to also check the managed API Jean-Jacques Hiblot
2019-10-22 12:00 ` [U-Boot] [PATCH v2 4/5] drivers: clk: Fix using assigned-clocks in the node of the clock it sets up Jean-Jacques Hiblot
2019-10-22 12:00 ` [U-Boot] [PATCH v2 5/5] test: clk: test clock self assignment Jean-Jacques Hiblot

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.