Module Name: src Committed By: msaitoh Date: Thu Jan 7 17:45:58 UTC 2010
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h Log Message: Make wm_reset() and wm_gmii_reset() close to e1000 driver. At least, this change make wm_attach() be stable on ICH9. To generate a diff of this commit: cvs rdiff -u -r1.188 -r1.189 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.31 -r1.32 src/sys/dev/pci/if_wmreg.h cvs rdiff -u -r1.5 -r1.6 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/pci/if_wm.c diff -u src/sys/dev/pci/if_wm.c:1.188 src/sys/dev/pci/if_wm.c:1.189 --- src/sys/dev/pci/if_wm.c:1.188 Thu Jan 7 17:34:38 2010 +++ src/sys/dev/pci/if_wm.c Thu Jan 7 17:45:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.188 2010/01/07 17:34:38 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.189 2010/01/07 17:45:58 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.188 2010/01/07 17:34:38 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.189 2010/01/07 17:45:58 msaitoh Exp $"); #include "bpfilter.h" #include "rnd.h" @@ -535,6 +535,8 @@ static void wm_attach(device_t, device_t, void *); static int wm_is_onboard_nvm_eeprom(struct wm_softc *); static void wm_get_auto_rd_done(struct wm_softc *); +static void wm_lan_init_done(struct wm_softc *); +static void wm_get_cfg_done(struct wm_softc *); static int wm_get_swsm_semaphore(struct wm_softc *); static void wm_put_swsm_semaphore(struct wm_softc *); static int wm_poll_eerd_eewr_done(struct wm_softc *, int); @@ -555,6 +557,7 @@ static int wm_check_mng_mode_ich8lan(struct wm_softc *); static int wm_check_mng_mode_82574(struct wm_softc *); static int wm_check_mng_mode_generic(struct wm_softc *); +static int wm_check_reset_block(struct wm_softc *); static void wm_get_hw_control(struct wm_softc *); static int wm_check_for_link(struct wm_softc *); @@ -994,6 +997,7 @@ break; default: memh_valid = 0; + break; } if (memh_valid) { @@ -1171,6 +1175,7 @@ "unknown PCIXSPD %d; assuming 66MHz\n", reg & STATUS_PCIXSPD_MASK); sc->sc_bus_speed = 66; + break; } } else sc->sc_bus_speed = (reg & STATUS_PCI66) ? 66 : 33; @@ -3013,7 +3018,9 @@ static void wm_reset(struct wm_softc *sc) { - uint32_t reg; + int phy_reset = 0; + uint32_t reg, func, mask; + int i; /* * Allocate on-chip memory according to the MTU size. @@ -3074,6 +3081,37 @@ /* clear interrupt */ CSR_WRITE(sc, WMREG_IMC, 0xffffffffU); + /* Stop the transmit and receive processes. */ + CSR_WRITE(sc, WMREG_RCTL, 0); + CSR_WRITE(sc, WMREG_TCTL, TCTL_PSP); + + /* set_tbi_sbp_82543() */ + + delay(10*1000); + + /* Must acquire the MDIO ownership before MAC reset */ + switch(sc->sc_type) { + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: + i = 0; + reg = CSR_READ(sc, WMREG_EXTCNFCTR) + | EXTCNFCTR_MDIO_SW_OWNERSHIP; + do { + CSR_WRITE(sc, WMREG_EXTCNFCTR, + reg | EXTCNFCTR_MDIO_SW_OWNERSHIP); + reg = CSR_READ(sc, WMREG_EXTCNFCTR); + if ((reg & EXTCNFCTR_MDIO_SW_OWNERSHIP) != 0) + break; + reg |= EXTCNFCTR_MDIO_SW_OWNERSHIP; + delay(2*1000); + i++; + } while (i < WM_MDIO_OWNERSHIP_TIMEOUT); + break; + default: + break; + } + /* * 82541 Errata 29? & 82547 Errata 28? * See also the description about PHY_RST bit in CTRL register @@ -3086,12 +3124,11 @@ } switch (sc->sc_type) { - case WM_T_82544: - case WM_T_82540: - case WM_T_82545: - case WM_T_82546: + case WM_T_82544: /* XXX check whether WM_F_IOH_VALID is set */ case WM_T_82541: case WM_T_82541_2: + case WM_T_82547: + case WM_T_82547_2: /* * On some chipsets, a reset through a memory-mapped write * cycle can cause the chip to reset before completing the @@ -3108,26 +3145,51 @@ else CSR_WRITE(sc, WMREG_CTRL, CTRL_RST); break; - case WM_T_82545_3: case WM_T_82546_3: /* Use the shadow control register on these chips. */ CSR_WRITE(sc, WMREG_CTRL_SHADOW, CTRL_RST); break; - + case WM_T_80003: + func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1; + mask = func ? SWFW_PHY1_SM : SWFW_PHY0_SM; + reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST; + wm_get_swfw_semaphore(sc, mask); + CSR_WRITE(sc, WMREG_CTRL, reg); + wm_put_swfw_semaphore(sc, mask); + break; case WM_T_ICH8: case WM_T_ICH9: case WM_T_ICH10: + reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST; + if (wm_check_reset_block(sc) == 0) { + reg |= CTRL_PHY_RESET; + phy_reset = 1; + } wm_get_swfwhw_semaphore(sc); - CSR_WRITE(sc, WMREG_CTRL, CTRL_RST | CTRL_PHY_RESET); - delay(10000); + CSR_WRITE(sc, WMREG_CTRL, reg); + delay(20*1000); + wm_put_swfwhw_semaphore(sc); break; + case WM_T_82542_2_0: + case WM_T_82542_2_1: + case WM_T_82543: + case WM_T_82540: + case WM_T_82545: + case WM_T_82546: + case WM_T_82571: + case WM_T_82572: + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: default: /* Everything else can safely use the documented method. */ - CSR_WRITE(sc, WMREG_CTRL, CTRL_RST); + CSR_WRITE(sc, WMREG_CTRL, CSR_READ(sc, WMREG_CTRL) | CTRL_RST); break; } - delay(10000); + + if (phy_reset != 0) + wm_get_cfg_done(sc); /* reload EEPROM */ switch(sc->sc_type) { @@ -3140,12 +3202,23 @@ CSR_WRITE(sc, WMREG_CTRL_EXT, reg); delay(2000); break; + case WM_T_82540: + case WM_T_82545: + case WM_T_82545_3: + case WM_T_82546: + case WM_T_82546_3: + delay(5*1000); + /* XXX Disable HW ARPs on ASF enabled adapters */ + break; case WM_T_82541: case WM_T_82541_2: case WM_T_82547: case WM_T_82547_2: delay(20000); + /* XXX Disable HW ARPs on ASF enabled adapters */ break; + case WM_T_82571: + case WM_T_82572: case WM_T_82573: case WM_T_82574: case WM_T_82583: @@ -3154,10 +3227,27 @@ reg = CSR_READ(sc, WMREG_CTRL_EXT) | CTRL_EXT_EE_RST; CSR_WRITE(sc, WMREG_CTRL_EXT, reg); } - /* FALLTHROUGH */ - default: /* check EECD_EE_AUTORD */ wm_get_auto_rd_done(sc); + /* + * Phy configuration from NVM just starts after EECD_AUTO_RD + * is set. + */ + if ((sc->sc_type == WM_T_82573) || (sc->sc_type == WM_T_82574) + || (sc->sc_type == WM_T_82583)) + delay(25*1000); + break; + case WM_T_80003: + case WM_T_ICH8: + case WM_T_ICH9: + /* check EECD_EE_AUTORD */ + wm_get_auto_rd_done(sc); + break; + case WM_T_ICH10: /* & PCH */ + wm_lan_init_done(sc); + break; + default: + panic("%s: unknown type\n", __func__); } /* reload sc_ctrl */ @@ -3648,12 +3738,12 @@ case WM_T_ICH8: case WM_T_ICH9: case WM_T_ICH10: - for (i = 10; i > 0; i--) { + for (i = 0; i < 10; i++) { if (CSR_READ(sc, WMREG_EECD) & EECD_EE_AUTORD) break; delay(1000); } - if (i == 0) { + if (i == 10) { log(LOG_ERR, "%s: auto read from eeprom failed to " "complete\n", device_xname(sc->sc_dev)); } @@ -3662,11 +3752,95 @@ delay(5000); break; } +} - /* Phy configuration starts after EECD_AUTO_RD is set */ - if (sc->sc_type == WM_T_82573 || sc->sc_type == WM_T_82574 - || sc->sc_type == WM_T_82574) - delay(25000); +void +wm_lan_init_done(struct wm_softc *sc) +{ + uint32_t reg = 0; + int i; + + /* wait for eeprom to reload */ + switch (sc->sc_type) { + case WM_T_ICH10: /* & PCH */ + for (i = 0; i < WM_ICH8_LAN_INIT_TIMEOUT; i++) { + reg = CSR_READ(sc, WMREG_STATUS); + if ((reg & STATUS_LAN_INIT_DONE) != 0) + break; + delay(100); + } + if (i >= WM_ICH8_LAN_INIT_TIMEOUT) { + log(LOG_ERR, "%s: %s: lan_init_done failed to " + "complete\n", device_xname(sc->sc_dev), __func__); + } + break; + default: + panic("%s: %s: unknown type\n", device_xname(sc->sc_dev), + __func__); + break; + } + + reg &= ~STATUS_LAN_INIT_DONE; + CSR_WRITE(sc, WMREG_STATUS, reg); +} + +void +wm_get_cfg_done(struct wm_softc *sc) +{ + int func = 0; + int mask; + int i; + + /* wait for eeprom to reload */ + switch (sc->sc_type) { + case WM_T_82542_2_0: + case WM_T_82542_2_1: + /* null */ + break; + case WM_T_82543: + case WM_T_82544: + case WM_T_82540: + case WM_T_82545: + case WM_T_82545_3: + case WM_T_82546: + case WM_T_82546_3: + case WM_T_82541: + case WM_T_82541_2: + case WM_T_82547: + case WM_T_82547_2: + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: + /* generic */ + delay(10*1000); + break; + case WM_T_80003: + case WM_T_82571: + case WM_T_82572: + case WM_T_ICH8: + case WM_T_ICH9: + case WM_T_ICH10: + if (sc->sc_type == WM_T_80003) + func = (CSR_READ(sc, WMREG_STATUS) + >> STATUS_FUNCID_SHIFT) & 1; + else + func = 0; /* XXX Is it true for 82571? */ + mask = (func == 1) ? EEMNGCTL_CFGDONE_1 : EEMNGCTL_CFGDONE_0; + for (i = 0; i < WM_PHY_CFG_TIMEOUT; i++) { + if (CSR_READ(sc, WMREG_EEMNGCTL) & mask) + break; + delay(1000); + } + if (i >= WM_PHY_CFG_TIMEOUT) { + DPRINTF(WM_DEBUG_GMII, ("%s: %s failed\n", + device_xname(sc->sc_dev), __func__)); + } + break; + default: + panic("%s: %s: unknown type\n", device_xname(sc->sc_dev), + __func__); + break; + } } /* @@ -4523,29 +4697,43 @@ { uint32_t reg; int func = 0; /* XXX gcc */ + int rv; - if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) - || (sc->sc_type == WM_T_ICH10)) { - if (wm_get_swfwhw_semaphore(sc)) { - aprint_error_dev(sc->sc_dev, - "%s: failed to get semaphore\n", __func__); - return; - } - } - if (sc->sc_type == WM_T_80003) { + /* get phy semaphore */ + switch (sc->sc_type) { + case WM_T_82571: + case WM_T_82572: + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: + /* XXX sould get sw semaphore, too */ + rv = wm_get_swsm_semaphore(sc); + break; + case WM_T_80003: func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1; - if (wm_get_swfw_semaphore(sc, - func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) { - aprint_error_dev(sc->sc_dev, - "%s: failed to get semaphore\n", __func__); - return; - } + rv = wm_get_swfw_semaphore(sc, + func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + break; + case WM_T_ICH8: + case WM_T_ICH9: + case WM_T_ICH10: + rv = wm_get_swfwhw_semaphore(sc); + break; + default: + /* nothing to do*/ + rv = 0; + break; + } + if (rv != 0) { + aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", + __func__); + return; } switch (sc->sc_type) { case WM_T_82542_2_0: case WM_T_82542_2_1: - /* null ? */ + /* null */ break; case WM_T_82543: /* @@ -4563,9 +4751,6 @@ CTRL_EXT_SWDPIN(4)); reg |= CTRL_EXT_SWDPIO(4); - CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_SWDPIN(4)); - delay(10); - CSR_WRITE(sc, WMREG_CTRL_EXT, reg); delay(10*1000); @@ -4574,7 +4759,7 @@ #if 0 sc->sc_ctrl_ext = reg | CTRL_EXT_SWDPIN(4); #endif - delay(20*1000); /* extra delay to get PHY ID? */ + delay(20*1000); /* XXX extra delay to get PHY ID? */ break; case WM_T_82544: /* reset 10000us */ case WM_T_82540: @@ -4621,15 +4806,72 @@ /* XXX add code to set LED after phy reset */ break; default: - panic("unknown sc_type\n"); + panic("%s: %s: unknown type\n", device_xname(sc->sc_dev), + __func__); break; } - if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) - || (sc->sc_type == WM_T_ICH10)) - wm_put_swfwhw_semaphore(sc); - if (sc->sc_type == WM_T_80003) + /* release PHY semaphore */ + switch (sc->sc_type) { + case WM_T_82571: + case WM_T_82572: + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: + /* XXX sould put sw semaphore, too */ + wm_put_swsm_semaphore(sc); + break; + case WM_T_80003: wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + break; + case WM_T_ICH8: + case WM_T_ICH9: + case WM_T_ICH10: + wm_put_swfwhw_semaphore(sc); + break; + default: + /* nothing to do*/ + rv = 0; + break; + } + + /* get_cfg_done */ + wm_get_cfg_done(sc); + + /* extra setup */ + switch (sc->sc_type) { + case WM_T_82542_2_0: + case WM_T_82542_2_1: + case WM_T_82543: + case WM_T_82544: + case WM_T_82540: + case WM_T_82545: + case WM_T_82545_3: + case WM_T_82546: + case WM_T_82546_3: + case WM_T_82541_2: + case WM_T_82547_2: + case WM_T_82571: + case WM_T_82572: + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: + case WM_T_80003: + /* null */ + break; + case WM_T_82541: + case WM_T_82547: + /* XXX Configure actively LED after PHY reset */ + break; + case WM_T_ICH8: + case WM_T_ICH9: + case WM_T_ICH10: + delay(10*1000); + break; + default: + panic("%s: unknown type\n", __func__); + break; + } } /* @@ -5734,6 +5976,41 @@ return 0; } +static int +wm_check_reset_block(struct wm_softc *sc) +{ + uint32_t reg; + + switch (sc->sc_type) { + case WM_T_ICH8: + case WM_T_ICH9: + case WM_T_ICH10: + reg = CSR_READ(sc, WMREG_FWSM); + if ((reg & FWSM_RSPCIPHY) != 0) + return 0; + else + return -1; + break; + case WM_T_82571: + case WM_T_82572: + case WM_T_82573: + case WM_T_82574: + case WM_T_82583: + case WM_T_80003: + reg = CSR_READ(sc, WMREG_MANC); + if ((reg & MANC_BLK_PHY_RST_ON_IDE) != 0) + return -1; + else + return 0; + break; + default: + /* no problem */ + break; + } + + return 0; +} + static void wm_get_hw_control(struct wm_softc *sc) { Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.31 src/sys/dev/pci/if_wmreg.h:1.32 --- src/sys/dev/pci/if_wmreg.h:1.31 Thu Jan 7 17:34:38 2010 +++ src/sys/dev/pci/if_wmreg.h Thu Jan 7 17:45:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.31 2010/01/07 17:34:38 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.32 2010/01/07 17:45:58 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -220,6 +220,7 @@ #define STATUS_SPEED_100 STATUS_SPEED(1) #define STATUS_SPEED_1000 STATUS_SPEED(2) #define STATUS_ASDV(x) ((x) << 8) /* auto speed det. val. (Livengood) */ +#define STATUS_LAN_INIT_DONE (1U << 9) /* Lan Init Completion by NVM */ #define STATUS_MTXCKOK (1U << 10) /* MTXD clock running */ #define STATUS_PCI66 (1U << 11) /* 66MHz bus (Livengood) */ #define STATUS_BUS64 (1U << 12) /* 64-bit bus (Livengood) */ @@ -612,6 +613,10 @@ #define WMREG_PBS 0x1008 /* Packet Buffer Size (ICH) */ +#define WMREG_EEMNGCTL 0x1010 /* MNG EEprom Control */ +#define EEMNGCTL_CFGDONE_0 0x040000 /* MNG config cycle done */ +#define EEMNGCTL_CFGDONE_1 0x080000 /* 2nd port */ + #define WMREG_TXDMAC 0x3000 /* Transfer DMA Control */ #define TXDMAC_DPP (1U << 0) /* disable packet prefetch */ @@ -670,7 +675,10 @@ #define WMREG_MDPHYA 0x003C /* PHY address - RW */ -#define WMREG_MANC2H 0x5860 /* Managment Control To Host - RW */ +#define WMREG_MANC 0x5820 /* Management Control */ +#define MANC_BLK_PHY_RST_ON_IDE 0x00040000 + +#define WMREG_MANC2H 0x5860 /* Manaegment Control To Host - RW */ #define WMREG_SWSM 0x5b50 /* SW Semaphore */ #define SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ @@ -683,6 +691,7 @@ #define FWSM_MODE_SHIFT 0x1 #define MNG_ICH_IAMT_MODE 0x2 #define MNG_IAMT_MODE 0x3 +#define FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */ #define WMREG_SW_FW_SYNC 0x5b5c /* software-firmware semaphore */ #define SWFW_EEP_SM 0x0001 /* eeprom access */ Index: src/sys/dev/pci/if_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.5 src/sys/dev/pci/if_wmvar.h:1.6 --- src/sys/dev/pci/if_wmvar.h:1.5 Tue Dec 29 16:01:21 2009 +++ src/sys/dev/pci/if_wmvar.h Thu Jan 7 17:45:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.5 2009/12/29 16:01:21 msaitoh Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.6 2010/01/07 17:45:58 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -113,4 +113,8 @@ WM_T_ICH10, /* ICH10 LAN */ } wm_chip_type; +#define WM_PHY_CFG_TIMEOUT 100 +#define WM_ICH8_LAN_INIT_TIMEOUT 1500 +#define WM_MDIO_OWNERSHIP_TIMEOUT 10 + #endif /* _DEV_PCI_IF_WMVAR_H_ */