Merge branch 'stmmac-100GB-Enterprise-MAC-support'
Jose Abreu says: ==================== net: stmmac: 100GB Enterprise MAC support Adds the support for Enterprise MAC IP version which allows operating speeds up to 100GB. Patch 1/4, adds the support in XPCS for XLGMII interface that is used in this kind of Enterprise MAC IPs. Patch 2/4, adds the XLGMII interface support in stmmac. Patch 3/4, adds the HW specific support for Enterprise MAC. We end in patch 4/4, by updating stmmac documentation to mention the support for this new IP version. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0419c450e1
|
@ -32,7 +32,8 @@ is also supported.
|
|||
DesignWare(R) Cores Ethernet MAC 10/100/1000 Universal version 3.70a
|
||||
(and older) and DesignWare(R) Cores Ethernet Quality-of-Service version 4.0
|
||||
(and upper) have been used for developing this driver as well as
|
||||
DesignWare(R) Cores XGMAC - 10G Ethernet MAC.
|
||||
DesignWare(R) Cores XGMAC - 10G Ethernet MAC and DesignWare(R) Cores
|
||||
Enterprise MAC - 100G Ethernet MAC.
|
||||
|
||||
This driver supports both the platform bus and PCI.
|
||||
|
||||
|
@ -48,6 +49,8 @@ Cores Ethernet Controllers and corresponding minimum and maximum versions:
|
|||
+-------------------------------+--------------+--------------+--------------+
|
||||
| XGMAC - 10G Ethernet MAC | 2.10a | N/A | XGMAC2+ |
|
||||
+-------------------------------+--------------+--------------+--------------+
|
||||
| XLGMAC - 100G Ethernet MAC | 2.00a | N/A | XLGMAC2+ |
|
||||
+-------------------------------+--------------+--------------+--------------+
|
||||
|
||||
For questions related to hardware requirements, refer to the documentation
|
||||
supplied with your Ethernet adapter. All hardware requirements listed apply
|
||||
|
@ -57,7 +60,7 @@ Feature List
|
|||
============
|
||||
|
||||
The following features are available in this driver:
|
||||
- GMII/MII/RGMII/SGMII/RMII/XGMII Interface
|
||||
- GMII/MII/RGMII/SGMII/RMII/XGMII/XLGMII Interface
|
||||
- Half-Duplex / Full-Duplex Operation
|
||||
- Energy Efficient Ethernet (EEE)
|
||||
- IEEE 802.3x PAUSE Packets (Flow Control)
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
#define DWMAC_CORE_5_00 0x50
|
||||
#define DWMAC_CORE_5_10 0x51
|
||||
#define DWXGMAC_CORE_2_10 0x21
|
||||
#define DWXLGMAC_CORE_2_00 0x20
|
||||
|
||||
/* Device ID */
|
||||
#define DWXGMAC_ID 0x76
|
||||
#define DWXLGMAC_ID 0x27
|
||||
|
||||
#define STMMAC_CHAN0 0 /* Always supported and default for all chips */
|
||||
|
||||
|
@ -426,6 +431,12 @@ struct mac_link {
|
|||
u32 speed5000;
|
||||
u32 speed10000;
|
||||
} xgmii;
|
||||
struct {
|
||||
u32 speed25000;
|
||||
u32 speed40000;
|
||||
u32 speed50000;
|
||||
u32 speed100000;
|
||||
} xlgmii;
|
||||
};
|
||||
|
||||
struct mii_regs {
|
||||
|
@ -459,6 +470,7 @@ struct mac_device_info {
|
|||
unsigned int pcs;
|
||||
unsigned int pmt;
|
||||
unsigned int ps;
|
||||
unsigned int xlgmac;
|
||||
};
|
||||
|
||||
struct stmmac_rx_routing {
|
||||
|
@ -470,6 +482,7 @@ int dwmac100_setup(struct stmmac_priv *priv);
|
|||
int dwmac1000_setup(struct stmmac_priv *priv);
|
||||
int dwmac4_setup(struct stmmac_priv *priv);
|
||||
int dwxgmac2_setup(struct stmmac_priv *priv);
|
||||
int dwxlgmac2_setup(struct stmmac_priv *priv);
|
||||
|
||||
void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
|
||||
unsigned int high, unsigned int low);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include "stmmac.h"
|
||||
#include "stmmac_ptp.h"
|
||||
#include "dwxlgmac2.h"
|
||||
#include "dwxgmac2.h"
|
||||
|
||||
static void dwxgmac2_core_init(struct mac_device_info *hw,
|
||||
|
@ -1485,6 +1486,67 @@ const struct stmmac_ops dwxgmac210_ops = {
|
|||
.fpe_configure = dwxgmac3_fpe_configure,
|
||||
};
|
||||
|
||||
static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
|
||||
u32 queue)
|
||||
{
|
||||
void __iomem *ioaddr = hw->pcsr;
|
||||
u32 value;
|
||||
|
||||
value = readl(ioaddr + XLGMAC_RXQ_ENABLE_CTRL0) & ~XGMAC_RXQEN(queue);
|
||||
if (mode == MTL_QUEUE_AVB)
|
||||
value |= 0x1 << XGMAC_RXQEN_SHIFT(queue);
|
||||
else if (mode == MTL_QUEUE_DCB)
|
||||
value |= 0x2 << XGMAC_RXQEN_SHIFT(queue);
|
||||
writel(value, ioaddr + XLGMAC_RXQ_ENABLE_CTRL0);
|
||||
}
|
||||
|
||||
const struct stmmac_ops dwxlgmac2_ops = {
|
||||
.core_init = dwxgmac2_core_init,
|
||||
.set_mac = dwxgmac2_set_mac,
|
||||
.rx_ipc = dwxgmac2_rx_ipc,
|
||||
.rx_queue_enable = dwxlgmac2_rx_queue_enable,
|
||||
.rx_queue_prio = dwxgmac2_rx_queue_prio,
|
||||
.tx_queue_prio = dwxgmac2_tx_queue_prio,
|
||||
.rx_queue_routing = NULL,
|
||||
.prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms,
|
||||
.prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms,
|
||||
.set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight,
|
||||
.map_mtl_to_dma = dwxgmac2_map_mtl_to_dma,
|
||||
.config_cbs = dwxgmac2_config_cbs,
|
||||
.dump_regs = dwxgmac2_dump_regs,
|
||||
.host_irq_status = dwxgmac2_host_irq_status,
|
||||
.host_mtl_irq_status = dwxgmac2_host_mtl_irq_status,
|
||||
.flow_ctrl = dwxgmac2_flow_ctrl,
|
||||
.pmt = dwxgmac2_pmt,
|
||||
.set_umac_addr = dwxgmac2_set_umac_addr,
|
||||
.get_umac_addr = dwxgmac2_get_umac_addr,
|
||||
.set_eee_mode = dwxgmac2_set_eee_mode,
|
||||
.reset_eee_mode = dwxgmac2_reset_eee_mode,
|
||||
.set_eee_timer = dwxgmac2_set_eee_timer,
|
||||
.set_eee_pls = dwxgmac2_set_eee_pls,
|
||||
.pcs_ctrl_ane = NULL,
|
||||
.pcs_rane = NULL,
|
||||
.pcs_get_adv_lp = NULL,
|
||||
.debug = NULL,
|
||||
.set_filter = dwxgmac2_set_filter,
|
||||
.safety_feat_config = dwxgmac3_safety_feat_config,
|
||||
.safety_feat_irq_status = dwxgmac3_safety_feat_irq_status,
|
||||
.safety_feat_dump = dwxgmac3_safety_feat_dump,
|
||||
.set_mac_loopback = dwxgmac2_set_mac_loopback,
|
||||
.rss_configure = dwxgmac2_rss_configure,
|
||||
.update_vlan_hash = dwxgmac2_update_vlan_hash,
|
||||
.rxp_config = dwxgmac3_rxp_config,
|
||||
.get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp,
|
||||
.flex_pps_config = dwxgmac2_flex_pps_config,
|
||||
.sarc_configure = dwxgmac2_sarc_configure,
|
||||
.enable_vlan = dwxgmac2_enable_vlan,
|
||||
.config_l3_filter = dwxgmac2_config_l3_filter,
|
||||
.config_l4_filter = dwxgmac2_config_l4_filter,
|
||||
.set_arp_offload = dwxgmac2_set_arp_offload,
|
||||
.est_configure = dwxgmac3_est_configure,
|
||||
.fpe_configure = dwxgmac3_fpe_configure,
|
||||
};
|
||||
|
||||
int dwxgmac2_setup(struct stmmac_priv *priv)
|
||||
{
|
||||
struct mac_device_info *mac = priv->hw;
|
||||
|
@ -1521,3 +1583,40 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dwxlgmac2_setup(struct stmmac_priv *priv)
|
||||
{
|
||||
struct mac_device_info *mac = priv->hw;
|
||||
|
||||
dev_info(priv->device, "\tXLGMAC\n");
|
||||
|
||||
priv->dev->priv_flags |= IFF_UNICAST_FLT;
|
||||
mac->pcsr = priv->ioaddr;
|
||||
mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
|
||||
mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
|
||||
mac->mcast_bits_log2 = 0;
|
||||
|
||||
if (mac->multicast_filter_bins)
|
||||
mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
|
||||
|
||||
mac->link.duplex = 0;
|
||||
mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
|
||||
mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
|
||||
mac->link.xgmii.speed10000 = XLGMAC_CONFIG_SS_10G;
|
||||
mac->link.xlgmii.speed25000 = XLGMAC_CONFIG_SS_25G;
|
||||
mac->link.xlgmii.speed40000 = XLGMAC_CONFIG_SS_40G;
|
||||
mac->link.xlgmii.speed50000 = XLGMAC_CONFIG_SS_50G;
|
||||
mac->link.xlgmii.speed100000 = XLGMAC_CONFIG_SS_100G;
|
||||
mac->link.speed_mask = XLGMAC_CONFIG_SS;
|
||||
|
||||
mac->mii.addr = XGMAC_MDIO_ADDR;
|
||||
mac->mii.data = XGMAC_MDIO_DATA;
|
||||
mac->mii.addr_shift = 16;
|
||||
mac->mii.addr_mask = GENMASK(20, 16);
|
||||
mac->mii.reg_shift = 0;
|
||||
mac->mii.reg_mask = GENMASK(15, 0);
|
||||
mac->mii.clk_csr_shift = 19;
|
||||
mac->mii.clk_csr_mask = GENMASK(21, 19);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2020 Synopsys, Inc. and/or its affiliates.
|
||||
* Synopsys DesignWare XLGMAC definitions.
|
||||
*/
|
||||
|
||||
#ifndef __STMMAC_DWXLGMAC2_H__
|
||||
#define __STMMAC_DWXLGMAC2_H__
|
||||
|
||||
/* MAC Registers */
|
||||
#define XLGMAC_CONFIG_SS GENMASK(30, 28)
|
||||
#define XLGMAC_CONFIG_SS_SHIFT 28
|
||||
#define XLGMAC_CONFIG_SS_40G (0x0 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_CONFIG_SS_25G (0x1 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_CONFIG_SS_50G (0x2 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_CONFIG_SS_100G (0x3 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_CONFIG_SS_10G (0x4 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_CONFIG_SS_2500 (0x6 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_CONFIG_SS_1000 (0x7 << XLGMAC_CONFIG_SS_SHIFT)
|
||||
#define XLGMAC_RXQ_ENABLE_CTRL0 0x00000140
|
||||
|
||||
#endif /* __STMMAC_DWXLGMAC2_H__ */
|
|
@ -23,6 +23,18 @@ static u32 stmmac_get_id(struct stmmac_priv *priv, u32 id_reg)
|
|||
return reg & GENMASK(7, 0);
|
||||
}
|
||||
|
||||
static u32 stmmac_get_dev_id(struct stmmac_priv *priv, u32 id_reg)
|
||||
{
|
||||
u32 reg = readl(priv->ioaddr + id_reg);
|
||||
|
||||
if (!reg) {
|
||||
dev_info(priv->device, "Version ID not available\n");
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
return (reg & GENMASK(15, 8)) >> 8;
|
||||
}
|
||||
|
||||
static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
|
||||
{
|
||||
struct mac_device_info *mac = priv->hw;
|
||||
|
@ -69,11 +81,18 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int stmmac_dwxlgmac_quirks(struct stmmac_priv *priv)
|
||||
{
|
||||
priv->hw->xlgmac = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct stmmac_hwif_entry {
|
||||
bool gmac;
|
||||
bool gmac4;
|
||||
bool xgmac;
|
||||
u32 min_id;
|
||||
u32 dev_id;
|
||||
const struct stmmac_regs_off regs;
|
||||
const void *desc;
|
||||
const void *dma;
|
||||
|
@ -199,6 +218,7 @@ static const struct stmmac_hwif_entry {
|
|||
.gmac4 = false,
|
||||
.xgmac = true,
|
||||
.min_id = DWXGMAC_CORE_2_10,
|
||||
.dev_id = DWXGMAC_ID,
|
||||
.regs = {
|
||||
.ptp_off = PTP_XGMAC_OFFSET,
|
||||
.mmc_off = MMC_XGMAC_OFFSET,
|
||||
|
@ -212,6 +232,25 @@ static const struct stmmac_hwif_entry {
|
|||
.mmc = &dwxgmac_mmc_ops,
|
||||
.setup = dwxgmac2_setup,
|
||||
.quirks = NULL,
|
||||
}, {
|
||||
.gmac = false,
|
||||
.gmac4 = false,
|
||||
.xgmac = true,
|
||||
.min_id = DWXLGMAC_CORE_2_00,
|
||||
.dev_id = DWXLGMAC_ID,
|
||||
.regs = {
|
||||
.ptp_off = PTP_XGMAC_OFFSET,
|
||||
.mmc_off = MMC_XGMAC_OFFSET,
|
||||
},
|
||||
.desc = &dwxgmac210_desc_ops,
|
||||
.dma = &dwxgmac210_dma_ops,
|
||||
.mac = &dwxlgmac2_ops,
|
||||
.hwtimestamp = &stmmac_ptp,
|
||||
.mode = NULL,
|
||||
.tc = &dwmac510_tc_ops,
|
||||
.mmc = &dwxgmac_mmc_ops,
|
||||
.setup = dwxlgmac2_setup,
|
||||
.quirks = stmmac_dwxlgmac_quirks,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -223,13 +262,15 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
|
|||
const struct stmmac_hwif_entry *entry;
|
||||
struct mac_device_info *mac;
|
||||
bool needs_setup = true;
|
||||
u32 id, dev_id = 0;
|
||||
int i, ret;
|
||||
u32 id;
|
||||
|
||||
if (needs_gmac) {
|
||||
id = stmmac_get_id(priv, GMAC_VERSION);
|
||||
} else if (needs_gmac4 || needs_xgmac) {
|
||||
id = stmmac_get_id(priv, GMAC4_VERSION);
|
||||
if (needs_xgmac)
|
||||
dev_id = stmmac_get_dev_id(priv, GMAC4_VERSION);
|
||||
} else {
|
||||
id = 0;
|
||||
}
|
||||
|
@ -267,6 +308,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
|
|||
/* Use synopsys_id var because some setups can override this */
|
||||
if (priv->synopsys_id < entry->min_id)
|
||||
continue;
|
||||
if (needs_xgmac && (dev_id ^ entry->dev_id))
|
||||
continue;
|
||||
|
||||
/* Only use generic HW helpers if needed */
|
||||
mac->desc = mac->desc ? : entry->desc;
|
||||
|
|
|
@ -605,6 +605,7 @@ extern const struct stmmac_dma_ops dwmac410_dma_ops;
|
|||
extern const struct stmmac_ops dwmac510_ops;
|
||||
extern const struct stmmac_tc_ops dwmac510_tc_ops;
|
||||
extern const struct stmmac_ops dwxgmac210_ops;
|
||||
extern const struct stmmac_ops dwxlgmac2_ops;
|
||||
extern const struct stmmac_dma_ops dwxgmac210_dma_ops;
|
||||
extern const struct stmmac_desc_ops dwxgmac210_desc_ops;
|
||||
extern const struct stmmac_mmc_ops dwmac_mmc_ops;
|
||||
|
|
|
@ -849,6 +849,38 @@ static void stmmac_validate(struct phylink_config *config,
|
|||
phylink_set(mac_supported, 10000baseKX4_Full);
|
||||
phylink_set(mac_supported, 10000baseKR_Full);
|
||||
}
|
||||
if (!max_speed || (max_speed >= 25000)) {
|
||||
phylink_set(mac_supported, 25000baseCR_Full);
|
||||
phylink_set(mac_supported, 25000baseKR_Full);
|
||||
phylink_set(mac_supported, 25000baseSR_Full);
|
||||
}
|
||||
if (!max_speed || (max_speed >= 40000)) {
|
||||
phylink_set(mac_supported, 40000baseKR4_Full);
|
||||
phylink_set(mac_supported, 40000baseCR4_Full);
|
||||
phylink_set(mac_supported, 40000baseSR4_Full);
|
||||
phylink_set(mac_supported, 40000baseLR4_Full);
|
||||
}
|
||||
if (!max_speed || (max_speed >= 50000)) {
|
||||
phylink_set(mac_supported, 50000baseCR2_Full);
|
||||
phylink_set(mac_supported, 50000baseKR2_Full);
|
||||
phylink_set(mac_supported, 50000baseSR2_Full);
|
||||
phylink_set(mac_supported, 50000baseKR_Full);
|
||||
phylink_set(mac_supported, 50000baseSR_Full);
|
||||
phylink_set(mac_supported, 50000baseCR_Full);
|
||||
phylink_set(mac_supported, 50000baseLR_ER_FR_Full);
|
||||
phylink_set(mac_supported, 50000baseDR_Full);
|
||||
}
|
||||
if (!max_speed || (max_speed >= 100000)) {
|
||||
phylink_set(mac_supported, 100000baseKR4_Full);
|
||||
phylink_set(mac_supported, 100000baseSR4_Full);
|
||||
phylink_set(mac_supported, 100000baseCR4_Full);
|
||||
phylink_set(mac_supported, 100000baseLR4_ER4_Full);
|
||||
phylink_set(mac_supported, 100000baseKR2_Full);
|
||||
phylink_set(mac_supported, 100000baseSR2_Full);
|
||||
phylink_set(mac_supported, 100000baseCR2_Full);
|
||||
phylink_set(mac_supported, 100000baseLR2_ER2_FR2_Full);
|
||||
phylink_set(mac_supported, 100000baseDR2_Full);
|
||||
}
|
||||
}
|
||||
|
||||
/* Half-Duplex can only work with single queue */
|
||||
|
@ -929,6 +961,32 @@ static void stmmac_mac_link_up(struct phylink_config *config,
|
|||
default:
|
||||
return;
|
||||
}
|
||||
} else if (interface == PHY_INTERFACE_MODE_XLGMII) {
|
||||
switch (speed) {
|
||||
case SPEED_100000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed100000;
|
||||
break;
|
||||
case SPEED_50000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed50000;
|
||||
break;
|
||||
case SPEED_40000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed40000;
|
||||
break;
|
||||
case SPEED_25000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed25000;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
ctrl |= priv->hw->link.xgmii.speed10000;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
ctrl |= priv->hw->link.speed2500;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ctrl |= priv->hw->link.speed1000;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch (speed) {
|
||||
case SPEED_2500:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#define SYNOPSYS_XPCS_USXGMII_ID 0x7996ced0
|
||||
#define SYNOPSYS_XPCS_10GKR_ID 0x7996ced0
|
||||
#define SYNOPSYS_XPCS_XLGMII_ID 0x7996ced0
|
||||
#define SYNOPSYS_XPCS_MASK 0xffffffff
|
||||
|
||||
/* Vendor regs access */
|
||||
|
@ -74,6 +75,36 @@ static const int xpcs_10gkr_features[] = {
|
|||
__ETHTOOL_LINK_MODE_MASK_NBITS,
|
||||
};
|
||||
|
||||
static const int xpcs_xlgmii_features[] = {
|
||||
ETHTOOL_LINK_MODE_Pause_BIT,
|
||||
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
|
||||
ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_usxgmii_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_USXGMII,
|
||||
PHY_INTERFACE_MODE_MAX,
|
||||
|
@ -84,6 +115,11 @@ static const phy_interface_t xpcs_10gkr_interfaces[] = {
|
|||
PHY_INTERFACE_MODE_MAX,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_xlgmii_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_XLGMII,
|
||||
PHY_INTERFACE_MODE_MAX,
|
||||
};
|
||||
|
||||
static struct xpcs_id {
|
||||
u32 id;
|
||||
u32 mask;
|
||||
|
@ -100,6 +136,11 @@ static struct xpcs_id {
|
|||
.mask = SYNOPSYS_XPCS_MASK,
|
||||
.supported = xpcs_10gkr_features,
|
||||
.interface = xpcs_10gkr_interfaces,
|
||||
}, {
|
||||
.id = SYNOPSYS_XPCS_XLGMII_ID,
|
||||
.mask = SYNOPSYS_XPCS_MASK,
|
||||
.supported = xpcs_xlgmii_features,
|
||||
.interface = xpcs_xlgmii_interfaces,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -458,6 +499,60 @@ static void xpcs_resolve_lpa(struct mdio_xpcs_args *xpcs,
|
|||
state->duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
static int xpcs_get_max_xlgmii_speed(struct mdio_xpcs_args *xpcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
unsigned long *adv = state->advertising;
|
||||
int speed = SPEED_UNKNOWN;
|
||||
int bit;
|
||||
|
||||
for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) {
|
||||
int new_speed = SPEED_UNKNOWN;
|
||||
|
||||
switch (bit) {
|
||||
case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
|
||||
new_speed = SPEED_25000;
|
||||
break;
|
||||
case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
|
||||
new_speed = SPEED_40000;
|
||||
break;
|
||||
case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT:
|
||||
new_speed = SPEED_50000;
|
||||
break;
|
||||
case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT:
|
||||
case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT:
|
||||
new_speed = SPEED_100000;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (new_speed > speed)
|
||||
speed = new_speed;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
static void xpcs_resolve_pma(struct mdio_xpcs_args *xpcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
|
@ -468,6 +563,9 @@ static void xpcs_resolve_pma(struct mdio_xpcs_args *xpcs,
|
|||
case PHY_INTERFACE_MODE_10GKR:
|
||||
state->speed = SPEED_10000;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_XLGMII:
|
||||
state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
|
||||
break;
|
||||
default:
|
||||
state->speed = SPEED_UNKNOWN;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue