This patch add support for (10G) high speed mac, usxgmii pcs and usxgmii interface in Cadence ethernet controller driver.
Signed-off-by: Parshuram Thombare <pthom...@cadence.com> --- drivers/net/ethernet/cadence/macb.h | 33 +++++++++ drivers/net/ethernet/cadence/macb_main.c | 110 ++++++++++++++++++++++++++++-- include/linux/phy.h | 3 + 3 files changed, 140 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 59c23e0..34df014 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -84,6 +84,7 @@ #define GEM_USRIO 0x000c /* User IO */ #define GEM_DMACFG 0x0010 /* DMA Configuration */ #define GEM_JML 0x0048 /* Jumbo Max Length */ +#define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */ #define GEM_HRB 0x0080 /* Hash Bottom */ #define GEM_HRT 0x0084 /* Hash Top */ #define GEM_SA1B 0x0088 /* Specific1 Bottom */ @@ -168,6 +169,9 @@ #define GEM_DCFG7 0x0298 /* Design Config 7 */ #define GEM_DCFG8 0x029C /* Design Config 8 */ #define GEM_DCFG10 0x02A4 /* Design Config 10 */ +#define GEM_DCFG12 0x02AC /* Design Config 12 */ +#define GEM_USX_CONTROL 0x0A80 /* USXGMII control register */ +#define GEM_USX_STATUS 0x0A88 /* USXGMII status register */ #define GEM_TXBDCTRL 0x04cc /* TX Buffer Descriptor control register */ #define GEM_RXBDCTRL 0x04d0 /* RX Buffer Descriptor control register */ @@ -275,6 +279,8 @@ #define MACB_IRXFCS_SIZE 1 /* GEM specific NCR bitfields. */ +#define GEM_ENABLE_HS_MAC_OFFSET 31 +#define GEM_ENABLE_HS_MAC_SIZE 1 #define GEM_TWO_PT_FIVE_GIG_OFFSET 29 #define GEM_TWO_PT_FIVE_GIG_SIZE 1 @@ -463,6 +469,10 @@ #define MACB_REV_OFFSET 0 #define MACB_REV_SIZE 16 +/* Bitfield in HS_MAC_CONFIG */ +#define GEM_HS_MAC_SPEED_OFFSET 0 +#define GEM_HS_MAC_SPEED_SIZE 3 + /* Bitfields in DCFG1. */ #define GEM_IRQCOR_OFFSET 23 #define GEM_IRQCOR_SIZE 1 @@ -504,6 +514,28 @@ #define GEM_RXBD_RDBUFF_OFFSET 8 #define GEM_RXBD_RDBUFF_SIZE 4 +/* Bitfields in DCFG12. */ +#define GEM_HIGH_SPEED_OFFSET 26 +#define GEM_HIGH_SPEED_SIZE 1 + +/* Bitfields in USX_CONTROL. */ +#define GEM_USX_CTRL_SPEED_OFFSET 14 +#define GEM_USX_CTRL_SPEED_SIZE 3 +#define GEM_SERDES_RATE_OFFSET 12 +#define GEM_SERDES_RATE_SIZE 2 +#define GEM_TX_EN_OFFSET 1 +#define GEM_TX_EN_SIZE 1 +#define GEM_SIGNAL_OK_OFFSET 0 +#define GEM_SIGNAL_OK_SIZE 1 + +/* Bitfields in USX_STATUS. */ +#define GEM_USX_TX_FAULT_OFFSET 28 +#define GEM_USX_TX_FAULT_SIZE 1 +#define GEM_USX_RX_FAULT_OFFSET 27 +#define GEM_USX_RX_FAULT_SIZE 1 +#define GEM_USX_BLOCK_LOCK_OFFSET 0 +#define GEM_USX_BLOCK_LOCK_SIZE 1 + /* Bitfields in TISUBN */ #define GEM_SUBNSINCR_OFFSET 0 #define GEM_SUBNSINCR_SIZE 16 @@ -664,6 +696,7 @@ #define MACB_CAPS_MACB_IS_GEM 0x80000000 #define MACB_CAPS_PCS 0x01000000 #define MACB_CAPS_TWO_PT_FIVE_GIG_SPEED 0x02000000 +#define MACB_CAPS_HIGH_SPEED 0x04000000 #define MACB_GEM7010_IDNUM 0x009 #define MACB_GEM7014_IDNUM 0x107 diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 2494abf..0e0acf9 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -79,6 +79,21 @@ */ #define MACB_HALT_TIMEOUT 1230 +enum { + HS_MAC_SPEED_100M, + HS_MAC_SPEED_1000M, + HS_MAC_SPEED_2500M, + HS_MAC_SPEED_5000M, + HS_MAC_SPEED_10000M, + HS_MAC_SPEED_25000M, +}; + +enum { + MACB_SERDES_RATE_5_PT_15625Gbps, + MACB_SERDES_RATE_10_PT_3125Gbps, + MACB_SERDES_RATE_25_PT_78125Gbps, +}; + /* DMA buffer descriptor might be different size * depends on hardware configuration: * @@ -443,6 +458,20 @@ static void macb_set_tx_clk(struct clk *clk, int speed, default: return; } + } else if (interface == PHY_INTERFACE_MODE_USXGMII) { + struct macb *bp = netdev_priv(dev); + u32 serdes_rate = GEM_BFEXT(SERDES_RATE, + gem_readl(bp, USX_CONTROL)); + switch (serdes_rate) { + case MACB_SERDES_RATE_5_PT_15625Gbps: + rate = 78125000; + break; + case MACB_SERDES_RATE_10_PT_3125Gbps: + rate = 156250000; + break; + default: + return; + } } else { return; } @@ -475,7 +504,7 @@ static void macb_handle_link_change(struct net_device *dev) if (phydev->link && (bp->speed != phydev->speed || bp->duplex != phydev->duplex)) { - u32 reg; + u32 reg, speed; reg = macb_readl(bp, NCFGR); reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); @@ -485,7 +514,53 @@ static void macb_handle_link_change(struct net_device *dev) reg |= MACB_BIT(FD); macb_or_gem_writel(bp, NCFGR, reg); - if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII && + if ((bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || + bp->phy_interface == PHY_INTERFACE_MODE_XGMII) && + phydev->speed >= SPEED_100) { + gem_writel(bp, NCR, gem_readl(bp, NCR) | + GEM_BIT(ENABLE_HS_MAC)); + if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { + /* Setup USXGMII PCS */ + reg = gem_readl(bp, USX_CONTROL); + reg = GEM_BFINS(SERDES_RATE, + MACB_SERDES_RATE_5_PT_15625Gbps, + reg); + gem_writel(bp, USX_CONTROL, reg | + GEM_BIT(TX_EN) | + GEM_BIT(SIGNAL_OK)); + while (!GEM_BFEXT(USX_BLOCK_LOCK, + gem_readl(bp, USX_STATUS))) + cpu_relax(); + } + switch (phydev->speed) { + case SPEED_10000: + speed = HS_MAC_SPEED_10000M; + break; + + case SPEED_5000: + speed = HS_MAC_SPEED_5000M; + break; + + case SPEED_2500: + speed = HS_MAC_SPEED_2500M; + break; + + case SPEED_1000: + speed = HS_MAC_SPEED_1000M; + break; + + default: + case SPEED_100: + speed = HS_MAC_SPEED_100M; + break; + } + gem_writel(bp, HS_MAC_CONFIG, + GEM_BFINS(HS_MAC_SPEED, speed, + gem_readl(bp, HS_MAC_CONFIG))); + gem_writel(bp, USX_CONTROL, + GEM_BFINS(USX_CTRL_SPEED, speed, + gem_readl(bp, USX_CONTROL))); + } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII && (phydev->speed == SPEED_1000 || phydev->speed == SPEED_2500)) { if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) { @@ -627,10 +702,15 @@ static int macb_mii_probe(struct net_device *dev) /* mask with MAC supported features */ if (macb_is_gem(bp)) { - linkmode_copy(phydev->supported, PHY_GBIT_FEATURES); - if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) - linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - phydev->supported); + if (bp->caps & MACB_CAPS_HIGH_SPEED) { + linkmode_copy(phydev->supported, PHY_10GBIT_FEATURES); + } else { + u32 bitmask = ETHTOOL_LINK_MODE_2500baseT_Full_BIT; + + linkmode_copy(phydev->supported, PHY_GBIT_FEATURES); + if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) + linkmode_set_bit(bitmask, phydev->supported); + } } else { linkmode_copy(phydev->supported, PHY_BASIC_FEATURES); } @@ -3344,6 +3424,9 @@ static void macb_configure_caps(struct macb *bp, bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE; if (GEM_BFEXT(NO_PCS, dcfg) == 0) bp->caps |= MACB_CAPS_PCS; + dcfg = gem_readl(bp, DCFG12); + if (GEM_BFEXT(HIGH_SPEED, dcfg) == 1) + bp->caps |= MACB_CAPS_HIGH_SPEED; switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) { case MACB_GEM7016_IDNUM: case MACB_GEM7017_IDNUM: @@ -4215,6 +4298,21 @@ static int macb_probe(struct platform_device *pdev) bp->phy_interface = PHY_INTERFACE_MODE_MII; } else { switch (err) { + case PHY_INTERFACE_MODE_USXGMII: + if ((bp->caps & MACB_CAPS_HIGH_SPEED) && + (bp->caps & MACB_CAPS_PCS)) { + bp->phy_interface = PHY_INTERFACE_MODE_USXGMII; + break; + } + /* Fallthrough */ + + case PHY_INTERFACE_MODE_XGMII: + if (bp->caps & MACB_CAPS_HIGH_SPEED) { + bp->phy_interface = PHY_INTERFACE_MODE_XGMII; + break; + } + /* Fallthrough */ + case PHY_INTERFACE_MODE_SGMII: if (bp->caps & MACB_CAPS_PCS) { bp->phy_interface = PHY_INTERFACE_MODE_SGMII; diff --git a/include/linux/phy.h b/include/linux/phy.h index 8e9fc57..b627e30 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -94,6 +94,7 @@ PHY_INTERFACE_MODE_RTBI, PHY_INTERFACE_MODE_SMII, PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_USXGMII, PHY_INTERFACE_MODE_MOCA, PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_TRGMII, @@ -162,6 +163,8 @@ unsigned int phy_supported_speeds(struct phy_device *phy, return "smii"; case PHY_INTERFACE_MODE_XGMII: return "xgmii"; + case PHY_INTERFACE_MODE_USXGMII: + return "usxgmii"; case PHY_INTERFACE_MODE_MOCA: return "moca"; case PHY_INTERFACE_MODE_QSGMII: -- 1.7.1