Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +47 −9 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <linux/debugfs.h> #include <linux/dma-iommu.h> #include <linux/iommu.h> #include <linux/micrel_phy.h> #include "stmmac.h" #include "stmmac_platform.h" Loading Loading @@ -102,6 +102,15 @@ #define LINK_DOWN_STATE 0x800 #define LINK_UP_STATE 0x400 #define MICREL_PHY_ID PHY_ID_KSZ9031 #define DWC_ETH_QOS_MICREL_PHY_INTCS 0x1b #define DWC_ETH_QOS_MICREL_PHY_CTL 0x1f #define DWC_ETH_QOS_MICREL_INTR_LEVEL 0x4000 #define DWC_ETH_QOS_BASIC_STATUS 0x0001 #define LINK_STATE_MASK 0x4 #define AUTONEG_STATE_MASK 0x20 #define MICREL_LINK_UP_INTR_STATUS BIT(0) bool phy_intr_en; struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0}; Loading Loading @@ -561,8 +570,36 @@ 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); phy_intr_status = ethqos_mdio_read(priv, priv->plat->phy_addr, int micrel_intr_status = 0; if (priv->phydev && (priv->phydev->phy_id & priv->phydev->drv->phy_id_mask) == MICREL_PHY_ID) { 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); micrel_intr_status = ethqos_mdio_read(priv, priv->plat->phy_addr, DWC_ETH_QOS_MICREL_PHY_INTCS); ETHQOSDBG("MICREL PHY Intr EN Reg (%#x) = %#x\n", DWC_ETH_QOS_MICREL_PHY_INTCS, micrel_intr_status); /* Interrupt received for link state change */ if (phy_intr_status & LINK_STATE_MASK) { if (micrel_intr_status & MICREL_LINK_UP_INTR_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); if (phy_intr_status & LINK_UP_STATE) Loading @@ -570,6 +607,7 @@ static void ethqos_handle_phy_interrupt(struct qcom_ethqos *ethqos) else if (phy_intr_status & LINK_DOWN_STATE) phylink_mac_change(priv->phylink, LINK_DOWN); } } static void ethqos_defer_phy_isr_work(struct work_struct *work) { Loading drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,7 @@ struct stmmac_priv { struct mac_device_info *hw; int (*hwif_quirks)(struct stmmac_priv *priv); struct mutex lock; struct phy_device *phydev; /* RX Queue */ struct stmmac_rx_queue rx_queue[MTL_MAX_RX_QUEUES]; Loading drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +27 −14 Original line number Diff line number Diff line Loading @@ -95,6 +95,11 @@ module_param(eee_timer, int, 0644); MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec"); #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x)) #define DWC_ETH_QOS_MICREL_PHY_CTL 0x1f #define DWC_ETH_QOS_MICREL_INTR_LEVEL 0x4000 #define PHY_ID_KSZ9031 0x00221620 #define MICREL_PHY_ID PHY_ID_KSZ9031 /* By default the driver will use the ring mode to manage tx and rx descriptors, * but allow user to force to use the chain instead of the ring */ Loading Loading @@ -1022,27 +1027,35 @@ static int stmmac_init_phy(struct net_device *dev) */ if (!node || ret) { int addr = priv->plat->phy_addr; struct phy_device *phydev; phydev = mdiobus_get_phy(priv->mii, addr); if (!phydev) { priv->phydev = mdiobus_get_phy(priv->mii, addr); if (!priv->phydev) { netdev_err(priv->dev, "no phy at addr %d\n", addr); return -ENODEV; } ret = phylink_connect_phy(priv->phylink, priv->phydev); if (phy_intr_en) { phydev->irq = PHY_IGNORE_INTERRUPT; phydev->interrupts = PHY_INTERRUPT_ENABLED; priv->phydev->irq = PHY_IGNORE_INTERRUPT; priv->phydev->interrupts = PHY_INTERRUPT_ENABLED; if (priv->phydev->drv->ack_interrupt && !priv->phydev->drv->ack_interrupt(priv->phydev)) { pr_info(" qcom-ethqos: %s ack_interrupt successful aftre connect\n", __func__); } else { pr_err(" qcom-ethqos: %s ack_interrupt failed aftre connect\n", __func__); } if (phydev->drv && phydev->drv->config_intr && !phydev->drv->config_intr(phydev)) { pr_debug(" qcom-ethqos: %s config_phy_intr successful\n", if (priv->phydev->drv && priv->phydev->drv->config_intr && !priv->phydev->drv->config_intr(priv->phydev)) { pr_err(" qcom-ethqos: %s config_phy_intr successful aftre connect\n", __func__); } } else { pr_err("stmmac phy polling mode\n"); phydev->irq = PHY_POLL; pr_info("stmmac phy polling mode\n"); priv->phydev->irq = PHY_POLL; } ret = phylink_connect_phy(priv->phylink, phydev); } return ret; Loading Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +47 −9 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <linux/debugfs.h> #include <linux/dma-iommu.h> #include <linux/iommu.h> #include <linux/micrel_phy.h> #include "stmmac.h" #include "stmmac_platform.h" Loading Loading @@ -102,6 +102,15 @@ #define LINK_DOWN_STATE 0x800 #define LINK_UP_STATE 0x400 #define MICREL_PHY_ID PHY_ID_KSZ9031 #define DWC_ETH_QOS_MICREL_PHY_INTCS 0x1b #define DWC_ETH_QOS_MICREL_PHY_CTL 0x1f #define DWC_ETH_QOS_MICREL_INTR_LEVEL 0x4000 #define DWC_ETH_QOS_BASIC_STATUS 0x0001 #define LINK_STATE_MASK 0x4 #define AUTONEG_STATE_MASK 0x20 #define MICREL_LINK_UP_INTR_STATUS BIT(0) bool phy_intr_en; struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0}; Loading Loading @@ -561,8 +570,36 @@ 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); phy_intr_status = ethqos_mdio_read(priv, priv->plat->phy_addr, int micrel_intr_status = 0; if (priv->phydev && (priv->phydev->phy_id & priv->phydev->drv->phy_id_mask) == MICREL_PHY_ID) { 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); micrel_intr_status = ethqos_mdio_read(priv, priv->plat->phy_addr, DWC_ETH_QOS_MICREL_PHY_INTCS); ETHQOSDBG("MICREL PHY Intr EN Reg (%#x) = %#x\n", DWC_ETH_QOS_MICREL_PHY_INTCS, micrel_intr_status); /* Interrupt received for link state change */ if (phy_intr_status & LINK_STATE_MASK) { if (micrel_intr_status & MICREL_LINK_UP_INTR_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); if (phy_intr_status & LINK_UP_STATE) Loading @@ -570,6 +607,7 @@ static void ethqos_handle_phy_interrupt(struct qcom_ethqos *ethqos) else if (phy_intr_status & LINK_DOWN_STATE) phylink_mac_change(priv->phylink, LINK_DOWN); } } static void ethqos_defer_phy_isr_work(struct work_struct *work) { Loading
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,7 @@ struct stmmac_priv { struct mac_device_info *hw; int (*hwif_quirks)(struct stmmac_priv *priv); struct mutex lock; struct phy_device *phydev; /* RX Queue */ struct stmmac_rx_queue rx_queue[MTL_MAX_RX_QUEUES]; Loading
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +27 −14 Original line number Diff line number Diff line Loading @@ -95,6 +95,11 @@ module_param(eee_timer, int, 0644); MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec"); #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x)) #define DWC_ETH_QOS_MICREL_PHY_CTL 0x1f #define DWC_ETH_QOS_MICREL_INTR_LEVEL 0x4000 #define PHY_ID_KSZ9031 0x00221620 #define MICREL_PHY_ID PHY_ID_KSZ9031 /* By default the driver will use the ring mode to manage tx and rx descriptors, * but allow user to force to use the chain instead of the ring */ Loading Loading @@ -1022,27 +1027,35 @@ static int stmmac_init_phy(struct net_device *dev) */ if (!node || ret) { int addr = priv->plat->phy_addr; struct phy_device *phydev; phydev = mdiobus_get_phy(priv->mii, addr); if (!phydev) { priv->phydev = mdiobus_get_phy(priv->mii, addr); if (!priv->phydev) { netdev_err(priv->dev, "no phy at addr %d\n", addr); return -ENODEV; } ret = phylink_connect_phy(priv->phylink, priv->phydev); if (phy_intr_en) { phydev->irq = PHY_IGNORE_INTERRUPT; phydev->interrupts = PHY_INTERRUPT_ENABLED; priv->phydev->irq = PHY_IGNORE_INTERRUPT; priv->phydev->interrupts = PHY_INTERRUPT_ENABLED; if (priv->phydev->drv->ack_interrupt && !priv->phydev->drv->ack_interrupt(priv->phydev)) { pr_info(" qcom-ethqos: %s ack_interrupt successful aftre connect\n", __func__); } else { pr_err(" qcom-ethqos: %s ack_interrupt failed aftre connect\n", __func__); } if (phydev->drv && phydev->drv->config_intr && !phydev->drv->config_intr(phydev)) { pr_debug(" qcom-ethqos: %s config_phy_intr successful\n", if (priv->phydev->drv && priv->phydev->drv->config_intr && !priv->phydev->drv->config_intr(priv->phydev)) { pr_err(" qcom-ethqos: %s config_phy_intr successful aftre connect\n", __func__); } } else { pr_err("stmmac phy polling mode\n"); phydev->irq = PHY_POLL; pr_info("stmmac phy polling mode\n"); priv->phydev->irq = PHY_POLL; } ret = phylink_connect_phy(priv->phylink, phydev); } return ret; Loading