soc/intel/cannonlake: Support Comet Lake v1 and v2 in one build

Define SOC_INTEL_COMETLAKE_1_2, which creates a build supporting both
Comet Lake v1 and v2 by including both sets of FSP binaries and
selecting one based on the CPUID.

A mainboard can select this instead of SOC_INTEL_COMETLAKE_1 or ..._2
to support all CML-U steppings in one build.

Change-Id: Ic8bf444560fd6b57064c47faf038643fabde010e
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/78345
Reviewed-by: Eric Lai <ericllai@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Michał Kopeć <michal.kopec@3mdeb.com>
diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig
index a42a3c3..fbee465 100644
--- a/src/soc/intel/cannonlake/Kconfig
+++ b/src/soc/intel/cannonlake/Kconfig
@@ -102,6 +102,17 @@
 	bool
 	select SOC_INTEL_COMETLAKE
 
+config SOC_INTEL_COMETLAKE_1_2
+	bool
+	select SOC_INTEL_COMETLAKE
+	select PLATFORM_USES_SECOND_FSP
+	help
+	  Support both CML v1 and v2, for boards that may have either stepping.
+	  Embeds both FSPs and selects the correct one at runtime.  The second
+	  FSP consumes about 800 KiB of flash space.
+
+	  The first FSP is for CML v1, the second is for CML v2.
+
 config SOC_INTEL_COMETLAKE_S
 	bool
 	select SOC_INTEL_COMETLAKE
@@ -285,17 +296,22 @@
 config FSP_HEADER_PATH
 	default "3rdparty/fsp/CoffeeLakeFspBinPkg/Include/" if SOC_INTEL_COFFEELAKE || SOC_INTEL_WHISKEYLAKE
 	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake1/Include/" if SOC_INTEL_COMETLAKE_1
-	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake2/Include/" if SOC_INTEL_COMETLAKE_2
+	# CML v1/v2 headers are equivalent (differ only in comments) so build
+	# against v2 arbitrarily.
+	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake2/Include/" if SOC_INTEL_COMETLAKE_2 || SOC_INTEL_COMETLAKE_1_2
 	default "3rdparty/fsp/CometLakeFspBinPkg/CometLakeS/Include/" if SOC_INTEL_COMETLAKE_S
 	default "3rdparty/fsp/CometLakeFspBinPkg/CometLakeV/Include/" if SOC_INTEL_COMETLAKE_V
 
 config FSP_FD_PATH
 	default "3rdparty/fsp/CoffeeLakeFspBinPkg/Fsp.fd" if SOC_INTEL_COFFEELAKE || SOC_INTEL_WHISKEYLAKE
-	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake1/Fsp.fd" if SOC_INTEL_COMETLAKE_1
+	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake1/Fsp.fd" if SOC_INTEL_COMETLAKE_1 || SOC_INTEL_COMETLAKE_1_2
 	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake2/Fsp.fd" if SOC_INTEL_COMETLAKE_2
 	default "3rdparty/fsp/CometLakeFspBinPkg/CometLakeS/Fsp.fd" if SOC_INTEL_COMETLAKE_S
 	default "3rdparty/fsp/CometLakeFspBinPkg/CometLakeV/Fsp.fd" if SOC_INTEL_COMETLAKE_V
 
+config FSP_FD_PATH_2
+	default "3rdparty/fsp/CometLakeFspBinPkg/CometLake2/Fsp.fd" if SOC_INTEL_COMETLAKE_1_2
+
 config SOC_INTEL_CANNONLAKE_DEBUG_CONSENT
 	int "Debug Consent for CNL"
 	# USB DBC is more common for developers so make this default to 3 if
diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc
index 2a1fcee..5ae0099 100644
--- a/src/soc/intel/cannonlake/Makefile.inc
+++ b/src/soc/intel/cannonlake/Makefile.inc
@@ -85,6 +85,9 @@
 bootblock-y += gpio_common.c
 ramstage-y += gpio_common.c
 
+romstage-$(CONFIG_SOC_INTEL_COMETLAKE_1_2) += cometlake_1_2.c
+ramstage-$(CONFIG_SOC_INTEL_COMETLAKE_1_2) += cometlake_1_2.c
+
 ifeq ($(CONFIG_SOC_INTEL_COFFEELAKE),y)
 ifeq ($(CONFIG_SOC_INTEL_CANNONLAKE_PCH_H),y)
 cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-9e-0a
diff --git a/src/soc/intel/cannonlake/cometlake_1_2.c b/src/soc/intel/cannonlake/cometlake_1_2.c
new file mode 100644
index 0000000..924b963
--- /dev/null
+++ b/src/soc/intel/cannonlake/cometlake_1_2.c
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/cpu.h>
+#include <console/console.h>
+#include <fsp/util.h>
+
+static bool use_fsp_v1(void)
+{
+	/*
+	 * Per the Comet Lake FSP documentation, differentiate Comet Lake v1/v2
+	 * by CPUID.  CML v1 has eax 0x000A0660 or 0x000806EC, CML v2 has
+	 * 0x000A0661.
+	 */
+	uint32_t cpuid = cpu_get_cpuid();
+	switch (cpuid) {
+	case 0x000A0660:
+	case 0x000806EC:
+		printk(BIOS_INFO, "CPUID %08X is Comet Lake v1\n", cpuid);
+		return true;
+	case 0x000A0661:
+		printk(BIOS_INFO, "CPUID %08X is Comet Lake v2\n", cpuid);
+		return false;
+	default:
+		/*
+		 * It's unlikely any new Comet Lake SKUs would be added
+		 * at this point, but guess CML v2 rather than failing
+		 * to boot entirely.
+		 */
+		printk(BIOS_ERR, "CPUID %08X is unknown, guessing Comet Lake v2\n",
+			cpuid);
+		return false;
+	}
+}
+
+const char *soc_select_fsp_m_cbfs(void)
+{
+	return use_fsp_v1() ? CONFIG_FSP_M_CBFS : CONFIG_FSP_M_CBFS_2;
+}
+
+const char *soc_select_fsp_s_cbfs(void)
+{
+	return use_fsp_v1() ? CONFIG_FSP_S_CBFS : CONFIG_FSP_S_CBFS_2;
+}