aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2007-11-13 00:08:03 -0500
committerDavid S. Miller <davem@davemloft.net>2007-11-13 00:08:03 -0500
commitce057f01956bfcb3cb8588091000ae546be78e00 (patch)
tree6438c33bcdde387ab191912e970b2fb65696b0a0 /drivers/net/tg3.c
parentc88864df27590b80fca4a991e0c257d1757cec41 (diff)
[TG3]: 5784 / 5764 GPHY power down fix
5784 and 5764 devices fail to link / pass traffic after one load / unload cycle. This happens because of a hardware bug in the new CPMU. During normal operation, the MAC depends on the PHY clock being available. When the PHY is powered down, the clock the MAC depends on is disabled. The fix is to switch the MAC clock to an alternate source before powering down the PHY, and to restore the MAC clock to the PHY source upon device resume. 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.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ddeaa0c7830..82b1cf0e2d1 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1106,6 +1106,19 @@ static int tg3_phy_reset(struct tg3 *tp)
1106 if (err) 1106 if (err)
1107 return err; 1107 return err;
1108 1108
1109 if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
1110 tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
1111 u32 val;
1112
1113 val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
1114 if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
1115 CPMU_LSPD_1000MB_MACCLK_12_5) {
1116 val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
1117 udelay(40);
1118 tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
1119 }
1120 }
1121
1109out: 1122out:
1110 if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { 1123 if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
1111 tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); 1124 tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1297,6 +1310,8 @@ static void tg3_nvram_unlock(struct tg3 *);
1297 1310
1298static void tg3_power_down_phy(struct tg3 *tp) 1311static void tg3_power_down_phy(struct tg3 *tp)
1299{ 1312{
1313 u32 val;
1314
1300 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { 1315 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
1301 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { 1316 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
1302 u32 sg_dig_ctrl = tr32(SG_DIG_CTRL); 1317 u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -1311,8 +1326,6 @@ static void tg3_power_down_phy(struct tg3 *tp)
1311 } 1326 }
1312 1327
1313 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { 1328 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
1314 u32 val;
1315
1316 tg3_bmcr_reset(tp); 1329 tg3_bmcr_reset(tp);
1317 val = tr32(GRC_MISC_CFG); 1330 val = tr32(GRC_MISC_CFG);
1318 tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); 1331 tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
@@ -1332,6 +1345,15 @@ static void tg3_power_down_phy(struct tg3 *tp)
1332 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && 1345 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
1333 (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) 1346 (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
1334 return; 1347 return;
1348
1349 if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
1350 tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
1351 val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
1352 val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
1353 val |= CPMU_LSPD_1000MB_MACCLK_12_5;
1354 tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
1355 }
1356
1335 tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); 1357 tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
1336} 1358}
1337 1359