Commit bcd5149d authored by Magnus Damm's avatar Magnus Damm Committed by David S. Miller

net: add Runtime PM to the sh_eth driver

Add Runtime PM support to the sh_eth driver.

The clock to the ethernet hardware block will be
enabled as long as the network device is up.
Signed-off-by: default avatarMagnus Damm <damm@opensource.se>
Tested-by: default avatarKuninori Morimoto <morimoto.kuninori@renesas.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 748031f9
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm_runtime.h>
#include "sh_eth.h" #include "sh_eth.h"
/* There is CPU dependent code */ /* There is CPU dependent code */
...@@ -1012,6 +1012,8 @@ static int sh_eth_open(struct net_device *ndev) ...@@ -1012,6 +1012,8 @@ static int sh_eth_open(struct net_device *ndev)
int ret = 0; int ret = 0;
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
pm_runtime_get_sync(&mdp->pdev->dev);
ret = request_irq(ndev->irq, &sh_eth_interrupt, ret = request_irq(ndev->irq, &sh_eth_interrupt,
#if defined(CONFIG_CPU_SUBTYPE_SH7763) || defined(CONFIG_CPU_SUBTYPE_SH7764) #if defined(CONFIG_CPU_SUBTYPE_SH7763) || defined(CONFIG_CPU_SUBTYPE_SH7764)
IRQF_SHARED, IRQF_SHARED,
...@@ -1048,6 +1050,7 @@ static int sh_eth_open(struct net_device *ndev) ...@@ -1048,6 +1050,7 @@ static int sh_eth_open(struct net_device *ndev)
out_free_irq: out_free_irq:
free_irq(ndev->irq, ndev); free_irq(ndev->irq, ndev);
pm_runtime_put_sync(&mdp->pdev->dev);
return ret; return ret;
} }
...@@ -1179,6 +1182,8 @@ static int sh_eth_close(struct net_device *ndev) ...@@ -1179,6 +1182,8 @@ static int sh_eth_close(struct net_device *ndev)
ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma); dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma);
pm_runtime_put_sync(&mdp->pdev->dev);
return 0; return 0;
} }
...@@ -1187,6 +1192,8 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) ...@@ -1187,6 +1192,8 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
u32 ioaddr = ndev->base_addr; u32 ioaddr = ndev->base_addr;
pm_runtime_get_sync(&mdp->pdev->dev);
mdp->stats.tx_dropped += ctrl_inl(ioaddr + TROCR); mdp->stats.tx_dropped += ctrl_inl(ioaddr + TROCR);
ctrl_outl(0, ioaddr + TROCR); /* (write clear) */ ctrl_outl(0, ioaddr + TROCR); /* (write clear) */
mdp->stats.collisions += ctrl_inl(ioaddr + CDCR); mdp->stats.collisions += ctrl_inl(ioaddr + CDCR);
...@@ -1202,6 +1209,8 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) ...@@ -1202,6 +1209,8 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR); mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR);
ctrl_outl(0, ioaddr + CNDCR); /* (write clear) */ ctrl_outl(0, ioaddr + CNDCR); /* (write clear) */
#endif #endif
pm_runtime_put_sync(&mdp->pdev->dev);
return &mdp->stats; return &mdp->stats;
} }
...@@ -1410,6 +1419,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev) ...@@ -1410,6 +1419,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
mdp = netdev_priv(ndev); mdp = netdev_priv(ndev);
spin_lock_init(&mdp->lock); spin_lock_init(&mdp->lock);
mdp->pdev = pdev;
pm_runtime_enable(&pdev->dev);
pm_runtime_resume(&pdev->dev);
pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data); pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
/* get PHY ID */ /* get PHY ID */
...@@ -1485,18 +1497,37 @@ static int sh_eth_drv_remove(struct platform_device *pdev) ...@@ -1485,18 +1497,37 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
sh_mdio_release(ndev); sh_mdio_release(ndev);
unregister_netdev(ndev); unregister_netdev(ndev);
flush_scheduled_work(); flush_scheduled_work();
pm_runtime_disable(&pdev->dev);
free_netdev(ndev); free_netdev(ndev);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
return 0; return 0;
} }
static int sh_eth_runtime_nop(struct device *dev)
{
/*
* Runtime PM callback shared between ->runtime_suspend()
* and ->runtime_resume(). Simply returns success.
*
* This driver re-initializes all registers after
* pm_runtime_get_sync() anyway so there is no need
* to save and restore registers here.
*/
return 0;
}
static struct dev_pm_ops sh_eth_dev_pm_ops = {
.runtime_suspend = sh_eth_runtime_nop,
.runtime_resume = sh_eth_runtime_nop,
};
static struct platform_driver sh_eth_driver = { static struct platform_driver sh_eth_driver = {
.probe = sh_eth_drv_probe, .probe = sh_eth_drv_probe,
.remove = sh_eth_drv_remove, .remove = sh_eth_drv_remove,
.driver = { .driver = {
.name = CARDNAME, .name = CARDNAME,
.pm = &sh_eth_dev_pm_ops,
}, },
}; };
......
...@@ -703,6 +703,7 @@ struct sh_eth_cpu_data { ...@@ -703,6 +703,7 @@ struct sh_eth_cpu_data {
}; };
struct sh_eth_private { struct sh_eth_private {
struct platform_device *pdev;
struct sh_eth_cpu_data *cd; struct sh_eth_cpu_data *cd;
dma_addr_t rx_desc_dma; dma_addr_t rx_desc_dma;
dma_addr_t tx_desc_dma; dma_addr_t tx_desc_dma;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment