devices/e1000e/nvm-3.6-ethercat.c
author Patrick Bruenn <p.bruenn@beckhoff.com>
Tue, 12 Apr 2016 11:17:36 +0200
branchstable-1.5
changeset 2654 b3f6b3e5ef29
parent 2546 2fa43746d972
permissions -rw-r--r--
devices/ccat: revert "limit rx processing to one frame per poll"

revert "limit rx processing to one frame per poll", which caused etherlab
frame timeouts in setups with more than one frame per cycle.
2546
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     1
/*******************************************************************************
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     2
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     3
  Intel PRO/1000 Linux driver
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     4
  Copyright(c) 1999 - 2012 Intel Corporation.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     5
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     6
  This program is free software; you can redistribute it and/or modify it
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     7
  under the terms and conditions of the GNU General Public License,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     8
  version 2, as published by the Free Software Foundation.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     9
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    10
  This program is distributed in the hope it will be useful, but WITHOUT
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    11
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    12
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    13
  more details.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    14
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    15
  You should have received a copy of the GNU General Public License along with
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    16
  this program; if not, write to the Free Software Foundation, Inc.,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    17
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    18
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    19
  The full GNU General Public License is included in this distribution in
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    20
  the file called "COPYING".
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    21
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    22
  Contact Information:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    23
  Linux NICS <linux.nics@intel.com>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    24
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    25
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    26
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    27
*******************************************************************************/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    28
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    29
#include "e1000-3.6-ethercat.h"
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    30
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    31
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    32
 *  e1000_raise_eec_clk - Raise EEPROM clock
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    33
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    34
 *  @eecd: pointer to the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    35
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    36
 *  Enable/Raise the EEPROM clock bit.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    37
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    38
static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    39
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    40
	*eecd = *eecd | E1000_EECD_SK;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    41
	ew32(EECD, *eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    42
	e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    43
	udelay(hw->nvm.delay_usec);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    44
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    45
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    46
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    47
 *  e1000_lower_eec_clk - Lower EEPROM clock
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    48
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    49
 *  @eecd: pointer to the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    50
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    51
 *  Clear/Lower the EEPROM clock bit.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    52
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    53
static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    54
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    55
	*eecd = *eecd & ~E1000_EECD_SK;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    56
	ew32(EECD, *eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    57
	e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    58
	udelay(hw->nvm.delay_usec);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    59
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    60
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    61
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    62
 *  e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    63
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    64
 *  @data: data to send to the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    65
 *  @count: number of bits to shift out
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    66
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    67
 *  We need to shift 'count' bits out to the EEPROM.  So, the value in the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    68
 *  "data" parameter will be shifted out to the EEPROM one bit at a time.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    69
 *  In order to do this, "data" must be broken down into bits.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    70
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    71
static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    72
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    73
	struct e1000_nvm_info *nvm = &hw->nvm;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    74
	u32 eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    75
	u32 mask;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    76
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    77
	mask = 0x01 << (count - 1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    78
	if (nvm->type == e1000_nvm_eeprom_spi)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    79
		eecd |= E1000_EECD_DO;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    80
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    81
	do {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    82
		eecd &= ~E1000_EECD_DI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    83
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    84
		if (data & mask)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    85
			eecd |= E1000_EECD_DI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    86
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    87
		ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    88
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    89
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    90
		udelay(nvm->delay_usec);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    91
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    92
		e1000_raise_eec_clk(hw, &eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    93
		e1000_lower_eec_clk(hw, &eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    94
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    95
		mask >>= 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    96
	} while (mask);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    97
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    98
	eecd &= ~E1000_EECD_DI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    99
	ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   100
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   101
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   102
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   103
 *  e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   104
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   105
 *  @count: number of bits to shift in
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   106
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   107
 *  In order to read a register from the EEPROM, we need to shift 'count' bits
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   108
 *  in from the EEPROM.  Bits are "shifted in" by raising the clock input to
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   109
 *  the EEPROM (setting the SK bit), and then reading the value of the data out
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   110
 *  "DO" bit.  During this "shifting in" process the data in "DI" bit should
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   111
 *  always be clear.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   112
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   113
static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   114
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   115
	u32 eecd;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   116
	u32 i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   117
	u16 data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   118
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   119
	eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   120
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   121
	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   122
	data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   123
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   124
	for (i = 0; i < count; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   125
		data <<= 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   126
		e1000_raise_eec_clk(hw, &eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   127
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   128
		eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   129
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   130
		eecd &= ~E1000_EECD_DI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   131
		if (eecd & E1000_EECD_DO)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   132
			data |= 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   133
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   134
		e1000_lower_eec_clk(hw, &eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   135
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   136
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   137
	return data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   138
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   139
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   140
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   141
 *  e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   142
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   143
 *  @ee_reg: EEPROM flag for polling
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   144
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   145
 *  Polls the EEPROM status bit for either read or write completion based
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   146
 *  upon the value of 'ee_reg'.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   147
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   148
s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   149
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   150
	u32 attempts = 100000;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   151
	u32 i, reg = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   152
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   153
	for (i = 0; i < attempts; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   154
		if (ee_reg == E1000_NVM_POLL_READ)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   155
			reg = er32(EERD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   156
		else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   157
			reg = er32(EEWR);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   158
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   159
		if (reg & E1000_NVM_RW_REG_DONE)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   160
			return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   161
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   162
		udelay(5);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   163
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   164
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   165
	return -E1000_ERR_NVM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   166
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   167
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   168
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   169
 *  e1000e_acquire_nvm - Generic request for access to EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   170
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   171
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   172
 *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   173
 *  Return successful if access grant bit set, else clear the request for
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   174
 *  EEPROM access and return -E1000_ERR_NVM (-1).
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   175
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   176
s32 e1000e_acquire_nvm(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   177
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   178
	u32 eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   179
	s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   180
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   181
	ew32(EECD, eecd | E1000_EECD_REQ);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   182
	eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   183
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   184
	while (timeout) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   185
		if (eecd & E1000_EECD_GNT)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   186
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   187
		udelay(5);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   188
		eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   189
		timeout--;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   190
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   191
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   192
	if (!timeout) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   193
		eecd &= ~E1000_EECD_REQ;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   194
		ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   195
		e_dbg("Could not acquire NVM grant\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   196
		return -E1000_ERR_NVM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   197
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   198
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   199
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   200
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   201
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   202
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   203
 *  e1000_standby_nvm - Return EEPROM to standby state
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   204
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   205
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   206
 *  Return the EEPROM to a standby state.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   207
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   208
static void e1000_standby_nvm(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   209
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   210
	struct e1000_nvm_info *nvm = &hw->nvm;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   211
	u32 eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   212
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   213
	if (nvm->type == e1000_nvm_eeprom_spi) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   214
		/* Toggle CS to flush commands */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   215
		eecd |= E1000_EECD_CS;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   216
		ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   217
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   218
		udelay(nvm->delay_usec);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   219
		eecd &= ~E1000_EECD_CS;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   220
		ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   221
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   222
		udelay(nvm->delay_usec);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   223
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   224
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   225
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   226
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   227
 *  e1000_stop_nvm - Terminate EEPROM command
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   228
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   229
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   230
 *  Terminates the current command by inverting the EEPROM's chip select pin.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   231
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   232
static void e1000_stop_nvm(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   233
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   234
	u32 eecd;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   235
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   236
	eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   237
	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   238
		/* Pull CS high */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   239
		eecd |= E1000_EECD_CS;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   240
		e1000_lower_eec_clk(hw, &eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   241
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   242
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   243
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   244
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   245
 *  e1000e_release_nvm - Release exclusive access to EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   246
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   247
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   248
 *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   249
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   250
void e1000e_release_nvm(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   251
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   252
	u32 eecd;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   253
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   254
	e1000_stop_nvm(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   255
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   256
	eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   257
	eecd &= ~E1000_EECD_REQ;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   258
	ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   259
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   260
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   261
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   262
 *  e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   263
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   264
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   265
 *  Setups the EEPROM for reading and writing.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   266
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   267
static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   268
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   269
	struct e1000_nvm_info *nvm = &hw->nvm;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   270
	u32 eecd = er32(EECD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   271
	u8 spi_stat_reg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   272
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   273
	if (nvm->type == e1000_nvm_eeprom_spi) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   274
		u16 timeout = NVM_MAX_RETRY_SPI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   275
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   276
		/* Clear SK and CS */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   277
		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   278
		ew32(EECD, eecd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   279
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   280
		udelay(1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   281
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   282
		/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   283
		 * Read "Status Register" repeatedly until the LSB is cleared.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   284
		 * The EEPROM will signal that the command has been completed
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   285
		 * by clearing bit 0 of the internal status register.  If it's
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   286
		 * not cleared within 'timeout', then error out.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   287
		 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   288
		while (timeout) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   289
			e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   290
						 hw->nvm.opcode_bits);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   291
			spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   292
			if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   293
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   294
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   295
			udelay(5);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   296
			e1000_standby_nvm(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   297
			timeout--;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   298
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   299
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   300
		if (!timeout) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   301
			e_dbg("SPI NVM Status error\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   302
			return -E1000_ERR_NVM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   303
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   304
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   305
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   306
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   307
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   308
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   309
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   310
 *  e1000e_read_nvm_eerd - Reads EEPROM using EERD register
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   311
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   312
 *  @offset: offset of word in the EEPROM to read
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   313
 *  @words: number of words to read
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   314
 *  @data: word read from the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   315
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   316
 *  Reads a 16 bit word from the EEPROM using the EERD register.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   317
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   318
s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   319
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   320
	struct e1000_nvm_info *nvm = &hw->nvm;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   321
	u32 i, eerd = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   322
	s32 ret_val = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   323
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   324
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   325
	 * A check for invalid values:  offset too large, too many words,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   326
	 * too many words for the offset, and not enough words.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   327
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   328
	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   329
	    (words == 0)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   330
		e_dbg("nvm parameter(s) out of bounds\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   331
		return -E1000_ERR_NVM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   332
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   333
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   334
	for (i = 0; i < words; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   335
		eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) +
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   336
		    E1000_NVM_RW_REG_START;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   337
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   338
		ew32(EERD, eerd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   339
		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   340
		if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   341
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   342
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   343
		data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   344
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   345
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   346
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   347
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   348
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   349
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   350
 *  e1000e_write_nvm_spi - Write to EEPROM using SPI
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   351
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   352
 *  @offset: offset within the EEPROM to be written to
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   353
 *  @words: number of words to write
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   354
 *  @data: 16 bit word(s) to be written to the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   355
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   356
 *  Writes data to EEPROM at offset using SPI interface.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   357
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   358
 *  If e1000e_update_nvm_checksum is not called after this function , the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   359
 *  EEPROM will most likely contain an invalid checksum.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   360
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   361
s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   362
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   363
	struct e1000_nvm_info *nvm = &hw->nvm;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   364
	s32 ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   365
	u16 widx = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   366
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   367
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   368
	 * A check for invalid values:  offset too large, too many words,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   369
	 * and not enough words.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   370
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   371
	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   372
	    (words == 0)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   373
		e_dbg("nvm parameter(s) out of bounds\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   374
		return -E1000_ERR_NVM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   375
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   376
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   377
	ret_val = nvm->ops.acquire(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   378
	if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   379
		return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   380
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   381
	while (widx < words) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   382
		u8 write_opcode = NVM_WRITE_OPCODE_SPI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   383
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   384
		ret_val = e1000_ready_nvm_eeprom(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   385
		if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   386
			goto release;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   387
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   388
		e1000_standby_nvm(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   389
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   390
		/* Send the WRITE ENABLE command (8 bit opcode) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   391
		e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   392
					 nvm->opcode_bits);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   393
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   394
		e1000_standby_nvm(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   395
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   396
		/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   397
		 * Some SPI eeproms use the 8th address bit embedded in the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   398
		 * opcode
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   399
		 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   400
		if ((nvm->address_bits == 8) && (offset >= 128))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   401
			write_opcode |= NVM_A8_OPCODE_SPI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   402
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   403
		/* Send the Write command (8-bit opcode + addr) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   404
		e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   405
		e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   406
					 nvm->address_bits);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   407
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   408
		/* Loop to allow for up to whole page write of eeprom */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   409
		while (widx < words) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   410
			u16 word_out = data[widx];
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   411
			word_out = (word_out >> 8) | (word_out << 8);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   412
			e1000_shift_out_eec_bits(hw, word_out, 16);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   413
			widx++;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   414
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   415
			if ((((offset + widx) * 2) % nvm->page_size) == 0) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   416
				e1000_standby_nvm(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   417
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   418
			}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   419
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   420
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   421
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   422
	usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   423
release:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   424
	nvm->ops.release(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   425
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   426
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   427
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   428
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   429
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   430
 *  e1000_read_pba_string_generic - Read device part number
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   431
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   432
 *  @pba_num: pointer to device part number
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   433
 *  @pba_num_size: size of part number buffer
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   434
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   435
 *  Reads the product board assembly (PBA) number from the EEPROM and stores
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   436
 *  the value in pba_num.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   437
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   438
s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   439
				  u32 pba_num_size)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   440
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   441
	s32 ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   442
	u16 nvm_data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   443
	u16 pba_ptr;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   444
	u16 offset;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   445
	u16 length;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   446
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   447
	if (pba_num == NULL) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   448
		e_dbg("PBA string buffer was null\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   449
		return -E1000_ERR_INVALID_ARGUMENT;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   450
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   451
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   452
	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   453
	if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   454
		e_dbg("NVM Read Error\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   455
		return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   456
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   457
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   458
	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   459
	if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   460
		e_dbg("NVM Read Error\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   461
		return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   462
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   463
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   464
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   465
	 * if nvm_data is not ptr guard the PBA must be in legacy format which
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   466
	 * means pba_ptr is actually our second data word for the PBA number
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   467
	 * and we can decode it into an ascii string
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   468
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   469
	if (nvm_data != NVM_PBA_PTR_GUARD) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   470
		e_dbg("NVM PBA number is not stored as string\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   471
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   472
		/* we will need 11 characters to store the PBA */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   473
		if (pba_num_size < 11) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   474
			e_dbg("PBA string buffer too small\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   475
			return E1000_ERR_NO_SPACE;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   476
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   477
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   478
		/* extract hex string from data and pba_ptr */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   479
		pba_num[0] = (nvm_data >> 12) & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   480
		pba_num[1] = (nvm_data >> 8) & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   481
		pba_num[2] = (nvm_data >> 4) & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   482
		pba_num[3] = nvm_data & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   483
		pba_num[4] = (pba_ptr >> 12) & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   484
		pba_num[5] = (pba_ptr >> 8) & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   485
		pba_num[6] = '-';
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   486
		pba_num[7] = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   487
		pba_num[8] = (pba_ptr >> 4) & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   488
		pba_num[9] = pba_ptr & 0xF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   489
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   490
		/* put a null character on the end of our string */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   491
		pba_num[10] = '\0';
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   492
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   493
		/* switch all the data but the '-' to hex char */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   494
		for (offset = 0; offset < 10; offset++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   495
			if (pba_num[offset] < 0xA)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   496
				pba_num[offset] += '0';
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   497
			else if (pba_num[offset] < 0x10)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   498
				pba_num[offset] += 'A' - 0xA;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   499
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   500
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   501
		return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   502
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   503
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   504
	ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   505
	if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   506
		e_dbg("NVM Read Error\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   507
		return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   508
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   509
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   510
	if (length == 0xFFFF || length == 0) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   511
		e_dbg("NVM PBA number section invalid length\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   512
		return -E1000_ERR_NVM_PBA_SECTION;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   513
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   514
	/* check if pba_num buffer is big enough */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   515
	if (pba_num_size < (((u32)length * 2) - 1)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   516
		e_dbg("PBA string buffer too small\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   517
		return -E1000_ERR_NO_SPACE;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   518
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   519
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   520
	/* trim pba length from start of string */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   521
	pba_ptr++;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   522
	length--;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   523
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   524
	for (offset = 0; offset < length; offset++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   525
		ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   526
		if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   527
			e_dbg("NVM Read Error\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   528
			return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   529
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   530
		pba_num[offset * 2] = (u8)(nvm_data >> 8);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   531
		pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   532
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   533
	pba_num[offset * 2] = '\0';
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   534
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   535
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   536
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   537
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   538
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   539
 *  e1000_read_mac_addr_generic - Read device MAC address
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   540
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   541
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   542
 *  Reads the device MAC address from the EEPROM and stores the value.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   543
 *  Since devices with two ports use the same EEPROM, we increment the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   544
 *  last bit in the MAC address for the second port.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   545
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   546
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   547
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   548
	u32 rar_high;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   549
	u32 rar_low;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   550
	u16 i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   551
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   552
	rar_high = er32(RAH(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   553
	rar_low = er32(RAL(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   554
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   555
	for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   556
		hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   557
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   558
	for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   559
		hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   560
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   561
	for (i = 0; i < ETH_ALEN; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   562
		hw->mac.addr[i] = hw->mac.perm_addr[i];
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   563
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   564
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   565
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   566
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   567
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   568
 *  e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   569
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   570
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   571
 *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   572
 *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   573
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   574
s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   575
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   576
	s32 ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   577
	u16 checksum = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   578
	u16 i, nvm_data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   579
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   580
	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   581
		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   582
		if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   583
			e_dbg("NVM Read Error\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   584
			return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   585
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   586
		checksum += nvm_data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   587
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   588
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   589
	if (checksum != (u16)NVM_SUM) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   590
		e_dbg("NVM Checksum Invalid\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   591
		return -E1000_ERR_NVM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   592
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   593
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   594
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   595
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   596
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   597
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   598
 *  e1000e_update_nvm_checksum_generic - Update EEPROM checksum
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   599
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   600
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   601
 *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   602
 *  up to the checksum.  Then calculates the EEPROM checksum and writes the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   603
 *  value to the EEPROM.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   604
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   605
s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   606
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   607
	s32 ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   608
	u16 checksum = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   609
	u16 i, nvm_data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   610
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   611
	for (i = 0; i < NVM_CHECKSUM_REG; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   612
		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   613
		if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   614
			e_dbg("NVM Read Error while updating checksum.\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   615
			return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   616
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   617
		checksum += nvm_data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   618
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   619
	checksum = (u16)NVM_SUM - checksum;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   620
	ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   621
	if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   622
		e_dbg("NVM Write Error while updating checksum.\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   623
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   624
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   625
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   626
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   627
/**
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   628
 *  e1000e_reload_nvm_generic - Reloads EEPROM
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   629
 *  @hw: pointer to the HW structure
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   630
 *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   631
 *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   632
 *  extended control register.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   633
 **/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   634
void e1000e_reload_nvm_generic(struct e1000_hw *hw)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   635
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   636
	u32 ctrl_ext;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   637
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   638
	udelay(10);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   639
	ctrl_ext = er32(CTRL_EXT);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   640
	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   641
	ew32(CTRL_EXT, ctrl_ext);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   642
	e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   643
}