Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29e5eea0 authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Kukjin Kim
Browse files

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: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Reviewed-by: default avatarJavier Martinez Canillas <javier.martinez@collabora.co.uk>
Tested-by: default avatarJavier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: default avatarKukjin Kim <kgene@kernel.org>
parent 0c5f989f
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -19,9 +19,10 @@ Optional Properties:
	domains.
- clock-names: The following clocks can be specified:
	- oscclk: Oscillator clock.
	- pclkN, clkN: Pairs of parent of input clock and input clock to the
		devices in this power domain. Maximum of 4 pairs (N = 0 to 3)
		are supported currently.
	- clkN: Input clocks to the devices in this power domain. These clocks
		will be reparented to oscclk before swithing power domain off.
		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
		the power domain. These clock should be enabled during power
		domain on/off operations.
+9 −7
Original line number Diff line number Diff line
@@ -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++) {
			if (IS_ERR(pd->clk[i]))
				break;
			pd->pclk[i] = clk_get_parent(pd->clk[i]);
			if (clk_set_parent(pd->clk[i], pd->oscclk))
				pr_err("%s: error setting oscclk as parent to clock %d\n",
						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++) {
			if (IS_ERR(pd->clk[i]))
				break;

			if (IS_ERR(pd->clk[i]))
				continue; /* Skip on first power up */
			if (clk_set_parent(pd->clk[i], pd->pclk[i]))
				pr_err("%s: error setting parent to clock%d\n",
						pd->name, i);
@@ -182,13 +186,11 @@ static __init int exynos4_pm_init_power_domain(void)
			pd->clk[i] = clk_get(dev, clk_name);
			if (IS_ERR(pd->clk[i]))
				break;
			snprintf(clk_name, sizeof(clk_name), "pclk%d", i);
			pd->pclk[i] = clk_get(dev, clk_name);
			if (IS_ERR(pd->pclk[i])) {
				clk_put(pd->clk[i]);
				pd->clk[i] = ERR_PTR(-EINVAL);
				break;
			}
			/*
			 * Skip setting parent on first power up.
			 * The parent at this time may not be useful at all.
			 */
			pd->pclk[i] = ERR_PTR(-EINVAL);
		}

		if (IS_ERR(pd->clk[0]))