Module Name:    src
Committed By:   msaitoh
Date:           Wed Dec 16 14:37:26 UTC 2009

Modified Files:
        src/sys/dev/mii: igphy.c
        src/sys/dev/pci: if_wm.c if_wmvar.h

Log Message:
Sync with Intel's original em driver:
- Add dspcode for igp3 and use it when the EEPROM isn't available.
- Add some delays.
- Stop the PHY transmitter before patching the DSP code and restart it after 
wrote.
- Save and restore register 0x2f5b.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/mii/igphy.c
cvs rdiff -u -r1.182 -r1.183 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/if_wmvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/mii/igphy.c
diff -u src/sys/dev/mii/igphy.c:1.19 src/sys/dev/mii/igphy.c:1.20
--- src/sys/dev/mii/igphy.c:1.19	Wed Dec 16 04:50:35 2009
+++ src/sys/dev/mii/igphy.c	Wed Dec 16 14:37:26 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: igphy.c,v 1.19 2009/12/16 04:50:35 msaitoh Exp $	*/
+/*	$NetBSD: igphy.c,v 1.20 2009/12/16 14:37:26 msaitoh Exp $	*/
 
 /*
  * The Intel copyright applies to the analog register setup, and the
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.19 2009/12/16 04:50:35 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.20 2009/12/16 14:37:26 msaitoh Exp $");
 
 #include "opt_mii.h"
 
@@ -94,10 +94,12 @@
 	struct mii_softc sc_mii;
 	int sc_smartspeed;
 	uint32_t sc_mactype;
+	uint32_t sc_macflags;
 };
 
 static void igphy_reset(struct mii_softc *);
 static void igphy_load_dspcode(struct mii_softc *);
+static void igphy_load_dspcode_igp3(struct mii_softc *);
 static void igphy_smartspeed_workaround(struct mii_softc *sc);
 
 static int	igphymatch(device_t, cfdata_t, void *);
@@ -152,6 +154,8 @@
 	dict = device_properties(parent);
 	if (!prop_dictionary_get_uint32(dict, "mactype", &igsc->sc_mactype))
 		aprint_error("WARNING! Failed to get mactype\n");
+	if (!prop_dictionary_get_uint32(dict, "macflags", &igsc->sc_macflags))
+		aprint_error("WARNING! Failed to get macflags\n");
 
 	sc->mii_dev = self;
 	sc->mii_inst = mii->mii_instance;
@@ -176,62 +180,127 @@
 	aprint_normal("\n");
 }
 
+typedef struct {
+	int reg;
+	uint16_t val;
+} dspcode;
+
+static const dspcode igp1code[] = {
+	{ 0x1f95, 0x0001 },
+	{ 0x1f71, 0xbd21 },
+	{ 0x1f79, 0x0018 },
+	{ 0x1f30, 0x1600 },
+	{ 0x1f31, 0x0014 },
+	{ 0x1f32, 0x161c },
+	{ 0x1f94, 0x0003 },
+	{ 0x1f96, 0x003f },
+	{ 0x2010, 0x0008 },
+	{ 0, 0 },
+};
+
+static const dspcode igp1code_r2[] = {
+	{ 0x1f73, 0x0099 },
+	{ 0, 0 },
+};
+
+static const dspcode igp3code[] = {
+	{ 0x2f5b, 0x9018},
+	{ 0x2f52, 0x0000},
+	{ 0x2fb1, 0x8b24},
+	{ 0x2fb2, 0xf8f0},
+	{ 0x2010, 0x10b0},
+	{ 0x2011, 0x0000},
+	{ 0x20dd, 0x249a},
+	{ 0x20de, 0x00d3},
+	{ 0x28b4, 0x04ce},
+	{ 0x2f70, 0x29e4},
+	{ 0x0000, 0x0140},
+	{ 0x1f30, 0x1606},
+	{ 0x1f31, 0xb814},
+	{ 0x1f35, 0x002a},
+	{ 0x1f3e, 0x0067},
+	{ 0x1f54, 0x0065},
+	{ 0x1f55, 0x002a},
+	{ 0x1f56, 0x002a},
+	{ 0x1f72, 0x3fb0},
+	{ 0x1f76, 0xc0ff},
+	{ 0x1f77, 0x1dec},
+	{ 0x1f78, 0xf9ef},
+	{ 0x1f79, 0x0210},
+	{ 0x1895, 0x0003},
+	{ 0x1796, 0x0008},
+	{ 0x1798, 0xd008},
+	{ 0x1898, 0xd918},
+	{ 0x187a, 0x0800},
+	{ 0x0019, 0x008d},
+	{ 0x001b, 0x2080},
+	{ 0x0014, 0x0045},
+	{ 0x0000, 0x1340},
+	{ 0, 0 },
+};
+
+/* DSP patch for igp1 and igp2 */
 static void
 igphy_load_dspcode(struct mii_softc *sc)
 {
 	struct igphy_softc *igsc = (struct igphy_softc *) sc;
-	static const struct {
-		int reg;
-		uint16_t val;
-	} dspcode[] = {
-		{ 0x1f95, 0x0001 },
-		{ 0x1f71, 0xbd21 },
-		{ 0x1f79, 0x0018 },
-		{ 0x1f30, 0x1600 },
-		{ 0x1f31, 0x0014 },
-		{ 0x1f32, 0x161c },
-		{ 0x1f94, 0x0003 },
-		{ 0x1f96, 0x003f },
-		{ 0x2010, 0x0008 },
-		{ 0, 0 },
-	};
+	const dspcode *code;
+	uint16_t reg;
 	int i;
 
 	/* This workaround is only for 82541 and 82547 */
 	switch (igsc->sc_mactype) {
 	case WM_T_82541:
 	case WM_T_82547:
+		code = igp1code;
+		break;
 	case WM_T_82541_2:
 	case WM_T_82547_2:
+		code = igp1code_r2;
 		break;
 	default:
-		/* byebye */
-		return;
+		return;	/* byebye */
 	}
 
-	delay(10);
+	/* Delay after phy reset to enable NVM configuration to load */
+	delay(20000);
+
+	/*
+	 * Save off the current value of register 0x2F5B to be restored at
+	 * the end of this routine.
+	 */
+	reg = IGPHY_READ(sc, 0x2f5b);
+
+	/* Disabled the PHY transmitter */
+	IGPHY_WRITE(sc, 0x2f5b, 0x0003);
+
+	delay(20000);
 
 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
 	PHY_WRITE(sc, 0x0000, 0x0140);
 
-	delay(5);
+	delay(5000);
 
-	switch (igsc->sc_mactype) {
-	case WM_T_82541:
-	case WM_T_82547:
-		for (i = 0; dspcode[i].reg != 0; i++)
-			IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
-		break;
-	case WM_T_82541_2:
-	case WM_T_82547_2:
-		IGPHY_WRITE(sc, 0x1f73, 0x0099);
-		break;
-	default:
-		break;
-	}
+	for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
+		IGPHY_WRITE(sc, code[i].reg, code[i].val);
 
 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
 	PHY_WRITE(sc, 0x0000, 0x3300);
+
+	delay(20000);
+
+	/* Now enable the transmitter */
+	IGPHY_WRITE(sc, 0x2f5b, reg);
+}
+
+static void
+igphy_load_dspcode_igp3(struct mii_softc *sc)
+{
+	const dspcode *code = igp3code;
+	int i;
+
+	for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
+		IGPHY_WRITE(sc, code[i].reg, code[i].val);
 }
 
 static void
@@ -241,7 +310,23 @@
 	uint16_t fused, fine, coarse;
 
 	mii_phy_reset(sc);
-	igphy_load_dspcode(sc);
+	delay(150);
+
+	switch (igsc->sc_mactype) {
+	case WM_T_82541:
+	case WM_T_82547:
+	case WM_T_82541_2:
+	case WM_T_82547_2:
+		igphy_load_dspcode(sc);
+		break;
+	case WM_T_ICH8:
+	case WM_T_ICH9:
+		if ((igsc->sc_macflags & WM_F_EEPROM_INVALID) != 0)
+			igphy_load_dspcode_igp3(sc);
+		break;
+	default:	/* Not for ICH10, PCH and 8257[12] */
+		break;
+	}
 
 	if (igsc->sc_mactype == WM_T_82547) {
 		fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
@@ -266,7 +351,7 @@
 			    ANALOG_FUSE_ENABLE_SW_CONTROL);
 		}
 	}
-	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
+	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
 }
 
 

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.182 src/sys/dev/pci/if_wm.c:1.183
--- src/sys/dev/pci/if_wm.c:1.182	Wed Dec 16 04:50:35 2009
+++ src/sys/dev/pci/if_wm.c	Wed Dec 16 14:37:26 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.182 2009/12/16 04:50:35 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.183 2009/12/16 14:37:26 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.182 2009/12/16 04:50:35 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.183 2009/12/16 14:37:26 msaitoh Exp $");
 
 #include "bpfilter.h"
 #include "rnd.h"
@@ -380,22 +380,6 @@
 	(sc)->sc_rxtailp = &(m)->m_next;				\
 } while (/*CONSTCOND*/0)
 
-/* sc_flags */
-#define	WM_F_HAS_MII		0x0001	/* has MII */
-#define	WM_F_EEPROM_HANDSHAKE	0x0002	/* requires EEPROM handshake */
-#define	WM_F_EEPROM_SEMAPHORE	0x0004	/* EEPROM with semaphore */
-#define	WM_F_EEPROM_EERDEEWR	0x0008	/* EEPROM access via EERD/EEWR */
-#define	WM_F_EEPROM_SPI		0x0010	/* EEPROM is SPI */
-#define	WM_F_EEPROM_FLASH	0x0020	/* EEPROM is FLASH */
-#define	WM_F_EEPROM_INVALID	0x0040	/* EEPROM not present (bad checksum) */
-#define	WM_F_IOH_VALID		0x0080	/* I/O handle is valid */
-#define	WM_F_BUS64		0x0100	/* bus is 64-bit */
-#define	WM_F_PCIX		0x0200	/* bus is PCI-X */
-#define	WM_F_CSA		0x0400	/* bus is CSA */
-#define	WM_F_PCIE		0x0800	/* bus is PCI-Express */
-#define WM_F_SWFW_SYNC		0x1000  /* Software-Firmware synchronisation */
-#define WM_F_SWFWHW_SYNC	0x2000  /* Software-Firmware synchronisation */
-
 #ifdef WM_EVENT_COUNTERS
 #define	WM_EVCNT_INCR(ev)	(ev)->ev_count++
 #define	WM_EVCNT_ADD(ev, val)	(ev)->ev_count += (val)
@@ -981,7 +965,7 @@
 			sc->sc_type = WM_T_82542_2_0;
 	}
 
-	/* Set device properties */
+	/* Set device properties (mactype)*/
 	dict = device_properties(sc->sc_dev);
 	prop_dictionary_set_uint32(dict, "mactype", sc->sc_type);
 
@@ -1351,18 +1335,26 @@
 	 * that no EEPROM is attached.
 	 */
 
-	/*
-	 * Validate the EEPROM checksum. If the checksum fails, flag this for
-	 * later, so we can fail future reads from the EEPROM.
-	 */
-	if (wm_validate_eeprom_checksum(sc)) {
+	/* Check whether EEPROM is present or not */
+	if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
+		/* Not found */
+		sc->sc_flags |= WM_F_EEPROM_INVALID;
+	} else {
 		/*
-		 * Read twice again because some PCI-e parts fail the first
-		 * check due to the link being in sleep state.
+		 * Validate the EEPROM checksum. If the checksum fails, flag
+		 * this for later, so we can fail future reads from the EEPROM.
 		 */
-		if (wm_validate_eeprom_checksum(sc))
-			sc->sc_flags |= WM_F_EEPROM_INVALID;
+		if (wm_validate_eeprom_checksum(sc)) {
+			/*
+			 * Read twice again because some PCI-e parts fail the
+			 * first check due to the link being in sleep state.
+			 */
+			if (wm_validate_eeprom_checksum(sc))
+				sc->sc_flags |= WM_F_EEPROM_INVALID;
+		}
 	}
+	/* Set device properties (macflags)*/
+	prop_dictionary_set_uint32(dict, "macflags", sc->sc_flags);
 
 	if (sc->sc_flags & WM_F_EEPROM_INVALID)
 		aprint_verbose_dev(sc->sc_dev, "No EEPROM\n");

Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.3 src/sys/dev/pci/if_wmvar.h:1.4
--- src/sys/dev/pci/if_wmvar.h:1.3	Wed Dec 16 04:50:36 2009
+++ src/sys/dev/pci/if_wmvar.h	Wed Dec 16 14:37:26 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmvar.h,v 1.3 2009/12/16 04:50:36 msaitoh Exp $	*/
+/*	$NetBSD: if_wmvar.h,v 1.4 2009/12/16 14:37:26 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -71,6 +71,22 @@
 #ifndef _DEV_PCI_IF_WMVAR_H_
 #define _DEV_PCI_IF_WMVAR_H_
 
+/* sc_flags */
+#define	WM_F_HAS_MII		0x0001	/* has MII */
+#define	WM_F_EEPROM_HANDSHAKE	0x0002	/* requires EEPROM handshake */
+#define	WM_F_EEPROM_SEMAPHORE	0x0004	/* EEPROM with semaphore */
+#define	WM_F_EEPROM_EERDEEWR	0x0008	/* EEPROM access via EERD/EEWR */
+#define	WM_F_EEPROM_SPI		0x0010	/* EEPROM is SPI */
+#define	WM_F_EEPROM_FLASH	0x0020	/* EEPROM is FLASH */
+#define	WM_F_EEPROM_INVALID	0x0040	/* EEPROM not present (bad checksum) */
+#define	WM_F_IOH_VALID		0x0080	/* I/O handle is valid */
+#define	WM_F_BUS64		0x0100	/* bus is 64-bit */
+#define	WM_F_PCIX		0x0200	/* bus is PCI-X */
+#define	WM_F_CSA		0x0400	/* bus is CSA */
+#define	WM_F_PCIE		0x0800	/* bus is PCI-Express */
+#define WM_F_SWFW_SYNC		0x1000  /* Software-Firmware synchronisation */
+#define WM_F_SWFWHW_SYNC	0x2000  /* Software-Firmware synchronisation */
+
 typedef enum {
 	WM_T_unknown		= 0,
 	WM_T_82542_2_0,			/* i82542 2.0 (really old) */

Reply via email to