summaryrefslogtreecommitdiffstats
path: root/nicintel_spi.c
diff options
context:
space:
mode:
authorRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>2017-03-22 14:30:52 +0100
committerDavid Hendricks <david.hendricks@gmail.com>2017-09-17 18:06:05 +0000
commit26d33d2be2851ce0ac16252bc0997eb67068fbed (patch)
tree2a70468056dfd8ca894b8ebee80e6890309eea79 /nicintel_spi.c
parent9fe1fb71c7e53e4f44d633fe52dc33453b36848b (diff)
downloadflashrom-26d33d2be2851ce0ac16252bc0997eb67068fbed.tar.gz
flashrom-26d33d2be2851ce0ac16252bc0997eb67068fbed.tar.bz2
flashrom-26d33d2be2851ce0ac16252bc0997eb67068fbed.zip
nicintel_spi: Support for I210/I211 cards
Implements I210 "raw" flash access as detailed in: http://www.intel.com/content/www/us/en/embedded/products/networking/i210-ethernet-controller-datasheet.html Unfortunately, most of the time the card is in Secure Mode, which means that the raw access is not available. But his should be pretty useful for bringing up boards. Change-Id: I8598ab21297b85dcae1e650a168043aa4cc15c10 Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Reviewed-on: https://review.coreboot.org/21430 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com>
Diffstat (limited to 'nicintel_spi.c')
-rw-r--r--nicintel_spi.c94
1 files changed, 71 insertions, 23 deletions
diff --git a/nicintel_spi.c b/nicintel_spi.c
index 9195c79e5..bbe0afb6d 100644
--- a/nicintel_spi.c
+++ b/nicintel_spi.c
@@ -70,6 +70,9 @@
#define FL_SO 3
#define FL_REQ 4
#define FL_GNT 5
+#define FL_LOCKED 6
+#define FL_ABORT 7
+#define FL_CLR_ERR 8
/* Currently unused */
// #define FL_BUSY 30
// #define FL_ER 31
@@ -95,6 +98,14 @@ const struct dev_entry nics_intel_spi[] = {
{PCI_VENDOR_ID_INTEL, 0x152a, NT, "Intel", "82599 10 Gigabit Dual Port Backplane Controller with FCoE"},
{PCI_VENDOR_ID_INTEL, 0x1557, NT, "Intel", "82599 10 Gigabit SFI Network Controller"},
+ {PCI_VENDOR_ID_INTEL, 0x1531, OK, "Intel", "I210 Gigabit Network Connection Unprogrammed"},
+ {PCI_VENDOR_ID_INTEL, 0x1532, NT, "Intel", "I211 Gigabit Network Connection Unprogrammed"},
+ {PCI_VENDOR_ID_INTEL, 0x1533, NT, "Intel", "I210 Gigabit Network Connection"},
+ {PCI_VENDOR_ID_INTEL, 0x1536, NT, "Intel", "I210 Gigabit Network Connection SERDES Fiber"},
+ {PCI_VENDOR_ID_INTEL, 0x1537, NT, "Intel", "I210 Gigabit Network Connection SERDES Backplane"},
+ {PCI_VENDOR_ID_INTEL, 0x1538, NT, "Intel", "I210 Gigabit Network Connection SGMII"},
+ {PCI_VENDOR_ID_INTEL, 0x1539, NT, "Intel", "I211 Gigabit Network Connection"},
+
{0},
};
@@ -182,32 +193,10 @@ static int nicintel_spi_shutdown(void *data)
return 0;
}
-int nicintel_spi_init(void)
+static int nicintel_spi_82599_enable_flash(void)
{
- struct pci_dev *dev = NULL;
uint32_t tmp;
- if (rget_io_perms())
- return 1;
-
- dev = pcidev_init(nics_intel_spi, PCI_BASE_ADDRESS_0);
- if (!dev)
- return 1;
-
- uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0);
- if (!io_base_addr)
- return 1;
-
- if (dev->device_id < 0x10d8) {
- nicintel_spibar = rphysmap("Intel Gigabit NIC w/ SPI flash", io_base_addr,
- MEMMAP_SIZE);
- } else {
- nicintel_spibar = rphysmap("Intel 10 Gigabit NIC w/ SPI flash", io_base_addr + 0x10000,
- MEMMAP_SIZE);
- }
- if (nicintel_spibar == ERROR_PTR)
- return 1;
-
/* Automatic restore of EECD on shutdown is not possible because EECD
* does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED,
* but other bits with side effects as well. Those other bits must be
@@ -228,6 +217,65 @@ int nicintel_spi_init(void)
if (register_shutdown(nicintel_spi_shutdown, NULL))
return 1;
+ return 0;
+}
+
+static int nicintel_spi_i210_enable_flash()
+{
+ uint32_t tmp;
+
+ tmp = pci_mmio_readl(nicintel_spibar + FLA);
+ if (tmp & (1 << FL_LOCKED)) {
+ msg_perr("Flash is in Secure Mode. Abort.\n");
+ return 1;
+ }
+
+ if (!(tmp & (1 << FL_ABORT)))
+ return 0;
+
+ tmp |= (1 << FL_CLR_ERR);
+ pci_mmio_writel(tmp, nicintel_spibar + FLA);
+ tmp = pci_mmio_readl(nicintel_spibar + FLA);
+ if (!(tmp & (1 << FL_ABORT))) {
+ msg_perr("Unable to clear Flash Access Error. Abort\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int nicintel_spi_init(void)
+{
+ struct pci_dev *dev = NULL;
+
+ if (rget_io_perms())
+ return 1;
+
+ dev = pcidev_init(nics_intel_spi, PCI_BASE_ADDRESS_0);
+ if (!dev)
+ return 1;
+
+ uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0);
+ if (!io_base_addr)
+ return 1;
+
+ if ((dev->device_id & 0xfff0) == 0x1530) {
+ nicintel_spibar = rphysmap("Intel I210 Gigabit w/ SPI flash", io_base_addr + 0x12000,
+ MEMMAP_SIZE);
+ if (!nicintel_spibar || nicintel_spi_i210_enable_flash())
+ return 1;
+ } else if (dev->device_id < 0x10d8) {
+ nicintel_spibar = rphysmap("Intel Gigabit NIC w/ SPI flash", io_base_addr,
+ MEMMAP_SIZE);
+ if (!nicintel_spibar || nicintel_spi_82599_enable_flash())
+ return 1;
+ } else {
+ nicintel_spibar = rphysmap("Intel 10 Gigabit NIC w/ SPI flash", io_base_addr + 0x10000,
+ MEMMAP_SIZE);
+ if (!nicintel_spibar || nicintel_spi_82599_enable_flash())
+ return 1;
+ }
+
if (register_spi_bitbang_master(&bitbang_spi_master_nicintel))
return 1;