e1000_i210.c revision 87371b9de5becc32af2f9be84008b8a8a424c58a
1f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/*******************************************************************************
2f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
3f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny  Intel(R) Gigabit Ethernet Linux driver
44b9ea4626b52c113c367c4776c9bb11b7231393dAkeem G. Abodunrin  Copyright(c) 2007-2013 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
106b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/
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
144b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher		/* Firmware currently using resource (fwmask) */
145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_put_hw_semaphore_i210(hw);
146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		mdelay(5);
147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		i++;
148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (i == timeout) {
151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
152f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
155f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
156f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync |= swmask;
157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_put_hw_semaphore_i210(hw);
160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_swfw_sync_i210 - Release SW/FW semaphore
166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
170f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're releasing the lock for.
171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		; /* Empty */
178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync = rd32(E1000_SW_FW_SYNC);
180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync &= ~mask;
181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_put_hw_semaphore_i210(hw);
184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
187f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset of word in the Shadow Ram to read
190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to read
191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: word read from the Shadow Ram
192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads a 16 bit word from the Shadow Ram using the EERD register.
194f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Uses necessary synchronization semaphores.
195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			     u16 *data)
198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, count;
201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
204b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	 * to read in bursts than synchronizing access for each word.
205b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	 */
206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
207f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
208f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
210f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = igb_read_nvm_eerd(hw, offset, count,
211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						     data + i);
212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		} else {
214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
215f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
216f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (status != E1000_SUCCESS)
218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
220f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_write_nvm_srwr - Write to Shadow Ram using EEWR
226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset within the Shadow Ram to be written to
228f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to write
229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow Ram
230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Writes data to Shadow Ram at offset using EEWR register.
232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  If igb_update_nvm_checksum is not called after this function , the
234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Shadow Ram will most likely contain an invalid checksum.
235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				u16 *data)
238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	struct e1000_nvm_info *nvm = &hw->nvm;
240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 i, k, eewr = 0;
241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 attempts = 100000;
242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
244b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	/* A check for invalid values:  offset too large, too many words,
245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * too many words for the offset, and not enough words.
246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	    (words == 0)) {
249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("nvm parameter(s) out of bounds\n");
250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_NVM;
251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
253f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i++) {
255f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			(data[i] << E1000_NVM_RW_REG_DATA) |
257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_NVM_RW_REG_START;
258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		wr32(E1000_SRWR, eewr);
260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (k = 0; k < attempts; k++) {
262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (E1000_NVM_RW_REG_DONE &
263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			    rd32(E1000_SRWR)) {
264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				ret_val = E1000_SUCCESS;
265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			udelay(5);
268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS) {
271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("Shadow RAM write EEWR timed out\n");
272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
275f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
2817916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
2827916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
2837916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @offset: offset within the Shadow RAM to be written to
2847916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @words: number of words to write
2857916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow RAM
2867916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2877916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  Writes data to Shadow RAM at offset using EEWR register.
2887916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2897916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  If e1000_update_nvm_checksum is not called after this function , the
2907916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  data will not be committed to FLASH and also Shadow RAM will most likely
2917916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  contain an invalid checksum.
2927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
2947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  partially written.
295b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/
2967916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornys32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
2977916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			      u16 *data)
2987916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
2997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 status = E1000_SUCCESS;
3007916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u16 i, count;
3017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
3037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
3047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 * to write in bursts than synchronizing access for each word.
3057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 */
3067916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
3077916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
3087916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
3097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
3107916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			status = igb_write_nvm_srwr(hw, offset, count,
3117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny						      data + i);
3127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			hw->nvm.ops.release(hw);
3137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		} else {
3147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
3157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		}
3167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (status != E1000_SUCCESS)
3187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
3197916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
3207916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3217916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return status;
3227916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
3237916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3247916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
325f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_i211 - Read NVM wrapper function for I211
326f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
3275c17a203721d72c36798e5d7fa564e1adf8beb65Akeem G. Abodunrin *  @words: number of words to read
328f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
329f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
330f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Wrapper function to return data formerly found in the NVM.
331f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
332f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
333f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			       u16 *data)
334f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
335f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
336f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
337f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* Only the MAC addr is required to be present in the iNVM */
338f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	switch (offset) {
339f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_MAC_ADDR:
340f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_read_invm_i211(hw, offset, &data[0]);
341f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]);
342f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]);
343f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS)
344f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("MAC Addr not found in iNVM\n");
345f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
346f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_2:
3471720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3481720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3491720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
3501720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3511720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
3521720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
353f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_4:
3541720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3551720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3561720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
3571720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3581720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
3591720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
360f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_1_CFG:
3611720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3621720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3631720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_LED_1_CFG_DEFAULT_I211;
3641720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3651720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
3661720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
367f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_0_2_CFG:
368f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_read_invm_i211(hw, offset, data);
3691720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3701720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
3711720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3721720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
373f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
3741720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny	case NVM_ID_LED_SETTINGS:
3751720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		ret_val = igb_read_invm_i211(hw, (u8)offset, data);
3761720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		if (ret_val != E1000_SUCCESS) {
3771720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = ID_LED_RESERVED_FFFF;
3781720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			ret_val = E1000_SUCCESS;
3791720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
380f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_DEV_ID:
381f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_device_id;
382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_VEN_ID:
384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_vendor_id;
385f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
386f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_DEV_ID:
387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->device_id;
388f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_VEN_ID:
390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->vendor_id;
391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	default:
393f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
394f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = NVM_RESERVED_WORD;
395f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
396f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
397f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
398f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_invm_i211 - Reads OTP
402f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
403f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @address: the word address (aka eeprom offset) to read
404f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
405f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
406f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads 16-bit words from the OTP. Return error when the word is not
407f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  stored in OTP.
408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
409f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
410f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
411f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
412f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 invm_dword;
413f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i;
414f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u8 record_type, word_address;
415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
416f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
417f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
418f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Get record type */
419f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
420f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
421f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
423f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
424f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
425f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
426f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
427f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
428f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (word_address == (u8)address) {
429f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
430f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("Read INVM Word 0x%02x = %x",
431f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny					  address, *data);
432f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				status = E1000_SUCCESS;
433f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
434f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
435f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
436f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
437f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (status != E1000_SUCCESS)
438f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Requested word 0x%02x not found in OTP\n", address);
439f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
440f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
441f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
442f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
44309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  igb_read_invm_version - Reads iNVM version and image type
44409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @hw: pointer to the HW structure
44509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @invm_ver: version structure for the version read
44609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *
44709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  Reads iNVM version and image type.
44809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/
44909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw,
45009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			  struct e1000_fw_version *invm_ver) {
45109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *record = NULL;
45209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *next_record = NULL;
45309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 i = 0;
45409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_dword = 0;
45509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
45609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					     E1000_INVM_RECORD_SIZE_IN_BYTES);
45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 buffer[E1000_INVM_SIZE];
45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u16 version = 0;
46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read iNVM memory */
46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		buffer[i] = invm_dword;
46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read version number */
46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have first version location used */
47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = 0;
47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have second version location used */
47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((i == 1) &&
48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have odd version location
48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
48909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 (i != 1))) {
49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*next_record & E1000_INVM_VER_FIELD_TWO)
49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				  >> 13;
49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
49609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have even version location
49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) {
50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
50709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	if (status == E1000_SUCCESS) {
50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					>> E1000_INVM_MAJOR_SHIFT;
51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read Image Type */
51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
51609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type = 0;
52009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
52109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
52209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
52309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
52409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & 0x3) == 0) &&
52509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
52609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((((*record & 0x3) != 0) && (i != 1)))) {
52709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type =
52809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
52909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
53009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
53109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
53209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
53309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	return status;
53409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny}
53509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
53609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/**
537f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
538f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
539f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
540f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
541f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
542f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
543f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
544f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
545f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
546f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
547f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
548f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
549f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
550b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher		/* Replace the read function with semaphore grabbing with
551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * the one that skips this for a while.
552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * We have semaphore taken already here.
553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		read_op_ptr = hw->nvm.ops.read;
555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = igb_read_nvm_eerd;
556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
557f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = igb_validate_nvm_checksum(hw);
558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
559f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Revert original read operation. */
560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = read_op_ptr;
561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
562f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
564f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = E1000_ERR_SWFW_SYNC;
565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_nvm_checksum_i210 - Update EEPROM checksum
572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  up to the checksum.  Then calculates the EEPROM checksum and writes the
576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  value to the EEPROM. Next commit EEPROM data onto the Flash.
577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 checksum = 0;
582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, nvm_data;
583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
584b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	/* Read the first word from the EEPROM. If this times out or fails, do
585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * not continue or we could be in for a very long wait while every
586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * EEPROM read fails
587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val != E1000_SUCCESS) {
590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("EEPROM read failed\n");
591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
592f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
594f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
595b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher		/* Do not use hw->nvm.ops.write, hw->nvm.ops.read
596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * because we do not want to take the synchronization
597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * semaphores twice here.
598f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (ret_val) {
603f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw->nvm.ops.release(hw);
604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("NVM Read Error while updating checksum.\n");
605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				goto out;
606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			checksum += nvm_data;
608f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
609f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		checksum = (u16) NVM_SUM - checksum;
610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						&checksum);
612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS) {
613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("NVM Write Error while updating checksum.\n");
615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_update_flash_i210(hw);
621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
626f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
6297916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_pool_flash_update_done_i210 - Pool FLUDONE status.
6307916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
6317916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
632b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/
6337916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
6347916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
6357916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 ret_val = -E1000_ERR_NVM;
6367916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u32 i, reg;
6377916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
6397916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		reg = rd32(E1000_EECD);
6407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (reg & E1000_EECD_FLUDONE_I210) {
6417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			ret_val = E1000_SUCCESS;
6427916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
6437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		}
6447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		udelay(5);
6457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
6467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return ret_val;
6487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
6497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
651f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_flash_i210 - Commit EEPROM to the flash
652f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
653f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
654f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
655f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_flash_i210(struct e1000_hw *hw)
656f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
657f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
658f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 flup;
659f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
660f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
661f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == -E1000_ERR_NVM) {
662f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
663f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
664f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
665f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
666f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
667f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_EECD, flup);
668f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
669f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
670f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == E1000_SUCCESS)
671f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update complete\n");
672f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	else
673f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
674f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
675f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
676f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
677f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
678f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
679f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
680f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_valid_led_default_i210 - Verify a valid default LED config
681f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the NVM (EEPROM)
683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Read the EEPROM for the current default LED configuration.  If the
685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  LED configuration is not valid, set to a valid LED configuration.
686f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
688f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val;
690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val) {
693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM Read Error\n");
694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
698f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		switch (hw->phy.media_type) {
699f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_internal_serdes:
700f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210_SERDES;
701f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
702f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_copper:
703f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		default:
704f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210;
705f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
706f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
707f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
708f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
709f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
710f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
71187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
71287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/**
71387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  __igb_access_xmdio_reg - Read/write XMDIO register
71487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @hw: pointer to the HW structure
71587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @address: XMDIO address to program
71687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @dev_addr: device address to program
71787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @data: pointer to value to read/write from/to the XMDIO address
71887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @read: boolean flag to indicate read or write
71987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/
72087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vickstatic s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address,
72187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick				  u8 dev_addr, u16 *data, bool read)
72287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{
72387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	s32 ret_val = E1000_SUCCESS;
72487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
72587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
72687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
72787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
72887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
72987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
73087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
73187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
73287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
73387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
73487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick							 dev_addr);
73587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
73687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
73787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
73887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (read)
73987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
74087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	else
74187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
74287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
74387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
74487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
74587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	/* Recalibrate the device back to 0 */
74687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
74787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
74887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
74987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
75087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	return ret_val;
75187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick}
75287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
75387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/**
75487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  igb_read_xmdio_reg - Read XMDIO register
75587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @hw: pointer to the HW structure
75687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @addr: XMDIO address to program
75787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @dev_addr: device address to program
75887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @data: value to be read from the EMI address
75987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/
76087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
76187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{
76287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true);
76387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick}
76487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
76587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/**
76687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  igb_write_xmdio_reg - Write XMDIO register
76787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @hw: pointer to the HW structure
76887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @addr: XMDIO address to program
76987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @dev_addr: device address to program
77087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @data: value to be written to the XMDIO address
77187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/
77287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
77387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{
77487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false);
77587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick}
776