Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 1 | /* |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 2 | * Copyright (c) 2018 Intel Corporation |
| 3 | * |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
Anas Nashif | 68c389c | 2019-06-21 12:55:37 -0400 | [diff] [blame] | 6 | #include <drivers/timer/system_timer.h> |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 7 | #include <sys_clock.h> |
| 8 | #include <spinlock.h> |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 9 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 10 | #define TIMER_IRQ UTIL_CAT(XCHAL_TIMER, \ |
| 11 | UTIL_CAT(CONFIG_XTENSA_TIMER_ID, _INTERRUPT)) |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 12 | |
Piotr Zięcik | 0c0c0d9 | 2019-04-23 15:08:00 +0200 | [diff] [blame] | 13 | #define CYC_PER_TICK (sys_clock_hw_cycles_per_sec() \ |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 14 | / CONFIG_SYS_CLOCK_TICKS_PER_SEC) |
Andy Ross | 5f63c9d | 2019-11-26 11:27:19 -0800 | [diff] [blame] | 15 | #define MAX_CYC 0xffffffffu |
| 16 | #define MAX_TICKS ((MAX_CYC - CYC_PER_TICK) / CYC_PER_TICK) |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 17 | #define MIN_DELAY 1000 |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 18 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 19 | static struct k_spinlock lock; |
| 20 | static unsigned int last_count; |
Andy Ross | ab48827 | 2018-09-20 13:56:45 -0700 | [diff] [blame] | 21 | |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 22 | static void set_ccompare(uint32_t val) |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 23 | { |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 24 | __asm__ volatile ("wsr.CCOMPARE" STRINGIFY(CONFIG_XTENSA_TIMER_ID) " %0" |
| 25 | :: "r"(val)); |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 26 | } |
| 27 | |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 28 | static uint32_t ccount(void) |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 29 | { |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 30 | uint32_t val; |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 31 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 32 | __asm__ volatile ("rsr.CCOUNT %0" : "=r"(val)); |
| 33 | return val; |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 34 | } |
| 35 | |
Tomasz Bursztyka | 4dcfb55 | 2020-06-17 14:58:56 +0200 | [diff] [blame] | 36 | static void ccompare_isr(const void *arg) |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 37 | { |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 38 | ARG_UNUSED(arg); |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 39 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 40 | k_spinlock_key_t key = k_spin_lock(&lock); |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 41 | uint32_t curr = ccount(); |
| 42 | uint32_t dticks = (curr - last_count) / CYC_PER_TICK; |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 43 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 44 | last_count += dticks * CYC_PER_TICK; |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 45 | |
Wentong Wu | 7222757 | 2020-05-12 10:32:40 +0800 | [diff] [blame] | 46 | if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 47 | uint32_t next = last_count + CYC_PER_TICK; |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 48 | |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 49 | if ((int32_t)(next - curr) < MIN_DELAY) { |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 50 | next += CYC_PER_TICK; |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 51 | } |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 52 | set_ccompare(next); |
Youvedeep Singh | 833025d | 2017-10-27 21:38:42 +0530 | [diff] [blame] | 53 | } |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 54 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 55 | k_spin_unlock(&lock, key); |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 56 | sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1); |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 57 | } |
| 58 | |
Anas Nashif | 5d6c219 | 2021-03-22 10:28:25 -0400 | [diff] [blame] | 59 | int sys_clock_driver_init(const struct device *dev) |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 60 | { |
Anas Nashif | 5d6c219 | 2021-03-22 10:28:25 -0400 | [diff] [blame] | 61 | ARG_UNUSED(dev); |
Flavio Ceolin | e1e4a40 | 2019-07-17 21:32:19 -0700 | [diff] [blame] | 62 | |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 63 | IRQ_CONNECT(TIMER_IRQ, 0, ccompare_isr, 0, 0); |
| 64 | set_ccompare(ccount() + CYC_PER_TICK); |
| 65 | irq_enable(TIMER_IRQ); |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 66 | return 0; |
| 67 | } |
| 68 | |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 69 | void sys_clock_set_timeout(int32_t ticks, bool idle) |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 70 | { |
| 71 | ARG_UNUSED(idle); |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 72 | |
Wentong Wu | 7222757 | 2020-05-12 10:32:40 +0800 | [diff] [blame] | 73 | #if defined(CONFIG_TICKLESS_KERNEL) |
Andy Ross | 7832738 | 2020-03-05 15:18:14 -0800 | [diff] [blame] | 74 | ticks = ticks == K_TICKS_FOREVER ? MAX_TICKS : ticks; |
Trond Einar Snekvik | 86c793a | 2020-10-27 12:27:25 +0100 | [diff] [blame] | 75 | ticks = CLAMP(ticks - 1, 0, (int32_t)MAX_TICKS); |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 76 | |
| 77 | k_spinlock_key_t key = k_spin_lock(&lock); |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 78 | uint32_t curr = ccount(), cyc, adj; |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 79 | |
| 80 | /* Round up to next tick boundary */ |
Andy Ross | 5f63c9d | 2019-11-26 11:27:19 -0800 | [diff] [blame] | 81 | cyc = ticks * CYC_PER_TICK; |
| 82 | adj = (curr - last_count) + (CYC_PER_TICK - 1); |
| 83 | if (cyc <= MAX_CYC - adj) { |
| 84 | cyc += adj; |
| 85 | } else { |
| 86 | cyc = MAX_CYC; |
| 87 | } |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 88 | cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK; |
| 89 | cyc += last_count; |
| 90 | |
| 91 | if ((cyc - curr) < MIN_DELAY) { |
| 92 | cyc += CYC_PER_TICK; |
| 93 | } |
| 94 | |
| 95 | set_ccompare(cyc); |
| 96 | k_spin_unlock(&lock, key); |
| 97 | #endif |
| 98 | } |
| 99 | |
Anas Nashif | 9c1efe6 | 2021-02-25 15:33:15 -0500 | [diff] [blame] | 100 | uint32_t sys_clock_elapsed(void) |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 101 | { |
| 102 | if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { |
| 103 | return 0; |
| 104 | } |
| 105 | |
| 106 | k_spinlock_key_t key = k_spin_lock(&lock); |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 107 | uint32_t ret = (ccount() - last_count) / CYC_PER_TICK; |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 108 | |
| 109 | k_spin_unlock(&lock, key); |
| 110 | return ret; |
| 111 | } |
| 112 | |
Anas Nashif | 12b53d1 | 2021-03-12 12:46:52 -0500 | [diff] [blame] | 113 | uint32_t sys_clock_cycle_get_32(void) |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 114 | { |
Andy Ross | 39b2a09 | 2018-10-23 09:08:58 -0700 | [diff] [blame] | 115 | return ccount(); |
Mazen NEIFER | 8f92bc2 | 2017-01-26 15:51:33 +0100 | [diff] [blame] | 116 | } |
Daniel Leung | d0ad419 | 2019-01-28 09:12:13 -0800 | [diff] [blame] | 117 | |
| 118 | #ifdef CONFIG_SMP |
| 119 | void smp_timer_init(void) |
| 120 | { |
| 121 | set_ccompare(ccount() + CYC_PER_TICK); |
| 122 | irq_enable(TIMER_IRQ); |
| 123 | } |
| 124 | #endif |