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