* [net-next] amd-xgbe: add hardware PTP timestamping support
@ 2025-07-07 17:53 Raju Rangoju
2025-07-08 10:54 ` Vadim Fedorenko
0 siblings, 1 reply; 3+ messages in thread
From: Raju Rangoju @ 2025-07-07 17:53 UTC (permalink / raw)
To: netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, Shyam-sundar.S-k,
Raju Rangoju
Adds support for hardware-based PTP (IEEE 1588) timestamping to
the AMD XGBE driver.
- Initialize and configure the MAC PTP registers based on link
speed and reference clock.
- Support both 50MHz and 125MHz PTP reference clocks.
- Update the driver interface and version data to support PTP
clock frequency selection.
Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-common.h | 10 ++
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 145 ++++++++++++++++----
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 15 +-
drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 2 +
drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 74 +++++-----
drivers/net/ethernet/amd/xgbe/xgbe.h | 25 +++-
6 files changed, 187 insertions(+), 84 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index e54e3e36d3f9..009fbc9b11ce 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -223,6 +223,10 @@
#define MAC_TSSR 0x0d20
#define MAC_TXSNR 0x0d30
#define MAC_TXSSR 0x0d34
+#define MAC_TICNR 0x0d58
+#define MAC_TICSNR 0x0d5C
+#define MAC_TECNR 0x0d60
+#define MAC_TECSNR 0x0d64
#define MAC_QTFCR_INC 4
#define MAC_MACA_INC 4
@@ -428,6 +432,8 @@
#define MAC_TSCR_SNAPTYPSEL_WIDTH 2
#define MAC_TSCR_TSADDREG_INDEX 5
#define MAC_TSCR_TSADDREG_WIDTH 1
+#define MAC_TSCR_TSUPDT_INDEX 3
+#define MAC_TSCR_TSUPDT_WIDTH 1
#define MAC_TSCR_TSCFUPDT_INDEX 1
#define MAC_TSCR_TSCFUPDT_WIDTH 1
#define MAC_TSCR_TSCTRLSSR_INDEX 9
@@ -456,6 +462,10 @@
#define MAC_TSSR_TXTSC_WIDTH 1
#define MAC_TXSNR_TXTSSTSMIS_INDEX 31
#define MAC_TXSNR_TXTSSTSMIS_WIDTH 1
+#define MAC_TICSNR_TSICSNS_INDEX 8
+#define MAC_TICSNR_TSICSNS_WIDTH 8
+#define MAC_TECSNR_TSECSNS_INDEX 8
+#define MAC_TECSNR_TSECSNS_WIDTH 8
#define MAC_VLANHTR_VLHT_INDEX 0
#define MAC_VLANHTR_VLHT_WIDTH 16
#define MAC_VLANIR_VLTI_INDEX 20
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 9e4e79bfe624..559425fa1846 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1558,6 +1558,29 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
DBGPR("<--rx_desc_init\n");
}
+static void xgbe_update_tstamp_time(struct xgbe_prv_data *pdata,
+ unsigned int sec, unsigned int nsec)
+{
+ unsigned int count = 10000;
+
+ /* Set the time values and tell the device */
+ XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
+ XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
+
+ /* issue command to update the system time value */
+ XGMAC_IOWRITE(pdata, MAC_TSCR,
+ XGMAC_IOREAD(pdata, MAC_TSCR) |
+ (1 << MAC_TSCR_TSUPDT_INDEX));
+
+ /* Wait for the time till update complete */
+ while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSUPDT))
+ udelay(5);
+
+ if (!count)
+ netdev_err(pdata->netdev,
+ "timed out updating system timestamp\n");
+}
+
static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
unsigned int addend)
{
@@ -1636,8 +1659,8 @@ static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
!XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
nsec = le32_to_cpu(rdesc->desc1);
- nsec <<= 32;
- nsec |= le32_to_cpu(rdesc->desc0);
+ nsec *= NSEC_PER_SEC;
+ nsec += le32_to_cpu(rdesc->desc0);
if (nsec != 0xffffffffffffffffULL) {
packet->rx_tstamp = nsec;
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
@@ -1646,39 +1669,18 @@ static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
}
}
-static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
- unsigned int mac_tscr)
+static void xgbe_config_tstamp(struct xgbe_prv_data *pdata,
+ unsigned int mac_tscr)
{
- /* Set one nano-second accuracy */
- XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
-
- /* Set fine timestamp update */
- XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
-
- /* Overwrite earlier timestamps */
- XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
-
- XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
-
- /* Exit if timestamping is not enabled */
- if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
- return 0;
+ unsigned int value = 0;
- /* Initialize time registers */
- XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
- XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
- xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
- xgbe_set_tstamp_time(pdata, 0, 0);
-
- /* Initialize the timecounter */
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
- ktime_to_ns(ktime_get_real()));
-
- return 0;
+ value = XGMAC_IOREAD(pdata, MAC_TSCR);
+ value |= mac_tscr;
+ XGMAC_IOWRITE(pdata, MAC_TSCR, value);
}
static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
- struct xgbe_ring *ring)
+ struct xgbe_ring *ring)
{
struct xgbe_prv_data *pdata = channel->pdata;
struct xgbe_ring_data *rdata;
@@ -3512,6 +3514,87 @@ static void xgbe_powerdown_rx(struct xgbe_prv_data *pdata)
}
}
+static void xgbe_init_ptp(struct xgbe_prv_data *pdata)
+{
+ unsigned int mac_tscr = 0;
+ struct timespec64 now;
+ u64 dividend;
+
+ /* Register Settings to be done based on the link speed. */
+ switch (pdata->phy.speed) {
+ case SPEED_1000:
+ XGMAC_IOWRITE(pdata, MAC_TICNR, MAC_TICNR_1G_INITVAL);
+ XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_1G_INITVAL);
+ break;
+ case SPEED_2500:
+ case SPEED_10000:
+ XGMAC_IOWRITE_BITS(pdata, MAC_TICSNR, TSICSNS,
+ MAC_TICSNR_10G_INITVAL);
+ XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_10G_INITVAL);
+ XGMAC_IOWRITE_BITS(pdata, MAC_TECSNR, TSECSNS,
+ MAC_TECSNR_10G_INITVAL);
+ break;
+ case SPEED_UNKNOWN:
+ default:
+ break;
+ }
+
+ /* Enable IEEE1588 PTP clock. */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+
+ /* Overwrite earlier timestamps */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
+
+ /* Set one nano-second accuracy */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
+
+ /* Set fine timestamp update */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
+
+ xgbe_config_tstamp(pdata, mac_tscr);
+
+ /* Exit if timestamping is not enabled */
+ if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
+ return;
+
+ if (pdata->vdata->tstamp_ptp_clock_freq) {
+ /* Initialize time registers based on
+ * 125MHz PTP Clock Frequency
+ */
+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC,
+ XGBE_V2_TSTAMP_SSINC);
+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC,
+ XGBE_V2_TSTAMP_SNSINC);
+ } else {
+ /* Initialize time registers based on
+ * 50MHz PTP Clock Frequency
+ */
+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
+ }
+
+ /* Calculate the addend:
+ * addend = 2^32 / (PTP ref clock / (PTP clock based on SSINC))
+ * = (2^32 * (PTP clock based on SSINC)) / PTP ref clock
+ */
+ if (pdata->vdata->tstamp_ptp_clock_freq)
+ dividend = 100000000; // PTP clock frequency is 125MHz
+ else
+ dividend = 50000000; // PTP clock frequency is 50MHz
+
+ dividend <<= 32;
+ pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
+
+ xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
+
+ dma_wmb();
+ /* initialize system time */
+ ktime_get_real_ts64(&now);
+
+ /* lower 32 bits of tv_sec are safe until y2106 */
+ xgbe_set_tstamp_time(pdata, (u32)now.tv_sec, now.tv_nsec);
+}
+
static int xgbe_init(struct xgbe_prv_data *pdata)
{
struct xgbe_desc_if *desc_if = &pdata->desc_if;
@@ -3672,9 +3755,11 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->read_mmc_stats = xgbe_read_mmc_stats;
/* For PTP config */
+ hw_if->init_ptp = xgbe_init_ptp;
hw_if->config_tstamp = xgbe_config_tstamp;
hw_if->update_tstamp_addend = xgbe_update_tstamp_addend;
hw_if->set_tstamp_time = xgbe_set_tstamp_time;
+ hw_if->update_tstamp_time = xgbe_update_tstamp_time;
hw_if->get_tstamp_time = xgbe_get_tstamp_time;
hw_if->get_tx_tstamp = xgbe_get_tx_tstamp;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 65447f9a0a59..a6b9d0cda48c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1377,7 +1377,6 @@ static void xgbe_tx_tstamp(struct work_struct *work)
struct xgbe_prv_data,
tx_tstamp_work);
struct skb_shared_hwtstamps hwtstamps;
- u64 nsec;
unsigned long flags;
spin_lock_irqsave(&pdata->tstamp_lock, flags);
@@ -1385,11 +1384,8 @@ static void xgbe_tx_tstamp(struct work_struct *work)
goto unlock;
if (pdata->tx_tstamp) {
- nsec = timecounter_cyc2time(&pdata->tstamp_tc,
- pdata->tx_tstamp);
-
memset(&hwtstamps, 0, sizeof(hwtstamps));
- hwtstamps.hwtstamp = ns_to_ktime(nsec);
+ hwtstamps.hwtstamp = ns_to_ktime(pdata->tx_tstamp);
skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
}
@@ -1776,6 +1772,9 @@ static int xgbe_open(struct net_device *netdev)
INIT_WORK(&pdata->stopdev_work, xgbe_stopdev);
INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
+ /* Initialize PTP timestamping and clock. */
+ pdata->hw_if.init_ptp(pdata);
+
ret = xgbe_alloc_memory(pdata);
if (ret)
goto err_ptpclk;
@@ -2546,12 +2545,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
if (XGMAC_GET_BITS(packet->attributes,
RX_PACKET_ATTRIBUTES, RX_TSTAMP)) {
- u64 nsec;
-
- nsec = timecounter_cyc2time(&pdata->tstamp_tc,
- packet->rx_tstamp);
hwtstamps = skb_hwtstamps(skb);
- hwtstamps->hwtstamp = ns_to_ktime(nsec);
+ hwtstamps->hwtstamp = ns_to_ktime(packet->rx_tstamp);
}
if (XGMAC_GET_BITS(packet->attributes,
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 097ec5e4f261..e3e1dca9856a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -414,6 +414,7 @@ static struct xgbe_version_data xgbe_v2a = {
.tx_max_fifo_size = 229376,
.rx_max_fifo_size = 229376,
.tx_tstamp_workaround = 1,
+ .tstamp_ptp_clock_freq = 1,
.ecc_support = 1,
.i2c_support = 1,
.irq_reissue_support = 1,
@@ -430,6 +431,7 @@ static struct xgbe_version_data xgbe_v2b = {
.tx_max_fifo_size = 65536,
.rx_max_fifo_size = 65536,
.tx_tstamp_workaround = 1,
+ .tstamp_ptp_clock_freq = 1,
.ecc_support = 1,
.i2c_support = 1,
.irq_reissue_support = 1,
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
index 978c4dd01fa0..52764dcd9f4d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
@@ -13,18 +13,6 @@
#include "xgbe.h"
#include "xgbe-common.h"
-static u64 xgbe_cc_read(const struct cyclecounter *cc)
-{
- struct xgbe_prv_data *pdata = container_of(cc,
- struct xgbe_prv_data,
- tstamp_cc);
- u64 nsec;
-
- nsec = pdata->hw_if.get_tstamp_time(pdata);
-
- return nsec;
-}
-
static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm)
{
struct xgbe_prv_data *pdata = container_of(info,
@@ -50,25 +38,55 @@ static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
struct xgbe_prv_data,
ptp_clock_info);
unsigned long flags;
+ unsigned int sec, nsec;
+ unsigned int neg_adjust = 0;
+ u32 quotient, reminder;
+
+ if (delta < 0) {
+ neg_adjust = 1;
+ delta = -delta;
+ }
+
+ quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
+ sec = quotient;
+ nsec = reminder;
+
+ /* Negative adjustment for Hw timer register. */
+ if (neg_adjust) {
+ sec = -sec;
+ if (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSCTRLSSR))
+ nsec = (1000000000UL - nsec);
+ else
+ nsec = (0x80000000UL - nsec);
+ }
+ nsec = (neg_adjust << 31) | nsec;
spin_lock_irqsave(&pdata->tstamp_lock, flags);
- timecounter_adjtime(&pdata->tstamp_tc, delta);
+ pdata->hw_if.update_tstamp_time(pdata, sec, nsec);
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
return 0;
}
-static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
+static int xgbe_gettimex(struct ptp_clock_info *info,
+ struct timespec64 *ts,
+ struct ptp_system_timestamp *sts)
{
struct xgbe_prv_data *pdata = container_of(info,
struct xgbe_prv_data,
ptp_clock_info);
unsigned long flags;
u64 nsec;
+ static int count = 3;
+
+ if (count > 0 && count--)
+ dump_stack();
spin_lock_irqsave(&pdata->tstamp_lock, flags);
- nsec = timecounter_read(&pdata->tstamp_tc);
+ ptp_read_system_prets(sts);
+ nsec = pdata->hw_if.get_tstamp_time(pdata);
+ ptp_read_system_postts(sts);
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
@@ -84,13 +102,10 @@ static int xgbe_settime(struct ptp_clock_info *info,
struct xgbe_prv_data,
ptp_clock_info);
unsigned long flags;
- u64 nsec;
-
- nsec = timespec64_to_ns(ts);
spin_lock_irqsave(&pdata->tstamp_lock, flags);
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+ pdata->hw_if.set_tstamp_time(pdata, ts->tv_sec, ts->tv_nsec);
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
@@ -107,8 +122,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
{
struct ptp_clock_info *info = &pdata->ptp_clock_info;
struct ptp_clock *clock;
- struct cyclecounter *cc = &pdata->tstamp_cc;
- u64 dividend;
snprintf(info->name, sizeof(info->name), "%s",
netdev_name(pdata->netdev));
@@ -116,7 +129,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
info->max_adj = pdata->ptpclk_rate;
info->adjfine = xgbe_adjfine;
info->adjtime = xgbe_adjtime;
- info->gettime64 = xgbe_gettime;
+ info->gettimex64 = xgbe_gettimex;
info->settime64 = xgbe_settime;
info->enable = xgbe_enable;
@@ -128,23 +141,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
pdata->ptp_clock = clock;
- /* Calculate the addend:
- * addend = 2^32 / (PTP ref clock / 50Mhz)
- * = (2^32 * 50Mhz) / PTP ref clock
- */
- dividend = 50000000;
- dividend <<= 32;
- pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
-
- /* Setup the timecounter */
- cc->read = xgbe_cc_read;
- cc->mask = CLOCKSOURCE_MASK(64);
- cc->mult = 1;
- cc->shift = 0;
-
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
- ktime_to_ns(ktime_get_real()));
-
/* Disable all timestamping to start */
XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 70169ea23c7f..b5c5624eb827 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -119,6 +119,14 @@
#define XGBE_MSI_BASE_COUNT 4
#define XGBE_MSI_MIN_COUNT (XGBE_MSI_BASE_COUNT + 1)
+/* Initial PTP register values based on Link Speed. */
+#define MAC_TICNR_1G_INITVAL 0x10
+#define MAC_TECNR_1G_INITVAL 0x28
+
+#define MAC_TICSNR_10G_INITVAL 0x33
+#define MAC_TECNR_10G_INITVAL 0x14
+#define MAC_TECSNR_10G_INITVAL 0xCC
+
/* PCI clock frequencies */
#define XGBE_V2_DMA_CLOCK_FREQ 500000000 /* 500 MHz */
#define XGBE_V2_PTP_CLOCK_FREQ 125000000 /* 125 MHz */
@@ -129,6 +137,8 @@
#define XGBE_TSTAMP_SSINC 20
#define XGBE_TSTAMP_SNSINC 0
+#define XGBE_V2_TSTAMP_SSINC 0xA
+#define XGBE_V2_TSTAMP_SNSINC 0
/* Driver PMT macros */
#define XGMAC_DRIVER_CONTEXT 1
#define XGMAC_IOCTL_CONTEXT 2
@@ -742,10 +752,16 @@ struct xgbe_hw_if {
void (*read_mmc_stats)(struct xgbe_prv_data *);
/* For Timestamp config */
- int (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
- void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int);
- void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
+ void (*init_ptp)(struct xgbe_prv_data *pdata);
+ void (*config_tstamp)(struct xgbe_prv_data *pdata,
+ unsigned int mac_tscr);
+ void (*update_tstamp_addend)(struct xgbe_prv_data *pdata,
+ unsigned int addend);
+ void (*set_tstamp_time)(struct xgbe_prv_data *pdata, unsigned int sec,
unsigned int nsec);
+ void (*update_tstamp_time)(struct xgbe_prv_data *pdata,
+ unsigned int sec,
+ unsigned int nsec);
u64 (*get_tstamp_time)(struct xgbe_prv_data *);
u64 (*get_tx_tstamp)(struct xgbe_prv_data *);
@@ -946,6 +962,7 @@ struct xgbe_version_data {
unsigned int tx_max_fifo_size;
unsigned int rx_max_fifo_size;
unsigned int tx_tstamp_workaround;
+ unsigned int tstamp_ptp_clock_freq;
unsigned int ecc_support;
unsigned int i2c_support;
unsigned int irq_reissue_support;
@@ -1131,8 +1148,6 @@ struct xgbe_prv_data {
struct ptp_clock_info ptp_clock_info;
struct ptp_clock *ptp_clock;
struct hwtstamp_config tstamp_config;
- struct cyclecounter tstamp_cc;
- struct timecounter tstamp_tc;
unsigned int tstamp_addend;
struct work_struct tx_tstamp_work;
struct sk_buff *tx_tstamp_skb;
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [net-next] amd-xgbe: add hardware PTP timestamping support
2025-07-07 17:53 [net-next] amd-xgbe: add hardware PTP timestamping support Raju Rangoju
@ 2025-07-08 10:54 ` Vadim Fedorenko
2025-07-12 10:22 ` Rangoju, Raju
0 siblings, 1 reply; 3+ messages in thread
From: Vadim Fedorenko @ 2025-07-08 10:54 UTC (permalink / raw)
To: Raju Rangoju, netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, Shyam-sundar.S-k
On 07/07/2025 18:53, Raju Rangoju wrote:
> Adds support for hardware-based PTP (IEEE 1588) timestamping to
> the AMD XGBE driver.
>
> - Initialize and configure the MAC PTP registers based on link
> speed and reference clock.
> - Support both 50MHz and 125MHz PTP reference clocks.
> - Update the driver interface and version data to support PTP
> clock frequency selection.
>
> Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
> ---
> drivers/net/ethernet/amd/xgbe/xgbe-common.h | 10 ++
> drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 145 ++++++++++++++++----
> drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 15 +-
> drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 2 +
> drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 74 +++++-----
> drivers/net/ethernet/amd/xgbe/xgbe.h | 25 +++-
> 6 files changed, 187 insertions(+), 84 deletions(-)
>
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
> index e54e3e36d3f9..009fbc9b11ce 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
> @@ -223,6 +223,10 @@
> #define MAC_TSSR 0x0d20
> #define MAC_TXSNR 0x0d30
> #define MAC_TXSSR 0x0d34
> +#define MAC_TICNR 0x0d58
> +#define MAC_TICSNR 0x0d5C
> +#define MAC_TECNR 0x0d60
> +#define MAC_TECSNR 0x0d64
>
> #define MAC_QTFCR_INC 4
> #define MAC_MACA_INC 4
> @@ -428,6 +432,8 @@
> #define MAC_TSCR_SNAPTYPSEL_WIDTH 2
> #define MAC_TSCR_TSADDREG_INDEX 5
> #define MAC_TSCR_TSADDREG_WIDTH 1
> +#define MAC_TSCR_TSUPDT_INDEX 3
> +#define MAC_TSCR_TSUPDT_WIDTH 1
> #define MAC_TSCR_TSCFUPDT_INDEX 1
> #define MAC_TSCR_TSCFUPDT_WIDTH 1
> #define MAC_TSCR_TSCTRLSSR_INDEX 9
> @@ -456,6 +462,10 @@
> #define MAC_TSSR_TXTSC_WIDTH 1
> #define MAC_TXSNR_TXTSSTSMIS_INDEX 31
> #define MAC_TXSNR_TXTSSTSMIS_WIDTH 1
> +#define MAC_TICSNR_TSICSNS_INDEX 8
> +#define MAC_TICSNR_TSICSNS_WIDTH 8
> +#define MAC_TECSNR_TSECSNS_INDEX 8
> +#define MAC_TECSNR_TSECSNS_WIDTH 8
> #define MAC_VLANHTR_VLHT_INDEX 0
> #define MAC_VLANHTR_VLHT_WIDTH 16
> #define MAC_VLANIR_VLTI_INDEX 20
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
> index 9e4e79bfe624..559425fa1846 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
> @@ -1558,6 +1558,29 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
> DBGPR("<--rx_desc_init\n");
> }
>
> +static void xgbe_update_tstamp_time(struct xgbe_prv_data *pdata,
> + unsigned int sec, unsigned int nsec)
> +{
> + unsigned int count = 10000;
> +
> + /* Set the time values and tell the device */
> + XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
> + XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
> +
> + /* issue command to update the system time value */
> + XGMAC_IOWRITE(pdata, MAC_TSCR,
> + XGMAC_IOREAD(pdata, MAC_TSCR) |
> + (1 << MAC_TSCR_TSUPDT_INDEX));
> +
> + /* Wait for the time till update complete */
> + while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSUPDT))
> + udelay(5);
> +
> + if (!count)
> + netdev_err(pdata->netdev,
> + "timed out updating system timestamp\n");
> +}
> +
> static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
> unsigned int addend)
> {
> @@ -1636,8 +1659,8 @@ static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
> if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
> !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
> nsec = le32_to_cpu(rdesc->desc1);
> - nsec <<= 32;
> - nsec |= le32_to_cpu(rdesc->desc0);
> + nsec *= NSEC_PER_SEC;
> + nsec += le32_to_cpu(rdesc->desc0);
This change is not explained in the commit message. Looks like the
HW timestamping has already been implemented, but in a wrong way?
> if (nsec != 0xffffffffffffffffULL) {
> packet->rx_tstamp = nsec;
> XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
> @@ -1646,39 +1669,18 @@ static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
> }
> }
>
> -static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
> - unsigned int mac_tscr)
> +static void xgbe_config_tstamp(struct xgbe_prv_data *pdata,
> + unsigned int mac_tscr)
> {
> - /* Set one nano-second accuracy */
> - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
> -
> - /* Set fine timestamp update */
> - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
> -
> - /* Overwrite earlier timestamps */
> - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
> -
> - XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
> -
> - /* Exit if timestamping is not enabled */
> - if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
> - return 0;
> + unsigned int value = 0;
>
> - /* Initialize time registers */
> - XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
> - XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
> - xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
> - xgbe_set_tstamp_time(pdata, 0, 0);
> -
> - /* Initialize the timecounter */
> - timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
> - ktime_to_ns(ktime_get_real()));
> -
> - return 0;
> + value = XGMAC_IOREAD(pdata, MAC_TSCR);
> + value |= mac_tscr;
> + XGMAC_IOWRITE(pdata, MAC_TSCR, value);
> }
>
> static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
> - struct xgbe_ring *ring)
> + struct xgbe_ring *ring)
doesn't look like we need this change
> {
> struct xgbe_prv_data *pdata = channel->pdata;
> struct xgbe_ring_data *rdata;
> @@ -3512,6 +3514,87 @@ static void xgbe_powerdown_rx(struct xgbe_prv_data *pdata)
> }
> }
>
> +static void xgbe_init_ptp(struct xgbe_prv_data *pdata)
> +{
> + unsigned int mac_tscr = 0;
> + struct timespec64 now;
> + u64 dividend;
> +
> + /* Register Settings to be done based on the link speed. */
> + switch (pdata->phy.speed) {
> + case SPEED_1000:
> + XGMAC_IOWRITE(pdata, MAC_TICNR, MAC_TICNR_1G_INITVAL);
> + XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_1G_INITVAL);
> + break;
> + case SPEED_2500:
> + case SPEED_10000:
> + XGMAC_IOWRITE_BITS(pdata, MAC_TICSNR, TSICSNS,
> + MAC_TICSNR_10G_INITVAL);
> + XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_10G_INITVAL);
> + XGMAC_IOWRITE_BITS(pdata, MAC_TECSNR, TSECSNS,
> + MAC_TECSNR_10G_INITVAL);
> + break;
> + case SPEED_UNKNOWN:
> + default:
> + break;
> + }
> +
> + /* Enable IEEE1588 PTP clock. */
> + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
> +
> + /* Overwrite earlier timestamps */
> + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
> +
> + /* Set one nano-second accuracy */
> + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
> +
> + /* Set fine timestamp update */
> + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
> +
> + xgbe_config_tstamp(pdata, mac_tscr);
> +
> + /* Exit if timestamping is not enabled */
> + if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
> + return;
> +
> + if (pdata->vdata->tstamp_ptp_clock_freq) {
> + /* Initialize time registers based on
> + * 125MHz PTP Clock Frequency
> + */
> + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC,
> + XGBE_V2_TSTAMP_SSINC);
> + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC,
> + XGBE_V2_TSTAMP_SNSINC);
> + } else {
> + /* Initialize time registers based on
> + * 50MHz PTP Clock Frequency
> + */
> + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
> + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
> + }
> +
> + /* Calculate the addend:
> + * addend = 2^32 / (PTP ref clock / (PTP clock based on SSINC))
> + * = (2^32 * (PTP clock based on SSINC)) / PTP ref clock
> + */
> + if (pdata->vdata->tstamp_ptp_clock_freq)
> + dividend = 100000000; // PTP clock frequency is 125MHz
> + else
> + dividend = 50000000; // PTP clock frequency is 50MHz
why do you use 100_000_000 value for 125MHz while 50_000_000 for 50MHz?
it doesn't look intuitive
also, please, be consistent with the style of comments.
> +
> + dividend <<= 32;
> + pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
> +
> + xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
> +
> + dma_wmb();
> + /* initialize system time */
> + ktime_get_real_ts64(&now);
> +
> + /* lower 32 bits of tv_sec are safe until y2106 */
> + xgbe_set_tstamp_time(pdata, (u32)now.tv_sec, now.tv_nsec);
> +}
> +
> static int xgbe_init(struct xgbe_prv_data *pdata)
> {
> struct xgbe_desc_if *desc_if = &pdata->desc_if;
> @@ -3672,9 +3755,11 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
> hw_if->read_mmc_stats = xgbe_read_mmc_stats;
>
> /* For PTP config */
> + hw_if->init_ptp = xgbe_init_ptp;
> hw_if->config_tstamp = xgbe_config_tstamp;
> hw_if->update_tstamp_addend = xgbe_update_tstamp_addend;
> hw_if->set_tstamp_time = xgbe_set_tstamp_time;
> + hw_if->update_tstamp_time = xgbe_update_tstamp_time;
> hw_if->get_tstamp_time = xgbe_get_tstamp_time;
> hw_if->get_tx_tstamp = xgbe_get_tx_tstamp;
>
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> index 65447f9a0a59..a6b9d0cda48c 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> @@ -1377,7 +1377,6 @@ static void xgbe_tx_tstamp(struct work_struct *work)
> struct xgbe_prv_data,
> tx_tstamp_work);
> struct skb_shared_hwtstamps hwtstamps;
> - u64 nsec;
> unsigned long flags;
>
> spin_lock_irqsave(&pdata->tstamp_lock, flags);
> @@ -1385,11 +1384,8 @@ static void xgbe_tx_tstamp(struct work_struct *work)
> goto unlock;
>
> if (pdata->tx_tstamp) {
> - nsec = timecounter_cyc2time(&pdata->tstamp_tc,
> - pdata->tx_tstamp);
> -
> memset(&hwtstamps, 0, sizeof(hwtstamps));
> - hwtstamps.hwtstamp = ns_to_ktime(nsec);
> + hwtstamps.hwtstamp = ns_to_ktime(pdata->tx_tstamp);
> skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
> }
>
> @@ -1776,6 +1772,9 @@ static int xgbe_open(struct net_device *netdev)
> INIT_WORK(&pdata->stopdev_work, xgbe_stopdev);
> INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
>
> + /* Initialize PTP timestamping and clock. */
> + pdata->hw_if.init_ptp(pdata);
> +
> ret = xgbe_alloc_memory(pdata);
> if (ret)
> goto err_ptpclk;
> @@ -2546,12 +2545,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
>
> if (XGMAC_GET_BITS(packet->attributes,
> RX_PACKET_ATTRIBUTES, RX_TSTAMP)) {
> - u64 nsec;
> -
> - nsec = timecounter_cyc2time(&pdata->tstamp_tc,
> - packet->rx_tstamp);
> hwtstamps = skb_hwtstamps(skb);
> - hwtstamps->hwtstamp = ns_to_ktime(nsec);
> + hwtstamps->hwtstamp = ns_to_ktime(packet->rx_tstamp);
> }
>
> if (XGMAC_GET_BITS(packet->attributes,
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
> index 097ec5e4f261..e3e1dca9856a 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
> @@ -414,6 +414,7 @@ static struct xgbe_version_data xgbe_v2a = {
> .tx_max_fifo_size = 229376,
> .rx_max_fifo_size = 229376,
> .tx_tstamp_workaround = 1,
> + .tstamp_ptp_clock_freq = 1,
> .ecc_support = 1,
> .i2c_support = 1,
> .irq_reissue_support = 1,
> @@ -430,6 +431,7 @@ static struct xgbe_version_data xgbe_v2b = {
> .tx_max_fifo_size = 65536,
> .rx_max_fifo_size = 65536,
> .tx_tstamp_workaround = 1,
> + .tstamp_ptp_clock_freq = 1,
> .ecc_support = 1,
> .i2c_support = 1,
> .irq_reissue_support = 1,
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
> index 978c4dd01fa0..52764dcd9f4d 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
> @@ -13,18 +13,6 @@
> #include "xgbe.h"
> #include "xgbe-common.h"
>
> -static u64 xgbe_cc_read(const struct cyclecounter *cc)
> -{
> - struct xgbe_prv_data *pdata = container_of(cc,
> - struct xgbe_prv_data,
> - tstamp_cc);
> - u64 nsec;
> -
> - nsec = pdata->hw_if.get_tstamp_time(pdata);
> -
> - return nsec;
> -}
> -
> static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm)
> {
> struct xgbe_prv_data *pdata = container_of(info,
> @@ -50,25 +38,55 @@ static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
> struct xgbe_prv_data,
> ptp_clock_info);
> unsigned long flags;
> + unsigned int sec, nsec;
> + unsigned int neg_adjust = 0;
> + u32 quotient, reminder;
please, use reverse x-mass tree ordering of variables
> +
> + if (delta < 0) {
> + neg_adjust = 1;
> + delta = -delta;
> + }
> +
> + quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
> + sec = quotient;
> + nsec = reminder;
> +
> + /* Negative adjustment for Hw timer register. */
> + if (neg_adjust) {
> + sec = -sec;
> + if (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSCTRLSSR))
> + nsec = (1000000000UL - nsec);
> + else
> + nsec = (0x80000000UL - nsec);
> + }
> + nsec = (neg_adjust << 31) | nsec;
>
> spin_lock_irqsave(&pdata->tstamp_lock, flags);
> - timecounter_adjtime(&pdata->tstamp_tc, delta);
> + pdata->hw_if.update_tstamp_time(pdata, sec, nsec);
> spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
>
> return 0;
> }
>
> -static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
> +static int xgbe_gettimex(struct ptp_clock_info *info,
> + struct timespec64 *ts,
> + struct ptp_system_timestamp *sts)
> {
> struct xgbe_prv_data *pdata = container_of(info,
> struct xgbe_prv_data,
> ptp_clock_info);
> unsigned long flags;
> u64 nsec;
> + static int count = 3;
> +> + if (count > 0 && count--)
> + dump_stack();
looks like debug leftover
>
> spin_lock_irqsave(&pdata->tstamp_lock, flags);
>
> - nsec = timecounter_read(&pdata->tstamp_tc);
> + ptp_read_system_prets(sts);
> + nsec = pdata->hw_if.get_tstamp_time(pdata);
> + ptp_read_system_postts(sts);
>
> spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
>
> @@ -84,13 +102,10 @@ static int xgbe_settime(struct ptp_clock_info *info,
> struct xgbe_prv_data,
> ptp_clock_info);
> unsigned long flags;
> - u64 nsec;
> -
> - nsec = timespec64_to_ns(ts);
>
> spin_lock_irqsave(&pdata->tstamp_lock, flags);
>
> - timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
> + pdata->hw_if.set_tstamp_time(pdata, ts->tv_sec, ts->tv_nsec);
>
> spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
>
> @@ -107,8 +122,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
> {
> struct ptp_clock_info *info = &pdata->ptp_clock_info;
> struct ptp_clock *clock;
> - struct cyclecounter *cc = &pdata->tstamp_cc;
> - u64 dividend;
>
> snprintf(info->name, sizeof(info->name), "%s",
> netdev_name(pdata->netdev));
> @@ -116,7 +129,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
> info->max_adj = pdata->ptpclk_rate;
> info->adjfine = xgbe_adjfine;
> info->adjtime = xgbe_adjtime;
> - info->gettime64 = xgbe_gettime;
> + info->gettimex64 = xgbe_gettimex;
> info->settime64 = xgbe_settime;
> info->enable = xgbe_enable;
>
> @@ -128,23 +141,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
>
> pdata->ptp_clock = clock;
>
> - /* Calculate the addend:
> - * addend = 2^32 / (PTP ref clock / 50Mhz)
> - * = (2^32 * 50Mhz) / PTP ref clock
> - */
> - dividend = 50000000;
> - dividend <<= 32;
> - pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
> -
> - /* Setup the timecounter */
> - cc->read = xgbe_cc_read;
> - cc->mask = CLOCKSOURCE_MASK(64);
> - cc->mult = 1;
> - cc->shift = 0;
> -
> - timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
> - ktime_to_ns(ktime_get_real()));
> -
> /* Disable all timestamping to start */
> XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
> pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
> index 70169ea23c7f..b5c5624eb827 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe.h
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
> @@ -119,6 +119,14 @@
> #define XGBE_MSI_BASE_COUNT 4
> #define XGBE_MSI_MIN_COUNT (XGBE_MSI_BASE_COUNT + 1)
>
> +/* Initial PTP register values based on Link Speed. */
> +#define MAC_TICNR_1G_INITVAL 0x10
> +#define MAC_TECNR_1G_INITVAL 0x28
> +
> +#define MAC_TICSNR_10G_INITVAL 0x33
> +#define MAC_TECNR_10G_INITVAL 0x14
> +#define MAC_TECSNR_10G_INITVAL 0xCC
> +
> /* PCI clock frequencies */
> #define XGBE_V2_DMA_CLOCK_FREQ 500000000 /* 500 MHz */
> #define XGBE_V2_PTP_CLOCK_FREQ 125000000 /* 125 MHz */
> @@ -129,6 +137,8 @@
> #define XGBE_TSTAMP_SSINC 20
> #define XGBE_TSTAMP_SNSINC 0
>
> +#define XGBE_V2_TSTAMP_SSINC 0xA
> +#define XGBE_V2_TSTAMP_SNSINC 0
> /* Driver PMT macros */
> #define XGMAC_DRIVER_CONTEXT 1
> #define XGMAC_IOCTL_CONTEXT 2
> @@ -742,10 +752,16 @@ struct xgbe_hw_if {
> void (*read_mmc_stats)(struct xgbe_prv_data *);
>
> /* For Timestamp config */
> - int (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
> - void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int);
> - void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
> + void (*init_ptp)(struct xgbe_prv_data *pdata);
> + void (*config_tstamp)(struct xgbe_prv_data *pdata,
> + unsigned int mac_tscr);
> + void (*update_tstamp_addend)(struct xgbe_prv_data *pdata,
> + unsigned int addend);
> + void (*set_tstamp_time)(struct xgbe_prv_data *pdata, unsigned int sec,
> unsigned int nsec);
> + void (*update_tstamp_time)(struct xgbe_prv_data *pdata,
> + unsigned int sec,
> + unsigned int nsec);
> u64 (*get_tstamp_time)(struct xgbe_prv_data *);
> u64 (*get_tx_tstamp)(struct xgbe_prv_data *);
>
> @@ -946,6 +962,7 @@ struct xgbe_version_data {
> unsigned int tx_max_fifo_size;
> unsigned int rx_max_fifo_size;
> unsigned int tx_tstamp_workaround;
> + unsigned int tstamp_ptp_clock_freq;
> unsigned int ecc_support;
> unsigned int i2c_support;
> unsigned int irq_reissue_support;
> @@ -1131,8 +1148,6 @@ struct xgbe_prv_data {
> struct ptp_clock_info ptp_clock_info;
> struct ptp_clock *ptp_clock;
> struct hwtstamp_config tstamp_config;
> - struct cyclecounter tstamp_cc;
> - struct timecounter tstamp_tc;
> unsigned int tstamp_addend;
> struct work_struct tx_tstamp_work;
> struct sk_buff *tx_tstamp_skb;
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [net-next] amd-xgbe: add hardware PTP timestamping support
2025-07-08 10:54 ` Vadim Fedorenko
@ 2025-07-12 10:22 ` Rangoju, Raju
0 siblings, 0 replies; 3+ messages in thread
From: Rangoju, Raju @ 2025-07-12 10:22 UTC (permalink / raw)
To: Vadim Fedorenko, netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, Shyam-sundar.S-k
On 7/8/2025 4:24 PM, Vadim Fedorenko wrote:
> On 07/07/2025 18:53, Raju Rangoju wrote:
>> @@ -1636,8 +1659,8 @@ static void xgbe_get_rx_tstamp(struct
>> xgbe_packet_data *packet,
>> if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
>> !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
>> nsec = le32_to_cpu(rdesc->desc1);
>> - nsec <<= 32;
>> - nsec |= le32_to_cpu(rdesc->desc0);
>> + nsec *= NSEC_PER_SEC;
>> + nsec += le32_to_cpu(rdesc->desc0);
>
> This change is not explained in the commit message. Looks like the
> HW timestamping has already been implemented, but in a wrong way?
Yes, the previous implementation was partial and not functional. This
patch adds support for full implementation.
>> + /* Calculate the addend:
>> + * addend = 2^32 / (PTP ref clock / (PTP clock based on SSINC))
>> + * = (2^32 * (PTP clock based on SSINC)) / PTP ref clock
>> + */
>> + if (pdata->vdata->tstamp_ptp_clock_freq)
>> + dividend = 100000000; // PTP clock frequency is 125MHz
>> + else
>> + dividend = 50000000; // PTP clock frequency is 50MHz
> why do you use 100_000_000 value for 125MHz while 50_000_000 for 50MHz?
> it doesn't look intuitive
>
That is due to the difference in the ideal clock frequency vs
actual clock freq running on the board. I'll address the comments in v2.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-12 10:22 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-07 17:53 [net-next] amd-xgbe: add hardware PTP timestamping support Raju Rangoju
2025-07-08 10:54 ` Vadim Fedorenko
2025-07-12 10:22 ` Rangoju, Raju
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.