mirror of
https://github.com/fpganinja/taxi.git
synced 2026-02-27 21:45:09 -08:00
cndm: Add PTP support
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -28,6 +28,9 @@ SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
|
||||
XDC_FILES = ../fpga.xdc
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/ptp/syn/vivado/taxi_ptp_td_leaf.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/ptp/syn/vivado/taxi_ptp_td_phc_regs.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/ptp/syn/vivado/taxi_ptp_td_rel2tod.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
|
||||
XDC_FILES = ../fpga.xdc
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/ptp/syn/vivado/taxi_ptp_td_leaf.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/ptp/syn/vivado/taxi_ptp_td_phc_regs.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/ptp/syn/vivado/taxi_ptp_td_rel2tod.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
|
||||
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ module fpga #
|
||||
parameter string VENDOR = "XILINX",
|
||||
// device family
|
||||
parameter string FAMILY = "kintexuplus",
|
||||
// PTP configuration
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
// 10G/25G MAC configuration
|
||||
parameter logic CFG_LOW_LATENCY = 1'b1,
|
||||
parameter logic COMBINED_MAC_PCS = 1'b1,
|
||||
@@ -491,6 +493,7 @@ fpga_core #(
|
||||
.SIM(SIM),
|
||||
.VENDOR(VENDOR),
|
||||
.FAMILY(FAMILY),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
|
||||
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
|
||||
.MAC_DATA_W(MAC_DATA_W)
|
||||
|
||||
@@ -24,6 +24,8 @@ module fpga_core #
|
||||
// device family
|
||||
parameter string FAMILY = "kintexuplus",
|
||||
parameter RQ_SEQ_NUM_W = 6,
|
||||
// PTP configuration
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
// 10G/25G MAC configuration
|
||||
parameter logic CFG_LOW_LATENCY = 1'b1,
|
||||
parameter logic COMBINED_MAC_PCS = 1'b1,
|
||||
@@ -114,6 +116,9 @@ module fpga_core #
|
||||
output wire [7:0] cfg_interrupt_msi_function_number
|
||||
);
|
||||
|
||||
localparam logic PTP_TS_FMT_TOD = 1'b0;
|
||||
localparam PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 48;
|
||||
|
||||
// SFP+
|
||||
wire sfp_tx_clk[2];
|
||||
wire sfp_tx_rst[2];
|
||||
@@ -126,7 +131,7 @@ assign sfp_led[0] = !sfp_rx_status[0];
|
||||
assign sfp_led[1] = !sfp_rx_status[1];
|
||||
assign led = '1;
|
||||
assign led_r = 1'b1;
|
||||
assign led_g = 1'b1;
|
||||
// assign led_g = 1'b1;
|
||||
|
||||
localparam HB_COUNT = 62500000;
|
||||
localparam CL_HB_COUNT = $clog2(HB_COUNT);
|
||||
@@ -160,8 +165,8 @@ assign sfp_mgt_refclk_out = sfp_mgt_refclk_bufg;
|
||||
wire sfp_rst;
|
||||
|
||||
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp_tx[2]();
|
||||
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp_tx_cpl[2]();
|
||||
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp_rx[2]();
|
||||
taxi_axis_if #(.DATA_W(PTP_TS_W), .KEEP_W(1), .ID_W(8)) axis_sfp_tx_cpl[2]();
|
||||
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1+PTP_TS_W)) axis_sfp_rx[2]();
|
||||
taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(8)) axis_sfp_stat();
|
||||
|
||||
if (SIM) begin
|
||||
@@ -207,6 +212,15 @@ taxi_apb_if #(
|
||||
)
|
||||
gt_apb_ctrl();
|
||||
|
||||
wire ptp_clk = sfp_mgt_refclk_bufg;
|
||||
wire ptp_rst = sfp_rst;
|
||||
wire ptp_sample_clk = clk_125mhz;
|
||||
wire ptp_td_sd;
|
||||
wire ptp_pps;
|
||||
wire ptp_pps_str;
|
||||
|
||||
assign led_g = ptp_pps_str;
|
||||
|
||||
taxi_eth_mac_25g_us #(
|
||||
.SIM(SIM),
|
||||
.VENDOR(VENDOR),
|
||||
@@ -230,9 +244,11 @@ taxi_eth_mac_25g_us #(
|
||||
.PADDING_EN(1'b1),
|
||||
.DIC_EN(1'b1),
|
||||
.MIN_FRAME_LEN(64),
|
||||
.PTP_TS_EN(1'b0),
|
||||
.PTP_TS_FMT_TOD(1'b1),
|
||||
.PTP_TS_W(96),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
|
||||
.PTP_TS_W(PTP_TS_W),
|
||||
.PTP_TD_SDI_PIPELINE(2),
|
||||
.PRBS31_EN(1'b0),
|
||||
.TX_SERDES_PIPELINE(1),
|
||||
.RX_SERDES_PIPELINE(1),
|
||||
@@ -284,7 +300,6 @@ sfp_mac_inst (
|
||||
.tx_clk(sfp_tx_clk),
|
||||
.tx_rst_in('{2{1'b0}}),
|
||||
.tx_rst_out(sfp_tx_rst),
|
||||
.ptp_sample_clk('{2{1'b0}}),
|
||||
|
||||
/*
|
||||
* Transmit interface (AXI stream)
|
||||
@@ -300,10 +315,18 @@ sfp_mac_inst (
|
||||
/*
|
||||
* PTP clock
|
||||
*/
|
||||
.tx_ptp_ts('{2{'0}}),
|
||||
.tx_ptp_ts_step('{2{1'b0}}),
|
||||
.rx_ptp_ts('{2{'0}}),
|
||||
.rx_ptp_ts_step('{2{1'b0}}),
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_sample_clk(ptp_sample_clk),
|
||||
.ptp_td_sdi(ptp_td_sd),
|
||||
.tx_ptp_ts_in('{2{'0}}),
|
||||
.tx_ptp_ts_out(),
|
||||
.tx_ptp_ts_step_out(),
|
||||
.tx_ptp_locked(),
|
||||
.rx_ptp_ts_in('{2{'0}}),
|
||||
.rx_ptp_ts_out(),
|
||||
.rx_ptp_ts_step_out(),
|
||||
.rx_ptp_locked(),
|
||||
|
||||
/*
|
||||
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
|
||||
@@ -440,6 +463,9 @@ cndm_micro_pcie_us #(
|
||||
.VENDOR(VENDOR),
|
||||
.FAMILY(FAMILY),
|
||||
.PORTS(2),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_CLK_PER_NS_NUM(32),
|
||||
.PTP_CLK_PER_NS_DENOM(5),
|
||||
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
|
||||
.BAR0_APERTURE(24)
|
||||
)
|
||||
@@ -497,6 +523,23 @@ cndm_inst (
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_sample_clk(ptp_sample_clk),
|
||||
.ptp_td_sdo(ptp_td_sd),
|
||||
.ptp_pps(ptp_pps),
|
||||
.ptp_pps_str(ptp_pps_str),
|
||||
.ptp_sync_locked(),
|
||||
.ptp_sync_ts_rel(),
|
||||
.ptp_sync_ts_rel_step(),
|
||||
.ptp_sync_ts_tod(),
|
||||
.ptp_sync_ts_tod_step(),
|
||||
.ptp_sync_pps(),
|
||||
.ptp_sync_pps_str(),
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
||||
export PARAM_SIM := "1'b1"
|
||||
export PARAM_VENDOR := "\"XILINX\""
|
||||
export PARAM_FAMILY := "\"kintexuplus\""
|
||||
export PARAM_PTP_TS_EN := "1'b1"
|
||||
export PARAM_CFG_LOW_LATENCY := "1'b1"
|
||||
export PARAM_COMBINED_MAC_PCS := "1'b1"
|
||||
export PARAM_MAC_DATA_W := "64"
|
||||
|
||||
@@ -486,6 +486,7 @@ def test_fpga_core(request, mac_data_w):
|
||||
parameters['SIM'] = "1'b1"
|
||||
parameters['VENDOR'] = "\"XILINX\""
|
||||
parameters['FAMILY'] = "\"kintexuplus\""
|
||||
parameters['PTP_TS_EN'] = "1'b1"
|
||||
parameters['CFG_LOW_LATENCY'] = "1'b1"
|
||||
parameters['COMBINED_MAC_PCS'] = "1'b1"
|
||||
parameters['MAC_DATA_W'] = mac_data_w
|
||||
|
||||
@@ -26,6 +26,8 @@ module test_fpga_core #
|
||||
parameter AXIS_PCIE_RQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 62 : 137,
|
||||
parameter AXIS_PCIE_CQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 85 : 183,
|
||||
parameter AXIS_PCIE_CC_USER_W = AXIS_PCIE_DATA_W < 512 ? 33 : 81,
|
||||
// PTP configuration
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
// 10G/25G MAC configuration
|
||||
parameter logic CFG_LOW_LATENCY = 1'b1,
|
||||
parameter logic COMBINED_MAC_PCS = 1'b1,
|
||||
@@ -137,6 +139,8 @@ fpga_core #(
|
||||
.VENDOR(VENDOR),
|
||||
.FAMILY(FAMILY),
|
||||
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
|
||||
// PTP configuration
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
// 10G/25G MAC configuration
|
||||
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
|
||||
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
|
||||
|
||||
@@ -10,6 +10,7 @@ cndm-y += cndm_irq.o
|
||||
cndm-y += cndm_dev.o
|
||||
cndm-y += cndm_netdev.o
|
||||
cndm-y += cndm_ethtool.o
|
||||
cndm-y += cndm_ptp.o
|
||||
cndm-y += cndm_tx.o
|
||||
cndm-y += cndm_rx.o
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ Authors:
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
@@ -52,7 +53,7 @@ struct cndm_dev {
|
||||
u32 port_offset;
|
||||
u32 port_stride;
|
||||
|
||||
void __iomem *ptp_regs;
|
||||
void __iomem *phc_regs;
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_clock_info;
|
||||
};
|
||||
@@ -61,6 +62,7 @@ struct cndm_tx_info {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma_addr;
|
||||
u32 len;
|
||||
int ts_requested;
|
||||
};
|
||||
|
||||
struct cndm_rx_info {
|
||||
@@ -86,6 +88,10 @@ struct cndm_priv {
|
||||
struct cndm_irq *irq;
|
||||
struct notifier_block irq_nb;
|
||||
|
||||
struct hwtstamp_config hwts_config;
|
||||
u64 ts_s;
|
||||
u8 ts_valid;
|
||||
|
||||
struct cndm_tx_info *tx_info;
|
||||
struct cndm_rx_info *rx_info;
|
||||
|
||||
@@ -140,7 +146,9 @@ struct cndm_desc {
|
||||
struct cndm_cpl {
|
||||
__u8 rsvd[4];
|
||||
__le32 len;
|
||||
__u8 rsvd2[7];
|
||||
__le32 ts_ns;
|
||||
__le16 ts_fns;
|
||||
__u8 ts_s;
|
||||
__u8 phase;
|
||||
};
|
||||
|
||||
@@ -162,6 +170,11 @@ extern const struct file_operations cndm_fops;
|
||||
// cndm_ethtool.c
|
||||
extern const struct ethtool_ops cndm_ethtool_ops;
|
||||
|
||||
// cndm_ptp.c
|
||||
ktime_t cndm_read_cpl_ts(struct cndm_priv *priv, const struct cndm_cpl *cpl);
|
||||
void cndm_register_phc(struct cndm_dev *cdev);
|
||||
void cndm_unregister_phc(struct cndm_dev *cdev);
|
||||
|
||||
// cndm_tx.c
|
||||
int cndm_free_tx_buf(struct cndm_priv *priv);
|
||||
int cndm_poll_tx_cq(struct napi_struct *napi, int budget);
|
||||
|
||||
@@ -11,6 +11,7 @@ Authors:
|
||||
#include "cndm.h"
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
static void cndm_get_drvinfo(struct net_device *ndev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
@@ -24,6 +25,37 @@ static void cndm_get_drvinfo(struct net_device *ndev,
|
||||
strscpy(drvinfo->bus_info, dev_name(cdev->dev), sizeof(drvinfo->bus_info));
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
|
||||
static int cndm_get_ts_info(struct net_device *ndev,
|
||||
struct kernel_ethtool_ts_info *info)
|
||||
#else
|
||||
static int cndm_get_ts_info(struct net_device *ndev,
|
||||
struct ethtool_ts_info *info)
|
||||
#endif
|
||||
{
|
||||
struct cndm_priv *priv = netdev_priv(ndev);
|
||||
struct cndm_dev *cdev = priv->cdev;
|
||||
|
||||
ethtool_op_get_ts_info(ndev, info);
|
||||
|
||||
if (cdev->ptp_clock)
|
||||
info->phc_index = ptp_clock_index(cdev->ptp_clock);
|
||||
|
||||
// if (!(priv->if_features & cndm_IF_FEATURE_PTP_TS) || !cdev->ptp_clock)
|
||||
// return 0;
|
||||
|
||||
info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
|
||||
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
|
||||
|
||||
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ethtool_ops cndm_ethtool_ops = {
|
||||
.get_drvinfo = cndm_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_ts_info = cndm_get_ts_info,
|
||||
};
|
||||
|
||||
@@ -63,6 +63,8 @@ static int cndm_common_probe(struct cndm_dev *cdev)
|
||||
if (cdev->port_count > ARRAY_SIZE(cdev->ndev))
|
||||
cdev->port_count = ARRAY_SIZE(cdev->ndev);
|
||||
|
||||
cndm_register_phc(cdev);
|
||||
|
||||
for (k = 0; k < cdev->port_count; k++) {
|
||||
struct net_device *ndev;
|
||||
|
||||
@@ -113,6 +115,8 @@ static void cndm_common_remove(struct cndm_dev *cdev)
|
||||
}
|
||||
}
|
||||
|
||||
cndm_unregister_phc(cdev);
|
||||
|
||||
devlink_unregister(devlink);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,67 @@ static int cndm_close(struct net_device *ndev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cndm_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
|
||||
{
|
||||
struct cndm_priv *priv = netdev_priv(ndev);
|
||||
struct hwtstamp_config hwts_config;
|
||||
|
||||
if (copy_from_user(&hwts_config, ifr->ifr_data, sizeof(hwts_config)))
|
||||
return -EFAULT;
|
||||
|
||||
if (hwts_config.flags)
|
||||
return -EINVAL;
|
||||
|
||||
switch (hwts_config.tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
case HWTSTAMP_TX_ON:
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (hwts_config.rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
break;
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
case HWTSTAMP_FILTER_SOME:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_NTP_ALL:
|
||||
hwts_config.rx_filter = HWTSTAMP_FILTER_ALL;
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
memcpy(&priv->hwts_config, &hwts_config, sizeof(hwts_config));
|
||||
|
||||
if (copy_to_user(ifr->ifr_data, &hwts_config, sizeof(hwts_config)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cndm_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr)
|
||||
{
|
||||
struct cndm_priv *priv = netdev_priv(ndev);
|
||||
|
||||
if (copy_to_user(ifr->ifr_data, &priv->hwts_config, sizeof(priv->hwts_config)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cndm_set_mac(struct net_device *ndev, void *addr)
|
||||
{
|
||||
struct sockaddr *saddr = addr;
|
||||
@@ -70,12 +131,29 @@ static int cndm_set_mac(struct net_device *ndev, void *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cndm_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case SIOCSHWTSTAMP:
|
||||
return cndm_hwtstamp_set(ndev, ifr);
|
||||
case SIOCGHWTSTAMP:
|
||||
return cndm_hwtstamp_get(ndev, ifr);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct net_device_ops cndm_netdev_ops = {
|
||||
.ndo_open = cndm_open,
|
||||
.ndo_stop = cndm_close,
|
||||
.ndo_start_xmit = cndm_start_xmit,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_mac_address = cndm_set_mac,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
.ndo_eth_ioctl = cndm_ioctl,
|
||||
#else
|
||||
.ndo_do_ioctl = cndm_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int cndm_netdev_irq(struct notifier_block *nb, unsigned long action, void *data)
|
||||
@@ -124,6 +202,10 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __io
|
||||
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
priv->hwts_config.flags = 0;
|
||||
priv->hwts_config.tx_type = HWTSTAMP_TX_OFF;
|
||||
priv->hwts_config.rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
|
||||
ndev->netdev_ops = &cndm_netdev_ops;
|
||||
ndev->ethtool_ops = &cndm_ethtool_ops;
|
||||
|
||||
|
||||
192
src/cndm/modules/cndm/cndm_ptp.c
Normal file
192
src/cndm/modules/cndm/cndm_ptp.c
Normal file
@@ -0,0 +1,192 @@
|
||||
// SPDX-License-Identifier: GPL
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
#include "cndm.h"
|
||||
#include <linux/version.h>
|
||||
|
||||
ktime_t cndm_read_cpl_ts(struct cndm_priv *priv, const struct cndm_cpl *cpl)
|
||||
{
|
||||
struct cndm_dev *cdev = priv->cdev;
|
||||
|
||||
// u64 ts_s = le16_to_cpu(cpl->ts_s);
|
||||
u64 ts_s = cpl->ts_s;
|
||||
u32 ts_ns = le32_to_cpu(cpl->ts_ns);
|
||||
|
||||
if (unlikely(!priv->ts_valid || (priv->ts_s ^ ts_s) & 0xf0)) {
|
||||
// seconds MSBs do not match, update cached timestamp
|
||||
if (cdev->phc_regs) {
|
||||
priv->ts_s = ioread32(cdev->phc_regs + 0x18);
|
||||
priv->ts_s |= (u64) ioread32(cdev->phc_regs + 0x1C) << 32;
|
||||
priv->ts_valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ts_s |= priv->ts_s & 0xfffffffffffffff0;
|
||||
|
||||
return ktime_set(ts_s, ts_ns);
|
||||
}
|
||||
|
||||
static int cndm_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
{
|
||||
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
|
||||
|
||||
bool neg = false;
|
||||
u64 nom_per_fns, adj;
|
||||
|
||||
dev_dbg(cdev->dev, "%s: scaled_ppm: %ld", __func__, scaled_ppm);
|
||||
|
||||
if (scaled_ppm < 0) {
|
||||
neg = true;
|
||||
scaled_ppm = -scaled_ppm;
|
||||
}
|
||||
|
||||
nom_per_fns = ioread32(cdev->phc_regs + 0x70);
|
||||
nom_per_fns |= (u64) ioread32(cdev->phc_regs + 0x74) << 32;
|
||||
|
||||
if (nom_per_fns == 0)
|
||||
nom_per_fns = 0x4ULL << 32;
|
||||
|
||||
adj = div_u64(((nom_per_fns >> 16) * scaled_ppm) + 500000, 1000000);
|
||||
|
||||
if (neg)
|
||||
adj = nom_per_fns - adj;
|
||||
else
|
||||
adj = nom_per_fns + adj;
|
||||
|
||||
iowrite32(adj & 0xffffffff, cdev->phc_regs + 0x78);
|
||||
iowrite32(adj >> 32, cdev->phc_regs + 0x7C);
|
||||
|
||||
dev_dbg(cdev->dev, "%s adj: 0x%llx", __func__, adj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cndm_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
|
||||
{
|
||||
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
|
||||
|
||||
ioread32(cdev->phc_regs + 0x30);
|
||||
ts->tv_nsec = ioread32(cdev->phc_regs + 0x34);
|
||||
ts->tv_sec = ioread32(cdev->phc_regs + 0x38);
|
||||
ts->tv_sec |= (u64) ioread32(cdev->phc_regs + 0x3C) << 32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
||||
static int cndm_phc_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, struct ptp_system_timestamp *sts)
|
||||
{
|
||||
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
|
||||
|
||||
ptp_read_system_prets(sts);
|
||||
ioread32(cdev->phc_regs + 0x30);
|
||||
ptp_read_system_postts(sts);
|
||||
ts->tv_nsec = ioread32(cdev->phc_regs + 0x34);
|
||||
ts->tv_sec = ioread32(cdev->phc_regs + 0x38);
|
||||
ts->tv_sec |= (u64) ioread32(cdev->phc_regs + 0x3C) << 32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cndm_phc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)
|
||||
{
|
||||
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
|
||||
|
||||
iowrite32(ts->tv_nsec, cdev->phc_regs + 0x54);
|
||||
iowrite32(ts->tv_sec & 0xffffffff, cdev->phc_regs + 0x58);
|
||||
iowrite32(ts->tv_sec >> 32, cdev->phc_regs + 0x5C);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cndm_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
|
||||
struct timespec64 ts;
|
||||
|
||||
dev_dbg(cdev->dev, "%s: delta: %lld", __func__, delta);
|
||||
|
||||
if (delta > 536000000 || delta < -536000000) {
|
||||
// for a large delta, perform a non-precision step
|
||||
cndm_phc_gettime(ptp, &ts);
|
||||
ts = timespec64_add(ts, ns_to_timespec64(delta));
|
||||
cndm_phc_settime(ptp, &ts);
|
||||
} else {
|
||||
// for a small delta, perform a precision atomic offset
|
||||
iowrite32(delta & 0xffffffff, cdev->phc_regs + 0x50);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cndm_phc_set_from_system_clock(struct ptp_clock_info *ptp)
|
||||
{
|
||||
struct timespec64 ts;
|
||||
|
||||
#ifdef ktime_get_clocktai_ts64
|
||||
ktime_get_clocktai_ts64(&ts);
|
||||
#else
|
||||
ts = ktime_to_timespec64(ktime_get_clocktai());
|
||||
#endif
|
||||
|
||||
cndm_phc_settime(ptp, &ts);
|
||||
}
|
||||
|
||||
void cndm_register_phc(struct cndm_dev *cdev)
|
||||
{
|
||||
if (cdev->ptp_clock) {
|
||||
dev_warn(cdev->dev, "PTP clock already registered");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO
|
||||
if (cdev->port_offset == 0x10000) {
|
||||
dev_info(cdev->dev, "PTP clock not present");
|
||||
return;
|
||||
}
|
||||
|
||||
cdev->phc_regs = cdev->hw_addr + 0x10000; // TODO
|
||||
|
||||
cdev->ptp_clock_info.owner = THIS_MODULE;
|
||||
snprintf(cdev->ptp_clock_info.name, sizeof(cdev->ptp_clock_info.name), "%s_phc", cdev->name);
|
||||
cdev->ptp_clock_info.max_adj = 1000000000;
|
||||
cdev->ptp_clock_info.n_alarm = 0;
|
||||
cdev->ptp_clock_info.n_ext_ts = 0;
|
||||
cdev->ptp_clock_info.n_per_out = 0;
|
||||
cdev->ptp_clock_info.n_pins = 0;
|
||||
cdev->ptp_clock_info.pps = 0;
|
||||
cdev->ptp_clock_info.adjfine = cndm_phc_adjfine;
|
||||
cdev->ptp_clock_info.adjtime = cndm_phc_adjtime;
|
||||
cdev->ptp_clock_info.gettime64 = cndm_phc_gettime;
|
||||
cdev->ptp_clock_info.gettimex64 = cndm_phc_gettimex;
|
||||
cdev->ptp_clock_info.settime64 = cndm_phc_settime;
|
||||
|
||||
cdev->ptp_clock = ptp_clock_register(&cdev->ptp_clock_info, cdev->dev);
|
||||
|
||||
if (IS_ERR(cdev->ptp_clock)) {
|
||||
dev_err(cdev->dev, "failed to register PHC");
|
||||
cdev->ptp_clock = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
dev_info(cdev->dev, "registered PHC (index %d)", ptp_clock_index(cdev->ptp_clock));
|
||||
|
||||
cndm_phc_set_from_system_clock(&cdev->ptp_clock_info);
|
||||
}
|
||||
|
||||
void cndm_unregister_phc(struct cndm_dev *cdev)
|
||||
{
|
||||
if (cdev->ptp_clock) {
|
||||
ptp_clock_unregister(cdev->ptp_clock);
|
||||
cdev->ptp_clock = NULL;
|
||||
dev_info(cdev->dev, "unregistered PHC");
|
||||
}
|
||||
}
|
||||
@@ -143,15 +143,20 @@ static int cndm_process_rx_cq(struct net_device *ndev, int napi_budget)
|
||||
|
||||
if (len < ETH_HLEN) {
|
||||
netdev_warn(priv->ndev, "Dropping short frame (len %d)", len);
|
||||
__free_pages(page, 0);
|
||||
goto rx_drop;
|
||||
}
|
||||
|
||||
skb = napi_get_frags(&priv->rx_napi);
|
||||
if (!skb) {
|
||||
netdev_err(priv->ndev, "Failed to allocate skb %d", index);
|
||||
break;
|
||||
__free_pages(page, 0);
|
||||
goto rx_drop;
|
||||
}
|
||||
|
||||
// RX hardware timestamp
|
||||
skb_hwtstamps(skb)->hwtstamp = cndm_read_cpl_ts(priv, cpl);
|
||||
|
||||
__skb_fill_page_desc(skb, 0, page, 0, len);
|
||||
|
||||
skb_shinfo(skb)->nr_frags = 1;
|
||||
|
||||
@@ -43,7 +43,9 @@ int cndm_free_tx_buf(struct cndm_priv *priv)
|
||||
static int cndm_process_tx_cq(struct net_device *ndev, int napi_budget)
|
||||
{
|
||||
struct cndm_priv *priv = netdev_priv(ndev);
|
||||
struct cndm_tx_info *tx_info;
|
||||
struct cndm_cpl *cpl;
|
||||
struct skb_shared_hwtstamps hwts;
|
||||
int done = 0;
|
||||
|
||||
u32 cq_cons_ptr;
|
||||
@@ -64,6 +66,14 @@ static int cndm_process_tx_cq(struct net_device *ndev, int napi_budget)
|
||||
dma_rmb();
|
||||
|
||||
index = cons_ptr & priv->txq_mask;
|
||||
tx_info = &priv->tx_info[index];
|
||||
|
||||
// TX hardware timestamp
|
||||
if (unlikely(tx_info->ts_requested)) {
|
||||
netdev_dbg(priv->ndev, "%s: TX TS requested", __func__);
|
||||
hwts.hwtstamp = cndm_read_cpl_ts(priv, cpl);
|
||||
skb_tstamp_tx(tx_info->skb, &hwts);
|
||||
}
|
||||
|
||||
cndm_free_tx_desc(priv, index, napi_budget);
|
||||
|
||||
@@ -100,6 +110,7 @@ int cndm_poll_tx_cq(struct napi_struct *napi, int budget)
|
||||
|
||||
int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
{
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
struct cndm_priv *priv = netdev_priv(ndev);
|
||||
struct device *dev = priv->dev;
|
||||
u32 index;
|
||||
@@ -123,6 +134,14 @@ int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
tx_desc = (struct cndm_desc *)(priv->txq_region + index*16);
|
||||
tx_info = &priv->tx_info[index];
|
||||
|
||||
// TX hardware timestamp
|
||||
tx_info->ts_requested = 0;
|
||||
if (unlikely(shinfo->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||
netdev_dbg(ndev, "%s: TX TS requested", __func__);
|
||||
shinfo->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
tx_info->ts_requested = 1;
|
||||
}
|
||||
|
||||
len = skb_headlen(skb);
|
||||
|
||||
dma_addr = dma_map_single(dev, skb->data, len, DMA_TO_DEVICE);
|
||||
@@ -143,6 +162,8 @@ int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
|
||||
priv->txq_prod++;
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
|
||||
if (priv->txq_prod - priv->txq_cons >= 128) {
|
||||
netdev_dbg(ndev, "TX ring full");
|
||||
netif_tx_stop_queue(priv->tx_queue);
|
||||
|
||||
@@ -12,5 +12,5 @@ cndm_micro_cpl_wr.sv
|
||||
../lib/taxi/src/axis/rtl/taxi_axis_async_fifo.f
|
||||
../lib/taxi/src/axis/rtl/taxi_axis_arb_mux.f
|
||||
../lib/taxi/src/axis/rtl/taxi_axis_demux.sv
|
||||
../lib/taxi/src/ptp/rtl/taxi_ptp_td_phc.sv
|
||||
../lib/taxi/src/ptp/rtl/taxi_ptp_td_leaf.sv
|
||||
../lib/taxi/src/ptp/rtl/taxi_ptp_td_phc_axil.f
|
||||
../lib/taxi/src/ptp/rtl/taxi_ptp_td_rel2tod.sv
|
||||
|
||||
@@ -16,10 +16,11 @@ Authors:
|
||||
* Corundum-micro core logic
|
||||
*/
|
||||
module cndm_micro_core #(
|
||||
parameter PORTS = 2//,
|
||||
// parameter logic PTP_TS_EN = 1'b1,
|
||||
// parameter PTP_CLK_PER_NS_NUM = 512,
|
||||
// parameter PTP_CLK_PER_NS_DENOM = 165
|
||||
parameter PORTS = 2,
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b0,
|
||||
parameter PTP_CLK_PER_NS_NUM = 512,
|
||||
parameter PTP_CLK_PER_NS_DENOM = 165
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
@@ -46,19 +47,20 @@ module cndm_micro_core #(
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
// input wire logic ptp_clk = 1'b0,
|
||||
// input wire logic ptp_rst = 1'b0,
|
||||
// input wire logic ptp_sample_clk = 1'b0,
|
||||
// output wire logic ptp_td_sdo,
|
||||
// output wire logic ptp_pps,
|
||||
// output wire logic ptp_pps_str,
|
||||
// output wire logic ptp_sync_locked,
|
||||
// output wire logic [63:0] ptp_sync_ts_rel,
|
||||
// output wire logic ptp_sync_ts_rel_step,
|
||||
// output wire logic [95:0] ptp_sync_ts_tod,
|
||||
// output wire logic ptp_sync_ts_tod_step,
|
||||
// output wire logic ptp_sync_pps,
|
||||
// output wire logic ptp_sync_pps_str,
|
||||
input wire logic ptp_clk = 1'b0,
|
||||
input wire logic ptp_rst = 1'b0,
|
||||
input wire logic ptp_sample_clk = 1'b0,
|
||||
input wire logic ptp_td_sdi = 1'b0,
|
||||
output wire logic ptp_td_sdo,
|
||||
output wire logic ptp_pps,
|
||||
output wire logic ptp_pps_str,
|
||||
output wire logic ptp_sync_locked,
|
||||
output wire logic [63:0] ptp_sync_ts_rel,
|
||||
output wire logic ptp_sync_ts_rel_step,
|
||||
output wire logic [95:0] ptp_sync_ts_tod,
|
||||
output wire logic ptp_sync_ts_tod_step,
|
||||
output wire logic ptp_sync_pps,
|
||||
output wire logic ptp_sync_pps_str,
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
@@ -84,8 +86,7 @@ localparam RAM_SEG_DATA_W = dma_ram_wr.SEG_DATA_W;
|
||||
localparam RAM_SEG_BE_W = dma_ram_wr.SEG_BE_W;
|
||||
localparam RAM_SEL_W = dma_ram_wr.SEL_W;
|
||||
|
||||
localparam PORT_OFFSET = 1;
|
||||
// localparam PORT_OFFSET = PTP_TS_EN ? 2 : 1;
|
||||
localparam PORT_OFFSET = PTP_TS_EN ? 2 : 1;
|
||||
|
||||
taxi_axil_if #(
|
||||
.DATA_W(s_axil_wr.DATA_W),
|
||||
@@ -182,8 +183,7 @@ always_ff @(posedge clk) begin
|
||||
|
||||
case ({s_axil_ctrl[0].araddr[15:2], 2'b00})
|
||||
16'h0100: s_axil_rdata_reg <= PORTS; // port count
|
||||
16'h0104: s_axil_rdata_reg <= 32'h00010000; // port offset
|
||||
// 16'h0104: s_axil_rdata_reg <= PTP_TS_EN ? 32'h00020000 : 32'h00010000; // port offset
|
||||
16'h0104: s_axil_rdata_reg <= PTP_TS_EN ? 32'h00020000 : 32'h00010000; // port offset
|
||||
16'h0108: s_axil_rdata_reg <= 32'h00010000; // port stride
|
||||
default: begin end
|
||||
endcase
|
||||
@@ -199,47 +199,54 @@ always_ff @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// if (PTP_TS_EN) begin : ptp
|
||||
if (PTP_TS_EN) begin : ptp
|
||||
|
||||
// cndm_micro_ptp #(
|
||||
// .PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
|
||||
// .PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM)
|
||||
// )
|
||||
// ptp_inst (
|
||||
// .clk(clk),
|
||||
// .rst(rst),
|
||||
taxi_ptp_td_phc_axil #(
|
||||
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
|
||||
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM)
|
||||
)
|
||||
ptp_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
// /*
|
||||
// * Control register interface
|
||||
// */
|
||||
// .s_axil_wr(s_axil_ctrl[1]),
|
||||
// .s_axil_rd(s_axil_ctrl[1]),
|
||||
/*
|
||||
* Control register interface
|
||||
*/
|
||||
.s_axil_wr(s_axil_ctrl[1]),
|
||||
.s_axil_rd(s_axil_ctrl[1]),
|
||||
|
||||
// /*
|
||||
// * PTP
|
||||
// */
|
||||
// .ptp_clk(ptp_clk),
|
||||
// .ptp_rst(ptp_rst),
|
||||
// .ptp_sample_clk(ptp_sample_clk),
|
||||
// .ptp_td_sdo(ptp_td_sdo),
|
||||
// .ptp_pps(ptp_pps),
|
||||
// .ptp_pps_str(ptp_pps_str),
|
||||
// .ptp_sync_locked(ptp_sync_locked),
|
||||
// .ptp_sync_ts_rel(ptp_sync_ts_rel),
|
||||
// .ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
|
||||
// .ptp_sync_ts_tod(ptp_sync_ts_tod),
|
||||
// .ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
|
||||
// .ptp_sync_pps(ptp_sync_pps),
|
||||
// .ptp_sync_pps_str(ptp_sync_pps_str)
|
||||
// );
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_sample_clk(ptp_sample_clk),
|
||||
.ptp_td_sdo(ptp_td_sdo),
|
||||
.ptp_pps(ptp_pps),
|
||||
.ptp_pps_str(ptp_pps_str),
|
||||
.ptp_sync_locked(ptp_sync_locked),
|
||||
.ptp_sync_ts_rel(ptp_sync_ts_rel),
|
||||
.ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
|
||||
.ptp_sync_ts_tod(ptp_sync_ts_tod),
|
||||
.ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
|
||||
.ptp_sync_pps(ptp_sync_pps),
|
||||
.ptp_sync_pps_str(ptp_sync_pps_str)
|
||||
);
|
||||
|
||||
// end else begin : ptp
|
||||
end else begin : ptp
|
||||
|
||||
// assign ptp_td_sdo = 1'b0;
|
||||
// assign ptp_pps = 1'b0;
|
||||
// assign ptp_pps_str = 1'b0;
|
||||
assign ptp_td_sdo = 1'b0;
|
||||
assign ptp_pps = 1'b0;
|
||||
assign ptp_pps_str = 1'b0;
|
||||
assign ptp_sync_locked = 1'b0;
|
||||
assign ptp_sync_ts_rel = '0;
|
||||
assign ptp_sync_ts_rel_step = 1'b0;
|
||||
assign ptp_sync_ts_tod = '0;
|
||||
assign ptp_sync_ts_tod_step = 1'b0;
|
||||
assign ptp_sync_pps = 1'b0;
|
||||
assign ptp_sync_pps_str = 1'b0;
|
||||
|
||||
// end
|
||||
end
|
||||
|
||||
taxi_dma_desc_if #(
|
||||
.SRC_ADDR_W(dma_rd_desc_req.SRC_ADDR_W),
|
||||
@@ -325,7 +332,8 @@ dma_mux_inst (
|
||||
for (genvar p = 0; p < PORTS; p = p + 1) begin : port
|
||||
|
||||
cndm_micro_port #(
|
||||
// .PTP_TS_EN(PTP_TS_EN)
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD)
|
||||
)
|
||||
port_inst (
|
||||
.clk(clk),
|
||||
@@ -349,6 +357,13 @@ for (genvar p = 0; p < PORTS; p = p + 1) begin : port
|
||||
|
||||
.irq(irq[p]),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_td_sdi(ptp_td_sdo),
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,10 @@ module cndm_micro_pcie_us #(
|
||||
// device family
|
||||
parameter string FAMILY = "virtexuplus",
|
||||
parameter PORTS = 2,
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b0,
|
||||
parameter PTP_CLK_PER_NS_NUM = 512,
|
||||
parameter PTP_CLK_PER_NS_DENOM = 165,
|
||||
parameter RQ_SEQ_NUM_W = 6,
|
||||
parameter BAR0_APERTURE = 24
|
||||
)
|
||||
@@ -80,6 +84,24 @@ module cndm_micro_pcie_us #(
|
||||
output wire [7:0] cfg_interrupt_msi_tph_st_tag,
|
||||
output wire [7:0] cfg_interrupt_msi_function_number,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
input wire logic ptp_clk = 1'b0,
|
||||
input wire logic ptp_rst = 1'b0,
|
||||
input wire logic ptp_sample_clk = 1'b0,
|
||||
input wire logic ptp_td_sdi = 1'b0,
|
||||
output wire logic ptp_td_sdo,
|
||||
output wire logic ptp_pps,
|
||||
output wire logic ptp_pps_str,
|
||||
output wire logic ptp_sync_locked,
|
||||
output wire logic [63:0] ptp_sync_ts_rel,
|
||||
output wire logic ptp_sync_ts_rel_step,
|
||||
output wire logic [95:0] ptp_sync_ts_tod,
|
||||
output wire logic ptp_sync_ts_tod_step,
|
||||
output wire logic ptp_sync_pps,
|
||||
output wire logic ptp_sync_pps_str,
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
@@ -455,7 +477,11 @@ msi_inst (
|
||||
);
|
||||
|
||||
cndm_micro_core #(
|
||||
.PORTS(PORTS)
|
||||
.PORTS(PORTS),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
|
||||
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
|
||||
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM)
|
||||
)
|
||||
core_inst (
|
||||
.clk(pcie_clk),
|
||||
@@ -479,6 +505,24 @@ core_inst (
|
||||
|
||||
.irq(irq),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_sample_clk(ptp_sample_clk),
|
||||
.ptp_td_sdi(ptp_td_sdi),
|
||||
.ptp_td_sdo(ptp_td_sdo),
|
||||
.ptp_pps(ptp_pps),
|
||||
.ptp_pps_str(ptp_pps_str),
|
||||
.ptp_sync_locked(ptp_sync_locked),
|
||||
.ptp_sync_ts_rel(ptp_sync_ts_rel),
|
||||
.ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
|
||||
.ptp_sync_ts_tod(ptp_sync_ts_tod),
|
||||
.ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
|
||||
.ptp_sync_pps(ptp_sync_pps),
|
||||
.ptp_sync_pps_str(ptp_sync_pps_str),
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,8 @@ Authors:
|
||||
* Corundum-micro port module
|
||||
*/
|
||||
module cndm_micro_port #(
|
||||
parameter logic PTP_TS_EN = 1'b1
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b0
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
@@ -40,6 +41,13 @@ module cndm_micro_port #(
|
||||
|
||||
output wire logic irq,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
input wire logic ptp_clk = 1'b0,
|
||||
input wire logic ptp_rst = 1'b0,
|
||||
input wire logic ptp_td_sdi = 1'b0,
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
@@ -454,7 +462,7 @@ taxi_axis_if #(
|
||||
.KEEP_EN(mac_axis_tx_cpl.KEEP_EN),
|
||||
.KEEP_W(mac_axis_tx_cpl.KEEP_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
.USER_W(mac_axis_tx_cpl.USER_W)
|
||||
)
|
||||
mac_tx_cpl_int();
|
||||
|
||||
@@ -507,12 +515,20 @@ tx_cpl_fifo (
|
||||
);
|
||||
|
||||
cndm_micro_tx #(
|
||||
.PTP_TS_EN(PTP_TS_EN)
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD)
|
||||
)
|
||||
tx_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_td_sdi(ptp_td_sdi),
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
@@ -530,7 +546,7 @@ tx_inst (
|
||||
taxi_axis_if #(
|
||||
.DATA_W(mac_axis_rx.DATA_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
.USER_W(mac_axis_rx.USER_W)
|
||||
) mac_rx_int();
|
||||
|
||||
taxi_axis_async_fifo #(
|
||||
@@ -582,12 +598,20 @@ rx_fifo (
|
||||
);
|
||||
|
||||
cndm_micro_rx #(
|
||||
.PTP_TS_EN(PTP_TS_EN)
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD)
|
||||
)
|
||||
rx_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_td_sdi(ptp_td_sdi),
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
|
||||
@@ -16,12 +16,20 @@ Authors:
|
||||
* Corundum-micro receive datapath
|
||||
*/
|
||||
module cndm_micro_rx #(
|
||||
parameter logic PTP_TS_EN = 1'b1
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b0
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
input wire logic ptp_clk = 1'b0,
|
||||
input wire logic ptp_rst = 1'b0,
|
||||
input wire logic ptp_td_sdi = 1'b0,
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
@@ -50,7 +58,7 @@ taxi_dma_desc_if #(
|
||||
.ID_EN(0),
|
||||
.DEST_EN(0),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
.USER_W(rx_data.USER_W)
|
||||
) dma_desc();
|
||||
|
||||
localparam [2:0]
|
||||
@@ -65,6 +73,84 @@ logic desc_req_reg = 1'b0;
|
||||
|
||||
assign desc_req = desc_req_reg;
|
||||
|
||||
wire [95:0] rx_ptp_ts;
|
||||
wire rx_ptp_ts_valid;
|
||||
|
||||
if (PTP_TS_EN) begin
|
||||
|
||||
if (PTP_TS_FMT_TOD) begin
|
||||
|
||||
assign rx_ptp_ts = dma_desc.sts_user[dma_desc.USER_W-1:1];
|
||||
assign rx_ptp_ts_valid = dma_desc.sts_valid;
|
||||
|
||||
end else begin
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(48),
|
||||
.KEEP_EN(0),
|
||||
.KEEP_W(1),
|
||||
.STRB_EN(0),
|
||||
.LAST_EN(0),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(0),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) ptp_ts_rel();
|
||||
|
||||
assign ptp_ts_rel.tdata = dma_desc.sts_user[dma_desc.USER_W-1:1];
|
||||
assign ptp_ts_rel.tuser = dma_desc.sts_user[0];
|
||||
assign ptp_ts_rel.tvalid = dma_desc.sts_valid;
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(96),
|
||||
.KEEP_EN(0),
|
||||
.KEEP_W(1),
|
||||
.STRB_EN(0),
|
||||
.LAST_EN(0),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(0),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) ptp_ts_tod();
|
||||
|
||||
assign rx_ptp_ts = ptp_ts_tod.tdata;
|
||||
assign rx_ptp_ts_valid = ptp_ts_tod.tvalid;
|
||||
|
||||
taxi_ptp_td_rel2tod #(
|
||||
.TS_FNS_W(16),
|
||||
.TS_REL_NS_W(ptp_ts_rel.DATA_W-16),
|
||||
.TS_TOD_S_W(48),
|
||||
.TS_REL_W(ptp_ts_rel.DATA_W),
|
||||
.TS_TOD_W(96),
|
||||
.TD_SDI_PIPELINE(2)
|
||||
)
|
||||
rel2tod_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* PTP clock interface
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_td_sdi(ptp_td_sdi),
|
||||
|
||||
/*
|
||||
* Timestamp conversion
|
||||
*/
|
||||
.s_axis_ts_rel(ptp_ts_rel),
|
||||
.m_axis_ts_tod(ptp_ts_tod)
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
assign rx_ptp_ts = '0;
|
||||
assign rx_ptp_ts_valid = 1'b0;
|
||||
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
desc_req_reg <= 1'b0;
|
||||
|
||||
@@ -104,6 +190,12 @@ always_ff @(posedge clk) begin
|
||||
axis_cpl.tlast <= 1'b1;
|
||||
axis_cpl.tvalid <= axis_cpl.tvalid && !axis_cpl.tready;
|
||||
|
||||
if (rx_ptp_ts_valid) begin
|
||||
axis_cpl.tdata[127:112] <= rx_ptp_ts[63:48]; // sec
|
||||
axis_cpl.tdata[95:64] <= rx_ptp_ts[47:16]; // ns
|
||||
axis_cpl.tdata[111:96] <= rx_ptp_ts[15:0]; // fns
|
||||
end
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
dma_desc.req_valid <= 1'b1;
|
||||
|
||||
@@ -16,12 +16,20 @@ Authors:
|
||||
* Corundum-micro transmit datapath
|
||||
*/
|
||||
module cndm_micro_tx #(
|
||||
parameter logic PTP_TS_EN = 1'b1
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b0
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
input wire logic ptp_clk = 1'b0,
|
||||
input wire logic ptp_rst = 1'b0,
|
||||
input wire logic ptp_td_sdi = 1'b0,
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
@@ -66,6 +74,68 @@ logic desc_req_reg = 1'b0;
|
||||
|
||||
assign desc_req = desc_req_reg;
|
||||
|
||||
wire [95:0] tx_cpl_ptp_ts;
|
||||
wire tx_cpl_valid;
|
||||
|
||||
if (PTP_TS_EN) begin
|
||||
|
||||
if (PTP_TS_FMT_TOD) begin
|
||||
|
||||
assign tx_cpl_ptp_ts = tx_cpl.tdata;
|
||||
assign tx_cpl_valid = tx_cpl.tvalid;
|
||||
|
||||
end else begin
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(96),
|
||||
.KEEP_EN(0),
|
||||
.KEEP_W(1),
|
||||
.STRB_EN(0),
|
||||
.LAST_EN(0),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(0),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) tx_cpl_tod();
|
||||
|
||||
assign tx_cpl_ptp_ts = tx_cpl_tod.tdata;
|
||||
assign tx_cpl_valid = tx_cpl_tod.tvalid;
|
||||
|
||||
taxi_ptp_td_rel2tod #(
|
||||
.TS_FNS_W(16),
|
||||
.TS_REL_NS_W(tx_cpl.DATA_W-16),
|
||||
.TS_TOD_S_W(48),
|
||||
.TS_REL_W(tx_cpl.DATA_W),
|
||||
.TS_TOD_W(96),
|
||||
.TD_SDI_PIPELINE(2)
|
||||
)
|
||||
rel2tod_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* PTP clock interface
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_td_sdi(ptp_td_sdi),
|
||||
|
||||
/*
|
||||
* Timestamp conversion
|
||||
*/
|
||||
.s_axis_ts_rel(tx_cpl),
|
||||
.m_axis_ts_tod(tx_cpl_tod)
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
assign tx_cpl_ptp_ts = '0;
|
||||
assign tx_cpl_valid = tx_cpl.tvalid;
|
||||
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
desc_req_reg <= 1'b0;
|
||||
|
||||
@@ -118,6 +188,8 @@ always_ff @(posedge clk) begin
|
||||
dma_desc.req_src_addr <= '0;
|
||||
dma_desc.req_len <= axis_desc.tdata[47:32];
|
||||
|
||||
axis_cpl.tdata[47:32] <= axis_desc.tdata[47:32];
|
||||
|
||||
if (axis_desc.tvalid && axis_desc.tready) begin
|
||||
if (axis_desc.tuser) begin
|
||||
// failed to read desc
|
||||
@@ -135,7 +207,10 @@ always_ff @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
STATE_TX_DATA: begin
|
||||
if (dma_desc.sts_valid) begin
|
||||
axis_cpl.tdata[127:112] <= tx_cpl_ptp_ts[63:48]; // sec
|
||||
axis_cpl.tdata[95:64] <= tx_cpl_ptp_ts[47:16]; // ns
|
||||
axis_cpl.tdata[111:96] <= tx_cpl_ptp_ts[15:0]; // fns
|
||||
if (tx_cpl_valid) begin
|
||||
axis_cpl.tvalid <= 1'b1;
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
|
||||
@@ -39,6 +39,10 @@ export PARAM_SIM := "1'b1"
|
||||
export PARAM_VENDOR := "\"XILINX\""
|
||||
export PARAM_FAMILY := "\"virtexuplus\""
|
||||
export PARAM_PORTS := 2
|
||||
export PARAM_PTP_TS_EN := 1
|
||||
export PARAM_PTP_TS_FMT_TOD := 0
|
||||
export PARAM_PTP_CLK_PER_NS_NUM := 512
|
||||
export PARAM_PTP_CLK_PER_NS_DENOM := 165
|
||||
export PARAM_MAC_DATA_W := 32
|
||||
export PARAM_AXIS_PCIE_DATA_W := 256
|
||||
export PARAM_BAR0_APERTURE := 24
|
||||
|
||||
@@ -271,6 +271,10 @@ class TB:
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**int(dut.uut.axil_ctrl_bar.ADDR_W))
|
||||
|
||||
# PTP
|
||||
cocotb.start_soon(Clock(dut.ptp_clk, 3.102, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start())
|
||||
|
||||
# Ethernet
|
||||
self.port_mac = []
|
||||
|
||||
@@ -291,6 +295,9 @@ class TB:
|
||||
rx_clk=dut.mac_rx_clk[k],
|
||||
rx_rst=dut.mac_rx_rst[k],
|
||||
rx_bus=AxiStreamBus.from_entity(dut.mac_axis_rx[k]),
|
||||
tx_ptp_time=dut.mac_axis_tx[k].tid, # TODO
|
||||
tx_ptp_ts=dut.mac_axis_tx_cpl[k].tdata, # TODO
|
||||
tx_ptp_ts_valid=dut.mac_axis_tx_cpl[k].tvalid, # TODO
|
||||
ifg=12, speed=eth_speed
|
||||
)
|
||||
self.port_mac.append(mac)
|
||||
@@ -347,6 +354,8 @@ class TB:
|
||||
|
||||
async def init(self):
|
||||
|
||||
self.dut.ptp_rst.setimmediatevalue(0)
|
||||
|
||||
for mac in self.port_mac:
|
||||
mac.rx.reset.setimmediatevalue(0)
|
||||
mac.tx.reset.setimmediatevalue(0)
|
||||
@@ -357,6 +366,8 @@ class TB:
|
||||
for k in range(10):
|
||||
await RisingEdge(self.dut.pcie_clk)
|
||||
|
||||
self.dut.ptp_rst.value = 1
|
||||
|
||||
for mac in self.port_mac:
|
||||
mac.rx.reset.value = 1
|
||||
mac.tx.reset.value = 1
|
||||
@@ -364,6 +375,8 @@ class TB:
|
||||
for k in range(10):
|
||||
await RisingEdge(self.dut.pcie_clk)
|
||||
|
||||
self.dut.ptp_rst.value = 0
|
||||
|
||||
for mac in self.port_mac:
|
||||
mac.rx.reset.value = 0
|
||||
mac.tx.reset.value = 0
|
||||
@@ -499,6 +512,10 @@ def test_cndm_micro_pcie_us(request, mac_data_w):
|
||||
parameters['VENDOR'] = "\"XILINX\""
|
||||
parameters['FAMILY'] = "\"virtexuplus\""
|
||||
parameters['PORTS'] = 2
|
||||
parameters["PTP_TS_EN"] = 1
|
||||
parameters["PTP_TS_FMT_TOD"] = 0
|
||||
parameters["PTP_CLK_PER_NS_NUM"] = 512
|
||||
parameters["PTP_CLK_PER_NS_DENOM"] = 165
|
||||
parameters['MAC_DATA_W'] = mac_data_w
|
||||
parameters['AXIS_PCIE_DATA_W'] = 256
|
||||
parameters['BAR0_APERTURE'] = 24
|
||||
|
||||
@@ -22,6 +22,10 @@ module test_cndm_micro_pcie_us #
|
||||
parameter string VENDOR = "XILINX",
|
||||
parameter string FAMILY = "virtexuplus",
|
||||
parameter PORTS = 2,
|
||||
parameter logic PTP_TS_EN = 1'b1,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b0,
|
||||
parameter PTP_CLK_PER_NS_NUM = 512,
|
||||
parameter PTP_CLK_PER_NS_DENOM = 165,
|
||||
parameter MAC_DATA_W = 32,
|
||||
parameter AXIS_PCIE_DATA_W = 256,
|
||||
parameter AXIS_PCIE_RC_USER_W = AXIS_PCIE_DATA_W < 512 ? 75 : 161,
|
||||
@@ -33,6 +37,8 @@ module test_cndm_micro_pcie_us #
|
||||
)
|
||||
();
|
||||
|
||||
localparam PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 48;
|
||||
|
||||
localparam AXIS_PCIE_KEEP_W = (AXIS_PCIE_DATA_W/32);
|
||||
localparam RQ_SEQ_NUM_W = AXIS_PCIE_RQ_USER_W == 60 ? 4 : 6;
|
||||
|
||||
@@ -122,6 +128,20 @@ logic [1:0] cfg_interrupt_msi_tph_type;
|
||||
logic [7:0] cfg_interrupt_msi_tph_st_tag;
|
||||
logic [7:0] cfg_interrupt_msi_function_number;
|
||||
|
||||
logic ptp_rst;
|
||||
logic ptp_clk;
|
||||
logic ptp_sample_clk;
|
||||
logic ptp_td_sdo;
|
||||
logic ptp_pps;
|
||||
logic ptp_pps_str;
|
||||
logic ptp_sync_locked;
|
||||
logic [63:0] ptp_sync_ts_rel;
|
||||
logic ptp_sync_ts_rel_step;
|
||||
logic [95:0] ptp_sync_ts_tod;
|
||||
logic ptp_sync_ts_tod_step;
|
||||
logic ptp_sync_pps;
|
||||
logic ptp_sync_pps_str;
|
||||
|
||||
logic mac_tx_clk[PORTS];
|
||||
logic mac_tx_rst[PORTS];
|
||||
|
||||
@@ -136,7 +156,7 @@ logic mac_rx_clk[PORTS];
|
||||
logic mac_rx_rst[PORTS];
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(96),
|
||||
.DATA_W(PTP_TS_W),
|
||||
.KEEP_W(1),
|
||||
.ID_W(8)
|
||||
) mac_axis_tx_cpl[PORTS]();
|
||||
@@ -145,7 +165,7 @@ taxi_axis_if #(
|
||||
.DATA_W(MAC_DATA_W),
|
||||
.ID_W(8),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
.USER_W(PTP_TS_W+1)
|
||||
) mac_axis_rx[PORTS]();
|
||||
|
||||
cndm_micro_pcie_us #(
|
||||
@@ -153,6 +173,9 @@ cndm_micro_pcie_us #(
|
||||
.VENDOR(VENDOR),
|
||||
.FAMILY(FAMILY),
|
||||
.PORTS(PORTS),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
|
||||
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM),
|
||||
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
|
||||
.BAR0_APERTURE(BAR0_APERTURE)
|
||||
)
|
||||
@@ -210,6 +233,23 @@ uut (
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
.ptp_clk(ptp_clk),
|
||||
.ptp_rst(ptp_rst),
|
||||
.ptp_sample_clk(ptp_sample_clk),
|
||||
.ptp_td_sdo(ptp_td_sdo),
|
||||
.ptp_pps(ptp_pps),
|
||||
.ptp_pps_str(ptp_pps_str),
|
||||
.ptp_sync_locked(ptp_sync_locked),
|
||||
.ptp_sync_ts_rel(ptp_sync_ts_rel),
|
||||
.ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
|
||||
.ptp_sync_ts_tod(ptp_sync_ts_tod),
|
||||
.ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
|
||||
.ptp_sync_pps(ptp_sync_pps),
|
||||
.ptp_sync_pps_str(ptp_sync_pps_str),
|
||||
|
||||
/*
|
||||
* Ethernet: SFP+
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user