diff options
Diffstat (limited to 'src/soc/intel/common/block/cse/cse.c')
-rw-r--r-- | src/soc/intel/common/block/cse/cse.c | 47 |
1 files changed, 40 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; } |