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