Add support for AMD Promonotory (Ryzen)

Message ID 20170305222312.13676-1-stefan.tauner@gmx.at
State New
Headers show

Commit Message

Stefan Tauner March 5, 2017, 10:23 p.m.
To that end, this patch refines determine_generation() to find
the respective SMBUS device too.
Additionally, remove the (unused) heuristics to identify Yangtze.

Signed-off-by: Stefan Tauner <stefan.tauner@gmx.at>
---
 chipset_enable.c |  1 +
 sb600spi.c       | 85 ++++++++++++++++++++++++++------------------------------
 2 files changed, 41 insertions(+), 45 deletions(-)

This version refines sb600spi.c's handling of SMBUS and puts it into
determine_generation() and has some higher hopes of getting somewhere
on Ryzen.

Patch

diff --git a/chipset_enable.c b/chipset_enable.c
index b181b93..72bf15b 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -1492,6 +1492,7 @@  const struct penable chipset_enables[] = {
 	{0x1022, 0x7440, OK,  "AMD", "AMD-768",				enable_flash_amd_768_8111},
 	{0x1022, 0x7468, OK,  "AMD", "AMD-8111",			enable_flash_amd_768_8111},
 	{0x1022, 0x780e, OK,  "AMD", "FCH",				enable_flash_sb600},
+	{0x1022, 0x790e, OK,  "AMD", "Promontory",			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 6bd5679..ebed87f 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -53,6 +53,7 @@  enum amd_chipset {
 	CHIPSET_HUDSON234,
 	CHIPSET_BOLTON,
 	CHIPSET_YANGTZE,
+	CHIPSET_PROMONTORY,
 };
 static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN;
 
@@ -86,18 +87,31 @@  static struct spi_master spi_master_yangtze = {
 	.write_aai = default_spi_write_aai,
 };
 
-static void determine_generation(struct pci_dev *dev)
+static int find_smbus (struct pci_dev **smbus_dev, uint16_t vendor, uint16_t device)
+{
+	*smbus_dev = pci_dev_find(vendor, device);
+	if (*smbus_dev == NULL) {
+		msg_pdbg("No SMBus device with ID %04X:%04X found.\n", vendor, device);
+		msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
+		return 1;
+	}
+	return 0;
+}
+
+/* Determine the chipset's version and identify the respective SMBUS device. */
+static int determine_generation(struct pci_dev *dev, struct pci_dev **smbus_dev)
 {
 	amd_gen = CHIPSET_AMD_UNKNOWN;
 	msg_pdbg2("Trying to determine the generation of the SPI interface... ");
 	if (dev->device_id == 0x438d) {
+		if (find_smbus(smbus_dev, 0x1002, 0x4385) != 0)
+			return 1;
 		amd_gen = CHIPSET_SB6XX;
 		msg_pdbg("SB6xx detected.\n");
 	} else if (dev->device_id == 0x439d) {
-		struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385);
-		if (smbus_dev == NULL)
-			return;
-		uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
+		if (find_smbus(smbus_dev, 0x1002, 0x4385) != 0)
+			return 1;
+		uint8_t rev = pci_read_byte(*smbus_dev, PCI_REVISION_ID);
 		if (rev >= 0x39 && rev <= 0x3D) {
 			amd_gen = CHIPSET_SB7XX;
 			msg_pdbg("SB7xx/SP5100 detected.\n");
@@ -113,28 +127,9 @@  static void determine_generation(struct pci_dev *dev)
 	} else 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 (find_smbus(smbus_dev, 0x1022, 0x780b) != 0)
+			return 1;
+		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");
@@ -149,12 +144,23 @@  static void determine_generation(struct pci_dev *dev)
 				  "Please report this to flashrom@flashrom.org and include this log and\n"
 				  "the output of lspci -nnvx, thanks!.\n", rev);
 		}
-#endif
+	} else if (dev->device_id == 0x790e) {
+		if (find_smbus(smbus_dev, 0x1022, 0x790b) != 0)
+			return 1;
+		amd_gen = CHIPSET_PROMONTORY;
+		msg_pdbg("Promontory (Ryzen) detected.\n");
 	} else
 		msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n"
 			  "Please report this to flashrom@flashrom.org and include this log and\n"
 			  "the output of lspci -nnvx, thanks!\n",
 			  __func__, dev->vendor_id, dev->device_id);
+
+	if (amd_gen == CHIPSET_AMD_UNKNOWN) {
+		msg_perr("Could not determine chipset generation.");
+		return 1;
+	}
+	return 0;
+
 }
 
 static void reset_internal_fifo_pointer(void)
@@ -550,9 +556,7 @@  int sb600_probe_spi(struct pci_dev *dev)
 	 */
 	sb600_spibar += tmp & 0xfff;
 
-	determine_generation(dev);
-	if (amd_gen == CHIPSET_AMD_UNKNOWN) {
-		msg_perr("Could not determine chipset generation.");
+	if (determine_generation(dev, &smbus_dev) != 0) {
 		return ERROR_NONFATAL;
 	}
 
@@ -577,7 +581,7 @@  int sb600_probe_spi(struct pci_dev *dev)
 		msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
 		if (amd_gen == CHIPSET_SB7XX)
 			msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
-		else if (amd_gen == CHIPSET_YANGTZE)
+		else if (amd_gen >= CHIPSET_YANGTZE)
 			msg_pdbg(", RouteTpm2Sp=%i", (tmp >> 3) & 0x1);
 
 		tmp = pci_read_byte(dev, 0xba);
@@ -613,13 +617,13 @@  int sb600_probe_spi(struct pci_dev *dev)
 	 */
 	tmp = mmio_readl(sb600_spibar + 0x00);
 	msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
-	if (amd_gen == CHIPSET_YANGTZE)
+	if (amd_gen >= CHIPSET_YANGTZE)
 		msg_pdbg(", IllegalAccess=%i", (tmp >> 21) & 0x1);
 
 	msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
 		 (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
 
-	if (amd_gen != CHIPSET_YANGTZE)
+	if (amd_gen < CHIPSET_YANGTZE)
 		msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1);
 
 	switch (amd_gen) {
@@ -628,6 +632,7 @@  int sb600_probe_spi(struct pci_dev *dev)
 	case CHIPSET_SB89XX:
 	case CHIPSET_HUDSON234:
 	case CHIPSET_YANGTZE:
+	case CHIPSET_PROMONTORY:
 		msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
 	default: break;
 	}
@@ -644,16 +649,6 @@  int sb600_probe_spi(struct pci_dev *dev)
 		/* FIXME: Handle SpiProtect* configuration on Yangtze. */
 	}
 
-	/* Look for the SMBus device. */
-	smbus_dev = pci_dev_find(0x1002, 0x4385);
-	if (!smbus_dev) {
-		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;
-		}
-	}
-
 	/* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
 	/* GPIO11/SPI_DO and GPIO12/SPI_DI status */
 	reg = pci_read_byte(smbus_dev, 0xAB);
@@ -690,7 +685,7 @@  int sb600_probe_spi(struct pci_dev *dev)
 		return ERROR_FATAL;
 
 	/* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */
-	if (amd_gen != CHIPSET_YANGTZE)
+	if (amd_gen < CHIPSET_YANGTZE)
 		register_spi_master(&spi_master_sb600);
 	else
 		register_spi_master(&spi_master_yangtze);