src/soc/intel/common/block/cse: Make hfsts1 common & add helper functions

Host FW status 1 (FWSTS1/HFSTS1) register definition is common across SoCs,
hence move it to common. Also add below helper function,

* wait_cse_sec_override_mode() - Polls ME status for "HECI_OP_MODE_SEC_OVERRIDE".
  It's a special CSE mode, the mode ensures CSE does not trigger any
  spi cycles to CSE region.

* set_host_ready() - Clears reset state from host CSR.

TEST=Verified CSE recover mode on CML RVP & Hatch board

Change-Id: Id5c12b7abdb27c38af74ea6ee568b42ec74bcb3c
Signed-off-by: Rizwan Qureshi <rizwan.qureshi@intel.com>
Signed-off-by: Sridhar Siricilla <sridhar.siricilla@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/35226
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aamir Bohra <aamir.bohra@intel.com>
diff --git a/src/soc/intel/cannonlake/me.c b/src/soc/intel/cannonlake/me.c
index cd94be5..d6dfec9 100644
--- a/src/soc/intel/cannonlake/me.c
+++ b/src/soc/intel/cannonlake/me.c
@@ -32,30 +32,6 @@
 	ME_WSTATE_NORMAL	= 0x05,
 };
 
-/* Host Firmware Status Register 1 */
-union hfsts1 {
-	uint32_t raw;
-	struct {
-		uint32_t working_state		: 4;
-		uint32_t mfg_mode		: 1;
-		uint32_t fpt_bad		: 1;
-		uint32_t operation_state	: 3;
-		uint32_t fw_init_complete	: 1;
-		uint32_t ft_bup_ld_flr		: 1;
-		uint32_t fw_upd_in_progress	: 1;
-		uint32_t error_code		: 4;
-		uint32_t operation_mode		: 4;
-		uint32_t reset_count		: 4;
-		uint32_t boot_options		: 1;
-		uint32_t rsvd0			: 1;
-		uint32_t bist_state		: 1;
-		uint32_t bist_reset_req		: 1;
-		uint32_t power_source		: 2;
-		uint32_t reserved1		: 1;
-		uint32_t d0i3_support_valid	: 1;
-	} __packed fields;
-};
-
 /* Host Firmware Status Register 2 */
 union hfsts2 {
 	uint32_t raw;
@@ -174,7 +150,7 @@
 		struct version fitc;
 	} __packed;
 
-	union hfsts1 hfsts1;
+	union me_hfsts1 hfsts1;
 	const struct mkhi_hdr fw_ver_msg = {
 		.group_id = MKHI_GEN_GROUP_ID,
 		.command = MKHI_GET_FW_VERSION,
@@ -189,7 +165,7 @@
 	if (!is_cse_enabled())
 		return;
 
-	hfsts1.raw = me_read_config32(PCI_ME_HFSTS1);
+	hfsts1.data = me_read_config32(PCI_ME_HFSTS1);
 
 	/*
 	 * Prerequisites:
@@ -225,7 +201,7 @@
 
 void dump_me_status(void *unused)
 {
-	union hfsts1 hfsts1;
+	union me_hfsts1 hfsts1;
 	union hfsts2 hfsts2;
 	union hfsts3 hfsts3;
 	union hfsts4 hfsts4;
@@ -235,7 +211,7 @@
 	if (!is_cse_enabled())
 		return;
 
-	hfsts1.raw = me_read_config32(PCI_ME_HFSTS1);
+	hfsts1.data = me_read_config32(PCI_ME_HFSTS1);
 	hfsts2.raw = me_read_config32(PCI_ME_HFSTS2);
 	hfsts3.raw = me_read_config32(PCI_ME_HFSTS3);
 	hfsts4.raw = me_read_config32(PCI_ME_HFSTS4);
@@ -243,7 +219,7 @@
 	hfsts6.raw = me_read_config32(PCI_ME_HFSTS6);
 
 	printk(BIOS_DEBUG, "ME: HFSTS1                  : 0x%08X\n",
-		hfsts1.raw);
+		hfsts1.data);
 	printk(BIOS_DEBUG, "ME: HFSTS2                  : 0x%08X\n",
 		hfsts2.raw);
 	printk(BIOS_DEBUG, "ME: HFSTS3                  : 0x%08X\n",
@@ -264,9 +240,9 @@
 	printk(BIOS_DEBUG, "ME: Firmware Init Complete  : %s\n",
 		hfsts1.fields.fw_init_complete ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Boot Options Present    : %s\n",
-		hfsts1.fields.boot_options ? "YES" : "NO");
+		hfsts1.fields.boot_options_present ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Update In Progress      : %s\n",
-		hfsts1.fields.fw_upd_in_progress ? "YES" : "NO");
+		hfsts1.fields.update_in_progress ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: D0i3 Support            : %s\n",
 		hfsts1.fields.d0i3_support_valid ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c
index 1671970..223eab5 100644
--- a/src/soc/intel/common/block/cse/cse.c
+++ b/src/soc/intel/common/block/cse/cse.c
@@ -67,6 +67,7 @@
 #define MEI_HDR_CSE_ADDR_START	0
 #define MEI_HDR_CSE_ADDR	(((1 << 8) - 1) << MEI_HDR_CSE_ADDR_START)
 
+#define HECI_OP_MODE_SEC_OVERRIDE 5
 
 static struct cse_device {
 	uintptr_t sec_bar;
@@ -239,6 +240,43 @@
 	return csr & CSR_READY;
 }
 
+/*
+ * Checks if CSE is in SEC_OVERRIDE operation mode. This is the mode where
+ * CSE will allow reflashing of CSE region.
+ */
+static uint8_t check_cse_sec_override_mode(void)
+{
+	union me_hfsts1 hfs1;
+	hfs1.data = me_read_config32(PCI_ME_HFSTS1);
+	if (hfs1.fields.operation_mode == HECI_OP_MODE_SEC_OVERRIDE)
+		return 1;
+	return 0;
+}
+
+/* Makes the host ready to communicate with CSE */
+void set_host_ready(void)
+{
+	uint32_t csr;
+	csr = read_host_csr();
+	csr &= ~CSR_RESET;
+	csr |= (CSR_IG | CSR_READY);
+	write_host_csr(csr);
+}
+
+/* Polls for ME state 'HECI_OP_MODE_SEC_OVERRIDE' for 15 seconds */
+uint8_t wait_cse_sec_override_mode(void)
+{
+	struct stopwatch sw;
+	stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
+	while (!check_cse_sec_override_mode()) {
+		udelay(HECI_DELAY);
+		if (stopwatch_expired(&sw))
+			return 0;
+	}
+
+	return 1;
+}
+
 static int wait_heci_ready(void)
 {
 	struct stopwatch sw;
@@ -484,17 +522,12 @@
 
 	/* Send reset request */
 	csr = read_host_csr();
-	csr |= CSR_RESET;
-	csr |= CSR_IG;
+	csr |= (CSR_RESET | CSR_IG);
 	write_host_csr(csr);
 
 	if (wait_heci_ready()) {
 		/* Device is back on its imaginary feet, clear reset */
-		csr = read_host_csr();
-		csr &= ~CSR_RESET;
-		csr |= CSR_IG;
-		csr |= CSR_READY;
-		write_host_csr(csr);
+		set_host_ready();
 		return 1;
 	}
 
diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h
index bce615c..30d17c8 100644
--- a/src/soc/intel/common/block/include/intelblocks/cse.h
+++ b/src/soc/intel/common/block/include/intelblocks/cse.h
@@ -29,6 +29,30 @@
 	PCI_ME_HFSTS6 = 0x6C,
 };
 
+/* ME Host Firmware Status register 1 */
+union me_hfsts1 {
+	u32 data;
+	struct {
+		u32 working_state: 4;
+		u32 mfg_mode: 1;
+		u32 fpt_bad: 1;
+		u32 operation_state: 3;
+		u32 fw_init_complete: 1;
+		u32 ft_bup_ld_flr: 1;
+		u32 update_in_progress: 1;
+		u32 error_code: 4;
+		u32 operation_mode: 4;
+		u32 reset_count: 4;
+		u32 boot_options_present: 1;
+		u32 reserved1: 1;
+		u32 bist_test_state: 1;
+		u32 bist_reset_request: 1;
+		u32 current_power_source: 2;
+		u32 d3_support_valid: 1;
+		u32 d0i3_support_valid: 1;
+	} __packed fields;
+};
+
 /* set up device for use in early boot enviroument with temp bar */
 void heci_init(uintptr_t bar);
 /*
@@ -72,6 +96,16 @@
  */
 bool is_cse_enabled(void);
 
+
+/* Makes the host ready to communicate with CSE*/
+void set_host_ready(void);
+
+/*
+ * Polls for ME state 'HECI_OP_MODE_SEC_OVERRIDE' for 15 seconds.
+ * Returns 0 on failure a 1 on success.
+ */
+uint8_t wait_cse_sec_override_mode(void);
+
 #define BIOS_HOST_ADDR							0x00
 #define HECI_MKHI_ADDR							0x07
 
diff --git a/src/soc/intel/skylake/include/soc/me.h b/src/soc/intel/skylake/include/soc/me.h
index fbe5033..ef84f59 100644
--- a/src/soc/intel/skylake/include/soc/me.h
+++ b/src/soc/intel/skylake/include/soc/me.h
@@ -47,30 +47,6 @@
 #define  ME_HFS_POWER_SOURCE_AC 1
 #define  ME_HFS_POWER_SOURCE_DC 2
 
-union me_hfs {
-	u32 data;
-	struct {
-	u32 working_state: 4;
-	u32 mfg_mode: 1;
-	u32 fpt_bad: 1;
-	u32 operation_state: 3;
-	u32 fw_init_complete: 1;
-	u32 ft_bup_ld_flr: 1;
-	u32 update_in_progress: 1;
-	u32 error_code: 4;
-	u32 operation_mode: 4;
-	u32 reset_count: 4;
-	u32 boot_options_present: 1;
-	u32 reserved1: 1;
-	u32 bist_test_state: 1;
-	u32 bist_reset_request: 1;
-	u32 current_power_source: 2;
-	u32 d3_support_valid: 1;
-	u32 d0i3_support_valid: 1;
-	} __packed fields;
-};
-
-#define PCI_ME_HFSTS2		0x48
 /* Infrastructure Progress Values */
 #define  ME_HFS2_PHASE_ROM		0
 #define  ME_HFS2_PHASE_UKERNEL		2
diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c
index 9e17ef1..5fc817f 100644
--- a/src/soc/intel/skylake/me.c
+++ b/src/soc/intel/skylake/me.c
@@ -229,7 +229,7 @@
 
 	struct fw_ver_resp resp;
 	size_t resp_size = sizeof(resp);
-	union me_hfs hfs;
+	union me_hfsts1 hfs1;
 
 	/*
 	 * Print ME version only if UART debugging is enabled. Else, it takes ~1
@@ -241,14 +241,14 @@
 	if (!is_cse_enabled())
 		return;
 
-	hfs.data = me_read_config32(PCI_ME_HFSTS1);
+	hfs1.data = me_read_config32(PCI_ME_HFSTS1);
 	/*
 	 * This command can be run only if:
 	 * - Working state is normal and
 	 * - Operation mode is normal.
 	 */
-	if ((hfs.fields.working_state != ME_HFS_CWS_NORMAL) ||
-	    (hfs.fields.operation_mode != ME_HFS_MODE_NORMAL))
+	if ((hfs1.fields.working_state != ME_HFS_CWS_NORMAL) ||
+	    (hfs1.fields.operation_mode != ME_HFS_MODE_NORMAL))
 		goto failed;
 
 	/*
@@ -282,7 +282,7 @@
 
 void intel_me_status(void)
 {
-	union me_hfs hfs;
+	union me_hfsts1 hfs1;
 	union me_hfs2 hfs2;
 	union me_hfs3 hfs3;
 	union me_hfs6 hfs6;
@@ -290,13 +290,13 @@
 	if (!is_cse_enabled())
 		return;
 
-	hfs.data = me_read_config32(PCI_ME_HFSTS1);
+	hfs1.data = me_read_config32(PCI_ME_HFSTS1);
 	hfs2.data = me_read_config32(PCI_ME_HFSTS2);
 	hfs3.data = me_read_config32(PCI_ME_HFSTS3);
 	hfs6.data = me_read_config32(PCI_ME_HFSTS6);
 
 	printk(BIOS_DEBUG, "ME: Host Firmware Status Register 1 : 0x%08X\n",
-		hfs.data);
+		hfs1.data);
 	printk(BIOS_DEBUG, "ME: Host Firmware Status Register 2 : 0x%08X\n",
 		hfs2.data);
 	printk(BIOS_DEBUG, "ME: Host Firmware Status Register 3 : 0x%08X\n",
@@ -309,21 +309,21 @@
 		hfs6.data);
 	/* Check Current States */
 	printk(BIOS_DEBUG, "ME: FW Partition Table      : %s\n",
-	       hfs.fields.fpt_bad ? "BAD" : "OK");
+	       hfs1.fields.fpt_bad ? "BAD" : "OK");
 	printk(BIOS_DEBUG, "ME: Bringup Loader Failure  : %s\n",
-	       hfs.fields.ft_bup_ld_flr ? "YES" : "NO");
+	       hfs1.fields.ft_bup_ld_flr ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Firmware Init Complete  : %s\n",
-	       hfs.fields.fw_init_complete ? "YES" : "NO");
+	       hfs1.fields.fw_init_complete ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Manufacturing Mode      : %s\n",
-	       hfs.fields.mfg_mode ? "YES" : "NO");
+	       hfs1.fields.mfg_mode ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Boot Options Present    : %s\n",
-	       hfs.fields.boot_options_present ? "YES" : "NO");
+	       hfs1.fields.boot_options_present ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Update In Progress      : %s\n",
-	       hfs.fields.update_in_progress ? "YES" : "NO");
+	       hfs1.fields.update_in_progress ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: D3 Support              : %s\n",
-	       hfs.fields.d3_support_valid ? "YES" : "NO");
+	       hfs1.fields.d3_support_valid ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: D0i3 Support            : %s\n",
-	       hfs.fields.d0i3_support_valid ? "YES" : "NO");
+	       hfs1.fields.d0i3_support_valid ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
 	       hfs2.fields.low_power_state ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: CPU Replaced            : %s\n",
@@ -331,13 +331,13 @@
 	printk(BIOS_DEBUG, "ME: CPU Replacement Valid   : %s\n",
 	       hfs2.fields.cpu_replaced_valid ? "YES" : "NO");
 	printk(BIOS_DEBUG, "ME: Current Working State   : %s\n",
-	       me_cws_values[hfs.fields.working_state]);
+	       me_cws_values[hfs1.fields.working_state]);
 	printk(BIOS_DEBUG, "ME: Current Operation State : %s\n",
-	       me_opstate_values[hfs.fields.operation_state]);
+	       me_opstate_values[hfs1.fields.operation_state]);
 	printk(BIOS_DEBUG, "ME: Current Operation Mode  : %s\n",
-	       me_opmode_values[hfs.fields.operation_mode]);
+	       me_opmode_values[hfs1.fields.operation_mode]);
 	printk(BIOS_DEBUG, "ME: Error Code              : %s\n",
-	       me_error_values[hfs.fields.error_code]);
+	       me_error_values[hfs1.fields.error_code]);
 	printk(BIOS_DEBUG, "ME: Progress Phase          : %s\n",
 	       me_progress_values[hfs2.fields.progress_code]);
 	printk(BIOS_DEBUG, "ME: Power Management Event  : %s\n",
@@ -484,14 +484,14 @@
 int send_global_reset(void)
 {
 	int status = -1;
-	union me_hfs hfs;
+	union me_hfsts1 hfs1;
 
 	if (!is_cse_enabled())
 		goto ret;
 
 	/* Check ME operating mode */
-	hfs.data = me_read_config32(PCI_ME_HFSTS1);
-	if (hfs.fields.operation_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 */