Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions meta-facebook/gc2-es/src/ipmi/plat_ipmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
#include "fru.h"
#include "hal_gpio.h"
#include "ipmi.h"
#include "power_status.h"
#include "libutil.h"
#include "plat_class.h"
#include "plat_fru.h"
#include "plat_ipmb.h"
#include "plat_dimm.h"
#include <logging/log.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -263,3 +265,167 @@ void OEM_1S_SET_GPIO_CONFIG(ipmi_msg *msg)
msg->data_len = 0;
msg->completion_code = CC_SUCCESS;
}

/*
Byte 0 - DIMM location
00h - A0
01h - A2
02h - A3
03h - A4
04h - A6
05h - A7
Byte 1: Device type
00h - SPD
01h - SPD NVM
02h - PMIC
Byte 2: Read/write data length
Byte 3:4: 2byte offset
Byte 5:~ write data
*/
void OEM_1S_WRITE_READ_DIMM(ipmi_msg *msg)
{
CHECK_NULL_ARG(msg);

// At least include DIMM location, device type, write/read len, offset
if (msg->data_len < 4) {
msg->completion_code = CC_INVALID_LENGTH;
return;
}

int ret = 0;
uint8_t dimm_id = msg->data[0];
uint8_t device_type = msg->data[1];

// If host is DC on, BIC can't read DIMM information via I3C
// Return failed and BMC asks ME
if (get_DC_status()) {
msg->completion_code = CC_NOT_SUPP_IN_CURR_STATE;
return;
}

I3C_MSG i3c_msg = { 0 };
i3c_msg.bus = I3C_BUS3;
i3c_msg.tx_len = msg->data_len - 3;
i3c_msg.rx_len = msg->data[2];

// Check offset byte count: SPD_NVM has 2 bytes offset
if (device_type == DIMM_SPD_NVM) {
if (i3c_msg.tx_len < 2) {
msg->completion_code = CC_INVALID_DATA_FIELD;
return;
}
} else {
// One byte offset
if (i3c_msg.tx_len < 1) {
msg->completion_code = CC_INVALID_DATA_FIELD;
return;
}
}

memcpy(&i3c_msg.data[0], &msg->data[3], i3c_msg.tx_len);
msg->data_len = i3c_msg.rx_len;

if (k_mutex_lock(&i3c_dimm_mux_mutex, K_MSEC(I3C_DIMM_MUX_MUTEX_TIMEOUT_MS))) {
LOG_ERR("Failed to lock I3C dimm MUX");
msg->completion_code = CC_NODE_BUSY;
return;
}

ret = switch_i3c_dimm_mux(I3C_MUX_TO_BIC, dimm_id / (MAX_COUNT_DIMM / 2));
if (ret < 0) {
msg->completion_code = CC_UNSPECIFIED_ERROR;
goto exit;
}

// I3C_CCC_RSTDAA: Reset dynamic address assignment
// I3C_CCC_SETAASA: Set all addresses to static address
ret = all_brocast_ccc(&i3c_msg);
if (ret != 0) {
LOG_ERR("Failed to brocast CCC, ret%d bus%d", ret, i3c_msg.bus);
msg->completion_code = CC_UNSPECIFIED_ERROR;
goto exit;
}

switch (device_type) {
case DIMM_SPD:
case DIMM_SPD_NVM:
i3c_msg.target_addr = spd_i3c_addr_list[dimm_id % (MAX_COUNT_DIMM / 2)];

if (device_type == DIMM_SPD_NVM) {
ret = i3c_spd_reg_read(&i3c_msg, true);
} else {
ret = i3c_spd_reg_read(&i3c_msg, false);
}

if (ret != 0) {
LOG_ERR("Failed to read SPD addr0x%x offset0x%x, ret%d",
i3c_msg.target_addr, i3c_msg.data[0], ret);
msg->completion_code = CC_UNSPECIFIED_ERROR;
} else {
memcpy(&msg->data[0], &i3c_msg.data, i3c_msg.rx_len);
msg->data_len = i3c_msg.rx_len;
msg->completion_code = CC_SUCCESS;
}
break;

case DIMM_PMIC:
i3c_msg.target_addr = pmic_i3c_addr_list[dimm_id % (MAX_COUNT_DIMM / 2)];

ret = i3c_transfer(&i3c_msg);
if (ret != 0) {
LOG_ERR("Failed to read PMIC addr0x%x offset0x%x, ret%d bus%d",
i3c_msg.target_addr, i3c_msg.data[0], ret, i3c_msg.bus);
msg->completion_code = CC_UNSPECIFIED_ERROR;
} else {
memcpy(&msg->data[0], &i3c_msg.data, i3c_msg.rx_len);
msg->data_len = i3c_msg.rx_len;
msg->completion_code = CC_SUCCESS;
}
break;

default:
msg->completion_code = CC_INVALID_DATA_FIELD;
break;
}

exit:
// Switch I3C MUX to CPU after read finish
switch_i3c_dimm_mux(I3C_MUX_TO_CPU, DIMM_MUX_TO_DIMM_A0A1A3);

if (k_mutex_unlock(&i3c_dimm_mux_mutex)) {
LOG_ERR("Failed to unlock I3C dimm MUX");
}
}

void OEM_1S_GET_DIMM_I3C_MUX_SELECTION(ipmi_msg *msg)
{
CHECK_NULL_ARG(msg);

I2C_MSG i2c_msg = { 0 };
int ret = 0, retry = 3;

i2c_msg.bus = I2C_BUS1;
i2c_msg.target_addr = CPLD_ADDR;
i2c_msg.tx_len = 1;
i2c_msg.rx_len = 1;
i2c_msg.data[0] = DIMM_I3C_MUX_CONTROL_OFFSET;

ret = i2c_master_read(&i2c_msg, retry);
if (ret != 0) {
LOG_ERR("Failed to read I3C MUX status, ret=%d", ret);
return;
}

if (GETBIT(i2c_msg.data[0], 0) == I3C_MUX_TO_CPU) {
msg->data[0] = I3C_MUX_TO_CPU;
} else if (GETBIT(i2c_msg.data[0], 0) == I3C_MUX_TO_BIC) {
msg->data[0] = I3C_MUX_TO_BIC;
} else {
msg->completion_code = CC_UNSPECIFIED_ERROR;
return;
}

msg->completion_code = CC_SUCCESS;
msg->data_len = 1;
return;
}
Loading
Loading