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

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
...@@ -847,9 +847,10 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -354,6 +354,7 @@ struct bcmgenet_mib_counters { ...@@ -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); ...@@ -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 */
......
...@@ -168,7 +168,7 @@ void bcmgenet_mii_reset(struct net_device *dev) ...@@ -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) ...@@ -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) ...@@ -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;
......
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