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)
diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h
index 9753798..c00e227 100644
--- a/src/soc/intel/common/block/include/intelblocks/cse.h
+++ b/src/soc/intel/common/block/include/intelblocks/cse.h
@@ -281,4 +281,15 @@
/* Trigger vboot recovery mode on a CSE error */
void cse_trigger_vboot_recovery(enum csme_failure_reason reason);
+enum cse_device_state {
+ DEV_IDLE,
+ DEV_ACTIVE,
+};
+
+/* Function to get the current CSE device state as per `cse_device_state` */
+enum cse_device_state get_cse_device_state(void);
+
+/* Function that put the CSE into desired state based on `requested_state` */
+bool set_cse_device_state(enum cse_device_state requested_state);
+
#endif // SOC_INTEL_COMMON_CSE_H