summaryrefslogtreecommitdiffstats
path: root/src/occ_gpe1
diff options
context:
space:
mode:
Diffstat (limited to 'src/occ_gpe1')
-rw-r--r--src/occ_gpe1/gpe1_main.c29
-rw-r--r--src/occ_gpe1/gpe_centaur.c726
-rw-r--r--src/occ_gpe1/gpe_centaur.h61
-rw-r--r--src/occ_gpe1/gpe_centaur_configuration.c497
-rw-r--r--src/occ_gpe1/gpe_centaur_scom.c762
-rw-r--r--src/occ_gpe1/gpe_membuf.c147
-rw-r--r--src/occ_gpe1/gpe_membuf.h177
-rw-r--r--src/occ_gpe1/gpe_membuf_scom.c605
-rw-r--r--src/occ_gpe1/gpe_ocmb.c630
-rw-r--r--src/occ_gpe1/ipc_func_tables.c8
-rw-r--r--src/occ_gpe1/link.cmd2
-rw-r--r--src/occ_gpe1/occ_gpe1_machine_check_handler.c38
-rw-r--r--src/occ_gpe1/topfiles.mk5
13 files changed, 2291 insertions, 1396 deletions
diff --git a/src/occ_gpe1/gpe1_main.c b/src/occ_gpe1/gpe1_main.c
index 2385ac9..2115f39 100644
--- a/src/occ_gpe1/gpe1_main.c
+++ b/src/occ_gpe1/gpe1_main.c
@@ -33,7 +33,12 @@
#include "pk_trace.h"
#include "ipc_api.h"
#include "gpe_export.h"
-#include "gpe_centaur.h"
+#include "gpe_membuf.h"
+
+#if defined(__OCMB_UNIT_TEST__)
+#include "membuf_structs.h"
+#include "ocmb_mem_data.h"
+#endif
#define KERNEL_STACK_SIZE 1024
@@ -47,6 +52,18 @@ gpe_shared_data_t * G_gpe_shared_data = (gpe_shared_data_t*) GPE_SHARED_DATA_ADD
extern PkTraceBuffer* g_pk_trace_buf_ptr;
+#if defined(__OCMB_UNIT_TEST__)
+MemBufGetMemDataParms_t G_dataParms;
+MemBufConfiguration_t G_membufConfiguration;
+OcmbMemData G_escache;
+
+extern MemBufConfiguration_t * G_membuf_config;
+
+int gpe_ocmb_configuration_create(MemBufConfiguration_t* o_config);
+int get_ocmb_sensorcache(MemBufConfiguration_t* i_config,
+ MemBufGetMemDataParms_t* i_parms);
+#endif
+
// The main function is called by the boot code (after initializing some
// registers)
int main(int argc, char **argv)
@@ -87,7 +104,17 @@ int main(int argc, char **argv)
PK_TRACE("ipc_enable failed with rc = 0x%08x", rc);
pk_halt();
}
+#if defined(__OCMB_UNIT_TEST__)
+ G_dataParms.error.rc = 0;
+ G_dataParms.collect = 0;
+ G_dataParms.update = -1;
+ G_dataParms.data = (uint64_t*)(&G_escache);
+ G_membuf_config = &G_membufConfiguration;
+
+ rc = get_ocmb_sensorcache(&G_membufConfiguration, &G_dataParms);
+ PK_TRACE("get_ocmb_sensorcache rc = %x",rc);
+#endif
return 0;
}
diff --git a/src/occ_gpe1/gpe_centaur.c b/src/occ_gpe1/gpe_centaur.c
index d492133..6c17878 100644
--- a/src/occ_gpe1/gpe_centaur.c
+++ b/src/occ_gpe1/gpe_centaur.c
@@ -1,102 +1,706 @@
-#include "gpe_centaur.h"
-#include "ipc_async_cmd.h"
-#include "gpe_util.h"
+/* 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
+ */
-CentaurConfiguration_t * G_centaur_config = NULL;
+#include "gpe_membuf.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"
-void gpe_centaur_init(ipc_msg_t* i_cmd, void* i_arg)
+// Power Bus Address bit that configures centaur for HOST/OCC P9=bit(38)
+#define PBA_HOST_OCC_CFG 0x0000000002000000ull;
+
+
+const uint32_t MCFGPR[OCCHW_N_MEMBUF] =
+{
+ 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 MCSYNC[OCCHW_N_MEMBUF/2] =
+{
+ MCS_0_MCSYNC,
+ MCS_1_MCSYNC,
+ MCS_2_MCSYNC,
+ MCS_3_MCSYNC
+};
+
+const uint32_t MCCHIFIR[OCCHW_N_MEMBUF] =
+{
+ MCP_CHAN0_CHI_FIR,
+ MCP_CHAN1_CHI_FIR,
+ MCP_CHAN2_CHI_FIR,
+ MCP_CHAN3_CHI_FIR,
+ MCP_CHAN4_CHI_FIR,
+ MCP_CHAN5_CHI_FIR,
+ MCP_CHAN6_CHI_FIR,
+ MCP_CHAN7_CHI_FIR
+};
+
+const uint32_t MCMCICFG1Q[OCCHW_N_MEMBUF] =
{
- int rc;
- ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd;
- CentaurConfigParms_t* payload = (CentaurConfigParms_t*)async_cmd->cmd_data;
+ MCP_CHAN0_CHI_MCICFG1Q,
+ MCP_CHAN1_CHI_MCICFG1Q,
+ MCP_CHAN2_CHI_MCICFG1Q,
+ MCP_CHAN3_CHI_MCICFG1Q,
+ MCP_CHAN4_CHI_MCICFG1Q,
+ MCP_CHAN5_CHI_MCICFG1Q,
+ MCP_CHAN6_CHI_MCICFG1Q,
+ MCP_CHAN7_CHI_MCICFG1Q
+};
+
+///////////////////////////////////////////////////////////////
+// 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;
- CentaurConfiguration_t * config = payload->centaurConfiguration;
- G_centaur_config = config;
+ slvctl->fields.enable = 1;
+ mask->fields.enable = all1;
- payload->error.error = 0;
- payload->error.ffdc = 0;
+ slvctl->fields.mid_match_value = OCI_MASTER_ID_GPE1;
+ mask->fields.mid_match_value = all1;
- if(G_centaur_config == NULL)
+ 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)
{
- PK_TRACE("gpe_centaur_init: centaurConfiguration data ptr is NULL!");
- rc = GPE_RC_CONFIG_DATA_NULL_PTR;
+
+ 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
{
- PK_TRACE("Centaur_configuration. MSR:%08x",mfmsr());
- rc = gpe_centaur_configuration_create(G_centaur_config);
+
+ slvctl->fields.buf_invalidate_ctl = 0;
+ mask->fields.buf_invalidate_ctl = all1;
}
- payload->error.rc = rc;
+ mask->value = ~(mask->value);
+
+ return 0;
+}
+
+
+////////////////////////////////////////////////
+// Centaur specific routines
+////////////////////////////////////////////////
+int gpe_centaur_configuration_create(MemBufConfiguration_t* o_config)
+{
+ int rc = 0;
+ unsigned int i = 0;
+ mcfgpr_t mcfgpr;
+ uint64_t* ptr = (uint64_t*)o_config;
+ int designated_sync = -1;
+
+ // Prevent unwanted interrupts from scom errors
+ const uint32_t orig_msr = mfmsr();
+ mtmsr((orig_msr & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM);
- // Send response
- rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS);
- if(rc)
+ for(i = 0; i < sizeof(MemBufConfiguration_t) / 8; ++i)
{
- PK_TRACE("gpe_centaur_init: Failed to send response. rc = %x. Halting GPE1.",
- rc);
+ *ptr++ = 0ull;
+ }
+
+ o_config->configRc = MEMBUF_NOT_CONFIGURED;
+
+ do
+ {
+ // Create the PBASLV configurations for the GPE procedures.
+ // The 'dataParms' define the PBASLV setup needed to access the
+ // Centaur sensor cache. The 'scomParms' define the PBASLV setup
+ // needed to access the Centaur SCOMs.
+
+ rc = gpe_pba_parms_create(&(o_config->dataParms),
+ PBA_SLAVE_MEMBUF,
+ PBA_WRITE_TTYPE_CI_PR_W,
+ PBA_WRITE_TTYPE_DC,
+ PBA_READ_TTYPE_CL_RD_NC);
+
+ if (rc)
+ {
+ rc = MEMBUF_DATA_SETUP_ERROR;
+ break;
+ }
+
+ rc = gpe_pba_parms_create(&(o_config->scomParms),
+ PBA_SLAVE_MEMBUF,
+ PBA_WRITE_TTYPE_CI_PR_W,
+ PBA_WRITE_TTYPE_DC,
+ PBA_READ_TTYPE_CI_PR_RD);
+
+ if (rc)
+ {
+ rc = MEMBUF_SCOM_SETUP_ERROR;
+ break;
+ }
+
+ // Iterate through each MCS on the chip and check configuration.
+
+ // Note that the code uniformly treats SCOM failures of the MCFGPR
+ // registers as an unconfigured Centaur. This works both for real
+ // hardware, as well as for our VBU models where some of the "valid"
+ // MCS are not in the simulation models.
+
+ for (i = 0; i < OCCHW_N_MEMBUF; ++i)
+ {
+ // check for channel checkstop
+ rc = check_centaur_channel_chkstp(i);
+ if (rc)
+ {
+ // If scom failed OR there is a channel checkstop then
+ // Centaur is not usable.
+ rc = 0;
+ continue;
+ }
+
+ // Verify that inband scom has been setup. If not then
+ // assume the centaur is either non-existant or not configured.
+ // Setup is provided by HWP p9c_set_inband_addr.C
+ rc = getscom_abs(MCFGPR[i], &(mcfgpr.value));
+
+ if (rc)
+ {
+ // ignore if can't be scomed.
+ rc = 0;
+ continue;
+ }
+
+ // If inband scom is not configured then assume the centaur does not exist
+ if (!mcfgpr.fields.mcfgprq_valid)
+ {
+ continue;
+ }
+
+
+ // The 31-bit base-address (inband scom BAR) corresponds to bits [8:38] 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]);
+
+ // Add the Centaur to the configuration
+ o_config->config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_MEMBUF(i));
+ }
+
+ if (rc)
+ {
+ break;
+ }
+
+ // Find the designated sync
+ for (i = 0; i < (OCCHW_N_MEMBUF/2); ++i)
+ {
+ uint64_t mcsync;
+ rc = getscom_abs(MCSYNC[i], &mcsync);
+ if (rc)
+ {
+ PK_TRACE("getscom failed on MCSYNC, rc = %d. The first configured MC will be"
+ " the designated sync",rc);
+ rc = 0;
+ }
+ if (mcsync != 0)
+ {
+ designated_sync = i;
+ // There can only be one sync, so stop searching.
+ break;
+ }
+ }
+
+ if (designated_sync < 0)
+ {
+ designated_sync = cntlz32(o_config->config << CHIP_CONFIG_MCS_BASE);
+ PK_TRACE("No designated sync found, using MCS(%d)",designated_sync);
+ }
+
+ o_config->mcSyncAddr = MCSYNC[designated_sync];
+
+
+ rc = configure_pba_bar_for_inband_access(o_config);
+ if( rc )
+ {
+ break;
+ }
+ // At this point the structure is initialized well-enough that it can
+ // be used by gpe_inband_scom().
+
+
+ o_config->configRc = 0;
+
+ if (o_config->config == 0)
+ {
+ break;
+ }
+
+
+ // Get Device ID from each centaur
+ membuf_get_scom_vector(o_config,
+ CENTAUR_DEVICE_ID,
+ (uint64_t*)(&(o_config->deviceId[0])));
- gpe_set_ffdc(&(payload->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
- pk_halt();
}
+ while(0);
+
+ o_config->configRc = rc;
+
+ mtmsr(orig_msr);
+
+ return rc;
}
-void gpe_centaur_scom(ipc_msg_t* i_cmd, void* i_arg)
+int configure_pba_bar_for_inband_access(MemBufConfiguration_t * i_config)
{
- static int g_log_once = 0;
- int rc;
- ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd;
- CentaurScomParms_t * scomParms = (CentaurScomParms_t*)async_cmd->cmd_data;
+ uint64_t bar = 0;
+ uint64_t barMsk = PBA_BARMSKN_MASK_MASK;
+ uint64_t mask = 0;
+ int i = 0;
+ int rc = 0;
- if(g_log_once == 0)
+ do
{
- g_log_once = 1;
- PK_TRACE("Centaur Scom. MSR:%08x",mfmsr());
- }
- gpe_scom_centaur(G_centaur_config, scomParms);
+ // 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 (i_config->config != 0)
+ {
+
+ for (i = 0; i < OCCHW_N_MEMBUF; ++i)
+ {
+ bar |= i_config->baseAddress[i];
+ }
+
+ bar &= ~barMsk;
+
+ PK_TRACE_DBG("PBABAR(%d): %016llx", PBA_BAR_MEMBUF, bar);
+ PK_TRACE_DBG("PBABARMSK: %016llx", barMsk);
+
+ rc = putscom_abs(PBA_BARMSKN(PBA_BAR_MEMBUF), barMsk);
+
+ if (rc)
+ {
+ PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n",
+ (uint32_t)rc, PBA_BAR_MEMBUF);
+ rc = MEMBUF_BARMSKN_PUTSCOM_FAILURE;
+ break;
+ }
+
+ rc = putscom_abs(PBA_BARN(PBA_BAR_MEMBUF), bar);
+ if (rc)
+ {
+ PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n",
+ (uint32_t)rc, PBA_BAR_MEMBUF);
+ rc = MEMBUF_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 (i_config->config != 0)
+ {
+ rc = getscom_abs(PBA_BARN(PBA_BAR_MEMBUF), &bar);
+
+ if (rc)
+ {
+ PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n",
+ (uint32_t)rc, PBA_BAR_MEMBUF);
+ rc = MEMBUF_BARN_GETSCOM_FAILURE;
+ break;
+ }
+
+ rc = getscom_abs(PBA_BARMSKN(PBA_BAR_MEMBUF), &mask);
+
+ if (rc)
+ {
+ PK_TRACE_DBG("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n",
+ (uint32_t)rc, PBA_BAR_MEMBUF);
+ rc = MEMBUF_BARMSKN_GETSCOM_FAILURE;
+ break;
+ }
+
+ bar = bar & PBA_BARN_ADDR_MASK;
+ mask = mask & PBA_BARMSKN_MASK_MASK;
+
+ if ((mask & 0x0000000003f00000ull) != 0x0000000003f00000ull)
+ {
- // Send response
- rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS);
- if(rc)
+ PK_TRACE("PBA BAR mask (%d) does not cover bits 38:43\n", PBA_BAR_MEMBUF);
+ rc = MEMBUF_MASK_ERROR;
+ break;
+ }
+
+ for (i = 0; i < OCCHW_N_MEMBUF; ++i)
+ {
+ if (i_config->baseAddress[i] != 0)
+ {
+ if ((i_config->baseAddress[i] & ~mask) !=
+ (bar & ~mask))
+ {
+
+ PK_TRACE("BAR/Mask (%d) error for MCS/Centaur %d",
+ PBA_BAR_MEMBUF, i);
+
+ PK_TRACE(" base = 0x%08x%08x",
+ (uint32_t)(i_config->baseAddress[i]>>32),
+ (uint32_t)(i_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 = MEMBUF_BAR_MASK_ERROR;
+ break;
+ }
+ }
+ }
+ }
+ } while(0);
+ return rc;
+}
+
+
+
+int check_centaur_channel_chkstp(unsigned int i_centaur)
+{
+ int rc = 0;
+ mcchifir_t chifir;
+ mcmcicfg_t chicfg;
+
+ do
{
- PK_TRACE("gpe_centaur_scom: Failed to send response. rc = %x. Halting GPE1.",
- rc);
+ rc = getscom_abs(MCCHIFIR[i_centaur], &(chifir.value));
+ if (rc)
+ {
+ PK_TRACE("MCCHIFIR scom failed. rc = %d",rc);
+ break;
+ }
- gpe_set_ffdc(&(scomParms->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
- pk_halt();
- }
+ if(chifir.fields.fir_dsrc_no_forward_progress ||
+ chifir.fields.fir_dmi_channel_fail ||
+ chifir.fields.fir_channel_init_timeout ||
+ chifir.fields.fir_channel_interlock_err ||
+ chifir.fields.fir_replay_buffer_ue ||
+ chifir.fields.fir_replay_buffer_overrun ||
+ chifir.fields.fir_df_sm_perr ||
+ chifir.fields.fir_cen_checkstop ||
+ chifir.fields.fir_dsff_tag_overrun ||
+ chifir.fields.fir_dsff_mca_async_cmd_error ||
+ chifir.fields.fir_dsff_seq_error ||
+ chifir.fields.fir_dsff_timeout)
+ {
+ PK_TRACE("MCCHIFIR: %08x%08x for channel %d",
+ chifir.words.high_order,
+ chifir.words.low_order,
+ i_centaur);
+ rc = getscom_abs(MCMCICFG1Q[i_centaur], &(chicfg.value));
+ if (rc)
+ {
+ PK_TRACE("MCMCICFG scom failed. rc = %d",rc);
+ break;
+ }
+ PK_TRACE("MCMCICFG1Q %08x%08x",
+ chicfg.words.high_order,
+ chicfg.words.low_order);
+
+ rc = MEMBUF_CHANNEL_CHECKSTOP;
+ }
+ } while(0);
+
+ return rc;
}
-void gpe_centaur_data(ipc_msg_t* i_cmd, void* i_arg)
+int centaur_throttle_sync(MemBufConfiguration_t* i_config)
{
- static int g_log_once = 0;
- int rc;
- ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd;
+ uint64_t data;
+ int rc = 0;
+ do
+ {
+ rc = getscom_abs(i_config->mcSyncAddr,&data);
+ if (rc)
+ {
+ PK_TRACE("centaur_throttle_sync: getscom failed. rc = %d",rc);
+ break;
+ }
- CentaurGetMemDataParms_t * dataParms =
- (CentaurGetMemDataParms_t *)async_cmd->cmd_data;
+ data &= ~MCS_MCSYNC_SYNC_GO;
- if(g_log_once == 0)
+ rc = putscom_abs(i_config->mcSyncAddr, data);
+ if (rc)
+ {
+ PK_TRACE("centaur_throttle_sync: reset sync putscom failed. rc = %d",rc);
+ break;
+ }
+
+ data |= MCS_MCSYNC_SYNC_GO;
+
+ rc = putscom_abs(i_config->mcSyncAddr, data);
+ if (rc)
+ {
+ PK_TRACE("centaur_throttle_sync: set sync putscom failed. rc = %d",rc);
+ break;
+ }
+ } while (0);
+
+ return rc;
+}
+
+int centaur_sensorcache_setup(MemBufConfiguration_t* i_config,
+ uint32_t i_centaur_instance,
+ uint32_t * o_oci_addr)
+{
+ int rc = 0;
+#if defined(__USE_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(__USE_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);
+#else
{
- g_log_once = 1;
- PK_TRACE("Centaur Data. MSR:%08x",mfmsr());
+ // HW bug workaround - don't use extaddr - use pbabar.
+ uint64_t barMsk = 0;
+
+ // Mask SIB from generating mck
+ mtmsr(mfmsr() | MSR_SEM);
+
+ // put the PBA in the BAR
+ rc = putscom_abs(PBA_BARN(PBA_BAR_MEMBUF), pb_addr);
+ if (rc)
+ {
+ PK_TRACE("centaur_sensorcache_setup: putscom fail on PBABAR,"
+ " rc = %d",rc);
+ }
+ else
+ {
+ rc = putscom_abs(PBA_BARMSKN(PBA_BAR_MEMBUF), barMsk);
+ if (rc)
+ {
+ PK_TRACE("centaur_sensrocache_setup: putscom fail on"
+ " PBABARMSK, rc = %d",rc);
+ }
+ }
}
- rc = centaur_get_mem_data(G_centaur_config, dataParms);
+#endif
+ // make oci address
+ *o_oci_addr = (uint32_t)(pb_addr & 0x07ffffffull);
+
+ // PBA space bits[0:1] = '10' bar select bits[3:4]
+ *o_oci_addr |= ((PBA_BAR_MEMBUF | 0x8) << 28);
+
+ return rc;
+}
+
+
+// read centaur data sensor cache
+int get_centaur_sensorcache(MemBufConfiguration_t* i_config,
+ MemBufGetMemDataParms_t* i_parms)
+{
+ int rc = 0;
+ uint32_t oci_addr = 0;
+ uint64_t pba_slvctln_save;
+ uint64_t data64 = 0;
+
+ i_parms->error.rc = MEMBUF_GET_MEM_DATA_DIED;
- dataParms->error.rc = rc;
+ pbaslvctl_reset(&(i_config->dataParms));
+ pba_slvctln_save = pbaslvctl_setup(&(i_config->dataParms));
- // Send response
- rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS);
- if(rc)
+ // Clear SIB error accumulator bits & mask SIB errors from
+ // generating machine checks
+ mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM);
+
+ if(i_parms->collect != -1)
{
- PK_TRACE("gpe_centaur_init: Failed to send response. rc = %x. Halting GPE1.",
- rc);
+ if((i_parms->collect >= OCCHW_N_MEMBUF) ||
+ (0 == (CHIP_CONFIG_MEMBUF(i_parms->collect) & (i_config->config))))
+ {
+ rc = MEMBUF_GET_MEM_DATA_COLLECT_INVALID;
+ }
+ else
+ {
+ rc = centaur_sensorcache_setup(i_config, i_parms->collect,&oci_addr);
+
+ if(!rc)
+ {
+ uint32_t org_msr = mfmsr();
+ mtmsr(org_msr | MSR_SEM); // Mask off SIB errors from gen mck
+ g_inband_access_state = INBAND_ACCESS_IN_PROGRESS;
+ // 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);
+ }
- gpe_set_ffdc(&(dataParms->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
- pk_halt();
+ // Poll for SIB errors or machine check
+ if((mfmsr() & MSR_SIBRC) ||
+ g_inband_access_state != INBAND_ACCESS_IN_PROGRESS)
+ {
+ // Take centaur out of config list
+ PK_TRACE("Removing Membuf %d from list of configured Membufs",
+ i_parms->collect);
+ i_config->config &= ~(CHIP_CONFIG_MEMBUF(i_parms->collect));
+
+ // This rc will cause the 405 to remove this centaur sensor
+ rc = MEMBUF_CHANNEL_CHECKSTOP;
+ }
+ mtmsr(org_msr);
+ g_inband_access_state = INBAND_ACCESS_INACTIVE;
+ }
+ }
}
+
+ if(i_parms->update != -1)
+ {
+ int update_rc = 0;
+ if((i_parms->update >= OCCHW_N_MEMBUF) ||
+ (0 == (CHIP_CONFIG_MEMBUF(i_parms->update) & (i_config->config))))
+ {
+ update_rc = MEMBUF_GET_MEM_DATA_UPDATE_INVALID;
+ }
+ else
+ {
+ update_rc = centaur_sensorcache_setup(i_config, i_parms->update,&oci_addr);
+
+ if(!update_rc)
+ {
+ // Writing a zero to this address tells the centaur to update
+ // the sensor cache for the next centaur.
+ data64 = 0;
+ update_rc = inband_access(i_config,
+ i_parms->update,
+ oci_addr,
+ &data64,
+ INBAND_ACCESS_WRITE);
+ }
+ }
+ if(!rc && update_rc)
+ {
+ rc = update_rc;
+ }
+ }
+
+ pbaslvctl_reset(&(i_config->dataParms));
+ PPE_STVD((i_config->dataParms).slvctl_address, pba_slvctln_save);
+
+ if(!rc)
+ {
+ int instance = i_parms->collect;
+ if(instance == -1)
+ {
+ instance = i_parms->update;
+ }
+ if (instance != -1)
+ {
+ rc = check_centaur_channel_chkstp(instance);
+ }
+ }
+
+ i_parms->error.rc = rc;
+ return rc;
}
+
diff --git a/src/occ_gpe1/gpe_centaur.h b/src/occ_gpe1/gpe_centaur.h
deleted file mode 100644
index 482af22..0000000
--- a/src/occ_gpe1/gpe_centaur.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#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);
-
-/**
- * Check for channel checkstop
- * @param[in] The ordinal centaur number
- * @return [0 | return code]
- */
-int check_channel_chkstp(unsigned int i_centaur);
-
-extern uint32_t g_centaur_access_state;
-#endif
diff --git a/src/occ_gpe1/gpe_centaur_configuration.c b/src/occ_gpe1/gpe_centaur_configuration.c
deleted file mode 100644
index b9866bb..0000000
--- a/src/occ_gpe1/gpe_centaur_configuration.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/* 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 MCSYNC[OCCHW_NCENTAUR/2] =
-{
- MCS_0_MCSYNC,
- MCS_1_MCSYNC,
- MCS_2_MCSYNC,
- MCS_3_MCSYNC
-};
-
-const uint32_t MCCHIFIR[OCCHW_NCENTAUR] =
-{
- MCP_CHAN0_CHI_FIR,
- MCP_CHAN1_CHI_FIR,
- MCP_CHAN2_CHI_FIR,
- MCP_CHAN3_CHI_FIR,
- MCP_CHAN4_CHI_FIR,
- MCP_CHAN5_CHI_FIR,
- MCP_CHAN6_CHI_FIR,
- MCP_CHAN7_CHI_FIR
-};
-
-const uint32_t MCMCICFG1Q[OCCHW_NCENTAUR] =
-{
- MCP_CHAN0_CHI_MCICFG1Q,
- MCP_CHAN1_CHI_MCICFG1Q,
- MCP_CHAN2_CHI_MCICFG1Q,
- MCP_CHAN3_CHI_MCICFG1Q,
- MCP_CHAN4_CHI_MCICFG1Q,
- MCP_CHAN5_CHI_MCICFG1Q,
- MCP_CHAN6_CHI_MCICFG1Q,
- MCP_CHAN7_CHI_MCICFG1Q
-};
-
-///////////////////////////////////////////////////////////////
-// 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;
- uint64_t bar = 0;
- uint64_t mask = 0;
- uint64_t* ptr = (uint64_t*)o_config;
- int designated_sync = -1;
-
- // 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 PBASLV configurations for the GPE procedures.
- // The 'dataParms' define the PBASLV setup needed to access the
- // Centaur sensor cache. The 'scomParms' define the PBASLV setup
- // needed to access the 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;
- }
-
- // Iterate through each MCS on the chip and check configuration.
-
- // Note that the code uniformly treats SCOM failures of the MCFGPR
- // registers as an unconfigured Centaur. This works both for real
- // hardware, 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)
- {
- // check for channel checkstop
- rc = check_channel_chkstp(i);
- if (rc)
- {
- // If scom failed OR there is a channel checkstop then
- // Centaur is not usable.
- rc = 0;
- continue;
- }
-
- // Verify that inband scom has been setup. If not then
- // assume the centaur is either non-existant or not configured.
- // Setup is provided by HWP p9c_set_inband_addr.C
- rc = getscom_abs(MCFGPR[i], &(mcfgpr.value));
-
- if (rc)
- {
- // ignore if can't be scomed.
- rc = 0;
- continue;
- }
-
- // If inband scom is not configured then assume the centaur does not exist
- if (!mcfgpr.fields.mcfgprq_valid)
- {
- continue;
- }
-
-
- // The 31-bit base-address (inband scom BAR) corresponds to bits [8:38] 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]);
-
- // Add the Centaur to the configuration
- o_config->config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_CENTAUR(i));
- }
-
- if (rc)
- {
- break;
- }
-
- // Find the designated sync
- for (i = 0; i < (OCCHW_NCENTAUR/2); ++i)
- {
- uint64_t mcsync;
- rc = getscom_abs(MCSYNC[i], &mcsync);
- if (rc)
- {
- PK_TRACE("getscom failed on MCSYNC, rc = %d. The first configured MC will be the designated sync",rc);
- rc = 0;
- }
- if (mcsync != 0)
- {
- designated_sync = i;
- // There can only be one sync, so stop searching.
- break;
- }
- }
-
- if (designated_sync < 0)
- {
- designated_sync = cntlz32(o_config->config << CHIP_CONFIG_MCS_BASE);
- PK_TRACE("No designated sync found, using MCS(%d)",designated_sync);
- }
-
- o_config->mcSyncAddr = MCSYNC[designated_sync];
-
-
- // 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;
-}
-
-int check_channel_chkstp(unsigned int i_centaur)
-{
- int rc = 0;
- mcchifir_t chifir;
- mcmcicfg_t chicfg;
-
- do
- {
- rc = getscom_abs(MCCHIFIR[i_centaur], &(chifir.value));
- if (rc)
- {
- PK_TRACE("MCCHIFIR scom failed. rc = %d",rc);
- break;
- }
-
- if(chifir.fields.fir_dsrc_no_forward_progress ||
- chifir.fields.fir_dmi_channel_fail ||
- chifir.fields.fir_channel_init_timeout ||
- chifir.fields.fir_channel_interlock_err ||
- chifir.fields.fir_replay_buffer_ue ||
- chifir.fields.fir_replay_buffer_overrun ||
- chifir.fields.fir_df_sm_perr ||
- chifir.fields.fir_cen_checkstop ||
- chifir.fields.fir_dsff_tag_overrun ||
- chifir.fields.fir_dsff_mca_async_cmd_error ||
- chifir.fields.fir_dsff_seq_error ||
- chifir.fields.fir_dsff_timeout)
- {
- PK_TRACE("MCCHIFIR: %08x%08x for channel %d",
- chifir.words.high_order,
- chifir.words.low_order,
- i_centaur);
-
- rc = getscom_abs(MCMCICFG1Q[i_centaur], &(chicfg.value));
- if (rc)
- {
- PK_TRACE("MCMCICFG scom failed. rc = %d",rc);
- break;
- }
-
- PK_TRACE("MCMCICFG1Q %08x%08x",
- chicfg.words.high_order,
- chicfg.words.low_order);
-
- rc = CENTAUR_CHANNEL_CHECKSTOP;
- }
- } while(0);
-
- return rc;
-}
diff --git a/src/occ_gpe1/gpe_centaur_scom.c b/src/occ_gpe1/gpe_centaur_scom.c
deleted file mode 100644
index edee857..0000000
--- a/src/occ_gpe1/gpe_centaur_scom.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/* 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"
-
-#define CENTAUR_ACCESS_READ 1
-#define CENTAUR_ACCESS_WRITE 2
-
-/**
- * @file centaur_scom
- * @brief scom access from gpe to a centaur
- */
-
-uint32_t g_centaur_access_state = CENTAUR_ACCESS_INACTIVE;
-
-int centaur_access(CentaurConfiguration_t* i_config,
- uint32_t i_instance,
- uint32_t i_oci_addr,
- uint64_t * io_data,
- int i_read_write)
-{
- int rc = 0;
- uint32_t org_msr = mfmsr();
- uint32_t msr = org_msr | MSR_SEM; // Mask off SIB from generating mck.
-
- g_centaur_access_state = CENTAUR_ACCESS_IN_PROGRESS;
-
- if(i_read_write == CENTAUR_ACCESS_READ)
- {
- mtmsr(msr);
- sync();
- PPE_LVD(i_oci_addr, *io_data);
- }
- else
- {
- // Set PPE to precise mode for stores so that in the case of a machine
- // check, there is a predictable instruction address to resume on.
- msr &= ~MSR_IPE;
- mtmsr(msr);
- sync();
-
- PPE_STVD(i_oci_addr, *io_data);
- }
-
- // Poll SIB error or machine check
- if((mfmsr() & MSR_SIBRC) ||
- g_centaur_access_state != CENTAUR_ACCESS_IN_PROGRESS)
- {
- // Take centaur out of config
- PK_TRACE("Removing Centaur %d from list of configured Centaurs",
- i_instance);
-
- i_config->config &= ~(CHIP_CONFIG_CENTAUR(i_instance));
-
- // This will cause the 405 to remove the centaur sensor.
- rc = CENTAUR_CHANNEL_CHECKSTOP;
- }
- g_centaur_access_state = CENTAUR_ACCESS_INACTIVE;
- mtmsr(org_msr);
- return rc;
-}
-
-/**
- * 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
- */
-int centaur_scom_setup(CentaurConfiguration_t* i_config,
- uint32_t i_centaur_instance,
- uint32_t i_scom_address,
- uint32_t *o_oci_addr)
-{
- int rc = 0;
-#if defined(__USE_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(__USE_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);
-#else
- // HW bug work-around
- {
- // workaround - don't use extraddr - use pbabar.
- uint64_t barMsk = 0;
-
- // Mask SIB from generating mck
- mtmsr(mfmsr() | MSR_SEM);
-
- // put the PBA in the BAR
- rc = putscom_abs(PBA_BARN(PBA_BAR_CENTAUR), pb_addr);
- if(rc)
- {
- PK_TRACE("centaur_scom_setup. putscom fail on PBABAR."
- " rc = %d",rc);
- }
- else
- {
- rc = putscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), barMsk);
- if(rc)
- {
- PK_TRACE("centaur_scom_setup. putscom fail on PBABARMSK"
- " rc = %d",rc);
- }
- }
- }
-#endif
- // make oci address
- *o_oci_addr = (uint32_t)(pb_addr & 0x07ffffffull);
-
- // upper nibble is PBA region and BAR_SELECT
- *o_oci_addr |= ((PBA_BAR_CENTAUR | 0x8) << 28);
- PK_TRACE_DBG("Centaur OCI scom addr: %08x",*o_oci_addr);
- return rc;
-}
-
-int centaur_sensorcache_setup(CentaurConfiguration_t* i_config,
- uint32_t i_centaur_instance,
- uint32_t * o_oci_addr)
-{
- int rc = 0;
-#if defined(__USE_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(__USE_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);
-#else
- {
- // HW bug workaround - don't use extaddr - use pbabar.
- uint64_t barMsk = 0;
-
- // Mask SIB from generating mck
- mtmsr(mfmsr() | MSR_SEM);
-
- // put the PBA in the BAR
- rc = putscom_abs(PBA_BARN(PBA_BAR_CENTAUR), pb_addr);
- if (rc)
- {
- PK_TRACE("centaur_sensorcache_setup: putscom fail on PBABAR,"
- " rc = %d",rc);
- }
- else
- {
- rc = putscom_abs(PBA_BARMSKN(PBA_BAR_CENTAUR), barMsk);
- if (rc)
- {
- PK_TRACE("centaur_sensrocache_setup: putscom fail on"
- " PBABARMSK, rc = %d",rc);
- }
- }
- }
-#endif
- // make oci address
- *o_oci_addr = (uint32_t)(pb_addr & 0x07ffffffull);
-
- // PBA space bits[0:1] = '10' bar select bits[3:4]
- *o_oci_addr |= ((PBA_BAR_CENTAUR | 0x8) << 28);
-
- return rc;
-}
-
-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 data from each existing centaur.
-int centaur_get_scom_vector(CentaurConfiguration_t* i_config,
- uint32_t i_scom_address,
- uint64_t* o_data)
-{
- int rc = 0;
- int access_rc = 0;
- int pba_rc = 0;
- 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;
- pba_rc = centaur_scom_setup(i_config,
- instance,
- i_scom_address,
- &oci_addr);
-
- if(pba_rc)
- {
- rc = pba_rc;
- // Already traced.
- // Trumps any access error
- *o_data = 0;
- }
-
- // read centaur scom
- access_rc = centaur_access(i_config,
- instance,
- oci_addr,
- o_data,
- CENTAUR_ACCESS_READ);
- if(!rc && access_rc)
- {
- // not critical, but don't touch this centaur again.
- rc = access_rc;
- *o_data = 0;
- // continue
- }
- }
- 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;
-}
-
-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));
-
- rc = centaur_scom_setup(i_config,
- i_centaur_instance,
- i_scom_address,
- &oci_addr);
-
- if( !rc && (CHIP_CONFIG_CENTAUR(i_centaur_instance) & (i_config->config)))
- {
- // read centaur scom
- rc = centaur_access(i_config,
- i_centaur_instance,
- oci_addr,
- o_data,
- CENTAUR_ACCESS_READ);
- }
- 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 rc = 0;
- int pba_rc = 0;
- int access_rc = 0;
- int instance = 0;
- uint64_t pba_slvctln_save;
-
- pbaslvctl_reset(&(i_config->scomParms));
- pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms));
-
- for(instance = 0; instance < OCCHW_NCENTAUR; ++instance)
- {
- if( CHIP_CONFIG_CENTAUR(instance) & (i_config->config))
- {
- uint32_t oci_addr;
- pba_rc = centaur_scom_setup(i_config,
- instance,
- i_scom_address,
- &oci_addr);
-
- if(pba_rc)
- {
- // Already traced in centaur_scom_setup
- // Trumps access_rc
- rc = pba_rc;
- }
-
- // centaur scom
- access_rc = centaur_access(i_config,
- instance,
- oci_addr,
- &i_data,
- CENTAUR_ACCESS_WRITE);
- if(!rc && access_rc)
- {
- // Centaur won't be touched again.
- rc = access_rc;
- // continue
- }
- }
- }
-
- // reset pba slave
- pbaslvctl_reset(&(i_config->scomParms));
- PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save);
-
- return rc;
-}
-
-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));
-
- rc = centaur_scom_setup(i_config,
- i_centaur_instance,
- i_scom_address,
- &oci_addr);
-
- if(!rc)
- {
- if(CHIP_CONFIG_CENTAUR(i_centaur_instance) & (i_config->config))
- {
- // write centaur scom
- rc = centaur_access(i_config,
- i_centaur_instance,
- oci_addr,
- &i_data,
- CENTAUR_ACCESS_WRITE);
- }
- }
-
- // reset pba slave
- 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));
-
- rc = centaur_scom_setup(i_config,
- i_centaur_instance,
- i_scom_address,
- &oci_addr);
- if(!rc)
- {
-
- rc = centaur_access(i_config,
- i_centaur_instance,
- oci_addr,
- &data64,
- CENTAUR_ACCESS_READ);
-
- if(!rc)
- {
- data64 &= (i_mask ^ 0xffffffffffffffffull);
- data64 |= *i_data;
-
- rc = centaur_access(i_config,
- i_centaur_instance,
- oci_addr,
- &data64,
- CENTAUR_ACCESS_WRITE);
- }
- }
-
- 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 rc = 0;
- int pba_rc = 0;
- int access_rc = 0;
- int instance = 0;
- uint64_t pba_slvctln_save;
-
- pbaslvctl_reset(&(i_config->scomParms));
- pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms));
-
- for(instance = 0; (instance < OCCHW_NCENTAUR); ++instance)
- {
- if( CHIP_CONFIG_CENTAUR(instance) & (i_config->config))
- {
- uint64_t data64;
- uint32_t oci_addr;
- pba_rc = centaur_scom_setup(i_config,
- instance,
- i_scom_address,
- &oci_addr);
- if(pba_rc)
- {
- rc = pba_rc;
- // Already traced in centaur_scom_setup
- // Trumps any access_rc
- }
- if(!pba_rc)
- {
-
- access_rc = centaur_access(i_config,
- instance,
- oci_addr,
- &data64,
- CENTAUR_ACCESS_READ);
-
- if(!access_rc)
- {
- data64 &= (i_mask ^ 0xffffffffffffffffull);
- data64 |= i_data;
-
- access_rc = centaur_access(i_config,
- instance,
- oci_addr,
- &data64,
- CENTAUR_ACCESS_WRITE);
- }
- }
- if(!rc && access_rc)
- {
- rc = access_rc;
- }
-
- pbaslvctl_reset(&(i_config->scomParms));
- }
- }
-
- PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save);
-
- return rc;
-}
-
-
-// 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;
-
- i_parms->error.rc = CENTAUR_GET_MEM_DATA_DIED;
-
- pbaslvctl_reset(&(i_config->dataParms));
- pba_slvctln_save = pbaslvctl_setup(&(i_config->dataParms));
-
- // Clear SIB error accumulator bits & mask SIB errors from
- // generating machine checks
- mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM);
-
- 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
- {
- rc = centaur_sensorcache_setup(i_config, i_parms->collect,&oci_addr);
-
- if(!rc)
- {
- uint32_t org_msr = mfmsr();
- mtmsr(org_msr | MSR_SEM); // Mask off SIB errors from gen mck
- g_centaur_access_state = CENTAUR_ACCESS_IN_PROGRESS;
- // 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);
- }
-
- // Poll for SIB errors or machine check
- if((mfmsr() & MSR_SIBRC) ||
- g_centaur_access_state != CENTAUR_ACCESS_IN_PROGRESS)
- {
- // Take centaur out of config list
- PK_TRACE("Removing Centaur %d from list of configured Centaurs",
- i_parms->collect);
- i_config->config &= ~(CHIP_CONFIG_CENTAUR(i_parms->collect));
-
- // This rc will cause the 405 to remove this centaur sensor
- rc = CENTAUR_CHANNEL_CHECKSTOP;
- }
- mtmsr(org_msr);
- g_centaur_access_state = CENTAUR_ACCESS_INACTIVE;
- }
- }
- }
-
- if(i_parms->update != -1)
- {
- int update_rc = 0;
- if((i_parms->update >= OCCHW_NCENTAUR) ||
- (0 == (CHIP_CONFIG_CENTAUR(i_parms->update) & (i_config->config))))
- {
- update_rc = CENTAUR_GET_MEM_DATA_UPDATE_INVALID;
- }
- else
- {
- update_rc = centaur_sensorcache_setup(i_config, i_parms->update,&oci_addr);
-
- if(!update_rc)
- {
- // Writing a zero to this address tells the centaur to update
- // the sensor cache for the next centaur.
- data64 = 0;
- update_rc = centaur_access(i_config,
- i_parms->update,
- oci_addr,
- &data64,
- CENTAUR_ACCESS_WRITE);
- }
- }
- if(!rc && update_rc)
- {
- rc = update_rc;
- }
- }
-
- pbaslvctl_reset(&(i_config->dataParms));
- PPE_STVD((i_config->dataParms).slvctl_address, pba_slvctln_save);
-
- if(!rc)
- {
- int instance = i_parms->collect;
- if(instance == -1)
- {
- instance = i_parms->update;
- }
- if (instance != -1)
- {
- rc = check_channel_chkstp(instance);
- }
- }
-
-
- i_parms->error.rc = rc;
- return rc;
-}
-
-
-int centaur_scom_sync(CentaurConfiguration_t* i_config)
-{
- uint64_t data;
- int rc = 0;
- do
- {
- rc = getscom_abs(i_config->mcSyncAddr,&data);
- if (rc)
- {
- PK_TRACE("centaur_scom_sync: getscom failed. rc = %d",rc);
- break;
- }
-
- data &= ~MCS_MCSYNC_SYNC_GO;
-
- rc = putscom_abs(i_config->mcSyncAddr, data);
- if (rc)
- {
- PK_TRACE("centaur_scom_sync: reset sync putscom failed. rc = %d",rc);
- break;
- }
-
- data |= MCS_MCSYNC_SYNC_GO;
-
- rc = putscom_abs(i_config->mcSyncAddr, data);
- if (rc)
- {
- PK_TRACE("centaur_scom_sync: set sync putscom failed. rc = %d",rc);
- break;
- }
- } while (0);
-
- 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;
- int rc = 0;
- mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM);
-
- for(i = 0; i < i_parms->entries; ++i)
- {
- switch(i_parms->scomList[i].commandType)
- {
- case CENTAUR_SCOM_NOP:
- break;
-
- case CENTAUR_SCOM_READ:
- rc =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:
- rc = 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:
- rc = 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:
- rc = centaur_get_scom_vector(i_config,
- i_parms->scomList[i].scom,
- i_parms->scomList[i].pData
- );
- break;
-
- case CENTAUR_SCOM_WRITE_ALL:
- rc = centaur_put_scom_all(i_config,
- i_parms->scomList[i].scom,
- i_parms->scomList[i].data);
- break;
-
- case CENTAUR_SCOM_RMW_ALL:
- rc = 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:
- rc = centaur_scom_sync(i_config);
- break;
-
- default:
- break;
- };
- i_parms->error.rc = rc;
- if (rc)
- {
- break;
- }
- }
-}
diff --git a/src/occ_gpe1/gpe_membuf.c b/src/occ_gpe1/gpe_membuf.c
new file mode 100644
index 0000000..c5f9dd4
--- /dev/null
+++ b/src/occ_gpe1/gpe_membuf.c
@@ -0,0 +1,147 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe1/gpe_membuf.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "gpe_membuf.h"
+#include "ipc_async_cmd.h"
+#include "gpe_util.h"
+
+MemBufConfiguration_t * G_membuf_config = NULL;
+
+void gpe_membuf_init(ipc_msg_t* i_cmd, void* i_arg)
+{
+ int rc;
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd;
+ MemBufConfigParms_t* payload = (MemBufConfigParms_t*)async_cmd->cmd_data;
+
+ MemBufConfiguration_t * config = payload->membufConfiguration;
+ G_membuf_config = config;
+
+ payload->error.error = 0;
+ payload->error.ffdc = 0;
+
+ if(G_membuf_config == NULL)
+ {
+ PK_TRACE("gpe_membuf_init: membufConfiguration data ptr is NULL!");
+ rc = GPE_RC_CONFIG_DATA_NULL_PTR;
+ }
+ else
+ {
+ if(payload->mem_type == MEMTYPE_CENTAUR)
+ {
+ PK_TRACE("Centaur_configuration. MSR:%08x",mfmsr());
+ rc = gpe_centaur_configuration_create(G_membuf_config);
+ }
+ else if(payload->mem_type == MEMTYPE_OCMB)
+ {
+ PK_TRACE("Ocmb_configuration. MSR:%08x",mfmsr());
+ rc = gpe_ocmb_configuration_create(G_membuf_config);
+ }
+ else
+ {
+ rc = GPE_RC_INVALID_MEMBUF_TYPE;
+ }
+ // Must set membuf_type AFTER config created!
+ G_membuf_config->membuf_type = payload->mem_type;
+ }
+
+ payload->error.rc = rc;
+
+ // Send response
+ rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS);
+ if(rc)
+ {
+ PK_TRACE("gpe_membuf_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_membuf_scom(ipc_msg_t* i_cmd, void* i_arg)
+{
+ static int g_log_once = 0;
+ int rc;
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd;
+ MemBufScomParms_t * scomParms = (MemBufScomParms_t*)async_cmd->cmd_data;
+
+ if(g_log_once == 0)
+ {
+ g_log_once = 1;
+ PK_TRACE("gpe_membuf_scom. MSR:%08x",mfmsr());
+ }
+ gpe_inband_scom(G_membuf_config, scomParms);
+
+ // Send response
+ rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS);
+ if(rc)
+ {
+ PK_TRACE("gpe_membuf_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_membuf_data(ipc_msg_t* i_cmd, void* i_arg)
+{
+ static int g_log_once = 0;
+ int rc;
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)i_cmd;
+
+ MemBufGetMemDataParms_t * dataParms =
+ (MemBufGetMemDataParms_t *)async_cmd->cmd_data;
+
+ if(g_log_once == 0)
+ {
+ g_log_once = 1;
+ PK_TRACE("Centaur Data. MSR:%08x",mfmsr());
+ }
+ if(G_membuf_config->membuf_type == MEMTYPE_CENTAUR)
+ {
+ rc = get_centaur_sensorcache(G_membuf_config, dataParms);
+ }
+ else
+ {
+ rc = get_ocmb_sensorcache(G_membuf_config, dataParms);
+ }
+
+ dataParms->error.rc = rc;
+
+ // Send response
+ rc = ipc_send_rsp(i_cmd, IPC_RC_SUCCESS);
+ if(rc)
+ {
+ PK_TRACE("gpe_membuf_data: 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_membuf.h b/src/occ_gpe1/gpe_membuf.h
new file mode 100644
index 0000000..39a4f53
--- /dev/null
+++ b/src/occ_gpe1/gpe_membuf.h
@@ -0,0 +1,177 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe1/gpe_membuf.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#if !defined(_GPE_MEMBUF_H)
+#define _GPE_MEMBUF_H
+
+#include "ipc_structs.h"
+#include "membuf_structs.h"
+
+
+// Which GPE controls the PBASLAVE
+#define OCI_MASTER_ID_GPE1 1
+
+
+#define INBAND_ACCESS_READ 1
+#define INBAND_ACCESS_WRITE 2
+
+
+// IPC interface
+void gpe_membuf_scom(ipc_msg_t* i_cmd, void* i_arg);
+void gpe_membuf_data(ipc_msg_t* i_cmd, void* i_arg);
+void gpe_membuf_init(ipc_msg_t* i_cmd, void* i_arg);
+
+// HCODE interfaces
+/**
+ * Reset the PBA slave controller
+ * @param[in] pba_parms
+ */
+void pbaslvctl_reset(GpePbaParms* i_pba_parms);
+
+/**
+ * Configure the PBA Slave
+ * @param[in] pba_parms
+ */
+uint64_t pbaslvctl_setup(GpePbaParms* i_pba_parms);
+
+
+/**
+ * Access the MEMBUF mmio over the PBA slave.
+ * @param[in] Memory buffer configuration
+ * @param[in] The membuf ordinal number
+ * @param[in] The OCI mapped address
+ * @param[io] The data to move
+ * @param[in] The operation to perform
+ */
+int inband_access(MemBufConfiguration_t* i_config,
+ uint32_t i_instance,
+ uint32_t i_oci_addr,
+ uint64_t * io_data,
+ int i_read_write);
+
+/**
+ * Populate the MemBufConfiguration object for Centaur
+ * @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(MemBufConfiguration_t * o_config);
+
+/**
+ * Scom all of the membufs 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 membuf.
+ * @return [0 | return code]
+ */
+int membuf_get_scom_vector(MemBufConfiguration_t* i_config,
+ uint32_t i_scom_address,
+ uint64_t* o_data);
+
+/**
+ * Scom one or more membuf modules
+ * @param[in] The MemBufConfiguration object
+ * @param[in/out] The Scom Parms object
+ * @return The return code is part of the MemBufScomParms object
+ */
+void gpe_inband_scom(MemBufConfiguration_t* i_config,
+ MemBufScomParms_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 get_centaur_sensorcache(MemBufConfiguration_t* i_config,
+ MemBufGetMemDataParms_t* i_parms);
+
+/**
+ * Check for channel checkstop
+ * @param[in] The ordinal centaur number
+ * @return [0 | return code]
+ */
+int check_centaur_channel_chkstp(unsigned int i_centaur);
+
+/**
+ * Send SYNC to centaur to effectuate the thottle values
+ * @param[in] the membuf configuration
+ */
+int centaur_throttle_sync(MemBufConfiguration_t* i_config);
+
+/**
+ * Create PBA slave configuration parameters.
+ * @param[in] ptr tor param data area to be filled out.
+ * @param[in] PBA slave to use.
+ * @param[in] write ttype (@see occhw_pba_common.h)
+ * @param[in] write tsize (@see occhw_pba_common.h)
+ * @param[in] read_ttype (@see occhw_pba_common.h)
+ * @return [SUCCESS | return code]
+ */
+int gpe_pba_parms_create(GpePbaParms* parms,
+ int slave,
+ int write_ttype,
+ int write_tsize,
+ int read_ttype);
+
+/**
+ * Configure the PBABAR for inband access
+ * @param[in] Configuration information
+ */
+int configure_pba_bar_for_inband_access(MemBufConfiguration_t * i_config);
+
+
+extern uint32_t g_inband_access_state;
+
+/**
+ * Populate a CentaurConfiguration object for ocmb
+ * @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_ocmb_configuration_create(MemBufConfiguration_t * o_config);
+
+/**
+ * Check for OCMBr sensor errors
+ * @param[in] Configuration information
+ * @param[in] The ordinal membuf number
+ * @return [0 | return code]
+ */
+int check_and_reset_mmio_fir(MemBufConfiguration_t * i_config,unsigned int i_membuf);
+
+/**
+ * Send SYNC to ocmb to effectuate the thottle values
+ * @param[in] the membuf configuration
+ */
+int ocmb_throttle_sync(MemBufConfiguration_t* i_config);
+
+int get_ocmb_sensorcache(MemBufConfiguration_t* i_config,
+ MemBufGetMemDataParms_t* i_parms);
+
+
+#endif
diff --git a/src/occ_gpe1/gpe_membuf_scom.c b/src/occ_gpe1/gpe_membuf_scom.c
new file mode 100644
index 0000000..b27ab3f
--- /dev/null
+++ b/src/occ_gpe1/gpe_membuf_scom.c
@@ -0,0 +1,605 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/lib/pm/membuf_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_membuf.h"
+#include "gpe_pba_cntl.h"
+#include "ppe42_scom.h"
+#include "ppe42.h"
+#include "pba_register_addresses.h"
+#include "ppe42_msr.h"
+
+/**
+ * @file gpe_membuf_scom
+ * @brief scom access from gpe to a membuf
+ */
+
+uint32_t g_inband_access_state = INBAND_ACCESS_INACTIVE;
+
+void swap_u64(uint64_t * data64)
+{
+ uint64_t val = *data64;
+ val = ((val << 8) & 0xff00ff00ff00ff00ULL) | ((val >> 8) & 0x00ff00ff00ff00ffULL);
+ val = ((val <<16) & 0xffff0000ffff0000ULL) | ((val >>16) & 0x0000ffff0000ffffULL);
+ *data64 = (val << 32) | (val >> 32);
+}
+
+int inband_access(MemBufConfiguration_t* i_config,
+ uint32_t i_instance,
+ uint32_t i_oci_addr,
+ uint64_t * io_data,
+ int i_read_write)
+{
+ int rc = 0;
+ uint32_t org_msr = mfmsr();
+ uint32_t msr = org_msr | MSR_SEM; // Mask off SIB from generating mck.
+
+ g_inband_access_state = INBAND_ACCESS_IN_PROGRESS;
+
+ if(i_read_write == INBAND_ACCESS_READ)
+ {
+ mtmsr(msr);
+ sync();
+ PPE_LVD(i_oci_addr, *io_data);
+
+ PK_TRACE("inband read %08x%08x from %08x",
+ (uint32_t)((*io_data)>>32),
+ (uint32_t)((*io_data)),
+ i_oci_addr);
+ if(i_config->membuf_type != MEMTYPE_CENTAUR)
+ {
+ swap_u64(io_data);
+ }
+ }
+ else
+ {
+ if(i_config->membuf_type != MEMTYPE_CENTAUR)
+ {
+ swap_u64(io_data);
+ }
+ // Set PPE to precise mode for stores so that in the case of a machine
+ // check, there is a predictable instruction address to resume on.
+
+ msr &= ~MSR_IPE;
+ mtmsr(msr);
+ sync();
+
+ uint64_t data64 = *io_data; //This makes PPE_STVD generate better code
+ PPE_STVD(i_oci_addr, data64);
+
+ PK_TRACE("inband write %08x%08x to %08x",
+ (uint32_t)((*io_data)>>32),
+ (uint32_t)((*io_data)),
+ i_oci_addr);
+ }
+
+ // Poll SIB error or machine check
+ if((mfmsr() & MSR_SIBRC) ||
+ g_inband_access_state != INBAND_ACCESS_IN_PROGRESS)
+ {
+ // Take membuf out of config
+ PK_TRACE("Removing MemBuf %d from list of configured MemBufs",
+ i_instance);
+
+ i_config->config &= ~(CHIP_CONFIG_MEMBUF(i_instance));
+
+ // This will cause the 405 to remove the membuf sensor(s).
+ rc = MEMBUF_CHANNEL_CHECKSTOP;
+ }
+ g_inband_access_state = INBAND_ACCESS_INACTIVE;
+ mtmsr(org_msr);
+ return rc;
+}
+
+/**
+ * Setup the PBASLVCTLN extended address and calculate the OCI scom address
+ * @param[in] PBA base address
+ * @param[in] The inband scom address
+ * @returns the mapped OCI address to scom the membuf
+ * @Post The extended address field in the PBASLVCNT is set
+ */
+int inband_scom_setup(MemBufConfiguration_t* i_config,
+ uint32_t i_membuf_instance,
+ uint32_t i_scom_address,
+ uint32_t *o_oci_addr)
+{
+ int rc = 0;
+ uint32_t scom_address = i_scom_address;
+ // TODO use PBASLV in P10
+#if defined(__USE_PBASLV__)
+ pba_slvctln_t slvctln;
+#endif
+ uint64_t pb_addr = i_config->baseAddress[i_membuf_instance];
+
+ if(i_config->membuf_type == MEMTYPE_CENTAUR)
+ {
+ // 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
+ 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(__USE_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);
+#else
+ // TODO P9 HW bug work-around - Use PBASLV in P10
+ {
+ // workaround - don't use extraddr - use pbabar.
+ uint64_t barMsk = 0;
+
+ // Mask SIB from generating mck
+ mtmsr(mfmsr() | MSR_SEM);
+
+ // put the PBA in the BAR
+ rc = putscom_abs(PBA_BARN(PBA_BAR_MEMBUF), pb_addr & 0x00fffffffff00000ull);
+ if(rc)
+ {
+ PK_TRACE("inband_scom_setup. putscom fail on PBABAR."
+ " rc = %d",rc);
+ }
+ else
+ {
+ rc = putscom_abs(PBA_BARMSKN(PBA_BAR_MEMBUF), barMsk);
+ if(rc)
+ {
+ PK_TRACE("inband_scom_setup. putscom fail on PBABARMSK"
+ " rc = %d",rc);
+ }
+ }
+ }
+#endif
+ // make oci address
+ *o_oci_addr = (uint32_t)(pb_addr & 0x07ffffffull);
+
+ // upper nibble is PBA region and BAR_SELECT
+ *o_oci_addr |= ((PBA_BAR_MEMBUF | 0x8) << 28);
+ PK_TRACE_DBG("OCI mapped scom addr: %08x",*o_oci_addr);
+ return rc;
+}
+
+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 data from each existing membuf.
+int membuf_get_scom_vector(MemBufConfiguration_t* i_config,
+ uint32_t i_scom_address,
+ uint64_t* o_data)
+{
+ int rc = 0;
+ int access_rc = 0;
+ int pba_rc = 0;
+ 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_N_MEMBUF; ++instance)
+ {
+ if( CHIP_CONFIG_MEMBUF(instance) & (i_config->config))
+ {
+ uint32_t oci_addr;
+ pba_rc = inband_scom_setup(i_config,
+ instance,
+ i_scom_address,
+ &oci_addr);
+
+ if(pba_rc)
+ {
+ rc = pba_rc;
+ // Already traced.
+ // Trumps any access error
+ *o_data = 0;
+ }
+ else
+ {
+ // inband scom read
+ access_rc = inband_access(i_config,
+ instance,
+ oci_addr,
+ o_data,
+ INBAND_ACCESS_READ);
+ // only set access_rc if rc not already set.
+ if(!rc && access_rc)
+ {
+ // not critical, but don't access this membuf again.
+ rc = access_rc;
+ *o_data = 0;
+ // continue with next instance
+ }
+ }
+ }
+ 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;
+}
+
+int membuf_get_scom(MemBufConfiguration_t* i_config,
+ int i_membuf_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));
+
+ rc = inband_scom_setup(i_config,
+ i_membuf_instance,
+ i_scom_address,
+ &oci_addr);
+
+ if( !rc && (CHIP_CONFIG_MEMBUF(i_membuf_instance) & (i_config->config)))
+ {
+ // read membuf scom
+ rc = inband_access(i_config,
+ i_membuf_instance,
+ oci_addr,
+ o_data,
+ INBAND_ACCESS_READ);
+ }
+ 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 membuf with the same data
+int membuf_put_scom_all(MemBufConfiguration_t* i_config,
+ uint32_t i_scom_address,
+ uint64_t i_data)
+{
+ int rc = 0;
+ int pba_rc = 0;
+ int access_rc = 0;
+ int instance = 0;
+ uint64_t pba_slvctln_save;
+
+ pbaslvctl_reset(&(i_config->scomParms));
+ pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms));
+
+ for(instance = 0; instance < OCCHW_N_MEMBUF; ++instance)
+ {
+ if( CHIP_CONFIG_MEMBUF(instance) & (i_config->config))
+ {
+ uint32_t oci_addr;
+ pba_rc = inband_scom_setup(i_config,
+ instance,
+ i_scom_address,
+ &oci_addr);
+
+ if(pba_rc)
+ {
+ // Already traced in inband_scom_setup
+ // Trumps access_rc
+ rc = pba_rc;
+ }
+ else
+ {
+ // membuf scom
+ access_rc = inband_access(i_config,
+ instance,
+ oci_addr,
+ &i_data,
+ INBAND_ACCESS_WRITE);
+ // Only set access_rc if rc not already set
+ if(!rc && access_rc)
+ {
+ // This MemBuf won't be touched again.
+ rc = access_rc;
+ // continue with next instance
+ }
+ }
+ }
+ }
+
+ // reset pba slave
+ pbaslvctl_reset(&(i_config->scomParms));
+ PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save);
+
+ return rc;
+}
+
+int membuf_put_scom(MemBufConfiguration_t* i_config,
+ int i_membuf_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));
+
+ rc = inband_scom_setup(i_config,
+ i_membuf_instance,
+ i_scom_address,
+ &oci_addr);
+
+ if(!rc)
+ {
+ if(CHIP_CONFIG_MEMBUF(i_membuf_instance) & (i_config->config))
+ {
+ // write membuf scom
+ rc = inband_access(i_config,
+ i_membuf_instance,
+ oci_addr,
+ &i_data,
+ INBAND_ACCESS_WRITE);
+ }
+ }
+
+ // reset pba slave
+ pbaslvctl_reset(&(i_config->scomParms));
+ PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save);
+
+ return rc;
+}
+
+// write x
+int membuf_scom_rmw(MemBufConfiguration_t* i_config,
+ int i_membuf_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));
+
+ rc = inband_scom_setup(i_config,
+ i_membuf_instance,
+ i_scom_address,
+ &oci_addr);
+ if(!rc)
+ {
+
+ rc = inband_access(i_config,
+ i_membuf_instance,
+ oci_addr,
+ &data64,
+ INBAND_ACCESS_READ);
+
+ if(!rc)
+ {
+ data64 &= (i_mask ^ 0xffffffffffffffffull);
+ data64 |= *i_data;
+
+ rc = inband_access(i_config,
+ i_membuf_instance,
+ oci_addr,
+ &data64,
+ INBAND_ACCESS_WRITE);
+ }
+ }
+
+ pbaslvctl_reset(&(i_config->scomParms));
+ PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save);
+
+ return rc;
+}
+
+
+int membuf_scom_rmw_all(MemBufConfiguration_t* i_config,
+ uint32_t i_scom_address,
+ uint64_t i_mask,
+ uint64_t i_data)
+{
+ int rc = 0;
+ int pba_rc = 0;
+ int access_rc = 0;
+ int instance = 0;
+ uint64_t pba_slvctln_save;
+
+ pbaslvctl_reset(&(i_config->scomParms));
+ pba_slvctln_save = pbaslvctl_setup(&(i_config->scomParms));
+
+ for(instance = 0; (instance < OCCHW_N_MEMBUF); ++instance)
+ {
+ if( CHIP_CONFIG_MEMBUF(instance) & (i_config->config))
+ {
+ uint64_t data64;
+ uint32_t oci_addr;
+ pba_rc = inband_scom_setup(i_config,
+ instance,
+ i_scom_address,
+ &oci_addr);
+ if(pba_rc)
+ {
+ rc = pba_rc;
+ // Already traced in inband_scom_setup
+ // Trumps any access_rc
+ }
+ if(!pba_rc)
+ {
+
+ access_rc = inband_access(i_config,
+ instance,
+ oci_addr,
+ &data64,
+ INBAND_ACCESS_READ);
+
+ if(!access_rc)
+ {
+ data64 &= (i_mask ^ 0xffffffffffffffffull);
+ data64 |= i_data;
+
+ access_rc = inband_access(i_config,
+ instance,
+ oci_addr,
+ &data64,
+ INBAND_ACCESS_WRITE);
+ }
+ }
+ if(!rc && access_rc)
+ {
+ rc = access_rc;
+ }
+
+ pbaslvctl_reset(&(i_config->scomParms));
+ }
+ }
+
+ PPE_STVD((i_config->scomParms).slvctl_address, pba_slvctln_save);
+
+ return rc;
+}
+
+
+
+// MemBufConfiguration needs to be setup before this is called
+void gpe_inband_scom(MemBufConfiguration_t* i_config,
+ MemBufScomParms_t* i_parms)
+{
+ int i;
+ int rc = 0;
+ mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM);
+
+ for(i = 0; i < i_parms->entries; ++i)
+ {
+ switch(i_parms->scomList[i].commandType)
+ {
+ case MEMBUF_SCOM_NOP:
+ break;
+
+ case MEMBUF_SCOM_READ:
+ rc =membuf_get_scom(i_config,
+ i_parms->scomList[i].instanceNumber,
+ i_parms->scomList[i].scom,
+ &(i_parms->scomList[i].data));
+ break;
+
+ case MEMBUF_SCOM_WRITE:
+ rc = membuf_put_scom(i_config,
+ i_parms->scomList[i].instanceNumber,
+ i_parms->scomList[i].scom,
+ i_parms->scomList[i].data);
+ break;
+
+ case MEMBUF_SCOM_RMW:
+ rc = membuf_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 MEMBUF_SCOM_READ_VECTOR:
+ rc = membuf_get_scom_vector(i_config,
+ i_parms->scomList[i].scom,
+ i_parms->scomList[i].pData
+ );
+ break;
+
+ case MEMBUF_SCOM_WRITE_ALL:
+ rc = membuf_put_scom_all(i_config,
+ i_parms->scomList[i].scom,
+ i_parms->scomList[i].data);
+ break;
+
+ case MEMBUF_SCOM_RMW_ALL:
+ rc = membuf_scom_rmw_all(i_config,
+ i_parms->scomList[i].scom,
+ i_parms->scomList[i].mask,
+ i_parms->scomList[i].data);
+ break;
+
+ case MEMBUF_SCOM_MEMBUF_SYNC:
+ if( i_config->membuf_type == MEMTYPE_CENTAUR)
+ {
+ rc = centaur_throttle_sync(i_config);
+ }
+ else
+ {
+ rc = ocmb_throttle_sync(i_config);
+ }
+ break;
+
+ default:
+ break;
+ };
+ if (rc)
+ {
+ break;
+ }
+ }
+ i_parms->error.rc = rc;
+}
diff --git a/src/occ_gpe1/gpe_ocmb.c b/src/occ_gpe1/gpe_ocmb.c
new file mode 100644
index 0000000..dfe7d89
--- /dev/null
+++ b/src/occ_gpe1/gpe_ocmb.c
@@ -0,0 +1,630 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe1/gpe_ocmb.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "gpe_membuf.h"
+#include "ppe42_scom.h"
+#include "pk.h"
+#include "ppe42_msr.h"
+#include "occhw_pba_common.h"
+#include "p9a_misc_scom_addresses.h"
+#include "p9a_firmware_registers.h"
+#include "ocmb_register_addresses.h"
+#include "ocmb_firmware_registers.h"
+#include "ocmb_mem_data.h"
+
+const uint32_t AXONE_MCFGPR[OCCHW_N_MEMBUF] =
+{
+ P9A_MI_0_MCFGPR0,
+ P9A_MI_0_MCFGPR1,
+ P9A_MI_1_MCFGPR0,
+ P9A_MI_1_MCFGPR1,
+ P9A_MI_2_MCFGPR0,
+ P9A_MI_2_MCFGPR1,
+ P9A_MI_3_MCFGPR0,
+ P9A_MI_3_MCFGPR1
+};
+
+const uint32_t AXONE_MCSYNC[OCCHW_N_MEMBUF/2] =
+{
+ P9A_MI_0_MCSYNC,
+ P9A_MI_1_MCSYNC,
+ P9A_MI_2_MCSYNC,
+ P9A_MI_3_MCSYNC
+};
+
+// This table was taken from ekb p9a_omi_setup_bars.C
+const int NUM_EXT_MASKS = 20;
+const uint8_t EXT_MASK_REORDER[][9] = // Workbook table 7
+{
+ // B 6 7 8 9 10 11 12 13
+ { 0x00, 15, 18, 16, 17, 21, 20, 19, 14 },
+ { 0x04, 15, 18, 16, 17, 21, 20, 14, 19 },
+ { 0x06, 15, 18, 16, 17, 21, 14, 20, 19 },
+ { 0x07, 15, 18, 16, 17, 14, 21, 20, 19 },
+ { 0x80, 15, 18, 16, 17, 21, 20, 19, 14 },
+ { 0x84, 15, 18, 16, 17, 21, 20, 14, 19 },
+ { 0x86, 15, 18, 16, 17, 21, 14, 20, 19 },
+ { 0x87, 15, 18, 16, 17, 14, 21, 20, 19 },
+ { 0xC0, 15, 21, 17, 18, 20, 19, 14, 16 },
+ { 0xC4, 15, 21, 17, 18, 20, 14, 19, 16 },
+ { 0xC6, 15, 21, 17, 18, 14, 20, 19, 16 },
+ { 0xC7, 15, 14, 17, 18, 21, 20, 19, 16 },
+ { 0xE0, 15, 20, 18, 21, 19, 14, 17, 16 },
+ { 0xE4, 15, 20, 18, 21, 14, 19, 17, 16 },
+ { 0xE6, 15, 14, 18, 21, 20, 19, 17, 16 },
+ { 0xE7, 15, 21, 18, 14, 20, 19, 17, 16 },
+ { 0xF0, 15, 19, 21, 20, 14, 18, 17, 16 },
+ { 0xF4, 15, 14, 21, 20, 19, 18, 17, 16 },
+ { 0xF6, 15, 20, 21, 14, 19, 18, 17, 16 },
+ { 0xF7, 15, 20, 14, 21, 19, 18, 17, 16 }
+};
+
+int inband_scom_setup(MemBufConfiguration_t* i_config,
+ uint32_t i_membuf_instance,
+ uint32_t i_scom_address,
+ uint32_t *o_oci_addr);
+
+int membuf_get_scom(MemBufConfiguration_t* i_config,
+ int i_membuf_instance,
+ uint32_t i_scom_address,
+ uint64_t* o_data);
+
+int membuf_put_scom(MemBufConfiguration_t* i_config,
+ int i_membuf_instance,
+ uint32_t i_scom_address,
+ uint64_t i_data);
+
+void swap_u32(uint32_t * data32)
+{
+ uint32_t val = *data32;
+ val = ((val << 8) & 0xff00ff00) | ((val >> 8) & 0x00ff00ff);
+ *data32 = (val << 16) | (val >> 16);
+}
+
+
+int ocmb_check_sensor_cache_enabled(MemBufConfiguration_t * i_config,
+ int i_instance)
+{
+ int rc = 0;
+ mmio_merrctl_t merrctl;
+
+ rc = membuf_get_scom(i_config,
+ i_instance,
+ MMIO_MERRCTL,
+ &(merrctl.value));
+ if(rc)
+ {
+ PK_TRACE("OCMB MERRCTL getscom failed. rc = %d",
+ (uint16_t)rc);
+ }
+ else
+ {
+ //PK_TRACE("1MERRCTL: %08x%08x",
+ // merrctl.words.high_order,
+ // merrctl.words.low_order);
+ if(merrctl.fields.snsc_master_enable == SNSC_MASTER_DISABLED)
+ {
+ // attempted to enable it
+ merrctl.fields.snsc_master_enable = SNSC_MASTER_ENABLED;
+ rc = membuf_put_scom(i_config,
+ i_instance,
+ MMIO_MERRCTL,
+ merrctl.value);
+ if(rc)
+ {
+ PK_TRACE("OCMB MERRCTL putscom failed. rc = %d",
+ (uint16_t)rc);
+ }
+ //PK_TRACE("2MERRCTL: %08x%08x",
+ // merrctl.words.high_order,
+ // merrctl.words.low_order);
+ }
+
+ }
+ return rc;
+}
+
+int gpe_ocmb_configuration_create(MemBufConfiguration_t* o_config)
+{
+ int rc = 0;
+ int i = 0;
+ int l_rule = 0;
+ int l_ext_addr_mask = 0;
+ int designated_sync = -1;
+ mcfgpr_t mcfgpr;
+ pb_mode_t pb_mode;
+ uint64_t* ptr = (uint64_t*)o_config;
+
+ // Prevent unwanted interrupts from scom errors
+ // Enable store Gathering, and Icache prefetch for performance.
+ const uint32_t orig_msr = mfmsr();
+ mtmsr((orig_msr & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM | MSR_IS1 | MSR_IS2 );
+ sync();
+
+ for(i = 0; i < sizeof(MemBufConfiguration_t) / 8; ++i)
+ {
+ *ptr++ = 0ull;
+ }
+
+ o_config->configRc = MEMBUF_NOT_CONFIGURED;
+ o_config->membuf_type = MEMTYPE_OCMB;
+
+ do
+ {
+ // Create the PBASLV configuration for collecting sensor data.
+ rc = gpe_pba_parms_create(&(o_config->dataParms),
+ PBA_SLAVE_MEMBUF,
+ PBA_WRITE_TTYPE_CI_PR_W,
+ PBA_WRITE_TTYPE_DC,
+ PBA_READ_TTYPE_CI_PR_RD);
+
+ if (rc)
+ {
+ rc = MEMBUF_DATA_SETUP_ERROR;
+ break;
+ }
+
+ // create the PBASLV configuration for doing inband scoms.
+ rc = gpe_pba_parms_create(&(o_config->scomParms),
+ PBA_SLAVE_MEMBUF,
+ PBA_WRITE_TTYPE_CI_PR_W,
+ PBA_WRITE_TTYPE_DC,
+ PBA_READ_TTYPE_CI_PR_RD);
+ if (rc)
+ {
+ rc = MEMBUF_SCOM_SETUP_ERROR;
+ break;
+ }
+
+ // On Ocmb the mmio bar value has been swizzled
+ // Need to un-swizzle
+ rc = getscom_abs(P9A_PU_NMMU_MMCQ_PB_MODE_REG, &(pb_mode.value));
+ if( rc )
+ {
+ PK_TRACE("Scom failed on PB_MODE_REG. rc = %d",
+ rc);
+ rc = MEMBUF_PBMODE_GETSCOM_FAILURE;
+ break;
+ }
+
+ l_ext_addr_mask = pb_mode.fields.addr_extension_group_id << 4;
+ l_ext_addr_mask |= pb_mode.fields.addr_extension_chip_id;
+
+ // bits [6:13] in mmio bar have been rearranged - look up translation
+ // rule.
+ for(l_rule = 0; l_rule < NUM_EXT_MASKS; ++l_rule)
+ {
+ if(EXT_MASK_REORDER[l_rule][0] == l_ext_addr_mask) // found
+ {
+ break;
+ }
+ }
+
+ if(l_rule == NUM_EXT_MASKS) // rule not found.
+ {
+ PK_TRACE("Failed to find match for %x in EXT_MASK_REORDER",
+ l_ext_addr_mask);
+ rc = MEMBUF_PMODE_DATA_MISMATCH;
+ break;
+ }
+
+ // Find all configured MEMBUFs
+ for (i = 0; i < OCCHW_N_MEMBUF; ++i)
+ {
+ uint64_t l_pba_addr = 0;
+ uint32_t l_mmio_bar = 0;
+
+ rc = getscom_abs(AXONE_MCFGPR[i], &(mcfgpr.value));
+
+ if( rc )
+ {
+ rc = 0; // Can't be scommed then ignore this MEMBUF
+ continue;
+ }
+
+ if(!mcfgpr.fields.mmio_valid)
+ {
+ continue; // MEMBUF MMIOBAR not configured, ignore MEMBUF
+ }
+
+ l_mmio_bar =
+ (uint32_t)(mcfgpr.fields.mmio_group_base_addr) << 1;
+ PK_TRACE("Ocmb[%d] MMIO Bar: %08x", i, l_mmio_bar);
+
+ // The mmio bar has been swizzled, It needs to be unswizzled.
+ // Make this easy for PPE 32 bit arch.
+
+ uint32_t l_mask = 0x02000000; //Start bit 6
+ uint32_t l_reordered = 0;
+ int l_col;
+
+ for(l_col = 1; l_col < 9; ++l_col)
+ {
+ if((l_mask & l_mmio_bar) != 0)
+ {
+ uint32_t l_setbit = 0x80000000 >>
+ EXT_MASK_REORDER[l_rule][l_col];
+ l_reordered |= l_setbit;
+ }
+
+ l_mask >>= 1;
+ }
+ l_mmio_bar &= 0xfc03ffff; //mask off bits 6-13
+ l_mmio_bar |= (l_reordered << 8);
+
+ l_pba_addr = (uint64_t)(l_mmio_bar) << 32;
+
+ // The 31-bit base-address (inband scom BAR) corresponds
+ // to bits [8:38] of the Power Bus addresss
+ l_pba_addr >>= 8;
+
+ if((i % 2) != 0)
+ {
+ l_pba_addr |= OCMB_IB_BAR_B_BIT;
+ }
+
+ PK_TRACE("MMIO Base Address: 0x%08x%08x on ocmb %d",
+ (uint32_t)(l_pba_addr >> 32),
+ (uint32_t)(l_pba_addr),
+ i);
+
+ o_config->baseAddress[i] = l_pba_addr;
+ // Add this membuf to the configuration
+ o_config->config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_MEMBUF(i));
+ }
+
+ if( rc )
+ {
+ break;
+ }
+
+ // Find the designated sync.
+ // Find the register that HWPs used to sync the throttle n/m values
+ // accross all membufs. Only one register should be setup.
+ for (i = 0; i < (OCCHW_N_MEMBUF/2); ++i)
+ {
+ uint64_t mcsync;
+ rc = getscom_abs(AXONE_MCSYNC[i], &mcsync);
+ if (rc)
+ {
+ PK_TRACE("getscom failed on MCSYNC, rc = %d. The first configured "
+ "MC will be the designated sync",rc);
+ rc = 0;
+ }
+ if (mcsync != 0)
+ {
+ designated_sync = i;
+ // There can only be one sync, so stop searching.
+ break;
+ }
+ }
+
+ if (designated_sync < 0)
+ {
+ // Leave mcSyncAddr zero.
+ PK_TRACE("No designated sync found. Ocmb sync disabled.");
+ }
+ else
+ {
+ o_config->mcSyncAddr = AXONE_MCSYNC[designated_sync];
+ }
+
+ if(o_config->config != 0)
+ {
+ rc = configure_pba_bar_for_inband_access(o_config);
+
+ if( rc )
+ {
+ break;
+ }
+ }
+
+ if(!rc)
+ {
+ for(i = 0; i < OCCHW_N_MEMBUF; ++i)
+ {
+ if( CHIP_CONFIG_MEMBUF(i) & (o_config->config))
+ {
+ // Attempt to reset any SCACHE FIR errors
+ // and insure the SCACHE is enabled
+ check_and_reset_mmio_fir(o_config, i);
+ ocmb_check_sensor_cache_enabled(o_config,i);
+ }
+ }
+
+ // Find out which DTS are present
+ OcmbMemData escache;
+ MemBufGetMemDataParms_t l_parms;
+
+ l_parms.update = -1;
+ l_parms.data = (uint64_t *)(&escache);
+
+ for(i = 0; i < OCCHW_N_MEMBUF; ++i)
+ {
+ if( CHIP_CONFIG_MEMBUF(i) & (o_config->config))
+ {
+ l_parms.collect = i;
+ rc = get_ocmb_sensorcache(o_config, &l_parms);
+ if( rc )
+ {
+ PK_TRACE("gpe_ocmb_configuration_create failed to"
+ " get sensorcache for MEMBUF %d, rc = %d.",
+ i, rc);
+ continue; // Thermal sensors not available.
+ }
+
+ if(escache.status.fields.ubdts0_present)
+ {
+ o_config->dts_config |= CONFIG_UBDTS0(i);
+ }
+ if(escache.status.fields.memdts0_present)
+ {
+ o_config->dts_config |= CONFIG_MEMDTS0(i);
+ }
+ if(escache.status.fields.memdts1_present)
+ {
+ o_config->dts_config |= CONFIG_MEMDTS1(i);
+ }
+ PK_TRACE("Ocmb dts_config: %08x",o_config->dts_config);
+ }
+ }
+ }
+
+ }
+ while( 0 );
+
+ o_config->configRc = rc;
+
+ mtmsr(orig_msr);
+
+ return rc;
+}
+
+int check_and_reset_mmio_fir(MemBufConfiguration_t* i_config, unsigned int i_membuf)
+{
+ int rc = 0;
+ mmio_mfir_t mfir;
+
+ rc = membuf_get_scom(i_config, i_membuf, MMIO_MFIR, &(mfir.value));
+ if(rc)
+ {
+ PK_TRACE("check_and_reset_mmio_fir mmio scom fail. rc = %d",rc);
+ }
+ else
+ {
+
+ // Check for bits 7,8,9,10
+ if(mfir.fields.snsc_both_starts_err ||
+ mfir.fields.snsc_mult_seq_perr ||
+ mfir.fields.snsc_fsm_perr ||
+ mfir.fields.snsc_reg_perr)
+ {
+ PK_TRACE("ocmb mmio fir: 0x%08x%08x",
+ mfir.words.high_order,
+ mfir.words.low_order);
+
+ rc = MEMBUF_SCACHE_ERROR;
+
+ mfir.value = 0xffffffffffffffffull;
+ mfir.fields.snsc_both_starts_err = 0;
+ mfir.fields.snsc_mult_seq_perr = 0;
+ mfir.fields.snsc_fsm_perr = 0;
+ mfir.fields.snsc_reg_perr = 0;
+ membuf_put_scom(i_config, i_membuf, MMIO_MFIR_AND, mfir.value);
+ }
+ }
+
+ return rc;
+}
+
+int ocmb_throttle_sync(MemBufConfiguration_t* i_config)
+{
+ // see
+ // https://farm3802.rtp.stglabs.ibm.com/regdb/entire_table.php?db=FIGDB_cb1_25_36_DB&name=MB_SIM.SRQ.MBA_FARB3Q
+ // SYNC only needed if OCMB_MBA_FARB3Q bit cfg_nm_change_after_sync is set.
+ // HWP programs this.
+ // Ocmb may not need to sync as it only has one FARB3Q reg to write.
+ uint64_t data;
+ int rc = 0;
+ do
+ {
+ // No designated sync addr, therefore Sync not needed.
+ if(i_config->mcSyncAddr == 0)
+ {
+ break;
+ }
+
+ rc = getscom_abs(i_config->mcSyncAddr,&data);
+ if (rc)
+ {
+ PK_TRACE("ocmb_throttle_sync: getscom failed. rc = %d",rc);
+ break;
+ }
+
+ data &= ~MCS_MCSYNC_SYNC_GO;
+
+ rc = putscom_abs(i_config->mcSyncAddr, data);
+ if (rc)
+ {
+ PK_TRACE("ocmb_throttle_sync: reset sync putscom failed. rc = %d",rc);
+ break;
+ }
+
+ data |= MCS_MCSYNC_SYNC_GO;
+
+ rc = putscom_abs(i_config->mcSyncAddr, data);
+ if (rc)
+ {
+ PK_TRACE("ocmb_throttle_sync: set sync putscom failed. rc = %d",rc);
+ break;
+ }
+ } while (0);
+
+ return rc;
+}
+
+void extract_32b(uint32_t oci_addr, uint64_t * i_dest_addr)
+{
+ typedef union
+ {
+ uint64_t v;
+ struct
+ {
+ uint32_t h;
+ uint32_t l;
+ } w;
+ } data64_t;
+
+ data64_t data64;
+ uint32_t * dest_addr = (uint32_t *)i_dest_addr;
+ PkMachineContext ctx;
+
+ pk_critical_section_enter(&ctx);
+ // Invalidate the cache block at oci_addr
+ asm volatile ("dcbi 0, %0" : : "r" (oci_addr) : "memory");
+
+ // The first load causes the PBA bridge to fetch the 32 byte sensor cache
+ // and place it in the PPE42 data cache. The PPE42 cache must not be
+ // invalidated by any other load(s) until all 32 bytes have been read.
+ // Note: A store does a store-through and won't invalidate the data cache.
+
+ asm volatile ("lvd %[d], 0(%[a])\n" : [d]"=r"(data64.v) : [a]"b"(oci_addr));
+ dest_addr[7] = data64.w.h;
+ dest_addr[6] = data64.w.l;
+
+ asm volatile ("lvd %[d], 8(%[a])\n" : [d]"=r"(data64.v) : [a]"b"(oci_addr));
+ dest_addr[5] = data64.w.h;
+ dest_addr[4] = data64.w.l;
+
+ asm volatile ("lvd %[d], 16(%[a])\n" : [d]"=r"(data64.v) : [a]"b"(oci_addr));
+ dest_addr[3] = data64.w.h;
+ dest_addr[2] = data64.w.l;
+
+ asm volatile ("lvd %[d], 24(%[a])\n" : [d]"=r"(data64.v) : [a]"b"(oci_addr));
+ dest_addr[1] = data64.w.h;
+ dest_addr[0] = data64.w.l;
+ sync();
+ pk_critical_section_exit(&ctx);
+}
+
+int get_ocmb_sensorcache(MemBufConfiguration_t* i_config,
+ MemBufGetMemDataParms_t* i_parms)
+{
+ int rc = 0;
+ uint64_t pba_slvctln_save;
+
+ i_parms->error.rc = MEMBUF_GET_MEM_DATA_DIED;
+
+ pbaslvctl_reset(&(i_config->dataParms));
+ pba_slvctln_save = pbaslvctl_setup(&(i_config->dataParms));
+
+ // Clear SIB error accumulator bits & mask SIB errors from
+ // generating machine checks
+ mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM);
+
+ //collect has the ordinal # of the membuf from which to collect the
+ //sensor cache.
+ if(i_parms->collect != -1)
+ {
+ if((i_parms->collect >= OCCHW_N_MEMBUF) ||
+ (0 == (CHIP_CONFIG_MEMBUF(i_parms->collect) & (i_config->config))))
+ {
+ rc = MEMBUF_GET_MEM_DATA_COLLECT_INVALID;
+ }
+ else
+ {
+ uint32_t oci_addr = 0;
+
+ int rc1 = check_and_reset_mmio_fir(i_config, i_parms->collect);
+ int rc2 = ocmb_check_sensor_cache_enabled(i_config,
+ i_parms->collect);
+
+ if(rc2)
+ {
+ rc = rc2; // mmio scom fail
+ }
+ else if (rc1)
+ {
+ rc = rc1; //mmio scom fail or MEMBUF_SCACHE_ERROR;
+ }
+ else
+ {
+
+ // NOTE: inband_scom_setup can be used to map the oci_addr so
+ // long as i_config->dataParms and i_config->scomParms are the,
+ // same, which for ocmb is currently true.
+ rc = inband_scom_setup(i_config,
+ i_parms->collect,
+ OCMB_IB_SENSOR_CACHE_ADDR,
+ &oci_addr);
+
+ if(!rc)
+ {
+ uint32_t org_msr = mfmsr();
+ // Mask off SIB errors from gen mck and set data cache enable,
+ // Enable Store Gathering, and Icache prefetch
+ mtmsr(org_msr | MSR_SEM | MSR_IS0 | MSR_IS1 | MSR_IS2);
+ sync();
+ g_inband_access_state = INBAND_ACCESS_IN_PROGRESS;
+
+ extract_32b(oci_addr,(i_parms->data)); //packet0
+ extract_32b(oci_addr + 32, (i_parms->data) + 4); //packet1
+
+ // Poll for SIB errors or machine check
+ if((mfmsr() & MSR_SIBRC) ||
+ g_inband_access_state != INBAND_ACCESS_IN_PROGRESS)
+ {
+ // Take membuf out of config list
+ PK_TRACE("Removing Membuf %d from list of configured Membufs",
+ i_parms->collect);
+ i_config->config &= ~(CHIP_CONFIG_MEMBUF(i_parms->collect));
+
+ // This rc will cause the 405 to remove this centaur sensor
+ rc = MEMBUF_CHANNEL_CHECKSTOP;
+ }
+ mtmsr(org_msr);
+ g_inband_access_state = INBAND_ACCESS_INACTIVE;
+
+ // Finish making data big-endian
+ uint32_t * p = (uint32_t *)(i_parms->data);
+ int i;
+ for(i=0; i < 16; ++i)
+ {
+ swap_u32(p);
+ ++p;
+ }
+ }
+ }
+ }
+ }
+ // if(i_parms->update != -1) {} -- not used for Ocmb
+
+ pbaslvctl_reset(&(i_config->dataParms));
+ PPE_STVD((i_config->dataParms).slvctl_address, pba_slvctln_save);
+
+ i_parms->error.rc = rc;
+ return rc;
+}
+
+
diff --git a/src/occ_gpe1/ipc_func_tables.c b/src/occ_gpe1/ipc_func_tables.c
index abc1575..8ee7cd0 100644
--- a/src/occ_gpe1/ipc_func_tables.c
+++ b/src/occ_gpe1/ipc_func_tables.c
@@ -26,7 +26,7 @@
#include "ipc_async_cmd.h"
#include "gpe1_dimm.h"
#include "gpu_structs.h"
-#include "gpe_centaur.h"
+#include "gpe_membuf.h"
void gpe_dimm_control(ipc_msg_t* cmd, void* arg);
void gpe1_nop(ipc_msg_t* cmd, void* arg);
@@ -86,9 +86,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(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(gpe_membuf_scom, 0) // 8 - IPC_ST_MEMBUF_SCOM_FUNCID
+IPC_HANDLER(gpe_membuf_data, 0) // 9 - IPC_ST_MEMBUF_DATA_FUNCID
+IPC_HANDLER(gpe_membuf_init, 0) // 10 -IPC_ST_MEMBUF_INIT_FUNCID
IPC_HANDLER(gpe_scom_nvdimms_nimbus, 0) // 11 -IPC_ST_EPOW_GPIO_ASSERT_FUNCID
IPC_HANDLER_DEFAULT // 12
IPC_HANDLER_DEFAULT // 13
diff --git a/src/occ_gpe1/link.cmd b/src/occ_gpe1/link.cmd
index ae41e28..67de73f 100644
--- a/src/occ_gpe1/link.cmd
+++ b/src/occ_gpe1/link.cmd
@@ -27,7 +27,7 @@
#undef powerpc
#ifndef INITIAL_STACK_SIZE
-#define INITIAL_STACK_SIZE 256
+#define INITIAL_STACK_SIZE 512
#endif
OUTPUT_FORMAT(elf32-powerpc);
diff --git a/src/occ_gpe1/occ_gpe1_machine_check_handler.c b/src/occ_gpe1/occ_gpe1_machine_check_handler.c
index 33424c6..53780f7 100644
--- a/src/occ_gpe1/occ_gpe1_machine_check_handler.c
+++ b/src/occ_gpe1/occ_gpe1_machine_check_handler.c
@@ -1,5 +1,29 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe1/occ_gpe1_machine_check_handler.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
#include "pk_panic_codes.h"
-#include "gpe_centaur.h"
+#include "gpe_membuf.h"
#include "pk.h"
#define OCI_ADDR_BAR_MASK 0xf0000000
@@ -8,7 +32,7 @@
extern uint32_t gpe1_machine_check_handler(uint32_t srr0,
uint32_t srr1,
uint32_t edr);
-extern uint32_t g_centaur_access_state;
+extern uint32_t g_inband_access_state;
uint32_t gpe1_machine_check_handler(uint32_t srr0,
uint32_t srr1,
@@ -20,15 +44,15 @@ uint32_t gpe1_machine_check_handler(uint32_t srr0,
edr);
// It's possible to get back-to-back machine checks for the same condition
- // so CENTAUR_CHANNEL_CHECKSTOP may already be set. Also check that the
- // machine check was due to a Centaur Access (PBABAR1)
- if((g_centaur_access_state == CENTAUR_ACCESS_IN_PROGRESS ||
- g_centaur_access_state == CENTAUR_CHANNEL_CHECKSTOP) &&
+ // so MEMBUF_CHANNEL_CHECKSTOP may already be set. Also check that the
+ // machine check was due to a MEMBUF PBA Access (PBABAR1)
+ if((g_inband_access_state == INBAND_ACCESS_IN_PROGRESS ||
+ g_inband_access_state == MEMBUF_CHANNEL_CHECKSTOP) &&
((edr & OCI_ADDR_BAR_MASK) == OCI_ADDR_BAR1))
{
// Returning this to OCC405 will cause sensor to be removed from
// active list
- g_centaur_access_state = CENTAUR_CHANNEL_CHECKSTOP;
+ g_inband_access_state = MEMBUF_CHANNEL_CHECKSTOP;
// The instruction that caused the machine check should
// be a double word load or store.
diff --git a/src/occ_gpe1/topfiles.mk b/src/occ_gpe1/topfiles.mk
index 53d35b5..5a0095f 100644
--- a/src/occ_gpe1/topfiles.mk
+++ b/src/occ_gpe1/topfiles.mk
@@ -26,8 +26,9 @@
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 \
- gpe_centaur_scom.c gpe_centaur_configuration.c \
- gpe_centaur.c occ_gpe1_machine_check_handler.c
+ gpe_membuf_scom.c gpe_centaur.c \
+ gpe_membuf.c occ_gpe1_machine_check_handler.c \
+ gpe_ocmb.c
TOP-S-SOURCES = occ_gpe1_mck_handler.S
OpenPOWER on IntegriCloud