ichspi: Add Intel Snow Ridge SoC

Hardware looks the same as C740 series / Emmitsburg. The descriptor,
however, has very different frequency settings and different regions
and masters.

The output of `ich_descriptors_tool' tested with an image from Intel
looks reasonable.

Change-Id: I9f9dc4414af63cbe48d22ef2955df28e297d7e4c
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/188
diff --git a/chipset_enable.c b/chipset_enable.c
index 2988a60..5a89589 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -705,6 +705,7 @@
 	case CHIPSET_APOLLO_LAKE:
 	case CHIPSET_GEMINI_LAKE:
 	case CHIPSET_ELKHART_LAKE:
+	case CHIPSET_SNOW_RIDGE: /* hard coded to 0 (SPI) */
 		boot_straps = boot_straps_apl;
 		break;
 	case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet
@@ -1018,6 +1019,12 @@
 	return enable_flash_pch_spidev(spi_dev, name, CHIPSET_C740_SERIES_EMMITSBURG);
 }
 
+static int enable_flash_snowridge(struct flashprog_programmer *const prog,
+				  struct pci_dev *const spi_dev, const char *const name)
+{
+	return enable_flash_pch_spidev(spi_dev, name, CHIPSET_SNOW_RIDGE);
+}
+
 /* Silvermont architecture: Bay Trail(-T/-I), Avoton/Rangeley.
  * These have a distinctly different behavior compared to other Intel chipsets and hence are handled separately.
  *
@@ -2218,6 +2225,7 @@
 	{0x8086, 0x54a4,   ANY_REV, B_S,    DEP, "Intel", "Alder Lake-N",		enable_flash_pch500},
 	{0x8086, 0x7a24,   ANY_REV, B_S,    NT,  "Intel", "Raptor Lake-S",		enable_flash_pch500},
 	{0x8086, 0x7aa4,   ANY_REV, B_S,    NT,  "Intel", "Alder Lake-S",		enable_flash_pch500},
+	{0x8086, 0x18e0,   ANY_REV, B_S,    NT,  "Intel", "Snow Ridge",			enable_flash_snowridge},
 #endif
 	{0},
 };
diff --git a/ich_descriptors.c b/ich_descriptors.c
index 207adb0..92be747 100644
--- a/ich_descriptors.c
+++ b/ich_descriptors.c
@@ -48,6 +48,7 @@
 	case CHIPSET_300_SERIES_CANNON_POINT:
 	case CHIPSET_500_SERIES_TIGER_POINT:
 	case CHIPSET_ELKHART_LAKE:
+	case CHIPSET_SNOW_RIDGE:
 		return 16;
 	case CHIPSET_100_SERIES_SUNRISE_POINT:
 		return 10;
@@ -73,6 +74,7 @@
 	switch (cs) {
 	case CHIPSET_C620_SERIES_LEWISBURG:
 	case CHIPSET_C740_SERIES_EMMITSBURG:
+	case CHIPSET_SNOW_RIDGE:
 		return 6;
 	case CHIPSET_APOLLO_LAKE:
 	case CHIPSET_GEMINI_LAKE:
@@ -127,7 +129,7 @@
 		"9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
 		"C620 series Lewisburg", "300/400 series Cannon/Comet Point",
 		"500/600 series Tiger/Alder Point", "Apollo Lake", "Gemini Lake", "Elkhart Lake",
-		"C740 series Emmitsburg",
+		"C740 series Emmitsburg", "Snow Ridge",
 	};
 	if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
 		cs = 0;
@@ -224,7 +226,7 @@
 
 static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
 {
-	static const char *const freq_str[5][8] = { {
+	static const char *const freq_str[][8] = { {
 		"20 MHz",
 		"33 MHz",
 		"reserved",
@@ -269,6 +271,15 @@
 		"20 MHz",
 		"reserved",
 		"reserved",
+	}, {
+		"reserved",
+		"48 MHz",
+		"32 MHz",
+		"reserved",
+		"24 MHz",
+		"19.2 MHz",
+		"13.7 MHz",
+		"reserved",
 	}};
 
 	switch (cs) {
@@ -300,6 +311,8 @@
 		return freq_str[3][value];
 	case CHIPSET_ELKHART_LAKE:
 		return freq_str[4][value];
+	case CHIPSET_SNOW_RIDGE:
+		return freq_str[5][value];
 	case CHIPSET_ICH_UNKNOWN:
 	default:
 		return "unknown";
@@ -308,7 +321,7 @@
 
 static void pprint_read_freq(enum ich_chipset cs, uint8_t value)
 {
-	static const char *const freq_str[1][8] = { {
+	static const char *const freq_str[][8] = { {
 		"20 MHz",
 		"24 MHz",
 		"30 MHz",
@@ -317,12 +330,24 @@
 		"reserved",
 		"reserved",
 		"reserved"
+	}, {
+		"16 MHz",
+		"19.2 MHz",
+		"24 MHz",
+		"32 MHz",
+		"48 MHz",
+		"reserved",
+		"reserved",
+		"reserved"
 	}};
 
 	switch (cs) {
 	case CHIPSET_300_SERIES_CANNON_POINT:
 		msg_pdbg2("eSPI/EC Bus Clock Frequency:    %s\n", freq_str[0][value]);
 		return;
+	case CHIPSET_SNOW_RIDGE:
+		msg_pdbg2("eSPI/EC Bus Clock Frequency:    %s\n", freq_str[1][value]);
+		return;
 	case CHIPSET_500_SERIES_TIGER_POINT:
 		msg_pdbg2("Read Clock Frequency:           %s\n", "reserved");
 		return;
@@ -369,6 +394,7 @@
 	case CHIPSET_100_SERIES_SUNRISE_POINT:
 	case CHIPSET_APOLLO_LAKE:
 	case CHIPSET_C620_SERIES_LEWISBURG:
+	case CHIPSET_SNOW_RIDGE:
 		msg_pdbg2("Dual Output Fast Read Support:  %sabled\n",
 			  desc->component.modes.dual_output ? "en" : "dis");
 		break;
@@ -411,7 +437,7 @@
 {
 	static const char *const region_names[] = {
 		"Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
-		"EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
+		"EC/BMC", "unknown", "IE", "10GbE/NIS", "OpROM", "iRC", "unknown", "PTT"
 	};
 	if (i >= ARRAY_SIZE(region_names)) {
 		msg_pdbg2("%s: region index too high.\n", __func__);
@@ -419,7 +445,7 @@
 	}
 	uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
 	uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
-	msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
+	msg_pdbg2("Region %d (%-9s) ", i, region_names[i]);
 	if (base > limit)
 		msg_pdbg2("is unused.\n");
 	else
@@ -529,13 +555,13 @@
 			prettyprint_pch100_masters(desc, nm, masters, nr, regions);
 		} else {
 			const char *const masters[] = {
-				"BIOS", "ME", "GbE", "unkn.", "EC", NULL
+				"BIOS", "ME", "GbE", "NAC", "EC", "unkn.", NULL
 			};
 			const char *const regions[] = {
 				" FD  ", "BIOS ", " ME  ", " GbE ", "Pltf.",
-				"Reg5 ", "Reg6 ", "Reg7 ", " EC  ", "Reg9 ",
-				"Reg10", "Reg11", "Reg12", "Reg13", "Reg14",
-				"Reg15", NULL
+				"Reg5 ", "BIOS2", "Reg7 ", " EC  ", "Reg9 ",
+				"Reg10", " NIS ", "Reg12", " iRC ", "Reg14",
+				" PTT ", NULL
 			};
 			prettyprint_pch100_masters(desc, nm, masters, nr, regions);
 		}
@@ -1027,6 +1053,11 @@
 			return CHIPSET_100_SERIES_SUNRISE_POINT;
 		warn_peculiar_desc("100 series");
 		return CHIPSET_100_SERIES_SUNRISE_POINT;
+	} else if (content->FLMAP2 == 0xffffffff) {
+		if (content->ISL == 0x8f)
+			return CHIPSET_SNOW_RIDGE;
+		warn_peculiar_desc("Snow Ridge");
+		return CHIPSET_SNOW_RIDGE;
 	} else {
 		if (content->ICCRIBA == 0x34)
 			return CHIPSET_300_SERIES_CANNON_POINT;
diff --git a/include/programmer.h b/include/programmer.h
index f82f11f..4d54582 100644
--- a/include/programmer.h
+++ b/include/programmer.h
@@ -367,6 +367,7 @@
 	CHIPSET_HAS_NEW_ACCESS_PERM, /****** BM_RAP/WAP regs from here on *****/
 
 	CHIPSET_C740_SERIES_EMMITSBURG = CHIPSET_HAS_NEW_ACCESS_PERM,
+	CHIPSET_SNOW_RIDGE,
 };
 
 /* ichspi.c */
diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c
index 36fd3e4..06ed0ae 100644
--- a/util/ich_descriptors_tool/ich_descriptors_tool.c
+++ b/util/ich_descriptors_tool/ich_descriptors_tool.c
@@ -141,6 +141,7 @@
 "\t- \"600\" or \"alder\" for Intel's 600 series chipsets.\n"
 "\t- \"c620\" or \"lewis\" for Intel's C620 series aka. Lewisburg chipsets.\n"
 "\t- \"c740\" or \"emmits\" for Intel's C740 series chipsets.\n"
+"\t- \"snow\" for Intel's Snow Ridge SoC.\n"
 "If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n"
 "the GbE blob that is required to initialize the GbE are also dumped to files.\n",
 	argv[0], argv[0]);
@@ -252,6 +253,8 @@
 		else if ((strcmp(csn, "c740") == 0) ||
 			 (strcmp(csn, "emmits") == 0))
 			cs = CHIPSET_C740_SERIES_EMMITSBURG;
+		else if (strcmp(csn, "snow") == 0)
+			cs = CHIPSET_SNOW_RIDGE;
 	}
 
 	ret = read_ich_descriptors_from_dump(buf, len, &cs, &desc);