12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- From 3dbdbeedb865d12700dae53b59e259ea083e6186 Mon Sep 17 00:00:00 2001
- From: Eric Anholt <eric@anholt.net>
- Date: Wed, 1 Jun 2016 12:05:35 -0700
- Subject: [PATCH] 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>
- ---
- drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++
- 1 file changed, 25 insertions(+)
- --- 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>
- @@ -1847,6 +1848,25 @@ static const struct bcm2835_clk_desc clk
- .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;
- @@ -1856,6 +1876,7 @@ static int bcm2835_clk_probe(struct plat
- 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),
- @@ -1886,6 +1907,10 @@ static int bcm2835_clk_probe(struct plat
- 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);
- }
|