aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/common/block/cse/cse.c157
-rw-r--r--src/soc/intel/common/block/include/intelblocks/cse.h20
2 files changed, 177 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
/*
diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h
index b031aa3390..4634984756 100644
--- a/src/soc/intel/common/block/include/intelblocks/cse.h
+++ b/src/soc/intel/common/block/include/intelblocks/cse.h
@@ -30,6 +30,14 @@
/* Get Firmware Version Command Id */
#define MKHI_GEN_GET_FW_VERSION 0x2
+/* Firmware Feature Shipment Time State Override Command Id */
+#define MKHI_GEN_FW_FEATURE_SHIPMENT_OVER 0x14
+#define ME_FW_FEATURE_PTT BIT(29)
+
+/* Get Firmware Feature State Command Id */
+#define MKHI_FWCAPS_GET_FW_FEATURE_STATE 0x02
+#define ME_FEATURE_STATE_RULE_ID 0x20
+
/* MEI bus disable command. Must be sent to MEI client endpoint, not MKHI */
#define MEI_BUS_DISABLE_COMMAND 0xc
@@ -567,4 +575,16 @@ void cse_get_telemetry_data(void);
/* Function to log the cse WP information like range, if WP etc. */
void cse_log_ro_write_protection_info(bool mfg_mode);
+/*
+ * Changes Intel PTT feature state at runtime. Global reset is required after
+ * successful HECI command completion.
+ */
+void cse_enable_ptt(bool state);
+
+/*
+ * Queries CSE for runtime status of firmware features.
+ * Returns 0 on success and < 0 on failure.
+ */
+enum cb_err cse_get_fw_feature_state(uint32_t *feature_state);
+
#endif // SOC_INTEL_COMMON_CSE_H