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