494688d
From 1b6867ee05d84cc6ec23b5ec0b78684187d3190a Mon Sep 17 00:00:00 2001
494688d
From: Boris Brezillon <boris.brezillon@bootlin.com>
494688d
Date: Wed, 7 Mar 2018 15:41:14 +0100
494688d
Subject: [PATCH] clk: bcm2835: Make sure the PLL is gated before changing its
494688d
 rate
494688d
494688d
All bcm2835 PLLs should be gated before their rate can be changed.
494688d
Setting CLK_SET_RATE_GATE will let the core enforce that, but this is
494688d
not enough to make the code work in all situations. Indeed, the
494688d
CLK_SET_RATE_GATE flag prevents a user from changing the rate while
494688d
the clock is enabled, but this check only guarantees there's no Linux
494688d
users. In our case, the clock might have been enabled by the
494688d
bootloader/FW, and, because we have CLK_IGNORE_UNUSED set, Linux never
494688d
disables the PLL. So we have to make sure the PLL is actually disabled
494688d
before changing the rate.
494688d
494688d
Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
494688d
Cc: <stable@vger.kernel.org>
494688d
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
494688d
---
494688d
 drivers/clk/bcm/clk-bcm2835.c | 14 +++++++++++++-
494688d
 1 file changed, 13 insertions(+), 1 deletion(-)
494688d
494688d
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
494688d
index 6c5d4a8e426c..051ce769c109 100644
494688d
--- a/drivers/clk/bcm/clk-bcm2835.c
494688d
+++ b/drivers/clk/bcm/clk-bcm2835.c
494688d
@@ -678,6 +678,18 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
494688d
 	u32 ana[4];
494688d
 	int i;
494688d
 
494688d
+	/*
494688d
+	 * Normally, the CLK_SET_RATE_GATE flag prevents a user from changing
494688d
+	 * the rate while the clock is enabled, but this check only makes sure
494688d
+	 * there's no Linux users.
494688d
+	 * In our case, the clock might have been enabled by the bootloader/FW,
494688d
+	 * and, since CLK_IGNORE_UNUSED flag is set, Linux never disables it.
494688d
+	 * So we have to make sure the clk is actually disabled before changing
494688d
+	 * the rate.
494688d
+	 */
494688d
+	if (bcm2835_pll_is_on(hw))
494688d
+		bcm2835_pll_off(hw);
494688d
+
494688d
 	if (rate > data->max_fb_rate) {
494688d
 		use_fb_prediv = true;
494688d
 		rate /= 2;
494688d
@@ -1318,7 +1330,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
494688d
 	init.num_parents = 1;
494688d
 	init.name = data->name;
494688d
 	init.ops = &bcm2835_pll_clk_ops;
494688d
-	init.flags = CLK_IGNORE_UNUSED;
494688d
+	init.flags = CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE;
494688d
 
494688d
 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
494688d
 	if (!pll)