Commit f1e9203e authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Michael Turquette

clk: samsung: Fix Exynos 5420 pinctrl setup and clock disable failure 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: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Tested-by: default avatarJavier Martinez Canillas <javier.martinez@collabora.co.uk>
Tested-by: default avatarKevin Hilman <khilman@linaro.org>
Signed-off-by: default avatarMichael Turquette <mturquette@linaro.org>
parent 83ccc467
......@@ -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
......@@ -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,
......@@ -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,
......@@ -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;
}
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment