e1000_i210.c revision 87371b9de5becc32af2f9be84008b8a8a424c58a
1f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/******************************************************************************* 2f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 3f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny Intel(R) Gigabit Ethernet Linux driver 44b9ea4626b52c113c367c4776c9bb11b7231393dAkeem G. Abodunrin Copyright(c) 2007-2013 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 387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 397916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_get_hw_semaphore_i210 - Acquire hardware semaphore 407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 427916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * Acquire the HW semaphore to access the PHY or NVM 437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */ 447916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) 457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u32 swsm; 477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 timeout = hw->nvm.word_size + 1; 497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 i = 0; 507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 517916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* Get the FW semaphore. */ 527916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny for (i = 0; i < timeout; i++) { 537916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny swsm = rd32(E1000_SWSM); 547916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); 557916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 567916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* Semaphore acquired if bit latched */ 577916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) 587916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny break; 597916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 607916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny udelay(50); 617916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 627916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 637916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (i == timeout) { 647916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* Release semaphores */ 657916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny igb_put_hw_semaphore(hw); 667916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny hw_dbg("Driver can't access the NVM\n"); 677916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny ret_val = -E1000_ERR_NVM; 687916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny goto out; 697916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 707916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 717916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornyout: 727916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny return ret_val; 737916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 74f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 75f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 76f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_acquire_nvm_i210 - Request for access to EEPROM 77f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 78f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 79f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the necessary semaphores for exclusive access to the EEPROM. 80f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Set the EEPROM access request bit and wait for EEPROM access grant bit. 81f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Return successful if access grant bit set, else clear the request for 82f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * EEPROM access and return -E1000_ERR_NVM (-1). 83f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 84f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_nvm_i210(struct e1000_hw *hw) 85f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 86f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 87f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 88f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 89f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 90f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_release_nvm_i210 - Release exclusive access to EEPROM 91f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 92f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 93f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Stop any current commands to the EEPROM and clear the EEPROM request bit, 94f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * then release the semaphores acquired. 95f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 96f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_nvm_i210(struct e1000_hw *hw) 97f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 98f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 99f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 100f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 101f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 1027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_put_hw_semaphore_i210 - Release hardware semaphore 1037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 1047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 1057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * Release hardware semaphore used to access the PHY or NVM 106b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/ 1077916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic void igb_put_hw_semaphore_i210(struct e1000_hw *hw) 1087916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 1097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u32 swsm; 1107916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 1117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny swsm = rd32(E1000_SWSM); 1127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 1137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny swsm &= ~E1000_SWSM_SWESMBI; 1147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 1157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny wr32(E1000_SWSM, swsm); 1167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 1177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 1187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 119f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore 120f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 121f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @mask: specifies which semaphore to acquire 122f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 123f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 124f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * will also specify which port we're acquiring the lock for. 125f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 126f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 127f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 128f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swfw_sync; 129f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swmask = mask; 130f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 fwmask = mask << 16; 131f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 132f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ 133f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 134f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny while (i < timeout) { 135f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (igb_get_hw_semaphore_i210(hw)) { 136f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 137f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 138f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 139f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 140f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync = rd32(E1000_SW_FW_SYNC); 141f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (!(swfw_sync & fwmask)) 142f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 143f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 144b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Firmware currently using resource (fwmask) */ 145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore_i210(hw); 146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny mdelay(5); 147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i++; 148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (i == timeout) { 151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); 152f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 155f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 156f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync |= swmask; 157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SW_FW_SYNC, swfw_sync); 158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore_i210(hw); 160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_release_swfw_sync_i210 - Release SW/FW semaphore 166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @mask: specifies which semaphore to acquire 168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Release the SW/FW semaphore used to access the PHY or NVM. The mask 170f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * will also specify which port we're releasing the lock for. 171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 swfw_sync; 175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS) 177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ; /* Empty */ 178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync = rd32(E1000_SW_FW_SYNC); 180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny swfw_sync &= ~mask; 181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SW_FW_SYNC, swfw_sync); 182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_put_hw_semaphore_i210(hw); 184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 187f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register 188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset of word in the Shadow Ram to read 190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to read 191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: word read from the Shadow Ram 192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Reads a 16 bit word from the Shadow Ram using the EERD register. 194f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Uses necessary synchronization semaphores. 195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, 197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = E1000_SUCCESS; 200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, count; 201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* We cannot hold synchronization semaphores for too long, 203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because of forceful takeover procedure. However it is more efficient 204b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher * to read in bursts than synchronizing access for each word. 205b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher */ 206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 207f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 208f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_EERD_EEWR_MAX_COUNT : (words - i); 209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 210f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_read_nvm_eerd(hw, offset, count, 211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny data + i); 212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 215f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 216f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (status != E1000_SUCCESS) 218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 220f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_write_nvm_srwr - Write to Shadow Ram using EEWR 226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @offset: offset within the Shadow Ram to be written to 228f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @words: number of words to write 229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: 16 bit word(s) to be written to the Shadow Ram 230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Writes data to Shadow Ram at offset using EEWR register. 232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * If igb_update_nvm_checksum is not called after this function , the 234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Shadow Ram will most likely contain an invalid checksum. 235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny struct e1000_nvm_info *nvm = &hw->nvm; 240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 i, k, eewr = 0; 241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 attempts = 100000; 242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 244b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* A check for invalid values: offset too large, too many words, 245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * too many words for the offset, and not enough words. 246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny (words == 0)) { 249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("nvm parameter(s) out of bounds\n"); 250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_NVM; 251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 253f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < words; i++) { 255f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | 256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny (data[i] << E1000_NVM_RW_REG_DATA) | 257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny E1000_NVM_RW_REG_START; 258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_SRWR, eewr); 260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (k = 0; k < attempts; k++) { 262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (E1000_NVM_RW_REG_DONE & 263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny rd32(E1000_SRWR)) { 264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = E1000_SUCCESS; 265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny udelay(5); 268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) { 271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Shadow RAM write EEWR timed out\n"); 272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 275f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 2817916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR 2827916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 2837916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @offset: offset within the Shadow RAM to be written to 2847916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @words: number of words to write 2857916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @data: 16 bit word(s) to be written to the Shadow RAM 2867916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 2877916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * Writes data to Shadow RAM at offset using EEWR register. 2887916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 2897916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * If e1000_update_nvm_checksum is not called after this function , the 2907916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * data will not be committed to FLASH and also Shadow RAM will most likely 2917916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * contain an invalid checksum. 2927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 2937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * If error code is returned, data and Shadow RAM may be inconsistent - buffer 2947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * partially written. 295b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/ 2967916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornys32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, 2977916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u16 *data) 2987916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 2997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 status = E1000_SUCCESS; 3007916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u16 i, count; 3017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny /* We cannot hold synchronization semaphores for too long, 3037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * because of forceful takeover procedure. However it is more efficient 3047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * to write in bursts than synchronizing access for each word. 3057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */ 3067916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 3077916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 3087916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny E1000_EERD_EEWR_MAX_COUNT : (words - i); 3097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 3107916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny status = igb_write_nvm_srwr(hw, offset, count, 3117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny data + i); 3127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny hw->nvm.ops.release(hw); 3137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } else { 3147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 3157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 3167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (status != E1000_SUCCESS) 3187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny break; 3197916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 3207916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3217916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny return status; 3227916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 3237916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 3247916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 325f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_nvm_i211 - Read NVM wrapper function for I211 326f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 3275c17a203721d72c36798e5d7fa564e1adf8beb65Akeem G. Abodunrin * @words: number of words to read 328f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the data read 329f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 330f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Wrapper function to return data formerly found in the NVM. 331f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 332f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, 333f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 *data) 334f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 335f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 336f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 337f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Only the MAC addr is required to be present in the iNVM */ 338f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny switch (offset) { 339f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_MAC_ADDR: 340f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_invm_i211(hw, offset, &data[0]); 341f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]); 342f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]); 343f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) 344f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("MAC Addr not found in iNVM\n"); 345f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 346f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_INIT_CTRL_2: 3471720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = igb_read_invm_i211(hw, (u8)offset, data); 3481720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny if (ret_val != E1000_SUCCESS) { 3491720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_INIT_CTRL_2_DEFAULT_I211; 3501720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = E1000_SUCCESS; 3511720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 3521720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny break; 353f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_INIT_CTRL_4: 3541720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = igb_read_invm_i211(hw, (u8)offset, data); 3551720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny if (ret_val != E1000_SUCCESS) { 3561720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_INIT_CTRL_4_DEFAULT_I211; 3571720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = E1000_SUCCESS; 3581720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 3591720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny break; 360f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_LED_1_CFG: 3611720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = igb_read_invm_i211(hw, (u8)offset, data); 3621720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny if (ret_val != E1000_SUCCESS) { 3631720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_LED_1_CFG_DEFAULT_I211; 3641720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = E1000_SUCCESS; 3651720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 3661720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny break; 367f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_LED_0_2_CFG: 368f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny igb_read_invm_i211(hw, offset, data); 3691720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny if (ret_val != E1000_SUCCESS) { 3701720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = NVM_LED_0_2_CFG_DEFAULT_I211; 3711720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = E1000_SUCCESS; 3721720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 373f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 3741720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny case NVM_ID_LED_SETTINGS: 3751720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = igb_read_invm_i211(hw, (u8)offset, data); 3761720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny if (ret_val != E1000_SUCCESS) { 3771720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny *data = ID_LED_RESERVED_FFFF; 3781720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny ret_val = E1000_SUCCESS; 3791720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny } 380f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_SUB_DEV_ID: 381f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->subsystem_device_id; 382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_SUB_VEN_ID: 384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->subsystem_vendor_id; 385f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 386f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_DEV_ID: 387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->device_id; 388f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case NVM_VEN_ID: 390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = hw->vendor_id; 391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny default: 393f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM word 0x%02x is not mapped.\n", offset); 394f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = NVM_RESERVED_WORD; 395f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 396f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 397f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 398f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_read_invm_i211 - Reads OTP 402f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 403f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @address: the word address (aka eeprom offset) to read 404f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the data read 405f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 406f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Reads 16-bit words from the OTP. Return error when the word is not 407f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * stored in OTP. 408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 409f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data) 410f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 411f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 412f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 invm_dword; 413f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i; 414f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u8 record_type, word_address; 415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 416f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < E1000_INVM_SIZE; i++) { 417f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny invm_dword = rd32(E1000_INVM_DATA_REG(i)); 418f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Get record type */ 419f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); 420f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) 421f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) 423f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; 424f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) 425f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; 426f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { 427f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); 428f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (word_address == (u8)address) { 429f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = INVM_DWORD_TO_WORD_DATA(invm_dword); 430f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Read INVM Word 0x%02x = %x", 431f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny address, *data); 432f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_SUCCESS; 433f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 434f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 435f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 436f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 437f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (status != E1000_SUCCESS) 438f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Requested word 0x%02x not found in OTP\n", address); 439f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 440f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 441f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 442f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 44309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * igb_read_invm_version - Reads iNVM version and image type 44409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * @hw: pointer to the HW structure 44509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * @invm_ver: version structure for the version read 44609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * 44709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * Reads iNVM version and image type. 44809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/ 44909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw, 45009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny struct e1000_fw_version *invm_ver) { 45109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 *record = NULL; 45209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 *next_record = NULL; 45309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 i = 0; 45409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 invm_dword = 0; 45509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / 45609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny E1000_INVM_RECORD_SIZE_IN_BYTES); 45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u32 buffer[E1000_INVM_SIZE]; 45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny u16 version = 0; 46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read iNVM memory */ 46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 0; i < E1000_INVM_SIZE; i++) { 46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_dword = rd32(E1000_INVM_DATA_REG(i)); 46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny buffer[i] = invm_dword; 46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read version number */ 46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 1; i < invm_blocks; i++) { 46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny record = &buffer[invm_blocks - i]; 47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny next_record = &buffer[invm_blocks - i + 1]; 47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have first version location used */ 47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { 47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = 0; 47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have second version location used */ 47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((i == 1) && 48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { 48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; 48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have odd version location 48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * used and it is the last one used 48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny */ 48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && 48909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && 49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny (i != 1))) { 49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*next_record & E1000_INVM_VER_FIELD_TWO) 49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny >> 13; 49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 49609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have even version location 49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny * used and it is the last one used 49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny */ 49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && 50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & 0x3) == 0)) { 50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; 50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 50709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if (status == E1000_SUCCESS) { 50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) 50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny >> E1000_INVM_MAJOR_SHIFT; 51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; 51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Read Image Type */ 51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny for (i = 1; i < invm_blocks; i++) { 51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny record = &buffer[invm_blocks - i]; 51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny next_record = &buffer[invm_blocks - i + 1]; 51609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have image type in first location used */ 51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { 51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_img_type = 0; 52009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 52109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 52209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 52309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny /* Check if we have image type in first location used */ 52409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny else if ((((*record & 0x3) == 0) && 52509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || 52609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny ((((*record & 0x3) != 0) && (i != 1)))) { 52709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny invm_ver->invm_img_type = 52809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; 52909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny status = E1000_SUCCESS; 53009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny break; 53109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 53209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny } 53309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny return status; 53409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny} 53509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny 53609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/** 537f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_validate_nvm_checksum_i210 - Validate EEPROM checksum 538f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 539f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 540f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 541f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * and then verifies that the sum of the EEPROM is equal to 0xBABA. 542f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 543f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw) 544f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 545f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 status = E1000_SUCCESS; 546f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); 547f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 548f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 549f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 550b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Replace the read function with semaphore grabbing with 551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * the one that skips this for a while. 552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * We have semaphore taken already here. 553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny read_op_ptr = hw->nvm.ops.read; 555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.read = igb_read_nvm_eerd; 556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 557f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = igb_validate_nvm_checksum(hw); 558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 559f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny /* Revert original read operation. */ 560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.read = read_op_ptr; 561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 562f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 564f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny status = E1000_ERR_SWFW_SYNC; 565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return status; 568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_update_nvm_checksum_i210 - Update EEPROM checksum 572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Updates the EEPROM checksum by reading/adding each word of the EEPROM 575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * up to the checksum. Then calculates the EEPROM checksum and writes the 576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * value to the EEPROM. Next commit EEPROM data onto the Flash. 577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_nvm_checksum_i210(struct e1000_hw *hw) 579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 checksum = 0; 582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u16 i, nvm_data; 583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 584b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Read the first word from the EEPROM. If this times out or fails, do 585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * not continue or we could be in for a very long wait while every 586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * EEPROM read fails 587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data); 589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) { 590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("EEPROM read failed\n"); 591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 592f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 594f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 595b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher /* Do not use hw->nvm.ops.write, hw->nvm.ops.read 596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * because we do not want to take the synchronization 597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * semaphores twice here. 598f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */ 599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny for (i = 0; i < NVM_CHECKSUM_REG; i++) { 601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data); 602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val) { 603f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Read Error while updating checksum.\n"); 605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny checksum += nvm_data; 608f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 609f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny checksum = (u16) NVM_SUM - checksum; 610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, 611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny &checksum); 612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val != E1000_SUCCESS) { 613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Write Error while updating checksum.\n"); 615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw->nvm.ops.release(hw); 619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_update_flash_i210(hw); 621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } else { 622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = -E1000_ERR_SWFW_SYNC; 623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 626f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 6297916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_pool_flash_update_done_i210 - Pool FLUDONE status. 6307916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * @hw: pointer to the HW structure 6317916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * 632b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/ 6337916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) 6347916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{ 6357916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny s32 ret_val = -E1000_ERR_NVM; 6367916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny u32 i, reg; 6377916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 6387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { 6397916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny reg = rd32(E1000_EECD); 6407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny if (reg & E1000_EECD_FLUDONE_I210) { 6417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny ret_val = E1000_SUCCESS; 6427916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny break; 6437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 6447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny udelay(5); 6457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny } 6467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 6477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny return ret_val; 6487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny} 6497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny 6507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/** 651f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_update_flash_i210 - Commit EEPROM to the flash 652f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 653f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 654f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 655f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_flash_i210(struct e1000_hw *hw) 656f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 657f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val = E1000_SUCCESS; 658f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny u32 flup; 659f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 660f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_pool_flash_update_done_i210(hw); 661f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val == -E1000_ERR_NVM) { 662f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update time out\n"); 663f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 664f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 665f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 666f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210; 667f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny wr32(E1000_EECD, flup); 668f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 669f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = igb_pool_flash_update_done_i210(hw); 670f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val == E1000_SUCCESS) 671f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update complete\n"); 672f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny else 673f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("Flash update time out\n"); 674f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 675f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 676f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 677f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 678f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 679f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/** 680f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * igb_valid_led_default_i210 - Verify a valid default LED config 681f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @hw: pointer to the HW structure 682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * @data: pointer to the NVM (EEPROM) 683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * 684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * Read the EEPROM for the current default LED configuration. If the 685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * LED configuration is not valid, set to a valid LED configuration. 686f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/ 687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data) 688f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{ 689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny s32 ret_val; 690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (ret_val) { 693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny hw_dbg("NVM Read Error\n"); 694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny goto out; 695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny 697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 698f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny switch (hw->phy.media_type) { 699f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case e1000_media_type_internal_serdes: 700f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210_SERDES; 701f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 702f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny case e1000_media_type_copper: 703f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny default: 704f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *data = ID_LED_DEFAULT_I210; 705f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny break; 706f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 707f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny } 708f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout: 709f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny return ret_val; 710f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny} 71187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 71287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/** 71387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * __igb_access_xmdio_reg - Read/write XMDIO register 71487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @hw: pointer to the HW structure 71587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @address: XMDIO address to program 71687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @dev_addr: device address to program 71787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @data: pointer to value to read/write from/to the XMDIO address 71887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @read: boolean flag to indicate read or write 71987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/ 72087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vickstatic s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address, 72187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick u8 dev_addr, u16 *data, bool read) 72287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{ 72387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick s32 ret_val = E1000_SUCCESS; 72487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 72587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr); 72687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 72787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 72887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 72987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address); 73087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 73187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 73287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 73387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA | 73487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick dev_addr); 73587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 73687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 73787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 73887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (read) 73987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data); 74087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick else 74187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data); 74287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 74387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 74487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 74587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick /* Recalibrate the device back to 0 */ 74687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0); 74787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick if (ret_val) 74887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 74987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 75087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return ret_val; 75187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick} 75287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 75387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/** 75487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * igb_read_xmdio_reg - Read XMDIO register 75587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @hw: pointer to the HW structure 75687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @addr: XMDIO address to program 75787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @dev_addr: device address to program 75887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @data: value to be read from the EMI address 75987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/ 76087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data) 76187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{ 76287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true); 76387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick} 76487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick 76587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/** 76687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * igb_write_xmdio_reg - Write XMDIO register 76787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @hw: pointer to the HW structure 76887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @addr: XMDIO address to program 76987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @dev_addr: device address to program 77087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick * @data: value to be written to the XMDIO address 77187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/ 77287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) 77387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{ 77487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false); 77587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick} 776