e1000_i210.c revision 7916a53d203f12461095886cf72d58e9281240d9
1f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/*******************************************************************************
2f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
3f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  Intel(R) Gigabit Ethernet Linux driver
4f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  Copyright(c) 2007-2012 Intel Corporation.
5f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
6f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  This program is free software; you can redistribute it and/or modify it
7f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  under the terms and conditions of the GNU General Public License,
8f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  version 2, as published by the Free Software Foundation.
9f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
10f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  This program is distributed in the hope it will be useful, but WITHOUT
11f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  more details.
14f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
15f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  You should have received a copy of the GNU General Public License along with
16f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  this program; if not, write to the Free Software Foundation, Inc.,
17f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
19f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  The full GNU General Public License is included in this distribution in
20f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  the file called "COPYING".
21f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
22f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  Contact Information:
23f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
24f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
25f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
26f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny******************************************************************************/
27f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
28f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/* e1000_i210
29f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * e1000_i211
30f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */
31f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
32f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/types.h>
33f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/if_ether.h>
34f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
35f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_hw.h"
36f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_i210.h"
37f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
397916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
427916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  Acquire the HW semaphore to access the PHY or NVM
437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */
447916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u32 swsm;
477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 timeout = hw->nvm.word_size + 1;
497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 i = 0;
507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
517916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	/* Get the FW semaphore. */
527916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < timeout; i++) {
537916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		swsm = rd32(E1000_SWSM);
547916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
557916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
567916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		/* Semaphore acquired if bit latched */
577916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
587916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
597916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
607916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		udelay(50);
617916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
627916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
637916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	if (i == timeout) {
647916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		/* Release semaphores */
657916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		igb_put_hw_semaphore(hw);
667916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		hw_dbg("Driver can't access the NVM\n");
677916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		ret_val = -E1000_ERR_NVM;
687916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		goto out;
697916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
707916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
717916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornyout:
727916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return ret_val;
737916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
74f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
75f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
76f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_acquire_nvm_i210 - Request for access to EEPROM
77f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
78f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
79f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the necessary semaphores for exclusive access to the EEPROM.
80f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
81f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Return successful if access grant bit set, else clear the request for
82f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  EEPROM access and return -E1000_ERR_NVM (-1).
83f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
84f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_nvm_i210(struct e1000_hw *hw)
85f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
86f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
87f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
88f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
89f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
90f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_nvm_i210 - Release exclusive access to EEPROM
91f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
92f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
93f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
94f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  then release the semaphores acquired.
95f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
96f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_nvm_i210(struct e1000_hw *hw)
97f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
98f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
99f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
100f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
101f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
1027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_put_hw_semaphore_i210 - Release hardware semaphore
1037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
1047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
1057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  Release hardware semaphore used to access the PHY or NVM
1067916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */
1077916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
1087916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
1097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u32 swsm;
1107916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
1117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	swsm = rd32(E1000_SWSM);
1127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
1137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	swsm &= ~E1000_SWSM_SWESMBI;
1147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
1157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	wr32(E1000_SWSM, swsm);
1167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
1177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
1187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
119f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
120f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
121f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
122f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
123f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
124f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're acquiring the lock for.
125f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
126f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
127f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
128f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
129f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swmask = mask;
130f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 fwmask = mask << 16;
131f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
132f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
133f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
134f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	while (i < timeout) {
135f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (igb_get_hw_semaphore_i210(hw)) {
136f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = -E1000_ERR_SWFW_SYNC;
137f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
138f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
139f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
140f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		swfw_sync = rd32(E1000_SW_FW_SYNC);
141f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (!(swfw_sync & fwmask))
142f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
143f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
144f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/*
145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * Firmware currently using resource (fwmask)
146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_put_hw_semaphore_i210(hw);
148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		mdelay(5);
149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		i++;
150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
152f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (i == timeout) {
153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
155f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
156f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync |= swmask;
159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_put_hw_semaphore_i210(hw);
162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_swfw_sync_i210 - Release SW/FW semaphore
168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
170f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're releasing the lock for.
173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		; /* Empty */
180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync = rd32(E1000_SW_FW_SYNC);
182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync &= ~mask;
183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_put_hw_semaphore_i210(hw);
186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
187f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset of word in the Shadow Ram to read
192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to read
193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: word read from the Shadow Ram
194f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads a 16 bit word from the Shadow Ram using the EERD register.
196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Uses necessary synchronization semaphores.
197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			     u16 *data)
200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, count;
203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
204f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
205f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * to read in bursts than synchronizing access for each word. */
207f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
208f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
210f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = igb_read_nvm_eerd(hw, offset, count,
212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						     data + i);
213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		} else {
215f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
216f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (status != E1000_SUCCESS)
219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
220f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_write_nvm_srwr - Write to Shadow Ram using EEWR
227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
228f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset within the Shadow Ram to be written to
229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to write
230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow Ram
231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Writes data to Shadow Ram at offset using EEWR register.
233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  If igb_update_nvm_checksum is not called after this function , the
235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Shadow Ram will most likely contain an invalid checksum.
236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				u16 *data)
239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	struct e1000_nvm_info *nvm = &hw->nvm;
241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 i, k, eewr = 0;
242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 attempts = 100000;
243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
244f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/*
246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * A check for invalid values:  offset too large, too many words,
247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * too many words for the offset, and not enough words.
248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	    (words == 0)) {
251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("nvm parameter(s) out of bounds\n");
252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_NVM;
253f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
255f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i++) {
257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			(data[i] << E1000_NVM_RW_REG_DATA) |
259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_NVM_RW_REG_START;
260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		wr32(E1000_SRWR, eewr);
262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (k = 0; k < attempts; k++) {
264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (E1000_NVM_RW_REG_DONE &
265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			    rd32(E1000_SRWR)) {
266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				ret_val = E1000_SUCCESS;
267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			udelay(5);
270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS) {
273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("Shadow RAM write EEWR timed out\n");
274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
275f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
281f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
282f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
2837916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
2847916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
2857916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @offset: offset within the Shadow RAM to be written to
2867916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @words: number of words to write
2877916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow RAM
2887916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2897916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  Writes data to Shadow RAM at offset using EEWR register.
2907916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2917916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  If e1000_update_nvm_checksum is not called after this function , the
2927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  data will not be committed to FLASH and also Shadow RAM will most likely
2937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  contain an invalid checksum.
2947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2957916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
2967916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  partially written.
2977916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */
2987916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornys32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
2997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			      u16 *data)
3007916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
3017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 status = E1000_SUCCESS;
3027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u16 i, count;
3037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
3057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
3067916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 * to write in bursts than synchronizing access for each word.
3077916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 */
3087916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
3097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
3107916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
3117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
3127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			status = igb_write_nvm_srwr(hw, offset, count,
3137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny						      data + i);
3147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			hw->nvm.ops.release(hw);
3157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		} else {
3167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
3177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		}
3187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3197916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (status != E1000_SUCCESS)
3207916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
3217916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
3227916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3237916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return status;
3247916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
3257916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3267916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
327f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_i211 - Read NVM wrapper function for I211
328f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
329f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @address: the word address (aka eeprom offset) to read
330f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
331f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
332f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Wrapper function to return data formerly found in the NVM.
333f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
334f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
335f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			       u16 *data)
336f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
337f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
338f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
339f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* Only the MAC addr is required to be present in the iNVM */
340f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	switch (offset) {
341f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_MAC_ADDR:
342f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_read_invm_i211(hw, offset, &data[0]);
343f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]);
344f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]);
345f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS)
346f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("MAC Addr not found in iNVM\n");
347f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
348f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_2:
3491720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3501720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3511720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
3521720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3531720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
3541720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
355f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_4:
3561720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3571720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3581720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
3591720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3601720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
3611720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
362f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_1_CFG:
3631720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3641720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3651720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_LED_1_CFG_DEFAULT_I211;
3661720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3671720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
3681720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
369f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_0_2_CFG:
370f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_read_invm_i211(hw, offset, data);
3711720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3721720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
3731720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3741720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
375f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
3761720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny	case NVM_ID_LED_SETTINGS:
3771720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3781720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3791720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = ID_LED_RESERVED_FFFF;
3801720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3811720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_DEV_ID:
383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_device_id;
384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
385f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_VEN_ID:
386f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_vendor_id;
387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
388f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_DEV_ID:
389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->device_id;
390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_VEN_ID:
392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->vendor_id;
393f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
394f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	default:
395f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
396f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = NVM_RESERVED_WORD;
397f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
398f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
402f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
403f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_invm_i211 - Reads OTP
404f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
405f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @address: the word address (aka eeprom offset) to read
406f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
407f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads 16-bit words from the OTP. Return error when the word is not
409f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  stored in OTP.
410f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
411f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
412f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
413f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
414f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 invm_dword;
415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i;
416f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u8 record_type, word_address;
417f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
418f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
419f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
420f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Get record type */
421f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
423f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
424f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
425f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
426f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
427f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
428f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
429f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
430f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (word_address == (u8)address) {
431f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
432f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("Read INVM Word 0x%02x = %x",
433f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny					  address, *data);
434f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				status = E1000_SUCCESS;
435f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
436f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
437f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
438f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
439f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (status != E1000_SUCCESS)
440f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Requested word 0x%02x not found in OTP\n", address);
441f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
442f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
443f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
444f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
44509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  igb_read_invm_version - Reads iNVM version and image type
44609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @hw: pointer to the HW structure
44709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @invm_ver: version structure for the version read
44809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *
44909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  Reads iNVM version and image type.
45009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/
45109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw,
45209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			  struct e1000_fw_version *invm_ver) {
45309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *record = NULL;
45409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *next_record = NULL;
45509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 i = 0;
45609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_dword = 0;
45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					     E1000_INVM_RECORD_SIZE_IN_BYTES);
45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 buffer[E1000_INVM_SIZE];
46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u16 version = 0;
46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read iNVM memory */
46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		buffer[i] = invm_dword;
46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read version number */
47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have first version location used */
47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = 0;
47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have second version location used */
48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((i == 1) &&
48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have odd version location
48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
48909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 (i != 1))) {
49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*next_record & E1000_INVM_VER_FIELD_TWO)
49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				  >> 13;
49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
49609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have even version location
49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) {
50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
50709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	if (status == E1000_SUCCESS) {
51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					>> E1000_INVM_MAJOR_SHIFT;
51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read Image Type */
51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
51609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
52009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
52109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type = 0;
52209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
52309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
52409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
52509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
52609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & 0x3) == 0) &&
52709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
52809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((((*record & 0x3) != 0) && (i != 1)))) {
52909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type =
53009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
53109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
53209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
53309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
53409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
53509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	return status;
53609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny}
53709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
53809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/**
539f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
540f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
541f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
542f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
543f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
544f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
545f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
546f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
547f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
548f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
549f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
550f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/*
553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * Replace the read function with semaphore grabbing with
554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * the one that skips this for a while.
555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * We have semaphore taken already here.
556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
557f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		read_op_ptr = hw->nvm.ops.read;
558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = igb_read_nvm_eerd;
559f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = igb_validate_nvm_checksum(hw);
561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
562f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Revert original read operation. */
563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = read_op_ptr;
564f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = E1000_ERR_SWFW_SYNC;
568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_nvm_checksum_i210 - Update EEPROM checksum
576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  up to the checksum.  Then calculates the EEPROM checksum and writes the
580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  value to the EEPROM. Next commit EEPROM data onto the Flash.
581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
584f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 checksum = 0;
586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, nvm_data;
587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/*
589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * Read the first word from the EEPROM. If this times out or fails, do
590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * not continue or we could be in for a very long wait while every
591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * EEPROM read fails
592f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
594f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val != E1000_SUCCESS) {
595f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("EEPROM read failed\n");
596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
598f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/*
601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * because we do not want to take the synchronization
603f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * semaphores twice here.
604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
608f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (ret_val) {
609f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw->nvm.ops.release(hw);
610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("NVM Read Error while updating checksum.\n");
611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				goto out;
612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			checksum += nvm_data;
614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		checksum = (u16) NVM_SUM - checksum;
616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						&checksum);
618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS) {
619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("NVM Write Error while updating checksum.\n");
621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
626f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_update_flash_i210(hw);
627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
629f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
630f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
631f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
632f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
633f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
634f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
6357916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_pool_flash_update_done_i210 - Pool FLUDONE status.
6367916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
6377916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
6387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */
6397916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
6407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
6417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 ret_val = -E1000_ERR_NVM;
6427916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u32 i, reg;
6437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
6457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		reg = rd32(E1000_EECD);
6467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (reg & E1000_EECD_FLUDONE_I210) {
6477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			ret_val = E1000_SUCCESS;
6487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
6497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		}
6507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		udelay(5);
6517916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
6527916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6537916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return ret_val;
6547916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
6557916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6567916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
657f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_flash_i210 - Commit EEPROM to the flash
658f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
659f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
660f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
661f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_flash_i210(struct e1000_hw *hw)
662f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
663f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
664f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 flup;
665f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
666f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
667f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == -E1000_ERR_NVM) {
668f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
669f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
670f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
671f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
672f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
673f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_EECD, flup);
674f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
675f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
676f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == E1000_SUCCESS)
677f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update complete\n");
678f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	else
679f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
680f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
681f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
686f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_valid_led_default_i210 - Verify a valid default LED config
687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
688f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the NVM (EEPROM)
689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Read the EEPROM for the current default LED configuration.  If the
691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  LED configuration is not valid, set to a valid LED configuration.
692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val;
696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
698f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val) {
699f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM Read Error\n");
700f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
701f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
702f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
703f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
704f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		switch (hw->phy.media_type) {
705f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_internal_serdes:
706f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210_SERDES;
707f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
708f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_copper:
709f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		default:
710f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210;
711f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
712f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
713f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
714f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
715f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
716f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
717