75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/******************************************************************************
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi Copyright (c) 2001-2015, Intel Corporation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi All rights reserved.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi Redistribution and use in source and binary forms, with or without
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi modification, are permitted provided that the following conditions are met:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 1. Redistributions of source code must retain the above copyright notice,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi this list of conditions and the following disclaimer.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 2. Redistributions in binary form must reproduce the above copyright
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi notice, this list of conditions and the following disclaimer in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi documentation and/or other materials provided with the distribution.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi contributors may be used to endorse or promote products derived from
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi this software without specific prior written permission.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi POSSIBILITY OF SUCH DAMAGE.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi******************************************************************************/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/*$FreeBSD$*/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi#include "e1000_api.h"
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic void e1000_reload_nvm_generic(struct e1000_hw *hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_init_nvm_ops_generic - Initialize NVM function pointers
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Setups up the function pointers to no-op functions
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_init_nvm_ops_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_init_nvm_ops_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Initialize function pointers */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.init_params = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.acquire = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.read = e1000_null_read_nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.release = e1000_null_nvm_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.reload = e1000_reload_nvm_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.update = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.valid_led_default = e1000_null_led_default;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.validate = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.write = e1000_null_write_nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_nvm_read - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 E1000_UNUSEDARG *c)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_read_nvm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_nvm_generic - No-op function, return void
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchivoid e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_nvm_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_led_default - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 E1000_UNUSEDARG *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_led_default");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_write_nvm - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 E1000_UNUSEDARG *c)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_write_nvm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_raise_eec_clk - Raise EEPROM clock
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eecd: pointer to the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Enable/Raise the EEPROM clock bit.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *eecd = *eecd | E1000_EECD_SK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, *eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(hw->nvm.delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_lower_eec_clk - Lower EEPROM clock
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eecd: pointer to the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Clear/Lower the EEPROM clock bit.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *eecd = *eecd & ~E1000_EECD_SK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, *eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(hw->nvm.delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to send to the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @count: number of bits to shift out
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * We need to shift 'count' bits out to the EEPROM. So, the value in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * "data" parameter will be shifted out to the EEPROM one bit at a time.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * In order to do this, "data" must be broken down into bits.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_shift_out_eec_bits");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = 0x01 << (count - 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (nvm->type == e1000_nvm_eeprom_microwire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_DO;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (nvm->type == e1000_nvm_eeprom_spi)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd |= E1000_EECD_DO;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi do {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_DI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (data & mask)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd |= E1000_EECD_DI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(nvm->delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_raise_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_lower_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask >>= 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } while (mask);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_DI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @count: number of bits to shift in
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * In order to read a register from the EEPROM, we need to shift 'count' bits
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in from the EEPROM. Bits are "shifted in" by raising the clock input to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the EEPROM (setting the SK bit), and then reading the value of the data out
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * "DO" bit. During this "shifting in" process the data in "DI" bit should
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * always be clear.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_shift_in_eec_bits");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < count; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data <<= 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_raise_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_DI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eecd & E1000_EECD_DO)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data |= 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_lower_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @ee_reg: EEPROM flag for polling
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Polls the EEPROM status bit for either read or write completion based
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * upon the value of 'ee_reg'.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 attempts = 100000;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i, reg = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_poll_eerd_eewr_done");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < attempts; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ee_reg == E1000_NVM_POLL_READ)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi reg = E1000_READ_REG(hw, E1000_EERD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi reg = E1000_READ_REG(hw, E1000_EEWR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (reg & E1000_NVM_RW_REG_DONE)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(5);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_acquire_nvm_generic - Generic request for access to EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Set the EEPROM access request bit and wait for EEPROM access grant bit.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Return successful if access grant bit set, else clear the request for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * EEPROM access and return -E1000_ERR_NVM (-1).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_acquire_nvm_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi while (timeout) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eecd & E1000_EECD_GNT)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(5);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi timeout--;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!timeout) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_REQ;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Could not acquire NVM grant\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_standby_nvm - Return EEPROM to standby state
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Return the EEPROM to a standby state.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic void e1000_standby_nvm(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_standby_nvm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (nvm->type == e1000_nvm_eeprom_microwire) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(nvm->delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_raise_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Select EEPROM */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd |= E1000_EECD_CS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(nvm->delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_lower_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if (nvm->type == e1000_nvm_eeprom_spi) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Toggle CS to flush commands */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd |= E1000_EECD_CS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(nvm->delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_CS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(nvm->delay_usec);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_stop_nvm - Terminate EEPROM command
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Terminates the current command by inverting the EEPROM's chip select pin.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_stop_nvm(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_stop_nvm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->nvm.type == e1000_nvm_eeprom_spi) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Pull CS high */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd |= E1000_EECD_CS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_lower_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* CS on Microwire is active-high */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_raise_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_lower_eec_clk(hw, &eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_release_nvm_generic - Release exclusive access to EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Stop any current commands to the EEPROM and clear the EEPROM request bit.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_release_nvm_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_release_nvm_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_stop_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~E1000_EECD_REQ;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Setups the EEPROM for reading and writing.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 spi_stat_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_ready_nvm_eeprom");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (nvm->type == e1000_nvm_eeprom_microwire) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Clear SK and DI */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set CS */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd |= E1000_EECD_CS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if (nvm->type == e1000_nvm_eeprom_spi) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 timeout = NVM_MAX_RETRY_SPI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Clear SK and CS */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EECD, eecd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read "Status Register" repeatedly until the LSB is cleared.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * The EEPROM will signal that the command has been completed
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * by clearing bit 0 of the internal status register. If it's
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * not cleared within 'timeout', then error out.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi while (timeout) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->nvm.opcode_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(5);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi timeout--;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!timeout) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("SPI NVM Status error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_nvm_spi - Read EEPROM's using SPI
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: offset of word in the EEPROM to read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @words: number of words to read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: word read from the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads a 16 bit word from the EEPROM.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 word_in;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 read_opcode = NVM_READ_OPCODE_SPI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_nvm_spi");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* A check for invalid values: offset too large, too many words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and not enough words.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (words == 0)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = nvm->ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_ready_nvm_eeprom(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((nvm->address_bits == 8) && (offset >= 128))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi read_opcode |= NVM_A8_OPCODE_SPI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Send the READ command (opcode + addr) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read the data. SPI NVMs increment the address with each byte
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * read and will roll over if reading beyond the end. This allows
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * us to read the whole NVM from any offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < words; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi word_in = e1000_shift_in_eec_bits(hw, 16);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data[i] = (word_in >> 8) | (word_in << 8);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_nvm_microwire - Reads EEPROM's using microwire
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: offset of word in the EEPROM to read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @words: number of words to read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: word read from the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads a 16 bit word from the EEPROM.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_nvm_microwire");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* A check for invalid values: offset too large, too many words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and not enough words.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (words == 0)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = nvm->ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_ready_nvm_eeprom(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < words; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Send the READ command (opcode + addr) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, (u16)(offset + i),
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->address_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read the data. For microwire, each word requires the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * overhead of setup and tear-down.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data[i] = e1000_shift_in_eec_bits(hw, 16);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_nvm_eerd - Reads EEPROM using EERD register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: offset of word in the EEPROM to read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @words: number of words to read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: word read from the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads a 16 bit word from the EEPROM using the EERD register.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i, eerd = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_nvm_eerd");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* A check for invalid values: offset too large, too many words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * too many words for the offset, and not enough words.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (words == 0)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < words; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_NVM_RW_REG_START;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_EERD, eerd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_NVM_RW_REG_DATA);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi DEBUGOUT1("NVM read error: %d\n", ret_val);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_nvm_spi - Write to EEPROM using SPI
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: offset within the EEPROM to be written to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @words: number of words to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: 16 bit word(s) to be written to the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes data to EEPROM at offset using SPI interface.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * If e1000_update_nvm_checksum is not called after this function , the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * EEPROM will most likely contain an invalid checksum.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 widx = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_nvm_spi");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* A check for invalid values: offset too large, too many words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and not enough words.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (words == 0)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi while (widx < words) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 write_opcode = NVM_WRITE_OPCODE_SPI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = nvm->ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_ready_nvm_eeprom(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Send the WRITE ENABLE command (8 bit opcode) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->opcode_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Some SPI eeproms use the 8th address bit embedded in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * opcode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((nvm->address_bits == 8) && (offset >= 128))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi write_opcode |= NVM_A8_OPCODE_SPI;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Send the Write command (8-bit opcode + addr) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->address_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Loop to allow for up to whole page write of eeprom */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi while (widx < words) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 word_out = data[widx];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi word_out = (word_out >> 8) | (word_out << 8);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, word_out, 16);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi widx++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((((offset + widx) * 2) % nvm->page_size) == 0) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(10);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_nvm_microwire - Writes EEPROM using microwire
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: offset within the EEPROM to be written to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @words: number of words to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: 16 bit word(s) to be written to the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes data to EEPROM at offset using microwire interface.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * If e1000_update_nvm_checksum is not called after this function , the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * EEPROM will most likely contain an invalid checksum.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eecd;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 words_written = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 widx = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_nvm_microwire");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* A check for invalid values: offset too large, too many words,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and not enough words.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (words == 0)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = nvm->ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_ready_nvm_eeprom(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (u16)(nvm->opcode_bits + 2));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi while (words_written < words) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->opcode_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, (u16)(offset + words_written),
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->address_bits);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, data[words_written], 16);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (widx = 0; widx < 200; widx++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eecd = E1000_READ_REG(hw, E1000_EECD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eecd & E1000_EECD_DO)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (widx == 200) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Write did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_standby_nvm(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi words_written++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (u16)(nvm->opcode_bits + 2));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi nvm->ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_pba_string_generic - Read device part number
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @pba_num: pointer to device part number
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @pba_num_size: size of part number buffer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the product board assembly (PBA) number from the EEPROM and stores
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the value in pba_num.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 pba_num_size)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 nvm_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 pba_ptr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 offset;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_pba_string_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if ((hw->mac.type >= e1000_i210) &&
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi !e1000_get_flash_presence_i210(hw)) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi DEBUGOUT("Flashless no PBA string\n");
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_NVM_PBA_SECTION;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_num == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("PBA string buffer was null\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_INVALID_ARGUMENT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* if nvm_data is not ptr guard the PBA must be in legacy format which
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * means pba_ptr is actually our second data word for the PBA number
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and we can decode it into an ascii string
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (nvm_data != NVM_PBA_PTR_GUARD) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM PBA number is not stored as string\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* make sure callers buffer is big enough to store the PBA */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_num_size < E1000_PBANUM_LENGTH) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("PBA string buffer too small\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_ERR_NO_SPACE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* extract hex string from data and pba_ptr */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[0] = (nvm_data >> 12) & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[1] = (nvm_data >> 8) & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[2] = (nvm_data >> 4) & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[3] = nvm_data & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[4] = (pba_ptr >> 12) & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[5] = (pba_ptr >> 8) & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[6] = '-';
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[7] = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[8] = (pba_ptr >> 4) & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[9] = pba_ptr & 0xF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* put a null character on the end of our string */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[10] = '\0';
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* switch all the data but the '-' to hex char */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (offset = 0; offset < 10; offset++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_num[offset] < 0xA)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[offset] += '0';
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else if (pba_num[offset] < 0x10)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[offset] += 'A' - 0xA;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == 0xFFFF || length == 0) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM PBA number section invalid length\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM_PBA_SECTION;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* check if pba_num buffer is big enough */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_num_size < (((u32)length * 2) - 1)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("PBA string buffer too small\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NO_SPACE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* trim pba length from start of string */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_ptr++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length--;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (offset = 0; offset < length; offset++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[offset * 2] = (u8)(nvm_data >> 8);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_num[offset * 2] = '\0';
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_pba_length_generic - Read device part number length
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @pba_num_size: size of part number buffer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the product board assembly (PBA) number length from the EEPROM and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * stores the value in pba_num_size.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 nvm_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 pba_ptr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_pba_length_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_num_size == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("PBA buffer size was null\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_INVALID_ARGUMENT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* if data is not ptr guard the PBA must be in legacy format */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (nvm_data != NVM_PBA_PTR_GUARD) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *pba_num_size = E1000_PBANUM_LENGTH;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == 0xFFFF || length == 0) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM PBA number section invalid length\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM_PBA_SECTION;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Convert from length in u16 values to u8 chars, add 1 for NULL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and subtract 2 because length field is included in length.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *pba_num_size = ((u32)length * 2) - 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_pba_raw
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eeprom_buf: optional pointer to EEPROM image
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eeprom_buf_size: size of EEPROM image in words
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @max_pba_block_size: PBA block size limit
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @pba: pointer to output PBA structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads PBA from EEPROM image when eeprom_buf is not NULL.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads PBA from physical EEPROM device when eeprom_buf is NULL.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eeprom_buf_size, u16 max_pba_block_size,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_pba *pba)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 pba_block_size;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba == NULL)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &pba->word[0]);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba->word[0] == NVM_PBA_PTR_GUARD) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba->pba_block == NULL)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_get_pba_block_size(hw, eeprom_buf,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eeprom_buf_size,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &pba_block_size);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_block_size > max_pba_block_size)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_nvm(hw, pba->word[1],
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_block_size,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->pba_block);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf_size > (u32)(pba->word[1] +
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi pba_block_size)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi memcpy(pba->pba_block,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &eeprom_buf[pba->word[1]],
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_block_size * sizeof(u16));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_pba_raw
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eeprom_buf: optional pointer to EEPROM image
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eeprom_buf_size: size of EEPROM image in words
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @pba: pointer to PBA structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes PBA to EEPROM image when eeprom_buf is not NULL.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes PBA to physical EEPROM device when eeprom_buf is NULL.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eeprom_buf_size, struct e1000_pba *pba)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba == NULL)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &pba->word[0]);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba->word[0] == NVM_PBA_PTR_GUARD) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba->pba_block == NULL)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_nvm(hw, pba->word[1],
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->pba_block[0],
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->pba_block);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf_size > (u32)(pba->word[1] +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->pba_block[0])) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi memcpy(&eeprom_buf[pba->word[1]],
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->pba_block,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba->pba_block[0] * sizeof(u16));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_pba_block_size
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eeprom_buf: optional pointer to EEPROM image
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @eeprom_buf_size: size of EEPROM image in words
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @pba_data_size: pointer to output variable
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Returns the size of the PBA block in words. Function operates on EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * image if the eeprom_buf pointer is not NULL otherwise it accesses physical
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * EEPROM device.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 eeprom_buf_size, u16 *pba_block_size)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 pba_word[2];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_pba_block_size");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_word[0] == NVM_PBA_PTR_GUARD) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf == NULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &length);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (eeprom_buf_size > pba_word[1])
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length = eeprom_buf[pba_word[1] + 0];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == 0xFFFF || length == 0)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM_PBA_SECTION;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* PBA number in legacy format, there is no PBA Block. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (pba_block_size != NULL)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *pba_block_size = length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_mac_addr_generic - Read device MAC address
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the device MAC address from the EEPROM and stores the value.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Since devices with two ports use the same EEPROM, we increment the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * last bit in the MAC address for the second port.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 rar_high;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 rar_low;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi rar_high = E1000_READ_REG(hw, E1000_RAH(0));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi rar_low = E1000_READ_REG(hw, E1000_RAL(0));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < ETH_ADDR_LEN; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.addr[i] = hw->mac.perm_addr[i];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and then verifies that the sum of the EEPROM is equal to 0xBABA.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 checksum = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 i, nvm_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_validate_nvm_checksum_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi checksum += nvm_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (checksum != (u16) NVM_SUM) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Checksum Invalid\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_NVM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_update_nvm_checksum_generic - Update EEPROM checksum
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Updates the EEPROM checksum by reading/adding each word of the EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * up to the checksum. Then calculates the EEPROM checksum and writes the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * value to the EEPROM.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 checksum = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 i, nvm_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_update_nvm_checksum");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < NVM_CHECKSUM_REG; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Read Error while updating checksum.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi checksum += nvm_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi checksum = (u16) NVM_SUM - checksum;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("NVM Write Error while updating checksum.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_reload_nvm_generic - Reloads EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * extended control register.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic void e1000_reload_nvm_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 ctrl_ext;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_reload_nvm_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(10);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl_ext |= E1000_CTRL_EXT_EE_RST;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi