15779Sxy150489 /* 25779Sxy150489 * CDDL HEADER START 35779Sxy150489 * 48571SChenlu.Chen@Sun.COM * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 55779Sxy150489 * The contents of this file are subject to the terms of the 65779Sxy150489 * Common Development and Distribution License (the "License"). 75779Sxy150489 * You may not use this file except in compliance with the License. 85779Sxy150489 * 95779Sxy150489 * You can obtain a copy of the license at: 105779Sxy150489 * http://www.opensolaris.org/os/licensing. 115779Sxy150489 * See the License for the specific language governing permissions 125779Sxy150489 * and limitations under the License. 135779Sxy150489 * 145779Sxy150489 * When using or redistributing this file, you may do so under the 155779Sxy150489 * License only. No other modification of this header is permitted. 165779Sxy150489 * 175779Sxy150489 * If applicable, add the following below this CDDL HEADER, with the 185779Sxy150489 * fields enclosed by brackets "[]" replaced with your own identifying 195779Sxy150489 * information: Portions Copyright [yyyy] [name of copyright owner] 205779Sxy150489 * 215779Sxy150489 * CDDL HEADER END 225779Sxy150489 */ 235779Sxy150489 245779Sxy150489 /* 258571SChenlu.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 265779Sxy150489 * Use is subject to license terms of the CDDL. 275779Sxy150489 */ 285779Sxy150489 29*10319SJason.Xu@Sun.COM /* IntelVersion: 1.49 v2-9-8_2009-6-12 */ 305779Sxy150489 315779Sxy150489 #include "igb_api.h" 328571SChenlu.Chen@Sun.COM 338571SChenlu.Chen@Sun.COM static void e1000_stop_nvm(struct e1000_hw *hw); 348571SChenlu.Chen@Sun.COM static void e1000_reload_nvm_generic(struct e1000_hw *hw); 358571SChenlu.Chen@Sun.COM 368571SChenlu.Chen@Sun.COM /* 378571SChenlu.Chen@Sun.COM * e1000_init_nvm_ops_generic - Initialize NVM function pointers 388571SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure 398571SChenlu.Chen@Sun.COM * 408571SChenlu.Chen@Sun.COM * Setups up the function pointers to no-op functions 418571SChenlu.Chen@Sun.COM */ 428571SChenlu.Chen@Sun.COM void 438571SChenlu.Chen@Sun.COM e1000_init_nvm_ops_generic(struct e1000_hw *hw) 448571SChenlu.Chen@Sun.COM { 458571SChenlu.Chen@Sun.COM struct e1000_nvm_info *nvm = &hw->nvm; 468571SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_init_nvm_ops_generic"); 478571SChenlu.Chen@Sun.COM 488571SChenlu.Chen@Sun.COM /* Initialize function pointers */ 498571SChenlu.Chen@Sun.COM nvm->ops.init_params = e1000_null_ops_generic; 508571SChenlu.Chen@Sun.COM nvm->ops.acquire = e1000_null_ops_generic; 518571SChenlu.Chen@Sun.COM nvm->ops.read = e1000_null_read_nvm; 528571SChenlu.Chen@Sun.COM nvm->ops.release = e1000_null_nvm_generic; 538571SChenlu.Chen@Sun.COM nvm->ops.reload = e1000_reload_nvm_generic; 548571SChenlu.Chen@Sun.COM nvm->ops.update = e1000_null_ops_generic; 558571SChenlu.Chen@Sun.COM nvm->ops.valid_led_default = e1000_null_led_default; 568571SChenlu.Chen@Sun.COM nvm->ops.validate = e1000_null_ops_generic; 578571SChenlu.Chen@Sun.COM nvm->ops.write = e1000_null_write_nvm; 588571SChenlu.Chen@Sun.COM } 598571SChenlu.Chen@Sun.COM 608571SChenlu.Chen@Sun.COM /* 618571SChenlu.Chen@Sun.COM * e1000_null_nvm_read - No-op function, return 0 628571SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure 638571SChenlu.Chen@Sun.COM */ 648571SChenlu.Chen@Sun.COM s32 658571SChenlu.Chen@Sun.COM e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c) 668571SChenlu.Chen@Sun.COM { 678571SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_null_read_nvm"); 688571SChenlu.Chen@Sun.COM UNREFERENCED_4PARAMETER(hw, a, b, c); 698571SChenlu.Chen@Sun.COM return (E1000_SUCCESS); 708571SChenlu.Chen@Sun.COM } 718571SChenlu.Chen@Sun.COM 728571SChenlu.Chen@Sun.COM /* 738571SChenlu.Chen@Sun.COM * e1000_null_nvm_generic - No-op function, return void 748571SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure 758571SChenlu.Chen@Sun.COM */ 768571SChenlu.Chen@Sun.COM void 778571SChenlu.Chen@Sun.COM e1000_null_nvm_generic(struct e1000_hw *hw) 788571SChenlu.Chen@Sun.COM { 798571SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_null_nvm_generic"); 808571SChenlu.Chen@Sun.COM UNREFERENCED_1PARAMETER(hw); 818571SChenlu.Chen@Sun.COM } 828571SChenlu.Chen@Sun.COM 838571SChenlu.Chen@Sun.COM /* 848571SChenlu.Chen@Sun.COM * e1000_null_led_default - No-op function, return 0 858571SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure 868571SChenlu.Chen@Sun.COM */ 878571SChenlu.Chen@Sun.COM s32 888571SChenlu.Chen@Sun.COM e1000_null_led_default(struct e1000_hw *hw, u16 *data) 898571SChenlu.Chen@Sun.COM { 908571SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_null_led_default"); 918571SChenlu.Chen@Sun.COM UNREFERENCED_2PARAMETER(hw, data); 928571SChenlu.Chen@Sun.COM return (E1000_SUCCESS); 938571SChenlu.Chen@Sun.COM } 948571SChenlu.Chen@Sun.COM 958571SChenlu.Chen@Sun.COM /* 968571SChenlu.Chen@Sun.COM * e1000_null_write_nvm - No-op function, return 0 978571SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure 988571SChenlu.Chen@Sun.COM */ 998571SChenlu.Chen@Sun.COM s32 1008571SChenlu.Chen@Sun.COM e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c) 1018571SChenlu.Chen@Sun.COM { 1028571SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_null_write_nvm"); 1038571SChenlu.Chen@Sun.COM UNREFERENCED_4PARAMETER(hw, a, b, c); 1048571SChenlu.Chen@Sun.COM return (E1000_SUCCESS); 1058571SChenlu.Chen@Sun.COM } 1065779Sxy150489 1075779Sxy150489 /* 1085779Sxy150489 * e1000_raise_eec_clk - Raise EEPROM clock 1095779Sxy150489 * @hw: pointer to the HW structure 1105779Sxy150489 * @eecd: pointer to the EEPROM 1115779Sxy150489 * 1125779Sxy150489 * Enable/Raise the EEPROM clock bit. 1135779Sxy150489 */ 1145779Sxy150489 static void 1155779Sxy150489 e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) 1165779Sxy150489 { 1175779Sxy150489 *eecd = *eecd | E1000_EECD_SK; 1185779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, *eecd); 1195779Sxy150489 E1000_WRITE_FLUSH(hw); 1205779Sxy150489 usec_delay(hw->nvm.delay_usec); 1215779Sxy150489 } 1225779Sxy150489 1235779Sxy150489 /* 1245779Sxy150489 * e1000_lower_eec_clk - Lower EEPROM clock 1255779Sxy150489 * @hw: pointer to the HW structure 1265779Sxy150489 * @eecd: pointer to the EEPROM 1275779Sxy150489 * 1285779Sxy150489 * Clear/Lower the EEPROM clock bit. 1295779Sxy150489 */ 1305779Sxy150489 static void 1315779Sxy150489 e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) 1325779Sxy150489 { 1335779Sxy150489 *eecd = *eecd & ~E1000_EECD_SK; 1345779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, *eecd); 1355779Sxy150489 E1000_WRITE_FLUSH(hw); 1365779Sxy150489 usec_delay(hw->nvm.delay_usec); 1375779Sxy150489 } 1385779Sxy150489 1395779Sxy150489 /* 1405779Sxy150489 * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM 1415779Sxy150489 * @hw: pointer to the HW structure 1425779Sxy150489 * @data: data to send to the EEPROM 1435779Sxy150489 * @count: number of bits to shift out 1445779Sxy150489 * 1455779Sxy150489 * We need to shift 'count' bits out to the EEPROM. So, the value in the 1465779Sxy150489 * "data" parameter will be shifted out to the EEPROM one bit at a time. 1475779Sxy150489 * In order to do this, "data" must be broken down into bits. 1485779Sxy150489 */ 1495779Sxy150489 static void 1505779Sxy150489 e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) 1515779Sxy150489 { 1525779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 1535779Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD); 1545779Sxy150489 u32 mask; 1555779Sxy150489 1565779Sxy150489 DEBUGFUNC("e1000_shift_out_eec_bits"); 1575779Sxy150489 1585779Sxy150489 mask = 0x01 << (count - 1); 1595779Sxy150489 if (nvm->type == e1000_nvm_eeprom_microwire) 1605779Sxy150489 eecd &= ~E1000_EECD_DO; 1615779Sxy150489 else if (nvm->type == e1000_nvm_eeprom_spi) 1625779Sxy150489 eecd |= E1000_EECD_DO; 1635779Sxy150489 1645779Sxy150489 do { 1655779Sxy150489 eecd &= ~E1000_EECD_DI; 1665779Sxy150489 1675779Sxy150489 if (data & mask) 1685779Sxy150489 eecd |= E1000_EECD_DI; 1695779Sxy150489 1705779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 1715779Sxy150489 E1000_WRITE_FLUSH(hw); 1725779Sxy150489 1735779Sxy150489 usec_delay(nvm->delay_usec); 1745779Sxy150489 1755779Sxy150489 e1000_raise_eec_clk(hw, &eecd); 1765779Sxy150489 e1000_lower_eec_clk(hw, &eecd); 1775779Sxy150489 1785779Sxy150489 mask >>= 1; 1795779Sxy150489 } while (mask); 1805779Sxy150489 1815779Sxy150489 eecd &= ~E1000_EECD_DI; 1825779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 1835779Sxy150489 } 1845779Sxy150489 1855779Sxy150489 /* 1865779Sxy150489 * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM 1875779Sxy150489 * @hw: pointer to the HW structure 1885779Sxy150489 * @count: number of bits to shift in 1895779Sxy150489 * 1905779Sxy150489 * In order to read a register from the EEPROM, we need to shift 'count' bits 1915779Sxy150489 * in from the EEPROM. Bits are "shifted in" by raising the clock input to 1925779Sxy150489 * the EEPROM (setting the SK bit), and then reading the value of the data out 1935779Sxy150489 * "DO" bit. During this "shifting in" process the data in "DI" bit should 1945779Sxy150489 * always be clear. 1955779Sxy150489 */ 1965779Sxy150489 static u16 1975779Sxy150489 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) 1985779Sxy150489 { 1995779Sxy150489 u32 eecd; 2005779Sxy150489 u32 i; 2015779Sxy150489 u16 data; 2025779Sxy150489 2035779Sxy150489 DEBUGFUNC("e1000_shift_in_eec_bits"); 2045779Sxy150489 2055779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 2065779Sxy150489 2075779Sxy150489 eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); 2085779Sxy150489 data = 0; 2095779Sxy150489 2105779Sxy150489 for (i = 0; i < count; i++) { 2115779Sxy150489 data <<= 1; 2125779Sxy150489 e1000_raise_eec_clk(hw, &eecd); 2135779Sxy150489 2145779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 2155779Sxy150489 2165779Sxy150489 eecd &= ~E1000_EECD_DI; 2175779Sxy150489 if (eecd & E1000_EECD_DO) 2185779Sxy150489 data |= 1; 2195779Sxy150489 2205779Sxy150489 e1000_lower_eec_clk(hw, &eecd); 2215779Sxy150489 } 2225779Sxy150489 2235779Sxy150489 return (data); 2245779Sxy150489 } 2255779Sxy150489 2265779Sxy150489 /* 2275779Sxy150489 * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion 2285779Sxy150489 * @hw: pointer to the HW structure 2295779Sxy150489 * @ee_reg: EEPROM flag for polling 2305779Sxy150489 * 2315779Sxy150489 * Polls the EEPROM status bit for either read or write completion based 2325779Sxy150489 * upon the value of 'ee_reg'. 2335779Sxy150489 */ 2345779Sxy150489 s32 2355779Sxy150489 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) 2365779Sxy150489 { 2375779Sxy150489 u32 attempts = 100000; 2385779Sxy150489 u32 i, reg = 0; 2395779Sxy150489 s32 ret_val = -E1000_ERR_NVM; 2405779Sxy150489 2415779Sxy150489 DEBUGFUNC("e1000_poll_eerd_eewr_done"); 2425779Sxy150489 2435779Sxy150489 for (i = 0; i < attempts; i++) { 2445779Sxy150489 if (ee_reg == E1000_NVM_POLL_READ) 2455779Sxy150489 reg = E1000_READ_REG(hw, E1000_EERD); 2465779Sxy150489 else 2475779Sxy150489 reg = E1000_READ_REG(hw, E1000_EEWR); 2485779Sxy150489 2495779Sxy150489 if (reg & E1000_NVM_RW_REG_DONE) { 2505779Sxy150489 ret_val = E1000_SUCCESS; 2515779Sxy150489 break; 2525779Sxy150489 } 2535779Sxy150489 2545779Sxy150489 usec_delay(5); 2555779Sxy150489 } 2565779Sxy150489 2575779Sxy150489 return (ret_val); 2585779Sxy150489 } 2595779Sxy150489 2605779Sxy150489 /* 2615779Sxy150489 * e1000_acquire_nvm_generic - Generic request for access to EEPROM 2625779Sxy150489 * @hw: pointer to the HW structure 2635779Sxy150489 * 2645779Sxy150489 * Set the EEPROM access request bit and wait for EEPROM access grant bit. 2655779Sxy150489 * Return successful if access grant bit set, else clear the request for 2665779Sxy150489 * EEPROM access and return -E1000_ERR_NVM (-1). 2675779Sxy150489 */ 2685779Sxy150489 s32 2695779Sxy150489 e1000_acquire_nvm_generic(struct e1000_hw *hw) 2705779Sxy150489 { 2715779Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD); 2725779Sxy150489 s32 timeout = E1000_NVM_GRANT_ATTEMPTS; 2735779Sxy150489 s32 ret_val = E1000_SUCCESS; 2745779Sxy150489 2755779Sxy150489 DEBUGFUNC("e1000_acquire_nvm_generic"); 2765779Sxy150489 2775779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); 2785779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 2795779Sxy150489 2805779Sxy150489 while (timeout) { 2815779Sxy150489 if (eecd & E1000_EECD_GNT) 2825779Sxy150489 break; 2835779Sxy150489 usec_delay(5); 2845779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 2855779Sxy150489 timeout--; 2865779Sxy150489 } 2875779Sxy150489 2885779Sxy150489 if (!timeout) { 2895779Sxy150489 eecd &= ~E1000_EECD_REQ; 2905779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 2915779Sxy150489 DEBUGOUT("Could not acquire NVM grant\n"); 2925779Sxy150489 ret_val = -E1000_ERR_NVM; 2935779Sxy150489 } 2945779Sxy150489 2955779Sxy150489 return (ret_val); 2965779Sxy150489 } 2975779Sxy150489 2985779Sxy150489 /* 2995779Sxy150489 * e1000_standby_nvm - Return EEPROM to standby state 3005779Sxy150489 * @hw: pointer to the HW structure 3015779Sxy150489 * 3025779Sxy150489 * Return the EEPROM to a standby state. 3035779Sxy150489 */ 3045779Sxy150489 static void 3055779Sxy150489 e1000_standby_nvm(struct e1000_hw *hw) 3065779Sxy150489 { 3075779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 3085779Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD); 3095779Sxy150489 3105779Sxy150489 DEBUGFUNC("e1000_standby_nvm"); 3115779Sxy150489 3125779Sxy150489 if (nvm->type == e1000_nvm_eeprom_microwire) { 3135779Sxy150489 eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); 3145779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 3155779Sxy150489 E1000_WRITE_FLUSH(hw); 3165779Sxy150489 usec_delay(nvm->delay_usec); 3175779Sxy150489 3185779Sxy150489 e1000_raise_eec_clk(hw, &eecd); 3195779Sxy150489 3205779Sxy150489 /* Select EEPROM */ 3215779Sxy150489 eecd |= E1000_EECD_CS; 3225779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 3235779Sxy150489 E1000_WRITE_FLUSH(hw); 3245779Sxy150489 usec_delay(nvm->delay_usec); 3255779Sxy150489 3265779Sxy150489 e1000_lower_eec_clk(hw, &eecd); 3275779Sxy150489 } else if (nvm->type == e1000_nvm_eeprom_spi) { 3285779Sxy150489 /* Toggle CS to flush commands */ 3295779Sxy150489 eecd |= E1000_EECD_CS; 3305779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 3315779Sxy150489 E1000_WRITE_FLUSH(hw); 3325779Sxy150489 usec_delay(nvm->delay_usec); 3335779Sxy150489 eecd &= ~E1000_EECD_CS; 3345779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 3355779Sxy150489 E1000_WRITE_FLUSH(hw); 3365779Sxy150489 usec_delay(nvm->delay_usec); 3375779Sxy150489 } 3385779Sxy150489 } 3395779Sxy150489 3405779Sxy150489 /* 3415779Sxy150489 * e1000_stop_nvm - Terminate EEPROM command 3425779Sxy150489 * @hw: pointer to the HW structure 3435779Sxy150489 * 3445779Sxy150489 * Terminates the current command by inverting the EEPROM's chip select pin. 3455779Sxy150489 */ 3465779Sxy150489 void 3475779Sxy150489 e1000_stop_nvm(struct e1000_hw *hw) 3485779Sxy150489 { 3495779Sxy150489 u32 eecd; 3505779Sxy150489 3515779Sxy150489 DEBUGFUNC("e1000_stop_nvm"); 3525779Sxy150489 3535779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 3545779Sxy150489 if (hw->nvm.type == e1000_nvm_eeprom_spi) { 3555779Sxy150489 /* Pull CS high */ 3565779Sxy150489 eecd |= E1000_EECD_CS; 3575779Sxy150489 e1000_lower_eec_clk(hw, &eecd); 3585779Sxy150489 } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) { 3598571SChenlu.Chen@Sun.COM /* CS on Microwire is active-high */ 3605779Sxy150489 eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); 3615779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 3625779Sxy150489 e1000_raise_eec_clk(hw, &eecd); 3635779Sxy150489 e1000_lower_eec_clk(hw, &eecd); 3645779Sxy150489 } 3655779Sxy150489 } 3665779Sxy150489 3675779Sxy150489 /* 3685779Sxy150489 * e1000_release_nvm_generic - Release exclusive access to EEPROM 3695779Sxy150489 * @hw: pointer to the HW structure 3705779Sxy150489 * 3715779Sxy150489 * Stop any current commands to the EEPROM and clear the EEPROM request bit. 3725779Sxy150489 */ 3735779Sxy150489 void 3745779Sxy150489 e1000_release_nvm_generic(struct e1000_hw *hw) 3755779Sxy150489 { 3765779Sxy150489 u32 eecd; 3775779Sxy150489 3785779Sxy150489 DEBUGFUNC("e1000_release_nvm_generic"); 3795779Sxy150489 3805779Sxy150489 e1000_stop_nvm(hw); 3815779Sxy150489 3825779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 3835779Sxy150489 eecd &= ~E1000_EECD_REQ; 3845779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 3855779Sxy150489 } 3865779Sxy150489 3875779Sxy150489 /* 3885779Sxy150489 * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write 3895779Sxy150489 * @hw: pointer to the HW structure 3905779Sxy150489 * 3915779Sxy150489 * Setups the EEPROM for reading and writing. 3925779Sxy150489 */ 3935779Sxy150489 static s32 3945779Sxy150489 e1000_ready_nvm_eeprom(struct e1000_hw *hw) 3955779Sxy150489 { 3965779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 3975779Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD); 3985779Sxy150489 s32 ret_val = E1000_SUCCESS; 3995779Sxy150489 u16 timeout = 0; 4005779Sxy150489 u8 spi_stat_reg; 4015779Sxy150489 4025779Sxy150489 DEBUGFUNC("e1000_ready_nvm_eeprom"); 4035779Sxy150489 4045779Sxy150489 if (nvm->type == e1000_nvm_eeprom_microwire) { 4055779Sxy150489 /* Clear SK and DI */ 4065779Sxy150489 eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); 4075779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 4085779Sxy150489 /* Set CS */ 4095779Sxy150489 eecd |= E1000_EECD_CS; 4105779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 4115779Sxy150489 } else if (nvm->type == e1000_nvm_eeprom_spi) { 4125779Sxy150489 /* Clear SK and CS */ 4135779Sxy150489 eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); 4145779Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd); 4155779Sxy150489 usec_delay(1); 4165779Sxy150489 timeout = NVM_MAX_RETRY_SPI; 4175779Sxy150489 4185779Sxy150489 /* 4195779Sxy150489 * Read "Status Register" repeatedly until the LSB is cleared. 4205779Sxy150489 * The EEPROM will signal that the command has been completed 4215779Sxy150489 * by clearing bit 0 of the internal status register. If it's 4225779Sxy150489 * not cleared within 'timeout', then error out. 4235779Sxy150489 */ 4245779Sxy150489 while (timeout) { 4255779Sxy150489 e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, 4265779Sxy150489 hw->nvm.opcode_bits); 4275779Sxy150489 spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); 4285779Sxy150489 if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) 4295779Sxy150489 break; 4305779Sxy150489 4315779Sxy150489 usec_delay(5); 4325779Sxy150489 e1000_standby_nvm(hw); 4335779Sxy150489 timeout--; 4345779Sxy150489 } 4355779Sxy150489 4365779Sxy150489 if (!timeout) { 4375779Sxy150489 DEBUGOUT("SPI NVM Status error\n"); 4385779Sxy150489 ret_val = -E1000_ERR_NVM; 4395779Sxy150489 goto out; 4405779Sxy150489 } 4415779Sxy150489 } 4425779Sxy150489 4435779Sxy150489 out: 4445779Sxy150489 return (ret_val); 4455779Sxy150489 } 4465779Sxy150489 4475779Sxy150489 /* 4485779Sxy150489 * e1000_read_nvm_microwire - Reads EEPROM's using microwire 4495779Sxy150489 * @hw: pointer to the HW structure 4505779Sxy150489 * @offset: offset of word in the EEPROM to read 4515779Sxy150489 * @words: number of words to read 4525779Sxy150489 * @data: word read from the EEPROM 4535779Sxy150489 * 4545779Sxy150489 * Reads a 16 bit word from the EEPROM. 4555779Sxy150489 */ 4565779Sxy150489 s32 4575779Sxy150489 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, 4585779Sxy150489 u16 *data) 4595779Sxy150489 { 4605779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 4615779Sxy150489 u32 i = 0; 4625779Sxy150489 s32 ret_val; 4635779Sxy150489 u8 read_opcode = NVM_READ_OPCODE_MICROWIRE; 4645779Sxy150489 4655779Sxy150489 DEBUGFUNC("e1000_read_nvm_microwire"); 4665779Sxy150489 4675779Sxy150489 /* 4685779Sxy150489 * A check for invalid values: offset too large, too many words, 4695779Sxy150489 * and not enough words. 4705779Sxy150489 */ 4715779Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 4725779Sxy150489 (words == 0)) { 4735779Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n"); 4745779Sxy150489 ret_val = -E1000_ERR_NVM; 4755779Sxy150489 goto out; 4765779Sxy150489 } 4775779Sxy150489 4788571SChenlu.Chen@Sun.COM ret_val = nvm->ops.acquire(hw); 4795779Sxy150489 if (ret_val) 4805779Sxy150489 goto out; 4815779Sxy150489 4825779Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw); 4835779Sxy150489 if (ret_val) 4845779Sxy150489 goto release; 4855779Sxy150489 4865779Sxy150489 for (i = 0; i < words; i++) { 4875779Sxy150489 /* Send the READ command (opcode + addr) */ 4885779Sxy150489 e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); 4895779Sxy150489 e1000_shift_out_eec_bits(hw, (u16)(offset + i), 4905779Sxy150489 nvm->address_bits); 4915779Sxy150489 4925779Sxy150489 /* 4935779Sxy150489 * Read the data. For microwire, each word requires the 4945779Sxy150489 * overhead of setup and tear-down. 4955779Sxy150489 */ 4965779Sxy150489 data[i] = e1000_shift_in_eec_bits(hw, 16); 4975779Sxy150489 e1000_standby_nvm(hw); 4985779Sxy150489 } 4995779Sxy150489 5005779Sxy150489 release: 5018571SChenlu.Chen@Sun.COM nvm->ops.release(hw); 5025779Sxy150489 5035779Sxy150489 out: 5045779Sxy150489 return (ret_val); 5055779Sxy150489 } 5065779Sxy150489 5075779Sxy150489 /* 5085779Sxy150489 * e1000_read_nvm_eerd - Reads EEPROM using EERD register 5095779Sxy150489 * @hw: pointer to the HW structure 5105779Sxy150489 * @offset: offset of word in the EEPROM to read 5115779Sxy150489 * @words: number of words to read 5125779Sxy150489 * @data: word read from the EEPROM 5135779Sxy150489 * 5145779Sxy150489 * Reads a 16 bit word from the EEPROM using the EERD register. 5155779Sxy150489 */ 5165779Sxy150489 s32 5175779Sxy150489 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) 5185779Sxy150489 { 5195779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 5205779Sxy150489 u32 i, eerd = 0; 5215779Sxy150489 s32 ret_val = E1000_SUCCESS; 5225779Sxy150489 5235779Sxy150489 DEBUGFUNC("e1000_read_nvm_eerd"); 5245779Sxy150489 5255779Sxy150489 /* 5265779Sxy150489 * A check for invalid values: offset too large, too many words, 5275779Sxy150489 * too many words for the offset, and not enough words. 5285779Sxy150489 */ 5295779Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 5305779Sxy150489 (words == 0)) { 5315779Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n"); 5325779Sxy150489 ret_val = -E1000_ERR_NVM; 5335779Sxy150489 goto out; 5345779Sxy150489 } 5355779Sxy150489 5365779Sxy150489 for (i = 0; i < words; i++) { 5375779Sxy150489 eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + 5385779Sxy150489 E1000_NVM_RW_REG_START; 5395779Sxy150489 5405779Sxy150489 E1000_WRITE_REG(hw, E1000_EERD, eerd); 5415779Sxy150489 ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); 5425779Sxy150489 if (ret_val) 5435779Sxy150489 break; 5445779Sxy150489 5455779Sxy150489 data[i] = (E1000_READ_REG(hw, E1000_EERD) >> 5465779Sxy150489 E1000_NVM_RW_REG_DATA); 5475779Sxy150489 } 5485779Sxy150489 5495779Sxy150489 out: 5505779Sxy150489 return (ret_val); 5515779Sxy150489 } 5525779Sxy150489 5535779Sxy150489 /* 5545779Sxy150489 * e1000_write_nvm_spi - Write to EEPROM using SPI 5555779Sxy150489 * @hw: pointer to the HW structure 5565779Sxy150489 * @offset: offset within the EEPROM to be written to 5575779Sxy150489 * @words: number of words to write 5585779Sxy150489 * @data: 16 bit word(s) to be written to the EEPROM 5595779Sxy150489 * 5605779Sxy150489 * Writes data to EEPROM at offset using SPI interface. 5615779Sxy150489 * 5625779Sxy150489 * If e1000_update_nvm_checksum is not called after this function , the 5638571SChenlu.Chen@Sun.COM * EEPROM will most likely contain an invalid checksum. 5645779Sxy150489 */ 5655779Sxy150489 s32 5665779Sxy150489 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) 5675779Sxy150489 { 5685779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 5695779Sxy150489 s32 ret_val; 5705779Sxy150489 u16 widx = 0; 5715779Sxy150489 5725779Sxy150489 DEBUGFUNC("e1000_write_nvm_spi"); 5735779Sxy150489 5745779Sxy150489 /* 5755779Sxy150489 * A check for invalid values: offset too large, too many words, 5765779Sxy150489 * and not enough words. 5775779Sxy150489 */ 5785779Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 5795779Sxy150489 (words == 0)) { 5805779Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n"); 5815779Sxy150489 ret_val = -E1000_ERR_NVM; 5825779Sxy150489 goto out; 5835779Sxy150489 } 5845779Sxy150489 5858571SChenlu.Chen@Sun.COM ret_val = nvm->ops.acquire(hw); 5865779Sxy150489 if (ret_val) 5875779Sxy150489 goto out; 5885779Sxy150489 5895779Sxy150489 while (widx < words) { 5905779Sxy150489 u8 write_opcode = NVM_WRITE_OPCODE_SPI; 5915779Sxy150489 5925779Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw); 5935779Sxy150489 if (ret_val) 5945779Sxy150489 goto release; 5955779Sxy150489 5965779Sxy150489 e1000_standby_nvm(hw); 5975779Sxy150489 5985779Sxy150489 /* Send the WRITE ENABLE command (8 bit opcode) */ 5995779Sxy150489 e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, 6005779Sxy150489 nvm->opcode_bits); 6015779Sxy150489 6025779Sxy150489 e1000_standby_nvm(hw); 6035779Sxy150489 6045779Sxy150489 /* 6055779Sxy150489 * Some SPI eeproms use the 8th address bit embedded in the 6065779Sxy150489 * opcode 6075779Sxy150489 */ 6085779Sxy150489 if ((nvm->address_bits == 8) && (offset >= 128)) 6095779Sxy150489 write_opcode |= NVM_A8_OPCODE_SPI; 6105779Sxy150489 6115779Sxy150489 /* Send the Write command (8-bit opcode + addr) */ 6125779Sxy150489 e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); 6135779Sxy150489 e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), 6145779Sxy150489 nvm->address_bits); 6155779Sxy150489 6165779Sxy150489 /* Loop to allow for up to whole page write of eeprom */ 6175779Sxy150489 while (widx < words) { 6185779Sxy150489 u16 word_out = data[widx]; 6195779Sxy150489 word_out = (word_out >> 8) | (word_out << 8); 6205779Sxy150489 e1000_shift_out_eec_bits(hw, word_out, 16); 6215779Sxy150489 widx++; 6225779Sxy150489 6235779Sxy150489 if ((((offset + widx) * 2) % nvm->page_size) == 0) { 6245779Sxy150489 e1000_standby_nvm(hw); 6255779Sxy150489 break; 6265779Sxy150489 } 6275779Sxy150489 } 6285779Sxy150489 } 6295779Sxy150489 6305779Sxy150489 msec_delay(10); 6315779Sxy150489 release: 6328571SChenlu.Chen@Sun.COM nvm->ops.release(hw); 6335779Sxy150489 6345779Sxy150489 out: 6355779Sxy150489 return (ret_val); 6365779Sxy150489 } 6375779Sxy150489 6385779Sxy150489 /* 6395779Sxy150489 * e1000_write_nvm_microwire - Writes EEPROM using microwire 6405779Sxy150489 * @hw: pointer to the HW structure 6415779Sxy150489 * @offset: offset within the EEPROM to be written to 6425779Sxy150489 * @words: number of words to write 6435779Sxy150489 * @data: 16 bit word(s) to be written to the EEPROM 6445779Sxy150489 * 6455779Sxy150489 * Writes data to EEPROM at offset using microwire interface. 6465779Sxy150489 * 6475779Sxy150489 * If e1000_update_nvm_checksum is not called after this function , the 6488571SChenlu.Chen@Sun.COM * EEPROM will most likely contain an invalid checksum. 6495779Sxy150489 */ 6505779Sxy150489 s32 6515779Sxy150489 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, 6525779Sxy150489 u16 *data) 6535779Sxy150489 { 6545779Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm; 6555779Sxy150489 s32 ret_val; 6565779Sxy150489 u32 eecd; 6575779Sxy150489 u16 words_written = 0; 6585779Sxy150489 u16 widx = 0; 6595779Sxy150489 6605779Sxy150489 DEBUGFUNC("e1000_write_nvm_microwire"); 6615779Sxy150489 6625779Sxy150489 /* 6635779Sxy150489 * A check for invalid values: offset too large, too many words, 6645779Sxy150489 * and not enough words. 6655779Sxy150489 */ 6665779Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || 6675779Sxy150489 (words == 0)) { 6685779Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n"); 6695779Sxy150489 ret_val = -E1000_ERR_NVM; 6705779Sxy150489 goto out; 6715779Sxy150489 } 6725779Sxy150489 6738571SChenlu.Chen@Sun.COM ret_val = nvm->ops.acquire(hw); 6745779Sxy150489 if (ret_val) 6755779Sxy150489 goto out; 6765779Sxy150489 6775779Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw); 6785779Sxy150489 if (ret_val) 6795779Sxy150489 goto release; 6805779Sxy150489 6815779Sxy150489 e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE, 6825779Sxy150489 (u16)(nvm->opcode_bits + 2)); 6835779Sxy150489 6845779Sxy150489 e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); 6855779Sxy150489 6865779Sxy150489 e1000_standby_nvm(hw); 6875779Sxy150489 6885779Sxy150489 while (words_written < words) { 6895779Sxy150489 e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE, 6905779Sxy150489 nvm->opcode_bits); 6915779Sxy150489 6925779Sxy150489 e1000_shift_out_eec_bits(hw, (u16)(offset + words_written), 6935779Sxy150489 nvm->address_bits); 6945779Sxy150489 6955779Sxy150489 e1000_shift_out_eec_bits(hw, data[words_written], 16); 6965779Sxy150489 6975779Sxy150489 e1000_standby_nvm(hw); 6985779Sxy150489 6995779Sxy150489 for (widx = 0; widx < 200; widx++) { 7005779Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD); 7015779Sxy150489 if (eecd & E1000_EECD_DO) 7025779Sxy150489 break; 7035779Sxy150489 usec_delay(50); 7045779Sxy150489 } 7055779Sxy150489 7065779Sxy150489 if (widx == 200) { 7075779Sxy150489 DEBUGOUT("NVM Write did not complete\n"); 7085779Sxy150489 ret_val = -E1000_ERR_NVM; 7095779Sxy150489 goto release; 7105779Sxy150489 } 7115779Sxy150489 7125779Sxy150489 e1000_standby_nvm(hw); 7135779Sxy150489 7145779Sxy150489 words_written++; 7155779Sxy150489 } 7165779Sxy150489 7175779Sxy150489 e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE, 7185779Sxy150489 (u16)(nvm->opcode_bits + 2)); 7195779Sxy150489 7205779Sxy150489 e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); 7215779Sxy150489 7225779Sxy150489 release: 7238571SChenlu.Chen@Sun.COM nvm->ops.release(hw); 7245779Sxy150489 7255779Sxy150489 out: 7265779Sxy150489 return (ret_val); 7275779Sxy150489 } 7285779Sxy150489 7295779Sxy150489 /* 7305779Sxy150489 * e1000_read_pba_num_generic - Read device part number 7315779Sxy150489 * @hw: pointer to the HW structure 7325779Sxy150489 * @pba_num: pointer to device part number 7335779Sxy150489 * 7345779Sxy150489 * Reads the product board assembly (PBA) number from the EEPROM and stores 7355779Sxy150489 * the value in pba_num. 7365779Sxy150489 */ 7375779Sxy150489 s32 7385779Sxy150489 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) 7395779Sxy150489 { 7405779Sxy150489 s32 ret_val; 7415779Sxy150489 u16 nvm_data; 7425779Sxy150489 7435779Sxy150489 DEBUGFUNC("e1000_read_pba_num_generic"); 7445779Sxy150489 7458571SChenlu.Chen@Sun.COM ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); 7465779Sxy150489 if (ret_val) { 7475779Sxy150489 DEBUGOUT("NVM Read Error\n"); 7485779Sxy150489 goto out; 7495779Sxy150489 } 7505779Sxy150489 *pba_num = (u32)(nvm_data << 16); 7515779Sxy150489 7528571SChenlu.Chen@Sun.COM ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); 7535779Sxy150489 if (ret_val) { 7545779Sxy150489 DEBUGOUT("NVM Read Error\n"); 7555779Sxy150489 goto out; 7565779Sxy150489 } 7575779Sxy150489 *pba_num |= nvm_data; 7585779Sxy150489 7595779Sxy150489 out: 7605779Sxy150489 return (ret_val); 7615779Sxy150489 } 7625779Sxy150489 7635779Sxy150489 /* 7645779Sxy150489 * e1000_read_mac_addr_generic - Read device MAC address 7655779Sxy150489 * @hw: pointer to the HW structure 7665779Sxy150489 * 7675779Sxy150489 * Reads the device MAC address from the EEPROM and stores the value. 7685779Sxy150489 * Since devices with two ports use the same EEPROM, we increment the 7695779Sxy150489 * last bit in the MAC address for the second port. 7705779Sxy150489 */ 7715779Sxy150489 s32 7725779Sxy150489 e1000_read_mac_addr_generic(struct e1000_hw *hw) 7735779Sxy150489 { 774*10319SJason.Xu@Sun.COM u32 rar_high; 775*10319SJason.Xu@Sun.COM u32 rar_low; 776*10319SJason.Xu@Sun.COM u16 i; 7775779Sxy150489 778*10319SJason.Xu@Sun.COM rar_high = E1000_READ_REG(hw, E1000_RAH(0)); 779*10319SJason.Xu@Sun.COM rar_low = E1000_READ_REG(hw, E1000_RAL(0)); 7805779Sxy150489 781*10319SJason.Xu@Sun.COM for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) 782*10319SJason.Xu@Sun.COM hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); 783*10319SJason.Xu@Sun.COM 784*10319SJason.Xu@Sun.COM for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) 785*10319SJason.Xu@Sun.COM hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); 7865779Sxy150489 7875779Sxy150489 for (i = 0; i < ETH_ADDR_LEN; i++) 7885779Sxy150489 hw->mac.addr[i] = hw->mac.perm_addr[i]; 7895779Sxy150489 790*10319SJason.Xu@Sun.COM return (E1000_SUCCESS); 7915779Sxy150489 } 7925779Sxy150489 7935779Sxy150489 /* 7945779Sxy150489 * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum 7955779Sxy150489 * @hw: pointer to the HW structure 7965779Sxy150489 * 7975779Sxy150489 * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 7985779Sxy150489 * and then verifies that the sum of the EEPROM is equal to 0xBABA. 7995779Sxy150489 */ 8005779Sxy150489 s32 8015779Sxy150489 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) 8025779Sxy150489 { 8035779Sxy150489 s32 ret_val = E1000_SUCCESS; 8045779Sxy150489 u16 checksum = 0; 8055779Sxy150489 u16 i, nvm_data; 8065779Sxy150489 8075779Sxy150489 DEBUGFUNC("e1000_validate_nvm_checksum_generic"); 8085779Sxy150489 8095779Sxy150489 for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { 8108571SChenlu.Chen@Sun.COM ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 8115779Sxy150489 if (ret_val) { 8125779Sxy150489 DEBUGOUT("NVM Read Error\n"); 8135779Sxy150489 goto out; 8145779Sxy150489 } 8155779Sxy150489 checksum += nvm_data; 8165779Sxy150489 } 8175779Sxy150489 8185779Sxy150489 if (checksum != (u16) NVM_SUM) { 8195779Sxy150489 DEBUGOUT("NVM Checksum Invalid\n"); 8205779Sxy150489 ret_val = -E1000_ERR_NVM; 8215779Sxy150489 goto out; 8225779Sxy150489 } 8235779Sxy150489 8245779Sxy150489 out: 8255779Sxy150489 return (ret_val); 8265779Sxy150489 } 8275779Sxy150489 8285779Sxy150489 /* 8295779Sxy150489 * e1000_update_nvm_checksum_generic - Update EEPROM checksum 8305779Sxy150489 * @hw: pointer to the HW structure 8315779Sxy150489 * 8325779Sxy150489 * Updates the EEPROM checksum by reading/adding each word of the EEPROM 8335779Sxy150489 * up to the checksum. Then calculates the EEPROM checksum and writes the 8345779Sxy150489 * value to the EEPROM. 8355779Sxy150489 */ 8365779Sxy150489 s32 8375779Sxy150489 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) 8385779Sxy150489 { 8395779Sxy150489 s32 ret_val; 8405779Sxy150489 u16 checksum = 0; 8415779Sxy150489 u16 i, nvm_data; 8425779Sxy150489 8435779Sxy150489 DEBUGFUNC("e1000_update_nvm_checksum"); 8445779Sxy150489 8455779Sxy150489 for (i = 0; i < NVM_CHECKSUM_REG; i++) { 8468571SChenlu.Chen@Sun.COM ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 8475779Sxy150489 if (ret_val) { 8485779Sxy150489 DEBUGOUT("NVM Read Error while updating checksum.\n"); 8495779Sxy150489 goto out; 8505779Sxy150489 } 8515779Sxy150489 checksum += nvm_data; 8525779Sxy150489 } 8535779Sxy150489 checksum = (u16) NVM_SUM - checksum; 8548571SChenlu.Chen@Sun.COM ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); 8558571SChenlu.Chen@Sun.COM if (ret_val) 8565779Sxy150489 DEBUGOUT("NVM Write Error while updating checksum.\n"); 8575779Sxy150489 8585779Sxy150489 out: 8595779Sxy150489 return (ret_val); 8605779Sxy150489 } 8615779Sxy150489 8625779Sxy150489 /* 8635779Sxy150489 * e1000_reload_nvm_generic - Reloads EEPROM 8645779Sxy150489 * @hw: pointer to the HW structure 8655779Sxy150489 * 8665779Sxy150489 * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the 8675779Sxy150489 * extended control register. 8685779Sxy150489 */ 8695779Sxy150489 void 8705779Sxy150489 e1000_reload_nvm_generic(struct e1000_hw *hw) 8715779Sxy150489 { 8725779Sxy150489 u32 ctrl_ext; 8735779Sxy150489 8745779Sxy150489 DEBUGFUNC("e1000_reload_nvm_generic"); 8755779Sxy150489 8765779Sxy150489 usec_delay(10); 8775779Sxy150489 ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 8785779Sxy150489 ctrl_ext |= E1000_CTRL_EXT_EE_RST; 8795779Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 8805779Sxy150489 E1000_WRITE_FLUSH(hw); 8815779Sxy150489 } 882