Skip to content

Commit 7e9ed6e

Browse files
yangbolu1991nashif
authored andcommitted
drivers: ethernet: dsa_nxp_imx_netc: support PTP timestamping
Supported PTP timestamping. Now only gPTP was supported. Signed-off-by: Yangbo Lu <[email protected]>
1 parent 600443a commit 7e9ed6e

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

drivers/ethernet/dsa/dsa_nxp_imx_netc.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
LOG_MODULE_REGISTER(dsa_netc, CONFIG_ETHERNET_LOG_LEVEL);
99

1010
#include <zephyr/net/dsa_core.h>
11+
#include <zephyr/net/dsa_tag_netc.h>
1112
#include <zephyr/drivers/pinctrl.h>
1213
#include <zephyr/drivers/ethernet/nxp_imx_netc.h>
1314
#include <zephyr/dt-bindings/ethernet/dsa_tag_proto.h>
@@ -37,10 +38,18 @@ struct dsa_netc_data {
3738
swt_config_t swt_config;
3839
swt_handle_t swt_handle;
3940
netc_cmd_bd_t *cmd_bd;
41+
#ifdef CONFIG_NET_L2_PTP
42+
uint8_t cpu_port_idx;
43+
struct k_fifo tx_ts_queue;
44+
#endif
4045
};
4146

4247
static int dsa_netc_port_init(const struct device *dev)
4348
{
49+
#ifdef CONFIG_NET_L2_PTP
50+
struct net_if *iface = net_if_lookup_by_dev(dev);
51+
struct ethernet_context *eth_ctx = net_if_l2_data(iface);
52+
#endif
4453
const struct dsa_port_config *cfg = dev->config;
4554
struct dsa_netc_port_config *prv_cfg = cfg->prv_config;
4655
struct dsa_switch_context *dsa_switch_ctx = dev->data;
@@ -67,6 +76,16 @@ static int dsa_netc_port_init(const struct device *dev)
6776
swt_config->bridgeCfg.dVFCfg.portMembership |= (1 << cfg->port_idx);
6877
swt_config->ports[cfg->port_idx].bridgeCfg.enMacStationMove = true;
6978

79+
#ifdef CONFIG_NET_L2_PTP
80+
/* Enable ingress port filter on user ports */
81+
if (eth_ctx->dsa_port == DSA_CPU_PORT) {
82+
prv->cpu_port_idx = cfg->port_idx;
83+
swt_config->ports[cfg->port_idx].commonCfg.ipfCfg.enIPFTable = false;
84+
} else {
85+
swt_config->ports[cfg->port_idx].commonCfg.ipfCfg.enIPFTable = true;
86+
}
87+
#endif
88+
7089
return 0;
7190
}
7291

@@ -79,6 +98,9 @@ static int dsa_netc_switch_setup(const struct dsa_switch_context *dsa_switch_ctx
7998
{
8099
struct dsa_netc_data *prv = PRV_DATA(dsa_switch_ctx);
81100
swt_config_t *swt_config = &prv->swt_config;
101+
#ifdef CONFIG_NET_L2_PTP
102+
uint32_t entry_id = 0;
103+
#endif
82104
status_t result;
83105

84106
swt_config->cmdRingUse = 1U;
@@ -90,6 +112,29 @@ static int dsa_netc_switch_setup(const struct dsa_switch_context *dsa_switch_ctx
90112
return -EIO;
91113
}
92114

115+
#ifdef CONFIG_NET_L2_PTP
116+
/*
117+
* For gPTP, switch should work as time-aware bridge.
118+
* Trap gPTP frames to cpu port to perform gPTP protocol.
119+
*/
120+
netc_tb_ipf_config_t ipf_entry_cfg = {
121+
.keye.etherType = htons(NET_ETH_PTYPE_PTP),
122+
.keye.etherTypeMask = 0xffff,
123+
.keye.srcPort = 0,
124+
.keye.srcPortMask = 0x0,
125+
.cfge.fltfa = kNETC_IPFRedirectToMgmtPort,
126+
.cfge.hr = kNETC_SoftwareDefHR0,
127+
.cfge.timecape = 1,
128+
.cfge.rrt = 1,
129+
};
130+
131+
result = SWT_RxIPFAddTableEntry(&prv->swt_handle, &ipf_entry_cfg, &entry_id);
132+
if ((result != kStatus_Success) || (entry_id == 0xFFFFFFFF)) {
133+
return -EIO;
134+
}
135+
136+
k_fifo_init(&prv->tx_ts_queue);
137+
#endif
93138
return 0;
94139
}
95140

@@ -118,6 +163,70 @@ static void dsa_netc_port_phylink_change(const struct device *phydev, struct phy
118163
}
119164
}
120165

166+
#ifdef CONFIG_NET_L2_PTP
167+
static int dsa_netc_port_txtstamp(const struct device *dev, struct net_pkt *pkt)
168+
{
169+
struct dsa_switch_context *dsa_switch_ctx = dev->data;
170+
struct dsa_netc_data *prv = PRV_DATA(dsa_switch_ctx);
171+
static uint8_t id = 1;
172+
173+
/* Utilize control block for timestamp request ID. */
174+
if (id == 16) {
175+
id = 0;
176+
}
177+
178+
pkt->cb.cb[0] = id;
179+
id++;
180+
181+
k_fifo_put(&prv->tx_ts_queue, pkt);
182+
net_pkt_ref(pkt);
183+
184+
return 0;
185+
}
186+
187+
static void dsa_netc_twostep_timestamp_handler(const struct dsa_switch_context *ctx,
188+
uint8_t ts_req_id, uint64_t ts)
189+
{
190+
struct dsa_netc_data *prv = PRV_DATA(ctx);
191+
struct net_pkt *pkt = k_fifo_get(&prv->tx_ts_queue, K_NO_WAIT);
192+
193+
while (pkt != NULL) {
194+
195+
/* Find the matched timestamp */
196+
if (pkt->cb.cb[0] == ts_req_id) {
197+
pkt->timestamp.nanosecond = ts % NSEC_PER_SEC;
198+
pkt->timestamp.second = ts / NSEC_PER_SEC;
199+
net_if_call_timestamp_cb(pkt);
200+
net_pkt_unref(pkt);
201+
return;
202+
/* Enqueue back */
203+
} else {
204+
k_fifo_put(&prv->tx_ts_queue, pkt);
205+
}
206+
207+
/* Try next */
208+
pkt = k_fifo_get(&prv->tx_ts_queue, K_NO_WAIT);
209+
}
210+
}
211+
#endif
212+
213+
static struct dsa_tag_netc_data dsa_netc_tag_data = {
214+
#ifdef CONFIG_NET_L2_PTP
215+
.twostep_timestamp_handler = dsa_netc_twostep_timestamp_handler,
216+
#endif
217+
};
218+
219+
static int dsa_netc_connect_tag_protocol(struct dsa_switch_context *dsa_switch_ctx,
220+
int tag_proto)
221+
{
222+
if (tag_proto == DSA_TAG_PROTO_NETC) {
223+
dsa_switch_ctx->tagger_data = (void *)(&dsa_netc_tag_data);
224+
return 0;
225+
}
226+
227+
return -EIO;
228+
}
229+
121230
static int dsa_netc_switch_init(const struct device *dev)
122231
{
123232
DEVICE_MMIO_NAMED_MAP(dev, base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP);
@@ -131,6 +240,10 @@ static struct dsa_api dsa_netc_api = {
131240
.port_generate_random_mac = dsa_netc_port_generate_random_mac,
132241
.switch_setup = dsa_netc_switch_setup,
133242
.port_phylink_change = dsa_netc_port_phylink_change,
243+
#ifdef CONFIG_NET_L2_PTP
244+
.port_txtstamp = dsa_netc_port_txtstamp,
245+
#endif
246+
.connect_tag_protocol = dsa_netc_connect_tag_protocol,
134247
};
135248

136249
#define DSA_NETC_PORT_INST_INIT(port, n) \
@@ -149,6 +262,8 @@ static struct dsa_api dsa_netc_api = {
149262
.phy_mode = DT_PROP_OR(port, phy_connection_type, ""), \
150263
.tag_proto = DT_PROP_OR(port, dsa_tag_protocol, DSA_TAG_PROTO_NOTAG), \
151264
.ethernet_connection = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(port, ethernet)), \
265+
IF_ENABLED(CONFIG_PTP_CLOCK_NXP_NETC, \
266+
(.ptp_clock = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(port, ptp_clock)),)) \
152267
.prv_config = &dsa_netc_##n##_##port##_config, \
153268
}; \
154269
DSA_PORT_INST_INIT(port, n, &dsa_##n##_##port##_config)

0 commit comments

Comments
 (0)