blob: 998eff6cf74b57d6978e21b3471e9f94d91a3cff [file] [log] [blame]
Anas Nashif6b555982017-12-21 08:14:19 -05001/*
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +02002 * Copyright (c) 2017-2019 Oticon A/S
Anas Nashif6b555982017-12-21 08:14:19 -05003 *
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 Nashif6b555982017-12-21 08:14:19 -050013#include "zephyr/types.h"
14#include "irq.h"
15#include "device.h"
Anas Nashif68c389c2019-06-21 12:55:37 -040016#include <drivers/timer/system_timer.h>
Alberto Escolar Piedras66c16522018-02-06 14:24:27 +010017#include "sys_clock.h"
Anas Nashif6b555982017-12-21 08:14:19 -050018#include "timer_model.h"
19#include "soc.h"
Stephanos Ioannidis2d746042019-10-25 00:08:21 +090020#include <arch/posix/posix_trace.h>
Anas Nashif6b555982017-12-21 08:14:19 -050021
Kumar Galaa1b77fd2020-05-27 11:26:57 -050022static uint64_t tick_period; /* System tick period in microseconds */
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020023/* Time (microseconds since boot) of the last timer tick interrupt */
Kumar Galaa1b77fd2020-05-27 11:26:57 -050024static uint64_t last_tick_time;
Alberto Escolar Piedras66c16522018-02-06 14:24:27 +010025
Anas Nashif6b555982017-12-21 08:14:19 -050026/**
27 * Return the current HW cycle counter
28 * (number of microseconds since boot in 32bits)
29 */
Anas Nashif12b53d12021-03-12 12:46:52 -050030uint32_t sys_clock_cycle_get_32(void)
Anas Nashif6b555982017-12-21 08:14:19 -050031{
32 return hwm_get_time();
33}
34
Christopher Friedt918a5742021-10-29 20:10:35 -040035uint64_t sys_clock_cycle_get_64(void)
36{
37 return hwm_get_time();
38}
39
Alberto Escolar Piedras6c483ea2018-02-08 12:46:13 +010040/**
41 * Interrupt handler for the timer interrupt
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020042 * Announce to the kernel that a number of ticks have passed
Alberto Escolar Piedras6c483ea2018-02-08 12:46:13 +010043 */
Tomasz Bursztyka4dcfb552020-06-17 14:58:56 +020044static void np_timer_isr(const void *arg)
Anas Nashif6b555982017-12-21 08:14:19 -050045{
46 ARG_UNUSED(arg);
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020047
Kumar Galaa1b77fd2020-05-27 11:26:57 -050048 uint64_t now = hwm_get_time();
49 int32_t elapsed_ticks = (now - last_tick_time)/tick_period;
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020050
51 last_tick_time += elapsed_ticks*tick_period;
Anas Nashif9c1efe62021-02-25 15:33:15 -050052 sys_clock_announce(elapsed_ticks);
Anas Nashif6b555982017-12-21 08:14:19 -050053}
54
Alberto Escolar Piedrasfe516b92020-12-10 13:23:29 +010055/**
56 * This function exists only to enable tests to call into the timer ISR
57 */
58void np_timer_isr_test_hook(const void *arg)
59{
60 np_timer_isr(NULL);
61}
62
Alberto Escolar Piedras66c16522018-02-06 14:24:27 +010063/*
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020064 * @brief Initialize system timer driver
65 *
Alberto Escolar Piedras6c483ea2018-02-08 12:46:13 +010066 * Enable the hw timer, setting its tick period, and setup its interrupt
Alberto Escolar Piedras66c16522018-02-06 14:24:27 +010067 */
Anas Nashif5d6c2192021-03-22 10:28:25 -040068int sys_clock_driver_init(const struct device *dev)
Anas Nashif6b555982017-12-21 08:14:19 -050069{
Anas Nashif5d6c2192021-03-22 10:28:25 -040070 ARG_UNUSED(dev);
Anas Nashif6b555982017-12-21 08:14:19 -050071
Andy Rosscbb77be2018-09-19 11:13:56 -070072 tick_period = 1000000ul / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
Alberto Escolar Piedras66c16522018-02-06 14:24:27 +010073
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020074 last_tick_time = hwm_get_time();
Alberto Escolar Piedras66c16522018-02-06 14:24:27 +010075 hwtimer_enable(tick_period);
76
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020077 IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0);
Anas Nashif6b555982017-12-21 08:14:19 -050078 irq_enable(TIMER_TICK_IRQ);
79
80 return 0;
81}
82
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020083/**
84 * @brief Set system clock timeout
85 *
86 * Informs the system clock driver that the next needed call to
Anas Nashif9c1efe62021-02-25 15:33:15 -050087 * sys_clock_announce() will not be until the specified number of ticks
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020088 * 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 Nashif9c1efe62021-02-25 15:33:15 -050096void sys_clock_set_timeout(int32_t ticks, bool idle)
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +020097{
98 ARG_UNUSED(idle);
99
100#if defined(CONFIG_TICKLESS_KERNEL)
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500101 uint64_t silent_ticks;
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +0200102
103 /* Note that we treat INT_MAX literally as anyhow the maximum amount of
Anas Nashif9c1efe62021-02-25 15:33:15 -0500104 * ticks we can report with sys_clock_announce() is INT_MAX
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +0200105 */
Andy Ross78327382020-03-05 15:18:14 -0800106 if (ticks == K_TICKS_FOREVER) {
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +0200107 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 Nashif9c1efe62021-02-25 15:33:15 -0500118 * @brief Ticks elapsed since last sys_clock_announce() call
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +0200119 *
120 * Queries the clock driver for the current time elapsed since the
Anas Nashif9c1efe62021-02-25 15:33:15 -0500121 * last call to sys_clock_announce() was made. The kernel will call
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +0200122 * this with appropriate locking, the driver needs only provide an
123 * instantaneous answer.
124 */
Anas Nashif9c1efe62021-02-25 15:33:15 -0500125uint32_t sys_clock_elapsed(void)
Alberto Escolar Piedrasf16ea522019-07-12 16:09:03 +0200126{
127 return (hwm_get_time() - last_tick_time)/tick_period;
128}
129
Anas Nashif6b555982017-12-21 08:14:19 -0500130
Alberto Escolar Piedrasba4a01e2018-09-30 14:02:16 +0200131#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 */
140void 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 */