[PATCH] clk: ti: Use CPU ticks to count timeout

Bastien Curutchet bastien.curutchet at bootlin.com
Wed Jul 8 10:38:10 CEST 2026


readl_relaxed_poll_timeout() relies on timers. On the beaglebone black,
the timer used by readl_relaxed_poll_timeout() depends on this clock
driver. So we have a sort of circular dependency [enable_clock ->
timer_init -> enable_clock -> timer_init]. It leads to a
division-per-zero during the second timer_init() and the beaglebone
fails to boot with following message:
| CPU  : AM335X-GP rev 2.1
| Model: TI AM335x BeagleBone Black
| DRAM:  512 MiB
| ### ERROR ### Please RESET the board ###

Replace readl_relaxed_poll_timeout() with a simple loop that uses CPU
ticks to countdown the timeout. This loop and the value of LDELAY are
inspired from what's done in arch/arm/mach-omap2/am33xx/clock.c
Also, arch/arm/mach-omap2/am33xx/clock.c doesn't return an error on
timeout, it only logs it, so let's stick with it.

Fixes: de2e3f00f2fa ("clk: ti: Remove AM33xx dependency")
Signed-off-by: Bastien Curutchet <bastien.curutchet at bootlin.com>
---
 drivers/clk/ti/clk-ctrl.c | 53 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/ti/clk-ctrl.c b/drivers/clk/ti/clk-ctrl.c
index 08f7410edce..e3564277982 100644
--- a/drivers/clk/ti/clk-ctrl.c
+++ b/drivers/clk/ti/clk-ctrl.c
@@ -12,7 +12,7 @@
 #include <asm/io.h>
 #include <linux/iopoll.h>
 
-#define TRANSITION_TIMEOUT_US	10000
+#define LDELAY	1000000
 
 struct clk_ti_ctrl_offs {
 	fdt_addr_t start;
@@ -39,30 +39,59 @@ static int clk_ti_ctrl_check_offs(struct clk *clk, fdt_addr_t offs)
 
 #define IDLEST_DISABLED		(MODULE_CLKCTRL_IDLEST_DISABLED << MODULE_CLKCTRL_IDLEST_SHIFT)
 #define IDLEST_TRANSITION	(MODULE_CLKCTRL_IDLEST_TRANSITIONING << MODULE_CLKCTRL_IDLEST_SHIFT)
-static int clk_ti_ctrl_disable_clock_module(u32 addr)
+static inline void wait_for_clk_disable(u32 addr)
 {
-	int val;
+	u32 bound = LDELAY;
+	int val = 0;
+
+	while ((val & MODULE_CLKCTRL_IDLEST_MASK) != IDLEST_DISABLED) {
+		val = readl(addr);
+
+		if (--bound == 0) {
+			printf("Clock disable failed for 0x%x idlest 0x%x\n",
+			       addr, val);
+			return;
+		}
+	}
+}
 
+static int clk_ti_ctrl_disable_clock_module(u32 addr)
+{
 	clrsetbits_le32(addr, MODULE_CLKCTRL_MODULEMODE_MASK,
 			MODULE_CLKCTRL_MODULEMODE_SW_DISABLE <<
 			MODULE_CLKCTRL_MODULEMODE_SHIFT);
 
-	return readl_relaxed_poll_timeout(addr, val,
-					  (val & MODULE_CLKCTRL_IDLEST_MASK) == IDLEST_DISABLED,
-					  TRANSITION_TIMEOUT_US);
+	wait_for_clk_disable(addr);
+
+	return 0;
 }
 
-static int clk_ti_ctrl_enable_clock_module(u32 addr)
+static inline void wait_for_clk_enable(u32 addr)
 {
-	int val;
+	int val = IDLEST_DISABLED;
+	u32 bound = LDELAY;
 
+	while (((val & MODULE_CLKCTRL_IDLEST_MASK) == IDLEST_DISABLED) ||
+	       ((val & MODULE_CLKCTRL_IDLEST_MASK) == IDLEST_TRANSITION)) {
+		val = readl(addr);
+
+		if (--bound == 0) {
+			printf("Clock enable failed for 0x%x idlest 0x%x\n",
+			       addr, val);
+			return;
+		}
+	}
+}
+
+static int clk_ti_ctrl_enable_clock_module(u32 addr)
+{
 	clrsetbits_le32(addr, MODULE_CLKCTRL_MODULEMODE_MASK,
 			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 			MODULE_CLKCTRL_MODULEMODE_SHIFT);
-	return readl_relaxed_poll_timeout(addr, val,
-					  ((val & MODULE_CLKCTRL_IDLEST_MASK) != IDLEST_DISABLED) &&
-					  ((val & MODULE_CLKCTRL_IDLEST_MASK) != IDLEST_TRANSITION),
-					  TRANSITION_TIMEOUT_US);
+
+	wait_for_clk_enable(addr);
+
+	return 0;
 }
 
 static int clk_ti_ctrl_disable(struct clk *clk)

---
base-commit: ee5d46b45ec0c63f8f9dd1e816e0dac3452ccc3d
change-id: 20260708-fix-beagle-66a3c8bac755

Best regards,
-- 
Bastien Curutchet <bastien.curutchet at bootlin.com>



More information about the U-Boot mailing list