summaryrefslogtreecommitdiffstats
path: root/src/occ_gpe1/gpe_centaur_configuration.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/occ_gpe1/gpe_centaur_configuration.c')
-rw-r--r--src/occ_gpe1/gpe_centaur_configuration.c538
1 files changed, 538 insertions, 0 deletions
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;
+}
+
OpenPOWER on IntegriCloud