diff options
Diffstat (limited to 'src/occ_gpe1/gpe1_dimm_reset.c')
-rw-r--r-- | src/occ_gpe1/gpe1_dimm_reset.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/occ_gpe1/gpe1_dimm_reset.c b/src/occ_gpe1/gpe1_dimm_reset.c new file mode 100644 index 0000000..9963eec --- /dev/null +++ b/src/occ_gpe1/gpe1_dimm_reset.c @@ -0,0 +1,223 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_gpe1/gpe1_dimm_reset.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 */ + +/// \file gpe1_dimm_reset.c +/// \brief Functions to handle resetting the I2C engine +/// + +//#define GPE1_DEBUG +#include "pk.h" +#include "ipc_api.h" +#include "ppe42_scom.h" +#include "ipc_async_cmd.h" +#include "gpe1.h" +#include "gpe1_dimm.h" + + +/* + * Function Specifications: + * + * Name: dimm_reset_master + * + * Description: Reset the I2C master + * + * Inputs: cmd is a pointer to IPC msg's cmd and cmd_data struct + * + * Outputs: error: sets rc, address, and ffdc in the cmd_data's + * GpeErrorStruct + * + * End Function Specification + */ +void dimm_reset_master(ipc_msg_t* cmd, void* arg) +{ + // Note: arg was set to 0 in ipc func table (ipc_func_tables.c), so don't use it. + // the ipc arguments passed through the ipc_msg_t structure, has a pointer + // to the G_gpe_start_pwr_meas_read_args struct. + + int rc; + uint32_t scomAddr; + uint64_t regValue; // a pointer to hold the putscom_abs register value + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + dimm_sm_args_t *args = (dimm_sm_args_t*)async_cmd->cmd_data; + + // Reset I2C Master + scomAddr = I2C_IMM_RESET_I2C | SCOM_ENGINE_OFFSET(args->i2cEngine); + regValue = 0x0000000000000000; + rc = putscom_abs(scomAddr, regValue); + if(rc) + { + PK_TRACE("dimm_reset_master: I2C_IMM_RESET_I2C putscom 0x%08X->0x%08X%08X FAILED. rc = 0x%08x", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue), rc); + gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_PUT_FAILED, rc); + } + else + { + GPE1_DIMM_DBG("dimm_reset_master: putscom(0x%08X,0x%08X%08X) SUCCESS - IMM_RESET_I2C", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue)); + } + + // Force reset of Port_busy_register + scomAddr = I2C_BUSY_REGISTER | SCOM_ENGINE_OFFSET(args->i2cEngine); + regValue = 0x8000000000000000; + rc = putscom_abs(scomAddr, regValue); + if(rc) + { + PK_TRACE("dimm_reset_master: I2C_BUSY_REGISTER putscom 0x%08X->0x%08X%08X FAILED. rc = 0x%08x", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue), rc); + gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_PUT_FAILED, rc); + } + else + { + GPE1_DIMM_DBG("dimm_reset_master: putscom(0x%08X,0x%08X%08X) SUCCESS - I2C_BUSY_REGISTER", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue)); + } + +} // end dimm_reset_master() + + +/* + * Function Specifications: + * + * Name: dimm_reset_slave + * + * Description: Start reset of I2C slave + * + * Inputs: cmd is a pointer to IPC msg's cmd and cmd_data struct + * + * Outputs: error: sets rc, address, and ffdc in the cmd_data's + * GpeErrorStruct + * + * End Function Specification + */ + +void dimm_reset_slave(ipc_msg_t* cmd, void* arg) +{ + int rc; + uint32_t scomAddr; + uint64_t regValue; // a pointer to hold the putscom_abs register value + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + dimm_sm_args_t *args = (dimm_sm_args_t*)async_cmd->cmd_data; + + // Write I2C mode register with the speed/port + scomAddr = I2C_MODE_REG | SCOM_ENGINE_OFFSET(args->i2cEngine); + regValue = 0x0177000000000000; + if ((args->i2cPort > 0) && (args->i2cPort < 6)) + { + regValue |= ((uint64_t)args->i2cPort << 42); + } + rc = putscom_abs(scomAddr, regValue); + if(rc) + { + PK_TRACE("dimm_reset_slave: I2C_MODE_REG putscom 0x%08X->0x%08X%08X FAILED. rc = 0x%08x", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue), rc); + gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_PUT_FAILED, rc); + } + else + { + GPE1_DIMM_DBG("dimm_reset_slave: putscom(0x%08X,0x%08X%08X) SUCCESS - MODE", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue)); + + // Force a stop-condition to the I2C slave + scomAddr = I2C_COMMAND_REG | SCOM_ENGINE_OFFSET(args->i2cEngine); + // stop bit + regValue = 0x1000000000000000; + rc = putscom_abs(scomAddr, regValue); + if(rc) + { + PK_TRACE("dimm_reset_slave: I2C_COMMAND_REG putscom 0x%08X->0x%08X%08X FAILED. rc = 0x%08x", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue), rc); + gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_PUT_FAILED, rc); + } + else + { + GPE1_DIMM_DBG("dimm_reset_slave: putscom(0x%08X,0x%08X%08X) SUCCESS - COMMAND (stop)", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue)); + } + } + +} // end dimm_reset_slave() + + +/* + * Function Specifications: + * + * Name: dimm_reset_slave_status + * + * Description: Read I2C status register to ensure slave has been reset + * + * Inputs: cmd is a pointer to IPC msg's cmd and cmd_data struct + * + * Outputs: error: sets rc, address, and ffdc in the cmd_data's + * GpeErrorStruct + * + * End Function Specification + */ +void dimm_reset_slave_status(ipc_msg_t* cmd, void* arg) +{ + int rc; + uint32_t scomAddr; + uint64_t regValue; // a pointer to hold the putscom_abs register value + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + dimm_sm_args_t *args = (dimm_sm_args_t*)async_cmd->cmd_data; + + // Read I2C status register + scomAddr = I2C_STATUS_REG | SCOM_ENGINE_OFFSET(args->i2cEngine); + rc = getscom_abs(scomAddr, ®Value); + if(rc) + { + PK_TRACE("dimm_reset_slave_status: I2C_STATUS_REG getscom 0x%08X FAILED. rc = 0x%08x - STATUS #1", + scomAddr, rc); + gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_GET_FAILED, rc); + } + else + { + GPE1_DIMM_DBG("dimm_reset_slave_status: getscom(0x%08X) returned 0x%08X%08X) - STATUS #1", + scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue)); + + // Wait until command complete is set + if (regValue & STATUS_COMPLETE_MASK) + { + // Reset completed + args->error.rc = GPE_RC_SUCCESS; + PK_TRACE("dimm_reset_slave_status: I2C Slave Port %d Reset completed", args->i2cPort); + + if ((regValue & STATUS_ERROR_OR_COMPLETE_MASK) != STATUS_COMPLETE_MASK) + { + // I2C errors found + PK_TRACE("dimm_reset_slave_status: I2C errors in status register: %08X%08X", + WORD_HIGH(regValue), WORD_LOW(regValue)); + // Continue with other slave resets and may trigger another reset... + } + } + else + { + // reset not complete yet... + args->error.rc = GPE_RC_NOT_COMPLETE; + } + } + +} // end dimm_reset_slave_status() + + |