diff options
author | Sridhar Siricilla <sridhar.siricilla@intel.com> | 2019-08-31 11:38:33 +0530 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2019-09-12 13:14:39 +0000 |
commit | b9d075b0fc12c26316eaaca2de6bfa659f0cb6c1 (patch) | |
tree | bd2eb747d26da36f66cca594462d3ef4c8212ad0 /src/soc/intel/common | |
parent | bc553e6a5beee3db02cfd27e3a5e410857e78897 (diff) |
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>
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r-- | src/soc/intel/common/block/cse/cse.c | 47 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/cse.h | 34 |
2 files changed, 74 insertions, 7 deletions
diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c index 1671970a19..223eab5fb2 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 @@ static int cse_ready(void) 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 @@ int heci_reset(void) /* 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 bce615c172..30d17c865a 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 @@ enum { 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 @@ uint32_t me_read_config32(int offset); */ 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 |