#define TJA1120_GLOBAL_INFRA_IRQ_STATUS 0x2C0C
#define TJA1120_DEV_BOOT_DONE BIT(1)
+#define TJA1120_VEND1_PTP_TRIG_DATA_S 0x1070
+
#define TJA1120_EGRESS_TS_DATA_S 0x9060
#define TJA1120_EGRESS_TS_END 0x9067
#define TJA1120_TS_VALID BIT(0)
void (*counters_enable)(struct phy_device *phydev);
bool (*get_egressts)(struct nxp_c45_phy *priv,
struct nxp_c45_hwts *hwts);
+ bool (*get_extts)(struct nxp_c45_phy *priv, struct timespec64 *extts);
void (*ptp_init)(struct phy_device *phydev);
void (*ptp_enable)(struct phy_device *phydev, bool enable);
void (*nmi_handler)(struct phy_device *phydev,
header->domain_number == hwts->domain_number;
}
-static void nxp_c45_get_extts(struct nxp_c45_phy *priv,
+static bool nxp_c45_get_extts(struct nxp_c45_phy *priv,
struct timespec64 *extts)
{
const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
regmap->vend1_ext_trg_data_3) << 16;
phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
regmap->vend1_ext_trg_ctrl, RING_DONE);
+
+ return true;
+}
+
+static bool tja1120_extts_is_valid(struct phy_device *phydev)
+{
+ bool valid;
+ int reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_VEND1_PTP_TRIG_DATA_S);
+ valid = !!(reg & TJA1120_TS_VALID);
+
+ return valid;
+}
+
+static bool tja1120_get_extts(struct nxp_c45_phy *priv,
+ struct timespec64 *extts)
+{
+ const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
+ struct phy_device *phydev = priv->phydev;
+ bool more_ts;
+ bool valid;
+ u16 reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ regmap->vend1_ext_trg_ctrl);
+ more_ts = !!(reg & TJA1120_MORE_TS);
+
+ valid = tja1120_extts_is_valid(phydev);
+ if (!valid) {
+ if (!more_ts)
+ goto tja1120_get_extts_out;
+
+ /* Bug workaround for TJA1120 engineering samples: move the new
+ * timestamp from the FIFO to the buffer.
+ */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ regmap->vend1_ext_trg_ctrl, RING_DONE);
+ valid = tja1120_extts_is_valid(phydev);
+ if (!valid)
+ goto tja1120_get_extts_out;
+ }
+
+ nxp_c45_get_extts(priv, extts);
+tja1120_get_extts_out:
+ return valid;
}
static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv,
bool reschedule = false;
struct timespec64 ts;
struct sk_buff *skb;
- bool txts_valid;
+ bool ts_valid;
u32 ts_raw;
while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) {
- txts_valid = data->get_egressts(priv, &hwts);
- if (unlikely(!txts_valid)) {
+ ts_valid = data->get_egressts(priv, &hwts);
+ if (unlikely(!ts_valid)) {
/* Still more skbs in the queue */
reschedule = true;
break;
}
if (priv->extts) {
- nxp_c45_get_extts(priv, &ts);
- if (timespec64_compare(&ts, &priv->extts_ts) != 0) {
+ ts_valid = data->get_extts(priv, &ts);
+ if (ts_valid && timespec64_compare(&ts, &priv->extts_ts) != 0) {
priv->extts_ts = ts;
event.index = priv->extts_index;
event.type = PTP_CLOCK_EXTTS;
.ack_ptp_irq = false,
.counters_enable = tja1103_counters_enable,
.get_egressts = nxp_c45_get_hwtxts,
+ .get_extts = nxp_c45_get_extts,
.ptp_init = tja1103_ptp_init,
.ptp_enable = tja1103_ptp_enable,
.nmi_handler = tja1103_nmi_handler,
.ack_ptp_irq = true,
.counters_enable = tja1120_counters_enable,
.get_egressts = tja1120_get_hwtxts,
+ .get_extts = tja1120_get_extts,
.ptp_init = tja1120_ptp_init,
.ptp_enable = tja1120_ptp_enable,
.nmi_handler = tja1120_nmi_handler,