The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash) but the SPI interface does. Bail out in case we detect Yangtze and add infrastructure to distinguish other families too for further refactorings.
Also, add ASRock IMB-A180 to the laptop whitelist.
Tested on ASRock IMB-A180 with and w/o USE_YANGTZE_HEURISTICS.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- board_enable.c | 2 ++ chipset_enable.c | 2 +- sb600spi.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/board_enable.c b/board_enable.c index d60f9cb..074cabb 100644 --- a/board_enable.c +++ b/board_enable.c @@ -2234,6 +2234,7 @@ static int it8718f_gpio63_raise(void) /* * Suited for all boards with ambiguous DMI chassis information, which should be * whitelisted because they are known to work: + * - ASRock IMB-A180(-H) * - Intel D945GCNL * - MSC Q7 Tunnel Creek Module (Q7-TCTC) */ @@ -2322,6 +2323,7 @@ const struct board_match board_matches[] = { {0x8086, 0x27b9, 0xa0a0, 0x0632, 0x8086, 0x27da, 0xa0a0, 0x0632, NULL, NULL, NULL, P3, "AOpen", "i945GMx-VFX", 0, OK, intel_ich_gpio38_raise}, {0x8086, 0x277c, 0xa0a0, 0x060b, 0x8086, 0x27da, 0xa0a0, 0x060b, NULL, NULL, NULL, P3, "AOpen", "i975Xa-YDG", 0, OK, board_aopen_i975xa_ydg}, {0x8086, 0x27b8, 0x1849, 0x27b8, 0x8086, 0x27da, 0x1849, 0x27da, "^ConRoeXFire-eSATA2", NULL, NULL, P3, "ASRock", "ConRoeXFire-eSATA2", 0, OK, intel_ich_gpio16_raise}, + {0x1022, 0x1536, 0x1849, 0x1536, 0x1022, 0x780e, 0x1849, 0x780e, "^Kabini CRB$", NULL, NULL, P2, "ASRock", "IMB-A180(-H)", 0, OK, p2_not_a_laptop}, {0x1039, 0x0741, 0x1849, 0x0741, 0x1039, 0x5513, 0x1849, 0x5513, "^K7S41 $", NULL, NULL, P3, "ASRock", "K7S41", 0, OK, w836xx_memw_enable_2e}, {0x1039, 0x0741, 0x1849, 0x0741, 0x1039, 0x5513, 0x1849, 0x5513, "^K7S41GX$", NULL, NULL, P3, "ASRock", "K7S41GX", 0, OK, w836xx_memw_enable_2e}, {0x8086, 0x24D4, 0x1849, 0x24D0, 0x8086, 0x24D5, 0x1849, 0x9739, NULL, NULL, NULL, P3, "ASRock", "P4i65GV", 0, OK, intel_ich_gpio23_raise}, diff --git a/chipset_enable.c b/chipset_enable.c index e1a74ae..6c5e34b 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -1304,7 +1304,7 @@ const struct penable chipset_enables[] = { {0x1022, 0x3000, OK, "AMD", "Elan SC520", get_flashbase_sc520}, {0x1022, 0x7440, OK, "AMD", "AMD-768", enable_flash_amd8111}, {0x1022, 0x7468, OK, "AMD", "AMD8111", enable_flash_amd8111}, - {0x1022, 0x780e, OK, "AMD", "Hudson", enable_flash_sb600}, + {0x1022, 0x780e, OK, "AMD", "FCH", enable_flash_sb600}, {0x1039, 0x0406, NT, "SiS", "501/5101/5501", enable_flash_sis501}, {0x1039, 0x0496, NT, "SiS", "85C496+497", enable_flash_sis85c496}, {0x1039, 0x0530, OK, "SiS", "530", enable_flash_sis530}, diff --git a/sb600spi.c b/sb600spi.c index 74106c2..168e910 100644 --- a/sb600spi.c +++ b/sb600spi.c @@ -44,6 +44,59 @@ */
static uint8_t *sb600_spibar = NULL; +enum amd_chipset { + CHIPSET_AMD_UNKNOWN, + CHIPSET_SB6XX, + CHIPSET_SB7XX, /* SP5100 too */ + CHIPSET_SB89XX, /* Hudson-1 too */ + CHIPSET_HUDSON234, + CHIPSET_YANGTZE, +}; +static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN; + +static void determine_generation(struct pci_dev *dev) +{ + amd_gen = CHIPSET_AMD_UNKNOWN; + msg_pdbg2("Trying to determine the generation of the SPI interface.\n"); + if (dev->device_id == 0x780e) { + /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash) + * although they use different SPI interfaces. */ +#ifdef USE_YANGTZE_HEURISTICS + /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by + * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on + * Yangtze (and newer, compatible chipsets). */ + int i; + msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... "); + for (i = 0x20; i <= 0x4f; i++) { + if (mmio_readb(sb600_spibar + i) != 0xff) { + amd_gen = CHIPSET_YANGTZE; + msg_pdbg("found.\n"); + return; + } + } + msg_pdbg("not found. Assuming Hudson.\n"); + amd_gen = CHIPSET_HUDSON234; +#else + struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B); + if (smbus_dev == NULL) { + msg_pdbg("No SMBus device with ID 1022:780B found.\n"); + return; + } + uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID); + if (rev >= 0x11 && rev <= 0x15) { + amd_gen = CHIPSET_HUDSON234; + msg_pdbg("Hudson-2/3/4 detected.\n"); + } else if (rev >= 0x39 && rev <= 0x3A) { + amd_gen = CHIPSET_YANGTZE; + msg_pdbg("Yangtze detected.\n"); + } else { + msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n" + "Please report this to flashrom@flashrom.org and include this log and\n" + "the output of lspci -nnvx, thanks!.\n", rev); + } +#endif + } +}
static void reset_internal_fifo_pointer(void) { @@ -281,6 +334,14 @@ int sb600_probe_spi(struct pci_dev *dev) */ sb600_spibar += tmp & 0xfff;
+ determine_generation(dev); + + if (amd_gen == CHIPSET_YANGTZE) { + msg_perr("SPI on Kabini/Temash and newer chipsets are not yet supported.\n" + "Please try a newer version of flashrom.\n"); + return ERROR_NONFATAL; + } + tmp = pci_read_long(dev, 0xa0); msg_pdbg("AltSpiCSEnable=%i, SpiRomEnable=%i, " "AbortEnable=%i\n", tmp & 0x1, (tmp & 0x2) >> 1, @@ -312,9 +373,8 @@ int sb600_probe_spi(struct pci_dev *dev)
/* Look for the SMBus device. */ smbus_dev = pci_dev_find(0x1002, 0x4385); - if (!smbus_dev) { - smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD Hudson */ + smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD FCH */ if (!smbus_dev) { msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n"); return ERROR_NONFATAL;