summaryrefslogtreecommitdiffstats
path: root/src/occ_gpe1
diff options
context:
space:
mode:
authorChris Cain <cjcain@us.ibm.com>2015-11-19 12:27:03 -0600
committerWilliam A. Bryan <wilbryan@us.ibm.com>2016-01-27 16:27:07 -0600
commit1cdc7f74cf7303b2d2e7e172b0e269928def09de (patch)
treebc88add88943f8389626a04c5219d0efc3d08f17 /src/occ_gpe1
parent476a284b52f50c1d0f5a8fc637cc28a22c714185 (diff)
downloadtalos-occ-1cdc7f74cf7303b2d2e7e172b0e269928def09de.tar.gz
talos-occ-1cdc7f74cf7303b2d2e7e172b0e269928def09de.zip
Implement code to read DIMM temperatures
Change-Id: I98fc83ab1c78bd40241fe6e47a9ddeae24f78c38 RTC: 140093 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22770 Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Tested-by: FSP CI Jenkins Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Christopher Cain <cjcain@us.ibm.com>
Diffstat (limited to 'src/occ_gpe1')
-rwxr-xr-xsrc/occ_gpe1/gpe1.h76
-rwxr-xr-xsrc/occ_gpe1/gpe1_dimm.h (renamed from src/occ_gpe1/gpe_export.h)53
-rw-r--r--src/occ_gpe1/gpe1_dimm_read.c511
-rw-r--r--src/occ_gpe1/gpe1_dimm_reset.c223
-rw-r--r--src/occ_gpe1/gpe1_main.c6
-rw-r--r--src/occ_gpe1/ipc_func_tables.c4
-rw-r--r--src/occ_gpe1/topfiles.mk2
7 files changed, 853 insertions, 22 deletions
diff --git a/src/occ_gpe1/gpe1.h b/src/occ_gpe1/gpe1.h
new file mode 100755
index 0000000..af26829
--- /dev/null
+++ b/src/occ_gpe1/gpe1.h
@@ -0,0 +1,76 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/gpe/gpe1.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 _GPE1_H
+#define _GPE1_H
+
+#include "gpe_export.h"
+
+
+// I2C SCOM Addresses:
+// (There are unique constants/addresses per engine, but to make the calls generic,
+// these constants are defined instead of using the base constants)
+#define PIB_BASE 0x000A0000
+// Engine B 0x00A0000
+// Engine C 0x00A1000
+// Engine D 0x00A2000
+// Engine E 0x00A3000
+#define SCOM_ENGINE_OFFSET(engine) (engine << 12)
+#define I2C_FIFO1_REG_READ 0x000A0004
+#define I2C_COMMAND_REG 0x000A0005
+#define I2C_MODE_REG 0x000A0006
+#define I2C_INTERRUPT_MASK_REG 0x000A0008
+#define I2C_STATUS_REG 0x000A000B // read
+#define I2C_IMM_RESET_I2C 0x000A000B // write
+#define I2C_BUSY_REGISTER 0x000A000E
+#define I2C_FIFO4_REG_READ 0x000A0012
+
+
+// I2C Status Reigster masks
+#define STATUS_ERROR_MASK 0xFE80330000000000
+#define STATUS_ERROR_OR_COMPLETE_MASK 0xFF80330000000000
+#define STATUS_COMPLETE_MASK 0x0100000000000000
+#define PEEK_ERROR_MASK 0x00000000FC000000
+#define PEEK_MORE_DATA 0x0000000002000000
+
+
+// Debug trace
+#ifdef GPE1_DEBUG
+ #define GPE1_DIMM_DBG(frmt,args...) \
+ PK_TRACE(frmt,##args)
+ #define GPE1_DIMM_DBG_HEXDUMP(data, len, string) \
+ PK_TRACE_BIN(data, len, string)
+#else
+ #define GPE1_DIMM_DBG(frmt,args...)
+ #define GPE1_DIMM_DBG_HEXDUMP(data, len, string)
+#endif
+
+
+void gpe_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc);
+
+void gpe_dimm_sm(ipc_msg_t* cmd, void* arg);
+
+
+#endif //_GPE1_H
diff --git a/src/occ_gpe1/gpe_export.h b/src/occ_gpe1/gpe1_dimm.h
index 84184e7..c3249c6 100755
--- a/src/occ_gpe1/gpe_export.h
+++ b/src/occ_gpe1/gpe1_dimm.h
@@ -1,7 +1,7 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
-/* $Source: src/occ_405/gpe/gpe_export.h $ */
+/* $Source: src/occ_405/gpe/gpe1_dimm.h $ */
/* */
/* OpenPOWER OnChipController Project */
/* */
@@ -23,19 +23,38 @@
/* */
/* IBM_PROLOG_END_TAG */
-#ifndef _GPE_EXPORT_H
-#define _GPE_EXPORT_H
-
-typedef struct {
- union
- {
- struct {
- uint32_t rc;
- uint32_t addr;
- };
- uint64_t error;
- };
- uint64_t ffdc;
-} GpeErrorStruct; // Same for every GPE program
-
-#endif //_GPE_EXPORT_H
+#ifndef _GPE1_DIMM_H
+#define _GPE1_DIMM_H
+
+#include "gpe_export.h"
+
+#define PIB_BASE 0x000A0000
+// Engine B 0x00A0000
+// Engine C 0x00A1000
+// Engine D 0x00A2000
+// Engine E 0x00A3000
+#define I2C_FIFO1_REG_READ 0x000A0004
+#define I2C_COMMAND_REG 0x000A0005
+#define I2C_MODE_REG 0x000A0006
+#define I2C_INTERRUPT_MASK_REG 0x000A0008
+#define I2C_STATUS_REG 0x000A000B // read
+#define I2C_IMM_RESET_I2C 0x000A000B // write
+#define I2C_BUSY_REGISTER 0x000A000E
+#define I2C_FIFO4_REG_READ 0x000A0012
+
+#define SCOM_ENGINE_OFFSET(engine) (engine << 12)
+
+// I2C Status Reigster masks
+#define STATUS_ERROR_MASK 0xFE80330000000000
+#define STATUS_ERROR_OR_COMPLETE_MASK 0xFF80330000000000
+#define STATUS_COMPLETE_MASK 0x0100000000000000
+#define PEEK_ERROR_MASK 0x00000000FC000000
+#define PEEK_MORE_DATA 0x0000000002000000
+
+
+void dimm_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc);
+
+void gpe_dimm_sm(ipc_msg_t* cmd, void* arg);
+
+
+#endif //_GPE1_DIMM_H
diff --git a/src/occ_gpe1/gpe1_dimm_read.c b/src/occ_gpe1/gpe1_dimm_read.c
new file mode 100644
index 0000000..be19506
--- /dev/null
+++ b/src/occ_gpe1/gpe1_dimm_read.c
@@ -0,0 +1,511 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe1/gpe1_dimm_read.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_read.c
+/// \brief Functions to handle reading the DIMM temperatures
+///
+
+//#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"
+
+
+void dimm_write_int_mask(ipc_msg_t* cmd, void* arg);
+void dimm_write_mode(ipc_msg_t* cmd, void* arg);
+void dimm_write_ts_addr(ipc_msg_t* cmd, void* arg);
+void dimm_initiate_read(ipc_msg_t* cmd, void* arg);
+void dimm_read_temp(ipc_msg_t* cmd, void* arg);
+// from gpe1_dimm_reset.c
+void dimm_reset_master(ipc_msg_t* cmd, void* arg);
+void dimm_reset_slave(ipc_msg_t* cmd, void* arg);
+void dimm_reset_slave_status(ipc_msg_t* cmd, void* arg);
+
+
+/*
+ * Function Specification
+ *
+ * Name: gpe_set_ffdc
+ *
+ * Description: Fills up the error struct with the given data.
+ *
+ * End Function Specification
+ */
+void gpe_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc)
+{
+
+ o_error->addr = i_addr;
+ //Return codes defined in gpe_err.h
+ o_error->rc = i_rc;
+ o_error->ffdc = i_ffdc;
+}
+
+
+/*
+ * Function Specifications:
+ *
+ * Name: gpe_dimm_sm
+ *
+ * Description: DIMM I2C State Machine handler in the GPE
+ *
+ * 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 gpe_dimm_sm(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;
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd;
+ dimm_sm_args_t *args = (dimm_sm_args_t*)async_cmd->cmd_data;
+
+ // clear error
+ args->error.error = 0;
+ args->error.ffdc = 0;
+
+ switch(args->state)
+ {
+ case DIMM_STATE_INIT:
+ dimm_write_int_mask(cmd, arg);
+ break;
+
+ // Read DIMM Temperature States
+
+ case DIMM_STATE_WRITE_MODE:
+ dimm_write_mode(cmd, arg);
+ break;
+
+ case DIMM_STATE_WRITE_ADDR:
+ dimm_write_ts_addr(cmd, arg);
+ break;
+
+ case DIMM_STATE_INITIATE_READ:
+ dimm_initiate_read(cmd, arg);
+ break;
+
+ case DIMM_STATE_READ_TEMP:
+ dimm_read_temp(cmd, arg);
+ break;
+
+ // I2C Reset States
+
+ case DIMM_STATE_RESET_MASTER:
+ dimm_reset_master(cmd, arg);
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P0:
+ case DIMM_STATE_RESET_SLAVE_P1:
+ dimm_reset_slave(cmd, arg);
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P0_COMPLETE:
+ case DIMM_STATE_RESET_SLAVE_P1_COMPLETE:
+ dimm_reset_slave_status(cmd, arg);
+ break;
+
+ default:
+ PK_TRACE("gpe_dimm_sm: Invalid state (0x%02X) received!", args->state);
+ args->error.rc = 0;
+ gpe_set_ffdc(&(args->error), 0, GPE_RC_INVALID_STATE, args->state);
+ break;
+ }
+
+ // Send back IPC response of success (IPC operation itself succeeded)
+ // (if any operation failed, the error (rc/ffdc) will be non-zero
+ // and can be handled by the 405)
+ rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ if(rc)
+ {
+ PK_TRACE("gpe_dimm_sm: Failed to send response back. Halting GPE1", rc);
+ gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
+ pk_halt();
+ }
+
+} // end gpe_dimm_sm()
+
+
+/*
+ * Function Specifications:
+ *
+ * Name: dimm_write_int_mask
+ *
+ * Description: Write the I2C interrupt mask and read I2C status register
+ *
+ * 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_write_int_mask(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;
+
+ scomAddr = I2C_INTERRUPT_MASK_REG | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ // Enable the following bit in the interrupt mask:
+ // invalid command, LBUS parity, back end overrun, back end access,
+ // arbitration lost, nack received, data request, command complete,
+ // stop, i2c busy
+ regValue = 0x0000FFC000000000;
+ rc = putscom_abs(scomAddr, regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_write_int_mask: I2C_INTERRUPT_MASK_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_write_int_mask: putscom(0x%08X,0x%08X%08X) SUCCESS - INT MASK",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ }
+
+ // READ I2C STATUS REGISTER
+ scomAddr = I2C_STATUS_REG | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ rc = getscom_abs(scomAddr, &regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_write_int_mask: I2C_STATUS_REG getscom 0x%08X FAILED. rc = 0x%08x - STATUS",
+ scomAddr, rc);
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_GET_FAILED, rc);
+ }
+ else
+ {
+ GPE1_DIMM_DBG("dimm_write_int_mask: getscom(0x%08X) returned 0x%08X%08X) - STATUS #1",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ // max_num_of_ports (bits 9:15)
+ args->maxPorts = (regValue >> 48) & 0x7F;
+ PK_TRACE("dimm_write_int_mask: maxPorts = %d", args->maxPorts);
+ }
+
+} // end dimm_write_int_mask()
+
+
+/*
+ * Function Specifications:
+ *
+ * Name: dimm_write_mode
+ *
+ * Description: Write the I2C mode register (set speed and port)
+ *
+ * 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_write_mode(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;
+
+ // MODE_REGISTER
+ 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_write_mode: 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_write_mode: putscom(0x%08X,0x%08X%08X) SUCCESS - MODE",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ }
+
+} // end dimm_write_mode()
+
+
+/*
+ * Function Specifications:
+ *
+ * Name: dimm_write_ts_addr
+ *
+ * Description: Write the Temperature Sensor address to I2C
+ *
+ * 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_write_ts_addr(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 command register with a 1 byte write
+ scomAddr = I2C_COMMAND_REG | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ // start+address + slave_address, rw=0=write, length=1, i2c address
+ regValue = 0xC000000100000000 | ((uint64_t)args->i2cAddr << 48);
+ rc = putscom_abs(scomAddr, regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_write_ts_addr: 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_write_ts_addr: putscom(0x%08X,0x%08X%08X) SUCCESS - COMMAND (write)",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+
+ // Write the Temperature Sensor address to the FIFO register
+ scomAddr = I2C_FIFO1_REG_READ | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ // 0x05 = temperature value
+ regValue = 0x0500000000000000;
+ rc = putscom_abs(scomAddr, regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_write_ts_addr: I2C_FIFO_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_write_ts_addr: putscom(0x%08X,0x%08X%08X) SUCCESS - FIFO",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ }
+ }
+
+} // end dimm_write_ts_addr()
+
+
+/*
+ * Function Specifications:
+ *
+ * Name: dimm_initiate_read
+ *
+ * Description: Initiate the read of the temperature sensor
+ *
+ * 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_initiate_read(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;
+
+ // Default the rc to NOT_COMPLETE (meaning the read was not initiated)
+ args->error.rc = GPE_RC_NOT_COMPLETE;
+
+ // Read the I2c Status Register to ensure the TS address was written successfully
+ scomAddr = I2C_STATUS_REG | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ rc = getscom_abs(scomAddr, &regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_initiate_read: I2C_STATUS_REG getscom 0x%08X FAILED. rc = 0x%08x",
+ scomAddr, rc);
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_GET_FAILED, rc);
+ }
+ else
+ {
+ GPE1_DIMM_DBG("dimm_initiate_read: getscom(0x%08X) returned 0x%08X%08X - STATUS",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+
+ if ((regValue & STATUS_ERROR_OR_COMPLETE_MASK) == STATUS_COMPLETE_MASK)
+ {
+ // Status register indicates no errors and last command completed.
+ // Write the I2C command register with a 2 byte read request
+ scomAddr = I2C_COMMAND_REG | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ // start+address+stop + slave_address, rw=1=read, length=2
+ regValue = 0xD001000200000000;
+ regValue |= ((uint64_t)args->i2cAddr << 48);
+ rc = putscom_abs(scomAddr, regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_initiate_read: 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
+ {
+ // The read command has been started, return success
+ GPE1_DIMM_DBG("dimm_initiate_read: putscom(0x%08X,0x%08X%08X) SUCCESS - COMMAND (read)",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ args->error.error = 0;
+ args->error.rc = GPE_RC_SUCCESS;
+ args->error.ffdc = 0;
+ }
+ }
+ else
+ {
+ if ((regValue & STATUS_ERROR_OR_COMPLETE_MASK) != 0)
+ {
+ // I2C error was found
+ PK_TRACE("dimm_initiate_read: Error in status register: 0x%08X%08X",
+ WORD_HIGH(regValue), WORD_LOW(regValue));
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_I2C_ERROR, regValue);
+ }
+ else
+ {
+ // Last command (write TS address) has not completed yet
+ PK_TRACE("dimm_initiate_read: last command not complete yet...");
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_NOT_COMPLETE, regValue);
+ }
+ // else, not complete yet
+ }
+ }
+
+} // end dimm_initiate_read()
+
+
+/*
+ * Function Specifications:
+ *
+ * Name: dimm_read_temp
+ *
+ * Description: Read the temperature sensor value
+ *
+ * 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_read_temp(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;
+
+ // Default the rc to NOT_COMPLETE (meaning the read has not completed)
+ args->error.rc = GPE_RC_NOT_COMPLETE;
+
+ // Read the I2C status register
+ scomAddr = I2C_STATUS_REG | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ rc = getscom_abs(scomAddr, &regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_read_temp: 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_read_temp: getscom(0x%08X) returned 0x%08X%08X) - STATUS #1",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+
+ uint8_t fifoLength = (regValue >> 32) & 0xFF;
+ if ((regValue & STATUS_ERROR_MASK) != 0)
+ {
+ // I2C error was found
+ PK_TRACE("dimm_read_temp: Error in status register: 0x%08X%08X",
+ WORD_HIGH(regValue), WORD_LOW(regValue));
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_I2C_ERROR, regValue);
+ }
+ else
+ {
+ // Need to wait until both bytes are available
+ if (fifoLength >= 2)
+ {
+ // Read the sensor value from the FIFO4 register
+ scomAddr = I2C_FIFO4_REG_READ | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ rc = getscom_abs(scomAddr, &regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_read_temp: I2C_FIFO4_REG getscom 0x%08X FAILED. rc = 0x%08x",
+ scomAddr, rc);
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_GET_FAILED, rc);
+ }
+ else
+ {
+ GPE1_DIMM_DBG("dimm_read_temp: getscom(0x%08X) returned 0x%08X%08X) - FIFO4",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ // Temperature is in bits 4-11
+ args->temp = (regValue >> 52) & 0xFF;
+ args->error.error = 0;
+ args->error.rc = GPE_RC_SUCCESS;
+ args->error.ffdc = 0;
+ PK_TRACE("dimm_read_temp: DIMM%04X temperature=%dC",
+ (args->i2cPort<<8)|args->dimm, args->temp);
+
+ // Check for operation complete bit
+ // (operation complete bit will not get set until all
+ // data has been read from the FIFO.)
+ if (regValue & PEEK_ERROR_MASK)
+ {
+ // I2C error was found
+ PK_TRACE("dimm_read_temp: Error in FIFO4 peek data: 0x%08X%08X",
+ WORD_HIGH(regValue), WORD_LOW(regValue));
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_I2C_ERROR, regValue);
+ }
+ else if (regValue & PEEK_MORE_DATA)
+ {
+ // The data_request bit is non-zero, but no more data is needed!
+ PK_TRACE("dimm_read_temp: Got data, but more data needs access??");
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_NOT_COMPLETE, regValue);
+ }
+ }
+ }
+ // else, all data not available yet (NOT_COMPLETE)
+ }
+ }
+
+} // end dimm_read_temp()
+
+
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, &regValue);
+ 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()
+
+
diff --git a/src/occ_gpe1/gpe1_main.c b/src/occ_gpe1/gpe1_main.c
index e81869e..88f3be8 100644
--- a/src/occ_gpe1/gpe1_main.c
+++ b/src/occ_gpe1/gpe1_main.c
@@ -1,7 +1,7 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
-/* $Source: src/occ_gpe0/gpe0_main.c $ */
+/* $Source: src/occ_gpe1/gpe1_main.c $ */
/* */
/* OpenPOWER OnChipController Project */
/* */
@@ -31,12 +31,12 @@
#include "pk.h"
#include "ipc_api.h"
-#include "ipc_ping.h"
#define KERNEL_STACK_SIZE 256
uint8_t G_kernel_stack[KERNEL_STACK_SIZE];
+
// The main function is called by the boot code (after initializing some
// registers)
int main(int argc, char **argv)
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
PK_TRACE("Kernel init completed");
- // Disable IPC's and register the IPC interrupt handler
+ // Disable IPC's and register the IPC interrupt handler
rc = ipc_init();
if(rc)
{
diff --git a/src/occ_gpe1/ipc_func_tables.c b/src/occ_gpe1/ipc_func_tables.c
index 1dfa02e..3c34920 100644
--- a/src/occ_gpe1/ipc_func_tables.c
+++ b/src/occ_gpe1/ipc_func_tables.c
@@ -1,4 +1,6 @@
#include "ipc_api.h"
+#include "gpe1_dimm.h"
+
// Function table for multi target (common) functions
IPC_MT_FUNC_TABLE_START
@@ -14,7 +16,7 @@ IPC_MT_FUNC_TABLE_END
// Function table for single target (processor-specific) functions
IPC_ST_FUNC_TABLE_START
-IPC_HANDLER_DEFAULT // 0
+IPC_HANDLER(gpe_dimm_sm, 0) // 0 - IPC_ST_DIMM_SM_FUNCID
IPC_HANDLER_DEFAULT // 1
IPC_HANDLER_DEFAULT // 2
IPC_HANDLER_DEFAULT // 3
diff --git a/src/occ_gpe1/topfiles.mk b/src/occ_gpe1/topfiles.mk
index 698d29f..0b8ca4b 100644
--- a/src/occ_gpe1/topfiles.mk
+++ b/src/occ_gpe1/topfiles.mk
@@ -1,4 +1,4 @@
-TOP-C-SOURCES = gpe1_main.c pk_app_irq_table.c ipc_func_tables.c
+TOP-C-SOURCES = gpe1_main.c gpe1_dimm_read.c gpe1_dimm_reset.c pk_app_irq_table.c ipc_func_tables.c
TOP-S-SOURCES =
TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o)
OpenPOWER on IntegriCloud