Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f0ca340 authored by Giuseppe Cavallaro's avatar Giuseppe Cavallaro Committed by David S. Miller
Browse files

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: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 914804b9
Loading
Loading
Loading
Loading
+10 −4
Original line number Original line Diff line number Diff line
@@ -284,9 +284,12 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state)
{
{
	int ret = 0;
	int ret = 0;
	struct device_driver *drv = dev->driver;
	struct device_driver *drv = dev->driver;
	struct phy_driver *phydrv = to_phy_driver(drv);
	struct phy_device *phydev = to_phy_device(dev);


	if (drv && drv->suspend)
	if ((!device_may_wakeup(phydev->dev.parent)) &&
		ret = drv->suspend(dev, state);
		(phydrv && phydrv->suspend))
			ret = phydrv->suspend(phydev);


	return ret;
	return ret;
}
}
@@ -295,9 +298,12 @@ static int mdio_bus_resume(struct device * dev)
{
{
	int ret = 0;
	int ret = 0;
	struct device_driver *drv = dev->driver;
	struct device_driver *drv = dev->driver;
	struct phy_driver *phydrv = to_phy_driver(drv);
	struct phy_device *phydev = to_phy_device(dev);


	if (drv && drv->resume)
	if ((!device_may_wakeup(phydev->dev.parent)) &&
		ret = drv->resume(dev);
		(phydrv && phydrv->resume))
		ret = phydrv->resume(phydev);


	return ret;
	return ret;
}
}
+30 −1
Original line number Original line Diff line number Diff line
@@ -779,7 +779,35 @@ static int genphy_config_init(struct phy_device *phydev)


	return 0;
	return 0;
}
}
int genphy_suspend(struct phy_device *phydev)
{
	int value;

	mutex_lock(&phydev->lock);

	value = phy_read(phydev, MII_BMCR);
	phy_write(phydev, MII_BMCR, (value | BMCR_PDOWN));

	mutex_unlock(&phydev->lock);

	return 0;
}
EXPORT_SYMBOL(genphy_suspend);


int genphy_resume(struct phy_device *phydev)
{
	int value;

	mutex_lock(&phydev->lock);

	value = phy_read(phydev, MII_BMCR);
	phy_write(phydev, MII_BMCR, (value & ~BMCR_PDOWN));

	mutex_unlock(&phydev->lock);

	return 0;
}
EXPORT_SYMBOL(genphy_resume);


/**
/**
 * phy_probe - probe and init a PHY device
 * phy_probe - probe and init a PHY device
@@ -855,7 +883,6 @@ int phy_driver_register(struct phy_driver *new_driver)
{
{
	int retval;
	int retval;


	memset(&new_driver->driver, 0, sizeof(new_driver->driver));
	new_driver->driver.name = new_driver->name;
	new_driver->driver.name = new_driver->name;
	new_driver->driver.bus = &mdio_bus_type;
	new_driver->driver.bus = &mdio_bus_type;
	new_driver->driver.probe = phy_probe;
	new_driver->driver.probe = phy_probe;
@@ -890,6 +917,8 @@ static struct phy_driver genphy_driver = {
	.features	= 0,
	.features	= 0,
	.config_aneg	= genphy_config_aneg,
	.config_aneg	= genphy_config_aneg,
	.read_status	= genphy_read_status,
	.read_status	= genphy_read_status,
	.suspend	= genphy_suspend,
	.resume		= genphy_resume,
	.driver		= {.owner= THIS_MODULE, },
	.driver		= {.owner= THIS_MODULE, },
};
};


+2 −0
Original line number Original line Diff line number Diff line
@@ -467,6 +467,8 @@ int genphy_restart_aneg(struct phy_device *phydev);
int genphy_config_aneg(struct phy_device *phydev);
int genphy_config_aneg(struct phy_device *phydev);
int genphy_update_link(struct phy_device *phydev);
int genphy_update_link(struct phy_device *phydev);
int genphy_read_status(struct phy_device *phydev);
int genphy_read_status(struct phy_device *phydev);
int genphy_suspend(struct phy_device *phydev);
int genphy_resume(struct phy_device *phydev);
void phy_driver_unregister(struct phy_driver *drv);
void phy_driver_unregister(struct phy_driver *drv);
int phy_driver_register(struct phy_driver *new_driver);
int phy_driver_register(struct phy_driver *new_driver);
void phy_prepare_link(struct phy_device *phydev,
void phy_prepare_link(struct phy_device *phydev,