1 /*
2  * Copyright (c) 2024 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_numaker_rtc
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/device.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/drivers/rtc.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/spinlock.h>
16 #include <zephyr/drivers/clock_control.h>
17 #include <zephyr/drivers/clock_control/clock_control_numaker.h>
18 #include "rtc_utils.h"
19 
20 LOG_MODULE_REGISTER(rtc_numaker, CONFIG_RTC_LOG_LEVEL);
21 
22 /* RTC support 2000 ~ 2099 */
23 #define NVT_RTC_YEAR_MIN 2000U
24 #define NVT_RTC_YEAR_MAX 2099U
25 /* struct tm start time:   1st, Jan, 1900 */
26 #define TM_YEAR_REF 1900U
27 
28 #define NVT_TIME_SCALE RTC_CLOCK_24
29 #define NVT_ALARM_MSK 0x3fU
30 #define NVT_ALARM_UNIT_MSK 0x03U
31 
32 struct rtc_numaker_config {
33 	RTC_T *rtc_base;
34 	uint32_t clk_modidx;
35 	const struct device *clk_dev;
36 	uint32_t oscillator;
37 };
38 
39 struct rtc_numaker_data {
40 	struct k_spinlock lock;
41 #ifdef CONFIG_RTC_ALARM
42 	rtc_alarm_callback alarm_callback;
43 	void *alarm_user_data;
44 	bool alarm_pending;
45 #endif /* CONFIG_RTC_ALARM */
46 };
47 
48 struct rtc_numaker_time {
49 	uint32_t year;		/* Year value */
50 	uint32_t month;		/* Month value */
51 	uint32_t day;		/* Day value */
52 	uint32_t day_of_week;	/* Day of week value */
53 	uint32_t hour;		/* Hour value */
54 	uint32_t minute;	/* Minute value */
55 	uint32_t second;	/* Second value */
56 	uint32_t time_scale;	/* 12-Hour, 24-Hour */
57 	uint32_t am_pm;		/* Only Time Scale select 12-hr used */
58 };
59 
rtc_numaker_set_time(const struct device * dev,const struct rtc_time * timeptr)60 static int rtc_numaker_set_time(const struct device *dev, const struct rtc_time *timeptr)
61 {
62 	struct rtc_numaker_time curr_time;
63 	struct rtc_numaker_data *data = dev->data;
64 	uint32_t real_year = timeptr->tm_year + TM_YEAR_REF;
65 #ifdef CONFIG_RTC_ALARM
66 	const struct rtc_numaker_config *config = dev->config;
67 	RTC_T *rtc_base = config->rtc_base;
68 #endif
69 
70 	if (real_year < NVT_RTC_YEAR_MIN || real_year > NVT_RTC_YEAR_MAX) {
71 		/* RTC can't support years out of 2000 ~ 2099 */
72 		return -EINVAL;
73 	}
74 
75 	if (timeptr->tm_wday == -1) {
76 		return -EINVAL;
77 	}
78 
79 	curr_time.year = real_year;
80 	curr_time.month = timeptr->tm_mon + 1;
81 	curr_time.day = timeptr->tm_mday;
82 	curr_time.hour = timeptr->tm_hour;
83 	curr_time.minute = timeptr->tm_min;
84 	curr_time.second = timeptr->tm_sec;
85 	curr_time.day_of_week = timeptr->tm_wday;
86 	curr_time.time_scale = NVT_TIME_SCALE;
87 
88 	k_spinlock_key_t key = k_spin_lock(&data->lock);
89 
90 	RTC_SetDateAndTime((S_RTC_TIME_DATA_T *)&curr_time);
91 
92 #ifdef CONFIG_RTC_ALARM
93 	/* Restore RTC alarm mask */
94 	rtc_base->CAMSK = rtc_base->SPR[1];
95 	rtc_base->TAMSK = rtc_base->SPR[2];
96 #endif
97 	k_spin_unlock(&data->lock, key);
98 
99 	return 0;
100 }
101 
rtc_numaker_get_time(const struct device * dev,struct rtc_time * timeptr)102 static int rtc_numaker_get_time(const struct device *dev, struct rtc_time *timeptr)
103 {
104 	struct rtc_numaker_data *data = dev->data;
105 	struct rtc_numaker_time curr_time;
106 
107 	curr_time.time_scale = NVT_TIME_SCALE;
108 	k_spinlock_key_t key = k_spin_lock(&data->lock);
109 
110 	RTC_GetDateAndTime((S_RTC_TIME_DATA_T *)&curr_time);
111 	k_spin_unlock(&data->lock, key);
112 
113 	timeptr->tm_year = curr_time.year - TM_YEAR_REF;
114 	timeptr->tm_mon = curr_time.month - 1;
115 	timeptr->tm_mday = curr_time.day;
116 	timeptr->tm_wday = curr_time.day_of_week;
117 
118 	timeptr->tm_hour = curr_time.hour;
119 	timeptr->tm_min = curr_time.minute;
120 	timeptr->tm_sec = curr_time.second;
121 	timeptr->tm_nsec = 0;
122 
123 	/* unknown values */
124 	timeptr->tm_yday = -1;
125 	timeptr->tm_isdst = -1;
126 
127 	return 0;
128 }
129 
rtc_numaker_isr(const struct device * dev)130 static void rtc_numaker_isr(const struct device *dev)
131 {
132 	const struct rtc_numaker_config *config = dev->config;
133 	RTC_T *rtc_base = config->rtc_base;
134 	uint32_t int_status;
135 #ifdef CONFIG_RTC_ALARM
136 	struct rtc_numaker_data *data = dev->data;
137 #endif
138 
139 	int_status = rtc_base->INTSTS;
140 	if (int_status & RTC_INTSTS_TICKIF_Msk) {
141 		/* Clear RTC Tick interrupt flag */
142 		rtc_base->INTSTS = RTC_INTSTS_TICKIF_Msk;
143 	}
144 
145 #ifdef CONFIG_RTC_ALARM
146 	if (int_status & RTC_INTSTS_ALMIF_Msk) {
147 		rtc_alarm_callback callback;
148 		void *user_data;
149 
150 		/* Clear RTC Alarm interrupt flag */
151 		rtc_base->INTSTS = RTC_INTSTS_ALMIF_Msk;
152 		rtc_base->CAMSK = 0x00;
153 		rtc_base->TAMSK = 0x00;
154 		callback = data->alarm_callback;
155 		user_data = data->alarm_user_data;
156 		data->alarm_pending = callback ? false : true;
157 
158 		if (callback != NULL) {
159 			callback(dev, 0, user_data);
160 		}
161 	}
162 #endif /* CONFIG_RTC_ALARM */
163 }
164 
165 #ifdef CONFIG_RTC_ALARM
rtc_numaker_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)166 static int rtc_numaker_alarm_get_supported_fields(const struct device *dev, uint16_t id,
167 						  uint16_t *mask)
168 {
169 	ARG_UNUSED(dev);
170 	ARG_UNUSED(id);
171 
172 	*mask =  RTC_ALARM_TIME_MASK_SECOND
173 		 | RTC_ALARM_TIME_MASK_MINUTE
174 		 | RTC_ALARM_TIME_MASK_HOUR
175 		 | RTC_ALARM_TIME_MASK_MONTHDAY
176 		 | RTC_ALARM_TIME_MASK_MONTH
177 		 | RTC_ALARM_TIME_MASK_YEAR;
178 
179 	return 0;
180 }
181 
rtc_numaker_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)182 static int rtc_numaker_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
183 				      const struct rtc_time *timeptr)
184 {
185 	struct rtc_numaker_data *data = dev->data;
186 	const struct rtc_numaker_config *config = dev->config;
187 	RTC_T *rtc_base = config->rtc_base;
188 	uint16_t mask_capable;
189 	struct rtc_numaker_time alarm_time;
190 
191 	rtc_numaker_alarm_get_supported_fields(dev, 0, &mask_capable);
192 
193 	if ((id != 0)) {
194 		return -EINVAL;
195 	}
196 
197 	if ((mask != 0) && (timeptr == NULL)) {
198 		return -EINVAL;
199 	}
200 
201 	if (mask & ~mask_capable) {
202 		return -EINVAL;
203 	}
204 
205 	if (rtc_utils_validate_rtc_time(timeptr, mask) == false) {
206 		return -EINVAL;
207 	}
208 
209 	k_spinlock_key_t key = k_spin_lock(&data->lock);
210 
211 	irq_disable(DT_INST_IRQN(0));
212 	if ((mask == 0) || (timeptr == NULL)) {
213 		/* Disable the alarm */
214 		rtc_base->SPR[0] = mask;
215 		rtc_base->SPR[1] = 0x00;
216 		rtc_base->SPR[2] = 0x00;
217 		irq_enable(DT_INST_IRQN(0));
218 		k_spin_unlock(&data->lock, key);
219 		rtc_base->CAMSK = rtc_base->SPR[1];
220 		rtc_base->TAMSK = rtc_base->SPR[2];
221 		/* Disable RTC Alarm Interrupt */
222 		RTC_DisableInt(RTC_INTEN_ALMIEN_Msk);
223 		return 0;
224 	}
225 
226 	alarm_time.time_scale = NVT_TIME_SCALE;
227 	RTC_GetDateAndTime((S_RTC_TIME_DATA_T *)&alarm_time);
228 
229 	/* Reset RTC alarm mask of camsk & tamsk */
230 	uint32_t camsk = NVT_ALARM_MSK;
231 	uint32_t tamsk = NVT_ALARM_MSK;
232 
233 	/* Set H/W care to match bits */
234 	if (mask & RTC_ALARM_TIME_MASK_YEAR) {
235 		alarm_time.year = timeptr->tm_year + TM_YEAR_REF;
236 		camsk &= ~(NVT_ALARM_UNIT_MSK << RTC_CAMSK_MYEAR_Pos);
237 	}
238 	if (mask & RTC_ALARM_TIME_MASK_MONTH) {
239 		alarm_time.month = timeptr->tm_mon + 1;
240 		camsk &= ~(NVT_ALARM_UNIT_MSK << RTC_CAMSK_MMON_Pos);
241 	}
242 	if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
243 		alarm_time.day = timeptr->tm_mday;
244 		camsk &= ~(NVT_ALARM_UNIT_MSK << RTC_CAMSK_MDAY_Pos);
245 	}
246 	if (mask & RTC_ALARM_TIME_MASK_HOUR) {
247 		alarm_time.hour = timeptr->tm_hour;
248 		tamsk &= ~(NVT_ALARM_UNIT_MSK << RTC_TAMSK_MHR_Pos);
249 	}
250 	if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
251 		alarm_time.minute = timeptr->tm_min;
252 		tamsk &= ~(NVT_ALARM_UNIT_MSK << RTC_TAMSK_MMIN_Pos);
253 	}
254 	if (mask & RTC_ALARM_TIME_MASK_SECOND) {
255 		alarm_time.second = timeptr->tm_sec;
256 		tamsk &= ~(NVT_ALARM_UNIT_MSK << RTC_TAMSK_MSEC_Pos);
257 	}
258 
259 	/* Disable RTC Alarm Interrupt */
260 	RTC_DisableInt(RTC_INTEN_ALMIEN_Msk);
261 
262 	/* Set the alarm time */
263 	RTC_SetAlarmDateAndTime((S_RTC_TIME_DATA_T *)&alarm_time);
264 
265 	/* Clear RTC alarm interrupt flag */
266 	RTC_CLEAR_ALARM_INT_FLAG();
267 
268 	rtc_base->SPR[0] = mask;
269 	rtc_base->SPR[1] = camsk;
270 	rtc_base->SPR[2] = tamsk;
271 
272 	rtc_base->CAMSK = rtc_base->SPR[1];
273 	rtc_base->TAMSK = rtc_base->SPR[2];
274 
275 	k_spin_unlock(&data->lock, key);
276 	irq_enable(DT_INST_IRQN(0));
277 
278 	/* Enable RTC Alarm Interrupt */
279 	RTC_EnableInt(RTC_INTEN_ALMIEN_Msk);
280 
281 	return 0;
282 }
283 
rtc_numaker_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)284 static int rtc_numaker_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
285 				      struct rtc_time *timeptr)
286 {
287 	struct rtc_numaker_data *data = dev->data;
288 	const struct rtc_numaker_config *config = dev->config;
289 	RTC_T *rtc_base = config->rtc_base;
290 	struct rtc_numaker_time alarm_time;
291 
292 	if ((id != 0) || (mask == NULL) || (timeptr == NULL)) {
293 		return -EINVAL;
294 	}
295 
296 	alarm_time.time_scale = NVT_TIME_SCALE;
297 
298 	K_SPINLOCK(&data->lock) {
299 		RTC_GetAlarmDateAndTime((S_RTC_TIME_DATA_T *)&alarm_time);
300 	}
301 
302 	*mask = rtc_base->SPR[0];
303 	if (*mask & RTC_ALARM_TIME_MASK_YEAR) {
304 		timeptr->tm_year = alarm_time.year - TM_YEAR_REF;
305 	}
306 	if (*mask & RTC_ALARM_TIME_MASK_MONTH) {
307 		timeptr->tm_mon = alarm_time.month - 1;
308 	}
309 	if (*mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
310 		timeptr->tm_mday = alarm_time.day;
311 	}
312 	if (*mask & RTC_ALARM_TIME_MASK_HOUR) {
313 		timeptr->tm_hour = alarm_time.hour;
314 	}
315 	if (*mask & RTC_ALARM_TIME_MASK_MINUTE) {
316 		timeptr->tm_min = alarm_time.minute;
317 	}
318 	if (*mask & RTC_ALARM_TIME_MASK_SECOND) {
319 		timeptr->tm_sec = alarm_time.second;
320 	}
321 
322 	return 0;
323 }
324 
rtc_numaker_alarm_is_pending(const struct device * dev,uint16_t id)325 static int rtc_numaker_alarm_is_pending(const struct device *dev, uint16_t id)
326 {
327 	struct rtc_numaker_data *data = dev->data;
328 	int ret;
329 
330 	if (id != 0) {
331 		return -EINVAL;
332 	}
333 
334 	K_SPINLOCK(&data->lock) {
335 		ret = data->alarm_pending ? 1 : 0;
336 		data->alarm_pending = false;
337 	}
338 
339 	return ret;
340 }
341 
rtc_numaker_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)342 static int rtc_numaker_alarm_set_callback(const struct device *dev, uint16_t id,
343 					  rtc_alarm_callback callback, void *user_data)
344 {
345 	struct rtc_numaker_data *data = dev->data;
346 
347 	if (id != 0) {
348 		return -EINVAL;
349 	}
350 
351 	K_SPINLOCK(&data->lock) {
352 		irq_disable(DT_INST_IRQN(0));
353 		data->alarm_callback = callback;
354 		data->alarm_user_data = user_data;
355 		if ((callback == NULL) && (user_data == NULL)) {
356 			/* Disable RTC Alarm Interrupt */
357 			RTC_DisableInt(RTC_INTEN_ALMIEN_Msk);
358 		}
359 		irq_enable(DT_INST_IRQN(0));
360 	}
361 
362 	return 0;
363 }
364 #endif /* CONFIG_RTC_ALARM */
365 
366 static DEVICE_API(rtc, rtc_numaker_driver_api) = {
367 	.set_time = rtc_numaker_set_time,
368 	.get_time = rtc_numaker_get_time,
369 #ifdef CONFIG_RTC_ALARM
370 	.alarm_get_supported_fields = rtc_numaker_alarm_get_supported_fields,
371 	.alarm_set_time = rtc_numaker_alarm_set_time,
372 	.alarm_get_time = rtc_numaker_alarm_get_time,
373 	.alarm_is_pending = rtc_numaker_alarm_is_pending,
374 	.alarm_set_callback = rtc_numaker_alarm_set_callback,
375 #endif /* CONFIG_RTC_ALARM */
376 };
377 
rtc_numaker_init(const struct device * dev)378 static int rtc_numaker_init(const struct device *dev)
379 {
380 	const struct rtc_numaker_config *cfg = dev->config;
381 	struct numaker_scc_subsys scc_subsys;
382 	RTC_T *rtc_base = cfg->rtc_base;
383 	int err;
384 
385 	/* CLK controller */
386 	memset(&scc_subsys, 0x00, sizeof(scc_subsys));
387 	scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC;
388 	scc_subsys.pcc.clk_modidx = cfg->clk_modidx;
389 
390 	SYS_UnlockReg();
391 
392 	/* CLK_EnableModuleClock */
393 	err = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&scc_subsys);
394 	if (err != 0) {
395 		goto done;
396 	}
397 
398 	RTC_SetClockSource(cfg->oscillator);
399 	/* Enable spare registers */
400 	rtc_base->SPRCTL = RTC_SPRCTL_SPRRWEN_Msk;
401 
402 	irq_disable(DT_INST_IRQN(0));
403 
404 	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), rtc_numaker_isr,
405 		    DEVICE_DT_INST_GET(0), 0);
406 
407 	irq_enable(DT_INST_IRQN(0));
408 	err = RTC_Open(0);
409 
410 done:
411 	SYS_LockReg();
412 	return err;
413 }
414 
415 static struct rtc_numaker_data rtc_data;
416 
417 /* Set config based on DTS */
418 static const struct rtc_numaker_config rtc_config = {
419 	.rtc_base = (RTC_T *)DT_INST_REG_ADDR(0),
420 	.clk_modidx = DT_INST_CLOCKS_CELL(0, clock_module_index),
421 	.clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(0))),
422 	.oscillator = DT_ENUM_IDX(DT_NODELABEL(rtc), oscillator),
423 };
424 
425 DEVICE_DT_INST_DEFINE(0, &rtc_numaker_init, NULL, &rtc_data, &rtc_config, PRE_KERNEL_1,
426 		      CONFIG_RTC_INIT_PRIORITY, &rtc_numaker_driver_api);
427