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