Detect AMD Yangtze (found in Kabini and Tamesh)
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 and refine the IMC
warning a bit.
Tested on ASRock IMB-A180 with and w/o USE_YANGTZE_HEURISTICS, and
by Chris Goodrich from Sage on
- SB600
- SB700
- SB800
- Hudson 3 (A70M)
- Kabini
Corresponding to flashrom svn r1706.
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
diff --git a/board_enable.c b/board_enable.c
index a565c15..d3460c1 100644
--- a/board_enable.c
+++ b/board_enable.c
@@ -2234,6 +2234,7 @@
/*
* Suited for all boards with ambiguous DMI chassis information, which should be
* whitelisted because they are known to work:
+ * - ASRock IMB-A180(-H)
* - MSC Q7 Tunnel Creek Module (Q7-TCTC)
*/
static int p2_not_a_laptop(void)
@@ -2321,6 +2322,7 @@
{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 b52a5b4..2706be4 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -1304,7 +1304,7 @@
{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 e76c04a..cb7c4ac 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -44,6 +44,58 @@
*/
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;
+ 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)
{
@@ -212,9 +264,9 @@
if (!amd_imc_force)
programmer_may_write = 0;
- msg_pinfo("Writes have been disabled for safety reasons because the IMC is active\n"
- "and it could interfere with accessing flash memory. Flashrom will try\n"
- "to disable it temporarily but even then this might not be safe:\n"
+ msg_pinfo("Writes have been disabled for safety reasons because the presence of the IMC\n"
+ "was detected and it could interfere with accessing flash memory. Flashrom will\n"
+ "try to disable it temporarily but even then this might not be safe:\n"
"when it is reenabled and after a reboot it expects to find working code\n"
"in the flash and it is unpredictable what happens if there is none.\n"
"\n"
@@ -281,6 +333,14 @@
*/
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 +372,8 @@
/* 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;