1 /*
2  * Copyright (c) 2024-2025 Gerson Fernando Budke <nandojve@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT atmel_sam0_rtc
8 
9 /** @file
10  * @brief RTC driver for Atmel SAM0 MCU family.
11  */
12 
13 #include <stdlib.h>
14 
15 #include <zephyr/kernel.h>
16 #include <zephyr/drivers/rtc.h>
17 #include "rtc_utils.h"
18 
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(rtc_sam0, CONFIG_RTC_LOG_LEVEL);
21 
22 /* clang-format off */
23 
24 #define RTC_SAM0_TIME_MASK		\
25 	(RTC_ALARM_TIME_MASK_SECOND	\
26 	| RTC_ALARM_TIME_MASK_MINUTE	\
27 	| RTC_ALARM_TIME_MASK_HOUR	\
28 	| RTC_ALARM_TIME_MASK_MONTHDAY	\
29 	| RTC_ALARM_TIME_MASK_MONTH	\
30 	| RTC_ALARM_TIME_MASK_YEAR	\
31 	)
32 
33 #define RTC_SAM0_CALIBRATE_PPB_MAX	(127)
34 #define RTC_SAM0_CALIBRATE_PPB_QUANTA	(1000)
35 
36 enum rtc_sam0_counter_mode {
37 	COUNTER_MODE_0,
38 	COUNTER_MODE_1,
39 	COUNTER_MODE_2,
40 };
41 
42 struct rtc_sam0_config {
43 	Rtc *regs;
44 	enum rtc_sam0_counter_mode mode;
45 	uint16_t prescaler;
46 
47 	volatile uint32_t *mclk;
48 	uint32_t mclk_mask;
49 	uint32_t gclk_gen;
50 	uint16_t gclk_id;
51 	bool has_gclk;
52 	bool has_osc32kctrl;
53 	uint8_t osc32_src;
54 	uint32_t evt_ctrl_msk;
55 
56 #ifdef CONFIG_RTC_ALARM
57 	uint8_t alarms_count;
58 #endif /* CONFIG_RTC_ALARM */
59 #ifdef CONFIG_RTC_CALIBRATION
60 	int32_t cal_constant;
61 #endif
62 };
63 
64 struct rtc_sam0_data_cb {
65 	rtc_alarm_callback cb;
66 	void *cb_data;
67 };
68 
69 struct rtc_sam0_data {
70 	struct k_spinlock lock;
71 #ifdef CONFIG_RTC_ALARM
72 	struct rtc_sam0_data_cb *const alarms;
73 #endif /* CONFIG_RTC_ALARM */
74 };
75 
rtc_sam0_sync(Rtc * rtc)76 static inline void rtc_sam0_sync(Rtc *rtc)
77 {
78 	/* Wait for synchronization */
79 #ifdef MCLK
80 	while (rtc->MODE0.SYNCBUSY.reg & RTC_MODE0_SYNCBUSY_MASK) {
81 	}
82 #else
83 	while (rtc->MODE0.STATUS.reg & RTC_STATUS_SYNCBUSY) {
84 	}
85 #endif
86 }
87 
rtc_sam0_set_time(const struct device * dev,const struct rtc_time * timeptr)88 static int rtc_sam0_set_time(const struct device *dev, const struct rtc_time *timeptr)
89 {
90 	const struct rtc_sam0_config *cfg = dev->config;
91 	struct rtc_sam0_data *data = dev->data;
92 	RtcMode2 *regs = &cfg->regs->MODE2;
93 	uint32_t datetime = 0;
94 
95 	if (rtc_utils_validate_rtc_time(timeptr, RTC_SAM0_TIME_MASK) == false) {
96 		return -EINVAL;
97 	}
98 
99 	datetime |= RTC_MODE2_CLOCK_SECOND(timeptr->tm_sec);
100 	datetime |= RTC_MODE2_CLOCK_MINUTE(timeptr->tm_min);
101 	datetime |= RTC_MODE2_CLOCK_HOUR(timeptr->tm_hour);
102 	datetime |= RTC_MODE2_CLOCK_DAY(timeptr->tm_mday);
103 	datetime |= RTC_MODE2_CLOCK_MONTH(timeptr->tm_mon + 1);
104 	datetime |= RTC_MODE2_CLOCK_YEAR(timeptr->tm_year - 99);
105 
106 	k_spinlock_key_t key = k_spin_lock(&data->lock);
107 
108 #ifdef MCLK
109 	regs->CTRLA.reg &= ~RTC_MODE0_CTRLA_ENABLE;
110 	rtc_sam0_sync(cfg->regs);
111 	regs->CLOCK.reg = datetime;
112 	regs->CTRLA.reg |= RTC_MODE0_CTRLA_ENABLE;
113 #else
114 	regs->CTRL.reg &= ~RTC_MODE0_CTRL_ENABLE;
115 	rtc_sam0_sync(cfg->regs);
116 	regs->CLOCK.reg = datetime;
117 	regs->CTRL.reg |= RTC_MODE0_CTRL_ENABLE;
118 #endif
119 
120 	k_spin_unlock(&data->lock, key);
121 
122 	return 0;
123 }
124 
rtc_sam0_get_time(const struct device * dev,struct rtc_time * timeptr)125 static int rtc_sam0_get_time(const struct device *dev, struct rtc_time *timeptr)
126 {
127 	const struct rtc_sam0_config *cfg = dev->config;
128 	RTC_MODE2_CLOCK_Type calendar = cfg->regs->MODE2.CLOCK;
129 
130 	timeptr->tm_sec = calendar.bit.SECOND;
131 	timeptr->tm_min = calendar.bit.MINUTE;
132 	timeptr->tm_hour = calendar.bit.HOUR;
133 	timeptr->tm_mday = calendar.bit.DAY;
134 	timeptr->tm_mon = calendar.bit.MONTH - 1;
135 	timeptr->tm_year = calendar.bit.YEAR + 99;
136 	timeptr->tm_wday = -1;
137 	timeptr->tm_yday = -1;
138 	timeptr->tm_isdst = -1;
139 	timeptr->tm_nsec = 0;
140 
141 	LOG_DBG("D/M/Y H:M:S %02d/%02d/%02d %02d:%02d:%02d",
142 		timeptr->tm_mday, timeptr->tm_mon + 1, timeptr->tm_year - 99,
143 		timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
144 
145 	return 0;
146 }
147 
148 #ifdef CONFIG_RTC_ALARM
rtc_sam0_datetime_from_tm(const struct rtc_time * timeptr,uint32_t mask)149 static inline uint32_t rtc_sam0_datetime_from_tm(const struct rtc_time *timeptr,
150 						 uint32_t mask)
151 {
152 	uint32_t datetime = 0;
153 
154 	if (mask & RTC_ALARM_TIME_MASK_SECOND) {
155 		datetime |= RTC_MODE2_CLOCK_SECOND(timeptr->tm_sec);
156 	}
157 
158 	if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
159 		datetime |= RTC_MODE2_CLOCK_MINUTE(timeptr->tm_min);
160 	}
161 
162 	if (mask & RTC_ALARM_TIME_MASK_HOUR) {
163 		datetime |= RTC_MODE2_CLOCK_HOUR(timeptr->tm_hour);
164 	}
165 
166 	if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
167 		datetime |= RTC_MODE2_CLOCK_DAY(timeptr->tm_mday);
168 	}
169 
170 	if (mask & RTC_ALARM_TIME_MASK_MONTH) {
171 		datetime |= RTC_MODE2_CLOCK_MONTH(timeptr->tm_mon + 1);
172 	}
173 
174 	if (mask & RTC_ALARM_TIME_MASK_YEAR) {
175 		datetime |= RTC_MODE2_CLOCK_YEAR(timeptr->tm_year - 99);
176 	}
177 
178 	return datetime;
179 }
180 
rtc_sam0_tm_from_datetime(struct rtc_time * timeptr,uint32_t mask,RTC_MODE2_ALARM_Type calendar)181 static inline void rtc_sam0_tm_from_datetime(struct rtc_time *timeptr, uint32_t mask,
182 					     RTC_MODE2_ALARM_Type calendar)
183 {
184 	memset(timeptr, 0x00, sizeof(struct rtc_time));
185 
186 	if (mask & RTC_ALARM_TIME_MASK_SECOND) {
187 		timeptr->tm_sec = calendar.bit.SECOND;
188 	}
189 
190 	if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
191 		timeptr->tm_min = calendar.bit.MINUTE;
192 	}
193 
194 	if (mask & RTC_ALARM_TIME_MASK_HOUR) {
195 		timeptr->tm_hour = calendar.bit.HOUR;
196 	}
197 
198 	if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
199 		timeptr->tm_mday = calendar.bit.DAY;
200 	}
201 
202 	if (mask & RTC_ALARM_TIME_MASK_MONTH) {
203 		timeptr->tm_mon = calendar.bit.MONTH - 1;
204 	}
205 
206 	if (mask & RTC_ALARM_TIME_MASK_YEAR) {
207 		timeptr->tm_year = calendar.bit.YEAR + 99;
208 	}
209 
210 	timeptr->tm_wday = -1;
211 	timeptr->tm_yday = -1;
212 	timeptr->tm_isdst = -1;
213 	timeptr->tm_nsec = 0;
214 }
215 
rtc_sam0_alarm_msk_from_mask(uint32_t mask)216 static inline uint32_t rtc_sam0_alarm_msk_from_mask(uint32_t mask)
217 {
218 	uint32_t alarm_mask = 0;
219 
220 	if (mask & RTC_ALARM_TIME_MASK_SECOND) {
221 		alarm_mask = RTC_MODE2_MASK_SEL_SS_Val;
222 	}
223 
224 	if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
225 		alarm_mask = RTC_MODE2_MASK_SEL_MMSS_Val;
226 	}
227 
228 	if (mask & RTC_ALARM_TIME_MASK_HOUR) {
229 		alarm_mask = RTC_MODE2_MASK_SEL_HHMMSS_Val;
230 	}
231 
232 	if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
233 		alarm_mask = RTC_MODE2_MASK_SEL_DDHHMMSS_Val;
234 	}
235 
236 	if (mask & RTC_ALARM_TIME_MASK_MONTH) {
237 		alarm_mask = RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val;
238 	}
239 
240 	if (mask & RTC_ALARM_TIME_MASK_YEAR) {
241 		alarm_mask = RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val;
242 	}
243 
244 	return alarm_mask;
245 }
246 
rtc_sam0_mask_from_alarm_msk(uint32_t alarm_mask)247 static inline uint32_t rtc_sam0_mask_from_alarm_msk(uint32_t alarm_mask)
248 {
249 	uint32_t mask = 0;
250 
251 	switch (alarm_mask) {
252 	case RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val:
253 		mask |= RTC_ALARM_TIME_MASK_YEAR;
254 		__fallthrough;
255 	case RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val:
256 		mask |= RTC_ALARM_TIME_MASK_MONTH;
257 		__fallthrough;
258 	case RTC_MODE2_MASK_SEL_DDHHMMSS_Val:
259 		mask |= RTC_ALARM_TIME_MASK_MONTHDAY;
260 		__fallthrough;
261 	case RTC_MODE2_MASK_SEL_HHMMSS_Val:
262 		mask |= RTC_ALARM_TIME_MASK_HOUR;
263 		__fallthrough;
264 	case RTC_MODE2_MASK_SEL_MMSS_Val:
265 		mask |= RTC_ALARM_TIME_MASK_MINUTE;
266 		__fallthrough;
267 	case RTC_MODE2_MASK_SEL_SS_Val:
268 		mask |= RTC_ALARM_TIME_MASK_SECOND;
269 		break;
270 	default:
271 		break;
272 	}
273 
274 	return mask;
275 }
276 
rtc_sam0_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)277 static int rtc_sam0_alarm_get_supported_fields(const struct device *dev, uint16_t id,
278 					       uint16_t *mask)
279 {
280 	ARG_UNUSED(dev);
281 	ARG_UNUSED(id);
282 
283 	*mask = RTC_SAM0_TIME_MASK;
284 
285 	return 0;
286 }
287 
rtc_sam0_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)288 static int rtc_sam0_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
289 				   const struct rtc_time *timeptr)
290 {
291 	const struct rtc_sam0_config *cfg = dev->config;
292 	struct rtc_sam0_data *data = dev->data;
293 	RtcMode2 *regs = &cfg->regs->MODE2;
294 	uint32_t mask_supported = RTC_SAM0_TIME_MASK;
295 	uint32_t datetime;
296 	uint32_t alarm_msk;
297 
298 	if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) {
299 		return -EINVAL;
300 	}
301 
302 	if ((mask > 0) && (timeptr == NULL)) {
303 		return -EINVAL;
304 	}
305 
306 	if (mask & ~mask_supported) {
307 		return -EINVAL;
308 	}
309 
310 	if (rtc_utils_validate_rtc_time(timeptr, mask) == false) {
311 		return -EINVAL;
312 	}
313 
314 	datetime = rtc_sam0_datetime_from_tm(timeptr, mask);
315 	alarm_msk = rtc_sam0_alarm_msk_from_mask(mask);
316 
317 	LOG_DBG("S: datetime: %d, mask: %d", datetime, alarm_msk);
318 
319 	k_spinlock_key_t key = k_spin_lock(&data->lock);
320 
321 	irq_disable(DT_INST_IRQN(0));
322 
323 	rtc_sam0_sync(cfg->regs);
324 	regs->Mode2Alarm[id].ALARM.reg = datetime;
325 	regs->Mode2Alarm[id].MASK.reg = RTC_MODE2_MASK_SEL(alarm_msk);
326 	regs->INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(BIT(id));
327 
328 	irq_enable(DT_INST_IRQN(0));
329 
330 	k_spin_unlock(&data->lock, key);
331 
332 	return 0;
333 }
334 
rtc_sam0_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)335 static int rtc_sam0_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
336 				   struct rtc_time *timeptr)
337 {
338 	const struct rtc_sam0_config *cfg = dev->config;
339 	struct rtc_sam0_data *data = dev->data;
340 	RtcMode2 *regs = &cfg->regs->MODE2;
341 	RTC_MODE2_ALARM_Type datetime;
342 	uint32_t alarm_msk;
343 
344 	if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) {
345 		return -EINVAL;
346 	}
347 
348 	if ((mask == NULL) || (timeptr == NULL)) {
349 		return -EINVAL;
350 	}
351 
352 	k_spinlock_key_t key = k_spin_lock(&data->lock);
353 
354 	rtc_sam0_sync(cfg->regs);
355 
356 	datetime = regs->Mode2Alarm[id].ALARM;
357 	alarm_msk = regs->Mode2Alarm[id].MASK.reg;
358 
359 	LOG_DBG("G: datetime: %d, mask: %d", datetime.reg, alarm_msk);
360 
361 	k_spin_unlock(&data->lock, key);
362 
363 	*mask = rtc_sam0_mask_from_alarm_msk(alarm_msk);
364 
365 	rtc_sam0_tm_from_datetime(timeptr, *mask, datetime);
366 
367 	return 0;
368 }
369 
rtc_sam0_alarm_is_pending(const struct device * dev,uint16_t id)370 static int rtc_sam0_alarm_is_pending(const struct device *dev, uint16_t id)
371 {
372 	const struct rtc_sam0_config *cfg = dev->config;
373 	struct rtc_sam0_data *data = dev->data;
374 	RtcMode2 *regs = &cfg->regs->MODE2;
375 
376 	if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) {
377 		return -EINVAL;
378 	}
379 
380 	k_spinlock_key_t key = k_spin_lock(&data->lock);
381 
382 	if ((regs->INTFLAG.reg & RTC_MODE2_INTFLAG_ALARM(BIT(id))) == 0) {
383 		k_spin_unlock(&data->lock, key);
384 
385 		return 0;
386 	}
387 
388 	regs->INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(BIT(id));
389 
390 	k_spin_unlock(&data->lock, key);
391 
392 	return 1;
393 }
394 
rtc_sam0_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)395 static int rtc_sam0_alarm_set_callback(const struct device *dev, uint16_t id,
396 				       rtc_alarm_callback callback, void *user_data)
397 {
398 	const struct rtc_sam0_config *cfg = dev->config;
399 	struct rtc_sam0_data *data = dev->data;
400 	RtcMode2 *regs = &cfg->regs->MODE2;
401 
402 	if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) {
403 		return -EINVAL;
404 	}
405 
406 	k_spinlock_key_t key = k_spin_lock(&data->lock);
407 
408 	data->alarms[id].cb = callback;
409 	data->alarms[id].cb_data = user_data;
410 
411 	if (callback) {
412 		regs->INTENSET.reg = RTC_MODE2_INTENSET_ALARM(BIT(id));
413 	} else {
414 		regs->INTENCLR.reg = RTC_MODE2_INTENCLR_ALARM(BIT(id));
415 	}
416 
417 	k_spin_unlock(&data->lock, key);
418 
419 	return 0;
420 }
421 
rtc_sam0_isr(const struct device * dev)422 static void rtc_sam0_isr(const struct device *dev)
423 {
424 	const struct rtc_sam0_config *cfg = dev->config;
425 	struct rtc_sam0_data *data = dev->data;
426 	RtcMode2 *regs = &cfg->regs->MODE2;
427 	uint32_t int_flags = regs->INTFLAG.reg;
428 
429 	for (int i = 0; i < cfg->alarms_count; ++i) {
430 		if (int_flags & RTC_MODE2_INTFLAG_ALARM(BIT(i))) {
431 			if (data->alarms[i].cb != NULL) {
432 				data->alarms[i].cb(dev, i, data->alarms[i].cb_data);
433 			}
434 		}
435 	}
436 
437 	regs->INTFLAG.reg |= int_flags;
438 }
439 
440 #endif /* CONFIG_RTC_ALARM */
441 
442 #ifdef CONFIG_RTC_CALIBRATION
rtc_sam0_set_calibration(const struct device * dev,int32_t calibration)443 static int rtc_sam0_set_calibration(const struct device *dev, int32_t calibration)
444 {
445 	const struct rtc_sam0_config *cfg = dev->config;
446 	RtcMode2 *regs = &cfg->regs->MODE2;
447 	int32_t correction = calibration / (1000000000 / cfg->cal_constant);
448 	uint32_t abs_correction = abs(correction);
449 
450 	LOG_DBG("Correction: %d, Absolute: %d, Calibration: %d",
451 		correction, abs_correction, calibration);
452 
453 	if (abs_correction == 0) {
454 		regs->FREQCORR.reg = 0;
455 		return 0;
456 	}
457 
458 	if (abs_correction > RTC_SAM0_CALIBRATE_PPB_MAX) {
459 		LOG_ERR("The calibration %d result in an out of range value %d",
460 			calibration, abs_correction);
461 		return -EINVAL;
462 	}
463 
464 	rtc_sam0_sync(cfg->regs);
465 	regs->FREQCORR.reg = RTC_FREQCORR_VALUE(abs_correction)
466 			   | (correction < 0 ? RTC_FREQCORR_SIGN : 0);
467 
468 	LOG_DBG("W REG: 0x%02x", regs->FREQCORR.reg);
469 
470 	return 0;
471 }
472 
rtc_sam0_get_calibration(const struct device * dev,int32_t * calibration)473 static int rtc_sam0_get_calibration(const struct device *dev, int32_t *calibration)
474 {
475 	const struct rtc_sam0_config *cfg = dev->config;
476 	RtcMode2 *regs = &cfg->regs->MODE2;
477 	int32_t correction;
478 
479 	if (calibration == NULL) {
480 		return -EINVAL;
481 	}
482 
483 	correction = regs->FREQCORR.bit.VALUE;
484 
485 	if (correction == 0) {
486 		*calibration = 0;
487 	} else {
488 		*calibration = (correction * 1000000000) / cfg->cal_constant;
489 	}
490 
491 	if (regs->FREQCORR.bit.SIGN) {
492 		*calibration *= -1;
493 	}
494 
495 	LOG_DBG("R REG: 0x%02x", regs->FREQCORR.reg);
496 
497 	return 0;
498 }
499 #endif /* CONFIG_RTC_CALIBRATION */
500 
rtc_sam0_init(const struct device * dev)501 static int rtc_sam0_init(const struct device *dev)
502 {
503 	const struct rtc_sam0_config *cfg = dev->config;
504 	RtcMode0 *regs = &cfg->regs->MODE0;
505 
506 	LOG_DBG("Counter Mode %d selected", cfg->mode);
507 	LOG_DBG("gclk_id: %d, gclk_gen: %d, prescaler: %d, osc32k: %d",
508 		cfg->gclk_id, cfg->gclk_gen, cfg->prescaler, cfg->osc32_src);
509 
510 	*cfg->mclk |= cfg->mclk_mask;
511 
512 #ifdef MCLK
513 	if (cfg->has_gclk) {
514 		GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN
515 						| GCLK_PCHCTRL_GEN(cfg->gclk_gen);
516 	}
517 #else
518 	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN
519 			  | GCLK_CLKCTRL_GEN(cfg->gclk_gen)
520 			  | GCLK_CLKCTRL_ID(cfg->gclk_id);
521 #endif
522 	rtc_sam0_sync(cfg->regs);
523 
524 #ifdef MCLK
525 	if (cfg->has_osc32kctrl) {
526 		OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL(cfg->osc32_src);
527 	}
528 #endif
529 
530 	rtc_sam0_sync(cfg->regs);
531 	regs->EVCTRL.reg = (cfg->evt_ctrl_msk & RTC_MODE0_EVCTRL_MASK);
532 
533 #ifdef MCLK
534 	regs->CTRLA.reg = RTC_MODE0_CTRLA_ENABLE
535 			| RTC_MODE0_CTRLA_COUNTSYNC
536 			| RTC_MODE0_CTRLA_MODE(cfg->mode)
537 			| RTC_MODE0_CTRLA_PRESCALER(cfg->prescaler + 1);
538 #else
539 	regs->CTRL.reg = RTC_MODE0_CTRL_ENABLE
540 		       | RTC_MODE0_CTRL_MODE(cfg->mode)
541 		       | RTC_MODE0_CTRL_PRESCALER(cfg->prescaler);
542 #endif
543 
544 	regs->INTFLAG.reg = 0;
545 #ifdef CONFIG_RTC_ALARM
546 	IRQ_CONNECT(DT_INST_IRQN(0),
547 		    DT_INST_IRQ(0, priority),
548 		    rtc_sam0_isr,
549 		    DEVICE_DT_INST_GET(0), 0);
550 	irq_enable(DT_INST_IRQN(0));
551 #endif
552 	return 0;
553 }
554 
555 static DEVICE_API(rtc, rtc_sam0_driver_api) = {
556 	.set_time = rtc_sam0_set_time,
557 	.get_time = rtc_sam0_get_time,
558 #ifdef CONFIG_RTC_ALARM
559 	.alarm_get_supported_fields = rtc_sam0_alarm_get_supported_fields,
560 	.alarm_set_time = rtc_sam0_alarm_set_time,
561 	.alarm_get_time = rtc_sam0_alarm_get_time,
562 	.alarm_is_pending = rtc_sam0_alarm_is_pending,
563 	.alarm_set_callback = rtc_sam0_alarm_set_callback,
564 #endif /* CONFIG_RTC_ALARM */
565 #ifdef CONFIG_RTC_CALIBRATION
566 	.set_calibration = rtc_sam0_set_calibration,
567 	.get_calibration = rtc_sam0_get_calibration,
568 #endif /* CONFIG_RTC_CALIBRATION */
569 };
570 
571 #define ASSIGNED_CLOCKS_CELL_BY_NAME							\
572 	ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME
573 
574 #define RTC_SAM0_GCLK(n)								\
575 	COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(n, gclk),					\
576 	(										\
577 		.has_gclk = true,							\
578 		.gclk_gen = ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen),			\
579 		.gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id)			\
580 	),										\
581 	(										\
582 		.has_gclk = false,							\
583 		.gclk_gen = 0,								\
584 		.gclk_id = 0								\
585 	))
586 
587 #define RTC_SAM0_OSC32KCTRL(n)								\
588 	COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(n, osc32kctrl),				\
589 	(										\
590 		.has_osc32kctrl = true,							\
591 		.osc32_src = ASSIGNED_CLOCKS_CELL_BY_NAME(n, osc32kctrl, src)		\
592 	),										\
593 	(										\
594 		.has_osc32kctrl = false,						\
595 		.osc32_src = 0								\
596 	))
597 
598 #define RTC_SAM0_DEVICE(n)								\
599 	BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, counter_mode),				\
600 	"sam0:rtc: Missing counter-mode devicetree property");				\
601 	BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, prescaler),				\
602 	"sam0:rtc: Missing prescaler devicetree property");				\
603 											\
604 	static const struct rtc_sam0_config rtc_sam0_config_##n = {			\
605 		.regs = (Rtc *)DT_INST_REG_ADDR(n),					\
606 		.mode = DT_INST_ENUM_IDX(n, counter_mode),				\
607 		.prescaler = DT_INST_ENUM_IDX(n, prescaler),				\
608 		.evt_ctrl_msk = DT_INST_PROP(n, event_control_msk),			\
609 		RTC_SAM0_GCLK(n),							\
610 		RTC_SAM0_OSC32KCTRL(n),							\
611 		.mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n),			\
612 		.mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit),		\
613 		IF_ENABLED(CONFIG_RTC_ALARM, (						\
614 			.alarms_count = DT_INST_PROP(n, alarms_count),			\
615 		))									\
616 		IF_ENABLED(CONFIG_RTC_CALIBRATION, (					\
617 			.cal_constant = DT_INST_PROP(n, cal_constant),			\
618 		))									\
619 	};										\
620 											\
621 	IF_ENABLED(CONFIG_RTC_ALARM, (							\
622 		static struct rtc_sam0_data_cb						\
623 			rtc_sam0_data_cb_##n[DT_INST_PROP(n, alarms_count)] = {};	\
624 	))										\
625 											\
626 	static struct rtc_sam0_data rtc_sam0_data_##n = {				\
627 		IF_ENABLED(CONFIG_RTC_ALARM, (						\
628 			.alarms = rtc_sam0_data_cb_##n,					\
629 		))									\
630 	};										\
631 											\
632 	DEVICE_DT_INST_DEFINE(n, rtc_sam0_init,						\
633 			      NULL,							\
634 			      &rtc_sam0_data_##n,					\
635 			      &rtc_sam0_config_##n, POST_KERNEL,			\
636 			      CONFIG_RTC_INIT_PRIORITY,					\
637 			      &rtc_sam0_driver_api);					\
638 
639 DT_INST_FOREACH_STATUS_OKAY(RTC_SAM0_DEVICE);
640 
641 /* clang-format on */
642