[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210223104818.1933-2-qiangqing.zhang@nxp.com>
Date: Tue, 23 Feb 2021 18:48:16 +0800
From: Joakim Zhang <qiangqing.zhang@....com>
To: peppe.cavallaro@...com, alexandre.torgue@...com,
joabreu@...opsys.com, davem@...emloft.net, kuba@...nel.org
Cc: netdev@...r.kernel.org, linux-imx@....com
Subject: [PATCH V1 net-next 1/3] net: stmmac: add clocks management for gmac driver
This patch intends to add clocks management for stmmac driver:
1. Keep clocks disabled after probe stage.
2. Enable clocks when up the net device, and disable clocks when down
the net device.
3. If the driver is built as module, it also keeps clocks disabled when
the module is removed.
Signed-off-by: Joakim Zhang <qiangqing.zhang@....com>
---
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 60 ++++++++++++++++---
1 file changed, 51 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 26b971cd4da5..35a79c00a477 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -113,6 +113,27 @@ static void stmmac_exit_fs(struct net_device *dev);
#define STMMAC_COAL_TIMER(x) (ns_to_ktime((x) * NSEC_PER_USEC))
+static int stmmac_bus_clks_enable(struct stmmac_priv *priv, bool enabled)
+{
+ int ret = 0;
+
+ if (enabled) {
+ ret = clk_prepare_enable(priv->plat->stmmac_clk);
+ if (ret)
+ return ret;
+ ret = clk_prepare_enable(priv->plat->pclk);
+ if (ret) {
+ clk_disable_unprepare(priv->plat->stmmac_clk);
+ return ret;
+ }
+ } else {
+ clk_disable_unprepare(priv->plat->stmmac_clk);
+ clk_disable_unprepare(priv->plat->pclk);
+ }
+
+ return ret;
+}
+
/**
* stmmac_verify_args - verify the driver parameters.
* Description: it checks the driver parameters and set a default in case of
@@ -2800,6 +2821,10 @@ static int stmmac_open(struct net_device *dev)
u32 chan;
int ret;
+ ret = stmmac_bus_clks_enable(priv, true);
+ if (ret)
+ return ret;
+
if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI &&
priv->hw->xpcs == NULL) {
@@ -2808,7 +2833,7 @@ static int stmmac_open(struct net_device *dev)
netdev_err(priv->dev,
"%s: Cannot attach to PHY (error: %d)\n",
__func__, ret);
- return ret;
+ goto clk_enable_error;
}
}
@@ -2924,6 +2949,8 @@ static int stmmac_open(struct net_device *dev)
free_dma_desc_resources(priv);
dma_desc_error:
phylink_disconnect_phy(priv->phylink);
+clk_enable_error:
+ stmmac_bus_clks_enable(priv, false);
return ret;
}
@@ -2974,6 +3001,8 @@ static int stmmac_release(struct net_device *dev)
stmmac_release_ptp(priv);
+ stmmac_bus_clks_enable(priv, false);
+
return 0;
}
@@ -4624,6 +4653,10 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
bool is_double = false;
int ret;
+ ret = stmmac_bus_clks_enable(priv, true);
+ if (ret)
+ return ret;
+
if (be16_to_cpu(proto) == ETH_P_8021AD)
is_double = true;
@@ -4632,10 +4665,15 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
if (priv->hw->num_vlan) {
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
if (ret)
- return ret;
+ goto clk_enable_error;
}
- return stmmac_vlan_update(priv, is_double);
+ ret = stmmac_vlan_update(priv, is_double);
+
+clk_enable_error:
+ stmmac_bus_clks_enable(priv, false);
+
+ return ret;
}
static const struct net_device_ops stmmac_netdev_ops = {
@@ -5111,6 +5149,8 @@ int stmmac_dvr_probe(struct device *device,
stmmac_init_fs(ndev);
#endif
+ stmmac_bus_clks_enable(priv, false);
+
return ret;
error_serdes_powerup:
@@ -5125,6 +5165,7 @@ int stmmac_dvr_probe(struct device *device,
stmmac_napi_del(ndev);
error_hw_init:
destroy_workqueue(priv->wq);
+ stmmac_bus_clks_enable(priv, false);
return ret;
}
@@ -5140,6 +5181,7 @@ int stmmac_dvr_remove(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
+ bool netif_status = netif_running(ndev);
netdev_info(priv->dev, "%s: removing driver", __func__);
@@ -5157,8 +5199,8 @@ int stmmac_dvr_remove(struct device *dev)
phylink_destroy(priv->phylink);
if (priv->plat->stmmac_rst)
reset_control_assert(priv->plat->stmmac_rst);
- clk_disable_unprepare(priv->plat->pclk);
- clk_disable_unprepare(priv->plat->stmmac_clk);
+ if (netif_status)
+ stmmac_bus_clks_enable(priv, false);
if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev);
@@ -5224,8 +5266,7 @@ int stmmac_suspend(struct device *dev)
pinctrl_pm_select_sleep_state(priv->device);
/* Disable clock in case of PWM is off */
clk_disable_unprepare(priv->plat->clk_ptp_ref);
- clk_disable_unprepare(priv->plat->pclk);
- clk_disable_unprepare(priv->plat->stmmac_clk);
+ stmmac_bus_clks_enable(priv, false);
}
mutex_unlock(&priv->lock);
@@ -5289,8 +5330,9 @@ int stmmac_resume(struct device *dev)
} else {
pinctrl_pm_select_default_state(priv->device);
/* enable the clk previously disabled */
- clk_prepare_enable(priv->plat->stmmac_clk);
- clk_prepare_enable(priv->plat->pclk);
+ ret = stmmac_bus_clks_enable(priv, true);
+ if (ret)
+ return ret;
if (priv->plat->clk_ptp_ref)
clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
--
2.17.1
Powered by blists - more mailing lists