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 <string.h>
24 #include "mxc_assert.h"
25 #include "tmr.h"
26 #include "tmr_reva.h"
27 #include "gpio.h"
28 #include "mxc_pins.h"
29 #include "mxc_lock.h"
30
31 /* **** Functions **** */
MXC_TMR_RevA_Init(mxc_tmr_reva_regs_t * tmr,mxc_tmr_cfg_t * cfg)32 void MXC_TMR_RevA_Init(mxc_tmr_reva_regs_t *tmr, mxc_tmr_cfg_t *cfg)
33 {
34 // Clear interrupt flag
35 tmr->intr = MXC_F_TMR_REVA_INTR_IRQ;
36
37 // Set the prescaler
38 switch (cfg->pres) {
39 case MXC_TMR_PRES_1:
40 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV1);
41 break;
42
43 case MXC_TMR_PRES_2:
44 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV2);
45 break;
46
47 case MXC_TMR_PRES_4:
48 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV4);
49 break;
50
51 case MXC_TMR_PRES_8:
52 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV8);
53 break;
54
55 case MXC_TMR_PRES_16:
56 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV16);
57 break;
58
59 case MXC_TMR_PRES_32:
60 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV32);
61 break;
62
63 case MXC_TMR_PRES_64:
64 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV64);
65 break;
66
67 case MXC_TMR_PRES_128:
68 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV128);
69 break;
70
71 case MXC_TMR_PRES_256:
72 tmr->cn |= (MXC_F_TMR_REVA_CN_PRES3);
73 tmr->cn &= ~(MXC_S_TMR_REVA_CN_PRES_DIV1);
74 break;
75
76 case MXC_TMR_PRES_512:
77 tmr->cn |= (MXC_F_TMR_REVA_CN_PRES3);
78 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV4);
79 break;
80
81 case MXC_TMR_PRES_1024:
82 tmr->cn |= (MXC_F_TMR_REVA_CN_PRES3);
83 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV8);
84 break;
85
86 case MXC_TMR_PRES_2048:
87 tmr->cn |= (MXC_F_TMR_REVA_CN_PRES3);
88 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV16);
89 break;
90
91 case MXC_TMR_PRES_4096:
92 tmr->cn |= (MXC_F_TMR_REVA_CN_PRES3);
93 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV32);
94 break;
95
96 default:
97 tmr->cn |= (MXC_S_TMR_REVA_CN_PRES_DIV1);
98 break;
99 }
100
101 tmr->cn |= cfg->mode << MXC_F_TMR_REVA_CN_TMODE_POS;
102 tmr->cn |= (cfg->pol) << MXC_F_TMR_REVA_CN_TPOL_POS;
103 //enable timer interrupt if needed
104 tmr->cnt = 0x1;
105 tmr->cmp = cfg->cmp_cnt;
106 }
107
MXC_TMR_RevA_Shutdown(mxc_tmr_reva_regs_t * tmr)108 void MXC_TMR_RevA_Shutdown(mxc_tmr_reva_regs_t *tmr)
109 {
110 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
111
112 // Disable timer and clear settings
113 tmr->cn = 0;
114 }
115
MXC_TMR_RevA_Start(mxc_tmr_reva_regs_t * tmr)116 void MXC_TMR_RevA_Start(mxc_tmr_reva_regs_t *tmr)
117 {
118 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
119
120 tmr->cn |= MXC_F_TMR_REVA_CN_TEN;
121 }
122
MXC_TMR_RevA_Stop(mxc_tmr_reva_regs_t * tmr)123 void MXC_TMR_RevA_Stop(mxc_tmr_reva_regs_t *tmr)
124 {
125 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
126
127 tmr->cn &= ~MXC_F_TMR_REVA_CN_TEN;
128 }
129
MXC_TMR_RevA_SetPWM(mxc_tmr_reva_regs_t * tmr,uint32_t pwm)130 int MXC_TMR_RevA_SetPWM(mxc_tmr_reva_regs_t *tmr, uint32_t pwm)
131 {
132 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
133
134 if (pwm > (tmr->cmp)) {
135 return E_BAD_PARAM;
136 }
137
138 tmr->pwm = pwm;
139
140 return E_NO_ERROR;
141 }
142
MXC_TMR_RevA_GetCompare(mxc_tmr_reva_regs_t * tmr)143 uint32_t MXC_TMR_RevA_GetCompare(mxc_tmr_reva_regs_t *tmr)
144 {
145 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
146
147 return tmr->cmp;
148 }
149
MXC_TMR_RevA_GetCapture(mxc_tmr_reva_regs_t * tmr)150 uint32_t MXC_TMR_RevA_GetCapture(mxc_tmr_reva_regs_t *tmr)
151 {
152 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
153
154 return tmr->pwm; //check this
155 }
156
MXC_TMR_RevA_GetCount(mxc_tmr_reva_regs_t * tmr)157 uint32_t MXC_TMR_RevA_GetCount(mxc_tmr_reva_regs_t *tmr)
158 {
159 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
160
161 return tmr->cnt;
162 }
163
MXC_TMR_RevA_ClearFlags(mxc_tmr_reva_regs_t * tmr)164 void MXC_TMR_RevA_ClearFlags(mxc_tmr_reva_regs_t *tmr)
165 {
166 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
167
168 tmr->intr = MXC_F_TMR_REVA_INTR_IRQ;
169 }
170
MXC_TMR_RevA_GetFlags(mxc_tmr_reva_regs_t * tmr)171 uint32_t MXC_TMR_RevA_GetFlags(mxc_tmr_reva_regs_t *tmr)
172 {
173 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
174
175 return tmr->intr;
176 }
177
MXC_TMR_RevA_SetCompare(mxc_tmr_reva_regs_t * tmr,uint32_t cmp_cnt)178 void MXC_TMR_RevA_SetCompare(mxc_tmr_reva_regs_t *tmr, uint32_t cmp_cnt)
179 {
180 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
181
182 tmr->cmp = cmp_cnt;
183 }
184
MXC_TMR_RevA_SetCount(mxc_tmr_reva_regs_t * tmr,uint32_t cnt)185 void MXC_TMR_RevA_SetCount(mxc_tmr_reva_regs_t *tmr, uint32_t cnt)
186 {
187 MXC_ASSERT(MXC_TMR_GET_IDX((mxc_tmr_regs_t *)tmr) >= 0);
188
189 tmr->cnt = cnt;
190 }
191
MXC_TMR_RevA_TO_Start(mxc_tmr_reva_regs_t * tmr,uint32_t us)192 void MXC_TMR_RevA_TO_Start(mxc_tmr_reva_regs_t *tmr, uint32_t us)
193 {
194 uint64_t ticks;
195 int clk_shift = 0;
196 mxc_tmr_cfg_t cfg;
197
198 ticks = (uint64_t)us * (uint64_t)PeripheralClock / (uint64_t)1000000;
199
200 while (ticks > 0xFFFFFFFFUL) {
201 ticks >>= 1;
202 ++clk_shift;
203 }
204
205 mxc_tmr_pres_t prescale = (mxc_tmr_pres_t)clk_shift << MXC_F_TMR_REVA_CN_PRES_POS;
206
207 memset(&cfg, 0, sizeof(mxc_tmr_cfg_t));
208
209 // Initialize the timer in one-shot mode
210 cfg.pres = prescale;
211 cfg.mode = MXC_TMR_MODE_ONESHOT;
212 cfg.cmp_cnt = ticks;
213 cfg.pol = 0;
214
215 MXC_TMR_Stop((mxc_tmr_regs_t *)tmr);
216 MXC_TMR_Init((mxc_tmr_regs_t *)tmr, &cfg);
217 MXC_TMR_ClearFlags((mxc_tmr_regs_t *)tmr);
218 MXC_TMR_Start((mxc_tmr_regs_t *)tmr);
219 }
220
MXC_TMR_RevA_GetTime(mxc_tmr_reva_regs_t * tmr,uint32_t ticks,uint32_t * time,mxc_tmr_unit_t * units)221 int MXC_TMR_RevA_GetTime(mxc_tmr_reva_regs_t *tmr, uint32_t ticks, uint32_t *time,
222 mxc_tmr_unit_t *units)
223 {
224 uint64_t temp_time = 0;
225 uint32_t timerClock = PeripheralClock;
226 uint32_t prescale =
227 ((tmr->cn & MXC_F_TMR_REVA_CN_PRES) >> MXC_F_TMR_REVA_CN_PRES_POS) |
228 (((tmr->cn & MXC_F_TMR_REVA_CN_PRES3) >> (MXC_F_TMR_REVA_CN_PRES3_POS)) << 3);
229
230 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000000);
231
232 if (!(temp_time & 0xffffffff00000000)) {
233 *time = temp_time;
234 *units = MXC_TMR_UNIT_NANOSEC;
235 return E_NO_ERROR;
236 }
237
238 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000);
239
240 if (!(temp_time & 0xffffffff00000000)) {
241 *time = temp_time;
242 *units = MXC_TMR_UNIT_MICROSEC;
243 return E_NO_ERROR;
244 }
245
246 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / timerClock;
247
248 if (!(temp_time & 0xffffffff00000000)) {
249 *time = temp_time;
250 *units = MXC_TMR_UNIT_MILLISEC;
251 return E_NO_ERROR;
252 }
253
254 temp_time = (uint64_t)ticks * (1 << (prescale & 0xF)) / timerClock;
255
256 if (!(temp_time & 0xffffffff00000000)) {
257 *time = temp_time;
258 *units = MXC_TMR_UNIT_SEC;
259 return E_NO_ERROR;
260 }
261
262 return E_INVALID;
263 }
264