ARM: EXYNOS: Get current parent clock for power domain on/off
Using a fixed (by DTS) parent for clocks when turning on the power domain may introduce issues in other drivers. For example when such driver changes the parent during runtime and expects that he is the only place of such change. Do not rely on DTS providing the fixed parent for such clocks. Instead before switching domain off, grab a current parent of a clock with clk_get_parent(). Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Reviewed-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Signed-off-by: Kukjin Kim <kgene@kernel.org>
This commit is contained in:
Родитель
0c5f989f1f
Коммит
29e5eea06b
|
@ -19,9 +19,10 @@ Optional Properties:
|
||||||
domains.
|
domains.
|
||||||
- clock-names: The following clocks can be specified:
|
- clock-names: The following clocks can be specified:
|
||||||
- oscclk: Oscillator clock.
|
- oscclk: Oscillator clock.
|
||||||
- pclkN, clkN: Pairs of parent of input clock and input clock to the
|
- clkN: Input clocks to the devices in this power domain. These clocks
|
||||||
devices in this power domain. Maximum of 4 pairs (N = 0 to 3)
|
will be reparented to oscclk before swithing power domain off.
|
||||||
are supported currently.
|
Their original parent will be brought back after turning on
|
||||||
|
the domain. Maximum of 4 clocks (N = 0 to 3) are supported.
|
||||||
- asbN: Clocks required by asynchronous bridges (ASB) present in
|
- asbN: Clocks required by asynchronous bridges (ASB) present in
|
||||||
the power domain. These clock should be enabled during power
|
the power domain. These clock should be enabled during power
|
||||||
domain on/off operations.
|
domain on/off operations.
|
||||||
|
|
|
@ -62,6 +62,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
||||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||||
if (IS_ERR(pd->clk[i]))
|
if (IS_ERR(pd->clk[i]))
|
||||||
break;
|
break;
|
||||||
|
pd->pclk[i] = clk_get_parent(pd->clk[i]);
|
||||||
if (clk_set_parent(pd->clk[i], pd->oscclk))
|
if (clk_set_parent(pd->clk[i], pd->oscclk))
|
||||||
pr_err("%s: error setting oscclk as parent to clock %d\n",
|
pr_err("%s: error setting oscclk as parent to clock %d\n",
|
||||||
pd->name, i);
|
pd->name, i);
|
||||||
|
@ -90,6 +91,9 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
||||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||||
if (IS_ERR(pd->clk[i]))
|
if (IS_ERR(pd->clk[i]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (IS_ERR(pd->clk[i]))
|
||||||
|
continue; /* Skip on first power up */
|
||||||
if (clk_set_parent(pd->clk[i], pd->pclk[i]))
|
if (clk_set_parent(pd->clk[i], pd->pclk[i]))
|
||||||
pr_err("%s: error setting parent to clock%d\n",
|
pr_err("%s: error setting parent to clock%d\n",
|
||||||
pd->name, i);
|
pd->name, i);
|
||||||
|
@ -182,13 +186,11 @@ static __init int exynos4_pm_init_power_domain(void)
|
||||||
pd->clk[i] = clk_get(dev, clk_name);
|
pd->clk[i] = clk_get(dev, clk_name);
|
||||||
if (IS_ERR(pd->clk[i]))
|
if (IS_ERR(pd->clk[i]))
|
||||||
break;
|
break;
|
||||||
snprintf(clk_name, sizeof(clk_name), "pclk%d", i);
|
/*
|
||||||
pd->pclk[i] = clk_get(dev, clk_name);
|
* Skip setting parent on first power up.
|
||||||
if (IS_ERR(pd->pclk[i])) {
|
* The parent at this time may not be useful at all.
|
||||||
clk_put(pd->clk[i]);
|
*/
|
||||||
pd->clk[i] = ERR_PTR(-EINVAL);
|
pd->pclk[i] = ERR_PTR(-EINVAL);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ERR(pd->clk[0]))
|
if (IS_ERR(pd->clk[0]))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче