Skip to content

Commit

Permalink
clk: samsung: Fix Exynos 5420 pinctrl setup and clock disable failure…
Browse files Browse the repository at this point in the history
… due to domain being gated

Audio subsystem clocks are located in separate block. On Exynos 5420 if
clock for this block (from main clock domain) 'mau_epll' is gated then
any read or write to audss registers will block.

This kind of boot hang was observed on Arndale Octa and Peach Pi/Pit
after introducing runtime PM to pl330 DMA driver. After that commit the
'mau_epll' was gated, because the "amba" clock was disabled and there
were no more users of mau_epll.

The system hang on one of steps:
1. Disabling unused clocks from audss block.
2. During audss GPIO setup (just before probing i2s0 because
   samsung_pinmux_setup() tried to access memory from audss block which was
   gated.

Add a workaround for this by enabling the 'mau_epll' clock in probe.

Signed-off-by: Krzysztof Kozlowski <[email protected]>
Acked-by: Sylwester Nawrocki <[email protected]>
Tested-by: Javier Martinez Canillas <[email protected]>
Tested-by: Kevin Hilman <[email protected]>
Signed-off-by: Michael Turquette <[email protected]>
  • Loading branch information
krzk authored and Michael Turquette committed Dec 17, 2014
1 parent 83ccc46 commit f1e9203
Showing 1 changed file with 28 additions and 1 deletion.
29 changes: 28 additions & 1 deletion drivers/clk/samsung/clk-exynos-audss.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ static DEFINE_SPINLOCK(lock);
static struct clk **clk_table;
static void __iomem *reg_base;
static struct clk_onecell_data clk_data;
/*
* On Exynos5420 this will be a clock which has to be enabled before any
* access to audss registers. Typically a child of EPLL.
*
* On other platforms this will be -ENODEV.
*/
static struct clk *epll;

#define ASS_CLK_SRC 0x0
#define ASS_CLK_DIV 0x4
Expand Down Expand Up @@ -98,6 +105,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to map audss registers\n");
return PTR_ERR(reg_base);
}
/* EPLL don't have to be enabled for boards other than Exynos5420 */
epll = ERR_PTR(-ENODEV);

clk_table = devm_kzalloc(&pdev->dev,
sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
Expand All @@ -115,8 +124,20 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
pll_in = devm_clk_get(&pdev->dev, "pll_in");
if (!IS_ERR(pll_ref))
mout_audss_p[0] = __clk_get_name(pll_ref);
if (!IS_ERR(pll_in))
if (!IS_ERR(pll_in)) {
mout_audss_p[1] = __clk_get_name(pll_in);

if (variant == TYPE_EXYNOS5420) {
epll = pll_in;

ret = clk_prepare_enable(epll);
if (ret) {
dev_err(&pdev->dev,
"failed to prepare the epll clock\n");
return ret;
}
}
}
clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
mout_audss_p, ARRAY_SIZE(mout_audss_p),
CLK_SET_RATE_NO_REPARENT,
Expand Down Expand Up @@ -203,6 +224,9 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
clk_unregister(clk_table[i]);
}

if (!IS_ERR(epll))
clk_disable_unprepare(epll);

return ret;
}

Expand All @@ -221,6 +245,9 @@ static int exynos_audss_clk_remove(struct platform_device *pdev)
clk_unregister(clk_table[i]);
}

if (!IS_ERR(epll))
clk_disable_unprepare(epll);

return 0;
}

Expand Down

0 comments on commit f1e9203

Please sign in to comment.