14919Sxy150489 /*
24919Sxy150489 * This file is provided under a CDDLv1 license. When using or
34919Sxy150489 * redistributing this file, you may do so under this license.
44919Sxy150489 * In redistributing this file this license must be included
54919Sxy150489 * and no other modification of this header file is permitted.
64919Sxy150489 *
74919Sxy150489 * CDDL LICENSE SUMMARY
84919Sxy150489 *
98479SChenlu.Chen@Sun.COM * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
104919Sxy150489 *
114919Sxy150489 * The contents of this file are subject to the terms of Version
124919Sxy150489 * 1.0 of the Common Development and Distribution License (the "License").
134919Sxy150489 *
144919Sxy150489 * You should have received a copy of the License with this software.
154919Sxy150489 * You can obtain a copy of the License at
164919Sxy150489 * http://www.opensolaris.org/os/licensing.
174919Sxy150489 * See the License for the specific language governing permissions
184919Sxy150489 * and limitations under the License.
194919Sxy150489 */
204919Sxy150489
214919Sxy150489 /*
228479SChenlu.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
234919Sxy150489 * Use is subject to license terms of the CDDLv1.
244919Sxy150489 */
254919Sxy150489
264919Sxy150489 /*
2711020SMin.Xu@Sun.COM * IntelVersion: 1.49 v3-1-10-1_2009-9-18_Release14-6
284919Sxy150489 */
294919Sxy150489 #include "e1000_api.h"
304919Sxy150489
318479SChenlu.Chen@Sun.COM static void e1000_reload_nvm_generic(struct e1000_hw *hw);
328479SChenlu.Chen@Sun.COM
334919Sxy150489 /*
346735Scc210113 * e1000_init_nvm_ops_generic - Initialize NVM function pointers
356735Scc210113 * @hw: pointer to the HW structure
366735Scc210113 *
376735Scc210113 * Setups up the function pointers to no-op functions
386735Scc210113 */
396735Scc210113 void
e1000_init_nvm_ops_generic(struct e1000_hw * hw)406735Scc210113 e1000_init_nvm_ops_generic(struct e1000_hw *hw)
416735Scc210113 {
426735Scc210113 struct e1000_nvm_info *nvm = &hw->nvm;
436735Scc210113 DEBUGFUNC("e1000_init_nvm_ops_generic");
446735Scc210113
456735Scc210113 /* Initialize function pointers */
466735Scc210113 nvm->ops.init_params = e1000_null_ops_generic;
476735Scc210113 nvm->ops.acquire = e1000_null_ops_generic;
486735Scc210113 nvm->ops.read = e1000_null_read_nvm;
496735Scc210113 nvm->ops.release = e1000_null_nvm_generic;
506735Scc210113 nvm->ops.reload = e1000_reload_nvm_generic;
516735Scc210113 nvm->ops.update = e1000_null_ops_generic;
526735Scc210113 nvm->ops.valid_led_default = e1000_null_led_default;
536735Scc210113 nvm->ops.validate = e1000_null_ops_generic;
546735Scc210113 nvm->ops.write = e1000_null_write_nvm;
556735Scc210113 }
566735Scc210113
576735Scc210113 /*
586735Scc210113 * e1000_null_nvm_read - No-op function, return 0
596735Scc210113 * @hw: pointer to the HW structure
606735Scc210113 */
616735Scc210113 s32
e1000_null_read_nvm(struct e1000_hw * hw,u16 a,u16 b,u16 * c)626735Scc210113 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c)
636735Scc210113 {
646735Scc210113 DEBUGFUNC("e1000_null_read_nvm");
656735Scc210113 UNREFERENCED_4PARAMETER(hw, a, b, c);
666735Scc210113 return (E1000_SUCCESS);
676735Scc210113 }
686735Scc210113
696735Scc210113 /*
706735Scc210113 * e1000_null_nvm_generic - No-op function, return void
716735Scc210113 * @hw: pointer to the HW structure
726735Scc210113 */
736735Scc210113 void
e1000_null_nvm_generic(struct e1000_hw * hw)746735Scc210113 e1000_null_nvm_generic(struct e1000_hw *hw)
756735Scc210113 {
766735Scc210113 DEBUGFUNC("e1000_null_nvm_generic");
776735Scc210113 UNREFERENCED_1PARAMETER(hw);
786735Scc210113 }
796735Scc210113
806735Scc210113 /*
816735Scc210113 * e1000_null_led_default - No-op function, return 0
826735Scc210113 * @hw: pointer to the HW structure
836735Scc210113 */
846735Scc210113 s32
e1000_null_led_default(struct e1000_hw * hw,u16 * data)856735Scc210113 e1000_null_led_default(struct e1000_hw *hw, u16 *data)
866735Scc210113 {
876735Scc210113 DEBUGFUNC("e1000_null_led_default");
886735Scc210113 UNREFERENCED_2PARAMETER(hw, data);
896735Scc210113 return (E1000_SUCCESS);
906735Scc210113 }
916735Scc210113
926735Scc210113 /*
936735Scc210113 * e1000_null_write_nvm - No-op function, return 0
946735Scc210113 * @hw: pointer to the HW structure
956735Scc210113 */
966735Scc210113 s32
e1000_null_write_nvm(struct e1000_hw * hw,u16 a,u16 b,u16 * c)976735Scc210113 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c)
986735Scc210113 {
996735Scc210113 DEBUGFUNC("e1000_null_write_nvm");
1006735Scc210113 UNREFERENCED_4PARAMETER(hw, a, b, c);
1016735Scc210113 return (E1000_SUCCESS);
1026735Scc210113 }
1036735Scc210113
1046735Scc210113 /*
1054919Sxy150489 * e1000_raise_eec_clk - Raise EEPROM clock
1064919Sxy150489 * @hw: pointer to the HW structure
1074919Sxy150489 * @eecd: pointer to the EEPROM
1084919Sxy150489 *
1094919Sxy150489 * Enable/Raise the EEPROM clock bit.
1104919Sxy150489 */
1114919Sxy150489 static void
e1000_raise_eec_clk(struct e1000_hw * hw,u32 * eecd)1124919Sxy150489 e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
1134919Sxy150489 {
1144919Sxy150489 *eecd = *eecd | E1000_EECD_SK;
1154919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, *eecd);
1164919Sxy150489 E1000_WRITE_FLUSH(hw);
1174919Sxy150489 usec_delay(hw->nvm.delay_usec);
1184919Sxy150489 }
1194919Sxy150489
1204919Sxy150489 /*
1214919Sxy150489 * e1000_lower_eec_clk - Lower EEPROM clock
1224919Sxy150489 * @hw: pointer to the HW structure
1234919Sxy150489 * @eecd: pointer to the EEPROM
1244919Sxy150489 *
1254919Sxy150489 * Clear/Lower the EEPROM clock bit.
1264919Sxy150489 */
1274919Sxy150489 static void
e1000_lower_eec_clk(struct e1000_hw * hw,u32 * eecd)1286735Scc210113 e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
1294919Sxy150489 {
1304919Sxy150489 *eecd = *eecd & ~E1000_EECD_SK;
1314919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, *eecd);
1324919Sxy150489 E1000_WRITE_FLUSH(hw);
1334919Sxy150489 usec_delay(hw->nvm.delay_usec);
1344919Sxy150489 }
1354919Sxy150489
1364919Sxy150489 /*
1374919Sxy150489 * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
1384919Sxy150489 * @hw: pointer to the HW structure
1394919Sxy150489 * @data: data to send to the EEPROM
1404919Sxy150489 * @count: number of bits to shift out
1414919Sxy150489 *
1424919Sxy150489 * We need to shift 'count' bits out to the EEPROM. So, the value in the
1434919Sxy150489 * "data" parameter will be shifted out to the EEPROM one bit at a time.
1444919Sxy150489 * In order to do this, "data" must be broken down into bits.
1454919Sxy150489 */
1464919Sxy150489 static void
e1000_shift_out_eec_bits(struct e1000_hw * hw,u16 data,u16 count)1474919Sxy150489 e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
1484919Sxy150489 {
1494919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
1504919Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1514919Sxy150489 u32 mask;
1524919Sxy150489
1534919Sxy150489 DEBUGFUNC("e1000_shift_out_eec_bits");
1544919Sxy150489
1554919Sxy150489 mask = 0x01 << (count - 1);
1564919Sxy150489 if (nvm->type == e1000_nvm_eeprom_microwire)
1574919Sxy150489 eecd &= ~E1000_EECD_DO;
1584919Sxy150489 else if (nvm->type == e1000_nvm_eeprom_spi)
1594919Sxy150489 eecd |= E1000_EECD_DO;
1604919Sxy150489
1614919Sxy150489 do {
1624919Sxy150489 eecd &= ~E1000_EECD_DI;
1634919Sxy150489
1644919Sxy150489 if (data & mask)
1654919Sxy150489 eecd |= E1000_EECD_DI;
1664919Sxy150489
1674919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
1684919Sxy150489 E1000_WRITE_FLUSH(hw);
1694919Sxy150489
1704919Sxy150489 usec_delay(nvm->delay_usec);
1714919Sxy150489
1724919Sxy150489 e1000_raise_eec_clk(hw, &eecd);
1734919Sxy150489 e1000_lower_eec_clk(hw, &eecd);
1744919Sxy150489
1754919Sxy150489 mask >>= 1;
1764919Sxy150489 } while (mask);
1774919Sxy150489
1784919Sxy150489 eecd &= ~E1000_EECD_DI;
1794919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
1804919Sxy150489 }
1814919Sxy150489
1824919Sxy150489 /*
1834919Sxy150489 * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
1844919Sxy150489 * @hw: pointer to the HW structure
1854919Sxy150489 * @count: number of bits to shift in
1864919Sxy150489 *
1874919Sxy150489 * In order to read a register from the EEPROM, we need to shift 'count' bits
1884919Sxy150489 * in from the EEPROM. Bits are "shifted in" by raising the clock input to
1894919Sxy150489 * the EEPROM (setting the SK bit), and then reading the value of the data out
1904919Sxy150489 * "DO" bit. During this "shifting in" process the data in "DI" bit should
1914919Sxy150489 * always be clear.
1924919Sxy150489 */
1934919Sxy150489 static u16
e1000_shift_in_eec_bits(struct e1000_hw * hw,u16 count)1944919Sxy150489 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
1954919Sxy150489 {
1964919Sxy150489 u32 eecd;
1974919Sxy150489 u32 i;
1984919Sxy150489 u16 data;
1994919Sxy150489
2004919Sxy150489 DEBUGFUNC("e1000_shift_in_eec_bits");
2014919Sxy150489
2024919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
2034919Sxy150489
2044919Sxy150489 eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
2054919Sxy150489 data = 0;
2064919Sxy150489
2074919Sxy150489 for (i = 0; i < count; i++) {
2084919Sxy150489 data <<= 1;
2094919Sxy150489 e1000_raise_eec_clk(hw, &eecd);
2104919Sxy150489
2114919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
2124919Sxy150489
2134919Sxy150489 eecd &= ~E1000_EECD_DI;
2144919Sxy150489 if (eecd & E1000_EECD_DO)
2154919Sxy150489 data |= 1;
2164919Sxy150489
2174919Sxy150489 e1000_lower_eec_clk(hw, &eecd);
2184919Sxy150489 }
2194919Sxy150489
2204919Sxy150489 return (data);
2214919Sxy150489 }
2224919Sxy150489
2234919Sxy150489 /*
2244919Sxy150489 * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion
2254919Sxy150489 * @hw: pointer to the HW structure
2264919Sxy150489 * @ee_reg: EEPROM flag for polling
2274919Sxy150489 *
2284919Sxy150489 * Polls the EEPROM status bit for either read or write completion based
2294919Sxy150489 * upon the value of 'ee_reg'.
2304919Sxy150489 */
2314919Sxy150489 s32
e1000_poll_eerd_eewr_done(struct e1000_hw * hw,int ee_reg)2324919Sxy150489 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
2334919Sxy150489 {
2344919Sxy150489 u32 attempts = 100000;
2354919Sxy150489 u32 i, reg = 0;
2364919Sxy150489 s32 ret_val = -E1000_ERR_NVM;
2374919Sxy150489
2384919Sxy150489 DEBUGFUNC("e1000_poll_eerd_eewr_done");
2394919Sxy150489
2404919Sxy150489 for (i = 0; i < attempts; i++) {
2414919Sxy150489 if (ee_reg == E1000_NVM_POLL_READ)
2424919Sxy150489 reg = E1000_READ_REG(hw, E1000_EERD);
2434919Sxy150489 else
2444919Sxy150489 reg = E1000_READ_REG(hw, E1000_EEWR);
2454919Sxy150489
2464919Sxy150489 if (reg & E1000_NVM_RW_REG_DONE) {
2474919Sxy150489 ret_val = E1000_SUCCESS;
2484919Sxy150489 break;
2494919Sxy150489 }
2504919Sxy150489
2514919Sxy150489 usec_delay(5);
2524919Sxy150489 }
2534919Sxy150489
2544919Sxy150489 return (ret_val);
2554919Sxy150489 }
2564919Sxy150489
2574919Sxy150489 /*
2584919Sxy150489 * e1000_acquire_nvm_generic - Generic request for access to EEPROM
2594919Sxy150489 * @hw: pointer to the HW structure
2604919Sxy150489 *
2614919Sxy150489 * Set the EEPROM access request bit and wait for EEPROM access grant bit.
2624919Sxy150489 * Return successful if access grant bit set, else clear the request for
2634919Sxy150489 * EEPROM access and return -E1000_ERR_NVM (-1).
2644919Sxy150489 */
2654919Sxy150489 s32
e1000_acquire_nvm_generic(struct e1000_hw * hw)2664919Sxy150489 e1000_acquire_nvm_generic(struct e1000_hw *hw)
2674919Sxy150489 {
2684919Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD);
2694919Sxy150489 s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
2704919Sxy150489 s32 ret_val = E1000_SUCCESS;
2714919Sxy150489
2724919Sxy150489 DEBUGFUNC("e1000_acquire_nvm_generic");
2734919Sxy150489
2744919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ);
2754919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
2764919Sxy150489
2774919Sxy150489 while (timeout) {
2784919Sxy150489 if (eecd & E1000_EECD_GNT)
2794919Sxy150489 break;
2804919Sxy150489 usec_delay(5);
2814919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
2824919Sxy150489 timeout--;
2834919Sxy150489 }
2844919Sxy150489
2854919Sxy150489 if (!timeout) {
2864919Sxy150489 eecd &= ~E1000_EECD_REQ;
2874919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
2884919Sxy150489 DEBUGOUT("Could not acquire NVM grant\n");
2894919Sxy150489 ret_val = -E1000_ERR_NVM;
2904919Sxy150489 }
2914919Sxy150489 return (ret_val);
2924919Sxy150489 }
2934919Sxy150489
2944919Sxy150489 /*
2954919Sxy150489 * e1000_standby_nvm - Return EEPROM to standby state
2964919Sxy150489 * @hw: pointer to the HW structure
2974919Sxy150489 *
2984919Sxy150489 * Return the EEPROM to a standby state.
2994919Sxy150489 */
3004919Sxy150489 static void
e1000_standby_nvm(struct e1000_hw * hw)3014919Sxy150489 e1000_standby_nvm(struct e1000_hw *hw)
3024919Sxy150489 {
3034919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
3044919Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD);
3054919Sxy150489
3064919Sxy150489 DEBUGFUNC("e1000_standby_nvm");
3074919Sxy150489
3084919Sxy150489 if (nvm->type == e1000_nvm_eeprom_microwire) {
3094919Sxy150489 eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
3104919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
3114919Sxy150489 E1000_WRITE_FLUSH(hw);
3124919Sxy150489 usec_delay(nvm->delay_usec);
3134919Sxy150489
3144919Sxy150489 e1000_raise_eec_clk(hw, &eecd);
3154919Sxy150489
3164919Sxy150489 /* Select EEPROM */
3174919Sxy150489 eecd |= E1000_EECD_CS;
3184919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
3194919Sxy150489 E1000_WRITE_FLUSH(hw);
3204919Sxy150489 usec_delay(nvm->delay_usec);
3214919Sxy150489
3224919Sxy150489 e1000_lower_eec_clk(hw, &eecd);
3234919Sxy150489 } else if (nvm->type == e1000_nvm_eeprom_spi) {
3244919Sxy150489 /* Toggle CS to flush commands */
3254919Sxy150489 eecd |= E1000_EECD_CS;
3264919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
3274919Sxy150489 E1000_WRITE_FLUSH(hw);
3284919Sxy150489 usec_delay(nvm->delay_usec);
3294919Sxy150489 eecd &= ~E1000_EECD_CS;
3304919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
3314919Sxy150489 E1000_WRITE_FLUSH(hw);
3324919Sxy150489 usec_delay(nvm->delay_usec);
3334919Sxy150489 }
3344919Sxy150489 }
3354919Sxy150489
3364919Sxy150489 /*
3374919Sxy150489 * e1000_stop_nvm - Terminate EEPROM command
3384919Sxy150489 * @hw: pointer to the HW structure
3394919Sxy150489 *
3404919Sxy150489 * Terminates the current command by inverting the EEPROM's chip select pin.
3414919Sxy150489 */
3424919Sxy150489 void
e1000_stop_nvm(struct e1000_hw * hw)3434919Sxy150489 e1000_stop_nvm(struct e1000_hw *hw)
3444919Sxy150489 {
3454919Sxy150489 u32 eecd;
3464919Sxy150489
3474919Sxy150489 DEBUGFUNC("e1000_stop_nvm");
3484919Sxy150489
3494919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
3504919Sxy150489 if (hw->nvm.type == e1000_nvm_eeprom_spi) {
3514919Sxy150489 /* Pull CS high */
3524919Sxy150489 eecd |= E1000_EECD_CS;
3534919Sxy150489 e1000_lower_eec_clk(hw, &eecd);
3544919Sxy150489 } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
3556735Scc210113 /* CS on Microwire is active-high */
3564919Sxy150489 eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
3574919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
3584919Sxy150489 e1000_raise_eec_clk(hw, &eecd);
3594919Sxy150489 e1000_lower_eec_clk(hw, &eecd);
3604919Sxy150489 }
3614919Sxy150489 }
3624919Sxy150489
3634919Sxy150489 /*
3644919Sxy150489 * e1000_release_nvm_generic - Release exclusive access to EEPROM
3654919Sxy150489 * @hw: pointer to the HW structure
3664919Sxy150489 *
3674919Sxy150489 * Stop any current commands to the EEPROM and clear the EEPROM request bit.
3684919Sxy150489 */
3694919Sxy150489 void
e1000_release_nvm_generic(struct e1000_hw * hw)3704919Sxy150489 e1000_release_nvm_generic(struct e1000_hw *hw)
3714919Sxy150489 {
3724919Sxy150489 u32 eecd;
3734919Sxy150489
3744919Sxy150489 DEBUGFUNC("e1000_release_nvm_generic");
3754919Sxy150489
3764919Sxy150489 e1000_stop_nvm(hw);
3774919Sxy150489
3784919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
3794919Sxy150489 eecd &= ~E1000_EECD_REQ;
3804919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
3814919Sxy150489 }
3824919Sxy150489
3834919Sxy150489 /*
3844919Sxy150489 * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
3854919Sxy150489 * @hw: pointer to the HW structure
3864919Sxy150489 *
3874919Sxy150489 * Setups the EEPROM for reading and writing.
3884919Sxy150489 */
3894919Sxy150489 static s32
e1000_ready_nvm_eeprom(struct e1000_hw * hw)3904919Sxy150489 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
3914919Sxy150489 {
3924919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
3934919Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD);
3944919Sxy150489 s32 ret_val = E1000_SUCCESS;
3954919Sxy150489 u16 timeout = 0;
3964919Sxy150489 u8 spi_stat_reg;
3974919Sxy150489
3984919Sxy150489 DEBUGFUNC("e1000_ready_nvm_eeprom");
3994919Sxy150489
4004919Sxy150489 if (nvm->type == e1000_nvm_eeprom_microwire) {
4014919Sxy150489 /* Clear SK and DI */
4024919Sxy150489 eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
4034919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
4044919Sxy150489 /* Set CS */
4054919Sxy150489 eecd |= E1000_EECD_CS;
4064919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
4074919Sxy150489 } else if (nvm->type == e1000_nvm_eeprom_spi) {
4084919Sxy150489 /* Clear SK and CS */
4094919Sxy150489 eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
4104919Sxy150489 E1000_WRITE_REG(hw, E1000_EECD, eecd);
4114919Sxy150489 usec_delay(1);
4124919Sxy150489 timeout = NVM_MAX_RETRY_SPI;
4134919Sxy150489
4144919Sxy150489 /*
4154919Sxy150489 * Read "Status Register" repeatedly until the LSB is cleared.
4164919Sxy150489 * The EEPROM will signal that the command has been completed
4174919Sxy150489 * by clearing bit 0 of the internal status register. If it's
4184919Sxy150489 * not cleared within 'timeout', then error out.
4194919Sxy150489 */
4204919Sxy150489 while (timeout) {
4214919Sxy150489 e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
4224919Sxy150489 hw->nvm.opcode_bits);
4234919Sxy150489 spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
4244919Sxy150489 if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
4254919Sxy150489 break;
4264919Sxy150489
4274919Sxy150489 usec_delay(5);
4284919Sxy150489 e1000_standby_nvm(hw);
4294919Sxy150489 timeout--;
4304919Sxy150489 }
4314919Sxy150489
4324919Sxy150489 if (!timeout) {
4334919Sxy150489 DEBUGOUT("SPI NVM Status error\n");
4344919Sxy150489 ret_val = -E1000_ERR_NVM;
4354919Sxy150489 goto out;
4364919Sxy150489 }
4374919Sxy150489 }
4384919Sxy150489
4394919Sxy150489 out:
4404919Sxy150489 return (ret_val);
4414919Sxy150489 }
4424919Sxy150489
4434919Sxy150489 /*
4444919Sxy150489 * e1000_read_nvm_spi - Read EEPROM's using SPI
4454919Sxy150489 * @hw: pointer to the HW structure
4464919Sxy150489 * @offset: offset of word in the EEPROM to read
4474919Sxy150489 * @words: number of words to read
4484919Sxy150489 * @data: word read from the EEPROM
4494919Sxy150489 *
4504919Sxy150489 * Reads a 16 bit word from the EEPROM.
4514919Sxy150489 */
4524919Sxy150489 s32
e1000_read_nvm_spi(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)4534919Sxy150489 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 * data)
4544919Sxy150489 {
4554919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
4564919Sxy150489 u32 i = 0;
4574919Sxy150489 s32 ret_val;
4584919Sxy150489 u16 word_in;
4594919Sxy150489 u8 read_opcode = NVM_READ_OPCODE_SPI;
4604919Sxy150489
4614919Sxy150489 DEBUGFUNC("e1000_read_nvm_spi");
4624919Sxy150489
4634919Sxy150489 /*
4644919Sxy150489 * A check for invalid values: offset too large, too many words, and
4654919Sxy150489 * not enough words.
4664919Sxy150489 */
4674919Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
4684919Sxy150489 (words == 0)) {
4694919Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n");
4704919Sxy150489 ret_val = -E1000_ERR_NVM;
4714919Sxy150489 goto out;
4724919Sxy150489 }
4734919Sxy150489
4746735Scc210113 ret_val = nvm->ops.acquire(hw);
4754919Sxy150489 if (ret_val)
4764919Sxy150489 goto out;
4774919Sxy150489
4784919Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw);
4794919Sxy150489 if (ret_val)
4804919Sxy150489 goto release;
4814919Sxy150489
4824919Sxy150489 e1000_standby_nvm(hw);
4834919Sxy150489
4844919Sxy150489 if ((nvm->address_bits == 8) && (offset >= 128))
4854919Sxy150489 read_opcode |= NVM_A8_OPCODE_SPI;
4864919Sxy150489
4874919Sxy150489 /* Send the READ command (opcode + addr) */
4884919Sxy150489 e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
4894919Sxy150489 e1000_shift_out_eec_bits(hw, (u16)(offset * 2), nvm->address_bits);
4904919Sxy150489
4914919Sxy150489 /*
4924919Sxy150489 * Read the data. SPI NVMs increment the address with each byte read
4934919Sxy150489 * and will roll over if reading beyond the end. This allows us to
4944919Sxy150489 * read the whole NVM from any offset
4954919Sxy150489 */
4964919Sxy150489 for (i = 0; i < words; i++) {
4974919Sxy150489 word_in = e1000_shift_in_eec_bits(hw, 16);
4984919Sxy150489 data[i] = (word_in >> 8) | (word_in << 8);
4994919Sxy150489 }
5004919Sxy150489
5014919Sxy150489 release:
5026735Scc210113 nvm->ops.release(hw);
5034919Sxy150489
5044919Sxy150489 out:
5054919Sxy150489 return (ret_val);
5064919Sxy150489 }
5074919Sxy150489
5084919Sxy150489 /*
5094919Sxy150489 * e1000_read_nvm_microwire - Reads EEPROM's using microwire
5104919Sxy150489 * @hw: pointer to the HW structure
5114919Sxy150489 * @offset: offset of word in the EEPROM to read
5124919Sxy150489 * @words: number of words to read
5134919Sxy150489 * @data: word read from the EEPROM
5144919Sxy150489 *
5154919Sxy150489 * Reads a 16 bit word from the EEPROM.
5164919Sxy150489 */
5174919Sxy150489 s32
e1000_read_nvm_microwire(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)5184919Sxy150489 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
5194919Sxy150489 {
5204919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
5214919Sxy150489 u32 i = 0;
5224919Sxy150489 s32 ret_val;
5234919Sxy150489 u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
5244919Sxy150489
5254919Sxy150489 DEBUGFUNC("e1000_read_nvm_microwire");
5264919Sxy150489
5274919Sxy150489 /*
5284919Sxy150489 * A check for invalid values: offset too large, too many words, and
5294919Sxy150489 * not enough words.
5304919Sxy150489 */
5314919Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
5324919Sxy150489 (words == 0)) {
5334919Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n");
5344919Sxy150489 ret_val = -E1000_ERR_NVM;
5354919Sxy150489 goto out;
5364919Sxy150489 }
5374919Sxy150489
5386735Scc210113 ret_val = nvm->ops.acquire(hw);
5394919Sxy150489 if (ret_val)
5404919Sxy150489 goto out;
5414919Sxy150489
5424919Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw);
5434919Sxy150489 if (ret_val)
5444919Sxy150489 goto release;
5454919Sxy150489
5464919Sxy150489 for (i = 0; i < words; i++) {
5474919Sxy150489 /* Send the READ command (opcode + addr) */
5484919Sxy150489 e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
5494919Sxy150489 e1000_shift_out_eec_bits(hw, (u16)(offset + i),
5504919Sxy150489 nvm->address_bits);
5514919Sxy150489
5524919Sxy150489 /*
5534919Sxy150489 * Read the data. For microwire, each word requires the
5544919Sxy150489 * overhead of setup and tear-down.
5554919Sxy150489 */
5564919Sxy150489 data[i] = e1000_shift_in_eec_bits(hw, 16);
5574919Sxy150489 e1000_standby_nvm(hw);
5584919Sxy150489 }
5594919Sxy150489
5604919Sxy150489 release:
5616735Scc210113 nvm->ops.release(hw);
5624919Sxy150489
5634919Sxy150489 out:
5644919Sxy150489 return (ret_val);
5654919Sxy150489 }
5664919Sxy150489
5674919Sxy150489 /*
5684919Sxy150489 * e1000_read_nvm_eerd - Reads EEPROM using EERD register
5694919Sxy150489 * @hw: pointer to the HW structure
5704919Sxy150489 * @offset: offset of word in the EEPROM to read
5714919Sxy150489 * @words: number of words to read
5724919Sxy150489 * @data: word read from the EEPROM
5734919Sxy150489 *
5744919Sxy150489 * Reads a 16 bit word from the EEPROM using the EERD register.
5754919Sxy150489 */
5764919Sxy150489 s32
e1000_read_nvm_eerd(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)5774919Sxy150489 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
5784919Sxy150489 {
5794919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
5804919Sxy150489 u32 i, eerd = 0;
5814919Sxy150489 s32 ret_val = E1000_SUCCESS;
5824919Sxy150489
5834919Sxy150489 DEBUGFUNC("e1000_read_nvm_eerd");
5844919Sxy150489
5854919Sxy150489 /*
5866735Scc210113 * A check for invalid values: offset too large, too many words,
5876735Scc210113 * too many words for the offset, and not enough words.
5884919Sxy150489 */
5894919Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
5904919Sxy150489 (words == 0)) {
5914919Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n");
5924919Sxy150489 ret_val = -E1000_ERR_NVM;
5934919Sxy150489 goto out;
5944919Sxy150489 }
5954919Sxy150489
5964919Sxy150489 for (i = 0; i < words; i++) {
5974919Sxy150489 eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) +
5984919Sxy150489 E1000_NVM_RW_REG_START;
5994919Sxy150489
6004919Sxy150489 E1000_WRITE_REG(hw, E1000_EERD, eerd);
6014919Sxy150489 ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
6024919Sxy150489 if (ret_val)
6034919Sxy150489 break;
6044919Sxy150489
6054919Sxy150489 data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
6064919Sxy150489 E1000_NVM_RW_REG_DATA);
6074919Sxy150489 }
6084919Sxy150489
6094919Sxy150489 out:
6104919Sxy150489 return (ret_val);
6114919Sxy150489 }
6124919Sxy150489
6134919Sxy150489 /*
6144919Sxy150489 * e1000_write_nvm_spi - Write to EEPROM using SPI
6154919Sxy150489 * @hw: pointer to the HW structure
6164919Sxy150489 * @offset: offset within the EEPROM to be written to
6174919Sxy150489 * @words: number of words to write
6184919Sxy150489 * @data: 16 bit word(s) to be written to the EEPROM
6194919Sxy150489 *
6204919Sxy150489 * Writes data to EEPROM at offset using SPI interface.
6214919Sxy150489 *
6224919Sxy150489 * If e1000_update_nvm_checksum is not called after this function , the
6236735Scc210113 * EEPROM will most likely contain an invalid checksum.
6244919Sxy150489 */
6254919Sxy150489 s32
e1000_write_nvm_spi(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)6266735Scc210113 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
6274919Sxy150489 {
6284919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
6294919Sxy150489 s32 ret_val;
6304919Sxy150489 u16 widx = 0;
6314919Sxy150489
6324919Sxy150489 DEBUGFUNC("e1000_write_nvm_spi");
6334919Sxy150489
6344919Sxy150489 /*
6354919Sxy150489 * A check for invalid values: offset too large, too many words, and
6364919Sxy150489 * not enough words.
6374919Sxy150489 */
6384919Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
6394919Sxy150489 (words == 0)) {
6404919Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n");
6414919Sxy150489 ret_val = -E1000_ERR_NVM;
6424919Sxy150489 goto out;
6434919Sxy150489 }
6444919Sxy150489
6456735Scc210113 ret_val = nvm->ops.acquire(hw);
6464919Sxy150489 if (ret_val)
6474919Sxy150489 goto out;
6484919Sxy150489
6494919Sxy150489 while (widx < words) {
6504919Sxy150489 u8 write_opcode = NVM_WRITE_OPCODE_SPI;
6514919Sxy150489
6524919Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw);
6534919Sxy150489 if (ret_val)
6544919Sxy150489 goto release;
6554919Sxy150489
6564919Sxy150489 e1000_standby_nvm(hw);
6574919Sxy150489
6584919Sxy150489 /* Send the WRITE ENABLE command (8 bit opcode) */
6594919Sxy150489 e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
6604919Sxy150489 nvm->opcode_bits);
6614919Sxy150489
6624919Sxy150489 e1000_standby_nvm(hw);
6634919Sxy150489
6644919Sxy150489 /*
6654919Sxy150489 * Some SPI eeproms use the 8th address bit embedded in the
6664919Sxy150489 * opcode
6674919Sxy150489 */
6684919Sxy150489 if ((nvm->address_bits == 8) && (offset >= 128))
6694919Sxy150489 write_opcode |= NVM_A8_OPCODE_SPI;
6704919Sxy150489
6714919Sxy150489 /* Send the Write command (8-bit opcode + addr) */
6724919Sxy150489 e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
6734919Sxy150489 e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
6744919Sxy150489 nvm->address_bits);
6754919Sxy150489
6764919Sxy150489 /* Loop to allow for up to whole page write of eeprom */
6774919Sxy150489 while (widx < words) {
6784919Sxy150489 u16 word_out = data[widx];
6794919Sxy150489
6804919Sxy150489 word_out = (word_out >> 8) | (word_out << 8);
6814919Sxy150489 e1000_shift_out_eec_bits(hw, word_out, 16);
6824919Sxy150489 widx++;
6834919Sxy150489
6844919Sxy150489 if ((((offset + widx) * 2) % nvm->page_size) == 0) {
6854919Sxy150489 e1000_standby_nvm(hw);
6864919Sxy150489 break;
6874919Sxy150489 }
6884919Sxy150489 }
6894919Sxy150489 }
6904919Sxy150489
6918479SChenlu.Chen@Sun.COM msec_delay(10);
6924919Sxy150489 release:
6936735Scc210113 nvm->ops.release(hw);
6944919Sxy150489
6954919Sxy150489 out:
6964919Sxy150489 return (ret_val);
6974919Sxy150489 }
6984919Sxy150489
6994919Sxy150489 /*
7004919Sxy150489 * e1000_write_nvm_microwire - Writes EEPROM using microwire
7014919Sxy150489 * @hw: pointer to the HW structure
7024919Sxy150489 * @offset: offset within the EEPROM to be written to
7034919Sxy150489 * @words: number of words to write
7044919Sxy150489 * @data: 16 bit word(s) to be written to the EEPROM
7054919Sxy150489 *
7064919Sxy150489 * Writes data to EEPROM at offset using microwire interface.
7074919Sxy150489 *
7084919Sxy150489 * If e1000_update_nvm_checksum is not called after this function , the
7096735Scc210113 * EEPROM will most likely contain an invalid checksum.
7104919Sxy150489 */
7114919Sxy150489 s32
e1000_write_nvm_microwire(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)7124919Sxy150489 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
7134919Sxy150489 {
7144919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
7154919Sxy150489 s32 ret_val;
7164919Sxy150489 u32 eecd;
7174919Sxy150489 u16 words_written = 0;
7184919Sxy150489 u16 widx = 0;
7194919Sxy150489
7204919Sxy150489 DEBUGFUNC("e1000_write_nvm_microwire");
7214919Sxy150489
7224919Sxy150489 /*
7234919Sxy150489 * A check for invalid values: offset too large, too many words, and
7244919Sxy150489 * not enough words.
7254919Sxy150489 */
7264919Sxy150489 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
7274919Sxy150489 (words == 0)) {
7284919Sxy150489 DEBUGOUT("nvm parameter(s) out of bounds\n");
7294919Sxy150489 ret_val = -E1000_ERR_NVM;
7304919Sxy150489 goto out;
7314919Sxy150489 }
7324919Sxy150489
7336735Scc210113 ret_val = nvm->ops.acquire(hw);
7344919Sxy150489 if (ret_val)
7354919Sxy150489 goto out;
7364919Sxy150489
7374919Sxy150489 ret_val = e1000_ready_nvm_eeprom(hw);
7384919Sxy150489 if (ret_val)
7394919Sxy150489 goto release;
7404919Sxy150489
7414919Sxy150489 e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
7424919Sxy150489 (u16)(nvm->opcode_bits + 2));
7434919Sxy150489
7444919Sxy150489 e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
7454919Sxy150489
7464919Sxy150489 e1000_standby_nvm(hw);
7474919Sxy150489
7484919Sxy150489 while (words_written < words) {
7494919Sxy150489 e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
7504919Sxy150489 nvm->opcode_bits);
7514919Sxy150489
7524919Sxy150489 e1000_shift_out_eec_bits(hw, (u16)(offset + words_written),
7534919Sxy150489 nvm->address_bits);
7544919Sxy150489
7554919Sxy150489 e1000_shift_out_eec_bits(hw, data[words_written], 16);
7564919Sxy150489
7574919Sxy150489 e1000_standby_nvm(hw);
7584919Sxy150489
7594919Sxy150489 for (widx = 0; widx < 200; widx++) {
7604919Sxy150489 eecd = E1000_READ_REG(hw, E1000_EECD);
7614919Sxy150489 if (eecd & E1000_EECD_DO)
7624919Sxy150489 break;
7634919Sxy150489 usec_delay(50);
7644919Sxy150489 }
7654919Sxy150489
7664919Sxy150489 if (widx == 200) {
7674919Sxy150489 DEBUGOUT("NVM Write did not complete\n");
7684919Sxy150489 ret_val = -E1000_ERR_NVM;
7694919Sxy150489 goto release;
7704919Sxy150489 }
7714919Sxy150489
7724919Sxy150489 e1000_standby_nvm(hw);
7734919Sxy150489
7744919Sxy150489 words_written++;
7754919Sxy150489 }
7764919Sxy150489
7774919Sxy150489 e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
7784919Sxy150489 (u16)(nvm->opcode_bits + 2));
7794919Sxy150489
7804919Sxy150489 e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
7814919Sxy150489
7824919Sxy150489 release:
7836735Scc210113 nvm->ops.release(hw);
7844919Sxy150489
7854919Sxy150489 out:
7864919Sxy150489 return (ret_val);
7874919Sxy150489 }
7884919Sxy150489
7894919Sxy150489 /*
7906735Scc210113 * e1000_read_pba_num_generic - Read device part number
7914919Sxy150489 * @hw: pointer to the HW structure
7926735Scc210113 * @pba_num: pointer to device part number
7934919Sxy150489 *
7944919Sxy150489 * Reads the product board assembly (PBA) number from the EEPROM and stores
7956735Scc210113 * the value in pba_num.
7964919Sxy150489 */
7974919Sxy150489 s32
e1000_read_pba_num_generic(struct e1000_hw * hw,u32 * pba_num)7986735Scc210113 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num)
7994919Sxy150489 {
8004919Sxy150489 s32 ret_val;
8014919Sxy150489 u16 nvm_data;
8024919Sxy150489
8036735Scc210113 DEBUGFUNC("e1000_read_pba_num_generic");
8044919Sxy150489
8056735Scc210113 ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
8064919Sxy150489 if (ret_val) {
8074919Sxy150489 DEBUGOUT("NVM Read Error\n");
8084919Sxy150489 goto out;
8094919Sxy150489 }
8106735Scc210113 *pba_num = (u32)(nvm_data << 16);
8114919Sxy150489
8126735Scc210113 ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
8134919Sxy150489 if (ret_val) {
8144919Sxy150489 DEBUGOUT("NVM Read Error\n");
8154919Sxy150489 goto out;
8164919Sxy150489 }
8176735Scc210113 *pba_num |= nvm_data;
8184919Sxy150489
8194919Sxy150489 out:
8204919Sxy150489 return (ret_val);
8214919Sxy150489 }
8224919Sxy150489
8234919Sxy150489 /*
8244919Sxy150489 * e1000_read_mac_addr_generic - Read device MAC address
8254919Sxy150489 * @hw: pointer to the HW structure
8264919Sxy150489 *
8274919Sxy150489 * Reads the device MAC address from the EEPROM and stores the value.
8284919Sxy150489 * Since devices with two ports use the same EEPROM, we increment the
8294919Sxy150489 * last bit in the MAC address for the second port.
8304919Sxy150489 */
8314919Sxy150489 s32
e1000_read_mac_addr_generic(struct e1000_hw * hw)8324919Sxy150489 e1000_read_mac_addr_generic(struct e1000_hw *hw)
8334919Sxy150489 {
83410680SMin.Xu@Sun.COM u32 rar_high;
83510680SMin.Xu@Sun.COM u32 rar_low;
83610680SMin.Xu@Sun.COM u16 i;
8374919Sxy150489
83810680SMin.Xu@Sun.COM rar_high = E1000_READ_REG(hw, E1000_RAH(0));
83910680SMin.Xu@Sun.COM rar_low = E1000_READ_REG(hw, E1000_RAL(0));
8404919Sxy150489
84110680SMin.Xu@Sun.COM for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
84210680SMin.Xu@Sun.COM hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
84310680SMin.Xu@Sun.COM
84410680SMin.Xu@Sun.COM for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
84510680SMin.Xu@Sun.COM hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
8464919Sxy150489
8474919Sxy150489 for (i = 0; i < ETH_ADDR_LEN; i++)
8484919Sxy150489 hw->mac.addr[i] = hw->mac.perm_addr[i];
8494919Sxy150489
85010680SMin.Xu@Sun.COM return (E1000_SUCCESS);
8514919Sxy150489 }
8524919Sxy150489
8534919Sxy150489 /*
8544919Sxy150489 * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum
8554919Sxy150489 * @hw: pointer to the HW structure
8564919Sxy150489 *
8574919Sxy150489 * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
8584919Sxy150489 * and then verifies that the sum of the EEPROM is equal to 0xBABA.
8594919Sxy150489 */
8604919Sxy150489 s32
e1000_validate_nvm_checksum_generic(struct e1000_hw * hw)8614919Sxy150489 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
8624919Sxy150489 {
8634919Sxy150489 s32 ret_val = E1000_SUCCESS;
8644919Sxy150489 u16 checksum = 0;
8654919Sxy150489 u16 i, nvm_data;
8664919Sxy150489
8674919Sxy150489 DEBUGFUNC("e1000_validate_nvm_checksum_generic");
8684919Sxy150489
8694919Sxy150489 for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
8706735Scc210113 ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
8714919Sxy150489 if (ret_val) {
8724919Sxy150489 DEBUGOUT("NVM Read Error\n");
8734919Sxy150489 goto out;
8744919Sxy150489 }
8754919Sxy150489 checksum += nvm_data;
8764919Sxy150489 }
8774919Sxy150489
8784919Sxy150489 if (checksum != (u16)NVM_SUM) {
8794919Sxy150489 DEBUGOUT("NVM Checksum Invalid\n");
8804919Sxy150489 ret_val = -E1000_ERR_NVM;
8814919Sxy150489 goto out;
8824919Sxy150489 }
8834919Sxy150489
8844919Sxy150489 out:
8854919Sxy150489 return (ret_val);
8864919Sxy150489 }
8874919Sxy150489
8884919Sxy150489 /*
8894919Sxy150489 * e1000_update_nvm_checksum_generic - Update EEPROM checksum
8904919Sxy150489 * @hw: pointer to the HW structure
8914919Sxy150489 *
8924919Sxy150489 * Updates the EEPROM checksum by reading/adding each word of the EEPROM
8934919Sxy150489 * up to the checksum. Then calculates the EEPROM checksum and writes the
8944919Sxy150489 * value to the EEPROM.
8954919Sxy150489 */
8964919Sxy150489 s32
e1000_update_nvm_checksum_generic(struct e1000_hw * hw)8974919Sxy150489 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
8984919Sxy150489 {
8994919Sxy150489 s32 ret_val;
9004919Sxy150489 u16 checksum = 0;
9014919Sxy150489 u16 i, nvm_data;
9024919Sxy150489
9034919Sxy150489 DEBUGFUNC("e1000_update_nvm_checksum");
9044919Sxy150489
9054919Sxy150489 for (i = 0; i < NVM_CHECKSUM_REG; i++) {
9066735Scc210113 ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
9074919Sxy150489 if (ret_val) {
9084919Sxy150489 DEBUGOUT("NVM Read Error while updating checksum.\n");
9094919Sxy150489 goto out;
9104919Sxy150489 }
9114919Sxy150489 checksum += nvm_data;
9124919Sxy150489 }
9134919Sxy150489 checksum = (u16)NVM_SUM - checksum;
9146735Scc210113 ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
915*11143SGuoqing.Zhu@Sun.COM if (ret_val) {
916*11143SGuoqing.Zhu@Sun.COM /* EMPTY */
9174919Sxy150489 DEBUGOUT("NVM Write Error while updating checksum.\n");
918*11143SGuoqing.Zhu@Sun.COM }
9194919Sxy150489
9204919Sxy150489 out:
9214919Sxy150489 return (ret_val);
9224919Sxy150489 }
9234919Sxy150489
9244919Sxy150489 /*
9254919Sxy150489 * e1000_reload_nvm_generic - Reloads EEPROM
9264919Sxy150489 * @hw: pointer to the HW structure
9274919Sxy150489 *
9284919Sxy150489 * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
9294919Sxy150489 * extended control register.
9304919Sxy150489 */
9314919Sxy150489 void
e1000_reload_nvm_generic(struct e1000_hw * hw)9324919Sxy150489 e1000_reload_nvm_generic(struct e1000_hw *hw)
9334919Sxy150489 {
9344919Sxy150489 u32 ctrl_ext;
9354919Sxy150489
9364919Sxy150489 DEBUGFUNC("e1000_reload_nvm_generic");
9374919Sxy150489
9384919Sxy150489 usec_delay(10);
9394919Sxy150489 ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
9404919Sxy150489 ctrl_ext |= E1000_CTRL_EXT_EE_RST;
9414919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
9424919Sxy150489 E1000_WRITE_FLUSH(hw);
9434919Sxy150489 }
944