From 1d472eb5b6701810e0b25ae5cea40a9908019780 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 28 Feb 2024 14:53:57 -0800 Subject: net: bcmasp: Add support for ASP 2.2 ASP 2.2 improves power savings during low power modes. A new register was added to toggle to a slower clock during low power modes. EEE was broken for ASP 2.0/2.1. A HW workaround was added for ASP 2.2 that requires toggling a chicken bit. Signed-off-by: Justin Chen Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 73 +++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 8 deletions(-) (limited to 'drivers/net/ethernet/broadcom/asp2/bcmasp.c') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index 80245c65cc90..100c69f3307a 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -972,7 +972,26 @@ static void bcmasp_core_init(struct bcmasp_priv *priv) ASP_INTR2_CLEAR); } -static void bcmasp_core_clock_select(struct bcmasp_priv *priv, bool slow) +static void bcmasp_core_clock_select_many(struct bcmasp_priv *priv, bool slow) +{ + u32 reg; + + reg = ctrl2_core_rl(priv, ASP_CTRL2_CORE_CLOCK_SELECT); + if (slow) + reg &= ~ASP_CTRL2_CORE_CLOCK_SELECT_MAIN; + else + reg |= ASP_CTRL2_CORE_CLOCK_SELECT_MAIN; + ctrl2_core_wl(priv, reg, ASP_CTRL2_CORE_CLOCK_SELECT); + + reg = ctrl2_core_rl(priv, ASP_CTRL2_CPU_CLOCK_SELECT); + if (slow) + reg &= ~ASP_CTRL2_CPU_CLOCK_SELECT_MAIN; + else + reg |= ASP_CTRL2_CPU_CLOCK_SELECT_MAIN; + ctrl2_core_wl(priv, reg, ASP_CTRL2_CPU_CLOCK_SELECT); +} + +static void bcmasp_core_clock_select_one(struct bcmasp_priv *priv, bool slow) { u32 reg; @@ -1166,6 +1185,24 @@ static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv) } } +static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) +{ + u32 reg, phy_lpi_overwrite; + + reg = rx_edpkt_core_rl(intf->parent, ASP_EDPKT_SPARE_REG); + phy_lpi_overwrite = intf->internal_phy ? ASP_EDPKT_SPARE_REG_EPHY_LPI : + ASP_EDPKT_SPARE_REG_GPHY_LPI; + + if (en) + reg |= phy_lpi_overwrite; + else + reg &= ~phy_lpi_overwrite; + + rx_edpkt_core_wl(intf->parent, reg, ASP_EDPKT_SPARE_REG); + + usleep_range(50, 100); +} + static struct bcmasp_hw_info v20_hw_info = { .rx_ctrl_flush = ASP_RX_CTRL_FLUSH, .umac2fb = UMAC2FB_OFFSET, @@ -1178,6 +1215,7 @@ static const struct bcmasp_plat_data v20_plat_data = { .init_wol = bcmasp_init_wol_per_intf, .enable_wol = bcmasp_enable_wol_per_intf, .destroy_wol = bcmasp_wol_irq_destroy_per_intf, + .core_clock_select = bcmasp_core_clock_select_one, .hw_info = &v20_hw_info, }; @@ -1194,17 +1232,39 @@ static const struct bcmasp_plat_data v21_plat_data = { .init_wol = bcmasp_init_wol_shared, .enable_wol = bcmasp_enable_wol_shared, .destroy_wol = bcmasp_wol_irq_destroy_shared, + .core_clock_select = bcmasp_core_clock_select_one, .hw_info = &v21_hw_info, }; +static const struct bcmasp_plat_data v22_plat_data = { + .init_wol = bcmasp_init_wol_shared, + .enable_wol = bcmasp_enable_wol_shared, + .destroy_wol = bcmasp_wol_irq_destroy_shared, + .core_clock_select = bcmasp_core_clock_select_many, + .hw_info = &v21_hw_info, + .eee_fixup = bcmasp_eee_fixup, +}; + +static void bcmasp_set_pdata(struct bcmasp_priv *priv, const struct bcmasp_plat_data *pdata) +{ + priv->init_wol = pdata->init_wol; + priv->enable_wol = pdata->enable_wol; + priv->destroy_wol = pdata->destroy_wol; + priv->core_clock_select = pdata->core_clock_select; + priv->eee_fixup = pdata->eee_fixup; + priv->hw_info = pdata->hw_info; +} + static const struct of_device_id bcmasp_of_match[] = { { .compatible = "brcm,asp-v2.0", .data = &v20_plat_data }, { .compatible = "brcm,asp-v2.1", .data = &v21_plat_data }, + { .compatible = "brcm,asp-v2.2", .data = &v22_plat_data }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, bcmasp_of_match); static const struct of_device_id bcmasp_mdio_of_match[] = { + { .compatible = "brcm,asp-v2.2-mdio", }, { .compatible = "brcm,asp-v2.1-mdio", }, { .compatible = "brcm,asp-v2.0-mdio", }, { /* sentinel */ }, @@ -1265,16 +1325,13 @@ static int bcmasp_probe(struct platform_device *pdev) if (!pdata) return dev_err_probe(dev, -EINVAL, "unable to find platform data\n"); - priv->init_wol = pdata->init_wol; - priv->enable_wol = pdata->enable_wol; - priv->destroy_wol = pdata->destroy_wol; - priv->hw_info = pdata->hw_info; + bcmasp_set_pdata(priv, pdata); /* Enable all clocks to ensure successful probing */ bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); /* Switch to the main clock */ - bcmasp_core_clock_select(priv, false); + priv->core_clock_select(priv, false); bcmasp_intr2_mask_set_all(priv); bcmasp_intr2_clear_all(priv); @@ -1381,7 +1438,7 @@ static int __maybe_unused bcmasp_suspend(struct device *d) */ bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE); - bcmasp_core_clock_select(priv, true); + priv->core_clock_select(priv, true); clk_disable_unprepare(priv->clk); @@ -1399,7 +1456,7 @@ static int __maybe_unused bcmasp_resume(struct device *d) return ret; /* Switch to the main clock domain */ - bcmasp_core_clock_select(priv, false); + priv->core_clock_select(priv, false); /* Re-enable all clocks for re-initialization */ bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); -- cgit v1.2.3 From cc7f105e7604477a9f40171331d35153e65a6ce3 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 28 Feb 2024 14:54:00 -0800 Subject: net: bcmasp: Add support for PHY interrupts Hook up the phy interrupts for internal phys to reduce mdio traffic and improve responsiveness of link changes. Signed-off-by: Justin Chen Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 17 +++++++++++++++++ drivers/net/ethernet/broadcom/asp2/bcmasp.h | 4 ++++ drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 5 +++++ 3 files changed, 26 insertions(+) (limited to 'drivers/net/ethernet/broadcom/asp2/bcmasp.c') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index 100c69f3307a..a806dadc4196 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -31,6 +31,20 @@ static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask) priv->irq_mask |= mask; } +void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en) +{ + struct bcmasp_priv *priv = intf->parent; + + /* Only supported with internal phys */ + if (!intf->internal_phy) + return; + + if (en) + _intr2_mask_clear(priv, ASP_INTR2_PHY_EVENT(intf->channel)); + else + _intr2_mask_set(priv, ASP_INTR2_PHY_EVENT(intf->channel)); +} + void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en) { struct bcmasp_priv *priv = intf->parent; @@ -79,6 +93,9 @@ static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status) __napi_schedule_irqoff(&intf->tx_napi); } } + + if (status & ASP_INTR2_PHY_EVENT(intf->channel)) + phy_mac_interrupt(intf->ndev->phydev); } static irqreturn_t bcmasp_isr(int irq, void *data) diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h index 127a5340625e..f93cb3da44b0 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -19,6 +19,8 @@ #define ASP_INTR2_TX_DESC(intr) BIT((intr) + 14) #define ASP_INTR2_UMC0_WAKE BIT(22) #define ASP_INTR2_UMC1_WAKE BIT(28) +#define ASP_INTR2_PHY_EVENT(intr) ((intr) ? BIT(30) | BIT(31) : \ + BIT(24) | BIT(25)) #define ASP_WAKEUP_INTR2_OFFSET 0x1200 #define ASP_WAKEUP_INTR2_STATUS 0x0 @@ -556,6 +558,8 @@ void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en); void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en); +void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en); + void bcmasp_flush_rx_port(struct bcmasp_intf *intf); extern const struct ethtool_ops bcmasp_ethtool_ops; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c index 25b03d32d791..dd06b68b33ed 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -382,6 +382,7 @@ static void bcmasp_netif_start(struct net_device *dev) bcmasp_enable_rx_irq(intf, 1); bcmasp_enable_tx_irq(intf, 1); + bcmasp_enable_phy_irq(intf, 1); phy_start(dev->phydev); } @@ -890,6 +891,7 @@ static void bcmasp_netif_deinit(struct net_device *dev) /* Disable interrupts */ bcmasp_enable_tx_irq(intf, 0); bcmasp_enable_rx_irq(intf, 0); + bcmasp_enable_phy_irq(intf, 0); netif_napi_del(&intf->tx_napi); netif_napi_del(&intf->rx_napi); @@ -1028,6 +1030,9 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) goto err_phy_disable; } + if (intf->internal_phy) + dev->phydev->irq = PHY_MAC_INTERRUPT; + /* Indicate that the MAC is responsible for PHY PM */ phydev->mac_managed_pm = true; } else if (!intf->wolopts) { -- cgit v1.2.3