From bd745c24851e58f0cc857e72046d1286ce040ba1 Mon Sep 17 00:00:00 2001 From: Bryan Zhu Date: Fri, 8 Dec 2023 16:31:29 +0800 Subject: [PATCH] drivers: serial: pl011: Remove busy wait in Ambiq UART initiate Ambiq UART requires specific busy wait during initialization for propagating powering control registers, original k_busy_wait() used here generated a dead loop because k_busy_wait() relays on timer, who's driver is initialized after UART(UART init in PRE_KERNEL_1, timer init in PRE_KERNEL_2), replace k_busy_wait() with checking power status register is more suitable here. (cherry picked from commit 3e456e8cfb9598f9ca4ec98ff43f5788fae8b5db) Original-Signed-off-by: Bryan Zhu GitOrigin-RevId: 3e456e8cfb9598f9ca4ec98ff43f5788fae8b5db Change-Id: I5dda348631135cd91afc4eddbb6fad4bce941333 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5109849 Tested-by: ChromeOS Prod (Robot) Reviewed-by: Fabio Baltieri Commit-Queue: Fabio Baltieri Tested-by: Fabio Baltieri --- drivers/serial/uart_pl011_ambiq.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/serial/uart_pl011_ambiq.h b/drivers/serial/uart_pl011_ambiq.h index 2223cbed577..470e0e35a95 100644 --- a/drivers/serial/uart_pl011_ambiq.h +++ b/drivers/serial/uart_pl011_ambiq.h @@ -50,9 +50,9 @@ static inline int clk_enable_ambiq_uart(const struct device *dev, uint32_t clk) return pl011_ambiq_clk_set(dev, clk); } -/* Problem: writes to pwrcfg reg take at most PWCTRL_MAX_WAIT_US time to propagate. - * Solution: busy wait for PWCTRL_MAX_WAIT_US microseconds to ensure that register - * writes have propagated. +/* Problem: writes to power configure register takes some time to take effective. + * Solution: Check device's power status to ensure that register has taken effective. + * Note: busy wait is not allowed to use here due to UART is initiated before timer starts. */ #define QUIRK_AMBIQ_UART_DEFINE(n) \ @@ -60,8 +60,12 @@ static inline int clk_enable_ambiq_uart(const struct device *dev, uint32_t clk) { \ uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ DT_INST_PHA(n, ambiq_pwrcfg, offset); \ + uint32_t pwr_status_addr = addr + 4; \ sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ - k_busy_wait(PWRCTRL_MAX_WAIT_US); \ + while ((sys_read32(pwr_status_addr) & DT_INST_PHA(n, ambiq_pwrcfg, mask)) != \ + DT_INST_PHA(n, ambiq_pwrcfg, mask)) { \ + arch_nop(); \ + }; \ return 0; \ }