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

Commit 7f163d07 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bcmgenet-next'



Florian Fainelli says:

====================
net: bcmgenet: integrated GPHY power up/down

This patch series implements integrated Gigabit PHY power up/down, which allows
us to save close to 300mW on some designs when the Gigabit PHY is known to be
unused (e.g: during bcmgenet_close or bcmgenet_suspend not doing Wake-on-LAN).

Changes in v2:

- drop an extra bcmgenet_ext_readl in bcmgenet_phy_power_set
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cc330b55 a6f31f5e
Loading
Loading
Loading
Loading
+25 −9
Original line number Original line Diff line number Diff line
@@ -847,9 +847,10 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
};
};


/* Power down the unimac, based on mode. */
/* Power down the unimac, based on mode. */
static void bcmgenet_power_down(struct bcmgenet_priv *priv,
static int bcmgenet_power_down(struct bcmgenet_priv *priv,
				enum bcmgenet_power_mode mode)
				enum bcmgenet_power_mode mode)
{
{
	int ret = 0;
	u32 reg;
	u32 reg;


	switch (mode) {
	switch (mode) {
@@ -858,7 +859,7 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv,
		break;
		break;


	case GENET_POWER_WOL_MAGIC:
	case GENET_POWER_WOL_MAGIC:
		bcmgenet_wol_power_down_cfg(priv, mode);
		ret = bcmgenet_wol_power_down_cfg(priv, mode);
		break;
		break;


	case GENET_POWER_PASSIVE:
	case GENET_POWER_PASSIVE:
@@ -868,11 +869,15 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv,
			reg |= (EXT_PWR_DOWN_PHY |
			reg |= (EXT_PWR_DOWN_PHY |
				EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS);
				EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS);
			bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
			bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);

			bcmgenet_phy_power_set(priv->dev, false);
		}
		}
		break;
		break;
	default:
	default:
		break;
		break;
	}
	}

	return 0;
}
}


static void bcmgenet_power_up(struct bcmgenet_priv *priv,
static void bcmgenet_power_up(struct bcmgenet_priv *priv,
@@ -2462,9 +2467,6 @@ static void bcmgenet_netif_start(struct net_device *dev)


	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);


	if (phy_is_internal(priv->phydev))
		bcmgenet_power_up(priv, GENET_POWER_PASSIVE);

	netif_tx_start_all_queues(dev);
	netif_tx_start_all_queues(dev);


	phy_start(priv->phydev);
	phy_start(priv->phydev);
@@ -2483,6 +2485,12 @@ static int bcmgenet_open(struct net_device *dev)
	if (!IS_ERR(priv->clk))
	if (!IS_ERR(priv->clk))
		clk_prepare_enable(priv->clk);
		clk_prepare_enable(priv->clk);


	/* If this is an internal GPHY, power it back on now, before UniMAC is
	 * brought out of reset as absolutely no UniMAC activity is allowed
	 */
	if (phy_is_internal(priv->phydev))
		bcmgenet_power_up(priv, GENET_POWER_PASSIVE);

	/* take MAC out of reset */
	/* take MAC out of reset */
	bcmgenet_umac_reset(priv);
	bcmgenet_umac_reset(priv);


@@ -2606,12 +2614,12 @@ static int bcmgenet_close(struct net_device *dev)
	free_irq(priv->irq1, priv);
	free_irq(priv->irq1, priv);


	if (phy_is_internal(priv->phydev))
	if (phy_is_internal(priv->phydev))
		bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
		ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);


	if (!IS_ERR(priv->clk))
	if (!IS_ERR(priv->clk))
		clk_disable_unprepare(priv->clk);
		clk_disable_unprepare(priv->clk);


	return 0;
	return ret;
}
}


static void bcmgenet_timeout(struct net_device *dev)
static void bcmgenet_timeout(struct net_device *dev)
@@ -3097,14 +3105,16 @@ static int bcmgenet_suspend(struct device *d)


	/* Prepare the device for Wake-on-LAN and switch to the slow clock */
	/* Prepare the device for Wake-on-LAN and switch to the slow clock */
	if (device_may_wakeup(d) && priv->wolopts) {
	if (device_may_wakeup(d) && priv->wolopts) {
		bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
		ret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
		clk_prepare_enable(priv->clk_wol);
		clk_prepare_enable(priv->clk_wol);
	} else if (phy_is_internal(priv->phydev)) {
		ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
	}
	}


	/* Turn off the clocks */
	/* Turn off the clocks */
	clk_disable_unprepare(priv->clk);
	clk_disable_unprepare(priv->clk);


	return 0;
	return ret;
}
}


static int bcmgenet_resume(struct device *d)
static int bcmgenet_resume(struct device *d)
@@ -3123,6 +3133,12 @@ static int bcmgenet_resume(struct device *d)
	if (ret)
	if (ret)
		return ret;
		return ret;


	/* If this is an internal GPHY, power it back on now, before UniMAC is
	 * brought out of reset as absolutely no UniMAC activity is allowed
	 */
	if (phy_is_internal(priv->phydev))
		bcmgenet_power_up(priv, GENET_POWER_PASSIVE);

	bcmgenet_umac_reset(priv);
	bcmgenet_umac_reset(priv);


	ret = init_umac(priv);
	ret = init_umac(priv);
+2 −0
Original line number Original line Diff line number Diff line
@@ -354,6 +354,7 @@ struct bcmgenet_mib_counters {
#define EXT_GPHY_CTRL			0x1C
#define EXT_GPHY_CTRL			0x1C
#define  EXT_CFG_IDDQ_BIAS		(1 << 0)
#define  EXT_CFG_IDDQ_BIAS		(1 << 0)
#define  EXT_CFG_PWR_DOWN		(1 << 1)
#define  EXT_CFG_PWR_DOWN		(1 << 1)
#define  EXT_CK25_DIS			(1 << 4)
#define  EXT_GPHY_RESET			(1 << 5)
#define  EXT_GPHY_RESET			(1 << 5)


/* DMA rings size */
/* DMA rings size */
@@ -663,6 +664,7 @@ int bcmgenet_mii_init(struct net_device *dev);
int bcmgenet_mii_config(struct net_device *dev, bool init);
int bcmgenet_mii_config(struct net_device *dev, bool init);
void bcmgenet_mii_exit(struct net_device *dev);
void bcmgenet_mii_exit(struct net_device *dev);
void bcmgenet_mii_reset(struct net_device *dev);
void bcmgenet_mii_reset(struct net_device *dev);
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
void bcmgenet_mii_setup(struct net_device *dev);
void bcmgenet_mii_setup(struct net_device *dev);


/* Wake-on-LAN routines */
/* Wake-on-LAN routines */
+20 −9
Original line number Original line Diff line number Diff line
@@ -168,7 +168,7 @@ void bcmgenet_mii_reset(struct net_device *dev)
	}
	}
}
}


static void bcmgenet_ephy_power_up(struct net_device *dev)
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
{
{
	struct bcmgenet_priv *priv = netdev_priv(dev);
	struct bcmgenet_priv *priv = netdev_priv(dev);
	u32 reg = 0;
	u32 reg = 0;
@@ -178,14 +178,25 @@ static void bcmgenet_ephy_power_up(struct net_device *dev)
		return;
		return;


	reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
	reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
	if (enable) {
		reg &= ~EXT_CK25_DIS;
		bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
		mdelay(1);

		reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN);
		reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN);
		reg |= EXT_GPHY_RESET;
		reg |= EXT_GPHY_RESET;
		bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
		bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
	mdelay(2);
		mdelay(1);


		reg &= ~EXT_GPHY_RESET;
		reg &= ~EXT_GPHY_RESET;
	} else {
		reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN | EXT_GPHY_RESET;
		bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
		mdelay(1);
		reg |= EXT_CK25_DIS;
	}
	bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
	bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
	udelay(20);
	udelay(60);
}
}


static void bcmgenet_internal_phy_setup(struct net_device *dev)
static void bcmgenet_internal_phy_setup(struct net_device *dev)
@@ -193,8 +204,8 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
	struct bcmgenet_priv *priv = netdev_priv(dev);
	struct bcmgenet_priv *priv = netdev_priv(dev);
	u32 reg;
	u32 reg;


	/* Power up EPHY */
	/* Power up PHY */
	bcmgenet_ephy_power_up(dev);
	bcmgenet_phy_power_set(dev, true);
	/* enable APD */
	/* enable APD */
	reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
	reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
	reg |= EXT_PWR_DN_EN_LD;
	reg |= EXT_PWR_DN_EN_LD;