summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c220
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 = &ethqos->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 = &ethqos->pdev->dev;
+ struct qcom_ethqos *ethqos = bsp_priv;
+ struct device *dev;
unsigned int i;
u32 val;
+ dev = &ethqos->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;