Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2017-2019 Oticon A/S
3 : : *
4 : : * SPDX-License-Identifier: Apache-2.0
5 : : */
6 : :
7 : : /**
8 : : * Driver for the native_sim board timer
9 : : * It provides the same API required by the kernel as any other timer driver
10 : : */
11 : : #include <zephyr/types.h>
12 : : #include <zephyr/irq.h>
13 : : #include <zephyr/init.h>
14 : : #include <zephyr/drivers/timer/system_timer.h>
15 : : #include <zephyr/sys_clock.h>
16 : : #include "nsi_hw_scheduler.h"
17 : : #include "nsi_timer_model.h"
18 : : #include "soc.h"
19 : :
20 : : static uint64_t tick_period; /* System tick period in microseconds */
21 : : /* Time (microseconds since boot) of the last timer tick interrupt */
22 : : static uint64_t last_tick_time;
23 : :
24 : : /**
25 : : * Return the current HW cycle counter
26 : : * (number of microseconds since boot in 32bits)
27 : : */
28 : 261 : uint32_t sys_clock_cycle_get_32(void)
29 : : {
30 : 261 : return nsi_hws_get_time();
31 : : }
32 : :
33 : 0 : uint64_t sys_clock_cycle_get_64(void)
34 : : {
35 : 0 : return nsi_hws_get_time();
36 : : }
37 : :
38 : : /**
39 : : * Interrupt handler for the timer interrupt
40 : : * Announce to the kernel that a number of ticks have passed
41 : : */
42 : 0 : static void np_timer_isr(const void *arg)
43 : : {
44 : 0 : ARG_UNUSED(arg);
45 : :
46 : 0 : uint64_t now = nsi_hws_get_time();
47 : 0 : int32_t elapsed_ticks = (now - last_tick_time)/tick_period;
48 : :
49 : 0 : last_tick_time += elapsed_ticks*tick_period;
50 : 0 : sys_clock_announce(elapsed_ticks);
51 : 0 : }
52 : :
53 : : /**
54 : : * This function exists only to enable tests to call into the timer ISR
55 : : */
56 : 0 : void np_timer_isr_test_hook(const void *arg)
57 : : {
58 : 0 : np_timer_isr(NULL);
59 : 0 : }
60 : :
61 : : /**
62 : : * @brief Set system clock timeout
63 : : *
64 : : * Informs the system clock driver that the next needed call to
65 : : * sys_clock_announce() will not be until the specified number of ticks
66 : : * from the current time have elapsed.
67 : : *
68 : : * See system_timer.h for more information
69 : : *
70 : : * @param ticks Timeout in tick units
71 : : * @param idle Hint to the driver that the system is about to enter
72 : : * the idle state immediately after setting the timeout
73 : : */
74 : 109 : void sys_clock_set_timeout(int32_t ticks, bool idle)
75 : : {
76 : 109 : ARG_UNUSED(idle);
77 : :
78 : : #if defined(CONFIG_TICKLESS_KERNEL)
79 : 109 : uint64_t silent_ticks;
80 : :
81 : : /* Note that we treat INT_MAX literally as anyhow the maximum amount of
82 : : * ticks we can report with sys_clock_announce() is INT_MAX
83 : : */
84 [ + - ]: 109 : if (ticks == K_TICKS_FOREVER) {
85 : : silent_ticks = INT64_MAX;
86 [ + - ]: 109 : } else if (ticks > 0) {
87 : 109 : silent_ticks = ticks - 1;
88 : : } else {
89 : : silent_ticks = 0;
90 : : }
91 : 109 : hwtimer_set_silent_ticks(silent_ticks);
92 : : #endif
93 : 109 : }
94 : :
95 : : /**
96 : : * @brief Ticks elapsed since last sys_clock_announce() call
97 : : *
98 : : * Queries the clock driver for the current time elapsed since the
99 : : * last call to sys_clock_announce() was made. The kernel will call
100 : : * this with appropriate locking, the driver needs only provide an
101 : : * instantaneous answer.
102 : : */
103 : 109 : uint32_t sys_clock_elapsed(void)
104 : : {
105 : 109 : return (nsi_hws_get_time() - last_tick_time)/tick_period;
106 : : }
107 : :
108 : : /**
109 : : * @brief Stop announcing sys ticks into the kernel
110 : : *
111 : : * Disable the system ticks generation
112 : : */
113 : 0 : void sys_clock_disable(void)
114 : : {
115 : 0 : irq_disable(TIMER_TICK_IRQ);
116 : 0 : hwtimer_set_silent_ticks(INT64_MAX);
117 : 0 : }
118 : :
119 : : /**
120 : : * @brief Initialize system timer driver
121 : : *
122 : : * Enable the hw timer, setting its tick period, and setup its interrupt
123 : : */
124 : 1 : static int sys_clock_driver_init(void)
125 : : {
126 : :
127 : 1 : tick_period = 1000000UL / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
128 : :
129 : 1 : last_tick_time = nsi_hws_get_time();
130 : 1 : hwtimer_enable(tick_period);
131 : :
132 : 1 : IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0);
133 : 1 : irq_enable(TIMER_TICK_IRQ);
134 : :
135 : 1 : return 0;
136 : : }
137 : :
138 : : SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2,
139 : : CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
|