Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 1 | /* |
| 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 Tamborrino | a62423f | 2023-06-07 08:58:25 -0300 | [diff] [blame] | 8 | |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 9 | #include <hal/systimer_hal.h> |
| 10 | #include <hal/systimer_ll.h> |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 11 | #include <esp_private/systimer.h> |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 12 | #include <rom/ets_sys.h> |
| 13 | #include <esp_attr.h> |
| 14 | |
Gerard Marull-Paretas | fb60aab | 2022-05-06 10:25:46 +0200 | [diff] [blame] | 15 | #include <zephyr/drivers/interrupt_controller/intc_esp32c3.h> |
| 16 | #include <zephyr/drivers/timer/system_timer.h> |
| 17 | #include <zephyr/sys_clock.h> |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 18 | #include <soc.h> |
Gerard Marull-Paretas | 12b2ee5 | 2023-08-28 13:15:43 +0200 | [diff] [blame] | 19 | #include <zephyr/init.h> |
Gerard Marull-Paretas | 597dd59 | 2022-10-05 17:29:57 +0200 | [diff] [blame] | 20 | #include <zephyr/spinlock.h> |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 21 | |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 22 | #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 Alves | cff71c8 | 2022-12-21 10:24:52 -0300 | [diff] [blame] | 26 | #define MIN_DELAY 1 |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 27 | |
Anas Nashif | ab24be5 | 2022-06-28 17:58:40 -0400 | [diff] [blame] | 28 | #if defined(CONFIG_TEST) |
| 29 | const int32_t z_sys_timer_irq_for_test = DT_IRQN(DT_NODELABEL(systimer0)); |
| 30 | #endif |
| 31 | |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 32 | #define TICKLESS IS_ENABLED(CONFIG_TICKLESS_KERNEL) |
| 33 | |
| 34 | static struct k_spinlock lock; |
| 35 | static uint64_t last_count; |
| 36 | |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 37 | /* Systimer HAL layer object */ |
| 38 | static systimer_hal_context_t systimer_hal; |
| 39 | |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 40 | static void set_systimer_alarm(uint64_t time) |
| 41 | { |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 42 | systimer_hal_select_alarm_mode(&systimer_hal, |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 43 | SYSTIMER_ALARM_OS_TICK_CORE0, SYSTIMER_ALARM_MODE_ONESHOT); |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 44 | |
Sylvio Alves | cff71c8 | 2022-12-21 10:24:52 -0300 | [diff] [blame] | 45 | systimer_counter_value_t alarm = {.val = time}; |
| 46 | |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 47 | 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 Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 52 | } |
| 53 | |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 54 | static uint64_t get_systimer_alarm(void) |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 55 | { |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 56 | return systimer_hal_get_counter_value(&systimer_hal, SYSTIMER_COUNTER_OS_TICK); |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 57 | } |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 58 | |
| 59 | static void sys_timer_isr(const void *arg) |
| 60 | { |
Felipe Neves | 132ab92 | 2021-06-14 11:19:33 -0300 | [diff] [blame] | 61 | ARG_UNUSED(arg); |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 62 | systimer_ll_clear_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0); |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 63 | |
| 64 | k_spinlock_key_t key = k_spin_lock(&lock); |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 65 | uint64_t now = get_systimer_alarm(); |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 66 | |
Sylvio Alves | 4701581 | 2023-03-09 09:16:42 -0300 | [diff] [blame] | 67 | uint64_t dticks = (uint64_t)((now - last_count) / CYC_PER_TICK); |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 68 | |
Sylvio Alves | 4701581 | 2023-03-09 09:16:42 -0300 | [diff] [blame] | 69 | last_count += dticks * CYC_PER_TICK; |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 70 | |
| 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 Alves | 4701581 | 2023-03-09 09:16:42 -0300 | [diff] [blame] | 81 | sys_clock_announce(dticks); |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 82 | } |
| 83 | |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 84 | void sys_clock_set_timeout(int32_t ticks, bool idle) |
| 85 | { |
Felipe Neves | 132ab92 | 2021-06-14 11:19:33 -0300 | [diff] [blame] | 86 | ARG_UNUSED(idle); |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 87 | |
| 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 Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 93 | uint64_t now = get_systimer_alarm(); |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 94 | 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 Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | uint32_t sys_clock_elapsed(void) |
| 115 | { |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 116 | if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { |
| 117 | return 0; |
| 118 | } |
| 119 | |
| 120 | k_spinlock_key_t key = k_spin_lock(&lock); |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 121 | uint32_t ret = ((uint32_t)get_systimer_alarm() - (uint32_t)last_count) / CYC_PER_TICK; |
Felipe Neves | 3917203 | 2021-07-26 21:35:48 -0300 | [diff] [blame] | 122 | |
| 123 | k_spin_unlock(&lock, key); |
| 124 | return ret; |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | uint32_t sys_clock_cycle_get_32(void) |
| 128 | { |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 129 | return (uint32_t)get_systimer_alarm(); |
Felipe Neves | 5d73676 | 2021-04-12 19:39:04 -0300 | [diff] [blame] | 130 | } |
Christopher Friedt | 918a574 | 2021-10-29 20:10:35 -0400 | [diff] [blame] | 131 | |
| 132 | uint64_t sys_clock_cycle_get_64(void) |
| 133 | { |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 134 | return get_systimer_alarm(); |
Christopher Friedt | 918a574 | 2021-10-29 20:10:35 -0400 | [diff] [blame] | 135 | } |
Gerard Marull-Paretas | b1ced75 | 2021-11-04 12:51:39 +0100 | [diff] [blame] | 136 | |
Sylvio Alves | f6fdfd4 | 2024-06-12 17:40:26 -0300 | [diff] [blame] | 137 | void 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-Paretas | a5fd0d1 | 2022-10-19 09:33:44 +0200 | [diff] [blame] | 144 | static int sys_clock_driver_init(void) |
Gerard Marull-Paretas | b1ced75 | 2021-11-04 12:51:39 +0100 | [diff] [blame] | 145 | { |
Raffael Rostagno | bb746cd | 2024-06-28 09:08:33 -0300 | [diff] [blame] | 146 | int ret; |
| 147 | |
| 148 | ret = esp_intr_alloc(DT_IRQ_BY_IDX(DT_NODELABEL(systimer0), 0, irq), |
Raffael Rostagno | 90c6106 | 2024-08-19 15:23:22 -0300 | [diff] [blame] | 149 | 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-Paretas | b1ced75 | 2021-11-04 12:51:39 +0100 | [diff] [blame] | 151 | sys_timer_isr, |
| 152 | NULL, |
| 153 | NULL); |
| 154 | |
Raffael Rostagno | bb746cd | 2024-06-28 09:08:33 -0300 | [diff] [blame] | 155 | if (ret != 0) { |
| 156 | return ret; |
| 157 | } |
| 158 | |
Sylvio Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 159 | systimer_hal_init(&systimer_hal); |
| 160 | systimer_hal_connect_alarm_counter(&systimer_hal, |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 161 | SYSTIMER_ALARM_OS_TICK_CORE0, SYSTIMER_COUNTER_OS_TICK); |
Gerard Marull-Paretas | b1ced75 | 2021-11-04 12:51:39 +0100 | [diff] [blame] | 162 | |
Lucas Tamborrino | fe57a12 | 2024-03-05 11:19:27 -0300 | [diff] [blame] | 163 | 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 Alves | 7a00f7b | 2022-08-15 14:50:59 -0300 | [diff] [blame] | 165 | last_count = get_systimer_alarm(); |
| 166 | set_systimer_alarm(last_count + CYC_PER_TICK); |
Gerard Marull-Paretas | b1ced75 | 2021-11-04 12:51:39 +0100 | [diff] [blame] | 167 | return 0; |
| 168 | } |
| 169 | |
Lucas Tamborrino | e282b0e | 2024-05-02 16:39:17 -0300 | [diff] [blame] | 170 | SYS_INIT(sys_clock_driver_init, PRE_KERNEL_1, |
Gerard Marull-Paretas | b1ced75 | 2021-11-04 12:51:39 +0100 | [diff] [blame] | 171 | CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); |