blob: 0bd05e9732ea8307f92115ab1a8831c558dc1781 [file] [log] [blame]
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Saravana Kannan <saravanak@google.com>
Date: Fri, 6 Dec 2019 11:17:26 -0800
Subject: ANDROID: GKI: clk: Don't disable unused clocks with sync state
support
Some clocks (that are left on at boot) of a clock provider with sync
state support might not have their "state held" during clock
registration because they remain orphans even after all the clocks in
the clock provider are registered.
These are typically clocks whose current parent is registered by a
different clock provider. When the other clock providers are registered,
these orphan clocks get adopted (no longer orphans) and will have their
"state held".
However if the clock provider of the parent clocks are modules, then
these orphan clocks would get turned off during late_initcall_sync()
because they'd look like unused clocks at that point. This might turn
off clocks that are in use by an active hardware block and cause system
issues.
To avoid this, don't turn off an unused clock if its clock provider has
sync state support and the clock doesn't have the CLK_DONT_HOLD_STATE
flag set.
[CPNOTE: 06/07/21] Lee: Pinged the author for an update
Bug: 144066914
Signed-off-by: Saravana Kannan <saravanak@google.com>
Change-Id: I1f1dbca4994a5b7085930996e1cc5e848266436c
---
drivers/clk/clk.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1217,6 +1217,10 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
hlist_for_each_entry(child, &core->children, child_node)
clk_unprepare_unused_subtree(child);
+ if (dev_has_sync_state(core->dev) &&
+ !(core->flags & CLK_DONT_HOLD_STATE))
+ return;
+
if (core->prepare_count)
return;
@@ -1248,6 +1252,10 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
hlist_for_each_entry(child, &core->children, child_node)
clk_disable_unused_subtree(child);
+ if (dev_has_sync_state(core->dev) &&
+ !(core->flags & CLK_DONT_HOLD_STATE))
+ return;
+
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_prepare_enable(core->parent);