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) */