xref: /dflybsd-src/sys/dev/netif/ig_hal/e1000_nvm.c (revision 01a55482b42bba8de64caeb8c9ede647a9208734)
19c80d176SSepherosa Ziehau /******************************************************************************
29c80d176SSepherosa Ziehau 
3*01a55482SSepherosa Ziehau   Copyright (c) 2001-2019, Intel Corporation
49c80d176SSepherosa Ziehau   All rights reserved.
59c80d176SSepherosa Ziehau 
69c80d176SSepherosa Ziehau   Redistribution and use in source and binary forms, with or without
79c80d176SSepherosa Ziehau   modification, are permitted provided that the following conditions are met:
89c80d176SSepherosa Ziehau 
99c80d176SSepherosa Ziehau    1. Redistributions of source code must retain the above copyright notice,
109c80d176SSepherosa Ziehau       this list of conditions and the following disclaimer.
119c80d176SSepherosa Ziehau 
129c80d176SSepherosa Ziehau    2. Redistributions in binary form must reproduce the above copyright
139c80d176SSepherosa Ziehau       notice, this list of conditions and the following disclaimer in the
149c80d176SSepherosa Ziehau       documentation and/or other materials provided with the distribution.
159c80d176SSepherosa Ziehau 
169c80d176SSepherosa Ziehau    3. Neither the name of the Intel Corporation nor the names of its
179c80d176SSepherosa Ziehau       contributors may be used to endorse or promote products derived from
189c80d176SSepherosa Ziehau       this software without specific prior written permission.
199c80d176SSepherosa Ziehau 
209c80d176SSepherosa Ziehau   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
219c80d176SSepherosa Ziehau   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229c80d176SSepherosa Ziehau   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239c80d176SSepherosa Ziehau   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
249c80d176SSepherosa Ziehau   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259c80d176SSepherosa Ziehau   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269c80d176SSepherosa Ziehau   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279c80d176SSepherosa Ziehau   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289c80d176SSepherosa Ziehau   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299c80d176SSepherosa Ziehau   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309c80d176SSepherosa Ziehau   POSSIBILITY OF SUCH DAMAGE.
319c80d176SSepherosa Ziehau 
329c80d176SSepherosa Ziehau ******************************************************************************/
3374dc3754SSepherosa Ziehau /*$FreeBSD$*/
349c80d176SSepherosa Ziehau 
359c80d176SSepherosa Ziehau #include "e1000_api.h"
369c80d176SSepherosa Ziehau 
376a5a645eSSepherosa Ziehau static void e1000_reload_nvm_generic(struct e1000_hw *hw);
386a5a645eSSepherosa Ziehau 
399c80d176SSepherosa Ziehau /**
409c80d176SSepherosa Ziehau  *  e1000_init_nvm_ops_generic - Initialize NVM function pointers
419c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
429c80d176SSepherosa Ziehau  *
439c80d176SSepherosa Ziehau  *  Setups up the function pointers to no-op functions
449c80d176SSepherosa Ziehau  **/
e1000_init_nvm_ops_generic(struct e1000_hw * hw)459c80d176SSepherosa Ziehau void e1000_init_nvm_ops_generic(struct e1000_hw *hw)
469c80d176SSepherosa Ziehau {
479c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
489c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_init_nvm_ops_generic");
499c80d176SSepherosa Ziehau 
509c80d176SSepherosa Ziehau 	/* Initialize function pointers */
519c80d176SSepherosa Ziehau 	nvm->ops.init_params = e1000_null_ops_generic;
529c80d176SSepherosa Ziehau 	nvm->ops.acquire = e1000_null_ops_generic;
539c80d176SSepherosa Ziehau 	nvm->ops.read = e1000_null_read_nvm;
549c80d176SSepherosa Ziehau 	nvm->ops.release = e1000_null_nvm_generic;
559c80d176SSepherosa Ziehau 	nvm->ops.reload = e1000_reload_nvm_generic;
569c80d176SSepherosa Ziehau 	nvm->ops.update = e1000_null_ops_generic;
579c80d176SSepherosa Ziehau 	nvm->ops.valid_led_default = e1000_null_led_default;
589c80d176SSepherosa Ziehau 	nvm->ops.validate = e1000_null_ops_generic;
599c80d176SSepherosa Ziehau 	nvm->ops.write = e1000_null_write_nvm;
609c80d176SSepherosa Ziehau }
619c80d176SSepherosa Ziehau 
629c80d176SSepherosa Ziehau /**
639c80d176SSepherosa Ziehau  *  e1000_null_nvm_read - No-op function, return 0
649c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
65*01a55482SSepherosa Ziehau  *  @a: dummy variable
66*01a55482SSepherosa Ziehau  *  @b: dummy variable
67*01a55482SSepherosa Ziehau  *  @c: dummy variable
689c80d176SSepherosa Ziehau  **/
e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG a,u16 E1000_UNUSEDARG b,u16 E1000_UNUSEDARG * c)69379ebbe7SSepherosa Ziehau s32 e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG *hw,
70379ebbe7SSepherosa Ziehau 			u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b,
71379ebbe7SSepherosa Ziehau 			u16 E1000_UNUSEDARG *c)
729c80d176SSepherosa Ziehau {
739c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_read_nvm");
749c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
759c80d176SSepherosa Ziehau }
769c80d176SSepherosa Ziehau 
779c80d176SSepherosa Ziehau /**
789c80d176SSepherosa Ziehau  *  e1000_null_nvm_generic - No-op function, return void
799c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
809c80d176SSepherosa Ziehau  **/
e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG * hw)81379ebbe7SSepherosa Ziehau void e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG *hw)
829c80d176SSepherosa Ziehau {
839c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_nvm_generic");
849c80d176SSepherosa Ziehau 	return;
859c80d176SSepherosa Ziehau }
869c80d176SSepherosa Ziehau 
879c80d176SSepherosa Ziehau /**
889c80d176SSepherosa Ziehau  *  e1000_null_led_default - No-op function, return 0
899c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
90*01a55482SSepherosa Ziehau  *  @data: dummy variable
919c80d176SSepherosa Ziehau  **/
e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG * data)92379ebbe7SSepherosa Ziehau s32 e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG *hw,
93379ebbe7SSepherosa Ziehau 			   u16 E1000_UNUSEDARG *data)
949c80d176SSepherosa Ziehau {
959c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_led_default");
969c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
979c80d176SSepherosa Ziehau }
989c80d176SSepherosa Ziehau 
999c80d176SSepherosa Ziehau /**
1009c80d176SSepherosa Ziehau  *  e1000_null_write_nvm - No-op function, return 0
1019c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
102*01a55482SSepherosa Ziehau  *  @a: dummy variable
103*01a55482SSepherosa Ziehau  *  @b: dummy variable
104*01a55482SSepherosa Ziehau  *  @c: dummy variable
1059c80d176SSepherosa Ziehau  **/
e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG a,u16 E1000_UNUSEDARG b,u16 E1000_UNUSEDARG * c)106379ebbe7SSepherosa Ziehau s32 e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG *hw,
107379ebbe7SSepherosa Ziehau 			 u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b,
108379ebbe7SSepherosa Ziehau 			 u16 E1000_UNUSEDARG *c)
1099c80d176SSepherosa Ziehau {
1109c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_write_nvm");
1119c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
1129c80d176SSepherosa Ziehau }
1139c80d176SSepherosa Ziehau 
1149c80d176SSepherosa Ziehau /**
1159c80d176SSepherosa Ziehau  *  e1000_raise_eec_clk - Raise EEPROM clock
1169c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
1179c80d176SSepherosa Ziehau  *  @eecd: pointer to the EEPROM
1189c80d176SSepherosa Ziehau  *
1199c80d176SSepherosa Ziehau  *  Enable/Raise the EEPROM clock bit.
1209c80d176SSepherosa Ziehau  **/
e1000_raise_eec_clk(struct e1000_hw * hw,u32 * eecd)1219c80d176SSepherosa Ziehau static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
1229c80d176SSepherosa Ziehau {
1239c80d176SSepherosa Ziehau 	*eecd = *eecd | E1000_EECD_SK;
1249c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_EECD, *eecd);
1259c80d176SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
1269c80d176SSepherosa Ziehau 	usec_delay(hw->nvm.delay_usec);
1279c80d176SSepherosa Ziehau }
1289c80d176SSepherosa Ziehau 
1299c80d176SSepherosa Ziehau /**
1309c80d176SSepherosa Ziehau  *  e1000_lower_eec_clk - Lower EEPROM clock
1319c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
1329c80d176SSepherosa Ziehau  *  @eecd: pointer to the EEPROM
1339c80d176SSepherosa Ziehau  *
1349c80d176SSepherosa Ziehau  *  Clear/Lower the EEPROM clock bit.
1359c80d176SSepherosa Ziehau  **/
e1000_lower_eec_clk(struct e1000_hw * hw,u32 * eecd)1369c80d176SSepherosa Ziehau static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
1379c80d176SSepherosa Ziehau {
1389c80d176SSepherosa Ziehau 	*eecd = *eecd & ~E1000_EECD_SK;
1399c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_EECD, *eecd);
1409c80d176SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
1419c80d176SSepherosa Ziehau 	usec_delay(hw->nvm.delay_usec);
1429c80d176SSepherosa Ziehau }
1439c80d176SSepherosa Ziehau 
1449c80d176SSepherosa Ziehau /**
1459c80d176SSepherosa Ziehau  *  e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
1469c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
1479c80d176SSepherosa Ziehau  *  @data: data to send to the EEPROM
1489c80d176SSepherosa Ziehau  *  @count: number of bits to shift out
1499c80d176SSepherosa Ziehau  *
1509c80d176SSepherosa Ziehau  *  We need to shift 'count' bits out to the EEPROM.  So, the value in the
1519c80d176SSepherosa Ziehau  *  "data" parameter will be shifted out to the EEPROM one bit at a time.
1529c80d176SSepherosa Ziehau  *  In order to do this, "data" must be broken down into bits.
1539c80d176SSepherosa Ziehau  **/
e1000_shift_out_eec_bits(struct e1000_hw * hw,u16 data,u16 count)1549c80d176SSepherosa Ziehau static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
1559c80d176SSepherosa Ziehau {
1569c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
1579c80d176SSepherosa Ziehau 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1589c80d176SSepherosa Ziehau 	u32 mask;
1599c80d176SSepherosa Ziehau 
1609c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_shift_out_eec_bits");
1619c80d176SSepherosa Ziehau 
1629c80d176SSepherosa Ziehau 	mask = 0x01 << (count - 1);
1639c80d176SSepherosa Ziehau 	if (nvm->type == e1000_nvm_eeprom_microwire)
1649c80d176SSepherosa Ziehau 		eecd &= ~E1000_EECD_DO;
1659c80d176SSepherosa Ziehau 	else
1669c80d176SSepherosa Ziehau 	if (nvm->type == e1000_nvm_eeprom_spi)
1679c80d176SSepherosa Ziehau 		eecd |= E1000_EECD_DO;
1689c80d176SSepherosa Ziehau 
1699c80d176SSepherosa Ziehau 	do {
1709c80d176SSepherosa Ziehau 		eecd &= ~E1000_EECD_DI;
1719c80d176SSepherosa Ziehau 
1729c80d176SSepherosa Ziehau 		if (data & mask)
1739c80d176SSepherosa Ziehau 			eecd |= E1000_EECD_DI;
1749c80d176SSepherosa Ziehau 
1759c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
1769c80d176SSepherosa Ziehau 		E1000_WRITE_FLUSH(hw);
1779c80d176SSepherosa Ziehau 
1789c80d176SSepherosa Ziehau 		usec_delay(nvm->delay_usec);
1799c80d176SSepherosa Ziehau 
1809c80d176SSepherosa Ziehau 		e1000_raise_eec_clk(hw, &eecd);
1819c80d176SSepherosa Ziehau 		e1000_lower_eec_clk(hw, &eecd);
1829c80d176SSepherosa Ziehau 
1839c80d176SSepherosa Ziehau 		mask >>= 1;
1849c80d176SSepherosa Ziehau 	} while (mask);
1859c80d176SSepherosa Ziehau 
1869c80d176SSepherosa Ziehau 	eecd &= ~E1000_EECD_DI;
1879c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_EECD, eecd);
1889c80d176SSepherosa Ziehau }
1899c80d176SSepherosa Ziehau 
1909c80d176SSepherosa Ziehau /**
1919c80d176SSepherosa Ziehau  *  e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
1929c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
1939c80d176SSepherosa Ziehau  *  @count: number of bits to shift in
1949c80d176SSepherosa Ziehau  *
1959c80d176SSepherosa Ziehau  *  In order to read a register from the EEPROM, we need to shift 'count' bits
1969c80d176SSepherosa Ziehau  *  in from the EEPROM.  Bits are "shifted in" by raising the clock input to
1979c80d176SSepherosa Ziehau  *  the EEPROM (setting the SK bit), and then reading the value of the data out
1989c80d176SSepherosa Ziehau  *  "DO" bit.  During this "shifting in" process the data in "DI" bit should
1999c80d176SSepherosa Ziehau  *  always be clear.
2009c80d176SSepherosa Ziehau  **/
e1000_shift_in_eec_bits(struct e1000_hw * hw,u16 count)2019c80d176SSepherosa Ziehau static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
2029c80d176SSepherosa Ziehau {
2039c80d176SSepherosa Ziehau 	u32 eecd;
2049c80d176SSepherosa Ziehau 	u32 i;
2059c80d176SSepherosa Ziehau 	u16 data;
2069c80d176SSepherosa Ziehau 
2079c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_shift_in_eec_bits");
2089c80d176SSepherosa Ziehau 
2099c80d176SSepherosa Ziehau 	eecd = E1000_READ_REG(hw, E1000_EECD);
2109c80d176SSepherosa Ziehau 
2119c80d176SSepherosa Ziehau 	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
2129c80d176SSepherosa Ziehau 	data = 0;
2139c80d176SSepherosa Ziehau 
2149c80d176SSepherosa Ziehau 	for (i = 0; i < count; i++) {
2159c80d176SSepherosa Ziehau 		data <<= 1;
2169c80d176SSepherosa Ziehau 		e1000_raise_eec_clk(hw, &eecd);
2179c80d176SSepherosa Ziehau 
2189c80d176SSepherosa Ziehau 		eecd = E1000_READ_REG(hw, E1000_EECD);
2199c80d176SSepherosa Ziehau 
2209c80d176SSepherosa Ziehau 		eecd &= ~E1000_EECD_DI;
2219c80d176SSepherosa Ziehau 		if (eecd & E1000_EECD_DO)
2229c80d176SSepherosa Ziehau 			data |= 1;
2239c80d176SSepherosa Ziehau 
2249c80d176SSepherosa Ziehau 		e1000_lower_eec_clk(hw, &eecd);
2259c80d176SSepherosa Ziehau 	}
2269c80d176SSepherosa Ziehau 
2279c80d176SSepherosa Ziehau 	return data;
2289c80d176SSepherosa Ziehau }
2299c80d176SSepherosa Ziehau 
2309c80d176SSepherosa Ziehau /**
2319c80d176SSepherosa Ziehau  *  e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion
2329c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2339c80d176SSepherosa Ziehau  *  @ee_reg: EEPROM flag for polling
2349c80d176SSepherosa Ziehau  *
2359c80d176SSepherosa Ziehau  *  Polls the EEPROM status bit for either read or write completion based
2369c80d176SSepherosa Ziehau  *  upon the value of 'ee_reg'.
2379c80d176SSepherosa Ziehau  **/
e1000_poll_eerd_eewr_done(struct e1000_hw * hw,int ee_reg)2389c80d176SSepherosa Ziehau s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
2399c80d176SSepherosa Ziehau {
2409c80d176SSepherosa Ziehau 	u32 attempts = 100000;
2419c80d176SSepherosa Ziehau 	u32 i, reg = 0;
2429c80d176SSepherosa Ziehau 
2439c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_poll_eerd_eewr_done");
2449c80d176SSepherosa Ziehau 
2459c80d176SSepherosa Ziehau 	for (i = 0; i < attempts; i++) {
2469c80d176SSepherosa Ziehau 		if (ee_reg == E1000_NVM_POLL_READ)
2479c80d176SSepherosa Ziehau 			reg = E1000_READ_REG(hw, E1000_EERD);
2489c80d176SSepherosa Ziehau 		else
2499c80d176SSepherosa Ziehau 			reg = E1000_READ_REG(hw, E1000_EEWR);
2509c80d176SSepherosa Ziehau 
2514be59a01SSepherosa Ziehau 		if (reg & E1000_NVM_RW_REG_DONE)
2524be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
2539c80d176SSepherosa Ziehau 
2549c80d176SSepherosa Ziehau 		usec_delay(5);
2559c80d176SSepherosa Ziehau 	}
2569c80d176SSepherosa Ziehau 
2574be59a01SSepherosa Ziehau 	return -E1000_ERR_NVM;
2589c80d176SSepherosa Ziehau }
2599c80d176SSepherosa Ziehau 
2609c80d176SSepherosa Ziehau /**
2619c80d176SSepherosa Ziehau  *  e1000_acquire_nvm_generic - Generic request for access to EEPROM
2629c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2639c80d176SSepherosa Ziehau  *
2649c80d176SSepherosa Ziehau  *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
2659c80d176SSepherosa Ziehau  *  Return successful if access grant bit set, else clear the request for
2669c80d176SSepherosa Ziehau  *  EEPROM access and return -E1000_ERR_NVM (-1).
2679c80d176SSepherosa Ziehau  **/
e1000_acquire_nvm_generic(struct e1000_hw * hw)2689c80d176SSepherosa Ziehau s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
2699c80d176SSepherosa Ziehau {
2709c80d176SSepherosa Ziehau 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
2719c80d176SSepherosa Ziehau 	s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
2729c80d176SSepherosa Ziehau 
2739c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_acquire_nvm_generic");
2749c80d176SSepherosa Ziehau 
2759c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ);
2769c80d176SSepherosa Ziehau 	eecd = E1000_READ_REG(hw, E1000_EECD);
2779c80d176SSepherosa Ziehau 
2789c80d176SSepherosa Ziehau 	while (timeout) {
2799c80d176SSepherosa Ziehau 		if (eecd & E1000_EECD_GNT)
2809c80d176SSepherosa Ziehau 			break;
2819c80d176SSepherosa Ziehau 		usec_delay(5);
2829c80d176SSepherosa Ziehau 		eecd = E1000_READ_REG(hw, E1000_EECD);
2839c80d176SSepherosa Ziehau 		timeout--;
2849c80d176SSepherosa Ziehau 	}
2859c80d176SSepherosa Ziehau 
2869c80d176SSepherosa Ziehau 	if (!timeout) {
2879c80d176SSepherosa Ziehau 		eecd &= ~E1000_EECD_REQ;
2889c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
2899c80d176SSepherosa Ziehau 		DEBUGOUT("Could not acquire NVM grant\n");
2904be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
2919c80d176SSepherosa Ziehau 	}
2929c80d176SSepherosa Ziehau 
2934be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
2949c80d176SSepherosa Ziehau }
2959c80d176SSepherosa Ziehau 
2969c80d176SSepherosa Ziehau /**
2979c80d176SSepherosa Ziehau  *  e1000_standby_nvm - Return EEPROM to standby state
2989c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2999c80d176SSepherosa Ziehau  *
3009c80d176SSepherosa Ziehau  *  Return the EEPROM to a standby state.
3019c80d176SSepherosa Ziehau  **/
e1000_standby_nvm(struct e1000_hw * hw)3029c80d176SSepherosa Ziehau static void e1000_standby_nvm(struct e1000_hw *hw)
3039c80d176SSepherosa Ziehau {
3049c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
3059c80d176SSepherosa Ziehau 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
3069c80d176SSepherosa Ziehau 
3079c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_standby_nvm");
3089c80d176SSepherosa Ziehau 
3099c80d176SSepherosa Ziehau 	if (nvm->type == e1000_nvm_eeprom_microwire) {
3109c80d176SSepherosa Ziehau 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
3119c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
3129c80d176SSepherosa Ziehau 		E1000_WRITE_FLUSH(hw);
3139c80d176SSepherosa Ziehau 		usec_delay(nvm->delay_usec);
3149c80d176SSepherosa Ziehau 
3159c80d176SSepherosa Ziehau 		e1000_raise_eec_clk(hw, &eecd);
3169c80d176SSepherosa Ziehau 
3179c80d176SSepherosa Ziehau 		/* Select EEPROM */
3189c80d176SSepherosa Ziehau 		eecd |= E1000_EECD_CS;
3199c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
3209c80d176SSepherosa Ziehau 		E1000_WRITE_FLUSH(hw);
3219c80d176SSepherosa Ziehau 		usec_delay(nvm->delay_usec);
3229c80d176SSepherosa Ziehau 
3239c80d176SSepherosa Ziehau 		e1000_lower_eec_clk(hw, &eecd);
3244be59a01SSepherosa Ziehau 	} else if (nvm->type == e1000_nvm_eeprom_spi) {
3259c80d176SSepherosa Ziehau 		/* Toggle CS to flush commands */
3269c80d176SSepherosa Ziehau 		eecd |= E1000_EECD_CS;
3279c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
3289c80d176SSepherosa Ziehau 		E1000_WRITE_FLUSH(hw);
3299c80d176SSepherosa Ziehau 		usec_delay(nvm->delay_usec);
3309c80d176SSepherosa Ziehau 		eecd &= ~E1000_EECD_CS;
3319c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
3329c80d176SSepherosa Ziehau 		E1000_WRITE_FLUSH(hw);
3339c80d176SSepherosa Ziehau 		usec_delay(nvm->delay_usec);
3349c80d176SSepherosa Ziehau 	}
3359c80d176SSepherosa Ziehau }
3369c80d176SSepherosa Ziehau 
3379c80d176SSepherosa Ziehau /**
3389c80d176SSepherosa Ziehau  *  e1000_stop_nvm - Terminate EEPROM command
3399c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
3409c80d176SSepherosa Ziehau  *
3419c80d176SSepherosa Ziehau  *  Terminates the current command by inverting the EEPROM's chip select pin.
3429c80d176SSepherosa Ziehau  **/
e1000_stop_nvm(struct e1000_hw * hw)3439c80d176SSepherosa Ziehau void e1000_stop_nvm(struct e1000_hw *hw)
3449c80d176SSepherosa Ziehau {
3459c80d176SSepherosa Ziehau 	u32 eecd;
3469c80d176SSepherosa Ziehau 
3479c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_stop_nvm");
3489c80d176SSepherosa Ziehau 
3499c80d176SSepherosa Ziehau 	eecd = E1000_READ_REG(hw, E1000_EECD);
3509c80d176SSepherosa Ziehau 	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
3519c80d176SSepherosa Ziehau 		/* Pull CS high */
3529c80d176SSepherosa Ziehau 		eecd |= E1000_EECD_CS;
3539c80d176SSepherosa Ziehau 		e1000_lower_eec_clk(hw, &eecd);
3549c80d176SSepherosa Ziehau 	} else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
3559c80d176SSepherosa Ziehau 		/* CS on Microwire is active-high */
3569c80d176SSepherosa Ziehau 		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
3579c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
3589c80d176SSepherosa Ziehau 		e1000_raise_eec_clk(hw, &eecd);
3599c80d176SSepherosa Ziehau 		e1000_lower_eec_clk(hw, &eecd);
3609c80d176SSepherosa Ziehau 	}
3619c80d176SSepherosa Ziehau }
3629c80d176SSepherosa Ziehau 
3639c80d176SSepherosa Ziehau /**
3649c80d176SSepherosa Ziehau  *  e1000_release_nvm_generic - Release exclusive access to EEPROM
3659c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
3669c80d176SSepherosa Ziehau  *
3679c80d176SSepherosa Ziehau  *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
3689c80d176SSepherosa Ziehau  **/
e1000_release_nvm_generic(struct e1000_hw * hw)3699c80d176SSepherosa Ziehau void e1000_release_nvm_generic(struct e1000_hw *hw)
3709c80d176SSepherosa Ziehau {
3719c80d176SSepherosa Ziehau 	u32 eecd;
3729c80d176SSepherosa Ziehau 
3739c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_release_nvm_generic");
3749c80d176SSepherosa Ziehau 
3759c80d176SSepherosa Ziehau 	e1000_stop_nvm(hw);
3769c80d176SSepherosa Ziehau 
3779c80d176SSepherosa Ziehau 	eecd = E1000_READ_REG(hw, E1000_EECD);
3789c80d176SSepherosa Ziehau 	eecd &= ~E1000_EECD_REQ;
3799c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_EECD, eecd);
3809c80d176SSepherosa Ziehau }
3819c80d176SSepherosa Ziehau 
3829c80d176SSepherosa Ziehau /**
3839c80d176SSepherosa Ziehau  *  e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
3849c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
3859c80d176SSepherosa Ziehau  *
3869c80d176SSepherosa Ziehau  *  Setups the EEPROM for reading and writing.
3879c80d176SSepherosa Ziehau  **/
e1000_ready_nvm_eeprom(struct e1000_hw * hw)3889c80d176SSepherosa Ziehau static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
3899c80d176SSepherosa Ziehau {
3909c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
3919c80d176SSepherosa Ziehau 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
3929c80d176SSepherosa Ziehau 	u8 spi_stat_reg;
3939c80d176SSepherosa Ziehau 
3949c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_ready_nvm_eeprom");
3959c80d176SSepherosa Ziehau 
3969c80d176SSepherosa Ziehau 	if (nvm->type == e1000_nvm_eeprom_microwire) {
3979c80d176SSepherosa Ziehau 		/* Clear SK and DI */
3989c80d176SSepherosa Ziehau 		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
3999c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
4009c80d176SSepherosa Ziehau 		/* Set CS */
4019c80d176SSepherosa Ziehau 		eecd |= E1000_EECD_CS;
4029c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
4034be59a01SSepherosa Ziehau 	} else if (nvm->type == e1000_nvm_eeprom_spi) {
4046d5e2922SSepherosa Ziehau 		u16 timeout = NVM_MAX_RETRY_SPI;
4056d5e2922SSepherosa Ziehau 
4069c80d176SSepherosa Ziehau 		/* Clear SK and CS */
4079c80d176SSepherosa Ziehau 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
4089c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EECD, eecd);
4094be59a01SSepherosa Ziehau 		E1000_WRITE_FLUSH(hw);
4109c80d176SSepherosa Ziehau 		usec_delay(1);
4119c80d176SSepherosa Ziehau 
412379ebbe7SSepherosa Ziehau 		/* Read "Status Register" repeatedly until the LSB is cleared.
4139c80d176SSepherosa Ziehau 		 * The EEPROM will signal that the command has been completed
4149c80d176SSepherosa Ziehau 		 * by clearing bit 0 of the internal status register.  If it's
4159c80d176SSepherosa Ziehau 		 * not cleared within 'timeout', then error out.
4169c80d176SSepherosa Ziehau 		 */
4179c80d176SSepherosa Ziehau 		while (timeout) {
4189c80d176SSepherosa Ziehau 			e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
4199c80d176SSepherosa Ziehau 						 hw->nvm.opcode_bits);
4209c80d176SSepherosa Ziehau 			spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
4219c80d176SSepherosa Ziehau 			if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
4229c80d176SSepherosa Ziehau 				break;
4239c80d176SSepherosa Ziehau 
4249c80d176SSepherosa Ziehau 			usec_delay(5);
4259c80d176SSepherosa Ziehau 			e1000_standby_nvm(hw);
4269c80d176SSepherosa Ziehau 			timeout--;
4279c80d176SSepherosa Ziehau 		}
4289c80d176SSepherosa Ziehau 
4299c80d176SSepherosa Ziehau 		if (!timeout) {
4309c80d176SSepherosa Ziehau 			DEBUGOUT("SPI NVM Status error\n");
4314be59a01SSepherosa Ziehau 			return -E1000_ERR_NVM;
4329c80d176SSepherosa Ziehau 		}
4339c80d176SSepherosa Ziehau 	}
4349c80d176SSepherosa Ziehau 
4354be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
4369c80d176SSepherosa Ziehau }
4379c80d176SSepherosa Ziehau 
4389c80d176SSepherosa Ziehau /**
4399c80d176SSepherosa Ziehau  *  e1000_read_nvm_spi - Read EEPROM's using SPI
4409c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
4419c80d176SSepherosa Ziehau  *  @offset: offset of word in the EEPROM to read
4429c80d176SSepherosa Ziehau  *  @words: number of words to read
4439c80d176SSepherosa Ziehau  *  @data: word read from the EEPROM
4449c80d176SSepherosa Ziehau  *
4459c80d176SSepherosa Ziehau  *  Reads a 16 bit word from the EEPROM.
4469c80d176SSepherosa Ziehau  **/
e1000_read_nvm_spi(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)4479c80d176SSepherosa Ziehau s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
4489c80d176SSepherosa Ziehau {
4499c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
4509c80d176SSepherosa Ziehau 	u32 i = 0;
4519c80d176SSepherosa Ziehau 	s32 ret_val;
4529c80d176SSepherosa Ziehau 	u16 word_in;
4539c80d176SSepherosa Ziehau 	u8 read_opcode = NVM_READ_OPCODE_SPI;
4549c80d176SSepherosa Ziehau 
4559c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_read_nvm_spi");
4569c80d176SSepherosa Ziehau 
457379ebbe7SSepherosa Ziehau 	/* A check for invalid values:  offset too large, too many words,
4589c80d176SSepherosa Ziehau 	 * and not enough words.
4599c80d176SSepherosa Ziehau 	 */
4609c80d176SSepherosa Ziehau 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
4619c80d176SSepherosa Ziehau 	    (words == 0)) {
4629c80d176SSepherosa Ziehau 		DEBUGOUT("nvm parameter(s) out of bounds\n");
4634be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
4649c80d176SSepherosa Ziehau 	}
4659c80d176SSepherosa Ziehau 
4669c80d176SSepherosa Ziehau 	ret_val = nvm->ops.acquire(hw);
4679c80d176SSepherosa Ziehau 	if (ret_val)
4684be59a01SSepherosa Ziehau 		return ret_val;
4699c80d176SSepherosa Ziehau 
4709c80d176SSepherosa Ziehau 	ret_val = e1000_ready_nvm_eeprom(hw);
4719c80d176SSepherosa Ziehau 	if (ret_val)
4729c80d176SSepherosa Ziehau 		goto release;
4739c80d176SSepherosa Ziehau 
4749c80d176SSepherosa Ziehau 	e1000_standby_nvm(hw);
4759c80d176SSepherosa Ziehau 
4769c80d176SSepherosa Ziehau 	if ((nvm->address_bits == 8) && (offset >= 128))
4779c80d176SSepherosa Ziehau 		read_opcode |= NVM_A8_OPCODE_SPI;
4789c80d176SSepherosa Ziehau 
4799c80d176SSepherosa Ziehau 	/* Send the READ command (opcode + addr) */
4809c80d176SSepherosa Ziehau 	e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
4819c80d176SSepherosa Ziehau 	e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
4829c80d176SSepherosa Ziehau 
483379ebbe7SSepherosa Ziehau 	/* Read the data.  SPI NVMs increment the address with each byte
4849c80d176SSepherosa Ziehau 	 * read and will roll over if reading beyond the end.  This allows
4859c80d176SSepherosa Ziehau 	 * us to read the whole NVM from any offset
4869c80d176SSepherosa Ziehau 	 */
4879c80d176SSepherosa Ziehau 	for (i = 0; i < words; i++) {
4889c80d176SSepherosa Ziehau 		word_in = e1000_shift_in_eec_bits(hw, 16);
4899c80d176SSepherosa Ziehau 		data[i] = (word_in >> 8) | (word_in << 8);
4909c80d176SSepherosa Ziehau 	}
4919c80d176SSepherosa Ziehau 
4929c80d176SSepherosa Ziehau release:
4939c80d176SSepherosa Ziehau 	nvm->ops.release(hw);
4949c80d176SSepherosa Ziehau 
4959c80d176SSepherosa Ziehau 	return ret_val;
4969c80d176SSepherosa Ziehau }
4979c80d176SSepherosa Ziehau 
4989c80d176SSepherosa Ziehau /**
4999c80d176SSepherosa Ziehau  *  e1000_read_nvm_microwire - Reads EEPROM's using microwire
5009c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
5019c80d176SSepherosa Ziehau  *  @offset: offset of word in the EEPROM to read
5029c80d176SSepherosa Ziehau  *  @words: number of words to read
5039c80d176SSepherosa Ziehau  *  @data: word read from the EEPROM
5049c80d176SSepherosa Ziehau  *
5059c80d176SSepherosa Ziehau  *  Reads a 16 bit word from the EEPROM.
5069c80d176SSepherosa Ziehau  **/
e1000_read_nvm_microwire(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)5079c80d176SSepherosa Ziehau s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
5089c80d176SSepherosa Ziehau 			     u16 *data)
5099c80d176SSepherosa Ziehau {
5109c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
5119c80d176SSepherosa Ziehau 	u32 i = 0;
5129c80d176SSepherosa Ziehau 	s32 ret_val;
5139c80d176SSepherosa Ziehau 	u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
5149c80d176SSepherosa Ziehau 
5159c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_read_nvm_microwire");
5169c80d176SSepherosa Ziehau 
517379ebbe7SSepherosa Ziehau 	/* A check for invalid values:  offset too large, too many words,
5189c80d176SSepherosa Ziehau 	 * and not enough words.
5199c80d176SSepherosa Ziehau 	 */
5209c80d176SSepherosa Ziehau 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
5219c80d176SSepherosa Ziehau 	    (words == 0)) {
5229c80d176SSepherosa Ziehau 		DEBUGOUT("nvm parameter(s) out of bounds\n");
5234be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
5249c80d176SSepherosa Ziehau 	}
5259c80d176SSepherosa Ziehau 
5269c80d176SSepherosa Ziehau 	ret_val = nvm->ops.acquire(hw);
5279c80d176SSepherosa Ziehau 	if (ret_val)
5284be59a01SSepherosa Ziehau 		return ret_val;
5299c80d176SSepherosa Ziehau 
5309c80d176SSepherosa Ziehau 	ret_val = e1000_ready_nvm_eeprom(hw);
5319c80d176SSepherosa Ziehau 	if (ret_val)
5329c80d176SSepherosa Ziehau 		goto release;
5339c80d176SSepherosa Ziehau 
5349c80d176SSepherosa Ziehau 	for (i = 0; i < words; i++) {
5359c80d176SSepherosa Ziehau 		/* Send the READ command (opcode + addr) */
5369c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
5379c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, (u16)(offset + i),
5389c80d176SSepherosa Ziehau 					nvm->address_bits);
5399c80d176SSepherosa Ziehau 
540379ebbe7SSepherosa Ziehau 		/* Read the data.  For microwire, each word requires the
5419c80d176SSepherosa Ziehau 		 * overhead of setup and tear-down.
5429c80d176SSepherosa Ziehau 		 */
5439c80d176SSepherosa Ziehau 		data[i] = e1000_shift_in_eec_bits(hw, 16);
5449c80d176SSepherosa Ziehau 		e1000_standby_nvm(hw);
5459c80d176SSepherosa Ziehau 	}
5469c80d176SSepherosa Ziehau 
5479c80d176SSepherosa Ziehau release:
5489c80d176SSepherosa Ziehau 	nvm->ops.release(hw);
5499c80d176SSepherosa Ziehau 
5509c80d176SSepherosa Ziehau 	return ret_val;
5519c80d176SSepherosa Ziehau }
5529c80d176SSepherosa Ziehau 
5539c80d176SSepherosa Ziehau /**
5549c80d176SSepherosa Ziehau  *  e1000_read_nvm_eerd - Reads EEPROM using EERD register
5559c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
5569c80d176SSepherosa Ziehau  *  @offset: offset of word in the EEPROM to read
5579c80d176SSepherosa Ziehau  *  @words: number of words to read
5589c80d176SSepherosa Ziehau  *  @data: word read from the EEPROM
5599c80d176SSepherosa Ziehau  *
5609c80d176SSepherosa Ziehau  *  Reads a 16 bit word from the EEPROM using the EERD register.
5619c80d176SSepherosa Ziehau  **/
e1000_read_nvm_eerd(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)5629c80d176SSepherosa Ziehau s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
5639c80d176SSepherosa Ziehau {
5649c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
5659c80d176SSepherosa Ziehau 	u32 i, eerd = 0;
5669c80d176SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
5679c80d176SSepherosa Ziehau 
5689c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_read_nvm_eerd");
5699c80d176SSepherosa Ziehau 
570379ebbe7SSepherosa Ziehau 	/* A check for invalid values:  offset too large, too many words,
5719c80d176SSepherosa Ziehau 	 * too many words for the offset, and not enough words.
5729c80d176SSepherosa Ziehau 	 */
5739c80d176SSepherosa Ziehau 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
5749c80d176SSepherosa Ziehau 	    (words == 0)) {
5759c80d176SSepherosa Ziehau 		DEBUGOUT("nvm parameter(s) out of bounds\n");
5764be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
5779c80d176SSepherosa Ziehau 	}
5789c80d176SSepherosa Ziehau 
5799c80d176SSepherosa Ziehau 	for (i = 0; i < words; i++) {
5809c80d176SSepherosa Ziehau 		eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) +
5819c80d176SSepherosa Ziehau 		       E1000_NVM_RW_REG_START;
5829c80d176SSepherosa Ziehau 
5839c80d176SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EERD, eerd);
5849c80d176SSepherosa Ziehau 		ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
5859c80d176SSepherosa Ziehau 		if (ret_val)
5869c80d176SSepherosa Ziehau 			break;
5879c80d176SSepherosa Ziehau 
5889c80d176SSepherosa Ziehau 		data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
5899c80d176SSepherosa Ziehau 			   E1000_NVM_RW_REG_DATA);
5909c80d176SSepherosa Ziehau 	}
5919c80d176SSepherosa Ziehau 
5924765c386SMichael Neumann 	if (ret_val)
5934765c386SMichael Neumann 		DEBUGOUT1("NVM read error: %d\n", ret_val);
5944765c386SMichael Neumann 
5959c80d176SSepherosa Ziehau 	return ret_val;
5969c80d176SSepherosa Ziehau }
5979c80d176SSepherosa Ziehau 
5989c80d176SSepherosa Ziehau /**
5999c80d176SSepherosa Ziehau  *  e1000_write_nvm_spi - Write to EEPROM using SPI
6009c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
6019c80d176SSepherosa Ziehau  *  @offset: offset within the EEPROM to be written to
6029c80d176SSepherosa Ziehau  *  @words: number of words to write
6039c80d176SSepherosa Ziehau  *  @data: 16 bit word(s) to be written to the EEPROM
6049c80d176SSepherosa Ziehau  *
6059c80d176SSepherosa Ziehau  *  Writes data to EEPROM at offset using SPI interface.
6069c80d176SSepherosa Ziehau  *
6079c80d176SSepherosa Ziehau  *  If e1000_update_nvm_checksum is not called after this function , the
6089c80d176SSepherosa Ziehau  *  EEPROM will most likely contain an invalid checksum.
6099c80d176SSepherosa Ziehau  **/
e1000_write_nvm_spi(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)6109c80d176SSepherosa Ziehau s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
6119c80d176SSepherosa Ziehau {
6129c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
613379ebbe7SSepherosa Ziehau 	s32 ret_val = -E1000_ERR_NVM;
6149c80d176SSepherosa Ziehau 	u16 widx = 0;
6159c80d176SSepherosa Ziehau 
6169c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_write_nvm_spi");
6179c80d176SSepherosa Ziehau 
618379ebbe7SSepherosa Ziehau 	/* A check for invalid values:  offset too large, too many words,
6199c80d176SSepherosa Ziehau 	 * and not enough words.
6209c80d176SSepherosa Ziehau 	 */
6219c80d176SSepherosa Ziehau 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
6229c80d176SSepherosa Ziehau 	    (words == 0)) {
6239c80d176SSepherosa Ziehau 		DEBUGOUT("nvm parameter(s) out of bounds\n");
6244be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
6259c80d176SSepherosa Ziehau 	}
6269c80d176SSepherosa Ziehau 
627379ebbe7SSepherosa Ziehau 	while (widx < words) {
628379ebbe7SSepherosa Ziehau 		u8 write_opcode = NVM_WRITE_OPCODE_SPI;
629379ebbe7SSepherosa Ziehau 
6309c80d176SSepherosa Ziehau 		ret_val = nvm->ops.acquire(hw);
6319c80d176SSepherosa Ziehau 		if (ret_val)
6324be59a01SSepherosa Ziehau 			return ret_val;
6339c80d176SSepherosa Ziehau 
6349c80d176SSepherosa Ziehau 		ret_val = e1000_ready_nvm_eeprom(hw);
635379ebbe7SSepherosa Ziehau 		if (ret_val) {
636379ebbe7SSepherosa Ziehau 			nvm->ops.release(hw);
637379ebbe7SSepherosa Ziehau 			return ret_val;
638379ebbe7SSepherosa Ziehau 		}
6399c80d176SSepherosa Ziehau 
6409c80d176SSepherosa Ziehau 		e1000_standby_nvm(hw);
6419c80d176SSepherosa Ziehau 
6429c80d176SSepherosa Ziehau 		/* Send the WRITE ENABLE command (8 bit opcode) */
6439c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
6449c80d176SSepherosa Ziehau 					 nvm->opcode_bits);
6459c80d176SSepherosa Ziehau 
6469c80d176SSepherosa Ziehau 		e1000_standby_nvm(hw);
6479c80d176SSepherosa Ziehau 
648379ebbe7SSepherosa Ziehau 		/* Some SPI eeproms use the 8th address bit embedded in the
6499c80d176SSepherosa Ziehau 		 * opcode
6509c80d176SSepherosa Ziehau 		 */
6519c80d176SSepherosa Ziehau 		if ((nvm->address_bits == 8) && (offset >= 128))
6529c80d176SSepherosa Ziehau 			write_opcode |= NVM_A8_OPCODE_SPI;
6539c80d176SSepherosa Ziehau 
6549c80d176SSepherosa Ziehau 		/* Send the Write command (8-bit opcode + addr) */
6559c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
6569c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
6579c80d176SSepherosa Ziehau 					 nvm->address_bits);
6589c80d176SSepherosa Ziehau 
6599c80d176SSepherosa Ziehau 		/* Loop to allow for up to whole page write of eeprom */
6609c80d176SSepherosa Ziehau 		while (widx < words) {
6619c80d176SSepherosa Ziehau 			u16 word_out = data[widx];
6629c80d176SSepherosa Ziehau 			word_out = (word_out >> 8) | (word_out << 8);
6639c80d176SSepherosa Ziehau 			e1000_shift_out_eec_bits(hw, word_out, 16);
6649c80d176SSepherosa Ziehau 			widx++;
6659c80d176SSepherosa Ziehau 
6669c80d176SSepherosa Ziehau 			if ((((offset + widx) * 2) % nvm->page_size) == 0) {
6679c80d176SSepherosa Ziehau 				e1000_standby_nvm(hw);
6689c80d176SSepherosa Ziehau 				break;
6699c80d176SSepherosa Ziehau 			}
6709c80d176SSepherosa Ziehau 		}
6719c80d176SSepherosa Ziehau 		msec_delay(10);
6729c80d176SSepherosa Ziehau 		nvm->ops.release(hw);
673379ebbe7SSepherosa Ziehau 	}
6749c80d176SSepherosa Ziehau 
6759c80d176SSepherosa Ziehau 	return ret_val;
6769c80d176SSepherosa Ziehau }
6779c80d176SSepherosa Ziehau 
6789c80d176SSepherosa Ziehau /**
6799c80d176SSepherosa Ziehau  *  e1000_write_nvm_microwire - Writes EEPROM using microwire
6809c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
6819c80d176SSepherosa Ziehau  *  @offset: offset within the EEPROM to be written to
6829c80d176SSepherosa Ziehau  *  @words: number of words to write
6839c80d176SSepherosa Ziehau  *  @data: 16 bit word(s) to be written to the EEPROM
6849c80d176SSepherosa Ziehau  *
6859c80d176SSepherosa Ziehau  *  Writes data to EEPROM at offset using microwire interface.
6869c80d176SSepherosa Ziehau  *
6879c80d176SSepherosa Ziehau  *  If e1000_update_nvm_checksum is not called after this function , the
6889c80d176SSepherosa Ziehau  *  EEPROM will most likely contain an invalid checksum.
6899c80d176SSepherosa Ziehau  **/
e1000_write_nvm_microwire(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)6909c80d176SSepherosa Ziehau s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
6919c80d176SSepherosa Ziehau 			      u16 *data)
6929c80d176SSepherosa Ziehau {
6939c80d176SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
6949c80d176SSepherosa Ziehau 	s32  ret_val;
6959c80d176SSepherosa Ziehau 	u32 eecd;
6969c80d176SSepherosa Ziehau 	u16 words_written = 0;
6979c80d176SSepherosa Ziehau 	u16 widx = 0;
6989c80d176SSepherosa Ziehau 
6999c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_write_nvm_microwire");
7009c80d176SSepherosa Ziehau 
701379ebbe7SSepherosa Ziehau 	/* A check for invalid values:  offset too large, too many words,
7029c80d176SSepherosa Ziehau 	 * and not enough words.
7039c80d176SSepherosa Ziehau 	 */
7049c80d176SSepherosa Ziehau 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
7059c80d176SSepherosa Ziehau 	    (words == 0)) {
7069c80d176SSepherosa Ziehau 		DEBUGOUT("nvm parameter(s) out of bounds\n");
7074be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
7089c80d176SSepherosa Ziehau 	}
7099c80d176SSepherosa Ziehau 
7109c80d176SSepherosa Ziehau 	ret_val = nvm->ops.acquire(hw);
7119c80d176SSepherosa Ziehau 	if (ret_val)
7124be59a01SSepherosa Ziehau 		return ret_val;
7139c80d176SSepherosa Ziehau 
7149c80d176SSepherosa Ziehau 	ret_val = e1000_ready_nvm_eeprom(hw);
7159c80d176SSepherosa Ziehau 	if (ret_val)
7169c80d176SSepherosa Ziehau 		goto release;
7179c80d176SSepherosa Ziehau 
7189c80d176SSepherosa Ziehau 	e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
7199c80d176SSepherosa Ziehau 				 (u16)(nvm->opcode_bits + 2));
7209c80d176SSepherosa Ziehau 
7219c80d176SSepherosa Ziehau 	e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
7229c80d176SSepherosa Ziehau 
7239c80d176SSepherosa Ziehau 	e1000_standby_nvm(hw);
7249c80d176SSepherosa Ziehau 
7259c80d176SSepherosa Ziehau 	while (words_written < words) {
7269c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
7279c80d176SSepherosa Ziehau 					 nvm->opcode_bits);
7289c80d176SSepherosa Ziehau 
7299c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, (u16)(offset + words_written),
7309c80d176SSepherosa Ziehau 					 nvm->address_bits);
7319c80d176SSepherosa Ziehau 
7329c80d176SSepherosa Ziehau 		e1000_shift_out_eec_bits(hw, data[words_written], 16);
7339c80d176SSepherosa Ziehau 
7349c80d176SSepherosa Ziehau 		e1000_standby_nvm(hw);
7359c80d176SSepherosa Ziehau 
7369c80d176SSepherosa Ziehau 		for (widx = 0; widx < 200; widx++) {
7379c80d176SSepherosa Ziehau 			eecd = E1000_READ_REG(hw, E1000_EECD);
7389c80d176SSepherosa Ziehau 			if (eecd & E1000_EECD_DO)
7399c80d176SSepherosa Ziehau 				break;
7409c80d176SSepherosa Ziehau 			usec_delay(50);
7419c80d176SSepherosa Ziehau 		}
7429c80d176SSepherosa Ziehau 
7439c80d176SSepherosa Ziehau 		if (widx == 200) {
7449c80d176SSepherosa Ziehau 			DEBUGOUT("NVM Write did not complete\n");
7459c80d176SSepherosa Ziehau 			ret_val = -E1000_ERR_NVM;
7469c80d176SSepherosa Ziehau 			goto release;
7479c80d176SSepherosa Ziehau 		}
7489c80d176SSepherosa Ziehau 
7499c80d176SSepherosa Ziehau 		e1000_standby_nvm(hw);
7509c80d176SSepherosa Ziehau 
7519c80d176SSepherosa Ziehau 		words_written++;
7529c80d176SSepherosa Ziehau 	}
7539c80d176SSepherosa Ziehau 
7549c80d176SSepherosa Ziehau 	e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
7559c80d176SSepherosa Ziehau 				 (u16)(nvm->opcode_bits + 2));
7569c80d176SSepherosa Ziehau 
7579c80d176SSepherosa Ziehau 	e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
7589c80d176SSepherosa Ziehau 
7599c80d176SSepherosa Ziehau release:
7609c80d176SSepherosa Ziehau 	nvm->ops.release(hw);
7619c80d176SSepherosa Ziehau 
7629c80d176SSepherosa Ziehau 	return ret_val;
7639c80d176SSepherosa Ziehau }
7649c80d176SSepherosa Ziehau 
7659c80d176SSepherosa Ziehau /**
7666a5a645eSSepherosa Ziehau  *  e1000_read_pba_string_generic - Read device part number
7676a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
7686a5a645eSSepherosa Ziehau  *  @pba_num: pointer to device part number
7696a5a645eSSepherosa Ziehau  *  @pba_num_size: size of part number buffer
7706a5a645eSSepherosa Ziehau  *
7716a5a645eSSepherosa Ziehau  *  Reads the product board assembly (PBA) number from the EEPROM and stores
7726a5a645eSSepherosa Ziehau  *  the value in pba_num.
7736a5a645eSSepherosa Ziehau  **/
e1000_read_pba_string_generic(struct e1000_hw * hw,u8 * pba_num,u32 pba_num_size)7746a5a645eSSepherosa Ziehau s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
7756a5a645eSSepherosa Ziehau 				  u32 pba_num_size)
7766a5a645eSSepherosa Ziehau {
7776a5a645eSSepherosa Ziehau 	s32 ret_val;
7786a5a645eSSepherosa Ziehau 	u16 nvm_data;
7796a5a645eSSepherosa Ziehau 	u16 pba_ptr;
7806a5a645eSSepherosa Ziehau 	u16 offset;
7816a5a645eSSepherosa Ziehau 	u16 length;
7826a5a645eSSepherosa Ziehau 
7836a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_read_pba_string_generic");
7846a5a645eSSepherosa Ziehau 
785ba0123e0SSepherosa Ziehau 	if ((hw->mac.type >= e1000_i210) &&
786ba0123e0SSepherosa Ziehau 	    !e1000_get_flash_presence_i210(hw)) {
787ba0123e0SSepherosa Ziehau 		DEBUGOUT("Flashless no PBA string\n");
788ba0123e0SSepherosa Ziehau 		return -E1000_ERR_NVM_PBA_SECTION;
789ba0123e0SSepherosa Ziehau 	}
790ba0123e0SSepherosa Ziehau 
7916a5a645eSSepherosa Ziehau 	if (pba_num == NULL) {
7926a5a645eSSepherosa Ziehau 		DEBUGOUT("PBA string buffer was null\n");
7934be59a01SSepherosa Ziehau 		return -E1000_ERR_INVALID_ARGUMENT;
7946a5a645eSSepherosa Ziehau 	}
7956a5a645eSSepherosa Ziehau 
7966a5a645eSSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
7976a5a645eSSepherosa Ziehau 	if (ret_val) {
7986a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
7994be59a01SSepherosa Ziehau 		return ret_val;
8006a5a645eSSepherosa Ziehau 	}
8016a5a645eSSepherosa Ziehau 
8026a5a645eSSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
8036a5a645eSSepherosa Ziehau 	if (ret_val) {
8046a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
8054be59a01SSepherosa Ziehau 		return ret_val;
8066a5a645eSSepherosa Ziehau 	}
8076a5a645eSSepherosa Ziehau 
808379ebbe7SSepherosa Ziehau 	/* if nvm_data is not ptr guard the PBA must be in legacy format which
8096a5a645eSSepherosa Ziehau 	 * means pba_ptr is actually our second data word for the PBA number
8106a5a645eSSepherosa Ziehau 	 * and we can decode it into an ascii string
8116a5a645eSSepherosa Ziehau 	 */
8126a5a645eSSepherosa Ziehau 	if (nvm_data != NVM_PBA_PTR_GUARD) {
8136a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM PBA number is not stored as string\n");
8146a5a645eSSepherosa Ziehau 
8154be59a01SSepherosa Ziehau 		/* make sure callers buffer is big enough to store the PBA */
8164be59a01SSepherosa Ziehau 		if (pba_num_size < E1000_PBANUM_LENGTH) {
8176a5a645eSSepherosa Ziehau 			DEBUGOUT("PBA string buffer too small\n");
8186a5a645eSSepherosa Ziehau 			return E1000_ERR_NO_SPACE;
8196a5a645eSSepherosa Ziehau 		}
8206a5a645eSSepherosa Ziehau 
8216a5a645eSSepherosa Ziehau 		/* extract hex string from data and pba_ptr */
8226a5a645eSSepherosa Ziehau 		pba_num[0] = (nvm_data >> 12) & 0xF;
8236a5a645eSSepherosa Ziehau 		pba_num[1] = (nvm_data >> 8) & 0xF;
8246a5a645eSSepherosa Ziehau 		pba_num[2] = (nvm_data >> 4) & 0xF;
8256a5a645eSSepherosa Ziehau 		pba_num[3] = nvm_data & 0xF;
8266a5a645eSSepherosa Ziehau 		pba_num[4] = (pba_ptr >> 12) & 0xF;
8276a5a645eSSepherosa Ziehau 		pba_num[5] = (pba_ptr >> 8) & 0xF;
8286a5a645eSSepherosa Ziehau 		pba_num[6] = '-';
8296a5a645eSSepherosa Ziehau 		pba_num[7] = 0;
8306a5a645eSSepherosa Ziehau 		pba_num[8] = (pba_ptr >> 4) & 0xF;
8316a5a645eSSepherosa Ziehau 		pba_num[9] = pba_ptr & 0xF;
8326a5a645eSSepherosa Ziehau 
8336a5a645eSSepherosa Ziehau 		/* put a null character on the end of our string */
8346a5a645eSSepherosa Ziehau 		pba_num[10] = '\0';
8356a5a645eSSepherosa Ziehau 
8366a5a645eSSepherosa Ziehau 		/* switch all the data but the '-' to hex char */
8376a5a645eSSepherosa Ziehau 		for (offset = 0; offset < 10; offset++) {
8386a5a645eSSepherosa Ziehau 			if (pba_num[offset] < 0xA)
8396a5a645eSSepherosa Ziehau 				pba_num[offset] += '0';
8406a5a645eSSepherosa Ziehau 			else if (pba_num[offset] < 0x10)
8416a5a645eSSepherosa Ziehau 				pba_num[offset] += 'A' - 0xA;
8426a5a645eSSepherosa Ziehau 		}
8436a5a645eSSepherosa Ziehau 
8444be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
8456a5a645eSSepherosa Ziehau 	}
8466a5a645eSSepherosa Ziehau 
8476a5a645eSSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
8486a5a645eSSepherosa Ziehau 	if (ret_val) {
8496a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
8504be59a01SSepherosa Ziehau 		return ret_val;
8516a5a645eSSepherosa Ziehau 	}
8526a5a645eSSepherosa Ziehau 
8536a5a645eSSepherosa Ziehau 	if (length == 0xFFFF || length == 0) {
8546a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM PBA number section invalid length\n");
8554be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM_PBA_SECTION;
8566a5a645eSSepherosa Ziehau 	}
8576a5a645eSSepherosa Ziehau 	/* check if pba_num buffer is big enough */
8586a5a645eSSepherosa Ziehau 	if (pba_num_size < (((u32)length * 2) - 1)) {
8596a5a645eSSepherosa Ziehau 		DEBUGOUT("PBA string buffer too small\n");
8604be59a01SSepherosa Ziehau 		return -E1000_ERR_NO_SPACE;
8616a5a645eSSepherosa Ziehau 	}
8626a5a645eSSepherosa Ziehau 
8636a5a645eSSepherosa Ziehau 	/* trim pba length from start of string */
8646a5a645eSSepherosa Ziehau 	pba_ptr++;
8656a5a645eSSepherosa Ziehau 	length--;
8666a5a645eSSepherosa Ziehau 
8676a5a645eSSepherosa Ziehau 	for (offset = 0; offset < length; offset++) {
8686a5a645eSSepherosa Ziehau 		ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
8696a5a645eSSepherosa Ziehau 		if (ret_val) {
8706a5a645eSSepherosa Ziehau 			DEBUGOUT("NVM Read Error\n");
8714be59a01SSepherosa Ziehau 			return ret_val;
8726a5a645eSSepherosa Ziehau 		}
8736a5a645eSSepherosa Ziehau 		pba_num[offset * 2] = (u8)(nvm_data >> 8);
8746a5a645eSSepherosa Ziehau 		pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
8756a5a645eSSepherosa Ziehau 	}
8766a5a645eSSepherosa Ziehau 	pba_num[offset * 2] = '\0';
8776a5a645eSSepherosa Ziehau 
8784be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
8796a5a645eSSepherosa Ziehau }
8806a5a645eSSepherosa Ziehau 
8816a5a645eSSepherosa Ziehau /**
8826a5a645eSSepherosa Ziehau  *  e1000_read_pba_length_generic - Read device part number length
8836a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
8846a5a645eSSepherosa Ziehau  *  @pba_num_size: size of part number buffer
8856a5a645eSSepherosa Ziehau  *
8866a5a645eSSepherosa Ziehau  *  Reads the product board assembly (PBA) number length from the EEPROM and
8876a5a645eSSepherosa Ziehau  *  stores the value in pba_num_size.
8886a5a645eSSepherosa Ziehau  **/
e1000_read_pba_length_generic(struct e1000_hw * hw,u32 * pba_num_size)8896a5a645eSSepherosa Ziehau s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
8906a5a645eSSepherosa Ziehau {
8916a5a645eSSepherosa Ziehau 	s32 ret_val;
8926a5a645eSSepherosa Ziehau 	u16 nvm_data;
8936a5a645eSSepherosa Ziehau 	u16 pba_ptr;
8946a5a645eSSepherosa Ziehau 	u16 length;
8956a5a645eSSepherosa Ziehau 
8966a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_read_pba_length_generic");
8976a5a645eSSepherosa Ziehau 
8986a5a645eSSepherosa Ziehau 	if (pba_num_size == NULL) {
8996a5a645eSSepherosa Ziehau 		DEBUGOUT("PBA buffer size was null\n");
9004be59a01SSepherosa Ziehau 		return -E1000_ERR_INVALID_ARGUMENT;
9016a5a645eSSepherosa Ziehau 	}
9026a5a645eSSepherosa Ziehau 
9036a5a645eSSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
9046a5a645eSSepherosa Ziehau 	if (ret_val) {
9056a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
9064be59a01SSepherosa Ziehau 		return ret_val;
9076a5a645eSSepherosa Ziehau 	}
9086a5a645eSSepherosa Ziehau 
9096a5a645eSSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
9106a5a645eSSepherosa Ziehau 	if (ret_val) {
9116a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
9124be59a01SSepherosa Ziehau 		return ret_val;
9136a5a645eSSepherosa Ziehau 	}
9146a5a645eSSepherosa Ziehau 
9156a5a645eSSepherosa Ziehau 	 /* if data is not ptr guard the PBA must be in legacy format */
9166a5a645eSSepherosa Ziehau 	if (nvm_data != NVM_PBA_PTR_GUARD) {
9174be59a01SSepherosa Ziehau 		*pba_num_size = E1000_PBANUM_LENGTH;
9184be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
9196a5a645eSSepherosa Ziehau 	}
9206a5a645eSSepherosa Ziehau 
9216a5a645eSSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
9226a5a645eSSepherosa Ziehau 	if (ret_val) {
9236a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
9244be59a01SSepherosa Ziehau 		return ret_val;
9256a5a645eSSepherosa Ziehau 	}
9266a5a645eSSepherosa Ziehau 
9276a5a645eSSepherosa Ziehau 	if (length == 0xFFFF || length == 0) {
9286a5a645eSSepherosa Ziehau 		DEBUGOUT("NVM PBA number section invalid length\n");
9294be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM_PBA_SECTION;
9306a5a645eSSepherosa Ziehau 	}
9316a5a645eSSepherosa Ziehau 
932379ebbe7SSepherosa Ziehau 	/* Convert from length in u16 values to u8 chars, add 1 for NULL,
9336a5a645eSSepherosa Ziehau 	 * and subtract 2 because length field is included in length.
9346a5a645eSSepherosa Ziehau 	 */
9356a5a645eSSepherosa Ziehau 	*pba_num_size = ((u32)length * 2) - 1;
9366a5a645eSSepherosa Ziehau 
9374be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
9386a5a645eSSepherosa Ziehau }
9396a5a645eSSepherosa Ziehau 
9404be59a01SSepherosa Ziehau 
9414be59a01SSepherosa Ziehau /**
9424be59a01SSepherosa Ziehau  *  e1000_read_pba_raw
9434be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
9444be59a01SSepherosa Ziehau  *  @eeprom_buf: optional pointer to EEPROM image
9454be59a01SSepherosa Ziehau  *  @eeprom_buf_size: size of EEPROM image in words
9464be59a01SSepherosa Ziehau  *  @max_pba_block_size: PBA block size limit
9474be59a01SSepherosa Ziehau  *  @pba: pointer to output PBA structure
9484be59a01SSepherosa Ziehau  *
9494be59a01SSepherosa Ziehau  *  Reads PBA from EEPROM image when eeprom_buf is not NULL.
9504be59a01SSepherosa Ziehau  *  Reads PBA from physical EEPROM device when eeprom_buf is NULL.
9514be59a01SSepherosa Ziehau  *
9524be59a01SSepherosa Ziehau  **/
e1000_read_pba_raw(struct e1000_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,u16 max_pba_block_size,struct e1000_pba * pba)9534be59a01SSepherosa Ziehau s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
9544be59a01SSepherosa Ziehau 		       u32 eeprom_buf_size, u16 max_pba_block_size,
9554be59a01SSepherosa Ziehau 		       struct e1000_pba *pba)
9564be59a01SSepherosa Ziehau {
9574be59a01SSepherosa Ziehau 	s32 ret_val;
9584be59a01SSepherosa Ziehau 	u16 pba_block_size;
9594be59a01SSepherosa Ziehau 
9604be59a01SSepherosa Ziehau 	if (pba == NULL)
9614be59a01SSepherosa Ziehau 		return -E1000_ERR_PARAM;
9624be59a01SSepherosa Ziehau 
9634be59a01SSepherosa Ziehau 	if (eeprom_buf == NULL) {
9644be59a01SSepherosa Ziehau 		ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
9654be59a01SSepherosa Ziehau 					 &pba->word[0]);
9664be59a01SSepherosa Ziehau 		if (ret_val)
9679c80d176SSepherosa Ziehau 			return ret_val;
9684be59a01SSepherosa Ziehau 	} else {
9694be59a01SSepherosa Ziehau 		if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
9704be59a01SSepherosa Ziehau 			pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
9714be59a01SSepherosa Ziehau 			pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
9724be59a01SSepherosa Ziehau 		} else {
9734be59a01SSepherosa Ziehau 			return -E1000_ERR_PARAM;
9744be59a01SSepherosa Ziehau 		}
9754be59a01SSepherosa Ziehau 	}
9764be59a01SSepherosa Ziehau 
9774be59a01SSepherosa Ziehau 	if (pba->word[0] == NVM_PBA_PTR_GUARD) {
9784be59a01SSepherosa Ziehau 		if (pba->pba_block == NULL)
9794be59a01SSepherosa Ziehau 			return -E1000_ERR_PARAM;
9804be59a01SSepherosa Ziehau 
9814be59a01SSepherosa Ziehau 		ret_val = e1000_get_pba_block_size(hw, eeprom_buf,
9824be59a01SSepherosa Ziehau 						   eeprom_buf_size,
9834be59a01SSepherosa Ziehau 						   &pba_block_size);
9844be59a01SSepherosa Ziehau 		if (ret_val)
9854be59a01SSepherosa Ziehau 			return ret_val;
9864be59a01SSepherosa Ziehau 
9874be59a01SSepherosa Ziehau 		if (pba_block_size > max_pba_block_size)
9884be59a01SSepherosa Ziehau 			return -E1000_ERR_PARAM;
9894be59a01SSepherosa Ziehau 
9904be59a01SSepherosa Ziehau 		if (eeprom_buf == NULL) {
9914be59a01SSepherosa Ziehau 			ret_val = e1000_read_nvm(hw, pba->word[1],
9924be59a01SSepherosa Ziehau 						 pba_block_size,
9934be59a01SSepherosa Ziehau 						 pba->pba_block);
9944be59a01SSepherosa Ziehau 			if (ret_val)
9954be59a01SSepherosa Ziehau 				return ret_val;
9964be59a01SSepherosa Ziehau 		} else {
9974be59a01SSepherosa Ziehau 			if (eeprom_buf_size > (u32)(pba->word[1] +
9984765c386SMichael Neumann 					      pba_block_size)) {
9994be59a01SSepherosa Ziehau 				memcpy(pba->pba_block,
10004be59a01SSepherosa Ziehau 				       &eeprom_buf[pba->word[1]],
10014be59a01SSepherosa Ziehau 				       pba_block_size * sizeof(u16));
10024be59a01SSepherosa Ziehau 			} else {
10034be59a01SSepherosa Ziehau 				return -E1000_ERR_PARAM;
10044be59a01SSepherosa Ziehau 			}
10054be59a01SSepherosa Ziehau 		}
10064be59a01SSepherosa Ziehau 	}
10074be59a01SSepherosa Ziehau 
10084be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
10094be59a01SSepherosa Ziehau }
10104be59a01SSepherosa Ziehau 
10114be59a01SSepherosa Ziehau /**
10124be59a01SSepherosa Ziehau  *  e1000_write_pba_raw
10134be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
10144be59a01SSepherosa Ziehau  *  @eeprom_buf: optional pointer to EEPROM image
10154be59a01SSepherosa Ziehau  *  @eeprom_buf_size: size of EEPROM image in words
10164be59a01SSepherosa Ziehau  *  @pba: pointer to PBA structure
10174be59a01SSepherosa Ziehau  *
10184be59a01SSepherosa Ziehau  *  Writes PBA to EEPROM image when eeprom_buf is not NULL.
10194be59a01SSepherosa Ziehau  *  Writes PBA to physical EEPROM device when eeprom_buf is NULL.
10204be59a01SSepherosa Ziehau  *
10214be59a01SSepherosa Ziehau  **/
e1000_write_pba_raw(struct e1000_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,struct e1000_pba * pba)10224be59a01SSepherosa Ziehau s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
10234be59a01SSepherosa Ziehau 			u32 eeprom_buf_size, struct e1000_pba *pba)
10244be59a01SSepherosa Ziehau {
10254be59a01SSepherosa Ziehau 	s32 ret_val;
10264be59a01SSepherosa Ziehau 
10274be59a01SSepherosa Ziehau 	if (pba == NULL)
10284be59a01SSepherosa Ziehau 		return -E1000_ERR_PARAM;
10294be59a01SSepherosa Ziehau 
10304be59a01SSepherosa Ziehau 	if (eeprom_buf == NULL) {
10314be59a01SSepherosa Ziehau 		ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
10324be59a01SSepherosa Ziehau 					  &pba->word[0]);
10334be59a01SSepherosa Ziehau 		if (ret_val)
10344be59a01SSepherosa Ziehau 			return ret_val;
10354be59a01SSepherosa Ziehau 	} else {
10364be59a01SSepherosa Ziehau 		if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
10374be59a01SSepherosa Ziehau 			eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
10384be59a01SSepherosa Ziehau 			eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
10394be59a01SSepherosa Ziehau 		} else {
10404be59a01SSepherosa Ziehau 			return -E1000_ERR_PARAM;
10414be59a01SSepherosa Ziehau 		}
10424be59a01SSepherosa Ziehau 	}
10434be59a01SSepherosa Ziehau 
10444be59a01SSepherosa Ziehau 	if (pba->word[0] == NVM_PBA_PTR_GUARD) {
10454be59a01SSepherosa Ziehau 		if (pba->pba_block == NULL)
10464be59a01SSepherosa Ziehau 			return -E1000_ERR_PARAM;
10474be59a01SSepherosa Ziehau 
10484be59a01SSepherosa Ziehau 		if (eeprom_buf == NULL) {
10494be59a01SSepherosa Ziehau 			ret_val = e1000_write_nvm(hw, pba->word[1],
10504be59a01SSepherosa Ziehau 						  pba->pba_block[0],
10514be59a01SSepherosa Ziehau 						  pba->pba_block);
10524be59a01SSepherosa Ziehau 			if (ret_val)
10534be59a01SSepherosa Ziehau 				return ret_val;
10544be59a01SSepherosa Ziehau 		} else {
10554be59a01SSepherosa Ziehau 			if (eeprom_buf_size > (u32)(pba->word[1] +
10564be59a01SSepherosa Ziehau 					      pba->pba_block[0])) {
10574be59a01SSepherosa Ziehau 				memcpy(&eeprom_buf[pba->word[1]],
10584be59a01SSepherosa Ziehau 				       pba->pba_block,
10594be59a01SSepherosa Ziehau 				       pba->pba_block[0] * sizeof(u16));
10604be59a01SSepherosa Ziehau 			} else {
10614be59a01SSepherosa Ziehau 				return -E1000_ERR_PARAM;
10624be59a01SSepherosa Ziehau 			}
10634be59a01SSepherosa Ziehau 		}
10644be59a01SSepherosa Ziehau 	}
10654be59a01SSepherosa Ziehau 
10664be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
10674be59a01SSepherosa Ziehau }
10684be59a01SSepherosa Ziehau 
10694be59a01SSepherosa Ziehau /**
10704be59a01SSepherosa Ziehau  *  e1000_get_pba_block_size
10714be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
10724be59a01SSepherosa Ziehau  *  @eeprom_buf: optional pointer to EEPROM image
10734be59a01SSepherosa Ziehau  *  @eeprom_buf_size: size of EEPROM image in words
10744be59a01SSepherosa Ziehau  *  @pba_data_size: pointer to output variable
10754be59a01SSepherosa Ziehau  *
10764be59a01SSepherosa Ziehau  *  Returns the size of the PBA block in words. Function operates on EEPROM
10774be59a01SSepherosa Ziehau  *  image if the eeprom_buf pointer is not NULL otherwise it accesses physical
10784be59a01SSepherosa Ziehau  *  EEPROM device.
10794be59a01SSepherosa Ziehau  *
10804be59a01SSepherosa Ziehau  **/
e1000_get_pba_block_size(struct e1000_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,u16 * pba_block_size)10814be59a01SSepherosa Ziehau s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
10824be59a01SSepherosa Ziehau 			     u32 eeprom_buf_size, u16 *pba_block_size)
10834be59a01SSepherosa Ziehau {
10844be59a01SSepherosa Ziehau 	s32 ret_val;
10854be59a01SSepherosa Ziehau 	u16 pba_word[2];
10864be59a01SSepherosa Ziehau 	u16 length;
10874be59a01SSepherosa Ziehau 
10884be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_get_pba_block_size");
10894be59a01SSepherosa Ziehau 
10904be59a01SSepherosa Ziehau 	if (eeprom_buf == NULL) {
10914be59a01SSepherosa Ziehau 		ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
10924be59a01SSepherosa Ziehau 		if (ret_val)
10934be59a01SSepherosa Ziehau 			return ret_val;
10944be59a01SSepherosa Ziehau 	} else {
10954be59a01SSepherosa Ziehau 		if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
10964be59a01SSepherosa Ziehau 			pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
10974be59a01SSepherosa Ziehau 			pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
10984be59a01SSepherosa Ziehau 		} else {
10994be59a01SSepherosa Ziehau 			return -E1000_ERR_PARAM;
11004be59a01SSepherosa Ziehau 		}
11014be59a01SSepherosa Ziehau 	}
11024be59a01SSepherosa Ziehau 
11034be59a01SSepherosa Ziehau 	if (pba_word[0] == NVM_PBA_PTR_GUARD) {
11044be59a01SSepherosa Ziehau 		if (eeprom_buf == NULL) {
11054be59a01SSepherosa Ziehau 			ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1,
11064be59a01SSepherosa Ziehau 						 &length);
11074be59a01SSepherosa Ziehau 			if (ret_val)
11084be59a01SSepherosa Ziehau 				return ret_val;
11094be59a01SSepherosa Ziehau 		} else {
11104be59a01SSepherosa Ziehau 			if (eeprom_buf_size > pba_word[1])
11114be59a01SSepherosa Ziehau 				length = eeprom_buf[pba_word[1] + 0];
11124be59a01SSepherosa Ziehau 			else
11134be59a01SSepherosa Ziehau 				return -E1000_ERR_PARAM;
11144be59a01SSepherosa Ziehau 		}
11154be59a01SSepherosa Ziehau 
11164be59a01SSepherosa Ziehau 		if (length == 0xFFFF || length == 0)
11174be59a01SSepherosa Ziehau 			return -E1000_ERR_NVM_PBA_SECTION;
11184be59a01SSepherosa Ziehau 	} else {
11194be59a01SSepherosa Ziehau 		/* PBA number in legacy format, there is no PBA Block. */
11204be59a01SSepherosa Ziehau 		length = 0;
11214be59a01SSepherosa Ziehau 	}
11224be59a01SSepherosa Ziehau 
11234be59a01SSepherosa Ziehau 	if (pba_block_size != NULL)
11244be59a01SSepherosa Ziehau 		*pba_block_size = length;
11254be59a01SSepherosa Ziehau 
11264be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
11279c80d176SSepherosa Ziehau }
11289c80d176SSepherosa Ziehau 
11299c80d176SSepherosa Ziehau /**
11309c80d176SSepherosa Ziehau  *  e1000_read_mac_addr_generic - Read device MAC address
11319c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
11329c80d176SSepherosa Ziehau  *
11339c80d176SSepherosa Ziehau  *  Reads the device MAC address from the EEPROM and stores the value.
11349c80d176SSepherosa Ziehau  *  Since devices with two ports use the same EEPROM, we increment the
11359c80d176SSepherosa Ziehau  *  last bit in the MAC address for the second port.
11369c80d176SSepherosa Ziehau  **/
e1000_read_mac_addr_generic(struct e1000_hw * hw)11379c80d176SSepherosa Ziehau s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
11389c80d176SSepherosa Ziehau {
11396a5a645eSSepherosa Ziehau 	u32 rar_high;
11406a5a645eSSepherosa Ziehau 	u32 rar_low;
11416a5a645eSSepherosa Ziehau 	u16 i;
11426a5a645eSSepherosa Ziehau 
11436a5a645eSSepherosa Ziehau 	rar_high = E1000_READ_REG(hw, E1000_RAH(0));
11446a5a645eSSepherosa Ziehau 	rar_low = E1000_READ_REG(hw, E1000_RAL(0));
11456a5a645eSSepherosa Ziehau 
11466a5a645eSSepherosa Ziehau 	for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
11476a5a645eSSepherosa Ziehau 		hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
11486a5a645eSSepherosa Ziehau 
11496a5a645eSSepherosa Ziehau 	for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
11506a5a645eSSepherosa Ziehau 		hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
11516a5a645eSSepherosa Ziehau 
11526a5a645eSSepherosa Ziehau 	for (i = 0; i < ETH_ADDR_LEN; i++)
11536a5a645eSSepherosa Ziehau 		hw->mac.addr[i] = hw->mac.perm_addr[i];
11546a5a645eSSepherosa Ziehau 
11556a5a645eSSepherosa Ziehau 	return E1000_SUCCESS;
11569c80d176SSepherosa Ziehau }
11579c80d176SSepherosa Ziehau 
11589c80d176SSepherosa Ziehau /**
11599c80d176SSepherosa Ziehau  *  e1000_validate_nvm_checksum_generic - Validate EEPROM checksum
11609c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
11619c80d176SSepherosa Ziehau  *
11629c80d176SSepherosa Ziehau  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
11639c80d176SSepherosa Ziehau  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
11649c80d176SSepherosa Ziehau  **/
e1000_validate_nvm_checksum_generic(struct e1000_hw * hw)11659c80d176SSepherosa Ziehau s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
11669c80d176SSepherosa Ziehau {
11674be59a01SSepherosa Ziehau 	s32 ret_val;
11689c80d176SSepherosa Ziehau 	u16 checksum = 0;
11699c80d176SSepherosa Ziehau 	u16 i, nvm_data;
11709c80d176SSepherosa Ziehau 
11719c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_validate_nvm_checksum_generic");
11729c80d176SSepherosa Ziehau 
11739c80d176SSepherosa Ziehau 	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
11749c80d176SSepherosa Ziehau 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
11759c80d176SSepherosa Ziehau 		if (ret_val) {
11769c80d176SSepherosa Ziehau 			DEBUGOUT("NVM Read Error\n");
11774be59a01SSepherosa Ziehau 			return ret_val;
11789c80d176SSepherosa Ziehau 		}
11799c80d176SSepherosa Ziehau 		checksum += nvm_data;
11809c80d176SSepherosa Ziehau 	}
11819c80d176SSepherosa Ziehau 
11829c80d176SSepherosa Ziehau 	if (checksum != (u16) NVM_SUM) {
11839c80d176SSepherosa Ziehau 		DEBUGOUT("NVM Checksum Invalid\n");
11844be59a01SSepherosa Ziehau 		return -E1000_ERR_NVM;
11859c80d176SSepherosa Ziehau 	}
11869c80d176SSepherosa Ziehau 
11874be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
11889c80d176SSepherosa Ziehau }
11899c80d176SSepherosa Ziehau 
11909c80d176SSepherosa Ziehau /**
11919c80d176SSepherosa Ziehau  *  e1000_update_nvm_checksum_generic - Update EEPROM checksum
11929c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
11939c80d176SSepherosa Ziehau  *
11949c80d176SSepherosa Ziehau  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
11959c80d176SSepherosa Ziehau  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
11969c80d176SSepherosa Ziehau  *  value to the EEPROM.
11979c80d176SSepherosa Ziehau  **/
e1000_update_nvm_checksum_generic(struct e1000_hw * hw)11989c80d176SSepherosa Ziehau s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
11999c80d176SSepherosa Ziehau {
12009c80d176SSepherosa Ziehau 	s32 ret_val;
12019c80d176SSepherosa Ziehau 	u16 checksum = 0;
12029c80d176SSepherosa Ziehau 	u16 i, nvm_data;
12039c80d176SSepherosa Ziehau 
12049c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_update_nvm_checksum");
12059c80d176SSepherosa Ziehau 
12069c80d176SSepherosa Ziehau 	for (i = 0; i < NVM_CHECKSUM_REG; i++) {
12079c80d176SSepherosa Ziehau 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
12089c80d176SSepherosa Ziehau 		if (ret_val) {
12099c80d176SSepherosa Ziehau 			DEBUGOUT("NVM Read Error while updating checksum.\n");
12104be59a01SSepherosa Ziehau 			return ret_val;
12119c80d176SSepherosa Ziehau 		}
12129c80d176SSepherosa Ziehau 		checksum += nvm_data;
12139c80d176SSepherosa Ziehau 	}
12149c80d176SSepherosa Ziehau 	checksum = (u16) NVM_SUM - checksum;
12159c80d176SSepherosa Ziehau 	ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
12169c80d176SSepherosa Ziehau 	if (ret_val)
12179c80d176SSepherosa Ziehau 		DEBUGOUT("NVM Write Error while updating checksum.\n");
12189c80d176SSepherosa Ziehau 
12199c80d176SSepherosa Ziehau 	return ret_val;
12209c80d176SSepherosa Ziehau }
12219c80d176SSepherosa Ziehau 
12229c80d176SSepherosa Ziehau /**
12239c80d176SSepherosa Ziehau  *  e1000_reload_nvm_generic - Reloads EEPROM
12249c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
12259c80d176SSepherosa Ziehau  *
12269c80d176SSepherosa Ziehau  *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
12279c80d176SSepherosa Ziehau  *  extended control register.
12289c80d176SSepherosa Ziehau  **/
e1000_reload_nvm_generic(struct e1000_hw * hw)12296a5a645eSSepherosa Ziehau static void e1000_reload_nvm_generic(struct e1000_hw *hw)
12309c80d176SSepherosa Ziehau {
12319c80d176SSepherosa Ziehau 	u32 ctrl_ext;
12329c80d176SSepherosa Ziehau 
12339c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_reload_nvm_generic");
12349c80d176SSepherosa Ziehau 
12359c80d176SSepherosa Ziehau 	usec_delay(10);
12369c80d176SSepherosa Ziehau 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
12379c80d176SSepherosa Ziehau 	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
12389c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
12399c80d176SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
12409c80d176SSepherosa Ziehau }
12419c80d176SSepherosa Ziehau 
12424be59a01SSepherosa Ziehau /**
12434be59a01SSepherosa Ziehau  *  e1000_get_fw_version - Get firmware version information
12444be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
12454be59a01SSepherosa Ziehau  *  @fw_vers: pointer to output version structure
12464be59a01SSepherosa Ziehau  *
12474be59a01SSepherosa Ziehau  *  unsupported/not present features return 0 in version structure
12484be59a01SSepherosa Ziehau  **/
e1000_get_fw_version(struct e1000_hw * hw,struct e1000_fw_version * fw_vers)12494be59a01SSepherosa Ziehau void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
12504be59a01SSepherosa Ziehau {
1251379ebbe7SSepherosa Ziehau 	u16 eeprom_verh, eeprom_verl, etrack_test, fw_version;
1252379ebbe7SSepherosa Ziehau 	u8 q, hval, rem, result;
12534be59a01SSepherosa Ziehau 	u16 comb_verh, comb_verl, comb_offset;
12544be59a01SSepherosa Ziehau 
12554be59a01SSepherosa Ziehau 	memset(fw_vers, 0, sizeof(struct e1000_fw_version));
12564be59a01SSepherosa Ziehau 
1257379ebbe7SSepherosa Ziehau 	/* basic eeprom version numbers, bits used vary by part and by tool
1258379ebbe7SSepherosa Ziehau 	 * used to create the nvm images */
1259379ebbe7SSepherosa Ziehau 	/* Check which data format we have */
12604be59a01SSepherosa Ziehau 	switch (hw->mac.type) {
12614be59a01SSepherosa Ziehau 	case e1000_i211:
12624be59a01SSepherosa Ziehau 		e1000_read_invm_version(hw, fw_vers);
12634be59a01SSepherosa Ziehau 		return;
12644be59a01SSepherosa Ziehau 	case e1000_82575:
12654be59a01SSepherosa Ziehau 	case e1000_82576:
12664be59a01SSepherosa Ziehau 	case e1000_82580:
126765aebe9fSSepherosa Ziehau 	case e1000_i354:
1268ba0123e0SSepherosa Ziehau 		hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
1269379ebbe7SSepherosa Ziehau 		/* Use this format, unless EETRACK ID exists,
1270379ebbe7SSepherosa Ziehau 		 * then use alternate format
1271379ebbe7SSepherosa Ziehau 		 */
1272379ebbe7SSepherosa Ziehau 		if ((etrack_test &  NVM_MAJOR_MASK) != NVM_ETRACK_VALID) {
12734be59a01SSepherosa Ziehau 			hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
1274379ebbe7SSepherosa Ziehau 			fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
1275379ebbe7SSepherosa Ziehau 					      >> NVM_MAJOR_SHIFT;
1276379ebbe7SSepherosa Ziehau 			fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK)
1277379ebbe7SSepherosa Ziehau 					      >> NVM_MINOR_SHIFT;
1278379ebbe7SSepherosa Ziehau 			fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK);
1279379ebbe7SSepherosa Ziehau 			goto etrack_id;
1280379ebbe7SSepherosa Ziehau 		}
1281379ebbe7SSepherosa Ziehau 		break;
12824be59a01SSepherosa Ziehau 	case e1000_i210:
1283ba0123e0SSepherosa Ziehau 		if (!(e1000_get_flash_presence_i210(hw))) {
1284ba0123e0SSepherosa Ziehau 			e1000_read_invm_version(hw, fw_vers);
1285ba0123e0SSepherosa Ziehau 			return;
1286ba0123e0SSepherosa Ziehau 		}
1287ba0123e0SSepherosa Ziehau 		/* fall through */
12884be59a01SSepherosa Ziehau 	case e1000_i350:
1289ba0123e0SSepherosa Ziehau 		hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
12904be59a01SSepherosa Ziehau 		/* find combo image version */
12914be59a01SSepherosa Ziehau 		hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
12924be59a01SSepherosa Ziehau 		if ((comb_offset != 0x0) &&
12934be59a01SSepherosa Ziehau 		    (comb_offset != NVM_VER_INVALID)) {
12944be59a01SSepherosa Ziehau 
12954be59a01SSepherosa Ziehau 			hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
12964be59a01SSepherosa Ziehau 					 + 1), 1, &comb_verh);
12974be59a01SSepherosa Ziehau 			hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
12984be59a01SSepherosa Ziehau 					 1, &comb_verl);
12994be59a01SSepherosa Ziehau 
13004be59a01SSepherosa Ziehau 			/* get Option Rom version if it exists and is valid */
13014be59a01SSepherosa Ziehau 			if ((comb_verh && comb_verl) &&
13024be59a01SSepherosa Ziehau 			    ((comb_verh != NVM_VER_INVALID) &&
13034be59a01SSepherosa Ziehau 			     (comb_verl != NVM_VER_INVALID))) {
13044be59a01SSepherosa Ziehau 
13054be59a01SSepherosa Ziehau 				fw_vers->or_valid = TRUE;
13064be59a01SSepherosa Ziehau 				fw_vers->or_major =
13074be59a01SSepherosa Ziehau 					comb_verl >> NVM_COMB_VER_SHFT;
13084be59a01SSepherosa Ziehau 				fw_vers->or_build =
13094be59a01SSepherosa Ziehau 					(comb_verl << NVM_COMB_VER_SHFT)
13104be59a01SSepherosa Ziehau 					| (comb_verh >> NVM_COMB_VER_SHFT);
13114be59a01SSepherosa Ziehau 				fw_vers->or_patch =
13124be59a01SSepherosa Ziehau 					comb_verh & NVM_COMB_VER_MASK;
13134be59a01SSepherosa Ziehau 			}
13144be59a01SSepherosa Ziehau 		}
13154be59a01SSepherosa Ziehau 		break;
13164be59a01SSepherosa Ziehau 	default:
1317ba0123e0SSepherosa Ziehau 		hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
1318379ebbe7SSepherosa Ziehau 		return;
1319379ebbe7SSepherosa Ziehau 	}
1320379ebbe7SSepherosa Ziehau 	hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
1321379ebbe7SSepherosa Ziehau 	fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
1322379ebbe7SSepherosa Ziehau 			      >> NVM_MAJOR_SHIFT;
1323379ebbe7SSepherosa Ziehau 
1324379ebbe7SSepherosa Ziehau 	/* check for old style version format in newer images*/
1325379ebbe7SSepherosa Ziehau 	if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) {
1326379ebbe7SSepherosa Ziehau 		eeprom_verl = (fw_version & NVM_COMB_VER_MASK);
1327379ebbe7SSepherosa Ziehau 	} else {
1328379ebbe7SSepherosa Ziehau 		eeprom_verl = (fw_version & NVM_MINOR_MASK)
1329379ebbe7SSepherosa Ziehau 				>> NVM_MINOR_SHIFT;
1330379ebbe7SSepherosa Ziehau 	}
1331379ebbe7SSepherosa Ziehau 	/* Convert minor value to hex before assigning to output struct
1332379ebbe7SSepherosa Ziehau 	 * Val to be converted will not be higher than 99, per tool output
1333379ebbe7SSepherosa Ziehau 	 */
1334379ebbe7SSepherosa Ziehau 	q = eeprom_verl / NVM_HEX_CONV;
1335379ebbe7SSepherosa Ziehau 	hval = q * NVM_HEX_TENS;
1336379ebbe7SSepherosa Ziehau 	rem = eeprom_verl % NVM_HEX_CONV;
1337379ebbe7SSepherosa Ziehau 	result = hval + rem;
1338379ebbe7SSepherosa Ziehau 	fw_vers->eep_minor = result;
1339379ebbe7SSepherosa Ziehau 
1340379ebbe7SSepherosa Ziehau etrack_id:
1341379ebbe7SSepherosa Ziehau 	if ((etrack_test &  NVM_MAJOR_MASK) == NVM_ETRACK_VALID) {
1342379ebbe7SSepherosa Ziehau 		hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
1343379ebbe7SSepherosa Ziehau 		hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
1344379ebbe7SSepherosa Ziehau 		fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT)
1345379ebbe7SSepherosa Ziehau 			| eeprom_verl;
1346ba0123e0SSepherosa Ziehau 	} else if ((etrack_test & NVM_ETRACK_VALID) == 0) {
1347ba0123e0SSepherosa Ziehau 		hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
1348ba0123e0SSepherosa Ziehau 		hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
1349ba0123e0SSepherosa Ziehau 		fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) |
1350ba0123e0SSepherosa Ziehau 				     eeprom_verl;
13514be59a01SSepherosa Ziehau 	}
13524be59a01SSepherosa Ziehau }
13534be59a01SSepherosa Ziehau 
1354