1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
9 
10 #include <zephyr/drivers/ptp_clock.h>
11 #include <zephyr/net/gptp.h>
12 
13 #include "gptp_messages.h"
14 #include "gptp_data_set.h"
15 
16 #include "net_private.h"
17 
18 static sys_slist_t phase_dis_callbacks;
19 
gptp_register_phase_dis_cb(struct gptp_phase_dis_cb * phase_dis,gptp_phase_dis_callback_t cb)20 void gptp_register_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis,
21 				gptp_phase_dis_callback_t cb)
22 {
23 	sys_slist_find_and_remove(&phase_dis_callbacks, &phase_dis->node);
24 	sys_slist_prepend(&phase_dis_callbacks, &phase_dis->node);
25 
26 	phase_dis->cb = cb;
27 }
28 
gptp_unregister_phase_dis_cb(struct gptp_phase_dis_cb * phase_dis)29 void gptp_unregister_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis)
30 {
31 	sys_slist_find_and_remove(&phase_dis_callbacks, &phase_dis->node);
32 }
33 
gptp_call_phase_dis_cb(void)34 void gptp_call_phase_dis_cb(void)
35 {
36 	struct gptp_global_ds *global_ds;
37 	sys_snode_t *sn, *sns;
38 	uint8_t *gm_id;
39 
40 	global_ds = GPTP_GLOBAL_DS();
41 	gm_id = &global_ds->gm_priority.root_system_id.grand_master_id[0];
42 
43 	SYS_SLIST_FOR_EACH_NODE_SAFE(&phase_dis_callbacks, sn, sns) {
44 		struct gptp_phase_dis_cb *phase_dis =
45 			CONTAINER_OF(sn, struct gptp_phase_dis_cb, node);
46 
47 		phase_dis->cb(gm_id,
48 			      &global_ds->gm_time_base_indicator,
49 			      &global_ds->clk_src_last_gm_phase_change,
50 			      &global_ds->clk_src_last_gm_freq_change);
51 	}
52 }
53 
gptp_event_capture(struct net_ptp_time * slave_time,bool * gm_present)54 int gptp_event_capture(struct net_ptp_time *slave_time, bool *gm_present)
55 {
56 	int port, key;
57 	const struct device *clk;
58 
59 	key = irq_lock();
60 	*gm_present =  GPTP_GLOBAL_DS()->gm_present;
61 
62 	for (port = GPTP_PORT_START; port <= GPTP_PORT_END; port++) {
63 		/* Get first available clock, or slave clock if GM present. */
64 		if (!*gm_present || (GPTP_GLOBAL_DS()->selected_role[port] ==
65 				     GPTP_PORT_SLAVE)) {
66 			clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
67 			if (clk) {
68 				ptp_clock_get(clk, slave_time);
69 				irq_unlock(key);
70 				return 0;
71 			}
72 		}
73 	}
74 
75 	irq_unlock(key);
76 	return -EAGAIN;
77 }
78 
gptp_sprint_clock_id(const uint8_t * clk_id,char * output,size_t output_len)79 char *gptp_sprint_clock_id(const uint8_t *clk_id, char *output, size_t output_len)
80 {
81 	return net_sprint_ll_addr_buf(clk_id, 8, output, output_len);
82 }
83 
gptp_clk_src_time_invoke(struct gptp_clk_src_time_invoke_params * arg)84 void gptp_clk_src_time_invoke(struct gptp_clk_src_time_invoke_params *arg)
85 {
86 	struct gptp_clk_master_sync_rcv_state *state;
87 
88 	state = &GPTP_STATE()->clk_master_sync_receive;
89 
90 	memcpy(&state->rcvd_clk_src_req, arg,
91 	       sizeof(struct gptp_clk_src_time_invoke_params));
92 
93 	state->rcvd_clock_source_req = true;
94 }
95