e1000_i210.c revision 09e77287e752c8fc9743d865ddadc1a0d81a4927
1f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/******************************************************************************* 2f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 3f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny Intel(R) Gigabit Ethernet Linux driver 4f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny Copyright(c) 2007-2012 Intel Corporation. 5f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 6f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny This program is free software; you can redistribute it and/or modify it 7f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny under the terms and conditions of the GNU General Public License, 8f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny version 2, as published by the Free Software Foundation. 9f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 10f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny This program is distributed in the hope it will be useful, but WITHOUT 11f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny more details. 14f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 15f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny You should have received a copy of the GNU General Public License along with 16f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny this program; if not, write to the Free Software Foundation, Inc., 17f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 19f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny The full GNU General Public License is included in this distribution in 20f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny the file called "COPYING". 21f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 22f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny Contact Information: 23f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 24f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 25f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 26f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny******************************************************************************/ 27f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 28f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/* e1000_i210 29f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * e1000_i211 30f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 31f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 32f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/types.h> 33f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/if_ether.h> 34f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 35f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_hw.h" 36f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_i210.h" 37f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 38f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw); 39f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic void igb_put_hw_semaphore_i210(struct e1000_hw *hw); 40f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 41f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data); 42f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw); 43f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 44f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 45f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_acquire_nvm_i210 - Request for access to EEPROM 46f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 47f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 48f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the necessary semaphores for exclusive access to the EEPROM. 49f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Set the EEPROM access request bit and wait for EEPROM access grant bit. 50f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Return successful if access grant bit set, else clear the request for 51f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * EEPROM access and return -E1000_ERR_NVM (-1). 52f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 53f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_nvm_i210(struct e1000_hw *hw) 54f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 55f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 56f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 57f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 58f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 59f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_release_nvm_i210 - Release exclusive access to EEPROM 60f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 61f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 62f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Stop any current commands to the EEPROM and clear the EEPROM request bit, 63f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * then release the semaphores acquired. 64f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 65f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_nvm_i210(struct e1000_hw *hw) 66f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 67f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 68f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 69f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 70f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 71f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore 72f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 73f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @mask: specifies which semaphore to acquire 74f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 75f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 76f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * will also specify which port we're acquiring the lock for. 77f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 78f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 79f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 80f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swfw_sync; 81f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swmask = mask; 82f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 fwmask = mask << 16; 83f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 84f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ 85f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 86f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny while (i < timeout) { 87f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (igb_get_hw_semaphore_i210(hw)) { 88f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 89f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 90f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 91f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 92f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync = rd32(E1000_SW_FW_SYNC); 93f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (!(swfw_sync & fwmask)) 94f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 95f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 96f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* 97f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Firmware currently using resource (fwmask) 98f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 99f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore_i210(hw); 100f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny mdelay(5); 101f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i++; 102f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 103f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 104f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (i == timeout) { 105f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); 106f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 107f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 108f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 109f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 110f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync |= swmask; 111f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SW_FW_SYNC, swfw_sync); 112f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 113f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore_i210(hw); 114f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 115f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 116f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 117f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 118f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 119f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_release_swfw_sync_i210 - Release SW/FW semaphore 120f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 121f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @mask: specifies which semaphore to acquire 122f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 123f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Release the SW/FW semaphore used to access the PHY or NVM. The mask 124f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * will also specify which port we're releasing the lock for. 125f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 126f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 127f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 128f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swfw_sync; 129f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 130f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS) 131f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ; /* Empty */ 132f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 133f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync = rd32(E1000_SW_FW_SYNC); 134f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync &= ~mask; 135f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SW_FW_SYNC, swfw_sync); 136f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 137f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore_i210(hw); 138f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 139f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 140f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 141f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_get_hw_semaphore_i210 - Acquire hardware semaphore 142f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 143f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 144f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the HW semaphore to access the PHY or NVM 145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) 147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swsm; 149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 timeout = hw->nvm.word_size + 1; 151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 i = 0; 152f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Get the FW semaphore. */ 154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < timeout; i++) { 155f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swsm = rd32(E1000_SWSM); 156f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); 157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Semaphore acquired if bit latched */ 159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) 160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny udelay(50); 163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (i == timeout) { 166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Release semaphores */ 167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore(hw); 168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Driver can't access the NVM\n"); 169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_NVM; 170f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_put_hw_semaphore_i210 - Release hardware semaphore 179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Release hardware semaphore used to access the PHY or NVM 182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic void igb_put_hw_semaphore_i210(struct e1000_hw *hw) 184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swsm; 186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 187f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swsm = rd32(E1000_SWSM); 188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swsm &= ~E1000_SWSM_SWESMBI; 190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SWSM, swsm); 192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 194f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register 196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset of word in the Shadow Ram to read 198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to read 199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: word read from the Shadow Ram 200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Reads a 16 bit word from the Shadow Ram using the EERD register. 202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Uses necessary synchronization semaphores. 203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 204f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, 205f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 207f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = E1000_SUCCESS; 208f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, count; 209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 210f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* We cannot hold synchronization semaphores for too long, 211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because of forceful takeover procedure. However it is more efficient 212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * to read in bursts than synchronizing access for each word. */ 213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 215f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_EERD_EEWR_MAX_COUNT : (words - i); 216f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_read_nvm_eerd(hw, offset, count, 218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny data + i); 219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 220f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (status != E1000_SUCCESS) 225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 228f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR 233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset within the Shadow RAM to be written to 235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to write 236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: 16 bit word(s) to be written to the Shadow RAM 237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Writes data to Shadow RAM at offset using EEWR register. 239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * If e1000_update_nvm_checksum is not called after this function , the 241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * data will not be committed to FLASH and also Shadow RAM will most likely 242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * contain an invalid checksum. 243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 244f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * If error code is returned, data and Shadow RAM may be inconsistent - buffer 245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * partially written. 246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, 248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = E1000_SUCCESS; 251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, count; 252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 253f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* We cannot hold synchronization semaphores for too long, 254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because of forceful takeover procedure. However it is more efficient 255f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * to write in bursts than synchronizing access for each word. */ 256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_EERD_EEWR_MAX_COUNT : (words - i); 259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_write_nvm_srwr(hw, offset, count, 261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny data + i); 262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (status != E1000_SUCCESS) 268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 275f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_write_nvm_srwr - Write to Shadow Ram using EEWR 276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset within the Shadow Ram to be written to 278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to write 279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: 16 bit word(s) to be written to the Shadow Ram 280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 281f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Writes data to Shadow Ram at offset using EEWR register. 282f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 283f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * If igb_update_nvm_checksum is not called after this function , the 284f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Shadow Ram will most likely contain an invalid checksum. 285f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 286f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 287f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 288f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 289f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny struct e1000_nvm_info *nvm = &hw->nvm; 290f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 i, k, eewr = 0; 291f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 attempts = 100000; 292f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 293f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 294f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* 295f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * A check for invalid values: offset too large, too many words, 296f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * too many words for the offset, and not enough words. 297f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 298f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 299f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny (words == 0)) { 300f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("nvm parameter(s) out of bounds\n"); 301f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_NVM; 302f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 303f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 304f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 305f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i++) { 306f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | 307f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny (data[i] << E1000_NVM_RW_REG_DATA) | 308f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_NVM_RW_REG_START; 309f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 310f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SRWR, eewr); 311f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 312f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (k = 0; k < attempts; k++) { 313f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (E1000_NVM_RW_REG_DONE & 314f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny rd32(E1000_SRWR)) { 315f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = E1000_SUCCESS; 316f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 317f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 318f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny udelay(5); 319f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 320f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 321f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) { 322f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Shadow RAM write EEWR timed out\n"); 323f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 324f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 325f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 326f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 327f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 328f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 329f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 330f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 331f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 332f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_nvm_i211 - Read NVM wrapper function for I211 333f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 334f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @address: the word address (aka eeprom offset) to read 335f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the data read 336f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 337f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Wrapper function to return data formerly found in the NVM. 338f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 339f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, 340f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 341f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 342f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 343f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 344f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Only the MAC addr is required to be present in the iNVM */ 345f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny switch (offset) { 346f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_MAC_ADDR: 347f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_invm_i211(hw, offset, &data[0]); 348f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]); 349f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]); 350f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) 351f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("MAC Addr not found in iNVM\n"); 352f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 353f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_ID_LED_SETTINGS: 354f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_INIT_CTRL_2: 355f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_INIT_CTRL_4: 356f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_LED_1_CFG: 357f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_LED_0_2_CFG: 358f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_read_invm_i211(hw, offset, data); 359f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 360f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_COMPAT: 361f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210; 362f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 363f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_SUB_DEV_ID: 364f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->subsystem_device_id; 365f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 366f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_SUB_VEN_ID: 367f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->subsystem_vendor_id; 368f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 369f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_DEV_ID: 370f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->device_id; 371f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 372f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_VEN_ID: 373f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->vendor_id; 374f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 375f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny default: 376f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM word 0x%02x is not mapped.\n", offset); 377f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = NVM_RESERVED_WORD; 378f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 379f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 380f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 381f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_invm_i211 - Reads OTP 385f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 386f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @address: the word address (aka eeprom offset) to read 387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the data read 388f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Reads 16-bit words from the OTP. Return error when the word is not 390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * stored in OTP. 391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data) 393f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 394f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 395f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 invm_dword; 396f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i; 397f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u8 record_type, word_address; 398f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < E1000_INVM_SIZE; i++) { 400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny invm_dword = rd32(E1000_INVM_DATA_REG(i)); 401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Get record type */ 402f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); 403f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) 404f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 405f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) 406f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; 407f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) 408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; 409f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { 410f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); 411f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (word_address == (u8)address) { 412f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = INVM_DWORD_TO_WORD_DATA(invm_dword); 413f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Read INVM Word 0x%02x = %x", 414f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny address, *data); 415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_SUCCESS; 416f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 417f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 418f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 419f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 420f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (status != E1000_SUCCESS) 421f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Requested word 0x%02x not found in OTP\n", address); 422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 423f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 424f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 425f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 42609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * igb_read_invm_version - Reads iNVM version and image type 42709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * @hw: pointer to the HW structure 42809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * @invm_ver: version structure for the version read 42909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * 43009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * Reads iNVM version and image type. 43109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/ 43209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw, 43309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny struct e1000_fw_version *invm_ver) { 43409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 *record = NULL; 43509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 *next_record = NULL; 43609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 i = 0; 43709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 invm_dword = 0; 43809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / 43909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny E1000_INVM_RECORD_SIZE_IN_BYTES); 44009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 buffer[E1000_INVM_SIZE]; 44109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 44209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u16 version = 0; 44309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 44409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read iNVM memory */ 44509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 0; i < E1000_INVM_SIZE; i++) { 44609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_dword = rd32(E1000_INVM_DATA_REG(i)); 44709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny buffer[i] = invm_dword; 44809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 44909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 45009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read version number */ 45109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 1; i < invm_blocks; i++) { 45209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny record = &buffer[invm_blocks - i]; 45309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny next_record = &buffer[invm_blocks - i + 1]; 45409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 45509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have first version location used */ 45609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { 45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = 0; 45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have second version location used */ 46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((i == 1) && 46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { 46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; 46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have odd version location 46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * used and it is the last one used 47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny */ 47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && 47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && 47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny (i != 1))) { 47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*next_record & E1000_INVM_VER_FIELD_TWO) 47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny >> 13; 47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have even version location 48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * used and it is the last one used 48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny */ 48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && 48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & 0x3) == 0)) { 48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; 48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 48909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if (status == E1000_SUCCESS) { 49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) 49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny >> E1000_INVM_MAJOR_SHIFT; 49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; 49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read Image Type */ 49609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 1; i < invm_blocks; i++) { 49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny record = &buffer[invm_blocks - i]; 49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny next_record = &buffer[invm_blocks - i + 1]; 49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have image type in first location used */ 50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { 50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_img_type = 0; 50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have image type in first location used */ 50709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((((*record & 0x3) == 0) && 50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || 50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((((*record & 0x3) != 0) && (i != 1)))) { 51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_img_type = 51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; 51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 51609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny return status; 51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny} 51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/** 520f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_validate_nvm_checksum_i210 - Validate EEPROM checksum 521f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 522f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 523f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 524f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * and then verifies that the sum of the EEPROM is equal to 0xBABA. 525f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 526f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw) 527f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 528f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = E1000_SUCCESS; 529f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); 530f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 531f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 532f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 533f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* 534f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Replace the read function with semaphore grabbing with 535f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * the one that skips this for a while. 536f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * We have semaphore taken already here. 537f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 538f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny read_op_ptr = hw->nvm.ops.read; 539f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.read = igb_read_nvm_eerd; 540f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 541f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_validate_nvm_checksum(hw); 542f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 543f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Revert original read operation. */ 544f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.read = read_op_ptr; 545f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 546f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 547f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 548f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 549f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 550f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_update_nvm_checksum_i210 - Update EEPROM checksum 557f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 559f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Updates the EEPROM checksum by reading/adding each word of the EEPROM 560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * up to the checksum. Then calculates the EEPROM checksum and writes the 561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * value to the EEPROM. Next commit EEPROM data onto the Flash. 562f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_nvm_checksum_i210(struct e1000_hw *hw) 564f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 checksum = 0; 567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, nvm_data; 568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* 570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Read the first word from the EEPROM. If this times out or fails, do 571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * not continue or we could be in for a very long wait while every 572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * EEPROM read fails 573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data); 575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) { 576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("EEPROM read failed\n"); 577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* 582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Do not use hw->nvm.ops.write, hw->nvm.ops.read 583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because we do not want to take the synchronization 584f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * semaphores twice here. 585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < NVM_CHECKSUM_REG; i++) { 588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data); 589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val) { 590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Read Error while updating checksum.\n"); 592f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 594f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny checksum += nvm_data; 595f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny checksum = (u16) NVM_SUM - checksum; 597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, 598f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny &checksum); 599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) { 600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Write Error while updating checksum.\n"); 602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 603f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_update_flash_i210(hw); 608f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 609f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_update_flash_i210 - Commit EEPROM to the flash 617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_flash_i210(struct e1000_hw *hw) 621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 flup; 624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_pool_flash_update_done_i210(hw); 626f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val == -E1000_ERR_NVM) { 627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update time out\n"); 628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 629f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 630f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 631f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210; 632f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_EECD, flup); 633f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 634f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_pool_flash_update_done_i210(hw); 635f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val == E1000_SUCCESS) 636f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update complete\n"); 637f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny else 638f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update time out\n"); 639f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 640f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 641f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 642f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 643f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 644f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 645f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_pool_flash_update_done_i210 - Pool FLUDONE status. 646f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 647f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 648f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 649f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) 650f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 651f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = -E1000_ERR_NVM; 652f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 i, reg; 653f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 654f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { 655f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny reg = rd32(E1000_EECD); 656f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (reg & E1000_EECD_FLUDONE_I210) { 657f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = E1000_SUCCESS; 658f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 659f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 660f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny udelay(5); 661f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 662f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 663f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 664f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 665f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 666f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 667f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_valid_led_default_i210 - Verify a valid default LED config 668f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 669f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the NVM (EEPROM) 670f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 671f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Read the EEPROM for the current default LED configuration. If the 672f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * LED configuration is not valid, set to a valid LED configuration. 673f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 674f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data) 675f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 676f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val; 677f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 678f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 679f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val) { 680f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Read Error\n"); 681f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny switch (hw->phy.media_type) { 686f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case e1000_media_type_internal_serdes: 687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210_SERDES; 688f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case e1000_media_type_copper: 690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny default: 691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210; 692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 698