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

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -5,6 +5,10 @@ through an Ethernet OF device node.

Optional properties:

- clocks:
  The clock used as phy reference clock and is connected to phy
  pin XTAL1/CLKIN.

- smsc,disable-energy-detect:
  If set, do not enable energy detect mode for the SMSC phy.
  default: enable energy detect mode
+46 −13
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 *
 */

#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mii.h>
@@ -44,14 +45,22 @@ 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)
{
	int rc = phy_write (phydev, MII_LAN83C185_IM,
			((PHY_INTERRUPT_ENABLED == phydev->interrupts)
			? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
			: 0));
	struct smsc_phy_priv *priv = phydev->priv;
	u16 intmask = 0;
	int rc;

	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;
}
@@ -66,19 +75,21 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
static int smsc_phy_config_init(struct phy_device *phydev)
{
	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)
		return rc;

	if (priv->energy_enable) {
	/* Enable energy detect mode for this SMSC Transceivers */
	rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
		       rc | MII_LAN83C185_EDPWRDOWN);
	if (rc < 0)
		return rc;
	}

	return smsc_phy_ack_interrupt(phydev);
}
@@ -244,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)
@@ -261,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;
}

@@ -364,9 +397,9 @@ static struct phy_driver smsc_phy_driver[] = {
	.name		= "SMSC LAN8710/LAN8720",

	/* PHY_BASIC_FEATURES */
	.flags		= PHY_RST_AFTER_CLK_EN,

	.probe		= smsc_phy_probe,
	.remove		= smsc_phy_remove,

	/* basic functions */
	.read_status	= lan87xx_read_status,