Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 1 | /* |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 2 | * Copyright (c) 2017-2019 Oticon A/S |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | /** |
| 8 | * Driver for the timer model of the POSIX native_posix board |
| 9 | * It provides the interfaces required by the kernel and the sanity testcases |
| 10 | * It also provides a custom k_busy_wait() which can be used with the |
| 11 | * POSIX arch and InfClock SOC |
| 12 | */ |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 13 | #include "zephyr/types.h" |
| 14 | #include "irq.h" |
| 15 | #include "device.h" |
Anas Nashif | 68c389c | 2019-06-21 12:55:37 -0400 | [diff] [blame] | 16 | #include <drivers/timer/system_timer.h> |
Alberto Escolar Piedras | 66c1652 | 2018-02-06 14:24:27 +0100 | [diff] [blame] | 17 | #include "sys_clock.h" |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 18 | #include "timer_model.h" |
| 19 | #include "soc.h" |
Stephanos Ioannidis | 2d74604 | 2019-10-25 00:08:21 +0900 | [diff] [blame] | 20 | #include <arch/posix/posix_trace.h> |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 21 | |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 22 | static uint64_t tick_period; /* System tick period in microseconds */ |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 23 | /* Time (microseconds since boot) of the last timer tick interrupt */ |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 24 | static uint64_t last_tick_time; |
Alberto Escolar Piedras | 66c1652 | 2018-02-06 14:24:27 +0100 | [diff] [blame] | 25 | |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 26 | /** |
| 27 | * Return the current HW cycle counter |
| 28 | * (number of microseconds since boot in 32bits) |
| 29 | */ |
Anas Nashif | 12b53d1 | 2021-03-12 12:46:52 -0500 | [diff] [blame] | 30 | uint32_t sys_clock_cycle_get_32(void) |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 31 | { |
| 32 | return hwm_get_time(); |
| 33 | } |
| 34 | |
Christopher Friedt | 918a574 | 2021-10-29 20:10:35 -0400 | [diff] [blame^] | 35 | uint64_t sys_clock_cycle_get_64(void) |
| 36 | { |
| 37 | return hwm_get_time(); |
| 38 | } |
| 39 | |
Alberto Escolar Piedras | 6c483ea | 2018-02-08 12:46:13 +0100 | [diff] [blame] | 40 | /** |
| 41 | * Interrupt handler for the timer interrupt |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 42 | * Announce to the kernel that a number of ticks have passed |
Alberto Escolar Piedras | 6c483ea | 2018-02-08 12:46:13 +0100 | [diff] [blame] | 43 | */ |
Tomasz Bursztyka | 4dcfb55 | 2020-06-17 14:58:56 +0200 | [diff] [blame] | 44 | static void np_timer_isr(const void *arg) |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 45 | { |
| 46 | ARG_UNUSED(arg); |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 47 | |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 48 | uint64_t now = hwm_get_time(); |
| 49 | int32_t elapsed_ticks = (now - last_tick_time)/tick_period; |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 50 | |
| 51 | last_tick_time += elapsed_ticks*tick_period; |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 52 | sys_clock_announce(elapsed_ticks); |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 53 | } |
| 54 | |
Alberto Escolar Piedras | fe516b9 | 2020-12-10 13:23:29 +0100 | [diff] [blame] | 55 | /** |
| 56 | * This function exists only to enable tests to call into the timer ISR |
| 57 | */ |
| 58 | void np_timer_isr_test_hook(const void *arg) |
| 59 | { |
| 60 | np_timer_isr(NULL); |
| 61 | } |
| 62 | |
Alberto Escolar Piedras | 66c1652 | 2018-02-06 14:24:27 +0100 | [diff] [blame] | 63 | /* |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 64 | * @brief Initialize system timer driver |
| 65 | * |
Alberto Escolar Piedras | 6c483ea | 2018-02-08 12:46:13 +0100 | [diff] [blame] | 66 | * Enable the hw timer, setting its tick period, and setup its interrupt |
Alberto Escolar Piedras | 66c1652 | 2018-02-06 14:24:27 +0100 | [diff] [blame] | 67 | */ |
Anas Nashif | 5d6c219 | 2021-03-22 10:28:25 -0400 | [diff] [blame] | 68 | int sys_clock_driver_init(const struct device *dev) |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 69 | { |
Anas Nashif | 5d6c219 | 2021-03-22 10:28:25 -0400 | [diff] [blame] | 70 | ARG_UNUSED(dev); |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 71 | |
Andy Ross | cbb77be | 2018-09-19 11:13:56 -0700 | [diff] [blame] | 72 | tick_period = 1000000ul / CONFIG_SYS_CLOCK_TICKS_PER_SEC; |
Alberto Escolar Piedras | 66c1652 | 2018-02-06 14:24:27 +0100 | [diff] [blame] | 73 | |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 74 | last_tick_time = hwm_get_time(); |
Alberto Escolar Piedras | 66c1652 | 2018-02-06 14:24:27 +0100 | [diff] [blame] | 75 | hwtimer_enable(tick_period); |
| 76 | |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 77 | IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0); |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 78 | irq_enable(TIMER_TICK_IRQ); |
| 79 | |
| 80 | return 0; |
| 81 | } |
| 82 | |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 83 | /** |
| 84 | * @brief Set system clock timeout |
| 85 | * |
| 86 | * Informs the system clock driver that the next needed call to |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 87 | * sys_clock_announce() will not be until the specified number of ticks |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 88 | * from the the current time have elapsed. |
| 89 | * |
| 90 | * See system_timer.h for more information |
| 91 | * |
| 92 | * @param ticks Timeout in tick units |
| 93 | * @param idle Hint to the driver that the system is about to enter |
| 94 | * the idle state immediately after setting the timeout |
| 95 | */ |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 96 | void sys_clock_set_timeout(int32_t ticks, bool idle) |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 97 | { |
| 98 | ARG_UNUSED(idle); |
| 99 | |
| 100 | #if defined(CONFIG_TICKLESS_KERNEL) |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 101 | uint64_t silent_ticks; |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 102 | |
| 103 | /* Note that we treat INT_MAX literally as anyhow the maximum amount of |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 104 | * ticks we can report with sys_clock_announce() is INT_MAX |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 105 | */ |
Andy Ross | 7832738 | 2020-03-05 15:18:14 -0800 | [diff] [blame] | 106 | if (ticks == K_TICKS_FOREVER) { |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 107 | silent_ticks = INT64_MAX; |
| 108 | } else if (ticks > 0) { |
| 109 | silent_ticks = ticks - 1; |
| 110 | } else { |
| 111 | silent_ticks = 0; |
| 112 | } |
| 113 | hwtimer_set_silent_ticks(silent_ticks); |
| 114 | #endif |
| 115 | } |
| 116 | |
| 117 | /** |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 118 | * @brief Ticks elapsed since last sys_clock_announce() call |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 119 | * |
| 120 | * Queries the clock driver for the current time elapsed since the |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 121 | * last call to sys_clock_announce() was made. The kernel will call |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 122 | * this with appropriate locking, the driver needs only provide an |
| 123 | * instantaneous answer. |
| 124 | */ |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 125 | uint32_t sys_clock_elapsed(void) |
Alberto Escolar Piedras | f16ea52 | 2019-07-12 16:09:03 +0200 | [diff] [blame] | 126 | { |
| 127 | return (hwm_get_time() - last_tick_time)/tick_period; |
| 128 | } |
| 129 | |
Anas Nashif | 6b55598 | 2017-12-21 08:14:19 -0500 | [diff] [blame] | 130 | |
Alberto Escolar Piedras | ba4a01e | 2018-09-30 14:02:16 +0200 | [diff] [blame] | 131 | #if defined(CONFIG_SYSTEM_CLOCK_DISABLE) |
| 132 | /** |
| 133 | * |
| 134 | * @brief Stop announcing sys ticks into the kernel |
| 135 | * |
| 136 | * Disable the system ticks generation |
| 137 | * |
| 138 | * @return N/A |
| 139 | */ |
| 140 | void sys_clock_disable(void) |
| 141 | { |
| 142 | irq_disable(TIMER_TICK_IRQ); |
| 143 | hwtimer_set_silent_ticks(INT64_MAX); |
| 144 | } |
| 145 | #endif /* CONFIG_SYSTEM_CLOCK_DISABLE */ |