1 /*
2  * Copyright (c) 2017 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public functions for the Precision Time Protocol Stack.
10  *
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_NET_GPTP_H_
14 #define ZEPHYR_INCLUDE_NET_GPTP_H_
15 
16 /**
17  * @brief generic Precision Time Protocol (gPTP) support
18  * @defgroup gptp gPTP support
19  * @since 1.13
20  * @version 0.1.0
21  * @ingroup networking
22  * @{
23  */
24 
25 #include <zephyr/net/net_core.h>
26 #include <zephyr/net/ptp_time.h>
27 #include <stdbool.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /** @cond INTERNAL_HIDDEN */
34 
35 #define GPTP_OFFSET_SCALED_LOG_VAR_UNKNOWN 0x436A
36 
37 #define GPTP_PRIORITY1_NON_GM_CAPABLE      255
38 #define GPTP_PRIORITY1_GM_CAPABLE          248
39 
40 #if defined(CONFIG_NET_GPTP_BMCA_PRIORITY2)
41 #define GPTP_PRIORITY2_DEFAULT             CONFIG_NET_GPTP_BMCA_PRIORITY2
42 #else
43 #define GPTP_PRIORITY2_DEFAULT             248
44 #endif
45 
46 /** @endcond */
47 
48 /**
49  * @brief Scaled Nanoseconds.
50  */
51 struct gptp_scaled_ns {
52 	/** High half. */
53 	int32_t high;
54 
55 	/** Low half. */
56 	int64_t low;
57 } __packed;
58 
59 /**
60  * @brief UScaled Nanoseconds.
61  */
62 struct gptp_uscaled_ns {
63 	/** High half. */
64 	uint32_t high;
65 
66 	/** Low half. */
67 	uint64_t low;
68 } __packed;
69 
70 /** @cond INTERNAL_HIDDEN */
71 
72 #if defined(CONFIG_NEWLIB_LIBC)
73 #include <math.h>
74 
75 #define GPTP_POW2(exp) pow(2, exp)
76 #else
77 
gptp_pow2(int exp)78 static inline double gptp_pow2(int exp)
79 {
80 	double res;
81 
82 	if (exp >= 0) {
83 		res = 1 << exp;
84 	} else {
85 		res = 1.0;
86 
87 		while (exp++) {
88 			res /= 2;
89 		}
90 	}
91 
92 	return res;
93 }
94 
95 #define GPTP_POW2(exp) gptp_pow2(exp)
96 #endif
97 
98 /* Pre-calculated constants */
99 /* 2^16 */
100 #define GPTP_POW2_16	65536.0
101 /* 2^41 */
102 #define GPTP_POW2_41	2199023255552.0
103 
104 /* Message types. Event messages have BIT(3) set to 0, and general messages
105  * have that bit set to 1. IEEE 802.1AS chapter 10.5.2.2.2
106  */
107 #define GPTP_SYNC_MESSAGE                0x00
108 #define GPTP_DELAY_REQ_MESSAGE           0x01
109 #define GPTP_PATH_DELAY_REQ_MESSAGE      0x02
110 #define GPTP_PATH_DELAY_RESP_MESSAGE     0x03
111 #define GPTP_FOLLOWUP_MESSAGE            0x08
112 #define GPTP_DELAY_RESP_MESSAGE          0x09
113 #define GPTP_PATH_DELAY_FOLLOWUP_MESSAGE 0x0a
114 #define GPTP_ANNOUNCE_MESSAGE            0x0b
115 #define GPTP_SIGNALING_MESSAGE           0x0c
116 #define GPTP_MANAGEMENT_MESSAGE          0x0d
117 
118 #define GPTP_IS_EVENT_MSG(msg_type)      (!((msg_type) & BIT(3)))
119 
120 #define GPTP_CLOCK_ID_LEN                8
121 
122 /** @endcond */
123 
124 /**
125  * @brief Port Identity.
126  */
127 struct gptp_port_identity {
128 	/** Clock identity of the port. */
129 	uint8_t clk_id[GPTP_CLOCK_ID_LEN];
130 
131 	/** Number of the port. */
132 	uint16_t port_number;
133 } __packed;
134 
135 /** gPTP message flags */
136 struct gptp_flags {
137 	union {
138 		/** Byte access. */
139 		uint8_t octets[2];
140 
141 		/** Whole field access. */
142 		uint16_t all;
143 	};
144 } __packed;
145 
146 /** gPTP message header */
147 struct gptp_hdr {
148 	/** Type of the message. */
149 	uint8_t message_type:4;
150 
151 	/** Transport specific, always 1. */
152 	uint8_t transport_specific:4;
153 
154 	/** Version of the PTP, always 2. */
155 	uint8_t ptp_version:4;
156 
157 	/** Reserved field. */
158 	uint8_t reserved0:4;
159 
160 	/** Total length of the message from the header to the last TLV. */
161 	uint16_t message_length;
162 
163 	/** Domain number, always 0. */
164 	uint8_t domain_number;
165 
166 	/** Reserved field. */
167 	uint8_t reserved1;
168 
169 	/** Message flags. */
170 	struct gptp_flags flags;
171 
172 	/** Correction Field. The content depends of the message type. */
173 	int64_t correction_field;
174 
175 	/** Reserved field. */
176 	uint32_t reserved2;
177 
178 	/** Port Identity of the sender. */
179 	struct gptp_port_identity port_id;
180 
181 	/** Sequence Id. */
182 	uint16_t sequence_id;
183 
184 	/** Control value. Sync: 0, Follow-up: 2, Others: 5. */
185 	uint8_t control;
186 
187 	/** Message Interval in Log2 for Sync and Announce messages. */
188 	int8_t log_msg_interval;
189 } __packed;
190 
191 /** @cond INTERNAL_HIDDEN */
192 
193 #define GPTP_GET_CURRENT_TIME_USCALED_NS(port, uscaled_ns_ptr)		\
194 	do {								\
195 		(uscaled_ns_ptr)->low =					\
196 			gptp_get_current_time_nanosecond(port) << 16;	\
197 		(uscaled_ns_ptr)->high = 0;				\
198 	} while (false)
199 
200 /** @endcond */
201 
202 /**
203  * @typedef gptp_phase_dis_callback_t
204  * @brief Define callback that is called after a phase discontinuity has been
205  *        sent by the grandmaster.
206  * @param gm_identity A pointer to first element of a ClockIdentity array.
207  *        The size of the array is GPTP_CLOCK_ID_LEN.
208  * @param time_base A pointer to the value of timeBaseIndicator of the current
209  *        grandmaster.
210  * @param last_gm_ph_change A pointer to the value of lastGmPhaseChange received
211  *        from grandmaster.
212  * @param last_gm_freq_change A pointer to the value of lastGmFreqChange
213  *        received from the grandmaster.
214  */
215 typedef void (*gptp_phase_dis_callback_t)(
216 	uint8_t *gm_identity,
217 	uint16_t *time_base,
218 	struct gptp_scaled_ns *last_gm_ph_change,
219 	double *last_gm_freq_change);
220 
221 /**
222  * @brief Phase discontinuity callback structure.
223  *
224  * Stores the phase discontinuity callback information. Caller must make sure
225  * that the variable pointed by this is valid during the lifetime of
226  * registration. Typically this means that the variable cannot be
227  * allocated from stack.
228  */
229 struct gptp_phase_dis_cb {
230 	/** Node information for the slist. */
231 	sys_snode_t node;
232 
233 	/** Phase discontinuity callback. */
234 	gptp_phase_dis_callback_t cb;
235 };
236 
237 /**
238  * @brief ClockSourceTime.invoke function parameters
239  *
240  * Parameters passed by ClockSourceTime.invoke function.
241  */
242 struct gptp_clk_src_time_invoke_params {
243 	/** Frequency change on the last Time Base Indicator Change. */
244 	double last_gm_freq_change;
245 
246 	/** The time this function is invoked. */
247 	struct net_ptp_extended_time src_time;
248 
249 	/** Phase change on the last Time Base Indicator Change. */
250 	struct gptp_scaled_ns last_gm_phase_change;
251 
252 	/** Time Base - changed only if Phase or Frequency changes. */
253 	uint16_t time_base_indicator;
254 };
255 
256 /**
257  * @brief Register a phase discontinuity callback.
258  *
259  * @param phase_dis Caller specified handler for the callback.
260  * @param cb Callback to register.
261  */
262 void gptp_register_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis,
263 				gptp_phase_dis_callback_t cb);
264 
265 /**
266  * @brief Unregister a phase discontinuity callback.
267  *
268  * @param phase_dis Caller specified handler for the callback.
269  */
270 void gptp_unregister_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis);
271 
272 /**
273  * @brief Call a phase discontinuity callback function.
274  */
275 void gptp_call_phase_dis_cb(void);
276 
277 /**
278  * @brief Get gPTP time.
279  *
280  * @param slave_time A pointer to structure where timestamp will be saved.
281  * @param gm_present A pointer to a boolean where status of the
282  *        presence of a grand master will be saved.
283  *
284  * @return Error code. 0 if no error.
285  */
286 int gptp_event_capture(struct net_ptp_time *slave_time, bool *gm_present);
287 
288 /**
289  * @brief Utility function to print clock id to a user supplied buffer.
290  *
291  * @param clk_id Clock id
292  * @param output Output buffer
293  * @param output_len Output buffer len
294  *
295  * @return Pointer to output buffer
296  */
297 char *gptp_sprint_clock_id(const uint8_t *clk_id, char *output,
298 			   size_t output_len);
299 
300 /**
301  * @typedef gptp_port_cb_t
302  * @brief Callback used while iterating over gPTP ports
303  *
304  * @param port Port number
305  * @param iface Pointer to network interface
306  * @param user_data A valid pointer to user data or NULL
307  */
308 typedef void (*gptp_port_cb_t)(int port, struct net_if *iface,
309 			       void *user_data);
310 
311 /**
312  * @brief Go through all the gPTP ports and call callback for each of them.
313  *
314  * @param cb User-supplied callback function to call
315  * @param user_data User specified data
316  */
317 void gptp_foreach_port(gptp_port_cb_t cb, void *user_data);
318 
319 /**
320  * @brief Get gPTP domain.
321  * @details This contains all the configuration / status of the gPTP domain.
322  *
323  * @return Pointer to domain or NULL if not found.
324  */
325 struct gptp_domain *gptp_get_domain(void);
326 
327 /**
328  * @brief This interface is used by the ClockSource entity to provide time to
329  *        the ClockMaster entity of a time-aware system.
330  *
331  * @param arg Current state and parameters of the ClockSource entity.
332  */
333 void gptp_clk_src_time_invoke(struct gptp_clk_src_time_invoke_params *arg);
334 
335 /**
336  * @brief Return pointer to gPTP packet header in network packet.
337  *
338  * @param pkt Network packet (received or sent)
339  *
340  * @return Pointer to gPTP header.
341  */
342 struct gptp_hdr *gptp_get_hdr(struct net_pkt *pkt);
343 
344 #ifdef __cplusplus
345 }
346 #endif
347 
348 /**
349  * @}
350  */
351 
352 #endif /* ZEPHYR_INCLUDE_NET_GPTP_H_ */
353