1e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny/* Intel(R) Gigabit Ethernet Linux driver
2e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * Copyright(c) 2007-2014 Intel Corporation.
3e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny *
4e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * This program is free software; you can redistribute it and/or modify it
5e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * under the terms and conditions of the GNU General Public License,
6e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * version 2, as published by the Free Software Foundation.
7e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny *
8e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * This program is distributed in the hope it will be useful, but WITHOUT
9e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * more details.
12e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny *
13e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * You should have received a copy of the GNU General Public License along with
14e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * this program; if not, see <http://www.gnu.org/licenses/>.
15e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny *
16e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * The full GNU General Public License is included in this distribution in
17e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * the file called "COPYING".
18e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny *
19e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * Contact Information:
20e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
21e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
22e52c0f960cbc2c691cbb809ac0bfec2becfe6da9Carolyn Wyborny */
23f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
24f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/* e1000_i210
25f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny * e1000_i211
26f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny */
27f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
28f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/types.h>
29f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include <linux/if_ether.h>
30f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
31f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_hw.h"
32f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny#include "e1000_i210.h"
33f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
34167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_update_flash_i210(struct e1000_hw *hw);
35167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsher
367916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
377916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
387916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
397916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
407916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  Acquire the HW semaphore to access the PHY or NVM
417916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny */
427916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u32 swsm;
457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 timeout = hw->nvm.word_size + 1;
467916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 i = 0;
477916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
48d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	/* Get the SW semaphore */
49d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	while (i < timeout) {
50d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		swsm = rd32(E1000_SWSM);
51d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		if (!(swsm & E1000_SWSM_SMBI))
52d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			break;
53d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick
54d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		udelay(50);
55d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		i++;
56d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	}
57d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick
58d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	if (i == timeout) {
59d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		/* In rare circumstances, the SW semaphore may already be held
60d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		 * unintentionally. Clear the semaphore once before giving up.
61d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		 */
62d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		if (hw->dev_spec._82575.clear_semaphore_once) {
63d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			hw->dev_spec._82575.clear_semaphore_once = false;
64d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			igb_put_hw_semaphore(hw);
65d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			for (i = 0; i < timeout; i++) {
66d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick				swsm = rd32(E1000_SWSM);
67d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick				if (!(swsm & E1000_SWSM_SMBI))
68d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick					break;
69d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick
70d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick				udelay(50);
71d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			}
72d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		}
73d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick
74d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		/* If we do not have the semaphore here, we have to give up. */
75d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		if (i == timeout) {
76d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			hw_dbg("Driver can't access device - SMBI bit is set.\n");
77d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick			return -E1000_ERR_NVM;
78d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		}
79d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	}
80d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick
817916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	/* Get the FW semaphore. */
827916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < timeout; i++) {
837916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		swsm = rd32(E1000_SWSM);
847916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
857916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
867916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		/* Semaphore acquired if bit latched */
877916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
887916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
897916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
907916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		udelay(50);
917916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	if (i == timeout) {
947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		/* Release semaphores */
957916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		igb_put_hw_semaphore(hw);
967916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		hw_dbg("Driver can't access the NVM\n");
97d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		return -E1000_ERR_NVM;
987916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
10023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	return 0;
1017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
102f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
103f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
104f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_acquire_nvm_i210 - Request for access to EEPROM
105f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
106f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
107f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the necessary semaphores for exclusive access to the EEPROM.
108f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
109f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Return successful if access grant bit set, else clear the request for
110f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  EEPROM access and return -E1000_ERR_NVM (-1).
111f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
112167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
113f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
114f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
115f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
116f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
117f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
118f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_nvm_i210 - Release exclusive access to EEPROM
119f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
120f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
121f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
122f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  then release the semaphores acquired.
123f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
124167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic void igb_release_nvm_i210(struct e1000_hw *hw)
125f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
126f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
127f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
128f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
129f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
130f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
131f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
132f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
133f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
134f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
135f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're acquiring the lock for.
136f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
137f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
138f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
139f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
140f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swmask = mask;
141f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 fwmask = mask << 16;
14223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 ret_val = 0;
143f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
144f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
145f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	while (i < timeout) {
146f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		if (igb_get_hw_semaphore_i210(hw)) {
147f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = -E1000_ERR_SWFW_SYNC;
148f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
149f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
150f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
151f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		swfw_sync = rd32(E1000_SW_FW_SYNC);
152d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		if (!(swfw_sync & (fwmask | swmask)))
153f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
154f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
155b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher		/* Firmware currently using resource (fwmask) */
156d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick		igb_put_hw_semaphore(hw);
157f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		mdelay(5);
158f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		i++;
159f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
160f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
161f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (i == timeout) {
162f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
163f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
164f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
165f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
166f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
167f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync |= swmask;
168f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
169f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
170d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	igb_put_hw_semaphore(hw);
171f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
172f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
173f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
174f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
175f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
176f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_release_swfw_sync_i210 - Release SW/FW semaphore
177f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
178f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @mask: specifies which semaphore to acquire
179f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
180f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
181f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  will also specify which port we're releasing the lock for.
182f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
183f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyvoid igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
184f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
185f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 swfw_sync;
186f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
18723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	while (igb_get_hw_semaphore_i210(hw))
188f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		; /* Empty */
189f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
190f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync = rd32(E1000_SW_FW_SYNC);
191f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	swfw_sync &= ~mask;
192f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_SW_FW_SYNC, swfw_sync);
193f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
194d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4Matthew Vick	igb_put_hw_semaphore(hw);
195f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
196f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
197f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
198f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
199f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
200f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset of word in the Shadow Ram to read
201f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to read
202f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: word read from the Shadow Ram
203f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
204f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Reads a 16 bit word from the Shadow Ram using the EERD register.
205f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Uses necessary synchronization semaphores.
206f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
207167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
208167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsher				  u16 *data)
209f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
21023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 status = 0;
211f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, count;
212f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
213f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
214f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
215b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	 * to read in bursts than synchronizing access for each word.
216b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	 */
217f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
218f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
219f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
22023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (!(hw->nvm.ops.acquire(hw))) {
221f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = igb_read_nvm_eerd(hw, offset, count,
222f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						     data + i);
223f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
224f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		} else {
225f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
226f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
227f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
22823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (status)
229f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
230f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
231f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
232f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
233f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
234f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
235f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
236f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_write_nvm_srwr - Write to Shadow Ram using EEWR
237f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
238f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @offset: offset within the Shadow Ram to be written to
239f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @words: number of words to write
240f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow Ram
241f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
242f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Writes data to Shadow Ram at offset using EEWR register.
243f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
244f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  If igb_update_nvm_checksum is not called after this function , the
245f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Shadow Ram will most likely contain an invalid checksum.
246f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
247f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornystatic s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
248f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				u16 *data)
249f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
250f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	struct e1000_nvm_info *nvm = &hw->nvm;
251f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 i, k, eewr = 0;
252f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 attempts = 100000;
25323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 ret_val = 0;
254f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
255b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	/* A check for invalid values:  offset too large, too many words,
256f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * too many words for the offset, and not enough words.
257f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
258f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
259f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	    (words == 0)) {
260f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("nvm parameter(s) out of bounds\n");
261f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_NVM;
262f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
263f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
264f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
265f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	for (i = 0; i < words; i++) {
266f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
267f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			(data[i] << E1000_NVM_RW_REG_DATA) |
268f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			E1000_NVM_RW_REG_START;
269f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
270f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		wr32(E1000_SRWR, eewr);
271f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
272f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (k = 0; k < attempts; k++) {
273f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (E1000_NVM_RW_REG_DONE &
274f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			    rd32(E1000_SRWR)) {
27523d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka				ret_val = 0;
276f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				break;
277f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
278f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			udelay(5);
279f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
280f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
28123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
282f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("Shadow RAM write EEWR timed out\n");
283f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
284f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
285f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
286f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
287f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
288f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
289f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
290f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
291f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
2927916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
2937916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
2947916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @offset: offset within the Shadow RAM to be written to
2957916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @words: number of words to write
2967916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @data: 16 bit word(s) to be written to the Shadow RAM
2977916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
2987916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  Writes data to Shadow RAM at offset using EEWR register.
2997916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
3007916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  If e1000_update_nvm_checksum is not called after this function , the
3017916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  data will not be committed to FLASH and also Shadow RAM will most likely
3027916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  contain an invalid checksum.
3037916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
3047916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
3057916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  partially written.
306b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/
307167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
308167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsher				   u16 *data)
3097916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
31023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 status = 0;
3117916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u16 i, count;
3127916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3137916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	/* We cannot hold synchronization semaphores for too long,
3147916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 * because of forceful takeover procedure. However it is more efficient
3157916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 * to write in bursts than synchronizing access for each word.
3167916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	 */
3177916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
3187916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
3197916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			E1000_EERD_EEWR_MAX_COUNT : (words - i);
32023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (!(hw->nvm.ops.acquire(hw))) {
3217916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			status = igb_write_nvm_srwr(hw, offset, count,
3227916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny						      data + i);
3237916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			hw->nvm.ops.release(hw);
3247916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		} else {
3257916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			status = E1000_ERR_SWFW_SYNC;
3267916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		}
3277916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
32823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (status)
3297916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
3307916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
3317916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3327916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return status;
3337916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
3347916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
3357916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
336ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *  igb_read_invm_word_i210 - Reads OTP
337ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *  @hw: pointer to the HW structure
338ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *  @address: the word address (aka eeprom offset) to read
339ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *  @data: pointer to the data read
340ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *
341ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *  Reads 16-bit words from the OTP. Return error when the word is not
342ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny *  stored in OTP.
343ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny **/
344ef3a009297c50876980f21060aee61e8b516a990Carolyn Wybornystatic s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
345ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny{
346ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
347ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	u32 invm_dword;
348ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	u16 i;
349ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	u8 record_type, word_address;
350ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny
351ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
352ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
353ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		/* Get record type */
354ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
355ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
356ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny			break;
357ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
358ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
359ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
360ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
361ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
362ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
363ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny			if (word_address == address) {
364ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
365c5ffe7e1f745984b37b8ffe03b03f3d716a072f3Jakub Kicinski				hw_dbg("Read INVM Word 0x%02x = %x\n",
366ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny					  address, *data);
36723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka				status = 0;
368ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny				break;
369ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny			}
370ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		}
371ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	}
37223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	if (status)
373ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		hw_dbg("Requested word 0x%02x not found in OTP\n", address);
374ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny	return status;
375ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny}
376ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny
377ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny/**
378ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny * igb_read_invm_i210 - Read invm wrapper function for I210/I211
379f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
3805c17a203721d72c36798e5d7fa564e1adf8beb65Akeem G. Abodunrin *  @words: number of words to read
381f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the data read
382f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
383f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Wrapper function to return data formerly found in the NVM.
384f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
385ef3a009297c50876980f21060aee61e8b516a990Carolyn Wybornystatic s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset,
386ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny				u16 words __always_unused, u16 *data)
387f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
38823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 ret_val = 0;
389f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
390f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	/* Only the MAC addr is required to be present in the iNVM */
391f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	switch (offset) {
392f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_MAC_ADDR:
393ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]);
394ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1,
395ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny						     &data[1]);
396ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2,
397ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny						     &data[2]);
39823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val)
399f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("MAC Addr not found in iNVM\n");
400f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
401f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_2:
402ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
40323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
4041720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
40523d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			ret_val = 0;
4061720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
4071720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
408f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_INIT_CTRL_4:
409ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
41023d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
4111720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
41223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			ret_val = 0;
4131720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
4141720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
415f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_1_CFG:
416ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
41723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
4181720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_LED_1_CFG_DEFAULT_I211;
41923d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			ret_val = 0;
4201720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
4211720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		break;
422f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_LED_0_2_CFG:
423ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
42423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
4251720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
42623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			ret_val = 0;
4271720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
428f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
4291720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny	case NVM_ID_LED_SETTINGS:
430ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
43123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
4321720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny			*data = ID_LED_RESERVED_FFFF;
43323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			ret_val = 0;
4341720ee3e4054eff175743820ceba16ecfe97943aCarolyn Wyborny		}
435b26141d47a4a73f07853986bd6b5a9f4ee6b4fa1Carolyn Wyborny		break;
436f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_DEV_ID:
437f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_device_id;
438f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
439f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_SUB_VEN_ID:
440f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->subsystem_vendor_id;
441f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
442f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_DEV_ID:
443f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->device_id;
444f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
445f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	case NVM_VEN_ID:
446f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = hw->vendor_id;
447f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
448f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	default:
449f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
450f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		*data = NVM_RESERVED_WORD;
451f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		break;
452f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
453f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
454f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
455f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
456f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
45709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  igb_read_invm_version - Reads iNVM version and image type
45809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @hw: pointer to the HW structure
45909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  @invm_ver: version structure for the version read
46009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *
46109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny *  Reads iNVM version and image type.
46209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny **/
46309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wybornys32 igb_read_invm_version(struct e1000_hw *hw,
46409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			  struct e1000_fw_version *invm_ver) {
46509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *record = NULL;
46609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 *next_record = NULL;
46709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 i = 0;
46809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_dword = 0;
46909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
47009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					     E1000_INVM_RECORD_SIZE_IN_BYTES);
47109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u32 buffer[E1000_INVM_SIZE];
47209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
47309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	u16 version = 0;
47409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
47509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read iNVM memory */
47609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 0; i < E1000_INVM_SIZE; i++) {
47709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_dword = rd32(E1000_INVM_DATA_REG(i));
47809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		buffer[i] = invm_dword;
47909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
48009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
48109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read version number */
48209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
48309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
48409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
48509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
48609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have first version location used */
48709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
48809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = 0;
48923d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			status = 0;
49009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
49109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
49209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have second version location used */
49309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((i == 1) &&
49409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
49509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
49623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			status = 0;
49709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
49809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
49909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have odd version location
50009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
50109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
50209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
50309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
50409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 (i != 1))) {
50509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*next_record & E1000_INVM_VER_FIELD_TWO)
50609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				  >> 13;
50723d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			status = 0;
50809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
50909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
51009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have even version location
51109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 * used and it is the last one used
51209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		 */
51309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
51409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & 0x3) == 0)) {
51509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
51623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			status = 0;
51709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
51809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
51909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
52009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
52123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	if (!status) {
52209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
52309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny					>> E1000_INVM_MAJOR_SHIFT;
52409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
52509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
52609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	/* Read Image Type */
52709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	for (i = 1; i < invm_blocks; i++) {
52809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		record = &buffer[invm_blocks - i];
52909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		next_record = &buffer[invm_blocks - i + 1];
53009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
53109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
53209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
53309e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type = 0;
53423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			status = 0;
53509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
53609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
53709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		/* Check if we have image type in first location used */
53809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		else if ((((*record & 0x3) == 0) &&
53909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
54009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			 ((((*record & 0x3) != 0) && (i != 1)))) {
54109e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			invm_ver->invm_img_type =
54209e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny				(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
54323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			status = 0;
54409e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny			break;
54509e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny		}
54609e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	}
54709e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny	return status;
54809e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny}
54909e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny
55009e77287e752c8fc9743d865ddadc1a0d81a4927Carolyn Wyborny/**
551f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
552f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
553f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
554f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
555f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
556f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
557167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
558f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
55923d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 status = 0;
560f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
561f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
56223d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	if (!(hw->nvm.ops.acquire(hw))) {
563f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
564b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher		/* Replace the read function with semaphore grabbing with
565f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * the one that skips this for a while.
566f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * We have semaphore taken already here.
567f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
568f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		read_op_ptr = hw->nvm.ops.read;
569f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = igb_read_nvm_eerd;
570f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
571f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = igb_validate_nvm_checksum(hw);
572f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
573f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		/* Revert original read operation. */
574f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.read = read_op_ptr;
575f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
576f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
577f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
578f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		status = E1000_ERR_SWFW_SYNC;
579f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
580f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
581f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return status;
582f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
583f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
584f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
585f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_nvm_checksum_i210 - Update EEPROM checksum
586f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
587f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
588f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
589f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  up to the checksum.  Then calculates the EEPROM checksum and writes the
590f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  value to the EEPROM. Next commit EEPROM data onto the Flash.
591f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
592167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
593f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
59423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 ret_val = 0;
595f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 checksum = 0;
596f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u16 i, nvm_data;
597f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
598b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher	/* Read the first word from the EEPROM. If this times out or fails, do
599f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * not continue or we could be in for a very long wait while every
600f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 * EEPROM read fails
601f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	 */
602f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
60323d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	if (ret_val) {
604f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("EEPROM read failed\n");
605f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
606f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
607f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
60823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	if (!(hw->nvm.ops.acquire(hw))) {
609b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher		/* Do not use hw->nvm.ops.write, hw->nvm.ops.read
610f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * because we do not want to take the synchronization
611f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 * semaphores twice here.
612f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		 */
613f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
614f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
615f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
616f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			if (ret_val) {
617f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw->nvm.ops.release(hw);
618f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				hw_dbg("NVM Read Error while updating checksum.\n");
619f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny				goto out;
620f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			}
621f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			checksum += nvm_data;
622f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
623f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		checksum = (u16) NVM_SUM - checksum;
624f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
625f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny						&checksum);
62623d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka		if (ret_val) {
627f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw->nvm.ops.release(hw);
628f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			hw_dbg("NVM Write Error while updating checksum.\n");
629f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			goto out;
630f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
631f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
632f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw->nvm.ops.release(hw);
633f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
634f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = igb_update_flash_i210(hw);
635f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	} else {
636f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		ret_val = -E1000_ERR_SWFW_SYNC;
637f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
638f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
639f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
640f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
641f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
642f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
6437916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  igb_pool_flash_update_done_i210 - Pool FLUDONE status.
6447916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *  @hw: pointer to the HW structure
6457916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny *
646b980ac18c95f3251038da7a3826370aff05a7434Jeff Kirsher **/
6477916a53d203f12461095886cf72d58e9281240d9Carolyn Wybornystatic s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
6487916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny{
6497916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	s32 ret_val = -E1000_ERR_NVM;
6507916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	u32 i, reg;
6517916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6527916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
6537916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		reg = rd32(E1000_EECD);
6547916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		if (reg & E1000_EECD_FLUDONE_I210) {
65523d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka			ret_val = 0;
6567916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny			break;
6577916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		}
6587916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny		udelay(5);
6597916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	}
6607916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6617916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny	return ret_val;
6627916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny}
6637916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny
6647916a53d203f12461095886cf72d58e9281240d9Carolyn Wyborny/**
6655a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny *  igb_get_flash_presence_i210 - Check if flash device is detected.
6665a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny *  @hw: pointer to the HW structure
6675a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny *
6685a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny **/
6695a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wybornybool igb_get_flash_presence_i210(struct e1000_hw *hw)
6705a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny{
6715a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	u32 eec = 0;
6725a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	bool ret_val = false;
6735a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny
6745a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	eec = rd32(E1000_EECD);
6755a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	if (eec & E1000_EECD_FLASH_DETECTED_I210)
6765a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		ret_val = true;
6775a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny
6785a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	return ret_val;
6795a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny}
6805a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny
6815a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny/**
682f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_update_flash_i210 - Commit EEPROM to the flash
683f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
684f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
685f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
686167f3f71c7e31da56c907b7363a36667a59dde85Jeff Kirsherstatic s32 igb_update_flash_i210(struct e1000_hw *hw)
687f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
68823d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 ret_val = 0;
689f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	u32 flup;
690f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
691f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
692f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val == -E1000_ERR_NVM) {
693f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
694f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
695f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
696f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
697f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
698f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	wr32(E1000_EECD, flup);
699f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
700f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = igb_pool_flash_update_done_i210(hw);
70123d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	if (ret_val)
702f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update complete\n");
703f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	else
704f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("Flash update time out\n");
705f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
706f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
707f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
708f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
709f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
710f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny/**
711f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  igb_valid_led_default_i210 - Verify a valid default LED config
712f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @hw: pointer to the HW structure
713f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  @data: pointer to the NVM (EEPROM)
714f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *
715f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  Read the EEPROM for the current default LED configuration.  If the
716f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny *  LED configuration is not valid, set to a valid LED configuration.
717f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny **/
718f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornys32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
719f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny{
720f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	s32 ret_val;
721f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
722f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
723f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (ret_val) {
724f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		hw_dbg("NVM Read Error\n");
725f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		goto out;
726f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
727f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny
728f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
729f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		switch (hw->phy.media_type) {
730f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_internal_serdes:
731f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210_SERDES;
732f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
733f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		case e1000_media_type_copper:
734f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		default:
735f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			*data = ID_LED_DEFAULT_I210;
736f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny			break;
737f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny		}
738f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	}
739f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wybornyout:
740f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny	return ret_val;
741f96a8a0b78548c0ec06b0b4b438db6ee895d67e9Carolyn Wyborny}
74287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
74387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/**
74487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  __igb_access_xmdio_reg - Read/write XMDIO register
74587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @hw: pointer to the HW structure
74687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @address: XMDIO address to program
74787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @dev_addr: device address to program
74887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @data: pointer to value to read/write from/to the XMDIO address
74987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @read: boolean flag to indicate read or write
75087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/
75187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vickstatic s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address,
75287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick				  u8 dev_addr, u16 *data, bool read)
75387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{
75423d87824de22002b6e073049bb57c97c309e5263Todd Fujinaka	s32 ret_val = 0;
75587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
75687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
75787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
75887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
75987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
76087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
76187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
76287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
76387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
76487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
76587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick							 dev_addr);
76687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
76787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
76887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
76987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (read)
77087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
77187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	else
77287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
77387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
77487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
77587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
77687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	/* Recalibrate the device back to 0 */
77787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
77887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	if (ret_val)
77987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick		return ret_val;
78087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
78187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	return ret_val;
78287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick}
78387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
78487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/**
78587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  igb_read_xmdio_reg - Read XMDIO register
78687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @hw: pointer to the HW structure
78787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @addr: XMDIO address to program
78887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @dev_addr: device address to program
78987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @data: value to be read from the EMI address
79087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/
79187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
79287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{
79387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true);
79487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick}
79587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick
79687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick/**
79787371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  igb_write_xmdio_reg - Write XMDIO register
79887371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @hw: pointer to the HW structure
79987371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @addr: XMDIO address to program
80087371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @dev_addr: device address to program
80187371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick *  @data: value to be written to the XMDIO address
80287371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick **/
80387371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vicks32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
80487371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick{
80587371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick	return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false);
80687371b9de5becc32af2f9be84008b8a8a424c58aMatthew Vick}
8075a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny
8085a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny/**
8095a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny *  igb_init_nvm_params_i210 - Init NVM func ptrs.
8105a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny *  @hw: pointer to the HW structure
8115a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny **/
8125a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wybornys32 igb_init_nvm_params_i210(struct e1000_hw *hw)
8135a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny{
8145a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	s32 ret_val = 0;
8155a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	struct e1000_nvm_info *nvm = &hw->nvm;
8165a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny
8175a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	nvm->ops.acquire = igb_acquire_nvm_i210;
8185a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	nvm->ops.release = igb_release_nvm_i210;
8195a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	nvm->ops.valid_led_default = igb_valid_led_default_i210;
8205a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny
8215a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	/* NVM Function Pointers */
8225a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	if (igb_get_flash_presence_i210(hw)) {
8235a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		hw->nvm.type = e1000_nvm_flash_hw;
8245a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.read    = igb_read_nvm_srrd_i210;
8255a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.write   = igb_write_nvm_srwr_i210;
8265a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.validate = igb_validate_nvm_checksum_i210;
8275a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.update   = igb_update_nvm_checksum_i210;
8285a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	} else {
8295a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		hw->nvm.type = e1000_nvm_invm;
830ef3a009297c50876980f21060aee61e8b516a990Carolyn Wyborny		nvm->ops.read     = igb_read_invm_i210;
8315a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.write    = NULL;
8325a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.validate = NULL;
8335a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny		nvm->ops.update   = NULL;
8345a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	}
8355a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny	return ret_val;
8365a823d8cdd0e16081bc09a03fa253b9750c4b034Carolyn Wyborny}
837948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
838948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka/**
839948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * igb_pll_workaround_i210
840948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * @hw: pointer to the HW structure
841948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka *
842948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * Works around an errata in the PLL circuit where it occasionally
843948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka * provides the wrong clock frequency after power up.
844948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka **/
845948264879b6894dc389a44b99fae4f0b72932619Todd Fujinakas32 igb_pll_workaround_i210(struct e1000_hw *hw)
846948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka{
847948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	s32 ret_val;
848948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
849948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	u16 nvm_word, phy_word, pci_word, tmp_nvm;
850948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	int i;
851948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
852948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	/* Get and set needed register values */
853948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	wuc = rd32(E1000_WUC);
854948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	mdicnfg = rd32(E1000_MDICNFG);
855948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;
856948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	wr32(E1000_MDICNFG, reg_val);
857948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
858948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	/* Get data from NVM, or set default */
859948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	ret_val = igb_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD,
860948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka					  &nvm_word);
861948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	if (ret_val)
862948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		nvm_word = E1000_INVM_DEFAULT_AL;
863948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
864948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
865948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		/* check current state directly from internal PHY */
866948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		igb_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE |
867948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka					 E1000_PHY_PLL_FREQ_REG), &phy_word);
868948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		if ((phy_word & E1000_PHY_PLL_UNCONF)
869948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		    != E1000_PHY_PLL_UNCONF) {
870948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka			ret_val = 0;
871948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka			break;
872948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		} else {
873948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka			ret_val = -E1000_ERR_PHY;
874948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		}
875948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		/* directly reset the internal PHY */
876948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		ctrl = rd32(E1000_CTRL);
877948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		wr32(E1000_CTRL, ctrl|E1000_CTRL_PHY_RST);
878948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
879948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		ctrl_ext = rd32(E1000_CTRL_EXT);
880948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);
881948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		wr32(E1000_CTRL_EXT, ctrl_ext);
882948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
883948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		wr32(E1000_WUC, 0);
884948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
885948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		wr32(E1000_EEARBC_I210, reg_val);
886948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
887948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		igb_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
888948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		pci_word |= E1000_PCI_PMCSR_D3;
889948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
890948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		usleep_range(1000, 2000);
891948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		pci_word &= ~E1000_PCI_PMCSR_D3;
892948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
893948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);
894948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		wr32(E1000_EEARBC_I210, reg_val);
895948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka
896948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		/* restore WUC register */
897948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka		wr32(E1000_WUC, wuc);
898948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	}
899948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	/* restore MDICNFG setting */
900948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	wr32(E1000_MDICNFG, mdicnfg);
901948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka	return ret_val;
902948264879b6894dc389a44b99fae4f0b72932619Todd Fujinaka}
903