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