From: Matt Carlson <mcarlson@broadcom.com>
Subject: tg3: 5785 and 57780 asic revs not working
References: bnc#580780
Patch-mainline: Never

There is a known problem with phylib that causes a lot of problems.
Phylib does not load phy modules as it detects devices on the MDIO bus.
If the phylib module gets loaded as a dependancy of tg3, there will be
no opportunity to load the needed broadcom.ko module before tg3 requests
phylib to probe the MDIO bus.  The result will be that tg3 will fail to
attach to 5785 and 57780 devices.

There are several known solutions to this problem.  (None of these
should go upstream.  The upstream fix should be to get phylib to load
modules for devices it encounters.)  Only one of them need be applied.

1) Statically link in the broadcom.ko module into the kernel.

2) Add the following to /etc/modprobe.d/local.conf or its equivalent:

install tg3 /sbin/modprobe broadcom; /sbin/modprobe --ignore-install tg3

3) Apply the following patch:

Signed-off-by: Brandon Philips <bphilips@suse.de>

---
 drivers/net/tg3.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/tg3.h |    9 +++++
 2 files changed, 92 insertions(+)

--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1998,6 +1998,58 @@ static int tg3_phy_reset(struct tg3 *tp)
 		tg3_phy_toggle_apd(tp, false);
 
 out:
+	if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM50610 ||
+	    (tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM50610M) {
+		u32 reg;
+
+		/* Enable SM_DSP clock and tx 6dB coding. */
+		reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+		      MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+		      MII_TG3_AUXCTL_ACTL_TX_6DB;
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+
+		reg = MII_TG3_DSP_EXP8_REJ2MHz;
+		tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, reg);
+
+		/* Apply workaround to A0 revision parts only. */
+		if (tp->phy_id == TG3_PHY_ID_BCM50610 ||
+		    tp->phy_id == TG3_PHY_ID_BCM50610M) {
+			tg3_phydsp_write(tp, 0x001F, 0x0300);
+			tg3_phydsp_write(tp, 0x601F, 0x0002);
+			tg3_phydsp_write(tp, 0x0F75, 0x003C);
+			tg3_phydsp_write(tp, 0x0F96, 0x0010);
+			tg3_phydsp_write(tp, 0x0F97, 0x0C0C);
+		}
+
+		/* Turn off SM_DSP clock. */
+		reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+		      MII_TG3_AUXCTL_ACTL_TX_6DB;
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+
+		/* Clear all mode configuration bits. */
+		reg = MII_TG3_MISC_SHDW_WREN |
+		      MII_TG3_MISC_SHDW_RGMII_SEL;
+		tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+	}
+	if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM57780) {
+		u32 reg;
+
+		/* Enable SM_DSP clock and tx 6dB coding. */
+		reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+		      MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+		      MII_TG3_AUXCTL_ACTL_TX_6DB;
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_EXP75);
+		tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &reg);
+		reg |= MII_TG3_DSP_EXP75_SUP_CM_OSC;
+		tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, reg);
+
+		/* Turn off SM_DSP clock. */
+		reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+		      MII_TG3_AUXCTL_ACTL_TX_6DB;
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+	}
 	if (tp->phy_flags & TG3_PHYFLG_ADC_BUG) {
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
 		tg3_phydsp_write(tp, 0x201f, 0x2aaa);
@@ -2054,6 +2106,22 @@ out:
 		/* adjust output voltage */
 		tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
 	}
+	else if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+		u32 brcmtest;
+		if (!tg3_readphy(tp, MII_TG3_FET_TEST, &brcmtest) &&
+		    !tg3_writephy(tp, MII_TG3_FET_TEST,
+				  brcmtest | MII_TG3_FET_SHADOW_EN)) {
+			u32 val, reg = MII_TG3_FET_SHDW_AUXMODE4;
+
+			if (!tg3_readphy(tp, reg, &val)) {
+				val &= ~MII_TG3_FET_SHDW_AM4_LED_MASK;
+				val |= MII_TG3_FET_SHDW_AM4_LED_MODE1;
+				tg3_writephy(tp, reg, val);
+			}
+
+			tg3_writephy(tp, MII_TG3_FET_TEST, brcmtest);
+		}
+	}
 
 	tg3_phy_toggle_automdix(tp, 1);
 	tg3_phy_set_wirespeed(tp);
@@ -3288,6 +3356,15 @@ relink:
 
	tg3_phy_eee_adjust(tp, current_link_up);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+		if (tp->link_config.active_speed == SPEED_10)
+			tw32(MAC_MI_STAT,
+			     MAC_MI_STAT_10MBPS_MODE |
+			     MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+		else
+			tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+	}
+
 	if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
 		/* Polled via timer. */
 		tw32_f(MAC_EVENT, 0);
@@ -13411,9 +13488,11 @@ static int __devinit tg3_get_invariants(
 	    GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
 		tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
 
+#if 0
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 		tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB;
+#endif
 
 	err = tg3_mdio_init(tp);
 	if (err)
@@ -14203,6 +14282,10 @@ static char * __devinit tg3_phy_string(s
 	case TG3_PHY_ID_BCM5718S:	return "5718S";
 	case TG3_PHY_ID_BCM57765:	return "57765";
 	case TG3_PHY_ID_BCM5719C:	return "5719C";
+	case TG3_PHY_ID_BCM50610:	return "50610";
+	case TG3_PHY_ID_BCM50610M:	return "50610M";
+	case TG3_PHY_ID_BCMAC131:	return "AC131";
+	case TG3_PHY_ID_BCM57780:	return "57780";
 	case TG3_PHY_ID_BCM8002:	return "8002/serdes";
 	case 0:			return "serdes";
 	default:		return "unknown";
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2072,6 +2072,7 @@
 #define  MII_TG3_DSP_EXP8_REJ2MHz	0x0001
 #define  MII_TG3_DSP_EXP8_AEDW		0x0200
 #define MII_TG3_DSP_EXP75		0x0f75
+#define  MII_TG3_DSP_EXP75_SUP_CM_OSC	0x0001
 #define MII_TG3_DSP_EXP96		0x0f96
 #define MII_TG3_DSP_EXP97		0x0f97
 
@@ -2127,6 +2128,8 @@
 #define MII_TG3_MISC_SHDW_SCR5_LPED	0x0010
 #define MII_TG3_MISC_SHDW_SCR5_SEL	0x1400
 
+#define MII_TG3_MISC_SHDW_RGMII_SEL	0x2c00
+
 #define MII_TG3_TEST1			0x1e
 #define MII_TG3_TEST1_TRIM_EN		0x0010
 #define MII_TG3_TEST1_CRC_EN		0x8000
@@ -2144,6 +2147,8 @@
 #define  MII_TG3_FET_SHDW_MISCCTRL_MDIX	0x4000
 
 #define MII_TG3_FET_SHDW_AUXMODE4	0x1a
+#define MII_TG3_FET_SHDW_AM4_LED_MODE1	0x0001
+#define MII_TG3_FET_SHDW_AM4_LED_MASK	0x0003
 #define MII_TG3_FET_SHDW_AUXMODE4_SBPD	0x0008
 
 #define MII_TG3_FET_SHDW_AUXSTAT2	0x1b
@@ -2922,6 +2927,10 @@ struct tg3 {
 #define TG3_PHY_ID_BCM5719C		0x5c0d8a20
 #define TG3_PHY_ID_BCM5906		0xdc00ac40
 #define TG3_PHY_ID_BCM8002		0x60010140
+#define TG3_PHY_ID_BCM50610		0xbc050d60
+#define TG3_PHY_ID_BCM50610M		0xbc050d70
+#define TG3_PHY_ID_BCMAC131		0xbc050c70
+#define TG3_PHY_ID_BCM57780		0x5c0d8990
 #define TG3_PHY_ID_INVALID		0xffffffff
 
 #define PHY_ID_RTL8211C			0x001cc910
