diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2008-11-22 02:18:59 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-22 02:18:59 +0100 |
commit | 6833c043f9fc03696fde623914c4a0277df2a0bc (patch) | |
tree | 2b8dbe4348da2182c7832a61ccac90512a819e36 | |
parent | tg3: Prevent corruption at 10 / 100Mbps w CLKREQ (diff) | |
download | linux-6833c043f9fc03696fde623914c4a0277df2a0bc.tar.xz linux-6833c043f9fc03696fde623914c4a0277df2a0bc.zip |
tg3: Enable GPHY APD on select devices
GPHY Autopowerdown (APD) is a way to save power when energy is not
detected on the wire. At the moment, only the 5784 and 5761 are
capable of enabling this mode.
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>
-rw-r--r-- | drivers/net/tg3.c | 52 | ||||
-rw-r--r-- | drivers/net/tg3.h | 2 |
2 files changed, 48 insertions, 6 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 659fb9978195..6972fe5ccbf6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1474,6 +1474,34 @@ static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); } +static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) +{ + u32 reg; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + return; + + reg = MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_SCR5_SEL | + MII_TG3_MISC_SHDW_SCR5_LPED | + MII_TG3_MISC_SHDW_SCR5_DLPTLM | + MII_TG3_MISC_SHDW_SCR5_SDTL | + MII_TG3_MISC_SHDW_SCR5_C125OE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable) + reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD; + + tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); + + + reg = MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_APD_SEL | + MII_TG3_MISC_SHDW_APD_WKTM_84MS; + if (enable) + reg |= MII_TG3_MISC_SHDW_APD_ENABLE; + + tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); +} + static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) { u32 phy; @@ -1816,16 +1844,15 @@ static int tg3_phy_reset(struct tg3 *tp) udelay(40); tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); } - - /* Disable GPHY autopowerdown. */ - tg3_writephy(tp, MII_TG3_MISC_SHDW, - MII_TG3_MISC_SHDW_WREN | - MII_TG3_MISC_SHDW_APD_SEL | - MII_TG3_MISC_SHDW_APD_WKTM_84MS); } tg3_phy_apply_otp(tp); + if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + tg3_phy_toggle_apd(tp, true); + else + tg3_phy_toggle_apd(tp, false); + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -10264,6 +10291,10 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_LOOPBACK_FAILED; + /* Turn off gphy autopowerdown. */ + if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + tg3_phy_toggle_apd(tp, false); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { @@ -10308,6 +10339,10 @@ static int tg3_test_loopback(struct tg3 *tp) err |= TG3_PHY_LOOPBACK_FAILED; } + /* Re-enable gphy autopowerdown. */ + if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + tg3_phy_toggle_apd(tp, true); + return err; } @@ -11596,6 +11631,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (cfg2 & (1 << 18)) tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && + GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX && + (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) + tp->tg3_flags3 |= TG3_FLG3_PHY_ENABLE_APD; + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { u32 cfg3; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 53684b9b83f9..eba62e2074ca 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1822,6 +1822,7 @@ #define NIC_SRAM_DATA_CFG_2 0x00000d38 +#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00000400 #define SHASTA_EXT_LED_MODE_MASK 0x00018000 #define SHASTA_EXT_LED_LEGACY 0x00000000 #define SHASTA_EXT_LED_SHARED 0x00008000 @@ -2619,6 +2620,7 @@ struct tg3 { #define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 #define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400 #define TG3_FLG3_CLKREQ_BUG 0x00000800 +#define TG3_FLG3_PHY_ENABLE_APD 0x00001000 struct timer_list timer; u16 timer_counter; |