Add SCOM read/write routines to FSI file

Read all relevant early IPL registers and
decode as part of sbe_status command.
parent ceccd14e
Pipeline #243 passed with stage
in 19 seconds
// © 2020 Raptor Engineering, LLC
// © 2020 - 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
......@@ -33,6 +33,28 @@
#define IBM_POWER9_ROOT_CTRL8 0x2918
#define IBM_POWER9_ROOT_CTRL1_CLEAR 0x2931
// SCOM definitions
#define IBM_POWER9_SCOM_PIB_BASE 0x1000
#define IBM_SCOM_FSI_CMD_REG 0x08
#define IBM_SCOM_FSI_STATUS_REG 0x1c
#define IBM_SCOM_FSI_RESET_REG 0x1c
#define IBM_SCOM_FSI_DATA0_REG 0x00
#define IBM_SCOM_FSI_DATA1_REG 0x04
#define IBM_SCOM_FSI2PIB_RESET_REG 0x18
#define IBM_SCOM_FSI_CMD_READ 0x00000000
#define IBM_SCOM_FSI_CMD_WRITE 0x80000000
#define IBM_SCOM_PIB_RESULT_SUCCESS 0
#define IBM_SCOM_PIB_RESULT_BLOCKED 1
#define IBM_SCOM_PIB_RESULT_OFFLINE 2
#define IBM_SCOM_PIB_RESULT_PARTIAL 3
#define IBM_SCOM_PIB_RESULT_BAD_ADDR 4
#define IBM_SCOM_PIB_RESULT_CLK_ERR 5
#define IBM_SCOM_PIB_RESULT_PARITY_ERR 6
#define IBM_SCOM_PIB_RESULT_TIMEOUT 7
// Platform data
#define IBM_POWER9_SLAVE_ID 0
......@@ -137,6 +159,101 @@ static int access_cfam(uint8_t slave_id, uint32_t cfam_address, fsi_data_length_
return access_fsi_mem(slave_id, fsi_address, data_length, write, data);
}
static int access_scom_fsi_handler(uint8_t slave_id, uint32_t scom_address, uint8_t write, uint64_t *data, uint32_t *scom_status)
{
uint32_t upload_data;
uint32_t response_data;
uint32_t cmd_data = scom_address;
if (write)
{
cmd_data |= IBM_SCOM_FSI_CMD_WRITE;
// Write SCOM data to buffer
upload_data = (*data >> 32) & 0xffffffff;
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_DATA0_REG, FSI_DATA_LENGTH_WORD, 1, &upload_data))
{
goto fail;
}
upload_data = (*data >> 0) & 0xffffffff;
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_DATA1_REG, FSI_DATA_LENGTH_WORD, 1, &upload_data))
{
goto fail;
}
// Write SCOM access request
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_CMD_REG, FSI_DATA_LENGTH_WORD, 1, &cmd_data))
{
goto fail;
}
// Read SCOM status register
response_data = 0;
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_STATUS_REG, FSI_DATA_LENGTH_WORD, 0, &response_data))
{
goto fail;
}
*scom_status = response_data;
}
else
{
*data = 0;
cmd_data |= IBM_SCOM_FSI_CMD_READ;
// Write SCOM access request
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_CMD_REG, FSI_DATA_LENGTH_WORD, 1, &cmd_data))
{
goto fail;
}
// Read SCOM status register
response_data = 0;
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_STATUS_REG, FSI_DATA_LENGTH_WORD, 0, &response_data))
{
goto fail;
}
*scom_status = response_data;
// Read SCOM data from buffer
response_data = 0;
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_DATA0_REG, FSI_DATA_LENGTH_WORD, 0, &response_data))
{
goto fail;
}
*data = ((uint64_t)response_data) << 32;
response_data = 0;
if (access_fsi_mem(slave_id, IBM_POWER9_SCOM_PIB_BASE + IBM_SCOM_FSI_DATA1_REG, FSI_DATA_LENGTH_WORD, 0, &response_data))
{
goto fail;
}
(*data) |= response_data;
}
return 0;
fail:
return -1;
}
static int access_scom(uint8_t slave_id, uint32_t scom_address, uint8_t write, uint64_t *data)
{
uint32_t scom_status;
uint8_t scom_response_code;
if (access_scom_fsi_handler(slave_id, scom_address, write, data, &scom_status))
{
return -1;
}
scom_response_code = (scom_status >> 12) & 0x7;
if (scom_response_code != IBM_SCOM_PIB_RESULT_SUCCESS)
{
#ifdef DEBUG
printf("%s(): SCOM access returned error code 0x%01x\n", __FUNCTION__, scom_response_code);
#endif
return -1;
}
return 0;
}
static int initialize_fsi_master(void)
{
uint32_t word;
......@@ -352,17 +469,209 @@ fail:
return -1;
}
void sbe_status_code_to_text(char *buffer, uint8_t code)
{
buffer[0] = 0;
switch (code)
{
case 0x0:
sprintf(buffer, "SBE_STATE_UNKNOWN");
break;
case 0x1:
sprintf(buffer, "SBE_STATE_IPLING");
break;
case 0x2:
sprintf(buffer, "SBE_STATE_ISTEP");
break;
case 0x3:
sprintf(buffer, "SBE_STATE_MPIPL");
break;
case 0x4:
sprintf(buffer, "SBE_STATE_RUNTIME");
break;
case 0x5:
sprintf(buffer, "SBE_STATE_DMT");
break;
case 0x6:
sprintf(buffer, "SBE_STATE_DUMP");
break;
case 0x7:
sprintf(buffer, "SBE_STATE_FAILURE");
break;
case 0x8:
sprintf(buffer, "SBE_STATE_QUIESCE");
break;
case 0x9:
sprintf(buffer, "SBE_STATE_QUIESCE");
break;
default:
sprintf(buffer, "SBE_INVALID_STATE");
break;
}
}
int get_sbe_status(void)
{
uint32_t word;
uint64_t qword;
char status_text_buffer[128];
// SBE
// IBM_POWER9_LL_MODE_REG
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_LL_MODE_REG, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_LL_MODE_REG, word);
// CFAM 0x1007
if (access_cfam(IBM_POWER9_SLAVE_ID, 0x1007, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", 0x1007, word);
if (word & (0x1 << 15))
{
printf("\tVDN Power:\t\t\tON\n");
}
else
{
printf("\tVDN Power:\t\t\tOFF\n");
}
printf("\tOSC Status:\t\t\t0x%01x\n", (word >> 8) & 0xf);
printf("\tSpread Spectrum PLL Locked:\t%d\n", (word >> 7) & 0x1);
printf("\tCP Filter PLL Locked:\t\t%d\n", (word >> 6) & 0x1);
printf("\tI/O Filter PLL Locked:\t\t%d\n", (word >> 5) & 0x1);
printf("\tNest PLL Locked:\t\t%d\n", (word >> 4) & 0x1);
// CFAM 0x2801
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_CBS_CS, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_CBS_CS, word);
if (word & (0x1 << 26))
{
printf("\tSecure Mode Disable:\t\tON\n");
}
else
{
printf("\tSecure Mode Disable:\t\tOFF\n");
}
printf("\tCBS State Delay:\t\t0x%03x\n", (word >> 16) & 0x3ff);
printf("\tCBS State Vector:\t\t0x%03x\n", (word >> 0) & 0xffff);
// CFAM 0x2802 (CBS trace)
if (access_cfam(IBM_POWER9_SLAVE_ID, 0x2802, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", 0x2802, word);
// CFAM 0x2803 (CBS event log)
if (access_cfam(IBM_POWER9_SLAVE_ID, 0x2803, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", 0x2803, word);
if (word & (0x1 << 15))
{
printf("\tVDN PGOOD dropped during CBS sequence\n");
}
if (word & (0x1 << 14))
{
printf("\tVDN PGOOD dropped after CBS sequence completion\n");
}
if (word & (0x1 << 13))
{
printf("\tPervasive register write occurred during CBS execution\n");
}
if (word & (0x1 << 12))
{
printf("\tInvalid state reached during CBS execution\n");
}
// CFAM 0x280b (CBS extended status)
if (access_cfam(IBM_POWER9_SLAVE_ID, 0x280b, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", 0x280b, word);
printf("\tVital HLD Stopped:\t\t%d\n", (word >> 29) & 0x1);
printf("\tSecurity Mode Bit:\t\t%d\n", (word >> 18) & 0x1);
printf("\tCBS Protocol Error:\t\t%d\n", (word >> 17) & 0x1);
printf("\tCurrent OPCG Mode:\t\t0x%01x\n", (word >> 12) & 0xf);
printf("\tPrevious OPCG Mode:\t\t0x%01x\n", (word >> 8) & 0xf);
printf("\tPCB Interface Error:\t\t%d\n", (word >> 7) & 0x1);
printf("\tPCB Parity Error:\t\t%d\n", (word >> 6) & 0x1);
printf("\tOther Clock Control Error:\t%d\n", (word >> 5) & 0x1);
printf("\tChiplet Aligned:\t\t%d\n", (word >> 4) & 0x1);
printf("\tPCB Request RXed After Reset:\t%d\n", (word >> 3) & 0x1);
// Root Control 0
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_ROOT_CTRL0, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_ROOT_CTRL0, word);
printf("\tPCB Reset:\t\t\t%d\n", (word >> 1) & 0x1);
printf("\tGlobal Endpoint Reset:\t\t%d\n", (word >> 0) & 0x1);
// Pervasive Control 0
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_PERV_CTRL0, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_PERV_CTRL0, word);
printf("\tChiplet Enable:\t\t\t%d\n", (word >> 31) & 0x1);
printf("\tPCB Reset:\t\t\t%d\n", (word >> 30) & 0x1);
// SBE Control / Status Register
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_SBE_CTRL_STATUS, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_SBE_CTRL_STATUS, word);
if (word & (0x1 << 31))
{
printf("\tSecure Debug Mode:\t\tON\n");
}
else
{
printf("\tSecure Debug Mode:\t\tOFF\n");
}
// SBE Message Register
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_SBE_MSG_REGISTER, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_SBE_MSG_REGISTER, word);
printf("\tAsync FFDC:\t\t\t%d\n", (word >> 30) & 0x1);
printf("\tSBE Booted:\t\t\t%d\n", (word >> 31) & 0x1);
sbe_status_code_to_text(status_text_buffer, (word >> 24) & 0xf);
printf("\tSBE Previous State:\t\t0x%01x [%s]\n", (word >> 24) & 0xf, status_text_buffer);
sbe_status_code_to_text(status_text_buffer, (word >> 20) & 0xf);
printf("\tSBE Current State:\t\t0x%01x [%s]\n", (word >> 20) & 0xf, status_text_buffer);
printf("\tMajor ISTEP:\t\t\t%d\n", (word >> 12) & 0xff);
printf("\tMinor ISTEP:\t\t\t%d\n", (word >> 6) & 0x3f);
// CFAM 0x283a (SBE scratch register 3)
if (access_cfam(IBM_POWER9_SLAVE_ID, 0x283a, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", 0x283a, word);
// Hostboot
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_HB_MBX5_REG, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
......@@ -372,6 +681,22 @@ int get_sbe_status(void)
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_HB_MBX5_REG, word);
// IBM_POWER9_ROOT_CTRL8
if (access_cfam(IBM_POWER9_SLAVE_ID, IBM_POWER9_ROOT_CTRL8, FSI_DATA_LENGTH_WORD, FSI_DIRECTION_READ, &word))
{
goto fail;
}
printf("CFAM 0x%06x: 0x%08x\n", IBM_POWER9_ROOT_CTRL8, word);
// SCOM 0x50001 (IBM_POWER9_CBS_CS)
if (access_scom(IBM_POWER9_SLAVE_ID, 0x50001, FSI_DIRECTION_READ, &qword))
{
goto fail;
}
printf("SCOM 0x%016x: 0x%016llx\n", 0x50001, qword);
return 0;
fail:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment