175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi 
3*49b78600SRobert Mustacchi   Copyright (c) 2001-2015, Intel Corporation
475eba5b6SRobert Mustacchi   All rights reserved.
575eba5b6SRobert Mustacchi 
675eba5b6SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
775eba5b6SRobert Mustacchi   modification, are permitted provided that the following conditions are met:
875eba5b6SRobert Mustacchi 
975eba5b6SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1075eba5b6SRobert Mustacchi       this list of conditions and the following disclaimer.
1175eba5b6SRobert Mustacchi 
1275eba5b6SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
1375eba5b6SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1475eba5b6SRobert Mustacchi       documentation and/or other materials provided with the distribution.
1575eba5b6SRobert Mustacchi 
1675eba5b6SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
1775eba5b6SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1875eba5b6SRobert Mustacchi       this software without specific prior written permission.
1975eba5b6SRobert Mustacchi 
2075eba5b6SRobert Mustacchi   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2175eba5b6SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2275eba5b6SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2375eba5b6SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2475eba5b6SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2575eba5b6SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2675eba5b6SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2775eba5b6SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2875eba5b6SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2975eba5b6SRobert Mustacchi   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3075eba5b6SRobert Mustacchi   POSSIBILITY OF SUCH DAMAGE.
3175eba5b6SRobert Mustacchi 
3275eba5b6SRobert Mustacchi ******************************************************************************/
3375eba5b6SRobert Mustacchi /*$FreeBSD$*/
3475eba5b6SRobert Mustacchi 
3575eba5b6SRobert Mustacchi #include "e1000_api.h"
3675eba5b6SRobert Mustacchi 
3775eba5b6SRobert Mustacchi static void e1000_reload_nvm_generic(struct e1000_hw *hw);
3875eba5b6SRobert Mustacchi 
3975eba5b6SRobert Mustacchi /**
4075eba5b6SRobert Mustacchi  *  e1000_init_nvm_ops_generic - Initialize NVM function pointers
4175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
4275eba5b6SRobert Mustacchi  *
4375eba5b6SRobert Mustacchi  *  Setups up the function pointers to no-op functions
4475eba5b6SRobert Mustacchi  **/
e1000_init_nvm_ops_generic(struct e1000_hw * hw)4575eba5b6SRobert Mustacchi void e1000_init_nvm_ops_generic(struct e1000_hw *hw)
4675eba5b6SRobert Mustacchi {
4775eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
4875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_nvm_ops_generic");
4975eba5b6SRobert Mustacchi 
5075eba5b6SRobert Mustacchi 	/* Initialize function pointers */
5175eba5b6SRobert Mustacchi 	nvm->ops.init_params = e1000_null_ops_generic;
5275eba5b6SRobert Mustacchi 	nvm->ops.acquire = e1000_null_ops_generic;
5375eba5b6SRobert Mustacchi 	nvm->ops.read = e1000_null_read_nvm;
5475eba5b6SRobert Mustacchi 	nvm->ops.release = e1000_null_nvm_generic;
5575eba5b6SRobert Mustacchi 	nvm->ops.reload = e1000_reload_nvm_generic;
5675eba5b6SRobert Mustacchi 	nvm->ops.update = e1000_null_ops_generic;
5775eba5b6SRobert Mustacchi 	nvm->ops.valid_led_default = e1000_null_led_default;
5875eba5b6SRobert Mustacchi 	nvm->ops.validate = e1000_null_ops_generic;
5975eba5b6SRobert Mustacchi 	nvm->ops.write = e1000_null_write_nvm;
6075eba5b6SRobert Mustacchi }
6175eba5b6SRobert Mustacchi 
6275eba5b6SRobert Mustacchi /**
6375eba5b6SRobert Mustacchi  *  e1000_null_nvm_read - No-op function, return 0
6475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
6575eba5b6SRobert Mustacchi  **/
e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG a,u16 E1000_UNUSEDARG b,u16 E1000_UNUSEDARG * c)66c124a83eSRobert Mustacchi s32 e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG *hw,
67c124a83eSRobert Mustacchi 			u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b,
68c124a83eSRobert Mustacchi 			u16 E1000_UNUSEDARG *c)
6975eba5b6SRobert Mustacchi {
7075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_read_nvm");
7175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
7275eba5b6SRobert Mustacchi }
7375eba5b6SRobert Mustacchi 
7475eba5b6SRobert Mustacchi /**
7575eba5b6SRobert Mustacchi  *  e1000_null_nvm_generic - No-op function, return void
7675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
7775eba5b6SRobert Mustacchi  **/
e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG * hw)78c124a83eSRobert Mustacchi void e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG *hw)
7975eba5b6SRobert Mustacchi {
8075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_nvm_generic");
8175eba5b6SRobert Mustacchi 	return;
8275eba5b6SRobert Mustacchi }
8375eba5b6SRobert Mustacchi 
8475eba5b6SRobert Mustacchi /**
8575eba5b6SRobert Mustacchi  *  e1000_null_led_default - No-op function, return 0
8675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
8775eba5b6SRobert Mustacchi  **/
e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG * data)88c124a83eSRobert Mustacchi s32 e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG *hw,
89c124a83eSRobert Mustacchi 			   u16 E1000_UNUSEDARG *data)
9075eba5b6SRobert Mustacchi {
9175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_led_default");
9275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
9375eba5b6SRobert Mustacchi }
9475eba5b6SRobert Mustacchi 
9575eba5b6SRobert Mustacchi /**
9675eba5b6SRobert Mustacchi  *  e1000_null_write_nvm - No-op function, return 0
9775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
9875eba5b6SRobert Mustacchi  **/
e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG a,u16 E1000_UNUSEDARG b,u16 E1000_UNUSEDARG * c)99c124a83eSRobert Mustacchi s32 e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG *hw,
100c124a83eSRobert Mustacchi 			 u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b,
101c124a83eSRobert Mustacchi 			 u16 E1000_UNUSEDARG *c)
10275eba5b6SRobert Mustacchi {
10375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_write_nvm");
10475eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
10575eba5b6SRobert Mustacchi }
10675eba5b6SRobert Mustacchi 
10775eba5b6SRobert Mustacchi /**
10875eba5b6SRobert Mustacchi  *  e1000_raise_eec_clk - Raise EEPROM clock
10975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
11075eba5b6SRobert Mustacchi  *  @eecd: pointer to the EEPROM
11175eba5b6SRobert Mustacchi  *
11275eba5b6SRobert Mustacchi  *  Enable/Raise the EEPROM clock bit.
11375eba5b6SRobert Mustacchi  **/
e1000_raise_eec_clk(struct e1000_hw * hw,u32 * eecd)11475eba5b6SRobert Mustacchi static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
11575eba5b6SRobert Mustacchi {
11675eba5b6SRobert Mustacchi 	*eecd = *eecd | E1000_EECD_SK;
11775eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EECD, *eecd);
11875eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
11975eba5b6SRobert Mustacchi 	usec_delay(hw->nvm.delay_usec);
12075eba5b6SRobert Mustacchi }
12175eba5b6SRobert Mustacchi 
12275eba5b6SRobert Mustacchi /**
12375eba5b6SRobert Mustacchi  *  e1000_lower_eec_clk - Lower EEPROM clock
12475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
12575eba5b6SRobert Mustacchi  *  @eecd: pointer to the EEPROM
12675eba5b6SRobert Mustacchi  *
12775eba5b6SRobert Mustacchi  *  Clear/Lower the EEPROM clock bit.
12875eba5b6SRobert Mustacchi  **/
e1000_lower_eec_clk(struct e1000_hw * hw,u32 * eecd)12975eba5b6SRobert Mustacchi static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
13075eba5b6SRobert Mustacchi {
13175eba5b6SRobert Mustacchi 	*eecd = *eecd & ~E1000_EECD_SK;
13275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EECD, *eecd);
13375eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
13475eba5b6SRobert Mustacchi 	usec_delay(hw->nvm.delay_usec);
13575eba5b6SRobert Mustacchi }
13675eba5b6SRobert Mustacchi 
13775eba5b6SRobert Mustacchi /**
13875eba5b6SRobert Mustacchi  *  e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
13975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
14075eba5b6SRobert Mustacchi  *  @data: data to send to the EEPROM
14175eba5b6SRobert Mustacchi  *  @count: number of bits to shift out
14275eba5b6SRobert Mustacchi  *
14375eba5b6SRobert Mustacchi  *  We need to shift 'count' bits out to the EEPROM.  So, the value in the
14475eba5b6SRobert Mustacchi  *  "data" parameter will be shifted out to the EEPROM one bit at a time.
14575eba5b6SRobert Mustacchi  *  In order to do this, "data" must be broken down into bits.
14675eba5b6SRobert Mustacchi  **/
e1000_shift_out_eec_bits(struct e1000_hw * hw,u16 data,u16 count)14775eba5b6SRobert Mustacchi static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
14875eba5b6SRobert Mustacchi {
14975eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
15075eba5b6SRobert Mustacchi 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
15175eba5b6SRobert Mustacchi 	u32 mask;
15275eba5b6SRobert Mustacchi 
15375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_shift_out_eec_bits");
15475eba5b6SRobert Mustacchi 
15575eba5b6SRobert Mustacchi 	mask = 0x01 << (count - 1);
15675eba5b6SRobert Mustacchi 	if (nvm->type == e1000_nvm_eeprom_microwire)
15775eba5b6SRobert Mustacchi 		eecd &= ~E1000_EECD_DO;
15875eba5b6SRobert Mustacchi 	else
15975eba5b6SRobert Mustacchi 	if (nvm->type == e1000_nvm_eeprom_spi)
16075eba5b6SRobert Mustacchi 		eecd |= E1000_EECD_DO;
16175eba5b6SRobert Mustacchi 
16275eba5b6SRobert Mustacchi 	do {
16375eba5b6SRobert Mustacchi 		eecd &= ~E1000_EECD_DI;
16475eba5b6SRobert Mustacchi 
16575eba5b6SRobert Mustacchi 		if (data & mask)
16675eba5b6SRobert Mustacchi 			eecd |= E1000_EECD_DI;
16775eba5b6SRobert Mustacchi 
16875eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
16975eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
17075eba5b6SRobert Mustacchi 
17175eba5b6SRobert Mustacchi 		usec_delay(nvm->delay_usec);
17275eba5b6SRobert Mustacchi 
17375eba5b6SRobert Mustacchi 		e1000_raise_eec_clk(hw, &eecd);
17475eba5b6SRobert Mustacchi 		e1000_lower_eec_clk(hw, &eecd);
17575eba5b6SRobert Mustacchi 
17675eba5b6SRobert Mustacchi 		mask >>= 1;
17775eba5b6SRobert Mustacchi 	} while (mask);
17875eba5b6SRobert Mustacchi 
17975eba5b6SRobert Mustacchi 	eecd &= ~E1000_EECD_DI;
18075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EECD, eecd);
18175eba5b6SRobert Mustacchi }
18275eba5b6SRobert Mustacchi 
18375eba5b6SRobert Mustacchi /**
18475eba5b6SRobert Mustacchi  *  e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
18575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
18675eba5b6SRobert Mustacchi  *  @count: number of bits to shift in
18775eba5b6SRobert Mustacchi  *
18875eba5b6SRobert Mustacchi  *  In order to read a register from the EEPROM, we need to shift 'count' bits
18975eba5b6SRobert Mustacchi  *  in from the EEPROM.  Bits are "shifted in" by raising the clock input to
19075eba5b6SRobert Mustacchi  *  the EEPROM (setting the SK bit), and then reading the value of the data out
19175eba5b6SRobert Mustacchi  *  "DO" bit.  During this "shifting in" process the data in "DI" bit should
19275eba5b6SRobert Mustacchi  *  always be clear.
19375eba5b6SRobert Mustacchi  **/
e1000_shift_in_eec_bits(struct e1000_hw * hw,u16 count)19475eba5b6SRobert Mustacchi static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
19575eba5b6SRobert Mustacchi {
19675eba5b6SRobert Mustacchi 	u32 eecd;
19775eba5b6SRobert Mustacchi 	u32 i;
19875eba5b6SRobert Mustacchi 	u16 data;
19975eba5b6SRobert Mustacchi 
20075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_shift_in_eec_bits");
20175eba5b6SRobert Mustacchi 
20275eba5b6SRobert Mustacchi 	eecd = E1000_READ_REG(hw, E1000_EECD);
20375eba5b6SRobert Mustacchi 
20475eba5b6SRobert Mustacchi 	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
20575eba5b6SRobert Mustacchi 	data = 0;
20675eba5b6SRobert Mustacchi 
20775eba5b6SRobert Mustacchi 	for (i = 0; i < count; i++) {
20875eba5b6SRobert Mustacchi 		data <<= 1;
20975eba5b6SRobert Mustacchi 		e1000_raise_eec_clk(hw, &eecd);
21075eba5b6SRobert Mustacchi 
21175eba5b6SRobert Mustacchi 		eecd = E1000_READ_REG(hw, E1000_EECD);
21275eba5b6SRobert Mustacchi 
21375eba5b6SRobert Mustacchi 		eecd &= ~E1000_EECD_DI;
21475eba5b6SRobert Mustacchi 		if (eecd & E1000_EECD_DO)
21575eba5b6SRobert Mustacchi 			data |= 1;
21675eba5b6SRobert Mustacchi 
21775eba5b6SRobert Mustacchi 		e1000_lower_eec_clk(hw, &eecd);
21875eba5b6SRobert Mustacchi 	}
21975eba5b6SRobert Mustacchi 
22075eba5b6SRobert Mustacchi 	return data;
22175eba5b6SRobert Mustacchi }
22275eba5b6SRobert Mustacchi 
22375eba5b6SRobert Mustacchi /**
22475eba5b6SRobert Mustacchi  *  e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion
22575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
22675eba5b6SRobert Mustacchi  *  @ee_reg: EEPROM flag for polling
22775eba5b6SRobert Mustacchi  *
22875eba5b6SRobert Mustacchi  *  Polls the EEPROM status bit for either read or write completion based
22975eba5b6SRobert Mustacchi  *  upon the value of 'ee_reg'.
23075eba5b6SRobert Mustacchi  **/
e1000_poll_eerd_eewr_done(struct e1000_hw * hw,int ee_reg)23175eba5b6SRobert Mustacchi s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
23275eba5b6SRobert Mustacchi {
23375eba5b6SRobert Mustacchi 	u32 attempts = 100000;
23475eba5b6SRobert Mustacchi 	u32 i, reg = 0;
23575eba5b6SRobert Mustacchi 
23675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_poll_eerd_eewr_done");
23775eba5b6SRobert Mustacchi 
23875eba5b6SRobert Mustacchi 	for (i = 0; i < attempts; i++) {
23975eba5b6SRobert Mustacchi 		if (ee_reg == E1000_NVM_POLL_READ)
24075eba5b6SRobert Mustacchi 			reg = E1000_READ_REG(hw, E1000_EERD);
24175eba5b6SRobert Mustacchi 		else
24275eba5b6SRobert Mustacchi 			reg = E1000_READ_REG(hw, E1000_EEWR);
24375eba5b6SRobert Mustacchi 
24475eba5b6SRobert Mustacchi 		if (reg & E1000_NVM_RW_REG_DONE)
24575eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
24675eba5b6SRobert Mustacchi 
24775eba5b6SRobert Mustacchi 		usec_delay(5);
24875eba5b6SRobert Mustacchi 	}
24975eba5b6SRobert Mustacchi 
25075eba5b6SRobert Mustacchi 	return -E1000_ERR_NVM;
25175eba5b6SRobert Mustacchi }
25275eba5b6SRobert Mustacchi 
25375eba5b6SRobert Mustacchi /**
25475eba5b6SRobert Mustacchi  *  e1000_acquire_nvm_generic - Generic request for access to EEPROM
25575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
25675eba5b6SRobert Mustacchi  *
25775eba5b6SRobert Mustacchi  *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
25875eba5b6SRobert Mustacchi  *  Return successful if access grant bit set, else clear the request for
25975eba5b6SRobert Mustacchi  *  EEPROM access and return -E1000_ERR_NVM (-1).
26075eba5b6SRobert Mustacchi  **/
e1000_acquire_nvm_generic(struct e1000_hw * hw)26175eba5b6SRobert Mustacchi s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
26275eba5b6SRobert Mustacchi {
26375eba5b6SRobert Mustacchi 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
26475eba5b6SRobert Mustacchi 	s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
26575eba5b6SRobert Mustacchi 
26675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_nvm_generic");
26775eba5b6SRobert Mustacchi 
26875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ);
26975eba5b6SRobert Mustacchi 	eecd = E1000_READ_REG(hw, E1000_EECD);
27075eba5b6SRobert Mustacchi 
27175eba5b6SRobert Mustacchi 	while (timeout) {
27275eba5b6SRobert Mustacchi 		if (eecd & E1000_EECD_GNT)
27375eba5b6SRobert Mustacchi 			break;
27475eba5b6SRobert Mustacchi 		usec_delay(5);
27575eba5b6SRobert Mustacchi 		eecd = E1000_READ_REG(hw, E1000_EECD);
27675eba5b6SRobert Mustacchi 		timeout--;
27775eba5b6SRobert Mustacchi 	}
27875eba5b6SRobert Mustacchi 
27975eba5b6SRobert Mustacchi 	if (!timeout) {
28075eba5b6SRobert Mustacchi 		eecd &= ~E1000_EECD_REQ;
28175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
28275eba5b6SRobert Mustacchi 		DEBUGOUT("Could not acquire NVM grant\n");
28375eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
28475eba5b6SRobert Mustacchi 	}
28575eba5b6SRobert Mustacchi 
28675eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
28775eba5b6SRobert Mustacchi }
28875eba5b6SRobert Mustacchi 
28975eba5b6SRobert Mustacchi /**
29075eba5b6SRobert Mustacchi  *  e1000_standby_nvm - Return EEPROM to standby state
29175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
29275eba5b6SRobert Mustacchi  *
29375eba5b6SRobert Mustacchi  *  Return the EEPROM to a standby state.
29475eba5b6SRobert Mustacchi  **/
e1000_standby_nvm(struct e1000_hw * hw)29575eba5b6SRobert Mustacchi static void e1000_standby_nvm(struct e1000_hw *hw)
29675eba5b6SRobert Mustacchi {
29775eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
29875eba5b6SRobert Mustacchi 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
29975eba5b6SRobert Mustacchi 
30075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_standby_nvm");
30175eba5b6SRobert Mustacchi 
30275eba5b6SRobert Mustacchi 	if (nvm->type == e1000_nvm_eeprom_microwire) {
30375eba5b6SRobert Mustacchi 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
30475eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
30575eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
30675eba5b6SRobert Mustacchi 		usec_delay(nvm->delay_usec);
30775eba5b6SRobert Mustacchi 
30875eba5b6SRobert Mustacchi 		e1000_raise_eec_clk(hw, &eecd);
30975eba5b6SRobert Mustacchi 
31075eba5b6SRobert Mustacchi 		/* Select EEPROM */
31175eba5b6SRobert Mustacchi 		eecd |= E1000_EECD_CS;
31275eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
31375eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
31475eba5b6SRobert Mustacchi 		usec_delay(nvm->delay_usec);
31575eba5b6SRobert Mustacchi 
31675eba5b6SRobert Mustacchi 		e1000_lower_eec_clk(hw, &eecd);
31775eba5b6SRobert Mustacchi 	} else if (nvm->type == e1000_nvm_eeprom_spi) {
31875eba5b6SRobert Mustacchi 		/* Toggle CS to flush commands */
31975eba5b6SRobert Mustacchi 		eecd |= E1000_EECD_CS;
32075eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
32175eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
32275eba5b6SRobert Mustacchi 		usec_delay(nvm->delay_usec);
32375eba5b6SRobert Mustacchi 		eecd &= ~E1000_EECD_CS;
32475eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
32575eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
32675eba5b6SRobert Mustacchi 		usec_delay(nvm->delay_usec);
32775eba5b6SRobert Mustacchi 	}
32875eba5b6SRobert Mustacchi }
32975eba5b6SRobert Mustacchi 
33075eba5b6SRobert Mustacchi /**
33175eba5b6SRobert Mustacchi  *  e1000_stop_nvm - Terminate EEPROM command
33275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
33375eba5b6SRobert Mustacchi  *
33475eba5b6SRobert Mustacchi  *  Terminates the current command by inverting the EEPROM's chip select pin.
33575eba5b6SRobert Mustacchi  **/
e1000_stop_nvm(struct e1000_hw * hw)33675eba5b6SRobert Mustacchi void e1000_stop_nvm(struct e1000_hw *hw)
33775eba5b6SRobert Mustacchi {
33875eba5b6SRobert Mustacchi 	u32 eecd;
33975eba5b6SRobert Mustacchi 
34075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_stop_nvm");
34175eba5b6SRobert Mustacchi 
34275eba5b6SRobert Mustacchi 	eecd = E1000_READ_REG(hw, E1000_EECD);
34375eba5b6SRobert Mustacchi 	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
34475eba5b6SRobert Mustacchi 		/* Pull CS high */
34575eba5b6SRobert Mustacchi 		eecd |= E1000_EECD_CS;
34675eba5b6SRobert Mustacchi 		e1000_lower_eec_clk(hw, &eecd);
34775eba5b6SRobert Mustacchi 	} else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
34875eba5b6SRobert Mustacchi 		/* CS on Microwire is active-high */
34975eba5b6SRobert Mustacchi 		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
35075eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
35175eba5b6SRobert Mustacchi 		e1000_raise_eec_clk(hw, &eecd);
35275eba5b6SRobert Mustacchi 		e1000_lower_eec_clk(hw, &eecd);
35375eba5b6SRobert Mustacchi 	}
35475eba5b6SRobert Mustacchi }
35575eba5b6SRobert Mustacchi 
35675eba5b6SRobert Mustacchi /**
35775eba5b6SRobert Mustacchi  *  e1000_release_nvm_generic - Release exclusive access to EEPROM
35875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
35975eba5b6SRobert Mustacchi  *
36075eba5b6SRobert Mustacchi  *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
36175eba5b6SRobert Mustacchi  **/
e1000_release_nvm_generic(struct e1000_hw * hw)36275eba5b6SRobert Mustacchi void e1000_release_nvm_generic(struct e1000_hw *hw)
36375eba5b6SRobert Mustacchi {
36475eba5b6SRobert Mustacchi 	u32 eecd;
36575eba5b6SRobert Mustacchi 
36675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_nvm_generic");
36775eba5b6SRobert Mustacchi 
36875eba5b6SRobert Mustacchi 	e1000_stop_nvm(hw);
36975eba5b6SRobert Mustacchi 
37075eba5b6SRobert Mustacchi 	eecd = E1000_READ_REG(hw, E1000_EECD);
37175eba5b6SRobert Mustacchi 	eecd &= ~E1000_EECD_REQ;
37275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EECD, eecd);
37375eba5b6SRobert Mustacchi }
37475eba5b6SRobert Mustacchi 
37575eba5b6SRobert Mustacchi /**
37675eba5b6SRobert Mustacchi  *  e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
37775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
37875eba5b6SRobert Mustacchi  *
37975eba5b6SRobert Mustacchi  *  Setups the EEPROM for reading and writing.
38075eba5b6SRobert Mustacchi  **/
e1000_ready_nvm_eeprom(struct e1000_hw * hw)38175eba5b6SRobert Mustacchi static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
38275eba5b6SRobert Mustacchi {
38375eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
38475eba5b6SRobert Mustacchi 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
38575eba5b6SRobert Mustacchi 	u8 spi_stat_reg;
38675eba5b6SRobert Mustacchi 
38775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_ready_nvm_eeprom");
38875eba5b6SRobert Mustacchi 
38975eba5b6SRobert Mustacchi 	if (nvm->type == e1000_nvm_eeprom_microwire) {
39075eba5b6SRobert Mustacchi 		/* Clear SK and DI */
39175eba5b6SRobert Mustacchi 		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
39275eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
39375eba5b6SRobert Mustacchi 		/* Set CS */
39475eba5b6SRobert Mustacchi 		eecd |= E1000_EECD_CS;
39575eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
39675eba5b6SRobert Mustacchi 	} else if (nvm->type == e1000_nvm_eeprom_spi) {
39775eba5b6SRobert Mustacchi 		u16 timeout = NVM_MAX_RETRY_SPI;
39875eba5b6SRobert Mustacchi 
39975eba5b6SRobert Mustacchi 		/* Clear SK and CS */
40075eba5b6SRobert Mustacchi 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
40175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
40275eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
40375eba5b6SRobert Mustacchi 		usec_delay(1);
40475eba5b6SRobert Mustacchi 
40575eba5b6SRobert Mustacchi 		/* Read "Status Register" repeatedly until the LSB is cleared.
40675eba5b6SRobert Mustacchi 		 * The EEPROM will signal that the command has been completed
40775eba5b6SRobert Mustacchi 		 * by clearing bit 0 of the internal status register.  If it's
40875eba5b6SRobert Mustacchi 		 * not cleared within 'timeout', then error out.
40975eba5b6SRobert Mustacchi 		 */
41075eba5b6SRobert Mustacchi 		while (timeout) {
41175eba5b6SRobert Mustacchi 			e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
41275eba5b6SRobert Mustacchi 						 hw->nvm.opcode_bits);
41375eba5b6SRobert Mustacchi 			spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
41475eba5b6SRobert Mustacchi 			if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
41575eba5b6SRobert Mustacchi 				break;
41675eba5b6SRobert Mustacchi 
41775eba5b6SRobert Mustacchi 			usec_delay(5);
41875eba5b6SRobert Mustacchi 			e1000_standby_nvm(hw);
41975eba5b6SRobert Mustacchi 			timeout--;
42075eba5b6SRobert Mustacchi 		}
42175eba5b6SRobert Mustacchi 
42275eba5b6SRobert Mustacchi 		if (!timeout) {
42375eba5b6SRobert Mustacchi 			DEBUGOUT("SPI NVM Status error\n");
42475eba5b6SRobert Mustacchi 			return -E1000_ERR_NVM;
42575eba5b6SRobert Mustacchi 		}
42675eba5b6SRobert Mustacchi 	}
42775eba5b6SRobert Mustacchi 
42875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
42975eba5b6SRobert Mustacchi }
43075eba5b6SRobert Mustacchi 
43175eba5b6SRobert Mustacchi /**
43275eba5b6SRobert Mustacchi  *  e1000_read_nvm_spi - Read EEPROM's using SPI
43375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
43475eba5b6SRobert Mustacchi  *  @offset: offset of word in the EEPROM to read
43575eba5b6SRobert Mustacchi  *  @words: number of words to read
43675eba5b6SRobert Mustacchi  *  @data: word read from the EEPROM
43775eba5b6SRobert Mustacchi  *
43875eba5b6SRobert Mustacchi  *  Reads a 16 bit word from the EEPROM.
43975eba5b6SRobert Mustacchi  **/
e1000_read_nvm_spi(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)44075eba5b6SRobert Mustacchi s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
44175eba5b6SRobert Mustacchi {
44275eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
44375eba5b6SRobert Mustacchi 	u32 i = 0;
44475eba5b6SRobert Mustacchi 	s32 ret_val;
44575eba5b6SRobert Mustacchi 	u16 word_in;
44675eba5b6SRobert Mustacchi 	u8 read_opcode = NVM_READ_OPCODE_SPI;
44775eba5b6SRobert Mustacchi 
44875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_nvm_spi");
44975eba5b6SRobert Mustacchi 
45075eba5b6SRobert Mustacchi 	/* A check for invalid values:  offset too large, too many words,
45175eba5b6SRobert Mustacchi 	 * and not enough words.
45275eba5b6SRobert Mustacchi 	 */
45375eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
45475eba5b6SRobert Mustacchi 	    (words == 0)) {
45575eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
45675eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
45775eba5b6SRobert Mustacchi 	}
45875eba5b6SRobert Mustacchi 
45975eba5b6SRobert Mustacchi 	ret_val = nvm->ops.acquire(hw);
46075eba5b6SRobert Mustacchi 	if (ret_val)
46175eba5b6SRobert Mustacchi 		return ret_val;
46275eba5b6SRobert Mustacchi 
46375eba5b6SRobert Mustacchi 	ret_val = e1000_ready_nvm_eeprom(hw);
46475eba5b6SRobert Mustacchi 	if (ret_val)
46575eba5b6SRobert Mustacchi 		goto release;
46675eba5b6SRobert Mustacchi 
46775eba5b6SRobert Mustacchi 	e1000_standby_nvm(hw);
46875eba5b6SRobert Mustacchi 
46975eba5b6SRobert Mustacchi 	if ((nvm->address_bits == 8) && (offset >= 128))
47075eba5b6SRobert Mustacchi 		read_opcode |= NVM_A8_OPCODE_SPI;
47175eba5b6SRobert Mustacchi 
47275eba5b6SRobert Mustacchi 	/* Send the READ command (opcode + addr) */
47375eba5b6SRobert Mustacchi 	e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
47475eba5b6SRobert Mustacchi 	e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
47575eba5b6SRobert Mustacchi 
47675eba5b6SRobert Mustacchi 	/* Read the data.  SPI NVMs increment the address with each byte
47775eba5b6SRobert Mustacchi 	 * read and will roll over if reading beyond the end.  This allows
47875eba5b6SRobert Mustacchi 	 * us to read the whole NVM from any offset
47975eba5b6SRobert Mustacchi 	 */
48075eba5b6SRobert Mustacchi 	for (i = 0; i < words; i++) {
48175eba5b6SRobert Mustacchi 		word_in = e1000_shift_in_eec_bits(hw, 16);
48275eba5b6SRobert Mustacchi 		data[i] = (word_in >> 8) | (word_in << 8);
48375eba5b6SRobert Mustacchi 	}
48475eba5b6SRobert Mustacchi 
48575eba5b6SRobert Mustacchi release:
48675eba5b6SRobert Mustacchi 	nvm->ops.release(hw);
48775eba5b6SRobert Mustacchi 
48875eba5b6SRobert Mustacchi 	return ret_val;
48975eba5b6SRobert Mustacchi }
49075eba5b6SRobert Mustacchi 
49175eba5b6SRobert Mustacchi /**
49275eba5b6SRobert Mustacchi  *  e1000_read_nvm_microwire - Reads EEPROM's using microwire
49375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
49475eba5b6SRobert Mustacchi  *  @offset: offset of word in the EEPROM to read
49575eba5b6SRobert Mustacchi  *  @words: number of words to read
49675eba5b6SRobert Mustacchi  *  @data: word read from the EEPROM
49775eba5b6SRobert Mustacchi  *
49875eba5b6SRobert Mustacchi  *  Reads a 16 bit word from the EEPROM.
49975eba5b6SRobert Mustacchi  **/
e1000_read_nvm_microwire(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)50075eba5b6SRobert Mustacchi s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
50175eba5b6SRobert Mustacchi 			     u16 *data)
50275eba5b6SRobert Mustacchi {
50375eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
50475eba5b6SRobert Mustacchi 	u32 i = 0;
50575eba5b6SRobert Mustacchi 	s32 ret_val;
50675eba5b6SRobert Mustacchi 	u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
50775eba5b6SRobert Mustacchi 
50875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_nvm_microwire");
50975eba5b6SRobert Mustacchi 
51075eba5b6SRobert Mustacchi 	/* A check for invalid values:  offset too large, too many words,
51175eba5b6SRobert Mustacchi 	 * and not enough words.
51275eba5b6SRobert Mustacchi 	 */
51375eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
51475eba5b6SRobert Mustacchi 	    (words == 0)) {
51575eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
51675eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
51775eba5b6SRobert Mustacchi 	}
51875eba5b6SRobert Mustacchi 
51975eba5b6SRobert Mustacchi 	ret_val = nvm->ops.acquire(hw);
52075eba5b6SRobert Mustacchi 	if (ret_val)
52175eba5b6SRobert Mustacchi 		return ret_val;
52275eba5b6SRobert Mustacchi 
52375eba5b6SRobert Mustacchi 	ret_val = e1000_ready_nvm_eeprom(hw);
52475eba5b6SRobert Mustacchi 	if (ret_val)
52575eba5b6SRobert Mustacchi 		goto release;
52675eba5b6SRobert Mustacchi 
52775eba5b6SRobert Mustacchi 	for (i = 0; i < words; i++) {
52875eba5b6SRobert Mustacchi 		/* Send the READ command (opcode + addr) */
52975eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
53075eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, (u16)(offset + i),
53175eba5b6SRobert Mustacchi 					nvm->address_bits);
53275eba5b6SRobert Mustacchi 
53375eba5b6SRobert Mustacchi 		/* Read the data.  For microwire, each word requires the
53475eba5b6SRobert Mustacchi 		 * overhead of setup and tear-down.
53575eba5b6SRobert Mustacchi 		 */
53675eba5b6SRobert Mustacchi 		data[i] = e1000_shift_in_eec_bits(hw, 16);
53775eba5b6SRobert Mustacchi 		e1000_standby_nvm(hw);
53875eba5b6SRobert Mustacchi 	}
53975eba5b6SRobert Mustacchi 
54075eba5b6SRobert Mustacchi release:
54175eba5b6SRobert Mustacchi 	nvm->ops.release(hw);
54275eba5b6SRobert Mustacchi 
54375eba5b6SRobert Mustacchi 	return ret_val;
54475eba5b6SRobert Mustacchi }
54575eba5b6SRobert Mustacchi 
54675eba5b6SRobert Mustacchi /**
54775eba5b6SRobert Mustacchi  *  e1000_read_nvm_eerd - Reads EEPROM using EERD register
54875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
54975eba5b6SRobert Mustacchi  *  @offset: offset of word in the EEPROM to read
55075eba5b6SRobert Mustacchi  *  @words: number of words to read
55175eba5b6SRobert Mustacchi  *  @data: word read from the EEPROM
55275eba5b6SRobert Mustacchi  *
55375eba5b6SRobert Mustacchi  *  Reads a 16 bit word from the EEPROM using the EERD register.
55475eba5b6SRobert Mustacchi  **/
e1000_read_nvm_eerd(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)55575eba5b6SRobert Mustacchi s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
55675eba5b6SRobert Mustacchi {
55775eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
55875eba5b6SRobert Mustacchi 	u32 i, eerd = 0;
55975eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
56075eba5b6SRobert Mustacchi 
56175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_nvm_eerd");
56275eba5b6SRobert Mustacchi 
56375eba5b6SRobert Mustacchi 	/* A check for invalid values:  offset too large, too many words,
56475eba5b6SRobert Mustacchi 	 * too many words for the offset, and not enough words.
56575eba5b6SRobert Mustacchi 	 */
56675eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
56775eba5b6SRobert Mustacchi 	    (words == 0)) {
56875eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
56975eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
57075eba5b6SRobert Mustacchi 	}
57175eba5b6SRobert Mustacchi 
57275eba5b6SRobert Mustacchi 	for (i = 0; i < words; i++) {
57375eba5b6SRobert Mustacchi 		eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
57475eba5b6SRobert Mustacchi 		       E1000_NVM_RW_REG_START;
57575eba5b6SRobert Mustacchi 
57675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EERD, eerd);
57775eba5b6SRobert Mustacchi 		ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
57875eba5b6SRobert Mustacchi 		if (ret_val)
57975eba5b6SRobert Mustacchi 			break;
58075eba5b6SRobert Mustacchi 
58175eba5b6SRobert Mustacchi 		data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
58275eba5b6SRobert Mustacchi 			   E1000_NVM_RW_REG_DATA);
58375eba5b6SRobert Mustacchi 	}
58475eba5b6SRobert Mustacchi 
585c124a83eSRobert Mustacchi 	if (ret_val)
586c124a83eSRobert Mustacchi 		DEBUGOUT1("NVM read error: %d\n", ret_val);
587c124a83eSRobert Mustacchi 
58875eba5b6SRobert Mustacchi 	return ret_val;
58975eba5b6SRobert Mustacchi }
59075eba5b6SRobert Mustacchi 
59175eba5b6SRobert Mustacchi /**
59275eba5b6SRobert Mustacchi  *  e1000_write_nvm_spi - Write to EEPROM using SPI
59375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
59475eba5b6SRobert Mustacchi  *  @offset: offset within the EEPROM to be written to
59575eba5b6SRobert Mustacchi  *  @words: number of words to write
59675eba5b6SRobert Mustacchi  *  @data: 16 bit word(s) to be written to the EEPROM
59775eba5b6SRobert Mustacchi  *
59875eba5b6SRobert Mustacchi  *  Writes data to EEPROM at offset using SPI interface.
59975eba5b6SRobert Mustacchi  *
60075eba5b6SRobert Mustacchi  *  If e1000_update_nvm_checksum is not called after this function , the
60175eba5b6SRobert Mustacchi  *  EEPROM will most likely contain an invalid checksum.
60275eba5b6SRobert Mustacchi  **/
e1000_write_nvm_spi(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)60375eba5b6SRobert Mustacchi s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
60475eba5b6SRobert Mustacchi {
60575eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
60675eba5b6SRobert Mustacchi 	s32 ret_val = -E1000_ERR_NVM;
60775eba5b6SRobert Mustacchi 	u16 widx = 0;
60875eba5b6SRobert Mustacchi 
60975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_nvm_spi");
61075eba5b6SRobert Mustacchi 
61175eba5b6SRobert Mustacchi 	/* A check for invalid values:  offset too large, too many words,
61275eba5b6SRobert Mustacchi 	 * and not enough words.
61375eba5b6SRobert Mustacchi 	 */
61475eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
61575eba5b6SRobert Mustacchi 	    (words == 0)) {
61675eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
61775eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
61875eba5b6SRobert Mustacchi 	}
61975eba5b6SRobert Mustacchi 
62075eba5b6SRobert Mustacchi 	while (widx < words) {
62175eba5b6SRobert Mustacchi 		u8 write_opcode = NVM_WRITE_OPCODE_SPI;
62275eba5b6SRobert Mustacchi 
62375eba5b6SRobert Mustacchi 		ret_val = nvm->ops.acquire(hw);
62475eba5b6SRobert Mustacchi 		if (ret_val)
62575eba5b6SRobert Mustacchi 			return ret_val;
62675eba5b6SRobert Mustacchi 
62775eba5b6SRobert Mustacchi 		ret_val = e1000_ready_nvm_eeprom(hw);
62875eba5b6SRobert Mustacchi 		if (ret_val) {
62975eba5b6SRobert Mustacchi 			nvm->ops.release(hw);
63075eba5b6SRobert Mustacchi 			return ret_val;
63175eba5b6SRobert Mustacchi 		}
63275eba5b6SRobert Mustacchi 
63375eba5b6SRobert Mustacchi 		e1000_standby_nvm(hw);
63475eba5b6SRobert Mustacchi 
63575eba5b6SRobert Mustacchi 		/* Send the WRITE ENABLE command (8 bit opcode) */
63675eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
63775eba5b6SRobert Mustacchi 					 nvm->opcode_bits);
63875eba5b6SRobert Mustacchi 
63975eba5b6SRobert Mustacchi 		e1000_standby_nvm(hw);
64075eba5b6SRobert Mustacchi 
64175eba5b6SRobert Mustacchi 		/* Some SPI eeproms use the 8th address bit embedded in the
64275eba5b6SRobert Mustacchi 		 * opcode
64375eba5b6SRobert Mustacchi 		 */
64475eba5b6SRobert Mustacchi 		if ((nvm->address_bits == 8) && (offset >= 128))
64575eba5b6SRobert Mustacchi 			write_opcode |= NVM_A8_OPCODE_SPI;
64675eba5b6SRobert Mustacchi 
64775eba5b6SRobert Mustacchi 		/* Send the Write command (8-bit opcode + addr) */
64875eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
64975eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
65075eba5b6SRobert Mustacchi 					 nvm->address_bits);
65175eba5b6SRobert Mustacchi 
65275eba5b6SRobert Mustacchi 		/* Loop to allow for up to whole page write of eeprom */
65375eba5b6SRobert Mustacchi 		while (widx < words) {
65475eba5b6SRobert Mustacchi 			u16 word_out = data[widx];
65575eba5b6SRobert Mustacchi 			word_out = (word_out >> 8) | (word_out << 8);
65675eba5b6SRobert Mustacchi 			e1000_shift_out_eec_bits(hw, word_out, 16);
65775eba5b6SRobert Mustacchi 			widx++;
65875eba5b6SRobert Mustacchi 
65975eba5b6SRobert Mustacchi 			if ((((offset + widx) * 2) % nvm->page_size) == 0) {
66075eba5b6SRobert Mustacchi 				e1000_standby_nvm(hw);
66175eba5b6SRobert Mustacchi 				break;
66275eba5b6SRobert Mustacchi 			}
66375eba5b6SRobert Mustacchi 		}
66475eba5b6SRobert Mustacchi 		msec_delay(10);
66575eba5b6SRobert Mustacchi 		nvm->ops.release(hw);
66675eba5b6SRobert Mustacchi 	}
66775eba5b6SRobert Mustacchi 
66875eba5b6SRobert Mustacchi 	return ret_val;
66975eba5b6SRobert Mustacchi }
67075eba5b6SRobert Mustacchi 
67175eba5b6SRobert Mustacchi /**
67275eba5b6SRobert Mustacchi  *  e1000_write_nvm_microwire - Writes EEPROM using microwire
67375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
67475eba5b6SRobert Mustacchi  *  @offset: offset within the EEPROM to be written to
67575eba5b6SRobert Mustacchi  *  @words: number of words to write
67675eba5b6SRobert Mustacchi  *  @data: 16 bit word(s) to be written to the EEPROM
67775eba5b6SRobert Mustacchi  *
67875eba5b6SRobert Mustacchi  *  Writes data to EEPROM at offset using microwire interface.
67975eba5b6SRobert Mustacchi  *
68075eba5b6SRobert Mustacchi  *  If e1000_update_nvm_checksum is not called after this function , the
68175eba5b6SRobert Mustacchi  *  EEPROM will most likely contain an invalid checksum.
68275eba5b6SRobert Mustacchi  **/
e1000_write_nvm_microwire(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)68375eba5b6SRobert Mustacchi s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
68475eba5b6SRobert Mustacchi 			      u16 *data)
68575eba5b6SRobert Mustacchi {
68675eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
68775eba5b6SRobert Mustacchi 	s32  ret_val;
68875eba5b6SRobert Mustacchi 	u32 eecd;
68975eba5b6SRobert Mustacchi 	u16 words_written = 0;
69075eba5b6SRobert Mustacchi 	u16 widx = 0;
69175eba5b6SRobert Mustacchi 
69275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_nvm_microwire");
69375eba5b6SRobert Mustacchi 
69475eba5b6SRobert Mustacchi 	/* A check for invalid values:  offset too large, too many words,
69575eba5b6SRobert Mustacchi 	 * and not enough words.
69675eba5b6SRobert Mustacchi 	 */
69775eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
69875eba5b6SRobert Mustacchi 	    (words == 0)) {
69975eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
70075eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
70175eba5b6SRobert Mustacchi 	}
70275eba5b6SRobert Mustacchi 
70375eba5b6SRobert Mustacchi 	ret_val = nvm->ops.acquire(hw);
70475eba5b6SRobert Mustacchi 	if (ret_val)
70575eba5b6SRobert Mustacchi 		return ret_val;
70675eba5b6SRobert Mustacchi 
70775eba5b6SRobert Mustacchi 	ret_val = e1000_ready_nvm_eeprom(hw);
70875eba5b6SRobert Mustacchi 	if (ret_val)
70975eba5b6SRobert Mustacchi 		goto release;
71075eba5b6SRobert Mustacchi 
71175eba5b6SRobert Mustacchi 	e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
71275eba5b6SRobert Mustacchi 				 (u16)(nvm->opcode_bits + 2));
71375eba5b6SRobert Mustacchi 
71475eba5b6SRobert Mustacchi 	e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
71575eba5b6SRobert Mustacchi 
71675eba5b6SRobert Mustacchi 	e1000_standby_nvm(hw);
71775eba5b6SRobert Mustacchi 
71875eba5b6SRobert Mustacchi 	while (words_written < words) {
71975eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
72075eba5b6SRobert Mustacchi 					 nvm->opcode_bits);
72175eba5b6SRobert Mustacchi 
72275eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, (u16)(offset + words_written),
72375eba5b6SRobert Mustacchi 					 nvm->address_bits);
72475eba5b6SRobert Mustacchi 
72575eba5b6SRobert Mustacchi 		e1000_shift_out_eec_bits(hw, data[words_written], 16);
72675eba5b6SRobert Mustacchi 
72775eba5b6SRobert Mustacchi 		e1000_standby_nvm(hw);
72875eba5b6SRobert Mustacchi 
72975eba5b6SRobert Mustacchi 		for (widx = 0; widx < 200; widx++) {
73075eba5b6SRobert Mustacchi 			eecd = E1000_READ_REG(hw, E1000_EECD);
73175eba5b6SRobert Mustacchi 			if (eecd & E1000_EECD_DO)
73275eba5b6SRobert Mustacchi 				break;
73375eba5b6SRobert Mustacchi 			usec_delay(50);
73475eba5b6SRobert Mustacchi 		}
73575eba5b6SRobert Mustacchi 
73675eba5b6SRobert Mustacchi 		if (widx == 200) {
73775eba5b6SRobert Mustacchi 			DEBUGOUT("NVM Write did not complete\n");
73875eba5b6SRobert Mustacchi 			ret_val = -E1000_ERR_NVM;
73975eba5b6SRobert Mustacchi 			goto release;
74075eba5b6SRobert Mustacchi 		}
74175eba5b6SRobert Mustacchi 
74275eba5b6SRobert Mustacchi 		e1000_standby_nvm(hw);
74375eba5b6SRobert Mustacchi 
74475eba5b6SRobert Mustacchi 		words_written++;
74575eba5b6SRobert Mustacchi 	}
74675eba5b6SRobert Mustacchi 
74775eba5b6SRobert Mustacchi 	e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
74875eba5b6SRobert Mustacchi 				 (u16)(nvm->opcode_bits + 2));
74975eba5b6SRobert Mustacchi 
75075eba5b6SRobert Mustacchi 	e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
75175eba5b6SRobert Mustacchi 
75275eba5b6SRobert Mustacchi release:
75375eba5b6SRobert Mustacchi 	nvm->ops.release(hw);
75475eba5b6SRobert Mustacchi 
75575eba5b6SRobert Mustacchi 	return ret_val;
75675eba5b6SRobert Mustacchi }
75775eba5b6SRobert Mustacchi 
75875eba5b6SRobert Mustacchi /**
75975eba5b6SRobert Mustacchi  *  e1000_read_pba_string_generic - Read device part number
76075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
76175eba5b6SRobert Mustacchi  *  @pba_num: pointer to device part number
76275eba5b6SRobert Mustacchi  *  @pba_num_size: size of part number buffer
76375eba5b6SRobert Mustacchi  *
76475eba5b6SRobert Mustacchi  *  Reads the product board assembly (PBA) number from the EEPROM and stores
76575eba5b6SRobert Mustacchi  *  the value in pba_num.
76675eba5b6SRobert Mustacchi  **/
e1000_read_pba_string_generic(struct e1000_hw * hw,u8 * pba_num,u32 pba_num_size)76775eba5b6SRobert Mustacchi s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
76875eba5b6SRobert Mustacchi 				  u32 pba_num_size)
76975eba5b6SRobert Mustacchi {
77075eba5b6SRobert Mustacchi 	s32 ret_val;
77175eba5b6SRobert Mustacchi 	u16 nvm_data;
77275eba5b6SRobert Mustacchi 	u16 pba_ptr;
77375eba5b6SRobert Mustacchi 	u16 offset;
77475eba5b6SRobert Mustacchi 	u16 length;
77575eba5b6SRobert Mustacchi 
77675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_pba_string_generic");
77775eba5b6SRobert Mustacchi 
778c124a83eSRobert Mustacchi 	if ((hw->mac.type >= e1000_i210) &&
779c124a83eSRobert Mustacchi 	    !e1000_get_flash_presence_i210(hw)) {
780c124a83eSRobert Mustacchi 		DEBUGOUT("Flashless no PBA string\n");
781c124a83eSRobert Mustacchi 		return -E1000_ERR_NVM_PBA_SECTION;
782c124a83eSRobert Mustacchi 	}
783c124a83eSRobert Mustacchi 
78475eba5b6SRobert Mustacchi 	if (pba_num == NULL) {
78575eba5b6SRobert Mustacchi 		DEBUGOUT("PBA string buffer was null\n");
78675eba5b6SRobert Mustacchi 		return -E1000_ERR_INVALID_ARGUMENT;
78775eba5b6SRobert Mustacchi 	}
78875eba5b6SRobert Mustacchi 
78975eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
79075eba5b6SRobert Mustacchi 	if (ret_val) {
79175eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
79275eba5b6SRobert Mustacchi 		return ret_val;
79375eba5b6SRobert Mustacchi 	}
79475eba5b6SRobert Mustacchi 
79575eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
79675eba5b6SRobert Mustacchi 	if (ret_val) {
79775eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
79875eba5b6SRobert Mustacchi 		return ret_val;
79975eba5b6SRobert Mustacchi 	}
80075eba5b6SRobert Mustacchi 
80175eba5b6SRobert Mustacchi 	/* if nvm_data is not ptr guard the PBA must be in legacy format which
80275eba5b6SRobert Mustacchi 	 * means pba_ptr is actually our second data word for the PBA number
80375eba5b6SRobert Mustacchi 	 * and we can decode it into an ascii string
80475eba5b6SRobert Mustacchi 	 */
80575eba5b6SRobert Mustacchi 	if (nvm_data != NVM_PBA_PTR_GUARD) {
80675eba5b6SRobert Mustacchi 		DEBUGOUT("NVM PBA number is not stored as string\n");
80775eba5b6SRobert Mustacchi 
80875eba5b6SRobert Mustacchi 		/* make sure callers buffer is big enough to store the PBA */
80975eba5b6SRobert Mustacchi 		if (pba_num_size < E1000_PBANUM_LENGTH) {
81075eba5b6SRobert Mustacchi 			DEBUGOUT("PBA string buffer too small\n");
81175eba5b6SRobert Mustacchi 			return E1000_ERR_NO_SPACE;
81275eba5b6SRobert Mustacchi 		}
81375eba5b6SRobert Mustacchi 
81475eba5b6SRobert Mustacchi 		/* extract hex string from data and pba_ptr */
81575eba5b6SRobert Mustacchi 		pba_num[0] = (nvm_data >> 12) & 0xF;
81675eba5b6SRobert Mustacchi 		pba_num[1] = (nvm_data >> 8) & 0xF;
81775eba5b6SRobert Mustacchi 		pba_num[2] = (nvm_data >> 4) & 0xF;
81875eba5b6SRobert Mustacchi 		pba_num[3] = nvm_data & 0xF;
81975eba5b6SRobert Mustacchi 		pba_num[4] = (pba_ptr >> 12) & 0xF;
82075eba5b6SRobert Mustacchi 		pba_num[5] = (pba_ptr >> 8) & 0xF;
82175eba5b6SRobert Mustacchi 		pba_num[6] = '-';
82275eba5b6SRobert Mustacchi 		pba_num[7] = 0;
82375eba5b6SRobert Mustacchi 		pba_num[8] = (pba_ptr >> 4) & 0xF;
82475eba5b6SRobert Mustacchi 		pba_num[9] = pba_ptr & 0xF;
82575eba5b6SRobert Mustacchi 
82675eba5b6SRobert Mustacchi 		/* put a null character on the end of our string */
82775eba5b6SRobert Mustacchi 		pba_num[10] = '\0';
82875eba5b6SRobert Mustacchi 
82975eba5b6SRobert Mustacchi 		/* switch all the data but the '-' to hex char */
83075eba5b6SRobert Mustacchi 		for (offset = 0; offset < 10; offset++) {
83175eba5b6SRobert Mustacchi 			if (pba_num[offset] < 0xA)
83275eba5b6SRobert Mustacchi 				pba_num[offset] += '0';
83375eba5b6SRobert Mustacchi 			else if (pba_num[offset] < 0x10)
83475eba5b6SRobert Mustacchi 				pba_num[offset] += 'A' - 0xA;
83575eba5b6SRobert Mustacchi 		}
83675eba5b6SRobert Mustacchi 
83775eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
83875eba5b6SRobert Mustacchi 	}
83975eba5b6SRobert Mustacchi 
84075eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
84175eba5b6SRobert Mustacchi 	if (ret_val) {
84275eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
84375eba5b6SRobert Mustacchi 		return ret_val;
84475eba5b6SRobert Mustacchi 	}
84575eba5b6SRobert Mustacchi 
84675eba5b6SRobert Mustacchi 	if (length == 0xFFFF || length == 0) {
84775eba5b6SRobert Mustacchi 		DEBUGOUT("NVM PBA number section invalid length\n");
84875eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM_PBA_SECTION;
84975eba5b6SRobert Mustacchi 	}
85075eba5b6SRobert Mustacchi 	/* check if pba_num buffer is big enough */
85175eba5b6SRobert Mustacchi 	if (pba_num_size < (((u32)length * 2) - 1)) {
85275eba5b6SRobert Mustacchi 		DEBUGOUT("PBA string buffer too small\n");
85375eba5b6SRobert Mustacchi 		return -E1000_ERR_NO_SPACE;
85475eba5b6SRobert Mustacchi 	}
85575eba5b6SRobert Mustacchi 
85675eba5b6SRobert Mustacchi 	/* trim pba length from start of string */
85775eba5b6SRobert Mustacchi 	pba_ptr++;
85875eba5b6SRobert Mustacchi 	length--;
85975eba5b6SRobert Mustacchi 
86075eba5b6SRobert Mustacchi 	for (offset = 0; offset < length; offset++) {
86175eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
86275eba5b6SRobert Mustacchi 		if (ret_val) {
86375eba5b6SRobert Mustacchi 			DEBUGOUT("NVM Read Error\n");
86475eba5b6SRobert Mustacchi 			return ret_val;
86575eba5b6SRobert Mustacchi 		}
86675eba5b6SRobert Mustacchi 		pba_num[offset * 2] = (u8)(nvm_data >> 8);
86775eba5b6SRobert Mustacchi 		pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
86875eba5b6SRobert Mustacchi 	}
86975eba5b6SRobert Mustacchi 	pba_num[offset * 2] = '\0';
87075eba5b6SRobert Mustacchi 
87175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
87275eba5b6SRobert Mustacchi }
87375eba5b6SRobert Mustacchi 
87475eba5b6SRobert Mustacchi /**
87575eba5b6SRobert Mustacchi  *  e1000_read_pba_length_generic - Read device part number length
87675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
87775eba5b6SRobert Mustacchi  *  @pba_num_size: size of part number buffer
87875eba5b6SRobert Mustacchi  *
87975eba5b6SRobert Mustacchi  *  Reads the product board assembly (PBA) number length from the EEPROM and
88075eba5b6SRobert Mustacchi  *  stores the value in pba_num_size.
88175eba5b6SRobert Mustacchi  **/
e1000_read_pba_length_generic(struct e1000_hw * hw,u32 * pba_num_size)88275eba5b6SRobert Mustacchi s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
88375eba5b6SRobert Mustacchi {
88475eba5b6SRobert Mustacchi 	s32 ret_val;
88575eba5b6SRobert Mustacchi 	u16 nvm_data;
88675eba5b6SRobert Mustacchi 	u16 pba_ptr;
88775eba5b6SRobert Mustacchi 	u16 length;
88875eba5b6SRobert Mustacchi 
88975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_pba_length_generic");
89075eba5b6SRobert Mustacchi 
89175eba5b6SRobert Mustacchi 	if (pba_num_size == NULL) {
89275eba5b6SRobert Mustacchi 		DEBUGOUT("PBA buffer size was null\n");
89375eba5b6SRobert Mustacchi 		return -E1000_ERR_INVALID_ARGUMENT;
89475eba5b6SRobert Mustacchi 	}
89575eba5b6SRobert Mustacchi 
89675eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
89775eba5b6SRobert Mustacchi 	if (ret_val) {
89875eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
89975eba5b6SRobert Mustacchi 		return ret_val;
90075eba5b6SRobert Mustacchi 	}
90175eba5b6SRobert Mustacchi 
90275eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
90375eba5b6SRobert Mustacchi 	if (ret_val) {
90475eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
90575eba5b6SRobert Mustacchi 		return ret_val;
90675eba5b6SRobert Mustacchi 	}
90775eba5b6SRobert Mustacchi 
90875eba5b6SRobert Mustacchi 	 /* if data is not ptr guard the PBA must be in legacy format */
90975eba5b6SRobert Mustacchi 	if (nvm_data != NVM_PBA_PTR_GUARD) {
91075eba5b6SRobert Mustacchi 		*pba_num_size = E1000_PBANUM_LENGTH;
91175eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
91275eba5b6SRobert Mustacchi 	}
91375eba5b6SRobert Mustacchi 
91475eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
91575eba5b6SRobert Mustacchi 	if (ret_val) {
91675eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
91775eba5b6SRobert Mustacchi 		return ret_val;
91875eba5b6SRobert Mustacchi 	}
91975eba5b6SRobert Mustacchi 
92075eba5b6SRobert Mustacchi 	if (length == 0xFFFF || length == 0) {
92175eba5b6SRobert Mustacchi 		DEBUGOUT("NVM PBA number section invalid length\n");
92275eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM_PBA_SECTION;
92375eba5b6SRobert Mustacchi 	}
92475eba5b6SRobert Mustacchi 
92575eba5b6SRobert Mustacchi 	/* Convert from length in u16 values to u8 chars, add 1 for NULL,
92675eba5b6SRobert Mustacchi 	 * and subtract 2 because length field is included in length.
92775eba5b6SRobert Mustacchi 	 */
92875eba5b6SRobert Mustacchi 	*pba_num_size = ((u32)length * 2) - 1;
92975eba5b6SRobert Mustacchi 
93075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
93175eba5b6SRobert Mustacchi }
93275eba5b6SRobert Mustacchi 
93375eba5b6SRobert Mustacchi 
93475eba5b6SRobert Mustacchi /**
93575eba5b6SRobert Mustacchi  *  e1000_read_pba_raw
93675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
93775eba5b6SRobert Mustacchi  *  @eeprom_buf: optional pointer to EEPROM image
93875eba5b6SRobert Mustacchi  *  @eeprom_buf_size: size of EEPROM image in words
93975eba5b6SRobert Mustacchi  *  @max_pba_block_size: PBA block size limit
94075eba5b6SRobert Mustacchi  *  @pba: pointer to output PBA structure
94175eba5b6SRobert Mustacchi  *
94275eba5b6SRobert Mustacchi  *  Reads PBA from EEPROM image when eeprom_buf is not NULL.
94375eba5b6SRobert Mustacchi  *  Reads PBA from physical EEPROM device when eeprom_buf is NULL.
94475eba5b6SRobert Mustacchi  *
94575eba5b6SRobert Mustacchi  **/
e1000_read_pba_raw(struct e1000_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,u16 max_pba_block_size,struct e1000_pba * pba)94675eba5b6SRobert Mustacchi s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
94775eba5b6SRobert Mustacchi 		       u32 eeprom_buf_size, u16 max_pba_block_size,
94875eba5b6SRobert Mustacchi 		       struct e1000_pba *pba)
94975eba5b6SRobert Mustacchi {
95075eba5b6SRobert Mustacchi 	s32 ret_val;
95175eba5b6SRobert Mustacchi 	u16 pba_block_size;
95275eba5b6SRobert Mustacchi 
95375eba5b6SRobert Mustacchi 	if (pba == NULL)
95475eba5b6SRobert Mustacchi 		return -E1000_ERR_PARAM;
95575eba5b6SRobert Mustacchi 
95675eba5b6SRobert Mustacchi 	if (eeprom_buf == NULL) {
95775eba5b6SRobert Mustacchi 		ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
95875eba5b6SRobert Mustacchi 					 &pba->word[0]);
95975eba5b6SRobert Mustacchi 		if (ret_val)
96075eba5b6SRobert Mustacchi 			return ret_val;
96175eba5b6SRobert Mustacchi 	} else {
96275eba5b6SRobert Mustacchi 		if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
96375eba5b6SRobert Mustacchi 			pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
96475eba5b6SRobert Mustacchi 			pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
96575eba5b6SRobert Mustacchi 		} else {
96675eba5b6SRobert Mustacchi 			return -E1000_ERR_PARAM;
96775eba5b6SRobert Mustacchi 		}
96875eba5b6SRobert Mustacchi 	}
96975eba5b6SRobert Mustacchi 
97075eba5b6SRobert Mustacchi 	if (pba->word[0] == NVM_PBA_PTR_GUARD) {
97175eba5b6SRobert Mustacchi 		if (pba->pba_block == NULL)
97275eba5b6SRobert Mustacchi 			return -E1000_ERR_PARAM;
97375eba5b6SRobert Mustacchi 
97475eba5b6SRobert Mustacchi 		ret_val = e1000_get_pba_block_size(hw, eeprom_buf,
97575eba5b6SRobert Mustacchi 						   eeprom_buf_size,
97675eba5b6SRobert Mustacchi 						   &pba_block_size);
97775eba5b6SRobert Mustacchi 		if (ret_val)
97875eba5b6SRobert Mustacchi 			return ret_val;
97975eba5b6SRobert Mustacchi 
98075eba5b6SRobert Mustacchi 		if (pba_block_size > max_pba_block_size)
98175eba5b6SRobert Mustacchi 			return -E1000_ERR_PARAM;
98275eba5b6SRobert Mustacchi 
98375eba5b6SRobert Mustacchi 		if (eeprom_buf == NULL) {
98475eba5b6SRobert Mustacchi 			ret_val = e1000_read_nvm(hw, pba->word[1],
98575eba5b6SRobert Mustacchi 						 pba_block_size,
98675eba5b6SRobert Mustacchi 						 pba->pba_block);
98775eba5b6SRobert Mustacchi 			if (ret_val)
98875eba5b6SRobert Mustacchi 				return ret_val;
98975eba5b6SRobert Mustacchi 		} else {
99075eba5b6SRobert Mustacchi 			if (eeprom_buf_size > (u32)(pba->word[1] +
991c124a83eSRobert Mustacchi 					      pba_block_size)) {
99275eba5b6SRobert Mustacchi 				memcpy(pba->pba_block,
99375eba5b6SRobert Mustacchi 				       &eeprom_buf[pba->word[1]],
99475eba5b6SRobert Mustacchi 				       pba_block_size * sizeof(u16));
99575eba5b6SRobert Mustacchi 			} else {
99675eba5b6SRobert Mustacchi 				return -E1000_ERR_PARAM;
99775eba5b6SRobert Mustacchi 			}
99875eba5b6SRobert Mustacchi 		}
99975eba5b6SRobert Mustacchi 	}
100075eba5b6SRobert Mustacchi 
100175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
100275eba5b6SRobert Mustacchi }
100375eba5b6SRobert Mustacchi 
100475eba5b6SRobert Mustacchi /**
100575eba5b6SRobert Mustacchi  *  e1000_write_pba_raw
100675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
100775eba5b6SRobert Mustacchi  *  @eeprom_buf: optional pointer to EEPROM image
100875eba5b6SRobert Mustacchi  *  @eeprom_buf_size: size of EEPROM image in words
100975eba5b6SRobert Mustacchi  *  @pba: pointer to PBA structure
101075eba5b6SRobert Mustacchi  *
101175eba5b6SRobert Mustacchi  *  Writes PBA to EEPROM image when eeprom_buf is not NULL.
101275eba5b6SRobert Mustacchi  *  Writes PBA to physical EEPROM device when eeprom_buf is NULL.
101375eba5b6SRobert Mustacchi  *
101475eba5b6SRobert Mustacchi  **/
e1000_write_pba_raw(struct e1000_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,struct e1000_pba * pba)101575eba5b6SRobert Mustacchi s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
101675eba5b6SRobert Mustacchi 			u32 eeprom_buf_size, struct e1000_pba *pba)
101775eba5b6SRobert Mustacchi {
101875eba5b6SRobert Mustacchi 	s32 ret_val;
101975eba5b6SRobert Mustacchi 
102075eba5b6SRobert Mustacchi 	if (pba == NULL)
102175eba5b6SRobert Mustacchi 		return -E1000_ERR_PARAM;
102275eba5b6SRobert Mustacchi 
102375eba5b6SRobert Mustacchi 	if (eeprom_buf == NULL) {
102475eba5b6SRobert Mustacchi 		ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
102575eba5b6SRobert Mustacchi 					  &pba->word[0]);
102675eba5b6SRobert Mustacchi 		if (ret_val)
102775eba5b6SRobert Mustacchi 			return ret_val;
102875eba5b6SRobert Mustacchi 	} else {
102975eba5b6SRobert Mustacchi 		if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
103075eba5b6SRobert Mustacchi 			eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
103175eba5b6SRobert Mustacchi 			eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
103275eba5b6SRobert Mustacchi 		} else {
103375eba5b6SRobert Mustacchi 			return -E1000_ERR_PARAM;
103475eba5b6SRobert Mustacchi 		}
103575eba5b6SRobert Mustacchi 	}
103675eba5b6SRobert Mustacchi 
103775eba5b6SRobert Mustacchi 	if (pba->word[0] == NVM_PBA_PTR_GUARD) {
103875eba5b6SRobert Mustacchi 		if (pba->pba_block == NULL)
103975eba5b6SRobert Mustacchi 			return -E1000_ERR_PARAM;
104075eba5b6SRobert Mustacchi 
104175eba5b6SRobert Mustacchi 		if (eeprom_buf == NULL) {
104275eba5b6SRobert Mustacchi 			ret_val = e1000_write_nvm(hw, pba->word[1],
104375eba5b6SRobert Mustacchi 						  pba->pba_block[0],
104475eba5b6SRobert Mustacchi 						  pba->pba_block);
104575eba5b6SRobert Mustacchi 			if (ret_val)
104675eba5b6SRobert Mustacchi 				return ret_val;
104775eba5b6SRobert Mustacchi 		} else {
104875eba5b6SRobert Mustacchi 			if (eeprom_buf_size > (u32)(pba->word[1] +
104975eba5b6SRobert Mustacchi 					      pba->pba_block[0])) {
105075eba5b6SRobert Mustacchi 				memcpy(&eeprom_buf[pba->word[1]],
105175eba5b6SRobert Mustacchi 				       pba->pba_block,
105275eba5b6SRobert Mustacchi 				       pba->pba_block[0] * sizeof(u16));
105375eba5b6SRobert Mustacchi 			} else {
105475eba5b6SRobert Mustacchi 				return -E1000_ERR_PARAM;
105575eba5b6SRobert Mustacchi 			}
105675eba5b6SRobert Mustacchi 		}
105775eba5b6SRobert Mustacchi 	}
105875eba5b6SRobert Mustacchi 
105975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
106075eba5b6SRobert Mustacchi }
106175eba5b6SRobert Mustacchi 
106275eba5b6SRobert Mustacchi /**
106375eba5b6SRobert Mustacchi  *  e1000_get_pba_block_size
106475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
106575eba5b6SRobert Mustacchi  *  @eeprom_buf: optional pointer to EEPROM image
106675eba5b6SRobert Mustacchi  *  @eeprom_buf_size: size of EEPROM image in words
106775eba5b6SRobert Mustacchi  *  @pba_data_size: pointer to output variable
106875eba5b6SRobert Mustacchi  *
106975eba5b6SRobert Mustacchi  *  Returns the size of the PBA block in words. Function operates on EEPROM
107075eba5b6SRobert Mustacchi  *  image if the eeprom_buf pointer is not NULL otherwise it accesses physical
107175eba5b6SRobert Mustacchi  *  EEPROM device.
107275eba5b6SRobert Mustacchi  *
107375eba5b6SRobert Mustacchi  **/
e1000_get_pba_block_size(struct e1000_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,u16 * pba_block_size)107475eba5b6SRobert Mustacchi s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
107575eba5b6SRobert Mustacchi 			     u32 eeprom_buf_size, u16 *pba_block_size)
107675eba5b6SRobert Mustacchi {
107775eba5b6SRobert Mustacchi 	s32 ret_val;
107875eba5b6SRobert Mustacchi 	u16 pba_word[2];
107975eba5b6SRobert Mustacchi 	u16 length;
108075eba5b6SRobert Mustacchi 
108175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_pba_block_size");
108275eba5b6SRobert Mustacchi 
108375eba5b6SRobert Mustacchi 	if (eeprom_buf == NULL) {
108475eba5b6SRobert Mustacchi 		ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
108575eba5b6SRobert Mustacchi 		if (ret_val)
108675eba5b6SRobert Mustacchi 			return ret_val;
108775eba5b6SRobert Mustacchi 	} else {
108875eba5b6SRobert Mustacchi 		if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
108975eba5b6SRobert Mustacchi 			pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
109075eba5b6SRobert Mustacchi 			pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
109175eba5b6SRobert Mustacchi 		} else {
109275eba5b6SRobert Mustacchi 			return -E1000_ERR_PARAM;
109375eba5b6SRobert Mustacchi 		}
109475eba5b6SRobert Mustacchi 	}
109575eba5b6SRobert Mustacchi 
109675eba5b6SRobert Mustacchi 	if (pba_word[0] == NVM_PBA_PTR_GUARD) {
109775eba5b6SRobert Mustacchi 		if (eeprom_buf == NULL) {
109875eba5b6SRobert Mustacchi 			ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1,
109975eba5b6SRobert Mustacchi 						 &length);
110075eba5b6SRobert Mustacchi 			if (ret_val)
110175eba5b6SRobert Mustacchi 				return ret_val;
110275eba5b6SRobert Mustacchi 		} else {
110375eba5b6SRobert Mustacchi 			if (eeprom_buf_size > pba_word[1])
110475eba5b6SRobert Mustacchi 				length = eeprom_buf[pba_word[1] + 0];
110575eba5b6SRobert Mustacchi 			else
110675eba5b6SRobert Mustacchi 				return -E1000_ERR_PARAM;
110775eba5b6SRobert Mustacchi 		}
110875eba5b6SRobert Mustacchi 
110975eba5b6SRobert Mustacchi 		if (length == 0xFFFF || length == 0)
111075eba5b6SRobert Mustacchi 			return -E1000_ERR_NVM_PBA_SECTION;
111175eba5b6SRobert Mustacchi 	} else {
111275eba5b6SRobert Mustacchi 		/* PBA number in legacy format, there is no PBA Block. */
111375eba5b6SRobert Mustacchi 		length = 0;
111475eba5b6SRobert Mustacchi 	}
111575eba5b6SRobert Mustacchi 
111675eba5b6SRobert Mustacchi 	if (pba_block_size != NULL)
111775eba5b6SRobert Mustacchi 		*pba_block_size = length;
111875eba5b6SRobert Mustacchi 
111975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
112075eba5b6SRobert Mustacchi }
112175eba5b6SRobert Mustacchi 
112275eba5b6SRobert Mustacchi /**
112375eba5b6SRobert Mustacchi  *  e1000_read_mac_addr_generic - Read device MAC address
112475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
112575eba5b6SRobert Mustacchi  *
112675eba5b6SRobert Mustacchi  *  Reads the device MAC address from the EEPROM and stores the value.
112775eba5b6SRobert Mustacchi  *  Since devices with two ports use the same EEPROM, we increment the
112875eba5b6SRobert Mustacchi  *  last bit in the MAC address for the second port.
112975eba5b6SRobert Mustacchi  **/
e1000_read_mac_addr_generic(struct e1000_hw * hw)113075eba5b6SRobert Mustacchi s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
113175eba5b6SRobert Mustacchi {
113275eba5b6SRobert Mustacchi 	u32 rar_high;
113375eba5b6SRobert Mustacchi 	u32 rar_low;
113475eba5b6SRobert Mustacchi 	u16 i;
113575eba5b6SRobert Mustacchi 
113675eba5b6SRobert Mustacchi 	rar_high = E1000_READ_REG(hw, E1000_RAH(0));
113775eba5b6SRobert Mustacchi 	rar_low = E1000_READ_REG(hw, E1000_RAL(0));
113875eba5b6SRobert Mustacchi 
113975eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
114075eba5b6SRobert Mustacchi 		hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
114175eba5b6SRobert Mustacchi 
114275eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
114375eba5b6SRobert Mustacchi 		hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
114475eba5b6SRobert Mustacchi 
114575eba5b6SRobert Mustacchi 	for (i = 0; i < ETH_ADDR_LEN; i++)
114675eba5b6SRobert Mustacchi 		hw->mac.addr[i] = hw->mac.perm_addr[i];
114775eba5b6SRobert Mustacchi 
114875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
114975eba5b6SRobert Mustacchi }
115075eba5b6SRobert Mustacchi 
115175eba5b6SRobert Mustacchi /**
115275eba5b6SRobert Mustacchi  *  e1000_validate_nvm_checksum_generic - Validate EEPROM checksum
115375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
115475eba5b6SRobert Mustacchi  *
115575eba5b6SRobert Mustacchi  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
115675eba5b6SRobert Mustacchi  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
115775eba5b6SRobert Mustacchi  **/
e1000_validate_nvm_checksum_generic(struct e1000_hw * hw)115875eba5b6SRobert Mustacchi s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
115975eba5b6SRobert Mustacchi {
116075eba5b6SRobert Mustacchi 	s32 ret_val;
116175eba5b6SRobert Mustacchi 	u16 checksum = 0;
116275eba5b6SRobert Mustacchi 	u16 i, nvm_data;
116375eba5b6SRobert Mustacchi 
116475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_validate_nvm_checksum_generic");
116575eba5b6SRobert Mustacchi 
116675eba5b6SRobert Mustacchi 	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
116775eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
116875eba5b6SRobert Mustacchi 		if (ret_val) {
116975eba5b6SRobert Mustacchi 			DEBUGOUT("NVM Read Error\n");
117075eba5b6SRobert Mustacchi 			return ret_val;
117175eba5b6SRobert Mustacchi 		}
117275eba5b6SRobert Mustacchi 		checksum += nvm_data;
117375eba5b6SRobert Mustacchi 	}
117475eba5b6SRobert Mustacchi 
117575eba5b6SRobert Mustacchi 	if (checksum != (u16) NVM_SUM) {
117675eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Checksum Invalid\n");
117775eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
117875eba5b6SRobert Mustacchi 	}
117975eba5b6SRobert Mustacchi 
118075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
118175eba5b6SRobert Mustacchi }
118275eba5b6SRobert Mustacchi 
118375eba5b6SRobert Mustacchi /**
118475eba5b6SRobert Mustacchi  *  e1000_update_nvm_checksum_generic - Update EEPROM checksum
118575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
118675eba5b6SRobert Mustacchi  *
118775eba5b6SRobert Mustacchi  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
118875eba5b6SRobert Mustacchi  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
118975eba5b6SRobert Mustacchi  *  value to the EEPROM.
119075eba5b6SRobert Mustacchi  **/
e1000_update_nvm_checksum_generic(struct e1000_hw * hw)119175eba5b6SRobert Mustacchi s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
119275eba5b6SRobert Mustacchi {
119375eba5b6SRobert Mustacchi 	s32 ret_val;
119475eba5b6SRobert Mustacchi 	u16 checksum = 0;
119575eba5b6SRobert Mustacchi 	u16 i, nvm_data;
119675eba5b6SRobert Mustacchi 
119775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_update_nvm_checksum");
119875eba5b6SRobert Mustacchi 
119975eba5b6SRobert Mustacchi 	for (i = 0; i < NVM_CHECKSUM_REG; i++) {
120075eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
120175eba5b6SRobert Mustacchi 		if (ret_val) {
120275eba5b6SRobert Mustacchi 			DEBUGOUT("NVM Read Error while updating checksum.\n");
120375eba5b6SRobert Mustacchi 			return ret_val;
120475eba5b6SRobert Mustacchi 		}
120575eba5b6SRobert Mustacchi 		checksum += nvm_data;
120675eba5b6SRobert Mustacchi 	}
120775eba5b6SRobert Mustacchi 	checksum = (u16) NVM_SUM - checksum;
120875eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
120975eba5b6SRobert Mustacchi 	if (ret_val)
121075eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Write Error while updating checksum.\n");
121175eba5b6SRobert Mustacchi 
121275eba5b6SRobert Mustacchi 	return ret_val;
121375eba5b6SRobert Mustacchi }
121475eba5b6SRobert Mustacchi 
121575eba5b6SRobert Mustacchi /**
121675eba5b6SRobert Mustacchi  *  e1000_reload_nvm_generic - Reloads EEPROM
121775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
121875eba5b6SRobert Mustacchi  *
121975eba5b6SRobert Mustacchi  *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
122075eba5b6SRobert Mustacchi  *  extended control register.
122175eba5b6SRobert Mustacchi  **/
e1000_reload_nvm_generic(struct e1000_hw * hw)122275eba5b6SRobert Mustacchi static void e1000_reload_nvm_generic(struct e1000_hw *hw)
122375eba5b6SRobert Mustacchi {
122475eba5b6SRobert Mustacchi 	u32 ctrl_ext;
122575eba5b6SRobert Mustacchi 
122675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_reload_nvm_generic");
122775eba5b6SRobert Mustacchi 
122875eba5b6SRobert Mustacchi 	usec_delay(10);
122975eba5b6SRobert Mustacchi 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
123075eba5b6SRobert Mustacchi 	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
123175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
123275eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
123375eba5b6SRobert Mustacchi }
1234c124a83eSRobert Mustacchi 
1235c124a83eSRobert Mustacchi 
1236