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