aboutsummaryrefslogtreecommitdiff
path: root/src/soc/intel/apollolake
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/apollolake')
-rw-r--r--src/soc/intel/apollolake/Kconfig1
-rw-r--r--src/soc/intel/apollolake/Makefile.inc5
-rw-r--r--src/soc/intel/apollolake/heci.c22
-rw-r--r--src/soc/intel/apollolake/include/soc/heci.h23
-rw-r--r--src/soc/intel/apollolake/reset.c44
5 files changed, 95 insertions, 0 deletions
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 8a786daea2..a30333bb68 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -99,6 +99,7 @@ config CPU_SPECIFIC_OPTIONS
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 b9d302c1e4..79fab1a9d1 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -12,6 +12,7 @@ subdirs-y += ../../../cpu/x86/cache
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 += ../../../cpu/intel/car/romstage.c
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 += cse.c
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 @@ ramstage-y += xhci.c
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 @@ postcar-y += gspi.c
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 0000000000..52dcca8de2
--- /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 c62ce7842b..d8a7f2a9b5 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 7eac9648bc..8641b63aaf 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)
{