1 /* ****************************************************************************
2 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of Maxim Integrated
23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
24 * Products, Inc. Branding Policy.
25 *
26 * The mere transfer of this software does not imply any licenses
27 * of trade secrets, proprietary technology, copyrights, patents,
28 * trademarks, maskwork rights, or any other form of intellectual
29 * property whatsoever. Maxim Integrated Products, Inc. retains all
30 * ownership rights.
31 *
32 *
33 **************************************************************************** */
34
35 #include "mxc_config.h"
36 #include "rtc_regs.h"
37 #include "rtc.h"
38 #include "mxc_sys.h"
39 #include "mxc_delay.h"
40 #include "gpio_regs.h"
41 #include "mxc_errors.h"
42
43 #if TARGET == 32650
44 #include "pwrseq_regs.h"
45 #endif
46
47 #define RTC_CTRL_RESET_DEFAULT (0x0000UL)
48 #define RTC_IS_BUSY (MXC_RTC->ctrl & MXC_F_RTC_CTRL_BUSY)
49 #define RTC_IS_ENABLED (MXC_RTC->ctrl & MXC_F_RTC_CTRL_RTCE)
50
51 #define BUSY_TIMEOUT 1000 // Timeout counts for the Busy bit
52
53 // *****************************************************************************
RTC_EnableTimeofdayInterrupt(mxc_rtc_regs_t * rtc)54 int RTC_EnableTimeofdayInterrupt(mxc_rtc_regs_t *rtc)
55 {
56 if (RTC_CheckBusy()) {
57 return E_BUSY;
58 }
59
60 rtc->ctrl |= MXC_F_RTC_CTRL_ADE; // Enable Time-of-day Interrupt
61 return E_SUCCESS;
62 }
63
64 // *****************************************************************************
RTC_DisableTimeofdayInterrupt(mxc_rtc_regs_t * rtc)65 int RTC_DisableTimeofdayInterrupt(mxc_rtc_regs_t *rtc)
66 {
67
68 if (RTC_CheckBusy()) {
69 return E_BUSY;
70 }
71
72 rtc->ctrl &= ~MXC_F_RTC_CTRL_ADE; // Disable Time-of-day Interrupt
73
74 if (RTC_CheckBusy()) {
75 return E_BUSY;
76 }
77
78 return E_SUCCESS;
79 }
80
81 // *****************************************************************************
RTC_EnableSubsecondInterrupt(mxc_rtc_regs_t * rtc)82 int RTC_EnableSubsecondInterrupt(mxc_rtc_regs_t *rtc)
83 {
84 if (RTC_CheckBusy()) {
85 return E_BUSY;
86 }
87
88 rtc->ctrl |= MXC_F_RTC_CTRL_ASE; // Enable Sub-Second Interrupt
89
90 return E_SUCCESS;
91 }
92
93 // *****************************************************************************
RTC_DisableSubsecondInterrupt(mxc_rtc_regs_t * rtc)94 int RTC_DisableSubsecondInterrupt(mxc_rtc_regs_t *rtc)
95 {
96
97 if (RTC_CheckBusy()) {
98 return E_BUSY;
99 }
100
101 rtc->ctrl &= ~MXC_F_RTC_CTRL_ASE; // Alarm Sub-Second Interrupt disabled
102
103 if (RTC_CheckBusy()) {
104 return E_BUSY;
105 }
106
107 return E_SUCCESS;
108 }
109
110 // *****************************************************************************
RTC_SetTimeofdayAlarm(mxc_rtc_regs_t * rtc,uint32_t ras)111 int RTC_SetTimeofdayAlarm(mxc_rtc_regs_t *rtc, uint32_t ras)
112 {
113 // ras can only be written if BUSY = 0 & (RTCE = 0 or ADE = 0);
114
115
116 if(RTC_DisableTimeofdayInterrupt(rtc) == E_BUSY) {
117 return E_BUSY;
118 }
119
120 if (RTC_CheckBusy()) {
121 return E_BUSY;
122 }
123
124 rtc->ras = (ras << MXC_F_RTC_RAS_RAS_POS) & MXC_F_RTC_RAS_RAS;
125
126 if(RTC_EnableTimeofdayInterrupt(rtc) == E_BUSY) {
127 return E_BUSY;
128 }
129
130 return E_SUCCESS;
131 }
132
133 // *****************************************************************************
RTC_SetSubsecondAlarm(mxc_rtc_regs_t * rtc,uint32_t rssa)134 int RTC_SetSubsecondAlarm(mxc_rtc_regs_t *rtc, uint32_t rssa)
135 {
136 // ras can only be written if BUSY = 0 & (RTCE = 0 or ASE = 0);
137
138 if(RTC_DisableSubsecondInterrupt(rtc) == E_BUSY) {
139 return E_BUSY;
140 }
141
142 if (RTC_CheckBusy()) {
143 return E_BUSY;
144 }
145
146 rtc->rssa = (rssa << MXC_F_RTC_RSSA_RSSA_POS) & MXC_F_RTC_RSSA_RSSA;
147
148 if(RTC_EnableSubsecondInterrupt(rtc) == E_BUSY) {
149 return E_BUSY;
150 }
151
152 return E_SUCCESS;
153 }
154
155
156 // *****************************************************************************
RTC_EnableRTCE(mxc_rtc_regs_t * rtc)157 int RTC_EnableRTCE(mxc_rtc_regs_t *rtc)
158 {
159 if (RTC_CheckBusy()) {
160 return E_BUSY;
161 }
162
163 rtc->ctrl |= MXC_F_RTC_CTRL_WE; // Allow writing to registers
164 if (RTC_CheckBusy()) {
165 return E_BUSY;
166 }
167 // Can only write if WE=1 and BUSY=0
168 rtc->ctrl |= MXC_F_RTC_CTRL_RTCE; // setting RTCE = 1
169 if (RTC_CheckBusy()) {
170 return E_BUSY;
171 }
172
173 rtc->ctrl &= ~MXC_F_RTC_CTRL_WE; // Prevent Writing...
174
175 return E_SUCCESS;
176 }
177
178 // *****************************************************************************
RTC_DisableRTCE(mxc_rtc_regs_t * rtc)179 int RTC_DisableRTCE(mxc_rtc_regs_t *rtc)
180 {
181 if (RTC_CheckBusy()) {
182 return E_BUSY;
183 }
184
185 rtc->ctrl |= MXC_F_RTC_CTRL_WE; // Allow writing to registers
186 if (RTC_CheckBusy()) {
187 return E_BUSY;
188 }
189
190 // Can only write if WE=1 and BUSY=0
191 rtc->ctrl &= ~MXC_F_RTC_CTRL_RTCE; // setting RTCE = 0
192 if (RTC_CheckBusy()) {
193 return E_BUSY;
194 }
195
196 rtc->ctrl &= ~MXC_F_RTC_CTRL_WE; // Prevent Writing...
197
198 return E_SUCCESS;
199 }
200
201
202 // *****************************************************************************
RTC_Init(mxc_rtc_regs_t * rtc,uint32_t sec,uint8_t ssec,sys_cfg_rtc_t * sys_cfg)203 int RTC_Init(mxc_rtc_regs_t *rtc, uint32_t sec, uint8_t ssec, sys_cfg_rtc_t *sys_cfg)
204 {
205 #if((TARGET == 32650) || (TARGET == 32660))
206 SYS_ClockEnable_X32K(sys_cfg);
207 #else
208 SYS_RTCClockEnable(sys_cfg);
209 #endif
210
211 if (RTC_CheckBusy()) {
212 return E_BUSY;
213 }
214
215 rtc->ctrl = MXC_F_RTC_CTRL_WE; // Allow Writes
216 if (RTC_CheckBusy()) {
217 return E_BUSY;
218 }
219
220 rtc->ctrl = RTC_CTRL_RESET_DEFAULT; // Start with a Clean Register
221 if (RTC_CheckBusy()) {
222 return E_BUSY;
223 }
224
225 rtc->ctrl |= MXC_F_RTC_CTRL_WE; // Set Write Enable, allow writing to reg.
226 if (RTC_CheckBusy()) {
227 return E_BUSY;
228 }
229
230 rtc->ssec = ssec;
231 if (RTC_CheckBusy()) {
232 return E_BUSY;
233 }
234
235 rtc->sec = sec;
236 if (RTC_CheckBusy()) {
237 return E_BUSY;
238 }
239
240 rtc->ctrl &= ~MXC_F_RTC_CTRL_WE; // Prevent Writing...
241
242 return E_SUCCESS;
243 }
244
245 // *****************************************************************************
RTC_SquareWave(mxc_rtc_regs_t * rtc,rtc_sqwave_en_t sqe,rtc_freq_sel_t ft,rtc_osc_mode_t x32kmd,const sys_cfg_rtc_t * sys_cfg)246 int RTC_SquareWave(mxc_rtc_regs_t *rtc, rtc_sqwave_en_t sqe, rtc_freq_sel_t ft,
247 rtc_osc_mode_t x32kmd, const sys_cfg_rtc_t* sys_cfg)
248 {
249
250 SYS_RTC_SqwavInit(sys_cfg); // Set the Output pins for the squarewave.
251
252 if (RTC_CheckBusy()) {
253 return E_BUSY;
254 }
255
256 rtc->ctrl |= MXC_F_RTC_CTRL_WE; // Allow writing to registers
257
258 if (RTC_CheckBusy()) {
259 return E_BUSY;
260 }
261
262 if (sqe == SQUARE_WAVE_ENABLED) {
263 if (ft == F_32KHZ){ // if 32KHz output is selected...
264 rtc->oscctrl |= MXC_F_RTC_OSCCTRL_OUT32K; // Enable 32KHz wave
265 if (RTC_CheckBusy()) {
266 return E_BUSY;
267 }
268 rtc->ctrl |= MXC_F_RTC_CTRL_SQE; // Enable output on the pin
269 } else { // if 1Hz, 512Hz, 4KHz output is selected
270
271 rtc->oscctrl &= ~MXC_F_RTC_OSCCTRL_OUT32K; // Must make sure that the 32KHz is disabled
272 if (RTC_CheckBusy()) {
273 return E_BUSY;
274 }
275 rtc->ctrl &= ~(MXC_F_RTC_CTRL_FT | MXC_F_RTC_CTRL_X32KMD);
276 if (RTC_CheckBusy()) {
277 return E_BUSY;
278 }
279 rtc->ctrl |= (MXC_F_RTC_CTRL_SQE | ft | x32kmd); // Enable Sq. wave,
280 }
281
282 if (RTC_CheckBusy()) {
283 return E_BUSY;
284 }
285 rtc->ctrl |= MXC_F_RTC_CTRL_RTCE; // Enable Real Time Clock
286 } else { // Turn off the square wave output on the pin
287
288 rtc->oscctrl &= ~MXC_F_RTC_OSCCTRL_OUT32K; // Must make sure that the 32KHz is disabled
289 if (RTC_CheckBusy()) {
290 return E_BUSY;
291 }
292 rtc->ctrl &= ~MXC_F_RTC_CTRL_SQE; // No sq. wave output
293 }
294
295 if (RTC_CheckBusy()) {
296 return E_BUSY;
297 }
298 rtc->ctrl &= ~MXC_F_RTC_CTRL_WE; // Disable Writing to register
299
300 return E_SUCCESS;
301 }
302
303 // *****************************************************************************
RTC_Trim(mxc_rtc_regs_t * rtc,int8_t trim)304 int RTC_Trim(mxc_rtc_regs_t *rtc, int8_t trim)
305 {
306
307 if (RTC_CheckBusy()) {
308 return E_BUSY;
309 }
310
311 rtc->ctrl |= MXC_F_RTC_CTRL_WE;
312
313 if (RTC_CheckBusy()) {
314 return E_BUSY;
315 }
316
317 MXC_SETFIELD(rtc->trim, MXC_F_RTC_TRIM_TRIM, trim << MXC_F_RTC_TRIM_TRIM_POS);
318
319 if (RTC_CheckBusy()) {
320 return E_BUSY;
321 }
322 rtc->ctrl &= ~MXC_F_RTC_CTRL_WE; // Disable Writing to register
323
324 return E_SUCCESS;
325 }
326
327 // *****************************************************************************
RTC_CheckBusy(void)328 int RTC_CheckBusy(void)
329 {
330 // Time-out transfer if it takes > BUSY_TIMEOUT microseconds
331 mxc_delay_start(MXC_DELAY_USEC(BUSY_TIMEOUT));
332 while (RTC_IS_BUSY) {
333 if (mxc_delay_check() != E_BUSY){
334 return E_BUSY;
335 }
336 }
337 mxc_delay_stop();
338 return E_SUCCESS;
339 }
340
341 // *****************************************************************************
RTC_GetFlags(void)342 int RTC_GetFlags(void)
343 {
344 return MXC_RTC->ctrl & (MXC_F_RTC_CTRL_ALDF | MXC_F_RTC_CTRL_ALSF | MXC_F_RTC_CTRL_RDY);
345 }
346
347 // *****************************************************************************
RTC_ClearFlags(int flags)348 int RTC_ClearFlags(int flags)
349 {
350 if (RTC_CheckBusy()) {
351 return E_BUSY;
352 }
353 MXC_RTC->ctrl &= ~(flags & (MXC_F_RTC_CTRL_ALDF | MXC_F_RTC_CTRL_ALSF | MXC_F_RTC_CTRL_RDY));
354
355 return E_SUCCESS;
356 }
357
358 // *****************************************************************************
RTC_GetSubSecond(void)359 int RTC_GetSubSecond(void)
360 {
361 #if TARGET == 32650
362 int ssec;
363 if(ChipRevision > 0xA1){
364 ssec = ((MXC_PWRSEQ->lpcn >> 12)& 0xF00) | (MXC_RTC->ssec & 0xFF);
365 }else{
366 ssec = MXC_RTC->ssec;
367 }
368 return ssec;
369 #else
370 return MXC_RTC->ssec;
371 #endif
372 }
373
374 // *****************************************************************************
RTC_GetSecond(void)375 int RTC_GetSecond(void)
376 {
377 return MXC_RTC->sec;
378 }
379
380 // *****************************************************************************
RTC_GetTime(uint32_t * sec,uint32_t * subsec)381 int RTC_GetTime(uint32_t* sec, uint32_t* subsec)
382 {
383 uint32_t temp_sec;
384 do {
385 // Check if an update is about to happen.
386 if(!(MXC_RTC->ctrl & MXC_F_RTC_CTRL_RDY)) {
387 return E_BUSY;
388 }
389
390 // Read the seconds count.
391 temp_sec = RTC_GetSecond();
392
393 // Check if an update is about to happen.
394 if(!(MXC_RTC->ctrl & MXC_F_RTC_CTRL_RDY)) {
395 return E_BUSY;
396 }
397
398 // Read the sub-seconds count.
399 *subsec = RTC_GetSubSecond();
400
401 // Check if an update is about to happen.
402 if(!(MXC_RTC->ctrl & MXC_F_RTC_CTRL_RDY)) {
403 return E_BUSY;
404 }
405
406 // Read the seconds count.
407 *sec = RTC_GetSecond();
408
409 // Repeat until a steady state is reached.
410 } while (temp_sec != *sec);
411
412 return E_NO_ERROR;
413 }
414
415 // *****************************************************************************
RTC_IsEnabled(void)416 int RTC_IsEnabled(void)
417 {
418 return RTC_IS_ENABLED;
419 }
420