From dcadbeed2a90b2e1cc98c369b299c3c59e9d712c Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 30 Jul 2026 12:55:14 +0200 Subject: cyclic: get rid of cyclic_get_list() helper As the comment indicates, this was used to silence a warning without having to add casts everywhere gd->cyclic_list was referenced. But nowadays gd is not volatile qualified, so this helper is not needed and only obfuscates the code somewhat, because the head of the list being operated on with the hlist_ or list_ macros is usually not obtained via a function call. Remove the helper and refer to the list head using the idiomatic &gd->cyclic_list. Signed-off-by: Rasmus Villemoes Reviewed-by: Stefan Roese --- cmd/cyclic.c | 5 ++++- common/cyclic.c | 14 ++++---------- include/cyclic.h | 9 --------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/cmd/cyclic.c b/cmd/cyclic.c index 339dd4a7bce..880cd648aae 100644 --- a/cmd/cyclic.c +++ b/cmd/cyclic.c @@ -16,6 +16,9 @@ #include #include #include +#include + +DECLARE_GLOBAL_DATA_PTR; struct cyclic_demo_info { struct cyclic_info cyclic; @@ -64,7 +67,7 @@ static int do_cyclic_list(struct cmd_tbl *cmdtp, int flag, int argc, struct hlist_node *tmp; u64 cnt, freq; - hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) { + hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic_list, list) { cnt = cyclic->run_cnt * 1000000ULL * 100ULL; freq = lldiv(cnt, timer_get_us() - cyclic->start_time_us); printf("function: %s, cpu-time: %lld us, frequency: %lld.%02d times/s\n", diff --git a/common/cyclic.c b/common/cyclic.c index 573e715587d..2bc3c773f27 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -22,17 +22,11 @@ DECLARE_GLOBAL_DATA_PTR; void hw_watchdog_reset(void); -struct hlist_head *cyclic_get_list(void) -{ - /* Silence "discards 'volatile' qualifier" warning. */ - return (struct hlist_head *)&gd->cyclic_list; -} - static bool cyclic_is_registered(const struct cyclic_info *cyclic) { const struct cyclic_info *c; - hlist_for_each_entry(c, cyclic_get_list(), list) { + hlist_for_each_entry(c, &gd->cyclic_list, list) { if (c == cyclic) return true; } @@ -52,7 +46,7 @@ void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, cyclic->name = name; cyclic->delay_us = delay_us; cyclic->start_time_us = get_timer_us(0); - hlist_add_head(&cyclic->list, cyclic_get_list()); + hlist_add_head(&cyclic->list, &gd->cyclic_list); } void cyclic_unregister(struct cyclic_info *cyclic) @@ -75,7 +69,7 @@ static void cyclic_run(void) gd->flags |= GD_FLG_CYCLIC_RUNNING; now = get_timer_us(0); - hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) { + hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic_list, list) { /* * Check if this cyclic function needs to get called, e.g. * do not call the cyclic func too often @@ -129,7 +123,7 @@ int cyclic_unregister_all(void) struct cyclic_info *cyclic; struct hlist_node *tmp; - hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) + hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic_list, list) cyclic_unregister(cyclic); return 0; diff --git a/include/cyclic.h b/include/cyclic.h index df8b725e3d0..ec2c53b6ecf 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -78,15 +78,6 @@ void cyclic_unregister(struct cyclic_info *cyclic); */ int cyclic_unregister_all(void); -/** - * cyclic_get_list() - Get cyclic list pointer - * - * Return the cyclic list pointer - * - * @return: pointer to cyclic_list - */ -struct hlist_head *cyclic_get_list(void); - #else static inline void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, -- cgit v1.3.1 From 2f44bb1417bfbcd2c8722dddec76425f27c8a8f5 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 30 Jul 2026 12:55:15 +0200 Subject: cyclic: return early from cyclic_run() if the list is empty It is possible that schedule(), and hence cyclic_run(), gets called very early, perhaps even from assembly code. With commit 9c1b13b3fd27 ("cyclic: reduce get_timer_us() calls inside hlist_for_each_entry_safe()"), there is now an unconditional get_timer_us(0) done outside the loop, and depending on the platform, the timer infrastructure may not be set up yet. In at least one case, that has caused a divide-by-0 and hence a failure to boot. Platforms should really ensure their timers are ready ASAP, and in the concrete case reported, that was indeed possible to fix that way. However, it doesn't hurt to also insert an early return here, and that could prevent other such hard-to-debug boot failures. Reported-by: Emanuele Ghidoli Link: https://marc.info/?l=u-boot&m=178481834846283&w=2 Fixes: 9c1b13b3fd27 ("cyclic: reduce get_timer_us() calls inside hlist_for_each_entry_safe()") Signed-off-by: Rasmus Villemoes Reviewed-by: Emanuele Ghidoli Reviewed-by: Stefan Roese [sr: fix Fixes: tag SHA length and return statement indentation] --- common/cyclic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/common/cyclic.c b/common/cyclic.c index 2bc3c773f27..1cf5b25d1d8 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -63,6 +63,19 @@ static void cyclic_run(void) struct hlist_node *tmp; u64 now, after, cpu_time; + /* + * Nothing to do if the list is empty. Also, schedule() can be + * called before timer infrastructure is ready, in which case + * calling get_timer_us() before the (empty) loop could cause + * a divide-by-0 or otherwise crash the system. No clients + * should be registered before the timer infrastructure is up, + * so the check for the list being empty should be + * ok. Otherwise, we would need a new GD_FLG_TIMERS_READY + * flag. + */ + if (hlist_empty(&gd->cyclic_list)) + return; + /* Prevent recursion */ if (gd->flags & GD_FLG_CYCLIC_RUNNING) return; -- cgit v1.3.1 From d9ce7ed30571ae01cdcb5fdfd2991e4a7be93c9f Mon Sep 17 00:00:00 2001 From: Ryan Chen Date: Thu, 2 Jul 2026 15:17:10 +0800 Subject: watchdog: ast2600: add AST2700 support The AST2700 reuses the AST2600 watchdog block unchanged. Bind the driver to the aspeed,ast2700-wdt compatible and enable WDT_AST2600 on the AST2700. Signed-off-by: Ryan Chen Reviewed-by: Stefan Roese --- drivers/watchdog/Kconfig | 6 +++--- drivers/watchdog/ast2600_wdt.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b91727e1265..3c56c541505 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -130,11 +130,11 @@ config WDT_ASPEED Second Boot. config WDT_AST2600 - bool "Aspeed AST2600 watchdog timer support" - depends on WDT && ASPEED_AST2600 + bool "Aspeed AST2600/AST2700 watchdog timer support" + depends on WDT && (ASPEED_AST2600 || ASPEED_AST2700) default y help - Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices. + Select this to enable watchdog timer for Aspeed ast2600/ast2700 devices. The watchdog timer is stopped when initialized. It performs reset, either full SoC reset or CPU or just some peripherals, based on the flags. diff --git a/drivers/watchdog/ast2600_wdt.c b/drivers/watchdog/ast2600_wdt.c index 190490f3692..5eb9b4ba96f 100644 --- a/drivers/watchdog/ast2600_wdt.c +++ b/drivers/watchdog/ast2600_wdt.c @@ -87,6 +87,7 @@ static const struct wdt_ops ast2600_wdt_ops = { static const struct udevice_id ast2600_wdt_ids[] = { { .compatible = "aspeed,ast2600-wdt" }, + { .compatible = "aspeed,ast2700-wdt" }, { } }; -- cgit v1.3.1