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