Commit f5b9a1cd authored by Wei Fang's avatar Wei Fang Committed by Paolo Abeni
Browse files

net: enetc: add PTP synchronization support for ENETC v4



Regarding PTP, ENETC v4 has some changes compared to ENETC v1 (LS1028A),
mainly as follows.

1. ENETC v4 uses a different PTP driver, so the way to get phc_index is
different from LS1028A. Therefore, enetc_get_ts_info() has been modified
appropriately to be compatible with ENETC v1 and v4.

2. The PMa_SINGLE_STEP register has changed in ENETC v4, not only the
register offset, but also some register fields. Therefore, two helper
functions are added, enetc_set_one_step_ts() for ENETC v1 and
enetc4_set_one_step_ts() for ENETC v4.

3. Since the generic helper functions from ptp_clock are used to get
the PHC index of the PTP clock, so FSL_ENETC_CORE depends on Kconfig
symbol "PTP_1588_CLOCK_OPTIONAL". But FSL_ENETC_CORE can only be
selected, so add the dependency to FSL_ENETC, FSL_ENETC_VF and
NXP_ENETC4. Perhaps the best approach would be to change FSL_ENETC_CORE
to a visible menu entry. Then make FSL_ENETC, FSL_ENETC_VF, and
NXP_ENETC4 depend on it, but this is not the goal of this patch, so this
may be changed in the future.

Signed-off-by: default avatarWei Fang <wei.fang@nxp.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20250829050615.1247468-14-wei.fang@nxp.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 7776d5e6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ config NXP_NTMP

config FSL_ENETC
	tristate "ENETC PF driver"
	depends on PTP_1588_CLOCK_OPTIONAL
	depends on PCI_MSI
	select FSL_ENETC_CORE
	select FSL_ENETC_IERB
@@ -45,6 +46,7 @@ config FSL_ENETC

config NXP_ENETC4
	tristate "ENETC4 PF driver"
	depends on PTP_1588_CLOCK_OPTIONAL
	depends on PCI_MSI
	select FSL_ENETC_CORE
	select FSL_ENETC_MDIO
@@ -62,6 +64,7 @@ config NXP_ENETC4

config FSL_ENETC_VF
	tristate "ENETC VF driver"
	depends on PTP_1588_CLOCK_OPTIONAL
	depends on PCI_MSI
	select FSL_ENETC_CORE
	select FSL_ENETC_MDIO
+31 −9
Original line number Diff line number Diff line
@@ -221,6 +221,31 @@ static void enetc_unwind_tx_frame(struct enetc_bdr *tx_ring, int count, int i)
	}
}

static void enetc_set_one_step_ts(struct enetc_si *si, bool udp, int offset)
{
	u32 val = ENETC_PM0_SINGLE_STEP_EN;

	val |= ENETC_SET_SINGLE_STEP_OFFSET(offset);
	if (udp)
		val |= ENETC_PM0_SINGLE_STEP_CH;

	/* The "Correction" field of a packet is updated based on the
	 * current time and the timestamp provided
	 */
	enetc_port_mac_wr(si, ENETC_PM0_SINGLE_STEP, val);
}

static void enetc4_set_one_step_ts(struct enetc_si *si, bool udp, int offset)
{
	u32 val = PM_SINGLE_STEP_EN;

	val |= PM_SINGLE_STEP_OFFSET_SET(offset);
	if (udp)
		val |= PM_SINGLE_STEP_CH;

	enetc_port_mac_wr(si, ENETC4_PM_SINGLE_STEP(0), val);
}

static u32 enetc_update_ptp_sync_msg(struct enetc_ndev_priv *priv,
				     struct sk_buff *skb)
{
@@ -234,7 +259,6 @@ static u32 enetc_update_ptp_sync_msg(struct enetc_ndev_priv *priv,
	u32 lo, hi, nsec;
	u8 *data;
	u64 sec;
	u32 val;

	lo = enetc_rd_hot(hw, ENETC_SICTR0);
	hi = enetc_rd_hot(hw, ENETC_SICTR1);
@@ -279,12 +303,10 @@ static u32 enetc_update_ptp_sync_msg(struct enetc_ndev_priv *priv,
	*(__be32 *)(data + tstamp_off + 6) = new_nsec;

	/* Configure single-step register */
	val = ENETC_PM0_SINGLE_STEP_EN;
	val |= ENETC_SET_SINGLE_STEP_OFFSET(corr_off);
	if (enetc_cb->udp)
		val |= ENETC_PM0_SINGLE_STEP_CH;

	enetc_port_mac_wr(priv->si, ENETC_PM0_SINGLE_STEP, val);
	if (is_enetc_rev1(si))
		enetc_set_one_step_ts(si, enetc_cb->udp, corr_off);
	else
		enetc4_set_one_step_ts(si, enetc_cb->udp, corr_off);

	return lo & ENETC_TXBD_TSTAMP;
}
@@ -3315,7 +3337,7 @@ int enetc_hwtstamp_set(struct net_device *ndev,
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	int err, new_offloads = priv->active_offloads;

	if (!IS_ENABLED(CONFIG_FSL_ENETC_PTP_CLOCK))
	if (!enetc_ptp_clock_is_enabled(priv->si))
		return -EOPNOTSUPP;

	switch (config->tx_type) {
@@ -3365,7 +3387,7 @@ int enetc_hwtstamp_get(struct net_device *ndev,
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);

	if (!IS_ENABLED(CONFIG_FSL_ENETC_PTP_CLOCK))
	if (!enetc_ptp_clock_is_enabled(priv->si))
		return -EOPNOTSUPP;

	if (priv->active_offloads & ENETC_F_TX_ONESTEP_SYNC_TSTAMP)
+8 −0
Original line number Diff line number Diff line
@@ -598,6 +598,14 @@ static inline void enetc_cbd_free_data_mem(struct enetc_si *si, int size,
void enetc_reset_ptcmsdur(struct enetc_hw *hw);
void enetc_set_ptcmsdur(struct enetc_hw *hw, u32 *queue_max_sdu);

static inline bool enetc_ptp_clock_is_enabled(struct enetc_si *si)
{
	if (is_enetc_rev1(si))
		return IS_ENABLED(CONFIG_FSL_ENETC_PTP_CLOCK);

	return IS_ENABLED(CONFIG_PTP_NETC_V4_TIMER);
}

#ifdef CONFIG_FSL_ENETC_QOS
int enetc_qos_query_caps(struct net_device *ndev, void *type_data);
int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
+6 −0
Original line number Diff line number Diff line
@@ -171,6 +171,12 @@
/* Port MAC 0/1 Pause Quanta Threshold Register */
#define ENETC4_PM_PAUSE_THRESH(mac)	(0x5064 + (mac) * 0x400)

#define ENETC4_PM_SINGLE_STEP(mac)	(0x50c0 + (mac) * 0x400)
#define  PM_SINGLE_STEP_CH		BIT(6)
#define  PM_SINGLE_STEP_OFFSET		GENMASK(15, 7)
#define  PM_SINGLE_STEP_OFFSET_SET(o)	FIELD_PREP(PM_SINGLE_STEP_OFFSET, o)
#define  PM_SINGLE_STEP_EN		BIT(31)

/* Port MAC 0 Interface Mode Control Register */
#define ENETC4_PM_IF_MODE(mac)		(0x5300 + (mac) * 0x400)
#define  PM_IF_MODE_IFMODE		GENMASK(2, 0)
+3 −0
Original line number Diff line number Diff line
@@ -569,6 +569,9 @@ static const struct net_device_ops enetc4_ndev_ops = {
	.ndo_set_features	= enetc4_pf_set_features,
	.ndo_vlan_rx_add_vid	= enetc_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= enetc_vlan_rx_del_vid,
	.ndo_eth_ioctl		= enetc_ioctl,
	.ndo_hwtstamp_get	= enetc_hwtstamp_get,
	.ndo_hwtstamp_set	= enetc_hwtstamp_set,
};

static struct phylink_pcs *
Loading