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 <stdbool.h>
24 #include "mxc_assert.h"
25 #include "tmr.h"
26 #include "tmr_revb.h"
27 #include "gpio.h"
28 #include "mxc_pins.h"
29 #include "mxc_lock.h"
30
31 /* **** Definitions **** */
32 #define TIMER_16A_OFFSET 0
33 #define TIMER_16B_OFFSET 16
34
35 typedef struct {
36 bool configured;
37 uint32_t freq;
38 } mxc_tmr_revb_clksrc_freq_t;
39
40 static mxc_tmr_revb_clksrc_freq_t tmr_clksrc[MXC_CFG_TMR_INSTANCES];
41
42 /* **** Functions **** */
MXC_TMR_RevB_Init(mxc_tmr_revb_regs_t * tmr,mxc_tmr_cfg_t * cfg,uint8_t clk_src)43 int MXC_TMR_RevB_Init(mxc_tmr_revb_regs_t *tmr, mxc_tmr_cfg_t *cfg, uint8_t clk_src)
44 {
45 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
46 (void)tmr_id;
47 MXC_ASSERT(tmr_id >= 0);
48
49 if (cfg == NULL) {
50 return E_NULL_PTR;
51 }
52
53 // Default 32 bit timer
54 if (cfg->bitMode & (MXC_TMR_BIT_MODE_16A | MXC_TMR_BIT_MODE_16B)) {
55 tmr->ctrl1 &= ~MXC_F_TMR_REVB_CTRL1_CASCADE;
56 } else {
57 tmr->ctrl1 |= MXC_F_TMR_REVB_CTRL1_CASCADE;
58 }
59
60 // Clear interrupt flag
61 tmr->intfl |= (MXC_F_TMR_REVB_INTFL_IRQ_A | MXC_F_TMR_REVB_INTFL_IRQ_B);
62
63 // Select clock Source and prescaler
64 // Note: For 32-bit cascade mode, TMR A and TMR B clock sources must be
65 // the same to ensure proper operation. (See MAX32670 UG Rev 4 Section 13.4)
66 if (cfg->bitMode == TMR_BIT_MODE_16A || cfg->bitMode == TMR_BIT_MODE_32) {
67 MXC_SETFIELD(tmr->ctrl1, MXC_F_TMR_CTRL1_CLKSEL_A,
68 (clk_src << MXC_F_TMR_CTRL1_CLKSEL_A_POS));
69 MXC_SETFIELD(tmr->ctrl0, MXC_F_TMR_CTRL0_CLKDIV_A, cfg->pres);
70 }
71 if (cfg->bitMode == TMR_BIT_MODE_16B || cfg->bitMode == TMR_BIT_MODE_32) {
72 MXC_SETFIELD(tmr->ctrl1, MXC_F_TMR_CTRL1_CLKSEL_B,
73 (clk_src << MXC_F_TMR_CTRL1_CLKSEL_B_POS));
74 // mxc_tmr_pres_t is for for CLKDIV_A register settings [4:7]
75 // Field positions for CLKDIV_B are Located at [16:19]. Shift 12 more bits.
76 MXC_SETFIELD(tmr->ctrl0, MXC_F_TMR_CTRL0_CLKDIV_B, (cfg->pres) << 12);
77 }
78
79 //TIMER_16B only supports compare, oneshot and continuous modes.
80 switch (cfg->mode) {
81 case MXC_TMR_MODE_ONESHOT:
82 MXC_TMR_RevB_ConfigGeneric((mxc_tmr_revb_regs_t *)tmr, cfg);
83 break;
84
85 case MXC_TMR_MODE_CONTINUOUS:
86 MXC_TMR_RevB_ConfigGeneric((mxc_tmr_revb_regs_t *)tmr, cfg);
87 break;
88
89 case MXC_TMR_MODE_COUNTER:
90 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
91 return E_NOT_SUPPORTED;
92 }
93
94 MXC_TMR_RevB_ConfigGeneric(tmr, cfg);
95 break;
96
97 case MXC_TMR_MODE_CAPTURE:
98 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
99 return E_NOT_SUPPORTED;
100 }
101
102 MXC_TMR_RevB_ConfigGeneric(tmr, cfg);
103 break;
104
105 case MXC_TMR_MODE_COMPARE:
106 MXC_TMR_RevB_ConfigGeneric((mxc_tmr_revb_regs_t *)tmr, cfg);
107 break;
108
109 case MXC_TMR_MODE_GATED:
110 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
111 return E_NOT_SUPPORTED;
112 }
113
114 MXC_TMR_RevB_ConfigGeneric(tmr, cfg);
115 break;
116
117 case MXC_TMR_MODE_CAPTURE_COMPARE:
118 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
119 return E_NOT_SUPPORTED;
120 }
121
122 MXC_TMR_RevB_ConfigGeneric(tmr, cfg);
123 break;
124
125 case MXC_TMR_MODE_DUAL_EDGE:
126 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
127 return E_NOT_SUPPORTED;
128 }
129
130 MXC_TMR_RevB_ConfigGeneric(tmr, cfg);
131 break;
132
133 case MXC_TMR_MODE_PWM:
134 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
135 return E_NOT_SUPPORTED;
136 }
137
138 MXC_TMR_RevB_ConfigGeneric((mxc_tmr_revb_regs_t *)tmr, cfg);
139 break;
140 }
141
142 return E_NO_ERROR;
143 }
144
MXC_TMR_RevB_SetClockSourceFreq(mxc_tmr_revb_regs_t * tmr,int clksrc_freq)145 void MXC_TMR_RevB_SetClockSourceFreq(mxc_tmr_revb_regs_t *tmr, int clksrc_freq)
146 {
147 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
148 (void)tmr_id;
149 MXC_ASSERT(tmr_id >= 0);
150
151 tmr_clksrc[tmr_id].configured = true;
152 tmr_clksrc[tmr_id].freq = clksrc_freq;
153 }
154
MXC_TMR_RevB_GetClockSourceFreq(mxc_tmr_revb_regs_t * tmr)155 int MXC_TMR_RevB_GetClockSourceFreq(mxc_tmr_revb_regs_t *tmr)
156 {
157 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
158 (void)tmr_id;
159 MXC_ASSERT(tmr_id >= 0);
160
161 if (tmr_clksrc[tmr_id].configured == false) {
162 return E_BAD_STATE;
163 }
164
165 return tmr_clksrc[tmr_id].freq;
166 }
167
MXC_TMR_RevB_ConfigGeneric(mxc_tmr_revb_regs_t * tmr,mxc_tmr_cfg_t * cfg)168 void MXC_TMR_RevB_ConfigGeneric(mxc_tmr_revb_regs_t *tmr, mxc_tmr_cfg_t *cfg)
169 {
170 uint32_t timerOffset;
171 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
172 (void)tmr_id;
173 MXC_ASSERT(tmr_id >= 0);
174
175 if (cfg == NULL) {
176 return;
177 }
178
179 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
180 timerOffset = TIMER_16B_OFFSET;
181 } else {
182 timerOffset = TIMER_16A_OFFSET;
183 }
184
185 tmr->ctrl0 |= (MXC_F_TMR_REVB_CTRL0_CLKEN_A << timerOffset);
186 while (!(tmr->ctrl1 & (MXC_F_TMR_REVB_CTRL1_CLKRDY_A << timerOffset))) {}
187
188 tmr->ctrl0 |= (cfg->mode << timerOffset);
189 tmr->ctrl0 |= ((cfg->pol << MXC_F_TMR_REVB_CTRL0_POL_A_POS) << timerOffset);
190 //enable timer interrupt if needed
191 tmr->cnt = (0x1 << timerOffset);
192 while (!(tmr->intfl & (MXC_F_TMR_REVB_INTFL_WRDONE_A << timerOffset))) {}
193
194 tmr->cmp = (cfg->cmp_cnt << timerOffset);
195 #if TARGET_NUM == 32655 || TARGET_NUM == 78000 || TARGET_NUM == 32690 || TARGET_NUM == 78002
196 tmr->ctrl1 &= ~(MXC_F_TMR_REVB_CTRL1_OUTEN_A << timerOffset);
197 #else
198 tmr->ctrl1 |= (MXC_F_TMR_REVB_CTRL1_OUTEN_A << timerOffset);
199 #endif
200
201 // If configured as TIMER_16B then enable the interrupt and start the timer
202 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
203 tmr->ctrl1 |= MXC_F_TMR_REVB_CTRL1_IE_B;
204
205 tmr->ctrl0 |= MXC_F_TMR_REVB_CTRL0_EN_B;
206 while (!(tmr->ctrl1 & MXC_F_TMR_REVB_CTRL1_CLKEN_B)) {}
207 }
208 }
209
MXC_TMR_RevB_Shutdown(mxc_tmr_revb_regs_t * tmr)210 void MXC_TMR_RevB_Shutdown(mxc_tmr_revb_regs_t *tmr)
211 {
212 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
213 (void)tmr_id;
214 MXC_ASSERT(tmr_id >= 0);
215
216 // Stop timer before disable it.
217 MXC_TMR_RevB_Stop(tmr);
218 // Disable timer and clear settings
219 tmr->ctrl0 = 0;
220 while (tmr->ctrl1 & MXC_F_TMR_REVB_CTRL1_CLKRDY_A) {}
221 tmr_clksrc[tmr_id].configured = false;
222 }
223
MXC_TMR_RevB_Start(mxc_tmr_revb_regs_t * tmr)224 void MXC_TMR_RevB_Start(mxc_tmr_revb_regs_t *tmr)
225 {
226 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
227 (void)tmr_id;
228 MXC_ASSERT(tmr_id >= 0);
229
230 tmr->ctrl0 |= MXC_F_TMR_REVB_CTRL0_EN_A;
231 while (!(tmr->ctrl1 & MXC_F_TMR_REVB_CTRL1_CLKEN_A)) {}
232 }
233
MXC_TMR_RevB_Stop(mxc_tmr_revb_regs_t * tmr)234 void MXC_TMR_RevB_Stop(mxc_tmr_revb_regs_t *tmr)
235 {
236 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
237 (void)tmr_id;
238 MXC_ASSERT(tmr_id >= 0);
239
240 tmr->ctrl0 &= ~MXC_F_TMR_REVB_CTRL0_EN_A;
241 }
242
MXC_TMR_RevB_SetPWM(mxc_tmr_revb_regs_t * tmr,uint32_t pwm)243 int MXC_TMR_RevB_SetPWM(mxc_tmr_revb_regs_t *tmr, uint32_t pwm)
244 {
245 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
246 (void)tmr_id;
247 MXC_ASSERT(tmr_id >= 0);
248
249 if (pwm > (tmr->cmp)) {
250 return E_BAD_PARAM;
251 }
252
253 bool timera_is_running = tmr->ctrl0 & MXC_F_TMR_CTRL0_EN_A;
254 bool timerb_is_running = tmr->ctrl0 & MXC_F_TMR_CTRL0_EN_B;
255
256 if (timera_is_running || timerb_is_running) {
257 MXC_TMR_RevB_ClearFlags(tmr); // Clear flags so we can catch the next one
258 while (!MXC_TMR_RevB_GetFlags(tmr)) {} // Wait for next PWM transition
259 MXC_TMR_RevB_Stop(tmr); // Pause timer
260 MXC_TMR_RevB_SetCount(tmr, 0); // Reset the count
261 MXC_TMR_RevB_ClearFlags(
262 tmr); // Clear flags since app code wants the new PWM transitions set by this function
263 }
264
265 tmr->pwm = pwm;
266 while (!(tmr->intfl & MXC_F_TMR_REVB_INTFL_WRDONE_A)) {}
267
268 if (timera_is_running) {
269 tmr->ctrl0 |= MXC_F_TMR_REVB_CTRL0_EN_A; // Unpause A
270 }
271
272 if (timerb_is_running) {
273 tmr->ctrl0 |= MXC_F_TMR_REVB_CTRL0_EN_B; // Unpause B
274 }
275
276 return E_NO_ERROR;
277 }
278
MXC_TMR_RevB_GetCompare(mxc_tmr_revb_regs_t * tmr)279 uint32_t MXC_TMR_RevB_GetCompare(mxc_tmr_revb_regs_t *tmr)
280 {
281 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
282 (void)tmr_id;
283 MXC_ASSERT(tmr_id >= 0);
284
285 return tmr->cmp;
286 }
287
MXC_TMR_RevB_GetCapture(mxc_tmr_revb_regs_t * tmr)288 uint32_t MXC_TMR_RevB_GetCapture(mxc_tmr_revb_regs_t *tmr)
289 {
290 uint32_t pwm;
291 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
292 (void)tmr_id;
293 MXC_ASSERT(tmr_id >= 0);
294
295 // read pwm register twice
296 pwm = tmr->pwm;
297 pwm = tmr->pwm;
298 return pwm;
299 }
300
MXC_TMR_RevB_GetCount(mxc_tmr_revb_regs_t * tmr)301 uint32_t MXC_TMR_RevB_GetCount(mxc_tmr_revb_regs_t *tmr)
302 {
303 uint32_t cnt;
304 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
305 (void)tmr_id;
306 MXC_ASSERT(tmr_id >= 0);
307
308 // read cnt register twice
309 cnt = tmr->cnt;
310 cnt = tmr->cnt;
311 return cnt;
312 }
313
MXC_TMR_RevB_GetPeriod(mxc_tmr_revb_regs_t * tmr,uint32_t clk_frequency,uint32_t prescalar,uint32_t frequency)314 uint32_t MXC_TMR_RevB_GetPeriod(mxc_tmr_revb_regs_t *tmr, uint32_t clk_frequency,
315 uint32_t prescalar, uint32_t frequency)
316 {
317 uint32_t periodTicks;
318 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
319 (void)tmr_id;
320 MXC_ASSERT(tmr_id >= 0);
321
322 periodTicks = clk_frequency / (frequency * prescalar);
323
324 return periodTicks;
325 }
326
MXC_TMR_RevB_ClearFlags(mxc_tmr_revb_regs_t * tmr)327 void MXC_TMR_RevB_ClearFlags(mxc_tmr_revb_regs_t *tmr)
328 {
329 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
330 (void)tmr_id;
331 MXC_ASSERT(tmr_id >= 0);
332
333 tmr->intfl |= (MXC_F_TMR_REVB_INTFL_IRQ_A | MXC_F_TMR_REVB_INTFL_IRQ_B);
334 }
335
MXC_TMR_RevB_GetFlags(mxc_tmr_revb_regs_t * tmr)336 uint32_t MXC_TMR_RevB_GetFlags(mxc_tmr_revb_regs_t *tmr)
337 {
338 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
339 (void)tmr_id;
340 MXC_ASSERT(tmr_id >= 0);
341
342 return (tmr->intfl & (MXC_F_TMR_REVB_INTFL_IRQ_A | MXC_F_TMR_REVB_INTFL_IRQ_B));
343 }
344
MXC_TMR_RevB_EnableInt(mxc_tmr_revb_regs_t * tmr)345 void MXC_TMR_RevB_EnableInt(mxc_tmr_revb_regs_t *tmr)
346 {
347 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
348 (void)tmr_id;
349 MXC_ASSERT(tmr_id >= 0);
350
351 tmr->ctrl1 |= MXC_F_TMR_REVB_CTRL1_IE_A | MXC_F_TMR_REVB_CTRL1_IE_B;
352 }
353
MXC_TMR_RevB_DisableInt(mxc_tmr_revb_regs_t * tmr)354 void MXC_TMR_RevB_DisableInt(mxc_tmr_revb_regs_t *tmr)
355 {
356 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
357 (void)tmr_id;
358 MXC_ASSERT(tmr_id >= 0);
359
360 tmr->ctrl1 &= ~(MXC_F_TMR_REVB_CTRL1_IE_A | MXC_F_TMR_REVB_CTRL1_IE_B);
361 }
362
MXC_TMR_RevB_EnableWakeup(mxc_tmr_revb_regs_t * tmr,mxc_tmr_cfg_t * cfg)363 void MXC_TMR_RevB_EnableWakeup(mxc_tmr_revb_regs_t *tmr, mxc_tmr_cfg_t *cfg)
364 {
365 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
366 (void)tmr_id;
367 MXC_ASSERT(tmr_id >= 0);
368
369 // Enable Timer wake-up source
370 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
371 tmr->ctrl1 |= MXC_F_TMR_REVB_CTRL1_WE_B;
372 } else {
373 tmr->ctrl1 |= MXC_F_TMR_REVB_CTRL1_WE_A;
374 }
375 }
376
MXC_TMR_RevB_DisableWakeup(mxc_tmr_revb_regs_t * tmr,mxc_tmr_cfg_t * cfg)377 void MXC_TMR_RevB_DisableWakeup(mxc_tmr_revb_regs_t *tmr, mxc_tmr_cfg_t *cfg)
378 {
379 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
380 (void)tmr_id;
381 MXC_ASSERT(tmr_id >= 0);
382
383 // Disable Timer wake-up source
384 if (cfg->bitMode == MXC_TMR_BIT_MODE_16B) {
385 tmr->ctrl1 &= ~MXC_F_TMR_REVB_CTRL1_WE_B;
386 } else {
387 tmr->ctrl1 &= ~MXC_F_TMR_REVB_CTRL1_WE_A;
388 }
389 }
390
MXC_TMR_RevB_SetCompare(mxc_tmr_revb_regs_t * tmr,uint32_t cmp_cnt)391 void MXC_TMR_RevB_SetCompare(mxc_tmr_revb_regs_t *tmr, uint32_t cmp_cnt)
392 {
393 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
394 (void)tmr_id;
395 MXC_ASSERT(tmr_id >= 0);
396
397 tmr->cmp = cmp_cnt;
398 }
399
MXC_TMR_RevB_SetCount(mxc_tmr_revb_regs_t * tmr,uint32_t cnt)400 void MXC_TMR_RevB_SetCount(mxc_tmr_revb_regs_t *tmr, uint32_t cnt)
401 {
402 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
403 (void)tmr_id;
404 MXC_ASSERT(tmr_id >= 0);
405
406 tmr->cnt = cnt;
407 while (!(tmr->intfl & MXC_F_TMR_REVB_INTFL_WRDONE_A)) {}
408 }
409
MXC_TMR_RevB_TO_Start(mxc_tmr_revb_regs_t * tmr,uint32_t us)410 void MXC_TMR_RevB_TO_Start(mxc_tmr_revb_regs_t *tmr, uint32_t us)
411 {
412 uint64_t ticks;
413 int clk_shift = 0;
414
415 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
416 (void)tmr_id;
417 MXC_ASSERT(tmr_id >= 0);
418
419 if (us == 0) {
420 return;
421 }
422
423 ticks = (uint64_t)us * (uint64_t)PeripheralClock / (uint64_t)1000000;
424
425 while (ticks > 0xFFFFFFFFUL) {
426 ticks >>= 1;
427 ++clk_shift;
428 }
429
430 mxc_tmr_pres_t prescale = (mxc_tmr_pres_t)(clk_shift << MXC_F_TMR_REVB_CTRL0_CLKDIV_A_POS);
431 mxc_tmr_cfg_t cfg;
432
433 // Initialize the timer in one-shot mode
434 cfg.pres = prescale;
435 cfg.mode = MXC_TMR_MODE_ONESHOT;
436 cfg.bitMode = MXC_TMR_BIT_MODE_32;
437 cfg.clock = MXC_TMR_APB_CLK;
438 cfg.cmp_cnt = ticks;
439 cfg.pol = 0;
440
441 MXC_TMR_Stop((mxc_tmr_regs_t *)tmr);
442 #if TARGET_NUM == 32662
443 MXC_TMR_Init((mxc_tmr_regs_t *)tmr, &cfg, false, MAP_A);
444 #else
445 MXC_TMR_Init((mxc_tmr_regs_t *)tmr, &cfg, false);
446 #endif
447 tmr->ctrl1 |= MXC_F_TMR_REVB_CTRL1_CASCADE;
448 MXC_TMR_ClearFlags((mxc_tmr_regs_t *)tmr);
449 MXC_TMR_Start((mxc_tmr_regs_t *)tmr);
450 }
451
MXC_TMR_RevB_GetTime(mxc_tmr_revb_regs_t * tmr,uint32_t ticks,uint32_t * time,mxc_tmr_unit_t * units)452 int MXC_TMR_RevB_GetTime(mxc_tmr_revb_regs_t *tmr, uint32_t ticks, uint32_t *time,
453 mxc_tmr_unit_t *units)
454 {
455 int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
456 (void)tmr_id;
457 MXC_ASSERT(tmr_id >= 0);
458
459 uint64_t temp_time = 0;
460 uint32_t prescale = (tmr->ctrl0 & MXC_F_TMR_REVB_CTRL0_CLKDIV_A) >>
461 MXC_F_TMR_REVB_CTRL0_CLKDIV_A_POS;
462
463 int timerClock = MXC_TMR_RevB_GetClockSourceFreq(tmr);
464
465 // Confirm clock is configured by checking for error return.
466 if (timerClock < 0) {
467 return timerClock;
468 }
469
470 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000000);
471
472 if (!(temp_time & 0xffffffff00000000)) {
473 *time = temp_time;
474 *units = MXC_TMR_UNIT_NANOSEC;
475 return E_NO_ERROR;
476 }
477
478 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000);
479
480 if (!(temp_time & 0xffffffff00000000)) {
481 *time = temp_time;
482 *units = MXC_TMR_UNIT_MICROSEC;
483 return E_NO_ERROR;
484 }
485
486 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / timerClock;
487
488 if (!(temp_time & 0xffffffff00000000)) {
489 *time = temp_time;
490 *units = MXC_TMR_UNIT_MILLISEC;
491 return E_NO_ERROR;
492 }
493
494 temp_time = (uint64_t)ticks * (1 << (prescale & 0xF)) / timerClock;
495
496 if (!(temp_time & 0xffffffff00000000)) {
497 *time = temp_time;
498 *units = MXC_TMR_UNIT_SEC;
499 return E_NO_ERROR;
500 }
501
502 return E_INVALID;
503 }
504
MXC_TMR_RevB_GetTicks(mxc_tmr_revb_regs_t * tmr,uint32_t time,mxc_tmr_unit_t units,uint32_t * ticks)505 int MXC_TMR_RevB_GetTicks(mxc_tmr_revb_regs_t *tmr, uint32_t time, mxc_tmr_unit_t units,
506 uint32_t *ticks)
507 {
508 uint32_t unit_div0, unit_div1;
509 uint32_t timerClock;
510 uint32_t prescale;
511 uint64_t temp_ticks;
512
513 timerClock = PeripheralClock;
514
515 prescale = ((tmr->ctrl0 & MXC_F_TMR_CTRL0_CLKDIV_A) >> MXC_F_TMR_CTRL0_CLKDIV_A_POS);
516
517 switch (units) {
518 case MXC_TMR_UNIT_NANOSEC:
519 unit_div0 = 1000000;
520 unit_div1 = 1000;
521 break;
522 case MXC_TMR_UNIT_MICROSEC:
523 unit_div0 = 1000;
524 unit_div1 = 1000;
525 break;
526 case MXC_TMR_UNIT_MILLISEC:
527 unit_div0 = 1;
528 unit_div1 = 1000;
529 break;
530 case MXC_TMR_UNIT_SEC:
531 unit_div0 = 1;
532 unit_div1 = 1;
533 break;
534 default:
535 return E_BAD_PARAM;
536 }
537
538 temp_ticks = (uint64_t)time * (timerClock / unit_div0) / (unit_div1 * (1 << (prescale & 0xF)));
539
540 //make sure ticks is within a 32 bit value
541 if (!(temp_ticks & 0xffffffff00000000) && (temp_ticks & 0xffffffff)) {
542 *ticks = temp_ticks;
543 return E_NO_ERROR;
544 }
545
546 return E_INVALID;
547 }
548