diff options
author | Giuseppe Cavallaro <peppe.cavallaro@st.com> | 2008-11-28 19:24:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-28 19:24:56 -0500 |
commit | 0f0ca340e57bd7446855fefd07a64249acf81223 (patch) | |
tree | 9a3af0f86f8bcce9eb86a38bf4dd5f4a2c5da2d1 | |
parent | 914804b95caa61c633431262044034ab05c78ba4 (diff) |
phy: power management support
This patch adds the power management support into the physical
abstraction layer.
Suspend and resume functions respectively turns on/off the bit 11
into the PHY Basic mode control register.
Generic PHY device starts supporting PM.
In order to support the wake-on LAN and avoid to put in power down
the PHY device, the MDIO is aware of what the Ethernet device wants to do.
Voluntary, no CONFIG_PM defines were added into the sources.
Also generic suspend/resume functions are exported to allow
other drivers use them (such as genphy_config_aneg etc.).
Within the phy_driver_register function, we need to remove the
memset. It overrides the device driver owner and it is not good.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 14 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 31 | ||||
-rw-r--r-- | include/linux/phy.h | 2 |
3 files changed, 42 insertions, 5 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 868812ff6de8..8755d8cd4166 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
@@ -284,9 +284,12 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state) | |||
284 | { | 284 | { |
285 | int ret = 0; | 285 | int ret = 0; |
286 | struct device_driver *drv = dev->driver; | 286 | struct device_driver *drv = dev->driver; |
287 | struct phy_driver *phydrv = to_phy_driver(drv); | ||
288 | struct phy_device *phydev = to_phy_device(dev); | ||
287 | 289 | ||
288 | if (drv && drv->suspend) | 290 | if ((!device_may_wakeup(phydev->dev.parent)) && |
289 | ret = drv->suspend(dev, state); | 291 | (phydrv && phydrv->suspend)) |
292 | ret = phydrv->suspend(phydev); | ||
290 | 293 | ||
291 | return ret; | 294 | return ret; |
292 | } | 295 | } |
@@ -295,9 +298,12 @@ static int mdio_bus_resume(struct device * dev) | |||
295 | { | 298 | { |
296 | int ret = 0; | 299 | int ret = 0; |
297 | struct device_driver *drv = dev->driver; | 300 | struct device_driver *drv = dev->driver; |
301 | struct phy_driver *phydrv = to_phy_driver(drv); | ||
302 | struct phy_device *phydev = to_phy_device(dev); | ||
298 | 303 | ||
299 | if (drv && drv->resume) | 304 | if ((!device_may_wakeup(phydev->dev.parent)) && |
300 | ret = drv->resume(dev); | 305 | (phydrv && phydrv->resume)) |
306 | ret = phydrv->resume(phydev); | ||
301 | 307 | ||
302 | return ret; | 308 | return ret; |
303 | } | 309 | } |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 29546a206045..4cc75a290c06 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -779,7 +779,35 @@ static int genphy_config_init(struct phy_device *phydev) | |||
779 | 779 | ||
780 | return 0; | 780 | return 0; |
781 | } | 781 | } |
782 | int genphy_suspend(struct phy_device *phydev) | ||
783 | { | ||
784 | int value; | ||
785 | |||
786 | mutex_lock(&phydev->lock); | ||
787 | |||
788 | value = phy_read(phydev, MII_BMCR); | ||
789 | phy_write(phydev, MII_BMCR, (value | BMCR_PDOWN)); | ||
790 | |||
791 | mutex_unlock(&phydev->lock); | ||
792 | |||
793 | return 0; | ||
794 | } | ||
795 | EXPORT_SYMBOL(genphy_suspend); | ||
782 | 796 | ||
797 | int genphy_resume(struct phy_device *phydev) | ||
798 | { | ||
799 | int value; | ||
800 | |||
801 | mutex_lock(&phydev->lock); | ||
802 | |||
803 | value = phy_read(phydev, MII_BMCR); | ||
804 | phy_write(phydev, MII_BMCR, (value & ~BMCR_PDOWN)); | ||
805 | |||
806 | mutex_unlock(&phydev->lock); | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | EXPORT_SYMBOL(genphy_resume); | ||
783 | 811 | ||
784 | /** | 812 | /** |
785 | * phy_probe - probe and init a PHY device | 813 | * phy_probe - probe and init a PHY device |
@@ -855,7 +883,6 @@ int phy_driver_register(struct phy_driver *new_driver) | |||
855 | { | 883 | { |
856 | int retval; | 884 | int retval; |
857 | 885 | ||
858 | memset(&new_driver->driver, 0, sizeof(new_driver->driver)); | ||
859 | new_driver->driver.name = new_driver->name; | 886 | new_driver->driver.name = new_driver->name; |
860 | new_driver->driver.bus = &mdio_bus_type; | 887 | new_driver->driver.bus = &mdio_bus_type; |
861 | new_driver->driver.probe = phy_probe; | 888 | new_driver->driver.probe = phy_probe; |
@@ -890,6 +917,8 @@ static struct phy_driver genphy_driver = { | |||
890 | .features = 0, | 917 | .features = 0, |
891 | .config_aneg = genphy_config_aneg, | 918 | .config_aneg = genphy_config_aneg, |
892 | .read_status = genphy_read_status, | 919 | .read_status = genphy_read_status, |
920 | .suspend = genphy_suspend, | ||
921 | .resume = genphy_resume, | ||
893 | .driver = {.owner= THIS_MODULE, }, | 922 | .driver = {.owner= THIS_MODULE, }, |
894 | }; | 923 | }; |
895 | 924 | ||
diff --git a/include/linux/phy.h b/include/linux/phy.h index 77c4ed60b982..d7e54d98869f 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
@@ -467,6 +467,8 @@ int genphy_restart_aneg(struct phy_device *phydev); | |||
467 | int genphy_config_aneg(struct phy_device *phydev); | 467 | int genphy_config_aneg(struct phy_device *phydev); |
468 | int genphy_update_link(struct phy_device *phydev); | 468 | int genphy_update_link(struct phy_device *phydev); |
469 | int genphy_read_status(struct phy_device *phydev); | 469 | int genphy_read_status(struct phy_device *phydev); |
470 | int genphy_suspend(struct phy_device *phydev); | ||
471 | int genphy_resume(struct phy_device *phydev); | ||
470 | void phy_driver_unregister(struct phy_driver *drv); | 472 | void phy_driver_unregister(struct phy_driver *drv); |
471 | int phy_driver_register(struct phy_driver *new_driver); | 473 | int phy_driver_register(struct phy_driver *new_driver); |
472 | void phy_prepare_link(struct phy_device *phydev, | 474 | void phy_prepare_link(struct phy_device *phydev, |