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