1 /*
2 * Copyright (c) 2016-2022 Arm Limited. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * \file timer_cmsdk_drv.c
19 * \brief Generic driver for CMSDK APB Timers.
20 * The timer is a 32-bit down-counter with the following features:
21 * - optional programmable external clock source
22 * - programmable interrupt source, triggered if counter reaches 0
23 * - automatic reload if counter reaches 0
24 */
25
26 #include "timer_cmsdk_drv.h"
27
28 /** Setter bit manipulation macro */
29 #define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
30 /** Clearing bit manipulation macro */
31 #define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
32 /** Getter bit manipulation macro */
33 #define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
34
35 /**
36 * \brief Timer register map structure
37 *
38 */
39 struct timer_cmsdk_reg_map_t {
40 volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */
41 volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */
42 volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */
43 union {
44 volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt
45 * status register
46 */
47 volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt
48 * clear register
49 */
50 }intreg;
51 };
52
53 /**
54 * \brief CTRL register bit definitions
55 *
56 */
57 enum ctrl_reg_bits_t {
58 CTRL_REG_ENUM_ENABLE_INDEX = 0,
59 CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1,
60 CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2,
61 CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3
62 };
63
64 /**
65 * \brief INTSTATUS/INTCLEAR register bit definitions
66 *
67 */
68 enum interrupt_reg_bits_t {
69 INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0
70 };
71
timer_cmsdk_init(const struct timer_cmsdk_dev_t * dev)72 void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev)
73 {
74 struct timer_cmsdk_reg_map_t* register_map =
75 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
76
77 if (dev->data->is_initialized == 0) {
78 register_map->ctrl = 0;
79 register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD;
80 dev->data->is_initialized = 1;
81 }
82 }
83
timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t * dev)84 bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev)
85 {
86 return dev->data->is_initialized;
87 }
88
timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t * dev)89 void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev)
90 {
91 struct timer_cmsdk_reg_map_t* register_map =
92 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
93 SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
94 }
95
timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t * dev)96 void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev)
97 {
98 struct timer_cmsdk_reg_map_t* register_map =
99 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
100 CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
101 }
102
timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t * dev)103 bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev)
104 {
105 struct timer_cmsdk_reg_map_t* register_map =
106 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
107 return GET_BIT(register_map->ctrl,
108 CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
109 }
110
timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t * dev)111 void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev)
112 {
113 struct timer_cmsdk_reg_map_t* register_map =
114 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
115 CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
116 }
117
timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t * dev)118 void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev)
119 {
120 struct timer_cmsdk_reg_map_t* register_map =
121 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
122 SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
123 }
124
timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t * dev)125 bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev)
126 {
127 struct timer_cmsdk_reg_map_t* register_map =
128 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
129 return GET_BIT(register_map->ctrl,
130 CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
131 }
132
timer_cmsdk_enable(const struct timer_cmsdk_dev_t * dev)133 void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev)
134 {
135 struct timer_cmsdk_reg_map_t* register_map =
136 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
137 SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
138 }
139
timer_cmsdk_disable(const struct timer_cmsdk_dev_t * dev)140 void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev)
141 {
142 struct timer_cmsdk_reg_map_t* register_map =
143 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
144 CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
145 }
146
timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t * dev)147 bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev)
148 {
149 struct timer_cmsdk_reg_map_t* register_map =
150 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
151 return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
152 }
153
timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t * dev)154 void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev)
155 {
156 struct timer_cmsdk_reg_map_t* register_map =
157 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
158 SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
159 }
160
timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t * dev)161 void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev)
162 {
163 struct timer_cmsdk_reg_map_t* register_map =
164 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
165 CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
166 }
167
timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t * dev)168 bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev)
169 {
170 struct timer_cmsdk_reg_map_t* register_map =
171 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
172 return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
173 }
174
timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t * dev)175 bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev)
176 {
177 struct timer_cmsdk_reg_map_t* register_map =
178 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
179 return GET_BIT(register_map->intreg.intstatus,
180 INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
181 }
182
timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t * dev)183 void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev)
184 {
185 struct timer_cmsdk_reg_map_t* register_map =
186 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
187 SET_BIT(register_map->intreg.intclear,
188 INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
189 }
190
timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t * dev)191 uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev)
192 {
193 struct timer_cmsdk_reg_map_t* register_map =
194 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
195 return register_map->value;
196 }
197
timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t * dev,uint32_t reload)198 void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
199 uint32_t reload)
200 {
201 struct timer_cmsdk_reg_map_t* register_map =
202 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
203 register_map->reload = reload;
204 }
205
timer_cmsdk_reset(const struct timer_cmsdk_dev_t * dev)206 void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev)
207 {
208 struct timer_cmsdk_reg_map_t* register_map =
209 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
210 register_map->value = register_map->reload;
211 }
212
timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t * dev)213 uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev)
214 {
215 struct timer_cmsdk_reg_map_t* register_map =
216 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
217 return register_map->reload;
218 }
219
timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t * dev)220 uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev)
221 {
222 struct timer_cmsdk_reg_map_t* register_map =
223 (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
224 return register_map->reload - register_map->value;
225 }
226