Skip to content

Commit b6e978e

Browse files
ffainellidavem330
authored andcommitted
net: bcmgenet: add suspend/resume callbacks
Implement suspend/resume callbacks in the GENET driver. This makes sure that we de-initialize and re-initialize the hardware correctly before entering suspend and when resuming. Signed-off-by: Florian Fainelli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 909ff5e commit b6e978e

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

drivers/net/ethernet/broadcom/genet/bcmgenet.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,13 +2584,108 @@ static int bcmgenet_remove(struct platform_device *pdev)
25842584
return 0;
25852585
}
25862586

2587+
#ifdef CONFIG_PM_SLEEP
2588+
static int bcmgenet_suspend(struct device *d)
2589+
{
2590+
struct net_device *dev = dev_get_drvdata(d);
2591+
struct bcmgenet_priv *priv = netdev_priv(dev);
2592+
int ret;
2593+
2594+
if (!netif_running(dev))
2595+
return 0;
2596+
2597+
bcmgenet_netif_stop(dev);
2598+
2599+
netif_device_detach(dev);
2600+
2601+
/* Disable MAC receive */
2602+
umac_enable_set(priv, CMD_RX_EN, false);
2603+
2604+
ret = bcmgenet_dma_teardown(priv);
2605+
if (ret)
2606+
return ret;
2607+
2608+
/* Disable MAC transmit. TX DMA disabled have to done before this */
2609+
umac_enable_set(priv, CMD_TX_EN, false);
2610+
2611+
/* tx reclaim */
2612+
bcmgenet_tx_reclaim_all(dev);
2613+
bcmgenet_fini_dma(priv);
2614+
2615+
/* Turn off the clocks */
2616+
clk_disable_unprepare(priv->clk);
2617+
2618+
return 0;
2619+
}
2620+
2621+
static int bcmgenet_resume(struct device *d)
2622+
{
2623+
struct net_device *dev = dev_get_drvdata(d);
2624+
struct bcmgenet_priv *priv = netdev_priv(dev);
2625+
unsigned long dma_ctrl;
2626+
int ret;
2627+
u32 reg;
2628+
2629+
if (!netif_running(dev))
2630+
return 0;
2631+
2632+
/* Turn on the clock */
2633+
ret = clk_prepare_enable(priv->clk);
2634+
if (ret)
2635+
return ret;
2636+
2637+
bcmgenet_umac_reset(priv);
2638+
2639+
ret = init_umac(priv);
2640+
if (ret)
2641+
goto out_clk_disable;
2642+
2643+
/* disable ethernet MAC while updating its registers */
2644+
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
2645+
2646+
bcmgenet_set_hw_addr(priv, dev->dev_addr);
2647+
2648+
if (phy_is_internal(priv->phydev)) {
2649+
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
2650+
reg |= EXT_ENERGY_DET_MASK;
2651+
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
2652+
}
2653+
2654+
/* Disable RX/TX DMA and flush TX queues */
2655+
dma_ctrl = bcmgenet_dma_disable(priv);
2656+
2657+
/* Reinitialize TDMA and RDMA and SW housekeeping */
2658+
ret = bcmgenet_init_dma(priv);
2659+
if (ret) {
2660+
netdev_err(dev, "failed to initialize DMA\n");
2661+
goto out_clk_disable;
2662+
}
2663+
2664+
/* Always enable ring 16 - descriptor ring */
2665+
bcmgenet_enable_dma(priv, dma_ctrl);
2666+
2667+
netif_device_attach(dev);
2668+
2669+
bcmgenet_netif_start(dev);
2670+
2671+
return 0;
2672+
2673+
out_clk_disable:
2674+
clk_disable_unprepare(priv->clk);
2675+
return ret;
2676+
}
2677+
#endif /* CONFIG_PM_SLEEP */
2678+
2679+
static SIMPLE_DEV_PM_OPS(bcmgenet_pm_ops, bcmgenet_suspend, bcmgenet_resume);
2680+
25872681
static struct platform_driver bcmgenet_driver = {
25882682
.probe = bcmgenet_probe,
25892683
.remove = bcmgenet_remove,
25902684
.driver = {
25912685
.name = "bcmgenet",
25922686
.owner = THIS_MODULE,
25932687
.of_match_table = bcmgenet_match,
2688+
.pm = &bcmgenet_pm_ops,
25942689
},
25952690
};
25962691
module_platform_driver(bcmgenet_driver);

0 commit comments

Comments
 (0)