summaryrefslogtreecommitdiffstats
path: root/bcm283x-clk-audio-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bcm283x-clk-audio-fixes.patch')
-rw-r--r--bcm283x-clk-audio-fixes.patch98
1 files changed, 98 insertions, 0 deletions
diff --git a/bcm283x-clk-audio-fixes.patch b/bcm283x-clk-audio-fixes.patch
new file mode 100644
index 000000000..51c9fa791
--- /dev/null
+++ b/bcm283x-clk-audio-fixes.patch
@@ -0,0 +1,98 @@
+From aa964d59aab2cb04bc011ffd370822ac79f82a0b Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Wed, 7 Mar 2018 15:39:17 +0100
+Subject: [PATCH] clk: bcm2835: De-assert/assert PLL reset signal when
+ appropriate
+
+In order to enable a PLL, not only the PLL has to be powered up and
+locked, but you also have to de-assert the reset signal. The last part
+was missing. Add it so PLLs that were not enabled by the FW/bootloader
+can be enabled from Linux.
+
+Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index a07f6451694a..6c5d4a8e426c 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -602,6 +602,9 @@ static void bcm2835_pll_off(struct clk_hw *hw)
+ const struct bcm2835_pll_data *data = pll->data;
+
+ spin_lock(&cprman->regs_lock);
++ cprman_write(cprman, data->a2w_ctrl_reg,
++ cprman_read(cprman, data->a2w_ctrl_reg) &
++ ~A2W_PLL_CTRL_PRST_DISABLE);
+ cprman_write(cprman, data->cm_ctrl_reg,
+ cprman_read(cprman, data->cm_ctrl_reg) |
+ CM_PLL_ANARST);
+@@ -640,6 +643,10 @@ static int bcm2835_pll_on(struct clk_hw *hw)
+ cpu_relax();
+ }
+
++ cprman_write(cprman, data->a2w_ctrl_reg,
++ cprman_read(cprman, data->a2w_ctrl_reg) |
++ A2W_PLL_CTRL_PRST_DISABLE);
++
+ return 0;
+ }
+
+From 1b6867ee05d84cc6ec23b5ec0b78684187d3190a Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Wed, 7 Mar 2018 15:41:14 +0100
+Subject: [PATCH] clk: bcm2835: Make sure the PLL is gated before changing its
+ rate
+
+All bcm2835 PLLs should be gated before their rate can be changed.
+Setting CLK_SET_RATE_GATE will let the core enforce that, but this is
+not enough to make the code work in all situations. Indeed, the
+CLK_SET_RATE_GATE flag prevents a user from changing the rate while
+the clock is enabled, but this check only guarantees there's no Linux
+users. In our case, the clock might have been enabled by the
+bootloader/FW, and, because we have CLK_IGNORE_UNUSED set, Linux never
+disables the PLL. So we have to make sure the PLL is actually disabled
+before changing the rate.
+
+Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 6c5d4a8e426c..051ce769c109 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -678,6 +678,18 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
+ u32 ana[4];
+ int i;
+
++ /*
++ * Normally, the CLK_SET_RATE_GATE flag prevents a user from changing
++ * the rate while the clock is enabled, but this check only makes sure
++ * there's no Linux users.
++ * In our case, the clock might have been enabled by the bootloader/FW,
++ * and, since CLK_IGNORE_UNUSED flag is set, Linux never disables it.
++ * So we have to make sure the clk is actually disabled before changing
++ * the rate.
++ */
++ if (bcm2835_pll_is_on(hw))
++ bcm2835_pll_off(hw);
++
+ if (rate > data->max_fb_rate) {
+ use_fb_prediv = true;
+ rate /= 2;
+@@ -1318,7 +1330,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
+ init.num_parents = 1;
+ init.name = data->name;
+ init.ops = &bcm2835_pll_clk_ops;
+- init.flags = CLK_IGNORE_UNUSED;
++ init.flags = CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)