mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-04 09:21:34 -04:00
net: stmmac: stm32: simplify clock handling
Some stm32 implementations need the receive clock running in suspend, as indicated by dwmac->ops->clk_rx_enable_in_suspend. The existing code achieved this in a rather complex way, by passing a flag around. However, the clk API prepare/enables are counted - which means that a clock won't be stopped as long as there are more prepare and enables than disables and unprepares, just like a reference count. Therefore, we can simplify this logic by calling clk_prepare_enable() an additional time in the probe function if this flag is set, and then balancing that at remove time. With this, we can avoid passing a "are we suspending" and "are we resuming" flag to various functions in the driver. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
0c49baf099
commit
61499764e5
@@ -119,7 +119,7 @@ struct stm32_ops {
|
||||
u32 syscfg_clr_off;
|
||||
};
|
||||
|
||||
static int stm32_dwmac_clk_enable(struct stm32_dwmac *dwmac, bool resume)
|
||||
static int stm32_dwmac_clk_enable(struct stm32_dwmac *dwmac)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -127,11 +127,9 @@ static int stm32_dwmac_clk_enable(struct stm32_dwmac *dwmac, bool resume)
|
||||
if (ret)
|
||||
goto err_clk_tx;
|
||||
|
||||
if (!dwmac->ops->clk_rx_enable_in_suspend || !resume) {
|
||||
ret = clk_prepare_enable(dwmac->clk_rx);
|
||||
if (ret)
|
||||
goto err_clk_rx;
|
||||
}
|
||||
ret = clk_prepare_enable(dwmac->clk_rx);
|
||||
if (ret)
|
||||
goto err_clk_rx;
|
||||
|
||||
ret = clk_prepare_enable(dwmac->syscfg_clk);
|
||||
if (ret)
|
||||
@@ -148,15 +146,14 @@ static int stm32_dwmac_clk_enable(struct stm32_dwmac *dwmac, bool resume)
|
||||
err_clk_eth_ck:
|
||||
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
err_syscfg_clk:
|
||||
if (!dwmac->ops->clk_rx_enable_in_suspend || !resume)
|
||||
clk_disable_unprepare(dwmac->clk_rx);
|
||||
clk_disable_unprepare(dwmac->clk_rx);
|
||||
err_clk_rx:
|
||||
clk_disable_unprepare(dwmac->clk_tx);
|
||||
err_clk_tx:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat, bool resume)
|
||||
static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
|
||||
{
|
||||
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
|
||||
int ret;
|
||||
@@ -167,7 +164,7 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat, bool resume)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return stm32_dwmac_clk_enable(dwmac, resume);
|
||||
return stm32_dwmac_clk_enable(dwmac);
|
||||
}
|
||||
|
||||
static int stm32mp1_select_ethck_external(struct plat_stmmacenet_data *plat_dat)
|
||||
@@ -382,12 +379,10 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
|
||||
SYSCFG_MCU_ETH_MASK, val << 23);
|
||||
}
|
||||
|
||||
static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac, bool suspend)
|
||||
static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac)
|
||||
{
|
||||
clk_disable_unprepare(dwmac->clk_tx);
|
||||
if (!dwmac->ops->clk_rx_enable_in_suspend || !suspend)
|
||||
clk_disable_unprepare(dwmac->clk_rx);
|
||||
|
||||
clk_disable_unprepare(dwmac->clk_rx);
|
||||
clk_disable_unprepare(dwmac->syscfg_clk);
|
||||
if (dwmac->enable_eth_ck)
|
||||
clk_disable_unprepare(dwmac->clk_eth_ck);
|
||||
@@ -541,18 +536,32 @@ static int stm32_dwmac_probe(struct platform_device *pdev)
|
||||
plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
|
||||
plat_dat->bsp_priv = dwmac;
|
||||
|
||||
ret = stm32_dwmac_init(plat_dat, false);
|
||||
ret = stm32_dwmac_init(plat_dat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If this platform requires the clock to be running in suspend,
|
||||
* prepare and enable the receive clock an additional time to keep
|
||||
* it running.
|
||||
*/
|
||||
if (dwmac->ops->clk_rx_enable_in_suspend) {
|
||||
ret = clk_prepare_enable(dwmac->clk_rx);
|
||||
if (ret)
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
||||
if (ret)
|
||||
goto err_clk_disable;
|
||||
goto err_clk_disable_suspend;
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_disable_suspend:
|
||||
if (dwmac->ops->clk_rx_enable_in_suspend)
|
||||
clk_disable_unprepare(dwmac->clk_rx);
|
||||
|
||||
err_clk_disable:
|
||||
stm32_dwmac_clk_disable(dwmac, false);
|
||||
stm32_dwmac_clk_disable(dwmac);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -565,7 +574,15 @@ static void stm32_dwmac_remove(struct platform_device *pdev)
|
||||
|
||||
stmmac_dvr_remove(&pdev->dev);
|
||||
|
||||
stm32_dwmac_clk_disable(dwmac, false);
|
||||
/* If this platform requires the clock to be running in suspend,
|
||||
* we need to disable and unprepare the receive clock an additional
|
||||
* time to balance the extra clk_prepare_enable() in the probe
|
||||
* function.
|
||||
*/
|
||||
if (dwmac->ops->clk_rx_enable_in_suspend)
|
||||
clk_disable_unprepare(dwmac->clk_rx);
|
||||
|
||||
stm32_dwmac_clk_disable(dwmac);
|
||||
|
||||
if (dwmac->irq_pwr_wakeup >= 0) {
|
||||
dev_pm_clear_wake_irq(&pdev->dev);
|
||||
@@ -596,7 +613,7 @@ static int stm32_dwmac_suspend(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
stm32_dwmac_clk_disable(dwmac, true);
|
||||
stm32_dwmac_clk_disable(dwmac);
|
||||
|
||||
if (dwmac->ops->suspend)
|
||||
ret = dwmac->ops->suspend(dwmac);
|
||||
@@ -614,7 +631,7 @@ static int stm32_dwmac_resume(struct device *dev)
|
||||
if (dwmac->ops->resume)
|
||||
dwmac->ops->resume(dwmac);
|
||||
|
||||
ret = stm32_dwmac_init(priv->plat, true);
|
||||
ret = stm32_dwmac_init(priv->plat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user