1 /*
2  * Copyright 2025 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT zephyr_rtc_counter
8 
9 #include <zephyr/drivers/rtc.h>
10 #include <zephyr/drivers/counter.h>
11 #include <zephyr/device.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/types.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/sys/timeutil.h>
16 #include "rtc_utils.h"
17 
18 LOG_MODULE_REGISTER(rtc_counter, CONFIG_RTC_LOG_LEVEL);
19 
20 struct rtc_counter_config {
21 	const struct device *counter_dev;
22 	/* Number of alarm channels */
23 	uint8_t alarms_count;
24 };
25 
26 struct rtc_counter_data {
27 	/* Offset in counter ticks between raw counter and Unix epoch */
28 	int64_t epoch_offset;
29 	/* protects epoch_offset */
30 	struct k_spinlock lock;
31 #ifdef CONFIG_RTC_ALARM
32 	/* false if counter has no alarm channels */
33 	bool alarm_capable;
34 	/* number of alarm channels exposed (<= underlying counter channels) */
35 	uint8_t num_alarm_chans;
36 	const struct device *rtc_dev;
37 	/* Per-instance arrays provided by init macro */
38 	rtc_alarm_callback *alarm_callback;
39 	void **alarm_user_data;
40 	uint16_t *alarm_mask;
41 	struct rtc_time *alarm_time;
42 	bool *alarm_pending;
43 #endif /* CONFIG_RTC_ALARM */
44 };
45 
46 /*
47  * Generic RTC time to ticks conversion using time.h and counter API.
48  * Returns 0 on success, -EINVAL on invalid time or overflow.
49  */
rtc_counter_time_to_ticks(const struct rtc_time * timeptr,uint32_t tick_freq,uint64_t * ticks_out)50 static int rtc_counter_time_to_ticks(const struct rtc_time *timeptr, uint32_t tick_freq,
51 					 uint64_t *ticks_out)
52 {
53 	struct tm tm_val;
54 	int64_t seconds64;
55 
56 	if (timeptr == NULL || ticks_out == NULL) {
57 		return -EINVAL;
58 	}
59 
60 	/* Populate broken-down time structure */
61 	memset(&tm_val, 0, sizeof(tm_val));
62 	tm_val.tm_sec = timeptr->tm_sec;
63 	tm_val.tm_min = timeptr->tm_min;
64 	tm_val.tm_hour = timeptr->tm_hour;
65 	tm_val.tm_mday = timeptr->tm_mday;
66 	tm_val.tm_mon = timeptr->tm_mon;
67 	tm_val.tm_year = timeptr->tm_year;
68 	tm_val.tm_isdst = -1;
69 
70 	/* UTC, 64-bit, no DST/timezone ambiguity */
71 	seconds64 = timeutil_timegm64(&tm_val);
72 
73 	if (seconds64 < 0) {
74 		return -EINVAL;
75 	}
76 
77 	if (tick_freq == 0U) {
78 		return -ERANGE;
79 	}
80 
81 	/* Guard overflow: ticks = seconds * freq must fit into 64-bit */
82 	if ((uint64_t)seconds64 > (uint64_t)INT64_MAX / (uint64_t)tick_freq) {
83 		return -ERANGE;
84 	}
85 
86 	*ticks_out = (uint64_t)seconds64 * (uint64_t)tick_freq;
87 	return 0;
88 }
89 
90 /* Generic RTC ticks to time conversion using time.h and counter API */
rtc_counter_ticks_to_time(uint64_t ticks,uint32_t tick_freq,struct rtc_time * timeptr)91 static void rtc_counter_ticks_to_time(uint64_t ticks, uint32_t tick_freq, struct rtc_time *timeptr)
92 {
93 	time_t seconds;
94 	struct tm tm_val;
95 
96 	if (tick_freq == 0U) {
97 		memset(timeptr, 0, sizeof(struct rtc_time));
98 		return;
99 	}
100 
101 	seconds = (time_t)(ticks / (uint64_t)tick_freq);
102 
103 	if (gmtime_r(&seconds, &tm_val) == NULL) {
104 		memset(timeptr, 0, sizeof(struct rtc_time));
105 		return;
106 	}
107 
108 	timeptr->tm_sec = tm_val.tm_sec;
109 	timeptr->tm_min = tm_val.tm_min;
110 	timeptr->tm_hour = tm_val.tm_hour;
111 	timeptr->tm_mday = tm_val.tm_mday;
112 	timeptr->tm_mon = tm_val.tm_mon;
113 	timeptr->tm_year = tm_val.tm_year;
114 	timeptr->tm_wday = tm_val.tm_wday;
115 	timeptr->tm_yday = tm_val.tm_yday;
116 	timeptr->tm_isdst = -1;
117 	timeptr->tm_nsec = 0;
118 }
119 
120 #if defined(CONFIG_RTC_ALARM)
121 
rtc_counter_alarm_callback(const struct device * counter_dev,uint8_t chan_id,uint32_t ticks,void * user_data)122 static void rtc_counter_alarm_callback(const struct device *counter_dev, uint8_t chan_id,
123 				       uint32_t ticks, void *user_data)
124 {
125 	struct rtc_counter_data *data = (struct rtc_counter_data *)user_data;
126 	const struct device *rtc_dev = data->rtc_dev;
127 
128 	if (chan_id < data->num_alarm_chans && data->alarm_callback[chan_id] != NULL) {
129 		data->alarm_callback[chan_id](rtc_dev, chan_id, data->alarm_user_data[chan_id]);
130 		data->alarm_pending[chan_id] = false;
131 	} else if (chan_id < data->num_alarm_chans) {
132 		data->alarm_pending[chan_id] = true;
133 	} else {
134 		LOG_DBG("Spurious alarm callback on channel %u (max %u)", chan_id,
135 			data->num_alarm_chans ? (data->num_alarm_chans - 1U) : 0U);
136 	}
137 }
138 
rtc_counter_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)139 static int rtc_counter_alarm_get_supported_fields(const struct device *dev, uint16_t id,
140 						  uint16_t *mask)
141 {
142 	struct rtc_counter_data *data = dev->data;
143 
144 	if (!data->alarm_capable) {
145 		return -ENOTSUP;
146 	}
147 
148 	if (id >= data->num_alarm_chans) {
149 		return -EINVAL;
150 	}
151 
152 	*mask = (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE |
153 		 RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY |
154 		 RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_YEAR |
155 		 RTC_ALARM_TIME_MASK_WEEKDAY | RTC_ALARM_TIME_MASK_YEARDAY);
156 
157 	return 0;
158 }
159 
rtc_counter_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)160 static int rtc_counter_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
161 				      const struct rtc_time *timeptr)
162 {
163 	const struct rtc_counter_config *config = dev->config;
164 	struct rtc_counter_data *data = dev->data;
165 	uint64_t desired_ticks;
166 	uint32_t freq;
167 	int ret;
168 	int64_t epoch;
169 	int64_t raw_alarm_ticks_64;
170 	uint32_t top;
171 	uint32_t alarm_ticks;
172 	uint32_t now_raw;
173 	struct counter_alarm_cfg alarm_cfg;
174 
175 	if (!data->alarm_capable) {
176 		return -ENOTSUP;
177 	}
178 
179 	if (id >= data->num_alarm_chans) {
180 		return -EINVAL;
181 	}
182 
183 	if (mask == 0U) {
184 		/* Disable alarm on selected channel */
185 		ret = counter_cancel_channel_alarm(config->counter_dev, (uint8_t)id);
186 		if (ret == 0) {
187 			K_SPINLOCK(&data->lock) {
188 				data->alarm_mask[id] = 0U;
189 				data->alarm_pending[id] = false;
190 				memset(&data->alarm_time[id], 0, sizeof(struct rtc_time));
191 			}
192 		}
193 		return ret;
194 	}
195 
196 	if (timeptr == NULL) {
197 		return -EINVAL;
198 	}
199 
200 	if (!rtc_utils_validate_rtc_time(timeptr, mask)) {
201 		return -EINVAL;
202 	}
203 
204 	freq = counter_get_frequency(config->counter_dev);
205 
206 	ret = rtc_counter_time_to_ticks(timeptr, freq, &desired_ticks);
207 
208 	/* -EINVAL on overflow/invalid time */
209 	if (ret < 0) {
210 		return ret;
211 	}
212 
213 	/* Convert desired absolute Unix time to a raw tick value for the counter */
214 	K_SPINLOCK(&data->lock) {
215 		epoch = data->epoch_offset;
216 	}
217 
218 	raw_alarm_ticks_64 = (int64_t)desired_ticks - epoch;
219 	/* Reject wraparound: must be within current window and not in the past */
220 	top = counter_get_top_value(config->counter_dev);
221 
222 	/* would require wrap */
223 	if (raw_alarm_ticks_64 < 0 || raw_alarm_ticks_64 > (int64_t)top) {
224 		return -ERANGE;
225 	}
226 
227 	alarm_ticks = (uint32_t)raw_alarm_ticks_64;
228 
229 	ret = counter_get_value(config->counter_dev, &now_raw);
230 	if (ret < 0) {
231 		return ret;
232 	}
233 
234 	/* target already passed in this window or equals 'now' */
235 	if (alarm_ticks <= now_raw) {
236 		/* 1-tick guard, but cannot wrap */
237 		if (now_raw == top) {
238 			return -ERANGE;
239 		}
240 		alarm_ticks = now_raw + 1U;
241 	}
242 
243 	alarm_cfg.callback = rtc_counter_alarm_callback;
244 	alarm_cfg.ticks = alarm_ticks;
245 	alarm_cfg.user_data = data;
246 	alarm_cfg.flags = COUNTER_ALARM_CFG_ABSOLUTE | COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
247 
248 	/* Record configured mask and time for get_time; clear pending */
249 	K_SPINLOCK(&data->lock) {
250 		data->alarm_mask[id] = mask;
251 		data->alarm_time[id] = *timeptr;
252 		data->alarm_pending[id] = false;
253 	}
254 
255 	return counter_set_channel_alarm(config->counter_dev, (uint8_t)id, &alarm_cfg);
256 }
257 
rtc_counter_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)258 static int rtc_counter_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
259 				      struct rtc_time *timeptr)
260 {
261 	struct rtc_counter_data *data = dev->data;
262 	int ret = 0;
263 
264 	if (!data->alarm_capable) {
265 		return -ENOTSUP;
266 	}
267 
268 	if (id >= data->num_alarm_chans) {
269 		return -EINVAL;
270 	}
271 
272 	if (mask == NULL || timeptr == NULL) {
273 		return -EINVAL;
274 	}
275 
276 	K_SPINLOCK(&data->lock) {
277 		if (data->alarm_mask[id] == 0U) {
278 			ret = -EINVAL;
279 		} else {
280 			*mask = data->alarm_mask[id];
281 			*timeptr = data->alarm_time[id];
282 		}
283 	}
284 
285 	return ret;
286 }
287 
rtc_counter_alarm_is_pending(const struct device * dev,uint16_t id)288 static int rtc_counter_alarm_is_pending(const struct device *dev, uint16_t id)
289 {
290 	int ret = 0;
291 	struct rtc_counter_data *data = dev->data;
292 
293 	if (!data->alarm_capable) {
294 		return -ENOTSUP;
295 	}
296 
297 	if (id >= data->num_alarm_chans) {
298 		return -EINVAL;
299 	}
300 
301 	K_SPINLOCK(&data->lock) {
302 		ret = data->alarm_pending[id] ? 1 : 0;
303 		data->alarm_pending[id] = false;
304 	}
305 
306 	return ret;
307 }
308 
rtc_counter_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)309 static int rtc_counter_alarm_set_callback(const struct device *dev, uint16_t id,
310 					  rtc_alarm_callback callback, void *user_data)
311 {
312 	struct rtc_counter_data *data = dev->data;
313 
314 	if (!data->alarm_capable) {
315 		return -ENOTSUP;
316 	}
317 
318 	if (id >= data->num_alarm_chans) {
319 		return -EINVAL;
320 	}
321 
322 	K_SPINLOCK(&data->lock) {
323 		data->alarm_callback[id] = callback;
324 		data->alarm_user_data[id] = user_data;
325 	}
326 
327 	return 0;
328 }
329 
330 /* Compute rearm tick within current counter window.
331  * Returns true and writes the tick to out_ticks; returns false if it should be skipped.
332  */
rtc_counter_compute_rearm_ticks(int64_t raw_alarm_ticks_64,uint32_t now_raw,uint32_t top,uint32_t * out_ticks)333 static inline bool rtc_counter_compute_rearm_ticks(int64_t raw_alarm_ticks_64, uint32_t now_raw,
334 						   uint32_t top, uint32_t *out_ticks)
335 {
336 	/* Out of range */
337 	if (raw_alarm_ticks_64 > (int64_t)top) {
338 		return false;
339 	}
340 
341 	/* In the past: arm to next tick if possible */
342 	if (raw_alarm_ticks_64 < 0) {
343 		if (now_raw == top) {
344 			return false;
345 		}
346 		*out_ticks = now_raw + 1U;
347 		return true;
348 	}
349 
350 	/* Within range */
351 	*out_ticks = (uint32_t)raw_alarm_ticks_64;
352 	if (*out_ticks <= now_raw) {
353 		if (now_raw == top) {
354 			return false;
355 		}
356 		*out_ticks = now_raw + 1U;
357 	}
358 
359 	return true;
360 }
361 
362 /* Recompute and rearm all active alarms after a time base (epoch) change */
rtc_counter_reschedule_alarms(const struct device * dev)363 static void rtc_counter_reschedule_alarms(const struct device *dev)
364 {
365 	const struct rtc_counter_config *config = dev->config;
366 	struct rtc_counter_data *data = dev->data;
367 	uint16_t configured_mask;
368 	struct rtc_time configured_time;
369 	uint64_t alarm_abs_ticks;
370 	uint32_t freq;
371 	int64_t epoch;
372 	int64_t raw_alarm_ticks_64;
373 	uint32_t top;
374 	uint32_t now_raw;
375 	uint32_t alarm_ticks;
376 	struct counter_alarm_cfg alarm_cfg;
377 
378 	/* Time base changed: reschedule any active alarms to the new epoch */
379 	if (!(data->alarm_capable && data->num_alarm_chans > 0U)) {
380 		return;
381 	}
382 
383 	for (uint8_t id = 0U; id < data->num_alarm_chans; id++) {
384 		/* Snapshot configured alarm (if any) and clear pending */
385 		K_SPINLOCK(&data->lock) {
386 			configured_mask = data->alarm_mask[id];
387 			configured_time = data->alarm_time[id];
388 			data->alarm_pending[id] = false;
389 		}
390 
391 		if (configured_mask == 0U) {
392 			continue;
393 		}
394 
395 		/* Cancel any in-flight alarm before reprogramming */
396 		(void)counter_cancel_channel_alarm(config->counter_dev, (uint8_t)id);
397 
398 		freq = counter_get_frequency(config->counter_dev);
399 		if (rtc_counter_time_to_ticks(&configured_time, freq, &alarm_abs_ticks) < 0) {
400 			/* Should not happen: skip this alarm */
401 			continue;
402 		}
403 
404 		K_SPINLOCK(&data->lock) {
405 			epoch = data->epoch_offset;
406 		}
407 
408 		raw_alarm_ticks_64 = (int64_t)alarm_abs_ticks - epoch;
409 		top = counter_get_top_value(config->counter_dev);
410 		if (counter_get_value(config->counter_dev, &now_raw) < 0) {
411 			continue;
412 		}
413 
414 		if (!rtc_counter_compute_rearm_ticks(raw_alarm_ticks_64, now_raw, top,
415 						     &alarm_ticks)) {
416 			continue;
417 		}
418 
419 		alarm_cfg.callback = rtc_counter_alarm_callback;
420 		alarm_cfg.ticks = alarm_ticks;
421 		alarm_cfg.user_data = data;
422 		alarm_cfg.flags = COUNTER_ALARM_CFG_ABSOLUTE | COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
423 
424 		(void)counter_set_channel_alarm(config->counter_dev, (uint8_t)id, &alarm_cfg);
425 	}
426 }
427 
428 #endif /* CONFIG_RTC_ALARM */
429 
rtc_counter_set_time(const struct device * dev,const struct rtc_time * timeptr)430 static int rtc_counter_set_time(const struct device *dev, const struct rtc_time *timeptr)
431 {
432 	const struct rtc_counter_config *config = dev->config;
433 	struct rtc_counter_data *data = dev->data;
434 	uint64_t desired_ticks = 0;
435 	uint32_t now_ticks = 0;
436 	int ret;
437 	uint32_t freq;
438 
439 	if (timeptr == NULL) {
440 		return -EINVAL;
441 	}
442 
443 	freq = counter_get_frequency(config->counter_dev);
444 
445 	ret = rtc_counter_time_to_ticks(timeptr, freq, &desired_ticks);
446 
447 	/* -EINVAL on overflow/invalid time */
448 	if (ret < 0) {
449 		return ret;
450 	}
451 
452 	/* Stop counter */
453 	ret = counter_stop(config->counter_dev);
454 
455 	if (ret < 0) {
456 		return ret;
457 	}
458 
459 	ret = counter_get_value(config->counter_dev, &now_ticks);
460 	if (ret < 0) {
461 		return ret;
462 	}
463 
464 	/* Update the software offset (in ticks): offset = desired_ticks - now_ticks */
465 	K_SPINLOCK(&data->lock) {
466 		data->epoch_offset = (int64_t)desired_ticks - (int64_t)now_ticks;
467 	}
468 
469 #ifdef CONFIG_RTC_ALARM
470 	rtc_counter_reschedule_alarms(dev);
471 #endif /* CONFIG_RTC_ALARM */
472 
473 	/* Restart counter */
474 	ret = counter_start(config->counter_dev);
475 	if (ret < 0) {
476 		return ret;
477 	}
478 
479 	return 0;
480 }
481 
rtc_counter_get_time(const struct device * dev,struct rtc_time * timeptr)482 static int rtc_counter_get_time(const struct device *dev, struct rtc_time *timeptr)
483 {
484 	const struct rtc_counter_config *config = dev->config;
485 	struct rtc_counter_data *data = dev->data;
486 	uint32_t now_ticks;
487 	int ret;
488 	int64_t epoch;
489 	uint64_t current_ticks_64;
490 	uint32_t freq;
491 
492 	if (timeptr == NULL) {
493 		return -EINVAL;
494 	}
495 
496 	ret = counter_get_value(config->counter_dev, &now_ticks);
497 
498 	if (ret < 0) {
499 		return ret;
500 	}
501 
502 	K_SPINLOCK(&data->lock) {
503 		epoch = data->epoch_offset;
504 	}
505 
506 	/* Compute accumulated ticks (may be > 32-bit) */
507 	int64_t sum_ticks = (int64_t)now_ticks + epoch;
508 
509 	if (sum_ticks < 0) {
510 		return -ERANGE;
511 	}
512 	current_ticks_64 = (uint64_t)sum_ticks;
513 	freq = counter_get_frequency(config->counter_dev);
514 
515 	/* Optional guard: derived seconds must fit 32-bit to mirror prior check */
516 	if (freq == 0U) {
517 		return -ERANGE;
518 	}
519 	if ((current_ticks_64 / (uint64_t)freq) > (uint64_t)UINT32_MAX) {
520 		return -ERANGE;
521 	}
522 
523 	memset(timeptr, 0, sizeof(struct rtc_time));
524 	rtc_counter_ticks_to_time(current_ticks_64, freq, timeptr);
525 
526 	return 0;
527 }
528 
529 #if defined(CONFIG_RTC_UPDATE)
530 
rtc_counter_update_set_callback(const struct device * dev,rtc_update_callback callback,void * user_data)531 static int rtc_counter_update_set_callback(const struct device *dev, rtc_update_callback callback,
532 					   void *user_data)
533 {
534 	ARG_UNUSED(dev);
535 	ARG_UNUSED(callback);
536 	ARG_UNUSED(user_data);
537 
538 	return -ENOTSUP;
539 }
540 
541 #endif /* CONFIG_RTC_UPDATE */
542 
543 #if defined(CONFIG_RTC_CALIBRATION)
544 
rtc_counter_set_calibration(const struct device * dev,int32_t calibration)545 static int rtc_counter_set_calibration(const struct device *dev, int32_t calibration)
546 {
547 	ARG_UNUSED(dev);
548 	ARG_UNUSED(calibration);
549 	return -ENOTSUP;
550 }
551 
rtc_counter_get_calibration(const struct device * dev,int32_t * calibration)552 static int rtc_counter_get_calibration(const struct device *dev, int32_t *calibration)
553 {
554 	ARG_UNUSED(dev);
555 	ARG_UNUSED(calibration);
556 	return -ENOTSUP;
557 }
558 
559 #endif /* CONFIG_RTC_CALIBRATION */
560 
rtc_counter_init(const struct device * dev)561 static int rtc_counter_init(const struct device *dev)
562 {
563 	const struct rtc_counter_config *config = dev->config;
564 	struct rtc_counter_data *data = dev->data;
565 	uint32_t freq;
566 
567 	if (!device_is_ready(config->counter_dev)) {
568 		LOG_ERR("Counter device %s not ready", config->counter_dev->name);
569 		return -ENODEV;
570 	}
571 
572 	/* Validate counter frequency (must be non-zero) */
573 	freq = counter_get_frequency(config->counter_dev);
574 	if (freq == 0U) {
575 		LOG_ERR("Unsupported counter frequency: %u Hz", freq);
576 		return -ENOTSUP;
577 	}
578 
579 	/* Start with zero offset until rtc_set_time is called */
580 	data->epoch_offset = 0;
581 
582 #ifdef CONFIG_RTC_ALARM
583 	data->rtc_dev = dev;
584 	if (config->alarms_count == 0U) {
585 		data->alarm_capable = false;
586 	} else {
587 		data->alarm_capable = true;
588 		data->num_alarm_chans = config->alarms_count;
589 		/* Clear per-channel state */
590 		for (uint8_t i = 0; i < data->num_alarm_chans; i++) {
591 			data->alarm_callback[i] = NULL;
592 			data->alarm_user_data[i] = NULL;
593 			data->alarm_mask[i] = 0;
594 			memset(&data->alarm_time[i], 0, sizeof(struct rtc_time));
595 			data->alarm_pending[i] = false;
596 		}
597 	}
598 #endif /* CONFIG_RTC_ALARM */
599 
600 	return 0;
601 }
602 
603 static DEVICE_API(rtc, rtc_counter_driver_api) = {
604 	.set_time = rtc_counter_set_time,
605 	.get_time = rtc_counter_get_time,
606 #if defined(CONFIG_RTC_ALARM)
607 	.alarm_get_supported_fields = rtc_counter_alarm_get_supported_fields,
608 	.alarm_set_time = rtc_counter_alarm_set_time,
609 	.alarm_get_time = rtc_counter_alarm_get_time,
610 	.alarm_is_pending = rtc_counter_alarm_is_pending,
611 	.alarm_set_callback = rtc_counter_alarm_set_callback,
612 #endif /* CONFIG_RTC_ALARM */
613 #if defined(CONFIG_RTC_UPDATE)
614 	.update_set_callback = rtc_counter_update_set_callback,
615 #endif /* CONFIG_RTC_UPDATE */
616 #if defined(CONFIG_RTC_CALIBRATION)
617 	.set_calibration = rtc_counter_set_calibration,
618 	.get_calibration = rtc_counter_get_calibration,
619 #endif /* CONFIG_RTC_CALIBRATION */
620 };
621 
622 /* Ensure RTC init priority is bigger than counter */
623 BUILD_ASSERT(CONFIG_RTC_INIT_PRIORITY > CONFIG_COUNTER_INIT_PRIORITY,
624 	     "RTC init priority must be bigger than counter");
625 
626 #define RTC_COUNTER_ALARMS_COUNT(n) DT_PROP_OR(DT_DRV_INST(n), alarms_count, 0)
627 #define RTC_COUNTER_ALARMS_SZ(n)    MAX(RTC_COUNTER_ALARMS_COUNT(n), 1)
628 
629 #if defined(CONFIG_RTC_ALARM)
630 
631 /* Per-instance static storage for alarm context, sized from DT */
632 #define RTC_COUNTER_DECLARE_ALARM_STORAGE(n)                                                \
633 	static rtc_alarm_callback rtc_counter_alarm_callback_arr_##n[RTC_COUNTER_ALARMS_SZ(n)]; \
634 	static void *rtc_counter_alarm_user_data_arr_##n[RTC_COUNTER_ALARMS_SZ(n)];             \
635 	static uint16_t rtc_counter_alarm_mask_arr_##n[RTC_COUNTER_ALARMS_SZ(n)];               \
636 	static struct rtc_time rtc_counter_alarm_time_arr_##n[RTC_COUNTER_ALARMS_SZ(n)];        \
637 	static bool rtc_counter_alarm_pending_arr_##n[RTC_COUNTER_ALARMS_SZ(n)];
638 
639 DT_INST_FOREACH_STATUS_OKAY(RTC_COUNTER_DECLARE_ALARM_STORAGE)
640 
641 #endif /* CONFIG_RTC_ALARM */
642 
643 #define RTC_COUNTER_DEVICE_INIT(n) \
644 	static const struct rtc_counter_config rtc_counter_config_##n = {           \
645 		.counter_dev = DEVICE_DT_GET(DT_INST_PARENT(n)),                        \
646 		.alarms_count = DT_PROP_OR(DT_DRV_INST(n), alarms_count, 0),            \
647 	};                                                                          \
648 	static struct rtc_counter_data rtc_counter_data_##n = {                     \
649 		IF_ENABLED(CONFIG_RTC_ALARM, (                                          \
650 			.alarm_callback = rtc_counter_alarm_callback_arr_##n,               \
651 			.alarm_user_data = rtc_counter_alarm_user_data_arr_##n,             \
652 			.alarm_mask = rtc_counter_alarm_mask_arr_##n,                       \
653 			.alarm_time = rtc_counter_alarm_time_arr_##n,                       \
654 			.alarm_pending = rtc_counter_alarm_pending_arr_##n,                 \
655 		))                                                                      \
656 	};                                                                          \
657 	DEVICE_DT_INST_DEFINE(n, rtc_counter_init, NULL, &rtc_counter_data_##n,     \
658 				&rtc_counter_config_##n, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, \
659 				&rtc_counter_driver_api);
660 
661 DT_INST_FOREACH_STATUS_OKAY(RTC_COUNTER_DEVICE_INIT)
662