diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c index 8e8d4bf0b9e..32762582dce 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c @@ -12,6 +12,9 @@ LOG_MODULE_REGISTER(nxp_imx_eth); #include #include #include +#ifdef CONFIG_PTP_CLOCK_NXP_NETC +#include +#endif #include #include #include @@ -28,6 +31,44 @@ LOG_MODULE_REGISTER(nxp_imx_eth); const struct device *netc_dev_list[NETC_DRV_MAX_INST_SUPPORT]; +#ifdef CONFIG_PTP_CLOCK_NXP_NETC +static void netc_eth_pkt_get_timestamp(struct net_pkt *pkt, const struct device *ptp_clock, + uint32_t timestamp) +{ + struct net_ptp_time ptp_time = {0}; + uint64_t time_ns; + uint32_t time_h; + uint32_t time_l; + + /* + * Packet timestamp is lower 32-bit ns value. + * Need to reconstruct 64-bit ns value with ptp clock time. + */ + ptp_clock_get(ptp_clock, &ptp_time); + + time_ns = ptp_time.second * NSEC_PER_SEC + ptp_time.nanosecond; + time_h = time_ns >> 32; + time_l = time_ns & 0xffffffff; + + /* Check if wrap happened. */ + if (time_l <= timestamp) { + time_h--; + } + + time_ns = (uint64_t)time_h << 32 | timestamp; + + pkt->timestamp.nanosecond = time_ns % NSEC_PER_SEC; + pkt->timestamp.second = time_ns / NSEC_PER_SEC; +} + +const struct device *netc_eth_get_ptp_clock(const struct device *dev) +{ + const struct netc_eth_config *cfg = dev->config; + + return cfg->ptp_clock; +} +#endif + static int netc_eth_rx(const struct device *dev) { struct netc_eth_data *data = dev->data; @@ -85,6 +126,13 @@ static int netc_eth_rx(const struct device *dev) goto out; } +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + if (attr.isTsAvail) { + const struct netc_eth_config *cfg = dev->config; + + netc_eth_pkt_get_timestamp(pkt, cfg->ptp_clock, attr.timestamp); + } +#endif /* Send to upper layer */ ret = net_recv_data(iface_dst, pkt); if (ret < 0) { @@ -169,6 +217,10 @@ int netc_eth_init_common(const struct device *dev) config->bdr_init(&bdr_config, &rx_bdr_config, &tx_bdr_config); +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + bdr_config.rxBdrConfig[0].extendDescEn = true; +#endif + /* MSIX entry configuration */ msg_addr = MSGINTR_GetIntrSelectAddr(NETC_MSGINTR, NETC_MSGINTR_CHANNEL); msix_entry[NETC_TX_MSIX_ENTRY_IDX].control = kNETC_MsixIntrMaskBit; @@ -254,7 +306,10 @@ int netc_eth_tx(const struct device *dev, struct net_pkt *pkt) #endif status_t result; int ret; - + ep_tx_opt opt = {0}; +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + bool pkt_is_gptp; +#endif __ASSERT(pkt, "Packet pointer is NULL"); iface_dst = data->iface; @@ -274,6 +329,12 @@ int netc_eth_tx(const struct device *dev, struct net_pkt *pkt) k_mutex_lock(&data->tx_mutex, K_FOREVER); +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + pkt_is_gptp = ntohs(NET_ETH_HDR(pkt)->type) == NET_ETH_PTYPE_PTP; + if (pkt_is_gptp || net_pkt_is_tx_timestamping(pkt)) { + opt.flags |= kEP_TX_OPT_REQ_TS; + } +#endif /* Copy packet to tx buffer */ buff.length = (uint16_t)pkt_len; ret = net_pkt_read(pkt, buff.buffer, pkt_len); @@ -298,10 +359,10 @@ int netc_eth_tx(const struct device *dev, struct net_pkt *pkt) result = EP_SendFrameCommon(&data->handle, &data->handle.txBdRing[0], 0, &frame, NULL, &txDesc[0], data->handle.cfg.txCacheMaintain); } else { - result = EP_SendFrame(&data->handle, 0, &frame, NULL, NULL); + result = EP_SendFrame(&data->handle, 0, &frame, NULL, &opt); } #else - result = EP_SendFrame(&data->handle, 0, &frame, NULL, NULL); + result = EP_SendFrame(&data->handle, 0, &frame, NULL, &opt); #endif if (result != kStatus_Success) { LOG_ERR("Failed to tx frame"); @@ -314,7 +375,7 @@ int netc_eth_tx(const struct device *dev, struct net_pkt *pkt) do { frame_info = EP_ReclaimTxDescCommon(&data->handle, &data->handle.txBdRing[0], - 0, false); + 0, true); if (frame_info != NULL) { if (frame_info->status != kNETC_EPTxSuccess) { memset(frame_info, 0, sizeof(netc_tx_frame_info_t)); @@ -322,6 +383,14 @@ int netc_eth_tx(const struct device *dev, struct net_pkt *pkt) ret = -EIO; goto error; } + +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + if (frame_info->isTsAvail) { + netc_eth_pkt_get_timestamp(pkt, cfg->ptp_clock, + frame_info->timestamp); + net_if_add_tx_timestamp(pkt); + } +#endif memset(frame_info, 0, sizeof(netc_tx_frame_info_t)); } } while (frame_info != NULL); @@ -345,6 +414,9 @@ enum ethernet_hw_caps netc_eth_get_capabilities(const struct device *dev) #if defined(CONFIG_NET_VLAN) | ETHERNET_HW_VLAN #endif +#if defined(CONFIG_PTP_CLOCK_NXP_NETC) + | ETHERNET_PTP +#endif #if defined(CONFIG_NET_PROMISCUOUS_MODE) | ETHERNET_PROMISC_MODE #endif diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h index f9f9c6419ea..157f7e61bae 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h @@ -92,6 +92,9 @@ struct netc_eth_config { const struct pinctrl_dev_config *pincfg; uint8_t tx_intr_msg_data; uint8_t rx_intr_msg_data; +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + const struct device *ptp_clock; +#endif }; typedef uint8_t rx_buffer_t[NETC_RX_RING_BUF_SIZE_ALIGN]; @@ -117,5 +120,7 @@ int netc_eth_tx(const struct device *dev, struct net_pkt *pkt); enum ethernet_hw_caps netc_eth_get_capabilities(const struct device *dev); int netc_eth_set_config(const struct device *dev, enum ethernet_config_type type, const struct ethernet_config *config); - +#ifdef CONFIG_PTP_CLOCK_NXP_NETC +const struct device *netc_eth_get_ptp_clock(const struct device *dev); +#endif #endif /* ZEPHYR_DRIVERS_ETHERNET_ETH_NXP_IMX_NETC_PRIV_H_ */ diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c index 30740d6cb1e..3dc10ae8724 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c @@ -128,6 +128,9 @@ static const struct ethernet_api netc_eth_api = {.iface_api.init = netc_eth_ifac .get_capabilities = netc_eth_get_capabilities, .get_phy = netc_eth_get_phy, .set_config = netc_eth_set_config, +#ifdef CONFIG_PTP_CLOCK_NXP_NETC + .get_ptp_clock = netc_eth_get_ptp_clock, +#endif .send = netc_eth_tx}; #define NETC_PSI_INSTANCE_DEFINE(n) \ @@ -199,6 +202,8 @@ static const struct ethernet_api netc_eth_api = {.iface_api.init = netc_eth_ifac .si_idx = (DT_INST_PROP(n, mac_index) << 8) | DT_INST_PROP(n, si_index), \ .tx_intr_msg_data = NETC_TX_INTR_MSG_DATA_START + n, \ .rx_intr_msg_data = NETC_RX_INTR_MSG_DATA_START + n, \ + IF_ENABLED(CONFIG_PTP_CLOCK_NXP_NETC, \ + (.ptp_clock = DEVICE_DT_GET(DT_INST_PHANDLE(n, ptp_clock)),)) \ }; \ ETH_NET_DEVICE_DT_INST_DEFINE(n, netc_eth_init, NULL, &netc_eth##n##_data, \ &netc_eth##n##_config, CONFIG_ETH_INIT_PRIORITY, \