libpayload: Use Kconfig instead of weak symbol for arch_ndelay()

Weak symbols don't work as expected when you want to override them from
within the same static library. This patch changes the arch_ndelay()
function so that instead of having a weak generic implementation, the
choice between generic implementation and an arch-specific override is
explicitly made by Kconfig. Let's also drop the "arch_" prefix and just
call this ndelay().

Change-Id: Ie4fe2734e0683fa3537e2ebcabfe067e7499463a
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/87776
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Subrata Banik <subratabanik@google.com>
Reviewed-by: Jakub "Kuba" Czapiga <czapiga@google.com>
This commit is contained in:
Julius Werner 2025-05-21 13:36:05 -07:00
commit 4ccb4a78c4
8 changed files with 21 additions and 17 deletions

View file

@ -512,6 +512,13 @@ config ARCH_HAS_MEM_FUNCTIONS
Architectures must select this when they want to override memset,
memcpy and memmove with optimized assembly implementations.
config ARCH_HAS_NDELAY
default n
bool
help
Architectures must select this when they want to override the ndelay()
function with a custom implementation.
source "arch/arm/Kconfig"
source "arch/arm64/Kconfig"
source "arch/x86/Kconfig"

View file

@ -32,6 +32,7 @@ config ARCH_X86
select LITTLE_ENDIAN
select IO_ADDRESS_SPACE
select ARCH_HAS_MEM_FUNCTIONS if GPL
select ARCH_HAS_NDELAY
if ARCH_X86

View file

@ -249,7 +249,7 @@ static void apic_init_timer(void)
apic_write32(APIC_TIMER_INIT_COUNT, UINT32_MAX);
/* This is safe because apic_initialized() returns false so
* arch_ndelay() falls back to a busy loop. */
* ndelay() falls back to a busy loop. */
mdelay(1);
ticks_per_ms =

View file

@ -38,7 +38,7 @@
/* Let's assume APIC interrupts take at least 100us */
#define APIC_INTERRUPT_LATENCY_NS (100 * NSECS_PER_USEC)
void arch_ndelay(uint64_t ns)
void ndelay(uint64_t ns)
{
uint64_t delta = ns * timer_hz() / NSECS_PER_SEC;
uint64_t pause_delta = 0;

View file

@ -14,17 +14,12 @@
unsigned int get_cpu_speed(void);
void arch_ndelay(uint64_t n);
/**
* Delay for a specified number of nanoseconds.
*
* @param ns Number of nanoseconds to delay for.
*/
static inline void ndelay(unsigned int ns)
{
arch_ndelay((uint64_t)ns);
}
void ndelay(uint64_t n);
/**
* Delay for a specified number of microseconds.
@ -33,7 +28,7 @@ static inline void ndelay(unsigned int ns)
*/
static inline void udelay(unsigned int us)
{
arch_ndelay((uint64_t)us * NSECS_PER_USEC);
ndelay((uint64_t)us * NSECS_PER_USEC);
}
/**
@ -43,7 +38,7 @@ static inline void udelay(unsigned int us)
*/
static inline void mdelay(unsigned int ms)
{
arch_ndelay((uint64_t)ms * NSECS_PER_MSEC);
ndelay((uint64_t)ms * NSECS_PER_MSEC);
}
/**
@ -53,7 +48,7 @@ static inline void mdelay(unsigned int ms)
*/
static inline void delay(unsigned int s)
{
arch_ndelay((uint64_t)s * NSECS_PER_SEC);
ndelay((uint64_t)s * NSECS_PER_SEC);
}
#endif /* LIBPAYLOAD_DELAY_H */

View file

@ -161,13 +161,14 @@ int gettimeofday(struct timeval *tv, void *tz)
return 0;
}
__attribute__((weak))
void arch_ndelay(uint64_t ns)
#if !CONFIG(LP_ARCH_HAS_NDELAY)
void ndelay(uint64_t ns)
{
uint64_t delta = ns * timer_hz() / NSECS_PER_SEC;
uint64_t start = timer_raw_value();
while (timer_raw_value() - start < delta) ;
}
#endif
u64 timer_us(u64 base)
{

View file

@ -8,4 +8,4 @@ graphics-test-srcs += libc/fpmath.c
speaker-test-srcs += tests/drivers/speaker-test.c
speaker-test-mocks += inb
speaker-test-mocks += outb
speaker-test-mocks += arch_ndelay
speaker-test-mocks += ndelay

View file

@ -104,7 +104,7 @@ static void test_speaker_disable(void **state)
speaker_disable();
}
void arch_ndelay(uint64_t ns)
void ndelay(uint64_t ns)
{
check_expected(ns);
}
@ -112,9 +112,9 @@ void arch_ndelay(uint64_t ns)
static void setup_speaker_tone_calls(u16 freq, unsigned int duration)
{
setup_speaker_enable_calls(freq, ~freq & 0xff);
expect_value(arch_ndelay, ns, (uint64_t)duration * NSECS_PER_MSEC);
expect_value(ndelay, ns, (uint64_t)duration * NSECS_PER_MSEC);
setup_speaker_disable_calls(0xff);
expect_any(arch_ndelay, ns);
expect_any(ndelay, ns);
}
static void test_speaker_tone(void **state)