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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 drivers/clk/clk-axi-clkgen.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

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])

-- 
2.47.0





[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux