Module Name: src Committed By: msaitoh Date: Tue Jul 25 06:00:17 UTC 2017
Modified Files: src/sys/dev/pci: if_wm.c if_wmvar.h Log Message: Use new nvm.{acquire,release}() for semaphore. Almost the same except the following: - 8257[12]: Don't directly access SPI but use EERD register. - 82575-I354: If the size of SPI ROM >= 32K words, use direct SPI access instead of EERD register access. - Add wm_nvm_eec_clock_raise() and wm_nvm_eec_clock_lower() and use them for Microwire/SPI bus control. Same as Linux and FreeBSD. - Redude timeout value for 80003 in wm_get_swfw_semaphore(). Same as Linux and FreeBSD. To generate a diff of this commit: cvs rdiff -u -r1.529 -r1.530 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.34 -r1.35 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.529 src/sys/dev/pci/if_wm.c:1.530 --- src/sys/dev/pci/if_wm.c:1.529 Thu Jul 20 10:00:25 2017 +++ src/sys/dev/pci/if_wm.c Tue Jul 25 06:00:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.529 2017/07/20 10:00:25 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.530 2017/07/25 06:00:17 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.529 2017/07/20 10:00:25 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.530 2017/07/25 06:00:17 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -442,6 +442,12 @@ struct wm_phyop { int reset_delay_us; }; +struct wm_nvmop { + int (*acquire)(struct wm_softc *); + void (*release)(struct wm_softc *); + int (*read)(struct wm_softc *, int, int, uint16_t *); +}; + /* * Software state per device. */ @@ -564,6 +570,7 @@ struct wm_softc { kmutex_t *sc_ich_nvmmtx; /* ICH/PCH specific NVM mutex */ struct wm_phyop phy; + struct wm_nvmop nvm; }; #define WM_CORE_LOCK(_sc) if ((_sc)->sc_core_lock) mutex_enter((_sc)->sc_core_lock) @@ -857,8 +864,6 @@ static int wm_nvm_read_spt(struct wm_sof 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 *); /* Lock, detecting NVM type, validate checksum and read */ -static int wm_nvm_acquire(struct wm_softc *); -static void wm_nvm_release(struct wm_softc *); static int wm_nvm_is_onboard_eeprom(struct wm_softc *); static int wm_nvm_get_flash_presence_i210(struct wm_softc *); static int wm_nvm_validate_checksum(struct wm_softc *); @@ -872,17 +877,23 @@ static int wm_nvm_read(struct wm_softc * */ static int wm_get_null(struct wm_softc *); static void wm_put_null(struct wm_softc *); +static int wm_get_eecd(struct wm_softc *); +static void wm_put_eecd(struct wm_softc *); static int wm_get_swsm_semaphore(struct wm_softc *); /* 8257[123] */ static void wm_put_swsm_semaphore(struct wm_softc *); static int wm_get_swfw_semaphore(struct wm_softc *, uint16_t); static void wm_put_swfw_semaphore(struct wm_softc *, uint16_t); +static int wm_get_nvm_80003(struct wm_softc *); +static void wm_put_nvm_80003(struct wm_softc *); +static int wm_get_nvm_82571(struct wm_softc *); +static void wm_put_nvm_82571(struct wm_softc *); static int wm_get_phy_82575(struct wm_softc *); static void wm_put_phy_82575(struct wm_softc *); static int wm_get_swfwhw_semaphore(struct wm_softc *); /* For 574/583 */ static void wm_put_swfwhw_semaphore(struct wm_softc *); static int wm_get_swflag_ich8lan(struct wm_softc *); /* For PHY */ static void wm_put_swflag_ich8lan(struct wm_softc *); -static int wm_get_nvm_ich8lan(struct wm_softc *); /* For NVM */ +static int wm_get_nvm_ich8lan(struct wm_softc *); static void wm_put_nvm_ich8lan(struct wm_softc *); static int wm_get_hw_semaphore_82573(struct wm_softc *); static void wm_put_hw_semaphore_82573(struct wm_softc *); @@ -1713,8 +1724,8 @@ wm_attach(device_t parent, device_t self sc->sc_type = wmp->wmp_type; /* Set default function pointers */ - sc->phy.acquire = wm_get_null; - sc->phy.release = wm_put_null; + sc->phy.acquire = sc->nvm.acquire = wm_get_null; + sc->phy.release = sc->nvm.release = wm_put_null; sc->phy.reset_delay_us = (sc->sc_type >= WM_T_82571) ? 100 : 10000; if (sc->sc_type < WM_T_82543) { @@ -2039,6 +2050,7 @@ alloc_retry: case WM_T_82543: case WM_T_82544: /* Microwire */ + sc->nvm.read = wm_nvm_read_uwire; sc->sc_nvm_wordsize = 64; sc->sc_nvm_addrbits = 6; break; @@ -2048,6 +2060,7 @@ alloc_retry: case WM_T_82546: case WM_T_82546_3: /* Microwire */ + sc->nvm.read = wm_nvm_read_uwire; reg = CSR_READ(sc, WMREG_EECD); if (reg & EECD_EE_SIZE) { sc->sc_nvm_wordsize = 256; @@ -2057,19 +2070,22 @@ alloc_retry: sc->sc_nvm_addrbits = 6; } sc->sc_flags |= WM_F_LOCK_EECD; + sc->nvm.acquire = wm_get_eecd; + sc->nvm.release = wm_put_eecd; break; case WM_T_82541: case WM_T_82541_2: case WM_T_82547: case WM_T_82547_2: - sc->sc_flags |= WM_F_LOCK_EECD; reg = CSR_READ(sc, WMREG_EECD); if (reg & EECD_EE_TYPE) { /* SPI */ + sc->nvm.read = wm_nvm_read_spi; sc->sc_flags |= WM_F_EEPROM_SPI; wm_nvm_set_addrbits_size_eecd(sc); } else { /* Microwire */ + sc->nvm.read = wm_nvm_read_uwire; if ((reg & EECD_EE_ABITS) != 0) { sc->sc_nvm_wordsize = 256; sc->sc_nvm_addrbits = 8; @@ -2078,29 +2094,37 @@ alloc_retry: sc->sc_nvm_addrbits = 6; } } + sc->sc_flags |= WM_F_LOCK_EECD; + sc->nvm.acquire = wm_get_eecd; + sc->nvm.release = wm_put_eecd; break; case WM_T_82571: case WM_T_82572: /* SPI */ + sc->nvm.read = wm_nvm_read_eerd; + /* Not use WM_F_LOCK_EECD because we use EERD */ sc->sc_flags |= WM_F_EEPROM_SPI; wm_nvm_set_addrbits_size_eecd(sc); - sc->sc_flags |= WM_F_LOCK_EECD | WM_F_LOCK_SWSM; sc->phy.acquire = wm_get_swsm_semaphore; sc->phy.release = wm_put_swsm_semaphore; + sc->nvm.acquire = wm_get_nvm_82571; + sc->nvm.release = wm_put_nvm_82571; break; case WM_T_82573: case WM_T_82574: case WM_T_82583: + sc->nvm.read = wm_nvm_read_eerd; + /* Not use WM_F_LOCK_EECD because we use EERD */ if (sc->sc_type == WM_T_82573) { - sc->sc_flags |= WM_F_LOCK_SWSM; sc->phy.acquire = wm_get_swsm_semaphore; sc->phy.release = wm_put_swsm_semaphore; + sc->nvm.acquire = wm_get_nvm_82571; + sc->nvm.release = wm_put_nvm_82571; } else { - sc->sc_flags |= WM_F_LOCK_EXTCNF; /* Both PHY and NVM use the same semaphore. */ - sc->phy.acquire + sc->phy.acquire = sc->nvm.acquire = wm_get_swfwhw_semaphore; - sc->phy.release + sc->phy.release = sc->nvm.release = wm_put_swfwhw_semaphore; } if (wm_nvm_is_onboard_eeprom(sc) == 0) { @@ -2111,7 +2135,6 @@ alloc_retry: sc->sc_flags |= WM_F_EEPROM_SPI; wm_nvm_set_addrbits_size_eecd(sc); } - sc->sc_flags |= WM_F_EEPROM_EERDEEWR; break; case WM_T_82575: case WM_T_82576: @@ -2122,10 +2145,18 @@ alloc_retry: /* SPI */ sc->sc_flags |= WM_F_EEPROM_SPI; wm_nvm_set_addrbits_size_eecd(sc); - sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW - | WM_F_LOCK_SWSM; + if((sc->sc_type == WM_T_80003) + || (sc->sc_nvm_wordsize < (1 << 15))) { + sc->nvm.read = wm_nvm_read_eerd; + /* Don't use WM_F_LOCK_EECD because we use EERD */ + } else { + sc->nvm.read = wm_nvm_read_spi; + sc->sc_flags |= WM_F_LOCK_EECD; + } sc->phy.acquire = wm_get_phy_82575; sc->phy.release = wm_put_phy_82575; + sc->nvm.acquire = wm_get_nvm_80003; + sc->nvm.release = wm_put_nvm_80003; break; case WM_T_ICH8: case WM_T_ICH9: @@ -2133,8 +2164,9 @@ alloc_retry: case WM_T_PCH: case WM_T_PCH2: case WM_T_PCH_LPT: + sc->nvm.read = wm_nvm_read_ich8; /* FLASH */ - sc->sc_flags |= WM_F_EEPROM_FLASH | WM_F_LOCK_EXTCNF; + sc->sc_flags |= WM_F_EEPROM_FLASH; sc->sc_nvm_wordsize = 2048; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag,WM_ICH8_FLASH); if (pci_mapreg_map(pa, WM_ICH8_FLASH, memtype, 0, @@ -2154,10 +2186,13 @@ alloc_retry: sc->sc_flashreg_offset = 0; sc->phy.acquire = wm_get_swflag_ich8lan; sc->phy.release = wm_put_swflag_ich8lan; + sc->nvm.acquire = wm_get_nvm_ich8lan; + sc->nvm.release = wm_put_nvm_ich8lan; break; case WM_T_PCH_SPT: + sc->nvm.read = wm_nvm_read_spt; /* SPT has no GFPREG; flash registers mapped through BAR0 */ - sc->sc_flags |= WM_F_EEPROM_FLASH | WM_F_LOCK_EXTCNF; + sc->sc_flags |= WM_F_EEPROM_FLASH; sc->sc_flasht = sc->sc_st; sc->sc_flashh = sc->sc_sh; sc->sc_ich8_flash_base = 0; @@ -2171,20 +2206,25 @@ alloc_retry: sc->sc_flashreg_offset = WM_PCH_SPT_FLASHOFFSET; sc->phy.acquire = wm_get_swflag_ich8lan; sc->phy.release = wm_put_swflag_ich8lan; + sc->nvm.acquire = wm_get_nvm_ich8lan; + sc->nvm.release = wm_put_nvm_ich8lan; break; case WM_T_I210: case WM_T_I211: if (wm_nvm_get_flash_presence_i210(sc)) { - wm_nvm_set_addrbits_size_eecd(sc); + sc->nvm.read = wm_nvm_read_eerd; + /* Don't use WM_F_LOCK_EECD because we use EERD */ sc->sc_flags |= WM_F_EEPROM_FLASH_HW; - sc->sc_flags |= WM_F_EEPROM_EERDEEWR; + wm_nvm_set_addrbits_size_eecd(sc); } else { - sc->sc_nvm_wordsize = INVM_SIZE; + sc->nvm.read = wm_nvm_read_invm; sc->sc_flags |= WM_F_EEPROM_INVM; + sc->sc_nvm_wordsize = INVM_SIZE; } - sc->sc_flags |= WM_F_LOCK_SWFW | WM_F_LOCK_SWSM; sc->phy.acquire = wm_get_phy_82575; sc->phy.release = wm_put_phy_82575; + sc->nvm.acquire = wm_get_nvm_80003; + sc->nvm.release = wm_put_nvm_80003; break; default: break; @@ -3674,7 +3714,7 @@ wm_phy_post_reset(struct wm_softc *sc) if (wm_phy_resetisblocked(sc)) { /* XXX */ - device_printf(sc->sc_dev, " PHY is blocked\n"); + device_printf(sc->sc_dev, "PHY is blocked\n"); return; } @@ -11422,6 +11462,9 @@ wm_nvm_read_uwire(struct wm_softc *sc, i DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); + if (sc->nvm.acquire(sc) != 0) + return -1; + for (i = 0; i < wordcnt; i++) { /* Clear SK and DI. */ reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_DI); @@ -11467,6 +11510,7 @@ wm_nvm_read_uwire(struct wm_softc *sc, i delay(2); } + sc->nvm.release(sc); return 0; } @@ -11558,7 +11602,7 @@ wm_nvm_ready_spi(struct wm_softc *sc) } if (usec >= SPI_MAX_RETRIES) { aprint_error_dev(sc->sc_dev,"EEPROM failed to become ready\n"); - return 1; + return -1; } return 0; } @@ -11574,18 +11618,22 @@ wm_nvm_read_spi(struct wm_softc *sc, int uint32_t reg, val; int i; uint8_t opc; + int rv = 0; DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); + if (sc->nvm.acquire(sc) != 0) + return -1; + /* Clear SK and CS. */ reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_CS); CSR_WRITE(sc, WMREG_EECD, reg); CSR_WRITE_FLUSH(sc); delay(2); - if (wm_nvm_ready_spi(sc)) - return 1; + if ((rv = wm_nvm_ready_spi(sc)) != 0) + goto out; /* Toggle CS to flush commands. */ CSR_WRITE(sc, WMREG_EECD, reg | EECD_CS); @@ -11613,7 +11661,9 @@ wm_nvm_read_spi(struct wm_softc *sc, int CSR_WRITE_FLUSH(sc); delay(2); - return 0; +out: + sc->nvm.release(sc); + return rv; } /* Using with EERD */ @@ -11643,23 +11693,27 @@ wm_nvm_read_eerd(struct wm_softc *sc, in uint16_t *data) { int i, eerd = 0; - int error = 0; + int rv = 0; DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); + if (sc->nvm.acquire(sc) != 0) + return -1; + for (i = 0; i < wordcnt; i++) { eerd = ((offset + i) << EERD_ADDR_SHIFT) | EERD_START; - CSR_WRITE(sc, WMREG_EERD, eerd); - error = wm_poll_eerd_eewr_done(sc, WMREG_EERD); - if (error != 0) + rv = wm_poll_eerd_eewr_done(sc, WMREG_EERD); + if (rv != 0) { + aprint_error_dev(sc->sc_dev, "EERD polling failed\n"); break; - + } data[i] = (CSR_READ(sc, WMREG_EERD) >> EERD_DATA_SHIFT); } - return error; + sc->nvm.release(sc); + return rv; } /* Flash */ @@ -11989,7 +12043,7 @@ wm_read_ich8_dword(struct wm_softc *sc, static int wm_nvm_read_ich8(struct wm_softc *sc, int offset, int words, uint16_t *data) { - int32_t error = 0; + int32_t rv = 0; uint32_t flash_bank = 0; uint32_t act_offset = 0; uint32_t bank_offset = 0; @@ -11999,14 +12053,17 @@ wm_nvm_read_ich8(struct wm_softc *sc, in DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); + if (sc->nvm.acquire(sc) != 0) + return -1; + /* * 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) { + rv = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); + if (rv) { DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", device_xname(sc->sc_dev))); flash_bank = 0; @@ -12021,8 +12078,8 @@ wm_nvm_read_ich8(struct wm_softc *sc, in for (i = 0; i < words; i++) { /* The NVM part needs a byte offset, hence * 2 */ act_offset = bank_offset + ((offset + i) * 2); - error = wm_read_ich8_word(sc, act_offset, &word); - if (error) { + rv = wm_read_ich8_word(sc, act_offset, &word); + if (rv) { aprint_error_dev(sc->sc_dev, "%s: failed to read NVM\n", __func__); break; @@ -12030,7 +12087,8 @@ wm_nvm_read_ich8(struct wm_softc *sc, in data[i] = word; } - return error; + sc->nvm.release(sc); + return rv; } /****************************************************************************** @@ -12045,7 +12103,7 @@ wm_nvm_read_ich8(struct wm_softc *sc, in static int wm_nvm_read_spt(struct wm_softc *sc, int offset, int words, uint16_t *data) { - int32_t error = 0; + int32_t rv = 0; uint32_t flash_bank = 0; uint32_t act_offset = 0; uint32_t bank_offset = 0; @@ -12055,14 +12113,17 @@ wm_nvm_read_spt(struct wm_softc *sc, int DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); + if (sc->nvm.acquire(sc) != 0) + return -1; + /* * 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) { + rv = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); + if (rv) { DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", device_xname(sc->sc_dev))); flash_bank = 0; @@ -12078,8 +12139,8 @@ wm_nvm_read_spt(struct wm_softc *sc, int /* 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) { + rv = wm_read_ich8_dword(sc, act_offset & ~0x3, &dword); + if (rv) { aprint_error_dev(sc->sc_dev, "%s: failed to read NVM\n", __func__); break; @@ -12091,7 +12152,8 @@ wm_nvm_read_spt(struct wm_softc *sc, int data[i] = (uint16_t)((dword >> 16) & 0xFFFF); } - return error; + sc->nvm.release(sc); + return rv; } /* iNVM */ @@ -12139,6 +12201,9 @@ wm_nvm_read_invm(struct wm_softc *sc, in DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); + if (sc->nvm.acquire(sc) != 0) + return -1; + for (i = 0; i < words; i++) { switch (offset + i) { case NVM_OFF_MACADDR: @@ -12193,104 +12258,12 @@ wm_nvm_read_invm(struct wm_softc *sc, in } } + sc->nvm.release(sc); return rv; } /* Lock, detecting NVM type, validate checksum, version and read */ -/* - * wm_nvm_acquire: - * - * Perform the EEPROM handshake required on some chips. - */ -static int -wm_nvm_acquire(struct wm_softc *sc) -{ - uint32_t reg; - int x; - int ret = 0; - - DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", - device_xname(sc->sc_dev), __func__)); - - if (sc->sc_type >= WM_T_ICH8) { - ret = wm_get_nvm_ich8lan(sc); - } else if (sc->sc_flags & WM_F_LOCK_EXTCNF) { - ret = wm_get_swfwhw_semaphore(sc); - } else if (sc->sc_flags & WM_F_LOCK_SWFW) { - /* This will also do wm_get_swsm_semaphore() if needed */ - ret = wm_get_swfw_semaphore(sc, SWFW_EEP_SM); - } else if (sc->sc_flags & WM_F_LOCK_SWSM) { - ret = wm_get_swsm_semaphore(sc); - } - - if (ret) { - aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", - __func__); - return 1; - } - - if (sc->sc_flags & WM_F_LOCK_EECD) { - reg = CSR_READ(sc, WMREG_EECD); - - /* Request EEPROM access. */ - reg |= EECD_EE_REQ; - CSR_WRITE(sc, WMREG_EECD, reg); - - /* ..and wait for it to be granted. */ - for (x = 0; x < 1000; x++) { - reg = CSR_READ(sc, WMREG_EECD); - if (reg & EECD_EE_GNT) - break; - delay(5); - } - if ((reg & EECD_EE_GNT) == 0) { - aprint_error_dev(sc->sc_dev, - "could not acquire EEPROM GNT\n"); - reg &= ~EECD_EE_REQ; - CSR_WRITE(sc, WMREG_EECD, reg); - if (sc->sc_flags & WM_F_LOCK_EXTCNF) - wm_put_swfwhw_semaphore(sc); - if (sc->sc_flags & WM_F_LOCK_SWFW) - wm_put_swfw_semaphore(sc, SWFW_EEP_SM); - else if (sc->sc_flags & WM_F_LOCK_SWSM) - wm_put_swsm_semaphore(sc); - return 1; - } - } - - return 0; -} - -/* - * wm_nvm_release: - * - * Release the EEPROM mutex. - */ -static void -wm_nvm_release(struct wm_softc *sc) -{ - uint32_t reg; - - DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", - device_xname(sc->sc_dev), __func__)); - - if (sc->sc_flags & WM_F_LOCK_EECD) { - reg = CSR_READ(sc, WMREG_EECD); - reg &= ~EECD_EE_REQ; - CSR_WRITE(sc, WMREG_EECD, reg); - } - - if (sc->sc_type >= WM_T_ICH8) { - wm_put_nvm_ich8lan(sc); - } else if (sc->sc_flags & WM_F_LOCK_EXTCNF) - wm_put_swfwhw_semaphore(sc); - else if (sc->sc_flags & WM_F_LOCK_SWFW) - wm_put_swfw_semaphore(sc, SWFW_EEP_SM); - else if (sc->sc_flags & WM_F_LOCK_SWSM) - wm_put_swsm_semaphore(sc); -} - static int wm_nvm_is_onboard_eeprom(struct wm_softc *sc) { @@ -12542,27 +12515,10 @@ wm_nvm_read(struct wm_softc *sc, int wor device_xname(sc->sc_dev), __func__)); if (sc->sc_flags & WM_F_EEPROM_INVALID) - return 1; - - if (wm_nvm_acquire(sc)) - return 1; - - 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)) - 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) - rv = wm_nvm_read_eerd(sc, word, wordcnt, data); - else if (sc->sc_flags & WM_F_EEPROM_SPI) - rv = wm_nvm_read_spi(sc, word, wordcnt, data); - else - rv = wm_nvm_read_uwire(sc, word, wordcnt, data); + return -1; - wm_nvm_release(sc); + rv = sc->nvm.read(sc, word, wordcnt, data); + return rv; } @@ -12589,6 +12545,94 @@ wm_put_null(struct wm_softc *sc) return; } +static int +wm_get_eecd(struct wm_softc *sc) +{ + uint32_t reg; + int x; + + DPRINTF(WM_DEBUG_LOCK | WM_DEBUG_NVM, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); + + reg = CSR_READ(sc, WMREG_EECD); + + /* Request EEPROM access. */ + reg |= EECD_EE_REQ; + CSR_WRITE(sc, WMREG_EECD, reg); + + /* ..and wait for it to be granted. */ + for (x = 0; x < 1000; x++) { + reg = CSR_READ(sc, WMREG_EECD); + if (reg & EECD_EE_GNT) + break; + delay(5); + } + if ((reg & EECD_EE_GNT) == 0) { + aprint_error_dev(sc->sc_dev, + "could not acquire EEPROM GNT\n"); + reg &= ~EECD_EE_REQ; + CSR_WRITE(sc, WMREG_EECD, reg); + return -1; + } + + return 0; +} + +static void +wm_nvm_eec_clock_raise(struct wm_softc *sc, uint32_t *eecd) +{ + + *eecd |= EECD_SK; + CSR_WRITE(sc, WMREG_EECD, *eecd); + CSR_WRITE_FLUSH(sc); + if ((sc->sc_flags & WM_F_EEPROM_SPI) != 0) + delay(1); + else + delay(50); +} + +static void +wm_nvm_eec_clock_lower(struct wm_softc *sc, uint32_t *eecd) +{ + + *eecd &= ~EECD_SK; + CSR_WRITE(sc, WMREG_EECD, *eecd); + CSR_WRITE_FLUSH(sc); + if ((sc->sc_flags & WM_F_EEPROM_SPI) != 0) + delay(1); + else + delay(50); +} + +static void +wm_put_eecd(struct wm_softc *sc) +{ + uint32_t reg; + + DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); + + /* Stop nvm */ + reg = CSR_READ(sc, WMREG_EECD); + if ((sc->sc_flags & WM_F_EEPROM_SPI) != 0) { + /* Pull CS high */ + reg |= EECD_CS; + wm_nvm_eec_clock_lower(sc, ®); + } else { + /* CS on Microwire is active-high */ + reg &= ~(EECD_CS | EECD_DI); + CSR_WRITE(sc, WMREG_EECD, reg); + wm_nvm_eec_clock_raise(sc, ®); + wm_nvm_eec_clock_lower(sc, ®); + } + + reg = CSR_READ(sc, WMREG_EECD); + reg &= ~EECD_EE_REQ; + CSR_WRITE(sc, WMREG_EECD, reg); + + return; +} + /* * Get hardware semaphore. * Same as e1000_get_hw_semaphore_generic() @@ -12665,7 +12709,7 @@ wm_put_swsm_semaphore(struct wm_softc *s /* * Get SW/FW semaphore. - * Same as e1000_acquire_swfw_sync_82575(). + * Same as e1000_acquire_swfw_sync_{80003es2lan,82575}(). */ static int wm_get_swfw_semaphore(struct wm_softc *sc, uint16_t mask) @@ -12673,31 +12717,31 @@ wm_get_swfw_semaphore(struct wm_softc *s uint32_t swfw_sync; uint32_t swmask = mask << SWFW_SOFT_SHIFT; uint32_t fwmask = mask << SWFW_FIRM_SHIFT; - int timeout = 200; + int timeout; DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); - KASSERT((sc->sc_flags & WM_F_LOCK_SWSM) != 0); + + if (sc->sc_type == WM_T_80003) + timeout = 50; + else + timeout = 200; for (timeout = 0; timeout < 200; timeout++) { - if (sc->sc_flags & WM_F_LOCK_SWSM) { - if (wm_get_swsm_semaphore(sc)) { - aprint_error_dev(sc->sc_dev, - "%s: failed to get semaphore\n", - __func__); - return 1; - } + if (wm_get_swsm_semaphore(sc)) { + aprint_error_dev(sc->sc_dev, + "%s: failed to get semaphore\n", + __func__); + return 1; } swfw_sync = CSR_READ(sc, WMREG_SW_FW_SYNC); if ((swfw_sync & (swmask | fwmask)) == 0) { swfw_sync |= swmask; CSR_WRITE(sc, WMREG_SW_FW_SYNC, swfw_sync); - if (sc->sc_flags & WM_F_LOCK_SWSM) - wm_put_swsm_semaphore(sc); + wm_put_swsm_semaphore(sc); return 0; } - if (sc->sc_flags & WM_F_LOCK_SWSM) - wm_put_swsm_semaphore(sc); + wm_put_swsm_semaphore(sc); delay(5000); } printf("%s: failed to get swfw semaphore mask 0x%x swfw 0x%x\n", @@ -12712,17 +12756,103 @@ wm_put_swfw_semaphore(struct wm_softc *s DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", device_xname(sc->sc_dev), __func__)); - KASSERT((sc->sc_flags & WM_F_LOCK_SWSM) != 0); - if (sc->sc_flags & WM_F_LOCK_SWSM) { - while (wm_get_swsm_semaphore(sc) != 0) - continue; - } + while (wm_get_swsm_semaphore(sc) != 0) + continue; + swfw_sync = CSR_READ(sc, WMREG_SW_FW_SYNC); swfw_sync &= ~(mask << SWFW_SOFT_SHIFT); CSR_WRITE(sc, WMREG_SW_FW_SYNC, swfw_sync); - if (sc->sc_flags & WM_F_LOCK_SWSM) + + wm_put_swsm_semaphore(sc); +} + +static int +wm_get_nvm_80003(struct wm_softc *sc) +{ + int rv; + + DPRINTF(WM_DEBUG_LOCK | WM_DEBUG_NVM, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); + + if ((rv = wm_get_swfw_semaphore(sc, SWFW_EEP_SM)) != 0) { + aprint_error_dev(sc->sc_dev, + "%s: failed to get semaphore(SWFW)\n", + __func__); + return rv; + } + + if (((sc->sc_flags & WM_F_LOCK_EECD) != 0) + && (rv = wm_get_eecd(sc)) != 0) { + aprint_error_dev(sc->sc_dev, + "%s: failed to get semaphore(EECD)\n", + __func__); + wm_put_swfw_semaphore(sc, SWFW_EEP_SM); + return rv; + } + + return 0; +} + +static void +wm_put_nvm_80003(struct wm_softc *sc) +{ + + DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); + + if ((sc->sc_flags & WM_F_LOCK_EECD) != 0) + wm_put_eecd(sc); + wm_put_swfw_semaphore(sc, SWFW_EEP_SM); +} + +static int +wm_get_nvm_82571(struct wm_softc *sc) +{ + int rv; + + DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); + + if ((rv = wm_get_swsm_semaphore(sc)) != 0) + return rv; + + switch (sc->sc_type) { + case WM_T_82573: + break; + default: + if ((sc->sc_flags & WM_F_LOCK_EECD) != 0) + rv = wm_get_eecd(sc); + break; + } + + if (rv != 0) { + aprint_error_dev(sc->sc_dev, + "%s: failed to get semaphore\n", + __func__); wm_put_swsm_semaphore(sc); + } + + return rv; +} + +static void +wm_put_nvm_82571(struct wm_softc *sc) +{ + + DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", + device_xname(sc->sc_dev), __func__)); + + switch (sc->sc_type) { + case WM_T_82573: + break; + default: + if ((sc->sc_flags & WM_F_LOCK_EECD) != 0) + wm_put_eecd(sc); + break; + } + + wm_put_swsm_semaphore(sc); } static int Index: src/sys/dev/pci/if_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.34 src/sys/dev/pci/if_wmvar.h:1.35 --- src/sys/dev/pci/if_wmvar.h:1.34 Mon Jun 26 04:03:34 2017 +++ src/sys/dev/pci/if_wmvar.h Tue Jul 25 06:00:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.34 2017/06/26 04:03:34 msaitoh Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.35 2017/07/25 06:00:17 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -74,10 +74,7 @@ /* sc_flags */ #define WM_F_HAS_MII 0x00000001 /* has MII */ #define WM_F_LOCK_EECD 0x00000002 /* Lock using with EECD register */ -#define WM_F_LOCK_SWSM 0x00000004 /* Lock using with SWSM register */ -#define WM_F_LOCK_SWFW 0x00000008 /* Lock using with SWFW register */ -#define WM_F_LOCK_EXTCNF 0x00000010 /* Lock using with EXTCNF reg. */ -#define WM_F_EEPROM_EERDEEWR 0x00000020 /* EEPROM access via EERD/EEWR */ +#define WM_F_EEPROM_INVM 0x00000020 /* NVM is iNVM */ #define WM_F_EEPROM_SPI 0x00000040 /* EEPROM is SPI */ #define WM_F_EEPROM_FLASH 0x00000080 /* EEPROM is FLASH */ #define WM_F_EEPROM_FLASH_HW 0x00000100 /* EEPROM is FLASH */ @@ -96,18 +93,17 @@ #define WM_F_WOL 0x00200000 #define WM_F_EEE 0x00400000 /* Energy Efficiency Ethernet */ #define WM_F_ATTACHED 0x00800000 /* attach() finished successfully */ -#define WM_F_EEPROM_INVM 0x01000000 /* NVM is iNVM */ #define WM_F_PCS_DIS_AUTONEGO 0x02000000 /* PCS Disable Autonego */ #define WM_F_PLL_WA_I210 0x04000000 /* I21[01] PLL workaround */ #define WM_FLAGS "\20" \ - "\1" "HAS_MII" "\2" "EECD" "\3" "SWSM" "\4" "SWFW" \ - "\5" "EXTCNF" "\6" "EERDEEWR" "\7" "SPI" "\10" "FLASH" \ + "\1" "HAS_MII" "\2" "LOCK_EECD" "\3" "_B02" "\4" "_B03" \ + "\5" "_B04" "\6" "INVM" "\7" "SPI" "\10" "FLASH" \ "\11" "FLASH_HW" "\12" "INVALID" "\13" "IOH_VALID" "\14" "BUS64" \ "\15" "PCIX" "\16" "CSA" "\17" "PCIE" "\20" "SGMII" \ "\21" "NEWQUEUE" "\22" "ASF_FIRM" "\23" "ARC_SUBSYS" "\24" "AMT" \ "\25" "MANAGE" "\26" "WOL" "\27" "EEE" "\30" "ATTACHED" \ - "\31" "INVM" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" + "\31" "_B24" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" /* * Variations of Intel gigabit Ethernet controller: