Skip to content

Commit f1e9203

Browse files
krzkMichael Turquette
authored andcommitted
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: Krzysztof Kozlowski <k.kozlowski@samsung.com> Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Tested-by: Kevin Hilman <khilman@linaro.org> Signed-off-by: Michael Turquette <mturquette@linaro.org>
1 parent 83ccc46 commit f1e9203

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

drivers/clk/samsung/clk-exynos-audss.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ static DEFINE_SPINLOCK(lock);
2929
static struct clk **clk_table;
3030
static void __iomem *reg_base;
3131
static struct clk_onecell_data clk_data;
32+
/*
33+
* On Exynos5420 this will be a clock which has to be enabled before any
34+
* access to audss registers. Typically a child of EPLL.
35+
*
36+
* On other platforms this will be -ENODEV.
37+
*/
38+
static struct clk *epll;
3239

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

102111
clk_table = devm_kzalloc(&pdev->dev,
103112
sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
@@ -115,8 +124,20 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
115124
pll_in = devm_clk_get(&pdev->dev, "pll_in");
116125
if (!IS_ERR(pll_ref))
117126
mout_audss_p[0] = __clk_get_name(pll_ref);
118-
if (!IS_ERR(pll_in))
127+
if (!IS_ERR(pll_in)) {
119128
mout_audss_p[1] = __clk_get_name(pll_in);
129+
130+
if (variant == TYPE_EXYNOS5420) {
131+
epll = pll_in;
132+
133+
ret = clk_prepare_enable(epll);
134+
if (ret) {
135+
dev_err(&pdev->dev,
136+
"failed to prepare the epll clock\n");
137+
return ret;
138+
}
139+
}
140+
}
120141
clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
121142
mout_audss_p, ARRAY_SIZE(mout_audss_p),
122143
CLK_SET_RATE_NO_REPARENT,
@@ -203,6 +224,9 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
203224
clk_unregister(clk_table[i]);
204225
}
205226

227+
if (!IS_ERR(epll))
228+
clk_disable_unprepare(epll);
229+
206230
return ret;
207231
}
208232

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

248+
if (!IS_ERR(epll))
249+
clk_disable_unprepare(epll);
250+
224251
return 0;
225252
}
226253

0 commit comments

Comments
 (0)