Commit 99100d0d authored by Wei Fang's avatar Wei Fang Committed by David S. Miller
Browse files

net: enetc: add preliminary support for i.MX95 ENETC PF



The i.MX95 ENETC has been upgraded to revision 4.1, which is different
from the LS1028A ENETC (revision 1.0) except for the SI part. Therefore,
the fsl-enetc driver is incompatible with i.MX95 ENETC PF. So add new
nxp-enetc4 driver to support i.MX95 ENETC PF, and this driver will be
used to support the ENETC PF with major revision 4 for other SoCs in the
future.

Currently, the nxp-enetc4 driver only supports basic transmission feature
for i.MX95 ENETC PF, the more basic and advanced features will be added
in the subsequent patches. In addition, PCS support has not been added
yet, so 10G ENETC (ENETC instance 2) is not supported now.

Signed-off-by: default avatarWei Fang <wei.fang@nxp.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9e7f2116
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -33,6 +33,23 @@ config FSL_ENETC

	  If compiled as module (M), the module name is fsl-enetc.

config NXP_ENETC4
	tristate "ENETC4 PF driver"
	depends on PCI_MSI
	select MDIO_DEVRES
	select FSL_ENETC_CORE
	select FSL_ENETC_MDIO
	select NXP_ENETC_PF_COMMON
	select PHYLINK
	select DIMLIB
	help
	  This driver supports NXP ENETC devices with major revision 4. ENETC is
	  as the NIC functionality in NETC, it supports virtualization/isolation
	  based on PCIe Single Root IO Virtualization (SR-IOV) and a full range
	  of TSN standards and NIC offload capabilities.

	  If compiled as module (M), the module name is nxp-enetc4.

config FSL_ENETC_VF
	tristate "ENETC VF driver"
	depends on PCI_MSI
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@ fsl-enetc-y := enetc_pf.o
fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o

obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
nxp-enetc4-y := enetc4_pf.o

obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
fsl-enetc-vf-y := enetc_vf.o

+77 −9
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include "enetc.h"
#include <linux/bpf_trace.h>
#include <linux/clk.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/vmalloc.h>
@@ -21,7 +22,7 @@ void enetc_port_mac_wr(struct enetc_si *si, u32 reg, u32 val)
{
	enetc_port_wr(&si->hw, reg, val);
	if (si->hw_features & ENETC_SI_F_QBU)
		enetc_port_wr(&si->hw, reg + ENETC_PMAC_OFFSET, val);
		enetc_port_wr(&si->hw, reg + si->drvdata->pmac_offset, val);
}
EXPORT_SYMBOL_GPL(enetc_port_mac_wr);

@@ -700,8 +701,9 @@ static void enetc_rx_dim_work(struct work_struct *w)
		net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
	struct enetc_int_vector	*v =
		container_of(dim, struct enetc_int_vector, rx_dim);
	struct enetc_ndev_priv *priv = netdev_priv(v->rx_ring.ndev);

	v->rx_ictt = enetc_usecs_to_cycles(moder.usec);
	v->rx_ictt = enetc_usecs_to_cycles(moder.usec, priv->sysclk_freq);
	dim->state = DIM_START_MEASURE;
}

@@ -1736,9 +1738,15 @@ void enetc_get_si_caps(struct enetc_si *si)
	si->num_rx_rings = (val >> 16) & 0xff;
	si->num_tx_rings = val & 0xff;

	val = enetc_rd(hw, ENETC_SIPCAPR0);
	if (val & ENETC_SIPCAPR0_RFS) {
		val = enetc_rd(hw, ENETC_SIRFSCAPR);
		si->num_fs_entries = ENETC_SIRFSCAPR_GET_NUM_RFS(val);
		si->num_fs_entries = min(si->num_fs_entries, ENETC_MAX_RFS_SIZE);
	} else {
		/* ENETC which not supports RFS */
		si->num_fs_entries = 0;
	}

	si->num_rss = 0;
	val = enetc_rd(hw, ENETC_SIPCAPR0);
@@ -2066,7 +2074,10 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
	/* enable SI */
	enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN);

	if (si->num_rss) {
	/* TODO: RSS support for i.MX95 will be supported later, and the
	 * is_enetc_rev1() condition will be removed
	 */
	if (si->num_rss && is_enetc_rev1(si)) {
		err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
		if (err)
			return err;
@@ -2090,9 +2101,9 @@ void enetc_init_si_rings_params(struct enetc_ndev_priv *priv)
	 */
	priv->num_rx_rings = min_t(int, cpus, si->num_rx_rings);
	priv->num_tx_rings = si->num_tx_rings;
	priv->bdr_int_num = cpus;
	priv->bdr_int_num = priv->num_rx_rings;
	priv->ic_mode = ENETC_IC_RX_ADAPTIVE | ENETC_IC_TX_MANUAL;
	priv->tx_ictt = ENETC_TXIC_TIMETHR;
	priv->tx_ictt = enetc_usecs_to_cycles(600, priv->sysclk_freq);
}
EXPORT_SYMBOL_GPL(enetc_init_si_rings_params);

@@ -2501,10 +2512,14 @@ int enetc_open(struct net_device *ndev)

	extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP);

	err = enetc_setup_irqs(priv);
	err = clk_prepare_enable(priv->ref_clk);
	if (err)
		return err;

	err = enetc_setup_irqs(priv);
	if (err)
		goto err_setup_irqs;

	err = enetc_phylink_connect(ndev);
	if (err)
		goto err_phy_connect;
@@ -2536,6 +2551,8 @@ int enetc_open(struct net_device *ndev)
		phylink_disconnect_phy(priv->phylink);
err_phy_connect:
	enetc_free_irqs(priv);
err_setup_irqs:
	clk_disable_unprepare(priv->ref_clk);

	return err;
}
@@ -2589,6 +2606,7 @@ int enetc_close(struct net_device *ndev)
	enetc_assign_tx_resources(priv, NULL);

	enetc_free_irqs(priv);
	clk_disable_unprepare(priv->ref_clk);

	return 0;
}
@@ -3254,5 +3272,55 @@ void enetc_pci_remove(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(enetc_pci_remove);

static const struct enetc_drvdata enetc_pf_data = {
	.sysclk_freq = ENETC_CLK_400M,
	.pmac_offset = ENETC_PMAC_OFFSET,
	.eth_ops = &enetc_pf_ethtool_ops,
};

static const struct enetc_drvdata enetc4_pf_data = {
	.sysclk_freq = ENETC_CLK_333M,
	.pmac_offset = ENETC4_PMAC_OFFSET,
	.eth_ops = &enetc4_pf_ethtool_ops,
};

static const struct enetc_drvdata enetc_vf_data = {
	.sysclk_freq = ENETC_CLK_400M,
	.eth_ops = &enetc_vf_ethtool_ops,
};

static const struct enetc_platform_info enetc_info[] = {
	{ .revision = ENETC_REV_1_0,
	  .dev_id = ENETC_DEV_ID_PF,
	  .data = &enetc_pf_data,
	},
	{ .revision = ENETC_REV_4_1,
	  .dev_id = NXP_ENETC_PF_DEV_ID,
	  .data = &enetc4_pf_data,
	},
	{ .revision = ENETC_REV_1_0,
	  .dev_id = ENETC_DEV_ID_VF,
	  .data = &enetc_vf_data,
	},
};

int enetc_get_driver_data(struct enetc_si *si)
{
	u16 dev_id = si->pdev->device;
	int i;

	for (i = 0; i < ARRAY_SIZE(enetc_info); i++) {
		if (si->revision == enetc_info[i].revision &&
		    dev_id == enetc_info[i].dev_id) {
			si->drvdata = enetc_info[i].data;

			return 0;
		}
	}

	return -ERANGE;
}
EXPORT_SYMBOL_GPL(enetc_get_driver_data);

MODULE_DESCRIPTION("NXP ENETC Ethernet driver");
MODULE_LICENSE("Dual BSD/GPL");
+28 −2
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <net/xdp.h>

#include "enetc_hw.h"
#include "enetc4_hw.h"

#define ENETC_MAC_MAXFRM_SIZE	9600
#define ENETC_MAX_MTU		(ENETC_MAC_MAXFRM_SIZE - \
@@ -231,6 +232,18 @@ enum enetc_errata {
#define ENETC_SI_F_QBV  BIT(1)
#define ENETC_SI_F_QBU  BIT(2)

struct enetc_drvdata {
	u32 pmac_offset; /* Only valid for PSI which supports 802.1Qbu */
	u64 sysclk_freq;
	const struct ethtool_ops *eth_ops;
};

struct enetc_platform_info {
	u16 revision;
	u16 dev_id;
	const struct enetc_drvdata *data;
};

/* PCI IEP device data */
struct enetc_si {
	struct pci_dev *pdev;
@@ -246,11 +259,18 @@ struct enetc_si {
	int num_fs_entries;
	int num_rss; /* number of RSS buckets */
	unsigned short pad;
	u16 revision;
	int hw_features;
	const struct enetc_drvdata *drvdata;
};

#define ENETC_SI_ALIGN	32

static inline bool is_enetc_rev1(struct enetc_si *si)
{
	return si->pdev->revision == ENETC_REV1;
}

static inline void *enetc_si_priv(const struct enetc_si *si)
{
	return (char *)si + ALIGN(sizeof(struct enetc_si), ENETC_SI_ALIGN);
@@ -302,7 +322,7 @@ struct enetc_cls_rule {
	int used;
};

#define ENETC_MAX_BDR_INT	2 /* fixed to max # of available cpus */
#define ENETC_MAX_BDR_INT	6 /* fixed to max # of available cpus */
struct psfp_cap {
	u32 max_streamid;
	u32 max_psfp_filter;
@@ -341,7 +361,6 @@ enum enetc_ic_mode {

#define ENETC_RXIC_PKTTHR	min_t(u32, 256, ENETC_RX_RING_DEFAULT_SIZE / 2)
#define ENETC_TXIC_PKTTHR	min_t(u32, 128, ENETC_TX_RING_DEFAULT_SIZE / 2)
#define ENETC_TXIC_TIMETHR	enetc_usecs_to_cycles(600)

struct enetc_ndev_priv {
	struct net_device *ndev;
@@ -389,6 +408,9 @@ struct enetc_ndev_priv {
	 * and link state updates
	 */
	struct mutex		mm_lock;

	struct clk *ref_clk; /* RGMII/RMII reference clock */
	u64 sysclk_freq; /* NETC system clock frequency */
};

/* Messaging */
@@ -418,6 +440,7 @@ void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
void enetc_free_si_resources(struct enetc_ndev_priv *priv);
int enetc_configure_si(struct enetc_ndev_priv *priv);
int enetc_get_driver_data(struct enetc_si *si);

int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev);
@@ -434,6 +457,9 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
		   struct xdp_frame **frames, u32 flags);

/* ethtool */
extern const struct ethtool_ops enetc_pf_ethtool_ops;
extern const struct ethtool_ops enetc4_pf_ethtool_ops;
extern const struct ethtool_ops enetc_vf_ethtool_ops;
void enetc_set_ethtool_ops(struct net_device *ndev);
void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link);
void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
+155 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/*
 * This header file defines the register offsets and bit fields
 * of ENETC4 PF and VFs. Note that the same registers as ENETC
 * version 1.0 are defined in the enetc_hw.h file.
 *
 * Copyright 2024 NXP
 */
#ifndef __ENETC4_HW_H_
#define __ENETC4_HW_H_

#define NXP_ENETC_VENDOR_ID		0x1131
#define NXP_ENETC_PF_DEV_ID		0xe101

/***************************ENETC port registers**************************/
#define ENETC4_ECAPR0			0x0
#define  ECAPR0_RFS			BIT(2)
#define  ECAPR0_TSD			BIT(5)
#define  ECAPR0_RSS			BIT(8)
#define  ECAPR0_RSC			BIT(9)
#define  ECAPR0_LSO			BIT(10)
#define  ECAPR0_WO			BIT(13)

#define ENETC4_ECAPR1			0x4
#define  ECAPR1_NUM_TCS			GENMASK(6, 4)
#define  ECAPR1_NUM_MCH			GENMASK(9, 8)
#define  ECAPR1_NUM_UCH			GENMASK(11, 10)
#define  ECAPR1_NUM_MSIX		GENMASK(22, 12)
#define  ECAPR1_NUM_VSI			GENMASK(27, 24)
#define  ECAPR1_NUM_IPV			BIT(31)

#define ENETC4_ECAPR2			0x8
#define  ECAPR2_NUM_TX_BDR		GENMASK(9, 0)
#define  ECAPR2_NUM_RX_BDR		GENMASK(25, 16)

#define ENETC4_PMR			0x10
#define  PMR_SI_EN(a)			BIT((16 + (a)))

/* Port Pause ON/OFF threshold register */
#define ENETC4_PPAUONTR			0x108
#define ENETC4_PPAUOFFTR		0x10c

/* Port Station interface promiscuous MAC mode register */
#define ENETC4_PSIPMMR			0x200
#define  PSIPMMR_SI_MAC_UP(a)		BIT(a) /* a = SI index */
#define  PSIPMMR_SI_MAC_MP(a)		BIT((a) + 16)

/* Port Station interface promiscuous VLAN mode register */
#define ENETC4_PSIPVMR			0x204

/* Port RSS key register n. n = 0,1,2,...,9 */
#define ENETC4_PRSSKR(n)		((n) * 0x4 + 0x250)

/* Port station interface MAC address filtering capability register */
#define ENETC4_PSIMAFCAPR		0x280
#define  PSIMAFCAPR_NUM_MAC_AFTE	GENMASK(11, 0)

/* Port station interface VLAN filtering capability register */
#define ENETC4_PSIVLANFCAPR		0x2c0
#define  PSIVLANFCAPR_NUM_VLAN_FTE	GENMASK(11, 0)

/* Port station interface VLAN filtering mode register */
#define ENETC4_PSIVLANFMR		0x2c4
#define  PSIVLANFMR_VS			BIT(0)

/* Port Station interface a primary MAC address registers */
#define ENETC4_PSIPMAR0(a)		((a) * 0x80 + 0x2000)
#define ENETC4_PSIPMAR1(a)		((a) * 0x80 + 0x2004)

/* Port station interface a configuration register 0/2 */
#define ENETC4_PSICFGR0(a)		((a) * 0x80 + 0x2010)
#define  PSICFGR0_VASE			BIT(13)
#define  PSICFGR0_ASE			BIT(15)
#define  PSICFGR0_ANTI_SPOOFING		(PSICFGR0_VASE | PSICFGR0_ASE)

#define ENETC4_PSICFGR2(a)		((a) * 0x80 + 0x2018)
#define  PSICFGR2_NUM_MSIX		GENMASK(5, 0)

#define ENETC4_PMCAPR			0x4004
#define  PMCAPR_HD			BIT(8)
#define  PMCAPR_FP			GENMASK(10, 9)

/* Port configuration register */
#define ENETC4_PCR			0x4010
#define  PCR_HDR_FMT			BIT(0)
#define  PCR_L2DOSE			BIT(4)
#define  PCR_TIMER_CS			BIT(8)
#define  PCR_PSPEED			GENMASK(29, 16)
#define  PCR_PSPEED_VAL(speed)		(((speed) / 10 - 1) << 16)

/* Port MAC address register 0/1 */
#define ENETC4_PMAR0			0x4020
#define ENETC4_PMAR1			0x4024

/* Port operational register */
#define ENETC4_POR			0x4100

/* Port traffic class a transmit maximum SDU register */
#define ENETC4_PTCTMSDUR(a)		((a) * 0x20 + 0x4208)
#define  PTCTMSDUR_MAXSDU		GENMASK(15, 0)
#define  PTCTMSDUR_SDU_TYPE		GENMASK(17, 16)
#define   SDU_TYPE_PPDU			0
#define   SDU_TYPE_MPDU			1
#define   SDU_TYPE_MSDU			2

#define ENETC4_PMAC_OFFSET		0x400
#define ENETC4_PM_CMD_CFG(mac)		(0x5008 + (mac) * 0x400)
#define  PM_CMD_CFG_TX_EN		BIT(0)
#define  PM_CMD_CFG_RX_EN		BIT(1)
#define  PM_CMD_CFG_PAUSE_FWD		BIT(7)
#define  PM_CMD_CFG_PAUSE_IGN		BIT(8)
#define  PM_CMD_CFG_TX_ADDR_INS		BIT(9)
#define  PM_CMD_CFG_LOOP_EN		BIT(10)
#define  PM_CMD_CFG_LPBK_MODE		GENMASK(12, 11)
#define   LPBCK_MODE_EXT_TX_CLK		0
#define   LPBCK_MODE_MAC_LEVEL		1
#define   LPBCK_MODE_INT_TX_CLK		2
#define  PM_CMD_CFG_CNT_FRM_EN		BIT(13)
#define  PM_CMD_CFG_TXP			BIT(15)
#define  PM_CMD_CFG_SEND_IDLE		BIT(16)
#define  PM_CMD_CFG_HD_FCEN		BIT(18)
#define  PM_CMD_CFG_SFD			BIT(21)
#define  PM_CMD_CFG_TX_FLUSH		BIT(22)
#define  PM_CMD_CFG_TX_LOWP_EN		BIT(23)
#define  PM_CMD_CFG_RX_LOWP_EMPTY	BIT(24)
#define  PM_CMD_CFG_SWR			BIT(26)
#define  PM_CMD_CFG_TS_MODE		BIT(30)
#define  PM_CMD_CFG_MG			BIT(31)

/* Port MAC 0/1 Maximum Frame Length Register */
#define ENETC4_PM_MAXFRM(mac)		(0x5014 + (mac) * 0x400)

/* Port MAC 0/1 Pause Quanta Register */
#define ENETC4_PM_PAUSE_QUANTA(mac)	(0x5054 + (mac) * 0x400)

/* Port MAC 0/1 Pause Quanta Threshold Register */
#define ENETC4_PM_PAUSE_THRESH(mac)	(0x5064 + (mac) * 0x400)

/* Port MAC 0 Interface Mode Control Register */
#define ENETC4_PM_IF_MODE(mac)		(0x5300 + (mac) * 0x400)
#define  PM_IF_MODE_IFMODE		GENMASK(2, 0)
#define   IFMODE_XGMII			0
#define   IFMODE_RMII			3
#define   IFMODE_RGMII			4
#define   IFMODE_SGMII			5
#define  PM_IF_MODE_REVMII		BIT(3)
#define  PM_IF_MODE_M10			BIT(4)
#define  PM_IF_MODE_HD			BIT(6)
#define  PM_IF_MODE_SSP			GENMASK(14, 13)
#define   SSP_100M			0
#define   SSP_10M			1
#define   SSP_1G			2
#define  PM_IF_MODE_ENA			BIT(15)

#endif
Loading