blob: bb36445d1131cf414da14f3687f7f5d3c956f2c0 [file] [log] [blame]
Felipe Neves5d736762021-04-12 19:39:04 -03001/*
2 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#include <soc/soc_caps.h>
7#include <soc/soc.h>
Lucas Tamborrinoa62423f2023-06-07 08:58:25 -03008
Felipe Neves5d736762021-04-12 19:39:04 -03009#include <hal/systimer_hal.h>
10#include <hal/systimer_ll.h>
Lucas Tamborrinofe57a122024-03-05 11:19:27 -030011#include <esp_private/systimer.h>
Felipe Neves5d736762021-04-12 19:39:04 -030012#include <rom/ets_sys.h>
13#include <esp_attr.h>
14
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020015#include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
16#include <zephyr/drivers/timer/system_timer.h>
17#include <zephyr/sys_clock.h>
Felipe Neves5d736762021-04-12 19:39:04 -030018#include <soc.h>
Gerard Marull-Paretas12b2ee52023-08-28 13:15:43 +020019#include <zephyr/init.h>
Gerard Marull-Paretas597dd592022-10-05 17:29:57 +020020#include <zephyr/spinlock.h>
Felipe Neves5d736762021-04-12 19:39:04 -030021
Felipe Neves39172032021-07-26 21:35:48 -030022#define CYC_PER_TICK ((uint32_t)((uint64_t)sys_clock_hw_cycles_per_sec() \
23 / (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC))
24#define MAX_CYC 0xffffffffu
25#define MAX_TICKS ((MAX_CYC - CYC_PER_TICK) / CYC_PER_TICK)
Sylvio Alvescff71c82022-12-21 10:24:52 -030026#define MIN_DELAY 1
Felipe Neves39172032021-07-26 21:35:48 -030027
Anas Nashifab24be52022-06-28 17:58:40 -040028#if defined(CONFIG_TEST)
29const int32_t z_sys_timer_irq_for_test = DT_IRQN(DT_NODELABEL(systimer0));
30#endif
31
Felipe Neves39172032021-07-26 21:35:48 -030032#define TICKLESS IS_ENABLED(CONFIG_TICKLESS_KERNEL)
33
34static struct k_spinlock lock;
35static uint64_t last_count;
36
Sylvio Alves7a00f7b2022-08-15 14:50:59 -030037/* Systimer HAL layer object */
38static systimer_hal_context_t systimer_hal;
39
Felipe Neves39172032021-07-26 21:35:48 -030040static void set_systimer_alarm(uint64_t time)
41{
Sylvio Alves7a00f7b2022-08-15 14:50:59 -030042 systimer_hal_select_alarm_mode(&systimer_hal,
Lucas Tamborrinofe57a122024-03-05 11:19:27 -030043 SYSTIMER_ALARM_OS_TICK_CORE0, SYSTIMER_ALARM_MODE_ONESHOT);
Sylvio Alves7a00f7b2022-08-15 14:50:59 -030044
Sylvio Alvescff71c82022-12-21 10:24:52 -030045 systimer_counter_value_t alarm = {.val = time};
46
Lucas Tamborrinofe57a122024-03-05 11:19:27 -030047 systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false);
48 systimer_ll_set_alarm_target(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, alarm.val);
49 systimer_ll_apply_alarm_value(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0);
50 systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, true);
51 systimer_ll_enable_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, true);
Felipe Neves39172032021-07-26 21:35:48 -030052}
53
Sylvio Alves7a00f7b2022-08-15 14:50:59 -030054static uint64_t get_systimer_alarm(void)
Felipe Neves39172032021-07-26 21:35:48 -030055{
Lucas Tamborrinofe57a122024-03-05 11:19:27 -030056 return systimer_hal_get_counter_value(&systimer_hal, SYSTIMER_COUNTER_OS_TICK);
Felipe Neves39172032021-07-26 21:35:48 -030057}
Felipe Neves5d736762021-04-12 19:39:04 -030058
59static void sys_timer_isr(const void *arg)
60{
Felipe Neves132ab922021-06-14 11:19:33 -030061 ARG_UNUSED(arg);
Lucas Tamborrinofe57a122024-03-05 11:19:27 -030062 systimer_ll_clear_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0);
Felipe Neves39172032021-07-26 21:35:48 -030063
64 k_spinlock_key_t key = k_spin_lock(&lock);
Sylvio Alves7a00f7b2022-08-15 14:50:59 -030065 uint64_t now = get_systimer_alarm();
Felipe Neves39172032021-07-26 21:35:48 -030066
Sylvio Alves47015812023-03-09 09:16:42 -030067 uint64_t dticks = (uint64_t)((now - last_count) / CYC_PER_TICK);
Felipe Neves39172032021-07-26 21:35:48 -030068
Sylvio Alves47015812023-03-09 09:16:42 -030069 last_count += dticks * CYC_PER_TICK;
Felipe Neves39172032021-07-26 21:35:48 -030070
71 if (!TICKLESS) {
72 uint64_t next = last_count + CYC_PER_TICK;
73
74 if ((int64_t)(next - now) < MIN_DELAY) {
75 next += CYC_PER_TICK;
76 }
77 set_systimer_alarm(next);
78 }
79
80 k_spin_unlock(&lock, key);
Sylvio Alves47015812023-03-09 09:16:42 -030081 sys_clock_announce(dticks);
Felipe Neves5d736762021-04-12 19:39:04 -030082}
83
Felipe Neves5d736762021-04-12 19:39:04 -030084void sys_clock_set_timeout(int32_t ticks, bool idle)
85{
Felipe Neves132ab922021-06-14 11:19:33 -030086 ARG_UNUSED(idle);
Felipe Neves39172032021-07-26 21:35:48 -030087
88#if defined(CONFIG_TICKLESS_KERNEL)
89 ticks = ticks == K_TICKS_FOREVER ? MAX_TICKS : ticks;
90 ticks = CLAMP(ticks - 1, 0, (int32_t)MAX_TICKS);
91
92 k_spinlock_key_t key = k_spin_lock(&lock);
Sylvio Alves7a00f7b2022-08-15 14:50:59 -030093 uint64_t now = get_systimer_alarm();
Felipe Neves39172032021-07-26 21:35:48 -030094 uint32_t adj, cyc = ticks * CYC_PER_TICK;
95
96 /* Round up to next tick boundary. */
97 adj = (uint32_t)(now - last_count) + (CYC_PER_TICK - 1);
98 if (cyc <= MAX_CYC - adj) {
99 cyc += adj;
100 } else {
101 cyc = MAX_CYC;
102 }
103 cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK;
104
105 if ((int32_t)(cyc + last_count - now) < MIN_DELAY) {
106 cyc += CYC_PER_TICK;
107 }
108
109 set_systimer_alarm(cyc + last_count);
110 k_spin_unlock(&lock, key);
111#endif
Felipe Neves5d736762021-04-12 19:39:04 -0300112}
113
114uint32_t sys_clock_elapsed(void)
115{
Felipe Neves39172032021-07-26 21:35:48 -0300116 if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
117 return 0;
118 }
119
120 k_spinlock_key_t key = k_spin_lock(&lock);
Sylvio Alves7a00f7b2022-08-15 14:50:59 -0300121 uint32_t ret = ((uint32_t)get_systimer_alarm() - (uint32_t)last_count) / CYC_PER_TICK;
Felipe Neves39172032021-07-26 21:35:48 -0300122
123 k_spin_unlock(&lock, key);
124 return ret;
Felipe Neves5d736762021-04-12 19:39:04 -0300125}
126
127uint32_t sys_clock_cycle_get_32(void)
128{
Sylvio Alves7a00f7b2022-08-15 14:50:59 -0300129 return (uint32_t)get_systimer_alarm();
Felipe Neves5d736762021-04-12 19:39:04 -0300130}
Christopher Friedt918a5742021-10-29 20:10:35 -0400131
132uint64_t sys_clock_cycle_get_64(void)
133{
Sylvio Alves7a00f7b2022-08-15 14:50:59 -0300134 return get_systimer_alarm();
Christopher Friedt918a5742021-10-29 20:10:35 -0400135}
Gerard Marull-Paretasb1ced752021-11-04 12:51:39 +0100136
Sylvio Alvesf6fdfd42024-06-12 17:40:26 -0300137void sys_clock_disable(void)
138{
139 systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false);
140 systimer_ll_enable_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false);
141 systimer_hal_deinit(&systimer_hal);
142}
143
Gerard Marull-Paretasa5fd0d12022-10-19 09:33:44 +0200144static int sys_clock_driver_init(void)
Gerard Marull-Paretasb1ced752021-11-04 12:51:39 +0100145{
Raffael Rostagnobb746cd2024-06-28 09:08:33 -0300146 int ret;
147
148 ret = esp_intr_alloc(DT_IRQ_BY_IDX(DT_NODELABEL(systimer0), 0, irq),
Raffael Rostagno90c61062024-08-19 15:23:22 -0300149 ESP_PRIO_TO_FLAGS(DT_IRQ_BY_IDX(DT_NODELABEL(systimer0), 0, priority)) |
150 ESP_INT_FLAGS_CHECK(DT_IRQ_BY_IDX(DT_NODELABEL(systimer0), 0, flags)),
Gerard Marull-Paretasb1ced752021-11-04 12:51:39 +0100151 sys_timer_isr,
152 NULL,
153 NULL);
154
Raffael Rostagnobb746cd2024-06-28 09:08:33 -0300155 if (ret != 0) {
156 return ret;
157 }
158
Sylvio Alves7a00f7b2022-08-15 14:50:59 -0300159 systimer_hal_init(&systimer_hal);
160 systimer_hal_connect_alarm_counter(&systimer_hal,
Lucas Tamborrinofe57a122024-03-05 11:19:27 -0300161 SYSTIMER_ALARM_OS_TICK_CORE0, SYSTIMER_COUNTER_OS_TICK);
Gerard Marull-Paretasb1ced752021-11-04 12:51:39 +0100162
Lucas Tamborrinofe57a122024-03-05 11:19:27 -0300163 systimer_hal_enable_counter(&systimer_hal, SYSTIMER_COUNTER_OS_TICK);
164 systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_COUNTER_OS_TICK, 0, true);
Sylvio Alves7a00f7b2022-08-15 14:50:59 -0300165 last_count = get_systimer_alarm();
166 set_systimer_alarm(last_count + CYC_PER_TICK);
Gerard Marull-Paretasb1ced752021-11-04 12:51:39 +0100167 return 0;
168}
169
Lucas Tamborrinoe282b0e2024-05-02 16:39:17 -0300170SYS_INIT(sys_clock_driver_init, PRE_KERNEL_1,
Gerard Marull-Paretasb1ced752021-11-04 12:51:39 +0100171 CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);