1 /*
2 * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdbool.h>
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <device_mec5.h>
11 #include "mec_pcfg.h"
12 #include "mec_defs.h"
13 #include "mec_btimer_api.h"
14 #include "mec_ecia_api.h"
15 #include "mec_pcr_api.h"
16 #include "mec_retval.h"
17
18 #define MEC_BTIMER_FAST_ADDR_LOOKUP
19
20 #define MEC_BTIMER_GIRQ 23
21
22 #define MEC_BTIMER0_GIRQ_POS 0
23 #define MEC_BTIMER1_GIRQ_POS 1
24 #define MEC_BTIMER2_GIRQ_POS 2
25 #define MEC_BTIMER3_GIRQ_POS 3
26 #define MEC_BTIMER4_GIRQ_POS 4
27 #define MEC_BTIMER5_GIRQ_POS 5
28
29 #define MEC_BTIMER0_ECIA_INFO MEC5_ECIA_INFO(23, 0, 14, 136)
30 #define MEC_BTIMER1_ECIA_INFO MEC5_ECIA_INFO(23, 1, 14, 137)
31 #define MEC_BTIMER2_ECIA_INFO MEC5_ECIA_INFO(23, 2, 14, 138)
32 #define MEC_BTIMER3_ECIA_INFO MEC5_ECIA_INFO(23, 3, 14, 139)
33 #define MEC_BTIMER4_ECIA_INFO MEC5_ECIA_INFO(23, 4, 14, 140)
34 #define MEC_BTIMER5_ECIA_INFO MEC5_ECIA_INFO(23, 5, 14, 141)
35
36 #define MEC5_BTMR_PRESCALE_MSK0 (MEC_BTMR_CTRL_PRESCALE_Msk >> MEC_BTMR_CTRL_PRESCALE_Pos)
37
38 struct mec_btimer_info {
39 uintptr_t base_addr;
40 uint16_t pcr_id;
41 uint32_t devi;
42 };
43
44 static const struct mec_btimer_info btimer_instances[MEC5_BASIC_TIMER_INSTANCES] = {
45 { MEC_BTMR0_BASE, MEC_PCR_BTMR0, MEC_BTIMER0_ECIA_INFO },
46 { MEC_BTMR1_BASE, MEC_PCR_BTMR1, MEC_BTIMER1_ECIA_INFO },
47 { MEC_BTMR2_BASE, MEC_PCR_BTMR2, MEC_BTIMER2_ECIA_INFO },
48 { MEC_BTMR3_BASE, MEC_PCR_BTMR3, MEC_BTIMER3_ECIA_INFO },
49 { MEC_BTMR4_BASE, MEC_PCR_BTMR4, MEC_BTIMER4_ECIA_INFO },
50 { MEC_BTMR5_BASE, MEC_PCR_BTMR5, MEC_BTIMER5_ECIA_INFO },
51 };
52
53 #ifdef MEC_BTIMER_FAST_ADDR_LOOKUP
54 /* Basic timers are spaced every 32 (0x20) bytes in AHB address space.
55 * All six instances are contiguous therefore we can calculate the
56 * zero based instance number from the address more quickly than using
57 * the lookup table.
58 */
btimer_fast_idx(struct mec_btmr_regs * regs)59 static inline uint32_t btimer_fast_idx(struct mec_btmr_regs *regs)
60 {
61 return (((uint32_t)regs >> 5) & 0x7u);
62 }
63
find_btimer_info(uintptr_t base_addr)64 static struct mec_btimer_info const *find_btimer_info(uintptr_t base_addr)
65 {
66 return &btimer_instances[btimer_fast_idx((struct mec_btmr_regs *)base_addr)];
67 }
68 #else
find_btimer_info(uintptr_t base_addr)69 static struct mec_btimer_info const *find_btimer_info(uintptr_t base_addr)
70 {
71 for (size_t i = 0; i < MEC5_BASIC_TIMER_INSTANCES; i++) {
72 if (base_addr == btimer_instances[i].base_addr) {
73 return &btimer_instances[i];
74 }
75 }
76
77 return NULL;
78 }
79 #endif /* MEC_BTIMER_FAST_ADDR_LOOKUP */
80
find_btimer_index(uintptr_t base_addr)81 static int find_btimer_index(uintptr_t base_addr)
82 {
83 for (int i = 0; i < (int)MEC5_BASIC_TIMER_INSTANCES; i++) {
84 if (base_addr == btimer_instances[i].base_addr) {
85 return i;
86 }
87 }
88
89 return -1;
90 }
91
92 /* ---- Public API ---- */
93
94 /* Initialize a basic timer instance.
95 * timer frequency = max_freq / (pre_scale + 1)
96 * pre_scale = b[31:16] of Control register.
97 */
mec_hal_btimer_init(struct mec_btmr_regs * regs,uint32_t freq_div,uint32_t count,uint32_t flags)98 int mec_hal_btimer_init(struct mec_btmr_regs *regs, uint32_t freq_div,
99 uint32_t count, uint32_t flags)
100 {
101 const struct mec_btimer_info *info = find_btimer_info((uintptr_t)regs);
102
103 if (!info || !freq_div) {
104 return MEC_RET_ERR_INVAL;
105 }
106
107 mec_hal_girq_ctrl(info->devi, 0);
108 mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
109
110 regs->CTRL = MEC_BIT(MEC_BTMR_CTRL_RESET_Pos);
111 regs->CTRL = ((freq_div - 1u) & MEC5_BTMR_PRESCALE_MSK0) << MEC_BTMR_CTRL_PRESCALE_Pos;
112 regs->PRELOAD = count;
113 regs->COUNT = count;
114
115 mec_hal_girq_ctrl(info->devi, 1);
116
117 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos);
118
119 if (flags & MEC_BIT(MEC5_BTIMER_CFG_FLAG_AUTO_RELOAD_POS)) {
120 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_RESTART_Pos);
121 }
122
123 if (flags & MEC_BIT(MEC5_BTIMER_CFG_FLAG_COUNT_UP_POS)) {
124 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_CNT_DIR_Pos);
125 }
126
127 if (flags & MEC_BIT(MEC5_BTIMER_CFG_FLAG_INTR_EN_POS)) {
128 regs->IEN |= MEC_BIT(MEC_BTMR_IEN_EVENT_Pos);
129 }
130
131 if (flags & MEC_BIT(MEC5_BTIMER_CFG_FLAG_START_POS)) {
132 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_START_Pos);
133 }
134
135 return MEC_RET_OK;
136 }
137
mec_hal_btimer_has_counter32(struct mec_btmr_regs * regs)138 int mec_hal_btimer_has_counter32(struct mec_btmr_regs *regs)
139 {
140 int idx = find_btimer_index((uint32_t)regs);
141
142 if ((idx >= 0) && (idx < 32)) {
143 if (MEC_BIT(idx) & MEC5_BASIC_TIMER_32_MSK) {
144 return 1;
145 }
146 }
147
148 return 0;
149 }
150
mec_hal_btimer_reset(struct mec_btmr_regs * regs,uint32_t flags)151 int mec_hal_btimer_reset(struct mec_btmr_regs *regs, uint32_t flags)
152 {
153 uint32_t ctrl = 0, msk = 0;
154
155 if (!regs) {
156 return MEC_RET_ERR_INVAL;
157 }
158
159 if (flags & MEC_BIT(MEC5_BTMR_RST_PRESERVE_FDIV_POS)) {
160 msk |= MEC_BTMR_CTRL_PRESCALE_Msk;
161 }
162
163 if (flags & MEC_BIT(MEC5_BTMR_RST_PRESERVE_DIR_POS)) {
164 msk |= MEC_BTMR_CTRL_CNT_DIR_Msk;
165 }
166
167 ctrl = regs->CTRL;
168 regs->CTRL = MEC_BIT(MEC_BTMR_CTRL_RESET_Pos);
169 mec_hal_btimer_intr_clr(regs);
170
171 if (msk) {
172 regs->CTRL = (regs->CTRL & (uint32_t)~msk) | (ctrl & msk);
173 }
174
175 return 0;
176 }
177
mec_hal_btimer_is_enabled(struct mec_btmr_regs * regs)178 bool mec_hal_btimer_is_enabled(struct mec_btmr_regs *regs)
179 {
180 if (regs->CTRL & MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos)) {
181 return true;
182 }
183
184 return false;
185 }
186
mec_hal_btimer_freq(struct mec_btmr_regs * regs)187 uint32_t mec_hal_btimer_freq(struct mec_btmr_regs *regs)
188 {
189 uint32_t freqhz = 0u;
190
191 if (regs) {
192 freqhz = (regs->CTRL & MEC_BTMR_CTRL_PRESCALE_Msk) >> MEC_BTMR_CTRL_PRESCALE_Pos;
193 freqhz = MEC5_BTIMER_MAX_FREQ_HZ / (freqhz + 1u); /* truncates */
194 }
195
196 return freqhz;
197 }
198
mec_hal_btimer_girq_ctrl(struct mec_btmr_regs * regs,uint8_t enable)199 int mec_hal_btimer_girq_ctrl(struct mec_btmr_regs *regs, uint8_t enable)
200 {
201 const struct mec_btimer_info *info = find_btimer_info((uintptr_t)regs);
202
203 if (!info) {
204 return MEC_RET_ERR_INVAL;
205 }
206
207 mec_hal_girq_ctrl(info->devi, enable);
208
209 return MEC_RET_OK;
210 }
211
mec_hal_btimer_girq_status_clr(struct mec_btmr_regs * regs)212 int mec_hal_btimer_girq_status_clr(struct mec_btmr_regs *regs)
213 {
214 const struct mec_btimer_info *info = find_btimer_info((uintptr_t)regs);
215
216 if (!regs) {
217 return MEC_RET_ERR_INVAL;
218 }
219
220 mec_hal_girq_clr_src(info->devi);
221
222 return MEC_RET_OK;
223 }
224
mec_hal_btimer_pre_and_reload(struct mec_btmr_regs * regs,uint32_t preload,uint8_t do_reload)225 void mec_hal_btimer_pre_and_reload(struct mec_btmr_regs *regs, uint32_t preload,
226 uint8_t do_reload)
227 {
228 uint32_t ctrl = regs->CTRL;
229
230 if (do_reload) {
231 ctrl |= (MEC_BIT(MEC_BTMR_CTRL_RELOAD_Pos) | MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos)
232 | MEC_BIT(MEC_BTMR_CTRL_START_Pos));
233 regs->PRELOAD = preload;
234 regs->CTRL = ctrl;
235 } else {
236 regs->PRELOAD = preload;
237 }
238 }
239
mec_hal_btimer_start_load(struct mec_btmr_regs * regs,uint32_t initial_count,uint32_t flags)240 void mec_hal_btimer_start_load(struct mec_btmr_regs *regs, uint32_t initial_count,
241 uint32_t flags)
242 {
243 uint32_t ien = 0;
244 uint32_t ctrl = regs->CTRL;
245
246 ctrl |= (MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos) | MEC_BIT(MEC_BTMR_CTRL_START_Pos));
247
248 if (flags & MEC_BIT(MEC5_BTIMER_START_FLAG_IEN_POS)) {
249 ien |= MEC_BIT(MEC_BTMR_IEN_EVENT_Pos);
250 }
251
252 if (flags & MEC_BIT(MEC5_BTIMER_START_FLAG_AUTO_POS)) {
253 ctrl |= MEC_BIT(MEC_BTMR_CTRL_RESTART_Pos);
254 regs->PRELOAD = initial_count;
255 } else {
256 ctrl &= (uint32_t)~MEC_BIT(MEC_BTMR_CTRL_RESTART_Pos);
257 }
258
259 if (flags & MEC_BIT(MEC5_BTIMER_START_FLAG_DIR_UP)) {
260 ctrl |= MEC_BIT(MEC_BTMR_CTRL_CNT_DIR_Pos);
261 } else {
262 ctrl &= (uint32_t)~MEC_BIT(MEC_BTMR_CTRL_CNT_DIR_Pos);
263 }
264
265 regs->STATUS = MEC_BIT(MEC_BTMR_STATUS_EVENT_Pos);
266 regs->COUNT = initial_count;
267 regs->CTRL = ctrl;
268 regs->IEN = ien;
269 }
270
mec_hal_btimer_is_started(struct mec_btmr_regs * regs)271 bool mec_hal_btimer_is_started(struct mec_btmr_regs *regs)
272 {
273 uint32_t msk = (MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos) | MEC_BIT(MEC_BTMR_CTRL_START_Pos));
274
275 if ((regs->CTRL & msk) == msk) {
276 return true;
277 }
278
279 return false;
280 }
281
mec_hal_btimer_is_counting_up(struct mec_btmr_regs * regs)282 bool mec_hal_btimer_is_counting_up(struct mec_btmr_regs *regs)
283 {
284 if (regs->CTRL & MEC_BIT(MEC_BTMR_CTRL_CNT_DIR_Pos)) {
285 return true;
286 }
287
288 return false;
289 }
290
mec_hal_btimer_auto_restart(struct mec_btmr_regs * regs,uint8_t enable)291 void mec_hal_btimer_auto_restart(struct mec_btmr_regs *regs, uint8_t enable)
292 {
293 if (enable) {
294 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_RESTART_Pos);
295 } else {
296 regs->CTRL &= (uint32_t)~MEC_BIT(MEC_BTMR_CTRL_RESTART_Pos);
297 }
298 }
299
mec_hal_btimer_is_auto_restart(struct mec_btmr_regs * regs)300 bool mec_hal_btimer_is_auto_restart(struct mec_btmr_regs *regs)
301 {
302 if (regs->CTRL & MEC_BIT(MEC_BTMR_CTRL_RESTART_Pos)) {
303 return true;
304 }
305 return false;
306 }
307
308 /* Works counter start is 1 or 0.
309 * Warning: there is race condition if counter is close to its limit.
310 */
mec_hal_btimer_reload_run(struct mec_btmr_regs * regs,uint32_t new_count)311 void mec_hal_btimer_reload_run(struct mec_btmr_regs *regs, uint32_t new_count)
312 {
313 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_HALT_Pos);
314 regs->COUNT = new_count;
315 regs->CTRL &= (uint32_t)~MEC_BIT(MEC_BTMR_CTRL_HALT_Pos);
316 }
317
mec_hal_btimer_intr_clr(struct mec_btmr_regs * regs)318 void mec_hal_btimer_intr_clr(struct mec_btmr_regs *regs)
319 {
320 uint32_t devi = btimer_instances[btimer_fast_idx(regs)].devi;
321
322 regs->STATUS = MEC_BIT(MEC_BTMR_STATUS_EVENT_Pos);
323 mec_hal_girq_clr_src(devi);
324 }
325
mec_hal_btimer_intr_en(struct mec_btmr_regs * regs,uint8_t enable)326 void mec_hal_btimer_intr_en(struct mec_btmr_regs *regs, uint8_t enable)
327 {
328 if (enable) {
329 regs->IEN |= MEC_BIT(MEC_BTMR_IEN_EVENT_Pos);
330 } else {
331 regs->IEN &= (uint32_t)~MEC_BIT(MEC_BTMR_IEN_EVENT_Pos);
332 }
333 }
334
335 /* ---- Power Management ----
336 * The basic timer keeps its PCR CLK_REQ signal asserted if it is
337 * enabled and counting ignoring the PCR SLP_REQ signal. We must
338 * save and clear each timers enable bit to cause PCR CLK_REQ to
339 * deassert.
340 */
341
342 static uint8_t btimer_pm_save_buf[MEC5_BASIC_TIMER_INSTANCES];
343
mec_hal_btimer_pm_save_disable(void)344 void mec_hal_btimer_pm_save_disable(void)
345 {
346 for (int i = 0; i < MEC5_BASIC_TIMER_INSTANCES; i++) {
347 struct mec_btmr_regs *regs = (struct mec_btmr_regs *)btimer_instances[i].base_addr;
348
349 btimer_pm_save_buf[i] = (uint8_t)(regs->CTRL & MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos));
350 regs->CTRL &= (uint32_t)~MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos);
351 }
352 }
353
mec_hal_btimer_pm_restore(void)354 void mec_hal_btimer_pm_restore(void)
355 {
356 for (int i = 0; i < MEC5_BASIC_TIMER_INSTANCES; i++) {
357 struct mec_btmr_regs *regs = (struct mec_btmr_regs *)btimer_instances[i].base_addr;
358
359 if (btimer_pm_save_buf[i]) {
360 regs->CTRL |= MEC_BIT(MEC_BTMR_CTRL_ENABLE_Pos);
361 }
362 }
363 }
364
365 /* end mec_btimer.c */
366