From 6a9493bf395971a420326320f65a286c9b664a91 Mon Sep 17 00:00:00 2001 From: Olivier Dufour Date: Wed, 14 Nov 2012 13:50:25 +0100 Subject: cleo/linux/drv/net/arm: switch off ethernet clocks, refs #2633 --- .../drivers/net/arm/synop3504.c | 66 +++++++++++++++++- .../drivers/net/arm/synop3504_hw.c | 80 ++++++++++++++++++++++ .../drivers/net/arm/synop3504_hw.h | 5 ++ 3 files changed, 149 insertions(+), 2 deletions(-) (limited to 'cleopatre') diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c index 51a728a9d7..9119cbc7f6 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c @@ -1633,6 +1633,66 @@ static int synop3504_init(struct net_device *dev) return 0; }// synop3504_init +#ifdef CONFIG_PM + +/** + * Suspend Synop3504 interface. + * \param pdev platform device + * \param state target suspend state + * \return error code + */ +static int synop3504_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct net_priv *priv = NULL; + Synopsys *synop = NULL; + + priv = netdev_priv(dev); + if(priv == NULL) + return -1; + synop = &priv->synop; + if(synop == NULL) + return -1; + + netif_device_detach(dev); + + SynopsysSuspendClk(synop); + + return 0; +} + +/** + * Resume Synop3504 interface. + * \param pdev platform device + * \return error code + */ +static int synop3504_resume(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct net_priv *priv = NULL; + Synopsys *synop = NULL; + struct phy_device *phydev = NULL; + + priv = netdev_priv(dev); + if(priv == NULL) + return -1; + synop = &priv->synop; + if(synop == NULL) + return -1; + phydev = priv->phydev; + if (phydev == NULL) + return -1; + + SynopsysResumeClk(synop); + SynopsysSetMiiClkCap(synop, phydev->speed); + + netif_device_attach(dev); + + return 0; +} + +#endif /* CONFIG_PM */ + /** * Number of devices registered */ @@ -1854,8 +1914,10 @@ static struct platform_driver synop3504_eth_driver = { .name = "synopsys3504", .owner = THIS_MODULE, }, - .suspend = NULL, - .resume = NULL, +#ifdef CONFIG_PM + .suspend = synop3504_suspend, + .resume = synop3504_resume, +#endif .remove = __exit_p(synop3504_module_remove), }; diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.c b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.c index 5004d48ce3..1d0119a4f9 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.c @@ -227,6 +227,86 @@ void SynopsysInit(Synopsys *synop, uint32_t txaddr, uint32_t rxaddr) TRACE("OK\n"); }// SynopsysInit +#ifdef CONFIG_PM + +/** + * Disable all clocks to enter suspend mode. + * \param synop synopsys context structure. + */ +void SynopsysSuspendClk(Synopsys *synop) +{ + if(synop->mac_id == 1) + { + RB_CLK_CMD_ETH1_TX_VA = CLK_CMD_OFF; + RB_CLK_CMD_ETH1_RX_VA = CLK_CMD_OFF; + } + else if(synop->mac_id == 2) + { + RB_CLK_CMD_ETH2_TX_VA = CLK_CMD_OFF; + RB_CLK_CMD_ETH2_RX_VA = CLK_CMD_OFF; + } +} + +/** + * Enable clocks when returning from suspend mode. + * \param synop synopsys context structure. + * + * /!\ This function only handles the enabling of base clocks. The function + * SynopsysSetMiiClkCap must be called right after to make the whole config + * clean. + */ +void SynopsysResumeClk(Synopsys *synop) +{ + if(synop->mac_id == 1) + { + RB_CLK_CMD_ETH1_TX_VA = CLK_CMD_PLL_ON; + while (RB_CLK_STAT_ETH1_TX_VA != CLK_ETH_TX_RX_PLL_IS_ON) + ; + + if(synop->mode == IS_RMII) + { + RB_CLK_CMD_ETH1_RX_VA = CLK_CMD_PLL_ON; + while (RB_CLK_STAT_ETH1_RX_VA != CLK_ETH_TX_RX_PLL_IS_ON) + ; + + RB_CLK_CMD_ETH1_RMII_VA = CLK_CMD_RMII_PLL_ON; + while (RB_CLK_STAT_ETH1_RMII_VA != CLK_ETH_RMII_PLL_IS_ON) + ; + } + else + { + RB_CLK_CMD_ETH1_RX_VA = CLK_CMD_MII_ON; + while (RB_CLK_STAT_ETH1_RX_VA != CLK_ETH_TX_RX_MII_IS_ON) + ; + } + } + else if(synop->mac_id == 2) + { + RB_CLK_CMD_ETH2_TX_VA = CLK_CMD_PLL_ON; + while (RB_CLK_STAT_ETH2_TX_VA != CLK_ETH_TX_RX_PLL_IS_ON) + ; + + if(synop->mode == IS_RMII) + { + RB_CLK_CMD_ETH2_RX_VA = CLK_CMD_PLL_ON; + while (RB_CLK_STAT_ETH2_RX_VA != CLK_ETH_TX_RX_PLL_IS_ON) + ; + + RB_CLK_CMD_ETH2_RMII_VA = CLK_CMD_RMII_PLL_ON; + while (RB_CLK_STAT_ETH2_RMII_VA != CLK_ETH_RMII_PLL_IS_ON) + ; + } + else + { + RB_CLK_CMD_ETH2_RX_VA = CLK_CMD_MII_ON; + while (RB_CLK_STAT_ETH2_RX_VA != CLK_ETH_TX_RX_MII_IS_ON) + ; + } + } +} + +#endif /* CONFIG_PM */ + /** * Set MII mode clock depending on * speed chosen by auto-negotiation. diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.h b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.h index 9dc04598d6..932d36daee 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.h +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504_hw.h @@ -185,6 +185,11 @@ void SynopsysInit(Synopsys *synop, uint32_t txaddr, uint32_t rxaddr); void SynopsysReset(Synopsys *synop); +#ifdef CONFIG_PM +void SynopsysSuspendClk(Synopsys *synop); +void SynopsysResumeClk(Synopsys *synop); +#endif + /** * Set MII mode clock depending on * speed chosen by auto-negotiation. -- cgit v1.2.3