Add Gemini Lake support

The SPI hardware is pretty much unchanged from Apollo Lake. However, the
IFD differs significantly enough to require special handling.

Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Change-Id: Ib5dcdf204166f44a8531c19b5f363b851d2ccd77
Reviewed-on: https://review.coreboot.org/c/flashrom/+/54276
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/chipset_enable.c b/chipset_enable.c
index 259902e..025203c 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -601,6 +601,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		reg_name = "BIOS_SPI_BC";
 		gcs = pci_read_long(dev, 0xdc);
 		bild = (gcs >> 7) & 1;
@@ -699,6 +700,7 @@
 		boot_straps = boot_straps_pch8_lp;
 		break;
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		boot_straps = boot_straps_apl;
 		break;
 	case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet
@@ -726,6 +728,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		bbs = (gcs >> 6) & 0x1;
 		break;
 	default:
@@ -976,6 +979,11 @@
 	return enable_flash_pch100_or_c620(dev, name, 0x0d, 2, CHIPSET_APOLLO_LAKE);
 }
 
+static int enable_flash_glk(struct pci_dev *const dev, const char *const name)
+{
+	return enable_flash_pch100_or_c620(dev, name, 0x0d, 2, CHIPSET_GEMINI_LAKE);
+}
+
 /* Silvermont architecture: Bay Trail(-T/-I), Avoton/Rangeley.
  * These have a distinctly different behavior compared to other Intel chipsets and hence are handled separately.
  *
@@ -2076,6 +2084,7 @@
 	{0x8086, 0xa2d2, B_S,    NT,  "Intel", "X299",				enable_flash_pch100},
 	{0x8086, 0x5ae8, B_S,    DEP, "Intel", "Apollo Lake",			enable_flash_apl},
 	{0x8086, 0x5af0, B_S,    DEP, "Intel", "Apollo Lake",			enable_flash_apl},
+	{0x8086, 0x31e8, B_S,    DEP, "Intel", "Gemini Lake",			enable_flash_glk},
 	{0x8086, 0xa303, B_S,    NT,  "Intel", "H310",				enable_flash_pch300},
 	{0x8086, 0xa304, B_S,    NT,  "Intel", "H370",				enable_flash_pch300},
 	{0x8086, 0xa305, B_S,    NT,  "Intel", "Z390",				enable_flash_pch300},
diff --git a/ich_descriptors.c b/ich_descriptors.c
index 7374984..c5f9f82 100644
--- a/ich_descriptors.c
+++ b/ich_descriptors.c
@@ -39,6 +39,7 @@
 {
 	switch (cs) {
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		return 6;
 	case CHIPSET_C620_SERIES_LEWISBURG:
 	case CHIPSET_300_SERIES_CANNON_POINT:
@@ -68,6 +69,7 @@
 	switch (cs) {
 	case CHIPSET_C620_SERIES_LEWISBURG:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		if (cont->NM <= MAX_NUM_MASTERS)
 			return cont->NM;
 		break;
@@ -104,7 +106,7 @@
 		"5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
 		"8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
 		"9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
-		"C620 series Lewisburg", "300 series Cannon Point", "Apollo Lake",
+		"C620 series Lewisburg", "300 series Cannon Point", "Apollo Lake", "Gemini Lake",
 	};
 	if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
 		cs = 0;
@@ -198,7 +200,8 @@
 	case CHIPSET_C620_SERIES_LEWISBURG:
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
-	case CHIPSET_APOLLO_LAKE: {
+	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE: {
 		uint8_t size_enc;
 		if (idx == 0) {
 			size_enc = desc->component.dens_new.comp1_density;
@@ -269,6 +272,7 @@
 	case CHIPSET_400_SERIES_COMET_POINT:
 		return freq_str[1][value];
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		return freq_str[2][value];
 	case CHIPSET_ICH_UNKNOWN:
 	default:
@@ -286,6 +290,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		has_flill1 = true;
 		break;
 	default:
@@ -462,7 +467,7 @@
 					  desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
 			msg_pdbg2("\n");
 		}
-	} else if (cs == CHIPSET_APOLLO_LAKE) {
+	} else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE) {
 		const char *const master_names[] = { "BIOS", "TXE", };
 		if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
 			msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
@@ -922,7 +927,9 @@
 		else if (content->ISL <= 16)
 			return CHIPSET_5_SERIES_IBEX_PEAK;
 		else if (content->FLMAP2 == 0) {
-			if (content->ISL != 19)
+			if (content->ISL == 23)
+				return CHIPSET_GEMINI_LAKE;
+			else if (content->ISL != 19)
 				msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
 			return CHIPSET_APOLLO_LAKE;
 		}
@@ -967,6 +974,7 @@
 	switch (guess) {
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
+	case CHIPSET_GEMINI_LAKE:
 		/* `freq_read` was repurposed, so can't check on it any more. */
 		return guess;
 	case CHIPSET_100_SERIES_SUNRISE_POINT:
@@ -1123,6 +1131,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		if (idx == 0) {
 			size_enc = desc->component.dens_new.comp1_density;
 		} else {
@@ -1159,6 +1168,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		mmio_le_writel(control, spibar + PCH100_REG_FDOC);
 		return mmio_le_readl(spibar + PCH100_REG_FDOD);
 	default:
diff --git a/ich_descriptors.h b/ich_descriptors.h
index c6bf5d8..727a31b 100644
--- a/ich_descriptors.h
+++ b/ich_descriptors.h
@@ -257,7 +257,7 @@
 
 struct ich_desc_south_strap {
 	union {
-		uint32_t STRPs[18]; /* current maximum: cougar point */
+		uint32_t STRPs[23]; /* current maximum: gemini lake */
 		struct { /* ich8 */
 			struct { /* STRP1 */
 				uint32_t ME_DISABLE		:1,
diff --git a/ichspi.c b/ichspi.c
index 613f3fc..57cbdee 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1740,6 +1740,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		num_pr			= 6;	/* Includes GPR0 */
 		reg_pr0			= PCH100_REG_FPR0;
 		swseq_data.reg_ssfsc	= PCH100_REG_SSFSC;
@@ -1772,6 +1773,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_400_SERIES_COMET_POINT:
 	case CHIPSET_APOLLO_LAKE:
+	case CHIPSET_GEMINI_LAKE:
 		num_freg = 16;
 		break;
 	default:
@@ -1868,6 +1870,7 @@
 		case CHIPSET_300_SERIES_CANNON_POINT:
 		case CHIPSET_400_SERIES_COMET_POINT:
 		case CHIPSET_APOLLO_LAKE:
+		case CHIPSET_GEMINI_LAKE:
 			tmp = mmio_readl(spibar + PCH100_REG_DLOCK);
 			msg_pdbg("0x0c: 0x%08x (DLOCK)\n", tmp);
 			prettyprint_pch100_reg_dlock(tmp);
@@ -1943,6 +1946,7 @@
 			case CHIPSET_300_SERIES_CANNON_POINT:
 			case CHIPSET_400_SERIES_COMET_POINT:
 			case CHIPSET_APOLLO_LAKE:
+			case CHIPSET_GEMINI_LAKE:
 			case CHIPSET_BAYTRAIL:
 				break;
 			default:
@@ -1976,6 +1980,7 @@
 			case CHIPSET_300_SERIES_CANNON_POINT:
 			case CHIPSET_400_SERIES_COMET_POINT:
 			case CHIPSET_APOLLO_LAKE:
+			case CHIPSET_GEMINI_LAKE:
 				break;
 			default:
 				tmp = mmio_readl(spibar + ICH9_REG_FPB);
@@ -2012,8 +2017,10 @@
 			ich_spi_mode = ich_hwseq;
 		}
 
-		if (ich_spi_mode == ich_auto && ich_gen == CHIPSET_APOLLO_LAKE) {
-			msg_pdbg("Enabling hardware sequencing by default for Apollo Lake.\n");
+		if (ich_spi_mode == ich_auto &&
+		    (ich_gen == CHIPSET_APOLLO_LAKE ||
+		     ich_gen == CHIPSET_GEMINI_LAKE)) {
+			msg_pdbg("Enabling hardware sequencing by default for Apollo/Gemini Lake.\n");
 			ich_spi_mode = ich_hwseq;
 		}
 
diff --git a/programmer.h b/programmer.h
index 1b0cdb9..d3a7ba3 100644
--- a/programmer.h
+++ b/programmer.h
@@ -672,6 +672,7 @@
 	CHIPSET_300_SERIES_CANNON_POINT,
 	CHIPSET_APOLLO_LAKE,
 	CHIPSET_400_SERIES_COMET_POINT,
+	CHIPSET_GEMINI_LAKE,
 };
 
 /* ichspi.c */
diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c
index 32eea12..bfeedc1 100644
--- a/util/ich_descriptors_tool/ich_descriptors_tool.c
+++ b/util/ich_descriptors_tool/ich_descriptors_tool.c
@@ -127,6 +127,7 @@
 "\t- \"ich10\",\n"
 "\t- \"silvermont\" for chipsets from Intel's Silvermont architecture (e.g. Bay Trail),\n"
 "\t- \"apollo\" for Intel's Apollo Lake SoC.\n"
+"\t- \"gemini\" for Intel's Gemini Lake SoC.\n"
 "\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n"
 "\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n"
 "\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n"
@@ -230,6 +231,8 @@
 			cs = CHIPSET_400_SERIES_COMET_POINT;
 		else if (strcmp(csn, "apollo") == 0)
 			cs = CHIPSET_APOLLO_LAKE;
+		else if (strcmp(csn, "gemini") == 0)
+			cs = CHIPSET_GEMINI_LAKE;
 	}
 
 	ret = read_ich_descriptors_from_dump(buf, len, &cs, &desc);