diff options
author | Justin M. Forbes <jforbes@redhat.com> | 2016-10-24 16:22:14 -0500 |
---|---|---|
committer | Justin M. Forbes <jforbes@redhat.com> | 2016-10-24 16:22:14 -0500 |
commit | d3e1de200c66cd2d2de363d359ea45cb207de835 (patch) | |
tree | e894c57e70b9f8a0f368cd792c5852960b007b38 | |
parent | e4b3d2ead04685e1f0f39096a2322c9e4ee56db9 (diff) | |
download | kernel-d3e1de200c66cd2d2de363d359ea45cb207de835.tar.gz kernel-d3e1de200c66cd2d2de363d359ea45cb207de835.tar.xz kernel-d3e1de200c66cd2d2de363d359ea45cb207de835.zip |
A collection of other clock fixes in -next for the RPi
-rw-r--r-- | bcm283x-vc4-fixes.patch | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/bcm283x-vc4-fixes.patch b/bcm283x-vc4-fixes.patch index 89793b62b..afde6e2f2 100644 --- a/bcm283x-vc4-fixes.patch +++ b/bcm283x-vc4-fixes.patch @@ -634,3 +634,314 @@ index 9ecd6ff..a4b5370 100644 -- 2.9.3 +From c4e634ce412d97f0e61223b2a5b3f8f9600cd4dc Mon Sep 17 00:00:00 2001 +From: Eric Anholt <eric@anholt.net> +Date: Fri, 30 Sep 2016 10:07:27 -0700 +Subject: clk: bcm2835: Clamp the PLL's requested rate to the hardware limits. + +Fixes setting low-resolution video modes on HDMI. Now the PLLH_PIX +divider adjusts itself until the PLLH is within bounds. + +Signed-off-by: Eric Anholt <eric@anholt.net> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/bcm/clk-bcm2835.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index b68bf57..8c7763f 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate, + static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) + { ++ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); ++ const struct bcm2835_pll_data *data = pll->data; + u32 ndiv, fdiv; + ++ rate = clamp(rate, data->min_rate, data->max_rate); ++ + bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv); + + return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1); +@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, + u32 ana[4]; + int i; + +- if (rate < data->min_rate || rate > data->max_rate) { +- dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n", +- clk_hw_get_name(hw), rate, +- data->min_rate, data->max_rate); +- return -EINVAL; +- } +- + if (rate > data->max_fb_rate) { + use_fb_prediv = true; + rate /= 2; +-- +cgit v0.12 + +From e69fdcca836f0b81a2260b69429c8622a80ea891 Mon Sep 17 00:00:00 2001 +From: Eric Anholt <eric@anholt.net> +Date: Wed, 1 Jun 2016 12:05:33 -0700 +Subject: clk: bcm2835: Mark the VPU clock as critical + +The VPU clock is also the clock for our AXI bus, so we really can't +disable it. This might have happened during boot if, for example, +uart1 (aux_uart clock) probed and was then disabled before the other +consumers of the VPU clock had probed. + +Signed-off-by: Eric Anholt <eric@anholt.net> +Acked-by: Martin Sperl <kernel@martin.sperl.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/bcm/clk-bcm2835.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 7a79708..d9db03c 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -443,6 +443,8 @@ struct bcm2835_clock_data { + /* Number of fractional bits in the divider */ + u32 frac_bits; + ++ u32 flags; ++ + bool is_vpu_clock; + bool is_mash_clock; + }; +@@ -1230,7 +1232,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, + init.parent_names = parents; + init.num_parents = data->num_mux_parents; + init.name = data->name; +- init.flags = CLK_IGNORE_UNUSED; ++ init.flags = data->flags | CLK_IGNORE_UNUSED; + + if (data->is_vpu_clock) { + init.ops = &bcm2835_vpu_clock_clk_ops; +@@ -1649,6 +1651,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .div_reg = CM_VPUDIV, + .int_bits = 12, + .frac_bits = 8, ++ .flags = CLK_IS_CRITICAL, + .is_vpu_clock = true), + + /* clocks with per parent mux */ +-- +cgit v0.12 + +From eddcbe8398fc7103fccd22aa6df6917caf0123bf Mon Sep 17 00:00:00 2001 +From: Eric Anholt <eric@anholt.net> +Date: Wed, 1 Jun 2016 12:05:34 -0700 +Subject: clk: bcm2835: Mark GPIO clocks enabled at boot as critical + +These divide off of PLLD_PER and are used for the ethernet and wifi +PHYs source PLLs. Neither of them is currently represented by a phy +device that would grab the clock for us. + +This keeps other drivers from killing the networking PHYs when they +disable their own clocks and trigger PLLD_PER's refcount going to 0. + +Signed-off-by: Eric Anholt <eric@anholt.net> +Acked-by: Martin Sperl <kernel@martin.sperl.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/bcm/clk-bcm2835.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index d9db03c..400615b 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1239,6 +1239,12 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, + } else { + init.ops = &bcm2835_clock_clk_ops; + init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; ++ ++ /* If the clock wasn't actually enabled at boot, it's not ++ * critical. ++ */ ++ if (!(cprman_read(cprman, data->ctl_reg) & CM_ENABLE)) ++ init.flags &= ~CLK_IS_CRITICAL; + } + + clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL); +@@ -1708,13 +1714,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .div_reg = CM_GP1DIV, + .int_bits = 12, + .frac_bits = 12, ++ .flags = CLK_IS_CRITICAL, + .is_mash_clock = true), + [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( + .name = "gp2", + .ctl_reg = CM_GP2CTL, + .div_reg = CM_GP2DIV, + .int_bits = 12, +- .frac_bits = 12), ++ .frac_bits = 12, ++ .flags = CLK_IS_CRITICAL), + + /* HDMI state machine */ + [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK( +-- +cgit v0.12 + +From 9e400c5cc5c105e35216ac59a346f20cdd7613be Mon Sep 17 00:00:00 2001 +From: Eric Anholt <eric@anholt.net> +Date: Wed, 1 Jun 2016 12:05:35 -0700 +Subject: clk: bcm2835: Mark the CM SDRAM clock's parent as critical + +While the SDRAM is being driven by its dedicated PLL most of the time, +there is a little loop running in the firmware that periodically turns +on the CM SDRAM clock (using its pre-initialized parent) and switches +SDRAM to using the CM clock to do PVT recalibration. + +This avoids system hangs if we choose SDRAM's parent for some other +clock, then disable that clock. + +Signed-off-by: Eric Anholt <eric@anholt.net> +Acked-by: Martin Sperl <kernel@martin.sperl.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 400615b..c6420b3 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -36,6 +36,7 @@ + + #include <linux/clk-provider.h> + #include <linux/clkdev.h> ++#include <linux/clk.h> + #include <linux/clk/bcm2835.h> + #include <linux/debugfs.h> + #include <linux/module.h> +@@ -1801,6 +1802,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .ctl_reg = CM_PERIICTL), + }; + ++/* ++ * Permanently take a reference on the parent of the SDRAM clock. ++ * ++ * While the SDRAM is being driven by its dedicated PLL most of the ++ * time, there is a little loop running in the firmware that ++ * periodically switches the SDRAM to using our CM clock to do PVT ++ * recalibration, with the assumption that the previously configured ++ * SDRAM parent is still enabled and running. ++ */ ++static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) ++{ ++ struct clk *parent = clk_get_parent(sdc); ++ ++ if (IS_ERR(parent)) ++ return PTR_ERR(parent); ++ ++ return clk_prepare_enable(parent); ++} ++ + static int bcm2835_clk_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1810,6 +1830,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + const struct bcm2835_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); + size_t i; ++ int ret; + + cprman = devm_kzalloc(dev, + sizeof(*cprman) + asize * sizeof(*clks), +@@ -1840,6 +1861,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + clks[i] = desc->clk_register(cprman, desc->data); + } + ++ ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]); ++ if (ret) ++ return ret; ++ + return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, + &cprman->onecell); + } +-- +cgit v0.12 + +From 67615c588a059b731df9d019edc3c561d8006ec9 Mon Sep 17 00:00:00 2001 +From: Eric Anholt <eric@anholt.net> +Date: Wed, 1 Jun 2016 12:05:36 -0700 +Subject: clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent + +If the firmware had set up a clock to source from PLLC, go along with +it. But if we're looking for a new parent, we don't want to switch it +to PLLC because the firmware will force PLLC (and thus the AXI bus +clock) to different frequencies during over-temp/under-voltage, +without notification to Linux. + +On my system, this moves the Linux-enabled HDMI state machine and DSI1 +escape clock over to plld_per from pllc_per. EMMC still ends up on +pllc_per, because the firmware had set it up to use that. + +Signed-off-by: Eric Anholt <eric@anholt.net> +Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") +Acked-by: Martin Sperl <kernel@martin.sperl.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/bcm/clk-bcm2835.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index c6420b3..e8a9646a 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1009,16 +1009,28 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, + return 0; + } + ++static bool ++bcm2835_clk_is_pllc(struct clk_hw *hw) ++{ ++ if (!hw) ++ return false; ++ ++ return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0; ++} ++ + static int bcm2835_clock_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) + { + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct clk_hw *parent, *best_parent = NULL; ++ bool current_parent_is_pllc; + unsigned long rate, best_rate = 0; + unsigned long prate, best_prate = 0; + size_t i; + u32 div; + ++ current_parent_is_pllc = bcm2835_clk_is_pllc(clk_hw_get_parent(hw)); ++ + /* + * Select parent clock that results in the closest but lower rate + */ +@@ -1026,6 +1038,17 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + parent = clk_hw_get_parent_by_index(hw, i); + if (!parent) + continue; ++ ++ /* ++ * Don't choose a PLLC-derived clock as our parent ++ * unless it had been manually set that way. PLLC's ++ * frequency gets adjusted by the firmware due to ++ * over-temp or under-voltage conditions, without ++ * prior notification to our clock consumer. ++ */ ++ if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc) ++ continue; ++ + prate = clk_hw_get_rate(parent); + div = bcm2835_clock_choose_div(hw, req->rate, prate, true); + rate = bcm2835_clock_rate_from_divisor(clock, prate, div); +-- +cgit v0.12 + |