soc/intel/common/../cse: Create APIs for CSE device state transition

This patch ensures APIs that are responsible for CSE device state
transition between active to idle and vice-versa are available
publically for other modules/boot stages to consume.

BUG=b:200644229
TEST=Able to build and boot ADLRVP-P.

Change-Id: Ia480877822d343f2b4c9bf87b246812186d49ea3
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57804
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-by: Maulik V Vaghela <maulik.v.vaghela@intel.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c
index 1cea7d9..10f9606 100644
--- a/src/soc/intel/common/block/cse/cse.c
+++ b/src/soc/intel/common/block/cse/cse.c
@@ -27,6 +27,8 @@
 #define HECI_SEND_TIMEOUT	(5 * 1000)
 /* Wait up to 5 sec for CSE to blurp a reply */
 #define HECI_READ_TIMEOUT	(5 * 1000)
+/* Wait up to 1 ms for CSE CIP */
+#define HECI_CIP_TIMEOUT	1000
 
 #define SLOT_SIZE		sizeof(uint32_t)
 
@@ -34,6 +36,9 @@
 #define MMIO_HOST_CSR		0x04
 #define MMIO_CSE_CB_RW		0x08
 #define MMIO_CSE_CSR		0x0c
+#define MMIO_CSE_DEVIDLE	0x800
+#define  CSE_DEV_IDLE		(1 << 2)
+#define  CSE_DEV_CIP		(1 << 0)
 
 #define CSR_IE			(1 << 0)
 #define CSR_IS			(1 << 1)
@@ -895,6 +900,73 @@
 	die("cse: Failed to trigger recovery mode(recovery subcode:%d)\n", reason);
 }
 
+static bool disable_cse_idle(void)
+{
+	struct stopwatch sw;
+	uint32_t dev_idle_ctrl = read_bar(MMIO_CSE_DEVIDLE);
+	dev_idle_ctrl &= ~CSE_DEV_IDLE;
+	write_bar(MMIO_CSE_DEVIDLE, dev_idle_ctrl);
+
+	stopwatch_init_usecs_expire(&sw, HECI_CIP_TIMEOUT);
+	do {
+		dev_idle_ctrl = read_bar(MMIO_CSE_DEVIDLE);
+		if ((dev_idle_ctrl & CSE_DEV_CIP) == CSE_DEV_CIP)
+			return true;
+		udelay(HECI_DELAY);
+	} while (!stopwatch_expired(&sw));
+
+	return false;
+}
+
+static void enable_cse_idle(void)
+{
+	uint32_t dev_idle_ctrl = read_bar(MMIO_CSE_DEVIDLE);
+	dev_idle_ctrl |= CSE_DEV_IDLE;
+	write_bar(MMIO_CSE_DEVIDLE, dev_idle_ctrl);
+}
+
+enum cse_device_state get_cse_device_state(void)
+{
+	uint32_t dev_idle_ctrl = read_bar(MMIO_CSE_DEVIDLE);
+	if ((dev_idle_ctrl & CSE_DEV_IDLE) == CSE_DEV_IDLE)
+		return DEV_IDLE;
+
+	return DEV_ACTIVE;
+}
+
+static enum cse_device_state ensure_cse_active(void)
+{
+	if (!disable_cse_idle())
+		return DEV_IDLE;
+	pci_or_config32(PCH_DEV_CSE, PCI_COMMAND, PCI_COMMAND_MEMORY |
+				 PCI_COMMAND_MASTER);
+
+	return DEV_ACTIVE;
+}
+
+static void ensure_cse_idle(void)
+{
+	enable_cse_idle();
+
+	pci_and_config32(PCH_DEV_CSE, PCI_COMMAND, ~(PCI_COMMAND_MEMORY |
+				 PCI_COMMAND_MASTER));
+}
+
+bool set_cse_device_state(enum cse_device_state requested_state)
+{
+	enum cse_device_state current_state = get_cse_device_state();
+
+	if (current_state == requested_state)
+		return true;
+
+	if (requested_state == DEV_ACTIVE)
+		return ensure_cse_active() == requested_state;
+	else
+		ensure_cse_idle();
+
+	return true;
+}
+
 #if ENV_RAMSTAGE
 
 static void update_sec_bar(struct device *dev)