Add support for controlling regulator powering the magnetics. In case
the interface is down, it is possible to save considerable power by
turning the regulator supplying the magnetics off.

Signed-off-by: Marek Vasut <ma...@denx.de>
Cc: Andrew Lunn <and...@lunn.ch>
Cc: Florian Fainelli <f.faine...@gmail.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Heiner Kallweit <hkallwe...@gmail.com>
---
 drivers/net/phy/smsc.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 33372756a451..edc2bd7d8100 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -20,6 +20,9 @@
 #include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/netdevice.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/consumer.h>
 #include <linux/smscphy.h>
 
 /* Vendor-specific PHY Definitions */
@@ -46,6 +49,7 @@ static struct smsc_hw_stat smsc_hw_stats[] = {
 struct smsc_phy_priv {
        bool energy_enable;
        struct clk *refclk;
+       struct regulator *vddio;
 };
 
 static int smsc_phy_ack_interrupt(struct phy_device *phydev)
@@ -288,6 +292,20 @@ static void smsc_get_stats(struct phy_device *phydev,
                data[i] = smsc_get_stat(phydev, i);
 }
 
+static void smsc_link_change_notify(struct phy_device *phydev)
+{
+       struct smsc_phy_priv *priv = phydev->priv;
+
+       if (!priv->vddio)
+               return;
+
+       if (phydev->state == PHY_HALTED)
+               regulator_disable(priv->vddio);
+
+       if (phydev->state == PHY_NOLINK)
+               regulator_enable(priv->vddio);
+}
+
 static void smsc_phy_remove(struct phy_device *phydev)
 {
        struct smsc_phy_priv *priv = phydev->priv;
@@ -309,6 +327,10 @@ static int smsc_phy_probe(struct phy_device *phydev)
 
        priv->energy_enable = true;
 
+       priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev, "vddio");
+       if (IS_ERR(priv->vddio))
+               return PTR_ERR(priv->vddio);
+
        if (of_property_read_bool(of_node, "smsc,disable-energy-detect"))
                priv->energy_enable = false;
 
@@ -432,7 +454,7 @@ static struct phy_driver smsc_phy_driver[] = {
        .name           = "SMSC LAN8710/LAN8720",
 
        /* PHY_BASIC_FEATURES */
-
+       .link_change_notify = smsc_link_change_notify,
        .probe          = smsc_phy_probe,
        .remove         = smsc_phy_remove,
 
-- 
2.29.2

Reply via email to