diff options
| author | David S. Miller <davem@davemloft.net> | 2015-03-23 22:10:50 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-23 22:10:50 -0400 |
| commit | 7f163d07ecd6fbba2ed3a2fcd0ca830846cc170e (patch) | |
| tree | eba7a9996f5d7f2b23d69f59e1a55a4ffa0cdb43 | |
| parent | cc330b55903aad9bce554427a0181d1ee3873b7c (diff) | |
| parent | a6f31f5e3b0498fc0034e07c172925316064201c (diff) | |
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: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmgenet.c | 34 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmmii.c | 29 |
3 files changed, 47 insertions, 18 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 12956b143b11..c38d5429e27a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |||
| @@ -847,9 +847,10 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { | |||
| 847 | }; | 847 | }; |
| 848 | 848 | ||
| 849 | /* Power down the unimac, based on mode. */ | 849 | /* Power down the unimac, based on mode. */ |
| 850 | static void bcmgenet_power_down(struct bcmgenet_priv *priv, | 850 | static int bcmgenet_power_down(struct bcmgenet_priv *priv, |
| 851 | enum bcmgenet_power_mode mode) | 851 | enum bcmgenet_power_mode mode) |
| 852 | { | 852 | { |
| 853 | int ret = 0; | ||
| 853 | u32 reg; | 854 | u32 reg; |
| 854 | 855 | ||
| 855 | switch (mode) { | 856 | switch (mode) { |
| @@ -858,7 +859,7 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv, | |||
| 858 | break; | 859 | break; |
| 859 | 860 | ||
| 860 | case GENET_POWER_WOL_MAGIC: | 861 | case GENET_POWER_WOL_MAGIC: |
| 861 | bcmgenet_wol_power_down_cfg(priv, mode); | 862 | ret = bcmgenet_wol_power_down_cfg(priv, mode); |
| 862 | break; | 863 | break; |
| 863 | 864 | ||
| 864 | case GENET_POWER_PASSIVE: | 865 | case GENET_POWER_PASSIVE: |
| @@ -868,11 +869,15 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv, | |||
| 868 | reg |= (EXT_PWR_DOWN_PHY | | 869 | reg |= (EXT_PWR_DOWN_PHY | |
| 869 | EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS); | 870 | EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS); |
| 870 | bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); | 871 | bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); |
| 872 | |||
| 873 | bcmgenet_phy_power_set(priv->dev, false); | ||
| 871 | } | 874 | } |
| 872 | break; | 875 | break; |
| 873 | default: | 876 | default: |
| 874 | break; | 877 | break; |
| 875 | } | 878 | } |
| 879 | |||
| 880 | return 0; | ||
| 876 | } | 881 | } |
| 877 | 882 | ||
| 878 | static void bcmgenet_power_up(struct bcmgenet_priv *priv, | 883 | static void bcmgenet_power_up(struct bcmgenet_priv *priv, |
| @@ -2462,9 +2467,6 @@ static void bcmgenet_netif_start(struct net_device *dev) | |||
| 2462 | 2467 | ||
| 2463 | umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true); | 2468 | umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true); |
| 2464 | 2469 | ||
| 2465 | if (phy_is_internal(priv->phydev)) | ||
| 2466 | bcmgenet_power_up(priv, GENET_POWER_PASSIVE); | ||
| 2467 | |||
| 2468 | netif_tx_start_all_queues(dev); | 2470 | netif_tx_start_all_queues(dev); |
| 2469 | 2471 | ||
| 2470 | phy_start(priv->phydev); | 2472 | phy_start(priv->phydev); |
| @@ -2483,6 +2485,12 @@ static int bcmgenet_open(struct net_device *dev) | |||
| 2483 | if (!IS_ERR(priv->clk)) | 2485 | if (!IS_ERR(priv->clk)) |
| 2484 | clk_prepare_enable(priv->clk); | 2486 | clk_prepare_enable(priv->clk); |
| 2485 | 2487 | ||
| 2488 | /* If this is an internal GPHY, power it back on now, before UniMAC is | ||
| 2489 | * brought out of reset as absolutely no UniMAC activity is allowed | ||
| 2490 | */ | ||
| 2491 | if (phy_is_internal(priv->phydev)) | ||
| 2492 | bcmgenet_power_up(priv, GENET_POWER_PASSIVE); | ||
| 2493 | |||
| 2486 | /* take MAC out of reset */ | 2494 | /* take MAC out of reset */ |
| 2487 | bcmgenet_umac_reset(priv); | 2495 | bcmgenet_umac_reset(priv); |
| 2488 | 2496 | ||
| @@ -2606,12 +2614,12 @@ static int bcmgenet_close(struct net_device *dev) | |||
| 2606 | free_irq(priv->irq1, priv); | 2614 | free_irq(priv->irq1, priv); |
| 2607 | 2615 | ||
| 2608 | if (phy_is_internal(priv->phydev)) | 2616 | if (phy_is_internal(priv->phydev)) |
| 2609 | bcmgenet_power_down(priv, GENET_POWER_PASSIVE); | 2617 | ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE); |
| 2610 | 2618 | ||
| 2611 | if (!IS_ERR(priv->clk)) | 2619 | if (!IS_ERR(priv->clk)) |
| 2612 | clk_disable_unprepare(priv->clk); | 2620 | clk_disable_unprepare(priv->clk); |
| 2613 | 2621 | ||
| 2614 | return 0; | 2622 | return ret; |
| 2615 | } | 2623 | } |
| 2616 | 2624 | ||
| 2617 | static void bcmgenet_timeout(struct net_device *dev) | 2625 | static void bcmgenet_timeout(struct net_device *dev) |
| @@ -3097,14 +3105,16 @@ static int bcmgenet_suspend(struct device *d) | |||
| 3097 | 3105 | ||
| 3098 | /* Prepare the device for Wake-on-LAN and switch to the slow clock */ | 3106 | /* Prepare the device for Wake-on-LAN and switch to the slow clock */ |
| 3099 | if (device_may_wakeup(d) && priv->wolopts) { | 3107 | if (device_may_wakeup(d) && priv->wolopts) { |
| 3100 | bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC); | 3108 | ret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC); |
| 3101 | clk_prepare_enable(priv->clk_wol); | 3109 | clk_prepare_enable(priv->clk_wol); |
| 3110 | } else if (phy_is_internal(priv->phydev)) { | ||
| 3111 | ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE); | ||
| 3102 | } | 3112 | } |
| 3103 | 3113 | ||
| 3104 | /* Turn off the clocks */ | 3114 | /* Turn off the clocks */ |
| 3105 | clk_disable_unprepare(priv->clk); | 3115 | clk_disable_unprepare(priv->clk); |
| 3106 | 3116 | ||
| 3107 | return 0; | 3117 | return ret; |
| 3108 | } | 3118 | } |
| 3109 | 3119 | ||
| 3110 | static int bcmgenet_resume(struct device *d) | 3120 | static int bcmgenet_resume(struct device *d) |
| @@ -3123,6 +3133,12 @@ static int bcmgenet_resume(struct device *d) | |||
| 3123 | if (ret) | 3133 | if (ret) |
| 3124 | return ret; | 3134 | return ret; |
| 3125 | 3135 | ||
| 3136 | /* If this is an internal GPHY, power it back on now, before UniMAC is | ||
| 3137 | * brought out of reset as absolutely no UniMAC activity is allowed | ||
| 3138 | */ | ||
| 3139 | if (phy_is_internal(priv->phydev)) | ||
| 3140 | bcmgenet_power_up(priv, GENET_POWER_PASSIVE); | ||
| 3141 | |||
| 3126 | bcmgenet_umac_reset(priv); | 3142 | bcmgenet_umac_reset(priv); |
| 3127 | 3143 | ||
| 3128 | ret = init_umac(priv); | 3144 | ret = init_umac(priv); |
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 1ea838946318..7a59879d441f 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h | |||
| @@ -354,6 +354,7 @@ struct bcmgenet_mib_counters { | |||
| 354 | #define EXT_GPHY_CTRL 0x1C | 354 | #define EXT_GPHY_CTRL 0x1C |
| 355 | #define EXT_CFG_IDDQ_BIAS (1 << 0) | 355 | #define EXT_CFG_IDDQ_BIAS (1 << 0) |
| 356 | #define EXT_CFG_PWR_DOWN (1 << 1) | 356 | #define EXT_CFG_PWR_DOWN (1 << 1) |
| 357 | #define EXT_CK25_DIS (1 << 4) | ||
| 357 | #define EXT_GPHY_RESET (1 << 5) | 358 | #define EXT_GPHY_RESET (1 << 5) |
| 358 | 359 | ||
| 359 | /* DMA rings size */ | 360 | /* DMA rings size */ |
| @@ -663,6 +664,7 @@ int bcmgenet_mii_init(struct net_device *dev); | |||
| 663 | int bcmgenet_mii_config(struct net_device *dev, bool init); | 664 | int bcmgenet_mii_config(struct net_device *dev, bool init); |
| 664 | void bcmgenet_mii_exit(struct net_device *dev); | 665 | void bcmgenet_mii_exit(struct net_device *dev); |
| 665 | void bcmgenet_mii_reset(struct net_device *dev); | 666 | void bcmgenet_mii_reset(struct net_device *dev); |
| 667 | void bcmgenet_phy_power_set(struct net_device *dev, bool enable); | ||
| 666 | void bcmgenet_mii_setup(struct net_device *dev); | 668 | void bcmgenet_mii_setup(struct net_device *dev); |
| 667 | 669 | ||
| 668 | /* Wake-on-LAN routines */ | 670 | /* Wake-on-LAN routines */ |
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 446889cc3c6a..6d3b66a103cc 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c | |||
| @@ -168,7 +168,7 @@ void bcmgenet_mii_reset(struct net_device *dev) | |||
| 168 | } | 168 | } |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | static void bcmgenet_ephy_power_up(struct net_device *dev) | 171 | void bcmgenet_phy_power_set(struct net_device *dev, bool enable) |
| 172 | { | 172 | { |
| 173 | struct bcmgenet_priv *priv = netdev_priv(dev); | 173 | struct bcmgenet_priv *priv = netdev_priv(dev); |
| 174 | u32 reg = 0; | 174 | u32 reg = 0; |
| @@ -178,14 +178,25 @@ static void bcmgenet_ephy_power_up(struct net_device *dev) | |||
| 178 | return; | 178 | return; |
| 179 | 179 | ||
| 180 | reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL); | 180 | reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL); |
| 181 | reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN); | 181 | if (enable) { |
| 182 | reg |= EXT_GPHY_RESET; | 182 | reg &= ~EXT_CK25_DIS; |
| 183 | bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); | 183 | bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); |
| 184 | mdelay(2); | 184 | mdelay(1); |
| 185 | |||
| 186 | reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN); | ||
| 187 | reg |= EXT_GPHY_RESET; | ||
| 188 | bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); | ||
| 189 | mdelay(1); | ||
| 185 | 190 | ||
| 186 | reg &= ~EXT_GPHY_RESET; | 191 | reg &= ~EXT_GPHY_RESET; |
| 192 | } else { | ||
| 193 | reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN | EXT_GPHY_RESET; | ||
| 194 | bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); | ||
| 195 | mdelay(1); | ||
| 196 | reg |= EXT_CK25_DIS; | ||
| 197 | } | ||
| 187 | bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); | 198 | bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); |
| 188 | udelay(20); | 199 | udelay(60); |
| 189 | } | 200 | } |
| 190 | 201 | ||
| 191 | static void bcmgenet_internal_phy_setup(struct net_device *dev) | 202 | 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 | struct bcmgenet_priv *priv = netdev_priv(dev); | 204 | struct bcmgenet_priv *priv = netdev_priv(dev); |
| 194 | u32 reg; | 205 | u32 reg; |
| 195 | 206 | ||
| 196 | /* Power up EPHY */ | 207 | /* Power up PHY */ |
| 197 | bcmgenet_ephy_power_up(dev); | 208 | bcmgenet_phy_power_set(dev, true); |
| 198 | /* enable APD */ | 209 | /* enable APD */ |
| 199 | reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); | 210 | reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); |
| 200 | reg |= EXT_PWR_DN_EN_LD; | 211 | reg |= EXT_PWR_DN_EN_LD; |
