e1000_i210.c revision 09e77287e752c8fc9743d865ddadc1a0d81a4927
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
38f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw);
39f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic void igb_put_hw_semaphore_i210(struct e1000_hw *hw);
40f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
41f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				u16 *data);
42f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw);
43f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
44f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
45f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_acquire_nvm_i210 - Request for access to EEPROM
46f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
47f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
48f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the necessary semaphores for exclusive access to the EEPROM.
49f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
50f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Return successful if access grant bit set, else clear the request for
51f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  EEPROM access and return -E1000_ERR_NVM (-1).
52f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
53f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_nvm_i210(struct e1000_hw *hw)
54f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
55f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
56f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
57f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
58f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
59f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_nvm_i210 - Release exclusive access to EEPROM
60f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
61f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
62f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
63f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  then release the semaphores acquired.
64f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
65f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_nvm_i210(struct e1000_hw *hw)
66f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
67f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
68f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
69f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
70f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
71f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
72f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
73f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
74f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
75f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
76f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're acquiring the lock for.
77f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
78f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
79f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
80f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
81f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swmask = mask;
82f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 fwmask = mask << 16;
83f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
84f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
85f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
86f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	while (i < timeout) {
87f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (igb_get_hw_semaphore_i210(hw)) {
88f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = -E1000_ERR_SWFW_SYNC;
89f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
90f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
91f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
92f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		swfw_sync = rd32(E1000_SW_FW_SYNC);
93f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (!(swfw_sync & fwmask))
94f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
95f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
96f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/*
97f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * Firmware currently using resource (fwmask)
98f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
99f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_put_hw_semaphore_i210(hw);
100f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		mdelay(5);
101f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		i++;
102f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
103f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
104f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (i == timeout) {
105f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
106f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
107f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
108f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
109f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
110f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync |= swmask;
111f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
112f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
113f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_put_hw_semaphore_i210(hw);
114f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
115f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
116f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
117f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
118f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
119f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_swfw_sync_i210 - Release SW/FW semaphore
120f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
121f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
122f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
123f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
124f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're releasing the lock for.
125f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
126f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
127f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
128f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
129f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
130f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
131f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		; /* Empty */
132f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
133f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync = rd32(E1000_SW_FW_SYNC);
134f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync &= ~mask;
135f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
136f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
137f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_put_hw_semaphore_i210(hw);
138f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
139f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
140f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
141f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_get_hw_semaphore_i210 - Acquire hardware semaphore
142f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
143f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
144f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the HW semaphore to access the PHY or NVM
145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swsm;
149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 timeout = hw->nvm.word_size + 1;
151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 i = 0;
152f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* Get the FW semaphore. */
154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < timeout; i++) {
155f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		swsm = rd32(E1000_SWSM);
156f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Semaphore acquired if bit latched */
159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		udelay(50);
163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (i == timeout) {
166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Release semaphores */
167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_put_hw_semaphore(hw);
168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Driver can't access the NVM\n");
169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_NVM;
170f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_put_hw_semaphore_i210 - Release hardware semaphore
179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Release hardware semaphore used to access the PHY or NVM
182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swsm;
186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
187f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swsm = rd32(E1000_SWSM);
188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swsm &= ~E1000_SWSM_SWESMBI;
190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SWSM, swsm);
192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
194f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset of word in the Shadow Ram to read
198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to read
199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: word read from the Shadow Ram
200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads a 16 bit word from the Shadow Ram using the EERD register.
202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Uses necessary synchronization semaphores.
203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
204f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
205f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			     u16 *data)
206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
207f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
208f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, count;
209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
210f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * to read in bursts than synchronizing access for each word. */
213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
215f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
216f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = igb_read_nvm_eerd(hw, offset, count,
218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						     data + i);
219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
220f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		} else {
221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (status != E1000_SUCCESS)
225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
228f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset within the Shadow RAM to be written to
235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to write
236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow RAM
237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Writes data to Shadow RAM at offset using EEWR register.
239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  If e1000_update_nvm_checksum is not called after this function , the
241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  data will not be committed to FLASH and also Shadow RAM will most likely
242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  contain an invalid checksum.
243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
244f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  partially written.
246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			      u16 *data)
249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, count;
252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
253f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
255f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * to write in bursts than synchronizing access for each word. */
256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = igb_write_nvm_srwr(hw, offset, count,
261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						      data + i);
262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		} else {
264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (status != E1000_SUCCESS)
268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
275f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_write_nvm_srwr - Write to Shadow Ram using EEWR
276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset within the Shadow Ram to be written to
278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to write
279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow Ram
280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
281f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Writes data to Shadow Ram at offset using EEWR register.
282f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
283f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  If igb_update_nvm_checksum is not called after this function , the
284f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Shadow Ram will most likely contain an invalid checksum.
285f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
286f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
287f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				u16 *data)
288f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
289f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	struct e1000_nvm_info *nvm = &hw->nvm;
290f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 i, k, eewr = 0;
291f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 attempts = 100000;
292f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
293f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
294f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/*
295f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * A check for invalid values:  offset too large, too many words,
296f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * too many words for the offset, and not enough words.
297f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
298f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
299f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	    (words == 0)) {
300f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("nvm parameter(s) out of bounds\n");
301f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_NVM;
302f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
303f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
304f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
305f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i++) {
306f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
307f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			(data[i] << E1000_NVM_RW_REG_DATA) |
308f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_NVM_RW_REG_START;
309f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
310f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		wr32(E1000_SRWR, eewr);
311f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
312f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (k = 0; k < attempts; k++) {
313f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (E1000_NVM_RW_REG_DONE &
314f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			    rd32(E1000_SRWR)) {
315f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				ret_val = E1000_SUCCESS;
316f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
317f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
318f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			udelay(5);
319f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
320f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
321f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS) {
322f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("Shadow RAM write EEWR timed out\n");
323f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
324f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
325f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
326f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
327f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
328f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
329f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
330f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
331f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
332f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_i211 - Read NVM wrapper function for I211
333f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
334f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @address: the word address (aka eeprom offset) to read
335f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
336f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
337f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Wrapper function to return data formerly found in the NVM.
338f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
339f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
340f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			       u16 *data)
341f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
342f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
343f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
344f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* Only the MAC addr is required to be present in the iNVM */
345f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	switch (offset) {
346f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_MAC_ADDR:
347f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_read_invm_i211(hw, offset, &data[0]);
348f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]);
349f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]);
350f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS)
351f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("MAC Addr not found in iNVM\n");
352f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
353f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_ID_LED_SETTINGS:
354f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_2:
355f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_4:
356f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_1_CFG:
357f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_0_2_CFG:
358f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		igb_read_invm_i211(hw, offset, data);
359f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
360f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_COMPAT:
361f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = ID_LED_DEFAULT_I210;
362f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
363f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_DEV_ID:
364f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_device_id;
365f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
366f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_VEN_ID:
367f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_vendor_id;
368f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
369f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_DEV_ID:
370f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->device_id;
371f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
372f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_VEN_ID:
373f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->vendor_id;
374f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
375f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	default:
376f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
377f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = NVM_RESERVED_WORD;
378f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
379f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
380f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
381f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_invm_i211 - Reads OTP
385f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
386f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @address: the word address (aka eeprom offset) to read
387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
388f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads 16-bit words from the OTP. Return error when the word is not
390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  stored in OTP.
391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
393f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
394f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
395f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 invm_dword;
396f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i;
397f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u8 record_type, word_address;
398f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Get record type */
402f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
403f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
404f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
405f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
406f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
407f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
409f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
410f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
411f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (word_address == (u8)address) {
412f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
413f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("Read INVM Word 0x%02x = %x",
414f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny					  address, *data);
415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				status = E1000_SUCCESS;
416f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
417f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
418f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
419f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
420f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (status != E1000_SUCCESS)
421f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Requested word 0x%02x not found in OTP\n", address);
422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
423f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
424f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
425f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
42609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  igb_read_invm_version - Reads iNVM version and image type
42709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @hw: pointer to the HW structure
42809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @invm_ver: version structure for the version read
42909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *
43009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  Reads iNVM version and image type.
43109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/
43209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw,
43309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			  struct e1000_fw_version *invm_ver) {
43409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *record = NULL;
43509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *next_record = NULL;
43609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 i = 0;
43709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_dword = 0;
43809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
43909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					     E1000_INVM_RECORD_SIZE_IN_BYTES);
44009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 buffer[E1000_INVM_SIZE];
44109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
44209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u16 version = 0;
44309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
44409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read iNVM memory */
44509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
44609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
44709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		buffer[i] = invm_dword;
44809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
44909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
45009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read version number */
45109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
45209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
45309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
45409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
45509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have first version location used */
45609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = 0;
45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have second version location used */
46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((i == 1) &&
46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have odd version location
46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 (i != 1))) {
47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*next_record & E1000_INVM_VER_FIELD_TWO)
47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				  >> 13;
47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have even version location
48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) {
48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
48909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	if (status == E1000_SUCCESS) {
49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					>> E1000_INVM_MAJOR_SHIFT;
49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read Image Type */
49609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type = 0;
50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
50709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & 0x3) == 0) &&
50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((((*record & 0x3) != 0) && (i != 1)))) {
51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type =
51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			status = E1000_SUCCESS;
51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
51609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	return status;
51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny}
51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/**
520f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
521f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
522f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
523f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
524f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
525f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
526f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
527f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
528f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 status = E1000_SUCCESS;
529f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
530f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
531f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
532f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
533f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/*
534f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * Replace the read function with semaphore grabbing with
535f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * the one that skips this for a while.
536f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * We have semaphore taken already here.
537f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
538f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		read_op_ptr = hw->nvm.ops.read;
539f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = igb_read_nvm_eerd;
540f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
541f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = igb_validate_nvm_checksum(hw);
542f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
543f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Revert original read operation. */
544f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = read_op_ptr;
545f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
546f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
547f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
548f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = E1000_ERR_SWFW_SYNC;
549f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
550f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_nvm_checksum_i210 - Update EEPROM checksum
557f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
559f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  up to the checksum.  Then calculates the EEPROM checksum and writes the
561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  value to the EEPROM. Next commit EEPROM data onto the Flash.
562f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
564f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 checksum = 0;
567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, nvm_data;
568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/*
570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * Read the first word from the EEPROM. If this times out or fails, do
571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * not continue or we could be in for a very long wait while every
572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * EEPROM read fails
573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val != E1000_SUCCESS) {
576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("EEPROM read failed\n");
577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/*
582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * because we do not want to take the synchronization
584f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * semaphores twice here.
585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (ret_val) {
590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw->nvm.ops.release(hw);
591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("NVM Read Error while updating checksum.\n");
592f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				goto out;
593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
594f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			checksum += nvm_data;
595f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		checksum = (u16) NVM_SUM - checksum;
597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
598f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						&checksum);
599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (ret_val != E1000_SUCCESS) {
600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("NVM Write Error while updating checksum.\n");
602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
603f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_update_flash_i210(hw);
608f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
609f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_flash_i210 - Commit EEPROM to the flash
617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_update_flash_i210(struct e1000_hw *hw)
621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = E1000_SUCCESS;
623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 flup;
624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
626f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == -E1000_ERR_NVM) {
627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
629f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
630f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
631f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
632f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_EECD, flup);
633f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
634f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
635f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == E1000_SUCCESS)
636f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update complete\n");
637f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	else
638f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
639f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
640f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
641f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
642f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
643f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
644f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
645f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_pool_flash_update_done_i210 - Pool FLUDONE status.
646f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
647f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
648f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
649f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
650f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
651f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val = -E1000_ERR_NVM;
652f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 i, reg;
653f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
654f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
655f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		reg = rd32(E1000_EECD);
656f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (reg & E1000_EECD_FLUDONE_I210) {
657f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = E1000_SUCCESS;
658f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
659f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
660f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		udelay(5);
661f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
662f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
663f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
664f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
665f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
666f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
667f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_valid_led_default_i210 - Verify a valid default LED config
668f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
669f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the NVM (EEPROM)
670f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
671f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Read the EEPROM for the current default LED configuration.  If the
672f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  LED configuration is not valid, set to a valid LED configuration.
673f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
674f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
675f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
676f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val;
677f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
678f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
679f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val) {
680f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM Read Error\n");
681f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		switch (hw->phy.media_type) {
686f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_internal_serdes:
687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210_SERDES;
688f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_copper:
690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		default:
691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210;
692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
698