1e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny/* Intel(R) Gigabit Ethernet Linux driver 2e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * Copyright(c) 2007-2014 Intel Corporation. 3e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * 4e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * This program is free software; you can redistribute it and/or modify it 5e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * under the terms and conditions of the GNU General Public License, 6e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * version 2, as published by the Free Software Foundation. 7e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * 8e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * This program is distributed in the hope it will be useful, but WITHOUT 9e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * more details. 12e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * 13e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * You should have received a copy of the GNU General Public License along with 14e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * this program; if not, see <http://www.gnu.org/licenses/>. 15e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * 16e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * The full GNU General Public License is included in this distribution in 17e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * the file called "COPYING". 18e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * 19e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * Contact Information: 20e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 21e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 22e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny */ 23f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 24f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/* e1000_i210 25f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * e1000_i211 26f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 27f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 28f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/types.h> 29f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/if_ether.h> 30f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 31f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_hw.h" 32f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_i210.h" 33f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 34167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_update_flash_i210(struct e1000_hw *hw); 35167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsher 367916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 377916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_get_hw_semaphore_i210 - Acquire hardware semaphore 387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 397916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * Acquire the HW semaphore to access the PHY or NVM 417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */ 427916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) 437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u32 swsm; 457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 timeout = hw->nvm.word_size + 1; 467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 i = 0; 477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 48d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick /* Get the SW semaphore */ 49d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick while (i < timeout) { 50d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick swsm = rd32(E1000_SWSM); 51d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick if (!(swsm & E1000_SWSM_SMBI)) 52d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick break; 53d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick 54d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick udelay(50); 55d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick i++; 56d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick } 57d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick 58d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick if (i == timeout) { 59d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick /* In rare circumstances, the SW semaphore may already be held 60d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick * unintentionally. Clear the semaphore once before giving up. 61d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick */ 62d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick if (hw->dev_spec._82575.clear_semaphore_once) { 63d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick hw->dev_spec._82575.clear_semaphore_once = false; 64d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick igb_put_hw_semaphore(hw); 65d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick for (i = 0; i < timeout; i++) { 66d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick swsm = rd32(E1000_SWSM); 67d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick if (!(swsm & E1000_SWSM_SMBI)) 68d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick break; 69d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick 70d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick udelay(50); 71d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick } 72d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick } 73d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick 74d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick /* If we do not have the semaphore here, we have to give up. */ 75d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick if (i == timeout) { 76d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick hw_dbg("Driver can't access device - SMBI bit is set.\n"); 77d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick return -E1000_ERR_NVM; 78d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick } 79d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick } 80d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick 817916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* Get the FW semaphore. */ 827916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny for (i = 0; i < timeout; i++) { 837916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny swsm = rd32(E1000_SWSM); 847916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); 857916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 867916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* Semaphore acquired if bit latched */ 877916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) 887916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny break; 897916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 907916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny udelay(50); 917916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (i == timeout) { 947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* Release semaphores */ 957916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny igb_put_hw_semaphore(hw); 967916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny hw_dbg("Driver can't access the NVM\n"); 97d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick return -E1000_ERR_NVM; 987916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 10023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka return 0; 1017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 102f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 103f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 104f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_acquire_nvm_i210 - Request for access to EEPROM 105f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 106f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 107f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the necessary semaphores for exclusive access to the EEPROM. 108f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Set the EEPROM access request bit and wait for EEPROM access grant bit. 109f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Return successful if access grant bit set, else clear the request for 110f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * EEPROM access and return -E1000_ERR_NVM (-1). 111f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 112167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_acquire_nvm_i210(struct e1000_hw *hw) 113f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 114f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 115f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 116f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 117f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 118f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_release_nvm_i210 - Release exclusive access to EEPROM 119f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 120f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 121f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Stop any current commands to the EEPROM and clear the EEPROM request bit, 122f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * then release the semaphores acquired. 123f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 124167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic void igb_release_nvm_i210(struct e1000_hw *hw) 125f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 126f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 127f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 128f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 129f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 130f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore 131f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 132f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @mask: specifies which semaphore to acquire 133f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 134f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 135f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * will also specify which port we're acquiring the lock for. 136f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 137f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 138f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 139f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swfw_sync; 140f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swmask = mask; 141f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 fwmask = mask << 16; 14223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 ret_val = 0; 143f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ 144f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny while (i < timeout) { 146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (igb_get_hw_semaphore_i210(hw)) { 147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync = rd32(E1000_SW_FW_SYNC); 152d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick if (!(swfw_sync & (fwmask | swmask))) 153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 155b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Firmware currently using resource (fwmask) */ 156d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick igb_put_hw_semaphore(hw); 157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny mdelay(5); 158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i++; 159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (i == timeout) { 162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); 163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync |= swmask; 168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SW_FW_SYNC, swfw_sync); 169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 170d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick igb_put_hw_semaphore(hw); 171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_release_swfw_sync_i210 - Release SW/FW semaphore 177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @mask: specifies which semaphore to acquire 179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Release the SW/FW semaphore used to access the PHY or NVM. The mask 181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * will also specify which port we're releasing the lock for. 182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swfw_sync; 186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 18723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka while (igb_get_hw_semaphore_i210(hw)) 188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ; /* Empty */ 189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync = rd32(E1000_SW_FW_SYNC); 191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync &= ~mask; 192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SW_FW_SYNC, swfw_sync); 193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 194d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick igb_put_hw_semaphore(hw); 195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register 199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset of word in the Shadow Ram to read 201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to read 202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: word read from the Shadow Ram 203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 204f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Reads a 16 bit word from the Shadow Ram using the EERD register. 205f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Uses necessary synchronization semaphores. 206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 207167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, 208167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsher u16 *data) 209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 21023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 status = 0; 211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, count; 212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* We cannot hold synchronization semaphores for too long, 214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because of forceful takeover procedure. However it is more efficient 215b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher * to read in bursts than synchronizing access for each word. 216b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher */ 217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_EERD_EEWR_MAX_COUNT : (words - i); 22023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (!(hw->nvm.ops.acquire(hw))) { 221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_read_nvm_eerd(hw, offset, count, 222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny data + i); 223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 22823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (status) 229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_write_nvm_srwr - Write to Shadow Ram using EEWR 237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset within the Shadow Ram to be written to 239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to write 240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: 16 bit word(s) to be written to the Shadow Ram 241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Writes data to Shadow Ram at offset using EEWR register. 243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 244f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * If igb_update_nvm_checksum is not called after this function , the 245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Shadow Ram will most likely contain an invalid checksum. 246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny struct e1000_nvm_info *nvm = &hw->nvm; 251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 i, k, eewr = 0; 252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 attempts = 100000; 25323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 ret_val = 0; 254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 255b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* A check for invalid values: offset too large, too many words, 256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * too many words for the offset, and not enough words. 257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny (words == 0)) { 260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("nvm parameter(s) out of bounds\n"); 261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_NVM; 262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i++) { 266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | 267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny (data[i] << E1000_NVM_RW_REG_DATA) | 268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_NVM_RW_REG_START; 269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SRWR, eewr); 271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (k = 0; k < attempts; k++) { 273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (E1000_NVM_RW_REG_DONE & 274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny rd32(E1000_SRWR)) { 27523d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny udelay(5); 279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 28123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 282f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Shadow RAM write EEWR timed out\n"); 283f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 284f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 285f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 286f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 287f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 288f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 289f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 290f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 291f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 2927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR 2937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 2947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @offset: offset within the Shadow RAM to be written to 2957916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @words: number of words to write 2967916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @data: 16 bit word(s) to be written to the Shadow RAM 2977916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 2987916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * Writes data to Shadow RAM at offset using EEWR register. 2997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 3007916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * If e1000_update_nvm_checksum is not called after this function , the 3017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * data will not be committed to FLASH and also Shadow RAM will most likely 3027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * contain an invalid checksum. 3037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 3047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * If error code is returned, data and Shadow RAM may be inconsistent - buffer 3057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * partially written. 306b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/ 307167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, 308167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsher u16 *data) 3097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 31023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 status = 0; 3117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u16 i, count; 3127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* We cannot hold synchronization semaphores for too long, 3147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * because of forceful takeover procedure. However it is more efficient 3157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * to write in bursts than synchronizing access for each word. 3167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */ 3177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 3187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 3197916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny E1000_EERD_EEWR_MAX_COUNT : (words - i); 32023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (!(hw->nvm.ops.acquire(hw))) { 3217916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny status = igb_write_nvm_srwr(hw, offset, count, 3227916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny data + i); 3237916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny hw->nvm.ops.release(hw); 3247916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } else { 3257916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 3267916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 3277916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 32823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (status) 3297916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny break; 3307916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 3317916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3327916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny return status; 3337916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 3347916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3357916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 336ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * igb_read_invm_word_i210 - Reads OTP 337ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * @hw: pointer to the HW structure 338ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * @address: the word address (aka eeprom offset) to read 339ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * @data: pointer to the data read 340ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * 341ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * Reads 16-bit words from the OTP. Return error when the word is not 342ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * stored in OTP. 343ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny **/ 344ef3a009297c50876980f21060aee61e8b516a990Carolyn Wybornystatic s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) 345ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny{ 346ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 347ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny u32 invm_dword; 348ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny u16 i; 349ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny u8 record_type, word_address; 350ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny 351ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny for (i = 0; i < E1000_INVM_SIZE; i++) { 352ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny invm_dword = rd32(E1000_INVM_DATA_REG(i)); 353ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny /* Get record type */ 354ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); 355ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) 356ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny break; 357ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) 358ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; 359ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) 360ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; 361ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { 362ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); 363ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny if (word_address == address) { 364ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *data = INVM_DWORD_TO_WORD_DATA(invm_dword); 365c5ffe7e1f745984b37b8ffe03b03f3d716a072f3Jakub Kicinski hw_dbg("Read INVM Word 0x%02x = %x\n", 366ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny address, *data); 36723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 368ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny break; 369ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny } 370ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny } 371ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny } 37223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (status) 373ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny hw_dbg("Requested word 0x%02x not found in OTP\n", address); 374ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny return status; 375ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny} 376ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny 377ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny/** 378ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * igb_read_invm_i210 - Read invm wrapper function for I210/I211 379f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 3805c17a203721d72c36798e5d7fa564e1adf8beb65Akeem G. Abodunrin * @words: number of words to read 381f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the data read 382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Wrapper function to return data formerly found in the NVM. 384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 385ef3a009297c50876980f21060aee61e8b516a990Carolyn Wybornystatic s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset, 386ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny u16 words __always_unused, u16 *data) 387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 38823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 ret_val = 0; 389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Only the MAC addr is required to be present in the iNVM */ 391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny switch (offset) { 392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_MAC_ADDR: 393ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]); 394ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1, 395ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny &data[1]); 396ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2, 397ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny &data[2]); 39823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) 399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("MAC Addr not found in iNVM\n"); 400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_INIT_CTRL_2: 402ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); 40323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 4041720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_INIT_CTRL_2_DEFAULT_I211; 40523d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 4061720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 4071720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny break; 408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_INIT_CTRL_4: 409ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); 41023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 4111720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_INIT_CTRL_4_DEFAULT_I211; 41223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 4131720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 4141720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny break; 415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_LED_1_CFG: 416ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); 41723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 4181720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_LED_1_CFG_DEFAULT_I211; 41923d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 4201720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 4211720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny break; 422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_LED_0_2_CFG: 423ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); 42423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 4251720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_LED_0_2_CFG_DEFAULT_I211; 42623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 4271720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 428f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 4291720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny case NVM_ID_LED_SETTINGS: 430ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); 43123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 4321720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = ID_LED_RESERVED_FFFF; 43323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 4341720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 435b26141d47a4a73f07853986bd6b5a9f4ee6b4fa1Carolyn Wyborny break; 436f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_SUB_DEV_ID: 437f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->subsystem_device_id; 438f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 439f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_SUB_VEN_ID: 440f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->subsystem_vendor_id; 441f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 442f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_DEV_ID: 443f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->device_id; 444f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 445f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_VEN_ID: 446f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->vendor_id; 447f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 448f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny default: 449f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM word 0x%02x is not mapped.\n", offset); 450f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = NVM_RESERVED_WORD; 451f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 452f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 453f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 454f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 455f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 456f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * igb_read_invm_version - Reads iNVM version and image type 45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * @hw: pointer to the HW structure 45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * @invm_ver: version structure for the version read 46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * 46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * Reads iNVM version and image type. 46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/ 46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw, 46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny struct e1000_fw_version *invm_ver) { 46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 *record = NULL; 46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 *next_record = NULL; 46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 i = 0; 46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 invm_dword = 0; 46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / 47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny E1000_INVM_RECORD_SIZE_IN_BYTES); 47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 buffer[E1000_INVM_SIZE]; 47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u16 version = 0; 47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read iNVM memory */ 47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 0; i < E1000_INVM_SIZE; i++) { 47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_dword = rd32(E1000_INVM_DATA_REG(i)); 47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny buffer[i] = invm_dword; 47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read version number */ 48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 1; i < invm_blocks; i++) { 48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny record = &buffer[invm_blocks - i]; 48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny next_record = &buffer[invm_blocks - i + 1]; 48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have first version location used */ 48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { 48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = 0; 48923d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have second version location used */ 49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((i == 1) && 49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { 49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; 49623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have odd version location 50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * used and it is the last one used 50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny */ 50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && 50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && 50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny (i != 1))) { 50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*next_record & E1000_INVM_VER_FIELD_TWO) 50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny >> 13; 50723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have even version location 51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * used and it is the last one used 51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny */ 51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && 51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & 0x3) == 0)) { 51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; 51623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 52009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 52123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (!status) { 52209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) 52309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny >> E1000_INVM_MAJOR_SHIFT; 52409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; 52509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 52609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read Image Type */ 52709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 1; i < invm_blocks; i++) { 52809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny record = &buffer[invm_blocks - i]; 52909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny next_record = &buffer[invm_blocks - i + 1]; 53009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 53109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have image type in first location used */ 53209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { 53309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_img_type = 0; 53423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 53509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 53609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 53709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have image type in first location used */ 53809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((((*record & 0x3) == 0) && 53909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || 54009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((((*record & 0x3) != 0) && (i != 1)))) { 54109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_img_type = 54209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; 54323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka status = 0; 54409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 54509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 54609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 54709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny return status; 54809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny} 54909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 55009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/** 551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_validate_nvm_checksum_i210 - Validate EEPROM checksum 552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * and then verifies that the sum of the EEPROM is equal to 0xBABA. 556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 557167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw) 558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 55923d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 status = 0; 560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); 561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 56223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (!(hw->nvm.ops.acquire(hw))) { 563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 564b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Replace the read function with semaphore grabbing with 565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * the one that skips this for a while. 566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * We have semaphore taken already here. 567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny read_op_ptr = hw->nvm.ops.read; 569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.read = igb_read_nvm_eerd; 570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_validate_nvm_checksum(hw); 572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Revert original read operation. */ 574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.read = read_op_ptr; 575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 584f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_update_nvm_checksum_i210 - Update EEPROM checksum 586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Updates the EEPROM checksum by reading/adding each word of the EEPROM 589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * up to the checksum. Then calculates the EEPROM checksum and writes the 590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * value to the EEPROM. Next commit EEPROM data onto the Flash. 591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 592167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw) 593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 59423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 ret_val = 0; 595f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 checksum = 0; 596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, nvm_data; 597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 598b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Read the first word from the EEPROM. If this times out or fails, do 599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * not continue or we could be in for a very long wait while every 600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * EEPROM read fails 601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data); 60323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("EEPROM read failed\n"); 605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 60823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (!(hw->nvm.ops.acquire(hw))) { 609b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Do not use hw->nvm.ops.write, hw->nvm.ops.read 610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because we do not want to take the synchronization 611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * semaphores twice here. 612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < NVM_CHECKSUM_REG; i++) { 615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data); 616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val) { 617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Read Error while updating checksum.\n"); 619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny checksum += nvm_data; 622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny checksum = (u16) NVM_SUM - checksum; 624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, 625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny &checksum); 62623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) { 627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Write Error while updating checksum.\n"); 629f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 630f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 631f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 632f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 633f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 634f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_update_flash_i210(hw); 635f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 636f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 637f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 638f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 639f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 640f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 641f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 642f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 6437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_pool_flash_update_done_i210 - Pool FLUDONE status. 6447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 6457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 646b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/ 6477916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) 6487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 6497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 ret_val = -E1000_ERR_NVM; 6507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u32 i, reg; 6517916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 6527916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { 6537916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny reg = rd32(E1000_EECD); 6547916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (reg & E1000_EECD_FLUDONE_I210) { 65523d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka ret_val = 0; 6567916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny break; 6577916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 6587916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny udelay(5); 6597916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 6607916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 6617916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny return ret_val; 6627916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 6637916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 6647916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 6655a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny * igb_get_flash_presence_i210 - Check if flash device is detected. 6665a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny * @hw: pointer to the HW structure 6675a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny * 6685a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny **/ 6695a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wybornybool igb_get_flash_presence_i210(struct e1000_hw *hw) 6705a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny{ 6715a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny u32 eec = 0; 6725a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny bool ret_val = false; 6735a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny 6745a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny eec = rd32(E1000_EECD); 6755a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny if (eec & E1000_EECD_FLASH_DETECTED_I210) 6765a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny ret_val = true; 6775a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny 6785a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny return ret_val; 6795a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny} 6805a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny 6815a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny/** 682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_update_flash_i210 - Commit EEPROM to the flash 683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 686167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_update_flash_i210(struct e1000_hw *hw) 687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 68823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 ret_val = 0; 689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 flup; 690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_pool_flash_update_done_i210(hw); 692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val == -E1000_ERR_NVM) { 693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update time out\n"); 694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210; 698f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_EECD, flup); 699f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 700f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_pool_flash_update_done_i210(hw); 70123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka if (ret_val) 702f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update complete\n"); 703f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny else 704f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update time out\n"); 705f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 706f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 707f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 708f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 709f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 710f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 711f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_valid_led_default_i210 - Verify a valid default LED config 712f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 713f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the NVM (EEPROM) 714f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 715f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Read the EEPROM for the current default LED configuration. If the 716f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * LED configuration is not valid, set to a valid LED configuration. 717f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 718f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data) 719f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 720f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val; 721f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 722f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 723f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val) { 724f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Read Error\n"); 725f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 726f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 727f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 728f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 729f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny switch (hw->phy.media_type) { 730f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case e1000_media_type_internal_serdes: 731f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210_SERDES; 732f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 733f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case e1000_media_type_copper: 734f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny default: 735f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210; 736f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 737f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 738f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 739f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 740f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 741f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 74287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 74387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/** 74487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * __igb_access_xmdio_reg - Read/write XMDIO register 74587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @hw: pointer to the HW structure 74687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @address: XMDIO address to program 74787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @dev_addr: device address to program 74887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @data: pointer to value to read/write from/to the XMDIO address 74987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @read: boolean flag to indicate read or write 75087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/ 75187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vickstatic s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address, 75287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick u8 dev_addr, u16 *data, bool read) 75387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{ 75423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka s32 ret_val = 0; 75587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 75687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr); 75787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 75887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 75987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 76087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address); 76187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 76287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 76387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 76487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA | 76587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick dev_addr); 76687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 76787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 76887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 76987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (read) 77087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data); 77187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick else 77287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data); 77387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 77487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 77587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 77687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick /* Recalibrate the device back to 0 */ 77787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0); 77887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 77987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 78087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 78187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 78287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick} 78387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 78487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/** 78587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * igb_read_xmdio_reg - Read XMDIO register 78687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @hw: pointer to the HW structure 78787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @addr: XMDIO address to program 78887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @dev_addr: device address to program 78987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @data: value to be read from the EMI address 79087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/ 79187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data) 79287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{ 79387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true); 79487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick} 79587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 79687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/** 79787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * igb_write_xmdio_reg - Write XMDIO register 79887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @hw: pointer to the HW structure 79987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @addr: XMDIO address to program 80087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @dev_addr: device address to program 80187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @data: value to be written to the XMDIO address 80287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/ 80387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) 80487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{ 80587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false); 80687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick} 8075a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny 8085a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny/** 8095a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny * igb_init_nvm_params_i210 - Init NVM func ptrs. 8105a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny * @hw: pointer to the HW structure 8115a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny **/ 8125a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wybornys32 igb_init_nvm_params_i210(struct e1000_hw *hw) 8135a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny{ 8145a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny s32 ret_val = 0; 8155a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny struct e1000_nvm_info *nvm = &hw->nvm; 8165a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny 8175a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.acquire = igb_acquire_nvm_i210; 8185a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.release = igb_release_nvm_i210; 8195a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.valid_led_default = igb_valid_led_default_i210; 8205a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny 8215a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny /* NVM Function Pointers */ 8225a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny if (igb_get_flash_presence_i210(hw)) { 8235a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny hw->nvm.type = e1000_nvm_flash_hw; 8245a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.read = igb_read_nvm_srrd_i210; 8255a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.write = igb_write_nvm_srwr_i210; 8265a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.validate = igb_validate_nvm_checksum_i210; 8275a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.update = igb_update_nvm_checksum_i210; 8285a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny } else { 8295a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny hw->nvm.type = e1000_nvm_invm; 830ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny nvm->ops.read = igb_read_invm_i210; 8315a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.write = NULL; 8325a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.validate = NULL; 8335a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny nvm->ops.update = NULL; 8345a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny } 8355a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny return ret_val; 8365a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny} 837948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 838948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka/** 839948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * igb_pll_workaround_i210 840948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * @hw: pointer to the HW structure 841948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * 842948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * Works around an errata in the PLL circuit where it occasionally 843948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * provides the wrong clock frequency after power up. 844948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka **/ 845948264879b6894dc389a44b99fae4f0b72932619Todd Fujinakas32 igb_pll_workaround_i210(struct e1000_hw *hw) 846948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka{ 847948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka s32 ret_val; 848948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val; 849948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka u16 nvm_word, phy_word, pci_word, tmp_nvm; 850948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka int i; 851948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 852948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka /* Get and set needed register values */ 853948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wuc = rd32(E1000_WUC); 854948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka mdicnfg = rd32(E1000_MDICNFG); 855948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO; 856948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_MDICNFG, reg_val); 857948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 858948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka /* Get data from NVM, or set default */ 859948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka ret_val = igb_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD, 860948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka &nvm_word); 861948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka if (ret_val) 862948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka nvm_word = E1000_INVM_DEFAULT_AL; 863948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL; 864948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka for (i = 0; i < E1000_MAX_PLL_TRIES; i++) { 865948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka /* check current state directly from internal PHY */ 866948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka igb_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE | 867948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka E1000_PHY_PLL_FREQ_REG), &phy_word); 868948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka if ((phy_word & E1000_PHY_PLL_UNCONF) 869948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka != E1000_PHY_PLL_UNCONF) { 870948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka ret_val = 0; 871948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka break; 872948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka } else { 873948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka ret_val = -E1000_ERR_PHY; 874948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka } 875948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka /* directly reset the internal PHY */ 876948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka ctrl = rd32(E1000_CTRL); 877948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_CTRL, ctrl|E1000_CTRL_PHY_RST); 878948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 879948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka ctrl_ext = rd32(E1000_CTRL_EXT); 880948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE); 881948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_CTRL_EXT, ctrl_ext); 882948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 883948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_WUC, 0); 884948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16); 885948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_EEARBC_I210, reg_val); 886948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 887948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka igb_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); 888948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka pci_word |= E1000_PCI_PMCSR_D3; 889948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); 890948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka usleep_range(1000, 2000); 891948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka pci_word &= ~E1000_PCI_PMCSR_D3; 892948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); 893948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16); 894948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_EEARBC_I210, reg_val); 895948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka 896948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka /* restore WUC register */ 897948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_WUC, wuc); 898948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka } 899948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka /* restore MDICNFG setting */ 900948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka wr32(E1000_MDICNFG, mdicnfg); 901948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka return ret_val; 902948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka} 903