diff options
author | Doug Gilbert <dgilbert@us.ibm.com> | 2017-10-30 12:58:10 -0500 |
---|---|---|
committer | Martha Broyles <mbroyles@us.ibm.com> | 2018-03-28 17:00:41 -0400 |
commit | 1bbbfec92b3a3744a6ffbc5e9f4a4eb46ca4abd1 (patch) | |
tree | 4af7fde07033e850abe820491c714f402f268da8 /src/occ_gpe1 | |
parent | b3a2f75d837fd671f13dacb2464c36a5fc8fc69d (diff) | |
download | talos-occ-1bbbfec92b3a3744a6ffbc5e9f4a4eb46ca4abd1.tar.gz talos-occ-1bbbfec92b3a3744a6ffbc5e9f4a4eb46ca4abd1.zip |
P9 Centaur sensor support
Change-Id: Ia84bc7532482ca314c26bd0bb5bf48ad6ee9c410
RTC: 163359
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/54989
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/occ_gpe1')
-rw-r--r-- | src/occ_gpe1/gpe1_main.c | 3 | ||||
-rw-r--r-- | src/occ_gpe1/gpe_centaur.c | 89 | ||||
-rw-r--r-- | src/occ_gpe1/gpe_centaur.h | 53 | ||||
-rw-r--r-- | src/occ_gpe1/gpe_centaur_configuration.c | 538 | ||||
-rw-r--r-- | src/occ_gpe1/gpe_centaur_scom.c | 571 | ||||
-rw-r--r-- | src/occ_gpe1/img_defs.mk | 27 | ||||
-rw-r--r-- | src/occ_gpe1/ipc_func_tables.c | 7 | ||||
-rw-r--r-- | src/occ_gpe1/topfiles.mk | 3 |
8 files changed, 1276 insertions, 15 deletions
diff --git a/src/occ_gpe1/gpe1_main.c b/src/occ_gpe1/gpe1_main.c index 6272621..326ae42 100644 --- a/src/occ_gpe1/gpe1_main.c +++ b/src/occ_gpe1/gpe1_main.c @@ -33,10 +33,11 @@ #include "pk_trace.h" #include "ipc_api.h" #include "gpe_export.h" +#include "gpe_centaur.h" #define KERNEL_STACK_SIZE 512 -uint8_t G_kernel_stack[KERNEL_STACK_SIZE]; +uint64_t G_kernel_stack[KERNEL_STACK_SIZE/8]; //Point to the GPE shared structure #define GPE_SHARED_DATA_ADDR 0xFFFB3C00 diff --git a/src/occ_gpe1/gpe_centaur.c b/src/occ_gpe1/gpe_centaur.c new file mode 100644 index 0000000..671b30d --- /dev/null +++ b/src/occ_gpe1/gpe_centaur.c @@ -0,0 +1,89 @@ +#include "gpe_centaur.h" +#include "ipc_async_cmd.h" +#include "gpe_util.h" + +CentaurConfiguration_t * G_centaur_config = NULL; + +void gpe_centaur_init(ipc_msg_t* i_cmd, void* i_arg) +{ + int rc; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd; + CentaurConfigParms_t* payload = (CentaurConfigParms_t*)async_cmd->cmd_data; + + CentaurConfiguration_t * config = payload->centaurConfiguration; + G_centaur_config = config; + + payload->error.error = 0; + payload->error.ffdc = 0; + + if(G_centaur_config == NULL) + { + PK_TRACE("gpe_centaur_init: centaurConfiguration data ptr is NULL!"); + rc = GPE_RC_CONFIG_DATA_NULL_PTR; + } + else + { + rc = gpe_centaur_configuration_create(G_centaur_config); + } + + payload->error.rc = rc; + + // Send response + rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS); + if(rc) + { + PK_TRACE("gpe_centaur_init: Failed to send response. rc = %x. Halting GPE1.", + rc); + + gpe_set_ffdc(&(payload->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + pk_halt(); + } +} + +void gpe_centaur_scom(ipc_msg_t* i_cmd, void* i_arg) +{ + int rc; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd; + CentaurScomParms_t * scomParms = (CentaurScomParms_t*)async_cmd->cmd_data; + + gpe_scom_centaur(G_centaur_config, scomParms); + + // Send response + rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS); + if(rc) + { + PK_TRACE("gpe_centaur_scom: Failed to send response. rc = %x. Halting GPE1.", + rc); + + gpe_set_ffdc(&(scomParms->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + pk_halt(); + } + + +} + +void gpe_centaur_data(ipc_msg_t* i_cmd, void* i_arg) +{ + int rc; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd; + + CentaurGetMemDataParms_t * dataParms = + (CentaurGetMemDataParms_t *)async_cmd->cmd_data; + + rc = centaur_get_mem_data(G_centaur_config, dataParms); + + dataParms->error.rc = rc; + + // Send response + rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS); + if(rc) + { + PK_TRACE("gpe_centaur_init: Failed to send response. rc = %x. Halting GPE1.", + rc); + + gpe_set_ffdc(&(dataParms->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + pk_halt(); + } +} + + diff --git a/src/occ_gpe1/gpe_centaur.h b/src/occ_gpe1/gpe_centaur.h new file mode 100644 index 0000000..ad8e2a7 --- /dev/null +++ b/src/occ_gpe1/gpe_centaur.h @@ -0,0 +1,53 @@ +#if !defined(_GPE_CENTAUR_H) +#define _GPE_CENTAUR_H + +#include "ipc_structs.h" +#include "centaur_structs.h" + +// IPC interface +void gpe_centaur_scom(ipc_msg_t* i_cmd, void* i_arg); +void gpe_centaur_data(ipc_msg_t* i_cmd, void* i_arg); +void gpe_centaur_init(ipc_msg_t* i_cmd, void* i_arg); + +// HCODE interface +/** + * Populate a CentaurConfiguration object + * @param[out] 8 byte aligned pointer to the CentaurConfiguration object. + * @return [0 | return code] + * @note The CentaurConfiguration object is shared with the 405 so + * it needs to be in non-cacheable sram. + */ +int gpe_centaur_configuration_create(CentaurConfiguration_t * o_config); + +/** + * Scom all of the centaurs with the same SCOM address. + * @param[in] The CentaurConfig object + * @param[in] The SCOM address + * @param[out] The array of data collected. Must be large enough to hold + * uint64_t data from each centaur. + * @return [0 | return code] + */ +int centaur_get_scom_vector(CentaurConfiguration_t* i_config, + uint32_t i_scom_address, + uint64_t* o_data); + +/** + * Scom one or more centaurs + * @param[in] The CentaurConfig object + * @param[in/out] The Centaur Scom Parms object + * @return The return code is part of the Centaur Scom Parms object + */ +void gpe_scom_centaur(CentaurConfiguration_t* i_config, + CentaurScomParms_t* i_parms); + + +/** + * Collect the centaur thermal data + * @param[in] The CentaurConfig object + * @param[in/out] The Centaur data parm object + * @return [0 | return code] + */ +int centaur_get_mem_data(CentaurConfiguration_t* i_config, + CentaurGetMemDataParms_t* i_parms); + +#endif diff --git a/src/occ_gpe1/gpe_centaur_configuration.c b/src/occ_gpe1/gpe_centaur_configuration.c new file mode 100644 index 0000000..83ac500 --- /dev/null +++ b/src/occ_gpe1/gpe_centaur_configuration.c @@ -0,0 +1,538 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/lib/pm/centaur_thermal_access.c $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/** + * @briefcentaur_thermal_access + */ + +#include "gpe_centaur.h" +#include "ppe42_scom.h" +#include "pk.h" +#include "p9_misc_scom_addresses.h" +#include "mcs_firmware_registers.h" +#include "pba_firmware_constants.h" +#include "pba_register_addresses.h" +#include "centaur_register_addresses.h" +#include "ppe42_msr.h" +#include "occhw_pba_common.h" + +// Which GPE controls the PBASLAVE +#define OCI_MASTER_ID_GPE1 1 + +// Power Bus Address bit that configures centaur for HOST/OCC P9=bit(38) +#define PBA_HOST_OCC_CFG 0x0000000002000000ull; + + +const uint32_t MCFGPR[OCCHW_NCENTAUR] = +{ + MCS_0_MCRSVDE, + MCS_0_MCRSVDF, + MCS_1_MCRSVDE, + MCS_1_MCRSVDF, + MCS_2_MCRSVDE, + MCS_2_MCRSVDF, + MCS_3_MCRSVDE, + MCS_3_MCRSVDF +}; + +//const uint32_t MCSMODE0[OCCHW_NCENTAUR / 2] __attribute__((section(".sdata2"))) = +//{ +// MCS_0_MCMODE0, +// MCS_1_MCMODE0, +// MCS_2_MCMODE0, +// MCS_3_MCMODE0 +//}; + +//const uint32_t MCFIR[OCCHW_NCENTAUR / 2] __attribute((section(".sdata2"))) = +//{ +// MCS_0_MCFIR, +// MCS_1_MCFIR, +// MCS_2_MCFIR, +// MCS_3_MCFIR +//}; + +const uint32_t MCFGP[OCCHW_NCENTAUR/2] = +{ + MCS_0_MCFGP, + MCS_1_MCFGP, + MCS_2_MCFGP, + MCS_3_MCFGP +}; + +/////////////////////////////////////////////////////////////// +// These are PPE specific PBA routines. +////////////////////////////////////////////////////////////// +int +gpe_pba_parms_create(GpePbaParms* parms, + int slave, + int write_ttype, + int write_tsize, + int read_ttype) +{ + pba_slvctln_t* slvctl, *mask; + pba_slvrst_t* slvrst; + pba_slvrst_t* slvrst_in_progress; + uint64_t all1 = 0xffffffffffffffffull; + + parms->slave_id = slave; + + slvctl = &(parms->slvctl); + mask = &(parms->mask); + slvrst = &(parms->slvrst); + slvrst_in_progress = &(parms->slvrst_in_progress); + + parms->slvctl_address = PBA_SLVCTLN(slave); + + slvrst->value = 0; + slvrst->fields.set = PBA_SLVRST_SET(slave); + + slvrst_in_progress->value = 0; + slvrst_in_progress->fields.in_prog = PBA_SLVRST_IN_PROG(slave); + + slvctl->value = 0; + mask->value = 0; + + slvctl->fields.enable = 1; + mask->fields.enable = all1; + + slvctl->fields.mid_match_value = OCI_MASTER_ID_GPE1; + mask->fields.mid_match_value = all1; + + slvctl->fields.mid_care_mask = all1; + mask->fields.mid_care_mask = all1; + + slvctl->fields.write_ttype = write_ttype; + mask->fields.write_ttype = all1; + + slvctl->fields.write_tsize = write_tsize; + mask->fields.write_tsize = all1; + + slvctl->fields.read_ttype = read_ttype; + mask->fields.read_ttype = all1; + + slvctl->fields.buf_alloc_a = 1; + slvctl->fields.buf_alloc_b = 1; + slvctl->fields.buf_alloc_c = 1; + slvctl->fields.buf_alloc_w = 1; + mask->fields.buf_alloc_a = 1; + mask->fields.buf_alloc_b = 1; + mask->fields.buf_alloc_c = 1; + mask->fields.buf_alloc_w = 1; + + if (read_ttype == PBA_READ_TTYPE_CI_PR_RD) + { + + slvctl->fields.buf_invalidate_ctl = 1; + mask->fields.buf_invalidate_ctl = all1; + + slvctl->fields.read_prefetch_ctl = PBA_READ_PREFETCH_NONE; + mask->fields.read_prefetch_ctl = all1; + + } + else + { + + slvctl->fields.buf_invalidate_ctl = 0; + mask->fields.buf_invalidate_ctl = all1; + } + + mask->value = ~(mask->value); + + return 0; +} + + +//////////////////////////////////////////////// +// Centaur specific routines +//////////////////////////////////////////////// +int gpe_centaur_configuration_create(CentaurConfiguration_t* o_config) +{ + int rc = 0; + unsigned int i = 0; + mcfgpr_t mcfgpr; + // mcifir_t mcifir; + // mcsmode0_t mcsmode0; + pba_slvctln_t slvctl; + int designatedSync = -1; + uint64_t bar = 0; + uint64_t mask = 0; + uint64_t base = 0; + uint64_t* ptr = (uint64_t*)o_config; + + // Prevent unwanted interrupts from scom errors + const uint32_t orig_msr = mfmsr() & MSR_SEM; + mtmsr((orig_msr & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM); + + for(i = 0; i < sizeof(CentaurConfiguration_t) / 8; ++i) + { + *ptr++ = 0ull; + } + + o_config->configRc = CENTAUR_NOT_CONFIGURED; + + do + { + // Create the setups for the GPE procedures. The 'dataParms' are the + // setup for accessing the Centaur sensor cache. The 'scomParms' are + // the setup for accessing Centaur SCOMs. + + rc = gpe_pba_parms_create(&(o_config->dataParms), + PBA_SLAVE_CENTAUR, + PBA_WRITE_TTYPE_CI_PR_W, + PBA_WRITE_TTYPE_DC, + PBA_READ_TTYPE_CL_RD_NC); + + if (rc) + { + rc = CENTAUR_DATA_SETUP_ERROR; + break; + } + + rc = gpe_pba_parms_create(&(o_config->scomParms), + PBA_SLAVE_CENTAUR, + PBA_WRITE_TTYPE_CI_PR_W, + PBA_WRITE_TTYPE_DC, + PBA_READ_TTYPE_CI_PR_RD); + + if (rc) + { + rc = CENTAUR_SCOM_SETUP_ERROR; + break; + } + + // Go into each MCS on the chip, and for all enabled MCS get a couple + // of SCOMs and check configuration items for correctness. If any of + // the Centaur are configured, exactly one of the MCS must be + // designated to receive the SYNC commands. + + // Note that the code uniformly treats SCOM failures of the MCFGPR + // registers as an unconfigured Centaur. This works both for Murano, + // which only defines the final 4 MCS, as well as for our VBU models + // where some of the "valid" MCS are not in the simulation models. + + for (i = 0; i < OCCHW_NCENTAUR; ++i) + { + uint64_t val64; + + // If can't scom then assume not configured + //rc = getscom_abs(MCFIR[i / 2], &(mcifir.value)); + + //if (rc) + //{ + // rc = 0; + // continue; + //} + + // See Cumulus MC "Datapath Fault Isolation Register" Is it right??? + //FIR bits have changed from p8 TODO do we need to look at the fir + //for P9 ?? + //if (mcifir.fields.channel_fail_signal_active) + //{ + // continue; + //} + + // Routine p9c_set_inband_addr.C uses MCRSVDE and MCRSVDF to set + // inband address (MCFGPR) + // + rc = getscom_abs(MCFGPR[i], &(mcfgpr.value)); + + if (rc) + { + rc = 0; + continue; + } + + // TODO ENGD work-around until gets pushed up. + // Turn on bit 25 in mode0 regs. They should all have the same value + rc = getscom_abs(0x05010811, &val64); + val64 |= 0x0000004000000000ull; + rc = putscom_abs(0x05010811, val64); + rc = putscom_abs(0x05010891, val64); + rc = putscom_abs(0x03010811, val64); + rc = putscom_abs(0x03010891, val64); + + // If inband scom is not configured then assume the centaur does not exist + if (!mcfgpr.fields.mcfgprq_valid) + { + continue; + } + + + // The 31-bit base-address is moved to begin at bit 8 in the + // 64-bit PowerBus address. + // Set the HOST/OCC bit in the address. + o_config->baseAddress[i] = + ((uint64_t)(mcfgpr.fields.mcfgprq_base_address) << 25) | PBA_HOST_OCC_CFG; + + PK_TRACE_DBG("Centar[%d] Base Address: %016llx",i,o_config->baseAddress[i]); + + + // TODO this bit no longer exists + // If this MCS is configured to be the designated SYNC unit, it + // must be the only one. + + //if (mcsmode0.fields.enable_centaur_sync) + //{ + // if (designatedSync > 0) + // { + // PK_TRACE_DBG("Both MCS %d and %d are designated " + // "for Centaur Sync", + // designatedSync, i); + // rc = CENTAUR_MULTIPLE_DESIGNATED_SYNC; + // break; + + // } + // else + // { + // designatedSync = i; + // } + //} + + + // Add the Centaur to the configuration + o_config->config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_CENTAUR(i)); + } + + if (rc) + { + break; + } + + + // In p9 the enable_centaur_sync is no longer available as a mode bit. + // TODO Anything to do? + // P8: + // If Centaur are configured, make sure at least one of the MCS will + // handle the SYNC. If so, convert its base address into an address + // for issuing SYNC commands by setting bits 27 (OCC) 28 and 29 + // (Sync), then insert this address into the extended address field of + // a PBA slave control register image. gsc_scom_centaur() then merges + // this extended address into the PBA slave control register (which + // has been set up for Centaur SCOM) to do the SYNC. + + // In the override mode (i_setup > 1) we tag the first valid MCS + // to recieve the sync if the firmware has not set it up correctly. + + if (o_config->config) + { +#if defined(__P8_DESIGNATED_SYNC__) + + if (designatedSync < 0) + { + if (i_setup <= 1) + { + PK_TRACE_DBG("No MCS is designated for Centaur SYNC"); + rc = CENTAUR_NO_DESIGNATED_SYNC; + break; + + } + else + { + + designatedSync = + cntlz32(o_config->config << CHIP_CONFIG_MCS_BASE); + + rc = _getscom(designatedSync, MCSMODE0, &(mcsmode0.value)); + + if (rc) + { + PK_TRACE_DBG("Unexpected rc = 0x%08x " + "SCOMing MCSMODE0(%d)", + (uint32_t)rc, + designatedSync); + + rc = CENTAUR_MCSMODE0_SCOM_FAILURE; + break; + } + + mcsmode0.fields.enable_centaur_sync = 1; + + rc = _putscom(designatedSync, MCSMODE0, mcsmode0.value); + + if (rc) + { + PK_TRACE_DBG("Unexpected rc = 0x%08x " + "SCOMing MCSMODE0(%d)", + (uint32_t)rc, + designatedSync); + + rc = CENTAUR_MCSMODE0_SCOM_FAILURE; + break; + } + } + } + +#else + // first centaur found + designatedSync = cntlz32(o_config->config << CHIP_CONFIG_MCS_BASE); +#endif + // Set the OCC/HOST bit in the PBA + base = o_config->baseAddress[designatedSync] | PBA_HOST_OCC_CFG; + + //Pick out the PBA address sub field that will be set by the slvctl extaddr + //bits [23:36] + slvctl.value = 0; + slvctl.fields.extaddr = base >> 27; + + o_config->syncSlaveControl.value = slvctl.value; + } + + + // Configure the PBA BAR and PBA BARMSK. + // Set the BARMSK bits such that: + // -PBA[8:22] are provided by the PBABAR. + // -PBA[23:36] are provided by the PBASLVCTL ExtrAddr field + // -PBA[37:43] are provided by the OCI addr[5:11] + // PBA[44:63] will always come from the OCI addr[12:31] + // Note: This code should no longer be needed when the BAR/BARMSK is set + // by PHYP. + if (o_config->config != 0) + { + uint64_t bar = 0; + uint64_t barMsk = PBA_BARMSKN_MASK_MASK; + + for (i = 0; i < OCCHW_NCENTAUR; ++i) + { + bar |= o_config->baseAddress[i]; + } + + bar &= ~barMsk; + + PK_TRACE_DBG("PBABAR(%d): %016llx", PBA_BAR_CENTAUR, bar); + PK_TRACE_DBG("PBABARMSK: %016llx", barMsk); + + rc = putscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), barMsk); + + if (rc) + { + PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n", + (uint32_t)rc, PBA_BAR_CENTAUR); + rc = CENTAUR_BARMSKN_PUTSCOM_FAILURE; + break; + } + + rc = putscom_abs(PBA_BARN(PBA_BAR_CENTAUR), bar); + if (rc) + { + PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n", + (uint32_t)rc, PBA_BAR_CENTAUR); + rc = CENTAUR_BARN_PUTSCOM_FAILURE; + break; + } + } + + // Do an independent check that every Centaur base address + // can be generated by the combination of the current BAR and + // BAR Mask, along with the initial requirement that the mask must + // include at least bits 38:43. + + if (o_config->config != 0) + { + rc = getscom_abs(PBA_BARN(PBA_BAR_CENTAUR), &bar); + + if (rc) + { + PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n", + (uint32_t)rc, PBA_BAR_CENTAUR); + rc = CENTAUR_BARN_GETSCOM_FAILURE; + break; + } + + rc = getscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), &mask); + + if (rc) + { + PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n", + (uint32_t)rc, PBA_BAR_CENTAUR); + rc = CENTAUR_BARMSKN_GETSCOM_FAILURE; + break; + } + + bar = bar & PBA_BARN_ADDR_MASK; + mask = mask & PBA_BARMSKN_MASK_MASK; + + if ((mask & 0x0000000003f00000ull) != 0x0000000003f00000ull) + { + + PK_TRACE("PBA BAR mask (%d) does not cover bits 38:43\n", PBA_BAR_CENTAUR); + rc = CENTAUR_MASK_ERROR; + break; + } + + for (i = 0; i < OCCHW_NCENTAUR; ++i) + { + if (o_config->baseAddress[i] != 0) + { + if ((o_config->baseAddress[i] & ~mask) != + (bar & ~mask)) + { + + PK_TRACE("BAR/Mask (%d) error for MCS/Centaur %d", + PBA_BAR_CENTAUR, i); + + PK_TRACE(" base = 0x%08x%08x", + (uint32_t)(o_config->baseAddress[i]>>32), + (uint32_t)(o_config->baseAddress[i])); + + PK_TRACE(" bar = 0x%08x%08x" + " mask = 0x%08x%08x", + (uint32_t)(bar >> 32), + (uint32_t)(bar), + (uint32_t)(mask >> 32), + (uint32_t)(mask)); + + rc = CENTAUR_BAR_MASK_ERROR; + break; + } + } + } + + if (rc) + { + break; + } + } + + + // At this point the structure is initialized well-enough that it can + // be used by gpe_scom_centaur(). + + + o_config->configRc = 0; + + if (o_config->config == 0) + { + break; + } + + + // Get Device ID from each centaur + centaur_get_scom_vector(o_config, + CENTAUR_DEVICE_ID, + (uint64_t*)(&(o_config->deviceId[0]))); + + } + while(0); + + o_config->configRc = rc; + + mtmsr(orig_msr); + + return rc; +} + diff --git a/src/occ_gpe1/gpe_centaur_scom.c b/src/occ_gpe1/gpe_centaur_scom.c new file mode 100644 index 0000000..cef0977 --- /dev/null +++ b/src/occ_gpe1/gpe_centaur_scom.c @@ -0,0 +1,571 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/lib/pm/centaur_scom.c $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <stdint.h> +#include "gpe_centaur.h" +#include "gpe_pba_cntl.h" +#include "ppe42_scom.h" +#include "ppe42.h" +#include "pba_register_addresses.h" +#include "ppe42_msr.h" + +/** + * @file centaur_scom + * @brief scom access from gpe to a centaur + */ + +/** + * Setup the PBASLVCTLN extended address and calculate the OCI scom address + * @param[in] PBA base address + * @param[in] The Centaur scom address + * @returns the OCI address to scom the centaur + * @Post The extended address field in the PBASLVCNT is set + */ +uint32_t centaur_scom_setup(CentaurConfiguration_t* i_config, + uint32_t i_centaur_instance, + uint32_t i_scom_address) +{ + uint32_t oci_addr = 0; + #if defined(__PBASLV__) + pba_slvctln_t slvctln; +#endif + uint64_t pb_addr = i_config->baseAddress[i_centaur_instance]; + + // Break address into componets + uint32_t local = i_scom_address & 0x00001fff; + uint32_t port = i_scom_address & 0x000f0000; + uint32_t slave = i_scom_address & 0x03000000; + uint32_t multi = i_scom_address & 0xc0000000; + + // compress to 21 bits for P9 + uint32_t scom_address = + local + + (port >> 3) + + (slave >> 7) + + (multi >> 11); + + // P9: Turn on bit 38 to indicate OCC + pb_addr |= 0x0000000002000000ull; + pb_addr |= ((uint64_t)scom_address << 3); + + #if defined(__PBASLV__) + // put bits 23:36 of address into slvctln extended addr + PPE_LVD((i_config->scomParms).slvctl_address, slvctln.value); + slvctln.fields.extaddr = pb_addr >> 27; + PPE_STVD((i_config->scomParms).slvctl_address, slvctln.value); +#endif + // HW bug work-around + { + // workaround - don't use extr addr - use pbabar. + uint64_t barMsk = 0; + // put the PBA in the BAR + putscom_abs(PBA_BARN(PBA_BAR_CENTAUR), pb_addr); + putscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), barMsk); + } + // make oci address + oci_addr = (uint32_t)(pb_addr & 0x07ffffffull); + + // upper nibble is PBA region and BAR_SELECT + oci_addr |= ((PBA_BAR_CENTAUR | 0x8) << 28); + PK_TRACE_DBG("Centaur OCI scom addr: %08x",oci_addr); + return oci_addr; +} + +uint32_t centaur_sensorcache_setup(CentaurConfiguration_t* i_config, + uint32_t i_centaur_instance) +{ + uint32_t oci_addr = 0; +#if defined(__PBASLV__) + pba_slvctln_t slvctln; +#endif + uint64_t pb_addr = i_config->baseAddress[i_centaur_instance]; + + // bit 38 set OCI master, bits 39,40 Centaur thermal sensors '10'b + pb_addr |= 0x0000000003000000ull; + +#if defined(__PBASLV__) + PPE_LVD((i_config->dataParms).slvctl_address, slvctln.value); + slvctln.fields.extaddr = pb_addr >> 27; + PPE_STVD((i_config->dataParms).slvctl_address, slvctln.value); +#endif + { + // HW bug workaround - don't use extr addr - use pbabar. + uint64_t barMsk = 0; + // put the PBA in the BAR + putscom_abs(PBA_BARN(PBA_BAR_CENTAUR), pb_addr); + putscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), barMsk); + } + // make oci address + oci_addr = (uint32_t)(pb_addr & 0x07ffffffull); + + // PBA space bits[0:1] = '10' bar select bits[3:4] + oci_addr |= ((PBA_BAR_CENTAUR | 0x8) << 28); + + return oci_addr; +} + +void pbaslvctl_reset(GpePbaParms* i_pba_parms) +{ + uint64_t val = 0; + + do + { + PPE_STVD(PBA_SLVRST, i_pba_parms->slvrst.value); + PPE_LVD(PBA_SLVRST, val); + val &= i_pba_parms->slvrst_in_progress.value; + } + while(val != 0); +} + +uint64_t pbaslvctl_setup(GpePbaParms* i_pba_parms) +{ + uint64_t slvctl_val; + uint64_t slvctl_val_org; + PPE_LVD(i_pba_parms->slvctl_address, slvctl_val_org); + slvctl_val = slvctl_val_org; + slvctl_val &= i_pba_parms->mask.value; + slvctl_val |= i_pba_parms->slvctl.value; + PPE_STVD(i_pba_parms->slvctl_address, slvctl_val); + return slvctl_val_org; +} + +// Get the most severe rc from the sibrca field in the msr +int rc_from_sibrc() +{ + int rc = 0; + uint32_t sibrca = (mfmsr() & 0x0000007f); + if(sibrca) + { + uint32_t mask = 1; + rc = 7; + for(; mask != 0x00000080; mask <<=1) + { + if( mask & sibrca ) + { + break; + } + --rc; + } + } + return rc; +} + +// Get data from each existing centaur. +int centaur_get_scom_vector(CentaurConfiguration_t* i_config, + uint32_t i_scom_address, + uint64_t* o_data) +{ + int instance = 0; + uint64_t pba_slvctln_save; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + // clear SIB errors in MSR + mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA))); + + for(instance = 0; instance < OCCHW_NCENTAUR; ++instance) + { + if( CHIP_CONFIG_CENTAUR(instance) & (i_config->config)) + { + uint32_t oci_addr = + centaur_scom_setup(i_config, instance, i_scom_address); + + // read centaur scom + PPE_LVD(oci_addr, *o_data); + } + else + { + *o_data = 0; + } + + ++o_data; + } + + // gpe_pba_cntl function? + pbaslvctl_reset(&(i_config->scomParms)); + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc_from_sibrc(); +} + +int centaur_get_scom(CentaurConfiguration_t* i_config, + int i_centaur_instance, + uint32_t i_scom_address, + uint64_t* o_data) +{ + int rc = 0; + uint32_t oci_addr; + uint64_t pba_slvctln_save; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + oci_addr = + centaur_scom_setup(i_config, i_centaur_instance, i_scom_address); + + if( CHIP_CONFIG_CENTAUR(i_centaur_instance) & (i_config->config)) + { + // read centaur scom + rc = getscom_abs(oci_addr, o_data); + } + else + { + *o_data = 0; + } + + // gpe_pba_cntl function? + pbaslvctl_reset(&(i_config->scomParms)); + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc; +} + + +// Write all configured centaur with the same data +int centaur_put_scom_all(CentaurConfiguration_t* i_config, + uint32_t i_scom_address, + uint64_t i_data) +{ + int instance = 0; + uint64_t pba_slvctln_save; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + // clear SIB errors in MSR + mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA))); + + for(instance = 0; instance < OCCHW_NCENTAUR; ++instance) + { + if( CHIP_CONFIG_CENTAUR(instance) & (i_config->config)) + { + uint32_t oci_addr = + centaur_scom_setup(i_config, instance, i_scom_address); + + // centaur scom + PPE_STVD(oci_addr, i_data); + } + } + + // gpe_pba_cntl function? + pbaslvctl_reset(&(i_config->scomParms)); + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc_from_sibrc(); +} + +int centaur_put_scom(CentaurConfiguration_t* i_config, + int i_centaur_instance, + uint32_t i_scom_address, + uint64_t i_data) +{ + int rc = 0; + uint32_t oci_addr; + uint64_t pba_slvctln_save; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + oci_addr = + centaur_scom_setup(i_config, i_centaur_instance, i_scom_address); + + if( CHIP_CONFIG_CENTAUR(i_centaur_instance) & (i_config->config)) + { + // write centaur scom + rc = putscom_abs(oci_addr, i_data); + } + else + { + rc = CENTAUR_INVALID_SCOM; + } + + // gpe_pba_cntl function? + pbaslvctl_reset(&(i_config->scomParms)); + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc; +} + +// write x +int centaur_scom_rmw(CentaurConfiguration_t* i_config, + int i_centaur_instance, + uint32_t i_scom_address, + uint64_t i_mask, + uint64_t* i_data) +{ + int rc = 0; + uint32_t oci_addr; + uint64_t pba_slvctln_save; + uint64_t data64; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + oci_addr = + centaur_scom_setup(i_config, i_centaur_instance, i_scom_address); + + rc = getscom_abs(oci_addr, &data64); + if(!rc) + { + data64 &= (i_mask ^ 0xffffffffffffffffull); + data64 |= *i_data; + + rc = putscom_abs(oci_addr, data64); + if(i_scom_address == 0x3010416) + { + PK_TRACE("N/M RMW PUTSCOM: %08x%08x",(uint32_t)(data64>>32),(uint32_t)data64); + } + } + + pbaslvctl_reset(&(i_config->scomParms)); + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc; +} + + +int centaur_scom_rmw_all(CentaurConfiguration_t* i_config, + uint32_t i_scom_address, + uint64_t i_mask, + uint64_t i_data) +{ + int instance = 0; + uint64_t pba_slvctln_save; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + // clear SIB errors in MSR + mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA))); + + for(instance = 0; (instance < OCCHW_NCENTAUR); ++instance) + { + if( CHIP_CONFIG_CENTAUR(instance) & (i_config->config)) + { + uint64_t data64; + uint32_t oci_addr = + centaur_scom_setup(i_config, instance, i_scom_address); + + PPE_LVD(oci_addr, data64); + data64 &= (i_mask ^ 0xffffffffffffffffull); + data64 |= i_data; + PPE_STVD(oci_addr, data64); + + pbaslvctl_reset(&(i_config->scomParms)); + } + } + + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc_from_sibrc(); +} + + +int centaur_scom_sync(CentaurConfiguration_t* i_config, + uint64_t i_data) +{ + int rc = 0; + uint32_t addr = (PBA_BAR_CENTAUR << 28); + uint64_t pba_slvctln_save; + + pbaslvctl_reset(&(i_config->scomParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms)); + + // sync setup + pba_slvctln_t slvctl; + PPE_LVD((i_config->scomParms).slvctl_address, slvctl.value); + slvctl.fields.extaddr = (i_config->syncSlaveControl).fields.extaddr; + PPE_STVD((i_config->scomParms).slvctl_address, slvctl.value); + + PPE_STVD(addr, i_data); + + pbaslvctl_reset(&(i_config->scomParms)); + PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save); + + return rc; +} + + +int centaur_scom_sync_all(CentaurConfiguration_t* i_config, + uint64_t i_data) +{ + return centaur_scom_sync(i_config, + (uint64_t)(i_config->config << 24) | i_data); +} + +// read centaur data sensor cache +int centaur_get_mem_data(CentaurConfiguration_t* i_config, + CentaurGetMemDataParms_t* i_parms) +{ + int rc = 0; + uint32_t oci_addr = 0; + uint64_t pba_slvctln_save; + uint64_t data64 = 0; + uint64_t barMskOrg = 0; + + i_parms->error.rc = CENTAUR_GET_MEM_DATA_DIED; + + // HW bug work-around + rc = getscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), &barMskOrg); + if(rc) + { + PK_TRACE("Workaround failed to read bar mask. rc = %x",rc); + } + + pbaslvctl_reset(&(i_config->dataParms)); + pba_slvctln_save = pbaslvctl_setup(&(i_config->dataParms)); + + if(i_parms->collect != -1) + { + if((i_parms->collect >= OCCHW_NCENTAUR) || + (0 == (CHIP_CONFIG_CENTAUR(i_parms->collect) & (i_config->config)))) + { + rc = CENTAUR_GET_MEM_DATA_COLLECT_INVALID; + } + else + { + oci_addr = centaur_sensorcache_setup(i_config, i_parms->collect); + + // Poke the Centaur sensor cache by writing to base address. + data64 = 0; + PPE_STVD(oci_addr, data64); + + // Read 128 bytes from centaur cache + int i; + for(i = 0; i < 128; i += 8) + { + PPE_LVDX(oci_addr, i, data64); + PPE_STVDX((i_parms->data), i, data64); + } + } + } + // TODO Decide to keep this or not. +#if defined(__JUNK__) + if(!rc && i_parms->update != -1) + { + if((i_parms->update >= OCCHW_NCENTAUR) || + (0 == (CHIP_CONFIG_CENTAUR(i_parms->update) & (i_config->config)))) + { + rc = CENTAUR_GET_MEM_DATA_UPDATE_INVALID; + } + else + { + oci_addr = centaur_sensorcache_setup(i_config, i_parms->update); + + //PK_TRACE("CACHE POKE: %08x",oci_addr); + // Writing a zero to this address "pokes" the centaur. + data64 = 0; + PPE_STVD(oci_addr, data64); + } + } +#endif + + pbaslvctl_reset(&(i_config->dataParms)); + PPE_STVD((i_config->dataParms).slvctl_address, pba_slvctln_save); + + // TODO if RC then check for centaur channel checkstop + // The MCFIR reg no longer contains a bit for CHANNEL_FAIL_SIGNAL_ACTIVE. + // No equivalent has been identified yet for P9. + // Return rc = CENTAUR_CHANNEL_CHECKSTOP + + // HW bug work-around + rc = putscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), barMskOrg); + if(rc) + { + PK_TRACE("Work around Failed to set bar mask. rc = %x",rc); + } + + i_parms->error.rc = rc; + return rc; +} + + +// CentaurConfiguration needs to be setup before this is called + +void gpe_scom_centaur(CentaurConfiguration_t* i_config, + CentaurScomParms_t* i_parms) +{ + int i; + mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM); + + // Do reset and pba_setup here? + for(i = 0; i < i_parms->entries; ++i) + { + switch(i_parms->scomList[i].commandType) + { + case CENTAUR_SCOM_NOP: + break; + + case CENTAUR_SCOM_READ: + centaur_get_scom(i_config, + i_parms->scomList[i].instanceNumber, + i_parms->scomList[i].scom, + &(i_parms->scomList[i].data)); + break; + + case CENTAUR_SCOM_WRITE: + centaur_put_scom(i_config, + i_parms->scomList[i].instanceNumber, + i_parms->scomList[i].scom, + i_parms->scomList[i].data); + break; + + case CENTAUR_SCOM_RMW: + centaur_scom_rmw(i_config, + i_parms->scomList[i].instanceNumber, + i_parms->scomList[i].scom, + i_parms->scomList[i].mask, + &(i_parms->scomList[i].data)); + break; + + case CENTAUR_SCOM_READ_VECTOR: + centaur_get_scom_vector(i_config, + i_parms->scomList[i].scom, + i_parms->scomList[i].pData + ); + break; + + case CENTAUR_SCOM_WRITE_ALL: + centaur_put_scom_all(i_config, + i_parms->scomList[i].scom, + i_parms->scomList[i].data); + break; + + case CENTAUR_SCOM_RMW_ALL: + centaur_scom_rmw_all(i_config, + i_parms->scomList[i].scom, + i_parms->scomList[i].mask, + i_parms->scomList[i].data); + break; + + case CENTAUR_SCOM_CENTAUR_SYNC: + centaur_scom_sync(i_config, + i_parms->scomList[i].data); + break; + + case CENTAUR_SCOM_CENTAUR_SYNC_ALL: + centaur_scom_sync(i_config, + i_parms->scomList[i].data); + break; + + default: + break; + }; + } +} diff --git a/src/occ_gpe1/img_defs.mk b/src/occ_gpe1/img_defs.mk index ba8cc18..be5c5a3 100644 --- a/src/occ_gpe1/img_defs.mk +++ b/src/occ_gpe1/img_defs.mk @@ -94,6 +94,10 @@ ifndef PK_SRCDIR export PK_SRCDIR = $(abspath ../ppe/pk) endif +ifndef OCCHW_SRCDIR +export OCCHW_SRCDIR = $(abspath ../ssx/occhw) +endif + ifndef COMMONLIB_SRCDIR export COMMONLIB_SRCDIR = $(abspath ../lib/common) endif @@ -111,16 +115,11 @@ $(warning The CTEPATH variable is not defined; Defaulting to /afs/awd) export CTEPATH = /afs/awd/projects/cte endif -ifdef P2P_ENABLE -# TODO -else - # libs needed by compiler ifndef PPE_TOOL_PATH PPE_TOOL_PATH = $(CTEPATH)/tools/ppetools/prod LD_LIBRARY_PATH += :$(PPE_TOOL_PATH)/lib: export LD_LIBRARY_PATH -endif ifndef GCC-TOOL-PREFIX GCC-TOOL-PREFIX = $(PPE_TOOL_PATH)/bin/powerpc-eabi- @@ -203,11 +202,19 @@ DEFS += $(GCC-DEFS) ############################################################################ -INCLUDES += $(IMG_INCLUDES) $(GLOBAL_INCLUDES) \ - -I$(PK_SRCDIR)/kernel -I$(PK_SRCDIR)/ppe42 -I$(PK_SRCDIR)/trace \ - -I$(PK_SRCDIR)/$(PPE_TYPE) -I$(PK_SRCDIR)/../../include \ - -I$(PK_SRCDIR)/../../include/registers -I$(OCCLIB_SRCDIR) -I$(COMMONLIB_SRCDIR) \ - -I$(OCC_COMMON_TYPES_DIR) -I$(IMAGE_SRCDIR)/../common +INCLUDES += $(IMG_INCLUDES) +INCLUDES += $(GLOBAL_INCLUDES) +INCLUDES += -I$(PK_SRCDIR)/kernel +INCLUDES += -I$(PK_SRCDIR)/ppe42 +INCLUDES += -I$(PK_SRCDIR)/trace +INCLUDES += -I$(PK_SRCDIR)/$(PPE_TYPE) +INCLUDES += -I$(PK_SRCDIR)/../../include +INCLUDES += -I$(PK_SRCDIR)/../../include/registers +INCLUDES += -I$(OCCLIB_SRCDIR) +INCLUDES += -I$(COMMONLIB_SRCDIR) +INCLUDES += -I$(OCC_COMMON_TYPES_DIR) +INCLUDES += -I$(IMAGE_SRCDIR)/../common +INCLUDES += -I$(OCCHW_SRCDIR) ifdef P2P_ENABLE PIPE-CFLAGS = -pipe -Wa,-m405 diff --git a/src/occ_gpe1/ipc_func_tables.c b/src/occ_gpe1/ipc_func_tables.c index a7fe5ea..2ca2486 100644 --- a/src/occ_gpe1/ipc_func_tables.c +++ b/src/occ_gpe1/ipc_func_tables.c @@ -26,6 +26,7 @@ #include "ipc_async_cmd.h" #include "gpe1_dimm.h" #include "gpu_structs.h" +#include "gpe_centaur.h" void gpe_dimm_control(ipc_msg_t* cmd, void* arg); void gpe1_nop(ipc_msg_t* cmd, void* arg); @@ -84,9 +85,9 @@ IPC_HANDLER(gpe_24x7, 0) // 4 - IPC_ST_24_X_7_FUNCID IPC_HANDLER(gpe_mem_power_control, 0) // 5 - IPC_ST_MEM_POWER_CONTROL_FUNCID IPC_HANDLER(gpe_gpu_sm, 0) // 6 - IPC_ST_GPU_SM_FUNCID IPC_HANDLER(gpe_gpu_init, 0) // 7 - IPC_ST_GPE_GPU_INIT_FUNCID -IPC_HANDLER_DEFAULT // 8 -IPC_HANDLER_DEFAULT // 9 -IPC_HANDLER_DEFAULT // 10 +IPC_HANDLER(gpe_centaur_scom, 0) // 8 - IPC_ST_CENTAUR_SCOM_FUNCID +IPC_HANDLER(gpe_centaur_data, 0) // 9 - IPC_ST_CENTAUR_DATA_FUNCID +IPC_HANDLER(gpe_centaur_init, 0) // 10 -IPC_ST_CENTAUR_INIT_FUNCID IPC_HANDLER_DEFAULT // 11 IPC_HANDLER_DEFAULT // 12 IPC_HANDLER_DEFAULT // 13 diff --git a/src/occ_gpe1/topfiles.mk b/src/occ_gpe1/topfiles.mk index d0c2c2f..672d1f7 100644 --- a/src/occ_gpe1/topfiles.mk +++ b/src/occ_gpe1/topfiles.mk @@ -25,7 +25,8 @@ TOP-C-SOURCES = gpe1_main.c gpe1_dimm_read.c gpe1_dimm_reset.c nop.c \ pk_app_irq_table.c ipc_func_tables.c gpe1_dimm_control.c \ - gpe1_24x7.c gpe1_memory_power_control.c gpe_gpu_init.c + gpe1_24x7.c gpe1_memory_power_control.c gpe_gpu_init.c \ + gpe_centaur_scom.c gpe_centaur_configuration.c gpe_centaur.c TOP-S-SOURCES = |