diff options
author | Benjamin Herrenschmidt <benh@linux.vnet.ibm.com> | 2018-07-03 17:24:47 +1000 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2018-07-06 10:53:20 -0700 |
commit | edc6f7e9b11d4ab54f80890dedf58a914cae61e4 (patch) | |
tree | 865bf30319c76585a09c638830b63b858928053a /drivers/clk/clk-aspeed.c | |
parent | 40dd71c75e395d9b0343f1e646de7ab5312540cc (diff) | |
download | talos-op-linux-edc6f7e9b11d4ab54f80890dedf58a914cae61e4.tar.gz talos-op-linux-edc6f7e9b11d4ab54f80890dedf58a914cae61e4.zip |
clk: aspeed: Treat a gate in reset as disabled
On some systems, we come out of the bootloader with some
gates set with the clock "enabled" but the reset also
asserted.
Since 8a53fc511c5e "clk: aspeed: Prevent reset if clock is enabled"
we check that enabled bit in aspeed_clk_enabled(), and do
nothing if already set.
This breaks when the above scenario occurs, as the clock
is enabled, but the reset still needs to be lifted.
This patch fixes it by also checking the reset bit (if any)
and treating a gate in "reset" as being disabled.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Fixes: 8a53fc511c5e "clk: aspeed: Prevent reset if clock is enabled"
Cc: Eddie James <eajames@linux.vnet.ibm.com>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/clk-aspeed.c')
-rw-r--r-- | drivers/clk/clk-aspeed.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c index 38b366b00c57..4ac926ab7530 100644 --- a/drivers/clk/clk-aspeed.c +++ b/drivers/clk/clk-aspeed.c @@ -212,9 +212,22 @@ static int aspeed_clk_is_enabled(struct clk_hw *hw) { struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw); u32 clk = BIT(gate->clock_idx); + u32 rst = BIT(gate->reset_idx); u32 enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk; u32 reg; + /* + * If the IP is in reset, treat the clock as not enabled, + * this happens with some clocks such as the USB one when + * coming from cold reset. Without this, aspeed_clk_enable() + * will fail to lift the reset. + */ + if (gate->reset_idx >= 0) { + regmap_read(gate->map, ASPEED_RESET_CTRL, ®); + if (reg & rst) + return 0; + } + regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®); return ((reg & clk) == enval) ? 1 : 0; |