aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2016-06-01 15:05:35 -0400
committerStephen Boyd <sboyd@codeaurora.org>2016-09-07 11:57:35 -0400
commit9e400c5cc5c105e35216ac59a346f20cdd7613be (patch)
treec47c237bebbf70d1cf67fab3f689e43da1bb5513
parenteddcbe8398fc7103fccd22aa6df6917caf0123bf (diff)
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>
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 400615baea97..c6420b36cbcb 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -36,6 +36,7 @@
36 36
37#include <linux/clk-provider.h> 37#include <linux/clk-provider.h>
38#include <linux/clkdev.h> 38#include <linux/clkdev.h>
39#include <linux/clk.h>
39#include <linux/clk/bcm2835.h> 40#include <linux/clk/bcm2835.h>
40#include <linux/debugfs.h> 41#include <linux/debugfs.h>
41#include <linux/module.h> 42#include <linux/module.h>
@@ -1801,6 +1802,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
1801 .ctl_reg = CM_PERIICTL), 1802 .ctl_reg = CM_PERIICTL),
1802}; 1803};
1803 1804
1805/*
1806 * Permanently take a reference on the parent of the SDRAM clock.
1807 *
1808 * While the SDRAM is being driven by its dedicated PLL most of the
1809 * time, there is a little loop running in the firmware that
1810 * periodically switches the SDRAM to using our CM clock to do PVT
1811 * recalibration, with the assumption that the previously configured
1812 * SDRAM parent is still enabled and running.
1813 */
1814static int bcm2835_mark_sdc_parent_critical(struct clk *sdc)
1815{
1816 struct clk *parent = clk_get_parent(sdc);
1817
1818 if (IS_ERR(parent))
1819 return PTR_ERR(parent);
1820
1821 return clk_prepare_enable(parent);
1822}
1823
1804static int bcm2835_clk_probe(struct platform_device *pdev) 1824static int bcm2835_clk_probe(struct platform_device *pdev)
1805{ 1825{
1806 struct device *dev = &pdev->dev; 1826 struct device *dev = &pdev->dev;
@@ -1810,6 +1830,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
1810 const struct bcm2835_clk_desc *desc; 1830 const struct bcm2835_clk_desc *desc;
1811 const size_t asize = ARRAY_SIZE(clk_desc_array); 1831 const size_t asize = ARRAY_SIZE(clk_desc_array);
1812 size_t i; 1832 size_t i;
1833 int ret;
1813 1834
1814 cprman = devm_kzalloc(dev, 1835 cprman = devm_kzalloc(dev,
1815 sizeof(*cprman) + asize * sizeof(*clks), 1836 sizeof(*cprman) + asize * sizeof(*clks),
@@ -1840,6 +1861,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
1840 clks[i] = desc->clk_register(cprman, desc->data); 1861 clks[i] = desc->clk_register(cprman, desc->data);
1841 } 1862 }
1842 1863
1864 ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]);
1865 if (ret)
1866 return ret;
1867
1843 return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, 1868 return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
1844 &cprman->onecell); 1869 &cprman->onecell);
1845} 1870}