175eba5b6SRobert Mustacchi /****************************************************************************** 275eba5b6SRobert Mustacchi 3*42cc51e0SRobert Mustacchi Copyright (c) 2001-2015, Intel Corporation 475eba5b6SRobert Mustacchi All rights reserved. 575eba5b6SRobert Mustacchi 675eba5b6SRobert Mustacchi Redistribution and use in source and binary forms, with or without 775eba5b6SRobert Mustacchi modification, are permitted provided that the following conditions are met: 875eba5b6SRobert Mustacchi 975eba5b6SRobert Mustacchi 1. Redistributions of source code must retain the above copyright notice, 1075eba5b6SRobert Mustacchi this list of conditions and the following disclaimer. 1175eba5b6SRobert Mustacchi 1275eba5b6SRobert Mustacchi 2. Redistributions in binary form must reproduce the above copyright 1375eba5b6SRobert Mustacchi notice, this list of conditions and the following disclaimer in the 1475eba5b6SRobert Mustacchi documentation and/or other materials provided with the distribution. 1575eba5b6SRobert Mustacchi 1675eba5b6SRobert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its 1775eba5b6SRobert Mustacchi contributors may be used to endorse or promote products derived from 1875eba5b6SRobert Mustacchi this software without specific prior written permission. 1975eba5b6SRobert Mustacchi 2075eba5b6SRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2175eba5b6SRobert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2275eba5b6SRobert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2375eba5b6SRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2475eba5b6SRobert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2575eba5b6SRobert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2675eba5b6SRobert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2775eba5b6SRobert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2875eba5b6SRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2975eba5b6SRobert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3075eba5b6SRobert Mustacchi POSSIBILITY OF SUCH DAMAGE. 3175eba5b6SRobert Mustacchi 3275eba5b6SRobert Mustacchi ******************************************************************************/ 3375eba5b6SRobert Mustacchi /*$FreeBSD$*/ 3475eba5b6SRobert Mustacchi 3575eba5b6SRobert Mustacchi #include "e1000_api.h" 3675eba5b6SRobert Mustacchi 3775eba5b6SRobert Mustacchi 3875eba5b6SRobert Mustacchi static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw); 3975eba5b6SRobert Mustacchi static void e1000_release_nvm_i210(struct e1000_hw *hw); 4075eba5b6SRobert Mustacchi static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw); 4175eba5b6SRobert Mustacchi static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 4275eba5b6SRobert Mustacchi u16 *data); 4375eba5b6SRobert Mustacchi static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw); 4475eba5b6SRobert Mustacchi static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data); 4575eba5b6SRobert Mustacchi 4675eba5b6SRobert Mustacchi /** 4775eba5b6SRobert Mustacchi * e1000_acquire_nvm_i210 - Request for access to EEPROM 4875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 4975eba5b6SRobert Mustacchi * 5075eba5b6SRobert Mustacchi * Acquire the necessary semaphores for exclusive access to the EEPROM. 5175eba5b6SRobert Mustacchi * Set the EEPROM access request bit and wait for EEPROM access grant bit. 5275eba5b6SRobert Mustacchi * Return successful if access grant bit set, else clear the request for 5375eba5b6SRobert Mustacchi * EEPROM access and return -E1000_ERR_NVM (-1). 5475eba5b6SRobert Mustacchi **/ 5575eba5b6SRobert Mustacchi static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw) 5675eba5b6SRobert Mustacchi { 5775eba5b6SRobert Mustacchi s32 ret_val; 5875eba5b6SRobert Mustacchi 5975eba5b6SRobert Mustacchi DEBUGFUNC("e1000_acquire_nvm_i210"); 6075eba5b6SRobert Mustacchi 6175eba5b6SRobert Mustacchi ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 6275eba5b6SRobert Mustacchi 6375eba5b6SRobert Mustacchi return ret_val; 6475eba5b6SRobert Mustacchi } 6575eba5b6SRobert Mustacchi 6675eba5b6SRobert Mustacchi /** 6775eba5b6SRobert Mustacchi * e1000_release_nvm_i210 - Release exclusive access to EEPROM 6875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 6975eba5b6SRobert Mustacchi * 7075eba5b6SRobert Mustacchi * Stop any current commands to the EEPROM and clear the EEPROM request bit, 7175eba5b6SRobert Mustacchi * then release the semaphores acquired. 7275eba5b6SRobert Mustacchi **/ 7375eba5b6SRobert Mustacchi static void e1000_release_nvm_i210(struct e1000_hw *hw) 7475eba5b6SRobert Mustacchi { 7575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_release_nvm_i210"); 7675eba5b6SRobert Mustacchi 7775eba5b6SRobert Mustacchi e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 7875eba5b6SRobert Mustacchi } 7975eba5b6SRobert Mustacchi 8075eba5b6SRobert Mustacchi /** 8175eba5b6SRobert Mustacchi * e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore 8275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 8375eba5b6SRobert Mustacchi * @mask: specifies which semaphore to acquire 8475eba5b6SRobert Mustacchi * 8575eba5b6SRobert Mustacchi * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 8675eba5b6SRobert Mustacchi * will also specify which port we're acquiring the lock for. 8775eba5b6SRobert Mustacchi **/ 8875eba5b6SRobert Mustacchi s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 8975eba5b6SRobert Mustacchi { 9075eba5b6SRobert Mustacchi u32 swfw_sync; 9175eba5b6SRobert Mustacchi u32 swmask = mask; 9275eba5b6SRobert Mustacchi u32 fwmask = mask << 16; 9375eba5b6SRobert Mustacchi s32 ret_val = E1000_SUCCESS; 9475eba5b6SRobert Mustacchi s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ 9575eba5b6SRobert Mustacchi 9675eba5b6SRobert Mustacchi DEBUGFUNC("e1000_acquire_swfw_sync_i210"); 9775eba5b6SRobert Mustacchi 9875eba5b6SRobert Mustacchi while (i < timeout) { 9975eba5b6SRobert Mustacchi if (e1000_get_hw_semaphore_i210(hw)) { 10075eba5b6SRobert Mustacchi ret_val = -E1000_ERR_SWFW_SYNC; 10175eba5b6SRobert Mustacchi goto out; 10275eba5b6SRobert Mustacchi } 10375eba5b6SRobert Mustacchi 10475eba5b6SRobert Mustacchi swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 10575eba5b6SRobert Mustacchi if (!(swfw_sync & (fwmask | swmask))) 10675eba5b6SRobert Mustacchi break; 10775eba5b6SRobert Mustacchi 10875eba5b6SRobert Mustacchi /* 10975eba5b6SRobert Mustacchi * Firmware currently using resource (fwmask) 11075eba5b6SRobert Mustacchi * or other software thread using resource (swmask) 11175eba5b6SRobert Mustacchi */ 11275eba5b6SRobert Mustacchi e1000_put_hw_semaphore_generic(hw); 11375eba5b6SRobert Mustacchi msec_delay_irq(5); 11475eba5b6SRobert Mustacchi i++; 11575eba5b6SRobert Mustacchi } 11675eba5b6SRobert Mustacchi 11775eba5b6SRobert Mustacchi if (i == timeout) { 11875eba5b6SRobert Mustacchi DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); 11975eba5b6SRobert Mustacchi ret_val = -E1000_ERR_SWFW_SYNC; 12075eba5b6SRobert Mustacchi goto out; 12175eba5b6SRobert Mustacchi } 12275eba5b6SRobert Mustacchi 12375eba5b6SRobert Mustacchi swfw_sync |= swmask; 12475eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 12575eba5b6SRobert Mustacchi 12675eba5b6SRobert Mustacchi e1000_put_hw_semaphore_generic(hw); 12775eba5b6SRobert Mustacchi 12875eba5b6SRobert Mustacchi out: 12975eba5b6SRobert Mustacchi return ret_val; 13075eba5b6SRobert Mustacchi } 13175eba5b6SRobert Mustacchi 13275eba5b6SRobert Mustacchi /** 13375eba5b6SRobert Mustacchi * e1000_release_swfw_sync_i210 - Release SW/FW semaphore 13475eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 13575eba5b6SRobert Mustacchi * @mask: specifies which semaphore to acquire 13675eba5b6SRobert Mustacchi * 13775eba5b6SRobert Mustacchi * Release the SW/FW semaphore used to access the PHY or NVM. The mask 13875eba5b6SRobert Mustacchi * will also specify which port we're releasing the lock for. 13975eba5b6SRobert Mustacchi **/ 14075eba5b6SRobert Mustacchi void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 14175eba5b6SRobert Mustacchi { 14275eba5b6SRobert Mustacchi u32 swfw_sync; 14375eba5b6SRobert Mustacchi 14475eba5b6SRobert Mustacchi DEBUGFUNC("e1000_release_swfw_sync_i210"); 14575eba5b6SRobert Mustacchi 14675eba5b6SRobert Mustacchi while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS) 14775eba5b6SRobert Mustacchi ; /* Empty */ 14875eba5b6SRobert Mustacchi 14975eba5b6SRobert Mustacchi swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 15075eba5b6SRobert Mustacchi swfw_sync &= ~mask; 15175eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 15275eba5b6SRobert Mustacchi 15375eba5b6SRobert Mustacchi e1000_put_hw_semaphore_generic(hw); 15475eba5b6SRobert Mustacchi } 15575eba5b6SRobert Mustacchi 15675eba5b6SRobert Mustacchi /** 15775eba5b6SRobert Mustacchi * e1000_get_hw_semaphore_i210 - Acquire hardware semaphore 15875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 15975eba5b6SRobert Mustacchi * 16075eba5b6SRobert Mustacchi * Acquire the HW semaphore to access the PHY or NVM 16175eba5b6SRobert Mustacchi **/ 16275eba5b6SRobert Mustacchi static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) 16375eba5b6SRobert Mustacchi { 16475eba5b6SRobert Mustacchi u32 swsm; 16575eba5b6SRobert Mustacchi s32 timeout = hw->nvm.word_size + 1; 16675eba5b6SRobert Mustacchi s32 i = 0; 16775eba5b6SRobert Mustacchi 16875eba5b6SRobert Mustacchi DEBUGFUNC("e1000_get_hw_semaphore_i210"); 16975eba5b6SRobert Mustacchi 17075eba5b6SRobert Mustacchi /* Get the SW semaphore */ 17175eba5b6SRobert Mustacchi while (i < timeout) { 17275eba5b6SRobert Mustacchi swsm = E1000_READ_REG(hw, E1000_SWSM); 17375eba5b6SRobert Mustacchi if (!(swsm & E1000_SWSM_SMBI)) 17475eba5b6SRobert Mustacchi break; 17575eba5b6SRobert Mustacchi 17675eba5b6SRobert Mustacchi usec_delay(50); 17775eba5b6SRobert Mustacchi i++; 17875eba5b6SRobert Mustacchi } 17975eba5b6SRobert Mustacchi 18075eba5b6SRobert Mustacchi if (i == timeout) { 181c124a83eSRobert Mustacchi /* In rare circumstances, the SW semaphore may already be held 182c124a83eSRobert Mustacchi * unintentionally. Clear the semaphore once before giving up. 18375eba5b6SRobert Mustacchi */ 18475eba5b6SRobert Mustacchi if (hw->dev_spec._82575.clear_semaphore_once) { 18575eba5b6SRobert Mustacchi hw->dev_spec._82575.clear_semaphore_once = FALSE; 18675eba5b6SRobert Mustacchi e1000_put_hw_semaphore_generic(hw); 18775eba5b6SRobert Mustacchi for (i = 0; i < timeout; i++) { 18875eba5b6SRobert Mustacchi swsm = E1000_READ_REG(hw, E1000_SWSM); 18975eba5b6SRobert Mustacchi if (!(swsm & E1000_SWSM_SMBI)) 19075eba5b6SRobert Mustacchi break; 19175eba5b6SRobert Mustacchi 19275eba5b6SRobert Mustacchi usec_delay(50); 19375eba5b6SRobert Mustacchi } 19475eba5b6SRobert Mustacchi } 19575eba5b6SRobert Mustacchi 19675eba5b6SRobert Mustacchi /* If we do not have the semaphore here, we have to give up. */ 19775eba5b6SRobert Mustacchi if (i == timeout) { 19875eba5b6SRobert Mustacchi DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); 19975eba5b6SRobert Mustacchi return -E1000_ERR_NVM; 20075eba5b6SRobert Mustacchi } 20175eba5b6SRobert Mustacchi } 20275eba5b6SRobert Mustacchi 20375eba5b6SRobert Mustacchi /* Get the FW semaphore. */ 20475eba5b6SRobert Mustacchi for (i = 0; i < timeout; i++) { 20575eba5b6SRobert Mustacchi swsm = E1000_READ_REG(hw, E1000_SWSM); 20675eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); 20775eba5b6SRobert Mustacchi 20875eba5b6SRobert Mustacchi /* Semaphore acquired if bit latched */ 20975eba5b6SRobert Mustacchi if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) 21075eba5b6SRobert Mustacchi break; 21175eba5b6SRobert Mustacchi 21275eba5b6SRobert Mustacchi usec_delay(50); 21375eba5b6SRobert Mustacchi } 21475eba5b6SRobert Mustacchi 21575eba5b6SRobert Mustacchi if (i == timeout) { 21675eba5b6SRobert Mustacchi /* Release semaphores */ 21775eba5b6SRobert Mustacchi e1000_put_hw_semaphore_generic(hw); 21875eba5b6SRobert Mustacchi DEBUGOUT("Driver can't access the NVM\n"); 21975eba5b6SRobert Mustacchi return -E1000_ERR_NVM; 22075eba5b6SRobert Mustacchi } 22175eba5b6SRobert Mustacchi 22275eba5b6SRobert Mustacchi return E1000_SUCCESS; 22375eba5b6SRobert Mustacchi } 22475eba5b6SRobert Mustacchi 22575eba5b6SRobert Mustacchi /** 22675eba5b6SRobert Mustacchi * e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register 22775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 22875eba5b6SRobert Mustacchi * @offset: offset of word in the Shadow Ram to read 22975eba5b6SRobert Mustacchi * @words: number of words to read 23075eba5b6SRobert Mustacchi * @data: word read from the Shadow Ram 23175eba5b6SRobert Mustacchi * 23275eba5b6SRobert Mustacchi * Reads a 16 bit word from the Shadow Ram using the EERD register. 23375eba5b6SRobert Mustacchi * Uses necessary synchronization semaphores. 23475eba5b6SRobert Mustacchi **/ 23575eba5b6SRobert Mustacchi s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, 23675eba5b6SRobert Mustacchi u16 *data) 23775eba5b6SRobert Mustacchi { 23875eba5b6SRobert Mustacchi s32 status = E1000_SUCCESS; 23975eba5b6SRobert Mustacchi u16 i, count; 24075eba5b6SRobert Mustacchi 24175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_read_nvm_srrd_i210"); 24275eba5b6SRobert Mustacchi 24375eba5b6SRobert Mustacchi /* We cannot hold synchronization semaphores for too long, 24475eba5b6SRobert Mustacchi * because of forceful takeover procedure. However it is more efficient 24575eba5b6SRobert Mustacchi * to read in bursts than synchronizing access for each word. */ 24675eba5b6SRobert Mustacchi for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 24775eba5b6SRobert Mustacchi count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 24875eba5b6SRobert Mustacchi E1000_EERD_EEWR_MAX_COUNT : (words - i); 24975eba5b6SRobert Mustacchi if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 25075eba5b6SRobert Mustacchi status = e1000_read_nvm_eerd(hw, offset, count, 25175eba5b6SRobert Mustacchi data + i); 25275eba5b6SRobert Mustacchi hw->nvm.ops.release(hw); 25375eba5b6SRobert Mustacchi } else { 25475eba5b6SRobert Mustacchi status = E1000_ERR_SWFW_SYNC; 25575eba5b6SRobert Mustacchi } 25675eba5b6SRobert Mustacchi 25775eba5b6SRobert Mustacchi if (status != E1000_SUCCESS) 25875eba5b6SRobert Mustacchi break; 25975eba5b6SRobert Mustacchi } 26075eba5b6SRobert Mustacchi 26175eba5b6SRobert Mustacchi return status; 26275eba5b6SRobert Mustacchi } 26375eba5b6SRobert Mustacchi 26475eba5b6SRobert Mustacchi /** 26575eba5b6SRobert Mustacchi * e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR 26675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 26775eba5b6SRobert Mustacchi * @offset: offset within the Shadow RAM to be written to 26875eba5b6SRobert Mustacchi * @words: number of words to write 26975eba5b6SRobert Mustacchi * @data: 16 bit word(s) to be written to the Shadow RAM 27075eba5b6SRobert Mustacchi * 27175eba5b6SRobert Mustacchi * Writes data to Shadow RAM at offset using EEWR register. 27275eba5b6SRobert Mustacchi * 27375eba5b6SRobert Mustacchi * If e1000_update_nvm_checksum is not called after this function , the 27475eba5b6SRobert Mustacchi * data will not be committed to FLASH and also Shadow RAM will most likely 27575eba5b6SRobert Mustacchi * contain an invalid checksum. 27675eba5b6SRobert Mustacchi * 27775eba5b6SRobert Mustacchi * If error code is returned, data and Shadow RAM may be inconsistent - buffer 27875eba5b6SRobert Mustacchi * partially written. 27975eba5b6SRobert Mustacchi **/ 28075eba5b6SRobert Mustacchi s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, 28175eba5b6SRobert Mustacchi u16 *data) 28275eba5b6SRobert Mustacchi { 28375eba5b6SRobert Mustacchi s32 status = E1000_SUCCESS; 28475eba5b6SRobert Mustacchi u16 i, count; 28575eba5b6SRobert Mustacchi 28675eba5b6SRobert Mustacchi DEBUGFUNC("e1000_write_nvm_srwr_i210"); 28775eba5b6SRobert Mustacchi 28875eba5b6SRobert Mustacchi /* We cannot hold synchronization semaphores for too long, 28975eba5b6SRobert Mustacchi * because of forceful takeover procedure. However it is more efficient 29075eba5b6SRobert Mustacchi * to write in bursts than synchronizing access for each word. */ 29175eba5b6SRobert Mustacchi for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 29275eba5b6SRobert Mustacchi count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 29375eba5b6SRobert Mustacchi E1000_EERD_EEWR_MAX_COUNT : (words - i); 29475eba5b6SRobert Mustacchi if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 29575eba5b6SRobert Mustacchi status = e1000_write_nvm_srwr(hw, offset, count, 29675eba5b6SRobert Mustacchi data + i); 29775eba5b6SRobert Mustacchi hw->nvm.ops.release(hw); 29875eba5b6SRobert Mustacchi } else { 29975eba5b6SRobert Mustacchi status = E1000_ERR_SWFW_SYNC; 30075eba5b6SRobert Mustacchi } 30175eba5b6SRobert Mustacchi 30275eba5b6SRobert Mustacchi if (status != E1000_SUCCESS) 30375eba5b6SRobert Mustacchi break; 30475eba5b6SRobert Mustacchi } 30575eba5b6SRobert Mustacchi 30675eba5b6SRobert Mustacchi return status; 30775eba5b6SRobert Mustacchi } 30875eba5b6SRobert Mustacchi 30975eba5b6SRobert Mustacchi /** 31075eba5b6SRobert Mustacchi * e1000_write_nvm_srwr - Write to Shadow Ram using EEWR 31175eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 31275eba5b6SRobert Mustacchi * @offset: offset within the Shadow Ram to be written to 31375eba5b6SRobert Mustacchi * @words: number of words to write 31475eba5b6SRobert Mustacchi * @data: 16 bit word(s) to be written to the Shadow Ram 31575eba5b6SRobert Mustacchi * 31675eba5b6SRobert Mustacchi * Writes data to Shadow Ram at offset using EEWR register. 31775eba5b6SRobert Mustacchi * 31875eba5b6SRobert Mustacchi * If e1000_update_nvm_checksum is not called after this function , the 31975eba5b6SRobert Mustacchi * Shadow Ram will most likely contain an invalid checksum. 32075eba5b6SRobert Mustacchi **/ 32175eba5b6SRobert Mustacchi static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 32275eba5b6SRobert Mustacchi u16 *data) 32375eba5b6SRobert Mustacchi { 32475eba5b6SRobert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm; 32575eba5b6SRobert Mustacchi u32 i, k, eewr = 0; 32675eba5b6SRobert Mustacchi u32 attempts = 100000; 32775eba5b6SRobert Mustacchi s32 ret_val = E1000_SUCCESS; 32875eba5b6SRobert Mustacchi 32975eba5b6SRobert Mustacchi DEBUGFUNC("e1000_write_nvm_srwr"); 33075eba5b6SRobert Mustacchi 33175eba5b6SRobert Mustacchi /* 33275eba5b6SRobert Mustacchi * A check for invalid values: offset too large, too many words, 33375eba5b6SRobert Mustacchi * too many words for the offset, and not enough words. 33475eba5b6SRobert Mustacchi */ 33575eba5b6SRobert Mustacchi if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 33675eba5b6SRobert Mustacchi (words == 0)) { 33775eba5b6SRobert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n"); 33875eba5b6SRobert Mustacchi ret_val = -E1000_ERR_NVM; 33975eba5b6SRobert Mustacchi goto out; 34075eba5b6SRobert Mustacchi } 34175eba5b6SRobert Mustacchi 34275eba5b6SRobert Mustacchi for (i = 0; i < words; i++) { 34375eba5b6SRobert Mustacchi eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | 34475eba5b6SRobert Mustacchi (data[i] << E1000_NVM_RW_REG_DATA) | 34575eba5b6SRobert Mustacchi E1000_NVM_RW_REG_START; 34675eba5b6SRobert Mustacchi 34775eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_SRWR, eewr); 34875eba5b6SRobert Mustacchi 34975eba5b6SRobert Mustacchi for (k = 0; k < attempts; k++) { 35075eba5b6SRobert Mustacchi if (E1000_NVM_RW_REG_DONE & 35175eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_SRWR)) { 35275eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS; 35375eba5b6SRobert Mustacchi break; 35475eba5b6SRobert Mustacchi } 35575eba5b6SRobert Mustacchi usec_delay(5); 35675eba5b6SRobert Mustacchi } 35775eba5b6SRobert Mustacchi 35875eba5b6SRobert Mustacchi if (ret_val != E1000_SUCCESS) { 35975eba5b6SRobert Mustacchi DEBUGOUT("Shadow RAM write EEWR timed out\n"); 36075eba5b6SRobert Mustacchi break; 36175eba5b6SRobert Mustacchi } 36275eba5b6SRobert Mustacchi } 36375eba5b6SRobert Mustacchi 36475eba5b6SRobert Mustacchi out: 36575eba5b6SRobert Mustacchi return ret_val; 36675eba5b6SRobert Mustacchi } 36775eba5b6SRobert Mustacchi 368c124a83eSRobert Mustacchi /** e1000_read_invm_word_i210 - Reads OTP 36975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 37075eba5b6SRobert Mustacchi * @address: the word address (aka eeprom offset) to read 37175eba5b6SRobert Mustacchi * @data: pointer to the data read 37275eba5b6SRobert Mustacchi * 37375eba5b6SRobert Mustacchi * Reads 16-bit words from the OTP. Return error when the word is not 37475eba5b6SRobert Mustacchi * stored in OTP. 37575eba5b6SRobert Mustacchi **/ 376c124a83eSRobert Mustacchi static s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) 37775eba5b6SRobert Mustacchi { 37875eba5b6SRobert Mustacchi s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 37975eba5b6SRobert Mustacchi u32 invm_dword; 38075eba5b6SRobert Mustacchi u16 i; 38175eba5b6SRobert Mustacchi u8 record_type, word_address; 38275eba5b6SRobert Mustacchi 383c124a83eSRobert Mustacchi DEBUGFUNC("e1000_read_invm_word_i210"); 38475eba5b6SRobert Mustacchi 38575eba5b6SRobert Mustacchi for (i = 0; i < E1000_INVM_SIZE; i++) { 38675eba5b6SRobert Mustacchi invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); 38775eba5b6SRobert Mustacchi /* Get record type */ 38875eba5b6SRobert Mustacchi record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); 38975eba5b6SRobert Mustacchi if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) 39075eba5b6SRobert Mustacchi break; 39175eba5b6SRobert Mustacchi if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) 39275eba5b6SRobert Mustacchi i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; 39375eba5b6SRobert Mustacchi if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) 39475eba5b6SRobert Mustacchi i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; 39575eba5b6SRobert Mustacchi if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { 39675eba5b6SRobert Mustacchi word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); 39775eba5b6SRobert Mustacchi if (word_address == address) { 39875eba5b6SRobert Mustacchi *data = INVM_DWORD_TO_WORD_DATA(invm_dword); 39975eba5b6SRobert Mustacchi DEBUGOUT2("Read INVM Word 0x%02x = %x", 40075eba5b6SRobert Mustacchi address, *data); 40175eba5b6SRobert Mustacchi status = E1000_SUCCESS; 40275eba5b6SRobert Mustacchi break; 40375eba5b6SRobert Mustacchi } 40475eba5b6SRobert Mustacchi } 40575eba5b6SRobert Mustacchi } 40675eba5b6SRobert Mustacchi if (status != E1000_SUCCESS) 40775eba5b6SRobert Mustacchi DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address); 40875eba5b6SRobert Mustacchi return status; 40975eba5b6SRobert Mustacchi } 41075eba5b6SRobert Mustacchi 411c124a83eSRobert Mustacchi /** e1000_read_invm_i210 - Read invm wrapper function for I210/I211 412c124a83eSRobert Mustacchi * @hw: pointer to the HW structure 413c124a83eSRobert Mustacchi * @address: the word address (aka eeprom offset) to read 414c124a83eSRobert Mustacchi * @data: pointer to the data read 415c124a83eSRobert Mustacchi * 416c124a83eSRobert Mustacchi * Wrapper function to return data formerly found in the NVM. 417c124a83eSRobert Mustacchi **/ 418c124a83eSRobert Mustacchi static s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset, 419c124a83eSRobert Mustacchi u16 E1000_UNUSEDARG words, u16 *data) 420c124a83eSRobert Mustacchi { 421c124a83eSRobert Mustacchi s32 ret_val = E1000_SUCCESS; 422c124a83eSRobert Mustacchi 423c124a83eSRobert Mustacchi DEBUGFUNC("e1000_read_invm_i210"); 424c124a83eSRobert Mustacchi 425c124a83eSRobert Mustacchi /* Only the MAC addr is required to be present in the iNVM */ 426c124a83eSRobert Mustacchi switch (offset) { 427c124a83eSRobert Mustacchi case NVM_MAC_ADDR: 428c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]); 429c124a83eSRobert Mustacchi ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1, 430c124a83eSRobert Mustacchi &data[1]); 431c124a83eSRobert Mustacchi ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2, 432c124a83eSRobert Mustacchi &data[2]); 433c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) 434c124a83eSRobert Mustacchi DEBUGOUT("MAC Addr not found in iNVM\n"); 435c124a83eSRobert Mustacchi break; 436c124a83eSRobert Mustacchi case NVM_INIT_CTRL_2: 437c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); 438c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) { 439c124a83eSRobert Mustacchi *data = NVM_INIT_CTRL_2_DEFAULT_I211; 440c124a83eSRobert Mustacchi ret_val = E1000_SUCCESS; 441c124a83eSRobert Mustacchi } 442c124a83eSRobert Mustacchi break; 443c124a83eSRobert Mustacchi case NVM_INIT_CTRL_4: 444c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); 445c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) { 446c124a83eSRobert Mustacchi *data = NVM_INIT_CTRL_4_DEFAULT_I211; 447c124a83eSRobert Mustacchi ret_val = E1000_SUCCESS; 448c124a83eSRobert Mustacchi } 449c124a83eSRobert Mustacchi break; 450c124a83eSRobert Mustacchi case NVM_LED_1_CFG: 451c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); 452c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) { 453c124a83eSRobert Mustacchi *data = NVM_LED_1_CFG_DEFAULT_I211; 454c124a83eSRobert Mustacchi ret_val = E1000_SUCCESS; 455c124a83eSRobert Mustacchi } 456c124a83eSRobert Mustacchi break; 457c124a83eSRobert Mustacchi case NVM_LED_0_2_CFG: 458c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); 459c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) { 460c124a83eSRobert Mustacchi *data = NVM_LED_0_2_CFG_DEFAULT_I211; 461c124a83eSRobert Mustacchi ret_val = E1000_SUCCESS; 462c124a83eSRobert Mustacchi } 463c124a83eSRobert Mustacchi break; 464c124a83eSRobert Mustacchi case NVM_ID_LED_SETTINGS: 465c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); 466c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) { 467c124a83eSRobert Mustacchi *data = ID_LED_RESERVED_FFFF; 468c124a83eSRobert Mustacchi ret_val = E1000_SUCCESS; 469c124a83eSRobert Mustacchi } 470c124a83eSRobert Mustacchi break; 471c124a83eSRobert Mustacchi case NVM_SUB_DEV_ID: 472c124a83eSRobert Mustacchi *data = hw->subsystem_device_id; 473c124a83eSRobert Mustacchi break; 474c124a83eSRobert Mustacchi case NVM_SUB_VEN_ID: 475c124a83eSRobert Mustacchi *data = hw->subsystem_vendor_id; 476c124a83eSRobert Mustacchi break; 477c124a83eSRobert Mustacchi case NVM_DEV_ID: 478c124a83eSRobert Mustacchi *data = hw->device_id; 479c124a83eSRobert Mustacchi break; 480c124a83eSRobert Mustacchi case NVM_VEN_ID: 481c124a83eSRobert Mustacchi *data = hw->vendor_id; 482c124a83eSRobert Mustacchi break; 483c124a83eSRobert Mustacchi default: 484c124a83eSRobert Mustacchi DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset); 485c124a83eSRobert Mustacchi *data = NVM_RESERVED_WORD; 486c124a83eSRobert Mustacchi break; 487c124a83eSRobert Mustacchi } 488c124a83eSRobert Mustacchi return ret_val; 489c124a83eSRobert Mustacchi } 490c124a83eSRobert Mustacchi 49175eba5b6SRobert Mustacchi /** 49275eba5b6SRobert Mustacchi * e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum 49375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 49475eba5b6SRobert Mustacchi * 49575eba5b6SRobert Mustacchi * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 49675eba5b6SRobert Mustacchi * and then verifies that the sum of the EEPROM is equal to 0xBABA. 49775eba5b6SRobert Mustacchi **/ 49875eba5b6SRobert Mustacchi s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw) 49975eba5b6SRobert Mustacchi { 50075eba5b6SRobert Mustacchi s32 status = E1000_SUCCESS; 50175eba5b6SRobert Mustacchi s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); 50275eba5b6SRobert Mustacchi 50375eba5b6SRobert Mustacchi DEBUGFUNC("e1000_validate_nvm_checksum_i210"); 50475eba5b6SRobert Mustacchi 50575eba5b6SRobert Mustacchi if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 50675eba5b6SRobert Mustacchi 50775eba5b6SRobert Mustacchi /* 50875eba5b6SRobert Mustacchi * Replace the read function with semaphore grabbing with 50975eba5b6SRobert Mustacchi * the one that skips this for a while. 51075eba5b6SRobert Mustacchi * We have semaphore taken already here. 51175eba5b6SRobert Mustacchi */ 51275eba5b6SRobert Mustacchi read_op_ptr = hw->nvm.ops.read; 51375eba5b6SRobert Mustacchi hw->nvm.ops.read = e1000_read_nvm_eerd; 51475eba5b6SRobert Mustacchi 51575eba5b6SRobert Mustacchi status = e1000_validate_nvm_checksum_generic(hw); 51675eba5b6SRobert Mustacchi 51775eba5b6SRobert Mustacchi /* Revert original read operation. */ 51875eba5b6SRobert Mustacchi hw->nvm.ops.read = read_op_ptr; 51975eba5b6SRobert Mustacchi 52075eba5b6SRobert Mustacchi hw->nvm.ops.release(hw); 52175eba5b6SRobert Mustacchi } else { 52275eba5b6SRobert Mustacchi status = E1000_ERR_SWFW_SYNC; 52375eba5b6SRobert Mustacchi } 52475eba5b6SRobert Mustacchi 52575eba5b6SRobert Mustacchi return status; 52675eba5b6SRobert Mustacchi } 52775eba5b6SRobert Mustacchi 52875eba5b6SRobert Mustacchi 52975eba5b6SRobert Mustacchi /** 53075eba5b6SRobert Mustacchi * e1000_update_nvm_checksum_i210 - Update EEPROM checksum 53175eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 53275eba5b6SRobert Mustacchi * 53375eba5b6SRobert Mustacchi * Updates the EEPROM checksum by reading/adding each word of the EEPROM 53475eba5b6SRobert Mustacchi * up to the checksum. Then calculates the EEPROM checksum and writes the 53575eba5b6SRobert Mustacchi * value to the EEPROM. Next commit EEPROM data onto the Flash. 53675eba5b6SRobert Mustacchi **/ 53775eba5b6SRobert Mustacchi s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw) 53875eba5b6SRobert Mustacchi { 539c124a83eSRobert Mustacchi s32 ret_val; 54075eba5b6SRobert Mustacchi u16 checksum = 0; 54175eba5b6SRobert Mustacchi u16 i, nvm_data; 54275eba5b6SRobert Mustacchi 54375eba5b6SRobert Mustacchi DEBUGFUNC("e1000_update_nvm_checksum_i210"); 54475eba5b6SRobert Mustacchi 54575eba5b6SRobert Mustacchi /* 54675eba5b6SRobert Mustacchi * Read the first word from the EEPROM. If this times out or fails, do 54775eba5b6SRobert Mustacchi * not continue or we could be in for a very long wait while every 54875eba5b6SRobert Mustacchi * EEPROM read fails 54975eba5b6SRobert Mustacchi */ 55075eba5b6SRobert Mustacchi ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data); 55175eba5b6SRobert Mustacchi if (ret_val != E1000_SUCCESS) { 55275eba5b6SRobert Mustacchi DEBUGOUT("EEPROM read failed\n"); 55375eba5b6SRobert Mustacchi goto out; 55475eba5b6SRobert Mustacchi } 55575eba5b6SRobert Mustacchi 55675eba5b6SRobert Mustacchi if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 55775eba5b6SRobert Mustacchi /* 55875eba5b6SRobert Mustacchi * Do not use hw->nvm.ops.write, hw->nvm.ops.read 55975eba5b6SRobert Mustacchi * because we do not want to take the synchronization 56075eba5b6SRobert Mustacchi * semaphores twice here. 56175eba5b6SRobert Mustacchi */ 56275eba5b6SRobert Mustacchi 56375eba5b6SRobert Mustacchi for (i = 0; i < NVM_CHECKSUM_REG; i++) { 56475eba5b6SRobert Mustacchi ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data); 56575eba5b6SRobert Mustacchi if (ret_val) { 56675eba5b6SRobert Mustacchi hw->nvm.ops.release(hw); 56775eba5b6SRobert Mustacchi DEBUGOUT("NVM Read Error while updating checksum.\n"); 56875eba5b6SRobert Mustacchi goto out; 56975eba5b6SRobert Mustacchi } 57075eba5b6SRobert Mustacchi checksum += nvm_data; 57175eba5b6SRobert Mustacchi } 57275eba5b6SRobert Mustacchi checksum = (u16) NVM_SUM - checksum; 57375eba5b6SRobert Mustacchi ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, 57475eba5b6SRobert Mustacchi &checksum); 57575eba5b6SRobert Mustacchi if (ret_val != E1000_SUCCESS) { 57675eba5b6SRobert Mustacchi hw->nvm.ops.release(hw); 57775eba5b6SRobert Mustacchi DEBUGOUT("NVM Write Error while updating checksum.\n"); 57875eba5b6SRobert Mustacchi goto out; 57975eba5b6SRobert Mustacchi } 58075eba5b6SRobert Mustacchi 58175eba5b6SRobert Mustacchi hw->nvm.ops.release(hw); 58275eba5b6SRobert Mustacchi 58375eba5b6SRobert Mustacchi ret_val = e1000_update_flash_i210(hw); 58475eba5b6SRobert Mustacchi } else { 58575eba5b6SRobert Mustacchi ret_val = E1000_ERR_SWFW_SYNC; 58675eba5b6SRobert Mustacchi } 58775eba5b6SRobert Mustacchi out: 58875eba5b6SRobert Mustacchi return ret_val; 58975eba5b6SRobert Mustacchi } 59075eba5b6SRobert Mustacchi 59175eba5b6SRobert Mustacchi /** 592c124a83eSRobert Mustacchi * e1000_get_flash_presence_i210 - Check if flash device is detected. 593c124a83eSRobert Mustacchi * @hw: pointer to the HW structure 594c124a83eSRobert Mustacchi * 595c124a83eSRobert Mustacchi **/ 596c124a83eSRobert Mustacchi bool e1000_get_flash_presence_i210(struct e1000_hw *hw) 597c124a83eSRobert Mustacchi { 598c124a83eSRobert Mustacchi u32 eec = 0; 599c124a83eSRobert Mustacchi bool ret_val = FALSE; 600c124a83eSRobert Mustacchi 601c124a83eSRobert Mustacchi DEBUGFUNC("e1000_get_flash_presence_i210"); 602c124a83eSRobert Mustacchi 603c124a83eSRobert Mustacchi eec = E1000_READ_REG(hw, E1000_EECD); 604c124a83eSRobert Mustacchi 605c124a83eSRobert Mustacchi if (eec & E1000_EECD_FLASH_DETECTED_I210) 606c124a83eSRobert Mustacchi ret_val = TRUE; 607c124a83eSRobert Mustacchi 608c124a83eSRobert Mustacchi return ret_val; 609c124a83eSRobert Mustacchi } 610c124a83eSRobert Mustacchi 611c124a83eSRobert Mustacchi /** 61275eba5b6SRobert Mustacchi * e1000_update_flash_i210 - Commit EEPROM to the flash 61375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 61475eba5b6SRobert Mustacchi * 61575eba5b6SRobert Mustacchi **/ 61675eba5b6SRobert Mustacchi s32 e1000_update_flash_i210(struct e1000_hw *hw) 61775eba5b6SRobert Mustacchi { 618c124a83eSRobert Mustacchi s32 ret_val; 61975eba5b6SRobert Mustacchi u32 flup; 62075eba5b6SRobert Mustacchi 62175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_update_flash_i210"); 62275eba5b6SRobert Mustacchi 62375eba5b6SRobert Mustacchi ret_val = e1000_pool_flash_update_done_i210(hw); 62475eba5b6SRobert Mustacchi if (ret_val == -E1000_ERR_NVM) { 62575eba5b6SRobert Mustacchi DEBUGOUT("Flash update time out\n"); 62675eba5b6SRobert Mustacchi goto out; 62775eba5b6SRobert Mustacchi } 62875eba5b6SRobert Mustacchi 62975eba5b6SRobert Mustacchi flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210; 63075eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, flup); 63175eba5b6SRobert Mustacchi 63275eba5b6SRobert Mustacchi ret_val = e1000_pool_flash_update_done_i210(hw); 63375eba5b6SRobert Mustacchi if (ret_val == E1000_SUCCESS) 63475eba5b6SRobert Mustacchi DEBUGOUT("Flash update complete\n"); 63575eba5b6SRobert Mustacchi else 63675eba5b6SRobert Mustacchi DEBUGOUT("Flash update time out\n"); 63775eba5b6SRobert Mustacchi 63875eba5b6SRobert Mustacchi out: 63975eba5b6SRobert Mustacchi return ret_val; 64075eba5b6SRobert Mustacchi } 64175eba5b6SRobert Mustacchi 64275eba5b6SRobert Mustacchi /** 64375eba5b6SRobert Mustacchi * e1000_pool_flash_update_done_i210 - Pool FLUDONE status. 64475eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 64575eba5b6SRobert Mustacchi * 64675eba5b6SRobert Mustacchi **/ 64775eba5b6SRobert Mustacchi s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw) 64875eba5b6SRobert Mustacchi { 64975eba5b6SRobert Mustacchi s32 ret_val = -E1000_ERR_NVM; 65075eba5b6SRobert Mustacchi u32 i, reg; 65175eba5b6SRobert Mustacchi 65275eba5b6SRobert Mustacchi DEBUGFUNC("e1000_pool_flash_update_done_i210"); 65375eba5b6SRobert Mustacchi 65475eba5b6SRobert Mustacchi for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { 65575eba5b6SRobert Mustacchi reg = E1000_READ_REG(hw, E1000_EECD); 65675eba5b6SRobert Mustacchi if (reg & E1000_EECD_FLUDONE_I210) { 65775eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS; 65875eba5b6SRobert Mustacchi break; 65975eba5b6SRobert Mustacchi } 66075eba5b6SRobert Mustacchi usec_delay(5); 66175eba5b6SRobert Mustacchi } 66275eba5b6SRobert Mustacchi 66375eba5b6SRobert Mustacchi return ret_val; 66475eba5b6SRobert Mustacchi } 66575eba5b6SRobert Mustacchi 66675eba5b6SRobert Mustacchi /** 66775eba5b6SRobert Mustacchi * e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers 66875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 66975eba5b6SRobert Mustacchi * 670c124a83eSRobert Mustacchi * Initialize the i210/i211 NVM parameters and function pointers. 67175eba5b6SRobert Mustacchi **/ 67275eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw) 67375eba5b6SRobert Mustacchi { 674c124a83eSRobert Mustacchi s32 ret_val; 67575eba5b6SRobert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm; 67675eba5b6SRobert Mustacchi 67775eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_nvm_params_i210"); 67875eba5b6SRobert Mustacchi 67975eba5b6SRobert Mustacchi ret_val = e1000_init_nvm_params_82575(hw); 68075eba5b6SRobert Mustacchi nvm->ops.acquire = e1000_acquire_nvm_i210; 68175eba5b6SRobert Mustacchi nvm->ops.release = e1000_release_nvm_i210; 682c124a83eSRobert Mustacchi nvm->ops.valid_led_default = e1000_valid_led_default_i210; 683c124a83eSRobert Mustacchi if (e1000_get_flash_presence_i210(hw)) { 684c124a83eSRobert Mustacchi hw->nvm.type = e1000_nvm_flash_hw; 68575eba5b6SRobert Mustacchi nvm->ops.read = e1000_read_nvm_srrd_i210; 68675eba5b6SRobert Mustacchi nvm->ops.write = e1000_write_nvm_srwr_i210; 68775eba5b6SRobert Mustacchi nvm->ops.validate = e1000_validate_nvm_checksum_i210; 68875eba5b6SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_i210; 689c124a83eSRobert Mustacchi } else { 690c124a83eSRobert Mustacchi hw->nvm.type = e1000_nvm_invm; 691c124a83eSRobert Mustacchi nvm->ops.read = e1000_read_invm_i210; 69275eba5b6SRobert Mustacchi nvm->ops.write = e1000_null_write_nvm; 69375eba5b6SRobert Mustacchi nvm->ops.validate = e1000_null_ops_generic; 69475eba5b6SRobert Mustacchi nvm->ops.update = e1000_null_ops_generic; 695c124a83eSRobert Mustacchi } 696c124a83eSRobert Mustacchi return ret_val; 69775eba5b6SRobert Mustacchi } 69875eba5b6SRobert Mustacchi 69975eba5b6SRobert Mustacchi /** 70075eba5b6SRobert Mustacchi * e1000_init_function_pointers_i210 - Init func ptrs. 70175eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 70275eba5b6SRobert Mustacchi * 70375eba5b6SRobert Mustacchi * Called to initialize all function pointers and parameters. 70475eba5b6SRobert Mustacchi **/ 70575eba5b6SRobert Mustacchi void e1000_init_function_pointers_i210(struct e1000_hw *hw) 70675eba5b6SRobert Mustacchi { 70775eba5b6SRobert Mustacchi e1000_init_function_pointers_82575(hw); 70875eba5b6SRobert Mustacchi hw->nvm.ops.init_params = e1000_init_nvm_params_i210; 709c124a83eSRobert Mustacchi 71075eba5b6SRobert Mustacchi return; 71175eba5b6SRobert Mustacchi } 71275eba5b6SRobert Mustacchi 71375eba5b6SRobert Mustacchi /** 71475eba5b6SRobert Mustacchi * e1000_valid_led_default_i210 - Verify a valid default LED config 71575eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 71675eba5b6SRobert Mustacchi * @data: pointer to the NVM (EEPROM) 71775eba5b6SRobert Mustacchi * 71875eba5b6SRobert Mustacchi * Read the EEPROM for the current default LED configuration. If the 71975eba5b6SRobert Mustacchi * LED configuration is not valid, set to a valid LED configuration. 72075eba5b6SRobert Mustacchi **/ 72175eba5b6SRobert Mustacchi static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data) 72275eba5b6SRobert Mustacchi { 72375eba5b6SRobert Mustacchi s32 ret_val; 72475eba5b6SRobert Mustacchi 72575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_valid_led_default_i210"); 72675eba5b6SRobert Mustacchi 72775eba5b6SRobert Mustacchi ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 72875eba5b6SRobert Mustacchi if (ret_val) { 72975eba5b6SRobert Mustacchi DEBUGOUT("NVM Read Error\n"); 73075eba5b6SRobert Mustacchi goto out; 73175eba5b6SRobert Mustacchi } 73275eba5b6SRobert Mustacchi 73375eba5b6SRobert Mustacchi if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 73475eba5b6SRobert Mustacchi switch (hw->phy.media_type) { 73575eba5b6SRobert Mustacchi case e1000_media_type_internal_serdes: 73675eba5b6SRobert Mustacchi *data = ID_LED_DEFAULT_I210_SERDES; 73775eba5b6SRobert Mustacchi break; 73875eba5b6SRobert Mustacchi case e1000_media_type_copper: 73975eba5b6SRobert Mustacchi default: 74075eba5b6SRobert Mustacchi *data = ID_LED_DEFAULT_I210; 74175eba5b6SRobert Mustacchi break; 74275eba5b6SRobert Mustacchi } 74375eba5b6SRobert Mustacchi } 74475eba5b6SRobert Mustacchi out: 74575eba5b6SRobert Mustacchi return ret_val; 74675eba5b6SRobert Mustacchi } 74713485e69SGarrett D'Amore 74813485e69SGarrett D'Amore /** 74913485e69SGarrett D'Amore * __e1000_access_xmdio_reg - Read/write XMDIO register 75013485e69SGarrett D'Amore * @hw: pointer to the HW structure 75113485e69SGarrett D'Amore * @address: XMDIO address to program 75213485e69SGarrett D'Amore * @dev_addr: device address to program 75313485e69SGarrett D'Amore * @data: pointer to value to read/write from/to the XMDIO address 75413485e69SGarrett D'Amore * @read: boolean flag to indicate read or write 75513485e69SGarrett D'Amore **/ 75613485e69SGarrett D'Amore static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address, 75713485e69SGarrett D'Amore u8 dev_addr, u16 *data, bool read) 75813485e69SGarrett D'Amore { 759c124a83eSRobert Mustacchi s32 ret_val; 76013485e69SGarrett D'Amore 76113485e69SGarrett D'Amore DEBUGFUNC("__e1000_access_xmdio_reg"); 76213485e69SGarrett D'Amore 76313485e69SGarrett D'Amore ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr); 76413485e69SGarrett D'Amore if (ret_val) 76513485e69SGarrett D'Amore return ret_val; 76613485e69SGarrett D'Amore 76713485e69SGarrett D'Amore ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address); 76813485e69SGarrett D'Amore if (ret_val) 76913485e69SGarrett D'Amore return ret_val; 77013485e69SGarrett D'Amore 77113485e69SGarrett D'Amore ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA | 77213485e69SGarrett D'Amore dev_addr); 77313485e69SGarrett D'Amore if (ret_val) 77413485e69SGarrett D'Amore return ret_val; 77513485e69SGarrett D'Amore 77613485e69SGarrett D'Amore if (read) 77713485e69SGarrett D'Amore ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data); 77813485e69SGarrett D'Amore else 77913485e69SGarrett D'Amore ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data); 78013485e69SGarrett D'Amore if (ret_val) 78113485e69SGarrett D'Amore return ret_val; 78213485e69SGarrett D'Amore 78313485e69SGarrett D'Amore /* Recalibrate the device back to 0 */ 78413485e69SGarrett D'Amore ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0); 78513485e69SGarrett D'Amore if (ret_val) 78613485e69SGarrett D'Amore return ret_val; 78713485e69SGarrett D'Amore 78813485e69SGarrett D'Amore return ret_val; 78913485e69SGarrett D'Amore } 79013485e69SGarrett D'Amore 79113485e69SGarrett D'Amore /** 79213485e69SGarrett D'Amore * e1000_read_xmdio_reg - Read XMDIO register 79313485e69SGarrett D'Amore * @hw: pointer to the HW structure 79413485e69SGarrett D'Amore * @addr: XMDIO address to program 79513485e69SGarrett D'Amore * @dev_addr: device address to program 79613485e69SGarrett D'Amore * @data: value to be read from the EMI address 79713485e69SGarrett D'Amore **/ 79813485e69SGarrett D'Amore s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data) 79913485e69SGarrett D'Amore { 80013485e69SGarrett D'Amore DEBUGFUNC("e1000_read_xmdio_reg"); 80113485e69SGarrett D'Amore 80213485e69SGarrett D'Amore return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, TRUE); 80313485e69SGarrett D'Amore } 80413485e69SGarrett D'Amore 80513485e69SGarrett D'Amore /** 80613485e69SGarrett D'Amore * e1000_write_xmdio_reg - Write XMDIO register 80713485e69SGarrett D'Amore * @hw: pointer to the HW structure 80813485e69SGarrett D'Amore * @addr: XMDIO address to program 80913485e69SGarrett D'Amore * @dev_addr: device address to program 81013485e69SGarrett D'Amore * @data: value to be written to the XMDIO address 81113485e69SGarrett D'Amore **/ 81213485e69SGarrett D'Amore s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) 81313485e69SGarrett D'Amore { 81413485e69SGarrett D'Amore DEBUGFUNC("e1000_read_xmdio_reg"); 81513485e69SGarrett D'Amore 81613485e69SGarrett D'Amore return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, FALSE); 81713485e69SGarrett D'Amore } 81813485e69SGarrett D'Amore 819c124a83eSRobert Mustacchi /** 820c124a83eSRobert Mustacchi * e1000_pll_workaround_i210 821c124a83eSRobert Mustacchi * @hw: pointer to the HW structure 822c124a83eSRobert Mustacchi * 823c124a83eSRobert Mustacchi * Works around an errata in the PLL circuit where it occasionally 824c124a83eSRobert Mustacchi * provides the wrong clock frequency after power up. 825c124a83eSRobert Mustacchi **/ 826c124a83eSRobert Mustacchi static s32 e1000_pll_workaround_i210(struct e1000_hw *hw) 827c124a83eSRobert Mustacchi { 828c124a83eSRobert Mustacchi s32 ret_val; 829c124a83eSRobert Mustacchi u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val; 830c124a83eSRobert Mustacchi u16 nvm_word, phy_word, pci_word, tmp_nvm; 831c124a83eSRobert Mustacchi int i; 83213485e69SGarrett D'Amore 833c124a83eSRobert Mustacchi /* Get and set needed register values */ 834c124a83eSRobert Mustacchi wuc = E1000_READ_REG(hw, E1000_WUC); 835c124a83eSRobert Mustacchi mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); 836c124a83eSRobert Mustacchi reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO; 837c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val); 838c124a83eSRobert Mustacchi 839c124a83eSRobert Mustacchi /* Get data from NVM, or set default */ 840c124a83eSRobert Mustacchi ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD, 841c124a83eSRobert Mustacchi &nvm_word); 842c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) 843c124a83eSRobert Mustacchi nvm_word = E1000_INVM_DEFAULT_AL; 844c124a83eSRobert Mustacchi tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL; 845c124a83eSRobert Mustacchi for (i = 0; i < E1000_MAX_PLL_TRIES; i++) { 846c124a83eSRobert Mustacchi /* check current state directly from internal PHY */ 847c124a83eSRobert Mustacchi e1000_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE | 848c124a83eSRobert Mustacchi E1000_PHY_PLL_FREQ_REG), &phy_word); 849c124a83eSRobert Mustacchi if ((phy_word & E1000_PHY_PLL_UNCONF) 850c124a83eSRobert Mustacchi != E1000_PHY_PLL_UNCONF) { 851c124a83eSRobert Mustacchi ret_val = E1000_SUCCESS; 852c124a83eSRobert Mustacchi break; 853c124a83eSRobert Mustacchi } else { 854c124a83eSRobert Mustacchi ret_val = -E1000_ERR_PHY; 855c124a83eSRobert Mustacchi } 856c124a83eSRobert Mustacchi /* directly reset the internal PHY */ 857c124a83eSRobert Mustacchi ctrl = E1000_READ_REG(hw, E1000_CTRL); 858c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, ctrl|E1000_CTRL_PHY_RST); 859c124a83eSRobert Mustacchi 860c124a83eSRobert Mustacchi ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 861c124a83eSRobert Mustacchi ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE); 862c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 863c124a83eSRobert Mustacchi 864c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_WUC, 0); 865c124a83eSRobert Mustacchi reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16); 866c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val); 867c124a83eSRobert Mustacchi 868c124a83eSRobert Mustacchi e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); 869c124a83eSRobert Mustacchi pci_word |= E1000_PCI_PMCSR_D3; 870c124a83eSRobert Mustacchi e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); 871c124a83eSRobert Mustacchi msec_delay(1); 872c124a83eSRobert Mustacchi pci_word &= ~E1000_PCI_PMCSR_D3; 873c124a83eSRobert Mustacchi e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); 874c124a83eSRobert Mustacchi reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16); 875c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val); 876c124a83eSRobert Mustacchi 877c124a83eSRobert Mustacchi /* restore WUC register */ 878c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_WUC, wuc); 879c124a83eSRobert Mustacchi } 880c124a83eSRobert Mustacchi /* restore MDICNFG setting */ 881c124a83eSRobert Mustacchi E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); 882c124a83eSRobert Mustacchi return ret_val; 883c124a83eSRobert Mustacchi } 884c124a83eSRobert Mustacchi 885c124a83eSRobert Mustacchi /** 886*42cc51e0SRobert Mustacchi * e1000_get_cfg_done_i210 - Read config done bit 887*42cc51e0SRobert Mustacchi * @hw: pointer to the HW structure 888*42cc51e0SRobert Mustacchi * 889*42cc51e0SRobert Mustacchi * Read the management control register for the config done bit for 890*42cc51e0SRobert Mustacchi * completion status. NOTE: silicon which is EEPROM-less will fail trying 891*42cc51e0SRobert Mustacchi * to read the config done bit, so an error is *ONLY* logged and returns 892*42cc51e0SRobert Mustacchi * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon 893*42cc51e0SRobert Mustacchi * would not be able to be reset or change link. 894*42cc51e0SRobert Mustacchi **/ 895*42cc51e0SRobert Mustacchi static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw) 896*42cc51e0SRobert Mustacchi { 897*42cc51e0SRobert Mustacchi s32 timeout = PHY_CFG_TIMEOUT; 898*42cc51e0SRobert Mustacchi u32 mask = E1000_NVM_CFG_DONE_PORT_0; 899*42cc51e0SRobert Mustacchi 900*42cc51e0SRobert Mustacchi DEBUGFUNC("e1000_get_cfg_done_i210"); 901*42cc51e0SRobert Mustacchi 902*42cc51e0SRobert Mustacchi while (timeout) { 903*42cc51e0SRobert Mustacchi if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask) 904*42cc51e0SRobert Mustacchi break; 905*42cc51e0SRobert Mustacchi msec_delay(1); 906*42cc51e0SRobert Mustacchi timeout--; 907*42cc51e0SRobert Mustacchi } 908*42cc51e0SRobert Mustacchi if (!timeout) 909*42cc51e0SRobert Mustacchi DEBUGOUT("MNG configuration cycle has not completed.\n"); 910*42cc51e0SRobert Mustacchi 911*42cc51e0SRobert Mustacchi return E1000_SUCCESS; 912*42cc51e0SRobert Mustacchi } 913*42cc51e0SRobert Mustacchi 914*42cc51e0SRobert Mustacchi /** 915c124a83eSRobert Mustacchi * e1000_init_hw_i210 - Init hw for I210/I211 916c124a83eSRobert Mustacchi * @hw: pointer to the HW structure 917c124a83eSRobert Mustacchi * 918c124a83eSRobert Mustacchi * Called to initialize hw for i210 hw family. 919c124a83eSRobert Mustacchi **/ 920c124a83eSRobert Mustacchi s32 e1000_init_hw_i210(struct e1000_hw *hw) 921c124a83eSRobert Mustacchi { 922c124a83eSRobert Mustacchi s32 ret_val; 923c124a83eSRobert Mustacchi 924c124a83eSRobert Mustacchi DEBUGFUNC("e1000_init_hw_i210"); 925c124a83eSRobert Mustacchi if ((hw->mac.type >= e1000_i210) && 926c124a83eSRobert Mustacchi !(e1000_get_flash_presence_i210(hw))) { 927c124a83eSRobert Mustacchi ret_val = e1000_pll_workaround_i210(hw); 928c124a83eSRobert Mustacchi if (ret_val != E1000_SUCCESS) 929c124a83eSRobert Mustacchi return ret_val; 930c124a83eSRobert Mustacchi } 931*42cc51e0SRobert Mustacchi hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210; 932c124a83eSRobert Mustacchi ret_val = e1000_init_hw_82575(hw); 933c124a83eSRobert Mustacchi return ret_val; 934c124a83eSRobert Mustacchi } 935