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