e1000: Allow direct access to the E1000 SPI EEPROM device
As a part of the manufacturing process for some of our custom hardware,
we are programming the EEPROMs attached to our Intel 82571EB controllers
from software using U-Boot and Linux.
This code provides several conditionally-compiled features to assist in
our manufacturing process:
CONFIG_CMD_E1000:
This is a basic "e1000" command which allows querying the controller
and (if other config options are set) performing EEPROM programming.
In particular, with CONFIG_E1000_SPI this allows you to display a
hex-dump of the EEPROM, copy to/from main memory, and verify/update
the software checksum.
CONFIG_E1000_SPI_GENERIC:
Build a generic SPI driver providing the standard U-Boot SPI driver
interface. This allows commands such as "sspi" to access the bus
attached to the E1000 controller. Additionally, some E1000 chipsets
can support user data in a reserved space in the E1000 EEPROM which
could be used for U-Boot environment storage.
CONFIG_E1000_SPI:
The core SPI access code used by the above interfaces.
For example, the following commands allow you to program the EEPROM from
a USB device (assumes CONFIG_E1000_SPI and CONFIG_CMD_E1000 are enabled):
usb start
fatload usb 0 $loadaddr 82571EB_No_Mgmt_Discrete-LOM.bin
e1000 0 spi program $loadaddr 0 1024
e1000 0 spi checksum update
Please keep in mind that the Intel-provided .eep files are organized as
16-bit words. When converting them to binary form for programming you
must byteswap each 16-bit word so that it is in little-endian form.
This means that when reading and writing words to the SPI EEPROM, the
bit ordering for each word looks like this on the wire:
Time >>>
------------------------------------------------------------------
... [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8], ...
------------------------------------------------------------------
(MSB is 15, LSB is 0).
Signed-off-by: Kyle Moffett <Kyle.D.Moffett@boeing.com>
Cc: Ben Warren <biggerbadderben@gmail.com>
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index fc5ed57..05f2bce 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -35,12 +35,17 @@
#define _E1000_HW_H_
#include <common.h>
+#include <linux/list.h>
#include <malloc.h>
#include <net.h>
#include <netdev.h>
#include <asm/io.h>
#include <pci.h>
+#ifdef CONFIG_E1000_SPI
+#include <spi.h>
+#endif
+
#define E1000_ERR(NIC, fmt, args...) \
printf("e1000: %s: ERROR: " fmt, (NIC)->name ,##args)
@@ -72,12 +77,18 @@
struct e1000_hw_stats;
/* Internal E1000 helper functions */
+struct e1000_hw *e1000_find_card(unsigned int cardnum);
int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
void e1000_standby_eeprom(struct e1000_hw *hw);
void e1000_release_eeprom(struct e1000_hw *hw);
void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+#ifdef CONFIG_E1000_SPI
+int do_e1000_spi(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
+ int argc, char * const argv[]);
+#endif
+
typedef enum {
FALSE = 0,
TRUE = 1
@@ -1068,7 +1079,11 @@
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
+ struct list_head list_node;
struct eth_device *nic;
+#ifdef CONFIG_E1000_SPI
+ struct spi_slave spi;
+#endif
unsigned int cardnum;
pci_dev_t pdev;