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