meta-facebook/yv35-cl/src/platform/platform.c (119 lines of code) (raw):

#include <zephyr.h> #include <stdlib.h> #include "ipmi.h" #include "plat_gpio.h" #define ME_FW_recovery 0x01 #define ME_FW_restore 0x02 static void set_ME_FW_mode(uint8_t ME_FW_mode) { ipmi_msg *me_msg; ipmb_error status; me_msg = (ipmi_msg *)malloc(sizeof(ipmi_msg)); if (me_msg == NULL) { printk("ME restore msg alloc fail\n"); return false; } me_msg->seq_source = 0xFF; me_msg->netfn = NETFN_NM_REQ; me_msg->cmd = 0xDF; // Get Intel ME FW Capabilities me_msg->InF_source = Self_IFs; me_msg->InF_target = ME_IPMB_IFs; me_msg->data_len = 4; me_msg->data[0] = 0x57; me_msg->data[1] = 0x01; me_msg->data[2] = 0x00; me_msg->data[3] = ME_FW_mode; status = ipmb_read(me_msg, IPMB_inf_index_map[me_msg->InF_target]); if (status != ipmb_error_success) { printk("set_ME_FW_mode reach ME fail with status: %x\n", status); } free(me_msg); return; } static void ME_enter_restore() { set_ME_FW_mode(ME_FW_restore); return; } static void ME_enter_recovery() { ipmi_msg *me_msg; ipmb_error status; uint8_t retry = 3; for (int i = 0; i < retry; i++) { set_ME_FW_mode(ME_FW_recovery); k_msleep(2000); me_msg = (ipmi_msg *)malloc(sizeof(ipmi_msg)); if (me_msg == NULL) { printk("ME recovery msg alloc fail\n"); k_msleep(10); continue; } me_msg->seq_source = 0xFF; me_msg->netfn = NETFN_APP_REQ; me_msg->cmd = CMD_APP_GET_SELFTEST_RESULTS; me_msg->InF_source = Self_IFs; me_msg->InF_target = ME_IPMB_IFs; me_msg->data_len = 0; status = ipmb_read(me_msg, IPMB_inf_index_map[me_msg->InF_target]); if (status == ipmb_error_success) { if ((me_msg->data_len == 2) && (me_msg->data[0] == 0x81) && (me_msg->data[1] == 0x02)) { free(me_msg); break; } } else { printk("ME restore get selftest fail with status: %x\n", status); } if (me_msg != NULL) { free(me_msg); } } return; } void set_ME_restore() { ipmi_msg *me_msg; ipmb_error status; me_msg = (ipmi_msg *)malloc(sizeof(ipmi_msg)); if (me_msg == NULL) { printk("ME restore msg alloc fail\n"); return; } me_msg->seq_source = 0xFF; me_msg->netfn = NETFN_APP_REQ; me_msg->cmd = CMD_APP_GET_SELFTEST_RESULTS; me_msg->InF_source = Self_IFs; me_msg->InF_target = ME_IPMB_IFs; me_msg->data_len = 0; status = ipmb_read(me_msg, IPMB_inf_index_map[me_msg->InF_target]); if (status == ipmb_error_success) { if ((me_msg->data_len == 2) && (me_msg->data[0] == 0x81) && (me_msg->data[1] == 0x02)) { ME_enter_restore(); } } else { printk("ME restore get selftest fail with status: %x\n", status); } free(me_msg); return; } void pal_warm_reset_prepare() { ME_enter_recovery(); } void pal_cold_reset_prepare() { ME_enter_recovery(); } /* BMC reset */ void BMC_reset_handler() { gpio_set(RST_BMC_R_N, GPIO_LOW); k_msleep(10); gpio_set(RST_BMC_R_N, GPIO_HIGH); } K_WORK_DELAYABLE_DEFINE(BMC_reset_work, BMC_reset_handler); void submit_bmc_warm_reset() { k_work_schedule(&BMC_reset_work, K_MSEC(1000)); } /* BMC reset */