@@ -739,6 +739,18 @@ int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val,
if (!(bus->flags & MII_BUS_F_PTP_STS_SUPPORTED))
ptp_read_system_postts(sts);
+ /* PTP offset compensation:
+ * After the MDIO access is completed (from the chip perspective), the
+ * switch chip will snapshot the PHC timestamp. To make sure our system
+ * timestamp corresponds to the PHC timestamp, we have to add the
+ * duration of this MDIO access to sts->post_ts. Linuxptp's phc2sys
+ * takes the average of pre_ts and post_ts to calculate the final
+ * system timestamp. With this in mind, we have to add ptp_sts_offset
+ * twice to post_ts, in order to not introduce an constant time offset.
+ */
+ if (sts)
+ timespec64_add_ns(&sts->post_ts, 2 * bus->ptp_sts_offset);
+
return retval;
}
EXPORT_SYMBOL(__mdiobus_write_sts);
@@ -283,8 +283,16 @@ struct mii_bus {
* The ptp_read_system_*ts functions already check the ptp_sts pointer.
* The MII_BUS_F_PTP_STS_SUPPORTED-bit must be set in flags, when the
* MDIO bus driver takes the timestamps as described above.
+ *
+ * @ptp_sts_offset: This is the compensation offset for the system
+ * timestamp which is introduced by the slow MDIO access duration. An
+ * MDIO access consists of 32 clock cycles. Usually the MDIO bus runs
+ * at ~2.5MHz, so we have to compensate ~12800ns offset.
+ * Set the ptp_sts_offset to the exact duration of one MDIO frame
+ * (= 32 * clock-period) in nano-seconds.
*/
struct ptp_system_timestamp *ptp_sts;
+ u32 ptp_sts_offset;
};
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)