diff options
| author | Kyle Moffett <Kyle.D.Moffett@boeing.com> | 2011-10-18 11:05:29 +0000 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2011-10-28 00:37:01 +0200 | 
| commit | ce5207e191c59b3135303fd03b98dd2ac3701ba2 (patch) | |
| tree | d9f5458d8dde3142031f21b76e6909a9cb328ca0 /drivers/net/e1000.c | |
| parent | 2326a94db10d9b6c0bf322c6536cafcac8e85522 (diff) | |
| download | olio-uboot-2014.01-ce5207e191c59b3135303fd03b98dd2ac3701ba2.tar.xz olio-uboot-2014.01-ce5207e191c59b3135303fd03b98dd2ac3701ba2.zip | |
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>
Diffstat (limited to 'drivers/net/e1000.c')
| -rw-r--r-- | drivers/net/e1000.c | 66 | 
1 files changed, 65 insertions, 1 deletions
| diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 7a6ecab45..c86bf0a0e 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -5155,6 +5155,9 @@ void e1000_get_bus_type(struct e1000_hw *hw)  	}  } +/* A list of all registered e1000 devices */ +static LIST_HEAD(e1000_hw_list); +  /**************************************************************************  PROBE - Look for an adapter, this routine's visible to the outside  You should omit the last argument struct pci_device * for a non-PCI NIC @@ -5234,8 +5237,9 @@ e1000_initialize(bd_t * bis)  		if (e1000_check_phy_reset_block(hw))  			E1000_ERR(nic, "PHY Reset is blocked!\n"); -		/* Basic init was OK, reset the hardware */ +		/* Basic init was OK, reset the hardware and allow SPI access */  		e1000_reset_hw(hw); +		list_add_tail(&hw->list_node, &e1000_hw_list);  		/* Validate the EEPROM and get chipset information */  #if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G)) @@ -5263,3 +5267,63 @@ e1000_initialize(bd_t * bis)  	return i;  } + +struct e1000_hw *e1000_find_card(unsigned int cardnum) +{ +	struct e1000_hw *hw; + +	list_for_each_entry(hw, &e1000_hw_list, list_node) +		if (hw->cardnum == cardnum) +			return hw; + +	return NULL; +} + +#ifdef CONFIG_CMD_E1000 +static int do_e1000(cmd_tbl_t *cmdtp, int flag, +		int argc, char * const argv[]) +{ +	struct e1000_hw *hw; + +	if (argc < 3) { +		cmd_usage(cmdtp); +		return 1; +	} + +	/* Make sure we can find the requested e1000 card */ +	hw = e1000_find_card(simple_strtoul(argv[1], NULL, 10)); +	if (!hw) { +		printf("e1000: ERROR: No such device: e1000#%s\n", argv[1]); +		return 1; +	} + +	if (!strcmp(argv[2], "print-mac-address")) { +		unsigned char *mac = hw->nic->enetaddr; +		printf("%02x:%02x:%02x:%02x:%02x:%02x\n", +			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +		return 0; +	} + +#ifdef CONFIG_E1000_SPI +	/* Handle the "SPI" subcommand */ +	if (!strcmp(argv[2], "spi")) +		return do_e1000_spi(cmdtp, hw, argc - 3, argv + 3); +#endif + +	cmd_usage(cmdtp); +	return 1; +} + +U_BOOT_CMD( +	e1000, 7, 0, do_e1000, +	"Intel e1000 controller management", +	/*  */"<card#> print-mac-address\n" +#ifdef CONFIG_E1000_SPI +	"e1000 <card#> spi show [<offset> [<length>]]\n" +	"e1000 <card#> spi dump <addr> <offset> <length>\n" +	"e1000 <card#> spi program <addr> <offset> <length>\n" +	"e1000 <card#> spi checksum [update]\n" +#endif +	"       - Manage the Intel E1000 PCI device" +); +#endif /* not CONFIG_CMD_E1000 */ |