xref: /dragonfly/sys/dev/netif/ig_hal/e1000_i210.c (revision 65aebe9f)
14be59a01SSepherosa Ziehau /******************************************************************************
24be59a01SSepherosa Ziehau 
3*65aebe9fSSepherosa Ziehau   Copyright (c) 2001-2016, Intel Corporation
44be59a01SSepherosa Ziehau   All rights reserved.
54be59a01SSepherosa Ziehau 
64be59a01SSepherosa Ziehau   Redistribution and use in source and binary forms, with or without
74be59a01SSepherosa Ziehau   modification, are permitted provided that the following conditions are met:
84be59a01SSepherosa Ziehau 
94be59a01SSepherosa Ziehau    1. Redistributions of source code must retain the above copyright notice,
104be59a01SSepherosa Ziehau       this list of conditions and the following disclaimer.
114be59a01SSepherosa Ziehau 
124be59a01SSepherosa Ziehau    2. Redistributions in binary form must reproduce the above copyright
134be59a01SSepherosa Ziehau       notice, this list of conditions and the following disclaimer in the
144be59a01SSepherosa Ziehau       documentation and/or other materials provided with the distribution.
154be59a01SSepherosa Ziehau 
164be59a01SSepherosa Ziehau    3. Neither the name of the Intel Corporation nor the names of its
174be59a01SSepherosa Ziehau       contributors may be used to endorse or promote products derived from
184be59a01SSepherosa Ziehau       this software without specific prior written permission.
194be59a01SSepherosa Ziehau 
204be59a01SSepherosa Ziehau   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
214be59a01SSepherosa Ziehau   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224be59a01SSepherosa Ziehau   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234be59a01SSepherosa Ziehau   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
244be59a01SSepherosa Ziehau   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
254be59a01SSepherosa Ziehau   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
264be59a01SSepherosa Ziehau   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
274be59a01SSepherosa Ziehau   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
284be59a01SSepherosa Ziehau   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
294be59a01SSepherosa Ziehau   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
304be59a01SSepherosa Ziehau   POSSIBILITY OF SUCH DAMAGE.
314be59a01SSepherosa Ziehau 
324be59a01SSepherosa Ziehau ******************************************************************************/
334be59a01SSepherosa Ziehau /*$FreeBSD$*/
344be59a01SSepherosa Ziehau 
354be59a01SSepherosa Ziehau #include "e1000_api.h"
364be59a01SSepherosa Ziehau 
374be59a01SSepherosa Ziehau 
384be59a01SSepherosa Ziehau static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw);
394be59a01SSepherosa Ziehau static void e1000_release_nvm_i210(struct e1000_hw *hw);
404be59a01SSepherosa Ziehau static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw);
414be59a01SSepherosa Ziehau static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
424be59a01SSepherosa Ziehau 				u16 *data);
434be59a01SSepherosa Ziehau static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
444be59a01SSepherosa Ziehau static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
454be59a01SSepherosa Ziehau 
464be59a01SSepherosa Ziehau /**
474be59a01SSepherosa Ziehau  *  e1000_acquire_nvm_i210 - Request for access to EEPROM
484be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
494be59a01SSepherosa Ziehau  *
504be59a01SSepherosa Ziehau  *  Acquire the necessary semaphores for exclusive access to the EEPROM.
514be59a01SSepherosa Ziehau  *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
524be59a01SSepherosa Ziehau  *  Return successful if access grant bit set, else clear the request for
534be59a01SSepherosa Ziehau  *  EEPROM access and return -E1000_ERR_NVM (-1).
544be59a01SSepherosa Ziehau  **/
e1000_acquire_nvm_i210(struct e1000_hw * hw)554be59a01SSepherosa Ziehau static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw)
564be59a01SSepherosa Ziehau {
574be59a01SSepherosa Ziehau 	s32 ret_val;
584be59a01SSepherosa Ziehau 
594be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_acquire_nvm_i210");
604be59a01SSepherosa Ziehau 
614be59a01SSepherosa Ziehau 	ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
624be59a01SSepherosa Ziehau 
634be59a01SSepherosa Ziehau 	return ret_val;
644be59a01SSepherosa Ziehau }
654be59a01SSepherosa Ziehau 
664be59a01SSepherosa Ziehau /**
674be59a01SSepherosa Ziehau  *  e1000_release_nvm_i210 - Release exclusive access to EEPROM
684be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
694be59a01SSepherosa Ziehau  *
704be59a01SSepherosa Ziehau  *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
714be59a01SSepherosa Ziehau  *  then release the semaphores acquired.
724be59a01SSepherosa Ziehau  **/
e1000_release_nvm_i210(struct e1000_hw * hw)734be59a01SSepherosa Ziehau static void e1000_release_nvm_i210(struct e1000_hw *hw)
744be59a01SSepherosa Ziehau {
754be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_release_nvm_i210");
764be59a01SSepherosa Ziehau 
774be59a01SSepherosa Ziehau 	e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
784be59a01SSepherosa Ziehau }
794be59a01SSepherosa Ziehau 
804be59a01SSepherosa Ziehau /**
814be59a01SSepherosa Ziehau  *  e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
824be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
834be59a01SSepherosa Ziehau  *  @mask: specifies which semaphore to acquire
844be59a01SSepherosa Ziehau  *
854be59a01SSepherosa Ziehau  *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
864be59a01SSepherosa Ziehau  *  will also specify which port we're acquiring the lock for.
874be59a01SSepherosa Ziehau  **/
e1000_acquire_swfw_sync_i210(struct e1000_hw * hw,u16 mask)884be59a01SSepherosa Ziehau s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
894be59a01SSepherosa Ziehau {
904be59a01SSepherosa Ziehau 	u32 swfw_sync;
914be59a01SSepherosa Ziehau 	u32 swmask = mask;
924be59a01SSepherosa Ziehau 	u32 fwmask = mask << 16;
934be59a01SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
944be59a01SSepherosa Ziehau 	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
954be59a01SSepherosa Ziehau 
964be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_acquire_swfw_sync_i210");
974be59a01SSepherosa Ziehau 
984be59a01SSepherosa Ziehau 	while (i < timeout) {
994be59a01SSepherosa Ziehau 		if (e1000_get_hw_semaphore_i210(hw)) {
1004be59a01SSepherosa Ziehau 			ret_val = -E1000_ERR_SWFW_SYNC;
1014be59a01SSepherosa Ziehau 			goto out;
1024be59a01SSepherosa Ziehau 		}
1034be59a01SSepherosa Ziehau 
1044be59a01SSepherosa Ziehau 		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
105379ebbe7SSepherosa Ziehau 		if (!(swfw_sync & (fwmask | swmask)))
1064be59a01SSepherosa Ziehau 			break;
1074be59a01SSepherosa Ziehau 
1084be59a01SSepherosa Ziehau 		/*
1094be59a01SSepherosa Ziehau 		 * Firmware currently using resource (fwmask)
110379ebbe7SSepherosa Ziehau 		 * or other software thread using resource (swmask)
1114be59a01SSepherosa Ziehau 		 */
112379ebbe7SSepherosa Ziehau 		e1000_put_hw_semaphore_generic(hw);
1134be59a01SSepherosa Ziehau 		msec_delay_irq(5);
1144be59a01SSepherosa Ziehau 		i++;
1154be59a01SSepherosa Ziehau 	}
1164be59a01SSepherosa Ziehau 
1174be59a01SSepherosa Ziehau 	if (i == timeout) {
1184be59a01SSepherosa Ziehau 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
1194be59a01SSepherosa Ziehau 		ret_val = -E1000_ERR_SWFW_SYNC;
1204be59a01SSepherosa Ziehau 		goto out;
1214be59a01SSepherosa Ziehau 	}
1224be59a01SSepherosa Ziehau 
1234be59a01SSepherosa Ziehau 	swfw_sync |= swmask;
1244be59a01SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
1254be59a01SSepherosa Ziehau 
126379ebbe7SSepherosa Ziehau 	e1000_put_hw_semaphore_generic(hw);
1274be59a01SSepherosa Ziehau 
1284be59a01SSepherosa Ziehau out:
1294be59a01SSepherosa Ziehau 	return ret_val;
1304be59a01SSepherosa Ziehau }
1314be59a01SSepherosa Ziehau 
1324be59a01SSepherosa Ziehau /**
1334be59a01SSepherosa Ziehau  *  e1000_release_swfw_sync_i210 - Release SW/FW semaphore
1344be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
1354be59a01SSepherosa Ziehau  *  @mask: specifies which semaphore to acquire
1364be59a01SSepherosa Ziehau  *
1374be59a01SSepherosa Ziehau  *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
1384be59a01SSepherosa Ziehau  *  will also specify which port we're releasing the lock for.
1394be59a01SSepherosa Ziehau  **/
e1000_release_swfw_sync_i210(struct e1000_hw * hw,u16 mask)1404be59a01SSepherosa Ziehau void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
1414be59a01SSepherosa Ziehau {
1424be59a01SSepherosa Ziehau 	u32 swfw_sync;
1434be59a01SSepherosa Ziehau 
1444be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_release_swfw_sync_i210");
1454be59a01SSepherosa Ziehau 
1464be59a01SSepherosa Ziehau 	while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
1474be59a01SSepherosa Ziehau 		; /* Empty */
1484be59a01SSepherosa Ziehau 
1494be59a01SSepherosa Ziehau 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
1504be59a01SSepherosa Ziehau 	swfw_sync &= ~mask;
1514be59a01SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
1524be59a01SSepherosa Ziehau 
153379ebbe7SSepherosa Ziehau 	e1000_put_hw_semaphore_generic(hw);
1544be59a01SSepherosa Ziehau }
1554be59a01SSepherosa Ziehau 
1564be59a01SSepherosa Ziehau /**
1574be59a01SSepherosa Ziehau  *  e1000_get_hw_semaphore_i210 - Acquire hardware semaphore
1584be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
1594be59a01SSepherosa Ziehau  *
1604be59a01SSepherosa Ziehau  *  Acquire the HW semaphore to access the PHY or NVM
1614be59a01SSepherosa Ziehau  **/
e1000_get_hw_semaphore_i210(struct e1000_hw * hw)1624be59a01SSepherosa Ziehau static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
1634be59a01SSepherosa Ziehau {
1644be59a01SSepherosa Ziehau 	u32 swsm;
1654be59a01SSepherosa Ziehau 	s32 timeout = hw->nvm.word_size + 1;
1664be59a01SSepherosa Ziehau 	s32 i = 0;
1674be59a01SSepherosa Ziehau 
1684be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_get_hw_semaphore_i210");
1694be59a01SSepherosa Ziehau 
170379ebbe7SSepherosa Ziehau 	/* Get the SW semaphore */
171379ebbe7SSepherosa Ziehau 	while (i < timeout) {
172379ebbe7SSepherosa Ziehau 		swsm = E1000_READ_REG(hw, E1000_SWSM);
173379ebbe7SSepherosa Ziehau 		if (!(swsm & E1000_SWSM_SMBI))
174379ebbe7SSepherosa Ziehau 			break;
175379ebbe7SSepherosa Ziehau 
176379ebbe7SSepherosa Ziehau 		usec_delay(50);
177379ebbe7SSepherosa Ziehau 		i++;
178379ebbe7SSepherosa Ziehau 	}
179379ebbe7SSepherosa Ziehau 
180379ebbe7SSepherosa Ziehau 	if (i == timeout) {
181379ebbe7SSepherosa Ziehau 		/* In rare circumstances, the SW semaphore may already be held
182379ebbe7SSepherosa Ziehau 		 * unintentionally. Clear the semaphore once before giving up.
183379ebbe7SSepherosa Ziehau 		 */
184379ebbe7SSepherosa Ziehau 		if (hw->dev_spec._82575.clear_semaphore_once) {
185379ebbe7SSepherosa Ziehau 			hw->dev_spec._82575.clear_semaphore_once = FALSE;
186379ebbe7SSepherosa Ziehau 			e1000_put_hw_semaphore_generic(hw);
187379ebbe7SSepherosa Ziehau 			for (i = 0; i < timeout; i++) {
188379ebbe7SSepherosa Ziehau 				swsm = E1000_READ_REG(hw, E1000_SWSM);
189379ebbe7SSepherosa Ziehau 				if (!(swsm & E1000_SWSM_SMBI))
190379ebbe7SSepherosa Ziehau 					break;
191379ebbe7SSepherosa Ziehau 
192379ebbe7SSepherosa Ziehau 				usec_delay(50);
193379ebbe7SSepherosa Ziehau 			}
194379ebbe7SSepherosa Ziehau 		}
195379ebbe7SSepherosa Ziehau 
196379ebbe7SSepherosa Ziehau 		/* If we do not have the semaphore here, we have to give up. */
197379ebbe7SSepherosa Ziehau 		if (i == timeout) {
198379ebbe7SSepherosa Ziehau 			DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
199379ebbe7SSepherosa Ziehau 			return -E1000_ERR_NVM;
200379ebbe7SSepherosa Ziehau 		}
201379ebbe7SSepherosa Ziehau 	}
202379ebbe7SSepherosa Ziehau 
2034be59a01SSepherosa Ziehau 	/* Get the FW semaphore. */
2044be59a01SSepherosa Ziehau 	for (i = 0; i < timeout; i++) {
2054be59a01SSepherosa Ziehau 		swsm = E1000_READ_REG(hw, E1000_SWSM);
2064be59a01SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
2074be59a01SSepherosa Ziehau 
2084be59a01SSepherosa Ziehau 		/* Semaphore acquired if bit latched */
2094be59a01SSepherosa Ziehau 		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
2104be59a01SSepherosa Ziehau 			break;
2114be59a01SSepherosa Ziehau 
2124be59a01SSepherosa Ziehau 		usec_delay(50);
2134be59a01SSepherosa Ziehau 	}
2144be59a01SSepherosa Ziehau 
2154be59a01SSepherosa Ziehau 	if (i == timeout) {
2164be59a01SSepherosa Ziehau 		/* Release semaphores */
2174be59a01SSepherosa Ziehau 		e1000_put_hw_semaphore_generic(hw);
2184be59a01SSepherosa Ziehau 		DEBUGOUT("Driver can't access the NVM\n");
219379ebbe7SSepherosa Ziehau 		return -E1000_ERR_NVM;
2204be59a01SSepherosa Ziehau 	}
2214be59a01SSepherosa Ziehau 
222379ebbe7SSepherosa Ziehau 	return E1000_SUCCESS;
2234be59a01SSepherosa Ziehau }
2244be59a01SSepherosa Ziehau 
2254be59a01SSepherosa Ziehau /**
2264be59a01SSepherosa Ziehau  *  e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
2274be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
2284be59a01SSepherosa Ziehau  *  @offset: offset of word in the Shadow Ram to read
2294be59a01SSepherosa Ziehau  *  @words: number of words to read
2304be59a01SSepherosa Ziehau  *  @data: word read from the Shadow Ram
2314be59a01SSepherosa Ziehau  *
2324be59a01SSepherosa Ziehau  *  Reads a 16 bit word from the Shadow Ram using the EERD register.
2334be59a01SSepherosa Ziehau  *  Uses necessary synchronization semaphores.
2344be59a01SSepherosa Ziehau  **/
e1000_read_nvm_srrd_i210(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)2354be59a01SSepherosa Ziehau s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
2364be59a01SSepherosa Ziehau 			     u16 *data)
2374be59a01SSepherosa Ziehau {
2384be59a01SSepherosa Ziehau 	s32 status = E1000_SUCCESS;
2394be59a01SSepherosa Ziehau 	u16 i, count;
2404be59a01SSepherosa Ziehau 
2414be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_read_nvm_srrd_i210");
2424be59a01SSepherosa Ziehau 
2434be59a01SSepherosa Ziehau 	/* We cannot hold synchronization semaphores for too long,
2444be59a01SSepherosa Ziehau 	 * because of forceful takeover procedure. However it is more efficient
2454be59a01SSepherosa Ziehau 	 * to read in bursts than synchronizing access for each word. */
2464be59a01SSepherosa Ziehau 	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
2474be59a01SSepherosa Ziehau 		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
2484be59a01SSepherosa Ziehau 			E1000_EERD_EEWR_MAX_COUNT : (words - i);
2494be59a01SSepherosa Ziehau 		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
2504be59a01SSepherosa Ziehau 			status = e1000_read_nvm_eerd(hw, offset, count,
2514be59a01SSepherosa Ziehau 						     data + i);
2524be59a01SSepherosa Ziehau 			hw->nvm.ops.release(hw);
2534be59a01SSepherosa Ziehau 		} else {
2544be59a01SSepherosa Ziehau 			status = E1000_ERR_SWFW_SYNC;
2554be59a01SSepherosa Ziehau 		}
2564be59a01SSepherosa Ziehau 
2574be59a01SSepherosa Ziehau 		if (status != E1000_SUCCESS)
2584be59a01SSepherosa Ziehau 			break;
2594be59a01SSepherosa Ziehau 	}
2604be59a01SSepherosa Ziehau 
2614be59a01SSepherosa Ziehau 	return status;
2624be59a01SSepherosa Ziehau }
2634be59a01SSepherosa Ziehau 
2644be59a01SSepherosa Ziehau /**
2654be59a01SSepherosa Ziehau  *  e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
2664be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
2674be59a01SSepherosa Ziehau  *  @offset: offset within the Shadow RAM to be written to
2684be59a01SSepherosa Ziehau  *  @words: number of words to write
2694be59a01SSepherosa Ziehau  *  @data: 16 bit word(s) to be written to the Shadow RAM
2704be59a01SSepherosa Ziehau  *
2714be59a01SSepherosa Ziehau  *  Writes data to Shadow RAM at offset using EEWR register.
2724be59a01SSepherosa Ziehau  *
2734be59a01SSepherosa Ziehau  *  If e1000_update_nvm_checksum is not called after this function , the
2744be59a01SSepherosa Ziehau  *  data will not be committed to FLASH and also Shadow RAM will most likely
2754be59a01SSepherosa Ziehau  *  contain an invalid checksum.
2764be59a01SSepherosa Ziehau  *
2774be59a01SSepherosa Ziehau  *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
2784be59a01SSepherosa Ziehau  *  partially written.
2794be59a01SSepherosa Ziehau  **/
e1000_write_nvm_srwr_i210(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)2804be59a01SSepherosa Ziehau s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
2814be59a01SSepherosa Ziehau 			      u16 *data)
2824be59a01SSepherosa Ziehau {
2834be59a01SSepherosa Ziehau 	s32 status = E1000_SUCCESS;
2844be59a01SSepherosa Ziehau 	u16 i, count;
2854be59a01SSepherosa Ziehau 
2864be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_write_nvm_srwr_i210");
2874be59a01SSepherosa Ziehau 
2884be59a01SSepherosa Ziehau 	/* We cannot hold synchronization semaphores for too long,
2894be59a01SSepherosa Ziehau 	 * because of forceful takeover procedure. However it is more efficient
2904be59a01SSepherosa Ziehau 	 * to write in bursts than synchronizing access for each word. */
2914be59a01SSepherosa Ziehau 	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
2924be59a01SSepherosa Ziehau 		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
2934be59a01SSepherosa Ziehau 			E1000_EERD_EEWR_MAX_COUNT : (words - i);
2944be59a01SSepherosa Ziehau 		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
2954be59a01SSepherosa Ziehau 			status = e1000_write_nvm_srwr(hw, offset, count,
2964be59a01SSepherosa Ziehau 						      data + i);
2974be59a01SSepherosa Ziehau 			hw->nvm.ops.release(hw);
2984be59a01SSepherosa Ziehau 		} else {
2994be59a01SSepherosa Ziehau 			status = E1000_ERR_SWFW_SYNC;
3004be59a01SSepherosa Ziehau 		}
3014be59a01SSepherosa Ziehau 
3024be59a01SSepherosa Ziehau 		if (status != E1000_SUCCESS)
3034be59a01SSepherosa Ziehau 			break;
3044be59a01SSepherosa Ziehau 	}
3054be59a01SSepherosa Ziehau 
3064be59a01SSepherosa Ziehau 	return status;
3074be59a01SSepherosa Ziehau }
3084be59a01SSepherosa Ziehau 
3094be59a01SSepherosa Ziehau /**
3104be59a01SSepherosa Ziehau  *  e1000_write_nvm_srwr - Write to Shadow Ram using EEWR
3114be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
3124be59a01SSepherosa Ziehau  *  @offset: offset within the Shadow Ram to be written to
3134be59a01SSepherosa Ziehau  *  @words: number of words to write
3144be59a01SSepherosa Ziehau  *  @data: 16 bit word(s) to be written to the Shadow Ram
3154be59a01SSepherosa Ziehau  *
3164be59a01SSepherosa Ziehau  *  Writes data to Shadow Ram at offset using EEWR register.
3174be59a01SSepherosa Ziehau  *
3184be59a01SSepherosa Ziehau  *  If e1000_update_nvm_checksum is not called after this function , the
3194be59a01SSepherosa Ziehau  *  Shadow Ram will most likely contain an invalid checksum.
3204be59a01SSepherosa Ziehau  **/
e1000_write_nvm_srwr(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)3214be59a01SSepherosa Ziehau static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
3224be59a01SSepherosa Ziehau 				u16 *data)
3234be59a01SSepherosa Ziehau {
3244be59a01SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
3254be59a01SSepherosa Ziehau 	u32 i, k, eewr = 0;
3264be59a01SSepherosa Ziehau 	u32 attempts = 100000;
3274be59a01SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
3284be59a01SSepherosa Ziehau 
3294be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_write_nvm_srwr");
3304be59a01SSepherosa Ziehau 
3314be59a01SSepherosa Ziehau 	/*
3324be59a01SSepherosa Ziehau 	 * A check for invalid values:  offset too large, too many words,
3334be59a01SSepherosa Ziehau 	 * too many words for the offset, and not enough words.
3344be59a01SSepherosa Ziehau 	 */
3354be59a01SSepherosa Ziehau 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
3364be59a01SSepherosa Ziehau 	    (words == 0)) {
3374be59a01SSepherosa Ziehau 		DEBUGOUT("nvm parameter(s) out of bounds\n");
3384be59a01SSepherosa Ziehau 		ret_val = -E1000_ERR_NVM;
3394be59a01SSepherosa Ziehau 		goto out;
3404be59a01SSepherosa Ziehau 	}
3414be59a01SSepherosa Ziehau 
3424be59a01SSepherosa Ziehau 	for (i = 0; i < words; i++) {
3434be59a01SSepherosa Ziehau 		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
3444be59a01SSepherosa Ziehau 			(data[i] << E1000_NVM_RW_REG_DATA) |
3454be59a01SSepherosa Ziehau 			E1000_NVM_RW_REG_START;
3464be59a01SSepherosa Ziehau 
3474be59a01SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_SRWR, eewr);
3484be59a01SSepherosa Ziehau 
3494be59a01SSepherosa Ziehau 		for (k = 0; k < attempts; k++) {
3504be59a01SSepherosa Ziehau 			if (E1000_NVM_RW_REG_DONE &
3514be59a01SSepherosa Ziehau 			    E1000_READ_REG(hw, E1000_SRWR)) {
3524be59a01SSepherosa Ziehau 				ret_val = E1000_SUCCESS;
3534be59a01SSepherosa Ziehau 				break;
3544be59a01SSepherosa Ziehau 			}
3554be59a01SSepherosa Ziehau 			usec_delay(5);
3564be59a01SSepherosa Ziehau 		}
3574be59a01SSepherosa Ziehau 
3584be59a01SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
3594be59a01SSepherosa Ziehau 			DEBUGOUT("Shadow RAM write EEWR timed out\n");
3604be59a01SSepherosa Ziehau 			break;
3614be59a01SSepherosa Ziehau 		}
3624be59a01SSepherosa Ziehau 	}
3634be59a01SSepherosa Ziehau 
3644be59a01SSepherosa Ziehau out:
3654be59a01SSepherosa Ziehau 	return ret_val;
3664be59a01SSepherosa Ziehau }
3674be59a01SSepherosa Ziehau 
368379ebbe7SSepherosa Ziehau /** e1000_read_invm_word_i210 - Reads OTP
3694be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
3704be59a01SSepherosa Ziehau  *  @address: the word address (aka eeprom offset) to read
3714be59a01SSepherosa Ziehau  *  @data: pointer to the data read
3724be59a01SSepherosa Ziehau  *
3734be59a01SSepherosa Ziehau  *  Reads 16-bit words from the OTP. Return error when the word is not
3744be59a01SSepherosa Ziehau  *  stored in OTP.
3754be59a01SSepherosa Ziehau  **/
e1000_read_invm_word_i210(struct e1000_hw * hw,u8 address,u16 * data)376379ebbe7SSepherosa Ziehau static s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
3774be59a01SSepherosa Ziehau {
3784be59a01SSepherosa Ziehau 	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
3794be59a01SSepherosa Ziehau 	u32 invm_dword;
3804be59a01SSepherosa Ziehau 	u16 i;
3814be59a01SSepherosa Ziehau 	u8 record_type, word_address;
3824be59a01SSepherosa Ziehau 
383379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_read_invm_word_i210");
3844be59a01SSepherosa Ziehau 
3854be59a01SSepherosa Ziehau 	for (i = 0; i < E1000_INVM_SIZE; i++) {
3864be59a01SSepherosa Ziehau 		invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
3874be59a01SSepherosa Ziehau 		/* Get record type */
3884be59a01SSepherosa Ziehau 		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
3894be59a01SSepherosa Ziehau 		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
3904be59a01SSepherosa Ziehau 			break;
3914be59a01SSepherosa Ziehau 		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
3924be59a01SSepherosa Ziehau 			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
3934be59a01SSepherosa Ziehau 		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
3944be59a01SSepherosa Ziehau 			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
3954be59a01SSepherosa Ziehau 		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
3964be59a01SSepherosa Ziehau 			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
3974be59a01SSepherosa Ziehau 			if (word_address == address) {
3984be59a01SSepherosa Ziehau 				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
3994be59a01SSepherosa Ziehau 				DEBUGOUT2("Read INVM Word 0x%02x = %x",
4004be59a01SSepherosa Ziehau 					  address, *data);
4014be59a01SSepherosa Ziehau 				status = E1000_SUCCESS;
4024be59a01SSepherosa Ziehau 				break;
4034be59a01SSepherosa Ziehau 			}
4044be59a01SSepherosa Ziehau 		}
4054be59a01SSepherosa Ziehau 	}
4064be59a01SSepherosa Ziehau 	if (status != E1000_SUCCESS)
4074be59a01SSepherosa Ziehau 		DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address);
4084be59a01SSepherosa Ziehau 	return status;
4094be59a01SSepherosa Ziehau }
4104be59a01SSepherosa Ziehau 
411379ebbe7SSepherosa Ziehau /** e1000_read_invm_i210 - Read invm wrapper function for I210/I211
412379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
413379ebbe7SSepherosa Ziehau  *  @address: the word address (aka eeprom offset) to read
414379ebbe7SSepherosa Ziehau  *  @data: pointer to the data read
415379ebbe7SSepherosa Ziehau  *
416379ebbe7SSepherosa Ziehau  *  Wrapper function to return data formerly found in the NVM.
417379ebbe7SSepherosa Ziehau  **/
e1000_read_invm_i210(struct e1000_hw * hw,u16 offset,u16 E1000_UNUSEDARG words,u16 * data)418379ebbe7SSepherosa Ziehau static s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset,
419379ebbe7SSepherosa Ziehau 				u16 E1000_UNUSEDARG words, u16 *data)
420379ebbe7SSepherosa Ziehau {
421379ebbe7SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
422379ebbe7SSepherosa Ziehau 
423379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_read_invm_i210");
424379ebbe7SSepherosa Ziehau 
425379ebbe7SSepherosa Ziehau 	/* Only the MAC addr is required to be present in the iNVM */
426379ebbe7SSepherosa Ziehau 	switch (offset) {
427379ebbe7SSepherosa Ziehau 	case NVM_MAC_ADDR:
428379ebbe7SSepherosa Ziehau 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]);
429379ebbe7SSepherosa Ziehau 		ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1,
430379ebbe7SSepherosa Ziehau 						     &data[1]);
431379ebbe7SSepherosa Ziehau 		ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2,
432379ebbe7SSepherosa Ziehau 						     &data[2]);
433379ebbe7SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS)
434379ebbe7SSepherosa Ziehau 			DEBUGOUT("MAC Addr not found in iNVM\n");
435379ebbe7SSepherosa Ziehau 		break;
436379ebbe7SSepherosa Ziehau 	case NVM_INIT_CTRL_2:
437379ebbe7SSepherosa Ziehau 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
438379ebbe7SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
439379ebbe7SSepherosa Ziehau 			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
440379ebbe7SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
441379ebbe7SSepherosa Ziehau 		}
442379ebbe7SSepherosa Ziehau 		break;
443379ebbe7SSepherosa Ziehau 	case NVM_INIT_CTRL_4:
444379ebbe7SSepherosa Ziehau 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
445379ebbe7SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
446379ebbe7SSepherosa Ziehau 			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
447379ebbe7SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
448379ebbe7SSepherosa Ziehau 		}
449379ebbe7SSepherosa Ziehau 		break;
450379ebbe7SSepherosa Ziehau 	case NVM_LED_1_CFG:
451379ebbe7SSepherosa Ziehau 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
452379ebbe7SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
453379ebbe7SSepherosa Ziehau 			*data = NVM_LED_1_CFG_DEFAULT_I211;
454379ebbe7SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
455379ebbe7SSepherosa Ziehau 		}
456379ebbe7SSepherosa Ziehau 		break;
457379ebbe7SSepherosa Ziehau 	case NVM_LED_0_2_CFG:
458379ebbe7SSepherosa Ziehau 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
459379ebbe7SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
460379ebbe7SSepherosa Ziehau 			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
461379ebbe7SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
462379ebbe7SSepherosa Ziehau 		}
463379ebbe7SSepherosa Ziehau 		break;
464379ebbe7SSepherosa Ziehau 	case NVM_ID_LED_SETTINGS:
465379ebbe7SSepherosa Ziehau 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
466379ebbe7SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
467379ebbe7SSepherosa Ziehau 			*data = ID_LED_RESERVED_FFFF;
468379ebbe7SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
469379ebbe7SSepherosa Ziehau 		}
470379ebbe7SSepherosa Ziehau 		break;
471379ebbe7SSepherosa Ziehau 	case NVM_SUB_DEV_ID:
472379ebbe7SSepherosa Ziehau 		*data = hw->subsystem_device_id;
473379ebbe7SSepherosa Ziehau 		break;
474379ebbe7SSepherosa Ziehau 	case NVM_SUB_VEN_ID:
475379ebbe7SSepherosa Ziehau 		*data = hw->subsystem_vendor_id;
476379ebbe7SSepherosa Ziehau 		break;
477379ebbe7SSepherosa Ziehau 	case NVM_DEV_ID:
478379ebbe7SSepherosa Ziehau 		*data = hw->device_id;
479379ebbe7SSepherosa Ziehau 		break;
480379ebbe7SSepherosa Ziehau 	case NVM_VEN_ID:
481379ebbe7SSepherosa Ziehau 		*data = hw->vendor_id;
482379ebbe7SSepherosa Ziehau 		break;
483379ebbe7SSepherosa Ziehau 	default:
484379ebbe7SSepherosa Ziehau 		DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
485379ebbe7SSepherosa Ziehau 		*data = NVM_RESERVED_WORD;
486379ebbe7SSepherosa Ziehau 		break;
487379ebbe7SSepherosa Ziehau 	}
488379ebbe7SSepherosa Ziehau 	return ret_val;
489379ebbe7SSepherosa Ziehau }
490379ebbe7SSepherosa Ziehau 
4914be59a01SSepherosa Ziehau /**
4924be59a01SSepherosa Ziehau  *  e1000_read_invm_version - Reads iNVM version and image type
4934be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
4944be59a01SSepherosa Ziehau  *  @invm_ver: version structure for the version read
4954be59a01SSepherosa Ziehau  *
4964be59a01SSepherosa Ziehau  *  Reads iNVM version and image type.
4974be59a01SSepherosa Ziehau  **/
e1000_read_invm_version(struct e1000_hw * hw,struct e1000_fw_version * invm_ver)4984be59a01SSepherosa Ziehau s32 e1000_read_invm_version(struct e1000_hw *hw,
4994be59a01SSepherosa Ziehau 			    struct e1000_fw_version *invm_ver)
5004be59a01SSepherosa Ziehau {
5014be59a01SSepherosa Ziehau 	u32 *record = NULL;
5024be59a01SSepherosa Ziehau 	u32 *next_record = NULL;
5034be59a01SSepherosa Ziehau 	u32 i = 0;
5044be59a01SSepherosa Ziehau 	u32 invm_dword = 0;
5054be59a01SSepherosa Ziehau 	u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
5064be59a01SSepherosa Ziehau 					     E1000_INVM_RECORD_SIZE_IN_BYTES);
5074be59a01SSepherosa Ziehau 	u32 buffer[E1000_INVM_SIZE];
5084be59a01SSepherosa Ziehau 	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
5094be59a01SSepherosa Ziehau 	u16 version = 0;
5104be59a01SSepherosa Ziehau 
5114be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_read_invm_version");
5124be59a01SSepherosa Ziehau 
5134be59a01SSepherosa Ziehau 	/* Read iNVM memory */
5144be59a01SSepherosa Ziehau 	for (i = 0; i < E1000_INVM_SIZE; i++) {
5154be59a01SSepherosa Ziehau 		invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
5164be59a01SSepherosa Ziehau 		buffer[i] = invm_dword;
5174be59a01SSepherosa Ziehau 	}
5184be59a01SSepherosa Ziehau 
5194be59a01SSepherosa Ziehau 	/* Read version number */
5204be59a01SSepherosa Ziehau 	for (i = 1; i < invm_blocks; i++) {
5214be59a01SSepherosa Ziehau 		record = &buffer[invm_blocks - i];
5224be59a01SSepherosa Ziehau 		next_record = &buffer[invm_blocks - i + 1];
5234be59a01SSepherosa Ziehau 
5244be59a01SSepherosa Ziehau 		/* Check if we have first version location used */
5254be59a01SSepherosa Ziehau 		if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
5264be59a01SSepherosa Ziehau 			version = 0;
5274be59a01SSepherosa Ziehau 			status = E1000_SUCCESS;
5284be59a01SSepherosa Ziehau 			break;
5294be59a01SSepherosa Ziehau 		}
5304be59a01SSepherosa Ziehau 		/* Check if we have second version location used */
5314be59a01SSepherosa Ziehau 		else if ((i == 1) &&
5324be59a01SSepherosa Ziehau 			 ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
5334be59a01SSepherosa Ziehau 			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
5344be59a01SSepherosa Ziehau 			status = E1000_SUCCESS;
5354be59a01SSepherosa Ziehau 			break;
5364be59a01SSepherosa Ziehau 		}
5374be59a01SSepherosa Ziehau 		/*
5384be59a01SSepherosa Ziehau 		 * Check if we have odd version location
5394be59a01SSepherosa Ziehau 		 * used and it is the last one used
5404be59a01SSepherosa Ziehau 		 */
5414be59a01SSepherosa Ziehau 		else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
5424be59a01SSepherosa Ziehau 			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
5434be59a01SSepherosa Ziehau 			 (i != 1))) {
5444be59a01SSepherosa Ziehau 			version = (*next_record & E1000_INVM_VER_FIELD_TWO)
5454be59a01SSepherosa Ziehau 				  >> 13;
5464be59a01SSepherosa Ziehau 			status = E1000_SUCCESS;
5474be59a01SSepherosa Ziehau 			break;
5484be59a01SSepherosa Ziehau 		}
5494be59a01SSepherosa Ziehau 		/*
5504be59a01SSepherosa Ziehau 		 * Check if we have even version location
5514be59a01SSepherosa Ziehau 		 * used and it is the last one used
5524be59a01SSepherosa Ziehau 		 */
5534be59a01SSepherosa Ziehau 		else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
5544be59a01SSepherosa Ziehau 			 ((*record & 0x3) == 0)) {
5554be59a01SSepherosa Ziehau 			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
5564be59a01SSepherosa Ziehau 			status = E1000_SUCCESS;
5574be59a01SSepherosa Ziehau 			break;
5584be59a01SSepherosa Ziehau 		}
5594be59a01SSepherosa Ziehau 	}
5604be59a01SSepherosa Ziehau 
5614be59a01SSepherosa Ziehau 	if (status == E1000_SUCCESS) {
5624be59a01SSepherosa Ziehau 		invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
5634be59a01SSepherosa Ziehau 					>> E1000_INVM_MAJOR_SHIFT;
5644be59a01SSepherosa Ziehau 		invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
5654be59a01SSepherosa Ziehau 	}
5664be59a01SSepherosa Ziehau 	/* Read Image Type */
5674be59a01SSepherosa Ziehau 	for (i = 1; i < invm_blocks; i++) {
5684be59a01SSepherosa Ziehau 		record = &buffer[invm_blocks - i];
5694be59a01SSepherosa Ziehau 		next_record = &buffer[invm_blocks - i + 1];
5704be59a01SSepherosa Ziehau 
5714be59a01SSepherosa Ziehau 		/* Check if we have image type in first location used */
5724be59a01SSepherosa Ziehau 		if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
5734be59a01SSepherosa Ziehau 			invm_ver->invm_img_type = 0;
5744be59a01SSepherosa Ziehau 			status = E1000_SUCCESS;
5754be59a01SSepherosa Ziehau 			break;
5764be59a01SSepherosa Ziehau 		}
5774be59a01SSepherosa Ziehau 		/* Check if we have image type in first location used */
5784be59a01SSepherosa Ziehau 		else if ((((*record & 0x3) == 0) &&
5794be59a01SSepherosa Ziehau 			 ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
5804be59a01SSepherosa Ziehau 			 ((((*record & 0x3) != 0) && (i != 1)))) {
5814be59a01SSepherosa Ziehau 			invm_ver->invm_img_type =
5824be59a01SSepherosa Ziehau 				(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
5834be59a01SSepherosa Ziehau 			status = E1000_SUCCESS;
5844be59a01SSepherosa Ziehau 			break;
5854be59a01SSepherosa Ziehau 		}
5864be59a01SSepherosa Ziehau 	}
5874be59a01SSepherosa Ziehau 	return status;
5884be59a01SSepherosa Ziehau }
5894be59a01SSepherosa Ziehau 
5904be59a01SSepherosa Ziehau /**
5914be59a01SSepherosa Ziehau  *  e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum
5924be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
5934be59a01SSepherosa Ziehau  *
5944be59a01SSepherosa Ziehau  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
5954be59a01SSepherosa Ziehau  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
5964be59a01SSepherosa Ziehau  **/
e1000_validate_nvm_checksum_i210(struct e1000_hw * hw)5974be59a01SSepherosa Ziehau s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw)
5984be59a01SSepherosa Ziehau {
5994be59a01SSepherosa Ziehau 	s32 status = E1000_SUCCESS;
6004be59a01SSepherosa Ziehau 	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
6014be59a01SSepherosa Ziehau 
6024be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_validate_nvm_checksum_i210");
6034be59a01SSepherosa Ziehau 
6044be59a01SSepherosa Ziehau 	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
6054be59a01SSepherosa Ziehau 
6064be59a01SSepherosa Ziehau 		/*
6074be59a01SSepherosa Ziehau 		 * Replace the read function with semaphore grabbing with
6084be59a01SSepherosa Ziehau 		 * the one that skips this for a while.
6094be59a01SSepherosa Ziehau 		 * We have semaphore taken already here.
6104be59a01SSepherosa Ziehau 		 */
6114be59a01SSepherosa Ziehau 		read_op_ptr = hw->nvm.ops.read;
6124be59a01SSepherosa Ziehau 		hw->nvm.ops.read = e1000_read_nvm_eerd;
6134be59a01SSepherosa Ziehau 
6144be59a01SSepherosa Ziehau 		status = e1000_validate_nvm_checksum_generic(hw);
6154be59a01SSepherosa Ziehau 
6164be59a01SSepherosa Ziehau 		/* Revert original read operation. */
6174be59a01SSepherosa Ziehau 		hw->nvm.ops.read = read_op_ptr;
6184be59a01SSepherosa Ziehau 
6194be59a01SSepherosa Ziehau 		hw->nvm.ops.release(hw);
6204be59a01SSepherosa Ziehau 	} else {
6214be59a01SSepherosa Ziehau 		status = E1000_ERR_SWFW_SYNC;
6224be59a01SSepherosa Ziehau 	}
6234be59a01SSepherosa Ziehau 
6244be59a01SSepherosa Ziehau 	return status;
6254be59a01SSepherosa Ziehau }
6264be59a01SSepherosa Ziehau 
6274be59a01SSepherosa Ziehau 
6284be59a01SSepherosa Ziehau /**
6294be59a01SSepherosa Ziehau  *  e1000_update_nvm_checksum_i210 - Update EEPROM checksum
6304be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
6314be59a01SSepherosa Ziehau  *
6324be59a01SSepherosa Ziehau  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
6334be59a01SSepherosa Ziehau  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
6344be59a01SSepherosa Ziehau  *  value to the EEPROM. Next commit EEPROM data onto the Flash.
6354be59a01SSepherosa Ziehau  **/
e1000_update_nvm_checksum_i210(struct e1000_hw * hw)6364be59a01SSepherosa Ziehau s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw)
6374be59a01SSepherosa Ziehau {
638ba0123e0SSepherosa Ziehau 	s32 ret_val;
6394be59a01SSepherosa Ziehau 	u16 checksum = 0;
6404be59a01SSepherosa Ziehau 	u16 i, nvm_data;
6414be59a01SSepherosa Ziehau 
6424be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_update_nvm_checksum_i210");
6434be59a01SSepherosa Ziehau 
6444be59a01SSepherosa Ziehau 	/*
6454be59a01SSepherosa Ziehau 	 * Read the first word from the EEPROM. If this times out or fails, do
6464be59a01SSepherosa Ziehau 	 * not continue or we could be in for a very long wait while every
6474be59a01SSepherosa Ziehau 	 * EEPROM read fails
6484be59a01SSepherosa Ziehau 	 */
6494be59a01SSepherosa Ziehau 	ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);
6504be59a01SSepherosa Ziehau 	if (ret_val != E1000_SUCCESS) {
6514be59a01SSepherosa Ziehau 		DEBUGOUT("EEPROM read failed\n");
6524be59a01SSepherosa Ziehau 		goto out;
6534be59a01SSepherosa Ziehau 	}
6544be59a01SSepherosa Ziehau 
6554be59a01SSepherosa Ziehau 	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
6564be59a01SSepherosa Ziehau 		/*
6574be59a01SSepherosa Ziehau 		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
6584be59a01SSepherosa Ziehau 		 * because we do not want to take the synchronization
6594be59a01SSepherosa Ziehau 		 * semaphores twice here.
6604be59a01SSepherosa Ziehau 		 */
6614be59a01SSepherosa Ziehau 
6624be59a01SSepherosa Ziehau 		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
6634be59a01SSepherosa Ziehau 			ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);
6644be59a01SSepherosa Ziehau 			if (ret_val) {
6654be59a01SSepherosa Ziehau 				hw->nvm.ops.release(hw);
6664be59a01SSepherosa Ziehau 				DEBUGOUT("NVM Read Error while updating checksum.\n");
6674be59a01SSepherosa Ziehau 				goto out;
6684be59a01SSepherosa Ziehau 			}
6694be59a01SSepherosa Ziehau 			checksum += nvm_data;
6704be59a01SSepherosa Ziehau 		}
6714be59a01SSepherosa Ziehau 		checksum = (u16) NVM_SUM - checksum;
6724be59a01SSepherosa Ziehau 		ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
6734be59a01SSepherosa Ziehau 						&checksum);
6744be59a01SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS) {
6754be59a01SSepherosa Ziehau 			hw->nvm.ops.release(hw);
6764be59a01SSepherosa Ziehau 			DEBUGOUT("NVM Write Error while updating checksum.\n");
6774be59a01SSepherosa Ziehau 			goto out;
6784be59a01SSepherosa Ziehau 		}
6794be59a01SSepherosa Ziehau 
6804be59a01SSepherosa Ziehau 		hw->nvm.ops.release(hw);
6814be59a01SSepherosa Ziehau 
6824be59a01SSepherosa Ziehau 		ret_val = e1000_update_flash_i210(hw);
6834be59a01SSepherosa Ziehau 	} else {
6844be59a01SSepherosa Ziehau 		ret_val = E1000_ERR_SWFW_SYNC;
6854be59a01SSepherosa Ziehau 	}
6864be59a01SSepherosa Ziehau out:
6874be59a01SSepherosa Ziehau 	return ret_val;
6884be59a01SSepherosa Ziehau }
6894be59a01SSepherosa Ziehau 
6904be59a01SSepherosa Ziehau /**
6914be59a01SSepherosa Ziehau  *  e1000_get_flash_presence_i210 - Check if flash device is detected.
6924be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
6934be59a01SSepherosa Ziehau  *
6944be59a01SSepherosa Ziehau  **/
e1000_get_flash_presence_i210(struct e1000_hw * hw)695379ebbe7SSepherosa Ziehau bool e1000_get_flash_presence_i210(struct e1000_hw *hw)
6964be59a01SSepherosa Ziehau {
6974be59a01SSepherosa Ziehau 	u32 eec = 0;
6984be59a01SSepherosa Ziehau 	bool ret_val = FALSE;
6994be59a01SSepherosa Ziehau 
7004be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_get_flash_presence_i210");
7014be59a01SSepherosa Ziehau 
7024be59a01SSepherosa Ziehau 	eec = E1000_READ_REG(hw, E1000_EECD);
7034be59a01SSepherosa Ziehau 
7044be59a01SSepherosa Ziehau 	if (eec & E1000_EECD_FLASH_DETECTED_I210)
7054be59a01SSepherosa Ziehau 		ret_val = TRUE;
7064be59a01SSepherosa Ziehau 
7074be59a01SSepherosa Ziehau 	return ret_val;
7084be59a01SSepherosa Ziehau }
7094be59a01SSepherosa Ziehau 
7104be59a01SSepherosa Ziehau /**
7114be59a01SSepherosa Ziehau  *  e1000_update_flash_i210 - Commit EEPROM to the flash
7124be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
7134be59a01SSepherosa Ziehau  *
7144be59a01SSepherosa Ziehau  **/
e1000_update_flash_i210(struct e1000_hw * hw)7154be59a01SSepherosa Ziehau s32 e1000_update_flash_i210(struct e1000_hw *hw)
7164be59a01SSepherosa Ziehau {
717ba0123e0SSepherosa Ziehau 	s32 ret_val;
7184be59a01SSepherosa Ziehau 	u32 flup;
7194be59a01SSepherosa Ziehau 
7204be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_update_flash_i210");
7214be59a01SSepherosa Ziehau 
7224be59a01SSepherosa Ziehau 	ret_val = e1000_pool_flash_update_done_i210(hw);
7234be59a01SSepherosa Ziehau 	if (ret_val == -E1000_ERR_NVM) {
7244be59a01SSepherosa Ziehau 		DEBUGOUT("Flash update time out\n");
7254be59a01SSepherosa Ziehau 		goto out;
7264be59a01SSepherosa Ziehau 	}
7274be59a01SSepherosa Ziehau 
7284be59a01SSepherosa Ziehau 	flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210;
7294be59a01SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_EECD, flup);
7304be59a01SSepherosa Ziehau 
7314be59a01SSepherosa Ziehau 	ret_val = e1000_pool_flash_update_done_i210(hw);
7324be59a01SSepherosa Ziehau 	if (ret_val == E1000_SUCCESS)
7334be59a01SSepherosa Ziehau 		DEBUGOUT("Flash update complete\n");
7344be59a01SSepherosa Ziehau 	else
7354be59a01SSepherosa Ziehau 		DEBUGOUT("Flash update time out\n");
7364be59a01SSepherosa Ziehau 
7374be59a01SSepherosa Ziehau out:
7384be59a01SSepherosa Ziehau 	return ret_val;
7394be59a01SSepherosa Ziehau }
7404be59a01SSepherosa Ziehau 
7414be59a01SSepherosa Ziehau /**
7424be59a01SSepherosa Ziehau  *  e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
7434be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
7444be59a01SSepherosa Ziehau  *
7454be59a01SSepherosa Ziehau  **/
e1000_pool_flash_update_done_i210(struct e1000_hw * hw)7464be59a01SSepherosa Ziehau s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
7474be59a01SSepherosa Ziehau {
7484be59a01SSepherosa Ziehau 	s32 ret_val = -E1000_ERR_NVM;
7494be59a01SSepherosa Ziehau 	u32 i, reg;
7504be59a01SSepherosa Ziehau 
7514be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_pool_flash_update_done_i210");
7524be59a01SSepherosa Ziehau 
7534be59a01SSepherosa Ziehau 	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
7544be59a01SSepherosa Ziehau 		reg = E1000_READ_REG(hw, E1000_EECD);
7554be59a01SSepherosa Ziehau 		if (reg & E1000_EECD_FLUDONE_I210) {
7564be59a01SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
7574be59a01SSepherosa Ziehau 			break;
7584be59a01SSepherosa Ziehau 		}
7594be59a01SSepherosa Ziehau 		usec_delay(5);
7604be59a01SSepherosa Ziehau 	}
7614be59a01SSepherosa Ziehau 
7624be59a01SSepherosa Ziehau 	return ret_val;
7634be59a01SSepherosa Ziehau }
7644be59a01SSepherosa Ziehau 
7654be59a01SSepherosa Ziehau /**
7664be59a01SSepherosa Ziehau  *  e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers
7674be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
7684be59a01SSepherosa Ziehau  *
769379ebbe7SSepherosa Ziehau  *  Initialize the i210/i211 NVM parameters and function pointers.
7704be59a01SSepherosa Ziehau  **/
e1000_init_nvm_params_i210(struct e1000_hw * hw)7714be59a01SSepherosa Ziehau static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
7724be59a01SSepherosa Ziehau {
773ba0123e0SSepherosa Ziehau 	s32 ret_val;
7744be59a01SSepherosa Ziehau 	struct e1000_nvm_info *nvm = &hw->nvm;
7754be59a01SSepherosa Ziehau 
7764be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_init_nvm_params_i210");
7774be59a01SSepherosa Ziehau 
7784be59a01SSepherosa Ziehau 	ret_val = e1000_init_nvm_params_82575(hw);
7794be59a01SSepherosa Ziehau 	nvm->ops.acquire = e1000_acquire_nvm_i210;
7804be59a01SSepherosa Ziehau 	nvm->ops.release = e1000_release_nvm_i210;
781379ebbe7SSepherosa Ziehau 	nvm->ops.valid_led_default = e1000_valid_led_default_i210;
782379ebbe7SSepherosa Ziehau 	if (e1000_get_flash_presence_i210(hw)) {
783379ebbe7SSepherosa Ziehau 		hw->nvm.type = e1000_nvm_flash_hw;
7844be59a01SSepherosa Ziehau 		nvm->ops.read    = e1000_read_nvm_srrd_i210;
7854be59a01SSepherosa Ziehau 		nvm->ops.write   = e1000_write_nvm_srwr_i210;
7864be59a01SSepherosa Ziehau 		nvm->ops.validate = e1000_validate_nvm_checksum_i210;
7874be59a01SSepherosa Ziehau 		nvm->ops.update   = e1000_update_nvm_checksum_i210;
788379ebbe7SSepherosa Ziehau 	} else {
789379ebbe7SSepherosa Ziehau 		hw->nvm.type = e1000_nvm_invm;
790379ebbe7SSepherosa Ziehau 		nvm->ops.read     = e1000_read_invm_i210;
7914be59a01SSepherosa Ziehau 		nvm->ops.write    = e1000_null_write_nvm;
7924be59a01SSepherosa Ziehau 		nvm->ops.validate = e1000_null_ops_generic;
7934be59a01SSepherosa Ziehau 		nvm->ops.update   = e1000_null_ops_generic;
794379ebbe7SSepherosa Ziehau 	}
795379ebbe7SSepherosa Ziehau 	return ret_val;
7964be59a01SSepherosa Ziehau }
7974be59a01SSepherosa Ziehau 
7984be59a01SSepherosa Ziehau /**
7994be59a01SSepherosa Ziehau  *  e1000_init_function_pointers_i210 - Init func ptrs.
8004be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
8014be59a01SSepherosa Ziehau  *
8024be59a01SSepherosa Ziehau  *  Called to initialize all function pointers and parameters.
8034be59a01SSepherosa Ziehau  **/
e1000_init_function_pointers_i210(struct e1000_hw * hw)8044be59a01SSepherosa Ziehau void e1000_init_function_pointers_i210(struct e1000_hw *hw)
8054be59a01SSepherosa Ziehau {
8064be59a01SSepherosa Ziehau 	e1000_init_function_pointers_82575(hw);
807379ebbe7SSepherosa Ziehau 	hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
8084be59a01SSepherosa Ziehau 
8094be59a01SSepherosa Ziehau 	return;
8104be59a01SSepherosa Ziehau }
8114be59a01SSepherosa Ziehau 
8124be59a01SSepherosa Ziehau /**
8134be59a01SSepherosa Ziehau  *  e1000_valid_led_default_i210 - Verify a valid default LED config
8144be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
8154be59a01SSepherosa Ziehau  *  @data: pointer to the NVM (EEPROM)
8164be59a01SSepherosa Ziehau  *
8174be59a01SSepherosa Ziehau  *  Read the EEPROM for the current default LED configuration.  If the
8184be59a01SSepherosa Ziehau  *  LED configuration is not valid, set to a valid LED configuration.
8194be59a01SSepherosa Ziehau  **/
e1000_valid_led_default_i210(struct e1000_hw * hw,u16 * data)8204be59a01SSepherosa Ziehau static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
8214be59a01SSepherosa Ziehau {
8224be59a01SSepherosa Ziehau 	s32 ret_val;
8234be59a01SSepherosa Ziehau 
8244be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_valid_led_default_i210");
8254be59a01SSepherosa Ziehau 
8264be59a01SSepherosa Ziehau 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
8274be59a01SSepherosa Ziehau 	if (ret_val) {
8284be59a01SSepherosa Ziehau 		DEBUGOUT("NVM Read Error\n");
8294be59a01SSepherosa Ziehau 		goto out;
8304be59a01SSepherosa Ziehau 	}
8314be59a01SSepherosa Ziehau 
8324be59a01SSepherosa Ziehau 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
8334be59a01SSepherosa Ziehau 		switch (hw->phy.media_type) {
8344be59a01SSepherosa Ziehau 		case e1000_media_type_internal_serdes:
8354be59a01SSepherosa Ziehau 			*data = ID_LED_DEFAULT_I210_SERDES;
8364be59a01SSepherosa Ziehau 			break;
8374be59a01SSepherosa Ziehau 		case e1000_media_type_copper:
8384be59a01SSepherosa Ziehau 		default:
8394be59a01SSepherosa Ziehau 			*data = ID_LED_DEFAULT_I210;
8404be59a01SSepherosa Ziehau 			break;
8414be59a01SSepherosa Ziehau 		}
8424be59a01SSepherosa Ziehau 	}
8434be59a01SSepherosa Ziehau out:
8444be59a01SSepherosa Ziehau 	return ret_val;
8454be59a01SSepherosa Ziehau }
846379ebbe7SSepherosa Ziehau 
847379ebbe7SSepherosa Ziehau /**
848379ebbe7SSepherosa Ziehau  *  __e1000_access_xmdio_reg - Read/write XMDIO register
849379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
850379ebbe7SSepherosa Ziehau  *  @address: XMDIO address to program
851379ebbe7SSepherosa Ziehau  *  @dev_addr: device address to program
852379ebbe7SSepherosa Ziehau  *  @data: pointer to value to read/write from/to the XMDIO address
853379ebbe7SSepherosa Ziehau  *  @read: boolean flag to indicate read or write
854379ebbe7SSepherosa Ziehau  **/
__e1000_access_xmdio_reg(struct e1000_hw * hw,u16 address,u8 dev_addr,u16 * data,bool read)855379ebbe7SSepherosa Ziehau static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address,
856379ebbe7SSepherosa Ziehau 				    u8 dev_addr, u16 *data, bool read)
857379ebbe7SSepherosa Ziehau {
858ba0123e0SSepherosa Ziehau 	s32 ret_val;
859379ebbe7SSepherosa Ziehau 
860379ebbe7SSepherosa Ziehau 	DEBUGFUNC("__e1000_access_xmdio_reg");
861379ebbe7SSepherosa Ziehau 
862379ebbe7SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
863379ebbe7SSepherosa Ziehau 	if (ret_val)
864379ebbe7SSepherosa Ziehau 		return ret_val;
865379ebbe7SSepherosa Ziehau 
866379ebbe7SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
867379ebbe7SSepherosa Ziehau 	if (ret_val)
868379ebbe7SSepherosa Ziehau 		return ret_val;
869379ebbe7SSepherosa Ziehau 
870379ebbe7SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
871379ebbe7SSepherosa Ziehau 							 dev_addr);
872379ebbe7SSepherosa Ziehau 	if (ret_val)
873379ebbe7SSepherosa Ziehau 		return ret_val;
874379ebbe7SSepherosa Ziehau 
875379ebbe7SSepherosa Ziehau 	if (read)
876379ebbe7SSepherosa Ziehau 		ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
877379ebbe7SSepherosa Ziehau 	else
878379ebbe7SSepherosa Ziehau 		ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
879379ebbe7SSepherosa Ziehau 	if (ret_val)
880379ebbe7SSepherosa Ziehau 		return ret_val;
881379ebbe7SSepherosa Ziehau 
882379ebbe7SSepherosa Ziehau 	/* Recalibrate the device back to 0 */
883379ebbe7SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
884379ebbe7SSepherosa Ziehau 	if (ret_val)
885379ebbe7SSepherosa Ziehau 		return ret_val;
886379ebbe7SSepherosa Ziehau 
887379ebbe7SSepherosa Ziehau 	return ret_val;
888379ebbe7SSepherosa Ziehau }
889379ebbe7SSepherosa Ziehau 
890379ebbe7SSepherosa Ziehau /**
891379ebbe7SSepherosa Ziehau  *  e1000_read_xmdio_reg - Read XMDIO register
892379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
893379ebbe7SSepherosa Ziehau  *  @addr: XMDIO address to program
894379ebbe7SSepherosa Ziehau  *  @dev_addr: device address to program
895379ebbe7SSepherosa Ziehau  *  @data: value to be read from the EMI address
896379ebbe7SSepherosa Ziehau  **/
e1000_read_xmdio_reg(struct e1000_hw * hw,u16 addr,u8 dev_addr,u16 * data)897379ebbe7SSepherosa Ziehau s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
898379ebbe7SSepherosa Ziehau {
899379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_read_xmdio_reg");
900379ebbe7SSepherosa Ziehau 
901379ebbe7SSepherosa Ziehau 	return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, TRUE);
902379ebbe7SSepherosa Ziehau }
903379ebbe7SSepherosa Ziehau 
904379ebbe7SSepherosa Ziehau /**
905379ebbe7SSepherosa Ziehau  *  e1000_write_xmdio_reg - Write XMDIO register
906379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
907379ebbe7SSepherosa Ziehau  *  @addr: XMDIO address to program
908379ebbe7SSepherosa Ziehau  *  @dev_addr: device address to program
909379ebbe7SSepherosa Ziehau  *  @data: value to be written to the XMDIO address
910379ebbe7SSepherosa Ziehau  **/
e1000_write_xmdio_reg(struct e1000_hw * hw,u16 addr,u8 dev_addr,u16 data)911379ebbe7SSepherosa Ziehau s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
912379ebbe7SSepherosa Ziehau {
913379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_read_xmdio_reg");
914379ebbe7SSepherosa Ziehau 
915379ebbe7SSepherosa Ziehau 	return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, FALSE);
916379ebbe7SSepherosa Ziehau }
917ba0123e0SSepherosa Ziehau 
918ba0123e0SSepherosa Ziehau /**
919ba0123e0SSepherosa Ziehau  * e1000_pll_workaround_i210
920ba0123e0SSepherosa Ziehau  * @hw: pointer to the HW structure
921ba0123e0SSepherosa Ziehau  *
922ba0123e0SSepherosa Ziehau  * Works around an errata in the PLL circuit where it occasionally
923ba0123e0SSepherosa Ziehau  * provides the wrong clock frequency after power up.
924ba0123e0SSepherosa Ziehau  **/
e1000_pll_workaround_i210(struct e1000_hw * hw)925ba0123e0SSepherosa Ziehau static s32 e1000_pll_workaround_i210(struct e1000_hw *hw)
926ba0123e0SSepherosa Ziehau {
927ba0123e0SSepherosa Ziehau 	s32 ret_val;
928ba0123e0SSepherosa Ziehau 	u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
929ba0123e0SSepherosa Ziehau 	u16 nvm_word, phy_word, pci_word, tmp_nvm;
930ba0123e0SSepherosa Ziehau 	int i;
931ba0123e0SSepherosa Ziehau 
932ba0123e0SSepherosa Ziehau 	/* Get and set needed register values */
933ba0123e0SSepherosa Ziehau 	wuc = E1000_READ_REG(hw, E1000_WUC);
934ba0123e0SSepherosa Ziehau 	mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
935ba0123e0SSepherosa Ziehau 	reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;
936ba0123e0SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val);
937ba0123e0SSepherosa Ziehau 
938ba0123e0SSepherosa Ziehau 	/* Get data from NVM, or set default */
939ba0123e0SSepherosa Ziehau 	ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD,
940ba0123e0SSepherosa Ziehau 					    &nvm_word);
941ba0123e0SSepherosa Ziehau 	if (ret_val != E1000_SUCCESS)
942ba0123e0SSepherosa Ziehau 		nvm_word = E1000_INVM_DEFAULT_AL;
943ba0123e0SSepherosa Ziehau 	tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
944ba0123e0SSepherosa Ziehau 	for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
945ba0123e0SSepherosa Ziehau 		/* check current state directly from internal PHY */
946ba0123e0SSepherosa Ziehau 		e1000_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE |
947ba0123e0SSepherosa Ziehau 					 E1000_PHY_PLL_FREQ_REG), &phy_word);
948ba0123e0SSepherosa Ziehau 		if ((phy_word & E1000_PHY_PLL_UNCONF)
949ba0123e0SSepherosa Ziehau 		    != E1000_PHY_PLL_UNCONF) {
950ba0123e0SSepherosa Ziehau 			ret_val = E1000_SUCCESS;
951ba0123e0SSepherosa Ziehau 			break;
952ba0123e0SSepherosa Ziehau 		} else {
953ba0123e0SSepherosa Ziehau 			ret_val = -E1000_ERR_PHY;
954ba0123e0SSepherosa Ziehau 		}
955ba0123e0SSepherosa Ziehau 		/* directly reset the internal PHY */
956ba0123e0SSepherosa Ziehau 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
957ba0123e0SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl|E1000_CTRL_PHY_RST);
958ba0123e0SSepherosa Ziehau 
959ba0123e0SSepherosa Ziehau 		ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
960ba0123e0SSepherosa Ziehau 		ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);
961ba0123e0SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
962ba0123e0SSepherosa Ziehau 
963ba0123e0SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_WUC, 0);
964ba0123e0SSepherosa Ziehau 		reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
965ba0123e0SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val);
966ba0123e0SSepherosa Ziehau 
967ba0123e0SSepherosa Ziehau 		e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
968ba0123e0SSepherosa Ziehau 		pci_word |= E1000_PCI_PMCSR_D3;
969ba0123e0SSepherosa Ziehau 		e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
970ba0123e0SSepherosa Ziehau 		msec_delay(1);
971ba0123e0SSepherosa Ziehau 		pci_word &= ~E1000_PCI_PMCSR_D3;
972ba0123e0SSepherosa Ziehau 		e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
973ba0123e0SSepherosa Ziehau 		reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);
974ba0123e0SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val);
975ba0123e0SSepherosa Ziehau 
976ba0123e0SSepherosa Ziehau 		/* restore WUC register */
977ba0123e0SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_WUC, wuc);
978ba0123e0SSepherosa Ziehau 	}
979ba0123e0SSepherosa Ziehau 	/* restore MDICNFG setting */
980ba0123e0SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
981ba0123e0SSepherosa Ziehau 	return ret_val;
982ba0123e0SSepherosa Ziehau }
983ba0123e0SSepherosa Ziehau 
984ba0123e0SSepherosa Ziehau /**
985a40fda39SSepherosa Ziehau  *  e1000_get_cfg_done_i210 - Read config done bit
986a40fda39SSepherosa Ziehau  *  @hw: pointer to the HW structure
987a40fda39SSepherosa Ziehau  *
988a40fda39SSepherosa Ziehau  *  Read the management control register for the config done bit for
989a40fda39SSepherosa Ziehau  *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
990a40fda39SSepherosa Ziehau  *  to read the config done bit, so an error is *ONLY* logged and returns
991a40fda39SSepherosa Ziehau  *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
992a40fda39SSepherosa Ziehau  *  would not be able to be reset or change link.
993a40fda39SSepherosa Ziehau  **/
e1000_get_cfg_done_i210(struct e1000_hw * hw)994a40fda39SSepherosa Ziehau static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw)
995a40fda39SSepherosa Ziehau {
996a40fda39SSepherosa Ziehau 	s32 timeout = PHY_CFG_TIMEOUT;
997a40fda39SSepherosa Ziehau 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
998a40fda39SSepherosa Ziehau 
999a40fda39SSepherosa Ziehau 	DEBUGFUNC("e1000_get_cfg_done_i210");
1000a40fda39SSepherosa Ziehau 
1001a40fda39SSepherosa Ziehau 	while (timeout) {
1002a40fda39SSepherosa Ziehau 		if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask)
1003a40fda39SSepherosa Ziehau 			break;
1004a40fda39SSepherosa Ziehau 		msec_delay(1);
1005a40fda39SSepherosa Ziehau 		timeout--;
1006a40fda39SSepherosa Ziehau 	}
1007a40fda39SSepherosa Ziehau 	if (!timeout)
1008a40fda39SSepherosa Ziehau 		DEBUGOUT("MNG configuration cycle has not completed.\n");
1009a40fda39SSepherosa Ziehau 
1010a40fda39SSepherosa Ziehau 	return E1000_SUCCESS;
1011a40fda39SSepherosa Ziehau }
1012a40fda39SSepherosa Ziehau 
1013a40fda39SSepherosa Ziehau /**
1014ba0123e0SSepherosa Ziehau  *  e1000_init_hw_i210 - Init hw for I210/I211
1015ba0123e0SSepherosa Ziehau  *  @hw: pointer to the HW structure
1016ba0123e0SSepherosa Ziehau  *
1017ba0123e0SSepherosa Ziehau  *  Called to initialize hw for i210 hw family.
1018ba0123e0SSepherosa Ziehau  **/
e1000_init_hw_i210(struct e1000_hw * hw)1019ba0123e0SSepherosa Ziehau s32 e1000_init_hw_i210(struct e1000_hw *hw)
1020ba0123e0SSepherosa Ziehau {
1021ba0123e0SSepherosa Ziehau 	s32 ret_val;
1022ba0123e0SSepherosa Ziehau 
1023ba0123e0SSepherosa Ziehau 	DEBUGFUNC("e1000_init_hw_i210");
1024ba0123e0SSepherosa Ziehau 	if ((hw->mac.type >= e1000_i210) &&
1025ba0123e0SSepherosa Ziehau 	    !(e1000_get_flash_presence_i210(hw))) {
1026ba0123e0SSepherosa Ziehau 		ret_val = e1000_pll_workaround_i210(hw);
1027ba0123e0SSepherosa Ziehau 		if (ret_val != E1000_SUCCESS)
1028ba0123e0SSepherosa Ziehau 			return ret_val;
1029ba0123e0SSepherosa Ziehau 	}
1030a40fda39SSepherosa Ziehau 	hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210;
1031ba0123e0SSepherosa Ziehau 	ret_val = e1000_init_hw_82575(hw);
1032ba0123e0SSepherosa Ziehau 	return ret_val;
1033ba0123e0SSepherosa Ziehau }
1034