1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019, 2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_irtc.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.irtc"
18 #endif
19 
20 #define IRTC_BASE_YEAR   (2112U)
21 #define YEAR_RANGE_START (1984U) /* Valid values for year range from -128 to 127; 2112 - 128 */
22 #define YEAR_RANGE_END   (2239U) /* Valid values for year range from -128 to 127; 2112 + 127 */
23 
24 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
25     (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
26 /*! @brief Array to map IRTC instance number to base pointer. */
27 static RTC_Type *const kIrtcBases[] = RTC_BASE_PTRS;
28 #endif
29 
30 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
31 /*! @brief Array to map IRTC instance number to clock gate enum. */
32 static clock_ip_name_t const kIrtcClocks[] = RTC_CLOCKS;
33 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
34 
35 #if defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET
36 /*! @brief Pointers to IRTC resets for each instance. */
37 static const reset_ip_name_t kIrtcResets[] = RTC_RSTS;
38 #endif
39 
40 /*******************************************************************************
41  * Prototypes
42  ******************************************************************************/
43 /*!
44  * @brief Checks whether the date and time passed in is valid
45  *
46  * @param datetime Pointer to structure where the date and time details are stored
47  *
48  * @return Returns false if the date & time details are out of range; true if in range
49  */
50 static bool IRTC_CheckDatetimeFormat(const irtc_datetime_t *datetime);
51 
52 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
53     (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
54 /*!
55  * @brief Returns an instance number given a base address.
56  *
57  * @param base The IRTC peripheral base address.
58  * @return IRTC instance number starting from 0. If cannot the base address is
59  * not a valid address, this function returns -1.
60  */
61 static int32_t IRTC_GetInstance(RTC_Type *base);
62 #endif
63 
64 /*******************************************************************************
65  * Code
66  ******************************************************************************/
IRTC_CheckDatetimeFormat(const irtc_datetime_t * datetime)67 static bool IRTC_CheckDatetimeFormat(const irtc_datetime_t *datetime)
68 {
69     assert(NULL != datetime);
70 
71     bool fgRet = true;
72 
73     /* Table of days in a month for a non leap year */
74     uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
75 
76     /* Check year, month, hour, minute, seconds */
77     if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
78         (datetime->month < 1U) || (datetime->weekDay >= 7U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) ||
79         (datetime->second >= 60U))
80     {
81         /* If not correct then error*/
82         fgRet = false;
83     }
84     else
85     {
86         /* Adjust the days in February for a leap year */
87         if (((0U == (datetime->year & 3U)) && (0U != (datetime->year % 100U))) || (0U == (datetime->year % 400U)))
88         {
89             daysPerMonth[2] = 29U;
90         }
91 
92         /* Check the validity of the day */
93         if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
94         {
95             fgRet = false;
96         }
97     }
98     return fgRet;
99 }
100 
101 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
102     (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
IRTC_GetInstance(RTC_Type * base)103 static int32_t IRTC_GetInstance(RTC_Type *base)
104 {
105     int32_t instance;
106 
107     for (instance = 0; instance < (int32_t)ARRAY_SIZE(kIrtcBases); ++instance)
108     {
109         if (MSDK_REG_SECURE_ADDR(kIrtcBases[instance]) == MSDK_REG_SECURE_ADDR(base))
110         {
111             break;
112         }
113     }
114 
115     if (instance >= (int32_t)ARRAY_SIZE(kIrtcBases))
116     {
117         instance = -1;
118     }
119 
120     return instance;
121 }
122 #endif
123 
124 /*!
125  * brief Ungates the IRTC clock and configures the peripheral for basic operation.
126  *
127  * This function initiates a soft-reset of the IRTC module, this has not effect on DST,
128  * calendaring, standby time and tamper detect registers.
129  *
130  * note This API should be called at the beginning of the application using the IRTC driver.
131  *
132  * param base   IRTC peripheral base address
133  * param config Pointer to user's IRTC config structure.
134  *
135  * return kStatus_Fail if we cannot disable register write protection
136  */
IRTC_Init(RTC_Type * base,const irtc_config_t * config)137 status_t IRTC_Init(RTC_Type *base, const irtc_config_t *config)
138 {
139     assert(NULL != config);
140 
141     uint16_t reg;
142     status_t status = kStatus_Success;
143 
144 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
145     (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
146     int32_t instance = IRTC_GetInstance(base);
147     if (instance < 0)
148     {
149         return kStatus_InvalidArgument;
150     }
151 #endif
152 
153 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
154     CLOCK_EnableClock(kIrtcClocks[instance]);
155 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
156 
157 #if defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET
158     RESET_ReleasePeripheralReset(kIrtcResets[instance]);
159 #endif
160 
161     /* Unlock to allow register write operation */
162     if (kStatus_Success == IRTC_SetWriteProtection(base, false))
163     {
164         /* Issue a software reset */
165         IRTC_Reset(base);
166 
167 #if !defined(FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE) || (!FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE)
168         /* Setup the wakeup pin select */
169         if (config->wakeupSelect)
170         {
171             base->CTRL2 |= RTC_CTRL2_WAKEUP_MODE_MASK;
172         }
173         else
174         {
175             base->CTRL2 &= ~(uint16_t)RTC_CTRL2_WAKEUP_MODE_MASK;
176         }
177 #endif
178         /* Setup alarm match operation, sampling clock operation in standby mode, 16.384kHz RTC clock and selected clock outout to other peripherals */
179         reg = base->CTRL;
180         reg &= ~(
181 #if !defined(FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK) || (!FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK)
182                (uint16_t)RTC_CTRL_TIMER_STB_MASK_MASK |
183 #endif
184 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
185                (uint16_t)RTC_CTRL_CLK_SEL_MASK |
186 #endif
187 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE) && FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE
188                (uint16_t)RTC_CTRL_CLKO_DIS_MASK |
189 #endif
190                (uint16_t)RTC_CTRL_ALM_MATCH_MASK);
191         reg |= (
192 #if !defined(FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK) || (!FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK)
193                RTC_CTRL_TIMER_STB_MASK(config->timerStdMask) |
194 #endif
195 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
196                RTC_CTRL_CLK_SEL(config->clockSelect) |
197 #endif
198 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE) && FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE
199                RTC_CTRL_CLKO_DIS(config->disableClockOutput) |
200 #endif
201                RTC_CTRL_ALM_MATCH(config->alrmMatch));
202         base->CTRL = reg;
203     }
204     else
205     {
206         status = kStatus_Fail;
207     }
208 
209     return status;
210 }
211 
212 /*
213  * brief Gate the IRTC clock
214  *
215  * param base IRTC peripheral base address
216  */
IRTC_Deinit(RTC_Type * base)217 status_t IRTC_Deinit(RTC_Type *base)
218 {
219 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
220     int32_t instance = IRTC_GetInstance(base);
221     if (instance < 0)
222     {
223         return kStatus_InvalidArgument;
224     }
225 
226     CLOCK_DisableClock(kIrtcClocks[instance]);
227 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
228 
229     return kStatus_Success;
230 }
231 
232 /*!
233  * brief Fill in the IRTC config struct with the default settings
234  *
235  * The default values are:
236  * code
237  *    config->wakeupSelect = true;
238  *    config->timerStdMask = false;
239  *    config->alrmMatch = kRTC_MatchSecMinHr;
240  * endcode
241  * param config Pointer to user's IRTC config structure.
242  */
IRTC_GetDefaultConfig(irtc_config_t * config)243 void IRTC_GetDefaultConfig(irtc_config_t *config)
244 {
245     assert(NULL != config);
246 
247     /* Initializes the configure structure to zero. */
248     (void)memset(config, 0, sizeof(*config));
249 
250 #if !defined(FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE) || (!FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE)
251     /* Tamper pin 0 is used as a wakeup/hibernation pin */
252     config->wakeupSelect = true;
253 #endif
254 
255 #if !defined(FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK) || (!FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK)
256     /* Sampling clock are not gated when in standby mode */
257     config->timerStdMask = false;
258 #endif
259 
260     /* Only seconds, minutes and hours are matched when generating an alarm */
261     config->alrmMatch = kRTC_MatchSecMinHr;
262 
263 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
264     /* 16.384kHz clock is selected */
265     config->clockSelect = kIRTC_Clk16K;
266 #endif
267 
268 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE) && FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE
269     /* The selected clock is not output to other peripherals */
270     config->disableClockOutput = true;
271 #endif
272 }
273 
274 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
275 /*!
276  * brief Sets the IRTC date and time according to the given time structure.
277  *
278  * The IRTC counter is started after the time is set.
279  *
280  * param base     IRTC peripheral base address
281  * param datetime Pointer to structure where the date and time details to set are stored
282  *
283  * return kStatus_Success: success in setting the time and starting the IRTC
284  *         kStatus_InvalidArgument: failure. An error occurs because the datetime format is incorrect.
285  */
IRTC_SetDatetime(RTC_Type * base,const irtc_datetime_t * datetime)286 status_t IRTC_SetDatetime(RTC_Type *base, const irtc_datetime_t *datetime)
287 {
288     assert(NULL != datetime);
289 
290     status_t status = kStatus_Success;
291 
292     /* Return error if the time provided is not valid */
293     if (IRTC_CheckDatetimeFormat(datetime))
294     {
295         /* The register stores the offset in years from the base year of 2112 */
296         if (datetime->year < IRTC_BASE_YEAR)
297         {
298             /* Values for years less than the base year range from -128 to 1 */
299             base->YEARMON =
300                 RTC_YEARMON_YROFST(0x100U + datetime->year - IRTC_BASE_YEAR) | RTC_YEARMON_MON_CNT(datetime->month);
301         }
302         else
303         {
304             /* Values for years greater or equal to the base year range from 0 to 127 */
305             base->YEARMON = RTC_YEARMON_YROFST(datetime->year - IRTC_BASE_YEAR) | RTC_YEARMON_MON_CNT(datetime->month);
306         }
307         /* Update the Day Count and Day of the week field */
308         base->DAYS = RTC_DAYS_DOW(datetime->weekDay) | RTC_DAYS_DAY_CNT(datetime->day);
309 
310         /* Update hour and minute field */
311         base->HOURMIN = RTC_HOURMIN_HOUR_CNT(datetime->hour) | RTC_HOURMIN_MIN_CNT(datetime->minute);
312 
313         /* Update the seconds register */
314         base->SECONDS = RTC_SECONDS_SEC_CNT(datetime->second);
315     }
316     else
317     {
318         status = kStatus_InvalidArgument;
319     }
320 
321     return status;
322 }
323 #endif /* FSL_FEATURE_RTC_IS_SLAVE  */
324 
325 /*!
326  * brief Gets the IRTC time and stores it in the given time structure.
327  *
328  * param base     IRTC peripheral base address
329  * param datetime Pointer to structure where the date and time details are stored.
330  */
IRTC_GetDatetime(RTC_Type * base,irtc_datetime_t * datetime)331 void IRTC_GetDatetime(RTC_Type *base, irtc_datetime_t *datetime)
332 {
333     assert(NULL != datetime);
334 
335     uint16_t temp = base->YEARMON;
336 
337     datetime->year =
338         (uint16_t)IRTC_BASE_YEAR + (uint16_t)((int8_t)(uint8_t)((temp >> RTC_YEARMON_YROFST_SHIFT) & 0xFFU));
339     datetime->month = (uint8_t)temp & RTC_YEARMON_MON_CNT_MASK;
340 
341     temp              = base->DAYS;
342     datetime->weekDay = (uint8_t)((temp & RTC_DAYS_DOW_MASK) >> RTC_DAYS_DOW_SHIFT);
343     datetime->day     = (uint8_t)temp & RTC_DAYS_DAY_CNT_MASK;
344 
345     temp             = base->HOURMIN;
346     datetime->hour   = (uint8_t)((temp & RTC_HOURMIN_HOUR_CNT_MASK) >> RTC_HOURMIN_HOUR_CNT_SHIFT);
347     datetime->minute = (uint8_t)temp & RTC_HOURMIN_MIN_CNT_MASK;
348 
349     datetime->second = (uint8_t)(base->SECONDS) & RTC_SECONDS_SEC_CNT_MASK;
350 }
351 
352 /*!
353  * brief Sets the IRTC alarm time
354  *
355  * param base      RTC peripheral base address
356  * param alarmTime Pointer to structure where the alarm time is stored.
357  *
358  * note weekDay field of alarmTime is not used during alarm match and should be set to 0
359  *
360  * return kStatus_Success: success in setting the alarm
361  *         kStatus_InvalidArgument: error in setting the alarm. Error occurs because the alarm
362  *                                  datetime format is incorrect.
363  */
IRTC_SetAlarm(RTC_Type * base,const irtc_datetime_t * alarmTime)364 status_t IRTC_SetAlarm(RTC_Type *base, const irtc_datetime_t *alarmTime)
365 {
366     assert(NULL != alarmTime);
367 
368     status_t status = kStatus_Success;
369 
370     /* Return error if the alarm time provided is not valid */
371     if (IRTC_CheckDatetimeFormat(alarmTime))
372     {
373         /* Set the alarm year */
374         if (alarmTime->year < IRTC_BASE_YEAR)
375         {
376             base->ALM_YEARMON = RTC_ALM_YEARMON_ALM_YEAR(0x100U + alarmTime->year - IRTC_BASE_YEAR) |
377                                 RTC_ALM_YEARMON_ALM_MON(alarmTime->month);
378         }
379         else
380         {
381             base->ALM_YEARMON =
382                 RTC_ALM_YEARMON_ALM_YEAR(alarmTime->year - IRTC_BASE_YEAR) | RTC_ALM_YEARMON_ALM_MON(alarmTime->month);
383         }
384 
385         /* Set the alarm day */
386         base->ALM_DAYS = RTC_ALM_DAYS_ALM_DAY(alarmTime->day);
387 
388         /* Set the alarm hour and minute */
389         base->ALM_HOURMIN = RTC_ALM_HOURMIN_ALM_HOUR(alarmTime->hour) | RTC_ALM_HOURMIN_ALM_MIN(alarmTime->minute);
390 
391         /* Set the alarm seconds */
392         base->ALM_SECONDS = RTC_ALM_SECONDS_ALM_SEC(alarmTime->second);
393     }
394     else
395     {
396         status = kStatus_InvalidArgument;
397     }
398 
399     return status;
400 }
401 
402 /*!
403  * brief Returns the IRTC alarm time.
404  *
405  * param base     RTC peripheral base address
406  * param datetime Pointer to structure where the alarm date and time details are stored.
407  */
IRTC_GetAlarm(RTC_Type * base,irtc_datetime_t * datetime)408 void IRTC_GetAlarm(RTC_Type *base, irtc_datetime_t *datetime)
409 {
410     assert(NULL != datetime);
411 
412     uint16_t temp = base->ALM_YEARMON;
413 
414     datetime->year =
415         (uint16_t)IRTC_BASE_YEAR + (uint16_t)((int8_t)(uint8_t)((temp >> RTC_ALM_YEARMON_ALM_YEAR_SHIFT) & 0xFFU));
416     datetime->month = (uint8_t)temp & RTC_ALM_YEARMON_ALM_MON_MASK;
417 
418     datetime->day = (uint8_t)(base->ALM_DAYS) & RTC_ALM_DAYS_ALM_DAY_MASK;
419 
420     temp             = base->ALM_HOURMIN;
421     datetime->hour   = (uint8_t)((temp & RTC_ALM_HOURMIN_ALM_HOUR_MASK) >> RTC_ALM_HOURMIN_ALM_HOUR_SHIFT);
422     datetime->minute = (uint8_t)temp & RTC_ALM_HOURMIN_ALM_MIN_MASK;
423 
424     datetime->second = (uint8_t)(base->ALM_SECONDS) & RTC_ALM_SECONDS_ALM_SEC_MASK;
425 }
426 
427 /*!
428  * brief Locks or unlocks IRTC registers for write access.
429  *
430  * note When the registers are unlocked, they remain in unlocked state for
431  * 2 seconds, after which they are locked automatically. After
432  * power-on-reset, the registers come out unlocked and they are locked
433  * automatically 15 seconds after power on.
434  *
435  * param base IRTC peripheral base address
436  * param lock true: Lock IRTC registers; false: Unlock IRTC registers.
437  *
438  * return kStatus_Success: if lock or unlock operation is successful
439  *         kStatus_Fail: if lock or unlock operation fails even after multiple retry attempts
440  */
IRTC_SetWriteProtection(RTC_Type * base,bool lock)441 status_t IRTC_SetWriteProtection(RTC_Type *base, bool lock)
442 {
443     /* Retry before giving up */
444     uint8_t repeatProtectSequence = 0xFFU;
445     status_t status               = kStatus_Success;
446 
447     if (!lock)
448     {
449         /* Unlock IRTC registers */
450         while ((0U != (base->STATUS & (uint16_t)RTC_STATUS_WRITE_PROT_EN_MASK)) && (0U != repeatProtectSequence))
451         {
452             /* Access in 8-bit mode while storing the value */
453             *(__IO uint8_t *)(&base->STATUS) = 0U;
454             *(__IO uint8_t *)(&base->STATUS) = 0x40U;
455             *(__IO uint8_t *)(&base->STATUS) = 0xC0U;
456             *(__IO uint8_t *)(&base->STATUS) = 0x80U;
457             repeatProtectSequence--;
458         }
459     }
460     else
461     {
462         /* Lock IRTC registers */
463         while ((0U == ((base->STATUS & (uint16_t)RTC_STATUS_WRITE_PROT_EN_MASK) >> RTC_STATUS_WRITE_PROT_EN_SHIFT)) &&
464                (0U != repeatProtectSequence))
465         {
466             *(__IO uint8_t *)(&base->STATUS) = 0x80U;
467             repeatProtectSequence--;
468         }
469     }
470 
471     /* Lock/unlock was not successful even after trying 256 times */
472     if (0U == repeatProtectSequence)
473     {
474         status = kStatus_Fail;
475     }
476 
477     return status;
478 }
479 
480 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
481 /*!
482  * brief Sets the IRTC daylight savings start and stop date and time.
483  *
484  * It also enables the daylight saving bit in the IRTC control register
485  *
486  * param base     IRTC peripheral base address
487  * param datetime Pointer to a structure where the date and time details are stored.
488  */
IRTC_SetDaylightTime(RTC_Type * base,const irtc_daylight_time_t * datetime)489 void IRTC_SetDaylightTime(RTC_Type *base, const irtc_daylight_time_t *datetime)
490 {
491     assert(NULL != datetime);
492 
493     /* Disable daylight saving time */
494     base->CTRL &= ~(uint16_t)RTC_CTRL_DST_EN_MASK;
495 
496     /* Set the daylight saving time start month and end month value */
497     base->DST_MONTH =
498         RTC_DST_MONTH_DST_START_MONTH(datetime->startMonth) | RTC_DST_MONTH_DST_END_MONTH(datetime->endMonth);
499 
500     /* Set the daylight saving time start day and end day value */
501     base->DST_DAY = RTC_DST_DAY_DST_START_DAY(datetime->startDay) | RTC_DST_DAY_DST_END_DAY(datetime->endDay);
502 
503     /* Set the daylight saving time start hour and end hour value */
504     base->DST_HOUR = RTC_DST_HOUR_DST_START_HOUR(datetime->startHour) | RTC_DST_HOUR_DST_END_HOUR(datetime->endHour);
505 
506     /* Enable daylight saving time */
507     base->CTRL |= RTC_CTRL_DST_EN_MASK;
508 }
509 #endif /* FSL_FEATURE_RTC_IS_SLAVE  */
510 
511 /*!
512  * brief Gets the IRTC daylight savings time and stores it in the given time structure.
513  *
514  * param base     IRTC peripheral base address
515  * param datetime Pointer to a structure where the date and time details are stored.
516  */
IRTC_GetDaylightTime(RTC_Type * base,irtc_daylight_time_t * datetime)517 void IRTC_GetDaylightTime(RTC_Type *base, irtc_daylight_time_t *datetime)
518 {
519     assert(NULL != datetime);
520 
521     uint16_t temp = base->DST_MONTH;
522 
523     /* Get the daylight savings time start and end month value */
524     datetime->startMonth =
525         (uint8_t)((temp & RTC_DST_MONTH_DST_START_MONTH_MASK) >> RTC_DST_MONTH_DST_START_MONTH_SHIFT);
526     datetime->endMonth = (uint8_t)((temp & RTC_DST_MONTH_DST_END_MONTH_MASK) >> RTC_DST_MONTH_DST_END_MONTH_SHIFT);
527 
528     /* Get the daylight savings time start and end day value */
529     temp               = base->DST_DAY;
530     datetime->startDay = (uint8_t)((temp & RTC_DST_DAY_DST_START_DAY_MASK) >> RTC_DST_DAY_DST_START_DAY_SHIFT);
531     datetime->endDay   = (uint8_t)((temp & RTC_DST_DAY_DST_END_DAY_MASK) >> RTC_DST_DAY_DST_END_DAY_SHIFT);
532 
533     /* Get the daylight savings time start and end hour value */
534     temp                = base->DST_HOUR;
535     datetime->startHour = (uint8_t)((temp & RTC_DST_HOUR_DST_START_HOUR_MASK) >> RTC_DST_HOUR_DST_START_HOUR_SHIFT);
536     datetime->endHour   = (uint8_t)((temp & RTC_DST_HOUR_DST_END_HOUR_MASK) >> RTC_DST_HOUR_DST_END_HOUR_SHIFT);
537 }
538 
539 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
540 /*!
541  * brief Enables the coarse compensation and sets the value in the IRTC compensation register.
542  *
543  * param base                 IRTC peripheral base address
544  * param compensationValue    Compensation value is a 2's complement value.
545  * param compensationInterval Compensation interval.
546  */
IRTC_SetCoarseCompensation(RTC_Type * base,uint8_t compensationValue,uint8_t compensationInterval)547 void IRTC_SetCoarseCompensation(RTC_Type *base, uint8_t compensationValue, uint8_t compensationInterval)
548 {
549     uint16_t reg;
550 
551     /* Set the compensation value and interval */
552     base->COMPEN = (uint16_t)compensationValue | ((uint16_t)compensationInterval << 8U);
553 
554     /* Disable fine and enable coarse compensation */
555     reg = base->CTRL;
556     reg &= ~(uint16_t)RTC_CTRL_FINEEN_MASK;
557     reg |= RTC_CTRL_COMP_EN_MASK;
558     base->CTRL = reg;
559 }
560 
561 /*!
562  * brief Enables the fine compensation and sets the value in the IRTC compensation register.
563  *
564  * param base                 The IRTC peripheral base address
565  * param integralValue        Compensation integral value; twos complement value of the integer part
566  * param fractionValue        Compensation fraction value expressed as number of clock cycles of a
567  *                             fixed 4.194304Mhz clock that have to be added.
568  * param accumulateFractional Flag indicating if we want to add to previous fractional part;
569  *                             true: Add to previously accumulated fractional part,
570  *                             false: Start afresh and overwrite current value
571  */
IRTC_SetFineCompensation(RTC_Type * base,uint8_t integralValue,uint8_t fractionValue,bool accumulateFractional)572 void IRTC_SetFineCompensation(RTC_Type *base, uint8_t integralValue, uint8_t fractionValue, bool accumulateFractional)
573 {
574     if (!accumulateFractional)
575     {
576         /* Disable compensation to clear previous accumulated fractional part */
577         base->CTRL &= ~(((uint16_t)1U << RTC_CTRL_COMP_EN_SHIFT) | ((uint16_t)1U << RTC_CTRL_FINEEN_SHIFT));
578     }
579 
580     /* Set the compensation fractional and integral parts */
581     base->COMPEN = ((uint16_t)fractionValue & 0x7FU) | (((uint16_t)integralValue & 0xFU) << 12U);
582     /* Enable fine compensation */
583     base->CTRL |= (RTC_CTRL_COMP_EN_MASK | RTC_CTRL_FINEEN_MASK);
584 }
585 #endif /* FSL_FEATURE_RTC_IS_SLAVE  */
586 
587 #if !defined(FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE) || (!FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE)
588 
589 /*!
590  * brief This function allows configuring the four tamper inputs.
591  *
592  * The function configures the filter properties for the three external tampers.
593  * It also sets up active/passive and direction of the tamper bits, which are not available
594  * on all platforms.
595  * note This function programs the tamper filter parameters. The user must gate the 32K clock to
596  * the RTC before calling this function. It is assumed that the time and date are set after this
597  * and the tamper parameters do not require to be changed again later.
598  *
599  * param base         The IRTC peripheral base address
600  * param tamperNumber The IRTC tamper input to configure
601  * param tamperConfig The IRTC tamper properties
602  */
IRTC_SetTamperParams(RTC_Type * base,irtc_tamper_pins_t tamperNumber,const irtc_tamper_config_t * tamperConfig)603 void IRTC_SetTamperParams(RTC_Type *base, irtc_tamper_pins_t tamperNumber, const irtc_tamper_config_t *tamperConfig)
604 {
605     assert(NULL != tamperConfig);
606 
607     uint16_t reg = 0;
608 
609 #if defined(FSL_FEATURE_RTC_HAS_TAMPER_DIRECTION) && (FSL_FEATURE_RTC_HAS_TAMPER_DIRECTION)
610     reg = base->TAMPER_DIRECTION;
611     /* Set whether tamper pin is active or passive */
612     if (tamperConfig->activePassive)
613     {
614         /* In case of active tamper, set the direction */
615         reg |= (1U << tamperNumber);
616         if (tamperConfig->direction)
617         {
618             /* Tamper direction is output */
619             reg |= (1U << (RTC_TAMPER_DIRECTION_I_O_TAMP_SHIFT + tamperNumber));
620         }
621         else
622         {
623             /* Tamper direction is input */
624             reg &= ~(1U << (RTC_TAMPER_DIRECTION_I_O_TAMP_SHIFT + tamperNumber));
625         }
626     }
627     else
628     {
629         /* Passive tampers are input only and the direction bit is read only in this case */
630         reg &= ~(1U << tamperNumber);
631     }
632     base->TAMPER_DIRECTION = reg;
633 #endif /* FSL_FEATURE_RTC_HAS_TAMPER_DIRECTION */
634 
635     /* Set the filter properties for the external tamper pins */
636     switch (tamperNumber)
637     {
638         case kIRTC_Tamper_0:
639             /* Set the pin for Tamper 0 */
640 #if !defined(FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE) || (!FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE)
641             base->CTRL2 &= ~(uint16_t)RTC_CTRL2_WAKEUP_MODE_MASK;
642 #endif
643             reg = base->FILTER01_CFG;
644             reg &= ~((uint16_t)RTC_FILTER01_CFG_POL0_MASK | (uint16_t)RTC_FILTER01_CFG_FIL_DUR0_MASK |
645                      (uint16_t)RTC_FILTER01_CFG_CLK_SEL0_MASK);
646             reg |= (RTC_FILTER01_CFG_POL0(tamperConfig->pinPolarity) |
647                     RTC_FILTER01_CFG_FIL_DUR0(tamperConfig->filterDuration) |
648                     RTC_FILTER01_CFG_CLK_SEL0(tamperConfig->filterClk));
649             base->FILTER01_CFG = reg;
650             break;
651         case kIRTC_Tamper_1:
652             reg = base->FILTER01_CFG;
653             reg &= ~((uint16_t)RTC_FILTER01_CFG_POL1_MASK | (uint16_t)RTC_FILTER01_CFG_FIL_DUR1_MASK |
654                      (uint16_t)RTC_FILTER01_CFG_CLK_SEL1_MASK);
655             reg |= (RTC_FILTER01_CFG_POL1(tamperConfig->pinPolarity) |
656                     RTC_FILTER01_CFG_FIL_DUR1(tamperConfig->filterDuration) |
657                     RTC_FILTER01_CFG_CLK_SEL1(tamperConfig->filterClk));
658             base->FILTER01_CFG = reg;
659             break;
660 #if defined(FSL_FEATURE_RTC_HAS_FILTER23_CFG) && FSL_FEATURE_RTC_HAS_FILTER23_CFG
661         case kIRTC_Tamper_2:
662             reg = base->FILTER23_CFG;
663             reg &= ~((uint16_t)RTC_FILTER23_CFG_POL2_MASK | (uint16_t)RTC_FILTER23_CFG_FIL_DUR2_MASK |
664                      (uint16_t)RTC_FILTER23_CFG_CLK_SEL2_MASK);
665             reg |= (RTC_FILTER23_CFG_POL2(tamperConfig->pinPolarity) |
666                     RTC_FILTER23_CFG_FIL_DUR2(tamperConfig->filterDuration) |
667                     RTC_FILTER23_CFG_CLK_SEL2(tamperConfig->filterClk));
668             base->FILTER23_CFG = reg;
669             break;
670         case kIRTC_Tamper_3:
671             reg = base->FILTER23_CFG;
672             reg &= ~((uint16_t)RTC_FILTER23_CFG_POL3_MASK | (uint16_t)RTC_FILTER23_CFG_FIL_DUR3_MASK |
673                      (uint16_t)RTC_FILTER23_CFG_CLK_SEL3_MASK);
674             reg |= (RTC_FILTER23_CFG_POL3(tamperConfig->pinPolarity) |
675                     RTC_FILTER23_CFG_FIL_DUR3(tamperConfig->filterDuration) |
676                     RTC_FILTER23_CFG_CLK_SEL3(tamperConfig->filterClk));
677             base->FILTER23_CFG = reg;
678             break;
679 #else
680         case kIRTC_Tamper_2:
681             reg = base->FILTER2_CFG;
682             reg &= ~((uint16_t)RTC_FILTER2_CFG_POL2_MASK | (uint16_t)RTC_FILTER2_CFG_FIL_DUR2_MASK |
683                      (uint16_t)RTC_FILTER2_CFG_CLK_SEL2_MASK);
684             reg |= (RTC_FILTER2_CFG_POL2(tamperConfig->pinPolarity) |
685                     RTC_FILTER2_CFG_FIL_DUR2(tamperConfig->filterDuration) |
686                     RTC_FILTER2_CFG_CLK_SEL2(tamperConfig->filterClk));
687             base->FILTER2_CFG = reg;
688             break;
689 #endif
690 
691         default:
692             /* Internal tamper, does not have filter configuration. */
693             break;
694     }
695 }
696 
697 #endif
698 
699 #if !defined(FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE) || (!FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE)
700 #if defined(FSL_FEATURE_RTC_HAS_TAMPER_QUEUE) && (FSL_FEATURE_RTC_HAS_TAMPER_QUEUE)
701 
702 /*!
703  * brief This function reads the tamper timestamp and returns the associated tamper pin.
704  *
705  * The tamper timestamp has month, day, hour, minutes, and seconds. Ignore the year field as this
706  * information is not available in the tamper queue. The user should look at the RTC_YEARMON register
707  * for this because the expectation is that the queue is read at least once a year.
708  * Return the tamper pin number associated with the timestamp.
709  *
710  * param base             The IRTC peripheral base address
711  * param tamperTimestamp  The tamper timestamp
712  *
713  * return The tamper pin number
714  */
IRTC_ReadTamperQueue(RTC_Type * base,irtc_datetime_t * tamperTimestamp)715 uint8_t IRTC_ReadTamperQueue(RTC_Type *base, irtc_datetime_t *tamperTimestamp)
716 {
717     assert(NULL != tamperTimestamp);
718 
719     /* Read the register 2 times to get a entry*/
720     uint16_t temp1 = base->TAMPER_QUEUE;
721     uint16_t temp2 = base->TAMPER_QUEUE;
722     uint8_t tamperNum;
723 
724     /*
725      * Tamper queue does not store the year field as this value can be read from RTC_YEARMON.
726      * It is expected that the queue will be read at least once in a year.
727      */
728     tamperTimestamp->year = 0;
729     /* From the first read; TAMPER_DATA[4:0] is the hour field */
730     tamperTimestamp->hour = (uint8_t)temp1 & 0x1FU;
731     /* From the first read; TAMPER_DATA[9:5] is the day field */
732     tamperTimestamp->day = (uint8_t)(temp1 >> 5U) & 0x1FU;
733     /* From the first read; TAMPER_DATA[13:10] is the month field */
734     tamperTimestamp->month = (uint8_t)(temp1 >> 10U) & 0xFU;
735 
736     /* From the second read; TAMPER_DATA[5:0] is the seconds field */
737     tamperTimestamp->second = (uint8_t)temp2 & 0x3FU;
738     /* From the second read; TAMPER_DATA[11:6] is the minutes field */
739     tamperTimestamp->minute = (uint8_t)(temp2 >> 6U) & 0x3FU;
740     /* From the second read; TAMPER_DATA[14:12] is the tamper index */
741     tamperNum = (uint8_t)(temp2 >> 12U) & 0x7U;
742 
743     return tamperNum;
744 }
745 
746 #endif /* FSL_FEATURE_RTC_HAS_TAMPER_QUEUE */
747 #endif /* FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE */
748 
749 /*!
750  * brief Select which clock to output from RTC.
751  *
752  * Select which clock to output from RTC for other modules to use inside SoC, for example,
753  * RTC subsystem needs RTC to output 1HZ clock for sub-second counter.
754  *
755  * param base IRTC peripheral base address
756  * param cloOut select clock to use for output
757  */
IRTC_ConfigClockOut(RTC_Type * base,irtc_clockout_sel_t clkOut)758 void IRTC_ConfigClockOut(RTC_Type *base, irtc_clockout_sel_t clkOut)
759 {
760     uint16_t ctrlVal = base->CTRL;
761 
762     ctrlVal &= (uint16_t)(~RTC_CTRL_CLKOUT_MASK);
763 
764     ctrlVal |= RTC_CTRL_CLKOUT((uint16_t)clkOut);
765 
766 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
767     if (clkOut == kIRTC_ClkoutCoarse1Hz)
768     {
769         ctrlVal |= RTC_CTRL_COMP_EN_MASK;
770     }
771     else if (clkOut == kIRTC_ClkoutFine1Hz)
772     {
773         ctrlVal |= RTC_CTRL_FINEEN_MASK;
774     }
775     else
776     {
777         /* empty else */
778     }
779 #endif /* FSL_FEATURE_RTC_IS_SLAVE */
780 
781     base->CTRL = ctrlVal;
782 }
783 
784 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
785 
786 /*!
787  * brief Select which clock is used by RTC.
788  *
789  * Select which clock is used by RTC to output to the peripheral
790  * and divided to generate a 512 Hz clock and a 1 Hz clock.
791  *
792  * param base IRTC peripheral base address
793  * param clkSelect select clock used by RTC
794  */
IRTC_ConfigClockSelect(RTC_Type * base,irtc_clock_select_t clkSelect)795 void IRTC_ConfigClockSelect(RTC_Type *base, irtc_clock_select_t clkSelect)
796 {
797     uint16_t ctrlVal = base->CTRL;
798 
799     ctrlVal &= (uint16_t)(~RTC_CTRL_CLK_SEL_MASK);
800 
801     ctrlVal |= RTC_CTRL_CLK_SEL((uint16_t)clkSelect);
802 
803     base->CTRL = ctrlVal;
804 }
805 
806 #endif /* FSL_FEATURE_RTC_HAS_CLOCK_SELECT */
807