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 <stdint.h>
23 #include <stddef.h>
24 #include "mxc_device.h"
25 #include "mxc_assert.h"
26 #include "mxc_sys.h"
27 #include "afe_timer.h"
28 #include "nvic_table.h"
29 #include "tmr_revb.h"
30 
31 #define MAX32675_FIRST_LP_TIMER_INSTANCE_NUMBER 4
32 #define MAX32680_FIRST_LP_TIMER_INSTANCE_NUMBER 4
33 
34 #define TIMER_16A_OFFSET 0
35 #define TIMER_16B_OFFSET 16
36 
37 // Globals
38 afe_timeout_complete_t afe_irq_callback;
39 afe_timeout_complete_t hart_irq_callback;
40 
41 uint32_t g_timer_prescaler = 0;
42 mxc_tmr_regs_t *g_afe_timer_inst;
43 uint32_t g_afe_spi_timer_complete = 0;
44 uint32_t g_afe_hart_timer_complete = 0;
45 
AFE_TMR_Stop_16(mxc_tmr_regs_t * tmr,mxc_tmr_bit_mode_t bitMode)46 static void AFE_TMR_Stop_16(mxc_tmr_regs_t *tmr, mxc_tmr_bit_mode_t bitMode)
47 {
48     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
49     (void)tmr_id;
50     MXC_ASSERT(tmr_id >= 0);
51 
52     uint32_t timerOffset;
53 
54     if (bitMode == TMR_BIT_MODE_16B) {
55         timerOffset = TIMER_16B_OFFSET;
56     } else {
57         timerOffset = TIMER_16A_OFFSET;
58     }
59 
60     tmr->ctrl0 &= ~(MXC_F_TMR_CTRL0_EN_A << timerOffset);
61 }
62 
AFE_TMR_SetCompare_16(mxc_tmr_regs_t * tmr,mxc_tmr_bit_mode_t bitMode,uint16_t cmp_cnt)63 static void AFE_TMR_SetCompare_16(mxc_tmr_regs_t *tmr, mxc_tmr_bit_mode_t bitMode, uint16_t cmp_cnt)
64 {
65     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
66     (void)tmr_id;
67     MXC_ASSERT(tmr_id >= 0);
68 
69     uint32_t timerOffset;
70 
71     if (bitMode == TMR_BIT_MODE_16B) {
72         timerOffset = TIMER_16B_OFFSET;
73     } else {
74         timerOffset = TIMER_16A_OFFSET;
75     }
76 
77     tmr->cmp &= ~(0xFFFF << timerOffset);
78     tmr->cmp |= (cmp_cnt << timerOffset);
79 }
80 
AFE_TMR_SetCount_16(mxc_tmr_regs_t * tmr,mxc_tmr_bit_mode_t bitMode,uint16_t cnt)81 static void AFE_TMR_SetCount_16(mxc_tmr_regs_t *tmr, mxc_tmr_bit_mode_t bitMode, uint16_t cnt)
82 {
83     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
84     (void)tmr_id;
85     MXC_ASSERT(tmr_id >= 0);
86 
87     uint32_t timerOffset;
88 
89     if (bitMode == TMR_BIT_MODE_16B) {
90         timerOffset = TIMER_16B_OFFSET;
91     } else {
92         timerOffset = TIMER_16A_OFFSET;
93     }
94 
95     // Note: must wait for Timer Write Done when setting TMR_CNT
96     tmr->cnt &= ~(0xFFFF << timerOffset);
97     while (!(tmr->intfl & (MXC_F_TMR_REVB_INTFL_WRDONE_A << timerOffset))) {}
98     tmr->cnt |= (cnt << timerOffset);
99     while (!(tmr->intfl & (MXC_F_TMR_REVB_INTFL_WRDONE_A << timerOffset))) {}
100 }
101 
AFE_TMR_ClearFlags_16(mxc_tmr_regs_t * tmr,mxc_tmr_bit_mode_t bitMode)102 static void AFE_TMR_ClearFlags_16(mxc_tmr_regs_t *tmr, mxc_tmr_bit_mode_t bitMode)
103 {
104     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
105     (void)tmr_id;
106     MXC_ASSERT(tmr_id >= 0);
107 
108     uint32_t timerOffset;
109 
110     if (bitMode == TMR_BIT_MODE_16B) {
111         timerOffset = TIMER_16B_OFFSET;
112     } else {
113         timerOffset = TIMER_16A_OFFSET;
114     }
115 
116     tmr->intfl |= (MXC_F_TMR_INTFL_IRQ_A << timerOffset);
117 }
118 
AFE_TMR_EnableInt_16(mxc_tmr_regs_t * tmr,mxc_tmr_bit_mode_t bitMode)119 static void AFE_TMR_EnableInt_16(mxc_tmr_regs_t *tmr, mxc_tmr_bit_mode_t bitMode)
120 {
121     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
122     (void)tmr_id;
123     MXC_ASSERT(tmr_id >= 0);
124 
125     uint32_t timerOffset;
126 
127     if (bitMode == TMR_BIT_MODE_16B) {
128         timerOffset = TIMER_16B_OFFSET;
129     } else {
130         timerOffset = TIMER_16A_OFFSET;
131     }
132 
133     tmr->ctrl1 |= (MXC_F_TMR_CTRL1_IE_A << timerOffset);
134 }
135 
AFE_TMR_Start_16(mxc_tmr_regs_t * tmr,mxc_tmr_bit_mode_t bitMode)136 static void AFE_TMR_Start_16(mxc_tmr_regs_t *tmr, mxc_tmr_bit_mode_t bitMode)
137 {
138     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
139     (void)tmr_id;
140     MXC_ASSERT(tmr_id >= 0);
141 
142     uint32_t timerOffset;
143 
144     if (bitMode == TMR_BIT_MODE_16B) {
145         timerOffset = TIMER_16B_OFFSET;
146     } else {
147         timerOffset = TIMER_16A_OFFSET;
148     }
149 
150     tmr->ctrl0 |= (MXC_F_TMR_CTRL0_EN_A << timerOffset);
151     while (!(tmr->ctrl1 & (MXC_F_TMR_CTRL1_CLKEN_A << timerOffset))) {}
152 }
153 
154 // Note, this only applies to NON-Lower Power Timers
AFE_TMR_GetClockSrc(mxc_tmr_clock_t clk,uint8_t * clockSource)155 static int AFE_TMR_GetClockSrc(mxc_tmr_clock_t clk, uint8_t *clockSource)
156 {
157     switch (clk) {
158     case MXC_TMR_APB_CLK:
159         *clockSource = MXC_TMR_CLK0;
160         break;
161 
162     case MXC_TMR_8M_CLK:
163         *clockSource = MXC_TMR_CLK2;
164         break;
165 
166     case MXC_TMR_32M_CLK:
167         *clockSource = MXC_TMR_CLK3;
168         break;
169 
170     default:
171         return E_BAD_PARAM;
172         break;
173     }
174 
175     return E_NO_ERROR;
176 }
177 
AFE_TMR_Config_16(mxc_tmr_regs_t * tmr,mxc_tmr_cfg_t * cfg)178 static int AFE_TMR_Config_16(mxc_tmr_regs_t *tmr, mxc_tmr_cfg_t *cfg)
179 {
180     uint32_t timerOffset;
181     uint8_t clk_src = 0;
182     int status = E_NO_ERROR;
183     int tmr_id = MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr);
184     (void)tmr_id;
185     MXC_ASSERT(tmr_id >= 0);
186 
187     if (cfg == NULL) {
188         return E_NULL_PTR;
189     }
190 
191     if (cfg->bitMode == TMR_BIT_MODE_16B) {
192         timerOffset = TIMER_16B_OFFSET;
193     } else {
194         timerOffset = TIMER_16A_OFFSET;
195     }
196 
197     // Convert Clock Type
198     status = AFE_TMR_GetClockSrc(cfg->clock, &clk_src);
199     if (status != E_NO_ERROR) {
200         return status;
201     }
202 
203     // Clear any existing config
204     tmr->ctrl0 &= ~(0xFFFF << timerOffset);
205     tmr->ctrl1 &= ~(0xFFFF << timerOffset);
206     tmr->cmp &= ~(0xFFFF << timerOffset);
207     tmr->cnt &= ~(0xFFFF << timerOffset);
208 
209     tmr->ctrl0 |= (MXC_F_TMR_CTRL0_CLKEN_A << timerOffset);
210     while (!(tmr->ctrl1 & (MXC_F_TMR_CTRL1_CLKRDY_A << timerOffset))) {}
211 
212     tmr->ctrl0 |= (cfg->mode << timerOffset);
213     tmr->ctrl0 |= ((cfg->pol << MXC_F_TMR_CTRL0_POL_A_POS) << timerOffset);
214     tmr->ctrl0 |= ((cfg->pres << MXC_F_TMR_CTRL0_CLKDIV_A_POS) << timerOffset);
215     tmr->ctrl1 |= ((clk_src << MXC_F_TMR_CTRL0_CLKDIV_A_POS) << timerOffset);
216     tmr->cnt = (0x1 << timerOffset);
217     tmr->cmp = (cfg->cmp_cnt << timerOffset);
218 
219     return E_NO_ERROR;
220 }
221 
afe_timer_interrupt_handler(void)222 static void afe_timer_interrupt_handler(void)
223 {
224     uint32_t flags = MXC_TMR_GetFlags(g_afe_timer_inst);
225 
226     if (flags & MXC_F_TMR_INTFL_IRQ_A) {
227         // AFE Timer Interrupt
228         AFE_TMR_ClearFlags_16(g_afe_timer_inst, AFE_SPI_TIMER);
229 
230         g_afe_spi_timer_complete = 1;
231 
232         if (afe_irq_callback) {
233             afe_irq_callback(E_ABORT);
234         }
235     } else if (flags & MXC_F_TMR_INTFL_IRQ_B) {
236         // HART Timer Interrupt
237         AFE_TMR_ClearFlags_16(g_afe_timer_inst, HART_TIMER);
238 
239         g_afe_hart_timer_complete = 1;
240 
241         if (hart_irq_callback) {
242             hart_irq_callback(E_ABORT);
243         }
244     }
245 }
246 
afe_timer_validate_id(mxc_tmr_regs_t * tmr)247 static int afe_timer_validate_id(mxc_tmr_regs_t *tmr)
248 {
249     uint8_t tmr_id = 0;
250     MXC_ASSERT((tmr_id = MXC_TMR_GET_IDX(tmr)) >= 0);
251 
252 #if (TARGET_NUM == 32675)
253     if (tmr_id >= MAX32675_FIRST_LP_TIMER_INSTANCE_NUMBER) {
254         return E_NOT_SUPPORTED;
255     }
256 #elif (TARGET_NUM == 32680)
257     if (tmr_id >= MAX32680_FIRST_LP_TIMER_INSTANCE_NUMBER) {
258         return E_NOT_SUPPORTED;
259     }
260 #else
261 #error "Selected TARGET is not known to have an AFE\n"
262 #endif
263 
264     g_afe_timer_inst = tmr;
265 
266     return E_NO_ERROR;
267 }
268 
afe_timer_choose_prescaler(void)269 static int afe_timer_choose_prescaler(void)
270 {
271     uint32_t timer_input_clk = 0;
272     uint32_t scaled_clk = 0;
273     int32_t scaled_diff_prev = 0;
274     int32_t scaled_diff_curr = 0;
275 
276     g_timer_prescaler = 0;
277 
278     SystemCoreClockUpdate(); // Ensure Clock is up to date
279     timer_input_clk = PeripheralClock;
280 
281     // Don't support input clock less than 1Mhz
282     if (timer_input_clk < 1000000) {
283         return E_NOT_SUPPORTED;
284     }
285 
286     scaled_clk = timer_input_clk / 1000000;
287 
288     // Prescaler formula is input_clk/(2^prescaler) I.E. prescaler of 0 is div 1.
289     for (g_timer_prescaler = 0; g_timer_prescaler < MXC_V_TMR_CTRL0_CLKDIV_A_DIV_BY_4096;
290          g_timer_prescaler++) {
291         if (scaled_clk <= (1 << g_timer_prescaler)) {
292             break;
293         }
294     }
295 
296     // Should be close now, choose current prescaler or previous one based on diff to 1Mhz
297     scaled_diff_curr = scaled_clk - (1 << g_timer_prescaler);
298     scaled_diff_prev = scaled_clk - (1 << (g_timer_prescaler - 1));
299 
300     // Get absolute value
301     if (scaled_diff_curr < 0) {
302         scaled_diff_curr *= -1;
303     }
304     if (scaled_diff_prev < 0) {
305         scaled_diff_prev *= -1;
306     }
307 
308     if (scaled_diff_curr > scaled_diff_prev) {
309         // Previous scaler was closer, use it
310         g_timer_prescaler--;
311     }
312 
313     return E_NO_ERROR;
314 }
315 
afe_timer_config(mxc_tmr_regs_t * tmr)316 int afe_timer_config(mxc_tmr_regs_t *tmr)
317 {
318     mxc_tmr_cfg_t afe_tmr_cfg;
319     mxc_tmr_cfg_t hart_tmr_cfg;
320     int status = E_NO_ERROR;
321 
322     // We require TO detection for SPI transactions with AFE,
323     //  and for accurately timed callbacks for HART UART transmitter.
324     // So we will split a system timer into two 16 bit timers.
325     // Doing so necessitates use of NON LP timers, and setting
326     //  the prescaler to allow for proper timer range.
327 
328     // The AFE timer (Timer A) will need to time a range from about 800us-10ms.
329     // The HART UART timer (Timer B) will need to time a range from about 1600us-19ms.
330     // Due to having only 16 bits each for counting, we will target for the
331     //  prescaled input clock to be ~1MHz which should provide adequate timer
332     //  range for both timers. @1MHz input clock each tick is 1us giving a max
333     //  timer value of 65.5ms.
334 
335     // First ensure specified timer is of correct type, that is NON LP timer.
336     status = afe_timer_validate_id(tmr);
337     if (status != E_NO_ERROR) {
338         return status;
339     }
340 
341     // Based on System Clock frequency choose divider to achieve input clock
342     //  closest to 1MHz.
343     // NOTE: Always using PCLK to simplify configurations.
344     status = afe_timer_choose_prescaler();
345     if (status != E_NO_ERROR) {
346         return status;
347     }
348 
349     // Setup AFE Timer driver configuration
350     afe_tmr_cfg.pres = (mxc_tmr_pres_t)g_timer_prescaler;
351     afe_tmr_cfg.mode = TMR_MODE_ONESHOT;
352     afe_tmr_cfg.bitMode = AFE_SPI_TIMER;
353     afe_tmr_cfg.clock = MXC_TMR_APB_CLK;
354     afe_tmr_cfg.cmp_cnt = 0;
355     afe_tmr_cfg.pol = 1;
356 
357     // Note: MXC_TMR_INIT does not properly handle split 16 bit modes
358     //   Calling it any way here to handle baseline initialization
359     status = MXC_TMR_Init(g_afe_timer_inst, &afe_tmr_cfg, FALSE);
360     if (status != E_NO_ERROR) {
361         return status;
362     }
363 
364     // Actual 16bit configuration
365     status = AFE_TMR_Config_16(g_afe_timer_inst, &afe_tmr_cfg);
366     if (status != E_NO_ERROR) {
367         return status;
368     }
369 
370     // Setup HART Timer driver configuration
371     hart_tmr_cfg.pres = (mxc_tmr_pres_t)g_timer_prescaler;
372     hart_tmr_cfg.mode = TMR_MODE_ONESHOT;
373     hart_tmr_cfg.bitMode = HART_TIMER;
374     hart_tmr_cfg.clock = MXC_TMR_APB_CLK;
375     hart_tmr_cfg.cmp_cnt = 0;
376     hart_tmr_cfg.pol = 1;
377 
378     // Actual 16bit configuration
379     status = AFE_TMR_Config_16(g_afe_timer_inst, &hart_tmr_cfg);
380     if (status != E_NO_ERROR) {
381         return status;
382     }
383 
384     // Overwrite default Timer IRQ Vector with ours
385     MXC_NVIC_SetVector(MXC_TMR_GET_IRQ(MXC_TMR_GET_IDX(g_afe_timer_inst)),
386                        afe_timer_interrupt_handler);
387     NVIC_EnableIRQ(MXC_TMR_GET_IRQ(MXC_TMR_GET_IDX(g_afe_timer_inst)));
388 
389     return status;
390 }
391 
afe_timer_calc_ticks(uint32_t microseconds,uint16_t * ticks)392 static int afe_timer_calc_ticks(uint32_t microseconds, uint16_t *ticks)
393 {
394     // Bounds check for MAX timeout and convert to actual ticks
395     uint64_t timer_tick_period_ns = 0;
396     uint64_t nanoseconds = microseconds * 1000;
397     uint64_t ratioed_ticks = 0;
398 
399     timer_tick_period_ns = ((1 << g_timer_prescaler) * 1000) / (PeripheralClock / 1000000);
400 
401     ratioed_ticks = nanoseconds / timer_tick_period_ns;
402 
403     // Bounds check the results
404     if (ratioed_ticks > UINT16_MAX) {
405         // Timeout longer than supported with current prescaler
406         *ticks = 0;
407         return E_OVERFLOW;
408     }
409 
410     if (ratioed_ticks == 0) {
411         // Unexpectedly resulting timeout count is 0
412         *ticks = 0;
413         return E_UNKNOWN;
414     }
415 
416     *ticks = ratioed_ticks;
417     return E_NO_ERROR;
418 }
419 
afe_timer_delay_async(mxc_tmr_bit_mode_t timer_selection,uint32_t timeout_us,afe_timeout_complete_t cb)420 int afe_timer_delay_async(mxc_tmr_bit_mode_t timer_selection, uint32_t timeout_us,
421                           afe_timeout_complete_t cb)
422 {
423     uint16_t calculated_ticks = 0;
424     int status = E_NO_ERROR;
425 
426     if ((timer_selection != AFE_SPI_TIMER) && (timer_selection != HART_TIMER)) {
427         return E_BAD_PARAM;
428     }
429 
430     if (timeout_us == 0) {
431         return E_BAD_PARAM;
432     }
433 
434     status = afe_timer_calc_ticks(timeout_us, &calculated_ticks);
435     if (status != E_NO_ERROR) {
436         return status;
437     }
438 
439     // TMR Driver does not provide low level access for 16 bit mode
440     AFE_TMR_Stop_16(g_afe_timer_inst, timer_selection);
441 
442     // Reset count every time, otherwise it will creep up and incur a false timeout
443     AFE_TMR_SetCount_16(g_afe_timer_inst, timer_selection, 1);
444     AFE_TMR_SetCompare_16(g_afe_timer_inst, timer_selection, calculated_ticks);
445     AFE_TMR_ClearFlags_16(g_afe_timer_inst, timer_selection);
446 
447     // Set up interrupts, and completion irq globals
448     if (timer_selection == AFE_SPI_TIMER) {
449         afe_irq_callback = cb;
450         g_afe_spi_timer_complete = 0;
451     } else {
452         hart_irq_callback = cb;
453         g_afe_hart_timer_complete = 0;
454     }
455 
456     AFE_TMR_EnableInt_16(g_afe_timer_inst, timer_selection);
457     AFE_TMR_Start_16(g_afe_timer_inst, timer_selection);
458 
459     return E_SUCCESS;
460 }
461 
afe_timer_delay_check(mxc_tmr_bit_mode_t timer_selection)462 int afe_timer_delay_check(mxc_tmr_bit_mode_t timer_selection)
463 {
464     if ((timer_selection != AFE_SPI_TIMER) && (timer_selection != HART_TIMER)) {
465         return E_BAD_PARAM;
466     }
467 
468     if (timer_selection == AFE_SPI_TIMER) {
469         if (g_afe_spi_timer_complete) {
470             return E_NO_ERROR;
471         }
472 
473         return E_BUSY;
474     } else {
475         if (g_afe_hart_timer_complete) {
476             return E_NO_ERROR;
477         }
478 
479         return E_BUSY;
480     }
481 }
482 
afe_timer_delay_abort(mxc_tmr_bit_mode_t timer_selection)483 int afe_timer_delay_abort(mxc_tmr_bit_mode_t timer_selection)
484 {
485     if ((timer_selection != AFE_SPI_TIMER) && (timer_selection != HART_TIMER)) {
486         return E_BAD_PARAM;
487     }
488 
489     AFE_TMR_Stop_16(g_afe_timer_inst, timer_selection);
490 
491     if (timer_selection == AFE_SPI_TIMER) {
492         if (afe_irq_callback) {
493             afe_irq_callback(E_ABORT);
494             afe_irq_callback = NULL;
495         }
496     } else {
497         if (hart_irq_callback) {
498             hart_irq_callback(E_ABORT);
499             hart_irq_callback = NULL;
500         }
501     }
502 
503     return E_SUCCESS;
504 }
505