1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define HAL_TICKER_CNTR_CLK_UNIT_FSEC 30517578125UL
8 #define HAL_TICKER_FSEC_PER_USEC      1000000000UL
9 #define HAL_TICKER_PSEC_PER_USEC      1000000UL
10 #define HAL_TICKER_FSEC_PER_PSEC      1000UL
11 
12 /* Macro defining the minimum counter compare offset */
13 #define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3
14 
15 /* Macro defining the max. counter update latency in ticks */
16 #define HAL_TICKER_CNTR_SET_LATENCY 0
17 
18 /* Macro defines the h/w supported most significant bit */
19 #define HAL_TICKER_CNTR_MSBIT 23
20 
21 /* Macro defining the HW supported counter bits */
22 #define HAL_TICKER_CNTR_MASK 0x00FFFFFF
23 
24 /* Macro to translate microseconds to tick units.
25  * NOTE: This returns the floor value.
26  */
27 #define HAL_TICKER_US_TO_TICKS(x) \
28 	( \
29 		((uint32_t)(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) / \
30 			    HAL_TICKER_CNTR_CLK_UNIT_FSEC)) & \
31 		HAL_TICKER_CNTR_MASK \
32 	)
33 
34 /* Macro to translate microseconds to tick units.
35  * NOTE: This returns the ceil value.
36  */
37 #define HAL_TICKER_US_TO_TICKS_CEIL(x) \
38 	( \
39 		DIV_ROUND_UP(((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC), \
40 			     HAL_TICKER_CNTR_CLK_UNIT_FSEC) & \
41 		HAL_TICKER_CNTR_MASK \
42 	)
43 
44 /* Macro to translate tick units to microseconds. */
45 #define HAL_TICKER_TICKS_TO_US(x) \
46 	( \
47 		((uint32_t)(((uint64_t)(x) * HAL_TICKER_CNTR_CLK_UNIT_FSEC) / \
48 		 HAL_TICKER_FSEC_PER_USEC)) \
49 	)
50 
51 /* Macro returning remainder in picoseconds (to fit in 32-bits) */
52 #define HAL_TICKER_REMAINDER(x) \
53 	( \
54 		( \
55 			((uint64_t) (x) * HAL_TICKER_FSEC_PER_USEC) \
56 			- ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * \
57 			   HAL_TICKER_CNTR_CLK_UNIT_FSEC) \
58 		) \
59 		/ HAL_TICKER_FSEC_PER_PSEC \
60 	)
61 
62 /* Macro defining the remainder resolution/range
63  * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1)
64  */
65 #define HAL_TICKER_REMAINDER_RANGE \
66 	HAL_TICKER_TICKS_TO_US(HAL_TICKER_PSEC_PER_USEC)
67 
68 /* Macro defining the margin for positioning re-scheduled nodes */
69 #define HAL_TICKER_RESCHEDULE_MARGIN \
70 	HAL_TICKER_US_TO_TICKS(150)
71 
72 /* Remove ticks and return positive remainder value in microseconds */
hal_ticker_remove_jitter(uint32_t * ticks,uint32_t * remainder)73 static inline void hal_ticker_remove_jitter(uint32_t *ticks,
74 					    uint32_t *remainder)
75 {
76 	/* Is remainder less than 1 us */
77 	if ((*remainder & BIT(31)) || !(*remainder / HAL_TICKER_PSEC_PER_USEC)) {
78 		*ticks -= 1U;
79 		*remainder += HAL_TICKER_CNTR_CLK_UNIT_FSEC / HAL_TICKER_FSEC_PER_PSEC;
80 	}
81 
82 	/* pico seconds to micro seconds unit */
83 	*remainder /= HAL_TICKER_PSEC_PER_USEC;
84 }
85 
86 /* Add ticks and return positive remainder value in microseconds */
hal_ticker_add_jitter(uint32_t * ticks,uint32_t * remainder)87 static inline void hal_ticker_add_jitter(uint32_t *ticks, uint32_t *remainder)
88 {
89 	/* Is remainder less than 1 us */
90 	if ((*remainder & BIT(31)) || !(*remainder / HAL_TICKER_PSEC_PER_USEC)) {
91 		*ticks += 1U;
92 		*remainder += HAL_TICKER_CNTR_CLK_UNIT_FSEC / HAL_TICKER_FSEC_PER_PSEC;
93 	}
94 
95 	/* pico seconds to micro seconds unit */
96 	*remainder /= HAL_TICKER_PSEC_PER_USEC;
97 }
98