diff options
Diffstat (limited to 'drivers/net/phy/smsc.c')
-rw-r--r-- | drivers/net/phy/smsc.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 0bcdf927a790..f181c1d1d17b 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -12,6 +12,7 @@ * */ +#include <linux/clk.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mii.h> @@ -44,6 +45,7 @@ static struct smsc_hw_stat smsc_hw_stats[] = { struct smsc_phy_priv { bool energy_enable; + struct clk *refclk; }; static int smsc_phy_config_intr(struct phy_device *phydev) @@ -253,11 +255,20 @@ static void smsc_get_stats(struct phy_device *phydev, data[i] = smsc_get_stat(phydev, i); } +static void smsc_phy_remove(struct phy_device *phydev) +{ + struct smsc_phy_priv *priv = phydev->priv; + + clk_disable_unprepare(priv->refclk); + clk_put(priv->refclk); +} + static int smsc_phy_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; struct device_node *of_node = dev->of_node; struct smsc_phy_priv *priv; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -270,6 +281,19 @@ static int smsc_phy_probe(struct phy_device *phydev) phydev->priv = priv; + /* Make clk optional to keep DTB backward compatibility. */ + priv->refclk = clk_get_optional(dev, NULL); + if (IS_ERR(priv->refclk)) + dev_err_probe(dev, PTR_ERR(priv->refclk), "Failed to request clock\n"); + + ret = clk_prepare_enable(priv->refclk); + if (ret) + return ret; + + ret = clk_set_rate(priv->refclk, 50 * 1000 * 1000); + if (ret) + return ret; + return 0; } @@ -376,6 +400,7 @@ static struct phy_driver smsc_phy_driver[] = { .flags = PHY_RST_AFTER_CLK_EN, .probe = smsc_phy_probe, + .remove = smsc_phy_remove, /* basic functions */ .read_status = lan87xx_read_status, |