Edward O'Callaghan has submitted this change. ( https://review.coreboot.org/c/flashrom/+/44073 )
Change subject: sb600spi.c: Add support for 0x790b rev 0x61 (AMD Zen) ......................................................................
sb600spi.c: Add support for 0x790b rev 0x61 (AMD Zen)
Adds support for rev 0x59 || 0x61 of did 0x790b.
This is quite confusing however it turns out FCH chipsets called 'Promontory' contain the so-called SPI100 ip core that uses memory mapping and not a ring buffer for transactions. Typically this is found on both Stoney Ridge and Zen platforms. In light of this, separate out the promontory path into its own callback struct state tracker so that it's implementation does not interfere with previous generations that predate the SPI100 controller.
Since there is some life-time state required to track the mapping during between the first attempted read and the final tear-down of the spi master we take the opportunity to avoid static locals and instead implement the functionality in a re-entrant way for follow up clean ups.
BUG=none BRANCH=none TEST= Zork => 'Promontory (rev 0x61) detected.' && Grunt => 'Promontory (rev 0x4b) detected.'
Change-Id: I5ce63b5de863aed0442cb4ffeff981e9b2fa445b Signed-off-by: Edward O'Callaghan quasisec@google.com Reviewed-on: https://review.coreboot.org/c/flashrom/+/44073 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Sam McNally sammc@google.com --- M sb600spi.c 1 file changed, 64 insertions(+), 3 deletions(-)
Approvals: build bot (Jenkins): Verified Sam McNally: Looks good to me, approved
diff --git a/sb600spi.c b/sb600spi.c index 40434f0..2e27cee 100644 --- a/sb600spi.c +++ b/sb600spi.c @@ -55,6 +55,10 @@ #define FIFO_SIZE_OLD 8 #define FIFO_SIZE_YANGTZE 71
+struct sb600spi_data { + struct flashctx *flash; +}; + static int find_smbus_dev_rev(uint16_t vendor, uint16_t device) { struct pci_dev *smbus_dev = pci_dev_find(vendor, device); @@ -116,8 +120,17 @@ if (rev == 0x4a) { msg_pdbg("Yangtze detected.\n"); return CHIPSET_YANGTZE; - } else if (rev == 0x4b) { - msg_pdbg("Promontory detected.\n"); + /** + * FCH chipsets called 'Promontory' are one's with the + * so-called SPI100 ip core that uses memory mapping and + * not a ring buffer for transactions. Typically this is + * found on both Stoney Ridge and Zen platforms. + * + * The revisions I have found by searching various lspci + * outputs are as follows: 0x4b, 0x59 & 0x61. + */ + } else if (rev == 0x4b || rev == 0x59 || rev == 0x61) { + msg_pdbg("Promontory (rev 0x%02x) detected.\n", rev); return CHIPSET_PROMONTORY; } else { msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n" @@ -541,6 +554,18 @@ return amd_imc_shutdown(dev); }
+static int promontory_read_memmapped(struct flashctx *flash, uint8_t *buf, + unsigned int start, unsigned int len) +{ + struct sb600spi_data * data = (struct sb600spi_data *)flash->mst->spi.data; + if (!data->flash) { + map_flash(flash); + data->flash = flash; /* keep a copy of flashctx for unmap() on tear-down. */ + } + mmio_readn((void *)(flash->virtual_memory + start), buf, len); + return 0; +} + static struct spi_master spi_master_sb600 = { .max_data_read = FIFO_SIZE_OLD, .max_data_write = FIFO_SIZE_OLD - 3, @@ -561,6 +586,25 @@ .write_aai = default_spi_write_aai, };
+static struct spi_master spi_master_promontory = { + .max_data_read = MAX_DATA_READ_UNLIMITED, + .max_data_write = FIFO_SIZE_YANGTZE - 3, + .command = spi100_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = promontory_read_memmapped, + .write_256 = default_spi_write_256, + .write_aai = default_spi_write_aai, +}; + +static int sb600spi_shutdown(void *data) +{ + struct flashctx *flash = ((struct sb600spi_data *)data)->flash; + if (flash) + finalize_flash_access(flash); + free(data); + return 0; +} + int sb600_probe_spi(struct pci_dev *dev) { struct pci_dev *smbus_dev; @@ -726,11 +770,28 @@ if (handle_imc(dev, amd_gen) != 0) return ERROR_FATAL;
+ struct sb600spi_data *data = calloc(1, sizeof(struct sb600spi_data)); + if (!data) { + msg_perr("Unable to allocate space for extra SPI master data.\n"); + return SPI_GENERIC_ERROR; + } + + data->flash = NULL; + + register_shutdown(sb600spi_shutdown, data); + spi_master_sb600.data = data; + spi_master_yangtze.data = data; + spi_master_promontory.data = data; + + /* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */ if (amd_gen < CHIPSET_YANGTZE) register_spi_master(&spi_master_sb600); - else + else if (amd_gen == CHIPSET_YANGTZE) register_spi_master(&spi_master_yangtze); + else + register_spi_master(&spi_master_promontory); + return 0; }