diff --git a/drivers/counter/counter_esp32_rtc.c b/drivers/counter/counter_esp32_rtc.c index bf751f6441439..9b57624b1893c 100644 --- a/drivers/counter/counter_esp32_rtc.c +++ b/drivers/counter/counter_esp32_rtc.c @@ -6,10 +6,16 @@ #define DT_DRV_COMPAT espressif_esp32_rtc_timer +#include +#include + +#if SOC_LP_TIMER_SUPPORTED +#include "hal/lp_timer_ll.h" +#else #include "soc/rtc_cntl_reg.h" #include "soc/rtc.h" -#include #include +#endif #include #include @@ -26,6 +32,9 @@ static void counter_esp32_isr(void *arg); struct counter_esp32_config { struct counter_config_info counter_info; +#if SOC_LP_TIMER_SUPPORTED + lp_timer_dev_t *dev; +#endif int irq_source; int irq_priority; int irq_flags; @@ -84,9 +93,37 @@ static int counter_esp32_stop(const struct device *dev) static int counter_esp32_get_value(const struct device *dev, uint32_t *ticks) { +#if SOC_LP_TIMER_SUPPORTED + const struct counter_esp32_config *cfg = dev->config; + + lp_timer_ll_counter_snapshot(cfg->dev); + + *ticks = lp_timer_ll_get_counter_value_low(cfg->dev, 0); +#else ARG_UNUSED(dev); *ticks = (uint32_t) rtc_cntl_ll_get_rtc_time(); +#endif + + return 0; +} + +static int counter_esp32_get_value_64(const struct device *dev, uint64_t *ticks) +{ +#if SOC_LP_TIMER_SUPPORTED + const struct counter_esp32_config *cfg = dev->config; + + lp_timer_ll_counter_snapshot(cfg->dev); + + uint32_t lo = lp_timer_ll_get_counter_value_low(cfg->dev, 0); + uint32_t hi = lp_timer_ll_get_counter_value_high(cfg->dev, 0); + + *ticks = ((uint64_t)hi << 32 | lo); +#else + ARG_UNUSED(dev); + + *ticks = rtc_cntl_ll_get_rtc_time(); +#endif return 0; } @@ -95,9 +132,13 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id, const struct counter_alarm_cfg *alarm_cfg) { ARG_UNUSED(chan_id); +#if SOC_LP_TIMER_SUPPORTED + const struct counter_esp32_config *cfg = dev->config; + lp_timer_dev_t *lp_timer = cfg->dev; +#endif struct counter_esp32_data *data = dev->data; - uint32_t now; - uint32_t ticks = 0; + uint64_t now; + uint64_t ticks = 0; #if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32C2) || \ defined(CONFIG_SOC_SERIES_ESP32C3) @@ -109,35 +150,63 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id, data->alarm_cfg.callback = alarm_cfg->callback; data->alarm_cfg.user_data = alarm_cfg->user_data; - counter_esp32_get_value(dev, &now); + counter_esp32_get_value_64(dev, &now); - ticks = (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) ? alarm_cfg->ticks - : now + alarm_cfg->ticks; + if (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) { + ticks = (now & ~0xFFFFFFFFULL) | alarm_cfg->ticks; + if (ticks < now) { + ticks += (1ULL << 32); + } + } else { + ticks = now + alarm_cfg->ticks; + } + + data->ticks = (uint32_t)ticks; +#if SOC_LP_TIMER_SUPPORTED + lp_timer_ll_clear_alarm_intr_status(cfg->dev); + lp_timer_ll_set_alarm_target(cfg->dev, 0, ticks); + lp_timer_ll_set_target_enable(cfg->dev, 0, true); + lp_timer->int_en.alarm = 1; +#else rtc_cntl_ll_set_wakeup_timer(ticks); /* RTC main timer set alarm value */ - CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xffffffff); + CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xFFFFFFFF); /* RTC main timer set alarm enable */ SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN); /* RTC main timer interrupt enable */ SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA); +#endif return 0; } static int counter_esp32_cancel_alarm(const struct device *dev, uint8_t chan_id) { - ARG_UNUSED(dev); ARG_UNUSED(chan_id); + struct counter_esp32_data *data = dev->data; +#if SOC_LP_TIMER_SUPPORTED + const struct counter_esp32_config *cfg = dev->config; + lp_timer_dev_t *lp_timer = cfg->dev; + + lp_timer_ll_set_target_enable(cfg->dev, 0, false); + lp_timer->int_en.alarm = 0; + lp_timer_ll_clear_alarm_intr_status(cfg->dev); +#else /* RTC main timer set alarm disable */ CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN); - /* RTC main timer interrupt disable */ + /* RTC main timer interrupt disable, and clear interrupt flag */ + REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR); +#endif + + data->alarm_cfg.callback = NULL; + data->alarm_cfg.user_data = NULL; return 0; } @@ -156,11 +225,18 @@ static int counter_esp32_set_top_value(const struct device *dev, static uint32_t counter_esp32_get_pending_int(const struct device *dev) { +#if SOC_LP_TIMER_SUPPORTED + const struct counter_esp32_config *cfg = dev->config; + lp_timer_dev_t *lp_timer = cfg->dev; + + return lp_timer->int_st.alarm; +#else ARG_UNUSED(dev); uint32_t rc = READ_PERI_REG(RTC_CNTL_INT_ST_REG) & RTC_CNTL_MAIN_TIMER_INT_ST; return (rc >> RTC_CNTL_MAIN_TIMER_INT_ST_S); +#endif } /* @@ -190,6 +266,9 @@ static const struct counter_esp32_config counter_config = { .flags = COUNTER_CONFIG_INFO_COUNT_UP, .channels = 1 }, +#if SOC_LP_TIMER_SUPPORTED + .dev = (lp_timer_dev_t *)DT_INST_REG_ADDR(0), +#endif .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)), .irq_source = DT_INST_IRQ_BY_IDX(0, 0, irq), .irq_priority = DT_INST_IRQ_BY_IDX(0, 0, priority), @@ -200,6 +279,7 @@ static DEVICE_API(counter, rtc_timer_esp32_api) = { .start = counter_esp32_start, .stop = counter_esp32_stop, .get_value = counter_esp32_get_value, + .get_value_64 = counter_esp32_get_value_64, .set_alarm = counter_esp32_set_alarm, .cancel_alarm = counter_esp32_cancel_alarm, .set_top_value = counter_esp32_set_top_value, @@ -212,18 +292,30 @@ static void counter_esp32_isr(void *arg) { const struct device *dev = (const struct device *)arg; struct counter_esp32_data *data = dev->data; + counter_alarm_callback_t cb = data->alarm_cfg.callback; + void *cb_data = data->alarm_cfg.user_data; uint32_t now; + +#if SOC_LP_TIMER_SUPPORTED + const struct counter_esp32_config *cfg = dev->config; + lp_timer_dev_t *lp_timer = cfg->dev; + + if (!lp_timer->int_st.alarm) { + return; + } +#else uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG); if (!(status & RTC_CNTL_MAIN_TIMER_INT_ST_M)) { return; } +#endif counter_esp32_cancel_alarm(dev, 0); counter_esp32_get_value(dev, &now); - if (data->alarm_cfg.callback) { - data->alarm_cfg.callback(dev, 0, now, data->alarm_cfg.user_data); + if (cb && (now > data->ticks)) { + cb(dev, 0, now, cb_data); } } diff --git a/dts/riscv/espressif/esp32c2/esp32c2_common.dtsi b/dts/riscv/espressif/esp32c2/esp32c2_common.dtsi index 2027dca1c0ad8..d52148c63d41b 100644 --- a/dts/riscv/espressif/esp32c2/esp32c2_common.dtsi +++ b/dts/riscv/espressif/esp32c2/esp32c2_common.dtsi @@ -101,7 +101,7 @@ rtc_timer: rtc_timer@60008004 { reg = <0x60008004 0xC>; - compatible = "espressif,esp32-rtc_timer"; + compatible = "espressif,esp32-rtc-timer"; clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; interrupt-parent = <&intc>; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi index 7cbe06705e2a0..ecd8b807a2d00 100644 --- a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi +++ b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi @@ -128,11 +128,11 @@ rtc_timer: rtc_timer@60008004 { reg = <0x60008004 0xC>; - compatible = "espressif,esp32-rtc_timer"; + compatible = "espressif,esp32-rtc-timer"; clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; interrupt-parent = <&intc>; - status = "okay"; + status = "disabled"; }; flash: flash-controller@60002000 { diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index 137aa1b863cc4..34d70c43121ee 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -173,7 +173,7 @@ }; rtc_timer: rtc_timer@600b0c00 { - compatible = "espressif,esp32-rtc_timer"; + compatible = "espressif,esp32-rtc-timer"; reg = <0x600B0C00 DT_SIZE_K(1)>; clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; diff --git a/dts/riscv/espressif/esp32h2/esp32h2_common.dtsi b/dts/riscv/espressif/esp32h2/esp32h2_common.dtsi index f7860994e9d7a..a1859be70c6e1 100644 --- a/dts/riscv/espressif/esp32h2/esp32h2_common.dtsi +++ b/dts/riscv/espressif/esp32h2/esp32h2_common.dtsi @@ -135,7 +135,7 @@ }; rtc_timer: rtc_timer@600b0c00 { - compatible = "espressif,esp32-rtc_timer"; + compatible = "espressif,esp32-rtc-timer"; reg = <0x600B0C00 DT_SIZE_K(1)>; clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; diff --git a/dts/xtensa/espressif/esp32/esp32_common.dtsi b/dts/xtensa/espressif/esp32/esp32_common.dtsi index a5e84de83b1e4..1baad064fae80 100644 --- a/dts/xtensa/espressif/esp32/esp32_common.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_common.dtsi @@ -192,7 +192,7 @@ clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; interrupt-parent = <&intc>; - status = "okay"; + status = "disabled"; }; flash: flash-controller@3ff42000 { diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi index 328fc225a6091..5cc33331afadc 100644 --- a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi +++ b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi @@ -142,11 +142,11 @@ rtc_timer: rtc_timer@3f408004 { reg = <0x3f408004 0xC>; - compatible = "espressif,esp32-rtc_timer"; + compatible = "espressif,esp32-rtc-timer"; clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; interrupt-parent = <&intc>; - status = "okay"; + status = "disabled"; }; flash: flash-controller@3f402000 { diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi index 80cd6827028dc..bd70801e63b0a 100644 --- a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi +++ b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi @@ -181,7 +181,7 @@ rtc_timer: rtc_timer@60008004 { reg = <0x60008004 0xC>; - compatible = "espressif,esp32-rtc_timer"; + compatible = "espressif,esp32-rtc-timer"; clocks = <&clock ESP32_MODULE_MAX>; interrupts = ; interrupt-parent = <&intc>; diff --git a/tests/drivers/counter/counter_basic_api/Kconfig b/tests/drivers/counter/counter_basic_api/Kconfig index 5608e52227bb6..79b61c6bcd9c3 100644 --- a/tests/drivers/counter/counter_basic_api/Kconfig +++ b/tests/drivers/counter/counter_basic_api/Kconfig @@ -7,4 +7,13 @@ config TEST_DRIVER_COUNTER_MCUX_LPC_RTC_HIGHRES help tests the nxp_lpc_rtc_highres compatible driver +config TEST_DRIVER_COUNTER_TOLERANCE + int "Counter ticks tolerance (%)" + default 10 + help + Error tolerance used in counter driver tests. + A number of ticks is estimated and counter is tested against systimer, + to verify accuracy. Tolerance is a percentage of deviation allowed for + the number of expected ticks. + source "Kconfig.zephyr" diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32_procpu.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32_procpu.overlay index cbdd63dda00c4..7b45a3ee9f7ae 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32_procpu.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32_procpu.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { @@ -5,6 +11,10 @@ }; }; +&rtc_timer { + status = "okay"; +}; + &clock { slow-clk-src = ; }; diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32c2.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32c2.overlay index 3f3bd924afa01..7b45a3ee9f7ae 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32c2.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32c2.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32c3.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32c3.overlay index cbdd63dda00c4..7b45a3ee9f7ae 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32c3.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32c3.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { @@ -5,6 +11,10 @@ }; }; +&rtc_timer { + status = "okay"; +}; + &clock { slow-clk-src = ; }; diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32c3_usb.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32c3_usb.overlay index cbdd63dda00c4..7b45a3ee9f7ae 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32c3_usb.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32c3_usb.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { @@ -5,6 +11,10 @@ }; }; +&rtc_timer { + status = "okay"; +}; + &clock { slow-clk-src = ; }; diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32c6_hpcore.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32c6_hpcore.overlay index 654ca2b00155f..5690ab230464f 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32c6_hpcore.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32c6_hpcore.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { @@ -11,3 +17,7 @@ status = "okay"; }; }; + +&rtc_timer { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32h2.conf b/tests/drivers/counter/counter_basic_api/socs/esp32h2.conf new file mode 100644 index 0000000000000..e87bbb9811817 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/socs/esp32h2.conf @@ -0,0 +1,2 @@ +# LP Timer is driven by RC_SLOW, which has limited precision +CONFIG_TEST_DRIVER_COUNTER_TOLERANCE=20 diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32h2.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32h2.overlay index 654ca2b00155f..5690ab230464f 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32h2.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32h2.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { @@ -11,3 +17,7 @@ status = "okay"; }; }; + +&rtc_timer { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32s2.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32s2.overlay index cbdd63dda00c4..7b45a3ee9f7ae 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32s2.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32s2.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { @@ -5,6 +11,10 @@ }; }; +&rtc_timer { + status = "okay"; +}; + &clock { slow-clk-src = ; }; diff --git a/tests/drivers/counter/counter_basic_api/socs/esp32s3_procpu.overlay b/tests/drivers/counter/counter_basic_api/socs/esp32s3_procpu.overlay index 3f3bd924afa01..7b45a3ee9f7ae 100644 --- a/tests/drivers/counter/counter_basic_api/socs/esp32s3_procpu.overlay +++ b/tests/drivers/counter/counter_basic_api/socs/esp32s3_procpu.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + &timer0 { status = "okay"; counter { diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index eb3078ee1f1b1..ff769883a950f 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -105,6 +105,9 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_TMR_ESP32 DEVS_FOR_DT_COMPAT(espressif_esp32_counter) #endif +#ifdef CONFIG_COUNTER_RTC_ESP32 + DEVS_FOR_DT_COMPAT(espressif_esp32_rtc_timer) +#endif #ifdef CONFIG_COUNTER_NXP_S32_SYS_TIMER DEVS_FOR_DT_COMPAT(nxp_s32_sys_timer) #endif @@ -744,8 +747,8 @@ static void test_valid_function_without_alarm(const struct device *dev) ticks_expected = counter_us_to_ticks(dev, wait_for_us); } - /* Set 10% or 2 ticks tolerance, whichever is greater */ - ticks_tol = ticks_expected / 10; + /* Set percentage or 2 ticks tolerance, whichever is greater */ + ticks_tol = (ticks_expected * CONFIG_TEST_DRIVER_COUNTER_TOLERANCE) / 100; ticks_tol = ticks_tol < 2 ? 2 : ticks_tol; err = counter_start(dev);