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 {

Reply via email to