[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