]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00269945: ARM: imx6sl: initialize use count of IPG clock
authorShawn Guo <shawn.guo@freescale.com>
Tue, 13 Aug 2013 01:16:52 +0000 (09:16 +0800)
committerJason Liu <r64343@freescale.com>
Wed, 30 Oct 2013 01:54:30 +0000 (09:54 +0800)
We're running into a system hang during imx6sl boot.  It's been tracked
down to SDMA driver function sdma_init().  System hangs immediately
after the clk_disable() is called in sdma_init().

It turns out that the issue is caused by IPG bus clock which is the
parent of sdma clock is turned off accidentally due to the incorrect
initial use count.  IPG clock is initial on and should be always on
when system operates.  But the use count of the clock is zero initially.
So when the last child clock gets disabled, the use count of IPG clock
reaches zero, and thus clock framework will turn off IPG clock (and
possibly parent clocks along the way), and causes the system hang.

Let's initialize the use count of IPG clock by calling
clk_prepare_enable() on it to match the on state of the clock, so that
the clock will not be turned off accidentally.

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
arch/arm/mach-imx/clk-imx6sl.c

index b96234338e9fc18e3976e05ce1345c32240ce67d..7a8d13a65c992fb911e2932e47730355084fdc9a 100644 (file)
@@ -71,6 +71,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
        struct device_node *np;
        void __iomem *base;
        int irq;
+       int ret;
        int i;
 
        clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
@@ -253,6 +254,15 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
        clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0");
        clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0");
 
+       /*
+        * To prevent the bus clock from being disabled accidently when
+        * clk_disable() gets called on child clock, let's increment the use
+        * count of IPG clock by initially calling clk_prepare_enable() on it.
+        */
+       ret = clk_prepare_enable(clks[IMX6SL_CLK_IPG]);
+       if (ret)
+               pr_warn("%s: failed to enable IPG clock %d\n", __func__, ret);
+
        if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
                clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]);
                clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]);