diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2008-11-03 19:54:15 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-03 19:54:15 -0500 |
commit | 0a459aac9d151c2e36ec65723b9b845b24c5cbc3 (patch) | |
tree | a3534dee05580e2061ef270e0b81f25ad8a6a256 /drivers/net/tg3.c | |
parent | 05ac4cb7dff4515447dce6e9a56c4de6b7e426d5 (diff) |
tg3: Allow WOL for phylib controlled Broadcom phys
This patch allows WOL to be enabled for Broadcom phys under phylib
control. The only exception is the AC131, which has a completely
different register set.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e64721b185d1..d0f314c6dbb0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -1963,7 +1963,7 @@ static int tg3_halt_cpu(struct tg3 *, u32); | |||
1963 | static int tg3_nvram_lock(struct tg3 *); | 1963 | static int tg3_nvram_lock(struct tg3 *); |
1964 | static void tg3_nvram_unlock(struct tg3 *); | 1964 | static void tg3_nvram_unlock(struct tg3 *); |
1965 | 1965 | ||
1966 | static void tg3_power_down_phy(struct tg3 *tp) | 1966 | static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) |
1967 | { | 1967 | { |
1968 | u32 val; | 1968 | u32 val; |
1969 | 1969 | ||
@@ -1986,10 +1986,15 @@ static void tg3_power_down_phy(struct tg3 *tp) | |||
1986 | tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); | 1986 | tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); |
1987 | udelay(40); | 1987 | udelay(40); |
1988 | return; | 1988 | return; |
1989 | } else if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { | 1989 | } else if (do_low_power) { |
1990 | tg3_writephy(tp, MII_TG3_EXT_CTRL, | 1990 | tg3_writephy(tp, MII_TG3_EXT_CTRL, |
1991 | MII_TG3_EXT_CTRL_FORCE_LED_OFF); | 1991 | MII_TG3_EXT_CTRL_FORCE_LED_OFF); |
1992 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); | 1992 | |
1993 | tg3_writephy(tp, MII_TG3_AUX_CTRL, | ||
1994 | MII_TG3_AUXCTL_SHDWSEL_PWRCTL | | ||
1995 | MII_TG3_AUXCTL_PCTL_100TX_LPWR | | ||
1996 | MII_TG3_AUXCTL_PCTL_SPR_ISOLATE | | ||
1997 | MII_TG3_AUXCTL_PCTL_VREG_11V); | ||
1993 | } | 1998 | } |
1994 | 1999 | ||
1995 | /* The PHY should not be powered down on some chips because | 2000 | /* The PHY should not be powered down on some chips because |
@@ -2052,7 +2057,7 @@ static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1) | |||
2052 | static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | 2057 | static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) |
2053 | { | 2058 | { |
2054 | u32 misc_host_ctrl; | 2059 | u32 misc_host_ctrl; |
2055 | bool device_should_wake; | 2060 | bool device_should_wake, do_low_power; |
2056 | 2061 | ||
2057 | /* Make sure register accesses (indirect or otherwise) | 2062 | /* Make sure register accesses (indirect or otherwise) |
2058 | * will function correctly. | 2063 | * will function correctly. |
@@ -2091,10 +2096,11 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
2091 | (tp->tg3_flags & TG3_FLAG_WOL_ENABLE); | 2096 | (tp->tg3_flags & TG3_FLAG_WOL_ENABLE); |
2092 | 2097 | ||
2093 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { | 2098 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { |
2099 | do_low_power = false; | ||
2094 | if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) && | 2100 | if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) && |
2095 | !tp->link_config.phy_is_low_power) { | 2101 | !tp->link_config.phy_is_low_power) { |
2096 | struct phy_device *phydev; | 2102 | struct phy_device *phydev; |
2097 | u32 advertising; | 2103 | u32 phyid, advertising; |
2098 | 2104 | ||
2099 | phydev = tp->mdio_bus->phy_map[PHY_ADDR]; | 2105 | phydev = tp->mdio_bus->phy_map[PHY_ADDR]; |
2100 | 2106 | ||
@@ -2124,8 +2130,19 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
2124 | phydev->advertising = advertising; | 2130 | phydev->advertising = advertising; |
2125 | 2131 | ||
2126 | phy_start_aneg(phydev); | 2132 | phy_start_aneg(phydev); |
2133 | |||
2134 | phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask; | ||
2135 | if (phyid != TG3_PHY_ID_BCMAC131) { | ||
2136 | phyid &= TG3_PHY_OUI_MASK; | ||
2137 | if (phyid == TG3_PHY_OUI_1 && | ||
2138 | phyid == TG3_PHY_OUI_2 && | ||
2139 | phyid == TG3_PHY_OUI_3) | ||
2140 | do_low_power = true; | ||
2141 | } | ||
2127 | } | 2142 | } |
2128 | } else { | 2143 | } else { |
2144 | do_low_power = false; | ||
2145 | |||
2129 | if (tp->link_config.phy_is_low_power == 0) { | 2146 | if (tp->link_config.phy_is_low_power == 0) { |
2130 | tp->link_config.phy_is_low_power = 1; | 2147 | tp->link_config.phy_is_low_power = 1; |
2131 | tp->link_config.orig_speed = tp->link_config.speed; | 2148 | tp->link_config.orig_speed = tp->link_config.speed; |
@@ -2169,7 +2186,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
2169 | u32 mac_mode; | 2186 | u32 mac_mode; |
2170 | 2187 | ||
2171 | if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { | 2188 | if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { |
2172 | if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { | 2189 | if (do_low_power) { |
2173 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); | 2190 | tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); |
2174 | udelay(40); | 2191 | udelay(40); |
2175 | } | 2192 | } |
@@ -2277,7 +2294,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
2277 | if (!(device_should_wake) && | 2294 | if (!(device_should_wake) && |
2278 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && | 2295 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && |
2279 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) | 2296 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) |
2280 | tg3_power_down_phy(tp); | 2297 | tg3_power_down_phy(tp, do_low_power); |
2281 | 2298 | ||
2282 | tg3_frob_aux_power(tp); | 2299 | tg3_frob_aux_power(tp); |
2283 | 2300 | ||