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