Add the compatible string "nxp,imx94-netc-blk-ctrl" for i.MX94 platforms. Signed-off-by: Wei Fang Acked-by: Rob Herring (Arm) --- Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml b/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml index 97389fd5dbbf..deea4fd73d76 100644 --- a/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml +++ b/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml @@ -21,6 +21,7 @@ maintainers: properties: compatible: enum: + - nxp,imx94-netc-blk-ctrl - nxp,imx95-netc-blk-ctrl reg: -- 2.34.1 The ENETC with pseudo MAC is used to connect to the CPU port of the NETC switch. This ENETC has a different PCI device ID, so add a standard PCI device compatible string to it. Signed-off-by: Wei Fang Acked-by: Rob Herring (Arm) --- Documentation/devicetree/bindings/net/fsl,enetc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/net/fsl,enetc.yaml b/Documentation/devicetree/bindings/net/fsl,enetc.yaml index ca70f0050171..aac20ab72ace 100644 --- a/Documentation/devicetree/bindings/net/fsl,enetc.yaml +++ b/Documentation/devicetree/bindings/net/fsl,enetc.yaml @@ -27,6 +27,7 @@ properties: - const: fsl,enetc - enum: - pci1131,e101 + - pci1131,e110 reg: maxItems: 1 -- 2.34.1 NETC blocks control is used for warm reset and pre-boot initialization. Different versions of NETC blocks control are not exactly the same. We need to add corresponding netc_devinfo data for each version. i.MX94 series are launched after i.MX95, so its NETC version (v4.3) is higher than i.MX95 NETC (v4.1). Currently, the patch adds the following configurations for ENETCs. 1. Set the link's MII protocol. 2. ENETC 0 (MAC 3) and the switch port 2 (MAC 2) share the same parallel interface, but due to SoC constraint, they cannot be used simultaneously. Since the switch is not supported yet, so the interface is assigned to ENETC 0 by default. The switch configuration will be added separately in a subsequent patch. Signed-off-by: Wei Fang Reviewed-by: Frank Li --- .../ethernet/freescale/enetc/netc_blk_ctrl.c | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c index bcb8eefeb93c..5978ea096e80 100644 --- a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c @@ -47,6 +47,13 @@ #define PCS_PROT_SFI BIT(4) #define PCS_PROT_10G_SXGMII BIT(6) +#define IMX94_EXT_PIN_CONTROL 0x10 +#define MAC2_MAC3_SEL BIT(1) + +#define IMX94_NETC_LINK_CFG(a) (0x4c + (a) * 4) +#define NETC_LINK_CFG_MII_PROT GENMASK(3, 0) +#define NETC_LINK_CFG_IO_VAR GENMASK(19, 16) + /* NETC privileged register block register */ #define PRB_NETCRR 0x100 #define NETCRR_SR BIT(0) @@ -68,6 +75,13 @@ #define IMX95_ENETC1_BUS_DEVFN 0x40 #define IMX95_ENETC2_BUS_DEVFN 0x80 +#define IMX94_ENETC0_BUS_DEVFN 0x100 +#define IMX94_ENETC1_BUS_DEVFN 0x140 +#define IMX94_ENETC2_BUS_DEVFN 0x180 +#define IMX94_ENETC0_LINK 3 +#define IMX94_ENETC1_LINK 4 +#define IMX94_ENETC2_LINK 5 + /* Flags for different platforms */ #define NETC_HAS_NETCMIX BIT(0) @@ -192,6 +206,90 @@ static int imx95_netcmix_init(struct platform_device *pdev) return 0; } +static int imx94_enetc_get_link_id(struct device_node *np) +{ + int bus_devfn = netc_of_pci_get_bus_devfn(np); + + /* Parse ENETC link number */ + switch (bus_devfn) { + case IMX94_ENETC0_BUS_DEVFN: + return IMX94_ENETC0_LINK; + case IMX94_ENETC1_BUS_DEVFN: + return IMX94_ENETC1_LINK; + case IMX94_ENETC2_BUS_DEVFN: + return IMX94_ENETC2_LINK; + default: + return -EINVAL; + } +} + +static int imx94_link_config(struct netc_blk_ctrl *priv, + struct device_node *np, int link_id) +{ + phy_interface_t interface; + int mii_proto; + u32 val; + + /* The node may be disabled and does not have a 'phy-mode' + * or 'phy-connection-type' property. + */ + if (of_get_phy_mode(np, &interface)) + return 0; + + mii_proto = netc_get_link_mii_protocol(interface); + if (mii_proto < 0) + return mii_proto; + + val = mii_proto & NETC_LINK_CFG_MII_PROT; + if (val == MII_PROT_SERIAL) + val = u32_replace_bits(val, IO_VAR_16FF_16G_SERDES, + NETC_LINK_CFG_IO_VAR); + + netc_reg_write(priv->netcmix, IMX94_NETC_LINK_CFG(link_id), val); + + return 0; +} + +static int imx94_enetc_link_config(struct netc_blk_ctrl *priv, + struct device_node *np) +{ + int link_id = imx94_enetc_get_link_id(np); + + if (link_id < 0) + return link_id; + + return imx94_link_config(priv, np, link_id); +} + +static int imx94_netcmix_init(struct platform_device *pdev) +{ + struct netc_blk_ctrl *priv = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node; + u32 val; + int err; + + for_each_child_of_node_scoped(np, child) { + for_each_child_of_node_scoped(child, gchild) { + if (!of_device_is_compatible(gchild, "pci1131,e101")) + continue; + + err = imx94_enetc_link_config(priv, gchild); + if (err) + return err; + } + } + + /* ENETC 0 and switch port 2 share the same parallel interface. + * Currently, the switch is not supported, so this interface is + * used by ENETC 0 by default. + */ + val = netc_reg_read(priv->netcmix, IMX94_EXT_PIN_CONTROL); + val |= MAC2_MAC3_SEL; + netc_reg_write(priv->netcmix, IMX94_EXT_PIN_CONTROL, val); + + return 0; +} + static bool netc_ierb_is_locked(struct netc_blk_ctrl *priv) { return !!(netc_reg_read(priv->prb, PRB_NETCRR) & NETCRR_LOCK); @@ -340,8 +438,14 @@ static const struct netc_devinfo imx95_devinfo = { .ierb_init = imx95_ierb_init, }; +static const struct netc_devinfo imx94_devinfo = { + .flags = NETC_HAS_NETCMIX, + .netcmix_init = imx94_netcmix_init, +}; + static const struct of_device_id netc_blk_ctrl_match[] = { { .compatible = "nxp,imx95-netc-blk-ctrl", .data = &imx95_devinfo }, + { .compatible = "nxp,imx94-netc-blk-ctrl", .data = &imx94_devinfo }, {}, }; MODULE_DEVICE_TABLE(of, netc_blk_ctrl_match); -- 2.34.1 From: Clark Wang The i.MX94 has three PTP timers, and all standalone ENETCs can select one of them to bind to as their PHC. The 'ptp-timer' property is used to represent the PTP device of the Ethernet controller. So users can add 'ptp-timer' to the ENETC node to specify the PTP timer. The driver parses this property to bind the two hardware devices. If the "ptp-timer" property is not present, the first timer of the PCIe bus where the ENETC is located is used as the default bound PTP timer. Signed-off-by: Clark Wang Signed-off-by: Wei Fang --- .../ethernet/freescale/enetc/netc_blk_ctrl.c | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c index 5978ea096e80..d7aee3c934d3 100644 --- a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c @@ -66,6 +66,7 @@ /* NETC integrated endpoint register block register */ #define IERB_EMDIOFAUXR 0x344 #define IERB_T0FAUXR 0x444 +#define IERB_ETBCR(a) (0x300c + 0x100 * (a)) #define IERB_EFAUXR(a) (0x3044 + 0x100 * (a)) #define IERB_VFAUXR(a) (0x4004 + 0x40 * (a)) #define FAUXR_LDID GENMASK(3, 0) @@ -78,10 +79,16 @@ #define IMX94_ENETC0_BUS_DEVFN 0x100 #define IMX94_ENETC1_BUS_DEVFN 0x140 #define IMX94_ENETC2_BUS_DEVFN 0x180 +#define IMX94_TIMER0_BUS_DEVFN 0x1 +#define IMX94_TIMER1_BUS_DEVFN 0x101 +#define IMX94_TIMER2_BUS_DEVFN 0x181 #define IMX94_ENETC0_LINK 3 #define IMX94_ENETC1_LINK 4 #define IMX94_ENETC2_LINK 5 +#define NETC_ENETC_ID(a) (a) +#define NETC_TIMER_ID(a) (a) + /* Flags for different platforms */ #define NETC_HAS_NETCMIX BIT(0) @@ -345,6 +352,98 @@ static int imx95_ierb_init(struct platform_device *pdev) return 0; } +static int imx94_get_enetc_id(struct device_node *np) +{ + int bus_devfn = netc_of_pci_get_bus_devfn(np); + + /* Parse ENETC offset */ + switch (bus_devfn) { + case IMX94_ENETC0_BUS_DEVFN: + return NETC_ENETC_ID(0); + case IMX94_ENETC1_BUS_DEVFN: + return NETC_ENETC_ID(1); + case IMX94_ENETC2_BUS_DEVFN: + return NETC_ENETC_ID(2); + default: + return -EINVAL; + } +} + +static int imx94_get_timer_id(struct device_node *np) +{ + int bus_devfn = netc_of_pci_get_bus_devfn(np); + + /* Parse NETC PTP timer ID, the timer0 is on bus 0, + * the timer 1 and timer2 is on bus 1. + */ + switch (bus_devfn) { + case IMX94_TIMER0_BUS_DEVFN: + return NETC_TIMER_ID(0); + case IMX94_TIMER1_BUS_DEVFN: + return NETC_TIMER_ID(1); + case IMX94_TIMER2_BUS_DEVFN: + return NETC_TIMER_ID(2); + default: + return -EINVAL; + } +} + +static int imx94_enetc_update_tid(struct netc_blk_ctrl *priv, + struct device_node *np) +{ + struct device *dev = &priv->pdev->dev; + struct device_node *timer_np; + int eid, tid; + + eid = imx94_get_enetc_id(np); + if (eid < 0) { + dev_err(dev, "Failed to get ENETC ID\n"); + return eid; + } + + timer_np = of_parse_phandle(np, "ptp-timer", 0); + if (!timer_np) { + /* If 'ptp-timer' is not present, the timer1 is the default + * timer of all standalone ENETCs, which is on the same PCIe + * bus as these ENETCs. + */ + tid = NETC_TIMER_ID(1); + goto end; + } + + tid = imx94_get_timer_id(timer_np); + of_node_put(timer_np); + if (tid < 0) { + dev_err(dev, "Failed to get NETC Timer ID\n"); + return tid; + } + +end: + netc_reg_write(priv->ierb, IERB_ETBCR(eid), tid); + + return 0; +} + +static int imx94_ierb_init(struct platform_device *pdev) +{ + struct netc_blk_ctrl *priv = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node; + int err; + + for_each_child_of_node_scoped(np, child) { + for_each_child_of_node_scoped(child, gchild) { + if (!of_device_is_compatible(gchild, "pci1131,e101")) + continue; + + err = imx94_enetc_update_tid(priv, gchild); + if (err) + return err; + } + } + + return 0; +} + static int netc_ierb_init(struct platform_device *pdev) { struct netc_blk_ctrl *priv = platform_get_drvdata(pdev); @@ -441,6 +540,7 @@ static const struct netc_devinfo imx95_devinfo = { static const struct netc_devinfo imx94_devinfo = { .flags = NETC_HAS_NETCMIX, .netcmix_init = imx94_netcmix_init, + .ierb_init = imx94_ierb_init, }; static const struct of_device_id netc_blk_ctrl_match[] = { -- 2.34.1 The ENETC with pseudo MAC is an internal port which connects to the CPU port of the switch. The switch CPU/host ENETC is fully integrated with the switch and does not require a back-to-back MAC, instead a light weight "pseudo MAC" provides the delineation between switch and ENETC. This translates to lower power (less logic and memory) and lower delay (as there is no serialization delay across this link). Different from the standalone ENETC which is used as the external port, the internal ENETC has a different PCIe device ID, and it does not have Ethernet MAC port registers, instead, it has a small number of pseudo MAC port registers, so some features are not supported by pseudo MAC, such as loopback, half duplex, one-step timestamping and so on. Therefore, the configuration of this internal ENETC is also somewhat different from that of the standalone ENETC. So add the basic support for ENETC with pseudo MAC. More supports will be added in the future. Signed-off-by: Wei Fang Reviewed-by: Claudiu Manoil --- drivers/net/ethernet/freescale/enetc/enetc.c | 24 +++++++- drivers/net/ethernet/freescale/enetc/enetc.h | 8 +++ .../net/ethernet/freescale/enetc/enetc4_hw.h | 30 +++++++++ .../net/ethernet/freescale/enetc/enetc4_pf.c | 15 +++++ .../ethernet/freescale/enetc/enetc_ethtool.c | 61 +++++++++++++++++++ .../net/ethernet/freescale/enetc/enetc_hw.h | 1 + .../freescale/enetc/enetc_pf_common.c | 5 +- 7 files changed, 142 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 0535e92404e3..3ed0e04eb589 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -14,12 +14,21 @@ u32 enetc_port_mac_rd(struct enetc_si *si, u32 reg) { + /* ENETC with pseudo MAC does not have Ethernet MAC + * port registers. + */ + if (enetc_is_pseudo_mac(si)) + return 0; + return enetc_port_rd(&si->hw, reg); } EXPORT_SYMBOL_GPL(enetc_port_mac_rd); void enetc_port_mac_wr(struct enetc_si *si, u32 reg, u32 val) { + if (enetc_is_pseudo_mac(si)) + return; + enetc_port_wr(&si->hw, reg, val); if (si->hw_features & ENETC_SI_F_QBU) enetc_port_wr(&si->hw, reg + si->drvdata->pmac_offset, val); @@ -3367,7 +3376,8 @@ int enetc_hwtstamp_set(struct net_device *ndev, new_offloads |= ENETC_F_TX_TSTAMP; break; case HWTSTAMP_TX_ONESTEP_SYNC: - if (!enetc_si_is_pf(priv->si)) + if (!enetc_si_is_pf(priv->si) || + enetc_is_pseudo_mac(priv->si)) return -EOPNOTSUPP; new_offloads &= ~ENETC_F_TX_TSTAMP_MASK; @@ -3708,6 +3718,13 @@ static const struct enetc_drvdata enetc4_pf_data = { .eth_ops = &enetc4_pf_ethtool_ops, }; +static const struct enetc_drvdata enetc4_ppm_data = { + .sysclk_freq = ENETC_CLK_333M, + .tx_csum = true, + .max_frags = ENETC4_MAX_SKB_FRAGS, + .eth_ops = &enetc4_ppm_ethtool_ops, +}; + static const struct enetc_drvdata enetc_vf_data = { .sysclk_freq = ENETC_CLK_400M, .max_frags = ENETC_MAX_SKB_FRAGS, @@ -3727,6 +3744,11 @@ static const struct enetc_platform_info enetc_info[] = { .dev_id = ENETC_DEV_ID_VF, .data = &enetc_vf_data, }, + { + .revision = ENETC_REV_4_3, + .dev_id = NXP_ENETC_PPM_DEV_ID, + .data = &enetc4_ppm_data, + }, }; int enetc_get_driver_data(struct enetc_si *si) diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index f279fa597991..dce27bd67a7d 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -273,6 +273,7 @@ enum enetc_errata { #define ENETC_SI_F_QBV BIT(1) #define ENETC_SI_F_QBU BIT(2) #define ENETC_SI_F_LSO BIT(3) +#define ENETC_SI_F_PPM BIT(4) /* pseudo MAC */ struct enetc_drvdata { u32 pmac_offset; /* Only valid for PSI which supports 802.1Qbu */ @@ -362,6 +363,11 @@ static inline int enetc_pf_to_port(struct pci_dev *pf_pdev) } } +static inline bool enetc_is_pseudo_mac(struct enetc_si *si) +{ + return si->hw_features & ENETC_SI_F_PPM; +} + #define ENETC_MAX_NUM_TXQS 8 #define ENETC_INT_NAME_MAX (IFNAMSIZ + 8) @@ -534,6 +540,8 @@ int enetc_hwtstamp_set(struct net_device *ndev, 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; +extern const struct ethtool_ops enetc4_ppm_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); diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h index 19bf0e89cdc2..ebea4298791c 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h @@ -11,6 +11,7 @@ #define NXP_ENETC_VENDOR_ID 0x1131 #define NXP_ENETC_PF_DEV_ID 0xe101 +#define NXP_ENETC_PPM_DEV_ID 0xe110 /**********************Station interface registers************************/ /* Station interface LSO segmentation flag mask register 0/1 */ @@ -115,6 +116,10 @@ #define PMCAPR_HD BIT(8) #define PMCAPR_FP GENMASK(10, 9) +/* Port capability register */ +#define ENETC4_PCAPR 0x4000 +#define PCAPR_LINK_TYPE BIT(4) + /* Port configuration register */ #define ENETC4_PCR 0x4010 #define PCR_HDR_FMT BIT(0) @@ -193,4 +198,29 @@ #define SSP_1G 2 #define PM_IF_MODE_ENA BIT(15) +/**********************ENETC Pseudo MAC port registers************************/ +/* Port pseudo MAC receive octets counter (64-bit) */ +#define ENETC4_PPMROCR 0x5080 + +/* Port pseudo MAC receive unicast frame counter register (64-bit) */ +#define ENETC4_PPMRUFCR 0x5088 + +/* Port pseudo MAC receive multicast frame counter register (64-bit) */ +#define ENETC4_PPMRMFCR 0x5090 + +/* Port pseudo MAC receive broadcast frame counter register (64-bit) */ +#define ENETC4_PPMRBFCR 0x5098 + +/* Port pseudo MAC transmit octets counter (64-bit) */ +#define ENETC4_PPMTOCR 0x50c0 + +/* Port pseudo MAC transmit unicast frame counter register (64-bit) */ +#define ENETC4_PPMTUFCR 0x50c8 + +/* Port pseudo MAC transmit multicast frame counter register (64-bit) */ +#define ENETC4_PPMTMFCR 0x50d0 + +/* Port pseudo MAC transmit broadcast frame counter register (64-bit) */ +#define ENETC4_PPMTBFCR 0x50d8 + #endif diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c index 82c443b28b15..498346dd996a 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c @@ -41,6 +41,16 @@ static void enetc4_get_port_caps(struct enetc_pf *pf) pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE; } +static void enetc4_get_psi_hw_features(struct enetc_si *si) +{ + struct enetc_hw *hw = &si->hw; + u32 val; + + val = enetc_port_rd(hw, ENETC4_PCAPR); + if (val & PCAPR_LINK_TYPE) + si->hw_features |= ENETC_SI_F_PPM; +} + static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si, const u8 *addr) { @@ -277,6 +287,7 @@ static int enetc4_pf_struct_init(struct enetc_si *si) pf->ops = &enetc4_pf_ops; enetc4_get_port_caps(pf); + enetc4_get_psi_hw_features(si); return 0; } @@ -589,6 +600,9 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode, struct enetc_si *si = pf->si; u32 val; + if (enetc_is_pseudo_mac(si)) + return; + val = enetc_port_mac_rd(si, ENETC4_PM_IF_MODE(0)); val &= ~(PM_IF_MODE_IFMODE | PM_IF_MODE_ENA); @@ -1071,6 +1085,7 @@ static void enetc4_pf_remove(struct pci_dev *pdev) static const struct pci_device_id enetc4_pf_id_table[] = { { PCI_DEVICE(NXP_ENETC_VENDOR_ID, NXP_ENETC_PF_DEV_ID) }, + { PCI_DEVICE(NXP_ENETC_VENDOR_ID, NXP_ENETC_PPM_DEV_ID) }, { 0, } /* End of table. */ }; MODULE_DEVICE_TABLE(pci, enetc4_pf_id_table); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c index 71d052de669a..5ef2c5f3ff8f 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c @@ -435,6 +435,48 @@ static void enetc_get_eth_mac_stats(struct net_device *ndev, } } +static void enetc_ppm_mac_stats(struct enetc_si *si, + struct ethtool_eth_mac_stats *s) +{ + struct enetc_hw *hw = &si->hw; + u64 rufcr, rmfcr, rbfcr; + u64 tufcr, tmfcr, tbfcr; + + rufcr = enetc_port_rd64(hw, ENETC4_PPMRUFCR); + rmfcr = enetc_port_rd64(hw, ENETC4_PPMRMFCR); + rbfcr = enetc_port_rd64(hw, ENETC4_PPMRBFCR); + + tufcr = enetc_port_rd64(hw, ENETC4_PPMTUFCR); + tmfcr = enetc_port_rd64(hw, ENETC4_PPMTMFCR); + tbfcr = enetc_port_rd64(hw, ENETC4_PPMTBFCR); + + s->FramesTransmittedOK = tufcr + tmfcr + tbfcr; + s->FramesReceivedOK = rufcr + rmfcr + rbfcr; + s->OctetsTransmittedOK = enetc_port_rd64(hw, ENETC4_PPMTOCR); + s->OctetsReceivedOK = enetc_port_rd64(hw, ENETC4_PPMROCR); + s->MulticastFramesXmittedOK = tmfcr; + s->BroadcastFramesXmittedOK = tbfcr; + s->MulticastFramesReceivedOK = rmfcr; + s->BroadcastFramesReceivedOK = rbfcr; +} + +static void enetc_ppm_get_eth_mac_stats(struct net_device *ndev, + struct ethtool_eth_mac_stats *mac_stats) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + switch (mac_stats->src) { + case ETHTOOL_MAC_STATS_SRC_EMAC: + enetc_ppm_mac_stats(priv->si, mac_stats); + break; + case ETHTOOL_MAC_STATS_SRC_PMAC: + break; + case ETHTOOL_MAC_STATS_SRC_AGGREGATE: + ethtool_aggregate_mac_stats(ndev, mac_stats); + break; + } +} + static void enetc_get_eth_ctrl_stats(struct net_device *ndev, struct ethtool_eth_ctrl_stats *ctrl_stats) { @@ -1313,6 +1355,25 @@ const struct ethtool_ops enetc_pf_ethtool_ops = { .get_mm_stats = enetc_get_mm_stats, }; +const struct ethtool_ops enetc4_ppm_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_MAX_FRAMES | + ETHTOOL_COALESCE_USE_ADAPTIVE_RX, + .get_eth_mac_stats = enetc_ppm_get_eth_mac_stats, + .get_rxnfc = enetc4_get_rxnfc, + .get_rxfh_key_size = enetc_get_rxfh_key_size, + .get_rxfh_indir_size = enetc_get_rxfh_indir_size, + .get_rxfh = enetc_get_rxfh, + .set_rxfh = enetc_set_rxfh, + .get_rxfh_fields = enetc_get_rxfh_fields, + .get_ringparam = enetc_get_ringparam, + .get_coalesce = enetc_get_coalesce, + .set_coalesce = enetc_set_coalesce, + .get_link_ksettings = enetc_get_link_ksettings, + .set_link_ksettings = enetc_set_link_ksettings, + .get_link = ethtool_op_get_link, +}; + const struct ethtool_ops enetc_vf_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES | diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h index 377c96325814..7b882b8921fe 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -378,6 +378,7 @@ enum enetc_bdr_type {TX, RX}; #define EIPBRR0_REVISION GENMASK(15, 0) #define ENETC_REV_1_0 0x0100 #define ENETC_REV_4_1 0X0401 +#define ENETC_REV_4_3 0x0403 #define ENETC_G_EIPBRR1 0x0bfc #define ENETC_G_EPFBLPR(n) (0xd00 + 4 * (n)) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c index edf14a95cab7..9c634205e2a7 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c @@ -109,7 +109,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK | + NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4; ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM | @@ -133,6 +133,9 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, ndev->features |= NETIF_F_RXHASH; } + if (!enetc_is_pseudo_mac(si)) + ndev->hw_features |= NETIF_F_LOOPBACK; + /* TODO: currently, i.MX95 ENETC driver does not support advanced features */ if (!is_enetc_rev1(si)) goto end; -- 2.34.1 The revision of i.MX94 ENETC is changed to v4.3, so add this revision to enetc_info to support i.MX94 ENETC. And add PTP suspport for i.MX94. Signed-off-by: Wei Fang Reviewed-by: Frank Li --- drivers/net/ethernet/freescale/enetc/enetc.c | 4 ++++ drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 3ed0e04eb589..d5e5800b84ef 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -3749,6 +3749,10 @@ static const struct enetc_platform_info enetc_info[] = { .dev_id = NXP_ENETC_PPM_DEV_ID, .data = &enetc4_ppm_data, }, + { .revision = ENETC_REV_4_3, + .dev_id = NXP_ENETC_PF_DEV_ID, + .data = &enetc4_pf_data, + }, }; int enetc_get_driver_data(struct enetc_si *si) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c index 5ef2c5f3ff8f..3e222321b937 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c @@ -936,6 +936,9 @@ static int enetc_get_phc_index_by_pdev(struct enetc_si *si) case ENETC_REV_4_1: devfn = PCI_DEVFN(24, 0); break; + case ENETC_REV_4_3: + devfn = PCI_DEVFN(0, 1); + break; default: return -1; } -- 2.34.1