1238148Sjfv/******************************************************************************
2238148Sjfv
3286833Ssbruno  Copyright (c) 2001-2015, Intel Corporation
4238148Sjfv  All rights reserved.
5238148Sjfv
6238148Sjfv  Redistribution and use in source and binary forms, with or without
7238148Sjfv  modification, are permitted provided that the following conditions are met:
8238148Sjfv
9238148Sjfv   1. Redistributions of source code must retain the above copyright notice,
10238148Sjfv      this list of conditions and the following disclaimer.
11238148Sjfv
12238148Sjfv   2. Redistributions in binary form must reproduce the above copyright
13238148Sjfv      notice, this list of conditions and the following disclaimer in the
14238148Sjfv      documentation and/or other materials provided with the distribution.
15238148Sjfv
16238148Sjfv   3. Neither the name of the Intel Corporation nor the names of its
17238148Sjfv      contributors may be used to endorse or promote products derived from
18238148Sjfv      this software without specific prior written permission.
19238148Sjfv
20238148Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21238148Sjfv  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22238148Sjfv  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23238148Sjfv  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24238148Sjfv  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25238148Sjfv  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26238148Sjfv  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27238148Sjfv  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28238148Sjfv  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29238148Sjfv  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30238148Sjfv  POSSIBILITY OF SUCH DAMAGE.
31238148Sjfv
32238148Sjfv******************************************************************************/
33238148Sjfv/*$FreeBSD$*/
34238148Sjfv
35238148Sjfv#include "e1000_api.h"
36238148Sjfv
37238148Sjfv
38238148Sjfvstatic s32 e1000_acquire_nvm_i210(struct e1000_hw *hw);
39238148Sjfvstatic void e1000_release_nvm_i210(struct e1000_hw *hw);
40238148Sjfvstatic s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw);
41238148Sjfvstatic s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
42238148Sjfv				u16 *data);
43238148Sjfvstatic s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
44238148Sjfvstatic s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
45238148Sjfv
46238148Sjfv/**
47238148Sjfv *  e1000_acquire_nvm_i210 - Request for access to EEPROM
48238148Sjfv *  @hw: pointer to the HW structure
49238148Sjfv *
50238148Sjfv *  Acquire the necessary semaphores for exclusive access to the EEPROM.
51238148Sjfv *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
52238148Sjfv *  Return successful if access grant bit set, else clear the request for
53238148Sjfv *  EEPROM access and return -E1000_ERR_NVM (-1).
54238148Sjfv **/
55238148Sjfvstatic s32 e1000_acquire_nvm_i210(struct e1000_hw *hw)
56238148Sjfv{
57238148Sjfv	s32 ret_val;
58238148Sjfv
59238148Sjfv	DEBUGFUNC("e1000_acquire_nvm_i210");
60238148Sjfv
61238148Sjfv	ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
62238148Sjfv
63238148Sjfv	return ret_val;
64238148Sjfv}
65238148Sjfv
66238148Sjfv/**
67238148Sjfv *  e1000_release_nvm_i210 - Release exclusive access to EEPROM
68238148Sjfv *  @hw: pointer to the HW structure
69238148Sjfv *
70238148Sjfv *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
71238148Sjfv *  then release the semaphores acquired.
72238148Sjfv **/
73238148Sjfvstatic void e1000_release_nvm_i210(struct e1000_hw *hw)
74238148Sjfv{
75238148Sjfv	DEBUGFUNC("e1000_release_nvm_i210");
76238148Sjfv
77238148Sjfv	e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
78238148Sjfv}
79238148Sjfv
80238148Sjfv/**
81238148Sjfv *  e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
82238148Sjfv *  @hw: pointer to the HW structure
83238148Sjfv *  @mask: specifies which semaphore to acquire
84238148Sjfv *
85238148Sjfv *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
86238148Sjfv *  will also specify which port we're acquiring the lock for.
87238148Sjfv **/
88238148Sjfvs32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
89238148Sjfv{
90238148Sjfv	u32 swfw_sync;
91238148Sjfv	u32 swmask = mask;
92238148Sjfv	u32 fwmask = mask << 16;
93238148Sjfv	s32 ret_val = E1000_SUCCESS;
94238148Sjfv	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
95238148Sjfv
96238148Sjfv	DEBUGFUNC("e1000_acquire_swfw_sync_i210");
97238148Sjfv
98238148Sjfv	while (i < timeout) {
99238148Sjfv		if (e1000_get_hw_semaphore_i210(hw)) {
100238148Sjfv			ret_val = -E1000_ERR_SWFW_SYNC;
101238148Sjfv			goto out;
102238148Sjfv		}
103238148Sjfv
104238148Sjfv		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
105247064Sjfv		if (!(swfw_sync & (fwmask | swmask)))
106238148Sjfv			break;
107238148Sjfv
108238148Sjfv		/*
109238148Sjfv		 * Firmware currently using resource (fwmask)
110247064Sjfv		 * or other software thread using resource (swmask)
111238148Sjfv		 */
112247064Sjfv		e1000_put_hw_semaphore_generic(hw);
113238148Sjfv		msec_delay_irq(5);
114238148Sjfv		i++;
115238148Sjfv	}
116238148Sjfv
117238148Sjfv	if (i == timeout) {
118238148Sjfv		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
119238148Sjfv		ret_val = -E1000_ERR_SWFW_SYNC;
120238148Sjfv		goto out;
121238148Sjfv	}
122238148Sjfv
123238148Sjfv	swfw_sync |= swmask;
124238148Sjfv	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
125238148Sjfv
126247064Sjfv	e1000_put_hw_semaphore_generic(hw);
127238148Sjfv
128238148Sjfvout:
129238148Sjfv	return ret_val;
130238148Sjfv}
131238148Sjfv
132238148Sjfv/**
133238148Sjfv *  e1000_release_swfw_sync_i210 - Release SW/FW semaphore
134238148Sjfv *  @hw: pointer to the HW structure
135238148Sjfv *  @mask: specifies which semaphore to acquire
136238148Sjfv *
137238148Sjfv *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
138238148Sjfv *  will also specify which port we're releasing the lock for.
139238148Sjfv **/
140238148Sjfvvoid e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
141238148Sjfv{
142238148Sjfv	u32 swfw_sync;
143238148Sjfv
144238148Sjfv	DEBUGFUNC("e1000_release_swfw_sync_i210");
145238148Sjfv
146238148Sjfv	while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
147238148Sjfv		; /* Empty */
148238148Sjfv
149238148Sjfv	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
150238148Sjfv	swfw_sync &= ~mask;
151238148Sjfv	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
152238148Sjfv
153247064Sjfv	e1000_put_hw_semaphore_generic(hw);
154238148Sjfv}
155238148Sjfv
156238148Sjfv/**
157238148Sjfv *  e1000_get_hw_semaphore_i210 - Acquire hardware semaphore
158238148Sjfv *  @hw: pointer to the HW structure
159238148Sjfv *
160238148Sjfv *  Acquire the HW semaphore to access the PHY or NVM
161238148Sjfv **/
162238148Sjfvstatic s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
163238148Sjfv{
164238148Sjfv	u32 swsm;
165238148Sjfv	s32 timeout = hw->nvm.word_size + 1;
166238148Sjfv	s32 i = 0;
167238148Sjfv
168238148Sjfv	DEBUGFUNC("e1000_get_hw_semaphore_i210");
169238148Sjfv
170247064Sjfv	/* Get the SW semaphore */
171247064Sjfv	while (i < timeout) {
172247064Sjfv		swsm = E1000_READ_REG(hw, E1000_SWSM);
173247064Sjfv		if (!(swsm & E1000_SWSM_SMBI))
174247064Sjfv			break;
175247064Sjfv
176247064Sjfv		usec_delay(50);
177247064Sjfv		i++;
178247064Sjfv	}
179247064Sjfv
180247064Sjfv	if (i == timeout) {
181256200Sjfv		/* In rare circumstances, the SW semaphore may already be held
182256200Sjfv		 * unintentionally. Clear the semaphore once before giving up.
183247064Sjfv		 */
184247064Sjfv		if (hw->dev_spec._82575.clear_semaphore_once) {
185247064Sjfv			hw->dev_spec._82575.clear_semaphore_once = FALSE;
186247064Sjfv			e1000_put_hw_semaphore_generic(hw);
187247064Sjfv			for (i = 0; i < timeout; i++) {
188247064Sjfv				swsm = E1000_READ_REG(hw, E1000_SWSM);
189247064Sjfv				if (!(swsm & E1000_SWSM_SMBI))
190247064Sjfv					break;
191247064Sjfv
192247064Sjfv				usec_delay(50);
193247064Sjfv			}
194247064Sjfv		}
195247064Sjfv
196247064Sjfv		/* If we do not have the semaphore here, we have to give up. */
197247064Sjfv		if (i == timeout) {
198247064Sjfv			DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
199247064Sjfv			return -E1000_ERR_NVM;
200247064Sjfv		}
201247064Sjfv	}
202247064Sjfv
203238148Sjfv	/* Get the FW semaphore. */
204238148Sjfv	for (i = 0; i < timeout; i++) {
205238148Sjfv		swsm = E1000_READ_REG(hw, E1000_SWSM);
206238148Sjfv		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
207238148Sjfv
208238148Sjfv		/* Semaphore acquired if bit latched */
209238148Sjfv		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
210238148Sjfv			break;
211238148Sjfv
212238148Sjfv		usec_delay(50);
213238148Sjfv	}
214238148Sjfv
215238148Sjfv	if (i == timeout) {
216238148Sjfv		/* Release semaphores */
217238148Sjfv		e1000_put_hw_semaphore_generic(hw);
218238148Sjfv		DEBUGOUT("Driver can't access the NVM\n");
219247064Sjfv		return -E1000_ERR_NVM;
220238148Sjfv	}
221238148Sjfv
222247064Sjfv	return E1000_SUCCESS;
223238148Sjfv}
224238148Sjfv
225238148Sjfv/**
226238148Sjfv *  e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
227238148Sjfv *  @hw: pointer to the HW structure
228238148Sjfv *  @offset: offset of word in the Shadow Ram to read
229238148Sjfv *  @words: number of words to read
230238148Sjfv *  @data: word read from the Shadow Ram
231238148Sjfv *
232238148Sjfv *  Reads a 16 bit word from the Shadow Ram using the EERD register.
233238148Sjfv *  Uses necessary synchronization semaphores.
234238148Sjfv **/
235238148Sjfvs32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
236238148Sjfv			     u16 *data)
237238148Sjfv{
238238148Sjfv	s32 status = E1000_SUCCESS;
239238148Sjfv	u16 i, count;
240238148Sjfv
241238148Sjfv	DEBUGFUNC("e1000_read_nvm_srrd_i210");
242238148Sjfv
243238148Sjfv	/* We cannot hold synchronization semaphores for too long,
244238148Sjfv	 * because of forceful takeover procedure. However it is more efficient
245238148Sjfv	 * to read in bursts than synchronizing access for each word. */
246238148Sjfv	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
247238148Sjfv		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
248238148Sjfv			E1000_EERD_EEWR_MAX_COUNT : (words - i);
249238148Sjfv		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
250238148Sjfv			status = e1000_read_nvm_eerd(hw, offset, count,
251238148Sjfv						     data + i);
252238148Sjfv			hw->nvm.ops.release(hw);
253238148Sjfv		} else {
254238148Sjfv			status = E1000_ERR_SWFW_SYNC;
255238148Sjfv		}
256238148Sjfv
257238148Sjfv		if (status != E1000_SUCCESS)
258238148Sjfv			break;
259238148Sjfv	}
260238148Sjfv
261238148Sjfv	return status;
262238148Sjfv}
263238148Sjfv
264238148Sjfv/**
265238148Sjfv *  e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
266238148Sjfv *  @hw: pointer to the HW structure
267238148Sjfv *  @offset: offset within the Shadow RAM to be written to
268238148Sjfv *  @words: number of words to write
269238148Sjfv *  @data: 16 bit word(s) to be written to the Shadow RAM
270238148Sjfv *
271238148Sjfv *  Writes data to Shadow RAM at offset using EEWR register.
272238148Sjfv *
273238148Sjfv *  If e1000_update_nvm_checksum is not called after this function , the
274238148Sjfv *  data will not be committed to FLASH and also Shadow RAM will most likely
275238148Sjfv *  contain an invalid checksum.
276238148Sjfv *
277238148Sjfv *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
278238148Sjfv *  partially written.
279238148Sjfv **/
280238148Sjfvs32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
281238148Sjfv			      u16 *data)
282238148Sjfv{
283238148Sjfv	s32 status = E1000_SUCCESS;
284238148Sjfv	u16 i, count;
285238148Sjfv
286238148Sjfv	DEBUGFUNC("e1000_write_nvm_srwr_i210");
287238148Sjfv
288238148Sjfv	/* We cannot hold synchronization semaphores for too long,
289238148Sjfv	 * because of forceful takeover procedure. However it is more efficient
290238148Sjfv	 * to write in bursts than synchronizing access for each word. */
291238148Sjfv	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
292238148Sjfv		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
293238148Sjfv			E1000_EERD_EEWR_MAX_COUNT : (words - i);
294238148Sjfv		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
295238148Sjfv			status = e1000_write_nvm_srwr(hw, offset, count,
296238148Sjfv						      data + i);
297238148Sjfv			hw->nvm.ops.release(hw);
298238148Sjfv		} else {
299238148Sjfv			status = E1000_ERR_SWFW_SYNC;
300238148Sjfv		}
301238148Sjfv
302238148Sjfv		if (status != E1000_SUCCESS)
303238148Sjfv			break;
304238148Sjfv	}
305238148Sjfv
306238148Sjfv	return status;
307238148Sjfv}
308238148Sjfv
309238148Sjfv/**
310238148Sjfv *  e1000_write_nvm_srwr - Write to Shadow Ram using EEWR
311238148Sjfv *  @hw: pointer to the HW structure
312238148Sjfv *  @offset: offset within the Shadow Ram to be written to
313238148Sjfv *  @words: number of words to write
314238148Sjfv *  @data: 16 bit word(s) to be written to the Shadow Ram
315238148Sjfv *
316238148Sjfv *  Writes data to Shadow Ram at offset using EEWR register.
317238148Sjfv *
318238148Sjfv *  If e1000_update_nvm_checksum is not called after this function , the
319238148Sjfv *  Shadow Ram will most likely contain an invalid checksum.
320238148Sjfv **/
321238148Sjfvstatic s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
322238148Sjfv				u16 *data)
323238148Sjfv{
324238148Sjfv	struct e1000_nvm_info *nvm = &hw->nvm;
325238148Sjfv	u32 i, k, eewr = 0;
326238148Sjfv	u32 attempts = 100000;
327238148Sjfv	s32 ret_val = E1000_SUCCESS;
328238148Sjfv
329238148Sjfv	DEBUGFUNC("e1000_write_nvm_srwr");
330238148Sjfv
331238148Sjfv	/*
332238148Sjfv	 * A check for invalid values:  offset too large, too many words,
333238148Sjfv	 * too many words for the offset, and not enough words.
334238148Sjfv	 */
335238148Sjfv	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
336238148Sjfv	    (words == 0)) {
337238148Sjfv		DEBUGOUT("nvm parameter(s) out of bounds\n");
338238148Sjfv		ret_val = -E1000_ERR_NVM;
339238148Sjfv		goto out;
340238148Sjfv	}
341238148Sjfv
342238148Sjfv	for (i = 0; i < words; i++) {
343238148Sjfv		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
344238148Sjfv			(data[i] << E1000_NVM_RW_REG_DATA) |
345238148Sjfv			E1000_NVM_RW_REG_START;
346238148Sjfv
347238148Sjfv		E1000_WRITE_REG(hw, E1000_SRWR, eewr);
348238148Sjfv
349238148Sjfv		for (k = 0; k < attempts; k++) {
350238148Sjfv			if (E1000_NVM_RW_REG_DONE &
351238148Sjfv			    E1000_READ_REG(hw, E1000_SRWR)) {
352238148Sjfv				ret_val = E1000_SUCCESS;
353238148Sjfv				break;
354238148Sjfv			}
355238148Sjfv			usec_delay(5);
356238148Sjfv		}
357238148Sjfv
358238148Sjfv		if (ret_val != E1000_SUCCESS) {
359238148Sjfv			DEBUGOUT("Shadow RAM write EEWR timed out\n");
360238148Sjfv			break;
361238148Sjfv		}
362238148Sjfv	}
363238148Sjfv
364238148Sjfvout:
365238148Sjfv	return ret_val;
366238148Sjfv}
367238148Sjfv
368256200Sjfv/** e1000_read_invm_word_i210 - Reads OTP
369238148Sjfv *  @hw: pointer to the HW structure
370238148Sjfv *  @address: the word address (aka eeprom offset) to read
371238148Sjfv *  @data: pointer to the data read
372238148Sjfv *
373256200Sjfv *  Reads 16-bit words from the OTP. Return error when the word is not
374256200Sjfv *  stored in OTP.
375256200Sjfv **/
376256200Sjfvstatic s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
377256200Sjfv{
378256200Sjfv	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
379256200Sjfv	u32 invm_dword;
380256200Sjfv	u16 i;
381256200Sjfv	u8 record_type, word_address;
382256200Sjfv
383256200Sjfv	DEBUGFUNC("e1000_read_invm_word_i210");
384256200Sjfv
385256200Sjfv	for (i = 0; i < E1000_INVM_SIZE; i++) {
386256200Sjfv		invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
387256200Sjfv		/* Get record type */
388256200Sjfv		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
389256200Sjfv		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
390256200Sjfv			break;
391256200Sjfv		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
392256200Sjfv			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
393256200Sjfv		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
394256200Sjfv			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
395256200Sjfv		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
396256200Sjfv			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
397256200Sjfv			if (word_address == address) {
398256200Sjfv				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
399256200Sjfv				DEBUGOUT2("Read INVM Word 0x%02x = %x",
400256200Sjfv					  address, *data);
401256200Sjfv				status = E1000_SUCCESS;
402256200Sjfv				break;
403256200Sjfv			}
404256200Sjfv		}
405256200Sjfv	}
406256200Sjfv	if (status != E1000_SUCCESS)
407256200Sjfv		DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address);
408256200Sjfv	return status;
409256200Sjfv}
410256200Sjfv
411256200Sjfv/** e1000_read_invm_i210 - Read invm wrapper function for I210/I211
412256200Sjfv *  @hw: pointer to the HW structure
413256200Sjfv *  @address: the word address (aka eeprom offset) to read
414256200Sjfv *  @data: pointer to the data read
415256200Sjfv *
416238148Sjfv *  Wrapper function to return data formerly found in the NVM.
417238148Sjfv **/
418256200Sjfvstatic s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset,
419256200Sjfv				u16 E1000_UNUSEDARG words, u16 *data)
420238148Sjfv{
421238148Sjfv	s32 ret_val = E1000_SUCCESS;
422238148Sjfv
423256200Sjfv	DEBUGFUNC("e1000_read_invm_i210");
424238148Sjfv
425238148Sjfv	/* Only the MAC addr is required to be present in the iNVM */
426238148Sjfv	switch (offset) {
427238148Sjfv	case NVM_MAC_ADDR:
428256200Sjfv		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]);
429256200Sjfv		ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1,
430256200Sjfv						     &data[1]);
431256200Sjfv		ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2,
432256200Sjfv						     &data[2]);
433238148Sjfv		if (ret_val != E1000_SUCCESS)
434238148Sjfv			DEBUGOUT("MAC Addr not found in iNVM\n");
435238148Sjfv		break;
436238148Sjfv	case NVM_INIT_CTRL_2:
437256200Sjfv		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
438247064Sjfv		if (ret_val != E1000_SUCCESS) {
439247064Sjfv			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
440247064Sjfv			ret_val = E1000_SUCCESS;
441247064Sjfv		}
442247064Sjfv		break;
443238148Sjfv	case NVM_INIT_CTRL_4:
444256200Sjfv		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
445247064Sjfv		if (ret_val != E1000_SUCCESS) {
446247064Sjfv			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
447247064Sjfv			ret_val = E1000_SUCCESS;
448247064Sjfv		}
449247064Sjfv		break;
450238148Sjfv	case NVM_LED_1_CFG:
451256200Sjfv		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
452247064Sjfv		if (ret_val != E1000_SUCCESS) {
453247064Sjfv			*data = NVM_LED_1_CFG_DEFAULT_I211;
454247064Sjfv			ret_val = E1000_SUCCESS;
455247064Sjfv		}
456247064Sjfv		break;
457238148Sjfv	case NVM_LED_0_2_CFG:
458256200Sjfv		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
459247064Sjfv		if (ret_val != E1000_SUCCESS) {
460247064Sjfv			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
461247064Sjfv			ret_val = E1000_SUCCESS;
462247064Sjfv		}
463238148Sjfv		break;
464247064Sjfv	case NVM_ID_LED_SETTINGS:
465256200Sjfv		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
466247064Sjfv		if (ret_val != E1000_SUCCESS) {
467247064Sjfv			*data = ID_LED_RESERVED_FFFF;
468247064Sjfv			ret_val = E1000_SUCCESS;
469247064Sjfv		}
470238148Sjfv		break;
471238148Sjfv	case NVM_SUB_DEV_ID:
472238148Sjfv		*data = hw->subsystem_device_id;
473238148Sjfv		break;
474238148Sjfv	case NVM_SUB_VEN_ID:
475238148Sjfv		*data = hw->subsystem_vendor_id;
476238148Sjfv		break;
477238148Sjfv	case NVM_DEV_ID:
478238148Sjfv		*data = hw->device_id;
479238148Sjfv		break;
480238148Sjfv	case NVM_VEN_ID:
481238148Sjfv		*data = hw->vendor_id;
482238148Sjfv		break;
483238148Sjfv	default:
484238148Sjfv		DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
485238148Sjfv		*data = NVM_RESERVED_WORD;
486238148Sjfv		break;
487238148Sjfv	}
488238148Sjfv	return ret_val;
489238148Sjfv}
490238148Sjfv
491238148Sjfv/**
492238148Sjfv *  e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum
493238148Sjfv *  @hw: pointer to the HW structure
494238148Sjfv *
495238148Sjfv *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
496238148Sjfv *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
497238148Sjfv **/
498238148Sjfvs32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw)
499238148Sjfv{
500238148Sjfv	s32 status = E1000_SUCCESS;
501238148Sjfv	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
502238148Sjfv
503238148Sjfv	DEBUGFUNC("e1000_validate_nvm_checksum_i210");
504238148Sjfv
505238148Sjfv	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
506238148Sjfv
507238148Sjfv		/*
508238148Sjfv		 * Replace the read function with semaphore grabbing with
509238148Sjfv		 * the one that skips this for a while.
510238148Sjfv		 * We have semaphore taken already here.
511238148Sjfv		 */
512238148Sjfv		read_op_ptr = hw->nvm.ops.read;
513238148Sjfv		hw->nvm.ops.read = e1000_read_nvm_eerd;
514238148Sjfv
515238148Sjfv		status = e1000_validate_nvm_checksum_generic(hw);
516238148Sjfv
517238148Sjfv		/* Revert original read operation. */
518238148Sjfv		hw->nvm.ops.read = read_op_ptr;
519238148Sjfv
520238148Sjfv		hw->nvm.ops.release(hw);
521238148Sjfv	} else {
522238148Sjfv		status = E1000_ERR_SWFW_SYNC;
523238148Sjfv	}
524238148Sjfv
525238148Sjfv	return status;
526238148Sjfv}
527238148Sjfv
528238148Sjfv
529238148Sjfv/**
530238148Sjfv *  e1000_update_nvm_checksum_i210 - Update EEPROM checksum
531238148Sjfv *  @hw: pointer to the HW structure
532238148Sjfv *
533238148Sjfv *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
534238148Sjfv *  up to the checksum.  Then calculates the EEPROM checksum and writes the
535238148Sjfv *  value to the EEPROM. Next commit EEPROM data onto the Flash.
536238148Sjfv **/
537238148Sjfvs32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw)
538238148Sjfv{
539267935Sjfv	s32 ret_val;
540238148Sjfv	u16 checksum = 0;
541238148Sjfv	u16 i, nvm_data;
542238148Sjfv
543238148Sjfv	DEBUGFUNC("e1000_update_nvm_checksum_i210");
544238148Sjfv
545238148Sjfv	/*
546238148Sjfv	 * Read the first word from the EEPROM. If this times out or fails, do
547238148Sjfv	 * not continue or we could be in for a very long wait while every
548238148Sjfv	 * EEPROM read fails
549238148Sjfv	 */
550238148Sjfv	ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);
551238148Sjfv	if (ret_val != E1000_SUCCESS) {
552238148Sjfv		DEBUGOUT("EEPROM read failed\n");
553238148Sjfv		goto out;
554238148Sjfv	}
555238148Sjfv
556238148Sjfv	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
557238148Sjfv		/*
558238148Sjfv		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
559238148Sjfv		 * because we do not want to take the synchronization
560238148Sjfv		 * semaphores twice here.
561238148Sjfv		 */
562238148Sjfv
563238148Sjfv		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
564238148Sjfv			ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);
565238148Sjfv			if (ret_val) {
566238148Sjfv				hw->nvm.ops.release(hw);
567238148Sjfv				DEBUGOUT("NVM Read Error while updating checksum.\n");
568238148Sjfv				goto out;
569238148Sjfv			}
570238148Sjfv			checksum += nvm_data;
571238148Sjfv		}
572238148Sjfv		checksum = (u16) NVM_SUM - checksum;
573238148Sjfv		ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
574238148Sjfv						&checksum);
575238148Sjfv		if (ret_val != E1000_SUCCESS) {
576238148Sjfv			hw->nvm.ops.release(hw);
577238148Sjfv			DEBUGOUT("NVM Write Error while updating checksum.\n");
578238148Sjfv			goto out;
579238148Sjfv		}
580238148Sjfv
581238148Sjfv		hw->nvm.ops.release(hw);
582238148Sjfv
583238148Sjfv		ret_val = e1000_update_flash_i210(hw);
584238148Sjfv	} else {
585238148Sjfv		ret_val = E1000_ERR_SWFW_SYNC;
586238148Sjfv	}
587238148Sjfvout:
588238148Sjfv	return ret_val;
589238148Sjfv}
590238148Sjfv
591238148Sjfv/**
592256200Sjfv *  e1000_get_flash_presence_i210 - Check if flash device is detected.
593256200Sjfv *  @hw: pointer to the HW structure
594256200Sjfv *
595256200Sjfv **/
596256200Sjfvbool e1000_get_flash_presence_i210(struct e1000_hw *hw)
597256200Sjfv{
598256200Sjfv	u32 eec = 0;
599256200Sjfv	bool ret_val = FALSE;
600256200Sjfv
601256200Sjfv	DEBUGFUNC("e1000_get_flash_presence_i210");
602256200Sjfv
603256200Sjfv	eec = E1000_READ_REG(hw, E1000_EECD);
604256200Sjfv
605256200Sjfv	if (eec & E1000_EECD_FLASH_DETECTED_I210)
606256200Sjfv		ret_val = TRUE;
607256200Sjfv
608256200Sjfv	return ret_val;
609256200Sjfv}
610256200Sjfv
611256200Sjfv/**
612238148Sjfv *  e1000_update_flash_i210 - Commit EEPROM to the flash
613238148Sjfv *  @hw: pointer to the HW structure
614238148Sjfv *
615238148Sjfv **/
616238148Sjfvs32 e1000_update_flash_i210(struct e1000_hw *hw)
617238148Sjfv{
618267935Sjfv	s32 ret_val;
619238148Sjfv	u32 flup;
620238148Sjfv
621238148Sjfv	DEBUGFUNC("e1000_update_flash_i210");
622238148Sjfv
623238148Sjfv	ret_val = e1000_pool_flash_update_done_i210(hw);
624238148Sjfv	if (ret_val == -E1000_ERR_NVM) {
625238148Sjfv		DEBUGOUT("Flash update time out\n");
626238148Sjfv		goto out;
627238148Sjfv	}
628238148Sjfv
629238148Sjfv	flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210;
630238148Sjfv	E1000_WRITE_REG(hw, E1000_EECD, flup);
631238148Sjfv
632238148Sjfv	ret_val = e1000_pool_flash_update_done_i210(hw);
633238148Sjfv	if (ret_val == E1000_SUCCESS)
634238148Sjfv		DEBUGOUT("Flash update complete\n");
635238148Sjfv	else
636238148Sjfv		DEBUGOUT("Flash update time out\n");
637238148Sjfv
638238148Sjfvout:
639238148Sjfv	return ret_val;
640238148Sjfv}
641238148Sjfv
642238148Sjfv/**
643238148Sjfv *  e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
644238148Sjfv *  @hw: pointer to the HW structure
645238148Sjfv *
646238148Sjfv **/
647238148Sjfvs32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
648238148Sjfv{
649238148Sjfv	s32 ret_val = -E1000_ERR_NVM;
650238148Sjfv	u32 i, reg;
651238148Sjfv
652238148Sjfv	DEBUGFUNC("e1000_pool_flash_update_done_i210");
653238148Sjfv
654238148Sjfv	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
655238148Sjfv		reg = E1000_READ_REG(hw, E1000_EECD);
656238148Sjfv		if (reg & E1000_EECD_FLUDONE_I210) {
657238148Sjfv			ret_val = E1000_SUCCESS;
658238148Sjfv			break;
659238148Sjfv		}
660238148Sjfv		usec_delay(5);
661238148Sjfv	}
662238148Sjfv
663238148Sjfv	return ret_val;
664238148Sjfv}
665238148Sjfv
666238148Sjfv/**
667238148Sjfv *  e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers
668238148Sjfv *  @hw: pointer to the HW structure
669238148Sjfv *
670256200Sjfv *  Initialize the i210/i211 NVM parameters and function pointers.
671238148Sjfv **/
672238148Sjfvstatic s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
673238148Sjfv{
674267935Sjfv	s32 ret_val;
675238148Sjfv	struct e1000_nvm_info *nvm = &hw->nvm;
676238148Sjfv
677238148Sjfv	DEBUGFUNC("e1000_init_nvm_params_i210");
678238148Sjfv
679238148Sjfv	ret_val = e1000_init_nvm_params_82575(hw);
680238148Sjfv	nvm->ops.acquire = e1000_acquire_nvm_i210;
681238148Sjfv	nvm->ops.release = e1000_release_nvm_i210;
682238148Sjfv	nvm->ops.valid_led_default = e1000_valid_led_default_i210;
683256200Sjfv	if (e1000_get_flash_presence_i210(hw)) {
684256200Sjfv		hw->nvm.type = e1000_nvm_flash_hw;
685256200Sjfv		nvm->ops.read    = e1000_read_nvm_srrd_i210;
686256200Sjfv		nvm->ops.write   = e1000_write_nvm_srwr_i210;
687256200Sjfv		nvm->ops.validate = e1000_validate_nvm_checksum_i210;
688256200Sjfv		nvm->ops.update   = e1000_update_nvm_checksum_i210;
689256200Sjfv	} else {
690256200Sjfv		hw->nvm.type = e1000_nvm_invm;
691256200Sjfv		nvm->ops.read     = e1000_read_invm_i210;
692256200Sjfv		nvm->ops.write    = e1000_null_write_nvm;
693256200Sjfv		nvm->ops.validate = e1000_null_ops_generic;
694256200Sjfv		nvm->ops.update   = e1000_null_ops_generic;
695256200Sjfv	}
696238148Sjfv	return ret_val;
697238148Sjfv}
698238148Sjfv
699238148Sjfv/**
700238148Sjfv *  e1000_init_function_pointers_i210 - Init func ptrs.
701238148Sjfv *  @hw: pointer to the HW structure
702238148Sjfv *
703238148Sjfv *  Called to initialize all function pointers and parameters.
704238148Sjfv **/
705238148Sjfvvoid e1000_init_function_pointers_i210(struct e1000_hw *hw)
706238148Sjfv{
707238148Sjfv	e1000_init_function_pointers_82575(hw);
708256200Sjfv	hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
709238148Sjfv
710238148Sjfv	return;
711238148Sjfv}
712238148Sjfv
713238148Sjfv/**
714238148Sjfv *  e1000_valid_led_default_i210 - Verify a valid default LED config
715238148Sjfv *  @hw: pointer to the HW structure
716238148Sjfv *  @data: pointer to the NVM (EEPROM)
717238148Sjfv *
718238148Sjfv *  Read the EEPROM for the current default LED configuration.  If the
719238148Sjfv *  LED configuration is not valid, set to a valid LED configuration.
720238148Sjfv **/
721238148Sjfvstatic s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
722238148Sjfv{
723238148Sjfv	s32 ret_val;
724238148Sjfv
725238148Sjfv	DEBUGFUNC("e1000_valid_led_default_i210");
726238148Sjfv
727238148Sjfv	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
728238148Sjfv	if (ret_val) {
729238148Sjfv		DEBUGOUT("NVM Read Error\n");
730238148Sjfv		goto out;
731238148Sjfv	}
732238148Sjfv
733238148Sjfv	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
734238148Sjfv		switch (hw->phy.media_type) {
735238148Sjfv		case e1000_media_type_internal_serdes:
736238148Sjfv			*data = ID_LED_DEFAULT_I210_SERDES;
737238148Sjfv			break;
738238148Sjfv		case e1000_media_type_copper:
739238148Sjfv		default:
740238148Sjfv			*data = ID_LED_DEFAULT_I210;
741238148Sjfv			break;
742238148Sjfv		}
743238148Sjfv	}
744238148Sjfvout:
745238148Sjfv	return ret_val;
746238148Sjfv}
747256200Sjfv
748256200Sjfv/**
749256200Sjfv *  __e1000_access_xmdio_reg - Read/write XMDIO register
750256200Sjfv *  @hw: pointer to the HW structure
751256200Sjfv *  @address: XMDIO address to program
752256200Sjfv *  @dev_addr: device address to program
753256200Sjfv *  @data: pointer to value to read/write from/to the XMDIO address
754256200Sjfv *  @read: boolean flag to indicate read or write
755256200Sjfv **/
756256200Sjfvstatic s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address,
757256200Sjfv				    u8 dev_addr, u16 *data, bool read)
758256200Sjfv{
759267935Sjfv	s32 ret_val;
760256200Sjfv
761256200Sjfv	DEBUGFUNC("__e1000_access_xmdio_reg");
762256200Sjfv
763256200Sjfv	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
764256200Sjfv	if (ret_val)
765256200Sjfv		return ret_val;
766256200Sjfv
767256200Sjfv	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
768256200Sjfv	if (ret_val)
769256200Sjfv		return ret_val;
770256200Sjfv
771256200Sjfv	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
772256200Sjfv							 dev_addr);
773256200Sjfv	if (ret_val)
774256200Sjfv		return ret_val;
775256200Sjfv
776256200Sjfv	if (read)
777256200Sjfv		ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
778256200Sjfv	else
779256200Sjfv		ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
780256200Sjfv	if (ret_val)
781256200Sjfv		return ret_val;
782256200Sjfv
783256200Sjfv	/* Recalibrate the device back to 0 */
784256200Sjfv	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
785256200Sjfv	if (ret_val)
786256200Sjfv		return ret_val;
787256200Sjfv
788256200Sjfv	return ret_val;
789256200Sjfv}
790256200Sjfv
791256200Sjfv/**
792256200Sjfv *  e1000_read_xmdio_reg - Read XMDIO register
793256200Sjfv *  @hw: pointer to the HW structure
794256200Sjfv *  @addr: XMDIO address to program
795256200Sjfv *  @dev_addr: device address to program
796256200Sjfv *  @data: value to be read from the EMI address
797256200Sjfv **/
798256200Sjfvs32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
799256200Sjfv{
800256200Sjfv	DEBUGFUNC("e1000_read_xmdio_reg");
801256200Sjfv
802256200Sjfv	return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, TRUE);
803256200Sjfv}
804256200Sjfv
805256200Sjfv/**
806256200Sjfv *  e1000_write_xmdio_reg - Write XMDIO register
807256200Sjfv *  @hw: pointer to the HW structure
808256200Sjfv *  @addr: XMDIO address to program
809256200Sjfv *  @dev_addr: device address to program
810256200Sjfv *  @data: value to be written to the XMDIO address
811256200Sjfv **/
812256200Sjfvs32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
813256200Sjfv{
814256200Sjfv	DEBUGFUNC("e1000_read_xmdio_reg");
815256200Sjfv
816256200Sjfv	return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, FALSE);
817256200Sjfv}
818267935Sjfv
819267935Sjfv/**
820267935Sjfv * e1000_pll_workaround_i210
821267935Sjfv * @hw: pointer to the HW structure
822267935Sjfv *
823267935Sjfv * Works around an errata in the PLL circuit where it occasionally
824267935Sjfv * provides the wrong clock frequency after power up.
825267935Sjfv **/
826267935Sjfvstatic s32 e1000_pll_workaround_i210(struct e1000_hw *hw)
827267935Sjfv{
828267935Sjfv	s32 ret_val;
829267935Sjfv	u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
830267935Sjfv	u16 nvm_word, phy_word, pci_word, tmp_nvm;
831267935Sjfv	int i;
832267935Sjfv
833267935Sjfv	/* Get and set needed register values */
834267935Sjfv	wuc = E1000_READ_REG(hw, E1000_WUC);
835267935Sjfv	mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
836267935Sjfv	reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;
837267935Sjfv	E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val);
838267935Sjfv
839267935Sjfv	/* Get data from NVM, or set default */
840267935Sjfv	ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD,
841267935Sjfv					    &nvm_word);
842267935Sjfv	if (ret_val != E1000_SUCCESS)
843267935Sjfv		nvm_word = E1000_INVM_DEFAULT_AL;
844267935Sjfv	tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
845267935Sjfv	for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
846267935Sjfv		/* check current state directly from internal PHY */
847267935Sjfv		e1000_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE |
848267935Sjfv					 E1000_PHY_PLL_FREQ_REG), &phy_word);
849267935Sjfv		if ((phy_word & E1000_PHY_PLL_UNCONF)
850267935Sjfv		    != E1000_PHY_PLL_UNCONF) {
851267935Sjfv			ret_val = E1000_SUCCESS;
852267935Sjfv			break;
853267935Sjfv		} else {
854267935Sjfv			ret_val = -E1000_ERR_PHY;
855267935Sjfv		}
856267935Sjfv		/* directly reset the internal PHY */
857267935Sjfv		ctrl = E1000_READ_REG(hw, E1000_CTRL);
858267935Sjfv		E1000_WRITE_REG(hw, E1000_CTRL, ctrl|E1000_CTRL_PHY_RST);
859267935Sjfv
860267935Sjfv		ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
861267935Sjfv		ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);
862267935Sjfv		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
863267935Sjfv
864267935Sjfv		E1000_WRITE_REG(hw, E1000_WUC, 0);
865267935Sjfv		reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
866267935Sjfv		E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val);
867267935Sjfv
868267935Sjfv		e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
869267935Sjfv		pci_word |= E1000_PCI_PMCSR_D3;
870267935Sjfv		e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
871267935Sjfv		msec_delay(1);
872267935Sjfv		pci_word &= ~E1000_PCI_PMCSR_D3;
873267935Sjfv		e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
874267935Sjfv		reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);
875267935Sjfv		E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val);
876267935Sjfv
877267935Sjfv		/* restore WUC register */
878267935Sjfv		E1000_WRITE_REG(hw, E1000_WUC, wuc);
879267935Sjfv	}
880267935Sjfv	/* restore MDICNFG setting */
881267935Sjfv	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
882267935Sjfv	return ret_val;
883267935Sjfv}
884267935Sjfv
885267935Sjfv/**
886295323Serj *  e1000_get_cfg_done_i210 - Read config done bit
887295323Serj *  @hw: pointer to the HW structure
888295323Serj *
889295323Serj *  Read the management control register for the config done bit for
890295323Serj *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
891295323Serj *  to read the config done bit, so an error is *ONLY* logged and returns
892295323Serj *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
893295323Serj *  would not be able to be reset or change link.
894295323Serj **/
895295323Serjstatic s32 e1000_get_cfg_done_i210(struct e1000_hw *hw)
896295323Serj{
897295323Serj	s32 timeout = PHY_CFG_TIMEOUT;
898295323Serj	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
899295323Serj
900295323Serj	DEBUGFUNC("e1000_get_cfg_done_i210");
901295323Serj
902295323Serj	while (timeout) {
903295323Serj		if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask)
904295323Serj			break;
905295323Serj		msec_delay(1);
906295323Serj		timeout--;
907295323Serj	}
908295323Serj	if (!timeout)
909295323Serj		DEBUGOUT("MNG configuration cycle has not completed.\n");
910295323Serj
911295323Serj	return E1000_SUCCESS;
912295323Serj}
913295323Serj
914295323Serj/**
915267935Sjfv *  e1000_init_hw_i210 - Init hw for I210/I211
916267935Sjfv *  @hw: pointer to the HW structure
917267935Sjfv *
918267935Sjfv *  Called to initialize hw for i210 hw family.
919267935Sjfv **/
920267935Sjfvs32 e1000_init_hw_i210(struct e1000_hw *hw)
921267935Sjfv{
922267935Sjfv	s32 ret_val;
923267935Sjfv
924267935Sjfv	DEBUGFUNC("e1000_init_hw_i210");
925267935Sjfv	if ((hw->mac.type >= e1000_i210) &&
926267935Sjfv	    !(e1000_get_flash_presence_i210(hw))) {
927267935Sjfv		ret_val = e1000_pll_workaround_i210(hw);
928267935Sjfv		if (ret_val != E1000_SUCCESS)
929267935Sjfv			return ret_val;
930267935Sjfv	}
931295323Serj	hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210;
932267935Sjfv	ret_val = e1000_init_hw_82575(hw);
933267935Sjfv	return ret_val;
934267935Sjfv}
935