Commit 34e43543 authored by David S. Miller's avatar David S. Miller

Merge branch 'SMSC-Cleanups-and-clock-setup'

Marco Felsch says:

====================
SMSC: Cleanups and clock setup

this small series cleans the smsc-phy code a bit and adds the support to
specify the phy clock source. Adding the phy clock source support is
also the main purpose of this series.

Each file has its own changelog.

Thanks a lot to Florian and Andrew for reviewing it.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 74c654a8 d65af218
...@@ -5,6 +5,10 @@ through an Ethernet OF device node. ...@@ -5,6 +5,10 @@ through an Ethernet OF device node.
Optional properties: Optional properties:
- clocks:
The clock used as phy reference clock and is connected to phy
pin XTAL1/CLKIN.
- smsc,disable-energy-detect: - smsc,disable-energy-detect:
If set, do not enable energy detect mode for the SMSC phy. If set, do not enable energy detect mode for the SMSC phy.
default: enable energy detect mode default: enable energy detect mode
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* *
*/ */
#include <linux/clk.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mii.h> #include <linux/mii.h>
...@@ -44,14 +45,22 @@ static struct smsc_hw_stat smsc_hw_stats[] = { ...@@ -44,14 +45,22 @@ static struct smsc_hw_stat smsc_hw_stats[] = {
struct smsc_phy_priv { struct smsc_phy_priv {
bool energy_enable; bool energy_enable;
struct clk *refclk;
}; };
static int smsc_phy_config_intr(struct phy_device *phydev) static int smsc_phy_config_intr(struct phy_device *phydev)
{ {
int rc = phy_write (phydev, MII_LAN83C185_IM, struct smsc_phy_priv *priv = phydev->priv;
((PHY_INTERRUPT_ENABLED == phydev->interrupts) u16 intmask = 0;
? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS int rc;
: 0));
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
intmask = MII_LAN83C185_ISF_INT4 | MII_LAN83C185_ISF_INT6;
if (priv->energy_enable)
intmask |= MII_LAN83C185_ISF_INT7;
}
rc = phy_write(phydev, MII_LAN83C185_IM, intmask);
return rc < 0 ? rc : 0; return rc < 0 ? rc : 0;
} }
...@@ -66,19 +75,21 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) ...@@ -66,19 +75,21 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
static int smsc_phy_config_init(struct phy_device *phydev) static int smsc_phy_config_init(struct phy_device *phydev)
{ {
struct smsc_phy_priv *priv = phydev->priv; struct smsc_phy_priv *priv = phydev->priv;
int rc;
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); if (!priv->energy_enable)
return 0;
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0) if (rc < 0)
return rc; return rc;
if (priv->energy_enable) {
/* Enable energy detect mode for this SMSC Transceivers */ /* Enable energy detect mode for this SMSC Transceivers */
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
rc | MII_LAN83C185_EDPWRDOWN); rc | MII_LAN83C185_EDPWRDOWN);
if (rc < 0) if (rc < 0)
return rc; return rc;
}
return smsc_phy_ack_interrupt(phydev); return smsc_phy_ack_interrupt(phydev);
} }
...@@ -244,11 +255,20 @@ static void smsc_get_stats(struct phy_device *phydev, ...@@ -244,11 +255,20 @@ static void smsc_get_stats(struct phy_device *phydev,
data[i] = smsc_get_stat(phydev, i); 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) static int smsc_phy_probe(struct phy_device *phydev)
{ {
struct device *dev = &phydev->mdio.dev; struct device *dev = &phydev->mdio.dev;
struct device_node *of_node = dev->of_node; struct device_node *of_node = dev->of_node;
struct smsc_phy_priv *priv; struct smsc_phy_priv *priv;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
...@@ -261,6 +281,19 @@ static int smsc_phy_probe(struct phy_device *phydev) ...@@ -261,6 +281,19 @@ static int smsc_phy_probe(struct phy_device *phydev)
phydev->priv = priv; 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; return 0;
} }
...@@ -364,9 +397,9 @@ static struct phy_driver smsc_phy_driver[] = { ...@@ -364,9 +397,9 @@ static struct phy_driver smsc_phy_driver[] = {
.name = "SMSC LAN8710/LAN8720", .name = "SMSC LAN8710/LAN8720",
/* PHY_BASIC_FEATURES */ /* PHY_BASIC_FEATURES */
.flags = PHY_RST_AFTER_CLK_EN,
.probe = smsc_phy_probe, .probe = smsc_phy_probe,
.remove = smsc_phy_remove,
/* basic functions */ /* basic functions */
.read_status = lan87xx_read_status, .read_status = lan87xx_read_status,
......
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