* [PATCH 2/5] ptp: ocp: Expose clock status drift and offset
2021-12-16 20:01 [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jonathan Lemon
@ 2021-12-16 20:01 ` Jonathan Lemon
2021-12-16 20:01 ` [PATCH 3/5] ptp: ocp: add tod_correction attribute Jonathan Lemon
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jonathan Lemon @ 2021-12-16 20:01 UTC (permalink / raw)
To: netdev, davem, kuba; +Cc: kernel-team
From: Vadim Fedorenko <vadfed@fb.com>
Monitoring of clock variance could be done through checking
the offset and the drift updates that are applied to atomic
clocks. Expose these values as attributes for timecard.
Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 17ad5f0d13b2..2ac5ef54fada 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -52,6 +52,8 @@ struct ocp_reg {
u32 servo_offset_i;
u32 servo_drift_p;
u32 servo_drift_i;
+ u32 status_offset;
+ u32 status_drift;
};
#define OCP_CTRL_ENABLE BIT(0)
@@ -1974,6 +1976,36 @@ available_clock_sources_show(struct device *dev,
}
static DEVICE_ATTR_RO(available_clock_sources);
+static ssize_t
+clock_status_drift_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+ int res;
+
+ val = ioread32(&bp->reg->status_drift);
+ res = (val & ~INT_MAX) ? -1 : 1;
+ res *= (val & INT_MAX);
+ return sysfs_emit(buf, "%d\n", res);
+}
+static DEVICE_ATTR_RO(clock_status_drift);
+
+static ssize_t
+clock_status_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+ int res;
+
+ val = ioread32(&bp->reg->status_offset);
+ res = (val & ~INT_MAX) ? -1 : 1;
+ res *= (val & INT_MAX);
+ return sysfs_emit(buf, "%d\n", res);
+}
+static DEVICE_ATTR_RO(clock_status_offset);
+
static struct attribute *timecard_attrs[] = {
&dev_attr_serialnum.attr,
&dev_attr_gnss_sync.attr,
@@ -1985,6 +2017,8 @@ static struct attribute *timecard_attrs[] = {
&dev_attr_sma4.attr,
&dev_attr_available_sma_inputs.attr,
&dev_attr_available_sma_outputs.attr,
+ &dev_attr_clock_status_drift.attr,
+ &dev_attr_clock_status_offset.attr,
&dev_attr_irig_b_mode.attr,
&dev_attr_utc_tai_offset.attr,
&dev_attr_ts_window_adjust.attr,
--
2.31.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 3/5] ptp: ocp: add tod_correction attribute
2021-12-16 20:01 [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jonathan Lemon
2021-12-16 20:01 ` [PATCH 2/5] ptp: ocp: Expose clock status drift and offset Jonathan Lemon
@ 2021-12-16 20:01 ` Jonathan Lemon
2021-12-16 20:01 ` [PATCH 4/5] ptp: ocp: adjust utc_tai_offset to TOD info Jonathan Lemon
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jonathan Lemon @ 2021-12-16 20:01 UTC (permalink / raw)
To: netdev, davem, kuba; +Cc: kernel-team
From: Vadim Fedorenko <vadfed@fb.com>
TOD correction register is used to compensate for leap seconds in
different domains. Export it as attribute with write access.
Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 2ac5ef54fada..2383d1024f0f 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -2006,6 +2006,46 @@ clock_status_offset_show(struct device *dev,
}
static DEVICE_ATTR_RO(clock_status_offset);
+static ssize_t
+tod_correction_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+ int res;
+
+ val = ioread32(&bp->tod->adj_sec);
+ res = (val & ~INT_MAX) ? -1 : 1;
+ res *= (val & INT_MAX);
+ return sysfs_emit(buf, "%d\n", res);
+}
+
+static ssize_t
+tod_correction_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ int err, res;
+ u32 val = 0;
+
+ err = kstrtos32(buf, 0, &res);
+ if (err)
+ return err;
+ if (res < 0) {
+ res *= -1;
+ val |= BIT(31);
+ }
+ val |= res;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ iowrite32(val, &bp->tod->adj_sec);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(tod_correction);
+
static struct attribute *timecard_attrs[] = {
&dev_attr_serialnum.attr,
&dev_attr_gnss_sync.attr,
@@ -2022,6 +2062,7 @@ static struct attribute *timecard_attrs[] = {
&dev_attr_irig_b_mode.attr,
&dev_attr_utc_tai_offset.attr,
&dev_attr_ts_window_adjust.attr,
+ &dev_attr_tod_correction.attr,
NULL,
};
ATTRIBUTE_GROUPS(timecard);
--
2.31.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 4/5] ptp: ocp: adjust utc_tai_offset to TOD info
2021-12-16 20:01 [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jonathan Lemon
2021-12-16 20:01 ` [PATCH 2/5] ptp: ocp: Expose clock status drift and offset Jonathan Lemon
2021-12-16 20:01 ` [PATCH 3/5] ptp: ocp: add tod_correction attribute Jonathan Lemon
@ 2021-12-16 20:01 ` Jonathan Lemon
2021-12-16 20:01 ` [PATCH 5/5] ptp: ocp: export board info via devlink Jonathan Lemon
2021-12-18 3:10 ` [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jakub Kicinski
4 siblings, 0 replies; 6+ messages in thread
From: Jonathan Lemon @ 2021-12-16 20:01 UTC (permalink / raw)
To: netdev, davem, kuba; +Cc: kernel-team
From: Vadim Fedorenko <vadfed@fb.com>
utc_tai_offset is used to correct IRIG, DCF and NMEA outputs and is
set during initialisation but is not corrected during leap second
announce event. Add watchdog code to control this correction.
Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 51 ++++++++++++++++++++++++++-----------------
1 file changed, 31 insertions(+), 20 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 2383d1024f0f..dc4d07b04320 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -761,12 +761,31 @@ __ptp_ocp_clear_drift_locked(struct ptp_ocp *bp)
iowrite32(select >> 16, &bp->reg->select);
}
+static void
+ptp_ocp_utc_distribute(struct ptp_ocp *bp, u32 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->lock, flags);
+
+ bp->utc_tai_offset = val;
+
+ if (bp->irig_out)
+ iowrite32(val, &bp->irig_out->adj_sec);
+ if (bp->dcf_out)
+ iowrite32(val, &bp->dcf_out->adj_sec);
+ if (bp->nmea_out)
+ iowrite32(val, &bp->nmea_out->adj_sec);
+
+ spin_unlock_irqrestore(&bp->lock, flags);
+}
+
static void
ptp_ocp_watchdog(struct timer_list *t)
{
struct ptp_ocp *bp = from_timer(bp, t, watchdog);
unsigned long flags;
- u32 status;
+ u32 status, utc_offset;
status = ioread32(&bp->pps_to_clk->status);
@@ -783,6 +802,17 @@ ptp_ocp_watchdog(struct timer_list *t)
bp->gnss_lost = 0;
}
+ /* if GNSS provides correct data we can rely on
+ * it to get leap second information
+ */
+ if (bp->tod) {
+ status = ioread32(&bp->tod->utc_status);
+ utc_offset = status & TOD_STATUS_UTC_MASK;
+ if (status & TOD_STATUS_UTC_VALID &&
+ utc_offset != bp->utc_tai_offset)
+ ptp_ocp_utc_distribute(bp, utc_offset);
+ }
+
mod_timer(&bp->watchdog, jiffies + HZ);
}
@@ -851,25 +881,6 @@ ptp_ocp_init_clock(struct ptp_ocp *bp)
return 0;
}
-static void
-ptp_ocp_utc_distribute(struct ptp_ocp *bp, u32 val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&bp->lock, flags);
-
- bp->utc_tai_offset = val;
-
- if (bp->irig_out)
- iowrite32(val, &bp->irig_out->adj_sec);
- if (bp->dcf_out)
- iowrite32(val, &bp->dcf_out->adj_sec);
- if (bp->nmea_out)
- iowrite32(val, &bp->nmea_out->adj_sec);
-
- spin_unlock_irqrestore(&bp->lock, flags);
-}
-
static void
ptp_ocp_tod_init(struct ptp_ocp *bp)
{
--
2.31.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 5/5] ptp: ocp: export board info via devlink
2021-12-16 20:01 [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jonathan Lemon
` (2 preceding siblings ...)
2021-12-16 20:01 ` [PATCH 4/5] ptp: ocp: adjust utc_tai_offset to TOD info Jonathan Lemon
@ 2021-12-16 20:01 ` Jonathan Lemon
2021-12-18 3:10 ` [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jakub Kicinski
4 siblings, 0 replies; 6+ messages in thread
From: Jonathan Lemon @ 2021-12-16 20:01 UTC (permalink / raw)
To: netdev, davem, kuba; +Cc: kernel-team
TimeCard has eeprom with manufacturer pre-defined information.
Export this via devlink interface.
Co-developed-by: Vadim Fedorenko <vadfed@fb.com>
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 71 +++++++++++++++++++++++++++++++------------
1 file changed, 52 insertions(+), 19 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index dc4d07b04320..8f235eef7521 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -203,6 +203,10 @@ struct ptp_ocp_ext_src {
int irq_vec;
};
+#define OCP_BOARD_MFR_LEN 8
+#define OCP_BOARD_ID_LEN 12
+#define OCP_SERIAL_LEN 6
+
struct ptp_ocp {
struct pci_dev *pdev;
struct device dev;
@@ -237,8 +241,10 @@ struct ptp_ocp {
int gnss2_port;
int mac_port; /* miniature atomic clock */
int nmea_port;
- u8 serial[6];
- bool has_serial;
+ u8 board_mfr[OCP_BOARD_MFR_LEN];
+ u8 board_id[OCP_BOARD_ID_LEN];
+ u8 serial[OCP_SERIAL_LEN];
+ bool has_eeprom_data;
u32 pps_req_map;
int flash_start;
u32 utc_tai_offset;
@@ -977,7 +983,7 @@ ptp_ocp_read_i2c(struct i2c_adapter *adap, u8 addr, u8 reg, u8 sz, u8 *data)
}
static void
-ptp_ocp_get_serial_number(struct ptp_ocp *bp)
+ptp_ocp_read_eeprom(struct ptp_ocp *bp)
{
struct i2c_adapter *adap;
struct device *dev;
@@ -999,16 +1005,30 @@ ptp_ocp_get_serial_number(struct ptp_ocp *bp)
goto out;
}
- err = ptp_ocp_read_i2c(adap, 0x58, 0x9A, 6, bp->serial);
- if (err) {
- dev_err(&bp->pdev->dev, "could not read eeprom: %d\n", err);
- goto out;
- }
+ err = ptp_ocp_read_i2c(adap, 0x50, 0x7A,
+ sizeof(bp->board_mfr), bp->board_mfr);
+ if (err)
+ goto read_fail;
- bp->has_serial = true;
+ err = ptp_ocp_read_i2c(adap, 0x50, 0x44,
+ sizeof(bp->board_id), bp->board_id);
+ if (err)
+ goto read_fail;
+
+ err = ptp_ocp_read_i2c(adap, 0x58, 0x9A,
+ sizeof(bp->serial), bp->serial);
+ if (err)
+ goto read_fail;
+
+ bp->has_eeprom_data = true;
out:
put_device(dev);
+ return;
+
+read_fail:
+ dev_err(&bp->pdev->dev, "could not read eeprom: %d\n", err);
+ goto out;
}
static struct device *
@@ -1127,16 +1147,29 @@ ptp_ocp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
return err;
}
- if (!bp->has_serial)
- ptp_ocp_get_serial_number(bp);
-
- if (bp->has_serial) {
- sprintf(buf, "%pM", bp->serial);
- err = devlink_info_serial_number_put(req, buf);
- if (err)
- return err;
+ if (!bp->has_eeprom_data) {
+ ptp_ocp_read_eeprom(bp);
+ if (!bp->has_eeprom_data)
+ return 0;
}
+ sprintf(buf, "%pM", bp->serial);
+ err = devlink_info_serial_number_put(req, buf);
+ if (err)
+ return err;
+
+ err = devlink_info_version_fixed_put(req,
+ DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE,
+ bp->board_mfr);
+ if (err)
+ return err;
+
+ err = devlink_info_version_fixed_put(req,
+ DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
+ bp->board_id);
+ if (err)
+ return err;
+
return 0;
}
@@ -1828,8 +1861,8 @@ serialnum_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ptp_ocp *bp = dev_get_drvdata(dev);
- if (!bp->has_serial)
- ptp_ocp_get_serial_number(bp);
+ if (!bp->has_eeprom_data)
+ ptp_ocp_read_eeprom(bp);
return sysfs_emit(buf, "%pM\n", bp->serial);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments
2021-12-16 20:01 [PATCH 1/5] ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments Jonathan Lemon
` (3 preceding siblings ...)
2021-12-16 20:01 ` [PATCH 5/5] ptp: ocp: export board info via devlink Jonathan Lemon
@ 2021-12-18 3:10 ` Jakub Kicinski
4 siblings, 0 replies; 6+ messages in thread
From: Jakub Kicinski @ 2021-12-18 3:10 UTC (permalink / raw)
To: Jonathan Lemon; +Cc: netdev, davem, kernel-team
On Thu, 16 Dec 2021 12:01:00 -0800 Jonathan Lemon wrote:
> In ("ptp: ocp: Have FPGA fold in ns adjustment for adjtime."), the
> ns adjustment was written to the FPGA register, so the clock could
> accurately perform adjustments.
>
> However, the adjtime() call passes in a s64, while the clock adjustment
> registers use a s32. When trying to perform adjustments with a large
> value (37 sec), things fail.
>
> Examine the incoming delta, and if larger than 1 sec, use the original
> (coarse) adjustment method. If smaller than 1 sec, then allow the
> FPGA to fold in the changes over a 1 second window.
>
> Fixes: 2d97ed56f671 ("ptp: ocp: Have FPGA fold in ns adjustment for adjtime.")
This SHA does not exist upstream. Please separate the fixes from the
features. Please CC Richard on the patches.
^ permalink raw reply [flat|nested] 6+ messages in thread