diff options
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 220 |
1 files changed, 87 insertions, 133 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 3ccf20fdf52a..ad3a983d2a08 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -100,9 +100,6 @@ struct ethqos_emac_driver_data { struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; - void (*configure_func)(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed); - struct clk *link_clk; struct phy *serdes_phy; phy_interface_t phy_mode; @@ -377,157 +374,126 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { struct device *dev = ðqos->pdev->dev; - int phase_shift; - int loopback; - - /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ - if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || - ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) - phase_shift = 0; - else - phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; + unsigned int prg_rclk_dly, loopback; + unsigned int phase_shift; /* Disable loopback mode */ rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG2); - /* Determine if this platform wants loopback enabled after programming */ - if (ethqos->rgmii_config_loopback_en) - loopback = RGMII_CONFIG_LOOPBACK_EN; - else - loopback = 0; - /* Select RGMII, write 0 to interface select */ rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG); - switch (speed) { - case SPEED_1000: - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, - RGMII_IO_MACRO_CONFIG); + if (speed != SPEED_1000 && speed != SPEED_100 && speed != SPEED_10) { + dev_err(dev, "Invalid speed %d\n", speed); + return -EINVAL; + } + + rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + + if (speed == SPEED_1000) { rgmii_clrmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, - RGMII_IO_MACRO_CONFIG2); - - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - phase_shift, RGMII_IO_MACRO_CONFIG2); - rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, - RGMII_IO_MACRO_CONFIG2); - rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); - - /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns, - * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns - */ - if (ethqos->has_emac_ge_3) { - /* 0.9 ns */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, - FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, - 115), SDCC_HC_REG_DDR_CONFIG); - } else { - /* 1.8 ns */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, - FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, - 57), SDCC_HC_REG_DDR_CONFIG); - } - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, - SDCC_HC_REG_DDR_CONFIG); - rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, - loopback, RGMII_IO_MACRO_CONFIG); - break; - - case SPEED_100: - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, - RGMII_IO_MACRO_CONFIG); + } else { rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, - RGMII_IO_MACRO_CONFIG2); - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - phase_shift, RGMII_IO_MACRO_CONFIG2); - rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, - FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1), - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, - RGMII_IO_MACRO_CONFIG2); + } - if (ethqos->has_emac_ge_3) - rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); - else - rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); + rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); - /* Write 0x5 to PRG_RCLK_DLY_CODE */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, - FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, - 5), SDCC_HC_REG_DDR_CONFIG); - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, - SDCC_HC_REG_DDR_CONFIG); - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, - SDCC_HC_REG_DDR_CONFIG); - rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, - loopback, RGMII_IO_MACRO_CONFIG); - break; + /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || + ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) + phase_shift = 0; + else + phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; - case SPEED_10: - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, - RGMII_IO_MACRO_CONFIG); - rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, phase_shift, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_100) + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, + FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1), RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, - RGMII_IO_MACRO_CONFIG2); - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - phase_shift, RGMII_IO_MACRO_CONFIG2); + else if (speed == SPEED_10) rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19), RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + + rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000 || ethqos->has_emac_ge_3) + rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); - if (ethqos->has_emac_ge_3) - rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); - else - rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); + + if (speed != SPEED_1000) { /* Write 0x5 to PRG_RCLK_DLY_CODE */ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 5), SDCC_HC_REG_DDR_CONFIG); + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, SDCC_HC_REG_DDR_CONFIG); + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_HC_REG_DDR_CONFIG); - rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, - loopback, RGMII_IO_MACRO_CONFIG); - break; - default: - dev_err(dev, "Invalid speed %d\n", speed); - return -EINVAL; + } else { + /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / + * (2 * RX delay ns), + * in practice this becomes PRG_RCLK_DLY = 52 * 4 / + * (2 * RX delay ns) + */ + if (ethqos->has_emac_ge_3) { + /* 0.9 ns */ + prg_rclk_dly = 115; + } else { + /* 1.8 ns */ + prg_rclk_dly = 57; + } + + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, + FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, + prg_rclk_dly), SDCC_HC_REG_DDR_CONFIG); + + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, + SDCC_HC_REG_DDR_CONFIG); } + if (ethqos->rgmii_config_loopback_en) + loopback = RGMII_CONFIG_LOOPBACK_EN; + else + loopback = 0; + + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, + RGMII_IO_MACRO_CONFIG); + return 0; } -static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed) +static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, + phy_interface_t interface, int speed, + unsigned int mode) { - struct device *dev = ðqos->pdev->dev; + struct qcom_ethqos *ethqos = bsp_priv; + struct device *dev; unsigned int i; u32 val; + dev = ðqos->pdev->dev; + /* Reset to POR values and enable clk */ for (i = 0; i < ethqos->num_rgmii_por; i++) rgmii_writel(ethqos, ethqos->rgmii_por[i].value, @@ -590,19 +556,22 @@ static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos, ethqos_rgmii_macro_init(ethqos, speed); } -static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable) +static void ethqos_pcs_set_inband(struct qcom_ethqos *ethqos, bool enable) { + struct net_device *dev = platform_get_drvdata(ethqos->pdev); + struct stmmac_priv *priv = netdev_priv(dev); + stmmac_pcs_ctrl_ane(priv, enable, 0); } /* On interface toggle MAC registers gets reset. * Configure MAC block for SGMII on ethernet phy link up */ -static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed) +static void ethqos_fix_mac_speed_sgmii(void *bsp_priv, + phy_interface_t interface, int speed, + unsigned int mode) { - struct net_device *dev = platform_get_drvdata(ethqos->pdev); - struct stmmac_priv *priv = netdev_priv(dev); + struct qcom_ethqos *ethqos = bsp_priv; switch (speed) { case SPEED_2500: @@ -620,21 +589,7 @@ static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, break; } - ethqos_pcs_set_inband(priv, interface == PHY_INTERFACE_MODE_SGMII); -} - -static void ethqos_configure(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed) -{ - return ethqos->configure_func(ethqos, interface, speed); -} - -static void ethqos_fix_mac_speed(void *priv, phy_interface_t interface, - int speed, unsigned int mode) -{ - struct qcom_ethqos *ethqos = priv; - - ethqos_configure(ethqos, interface, speed); + ethqos_pcs_set_inband(ethqos, interface == PHY_INTERFACE_MODE_SGMII); } static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) @@ -693,7 +648,7 @@ static int ethqos_clks_config(void *priv, bool enabled) /* Enable functional clock to prevent DMA reset to timeout due * to lacking PHY clock after the hardware block has been power * cycled. The actual configuration will be adjusted once - * ethqos_fix_mac_speed() is invoked. + * ethqos' fix_mac_speed() method is invoked. */ qcom_ethqos_set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); @@ -759,11 +714,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev) case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: - ethqos->configure_func = ethqos_configure_rgmii; + plat_dat->fix_mac_speed = ethqos_fix_mac_speed_rgmii; break; case PHY_INTERFACE_MODE_2500BASEX: case PHY_INTERFACE_MODE_SGMII: - ethqos->configure_func = ethqos_configure_sgmii; + plat_dat->fix_mac_speed = ethqos_fix_mac_speed_sgmii; plat_dat->mac_finish = ethqos_mac_finish_serdes; break; default: @@ -811,7 +766,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->bsp_priv = ethqos; plat_dat->set_clk_tx_rate = ethqos_set_clk_tx_rate; - plat_dat->fix_mac_speed = ethqos_fix_mac_speed; plat_dat->dump_debug_regs = rgmii_dump; plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config; plat_dat->core_type = DWMAC_CORE_GMAC4; |
