Module Name: src Committed By: msaitoh Date: Fri May 6 08:56:20 UTC 2016
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h Log Message: Basic support for I219. It doesn't work on I219, so it's disabled. To generate a diff of this commit: cvs rdiff -u -r1.391 -r1.392 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.88 -r1.89 src/sys/dev/pci/if_wmreg.h cvs rdiff -u -r1.30 -r1.31 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.391 src/sys/dev/pci/if_wm.c:1.392 --- src/sys/dev/pci/if_wm.c:1.391 Tue Feb 9 08:32:11 2016 +++ src/sys/dev/pci/if_wm.c Fri May 6 08:56:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.391 2016/02/09 08:32:11 ozaki-r Exp $ */ +/* $NetBSD: if_wm.c,v 1.392 2016/05/06 08:56:20 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -83,7 +83,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.391 2016/02/09 08:32:11 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.392 2016/05/06 08:56:20 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -146,8 +146,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1. #define WM_DEBUG_GMII 0x08 #define WM_DEBUG_MANAGE 0x10 #define WM_DEBUG_NVM 0x20 +#define WM_DEBUG_INIT 0x40 int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII - | WM_DEBUG_MANAGE | WM_DEBUG_NVM; + | WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT; #define DPRINTF(x, y) if (wm_debug & (x)) printf y #else @@ -334,6 +335,10 @@ struct wm_softc { bus_space_tag_t sc_flasht; /* flash registers space tag */ bus_space_handle_t sc_flashh; /* flash registers space handle */ bus_size_t sc_flashs; /* flash registers space size */ + off_t sc_flashreg_offset; /* + * offset to flash registers from + * start of BAR + */ bus_dma_tag_t sc_dmat; /* bus DMA tag */ struct ethercom sc_ethercom; /* ethernet common data */ @@ -490,15 +495,19 @@ do { \ #define CSR_WRITE_FLUSH(sc) \ (void) CSR_READ((sc), WMREG_STATUS) -#define ICH8_FLASH_READ32(sc, reg) \ - bus_space_read_4((sc)->sc_flasht, (sc)->sc_flashh, (reg)) -#define ICH8_FLASH_WRITE32(sc, reg, data) \ - bus_space_write_4((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) - -#define ICH8_FLASH_READ16(sc, reg) \ - bus_space_read_2((sc)->sc_flasht, (sc)->sc_flashh, (reg)) -#define ICH8_FLASH_WRITE16(sc, reg, data) \ - bus_space_write_2((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) +#define ICH8_FLASH_READ32(sc, reg) \ + bus_space_read_4((sc)->sc_flasht, (sc)->sc_flashh, \ + (reg) + sc->sc_flashreg_offset) +#define ICH8_FLASH_WRITE32(sc, reg, data) \ + bus_space_write_4((sc)->sc_flasht, (sc)->sc_flashh, \ + (reg) + sc->sc_flashreg_offset, (data)) + +#define ICH8_FLASH_READ16(sc, reg) \ + bus_space_read_2((sc)->sc_flasht, (sc)->sc_flashh, \ + (reg) + sc->sc_flashreg_offset) +#define ICH8_FLASH_WRITE16(sc, reg, data) \ + bus_space_write_2((sc)->sc_flasht, (sc)->sc_flashh, \ + (reg) + sc->sc_flashreg_offset, (data)) #define WM_CDTXADDR(txq, x) ((txq)->txq_desc_dma + WM_CDTXOFF((x))) #define WM_CDRXADDR(rxq, x) ((rxq)->rxq_desc_dma + WM_CDRXOFF((x))) @@ -688,10 +697,12 @@ static int wm_nvm_valid_bank_detect_ich8 static int32_t wm_ich8_cycle_init(struct wm_softc *); static int32_t wm_ich8_flash_cycle(struct wm_softc *, uint32_t); static int32_t wm_read_ich8_data(struct wm_softc *, uint32_t, uint32_t, - uint16_t *); + uint32_t *); static int32_t wm_read_ich8_byte(struct wm_softc *, uint32_t, uint8_t *); static int32_t wm_read_ich8_word(struct wm_softc *, uint32_t, uint16_t *); +static int32_t wm_read_ich8_dword(struct wm_softc *, uint32_t, uint32_t *); static int wm_nvm_read_ich8(struct wm_softc *, int, int, uint16_t *); +static int wm_nvm_read_spt(struct wm_softc *, int, int, uint16_t *); /* iNVM */ static int wm_nvm_read_word_invm(struct wm_softc *, uint16_t, uint16_t *); static int wm_nvm_read_invm(struct wm_softc *, int, int, uint16_t *); @@ -732,7 +743,7 @@ static int wm_enable_mng_pass_thru(struc static bool wm_phy_resetisblocked(struct wm_softc *); static void wm_get_hw_control(struct wm_softc *); static void wm_release_hw_control(struct wm_softc *); -static void wm_gate_hw_phy_config_ich8lan(struct wm_softc *, int); +static void wm_gate_hw_phy_config_ich8lan(struct wm_softc *, bool); static void wm_smbustopci(struct wm_softc *); static void wm_init_manageability(struct wm_softc *); static void wm_release_manageability(struct wm_softc *); @@ -1282,6 +1293,20 @@ static const struct wm_product { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_LM3, "I218 LM Ethernet Connection", WM_T_PCH_LPT, WMP_F_COPPER }, +#if 0 + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V, + "I219 V Ethernet Connection", + WM_T_PCH_SPT, WMP_F_COPPER }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V2, + "I219 V Ethernet Connection", + WM_T_PCH_SPT, WMP_F_COPPER }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM, + "I219 LM Ethernet Connection", + WM_T_PCH_SPT, WMP_F_COPPER }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM2, + "I219 LM Ethernet Connection", + WM_T_PCH_SPT, WMP_F_COPPER }, +#endif { 0, 0, NULL, 0, 0 }, @@ -1710,7 +1735,8 @@ alloc_retry: && (sc->sc_type != WM_T_ICH10) && (sc->sc_type != WM_T_PCH) && (sc->sc_type != WM_T_PCH2) - && (sc->sc_type != WM_T_PCH_LPT)) { + && (sc->sc_type != WM_T_PCH_LPT) + && (sc->sc_type != WM_T_PCH_SPT)) { /* ICH* and PCH* have no PCIe capability registers */ if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, &sc->sc_pcixe_capoff, @@ -1799,7 +1825,7 @@ alloc_retry: /* get PHY control from SMBus to PCIe */ if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) - || (sc->sc_type == WM_T_PCH_LPT)) + || (sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT)) wm_smbustopci(sc); /* Reset the chip to a known state. */ @@ -1910,6 +1936,22 @@ alloc_retry: sc->sc_ich8_flash_bank_size -= (reg & ICH_GFPREG_BASE_MASK); sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE; sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t); + sc->sc_flashreg_offset = 0; + break; + case WM_T_PCH_SPT: + /* SPT has no GFPREG; flash registers mapped through BAR0 */ + sc->sc_flags |= WM_F_EEPROM_FLASH | WM_F_LOCK_EXTCNF; + sc->sc_flasht = sc->sc_st; + sc->sc_flashh = sc->sc_sh; + sc->sc_ich8_flash_base = 0; + sc->sc_nvm_wordsize = + (((CSR_READ(sc, WMREG_STRAP) >> 1) & 0x1F) + 1) + * NVM_SIZE_MULTIPLIER; + /* It is size in bytes, we want words */ + sc->sc_nvm_wordsize /= 2; + /* assume 2 banks */ + sc->sc_ich8_flash_bank_size = sc->sc_nvm_wordsize / 2; + sc->sc_flashreg_offset = WM_PCH_SPT_FLASHOFFSET; break; case WM_T_I210: case WM_T_I211: @@ -2030,6 +2072,7 @@ alloc_retry: case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* Non-AMT based hardware can now take control from firmware */ if ((sc->sc_flags & WM_F_HAS_AMT) == 0) wm_get_hw_control(sc); @@ -2121,6 +2164,7 @@ alloc_retry: case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* XXX The funcid should be checked on some devices */ apme_mask = WUC_APME; eeprom_data = CSR_READ(sc, WMREG_WUC); @@ -2237,7 +2281,7 @@ alloc_retry: if (sc->sc_type == WM_T_ICH8 || sc->sc_type == WM_T_ICH9 || sc->sc_type == WM_T_ICH10 || sc->sc_type == WM_T_PCH || sc->sc_type == WM_T_PCH2 || sc->sc_type == WM_T_PCH_LPT - || sc->sc_type == WM_T_82573 + || sc->sc_type == WM_T_PCH_SPT || sc->sc_type == WM_T_82573 || sc->sc_type == WM_T_82574 || sc->sc_type == WM_T_82583) { /* STATUS_TBIMODE reserved/reused, can't rely on it */ wm_gmii_mediainit(sc, wmp->wmp_product); @@ -2376,6 +2420,7 @@ alloc_retry: case WM_T_ICH10: case WM_T_PCH2: /* PCH2 supports 9K frame size */ case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* XXX limited to 9234 */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU; break; @@ -2783,6 +2828,8 @@ wm_ioctl(struct ifnet *ifp, u_long cmd, struct sockaddr_dl *sdl; int s, error; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); #ifndef WM_MPSAFE s = splnet(); #endif @@ -3000,7 +3047,8 @@ wm_mchash(struct wm_softc *sc, const uin if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) - || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { + || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT) + || (sc->sc_type == WM_T_PCH_SPT)) { hash = (enaddr[4] >> ich8_lo_shift[sc->sc_mchash_type]) | (((uint16_t) enaddr[5]) << ich8_hi_shift[sc->sc_mchash_type]); return (hash & 0x3ff); @@ -3027,6 +3075,8 @@ wm_set_filter(struct wm_softc *sc) uint32_t hash, reg, bit; int i, size, ralmax; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); if (sc->sc_type >= WM_T_82544) mta_reg = WMREG_CORDOVA_MTA; else @@ -3052,7 +3102,7 @@ wm_set_filter(struct wm_softc *sc) size = WM_RAL_TABSIZE_ICH8; else if (sc->sc_type == WM_T_PCH2) size = WM_RAL_TABSIZE_PCH2; - else if (sc->sc_type == WM_T_PCH_LPT) + else if ((sc->sc_type == WM_T_PCH_LPT) ||(sc->sc_type == WM_T_PCH_SPT)) size = WM_RAL_TABSIZE_PCH_LPT; else if (sc->sc_type == WM_T_82575) size = WM_RAL_TABSIZE_82575; @@ -3064,7 +3114,7 @@ wm_set_filter(struct wm_softc *sc) size = WM_RAL_TABSIZE; wm_set_ral(sc, CLLADDR(ifp->if_sadl), 0); - if (sc->sc_type == WM_T_PCH_LPT) { + if ((sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT)) { i = __SHIFTOUT(CSR_READ(sc, WMREG_FWSM), FWSM_WLOCK_MAC); switch (i) { case 0: @@ -3088,7 +3138,8 @@ wm_set_filter(struct wm_softc *sc) if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) - || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) + || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT) + || (sc->sc_type == WM_T_PCH_SPT)) size = WM_ICH8_MC_TABSIZE; else size = WM_MC_TABSIZE; @@ -3116,7 +3167,8 @@ wm_set_filter(struct wm_softc *sc) if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) - || (sc->sc_type == WM_T_PCH_LPT)) + || (sc->sc_type == WM_T_PCH_LPT) + || (sc->sc_type == WM_T_PCH_SPT)) reg &= 0x1f; else reg &= 0x7f; @@ -3156,6 +3208,9 @@ wm_set_filter(struct wm_softc *sc) static void wm_set_vlan(struct wm_softc *sc) { + + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); /* Deal with VLAN enables. */ if (VLAN_ATTACHED(&sc->sc_ethercom)) sc->sc_ctrl |= CTRL_VME; @@ -3245,6 +3300,7 @@ wm_lan_init_done(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: for (i = 0; i < WM_ICH8_LAN_INIT_TIMEOUT; i++) { reg = CSR_READ(sc, WMREG_STATUS); if ((reg & STATUS_LAN_INIT_DONE) != 0) @@ -3327,6 +3383,7 @@ wm_get_cfg_done(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: delay(10*1000); if (sc->sc_type >= WM_T_ICH10) wm_lan_init_done(sc); @@ -3350,6 +3407,8 @@ wm_initialize_hardware_bits(struct wm_so { uint32_t tarc0, tarc1, reg; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); /* For 82571 variant, 80003 and ICHs */ if (((sc->sc_type >= WM_T_82571) && (sc->sc_type <= WM_T_82583)) || (sc->sc_type >= WM_T_80003)) { @@ -3572,6 +3631,8 @@ wm_reset(struct wm_softc *sc) int i, error = 0; uint32_t reg, mask; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); /* * Allocate on-chip memory according to the MTU size. * The Packet Buffer Allocation register must be written @@ -3630,6 +3691,7 @@ wm_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: sc->sc_pba = PBA_26K; break; default: @@ -3751,6 +3813,7 @@ wm_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST; if (wm_phy_resetisblocked(sc) == false) { /* @@ -3760,7 +3823,7 @@ wm_reset(struct wm_softc *sc) if ((sc->sc_type == WM_T_PCH2) && ((CSR_READ(sc, WMREG_FWSM) & FWSM_FW_VALID) == 0)) - wm_gate_hw_phy_config_ich8lan(sc, 1); + wm_gate_hw_phy_config_ich8lan(sc, true); reg |= CTRL_PHY_RESET; phy_reset = 1; @@ -3880,6 +3943,7 @@ wm_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: break; default: panic("%s: unknown type\n", __func__); @@ -4448,6 +4512,8 @@ wm_init_locked(struct ifnet *ifp) int i, j, trynum, error = 0; uint32_t reg; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); KASSERT(WM_CORE_LOCKED(sc)); /* * *_HDR_ALIGNED_P is constant 1 if __NO_STRICT_ALIGMENT is set. @@ -4492,6 +4558,7 @@ wm_init_locked(struct ifnet *ifp) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* AMT based hardware can now take control from firmware */ if ((sc->sc_flags & WM_F_HAS_AMT) != 0) wm_get_hw_control(sc); @@ -4556,7 +4623,8 @@ wm_init_locked(struct ifnet *ifp) */ if ((sc->sc_type != WM_T_ICH8) && (sc->sc_type != WM_T_ICH9) && (sc->sc_type != WM_T_ICH10) && (sc->sc_type != WM_T_PCH) - && (sc->sc_type != WM_T_PCH2) && (sc->sc_type != WM_T_PCH_LPT)) { + && (sc->sc_type != WM_T_PCH2) && (sc->sc_type != WM_T_PCH_LPT) + && (sc->sc_type != WM_T_PCH_SPT)) { CSR_WRITE(sc, WMREG_FCAL, FCAL_CONST); CSR_WRITE(sc, WMREG_FCAH, FCAH_CONST); CSR_WRITE(sc, WMREG_FCT, ETHERTYPE_FLOWCONTROL); @@ -4590,6 +4658,7 @@ wm_init_locked(struct ifnet *ifp) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* * Set the mac to wait the maximum time between each * iteration and increase the max iterations when @@ -4829,7 +4898,8 @@ wm_init_locked(struct ifnet *ifp) if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) - || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { + || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT) + || (sc->sc_type == WM_T_PCH_SPT)) { reg = CSR_READ(sc, WMREG_KABGTXD); reg |= KABGTXD_BGSQLBIAS; CSR_WRITE(sc, WMREG_KABGTXD, reg); @@ -4959,6 +5029,7 @@ wm_init_locked(struct ifnet *ifp) CSR_WRITE(sc, WMREG_PBA_ECC, reg); break; case WM_T_PCH_LPT: + case WM_T_PCH_SPT: reg = CSR_READ(sc, WMREG_PBECCSTS); reg |= PBECCSTS_UNCORR_ECC_ENABLE; CSR_WRITE(sc, WMREG_PBECCSTS, reg); @@ -5024,6 +5095,8 @@ wm_stop_locked(struct ifnet *ifp, int di struct wm_txsoft *txs; int i, qidx; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); KASSERT(WM_CORE_LOCKED(sc)); sc->sc_stopping = true; @@ -5800,6 +5873,8 @@ wm_init_txrx_queues(struct wm_softc *sc) { int i, error; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); for (i = 0; i < sc->sc_ntxqueues; i++) { struct wm_txqueue *txq = &sc->sc_txq[i]; WM_TX_LOCK(txq); @@ -7623,6 +7698,8 @@ wm_gmii_reset(struct wm_softc *sc) uint32_t reg; int rv; + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); /* get phy semaphore */ switch (sc->sc_type) { case WM_T_82571: @@ -7649,6 +7726,7 @@ wm_gmii_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: rv = wm_get_swfwhw_semaphore(sc); break; default: @@ -7740,6 +7818,7 @@ wm_gmii_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* generic reset */ CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET); CSR_WRITE_FLUSH(sc); @@ -7780,10 +7859,11 @@ wm_gmii_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: wm_put_swfwhw_semaphore(sc); break; default: - /* nothing to do*/ + /* nothing to do */ rv = 0; break; } @@ -7831,6 +7911,7 @@ wm_gmii_reset(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* Allow time for h/w to get to a quiescent state afer reset */ delay(10*1000); @@ -8015,7 +8096,7 @@ wm_gmii_mediainit(struct wm_softc *sc, p } break; } - if ((sc->sc_type >= WM_T_PCH) && (sc->sc_type <= WM_T_PCH_LPT)) { + if ((sc->sc_type >= WM_T_PCH) && (sc->sc_type <= WM_T_PCH_SPT)) { /* All PCH* use _hv_ */ mii->mii_readreg = wm_gmii_hv_readreg; mii->mii_writereg = wm_gmii_hv_writereg; @@ -9998,6 +10079,21 @@ wm_nvm_valid_bank_detect_ich8lan(struct uint8_t sig_byte = 0; switch (sc->sc_type) { + case WM_T_PCH_SPT: + /* + * In SPT, read from the CTRL_EXT reg instead of accessing the + * sector valid bits from the NVM. + */ + *bank = CSR_READ(sc, WMREG_CTRL_EXT) & CTRL_EXT_NVMVS; + if ((*bank == 0) || (*bank == 1)) { + aprint_error_dev(sc->sc_dev, + "%s: no valid NVM bank present\n", + __func__); + return -1; + } else { + *bank = *bank - 2; + return 0; + } case WM_T_ICH8: case WM_T_ICH9: eecd = CSR_READ(sc, WMREG_EECD); @@ -10136,16 +10232,16 @@ wm_ich8_flash_cycle(struct wm_softc *sc, } /****************************************************************************** - * Reads a byte or word from the NVM using the ICH8 flash access registers. + * Reads a byte or (d)word from the NVM using the ICH8 flash access registers. * * sc - The pointer to the hw structure * index - The index of the byte or word to read. - * size - Size of data to read, 1=byte 2=word + * size - Size of data to read, 1=byte 2=word, 4=dword * data - Pointer to the word to store the value read. *****************************************************************************/ static int32_t wm_read_ich8_data(struct wm_softc *sc, uint32_t index, - uint32_t size, uint16_t *data) + uint32_t size, uint32_t *data) { uint16_t hsfsts; uint16_t hsflctl; @@ -10154,7 +10250,7 @@ wm_read_ich8_data(struct wm_softc *sc, u int32_t error = 1; int32_t count = 0; - if (size < 1 || size > 2 || data == 0x0 || + if (size < 1 || size > 4 || data == 0x0 || index > ICH_FLASH_LINEAR_ADDR_MASK) return error; @@ -10173,7 +10269,15 @@ wm_read_ich8_data(struct wm_softc *sc, u hsflctl |= ((size - 1) << HSFCTL_BCOUNT_SHIFT) & HSFCTL_BCOUNT_MASK; hsflctl |= ICH_CYCLE_READ << HSFCTL_CYCLE_SHIFT; - ICH8_FLASH_WRITE16(sc, ICH_FLASH_HSFCTL, hsflctl); + if (sc->sc_type == WM_T_PCH_SPT) { + /* + * In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported. + */ + ICH8_FLASH_WRITE32(sc, ICH_FLASH_HSFCTL, + (uint32_t)hsflctl); + } else + ICH8_FLASH_WRITE16(sc, ICH_FLASH_HSFCTL, hsflctl); /* * Write the last 24 bits of index into Flash Linear address @@ -10197,6 +10301,8 @@ wm_read_ich8_data(struct wm_softc *sc, u *data = (uint8_t)(flash_data & 0x000000FF); else if (size == 2) *data = (uint16_t)(flash_data & 0x0000FFFF); + else if (size == 4) + *data = (uint32_t)flash_data; break; } else { /* @@ -10228,7 +10334,7 @@ static int32_t wm_read_ich8_byte(struct wm_softc *sc, uint32_t index, uint8_t* data) { int32_t status; - uint16_t word = 0; + uint32_t word = 0; status = wm_read_ich8_data(sc, index, 1, &word); if (status == 0) @@ -10250,8 +10356,30 @@ static int32_t wm_read_ich8_word(struct wm_softc *sc, uint32_t index, uint16_t *data) { int32_t status; + uint32_t word = 0; + + status = wm_read_ich8_data(sc, index, 2, &word); + if (status == 0) + *data = (uint16_t)word; + else + *data = 0; + + return status; +} + +/****************************************************************************** + * Reads a dword from the NVM using the ICH8 flash access registers. + * + * sc - pointer to wm_hw structure + * index - The starting byte index of the word to read. + * data - Pointer to a word to store the value read. + *****************************************************************************/ +static int32_t +wm_read_ich8_dword(struct wm_softc *sc, uint32_t index, uint32_t *data) +{ + int32_t status; - status = wm_read_ich8_data(sc, index, 2, data); + status = wm_read_ich8_data(sc, index, 4, data); return status; } @@ -10316,6 +10444,72 @@ wm_nvm_read_ich8(struct wm_softc *sc, in return error; } +/****************************************************************************** + * Reads a 16 bit word or words from the EEPROM using the SPT's flash access + * register. + * + * sc - Struct containing variables accessed by shared code + * offset - offset of word in the EEPROM to read + * data - word read from the EEPROM + * words - number of words to read + *****************************************************************************/ +static int +wm_nvm_read_spt(struct wm_softc *sc, int offset, int words, uint16_t *data) +{ + int32_t error = 0; + uint32_t flash_bank = 0; + uint32_t act_offset = 0; + uint32_t bank_offset = 0; + uint32_t dword = 0; + uint16_t i = 0; + + /* + * We need to know which is the valid flash bank. In the event + * that we didn't allocate eeprom_shadow_ram, we may not be + * managing flash_bank. So it cannot be trusted and needs + * to be updated with each read. + */ + error = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); + if (error) { + DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", + device_xname(sc->sc_dev))); + flash_bank = 0; + } + + /* + * Adjust offset appropriately if we're on bank 1 - adjust for word + * size + */ + bank_offset = flash_bank * (sc->sc_ich8_flash_bank_size * 2); + + error = wm_get_swfwhw_semaphore(sc); + if (error) { + aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", + __func__); + return error; + } + + for (i = 0; i < words; i++) { + /* The NVM part needs a byte offset, hence * 2 */ + act_offset = bank_offset + ((offset + i) * 2); + /* but we must read dword aligned, so mask ... */ + error = wm_read_ich8_dword(sc, act_offset & ~0x3, &dword); + if (error) { + aprint_error_dev(sc->sc_dev, + "%s: failed to read NVM\n", __func__); + break; + } + /* ... and pick out low or high word */ + if ((act_offset & 0x2) == 0) + data[i] = (uint16_t)(dword & 0xFFFF); + else + data[i] = (uint16_t)((dword >> 16) & 0xFFFF); + } + + wm_put_swfwhw_semaphore(sc); + return error; +} + /* iNVM */ static int @@ -10570,6 +10764,7 @@ wm_nvm_validate_checksum(struct wm_softc if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { + /* XXX PCH_SPT? */ wm_nvm_read(sc, csum_wordaddr, 1, &eeprom_data); if ((eeprom_data & valid_checksum) == 0) { DPRINTF(WM_DEBUG_NVM, @@ -10756,6 +10951,8 @@ wm_nvm_read(struct wm_softc *sc, int wor || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) rv = wm_nvm_read_ich8(sc, word, wordcnt, data); + else if (sc->sc_type == WM_T_PCH_SPT) + rv = wm_nvm_read_spt(sc, word, wordcnt, data); else if (sc->sc_flags & WM_F_EEPROM_INVM) rv = wm_nvm_read_invm(sc, word, wordcnt, data); else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR) @@ -10971,6 +11168,7 @@ wm_check_mng_mode(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: rv = wm_check_mng_mode_ich8lan(sc); break; case WM_T_82574: @@ -11086,6 +11284,7 @@ wm_phy_resetisblocked(struct wm_softc *s case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: do { reg = CSR_READ(sc, WMREG_FWSM); if ((reg & FWSM_RSPCIPHY) == 0) { @@ -11138,6 +11337,7 @@ wm_get_hw_control(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: reg = CSR_READ(sc, WMREG_CTRL_EXT); CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_DRV_LOAD); break; @@ -11165,13 +11365,13 @@ wm_release_hw_control(struct wm_softc *s } static void -wm_gate_hw_phy_config_ich8lan(struct wm_softc *sc, int on) +wm_gate_hw_phy_config_ich8lan(struct wm_softc *sc, bool gate) { uint32_t reg; reg = CSR_READ(sc, WMREG_EXTCNFCTR); - if (on != 0) + if (gate) reg |= EXTCNFCTR_GATE_PHY_CFG; else reg &= ~EXTCNFCTR_GATE_PHY_CFG; @@ -11210,6 +11410,8 @@ static void wm_init_manageability(struct wm_softc *sc) { + DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); if (sc->sc_flags & WM_F_HAS_MANAGE) { uint32_t manc2h = CSR_READ(sc, WMREG_MANC2H); uint32_t manc = CSR_READ(sc, WMREG_MANC); @@ -11274,6 +11476,7 @@ wm_get_wakeup(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* XXX only Q170 chipset? */ sc->sc_flags |= WM_F_HAS_AMT; sc->sc_flags |= WM_F_ASF_FIRMWARE_PRES; break; @@ -11387,6 +11590,7 @@ wm_enable_wakeup(struct wm_softc *sc) case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + case WM_T_PCH_SPT: /* Disable gig during WOL */ reg = CSR_READ(sc, WMREG_PHY_CTRL); reg |= PHY_CTRL_D0A_LPLU | PHY_CTRL_GBE_DIS; Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.88 src/sys/dev/pci/if_wmreg.h:1.89 --- src/sys/dev/pci/if_wmreg.h:1.88 Fri Dec 25 04:50:16 2015 +++ src/sys/dev/pci/if_wmreg.h Fri May 6 08:56:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.88 2015/12/25 04:50:16 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.89 2016/05/06 08:56:20 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -202,6 +202,10 @@ struct livengood_tcpip_ctxdesc { /* registers for FLASH access on ICH8 */ #define WM_ICH8_FLASH 0x0014 +/* XXX Only for PCH_SPT? */ +#define WM_PCI_DESCRING_STATUS 0xe4 +#define DESCRING_STATUS_FLUSH_REQ __BIT(8) + /* * Wiseman Control/Status Registers. */ @@ -270,6 +274,12 @@ struct livengood_tcpip_ctxdesc { #define STATUS_GIO_M_ENA (1U << 19) /* GIO master enable */ #define STATUS_DEV_RST_SET (1U << 20) /* Device Reset Set */ +/* Strapping Option Register (PCH_SPT and newer) */ +#define WMREG_STRAP 0x000c +#define STRAP_NVMSIZE __BITS(1, 6) +#define STRAP_FREQ __BITS(12, 13) +#define STRAP_SMBUSADDR __BITS(17, 23) + #define WMREG_EECD 0x0010 /* EEPROM Control Register */ #define EECD_SK (1U << 0) /* clock */ #define EECD_CS (1U << 1) /* chip select */ @@ -301,6 +311,7 @@ struct livengood_tcpip_ctxdesc { #define WMREG_CTRL_EXT 0x0018 /* Extended Device Control Register */ #define CTRL_EXT_NSICR __BIT(0) /* Non Interrupt clear on read */ #define CTRL_EXT_GPI_EN(x) (1U << (x)) /* gpin interrupt enable */ +#define CTRL_EXT_NVMVS __BITS(0, 1) /* NVM valid sector */ #define CTRL_EXT_SWDPINS_SHIFT 4 #define CTRL_EXT_SWDPINS_MASK 0x0d /* The bit order of the SW Definable pin is not 6543 but 3654! */ @@ -310,6 +321,7 @@ struct livengood_tcpip_ctxdesc { #define CTRL_EXT_SWDPIO_MASK 0x0d #define CTRL_EXT_SWDPIO(x) (1U << (CTRL_EXT_SWDPIO_SHIFT \ + ((x) == 3 ? 3 : ((x) - 4)))) +#define CTRL_EXT_FORCE_SMBUS __BIT(11) /* Force SMBus mode */ #define CTRL_EXT_ASDCHK (1U << 12) /* ASD check */ #define CTRL_EXT_EE_RST (1U << 13) /* EEPROM reset */ #define CTRL_EXT_IPS (1U << 14) /* invert power state bit 0 */ @@ -497,6 +509,7 @@ struct livengood_tcpip_ctxdesc { #define RCTL_RDMTS_MASK RCTL_RDMTS(3) #define RCTL_MO(x) ((x) << 12) /* multicast offset */ #define RCTL_BAM (1U << 15) /* broadcast accept mode */ +#define RCTL_RDMTS_HEX __BIT(16) #define RCTL_2k (0 << 16) /* 2k Rx buffers */ #define RCTL_1k (1 << 16) /* 1k Rx buffers */ #define RCTL_512 (2 << 16) /* 512 byte Rx buffers */ @@ -715,6 +728,8 @@ struct livengood_tcpip_ctxdesc { #define PHY_CTRL_NOND0A_GBE_DIS (1 << 3) #define PHY_CTRL_GBE_DIS (1 << 6) +#define WMREG_IOSFPC 0x0f28 /* Tx corrupted data */ + #define WMREG_PBA 0x1000 /* Packet Buffer Allocation */ #define PBA_BYTE_SHIFT 10 /* KB -> bytes */ #define PBA_ADDR_SHIFT 7 /* KB -> quadwords */ @@ -1021,6 +1036,9 @@ struct livengood_tcpip_ctxdesc { #define SWFW_FIRM_SHIFT 16 /* firmware semaphores */ #define WMREG_GCR2 0x5b64 /* 3GPIO Control Register 2 */ +#define WMREG_FEXTNVM9 0x5bb4 /* Future Extended NVM 9 */ +#define WMREG_FEXTNVM11 0x5bbc /* Future Extended NVM 11 */ +#define FEXTNVM11_DIS_MULRFIX __BIT(13) /* Disable MULR fix */ #define WMREG_CRC_OFFSET 0x5f50 @@ -1244,6 +1262,9 @@ struct livengood_tcpip_ctxdesc { #define ICH_NVM_VALID_SIG_MASK 0xc0 #define ICH_NVM_SIG_VALUE 0x80 +#define NVM_SIZE_MULTIPLIER 4096 /* multiplier for NVMS field */ +#define WM_PCH_SPT_FLASHOFFSET 0xe000 /* offset of NVM access regs(PCH_SPT)*/ + /* for PCI express Capability registers */ #define WM_PCIE_DCSR2_16MS 0x00000005 Index: src/sys/dev/pci/if_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.30 src/sys/dev/pci/if_wmvar.h:1.31 --- src/sys/dev/pci/if_wmvar.h:1.30 Fri Dec 25 04:50:16 2015 +++ src/sys/dev/pci/if_wmvar.h Fri May 6 08:56:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.30 2015/12/25 04:50:16 msaitoh Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.31 2016/05/06 08:56:20 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -149,6 +149,7 @@ typedef enum { WM_T_PCH, /* PCH (Platform Controller Hub) LAN */ WM_T_PCH2, /* PCH2 LAN */ WM_T_PCH_LPT, /* PCH "Lynx Point" LAN (I217, I218) */ + WM_T_PCH_SPT, /* PCH "Sunrise Point" LAN (I219) */ } wm_chip_type; typedef enum {