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