From 31bc72d97656af11b89ebf108685ffc8ded8c5f4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 1 Sep 2020 14:43:47 -0700 Subject: net: systemport: fetch and use clock resources We disable clocks shortly after probing the device to save as much power as possible in case the interface is never used. When bcm_sysport_open() is invoked, clocks are enabled, and disabled in bcm_sysport_stop(). A similar scheme is applied to the suspend/resume functions. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 30 +++++++++++++++++++++++++++++- drivers/net/ethernet/broadcom/bcmsysport.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index dfed9ade6950..91eadba5540c 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -186,6 +187,11 @@ static int bcm_sysport_set_features(struct net_device *dev, netdev_features_t features) { struct bcm_sysport_priv *priv = netdev_priv(dev); + int ret; + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; /* Read CRC forward */ if (!priv->is_lite) @@ -197,6 +203,8 @@ static int bcm_sysport_set_features(struct net_device *dev, bcm_sysport_set_rx_csum(dev, features); bcm_sysport_set_tx_csum(dev, features); + clk_disable_unprepare(priv->clk); + return 0; } @@ -1940,6 +1948,8 @@ static int bcm_sysport_open(struct net_device *dev) unsigned int i; int ret; + clk_prepare_enable(priv->clk); + /* Reset UniMAC */ umac_reset(priv); @@ -1970,7 +1980,8 @@ static int bcm_sysport_open(struct net_device *dev) 0, priv->phy_interface); if (!phydev) { netdev_err(dev, "could not attach to PHY\n"); - return -ENODEV; + ret = -ENODEV; + goto out_clk_disable; } /* Reset house keeping link status */ @@ -2048,6 +2059,8 @@ out_free_irq0: free_irq(priv->irq0, dev); out_phy_disconnect: phy_disconnect(phydev); +out_clk_disable: + clk_disable_unprepare(priv->clk); return ret; } @@ -2106,6 +2119,8 @@ static int bcm_sysport_stop(struct net_device *dev) /* Disconnect from PHY */ phy_disconnect(dev->phydev); + clk_disable_unprepare(priv->clk); + return 0; } @@ -2487,6 +2502,10 @@ static int bcm_sysport_probe(struct platform_device *pdev) /* Initialize private members */ priv = netdev_priv(dev); + priv->clk = devm_clk_get_optional(&pdev->dev, "sw_sysport"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + /* Allocate number of TX rings */ priv->tx_rings = devm_kcalloc(&pdev->dev, txq, sizeof(struct bcm_sysport_tx_ring), @@ -2588,6 +2607,8 @@ static int bcm_sysport_probe(struct platform_device *pdev) goto err_deregister_notifier; } + clk_prepare_enable(priv->clk); + priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; dev_info(&pdev->dev, "Broadcom SYSTEMPORT%s " REV_FMT @@ -2596,6 +2617,8 @@ static int bcm_sysport_probe(struct platform_device *pdev) (priv->rev >> 8) & 0xff, priv->rev & 0xff, priv->irq0, priv->irq1, txq, rxq); + clk_disable_unprepare(priv->clk); + return 0; err_deregister_notifier: @@ -2752,6 +2775,8 @@ static int __maybe_unused bcm_sysport_suspend(struct device *d) if (device_may_wakeup(d) && priv->wolopts) ret = bcm_sysport_suspend_to_wol(priv); + clk_disable_unprepare(priv->clk); + return ret; } @@ -2765,6 +2790,8 @@ static int __maybe_unused bcm_sysport_resume(struct device *d) if (!netif_running(dev)) return 0; + clk_prepare_enable(priv->clk); + umac_reset(priv); /* Disable the UniMAC RX/TX */ @@ -2844,6 +2871,7 @@ out_free_rx_ring: out_free_tx_rings: for (i = 0; i < dev->num_tx_queues; i++) bcm_sysport_fini_tx_ring(priv, i); + clk_disable_unprepare(priv->clk); return ret; } diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index 6d80735fbc7f..51800053e88c 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h @@ -770,6 +770,7 @@ struct bcm_sysport_priv { u32 wolopts; u8 sopass[SOPASS_MAX]; unsigned int wol_irq_disabled:1; + struct clk *clk; /* MIB related fields */ struct bcm_sysport_mib mib; -- cgit v1.2.3