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