From 8299abc5ff0b5c2403a3f085376247d4cd8c37d1 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Mon, 3 May 2021 08:08:46 +0200 Subject: [PATCH] net: mvpp2: add 1000BaseX and 2500BaseX ppv2 support Signed-off-by: Stefan Chulski Signed-off-by: Stefan Roese Reviewed-by: Ramon Fried --- drivers/net/mvpp2.c | 117 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 5 deletions(-) diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 015f5329de..847007d5b4 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -2880,6 +2880,10 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port) case PHY_INTERFACE_MODE_SGMII: val |= MVPP2_GMAC_INBAND_AN_MASK; break; + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + val &= ~MVPP2_GMAC_INBAND_AN_MASK; + break; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: val |= MVPP2_GMAC_PORT_RGMII_MASK; @@ -2940,7 +2944,9 @@ static void mvpp2_port_loopback_set(struct mvpp2_port *port) else val &= ~MVPP2_GMAC_GMII_LB_EN_MASK; - if (port->phy_interface == PHY_INTERFACE_MODE_SGMII) + if (port->phy_interface == PHY_INTERFACE_MODE_SGMII || + port->phy_interface == PHY_INTERFACE_MODE_1000BASEX || + port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) val |= MVPP2_GMAC_PCS_LB_EN_MASK; else val &= ~MVPP2_GMAC_PCS_LB_EN_MASK; @@ -3051,10 +3057,10 @@ static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port) val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); /* - * Configure GIG MAC to 1000Base-X mode connected to a fiber + * Configure GIG MAC to SGMII mode connected to a fiber * transceiver */ - val |= MVPP2_GMAC_PORT_TYPE_MASK; + val &= ~MVPP2_GMAC_PORT_TYPE_MASK; writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); /* configure AN 0x9268 */ @@ -3106,6 +3112,89 @@ static void gop_gmac_sgmii_cfg(struct mvpp2_port *port) writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); } +static void gop_gmac_2500basex_cfg(struct mvpp2_port *port) +{ + u32 val, thresh; + + /* + * Configure minimal level of the Tx FIFO before the lower part + * starts to read a packet + */ + thresh = MVPP2_SGMII2_5_TX_FIFO_MIN_TH; + val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG); + val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK; + val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh); + writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG); + + /* Disable bypass of sync module */ + val = readl(port->base + MVPP2_GMAC_CTRL_4_REG); + val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK; + /* configure DP clock select according to mode */ + val |= MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK; + /* configure QSGMII bypass according to mode */ + val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK; + writel(val, port->base + MVPP2_GMAC_CTRL_4_REG); + + val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); + /* + * Configure GIG MAC to 2500Base-X mode connected to a fiber + * transceiver + */ + val |= MVPP2_GMAC_PORT_TYPE_MASK; + writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); + + /* In 2500BaseX mode, we can't negotiate speed + * and we do not want InBand autoneg + * bypass enabled (link interrupt storm risk + * otherwise). + */ + val = MVPP2_GMAC_EN_PCS_AN | + MVPP2_GMAC_CONFIG_GMII_SPEED | + MVPP2_GMAC_CONFIG_FULL_DUPLEX | + MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG; + writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); +} + +static void gop_gmac_1000basex_cfg(struct mvpp2_port *port) +{ + u32 val, thresh; + + /* + * Configure minimal level of the Tx FIFO before the lower part + * starts to read a packet + */ + thresh = MVPP2_SGMII_TX_FIFO_MIN_TH; + val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG); + val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK; + val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh); + writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG); + + /* Disable bypass of sync module */ + val = readl(port->base + MVPP2_GMAC_CTRL_4_REG); + val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK; + /* configure DP clock select according to mode */ + val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK; + /* configure QSGMII bypass according to mode */ + val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK; + writel(val, port->base + MVPP2_GMAC_CTRL_4_REG); + + val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); + /* configure GIG MAC to 1000BASEX mode */ + val |= MVPP2_GMAC_PORT_TYPE_MASK; + writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); + + /* In 1000BaseX mode, we can't negotiate speed (it's + * only 1000), and we do not want InBand autoneg + * bypass enabled (link interrupt storm risk + * otherwise). + */ + val = MVPP2_GMAC_EN_PCS_AN | + MVPP2_GMAC_CONFIG_GMII_SPEED | + MVPP2_GMAC_CONFIG_FULL_DUPLEX | + MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG; + writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); +} + static void gop_gmac_rgmii_cfg(struct mvpp2_port *port) { u32 val, thresh; @@ -3157,6 +3246,12 @@ static int gop_gmac_mode_cfg(struct mvpp2_port *port) gop_gmac_sgmii_cfg(port); break; + case PHY_INTERFACE_MODE_1000BASEX: + gop_gmac_1000basex_cfg(port); + + case PHY_INTERFACE_MODE_2500BASEX: + gop_gmac_2500basex_cfg(port); + case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: gop_gmac_rgmii_cfg(port); @@ -3329,6 +3424,8 @@ static int gop_port_init(struct mvpp2_port *port) break; case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: /* configure PCS */ gop_gpcs_mode_cfg(port, 1); @@ -3386,6 +3483,8 @@ static void gop_port_enable(struct mvpp2_port *port, int enable) case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: if (enable) mvpp2_port_enable(port); else @@ -3419,7 +3518,9 @@ static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type) u32 val = 0; if (gop_id == 2) { - if (phy_type == PHY_INTERFACE_MODE_SGMII) + if (phy_type == PHY_INTERFACE_MODE_SGMII || + phy_type == PHY_INTERFACE_MODE_1000BASEX || + phy_type == PHY_INTERFACE_MODE_2500BASEX) val |= MV_NETC_GE_MAC2_SGMII; else if (phy_type == PHY_INTERFACE_MODE_RGMII || phy_type == PHY_INTERFACE_MODE_RGMII_ID) @@ -3427,7 +3528,9 @@ static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type) } if (gop_id == 3) { - if (phy_type == PHY_INTERFACE_MODE_SGMII) + if (phy_type == PHY_INTERFACE_MODE_SGMII || + phy_type == PHY_INTERFACE_MODE_1000BASEX || + phy_type == PHY_INTERFACE_MODE_2500BASEX) val |= MV_NETC_GE_MAC3_SGMII; else if (phy_type == PHY_INTERFACE_MODE_RGMII || phy_type == PHY_INTERFACE_MODE_RGMII_ID) @@ -4423,6 +4526,8 @@ static void mvpp2_start_dev(struct mvpp2_port *port) case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: mvpp2_gmac_max_rx_size_set(port); default: break; @@ -5159,6 +5264,8 @@ static int mvpp2_start(struct udevice *dev) case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: mvpp2_port_power_up(port); default: break; -- 2.39.5