1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file
10  * @brief Public API for counter and timer drivers
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_
14 #define ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_
15 
16 /**
17  * @brief Counter Interface
18  * @defgroup counter_interface Counter Interface
19  * @ingroup io_interfaces
20  * @{
21  */
22 
23 #include <errno.h>
24 
25 #include <zephyr/types.h>
26 #include <stddef.h>
27 #include <zephyr/device.h>
28 #include <zephyr/sys_clock.h>
29 #include <stdbool.h>
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /**@defgroup COUNTER_FLAGS Counter device capabilities
36  * @{ */
37 
38 /**
39  * @brief Counter count up flag.
40  */
41 #define COUNTER_CONFIG_INFO_COUNT_UP BIT(0)
42 
43 /**@} */
44 
45 /**@defgroup COUNTER_TOP_FLAGS Flags used by @ref counter_top_cfg.
46  * @{
47  */
48 
49 /**
50  * @brief Flag preventing counter reset when top value is changed.
51  *
52  * If flags is set then counter is free running while top value is updated,
53  * otherwise counter is reset (see @ref counter_set_top_value()).
54  */
55 #define COUNTER_TOP_CFG_DONT_RESET BIT(0)
56 
57 /**
58  * @brief Flag instructing counter to reset itself if changing top value
59  *	  results in counter going out of new top value bound.
60  *
61  * See @ref COUNTER_TOP_CFG_DONT_RESET.
62  */
63 #define COUNTER_TOP_CFG_RESET_WHEN_LATE BIT(1)
64 
65 /**@} */
66 
67 /**@defgroup COUNTER_ALARM_FLAGS Alarm configuration flags
68  *
69  * @brief Used in alarm configuration structure (@ref counter_alarm_cfg).
70  * @{ */
71 
72 /**
73  * @brief Counter alarm absolute value flag.
74  *
75  * Ticks relation to counter value. If set ticks are treated as absolute value,
76  * else it is relative to the counter reading performed during the call.
77  */
78 #define COUNTER_ALARM_CFG_ABSOLUTE BIT(0)
79 
80 /**
81  * @brief Alarm flag enabling immediate expiration when driver detects that
82  *	  absolute alarm was set too late.
83  *
84  * Alarm callback must be called from the same context as if it was set on time.
85  */
86 #define COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE  BIT(1)
87 
88 /**@} */
89 
90 /**@defgroup COUNTER_GUARD_PERIOD_FLAGS Counter guard period flags
91  *
92  * @brief Used by @ref counter_set_guard_period and
93  *	  @ref counter_get_guard_period.
94  * @{ */
95 
96 /**
97  * @brief Identifies guard period needed for detection of late setting of
98  *	  absolute alarm (see @ref counter_set_channel_alarm).
99  */
100 #define COUNTER_GUARD_PERIOD_LATE_TO_SET BIT(0)
101 
102 /**@} */
103 
104 /** @brief Alarm callback
105  *
106  * @param dev       Pointer to the device structure for the driver instance.
107  * @param chan_id   Channel ID.
108  * @param ticks     Counter value that triggered the alarm.
109  * @param user_data User data.
110  */
111 typedef void (*counter_alarm_callback_t)(const struct device *dev,
112 					 uint8_t chan_id, uint32_t ticks,
113 					 void *user_data);
114 
115 /** @brief Alarm callback structure.
116  *
117  * @param callback Callback called on alarm (cannot be NULL).
118  * @param ticks Number of ticks that triggers the alarm. It can be relative (to
119  *		now) or an absolute value (see @ref COUNTER_ALARM_CFG_ABSOLUTE).
120  *		Both, relative and absolute, alarm values can be any value
121  *		between zero and the current top value (see @ref counter_get_top_value).
122  *		When setting an absolute alarm value close to the current counter
123  *		value there is a risk that the counter will have counted past the
124  *		given absolute value before the driver manages to activate the alarm.
125  *		Therefore a guard period can be defined that lets the driver decide
126  *		unambiguously whether it is late or not (see @ref counter_set_guard_period).
127  *		If the counter is clock driven then ticks can be converted to
128  *		microseconds (see @ref counter_ticks_to_us). Alternatively,
129  *		the counter implementation may count asynchronous events.
130  * @param user_data User data returned in callback.
131  * @param flags	Alarm flags. See @ref COUNTER_ALARM_FLAGS.
132  */
133 struct counter_alarm_cfg {
134 	counter_alarm_callback_t callback;
135 	uint32_t ticks;
136 	void *user_data;
137 	uint32_t flags;
138 };
139 
140 /** @brief Callback called when counter turns around.
141  *
142  * @param dev       Pointer to the device structure for the driver instance.
143  * @param user_data User data provided in @ref counter_set_top_value.
144  */
145 typedef void (*counter_top_callback_t)(const struct device *dev,
146 				       void *user_data);
147 
148 /** @brief Top value configuration structure.
149  *
150  * @param ticks		Top value.
151  * @param callback	Callback function. Can be NULL.
152  * @param user_data	User data passed to callback function. Not valid if
153  *			callback is NULL.
154  * @param flags		Flags. See @ref COUNTER_TOP_FLAGS.
155  */
156 struct counter_top_cfg {
157 	uint32_t ticks;
158 	counter_top_callback_t callback;
159 	void *user_data;
160 	uint32_t flags;
161 };
162 
163 /** @brief Structure with generic counter features.
164  *
165  * @param max_top_value Maximal (default) top value on which counter is reset
166  *			(cleared or reloaded).
167  * @param freq		Frequency of the source clock if synchronous events are
168  *			counted.
169  * @param flags		Flags. See @ref COUNTER_FLAGS.
170  * @param channels	Number of channels that can be used for setting alarm,
171  *			see @ref counter_set_channel_alarm.
172  */
173 struct counter_config_info {
174 	uint32_t max_top_value;
175 	uint32_t freq;
176 	uint8_t flags;
177 	uint8_t channels;
178 };
179 
180 typedef int (*counter_api_start)(const struct device *dev);
181 typedef int (*counter_api_stop)(const struct device *dev);
182 typedef int (*counter_api_get_value)(const struct device *dev,
183 				     uint32_t *ticks);
184 typedef int (*counter_api_get_value_64)(const struct device *dev,
185 			uint64_t *ticks);
186 typedef int (*counter_api_set_alarm)(const struct device *dev,
187 				     uint8_t chan_id,
188 				     const struct counter_alarm_cfg *alarm_cfg);
189 typedef int (*counter_api_cancel_alarm)(const struct device *dev,
190 					uint8_t chan_id);
191 typedef int (*counter_api_set_top_value)(const struct device *dev,
192 					 const struct counter_top_cfg *cfg);
193 typedef uint32_t (*counter_api_get_pending_int)(const struct device *dev);
194 typedef uint32_t (*counter_api_get_top_value)(const struct device *dev);
195 typedef uint32_t (*counter_api_get_guard_period)(const struct device *dev,
196 						 uint32_t flags);
197 typedef int (*counter_api_set_guard_period)(const struct device *dev,
198 						uint32_t ticks,
199 						uint32_t flags);
200 typedef uint32_t (*counter_api_get_freq)(const struct device *dev);
201 
202 __subsystem struct counter_driver_api {
203 	counter_api_start start;
204 	counter_api_stop stop;
205 	counter_api_get_value get_value;
206 	counter_api_get_value_64 get_value_64;
207 	counter_api_set_alarm set_alarm;
208 	counter_api_cancel_alarm cancel_alarm;
209 	counter_api_set_top_value set_top_value;
210 	counter_api_get_pending_int get_pending_int;
211 	counter_api_get_top_value get_top_value;
212 	counter_api_get_guard_period get_guard_period;
213 	counter_api_set_guard_period set_guard_period;
214 	counter_api_get_freq get_freq;
215 };
216 
217 /**
218  * @brief Function to check if counter is counting up.
219  *
220  * @param[in]  dev    Pointer to the device structure for the driver instance.
221  *
222  * @retval true if counter is counting up.
223  * @retval false if counter is counting down.
224  */
225 __syscall bool counter_is_counting_up(const struct device *dev);
226 
z_impl_counter_is_counting_up(const struct device * dev)227 static inline bool z_impl_counter_is_counting_up(const struct device *dev)
228 {
229 	const struct counter_config_info *config =
230 			(const struct counter_config_info *)dev->config;
231 
232 	return config->flags & COUNTER_CONFIG_INFO_COUNT_UP;
233 }
234 
235 /**
236  * @brief Function to get number of alarm channels.
237  *
238  * @param[in]  dev    Pointer to the device structure for the driver instance.
239  *
240  * @return Number of alarm channels.
241  */
242 __syscall uint8_t counter_get_num_of_channels(const struct device *dev);
243 
z_impl_counter_get_num_of_channels(const struct device * dev)244 static inline uint8_t z_impl_counter_get_num_of_channels(const struct device *dev)
245 {
246 	const struct counter_config_info *config =
247 			(const struct counter_config_info *)dev->config;
248 
249 	return config->channels;
250 }
251 
252 /**
253  * @brief Function to get counter frequency.
254  *
255  * @param[in]  dev    Pointer to the device structure for the driver instance.
256  *
257  * @return Frequency of the counter in Hz, or zero if the counter does
258  * not have a fixed frequency.
259  */
260 __syscall uint32_t counter_get_frequency(const struct device *dev);
261 
z_impl_counter_get_frequency(const struct device * dev)262 static inline uint32_t z_impl_counter_get_frequency(const struct device *dev)
263 {
264 	const struct counter_config_info *config =
265 			(const struct counter_config_info *)dev->config;
266 	const struct counter_driver_api *api =
267 				(struct counter_driver_api *)dev->api;
268 
269 	return api->get_freq ? api->get_freq(dev) : config->freq;
270 }
271 
272 /**
273  * @brief Function to convert microseconds to ticks.
274  *
275  * @param[in]  dev    Pointer to the device structure for the driver instance.
276  * @param[in]  us     Microseconds.
277  *
278  * @return Converted ticks. Ticks will be saturated if exceed 32 bits.
279  */
280 __syscall uint32_t counter_us_to_ticks(const struct device *dev, uint64_t us);
281 
z_impl_counter_us_to_ticks(const struct device * dev,uint64_t us)282 static inline uint32_t z_impl_counter_us_to_ticks(const struct device *dev,
283 					       uint64_t us)
284 {
285 	uint64_t ticks = (us * z_impl_counter_get_frequency(dev)) / USEC_PER_SEC;
286 
287 	return (ticks > (uint64_t)UINT32_MAX) ? UINT32_MAX : ticks;
288 }
289 
290 /**
291  * @brief Function to convert ticks to microseconds.
292  *
293  * @param[in]  dev    Pointer to the device structure for the driver instance.
294  * @param[in]  ticks  Ticks.
295  *
296  * @return Converted microseconds.
297  */
298 __syscall uint64_t counter_ticks_to_us(const struct device *dev, uint32_t ticks);
299 
z_impl_counter_ticks_to_us(const struct device * dev,uint32_t ticks)300 static inline uint64_t z_impl_counter_ticks_to_us(const struct device *dev,
301 					       uint32_t ticks)
302 {
303 	return ((uint64_t)ticks * USEC_PER_SEC) / z_impl_counter_get_frequency(dev);
304 }
305 
306 /**
307  * @brief Function to retrieve maximum top value that can be set.
308  *
309  * @param[in]  dev    Pointer to the device structure for the driver instance.
310  *
311  * @return Max top value.
312  */
313 __syscall uint32_t counter_get_max_top_value(const struct device *dev);
314 
z_impl_counter_get_max_top_value(const struct device * dev)315 static inline uint32_t z_impl_counter_get_max_top_value(const struct device *dev)
316 {
317 	const struct counter_config_info *config =
318 			(const struct counter_config_info *)dev->config;
319 
320 	return config->max_top_value;
321 }
322 
323 /**
324  * @brief Start counter device in free running mode.
325  *
326  * @param dev Pointer to the device structure for the driver instance.
327  *
328  * @retval 0 If successful.
329  * @retval Negative errno code if failure.
330  */
331 __syscall int counter_start(const struct device *dev);
332 
z_impl_counter_start(const struct device * dev)333 static inline int z_impl_counter_start(const struct device *dev)
334 {
335 	const struct counter_driver_api *api =
336 				(struct counter_driver_api *)dev->api;
337 
338 	return api->start(dev);
339 }
340 
341 /**
342  * @brief Stop counter device.
343  *
344  * @param dev Pointer to the device structure for the driver instance.
345  *
346  * @retval 0 If successful.
347  * @retval -ENOTSUP if the device doesn't support stopping the
348  *                        counter.
349  */
350 __syscall int counter_stop(const struct device *dev);
351 
z_impl_counter_stop(const struct device * dev)352 static inline int z_impl_counter_stop(const struct device *dev)
353 {
354 	const struct counter_driver_api *api =
355 				(struct counter_driver_api *)dev->api;
356 
357 	return api->stop(dev);
358 }
359 
360 /**
361  * @brief Get current counter value.
362  * @param dev Pointer to the device structure for the driver instance.
363  * @param ticks Pointer to where to store the current counter value
364  *
365  * @retval 0 If successful.
366  * @retval Negative error code on failure getting the counter value
367  */
368 __syscall int counter_get_value(const struct device *dev, uint32_t *ticks);
369 
z_impl_counter_get_value(const struct device * dev,uint32_t * ticks)370 static inline int z_impl_counter_get_value(const struct device *dev,
371 					   uint32_t *ticks)
372 {
373 	const struct counter_driver_api *api =
374 				(struct counter_driver_api *)dev->api;
375 
376 	return api->get_value(dev, ticks);
377 }
378 
379 /**
380  * @brief Get current counter 64-bit value.
381  * @param dev Pointer to the device structure for the driver instance.
382  * @param ticks Pointer to where to store the current counter value
383  *
384  * @retval 0 If successful.
385  * @retval Negative error code on failure getting the counter value
386  */
387 __syscall int counter_get_value_64(const struct device *dev, uint64_t *ticks);
388 
z_impl_counter_get_value_64(const struct device * dev,uint64_t * ticks)389 static inline int z_impl_counter_get_value_64(const struct device *dev,
390 					   uint64_t *ticks)
391 {
392 	const struct counter_driver_api *api =
393 				(struct counter_driver_api *)dev->api;
394 
395 	if (!api->get_value_64) {
396 		return -ENOTSUP;
397 	}
398 
399 	return api->get_value_64(dev, ticks);
400 }
401 
402 /**
403  * @brief Set a single shot alarm on a channel.
404  *
405  * After expiration alarm can be set again, disabling is not needed. When alarm
406  * expiration handler is called, channel is considered available and can be
407  * set again in that context.
408  *
409  * @note API is not thread safe.
410  *
411  * @param dev		Pointer to the device structure for the driver instance.
412  * @param chan_id	Channel ID.
413  * @param alarm_cfg	Alarm configuration.
414  *
415  * @retval 0 If successful.
416  * @retval -ENOTSUP if request is not supported (device does not support
417  *		    interrupts or requested channel).
418  * @retval -EINVAL if alarm settings are invalid.
419  * @retval -ETIME  if absolute alarm was set too late.
420  * @retval -EBUSY  if alarm is already active.
421  */
422 __syscall int counter_set_channel_alarm(const struct device *dev,
423 					uint8_t chan_id,
424 					const struct counter_alarm_cfg *alarm_cfg);
425 
z_impl_counter_set_channel_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)426 static inline int z_impl_counter_set_channel_alarm(const struct device *dev,
427 						   uint8_t chan_id,
428 						   const struct counter_alarm_cfg *alarm_cfg)
429 {
430 	const struct counter_driver_api *api =
431 				(struct counter_driver_api *)dev->api;
432 
433 	if (chan_id >= counter_get_num_of_channels(dev)) {
434 		return -ENOTSUP;
435 	}
436 
437 	return api->set_alarm(dev, chan_id, alarm_cfg);
438 }
439 
440 /**
441  * @brief Cancel an alarm on a channel.
442  *
443  * @note API is not thread safe.
444  *
445  * @param dev		Pointer to the device structure for the driver instance.
446  * @param chan_id	Channel ID.
447  *
448  * @retval 0 If successful.
449  * @retval -ENOTSUP if request is not supported or the counter was not started
450  *		    yet.
451  */
452 __syscall int counter_cancel_channel_alarm(const struct device *dev,
453 					   uint8_t chan_id);
454 
z_impl_counter_cancel_channel_alarm(const struct device * dev,uint8_t chan_id)455 static inline int z_impl_counter_cancel_channel_alarm(const struct device *dev,
456 						      uint8_t chan_id)
457 {
458 	const struct counter_driver_api *api =
459 				(struct counter_driver_api *)dev->api;
460 
461 	if (chan_id >= counter_get_num_of_channels(dev)) {
462 		return -ENOTSUP;
463 	}
464 
465 	return api->cancel_alarm(dev, chan_id);
466 }
467 
468 /**
469  * @brief Set counter top value.
470  *
471  * Function sets top value and optionally resets the counter to 0 or top value
472  * depending on counter direction. On turnaround, counter can be reset and
473  * optional callback is periodically called. Top value can only be changed when
474  * there is no active channel alarm.
475  *
476  * @ref COUNTER_TOP_CFG_DONT_RESET prevents counter reset. When counter is
477  * running while top value is updated, it is possible that counter progresses
478  * outside the new top value. In that case, error is returned and optionally
479  * driver can reset the counter (see @ref COUNTER_TOP_CFG_RESET_WHEN_LATE).
480  *
481  * @param dev		Pointer to the device structure for the driver instance.
482  * @param cfg		Configuration. Cannot be NULL.
483  *
484  * @retval 0 If successful.
485  * @retval -ENOTSUP if request is not supported (e.g. top value cannot be
486  *		    changed or counter cannot/must be reset during top value
487 		    update).
488  * @retval -EBUSY if any alarm is active.
489  * @retval -ETIME if @ref COUNTER_TOP_CFG_DONT_RESET was set and new top value
490  *		  is smaller than current counter value (counter counting up).
491  */
492 __syscall int counter_set_top_value(const struct device *dev,
493 				    const struct counter_top_cfg *cfg);
494 
z_impl_counter_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)495 static inline int z_impl_counter_set_top_value(const struct device *dev,
496 					       const struct counter_top_cfg
497 					       *cfg)
498 {
499 	const struct counter_driver_api *api =
500 				(struct counter_driver_api *)dev->api;
501 
502 	if (cfg->ticks > counter_get_max_top_value(dev)) {
503 		return -EINVAL;
504 	}
505 
506 	return api->set_top_value(dev, cfg);
507 }
508 
509 /**
510  * @brief Function to get pending interrupts
511  *
512  * The purpose of this function is to return the interrupt
513  * status register for the device.
514  * This is especially useful when waking up from
515  * low power states to check the wake up source.
516  *
517  * @param dev Pointer to the device structure for the driver instance.
518  *
519  * @retval 1 if any counter interrupt is pending.
520  * @retval 0 if no counter interrupt is pending.
521  */
522 __syscall int counter_get_pending_int(const struct device *dev);
523 
z_impl_counter_get_pending_int(const struct device * dev)524 static inline int z_impl_counter_get_pending_int(const struct device *dev)
525 {
526 	const struct counter_driver_api *api =
527 				(struct counter_driver_api *)dev->api;
528 
529 	return api->get_pending_int(dev);
530 }
531 
532 /**
533  * @brief Function to retrieve current top value.
534  *
535  * @param[in]  dev    Pointer to the device structure for the driver instance.
536  *
537  * @return Top value.
538  */
539 __syscall uint32_t counter_get_top_value(const struct device *dev);
540 
z_impl_counter_get_top_value(const struct device * dev)541 static inline uint32_t z_impl_counter_get_top_value(const struct device *dev)
542 {
543 	const struct counter_driver_api *api =
544 				(struct counter_driver_api *)dev->api;
545 
546 	return api->get_top_value(dev);
547 }
548 
549 /**
550  * @brief Set guard period in counter ticks.
551  *
552  * When setting an absolute alarm value close to the current counter value there
553  * is a risk that the counter will have counted past the given absolute value
554  * before the driver manages to activate the alarm. If this would go unnoticed
555  * then the alarm would only expire after the timer has wrapped and reached the
556  * given absolute value again after a full timer period. This could take a long
557  * time in case of a 32 bit timer. Setting a sufficiently large guard period will
558  * help the driver detect unambiguously whether it is late or not.
559  *
560  * The guard period should be as many counter ticks as the driver will need at
561  * most to actually activate the alarm after the driver API has been called. If
562  * the driver finds that the counter has just passed beyond the given absolute
563  * tick value but is still close enough to fall within the guard period, it will
564  * assume that it is "late", i.e. that the intended expiry time has already passed.
565  * Depending on the @ref COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE flag the driver will
566  * either ignore the alarm or expire it immediately in such a case.
567  *
568  * If, however, the counter is past the given absolute tick value but outside
569  * the guard period, then the driver will assume that this is intentional and
570  * let the counter wrap around to/from zero before it expires.
571  *
572  * More precisely:
573  *
574  * - When counting upwards (see @ref COUNTER_CONFIG_INFO_COUNT_UP) the given
575  *   absolute tick value must be above (now + guard_period) % top_value to be
576  *   accepted by the driver.
577  * - When counting downwards, the given absolute tick value must be less than
578  *   (now + top_value - guard_period) % top_value to be accepted.
579  *
580  * Examples:
581  *
582  * - counting upwards, now = 4950, top value = 5000, guard period = 100:
583  *      absolute tick value >= (4950 + 100) % 5000 = 50
584  * - counting downwards, now = 50, top value = 5000, guard period = 100:
585  *      absolute tick value <= (50 + 5000 - * 100) % 5000 = 4950
586  *
587  * If you need only short alarm periods, you can set the guard period very high
588  * (e.g. half of the counter top value) which will make it highly unlikely that
589  * the counter will ever unintentionally wrap.
590  *
591  * The guard period is set to 0 on initialization (no protection).
592  *
593  * @param dev		Pointer to the device structure for the driver instance.
594  * @param ticks		Guard period in counter ticks.
595  * @param flags		See @ref COUNTER_GUARD_PERIOD_FLAGS.
596  *
597  * @retval 0 if successful.
598  * @retval -ENOTSUP if function or flags are not supported.
599  * @retval -EINVAL if ticks value is invalid.
600  */
601 __syscall int counter_set_guard_period(const struct device *dev,
602 					uint32_t ticks,
603 					uint32_t flags);
604 
z_impl_counter_set_guard_period(const struct device * dev,uint32_t ticks,uint32_t flags)605 static inline int z_impl_counter_set_guard_period(const struct device *dev,
606 						   uint32_t ticks, uint32_t flags)
607 {
608 	const struct counter_driver_api *api =
609 				(struct counter_driver_api *)dev->api;
610 
611 	if (!api->set_guard_period) {
612 		return -ENOTSUP;
613 	}
614 
615 	return api->set_guard_period(dev, ticks, flags);
616 }
617 
618 /**
619  * @brief Return guard period.
620  *
621  * See @ref counter_set_guard_period.
622  *
623  * @param dev	Pointer to the device structure for the driver instance.
624  * @param flags	See @ref COUNTER_GUARD_PERIOD_FLAGS.
625  *
626  * @return Guard period given in counter ticks or 0 if function or flags are
627  *	   not supported.
628  */
629 __syscall uint32_t counter_get_guard_period(const struct device *dev,
630 					    uint32_t flags);
631 
z_impl_counter_get_guard_period(const struct device * dev,uint32_t flags)632 static inline uint32_t z_impl_counter_get_guard_period(const struct device *dev,
633 							uint32_t flags)
634 {
635 	const struct counter_driver_api *api =
636 				(struct counter_driver_api *)dev->api;
637 
638 	return (api->get_guard_period) ? api->get_guard_period(dev, flags) : 0;
639 }
640 
641 #ifdef __cplusplus
642 }
643 #endif
644 
645 /**
646  * @}
647  */
648 
649 #include <syscalls/counter.h>
650 
651 #endif /* ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_ */
652