1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_PTPC_DRV_H
9 #define HPM_PTPC_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_ptpc_regs.h"
13
14 /**
15 * @brief PTPC driver
16 * @defgroup ptpc_interface PTPC driver APIs
17 * @ingroup timer_interfaces Timers
18 * @{
19 */
20
21 #define PTPC_EVENT_COMPARE0_MASK PTPC_INT_STS_COMP_INT_STS0_MASK
22 #define PTPC_EVENT_CAPTURE0_MASK PTPC_INT_STS_CAPTURE_INT_STS0_MASK
23 #define PTPC_EVENT_PPS0_MASK PTPC_INT_STS_PPS_INT_STS0_MASK
24 #define PTPC_EVENT_COMPARE1_MASK PTPC_INT_STS_COMP_INT_STS1_MASK
25 #define PTPC_EVENT_CAPTURE1_MASK PTPC_INT_STS_CAPTURE_INT_STS1_MASK
26 #define PTPC_EVENT_PPS1_MASK PTPC_INT_STS_PPS_INT_STS1_MASK
27
28 #define PTPC_MAX_NS_COUNTER (0x3B9ACA00UL)
29
30 /**
31 * @brief Counter types
32 */
33 typedef enum ptpc_ns_counter_rollover_type {
34 ptpc_ns_counter_rollover_binary = 0, /**< binary mode, resolution ~0.466ns, overflow at 0x7FFFFFFF */
35 ptpc_ns_counter_rollover_digital = 1, /**< digital mode, resolution 1ns, overflow at 0x3B9ACA00 */
36 } ptpc_ns_counter_rollover_type_t;
37
38 /**
39 * @brief Capture trigger types
40 */
41 typedef enum ptpc_capture_trigger_type {
42 ptpc_capture_trigger_none = 0,
43 ptpc_capture_trigger_on_rising_edge = PTPC_PTPC_CTRL0_CAPT_SNAP_POS_EN_MASK,
44 ptpc_capture_trigger_on_failing_edge = PTPC_PTPC_CTRL0_CAPT_SNAP_NEG_EN_MASK,
45 ptpc_capture_trigger_on_both_edges = PTPC_PTPC_CTRL0_CAPT_SNAP_POS_EN_MASK
46 | PTPC_PTPC_CTRL0_CAPT_SNAP_NEG_EN_MASK,
47 } ptpc_capture_trigger_type_t;
48
49 /**
50 * @brief Capture trigger types
51 */
52 typedef enum ptpc_counting_mode {
53 ptpc_counting_increment = 0, /**< Increment the counter */
54 ptpc_counting_decrement = 1, /**< Decrement the counter */
55 } ptpc_counting_mode;
56
57 /**
58 * @brief Timer config
59 */
60 typedef struct {
61 ptpc_capture_trigger_type_t capture_trigger; /**< Capture trigger */
62 ptpc_ns_counter_rollover_type_t ns_rollover_mode; /**< Ns rollover mode */
63 bool coarse_increment; /**< Set false to use fine increment */
64 bool capture_keep; /**< Keep captured timer counter */
65 uint32_t src_frequency; /**< Source frequency */
66 } ptpc_config_t;
67
68 #ifdef __cplusplus
69 extern "C" {
70 #endif
71
72 /**
73 * @brief Configure ns counter rollover mode
74 *
75 * @param[in] ptr PTPC base address
76 * @param[in] index Index of target counter
77 * @param[in] rollover Rollover type
78 */
ptpc_set_ns_counter_rollover(PTPC_Type * ptr,uint8_t index,ptpc_ns_counter_rollover_type_t rollover)79 static inline void ptpc_set_ns_counter_rollover(PTPC_Type *ptr, uint8_t index,
80 ptpc_ns_counter_rollover_type_t rollover)
81 {
82 ptr->PTPC[index].CTRL0 = (ptr->PTPC[index].CTRL0 & ~PTPC_PTPC_CTRL0_SUBSEC_DIGITAL_ROLLOVER_MASK)
83 | PTPC_PTPC_CTRL0_SUBSEC_DIGITAL_ROLLOVER_SET(rollover);
84 }
85
86 /**
87 * @brief Enable capture keep
88 *
89 * @param[in] ptr PTPC base address
90 * @param[in] index Target index
91 */
ptpc_enable_capture_keep(PTPC_Type * ptr,uint8_t index)92 static inline void ptpc_enable_capture_keep(PTPC_Type *ptr, uint8_t index)
93 {
94 ptr->PTPC[index].CTRL0 |= PTPC_PTPC_CTRL0_CAPT_SNAP_KEEP_MASK;
95 }
96
97 /**
98 * @brief Disable capture keep
99 *
100 * @param[in] ptr PTPC base address
101 * @param[in] index Target index
102 */
ptpc_disable_capture_keep(PTPC_Type * ptr,uint8_t index)103 static inline void ptpc_disable_capture_keep(PTPC_Type *ptr, uint8_t index)
104 {
105 ptr->PTPC[index].CTRL0 &= ~PTPC_PTPC_CTRL0_CAPT_SNAP_KEEP_MASK;
106 }
107
108 /**
109 * @brief Update ns counter update type
110 *
111 * @param[in] ptr PTPC base address
112 * @param[in] index Index of target counter
113 * @param[in] coarse_update Counter will be increment by 1 on
114 */
ptpc_set_ns_counter_update_type(PTPC_Type * ptr,uint8_t index,bool coarse_update)115 static inline void ptpc_set_ns_counter_update_type(PTPC_Type *ptr, uint8_t index, bool coarse_update)
116 {
117 ptr->PTPC[index].CTRL0 = (ptr->PTPC[index].CTRL0 & ~PTPC_PTPC_CTRL0_FINE_COARSE_SEL_MASK)
118 | PTPC_PTPC_CTRL0_FINE_COARSE_SEL_SET(coarse_update);
119 }
120
121 /**
122 * @brief Set ns counter increment step
123 *
124 * @param[in] ptr PTPC base address
125 * @param[in] index Target index
126 * @param[in] ns_step Increment step
127 */
ptpc_set_ns_counter_step(PTPC_Type * ptr,uint8_t index,uint32_t ns_step)128 static inline void ptpc_set_ns_counter_step(PTPC_Type *ptr, uint8_t index, uint32_t ns_step)
129 {
130 ptr->PTPC[index].CTRL1 = PTPC_PTPC_CTRL1_SS_INCR_SET(ns_step);
131 }
132
133 /**
134 * @brief Set Second portion update value
135 *
136 * @param[in] ptr PTPC base address
137 * @param[in] index Target index
138 * @param[in] sec Second value
139 */
ptpc_set_second_update(PTPC_Type * ptr,uint8_t index,uint32_t sec)140 static inline void ptpc_set_second_update(PTPC_Type *ptr, uint8_t index, uint32_t sec)
141 {
142 ptr->PTPC[index].TS_UPDTH = PTPC_PTPC_TS_UPDTH_SEC_UPDATE_SET(sec);
143 }
144
145 /**
146 * @brief Set ns portion update value
147 *
148 * @param[in] ptr PTPC base address
149 * @param[in] index Target index
150 * @param[in] ns Ns value (31 bits, 0x3B9ACA00 max)
151 * @param[in] mode Counting mode
152 *
153 * @return status_success if everything is okay
154 */
155 hpm_stat_t ptpc_set_ns_update(PTPC_Type *ptr, uint8_t index, uint32_t ns, ptpc_counting_mode mode);
156
157 /**
158 * @brief Get current timestamp Second portion
159 *
160 * @param[in] ptr PTPC base address
161 * @param[in] index Target index
162 *
163 * @return Seconds value
164 */
ptpc_get_timestamp_second(PTPC_Type * ptr,uint8_t index)165 static inline uint32_t ptpc_get_timestamp_second(PTPC_Type *ptr, uint8_t index)
166 {
167 return PTPC_PTPC_TIMEH_TIMESTAMP_HIGH_GET(ptr->PTPC[index].TIMEH);
168 }
169
170 /**
171 * @brief Get timestamp ns portion
172 *
173 * @param[in] ptr PTPC base address
174 * @param[in] index Target index
175 *
176 * @return ns value
177 */
ptpc_get_timestamp_ns(PTPC_Type * ptr,uint8_t index)178 static inline uint32_t ptpc_get_timestamp_ns(PTPC_Type *ptr, uint8_t index)
179 {
180 return PTPC_PTPC_TIMEL_TIMESTAMP_LOW_GET(ptr->PTPC[index].TIMEL);
181 }
182
183 /**
184 * @brief Config compare
185 *
186 * @param[in] ptr PTPC base address
187 * @param[in] index Target index
188 * @param[in] sec Target second
189 * @param[in] ns Target ns
190 */
ptpc_config_compare(PTPC_Type * ptr,uint8_t index,uint32_t sec,uint32_t ns)191 static inline void ptpc_config_compare(PTPC_Type *ptr, uint8_t index, uint32_t sec, uint32_t ns)
192 {
193 ptr->PTPC[index].TARH = PTPC_PTPC_TARH_TARGET_TIME_HIGH_SET(sec);
194 ptr->PTPC[index].TARL = PTPC_PTPC_TARL_TARGET_TIME_LOW_SET(ns);
195 ptr->PTPC[index].CTRL0 |= PTPC_PTPC_CTRL0_COMP_EN_MASK;
196 }
197
198 /**
199 * @brief Update Second portion
200 *
201 * @param[in] ptr PTPC base address
202 * @param[in] index Target index
203 * @param[in] sec Target second
204 */
ptpc_update_timestamp_second(PTPC_Type * ptr,uint8_t index,uint32_t sec)205 static inline void ptpc_update_timestamp_second(PTPC_Type *ptr, uint8_t index, uint32_t sec)
206 {
207 ptr->PTPC[index].TS_UPDTH = PTPC_PTPC_TS_UPDTH_SEC_UPDATE_SET(sec);
208 }
209
210 /**
211 * @brief Update Ns portion
212 *
213 * @param[in] ptr PTPC base address
214 * @param[in] index Target index
215 * @param[in] ns Target ns
216 * @param[in] mode Counting mode
217 */
ptpc_update_timestamp_ns(PTPC_Type * ptr,uint8_t index,uint32_t ns,ptpc_counting_mode mode)218 static inline void ptpc_update_timestamp_ns(PTPC_Type *ptr, uint8_t index, uint32_t ns, ptpc_counting_mode mode)
219 {
220 ptr->PTPC[index].TS_UPDTL = PTPC_PTPC_TS_UPDTL_NS_UPDATE_SET(ns) | PTPC_PTPC_TS_UPDTL_ADD_SUB_SET(mode);
221 }
222
223 /**
224 * @brief Enable timer
225 *
226 * @param[in] ptr PTPC base address
227 * @param[in] index Target index
228 */
ptpc_enable_timer(PTPC_Type * ptr,uint8_t index)229 static inline void ptpc_enable_timer(PTPC_Type *ptr, uint8_t index)
230 {
231 ptr->PTPC[index].CTRL0 |= PTPC_PTPC_CTRL0_TIMER_ENABLE_MASK;
232 }
233
234 /**
235 * @brief Disable timer
236 *
237 * @param[in] ptr PTPC base address
238 * @param[in] index Target index
239 */
ptpc_disable_timer(PTPC_Type * ptr,uint8_t index)240 static inline void ptpc_disable_timer(PTPC_Type *ptr, uint8_t index)
241 {
242 ptr->PTPC[index].CTRL0 &= ~PTPC_PTPC_CTRL0_TIMER_ENABLE_MASK;
243 }
244
245 /**
246 * @brief Config capture trigger event
247 *
248 * @param[in] ptr PTPC base address
249 * @param[in] index Target index
250 * @param[in] trigger Capture trigger type
251 */
ptpc_config_capture(PTPC_Type * ptr,uint8_t index,ptpc_capture_trigger_type_t trigger)252 static inline void ptpc_config_capture(PTPC_Type *ptr, uint8_t index,
253 ptpc_capture_trigger_type_t trigger)
254 {
255 ptr->PTPC[index].CTRL0 = (ptr->PTPC[index].CTRL0 & ~(PTPC_PTPC_CTRL0_CAPT_SNAP_POS_EN_MASK
256 | PTPC_PTPC_CTRL0_CAPT_SNAP_NEG_EN_MASK)) | trigger;
257 }
258
259 /**
260 * @brief Get snapped ns value
261 *
262 * @param[in] ptr PTPC base address
263 * @param[in] index Target index
264 *
265 * @return ns portion on capture
266 */
ptpc_get_capture_ns(PTPC_Type * ptr,uint8_t index)267 static inline uint32_t ptpc_get_capture_ns(PTPC_Type *ptr, uint8_t index)
268 {
269 return PTPC_PTPC_CAPT_SNAPL_CAPT_SNAP_LOW_GET(ptr->PTPC[index].CAPT_SNAPL);
270 }
271
272 /**
273 * @brief Get captured second
274 *
275 * @param[in] ptr PTPC base address
276 * @param[in] index Target index
277 *
278 * @return second portion on capture
279 */
ptpc_get_capture_second(PTPC_Type * ptr,uint8_t index)280 static inline uint32_t ptpc_get_capture_second(PTPC_Type *ptr, uint8_t index)
281 {
282 return PTPC_PTPC_CAPT_SNAPH_CAPT_SNAP_HIGH_GET(ptr->PTPC[index].CAPT_SNAPH);
283 }
284
285 /**
286 * @brief Clear interrupt status
287 *
288 * @param[in] ptr PTPC base address
289 * @param[in] mask Mask of interrupts to be cleared
290 */
ptpc_clear_irq_status(PTPC_Type * ptr,uint32_t mask)291 static inline void ptpc_clear_irq_status(PTPC_Type *ptr, uint32_t mask)
292 {
293 ptr->INT_STS = mask;
294 }
295
296 /**
297 * @brief Get interrupt status
298 *
299 * @param[in] ptr PTPC base address
300 *
301 * @return interrupt status mask
302 */
ptpc_get_irq_status(PTPC_Type * ptr)303 static inline uint32_t ptpc_get_irq_status(PTPC_Type *ptr)
304 {
305 return ptr->INT_STS;
306 }
307
308 /**
309 * @brief Disable interrupt with mask
310 *
311 * @param[in] ptr PTPC base address
312 * @param[in] mask Mask of interrupts to be disabled
313 */
ptpc_irq_disable(PTPC_Type * ptr,uint32_t mask)314 static inline void ptpc_irq_disable(PTPC_Type *ptr, uint32_t mask)
315 {
316 ptr->INT_EN &= ~mask;
317 }
318
319 /**
320 * @brief Enable interrupt with mask
321 *
322 * @param[in] ptr PTPC base address
323 * @param[in] mask Mask of interrupts to be enabled
324 */
ptpc_irq_enable(PTPC_Type * ptr,uint32_t mask)325 static inline void ptpc_irq_enable(PTPC_Type *ptr, uint32_t mask)
326 {
327 ptr->INT_EN |= mask;
328 }
329
330 /**
331 * @brief Initialize PTPC module
332 *
333 * @param[in] ptr PTPC base address
334 * @param[in] index Target index
335 * @param[in] config Pointer to configuration struct
336 *
337 * @return status_success if everything is okay
338 */
339 hpm_stat_t ptpc_init(PTPC_Type *ptr, uint8_t index, ptpc_config_t *config);
340
341 /**
342 * @brief Set PTPC output destination
343 *
344 * @param[in] ptr PTPC base address
345 * @param[in] can_index Target CAN instance
346 * @param[in] use_ptpc1 Use PTPC1 if set to true, otherwise PTPC0
347 *
348 * @return status_success if everything is okay
349 */
350 hpm_stat_t ptpc_set_timer_output(PTPC_Type *ptr, uint8_t can_index, bool use_ptpc1);
351
352 /**
353 * @brief Get default config
354 *
355 * @param[in] ptr PTPC base address
356 * @param[out] config Pointer of config struct
357 */
358 void ptpc_get_default_config(PTPC_Type *ptr, ptpc_config_t *config);
359
360 /**
361 * @brief Initialize timer to count from 0
362 *
363 * @param[in] ptr PTPC base address
364 * @param[in] index Target index
365 *
366 */
367 void ptpc_init_timer(PTPC_Type *ptr, uint8_t index);
368
369 /**
370 * @brief Initialize timer with initial values
371 *
372 * @param[in] ptr PTPC base address
373 * @param[in] index Target index
374 * @param[in] sec Seconds
375 * @param[in] ns Ns
376 * @param[in] mode Counting mode
377 *
378 * @return status_success if everything is okay
379 */
380 hpm_stat_t ptpc_init_timer_with_initial(PTPC_Type *ptr, uint8_t index, uint32_t sec, uint32_t ns, ptpc_counting_mode mode);
381
382 /**
383 * @brief Update timestamp counter
384 *
385 * @param[in] ptr PTPC base address
386 * @param[in] index Target index
387 * @param[in] sec Seconds
388 * @param[in] ns Ns
389 * @param[in] mode Counting mode
390 * @return status_success if everything is okay
391 */
392 hpm_stat_t ptpc_update_timer(PTPC_Type *ptr, uint8_t index, uint32_t sec, uint32_t ns, ptpc_counting_mode mode);
393
394 /**
395 * @brief Set period of pulse generated per second
396 *
397 * @param[in] ptr PTPC base address
398 * @param[in] index Target index
399 * @param[in] p (2^power Hz, from [0 - 15])
400 *
401 * @return true if requested frequency can be set
402 * @return false if requested frequency can not be set
403 */
404 hpm_stat_t ptpc_set_pps(PTPC_Type *ptr, uint8_t index, uint8_t p);
405
406 #ifdef __cplusplus
407 }
408 #endif
409 /**
410 * @}
411 */
412
413 #endif /* HPM_PTPC_DRV_H */
414