1 /*
2  * Copyright (c) 2018, Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/drivers/counter.h>
7 #include <hal/nrf_rtc.h>
8 #ifdef CONFIG_CLOCK_CONTROL_NRF
9 #include <zephyr/drivers/clock_control.h>
10 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
11 #endif
12 #include <haly/nrfy_rtc.h>
13 #include <zephyr/sys/atomic.h>
14 #ifdef DPPI_PRESENT
15 #include <nrfx_dppi.h>
16 #else
17 #include <nrfx_ppi.h>
18 #endif
19 
20 #define LOG_MODULE_NAME counter_rtc
21 #include <zephyr/logging/log.h>
22 #include <zephyr/irq.h>
23 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_COUNTER_LOG_LEVEL);
24 
25 #define ERR(...) LOG_INST_ERR( \
26 	((const struct counter_nrfx_config *)dev->config)->log, __VA_ARGS__)
27 #define WRN(...) LOG_INST_WRN( \
28 	((const struct counter_nrfx_config *)dev->config)->log, __VA_ARGS__)
29 #define INF(...) LOG_INST_INF( \
30 	((const struct counter_nrfx_config *)dev->config)->log, __VA_ARGS__)
31 #define DBG(...) LOG_INST_DBG( \
32 	((const struct counter_nrfx_config *)dev->config)->log, __VA_ARGS__)
33 
34 #define DT_DRV_COMPAT nordic_nrf_rtc
35 
36 #define COUNTER_GET_TOP_CH(dev) counter_get_num_of_channels(dev)
37 
38 #define IS_FIXED_TOP(dev) COND_CODE_1(CONFIG_COUNTER_RTC_CUSTOM_TOP_SUPPORT, \
39 		(((const struct counter_nrfx_config *)dev->config)->fixed_top), (true))
40 
41 #define IS_PPI_WRAP(dev) COND_CODE_1(CONFIG_COUNTER_RTC_WITH_PPI_WRAP, \
42 		(((const struct counter_nrfx_config *)dev->config)->use_ppi), (false))
43 
44 #define CC_ADJUSTED_OFFSET 16
45 #define CC_ADJ_MASK(chan) (BIT(chan + CC_ADJUSTED_OFFSET))
46 
47 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
48 #define MAYBE_CONST_CONFIG
49 #else
50 #define MAYBE_CONST_CONFIG const
51 #endif
52 
53 struct counter_nrfx_data {
54 	counter_top_callback_t top_cb;
55 	void *top_user_data;
56 	uint32_t top;
57 	uint32_t guard_period;
58 	/* Store channel interrupt pending and CC adjusted flags. */
59 	atomic_t ipend_adj;
60 #if CONFIG_COUNTER_RTC_WITH_PPI_WRAP
61 	uint8_t ppi_ch;
62 #endif
63 };
64 
65 struct counter_nrfx_ch_data {
66 	counter_alarm_callback_t callback;
67 	void *user_data;
68 };
69 
70 struct counter_nrfx_config {
71 	struct counter_config_info info;
72 	struct counter_nrfx_ch_data *ch_data;
73 	NRF_RTC_Type *rtc;
74 #if CONFIG_COUNTER_RTC_WITH_PPI_WRAP
75 	bool use_ppi;
76 #endif
77 #if CONFIG_COUNTER_RTC_CUSTOM_TOP_SUPPORT
78 	bool fixed_top;
79 #endif
80 	LOG_INSTANCE_PTR_DECLARE(log);
81 };
82 
start(const struct device * dev)83 static int start(const struct device *dev)
84 {
85 	const struct counter_nrfx_config *config = dev->config;
86 
87 	nrfy_rtc_task_trigger(config->rtc, NRF_RTC_TASK_START);
88 
89 	return 0;
90 }
91 
stop(const struct device * dev)92 static int stop(const struct device *dev)
93 {
94 	const struct counter_nrfx_config *config = dev->config;
95 
96 	nrfy_rtc_task_trigger(config->rtc, NRF_RTC_TASK_STOP);
97 
98 	return 0;
99 }
100 
read(const struct device * dev)101 static uint32_t read(const struct device *dev)
102 {
103 	const struct counter_nrfx_config *config = dev->config;
104 
105 	return nrfy_rtc_counter_get(config->rtc);
106 }
107 
get_value(const struct device * dev,uint32_t * ticks)108 static int get_value(const struct device *dev, uint32_t *ticks)
109 {
110 	*ticks = read(dev);
111 	return 0;
112 }
113 
114 /* Function calculates distance between to values assuming that one first
115  * argument is in front and that values wrap.
116  */
ticks_sub(const struct device * dev,uint32_t val,uint32_t old,uint32_t top)117 static uint32_t ticks_sub(const struct device *dev, uint32_t val,
118 			  uint32_t old, uint32_t top)
119 {
120 	if (IS_FIXED_TOP(dev)) {
121 		return (val - old) & NRF_RTC_COUNTER_MAX;
122 	} else if (likely(IS_BIT_MASK(top))) {
123 		return (val - old) & top;
124 	}
125 
126 	/* if top is not 2^n-1 */
127 	return (val >= old) ? (val - old) : val + top + 1 - old;
128 
129 }
130 
skip_zero_on_custom_top(uint32_t val,uint32_t top)131 static uint32_t skip_zero_on_custom_top(uint32_t val, uint32_t top)
132 {
133 	/* From Product Specification: If a CC register value is 0 when
134 	 * a CLEAR task is set, this will not trigger a COMPARE event.
135 	 */
136 	if (unlikely(val == 0) && (top != NRF_RTC_COUNTER_MAX)) {
137 		val++;
138 	}
139 
140 	return val;
141 }
142 
ticks_add(const struct device * dev,uint32_t val1,uint32_t val2,uint32_t top)143 static uint32_t ticks_add(const struct device *dev, uint32_t val1,
144 			  uint32_t val2, uint32_t top)
145 {
146 	uint32_t sum = val1 + val2;
147 
148 	if (IS_FIXED_TOP(dev)) {
149 		ARG_UNUSED(top);
150 		return sum & NRF_RTC_COUNTER_MAX;
151 	}
152 	if (likely(IS_BIT_MASK(top))) {
153 		sum = sum & top;
154 	} else {
155 		sum = sum > top ? sum - (top + 1) : sum;
156 	}
157 
158 	return skip_zero_on_custom_top(sum, top);
159 }
160 
set_cc_int_pending(const struct device * dev,uint8_t chan)161 static void set_cc_int_pending(const struct device *dev, uint8_t chan)
162 {
163 	const struct counter_nrfx_config *config = dev->config;
164 	struct counter_nrfx_data *data = dev->data;
165 
166 	atomic_or(&data->ipend_adj, BIT(chan));
167 	NRFY_IRQ_PENDING_SET(NRFX_IRQ_NUMBER_GET(config->rtc));
168 }
169 
170 /** @brief Handle case when CC value equals COUNTER+1.
171  *
172  * RTC will not generate event if CC value equals COUNTER+1. If such CC is
173  * about to be set then special algorithm is applied. Since counter must not
174  * expire before expected value, CC is set to COUNTER+2. If COUNTER progressed
175  * during that time it means that target value is reached and interrupt is
176  * manually triggered. If not then interrupt is enabled since it is expected
177  * that CC value will generate event.
178  *
179  * Additionally, an information about CC adjustment is stored. This information
180  * is used in the callback to return original CC value which was requested by
181  * the user.
182  */
handle_next_tick_case(const struct device * dev,uint8_t chan,uint32_t now,uint32_t val)183 static void handle_next_tick_case(const struct device *dev, uint8_t chan,
184 				  uint32_t now, uint32_t val)
185 {
186 	const struct counter_nrfx_config *config = dev->config;
187 	struct counter_nrfx_data *data = dev->data;
188 
189 	val = ticks_add(dev, val, 1, data->top);
190 	nrfy_rtc_cc_set(config->rtc, chan, val);
191 	atomic_or(&data->ipend_adj, CC_ADJ_MASK(chan));
192 	if (nrfy_rtc_counter_get(config->rtc) != now) {
193 		set_cc_int_pending(dev, chan);
194 	} else {
195 		nrfy_rtc_int_enable(config->rtc, NRF_RTC_CHANNEL_INT_MASK(chan));
196 	}
197 }
198 
199 /*
200  * @brief Set COMPARE value with optional too late setting detection.
201  *
202  * Setting CC algorithm takes into account:
203  * - Current COMPARE value written to the register may be close to the current
204  *   COUNTER value thus COMPARE event may be generated at any moment
205  * - Next COMPARE value may be soon in the future. Taking into account potential
206  *   preemption COMPARE value may be set too late.
207  * - RTC registers are clocked with LF clock (32kHz) and sampled between two
208  *   LF ticks.
209  * - Setting COMPARE register to COUNTER+1 does not generate COMPARE event if
210  *   done half tick before tick boundary.
211  *
212  * Algorithm assumes that:
213  * - COMPARE interrupt is disabled
214  * - absolute value is taking into account guard period. It means that
215  *   it won't be further in future than <top> - <guard_period> from now.
216  *
217  * @param dev	Device.
218  * @param chan	COMPARE channel.
219  * @param val	Value (absolute or relative).
220  * @param flags	Alarm flags.
221  *
222  * @retval 0 if COMPARE value was set on time and COMPARE interrupt is expected.
223  * @retval -ETIME if absolute alarm was set too late and error reporting is
224  *		  enabled.
225  *
226  */
set_cc(const struct device * dev,uint8_t chan,uint32_t val,uint32_t flags)227 static int set_cc(const struct device *dev, uint8_t chan, uint32_t val,
228 		  uint32_t flags)
229 {
230 	const struct counter_nrfx_config *config = dev->config;
231 	struct counter_nrfx_data *data = dev->data;
232 
233 	__ASSERT_NO_MSG(data->guard_period < data->top);
234 	NRF_RTC_Type  *rtc = config->rtc;
235 	nrf_rtc_event_t evt;
236 	uint32_t prev_val;
237 	uint32_t top;
238 	uint32_t now;
239 	uint32_t diff;
240 	uint32_t int_mask = NRF_RTC_CHANNEL_INT_MASK(chan);
241 	int err = 0;
242 	uint32_t max_rel_val;
243 	bool absolute = flags & COUNTER_ALARM_CFG_ABSOLUTE;
244 	bool irq_on_late;
245 
246 	__ASSERT(nrf_rtc_int_enable_check(rtc, int_mask) == 0,
247 			"Expected that CC interrupt is disabled.");
248 
249 	evt = NRF_RTC_CHANNEL_EVENT_ADDR(chan);
250 	top = data->top;
251 	now = nrfy_rtc_counter_get(rtc);
252 
253 	/* First take care of a risk of an event coming from CC being set to
254 	 * next tick. Reconfigure CC to future (now tick is the furthest
255 	 * future). If CC was set to next tick we need to wait for up to 15us
256 	 * (half of 32k tick) and clean potential event. After that time there
257 	 * is no risk of unwanted event.
258 	 */
259 	prev_val = nrfy_rtc_cc_get(rtc, chan);
260 	nrfy_rtc_event_clear(rtc, evt);
261 	nrfy_rtc_cc_set(rtc, chan, now);
262 	nrfy_rtc_event_enable(rtc, int_mask);
263 
264 	if (ticks_sub(dev, prev_val, now, top) == 1) {
265 		NRFX_DELAY_US(15);
266 		nrfy_rtc_event_clear(rtc, evt);
267 	}
268 
269 	now = nrfy_rtc_counter_get(rtc);
270 
271 	if (absolute) {
272 		val = skip_zero_on_custom_top(val, top);
273 		irq_on_late = flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
274 		max_rel_val = top - data->guard_period;
275 	} else {
276 		/* If relative value is smaller than half of the counter range
277 		 * it is assumed that there is a risk of setting value too late
278 		 * and late detection algorithm must be applied. When late
279 		 * setting is detected, interrupt shall be triggered for
280 		 * immediate expiration of the timer. Detection is performed
281 		 * by limiting relative distance between CC and counter.
282 		 *
283 		 * Note that half of counter range is an arbitrary value.
284 		 */
285 		irq_on_late = val < (top / 2);
286 		/* limit max to detect short relative being set too late. */
287 		max_rel_val = irq_on_late ? top / 2 : top;
288 		val = ticks_add(dev, now, val, top);
289 	}
290 
291 	diff = ticks_sub(dev, val, now, top);
292 	if (diff == 1) {
293 		/* CC cannot be set to COUNTER+1 because that will not
294 		 * generate an event. In that case, special handling is
295 		 * performed (attempt to set CC to COUNTER+2).
296 		 */
297 		handle_next_tick_case(dev, chan, now, val);
298 	} else {
299 		nrfy_rtc_cc_set(rtc, chan, val);
300 		now = nrfy_rtc_counter_get(rtc);
301 
302 		/* decrement value to detect also case when val == read(dev).
303 		 * Otherwise, condition would need to include comparing diff
304 		 * against 0.
305 		 */
306 		diff = ticks_sub(dev, val - 1, now, top);
307 		if (diff > max_rel_val) {
308 			if (absolute) {
309 				err = -ETIME;
310 			}
311 
312 			/* Interrupt is triggered always for relative alarm and
313 			 * for absolute depending on the flag.
314 			 */
315 			if (irq_on_late) {
316 				set_cc_int_pending(dev, chan);
317 			} else {
318 				config->ch_data[chan].callback = NULL;
319 			}
320 		} else if (diff == 0) {
321 			/* It is possible that setting CC was interrupted and
322 			 * CC might be set to COUNTER+1 value which will not
323 			 * generate an event. In that case, special handling
324 			 * is performed (attempt to set CC to COUNTER+2).
325 			 */
326 			handle_next_tick_case(dev, chan, now, val);
327 		} else {
328 			nrfy_rtc_int_enable(rtc, int_mask);
329 		}
330 	}
331 
332 	return err;
333 }
334 
set_channel_alarm(const struct device * dev,uint8_t chan,const struct counter_alarm_cfg * alarm_cfg)335 static int set_channel_alarm(const struct device *dev, uint8_t chan,
336 			     const struct counter_alarm_cfg *alarm_cfg)
337 {
338 	const struct counter_nrfx_config *nrfx_config = dev->config;
339 	struct counter_nrfx_data *data = dev->data;
340 	struct counter_nrfx_ch_data *chdata = &nrfx_config->ch_data[chan];
341 
342 	if (alarm_cfg->ticks > data->top) {
343 		return -EINVAL;
344 	}
345 
346 	if (chdata->callback) {
347 		return -EBUSY;
348 	}
349 
350 	chdata->callback = alarm_cfg->callback;
351 	chdata->user_data = alarm_cfg->user_data;
352 	atomic_and(&data->ipend_adj, ~CC_ADJ_MASK(chan));
353 
354 	return set_cc(dev, chan, alarm_cfg->ticks, alarm_cfg->flags);
355 }
356 
disable(const struct device * dev,uint8_t chan)357 static void disable(const struct device *dev, uint8_t chan)
358 {
359 	const struct counter_nrfx_config *config = dev->config;
360 	NRF_RTC_Type *rtc = config->rtc;
361 	nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR(chan);
362 
363 	nrfy_rtc_event_int_disable(rtc, NRF_RTC_CHANNEL_INT_MASK(chan));
364 	nrfy_rtc_event_clear(rtc, evt);
365 	config->ch_data[chan].callback = NULL;
366 }
367 
cancel_alarm(const struct device * dev,uint8_t chan_id)368 static int cancel_alarm(const struct device *dev, uint8_t chan_id)
369 {
370 	disable(dev, chan_id);
371 
372 	return 0;
373 }
374 
ppi_setup(const struct device * dev,uint8_t chan)375 static int ppi_setup(const struct device *dev, uint8_t chan)
376 {
377 #if CONFIG_COUNTER_RTC_WITH_PPI_WRAP
378 	const struct counter_nrfx_config *nrfx_config = dev->config;
379 	struct counter_nrfx_data *data = dev->data;
380 	NRF_RTC_Type *rtc = nrfx_config->rtc;
381 	nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR(chan);
382 	nrfx_err_t result;
383 
384 	if (!nrfx_config->use_ppi) {
385 		return 0;
386 	}
387 
388 	nrfy_rtc_event_enable(rtc, NRF_RTC_CHANNEL_INT_MASK(chan));
389 #ifdef DPPI_PRESENT
390 	nrfx_dppi_t dppi = NRFX_DPPI_INSTANCE(0);
391 
392 	result = nrfx_dppi_channel_alloc(&dppi, &data->ppi_ch);
393 	if (result != NRFX_SUCCESS) {
394 		ERR("Failed to allocate PPI channel.");
395 		return -ENODEV;
396 	}
397 
398 	nrfy_rtc_subscribe_set(rtc, NRF_RTC_TASK_CLEAR, data->ppi_ch);
399 	nrfy_rtc_publish_set(rtc, evt, data->ppi_ch);
400 	(void)nrfx_dppi_channel_enable(&dppi, data->ppi_ch);
401 #else /* DPPI_PRESENT */
402 	uint32_t evt_addr;
403 	uint32_t task_addr;
404 
405 	evt_addr = nrfy_rtc_event_address_get(rtc, evt);
406 	task_addr = nrfy_rtc_task_address_get(rtc, NRF_RTC_TASK_CLEAR);
407 
408 	result = nrfx_ppi_channel_alloc(&data->ppi_ch);
409 	if (result != NRFX_SUCCESS) {
410 		ERR("Failed to allocate PPI channel.");
411 		return -ENODEV;
412 	}
413 	(void)nrfx_ppi_channel_assign(data->ppi_ch, evt_addr, task_addr);
414 	(void)nrfx_ppi_channel_enable(data->ppi_ch);
415 #endif
416 #endif /* CONFIG_COUNTER_RTC_WITH_PPI_WRAP */
417 	return 0;
418 }
419 
ppi_free(const struct device * dev,uint8_t chan)420 static void ppi_free(const struct device *dev, uint8_t chan)
421 {
422 #if CONFIG_COUNTER_RTC_WITH_PPI_WRAP
423 	const struct counter_nrfx_config *nrfx_config = dev->config;
424 	struct counter_nrfx_data *data = dev->data;
425 	uint8_t ppi_ch = data->ppi_ch;
426 	NRF_RTC_Type *rtc = nrfx_config->rtc;
427 
428 	if (!nrfx_config->use_ppi) {
429 		return;
430 	}
431 	nrfy_rtc_event_disable(rtc, NRF_RTC_CHANNEL_INT_MASK(chan));
432 #ifdef DPPI_PRESENT
433 	nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR(chan);
434 	nrfx_dppi_t dppi = NRFX_DPPI_INSTANCE(0);
435 
436 	(void)nrfx_dppi_channel_disable(&dppi, ppi_ch);
437 	nrfy_rtc_subscribe_clear(rtc, NRF_RTC_TASK_CLEAR);
438 	nrfy_rtc_publish_clear(rtc, evt);
439 	(void)nrfx_dppi_channel_free(&dppi, ppi_ch);
440 #else /* DPPI_PRESENT */
441 	(void)nrfx_ppi_channel_disable(ppi_ch);
442 	(void)nrfx_ppi_channel_free(ppi_ch);
443 #endif
444 #endif
445 }
446 
447 /* Return true if counter must be cleared by the CPU. It is cleared
448  * automatically in case of max top value or PPI usage.
449  */
sw_wrap_required(const struct device * dev)450 static bool sw_wrap_required(const struct device *dev)
451 {
452 	struct counter_nrfx_data *data = dev->data;
453 
454 	return (data->top != NRF_RTC_COUNTER_MAX) && !IS_PPI_WRAP(dev);
455 }
456 
set_fixed_top_value(const struct device * dev,const struct counter_top_cfg * cfg)457 static int set_fixed_top_value(const struct device *dev,
458 				const struct counter_top_cfg *cfg)
459 {
460 	const struct counter_nrfx_config *config = dev->config;
461 	struct counter_nrfx_data *data = dev->data;
462 
463 	NRF_RTC_Type *rtc = config->rtc;
464 
465 	if (cfg->ticks != NRF_RTC_COUNTER_MAX) {
466 		return -EINVAL;
467 	}
468 
469 	nrfy_rtc_int_disable(rtc, NRF_RTC_INT_OVERFLOW_MASK);
470 	data->top_cb = cfg->callback;
471 	data->top_user_data = cfg->user_data;
472 
473 	if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
474 		nrfy_rtc_task_trigger(rtc, NRF_RTC_TASK_CLEAR);
475 	}
476 
477 	if (cfg->callback) {
478 		nrfy_rtc_int_enable(rtc, NRF_RTC_INT_OVERFLOW_MASK);
479 	}
480 
481 	return 0;
482 }
483 
set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)484 static int set_top_value(const struct device *dev,
485 			 const struct counter_top_cfg *cfg)
486 {
487 	const struct counter_nrfx_config *nrfx_config = dev->config;
488 	NRF_RTC_Type *rtc = nrfx_config->rtc;
489 	struct counter_nrfx_data *dev_data = dev->data;
490 	uint32_t top_ch = COUNTER_GET_TOP_CH(dev);
491 	int err = 0;
492 
493 	if (IS_FIXED_TOP(dev)) {
494 		return set_fixed_top_value(dev, cfg);
495 	}
496 
497 	for (int i = 0; i < counter_get_num_of_channels(dev); i++) {
498 		/* Overflow can be changed only when all alarms are
499 		 * disables.
500 		 */
501 		if (nrfx_config->ch_data[i].callback) {
502 			return -EBUSY;
503 		}
504 	}
505 
506 	nrfy_rtc_int_disable(rtc, NRF_RTC_CHANNEL_INT_MASK(top_ch));
507 
508 	if (IS_PPI_WRAP(dev)) {
509 		if ((dev_data->top == NRF_RTC_COUNTER_MAX) &&
510 				cfg->ticks != NRF_RTC_COUNTER_MAX) {
511 			err = ppi_setup(dev, top_ch);
512 		} else if (((dev_data->top != NRF_RTC_COUNTER_MAX) &&
513 				cfg->ticks == NRF_RTC_COUNTER_MAX)) {
514 			ppi_free(dev, top_ch);
515 		}
516 	}
517 
518 	dev_data->top_cb = cfg->callback;
519 	dev_data->top_user_data = cfg->user_data;
520 	dev_data->top = cfg->ticks;
521 	nrfy_rtc_cc_set(rtc, top_ch, cfg->ticks);
522 
523 	if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
524 		nrfy_rtc_task_trigger(rtc, NRF_RTC_TASK_CLEAR);
525 	} else if (read(dev) >= cfg->ticks) {
526 		err = -ETIME;
527 		if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
528 			nrfy_rtc_task_trigger(rtc, NRF_RTC_TASK_CLEAR);
529 		}
530 	}
531 
532 	if (cfg->callback || sw_wrap_required(dev)) {
533 		nrfy_rtc_int_enable(rtc, NRF_RTC_CHANNEL_INT_MASK(top_ch));
534 	}
535 
536 	return err;
537 }
538 
get_pending_int(const struct device * dev)539 static uint32_t get_pending_int(const struct device *dev)
540 {
541 	return 0;
542 }
543 
init_rtc(const struct device * dev,uint32_t prescaler)544 static int init_rtc(const struct device *dev, uint32_t prescaler)
545 {
546 	MAYBE_CONST_CONFIG struct counter_nrfx_config *nrfx_config =
547 			(MAYBE_CONST_CONFIG struct counter_nrfx_config *) dev->config;
548 	struct counter_nrfx_data *data = dev->data;
549 	struct counter_top_cfg top_cfg = {
550 		.ticks = NRF_RTC_COUNTER_MAX
551 	};
552 
553 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
554 	/* For simulated devices we need to convert the hardcoded DT address from the real
555 	 * peripheral into the correct one for simulation
556 	 */
557 	nrfx_config->rtc = nhw_convert_periph_base_addr(nrfx_config->rtc);
558 #endif
559 
560 	NRF_RTC_Type *rtc = nrfx_config->rtc;
561 	int err;
562 
563 #ifdef CONFIG_CLOCK_CONTROL_NRF
564 	z_nrf_clock_control_lf_on(CLOCK_CONTROL_NRF_LF_START_NOWAIT);
565 #endif
566 
567 	nrfy_rtc_prescaler_set(rtc, prescaler);
568 
569 	NRFY_IRQ_ENABLE(NRFX_IRQ_NUMBER_GET(rtc));
570 
571 	data->top = NRF_RTC_COUNTER_MAX;
572 	err = set_top_value(dev, &top_cfg);
573 	DBG("Initialized");
574 
575 	return err;
576 }
577 
get_top_value(const struct device * dev)578 static uint32_t get_top_value(const struct device *dev)
579 {
580 	struct counter_nrfx_data *data = dev->data;
581 
582 	return data->top;
583 }
584 
get_guard_period(const struct device * dev,uint32_t flags)585 static uint32_t get_guard_period(const struct device *dev, uint32_t flags)
586 {
587 	struct counter_nrfx_data *data = dev->data;
588 
589 	return data->guard_period;
590 }
591 
set_guard_period(const struct device * dev,uint32_t guard,uint32_t flags)592 static int set_guard_period(const struct device *dev, uint32_t guard,
593 			    uint32_t flags)
594 {
595 	struct counter_nrfx_data *data = dev->data;
596 
597 	data->guard_period = guard;
598 	return 0;
599 }
600 
top_irq_handle(const struct device * dev)601 static void top_irq_handle(const struct device *dev)
602 {
603 	const struct counter_nrfx_config *config = dev->config;
604 	struct counter_nrfx_data *data = dev->data;
605 
606 	NRF_RTC_Type *rtc = config->rtc;
607 	counter_top_callback_t cb = data->top_cb;
608 	nrf_rtc_event_t top_evt;
609 
610 	top_evt = IS_FIXED_TOP(dev) ?
611 		  NRF_RTC_EVENT_OVERFLOW :
612 		  NRF_RTC_CHANNEL_EVENT_ADDR(counter_get_num_of_channels(dev));
613 
614 	uint32_t event_mask = nrfy_rtc_events_process(rtc, NRFY_EVENT_TO_INT_BITMASK(top_evt));
615 
616 	if (event_mask & NRFY_EVENT_TO_INT_BITMASK(top_evt)) {
617 		/* Perform manual clear if custom top value is used and PPI
618 		 * clearing is not used.
619 		 */
620 		if (!IS_FIXED_TOP(dev) && !IS_PPI_WRAP(dev)) {
621 			nrfy_rtc_task_trigger(rtc, NRF_RTC_TASK_CLEAR);
622 		}
623 
624 		if (cb) {
625 			cb(dev, data->top_user_data);
626 		}
627 	}
628 }
629 
alarm_irq_handle(const struct device * dev,uint32_t chan)630 static void alarm_irq_handle(const struct device *dev, uint32_t chan)
631 {
632 	const struct counter_nrfx_config *config = dev->config;
633 	struct counter_nrfx_data *data = dev->data;
634 
635 	NRF_RTC_Type *rtc = config->rtc;
636 	nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR(chan);
637 	uint32_t int_mask = NRF_RTC_CHANNEL_INT_MASK(chan);
638 
639 	bool hw_irq_pending = nrfy_rtc_events_process(rtc, NRFY_EVENT_TO_INT_BITMASK(evt)) &
640 			      nrfy_rtc_int_enable_check(rtc, NRFY_EVENT_TO_INT_BITMASK(evt));
641 	bool sw_irq_pending = data->ipend_adj & BIT(chan);
642 
643 	if (hw_irq_pending || sw_irq_pending) {
644 		struct counter_nrfx_ch_data *chdata;
645 		counter_alarm_callback_t cb;
646 
647 		atomic_and(&data->ipend_adj, ~BIT(chan));
648 		nrfy_rtc_int_disable(rtc, int_mask);
649 
650 		chdata = &config->ch_data[chan];
651 		cb = chdata->callback;
652 		chdata->callback = NULL;
653 
654 		if (cb) {
655 			uint32_t cc = nrfy_rtc_cc_get(rtc, chan);
656 
657 			if (data->ipend_adj & CC_ADJ_MASK(chan)) {
658 				cc = ticks_sub(dev, cc, 1, data->top);
659 			}
660 
661 			cb(dev, chan, cc, chdata->user_data);
662 		}
663 	}
664 }
665 
irq_handler(const void * arg)666 static void irq_handler(const void *arg)
667 {
668 	const struct device *dev = arg;
669 
670 	top_irq_handle(dev);
671 
672 	for (uint32_t i = 0; i < counter_get_num_of_channels(dev); i++) {
673 		alarm_irq_handle(dev, i);
674 	}
675 }
676 
677 static DEVICE_API(counter, counter_nrfx_driver_api) = {
678 	.start = start,
679 	.stop = stop,
680 	.get_value = get_value,
681 	.set_alarm = set_channel_alarm,
682 	.cancel_alarm = cancel_alarm,
683 	.set_top_value = set_top_value,
684 	.get_pending_int = get_pending_int,
685 	.get_top_value = get_top_value,
686 	.get_guard_period = get_guard_period,
687 	.set_guard_period = set_guard_period,
688 };
689 
690 /*
691  * Devicetree access is done with node labels due to HAL API
692  * requirements. In particular, RTCx_CC_NUM values from HALs
693  * are indexed by peripheral number, so DT_INST APIs won't work.
694  */
695 
696 #define RTC_IRQ_CONNECT(idx)						       \
697 	COND_CODE_1(DT_INST_PROP(idx, zli),				       \
698 		(IRQ_DIRECT_CONNECT(DT_INST_IRQN(idx),			       \
699 				    DT_INST_IRQ(idx, priority),		       \
700 				    counter_rtc##idx##_isr_wrapper,	       \
701 				    IRQ_ZERO_LATENCY)),			       \
702 		(IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority),    \
703 			    irq_handler, DEVICE_DT_INST_GET(idx), 0))	       \
704 	)
705 
706 #define COUNTER_NRF_RTC_DEVICE(idx)					       \
707 	BUILD_ASSERT((DT_INST_PROP(idx, prescaler) - 1) <=		       \
708 		     RTC_PRESCALER_PRESCALER_Msk,			       \
709 		     "RTC prescaler out of range");			       \
710 	COND_CODE_1(DT_INST_PROP(idx, zli), (				       \
711 		ISR_DIRECT_DECLARE(counter_rtc##idx##_isr_wrapper)	       \
712 		{							       \
713 			irq_handler(DEVICE_DT_INST_GET(idx));		       \
714 			/* No rescheduling, it shall not access zephyr primitives. */ \
715 			return 0;					       \
716 		}), ())							       \
717 	static int counter_##idx##_init(const struct device *dev)	       \
718 	{								       \
719 		RTC_IRQ_CONNECT(idx);					       \
720 		return init_rtc(dev, DT_INST_PROP(idx, prescaler) - 1);	       \
721 	}								       \
722 	static struct counter_nrfx_data counter_##idx##_data;		       \
723 	static struct counter_nrfx_ch_data				       \
724 		counter##idx##_ch_data[DT_INST_PROP(idx, cc_num)];	       \
725 	LOG_INSTANCE_REGISTER(LOG_MODULE_NAME, idx, CONFIG_COUNTER_LOG_LEVEL); \
726 	static MAYBE_CONST_CONFIG					       \
727 		struct counter_nrfx_config nrfx_counter_##idx##_config = {     \
728 		.info = {						       \
729 			.max_top_value = NRF_RTC_COUNTER_MAX,		       \
730 			.freq = DT_INST_PROP(idx, clock_frequency) /	       \
731 				DT_INST_PROP(idx, prescaler),		       \
732 			.flags = COUNTER_CONFIG_INFO_COUNT_UP,		       \
733 			.channels = DT_INST_PROP(idx, fixed_top)	       \
734 				  ? DT_INST_PROP(idx, cc_num)		       \
735 				  : DT_INST_PROP(idx, cc_num) - 1	       \
736 		},							       \
737 		.ch_data = counter##idx##_ch_data,			       \
738 		.rtc = (NRF_RTC_Type *)DT_INST_REG_ADDR(idx),		       \
739 		IF_ENABLED(CONFIG_COUNTER_RTC_WITH_PPI_WRAP,		       \
740 			   (.use_ppi = DT_INST_PROP(idx, ppi_wrap),))	       \
741 		IF_ENABLED(CONFIG_COUNTER_RTC_CUSTOM_TOP_SUPPORT,	       \
742 			   (.fixed_top = DT_INST_PROP(idx, fixed_top),))       \
743 		LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx)	       \
744 	};								       \
745 	DEVICE_DT_INST_DEFINE(idx,					       \
746 			    counter_##idx##_init,			       \
747 			    NULL,					       \
748 			    &counter_##idx##_data,			       \
749 			    &nrfx_counter_##idx##_config.info,		       \
750 			    PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY,	       \
751 			    &counter_nrfx_driver_api);
752 
753 DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRF_RTC_DEVICE)
754