diff options
author | Douglas Gilbert <dgilbert@us.ibm.com> | 2018-08-20 12:00:00 -0500 |
---|---|---|
committer | William A. Bryan <wilbryan@us.ibm.com> | 2019-05-01 14:06:09 -0500 |
commit | afa37a7e9bc0fa22fb2271fb2e7ea2557376181e (patch) | |
tree | 5b39ee8a394474649721a51c1c0d4968e52cac08 | |
parent | a880ffe3a854a8eb219ea92e7fbc4845d8fa2511 (diff) | |
download | talos-occ-afa37a7e9bc0fa22fb2271fb2e7ea2557376181e.tar.gz talos-occ-afa37a7e9bc0fa22fb2271fb2e7ea2557376181e.zip |
Explorer MSBUF monitoring
Change-Id: Ia8e48ba5c3ad7836dbd249f3965768e79083c181
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/73263
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
41 files changed, 4318 insertions, 1843 deletions
diff --git a/src/common/centaur_configuration.h b/src/common/centaur_configuration.h deleted file mode 100644 index 46f9521..0000000 --- a/src/common/centaur_configuration.h +++ /dev/null @@ -1,200 +0,0 @@ -#if !defined(__CENTAUR_CONFIGURATION_H__) -#define __CENTAUR_CONFIGURATION_H__ - -//#include "occhw_common.h" -#include "gpe_pba_parms.h" -#include "centaur_firmware_registers.h" - -#define OCCHW_NCENTAUR 8 - -/// Error return codes set/returned by centaur_configuration_create() - -typedef enum -{ - - CENTAUR_INVALID_ARGUMENT = 0x007ccc01, - CENTAUR_MCSMODE0_SCOM_FAILURE = 0x007ccc02, - CENTAUR_MCSMODE0_19_FAILURE = 0x007ccc03, - CENTAUR_ADDRESS_27_FAILURE = 0x007ccc04, - CENTAUR_MULTIPLE_DESIGNATED_SYNC = 0x007ccc05, - CENTAUR_NO_DESIGNATED_SYNC = 0x007ccc06, - CENTAUR_BAR_MASK_ERROR = 0x007ccc07, - CENTAUR_CONFIGURATION_FAILED = 0x007ccc08, - CENTAUR_DATA_SETUP_ERROR = 0x007ccc09, - CENTAUR_SCOM_SETUP_ERROR = 0x007ccc0a, - CENTAUR_NOT_CONFIGURED = 0x007ccc0b, - CENTAUR_MASK_ERROR = 0x007ccc0c, - CENTAUR_READ_TPC_ID_FAILURE = 0x007ccc0d, - CENTAUR_BARMSKN_PUTSCOM_FAILURE = 0x007ccc0e, - CENTAUR_BARN_PUTSCOM_FAILURE = 0x007ccc0f, - CENTAUR_BARMSKN_GETSCOM_FAILURE = 0x007ccc10, - CENTAUR_BARN_GETSCOM_FAILURE = 0x007ccc11, -} CentaurConfigurationCreateRc; - -/** - * Definition of the CentaurConfiguration data. - * @note location must be 8-byte aligned, size must be multiple of 8 bytes. - */ -typedef struct -{ - - /// Centaur base addresses for in-band operations - /// - uint64_t baseAddress[OCCHW_NCENTAUR]; - - /// Contents of Centaur device id registers - /// - /// These are the device ID SCOMs (0x000f000f) read from configured - /// Centaur during initialization. A 0 value indicates an unconfigured - /// Centaur. These values are deconstructed by the memory buffer (mb) - /// APIs mb_id(), mb_chip_type() and mb_ec_level(). - centaur_device_id_t deviceId[OCCHW_NCENTAUR]; - - /// Designated sync scom address - /// \note One and Only one of the MCS units can be targeted with SYNC - /// commands. The design includes a private bus connecting all MCS on the - /// chip that allows this "SYNC master" to broadcast the SYNC to all other - /// MCS on the chip. - uint32_t mcSyncAddr; - uint32_t reserved; // keep 8 byte aligned - - /// A GpePbaParms parameter block for gpe_mem_data() - /// - /// This parameter block is set up in advance and used by the GPE - /// procedure gpe_mem_data(). Given the complexity of accessing Centaur - /// sensors and SCOM through the PBA it is simpler to set these up ahead - /// of time and simply have the GPE procedures access preconfigured global - /// data. The \a dataParms and \a scomParms members are distinguished by - /// the different way the PBA slave needs to be configured to access - /// either the Centaur sensor cache or Centaur SCOMs. - GpePbaParms dataParms; - - /// A GpePbaParms parameter block for IPC_ST_CENTAUR_SCOM(). - GpePbaParms scomParms; - - /// A "chip configuration" bit mask denoting valid Centaur - /// - /// It shoud always be true that a bit denoting a configured Centaur is - /// associated with a non-0 \a baseAddress and vice-versa. - uint32_t config; - - - /// The final return code from centaur_configuration_create(). - /// @see CentaurConfigurationCreateRc - /// If initialization fails then this value can be used to diagnose what - /// happend. This field should be statically initialized to a non-0 value - /// (CENTAUR_NOT_CONFIGURED) and can then be checked against 0 to - /// determine if the structure has been correctly initialized. - int32_t configRc; - -} CentaurConfiguration_t __attribute__((aligned(8))); - -// Moved CentaurGetMemDataParms_t to centaur_structs.h - -typedef struct -{ - union - { - struct - { - uint32_t scom; - uint8_t reserved; - uint8_t errorFlags; - uint8_t instanceNumber; - uint8_t commandType; - }; - uint64_t command; - }; - uint64_t mask; - union - { - uint64_t data; - struct - { - uint32_t unused; - uint64_t* pData; - }; - }; -} scomList_t; - - -// Centaur Scom Return Codes -enum -{ - // rc 1 - 7 reserved from scom rc - CENTAUR_ACCESS_INACTIVE = 98, - CENTAUR_ACCESS_IN_PROGRESS = 99, - CENTAUR_INVALID_SCOM = 100, - CENTAUR_GET_MEM_DATA_COLLECT_INVALID = 200, - CENTAUR_GET_MEM_DATA_UPDATE_INVALID = 201, - CENTAUR_GET_MEM_DATA_DIED = 202, - CENTAUR_CHANNEL_CHECKSTOP = 203, -}; - -// Centaur Scom Operations -typedef enum -{ - /// No operation - CENTAUR_SCOM_NOP, - - /// Read from SCOM, depositing read data into the \a data field of the - /// scomList_t. - CENTAUR_SCOM_READ, - - /// Write to SCOM, taking write data from the \a data field of the scomList_t. - CENTAUR_SCOM_WRITE, - - /// Read-Modify-Write. - /// - /// This operation first reads the SCOM. Bits under the \a mask field of the - /// scomList_t are then cleared in the read data. The masked read data is then - /// ORed with the contents of the \a data field of the scomList_t and the - /// result is written back to the SCOM address. - /// - /// \note This command \e does \e not apply the mask to the data from the \a - /// data field of the scomList_t. The caller should do this (if necessary) - /// when setting up the scomList_t. - /// - /// \note The procedures do not provide a way to distinguish errors that may - /// have occurred on the initial read vs. those that may have occurred on the - /// subsequenct write. - CENTAUR_SCOM_RMW, - - /// For IPC_ST_CENTAUR_SCOM(), the \a data field of the scomList_t contains a - /// 32-bit pointer (cast to a uint64_t) to an array of PGP_NCENTAUR uint64_t - /// values. SCOM read data for each configured Centaur (MCS) is deposited in - /// this array. Array entries for unconfigured Centaur are zeroed. - CENTAUR_SCOM_READ_VECTOR, - - /// For IPC_ST_CENTAUR_SCOM(), write the \a data field of the scomList_t to - /// all configured Centaur. Currently unsupported for gpe_scom_p8(). - CENTAUR_SCOM_WRITE_ALL, - - /// For IPC_ST_CENTAUR_SCOM(), perform read-modify write for all configured - /// Centaur. Currently unsupported for gpe_scom_p8(). - CENTAUR_SCOM_RMW_ALL, - - // Send Centaur SYNC to broadcast new throttle values. - CENTAUR_SCOM_CENTAUR_SYNC, - -} centaur_scom_operation_t; - -#define MCS_MCSYNC_SYNC_GO 0x0000800000000000ull - -// BAR and PBA_SLAVE assigned to gpe1 centaur -// - @see POWER Energy Management Hcode/HWP spec -#define PBA_BAR_CENTAUR 1 -#define PBA_SLAVE_CENTAUR 2 - -// This is used to setup CentaurConfiguration.config field -#define CHIP_CONFIG_MCS_BASE 16 -#define CHIP_CONFIG_MCS(n) \ - ((0x80000000ul >> CHIP_CONFIG_MCS_BASE) >> (n)) - -#define CHIP_CONFIG_CENTAUR_BASE 24 -#define CHIP_CONFIG_CENTAUR(n) \ - ((0x80000000ul >> CHIP_CONFIG_CENTAUR_BASE) >> (n)) - -#endif - - diff --git a/src/common/centaur_structs.h b/src/common/centaur_structs.h deleted file mode 100644 index c0b7a66..0000000 --- a/src/common/centaur_structs.h +++ /dev/null @@ -1,64 +0,0 @@ -#if !defined(_CENTAUR_STRUCTS_H) -#define _CENTAUR_STRUCTS_H - -#include "stdint.h" -#include "gpe_export.h" -#include "centaur_configuration.h" - -// IPC message payload for call to IPC_ST_CENTAUR_INIT_FUNCID -typedef struct -{ - GpeErrorStruct error; - CentaurConfiguration_t * centaurConfiguration; - -} CentaurConfigParms_t; - -// IPC message payload for call to IPC_ST_CENTAUR_SCOM_FUNCID -typedef struct -{ - GpeErrorStruct error; - - /** - * Input: The SCOM list - * This is a pointer to an array of scomList_t objects - * describing the sequence of commands to execute. - */ - scomList_t* scomList; - - /** - * Input: The number of entries in the scomList. - * @note It is considered an error if \a entries is 0, under the - * assumption that the caller must have neglected to initialize the - * structure. - */ - int entries; - -} CentaurScomParms_t; - -// IPC message payload for call to IPC_ST_CENTAUR_DATA_FUNCID -typedef struct -{ - GpeErrorStruct error; - - /** - * The index (0 .. PGP_NCENTAUR - 1) of the Centaur whose sensor cache - * data to collect, or -1 to bypass collection. - */ - int collect; - - /** - * The index (0 .. PGP_NCENTAUR - 1) of the Centaur to "poke" to cause it - * to begin collecting the next round of data into its sensor cache, or - * -1 to bypass updating - */ - int update; - - /** - * Pointer to data collected. Needs to be set if collect != -1 - * otherwise it's not used. - */ - uint64_t * data; -} CentaurGetMemDataParms_t; - - -#endif diff --git a/src/common/gpe_err.h b/src/common/gpe_err.h index 66e9295..b6cdb45 100644 --- a/src/common/gpe_err.h +++ b/src/common/gpe_err.h @@ -44,6 +44,7 @@ #define GPE_RC_INVALID_MEM_PWR_CTL 0x20 // Invalid value for the memory power control command // Centaur mem ctl codes #define GPE_RC_CONFIG_DATA_NULL_PTR 0x30 // centaurConfiguration data ptr NULL +#define GPE_RC_INVALID_MEMBUF_TYPE 0x31 // membuf type is not valid. // APSS Specific gpe return Codes #define GPE_RC_INVALID_APSS_MODE 0x40 // OCC requested undefined APSS mode diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h index 748a337..8258255 100644 --- a/src/common/ipc_func_ids.h +++ b/src/common/ipc_func_ids.h @@ -75,9 +75,9 @@ IPC_FUNCIDS_TABLE_START IPC_FUNC_ID(IPC_ST_MEM_POWER_CONTROL_FUNCID) IPC_FUNC_ID(IPC_ST_GPU_SM_FUNCID) IPC_FUNC_ID(IPC_ST_GPE_GPU_INIT_FUNCID) - IPC_FUNC_ID(IPC_ST_CENTAUR_SCOM_FUNCID) - IPC_FUNC_ID(IPC_ST_CENTAUR_DATA_FUNCID) - IPC_FUNC_ID(IPC_ST_CENTAUR_INIT_FUNCID) + IPC_FUNC_ID(IPC_ST_MEMBUF_SCOM_FUNCID) + IPC_FUNC_ID(IPC_ST_MEMBUF_DATA_FUNCID) + IPC_FUNC_ID(IPC_ST_MEMBUF_INIT_FUNCID) IPC_FUNC_ID(IPC_ST_EPOW_GPIO_ASSERT_FUNCID) IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE1) diff --git a/src/common/membuf_configuration.h b/src/common/membuf_configuration.h new file mode 100644 index 0000000..576f6b4 --- /dev/null +++ b/src/common/membuf_configuration.h @@ -0,0 +1,240 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/common/membuf_configuration.h $ */ +/* */ +/* 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 */ + +/* This header file is used by both occ_405 and occ_gpe1. */ +/* Contains common structures and globals. */ +#if !defined(__MEMBUF_CONFIGURATION_H__) +#define __MEMBUF_CONFIGURATION_H__ + +//#include "occhw_common.h" +#include "gpe_pba_parms.h" +#include "centaur_firmware_registers.h" + +#define OCCHW_N_MEMBUF 8 + +#define MEMTYPE_CENTAUR 1 +#define MEMTYPE_OCMB 2 + +/// Error return codes set/returned by gpe_*_configuration_create() + +typedef enum +{ + + MEMBUF_INVALID_ARGUMENT = 0x007ccc01, + MEMBUF_BAR_MASK_ERROR = 0x007ccc07, + MEMBUF_DATA_SETUP_ERROR = 0x007ccc09, + MEMBUF_SCOM_SETUP_ERROR = 0x007ccc0a, + MEMBUF_NOT_CONFIGURED = 0x007ccc0b, + MEMBUF_MASK_ERROR = 0x007ccc0c, + MEMBUF_BARN_GETSCOM_FAILURE = 0x007ccc0d, + MEMBUF_BARMSKN_PUTSCOM_FAILURE = 0x007ccc0e, + MEMBUF_BARN_PUTSCOM_FAILURE = 0x007ccc0f, + MEMBUF_BARMSKN_GETSCOM_FAILURE = 0x007ccc10, + MEMBUF_PBMODE_GETSCOM_FAILURE = 0x007ccc11, + MEMBUF_PMODE_DATA_MISMATCH = 0x007ccc12, +} MemBufConfigurationCreateRc; + +/** + * Definition of the MemBufConfiguration data. + * @note location must be 8-byte aligned, size must be multiple of 8 bytes. + */ +typedef struct +{ + + /// Membuf base addresses for in-band MMIO/SCOM operations + /// + uint64_t baseAddress[OCCHW_N_MEMBUF]; + + /// Contents of the Centaur device id register which includes cfam_id + // and module_id. + // (Not used on OCMB) + /// + uint64_t deviceId[OCCHW_N_MEMBUF]; + + /// Designated sync scom address + /// \note One and Only one of the MCS units can be targeted with SYNC + /// commands. The design includes a private bus connecting all MCS on the + /// chip that allows this "SYNC master" to broadcast the SYNC to all other + /// MCS on the chip. + uint32_t mcSyncAddr; + + // Membuf_type is MEMTYPE_CENTAUR | MEMTYPE_OCMB | etc. + uint32_t membuf_type; // keep 8 byte aligned + + /// A GpePbaParms parameter block for gpe_mem_data() + /// + /// This parameter block is set up in advance and used by the GPE + /// procedure gpe_membuf_data(). Given the complexity of accessing memory + /// sensors and SCOM through the PBA it is simpler to set these up ahead + /// of time and simply have the GPE procedures access preconfigured global + /// data. The \a dataParms and \a scomParms members are distinguished by + /// the different way the PBA slave needs to be configured to access + /// either the memory sensor cache or inband SCOMs. + GpePbaParms dataParms; + + /// A GpePbaParms parameter block for inband scom. + GpePbaParms scomParms; + + /// A "chip configuration" bit mask denoting valid memory buffer. + /// + /// It shoud always be true that a bit denoting a configured memory buffer + // is associated with a non-0 \a baseAddress and vice-versa. + uint32_t config; + + // Digital Thermal Sensor configuration bitmap. + // use CONFIG_UBDTS0(n) CONFIG_MEMDTS0(n) CONFIG_MEMDTS1(n) to set/test + uint32_t dts_config; + + uint32_t reserved; // Keep structure size multiple of 8 + + /// The final return code from gpe_*_configuration_create(). + /// @see MemBufConfigurationCreateRc + /// If initialization fails then this value can be used to diagnose what + /// happend. This field should be statically initialized to a non-0 value + /// (MEMBUF_NOT_CONFIGURED) and can then be checked against 0 to + /// determine if the structure has been correctly initialized. + int32_t configRc; + +} MemBufConfiguration_t __attribute__((aligned(8))); + + +typedef struct +{ + union + { + struct + { + uint32_t scom; + uint8_t reserved; + uint8_t errorFlags; + uint8_t instanceNumber; + uint8_t commandType; + }; + uint64_t command; + }; + uint64_t mask; + union + { + uint64_t data; + struct + { + uint32_t unused; + uint64_t* pData; + }; + }; +} scomList_t; + + +// Inband Scom Return Codes +enum +{ + // rc 1 - 7 reserved from scom rc + INBAND_ACCESS_INACTIVE = 98, + INBAND_ACCESS_IN_PROGRESS = 99, + MEMBUF_INVALID_SCOM = 100, + MEMBUF_GET_MEM_DATA_COLLECT_INVALID = 200, + MEMBUF_GET_MEM_DATA_UPDATE_INVALID = 201, + MEMBUF_GET_MEM_DATA_DIED = 202, + MEMBUF_CHANNEL_CHECKSTOP = 203, + MEMBUF_SCACHE_ERROR = 204, +}; + +// Inband Scom Operations +typedef enum +{ + /// No operation + MEMBUF_SCOM_NOP, + + /// Read from SCOM, depositing read data into the \a data field of the + /// scomList_t. + MEMBUF_SCOM_READ, + + /// Write to SCOM, taking write data from the \a data field of the scomList_t. + MEMBUF_SCOM_WRITE, + + /// Read-Modify-Write. + /// + /// This operation first reads the SCOM. Bits under the \a mask field of the + /// scomList_t are then cleared in the read data. The masked read data is then + /// ORed with the contents of the \a data field of the scomList_t and the + /// result is written back to the SCOM address. + /// + /// \note This command \e does \e not apply the mask to the data from the \a + /// data field of the scomList_t. The caller should do this (if necessary) + /// when setting up the scomList_t. + /// + /// \note The procedures do not provide a way to distinguish errors that may + /// have occurred on the initial read vs. those that may have occurred on the + /// subsequenct write. + MEMBUF_SCOM_RMW, + + /// The \a data field of the scomList_t contains a + /// 32-bit pointer (cast to a uint64_t) to an array of # of MEMBUF uint64_t + /// values. SCOM read data for each configured memory buffer module is + // deposited in this array. Array entries for unconfigured memory + // modules are zeroed. + MEMBUF_SCOM_READ_VECTOR, + + /// Write the \a data field of the scomList_t to + /// all configured MEMBUFs. + MEMBUF_SCOM_WRITE_ALL, + + /// Perform read-modify write for all configured + /// MEMBUF. + MEMBUF_SCOM_RMW_ALL, + + // Send SYNC to broadcast new throttle values. + MEMBUF_SCOM_MEMBUF_SYNC, + +} membuf_scom_operation_t; + +#define MCS_MCSYNC_SYNC_GO 0x0000800000000000ull + +// BAR and PBA_SLAVE assigned to gpe1 membuf +// - @see POWER Energy Management Hcode/HWP spec +#define PBA_BAR_MEMBUF 1 +#define PBA_SLAVE_MEMBUF 2 + +// These are used to setup MemBufConfiguration.config field +#define CHIP_CONFIG_MCS_BASE 16 +#define CHIP_CONFIG_MCS(n) \ + ((0x80000000ul >> CHIP_CONFIG_MCS_BASE) >> (n)) + +#define CHIP_CONFIG_MEMBUF_BASE 24 +#define CHIP_CONFIG_MEMBUF(n) \ + ((0x80000000ul >> CHIP_CONFIG_MEMBUF_BASE) >> (n)) + +#define CONFIG_UBDTS0(n) \ + (0x80000000ul >> (4*n)) + +#define CONFIG_MEMDTS0(n) \ + (0x40000000ul >> (4*n)) + +#define CONFIG_MEMDTS1(n) \ + (0x20000000ul >> (4*n)) + +#endif + + diff --git a/src/common/membuf_structs.h b/src/common/membuf_structs.h new file mode 100644 index 0000000..279af31 --- /dev/null +++ b/src/common/membuf_structs.h @@ -0,0 +1,92 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/common/membuf_structs.h $ */ +/* */ +/* 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 */ + +/* This header file is used by both occ_405 and occ_gpe1. */ +/* Contains common structures and globals. */ +#if !defined(_MEMBUF_STRUCTS_H) +#define _MEMBUF_STRUCTS_H + +#include "stdint.h" +#include "gpe_export.h" +#include "membuf_configuration.h" + +// IPC message payload for call to gpe_membuf_init() +typedef struct +{ + GpeErrorStruct error; + MemBufConfiguration_t * membufConfiguration; + uint32_t mem_type; + +} MemBufConfigParms_t; + +// IPC message payload for call to gpe_membuf_scom() +typedef struct +{ + GpeErrorStruct error; + + /** + * Input: The SCOM list + * This is a pointer to an array of scomList_t objects + * describing the sequence of commands to execute. + */ + scomList_t* scomList; + + /** + * Input: The number of entries in the scomList. + * @note It is considered an error if \a entries is 0, under the + * assumption that the caller must have neglected to initialize the + * structure. + */ + int entries; + +} MemBufScomParms_t; + +// IPC message payload for call to gpe_membuf_data() +typedef struct +{ + GpeErrorStruct error; + + /** + * The index (0 .. NMEMBUF - 1) of the MemBuf whose sensor cache + * data to collect, or -1 to bypass collection. + */ + int collect; + + /** + * The index (0 .. NMEMBUF - 1) of the MemBuf to "poke" to cause it + * to begin collecting the next round of data into its sensor cache, or + * -1 to bypass updating + */ + int update; + + /** + * Pointer to data collected. Needs to be set if collect != -1 + * otherwise it's not used. + */ + uint64_t * data; +} MemBufGetMemDataParms_t; + + +#endif diff --git a/src/common/ocmb_mem_data.h b/src/common/ocmb_mem_data.h new file mode 100644 index 0000000..4534dc5 --- /dev/null +++ b/src/common/ocmb_mem_data.h @@ -0,0 +1,87 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/common/ocmb_mem_data.h $ */ +/* */ +/* 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 */ + +/* This header file is used by both occ_405 and occ_gpe1. */ +/* Contains common structures and globals. */ +#if !defined(__OCMB_MEM_DATA_H__) +#define __OCMB_MEM_DATA_H__ + +typedef union +{ + uint16_t value; + struct + { + uint16_t ubdts0_err : 1; + uint16_t ubdts0_valid : 1; + uint16_t ubdts0_present : 1; + uint16_t memdts0_err : 1; + uint16_t memdts0_valid : 1; + uint16_t memdts0_present : 1; + uint16_t memdts1_err : 1; + uint16_t memdts1_valid : 1; + uint16_t memdts1_present : 1; + uint16_t event : 1; + uint16_t initial_packet0 : 1; + uint16_t reserved : 5; + + } fields; +} ocmb_status_t; + +typedef union +{ + uint32_t value; + struct + { + uint32_t initial_packet1 : 1; + uint32_t reserved2 : 7; + uint32_t reserved1 : 24; + } fields; +} ocmb_pkt1_status_t; + + +typedef struct +{ + ocmb_status_t status; + uint16_t ubdts0; // Membuf thermal sensor + uint16_t memdts[2]; // dimm0/1/ thermal sensor + uint32_t mba_rd; // MBA reads + uint32_t mba_wr; // MBA writes + uint32_t mba_act; // MBA activations + uint32_t mba_powerups; + uint8_t self_timed_refresh; // lp2_exists + uint8_t reserved1; + uint16_t reserved2; + uint32_t frame_count; + + uint32_t mba_arr_cnt_base; + uint32_t mba_arr_cnt_low; + uint32_t mba_arr_cnt_med; + uint32_t mba_arr_cnt_high; + ocmb_pkt1_status_t status1; + uint32_t reserved4; + uint64_t reserved5; +} OcmbMemData; + +#endif diff --git a/src/include/registers/ocmb_firmware_registers.h b/src/include/registers/ocmb_firmware_registers.h new file mode 100644 index 0000000..dabd2d1 --- /dev/null +++ b/src/include/registers/ocmb_firmware_registers.h @@ -0,0 +1,93 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/registers/ocmb_firmware_registers.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* [+] 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 */ +#ifndef __OCMB_FIRMWARE_REGISTERS_H__ +#define __OCMB_FIRMWARE_REGISTERS_H__ + +#include <stdint.h> + +typedef union ocmb_mmio_merrctl +{ + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + + struct + { + uint64_t dont_care0: 52; + uint64_t snsc_master_enable : 1; + uint64_t dont_care1: 11; + } fields; + +} mmio_merrctl_t; + +#define SNSC_MASTER_ENABLED 1 +#define SNSC_MASTER_DISABLED 0 + +typedef union ocmb_mmio_mfir +{ + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + + struct + { + uint64_t dont_care0: 7; + uint64_t snsc_both_starts_err: 1; + uint64_t snsc_mult_seq_perr: 1; + uint64_t snsc_fsm_perr: 1; + uint64_t snsc_reg_perr: 1; + uint64_t dont_care1: 53; + } fields; +} mmio_mfir_t; + +typedef union ocmb_mba_farb3q +{ + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + + struct + { + uint64_t cfg_nm_n_per_slot: 15; //mba + uint64_t cfg_nm_n_per_port: 16; //chip + uint64_t cfg_nm_m: 14; + uint64_t cfg_nm_ras_weight: 3; + uint64_t cfg_nm_cas_weight: 3; + uint64_t reserved0: 2; + uint64_t cfg_nm_change_after_sync: 1; + uint64_t reserved1: 10; + } fields; +} ocmb_mba_farb3q_t; + +#endif diff --git a/src/include/registers/ocmb_register_addresses.h b/src/include/registers/ocmb_register_addresses.h new file mode 100644 index 0000000..fb3070a --- /dev/null +++ b/src/include/registers/ocmb_register_addresses.h @@ -0,0 +1,39 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/registers/ocmb_register_addresses.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* [+] 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 */ +#ifndef __OCMB_REGISTER_ADDRESSES_H__ +#define __OCMB_REGISTER_ADDRESSES_H__ + + +#define MMIO_MERRCTL 0x080108ea +#define MMIO_MFIR 0x08010870 +#define MMIO_MFIR_AND 0x08010871 + +// N/M Throtling Control +#define OCMB_MBA_FARB3Q 0x08011418 + +#define OCMB_IB_SENSOR_CACHE_ADDR (0x40084200 >> 3) +#define OCMB_IB_BAR_B_BIT (0x0000000080000000ull) + +#endif diff --git a/src/include/registers/p9a_firmware_registers.h b/src/include/registers/p9a_firmware_registers.h new file mode 100644 index 0000000..98c1bcd --- /dev/null +++ b/src/include/registers/p9a_firmware_registers.h @@ -0,0 +1,79 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/registers/p9a_firmware_registers.h $ */ +/* */ +/* 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 */ + +/* This header file is used by both occ_405 and occ_gpe1. */ +/* Contains common structures and globals. */ +#if !defined(__P9A_FIRMWARE_REGISTERS_H__) +#define __P9A_FIRMWARE_REGISTERS_H__ + +typedef union mcfgpr +{ + uint64_t value; + struct + { +#ifdef _BIG_ENDIAN + uint32_t high_order; + uint32_t low_order; +#else + uint32_t low_order; + uint32_t high_order; +#endif // _BIG_ENDIAN + } words; + struct + { +#ifdef _BIG_ENDIAN + uint64_t config_valid : 1; + uint64_t mmio_valid : 1; + uint64_t config_group_addr : 31; + uint64_t mmio_group_base_addr : 31; +#else + uint64_t mmio_group_base_addr : 31; + uint64_t config_group_addr : 31; + uint64_t mmio_valid : 1; + uint64_t config_valid : 1; +#endif // _BIG_ENDIAN + } fields; +} mcfgpr_t; + + +typedef union +{ + uint64_t value; + struct + { +#ifdef _BIG_ENDIAN + uint64_t dont_care : 56; + uint64_t addr_extension_group_id : 4; + uint64_t addr_extension_chip_id : 3; + uint64_t dont_care1 : 1; +#else + uint64_t dont_care1 : 1; + uint64_t addr_extension_chip_id : 3; + uint64_t addr_extension_group_id : 4; + uint64_t dont_care : 56; +#endif + } fields; +} pb_mode_t; +#endif diff --git a/src/include/registers/p9a_misc_scom_addresses.h b/src/include/registers/p9a_misc_scom_addresses.h new file mode 100644 index 0000000..6a6975e --- /dev/null +++ b/src/include/registers/p9a_misc_scom_addresses.h @@ -0,0 +1,43 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/registers/p9a_misc_scom_addresses.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* [+] 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 */ +// Axone MC Primary Memory Configuration Register, Inband +#define P9A_MI_0_MCFGPR0 0x0501080C +#define P9A_MI_1_MCFGPR0 0x0501088C +#define P9A_MI_2_MCFGPR0 0x0301080C +#define P9A_MI_3_MCFGPR0 0x0301088C + +#define P9A_MI_0_MCFGPR1 0x0501080D +#define P9A_MI_1_MCFGPR1 0x0501088D +#define P9A_MI_2_MCFGPR1 0x0301080D +#define P9A_MI_3_MCFGPR1 0x0301088D + +// Axone MC Sync Command Register +#define P9A_MI_0_MCSYNC 0x05010815 +#define P9A_MI_1_MCSYNC 0x05010895 +#define P9A_MI_2_MCSYNC 0x03010815 +#define P9A_MI_3_MCSYNC 0x03010895 + +// Axone PB Mode register +#define P9A_PU_NMMU_MMCQ_PB_MODE_REG 0x05012C15 diff --git a/src/occ_405/amec/amec_sensors_ocmb.c b/src/occ_405/amec/amec_sensors_ocmb.c new file mode 100644 index 0000000..3e57266 --- /dev/null +++ b/src/occ_405/amec/amec_sensors_ocmb.c @@ -0,0 +1,634 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/amec/amec_sensors_centaur.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,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 */ + +/******************************************************************************/ +/* includes */ +/******************************************************************************/ +#include <occ_common.h> +#include <ssx.h> +#include <errl.h> // Error logging +#include "sensor.h" +#include "rtls.h" +#include "occ_sys_config.h" +#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE +#include "dcom.h" +#include "memory.h" +#include "centaur_data.h" +#include "amec_smh.h" +#include "amec_slave_smh.h" +#include <trac.h> +#include "amec_sys.h" +#include "sensor_enum.h" +#include "amec_service_codes.h" +#include "amec_sensors_ocmb.h" +#include "ocmb_mem_data.h" + +/******************************************************************************/ +/* Globals */ +/******************************************************************************/ +extern dimm_sensor_flags_t G_dimm_overtemp_bitmap; +extern dimm_sensor_flags_t G_dimm_temp_updated_bitmap; +extern uint8_t G_cent_overtemp_bitmap; +extern uint8_t G_cent_temp_updated_bitmap; +extern uint8_t G_centaur_needs_recovery; +extern uint64_t G_inject_dimm; +extern uint32_t G_inject_dimm_trace[MAX_NUM_OCMBS][NUM_DIMMS_PER_OCMB]; + +uint32_t amec_diff_adjust_for_overflow(uint32_t i_new_value, uint32_t i_old_value); + +/******************************************************************************/ +/* Forward Declarations */ +/******************************************************************************/ +void amec_update_ocmb_dimm_dts_sensors(OcmbMemData * i_sensor_cache, uint8_t i_membuf); +void amec_update_ocmb_dts_sensors(OcmbMemData * i_sensor_cache, uint8_t i_membuf); +void amec_perfcount_ocmb_getmc( OcmbMemData * i_sensor_cache, uint8_t i_membuf); + +/******************************************************************************/ +/* Code */ +/******************************************************************************/ + +// Function Specification +// +// Name: amec_update_ocmb_dimm_dts_sensors +// +// Description: Updates sensors that have data grabbed by the fast core data +// task. +// +// Thread: RealTime Loop +// +// End Function Specification +void amec_update_ocmb_sensors(uint8_t i_membuf) +{ + if(CENTAUR_PRESENT(i_membuf)) + { + OcmbMemData * l_sensor_cache = + (OcmbMemData *)cent_get_centaur_data_ptr(i_membuf); + if(CENTAUR_UPDATED(i_membuf)) + { + amec_update_ocmb_dimm_dts_sensors(l_sensor_cache, i_membuf); + amec_update_ocmb_dts_sensors(l_sensor_cache, i_membuf); + amec_perfcount_ocmb_getmc(l_sensor_cache, i_membuf); + } + CLEAR_CENTAUR_UPDATED(i_membuf); + } +} + +// Function Specification +// +// Name: amec_update_ocmb_dimm_dts_sensors +// +// Description: Updates sensors that have data from the membuf sensor cache +// +// Thread: RealTime Loop +// +// Note: The ocmb cache data uses the same space as the Centaur +// membuf cache data, so some of the centaur attributes apply to +// Ocmb data as well as Centaur. +// +// End Function Specification +void amec_update_ocmb_dimm_dts_sensors(OcmbMemData * i_sensor_cache, uint8_t i_membuf) +{ +#define MIN_VALID_DIMM_TEMP 1 +#define MAX_VALID_DIMM_TEMP 125 //according to Mike Pardiek 04/23/2019 +#define MAX_MEM_TEMP_CHANGE 2 + + uint32_t k, l_hottest_dimm_temp; + uint16_t l_dts[NUM_DIMMS_PER_OCMB] = {0}; + uint32_t l_hottest_dimm_loc = NUM_DIMMS_PER_OCMB; + int32_t l_dimm_temp, l_prev_temp; + static uint8_t L_ran_once[MAX_NUM_OCMBS] = {FALSE}; + + // Harvest thermal data for all dimms + for(k=0; k < NUM_DIMMS_PER_OCMB; k++) + { + if(!CENTAUR_SENSOR_ENABLED(i_membuf, k)) + { + continue; + } + +#ifdef __INJECT_DIMM__ + if (g_amec->proc[0].memctl[i_membuf].centaur.dimm_temps[k].temp_sid) // DIMM has sensor ID + { + if ((G_inject_dimm & ((uint64_t)1 << ((i_membuf * 8) + k))) == 0) + { + if (G_inject_dimm_trace[i_membuf][k] != 0) + { + TRAC_INFO("amec_update_ocmb_dimm_dts_sensors: stopping injection of errors for DIMM%04X", (i_membuf<<8)|k); + G_inject_dimm_trace[i_membuf][k] = 0; + } + } + else + { + if (G_inject_dimm_trace[i_membuf][k] == 0) + { + TRAC_INFO("amec_update_ocmb_dimm_dts_sensors: injecting errors for DIMM%04X", (i_membuf<<8)|k); + G_inject_dimm_trace[i_membuf][k] = 1; + } + continue; // Skip this DIMM + } + } +#endif + + fru_temp_t* l_fru = &g_amec->proc[0].memctl[i_membuf].centaur.dimm_temps[k]; + + l_dimm_temp = i_sensor_cache->memdts[k]; + l_prev_temp = l_fru->cur_temp; + if(!l_prev_temp) + { + l_prev_temp = l_dimm_temp; + } + + //Check DTS status bits. VALID NEW if valid and !err + if((k == 0 && + i_sensor_cache->status.fields.memdts0_valid && + (!i_sensor_cache->status.fields.memdts0_err)) || + (k == 1 && + i_sensor_cache->status.fields.memdts1_valid && + (!i_sensor_cache->status.fields.memdts1_err))) + { + //make sure temperature is within a 'reasonable' range. + if(l_dimm_temp < MIN_VALID_DIMM_TEMP || + l_dimm_temp > MAX_VALID_DIMM_TEMP) + { + //set a flag so that if we end up logging an error we have something to debug why + l_fru->flags |= FRU_TEMP_OUT_OF_RANGE; + l_dts[k] = l_prev_temp; + } + else + { + //don't allow temp to change more than is reasonable for 2ms + if(l_dimm_temp > (l_prev_temp + MAX_MEM_TEMP_CHANGE)) + { + l_dts[k] = l_prev_temp + MAX_MEM_TEMP_CHANGE; + if(!l_fru->flags) + { + TRAC_INFO("dimm temp rose faster than reasonable: membuf[%d] dimm[%d] prev[%d] cur[%d]", + i_membuf, k, l_prev_temp, l_dimm_temp); + l_fru->flags |= FRU_TEMP_FAST_CHANGE; + } + } + else if (l_dimm_temp < (l_prev_temp - MAX_MEM_TEMP_CHANGE)) + { + l_dts[k] = l_prev_temp - MAX_MEM_TEMP_CHANGE; + if(!l_fru->flags) + { + TRAC_INFO("dimm temp fell faster than reasonable: membuf[%d] dimm[%d] prev[%d] cur[%d]", + i_membuf, k, l_prev_temp, l_dimm_temp); + l_fru->flags |= FRU_TEMP_FAST_CHANGE; + } + } + else //reasonable amount of change occurred + { + l_dts[k] = l_dimm_temp; + l_fru->flags &= ~FRU_TEMP_FAST_CHANGE; + } + + //Notify thermal thread that temperature has been updated + G_dimm_temp_updated_bitmap.bytes[i_membuf] |= DIMM_SENSOR0 >> k; + + //clear error flags + l_fru->flags &= FRU_TEMP_FAST_CHANGE; + } + } + else //status was VALID_OLD or ERROR + { + //convert status number to a flag + uint8_t l_status_flag = 0; + if((k == 0 && i_sensor_cache->status.fields.memdts0_err) || + (k == 1 && i_sensor_cache->status.fields.memdts1_err)) + { + l_status_flag = FRU_SENSOR_STATUS_ERROR; + } + else + { + l_status_flag = FRU_SENSOR_STATUS_VALID_OLD; + } + + if(L_ran_once[i_membuf]) + { + //Trace the error if we haven't traced it already for this sensor + if((l_status_flag != FRU_SENSOR_STATUS_VALID_OLD) && + !(l_status_flag & l_fru->flags)) + { + TRAC_ERR("Membuf %d dimm sensor%d reported an error.", i_membuf, k); + } + + l_fru->flags |= l_status_flag; + } + + //use last temperature + l_dts[k] = l_prev_temp; + + //request recovery (disable and re-enable sensor cache collection) + if(i_sensor_cache->status.fields.memdts0_err || + i_sensor_cache->status.fields.memdts1_err) + { + G_centaur_needs_recovery |= CENTAUR0_PRESENT_MASK >> i_membuf; + } + } + + //Check if at or above the error temperature + if(l_dts[k] >= g_amec->thermaldimm.ot_error) + { + //Set a bit so that this dimm can be called out by the thermal thread + G_dimm_overtemp_bitmap.bytes[i_membuf] |= 1 << k; + } + } + + // Find hottest temperature from all DIMMs for this centaur + for(l_hottest_dimm_temp = 0, k = 0; k < NUM_DIMMS_PER_OCMB; k++) + { + if(l_dts[k] > l_hottest_dimm_temp) + { + l_hottest_dimm_temp = l_dts[k]; + l_hottest_dimm_loc = k; + } + g_amec->proc[0].memctl[i_membuf].centaur.dimm_temps[k].cur_temp = l_dts[k]; + } + + amec_centaur_t* l_centaur_ptr = &g_amec->proc[0].memctl[i_membuf].centaur; + + //only update location if hottest dimm temp is greater than previous maximum + if(l_hottest_dimm_temp > l_centaur_ptr->tempdimmax.sample_max) + { + sensor_update(&l_centaur_ptr->locdimmax, l_hottest_dimm_loc); + } + + //update the max dimm temperature sensor for this centaur + sensor_update(&l_centaur_ptr->tempdimmax, l_hottest_dimm_temp); + + L_ran_once[i_membuf] = TRUE; + AMEC_DBG("Centaur[%d]: HotDimm=%d\n",i_membuf,l_hottest_dimm_temp); +} + +// Function Specification +// +// Name: amec_update_ocmb_dts_sensors +// +// Description: Updates sensors that have data grabbed by the fast core data +// +// Thread: RealTime Loop +// +// End Function Specification +void amec_update_ocmb_dts_sensors(OcmbMemData * i_sensor_cache, uint8_t i_membuf) +{ +#define MIN_VALID_MEMBUF_TEMP 1 +#define MAX_VALID_MEMBUF_TEMP 125 //according to Mike Pardiek + + uint16_t l_dts; + uint16_t l_sens_temp; + int32_t l_prev_temp; + static uint8_t L_ran_once[MAX_NUM_OCMBS] = {FALSE}; + + l_sens_temp = i_sensor_cache->ubdts0; + + fru_temp_t* l_fru = &g_amec->proc[0].memctl[i_membuf].centaur.centaur_hottest; + + l_prev_temp = l_fru->cur_temp; + if(!l_prev_temp) + { + l_prev_temp = l_sens_temp; + } + + //Check DTS status bits + if(i_sensor_cache->status.fields.ubdts0_valid && + (!i_sensor_cache->status.fields.ubdts0_err)) + { + //make sure temperature is within a 'reasonable' range. + if(l_sens_temp < MIN_VALID_MEMBUF_TEMP || + l_sens_temp > MAX_VALID_MEMBUF_TEMP) + { + //set a flag so that if we end up logging an error we have something to debug why + l_fru->flags |= FRU_TEMP_OUT_OF_RANGE; + l_dts = l_prev_temp; + } + else + { + //don't allow temp to change more than is reasonable for 2ms + if(l_sens_temp > (l_prev_temp + MAX_MEM_TEMP_CHANGE)) + { + l_dts = l_prev_temp + MAX_MEM_TEMP_CHANGE; + if(!l_fru->flags) + { + TRAC_INFO("membuf temp rose faster than reasonable: membuf[%d] prev[%d] cur[%d]", + i_membuf, l_prev_temp, l_sens_temp); + l_fru->flags |= FRU_TEMP_FAST_CHANGE; + } + } + else if (l_sens_temp < (l_prev_temp - MAX_MEM_TEMP_CHANGE)) + { + l_dts = l_prev_temp - MAX_MEM_TEMP_CHANGE; + if(!l_fru->flags) + { + TRAC_INFO("membuf temp fell faster than reasonable: cent[%d] prev[%d] cur[%d]", + i_membuf, l_prev_temp, l_sens_temp); + l_fru->flags |= FRU_TEMP_FAST_CHANGE; + } + } + else //reasonable amount of change occurred + { + l_dts = l_sens_temp; + l_fru->flags &= ~FRU_TEMP_FAST_CHANGE; + } + + //Notify thermal thread that temperature has been updated + G_cent_temp_updated_bitmap |= CENTAUR0_PRESENT_MASK >> i_membuf; + + //clear error flags + l_fru->flags &= FRU_TEMP_FAST_CHANGE; + } + } + else //status was INVALID + { + if(L_ran_once[i_membuf]) + { + //Trace the error if we haven't traced it already for this sensor + if(!(l_fru->flags & FRU_SENSOR_STATUS_INVALID) && + i_sensor_cache->status.fields.ubdts0_err) + { + TRAC_ERR("Membuf %d temp sensor error.", i_membuf); + } + + l_fru->flags |= FRU_SENSOR_STATUS_INVALID; + } + + //use last temperature + l_dts = l_prev_temp; + } + + L_ran_once[i_membuf] = TRUE; + + //Check if at or above the error temperature + if(l_dts >= g_amec->thermalcent.ot_error) + { + //Set a bit so that this dimm can be called out by the thermal thread + G_cent_overtemp_bitmap |= (CENTAUR0_PRESENT_MASK >> i_membuf); + } + + // Update Interim Data - later this will get picked up to form centaur sensor + g_amec->proc[0].memctl[i_membuf].centaur.centaur_hottest.cur_temp = l_dts; + + AMEC_DBG("Membuf[%d]: HotMembuf=%d\n",i_membuf,l_dts); +} + +// Function Specification +// +// Name: amec_update_ocmb_temp_sensors +// +// Description: Updates thermal sensors that have data grabbed by the centaur. +// +// Thread: RealTime Loop +// +// End Function Specification +void amec_update_ocmb_temp_sensors(void) +{ + uint32_t k; + uint32_t l_hot_dimm = 0; + uint32_t l_hot_mb = 0; + + // ----------------------------------------------------------- + // Find hottest temperature from all membufs for this Proc chip + // Find hottest temperature from all DIMMs for this Proc chip + // ----------------------------------------------------------- + for(k=0; k < MAX_NUM_OCMBS; k++) + { + if(g_amec->proc[0].memctl[k].centaur.centaur_hottest.cur_temp > l_hot_mb) + { + l_hot_mb = g_amec->proc[0].memctl[k].centaur.centaur_hottest.cur_temp; + } + if(g_amec->proc[0].memctl[k].centaur.tempdimmax.sample > l_hot_dimm) + { + l_hot_dimm = g_amec->proc[0].memctl[k].centaur.tempdimmax.sample; + } + } + sensor_update(&g_amec->proc[0].temp2mscent,l_hot_mb); + AMEC_DBG("HotMembuf=%d\n",l_hot_mb); + + sensor_update(&g_amec->proc[0].tempdimmthrm,l_hot_dimm); + AMEC_DBG("HotDimm=%d\n",l_hot_dimm); + +} + + +// Function Specification +// +// Name: amec_perfcount_ocmb_getmc +// +// Description: Updates performance sensors that have data grabbed by the +// centaur. +// +// Thread: RealTime Loop +// +// End Function Specification + +void amec_perfcount_ocmb_getmc( OcmbMemData * i_sensor_cache, + uint8_t i_membuf) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + uint32_t tempu = 0; + uint32_t templ = 0; + uint32_t temp32new = 0; + uint32_t temp32 = 0; + uint32_t tempreg = 0; + + #define AMECSENSOR_PORTPAIR_PTR(sensor_base,idx,idx2) \ + (&(g_amec->proc[0].memctl[idx].centaur.portpair[idx2].sensor_base)) + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + OcmbMemData * l_sensor_cache = i_sensor_cache; + + tempu = l_sensor_cache->mba_rd; + templ = l_sensor_cache->mba_wr; + + // --------------------------------------------------------------------------- + // Interim Calculation: MWRMx (0.01 Mrps) Memory write requests per sec + // --------------------------------------------------------------------------- + + // Extract write bandwidth + temp32new = (templ); + + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.wr_cnt_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.wr_cnt_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.memwrite2ms = tempreg; + + // ------------------------------------------------------------------------- + // Interim Calculation: MRDMx (0.01 Mrps) Memory read requests per sec + // ------------------------------------------------------------------------- + + // Extract read bandwidth + temp32new = (tempu); + + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.rd_cnt_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.rd_cnt_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.memread2ms = tempreg; + + // Go after second MC performance counter (power ups and activations) + tempu = l_sensor_cache->mba_act; + templ = l_sensor_cache->mba_powerups; + + // ---------------------------------------------------------------- + // Sensor: MPUMx (0.01 Mrps) Memory power-up requests per sec + // ---------------------------------------------------------------- + // Extract power up count + temp32new = (templ); // left shift into top 20 bits of 32 bits + + // For DD1.0, we only have 1 channel field that we use; DD2.0 we need to add another channel + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.pwrup_cnt_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.pwrup_cnt_accum = temp32new; // Save latest accumulator away for next time + tempreg=(uint16_t)(temp32>>12); // Select upper 20 bits + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.pwrup_cnt=(uint16_t)tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mpu2ms,i_membuf,0), tempreg); + + // ------------------------------------------------------------------- + // Sensor: MACMx (0.01 Mrps) Memory activation requests per sec + // ------------------------------------------------------------------- + // Extract activation count + temp32 = templ; + temp32 += tempu; + + temp32new = (temp32); // left shift into top 20 bits of 32 bits + // For DD1.0, we only have 1 channel field that we use; DD2.0 we need to add another channel + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.act_cnt_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.act_cnt_accum = temp32new; // Save latest accumulator away for next time + tempreg=(uint16_t)(temp32>>12); // Select lower 16 of 20 bits + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.act_cnt=(uint16_t)tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mac2ms,i_membuf,0), tempreg); + + // -------------------------------------------------------------------------- + // Sensor: MTS (count) Last received Timestamp (frame count) from Centaur + // -------------------------------------------------------------------------- + // Extract framecount (clock is 266.6666666MHz * 0.032 / 4096)=2083. + temp32new = l_sensor_cache->frame_count; + + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.fr2_cnt_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.fr2_cnt_accum = temp32new; // Save latest accumulator away for next time + tempreg=(uint16_t)(temp32>>12); // Select upper 20 bits + + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.fr2_cnt=(uint16_t)tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mts2ms,i_membuf,0), tempreg); + + // ------------------------------------------------------------------------------ + // Sensor: MIRB (0.01 Mevents/s) Memory Inter-request arrival idle intervals + // ------------------------------------------------------------------------------ + temp32new = l_sensor_cache->mba_arr_cnt_base; + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_base_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_base_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.mirb2ms = tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mirb2ms,i_membuf,0), tempreg); + + // -------------------------------------------------------------------------------------------------------- + // Sensor: MIRL (0.01 Mevents/s) Memory Inter-request arrival idle intervals longer than low threshold + // -------------------------------------------------------------------------------------------------------- + temp32new = l_sensor_cache->mba_arr_cnt_low; + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_low_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_low_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.mirl2ms = tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mirl2ms,i_membuf,0), tempreg); + + // ----------------------------------------------------------------------------------------------------------- + // Sensor: MIRM (0.01 Mevents/s) Memory Inter-request arrival idle intervals longer than medium threshold + // ----------------------------------------------------------------------------------------------------------- + temp32new = l_sensor_cache->mba_arr_cnt_med; + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_med_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_med_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.mirm2ms = tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mirm2ms,i_membuf,0), tempreg); + + // --------------------------------------------------------------------------------------------------------- + // Sensor: MIRH (0.01 Mevents/s) Memory Inter-request arrival idle intervals longer than high threshold + // --------------------------------------------------------------------------------------------------------- + temp32new = l_sensor_cache->mba_arr_cnt_high; + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_high_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.intreq_high_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.mirh2ms = tempreg; + sensor_update(AMECSENSOR_PORTPAIR_PTR(mirh2ms,i_membuf,0), tempreg); + + // ---------------------------------------------------- + // Sensor: MLP2 (events/s) Number of LP2 exits + // ---------------------------------------------------- + temp32new = l_sensor_cache->self_timed_refresh; + temp32 = g_amec->proc[0].memctl[i_membuf].centaur.perf.lp2exit_accum; + temp32 = amec_diff_adjust_for_overflow(temp32new, temp32); + g_amec->proc[0].memctl[i_membuf].centaur.perf.lp2exit_accum = temp32new; // Save latest accumulator away for next time + + // Read every 8 ms....to convert to 0.01 Mrps = ((8ms read * 125)/10000) + tempreg = ((temp32*125)/10000); + g_amec->proc[0].memctl[i_membuf].centaur.perf.mlp2_2ms = tempreg; + sensor_update((&(g_amec->proc[0].memctl[i_membuf].centaur.mlp2ms)), tempreg); + + // ------------------------------------------------------------ + // Sensor: MRDMx (0.01 Mrps) Memory read requests per sec + // ------------------------------------------------------------ + tempreg = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.memread2ms; + tempreg += g_amec->proc[0].memctl[i_membuf].centaur.portpair[1].perf.memread2ms; + sensor_update( (&(g_amec->proc[0].memctl[i_membuf].mrd)), tempreg); + + // ------------------------------------------------------------- + // Sensor: MWRMx (0.01 Mrps) Memory write requests per sec + // ------------------------------------------------------------- + tempreg = g_amec->proc[0].memctl[i_membuf].centaur.portpair[0].perf.memwrite2ms; + tempreg += g_amec->proc[0].memctl[i_membuf].centaur.portpair[1].perf.memwrite2ms; + sensor_update( (&(g_amec->proc[0].memctl[i_membuf].mwr)), tempreg); + + return; +} + +/*----------------------------------------------------------------------------*/ +/* End */ +/*----------------------------------------------------------------------------*/ diff --git a/src/occ_405/amec/amec_sensors_ocmb.h b/src/occ_405/amec/amec_sensors_ocmb.h new file mode 100644 index 0000000..c290a3d --- /dev/null +++ b/src/occ_405/amec/amec_sensors_ocmb.h @@ -0,0 +1,36 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/amec/amec_sensors_ocmb.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +#ifndef _AMEC_SENSORS_OCMB_H +#define _AMEC_SENSORS_OCMB_H + +//************************************************************************* +// Function Prototypes +//************************************************************************* +void amec_update_ocmb_sensors(uint8_t i_membuf); +void amec_update_ocmb_temp_sensors(void); + +#endif + diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c index 8c34a8a..5293f2f 100755 --- a/src/occ_405/amec/amec_slave_smh.c +++ b/src/occ_405/amec/amec_slave_smh.c @@ -46,6 +46,7 @@ #include <amec_sensors_power.h> #include <memory.h> #include <amec_sensors_centaur.h> +#include <amec_sensors_ocmb.h> #include <amec_sensors_fw.h> #include <amec_freq.h> #include <amec_data.h> @@ -502,8 +503,14 @@ void amec_slv_state_0(void) //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_0); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_0); + } //------------------------------------------------------- // Update vector sensors @@ -531,20 +538,24 @@ void amec_slv_state_0(void) // End Function Specification void amec_slv_state_1(void) { - AMEC_DBG("\tAMEC Slave State 1\n"); - - //------------------------------------------------------- - // Update Centaur sensors (for this tick) - //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) - { - amec_update_centaur_sensors(CENTAUR_1); + AMEC_DBG("\tAMEC Slave State 1\n"); + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { + //------------------------------------------------------- + // Update Centaur sensors (for this tick) + //------------------------------------------------------- + amec_update_centaur_sensors(CENTAUR_1); - //------------------------------------------------------- - // Update Proc Level Centaur/DIMM Temperature sensors - //------------------------------------------------------- - amec_update_centaur_temp_sensors(); - } + //------------------------------------------------------- + // Update Proc Level Centaur/DIMM Temperature sensors + //------------------------------------------------------- + amec_update_centaur_temp_sensors(); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_1); + amec_update_ocmb_temp_sensors(); + } } @@ -562,8 +573,14 @@ void amec_slv_state_2(void) //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_2); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_2); + } // Call VRM Vdd thermal controller amec_controller_vrm_vdd_thermal(); @@ -586,8 +603,14 @@ void amec_slv_state_3(void) //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_3); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_3); + } } @@ -602,13 +625,19 @@ void amec_slv_state_3(void) // End Function Specification void amec_slv_state_4(void) { - AMEC_DBG("\tAMEC Slave State 4\n"); + AMEC_DBG("\tAMEC Slave State 4\n"); //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_4); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_4); + } //------------------------------------------------------- // Run WOF Algorithm if we are NOT getting readings from PGPE @@ -638,8 +667,14 @@ void amec_slv_state_5(void) //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_5); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_5); + } //------------------------------------------------------- // Update partition sensors for DPS algorithms (for this tick) @@ -665,8 +700,14 @@ void amec_slv_state_6(void) //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_6); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_6); + } } @@ -684,8 +725,14 @@ void amec_slv_state_7(void) //------------------------------------------------------- // Update Centaur sensors (for this tick) //------------------------------------------------------- - if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { amec_update_centaur_sensors(CENTAUR_7); + } + else if(MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + amec_update_ocmb_sensors(CENTAUR_7); + } } // Function Specification diff --git a/src/occ_405/cent/centaur_control.c b/src/occ_405/cent/centaur_control.c index 407bbdd..dd3fb7f 100755 --- a/src/occ_405/cent/centaur_control.c +++ b/src/occ_405/cent/centaur_control.c @@ -39,7 +39,7 @@ #include "rtls.h" #include "apss.h" #include "state.h" -#include "centaur_structs.h" +#include "membuf_structs.h" #include "centaur_firmware_registers.h" #include "centaur_register_addresses.h" #include "amec_sys.h" @@ -64,7 +64,7 @@ typedef enum NM_THROTTLE_MBA23 = 1, MBS_THROTTLE_SYNC = 2, NUM_CENT_THROTTLE_SCOMS = 3, -} eCentaurThrottleRegs; +} eMemBufThrottleRegs; //*************************************************************************/ @@ -78,9 +78,9 @@ typedef enum //Pore flex request for the GPE job that is used for centaur init. GpeRequest G_centaur_control_request; -// @see CentaurScomParms in centaur_structs.h -GPE_BUFFER(CentaurScomParms_t G_centaur_control_reg_parms); -// scomList_t @see centaur_configuration.h +// @see CentaurScomParms in membuf_structs.h +GPE_BUFFER(MemBufScomParms_t G_membuf_control_reg_parms); +// scomList_t @see membuf_configuration.h GPE_BUFFER(scomList_t G_centaurThrottle[NUM_CENT_THROTTLE_SCOMS]); //bitmap of configured MBA's (2 per centaur, lsb is centaur 0/mba 0) @@ -244,8 +244,8 @@ bool centaur_control( memory_control_task_t * i_memControlTask ) amec_centaur_t *l_cent_ptr = NULL; int l_cent = i_memControlTask->curMemIndex; - CentaurScomParms_t * l_parms = - (CentaurScomParms_t *)(i_memControlTask->gpe_req.cmd_data); + MemBufScomParms_t * l_parms = + (MemBufScomParms_t *)(i_memControlTask->gpe_req.cmd_data); do { @@ -292,7 +292,7 @@ bool centaur_control( memory_control_task_t * i_memControlTask ) if(MBA_CONFIGURED(l_cent, 0)) { /// [0]: Set up N/M throttle MBA01 - G_centaurThrottle[NM_THROTTLE_MBA01].commandType = CENTAUR_SCOM_RMW; + G_centaurThrottle[NM_THROTTLE_MBA01].commandType = MEMBUF_SCOM_RMW; G_centaurThrottle[NM_THROTTLE_MBA01].instanceNumber = l_cent; // Set up value to be written l_mbafarbq.fields.cfg_nm_n_per_mba = l_mba01_n_per_mba; @@ -301,14 +301,14 @@ bool centaur_control( memory_control_task_t * i_memControlTask ) } else { - G_centaurThrottle[NM_THROTTLE_MBA01].commandType = CENTAUR_SCOM_NOP; + G_centaurThrottle[NM_THROTTLE_MBA01].commandType = MEMBUF_SCOM_NOP; } //only write to MBA23 if configured if(MBA_CONFIGURED(l_cent, 1)) { /// [1]: Set up N/M throttle MBA23 - G_centaurThrottle[NM_THROTTLE_MBA23].commandType = CENTAUR_SCOM_RMW; + G_centaurThrottle[NM_THROTTLE_MBA23].commandType = MEMBUF_SCOM_RMW; G_centaurThrottle[NM_THROTTLE_MBA23].instanceNumber = l_cent; // Set up value to be written l_mbafarbq.fields.cfg_nm_n_per_mba = l_mba23_n_per_mba; @@ -317,10 +317,10 @@ bool centaur_control( memory_control_task_t * i_memControlTask ) } else { - G_centaurThrottle[NM_THROTTLE_MBA23].commandType = CENTAUR_SCOM_NOP; + G_centaurThrottle[NM_THROTTLE_MBA23].commandType = MEMBUF_SCOM_NOP; } - G_centaurThrottle[MBS_THROTTLE_SYNC].commandType = CENTAUR_SCOM_CENTAUR_SYNC; + G_centaurThrottle[MBS_THROTTLE_SYNC].commandType = MEMBUF_SCOM_MEMBUF_SYNC; /// Set up GPE parameters l_parms->scomList = G_centaurThrottle; @@ -377,9 +377,9 @@ void centaur_control_init( void ) G_centaurThrottle[NM_THROTTLE_MBA23].mask = l_mbafarbq.value; // Set up GPE parameters - G_centaur_control_reg_parms.error.ffdc = 0; - G_centaur_control_reg_parms.entries = 0; - G_centaur_control_reg_parms.scomList = &G_centaurThrottle[0]; + G_membuf_control_reg_parms.error.ffdc = 0; + G_membuf_control_reg_parms.entries = 0; + G_membuf_control_reg_parms.scomList = &G_centaurThrottle[0]; //-------------------------------------------------- // Initializes GPE Centaur Control Task, but @@ -388,8 +388,8 @@ void centaur_control_init( void ) l_rc_gpe = gpe_request_create( &G_memory_control_task.gpe_req, // gpe_req for the task &G_async_gpe_queue1, // queue - IPC_ST_CENTAUR_SCOM_FUNCID, // Function ID - &G_centaur_control_reg_parms, // parm for the task + IPC_ST_MEMBUF_SCOM_FUNCID, // Function ID + &G_membuf_control_reg_parms, // parm for the task SSX_WAIT_FOREVER, // NULL, // callback NULL, // callback argument @@ -429,7 +429,7 @@ void centaur_control_init( void ) ); addUsrDtlsToErrl(l_err, //io_err - (uint8_t *) &G_centaur_control_request.ffdc, //i_dataPtr, + (uint8_t *) &G_memory_control_task.gpe_req.ffdc, //i_dataPtr, sizeof(GpeFfdc), //i_size ERRL_USR_DTL_STRUCT_VERSION_1, //version ERRL_USR_DTL_BINARY_DATA); //type diff --git a/src/occ_405/cent/centaur_data.c b/src/occ_405/cent/centaur_data.c index ec27b9d..3ccd7bf 100755 --- a/src/occ_405/cent/centaur_data.c +++ b/src/occ_405/cent/centaur_data.c @@ -38,10 +38,11 @@ #include "apss.h" #include "state.h" #include "occhw_scom.h" -#include "centaur_structs.h" +#include "membuf_structs.h" #include "centaur_mem_data.h" #include "centaur_firmware_registers.h" #include "centaur_register_addresses.h" +#include "dimm.h" // MEM_TYPE_ //*************************************************************************/ // Externs @@ -111,19 +112,19 @@ GPE_BUFFER(CentaurMemData G_centaur_data[NUM_CENTAUR_DATA_BUFF + //pore request for scoming centaur registers GpeRequest G_cent_scom_req; // p8/working/procedures/ssx/pgp/pgp_async.h -//input/output parameters for IPC_ST_CENTAUR_SCOM() -GPE_BUFFER(CentaurScomParms_t G_cent_scom_gpe_parms); +//input/output parameters for IPC_ST_MEMBUF_SCOM() +GPE_BUFFER(MemBufScomParms_t G_cent_scom_gpe_parms); //scom command list entry GPE_BUFFER(scomList_t G_cent_scom_list_entry[NUM_CENT_OPS]); -//buffer for storing output from running IPC_ST_CENTAUR_SCOM() +//buffer for storing output from running IPC_ST_MEMBUF_SCOM() GPE_BUFFER(uint64_t G_cent_scom_data[MAX_NUM_CENTAURS]) = {0}; -// parms for call to IPC_ST_CENTAUR_INIT_FUNCID -GPE_BUFFER(CentaurConfigParms_t G_gpe_centaur_config_args); +// parms for call to IPC_ST_MEMBUF_INIT_FUNCID +GPE_BUFFER(MemBufConfigParms_t G_gpe_centaur_config_args); -GPE_BUFFER(CentaurConfiguration_t G_centaurConfiguration); +GPE_BUFFER(MemBufConfiguration_t G_membufConfiguration); //Global array of centaur data pointers CentaurMemData * G_centaur_data_ptrs[MAX_NUM_CENTAURS] = { &G_centaur_data[0], &G_centaur_data[1], &G_centaur_data[2], &G_centaur_data[3], @@ -131,18 +132,18 @@ CentaurMemData * G_centaur_data_ptrs[MAX_NUM_CENTAURS] = { &G_centaur_data[0], &G_centaur_data[7]}; //Global structures for gpe get mem data parms -GPE_BUFFER(CentaurGetMemDataParms_t G_centaur_data_parms); +GPE_BUFFER(MemBufGetMemDataParms_t G_membuf_data_parms); //Pore flex request for the GPE job that is used for centaur init. GpeRequest G_centaur_reg_gpe_req; //Centaur structures used for task data pointers. -centaur_data_task_t G_centaur_data_task = { - .start_centaur = 0, - .current_centaur = 0, - .end_centaur = 7, - .prev_centaur = 7, - .centaur_data_ptr = &G_centaur_data[MAX_NUM_CENTAURS] +membuf_data_task_t G_membuf_data_task = { + .start_membuf = 0, + .current_membuf = 0, + .end_membuf = 7, + .prev_membuf = 7, + .membuf_data_ptr = &G_centaur_data[MAX_NUM_CENTAURS] }; @@ -274,7 +275,7 @@ void cent_recovery(uint32_t i_cent) { // Check if the centaur has a channel checkstop. If it does then remove the centaur // from the enabled sensor bit map and do not log any errors - if(G_cent_scom_gpe_parms.error.rc == CENTAUR_CHANNEL_CHECKSTOP) + if(G_cent_scom_gpe_parms.error.rc == MEMBUF_CHANNEL_CHECKSTOP) { cent_chan_checkstop(l_prev_cent); } @@ -284,7 +285,7 @@ void cent_recovery(uint32_t i_cent) L_cent_callouts |= l_cent_mask; // There was an error doing the recovery scoms - TRAC_ERR("cent_recovery: IPC_ST_CENTAUR_SCOM failed. rc[0x%08x] cent[%d] entries[%d] errorIndex[0x%08X]", + TRAC_ERR("cent_recovery: IPC_ST_MEMBUF_SCOM failed. rc[0x%08x] cent[%d] entries[%d] errorIndex[0x%08X]", G_cent_scom_gpe_parms.error.rc, l_prev_cent, G_cent_scom_gpe_parms.entries, @@ -449,17 +450,17 @@ void cent_recovery(uint32_t i_cent) //check if this centaur requires lfir6 recovery if(G_centaur_nest_lfir6 & l_cent_mask) { - //Set the command type from CENTAUR_SCOM_NOP to CENTAUR_SCOM_RMW + //Set the command type from MEMBUF_SCOM_NOP to MEMBUF_SCOM_RMW //these entries will reset the centaur DTS FSM and clear LFIR 6 //if recovery worked, LFIR 6 should remain cleared. - G_cent_scom_list_entry[RESET_DTS_FSM].commandType = CENTAUR_SCOM_WRITE; - G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = CENTAUR_SCOM_WRITE; + G_cent_scom_list_entry[RESET_DTS_FSM].commandType = MEMBUF_SCOM_WRITE; + G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = MEMBUF_SCOM_WRITE; } else { //these ops aren't needed so disable them - G_cent_scom_list_entry[RESET_DTS_FSM].commandType = CENTAUR_SCOM_NOP; - G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = CENTAUR_SCOM_NOP; + G_cent_scom_list_entry[RESET_DTS_FSM].commandType = MEMBUF_SCOM_NOP; + G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = MEMBUF_SCOM_NOP; } //Decrement the delay counter for centaur i2c recovery @@ -489,13 +490,13 @@ void cent_recovery(uint32_t i_cent) //clear the request for i2c recovery here G_centaur_needs_recovery &= ~l_cent_mask; - //Set the command type from CENTAUR_SCOM_NOP to CENTAUR_SCOM_RMW + //Set the command type from MEMBUF_SCOM_NOP to MEMBUF_SCOM_RMW //this entry will disable the centaur sensor cache and //set a flag to finish the recovery in a later call of this //function (cent_recovery for a given centaur is called every //2 msec) - G_cent_scom_list_entry[DISABLE_SC].commandType = CENTAUR_SCOM_RMW; - G_cent_scom_list_entry[ENABLE_SC].commandType = CENTAUR_SCOM_NOP; + G_cent_scom_list_entry[DISABLE_SC].commandType = MEMBUF_SCOM_RMW; + G_cent_scom_list_entry[ENABLE_SC].commandType = MEMBUF_SCOM_NOP; L_i2c_finish_recovery[i_cent] = TRUE; } } @@ -515,8 +516,8 @@ void cent_recovery(uint32_t i_cent) } //these ops aren't needed so disable them - G_cent_scom_list_entry[DISABLE_SC].commandType = CENTAUR_SCOM_NOP; - G_cent_scom_list_entry[ENABLE_SC].commandType = CENTAUR_SCOM_NOP; + G_cent_scom_list_entry[DISABLE_SC].commandType = MEMBUF_SCOM_NOP; + G_cent_scom_list_entry[ENABLE_SC].commandType = MEMBUF_SCOM_NOP; // Finish the i2c recovery if it was started for this centaur if(L_i2c_finish_recovery[i_cent] == TRUE) @@ -527,11 +528,11 @@ void cent_recovery(uint32_t i_cent) //clear the finish_recovery flag for this centaur L_i2c_finish_recovery[i_cent] = FALSE; - //Set the command type from CENTAUR_SCOM_NOP to CENTAUR_SCOM_RMW + //Set the command type from MEMBUF_SCOM_NOP to MEMBUF_SCOM_RMW //this entry will re-enable the centaur sensor cache //which will also cause the i2c master to be reset - G_cent_scom_list_entry[DISABLE_SC].commandType = CENTAUR_SCOM_NOP; - G_cent_scom_list_entry[ENABLE_SC].commandType = CENTAUR_SCOM_RMW; + G_cent_scom_list_entry[DISABLE_SC].commandType = MEMBUF_SCOM_NOP; + G_cent_scom_list_entry[ENABLE_SC].commandType = MEMBUF_SCOM_RMW; } } @@ -596,9 +597,9 @@ void centaur_data( void ) errlHndl_t l_err = NULL; // Error handler int rc = 0; // Return code CentaurMemData * l_temp = NULL; - centaur_data_task_t * l_centaur_data_ptr = &G_centaur_data_task; - CentaurGetMemDataParms_t * l_parms = - (CentaurGetMemDataParms_t *)(l_centaur_data_ptr->gpe_req.cmd_data); + membuf_data_task_t * l_centaur_data_ptr = &G_membuf_data_task; + MemBufGetMemDataParms_t * l_parms = + (MemBufGetMemDataParms_t *)(l_centaur_data_ptr->gpe_req.cmd_data); static bool L_gpe_scheduled = FALSE; static bool L_gpe_error_logged = FALSE; static bool L_gpe_had_1_tick = FALSE; @@ -608,16 +609,16 @@ void centaur_data( void ) // ------------------------------------------ // Centaur Data Task Variable Initial State // ------------------------------------------ - // ->current_centaur: the one that was just 'written' to last tick to + // ->current_membuf: the one that was just 'written' to last tick to // kick off the sensor cache population in the - // centaur. It will be 'read from' during this tick. + // membuf. It will be 'read from' during this tick. // - // ->prev_centaur: the one that was 'read from' during the last tick + // ->prev_membuf: the one that was 'read from' during the last tick // and will be used to update the // G_updated_centaur_mask during this tick. // - // ->centaur_data_ptr: points to G_centaur_data_ptrs[] for - // the centaur that is referenced by prev_centaur + // ->membuf_data_ptr: points to G_centaur_data_ptrs[] for + // the centaur that is referenced by prev_membuf // (the one that was just 'read') //First, check to see if the previous GPE request still running @@ -648,7 +649,7 @@ void centaur_data( void ) //Need to complete collecting data for all assigned centaurs from //previous interval and tick 0 is the current tick before collect data again. - if( (l_centaur_data_ptr->current_centaur == l_centaur_data_ptr->end_centaur) + if( (l_centaur_data_ptr->current_membuf == l_centaur_data_ptr->end_membuf) && ((CURRENT_TICK & (MAX_NUM_TICKS - 1)) != 0) ) { CENT_DBG("Did not collect centaur data. Need to wait for tick."); @@ -666,11 +667,11 @@ void centaur_data( void ) { // Check if the centaur has a channel checkstop. If it does then do not // log any errors, but remove the centaur from the config - if(l_parms->error.rc == CENTAUR_CHANNEL_CHECKSTOP) + if(l_parms->error.rc == MEMBUF_CHANNEL_CHECKSTOP) { - cent_chan_checkstop(l_centaur_data_ptr->prev_centaur); + cent_chan_checkstop(l_centaur_data_ptr->prev_membuf); } - else // log the error if it was not a CENTAUR_CHANNEL_CHECKSTOP + else // log the error if it was not a MEMBUF_CHANNEL_CHECKSTOP { //log an error the first time this happens but keep on running. //This should be informational (except mfg) since we are going to retry @@ -683,8 +684,8 @@ void centaur_data( void ) // There was an error collecting the centaur sensor cache TRAC_ERR("task_centaur_data: gpe_get_mem_data failed. rc=0x%08x, cur=%d, prev=%d", l_parms->error.rc, - l_centaur_data_ptr->current_centaur, - l_centaur_data_ptr->prev_centaur); + l_centaur_data_ptr->current_membuf, + l_centaur_data_ptr->prev_membuf); /* @ * @errortype * @moduleid CENT_TASK_DATA_MOD @@ -714,8 +715,16 @@ void centaur_data( void ) ERRL_USR_DTL_STRUCT_VERSION_1, //version ERRL_USR_DTL_BINARY_DATA); //type + + // Capture the GPE1 trace buffer + addUsrDtlsToErrl(l_err, + (uint8_t *) G_shared_gpe_data.gpe1_tb_ptr, + G_shared_gpe_data.gpe1_tb_sz, + ERRL_USR_DTL_STRUCT_VERSION_1, + ERRL_USR_DTL_TRACE_DATA); + //Callouts depend on the return code of the gpe_get_mem_data procedure - if(l_parms->error.rc == CENTAUR_GET_MEM_DATA_DIED) + if(l_parms->error.rc == MEMBUF_GET_MEM_DATA_DIED) { //callout the processor addCalloutToErrl(l_err, @@ -723,14 +732,15 @@ void centaur_data( void ) G_sysConfigData.proc_huid, ERRL_CALLOUT_PRIORITY_LOW); } - else if(l_parms->error.rc == CENTAUR_GET_MEM_DATA_SENSOR_CACHE_FAILED) + else if(l_parms->error.rc == CENTAUR_GET_MEM_DATA_SENSOR_CACHE_FAILED || + l_parms->error.rc == MEMBUF_SCACHE_ERROR) { //callout the previous centaur if present - if(CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur)) + if(CENTAUR_PRESENT(l_centaur_data_ptr->prev_membuf)) { addCalloutToErrl(l_err, ERRL_CALLOUT_TYPE_HUID, - G_sysConfigData.centaur_huids[l_centaur_data_ptr->prev_centaur], + G_sysConfigData.centaur_huids[l_centaur_data_ptr->prev_membuf], ERRL_CALLOUT_PRIORITY_HIGH); } @@ -743,11 +753,11 @@ void centaur_data( void ) else if(l_parms->error.rc == CENTAUR_GET_MEM_DATA_UPDATE_FAILED) { //callout the current centaur if present - if(CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur)) + if(CENTAUR_PRESENT(l_centaur_data_ptr->current_membuf)) { addCalloutToErrl(l_err, ERRL_CALLOUT_TYPE_HUID, - G_sysConfigData.centaur_huids[l_centaur_data_ptr->current_centaur], + G_sysConfigData.centaur_huids[l_centaur_data_ptr->current_membuf], ERRL_CALLOUT_PRIORITY_HIGH); } @@ -775,18 +785,18 @@ void centaur_data( void ) //If the previous GPE request succeeded then swap l_centaur_data_ptr //with the global one. The gpe routine will write new data into //a buffer that is not being accessed by the RTLoop code. - l_temp = l_centaur_data_ptr->centaur_data_ptr; - l_centaur_data_ptr->centaur_data_ptr = - G_centaur_data_ptrs[l_centaur_data_ptr->current_centaur]; - G_centaur_data_ptrs[l_centaur_data_ptr->prev_centaur] = l_temp; + l_temp = l_centaur_data_ptr->membuf_data_ptr; + l_centaur_data_ptr->membuf_data_ptr = + G_centaur_data_ptrs[l_centaur_data_ptr->current_membuf]; + G_centaur_data_ptrs[l_centaur_data_ptr->prev_membuf] = l_temp; //Centaur data has been collected so set the bit in global mask. //AMEC code will know which centaur to update sensors for. AMEC is //responsible for clearing the bit later on. // prev centaur is the one that was just 'read from' in the last tick - if( CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur) ) + if( CENTAUR_PRESENT(l_centaur_data_ptr->prev_membuf) ) { - G_updated_centaur_mask |= CENTAUR_BY_MASK(l_centaur_data_ptr->prev_centaur); + G_updated_centaur_mask |= CENTAUR_BY_MASK(l_centaur_data_ptr->prev_membuf); } } }//if(L_gpe_scheduled) @@ -794,48 +804,48 @@ void centaur_data( void ) // If the centaur is not present, then we need to point to the empty G_centaur_data // so that we don't use old/stale data from a leftover G_centaur_data // (this is very handy for debug...) - if( !CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur)) + if( !CENTAUR_PRESENT(l_centaur_data_ptr->current_membuf)) { - G_centaur_data_ptrs[l_centaur_data_ptr->current_centaur] = &G_centaur_data[9]; + G_centaur_data_ptrs[l_centaur_data_ptr->current_membuf] = &G_centaur_data[9]; } //Update current centaur - if ( l_centaur_data_ptr->current_centaur >= l_centaur_data_ptr->end_centaur ) + if ( l_centaur_data_ptr->current_membuf >= l_centaur_data_ptr->end_membuf ) { - l_centaur_data_ptr->prev_centaur = l_centaur_data_ptr->current_centaur; - l_centaur_data_ptr->current_centaur = l_centaur_data_ptr->start_centaur; + l_centaur_data_ptr->prev_membuf = l_centaur_data_ptr->current_membuf; + l_centaur_data_ptr->current_membuf = l_centaur_data_ptr->start_membuf; } else { - l_centaur_data_ptr->prev_centaur = l_centaur_data_ptr->current_centaur; - l_centaur_data_ptr->current_centaur++; + l_centaur_data_ptr->prev_membuf = l_centaur_data_ptr->current_membuf; + l_centaur_data_ptr->current_membuf++; } // ------------------------------------------ - // Centaur Data Task Variable State Changed + // Membuf Data Task Variable State Changed // ------------------------------------------ - // ->current_centaur: the one that will be 'written' to in order to + // ->current_membuf: the one that will be 'written' to in order to // kick off the sensor cache population in the - // centaur. + // membuf. // - // ->prev_centaur: the one that will be 'read from', meaning have - // the sensor cache transferred from the Centaur - // to l_centaur_data_ptr->centaur_data_ptr + // ->prev_membuf: the one that will be 'read from', meaning have + // the sensor cache transferred from the membuf + // to l_centaur_data_ptr->membuf_data_ptr // - // ->centaur_data_ptr: points to G_centaur_data_ptrs[] for - // the centaur that is referenced by prev_centaur + // ->membuf_data_ptr: points to G_centaur_data_ptrs[] for + // the centaur that is referenced by prev_membuf // (the one that will be 'read') //If centaur is not present then skip it. This task assigned to this centaur will //be idle during this time it would have collected the data. - if( CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur) - || CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur) ) + if( CENTAUR_PRESENT(l_centaur_data_ptr->current_membuf) + || CENTAUR_PRESENT(l_centaur_data_ptr->prev_membuf) ) { // Setup the 'get centaur data' parms // ->config controls which Centaur we are reading from - if( CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur) ){ + if( CENTAUR_PRESENT(l_centaur_data_ptr->prev_membuf) ){ // If prev centaur is present, do the read of the sensor cache - l_parms->collect = l_centaur_data_ptr->prev_centaur; + l_parms->collect = l_centaur_data_ptr->prev_membuf; } else{ // If prev centaur is not present, don't do the read of the sensor cache. @@ -843,16 +853,16 @@ void centaur_data( void ) } // ->config_update controls which Centaur we are writing to - if( CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur) ){ + if( CENTAUR_PRESENT(l_centaur_data_ptr->current_membuf) ){ // If cur centaur is present, do the write to kick off the sensor cache collect - l_parms->update = l_centaur_data_ptr->current_centaur; + l_parms->update = l_centaur_data_ptr->current_membuf; } else{ // If cur centaur is not present, don't do the write to kick off the sensor cache collect l_parms->update = -1; } - l_parms->data = (uint64_t *)(l_centaur_data_ptr->centaur_data_ptr); + l_parms->data = (uint64_t *)(l_centaur_data_ptr->membuf_data_ptr); l_parms->error.ffdc = 0; // Pore flex schedule gpe_get_mem_data @@ -899,9 +909,12 @@ void centaur_data( void ) while(0); //handle centaur i2c recovery requests and centaur workaround. - if(CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur)) + if(CENTAUR_PRESENT(l_centaur_data_ptr->current_membuf)) { - cent_recovery(l_centaur_data_ptr->current_centaur); + if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { + cent_recovery(l_centaur_data_ptr->current_membuf); + } } return; } @@ -923,7 +936,7 @@ int cent_get_enabled_sensors() { // Set up scom list entry (there's only 1) G_cent_scom_list_entry[0].scom = CENTAUR_SENSCACHE_ENABLE; //scom address - G_cent_scom_list_entry[0].commandType = CENTAUR_SCOM_READ_VECTOR; //scom operation to perform + G_cent_scom_list_entry[0].commandType = MEMBUF_SCOM_READ_VECTOR; //scom operation to perform G_cent_scom_list_entry[0].instanceNumber = 0; //Ignored for READ_VECTOR operation G_cent_scom_list_entry[0].pData = (uint64_t *) G_cent_scom_data; //scom data will be stored here @@ -936,7 +949,7 @@ int cent_get_enabled_sensors() l_rc = gpe_request_create( &G_cent_scom_req, // gpe_req for the task &G_async_gpe_queue1, // queue - IPC_ST_CENTAUR_SCOM_FUNCID, // Function ID + IPC_ST_MEMBUF_SCOM_FUNCID, // Function ID &G_cent_scom_gpe_parms, // parm for the task SSX_SECONDS(2), // timeout NULL, // callback @@ -985,7 +998,7 @@ void centaur_init( void ) int rc = 0; // Return code int l_jj = 0; // Indexer static scomList_t L_scomList[2] SECTION_ATTRIBUTE(".noncacheable"); - static CentaurScomParms_t L_centaur_reg_parms SECTION_ATTRIBUTE(".noncacheable"); + static MemBufScomParms_t L_centaur_reg_parms SECTION_ATTRIBUTE(".noncacheable"); do { @@ -998,7 +1011,7 @@ void centaur_init( void ) /// Before anything else, we need to call this procedure to /// determine which Centaurs are out there, their config info. /// and Type/EC Level - rc = centaur_configuration_create(&G_centaurConfiguration); + rc = membuf_configuration_create(); if( rc ) { break; @@ -1015,14 +1028,13 @@ void centaur_init( void ) if( CENTAUR_BY_MASK(l_jj) ) { - if( G_centaurConfiguration.baseAddress[l_jj] ) + if( G_membufConfiguration.baseAddress[l_jj] ) { // G_cent_ba is != 0, so a valid Bar Address was found // This means there is a VALID centaur there. G_present_centaurs |= (CENTAUR0_PRESENT_MASK >> l_jj); - // Trace out the CFAM Chip ID, which includes Type & EC - TRAC_INFO("centaur_init: Centaur[%d] Found, Chip Id= 0x%08x",l_jj); + TRAC_INFO("centaur_init: Centaur[%d] Found",l_jj); } } } @@ -1034,49 +1046,49 @@ void centaur_init( void ) // Set up recovery scom list entries G_cent_scom_list_entry[L4_LINE_DELETE].scom = MBCCFGQ_REG; //scom address - G_cent_scom_list_entry[L4_LINE_DELETE].commandType = CENTAUR_SCOM_RMW; //scom operation to perform + G_cent_scom_list_entry[L4_LINE_DELETE].commandType = MEMBUF_SCOM_RMW; //scom operation to perform G_cent_scom_list_entry[L4_LINE_DELETE].mask = LINE_DELETE_ON_NEXT_CE; //mask of bits to change G_cent_scom_list_entry[L4_LINE_DELETE].data = LINE_DELETE_ON_NEXT_CE; //scom data (always set the bit) //one time init for reading LFIR6 G_cent_scom_list_entry[READ_NEST_LFIR6].scom = CENT_NEST_LFIR_REG; //scom address - G_cent_scom_list_entry[READ_NEST_LFIR6].commandType = CENTAUR_SCOM_READ; //scom operation to perform + G_cent_scom_list_entry[READ_NEST_LFIR6].commandType = MEMBUF_SCOM_READ; //scom operation to perform G_cent_scom_list_entry[READ_NEST_LFIR6].mask = 0; //mask (not used for reads) G_cent_scom_list_entry[READ_NEST_LFIR6].data = 0; //scom data (initialize to 0) //one time init for reading centaur thermal status register G_cent_scom_list_entry[READ_THERM_STATUS].scom = CENT_THRM_STATUS_REG; //scom address - G_cent_scom_list_entry[READ_THERM_STATUS].commandType = CENTAUR_SCOM_READ; //scom operation to perform + G_cent_scom_list_entry[READ_THERM_STATUS].commandType = MEMBUF_SCOM_READ; //scom operation to perform G_cent_scom_list_entry[READ_THERM_STATUS].mask = 0; //mask (not used for reads) G_cent_scom_list_entry[READ_THERM_STATUS].data = 0; //scom data (initialize to 0) //one time init to reset the centaur dts FSM G_cent_scom_list_entry[RESET_DTS_FSM].scom = CENT_THRM_CTRL_REG; //scom address - G_cent_scom_list_entry[RESET_DTS_FSM].commandType = CENTAUR_SCOM_NOP; //init to no-op (only runs if needed) + G_cent_scom_list_entry[RESET_DTS_FSM].commandType = MEMBUF_SCOM_NOP; //init to no-op (only runs if needed) G_cent_scom_list_entry[RESET_DTS_FSM].mask = 0; //mask (not used for writes) G_cent_scom_list_entry[RESET_DTS_FSM].data = CENT_THRM_CTRL4; //scom data (sets bit4) //one time init to clear centaur NEST LFIR 6 G_cent_scom_list_entry[CLEAR_NEST_LFIR6].scom = CENT_NEST_LFIR_AND_REG; //scom address - G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = CENTAUR_SCOM_NOP; //init to no-op (only runs if needed) + G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = MEMBUF_SCOM_NOP; //init to no-op (only runs if needed) G_cent_scom_list_entry[CLEAR_NEST_LFIR6].mask = 0; //mask (not used for writes) G_cent_scom_list_entry[CLEAR_NEST_LFIR6].data = ~CENT_NEST_LFIR6; //scom data //one time init to disable centaur sensor cache G_cent_scom_list_entry[DISABLE_SC].scom = SCAC_CONFIG_REG; //scom address - G_cent_scom_list_entry[DISABLE_SC].commandType = CENTAUR_SCOM_NOP; //init to no-op (only runs if needed) + G_cent_scom_list_entry[DISABLE_SC].commandType = MEMBUF_SCOM_NOP; //init to no-op (only runs if needed) G_cent_scom_list_entry[DISABLE_SC].mask = SCAC_MASTER_ENABLE; //mask of bits to change G_cent_scom_list_entry[DISABLE_SC].data = 0; //scom data (disable sensor cache) //one time init to enable centaur sensor cache G_cent_scom_list_entry[ENABLE_SC].scom = SCAC_CONFIG_REG; //scom address - G_cent_scom_list_entry[ENABLE_SC].commandType = CENTAUR_SCOM_NOP; //init to no-op (only runs if needed) + G_cent_scom_list_entry[ENABLE_SC].commandType = MEMBUF_SCOM_NOP; //init to no-op (only runs if needed) G_cent_scom_list_entry[ENABLE_SC].mask = SCAC_MASTER_ENABLE; //mask of bits to change G_cent_scom_list_entry[ENABLE_SC].data = SCAC_MASTER_ENABLE; //scom data (enable sensor cache) //one time init for reading centaur sensor cache lfir G_cent_scom_list_entry[READ_SCAC_LFIR].scom = SCAC_LFIR_REG; //scom address - G_cent_scom_list_entry[READ_SCAC_LFIR].commandType = CENTAUR_SCOM_READ; //scom operation to perform + G_cent_scom_list_entry[READ_SCAC_LFIR].commandType = MEMBUF_SCOM_READ; //scom operation to perform G_cent_scom_list_entry[READ_SCAC_LFIR].mask = 0; //mask (not used for reads) G_cent_scom_list_entry[READ_SCAC_LFIR].data = 0; //scom data (initialize to 0) @@ -1085,7 +1097,7 @@ void centaur_init( void ) /// NOTE: max timeout is about 2 seconds. L_scomList[0].scom = CENTAUR_MBSCFGQ; - L_scomList[0].commandType = CENTAUR_SCOM_RMW_ALL; + L_scomList[0].commandType = MEMBUF_SCOM_RMW_ALL; centaur_mbscfgq_t l_mbscfg; l_mbscfg.value = 0; @@ -1102,7 +1114,7 @@ void centaur_init( void ) /// [1]: clear the emergency throttle bit L_scomList[1].scom = CENTAUR_MBSEMERTHROQ; - L_scomList[1].commandType = CENTAUR_SCOM_RMW_ALL; + L_scomList[1].commandType = MEMBUF_SCOM_RMW_ALL; centaur_mbsemerthroq_t l_mbs_et; l_mbs_et.value = 0; @@ -1122,7 +1134,7 @@ void centaur_init( void ) rc = gpe_request_create( &G_centaur_reg_gpe_req, //gpe_req for the task &G_async_gpe_queue1, //queue - IPC_ST_CENTAUR_SCOM_FUNCID, // Function ID + IPC_ST_MEMBUF_SCOM_FUNCID, // Function ID &L_centaur_reg_parms, //parm for the task SSX_SECONDS(5), //timeout NULL, //callback @@ -1140,7 +1152,7 @@ void centaur_init( void ) // Check for errors on Scom if(rc || L_centaur_reg_parms.error.rc) { - TRAC_ERR("centaur_init: IPC_ST_CENTAUR_SCOM failure. rc = 0x%08x, gpe_rc = 0x%08x, address = 0x%08x", + TRAC_ERR("centaur_init: IPC_ST_MEMBUF_SCOM failure. rc = 0x%08x, gpe_rc = 0x%08x, address = 0x%08x", rc, L_centaur_reg_parms.error.rc, L_centaur_reg_parms.error.addr); @@ -1156,17 +1168,17 @@ void centaur_init( void ) /// to gather the 'centaur' data, but we will set them to /// invalid (-1) until the task sets them up - G_centaur_data_parms.error.ffdc = 0; - G_centaur_data_parms.collect = -1; - G_centaur_data_parms.update = -1; - G_centaur_data_parms.data = 0; + G_membuf_data_parms.error.ffdc = 0; + G_membuf_data_parms.collect = -1; + G_membuf_data_parms.update = -1; + G_membuf_data_parms.data = 0; //Initializes existing PoreFlex object for centaur data rc = gpe_request_create( - &G_centaur_data_task.gpe_req, //gpe_req for the task + &G_membuf_data_task.gpe_req, //gpe_req for the task &G_async_gpe_queue1, //queue - IPC_ST_CENTAUR_DATA_FUNCID, //Function ID - &G_centaur_data_parms, //parm for the task + IPC_ST_MEMBUF_DATA_FUNCID, //Function ID + &G_membuf_data_parms, //parm for the task SSX_WAIT_FOREVER, // NULL, //callback NULL, //callback argument @@ -1174,7 +1186,7 @@ void centaur_init( void ) if(rc) { - TRAC_ERR("centaur_init: gpe_request_create failed for G_centaur_data_task.gpe_req. rc = 0x%08x", rc); + TRAC_ERR("centaur_init: gpe_request_create failed for G_membuf_data_task.gpe_req. rc = 0x%08x", rc); break; } @@ -1182,7 +1194,7 @@ void centaur_init( void ) rc = gpe_request_create( &G_cent_scom_req, // gpe_req for the task &G_async_gpe_queue1, // queue - IPC_ST_CENTAUR_SCOM_FUNCID, // entry point + IPC_ST_MEMBUF_SCOM_FUNCID, // entry point &G_cent_scom_gpe_parms, // parm for the task SSX_WAIT_FOREVER, // NULL, // callback @@ -1275,19 +1287,27 @@ CentaurMemData * cent_get_centaur_data_ptr( const uint8_t i_occ_centaur_id ) } } -uint32_t centaur_configuration_create( CentaurConfiguration_t * i_centaurConfiguration ) +uint32_t membuf_configuration_create( ) { bool rc = 0; GpeRequest l_request; do { - G_gpe_centaur_config_args.centaurConfiguration = i_centaurConfiguration; + G_gpe_centaur_config_args.membufConfiguration = &G_membufConfiguration; + if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) + { + G_gpe_centaur_config_args.mem_type = MEMTYPE_CENTAUR; + } + else + { + G_gpe_centaur_config_args.mem_type = MEMTYPE_OCMB; + } rc = gpe_request_create( &l_request, // request &G_async_gpe_queue1, // gpe queue - IPC_ST_CENTAUR_INIT_FUNCID, // Function Id + IPC_ST_MEMBUF_INIT_FUNCID, // Function Id &G_gpe_centaur_config_args, // GPE arg_ptr SSX_SECONDS(5), // timeout NULL, // callback @@ -1295,22 +1315,22 @@ uint32_t centaur_configuration_create( CentaurConfiguration_t * i_centaurConfigu ASYNC_REQUEST_BLOCKING); if( rc ) { - TRAC_ERR("centaur_configuration_create: gpe_request_create failed for" - " IPC_ST_CENTAUR_INIT_FUNCID. rc = 0x%08x",rc); + TRAC_ERR("membuf_configuration_create: gpe_request_create failed for" + " IPC_ST_MEMBUF_INIT_FUNCID. rc = 0x%08x",rc); break; } - TRAC_INFO("centaur_configuration_create: Scheduling request for IPC_ST_CENTAUR_INIT_FUNCID"); + TRAC_INFO("membuf_configuration_create: Scheduling request for IPC_ST_MEMBUF_INIT_FUNCID"); gpe_request_schedule(&l_request); - TRAC_INFO("centaur_configuration_create: GPE_centaur_configuration_create w/rc=0x%08x", + TRAC_INFO("membuf_configuration_create: GPE_membuf_configuration_create w/rc=0x%08x", l_request.request.completion_state); if(ASYNC_REQUEST_STATE_COMPLETE != l_request.request.completion_state) { rc = l_request.request.completion_state; - TRAC_ERR("centaur_configuration_create: IPC_ST_CENTAUR_INIT_FUNCID" + TRAC_ERR("membuf_configuration_create: IPC_ST_MEMBUF_INIT_FUNCID" " request did not complete."); break; } @@ -1318,7 +1338,7 @@ uint32_t centaur_configuration_create( CentaurConfiguration_t * i_centaurConfigu if (G_gpe_centaur_config_args.error.rc != GPE_RC_SUCCESS) { rc = G_gpe_centaur_config_args.error.rc; - TRAC_ERR("centaur_configuration_create: IPC_ST_CENTAUR_INIT_FUNCID" + TRAC_ERR("membuf_configuration_create: IPC_ST_MEMBUF_INIT_FUNCID" " failed with rc=0x%08x.", rc); break; diff --git a/src/occ_405/cent/centaur_data.h b/src/occ_405/cent/centaur_data.h index 30c0e0d..2c7e259 100755 --- a/src/occ_405/cent/centaur_data.h +++ b/src/occ_405/cent/centaur_data.h @@ -33,7 +33,7 @@ #include <ssx.h> #include "rtls.h" #include "centaur_mem_data.h" -#include "centaur_structs.h" +#include "membuf_structs.h" #include "occ_sys_config.h" #include "memory.h" @@ -109,15 +109,15 @@ enum eOccCentaurs //Centaur data collect structures used for task data pointers -struct centaur_data_task { - uint8_t start_centaur; - uint8_t current_centaur; - uint8_t end_centaur; - uint8_t prev_centaur; - CentaurMemData * centaur_data_ptr; +struct membuf_data_task { + uint8_t start_membuf; + uint8_t current_membuf; + uint8_t end_membuf; + uint8_t prev_membuf; + CentaurMemData * membuf_data_ptr; GpeRequest gpe_req; } __attribute__ ((__packed__)); -typedef struct centaur_data_task centaur_data_task_t; +typedef struct membuf_data_task membuf_data_task_t; //************************************************************************* @@ -125,7 +125,7 @@ typedef struct centaur_data_task centaur_data_task_t; //************************************************************************* //Global centaur structures used for task data pointers -extern centaur_data_task_t G_centaur_data_task; +extern membuf_data_task_t G_membuf_data_task; //Global is bitmask of centaurs extern uint32_t G_present_centaurs; @@ -158,6 +158,9 @@ extern uint8_t G_cent_temp_updated_bitmap; //bitmap of configured MBA's (2 per centaur, lsb is centaur0/mba0) extern uint16_t G_configured_mbas; +//global Message payload for collecting membuf sensor cache data. +extern MemBufGetMemDataParms_t G_membuf_data_parms; + //************************************************************************* // Function Prototypes //************************************************************************* @@ -176,11 +179,12 @@ void cent_recovery(uint32_t i_cent); //associated with the specified OCC centaur id. CentaurMemData * cent_get_centaur_data_ptr( const uint8_t i_centaur_id ); -// Create the centaur configuration object -uint32_t centaur_configuration_create( CentaurConfiguration_t * i_centaurConfiguration ); +// Create the global membuf configuration object +uint32_t membuf_configuration_create( ); // Remove centaur from enabled sensor list due to channel checkstop void cent_chan_checkstop(uint32_t i_cent); +void ocmb_init(void); #endif //_CENTAUR_DATA_H diff --git a/src/occ_405/cent/centaur_data_service_codes.h b/src/occ_405/cent/centaur_data_service_codes.h index 85515ba..426090e 100755 --- a/src/occ_405/cent/centaur_data_service_codes.h +++ b/src/occ_405/cent/centaur_data_service_codes.h @@ -48,6 +48,7 @@ enum centModuleId CENTAUR_INIT_MOD = CENT_COMP_ID | 0x01, CENT_CONTROL_MOD = CENT_COMP_ID | 0x02, CENT_RECOVERY_MOD = CENT_COMP_ID | 0x03, + OCMB_INIT_MOD = CENT_COMP_ID | 0x04, }; //************************************************************************* diff --git a/src/occ_405/cent/ocmb_control.c b/src/occ_405/cent/ocmb_control.c new file mode 100644 index 0000000..02be215 --- /dev/null +++ b/src/occ_405/cent/ocmb_control.c @@ -0,0 +1,191 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/cent/ocmb_control.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 <occ_common.h> +#include "gpe_export.h" +#include "centaur_data_service_codes.h" +#include "errl.h" +#include "trac.h" +#include "memory.h" +#include "membuf_structs.h" +#include "ocmb_firmware_registers.h" +#include "ocmb_register_addresses.h" +#include "amec_sys.h" + +// These are found in centaur_control.c. They are valid for Ocmb +extern MemBufScomParms_t G_membuf_control_reg_parms; +GPE_BUFFER(extern scomList_t *G_centaurThrottle); +extern memory_control_task_t G_memory_control_task; +void cent_update_nlimits(uint32_t i_cent); +uint16_t centaurThrottle_convert2Numerator(uint16_t i_throttle, uint8_t i_cent, uint8_t i_mba); + +typedef enum +{ + NM_THROTTLE_MBA = 0, + NM_THROTTLE_SYNC = 1, + NUM_THROTTLE_SCOMS = 2, +} eOcmbThrottleInfo; + + +void ocmb_control_init( void ) +{ + errlHndl_t err = NULL; + int rc_gpe = 0; + ocmb_mba_farb3q_t l_mbafarbq; + + //initialize the active throttle limits + memset(G_memoryThrottleLimits, 0, sizeof(G_memoryThrottleLimits)); + + // set upt the throttle scom regs. //slot 0, slot1 or per-port + G_centaurThrottle[NM_THROTTLE_MBA].scom = OCMB_MBA_FARB3Q; + l_mbafarbq.value = 0; + l_mbafarbq.fields.cfg_nm_n_per_slot = -1; + l_mbafarbq.fields.cfg_nm_n_per_port = -1; + G_centaurThrottle[NM_THROTTLE_MBA].mask = l_mbafarbq.value; + + // Set up GPE parameters + G_membuf_control_reg_parms.error.ffdc = 0; + G_membuf_control_reg_parms.entries = 0; + G_membuf_control_reg_parms.scomList = &G_centaurThrottle[0]; + + //-------------------------------------------------- + // Initializes GPE Centaur Control Task, but + // doesn't actually run anything until RTL + //-------------------------------------------------- + rc_gpe = gpe_request_create( + &G_memory_control_task.gpe_req, // gpe_req for the task + &G_async_gpe_queue1, // queue + IPC_ST_MEMBUF_SCOM_FUNCID, // Function ID + &G_membuf_control_reg_parms, // parm for the task + SSX_WAIT_FOREVER, // + NULL, // callback + NULL, // callback argument + ASYNC_CALLBACK_IMMEDIATE ); // options + + if (rc_gpe) + { + //If fail to create gpe request then there is a problem. + TRAC_ERR("ocmb_control_init: Failed to initialize membuf control task [rc_gpe=0x%x]", rc_gpe); + + /* @ + * @errortype + * @moduleid CENTAUR_INIT_MOD + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 l_rc_gpe - Return code of failing function + * @userdata2 0 + * @userdata4 ERC_CENTAUR_GPE_REQUEST_CREATE_FAILURE + * @devdesc Failed to initialize GPE routine + */ + err = createErrl( + OCMB_INIT_MOD, //modId + SSX_GENERIC_FAILURE, //reasoncode + ERC_CENTAUR_GPE_REQUEST_CREATE_FAILURE, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc_gpe, //userdata1 + 0 //userdata2 + ); + + addUsrDtlsToErrl(err, //io_err + (uint8_t *) &G_memory_control_task.gpe_req.ffdc, //i_dataPtr, + sizeof(GpeFfdc), //i_size + ERRL_USR_DTL_STRUCT_VERSION_1, //version + ERRL_USR_DTL_BINARY_DATA); //type + + REQUEST_RESET(err); + } +} + +// Function Specification +// +// Name: ocmb_control +// +// Description: Performs centaur control. +// return TRUE settings changed HW needs to be updated. +// return FALSE settings did not change +// +// End Function Specification +bool ocmb_control( memory_control_task_t * i_memControlTask ) +{ + bool throttle_updated = TRUE; + int l_membuf = i_memControlTask->curMemIndex; + amec_centaur_t * l_cent_ptr = NULL; + + MemBufScomParms_t * l_parms = + (MemBufScomParms_t *)(i_memControlTask->gpe_req.cmd_data); + + l_cent_ptr = &g_amec->proc[0].memctl[l_membuf].centaur; + + // update min/max settings + cent_update_nlimits(l_membuf); + + // calculate new N values + ocmb_mba_farb3q_t l_mbafarbq; + uint16_t l_mba01_n_per_mba = + centaurThrottle_convert2Numerator(g_amec->mem_speed_request, l_membuf, 0); + + uint16_t l_mba01_n_per_chip = G_memoryThrottleLimits[l_membuf][0].max_n_per_chip; + amec_cent_mem_speed_t l_mba01_speed; + + //combine port and slot(mba) settings (16 bit) in to a single 32bit value + l_mba01_speed.mba_n = l_mba01_n_per_mba; + l_mba01_speed.chip_n = l_mba01_n_per_chip; + + + // Check if the throttle value has been updated since the last + // time we sent it. If it has, then send a new value, otherwise + // do nothing. + if ( l_mba01_speed.word32 != l_cent_ptr->portpair[0].last_mem_speed_sent.word32 ) + { + + /// Set up Centuar Scom Registers - array of Scoms + /// [0]: N/M Throttle MBA + + /// [0]: Set up N/M throttle MBA + G_centaurThrottle[NM_THROTTLE_MBA].commandType = MEMBUF_SCOM_RMW; + G_centaurThrottle[NM_THROTTLE_MBA].instanceNumber = l_membuf; + // Set up value to be written + l_mbafarbq.fields.cfg_nm_n_per_slot = l_mba01_n_per_mba; + l_mbafarbq.fields.cfg_nm_n_per_port = l_mba01_n_per_chip; + G_centaurThrottle[NM_THROTTLE_MBA].data = l_mbafarbq.value; + + G_centaurThrottle[NM_THROTTLE_SYNC].commandType = MEMBUF_SCOM_MEMBUF_SYNC; + + /// Set up GPE parameters + l_parms->scomList = G_centaurThrottle; + l_parms->entries = NUM_THROTTLE_SCOMS; + l_parms->error.ffdc = 0; + + // Update the last sent throttle value, this will get + // cleared if the GPE does not complete successfully. + l_cent_ptr->portpair[0].last_mem_speed_sent.word32 = l_mba01_speed.word32; + } + else + { + throttle_updated = FALSE; + } + + return throttle_updated; +} diff --git a/src/occ_405/cent/ocmb_data.c b/src/occ_405/cent/ocmb_data.c new file mode 100644 index 0000000..8599b28 --- /dev/null +++ b/src/occ_405/cent/ocmb_data.c @@ -0,0 +1,162 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/cent/ocmb_data.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 "centaur_data.h" +#include "ocmb_membuf.h" +#include "occ_service_codes.h" +#include "centaur_data_service_codes.h" +#include "errl.h" +#include "trac.h" +#include "membuf_structs.h" + +/** + * GPE shared data area for gpe0 tracebuffer and size + */ +extern gpe_shared_data_t G_shared_gpe_data; + +/** + * ocmb_init + * Initialize environment for collection of ocmb DTS and performance + * data. + * @post G_membufConfiguration populated + * @post G_present_centaurs populated + * @post G_dimm_present_sensors + * @post G_membuf_data_task populated + * @post GPE request to call for recover created ? + * @post GPE request to call for throttle conttrol created + * @note HW Deadman timer enabled and set to max value + * @note HW Any emergency throttle cleared +*/ +void ocmb_init(void) +{ + //errlHndl_t err = NULL; + int rc = 0; + int membuf_idx = 0; + do + { + TRAC_INFO("ocmb_init: Initializing Memory Data Controller"); + // Create configuration data use G_membufConfiguration + rc = membuf_configuration_create(&G_membufConfiguration); + if( rc ) + { + break; + } + + // Configure OCC_405 global membuf present and sensor enabled flags + G_present_centaurs = 0; + for(membuf_idx=0; membuf_idx<MAX_NUM_CENTAURS; ++membuf_idx) + { + // Check if this membuf is even possible to be present + if( CENTAUR_BY_MASK(membuf_idx) ) + { + if( G_membufConfiguration.baseAddress[membuf_idx] ) + { + // A valid inband Bar Address was found + G_present_centaurs |= (CENTAUR0_PRESENT_MASK >> membuf_idx); + + if(G_membufConfiguration.dts_config & CONFIG_MEMDTS0(membuf_idx)) + { + G_dimm_enabled_sensors.bytes[membuf_idx] = DIMM_SENSOR0; + } + if(G_membufConfiguration.dts_config & CONFIG_MEMDTS1(membuf_idx)) + { + G_dimm_enabled_sensors.bytes[membuf_idx] = (DIMM_SENSOR0 >> 1); + } + TRAC_INFO("ocmb_init: Membuf[%d] Found.", + membuf_idx); + } + } + } + + TRAC_IMP("ocmb_init: G_present_centaurs = 0x%08x", G_present_centaurs); + + G_dimm_present_sensors = G_dimm_enabled_sensors; + + TRAC_IMP("bitmap of present dimm temperature sensors: 0x%08X%08X", + G_dimm_enabled_sensors.words[0], + G_dimm_enabled_sensors.words[1]); + + // Setup the GPE request to do sensor data collection + G_membuf_data_parms.error.ffdc = 0; + G_membuf_data_parms.collect = -1; + G_membuf_data_parms.update = -1; + G_membuf_data_parms.data = 0; + + rc = gpe_request_create( + &G_membuf_data_task.gpe_req, //gpe_req for the task + &G_async_gpe_queue1, //queue + IPC_ST_MEMBUF_DATA_FUNCID, //Function ID + &G_membuf_data_parms, //parm for the task + SSX_WAIT_FOREVER, // + NULL, //callback + NULL, //callback argument + 0 ); //options + if( rc ) + { + TRAC_ERR("ocmb_init: gpe_request_create failed for " + "G_membuf_data_task.gpe_req. rc = 0x%08x", rc); + break; + } + + } while(0); + + if( rc ) + { + /* @ + * @errortype + * @moduleid OCMB_INIT_MOD + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 rc - Return code of failing function + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failed to initialize memory buffer sensors + */ + errlHndl_t l_err = + createErrl( + OCMB_INIT_MOD, //modId + SSX_GENERIC_FAILURE, //reasoncode + OCC_NO_EXTENDED_RC, //Extended reasoncode + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc, //userdata1 + 0 //userdata2 + ); + + // Capture the GPE1 trace buffer + addUsrDtlsToErrl(l_err, + (uint8_t *) G_shared_gpe_data.gpe1_tb_ptr, + G_shared_gpe_data.gpe1_tb_sz, + ERRL_USR_DTL_STRUCT_VERSION_1, + ERRL_USR_DTL_TRACE_DATA); + + + REQUEST_RESET(l_err); + } + else + { + ocmb_control_init(); + } + + return; +} diff --git a/src/occ_405/cent/ocmb_membuf.h b/src/occ_405/cent/ocmb_membuf.h new file mode 100644 index 0000000..844974d --- /dev/null +++ b/src/occ_405/cent/ocmb_membuf.h @@ -0,0 +1,47 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/cent/ocmb_membuf.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* [+] 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 */ +#ifndef __OCMB_MEMBUF_H__ +#define __OCMB_MEMBUF_H__ + +#include "ssx.h" +#include "memory.h" +#include "membuf_structs.h" + + +extern MemBufConfiguration_t G_membufConfiguration; + +/** + * Control ocmb memory buffer thottling + * @param[in] The memroy control task + * @return TRUE if throttle values changed, otherwise FALSE. + */ +bool ocmb_control( memory_control_task_t * i_memControlTask ); + +/** + * Initialize structures for throttle control on ocmb memory data buffer + */ +void ocmb_control_init( void ); + +#endif diff --git a/src/occ_405/dimm/dimm.c b/src/occ_405/dimm/dimm.c index 56d36dd..fd8e6e3 100755 --- a/src/occ_405/dimm/dimm.c +++ b/src/occ_405/dimm/dimm.c @@ -1031,7 +1031,7 @@ void task_dimm_sm(struct task *i_self) } } } - else // G_sysConfigData.mem_type is Centaur + else // G_sysConfigData.mem_type is Cumulus(Centaur) or Axone(Ocmb) { centaur_data(); } diff --git a/src/occ_405/mem/memory.c b/src/occ_405/mem/memory.c index 111407d..1ab7277 100644 --- a/src/occ_405/mem/memory.c +++ b/src/occ_405/mem/memory.c @@ -30,8 +30,9 @@ #include "memory_power_control.h" #include "dimm_control.h" #include "centaur_control.h" +#include "ocmb_membuf.h" #include "centaur_data.h" -#include "centaur_structs.h" +#include "membuf_structs.h" #include "memory_service_codes.h" #include <occ_service_codes.h> // for SSX_GENERIC_FAILURE #include "amec_sys.h" @@ -41,7 +42,7 @@ extern dimm_control_args_t G_dimm_control_args; extern task_t G_task_table[TASK_END]; -extern CentaurScomParms_t G_centaur_control_reg_parms; +extern MemBufScomParms_t G_membuf_control_reg_parms; // This array identifies dimm throttle limits for both Centaurs (Cumulus) and // rdimms (Nimbus) based systems. @@ -105,7 +106,11 @@ void task_memory_control( task_t * i_task ) } else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) { - gpe_rc = G_centaur_control_reg_parms.error.rc; + gpe_rc = G_membuf_control_reg_parms.error.rc; + } + else if (MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + gpe_rc = G_membuf_control_reg_parms.error.rc; } do @@ -148,7 +153,7 @@ void task_memory_control( task_t * i_task ) { // ignore error and stop monitoring this centaur if there is a channel checkstop if( (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) && - (gpe_rc == CENTAUR_CHANNEL_CHECKSTOP) ) + (gpe_rc == MEMBUF_CHANNEL_CHECKSTOP) ) { // Remove the centaur sensor and all dimm sensors behind it. cent_chan_checkstop(memControlTask->curMemIndex); @@ -224,6 +229,16 @@ void task_memory_control( task_t * i_task ) } rc = centaur_control(memControlTask); // Control one centaur } + else if (MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + // We use the same macros for Ocmb and Centaur + if(!CENTAUR_PRESENT(memIndex) || + (!MBA_CONFIGURED(memIndex, 0) && !MBA_CONFIGURED(memIndex, 1))) + { + break; + } + rc = ocmb_control(memControlTask); + } if(rc) { @@ -237,7 +252,7 @@ void task_memory_control( task_t * i_task ) } else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) { - gpe_rc = G_centaur_control_reg_parms.error.rc; + gpe_rc = G_membuf_control_reg_parms.error.rc; } //Error in schedule gpe memory (dimm/centaur) control @@ -361,11 +376,18 @@ void memory_init() // Init DIMM state manager IPC request memory_nimbus_init(); } - else + else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) { - TRAC_INFO("memory_init: calling centaur_init()"); centaur_init(); //no rc, handles errors internally } + else if (MEM_TYPE_OCM == G_sysConfigData.mem_type) + { + ocmb_init(); + } + else + { + TRAC_ERR("memory_init: Uknown memory type"); + } // check if the init resulted in a reset if(isSafeStateRequested()) diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile index 97f2f9a..f34fde3 100644 --- a/src/occ_405/occLinkInputFile +++ b/src/occ_405/occLinkInputFile @@ -15,6 +15,7 @@ INPUT ( amec_amester.o amec_sensors_fw.o amec_sensors_power.o amec_sensors_centaur.o + amec_sensors_ocmb.o amec_sensors_core.o amec_slave_smh.o amec_tasks.o @@ -22,6 +23,8 @@ INPUT ( amec_amester.o avsbus.o centaur_control.o centaur_data.o + ocmb_control.o + ocmb_data.o chom.o cmdh_dbug_cmd.o cmdh_fsp_cmds_datacnfg.o diff --git a/src/occ_405/occbuildname.c b/src/occ_405/occbuildname.c index 1f73927..b3e3a04 100755 --- a/src/occ_405/occbuildname.c +++ b/src/occ_405/occbuildname.c @@ -34,6 +34,6 @@ volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = #else -volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = /*<BuildName>*/ "op_occ_190424a\0" /*</BuildName>*/ ; +volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = /*<BuildName>*/ "op_occ_190426a\0" /*</BuildName>*/ ; #endif diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk index 7d98dbc..94dadfd 100644 --- a/src/occ_405/topfiles.mk +++ b/src/occ_405/topfiles.mk @@ -39,12 +39,15 @@ TOP-C-SOURCES = amec/amec_controller.c \ amec/amec_sensors_fw.c \ amec/amec_sensors_power.c \ amec/amec_sensors_centaur.c \ + amec/amec_sensors_ocmb.c \ amec/amec_sensors_core.c \ amec/amec_slave_smh.c \ amec/amec_tasks.c \ amec/sensor_power.c \ cent/centaur_control.c \ cent/centaur_data.c \ + cent/ocmb_control.c \ + cent/ocmb_data.c \ cmdh/cmdh_dbug_cmd.c \ cmdh/cmdh_fsp_cmds_datacnfg.c \ cmdh/cmdh_fsp_cmds.c \ diff --git a/src/occ_gpe0/firdata/firData.c b/src/occ_gpe0/firdata/firData.c index 5e35056..fc827b0 100644 --- a/src/occ_gpe0/firdata/firData.c +++ b/src/occ_gpe0/firdata/firData.c @@ -971,9 +971,9 @@ void FirData_addTrgtsToPnor( FirData_t * io_fd ) ADD_SUBUNITS_TO_PNOR( omicMask, MC, OMIC ) END_UNIT_LOOP } - else if ( HOMER_CHIP_EXPLORER == chipHdr->chipType ) + else if ( HOMER_CHIP_OCMB == chipHdr->chipType ) { - // NOTE: The Explorer chip does not have any unit data. + // NOTE: The Ocmb chip does not have any unit data. isM = false; // processor chips only. @@ -1136,9 +1136,9 @@ int32_t FirData_init( FirData_t * io_fd, { reglist += sizeof(HOMER_ChipAxone_t); } - else if (HOMER_CHIP_EXPLORER == l_chiptPtr->chipType) + else if (HOMER_CHIP_OCMB == l_chiptPtr->chipType) { - // There is no chip unit data for Explorer. + // There is no chip unit data for Ocmb. } else { diff --git a/src/occ_gpe0/firdata/homerData_common.h b/src/occ_gpe0/firdata/homerData_common.h index e661467..0d1a3cc 100644 --- a/src/occ_gpe0/firdata/homerData_common.h +++ b/src/occ_gpe0/firdata/homerData_common.h @@ -142,7 +142,7 @@ typedef enum { HOMER_CHIP_NIMBUS, /** P9 Nimbus processor chip */ HOMER_CHIP_AXONE, /** P9 Axone processor chip */ - HOMER_CHIP_EXPLORER, /** Explorer memory buffer chip */ + HOMER_CHIP_OCMB, /** OCMB memory buffer chip */ HOMER_CHIP_INVALID = 0xff, /** Invalid chip */ 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 |