Zephyr Project API 3.7.0
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
timer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 IoT.bzh
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_TIMER_H_
8#define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_TIMER_H_
9
10#ifdef CONFIG_ARM_ARCH_TIMER
11
12#ifndef _ASMLANGUAGE
13
16#include <zephyr/types.h>
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22#define ARM_ARCH_TIMER_BASE DT_REG_ADDR_BY_IDX(ARM_TIMER_NODE, 0)
23#define ARM_ARCH_TIMER_IRQ ARM_TIMER_VIRTUAL_IRQ
24#define ARM_ARCH_TIMER_PRIO ARM_TIMER_VIRTUAL_PRIO
25#define ARM_ARCH_TIMER_FLAGS ARM_TIMER_VIRTUAL_FLAGS
26
27#define TIMER_CNT_LOWER 0x00
28#define TIMER_CNT_UPPER 0x04
29#define TIMER_CTRL 0x08
30#define TIMER_ISR 0x0c
31#define TIMER_CMP_LOWER 0x10
32#define TIMER_CMP_UPPER 0x14
33
34#define TIMER_IRQ_ENABLE BIT(2)
35#define TIMER_COMP_ENABLE BIT(1)
36#define TIMER_ENABLE BIT(0)
37
38#define TIMER_ISR_EVENT_FLAG BIT(0)
39
41
42#define TIMER_REG_GET(offs) (DEVICE_MMIO_TOPLEVEL_GET(timer_regs) + offs)
43
44static ALWAYS_INLINE void arm_arch_timer_init(void)
45{
47}
48
50{
51 uint32_t lower = (uint32_t)val;
52 uint32_t upper = (uint32_t)(val >> 32);
53 uint32_t ctrl;
54
55 /* Disable IRQ and comparator */
56 ctrl = sys_read32(TIMER_REG_GET(TIMER_CTRL));
57 ctrl &= ~(TIMER_COMP_ENABLE | TIMER_IRQ_ENABLE);
58 sys_write32(ctrl, TIMER_REG_GET(TIMER_CTRL));
59
60 sys_write32(lower, TIMER_REG_GET(TIMER_CMP_LOWER));
61 sys_write32(upper, TIMER_REG_GET(TIMER_CMP_UPPER));
62
63 /* enable comparator back, let set_irq_mask enabling the IRQ again */
64 ctrl |= TIMER_COMP_ENABLE;
65 sys_write32(ctrl, TIMER_REG_GET(TIMER_CTRL));
66}
67
68#if defined(CONFIG_ARM_ARCH_TIMER_ERRATUM_740657)
69
70/*
71 * R/W access to the event flag register is required for the timer errata
72 * 740657 workaround -> comp. ISR implementation in arm_arch_timer.c.
73 * This functionality is not present in the aarch64 implementation of the
74 * ARM global timer access functions.
75 *
76 * comp. ARM Cortex-A9 processors Software Developers Errata Notice,
77 * ARM document ID032315.
78 */
79
80static ALWAYS_INLINE uint8_t arm_arch_timer_get_int_status(void)
81{
82 return (uint8_t)(sys_read32(TIMER_REG_GET(TIMER_ISR)) & TIMER_ISR_EVENT_FLAG);
83}
84
85static ALWAYS_INLINE void arm_arch_timer_clear_int_status(void)
86{
87 sys_write32(TIMER_ISR_EVENT_FLAG, TIMER_REG_GET(TIMER_ISR));
88}
89
90#endif /* CONFIG_ARM_ARCH_TIMER_ERRATUM_740657 */
91
92static ALWAYS_INLINE void arm_arch_timer_enable(bool enable)
93{
94 uint32_t ctrl;
95
96 ctrl = sys_read32(TIMER_REG_GET(TIMER_CTRL));
97 if (enable) {
98 ctrl |= TIMER_ENABLE;
99 } else {
100 ctrl &= ~TIMER_ENABLE;
101 }
102
103 sys_write32(ctrl, TIMER_REG_GET(TIMER_CTRL));
104}
105
106static ALWAYS_INLINE void arm_arch_timer_set_irq_mask(bool mask)
107{
108 uint32_t ctrl;
109
110 ctrl = sys_read32(TIMER_REG_GET(TIMER_CTRL));
111 if (mask) {
112 ctrl &= ~TIMER_IRQ_ENABLE;
113 } else {
114 ctrl |= TIMER_IRQ_ENABLE;
115 sys_write32(1, TIMER_REG_GET(TIMER_ISR));
116 }
117 sys_write32(ctrl, TIMER_REG_GET(TIMER_CTRL));
118}
119
121{
122 uint32_t lower;
123 uint32_t upper, upper_saved;
124
125 /* To get the value from the Global Timer Counter register proceed
126 * as follows:
127 * 1. Read the upper 32-bit timer counter register.
128 * 2. Read the lower 32-bit timer counter register.
129 * 3. Read the upper 32-bit timer counter register again. If the value
130 * is different to the 32-bit upper value read previously,
131 * go back to step 2.
132 * Otherwise the 64-bit timer counter value is correct.
133 */
134 upper = sys_read32(TIMER_REG_GET(TIMER_CNT_UPPER));
135 do {
136 upper_saved = upper;
137 lower = sys_read32(TIMER_REG_GET(TIMER_CNT_LOWER));
138 upper = sys_read32(TIMER_REG_GET(TIMER_CNT_UPPER));
139 } while (upper != upper_saved);
140
141 return ((uint64_t)upper) << 32 | lower;
142}
143
144#ifdef __cplusplus
145}
146#endif
147
148#endif /* _ASMLANGUAGE */
149
150#endif /* CONFIG_ARM_ARCH_TIMER */
151
152#endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_A_R_TIMER_H_ */
#define ARM_TIMER_NODE
Definition arm_arch_timer.h:14
static ALWAYS_INLINE uint64_t arm_arch_timer_count(void)
Definition armv8_timer.h:63
static ALWAYS_INLINE void arm_arch_timer_set_irq_mask(bool mask)
Definition armv8_timer.h:48
static ALWAYS_INLINE void arm_arch_timer_set_compare(uint64_t val)
Definition armv8_timer.h:28
static ALWAYS_INLINE void arm_arch_timer_enable(unsigned char enable)
Definition armv8_timer.h:33
static ALWAYS_INLINE void arm_arch_timer_init(void)
Definition armv8_timer.h:24
#define ALWAYS_INLINE
Definition common.h:129
#define DEVICE_MMIO_TOPLEVEL_MAP(name, flags)
Set up memory for a driver'sMMIO region.
Definition device_mmio.h:715
#define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id)
Declare top-level storage for MMIO information, static scope.
Definition device_mmio.h:661
#define K_MEM_CACHE_NONE
No caching.
Definition mm.h:34
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT64_TYPE__ uint64_t
Definition stdint.h:91
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
static ALWAYS_INLINE void sys_write32(uint32_t data, mem_addr_t addr)
Definition sys-io-common.h:70
static ALWAYS_INLINE uint32_t sys_read32(mem_addr_t addr)
Definition sys-io-common.h:59