diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2022-12-06 14:38:53 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2022-12-06 14:38:53 -0800 |
commit | 5ab0127c2b72f4ce1289f7125df41f2bf6e94c3b (patch) | |
tree | af0752d356b26715937df902b4674120c75a2803 | |
parent | 74b331d03c33a2037ad3ecf8607e155eb51ce0a9 (diff) | |
parent | acc4fee245443de91f324aafa88d296ead452a2c (diff) |
Merge "net: stmmac: add support for marvel phy" into wip-er12
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 89 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 22 | ||||
-rw-r--r-- | include/linux/stmmac.h | 1 |
4 files changed, 99 insertions, 16 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index b8548bf5676aa..b41ffae556b5d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -89,14 +89,21 @@ #define MII_BUSY 0x00000001 #define MII_WRITE 0x00000002 -#define DWC_ETH_QOS_PHY_INTR_STATUS 0x0013 - #define LINK_UP 1 #define LINK_DOWN 0 #define LINK_DOWN_STATE 0x800 #define LINK_UP_STATE 0x400 +#define DWC_ETH_QOS_PHY_INTR_STATUS 0x0013 +#define DWC_ETH_QOS_BASIC_STATUS 0x0001 +#define LINK_STATE_MASK 0x4 +#define AUTONEG_STATE_MASK 0x20 + +#define MARVEL_PHY_INTCS 0x13 +#define MARVEL_PHY_STATUS 0x11 +#define MARVEL_LINK_UP_STATUS BIT(10) + struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0}; struct plat_stmmacenet_data *plat_dat; @@ -308,7 +315,8 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 0, RGMII_IO_MACRO_CONFIG2); - if (priv->plat->mac2mac_88Q5072) + if (priv->plat->mac2mac_88Q5072 || + (priv->phydev && priv->phydev->phy_id == MARVEL_PHY_ID)) rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 0, RGMII_IO_MACRO_CONFIG2); @@ -355,9 +363,16 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) 0, RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 0, RGMII_IO_MACRO_CONFIG2); - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - RGMII_IO_MACRO_CONFIG2); + if (priv->plat->mac2mac_88Q5072 || + (priv->phydev && priv->phydev->phy_id == MARVEL_PHY_ID)) + rgmii_updatel(ethqos, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + 0, RGMII_IO_MACRO_CONFIG2); + else + rgmii_updatel(ethqos, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, BIT(6), RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, @@ -403,15 +418,17 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 0, RGMII_IO_MACRO_CONFIG2); - if (ethqos->emac_ver == EMAC_HW_v3_0_0_RG) + if (ethqos->emac_ver != EMAC_HW_v3_0_0_RG || + priv->plat->mac2mac_88Q5072 || + (priv->phydev && priv->phydev->phy_id == MARVEL_PHY_ID)) rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - RGMII_IO_MACRO_CONFIG2); + 0, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - 0, RGMII_IO_MACRO_CONFIG2); + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, BIT(12) | GENMASK(9, 8), RGMII_IO_MACRO_CONFIG); @@ -589,13 +606,50 @@ static void ethqos_handle_phy_interrupt(struct qcom_ethqos *ethqos) struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); + int marvel_intr_status = 0; + int marvel_status = 0; + int phy_id = 0; + + if (!priv->phydev) + return; + + phy_id = priv->phydev->phy_id & priv->phydev->drv->phy_id_mask; + + if (phy_id == MARVEL_PHY_ID) { + marvel_intr_status = + ethqos_mdio_read(priv, + priv->plat->phy_addr, + MARVEL_PHY_INTCS); + marvel_status = ethqos_mdio_read(priv, + priv->plat->phy_addr, + MARVEL_PHY_STATUS); + + /* Interrupt received for link state change */ + phy_intr_status = ethqos_mdio_read(priv, + priv->plat->phy_addr, + DWC_ETH_QOS_BASIC_STATUS); + ETHQOSDBG("Basic Status Reg (%#x) = %#x\n", + DWC_ETH_QOS_BASIC_STATUS, phy_intr_status); + + if (phy_intr_status & LINK_STATE_MASK) { + if (marvel_status & MARVEL_LINK_UP_STATUS) + ETHQOSDBG("Intr for link UP state\n"); + phy_mac_interrupt(priv->phydev); + } else if (!(phy_intr_status & LINK_STATE_MASK)) { + ETHQOSDBG("Intr for link DOWN state\n"); + phy_mac_interrupt(priv->phydev); + } else if (!(phy_intr_status & AUTONEG_STATE_MASK)) { + ETHQOSDBG("Intr for link down with auto-neg err\n"); + } + } else { + phy_intr_status = + ethqos_mdio_read(priv, priv->plat->phy_addr, + DWC_ETH_QOS_PHY_INTR_STATUS); - phy_intr_status = ethqos_mdio_read(priv, priv->plat->phy_addr, - DWC_ETH_QOS_PHY_INTR_STATUS); - - if ((phy_intr_status & LINK_UP_STATE) || - (phy_intr_status & LINK_DOWN_STATE)) - phy_mac_interrupt(priv->phydev); + if ((phy_intr_status & LINK_UP_STATE) || + (phy_intr_status & LINK_DOWN_STATE)) + phy_mac_interrupt(priv->phydev); + } } static void ethqos_defer_phy_isr_work(struct work_struct *work) @@ -763,6 +817,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->mac2mac_88Q5072 = of_property_read_bool(np, "mac2mac-88Q5072"); + plat_dat->phy_fixed_link = + of_property_read_bool(np, "phy-fixed-link"); + if (of_property_read_bool(pdev->dev.of_node, "emac-core-version")) { /* Read emac core version value from dtsi */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index b7626aebe5975..b9944d5046d36 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -24,6 +24,9 @@ #include <linux/reset.h> #include <net/page_pool.h> +#define MARVELL_PHY_ID_88EA1512 0x01410dd4 +#define MARVEL_PHY_ID MARVELL_PHY_ID_88EA1512 + struct stmmac_resources { void __iomem *addr; u8 mac[ETH_ALEN]; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 6e57513b94656..cfa4cb8805e86 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1023,6 +1023,14 @@ static void stmmac_validate(struct phylink_config *config, /* If PCS is supported, check which modes it supports. */ if (priv->hw->xpcs) xpcs_validate(priv->hw->xpcs, supported, state); + + if (priv->plat->phy_fixed_link) { + state->link = 1; + state->duplex = DUPLEX_FULL; + state->speed = SPEED_1000; + if (priv->phydev) + priv->phydev->autoneg = AUTONEG_DISABLE; + } } static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, @@ -1204,6 +1212,7 @@ static int stmmac_init_phy(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); struct device_node *node; + int phy_id = 0; int ret; node = priv->plat->phylink_node; @@ -1223,6 +1232,19 @@ static int stmmac_init_phy(struct net_device *dev) return -ENODEV; } + phy_id = priv->phydev->phy_id & priv->phydev->drv->phy_id_mask; + if (phy_id == MARVEL_PHY_ID && !priv->plat->phy_intr_en) { + pr_info(" %s phy_id = %#x, phy_id_mask = %#x\n", + __func__, priv->phydev->phy_id, + priv->phydev->drv->phy_id_mask); + ret = priv->plat->phy_intr_enable(priv); + if (ret) + pr_err("%s: Unable to enable PHY interrupt\n", + __func__); + else + priv->plat->phy_intr_en = true; + } + if (priv->plat->phy_intr_en_extn_stm && priv->plat->phy_intr_en) { priv->phydev->irq = PHY_MAC_INTERRUPT; diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index e6bd4e4d8e876..d8a97f4b741c8 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -285,6 +285,7 @@ struct plat_stmmacenet_data { bool mac2mac_en; int mac2mac_link; bool mac2mac_88Q5072; + bool phy_fixed_link; struct emac_emb_smmu_cb_ctx stmmac_emb_smmu_ctx; bool phy_intr_en_extn_stm; bool phy_intr_en; |