From f301809e56b82fe61260a15f437183976db9ef75 Mon Sep 17 00:00:00 2001 From: Prachi Gupta Date: Fri, 14 Jul 2017 08:15:16 -0500 Subject: rt_xstop_analysis: move firdata code from occ_405 to occ_gpe0 Change-Id: Idaafd3bd9d40cfce4afd7b5d3308cd376f443967 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43242 Reviewed-by: Zane C. Shelley Reviewed-by: ILYA SMIRNOV Reviewed-by: Brian J. Stegmiller Reviewed-by: William A. Bryan Tested-by: William A. Bryan --- src/occ_405/firdata/ast_mboxdd.c | 326 ------- src/occ_405/firdata/ast_mboxdd.h | 292 ------ src/occ_405/firdata/ecc.c | 272 ------ src/occ_405/firdata/ecc.h | 76 -- src/occ_405/firdata/firData.c | 1389 ---------------------------- src/occ_405/firdata/firData.h | 48 - src/occ_405/firdata/firDataConst_common.h | 132 --- src/occ_405/firdata/fir_data_collect.c | 166 ---- src/occ_405/firdata/fir_data_collect.h | 56 -- src/occ_405/firdata/fsi.c | 152 --- src/occ_405/firdata/fsi.h | 47 - src/occ_405/firdata/homerData_common.h | 271 ------ src/occ_405/firdata/lpc.c | 391 -------- src/occ_405/firdata/lpc.h | 55 -- src/occ_405/firdata/native.c | 76 -- src/occ_405/firdata/native.h | 98 -- src/occ_405/firdata/norflash.h | 154 --- src/occ_405/firdata/pnorData_common.h | 162 ---- src/occ_405/firdata/pnor_mboxdd.c | 404 -------- src/occ_405/firdata/pnor_mboxdd.h | 135 --- src/occ_405/firdata/pnor_util.c | 220 ----- src/occ_405/firdata/pnor_util.h | 41 - src/occ_405/firdata/sbe_fifo.c | 444 --------- src/occ_405/firdata/sbe_fifo.h | 123 --- src/occ_405/firdata/scom_addr_util.c | 82 -- src/occ_405/firdata/scom_addr_util.h | 81 -- src/occ_405/firdata/scom_trgt.c | 180 ---- src/occ_405/firdata/scom_trgt.h | 89 -- src/occ_405/firdata/scom_util.c | 607 ------------ src/occ_405/firdata/scom_util.h | 98 -- src/occ_gpe0/firdata/ast_mboxdd.c | 326 +++++++ src/occ_gpe0/firdata/ast_mboxdd.h | 292 ++++++ src/occ_gpe0/firdata/ecc.c | 272 ++++++ src/occ_gpe0/firdata/ecc.h | 76 ++ src/occ_gpe0/firdata/firData.c | 1389 ++++++++++++++++++++++++++++ src/occ_gpe0/firdata/firData.h | 48 + src/occ_gpe0/firdata/firDataConst_common.h | 132 +++ src/occ_gpe0/firdata/fir_data_collect.c | 166 ++++ src/occ_gpe0/firdata/fir_data_collect.h | 56 ++ src/occ_gpe0/firdata/fsi.c | 152 +++ src/occ_gpe0/firdata/fsi.h | 47 + src/occ_gpe0/firdata/homerData_common.h | 271 ++++++ src/occ_gpe0/firdata/lpc.c | 391 ++++++++ src/occ_gpe0/firdata/lpc.h | 55 ++ src/occ_gpe0/firdata/native.c | 76 ++ src/occ_gpe0/firdata/native.h | 98 ++ src/occ_gpe0/firdata/norflash.h | 154 +++ src/occ_gpe0/firdata/pnorData_common.h | 162 ++++ src/occ_gpe0/firdata/pnor_mboxdd.c | 404 ++++++++ src/occ_gpe0/firdata/pnor_mboxdd.h | 135 +++ src/occ_gpe0/firdata/pnor_util.c | 220 +++++ src/occ_gpe0/firdata/pnor_util.h | 41 + src/occ_gpe0/firdata/sbe_fifo.c | 444 +++++++++ src/occ_gpe0/firdata/sbe_fifo.h | 123 +++ src/occ_gpe0/firdata/scom_addr_util.c | 82 ++ src/occ_gpe0/firdata/scom_addr_util.h | 81 ++ src/occ_gpe0/firdata/scom_trgt.c | 180 ++++ src/occ_gpe0/firdata/scom_trgt.h | 89 ++ src/occ_gpe0/firdata/scom_util.c | 607 ++++++++++++ src/occ_gpe0/firdata/scom_util.h | 98 ++ 60 files changed, 6667 insertions(+), 6667 deletions(-) delete mode 100644 src/occ_405/firdata/ast_mboxdd.c delete mode 100644 src/occ_405/firdata/ast_mboxdd.h delete mode 100644 src/occ_405/firdata/ecc.c delete mode 100644 src/occ_405/firdata/ecc.h delete mode 100644 src/occ_405/firdata/firData.c delete mode 100644 src/occ_405/firdata/firData.h delete mode 100644 src/occ_405/firdata/firDataConst_common.h delete mode 100644 src/occ_405/firdata/fir_data_collect.c delete mode 100644 src/occ_405/firdata/fir_data_collect.h delete mode 100644 src/occ_405/firdata/fsi.c delete mode 100644 src/occ_405/firdata/fsi.h delete mode 100644 src/occ_405/firdata/homerData_common.h delete mode 100644 src/occ_405/firdata/lpc.c delete mode 100644 src/occ_405/firdata/lpc.h delete mode 100644 src/occ_405/firdata/native.c delete mode 100644 src/occ_405/firdata/native.h delete mode 100644 src/occ_405/firdata/norflash.h delete mode 100644 src/occ_405/firdata/pnorData_common.h delete mode 100644 src/occ_405/firdata/pnor_mboxdd.c delete mode 100644 src/occ_405/firdata/pnor_mboxdd.h delete mode 100644 src/occ_405/firdata/pnor_util.c delete mode 100644 src/occ_405/firdata/pnor_util.h delete mode 100644 src/occ_405/firdata/sbe_fifo.c delete mode 100644 src/occ_405/firdata/sbe_fifo.h delete mode 100644 src/occ_405/firdata/scom_addr_util.c delete mode 100644 src/occ_405/firdata/scom_addr_util.h delete mode 100644 src/occ_405/firdata/scom_trgt.c delete mode 100644 src/occ_405/firdata/scom_trgt.h delete mode 100644 src/occ_405/firdata/scom_util.c delete mode 100644 src/occ_405/firdata/scom_util.h create mode 100644 src/occ_gpe0/firdata/ast_mboxdd.c create mode 100644 src/occ_gpe0/firdata/ast_mboxdd.h create mode 100644 src/occ_gpe0/firdata/ecc.c create mode 100644 src/occ_gpe0/firdata/ecc.h create mode 100644 src/occ_gpe0/firdata/firData.c create mode 100644 src/occ_gpe0/firdata/firData.h create mode 100644 src/occ_gpe0/firdata/firDataConst_common.h create mode 100644 src/occ_gpe0/firdata/fir_data_collect.c create mode 100644 src/occ_gpe0/firdata/fir_data_collect.h create mode 100644 src/occ_gpe0/firdata/fsi.c create mode 100644 src/occ_gpe0/firdata/fsi.h create mode 100644 src/occ_gpe0/firdata/homerData_common.h create mode 100644 src/occ_gpe0/firdata/lpc.c create mode 100644 src/occ_gpe0/firdata/lpc.h create mode 100644 src/occ_gpe0/firdata/native.c create mode 100644 src/occ_gpe0/firdata/native.h create mode 100644 src/occ_gpe0/firdata/norflash.h create mode 100644 src/occ_gpe0/firdata/pnorData_common.h create mode 100644 src/occ_gpe0/firdata/pnor_mboxdd.c create mode 100644 src/occ_gpe0/firdata/pnor_mboxdd.h create mode 100644 src/occ_gpe0/firdata/pnor_util.c create mode 100644 src/occ_gpe0/firdata/pnor_util.h create mode 100644 src/occ_gpe0/firdata/sbe_fifo.c create mode 100644 src/occ_gpe0/firdata/sbe_fifo.h create mode 100644 src/occ_gpe0/firdata/scom_addr_util.c create mode 100644 src/occ_gpe0/firdata/scom_addr_util.h create mode 100644 src/occ_gpe0/firdata/scom_trgt.c create mode 100644 src/occ_gpe0/firdata/scom_trgt.h create mode 100644 src/occ_gpe0/firdata/scom_util.c create mode 100644 src/occ_gpe0/firdata/scom_util.h (limited to 'src') diff --git a/src/occ_405/firdata/ast_mboxdd.c b/src/occ_405/firdata/ast_mboxdd.c deleted file mode 100644 index 064bcca..0000000 --- a/src/occ_405/firdata/ast_mboxdd.c +++ /dev/null @@ -1,326 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/ast_mboxdd.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ -/** - * @file ast_mboxdd.C - * - * @brief Implementation of the PNOR Accesser using the AST MBOX protocol - */ - -/*****************************************************************************/ -// I n c l u d e s -/*****************************************************************************/ -#include -#include -#include -#include - -errorHndl_t writeRegSIO(uint8_t i_regAddr, uint8_t i_data) -{ - errorHndl_t l_err = NO_ERROR; - - do { - size_t reg_size = sizeof(uint8_t); - - /* Write out the register address */ - l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, - &i_regAddr, - reg_size ); - if( l_err ) { break; } - - /* Write out the register data */ - l_err = lpc_write( LPC_TRANS_IO, SIO_DATA_REG_2F, - &i_data, - reg_size ); - if( l_err ) { break; } - - } while(0); - - return l_err; -} - -errorHndl_t readRegSIO(uint8_t i_regAddr, uint8_t* o_data) -{ - errorHndl_t l_err = NO_ERROR; - - do { - size_t reg_size = sizeof(uint8_t); - - /* Write out the register address */ - l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, - &i_regAddr, - reg_size ); - if( l_err ) { break; } - - /* Read in the register data */ - l_err = lpc_read( LPC_TRANS_IO, SIO_DATA_REG_2F, - o_data, - reg_size ); - if( l_err ) { break; } - - } while(0); - - return l_err; -} - -errorHndl_t mboxOut(uint64_t i_addr, uint8_t i_byte) -{ - size_t len = sizeof(i_byte); - - return lpc_write( LPC_TRANS_IO, - i_addr + MBOX_IO_BASE, - &i_byte, - len ); -} - -errorHndl_t mboxIn(uint64_t i_addr, uint8_t *o_byte) -{ - size_t len = sizeof(uint8_t); - - return lpc_read( LPC_TRANS_IO, - i_addr + MBOX_IO_BASE, - o_byte, - len ); -} - -errorHndl_t doMessage( astMbox_t *io_mbox, mboxMessage_t *io_msg ) -{ - uint8_t* l_data = (uint8_t*)io_msg; - errorHndl_t l_err = NO_ERROR; - uint8_t l_stat1; - uint32_t l_loops = 0; - bool l_prot_error = false; - int i; - - io_msg->iv_seq = io_mbox->iv_mboxMsgSeq++; - - do - { - /* Write message out */ - for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++) - { - l_err = mboxOut(i, l_data[i]); - } - - if ( l_err ) - { - break; - } - - /* Clear status1 response bit as it was just set via reg write*/ - l_err = mboxOut(MBOX_STATUS_1, MBOX_STATUS1_RESP); - - if ( l_err ) - { - break; - } - - /* Ping BMC */ - l_err = mboxOut(MBOX_HOST_CTRL, MBOX_CTRL_INT_SEND); - - if ( l_err ) - { - break; - } - - /* Wait for response */ - while ( l_loops++ < MBOX_MAX_RESP_WAIT_US && !l_err ) - { - l_err = mboxIn(MBOX_STATUS_1, &l_stat1); - - if ( l_err ) - { - TRAC_ERR("doMessage error from MBOX_STATUS_1"); - break; - } - - if ( l_stat1 & MBOX_STATUS1_RESP ) - { - break; - } - sleep(1000); - } - - if ( l_err ) - { - TRAC_ERR( "Got error waiting for response !"); - break; - } - - if ( !(l_stat1 & MBOX_STATUS1_RESP) ) - { - TRAC_ERR( "Timeout waiting for response !"); - - // Don't try to interrupt the BMC anymore - l_err = mboxOut(MBOX_HOST_CTRL, 0); - if ( l_err) - { - //Note the command failed - TRAC_ERR( "Error communicating with MBOX daemon"); - TRAC_ERR( "Mbox status 1 reg: %x", l_stat1); - } - - // Tell the code below that we generated the error - // (not an LPC error) - l_prot_error = true; - break; - } - - /* Clear status */ - l_err = mboxOut(MBOX_STATUS_1, MBOX_STATUS1_RESP); - if (l_err) - { - TRAC_ERR( "Got error clearing status"); - break; - } - - // Remember some message fields before they get overwritten - // by the response - uint8_t old_seq = io_msg->iv_seq; - - // Read response - for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++) - { - l_err = mboxIn(i, &l_data[i]); - } - - if ( l_err ) - { - TRAC_ERR( "Got error reading response !"); - break; - } - - if (old_seq != io_msg->iv_seq) - { - TRAC_ERR( "bad sequence number in mbox message, got %d want %d", - io_msg->iv_seq, old_seq); - l_err = -1; - break; - } - - if (io_msg->iv_resp != MBOX_R_SUCCESS) - { - TRAC_ERR( "BMC mbox command failed with err %d", - io_msg->iv_resp); - l_err = -1; - // Tell code below that we generated the error (not an LPC error) - l_prot_error = true; - break; - } - - } - while(0); - - // If we got an LPC error, commit it and generate our own - if ( l_err && !l_prot_error ) - { - l_err = -1; - } - - return l_err; -} - -errorHndl_t initializeMbox(void) -{ - errorHndl_t l_errl = NO_ERROR; - - do - { - size_t reg_size = sizeof(uint8_t); - - //First need to unlock SIO registers - /* Send SuperIO password - send A5 twice to offset 0x2E */ - uint8_t data = SIO_PASSWORD_REG; - l_errl = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, - &data, reg_size ); - if( l_errl ) { break; } - - l_errl = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, - &data, reg_size ); - if( l_errl ) { break; } - - //Second need to select Mailbox SIO Device - // Register 0x07 is device select reg - // Device 0x0E is the sio mailbox device - l_errl = writeRegSIO( SIO_DEVICE_SELECT_REG, SIO_MB ); - if( l_errl ) { break; } - - //First disable SIO Mailbox engine to configure it - // 0x30 - Enable/Disable Reg - // 0x00 - Disable Device (previously selected mailbox device) - l_errl = writeRegSIO( 0x30, 0x00 ); - - if (l_errl) - { - break; - } - - // Set MBOX Base Address - //Regs 0x60/0x61 are a BAR-like reg to configure the MBOX base address - l_errl = writeRegSIO( 0x60, (MBOX_IO_BASE >> 8) & 0xFF ); - - if (l_errl) - { - break; - } - - // Set other half of MBOX Base Address - l_errl = writeRegSIO( 0x61, MBOX_IO_BASE & 0xFF ); - - if (l_errl) - { - break; - } - - //Configure MBOX IRQs - //Regs 0x70 / 0x71 control that - l_errl = writeRegSIO( 0x70, MBOX_LPC_IRQ ); - - if (l_errl) - { - break; - } - - //Other half of MBOX IRQ Configuration - // 1 == Low level trigger - l_errl = writeRegSIO( 0x71, 1 ); - - if (l_errl) - { - break; - } - - //Re-enable Device now that base addr and IRQs are configured - // 1 == Enable Device - l_errl = writeRegSIO( 0x30, 0x01 ); - - if (l_errl) - { - break; - } - } - while(0); - - return l_errl; -} diff --git a/src/occ_405/firdata/ast_mboxdd.h b/src/occ_405/firdata/ast_mboxdd.h deleted file mode 100644 index 64ea40a..0000000 --- a/src/occ_405/firdata/ast_mboxdd.h +++ /dev/null @@ -1,292 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/ast_mboxdd.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __AST_MBOXDD_H -#define __AST_MBOXDD_H - -/** @file ast_mboxdd.H - * @brief Provides the interfaces Aspeed MBOX hardware - */ - -/** - * @brief Provides the interface to exchange Mbox - * messages with the BMC. - */ - -enum -{ - BMC_MBOX_DATA_REGS = 14, - BMC_MBOX_ARGS_REGS = 11, - - /* Commands */ - MBOX_C_RESET_STATE = 0x01, - MBOX_C_GET_MBOX_INFO = 0x02, - MBOX_C_GET_FLASH_INFO = 0x03, - MBOX_C_CREATE_READ_WINDOW = 0x04, - MBOX_C_CLOSE_WINDOW = 0x05, - MBOX_C_CREATE_WRITE_WINDOW = 0x06, - MBOX_C_MARK_WRITE_DIRTY = 0x07, - MBOX_C_WRITE_FLUSH = 0x08, - MBOX_C_BMC_EVENT_ACK = 0x09, - MBOX_C_MARK_WRITE_ERASED = 0x0a, - - /* Responses */ - MBOX_R_SUCCESS = 0x01, - MBOX_R_PARAM_ERROR = 0x02, - MBOX_R_WRITE_ERROR = 0x03, - MBOX_R_SYSTEM_ERROR = 0x04, - MBOX_R_TIMEOUT = 0x05, - MBOX_R_BUSY = 0x06, - MBOX_R_WINDOW_ERROR = 0x07, - -}; - -enum{ - SIO_DEVICE_SELECT_REG = 0x07, /**< Regsiter to select SIO device */ - SIO_ADDR_REG_2E = 0x2E, /**< SuperIO address register */ - SIO_DATA_REG_2F = 0x2F, /**< SuperIO data register */ - SIO_PASSWORD_REG = 0xA5, /**< SuperIO password register (to be unlocked to access SIO) */ - SIO_MB = 0x0E, /**< SIO device: Mailbox */ - SIO_ENABLE_DEVICE = 0x01, /**< Enable SIO device by writing 1 to reg 30 of device */ - SIO_DISABLE_DEVICE = 0x00, /**< Disable SIO device by writing 0 to reg 30 of device */ -}; - - -typedef struct -{ - uint8_t iv_cmd; - uint8_t iv_seq; - uint8_t iv_args[BMC_MBOX_ARGS_REGS]; - uint8_t iv_resp; - -} mboxMessage_t; - -/** - * @brief Write a single byte into an SIO register - * - * @param[in] i_reg: Register to write - * @param[in] i_data: Data to write - * - * @return Error from operation - */ -errorHndl_t writeRegSIO(uint8_t i_regAddr, - uint8_t i_data ); - -/** - * @brief Read a single byte from an SIO register - * - * @param[in] i_reg: Register to read - * @param[in] o_data: Data that was read - * - * @return Error from operation - */ -errorHndl_t readRegSIO(uint8_t i_regAddr, - uint8_t* o_data ); - - -//Helper functions to create mbox messages to send to the BMC - -/** - * @brief 8-bit read accessor of the args section - * - * @param[in] i_msg: mboxMessage_t pointer to access args section - * @param[in] i_index: Index into args section to be read from - * - * @return data requested - */ -static inline uint8_t get8( mboxMessage_t *i_msg, uint8_t i_index) -{ - if ( i_index >= BMC_MBOX_ARGS_REGS ) - { - return 0; - } - - return i_msg->iv_args[i_index]; -} - -/** - * @brief 8-bit write accessor of the args section - * - * @param[in] i_msg: mboxMessage_t pointer to access args section - * @param[in] i_index: Index into args section to be written to - * @param[in] i_value: data to be written - */ -static inline void put8(mboxMessage_t *i_msg, uint8_t i_index, uint8_t i_value) -{ - if ( i_index >= BMC_MBOX_ARGS_REGS ) - { - return; - } - - i_msg->iv_args[i_index] = i_value; -} - -/** - * @brief 16-bit read accessor of the args section - * @param[in] i_msg: mboxMessage_t pointer to access args section - * @param[in] i_index: Index into args section to be read from - * - * @return data requested - */ -static inline uint16_t get16( mboxMessage_t *i_msg, uint8_t i_index ) -{ - if ( i_index >= (BMC_MBOX_ARGS_REGS-1) ) - { - return 0; - } - - return i_msg->iv_args[i_index] | (i_msg->iv_args[i_index + 1] << 8); -} - -/** - * @brief 16-bit write accessor of the args section - * - * @param[in] i_msg: mboxMessage_t pointer to access args section - * @param[in] i_index: Index into args section to be written to - * @param[in] i_value: data to be written - */ -static inline void put16(mboxMessage_t *i_msg, - uint8_t i_index, - uint16_t i_value) -{ - if ( i_index >= (BMC_MBOX_ARGS_REGS-1) ) - { - return; - } - - i_msg->iv_args[i_index] = i_value & 0xff; - i_msg->iv_args[i_index + 1] = i_value >> 8; -} - -/** - * @brief 32-bit read accessor of the args section - * - * @param[in] i_msg: mboxMessage_t pointer to access args section - * @param[in] i_index: Index into args section to be read from - * - * @return data requested - */ -static inline uint32_t get32( mboxMessage_t *i_msg, uint8_t i_index ) -{ - if ( i_index >= (BMC_MBOX_ARGS_REGS-3) ) - { - return 0; - } - - return i_msg->iv_args[i_index] | - (i_msg->iv_args[i_index + 1] << 8) | - (i_msg->iv_args[i_index + 2] << 16) | - (i_msg->iv_args[i_index + 3] << 24); -} - -/** - * @brief 32-bit write accessor of the args section - * - * @param[in] i_msg: mboxMessage_t pointer to access args section - * @param[in] i_index: Index into args section to be read from - */ -static inline void put32(mboxMessage_t *i_msg, - uint8_t i_index, - uint32_t i_value) -{ - if ( i_index >= (BMC_MBOX_ARGS_REGS-3) ) - { - return; - } - - i_msg->iv_args[i_index] = i_value & 0xff; - i_msg->iv_args[i_index + 1] = (i_value >> 8) & 0xff; - i_msg->iv_args[i_index + 2] = (i_value >> 16) & 0xff; - i_msg->iv_args[i_index + 3 ] = i_value >> 24; -} - -typedef struct { - - uint8_t iv_mboxMsgSeq; - mboxMessage_t iv_msg; - -} astMbox_t; - -/** - * @brief Send a message and receive the response - * - * @parm[in/out] io_mbox Mbox pointer to send message - * @parm[in/out] io_msg Message to send, contains the response on exit - * - * @return Error from operation - */ -errorHndl_t doMessage( astMbox_t *io_mbox, mboxMessage_t *io_msg ); - -enum -{ - MBOX_FLAG_REG = 0x0f, - MBOX_STATUS_0 = 0x10, - MBOX_STATUS_1 = 0x11, - MBOX_STATUS1_ATTN = 0x80, - MBOX_STATUS1_RESP = 0x20, - MBOX_BMC_CTRL = 0x12, - MBOX_CTRL_INT_STATUS = 0x80, - MBOX_CTRL_INT_MASK = 0x02, - MBOX_CTRL_INT_SEND = 0x01, - MBOX_HOST_CTRL = 0x13, - MBOX_BMC_INT_EN_0 = 0x14, - MBOX_BMC_INT_EN_1 = 0x15, - MBOX_HOST_INT_EN_0 = 0x16, - MBOX_HOST_INT_EN_1 = 0x17, - - MBOX_IO_BASE = 0x1000, - MBOX_LPC_IRQ = 0x9, - - MBOX_MAX_RESP_WAIT_US = 10000000, /* 10s timeout */ -}; - -/** - * @brief Initialize/Enable the MBox in the SIO - * - * @return Error from operation - */ -errorHndl_t initializeMbox( void ); - -/** - * @brief Write a byte to the mBox - * - * @parm[in] i_addr: Register offset in the mbox - * @parm[in] i_byte: Byte to write - * - * @return Error from operation -*/ -errorHndl_t mboxOut( uint64_t i_addr, uint8_t i_byte ); - -/** - * @brief Read a byte from the mBox - * - * @parm[in] i_addr: Register offset in the mbox - * @parm[out] o_byte: Byte read - * - * @return Error from operation - */ -errorHndl_t mboxIn( uint64_t i_addr, uint8_t *o_byte ); - -#endif /* __AST_MBOXDD_H */ diff --git a/src/occ_405/firdata/ecc.c b/src/occ_405/firdata/ecc.c deleted file mode 100644 index 6696678..0000000 --- a/src/occ_405/firdata/ecc.c +++ /dev/null @@ -1,272 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/ecc.C $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ - -/*#include */ -#include -#include - -#include -#include - -/** Matrix used for ECC calculation. - * - * Each row of this is the set of data word bits that are used for - * the calculation of the corresponding ECC bit. The parity of the - * bitset is the value of the ECC bit. - * - * ie. ECC[n] = eccMatrix[n] & data - * - * Note: To make the math easier (and less shifts in resulting code), - * row0 = ECC7. HW numbering is MSB, order here is LSB. - * - * These values come from the HW design of the ECC algorithm. - */ -static uint64_t eccMatrix[] = { - /*0000000000000000111010000100001000111100000011111001100111111111 */ - 0x0000e8423c0f99ff, - /*0000000011101000010000100011110000001111100110011111111100000000 */ - 0x00e8423c0f99ff00, - /*1110100001000010001111000000111110011001111111110000000000000000 */ - 0xe8423c0f99ff0000, - /*0100001000111100000011111001100111111111000000000000000011101000 */ - 0x423c0f99ff0000e8, - /*0011110000001111100110011111111100000000000000001110100001000010 */ - 0x3c0f99ff0000e842, - /*0000111110011001111111110000000000000000111010000100001000111100 */ - 0x0f99ff0000e8423c, - /*1001100111111111000000000000000011101000010000100011110000001111 */ - 0x99ff0000e8423c0f, - /*1111111100000000000000001110100001000010001111000000111110011001 */ - 0xff0000e8423c0f99 -}; - -/** Syndrome calculation matrix. - * - * Maps syndrome to flipped bit. - * - * To perform ECC correction, this matrix is a look-up of the bit - * that is bad based on the binary difference of the good and bad - * ECC. This difference is called the "syndrome". - * - * When a particular bit is on in the data, it cause a column from - * eccMatrix being XOR'd into the ECC field. This column is the - * "effect" of each bit. If a bit is flipped in the data then its - * "effect" is missing from the ECC. You can calculate ECC on unknown - * quality data and compare the ECC field between the calculated - * value and the stored value. If the difference is zero, then the - * data is clean. If the difference is non-zero, you look up the - * difference in the syndrome table to identify the "effect" that - * is missing, which is the bit that is flipped. - * - * Notice that ECC bit flips are recorded by a single "effect" - * bit (ie. 0x1, 0x2, 0x4, 0x8 ...) and double bit flips are identified - * by the UE status in the table. - * - * Bits are in MSB order. - */ -static uint8_t syndromeMatrix[] = { - ECC_GD, ECC_E7, ECC_E6, ECC_UE, ECC_E5, ECC_UE, ECC_UE, 47, - ECC_E4, ECC_UE, ECC_UE, 37, ECC_UE, 35, 39, ECC_UE, - ECC_E3, ECC_UE, ECC_UE, 48, ECC_UE, 30, 29, ECC_UE, - ECC_UE, 57, 27, ECC_UE, 31, ECC_UE, ECC_UE, ECC_UE, - ECC_E2, ECC_UE, ECC_UE, 17, ECC_UE, 18, 40, ECC_UE, - ECC_UE, 58, 22, ECC_UE, 21, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, 16, 49, ECC_UE, 19, ECC_UE, ECC_UE, ECC_UE, - 23, ECC_UE, ECC_UE, ECC_UE, ECC_UE, 20, ECC_UE, ECC_UE, - ECC_E1, ECC_UE, ECC_UE, 51, ECC_UE, 46, 9, ECC_UE, - ECC_UE, 34, 10, ECC_UE, 32, ECC_UE, ECC_UE, 36, - ECC_UE, 62, 50, ECC_UE, 14, ECC_UE, ECC_UE, ECC_UE, - 13, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, 61, 8, ECC_UE, 41, ECC_UE, ECC_UE, ECC_UE, - 11, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - 15, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, ECC_UE, 12, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_E0, ECC_UE, ECC_UE, 55, ECC_UE, 45, 43, ECC_UE, - ECC_UE, 56, 38, ECC_UE, 1, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, 25, 26, ECC_UE, 2, ECC_UE, ECC_UE, ECC_UE, - 24, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, 28, ECC_UE, - ECC_UE, 59, 54, ECC_UE, 42, ECC_UE, ECC_UE, 44, - 6, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - 5, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, 63, 53, ECC_UE, 0, ECC_UE, ECC_UE, ECC_UE, - 33, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - 3, ECC_UE, ECC_UE, 52, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - 7, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, 60, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, ECC_UE, ECC_UE, ECC_UE, 4, ECC_UE, ECC_UE, ECC_UE, - ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, -}; - -/** Returns the parity of x, i.e. the number of 1-bits in x modulo 2. - * Replacement for __builtin_parityl - */ -uint8_t parity_check( uint64_t i_data ) -{ - int ones = 0; - size_t x; - for( x=0; x<(sizeof(i_data)*8); x++ ) - { - if( i_data & (0x8000000000000000ull >> x) ) - { - ones++; - } - } - return ones%2; -} - -/** Create the ECC field corresponding to a 8-byte data field - * - * @param[in] i_data - The 8 byte data to generate ECC for. - * @return The 1 byte ECC corresponding to the data. - */ -uint8_t generateECC(uint64_t i_data) -{ - uint8_t result = 0; - - int i = 0; - for (i = 0; i < 8; i++) - { - result |= (parity_check(eccMatrix[i] & i_data) << i); - } - - return result; -} - -/** Verify the data and ECC match or indicate how they are wrong. - * - * @param[in] i_data - The data to check ECC on. - * @param[in] i_ecc - The [supposed] ECC for the data. - * - * @return eccBitfield or 0-64. - * - * @retval GD - Indicates the data is good (matches ECC). - * @retval UE - Indicates the data is uncorrectable. - * @retval all others - Indication of which bit is incorrect. - */ -uint8_t verifyECC(uint64_t i_data, uint8_t i_ecc) -{ - return syndromeMatrix[generateECC(i_data) ^ i_ecc]; -} - -/** Correct the data and/or ECC. - * - * @param[in,out] io_data - Data to check / correct. - * @param[in,out] io_ecc - ECC to check / correct. - * - * @return eccBitfield or 0-64. - * - * @retval GD - Data is good. - * @retval UE - Data is uncorrectable. - * @retval all others - which bit was corrected. - */ -uint8_t correctECC(uint64_t* io_data, uint8_t* io_ecc) -{ - uint8_t badBit = verifyECC(*io_data, *io_ecc); - - if ((badBit != ECC_GD) && (badBit != ECC_UE)) /* Good is done, UE is hopeless. */ - { - /* Determine if the ECC or data part is bad, do bit flip. */ - if (badBit >= ECC_E7) - { - *io_ecc ^= (1 << (badBit - ECC_E7)); - } - else - { - *io_data ^= (1ul << (63 - badBit)); - } - } - return badBit; -} - -void injectECC(const uint8_t* i_src, - size_t i_srcSz, - uint8_t* o_dst) -{ - assert(0 == (i_srcSz % sizeof(uint64_t))); - - size_t i = 0; - size_t o = 0; - for(i = 0, o = 0; - i < i_srcSz; - i += sizeof(uint64_t), o += sizeof(uint64_t) + sizeof(uint8_t)) - { - /* Read data word, copy to destination. */ - uint64_t data = *((const uint64_t*)(&i_src[i])); - *((uint64_t*)(&o_dst[o])) = data; - data = be64toh(data); - - /* Calculate ECC, copy to destination. */ - uint8_t ecc = generateECC(data); - o_dst[o + sizeof(uint64_t)] = ecc; - } -} - -eccStatus removeECC(uint8_t* io_src, - uint8_t* o_dst, size_t i_dstSz) -{ - assert(0 == (i_dstSz % sizeof(uint64_t))); - - eccStatus rc = ECC_CLEAN; - - size_t i = 0, o = 0; - for(i = 0, o = 0; - o < i_dstSz; - i += sizeof(uint64_t) + sizeof(uint8_t), o += sizeof(uint64_t)) - { - /* Read data and ECC parts. */ - uint64_t data = *((uint64_t*)(&io_src[i])); - data = be64toh(data); - uint8_t ecc = io_src[i + sizeof(uint64_t)]; - - /* Calculate failing bit and fix data. */ - uint8_t badBit = correctECC(&data, &ecc); - - /* Return data to big endian. */ - data = htobe64(data); - - /* Perform correction and status update. */ - if (badBit == ECC_UE) - { - rc = ECC_UNCORRECTABLE; - } - else if (badBit != ECC_GD) - { - if (rc != ECC_UNCORRECTABLE) - { - rc = ECC_CORRECTED; - } - *((uint64_t*)(&io_src[i])) = data; - io_src[i + sizeof(uint64_t)] = ecc; - } - - /* Copy fixed data to destination buffer. */ - *((uint64_t*)(&o_dst[o])) = data; - } - - return rc; -} - diff --git a/src/occ_405/firdata/ecc.h b/src/occ_405/firdata/ecc.h deleted file mode 100644 index 12ffe4e..0000000 --- a/src/occ_405/firdata/ecc.h +++ /dev/null @@ -1,76 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/ecc.H $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __PNOR_ECC_H -#define __PNOR_ECC_H - -#include - -/** @file ecc.H - * @brief Interfaces for the P8 8-byte ECC algorithm. - */ - -/** Status for the ECC removal function. */ -typedef uint8_t eccStatus; -#define ECC_CLEAN 0x00 /*< No ECC Error was detected. */ -#define ECC_CORRECTED 0x01 /*< ECC error detected and corrected. */ -#define ECC_UNCORRECTABLE 0x02 /*< ECC error detected and uncorrectable. */ - -/** Bit field identifiers for syndrome calculations. */ -typedef uint8_t eccBitfields; -#define ECC_GD 0xff /*< Good ECC matches. */ -#define ECC_UE 0xfe /*< Uncorrectable. */ -#define ECC_E0 71 /*< Error in ECC bit 0 */ -#define ECC_E1 70 /*< Error in ECC bit 1 */ -#define ECC_E2 69 /*< Error in ECC bit 2 */ -#define ECC_E3 68 /*< Error in ECC bit 3 */ -#define ECC_E4 67 /*< Error in ECC bit 4 */ -#define ECC_E5 66 /*< Error in ECC bit 5 */ -#define ECC_E6 65 /*< Error in ECC bit 6 */ -#define ECC_E7 64 /*< Error in ECC bit 7 */ - -/** Inject ECC into a data stream. - * - * @param[in] i_src - Source data to create ECC on. - * @param[in] i_srcSz - Size in bytes of source data. - * @param[out] o_dst - Destination buffer of data+ECC. - * - * @note i_srcSz must be a multiple of 8 bytes. - */ -void injectECC(const uint8_t* i_src, size_t i_srcSz, - uint8_t* o_dst); - -/** Remove ECC from a data stream. - * - * @param[in,out] io_src - Source data+ECC stream. - * @param[out] o_dst - Destination buffer for data only. - * @param[in] i_dstSz - Size in bytes of destination ((srcSz / 9) * 8). - * - * @note i_dstSz must be a multiple of 8 bytes. - */ -eccStatus removeECC(uint8_t* io_src, - uint8_t* o_dst, size_t i_dstSz); - - -#endif diff --git a/src/occ_405/firdata/firData.c b/src/occ_405/firdata/firData.c deleted file mode 100644 index 299f92b..0000000 --- a/src/occ_405/firdata/firData.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/firData.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -#include - -#include -#include -#include -#include -#include - -/** Keeps track of pointers to register lists in the HOMER data for each target - * type. */ -typedef struct -{ - uint32_t * glbl; /*/< Global registers */ - uint32_t * fir; /*/< Normal FIRs */ - uint32_t * reg; /*/< Normal registers */ - uint64_t * idFir; /*/< Indirect-SCOM FIRs */ - uint64_t * idReg; /*/< Indirect-SCOM registers */ -} FirData_ListPointers_t; - -/** Contains pointers and sizes for the HOMER and PNOR data buffers. */ -typedef struct -{ - uint8_t * hBuf; /*/< Pointer to the HOMER data buffer */ - uint32_t maxHBufSize; /*/< Maximum size of the HOMER data buffer */ - HOMER_Data_t * hData; /*/< Pointer to the HOMER header data */ - - uint8_t * pBuf; /*/< Pointer to the PNOR data buffer */ - uint32_t maxPBufSize; /*/< Maximum size of the PNOR data buffer */ - PNOR_Data_t * pData; /*/< Pointer to the PNOR header data */ - uint32_t pBufSize; /*/< Current size of the PNOR data buffer */ - - FirData_ListPointers_t hPtrs[TRGT_MAX]; /*/< Pointers to the reg lists */ - - HOMER_ChipSpecAddr_t * ecDepReg; /*/< EC dependent regs */ - -} FirData_t; - - -/** We move the chiplet exist bit fields into this structure left */ -/** justified for easy checking of the fields with a mask */ -typedef struct -{ - uint32_t xbusMask; - uint32_t obusMask; - uint32_t ecMask; - - uint32_t eqMask; - uint32_t exMask; - uint32_t mcbist_mc_Mask; - uint32_t mcs_mi_Mask; - uint32_t mca_dmi_Mask; - - uint32_t cappMask; - uint32_t pecMask; - uint32_t phbMask; - -} FirData_existBits_t; - -/* Uncomment for additional debug traces */ -#if 0 -#define DEBUG_PRD_CHKSTOP_ANALYSIS -#endif - -/*------------------------------------------------------------------------------ */ - -/** @brief Add generic data to the PNOR buffer. - * @param io_fd The FIR data stuct. - * @param i_data Pointer to the data to add to the buffer. - * @param i_dataSize Size of the data to add to the buffer. - * @return True, if where is no room to add the new data. False, otherwise. - */ -bool FirData_addDataToPnor( FirData_t * io_fd, void * i_data, - uint32_t i_dataSize ) -{ - bool full = (io_fd->maxPBufSize < io_fd->pBufSize + i_dataSize); - - if ( full ) - { - /* Indicate the PNOR data is full. */ - io_fd->pData->full = 1; - } - else - { - /* Copy data to PNOR buffer. */ - memcpy( &io_fd->pBuf[io_fd->pBufSize], i_data, i_dataSize ); - io_fd->pBufSize += i_dataSize; - } - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief SCOMs hardware and adds a normal register to PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param i_addr 32-bit address to SCOM. - * @param o_nonZero True if the value of the register was non-zero. False, - * otherwise. - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addRegToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, uint32_t i_addr, - bool * o_nonZero ) -{ - bool full = false; - - int32_t rc = 0; - PNOR_Reg_t reg = { i_addr, 0 }; - - *o_nonZero = false; - - do - { - rc = SCOM_getScom( i_sTrgt, i_addr, &(reg.val) ); - if ( SUCCESS != rc ) - { - TRAC_ERR( "[FirData_addRegToPnor] t=%d p=%d u=%d rc=%d " - "addr=0x%08x val=0x%08x%08x", i_sTrgt.type, - i_sTrgt.procPos, i_sTrgt.procUnitPos, rc, i_addr, - (uint32_t)(reg.val >> 32), (uint32_t)reg.val ); - - if ( io_pTrgt->scomErrs < PNOR_Trgt_MAX_SCOM_ERRORS ) - io_pTrgt->scomErrs++; - - break; - } - - if ( 0 == reg.val ) break; // Skip zero value registers. - - full = FirData_addDataToPnor( io_fd, ®, sizeof(reg) ); - if ( full ) break; - - *o_nonZero = true; - - if ( io_pTrgt->regs < PNOR_Trgt_MAX_REGS_PER_TRGT ) - io_pTrgt->regs++; - - } while (0); - -#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS - TRAC_INFO(" addToPnor: Type:%d Pos:%d Unit:%d Addr:%X Full:%d", - i_sTrgt.type, i_sTrgt.procPos, i_sTrgt.procUnitPos, - i_addr, full ); -#endif - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief SCOMs hardware and add a indirect-SCOM register to PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param i_sTrgt Target to SCOM. - * @param i_addr 64-bit address to SCOM. - * @param o_nonZero True if the value of the register was non-zero. False, - * otherwise. - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addIdRegToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, uint64_t i_addr, - bool * o_nonZero ) -{ - bool full = false; - - int32_t rc = 0; - PNOR_IdReg_t reg = { i_addr, 0 }; - - *o_nonZero = false; - - do - { - rc = SCOM_getIdScom( i_sTrgt, i_addr, &(reg.val) ); - if ( SUCCESS != rc ) - { - if ( io_pTrgt->scomErrs < PNOR_Trgt_MAX_SCOM_ERRORS ) - io_pTrgt->scomErrs++; - break; - } - - if ( 0 == reg.val ) break; // Skip zero value registers. - - full = FirData_addDataToPnor( io_fd, ®, sizeof(reg) ); - if ( full ) break; - - *o_nonZero = true; - - if ( io_pTrgt->idRegs < PNOR_Trgt_MAX_ID_REGS_PER_TRGT ) - io_pTrgt->idRegs++; - - } while (0); - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief Iterates a list of global registers and adds them to the PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param o_noAttn True, if the global registers showed no active attentions - * on the target. False, otherwise. - * @param i_chipStruct Provides chipType and ecLevel we need - * for EC dependent regs - * - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addGlblsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, bool * o_noAttn, - HOMER_Chip_t *i_chipStruct ) -{ - bool full = false; - bool l_isAnyGlobal = false; /* true when we find global reg */ - bool l_isAnyNonZero = false; /* true if ATTN is active on any reg */ - - uint8_t t = i_sTrgt.type; - uint8_t cnt = io_fd->hData->regCounts[t][REG_GLBL]; - - uint32_t i = 0; - - uint32_t addr = 0; - bool nonZero = false; - - *o_noAttn = false; /* Must be false if there are no global regs. */ - - if ( 0 != cnt ) - { - /** If we get here, we have GLOBALS for this target **/ - l_isAnyGlobal = true; - - for ( i = 0; i < cnt; i++ ) - { - addr = io_fd->hPtrs[t].glbl[i]; - nonZero = false; - - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, - &nonZero ); - if ( full ) break; - - if ( nonZero ) l_isAnyNonZero = true; - } - } - - - /** Handle EC dependent registers, if any */ - HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; - cnt = io_fd->hData->ecDepCounts; - - /** We have a structure with one element for each EC dep address. */ - /** Need to loop thru and verify we have same regType among */ - /** other things prior to using the address. */ - for ( i = 0; i < cnt; i++ ) - { -#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS - TRAC_INFO(" addGlblsToPnor In/Array: chipType:%X::%X trgType:%X::%X" - " regType:%X::%X ecLevel %X::%X", - i_chipStruct->chipType, l_ecAddrtPtr->chipType, - t, l_ecAddrtPtr->trgtType, - REG_GLBL, l_ecAddrtPtr->regType, - i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); -#endif - - /** Need same chipType (nimbus,cumulus,etc..), same target type, */ - /** same register type and EC level must match too */ - if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && - (l_ecAddrtPtr->trgtType == t ) && - (l_ecAddrtPtr->regType == REG_GLBL) && - (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) - ) - { - /** If we get here, we have GLOBALS for this target **/ - l_isAnyGlobal = true; - - /* address is right justified in 64 bits */ - addr = (uint32_t)(l_ecAddrtPtr->address); - nonZero = false; - - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, - &nonZero ); - if ( full ) break; - - if ( nonZero ) l_isAnyNonZero = true; - } /* end if we found an EC dep reg */ - - /* prep pointer for next element (if any) */ - l_ecAddrtPtr++; - - } /** end EC dependent reg loop */ - - /* If we have no GLOBALS, we want to collect other regs */ - /* so then we want to return 'attn is active)'. */ - /* If we have GLOBALS, then we need non-zero reg to */ - /* collect the rest of the regs (attn is active). */ - if ( (true == l_isAnyGlobal) && (false == l_isAnyNonZero) ) - { - /* This indicates we won't collect additional regs */ - *o_noAttn = true; /* starts out as false */ - } - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief Iterates a list of FIRs and adds them to the PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param i_chipStruct Provides chipType and ecLevel we need - * for EC dependent regs - * - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addFirsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, - HOMER_Chip_t *i_chipStruct ) -{ - bool full = false; - - uint8_t t = i_sTrgt.type; - uint8_t cnt = io_fd->hData->regCounts[t][REG_FIR]; - - uint32_t i = 0; - - uint32_t addr = 0; - bool nonZero = false; - bool tmp = false; /* ignored, not used */ - - for ( i = 0; i < cnt; i++ ) - { - addr = io_fd->hPtrs[t].fir[i]; - nonZero = false; - - /* Add FIR */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &nonZero ); - if ( full ) break; - - /* Add MASK */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 3, &tmp ); - if ( full ) break; - - if ( nonZero ) - { - /* Add ACT0 */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 6, - &tmp ); - if ( full ) break; - - /* Add ACT1 */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 7, - &tmp ); - if ( full ) break; - } - } - - - /** Handle EC dependent registers, if any */ - HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; - cnt = io_fd->hData->ecDepCounts; - - /** We have a structure with one element for each EC dep address. */ - /** Need to loop thru and verify we have same regType among */ - /** other things prior to using the address. */ - for ( i = 0; i < cnt; i++ ) - { -#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS - TRAC_INFO(" addFirsToPnor In/Array: chipType:%X::%X trgType:%X::%X" - " regType:%X::%X ecLevel %X::%X", - i_chipStruct->chipType, l_ecAddrtPtr->chipType, - t, l_ecAddrtPtr->trgtType, - REG_GLBL, l_ecAddrtPtr->regType, - i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); -#endif - - /** Need same chipType (nimbus,cumulus,etc..), same target type, */ - /** same register type and EC level must match too */ - if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && - (l_ecAddrtPtr->trgtType == t ) && - (l_ecAddrtPtr->regType == REG_FIR) && - (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) - ) - { /* address is right justified in 64 bits */ - addr = (uint32_t)(l_ecAddrtPtr->address); - nonZero = false; - - /* Add FIR */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &nonZero ); - if ( full ) break; - - /* Add MASK */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 3, &tmp ); - if ( full ) break; - - if ( nonZero ) - { - /* Add ACT0 */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 6, - &tmp ); - if ( full ) break; - - /* Add ACT1 */ - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 7, - &tmp ); - if ( full ) break; - } - - } /* end if we found an EC dep reg */ - - /* prep pointer for next element (if any) */ - l_ecAddrtPtr++; - - } /** end EC dependent reg loop */ - - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief Iterates a list of REGs and adds them to the PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param i_chipStruct Provides chipType and ecLevel we need - * for EC dependent regs - * - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addRegsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, - HOMER_Chip_t *i_chipStruct ) -{ - bool full = false; - - uint8_t t = i_sTrgt.type; - uint8_t cnt = io_fd->hData->regCounts[t][REG_REG]; - - uint32_t i = 0; - - uint32_t addr = 0; - bool tmp = false; /* ignored, not used */ - - for ( i = 0; i < cnt; i++ ) - { - addr = io_fd->hPtrs[t].reg[i]; - - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &tmp ); - if ( full ) break; - } - - /** Handle EC dependent registers, if any */ - HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; - cnt = io_fd->hData->ecDepCounts; - - /** We have a structure with one element for each EC dep address. */ - /** Need to loop thru and verify we have same regType among */ - /** other things prior to using the address. */ - for ( i = 0; i < cnt; i++ ) - { -#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS - TRAC_INFO(" addRegsToPnor In/Array: chipType:%X::%X trgType:%X::%X" - " regType:%X::%X ecLevel %X::%X", - i_chipStruct->chipType, l_ecAddrtPtr->chipType, - t, l_ecAddrtPtr->trgtType, - REG_GLBL, l_ecAddrtPtr->regType, - i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); -#endif - - /** Need same chipType (nimbus,cumulus,etc..), same target type, */ - /** same register type and EC level must match too */ - if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && - (l_ecAddrtPtr->trgtType == t ) && - (l_ecAddrtPtr->regType == REG_REG) && - (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) - ) - { /* address is right justified in 64 bits */ - addr = (uint32_t)(l_ecAddrtPtr->address); - - full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, - &tmp ); - if ( full ) break; - } /* end if we found an EC dep reg */ - - /* prep pointer for next element (if any) */ - l_ecAddrtPtr++; - - } /** end EC dependent reg loop */ - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief Iterates a list of IDFIRs and adds them to the PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param i_chipStruct Provides chipType and ecLevel we need - * for EC dependent regs - * - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addIdFirsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, - HOMER_Chip_t *i_chipStruct ) -{ - bool full = false; - - uint8_t t = i_sTrgt.type; - uint8_t cnt = io_fd->hData->regCounts[t][REG_IDFIR]; - - uint32_t i = 0; - - uint64_t addr = 0; - bool nonZero = false; - bool tmp = false; /* ignored, not used */ - - for ( i = 0; i < cnt; i++ ) - { - addr = io_fd->hPtrs[t].idFir[i]; - nonZero = false; - - /* Add FIR */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, - &nonZero ); - if ( full ) break; - - /* Add MASK */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, - addr + 0x300000000ll, &tmp ); - if ( full ) break; - - if ( nonZero ) - { - /* Add ACT0 */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, - addr + 0x600000000ll, &tmp ); - if ( full ) break; - - /* Add ACT1 */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, - addr + 0x700000000ll, &tmp ); - if ( full ) break; - } - } - - - /** Handle EC dependent registers, if any */ - HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; - cnt = io_fd->hData->ecDepCounts; - - /** We have a structure with one element for each EC dep address. */ - /** Need to loop thru and verify we have same regType among */ - /** other things prior to using the address. */ - for ( i = 0; i < cnt; i++ ) - { -#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS - TRAC_INFO(" addIdFirsToPnor In/Array: chipType:%X::%X trgType:%X::%X" - " regType:%X::%X ecLevel %X::%X", - i_chipStruct->chipType, l_ecAddrtPtr->chipType, - t, l_ecAddrtPtr->trgtType, - REG_GLBL, l_ecAddrtPtr->regType, - i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); -#endif - - /** Need same chipType (nimbus,cumulus,etc..), same target type, */ - /** same register type and EC level must match too */ - if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && - (l_ecAddrtPtr->trgtType == t ) && - (l_ecAddrtPtr->regType == REG_IDFIR) && - (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) - ) - { /* need full 64 bit address here */ - addr = l_ecAddrtPtr->address; - nonZero = false; - - /* Add FIR */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, - &nonZero ); - if ( full ) break; - - /* Add MASK */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, - addr + 0x300000000ll, &tmp ); - if ( full ) break; - - if ( nonZero ) - { - /* Add ACT0 */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, - addr + 0x600000000ll, &tmp ); - if ( full ) break; - - /* Add ACT1 */ - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, - addr + 0x700000000ll, &tmp ); - if ( full ) break; - } - - } /* end if we found an EC dep reg */ - - /* prep pointer for next element (if any) */ - l_ecAddrtPtr++; - - } /** end EC dependent reg loop */ - - return full; -} - -/*------------------------------------------------------------------------------ */ - -/** @brief Iterates a list of IDREGs and adds them to the PNOR. - * @param io_fd The FIR data stuct. - * @param io_pTrgt Pointer to PNOR target. - * @param i_sTrgt SCOM target. - * @param i_chipStruct Provides chipType and ecLevel we need - * for EC dependent regs - * - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addIdRegsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, - SCOM_Trgt_t i_sTrgt, - HOMER_Chip_t *i_chipStruct ) -{ - bool full = false; - - uint8_t t = i_sTrgt.type; - uint8_t cnt = io_fd->hData->regCounts[t][REG_IDREG]; - - uint32_t i = 0; - - uint64_t addr = 0; - bool tmp = false; /* ignored, not used */ - - for ( i = 0; i < cnt; i++ ) - { - addr = io_fd->hPtrs[t].idReg[i]; - - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &tmp ); - if ( full ) break; - } - - - /** Handle EC dependent registers, if any */ - HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; - cnt = io_fd->hData->ecDepCounts; - - /** We have a structure with one element for each EC dep address. */ - /** Need to loop thru and verify we have same regType among */ - /** other things prior to using the address. */ - for ( i = 0; i < cnt; i++ ) - { -#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS - TRAC_INFO(" addIdRegsToPnor In/Array: chipType:%X::%X trgType:%X::%X" - " regType:%X::%X ecLevel %X::%X", - i_chipStruct->chipType, l_ecAddrtPtr->chipType, - t, l_ecAddrtPtr->trgtType, - REG_GLBL, l_ecAddrtPtr->regType, - i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); -#endif - - /** Need same chipType (nimbus,cumulus,etc..), same target type, */ - /** same register type and EC level must match too */ - if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && - (l_ecAddrtPtr->trgtType == t ) && - (l_ecAddrtPtr->regType == REG_IDREG) && - (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) - ) - { /* Using full 64 bit address here */ - addr = l_ecAddrtPtr->address; - - full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &tmp ); - if ( full ) break; - } /* end if we found an EC dep reg */ - - /* prep pointer for next element (if any) */ - l_ecAddrtPtr++; - - } /** end EC dependent reg loop */ - - - return full; -} - - -/*------------------------------------------------------------------------------ */ - -/** @brief Adds a target to the PNOR. - * @param io_fd The FIR data stuct. - * @param i_sTrgt SCOM Target. - * @param o_noAttn True, if the global registers showed no active - * attentions on the target. False, otherwise. - * @param i_chipStruct Provides chipType and ecLevel we need - * for EC dependent regs - * - * @return True if the PNOR buffer is full, false if there was room. - */ -bool FirData_addTrgtToPnor( FirData_t * io_fd, SCOM_Trgt_t i_sTrgt, - bool * o_noAttn, HOMER_Chip_t *i_chipStruct ) -{ - bool full = false; - - PNOR_Trgt_t * pTrgt = (PNOR_Trgt_t *)(&io_fd->pBuf[io_fd->pBufSize]); - - PNOR_Trgt_t tmp_pTrgt = PNOR_getTrgt( i_sTrgt.type, i_sTrgt.procPos, - i_sTrgt.procUnitPos ); - - *o_noAttn = false; /* Must be false if there are no global regs. */ - - TRAC_IMP( "FIRDATA: t=%d p=%d u=%d FSI=0x%08x isM=%c", i_sTrgt.type, - i_sTrgt.procPos, i_sTrgt.procUnitPos, i_sTrgt.fsiBaseAddr, - i_sTrgt.isMaster ? 'T' : 'F' ); - - do - { - /* Add the target info to PNOR. */ - full = FirData_addDataToPnor( io_fd, &tmp_pTrgt, sizeof(tmp_pTrgt) ); - if ( full ) break; - - /* Update the number of targets in the PNOR data. */ - io_fd->pData->trgts++; - - /* NOTE: Must add all regular registers (REG_GLBL, REG_FIR, REG_REG) - * before all indirect-SCOM registers. Also, must check REG_GLBL - * registers first to determine whether it is necessary to do the - * other registers. */ - - /* Add the GLBLs. */ - full = FirData_addGlblsToPnor( io_fd, pTrgt, i_sTrgt, o_noAttn, i_chipStruct ); - if ( full || *o_noAttn ) break; - - /* Add the FIRs. */ - full = FirData_addFirsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); - if ( full ) break; - - /* Add the REGs. */ - full = FirData_addRegsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); - if ( full ) break; - - /* Add the IDFIRs. */ - full = FirData_addIdFirsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); - if ( full ) break; - - /* Add the IDREGs. */ - full = FirData_addIdRegsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); - if ( full ) break; - - } while (0); - - return full; -} - - -/*------------------------------------------------------------------------------ */ - -/** @brief Iterates through configured targets and adds the data to PNOR. - * @param io_fd The FIR data stuct. - */ -void FirData_addTrgtsToPnor( FirData_t * io_fd ) -{ - bool full = false; - bool noAttn = false; - - uint8_t p = 0; - uint8_t u = 0; - uint8_t l_unit = 0; - - bool isM = false; - uint32_t fsi = 0; - - SCOM_Trgt_t sTrgt; - FirData_existBits_t l_existBits; - - do - { - memset(&l_existBits, 0x00, sizeof(FirData_existBits_t) ); - - /* Point past HOMER header to first chiplet info */ - /* The HOMER_Data_t struct may have some padding added after the struct - * to ensure the HOMER_Chip_t structs are 4-byte word aligned. */ - uint32_t sz_word = sizeof(uint32_t); - uint32_t pad = (sz_word - (sizeof(HOMER_Data_t) % sz_word)) % sz_word; - uint8_t *l_bytePtr = io_fd->hBuf + sizeof(HOMER_Data_t) + pad; - HOMER_Chip_t *l_chipPtr = NULL; - - TRAC_INFO("AddTgtsMain:numChips:%d", io_fd->hData->chipCount); - - /* Iterate ALL CHIPs */ - for ( p = 0; p < io_fd->hData->chipCount; p++ ) - { - l_chipPtr = (HOMER_Chip_t *)l_bytePtr; - - /* get FSI base address and chip position (proc or centaur) */ - fsi = l_chipPtr->fsiBaseAddr; - p = l_chipPtr->chipPos; - - TRAC_INFO( " AddTgtsMain:ChipType:%d ChipNumber:%d", - l_chipPtr->chipType, p ); - - /* Is this a PROC or Centaur chip ? */ - if ( (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) || - (HOMER_CHIP_CUMULUS == l_chipPtr->chipType) ) - { - /* To access the 'chiplet exist' structure */ - l_bytePtr += sizeof(HOMER_Chip_t); - - /* 'Existing chiplet area' varies in size */ - if (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) - { - HOMER_ChipNimbus_t *l_nimExistBitPtr = - (HOMER_ChipNimbus_t *)l_bytePtr; - - /* get master proc indicator */ - isM = l_nimExistBitPtr->isMaster; - - /* Exist bit structure can differ so move to */ - /* common format and left justify for ease of use */ - l_existBits.xbusMask = ((uint32_t)(l_nimExistBitPtr->xbusMask)) - << (32 - MAX_XBUS_PER_PROC); - l_existBits.obusMask = ((uint32_t)(l_nimExistBitPtr->obusMask)) - << (32 - MAX_OBUS_PER_PROC); - l_existBits.ecMask = ((uint32_t)(l_nimExistBitPtr->ecMask)) - << (32 - MAX_EC_PER_PROC); - l_existBits.eqMask = ((uint32_t)(l_nimExistBitPtr->eqMask)) - << (32 - MAX_EQ_PER_PROC); - l_existBits.exMask = ((uint32_t)(l_nimExistBitPtr->exMask)) - << (32 - MAX_EX_PER_PROC); - l_existBits.mcbist_mc_Mask = ((uint32_t)(l_nimExistBitPtr->mcbistMask)) - << (32 - MAX_MCBIST_PER_PROC); - l_existBits.mcs_mi_Mask = ((uint32_t)(l_nimExistBitPtr->mcsMask)) - << (32 - MAX_MCS_PER_PROC); - l_existBits.mca_dmi_Mask = ((uint32_t)(l_nimExistBitPtr->mcaMask)) - << (32 - MAX_MCA_PER_PROC); - l_existBits.cappMask = ((uint32_t)(l_nimExistBitPtr->cappMask)) - << (32 - MAX_CAPP_PER_PROC); - l_existBits.pecMask = ((uint32_t)(l_nimExistBitPtr->pecMask)) - << (32 - MAX_PEC_PER_PROC); - l_existBits.phbMask = ((uint32_t)(l_nimExistBitPtr->phbMask)) - << (32 - MAX_PHB_PER_PROC); - - /* advance our pointer to next chip type */ - l_bytePtr += sizeof(HOMER_ChipNimbus_t); - - } /* if nimbus */ - else if (HOMER_CHIP_CUMULUS == l_chipPtr->chipType) - { - HOMER_ChipCumulus_t *l_cumExistBitPtr = - (HOMER_ChipCumulus_t *)l_bytePtr; - - /* get master proc indicator */ - isM = l_cumExistBitPtr->isMaster; - - /* Exist bit structure can differ so move to */ - /* common format and left justify for ease of use */ - l_existBits.xbusMask = ((uint32_t)(l_cumExistBitPtr->xbusMask)) - << (32 - MAX_XBUS_PER_PROC); - l_existBits.obusMask = ((uint32_t)(l_cumExistBitPtr->obusMask)) - << (32 - MAX_OBUS_PER_PROC); - l_existBits.ecMask = ((uint32_t)(l_cumExistBitPtr->ecMask)) - << (32 - MAX_EC_PER_PROC); - l_existBits.eqMask = ((uint32_t)(l_cumExistBitPtr->eqMask)) - << (32 - MAX_EQ_PER_PROC); - l_existBits.exMask = ((uint32_t)(l_cumExistBitPtr->exMask)) - << (32 - MAX_EX_PER_PROC); - l_existBits.mcbist_mc_Mask = ((uint32_t)(l_cumExistBitPtr->mcMask)) - << (32 - MAX_MC_PER_PROC); - l_existBits.mcs_mi_Mask = ((uint32_t)(l_cumExistBitPtr->miMask)) - << (32 - MAX_MI_PER_PROC); - l_existBits.mca_dmi_Mask = ((uint32_t)(l_cumExistBitPtr->dmiMask)) - << (32 - MAX_DMI_PER_PROC); - l_existBits.cappMask = ((uint32_t)(l_cumExistBitPtr->cappMask)) - << (32 - MAX_CAPP_PER_PROC); - l_existBits.pecMask = ((uint32_t)(l_cumExistBitPtr->pecMask)) - << (32 - MAX_PEC_PER_PROC); - l_existBits.phbMask = ((uint32_t)(l_cumExistBitPtr->phbMask)) - << (32 - MAX_PHB_PER_PROC); - - /* advance our pointer to next chip type */ - l_bytePtr += sizeof(HOMER_ChipCumulus_t); - } /* else if cumulus */ - - TRAC_INFO( " Masks XBUS:%X OBUS:%X EC:%X EQ:%X EX:%X CAPP:%X PEC:%X PHB:%X", - l_existBits.xbusMask, l_existBits.obusMask, l_existBits.ecMask, - l_existBits.eqMask, l_existBits.exMask, l_existBits.cappMask, - l_existBits.pecMask, l_existBits.phbMask ); - TRAC_INFO( " Masks MCBIST:%X MCS:%X MCA:%X", - l_existBits.mcbist_mc_Mask, l_existBits.mcs_mi_Mask, - l_existBits.mca_dmi_Mask ); - - /* Add this PROC to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_PROC, p, 0, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - /* noAttn is true when we have global regs but none */ - /* indicate an attention is present */ - if ( full ) break; - if ( noAttn ) continue; /* Skip other proc chiplets */ - - - /* gather other chiplets on the processor */ - for ( u = 0; u < MAX_XBUS_PER_PROC; u++ ) - { - /* Check if the XBUS is configured. */ - if ( 0 == (l_existBits.xbusMask & (0x80000000 >> u)) ) continue; - - /* Add this XBUS to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_XBUS, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - } - if ( full ) break; - - /* gather other chiplets on the processor */ - for ( u = 0; u < MAX_OBUS_PER_PROC; u++ ) - { - /* Check if the OBUS is configured. */ - if ( 0 == (l_existBits.obusMask & (0x80000000 >> u)) ) continue; - - /* Add this OBUS to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_OBUS, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - } - if ( full ) break; - - /* gather more proc chiplets */ - for ( u = 0; u < MAX_CAPP_PER_PROC; u++ ) - { - /* Check if the CAPP is configured. */ - if ( 0 == (l_existBits.cappMask & (0x80000000 >> u)) ) continue; - - /* Add this CAPP to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_CAPP, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - } - if ( full ) break; - - /* gather other chiplets on the processor */ - for ( u = 0; u < MAX_PEC_PER_PROC; u++ ) - { - /* Check if the PEC is configured. */ - if ( 0 == (l_existBits.pecMask & (0x80000000 >> u)) ) continue; - - /* Add this PEC to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_PEC, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - if ( noAttn ) continue; /* Skip the rest */ - - /* gather PHB's under the PEC */ - /* ************************** */ - /* PEC0-> PHB0 */ - /* PEC1-> PHB1 PHB2 */ - /* PEC2-> PHB3 PHB4 PHB5 */ - /* ************************** */ - uint32_t l_PhbPos; - - /* u will be 0, l_unit 0 */ - /* u will be 1, l_unit 0 and 1 */ - /* u will be 2, l_unit 0 and 1 and 2 */ - for ( l_unit = 0; l_unit < (u+1); l_unit++ ) - { - l_PhbPos = u + l_unit; - /** When we hit PEC2, need to bump PHB position */ - if ((MAX_PEC_PER_PROC - 1) == u) - { - l_PhbPos++; - } /* if last PEC unit */ - - /* Check if the PHB is configured. */ - if ( 0 == (l_existBits.phbMask & (0x80000000 >> l_PhbPos)) ) continue; - - /* Add this PHB to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_PHB, p, l_PhbPos, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - if ( noAttn ) continue; /* Skip the rest */ - - } /* end for on PHB chiplet */ - if ( full ) break; - - } /* end for on PEC chiplet */ - if ( full ) break; - - /* gather other chiplets on the processor */ - for ( u = 0; u < MAX_EC_PER_PROC; u++ ) - { - /* Check if the EC is configured. */ - if ( 0 == (l_existBits.ecMask & (0x80000000 >> u)) ) continue; - - /* Add this EC to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_EC, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - if ( noAttn ) continue; /* Skip the rest */ - - } /* end for on EC chiplet */ - if ( full ) break; - - /* gather other chiplets on the processor */ - for ( u = 0; u < MAX_EQ_PER_PROC; u++ ) - { - /* Check if the EQ is configured. */ - if ( 0 == (l_existBits.eqMask & (0x80000000 >> u)) ) continue; - - /* Add this EQ to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_EQ, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - if ( noAttn ) continue; /* Skip the rest */ - - /* gather other chiplets on the processor */ - uint32_t l_ExPerEq = (MAX_EX_PER_PROC/MAX_EQ_PER_PROC); - uint32_t l_ExPos; - - for (l_unit=0; l_unit < l_ExPerEq; l_unit++) - { - l_ExPos = (l_ExPerEq * u) + l_unit; - - /* Check if the EX is configured. */ - if ( 0 == (l_existBits.exMask & (0x80000000 >> l_ExPos)) ) continue; - - /* Add this EX to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(TRGT_EX, p, l_ExPos, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - if ( noAttn ) continue; /* Skip the rest */ - - } /* end for on EX chiplet */ - if ( full ) break; - - } /* end for on EQ chiplet */ - if ( full ) break; - - - /* processor type can impact next few units */ - TrgtType_t l_pnorTarget = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? - TRGT_MCBIST : TRGT_MC; - uint32_t l_maxPerProc = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? - MAX_MCBIST_PER_PROC : MAX_MC_PER_PROC; - - TrgtType_t l_pnorTarg2 = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? - TRGT_MCA : TRGT_DMI; - uint32_t l_maxPerProc2 = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? - MAX_MCA_PER_PROC : MAX_DMI_PER_PROC; - - uint32_t l_UnitPerMc = l_maxPerProc2 / l_maxPerProc; - uint8_t l_unitNumber; - - for ( u = 0; u < l_maxPerProc; u++ ) - { - /* Check if MCBIST / MC is configured. */ - if ( 0 == (l_existBits.mcbist_mc_Mask & (0x80000000 >> u)) ) continue; - - /* Add this MCBIST or MC to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(l_pnorTarget, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - if ( noAttn ) continue; /* Skip the rest */ - - /* Grab underlying MCA/DMI chiplet */ - for ( l_unit = 0; l_unit < l_UnitPerMc; l_unit++ ) - { - /* u=0 or 1 while l_unit is 0 thru 3 */ - /* Leading to unit number 0:3 or 4:7 */ - l_unitNumber = l_unit + (u * l_UnitPerMc); - /* Check if the MCA / DMI is configured. */ - if ( 0 == (l_existBits.mca_dmi_Mask & (0x80000000 >> l_unitNumber)) ) continue; - - /* Add this MCA / DMI to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(l_pnorTarg2, p, l_unitNumber, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - - } /* end for on MCA/DMI */ - if ( full ) break; - - } /* end for on MCBIST */ - if ( full ) break; - - - l_pnorTarget = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? - TRGT_MCS : TRGT_MI; - l_maxPerProc = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? - MAX_MCS_PER_PROC : MAX_MI_PER_PROC; - - for ( u = 0; u < l_maxPerProc; u++ ) - { - /* Check if the MCS / MI is configured. */ - if ( 0 == (l_existBits.mcs_mi_Mask & (0x80000000 >> u)) ) continue; - - /* Add this MCS or MI to the PNOR. */ - sTrgt = SCOM_Trgt_getTrgt(l_pnorTarget, p, u, fsi, isM); - full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); - if ( full ) break; - } - if ( full ) break; - - - } /* if processor chip type */ - else if (HOMER_CHIP_CENTAUR == l_chipPtr->chipType) - { - /* HOMER_ChipCentaur_t *l_cenExistBitPtr = - (HOMER_ChipCentaur_t *)l_bytePtr; */ - /* uint32_t l_mbaMask = ((uint32_t) l_cenExistBitPtr->mbaMask) << - (sizeof(uint32_t) - MAX_MBA_PER_MEMBUF) */ - - /* we have Centaur chipPos in 'p' and fsi address in 'fsi' */ - - /* add this centaur later and iterate thru l_mbaMask */ - /* don't need for initial support */ - /* TODO RTC 173614 -- with CUMULUS */ - - /* advance our pointer to next chip type */ - l_bytePtr += sizeof(HOMER_ChipCentaur_t); - - } /* end if centaur chip type */ - else - { - /* unexpected chip type */ - TRAC_ERR( "addTrgtsToPnor saw invalid chip:0x%X", - l_chipPtr->chipType ); - break; - } /* end if centaur chip type */ - - } /* end for on all CHIPS we have in homer data */ - - } while (0); - -} /* end FirData_addTrgtsToPnor */ - -/*------------------------------------------------------------------------------ */ - -/** @brief Initializes the FIR data struct. Does range checking for the HOMER - * data. Initializes the PNOR header data. - * @param io_fd The FIR data stuct. - * @param i_hBuf SRAM pointer to the beginning of the HOMER data buffer. - * This should contain the FIR data information provided by - * PRD that is used to define which registers the OCC will - * need to SCOM. - * @param i_hBufSize Total size of the HOMER data buffer. - * @param i_pBuf SRAM pointer to the beginning of the PNOR data buffer. - * This will be used by this function as a temporary area of - * memory to store the PNOR data before writing that data to - * the PNOR. - * @param i_pBufSize Total size of the PNOR data buffer. - * @return Non-SUCCESS if HOMER or PNOR range checking fails or if an - * internal function fails. SUCCESS otherwise. - */ -int32_t FirData_init( FirData_t * io_fd, - uint8_t * i_hBuf, uint32_t i_hBufSize, - uint8_t * i_pBuf, uint32_t i_pBufSize ) -{ - #define FUNC "[FirData_init] " - - int32_t rc = SUCCESS; - - size_t sz_hData = sizeof(HOMER_Data_t); - size_t sz_pnoNoEcc = 0; - size_t sz_u32 = sizeof(uint32_t); - size_t sz_u64 = sizeof(uint64_t); - - bool full = false; - - uint32_t x[TRGT_MAX][REG_MAX]; - size_t curIdx = 0; - - uint32_t t = TRGT_FIRST; - - uint8_t * reglist = NULL; - - PNOR_Data_t pData = PNOR_getData(); - - do - { - /* Init the struct. */ - io_fd->hBuf = i_hBuf; - io_fd->maxHBufSize = i_hBufSize; - io_fd->hData = (HOMER_Data_t *)i_hBuf; - - io_fd->pBuf = i_pBuf; - io_fd->maxPBufSize = i_pBufSize; - io_fd->pData = (PNOR_Data_t *)i_pBuf; - io_fd->pBufSize = 0; - - memset( io_fd->hPtrs, 0x00, sizeof(io_fd->hPtrs) ); - - /* Check HOMER header data size. */ - if ( io_fd->maxHBufSize < sz_hData ) - { - TRAC_ERR( FUNC"HOMER header data size %d is larger than HOMER " - "data buffer %d", sz_hData, io_fd->maxHBufSize ); - rc = FAIL; - break; - } - - /* Check for valid HOMER data. */ - if ( HOMER_FIR2 != io_fd->hData->header ) - { - break; /* nothing to analyze. */ - } - - /* The actual maximum PNOR size may possibly be less then the PNOR data */ - /* buffer. If so, adjust maximum size. */ - sz_pnoNoEcc = (io_fd->hData->pnorInfo.pnorSize / 9) * 8; - if ( sz_pnoNoEcc < io_fd->maxPBufSize ) - io_fd->maxPBufSize = sz_pnoNoEcc; - - /* Initialize the PNOR header data. */ - full = FirData_addDataToPnor( io_fd, &pData, sizeof(pData) ); - if ( full ) - { - TRAC_ERR( FUNC"Unable to add header to PNOR buffer" ); - rc = FAIL; - break; - } - - /* Copy the IPL state from the HOMER data to the PNOR data. */ - io_fd->pData->iplState = io_fd->hData->iplState; - - /* Get the register list byte indexes in HOMER data buffer */ - memset( x, 0x00, sizeof(x) ); - for ( t = TRGT_FIRST; t < TRGT_MAX; t++ ) - { - x[t][REG_GLBL] = curIdx; - x[t][REG_FIR] = x[t][REG_GLBL] + sz_u32 * io_fd->hData->regCounts[t][REG_GLBL]; - x[t][REG_REG] = x[t][REG_FIR] + sz_u32 * io_fd->hData->regCounts[t][REG_FIR]; - x[t][REG_IDFIR] = x[t][REG_REG] + sz_u32 * io_fd->hData->regCounts[t][REG_REG]; - x[t][REG_IDREG] = x[t][REG_IDFIR] + sz_u64 * io_fd->hData->regCounts[t][REG_IDFIR]; - curIdx = x[t][REG_IDREG] + sz_u64 * io_fd->hData->regCounts[t][REG_IDREG]; - } - - /* Check to make sure the list data is not larger than the available */ - /* Homer buffer. */ - if ( io_fd->maxHBufSize - sz_hData < curIdx ) - { - TRAC_ERR( FUNC"HOMER list size %d is larger than HOMER data " - "buffer %d", curIdx, io_fd->maxHBufSize - sz_hData ); - rc = FAIL; - break; - } - - /* Now, skip chip sections. Note that the HOMER_Data_t struct may have - * some padding added after the struct to ensure the HOMER_Chip_t - * structs are 4-byte word aligned. */ - uint32_t pad = (sz_u32 - (sz_hData % sz_u32)) % sz_u32; - reglist = io_fd->hBuf + sz_hData + pad; - HOMER_Chip_t *l_chiptPtr = NULL; - - /* Need to skip over chip list **/ - uint32_t l_chipNum; - for ( l_chipNum=0; - (l_chipNum < io_fd->hData->chipCount); - l_chipNum++ ) - { - l_chiptPtr = (HOMER_Chip_t *)reglist; - - /* Skip section on chip type, chip position, etc... */ - reglist += sizeof(HOMER_Chip_t); - - /* 'Existing chiplet area' varies in size */ - if (HOMER_CHIP_NIMBUS == l_chiptPtr->chipType) - { - reglist += sizeof(HOMER_ChipNimbus_t); - } - else if (HOMER_CHIP_CUMULUS == l_chiptPtr->chipType) - { - reglist += sizeof(HOMER_ChipCumulus_t); - } - else if (HOMER_CHIP_CENTAUR == l_chiptPtr->chipType) - { - reglist += sizeof(HOMER_ChipCentaur_t); - } - else - { - TRAC_ERR(FUNC"Chiptype is invalid %X ", l_chiptPtr->chipType); - rc = FAIL; - break; - } - - } /* end for loop skipping chip info sections */ - - - /* Now, get the pointers for each list. */ - for ( t = TRGT_FIRST; t < TRGT_MAX; t++ ) - { - (io_fd->hPtrs[t]).glbl = (uint32_t *)(reglist + x[t][REG_GLBL] ); - (io_fd->hPtrs[t]).fir = (uint32_t *)(reglist + x[t][REG_FIR] ); - (io_fd->hPtrs[t]).reg = (uint32_t *)(reglist + x[t][REG_REG] ); - (io_fd->hPtrs[t]).idFir = (uint64_t *)(reglist + x[t][REG_IDFIR]); - (io_fd->hPtrs[t]).idReg = (uint64_t *)(reglist + x[t][REG_IDREG]); - } - - /* Set EC level dep reg list ptr - at very end of list */ - io_fd->ecDepReg = (HOMER_ChipSpecAddr_t *)(reglist + curIdx); - - - } while (0); - - return rc; - - #undef FUNC -} - -/*------------------------------------------------------------------------------ */ -/* External functions */ -/*------------------------------------------------------------------------------ */ - -int32_t FirData_captureCsFirData( uint8_t * i_hBuf, uint32_t i_hBufSize, - uint8_t * i_pBuf, uint32_t i_pBufSize ) -{ - #define FUNC "[FirData_captureCsFirData] " - - int32_t rc = SUCCESS; - - do - { - /* Init the FIR data struct. */ - FirData_t fd; - rc = FirData_init( &fd, i_hBuf, i_hBufSize, i_pBuf, i_pBufSize ); - if ( SUCCESS != rc ) - { - TRAC_ERR( FUNC"Failed to init FIR data" ); - break; - } - - /* Check for valid HOMER data. */ - if ( HOMER_FIR2 != fd.hData->header ) - { - TRAC_ERR( FUNC"No HOMER data detected: header=0x%08x", - fd.hData->header ); - break; /* nothing to analyze. */ - } - - /* Start adding register data to PNOR for each target. */ - FirData_addTrgtsToPnor( &fd ); - - /* Write Buffer to PNOR */ -/* TODO: enable when function is supported. - rc = PNOR_writeFirData( fd.hData->pnorInfo, fd.pBuf, fd.pBufSize ); - if ( SUCCESS != rc ) - { - TRAC_ERR( FUNC"Failed to process FIR data" ); - break; - } -*/ - - } while (0); - - if ( SUCCESS != rc ) - { - TRAC_ERR( FUNC"Failed: i_hBuf=%p, i_hBufSize=0x%08x, i_pBuf=%p, " - "i_pBufSize=%08x", i_hBuf, i_hBufSize, i_pBuf, i_pBufSize ); - } - - return rc; - - #undef FUNC -} - diff --git a/src/occ_405/firdata/firData.h b/src/occ_405/firdata/firData.h deleted file mode 100644 index f1475db..0000000 --- a/src/occ_405/firdata/firData.h +++ /dev/null @@ -1,48 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/firData.H $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __firData_h -#define __firData_h - -#include "native.h" - -/** @brief Reads the register list from the HOMER data, SCOMs hardware, and - * stores the register values in PNOR. - * @param i_hBuf SRAM pointer to the beginning of the HOMER data buffer. - * This should contain the FIR data information provided by - * PRD that is used to define which registers the OCC will - * need to SCOM. - * @param i_hBufSize Total size of the HOMER data buffer. - * @param i_pBuf SRAM pointer to the beginning of the PNOR data buffer. - * This will be used by this function as a temporary area - * of memory to store the PNOR data before writing that - * data to the PNOR. - * @param i_pBufSize Total size of the PNOR data buffer. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t FirData_captureCsFirData( uint8_t * i_hBuf, uint32_t i_hBufSize, - uint8_t * i_pBuf, uint32_t i_pBufSize ); - -#endif /* __firData_h */ diff --git a/src/occ_405/firdata/firDataConst_common.h b/src/occ_405/firdata/firDataConst_common.h deleted file mode 100644 index 403a028..0000000 --- a/src/occ_405/firdata/firDataConst_common.h +++ /dev/null @@ -1,132 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/firDataConst_common.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 __firDataConst_common_h -#define __firDataConst_common_h - -/** NOTE: This file is common between OCC and Hosboot. Any change to this file - * must be mirrored to both repositories. Also, this must be C, not C++, - * because OCC strictly uses C. */ - -#include - -/** Target types for all supported targets. */ -/** NOTE: These are used to build the register list in HOMER data */ -/** and also to create the exiting chiplet masks. Hence, */ -/** the numbers assigned here have to match the sequence */ -/** of chiplets in HOMER_ChipNimbus_t, HOMER_ChipCumulus_t, etc. */ -typedef enum -{ - /* NOTE: These will be used as array indexes. */ - TRGT_FIRST = 0, - - /** Common Nimbus/Cumulus types */ - TRGT_PROC = TRGT_FIRST, - TRGT_CAPP, - TRGT_XBUS, - TRGT_OBUS, - TRGT_PEC, - TRGT_PHB, - TRGT_EQ, - TRGT_EX, - TRGT_EC, - - /* Nimbus only */ - TRGT_MCBIST, - TRGT_MCS, - TRGT_MCA, - - /* Cumulus only */ - /* NOTE: Nimbus and Cumulus cannot be used at the same time. So we can have - * These array indexes overlap to save space. */ - TRGT_MC = TRGT_MCBIST, - TRGT_MI, - TRGT_DMI, - - /* Centaur only */ - TRGT_MEMBUF, - TRGT_MBA, - - TRGT_MAX, - -} TrgtType_t; - -/** Boundary/position ranges for each target type. */ -typedef enum -{ - /* Common Nimbus/Cumulus */ - MAX_PROC_PER_NODE = 8, - MAX_CAPP_PER_PROC = 2, - MAX_XBUS_PER_PROC = 3, /* Nimbus 1 and 2, Cumulus 0, 1, and 2 */ - MAX_OBUS_PER_PROC = 4, /* Nimbus 0 and 3, Cumulus 0, 1, 2, and 3 */ - MAX_PEC_PER_PROC = 3, - MAX_PHB_PER_PROC = 6, - MAX_EQ_PER_PROC = 6, - MAX_EX_PER_PROC = 12, - MAX_EC_PER_PROC = 24, - - /** Nimbus only */ - MAX_MCBIST_PER_PROC = 2, - MAX_MCS_PER_PROC = 4, - MAX_MCA_PER_PROC = 8, - - /** Cumulus only */ - MAX_MC_PER_PROC = 2, - MAX_MI_PER_PROC = 4, - MAX_DMI_PER_PROC = 8, - - /** Centaur only */ - MAX_MEMBUF_PER_PROC = 8, - MAX_MEMBUF_PER_NODE = MAX_MEMBUF_PER_PROC * MAX_PROC_PER_NODE, - MAX_MBA_PER_MEMBUF = 2, - MAX_MBA_PER_PROC = MAX_MEMBUF_PER_PROC * MAX_MBA_PER_MEMBUF, - -} TrgtPos_t; - -/** All register types. */ -typedef enum -{ - /* NOTE: These will be used as array indexes. */ - REG_FIRST = 0, - - REG_GLBL = REG_FIRST, /* 32-bit addresses, 64-bit value */ - REG_FIR, /* 32-bit addresses, 64-bit value */ - REG_REG, /* 32-bit addresses, 64-bit value */ - REG_IDFIR, /* 64-bit addresses, 32-bit value */ - REG_IDREG, /* 64-bit addresses, 32-bit value */ - - REG_MAX, - -} RegType_t; - -/** Indicates the state of the machine when the checkstop occurred. */ -typedef enum -{ - FIRDATA_STATE_RUNTIME = 0, - FIRDATA_STATE_IPL = 1, - -} IplState_t; - -#endif /* __firDataConst_common_h */ diff --git a/src/occ_405/firdata/fir_data_collect.c b/src/occ_405/firdata/fir_data_collect.c deleted file mode 100644 index a2af34f..0000000 --- a/src/occ_405/firdata/fir_data_collect.c +++ /dev/null @@ -1,166 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/fir_data_collect.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - - -#include -#include -#include -#include -#include "tpc_firmware_registers.h" -#include "tpc_register_addresses.h" -#include -#include -#include - -FIR_HEAP_BUFFER(uint8_t G_fir_heap[FIR_HEAP_SECTION_SIZE]); -FIR_PARMS_BUFFER(uint8_t G_fir_data_parms[FIR_PARMS_SECTION_SIZE]); -uint32_t G_fir_master = FIR_OCC_NOT_FIR_MASTER; - -/* - * Function Specification - * - * Name: fir_data_collect - * - * Description: Collects FIR data on checkstop. - * - * End Function Specification - */ -void fir_data_collect(void) -{ - - int32_t l_rc = 0; - - // Homer data section and size - uint8_t *l_hBuf = (uint8_t*) FIR_PARMS_SECTION_BASE_ADDRESS; - uint32_t l_hBufSize = HOMER_FIR_PARM_SIZE; - // PNOR working buffer in SRAM and size - uint8_t *l_pBuf = (uint8_t*) FIR_HEAP_SECTION_BASE_ADDRESS; - uint32_t l_pBufSize = FIR_HEAP_SECTION_SIZE; - - l_rc = FirData_captureCsFirData(l_hBuf, - l_hBufSize, - l_pBuf, - l_pBufSize); - - // Trace the rc only, error logs cannot be collected in this state - TRAC_IMP("Checkstop FIR data capture completed with rc=%d", l_rc); -} - - -/* - * Function Specification - * - * Name: pnor_access_ok - * - * Description: Determines if it is ok for this OCC to access the PNOR. - * - * End Function Specification - */ -// TODO: This code is not allowed currently, as it relies on performing scom operations. -#if 0 -bool pnor_access_allowed(void) -{ - /* BMC ownership of the PNOR is indicated by bit 18 in TPC_GP0 */ - int l_rc = 0; - tpc_gp0_t l_tp_gp0_read; - bool l_access_allowed = FALSE; - - l_tp_gp0_read.words.high_order = 0x00000000; - l_tp_gp0_read.words.low_order = 0x00000000; - - l_rc = getscom_ffdc(TPC_GP0, (uint64_t *)&l_tp_gp0_read, NULL); - - if (l_rc == 0) - { - if ((l_tp_gp0_read.words.high_order & TPC_GP0_BIT18_PNOR_OWNER_MASK) == 0) - { - TRAC_INFO("PNOR access allowed at this time"); - l_access_allowed = TRUE; - } - else - { - TRAC_INFO("PNOR access NOT allowed at this time, tpc_gp0.hi = 0x%08x", - l_tp_gp0_read.words.high_order); - - /* @ - * @errortype - * @moduleid FIR_DATA_MID - * @reasoncode INTERNAL_FAILURE - * @userdata1 TPC_GP0 high word - * @userdata4 ERC_PNOR_OWNERSHIP_NOT_AVAILABLE - * @devdesc PNOR access not allowed at this time. - */ - errlHndl_t l_errl = createErrl( - FIR_DATA_MID, /*ModId */ - INTERNAL_FAILURE, /*Reasoncode */ - ERC_PNOR_OWNERSHIP_NOT_AVAILABLE, /*Extended reasoncode */ - ERRL_SEV_INFORMATIONAL, /*Severity */ - NULL, /*Trace Buf */ - DEFAULT_TRACE_SIZE, /*Trace Size */ - l_tp_gp0_read.words.high_order, /*Userdata1 */ - 0 /*Userdata2 */ - ); - - /* Commit log */ - commitErrl(&l_errl); - } - } - else - { - /* getscom failure */ - TRAC_ERR("TPC_GP0 getscom failure rc = 0x%08x", -l_rc ); - - /* @ - * @errortype - * @moduleid FIR_DATA_MID - * @reasoncode INTERNAL_HW_FAILURE - * @userdata1 getscom failure rc - * @userdata4 ERC_GETSCOM_TPC_GP0_FAILURE - * @devdesc Failure determining PNOR ownership. Cannot read TPC_GP0. - */ - errlHndl_t l_errl = createErrl( - FIR_DATA_MID, /*ModId */ - INTERNAL_HW_FAILURE, /*Reasoncode */ - ERC_GETSCOM_TPC_GP0_FAILURE, /*Extended reasoncode */ - ERRL_SEV_PREDICTIVE, /*Severity */ - NULL, /*Trace Buf */ - DEFAULT_TRACE_SIZE, /*Trace Size */ - l_rc, /*Userdata1 */ - 0 /*Userdata2 */ - ); - - /* Callout firmware */ - addCalloutToErrl(l_errl, - ERRL_CALLOUT_TYPE_COMPONENT_ID, - ERRL_COMPONENT_ID_FIRMWARE, - ERRL_CALLOUT_PRIORITY_HIGH); - - /* Commit log */ - commitErrl(&l_errl); - } - - return l_access_allowed; -} -#endif diff --git a/src/occ_405/firdata/fir_data_collect.h b/src/occ_405/firdata/fir_data_collect.h deleted file mode 100644 index c313956..0000000 --- a/src/occ_405/firdata/fir_data_collect.h +++ /dev/null @@ -1,56 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/fir_data_collect.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 _FIR_DATA_COLLECT_H -#define _FIR_DATA_COLLECT_H - -#include - -/* This size has to agree with the size _FIR_PARMS_SECTION_SIZE defined in the */ -/* OCC linker command file. */ -#define FIR_PARMS_SECTION_SIZE 0x1000 -// This size has to agree with the size _FIR_HEAP_SECTION_SIZE defined in the -// OCC linker command file. -#define FIR_HEAP_SECTION_SIZE 0x3000 - -enum fir_master -{ - FIR_OCC_NOT_FIR_MASTER = 0x00000000, - FIR_OCC_IS_FIR_MASTER = 0x00000001 -}; - -extern uint8_t G_fir_data_parms[FIR_PARMS_SECTION_SIZE]; -extern uint8_t G_fir_heap[FIR_HEAP_SECTION_SIZE]; -extern uint32_t G_fir_master; - -#define OCC_SET_FIR_MASTER(_fm_t) G_fir_master = _fm_t -#define OCC_IS_FIR_MASTER() (G_fir_master == FIR_OCC_IS_FIR_MASTER) ? TRUE : FALSE -#define TPC_GP0_BIT18_PNOR_OWNER_MASK 0x00002000 - -void fir_data_collect(void); -bool pnor_access_allowed(void); - -#endif /* _FIR_DATA_COLLECT_H */ diff --git a/src/occ_405/firdata/fsi.c b/src/occ_405/firdata/fsi.c deleted file mode 100644 index 4bf105a..0000000 --- a/src/occ_405/firdata/fsi.c +++ /dev/null @@ -1,152 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/fsi.C $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ - -#include -#include -#include - -#define OPB_REG_CMD 0x00020010 -#define OPB_REG_STAT 0x00020011 -#define OPB_REG_RES 0x00020014 -#define OPB_STAT_BUSY 0x0001000000000000 /**< 15 is the Busy bit */ -#define NS_PER_MSEC (1000000ull) - - -void fsi_recovery() -{ - int32_t rc = SUCCESS; - - /* Clear out OPB error */ - uint64_t scom_data = 0; - scom_data = 0x8000000000000000; /*0=Unit Reset*/ - rc |= xscom_write( OPB_REG_RES, scom_data ); - rc |= xscom_write( OPB_REG_STAT, scom_data ); - - /* Check if we have any errors left */ - rc |= xscom_read( OPB_REG_STAT, &scom_data ); - - TRACFCOMP( "PIB2OPB Status after cleanup = %08X%08X (rc=%d)", - (uint32_t)(scom_data >> 32), (uint32_t)scom_data, rc ); -} - -/** - * @brief Poll for completion of a FSI operation, return data on read - */ -int32_t poll_for_complete( uint32_t * o_val ) -{ - int32_t rc = SUCCESS; - - enum { MAX_OPB_TIMEOUT_NS = 10*NS_PER_MSEC }; /*=10ms */ - - *o_val = 0; - - uint64_t read_data = 0; - uint64_t elapsed_time_ns = 0; - do - { - rc = xscom_read( OPB_REG_STAT, &read_data ); - if ( SUCCESS != rc ) - { - fsi_recovery(); /* Try to recover the engine. */ - return rc; - } - - /* Check for completion. Note: not checking for FSI errors. */ - if ( (read_data & OPB_STAT_BUSY) == 0 ) break; /* Not busy */ - - sleep( 10000 ); /* sleep for 10,000 ns */ - elapsed_time_ns += 10000; - - } while ( elapsed_time_ns <= MAX_OPB_TIMEOUT_NS ); - - if ( MAX_OPB_TIMEOUT_NS < elapsed_time_ns ) - { - TRAC_ERR( "[poll_for_complete] FSI request timed out." ); - return FAIL; - } - - *o_val = (uint32_t)read_data; /* Data in the bottom half. */ - - return rc; -} - -/** - * @brief Read a FSI register - */ -int32_t getfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t * o_val ) -{ - int32_t rc = SUCCESS; - - uint32_t fsi_addr = i_trgt.fsiBaseAddr | i_addr; - - /* setup the OPB command register */ - /* only supporting 4-byte access */ - uint64_t fsi_cmd = fsi_addr | 0x60000000; /* 011=Read Full Word */ - fsi_cmd <<= 32; /* Command is in the upper word of the scom */ - - /* Write the OPB command register to trigger the read */ - rc = xscom_write( OPB_REG_CMD, fsi_cmd ); - if ( SUCCESS != rc ) - { - fsi_recovery(); /* Try to recover the engine. */ - return rc; - } - - /* Poll for complete and get the data back. */ - rc = poll_for_complete( o_val ); - - return rc; -} - -/** - * @brief Write a FSI register - */ -int32_t putfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t i_val ) -{ - int32_t rc = SUCCESS; - - uint32_t fsi_addr = i_trgt.fsiBaseAddr | i_addr; - - /* setup the OPB command register */ - /* only supporting 4-byte access */ - uint64_t fsi_cmd = fsi_addr | 0xE0000000; /* 111=Write Full Word */ - fsi_cmd <<= 32; /* Command is in the upper word of the scom */ - fsi_cmd |= i_val; /* Data is in the bottom 32-bits */ - - /* Write the OPB command register to trigger the read */ - rc = xscom_write( OPB_REG_CMD, fsi_cmd ); - if ( SUCCESS != rc ) - { - fsi_recovery(); /* Try to recover the engine. */ - return rc; - } - - /* Poll for complete */ - uint32_t junk = 0; // Not used. - rc = poll_for_complete( &junk ); - - return rc; -} - diff --git a/src/occ_405/firdata/fsi.h b/src/occ_405/firdata/fsi.h deleted file mode 100644 index 870e47f..0000000 --- a/src/occ_405/firdata/fsi.h +++ /dev/null @@ -1,47 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/fsi.H $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ - -/* Interfaces to read/write FSI registers */ - -#include - -/** - * @brief Read a FSI register. - * @param i_trgt Chip/unit to read from. - * @param i_addr FSI address to read, relative to slave's base address. - * @param o_val Returned value. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t getfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t * o_val ); - -/** - * @brief Write a FSI register. - * @param i_trgt Chip/unit to write to. - * @param i_addr FSI address to write, relative to slave's base address. - * @param o_val Value to write. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t putfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t i_val ); - diff --git a/src/occ_405/firdata/homerData_common.h b/src/occ_405/firdata/homerData_common.h deleted file mode 100644 index 66aa53a..0000000 --- a/src/occ_405/firdata/homerData_common.h +++ /dev/null @@ -1,271 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/homerData_common.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 __homerData_common_h -#define __homerData_common_h - -/** NOTE: This file is common between OCC and Hosboot. Any change to this file - * must be mirrored to both repositories. Also, this must be C, not C++, - * because OCC strictly uses C. */ - -#include -#include - -/** This file is used to define the format of the register list stored in the - * HOMER data that the OCC will use to determine what register data to capture - * in the event of a system checkstop. The data will be stored in the following - * format: - * - * - HOMER_Data_t struct - This contains PNOR information, IPL state, number of - * configured chips, and number of register addresses per target type per - * register type. - * - * - For each configured chip, the following format will be used: - * - HOMER_Chip_t struct - containing FSI base address, chip type, and chip - * position. - * - Immediately following will be a chip struct that is specific to the - * chip type stored in the preceding struct. These vary in size and - * structure depending on the chip type. - * - * - Register address lists - These lists vary in size depending on the number - * of register addresses needed in each list. The list counts are stored in - * HOMER_Data_t::regCounts. Order of the lists must match the array indexes - * of HOMER_Data_t::regCounts, which are specified in TrgtType_t and - * RegType_t. - * - * - Chip specific address list - This is a list of HOMER_ChipSpecAddr_t - * structs and will vary in size depending on the number of register - * addresses that are specific to a certain chip or DD level. The number of - * entries in this list is stored in HOMER_Data_t::ecDepCounts. - * - * IMPORTANT NOTE: All of the structs used here are packed. Therefore, we must - * ensure the variables within the struct are byte aligned. Meaning each - * uint32_t within the struct must be 4-byte aligned and each uint16_t must - * be 2-byte aligned. This also means the structs must always start on a - * 4-bye word boundary to maintain alignment. This is required due to the - * limitations of the PPE42/SRAM hardware. - * - * Note that FIRs and indirect-SCOM FIRs characterize a set of registers to - * capture. In addition to capturing the FIR (or ID FIR), the OCC will need to - * capture the following addresses for each type: - * - FIR - * - MASK (FIR address + 3) - * - ACT0 (FIR address + 6) - * - ACT1 (FIR address + 7) - * - ID FIR - * - ID MASK (ID FIR address + 0x300000000ll) - * - ID ACT0 (ID FIR address + 0x600000000ll) - * - ID ACT1 (ID FIR address + 0x700000000ll) - * Note that not all FIRs have a corresponding WOF register. So any WOFs needed - * for analysis will need to be explicitly listed in the corresponding - * 'Registers' lists. - */ - -typedef enum -{ - HOMER_FIR1 = 0x46495231, /** FIR data version 1 ("FIR1" in ascii) P8 */ - HOMER_FIR2 = 0x46495232, /** FIR data version 1 ("FIR2" in ascii) P9 */ - -} HOMER_Version_t; - -/** PNOR information contained within the HOMER data. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t pnorOffset; /** Physical offset of FIRDATA in PNOR */ - uint32_t pnorSize; /** Maximum size of FIRDATA (includes ECC) */ - uint32_t mmioOffset; /** Address of MMIO access */ - uint32_t norWorkarounds; /** NOR flash vendor */ - -} HOMER_PnorInfo_t; - -/** HOMER data header information containing hardware configurations and - * register counts. */ -/* NOTE: This structure may, or may not, be 4-byte word aligned. It all depends - * on the size of regCounts, which will change based on the number of - * target types and register types we support. When reading/writing this - * data ensure that proper padding has been added after this structure so - * that subsequent structures are 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t header; /** Magic number to indicate valid data and version */ - - uint32_t chipCount : 8; /** Number of configured chips per node */ - uint32_t ecDepCounts : 8; /** Number of regs that are EC dependent */ - uint32_t iplState : 1; /** See IplState_t. */ - uint32_t reserved : 15; - - /** Information regarding the PNOR location and size. */ - HOMER_PnorInfo_t pnorInfo; - - /** Contains number of registers per type for each target type. */ - uint8_t regCounts[TRGT_MAX][REG_MAX]; - -} HOMER_Data_t; - -/** @return An initialized HOMER_Data_t struct. */ -static inline HOMER_Data_t HOMER_getData() -{ - HOMER_Data_t d; memset( &d, 0x00, sizeof(d) ); /* init to zero */ - - d.header = HOMER_FIR2; - - return d; -} - -/*----------------------------------------------------------------------------*/ - -/** Supported chip types. */ -typedef enum -{ - HOMER_CHIP_NIMBUS, /** P9 Nimbus processor chip */ - HOMER_CHIP_CUMULUS, /** P9 Cumulus processor chip */ - HOMER_CHIP_CENTAUR, /** Centaur memory buffer chip */ - -} HOMER_ChipType_t; - -/** Information for each configured chip. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t fsiBaseAddr; /** FSI base address for the chip. */ - - uint32_t chipType : 4; /** Chip type (see HOMER_ChipType_t) */ - uint32_t chipPos : 6; /** Chip position relative to the node. */ - uint32_t chipEcLevel : 8; /** EC level for this chip */ - uint32_t reserved : 14; - -} HOMER_Chip_t; - -/** Used for Registers that have EC level dependencies */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t chipType : 4; /** See HOMER_ChipType_t. */ - uint32_t trgtType : 6; /** See TrgtType_t. */ - uint32_t regType : 4; /** See RegType_t. */ - uint32_t ddLevel : 8; /** A zero value applies to all levels on a chip. */ - uint32_t reserved : 10; /** unused at this time */ - - /** The 32 or 64 bit address (right justified). */ - uint64_t address; - -} HOMER_ChipSpecAddr_t; - -/** @return An initialized HOMER_Chip_t struct. */ -static inline HOMER_Chip_t HOMER_getChip( HOMER_ChipType_t i_type ) -{ - HOMER_Chip_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ - - c.fsiBaseAddr = 0xffffffff; - c.chipType = i_type; - - return c; -} - -/*----------------------------------------------------------------------------*/ - -/** Information specific to a P9 Nimbus processor chip. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t isMaster : 1; /** 1 if this is the master PROC, 0 otherwise */ - uint32_t xbusMask : 3; /** Mask of configured XBUS units (0-2) */ - uint32_t obusMask : 4; /** Mask of configured OBUS units (0-3) */ - uint32_t ecMask : 24; /** Mask of configured EC units (0-23) */ - - uint32_t eqMask : 6; /** Mask of configured EQ units (0-5) */ - uint32_t exMask : 12; /** Mask of configured EX units (0-11) */ - uint32_t mcbistMask : 2; /** Mask of configured MCBIST units (0-1) */ - uint32_t mcsMask : 4; /** Mask of configured MCS units (0-3) */ - uint32_t mcaMask : 8; /** Mask of configured MCA units (0-7) */ - - uint32_t cappMask : 2; /** Mask of configured CAPP units (0-1) */ - uint32_t pecMask : 3; /** Mask of configured PEC units (0-2) */ - uint32_t phbMask : 6; /** Mask of configured PHB units (0-5) */ - uint32_t reserved : 21; - -} HOMER_ChipNimbus_t; - -/** @return An initialized HOMER_ChipNimbus_t struct. */ -static inline HOMER_ChipNimbus_t HOMER_initChipNimbus() -{ - HOMER_ChipNimbus_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ - - return c; -} - -/*----------------------------------------------------------------------------*/ - -/** Information specific to a P9 Cumulus processor chip. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t isMaster : 1; /** 1 if this is the master PROC, 0 otherwise */ - uint32_t xbusMask : 3; /** Mask of configured XBUS units (0-2) */ - uint32_t obusMask : 4; /** Mask of configured OBUS units (0-3) */ - uint32_t ecMask : 24; /** Mask of configured EC units (0-23) */ - - uint32_t eqMask : 6; /** Mask of configured EQ units (0-5) */ - uint32_t exMask : 12; /** Mask of configured EX units (0-11) */ - uint32_t mcMask : 2; /** Mask of configured MC units (0-1) */ - uint32_t miMask : 4; /** Mask of configured MI units (0-3) */ - uint32_t dmiMask : 8; /** Mask of configured DMI units (0-7) */ - - uint32_t cappMask : 2; /** Mask of configured CAPP units (0-1) */ - uint32_t pecMask : 3; /** Mask of configured PEC units (0-2) */ - uint32_t phbMask : 6; /** Mask of configured PHB units (0-5) */ - uint32_t reserved : 21; - -} HOMER_ChipCumulus_t; - -/** @return An initialized HOMER_ChipCumulus_t struct. */ -static inline HOMER_ChipCumulus_t HOMER_initChipCumulus() -{ - HOMER_ChipCumulus_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ - - return c; -} - -/*----------------------------------------------------------------------------*/ - -/** Information specific to a Centaur memory buffer chip. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t mbaMask : 2; /** Mask of configured MBA units (0-1) */ - uint32_t reserved : 30; - -} HOMER_ChipCentaur_t; - -/** @return An initialized HOMER_ChipCentaur_t struct. */ -static inline HOMER_ChipCentaur_t HOMER_initChipCentaur() -{ - HOMER_ChipCentaur_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ - - return c; -} - -#endif /* __homerData_common_h */ diff --git a/src/occ_405/firdata/lpc.c b/src/occ_405/firdata/lpc.c deleted file mode 100644 index ffe2b48..0000000 --- a/src/occ_405/firdata/lpc.c +++ /dev/null @@ -1,391 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/lpc.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -#include -#include -#include -#include - -#define LPCHC_FW_SPACE 0xF0000000 /**< LPC Host Controller FW Space */ -#define LPCHC_MEM_SPACE 0xE0000000 /**< LPC Host Controller Mem Space */ -#define LPCHC_IO_SPACE 0xD0010000 /**< LPC Host Controller I/O Space */ -#define LPCHC_REG_SPACE 0xC0012000 /**< LPC Host Ctlr Register Space */ -#define ECCB_NON_FW_RESET_REG 0x000B0001 /**< ECCB Reset Reg (non-FW) */ - -#define LPC_BASE_REG 0x00090040 /**< LPC Base Address Register */ -#define LPC_CMD_REG 0x00090041 /**< LPC Command Register */ -#define LPC_DATA_REG 0x00090042 /**< LPC Data Register */ -#define LPC_STATUS_REG 0x00090043 /**< LPC Status Register */ - -#define ECCB_CTL_REG 0x000B0020 /**< ECCB Control Reg (FW) */ -#define ECCB_RESET_REG 0x000B0021 /**< ECCB Reset Reg (FW) */ -#define ECCB_STAT_REG 0x000B0022 /**< ECCB Status Reg (FW) */ -#define ECCB_DATA_REG 0x000B0023 /**< ECCB Data Reg (FW) */ - -/* Default Values to set for all operations - 1101.0100.0000.000x.0000.0001.0000.0000.
*/ -#define ECCB_CTL_REG_DEFAULT 0xD400010000000000 - -/* Error bits: wh_todo comments here */ -#define LPC_STAT_REG_ERROR_MASK 0x0000000000000000 /**< Error Bits */ //wh_todo correctly set mask - -/**< OPB LPCM Sync FIR Reg - used to read the FIR*/ -#define OPB_LPCM_FIR_REG 0x01010C00 - -/**< OPB LPCM Sync FIR Reg WOX_AND - used to clear the FIR */ -#define OPB_LPCM_FIR_WOX_AND_REG 0x01010C01 - -/**< OPB LPCM Sync FIR Mask Reg WO_OR - used to set the mask */ -#define OPB_LPCM_FIR_MASK_WO_OR_REG 0x01010C05 - -#define OPB_LPCM_FIR_ERROR_MASK 0xFF00000000000000 /**< Error Bits MASK */ - -/* LPCHC reset-related registers */ -#define OPB_MASTER_LS_CONTROL_REG 0x008 /**data64)); - - if( l_err ) - { - break; - } - - if( o_stat->op_done ) - { - break; - } - - /* Want to start out incrementing by small numbers then get bigger - to avoid a really tight loop in an error case so we'll increase - the wait each time through */ - sleep( LPC_POLL_INCR_NS*(++loop) ); - poll_time += LPC_POLL_INCR_NS * loop; - } while ( poll_time < LPC_POLL_TIME_NS ); - - /* Check for hw errors or timeout if no previous logs */ - if( (l_err == NO_ERROR) && - ((o_stat->data64 & LPC_STAT_REG_ERROR_MASK) - || (!o_stat->op_done)) ) - { - TRAC_ERR( "LpcDD::pollComplete> LPC error or timeout: addr=0x%.8X, status=0x%.8X%.8X", - i_ctrl->address, (uint32_t)(o_stat->data64>>32), (uint32_t)o_stat->data64 ); - l_err = -1; - break; - } - } while(0); - - return l_err; - -} - - -/*========================================================*/ - -errorHndl_t lpc_read( LpcTransType i_type, - uint32_t i_addr, - uint8_t* o_data, - size_t i_size ) -{ - errorHndl_t l_err = NO_ERROR; - int32_t l_addr = 0; - uint64_t l_ret; - uint32_t l_shift_amount; - uint64_t l_temp_data; - - do { - if( o_data == NULL ) - { - TRACFCOMP( "o_data is NULL!" ); - l_err = -2; - break; - } - - - /* Generate the full absolute LPC address */ - l_addr = checkAddr( i_type, i_addr ); - - /* Setup command */ - CommandReg_t lpc_cmd; - lpc_cmd.rnw = 1; //Indicate read not write - lpc_cmd.size = i_size; - lpc_cmd.address = l_addr; - - /* Execute command via Scom */ - SCOM_Trgt_t l_target; - l_target.type = TRGT_PROC; - l_target.isMaster = TRUE; - - //First write the address we want to read from in the - //LPC_CMD_REG scom address - l_err = SCOM_putScom(l_target, LPC_CMD_REG, lpc_cmd.data64); - if(l_err != SUCCESS) - { - TRAC_ERR("lpc_read: SCOM_putScom failed to write to LPC_CMD_REG command rc=0x%08x", - (uint32_t)l_err); - break; - } - - /* Poll for completion */ - StatusReg_t lpc_status; - l_err = pollComplete( &lpc_cmd, &lpc_status ); - if( l_err ) { break; } - - // Read data from the LPC_DATA_REG - l_err = SCOM_getScom(l_target, LPC_DATA_REG, &l_ret); - if(l_err != SUCCESS) - { - TRAC_ERR("lpc_read: SCOM_getScom failed rc=0x%08x", (uint32_t)l_err); - break; - } - - //The scom returns the data in the byte offset represented by last - //3 bits of the address. For example, addr 0x21 will have have data - //starting in byte1 on value returned from scom. - //addr & 0x7 <-- this gives the byte offset - //7 - (addr & 0x7) <-- subratcing from 7 as the data is left aligned - //adding (size - 1) <-- to incorporate reading more than one byte - //multiply by 8 to convert from byte to bits - l_shift_amount = (7 - ((l_addr & 0x7) + (i_size-1))) * 8; - l_temp_data = l_ret >> l_shift_amount; - - //Had some weird problems with memcpy, that's why typecasting - //to the size of data asked. - if (i_size == sizeof(uint8_t)) - { - uint8_t* l_temp_ptr = (uint8_t*)(o_data); - *l_temp_ptr = l_temp_data; - } - else if (i_size == sizeof(uint16_t)) - { - uint16_t* l_temp_ptr = (uint16_t*)(o_data); - *l_temp_ptr = l_temp_data; - } - else if (i_size == sizeof(uint32_t)) - { - uint32_t* l_temp_ptr = (uint32_t*)(o_data); - *l_temp_ptr = l_temp_data; - } - else if (i_size == sizeof(uint64_t)) - { - uint64_t* l_temp_ptr = (uint64_t*)(o_data); - *l_temp_ptr = l_temp_data; - } - else - { - TRAC_ERR("lpc_read: unsupported size length"); - l_err = -1; - break; - } - - } while(0); - - return l_err; -} - -errorHndl_t lpc_write( LpcTransType i_type, - uint32_t i_addr, - uint8_t* i_data, - size_t i_size ) -{ - errorHndl_t l_err = NO_ERROR; - uint32_t l_addr = 0; - uint64_t l_write_data = 0; - uint64_t l_data = 0; - uint32_t l_shift_amount; - - do { - /* Generate the full absolute LPC address */ - l_addr = checkAddr( i_type, i_addr ); - - /* Setup Write Command */ - CommandReg_t lpc_cmd; - lpc_cmd.rnw = 0; //Indicate write - lpc_cmd.size = i_size; - lpc_cmd.address = l_addr; - - /* Setup Write command via Scom */ - SCOM_Trgt_t l_target; - l_target.type = TRGT_PROC; - l_target.isMaster = TRUE; - - //First write the address we want to write to in LPC_CMD_REG - l_err = SCOM_putScom(l_target, LPC_CMD_REG, lpc_cmd.data64); - if(l_err != SUCCESS) - { - TRAC_ERR("ERROR> lpc_write: SCOM_putScom failed to write to LPC_CMD_REG command: rc=0x%08x", - (uint32_t)l_err); - break; - } - - //There were some weird memcpy problems. That's why, typecasting - //to the size of data requested to write - if (i_size == sizeof(uint8_t)) - { - l_write_data = (*i_data); - } - else if (i_size == sizeof(uint16_t)) - { - uint16_t* l_temp_ptr = (uint16_t*)(i_data); - l_write_data = *l_temp_ptr; - } - else if (i_size == sizeof(uint32_t)) - { - uint32_t* l_temp_ptr = (uint32_t*)(i_data); - l_write_data = *l_temp_ptr; - } - else if (i_size == sizeof(uint64_t)) - { - uint64_t* l_temp_ptr = (uint64_t*)(i_data); - l_write_data = *l_temp_ptr; - } - else - { - TRAC_ERR("lpc_write: unsupported size length"); - l_err = -1; - break; - } - - //The scom expects the data in the byte offset represented by last - //3 bits of the address. For example, addr 0x21 will have have data - //starting in byte1 on value returned from scom. - //addr & 0x7 <-- this gives the byte offset - //7 - (addr & 0x7) <-- subratcing from 7 as the data in the scom reg - //is expected to be left aligned - //adding (size - 1) <-- to incorporate reading more than one byte - //multiply by 8 to convert from byte to bits - l_shift_amount = (7 - ((l_addr & 0x7) + (i_size-1))) * 8; - l_data = (l_write_data << l_shift_amount); - - //Write the value to the LPC_DATA_REG - l_err = SCOM_putScom(l_target, LPC_DATA_REG, l_data); - if(l_err != SUCCESS) - { - TRAC_ERR("ERROR> lpc_write: SCOM_putScom failed to write to LPC_DATA_REG data: rc=0x%08x", - (uint32_t)l_err); - break; - } - - /* Poll for completion */ - StatusReg_t lpc_stat; - l_err = pollComplete( &lpc_cmd, &lpc_stat ); - if( l_err ) { break; } - - - } while(0); - - return l_err; -} diff --git a/src/occ_405/firdata/lpc.h b/src/occ_405/firdata/lpc.h deleted file mode 100644 index 177deda..0000000 --- a/src/occ_405/firdata/lpc.h +++ /dev/null @@ -1,55 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/lpc.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 _LPC_H -#define _LPC_H - -#include -#include - -/** - * @enum LPC::TransType - * @brief LPC Transaction Types - */ -typedef enum { - LPC_TRANS_IO = 0, /* LPC IO Space */ - LPC_TRANS_FW = 1, /* LPC Firmware Space */ -} LpcTransType; - -errorHndl_t lpc_read( LpcTransType i_type, - uint32_t i_addr, - uint8_t* o_data, - size_t i_size ); - -errorHndl_t lpc_write( LpcTransType i_type, - uint32_t i_addr, - uint8_t* i_data, - size_t i_size ); - -uint32_t checkAddr(LpcTransType i_type, - uint32_t i_addr); - - -#endif diff --git a/src/occ_405/firdata/native.c b/src/occ_405/firdata/native.c deleted file mode 100644 index d214468..0000000 --- a/src/occ_405/firdata/native.c +++ /dev/null @@ -1,76 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/native.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -#include -#include -#include - -void sleep( SsxInterval i_nanoseconds ) -{ - ssx_sleep(SSX_NANOSECONDS(i_nanoseconds)); -} - -int TRACE_XSCOM=0; - -int32_t xscom_read( uint32_t i_address, uint64_t * o_data ) -{ - int32_t rc = SUCCESS; - - *o_data = 0; - - rc = getscom_ffdc( i_address, o_data, NULL ); - if ( SUCCESS != rc ) - { - TRAC_ERR( "SCOM error in xscom_read wrapper, rc=%d", rc ); - } - - if ( TRACE_XSCOM ) - { - TRACFCOMP( "xscom_read(%08X)=%08X%08X", i_address, - (uint32_t)(*o_data>>32), (uint32_t)(*o_data) ); - } - - return rc; -} - -int32_t xscom_write( uint32_t i_address, uint64_t i_data ) -{ - int32_t rc = SUCCESS; - - rc = putscom_ffdc( i_address, i_data, NULL ); - if ( SUCCESS != rc ) - { - TRAC_ERR( "SCOM error in xscom_write wrapper, rc=%d", rc ); - } - - if ( TRACE_XSCOM ) - { - TRACFCOMP( "xscom_write(%08X)=%08X%08X", i_address, - (uint32_t)(i_data>>32), (uint32_t)i_data); - } - - return rc; -} - diff --git a/src/occ_405/firdata/native.h b/src/occ_405/firdata/native.h deleted file mode 100644 index dd0daa7..0000000 --- a/src/occ_405/firdata/native.h +++ /dev/null @@ -1,98 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/native.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -/* Native functions provided by OCC code */ -#ifndef _NATIVE_H -#define _NATIVE_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -#include "ssx.h" -#ifdef __cplusplus -} -#endif - -#ifndef NO_TRAC_STRINGS - -#ifdef FIRD_DEBUG -#define TRACDCOMP(frmt,args...) DBG_PRINT(frmt,##args) -#else -#define TRACDCOMP(frmt,args...) -#endif // FIRD_DEBUG - -#define TRACFCOMP(frmt,args...) TRACE(&g_des_array[INF_TRACE_DESCRIPTOR],INFO_MRK frmt,##args) - -#else // NO_TRAC_STRINGS - -#define TRACDCOMP(frmt,args...) -#define TRACFCOMP(frmt,args...) - -#endif // NO_TRAC_STRINGS - -typedef uint32_t errorHndl_t; - -#define ENTER_MRK -#define NO_ERROR 0 - -/* Return a number >= input that is aligned up to the next 4-byte boundary */ -#define ALIGN_4(u) (((u) + 0x3ull) & ~0x3ull) - -#define NS_PER_SEC (1000000000ull) - -#undef be64toh -#undef htobe64 -#define be64toh(x) (x) -#define htobe64(x) (x) - -#define KILOBYTE (1024ul) /**< 1 KB */ -#define MEGABYTE (1024 * 1024ul) /**< 1 MB */ -#define GIGABYTE (MEGABYTE * 1024ul) /**< 1 GB */ -#define TERABYTE (GIGABYTE * 1024ul) /**< 1 TB */ - -#define PAGESIZE (4*KILOBYTE) /**< 4 KB */ - -#undef SUCCESS -#define SUCCESS 0 - -#undef FAIL -#define FAIL -1 - -/*================================================ */ - -/* XSCOM Read */ -int32_t xscom_read( uint32_t i_address, uint64_t * o_data ); - -/* XSCOM Write */ -int32_t xscom_write( uint32_t i_address, uint64_t i_data ); - -/* Sleep */ -void sleep( SsxInterval i_nanoseconds ); - - -#endif diff --git a/src/occ_405/firdata/norflash.h b/src/occ_405/firdata/norflash.h deleted file mode 100644 index c4c9cdc..0000000 --- a/src/occ_405/firdata/norflash.h +++ /dev/null @@ -1,154 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/norflash.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 __PNOR_NORFLASH_H -#define __PNOR_NORFLASH_H - -#include -#include - -/** @file norflash.H - * @brief Contains constants related to specific types of - * of NOR flash chips - */ - -/** - * @brief Supported NOR Chip IDs - */ -enum NorChipIDs -{ - UNKNOWN_NOR_ID = 0x12345600, /**< Initial value before read */ - - MICRON_MFG_ID = 0x20000000, /**< Micron Mfg ID */ - MICRON_NOR_ID = 0x20ba2000, /**< Micron NOR */ - - MACRONIX_MFG_ID = 0xC2000000, /**< Macronix Mfg ID */ - MACRONIX32_NOR_ID = 0xC2201A00, /**< Macronix NOR MXxxL51235F */ - MACRONIX64_NOR_ID = 0xC2201900, /**< Macronix NOR MXxxL25635F */ - - /* Note: Simics currently models Micron NOR */ - VPO_NOR_ID = 0x20201800, /**< VPO NOR chip ID */ - FAKE_NOR_ID = 0xBADBAD00, /**< ID used during fake pnor */ - - ID_MASK = 0xFFFFFF00, /**< Only look at 3 bytes */ - MFGID_MASK = 0xFF000000, /**< Manufacturer ID is the first byte */ -}; - -/** - * @brief SPI Config Info - * OP Codes and other MISC info for configuring SFC - */ -typedef enum -{ - SPI_NO_OPCODE = 0x00, /**< Undefined value */ - - /* - * Micron Flash Commands - */ - SPI_MICRON_FLAG_STAT = 0x70, /**< Check write/erase complete */ - SPI_MICRON_CLRFLAG_STAT = 0x50, /**< Clear write/erase Status reg */ - - /* - * Macronix Flash Commands - */ - SPI_MACRONIX_EN4B = 0xB7, /**< Enable Macronix 4-Byte addressing */ - - /* SPI protocol commands */ - SPI_JEDEC_WRITE_STATUS = 0x01, /*WRSR */ - SPI_JEDEC_PAGE_PROGRAM = 0x02, /*PP */ - SPI_JEDEC_READ = 0x03, /*READ */ - SPI_JEDEC_WRITE_DISABLE = 0x04, /*WRDI */ - SPI_JEDEC_READ_STATUS = 0x05, /*RDSR */ - SPI_JEDEC_WRITE_ENABLE = 0x06, /*WREN */ - SPI_JEDEC_FAST_READ = 0x0B, /*FAST_READ */ - SPI_JEDEC_SECTOR_ERASE = 0x20, /*SE */ - SPI_JEDEC_READ_SFDP = 0x5A, /*RDSFDP */ - SPI_JEDEC_CHIPID = 0x9F, /*RDID */ - SPI_JEDEC_BLOCK_ERASE = 0xD8, /*BE */ - -} SpiConfigInfo; - -/** - * @brief General Constants related to flash - */ -enum -{ - PAGE_PROGRAM_BYTES = 256, /***< 256 bytes per PP command */ -}; - - -/** - * Common format of Status Register - */ -typedef union -{ - uint8_t data8; - struct - { - uint8_t writeProtect : 1; /*0 */ - uint8_t rsvd : 5; /*1:5 */ - uint8_t writeEnable : 1; /*6 */ - uint8_t writeInProgress : 1; /*7 */ - }; -} NorStatusReg_t; - -/** - * Flags used to trigger Hardware workarounds - */ -enum -{ - /* No workarounds present */ - HWWK_NO_WORKAROUNDS = 0x00000000, - - /* Must perform 'read flag status' commands after */ - /* any write or erase */ - HWWK_MICRON_WRT_ERASE = 0x00000001, - - /* Must do a read of a low flash address before issuing read */ - /* commands that return more than 1 word of data */ - HWWK_MICRON_EXT_READ = 0x00000002, -}; - - -/* - * Vendor-specific interfaces - */ - -/** - * @brief Check flag status bit on Micron NOR chips - * The current version of Micron parts require the Flag - * Status register be read after a read or erase operation, - * otherwise all future operations won't work.. - * - * @parm i_pnorMbox Pnor Mbox Struct to operate on - * - * @return Error from operation - */ -errorHndl_t micronFlagStatus( pnorMbox_t* i_pnorMbox ); - - - - -#endif diff --git a/src/occ_405/firdata/pnorData_common.h b/src/occ_405/firdata/pnorData_common.h deleted file mode 100644 index 3037e39..0000000 --- a/src/occ_405/firdata/pnorData_common.h +++ /dev/null @@ -1,162 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/pnorData_common.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 __pnorData_common_h -#define __pnorData_common_h - -/** NOTE: This file is common between OCC and Hosboot. Any change to this file - * must be mirrored to both repositories. Also, this must be C, not C++, - * because OCC strictly uses C. */ - -#include -#include - -/** This file is used to define the format of the register data captured by the - * OCC and stored in PNOR. The data will be stored in the following format: - * - * - PNOR_Data_t struct - This has all of the information characterizing how - * many targets that have register data. - * - For each target with register data, the following format will be used: - * - PNOR_Trgt_t struct - Contains the target type, position, and how many - * registers are in the register list. - * - A list of all regular registers (PNOR_Reg_t). - * - A list of all indirect-SCOM registers (PNOR_IdReg_t). - * - * IMPORTANT NOTE: All of the structs used here are packed. Therefore, we must - * ensure the variables within the struct are byte aligned. Meaning each - * uint32_t within the struct must be 4-byte aligned and each uint16_t must - * be 2-byte aligned. This also means the structs must always start on a - * 4-bye word boundary to maintain alignment. This is required due to the - * limitations of the PPE42/SRAM hardware. - * - * The PNOR has limited data space. So the following rules will apply: - * - Any registers with the value of zero will not be captured. - * - Registers with SCOM errors will not be captured, however, the number - * of SCOM errors detected should be stored in each PNOR_Trgt_t struct. - * - If the value of a FIR (or ID FIR) is zero, do not capture the - * associated ACT0 and ACT1 registers. Note that the associated MASK - * register is still needed for FFDC. - * - Each target type may have associated global registers. If none exist, - * simply capture all registers for that type. However, if they do exist - * and the values of ALL the global registers are zero, skip capturing - * the associated registers of the target and any subsequent targets on - * the affinity path. Example, - * - For a MCBIST, skip this MCBIST and all associated MCSs, and MCAs. - * - If for some reason we run out of space in the PNOR, do not SCOM any - * more registers, set the 'full' bit in the PNOR_Data_t struct, and - * write all data successfully captured to PNOR. - */ - -typedef enum -{ - PNOR_FIR1 = 0x46495231, /** FIR data version 1 ("FIR1" in ascii) P8 */ - PNOR_FIR2 = 0x46495232, /** FIR data version 2 ("FIR2" in ascii) P9 */ - -} PNOR_Version_t; - -/** PNOR data header information. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t header; /** Magic number to indicate valid data and version */ - - uint32_t trgts : 12; /** Number of targets with register data */ - uint32_t full : 1; /** 1 if PNOR data is full and data incomplete */ - uint32_t iplState : 1; /** See enum IplState_t */ - uint32_t reserved : 18; - -} PNOR_Data_t; - -/** @return An initialized PNOR_Data_t struct. */ -static inline PNOR_Data_t PNOR_getData() -{ - PNOR_Data_t d; memset( &d, 0x00, sizeof(d) ); /* init to zero */ - - d.header = PNOR_FIR2; - - return d; -}; - -/** These values will match the corresponding bit fields in PNOR_Trgt_t. */ -typedef enum -{ - PNOR_Trgt_MAX_REGS_PER_TRGT = 511, /* Currently expect 266 on the PROC */ - PNOR_Trgt_MAX_ID_REGS_PER_TRGT = 15, /* Currently expect 9 on the MBA */ - PNOR_Trgt_MAX_SCOM_ERRORS = 255, /* Should be plenty */ - -} PNOR_Trgt_RegLimits_t; - -/** Information for each target with SCOM data. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t chipPos : 6; /** Parent chip position relative to the node */ - uint32_t unitPos : 5; /** Unit position relative to the parent chip */ - uint32_t regs : 9; /** Number of normal registers */ - uint32_t idRegs : 4; /** Number of indirect-SCOM registers */ - uint32_t scomErrs : 8; /** Number of SCOM errors detected */ - - uint32_t trgtType : 6; /** Target type. See enum TrgtType_t */ - uint32_t reserved : 26; - -} PNOR_Trgt_t; - -/** @param i_trgtType Target type. See enum TrgtType_t. - * @param i_chipPos Parent chip position relative to the node. - * @param i_unitPos Unit position relative to the parent chip. - * @return An initialized PNOR_Data_t struct. - */ -static inline PNOR_Trgt_t PNOR_getTrgt( uint32_t i_trgtType, uint32_t i_chipPos, - uint32_t i_unitPos ) -{ - PNOR_Trgt_t t; memset( &t, 0x00, sizeof(t) ); /* init to zero */ - - t.trgtType = i_trgtType; - t.chipPos = i_chipPos; - t.unitPos = i_unitPos; - - return t; -}; - -/** Information for a normal register. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint32_t addr; /** 32-bit address */ - uint64_t val; /** 64-bit value */ - -} PNOR_Reg_t; - -/** Information for an indirect-SCOM register. */ -/* NOTE: This structure is 4-byte word aligned. */ -typedef struct __attribute__((packed)) -{ - uint64_t addr; /** 64-bit address */ - uint32_t val; /** 32-bit value */ - -} PNOR_IdReg_t; - -#endif // __pnorData_common_h - diff --git a/src/occ_405/firdata/pnor_mboxdd.c b/src/occ_405/firdata/pnor_mboxdd.c deleted file mode 100644 index 463e950..0000000 --- a/src/occ_405/firdata/pnor_mboxdd.c +++ /dev/null @@ -1,404 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/pnor_mboxdd.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ - -/** - * @file ast_mboxdd.c - * - * @brief Implementation of the PNOR access code on top of AST MBOX protocol - */ - -/*****************************************************************************/ -// I n c l u d e s -/*****************************************************************************/ -#include -#include -#include -#include - -errorHndl_t hwInit(pnorMbox_t* i_pnorMbox) -{ - errorHndl_t l_err = NO_ERROR; - uint8_t* l_data; - int i; - do - { - //Current window starts closed - i_pnorMbox->iv_curWindowOpen = false; - i_pnorMbox->iv_mbox.iv_mboxMsgSeq = 1; - l_err = initializeMbox(); - if (l_err) - { - TRAC_ERR("initializeMbox failed rc:0x%x", l_err); - break; - } - - //Send message to BMC Mbox to get MBOX info - // This message gets the MBOX protocol version - mboxMessage_t l_getInfoMsg; - l_data = (uint8_t*)(&l_getInfoMsg); - for (i = 0; i < BMC_MBOX_DATA_REGS; i++) - { - l_data[i] = 0; - } - - l_getInfoMsg.iv_cmd = MBOX_C_GET_MBOX_INFO; - put8(&l_getInfoMsg, 0, 2); - l_err = doMessage(&i_pnorMbox->iv_mbox, &l_getInfoMsg); - if (l_err) - { - TRAC_ERR("doMessage to ping BMC failed with rc=0x%x", l_err); - break; - } - - i_pnorMbox->iv_protocolVersion = get8(&l_getInfoMsg, 0); - if (i_pnorMbox->iv_protocolVersion == 1) - { - i_pnorMbox->iv_blockShift = 12; - i_pnorMbox->iv_readWindowSize = get16(&l_getInfoMsg, 1) - << i_pnorMbox->iv_blockShift; - i_pnorMbox->iv_writeWindowSize = get16(&l_getInfoMsg, 3) - << i_pnorMbox->iv_blockShift; - } - else - { - i_pnorMbox->iv_blockShift = get8(&l_getInfoMsg, 5); - } - - //Now get the size of the flash - mboxMessage_t l_getSizeMsg; - l_getSizeMsg.iv_cmd = MBOX_C_GET_FLASH_INFO; - l_err = doMessage(&i_pnorMbox->iv_mbox, &l_getSizeMsg); - if (l_err) - { - TRAC_ERR("doMessage failed to get flash size rc=0x%x", l_err); - break; - } - - if (i_pnorMbox->iv_protocolVersion == 1) - { - i_pnorMbox->iv_flashSize = get32(&l_getSizeMsg, 0); - i_pnorMbox->iv_flashEraseSize = get32(&l_getSizeMsg, 4); - } - else - { - i_pnorMbox->iv_flashSize = get16(&l_getSizeMsg, 0) - << i_pnorMbox->iv_blockShift; - i_pnorMbox->iv_flashEraseSize = get16(&l_getSizeMsg, 2) - << i_pnorMbox->iv_blockShift; - } - } while (0); - return l_err; -} - - -errorHndl_t readFlash(pnorMbox_t* i_pnorMbox, - uint32_t i_addr, - size_t i_size, - void* o_data) -{ - errorHndl_t l_err = NO_ERROR; - - do - { - // Ensure we are operating on a 4-byte boundary - if ((i_size % 4 != 0) && (i_addr % 4 != 0)) - { - TRAC_ERR("readFlash: not on 4-byte boundary"); - return FAIL; - } - - while (i_size) - { - uint32_t l_lpcAddr; - size_t l_chunkLen; - - l_err = adjustMboxWindow(i_pnorMbox, - false, - i_addr, - i_size, - &l_lpcAddr, - &l_chunkLen); - - if (l_err) - { - break; - } - - //Directly access LPC to do read/write as BMC is setup now - l_err = lpc_read(LPC_TRANS_FW, l_lpcAddr, o_data, l_chunkLen); - - if (l_err) - { - break; - } - - i_addr += l_chunkLen; - i_size -= l_chunkLen; - o_data = (char*)o_data + l_chunkLen; - } - - if(l_err) - { - break; - } - - } - while(0); - - return l_err; -} - -errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, - uint32_t i_addr, - size_t i_size, - void* i_data) -{ - errorHndl_t l_err = NO_ERROR; - - do - { - // Ensure we are operating on a 4-byte boundary - if (i_size % 4 != 0) - { - TRAC_ERR("writeFlash: not on 4-byte boundary"); - return FAIL; - } - - - errorHndl_t l_flushErr = NO_ERROR; - - while (i_size) - { - uint32_t l_lpcAddr; - size_t l_chunkLen; - - l_err = adjustMboxWindow(i_pnorMbox, - true, - i_addr, - i_size, - &l_lpcAddr, - &l_chunkLen); - - if (l_err) - { - break; - } - - //Directly do LPC access to space pointed to by BMC - l_err = lpc_write(LPC_TRANS_FW, l_lpcAddr, i_data, l_chunkLen); - - if (l_err) - { - break; - } - - //Tell BMC to push data from LPC space into PNOR - l_err = writeDirty(i_pnorMbox, i_addr, l_chunkLen); - - if (l_err) - { - break; - } - - i_addr += l_chunkLen; - i_size -= l_chunkLen; - i_data = (char*)i_data + l_chunkLen; - } - - /* We flush whether we had an error or not. - * - * NOTE: It would help the daemon a lot if we moved that out of here - * and instead had a single flush call over a series of writes. - */ - l_flushErr = writeFlush(i_pnorMbox); - - if ( l_err == NO_ERROR && l_flushErr ) - { - l_err = l_flushErr; - } - - if( l_err ) - { - i_size = 0; - } - - if(l_err) - { - break; - } - - } - while(0); - - return l_err; -} - -errorHndl_t adjustMboxWindow(pnorMbox_t* i_pnorMbox, - bool i_isWrite, uint32_t i_reqAddr, - size_t i_reqSize, uint32_t *o_lpcAddr, - size_t *o_chunkLen) -{ - errorHndl_t l_err = NO_ERROR; - uint32_t l_pos, l_wSize, l_reqSize; - - do - { - /* - * Handle the case where the window is already opened, is of - * the right type and contains the requested address. - */ - uint32_t l_wEnd = i_pnorMbox->iv_curWindowOffset + - i_pnorMbox->iv_curWindowSize; - - /* A read request can be serviced by a write window */ - if (i_pnorMbox->iv_curWindowOpen && - (i_pnorMbox->iv_curWindowWrite || !i_isWrite) && - i_reqAddr >= i_pnorMbox->iv_curWindowOffset && i_reqAddr < l_wEnd) - { - size_t l_gap = (l_wEnd - i_reqAddr); - - *o_lpcAddr = i_pnorMbox->iv_curWindowLpcOffset + - (i_reqAddr - i_pnorMbox->iv_curWindowOffset); - if (i_reqSize <= l_gap) - { - *o_chunkLen = i_reqSize; - } - else - { - *o_chunkLen = l_gap; - } - return NO_ERROR; - } - - /* - * We need a window change, mark it closed first - */ - i_pnorMbox->iv_curWindowOpen = false; - - /* - * Then open the new one at the right position. The required - * alignment differs between protocol versions - */ - if (i_pnorMbox->iv_protocolVersion == 1) - { - l_wSize = i_isWrite ? i_pnorMbox->iv_writeWindowSize - : i_pnorMbox->iv_readWindowSize; - l_pos = i_reqAddr & ~(l_wSize - 1); - l_reqSize = 0; - } - else - { - uint32_t l_blockMask = (1u << i_pnorMbox->iv_blockShift) - 1; - l_wSize = 0; - l_pos = i_reqAddr & ~l_blockMask; - l_reqSize = (((i_reqAddr + i_reqSize) + l_blockMask) & ~l_blockMask) - - l_pos; - } - - mboxMessage_t winMsg; - if (i_isWrite) - { - winMsg.iv_cmd = MBOX_C_CREATE_WRITE_WINDOW; - } - else - { - winMsg.iv_cmd = MBOX_C_CREATE_READ_WINDOW; - } - - put16(&winMsg, 0, l_pos >> i_pnorMbox->iv_blockShift); - put16(&winMsg, 2, l_reqSize >> i_pnorMbox->iv_blockShift); - l_err = doMessage(&i_pnorMbox->iv_mbox, &winMsg); - - if (l_err) - { - break; - } - - i_pnorMbox->iv_curWindowLpcOffset = - (get16(&winMsg,0)) << i_pnorMbox->iv_blockShift; - - if (i_pnorMbox->iv_protocolVersion == 1) - { - i_pnorMbox->iv_curWindowOffset = l_pos; - i_pnorMbox->iv_curWindowLpcOffset = - (get16(&winMsg,0)) << i_pnorMbox->iv_blockShift; - i_pnorMbox->iv_curWindowSize = l_wSize; - } - else - { - i_pnorMbox->iv_curWindowLpcOffset = (get16(&winMsg,0)) - << i_pnorMbox->iv_blockShift; - i_pnorMbox->iv_curWindowSize = (get16(&winMsg,2)) - << i_pnorMbox->iv_blockShift; - i_pnorMbox->iv_curWindowOffset = (get16(&winMsg,4)) - << i_pnorMbox->iv_blockShift; - } - - i_pnorMbox->iv_curWindowOpen = true; - i_pnorMbox->iv_curWindowWrite = i_isWrite; - - } - while (true); - - return l_err; -} - -errorHndl_t writeDirty(pnorMbox_t* i_pnorMbox, uint32_t i_addr, size_t i_size) -{ - /* To pass a correct "size" for both protocol versions, we - * calculate the block-aligned start and end. - */ - uint32_t l_blockMask = (1u << i_pnorMbox->iv_blockShift) - 1; - uint32_t l_start = i_addr & ~l_blockMask; - uint32_t l_end = ((i_addr + i_size) + l_blockMask) & ~l_blockMask; - - mboxMessage_t dirtyMsg; - dirtyMsg.iv_cmd = MBOX_C_MARK_WRITE_DIRTY; - - if (i_pnorMbox->iv_protocolVersion == 1) - { - put16(&dirtyMsg, 0, i_addr >> i_pnorMbox->iv_blockShift); - put32(&dirtyMsg, 2, l_end - l_start); - } - else - { - put16(&dirtyMsg, 0, (i_addr - i_pnorMbox->iv_curWindowOffset) - >> i_pnorMbox->iv_blockShift); - put16(&dirtyMsg, 2, (l_end - l_start) >> i_pnorMbox->iv_blockShift); - } - - return doMessage(&i_pnorMbox->iv_mbox, &dirtyMsg); -} - -errorHndl_t writeFlush(pnorMbox_t* i_pnorMbox) -{ - mboxMessage_t flushMsg; - flushMsg.iv_cmd = MBOX_C_WRITE_FLUSH; - - put16(&flushMsg, 0, 0); - put32(&flushMsg, 2, 0); - - return doMessage(&i_pnorMbox->iv_mbox, &flushMsg); -} diff --git a/src/occ_405/firdata/pnor_mboxdd.h b/src/occ_405/firdata/pnor_mboxdd.h deleted file mode 100644 index ab8f05d..0000000 --- a/src/occ_405/firdata/pnor_mboxdd.h +++ /dev/null @@ -1,135 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/pnor_mboxdd.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __PNOR_MBOX_H -#define __PNOR_MBOX_H - -//NOTE: Protocol Definition is here: -// https://github.com/openbmc/mboxbridge/blob/master/Documentation/mbox_protocol.md - -#include - -/** @file pnor_mbox.h - * @brief Provides the interfaces to the PNOR via the - * MBOX protocol - */ - -typedef struct -{ - astMbox_t iv_mbox; - uint32_t iv_protocolVersion; - //Block size is either 4k (V1) or BMC defined (V2) - // the iv_blockShift parm is a representation of that size - // as a power of 2. Most command and response args are specified - // in some multiple of block size - uint32_t iv_blockShift; - uint32_t iv_flashSize; - uint32_t iv_flashEraseSize; - // Current Window - bool iv_curWindowOpen; // Currently open - bool iv_curWindowWrite; // Write vs Read window - uint32_t iv_curWindowOffset; // Offset into flash - uint32_t iv_curWindowSize; // Size - uint32_t iv_curWindowLpcOffset; // Offset into LPC FW space - // Legacy v1 protocol - uint32_t iv_readWindowSize; - uint32_t iv_writeWindowSize; - -} pnorMbox_t; - -/* - * @brief Do base initialization of the MBOX functionality - * - * @parm[io] io_pnorMbox - Pointer to pnorMbox_t structure - * - * @return Error from operation - */ -errorHndl_t hwInit(pnorMbox_t* i_pnorMbox); - -/* - * @brief Read data from the PNOR flash - * - * @param[in] Pointer to pnorMbox struct - * @parm[in] i_addr PNOR flash Address to read - * @parm[in] i_size Amount of data to read, in bytes. - * @parm[out] o_data Buffer to read data into - * - * @return Error from operation - */ -errorHndl_t readFlash(pnorMbox_t* i_pnorMbox, - uint32_t i_addr, - size_t i_size, - void* o_data); - -/** - * @brief Write data to the PNOR flash - * @param[in] Pointer to pnorMbox struct - * @parm i_addr PNOR flash Address to write - * @parm i_size Amount of data to write, in bytes. - * @parm i_data Buffer containing data to write - * - * @return Error from operation - */ -errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, - uint32_t i_addr, - size_t i_size, - void* i_data); - -/** - * @brief Open a window on the BMC for PNOR accesses - * if necessary and return adjusted LPC address and chunk size - * @param[in] Pointer to pnorMbbox struct - * @parm[in] i_isWrite Write or read window - * @parm[in] i_reqAddr Requested flash offset - * @parm[in] i_reqSize Requested size - * @parm[out] o_lpcAddr LPC offset for the requested offset - * @parm[out] o_chunkLen i_reqSize adjusted to fit in the window - * - * @return Error from operation - */ -errorHndl_t adjustMboxWindow(pnorMbox_t* i_pnorMbox, - bool i_isWrite, - uint32_t i_reqAddr, - size_t i_reqSize, - uint32_t *o_lpcAddr, - size_t *o_chunkLen); - -/** - * @brief Mark a range dirty in a write window - * @param[in] Pointer to pnorMbox struct - * @parm[in] i_addr Flash offset of the range - * @parm[in] i_size Size of the range - * - * @return Error from operation - */ -errorHndl_t writeDirty(pnorMbox_t* i_pnorMbox, uint32_t i_addr, size_t i_size); - -/** -* @brief Flush all pending dirty data to the flash -* @param[in] Pointer to pnorMbox struct -* @return Error from operation -*/ -errorHndl_t writeFlush(pnorMbox_t* i_pnorMbox); - -#endif /* __PNOR_MBOX_H */ diff --git a/src/occ_405/firdata/pnor_util.c b/src/occ_405/firdata/pnor_util.c deleted file mode 100644 index 2c48179..0000000 --- a/src/occ_405/firdata/pnor_util.c +++ /dev/null @@ -1,220 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/pnor_util.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -/* Interfaces to write into PNOR */ - -#include -#include -#include -#include - -/*================================================================= */ -/* The offset of the next byte to write */ -uint32_t g_next_byte = 0xFFFFFFFF; -/* Size of the FIRDATA section of PNOR */ -uint32_t g_pnor_size = 0; -/* Global PNOR Mbox object */ -pnorMbox_t* g_pnorMbox; - -/* Cache to queue up PNOR writes */ -uint8_t g_write_cache[PAGE_PROGRAM_BYTES]; -/* Current position of data inside write cache */ -size_t g_write_cache_index = 0; - -/** - * @brief Write 8 bytes of data into PNOR starting - */ -int32_t pnor_write_8B( uint64_t i_data ) -{ - int32_t rc = SUCCESS; - - if ( (g_next_byte == 0xFFFFFFFF) || /* initialized data */ - ((g_next_byte + g_pnor_size) < (g_next_byte + 9)) ) /* make sure there is room */ - { - TRACFCOMP("pnor_write_8B> g_next_byte=%.8X, g_pnor_size=%.8X",g_next_byte,g_pnor_size); - /* must have been some error in the prep */ - return FAIL; - } - -//@TODO: Do we need ECC, or does the BMC handle that for us now? - /* Create 9-byte ECC-ified version */ -// uint8_t data9[9]; -// injectECC( (uint8_t*)(&i_data), 8, data9 ); - - /* Copy data into the write cache until we queue up - a big chunk of data to write. This is more efficient - and avoids handling the write boundary of the PP - command internally. */ -// size_t cpsz = 9; - - uint8_t data8[8]; - size_t cpsz = 8; - - if( (g_write_cache_index + cpsz) > PAGE_PROGRAM_BYTES ) - { - cpsz = PAGE_PROGRAM_BYTES - g_write_cache_index; - } - memcpy( &(g_write_cache[g_write_cache_index]), data8, cpsz ); -// memcpy( &(g_write_cache[g_write_cache_index]), data9, cpsz ); - - g_write_cache_index += cpsz; - - /* Write a complete chunk into the flash */ - if( g_write_cache_index == PAGE_PROGRAM_BYTES ) - { - errorHndl_t tmp = writeFlash( g_pnorMbox, - g_next_byte, - PAGE_PROGRAM_BYTES, - g_write_cache ); - if ( NO_ERROR != tmp ) - { - TRACFCOMP("pnor_write_8B> writeFlash failed"); - /* hit an error, stop any more writes from happening */ - g_next_byte = 0xFFFFFFFF; - g_pnor_size = 0; - return FAIL; - } - g_next_byte += PAGE_PROGRAM_BYTES; - memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); - g_write_cache_index = 0; - - if( (8 - cpsz) > 0 ) - { - memcpy( &(g_write_cache[0]), &(data8[cpsz]), 8 - cpsz ); - g_write_cache_index = 8 - cpsz; - } - - /* Handle the overflow */ -// if( (9 - cpsz) > 0 ) -// { -// memcpy( &(g_write_cache[0]), &(data9[cpsz]), 9 - cpsz ); -// g_write_cache_index = 9 - cpsz; -// } - } - - return rc; -} - - -/** - * @brief Perform any necessary operations to prepare - * the PNOR hw/code for writing - */ -errorHndl_t pnor_prep( HOMER_PnorInfo_t* i_pnorInfo ) -{ - errorHndl_t l_err = NO_ERROR; - - /* Figure out where to start */ - TRACFCOMP("FIRDATA is at %.8X..%.8X", i_pnorInfo->pnorOffset, i_pnorInfo->pnorOffset+i_pnorInfo->pnorSize ); - g_next_byte = i_pnorInfo->pnorOffset; - g_pnor_size = i_pnorInfo->pnorSize; - memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); - - /* Can we rely on skiboot leaving things in a good state? */ - l_err = hwInit(g_pnorMbox); - if( l_err ) - { - TRACFCOMP("hwInit failed"); - /* hit an error, stop any writes from happening */ - g_next_byte = 0xFFFFFFFF; - g_pnor_size = 0; - } - - return l_err; -} - -/*------------------------------------------------------------------------------ */ - -int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, - uint8_t * i_buf, uint32_t i_bufSize ) -{ - int32_t rc = SUCCESS; - TRACFCOMP(">>PNOR_writeFirData"); - - do - { - /* Initialize the PNOR data. */ - errorHndl_t l_err = pnor_prep( &i_pnorInfo ); - if( l_err ) - { - TRACFCOMP("pnor_prep failed"); - rc = FAIL; - break; /*nothing more to do here*/ - } - - uint32_t idx = 0; - uint64_t dataChunk = 0; - size_t sz_dataChunk = sizeof(uint64_t); - - /* Add PNOR data 8 bytes at a time. */ - for ( idx = 0; idx < i_bufSize; idx += sz_dataChunk ) - { - memcpy( &dataChunk, &i_buf[idx], sz_dataChunk ); - - rc = pnor_write_8B( dataChunk ); - if ( SUCCESS != rc ) - { - TRACFCOMP( "pnor_write_8B() failed during FIR write" ); - break; - } - } - if ( SUCCESS != rc ) break; - - /* Add any extra bytes if they exist at the end of the buffer. */ - if ( idx != i_bufSize ) - { - uint32_t extraBytes = idx - i_bufSize; - - dataChunk = 0; - memcpy( &dataChunk, &i_buf[idx], extraBytes ); - - rc = pnor_write_8B( dataChunk ); - if ( SUCCESS != rc ) - { - TRACFCOMP( "pnor_write_8B() failed during blank fill" ); - break; - } - } - - /* Fill the rest of the page with good ECC */ - for ( idx = i_bufSize; - idx < i_pnorInfo.pnorSize; - idx += sz_dataChunk ) - { - dataChunk = 0xFFFFFFFFFFFFFFFFull; - rc = pnor_write_8B( dataChunk ); - if ( SUCCESS != rc ) - { - TRACFCOMP( "pnor_write_8B() failed during ECC fill" ); - break; - } - } - - } while (0); - - TRACFCOMP("< - -/** - * @brief Writes a buffer containing the FIR data to PNOR (adding ECC). - * @param i_pnorInfo Information regarding PNOR location, size, etc. - * @param i_buf Data buffer (no ECC included). - * @param i_bufSize Size of the data buffer. - * @return Non-SUCCESS, if the write fails. SUCCESS, otherwise. - */ -int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, - uint8_t * i_buf, uint32_t i_bufSize ); - -#endif /* __pnor_util_h */ diff --git a/src/occ_405/firdata/sbe_fifo.c b/src/occ_405/firdata/sbe_fifo.c deleted file mode 100644 index 9a2099a..0000000 --- a/src/occ_405/firdata/sbe_fifo.c +++ /dev/null @@ -1,444 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/sbe_fifo.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ -#include "sbe_fifo.h" -#include -#include -#include - -/** @brief Waits for FIFO to be ready to be written to - * @param i_target The SCOM target. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -uint32_t waitUpFifoReady(SCOM_Trgt_t* i_target) -{ - uint32_t l_rc = SUCCESS; - - uint64_t l_elapsed_time_ns = 0; - uint32_t l_addr = SBE_FIFO_UPFIFO_STATUS; - uint32_t l_data = 0; - - do - { - //Read upstream status to see if there is room for more data - l_rc = getfsi(*i_target, l_addr, &l_data); - if(l_rc != SUCCESS) - { - TRAC_ERR("waitUpFifoReady: failed to getfsi from addr 0x%08x", - l_addr); - break; - } - - if(!(l_data & UPFIFO_STATUS_FIFO_FULL)) - { - break; - } - - //Check for timeout - if(l_elapsed_time_ns >= MAX_UP_FIFO_TIMEOUT_NS) - { - l_rc = FAIL; - TRAC_ERR("waitUpFifoReady: timeout occurred while waiting for" - " FIFO to clear"); - break; - } - - sleep(10000); //sleep for 10,000 ns - l_elapsed_time_ns += 10000; - }while(TRUE); - - return l_rc; -} - -/** @brief Waits for information to show up in FIFO - * @param i_target The SCOM target. - * @param o_status the status of the FIFO - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -uint32_t waitDnFifoReady(SCOM_Trgt_t* i_target, uint32_t* o_status) -{ - uint32_t l_rc = SUCCESS; - - uint64_t l_elapsed_time_ns = 0; - uint32_t l_addr = SBE_FIFO_DNFIFO_STATUS; - - do - { - // read dnstream status to see if data ready to be read - // or if has hit the EOT - l_rc = getfsi(*i_target, l_addr, o_status); - if(l_rc != SUCCESS) - { - return l_rc; - } - - if(!(*o_status & DNFIFO_STATUS_FIFO_EMPTY) || - (*o_status & DNFIFO_STATUS_DEQUEUED_EOT_FLAG)) - { - break; - } - else - { - TRAC_IMP("SBE status reg returned fifo empty or dequeued eot flag 0x%.8X", - *o_status); - } - - // Check for timeout - if(l_elapsed_time_ns >= MAX_UP_FIFO_TIMEOUT_NS) - { - TRAC_ERR("waitDnFifoReady: timeout waiting for downstream FIFO" - " to be empty."); - l_rc = FAIL; - break; - } - - sleep(10000); // wait for 10,000 ns - l_elapsed_time_ns += 10000; - - }while(TRUE); - - return l_rc; -} - -/** @brief Writes a request to FIFO - * @param i_target The SCOM target. - * @param i_fifoRequest the request to execute. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -uint32_t writeRequest(SCOM_Trgt_t* i_target, uint32_t* i_fifoRequest) -{ - uint32_t l_rc = SUCCESS; - - TRAC_IMP("Enter writeRequest"); - - // Ensure Downstream Max Transfer Counter is 0 non-0 can cause - // protocol issues) - uint32_t l_addr = SBE_FIFO_DNFIFO_MAX_TSFR; - uint32_t l_data = 0; - l_rc = putfsi(*i_target, l_addr, l_data); - if(l_rc != SUCCESS) - { - TRAC_ERR("writeRequest: failed to putfsi to addr 0x%08x", - l_addr); - return l_rc; - } - - //The first uint32_t has the number of uint32_t words in the request - l_addr = SBE_FIFO_UPFIFO_DATA_IN; - uint32_t* l_sent = i_fifoRequest; //This pointer will advance as words are sent - uint32_t l_count = *l_sent; - uint32_t i; - - for(i = 0; i < l_count; ++i) - { - //Wait for room to write into fifo - l_rc = waitUpFifoReady(i_target); - if(l_rc != SUCCESS) - { - return l_rc; - } - - //Send data into fifo - l_rc = putfsi(*i_target, l_addr, *l_sent); - if(l_rc != SUCCESS) - { - TRAC_ERR("writeRequest: failed to putfsi to addr 0x%08x", - l_addr); - return l_rc; - } - - l_sent++; - } - - //Notify SBE that last word has been sent - l_rc = waitUpFifoReady(i_target); - if(l_rc != SUCCESS) - { - return l_rc; - } - - l_addr = SBE_FIFO_UPFIFO_SIG_EOT; - l_data = FSB_UPFIFO_SIG_EOT; - l_rc = putfsi(*i_target, l_addr, l_data); - if(l_rc != SUCCESS) - { - TRAC_ERR("writeRequest: failed to putfsi to addr 0x%08x", l_addr); - } - - TRAC_IMP("Exit writeRequest"); - - return l_rc; -} - -/** @brief Reads and processes the FIFO response - * @param i_target The SCOM target. - * @param i_fifoRequest the original FIFO request. - * @param o_fifoResponse the FIFO response. - * @param i_responseSize the expected size of the response. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -uint32_t readResponse(SCOM_Trgt_t* i_target, - uint32_t* i_fifoRequest, - uint32_t* o_fifoResponse, - uint32_t i_responseSize) -{ - uint32_t l_rc = SUCCESS; - uint32_t l_readBuffer[READ_BUFFER_SIZE]; - - TRAC_IMP("Enter readResponse"); - - // EOT is expected before the response buffer is full. Room for - // the PCBPIB status or FFDC is included, but is only returned - // if there is an error. The last received word has the distance - // to the status, which is placed at the end of the returned data - // in order to reflect errors during transfer. - - uint32_t* l_received = o_fifoResponse; // advance as words are received - uint32_t l_maxWords = i_responseSize / sizeof(uint32_t); - uint32_t l_wordsReceived = 0; // Used to validata the "distance" to status - bool l_eotReceived = FALSE; - uint32_t l_lastWord = 0; // Last word received. Final read is the "distance" - // in words to the status header. - bool l_overRun = FALSE; - - do - { - // Wait for data to be ready to receive (download) or if the EOT - // has been sent. If not EOT, then data ready to receive. - uint32_t l_status = 0; - l_rc = waitDnFifoReady(i_target, &l_status); - if(l_rc != SUCCESS) - { - return l_rc; - } - - if(l_status & DNFIFO_STATUS_DEQUEUED_EOT_FLAG) - { - l_eotReceived = TRUE; - // Ignore EOT dummy word - if(l_wordsReceived >= (sizeof(struct statusHeader) / sizeof(uint32_t))) - { - if(l_overRun == FALSE) - { - l_received--; - l_wordsReceived--; - l_lastWord = o_fifoResponse[l_wordsReceived-1]; - } - else - { - l_lastWord = l_readBuffer[l_wordsReceived-2]; - } - } - break; - } - - // When error occurs, SBE will write more than l_maxWords - // we have to keep reading 1 word at a time until we get EOT - // or more than READ_BUFFER_SIZE. Save what we read in the buffer - if(l_wordsReceived >= l_maxWords) - { - l_overRun = TRUE; - } - - // Read next word - l_rc = getfsi(*i_target, SBE_FIFO_DNFIFO_DATA_OUT, &l_lastWord); - if(l_rc != SUCCESS) - { - return l_rc; - } - - l_readBuffer[l_wordsReceived] = l_lastWord; - - if(l_overRun == FALSE) - { - *l_received = l_lastWord; // Copy to returned output buffer - l_received++; // Advance to the next position - } - l_wordsReceived++; - - if(l_wordsReceived > READ_BUFFER_SIZE) - { - TRAC_ERR("readResponse: data overflow without EOT"); - l_rc = FAIL; - return l_rc; - } - - }while(TRUE); - - // At this point, l_wordsReceived of words received. - // l_received points to 1 word past last word received. - // l_lastWord has last word received, which is "distance" to status - // EOT is expected before running out of response buffer - if(!l_eotReceived) - { - l_rc = FAIL; - TRAC_ERR("readResponse: no EOT cmd = 0x%08x size = %d", - i_fifoRequest[1], i_responseSize); - return l_rc; - } - - // Notify SBE that EOT has been received - uint32_t l_eotSig = FSB_UPFIFO_SIG_EOT; - l_rc = putfsi(*i_target, SBE_FIFO_DNFIFO_ACK_EOT, l_eotSig); - if(l_rc != SUCCESS) - { - return l_rc; - } - - // Determine if transmission is successful. - // Last word received has the distance to status in words including itself. - // l_wordsReceived has number of words received. - // Need to have received at least status header and distance word. - if((l_lastWord < (sizeof(struct statusHeader)/sizeof(uint32_t) + 1)) || - (l_wordsReceived < (sizeof(struct statusHeader)/sizeof(uint32_t) + 1)) || - (l_lastWord > l_wordsReceived)) - { - TRAC_ERR("readResponse: invalid status distance. Cmd = 0x%08x distance" - " = %d allocated response size = %d received word size = %d", - i_fifoRequest[1], l_lastWord, i_responseSize, l_wordsReceived); - l_rc = FAIL; - return l_rc; - } - - // Check status for success. - // l_received points one word past last word received. - // l_lastWord has number of words to status header including self. - uint32_t* l_statusTmp = (l_overRun == FALSE) ? (l_received - l_lastWord) : - &l_readBuffer[l_wordsReceived - 1]; - struct statusHeader* l_statusHeader = (struct statusHeader*)l_statusTmp; - if((FIFO_STATUS_MAGIC != l_statusHeader->magic) || - (SBE_PRI_OPERATION_SUCCESSFUL != l_statusHeader->primaryStatus) || - (SBE_SEC_OPERATION_SUCCESSFUL != l_statusHeader->secondaryStatus)) - { - TRAC_ERR("readResponse: failing downstream status cmd = 0x%08x magic = " - "0x%08x primary status = 0x%08x secondary status = 0x%08x", - i_fifoRequest[1], - l_statusHeader->magic, - l_statusHeader->primaryStatus, - l_statusHeader->secondaryStatus); - - l_rc = FAIL; - } - - TRAC_IMP("Exit readResponse"); - return l_rc; -} - -/** @brief Performs a FIFO operation (read or write) - * @param i_target The SCOM target. - * @param i_fifoRequest the FIFO request data structure - * @param i_fifoResponse the response from SBE - * @param i_responseSize the size of the response - * @return Non-SUCCESS if the operation fails. SUCCESS otherwise. - */ -uint32_t performFifoChipOp(SCOM_Trgt_t* i_target, - uint32_t* i_fifoRequest, - uint32_t* i_fifoResponse, - uint32_t i_responseSize) -{ - uint32_t l_rc = SUCCESS; - - TRAC_IMP("Enter performFifoChipOp"); - - l_rc = writeRequest(i_target, i_fifoRequest); - if(l_rc != SUCCESS) - { - return l_rc; - } - - l_rc = readResponse(i_target, - i_fifoRequest, - i_fifoResponse, - i_responseSize); - - TRAC_IMP("Exit performFifoChioOp"); - - return l_rc; -} - -/** @brief Performs a write SCOM operation using SBE FIFO - * @param i_target The SCOM target. - * @param i_addr 64-bit SCOM address. - * @param i_data 64-bit data to write. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -int32_t putFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t i_data) -{ - uint32_t l_rc = SUCCESS; - - TRAC_IMP("Enter putFifoScom"); - - struct fifoPutScomRequest l_fifoRequest; - struct fifoPutScomResponse l_fifoResponse; - - l_fifoRequest.wordCnt = PUT_SCOM_REQUEST_WORD_CNT; - l_fifoRequest.reserved = 0; - l_fifoRequest.commandClass = SBE_FIFO_CLASS_SCOM_ACCESS; - l_fifoRequest.command = SBE_FIFO_CMD_PUT_SCOM; - l_fifoRequest.address = i_addr; - l_fifoRequest.data = i_data; - - l_rc = performFifoChipOp(i_target, - (uint32_t*)&l_fifoRequest, - (uint32_t*)&l_fifoResponse, - sizeof(struct fifoPutScomResponse)); - - TRAC_IMP("Exit putFifoScom"); - - return l_rc; -} - -/** @brief Performs a read SCOM operation using SBE FIFO - * @param i_target The SCOM target. - * @param i_addr 64-bit SCOM address. - * @param o_data 64-bit returned value. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -int32_t getFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t* o_data) -{ - uint32_t l_rc = SUCCESS; - - TRAC_IMP("Enter getFifoScom"); - - struct fifoGetScomRequest l_fifoRequest; - struct fifoGetScomResponse l_fifoResponse; - - l_fifoRequest.wordCnt = GET_SCOM_REQUEST_WORD_CNT; - l_fifoRequest.reserved = 0; - l_fifoRequest.commandClass = SBE_FIFO_CLASS_SCOM_ACCESS; - l_fifoRequest.command = SBE_FIFO_CMD_GET_SCOM; - l_fifoRequest.address = i_addr; - - l_rc = performFifoChipOp(i_target, - (uint32_t*)&l_fifoRequest, - (uint32_t*)&l_fifoResponse, - sizeof(struct fifoGetScomResponse)); - - //Always return data even if there is an error - *o_data = l_fifoResponse.data; - - TRAC_IMP("Exit getFifoScom"); - - return l_rc; -} diff --git a/src/occ_405/firdata/sbe_fifo.h b/src/occ_405/firdata/sbe_fifo.h deleted file mode 100644 index 4194471..0000000 --- a/src/occ_405/firdata/sbe_fifo.h +++ /dev/null @@ -1,123 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/sbe_fifo.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __SBE_FIFO_H -#define __SBE_FIFO_H - -#include -#include - -#define PACKED __attribute__((__packed__)) - -#define PUT_SCOM_REQUEST_WORD_CNT 0x06 -#define GET_SCOM_REQUEST_WORD_CNT 0x04 - -#define SBE_FIFO_CMD_GET_SCOM 0x01 -#define SBE_FIFO_CMD_PUT_SCOM 0x02 -#define SBE_FIFO_CLASS_SCOM_ACCESS 0xA2 -#define SBE_FIFO_DNFIFO_MAX_TSFR 0x00002458 -#define SBE_FIFO_UPFIFO_DATA_IN 0x00002400 -#define SBE_FIFO_UPFIFO_SIG_EOT 0x00002408 -#define FSB_UPFIFO_SIG_EOT 0x80000000 -#define SBE_FIFO_UPFIFO_STATUS 0x00002404 -#define SBE_FIFO_DNFIFO_STATUS 0x00002444 -#define UPFIFO_STATUS_FIFO_FULL 0x00200000 -#define DNFIFO_STATUS_FIFO_EMPTY 0x00100000 -#define DNFIFO_STATUS_DEQUEUED_EOT_FLAG 0x00800000 -#define SBE_FIFO_DNFIFO_ACK_EOT 0x00002454 -#define SBE_FIFO_DNFIFO_DATA_OUT 0x00002440 -#define NS_PER_MSEC (1000000ull) -#define MAX_UP_FIFO_TIMEOUT_NS 10*NS_PER_MSEC -#define READ_BUFFER_SIZE 2048 -#define FIFO_STATUS_MAGIC 0xC0DE -#define SBE_PRI_OPERATION_SUCCESSFUL 0x00 -#define SBE_SEC_OPERATION_SUCCESSFUL 0x00 - -struct statusHeader -{ - uint16_t magic; //set to 0xC0DE - uint8_t commandClass; - uint8_t command; - uint16_t primaryStatus; - uint16_t secondaryStatus; -} PACKED; - -struct ffdc_struct -{ - const void* ptr; - size_t size; -}; - -struct fifoPutScomRequest -{ - uint32_t wordCnt; - uint16_t reserved; - uint8_t commandClass; - uint8_t command; - uint64_t address; - uint64_t data; -} PACKED; - -struct fifoPutScomResponse -{ - struct statusHeader status; - struct ffdc_struct ffdc; //ffdc data - uint32_t status_distance; //distance to status -} PACKED; - -struct fifoGetScomRequest -{ - uint32_t wordCnt; - uint16_t reserved; - uint8_t commandClass; - uint8_t command; - uint64_t address; -} PACKED; - -struct fifoGetScomResponse -{ - uint64_t data; //Data (0..31) + (32..63) - struct statusHeader status; - struct ffdc_struct ffdc; //ffdc data - uint32_t status_distance; // distance to status -} PACKED; - -/** @brief Performs a write SCOM operation using SBE FIFO - * @param i_target The SCOM target. - * @param i_addr 64-bit SCOM address. - * @param i_data 64-bit data to write. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -int32_t putFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t i_data); - -/** @brief Performs a read SCOM operation using SBE FIFO - * @param i_target The SCOM target. - * @param i_addr 64-bit SCOM address. - * @param o_data 64-bit returned value. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -int32_t getFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t* o_data); - -#endif - diff --git a/src/occ_405/firdata/scom_addr_util.c b/src/occ_405/firdata/scom_addr_util.c deleted file mode 100644 index a59a5a7..0000000 --- a/src/occ_405/firdata/scom_addr_util.c +++ /dev/null @@ -1,82 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/scom_addr_util.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 */ -#include "scom_addr_util.h" - - -void set_sat_id(const uint8_t i_sat_id, uint64_t * o_addr) -{ - *o_addr &= 0xFFFFFFFFFFFFFC3FULL; - *o_addr |= ((i_sat_id & 0xF) << 6); -} - -void set_chiplet_id(const uint8_t i_chiplet_id, uint64_t * o_addr) -{ - *o_addr &= 0xFFFFFFFFC0FFFFFFULL; - *o_addr |= ((i_chiplet_id & 0x3F) << 24); -} - -void set_ring(const uint8_t i_ring, uint64_t * o_addr) -{ - *o_addr &= 0xFFFFFFFFFFFF03FFULL; - *o_addr |= ((i_ring & 0x3F) << 10); -} - -void set_sat_offset(const uint8_t i_sat_offset, uint64_t * o_addr) -{ - *o_addr &= 0xFFFFFFFFFFFFFFC0ULL; - *o_addr |= (i_sat_offset & 0x3F); -} - -void set_rxtx_group_id(const uint8_t i_grp_id, uint64_t * o_addr) -{ - *o_addr &= 0xFFFFF81FFFFFFFFFULL; - *o_addr |= (i_grp_id & 0x3FULL) << 37; -} - -uint8_t get_sat_id(const uint64_t i_addr) -{ - return ((i_addr >> 6) & 0xF); -} - -uint8_t get_chiplet_id(const uint64_t i_addr) -{ - return ((i_addr >> 24) & 0x3F); -} - -uint8_t get_ring(const uint64_t i_addr) -{ - return ((i_addr >> 10) & 0x3F); -} - -uint8_t get_sat_offset(const uint64_t i_addr) -{ - return (i_addr & 0x3F); -} - -uint8_t get_rxtx_group_id(const uint64_t i_addr) -{ - return (i_addr >> 37) & 0x3F; -} - diff --git a/src/occ_405/firdata/scom_addr_util.h b/src/occ_405/firdata/scom_addr_util.h deleted file mode 100644 index 51988b4..0000000 --- a/src/occ_405/firdata/scom_addr_util.h +++ /dev/null @@ -1,81 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/scom_addr_util.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __scom_addr_util_h -#define __scom_addr_util_h - -#include - -//This file is a result of de-classing the p9_scom_addr that currently -//lives in EKB: chips/p9/common/scominfo/p9_scom_addr.H - -// @brief Modify SCOM address, update satellite ID field -// @param[in] i_sat_id Satellite ID value to write -// @retval none -// -void set_sat_id(const uint8_t i_sat_id, uint64_t * o_addr); - -// @brief Modify SCOM address, update pervasive chiplet ID -// @param[in] i_chiplet_id Chiplet ID value to write -// @retval none -// -void set_chiplet_id(const uint8_t i_chiplet_id, uint64_t * o_addr); - -// @brief Modify SCOM address, update ring field value -// @param[in] i_ring Ring field value to write -// @retval none -void set_ring(const uint8_t i_ring, uint64_t * o_addr); - -// @brief Modify SCOM address, update satellite offset field -// @param[in] i_sat_offset Satellite offset value to write -// @retval none -void set_sat_offset(const uint8_t i_sat_offset, uint64_t * o_addr); - -// @brief Modify SCOM address, update the RX or TX Group ID -// @param[in] i_grp_id Group id to set -// @retval none -void set_rxtx_group_id(const uint8_t i_grp_id, uint64_t * o_addr); - -// @brief Extract satellite ID field from SCOM address -// @retval uint8_t Satellite ID field value -uint8_t get_sat_id(const uint64_t i_addr); - -// @brief Extract pervasive chiplet ID from SCOM address -// @retval uint8_t Pervasive chiplet ID value -uint8_t get_chiplet_id(const uint64_t i_addr); - -// @brief Extract ring field from SCOM address -// @retval uint8_t Ring field value -uint8_t get_ring(const uint64_t i_addr); - -// @brief Extract satellite register offset field from SCOM address -// @retval uint8_t Satellite register offset field value -uint8_t get_sat_offset(const uint64_t i_addr); - -// @brief Extract the RX or TX Group ID of an indirect scom address -// @retval uint8_t Satellite register offset field value -uint8_t get_rxtx_group_id(const uint64_t i_addr); - - -#endif diff --git a/src/occ_405/firdata/scom_trgt.c b/src/occ_405/firdata/scom_trgt.c deleted file mode 100644 index 15ad3fc..0000000 --- a/src/occ_405/firdata/scom_trgt.c +++ /dev/null @@ -1,180 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/scom_trgt.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -#include -#include -#include - -/*------------------------------------------------------------------------------ */ - -SCOM_Trgt_t SCOM_Trgt_getTrgt( TrgtType_t i_type, uint8_t i_procPos, - uint8_t i_procUnitPos, uint32_t i_fsiBaseAddr, - bool i_isMaster ) -{ - SCOM_Trgt_t trgt = { - .type = i_type, - .procPos = i_procPos, - .procUnitPos = i_procUnitPos, - .isMaster = i_isMaster, - .fsiBaseAddr = i_fsiBaseAddr, - }; - - if (TRGT_PROC == trgt.type) - { - trgt.procUnitPos = 0; - } - - if ( TRGT_MEMBUF == trgt.type || TRGT_MBA == trgt.type ) - { - trgt.isMaster = false; - } - - return trgt; -} - -/*------------------------------------------------------------------------------ */ - -uint8_t SCOM_Trgt_getChipPos( SCOM_Trgt_t i_trgt ) -{ - uint32_t p = 0; - - switch ( i_trgt.type ) - { - case TRGT_PROC: - case TRGT_CAPP: - case TRGT_XBUS: - case TRGT_OBUS: - case TRGT_PEC: - case TRGT_PHB: - case TRGT_EQ: - case TRGT_EX: - case TRGT_EC: - case TRGT_MCBIST: - case TRGT_MCS: - case TRGT_MCA: - p = i_trgt.procPos; - break; - - case TRGT_MEMBUF: /* TODO RTC 173614 -- with CUMULUS */ - p = (i_trgt.procPos * MAX_MEMBUF_PER_PROC) + i_trgt.procUnitPos; - break; - - case TRGT_MBA: /* TODO RTC 173614 -- with CUMULUS */ - p = (i_trgt.procPos * MAX_MEMBUF_PER_PROC) + - (i_trgt.procUnitPos / MAX_MBA_PER_MEMBUF); - break; - - default: ; - } - - return p; -} - -/*------------------------------------------------------------------------------ */ - -uint8_t SCOM_Trgt_getChipUnitPos( SCOM_Trgt_t i_trgt ) -{ - uint32_t u = 0; - - switch ( i_trgt.type ) - { - case TRGT_PROC: - case TRGT_MEMBUF: u = 0; break; - - case TRGT_CAPP: - case TRGT_XBUS: - case TRGT_OBUS: - case TRGT_PEC: - case TRGT_PHB: - case TRGT_EQ: - case TRGT_EX: - case TRGT_EC: - case TRGT_MCBIST: - case TRGT_MCS: - case TRGT_MCA: u = i_trgt.procUnitPos; break; - - case TRGT_MBA: u = i_trgt.procUnitPos % MAX_MBA_PER_MEMBUF; break; - /* TODO RTC 173614 -- with CUMULUS */ - - default: ; - } - - return u; -} - -/*------------------------------------------------------------------------------ */ - -SCOM_Trgt_t SCOM_Trgt_getParentChip( SCOM_Trgt_t i_trgt ) -{ - TrgtType_t t = TRGT_MAX; - switch ( i_trgt.type ) - { - case TRGT_PROC: - case TRGT_CAPP: - case TRGT_XBUS: - case TRGT_OBUS: - case TRGT_PEC: - case TRGT_PHB: - case TRGT_EQ: - case TRGT_EX: - case TRGT_EC: - case TRGT_MCBIST: - case TRGT_MCS: - case TRGT_MCA: t = TRGT_PROC; break; - - case TRGT_MEMBUF: - case TRGT_MBA: t = TRGT_MEMBUF; break; - - default: ; - } - - uint8_t u = 0; - switch ( i_trgt.type ) - { - case TRGT_PROC: - case TRGT_CAPP: - case TRGT_XBUS: - case TRGT_OBUS: - case TRGT_PEC: - case TRGT_PHB: - case TRGT_EQ: - case TRGT_EX: - case TRGT_EC: - case TRGT_MCBIST: - case TRGT_MCS: - case TRGT_MCA: - case TRGT_MEMBUF: u = i_trgt.procUnitPos; break; - /* TODO RTC 173614 -- with CUMULUS */ - - case TRGT_MBA: u = i_trgt.procUnitPos / MAX_MBA_PER_MEMBUF; break; - /* TODO RTC 173614 -- with CUMULUS */ - - default: ; - } - - return SCOM_Trgt_getTrgt( t, i_trgt.procPos, u, i_trgt.fsiBaseAddr, - i_trgt.isMaster ); -} - diff --git a/src/occ_405/firdata/scom_trgt.h b/src/occ_405/firdata/scom_trgt.h deleted file mode 100644 index 4ffe8b5..0000000 --- a/src/occ_405/firdata/scom_trgt.h +++ /dev/null @@ -1,89 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/scom.H $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 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 __scom_trgt_h -#define __scom_trgt_h - -#include -#include - -typedef struct -{ - /** See enum TrgtType_t. NOTE: This value is not consistant with Hostboot - * target types. */ - TrgtType_t type; - - /** Absolute position of the connected PROC within the node. This value - * should be consistant with the Hostboot target positions. */ - uint8_t procPos; - - /** Unit position relative to the connected PROC. This value should be - * consistant with the Hostboot target positions. */ - uint8_t procUnitPos; - - /** Indicates this target is, or is connected to, the master processor. */ - bool isMaster; - - /** This target's FSI base address. */ - uint32_t fsiBaseAddr; - -} SCOM_Trgt_t; - -/** @param i_type See enum Type. - * @param i_procPos Absolute position within the node of the connected - * PROC target. - * @param i_procUnitPos Unit position relative to the connected PROC. Will be - * explicitly set to 0 for PROC targets. - * @param i_fsiBaseAddr For EX and MCS, the FSI base address for the - * connected PROC. For MEMB and MBA, the FSI base - * address for the connected MEMB. - * @param i_isMaster True, if this target is, or is connected to, the - * master processor. False, otherwise. Will be explicitly - * set to false for MEMB and MBA targets. - * @return A SCOM_Trgt_t struct. - */ -SCOM_Trgt_t SCOM_Trgt_getTrgt( TrgtType_t i_type, uint8_t i_procPos, - uint8_t i_procUnitPos, uint32_t i_fsiBaseAddr, - bool i_isMaster ); - -/** @param i_trgt The SCOM target. - * @return This target's absolute position of the parent chip (PROC or - * MEMB) within the node. - */ -uint8_t SCOM_Trgt_getChipPos( SCOM_Trgt_t i_trgt ); - -/** @param i_trgt The SCOM target. - * @return This target's unit position relative to the parent chip. Only - * valid for EX, MCS, and MBA units. Will return 0 for PROC and - * MEMB chips. - */ -uint8_t SCOM_Trgt_getChipUnitPos( SCOM_Trgt_t i_trgt ); - -/** @param i_trgt The SCOM target. - * @return A target for the containing parent chip (PROC or MEMB). - */ -SCOM_Trgt_t SCOM_Trgt_getParentChip( SCOM_Trgt_t i_trgt ); - -#endif /* __scom_trgt_h */ diff --git a/src/occ_405/firdata/scom_util.c b/src/occ_405/firdata/scom_util.c deleted file mode 100644 index 7709017..0000000 --- a/src/occ_405/firdata/scom_util.c +++ /dev/null @@ -1,607 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/scom_util.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -/* Support for SCOM operations */ -#include -#include -#include -#include "occ_common.h" -#include "gpe_export.h" -#include -#include "scom_addr_util.h" -#include - -bool G_request_created = FALSE; -GPE_BUFFER(ipc_scom_op_t G_scom_op); -GpeRequest G_request; - -enum { - /*FSI addresses are byte offsets, so need to multiply by 4 - since each register is 4 bytes long. - prefix with 0x10xx for FSI2PIB engine offset */ - DATA0_REG = 0x1000, /* SCOM Data Register 0 (0x00) */ - DATA1_REG = 0x1004, /* SCOM Data Register 1 (0x01) */ - COMMAND_REG = 0x1008, /* SCOM Command Register (0x02) */ - ENGINE_RESET_REG = 0x1018, /* Engine Reset Register (0x06) */ - STATUS_REG = 0x101C, /* STATUS Register (0x07) */ - PIB_RESET_REG = 0x101C, /* PIB Reset Register (0x07) */ - - PIB_ABORT_BIT = 0x00100000, /* 12= PIB Abort */ - PIB_ERROR_BITS = 0x00007000, /* 17:19= PCB/PIB Errors */ -}; - -/** - * @brief Indirect SCOM Status - */ -typedef union -{ - uint64_t data64; - struct - { - uint64_t :12; /*0:11*/ - uint64_t addr:20; /*12:31*/ - uint64_t done:1; /*32*/ - uint64_t piberr:3; /*33:35*/ - uint64_t userstat:4; /*36:39*/ - uint64_t :8; /*40:47*/ - uint64_t data:16; /*48:63*/ - }; -} IndirectScom_t; - -enum { - MCS_MASK = 0xFFFFFFFF7FFFFF80, - MCS_BASEADDR = 0x0000000002011800, - MCS_DMI_BASEADDR = 0x0000000002011A00, - IND_MCS_BASEADDR = 0x8000006002011A00, - IND_MCS_DMI_BASEADDR = 0x8000006002011A3F, - MBA_MASK = 0xFFFFFFFF7FFFFC00, - MBA_BASEADDR = 0x0000000003010400, - TCM_MBA_BASEADDR = 0x0000000003010800, - IND_MBA_BASEADDR = 0x800000000301143f, -}; - -/** - * @brief Translates a relative unit address to a real physical address - * @param i_trgt Chip/unit to SCOM. - * @param i_addr Address to SCOM (the unit's 0th address for unit SCOMs). - * @param o_addr Return address. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t translate_addr( SCOM_Trgt_t i_trgt, uint64_t i_addr, uint64_t * o_addr ) -{ - #define FUNC "[translate_addr] " - - int32_t rc = SUCCESS; - uint8_t l_chip_unit_num = SCOM_Trgt_getChipUnitPos(i_trgt); - - *o_addr = i_addr; - - //The following translation logic is a copy of p9_scominfo_createChipUnitScomAddr - //function from EKB (chips/p9/common/scominfo/p9_scominfo.C) - - if(i_trgt.type == TRGT_PROC || i_trgt.type == TRGT_MEMBUF) - { - //No need to translate here. - //We already assigned i_addr to o_addr above, so just return SUCCESS. - return rc; - } - else if(i_trgt.type == TRGT_CAPP) //CAPP - { - set_chiplet_id(N0_CHIPLET_ID + (l_chip_unit_num * 2), o_addr); - } - else if(i_trgt.type == TRGT_XBUS) //XBUS - { - uint8_t l_ring_id = get_ring(i_addr) & 0xF; - if(l_ring_id <= XB_IOX_2_RING_ID && l_ring_id >= XB_IOX_0_RING_ID) - { - set_ring((XB_IOX_0_RING_ID + l_chip_unit_num) & 0xF, o_addr); - } - else if(l_ring_id <= XB_PBIOX_2_RING_ID && - l_ring_id >= XB_PBIOX_0_RING_ID) - { - set_ring((XB_PBIOX_0_RING_ID + l_chip_unit_num) & 0xF, o_addr); - } - } - else if(i_trgt.type == TRGT_OBUS) //OBUS - { - set_chiplet_id(OB0_CHIPLET_ID + l_chip_unit_num, o_addr); - } - else if(i_trgt.type == TRGT_PEC) //PEC - { - if(get_chiplet_id(i_addr) == N2_CHIPLET_ID) - { - // nest - set_ring((N2_PCIS0_0_RING_ID + l_chip_unit_num) & 0xF, o_addr); - } - else - { - // iopci / pci - set_chiplet_id(PCI0_CHIPLET_ID + l_chip_unit_num, o_addr); - } - } - else if (i_trgt.type == TRGT_PHB) //PHB - { - if(get_chiplet_id(i_addr) == N2_CHIPLET_ID) - { - // nest - if(l_chip_unit_num == 0) - { - set_ring(N2_PCIS0_0_RING_ID & 0xF, o_addr); - set_sat_id((get_sat_id(i_addr) < 4) ? 1 : 4, o_addr); - } - else - { - set_ring((N2_PCIS0_0_RING_ID + (l_chip_unit_num / 3) + 1) & 0xF, - o_addr); - set_sat_id(((get_sat_id(i_addr) < 4) ? 1 : 4) + - ((l_chip_unit_num % 2) ? 0 : 1) + - (2 * l_chip_unit_num / 5), o_addr); - } - } - else - { - // pci - if(l_chip_unit_num == 0) - { - set_chiplet_id(PCI0_CHIPLET_ID, o_addr); - set_sat_id(((get_sat_id(i_addr) < 4) ? 1 : 4), o_addr); - } - else - { - set_chiplet_id(PCI0_CHIPLET_ID + (l_chip_unit_num / 3) + 1, o_addr); - set_sat_id(((get_sat_id(i_addr) < 4) ? 1 : 4) + - ((l_chip_unit_num % 2) ? 0 : 1) + - 2 * l_chip_unit_num / 5, o_addr); - } - } - } - else if(i_trgt.type == TRGT_EX) //EX - { - if(get_chiplet_id(i_addr) <= EP05_CHIPLET_ID && - get_chiplet_id(i_addr) >= EP00_CHIPLET_ID) - { - set_chiplet_id(EP00_CHIPLET_ID + (l_chip_unit_num / 2), o_addr); - uint8_t l_ring_id = get_ring(i_addr) & 0xF; - l_ring_id = (l_ring_id - (l_ring_id % 2)) + (l_chip_unit_num % 2); - set_ring(l_ring_id & 0xF, o_addr); - } - else if(get_chiplet_id(i_addr) <= EC23_CHIPLET_ID && - get_chiplet_id(i_addr) >= EC00_CHIPLET_ID) - { - set_chiplet_id(EC00_CHIPLET_ID + - (get_chiplet_id(i_addr) % 2) + - (l_chip_unit_num * 2), o_addr); - } - } - else if(i_trgt.type == TRGT_EQ) //EQ - { - set_chiplet_id(EP00_CHIPLET_ID + l_chip_unit_num, o_addr); - } - else if(i_trgt.type == TRGT_EC) //EC - { - set_chiplet_id(EC00_CHIPLET_ID + l_chip_unit_num, o_addr); - } - else if(i_trgt.type == TRGT_MBA) //MBA - { - if( (i_addr & MBA_MASK) == MBA_BASEADDR ) - { - /* 0x00000000_03010400 MBA 0 # MBA01 */ - /* 0x00000000_03010C00 MBA 1 # MBA23 */ - if( l_chip_unit_num == 1 ) - { - *o_addr |= 0x00000800; - } - } - else if( (i_addr & MBA_MASK) == TCM_MBA_BASEADDR ) - { - /* 0x00000000_03010880 MBA 0 # Trace for MBA01 */ - /* 0x00000000_030110C0 MBA 1 # Trace for MBA23 */ - *o_addr |= (l_chip_unit_num * 0x840); - } - else if( (i_addr & MBA_MASK) == IND_MBA_BASEADDR ) - { - /* 0x00000000_03011400 MBA 0 # DPHY01 (indirect addressing) */ - /* 0x00000000_03011800 MBA 1 # DPHY23 (indirect addressing) */ - /* 0x80000000_0301143f MBA 0 # DPHY01 (indirect addressing) */ - /* 0x80000000_0301183f MBA 1 # DPHY23 (indirect addressing) */ - /* 0x80000000_0701143f MBA 0 # DPHY01 (indirect addressing) */ - /* 0x80000000_0701183f MBA 1 # DPHY23 (indirect addressing) */ - if( l_chip_unit_num == 1 ) - { - /* 030114zz->030118zz */ - *o_addr &= 0xFFFFFFFFFFFFFBFF; - *o_addr |= 0x0000000000000800; - } - } - } - else if(i_trgt.type == TRGT_MCS || //MCS - i_trgt.type == TRGT_MI) //MI TODO RTC 175488 - { - set_chiplet_id(N3_CHIPLET_ID - (2 * (l_chip_unit_num / 2)), o_addr); - set_sat_id(2 * (l_chip_unit_num % 2), o_addr); - } - else if(i_trgt.type == TRGT_MCBIST || //MCBIST - i_trgt.type == TRGT_MC) //MC TODO RTC 175488 - { - set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num, o_addr); - } - else if(i_trgt.type == TRGT_MCA) //MCA - { - if(get_chiplet_id(i_addr) == MC01_CHIPLET_ID || - get_chiplet_id(i_addr) == MC23_CHIPLET_ID) - { - set_chiplet_id(MC01_CHIPLET_ID + (l_chip_unit_num / 4), o_addr); - - if((get_ring(i_addr) & 0xf) == MC_MC01_0_RING_ID) - { - // mc - uint8_t l_sat_id = get_sat_id(i_addr); - set_sat_id((l_sat_id - (l_sat_id % 4)) + (l_chip_unit_num % 4) - , o_addr); - } - else - { - // iomc - set_ring((MC_IOM01_0_RING_ID + (l_chip_unit_num % 4)) & 0xF - , o_addr); - } - } - else - { - // mcs->mca registers - uint8_t l_mcs_unitnum = l_chip_unit_num / 2; - set_chiplet_id(N3_CHIPLET_ID - (2 * (l_mcs_unitnum / 2)) , o_addr); - set_sat_id(2 * (l_chip_unit_num % 2), o_addr); - uint8_t l_mcs_sat_offset = 0x2F & get_sat_offset(i_addr); - l_mcs_sat_offset |= (l_chip_unit_num % 2) << 4; - set_sat_offset(l_mcs_sat_offset, o_addr); - } - } - else if(i_trgt.type == TRGT_DMI) //DMI TODO RTC 175488 - { - if(get_chiplet_id(i_addr) == N3_CHIPLET_ID || get_chiplet_id(i_addr) == N1_CHIPLET_ID) - { - set_chiplet_id(N3_CHIPLET_ID - 2 * (l_chip_unit_num / 4), o_addr); - set_sat_id(2 * ((l_chip_unit_num / 2) % 2), o_addr); - uint8_t l_sat_offset = get_sat_offset(i_addr); - l_sat_offset = (l_sat_offset & 0xF) + ((2 + (l_chip_unit_num % 2)) << 4); - set_sat_offset(l_sat_offset, o_addr); - } - else if(get_chiplet_id(i_addr) == MC01_CHIPLET_ID || get_chiplet_id(i_addr) == MC23_CHIPLET_ID) - { - if(get_ring(i_addr) == P9C_MC_CHAN_RING_ID) - { - set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num / 4, o_addr); - uint8_t l_sat_id = get_sat_id(i_addr); - l_sat_id = l_sat_id & 0xC; - set_sat_id(l_sat_id + l_chip_unit_num % 4, o_addr); - } - else if(get_ring(i_addr) == P9C_MC_BIST_RING_ID) - { - set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num / 4, o_addr); - uint8_t l_sat_offset = get_sat_offset(i_addr); - l_sat_offset = (l_sat_offset & 0xF) + ((l_chip_unit_num % 2) << 4); - set_sat_offset(l_sat_offset, o_addr); - } - else if(get_ring(i_addr) == P9C_MC_IO_RING_ID) - { - set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num / 4, o_addr); - uint8_t l_rxtx_group = get_rxtx_group_id(i_addr); - l_rxtx_group = l_rxtx_group & 0xF0; - - switch(l_chip_unit_num % 4) - { - case 0: - l_rxtx_group += 3; - break; - case 1: - l_rxtx_group += 2; - break; - case 2: - l_rxtx_group += 0; - break; - case 3: - l_rxtx_group += 1; - break; - default: - break; - } - set_rxtx_group_id(l_rxtx_group, o_addr); - } - } - } - else - { - TRAC_ERR( FUNC"unsupported unit type %d", i_trgt.type ); - rc = FAIL; - } - - return rc; - - #undef FUNC -} - -/** - * @brief Performs a getscom operation with no address translation. - * @param i_chip Chip to SCOM. - * @param i_addr Address to SCOM. - * @param o_val Returned value. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t getscomraw( SCOM_Trgt_t i_chip, uint32_t i_addr, uint64_t * o_val ) -{ - int32_t l_rc = SUCCESS; - - //Use SBE FIFO if it's a slave proc - if(!i_chip.isMaster) - { - return getFifoScom(&i_chip, i_addr, o_val); - } - - if(!G_request_created) //Only need to create request once - { - l_rc = gpe_request_create(&G_request, //Request - &G_async_gpe_queue0, //Queue - IPC_ST_SCOM_OPERATION, //Function ID - &G_scom_op, //GPE arguments - SSX_SECONDS(5), //Timeout - NULL, //Callback function - NULL, //Callback args - ASYNC_REQUEST_BLOCKING); //Options - if(l_rc) - { - TRAC_ERR("getscomraw: failed to create gpe request, rc=0x%08X", l_rc); - return l_rc; - } - else - { - G_request_created = TRUE; - } - } - - //Pack in the request data - G_scom_op.read = TRUE; - G_scom_op.addr = i_addr; - - l_rc = gpe_request_schedule(&G_request); - if(l_rc) - { - TRAC_ERR("getscomraw: failed to schedule gpe request, rc=0x%08X", l_rc); - return l_rc; - } - - //Since it's a blocking request, it should be completed by the time we - //get here. If it's not, then a timeout has occurred. - if(G_request.request.completion_state == ASYNC_REQUEST_STATE_COMPLETE) - { - *o_val = G_scom_op.data; - } - else - { - *o_val = 0; - l_rc = FAIL; - } - - return l_rc; -} - -/** - * @brief Perform a putscom operation with no address translation. - * @param i_chip Chip to SCOM. - * @param i_addr Address to SCOM. - * @param i_val Value to write. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t putscomraw( SCOM_Trgt_t i_chip, uint32_t i_addr, uint64_t i_val ) -{ - int32_t l_rc = SUCCESS; - - //Use SBE FIFO if it's a slave proc - if(!i_chip.isMaster) - { - return putFifoScom(&i_chip, i_addr, i_val); - } - - if(!G_request_created) //Only need to create request once - { - l_rc = gpe_request_create(&G_request, //Request - &G_async_gpe_queue0, //Queue - IPC_ST_SCOM_OPERATION, //Function ID - &G_scom_op, //GPE arguments - SSX_SECONDS(5), //Timeout - NULL, //Callback function - NULL, //Callback args - ASYNC_REQUEST_BLOCKING); //Options - if(l_rc) - { - TRAC_ERR("putscomraw gpe request create failed, rc = 0x%08x", l_rc); - return l_rc; - } - else - { - G_request_created = TRUE; - } - } - - //Pack in the request data - G_scom_op.read = FALSE; - G_scom_op.addr = i_addr; - G_scom_op.data = i_val; - - l_rc = gpe_request_schedule(&G_request); - if(l_rc) - { - TRAC_ERR("putscomraw gpe request schedule failed, rc=0x%08X", l_rc); - return l_rc; - } - - //It's a blocking request, so if the request hasn't been completed by this - //time, then a timeout has occurred. - if(G_request.request.completion_state != ASYNC_REQUEST_STATE_COMPLETE) - { - TRAC_ERR("putscomraw gpe request failed to complete, rc = 0x%08x", l_rc); - l_rc = FAIL; - } - - return l_rc; -} - -/** - * @brief Executes standard getscom. - * @param i_trgt Chip to SCOM. - * @param i_addr Address to SCOM. - * @param o_val Returned value. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t SCOM_getScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t * o_val ) -{ - int32_t rc = SUCCESS; - - /* Get the parent chip. */ - SCOM_Trgt_t chip_targ = SCOM_Trgt_getParentChip(i_trgt); - - /* Get the address relative to the parent chip. */ - uint64_t trans_addr; - rc = translate_addr( i_trgt, i_addr, &trans_addr ); - if ( SUCCESS == rc ) - { - /* Do the SCOM. */ - rc = getscomraw( chip_targ, trans_addr, o_val ); - } - - return rc; -} - -/** - * @brief Execute indirect getscom. - * @param i_trgt Chip to SCOM. - * @param i_addr Address to SCOM. - * @param o_val Returned value. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. - */ -int32_t SCOM_getIdScom( SCOM_Trgt_t i_trgt, uint64_t i_addr, uint32_t * o_val ) -{ - #define FUNC "[SCOM_getIdScom] " - - int32_t rc = SUCCESS; - - *o_val = 0; - - /* Get the parent chip */ - SCOM_Trgt_t chip_targ = SCOM_Trgt_getParentChip(i_trgt); - - /* Get the address relative to the parent chip. */ - uint64_t trans_addr; - rc = translate_addr( i_trgt, i_addr, &trans_addr ); - if ( SUCCESS != rc ) return rc; - - /* An indirect SCOM is performed by putting the top of the 64-bit address - * into the first data word of the SCOM */ - - /* Zero out the indirect address from the buffer. */ - /* bit 0-31 - indirect area. */ - /* bit 32 - always 0 */ - /* bit 33-47 - bcast/chipletID/port */ - /* bit 48-63 - local addr */ - uint32_t phys_addr = trans_addr & 0x000000007FFFFFFF; - - /* To do a read we need to do a write first. */ - - /* Start with the 20bit indirect address */ - uint64_t data_buffer = trans_addr & 0x001FFFFF00000000; - /* Turn the read bit on. */ - data_buffer |= 0x8000000000000000; - - /* perform write before the read with the new */ - rc = putscomraw( i_trgt, phys_addr, data_buffer ); - if ( SUCCESS != rc ) return rc; - - // Loop on read until we see done, error, or we timeout - IndirectScom_t scomout; - uint64_t elapsed_indScom_time_ns = 0; - do - { - /* Now perform the op requested using the passed in */ - /* IO_Buffer to pass the read data back to caller. */ - rc = getscomraw( chip_targ, phys_addr, &(scomout.data64) ); - if ( SUCCESS != rc ) return rc; - - /* Check for PIB error. */ - if ( scomout.piberr ) - { - TRAC_ERR( FUNC"ID SCOM PIB error: phys_addr=0x%08x " - "trans_addr=0x%08x%08x", phys_addr, - (uint32_t)(trans_addr >> 32), (uint32_t)trans_addr ); - return FAIL; - } - - /* Jump out when done. */ - if ( scomout.done ) break; - - sleep( 10000 ); /* sleep for 10,000 ns */ - elapsed_indScom_time_ns += 10000; - - } while ( elapsed_indScom_time_ns <= 100000 ); /* wait for .1ms */ - - if ( !scomout.done ) - { - TRAC_ERR( FUNC"ID SCOM loop timeout exceeded: phys_addr=0x%08x " - "trans_addr=0x%08x%08x", phys_addr, - (uint32_t)(trans_addr >> 32), (uint32_t)trans_addr ); - return FAIL; - } - - *o_val = scomout.data; - - return rc; - - #undef FUNC -} - -/** - * @brief Executes standard putscom. - * @param i_trgt Chip to SCOM. - * @param i_addr Address to SCOM. - * @param i_val Value to put. - * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. -*/ -int32_t SCOM_putScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t i_val ) -{ - int32_t l_rc = SUCCESS; - - /* Get the parent chip. */ - SCOM_Trgt_t l_chip_targ = SCOM_Trgt_getParentChip(i_trgt); - - /* Get the address relative to the parent chip. */ - uint64_t l_trans_addr; - l_rc = translate_addr( i_trgt, i_addr, &l_trans_addr ); - if ( SUCCESS == l_rc ) - { - /* Do the SCOM. */ - l_rc = putscomraw( l_chip_targ, l_trans_addr, i_val ); - } - - return l_rc; -} diff --git a/src/occ_405/firdata/scom_util.h b/src/occ_405/firdata/scom_util.h deleted file mode 100644 index 1ec7fd2..0000000 --- a/src/occ_405/firdata/scom_util.h +++ /dev/null @@ -1,98 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/firdata/scom_util.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,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 */ - -/* Interfaces to read SCOM registers */ - -/*#include */ -#include -#include - -#define SCOMFAIL 0xDEADBEEF - -typedef enum -{ - N0_CHIPLET_ID = 0x02, ///< Nest0 (North) chiplet - N1_CHIPLET_ID = 0x03, ///< Nest1 (East) chiplet - N2_CHIPLET_ID = 0x04, ///< Nest2 (South) chiplet - N3_CHIPLET_ID = 0x05, ///< Nest3 (West) chiplet - MC01_CHIPLET_ID = 0x07, ///< MC01 (West) chiplet - MC23_CHIPLET_ID = 0x08, ///< MC23 (East) chiplet - OB0_CHIPLET_ID = 0x09, ///< OBus0 chiplet - PCI0_CHIPLET_ID = 0x0D, ///< PCIe0 chiplet - EP00_CHIPLET_ID = 0x10, ///< Quad0 chiplet (EX0/1) - EP05_CHIPLET_ID = 0x15, ///< Quad5 chiplet (EX10/11) - EC00_CHIPLET_ID = 0x20, ///< Core0 chiplet (Quad0, EX0, C0) - EC23_CHIPLET_ID = 0x37 ///< Core23 chiplet (Quad5, EX11, C1) -} p9_chiplet_id_t; - -typedef enum -{ - MC_MC01_0_RING_ID = 0x2, ///< MC01_0 / MC23_0 - MC_IOM01_0_RING_ID = 0x4, ///< IOM01_0 / IOM45_0 -} p9_mc_ring_id_t; - -typedef enum -{ - XB_IOX_0_RING_ID = 0x3, ///< IOX_0 - XB_IOX_2_RING_ID = 0x5, ///< IOX_2 - XB_PBIOX_0_RING_ID = 0x6, ///< PBIOX_0 - XB_PBIOX_2_RING_ID = 0x8 ///< PBIOX_2 -} p9_xb_ring_id_t; - -typedef enum -{ - P9C_MC_CHAN_RING_ID = 0x2, - P9C_MC_IO_RING_ID = 0x4, - P9C_MC_BIST_RING_ID = 0x8 -} p9c_mc_ring_id_t; - -typedef enum -{ - N2_PCIS0_0_RING_ID = 0x3, ///< PCIS0_0 -} p9_n2_ring_id_t; - -/** @brief Performs a hardware scom on a regular register. - * @param i_trgt The SCOM target. - * @param i_addr 32-bit SCOM address. - * @param o_val 64-bit returned value. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -int32_t SCOM_getScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t * o_val ); - -/** @brief Performs a hardware put scom on a regular register. - * @param i_trgt The SCOM target. - * @param i_addr 32-bit SCOM address. - * @param i_val 64-bit value to write to the address. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. -*/ -int32_t SCOM_putScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t i_val ); - -/** @brief Performs a hardware scom on an indirect-SCOM register. - * @param i_trgt The SCOM target. - * @param i_addr 64-bit SCOM address. - * @param o_val 32-bit returned value. - * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. - */ -int32_t SCOM_getIdScom( SCOM_Trgt_t i_trgt, uint64_t i_addr, uint32_t * o_val ); diff --git a/src/occ_gpe0/firdata/ast_mboxdd.c b/src/occ_gpe0/firdata/ast_mboxdd.c new file mode 100644 index 0000000..064bcca --- /dev/null +++ b/src/occ_gpe0/firdata/ast_mboxdd.c @@ -0,0 +1,326 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/ast_mboxdd.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file ast_mboxdd.C + * + * @brief Implementation of the PNOR Accesser using the AST MBOX protocol + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include +#include +#include +#include + +errorHndl_t writeRegSIO(uint8_t i_regAddr, uint8_t i_data) +{ + errorHndl_t l_err = NO_ERROR; + + do { + size_t reg_size = sizeof(uint8_t); + + /* Write out the register address */ + l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, + &i_regAddr, + reg_size ); + if( l_err ) { break; } + + /* Write out the register data */ + l_err = lpc_write( LPC_TRANS_IO, SIO_DATA_REG_2F, + &i_data, + reg_size ); + if( l_err ) { break; } + + } while(0); + + return l_err; +} + +errorHndl_t readRegSIO(uint8_t i_regAddr, uint8_t* o_data) +{ + errorHndl_t l_err = NO_ERROR; + + do { + size_t reg_size = sizeof(uint8_t); + + /* Write out the register address */ + l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, + &i_regAddr, + reg_size ); + if( l_err ) { break; } + + /* Read in the register data */ + l_err = lpc_read( LPC_TRANS_IO, SIO_DATA_REG_2F, + o_data, + reg_size ); + if( l_err ) { break; } + + } while(0); + + return l_err; +} + +errorHndl_t mboxOut(uint64_t i_addr, uint8_t i_byte) +{ + size_t len = sizeof(i_byte); + + return lpc_write( LPC_TRANS_IO, + i_addr + MBOX_IO_BASE, + &i_byte, + len ); +} + +errorHndl_t mboxIn(uint64_t i_addr, uint8_t *o_byte) +{ + size_t len = sizeof(uint8_t); + + return lpc_read( LPC_TRANS_IO, + i_addr + MBOX_IO_BASE, + o_byte, + len ); +} + +errorHndl_t doMessage( astMbox_t *io_mbox, mboxMessage_t *io_msg ) +{ + uint8_t* l_data = (uint8_t*)io_msg; + errorHndl_t l_err = NO_ERROR; + uint8_t l_stat1; + uint32_t l_loops = 0; + bool l_prot_error = false; + int i; + + io_msg->iv_seq = io_mbox->iv_mboxMsgSeq++; + + do + { + /* Write message out */ + for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++) + { + l_err = mboxOut(i, l_data[i]); + } + + if ( l_err ) + { + break; + } + + /* Clear status1 response bit as it was just set via reg write*/ + l_err = mboxOut(MBOX_STATUS_1, MBOX_STATUS1_RESP); + + if ( l_err ) + { + break; + } + + /* Ping BMC */ + l_err = mboxOut(MBOX_HOST_CTRL, MBOX_CTRL_INT_SEND); + + if ( l_err ) + { + break; + } + + /* Wait for response */ + while ( l_loops++ < MBOX_MAX_RESP_WAIT_US && !l_err ) + { + l_err = mboxIn(MBOX_STATUS_1, &l_stat1); + + if ( l_err ) + { + TRAC_ERR("doMessage error from MBOX_STATUS_1"); + break; + } + + if ( l_stat1 & MBOX_STATUS1_RESP ) + { + break; + } + sleep(1000); + } + + if ( l_err ) + { + TRAC_ERR( "Got error waiting for response !"); + break; + } + + if ( !(l_stat1 & MBOX_STATUS1_RESP) ) + { + TRAC_ERR( "Timeout waiting for response !"); + + // Don't try to interrupt the BMC anymore + l_err = mboxOut(MBOX_HOST_CTRL, 0); + if ( l_err) + { + //Note the command failed + TRAC_ERR( "Error communicating with MBOX daemon"); + TRAC_ERR( "Mbox status 1 reg: %x", l_stat1); + } + + // Tell the code below that we generated the error + // (not an LPC error) + l_prot_error = true; + break; + } + + /* Clear status */ + l_err = mboxOut(MBOX_STATUS_1, MBOX_STATUS1_RESP); + if (l_err) + { + TRAC_ERR( "Got error clearing status"); + break; + } + + // Remember some message fields before they get overwritten + // by the response + uint8_t old_seq = io_msg->iv_seq; + + // Read response + for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++) + { + l_err = mboxIn(i, &l_data[i]); + } + + if ( l_err ) + { + TRAC_ERR( "Got error reading response !"); + break; + } + + if (old_seq != io_msg->iv_seq) + { + TRAC_ERR( "bad sequence number in mbox message, got %d want %d", + io_msg->iv_seq, old_seq); + l_err = -1; + break; + } + + if (io_msg->iv_resp != MBOX_R_SUCCESS) + { + TRAC_ERR( "BMC mbox command failed with err %d", + io_msg->iv_resp); + l_err = -1; + // Tell code below that we generated the error (not an LPC error) + l_prot_error = true; + break; + } + + } + while(0); + + // If we got an LPC error, commit it and generate our own + if ( l_err && !l_prot_error ) + { + l_err = -1; + } + + return l_err; +} + +errorHndl_t initializeMbox(void) +{ + errorHndl_t l_errl = NO_ERROR; + + do + { + size_t reg_size = sizeof(uint8_t); + + //First need to unlock SIO registers + /* Send SuperIO password - send A5 twice to offset 0x2E */ + uint8_t data = SIO_PASSWORD_REG; + l_errl = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, + &data, reg_size ); + if( l_errl ) { break; } + + l_errl = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E, + &data, reg_size ); + if( l_errl ) { break; } + + //Second need to select Mailbox SIO Device + // Register 0x07 is device select reg + // Device 0x0E is the sio mailbox device + l_errl = writeRegSIO( SIO_DEVICE_SELECT_REG, SIO_MB ); + if( l_errl ) { break; } + + //First disable SIO Mailbox engine to configure it + // 0x30 - Enable/Disable Reg + // 0x00 - Disable Device (previously selected mailbox device) + l_errl = writeRegSIO( 0x30, 0x00 ); + + if (l_errl) + { + break; + } + + // Set MBOX Base Address + //Regs 0x60/0x61 are a BAR-like reg to configure the MBOX base address + l_errl = writeRegSIO( 0x60, (MBOX_IO_BASE >> 8) & 0xFF ); + + if (l_errl) + { + break; + } + + // Set other half of MBOX Base Address + l_errl = writeRegSIO( 0x61, MBOX_IO_BASE & 0xFF ); + + if (l_errl) + { + break; + } + + //Configure MBOX IRQs + //Regs 0x70 / 0x71 control that + l_errl = writeRegSIO( 0x70, MBOX_LPC_IRQ ); + + if (l_errl) + { + break; + } + + //Other half of MBOX IRQ Configuration + // 1 == Low level trigger + l_errl = writeRegSIO( 0x71, 1 ); + + if (l_errl) + { + break; + } + + //Re-enable Device now that base addr and IRQs are configured + // 1 == Enable Device + l_errl = writeRegSIO( 0x30, 0x01 ); + + if (l_errl) + { + break; + } + } + while(0); + + return l_errl; +} diff --git a/src/occ_gpe0/firdata/ast_mboxdd.h b/src/occ_gpe0/firdata/ast_mboxdd.h new file mode 100644 index 0000000..64ea40a --- /dev/null +++ b/src/occ_gpe0/firdata/ast_mboxdd.h @@ -0,0 +1,292 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/ast_mboxdd.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __AST_MBOXDD_H +#define __AST_MBOXDD_H + +/** @file ast_mboxdd.H + * @brief Provides the interfaces Aspeed MBOX hardware + */ + +/** + * @brief Provides the interface to exchange Mbox + * messages with the BMC. + */ + +enum +{ + BMC_MBOX_DATA_REGS = 14, + BMC_MBOX_ARGS_REGS = 11, + + /* Commands */ + MBOX_C_RESET_STATE = 0x01, + MBOX_C_GET_MBOX_INFO = 0x02, + MBOX_C_GET_FLASH_INFO = 0x03, + MBOX_C_CREATE_READ_WINDOW = 0x04, + MBOX_C_CLOSE_WINDOW = 0x05, + MBOX_C_CREATE_WRITE_WINDOW = 0x06, + MBOX_C_MARK_WRITE_DIRTY = 0x07, + MBOX_C_WRITE_FLUSH = 0x08, + MBOX_C_BMC_EVENT_ACK = 0x09, + MBOX_C_MARK_WRITE_ERASED = 0x0a, + + /* Responses */ + MBOX_R_SUCCESS = 0x01, + MBOX_R_PARAM_ERROR = 0x02, + MBOX_R_WRITE_ERROR = 0x03, + MBOX_R_SYSTEM_ERROR = 0x04, + MBOX_R_TIMEOUT = 0x05, + MBOX_R_BUSY = 0x06, + MBOX_R_WINDOW_ERROR = 0x07, + +}; + +enum{ + SIO_DEVICE_SELECT_REG = 0x07, /**< Regsiter to select SIO device */ + SIO_ADDR_REG_2E = 0x2E, /**< SuperIO address register */ + SIO_DATA_REG_2F = 0x2F, /**< SuperIO data register */ + SIO_PASSWORD_REG = 0xA5, /**< SuperIO password register (to be unlocked to access SIO) */ + SIO_MB = 0x0E, /**< SIO device: Mailbox */ + SIO_ENABLE_DEVICE = 0x01, /**< Enable SIO device by writing 1 to reg 30 of device */ + SIO_DISABLE_DEVICE = 0x00, /**< Disable SIO device by writing 0 to reg 30 of device */ +}; + + +typedef struct +{ + uint8_t iv_cmd; + uint8_t iv_seq; + uint8_t iv_args[BMC_MBOX_ARGS_REGS]; + uint8_t iv_resp; + +} mboxMessage_t; + +/** + * @brief Write a single byte into an SIO register + * + * @param[in] i_reg: Register to write + * @param[in] i_data: Data to write + * + * @return Error from operation + */ +errorHndl_t writeRegSIO(uint8_t i_regAddr, + uint8_t i_data ); + +/** + * @brief Read a single byte from an SIO register + * + * @param[in] i_reg: Register to read + * @param[in] o_data: Data that was read + * + * @return Error from operation + */ +errorHndl_t readRegSIO(uint8_t i_regAddr, + uint8_t* o_data ); + + +//Helper functions to create mbox messages to send to the BMC + +/** + * @brief 8-bit read accessor of the args section + * + * @param[in] i_msg: mboxMessage_t pointer to access args section + * @param[in] i_index: Index into args section to be read from + * + * @return data requested + */ +static inline uint8_t get8( mboxMessage_t *i_msg, uint8_t i_index) +{ + if ( i_index >= BMC_MBOX_ARGS_REGS ) + { + return 0; + } + + return i_msg->iv_args[i_index]; +} + +/** + * @brief 8-bit write accessor of the args section + * + * @param[in] i_msg: mboxMessage_t pointer to access args section + * @param[in] i_index: Index into args section to be written to + * @param[in] i_value: data to be written + */ +static inline void put8(mboxMessage_t *i_msg, uint8_t i_index, uint8_t i_value) +{ + if ( i_index >= BMC_MBOX_ARGS_REGS ) + { + return; + } + + i_msg->iv_args[i_index] = i_value; +} + +/** + * @brief 16-bit read accessor of the args section + * @param[in] i_msg: mboxMessage_t pointer to access args section + * @param[in] i_index: Index into args section to be read from + * + * @return data requested + */ +static inline uint16_t get16( mboxMessage_t *i_msg, uint8_t i_index ) +{ + if ( i_index >= (BMC_MBOX_ARGS_REGS-1) ) + { + return 0; + } + + return i_msg->iv_args[i_index] | (i_msg->iv_args[i_index + 1] << 8); +} + +/** + * @brief 16-bit write accessor of the args section + * + * @param[in] i_msg: mboxMessage_t pointer to access args section + * @param[in] i_index: Index into args section to be written to + * @param[in] i_value: data to be written + */ +static inline void put16(mboxMessage_t *i_msg, + uint8_t i_index, + uint16_t i_value) +{ + if ( i_index >= (BMC_MBOX_ARGS_REGS-1) ) + { + return; + } + + i_msg->iv_args[i_index] = i_value & 0xff; + i_msg->iv_args[i_index + 1] = i_value >> 8; +} + +/** + * @brief 32-bit read accessor of the args section + * + * @param[in] i_msg: mboxMessage_t pointer to access args section + * @param[in] i_index: Index into args section to be read from + * + * @return data requested + */ +static inline uint32_t get32( mboxMessage_t *i_msg, uint8_t i_index ) +{ + if ( i_index >= (BMC_MBOX_ARGS_REGS-3) ) + { + return 0; + } + + return i_msg->iv_args[i_index] | + (i_msg->iv_args[i_index + 1] << 8) | + (i_msg->iv_args[i_index + 2] << 16) | + (i_msg->iv_args[i_index + 3] << 24); +} + +/** + * @brief 32-bit write accessor of the args section + * + * @param[in] i_msg: mboxMessage_t pointer to access args section + * @param[in] i_index: Index into args section to be read from + */ +static inline void put32(mboxMessage_t *i_msg, + uint8_t i_index, + uint32_t i_value) +{ + if ( i_index >= (BMC_MBOX_ARGS_REGS-3) ) + { + return; + } + + i_msg->iv_args[i_index] = i_value & 0xff; + i_msg->iv_args[i_index + 1] = (i_value >> 8) & 0xff; + i_msg->iv_args[i_index + 2] = (i_value >> 16) & 0xff; + i_msg->iv_args[i_index + 3 ] = i_value >> 24; +} + +typedef struct { + + uint8_t iv_mboxMsgSeq; + mboxMessage_t iv_msg; + +} astMbox_t; + +/** + * @brief Send a message and receive the response + * + * @parm[in/out] io_mbox Mbox pointer to send message + * @parm[in/out] io_msg Message to send, contains the response on exit + * + * @return Error from operation + */ +errorHndl_t doMessage( astMbox_t *io_mbox, mboxMessage_t *io_msg ); + +enum +{ + MBOX_FLAG_REG = 0x0f, + MBOX_STATUS_0 = 0x10, + MBOX_STATUS_1 = 0x11, + MBOX_STATUS1_ATTN = 0x80, + MBOX_STATUS1_RESP = 0x20, + MBOX_BMC_CTRL = 0x12, + MBOX_CTRL_INT_STATUS = 0x80, + MBOX_CTRL_INT_MASK = 0x02, + MBOX_CTRL_INT_SEND = 0x01, + MBOX_HOST_CTRL = 0x13, + MBOX_BMC_INT_EN_0 = 0x14, + MBOX_BMC_INT_EN_1 = 0x15, + MBOX_HOST_INT_EN_0 = 0x16, + MBOX_HOST_INT_EN_1 = 0x17, + + MBOX_IO_BASE = 0x1000, + MBOX_LPC_IRQ = 0x9, + + MBOX_MAX_RESP_WAIT_US = 10000000, /* 10s timeout */ +}; + +/** + * @brief Initialize/Enable the MBox in the SIO + * + * @return Error from operation + */ +errorHndl_t initializeMbox( void ); + +/** + * @brief Write a byte to the mBox + * + * @parm[in] i_addr: Register offset in the mbox + * @parm[in] i_byte: Byte to write + * + * @return Error from operation +*/ +errorHndl_t mboxOut( uint64_t i_addr, uint8_t i_byte ); + +/** + * @brief Read a byte from the mBox + * + * @parm[in] i_addr: Register offset in the mbox + * @parm[out] o_byte: Byte read + * + * @return Error from operation + */ +errorHndl_t mboxIn( uint64_t i_addr, uint8_t *o_byte ); + +#endif /* __AST_MBOXDD_H */ diff --git a/src/occ_gpe0/firdata/ecc.c b/src/occ_gpe0/firdata/ecc.c new file mode 100644 index 0000000..6696678 --- /dev/null +++ b/src/occ_gpe0/firdata/ecc.c @@ -0,0 +1,272 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/ecc.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +/*#include */ +#include +#include + +#include +#include + +/** Matrix used for ECC calculation. + * + * Each row of this is the set of data word bits that are used for + * the calculation of the corresponding ECC bit. The parity of the + * bitset is the value of the ECC bit. + * + * ie. ECC[n] = eccMatrix[n] & data + * + * Note: To make the math easier (and less shifts in resulting code), + * row0 = ECC7. HW numbering is MSB, order here is LSB. + * + * These values come from the HW design of the ECC algorithm. + */ +static uint64_t eccMatrix[] = { + /*0000000000000000111010000100001000111100000011111001100111111111 */ + 0x0000e8423c0f99ff, + /*0000000011101000010000100011110000001111100110011111111100000000 */ + 0x00e8423c0f99ff00, + /*1110100001000010001111000000111110011001111111110000000000000000 */ + 0xe8423c0f99ff0000, + /*0100001000111100000011111001100111111111000000000000000011101000 */ + 0x423c0f99ff0000e8, + /*0011110000001111100110011111111100000000000000001110100001000010 */ + 0x3c0f99ff0000e842, + /*0000111110011001111111110000000000000000111010000100001000111100 */ + 0x0f99ff0000e8423c, + /*1001100111111111000000000000000011101000010000100011110000001111 */ + 0x99ff0000e8423c0f, + /*1111111100000000000000001110100001000010001111000000111110011001 */ + 0xff0000e8423c0f99 +}; + +/** Syndrome calculation matrix. + * + * Maps syndrome to flipped bit. + * + * To perform ECC correction, this matrix is a look-up of the bit + * that is bad based on the binary difference of the good and bad + * ECC. This difference is called the "syndrome". + * + * When a particular bit is on in the data, it cause a column from + * eccMatrix being XOR'd into the ECC field. This column is the + * "effect" of each bit. If a bit is flipped in the data then its + * "effect" is missing from the ECC. You can calculate ECC on unknown + * quality data and compare the ECC field between the calculated + * value and the stored value. If the difference is zero, then the + * data is clean. If the difference is non-zero, you look up the + * difference in the syndrome table to identify the "effect" that + * is missing, which is the bit that is flipped. + * + * Notice that ECC bit flips are recorded by a single "effect" + * bit (ie. 0x1, 0x2, 0x4, 0x8 ...) and double bit flips are identified + * by the UE status in the table. + * + * Bits are in MSB order. + */ +static uint8_t syndromeMatrix[] = { + ECC_GD, ECC_E7, ECC_E6, ECC_UE, ECC_E5, ECC_UE, ECC_UE, 47, + ECC_E4, ECC_UE, ECC_UE, 37, ECC_UE, 35, 39, ECC_UE, + ECC_E3, ECC_UE, ECC_UE, 48, ECC_UE, 30, 29, ECC_UE, + ECC_UE, 57, 27, ECC_UE, 31, ECC_UE, ECC_UE, ECC_UE, + ECC_E2, ECC_UE, ECC_UE, 17, ECC_UE, 18, 40, ECC_UE, + ECC_UE, 58, 22, ECC_UE, 21, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, 16, 49, ECC_UE, 19, ECC_UE, ECC_UE, ECC_UE, + 23, ECC_UE, ECC_UE, ECC_UE, ECC_UE, 20, ECC_UE, ECC_UE, + ECC_E1, ECC_UE, ECC_UE, 51, ECC_UE, 46, 9, ECC_UE, + ECC_UE, 34, 10, ECC_UE, 32, ECC_UE, ECC_UE, 36, + ECC_UE, 62, 50, ECC_UE, 14, ECC_UE, ECC_UE, ECC_UE, + 13, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, 61, 8, ECC_UE, 41, ECC_UE, ECC_UE, ECC_UE, + 11, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + 15, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, ECC_UE, 12, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_E0, ECC_UE, ECC_UE, 55, ECC_UE, 45, 43, ECC_UE, + ECC_UE, 56, 38, ECC_UE, 1, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, 25, 26, ECC_UE, 2, ECC_UE, ECC_UE, ECC_UE, + 24, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, 28, ECC_UE, + ECC_UE, 59, 54, ECC_UE, 42, ECC_UE, ECC_UE, 44, + 6, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + 5, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, 63, 53, ECC_UE, 0, ECC_UE, ECC_UE, ECC_UE, + 33, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + 3, ECC_UE, ECC_UE, 52, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + 7, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, 60, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, ECC_UE, ECC_UE, ECC_UE, 4, ECC_UE, ECC_UE, ECC_UE, + ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, ECC_UE, +}; + +/** Returns the parity of x, i.e. the number of 1-bits in x modulo 2. + * Replacement for __builtin_parityl + */ +uint8_t parity_check( uint64_t i_data ) +{ + int ones = 0; + size_t x; + for( x=0; x<(sizeof(i_data)*8); x++ ) + { + if( i_data & (0x8000000000000000ull >> x) ) + { + ones++; + } + } + return ones%2; +} + +/** Create the ECC field corresponding to a 8-byte data field + * + * @param[in] i_data - The 8 byte data to generate ECC for. + * @return The 1 byte ECC corresponding to the data. + */ +uint8_t generateECC(uint64_t i_data) +{ + uint8_t result = 0; + + int i = 0; + for (i = 0; i < 8; i++) + { + result |= (parity_check(eccMatrix[i] & i_data) << i); + } + + return result; +} + +/** Verify the data and ECC match or indicate how they are wrong. + * + * @param[in] i_data - The data to check ECC on. + * @param[in] i_ecc - The [supposed] ECC for the data. + * + * @return eccBitfield or 0-64. + * + * @retval GD - Indicates the data is good (matches ECC). + * @retval UE - Indicates the data is uncorrectable. + * @retval all others - Indication of which bit is incorrect. + */ +uint8_t verifyECC(uint64_t i_data, uint8_t i_ecc) +{ + return syndromeMatrix[generateECC(i_data) ^ i_ecc]; +} + +/** Correct the data and/or ECC. + * + * @param[in,out] io_data - Data to check / correct. + * @param[in,out] io_ecc - ECC to check / correct. + * + * @return eccBitfield or 0-64. + * + * @retval GD - Data is good. + * @retval UE - Data is uncorrectable. + * @retval all others - which bit was corrected. + */ +uint8_t correctECC(uint64_t* io_data, uint8_t* io_ecc) +{ + uint8_t badBit = verifyECC(*io_data, *io_ecc); + + if ((badBit != ECC_GD) && (badBit != ECC_UE)) /* Good is done, UE is hopeless. */ + { + /* Determine if the ECC or data part is bad, do bit flip. */ + if (badBit >= ECC_E7) + { + *io_ecc ^= (1 << (badBit - ECC_E7)); + } + else + { + *io_data ^= (1ul << (63 - badBit)); + } + } + return badBit; +} + +void injectECC(const uint8_t* i_src, + size_t i_srcSz, + uint8_t* o_dst) +{ + assert(0 == (i_srcSz % sizeof(uint64_t))); + + size_t i = 0; + size_t o = 0; + for(i = 0, o = 0; + i < i_srcSz; + i += sizeof(uint64_t), o += sizeof(uint64_t) + sizeof(uint8_t)) + { + /* Read data word, copy to destination. */ + uint64_t data = *((const uint64_t*)(&i_src[i])); + *((uint64_t*)(&o_dst[o])) = data; + data = be64toh(data); + + /* Calculate ECC, copy to destination. */ + uint8_t ecc = generateECC(data); + o_dst[o + sizeof(uint64_t)] = ecc; + } +} + +eccStatus removeECC(uint8_t* io_src, + uint8_t* o_dst, size_t i_dstSz) +{ + assert(0 == (i_dstSz % sizeof(uint64_t))); + + eccStatus rc = ECC_CLEAN; + + size_t i = 0, o = 0; + for(i = 0, o = 0; + o < i_dstSz; + i += sizeof(uint64_t) + sizeof(uint8_t), o += sizeof(uint64_t)) + { + /* Read data and ECC parts. */ + uint64_t data = *((uint64_t*)(&io_src[i])); + data = be64toh(data); + uint8_t ecc = io_src[i + sizeof(uint64_t)]; + + /* Calculate failing bit and fix data. */ + uint8_t badBit = correctECC(&data, &ecc); + + /* Return data to big endian. */ + data = htobe64(data); + + /* Perform correction and status update. */ + if (badBit == ECC_UE) + { + rc = ECC_UNCORRECTABLE; + } + else if (badBit != ECC_GD) + { + if (rc != ECC_UNCORRECTABLE) + { + rc = ECC_CORRECTED; + } + *((uint64_t*)(&io_src[i])) = data; + io_src[i + sizeof(uint64_t)] = ecc; + } + + /* Copy fixed data to destination buffer. */ + *((uint64_t*)(&o_dst[o])) = data; + } + + return rc; +} + diff --git a/src/occ_gpe0/firdata/ecc.h b/src/occ_gpe0/firdata/ecc.h new file mode 100644 index 0000000..12ffe4e --- /dev/null +++ b/src/occ_gpe0/firdata/ecc.h @@ -0,0 +1,76 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/ecc.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __PNOR_ECC_H +#define __PNOR_ECC_H + +#include + +/** @file ecc.H + * @brief Interfaces for the P8 8-byte ECC algorithm. + */ + +/** Status for the ECC removal function. */ +typedef uint8_t eccStatus; +#define ECC_CLEAN 0x00 /*< No ECC Error was detected. */ +#define ECC_CORRECTED 0x01 /*< ECC error detected and corrected. */ +#define ECC_UNCORRECTABLE 0x02 /*< ECC error detected and uncorrectable. */ + +/** Bit field identifiers for syndrome calculations. */ +typedef uint8_t eccBitfields; +#define ECC_GD 0xff /*< Good ECC matches. */ +#define ECC_UE 0xfe /*< Uncorrectable. */ +#define ECC_E0 71 /*< Error in ECC bit 0 */ +#define ECC_E1 70 /*< Error in ECC bit 1 */ +#define ECC_E2 69 /*< Error in ECC bit 2 */ +#define ECC_E3 68 /*< Error in ECC bit 3 */ +#define ECC_E4 67 /*< Error in ECC bit 4 */ +#define ECC_E5 66 /*< Error in ECC bit 5 */ +#define ECC_E6 65 /*< Error in ECC bit 6 */ +#define ECC_E7 64 /*< Error in ECC bit 7 */ + +/** Inject ECC into a data stream. + * + * @param[in] i_src - Source data to create ECC on. + * @param[in] i_srcSz - Size in bytes of source data. + * @param[out] o_dst - Destination buffer of data+ECC. + * + * @note i_srcSz must be a multiple of 8 bytes. + */ +void injectECC(const uint8_t* i_src, size_t i_srcSz, + uint8_t* o_dst); + +/** Remove ECC from a data stream. + * + * @param[in,out] io_src - Source data+ECC stream. + * @param[out] o_dst - Destination buffer for data only. + * @param[in] i_dstSz - Size in bytes of destination ((srcSz / 9) * 8). + * + * @note i_dstSz must be a multiple of 8 bytes. + */ +eccStatus removeECC(uint8_t* io_src, + uint8_t* o_dst, size_t i_dstSz); + + +#endif diff --git a/src/occ_gpe0/firdata/firData.c b/src/occ_gpe0/firdata/firData.c new file mode 100644 index 0000000..299f92b --- /dev/null +++ b/src/occ_gpe0/firdata/firData.c @@ -0,0 +1,1389 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/firData.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +#include + +#include +#include +#include +#include +#include + +/** Keeps track of pointers to register lists in the HOMER data for each target + * type. */ +typedef struct +{ + uint32_t * glbl; /*/< Global registers */ + uint32_t * fir; /*/< Normal FIRs */ + uint32_t * reg; /*/< Normal registers */ + uint64_t * idFir; /*/< Indirect-SCOM FIRs */ + uint64_t * idReg; /*/< Indirect-SCOM registers */ +} FirData_ListPointers_t; + +/** Contains pointers and sizes for the HOMER and PNOR data buffers. */ +typedef struct +{ + uint8_t * hBuf; /*/< Pointer to the HOMER data buffer */ + uint32_t maxHBufSize; /*/< Maximum size of the HOMER data buffer */ + HOMER_Data_t * hData; /*/< Pointer to the HOMER header data */ + + uint8_t * pBuf; /*/< Pointer to the PNOR data buffer */ + uint32_t maxPBufSize; /*/< Maximum size of the PNOR data buffer */ + PNOR_Data_t * pData; /*/< Pointer to the PNOR header data */ + uint32_t pBufSize; /*/< Current size of the PNOR data buffer */ + + FirData_ListPointers_t hPtrs[TRGT_MAX]; /*/< Pointers to the reg lists */ + + HOMER_ChipSpecAddr_t * ecDepReg; /*/< EC dependent regs */ + +} FirData_t; + + +/** We move the chiplet exist bit fields into this structure left */ +/** justified for easy checking of the fields with a mask */ +typedef struct +{ + uint32_t xbusMask; + uint32_t obusMask; + uint32_t ecMask; + + uint32_t eqMask; + uint32_t exMask; + uint32_t mcbist_mc_Mask; + uint32_t mcs_mi_Mask; + uint32_t mca_dmi_Mask; + + uint32_t cappMask; + uint32_t pecMask; + uint32_t phbMask; + +} FirData_existBits_t; + +/* Uncomment for additional debug traces */ +#if 0 +#define DEBUG_PRD_CHKSTOP_ANALYSIS +#endif + +/*------------------------------------------------------------------------------ */ + +/** @brief Add generic data to the PNOR buffer. + * @param io_fd The FIR data stuct. + * @param i_data Pointer to the data to add to the buffer. + * @param i_dataSize Size of the data to add to the buffer. + * @return True, if where is no room to add the new data. False, otherwise. + */ +bool FirData_addDataToPnor( FirData_t * io_fd, void * i_data, + uint32_t i_dataSize ) +{ + bool full = (io_fd->maxPBufSize < io_fd->pBufSize + i_dataSize); + + if ( full ) + { + /* Indicate the PNOR data is full. */ + io_fd->pData->full = 1; + } + else + { + /* Copy data to PNOR buffer. */ + memcpy( &io_fd->pBuf[io_fd->pBufSize], i_data, i_dataSize ); + io_fd->pBufSize += i_dataSize; + } + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief SCOMs hardware and adds a normal register to PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param i_addr 32-bit address to SCOM. + * @param o_nonZero True if the value of the register was non-zero. False, + * otherwise. + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addRegToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, uint32_t i_addr, + bool * o_nonZero ) +{ + bool full = false; + + int32_t rc = 0; + PNOR_Reg_t reg = { i_addr, 0 }; + + *o_nonZero = false; + + do + { + rc = SCOM_getScom( i_sTrgt, i_addr, &(reg.val) ); + if ( SUCCESS != rc ) + { + TRAC_ERR( "[FirData_addRegToPnor] t=%d p=%d u=%d rc=%d " + "addr=0x%08x val=0x%08x%08x", i_sTrgt.type, + i_sTrgt.procPos, i_sTrgt.procUnitPos, rc, i_addr, + (uint32_t)(reg.val >> 32), (uint32_t)reg.val ); + + if ( io_pTrgt->scomErrs < PNOR_Trgt_MAX_SCOM_ERRORS ) + io_pTrgt->scomErrs++; + + break; + } + + if ( 0 == reg.val ) break; // Skip zero value registers. + + full = FirData_addDataToPnor( io_fd, ®, sizeof(reg) ); + if ( full ) break; + + *o_nonZero = true; + + if ( io_pTrgt->regs < PNOR_Trgt_MAX_REGS_PER_TRGT ) + io_pTrgt->regs++; + + } while (0); + +#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS + TRAC_INFO(" addToPnor: Type:%d Pos:%d Unit:%d Addr:%X Full:%d", + i_sTrgt.type, i_sTrgt.procPos, i_sTrgt.procUnitPos, + i_addr, full ); +#endif + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief SCOMs hardware and add a indirect-SCOM register to PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param i_sTrgt Target to SCOM. + * @param i_addr 64-bit address to SCOM. + * @param o_nonZero True if the value of the register was non-zero. False, + * otherwise. + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addIdRegToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, uint64_t i_addr, + bool * o_nonZero ) +{ + bool full = false; + + int32_t rc = 0; + PNOR_IdReg_t reg = { i_addr, 0 }; + + *o_nonZero = false; + + do + { + rc = SCOM_getIdScom( i_sTrgt, i_addr, &(reg.val) ); + if ( SUCCESS != rc ) + { + if ( io_pTrgt->scomErrs < PNOR_Trgt_MAX_SCOM_ERRORS ) + io_pTrgt->scomErrs++; + break; + } + + if ( 0 == reg.val ) break; // Skip zero value registers. + + full = FirData_addDataToPnor( io_fd, ®, sizeof(reg) ); + if ( full ) break; + + *o_nonZero = true; + + if ( io_pTrgt->idRegs < PNOR_Trgt_MAX_ID_REGS_PER_TRGT ) + io_pTrgt->idRegs++; + + } while (0); + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief Iterates a list of global registers and adds them to the PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param o_noAttn True, if the global registers showed no active attentions + * on the target. False, otherwise. + * @param i_chipStruct Provides chipType and ecLevel we need + * for EC dependent regs + * + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addGlblsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, bool * o_noAttn, + HOMER_Chip_t *i_chipStruct ) +{ + bool full = false; + bool l_isAnyGlobal = false; /* true when we find global reg */ + bool l_isAnyNonZero = false; /* true if ATTN is active on any reg */ + + uint8_t t = i_sTrgt.type; + uint8_t cnt = io_fd->hData->regCounts[t][REG_GLBL]; + + uint32_t i = 0; + + uint32_t addr = 0; + bool nonZero = false; + + *o_noAttn = false; /* Must be false if there are no global regs. */ + + if ( 0 != cnt ) + { + /** If we get here, we have GLOBALS for this target **/ + l_isAnyGlobal = true; + + for ( i = 0; i < cnt; i++ ) + { + addr = io_fd->hPtrs[t].glbl[i]; + nonZero = false; + + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, + &nonZero ); + if ( full ) break; + + if ( nonZero ) l_isAnyNonZero = true; + } + } + + + /** Handle EC dependent registers, if any */ + HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; + cnt = io_fd->hData->ecDepCounts; + + /** We have a structure with one element for each EC dep address. */ + /** Need to loop thru and verify we have same regType among */ + /** other things prior to using the address. */ + for ( i = 0; i < cnt; i++ ) + { +#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS + TRAC_INFO(" addGlblsToPnor In/Array: chipType:%X::%X trgType:%X::%X" + " regType:%X::%X ecLevel %X::%X", + i_chipStruct->chipType, l_ecAddrtPtr->chipType, + t, l_ecAddrtPtr->trgtType, + REG_GLBL, l_ecAddrtPtr->regType, + i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); +#endif + + /** Need same chipType (nimbus,cumulus,etc..), same target type, */ + /** same register type and EC level must match too */ + if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && + (l_ecAddrtPtr->trgtType == t ) && + (l_ecAddrtPtr->regType == REG_GLBL) && + (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) + ) + { + /** If we get here, we have GLOBALS for this target **/ + l_isAnyGlobal = true; + + /* address is right justified in 64 bits */ + addr = (uint32_t)(l_ecAddrtPtr->address); + nonZero = false; + + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, + &nonZero ); + if ( full ) break; + + if ( nonZero ) l_isAnyNonZero = true; + } /* end if we found an EC dep reg */ + + /* prep pointer for next element (if any) */ + l_ecAddrtPtr++; + + } /** end EC dependent reg loop */ + + /* If we have no GLOBALS, we want to collect other regs */ + /* so then we want to return 'attn is active)'. */ + /* If we have GLOBALS, then we need non-zero reg to */ + /* collect the rest of the regs (attn is active). */ + if ( (true == l_isAnyGlobal) && (false == l_isAnyNonZero) ) + { + /* This indicates we won't collect additional regs */ + *o_noAttn = true; /* starts out as false */ + } + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief Iterates a list of FIRs and adds them to the PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param i_chipStruct Provides chipType and ecLevel we need + * for EC dependent regs + * + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addFirsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, + HOMER_Chip_t *i_chipStruct ) +{ + bool full = false; + + uint8_t t = i_sTrgt.type; + uint8_t cnt = io_fd->hData->regCounts[t][REG_FIR]; + + uint32_t i = 0; + + uint32_t addr = 0; + bool nonZero = false; + bool tmp = false; /* ignored, not used */ + + for ( i = 0; i < cnt; i++ ) + { + addr = io_fd->hPtrs[t].fir[i]; + nonZero = false; + + /* Add FIR */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &nonZero ); + if ( full ) break; + + /* Add MASK */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 3, &tmp ); + if ( full ) break; + + if ( nonZero ) + { + /* Add ACT0 */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 6, + &tmp ); + if ( full ) break; + + /* Add ACT1 */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 7, + &tmp ); + if ( full ) break; + } + } + + + /** Handle EC dependent registers, if any */ + HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; + cnt = io_fd->hData->ecDepCounts; + + /** We have a structure with one element for each EC dep address. */ + /** Need to loop thru and verify we have same regType among */ + /** other things prior to using the address. */ + for ( i = 0; i < cnt; i++ ) + { +#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS + TRAC_INFO(" addFirsToPnor In/Array: chipType:%X::%X trgType:%X::%X" + " regType:%X::%X ecLevel %X::%X", + i_chipStruct->chipType, l_ecAddrtPtr->chipType, + t, l_ecAddrtPtr->trgtType, + REG_GLBL, l_ecAddrtPtr->regType, + i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); +#endif + + /** Need same chipType (nimbus,cumulus,etc..), same target type, */ + /** same register type and EC level must match too */ + if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && + (l_ecAddrtPtr->trgtType == t ) && + (l_ecAddrtPtr->regType == REG_FIR) && + (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) + ) + { /* address is right justified in 64 bits */ + addr = (uint32_t)(l_ecAddrtPtr->address); + nonZero = false; + + /* Add FIR */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &nonZero ); + if ( full ) break; + + /* Add MASK */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 3, &tmp ); + if ( full ) break; + + if ( nonZero ) + { + /* Add ACT0 */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 6, + &tmp ); + if ( full ) break; + + /* Add ACT1 */ + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr + 7, + &tmp ); + if ( full ) break; + } + + } /* end if we found an EC dep reg */ + + /* prep pointer for next element (if any) */ + l_ecAddrtPtr++; + + } /** end EC dependent reg loop */ + + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief Iterates a list of REGs and adds them to the PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param i_chipStruct Provides chipType and ecLevel we need + * for EC dependent regs + * + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addRegsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, + HOMER_Chip_t *i_chipStruct ) +{ + bool full = false; + + uint8_t t = i_sTrgt.type; + uint8_t cnt = io_fd->hData->regCounts[t][REG_REG]; + + uint32_t i = 0; + + uint32_t addr = 0; + bool tmp = false; /* ignored, not used */ + + for ( i = 0; i < cnt; i++ ) + { + addr = io_fd->hPtrs[t].reg[i]; + + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &tmp ); + if ( full ) break; + } + + /** Handle EC dependent registers, if any */ + HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; + cnt = io_fd->hData->ecDepCounts; + + /** We have a structure with one element for each EC dep address. */ + /** Need to loop thru and verify we have same regType among */ + /** other things prior to using the address. */ + for ( i = 0; i < cnt; i++ ) + { +#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS + TRAC_INFO(" addRegsToPnor In/Array: chipType:%X::%X trgType:%X::%X" + " regType:%X::%X ecLevel %X::%X", + i_chipStruct->chipType, l_ecAddrtPtr->chipType, + t, l_ecAddrtPtr->trgtType, + REG_GLBL, l_ecAddrtPtr->regType, + i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); +#endif + + /** Need same chipType (nimbus,cumulus,etc..), same target type, */ + /** same register type and EC level must match too */ + if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && + (l_ecAddrtPtr->trgtType == t ) && + (l_ecAddrtPtr->regType == REG_REG) && + (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) + ) + { /* address is right justified in 64 bits */ + addr = (uint32_t)(l_ecAddrtPtr->address); + + full = FirData_addRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, + &tmp ); + if ( full ) break; + } /* end if we found an EC dep reg */ + + /* prep pointer for next element (if any) */ + l_ecAddrtPtr++; + + } /** end EC dependent reg loop */ + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief Iterates a list of IDFIRs and adds them to the PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param i_chipStruct Provides chipType and ecLevel we need + * for EC dependent regs + * + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addIdFirsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, + HOMER_Chip_t *i_chipStruct ) +{ + bool full = false; + + uint8_t t = i_sTrgt.type; + uint8_t cnt = io_fd->hData->regCounts[t][REG_IDFIR]; + + uint32_t i = 0; + + uint64_t addr = 0; + bool nonZero = false; + bool tmp = false; /* ignored, not used */ + + for ( i = 0; i < cnt; i++ ) + { + addr = io_fd->hPtrs[t].idFir[i]; + nonZero = false; + + /* Add FIR */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, + &nonZero ); + if ( full ) break; + + /* Add MASK */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, + addr + 0x300000000ll, &tmp ); + if ( full ) break; + + if ( nonZero ) + { + /* Add ACT0 */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, + addr + 0x600000000ll, &tmp ); + if ( full ) break; + + /* Add ACT1 */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, + addr + 0x700000000ll, &tmp ); + if ( full ) break; + } + } + + + /** Handle EC dependent registers, if any */ + HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; + cnt = io_fd->hData->ecDepCounts; + + /** We have a structure with one element for each EC dep address. */ + /** Need to loop thru and verify we have same regType among */ + /** other things prior to using the address. */ + for ( i = 0; i < cnt; i++ ) + { +#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS + TRAC_INFO(" addIdFirsToPnor In/Array: chipType:%X::%X trgType:%X::%X" + " regType:%X::%X ecLevel %X::%X", + i_chipStruct->chipType, l_ecAddrtPtr->chipType, + t, l_ecAddrtPtr->trgtType, + REG_GLBL, l_ecAddrtPtr->regType, + i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); +#endif + + /** Need same chipType (nimbus,cumulus,etc..), same target type, */ + /** same register type and EC level must match too */ + if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && + (l_ecAddrtPtr->trgtType == t ) && + (l_ecAddrtPtr->regType == REG_IDFIR) && + (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) + ) + { /* need full 64 bit address here */ + addr = l_ecAddrtPtr->address; + nonZero = false; + + /* Add FIR */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, + &nonZero ); + if ( full ) break; + + /* Add MASK */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, + addr + 0x300000000ll, &tmp ); + if ( full ) break; + + if ( nonZero ) + { + /* Add ACT0 */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, + addr + 0x600000000ll, &tmp ); + if ( full ) break; + + /* Add ACT1 */ + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, + addr + 0x700000000ll, &tmp ); + if ( full ) break; + } + + } /* end if we found an EC dep reg */ + + /* prep pointer for next element (if any) */ + l_ecAddrtPtr++; + + } /** end EC dependent reg loop */ + + return full; +} + +/*------------------------------------------------------------------------------ */ + +/** @brief Iterates a list of IDREGs and adds them to the PNOR. + * @param io_fd The FIR data stuct. + * @param io_pTrgt Pointer to PNOR target. + * @param i_sTrgt SCOM target. + * @param i_chipStruct Provides chipType and ecLevel we need + * for EC dependent regs + * + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addIdRegsToPnor( FirData_t * io_fd, PNOR_Trgt_t * io_pTrgt, + SCOM_Trgt_t i_sTrgt, + HOMER_Chip_t *i_chipStruct ) +{ + bool full = false; + + uint8_t t = i_sTrgt.type; + uint8_t cnt = io_fd->hData->regCounts[t][REG_IDREG]; + + uint32_t i = 0; + + uint64_t addr = 0; + bool tmp = false; /* ignored, not used */ + + for ( i = 0; i < cnt; i++ ) + { + addr = io_fd->hPtrs[t].idReg[i]; + + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &tmp ); + if ( full ) break; + } + + + /** Handle EC dependent registers, if any */ + HOMER_ChipSpecAddr_t *l_ecAddrtPtr = io_fd->ecDepReg; + cnt = io_fd->hData->ecDepCounts; + + /** We have a structure with one element for each EC dep address. */ + /** Need to loop thru and verify we have same regType among */ + /** other things prior to using the address. */ + for ( i = 0; i < cnt; i++ ) + { +#ifdef DEBUG_PRD_CHKSTOP_ANALYSIS + TRAC_INFO(" addIdRegsToPnor In/Array: chipType:%X::%X trgType:%X::%X" + " regType:%X::%X ecLevel %X::%X", + i_chipStruct->chipType, l_ecAddrtPtr->chipType, + t, l_ecAddrtPtr->trgtType, + REG_GLBL, l_ecAddrtPtr->regType, + i_chipStruct->chipEcLevel, l_ecAddrtPtr->ddLevel ); +#endif + + /** Need same chipType (nimbus,cumulus,etc..), same target type, */ + /** same register type and EC level must match too */ + if ( (l_ecAddrtPtr->chipType == i_chipStruct->chipType) && + (l_ecAddrtPtr->trgtType == t ) && + (l_ecAddrtPtr->regType == REG_IDREG) && + (l_ecAddrtPtr->ddLevel == i_chipStruct->chipEcLevel) + ) + { /* Using full 64 bit address here */ + addr = l_ecAddrtPtr->address; + + full = FirData_addIdRegToPnor( io_fd, io_pTrgt, i_sTrgt, addr, &tmp ); + if ( full ) break; + } /* end if we found an EC dep reg */ + + /* prep pointer for next element (if any) */ + l_ecAddrtPtr++; + + } /** end EC dependent reg loop */ + + + return full; +} + + +/*------------------------------------------------------------------------------ */ + +/** @brief Adds a target to the PNOR. + * @param io_fd The FIR data stuct. + * @param i_sTrgt SCOM Target. + * @param o_noAttn True, if the global registers showed no active + * attentions on the target. False, otherwise. + * @param i_chipStruct Provides chipType and ecLevel we need + * for EC dependent regs + * + * @return True if the PNOR buffer is full, false if there was room. + */ +bool FirData_addTrgtToPnor( FirData_t * io_fd, SCOM_Trgt_t i_sTrgt, + bool * o_noAttn, HOMER_Chip_t *i_chipStruct ) +{ + bool full = false; + + PNOR_Trgt_t * pTrgt = (PNOR_Trgt_t *)(&io_fd->pBuf[io_fd->pBufSize]); + + PNOR_Trgt_t tmp_pTrgt = PNOR_getTrgt( i_sTrgt.type, i_sTrgt.procPos, + i_sTrgt.procUnitPos ); + + *o_noAttn = false; /* Must be false if there are no global regs. */ + + TRAC_IMP( "FIRDATA: t=%d p=%d u=%d FSI=0x%08x isM=%c", i_sTrgt.type, + i_sTrgt.procPos, i_sTrgt.procUnitPos, i_sTrgt.fsiBaseAddr, + i_sTrgt.isMaster ? 'T' : 'F' ); + + do + { + /* Add the target info to PNOR. */ + full = FirData_addDataToPnor( io_fd, &tmp_pTrgt, sizeof(tmp_pTrgt) ); + if ( full ) break; + + /* Update the number of targets in the PNOR data. */ + io_fd->pData->trgts++; + + /* NOTE: Must add all regular registers (REG_GLBL, REG_FIR, REG_REG) + * before all indirect-SCOM registers. Also, must check REG_GLBL + * registers first to determine whether it is necessary to do the + * other registers. */ + + /* Add the GLBLs. */ + full = FirData_addGlblsToPnor( io_fd, pTrgt, i_sTrgt, o_noAttn, i_chipStruct ); + if ( full || *o_noAttn ) break; + + /* Add the FIRs. */ + full = FirData_addFirsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); + if ( full ) break; + + /* Add the REGs. */ + full = FirData_addRegsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); + if ( full ) break; + + /* Add the IDFIRs. */ + full = FirData_addIdFirsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); + if ( full ) break; + + /* Add the IDREGs. */ + full = FirData_addIdRegsToPnor( io_fd, pTrgt, i_sTrgt, i_chipStruct ); + if ( full ) break; + + } while (0); + + return full; +} + + +/*------------------------------------------------------------------------------ */ + +/** @brief Iterates through configured targets and adds the data to PNOR. + * @param io_fd The FIR data stuct. + */ +void FirData_addTrgtsToPnor( FirData_t * io_fd ) +{ + bool full = false; + bool noAttn = false; + + uint8_t p = 0; + uint8_t u = 0; + uint8_t l_unit = 0; + + bool isM = false; + uint32_t fsi = 0; + + SCOM_Trgt_t sTrgt; + FirData_existBits_t l_existBits; + + do + { + memset(&l_existBits, 0x00, sizeof(FirData_existBits_t) ); + + /* Point past HOMER header to first chiplet info */ + /* The HOMER_Data_t struct may have some padding added after the struct + * to ensure the HOMER_Chip_t structs are 4-byte word aligned. */ + uint32_t sz_word = sizeof(uint32_t); + uint32_t pad = (sz_word - (sizeof(HOMER_Data_t) % sz_word)) % sz_word; + uint8_t *l_bytePtr = io_fd->hBuf + sizeof(HOMER_Data_t) + pad; + HOMER_Chip_t *l_chipPtr = NULL; + + TRAC_INFO("AddTgtsMain:numChips:%d", io_fd->hData->chipCount); + + /* Iterate ALL CHIPs */ + for ( p = 0; p < io_fd->hData->chipCount; p++ ) + { + l_chipPtr = (HOMER_Chip_t *)l_bytePtr; + + /* get FSI base address and chip position (proc or centaur) */ + fsi = l_chipPtr->fsiBaseAddr; + p = l_chipPtr->chipPos; + + TRAC_INFO( " AddTgtsMain:ChipType:%d ChipNumber:%d", + l_chipPtr->chipType, p ); + + /* Is this a PROC or Centaur chip ? */ + if ( (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) || + (HOMER_CHIP_CUMULUS == l_chipPtr->chipType) ) + { + /* To access the 'chiplet exist' structure */ + l_bytePtr += sizeof(HOMER_Chip_t); + + /* 'Existing chiplet area' varies in size */ + if (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) + { + HOMER_ChipNimbus_t *l_nimExistBitPtr = + (HOMER_ChipNimbus_t *)l_bytePtr; + + /* get master proc indicator */ + isM = l_nimExistBitPtr->isMaster; + + /* Exist bit structure can differ so move to */ + /* common format and left justify for ease of use */ + l_existBits.xbusMask = ((uint32_t)(l_nimExistBitPtr->xbusMask)) + << (32 - MAX_XBUS_PER_PROC); + l_existBits.obusMask = ((uint32_t)(l_nimExistBitPtr->obusMask)) + << (32 - MAX_OBUS_PER_PROC); + l_existBits.ecMask = ((uint32_t)(l_nimExistBitPtr->ecMask)) + << (32 - MAX_EC_PER_PROC); + l_existBits.eqMask = ((uint32_t)(l_nimExistBitPtr->eqMask)) + << (32 - MAX_EQ_PER_PROC); + l_existBits.exMask = ((uint32_t)(l_nimExistBitPtr->exMask)) + << (32 - MAX_EX_PER_PROC); + l_existBits.mcbist_mc_Mask = ((uint32_t)(l_nimExistBitPtr->mcbistMask)) + << (32 - MAX_MCBIST_PER_PROC); + l_existBits.mcs_mi_Mask = ((uint32_t)(l_nimExistBitPtr->mcsMask)) + << (32 - MAX_MCS_PER_PROC); + l_existBits.mca_dmi_Mask = ((uint32_t)(l_nimExistBitPtr->mcaMask)) + << (32 - MAX_MCA_PER_PROC); + l_existBits.cappMask = ((uint32_t)(l_nimExistBitPtr->cappMask)) + << (32 - MAX_CAPP_PER_PROC); + l_existBits.pecMask = ((uint32_t)(l_nimExistBitPtr->pecMask)) + << (32 - MAX_PEC_PER_PROC); + l_existBits.phbMask = ((uint32_t)(l_nimExistBitPtr->phbMask)) + << (32 - MAX_PHB_PER_PROC); + + /* advance our pointer to next chip type */ + l_bytePtr += sizeof(HOMER_ChipNimbus_t); + + } /* if nimbus */ + else if (HOMER_CHIP_CUMULUS == l_chipPtr->chipType) + { + HOMER_ChipCumulus_t *l_cumExistBitPtr = + (HOMER_ChipCumulus_t *)l_bytePtr; + + /* get master proc indicator */ + isM = l_cumExistBitPtr->isMaster; + + /* Exist bit structure can differ so move to */ + /* common format and left justify for ease of use */ + l_existBits.xbusMask = ((uint32_t)(l_cumExistBitPtr->xbusMask)) + << (32 - MAX_XBUS_PER_PROC); + l_existBits.obusMask = ((uint32_t)(l_cumExistBitPtr->obusMask)) + << (32 - MAX_OBUS_PER_PROC); + l_existBits.ecMask = ((uint32_t)(l_cumExistBitPtr->ecMask)) + << (32 - MAX_EC_PER_PROC); + l_existBits.eqMask = ((uint32_t)(l_cumExistBitPtr->eqMask)) + << (32 - MAX_EQ_PER_PROC); + l_existBits.exMask = ((uint32_t)(l_cumExistBitPtr->exMask)) + << (32 - MAX_EX_PER_PROC); + l_existBits.mcbist_mc_Mask = ((uint32_t)(l_cumExistBitPtr->mcMask)) + << (32 - MAX_MC_PER_PROC); + l_existBits.mcs_mi_Mask = ((uint32_t)(l_cumExistBitPtr->miMask)) + << (32 - MAX_MI_PER_PROC); + l_existBits.mca_dmi_Mask = ((uint32_t)(l_cumExistBitPtr->dmiMask)) + << (32 - MAX_DMI_PER_PROC); + l_existBits.cappMask = ((uint32_t)(l_cumExistBitPtr->cappMask)) + << (32 - MAX_CAPP_PER_PROC); + l_existBits.pecMask = ((uint32_t)(l_cumExistBitPtr->pecMask)) + << (32 - MAX_PEC_PER_PROC); + l_existBits.phbMask = ((uint32_t)(l_cumExistBitPtr->phbMask)) + << (32 - MAX_PHB_PER_PROC); + + /* advance our pointer to next chip type */ + l_bytePtr += sizeof(HOMER_ChipCumulus_t); + } /* else if cumulus */ + + TRAC_INFO( " Masks XBUS:%X OBUS:%X EC:%X EQ:%X EX:%X CAPP:%X PEC:%X PHB:%X", + l_existBits.xbusMask, l_existBits.obusMask, l_existBits.ecMask, + l_existBits.eqMask, l_existBits.exMask, l_existBits.cappMask, + l_existBits.pecMask, l_existBits.phbMask ); + TRAC_INFO( " Masks MCBIST:%X MCS:%X MCA:%X", + l_existBits.mcbist_mc_Mask, l_existBits.mcs_mi_Mask, + l_existBits.mca_dmi_Mask ); + + /* Add this PROC to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_PROC, p, 0, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + /* noAttn is true when we have global regs but none */ + /* indicate an attention is present */ + if ( full ) break; + if ( noAttn ) continue; /* Skip other proc chiplets */ + + + /* gather other chiplets on the processor */ + for ( u = 0; u < MAX_XBUS_PER_PROC; u++ ) + { + /* Check if the XBUS is configured. */ + if ( 0 == (l_existBits.xbusMask & (0x80000000 >> u)) ) continue; + + /* Add this XBUS to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_XBUS, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + } + if ( full ) break; + + /* gather other chiplets on the processor */ + for ( u = 0; u < MAX_OBUS_PER_PROC; u++ ) + { + /* Check if the OBUS is configured. */ + if ( 0 == (l_existBits.obusMask & (0x80000000 >> u)) ) continue; + + /* Add this OBUS to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_OBUS, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + } + if ( full ) break; + + /* gather more proc chiplets */ + for ( u = 0; u < MAX_CAPP_PER_PROC; u++ ) + { + /* Check if the CAPP is configured. */ + if ( 0 == (l_existBits.cappMask & (0x80000000 >> u)) ) continue; + + /* Add this CAPP to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_CAPP, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + } + if ( full ) break; + + /* gather other chiplets on the processor */ + for ( u = 0; u < MAX_PEC_PER_PROC; u++ ) + { + /* Check if the PEC is configured. */ + if ( 0 == (l_existBits.pecMask & (0x80000000 >> u)) ) continue; + + /* Add this PEC to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_PEC, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + if ( noAttn ) continue; /* Skip the rest */ + + /* gather PHB's under the PEC */ + /* ************************** */ + /* PEC0-> PHB0 */ + /* PEC1-> PHB1 PHB2 */ + /* PEC2-> PHB3 PHB4 PHB5 */ + /* ************************** */ + uint32_t l_PhbPos; + + /* u will be 0, l_unit 0 */ + /* u will be 1, l_unit 0 and 1 */ + /* u will be 2, l_unit 0 and 1 and 2 */ + for ( l_unit = 0; l_unit < (u+1); l_unit++ ) + { + l_PhbPos = u + l_unit; + /** When we hit PEC2, need to bump PHB position */ + if ((MAX_PEC_PER_PROC - 1) == u) + { + l_PhbPos++; + } /* if last PEC unit */ + + /* Check if the PHB is configured. */ + if ( 0 == (l_existBits.phbMask & (0x80000000 >> l_PhbPos)) ) continue; + + /* Add this PHB to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_PHB, p, l_PhbPos, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + if ( noAttn ) continue; /* Skip the rest */ + + } /* end for on PHB chiplet */ + if ( full ) break; + + } /* end for on PEC chiplet */ + if ( full ) break; + + /* gather other chiplets on the processor */ + for ( u = 0; u < MAX_EC_PER_PROC; u++ ) + { + /* Check if the EC is configured. */ + if ( 0 == (l_existBits.ecMask & (0x80000000 >> u)) ) continue; + + /* Add this EC to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_EC, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + if ( noAttn ) continue; /* Skip the rest */ + + } /* end for on EC chiplet */ + if ( full ) break; + + /* gather other chiplets on the processor */ + for ( u = 0; u < MAX_EQ_PER_PROC; u++ ) + { + /* Check if the EQ is configured. */ + if ( 0 == (l_existBits.eqMask & (0x80000000 >> u)) ) continue; + + /* Add this EQ to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_EQ, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + if ( noAttn ) continue; /* Skip the rest */ + + /* gather other chiplets on the processor */ + uint32_t l_ExPerEq = (MAX_EX_PER_PROC/MAX_EQ_PER_PROC); + uint32_t l_ExPos; + + for (l_unit=0; l_unit < l_ExPerEq; l_unit++) + { + l_ExPos = (l_ExPerEq * u) + l_unit; + + /* Check if the EX is configured. */ + if ( 0 == (l_existBits.exMask & (0x80000000 >> l_ExPos)) ) continue; + + /* Add this EX to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(TRGT_EX, p, l_ExPos, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + if ( noAttn ) continue; /* Skip the rest */ + + } /* end for on EX chiplet */ + if ( full ) break; + + } /* end for on EQ chiplet */ + if ( full ) break; + + + /* processor type can impact next few units */ + TrgtType_t l_pnorTarget = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? + TRGT_MCBIST : TRGT_MC; + uint32_t l_maxPerProc = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? + MAX_MCBIST_PER_PROC : MAX_MC_PER_PROC; + + TrgtType_t l_pnorTarg2 = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? + TRGT_MCA : TRGT_DMI; + uint32_t l_maxPerProc2 = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? + MAX_MCA_PER_PROC : MAX_DMI_PER_PROC; + + uint32_t l_UnitPerMc = l_maxPerProc2 / l_maxPerProc; + uint8_t l_unitNumber; + + for ( u = 0; u < l_maxPerProc; u++ ) + { + /* Check if MCBIST / MC is configured. */ + if ( 0 == (l_existBits.mcbist_mc_Mask & (0x80000000 >> u)) ) continue; + + /* Add this MCBIST or MC to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(l_pnorTarget, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + if ( noAttn ) continue; /* Skip the rest */ + + /* Grab underlying MCA/DMI chiplet */ + for ( l_unit = 0; l_unit < l_UnitPerMc; l_unit++ ) + { + /* u=0 or 1 while l_unit is 0 thru 3 */ + /* Leading to unit number 0:3 or 4:7 */ + l_unitNumber = l_unit + (u * l_UnitPerMc); + /* Check if the MCA / DMI is configured. */ + if ( 0 == (l_existBits.mca_dmi_Mask & (0x80000000 >> l_unitNumber)) ) continue; + + /* Add this MCA / DMI to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(l_pnorTarg2, p, l_unitNumber, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + + } /* end for on MCA/DMI */ + if ( full ) break; + + } /* end for on MCBIST */ + if ( full ) break; + + + l_pnorTarget = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? + TRGT_MCS : TRGT_MI; + l_maxPerProc = (HOMER_CHIP_NIMBUS == l_chipPtr->chipType) ? + MAX_MCS_PER_PROC : MAX_MI_PER_PROC; + + for ( u = 0; u < l_maxPerProc; u++ ) + { + /* Check if the MCS / MI is configured. */ + if ( 0 == (l_existBits.mcs_mi_Mask & (0x80000000 >> u)) ) continue; + + /* Add this MCS or MI to the PNOR. */ + sTrgt = SCOM_Trgt_getTrgt(l_pnorTarget, p, u, fsi, isM); + full = FirData_addTrgtToPnor( io_fd, sTrgt, &noAttn, l_chipPtr ); + if ( full ) break; + } + if ( full ) break; + + + } /* if processor chip type */ + else if (HOMER_CHIP_CENTAUR == l_chipPtr->chipType) + { + /* HOMER_ChipCentaur_t *l_cenExistBitPtr = + (HOMER_ChipCentaur_t *)l_bytePtr; */ + /* uint32_t l_mbaMask = ((uint32_t) l_cenExistBitPtr->mbaMask) << + (sizeof(uint32_t) - MAX_MBA_PER_MEMBUF) */ + + /* we have Centaur chipPos in 'p' and fsi address in 'fsi' */ + + /* add this centaur later and iterate thru l_mbaMask */ + /* don't need for initial support */ + /* TODO RTC 173614 -- with CUMULUS */ + + /* advance our pointer to next chip type */ + l_bytePtr += sizeof(HOMER_ChipCentaur_t); + + } /* end if centaur chip type */ + else + { + /* unexpected chip type */ + TRAC_ERR( "addTrgtsToPnor saw invalid chip:0x%X", + l_chipPtr->chipType ); + break; + } /* end if centaur chip type */ + + } /* end for on all CHIPS we have in homer data */ + + } while (0); + +} /* end FirData_addTrgtsToPnor */ + +/*------------------------------------------------------------------------------ */ + +/** @brief Initializes the FIR data struct. Does range checking for the HOMER + * data. Initializes the PNOR header data. + * @param io_fd The FIR data stuct. + * @param i_hBuf SRAM pointer to the beginning of the HOMER data buffer. + * This should contain the FIR data information provided by + * PRD that is used to define which registers the OCC will + * need to SCOM. + * @param i_hBufSize Total size of the HOMER data buffer. + * @param i_pBuf SRAM pointer to the beginning of the PNOR data buffer. + * This will be used by this function as a temporary area of + * memory to store the PNOR data before writing that data to + * the PNOR. + * @param i_pBufSize Total size of the PNOR data buffer. + * @return Non-SUCCESS if HOMER or PNOR range checking fails or if an + * internal function fails. SUCCESS otherwise. + */ +int32_t FirData_init( FirData_t * io_fd, + uint8_t * i_hBuf, uint32_t i_hBufSize, + uint8_t * i_pBuf, uint32_t i_pBufSize ) +{ + #define FUNC "[FirData_init] " + + int32_t rc = SUCCESS; + + size_t sz_hData = sizeof(HOMER_Data_t); + size_t sz_pnoNoEcc = 0; + size_t sz_u32 = sizeof(uint32_t); + size_t sz_u64 = sizeof(uint64_t); + + bool full = false; + + uint32_t x[TRGT_MAX][REG_MAX]; + size_t curIdx = 0; + + uint32_t t = TRGT_FIRST; + + uint8_t * reglist = NULL; + + PNOR_Data_t pData = PNOR_getData(); + + do + { + /* Init the struct. */ + io_fd->hBuf = i_hBuf; + io_fd->maxHBufSize = i_hBufSize; + io_fd->hData = (HOMER_Data_t *)i_hBuf; + + io_fd->pBuf = i_pBuf; + io_fd->maxPBufSize = i_pBufSize; + io_fd->pData = (PNOR_Data_t *)i_pBuf; + io_fd->pBufSize = 0; + + memset( io_fd->hPtrs, 0x00, sizeof(io_fd->hPtrs) ); + + /* Check HOMER header data size. */ + if ( io_fd->maxHBufSize < sz_hData ) + { + TRAC_ERR( FUNC"HOMER header data size %d is larger than HOMER " + "data buffer %d", sz_hData, io_fd->maxHBufSize ); + rc = FAIL; + break; + } + + /* Check for valid HOMER data. */ + if ( HOMER_FIR2 != io_fd->hData->header ) + { + break; /* nothing to analyze. */ + } + + /* The actual maximum PNOR size may possibly be less then the PNOR data */ + /* buffer. If so, adjust maximum size. */ + sz_pnoNoEcc = (io_fd->hData->pnorInfo.pnorSize / 9) * 8; + if ( sz_pnoNoEcc < io_fd->maxPBufSize ) + io_fd->maxPBufSize = sz_pnoNoEcc; + + /* Initialize the PNOR header data. */ + full = FirData_addDataToPnor( io_fd, &pData, sizeof(pData) ); + if ( full ) + { + TRAC_ERR( FUNC"Unable to add header to PNOR buffer" ); + rc = FAIL; + break; + } + + /* Copy the IPL state from the HOMER data to the PNOR data. */ + io_fd->pData->iplState = io_fd->hData->iplState; + + /* Get the register list byte indexes in HOMER data buffer */ + memset( x, 0x00, sizeof(x) ); + for ( t = TRGT_FIRST; t < TRGT_MAX; t++ ) + { + x[t][REG_GLBL] = curIdx; + x[t][REG_FIR] = x[t][REG_GLBL] + sz_u32 * io_fd->hData->regCounts[t][REG_GLBL]; + x[t][REG_REG] = x[t][REG_FIR] + sz_u32 * io_fd->hData->regCounts[t][REG_FIR]; + x[t][REG_IDFIR] = x[t][REG_REG] + sz_u32 * io_fd->hData->regCounts[t][REG_REG]; + x[t][REG_IDREG] = x[t][REG_IDFIR] + sz_u64 * io_fd->hData->regCounts[t][REG_IDFIR]; + curIdx = x[t][REG_IDREG] + sz_u64 * io_fd->hData->regCounts[t][REG_IDREG]; + } + + /* Check to make sure the list data is not larger than the available */ + /* Homer buffer. */ + if ( io_fd->maxHBufSize - sz_hData < curIdx ) + { + TRAC_ERR( FUNC"HOMER list size %d is larger than HOMER data " + "buffer %d", curIdx, io_fd->maxHBufSize - sz_hData ); + rc = FAIL; + break; + } + + /* Now, skip chip sections. Note that the HOMER_Data_t struct may have + * some padding added after the struct to ensure the HOMER_Chip_t + * structs are 4-byte word aligned. */ + uint32_t pad = (sz_u32 - (sz_hData % sz_u32)) % sz_u32; + reglist = io_fd->hBuf + sz_hData + pad; + HOMER_Chip_t *l_chiptPtr = NULL; + + /* Need to skip over chip list **/ + uint32_t l_chipNum; + for ( l_chipNum=0; + (l_chipNum < io_fd->hData->chipCount); + l_chipNum++ ) + { + l_chiptPtr = (HOMER_Chip_t *)reglist; + + /* Skip section on chip type, chip position, etc... */ + reglist += sizeof(HOMER_Chip_t); + + /* 'Existing chiplet area' varies in size */ + if (HOMER_CHIP_NIMBUS == l_chiptPtr->chipType) + { + reglist += sizeof(HOMER_ChipNimbus_t); + } + else if (HOMER_CHIP_CUMULUS == l_chiptPtr->chipType) + { + reglist += sizeof(HOMER_ChipCumulus_t); + } + else if (HOMER_CHIP_CENTAUR == l_chiptPtr->chipType) + { + reglist += sizeof(HOMER_ChipCentaur_t); + } + else + { + TRAC_ERR(FUNC"Chiptype is invalid %X ", l_chiptPtr->chipType); + rc = FAIL; + break; + } + + } /* end for loop skipping chip info sections */ + + + /* Now, get the pointers for each list. */ + for ( t = TRGT_FIRST; t < TRGT_MAX; t++ ) + { + (io_fd->hPtrs[t]).glbl = (uint32_t *)(reglist + x[t][REG_GLBL] ); + (io_fd->hPtrs[t]).fir = (uint32_t *)(reglist + x[t][REG_FIR] ); + (io_fd->hPtrs[t]).reg = (uint32_t *)(reglist + x[t][REG_REG] ); + (io_fd->hPtrs[t]).idFir = (uint64_t *)(reglist + x[t][REG_IDFIR]); + (io_fd->hPtrs[t]).idReg = (uint64_t *)(reglist + x[t][REG_IDREG]); + } + + /* Set EC level dep reg list ptr - at very end of list */ + io_fd->ecDepReg = (HOMER_ChipSpecAddr_t *)(reglist + curIdx); + + + } while (0); + + return rc; + + #undef FUNC +} + +/*------------------------------------------------------------------------------ */ +/* External functions */ +/*------------------------------------------------------------------------------ */ + +int32_t FirData_captureCsFirData( uint8_t * i_hBuf, uint32_t i_hBufSize, + uint8_t * i_pBuf, uint32_t i_pBufSize ) +{ + #define FUNC "[FirData_captureCsFirData] " + + int32_t rc = SUCCESS; + + do + { + /* Init the FIR data struct. */ + FirData_t fd; + rc = FirData_init( &fd, i_hBuf, i_hBufSize, i_pBuf, i_pBufSize ); + if ( SUCCESS != rc ) + { + TRAC_ERR( FUNC"Failed to init FIR data" ); + break; + } + + /* Check for valid HOMER data. */ + if ( HOMER_FIR2 != fd.hData->header ) + { + TRAC_ERR( FUNC"No HOMER data detected: header=0x%08x", + fd.hData->header ); + break; /* nothing to analyze. */ + } + + /* Start adding register data to PNOR for each target. */ + FirData_addTrgtsToPnor( &fd ); + + /* Write Buffer to PNOR */ +/* TODO: enable when function is supported. + rc = PNOR_writeFirData( fd.hData->pnorInfo, fd.pBuf, fd.pBufSize ); + if ( SUCCESS != rc ) + { + TRAC_ERR( FUNC"Failed to process FIR data" ); + break; + } +*/ + + } while (0); + + if ( SUCCESS != rc ) + { + TRAC_ERR( FUNC"Failed: i_hBuf=%p, i_hBufSize=0x%08x, i_pBuf=%p, " + "i_pBufSize=%08x", i_hBuf, i_hBufSize, i_pBuf, i_pBufSize ); + } + + return rc; + + #undef FUNC +} + diff --git a/src/occ_gpe0/firdata/firData.h b/src/occ_gpe0/firdata/firData.h new file mode 100644 index 0000000..f1475db --- /dev/null +++ b/src/occ_gpe0/firdata/firData.h @@ -0,0 +1,48 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/firData.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __firData_h +#define __firData_h + +#include "native.h" + +/** @brief Reads the register list from the HOMER data, SCOMs hardware, and + * stores the register values in PNOR. + * @param i_hBuf SRAM pointer to the beginning of the HOMER data buffer. + * This should contain the FIR data information provided by + * PRD that is used to define which registers the OCC will + * need to SCOM. + * @param i_hBufSize Total size of the HOMER data buffer. + * @param i_pBuf SRAM pointer to the beginning of the PNOR data buffer. + * This will be used by this function as a temporary area + * of memory to store the PNOR data before writing that + * data to the PNOR. + * @param i_pBufSize Total size of the PNOR data buffer. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t FirData_captureCsFirData( uint8_t * i_hBuf, uint32_t i_hBufSize, + uint8_t * i_pBuf, uint32_t i_pBufSize ); + +#endif /* __firData_h */ diff --git a/src/occ_gpe0/firdata/firDataConst_common.h b/src/occ_gpe0/firdata/firDataConst_common.h new file mode 100644 index 0000000..403a028 --- /dev/null +++ b/src/occ_gpe0/firdata/firDataConst_common.h @@ -0,0 +1,132 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/firDataConst_common.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 __firDataConst_common_h +#define __firDataConst_common_h + +/** NOTE: This file is common between OCC and Hosboot. Any change to this file + * must be mirrored to both repositories. Also, this must be C, not C++, + * because OCC strictly uses C. */ + +#include + +/** Target types for all supported targets. */ +/** NOTE: These are used to build the register list in HOMER data */ +/** and also to create the exiting chiplet masks. Hence, */ +/** the numbers assigned here have to match the sequence */ +/** of chiplets in HOMER_ChipNimbus_t, HOMER_ChipCumulus_t, etc. */ +typedef enum +{ + /* NOTE: These will be used as array indexes. */ + TRGT_FIRST = 0, + + /** Common Nimbus/Cumulus types */ + TRGT_PROC = TRGT_FIRST, + TRGT_CAPP, + TRGT_XBUS, + TRGT_OBUS, + TRGT_PEC, + TRGT_PHB, + TRGT_EQ, + TRGT_EX, + TRGT_EC, + + /* Nimbus only */ + TRGT_MCBIST, + TRGT_MCS, + TRGT_MCA, + + /* Cumulus only */ + /* NOTE: Nimbus and Cumulus cannot be used at the same time. So we can have + * These array indexes overlap to save space. */ + TRGT_MC = TRGT_MCBIST, + TRGT_MI, + TRGT_DMI, + + /* Centaur only */ + TRGT_MEMBUF, + TRGT_MBA, + + TRGT_MAX, + +} TrgtType_t; + +/** Boundary/position ranges for each target type. */ +typedef enum +{ + /* Common Nimbus/Cumulus */ + MAX_PROC_PER_NODE = 8, + MAX_CAPP_PER_PROC = 2, + MAX_XBUS_PER_PROC = 3, /* Nimbus 1 and 2, Cumulus 0, 1, and 2 */ + MAX_OBUS_PER_PROC = 4, /* Nimbus 0 and 3, Cumulus 0, 1, 2, and 3 */ + MAX_PEC_PER_PROC = 3, + MAX_PHB_PER_PROC = 6, + MAX_EQ_PER_PROC = 6, + MAX_EX_PER_PROC = 12, + MAX_EC_PER_PROC = 24, + + /** Nimbus only */ + MAX_MCBIST_PER_PROC = 2, + MAX_MCS_PER_PROC = 4, + MAX_MCA_PER_PROC = 8, + + /** Cumulus only */ + MAX_MC_PER_PROC = 2, + MAX_MI_PER_PROC = 4, + MAX_DMI_PER_PROC = 8, + + /** Centaur only */ + MAX_MEMBUF_PER_PROC = 8, + MAX_MEMBUF_PER_NODE = MAX_MEMBUF_PER_PROC * MAX_PROC_PER_NODE, + MAX_MBA_PER_MEMBUF = 2, + MAX_MBA_PER_PROC = MAX_MEMBUF_PER_PROC * MAX_MBA_PER_MEMBUF, + +} TrgtPos_t; + +/** All register types. */ +typedef enum +{ + /* NOTE: These will be used as array indexes. */ + REG_FIRST = 0, + + REG_GLBL = REG_FIRST, /* 32-bit addresses, 64-bit value */ + REG_FIR, /* 32-bit addresses, 64-bit value */ + REG_REG, /* 32-bit addresses, 64-bit value */ + REG_IDFIR, /* 64-bit addresses, 32-bit value */ + REG_IDREG, /* 64-bit addresses, 32-bit value */ + + REG_MAX, + +} RegType_t; + +/** Indicates the state of the machine when the checkstop occurred. */ +typedef enum +{ + FIRDATA_STATE_RUNTIME = 0, + FIRDATA_STATE_IPL = 1, + +} IplState_t; + +#endif /* __firDataConst_common_h */ diff --git a/src/occ_gpe0/firdata/fir_data_collect.c b/src/occ_gpe0/firdata/fir_data_collect.c new file mode 100644 index 0000000..a2af34f --- /dev/null +++ b/src/occ_gpe0/firdata/fir_data_collect.c @@ -0,0 +1,166 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/fir_data_collect.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + + +#include +#include +#include +#include +#include "tpc_firmware_registers.h" +#include "tpc_register_addresses.h" +#include +#include +#include + +FIR_HEAP_BUFFER(uint8_t G_fir_heap[FIR_HEAP_SECTION_SIZE]); +FIR_PARMS_BUFFER(uint8_t G_fir_data_parms[FIR_PARMS_SECTION_SIZE]); +uint32_t G_fir_master = FIR_OCC_NOT_FIR_MASTER; + +/* + * Function Specification + * + * Name: fir_data_collect + * + * Description: Collects FIR data on checkstop. + * + * End Function Specification + */ +void fir_data_collect(void) +{ + + int32_t l_rc = 0; + + // Homer data section and size + uint8_t *l_hBuf = (uint8_t*) FIR_PARMS_SECTION_BASE_ADDRESS; + uint32_t l_hBufSize = HOMER_FIR_PARM_SIZE; + // PNOR working buffer in SRAM and size + uint8_t *l_pBuf = (uint8_t*) FIR_HEAP_SECTION_BASE_ADDRESS; + uint32_t l_pBufSize = FIR_HEAP_SECTION_SIZE; + + l_rc = FirData_captureCsFirData(l_hBuf, + l_hBufSize, + l_pBuf, + l_pBufSize); + + // Trace the rc only, error logs cannot be collected in this state + TRAC_IMP("Checkstop FIR data capture completed with rc=%d", l_rc); +} + + +/* + * Function Specification + * + * Name: pnor_access_ok + * + * Description: Determines if it is ok for this OCC to access the PNOR. + * + * End Function Specification + */ +// TODO: This code is not allowed currently, as it relies on performing scom operations. +#if 0 +bool pnor_access_allowed(void) +{ + /* BMC ownership of the PNOR is indicated by bit 18 in TPC_GP0 */ + int l_rc = 0; + tpc_gp0_t l_tp_gp0_read; + bool l_access_allowed = FALSE; + + l_tp_gp0_read.words.high_order = 0x00000000; + l_tp_gp0_read.words.low_order = 0x00000000; + + l_rc = getscom_ffdc(TPC_GP0, (uint64_t *)&l_tp_gp0_read, NULL); + + if (l_rc == 0) + { + if ((l_tp_gp0_read.words.high_order & TPC_GP0_BIT18_PNOR_OWNER_MASK) == 0) + { + TRAC_INFO("PNOR access allowed at this time"); + l_access_allowed = TRUE; + } + else + { + TRAC_INFO("PNOR access NOT allowed at this time, tpc_gp0.hi = 0x%08x", + l_tp_gp0_read.words.high_order); + + /* @ + * @errortype + * @moduleid FIR_DATA_MID + * @reasoncode INTERNAL_FAILURE + * @userdata1 TPC_GP0 high word + * @userdata4 ERC_PNOR_OWNERSHIP_NOT_AVAILABLE + * @devdesc PNOR access not allowed at this time. + */ + errlHndl_t l_errl = createErrl( + FIR_DATA_MID, /*ModId */ + INTERNAL_FAILURE, /*Reasoncode */ + ERC_PNOR_OWNERSHIP_NOT_AVAILABLE, /*Extended reasoncode */ + ERRL_SEV_INFORMATIONAL, /*Severity */ + NULL, /*Trace Buf */ + DEFAULT_TRACE_SIZE, /*Trace Size */ + l_tp_gp0_read.words.high_order, /*Userdata1 */ + 0 /*Userdata2 */ + ); + + /* Commit log */ + commitErrl(&l_errl); + } + } + else + { + /* getscom failure */ + TRAC_ERR("TPC_GP0 getscom failure rc = 0x%08x", -l_rc ); + + /* @ + * @errortype + * @moduleid FIR_DATA_MID + * @reasoncode INTERNAL_HW_FAILURE + * @userdata1 getscom failure rc + * @userdata4 ERC_GETSCOM_TPC_GP0_FAILURE + * @devdesc Failure determining PNOR ownership. Cannot read TPC_GP0. + */ + errlHndl_t l_errl = createErrl( + FIR_DATA_MID, /*ModId */ + INTERNAL_HW_FAILURE, /*Reasoncode */ + ERC_GETSCOM_TPC_GP0_FAILURE, /*Extended reasoncode */ + ERRL_SEV_PREDICTIVE, /*Severity */ + NULL, /*Trace Buf */ + DEFAULT_TRACE_SIZE, /*Trace Size */ + l_rc, /*Userdata1 */ + 0 /*Userdata2 */ + ); + + /* Callout firmware */ + addCalloutToErrl(l_errl, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + + /* Commit log */ + commitErrl(&l_errl); + } + + return l_access_allowed; +} +#endif diff --git a/src/occ_gpe0/firdata/fir_data_collect.h b/src/occ_gpe0/firdata/fir_data_collect.h new file mode 100644 index 0000000..c313956 --- /dev/null +++ b/src/occ_gpe0/firdata/fir_data_collect.h @@ -0,0 +1,56 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/fir_data_collect.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 _FIR_DATA_COLLECT_H +#define _FIR_DATA_COLLECT_H + +#include + +/* This size has to agree with the size _FIR_PARMS_SECTION_SIZE defined in the */ +/* OCC linker command file. */ +#define FIR_PARMS_SECTION_SIZE 0x1000 +// This size has to agree with the size _FIR_HEAP_SECTION_SIZE defined in the +// OCC linker command file. +#define FIR_HEAP_SECTION_SIZE 0x3000 + +enum fir_master +{ + FIR_OCC_NOT_FIR_MASTER = 0x00000000, + FIR_OCC_IS_FIR_MASTER = 0x00000001 +}; + +extern uint8_t G_fir_data_parms[FIR_PARMS_SECTION_SIZE]; +extern uint8_t G_fir_heap[FIR_HEAP_SECTION_SIZE]; +extern uint32_t G_fir_master; + +#define OCC_SET_FIR_MASTER(_fm_t) G_fir_master = _fm_t +#define OCC_IS_FIR_MASTER() (G_fir_master == FIR_OCC_IS_FIR_MASTER) ? TRUE : FALSE +#define TPC_GP0_BIT18_PNOR_OWNER_MASK 0x00002000 + +void fir_data_collect(void); +bool pnor_access_allowed(void); + +#endif /* _FIR_DATA_COLLECT_H */ diff --git a/src/occ_gpe0/firdata/fsi.c b/src/occ_gpe0/firdata/fsi.c new file mode 100644 index 0000000..4bf105a --- /dev/null +++ b/src/occ_gpe0/firdata/fsi.c @@ -0,0 +1,152 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/fsi.C $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +#include +#include +#include + +#define OPB_REG_CMD 0x00020010 +#define OPB_REG_STAT 0x00020011 +#define OPB_REG_RES 0x00020014 +#define OPB_STAT_BUSY 0x0001000000000000 /**< 15 is the Busy bit */ +#define NS_PER_MSEC (1000000ull) + + +void fsi_recovery() +{ + int32_t rc = SUCCESS; + + /* Clear out OPB error */ + uint64_t scom_data = 0; + scom_data = 0x8000000000000000; /*0=Unit Reset*/ + rc |= xscom_write( OPB_REG_RES, scom_data ); + rc |= xscom_write( OPB_REG_STAT, scom_data ); + + /* Check if we have any errors left */ + rc |= xscom_read( OPB_REG_STAT, &scom_data ); + + TRACFCOMP( "PIB2OPB Status after cleanup = %08X%08X (rc=%d)", + (uint32_t)(scom_data >> 32), (uint32_t)scom_data, rc ); +} + +/** + * @brief Poll for completion of a FSI operation, return data on read + */ +int32_t poll_for_complete( uint32_t * o_val ) +{ + int32_t rc = SUCCESS; + + enum { MAX_OPB_TIMEOUT_NS = 10*NS_PER_MSEC }; /*=10ms */ + + *o_val = 0; + + uint64_t read_data = 0; + uint64_t elapsed_time_ns = 0; + do + { + rc = xscom_read( OPB_REG_STAT, &read_data ); + if ( SUCCESS != rc ) + { + fsi_recovery(); /* Try to recover the engine. */ + return rc; + } + + /* Check for completion. Note: not checking for FSI errors. */ + if ( (read_data & OPB_STAT_BUSY) == 0 ) break; /* Not busy */ + + sleep( 10000 ); /* sleep for 10,000 ns */ + elapsed_time_ns += 10000; + + } while ( elapsed_time_ns <= MAX_OPB_TIMEOUT_NS ); + + if ( MAX_OPB_TIMEOUT_NS < elapsed_time_ns ) + { + TRAC_ERR( "[poll_for_complete] FSI request timed out." ); + return FAIL; + } + + *o_val = (uint32_t)read_data; /* Data in the bottom half. */ + + return rc; +} + +/** + * @brief Read a FSI register + */ +int32_t getfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t * o_val ) +{ + int32_t rc = SUCCESS; + + uint32_t fsi_addr = i_trgt.fsiBaseAddr | i_addr; + + /* setup the OPB command register */ + /* only supporting 4-byte access */ + uint64_t fsi_cmd = fsi_addr | 0x60000000; /* 011=Read Full Word */ + fsi_cmd <<= 32; /* Command is in the upper word of the scom */ + + /* Write the OPB command register to trigger the read */ + rc = xscom_write( OPB_REG_CMD, fsi_cmd ); + if ( SUCCESS != rc ) + { + fsi_recovery(); /* Try to recover the engine. */ + return rc; + } + + /* Poll for complete and get the data back. */ + rc = poll_for_complete( o_val ); + + return rc; +} + +/** + * @brief Write a FSI register + */ +int32_t putfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t i_val ) +{ + int32_t rc = SUCCESS; + + uint32_t fsi_addr = i_trgt.fsiBaseAddr | i_addr; + + /* setup the OPB command register */ + /* only supporting 4-byte access */ + uint64_t fsi_cmd = fsi_addr | 0xE0000000; /* 111=Write Full Word */ + fsi_cmd <<= 32; /* Command is in the upper word of the scom */ + fsi_cmd |= i_val; /* Data is in the bottom 32-bits */ + + /* Write the OPB command register to trigger the read */ + rc = xscom_write( OPB_REG_CMD, fsi_cmd ); + if ( SUCCESS != rc ) + { + fsi_recovery(); /* Try to recover the engine. */ + return rc; + } + + /* Poll for complete */ + uint32_t junk = 0; // Not used. + rc = poll_for_complete( &junk ); + + return rc; +} + diff --git a/src/occ_gpe0/firdata/fsi.h b/src/occ_gpe0/firdata/fsi.h new file mode 100644 index 0000000..870e47f --- /dev/null +++ b/src/occ_gpe0/firdata/fsi.h @@ -0,0 +1,47 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/fsi.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +/* Interfaces to read/write FSI registers */ + +#include + +/** + * @brief Read a FSI register. + * @param i_trgt Chip/unit to read from. + * @param i_addr FSI address to read, relative to slave's base address. + * @param o_val Returned value. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t getfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t * o_val ); + +/** + * @brief Write a FSI register. + * @param i_trgt Chip/unit to write to. + * @param i_addr FSI address to write, relative to slave's base address. + * @param o_val Value to write. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t putfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t i_val ); + diff --git a/src/occ_gpe0/firdata/homerData_common.h b/src/occ_gpe0/firdata/homerData_common.h new file mode 100644 index 0000000..66aa53a --- /dev/null +++ b/src/occ_gpe0/firdata/homerData_common.h @@ -0,0 +1,271 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/homerData_common.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 __homerData_common_h +#define __homerData_common_h + +/** NOTE: This file is common between OCC and Hosboot. Any change to this file + * must be mirrored to both repositories. Also, this must be C, not C++, + * because OCC strictly uses C. */ + +#include +#include + +/** This file is used to define the format of the register list stored in the + * HOMER data that the OCC will use to determine what register data to capture + * in the event of a system checkstop. The data will be stored in the following + * format: + * + * - HOMER_Data_t struct - This contains PNOR information, IPL state, number of + * configured chips, and number of register addresses per target type per + * register type. + * + * - For each configured chip, the following format will be used: + * - HOMER_Chip_t struct - containing FSI base address, chip type, and chip + * position. + * - Immediately following will be a chip struct that is specific to the + * chip type stored in the preceding struct. These vary in size and + * structure depending on the chip type. + * + * - Register address lists - These lists vary in size depending on the number + * of register addresses needed in each list. The list counts are stored in + * HOMER_Data_t::regCounts. Order of the lists must match the array indexes + * of HOMER_Data_t::regCounts, which are specified in TrgtType_t and + * RegType_t. + * + * - Chip specific address list - This is a list of HOMER_ChipSpecAddr_t + * structs and will vary in size depending on the number of register + * addresses that are specific to a certain chip or DD level. The number of + * entries in this list is stored in HOMER_Data_t::ecDepCounts. + * + * IMPORTANT NOTE: All of the structs used here are packed. Therefore, we must + * ensure the variables within the struct are byte aligned. Meaning each + * uint32_t within the struct must be 4-byte aligned and each uint16_t must + * be 2-byte aligned. This also means the structs must always start on a + * 4-bye word boundary to maintain alignment. This is required due to the + * limitations of the PPE42/SRAM hardware. + * + * Note that FIRs and indirect-SCOM FIRs characterize a set of registers to + * capture. In addition to capturing the FIR (or ID FIR), the OCC will need to + * capture the following addresses for each type: + * - FIR + * - MASK (FIR address + 3) + * - ACT0 (FIR address + 6) + * - ACT1 (FIR address + 7) + * - ID FIR + * - ID MASK (ID FIR address + 0x300000000ll) + * - ID ACT0 (ID FIR address + 0x600000000ll) + * - ID ACT1 (ID FIR address + 0x700000000ll) + * Note that not all FIRs have a corresponding WOF register. So any WOFs needed + * for analysis will need to be explicitly listed in the corresponding + * 'Registers' lists. + */ + +typedef enum +{ + HOMER_FIR1 = 0x46495231, /** FIR data version 1 ("FIR1" in ascii) P8 */ + HOMER_FIR2 = 0x46495232, /** FIR data version 1 ("FIR2" in ascii) P9 */ + +} HOMER_Version_t; + +/** PNOR information contained within the HOMER data. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t pnorOffset; /** Physical offset of FIRDATA in PNOR */ + uint32_t pnorSize; /** Maximum size of FIRDATA (includes ECC) */ + uint32_t mmioOffset; /** Address of MMIO access */ + uint32_t norWorkarounds; /** NOR flash vendor */ + +} HOMER_PnorInfo_t; + +/** HOMER data header information containing hardware configurations and + * register counts. */ +/* NOTE: This structure may, or may not, be 4-byte word aligned. It all depends + * on the size of regCounts, which will change based on the number of + * target types and register types we support. When reading/writing this + * data ensure that proper padding has been added after this structure so + * that subsequent structures are 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t header; /** Magic number to indicate valid data and version */ + + uint32_t chipCount : 8; /** Number of configured chips per node */ + uint32_t ecDepCounts : 8; /** Number of regs that are EC dependent */ + uint32_t iplState : 1; /** See IplState_t. */ + uint32_t reserved : 15; + + /** Information regarding the PNOR location and size. */ + HOMER_PnorInfo_t pnorInfo; + + /** Contains number of registers per type for each target type. */ + uint8_t regCounts[TRGT_MAX][REG_MAX]; + +} HOMER_Data_t; + +/** @return An initialized HOMER_Data_t struct. */ +static inline HOMER_Data_t HOMER_getData() +{ + HOMER_Data_t d; memset( &d, 0x00, sizeof(d) ); /* init to zero */ + + d.header = HOMER_FIR2; + + return d; +} + +/*----------------------------------------------------------------------------*/ + +/** Supported chip types. */ +typedef enum +{ + HOMER_CHIP_NIMBUS, /** P9 Nimbus processor chip */ + HOMER_CHIP_CUMULUS, /** P9 Cumulus processor chip */ + HOMER_CHIP_CENTAUR, /** Centaur memory buffer chip */ + +} HOMER_ChipType_t; + +/** Information for each configured chip. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t fsiBaseAddr; /** FSI base address for the chip. */ + + uint32_t chipType : 4; /** Chip type (see HOMER_ChipType_t) */ + uint32_t chipPos : 6; /** Chip position relative to the node. */ + uint32_t chipEcLevel : 8; /** EC level for this chip */ + uint32_t reserved : 14; + +} HOMER_Chip_t; + +/** Used for Registers that have EC level dependencies */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t chipType : 4; /** See HOMER_ChipType_t. */ + uint32_t trgtType : 6; /** See TrgtType_t. */ + uint32_t regType : 4; /** See RegType_t. */ + uint32_t ddLevel : 8; /** A zero value applies to all levels on a chip. */ + uint32_t reserved : 10; /** unused at this time */ + + /** The 32 or 64 bit address (right justified). */ + uint64_t address; + +} HOMER_ChipSpecAddr_t; + +/** @return An initialized HOMER_Chip_t struct. */ +static inline HOMER_Chip_t HOMER_getChip( HOMER_ChipType_t i_type ) +{ + HOMER_Chip_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ + + c.fsiBaseAddr = 0xffffffff; + c.chipType = i_type; + + return c; +} + +/*----------------------------------------------------------------------------*/ + +/** Information specific to a P9 Nimbus processor chip. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t isMaster : 1; /** 1 if this is the master PROC, 0 otherwise */ + uint32_t xbusMask : 3; /** Mask of configured XBUS units (0-2) */ + uint32_t obusMask : 4; /** Mask of configured OBUS units (0-3) */ + uint32_t ecMask : 24; /** Mask of configured EC units (0-23) */ + + uint32_t eqMask : 6; /** Mask of configured EQ units (0-5) */ + uint32_t exMask : 12; /** Mask of configured EX units (0-11) */ + uint32_t mcbistMask : 2; /** Mask of configured MCBIST units (0-1) */ + uint32_t mcsMask : 4; /** Mask of configured MCS units (0-3) */ + uint32_t mcaMask : 8; /** Mask of configured MCA units (0-7) */ + + uint32_t cappMask : 2; /** Mask of configured CAPP units (0-1) */ + uint32_t pecMask : 3; /** Mask of configured PEC units (0-2) */ + uint32_t phbMask : 6; /** Mask of configured PHB units (0-5) */ + uint32_t reserved : 21; + +} HOMER_ChipNimbus_t; + +/** @return An initialized HOMER_ChipNimbus_t struct. */ +static inline HOMER_ChipNimbus_t HOMER_initChipNimbus() +{ + HOMER_ChipNimbus_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ + + return c; +} + +/*----------------------------------------------------------------------------*/ + +/** Information specific to a P9 Cumulus processor chip. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t isMaster : 1; /** 1 if this is the master PROC, 0 otherwise */ + uint32_t xbusMask : 3; /** Mask of configured XBUS units (0-2) */ + uint32_t obusMask : 4; /** Mask of configured OBUS units (0-3) */ + uint32_t ecMask : 24; /** Mask of configured EC units (0-23) */ + + uint32_t eqMask : 6; /** Mask of configured EQ units (0-5) */ + uint32_t exMask : 12; /** Mask of configured EX units (0-11) */ + uint32_t mcMask : 2; /** Mask of configured MC units (0-1) */ + uint32_t miMask : 4; /** Mask of configured MI units (0-3) */ + uint32_t dmiMask : 8; /** Mask of configured DMI units (0-7) */ + + uint32_t cappMask : 2; /** Mask of configured CAPP units (0-1) */ + uint32_t pecMask : 3; /** Mask of configured PEC units (0-2) */ + uint32_t phbMask : 6; /** Mask of configured PHB units (0-5) */ + uint32_t reserved : 21; + +} HOMER_ChipCumulus_t; + +/** @return An initialized HOMER_ChipCumulus_t struct. */ +static inline HOMER_ChipCumulus_t HOMER_initChipCumulus() +{ + HOMER_ChipCumulus_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ + + return c; +} + +/*----------------------------------------------------------------------------*/ + +/** Information specific to a Centaur memory buffer chip. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t mbaMask : 2; /** Mask of configured MBA units (0-1) */ + uint32_t reserved : 30; + +} HOMER_ChipCentaur_t; + +/** @return An initialized HOMER_ChipCentaur_t struct. */ +static inline HOMER_ChipCentaur_t HOMER_initChipCentaur() +{ + HOMER_ChipCentaur_t c; memset( &c, 0x00, sizeof(c) ); /* init to zero */ + + return c; +} + +#endif /* __homerData_common_h */ diff --git a/src/occ_gpe0/firdata/lpc.c b/src/occ_gpe0/firdata/lpc.c new file mode 100644 index 0000000..ffe2b48 --- /dev/null +++ b/src/occ_gpe0/firdata/lpc.c @@ -0,0 +1,391 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/lpc.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +#include +#include +#include +#include + +#define LPCHC_FW_SPACE 0xF0000000 /**< LPC Host Controller FW Space */ +#define LPCHC_MEM_SPACE 0xE0000000 /**< LPC Host Controller Mem Space */ +#define LPCHC_IO_SPACE 0xD0010000 /**< LPC Host Controller I/O Space */ +#define LPCHC_REG_SPACE 0xC0012000 /**< LPC Host Ctlr Register Space */ +#define ECCB_NON_FW_RESET_REG 0x000B0001 /**< ECCB Reset Reg (non-FW) */ + +#define LPC_BASE_REG 0x00090040 /**< LPC Base Address Register */ +#define LPC_CMD_REG 0x00090041 /**< LPC Command Register */ +#define LPC_DATA_REG 0x00090042 /**< LPC Data Register */ +#define LPC_STATUS_REG 0x00090043 /**< LPC Status Register */ + +#define ECCB_CTL_REG 0x000B0020 /**< ECCB Control Reg (FW) */ +#define ECCB_RESET_REG 0x000B0021 /**< ECCB Reset Reg (FW) */ +#define ECCB_STAT_REG 0x000B0022 /**< ECCB Status Reg (FW) */ +#define ECCB_DATA_REG 0x000B0023 /**< ECCB Data Reg (FW) */ + +/* Default Values to set for all operations + 1101.0100.0000.000x.0000.0001.0000.0000.
*/ +#define ECCB_CTL_REG_DEFAULT 0xD400010000000000 + +/* Error bits: wh_todo comments here */ +#define LPC_STAT_REG_ERROR_MASK 0x0000000000000000 /**< Error Bits */ //wh_todo correctly set mask + +/**< OPB LPCM Sync FIR Reg - used to read the FIR*/ +#define OPB_LPCM_FIR_REG 0x01010C00 + +/**< OPB LPCM Sync FIR Reg WOX_AND - used to clear the FIR */ +#define OPB_LPCM_FIR_WOX_AND_REG 0x01010C01 + +/**< OPB LPCM Sync FIR Mask Reg WO_OR - used to set the mask */ +#define OPB_LPCM_FIR_MASK_WO_OR_REG 0x01010C05 + +#define OPB_LPCM_FIR_ERROR_MASK 0xFF00000000000000 /**< Error Bits MASK */ + +/* LPCHC reset-related registers */ +#define OPB_MASTER_LS_CONTROL_REG 0x008 /**data64)); + + if( l_err ) + { + break; + } + + if( o_stat->op_done ) + { + break; + } + + /* Want to start out incrementing by small numbers then get bigger + to avoid a really tight loop in an error case so we'll increase + the wait each time through */ + sleep( LPC_POLL_INCR_NS*(++loop) ); + poll_time += LPC_POLL_INCR_NS * loop; + } while ( poll_time < LPC_POLL_TIME_NS ); + + /* Check for hw errors or timeout if no previous logs */ + if( (l_err == NO_ERROR) && + ((o_stat->data64 & LPC_STAT_REG_ERROR_MASK) + || (!o_stat->op_done)) ) + { + TRAC_ERR( "LpcDD::pollComplete> LPC error or timeout: addr=0x%.8X, status=0x%.8X%.8X", + i_ctrl->address, (uint32_t)(o_stat->data64>>32), (uint32_t)o_stat->data64 ); + l_err = -1; + break; + } + } while(0); + + return l_err; + +} + + +/*========================================================*/ + +errorHndl_t lpc_read( LpcTransType i_type, + uint32_t i_addr, + uint8_t* o_data, + size_t i_size ) +{ + errorHndl_t l_err = NO_ERROR; + int32_t l_addr = 0; + uint64_t l_ret; + uint32_t l_shift_amount; + uint64_t l_temp_data; + + do { + if( o_data == NULL ) + { + TRACFCOMP( "o_data is NULL!" ); + l_err = -2; + break; + } + + + /* Generate the full absolute LPC address */ + l_addr = checkAddr( i_type, i_addr ); + + /* Setup command */ + CommandReg_t lpc_cmd; + lpc_cmd.rnw = 1; //Indicate read not write + lpc_cmd.size = i_size; + lpc_cmd.address = l_addr; + + /* Execute command via Scom */ + SCOM_Trgt_t l_target; + l_target.type = TRGT_PROC; + l_target.isMaster = TRUE; + + //First write the address we want to read from in the + //LPC_CMD_REG scom address + l_err = SCOM_putScom(l_target, LPC_CMD_REG, lpc_cmd.data64); + if(l_err != SUCCESS) + { + TRAC_ERR("lpc_read: SCOM_putScom failed to write to LPC_CMD_REG command rc=0x%08x", + (uint32_t)l_err); + break; + } + + /* Poll for completion */ + StatusReg_t lpc_status; + l_err = pollComplete( &lpc_cmd, &lpc_status ); + if( l_err ) { break; } + + // Read data from the LPC_DATA_REG + l_err = SCOM_getScom(l_target, LPC_DATA_REG, &l_ret); + if(l_err != SUCCESS) + { + TRAC_ERR("lpc_read: SCOM_getScom failed rc=0x%08x", (uint32_t)l_err); + break; + } + + //The scom returns the data in the byte offset represented by last + //3 bits of the address. For example, addr 0x21 will have have data + //starting in byte1 on value returned from scom. + //addr & 0x7 <-- this gives the byte offset + //7 - (addr & 0x7) <-- subratcing from 7 as the data is left aligned + //adding (size - 1) <-- to incorporate reading more than one byte + //multiply by 8 to convert from byte to bits + l_shift_amount = (7 - ((l_addr & 0x7) + (i_size-1))) * 8; + l_temp_data = l_ret >> l_shift_amount; + + //Had some weird problems with memcpy, that's why typecasting + //to the size of data asked. + if (i_size == sizeof(uint8_t)) + { + uint8_t* l_temp_ptr = (uint8_t*)(o_data); + *l_temp_ptr = l_temp_data; + } + else if (i_size == sizeof(uint16_t)) + { + uint16_t* l_temp_ptr = (uint16_t*)(o_data); + *l_temp_ptr = l_temp_data; + } + else if (i_size == sizeof(uint32_t)) + { + uint32_t* l_temp_ptr = (uint32_t*)(o_data); + *l_temp_ptr = l_temp_data; + } + else if (i_size == sizeof(uint64_t)) + { + uint64_t* l_temp_ptr = (uint64_t*)(o_data); + *l_temp_ptr = l_temp_data; + } + else + { + TRAC_ERR("lpc_read: unsupported size length"); + l_err = -1; + break; + } + + } while(0); + + return l_err; +} + +errorHndl_t lpc_write( LpcTransType i_type, + uint32_t i_addr, + uint8_t* i_data, + size_t i_size ) +{ + errorHndl_t l_err = NO_ERROR; + uint32_t l_addr = 0; + uint64_t l_write_data = 0; + uint64_t l_data = 0; + uint32_t l_shift_amount; + + do { + /* Generate the full absolute LPC address */ + l_addr = checkAddr( i_type, i_addr ); + + /* Setup Write Command */ + CommandReg_t lpc_cmd; + lpc_cmd.rnw = 0; //Indicate write + lpc_cmd.size = i_size; + lpc_cmd.address = l_addr; + + /* Setup Write command via Scom */ + SCOM_Trgt_t l_target; + l_target.type = TRGT_PROC; + l_target.isMaster = TRUE; + + //First write the address we want to write to in LPC_CMD_REG + l_err = SCOM_putScom(l_target, LPC_CMD_REG, lpc_cmd.data64); + if(l_err != SUCCESS) + { + TRAC_ERR("ERROR> lpc_write: SCOM_putScom failed to write to LPC_CMD_REG command: rc=0x%08x", + (uint32_t)l_err); + break; + } + + //There were some weird memcpy problems. That's why, typecasting + //to the size of data requested to write + if (i_size == sizeof(uint8_t)) + { + l_write_data = (*i_data); + } + else if (i_size == sizeof(uint16_t)) + { + uint16_t* l_temp_ptr = (uint16_t*)(i_data); + l_write_data = *l_temp_ptr; + } + else if (i_size == sizeof(uint32_t)) + { + uint32_t* l_temp_ptr = (uint32_t*)(i_data); + l_write_data = *l_temp_ptr; + } + else if (i_size == sizeof(uint64_t)) + { + uint64_t* l_temp_ptr = (uint64_t*)(i_data); + l_write_data = *l_temp_ptr; + } + else + { + TRAC_ERR("lpc_write: unsupported size length"); + l_err = -1; + break; + } + + //The scom expects the data in the byte offset represented by last + //3 bits of the address. For example, addr 0x21 will have have data + //starting in byte1 on value returned from scom. + //addr & 0x7 <-- this gives the byte offset + //7 - (addr & 0x7) <-- subratcing from 7 as the data in the scom reg + //is expected to be left aligned + //adding (size - 1) <-- to incorporate reading more than one byte + //multiply by 8 to convert from byte to bits + l_shift_amount = (7 - ((l_addr & 0x7) + (i_size-1))) * 8; + l_data = (l_write_data << l_shift_amount); + + //Write the value to the LPC_DATA_REG + l_err = SCOM_putScom(l_target, LPC_DATA_REG, l_data); + if(l_err != SUCCESS) + { + TRAC_ERR("ERROR> lpc_write: SCOM_putScom failed to write to LPC_DATA_REG data: rc=0x%08x", + (uint32_t)l_err); + break; + } + + /* Poll for completion */ + StatusReg_t lpc_stat; + l_err = pollComplete( &lpc_cmd, &lpc_stat ); + if( l_err ) { break; } + + + } while(0); + + return l_err; +} diff --git a/src/occ_gpe0/firdata/lpc.h b/src/occ_gpe0/firdata/lpc.h new file mode 100644 index 0000000..177deda --- /dev/null +++ b/src/occ_gpe0/firdata/lpc.h @@ -0,0 +1,55 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/lpc.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 _LPC_H +#define _LPC_H + +#include +#include + +/** + * @enum LPC::TransType + * @brief LPC Transaction Types + */ +typedef enum { + LPC_TRANS_IO = 0, /* LPC IO Space */ + LPC_TRANS_FW = 1, /* LPC Firmware Space */ +} LpcTransType; + +errorHndl_t lpc_read( LpcTransType i_type, + uint32_t i_addr, + uint8_t* o_data, + size_t i_size ); + +errorHndl_t lpc_write( LpcTransType i_type, + uint32_t i_addr, + uint8_t* i_data, + size_t i_size ); + +uint32_t checkAddr(LpcTransType i_type, + uint32_t i_addr); + + +#endif diff --git a/src/occ_gpe0/firdata/native.c b/src/occ_gpe0/firdata/native.c new file mode 100644 index 0000000..d214468 --- /dev/null +++ b/src/occ_gpe0/firdata/native.c @@ -0,0 +1,76 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/native.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +#include +#include +#include + +void sleep( SsxInterval i_nanoseconds ) +{ + ssx_sleep(SSX_NANOSECONDS(i_nanoseconds)); +} + +int TRACE_XSCOM=0; + +int32_t xscom_read( uint32_t i_address, uint64_t * o_data ) +{ + int32_t rc = SUCCESS; + + *o_data = 0; + + rc = getscom_ffdc( i_address, o_data, NULL ); + if ( SUCCESS != rc ) + { + TRAC_ERR( "SCOM error in xscom_read wrapper, rc=%d", rc ); + } + + if ( TRACE_XSCOM ) + { + TRACFCOMP( "xscom_read(%08X)=%08X%08X", i_address, + (uint32_t)(*o_data>>32), (uint32_t)(*o_data) ); + } + + return rc; +} + +int32_t xscom_write( uint32_t i_address, uint64_t i_data ) +{ + int32_t rc = SUCCESS; + + rc = putscom_ffdc( i_address, i_data, NULL ); + if ( SUCCESS != rc ) + { + TRAC_ERR( "SCOM error in xscom_write wrapper, rc=%d", rc ); + } + + if ( TRACE_XSCOM ) + { + TRACFCOMP( "xscom_write(%08X)=%08X%08X", i_address, + (uint32_t)(i_data>>32), (uint32_t)i_data); + } + + return rc; +} + diff --git a/src/occ_gpe0/firdata/native.h b/src/occ_gpe0/firdata/native.h new file mode 100644 index 0000000..dd0daa7 --- /dev/null +++ b/src/occ_gpe0/firdata/native.h @@ -0,0 +1,98 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/native.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +/* Native functions provided by OCC code */ +#ifndef _NATIVE_H +#define _NATIVE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include "ssx.h" +#ifdef __cplusplus +} +#endif + +#ifndef NO_TRAC_STRINGS + +#ifdef FIRD_DEBUG +#define TRACDCOMP(frmt,args...) DBG_PRINT(frmt,##args) +#else +#define TRACDCOMP(frmt,args...) +#endif // FIRD_DEBUG + +#define TRACFCOMP(frmt,args...) TRACE(&g_des_array[INF_TRACE_DESCRIPTOR],INFO_MRK frmt,##args) + +#else // NO_TRAC_STRINGS + +#define TRACDCOMP(frmt,args...) +#define TRACFCOMP(frmt,args...) + +#endif // NO_TRAC_STRINGS + +typedef uint32_t errorHndl_t; + +#define ENTER_MRK +#define NO_ERROR 0 + +/* Return a number >= input that is aligned up to the next 4-byte boundary */ +#define ALIGN_4(u) (((u) + 0x3ull) & ~0x3ull) + +#define NS_PER_SEC (1000000000ull) + +#undef be64toh +#undef htobe64 +#define be64toh(x) (x) +#define htobe64(x) (x) + +#define KILOBYTE (1024ul) /**< 1 KB */ +#define MEGABYTE (1024 * 1024ul) /**< 1 MB */ +#define GIGABYTE (MEGABYTE * 1024ul) /**< 1 GB */ +#define TERABYTE (GIGABYTE * 1024ul) /**< 1 TB */ + +#define PAGESIZE (4*KILOBYTE) /**< 4 KB */ + +#undef SUCCESS +#define SUCCESS 0 + +#undef FAIL +#define FAIL -1 + +/*================================================ */ + +/* XSCOM Read */ +int32_t xscom_read( uint32_t i_address, uint64_t * o_data ); + +/* XSCOM Write */ +int32_t xscom_write( uint32_t i_address, uint64_t i_data ); + +/* Sleep */ +void sleep( SsxInterval i_nanoseconds ); + + +#endif diff --git a/src/occ_gpe0/firdata/norflash.h b/src/occ_gpe0/firdata/norflash.h new file mode 100644 index 0000000..c4c9cdc --- /dev/null +++ b/src/occ_gpe0/firdata/norflash.h @@ -0,0 +1,154 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/norflash.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 __PNOR_NORFLASH_H +#define __PNOR_NORFLASH_H + +#include +#include + +/** @file norflash.H + * @brief Contains constants related to specific types of + * of NOR flash chips + */ + +/** + * @brief Supported NOR Chip IDs + */ +enum NorChipIDs +{ + UNKNOWN_NOR_ID = 0x12345600, /**< Initial value before read */ + + MICRON_MFG_ID = 0x20000000, /**< Micron Mfg ID */ + MICRON_NOR_ID = 0x20ba2000, /**< Micron NOR */ + + MACRONIX_MFG_ID = 0xC2000000, /**< Macronix Mfg ID */ + MACRONIX32_NOR_ID = 0xC2201A00, /**< Macronix NOR MXxxL51235F */ + MACRONIX64_NOR_ID = 0xC2201900, /**< Macronix NOR MXxxL25635F */ + + /* Note: Simics currently models Micron NOR */ + VPO_NOR_ID = 0x20201800, /**< VPO NOR chip ID */ + FAKE_NOR_ID = 0xBADBAD00, /**< ID used during fake pnor */ + + ID_MASK = 0xFFFFFF00, /**< Only look at 3 bytes */ + MFGID_MASK = 0xFF000000, /**< Manufacturer ID is the first byte */ +}; + +/** + * @brief SPI Config Info + * OP Codes and other MISC info for configuring SFC + */ +typedef enum +{ + SPI_NO_OPCODE = 0x00, /**< Undefined value */ + + /* + * Micron Flash Commands + */ + SPI_MICRON_FLAG_STAT = 0x70, /**< Check write/erase complete */ + SPI_MICRON_CLRFLAG_STAT = 0x50, /**< Clear write/erase Status reg */ + + /* + * Macronix Flash Commands + */ + SPI_MACRONIX_EN4B = 0xB7, /**< Enable Macronix 4-Byte addressing */ + + /* SPI protocol commands */ + SPI_JEDEC_WRITE_STATUS = 0x01, /*WRSR */ + SPI_JEDEC_PAGE_PROGRAM = 0x02, /*PP */ + SPI_JEDEC_READ = 0x03, /*READ */ + SPI_JEDEC_WRITE_DISABLE = 0x04, /*WRDI */ + SPI_JEDEC_READ_STATUS = 0x05, /*RDSR */ + SPI_JEDEC_WRITE_ENABLE = 0x06, /*WREN */ + SPI_JEDEC_FAST_READ = 0x0B, /*FAST_READ */ + SPI_JEDEC_SECTOR_ERASE = 0x20, /*SE */ + SPI_JEDEC_READ_SFDP = 0x5A, /*RDSFDP */ + SPI_JEDEC_CHIPID = 0x9F, /*RDID */ + SPI_JEDEC_BLOCK_ERASE = 0xD8, /*BE */ + +} SpiConfigInfo; + +/** + * @brief General Constants related to flash + */ +enum +{ + PAGE_PROGRAM_BYTES = 256, /***< 256 bytes per PP command */ +}; + + +/** + * Common format of Status Register + */ +typedef union +{ + uint8_t data8; + struct + { + uint8_t writeProtect : 1; /*0 */ + uint8_t rsvd : 5; /*1:5 */ + uint8_t writeEnable : 1; /*6 */ + uint8_t writeInProgress : 1; /*7 */ + }; +} NorStatusReg_t; + +/** + * Flags used to trigger Hardware workarounds + */ +enum +{ + /* No workarounds present */ + HWWK_NO_WORKAROUNDS = 0x00000000, + + /* Must perform 'read flag status' commands after */ + /* any write or erase */ + HWWK_MICRON_WRT_ERASE = 0x00000001, + + /* Must do a read of a low flash address before issuing read */ + /* commands that return more than 1 word of data */ + HWWK_MICRON_EXT_READ = 0x00000002, +}; + + +/* + * Vendor-specific interfaces + */ + +/** + * @brief Check flag status bit on Micron NOR chips + * The current version of Micron parts require the Flag + * Status register be read after a read or erase operation, + * otherwise all future operations won't work.. + * + * @parm i_pnorMbox Pnor Mbox Struct to operate on + * + * @return Error from operation + */ +errorHndl_t micronFlagStatus( pnorMbox_t* i_pnorMbox ); + + + + +#endif diff --git a/src/occ_gpe0/firdata/pnorData_common.h b/src/occ_gpe0/firdata/pnorData_common.h new file mode 100644 index 0000000..3037e39 --- /dev/null +++ b/src/occ_gpe0/firdata/pnorData_common.h @@ -0,0 +1,162 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/pnorData_common.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 __pnorData_common_h +#define __pnorData_common_h + +/** NOTE: This file is common between OCC and Hosboot. Any change to this file + * must be mirrored to both repositories. Also, this must be C, not C++, + * because OCC strictly uses C. */ + +#include +#include + +/** This file is used to define the format of the register data captured by the + * OCC and stored in PNOR. The data will be stored in the following format: + * + * - PNOR_Data_t struct - This has all of the information characterizing how + * many targets that have register data. + * - For each target with register data, the following format will be used: + * - PNOR_Trgt_t struct - Contains the target type, position, and how many + * registers are in the register list. + * - A list of all regular registers (PNOR_Reg_t). + * - A list of all indirect-SCOM registers (PNOR_IdReg_t). + * + * IMPORTANT NOTE: All of the structs used here are packed. Therefore, we must + * ensure the variables within the struct are byte aligned. Meaning each + * uint32_t within the struct must be 4-byte aligned and each uint16_t must + * be 2-byte aligned. This also means the structs must always start on a + * 4-bye word boundary to maintain alignment. This is required due to the + * limitations of the PPE42/SRAM hardware. + * + * The PNOR has limited data space. So the following rules will apply: + * - Any registers with the value of zero will not be captured. + * - Registers with SCOM errors will not be captured, however, the number + * of SCOM errors detected should be stored in each PNOR_Trgt_t struct. + * - If the value of a FIR (or ID FIR) is zero, do not capture the + * associated ACT0 and ACT1 registers. Note that the associated MASK + * register is still needed for FFDC. + * - Each target type may have associated global registers. If none exist, + * simply capture all registers for that type. However, if they do exist + * and the values of ALL the global registers are zero, skip capturing + * the associated registers of the target and any subsequent targets on + * the affinity path. Example, + * - For a MCBIST, skip this MCBIST and all associated MCSs, and MCAs. + * - If for some reason we run out of space in the PNOR, do not SCOM any + * more registers, set the 'full' bit in the PNOR_Data_t struct, and + * write all data successfully captured to PNOR. + */ + +typedef enum +{ + PNOR_FIR1 = 0x46495231, /** FIR data version 1 ("FIR1" in ascii) P8 */ + PNOR_FIR2 = 0x46495232, /** FIR data version 2 ("FIR2" in ascii) P9 */ + +} PNOR_Version_t; + +/** PNOR data header information. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t header; /** Magic number to indicate valid data and version */ + + uint32_t trgts : 12; /** Number of targets with register data */ + uint32_t full : 1; /** 1 if PNOR data is full and data incomplete */ + uint32_t iplState : 1; /** See enum IplState_t */ + uint32_t reserved : 18; + +} PNOR_Data_t; + +/** @return An initialized PNOR_Data_t struct. */ +static inline PNOR_Data_t PNOR_getData() +{ + PNOR_Data_t d; memset( &d, 0x00, sizeof(d) ); /* init to zero */ + + d.header = PNOR_FIR2; + + return d; +}; + +/** These values will match the corresponding bit fields in PNOR_Trgt_t. */ +typedef enum +{ + PNOR_Trgt_MAX_REGS_PER_TRGT = 511, /* Currently expect 266 on the PROC */ + PNOR_Trgt_MAX_ID_REGS_PER_TRGT = 15, /* Currently expect 9 on the MBA */ + PNOR_Trgt_MAX_SCOM_ERRORS = 255, /* Should be plenty */ + +} PNOR_Trgt_RegLimits_t; + +/** Information for each target with SCOM data. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t chipPos : 6; /** Parent chip position relative to the node */ + uint32_t unitPos : 5; /** Unit position relative to the parent chip */ + uint32_t regs : 9; /** Number of normal registers */ + uint32_t idRegs : 4; /** Number of indirect-SCOM registers */ + uint32_t scomErrs : 8; /** Number of SCOM errors detected */ + + uint32_t trgtType : 6; /** Target type. See enum TrgtType_t */ + uint32_t reserved : 26; + +} PNOR_Trgt_t; + +/** @param i_trgtType Target type. See enum TrgtType_t. + * @param i_chipPos Parent chip position relative to the node. + * @param i_unitPos Unit position relative to the parent chip. + * @return An initialized PNOR_Data_t struct. + */ +static inline PNOR_Trgt_t PNOR_getTrgt( uint32_t i_trgtType, uint32_t i_chipPos, + uint32_t i_unitPos ) +{ + PNOR_Trgt_t t; memset( &t, 0x00, sizeof(t) ); /* init to zero */ + + t.trgtType = i_trgtType; + t.chipPos = i_chipPos; + t.unitPos = i_unitPos; + + return t; +}; + +/** Information for a normal register. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint32_t addr; /** 32-bit address */ + uint64_t val; /** 64-bit value */ + +} PNOR_Reg_t; + +/** Information for an indirect-SCOM register. */ +/* NOTE: This structure is 4-byte word aligned. */ +typedef struct __attribute__((packed)) +{ + uint64_t addr; /** 64-bit address */ + uint32_t val; /** 32-bit value */ + +} PNOR_IdReg_t; + +#endif // __pnorData_common_h + diff --git a/src/occ_gpe0/firdata/pnor_mboxdd.c b/src/occ_gpe0/firdata/pnor_mboxdd.c new file mode 100644 index 0000000..463e950 --- /dev/null +++ b/src/occ_gpe0/firdata/pnor_mboxdd.c @@ -0,0 +1,404 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/pnor_mboxdd.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ + +/** + * @file ast_mboxdd.c + * + * @brief Implementation of the PNOR access code on top of AST MBOX protocol + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include +#include +#include +#include + +errorHndl_t hwInit(pnorMbox_t* i_pnorMbox) +{ + errorHndl_t l_err = NO_ERROR; + uint8_t* l_data; + int i; + do + { + //Current window starts closed + i_pnorMbox->iv_curWindowOpen = false; + i_pnorMbox->iv_mbox.iv_mboxMsgSeq = 1; + l_err = initializeMbox(); + if (l_err) + { + TRAC_ERR("initializeMbox failed rc:0x%x", l_err); + break; + } + + //Send message to BMC Mbox to get MBOX info + // This message gets the MBOX protocol version + mboxMessage_t l_getInfoMsg; + l_data = (uint8_t*)(&l_getInfoMsg); + for (i = 0; i < BMC_MBOX_DATA_REGS; i++) + { + l_data[i] = 0; + } + + l_getInfoMsg.iv_cmd = MBOX_C_GET_MBOX_INFO; + put8(&l_getInfoMsg, 0, 2); + l_err = doMessage(&i_pnorMbox->iv_mbox, &l_getInfoMsg); + if (l_err) + { + TRAC_ERR("doMessage to ping BMC failed with rc=0x%x", l_err); + break; + } + + i_pnorMbox->iv_protocolVersion = get8(&l_getInfoMsg, 0); + if (i_pnorMbox->iv_protocolVersion == 1) + { + i_pnorMbox->iv_blockShift = 12; + i_pnorMbox->iv_readWindowSize = get16(&l_getInfoMsg, 1) + << i_pnorMbox->iv_blockShift; + i_pnorMbox->iv_writeWindowSize = get16(&l_getInfoMsg, 3) + << i_pnorMbox->iv_blockShift; + } + else + { + i_pnorMbox->iv_blockShift = get8(&l_getInfoMsg, 5); + } + + //Now get the size of the flash + mboxMessage_t l_getSizeMsg; + l_getSizeMsg.iv_cmd = MBOX_C_GET_FLASH_INFO; + l_err = doMessage(&i_pnorMbox->iv_mbox, &l_getSizeMsg); + if (l_err) + { + TRAC_ERR("doMessage failed to get flash size rc=0x%x", l_err); + break; + } + + if (i_pnorMbox->iv_protocolVersion == 1) + { + i_pnorMbox->iv_flashSize = get32(&l_getSizeMsg, 0); + i_pnorMbox->iv_flashEraseSize = get32(&l_getSizeMsg, 4); + } + else + { + i_pnorMbox->iv_flashSize = get16(&l_getSizeMsg, 0) + << i_pnorMbox->iv_blockShift; + i_pnorMbox->iv_flashEraseSize = get16(&l_getSizeMsg, 2) + << i_pnorMbox->iv_blockShift; + } + } while (0); + return l_err; +} + + +errorHndl_t readFlash(pnorMbox_t* i_pnorMbox, + uint32_t i_addr, + size_t i_size, + void* o_data) +{ + errorHndl_t l_err = NO_ERROR; + + do + { + // Ensure we are operating on a 4-byte boundary + if ((i_size % 4 != 0) && (i_addr % 4 != 0)) + { + TRAC_ERR("readFlash: not on 4-byte boundary"); + return FAIL; + } + + while (i_size) + { + uint32_t l_lpcAddr; + size_t l_chunkLen; + + l_err = adjustMboxWindow(i_pnorMbox, + false, + i_addr, + i_size, + &l_lpcAddr, + &l_chunkLen); + + if (l_err) + { + break; + } + + //Directly access LPC to do read/write as BMC is setup now + l_err = lpc_read(LPC_TRANS_FW, l_lpcAddr, o_data, l_chunkLen); + + if (l_err) + { + break; + } + + i_addr += l_chunkLen; + i_size -= l_chunkLen; + o_data = (char*)o_data + l_chunkLen; + } + + if(l_err) + { + break; + } + + } + while(0); + + return l_err; +} + +errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, + uint32_t i_addr, + size_t i_size, + void* i_data) +{ + errorHndl_t l_err = NO_ERROR; + + do + { + // Ensure we are operating on a 4-byte boundary + if (i_size % 4 != 0) + { + TRAC_ERR("writeFlash: not on 4-byte boundary"); + return FAIL; + } + + + errorHndl_t l_flushErr = NO_ERROR; + + while (i_size) + { + uint32_t l_lpcAddr; + size_t l_chunkLen; + + l_err = adjustMboxWindow(i_pnorMbox, + true, + i_addr, + i_size, + &l_lpcAddr, + &l_chunkLen); + + if (l_err) + { + break; + } + + //Directly do LPC access to space pointed to by BMC + l_err = lpc_write(LPC_TRANS_FW, l_lpcAddr, i_data, l_chunkLen); + + if (l_err) + { + break; + } + + //Tell BMC to push data from LPC space into PNOR + l_err = writeDirty(i_pnorMbox, i_addr, l_chunkLen); + + if (l_err) + { + break; + } + + i_addr += l_chunkLen; + i_size -= l_chunkLen; + i_data = (char*)i_data + l_chunkLen; + } + + /* We flush whether we had an error or not. + * + * NOTE: It would help the daemon a lot if we moved that out of here + * and instead had a single flush call over a series of writes. + */ + l_flushErr = writeFlush(i_pnorMbox); + + if ( l_err == NO_ERROR && l_flushErr ) + { + l_err = l_flushErr; + } + + if( l_err ) + { + i_size = 0; + } + + if(l_err) + { + break; + } + + } + while(0); + + return l_err; +} + +errorHndl_t adjustMboxWindow(pnorMbox_t* i_pnorMbox, + bool i_isWrite, uint32_t i_reqAddr, + size_t i_reqSize, uint32_t *o_lpcAddr, + size_t *o_chunkLen) +{ + errorHndl_t l_err = NO_ERROR; + uint32_t l_pos, l_wSize, l_reqSize; + + do + { + /* + * Handle the case where the window is already opened, is of + * the right type and contains the requested address. + */ + uint32_t l_wEnd = i_pnorMbox->iv_curWindowOffset + + i_pnorMbox->iv_curWindowSize; + + /* A read request can be serviced by a write window */ + if (i_pnorMbox->iv_curWindowOpen && + (i_pnorMbox->iv_curWindowWrite || !i_isWrite) && + i_reqAddr >= i_pnorMbox->iv_curWindowOffset && i_reqAddr < l_wEnd) + { + size_t l_gap = (l_wEnd - i_reqAddr); + + *o_lpcAddr = i_pnorMbox->iv_curWindowLpcOffset + + (i_reqAddr - i_pnorMbox->iv_curWindowOffset); + if (i_reqSize <= l_gap) + { + *o_chunkLen = i_reqSize; + } + else + { + *o_chunkLen = l_gap; + } + return NO_ERROR; + } + + /* + * We need a window change, mark it closed first + */ + i_pnorMbox->iv_curWindowOpen = false; + + /* + * Then open the new one at the right position. The required + * alignment differs between protocol versions + */ + if (i_pnorMbox->iv_protocolVersion == 1) + { + l_wSize = i_isWrite ? i_pnorMbox->iv_writeWindowSize + : i_pnorMbox->iv_readWindowSize; + l_pos = i_reqAddr & ~(l_wSize - 1); + l_reqSize = 0; + } + else + { + uint32_t l_blockMask = (1u << i_pnorMbox->iv_blockShift) - 1; + l_wSize = 0; + l_pos = i_reqAddr & ~l_blockMask; + l_reqSize = (((i_reqAddr + i_reqSize) + l_blockMask) & ~l_blockMask) + - l_pos; + } + + mboxMessage_t winMsg; + if (i_isWrite) + { + winMsg.iv_cmd = MBOX_C_CREATE_WRITE_WINDOW; + } + else + { + winMsg.iv_cmd = MBOX_C_CREATE_READ_WINDOW; + } + + put16(&winMsg, 0, l_pos >> i_pnorMbox->iv_blockShift); + put16(&winMsg, 2, l_reqSize >> i_pnorMbox->iv_blockShift); + l_err = doMessage(&i_pnorMbox->iv_mbox, &winMsg); + + if (l_err) + { + break; + } + + i_pnorMbox->iv_curWindowLpcOffset = + (get16(&winMsg,0)) << i_pnorMbox->iv_blockShift; + + if (i_pnorMbox->iv_protocolVersion == 1) + { + i_pnorMbox->iv_curWindowOffset = l_pos; + i_pnorMbox->iv_curWindowLpcOffset = + (get16(&winMsg,0)) << i_pnorMbox->iv_blockShift; + i_pnorMbox->iv_curWindowSize = l_wSize; + } + else + { + i_pnorMbox->iv_curWindowLpcOffset = (get16(&winMsg,0)) + << i_pnorMbox->iv_blockShift; + i_pnorMbox->iv_curWindowSize = (get16(&winMsg,2)) + << i_pnorMbox->iv_blockShift; + i_pnorMbox->iv_curWindowOffset = (get16(&winMsg,4)) + << i_pnorMbox->iv_blockShift; + } + + i_pnorMbox->iv_curWindowOpen = true; + i_pnorMbox->iv_curWindowWrite = i_isWrite; + + } + while (true); + + return l_err; +} + +errorHndl_t writeDirty(pnorMbox_t* i_pnorMbox, uint32_t i_addr, size_t i_size) +{ + /* To pass a correct "size" for both protocol versions, we + * calculate the block-aligned start and end. + */ + uint32_t l_blockMask = (1u << i_pnorMbox->iv_blockShift) - 1; + uint32_t l_start = i_addr & ~l_blockMask; + uint32_t l_end = ((i_addr + i_size) + l_blockMask) & ~l_blockMask; + + mboxMessage_t dirtyMsg; + dirtyMsg.iv_cmd = MBOX_C_MARK_WRITE_DIRTY; + + if (i_pnorMbox->iv_protocolVersion == 1) + { + put16(&dirtyMsg, 0, i_addr >> i_pnorMbox->iv_blockShift); + put32(&dirtyMsg, 2, l_end - l_start); + } + else + { + put16(&dirtyMsg, 0, (i_addr - i_pnorMbox->iv_curWindowOffset) + >> i_pnorMbox->iv_blockShift); + put16(&dirtyMsg, 2, (l_end - l_start) >> i_pnorMbox->iv_blockShift); + } + + return doMessage(&i_pnorMbox->iv_mbox, &dirtyMsg); +} + +errorHndl_t writeFlush(pnorMbox_t* i_pnorMbox) +{ + mboxMessage_t flushMsg; + flushMsg.iv_cmd = MBOX_C_WRITE_FLUSH; + + put16(&flushMsg, 0, 0); + put32(&flushMsg, 2, 0); + + return doMessage(&i_pnorMbox->iv_mbox, &flushMsg); +} diff --git a/src/occ_gpe0/firdata/pnor_mboxdd.h b/src/occ_gpe0/firdata/pnor_mboxdd.h new file mode 100644 index 0000000..ab8f05d --- /dev/null +++ b/src/occ_gpe0/firdata/pnor_mboxdd.h @@ -0,0 +1,135 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/pnor_mboxdd.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __PNOR_MBOX_H +#define __PNOR_MBOX_H + +//NOTE: Protocol Definition is here: +// https://github.com/openbmc/mboxbridge/blob/master/Documentation/mbox_protocol.md + +#include + +/** @file pnor_mbox.h + * @brief Provides the interfaces to the PNOR via the + * MBOX protocol + */ + +typedef struct +{ + astMbox_t iv_mbox; + uint32_t iv_protocolVersion; + //Block size is either 4k (V1) or BMC defined (V2) + // the iv_blockShift parm is a representation of that size + // as a power of 2. Most command and response args are specified + // in some multiple of block size + uint32_t iv_blockShift; + uint32_t iv_flashSize; + uint32_t iv_flashEraseSize; + // Current Window + bool iv_curWindowOpen; // Currently open + bool iv_curWindowWrite; // Write vs Read window + uint32_t iv_curWindowOffset; // Offset into flash + uint32_t iv_curWindowSize; // Size + uint32_t iv_curWindowLpcOffset; // Offset into LPC FW space + // Legacy v1 protocol + uint32_t iv_readWindowSize; + uint32_t iv_writeWindowSize; + +} pnorMbox_t; + +/* + * @brief Do base initialization of the MBOX functionality + * + * @parm[io] io_pnorMbox - Pointer to pnorMbox_t structure + * + * @return Error from operation + */ +errorHndl_t hwInit(pnorMbox_t* i_pnorMbox); + +/* + * @brief Read data from the PNOR flash + * + * @param[in] Pointer to pnorMbox struct + * @parm[in] i_addr PNOR flash Address to read + * @parm[in] i_size Amount of data to read, in bytes. + * @parm[out] o_data Buffer to read data into + * + * @return Error from operation + */ +errorHndl_t readFlash(pnorMbox_t* i_pnorMbox, + uint32_t i_addr, + size_t i_size, + void* o_data); + +/** + * @brief Write data to the PNOR flash + * @param[in] Pointer to pnorMbox struct + * @parm i_addr PNOR flash Address to write + * @parm i_size Amount of data to write, in bytes. + * @parm i_data Buffer containing data to write + * + * @return Error from operation + */ +errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, + uint32_t i_addr, + size_t i_size, + void* i_data); + +/** + * @brief Open a window on the BMC for PNOR accesses + * if necessary and return adjusted LPC address and chunk size + * @param[in] Pointer to pnorMbbox struct + * @parm[in] i_isWrite Write or read window + * @parm[in] i_reqAddr Requested flash offset + * @parm[in] i_reqSize Requested size + * @parm[out] o_lpcAddr LPC offset for the requested offset + * @parm[out] o_chunkLen i_reqSize adjusted to fit in the window + * + * @return Error from operation + */ +errorHndl_t adjustMboxWindow(pnorMbox_t* i_pnorMbox, + bool i_isWrite, + uint32_t i_reqAddr, + size_t i_reqSize, + uint32_t *o_lpcAddr, + size_t *o_chunkLen); + +/** + * @brief Mark a range dirty in a write window + * @param[in] Pointer to pnorMbox struct + * @parm[in] i_addr Flash offset of the range + * @parm[in] i_size Size of the range + * + * @return Error from operation + */ +errorHndl_t writeDirty(pnorMbox_t* i_pnorMbox, uint32_t i_addr, size_t i_size); + +/** +* @brief Flush all pending dirty data to the flash +* @param[in] Pointer to pnorMbox struct +* @return Error from operation +*/ +errorHndl_t writeFlush(pnorMbox_t* i_pnorMbox); + +#endif /* __PNOR_MBOX_H */ diff --git a/src/occ_gpe0/firdata/pnor_util.c b/src/occ_gpe0/firdata/pnor_util.c new file mode 100644 index 0000000..2c48179 --- /dev/null +++ b/src/occ_gpe0/firdata/pnor_util.c @@ -0,0 +1,220 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/pnor_util.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +/* Interfaces to write into PNOR */ + +#include +#include +#include +#include + +/*================================================================= */ +/* The offset of the next byte to write */ +uint32_t g_next_byte = 0xFFFFFFFF; +/* Size of the FIRDATA section of PNOR */ +uint32_t g_pnor_size = 0; +/* Global PNOR Mbox object */ +pnorMbox_t* g_pnorMbox; + +/* Cache to queue up PNOR writes */ +uint8_t g_write_cache[PAGE_PROGRAM_BYTES]; +/* Current position of data inside write cache */ +size_t g_write_cache_index = 0; + +/** + * @brief Write 8 bytes of data into PNOR starting + */ +int32_t pnor_write_8B( uint64_t i_data ) +{ + int32_t rc = SUCCESS; + + if ( (g_next_byte == 0xFFFFFFFF) || /* initialized data */ + ((g_next_byte + g_pnor_size) < (g_next_byte + 9)) ) /* make sure there is room */ + { + TRACFCOMP("pnor_write_8B> g_next_byte=%.8X, g_pnor_size=%.8X",g_next_byte,g_pnor_size); + /* must have been some error in the prep */ + return FAIL; + } + +//@TODO: Do we need ECC, or does the BMC handle that for us now? + /* Create 9-byte ECC-ified version */ +// uint8_t data9[9]; +// injectECC( (uint8_t*)(&i_data), 8, data9 ); + + /* Copy data into the write cache until we queue up + a big chunk of data to write. This is more efficient + and avoids handling the write boundary of the PP + command internally. */ +// size_t cpsz = 9; + + uint8_t data8[8]; + size_t cpsz = 8; + + if( (g_write_cache_index + cpsz) > PAGE_PROGRAM_BYTES ) + { + cpsz = PAGE_PROGRAM_BYTES - g_write_cache_index; + } + memcpy( &(g_write_cache[g_write_cache_index]), data8, cpsz ); +// memcpy( &(g_write_cache[g_write_cache_index]), data9, cpsz ); + + g_write_cache_index += cpsz; + + /* Write a complete chunk into the flash */ + if( g_write_cache_index == PAGE_PROGRAM_BYTES ) + { + errorHndl_t tmp = writeFlash( g_pnorMbox, + g_next_byte, + PAGE_PROGRAM_BYTES, + g_write_cache ); + if ( NO_ERROR != tmp ) + { + TRACFCOMP("pnor_write_8B> writeFlash failed"); + /* hit an error, stop any more writes from happening */ + g_next_byte = 0xFFFFFFFF; + g_pnor_size = 0; + return FAIL; + } + g_next_byte += PAGE_PROGRAM_BYTES; + memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); + g_write_cache_index = 0; + + if( (8 - cpsz) > 0 ) + { + memcpy( &(g_write_cache[0]), &(data8[cpsz]), 8 - cpsz ); + g_write_cache_index = 8 - cpsz; + } + + /* Handle the overflow */ +// if( (9 - cpsz) > 0 ) +// { +// memcpy( &(g_write_cache[0]), &(data9[cpsz]), 9 - cpsz ); +// g_write_cache_index = 9 - cpsz; +// } + } + + return rc; +} + + +/** + * @brief Perform any necessary operations to prepare + * the PNOR hw/code for writing + */ +errorHndl_t pnor_prep( HOMER_PnorInfo_t* i_pnorInfo ) +{ + errorHndl_t l_err = NO_ERROR; + + /* Figure out where to start */ + TRACFCOMP("FIRDATA is at %.8X..%.8X", i_pnorInfo->pnorOffset, i_pnorInfo->pnorOffset+i_pnorInfo->pnorSize ); + g_next_byte = i_pnorInfo->pnorOffset; + g_pnor_size = i_pnorInfo->pnorSize; + memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); + + /* Can we rely on skiboot leaving things in a good state? */ + l_err = hwInit(g_pnorMbox); + if( l_err ) + { + TRACFCOMP("hwInit failed"); + /* hit an error, stop any writes from happening */ + g_next_byte = 0xFFFFFFFF; + g_pnor_size = 0; + } + + return l_err; +} + +/*------------------------------------------------------------------------------ */ + +int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, + uint8_t * i_buf, uint32_t i_bufSize ) +{ + int32_t rc = SUCCESS; + TRACFCOMP(">>PNOR_writeFirData"); + + do + { + /* Initialize the PNOR data. */ + errorHndl_t l_err = pnor_prep( &i_pnorInfo ); + if( l_err ) + { + TRACFCOMP("pnor_prep failed"); + rc = FAIL; + break; /*nothing more to do here*/ + } + + uint32_t idx = 0; + uint64_t dataChunk = 0; + size_t sz_dataChunk = sizeof(uint64_t); + + /* Add PNOR data 8 bytes at a time. */ + for ( idx = 0; idx < i_bufSize; idx += sz_dataChunk ) + { + memcpy( &dataChunk, &i_buf[idx], sz_dataChunk ); + + rc = pnor_write_8B( dataChunk ); + if ( SUCCESS != rc ) + { + TRACFCOMP( "pnor_write_8B() failed during FIR write" ); + break; + } + } + if ( SUCCESS != rc ) break; + + /* Add any extra bytes if they exist at the end of the buffer. */ + if ( idx != i_bufSize ) + { + uint32_t extraBytes = idx - i_bufSize; + + dataChunk = 0; + memcpy( &dataChunk, &i_buf[idx], extraBytes ); + + rc = pnor_write_8B( dataChunk ); + if ( SUCCESS != rc ) + { + TRACFCOMP( "pnor_write_8B() failed during blank fill" ); + break; + } + } + + /* Fill the rest of the page with good ECC */ + for ( idx = i_bufSize; + idx < i_pnorInfo.pnorSize; + idx += sz_dataChunk ) + { + dataChunk = 0xFFFFFFFFFFFFFFFFull; + rc = pnor_write_8B( dataChunk ); + if ( SUCCESS != rc ) + { + TRACFCOMP( "pnor_write_8B() failed during ECC fill" ); + break; + } + } + + } while (0); + + TRACFCOMP("< + +/** + * @brief Writes a buffer containing the FIR data to PNOR (adding ECC). + * @param i_pnorInfo Information regarding PNOR location, size, etc. + * @param i_buf Data buffer (no ECC included). + * @param i_bufSize Size of the data buffer. + * @return Non-SUCCESS, if the write fails. SUCCESS, otherwise. + */ +int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, + uint8_t * i_buf, uint32_t i_bufSize ); + +#endif /* __pnor_util_h */ diff --git a/src/occ_gpe0/firdata/sbe_fifo.c b/src/occ_gpe0/firdata/sbe_fifo.c new file mode 100644 index 0000000..9a2099a --- /dev/null +++ b/src/occ_gpe0/firdata/sbe_fifo.c @@ -0,0 +1,444 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/sbe_fifo.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#include "sbe_fifo.h" +#include +#include +#include + +/** @brief Waits for FIFO to be ready to be written to + * @param i_target The SCOM target. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +uint32_t waitUpFifoReady(SCOM_Trgt_t* i_target) +{ + uint32_t l_rc = SUCCESS; + + uint64_t l_elapsed_time_ns = 0; + uint32_t l_addr = SBE_FIFO_UPFIFO_STATUS; + uint32_t l_data = 0; + + do + { + //Read upstream status to see if there is room for more data + l_rc = getfsi(*i_target, l_addr, &l_data); + if(l_rc != SUCCESS) + { + TRAC_ERR("waitUpFifoReady: failed to getfsi from addr 0x%08x", + l_addr); + break; + } + + if(!(l_data & UPFIFO_STATUS_FIFO_FULL)) + { + break; + } + + //Check for timeout + if(l_elapsed_time_ns >= MAX_UP_FIFO_TIMEOUT_NS) + { + l_rc = FAIL; + TRAC_ERR("waitUpFifoReady: timeout occurred while waiting for" + " FIFO to clear"); + break; + } + + sleep(10000); //sleep for 10,000 ns + l_elapsed_time_ns += 10000; + }while(TRUE); + + return l_rc; +} + +/** @brief Waits for information to show up in FIFO + * @param i_target The SCOM target. + * @param o_status the status of the FIFO + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +uint32_t waitDnFifoReady(SCOM_Trgt_t* i_target, uint32_t* o_status) +{ + uint32_t l_rc = SUCCESS; + + uint64_t l_elapsed_time_ns = 0; + uint32_t l_addr = SBE_FIFO_DNFIFO_STATUS; + + do + { + // read dnstream status to see if data ready to be read + // or if has hit the EOT + l_rc = getfsi(*i_target, l_addr, o_status); + if(l_rc != SUCCESS) + { + return l_rc; + } + + if(!(*o_status & DNFIFO_STATUS_FIFO_EMPTY) || + (*o_status & DNFIFO_STATUS_DEQUEUED_EOT_FLAG)) + { + break; + } + else + { + TRAC_IMP("SBE status reg returned fifo empty or dequeued eot flag 0x%.8X", + *o_status); + } + + // Check for timeout + if(l_elapsed_time_ns >= MAX_UP_FIFO_TIMEOUT_NS) + { + TRAC_ERR("waitDnFifoReady: timeout waiting for downstream FIFO" + " to be empty."); + l_rc = FAIL; + break; + } + + sleep(10000); // wait for 10,000 ns + l_elapsed_time_ns += 10000; + + }while(TRUE); + + return l_rc; +} + +/** @brief Writes a request to FIFO + * @param i_target The SCOM target. + * @param i_fifoRequest the request to execute. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +uint32_t writeRequest(SCOM_Trgt_t* i_target, uint32_t* i_fifoRequest) +{ + uint32_t l_rc = SUCCESS; + + TRAC_IMP("Enter writeRequest"); + + // Ensure Downstream Max Transfer Counter is 0 non-0 can cause + // protocol issues) + uint32_t l_addr = SBE_FIFO_DNFIFO_MAX_TSFR; + uint32_t l_data = 0; + l_rc = putfsi(*i_target, l_addr, l_data); + if(l_rc != SUCCESS) + { + TRAC_ERR("writeRequest: failed to putfsi to addr 0x%08x", + l_addr); + return l_rc; + } + + //The first uint32_t has the number of uint32_t words in the request + l_addr = SBE_FIFO_UPFIFO_DATA_IN; + uint32_t* l_sent = i_fifoRequest; //This pointer will advance as words are sent + uint32_t l_count = *l_sent; + uint32_t i; + + for(i = 0; i < l_count; ++i) + { + //Wait for room to write into fifo + l_rc = waitUpFifoReady(i_target); + if(l_rc != SUCCESS) + { + return l_rc; + } + + //Send data into fifo + l_rc = putfsi(*i_target, l_addr, *l_sent); + if(l_rc != SUCCESS) + { + TRAC_ERR("writeRequest: failed to putfsi to addr 0x%08x", + l_addr); + return l_rc; + } + + l_sent++; + } + + //Notify SBE that last word has been sent + l_rc = waitUpFifoReady(i_target); + if(l_rc != SUCCESS) + { + return l_rc; + } + + l_addr = SBE_FIFO_UPFIFO_SIG_EOT; + l_data = FSB_UPFIFO_SIG_EOT; + l_rc = putfsi(*i_target, l_addr, l_data); + if(l_rc != SUCCESS) + { + TRAC_ERR("writeRequest: failed to putfsi to addr 0x%08x", l_addr); + } + + TRAC_IMP("Exit writeRequest"); + + return l_rc; +} + +/** @brief Reads and processes the FIFO response + * @param i_target The SCOM target. + * @param i_fifoRequest the original FIFO request. + * @param o_fifoResponse the FIFO response. + * @param i_responseSize the expected size of the response. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +uint32_t readResponse(SCOM_Trgt_t* i_target, + uint32_t* i_fifoRequest, + uint32_t* o_fifoResponse, + uint32_t i_responseSize) +{ + uint32_t l_rc = SUCCESS; + uint32_t l_readBuffer[READ_BUFFER_SIZE]; + + TRAC_IMP("Enter readResponse"); + + // EOT is expected before the response buffer is full. Room for + // the PCBPIB status or FFDC is included, but is only returned + // if there is an error. The last received word has the distance + // to the status, which is placed at the end of the returned data + // in order to reflect errors during transfer. + + uint32_t* l_received = o_fifoResponse; // advance as words are received + uint32_t l_maxWords = i_responseSize / sizeof(uint32_t); + uint32_t l_wordsReceived = 0; // Used to validata the "distance" to status + bool l_eotReceived = FALSE; + uint32_t l_lastWord = 0; // Last word received. Final read is the "distance" + // in words to the status header. + bool l_overRun = FALSE; + + do + { + // Wait for data to be ready to receive (download) or if the EOT + // has been sent. If not EOT, then data ready to receive. + uint32_t l_status = 0; + l_rc = waitDnFifoReady(i_target, &l_status); + if(l_rc != SUCCESS) + { + return l_rc; + } + + if(l_status & DNFIFO_STATUS_DEQUEUED_EOT_FLAG) + { + l_eotReceived = TRUE; + // Ignore EOT dummy word + if(l_wordsReceived >= (sizeof(struct statusHeader) / sizeof(uint32_t))) + { + if(l_overRun == FALSE) + { + l_received--; + l_wordsReceived--; + l_lastWord = o_fifoResponse[l_wordsReceived-1]; + } + else + { + l_lastWord = l_readBuffer[l_wordsReceived-2]; + } + } + break; + } + + // When error occurs, SBE will write more than l_maxWords + // we have to keep reading 1 word at a time until we get EOT + // or more than READ_BUFFER_SIZE. Save what we read in the buffer + if(l_wordsReceived >= l_maxWords) + { + l_overRun = TRUE; + } + + // Read next word + l_rc = getfsi(*i_target, SBE_FIFO_DNFIFO_DATA_OUT, &l_lastWord); + if(l_rc != SUCCESS) + { + return l_rc; + } + + l_readBuffer[l_wordsReceived] = l_lastWord; + + if(l_overRun == FALSE) + { + *l_received = l_lastWord; // Copy to returned output buffer + l_received++; // Advance to the next position + } + l_wordsReceived++; + + if(l_wordsReceived > READ_BUFFER_SIZE) + { + TRAC_ERR("readResponse: data overflow without EOT"); + l_rc = FAIL; + return l_rc; + } + + }while(TRUE); + + // At this point, l_wordsReceived of words received. + // l_received points to 1 word past last word received. + // l_lastWord has last word received, which is "distance" to status + // EOT is expected before running out of response buffer + if(!l_eotReceived) + { + l_rc = FAIL; + TRAC_ERR("readResponse: no EOT cmd = 0x%08x size = %d", + i_fifoRequest[1], i_responseSize); + return l_rc; + } + + // Notify SBE that EOT has been received + uint32_t l_eotSig = FSB_UPFIFO_SIG_EOT; + l_rc = putfsi(*i_target, SBE_FIFO_DNFIFO_ACK_EOT, l_eotSig); + if(l_rc != SUCCESS) + { + return l_rc; + } + + // Determine if transmission is successful. + // Last word received has the distance to status in words including itself. + // l_wordsReceived has number of words received. + // Need to have received at least status header and distance word. + if((l_lastWord < (sizeof(struct statusHeader)/sizeof(uint32_t) + 1)) || + (l_wordsReceived < (sizeof(struct statusHeader)/sizeof(uint32_t) + 1)) || + (l_lastWord > l_wordsReceived)) + { + TRAC_ERR("readResponse: invalid status distance. Cmd = 0x%08x distance" + " = %d allocated response size = %d received word size = %d", + i_fifoRequest[1], l_lastWord, i_responseSize, l_wordsReceived); + l_rc = FAIL; + return l_rc; + } + + // Check status for success. + // l_received points one word past last word received. + // l_lastWord has number of words to status header including self. + uint32_t* l_statusTmp = (l_overRun == FALSE) ? (l_received - l_lastWord) : + &l_readBuffer[l_wordsReceived - 1]; + struct statusHeader* l_statusHeader = (struct statusHeader*)l_statusTmp; + if((FIFO_STATUS_MAGIC != l_statusHeader->magic) || + (SBE_PRI_OPERATION_SUCCESSFUL != l_statusHeader->primaryStatus) || + (SBE_SEC_OPERATION_SUCCESSFUL != l_statusHeader->secondaryStatus)) + { + TRAC_ERR("readResponse: failing downstream status cmd = 0x%08x magic = " + "0x%08x primary status = 0x%08x secondary status = 0x%08x", + i_fifoRequest[1], + l_statusHeader->magic, + l_statusHeader->primaryStatus, + l_statusHeader->secondaryStatus); + + l_rc = FAIL; + } + + TRAC_IMP("Exit readResponse"); + return l_rc; +} + +/** @brief Performs a FIFO operation (read or write) + * @param i_target The SCOM target. + * @param i_fifoRequest the FIFO request data structure + * @param i_fifoResponse the response from SBE + * @param i_responseSize the size of the response + * @return Non-SUCCESS if the operation fails. SUCCESS otherwise. + */ +uint32_t performFifoChipOp(SCOM_Trgt_t* i_target, + uint32_t* i_fifoRequest, + uint32_t* i_fifoResponse, + uint32_t i_responseSize) +{ + uint32_t l_rc = SUCCESS; + + TRAC_IMP("Enter performFifoChipOp"); + + l_rc = writeRequest(i_target, i_fifoRequest); + if(l_rc != SUCCESS) + { + return l_rc; + } + + l_rc = readResponse(i_target, + i_fifoRequest, + i_fifoResponse, + i_responseSize); + + TRAC_IMP("Exit performFifoChioOp"); + + return l_rc; +} + +/** @brief Performs a write SCOM operation using SBE FIFO + * @param i_target The SCOM target. + * @param i_addr 64-bit SCOM address. + * @param i_data 64-bit data to write. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +int32_t putFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t i_data) +{ + uint32_t l_rc = SUCCESS; + + TRAC_IMP("Enter putFifoScom"); + + struct fifoPutScomRequest l_fifoRequest; + struct fifoPutScomResponse l_fifoResponse; + + l_fifoRequest.wordCnt = PUT_SCOM_REQUEST_WORD_CNT; + l_fifoRequest.reserved = 0; + l_fifoRequest.commandClass = SBE_FIFO_CLASS_SCOM_ACCESS; + l_fifoRequest.command = SBE_FIFO_CMD_PUT_SCOM; + l_fifoRequest.address = i_addr; + l_fifoRequest.data = i_data; + + l_rc = performFifoChipOp(i_target, + (uint32_t*)&l_fifoRequest, + (uint32_t*)&l_fifoResponse, + sizeof(struct fifoPutScomResponse)); + + TRAC_IMP("Exit putFifoScom"); + + return l_rc; +} + +/** @brief Performs a read SCOM operation using SBE FIFO + * @param i_target The SCOM target. + * @param i_addr 64-bit SCOM address. + * @param o_data 64-bit returned value. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +int32_t getFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t* o_data) +{ + uint32_t l_rc = SUCCESS; + + TRAC_IMP("Enter getFifoScom"); + + struct fifoGetScomRequest l_fifoRequest; + struct fifoGetScomResponse l_fifoResponse; + + l_fifoRequest.wordCnt = GET_SCOM_REQUEST_WORD_CNT; + l_fifoRequest.reserved = 0; + l_fifoRequest.commandClass = SBE_FIFO_CLASS_SCOM_ACCESS; + l_fifoRequest.command = SBE_FIFO_CMD_GET_SCOM; + l_fifoRequest.address = i_addr; + + l_rc = performFifoChipOp(i_target, + (uint32_t*)&l_fifoRequest, + (uint32_t*)&l_fifoResponse, + sizeof(struct fifoGetScomResponse)); + + //Always return data even if there is an error + *o_data = l_fifoResponse.data; + + TRAC_IMP("Exit getFifoScom"); + + return l_rc; +} diff --git a/src/occ_gpe0/firdata/sbe_fifo.h b/src/occ_gpe0/firdata/sbe_fifo.h new file mode 100644 index 0000000..4194471 --- /dev/null +++ b/src/occ_gpe0/firdata/sbe_fifo.h @@ -0,0 +1,123 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/sbe_fifo.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __SBE_FIFO_H +#define __SBE_FIFO_H + +#include +#include + +#define PACKED __attribute__((__packed__)) + +#define PUT_SCOM_REQUEST_WORD_CNT 0x06 +#define GET_SCOM_REQUEST_WORD_CNT 0x04 + +#define SBE_FIFO_CMD_GET_SCOM 0x01 +#define SBE_FIFO_CMD_PUT_SCOM 0x02 +#define SBE_FIFO_CLASS_SCOM_ACCESS 0xA2 +#define SBE_FIFO_DNFIFO_MAX_TSFR 0x00002458 +#define SBE_FIFO_UPFIFO_DATA_IN 0x00002400 +#define SBE_FIFO_UPFIFO_SIG_EOT 0x00002408 +#define FSB_UPFIFO_SIG_EOT 0x80000000 +#define SBE_FIFO_UPFIFO_STATUS 0x00002404 +#define SBE_FIFO_DNFIFO_STATUS 0x00002444 +#define UPFIFO_STATUS_FIFO_FULL 0x00200000 +#define DNFIFO_STATUS_FIFO_EMPTY 0x00100000 +#define DNFIFO_STATUS_DEQUEUED_EOT_FLAG 0x00800000 +#define SBE_FIFO_DNFIFO_ACK_EOT 0x00002454 +#define SBE_FIFO_DNFIFO_DATA_OUT 0x00002440 +#define NS_PER_MSEC (1000000ull) +#define MAX_UP_FIFO_TIMEOUT_NS 10*NS_PER_MSEC +#define READ_BUFFER_SIZE 2048 +#define FIFO_STATUS_MAGIC 0xC0DE +#define SBE_PRI_OPERATION_SUCCESSFUL 0x00 +#define SBE_SEC_OPERATION_SUCCESSFUL 0x00 + +struct statusHeader +{ + uint16_t magic; //set to 0xC0DE + uint8_t commandClass; + uint8_t command; + uint16_t primaryStatus; + uint16_t secondaryStatus; +} PACKED; + +struct ffdc_struct +{ + const void* ptr; + size_t size; +}; + +struct fifoPutScomRequest +{ + uint32_t wordCnt; + uint16_t reserved; + uint8_t commandClass; + uint8_t command; + uint64_t address; + uint64_t data; +} PACKED; + +struct fifoPutScomResponse +{ + struct statusHeader status; + struct ffdc_struct ffdc; //ffdc data + uint32_t status_distance; //distance to status +} PACKED; + +struct fifoGetScomRequest +{ + uint32_t wordCnt; + uint16_t reserved; + uint8_t commandClass; + uint8_t command; + uint64_t address; +} PACKED; + +struct fifoGetScomResponse +{ + uint64_t data; //Data (0..31) + (32..63) + struct statusHeader status; + struct ffdc_struct ffdc; //ffdc data + uint32_t status_distance; // distance to status +} PACKED; + +/** @brief Performs a write SCOM operation using SBE FIFO + * @param i_target The SCOM target. + * @param i_addr 64-bit SCOM address. + * @param i_data 64-bit data to write. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +int32_t putFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t i_data); + +/** @brief Performs a read SCOM operation using SBE FIFO + * @param i_target The SCOM target. + * @param i_addr 64-bit SCOM address. + * @param o_data 64-bit returned value. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +int32_t getFifoScom(SCOM_Trgt_t* i_target, uint64_t i_addr, uint64_t* o_data); + +#endif + diff --git a/src/occ_gpe0/firdata/scom_addr_util.c b/src/occ_gpe0/firdata/scom_addr_util.c new file mode 100644 index 0000000..a59a5a7 --- /dev/null +++ b/src/occ_gpe0/firdata/scom_addr_util.c @@ -0,0 +1,82 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/scom_addr_util.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#include "scom_addr_util.h" + + +void set_sat_id(const uint8_t i_sat_id, uint64_t * o_addr) +{ + *o_addr &= 0xFFFFFFFFFFFFFC3FULL; + *o_addr |= ((i_sat_id & 0xF) << 6); +} + +void set_chiplet_id(const uint8_t i_chiplet_id, uint64_t * o_addr) +{ + *o_addr &= 0xFFFFFFFFC0FFFFFFULL; + *o_addr |= ((i_chiplet_id & 0x3F) << 24); +} + +void set_ring(const uint8_t i_ring, uint64_t * o_addr) +{ + *o_addr &= 0xFFFFFFFFFFFF03FFULL; + *o_addr |= ((i_ring & 0x3F) << 10); +} + +void set_sat_offset(const uint8_t i_sat_offset, uint64_t * o_addr) +{ + *o_addr &= 0xFFFFFFFFFFFFFFC0ULL; + *o_addr |= (i_sat_offset & 0x3F); +} + +void set_rxtx_group_id(const uint8_t i_grp_id, uint64_t * o_addr) +{ + *o_addr &= 0xFFFFF81FFFFFFFFFULL; + *o_addr |= (i_grp_id & 0x3FULL) << 37; +} + +uint8_t get_sat_id(const uint64_t i_addr) +{ + return ((i_addr >> 6) & 0xF); +} + +uint8_t get_chiplet_id(const uint64_t i_addr) +{ + return ((i_addr >> 24) & 0x3F); +} + +uint8_t get_ring(const uint64_t i_addr) +{ + return ((i_addr >> 10) & 0x3F); +} + +uint8_t get_sat_offset(const uint64_t i_addr) +{ + return (i_addr & 0x3F); +} + +uint8_t get_rxtx_group_id(const uint64_t i_addr) +{ + return (i_addr >> 37) & 0x3F; +} + diff --git a/src/occ_gpe0/firdata/scom_addr_util.h b/src/occ_gpe0/firdata/scom_addr_util.h new file mode 100644 index 0000000..51988b4 --- /dev/null +++ b/src/occ_gpe0/firdata/scom_addr_util.h @@ -0,0 +1,81 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/scom_addr_util.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __scom_addr_util_h +#define __scom_addr_util_h + +#include + +//This file is a result of de-classing the p9_scom_addr that currently +//lives in EKB: chips/p9/common/scominfo/p9_scom_addr.H + +// @brief Modify SCOM address, update satellite ID field +// @param[in] i_sat_id Satellite ID value to write +// @retval none +// +void set_sat_id(const uint8_t i_sat_id, uint64_t * o_addr); + +// @brief Modify SCOM address, update pervasive chiplet ID +// @param[in] i_chiplet_id Chiplet ID value to write +// @retval none +// +void set_chiplet_id(const uint8_t i_chiplet_id, uint64_t * o_addr); + +// @brief Modify SCOM address, update ring field value +// @param[in] i_ring Ring field value to write +// @retval none +void set_ring(const uint8_t i_ring, uint64_t * o_addr); + +// @brief Modify SCOM address, update satellite offset field +// @param[in] i_sat_offset Satellite offset value to write +// @retval none +void set_sat_offset(const uint8_t i_sat_offset, uint64_t * o_addr); + +// @brief Modify SCOM address, update the RX or TX Group ID +// @param[in] i_grp_id Group id to set +// @retval none +void set_rxtx_group_id(const uint8_t i_grp_id, uint64_t * o_addr); + +// @brief Extract satellite ID field from SCOM address +// @retval uint8_t Satellite ID field value +uint8_t get_sat_id(const uint64_t i_addr); + +// @brief Extract pervasive chiplet ID from SCOM address +// @retval uint8_t Pervasive chiplet ID value +uint8_t get_chiplet_id(const uint64_t i_addr); + +// @brief Extract ring field from SCOM address +// @retval uint8_t Ring field value +uint8_t get_ring(const uint64_t i_addr); + +// @brief Extract satellite register offset field from SCOM address +// @retval uint8_t Satellite register offset field value +uint8_t get_sat_offset(const uint64_t i_addr); + +// @brief Extract the RX or TX Group ID of an indirect scom address +// @retval uint8_t Satellite register offset field value +uint8_t get_rxtx_group_id(const uint64_t i_addr); + + +#endif diff --git a/src/occ_gpe0/firdata/scom_trgt.c b/src/occ_gpe0/firdata/scom_trgt.c new file mode 100644 index 0000000..15ad3fc --- /dev/null +++ b/src/occ_gpe0/firdata/scom_trgt.c @@ -0,0 +1,180 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/scom_trgt.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +#include +#include +#include + +/*------------------------------------------------------------------------------ */ + +SCOM_Trgt_t SCOM_Trgt_getTrgt( TrgtType_t i_type, uint8_t i_procPos, + uint8_t i_procUnitPos, uint32_t i_fsiBaseAddr, + bool i_isMaster ) +{ + SCOM_Trgt_t trgt = { + .type = i_type, + .procPos = i_procPos, + .procUnitPos = i_procUnitPos, + .isMaster = i_isMaster, + .fsiBaseAddr = i_fsiBaseAddr, + }; + + if (TRGT_PROC == trgt.type) + { + trgt.procUnitPos = 0; + } + + if ( TRGT_MEMBUF == trgt.type || TRGT_MBA == trgt.type ) + { + trgt.isMaster = false; + } + + return trgt; +} + +/*------------------------------------------------------------------------------ */ + +uint8_t SCOM_Trgt_getChipPos( SCOM_Trgt_t i_trgt ) +{ + uint32_t p = 0; + + switch ( i_trgt.type ) + { + case TRGT_PROC: + case TRGT_CAPP: + case TRGT_XBUS: + case TRGT_OBUS: + case TRGT_PEC: + case TRGT_PHB: + case TRGT_EQ: + case TRGT_EX: + case TRGT_EC: + case TRGT_MCBIST: + case TRGT_MCS: + case TRGT_MCA: + p = i_trgt.procPos; + break; + + case TRGT_MEMBUF: /* TODO RTC 173614 -- with CUMULUS */ + p = (i_trgt.procPos * MAX_MEMBUF_PER_PROC) + i_trgt.procUnitPos; + break; + + case TRGT_MBA: /* TODO RTC 173614 -- with CUMULUS */ + p = (i_trgt.procPos * MAX_MEMBUF_PER_PROC) + + (i_trgt.procUnitPos / MAX_MBA_PER_MEMBUF); + break; + + default: ; + } + + return p; +} + +/*------------------------------------------------------------------------------ */ + +uint8_t SCOM_Trgt_getChipUnitPos( SCOM_Trgt_t i_trgt ) +{ + uint32_t u = 0; + + switch ( i_trgt.type ) + { + case TRGT_PROC: + case TRGT_MEMBUF: u = 0; break; + + case TRGT_CAPP: + case TRGT_XBUS: + case TRGT_OBUS: + case TRGT_PEC: + case TRGT_PHB: + case TRGT_EQ: + case TRGT_EX: + case TRGT_EC: + case TRGT_MCBIST: + case TRGT_MCS: + case TRGT_MCA: u = i_trgt.procUnitPos; break; + + case TRGT_MBA: u = i_trgt.procUnitPos % MAX_MBA_PER_MEMBUF; break; + /* TODO RTC 173614 -- with CUMULUS */ + + default: ; + } + + return u; +} + +/*------------------------------------------------------------------------------ */ + +SCOM_Trgt_t SCOM_Trgt_getParentChip( SCOM_Trgt_t i_trgt ) +{ + TrgtType_t t = TRGT_MAX; + switch ( i_trgt.type ) + { + case TRGT_PROC: + case TRGT_CAPP: + case TRGT_XBUS: + case TRGT_OBUS: + case TRGT_PEC: + case TRGT_PHB: + case TRGT_EQ: + case TRGT_EX: + case TRGT_EC: + case TRGT_MCBIST: + case TRGT_MCS: + case TRGT_MCA: t = TRGT_PROC; break; + + case TRGT_MEMBUF: + case TRGT_MBA: t = TRGT_MEMBUF; break; + + default: ; + } + + uint8_t u = 0; + switch ( i_trgt.type ) + { + case TRGT_PROC: + case TRGT_CAPP: + case TRGT_XBUS: + case TRGT_OBUS: + case TRGT_PEC: + case TRGT_PHB: + case TRGT_EQ: + case TRGT_EX: + case TRGT_EC: + case TRGT_MCBIST: + case TRGT_MCS: + case TRGT_MCA: + case TRGT_MEMBUF: u = i_trgt.procUnitPos; break; + /* TODO RTC 173614 -- with CUMULUS */ + + case TRGT_MBA: u = i_trgt.procUnitPos / MAX_MBA_PER_MEMBUF; break; + /* TODO RTC 173614 -- with CUMULUS */ + + default: ; + } + + return SCOM_Trgt_getTrgt( t, i_trgt.procPos, u, i_trgt.fsiBaseAddr, + i_trgt.isMaster ); +} + diff --git a/src/occ_gpe0/firdata/scom_trgt.h b/src/occ_gpe0/firdata/scom_trgt.h new file mode 100644 index 0000000..4ffe8b5 --- /dev/null +++ b/src/occ_gpe0/firdata/scom_trgt.h @@ -0,0 +1,89 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ/firdata/scom.H $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __scom_trgt_h +#define __scom_trgt_h + +#include +#include + +typedef struct +{ + /** See enum TrgtType_t. NOTE: This value is not consistant with Hostboot + * target types. */ + TrgtType_t type; + + /** Absolute position of the connected PROC within the node. This value + * should be consistant with the Hostboot target positions. */ + uint8_t procPos; + + /** Unit position relative to the connected PROC. This value should be + * consistant with the Hostboot target positions. */ + uint8_t procUnitPos; + + /** Indicates this target is, or is connected to, the master processor. */ + bool isMaster; + + /** This target's FSI base address. */ + uint32_t fsiBaseAddr; + +} SCOM_Trgt_t; + +/** @param i_type See enum Type. + * @param i_procPos Absolute position within the node of the connected + * PROC target. + * @param i_procUnitPos Unit position relative to the connected PROC. Will be + * explicitly set to 0 for PROC targets. + * @param i_fsiBaseAddr For EX and MCS, the FSI base address for the + * connected PROC. For MEMB and MBA, the FSI base + * address for the connected MEMB. + * @param i_isMaster True, if this target is, or is connected to, the + * master processor. False, otherwise. Will be explicitly + * set to false for MEMB and MBA targets. + * @return A SCOM_Trgt_t struct. + */ +SCOM_Trgt_t SCOM_Trgt_getTrgt( TrgtType_t i_type, uint8_t i_procPos, + uint8_t i_procUnitPos, uint32_t i_fsiBaseAddr, + bool i_isMaster ); + +/** @param i_trgt The SCOM target. + * @return This target's absolute position of the parent chip (PROC or + * MEMB) within the node. + */ +uint8_t SCOM_Trgt_getChipPos( SCOM_Trgt_t i_trgt ); + +/** @param i_trgt The SCOM target. + * @return This target's unit position relative to the parent chip. Only + * valid for EX, MCS, and MBA units. Will return 0 for PROC and + * MEMB chips. + */ +uint8_t SCOM_Trgt_getChipUnitPos( SCOM_Trgt_t i_trgt ); + +/** @param i_trgt The SCOM target. + * @return A target for the containing parent chip (PROC or MEMB). + */ +SCOM_Trgt_t SCOM_Trgt_getParentChip( SCOM_Trgt_t i_trgt ); + +#endif /* __scom_trgt_h */ diff --git a/src/occ_gpe0/firdata/scom_util.c b/src/occ_gpe0/firdata/scom_util.c new file mode 100644 index 0000000..7709017 --- /dev/null +++ b/src/occ_gpe0/firdata/scom_util.c @@ -0,0 +1,607 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/scom_util.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +/* Support for SCOM operations */ +#include +#include +#include +#include "occ_common.h" +#include "gpe_export.h" +#include +#include "scom_addr_util.h" +#include + +bool G_request_created = FALSE; +GPE_BUFFER(ipc_scom_op_t G_scom_op); +GpeRequest G_request; + +enum { + /*FSI addresses are byte offsets, so need to multiply by 4 + since each register is 4 bytes long. + prefix with 0x10xx for FSI2PIB engine offset */ + DATA0_REG = 0x1000, /* SCOM Data Register 0 (0x00) */ + DATA1_REG = 0x1004, /* SCOM Data Register 1 (0x01) */ + COMMAND_REG = 0x1008, /* SCOM Command Register (0x02) */ + ENGINE_RESET_REG = 0x1018, /* Engine Reset Register (0x06) */ + STATUS_REG = 0x101C, /* STATUS Register (0x07) */ + PIB_RESET_REG = 0x101C, /* PIB Reset Register (0x07) */ + + PIB_ABORT_BIT = 0x00100000, /* 12= PIB Abort */ + PIB_ERROR_BITS = 0x00007000, /* 17:19= PCB/PIB Errors */ +}; + +/** + * @brief Indirect SCOM Status + */ +typedef union +{ + uint64_t data64; + struct + { + uint64_t :12; /*0:11*/ + uint64_t addr:20; /*12:31*/ + uint64_t done:1; /*32*/ + uint64_t piberr:3; /*33:35*/ + uint64_t userstat:4; /*36:39*/ + uint64_t :8; /*40:47*/ + uint64_t data:16; /*48:63*/ + }; +} IndirectScom_t; + +enum { + MCS_MASK = 0xFFFFFFFF7FFFFF80, + MCS_BASEADDR = 0x0000000002011800, + MCS_DMI_BASEADDR = 0x0000000002011A00, + IND_MCS_BASEADDR = 0x8000006002011A00, + IND_MCS_DMI_BASEADDR = 0x8000006002011A3F, + MBA_MASK = 0xFFFFFFFF7FFFFC00, + MBA_BASEADDR = 0x0000000003010400, + TCM_MBA_BASEADDR = 0x0000000003010800, + IND_MBA_BASEADDR = 0x800000000301143f, +}; + +/** + * @brief Translates a relative unit address to a real physical address + * @param i_trgt Chip/unit to SCOM. + * @param i_addr Address to SCOM (the unit's 0th address for unit SCOMs). + * @param o_addr Return address. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t translate_addr( SCOM_Trgt_t i_trgt, uint64_t i_addr, uint64_t * o_addr ) +{ + #define FUNC "[translate_addr] " + + int32_t rc = SUCCESS; + uint8_t l_chip_unit_num = SCOM_Trgt_getChipUnitPos(i_trgt); + + *o_addr = i_addr; + + //The following translation logic is a copy of p9_scominfo_createChipUnitScomAddr + //function from EKB (chips/p9/common/scominfo/p9_scominfo.C) + + if(i_trgt.type == TRGT_PROC || i_trgt.type == TRGT_MEMBUF) + { + //No need to translate here. + //We already assigned i_addr to o_addr above, so just return SUCCESS. + return rc; + } + else if(i_trgt.type == TRGT_CAPP) //CAPP + { + set_chiplet_id(N0_CHIPLET_ID + (l_chip_unit_num * 2), o_addr); + } + else if(i_trgt.type == TRGT_XBUS) //XBUS + { + uint8_t l_ring_id = get_ring(i_addr) & 0xF; + if(l_ring_id <= XB_IOX_2_RING_ID && l_ring_id >= XB_IOX_0_RING_ID) + { + set_ring((XB_IOX_0_RING_ID + l_chip_unit_num) & 0xF, o_addr); + } + else if(l_ring_id <= XB_PBIOX_2_RING_ID && + l_ring_id >= XB_PBIOX_0_RING_ID) + { + set_ring((XB_PBIOX_0_RING_ID + l_chip_unit_num) & 0xF, o_addr); + } + } + else if(i_trgt.type == TRGT_OBUS) //OBUS + { + set_chiplet_id(OB0_CHIPLET_ID + l_chip_unit_num, o_addr); + } + else if(i_trgt.type == TRGT_PEC) //PEC + { + if(get_chiplet_id(i_addr) == N2_CHIPLET_ID) + { + // nest + set_ring((N2_PCIS0_0_RING_ID + l_chip_unit_num) & 0xF, o_addr); + } + else + { + // iopci / pci + set_chiplet_id(PCI0_CHIPLET_ID + l_chip_unit_num, o_addr); + } + } + else if (i_trgt.type == TRGT_PHB) //PHB + { + if(get_chiplet_id(i_addr) == N2_CHIPLET_ID) + { + // nest + if(l_chip_unit_num == 0) + { + set_ring(N2_PCIS0_0_RING_ID & 0xF, o_addr); + set_sat_id((get_sat_id(i_addr) < 4) ? 1 : 4, o_addr); + } + else + { + set_ring((N2_PCIS0_0_RING_ID + (l_chip_unit_num / 3) + 1) & 0xF, + o_addr); + set_sat_id(((get_sat_id(i_addr) < 4) ? 1 : 4) + + ((l_chip_unit_num % 2) ? 0 : 1) + + (2 * l_chip_unit_num / 5), o_addr); + } + } + else + { + // pci + if(l_chip_unit_num == 0) + { + set_chiplet_id(PCI0_CHIPLET_ID, o_addr); + set_sat_id(((get_sat_id(i_addr) < 4) ? 1 : 4), o_addr); + } + else + { + set_chiplet_id(PCI0_CHIPLET_ID + (l_chip_unit_num / 3) + 1, o_addr); + set_sat_id(((get_sat_id(i_addr) < 4) ? 1 : 4) + + ((l_chip_unit_num % 2) ? 0 : 1) + + 2 * l_chip_unit_num / 5, o_addr); + } + } + } + else if(i_trgt.type == TRGT_EX) //EX + { + if(get_chiplet_id(i_addr) <= EP05_CHIPLET_ID && + get_chiplet_id(i_addr) >= EP00_CHIPLET_ID) + { + set_chiplet_id(EP00_CHIPLET_ID + (l_chip_unit_num / 2), o_addr); + uint8_t l_ring_id = get_ring(i_addr) & 0xF; + l_ring_id = (l_ring_id - (l_ring_id % 2)) + (l_chip_unit_num % 2); + set_ring(l_ring_id & 0xF, o_addr); + } + else if(get_chiplet_id(i_addr) <= EC23_CHIPLET_ID && + get_chiplet_id(i_addr) >= EC00_CHIPLET_ID) + { + set_chiplet_id(EC00_CHIPLET_ID + + (get_chiplet_id(i_addr) % 2) + + (l_chip_unit_num * 2), o_addr); + } + } + else if(i_trgt.type == TRGT_EQ) //EQ + { + set_chiplet_id(EP00_CHIPLET_ID + l_chip_unit_num, o_addr); + } + else if(i_trgt.type == TRGT_EC) //EC + { + set_chiplet_id(EC00_CHIPLET_ID + l_chip_unit_num, o_addr); + } + else if(i_trgt.type == TRGT_MBA) //MBA + { + if( (i_addr & MBA_MASK) == MBA_BASEADDR ) + { + /* 0x00000000_03010400 MBA 0 # MBA01 */ + /* 0x00000000_03010C00 MBA 1 # MBA23 */ + if( l_chip_unit_num == 1 ) + { + *o_addr |= 0x00000800; + } + } + else if( (i_addr & MBA_MASK) == TCM_MBA_BASEADDR ) + { + /* 0x00000000_03010880 MBA 0 # Trace for MBA01 */ + /* 0x00000000_030110C0 MBA 1 # Trace for MBA23 */ + *o_addr |= (l_chip_unit_num * 0x840); + } + else if( (i_addr & MBA_MASK) == IND_MBA_BASEADDR ) + { + /* 0x00000000_03011400 MBA 0 # DPHY01 (indirect addressing) */ + /* 0x00000000_03011800 MBA 1 # DPHY23 (indirect addressing) */ + /* 0x80000000_0301143f MBA 0 # DPHY01 (indirect addressing) */ + /* 0x80000000_0301183f MBA 1 # DPHY23 (indirect addressing) */ + /* 0x80000000_0701143f MBA 0 # DPHY01 (indirect addressing) */ + /* 0x80000000_0701183f MBA 1 # DPHY23 (indirect addressing) */ + if( l_chip_unit_num == 1 ) + { + /* 030114zz->030118zz */ + *o_addr &= 0xFFFFFFFFFFFFFBFF; + *o_addr |= 0x0000000000000800; + } + } + } + else if(i_trgt.type == TRGT_MCS || //MCS + i_trgt.type == TRGT_MI) //MI TODO RTC 175488 + { + set_chiplet_id(N3_CHIPLET_ID - (2 * (l_chip_unit_num / 2)), o_addr); + set_sat_id(2 * (l_chip_unit_num % 2), o_addr); + } + else if(i_trgt.type == TRGT_MCBIST || //MCBIST + i_trgt.type == TRGT_MC) //MC TODO RTC 175488 + { + set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num, o_addr); + } + else if(i_trgt.type == TRGT_MCA) //MCA + { + if(get_chiplet_id(i_addr) == MC01_CHIPLET_ID || + get_chiplet_id(i_addr) == MC23_CHIPLET_ID) + { + set_chiplet_id(MC01_CHIPLET_ID + (l_chip_unit_num / 4), o_addr); + + if((get_ring(i_addr) & 0xf) == MC_MC01_0_RING_ID) + { + // mc + uint8_t l_sat_id = get_sat_id(i_addr); + set_sat_id((l_sat_id - (l_sat_id % 4)) + (l_chip_unit_num % 4) + , o_addr); + } + else + { + // iomc + set_ring((MC_IOM01_0_RING_ID + (l_chip_unit_num % 4)) & 0xF + , o_addr); + } + } + else + { + // mcs->mca registers + uint8_t l_mcs_unitnum = l_chip_unit_num / 2; + set_chiplet_id(N3_CHIPLET_ID - (2 * (l_mcs_unitnum / 2)) , o_addr); + set_sat_id(2 * (l_chip_unit_num % 2), o_addr); + uint8_t l_mcs_sat_offset = 0x2F & get_sat_offset(i_addr); + l_mcs_sat_offset |= (l_chip_unit_num % 2) << 4; + set_sat_offset(l_mcs_sat_offset, o_addr); + } + } + else if(i_trgt.type == TRGT_DMI) //DMI TODO RTC 175488 + { + if(get_chiplet_id(i_addr) == N3_CHIPLET_ID || get_chiplet_id(i_addr) == N1_CHIPLET_ID) + { + set_chiplet_id(N3_CHIPLET_ID - 2 * (l_chip_unit_num / 4), o_addr); + set_sat_id(2 * ((l_chip_unit_num / 2) % 2), o_addr); + uint8_t l_sat_offset = get_sat_offset(i_addr); + l_sat_offset = (l_sat_offset & 0xF) + ((2 + (l_chip_unit_num % 2)) << 4); + set_sat_offset(l_sat_offset, o_addr); + } + else if(get_chiplet_id(i_addr) == MC01_CHIPLET_ID || get_chiplet_id(i_addr) == MC23_CHIPLET_ID) + { + if(get_ring(i_addr) == P9C_MC_CHAN_RING_ID) + { + set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num / 4, o_addr); + uint8_t l_sat_id = get_sat_id(i_addr); + l_sat_id = l_sat_id & 0xC; + set_sat_id(l_sat_id + l_chip_unit_num % 4, o_addr); + } + else if(get_ring(i_addr) == P9C_MC_BIST_RING_ID) + { + set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num / 4, o_addr); + uint8_t l_sat_offset = get_sat_offset(i_addr); + l_sat_offset = (l_sat_offset & 0xF) + ((l_chip_unit_num % 2) << 4); + set_sat_offset(l_sat_offset, o_addr); + } + else if(get_ring(i_addr) == P9C_MC_IO_RING_ID) + { + set_chiplet_id(MC01_CHIPLET_ID + l_chip_unit_num / 4, o_addr); + uint8_t l_rxtx_group = get_rxtx_group_id(i_addr); + l_rxtx_group = l_rxtx_group & 0xF0; + + switch(l_chip_unit_num % 4) + { + case 0: + l_rxtx_group += 3; + break; + case 1: + l_rxtx_group += 2; + break; + case 2: + l_rxtx_group += 0; + break; + case 3: + l_rxtx_group += 1; + break; + default: + break; + } + set_rxtx_group_id(l_rxtx_group, o_addr); + } + } + } + else + { + TRAC_ERR( FUNC"unsupported unit type %d", i_trgt.type ); + rc = FAIL; + } + + return rc; + + #undef FUNC +} + +/** + * @brief Performs a getscom operation with no address translation. + * @param i_chip Chip to SCOM. + * @param i_addr Address to SCOM. + * @param o_val Returned value. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t getscomraw( SCOM_Trgt_t i_chip, uint32_t i_addr, uint64_t * o_val ) +{ + int32_t l_rc = SUCCESS; + + //Use SBE FIFO if it's a slave proc + if(!i_chip.isMaster) + { + return getFifoScom(&i_chip, i_addr, o_val); + } + + if(!G_request_created) //Only need to create request once + { + l_rc = gpe_request_create(&G_request, //Request + &G_async_gpe_queue0, //Queue + IPC_ST_SCOM_OPERATION, //Function ID + &G_scom_op, //GPE arguments + SSX_SECONDS(5), //Timeout + NULL, //Callback function + NULL, //Callback args + ASYNC_REQUEST_BLOCKING); //Options + if(l_rc) + { + TRAC_ERR("getscomraw: failed to create gpe request, rc=0x%08X", l_rc); + return l_rc; + } + else + { + G_request_created = TRUE; + } + } + + //Pack in the request data + G_scom_op.read = TRUE; + G_scom_op.addr = i_addr; + + l_rc = gpe_request_schedule(&G_request); + if(l_rc) + { + TRAC_ERR("getscomraw: failed to schedule gpe request, rc=0x%08X", l_rc); + return l_rc; + } + + //Since it's a blocking request, it should be completed by the time we + //get here. If it's not, then a timeout has occurred. + if(G_request.request.completion_state == ASYNC_REQUEST_STATE_COMPLETE) + { + *o_val = G_scom_op.data; + } + else + { + *o_val = 0; + l_rc = FAIL; + } + + return l_rc; +} + +/** + * @brief Perform a putscom operation with no address translation. + * @param i_chip Chip to SCOM. + * @param i_addr Address to SCOM. + * @param i_val Value to write. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t putscomraw( SCOM_Trgt_t i_chip, uint32_t i_addr, uint64_t i_val ) +{ + int32_t l_rc = SUCCESS; + + //Use SBE FIFO if it's a slave proc + if(!i_chip.isMaster) + { + return putFifoScom(&i_chip, i_addr, i_val); + } + + if(!G_request_created) //Only need to create request once + { + l_rc = gpe_request_create(&G_request, //Request + &G_async_gpe_queue0, //Queue + IPC_ST_SCOM_OPERATION, //Function ID + &G_scom_op, //GPE arguments + SSX_SECONDS(5), //Timeout + NULL, //Callback function + NULL, //Callback args + ASYNC_REQUEST_BLOCKING); //Options + if(l_rc) + { + TRAC_ERR("putscomraw gpe request create failed, rc = 0x%08x", l_rc); + return l_rc; + } + else + { + G_request_created = TRUE; + } + } + + //Pack in the request data + G_scom_op.read = FALSE; + G_scom_op.addr = i_addr; + G_scom_op.data = i_val; + + l_rc = gpe_request_schedule(&G_request); + if(l_rc) + { + TRAC_ERR("putscomraw gpe request schedule failed, rc=0x%08X", l_rc); + return l_rc; + } + + //It's a blocking request, so if the request hasn't been completed by this + //time, then a timeout has occurred. + if(G_request.request.completion_state != ASYNC_REQUEST_STATE_COMPLETE) + { + TRAC_ERR("putscomraw gpe request failed to complete, rc = 0x%08x", l_rc); + l_rc = FAIL; + } + + return l_rc; +} + +/** + * @brief Executes standard getscom. + * @param i_trgt Chip to SCOM. + * @param i_addr Address to SCOM. + * @param o_val Returned value. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t SCOM_getScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t * o_val ) +{ + int32_t rc = SUCCESS; + + /* Get the parent chip. */ + SCOM_Trgt_t chip_targ = SCOM_Trgt_getParentChip(i_trgt); + + /* Get the address relative to the parent chip. */ + uint64_t trans_addr; + rc = translate_addr( i_trgt, i_addr, &trans_addr ); + if ( SUCCESS == rc ) + { + /* Do the SCOM. */ + rc = getscomraw( chip_targ, trans_addr, o_val ); + } + + return rc; +} + +/** + * @brief Execute indirect getscom. + * @param i_trgt Chip to SCOM. + * @param i_addr Address to SCOM. + * @param o_val Returned value. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. + */ +int32_t SCOM_getIdScom( SCOM_Trgt_t i_trgt, uint64_t i_addr, uint32_t * o_val ) +{ + #define FUNC "[SCOM_getIdScom] " + + int32_t rc = SUCCESS; + + *o_val = 0; + + /* Get the parent chip */ + SCOM_Trgt_t chip_targ = SCOM_Trgt_getParentChip(i_trgt); + + /* Get the address relative to the parent chip. */ + uint64_t trans_addr; + rc = translate_addr( i_trgt, i_addr, &trans_addr ); + if ( SUCCESS != rc ) return rc; + + /* An indirect SCOM is performed by putting the top of the 64-bit address + * into the first data word of the SCOM */ + + /* Zero out the indirect address from the buffer. */ + /* bit 0-31 - indirect area. */ + /* bit 32 - always 0 */ + /* bit 33-47 - bcast/chipletID/port */ + /* bit 48-63 - local addr */ + uint32_t phys_addr = trans_addr & 0x000000007FFFFFFF; + + /* To do a read we need to do a write first. */ + + /* Start with the 20bit indirect address */ + uint64_t data_buffer = trans_addr & 0x001FFFFF00000000; + /* Turn the read bit on. */ + data_buffer |= 0x8000000000000000; + + /* perform write before the read with the new */ + rc = putscomraw( i_trgt, phys_addr, data_buffer ); + if ( SUCCESS != rc ) return rc; + + // Loop on read until we see done, error, or we timeout + IndirectScom_t scomout; + uint64_t elapsed_indScom_time_ns = 0; + do + { + /* Now perform the op requested using the passed in */ + /* IO_Buffer to pass the read data back to caller. */ + rc = getscomraw( chip_targ, phys_addr, &(scomout.data64) ); + if ( SUCCESS != rc ) return rc; + + /* Check for PIB error. */ + if ( scomout.piberr ) + { + TRAC_ERR( FUNC"ID SCOM PIB error: phys_addr=0x%08x " + "trans_addr=0x%08x%08x", phys_addr, + (uint32_t)(trans_addr >> 32), (uint32_t)trans_addr ); + return FAIL; + } + + /* Jump out when done. */ + if ( scomout.done ) break; + + sleep( 10000 ); /* sleep for 10,000 ns */ + elapsed_indScom_time_ns += 10000; + + } while ( elapsed_indScom_time_ns <= 100000 ); /* wait for .1ms */ + + if ( !scomout.done ) + { + TRAC_ERR( FUNC"ID SCOM loop timeout exceeded: phys_addr=0x%08x " + "trans_addr=0x%08x%08x", phys_addr, + (uint32_t)(trans_addr >> 32), (uint32_t)trans_addr ); + return FAIL; + } + + *o_val = scomout.data; + + return rc; + + #undef FUNC +} + +/** + * @brief Executes standard putscom. + * @param i_trgt Chip to SCOM. + * @param i_addr Address to SCOM. + * @param i_val Value to put. + * @return Non-SUCCESS if an internal function fails. SUCCESS otherwise. +*/ +int32_t SCOM_putScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t i_val ) +{ + int32_t l_rc = SUCCESS; + + /* Get the parent chip. */ + SCOM_Trgt_t l_chip_targ = SCOM_Trgt_getParentChip(i_trgt); + + /* Get the address relative to the parent chip. */ + uint64_t l_trans_addr; + l_rc = translate_addr( i_trgt, i_addr, &l_trans_addr ); + if ( SUCCESS == l_rc ) + { + /* Do the SCOM. */ + l_rc = putscomraw( l_chip_targ, l_trans_addr, i_val ); + } + + return l_rc; +} diff --git a/src/occ_gpe0/firdata/scom_util.h b/src/occ_gpe0/firdata/scom_util.h new file mode 100644 index 0000000..1ec7fd2 --- /dev/null +++ b/src/occ_gpe0/firdata/scom_util.h @@ -0,0 +1,98 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/firdata/scom_util.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,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 */ + +/* Interfaces to read SCOM registers */ + +/*#include */ +#include +#include + +#define SCOMFAIL 0xDEADBEEF + +typedef enum +{ + N0_CHIPLET_ID = 0x02, ///< Nest0 (North) chiplet + N1_CHIPLET_ID = 0x03, ///< Nest1 (East) chiplet + N2_CHIPLET_ID = 0x04, ///< Nest2 (South) chiplet + N3_CHIPLET_ID = 0x05, ///< Nest3 (West) chiplet + MC01_CHIPLET_ID = 0x07, ///< MC01 (West) chiplet + MC23_CHIPLET_ID = 0x08, ///< MC23 (East) chiplet + OB0_CHIPLET_ID = 0x09, ///< OBus0 chiplet + PCI0_CHIPLET_ID = 0x0D, ///< PCIe0 chiplet + EP00_CHIPLET_ID = 0x10, ///< Quad0 chiplet (EX0/1) + EP05_CHIPLET_ID = 0x15, ///< Quad5 chiplet (EX10/11) + EC00_CHIPLET_ID = 0x20, ///< Core0 chiplet (Quad0, EX0, C0) + EC23_CHIPLET_ID = 0x37 ///< Core23 chiplet (Quad5, EX11, C1) +} p9_chiplet_id_t; + +typedef enum +{ + MC_MC01_0_RING_ID = 0x2, ///< MC01_0 / MC23_0 + MC_IOM01_0_RING_ID = 0x4, ///< IOM01_0 / IOM45_0 +} p9_mc_ring_id_t; + +typedef enum +{ + XB_IOX_0_RING_ID = 0x3, ///< IOX_0 + XB_IOX_2_RING_ID = 0x5, ///< IOX_2 + XB_PBIOX_0_RING_ID = 0x6, ///< PBIOX_0 + XB_PBIOX_2_RING_ID = 0x8 ///< PBIOX_2 +} p9_xb_ring_id_t; + +typedef enum +{ + P9C_MC_CHAN_RING_ID = 0x2, + P9C_MC_IO_RING_ID = 0x4, + P9C_MC_BIST_RING_ID = 0x8 +} p9c_mc_ring_id_t; + +typedef enum +{ + N2_PCIS0_0_RING_ID = 0x3, ///< PCIS0_0 +} p9_n2_ring_id_t; + +/** @brief Performs a hardware scom on a regular register. + * @param i_trgt The SCOM target. + * @param i_addr 32-bit SCOM address. + * @param o_val 64-bit returned value. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +int32_t SCOM_getScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t * o_val ); + +/** @brief Performs a hardware put scom on a regular register. + * @param i_trgt The SCOM target. + * @param i_addr 32-bit SCOM address. + * @param i_val 64-bit value to write to the address. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. +*/ +int32_t SCOM_putScom( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint64_t i_val ); + +/** @brief Performs a hardware scom on an indirect-SCOM register. + * @param i_trgt The SCOM target. + * @param i_addr 64-bit SCOM address. + * @param o_val 32-bit returned value. + * @return Non-SUCCESS if the SCOM fails. SUCCESS otherwise. + */ +int32_t SCOM_getIdScom( SCOM_Trgt_t i_trgt, uint64_t i_addr, uint32_t * o_val ); -- cgit v1.2.1