xref: /titanic_51/usr/src/uts/common/io/e1000api/e1000_i210.c (revision 42cc51e07cdbcad3b9aca8d9d991fc09b251feb7)
175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi 
3*42cc51e0SRobert Mustacchi   Copyright (c) 2001-2015, Intel Corporation
475eba5b6SRobert Mustacchi   All rights reserved.
575eba5b6SRobert Mustacchi 
675eba5b6SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
775eba5b6SRobert Mustacchi   modification, are permitted provided that the following conditions are met:
875eba5b6SRobert Mustacchi 
975eba5b6SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1075eba5b6SRobert Mustacchi       this list of conditions and the following disclaimer.
1175eba5b6SRobert Mustacchi 
1275eba5b6SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
1375eba5b6SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1475eba5b6SRobert Mustacchi       documentation and/or other materials provided with the distribution.
1575eba5b6SRobert Mustacchi 
1675eba5b6SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
1775eba5b6SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1875eba5b6SRobert Mustacchi       this software without specific prior written permission.
1975eba5b6SRobert Mustacchi 
2075eba5b6SRobert Mustacchi   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2175eba5b6SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2275eba5b6SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2375eba5b6SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2475eba5b6SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2575eba5b6SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2675eba5b6SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2775eba5b6SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2875eba5b6SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2975eba5b6SRobert Mustacchi   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3075eba5b6SRobert Mustacchi   POSSIBILITY OF SUCH DAMAGE.
3175eba5b6SRobert Mustacchi 
3275eba5b6SRobert Mustacchi ******************************************************************************/
3375eba5b6SRobert Mustacchi /*$FreeBSD$*/
3475eba5b6SRobert Mustacchi 
3575eba5b6SRobert Mustacchi #include "e1000_api.h"
3675eba5b6SRobert Mustacchi 
3775eba5b6SRobert Mustacchi 
3875eba5b6SRobert Mustacchi static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw);
3975eba5b6SRobert Mustacchi static void e1000_release_nvm_i210(struct e1000_hw *hw);
4075eba5b6SRobert Mustacchi static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw);
4175eba5b6SRobert Mustacchi static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
4275eba5b6SRobert Mustacchi 				u16 *data);
4375eba5b6SRobert Mustacchi static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
4475eba5b6SRobert Mustacchi static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
4575eba5b6SRobert Mustacchi 
4675eba5b6SRobert Mustacchi /**
4775eba5b6SRobert Mustacchi  *  e1000_acquire_nvm_i210 - Request for access to EEPROM
4875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
4975eba5b6SRobert Mustacchi  *
5075eba5b6SRobert Mustacchi  *  Acquire the necessary semaphores for exclusive access to the EEPROM.
5175eba5b6SRobert Mustacchi  *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
5275eba5b6SRobert Mustacchi  *  Return successful if access grant bit set, else clear the request for
5375eba5b6SRobert Mustacchi  *  EEPROM access and return -E1000_ERR_NVM (-1).
5475eba5b6SRobert Mustacchi  **/
5575eba5b6SRobert Mustacchi static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw)
5675eba5b6SRobert Mustacchi {
5775eba5b6SRobert Mustacchi 	s32 ret_val;
5875eba5b6SRobert Mustacchi 
5975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_nvm_i210");
6075eba5b6SRobert Mustacchi 
6175eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
6275eba5b6SRobert Mustacchi 
6375eba5b6SRobert Mustacchi 	return ret_val;
6475eba5b6SRobert Mustacchi }
6575eba5b6SRobert Mustacchi 
6675eba5b6SRobert Mustacchi /**
6775eba5b6SRobert Mustacchi  *  e1000_release_nvm_i210 - Release exclusive access to EEPROM
6875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
6975eba5b6SRobert Mustacchi  *
7075eba5b6SRobert Mustacchi  *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
7175eba5b6SRobert Mustacchi  *  then release the semaphores acquired.
7275eba5b6SRobert Mustacchi  **/
7375eba5b6SRobert Mustacchi static void e1000_release_nvm_i210(struct e1000_hw *hw)
7475eba5b6SRobert Mustacchi {
7575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_nvm_i210");
7675eba5b6SRobert Mustacchi 
7775eba5b6SRobert Mustacchi 	e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
7875eba5b6SRobert Mustacchi }
7975eba5b6SRobert Mustacchi 
8075eba5b6SRobert Mustacchi /**
8175eba5b6SRobert Mustacchi  *  e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
8275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
8375eba5b6SRobert Mustacchi  *  @mask: specifies which semaphore to acquire
8475eba5b6SRobert Mustacchi  *
8575eba5b6SRobert Mustacchi  *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
8675eba5b6SRobert Mustacchi  *  will also specify which port we're acquiring the lock for.
8775eba5b6SRobert Mustacchi  **/
8875eba5b6SRobert Mustacchi s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
8975eba5b6SRobert Mustacchi {
9075eba5b6SRobert Mustacchi 	u32 swfw_sync;
9175eba5b6SRobert Mustacchi 	u32 swmask = mask;
9275eba5b6SRobert Mustacchi 	u32 fwmask = mask << 16;
9375eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
9475eba5b6SRobert Mustacchi 	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
9575eba5b6SRobert Mustacchi 
9675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_swfw_sync_i210");
9775eba5b6SRobert Mustacchi 
9875eba5b6SRobert Mustacchi 	while (i < timeout) {
9975eba5b6SRobert Mustacchi 		if (e1000_get_hw_semaphore_i210(hw)) {
10075eba5b6SRobert Mustacchi 			ret_val = -E1000_ERR_SWFW_SYNC;
10175eba5b6SRobert Mustacchi 			goto out;
10275eba5b6SRobert Mustacchi 		}
10375eba5b6SRobert Mustacchi 
10475eba5b6SRobert Mustacchi 		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
10575eba5b6SRobert Mustacchi 		if (!(swfw_sync & (fwmask | swmask)))
10675eba5b6SRobert Mustacchi 			break;
10775eba5b6SRobert Mustacchi 
10875eba5b6SRobert Mustacchi 		/*
10975eba5b6SRobert Mustacchi 		 * Firmware currently using resource (fwmask)
11075eba5b6SRobert Mustacchi 		 * or other software thread using resource (swmask)
11175eba5b6SRobert Mustacchi 		 */
11275eba5b6SRobert Mustacchi 		e1000_put_hw_semaphore_generic(hw);
11375eba5b6SRobert Mustacchi 		msec_delay_irq(5);
11475eba5b6SRobert Mustacchi 		i++;
11575eba5b6SRobert Mustacchi 	}
11675eba5b6SRobert Mustacchi 
11775eba5b6SRobert Mustacchi 	if (i == timeout) {
11875eba5b6SRobert Mustacchi 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
11975eba5b6SRobert Mustacchi 		ret_val = -E1000_ERR_SWFW_SYNC;
12075eba5b6SRobert Mustacchi 		goto out;
12175eba5b6SRobert Mustacchi 	}
12275eba5b6SRobert Mustacchi 
12375eba5b6SRobert Mustacchi 	swfw_sync |= swmask;
12475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
12575eba5b6SRobert Mustacchi 
12675eba5b6SRobert Mustacchi 	e1000_put_hw_semaphore_generic(hw);
12775eba5b6SRobert Mustacchi 
12875eba5b6SRobert Mustacchi out:
12975eba5b6SRobert Mustacchi 	return ret_val;
13075eba5b6SRobert Mustacchi }
13175eba5b6SRobert Mustacchi 
13275eba5b6SRobert Mustacchi /**
13375eba5b6SRobert Mustacchi  *  e1000_release_swfw_sync_i210 - Release SW/FW semaphore
13475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
13575eba5b6SRobert Mustacchi  *  @mask: specifies which semaphore to acquire
13675eba5b6SRobert Mustacchi  *
13775eba5b6SRobert Mustacchi  *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
13875eba5b6SRobert Mustacchi  *  will also specify which port we're releasing the lock for.
13975eba5b6SRobert Mustacchi  **/
14075eba5b6SRobert Mustacchi void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
14175eba5b6SRobert Mustacchi {
14275eba5b6SRobert Mustacchi 	u32 swfw_sync;
14375eba5b6SRobert Mustacchi 
14475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_swfw_sync_i210");
14575eba5b6SRobert Mustacchi 
14675eba5b6SRobert Mustacchi 	while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
14775eba5b6SRobert Mustacchi 		; /* Empty */
14875eba5b6SRobert Mustacchi 
14975eba5b6SRobert Mustacchi 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
15075eba5b6SRobert Mustacchi 	swfw_sync &= ~mask;
15175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
15275eba5b6SRobert Mustacchi 
15375eba5b6SRobert Mustacchi 	e1000_put_hw_semaphore_generic(hw);
15475eba5b6SRobert Mustacchi }
15575eba5b6SRobert Mustacchi 
15675eba5b6SRobert Mustacchi /**
15775eba5b6SRobert Mustacchi  *  e1000_get_hw_semaphore_i210 - Acquire hardware semaphore
15875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
15975eba5b6SRobert Mustacchi  *
16075eba5b6SRobert Mustacchi  *  Acquire the HW semaphore to access the PHY or NVM
16175eba5b6SRobert Mustacchi  **/
16275eba5b6SRobert Mustacchi static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
16375eba5b6SRobert Mustacchi {
16475eba5b6SRobert Mustacchi 	u32 swsm;
16575eba5b6SRobert Mustacchi 	s32 timeout = hw->nvm.word_size + 1;
16675eba5b6SRobert Mustacchi 	s32 i = 0;
16775eba5b6SRobert Mustacchi 
16875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_hw_semaphore_i210");
16975eba5b6SRobert Mustacchi 
17075eba5b6SRobert Mustacchi 	/* Get the SW semaphore */
17175eba5b6SRobert Mustacchi 	while (i < timeout) {
17275eba5b6SRobert Mustacchi 		swsm = E1000_READ_REG(hw, E1000_SWSM);
17375eba5b6SRobert Mustacchi 		if (!(swsm & E1000_SWSM_SMBI))
17475eba5b6SRobert Mustacchi 			break;
17575eba5b6SRobert Mustacchi 
17675eba5b6SRobert Mustacchi 		usec_delay(50);
17775eba5b6SRobert Mustacchi 		i++;
17875eba5b6SRobert Mustacchi 	}
17975eba5b6SRobert Mustacchi 
18075eba5b6SRobert Mustacchi 	if (i == timeout) {
181c124a83eSRobert Mustacchi 		/* In rare circumstances, the SW semaphore may already be held
182c124a83eSRobert Mustacchi 		 * unintentionally. Clear the semaphore once before giving up.
18375eba5b6SRobert Mustacchi 		 */
18475eba5b6SRobert Mustacchi 		if (hw->dev_spec._82575.clear_semaphore_once) {
18575eba5b6SRobert Mustacchi 			hw->dev_spec._82575.clear_semaphore_once = FALSE;
18675eba5b6SRobert Mustacchi 			e1000_put_hw_semaphore_generic(hw);
18775eba5b6SRobert Mustacchi 			for (i = 0; i < timeout; i++) {
18875eba5b6SRobert Mustacchi 				swsm = E1000_READ_REG(hw, E1000_SWSM);
18975eba5b6SRobert Mustacchi 				if (!(swsm & E1000_SWSM_SMBI))
19075eba5b6SRobert Mustacchi 					break;
19175eba5b6SRobert Mustacchi 
19275eba5b6SRobert Mustacchi 				usec_delay(50);
19375eba5b6SRobert Mustacchi 			}
19475eba5b6SRobert Mustacchi 		}
19575eba5b6SRobert Mustacchi 
19675eba5b6SRobert Mustacchi 		/* If we do not have the semaphore here, we have to give up. */
19775eba5b6SRobert Mustacchi 		if (i == timeout) {
19875eba5b6SRobert Mustacchi 			DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
19975eba5b6SRobert Mustacchi 			return -E1000_ERR_NVM;
20075eba5b6SRobert Mustacchi 		}
20175eba5b6SRobert Mustacchi 	}
20275eba5b6SRobert Mustacchi 
20375eba5b6SRobert Mustacchi 	/* Get the FW semaphore. */
20475eba5b6SRobert Mustacchi 	for (i = 0; i < timeout; i++) {
20575eba5b6SRobert Mustacchi 		swsm = E1000_READ_REG(hw, E1000_SWSM);
20675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
20775eba5b6SRobert Mustacchi 
20875eba5b6SRobert Mustacchi 		/* Semaphore acquired if bit latched */
20975eba5b6SRobert Mustacchi 		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
21075eba5b6SRobert Mustacchi 			break;
21175eba5b6SRobert Mustacchi 
21275eba5b6SRobert Mustacchi 		usec_delay(50);
21375eba5b6SRobert Mustacchi 	}
21475eba5b6SRobert Mustacchi 
21575eba5b6SRobert Mustacchi 	if (i == timeout) {
21675eba5b6SRobert Mustacchi 		/* Release semaphores */
21775eba5b6SRobert Mustacchi 		e1000_put_hw_semaphore_generic(hw);
21875eba5b6SRobert Mustacchi 		DEBUGOUT("Driver can't access the NVM\n");
21975eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
22075eba5b6SRobert Mustacchi 	}
22175eba5b6SRobert Mustacchi 
22275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
22375eba5b6SRobert Mustacchi }
22475eba5b6SRobert Mustacchi 
22575eba5b6SRobert Mustacchi /**
22675eba5b6SRobert Mustacchi  *  e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
22775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
22875eba5b6SRobert Mustacchi  *  @offset: offset of word in the Shadow Ram to read
22975eba5b6SRobert Mustacchi  *  @words: number of words to read
23075eba5b6SRobert Mustacchi  *  @data: word read from the Shadow Ram
23175eba5b6SRobert Mustacchi  *
23275eba5b6SRobert Mustacchi  *  Reads a 16 bit word from the Shadow Ram using the EERD register.
23375eba5b6SRobert Mustacchi  *  Uses necessary synchronization semaphores.
23475eba5b6SRobert Mustacchi  **/
23575eba5b6SRobert Mustacchi s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
23675eba5b6SRobert Mustacchi 			     u16 *data)
23775eba5b6SRobert Mustacchi {
23875eba5b6SRobert Mustacchi 	s32 status = E1000_SUCCESS;
23975eba5b6SRobert Mustacchi 	u16 i, count;
24075eba5b6SRobert Mustacchi 
24175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_nvm_srrd_i210");
24275eba5b6SRobert Mustacchi 
24375eba5b6SRobert Mustacchi 	/* We cannot hold synchronization semaphores for too long,
24475eba5b6SRobert Mustacchi 	 * because of forceful takeover procedure. However it is more efficient
24575eba5b6SRobert Mustacchi 	 * to read in bursts than synchronizing access for each word. */
24675eba5b6SRobert Mustacchi 	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
24775eba5b6SRobert Mustacchi 		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
24875eba5b6SRobert Mustacchi 			E1000_EERD_EEWR_MAX_COUNT : (words - i);
24975eba5b6SRobert Mustacchi 		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
25075eba5b6SRobert Mustacchi 			status = e1000_read_nvm_eerd(hw, offset, count,
25175eba5b6SRobert Mustacchi 						     data + i);
25275eba5b6SRobert Mustacchi 			hw->nvm.ops.release(hw);
25375eba5b6SRobert Mustacchi 		} else {
25475eba5b6SRobert Mustacchi 			status = E1000_ERR_SWFW_SYNC;
25575eba5b6SRobert Mustacchi 		}
25675eba5b6SRobert Mustacchi 
25775eba5b6SRobert Mustacchi 		if (status != E1000_SUCCESS)
25875eba5b6SRobert Mustacchi 			break;
25975eba5b6SRobert Mustacchi 	}
26075eba5b6SRobert Mustacchi 
26175eba5b6SRobert Mustacchi 	return status;
26275eba5b6SRobert Mustacchi }
26375eba5b6SRobert Mustacchi 
26475eba5b6SRobert Mustacchi /**
26575eba5b6SRobert Mustacchi  *  e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
26675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
26775eba5b6SRobert Mustacchi  *  @offset: offset within the Shadow RAM to be written to
26875eba5b6SRobert Mustacchi  *  @words: number of words to write
26975eba5b6SRobert Mustacchi  *  @data: 16 bit word(s) to be written to the Shadow RAM
27075eba5b6SRobert Mustacchi  *
27175eba5b6SRobert Mustacchi  *  Writes data to Shadow RAM at offset using EEWR register.
27275eba5b6SRobert Mustacchi  *
27375eba5b6SRobert Mustacchi  *  If e1000_update_nvm_checksum is not called after this function , the
27475eba5b6SRobert Mustacchi  *  data will not be committed to FLASH and also Shadow RAM will most likely
27575eba5b6SRobert Mustacchi  *  contain an invalid checksum.
27675eba5b6SRobert Mustacchi  *
27775eba5b6SRobert Mustacchi  *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
27875eba5b6SRobert Mustacchi  *  partially written.
27975eba5b6SRobert Mustacchi  **/
28075eba5b6SRobert Mustacchi s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
28175eba5b6SRobert Mustacchi 			      u16 *data)
28275eba5b6SRobert Mustacchi {
28375eba5b6SRobert Mustacchi 	s32 status = E1000_SUCCESS;
28475eba5b6SRobert Mustacchi 	u16 i, count;
28575eba5b6SRobert Mustacchi 
28675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_nvm_srwr_i210");
28775eba5b6SRobert Mustacchi 
28875eba5b6SRobert Mustacchi 	/* We cannot hold synchronization semaphores for too long,
28975eba5b6SRobert Mustacchi 	 * because of forceful takeover procedure. However it is more efficient
29075eba5b6SRobert Mustacchi 	 * to write in bursts than synchronizing access for each word. */
29175eba5b6SRobert Mustacchi 	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
29275eba5b6SRobert Mustacchi 		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
29375eba5b6SRobert Mustacchi 			E1000_EERD_EEWR_MAX_COUNT : (words - i);
29475eba5b6SRobert Mustacchi 		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
29575eba5b6SRobert Mustacchi 			status = e1000_write_nvm_srwr(hw, offset, count,
29675eba5b6SRobert Mustacchi 						      data + i);
29775eba5b6SRobert Mustacchi 			hw->nvm.ops.release(hw);
29875eba5b6SRobert Mustacchi 		} else {
29975eba5b6SRobert Mustacchi 			status = E1000_ERR_SWFW_SYNC;
30075eba5b6SRobert Mustacchi 		}
30175eba5b6SRobert Mustacchi 
30275eba5b6SRobert Mustacchi 		if (status != E1000_SUCCESS)
30375eba5b6SRobert Mustacchi 			break;
30475eba5b6SRobert Mustacchi 	}
30575eba5b6SRobert Mustacchi 
30675eba5b6SRobert Mustacchi 	return status;
30775eba5b6SRobert Mustacchi }
30875eba5b6SRobert Mustacchi 
30975eba5b6SRobert Mustacchi /**
31075eba5b6SRobert Mustacchi  *  e1000_write_nvm_srwr - Write to Shadow Ram using EEWR
31175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
31275eba5b6SRobert Mustacchi  *  @offset: offset within the Shadow Ram to be written to
31375eba5b6SRobert Mustacchi  *  @words: number of words to write
31475eba5b6SRobert Mustacchi  *  @data: 16 bit word(s) to be written to the Shadow Ram
31575eba5b6SRobert Mustacchi  *
31675eba5b6SRobert Mustacchi  *  Writes data to Shadow Ram at offset using EEWR register.
31775eba5b6SRobert Mustacchi  *
31875eba5b6SRobert Mustacchi  *  If e1000_update_nvm_checksum is not called after this function , the
31975eba5b6SRobert Mustacchi  *  Shadow Ram will most likely contain an invalid checksum.
32075eba5b6SRobert Mustacchi  **/
32175eba5b6SRobert Mustacchi static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
32275eba5b6SRobert Mustacchi 				u16 *data)
32375eba5b6SRobert Mustacchi {
32475eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
32575eba5b6SRobert Mustacchi 	u32 i, k, eewr = 0;
32675eba5b6SRobert Mustacchi 	u32 attempts = 100000;
32775eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
32875eba5b6SRobert Mustacchi 
32975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_nvm_srwr");
33075eba5b6SRobert Mustacchi 
33175eba5b6SRobert Mustacchi 	/*
33275eba5b6SRobert Mustacchi 	 * A check for invalid values:  offset too large, too many words,
33375eba5b6SRobert Mustacchi 	 * too many words for the offset, and not enough words.
33475eba5b6SRobert Mustacchi 	 */
33575eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
33675eba5b6SRobert Mustacchi 	    (words == 0)) {
33775eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
33875eba5b6SRobert Mustacchi 		ret_val = -E1000_ERR_NVM;
33975eba5b6SRobert Mustacchi 		goto out;
34075eba5b6SRobert Mustacchi 	}
34175eba5b6SRobert Mustacchi 
34275eba5b6SRobert Mustacchi 	for (i = 0; i < words; i++) {
34375eba5b6SRobert Mustacchi 		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
34475eba5b6SRobert Mustacchi 			(data[i] << E1000_NVM_RW_REG_DATA) |
34575eba5b6SRobert Mustacchi 			E1000_NVM_RW_REG_START;
34675eba5b6SRobert Mustacchi 
34775eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_SRWR, eewr);
34875eba5b6SRobert Mustacchi 
34975eba5b6SRobert Mustacchi 		for (k = 0; k < attempts; k++) {
35075eba5b6SRobert Mustacchi 			if (E1000_NVM_RW_REG_DONE &
35175eba5b6SRobert Mustacchi 			    E1000_READ_REG(hw, E1000_SRWR)) {
35275eba5b6SRobert Mustacchi 				ret_val = E1000_SUCCESS;
35375eba5b6SRobert Mustacchi 				break;
35475eba5b6SRobert Mustacchi 			}
35575eba5b6SRobert Mustacchi 			usec_delay(5);
35675eba5b6SRobert Mustacchi 		}
35775eba5b6SRobert Mustacchi 
35875eba5b6SRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
35975eba5b6SRobert Mustacchi 			DEBUGOUT("Shadow RAM write EEWR timed out\n");
36075eba5b6SRobert Mustacchi 			break;
36175eba5b6SRobert Mustacchi 		}
36275eba5b6SRobert Mustacchi 	}
36375eba5b6SRobert Mustacchi 
36475eba5b6SRobert Mustacchi out:
36575eba5b6SRobert Mustacchi 	return ret_val;
36675eba5b6SRobert Mustacchi }
36775eba5b6SRobert Mustacchi 
368c124a83eSRobert Mustacchi /** e1000_read_invm_word_i210 - Reads OTP
36975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
37075eba5b6SRobert Mustacchi  *  @address: the word address (aka eeprom offset) to read
37175eba5b6SRobert Mustacchi  *  @data: pointer to the data read
37275eba5b6SRobert Mustacchi  *
37375eba5b6SRobert Mustacchi  *  Reads 16-bit words from the OTP. Return error when the word is not
37475eba5b6SRobert Mustacchi  *  stored in OTP.
37575eba5b6SRobert Mustacchi  **/
376c124a83eSRobert Mustacchi static s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
37775eba5b6SRobert Mustacchi {
37875eba5b6SRobert Mustacchi 	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
37975eba5b6SRobert Mustacchi 	u32 invm_dword;
38075eba5b6SRobert Mustacchi 	u16 i;
38175eba5b6SRobert Mustacchi 	u8 record_type, word_address;
38275eba5b6SRobert Mustacchi 
383c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_read_invm_word_i210");
38475eba5b6SRobert Mustacchi 
38575eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_INVM_SIZE; i++) {
38675eba5b6SRobert Mustacchi 		invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
38775eba5b6SRobert Mustacchi 		/* Get record type */
38875eba5b6SRobert Mustacchi 		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
38975eba5b6SRobert Mustacchi 		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
39075eba5b6SRobert Mustacchi 			break;
39175eba5b6SRobert Mustacchi 		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
39275eba5b6SRobert Mustacchi 			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
39375eba5b6SRobert Mustacchi 		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
39475eba5b6SRobert Mustacchi 			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
39575eba5b6SRobert Mustacchi 		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
39675eba5b6SRobert Mustacchi 			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
39775eba5b6SRobert Mustacchi 			if (word_address == address) {
39875eba5b6SRobert Mustacchi 				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
39975eba5b6SRobert Mustacchi 				DEBUGOUT2("Read INVM Word 0x%02x = %x",
40075eba5b6SRobert Mustacchi 					  address, *data);
40175eba5b6SRobert Mustacchi 				status = E1000_SUCCESS;
40275eba5b6SRobert Mustacchi 				break;
40375eba5b6SRobert Mustacchi 			}
40475eba5b6SRobert Mustacchi 		}
40575eba5b6SRobert Mustacchi 	}
40675eba5b6SRobert Mustacchi 	if (status != E1000_SUCCESS)
40775eba5b6SRobert Mustacchi 		DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address);
40875eba5b6SRobert Mustacchi 	return status;
40975eba5b6SRobert Mustacchi }
41075eba5b6SRobert Mustacchi 
411c124a83eSRobert Mustacchi /** e1000_read_invm_i210 - Read invm wrapper function for I210/I211
412c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
413c124a83eSRobert Mustacchi  *  @address: the word address (aka eeprom offset) to read
414c124a83eSRobert Mustacchi  *  @data: pointer to the data read
415c124a83eSRobert Mustacchi  *
416c124a83eSRobert Mustacchi  *  Wrapper function to return data formerly found in the NVM.
417c124a83eSRobert Mustacchi  **/
418c124a83eSRobert Mustacchi static s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset,
419c124a83eSRobert Mustacchi 				u16 E1000_UNUSEDARG words, u16 *data)
420c124a83eSRobert Mustacchi {
421c124a83eSRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
422c124a83eSRobert Mustacchi 
423c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_read_invm_i210");
424c124a83eSRobert Mustacchi 
425c124a83eSRobert Mustacchi 	/* Only the MAC addr is required to be present in the iNVM */
426c124a83eSRobert Mustacchi 	switch (offset) {
427c124a83eSRobert Mustacchi 	case NVM_MAC_ADDR:
428c124a83eSRobert Mustacchi 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]);
429c124a83eSRobert Mustacchi 		ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1,
430c124a83eSRobert Mustacchi 						     &data[1]);
431c124a83eSRobert Mustacchi 		ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2,
432c124a83eSRobert Mustacchi 						     &data[2]);
433c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS)
434c124a83eSRobert Mustacchi 			DEBUGOUT("MAC Addr not found in iNVM\n");
435c124a83eSRobert Mustacchi 		break;
436c124a83eSRobert Mustacchi 	case NVM_INIT_CTRL_2:
437c124a83eSRobert Mustacchi 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
438c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
439c124a83eSRobert Mustacchi 			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
440c124a83eSRobert Mustacchi 			ret_val = E1000_SUCCESS;
441c124a83eSRobert Mustacchi 		}
442c124a83eSRobert Mustacchi 		break;
443c124a83eSRobert Mustacchi 	case NVM_INIT_CTRL_4:
444c124a83eSRobert Mustacchi 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
445c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
446c124a83eSRobert Mustacchi 			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
447c124a83eSRobert Mustacchi 			ret_val = E1000_SUCCESS;
448c124a83eSRobert Mustacchi 		}
449c124a83eSRobert Mustacchi 		break;
450c124a83eSRobert Mustacchi 	case NVM_LED_1_CFG:
451c124a83eSRobert Mustacchi 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
452c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
453c124a83eSRobert Mustacchi 			*data = NVM_LED_1_CFG_DEFAULT_I211;
454c124a83eSRobert Mustacchi 			ret_val = E1000_SUCCESS;
455c124a83eSRobert Mustacchi 		}
456c124a83eSRobert Mustacchi 		break;
457c124a83eSRobert Mustacchi 	case NVM_LED_0_2_CFG:
458c124a83eSRobert Mustacchi 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
459c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
460c124a83eSRobert Mustacchi 			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
461c124a83eSRobert Mustacchi 			ret_val = E1000_SUCCESS;
462c124a83eSRobert Mustacchi 		}
463c124a83eSRobert Mustacchi 		break;
464c124a83eSRobert Mustacchi 	case NVM_ID_LED_SETTINGS:
465c124a83eSRobert Mustacchi 		ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
466c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
467c124a83eSRobert Mustacchi 			*data = ID_LED_RESERVED_FFFF;
468c124a83eSRobert Mustacchi 			ret_val = E1000_SUCCESS;
469c124a83eSRobert Mustacchi 		}
470c124a83eSRobert Mustacchi 		break;
471c124a83eSRobert Mustacchi 	case NVM_SUB_DEV_ID:
472c124a83eSRobert Mustacchi 		*data = hw->subsystem_device_id;
473c124a83eSRobert Mustacchi 		break;
474c124a83eSRobert Mustacchi 	case NVM_SUB_VEN_ID:
475c124a83eSRobert Mustacchi 		*data = hw->subsystem_vendor_id;
476c124a83eSRobert Mustacchi 		break;
477c124a83eSRobert Mustacchi 	case NVM_DEV_ID:
478c124a83eSRobert Mustacchi 		*data = hw->device_id;
479c124a83eSRobert Mustacchi 		break;
480c124a83eSRobert Mustacchi 	case NVM_VEN_ID:
481c124a83eSRobert Mustacchi 		*data = hw->vendor_id;
482c124a83eSRobert Mustacchi 		break;
483c124a83eSRobert Mustacchi 	default:
484c124a83eSRobert Mustacchi 		DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
485c124a83eSRobert Mustacchi 		*data = NVM_RESERVED_WORD;
486c124a83eSRobert Mustacchi 		break;
487c124a83eSRobert Mustacchi 	}
488c124a83eSRobert Mustacchi 	return ret_val;
489c124a83eSRobert Mustacchi }
490c124a83eSRobert Mustacchi 
49175eba5b6SRobert Mustacchi /**
49275eba5b6SRobert Mustacchi  *  e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum
49375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
49475eba5b6SRobert Mustacchi  *
49575eba5b6SRobert Mustacchi  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
49675eba5b6SRobert Mustacchi  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
49775eba5b6SRobert Mustacchi  **/
49875eba5b6SRobert Mustacchi s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw)
49975eba5b6SRobert Mustacchi {
50075eba5b6SRobert Mustacchi 	s32 status = E1000_SUCCESS;
50175eba5b6SRobert Mustacchi 	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
50275eba5b6SRobert Mustacchi 
50375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_validate_nvm_checksum_i210");
50475eba5b6SRobert Mustacchi 
50575eba5b6SRobert Mustacchi 	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
50675eba5b6SRobert Mustacchi 
50775eba5b6SRobert Mustacchi 		/*
50875eba5b6SRobert Mustacchi 		 * Replace the read function with semaphore grabbing with
50975eba5b6SRobert Mustacchi 		 * the one that skips this for a while.
51075eba5b6SRobert Mustacchi 		 * We have semaphore taken already here.
51175eba5b6SRobert Mustacchi 		 */
51275eba5b6SRobert Mustacchi 		read_op_ptr = hw->nvm.ops.read;
51375eba5b6SRobert Mustacchi 		hw->nvm.ops.read = e1000_read_nvm_eerd;
51475eba5b6SRobert Mustacchi 
51575eba5b6SRobert Mustacchi 		status = e1000_validate_nvm_checksum_generic(hw);
51675eba5b6SRobert Mustacchi 
51775eba5b6SRobert Mustacchi 		/* Revert original read operation. */
51875eba5b6SRobert Mustacchi 		hw->nvm.ops.read = read_op_ptr;
51975eba5b6SRobert Mustacchi 
52075eba5b6SRobert Mustacchi 		hw->nvm.ops.release(hw);
52175eba5b6SRobert Mustacchi 	} else {
52275eba5b6SRobert Mustacchi 		status = E1000_ERR_SWFW_SYNC;
52375eba5b6SRobert Mustacchi 	}
52475eba5b6SRobert Mustacchi 
52575eba5b6SRobert Mustacchi 	return status;
52675eba5b6SRobert Mustacchi }
52775eba5b6SRobert Mustacchi 
52875eba5b6SRobert Mustacchi 
52975eba5b6SRobert Mustacchi /**
53075eba5b6SRobert Mustacchi  *  e1000_update_nvm_checksum_i210 - Update EEPROM checksum
53175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
53275eba5b6SRobert Mustacchi  *
53375eba5b6SRobert Mustacchi  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
53475eba5b6SRobert Mustacchi  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
53575eba5b6SRobert Mustacchi  *  value to the EEPROM. Next commit EEPROM data onto the Flash.
53675eba5b6SRobert Mustacchi  **/
53775eba5b6SRobert Mustacchi s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw)
53875eba5b6SRobert Mustacchi {
539c124a83eSRobert Mustacchi 	s32 ret_val;
54075eba5b6SRobert Mustacchi 	u16 checksum = 0;
54175eba5b6SRobert Mustacchi 	u16 i, nvm_data;
54275eba5b6SRobert Mustacchi 
54375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_update_nvm_checksum_i210");
54475eba5b6SRobert Mustacchi 
54575eba5b6SRobert Mustacchi 	/*
54675eba5b6SRobert Mustacchi 	 * Read the first word from the EEPROM. If this times out or fails, do
54775eba5b6SRobert Mustacchi 	 * not continue or we could be in for a very long wait while every
54875eba5b6SRobert Mustacchi 	 * EEPROM read fails
54975eba5b6SRobert Mustacchi 	 */
55075eba5b6SRobert Mustacchi 	ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);
55175eba5b6SRobert Mustacchi 	if (ret_val != E1000_SUCCESS) {
55275eba5b6SRobert Mustacchi 		DEBUGOUT("EEPROM read failed\n");
55375eba5b6SRobert Mustacchi 		goto out;
55475eba5b6SRobert Mustacchi 	}
55575eba5b6SRobert Mustacchi 
55675eba5b6SRobert Mustacchi 	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
55775eba5b6SRobert Mustacchi 		/*
55875eba5b6SRobert Mustacchi 		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
55975eba5b6SRobert Mustacchi 		 * because we do not want to take the synchronization
56075eba5b6SRobert Mustacchi 		 * semaphores twice here.
56175eba5b6SRobert Mustacchi 		 */
56275eba5b6SRobert Mustacchi 
56375eba5b6SRobert Mustacchi 		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
56475eba5b6SRobert Mustacchi 			ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);
56575eba5b6SRobert Mustacchi 			if (ret_val) {
56675eba5b6SRobert Mustacchi 				hw->nvm.ops.release(hw);
56775eba5b6SRobert Mustacchi 				DEBUGOUT("NVM Read Error while updating checksum.\n");
56875eba5b6SRobert Mustacchi 				goto out;
56975eba5b6SRobert Mustacchi 			}
57075eba5b6SRobert Mustacchi 			checksum += nvm_data;
57175eba5b6SRobert Mustacchi 		}
57275eba5b6SRobert Mustacchi 		checksum = (u16) NVM_SUM - checksum;
57375eba5b6SRobert Mustacchi 		ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
57475eba5b6SRobert Mustacchi 						&checksum);
57575eba5b6SRobert Mustacchi 		if (ret_val != E1000_SUCCESS) {
57675eba5b6SRobert Mustacchi 			hw->nvm.ops.release(hw);
57775eba5b6SRobert Mustacchi 			DEBUGOUT("NVM Write Error while updating checksum.\n");
57875eba5b6SRobert Mustacchi 			goto out;
57975eba5b6SRobert Mustacchi 		}
58075eba5b6SRobert Mustacchi 
58175eba5b6SRobert Mustacchi 		hw->nvm.ops.release(hw);
58275eba5b6SRobert Mustacchi 
58375eba5b6SRobert Mustacchi 		ret_val = e1000_update_flash_i210(hw);
58475eba5b6SRobert Mustacchi 	} else {
58575eba5b6SRobert Mustacchi 		ret_val = E1000_ERR_SWFW_SYNC;
58675eba5b6SRobert Mustacchi 	}
58775eba5b6SRobert Mustacchi out:
58875eba5b6SRobert Mustacchi 	return ret_val;
58975eba5b6SRobert Mustacchi }
59075eba5b6SRobert Mustacchi 
59175eba5b6SRobert Mustacchi /**
592c124a83eSRobert Mustacchi  *  e1000_get_flash_presence_i210 - Check if flash device is detected.
593c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
594c124a83eSRobert Mustacchi  *
595c124a83eSRobert Mustacchi  **/
596c124a83eSRobert Mustacchi bool e1000_get_flash_presence_i210(struct e1000_hw *hw)
597c124a83eSRobert Mustacchi {
598c124a83eSRobert Mustacchi 	u32 eec = 0;
599c124a83eSRobert Mustacchi 	bool ret_val = FALSE;
600c124a83eSRobert Mustacchi 
601c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_get_flash_presence_i210");
602c124a83eSRobert Mustacchi 
603c124a83eSRobert Mustacchi 	eec = E1000_READ_REG(hw, E1000_EECD);
604c124a83eSRobert Mustacchi 
605c124a83eSRobert Mustacchi 	if (eec & E1000_EECD_FLASH_DETECTED_I210)
606c124a83eSRobert Mustacchi 		ret_val = TRUE;
607c124a83eSRobert Mustacchi 
608c124a83eSRobert Mustacchi 	return ret_val;
609c124a83eSRobert Mustacchi }
610c124a83eSRobert Mustacchi 
611c124a83eSRobert Mustacchi /**
61275eba5b6SRobert Mustacchi  *  e1000_update_flash_i210 - Commit EEPROM to the flash
61375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
61475eba5b6SRobert Mustacchi  *
61575eba5b6SRobert Mustacchi  **/
61675eba5b6SRobert Mustacchi s32 e1000_update_flash_i210(struct e1000_hw *hw)
61775eba5b6SRobert Mustacchi {
618c124a83eSRobert Mustacchi 	s32 ret_val;
61975eba5b6SRobert Mustacchi 	u32 flup;
62075eba5b6SRobert Mustacchi 
62175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_update_flash_i210");
62275eba5b6SRobert Mustacchi 
62375eba5b6SRobert Mustacchi 	ret_val = e1000_pool_flash_update_done_i210(hw);
62475eba5b6SRobert Mustacchi 	if (ret_val == -E1000_ERR_NVM) {
62575eba5b6SRobert Mustacchi 		DEBUGOUT("Flash update time out\n");
62675eba5b6SRobert Mustacchi 		goto out;
62775eba5b6SRobert Mustacchi 	}
62875eba5b6SRobert Mustacchi 
62975eba5b6SRobert Mustacchi 	flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210;
63075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EECD, flup);
63175eba5b6SRobert Mustacchi 
63275eba5b6SRobert Mustacchi 	ret_val = e1000_pool_flash_update_done_i210(hw);
63375eba5b6SRobert Mustacchi 	if (ret_val == E1000_SUCCESS)
63475eba5b6SRobert Mustacchi 		DEBUGOUT("Flash update complete\n");
63575eba5b6SRobert Mustacchi 	else
63675eba5b6SRobert Mustacchi 		DEBUGOUT("Flash update time out\n");
63775eba5b6SRobert Mustacchi 
63875eba5b6SRobert Mustacchi out:
63975eba5b6SRobert Mustacchi 	return ret_val;
64075eba5b6SRobert Mustacchi }
64175eba5b6SRobert Mustacchi 
64275eba5b6SRobert Mustacchi /**
64375eba5b6SRobert Mustacchi  *  e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
64475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
64575eba5b6SRobert Mustacchi  *
64675eba5b6SRobert Mustacchi  **/
64775eba5b6SRobert Mustacchi s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
64875eba5b6SRobert Mustacchi {
64975eba5b6SRobert Mustacchi 	s32 ret_val = -E1000_ERR_NVM;
65075eba5b6SRobert Mustacchi 	u32 i, reg;
65175eba5b6SRobert Mustacchi 
65275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_pool_flash_update_done_i210");
65375eba5b6SRobert Mustacchi 
65475eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
65575eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_EECD);
65675eba5b6SRobert Mustacchi 		if (reg & E1000_EECD_FLUDONE_I210) {
65775eba5b6SRobert Mustacchi 			ret_val = E1000_SUCCESS;
65875eba5b6SRobert Mustacchi 			break;
65975eba5b6SRobert Mustacchi 		}
66075eba5b6SRobert Mustacchi 		usec_delay(5);
66175eba5b6SRobert Mustacchi 	}
66275eba5b6SRobert Mustacchi 
66375eba5b6SRobert Mustacchi 	return ret_val;
66475eba5b6SRobert Mustacchi }
66575eba5b6SRobert Mustacchi 
66675eba5b6SRobert Mustacchi /**
66775eba5b6SRobert Mustacchi  *  e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers
66875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
66975eba5b6SRobert Mustacchi  *
670c124a83eSRobert Mustacchi  *  Initialize the i210/i211 NVM parameters and function pointers.
67175eba5b6SRobert Mustacchi  **/
67275eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
67375eba5b6SRobert Mustacchi {
674c124a83eSRobert Mustacchi 	s32 ret_val;
67575eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
67675eba5b6SRobert Mustacchi 
67775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_nvm_params_i210");
67875eba5b6SRobert Mustacchi 
67975eba5b6SRobert Mustacchi 	ret_val = e1000_init_nvm_params_82575(hw);
68075eba5b6SRobert Mustacchi 	nvm->ops.acquire = e1000_acquire_nvm_i210;
68175eba5b6SRobert Mustacchi 	nvm->ops.release = e1000_release_nvm_i210;
682c124a83eSRobert Mustacchi 	nvm->ops.valid_led_default = e1000_valid_led_default_i210;
683c124a83eSRobert Mustacchi 	if (e1000_get_flash_presence_i210(hw)) {
684c124a83eSRobert Mustacchi 		hw->nvm.type = e1000_nvm_flash_hw;
68575eba5b6SRobert Mustacchi 		nvm->ops.read    = e1000_read_nvm_srrd_i210;
68675eba5b6SRobert Mustacchi 		nvm->ops.write   = e1000_write_nvm_srwr_i210;
68775eba5b6SRobert Mustacchi 		nvm->ops.validate = e1000_validate_nvm_checksum_i210;
68875eba5b6SRobert Mustacchi 		nvm->ops.update   = e1000_update_nvm_checksum_i210;
689c124a83eSRobert Mustacchi 	} else {
690c124a83eSRobert Mustacchi 		hw->nvm.type = e1000_nvm_invm;
691c124a83eSRobert Mustacchi 		nvm->ops.read     = e1000_read_invm_i210;
69275eba5b6SRobert Mustacchi 		nvm->ops.write    = e1000_null_write_nvm;
69375eba5b6SRobert Mustacchi 		nvm->ops.validate = e1000_null_ops_generic;
69475eba5b6SRobert Mustacchi 		nvm->ops.update   = e1000_null_ops_generic;
695c124a83eSRobert Mustacchi 	}
696c124a83eSRobert Mustacchi 	return ret_val;
69775eba5b6SRobert Mustacchi }
69875eba5b6SRobert Mustacchi 
69975eba5b6SRobert Mustacchi /**
70075eba5b6SRobert Mustacchi  *  e1000_init_function_pointers_i210 - Init func ptrs.
70175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
70275eba5b6SRobert Mustacchi  *
70375eba5b6SRobert Mustacchi  *  Called to initialize all function pointers and parameters.
70475eba5b6SRobert Mustacchi  **/
70575eba5b6SRobert Mustacchi void e1000_init_function_pointers_i210(struct e1000_hw *hw)
70675eba5b6SRobert Mustacchi {
70775eba5b6SRobert Mustacchi 	e1000_init_function_pointers_82575(hw);
70875eba5b6SRobert Mustacchi 	hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
709c124a83eSRobert Mustacchi 
71075eba5b6SRobert Mustacchi 	return;
71175eba5b6SRobert Mustacchi }
71275eba5b6SRobert Mustacchi 
71375eba5b6SRobert Mustacchi /**
71475eba5b6SRobert Mustacchi  *  e1000_valid_led_default_i210 - Verify a valid default LED config
71575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
71675eba5b6SRobert Mustacchi  *  @data: pointer to the NVM (EEPROM)
71775eba5b6SRobert Mustacchi  *
71875eba5b6SRobert Mustacchi  *  Read the EEPROM for the current default LED configuration.  If the
71975eba5b6SRobert Mustacchi  *  LED configuration is not valid, set to a valid LED configuration.
72075eba5b6SRobert Mustacchi  **/
72175eba5b6SRobert Mustacchi static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
72275eba5b6SRobert Mustacchi {
72375eba5b6SRobert Mustacchi 	s32 ret_val;
72475eba5b6SRobert Mustacchi 
72575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_valid_led_default_i210");
72675eba5b6SRobert Mustacchi 
72775eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
72875eba5b6SRobert Mustacchi 	if (ret_val) {
72975eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
73075eba5b6SRobert Mustacchi 		goto out;
73175eba5b6SRobert Mustacchi 	}
73275eba5b6SRobert Mustacchi 
73375eba5b6SRobert Mustacchi 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
73475eba5b6SRobert Mustacchi 		switch (hw->phy.media_type) {
73575eba5b6SRobert Mustacchi 		case e1000_media_type_internal_serdes:
73675eba5b6SRobert Mustacchi 			*data = ID_LED_DEFAULT_I210_SERDES;
73775eba5b6SRobert Mustacchi 			break;
73875eba5b6SRobert Mustacchi 		case e1000_media_type_copper:
73975eba5b6SRobert Mustacchi 		default:
74075eba5b6SRobert Mustacchi 			*data = ID_LED_DEFAULT_I210;
74175eba5b6SRobert Mustacchi 			break;
74275eba5b6SRobert Mustacchi 		}
74375eba5b6SRobert Mustacchi 	}
74475eba5b6SRobert Mustacchi out:
74575eba5b6SRobert Mustacchi 	return ret_val;
74675eba5b6SRobert Mustacchi }
74713485e69SGarrett D'Amore 
74813485e69SGarrett D'Amore /**
74913485e69SGarrett D'Amore  *  __e1000_access_xmdio_reg - Read/write XMDIO register
75013485e69SGarrett D'Amore  *  @hw: pointer to the HW structure
75113485e69SGarrett D'Amore  *  @address: XMDIO address to program
75213485e69SGarrett D'Amore  *  @dev_addr: device address to program
75313485e69SGarrett D'Amore  *  @data: pointer to value to read/write from/to the XMDIO address
75413485e69SGarrett D'Amore  *  @read: boolean flag to indicate read or write
75513485e69SGarrett D'Amore  **/
75613485e69SGarrett D'Amore static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address,
75713485e69SGarrett D'Amore 				    u8 dev_addr, u16 *data, bool read)
75813485e69SGarrett D'Amore {
759c124a83eSRobert Mustacchi 	s32 ret_val;
76013485e69SGarrett D'Amore 
76113485e69SGarrett D'Amore 	DEBUGFUNC("__e1000_access_xmdio_reg");
76213485e69SGarrett D'Amore 
76313485e69SGarrett D'Amore 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
76413485e69SGarrett D'Amore 	if (ret_val)
76513485e69SGarrett D'Amore 		return ret_val;
76613485e69SGarrett D'Amore 
76713485e69SGarrett D'Amore 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
76813485e69SGarrett D'Amore 	if (ret_val)
76913485e69SGarrett D'Amore 		return ret_val;
77013485e69SGarrett D'Amore 
77113485e69SGarrett D'Amore 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
77213485e69SGarrett D'Amore 							 dev_addr);
77313485e69SGarrett D'Amore 	if (ret_val)
77413485e69SGarrett D'Amore 		return ret_val;
77513485e69SGarrett D'Amore 
77613485e69SGarrett D'Amore 	if (read)
77713485e69SGarrett D'Amore 		ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
77813485e69SGarrett D'Amore 	else
77913485e69SGarrett D'Amore 		ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
78013485e69SGarrett D'Amore 	if (ret_val)
78113485e69SGarrett D'Amore 		return ret_val;
78213485e69SGarrett D'Amore 
78313485e69SGarrett D'Amore 	/* Recalibrate the device back to 0 */
78413485e69SGarrett D'Amore 	ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
78513485e69SGarrett D'Amore 	if (ret_val)
78613485e69SGarrett D'Amore 		return ret_val;
78713485e69SGarrett D'Amore 
78813485e69SGarrett D'Amore 	return ret_val;
78913485e69SGarrett D'Amore }
79013485e69SGarrett D'Amore 
79113485e69SGarrett D'Amore /**
79213485e69SGarrett D'Amore  *  e1000_read_xmdio_reg - Read XMDIO register
79313485e69SGarrett D'Amore  *  @hw: pointer to the HW structure
79413485e69SGarrett D'Amore  *  @addr: XMDIO address to program
79513485e69SGarrett D'Amore  *  @dev_addr: device address to program
79613485e69SGarrett D'Amore  *  @data: value to be read from the EMI address
79713485e69SGarrett D'Amore  **/
79813485e69SGarrett D'Amore s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
79913485e69SGarrett D'Amore {
80013485e69SGarrett D'Amore 	DEBUGFUNC("e1000_read_xmdio_reg");
80113485e69SGarrett D'Amore 
80213485e69SGarrett D'Amore 	return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, TRUE);
80313485e69SGarrett D'Amore }
80413485e69SGarrett D'Amore 
80513485e69SGarrett D'Amore /**
80613485e69SGarrett D'Amore  *  e1000_write_xmdio_reg - Write XMDIO register
80713485e69SGarrett D'Amore  *  @hw: pointer to the HW structure
80813485e69SGarrett D'Amore  *  @addr: XMDIO address to program
80913485e69SGarrett D'Amore  *  @dev_addr: device address to program
81013485e69SGarrett D'Amore  *  @data: value to be written to the XMDIO address
81113485e69SGarrett D'Amore  **/
81213485e69SGarrett D'Amore s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
81313485e69SGarrett D'Amore {
81413485e69SGarrett D'Amore 	DEBUGFUNC("e1000_read_xmdio_reg");
81513485e69SGarrett D'Amore 
81613485e69SGarrett D'Amore 	return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, FALSE);
81713485e69SGarrett D'Amore }
81813485e69SGarrett D'Amore 
819c124a83eSRobert Mustacchi /**
820c124a83eSRobert Mustacchi  * e1000_pll_workaround_i210
821c124a83eSRobert Mustacchi  * @hw: pointer to the HW structure
822c124a83eSRobert Mustacchi  *
823c124a83eSRobert Mustacchi  * Works around an errata in the PLL circuit where it occasionally
824c124a83eSRobert Mustacchi  * provides the wrong clock frequency after power up.
825c124a83eSRobert Mustacchi  **/
826c124a83eSRobert Mustacchi static s32 e1000_pll_workaround_i210(struct e1000_hw *hw)
827c124a83eSRobert Mustacchi {
828c124a83eSRobert Mustacchi 	s32 ret_val;
829c124a83eSRobert Mustacchi 	u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
830c124a83eSRobert Mustacchi 	u16 nvm_word, phy_word, pci_word, tmp_nvm;
831c124a83eSRobert Mustacchi 	int i;
83213485e69SGarrett D'Amore 
833c124a83eSRobert Mustacchi 	/* Get and set needed register values */
834c124a83eSRobert Mustacchi 	wuc = E1000_READ_REG(hw, E1000_WUC);
835c124a83eSRobert Mustacchi 	mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
836c124a83eSRobert Mustacchi 	reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;
837c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val);
838c124a83eSRobert Mustacchi 
839c124a83eSRobert Mustacchi 	/* Get data from NVM, or set default */
840c124a83eSRobert Mustacchi 	ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD,
841c124a83eSRobert Mustacchi 					    &nvm_word);
842c124a83eSRobert Mustacchi 	if (ret_val != E1000_SUCCESS)
843c124a83eSRobert Mustacchi 		nvm_word = E1000_INVM_DEFAULT_AL;
844c124a83eSRobert Mustacchi 	tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
845c124a83eSRobert Mustacchi 	for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
846c124a83eSRobert Mustacchi 		/* check current state directly from internal PHY */
847c124a83eSRobert Mustacchi 		e1000_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE |
848c124a83eSRobert Mustacchi 					 E1000_PHY_PLL_FREQ_REG), &phy_word);
849c124a83eSRobert Mustacchi 		if ((phy_word & E1000_PHY_PLL_UNCONF)
850c124a83eSRobert Mustacchi 		    != E1000_PHY_PLL_UNCONF) {
851c124a83eSRobert Mustacchi 			ret_val = E1000_SUCCESS;
852c124a83eSRobert Mustacchi 			break;
853c124a83eSRobert Mustacchi 		} else {
854c124a83eSRobert Mustacchi 			ret_val = -E1000_ERR_PHY;
855c124a83eSRobert Mustacchi 		}
856c124a83eSRobert Mustacchi 		/* directly reset the internal PHY */
857c124a83eSRobert Mustacchi 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
858c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl|E1000_CTRL_PHY_RST);
859c124a83eSRobert Mustacchi 
860c124a83eSRobert Mustacchi 		ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
861c124a83eSRobert Mustacchi 		ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);
862c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
863c124a83eSRobert Mustacchi 
864c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_WUC, 0);
865c124a83eSRobert Mustacchi 		reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
866c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val);
867c124a83eSRobert Mustacchi 
868c124a83eSRobert Mustacchi 		e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
869c124a83eSRobert Mustacchi 		pci_word |= E1000_PCI_PMCSR_D3;
870c124a83eSRobert Mustacchi 		e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
871c124a83eSRobert Mustacchi 		msec_delay(1);
872c124a83eSRobert Mustacchi 		pci_word &= ~E1000_PCI_PMCSR_D3;
873c124a83eSRobert Mustacchi 		e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
874c124a83eSRobert Mustacchi 		reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);
875c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val);
876c124a83eSRobert Mustacchi 
877c124a83eSRobert Mustacchi 		/* restore WUC register */
878c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_WUC, wuc);
879c124a83eSRobert Mustacchi 	}
880c124a83eSRobert Mustacchi 	/* restore MDICNFG setting */
881c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
882c124a83eSRobert Mustacchi 	return ret_val;
883c124a83eSRobert Mustacchi }
884c124a83eSRobert Mustacchi 
885c124a83eSRobert Mustacchi /**
886*42cc51e0SRobert Mustacchi  *  e1000_get_cfg_done_i210 - Read config done bit
887*42cc51e0SRobert Mustacchi  *  @hw: pointer to the HW structure
888*42cc51e0SRobert Mustacchi  *
889*42cc51e0SRobert Mustacchi  *  Read the management control register for the config done bit for
890*42cc51e0SRobert Mustacchi  *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
891*42cc51e0SRobert Mustacchi  *  to read the config done bit, so an error is *ONLY* logged and returns
892*42cc51e0SRobert Mustacchi  *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
893*42cc51e0SRobert Mustacchi  *  would not be able to be reset or change link.
894*42cc51e0SRobert Mustacchi  **/
895*42cc51e0SRobert Mustacchi static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw)
896*42cc51e0SRobert Mustacchi {
897*42cc51e0SRobert Mustacchi 	s32 timeout = PHY_CFG_TIMEOUT;
898*42cc51e0SRobert Mustacchi 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
899*42cc51e0SRobert Mustacchi 
900*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_get_cfg_done_i210");
901*42cc51e0SRobert Mustacchi 
902*42cc51e0SRobert Mustacchi 	while (timeout) {
903*42cc51e0SRobert Mustacchi 		if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask)
904*42cc51e0SRobert Mustacchi 			break;
905*42cc51e0SRobert Mustacchi 		msec_delay(1);
906*42cc51e0SRobert Mustacchi 		timeout--;
907*42cc51e0SRobert Mustacchi 	}
908*42cc51e0SRobert Mustacchi 	if (!timeout)
909*42cc51e0SRobert Mustacchi 		DEBUGOUT("MNG configuration cycle has not completed.\n");
910*42cc51e0SRobert Mustacchi 
911*42cc51e0SRobert Mustacchi 	return E1000_SUCCESS;
912*42cc51e0SRobert Mustacchi }
913*42cc51e0SRobert Mustacchi 
914*42cc51e0SRobert Mustacchi /**
915c124a83eSRobert Mustacchi  *  e1000_init_hw_i210 - Init hw for I210/I211
916c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
917c124a83eSRobert Mustacchi  *
918c124a83eSRobert Mustacchi  *  Called to initialize hw for i210 hw family.
919c124a83eSRobert Mustacchi  **/
920c124a83eSRobert Mustacchi s32 e1000_init_hw_i210(struct e1000_hw *hw)
921c124a83eSRobert Mustacchi {
922c124a83eSRobert Mustacchi 	s32 ret_val;
923c124a83eSRobert Mustacchi 
924c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_init_hw_i210");
925c124a83eSRobert Mustacchi 	if ((hw->mac.type >= e1000_i210) &&
926c124a83eSRobert Mustacchi 	    !(e1000_get_flash_presence_i210(hw))) {
927c124a83eSRobert Mustacchi 		ret_val = e1000_pll_workaround_i210(hw);
928c124a83eSRobert Mustacchi 		if (ret_val != E1000_SUCCESS)
929c124a83eSRobert Mustacchi 			return ret_val;
930c124a83eSRobert Mustacchi 	}
931*42cc51e0SRobert Mustacchi 	hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210;
932c124a83eSRobert Mustacchi 	ret_val = e1000_init_hw_82575(hw);
933c124a83eSRobert Mustacchi 	return ret_val;
934c124a83eSRobert Mustacchi }
935