1 /******************************************************************************
2 *
3 * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4 * Analog Devices, Inc.),
5 * Copyright (C) 2023-2024 Analog Devices, Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20
21 /* **** Includes **** */
22 #include <stddef.h>
23 #include "mxc_assert.h"
24 #include "tmr.h"
25 #include "tmr_revc.h"
26 #include "gpio.h"
27 #include "mxc_pins.h"
28 #include "mxc_lock.h"
29
30 /* **** Definitions **** */
31
32 /* **** Functions **** */
MXC_TMR_RevC_Init(mxc_tmr_regs_t * tmr,mxc_tmr_cfg_t * cfg)33 int MXC_TMR_RevC_Init(mxc_tmr_regs_t *tmr, mxc_tmr_cfg_t *cfg)
34 {
35 int tmr_id = MXC_TMR_GET_IDX(tmr);
36 MXC_ASSERT(tmr_id >= 0);
37
38 if (cfg == NULL) {
39 return E_NULL_PTR;
40 }
41
42 // Clear interrupt flag
43 tmr->intr |= MXC_F_TMR_INTR_IRQ;
44
45 // Set the prescaler
46 switch (cfg->pres) {
47 case MXC_TMR_PRES_1:
48 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_1);
49 break;
50
51 case MXC_TMR_PRES_2:
52 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_2);
53 break;
54
55 case MXC_TMR_PRES_4:
56 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_4);
57 break;
58
59 case MXC_TMR_PRES_8:
60 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_8);
61 break;
62
63 case MXC_TMR_PRES_16:
64 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_16);
65 break;
66
67 case MXC_TMR_PRES_32:
68 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_32);
69 break;
70
71 case MXC_TMR_PRES_64:
72 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_64);
73 break;
74
75 case MXC_TMR_PRES_128:
76 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_128);
77 break;
78
79 case MXC_TMR_PRES_256:
80 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_256);
81 break;
82
83 case MXC_TMR_PRES_512:
84 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_512);
85 break;
86
87 case MXC_TMR_PRES_1024:
88 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_1024);
89 break;
90
91 case MXC_TMR_PRES_2048:
92 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_2048);
93 break;
94
95 case MXC_TMR_PRES_4096:
96 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_4096);
97 break;
98
99 case MXC_TMR_PRES_8192:
100 tmr->cn |= (MXC_S_TMR_CN_PRES_DIV_BY_8192);
101 break;
102 }
103
104 MXC_TMR_RevC_ConfigGeneric(tmr, cfg);
105
106 return E_NO_ERROR;
107 }
108
MXC_TMR_RevC_ConfigGeneric(mxc_tmr_regs_t * tmr,mxc_tmr_cfg_t * cfg)109 void MXC_TMR_RevC_ConfigGeneric(mxc_tmr_regs_t *tmr, mxc_tmr_cfg_t *cfg)
110 {
111 int tmr_id = MXC_TMR_GET_IDX(tmr);
112 MXC_ASSERT(tmr_id >= 0);
113
114 if (cfg == NULL) {
115 return;
116 }
117
118 tmr->cn |= (MXC_F_TMR_CN_TEN);
119 tmr->cn |= (cfg->mode << MXC_F_TMR_CN_TMODE_POS);
120 tmr->cn |= (cfg->pol << MXC_F_TMR_CN_TPOL_POS);
121 //enable timer interrupt if needed
122 tmr->cnt = 0x1;
123 tmr->cmp = (cfg->cmp_cnt);
124 }
125
MXC_TMR_RevC_Shutdown(mxc_tmr_regs_t * tmr)126 void MXC_TMR_RevC_Shutdown(mxc_tmr_regs_t *tmr)
127 {
128 int tmr_id = MXC_TMR_GET_IDX(tmr);
129 MXC_ASSERT(tmr_id >= 0);
130
131 // Disable timer and clear settings
132 tmr->cn = 0;
133 }
134
MXC_TMR_RevC_Start(mxc_tmr_regs_t * tmr)135 void MXC_TMR_RevC_Start(mxc_tmr_regs_t *tmr)
136 {
137 int tmr_id = MXC_TMR_GET_IDX(tmr);
138 MXC_ASSERT(tmr_id >= 0);
139
140 tmr->cn |= MXC_F_TMR_CN_TEN;
141 }
142
MXC_TMR_RevC_Stop(mxc_tmr_regs_t * tmr)143 void MXC_TMR_RevC_Stop(mxc_tmr_regs_t *tmr)
144 {
145 int tmr_id = MXC_TMR_GET_IDX(tmr);
146 MXC_ASSERT(tmr_id >= 0);
147
148 tmr->cn &= ~MXC_F_TMR_CN_TEN;
149 }
150
MXC_TMR_RevC_SetPWM(mxc_tmr_regs_t * tmr,uint32_t pwm)151 int MXC_TMR_RevC_SetPWM(mxc_tmr_regs_t *tmr, uint32_t pwm)
152 {
153 int tmr_id = MXC_TMR_GET_IDX(tmr);
154 MXC_ASSERT(tmr_id >= 0);
155
156 if (pwm > (tmr->cmp)) {
157 return E_BAD_PARAM;
158 }
159
160 while (tmr->cnt >= pwm) {}
161
162 tmr->pwm = pwm;
163
164 return E_NO_ERROR;
165 }
166
MXC_TMR_RevC_GetCompare(mxc_tmr_regs_t * tmr)167 uint32_t MXC_TMR_RevC_GetCompare(mxc_tmr_regs_t *tmr)
168 {
169 int tmr_id = MXC_TMR_GET_IDX(tmr);
170 MXC_ASSERT(tmr_id >= 0);
171
172 return tmr->cmp;
173 }
174
MXC_TMR_RevC_GetCapture(mxc_tmr_regs_t * tmr)175 uint32_t MXC_TMR_RevC_GetCapture(mxc_tmr_regs_t *tmr)
176 {
177 int tmr_id = MXC_TMR_GET_IDX(tmr);
178 MXC_ASSERT(tmr_id >= 0);
179
180 return tmr->pwm; //check this
181 }
182
MXC_TMR_RevC_GetCount(mxc_tmr_regs_t * tmr)183 uint32_t MXC_TMR_RevC_GetCount(mxc_tmr_regs_t *tmr)
184 {
185 int tmr_id = MXC_TMR_GET_IDX(tmr);
186 MXC_ASSERT(tmr_id >= 0);
187
188 return tmr->cnt;
189 }
190
MXC_TMR_RevC_GetPeriod(mxc_tmr_regs_t * tmr,mxc_tmr_clock_t clock,uint32_t prescalar,uint32_t frequency)191 uint32_t MXC_TMR_RevC_GetPeriod(mxc_tmr_regs_t *tmr, mxc_tmr_clock_t clock, uint32_t prescalar,
192 uint32_t frequency)
193 {
194 uint32_t periodTicks;
195 int tmr_id = MXC_TMR_GET_IDX(tmr);
196 MXC_ASSERT(tmr_id >= 0);
197
198 switch (clock) {
199 case MXC_TMR_EXT_CLK:
200 periodTicks = 32768 / (frequency * prescalar);
201 break;
202
203 case MXC_TMR_HFIO_CLK:
204 periodTicks = PeripheralClock / (frequency * prescalar);
205 break;
206
207 case MXC_TMR_NANORING_CLK:
208 periodTicks = 8000 / (frequency * prescalar);
209 break;
210
211 default:
212 return E_BAD_PARAM;
213 break;
214 }
215 return periodTicks;
216 }
217
MXC_TMR_RevC_ClearFlags(mxc_tmr_regs_t * tmr)218 void MXC_TMR_RevC_ClearFlags(mxc_tmr_regs_t *tmr)
219 {
220 int tmr_id = MXC_TMR_GET_IDX(tmr);
221 MXC_ASSERT(tmr_id >= 0);
222
223 tmr->intr = 1;
224 }
225
MXC_TMR_RevC_GetFlags(mxc_tmr_regs_t * tmr)226 uint32_t MXC_TMR_RevC_GetFlags(mxc_tmr_regs_t *tmr)
227 {
228 int tmr_id = MXC_TMR_GET_IDX(tmr);
229 MXC_ASSERT(tmr_id >= 0);
230
231 return tmr->intr;
232 }
233
MXC_TMR_RevC_SetCompare(mxc_tmr_regs_t * tmr,uint32_t cmp_cnt)234 void MXC_TMR_RevC_SetCompare(mxc_tmr_regs_t *tmr, uint32_t cmp_cnt)
235 {
236 int tmr_id = MXC_TMR_GET_IDX(tmr);
237 MXC_ASSERT(tmr_id >= 0);
238
239 tmr->cmp = cmp_cnt;
240 }
241
MXC_TMR_RevC_SetCount(mxc_tmr_regs_t * tmr,uint32_t cnt)242 void MXC_TMR_RevC_SetCount(mxc_tmr_regs_t *tmr, uint32_t cnt)
243 {
244 int tmr_id = MXC_TMR_GET_IDX(tmr);
245 MXC_ASSERT(tmr_id >= 0);
246
247 tmr->cnt = cnt;
248 }
249
MXC_TMR_RevC_TO_Start(mxc_tmr_regs_t * tmr,uint32_t us)250 void MXC_TMR_RevC_TO_Start(mxc_tmr_regs_t *tmr, uint32_t us)
251 {
252 uint64_t ticks;
253 int clk_shift = 0;
254 int tmr_id = MXC_TMR_GET_IDX(tmr);
255 MXC_ASSERT(tmr_id >= 0);
256
257 if (us == 0) {
258 return;
259 }
260
261 ticks = (uint64_t)us * (uint64_t)PeripheralClock / (uint64_t)1000000;
262
263 while (ticks > 0xFFFFFFFFUL) {
264 ticks >>= 1;
265 ++clk_shift;
266 }
267
268 mxc_tmr_pres_t prescale =
269 (mxc_tmr_pres_t)(((tmr->cn & MXC_F_TMR_CN_PRES) >> MXC_F_TMR_CN_PRES_POS) |
270 ((((tmr->cn & MXC_F_TMR_CN_PRES3) >> (MXC_F_TMR_CN_PRES3_POS)) << 3)));
271 mxc_tmr_cfg_t cfg;
272
273 // Initialize the timer in one-shot mode
274 cfg.pres = prescale;
275 cfg.clock = MXC_TMR_HFIO_CLK;
276 cfg.mode = MXC_TMR_MODE_ONESHOT;
277 cfg.cmp_cnt = ticks;
278 cfg.pol = 0;
279
280 MXC_TMR_Stop(tmr);
281 MXC_TMR_Init(tmr, &cfg);
282 MXC_TMR_ClearFlags(tmr);
283 MXC_TMR_Start(tmr);
284 }
285
MXC_TMR_RevC_GetTime(mxc_tmr_regs_t * tmr,uint32_t ticks,uint32_t * time,mxc_tmr_unit_t * units)286 int MXC_TMR_RevC_GetTime(mxc_tmr_regs_t *tmr, uint32_t ticks, uint32_t *time, mxc_tmr_unit_t *units)
287 {
288 int tmr_id = MXC_TMR_GET_IDX(tmr);
289 MXC_ASSERT(tmr_id >= 0);
290
291 uint64_t temp_time = 0;
292 uint32_t timerClock = PeripheralClock;
293 uint32_t prescale = (((tmr->cn & MXC_F_TMR_CN_PRES) >> MXC_F_TMR_CN_PRES_POS) |
294 ((((tmr->cn & MXC_F_TMR_CN_PRES3) >> (MXC_F_TMR_CN_PRES3_POS)) << 3)));
295
296 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000000);
297
298 if (!(temp_time & 0xffffffff00000000)) {
299 *time = temp_time;
300 *units = MXC_TMR_UNIT_NANOSEC;
301 return E_NO_ERROR;
302 }
303
304 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000);
305
306 if (!(temp_time & 0xffffffff00000000)) {
307 *time = temp_time;
308 *units = MXC_TMR_UNIT_MICROSEC;
309 return E_NO_ERROR;
310 }
311
312 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / timerClock;
313
314 if (!(temp_time & 0xffffffff00000000)) {
315 *time = temp_time;
316 *units = MXC_TMR_UNIT_MILLISEC;
317 return E_NO_ERROR;
318 }
319
320 temp_time = (uint64_t)ticks * (1 << (prescale & 0xF)) / timerClock;
321
322 if (!(temp_time & 0xffffffff00000000)) {
323 *time = temp_time;
324 *units = MXC_TMR_UNIT_SEC;
325 return E_NO_ERROR;
326 }
327
328 return E_INVALID;
329 }
330