diff options
Diffstat (limited to 'src/soc/intel/common/block/cse/cse.c')
-rw-r--r-- | src/soc/intel/common/block/cse/cse.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c index d697c84a97..2928a4e6c6 100644 --- a/src/soc/intel/common/block/cse/cse.c +++ b/src/soc/intel/common/block/cse/cse.c @@ -247,6 +247,15 @@ static bool cse_check_hfs1_com(int mode) return hfs1.fields.operation_mode == mode; } +static bool cse_is_hfs1_fw_init_complete(void) +{ + union me_hfsts1 hfs1; + hfs1.data = me_read_config32(PCI_ME_HFSTS1); + if (hfs1.fields.fw_init_complete) + return true; + return false; +} + bool cse_is_hfs1_cws_normal(void) { union me_hfsts1 hfs1; @@ -1069,6 +1078,154 @@ void cse_control_global_reset_lock(void) pmc_global_reset_enable(false); } +enum cb_err cse_get_fw_feature_state(uint32_t *feature_state) +{ + struct fw_feature_state_msg { + struct mkhi_hdr hdr; + uint32_t rule_id; + } __packed; + + /* Get Firmware Feature State message */ + struct fw_feature_state_msg msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_FWCAPS, + .command = MKHI_FWCAPS_GET_FW_FEATURE_STATE, + }, + .rule_id = ME_FEATURE_STATE_RULE_ID + }; + + /* Get Firmware Feature State response */ + struct fw_feature_state_resp { + struct mkhi_hdr hdr; + uint32_t rule_id; + uint8_t rule_len; + uint32_t fw_runtime_status; + } __packed; + + struct fw_feature_state_resp resp; + size_t resp_size = sizeof(struct fw_feature_state_resp); + + /* Ignore if CSE is disabled or input buffer is invalid */ + if (!is_cse_enabled() || !feature_state) + return CB_ERR; + + /* + * Prerequisites: + * 1) HFSTS1 Current Working State is Normal + * 2) HFSTS1 Current Operation Mode is Normal + * 3) It's after DRAM INIT DONE message (taken care of by calling it + * during ramstage) + */ + if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal() || !ENV_RAMSTAGE) + return CB_ERR; + + printk(BIOS_DEBUG, "HECI: Send GET FW FEATURE STATE Command\n"); + + if (heci_send_receive(&msg, sizeof(struct fw_feature_state_msg), + &resp, &resp_size, HECI_MKHI_ADDR)) + return CB_ERR; + + if (resp.hdr.result) { + printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result); + return CB_ERR; + } + + if (resp.rule_len != sizeof(resp.fw_runtime_status)) { + printk(BIOS_ERR, "HECI: GET FW FEATURE STATE has invalid rule data length\n"); + return CB_ERR; + } + + *feature_state = resp.fw_runtime_status; + + return CB_SUCCESS; +} + +void cse_enable_ptt(bool state) +{ + struct fw_feature_shipment_override_msg { + struct mkhi_hdr hdr; + uint32_t enable_mask; + uint32_t disable_mask; + } __packed; + + /* FW Feature Shipment Time State Override message */ + struct fw_feature_shipment_override_msg msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_GEN, + .command = MKHI_GEN_FW_FEATURE_SHIPMENT_OVER, + }, + .enable_mask = 0, + .disable_mask = 0 + }; + + /* FW Feature Shipment Time State Override response */ + struct fw_feature_shipment_override_resp { + struct mkhi_hdr hdr; + uint32_t data; + } __packed; + + struct fw_feature_shipment_override_resp resp; + size_t resp_size = sizeof(struct fw_feature_shipment_override_resp); + uint32_t feature_status; + + /* Ignore if CSE is disabled */ + if (!is_cse_enabled()) + return; + + printk(BIOS_DEBUG, "Requested to change PTT state to %sabled\n", state ? "en" : "dis"); + + /* + * Prerequisites: + * 1) HFSTS1 Current Working State is Normal + * 2) HFSTS1 Current Operation Mode is Normal + * 3) It's after DRAM INIT DONE message (taken care of by calling it + * during ramstage + * 4) HFSTS1 FW Init Complete is set + * 5) Before EOP issued to CSE + */ + if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal() || + !cse_is_hfs1_fw_init_complete() || !ENV_RAMSTAGE) { + printk(BIOS_ERR, "HECI: Unmet prerequisites for" + "FW FEATURE SHIPMENT TIME STATE OVERRIDE\n"); + return; + } + + if (cse_get_fw_feature_state(&feature_status) != CB_SUCCESS) { + printk(BIOS_ERR, "HECI: Cannot determine current feature status\n"); + return; + } + + if (!!(feature_status & ME_FW_FEATURE_PTT) == state) { + printk(BIOS_DEBUG, "HECI: PTT is already in the requested state\n"); + return; + } + + printk(BIOS_DEBUG, "HECI: Send FW FEATURE SHIPMENT TIME STATE OVERRIDE Command\n"); + + if (state) + msg.enable_mask |= ME_FW_FEATURE_PTT; + else + msg.disable_mask |= ME_FW_FEATURE_PTT; + + if (heci_send_receive(&msg, sizeof(struct fw_feature_shipment_override_msg), + &resp, &resp_size, HECI_MKHI_ADDR)) + return; + + if (resp.hdr.result) { + printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result); + return; + } + + /* Global reset is required after acceptance of the command */ + if (resp.data == 0) { + printk(BIOS_DEBUG, "HECI: FW FEATURE SHIPMENT TIME STATE OVERRIDE success\n"); + do_global_reset(); + } else { + printk(BIOS_ERR, "HECI: FW FEATURE SHIPMENT TIME STATE OVERRIDE error (%x)\n", + resp.data); + } +} + #if ENV_RAMSTAGE /* |