e1000_i210.c revision 238148
1238148Sjfv/****************************************************************************** 2238148Sjfv 3238148Sjfv Copyright (c) 2001-2012, Intel Corporation 4238148Sjfv All rights reserved. 5238148Sjfv 6238148Sjfv Redistribution and use in source and binary forms, with or without 7238148Sjfv modification, are permitted provided that the following conditions are met: 8238148Sjfv 9238148Sjfv 1. Redistributions of source code must retain the above copyright notice, 10238148Sjfv this list of conditions and the following disclaimer. 11238148Sjfv 12238148Sjfv 2. Redistributions in binary form must reproduce the above copyright 13238148Sjfv notice, this list of conditions and the following disclaimer in the 14238148Sjfv documentation and/or other materials provided with the distribution. 15238148Sjfv 16238148Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17238148Sjfv contributors may be used to endorse or promote products derived from 18238148Sjfv this software without specific prior written permission. 19238148Sjfv 20238148Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21238148Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22238148Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23238148Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24238148Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25238148Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26238148Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27238148Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28238148Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29238148Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30238148Sjfv POSSIBILITY OF SUCH DAMAGE. 31238148Sjfv 32238148Sjfv******************************************************************************/ 33238148Sjfv/*$FreeBSD: head/sys/dev/e1000/e1000_i210.c 238148 2012-07-05 20:26:57Z jfv $*/ 34238148Sjfv 35238148Sjfv#include "e1000_api.h" 36238148Sjfv 37238148Sjfv 38238148Sjfvstatic s32 e1000_acquire_nvm_i210(struct e1000_hw *hw); 39238148Sjfvstatic void e1000_release_nvm_i210(struct e1000_hw *hw); 40238148Sjfvstatic s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw); 41238148Sjfvstatic void e1000_put_hw_semaphore_i210(struct e1000_hw *hw); 42238148Sjfvstatic s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 43238148Sjfv u16 *data); 44238148Sjfvstatic s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw); 45238148Sjfvstatic s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data); 46238148Sjfvstatic s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, 47238148Sjfv u16 *data); 48238148Sjfv 49238148Sjfv/** 50238148Sjfv * e1000_acquire_nvm_i210 - Request for access to EEPROM 51238148Sjfv * @hw: pointer to the HW structure 52238148Sjfv * 53238148Sjfv * Acquire the necessary semaphores for exclusive access to the EEPROM. 54238148Sjfv * Set the EEPROM access request bit and wait for EEPROM access grant bit. 55238148Sjfv * Return successful if access grant bit set, else clear the request for 56238148Sjfv * EEPROM access and return -E1000_ERR_NVM (-1). 57238148Sjfv **/ 58238148Sjfvstatic s32 e1000_acquire_nvm_i210(struct e1000_hw *hw) 59238148Sjfv{ 60238148Sjfv s32 ret_val; 61238148Sjfv 62238148Sjfv DEBUGFUNC("e1000_acquire_nvm_i210"); 63238148Sjfv 64238148Sjfv ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 65238148Sjfv 66238148Sjfv return ret_val; 67238148Sjfv} 68238148Sjfv 69238148Sjfv/** 70238148Sjfv * e1000_release_nvm_i210 - Release exclusive access to EEPROM 71238148Sjfv * @hw: pointer to the HW structure 72238148Sjfv * 73238148Sjfv * Stop any current commands to the EEPROM and clear the EEPROM request bit, 74238148Sjfv * then release the semaphores acquired. 75238148Sjfv **/ 76238148Sjfvstatic void e1000_release_nvm_i210(struct e1000_hw *hw) 77238148Sjfv{ 78238148Sjfv DEBUGFUNC("e1000_release_nvm_i210"); 79238148Sjfv 80238148Sjfv e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); 81238148Sjfv} 82238148Sjfv 83238148Sjfv/** 84238148Sjfv * e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore 85238148Sjfv * @hw: pointer to the HW structure 86238148Sjfv * @mask: specifies which semaphore to acquire 87238148Sjfv * 88238148Sjfv * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 89238148Sjfv * will also specify which port we're acquiring the lock for. 90238148Sjfv **/ 91238148Sjfvs32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 92238148Sjfv{ 93238148Sjfv u32 swfw_sync; 94238148Sjfv u32 swmask = mask; 95238148Sjfv u32 fwmask = mask << 16; 96238148Sjfv s32 ret_val = E1000_SUCCESS; 97238148Sjfv s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ 98238148Sjfv 99238148Sjfv DEBUGFUNC("e1000_acquire_swfw_sync_i210"); 100238148Sjfv 101238148Sjfv while (i < timeout) { 102238148Sjfv if (e1000_get_hw_semaphore_i210(hw)) { 103238148Sjfv ret_val = -E1000_ERR_SWFW_SYNC; 104238148Sjfv goto out; 105238148Sjfv } 106238148Sjfv 107238148Sjfv swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 108238148Sjfv if (!(swfw_sync & fwmask)) 109238148Sjfv break; 110238148Sjfv 111238148Sjfv /* 112238148Sjfv * Firmware currently using resource (fwmask) 113238148Sjfv */ 114238148Sjfv e1000_put_hw_semaphore_i210(hw); 115238148Sjfv msec_delay_irq(5); 116238148Sjfv i++; 117238148Sjfv } 118238148Sjfv 119238148Sjfv if (i == timeout) { 120238148Sjfv DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); 121238148Sjfv ret_val = -E1000_ERR_SWFW_SYNC; 122238148Sjfv goto out; 123238148Sjfv } 124238148Sjfv 125238148Sjfv swfw_sync |= swmask; 126238148Sjfv E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 127238148Sjfv 128238148Sjfv e1000_put_hw_semaphore_i210(hw); 129238148Sjfv 130238148Sjfvout: 131238148Sjfv return ret_val; 132238148Sjfv} 133238148Sjfv 134238148Sjfv/** 135238148Sjfv * e1000_release_swfw_sync_i210 - Release SW/FW semaphore 136238148Sjfv * @hw: pointer to the HW structure 137238148Sjfv * @mask: specifies which semaphore to acquire 138238148Sjfv * 139238148Sjfv * Release the SW/FW semaphore used to access the PHY or NVM. The mask 140238148Sjfv * will also specify which port we're releasing the lock for. 141238148Sjfv **/ 142238148Sjfvvoid e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) 143238148Sjfv{ 144238148Sjfv u32 swfw_sync; 145238148Sjfv 146238148Sjfv DEBUGFUNC("e1000_release_swfw_sync_i210"); 147238148Sjfv 148238148Sjfv while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS) 149238148Sjfv ; /* Empty */ 150238148Sjfv 151238148Sjfv swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 152238148Sjfv swfw_sync &= ~mask; 153238148Sjfv E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 154238148Sjfv 155238148Sjfv e1000_put_hw_semaphore_i210(hw); 156238148Sjfv} 157238148Sjfv 158238148Sjfv/** 159238148Sjfv * e1000_get_hw_semaphore_i210 - Acquire hardware semaphore 160238148Sjfv * @hw: pointer to the HW structure 161238148Sjfv * 162238148Sjfv * Acquire the HW semaphore to access the PHY or NVM 163238148Sjfv **/ 164238148Sjfvstatic s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) 165238148Sjfv{ 166238148Sjfv u32 swsm; 167238148Sjfv s32 ret_val = E1000_SUCCESS; 168238148Sjfv s32 timeout = hw->nvm.word_size + 1; 169238148Sjfv s32 i = 0; 170238148Sjfv 171238148Sjfv DEBUGFUNC("e1000_get_hw_semaphore_i210"); 172238148Sjfv 173238148Sjfv /* Get the FW semaphore. */ 174238148Sjfv for (i = 0; i < timeout; i++) { 175238148Sjfv swsm = E1000_READ_REG(hw, E1000_SWSM); 176238148Sjfv E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); 177238148Sjfv 178238148Sjfv /* Semaphore acquired if bit latched */ 179238148Sjfv if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) 180238148Sjfv break; 181238148Sjfv 182238148Sjfv usec_delay(50); 183238148Sjfv } 184238148Sjfv 185238148Sjfv if (i == timeout) { 186238148Sjfv /* Release semaphores */ 187238148Sjfv e1000_put_hw_semaphore_generic(hw); 188238148Sjfv DEBUGOUT("Driver can't access the NVM\n"); 189238148Sjfv ret_val = -E1000_ERR_NVM; 190238148Sjfv goto out; 191238148Sjfv } 192238148Sjfv 193238148Sjfvout: 194238148Sjfv return ret_val; 195238148Sjfv} 196238148Sjfv 197238148Sjfv/** 198238148Sjfv * e1000_put_hw_semaphore_i210 - Release hardware semaphore 199238148Sjfv * @hw: pointer to the HW structure 200238148Sjfv * 201238148Sjfv * Release hardware semaphore used to access the PHY or NVM 202238148Sjfv **/ 203238148Sjfvstatic void e1000_put_hw_semaphore_i210(struct e1000_hw *hw) 204238148Sjfv{ 205238148Sjfv u32 swsm; 206238148Sjfv 207238148Sjfv DEBUGFUNC("e1000_put_hw_semaphore_i210"); 208238148Sjfv 209238148Sjfv swsm = E1000_READ_REG(hw, E1000_SWSM); 210238148Sjfv 211238148Sjfv swsm &= ~E1000_SWSM_SWESMBI; 212238148Sjfv 213238148Sjfv E1000_WRITE_REG(hw, E1000_SWSM, swsm); 214238148Sjfv} 215238148Sjfv 216238148Sjfv/** 217238148Sjfv * e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register 218238148Sjfv * @hw: pointer to the HW structure 219238148Sjfv * @offset: offset of word in the Shadow Ram to read 220238148Sjfv * @words: number of words to read 221238148Sjfv * @data: word read from the Shadow Ram 222238148Sjfv * 223238148Sjfv * Reads a 16 bit word from the Shadow Ram using the EERD register. 224238148Sjfv * Uses necessary synchronization semaphores. 225238148Sjfv **/ 226238148Sjfvs32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, 227238148Sjfv u16 *data) 228238148Sjfv{ 229238148Sjfv s32 status = E1000_SUCCESS; 230238148Sjfv u16 i, count; 231238148Sjfv 232238148Sjfv DEBUGFUNC("e1000_read_nvm_srrd_i210"); 233238148Sjfv 234238148Sjfv /* We cannot hold synchronization semaphores for too long, 235238148Sjfv * because of forceful takeover procedure. However it is more efficient 236238148Sjfv * to read in bursts than synchronizing access for each word. */ 237238148Sjfv for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 238238148Sjfv count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 239238148Sjfv E1000_EERD_EEWR_MAX_COUNT : (words - i); 240238148Sjfv if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 241238148Sjfv status = e1000_read_nvm_eerd(hw, offset, count, 242238148Sjfv data + i); 243238148Sjfv hw->nvm.ops.release(hw); 244238148Sjfv } else { 245238148Sjfv status = E1000_ERR_SWFW_SYNC; 246238148Sjfv } 247238148Sjfv 248238148Sjfv if (status != E1000_SUCCESS) 249238148Sjfv break; 250238148Sjfv } 251238148Sjfv 252238148Sjfv return status; 253238148Sjfv} 254238148Sjfv 255238148Sjfv/** 256238148Sjfv * e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR 257238148Sjfv * @hw: pointer to the HW structure 258238148Sjfv * @offset: offset within the Shadow RAM to be written to 259238148Sjfv * @words: number of words to write 260238148Sjfv * @data: 16 bit word(s) to be written to the Shadow RAM 261238148Sjfv * 262238148Sjfv * Writes data to Shadow RAM at offset using EEWR register. 263238148Sjfv * 264238148Sjfv * If e1000_update_nvm_checksum is not called after this function , the 265238148Sjfv * data will not be committed to FLASH and also Shadow RAM will most likely 266238148Sjfv * contain an invalid checksum. 267238148Sjfv * 268238148Sjfv * If error code is returned, data and Shadow RAM may be inconsistent - buffer 269238148Sjfv * partially written. 270238148Sjfv **/ 271238148Sjfvs32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, 272238148Sjfv u16 *data) 273238148Sjfv{ 274238148Sjfv s32 status = E1000_SUCCESS; 275238148Sjfv u16 i, count; 276238148Sjfv 277238148Sjfv DEBUGFUNC("e1000_write_nvm_srwr_i210"); 278238148Sjfv 279238148Sjfv /* We cannot hold synchronization semaphores for too long, 280238148Sjfv * because of forceful takeover procedure. However it is more efficient 281238148Sjfv * to write in bursts than synchronizing access for each word. */ 282238148Sjfv for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { 283238148Sjfv count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? 284238148Sjfv E1000_EERD_EEWR_MAX_COUNT : (words - i); 285238148Sjfv if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 286238148Sjfv status = e1000_write_nvm_srwr(hw, offset, count, 287238148Sjfv data + i); 288238148Sjfv hw->nvm.ops.release(hw); 289238148Sjfv } else { 290238148Sjfv status = E1000_ERR_SWFW_SYNC; 291238148Sjfv } 292238148Sjfv 293238148Sjfv if (status != E1000_SUCCESS) 294238148Sjfv break; 295238148Sjfv } 296238148Sjfv 297238148Sjfv return status; 298238148Sjfv} 299238148Sjfv 300238148Sjfv/** 301238148Sjfv * e1000_write_nvm_srwr - Write to Shadow Ram using EEWR 302238148Sjfv * @hw: pointer to the HW structure 303238148Sjfv * @offset: offset within the Shadow Ram to be written to 304238148Sjfv * @words: number of words to write 305238148Sjfv * @data: 16 bit word(s) to be written to the Shadow Ram 306238148Sjfv * 307238148Sjfv * Writes data to Shadow Ram at offset using EEWR register. 308238148Sjfv * 309238148Sjfv * If e1000_update_nvm_checksum is not called after this function , the 310238148Sjfv * Shadow Ram will most likely contain an invalid checksum. 311238148Sjfv **/ 312238148Sjfvstatic s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, 313238148Sjfv u16 *data) 314238148Sjfv{ 315238148Sjfv struct e1000_nvm_info *nvm = &hw->nvm; 316238148Sjfv u32 i, k, eewr = 0; 317238148Sjfv u32 attempts = 100000; 318238148Sjfv s32 ret_val = E1000_SUCCESS; 319238148Sjfv 320238148Sjfv DEBUGFUNC("e1000_write_nvm_srwr"); 321238148Sjfv 322238148Sjfv /* 323238148Sjfv * A check for invalid values: offset too large, too many words, 324238148Sjfv * too many words for the offset, and not enough words. 325238148Sjfv */ 326238148Sjfv if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 327238148Sjfv (words == 0)) { 328238148Sjfv DEBUGOUT("nvm parameter(s) out of bounds\n"); 329238148Sjfv ret_val = -E1000_ERR_NVM; 330238148Sjfv goto out; 331238148Sjfv } 332238148Sjfv 333238148Sjfv for (i = 0; i < words; i++) { 334238148Sjfv eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | 335238148Sjfv (data[i] << E1000_NVM_RW_REG_DATA) | 336238148Sjfv E1000_NVM_RW_REG_START; 337238148Sjfv 338238148Sjfv E1000_WRITE_REG(hw, E1000_SRWR, eewr); 339238148Sjfv 340238148Sjfv for (k = 0; k < attempts; k++) { 341238148Sjfv if (E1000_NVM_RW_REG_DONE & 342238148Sjfv E1000_READ_REG(hw, E1000_SRWR)) { 343238148Sjfv ret_val = E1000_SUCCESS; 344238148Sjfv break; 345238148Sjfv } 346238148Sjfv usec_delay(5); 347238148Sjfv } 348238148Sjfv 349238148Sjfv if (ret_val != E1000_SUCCESS) { 350238148Sjfv DEBUGOUT("Shadow RAM write EEWR timed out\n"); 351238148Sjfv break; 352238148Sjfv } 353238148Sjfv } 354238148Sjfv 355238148Sjfvout: 356238148Sjfv return ret_val; 357238148Sjfv} 358238148Sjfv 359238148Sjfv/** 360238148Sjfv * e1000_read_nvm_i211 - Read NVM wrapper function for I211 361238148Sjfv * @hw: pointer to the HW structure 362238148Sjfv * @address: the word address (aka eeprom offset) to read 363238148Sjfv * @data: pointer to the data read 364238148Sjfv * 365238148Sjfv * Wrapper function to return data formerly found in the NVM. 366238148Sjfv **/ 367238148Sjfvstatic s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, 368238148Sjfv u16 *data) 369238148Sjfv{ 370238148Sjfv s32 ret_val = E1000_SUCCESS; 371238148Sjfv 372238148Sjfv DEBUGFUNC("e1000_read_nvm_i211"); 373238148Sjfv 374238148Sjfv /* Only the MAC addr is required to be present in the iNVM */ 375238148Sjfv switch (offset) { 376238148Sjfv case NVM_MAC_ADDR: 377238148Sjfv ret_val = e1000_read_invm_i211(hw, (u8)offset, &data[0]); 378238148Sjfv ret_val |= e1000_read_invm_i211(hw, (u8)offset+1, &data[1]); 379238148Sjfv ret_val |= e1000_read_invm_i211(hw, (u8)offset+2, &data[2]); 380238148Sjfv if (ret_val != E1000_SUCCESS) 381238148Sjfv DEBUGOUT("MAC Addr not found in iNVM\n"); 382238148Sjfv break; 383238148Sjfv case NVM_ID_LED_SETTINGS: 384238148Sjfv case NVM_INIT_CTRL_2: 385238148Sjfv case NVM_INIT_CTRL_4: 386238148Sjfv case NVM_LED_1_CFG: 387238148Sjfv case NVM_LED_0_2_CFG: 388238148Sjfv e1000_read_invm_i211(hw, (u8)offset, data); 389238148Sjfv break; 390238148Sjfv case NVM_COMPAT: 391238148Sjfv *data = ID_LED_DEFAULT_I210; 392238148Sjfv break; 393238148Sjfv case NVM_SUB_DEV_ID: 394238148Sjfv *data = hw->subsystem_device_id; 395238148Sjfv break; 396238148Sjfv case NVM_SUB_VEN_ID: 397238148Sjfv *data = hw->subsystem_vendor_id; 398238148Sjfv break; 399238148Sjfv case NVM_DEV_ID: 400238148Sjfv *data = hw->device_id; 401238148Sjfv break; 402238148Sjfv case NVM_VEN_ID: 403238148Sjfv *data = hw->vendor_id; 404238148Sjfv break; 405238148Sjfv default: 406238148Sjfv DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset); 407238148Sjfv *data = NVM_RESERVED_WORD; 408238148Sjfv break; 409238148Sjfv } 410238148Sjfv return ret_val; 411238148Sjfv} 412238148Sjfv 413238148Sjfv/** 414238148Sjfv * e1000_read_invm_i211 - Reads OTP 415238148Sjfv * @hw: pointer to the HW structure 416238148Sjfv * @address: the word address (aka eeprom offset) to read 417238148Sjfv * @data: pointer to the data read 418238148Sjfv * 419238148Sjfv * Reads 16-bit words from the OTP. Return error when the word is not 420238148Sjfv * stored in OTP. 421238148Sjfv **/ 422238148Sjfvs32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data) 423238148Sjfv{ 424238148Sjfv s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; 425238148Sjfv u32 invm_dword; 426238148Sjfv u16 i; 427238148Sjfv u8 record_type, word_address; 428238148Sjfv 429238148Sjfv DEBUGFUNC("e1000_read_invm_i211"); 430238148Sjfv 431238148Sjfv for (i = 0; i < E1000_INVM_SIZE; i++) { 432238148Sjfv invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); 433238148Sjfv /* Get record type */ 434238148Sjfv record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); 435238148Sjfv if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) 436238148Sjfv break; 437238148Sjfv if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) 438238148Sjfv i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; 439238148Sjfv if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) 440238148Sjfv i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; 441238148Sjfv if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { 442238148Sjfv word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); 443238148Sjfv if (word_address == address) { 444238148Sjfv *data = INVM_DWORD_TO_WORD_DATA(invm_dword); 445238148Sjfv DEBUGOUT2("Read INVM Word 0x%02x = %x", 446238148Sjfv address, *data); 447238148Sjfv status = E1000_SUCCESS; 448238148Sjfv break; 449238148Sjfv } 450238148Sjfv } 451238148Sjfv } 452238148Sjfv if (status != E1000_SUCCESS) 453238148Sjfv DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address); 454238148Sjfv return status; 455238148Sjfv} 456238148Sjfv 457238148Sjfv/** 458238148Sjfv * e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum 459238148Sjfv * @hw: pointer to the HW structure 460238148Sjfv * 461238148Sjfv * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 462238148Sjfv * and then verifies that the sum of the EEPROM is equal to 0xBABA. 463238148Sjfv **/ 464238148Sjfvs32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw) 465238148Sjfv{ 466238148Sjfv s32 status = E1000_SUCCESS; 467238148Sjfv s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); 468238148Sjfv 469238148Sjfv DEBUGFUNC("e1000_validate_nvm_checksum_i210"); 470238148Sjfv 471238148Sjfv if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 472238148Sjfv 473238148Sjfv /* 474238148Sjfv * Replace the read function with semaphore grabbing with 475238148Sjfv * the one that skips this for a while. 476238148Sjfv * We have semaphore taken already here. 477238148Sjfv */ 478238148Sjfv read_op_ptr = hw->nvm.ops.read; 479238148Sjfv hw->nvm.ops.read = e1000_read_nvm_eerd; 480238148Sjfv 481238148Sjfv status = e1000_validate_nvm_checksum_generic(hw); 482238148Sjfv 483238148Sjfv /* Revert original read operation. */ 484238148Sjfv hw->nvm.ops.read = read_op_ptr; 485238148Sjfv 486238148Sjfv hw->nvm.ops.release(hw); 487238148Sjfv } else { 488238148Sjfv status = E1000_ERR_SWFW_SYNC; 489238148Sjfv } 490238148Sjfv 491238148Sjfv return status; 492238148Sjfv} 493238148Sjfv 494238148Sjfv 495238148Sjfv/** 496238148Sjfv * e1000_update_nvm_checksum_i210 - Update EEPROM checksum 497238148Sjfv * @hw: pointer to the HW structure 498238148Sjfv * 499238148Sjfv * Updates the EEPROM checksum by reading/adding each word of the EEPROM 500238148Sjfv * up to the checksum. Then calculates the EEPROM checksum and writes the 501238148Sjfv * value to the EEPROM. Next commit EEPROM data onto the Flash. 502238148Sjfv **/ 503238148Sjfvs32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw) 504238148Sjfv{ 505238148Sjfv s32 ret_val = E1000_SUCCESS; 506238148Sjfv u16 checksum = 0; 507238148Sjfv u16 i, nvm_data; 508238148Sjfv 509238148Sjfv DEBUGFUNC("e1000_update_nvm_checksum_i210"); 510238148Sjfv 511238148Sjfv /* 512238148Sjfv * Read the first word from the EEPROM. If this times out or fails, do 513238148Sjfv * not continue or we could be in for a very long wait while every 514238148Sjfv * EEPROM read fails 515238148Sjfv */ 516238148Sjfv ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data); 517238148Sjfv if (ret_val != E1000_SUCCESS) { 518238148Sjfv DEBUGOUT("EEPROM read failed\n"); 519238148Sjfv goto out; 520238148Sjfv } 521238148Sjfv 522238148Sjfv if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { 523238148Sjfv /* 524238148Sjfv * Do not use hw->nvm.ops.write, hw->nvm.ops.read 525238148Sjfv * because we do not want to take the synchronization 526238148Sjfv * semaphores twice here. 527238148Sjfv */ 528238148Sjfv 529238148Sjfv for (i = 0; i < NVM_CHECKSUM_REG; i++) { 530238148Sjfv ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data); 531238148Sjfv if (ret_val) { 532238148Sjfv hw->nvm.ops.release(hw); 533238148Sjfv DEBUGOUT("NVM Read Error while updating checksum.\n"); 534238148Sjfv goto out; 535238148Sjfv } 536238148Sjfv checksum += nvm_data; 537238148Sjfv } 538238148Sjfv checksum = (u16) NVM_SUM - checksum; 539238148Sjfv ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, 540238148Sjfv &checksum); 541238148Sjfv if (ret_val != E1000_SUCCESS) { 542238148Sjfv hw->nvm.ops.release(hw); 543238148Sjfv DEBUGOUT("NVM Write Error while updating checksum.\n"); 544238148Sjfv goto out; 545238148Sjfv } 546238148Sjfv 547238148Sjfv hw->nvm.ops.release(hw); 548238148Sjfv 549238148Sjfv ret_val = e1000_update_flash_i210(hw); 550238148Sjfv } else { 551238148Sjfv ret_val = E1000_ERR_SWFW_SYNC; 552238148Sjfv } 553238148Sjfvout: 554238148Sjfv return ret_val; 555238148Sjfv} 556238148Sjfv 557238148Sjfv/** 558238148Sjfv * e1000_get_flash_presence_i210 - Check if flash device is detected. 559238148Sjfv * @hw: pointer to the HW structure 560238148Sjfv * 561238148Sjfv **/ 562238148Sjfvstatic bool e1000_get_flash_presence_i210(struct e1000_hw *hw) 563238148Sjfv{ 564238148Sjfv u32 eec = 0; 565238148Sjfv bool ret_val = FALSE; 566238148Sjfv 567238148Sjfv DEBUGFUNC("e1000_get_flash_presence_i210"); 568238148Sjfv 569238148Sjfv eec = E1000_READ_REG(hw, E1000_EECD); 570238148Sjfv 571238148Sjfv if (eec & E1000_EECD_FLASH_DETECTED_I210) 572238148Sjfv ret_val = TRUE; 573238148Sjfv 574238148Sjfv return ret_val; 575238148Sjfv} 576238148Sjfv 577238148Sjfv/** 578238148Sjfv * e1000_update_flash_i210 - Commit EEPROM to the flash 579238148Sjfv * @hw: pointer to the HW structure 580238148Sjfv * 581238148Sjfv **/ 582238148Sjfvs32 e1000_update_flash_i210(struct e1000_hw *hw) 583238148Sjfv{ 584238148Sjfv s32 ret_val = E1000_SUCCESS; 585238148Sjfv u32 flup; 586238148Sjfv 587238148Sjfv DEBUGFUNC("e1000_update_flash_i210"); 588238148Sjfv 589238148Sjfv ret_val = e1000_pool_flash_update_done_i210(hw); 590238148Sjfv if (ret_val == -E1000_ERR_NVM) { 591238148Sjfv DEBUGOUT("Flash update time out\n"); 592238148Sjfv goto out; 593238148Sjfv } 594238148Sjfv 595238148Sjfv flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210; 596238148Sjfv E1000_WRITE_REG(hw, E1000_EECD, flup); 597238148Sjfv 598238148Sjfv ret_val = e1000_pool_flash_update_done_i210(hw); 599238148Sjfv if (ret_val == E1000_SUCCESS) 600238148Sjfv DEBUGOUT("Flash update complete\n"); 601238148Sjfv else 602238148Sjfv DEBUGOUT("Flash update time out\n"); 603238148Sjfv 604238148Sjfvout: 605238148Sjfv return ret_val; 606238148Sjfv} 607238148Sjfv 608238148Sjfv/** 609238148Sjfv * e1000_pool_flash_update_done_i210 - Pool FLUDONE status. 610238148Sjfv * @hw: pointer to the HW structure 611238148Sjfv * 612238148Sjfv **/ 613238148Sjfvs32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw) 614238148Sjfv{ 615238148Sjfv s32 ret_val = -E1000_ERR_NVM; 616238148Sjfv u32 i, reg; 617238148Sjfv 618238148Sjfv DEBUGFUNC("e1000_pool_flash_update_done_i210"); 619238148Sjfv 620238148Sjfv for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { 621238148Sjfv reg = E1000_READ_REG(hw, E1000_EECD); 622238148Sjfv if (reg & E1000_EECD_FLUDONE_I210) { 623238148Sjfv ret_val = E1000_SUCCESS; 624238148Sjfv break; 625238148Sjfv } 626238148Sjfv usec_delay(5); 627238148Sjfv } 628238148Sjfv 629238148Sjfv return ret_val; 630238148Sjfv} 631238148Sjfv 632238148Sjfv/** 633238148Sjfv * e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers 634238148Sjfv * @hw: pointer to the HW structure 635238148Sjfv * 636238148Sjfv * Initialize the i210 NVM parameters and function pointers. 637238148Sjfv **/ 638238148Sjfvstatic s32 e1000_init_nvm_params_i210(struct e1000_hw *hw) 639238148Sjfv{ 640238148Sjfv s32 ret_val = E1000_SUCCESS; 641238148Sjfv struct e1000_nvm_info *nvm = &hw->nvm; 642238148Sjfv 643238148Sjfv DEBUGFUNC("e1000_init_nvm_params_i210"); 644238148Sjfv 645238148Sjfv ret_val = e1000_init_nvm_params_82575(hw); 646238148Sjfv 647238148Sjfv nvm->ops.acquire = e1000_acquire_nvm_i210; 648238148Sjfv nvm->ops.release = e1000_release_nvm_i210; 649238148Sjfv nvm->ops.read = e1000_read_nvm_srrd_i210; 650238148Sjfv nvm->ops.write = e1000_write_nvm_srwr_i210; 651238148Sjfv nvm->ops.valid_led_default = e1000_valid_led_default_i210; 652238148Sjfv nvm->ops.validate = e1000_validate_nvm_checksum_i210; 653238148Sjfv nvm->ops.update = e1000_update_nvm_checksum_i210; 654238148Sjfv 655238148Sjfv return ret_val; 656238148Sjfv} 657238148Sjfv 658238148Sjfv/** 659238148Sjfv * e1000_init_nvm_params_i211 - Initialize i211 NVM function pointers 660238148Sjfv * @hw: pointer to the HW structure 661238148Sjfv * 662238148Sjfv * Initialize the NVM parameters and function pointers for i211. 663238148Sjfv **/ 664238148Sjfvstatic s32 e1000_init_nvm_params_i211(struct e1000_hw *hw) 665238148Sjfv{ 666238148Sjfv struct e1000_nvm_info *nvm = &hw->nvm; 667238148Sjfv 668238148Sjfv DEBUGFUNC("e1000_init_nvm_params_i211"); 669238148Sjfv 670238148Sjfv nvm->ops.acquire = e1000_acquire_nvm_i210; 671238148Sjfv nvm->ops.release = e1000_release_nvm_i210; 672238148Sjfv nvm->ops.read = e1000_read_nvm_i211; 673238148Sjfv nvm->ops.valid_led_default = e1000_valid_led_default_i210; 674238148Sjfv nvm->ops.write = e1000_null_write_nvm; 675238148Sjfv nvm->ops.validate = e1000_null_ops_generic; 676238148Sjfv nvm->ops.update = e1000_null_ops_generic; 677238148Sjfv 678238148Sjfv return E1000_SUCCESS; 679238148Sjfv} 680238148Sjfv 681238148Sjfv/** 682238148Sjfv * e1000_init_function_pointers_i210 - Init func ptrs. 683238148Sjfv * @hw: pointer to the HW structure 684238148Sjfv * 685238148Sjfv * Called to initialize all function pointers and parameters. 686238148Sjfv **/ 687238148Sjfvvoid e1000_init_function_pointers_i210(struct e1000_hw *hw) 688238148Sjfv{ 689238148Sjfv e1000_init_function_pointers_82575(hw); 690238148Sjfv 691238148Sjfv switch (hw->mac.type) { 692238148Sjfv case e1000_i210: 693238148Sjfv if (e1000_get_flash_presence_i210(hw)) 694238148Sjfv hw->nvm.ops.init_params = e1000_init_nvm_params_i210; 695238148Sjfv else 696238148Sjfv hw->nvm.ops.init_params = e1000_init_nvm_params_i211; 697238148Sjfv break; 698238148Sjfv case e1000_i211: 699238148Sjfv hw->nvm.ops.init_params = e1000_init_nvm_params_i211; 700238148Sjfv break; 701238148Sjfv default: 702238148Sjfv break; 703238148Sjfv } 704238148Sjfv return; 705238148Sjfv} 706238148Sjfv 707238148Sjfv/** 708238148Sjfv * e1000_valid_led_default_i210 - Verify a valid default LED config 709238148Sjfv * @hw: pointer to the HW structure 710238148Sjfv * @data: pointer to the NVM (EEPROM) 711238148Sjfv * 712238148Sjfv * Read the EEPROM for the current default LED configuration. If the 713238148Sjfv * LED configuration is not valid, set to a valid LED configuration. 714238148Sjfv **/ 715238148Sjfvstatic s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data) 716238148Sjfv{ 717238148Sjfv s32 ret_val; 718238148Sjfv 719238148Sjfv DEBUGFUNC("e1000_valid_led_default_i210"); 720238148Sjfv 721238148Sjfv ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 722238148Sjfv if (ret_val) { 723238148Sjfv DEBUGOUT("NVM Read Error\n"); 724238148Sjfv goto out; 725238148Sjfv } 726238148Sjfv 727238148Sjfv if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 728238148Sjfv switch (hw->phy.media_type) { 729238148Sjfv case e1000_media_type_internal_serdes: 730238148Sjfv *data = ID_LED_DEFAULT_I210_SERDES; 731238148Sjfv break; 732238148Sjfv case e1000_media_type_copper: 733238148Sjfv default: 734238148Sjfv *data = ID_LED_DEFAULT_I210; 735238148Sjfv break; 736238148Sjfv } 737238148Sjfv } 738238148Sjfvout: 739238148Sjfv return ret_val; 740238148Sjfv} 741