xref: /onnv-gate/usr/src/uts/common/io/e1000g/e1000_nvm.c (revision 11143:f855b68211a7)
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