diff mbox series

[2/2] clk: clk-axi-clkgen: make sure to enable the AXI bus clock

Message ID 20241023-axi-clkgen-fix-axiclk-v1-2-980a42ba51c3@analog.com (mailing list archive)
State Under Review
Headers show
Series clk: clk-axi-clkgen: make sure to enable the AXI bus clock | expand

Commit Message

Nuno Sa Oct. 23, 2024, 2:56 p.m. UTC
In order to access the registers of the HW, we need to make sure that
the AXI bus clock is enabled. Hence let's increase the number of clocks
by one.

In order to keep backward compatibility, the new axi clock must be the
last phandle in the array. On top of that, it's not an actual parent of
the axi-clkgen.

Fixes: 0e646c52cf0e ("clk: Add axi-clkgen driver")
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index bf4d8ddc93aea1d4509a9ae50fa69fdb3f707a29..6403f0e321b4f8fb74852cae2d13507d8cad82df 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -7,6 +7,7 @@ 
  */
 
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -505,6 +506,16 @@  static const struct clk_ops axi_clkgen_ops = {
 	.get_parent = axi_clkgen_get_parent,
 };
 
+static void axi_clk_put(void *clk)
+{
+	clk_put(clk);
+}
+
+static void axi_clk_disable(void *clk)
+{
+	clk_disable_unprepare(clk);
+}
+
 static int axi_clkgen_probe(struct platform_device *pdev)
 {
 	const struct axi_clkgen_limits *dflt_limits;
@@ -512,6 +523,7 @@  static int axi_clkgen_probe(struct platform_device *pdev)
 	struct clk_init_data init;
 	const char *parent_names[2];
 	const char *clk_name;
+	struct clk *axi_clk;
 	unsigned int i;
 	int ret;
 
@@ -528,9 +540,30 @@  static int axi_clkgen_probe(struct platform_device *pdev)
 		return PTR_ERR(axi_clkgen->base);
 
 	init.num_parents = of_clk_get_parent_count(pdev->dev.of_node);
-	if (init.num_parents < 1 || init.num_parents > 2)
+	if (init.num_parents < 2 || init.num_parents > 3)
 		return -EINVAL;
 
+	/*
+	 * The last clock is the axi bus clock that needs to be enabled so we
+	 * can access the IP core registers.
+	 */
+	axi_clk = of_clk_get(pdev->dev.of_node, init.num_parents - 1);
+	if (IS_ERR(axi_clk))
+		return PTR_ERR(axi_clk);
+
+	ret = devm_add_action_or_reset(&pdev->dev, axi_clk_put, axi_clk);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(axi_clk);
+	if (ret)
+		return ret;
+
+	ret = devm_add_action_or_reset(&pdev->dev, axi_clk_disable, axi_clk);
+	if (ret)
+		return ret;
+
+	init.num_parents -= 1;
 	for (i = 0; i < init.num_parents; i++) {
 		parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i);
 		if (!parent_names[i])