void op_display(enum op_severity sev, enum op_module mod, uint16_t code) { struct fsp_msg *op_msg; uint32_t w0; uint32_t w1; if (!fsp_present()) return; w0 = sev << 16 | mod; w1 = tohex((code >> 12) & 0xf) << 24; w1 |= tohex((code >> 8) & 0xf) << 16; w1 |= tohex((code >> 4) & 0xf) << 8; w1 |= tohex((code ) & 0xf); if (sev == OP_FATAL) { fsp_op_display_fatal(w0, w1); } else { op_msg = fsp_allocmsg(true); if (!op_msg) { prerror("Failed to allocate FSP message for PANEL\n"); return; } fsp_fillmsg(op_msg, FSP_CMD_DISP_SRC_DIRECT, 3, 1, w0, w1); if(fsp_queue_msg(op_msg, fsp_freemsg)) prerror("Failed to queue FSP message for OP PANEL\n"); } }
static bool send_response_to_fsp(u32 cmd_sub_mod) { struct fsp_msg *rsp; int rc = -ENOMEM; rsp = fsp_mkmsg(cmd_sub_mod, 0); if (rsp) rc = fsp_queue_msg(rsp, fsp_freemsg); if (rc) { fsp_freemsg(rsp); /* XXX Generate error logs */ prerror("Error %d queueing FSP memory error reply\n", rc); return false; } return true; }
static bool fsp_chiptod_update_topology(uint32_t cmd_sub_mod, struct fsp_msg *msg) { struct fsp_msg *resp; enum chiptod_topology topo; bool action; uint8_t status = 0; switch (cmd_sub_mod) { case FSP_CMD_TOPO_ENABLE_DISABLE: /* * Action Values: 0x00 = Disable, 0x01 = Enable * Topology Values: 0x00 = Primary, 0x01 = Secondary */ action = !!msg->data.bytes[2]; topo = msg->data.bytes[3]; prlog(PR_DEBUG, "Topology update event:\n"); prlog(PR_DEBUG, " Action = %s, Topology = %s\n", action ? "Enable" : "Disable", topo ? "Secondary" : "Primary"); if (!chiptod_adjust_topology(topo, action)) status = FSP_STATUS_TOPO_IN_USE; else status = 0x00; resp = fsp_mkmsg(FSP_RSP_TOPO_ENABLE_DISABLE | status, 0); if (!resp) { prerror("Response allocation failed\n"); return false; } if (fsp_queue_msg(resp, fsp_freemsg)) { fsp_freemsg(resp); prerror("Failed to queue response msg\n"); return false; } return true; default: prlog(PR_DEBUG, "Unhandled sub cmd: %06x\n", cmd_sub_mod); break; } return false; }
/* Process captured EPOW event notification */ static void fsp_process_epow(struct fsp_msg *msg, int epow_type) { struct fsp_msg *resp; u8 epow[8]; /* Basic EPOW signature */ if (msg->data.bytes[0] != 0xF2) { prlog(PR_ERR, "Signature mismatch\n"); return; } /* Common to all EPOW event types */ epow[0] = msg->data.bytes[0]; epow[1] = msg->data.bytes[1]; epow[2] = msg->data.bytes[2]; epow[3] = msg->data.bytes[3]; /* * After receiving the FSP async message, HV needs to * ask for the detailed panel status through corresponding * mbox command. HV need not use the received details status * as it does not have any thing more or new than what came * along with the original FSP async message. But requesting * for the detailed panel status exclussively is necessary as * it forms a kind of handshaking with the FSP. Without this * step, FSP wont be sending any new panel status messages. */ switch(epow_type) { case EPOW_NORMAL: resp = fsp_mkmsg(FSP_CMD_STATUS_REQ, 0); if (resp == NULL) { prerror("%s : Message allocation failed\n", __func__); break; } if (fsp_queue_msg(resp, fsp_freemsg)) { fsp_freemsg(resp); prerror("%s : Failed to queue response " "message\n", __func__); } break; case EPOW_EX1: /* EPOW_EX1 specific extra event data */ epow[4] = msg->data.bytes[4]; resp = fsp_mkmsg(FSP_CMD_STATUS_EX1_REQ, 0); if (resp == NULL) { prerror("%s : Message allocation failed\n", __func__); break; } if (fsp_queue_msg(resp, fsp_freemsg)) { fsp_freemsg(resp); prerror("%s : Failed to queue response " "message\n", __func__); } break; case EPOW_EX2: resp = fsp_mkmsg(FSP_CMD_STATUS_EX2_REQ, 0); if (resp == NULL) { prerror("%s : Message allocation failed\n", __func__); break; } if (fsp_queue_msg(resp, fsp_freemsg)) { fsp_freemsg(resp); prerror("%s : Failed to queue response " "message\n", __func__); } break; default: prlog(PR_WARNING, "Unknown EPOW event notification\n"); return; } fsp_epow_update(epow, epow_type); }