Hi Tom, On 6/8/26 3:11 PM, Bastien Curutchet wrote:
The clock controller driven by this driver exists on other OMAP platforms than the AM33xx. Yet, it uses functions provided by arch/arm/mach-omap2/am33xx/clock.c making it unusable by other OMAPs.Replace am33xx-specific do_{enable/disable}_clocks() with new static functions implemented locally. Replace the am33xx-specific clock header with the one shared by all OMAP platforms. Signed-off-by: Bastien Curutchet <[email protected]> --- drivers/clk/ti/clk-ctrl.c | 48 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/drivers/clk/ti/clk-ctrl.c b/drivers/clk/ti/clk-ctrl.c index c5c97dc35c4..08f7410edce 100644 --- a/drivers/clk/ti/clk-ctrl.c +++ b/drivers/clk/ti/clk-ctrl.c @@ -8,7 +8,11 @@ #include <dm.h> #include <dm/device_compat.h> #include <clk-uclass.h> -#include <asm/arch-am33xx/clock.h> +#include <asm/ti-common/omap_clock.h> +#include <asm/io.h> +#include <linux/iopoll.h> + +#define TRANSITION_TIMEOUT_US 10000struct clk_ti_ctrl_offs {fdt_addr_t start; @@ -33,10 +37,37 @@ static int clk_ti_ctrl_check_offs(struct clk *clk, fdt_addr_t offs) return -EFAULT; }+#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) +{ + int val; + + 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); +} + +static int clk_ti_ctrl_enable_clock_module(u32 addr) +{ + int val; + + 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);
This is the culprit. In arch/arm/mach-omap2/am333x/clock.c, the timeout is computed using CPU ticks. Here, readl_relaxed_poll_timeout() relies on a timer. On the beaglebone, this timer dependency creates a sort of circular dependency during initialization (enable clock -> init timer -> enable clock -> init timer) which leads to a division-by-0 during the second timer initialization. This division triggers the hang() outputting the "### ERROR ### Please RESET the board ###".
I'm going to send a new series for the OMAP4 support that uses a CPU-based loop in this driver instead of readl_relaxed_poll_timeout().
Best regards, Bastien

