1 /*
2  * Copyright 2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_bbnsm.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.bbnsm"
17 #endif
18 
19 /*******************************************************************************
20  * Prototypes
21  ******************************************************************************/
22 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
23 /*!
24  * @brief Get the BBNSM instance from peripheral base address.
25  *
26  * @param base BBNSM peripheral base address.
27  *
28  * @return BBNSM instance.
29  */
30 static uint32_t BBNSM_GetInstance(BBNSM_Type *base);
31 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
32 
33 /*******************************************************************************
34  * Variables
35  ******************************************************************************/
36 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
37 /*! @brief Pointer to bbnsm_lp clock. */
38 const clock_ip_name_t s_bbnsmClock[] = BBNSM_CLOCKS;
39 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
40 
41 /*******************************************************************************
42  * Code
43  ******************************************************************************/
44 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
BBNSM_GetInstance(BBNSM_Type * base)45 static uint32_t BBNSM_GetInstance(BBNSM_Type *base)
46 {
47     return 0U;
48 }
49 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
50 
51 /*!
52  * brief Ungates the BBNSM clock.
53  *
54  * note This API should be called at the beginning of the application using the BBNSM driver.
55  *
56  * param base   BBNSM peripheral base address
57  */
BBNSM_Init(BBNSM_Type * base)58 void BBNSM_Init(BBNSM_Type *base)
59 {
60 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
61     uint32_t instance = BBNSM_GetInstance(base);
62     CLOCK_EnableClock(s_bbnsmClock[instance]);
63 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
64 }
65 
66 /*!
67  * brief Deinit the BBNSM section.
68  *
69  * param base BBNSM peripheral base address
70  */
BBNSM_Deinit(BBNSM_Type * base)71 void BBNSM_Deinit(BBNSM_Type *base)
72 {
73 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
74     uint32_t instance = BBNSM_GetInstance(base);
75     CLOCK_DisableClock(s_bbnsmClock[instance]);
76 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
77 }
78 
79 /*!
80  * brief Ungates the BBNSM clock and configures the peripheral for basic operation.
81  *
82  * note This API should be called at the beginning of the application using the BBNSM driver.
83  *
84  * param base   BBNSM peripheral base address
85  * param config Pointer to the user's BBNSM configuration structure.
86  */
BBNSM_RTC_Init(BBNSM_Type * base,const bbnsm_rtc_config_t * config)87 void BBNSM_RTC_Init(BBNSM_Type *base, const bbnsm_rtc_config_t *config)
88 {
89     assert(config != NULL);
90 
91 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
92     uint32_t instance = BBNSM_GetInstance(base);
93     CLOCK_EnableClock(s_bbnsmClock[instance]);
94 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
95 
96     if (config->rtcCalEnable)
97     {
98         base->BBNSM_CTRL = BBNSM_BBNSM_CTRL_CAL_VAL(config->rtcCalValue);
99         base->BBNSM_CTRL |= BBNSM_BBNSM_CTRL_CAL_EN(0x1);
100     }
101 
102     BBNSM_RTC_StartTimer(base);
103 }
104 
105 /*!
106  * brief Stops the RTC timer.
107  *
108  * param base BBNSM peripheral base address
109  */
BBNSM_RTC_Deinit(BBNSM_Type * base)110 void BBNSM_RTC_Deinit(BBNSM_Type *base)
111 {
112     base->BBNSM_CTRL &= ~BBNSM_BBNSM_CTRL_RTC_EN(0x2);
113 
114 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && defined(BBNSM_CLOCKS))
115     uint32_t instance = BBNSM_GetInstance(base);
116     CLOCK_DisableClock(s_bbnsmClock[instance]);
117 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
118 }
119 
120 /*!
121  * brief Fills in the BBNSM config struct with the default settings.
122  *
123  * The default values are as follows.
124  * code
125  *    config->rtccalenable = false;
126  *    config->rtccalvalue = 0U;
127  * endcode
128  * param config Pointer to the user's BBNSM RTC configuration structure.
129  */
BBNSM_RTC_GetDefaultConfig(bbnsm_rtc_config_t * config)130 void BBNSM_RTC_GetDefaultConfig(bbnsm_rtc_config_t *config)
131 {
132     assert(config != NULL);
133 
134     /* Initializes the configure structure to zero. */
135     (void)memset(config, 0, sizeof(*config));
136 
137     config->rtcCalEnable = false;
138     config->rtcCalValue  = 0U;
139 }
140 
BBNSM_RTC_GetSeconds(BBNSM_Type * base)141 uint32_t BBNSM_RTC_GetSeconds(BBNSM_Type *base)
142 {
143     uint32_t seconds = 0;
144     uint32_t tmp     = 0;
145 
146     /* Do consecutive reads until value is correct */
147     do
148     {
149         seconds = tmp;
150         tmp     = (base->BBNSM_RTC_MS << 17U);
151         tmp |= (base->BBNSM_RTC_LS >> 15U);
152     } while (tmp != seconds);
153 
154     return seconds;
155 }
156 
157 /*!
158  * brief Sets the BBNSM RTC date and time according to the given time structure.
159  *
160  * param base     BBNSM peripheral base address
161  * param seconds
162  */
BBNSM_RTC_SetSeconds(BBNSM_Type * base,uint32_t seconds)163 void BBNSM_RTC_SetSeconds(BBNSM_Type *base, uint32_t seconds)
164 {
165     uint32_t tmp = base->BBNSM_CTRL;
166 
167     /* disable RTC */
168     BBNSM_RTC_StopTimer(base);
169 
170     base->BBNSM_RTC_MS = (uint32_t)(seconds >> 17U);
171     base->BBNSM_RTC_LS = (uint32_t)(seconds << 15U);
172 
173     /* reenable RTC in case that it was enabled before */
174     if ((tmp & BBNSM_BBNSM_CTRL_RTC_EN(0x2)) != 0U)
175     {
176         BBNSM_RTC_StartTimer(base);
177     }
178 }
179 
180 /*!
181  * brief Sets the BBNSM RTC alarm time.
182  *
183  * The function sets the RTC alarm. It also checks whether the specified alarm
184  * time is greater than the present time. If not, the function does not set the alarm
185  * and returns an error.
186  * Please note, that RTC alarm has limited resolution because only 32 most
187  * significant bits of RTC counter are compared to RTC Alarm register.
188  * If the alarm time is beyond RTC resolution, the function does not set the alarm
189  * and returns an error.
190  *
191  * param base      BBNSM peripheral base address
192  * param alarmTime Pointer to the structure where the alarm time is stored.
193  *
194  * return kStatus_Success: success in setting the BBNSM RTC alarm
195  *         kStatus_InvalidArgument: Error because the alarm datetime format is incorrect
196  *         kStatus_Fail: Error because the alarm time has already passed or is beyond resolution
197  */
BBNSM_RTC_SetAlarm(BBNSM_Type * base,uint32_t alarmSeconds)198 status_t BBNSM_RTC_SetAlarm(BBNSM_Type *base, uint32_t alarmSeconds)
199 {
200     uint32_t currSeconds = 0U;
201     uint32_t tmp;
202 
203     currSeconds = BBNSM_RTC_GetSeconds(base);
204 
205     /* Return error if the alarm time has passed */
206     if (alarmSeconds <= currSeconds)
207     {
208         return kStatus_Fail;
209     }
210 
211     /* disable RTC alarm interrupt */
212     tmp = base->BBNSM_INT_EN &
213           ~BBNSM_BBNSM_INT_EN_TA_INT_EN(
214               0x3); /* Clear TA_INT_EN field to avoid writing an invalid value(0b00/0b11) to the TA_INT_EN field */
215 
216     base->BBNSM_INT_EN = tmp | BBNSM_BBNSM_INT_EN_TA_INT_EN(0x1);
217     while ((base->BBNSM_INT_EN & BBNSM_BBNSM_INT_EN_TA_INT_EN(0x1)) == 0U)
218     {
219     }
220 
221     /* Set alarm in seconds*/
222     base->BBNSM_TA = alarmSeconds;
223 
224     /* Enable RTC alarm interrupt */
225     tmp = base->BBNSM_INT_EN &
226           ~BBNSM_BBNSM_INT_EN_TA_INT_EN(
227               0x3); /* Clear TA_INT_EN field to avoid writing an invalid value(0b11) to the TA_INT_EN field */
228     base->BBNSM_INT_EN = tmp | BBNSM_BBNSM_INT_EN_TA_INT_EN(0x2);
229 
230     /* Time alarm enable */
231     tmp =
232         base->BBNSM_CTRL &
233         ~BBNSM_BBNSM_CTRL_TA_EN(0x3); /* Clear TA_EN field to avoid writing an invalid value(0b11) to the TA_EN field */
234     base->BBNSM_CTRL = tmp | BBNSM_BBNSM_CTRL_TA_EN(0x2);
235 
236     return kStatus_Success;
237 }
238 
239 /*!
240  * brief Returns the BBNSM RTC alarm time.
241  *
242  * param base     BBNSM peripheral base address
243  */
BBNSM_RTC_GetAlarm(BBNSM_Type * base)244 uint32_t BBNSM_RTC_GetAlarm(BBNSM_Type *base)
245 {
246     /* Get alarm in seconds  */
247     return base->BBNSM_TA;
248 }
249 
250 /*!
251  * brief Gets the BBNSM status flags.
252  *
253  * param base BBNSM peripheral base address
254  *
255  * return The status flags. This is the logical OR of members of the
256  *         enumeration ::bbnsm_status_flags_t
257  */
BBNSM_GetStatusFlags(BBNSM_Type * base)258 uint32_t BBNSM_GetStatusFlags(BBNSM_Type *base)
259 {
260     return base->BBNSM_EVENTS;
261 }
262 
263 /*!
264  * brief Gets the enabled BBNSM interrupts.
265  *
266  * param base BBNSM peripheral base address
267  *
268  * return The enabled interrupts. This is the logical OR of members of the
269  *         enumeration ::bbnsm_interrupt_enable_t
270  */
BBNSM_GetEnabledInterrupts(BBNSM_Type * base)271 uint32_t BBNSM_GetEnabledInterrupts(BBNSM_Type *base)
272 {
273     return base->BBNSM_INT_EN;
274 }
275