[TG3]: Prescaler fix

Internal hardware timers become inaccurate after link events.  Clock
frequency switches performed by the CPMU fail to adjust timer
prescalers.  The fix is to detect core clock frequency changes during
link events and adjust the timer prescalers accordingly.

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>
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bb3b734..ecd64a2 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3154,6 +3154,22 @@
 		err = tg3_setup_copper_phy(tp, force_reset);
 	}
 
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+		u32 val, scale;
+
+		val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+		if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+			scale = 65;
+		else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+			scale = 6;
+		else
+			scale = 12;
+
+		val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+		val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+		tw32(GRC_MISC_CFG, val);
+	}
+
 	if (tp->link_config.active_speed == SPEED_1000 &&
 	    tp->link_config.active_duplex == DUPLEX_HALF)
 		tw32(MAC_TX_LENGTHS,