diff options
Diffstat (limited to 'src/soc/intel/apollolake')
-rw-r--r-- | src/soc/intel/apollolake/Kconfig | 1 | ||||
-rw-r--r-- | src/soc/intel/apollolake/Makefile.inc | 5 | ||||
-rw-r--r-- | src/soc/intel/apollolake/heci.c | 22 | ||||
-rw-r--r-- | src/soc/intel/apollolake/include/soc/heci.h | 23 | ||||
-rw-r--r-- | src/soc/intel/apollolake/reset.c | 44 |
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) { |