[PATCH linux dev-4.13] clk: aspeed: Prevent reset and enable if clock is already enabled

Eddie James eajames at linux.vnet.ibm.com
Wed Mar 7 07:24:32 AEDT 2018


Systems are seeing some issues where the LPC clock gets into a bad state
when the ASPEED clock driver resets and enables the clock during
startup. The LPC clock (according to AST2500 spec) is enabled by default,
so resetting and re-enabling is not desired. Add a simple check before the
enable procedure to see if the clock is already enabled.

Signed-off-by: Eddie James <eajames at linux.vnet.ibm.com>
---
 drivers/clk/clk-aspeed.c | 42 ++++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c
index b67ba14..3d12f7a 100644
--- a/drivers/clk/clk-aspeed.c
+++ b/drivers/clk/clk-aspeed.c
@@ -221,27 +221,33 @@ static int aspeed_clk_enable(struct clk_hw *hw)
 	u32 clk = BIT(gate->clock_idx);
 	u32 rst = BIT(gate->reset_idx);
 	u32 enval;
+	u32 reg;
 
 	spin_lock_irqsave(gate->lock, flags);
 
-	if (gate->reset_idx >= 0) {
-		/* Put IP in reset */
-		regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst);
-
-		/* Delay 100us */
-		udelay(100);
-	}
-
-	/* Enable clock */
-	enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
-	regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
-
-	if (gate->reset_idx >= 0) {
-		/* A delay of 10ms is specified by the ASPEED docs */
-		mdelay(10);
-
-		/* Take IP out of reset */
-		regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, 0);
+	/* Only reset/enable/unreset if clock isn't already enabled */
+	regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, &reg);
+	if (reg & clk) {
+		if (gate->reset_idx >= 0) {
+			/* Put IP in reset */
+			regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst,
+					   rst);
+
+			/* Delay 100us */
+			udelay(100);
+		}
+
+		/* Enable clock */
+		enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
+		regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
+
+		if (gate->reset_idx >= 0) {
+			/* A delay of 10ms is specified by the ASPEED docs */
+			mdelay(10);
+
+			/* Take IP out of reset */
+			regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst,						   0);
+		}
 	}
 
 	spin_unlock_irqrestore(gate->lock, flags);
-- 
1.8.3.1



More information about the openbmc mailing list