Revert "soc/intel: Refactor do_global_reset() function"

This reverts commit 77cc3267fc970c710299a164ecbc471f9287d719.

Reason for revert: Breaks quark and also needs breaking down into multiple CLs as commented by Nico on CB:45541

Change-Id: Idf4ca74158df15483856754ee24cc4472a8e09b0
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/44997
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Subrata Banik <subrata.banik@intel.com>
diff --git a/src/soc/intel/alderlake/reset.c b/src/soc/intel/alderlake/reset.c
index ecc052e6..1f7ea3c 100644
--- a/src/soc/intel/alderlake/reset.c
+++ b/src/soc/intel/alderlake/reset.c
@@ -1,8 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
 #include <fsp/util.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset())
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 8a786da..a30333b 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -99,6 +99,7 @@
 	select UDK_2015_BINDING if !SOC_INTEL_GEMINILAKE
 	select UDK_2017_BINDING if SOC_INTEL_GEMINILAKE
 	select SOC_INTEL_COMMON_RESET
+	select HAVE_CF9_RESET_PREPARE
 	select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
 	select HAVE_FSP_GOP
 	select HAVE_FSP_LOGO_SUPPORT
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index b9d302c..79fab1a 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -12,6 +12,7 @@
 bootblock-y += bootblock/bootblock.c
 bootblock-$(CONFIG_FSP_CAR) += fspcar.c
 bootblock-y += car.c
+bootblock-y += heci.c
 bootblock-y += gspi.c
 bootblock-y += i2c.c
 bootblock-y += lpc.c
@@ -25,6 +26,7 @@
 romstage-y += romstage.c
 romstage-y += report_platform.c
 romstage-y += gspi.c
+romstage-y += heci.c
 romstage-y += i2c.c
 romstage-y += uart.c
 romstage-y += meminit.c
@@ -54,6 +56,7 @@
 ramstage-y += elog.c
 ramstage-y += graphics.c
 ramstage-y += gspi.c
+ramstage-y += heci.c
 ramstage-y += i2c.c
 ramstage-y += lpc.c
 ramstage-y += mmap_boot.c
@@ -72,6 +75,7 @@
 postcar-y += mmap_boot.c
 postcar-y += spi.c
 postcar-y += i2c.c
+postcar-y += heci.c
 postcar-y += reset.c
 postcar-y += uart.c
 postcar-y += gspi.c
@@ -79,6 +83,7 @@
 verstage-y += car.c
 verstage-y += i2c.c
 verstage-y += gspi.c
+verstage-y += heci.c
 verstage-y += mmap_boot.c
 verstage-y += uart.c
 verstage-y += pmutil.c
diff --git a/src/soc/intel/apollolake/heci.c b/src/soc/intel/apollolake/heci.c
new file mode 100644
index 0000000..52dcca8
--- /dev/null
+++ b/src/soc/intel/apollolake/heci.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <device/pci_ops.h>
+#include <soc/heci.h>
+#include <soc/pci_devs.h>
+
+uint32_t heci_fw_sts(void)
+{
+	return pci_read_config32(PCH_DEV_CSE, REG_SEC_FW_STS0);
+}
+
+bool heci_cse_normal(void)
+{
+	return ((heci_fw_sts() & MASK_SEC_STATUS) == SEC_STATE_NORMAL);
+}
+
+bool heci_cse_done(void)
+{
+	return (!!(heci_fw_sts() & MASK_SEC_FIRMWARE_COMPLETE));
+}
diff --git a/src/soc/intel/apollolake/include/soc/heci.h b/src/soc/intel/apollolake/include/soc/heci.h
index c62ce78..d8a7f2a 100644
--- a/src/soc/intel/apollolake/include/soc/heci.h
+++ b/src/soc/intel/apollolake/include/soc/heci.h
@@ -5,6 +5,29 @@
 
 #include <stdint.h>
 
+enum sec_status {
+	SEC_STATE_RESET = 0,
+	SEC_STATE_INIT,
+	SEC_STATE_RECOVERY,
+	SEC_STATE_UNKNOWN0,
+	SEC_STATE_UNKNOWN1,
+	SEC_STATE_NORMAL,
+	SEC_STATE_DISABLE_WAIT,
+	SEC_STATE_TRANSITION,
+	SEC_STATE_INVALID_CPU
+};
+
+#define REG_SEC_FW_STS0					0x40
+#define MASK_SEC_FIRMWARE_COMPLETE			(1 << 9)
+#define MASK_SEC_STATUS					0xf
+
+/* Read Firmware Status register */
+uint32_t heci_fw_sts(void);
+/* Returns true if CSE is in normal status */
+bool heci_cse_normal(void);
+/* Returns true if CSE is done with whatever it was doing */
+bool heci_cse_done(void);
+
 /* Dump CSE state and lockdown HECI1 interface using P2SB message. */
 void heci_cse_lockdown(void);
 
diff --git a/src/soc/intel/apollolake/reset.c b/src/soc/intel/apollolake/reset.c
index 7eac964..8641b63 100644
--- a/src/soc/intel/apollolake/reset.c
+++ b/src/soc/intel/apollolake/reset.c
@@ -1,8 +1,52 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
+#include <delay.h>
 #include <fsp/util.h>
+#include <intelblocks/pmclib.h>
+#include <soc/heci.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pm.h>
+#include <timer.h>
+
+#define CSE_WAIT_MAX_MS							1000
+
+void do_global_reset(void)
+{
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
+
+void cf9_reset_prepare(void)
+{
+	struct stopwatch sw;
+
+	/*
+	 * If CSE state is something else than 'normal', it is probably in some
+	 * recovery state. In this case there is no point in  waiting for it to
+	 * get ready so we cross fingers and reset.
+	 */
+	if (!heci_cse_normal()) {
+		printk(BIOS_DEBUG, "CSE is not in normal state, resetting\n");
+		return;
+	}
+
+	/* Reset if CSE is ready */
+	if (heci_cse_done())
+		return;
+
+	printk(BIOS_SPEW, "CSE is not yet ready, waiting\n");
+	stopwatch_init_msecs_expire(&sw, CSE_WAIT_MAX_MS);
+	while (!heci_cse_done()) {
+		if (stopwatch_expired(&sw)) {
+			printk(BIOS_SPEW, "CSE timed out. Resetting\n");
+			return;
+		}
+		mdelay(1);
+	}
+	printk(BIOS_SPEW, "CSE took %lu ms\n", stopwatch_duration_msecs(&sw));
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/cannonlake/reset.c b/src/soc/intel/cannonlake/reset.c
index ecc052e6..1f7ea3c 100644
--- a/src/soc/intel/cannonlake/reset.c
+++ b/src/soc/intel/cannonlake/reset.c
@@ -1,8 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
 #include <fsp/util.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset())
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c
index e595b99..c9e4e1f 100644
--- a/src/soc/intel/common/block/cse/cse_lite.c
+++ b/src/soc/intel/common/block/cse/cse_lite.c
@@ -384,7 +384,7 @@
 	cse_board_reset();
 
 	/* If board does not perform the reset, then perform global_reset */
-	global_reset();
+	do_global_reset();
 
 	die("cse_lite: Failed to reset the system\n");
 
diff --git a/src/soc/intel/common/reset.c b/src/soc/intel/common/reset.c
index ca31897..c6c394b 100644
--- a/src/soc/intel/common/reset.c
+++ b/src/soc/intel/common/reset.c
@@ -4,35 +4,16 @@
 #include <cf9_reset.h>
 #include <console/console.h>
 #include <halt.h>
-#include <intelblocks/cse.h>
-#include <intelblocks/pmclib.h>
 #include <reset.h>
 
 #include "reset.h"
 
-static void force_global_reset(void)
-{
-	/* Ask CSE to do the global reset */
-	if (CONFIG(SOC_INTEL_COMMON_BLOCK_CSE))
-		if (cse_request_global_reset())
-			return;
-
-	/*
-	 * If ME is unable to reset platform then enable the PMC CF9GR register [B0:D31:F2
-	 * register offset 0xAC bit 20] and force a global reset by writing 0x06 or 0x0E.
-	 */
-	if (CONFIG(SOC_INTEL_COMMON_BLOCK_PMC))
-		pmc_global_reset_enable(true);
-	/* Now BIOS can write 0x06 or 0x0E to 0xCF9 port to global reset platform */
-	do_full_reset();
-}
-
 void global_reset(void)
 {
 	printk(BIOS_INFO, "%s() called!\n", __func__);
 	cf9_reset_prepare();
 	dcache_clean_all();
-	force_global_reset();
+	do_global_reset();
 	halt();
 }
 
diff --git a/src/soc/intel/common/reset.h b/src/soc/intel/common/reset.h
index bf8d651..e1f6aab 100644
--- a/src/soc/intel/common/reset.h
+++ b/src/soc/intel/common/reset.h
@@ -3,7 +3,14 @@
 #ifndef _INTEL_COMMON_RESET_H_
 #define _INTEL_COMMON_RESET_H_
 
-/* Prepare for reset, run force_global_reset(), halt. */
+/*
+ * Implement SoC specific global reset (i.e. a reset of both host and
+ * ME partitions). Usually the ME is asked to perform the reset first.
+ * If that doesn't work out, fall back to a manual global reset.
+ */
+void do_global_reset(void);
+
+/* Prepare for reset, run do_global_reset(), halt. */
 __noreturn void global_reset(void);
 
 #endif	/* _INTEL_COMMON_RESET_H_ */
diff --git a/src/soc/intel/elkhartlake/reset.c b/src/soc/intel/elkhartlake/reset.c
index ecc052e6..fe3d769 100644
--- a/src/soc/intel/elkhartlake/reset.c
+++ b/src/soc/intel/elkhartlake/reset.c
@@ -1,8 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
 #include <fsp/util.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset())
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/icelake/reset.c b/src/soc/intel/icelake/reset.c
index ecc052e6..1f7ea3c 100644
--- a/src/soc/intel/icelake/reset.c
+++ b/src/soc/intel/icelake/reset.c
@@ -1,8 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
 #include <fsp/util.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset())
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/jasperlake/reset.c b/src/soc/intel/jasperlake/reset.c
index ecc052e6..1f7ea3c 100644
--- a/src/soc/intel/jasperlake/reset.c
+++ b/src/soc/intel/jasperlake/reset.c
@@ -1,8 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
 #include <fsp/util.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset())
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/skylake/include/soc/me.h b/src/soc/intel/skylake/include/soc/me.h
index 50cc087..5dbcefe 100644
--- a/src/soc/intel/skylake/include/soc/me.h
+++ b/src/soc/intel/skylake/include/soc/me.h
@@ -178,5 +178,6 @@
 };
 
 void intel_me_status(void);
+int send_global_reset(void);
 
 #endif
diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c
index 1b222f3..c37f692 100644
--- a/src/soc/intel/skylake/me.c
+++ b/src/soc/intel/skylake/me.c
@@ -338,6 +338,25 @@
 	}
 }
 
+int send_global_reset(void)
+{
+	int status = -1;
+	union me_hfsts1 hfs1;
+
+	if (!is_cse_enabled())
+		goto ret;
+
+	/* Check ME operating mode */
+	hfs1.data = me_read_config32(PCI_ME_HFSTS1);
+	if (hfs1.fields.operation_mode)
+		goto ret;
+
+	/* ME should be in Normal Mode for this command */
+	status = cse_request_global_reset();
+ret:
+	return status;
+}
+
 /*
  * This can't be put in intel_me_status because by the time control
  * reaches there, ME doesn't respond to GET_FW_VERSION command.
diff --git a/src/soc/intel/skylake/reset.c b/src/soc/intel/skylake/reset.c
index ecc052e6..1076ad2 100644
--- a/src/soc/intel/skylake/reset.c
+++ b/src/soc/intel/skylake/reset.c
@@ -1,8 +1,35 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
 #include <fsp/util.h>
+#include <intelblocks/pmclib.h>
 #include <soc/intel/common/reset.h>
+#include <soc/me.h>
+#include <soc/pm.h>
+
+static void do_force_global_reset(void)
+{
+	/*
+	 * BIOS should ensure it does a global reset
+	 * to reset both host and Intel ME by setting
+	 * PCH PMC [B0:D31:F2 register offset 0xAC bit 20]
+	 */
+	pmc_global_reset_enable(true);
+
+	/* Now BIOS can write 0x06 or 0x0E to 0xCF9 port
+	 * to global reset platform */
+	do_full_reset();
+}
+
+void do_global_reset(void)
+{
+	if (!send_global_reset()) {
+		/* If ME unable to reset platform then
+		 * force global reset using PMC CF9GR register*/
+		do_force_global_reset();
+	}
+}
 
 void chipset_handle_reset(uint32_t status)
 {
diff --git a/src/soc/intel/tigerlake/reset.c b/src/soc/intel/tigerlake/reset.c
index ecc052e6..1f7ea3c 100644
--- a/src/soc/intel/tigerlake/reset.c
+++ b/src/soc/intel/tigerlake/reset.c
@@ -1,8 +1,23 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <cf9_reset.h>
 #include <console/console.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
 #include <fsp/util.h>
 #include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset())
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
 
 void chipset_handle_reset(uint32_t status)
 {