e1000_i210.c revision 238148
1238148Sjfv/******************************************************************************
2238148Sjfv
3238148Sjfv  Copyright (c) 2001-2012, 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: head/sys/dev/e1000/e1000_i210.c 238148 2012-07-05 20:26:57Z jfv $*/
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 void e1000_put_hw_semaphore_i210(struct e1000_hw *hw);
42238148Sjfvstatic s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
43238148Sjfv				u16 *data);
44238148Sjfvstatic s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
45238148Sjfvstatic s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
46238148Sjfvstatic s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
47238148Sjfv			       u16 *data);
48238148Sjfv
49238148Sjfv/**
50238148Sjfv *  e1000_acquire_nvm_i210 - Request for access to EEPROM
51238148Sjfv *  @hw: pointer to the HW structure
52238148Sjfv *
53238148Sjfv *  Acquire the necessary semaphores for exclusive access to the EEPROM.
54238148Sjfv *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
55238148Sjfv *  Return successful if access grant bit set, else clear the request for
56238148Sjfv *  EEPROM access and return -E1000_ERR_NVM (-1).
57238148Sjfv **/
58238148Sjfvstatic s32 e1000_acquire_nvm_i210(struct e1000_hw *hw)
59238148Sjfv{
60238148Sjfv	s32 ret_val;
61238148Sjfv
62238148Sjfv	DEBUGFUNC("e1000_acquire_nvm_i210");
63238148Sjfv
64238148Sjfv	ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
65238148Sjfv
66238148Sjfv	return ret_val;
67238148Sjfv}
68238148Sjfv
69238148Sjfv/**
70238148Sjfv *  e1000_release_nvm_i210 - Release exclusive access to EEPROM
71238148Sjfv *  @hw: pointer to the HW structure
72238148Sjfv *
73238148Sjfv *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
74238148Sjfv *  then release the semaphores acquired.
75238148Sjfv **/
76238148Sjfvstatic void e1000_release_nvm_i210(struct e1000_hw *hw)
77238148Sjfv{
78238148Sjfv	DEBUGFUNC("e1000_release_nvm_i210");
79238148Sjfv
80238148Sjfv	e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
81238148Sjfv}
82238148Sjfv
83238148Sjfv/**
84238148Sjfv *  e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
85238148Sjfv *  @hw: pointer to the HW structure
86238148Sjfv *  @mask: specifies which semaphore to acquire
87238148Sjfv *
88238148Sjfv *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
89238148Sjfv *  will also specify which port we're acquiring the lock for.
90238148Sjfv **/
91238148Sjfvs32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
92238148Sjfv{
93238148Sjfv	u32 swfw_sync;
94238148Sjfv	u32 swmask = mask;
95238148Sjfv	u32 fwmask = mask << 16;
96238148Sjfv	s32 ret_val = E1000_SUCCESS;
97238148Sjfv	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
98238148Sjfv
99238148Sjfv	DEBUGFUNC("e1000_acquire_swfw_sync_i210");
100238148Sjfv
101238148Sjfv	while (i < timeout) {
102238148Sjfv		if (e1000_get_hw_semaphore_i210(hw)) {
103238148Sjfv			ret_val = -E1000_ERR_SWFW_SYNC;
104238148Sjfv			goto out;
105238148Sjfv		}
106238148Sjfv
107238148Sjfv		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
108238148Sjfv		if (!(swfw_sync & fwmask))
109238148Sjfv			break;
110238148Sjfv
111238148Sjfv		/*
112238148Sjfv		 * Firmware currently using resource (fwmask)
113238148Sjfv		 */
114238148Sjfv		e1000_put_hw_semaphore_i210(hw);
115238148Sjfv		msec_delay_irq(5);
116238148Sjfv		i++;
117238148Sjfv	}
118238148Sjfv
119238148Sjfv	if (i == timeout) {
120238148Sjfv		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
121238148Sjfv		ret_val = -E1000_ERR_SWFW_SYNC;
122238148Sjfv		goto out;
123238148Sjfv	}
124238148Sjfv
125238148Sjfv	swfw_sync |= swmask;
126238148Sjfv	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
127238148Sjfv
128238148Sjfv	e1000_put_hw_semaphore_i210(hw);
129238148Sjfv
130238148Sjfvout:
131238148Sjfv	return ret_val;
132238148Sjfv}
133238148Sjfv
134238148Sjfv/**
135238148Sjfv *  e1000_release_swfw_sync_i210 - Release SW/FW semaphore
136238148Sjfv *  @hw: pointer to the HW structure
137238148Sjfv *  @mask: specifies which semaphore to acquire
138238148Sjfv *
139238148Sjfv *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
140238148Sjfv *  will also specify which port we're releasing the lock for.
141238148Sjfv **/
142238148Sjfvvoid e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
143238148Sjfv{
144238148Sjfv	u32 swfw_sync;
145238148Sjfv
146238148Sjfv	DEBUGFUNC("e1000_release_swfw_sync_i210");
147238148Sjfv
148238148Sjfv	while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
149238148Sjfv		; /* Empty */
150238148Sjfv
151238148Sjfv	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
152238148Sjfv	swfw_sync &= ~mask;
153238148Sjfv	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
154238148Sjfv
155238148Sjfv	e1000_put_hw_semaphore_i210(hw);
156238148Sjfv}
157238148Sjfv
158238148Sjfv/**
159238148Sjfv *  e1000_get_hw_semaphore_i210 - Acquire hardware semaphore
160238148Sjfv *  @hw: pointer to the HW structure
161238148Sjfv *
162238148Sjfv *  Acquire the HW semaphore to access the PHY or NVM
163238148Sjfv **/
164238148Sjfvstatic s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
165238148Sjfv{
166238148Sjfv	u32 swsm;
167238148Sjfv	s32 ret_val = E1000_SUCCESS;
168238148Sjfv	s32 timeout = hw->nvm.word_size + 1;
169238148Sjfv	s32 i = 0;
170238148Sjfv
171238148Sjfv	DEBUGFUNC("e1000_get_hw_semaphore_i210");
172238148Sjfv
173238148Sjfv	/* Get the FW semaphore. */
174238148Sjfv	for (i = 0; i < timeout; i++) {
175238148Sjfv		swsm = E1000_READ_REG(hw, E1000_SWSM);
176238148Sjfv		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
177238148Sjfv
178238148Sjfv		/* Semaphore acquired if bit latched */
179238148Sjfv		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
180238148Sjfv			break;
181238148Sjfv
182238148Sjfv		usec_delay(50);
183238148Sjfv	}
184238148Sjfv
185238148Sjfv	if (i == timeout) {
186238148Sjfv		/* Release semaphores */
187238148Sjfv		e1000_put_hw_semaphore_generic(hw);
188238148Sjfv		DEBUGOUT("Driver can't access the NVM\n");
189238148Sjfv		ret_val = -E1000_ERR_NVM;
190238148Sjfv		goto out;
191238148Sjfv	}
192238148Sjfv
193238148Sjfvout:
194238148Sjfv	return ret_val;
195238148Sjfv}
196238148Sjfv
197238148Sjfv/**
198238148Sjfv *  e1000_put_hw_semaphore_i210 - Release hardware semaphore
199238148Sjfv *  @hw: pointer to the HW structure
200238148Sjfv *
201238148Sjfv *  Release hardware semaphore used to access the PHY or NVM
202238148Sjfv **/
203238148Sjfvstatic void e1000_put_hw_semaphore_i210(struct e1000_hw *hw)
204238148Sjfv{
205238148Sjfv	u32 swsm;
206238148Sjfv
207238148Sjfv	DEBUGFUNC("e1000_put_hw_semaphore_i210");
208238148Sjfv
209238148Sjfv	swsm = E1000_READ_REG(hw, E1000_SWSM);
210238148Sjfv
211238148Sjfv	swsm &= ~E1000_SWSM_SWESMBI;
212238148Sjfv
213238148Sjfv	E1000_WRITE_REG(hw, E1000_SWSM, swsm);
214238148Sjfv}
215238148Sjfv
216238148Sjfv/**
217238148Sjfv *  e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
218238148Sjfv *  @hw: pointer to the HW structure
219238148Sjfv *  @offset: offset of word in the Shadow Ram to read
220238148Sjfv *  @words: number of words to read
221238148Sjfv *  @data: word read from the Shadow Ram
222238148Sjfv *
223238148Sjfv *  Reads a 16 bit word from the Shadow Ram using the EERD register.
224238148Sjfv *  Uses necessary synchronization semaphores.
225238148Sjfv **/
226238148Sjfvs32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
227238148Sjfv			     u16 *data)
228238148Sjfv{
229238148Sjfv	s32 status = E1000_SUCCESS;
230238148Sjfv	u16 i, count;
231238148Sjfv
232238148Sjfv	DEBUGFUNC("e1000_read_nvm_srrd_i210");
233238148Sjfv
234238148Sjfv	/* We cannot hold synchronization semaphores for too long,
235238148Sjfv	 * because of forceful takeover procedure. However it is more efficient
236238148Sjfv	 * to read in bursts than synchronizing access for each word. */
237238148Sjfv	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
238238148Sjfv		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
239238148Sjfv			E1000_EERD_EEWR_MAX_COUNT : (words - i);
240238148Sjfv		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
241238148Sjfv			status = e1000_read_nvm_eerd(hw, offset, count,
242238148Sjfv						     data + i);
243238148Sjfv			hw->nvm.ops.release(hw);
244238148Sjfv		} else {
245238148Sjfv			status = E1000_ERR_SWFW_SYNC;
246238148Sjfv		}
247238148Sjfv
248238148Sjfv		if (status != E1000_SUCCESS)
249238148Sjfv			break;
250238148Sjfv	}
251238148Sjfv
252238148Sjfv	return status;
253238148Sjfv}
254238148Sjfv
255238148Sjfv/**
256238148Sjfv *  e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
257238148Sjfv *  @hw: pointer to the HW structure
258238148Sjfv *  @offset: offset within the Shadow RAM to be written to
259238148Sjfv *  @words: number of words to write
260238148Sjfv *  @data: 16 bit word(s) to be written to the Shadow RAM
261238148Sjfv *
262238148Sjfv *  Writes data to Shadow RAM at offset using EEWR register.
263238148Sjfv *
264238148Sjfv *  If e1000_update_nvm_checksum is not called after this function , the
265238148Sjfv *  data will not be committed to FLASH and also Shadow RAM will most likely
266238148Sjfv *  contain an invalid checksum.
267238148Sjfv *
268238148Sjfv *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
269238148Sjfv *  partially written.
270238148Sjfv **/
271238148Sjfvs32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
272238148Sjfv			      u16 *data)
273238148Sjfv{
274238148Sjfv	s32 status = E1000_SUCCESS;
275238148Sjfv	u16 i, count;
276238148Sjfv
277238148Sjfv	DEBUGFUNC("e1000_write_nvm_srwr_i210");
278238148Sjfv
279238148Sjfv	/* We cannot hold synchronization semaphores for too long,
280238148Sjfv	 * because of forceful takeover procedure. However it is more efficient
281238148Sjfv	 * to write in bursts than synchronizing access for each word. */
282238148Sjfv	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
283238148Sjfv		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
284238148Sjfv			E1000_EERD_EEWR_MAX_COUNT : (words - i);
285238148Sjfv		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
286238148Sjfv			status = e1000_write_nvm_srwr(hw, offset, count,
287238148Sjfv						      data + i);
288238148Sjfv			hw->nvm.ops.release(hw);
289238148Sjfv		} else {
290238148Sjfv			status = E1000_ERR_SWFW_SYNC;
291238148Sjfv		}
292238148Sjfv
293238148Sjfv		if (status != E1000_SUCCESS)
294238148Sjfv			break;
295238148Sjfv	}
296238148Sjfv
297238148Sjfv	return status;
298238148Sjfv}
299238148Sjfv
300238148Sjfv/**
301238148Sjfv *  e1000_write_nvm_srwr - Write to Shadow Ram using EEWR
302238148Sjfv *  @hw: pointer to the HW structure
303238148Sjfv *  @offset: offset within the Shadow Ram to be written to
304238148Sjfv *  @words: number of words to write
305238148Sjfv *  @data: 16 bit word(s) to be written to the Shadow Ram
306238148Sjfv *
307238148Sjfv *  Writes data to Shadow Ram at offset using EEWR register.
308238148Sjfv *
309238148Sjfv *  If e1000_update_nvm_checksum is not called after this function , the
310238148Sjfv *  Shadow Ram will most likely contain an invalid checksum.
311238148Sjfv **/
312238148Sjfvstatic s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
313238148Sjfv				u16 *data)
314238148Sjfv{
315238148Sjfv	struct e1000_nvm_info *nvm = &hw->nvm;
316238148Sjfv	u32 i, k, eewr = 0;
317238148Sjfv	u32 attempts = 100000;
318238148Sjfv	s32 ret_val = E1000_SUCCESS;
319238148Sjfv
320238148Sjfv	DEBUGFUNC("e1000_write_nvm_srwr");
321238148Sjfv
322238148Sjfv	/*
323238148Sjfv	 * A check for invalid values:  offset too large, too many words,
324238148Sjfv	 * too many words for the offset, and not enough words.
325238148Sjfv	 */
326238148Sjfv	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
327238148Sjfv	    (words == 0)) {
328238148Sjfv		DEBUGOUT("nvm parameter(s) out of bounds\n");
329238148Sjfv		ret_val = -E1000_ERR_NVM;
330238148Sjfv		goto out;
331238148Sjfv	}
332238148Sjfv
333238148Sjfv	for (i = 0; i < words; i++) {
334238148Sjfv		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
335238148Sjfv			(data[i] << E1000_NVM_RW_REG_DATA) |
336238148Sjfv			E1000_NVM_RW_REG_START;
337238148Sjfv
338238148Sjfv		E1000_WRITE_REG(hw, E1000_SRWR, eewr);
339238148Sjfv
340238148Sjfv		for (k = 0; k < attempts; k++) {
341238148Sjfv			if (E1000_NVM_RW_REG_DONE &
342238148Sjfv			    E1000_READ_REG(hw, E1000_SRWR)) {
343238148Sjfv				ret_val = E1000_SUCCESS;
344238148Sjfv				break;
345238148Sjfv			}
346238148Sjfv			usec_delay(5);
347238148Sjfv		}
348238148Sjfv
349238148Sjfv		if (ret_val != E1000_SUCCESS) {
350238148Sjfv			DEBUGOUT("Shadow RAM write EEWR timed out\n");
351238148Sjfv			break;
352238148Sjfv		}
353238148Sjfv	}
354238148Sjfv
355238148Sjfvout:
356238148Sjfv	return ret_val;
357238148Sjfv}
358238148Sjfv
359238148Sjfv/**
360238148Sjfv *  e1000_read_nvm_i211 - Read NVM wrapper function for I211
361238148Sjfv *  @hw: pointer to the HW structure
362238148Sjfv *  @address: the word address (aka eeprom offset) to read
363238148Sjfv *  @data: pointer to the data read
364238148Sjfv *
365238148Sjfv *  Wrapper function to return data formerly found in the NVM.
366238148Sjfv **/
367238148Sjfvstatic s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
368238148Sjfv			       u16 *data)
369238148Sjfv{
370238148Sjfv	s32 ret_val = E1000_SUCCESS;
371238148Sjfv
372238148Sjfv	DEBUGFUNC("e1000_read_nvm_i211");
373238148Sjfv
374238148Sjfv	/* Only the MAC addr is required to be present in the iNVM */
375238148Sjfv	switch (offset) {
376238148Sjfv	case NVM_MAC_ADDR:
377238148Sjfv		ret_val = e1000_read_invm_i211(hw, (u8)offset, &data[0]);
378238148Sjfv		ret_val |= e1000_read_invm_i211(hw, (u8)offset+1, &data[1]);
379238148Sjfv		ret_val |= e1000_read_invm_i211(hw, (u8)offset+2, &data[2]);
380238148Sjfv		if (ret_val != E1000_SUCCESS)
381238148Sjfv			DEBUGOUT("MAC Addr not found in iNVM\n");
382238148Sjfv		break;
383238148Sjfv	case NVM_ID_LED_SETTINGS:
384238148Sjfv	case NVM_INIT_CTRL_2:
385238148Sjfv	case NVM_INIT_CTRL_4:
386238148Sjfv	case NVM_LED_1_CFG:
387238148Sjfv	case NVM_LED_0_2_CFG:
388238148Sjfv		e1000_read_invm_i211(hw, (u8)offset, data);
389238148Sjfv		break;
390238148Sjfv	case NVM_COMPAT:
391238148Sjfv		*data = ID_LED_DEFAULT_I210;
392238148Sjfv		break;
393238148Sjfv	case NVM_SUB_DEV_ID:
394238148Sjfv		*data = hw->subsystem_device_id;
395238148Sjfv		break;
396238148Sjfv	case NVM_SUB_VEN_ID:
397238148Sjfv		*data = hw->subsystem_vendor_id;
398238148Sjfv		break;
399238148Sjfv	case NVM_DEV_ID:
400238148Sjfv		*data = hw->device_id;
401238148Sjfv		break;
402238148Sjfv	case NVM_VEN_ID:
403238148Sjfv		*data = hw->vendor_id;
404238148Sjfv		break;
405238148Sjfv	default:
406238148Sjfv		DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
407238148Sjfv		*data = NVM_RESERVED_WORD;
408238148Sjfv		break;
409238148Sjfv	}
410238148Sjfv	return ret_val;
411238148Sjfv}
412238148Sjfv
413238148Sjfv/**
414238148Sjfv *  e1000_read_invm_i211 - Reads OTP
415238148Sjfv *  @hw: pointer to the HW structure
416238148Sjfv *  @address: the word address (aka eeprom offset) to read
417238148Sjfv *  @data: pointer to the data read
418238148Sjfv *
419238148Sjfv *  Reads 16-bit words from the OTP. Return error when the word is not
420238148Sjfv *  stored in OTP.
421238148Sjfv **/
422238148Sjfvs32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data)
423238148Sjfv{
424238148Sjfv	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
425238148Sjfv	u32 invm_dword;
426238148Sjfv	u16 i;
427238148Sjfv	u8 record_type, word_address;
428238148Sjfv
429238148Sjfv	DEBUGFUNC("e1000_read_invm_i211");
430238148Sjfv
431238148Sjfv	for (i = 0; i < E1000_INVM_SIZE; i++) {
432238148Sjfv		invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
433238148Sjfv		/* Get record type */
434238148Sjfv		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
435238148Sjfv		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
436238148Sjfv			break;
437238148Sjfv		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
438238148Sjfv			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
439238148Sjfv		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
440238148Sjfv			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
441238148Sjfv		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
442238148Sjfv			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
443238148Sjfv			if (word_address == address) {
444238148Sjfv				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
445238148Sjfv				DEBUGOUT2("Read INVM Word 0x%02x = %x",
446238148Sjfv					  address, *data);
447238148Sjfv				status = E1000_SUCCESS;
448238148Sjfv				break;
449238148Sjfv			}
450238148Sjfv		}
451238148Sjfv	}
452238148Sjfv	if (status != E1000_SUCCESS)
453238148Sjfv		DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address);
454238148Sjfv	return status;
455238148Sjfv}
456238148Sjfv
457238148Sjfv/**
458238148Sjfv *  e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum
459238148Sjfv *  @hw: pointer to the HW structure
460238148Sjfv *
461238148Sjfv *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
462238148Sjfv *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
463238148Sjfv **/
464238148Sjfvs32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw)
465238148Sjfv{
466238148Sjfv	s32 status = E1000_SUCCESS;
467238148Sjfv	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
468238148Sjfv
469238148Sjfv	DEBUGFUNC("e1000_validate_nvm_checksum_i210");
470238148Sjfv
471238148Sjfv	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
472238148Sjfv
473238148Sjfv		/*
474238148Sjfv		 * Replace the read function with semaphore grabbing with
475238148Sjfv		 * the one that skips this for a while.
476238148Sjfv		 * We have semaphore taken already here.
477238148Sjfv		 */
478238148Sjfv		read_op_ptr = hw->nvm.ops.read;
479238148Sjfv		hw->nvm.ops.read = e1000_read_nvm_eerd;
480238148Sjfv
481238148Sjfv		status = e1000_validate_nvm_checksum_generic(hw);
482238148Sjfv
483238148Sjfv		/* Revert original read operation. */
484238148Sjfv		hw->nvm.ops.read = read_op_ptr;
485238148Sjfv
486238148Sjfv		hw->nvm.ops.release(hw);
487238148Sjfv	} else {
488238148Sjfv		status = E1000_ERR_SWFW_SYNC;
489238148Sjfv	}
490238148Sjfv
491238148Sjfv	return status;
492238148Sjfv}
493238148Sjfv
494238148Sjfv
495238148Sjfv/**
496238148Sjfv *  e1000_update_nvm_checksum_i210 - Update EEPROM checksum
497238148Sjfv *  @hw: pointer to the HW structure
498238148Sjfv *
499238148Sjfv *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
500238148Sjfv *  up to the checksum.  Then calculates the EEPROM checksum and writes the
501238148Sjfv *  value to the EEPROM. Next commit EEPROM data onto the Flash.
502238148Sjfv **/
503238148Sjfvs32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw)
504238148Sjfv{
505238148Sjfv	s32 ret_val = E1000_SUCCESS;
506238148Sjfv	u16 checksum = 0;
507238148Sjfv	u16 i, nvm_data;
508238148Sjfv
509238148Sjfv	DEBUGFUNC("e1000_update_nvm_checksum_i210");
510238148Sjfv
511238148Sjfv	/*
512238148Sjfv	 * Read the first word from the EEPROM. If this times out or fails, do
513238148Sjfv	 * not continue or we could be in for a very long wait while every
514238148Sjfv	 * EEPROM read fails
515238148Sjfv	 */
516238148Sjfv	ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);
517238148Sjfv	if (ret_val != E1000_SUCCESS) {
518238148Sjfv		DEBUGOUT("EEPROM read failed\n");
519238148Sjfv		goto out;
520238148Sjfv	}
521238148Sjfv
522238148Sjfv	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
523238148Sjfv		/*
524238148Sjfv		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
525238148Sjfv		 * because we do not want to take the synchronization
526238148Sjfv		 * semaphores twice here.
527238148Sjfv		 */
528238148Sjfv
529238148Sjfv		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
530238148Sjfv			ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);
531238148Sjfv			if (ret_val) {
532238148Sjfv				hw->nvm.ops.release(hw);
533238148Sjfv				DEBUGOUT("NVM Read Error while updating checksum.\n");
534238148Sjfv				goto out;
535238148Sjfv			}
536238148Sjfv			checksum += nvm_data;
537238148Sjfv		}
538238148Sjfv		checksum = (u16) NVM_SUM - checksum;
539238148Sjfv		ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
540238148Sjfv						&checksum);
541238148Sjfv		if (ret_val != E1000_SUCCESS) {
542238148Sjfv			hw->nvm.ops.release(hw);
543238148Sjfv			DEBUGOUT("NVM Write Error while updating checksum.\n");
544238148Sjfv			goto out;
545238148Sjfv		}
546238148Sjfv
547238148Sjfv		hw->nvm.ops.release(hw);
548238148Sjfv
549238148Sjfv		ret_val = e1000_update_flash_i210(hw);
550238148Sjfv	} else {
551238148Sjfv		ret_val = E1000_ERR_SWFW_SYNC;
552238148Sjfv	}
553238148Sjfvout:
554238148Sjfv	return ret_val;
555238148Sjfv}
556238148Sjfv
557238148Sjfv/**
558238148Sjfv *  e1000_get_flash_presence_i210 - Check if flash device is detected.
559238148Sjfv *  @hw: pointer to the HW structure
560238148Sjfv *
561238148Sjfv **/
562238148Sjfvstatic bool e1000_get_flash_presence_i210(struct e1000_hw *hw)
563238148Sjfv{
564238148Sjfv	u32 eec = 0;
565238148Sjfv	bool ret_val = FALSE;
566238148Sjfv
567238148Sjfv	DEBUGFUNC("e1000_get_flash_presence_i210");
568238148Sjfv
569238148Sjfv	eec = E1000_READ_REG(hw, E1000_EECD);
570238148Sjfv
571238148Sjfv	if (eec & E1000_EECD_FLASH_DETECTED_I210)
572238148Sjfv		ret_val = TRUE;
573238148Sjfv
574238148Sjfv	return ret_val;
575238148Sjfv}
576238148Sjfv
577238148Sjfv/**
578238148Sjfv *  e1000_update_flash_i210 - Commit EEPROM to the flash
579238148Sjfv *  @hw: pointer to the HW structure
580238148Sjfv *
581238148Sjfv **/
582238148Sjfvs32 e1000_update_flash_i210(struct e1000_hw *hw)
583238148Sjfv{
584238148Sjfv	s32 ret_val = E1000_SUCCESS;
585238148Sjfv	u32 flup;
586238148Sjfv
587238148Sjfv	DEBUGFUNC("e1000_update_flash_i210");
588238148Sjfv
589238148Sjfv	ret_val = e1000_pool_flash_update_done_i210(hw);
590238148Sjfv	if (ret_val == -E1000_ERR_NVM) {
591238148Sjfv		DEBUGOUT("Flash update time out\n");
592238148Sjfv		goto out;
593238148Sjfv	}
594238148Sjfv
595238148Sjfv	flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210;
596238148Sjfv	E1000_WRITE_REG(hw, E1000_EECD, flup);
597238148Sjfv
598238148Sjfv	ret_val = e1000_pool_flash_update_done_i210(hw);
599238148Sjfv	if (ret_val == E1000_SUCCESS)
600238148Sjfv		DEBUGOUT("Flash update complete\n");
601238148Sjfv	else
602238148Sjfv		DEBUGOUT("Flash update time out\n");
603238148Sjfv
604238148Sjfvout:
605238148Sjfv	return ret_val;
606238148Sjfv}
607238148Sjfv
608238148Sjfv/**
609238148Sjfv *  e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
610238148Sjfv *  @hw: pointer to the HW structure
611238148Sjfv *
612238148Sjfv **/
613238148Sjfvs32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
614238148Sjfv{
615238148Sjfv	s32 ret_val = -E1000_ERR_NVM;
616238148Sjfv	u32 i, reg;
617238148Sjfv
618238148Sjfv	DEBUGFUNC("e1000_pool_flash_update_done_i210");
619238148Sjfv
620238148Sjfv	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
621238148Sjfv		reg = E1000_READ_REG(hw, E1000_EECD);
622238148Sjfv		if (reg & E1000_EECD_FLUDONE_I210) {
623238148Sjfv			ret_val = E1000_SUCCESS;
624238148Sjfv			break;
625238148Sjfv		}
626238148Sjfv		usec_delay(5);
627238148Sjfv	}
628238148Sjfv
629238148Sjfv	return ret_val;
630238148Sjfv}
631238148Sjfv
632238148Sjfv/**
633238148Sjfv *  e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers
634238148Sjfv *  @hw: pointer to the HW structure
635238148Sjfv *
636238148Sjfv *  Initialize the i210 NVM parameters and function pointers.
637238148Sjfv **/
638238148Sjfvstatic s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
639238148Sjfv{
640238148Sjfv	s32 ret_val = E1000_SUCCESS;
641238148Sjfv	struct e1000_nvm_info *nvm = &hw->nvm;
642238148Sjfv
643238148Sjfv	DEBUGFUNC("e1000_init_nvm_params_i210");
644238148Sjfv
645238148Sjfv	ret_val = e1000_init_nvm_params_82575(hw);
646238148Sjfv
647238148Sjfv	nvm->ops.acquire = e1000_acquire_nvm_i210;
648238148Sjfv	nvm->ops.release = e1000_release_nvm_i210;
649238148Sjfv	nvm->ops.read    = e1000_read_nvm_srrd_i210;
650238148Sjfv	nvm->ops.write   = e1000_write_nvm_srwr_i210;
651238148Sjfv	nvm->ops.valid_led_default = e1000_valid_led_default_i210;
652238148Sjfv	nvm->ops.validate = e1000_validate_nvm_checksum_i210;
653238148Sjfv	nvm->ops.update   = e1000_update_nvm_checksum_i210;
654238148Sjfv
655238148Sjfv	return ret_val;
656238148Sjfv}
657238148Sjfv
658238148Sjfv/**
659238148Sjfv *  e1000_init_nvm_params_i211 - Initialize i211 NVM function pointers
660238148Sjfv *  @hw: pointer to the HW structure
661238148Sjfv *
662238148Sjfv *  Initialize the NVM parameters and function pointers for i211.
663238148Sjfv **/
664238148Sjfvstatic s32 e1000_init_nvm_params_i211(struct e1000_hw *hw)
665238148Sjfv{
666238148Sjfv	struct e1000_nvm_info *nvm = &hw->nvm;
667238148Sjfv
668238148Sjfv	DEBUGFUNC("e1000_init_nvm_params_i211");
669238148Sjfv
670238148Sjfv	nvm->ops.acquire  = e1000_acquire_nvm_i210;
671238148Sjfv	nvm->ops.release  = e1000_release_nvm_i210;
672238148Sjfv	nvm->ops.read     = e1000_read_nvm_i211;
673238148Sjfv	nvm->ops.valid_led_default = e1000_valid_led_default_i210;
674238148Sjfv	nvm->ops.write    = e1000_null_write_nvm;
675238148Sjfv	nvm->ops.validate = e1000_null_ops_generic;
676238148Sjfv	nvm->ops.update   = e1000_null_ops_generic;
677238148Sjfv
678238148Sjfv	return E1000_SUCCESS;
679238148Sjfv}
680238148Sjfv
681238148Sjfv/**
682238148Sjfv *  e1000_init_function_pointers_i210 - Init func ptrs.
683238148Sjfv *  @hw: pointer to the HW structure
684238148Sjfv *
685238148Sjfv *  Called to initialize all function pointers and parameters.
686238148Sjfv **/
687238148Sjfvvoid e1000_init_function_pointers_i210(struct e1000_hw *hw)
688238148Sjfv{
689238148Sjfv	e1000_init_function_pointers_82575(hw);
690238148Sjfv
691238148Sjfv	switch (hw->mac.type) {
692238148Sjfv	case e1000_i210:
693238148Sjfv		if (e1000_get_flash_presence_i210(hw))
694238148Sjfv			hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
695238148Sjfv		else
696238148Sjfv			hw->nvm.ops.init_params = e1000_init_nvm_params_i211;
697238148Sjfv		break;
698238148Sjfv	case e1000_i211:
699238148Sjfv		hw->nvm.ops.init_params = e1000_init_nvm_params_i211;
700238148Sjfv		break;
701238148Sjfv	default:
702238148Sjfv		break;
703238148Sjfv	}
704238148Sjfv	return;
705238148Sjfv}
706238148Sjfv
707238148Sjfv/**
708238148Sjfv *  e1000_valid_led_default_i210 - Verify a valid default LED config
709238148Sjfv *  @hw: pointer to the HW structure
710238148Sjfv *  @data: pointer to the NVM (EEPROM)
711238148Sjfv *
712238148Sjfv *  Read the EEPROM for the current default LED configuration.  If the
713238148Sjfv *  LED configuration is not valid, set to a valid LED configuration.
714238148Sjfv **/
715238148Sjfvstatic s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
716238148Sjfv{
717238148Sjfv	s32 ret_val;
718238148Sjfv
719238148Sjfv	DEBUGFUNC("e1000_valid_led_default_i210");
720238148Sjfv
721238148Sjfv	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
722238148Sjfv	if (ret_val) {
723238148Sjfv		DEBUGOUT("NVM Read Error\n");
724238148Sjfv		goto out;
725238148Sjfv	}
726238148Sjfv
727238148Sjfv	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
728238148Sjfv		switch (hw->phy.media_type) {
729238148Sjfv		case e1000_media_type_internal_serdes:
730238148Sjfv			*data = ID_LED_DEFAULT_I210_SERDES;
731238148Sjfv			break;
732238148Sjfv		case e1000_media_type_copper:
733238148Sjfv		default:
734238148Sjfv			*data = ID_LED_DEFAULT_I210;
735238148Sjfv			break;
736238148Sjfv		}
737238148Sjfv	}
738238148Sjfvout:
739238148Sjfv	return ret_val;
740238148Sjfv}
741