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 #include <stdio.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include "mxc_device.h"
25 #include "mxc_assert.h"
26 #include "mxc_lock.h"
27 #include "mxc_sys.h"
28 #include "mxc_delay.h"
29 #include "htmr_reva_regs.h"
30 #include "htmr.h"
31 #include "htmr_reva.h"
32
33 /* **** Definitions **** */
34 #define HTMR_CTRL_RESET_DEFAULT (0x8000UL)
35 #define BUSY_TIMEOUT (10000) // Timeout counts for the Busy bit
36 #define ASYNC_MODE (MXC_F_HTMR_REVA_CTRL_ACRE & htmr->ctrl)
37
38 #define MXC_HTMR_ALL_INT_FLAGS \
39 (MXC_F_HTMR_REVA_CTRL_RDY | MXC_F_HTMR_REVA_CTRL_ALDF | MXC_F_HTMR_REVA_CTRL_ALSF)
40 #define MXC_HTMR_ALL_INT_ENABLES \
41 (MXC_F_HTMR_REVA_CTRL_RDYE | MXC_F_HTMR_REVA_CTRL_ADE | MXC_F_HTMR_REVA_CTRL_ASE)
42
43 /* ***** Functions ***** */
MXC_HTMR_RevA_Init(mxc_htmr_reva_regs_t * htmr,uint32_t sec,uint8_t ssec)44 int MXC_HTMR_RevA_Init(mxc_htmr_reva_regs_t *htmr, uint32_t sec, uint8_t ssec)
45 {
46 if (htmr == NULL) {
47 return E_NULL_PTR;
48 }
49
50 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
51 return E_BUSY;
52 }
53
54 htmr->ctrl = MXC_F_HTMR_REVA_CTRL_WE; // Allow Writes
55
56 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
57 return E_BUSY;
58 }
59
60 htmr->ctrl = HTMR_CTRL_RESET_DEFAULT; // Start with a Clean Register
61
62 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
63 return E_BUSY;
64 }
65
66 htmr->ctrl |= MXC_F_HTMR_REVA_CTRL_WE; // Set Write Enable, allow writing to reg.
67
68 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
69 return E_BUSY;
70 }
71
72 htmr->ssec = ssec;
73
74 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
75 return E_BUSY;
76 }
77
78 htmr->sec = sec;
79
80 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
81 return E_BUSY;
82 }
83
84 // If the peripheral clock is twice the frequency of the clock driving HTMR
85 // we can enable Asynchronous read mode for htmr->sec and htmr->ssec registers
86 if (PeripheralClock > (2 * IBRO_FREQ)) {
87 htmr->ctrl |= MXC_F_HTMR_REVA_CTRL_ACRE;
88 }
89
90 htmr->ctrl &= ~MXC_F_HTMR_REVA_CTRL_WE; // Prevent Writing...
91
92 return E_SUCCESS;
93 }
94
MXC_HTMR_RevA_Start(mxc_htmr_reva_regs_t * htmr)95 int MXC_HTMR_RevA_Start(mxc_htmr_reva_regs_t *htmr)
96 {
97 if (htmr == NULL) {
98 return E_NULL_PTR;
99 }
100
101 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
102 return E_BUSY;
103 }
104
105 htmr->ctrl |= MXC_F_HTMR_REVA_CTRL_WE; // Allow writing to registers
106
107 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
108 return E_BUSY;
109 }
110
111 // Can only write if WE=1 and BUSY=0
112 htmr->ctrl |= MXC_F_HTMR_REVA_CTRL_HTEN; // setting RTCE = 1
113
114 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
115 return E_BUSY;
116 }
117
118 htmr->ctrl &= ~MXC_F_HTMR_REVA_CTRL_WE; // Prevent Writing...
119
120 return E_SUCCESS;
121 }
122
MXC_HTMR_RevA_Stop(mxc_htmr_reva_regs_t * htmr)123 int MXC_HTMR_RevA_Stop(mxc_htmr_reva_regs_t *htmr)
124 {
125 if (htmr == NULL) {
126 return E_NULL_PTR;
127 }
128
129 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
130 return E_BUSY;
131 }
132
133 htmr->ctrl |= MXC_F_HTMR_REVA_CTRL_WE; // Allow writing to registers
134
135 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
136 return E_BUSY;
137 }
138
139 // Can only write if WE=1 and BUSY=0
140 htmr->ctrl &= ~MXC_F_HTMR_REVA_CTRL_HTEN; // setting RTCE = 0
141
142 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
143 return E_BUSY;
144 }
145
146 htmr->ctrl &= ~MXC_F_HTMR_REVA_CTRL_WE; // Prevent Writing...
147
148 return E_SUCCESS;
149 }
150
MXC_HTMR_RevA_GetShortCount(mxc_htmr_reva_regs_t * htmr)151 int MXC_HTMR_RevA_GetShortCount(mxc_htmr_reva_regs_t *htmr)
152 {
153 if (htmr == NULL) {
154 return E_NULL_PTR;
155 }
156
157 // Don't bother calling CheckBusy() if we're in async mode
158 if (!ASYNC_MODE) {
159 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
160 return E_BUSY;
161 }
162 }
163
164 return htmr->ssec;
165 }
166
MXC_HTMR_RevA_GetLongCount(mxc_htmr_reva_regs_t * htmr)167 int MXC_HTMR_RevA_GetLongCount(mxc_htmr_reva_regs_t *htmr)
168 {
169 if (htmr == NULL) {
170 return E_NULL_PTR;
171 }
172
173 // Don't bother calling CheckBusy() if we're in async mode
174 if (!ASYNC_MODE) {
175 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
176 return E_BUSY;
177 }
178 }
179
180 return htmr->sec;
181 }
182
MXC_HTMR_RevA_SetLongAlarm(mxc_htmr_reva_regs_t * htmr,uint32_t ras)183 int MXC_HTMR_RevA_SetLongAlarm(mxc_htmr_reva_regs_t *htmr, uint32_t ras)
184 {
185 // compare with maximum value
186 if (ras > 0xFFFFF) {
187 return E_BAD_PARAM;
188 }
189
190 if (MXC_HTMR_DisableInt((mxc_htmr_regs_t *)htmr, MXC_F_HTMR_REVA_CTRL_ADE) == E_BUSY) {
191 return E_BUSY;
192 }
193
194 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
195 return E_BUSY;
196 }
197
198 htmr->ras = (ras << MXC_F_HTMR_REVA_RAS_RAS_POS) & MXC_F_HTMR_REVA_RAS_RAS;
199
200 if (MXC_HTMR_EnableInt((mxc_htmr_regs_t *)htmr, MXC_F_HTMR_REVA_CTRL_ADE) == E_BUSY) {
201 return E_BUSY;
202 }
203
204 return E_SUCCESS;
205 }
206
MXC_HTMR_RevA_SetShortAlarm(mxc_htmr_reva_regs_t * htmr,uint32_t rssa)207 int MXC_HTMR_RevA_SetShortAlarm(mxc_htmr_reva_regs_t *htmr, uint32_t rssa)
208 {
209 if (MXC_HTMR_DisableInt((mxc_htmr_regs_t *)htmr, MXC_F_HTMR_REVA_CTRL_ASE) == E_BUSY) {
210 return E_BUSY;
211 }
212
213 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
214 return E_BUSY;
215 }
216
217 htmr->rssa = (rssa << MXC_F_HTMR_REVA_RSSA_RSSA_POS) & MXC_F_HTMR_REVA_RSSA_RSSA;
218
219 if (MXC_HTMR_EnableInt((mxc_htmr_regs_t *)htmr, MXC_F_HTMR_REVA_CTRL_ASE) == E_BUSY) {
220 return E_BUSY;
221 }
222
223 return E_SUCCESS;
224 }
225
MXC_HTMR_RevA_CheckBusy(mxc_htmr_reva_regs_t * htmr)226 int MXC_HTMR_RevA_CheckBusy(mxc_htmr_reva_regs_t *htmr)
227 {
228 MXC_DelayAsync(MXC_DELAY_USEC(BUSY_TIMEOUT), NULL);
229
230 while (htmr->ctrl & MXC_F_HTMR_CTRL_BUSY) {
231 MXC_DelayAbort();
232
233 if (MXC_DelayCheck() != E_BUSY) {
234 return E_BUSY;
235 }
236 }
237
238 return E_SUCCESS;
239 }
240
MXC_HTMR_RevA_GetFlags(mxc_htmr_reva_regs_t * htmr)241 int MXC_HTMR_RevA_GetFlags(mxc_htmr_reva_regs_t *htmr)
242 {
243 if (htmr == NULL) {
244 return E_NULL_PTR;
245 }
246
247 return htmr->ctrl & MXC_HTMR_ALL_INT_FLAGS;
248 }
249
MXC_HTMR_RevA_ClearFlags(mxc_htmr_reva_regs_t * htmr,int flags)250 int MXC_HTMR_RevA_ClearFlags(mxc_htmr_reva_regs_t *htmr, int flags)
251 {
252 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
253 return E_BUSY;
254 }
255
256 htmr->ctrl &= ~(flags & MXC_HTMR_ALL_INT_FLAGS);
257
258 return E_SUCCESS;
259 }
260
MXC_HTMR_RevA_EnableInt(mxc_htmr_reva_regs_t * htmr,uint32_t mask)261 int MXC_HTMR_RevA_EnableInt(mxc_htmr_reva_regs_t *htmr, uint32_t mask)
262 {
263 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
264 return E_BUSY;
265 }
266
267 htmr->ctrl |= (mask & MXC_HTMR_ALL_INT_ENABLES); // Disable Long Interval Interrupt
268
269 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
270 return E_BUSY;
271 }
272
273 return E_SUCCESS;
274 }
275
MXC_HTMR_RevA_DisableInt(mxc_htmr_reva_regs_t * htmr,uint32_t mask)276 int MXC_HTMR_RevA_DisableInt(mxc_htmr_reva_regs_t *htmr, uint32_t mask)
277 {
278 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
279 return E_BUSY;
280 }
281
282 htmr->ctrl &= ~(mask & MXC_HTMR_ALL_INT_ENABLES); // Disable Long Interval Interrupt
283
284 if (MXC_HTMR_CheckBusy((mxc_htmr_regs_t *)htmr)) {
285 return E_BUSY;
286 }
287
288 return E_SUCCESS;
289 }
290