From 97cdedec80cbb8c0dd593441bfacd55745803d0e Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Thu, 29 May 2025 17:43:37 +0800 Subject: [PATCH] drivers/timer: it51xxx: Compensate time calculation to reduce drift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EC timer runs at 9.2 MHz, which leads to a non-integer number of ticks per microsecond. This causes slight overestimation when delays are computed using whole ticks (e.g., using 10 ticks for 1 µs). To address this, the busy wait calculation is adjusted with a compensation factor to minimize cumulative timing error over time. Signed-off-by: Tim Lin --- drivers/timer/ite_it51xxx_timer.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/timer/ite_it51xxx_timer.c b/drivers/timer/ite_it51xxx_timer.c index aa99e2735a9..6d934bad425 100644 --- a/drivers/timer/ite_it51xxx_timer.c +++ b/drivers/timer/ite_it51xxx_timer.c @@ -126,11 +126,16 @@ static uint32_t read_timer_obser(enum ext_timer_idx timer_idx) uint32_t obser; __unused uint8_t etnpsr; + /* Critical section */ + unsigned int key = irq_lock(); + /* Workaround for observation register latch issue */ obser = sys_read32(timer_base + TIMER_ETNCNTOLR(timer_idx)); etnpsr = sys_read8(timer_base + TIMER_ETNPSR(timer_idx)); obser = sys_read32(timer_base + TIMER_ETNCNTOLR(timer_idx)); + irq_unlock(key); + return obser; } @@ -334,16 +339,24 @@ static int timer_init(enum ext_timer_idx ext_timer, enum ext_clk_src_sel clock_s void arch_busy_wait(uint32_t usec_to_wait) { uint32_t start = read_timer_obser(BUSY_WAIT_H_TIMER); + uint32_t compensated_us; if (!usec_to_wait) { return; } - /* Decrease 1us here to calibrate our access registers latency */ - usec_to_wait--; - + /* + * The EC runs at 9.2MHz, meaning each tick is approximately 108.6ns. + * The number of ticks per microsecond is calculated as: + * COUNT_1US = EC_CLOCK / USEC_PER_SEC = 9200000 / 1000000 = 9.2 + * Since the timer counts down from a preset value to 0, using a preload value of + * 9 actually results in 10 ticks per cycle. + * This overestimates 1us and introduces a small cumulative timing error over time. + * To compensate for this, we scale the requested delay using (1000 / 1086). + */ + compensated_us = usec_to_wait * 1000 / 1086; for (;;) { - if ((read_timer_obser(BUSY_WAIT_H_TIMER) - start) >= usec_to_wait) { + if ((read_timer_obser(BUSY_WAIT_H_TIMER) - start) >= compensated_us) { break; } }