1 /*
2 * Copyright (c) 2023 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <zephyr/device.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/irq.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/devicetree.h>
13 #include <zephyr/drivers/rtc.h>
14 #include <zephyr/drivers/clock_control.h>
15 #include <zephyr/drivers/clock_control/smartbond_clock_control.h>
16 #include <DA1469xAB.h>
17 #include <da1469x_config.h>
18 #include <da1469x_pdc.h>
19 #include "rtc_utils.h"
20 #include <zephyr/logging/log.h>
21
22 LOG_MODULE_REGISTER(rtc_smartbond, CONFIG_RTC_LOG_LEVEL);
23
24 #define DT_DRV_COMPAT renesas_smartbond_rtc
25
26 #define SMARTBOND_IRQN DT_INST_IRQN(0)
27 #define SMARTBOND_IRQ_PRIO DT_INST_IRQ(0, priority)
28
29 #define RTC_ALARMS_COUNT DT_PROP(DT_NODELABEL(rtc), alarms_count)
30
31 #define TM_YEAR_REF 1900
32 #define RTC_DIV_DENOM_1000 0
33 #define RTC_DIV_DENOM_1024 1
34
35 #define RTC_SMARTBOND_SUPPORTED_ALARM_FIELDS \
36 (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \
37 RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_MONTHDAY)
38
39 #define RTC_TIME_REG_SET_FIELD(_field, _var, _val) \
40 ((_var) = \
41 ((_var) & ~(RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _T_Msk | \
42 RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Msk)) | \
43 (((_val) << RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Pos) & \
44 (RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _T_Msk | \
45 RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Msk)))
46
47 #define RTC_CALENDAR_REG_SET_FIELD(_field, _var, _val) \
48 ((_var) = \
49 ((_var) & ~(RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _T_Msk | \
50 RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Msk)) | \
51 (((_val) << RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Pos) & \
52 (RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _T_Msk | \
53 RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Msk)))
54
55 #define RTC_CALENDAR_ALARM_REG_SET_FIELD(_field, _var, _val) \
56 ((_var) = \
57 ((_var) & ~(RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _T_Msk | \
58 RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Msk)) | \
59 (((_val) << RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Pos) & \
60 (RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _T_Msk | \
61 RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Msk)))
62
63 #define RTC_TIME_ALARM_REG_SET_FIELD(_field, _var, _val) \
64 ((_var) = \
65 ((_var) & ~(RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _T_Msk | \
66 RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Msk)) | \
67 (((_val) << RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Pos) & \
68 (RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _T_Msk | \
69 RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Msk)))
70
71 #define RTC_TIME_REG_GET_FIELD(_field, _var) \
72 (((_var) & (RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _T_Msk | \
73 RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Msk)) >> \
74 RTC_RTC_TIME_REG_RTC_TIME_ ## _field ## _U_Pos)
75
76 #define RTC_CALENDAR_REG_GET_FIELD(_field, _var) \
77 (((_var) & (RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _T_Msk | \
78 RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Msk)) >> \
79 RTC_RTC_CALENDAR_REG_RTC_CAL_ ## _field ## _U_Pos)
80
81 #define RTC_CALENDAR_ALARM_REG_GET_FIELD(_field, _var) \
82 (((_var) & (RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _T_Msk | \
83 RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Msk)) >> \
84 RTC_RTC_CALENDAR_ALARM_REG_RTC_CAL_ ## _field ## _U_Pos)
85
86 #define RTC_TIME_ALARM_REG_GET_FIELD(_field, _var) \
87 (((_var) & (RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _T_Msk | \
88 RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Msk)) >> \
89 RTC_RTC_TIME_ALARM_REG_RTC_TIME_ ## _field ## _U_Pos)
90
91 #define CLK_RTCDIV_REG_SET_FIELD(_field, _var, _val) \
92 ((_var) = \
93 ((_var) & ~CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ ## _field ## _Msk) | \
94 (((_val) << CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ ## _field ## _Pos) & \
95 CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ ## _field ## _Msk))
96
97 struct rtc_smartbond_data {
98 struct k_mutex lock;
99 bool is_rtc_configured;
100 #if defined(CONFIG_RTC_ALARM)
101 volatile bool is_alarm_pending;
102 rtc_alarm_callback alarm_cb;
103 void *alarm_user_data;
104 #endif
105 #if defined(CONFIG_RTC_UPDATE)
106 rtc_update_callback update_cb;
107 void *update_user_data;
108 #endif
109 };
110
111 #if defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE)
smartbond_rtc_isr(const struct device * dev)112 static void smartbond_rtc_isr(const struct device *dev)
113 {
114 struct rtc_smartbond_data *data = dev->data;
115 /* Exercise which events asserted the RTC IRQ line. Register is cleared upon read. */
116 uint32_t rtc_event_flags_reg = RTC->RTC_EVENT_FLAGS_REG;
117 /* RTC_EVENT_FLASH_REG will be updated regardless of the interrupt mask. */
118 uint32_t rtc_interrupt_mask_reg = RTC->RTC_INTERRUPT_MASK_REG;
119
120 #if defined(CONFIG_RTC_ALARM)
121 if ((rtc_event_flags_reg & RTC_RTC_EVENT_FLAGS_REG_RTC_EVENT_ALRM_Msk) &&
122 !(rtc_interrupt_mask_reg & RTC_RTC_INTERRUPT_MASK_REG_RTC_ALRM_INT_MSK_Msk)) {
123 if (data->alarm_cb) {
124 data->alarm_cb(dev, 0, data->alarm_user_data);
125 data->is_alarm_pending = false;
126 } else {
127 data->is_alarm_pending = true;
128 }
129 }
130 #endif
131
132 #if defined(CONFIG_RTC_UPDATE)
133 if ((rtc_event_flags_reg & RTC_RTC_EVENT_FLAGS_REG_RTC_EVENT_SEC_Msk) &&
134 !(rtc_interrupt_mask_reg & RTC_RTC_INTERRUPT_MASK_REG_RTC_SEC_INT_MSK_Msk)) {
135 if (data->update_cb) {
136 data->update_cb(dev, data->update_user_data);
137 }
138 }
139 #endif
140 }
141 #endif
142
rtc_smartbond_set_status(bool status)143 static inline void rtc_smartbond_set_status(bool status)
144 {
145 if (status) {
146 CRG_TOP->CLK_RTCDIV_REG |= CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ENABLE_Msk;
147 RTC->RTC_CONTROL_REG = 0;
148 } else {
149 RTC->RTC_CONTROL_REG = (RTC_RTC_CONTROL_REG_RTC_CAL_DISABLE_Msk |
150 RTC_RTC_CONTROL_REG_RTC_TIME_DISABLE_Msk);
151 CRG_TOP->CLK_RTCDIV_REG &= ~CRG_TOP_CLK_RTCDIV_REG_RTC_DIV_ENABLE_Msk;
152 }
153 }
154
rtc_time_to_bcd(const struct rtc_time * timeptr)155 static uint32_t rtc_time_to_bcd(const struct rtc_time *timeptr)
156 {
157 uint32_t rtc_time_reg = 0;
158
159 RTC_TIME_REG_SET_FIELD(S, rtc_time_reg, bin2bcd(timeptr->tm_sec)); /*[0, 59]*/
160 RTC_TIME_REG_SET_FIELD(M, rtc_time_reg, bin2bcd(timeptr->tm_min)); /*[0, 59]*/
161 RTC_TIME_REG_SET_FIELD(HR, rtc_time_reg, bin2bcd(timeptr->tm_hour)); /*[0, 23]*/
162
163 return rtc_time_reg;
164 }
165
rtc_calendar_to_bcd(const struct rtc_time * timeptr)166 static uint32_t rtc_calendar_to_bcd(const struct rtc_time *timeptr)
167 {
168 uint32_t rtc_calendar_reg = 0;
169
170 RTC_CALENDAR_REG_SET_FIELD(D, rtc_calendar_reg, bin2bcd(timeptr->tm_mday)); /*[1, 31]*/
171 RTC_CALENDAR_REG_SET_FIELD(Y, rtc_calendar_reg,
172 bin2bcd((timeptr->tm_year + TM_YEAR_REF) % 100)); /*[year - 1900]*/
173 RTC_CALENDAR_REG_SET_FIELD(C, rtc_calendar_reg,
174 bin2bcd((timeptr->tm_year + TM_YEAR_REF) / 100));
175 RTC_CALENDAR_REG_SET_FIELD(M, rtc_calendar_reg, bin2bcd(timeptr->tm_mon + 1)); /*[0, 11]*/
176
177 if (timeptr->tm_wday != -1) {
178 rtc_calendar_reg |= ((timeptr->tm_wday + 1) &
179 RTC_RTC_CALENDAR_REG_RTC_DAY_Msk); /*[0, 6]*/
180 }
181
182 return rtc_calendar_reg;
183 }
184
bcd_to_rtc_time(struct rtc_time * timeptr)185 static void bcd_to_rtc_time(struct rtc_time *timeptr)
186 {
187 uint32_t rtc_time_reg = RTC->RTC_TIME_REG;
188
189 timeptr->tm_sec = bcd2bin(RTC_TIME_REG_GET_FIELD(S, rtc_time_reg));
190 timeptr->tm_min = bcd2bin(RTC_TIME_REG_GET_FIELD(M, rtc_time_reg));
191 timeptr->tm_hour = bcd2bin(RTC_TIME_REG_GET_FIELD(HR, rtc_time_reg));
192
193 timeptr->tm_nsec = 0; /*Unknown*/
194 }
195
bcd_to_rtc_calendar(struct rtc_time * timeptr)196 static void bcd_to_rtc_calendar(struct rtc_time *timeptr)
197 {
198 uint32_t rtc_calendar_reg = RTC->RTC_CALENDAR_REG;
199
200 timeptr->tm_mday = bcd2bin(RTC_CALENDAR_REG_GET_FIELD(D, rtc_calendar_reg));
201 timeptr->tm_mon = bcd2bin(RTC_CALENDAR_REG_GET_FIELD(M, rtc_calendar_reg)) - 1;
202 timeptr->tm_year = bcd2bin(RTC_CALENDAR_REG_GET_FIELD(Y, rtc_calendar_reg)) +
203 (bcd2bin(RTC_CALENDAR_REG_GET_FIELD(C, rtc_calendar_reg)) * 100) - TM_YEAR_REF;
204 timeptr->tm_wday = (rtc_calendar_reg & RTC_RTC_CALENDAR_REG_RTC_DAY_Msk) - 1;
205
206 timeptr->tm_yday = timeptr->tm_isdst = -1; /*Unknown*/
207 }
208
rtc_smartbond_set_time(const struct device * dev,const struct rtc_time * timeptr)209 static int rtc_smartbond_set_time(const struct device *dev, const struct rtc_time *timeptr)
210 {
211 struct rtc_smartbond_data *data = dev->data;
212 int ret = 0;
213 uint32_t rtc_time_reg, rtc_calendar_reg, rtc_status_reg;
214
215 if (timeptr == NULL) {
216 LOG_ERR("No pointer is provided to set time");
217 return -EINVAL;
218 }
219
220 if (timeptr->tm_year + TM_YEAR_REF < TM_YEAR_REF) {
221 LOG_ERR("RTC time exceeds HW capabilities");
222 return -EINVAL;
223 }
224
225 if ((timeptr->tm_yday != -1) || (timeptr->tm_isdst != -1) || (timeptr->tm_nsec != 0)) {
226 LOG_WRN("Unsupported RTC sub-values");
227 }
228
229 k_mutex_lock(&data->lock, K_FOREVER);
230 rtc_smartbond_set_status(false);
231
232 /* Store current counter values as it might happen that the requested time is not valid */
233 rtc_time_reg = RTC->RTC_TIME_REG;
234 rtc_calendar_reg = RTC->RTC_CALENDAR_REG;
235
236 RTC->RTC_TIME_REG = rtc_time_to_bcd(timeptr);
237 RTC->RTC_CALENDAR_REG = rtc_calendar_to_bcd(timeptr);
238
239 /* Check if the new values were valid, otherwise reset back to the previous ones. */
240 rtc_status_reg = RTC->RTC_STATUS_REG;
241 if (!(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_CAL_Msk) ||
242 !(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_TIME_Msk)) {
243 RTC->RTC_TIME_REG = rtc_time_reg;
244 RTC->RTC_CALENDAR_REG = rtc_calendar_reg;
245 ret = -EINVAL;
246 }
247
248 /* Mark the very first valid RTC configuration; used to check if RTC contains valid data. */
249 if (!data->is_rtc_configured && (ret == 0)) {
250 data->is_rtc_configured = true;
251 }
252
253 /* It might happen that the very first time RTC is not configured correctly; do not care. */
254 rtc_smartbond_set_status(true);
255 k_mutex_unlock(&data->lock);
256
257 return ret;
258 }
259
rtc_smartbond_get_time(const struct device * dev,struct rtc_time * timeptr)260 static int rtc_smartbond_get_time(const struct device *dev, struct rtc_time *timeptr)
261 {
262 struct rtc_smartbond_data *data = dev->data;
263
264 if (timeptr == NULL) {
265 LOG_ERR("No pointer is provided to store the requested time");
266 return -EINVAL;
267 }
268
269 if (!data->is_rtc_configured) {
270 LOG_WRN("RTC is not initialized yet");
271 }
272
273 k_mutex_lock(&data->lock, K_FOREVER);
274 /* Stop RTC counters to obtain coherent data. */
275 rtc_smartbond_set_status(false);
276
277 bcd_to_rtc_time(timeptr);
278 bcd_to_rtc_calendar(timeptr);
279
280 rtc_smartbond_set_status(true);
281 k_mutex_unlock(&data->lock);
282
283 return 0;
284 }
285
286 #if defined(CONFIG_RTC_ALARM)
287 BUILD_ASSERT(RTC_ALARMS_COUNT, "At least one alarm event should be supported");
288
289 /*
290 * Parse only the alarm fields indicated by the mask. Default valid values should be assigned
291 * to unused fields as it might happen that application has provided with invalid values.
292 */
alarm_calendar_to_bcd(const struct rtc_time * timeptr,uint16_t mask)293 static uint32_t alarm_calendar_to_bcd(const struct rtc_time *timeptr, uint16_t mask)
294 {
295 uint32_t rtc_calendar_alarm_reg = 0x0108;
296
297 if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
298 RTC_CALENDAR_ALARM_REG_SET_FIELD(D, rtc_calendar_alarm_reg,
299 bin2bcd(timeptr->tm_mday));
300 }
301
302 if (mask & RTC_ALARM_TIME_MASK_MONTH) {
303 RTC_CALENDAR_ALARM_REG_SET_FIELD(M, rtc_calendar_alarm_reg,
304 bin2bcd(timeptr->tm_mon + 1));
305 }
306
307 return rtc_calendar_alarm_reg;
308 }
309
310 /*
311 * Parse only the alarm fields indicated by the mask. Default valid values should be assigned
312 * to unused fields as it might happen that application has provided with invalid values.
313 */
alarm_time_to_bcd(const struct rtc_time * timeptr,uint16_t mask)314 static inline uint32_t alarm_time_to_bcd(const struct rtc_time *timeptr, uint16_t mask)
315 {
316 uint32_t rtc_time_alarm_reg = 0;
317
318 if (mask & RTC_ALARM_TIME_MASK_SECOND) {
319 /*[0, 59]*/
320 RTC_TIME_ALARM_REG_SET_FIELD(S, rtc_time_alarm_reg, bin2bcd(timeptr->tm_sec));
321 }
322
323 if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
324 /*[0, 59]*/
325 RTC_TIME_ALARM_REG_SET_FIELD(M, rtc_time_alarm_reg, bin2bcd(timeptr->tm_min));
326 }
327
328 if (mask & RTC_ALARM_TIME_MASK_HOUR) {
329 /*[0, 23]*/
330 RTC_TIME_ALARM_REG_SET_FIELD(HR, rtc_time_alarm_reg, bin2bcd(timeptr->tm_hour));
331 }
332
333 return rtc_time_alarm_reg;
334 }
335
bcd_to_alarm_calendar(struct rtc_time * timeptr)336 static void bcd_to_alarm_calendar(struct rtc_time *timeptr)
337 {
338 uint32_t rtc_calendar_alarm_reg = RTC->RTC_CALENDAR_ALARM_REG;
339
340 timeptr->tm_mday = bcd2bin(RTC_CALENDAR_ALARM_REG_GET_FIELD(D, rtc_calendar_alarm_reg));
341 timeptr->tm_mon = bcd2bin(RTC_CALENDAR_ALARM_REG_GET_FIELD(M, rtc_calendar_alarm_reg)) - 1;
342
343 timeptr->tm_yday = timeptr->tm_wday = timeptr->tm_isdst = timeptr->tm_year = -1;
344 }
345
bcd_to_alarm_time(struct rtc_time * timeptr)346 static void bcd_to_alarm_time(struct rtc_time *timeptr)
347 {
348 uint32_t rtc_time_alarm_reg = RTC->RTC_TIME_ALARM_REG;
349
350 timeptr->tm_sec = bcd2bin(RTC_TIME_ALARM_REG_GET_FIELD(S, rtc_time_alarm_reg));
351 timeptr->tm_min = bcd2bin(RTC_TIME_ALARM_REG_GET_FIELD(M, rtc_time_alarm_reg));
352 timeptr->tm_hour = bcd2bin(RTC_TIME_ALARM_REG_GET_FIELD(HR, rtc_time_alarm_reg));
353
354 timeptr->tm_nsec = 0;
355 }
356
tm_to_rtc_alarm_mask(uint16_t mask)357 static uint32_t tm_to_rtc_alarm_mask(uint16_t mask)
358 {
359 uint32_t rtc_alarm_enable_reg = 0;
360
361 if (mask & RTC_ALARM_TIME_MASK_SECOND) {
362 rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_SEC_EN_Msk;
363 }
364 if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
365 rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MIN_EN_Msk;
366 }
367 if (mask & RTC_ALARM_TIME_MASK_HOUR) {
368 rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_HOUR_EN_Msk;
369 }
370 if (mask & RTC_ALARM_TIME_MASK_MONTH) {
371 rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MNTH_EN_Msk;
372 }
373 if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
374 rtc_alarm_enable_reg |= RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_DATE_EN_Msk;
375 }
376
377 return rtc_alarm_enable_reg;
378 }
379
rtc_to_tm_alarm_mask(uint32_t rtc_alarm_enable_reg)380 static uint16_t rtc_to_tm_alarm_mask(uint32_t rtc_alarm_enable_reg)
381 {
382 uint16_t mask = 0;
383
384 if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_SEC_EN_Msk) {
385 mask |= RTC_ALARM_TIME_MASK_SECOND;
386 }
387 if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MIN_EN_Msk) {
388 mask |= RTC_ALARM_TIME_MASK_MINUTE;
389 }
390 if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_HOUR_EN_Msk) {
391 mask |= RTC_ALARM_TIME_MASK_HOUR;
392 }
393 if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_MNTH_EN_Msk) {
394 mask |= RTC_ALARM_TIME_MASK_MONTH;
395 }
396 if (rtc_alarm_enable_reg & RTC_RTC_ALARM_ENABLE_REG_RTC_ALARM_DATE_EN_Msk) {
397 mask |= RTC_ALARM_TIME_MASK_MONTHDAY;
398 }
399
400 return mask;
401 }
402
rtc_smartbond_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)403 static int rtc_smartbond_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
404 const struct rtc_time *timeptr)
405 {
406 int ret = 0;
407 struct rtc_smartbond_data *data = dev->data;
408 uint32_t rtc_time_alarm_reg;
409 uint32_t rtc_calendar_alarm_reg;
410 uint32_t rtc_alarm_enable_reg;
411 uint32_t rtc_status_reg;
412
413 if (id >= RTC_ALARMS_COUNT) {
414 LOG_ERR("Alarm id is out of range");
415 return -EINVAL;
416 }
417
418 if (mask & ~RTC_SMARTBOND_SUPPORTED_ALARM_FIELDS) {
419 LOG_ERR("Invalid alarm mask");
420 return -EINVAL;
421 }
422
423 if ((timeptr == NULL) && (mask != 0)) {
424 LOG_ERR("No pointer is provided to set alarm");
425 return -EINVAL;
426 }
427
428 if (!rtc_utils_validate_rtc_time(timeptr, mask)) {
429 LOG_ERR("Invalid alarm fields values");
430 return -EINVAL;
431 }
432
433 if (!data->is_rtc_configured) {
434 LOG_WRN("RTC is not initialized yet");
435 }
436
437 k_mutex_lock(&data->lock, K_FOREVER);
438
439 rtc_alarm_enable_reg = RTC->RTC_ALARM_ENABLE_REG;
440
441 /* Disable alarm to obtain coherency and/or when the alarm mask is empty */
442 RTC->RTC_ALARM_ENABLE_REG = 0;
443 RTC->RTC_INTERRUPT_DISABLE_REG = RTC_RTC_INTERRUPT_DISABLE_REG_RTC_ALRM_INT_DIS_Msk;
444
445 if (mask) {
446 /* Store current counter values as it might happen requested alrm is not valid */
447 rtc_time_alarm_reg = RTC->RTC_TIME_ALARM_REG;
448 rtc_calendar_alarm_reg = RTC->RTC_CALENDAR_ALARM_REG;
449
450 RTC->RTC_TIME_ALARM_REG = alarm_time_to_bcd(timeptr, mask);
451 RTC->RTC_CALENDAR_ALARM_REG = alarm_calendar_to_bcd(timeptr, mask);
452
453 rtc_status_reg = RTC->RTC_STATUS_REG;
454 if (!(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_CAL_ALM_Msk) ||
455 !(rtc_status_reg & RTC_RTC_STATUS_REG_RTC_VALID_TIME_ALM_Msk)) {
456 RTC->RTC_TIME_ALARM_REG = rtc_time_alarm_reg;
457 RTC->RTC_CALENDAR_ALARM_REG = rtc_calendar_alarm_reg;
458 RTC->RTC_ALARM_ENABLE_REG = rtc_alarm_enable_reg;
459 ret = -EINVAL;
460 } else {
461 RTC->RTC_ALARM_ENABLE_REG = tm_to_rtc_alarm_mask(mask);
462 }
463
464 RTC->RTC_INTERRUPT_ENABLE_REG = RTC_RTC_INTERRUPT_ENABLE_REG_RTC_ALRM_INT_EN_Msk;
465 }
466
467 k_mutex_unlock(&data->lock);
468
469 return ret;
470 }
471
rtc_smartbond_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)472 static int rtc_smartbond_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
473 struct rtc_time *timeptr)
474 {
475 struct rtc_smartbond_data *data = dev->data;
476
477 if (id >= RTC_ALARMS_COUNT) {
478 LOG_ERR("Alarm id is out of range");
479 return -EINVAL;
480 }
481
482 if ((timeptr == NULL) || (mask == NULL)) {
483 LOG_ERR("No pointer is provided to store the requested alarm time/mask");
484 return -EINVAL;
485 }
486
487 if (!data->is_rtc_configured) {
488 LOG_WRN("RTC is not initialized yet");
489 }
490
491 k_mutex_lock(&data->lock, K_FOREVER);
492
493 bcd_to_alarm_calendar(timeptr);
494 bcd_to_alarm_time(timeptr);
495 *mask = rtc_to_tm_alarm_mask(RTC->RTC_ALARM_ENABLE_REG);
496
497 k_mutex_unlock(&data->lock);
498
499 return 0;
500 }
501
rtc_smartbond_alarm_is_pending(const struct device * dev,uint16_t id)502 static int rtc_smartbond_alarm_is_pending(const struct device *dev, uint16_t id)
503 {
504 unsigned int key;
505 int status;
506 struct rtc_smartbond_data *data = dev->data;
507
508 if (id >= RTC_ALARMS_COUNT) {
509 LOG_ERR("Alarm id is out of range");
510 return -EINVAL;
511 }
512
513 /* Globally disable interrupts as the status flag can be updated within ISR */
514 key = DA1469X_IRQ_DISABLE();
515 status = data->is_alarm_pending;
516 /* After reading, the alarm status should be cleared. */
517 data->is_alarm_pending = 0;
518 DA1469X_IRQ_ENABLE(key);
519
520 return status;
521 }
522
rtc_smartbond_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)523 static int rtc_smartbond_alarm_set_callback(const struct device *dev, uint16_t id,
524 rtc_alarm_callback callback, void *user_data)
525 {
526 struct rtc_smartbond_data *data = dev->data;
527
528 if (id >= RTC_ALARMS_COUNT) {
529 LOG_ERR("Alarm id is out of range");
530 return -EINVAL;
531 }
532
533 k_mutex_lock(&data->lock, K_FOREVER);
534
535 data->alarm_cb = callback;
536 data->alarm_user_data = user_data;
537
538 k_mutex_unlock(&data->lock);
539
540 return 0;
541 }
542
rtc_smartbond_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)543 static int rtc_smartbond_alarm_get_supported_fields(const struct device *dev, uint16_t id,
544 uint16_t *mask)
545 {
546 if (id >= RTC_ALARMS_COUNT) {
547 LOG_ERR("Alarm id is out of range");
548 return -EINVAL;
549 }
550
551 if (mask == NULL) {
552 LOG_ERR("Pointer to store the mask value is missed");
553 return -EINVAL;
554 }
555
556 *mask = (uint16_t)RTC_SMARTBOND_SUPPORTED_ALARM_FIELDS;
557
558 return 0;
559 }
560 #endif
561
562 #if defined(CONFIG_RTC_UPDATE)
rtc_smartbond_update_set_callback(const struct device * dev,rtc_update_callback callback,void * user_data)563 static int rtc_smartbond_update_set_callback(const struct device *dev, rtc_update_callback callback,
564 void *user_data)
565 {
566 struct rtc_smartbond_data *data = dev->data;
567
568 k_mutex_lock(&data->lock, K_FOREVER);
569
570 data->update_cb = callback;
571 data->update_user_data = user_data;
572
573 if (data->update_cb) {
574 /* Enable asserting the RTC interrupt line when the second counter rolls over. */
575 RTC->RTC_INTERRUPT_ENABLE_REG = RTC_RTC_INTERRUPT_ENABLE_REG_RTC_SEC_INT_EN_Msk;
576 } else {
577 RTC->RTC_INTERRUPT_DISABLE_REG = RTC_RTC_INTERRUPT_DISABLE_REG_RTC_SEC_INT_DIS_Msk;
578 }
579
580 k_mutex_unlock(&data->lock);
581
582 return 0;
583 }
584 #endif
585
586 static DEVICE_API(rtc, rtc_smartbond_driver_api) = {
587 .get_time = rtc_smartbond_get_time,
588 .set_time = rtc_smartbond_set_time,
589 #if defined(CONFIG_RTC_ALARM)
590 .alarm_get_time = rtc_smartbond_alarm_get_time,
591 .alarm_set_time = rtc_smartbond_alarm_set_time,
592 .alarm_is_pending = rtc_smartbond_alarm_is_pending,
593 .alarm_set_callback = rtc_smartbond_alarm_set_callback,
594 .alarm_get_supported_fields = rtc_smartbond_alarm_get_supported_fields,
595 #endif
596 #if defined(CONFIG_RTC_UPDATE)
597 .update_set_callback = rtc_smartbond_update_set_callback,
598 #endif
599 };
600
rtc_smartbond_100HZ_clock_cfg(void)601 static void rtc_smartbond_100HZ_clock_cfg(void)
602 {
603 const struct device * const dev = DEVICE_DT_GET(DT_NODELABEL(osc));
604 uint32_t lp_clk_rate;
605 uint32_t clk_rtcdiv_reg;
606
607 if (!device_is_ready(dev)) {
608 __ASSERT_MSG_INFO("Clock device is not ready");
609 }
610
611 if (clock_control_get_rate(dev, (clock_control_subsys_t)SMARTBOND_CLK_LP_CLK,
612 &lp_clk_rate) < 0) {
613 __ASSERT_MSG_INFO("Cannot extract LP clock rate");
614 }
615
616 clk_rtcdiv_reg = CRG_TOP->CLK_RTCDIV_REG;
617 CLK_RTCDIV_REG_SET_FIELD(DENOM, clk_rtcdiv_reg, RTC_DIV_DENOM_1000);
618 CLK_RTCDIV_REG_SET_FIELD(INT, clk_rtcdiv_reg, lp_clk_rate / 100);
619 CLK_RTCDIV_REG_SET_FIELD(FRAC, clk_rtcdiv_reg, (lp_clk_rate % 100) * 10);
620 CRG_TOP->CLK_RTCDIV_REG = clk_rtcdiv_reg;
621 }
622
rtc_smartbond_init(const struct device * dev)623 static int rtc_smartbond_init(const struct device *dev)
624 {
625 ARG_UNUSED(dev);
626
627 /* Wakeup device from RTC events (alarm/roll over) */
628 #if CONFIG_PM
629 bool is_xtal32m_enabled = DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(xtal32m));
630 int pdc_idx = da1469x_pdc_add(MCU_PDC_TRIGGER_RTC_ALARM, MCU_PDC_MASTER_M33,
631 is_xtal32m_enabled ? MCU_PDC_EN_XTAL : 0);
632
633 __ASSERT(pdc_idx >= 0, "Failed to add RTC PDC entry");
634 da1469x_pdc_set(pdc_idx);
635 da1469x_pdc_ack(pdc_idx);
636 #endif
637
638 rtc_smartbond_100HZ_clock_cfg();
639
640 /* Timer and calendar counters will not reset after SW reset */
641 RTC->RTC_KEEP_RTC_REG |= RTC_RTC_KEEP_RTC_REG_RTC_KEEP_Msk;
642
643 #if defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE)
644 IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_rtc_isr,
645 DEVICE_DT_INST_GET(0), 0);
646 irq_enable(SMARTBOND_IRQN);
647 #endif
648
649 return 0;
650 }
651
652 #define SMARTBOND_RTC_INIT(inst) \
653 BUILD_ASSERT((inst) == 0, "multiple instances are not supported"); \
654 \
655 static struct rtc_smartbond_data rtc_smartbond_data_ ## inst; \
656 \
657 DEVICE_DT_INST_DEFINE(0, rtc_smartbond_init, NULL, \
658 &rtc_smartbond_data_ ## inst, NULL, \
659 POST_KERNEL, \
660 CONFIG_RTC_INIT_PRIORITY, \
661 &rtc_smartbond_driver_api);
662
663 DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_RTC_INIT)
664