Skip to content

Commit

Permalink
Update i2c driver for OCMB chip
Browse files Browse the repository at this point in the history
After doing some testing with the simics Axone model we found that
we had some errors in the protocols used to do reg reads and writes.
We had to put extra dummy information when we latch and address to
read and also we were not reading enough bytes when reading the
status. This commit addresses both of these issues.

Change-Id: I15ce40ef28d6c6c2303fe600986c8872b0829ad0
RTC: 196806
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69575
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/71414
Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com>
  • Loading branch information
crgeddes authored and sgupta2m committed Feb 13, 2019
1 parent 9eba575 commit 0f9a51d
Showing 1 changed file with 40 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER sbe Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2018 */
/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -114,6 +114,8 @@ inline fapi2::ReturnCode fw_status(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_C
{
std::vector<uint8_t> l_data;
FAPI_TRY(fapi2::getI2c(i_target, l_size, l_cmd_id, l_data));
FAPI_INF( "status returned ( 5 bytes ) : 0x%.02X 0x%.02X 0x%.02X 0x%.02X 0x%.02X",
l_data[0], l_data[1] , l_data[2], l_data[3], l_data[4]);
FAPI_TRY( check::status_code(i_target, l_cmd_id[0], l_data) );
}

Expand Down Expand Up @@ -197,12 +199,9 @@ inline fapi2::ReturnCode fw_reg_write(const fapi2::Target<fapi2::TARGET_TYPE_OC
{
// create byte vector that will hold command bytes in sequence that will do the scom
std::vector<uint8_t> l_cmd_vector;
std::vector<uint8_t> l_le_addr_vector;
std::vector<uint8_t> l_le_data_vector;
uint32_t l_input_data = static_cast<uint32_t>(i_data_buffer);
std::vector<uint8_t> l_be_vector;

forceLE(i_addr, l_le_addr_vector);
forceLE(l_input_data, l_le_data_vector);
uint32_t l_input_data = static_cast<uint32_t>(i_data_buffer);

// Start building the cmd vector for the write operation
l_cmd_vector.push_back(FW_REG_WRITE); // Byte 0 = 0x05 (FW_REG_WRITE)
Expand All @@ -212,9 +211,14 @@ inline fapi2::ReturnCode fw_reg_write(const fapi2::Target<fapi2::TARGET_TYPE_OC
// write them directly to the cmd_vector in the same order they
// currently are
// Byte 2:5 = Address
l_cmd_vector.insert(l_cmd_vector.end(), l_le_addr_vector.begin(), l_le_addr_vector.end());
forceBE(i_addr, l_be_vector);
l_cmd_vector.insert(l_cmd_vector.end(), l_be_vector.begin(), l_be_vector.end());

l_be_vector.clear();
forceBE(l_input_data, l_be_vector);

// Byte 6:9 = Data
l_cmd_vector.insert(l_cmd_vector.end(), l_le_data_vector.begin(), l_le_data_vector.end());
l_cmd_vector.insert(l_cmd_vector.end(), l_be_vector.begin(), l_be_vector.end());

// Use fapi2 putI2c interface to execute command
FAPI_TRY(fapi2::putI2c(i_target, l_cmd_vector),
Expand Down Expand Up @@ -244,22 +248,23 @@ inline fapi2::ReturnCode fw_reg_read(const fapi2::Target<fapi2::TARGET_TYPE_OCMB
{
// create byte vector that will hold command bytes in sequence that will do the scom
std::vector<uint8_t> l_cmd_vector;
std::vector<uint8_t> l_read_data;
std::vector<uint8_t> l_le_addr_vector;
uint32_t l_index = 0;
uint32_t l_read_value = 0;
std::vector<uint8_t> l_tmp_vector;

forceLE(i_addr, l_le_addr_vector);
// Flush o_data_buffer w/ all 0's to avoid stale data
o_data_buffer.flush<0>();

// Force the address to be BE
forceBE(i_addr, l_tmp_vector);

// Build the cmd vector for the Read
l_cmd_vector.push_back(FW_REG_ADDR_LATCH); // Byte 0 = 0x03 (FW_REG_ADDR_LATCH)
l_cmd_vector.push_back(FW_REG_ADDR_LATCH_SIZE); // Byte 1 = 0x04 (FW_REG_ADDR_LATCH_SIZE)

// i_addr was converted to LE above so we can write it
// i_addr was converted to BE above so we can write it
// directly to the cmd_vector in the same order it
// currently is in
// Byte 2:5 = Address
l_cmd_vector.insert(l_cmd_vector.end(), l_le_addr_vector.begin(), l_le_addr_vector.end());
l_cmd_vector.insert(l_cmd_vector.end(), l_tmp_vector.begin(), l_tmp_vector.end());

// Use fapi2 putI2c interface to execute command
FAPI_TRY(fapi2::putI2c(i_target, l_cmd_vector),
Expand All @@ -271,41 +276,50 @@ inline fapi2::ReturnCode fw_reg_read(const fapi2::Target<fapi2::TARGET_TYPE_OCMB
"Invalid Status after FW_REG_ADDR_LATCH operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X",
i_addr, mss::fapi_pos(i_target));

// Clear out the tmp_vector because we will re-use as the read buffer
l_tmp_vector.clear();

// Clear out cmd vector as i2c op is complete and we must prepare for next
l_cmd_vector.clear();

// Cmd vector is a single byte with FW_REG_READ code
l_cmd_vector.push_back(FW_REG_READ); // Byte 0 = 0x04 (FW_REG_READ)
l_cmd_vector.push_back(0x4); // Remaining bytes dont matter to HB firmware
l_cmd_vector.push_back(0x0); // but the hw is expecting something there so
l_cmd_vector.push_back(0x0); // we should write something
l_cmd_vector.push_back(0x0);
l_cmd_vector.push_back(0x0);

// Use fapi2 getI2c interface to execute command
FAPI_TRY(fapi2::getI2c(i_target, FW_I2C_SCOM_READ_SIZE, l_cmd_vector, l_read_data),
FAPI_TRY(fapi2::getI2c(i_target, FW_I2C_SCOM_READ_SIZE, l_cmd_vector, l_tmp_vector),
"getI2c returned error for FW_REG_READ operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X",
i_addr, mss::fapi_pos(i_target));

// The first byte returned should be the size of the remaining data
// We requested FW_REG_ADDR_LATCH_SIZE bytes so that is what we
// expect to see as the first byte.
FAPI_ASSERT( (l_read_data.front() == FW_REG_ADDR_LATCH_SIZE),
FAPI_ASSERT( (l_tmp_vector.front() == FW_REG_ADDR_LATCH_SIZE),
fapi2::I2C_GET_SCOM_INVALID_READ_SIZE()
.set_TARGET(i_target)
.set_ADDRESS(i_addr)
.set_SIZE_RETURNED(l_read_data[0])
.set_SIZE_RETURNED(l_tmp_vector[0])
.set_SIZE_REQUESTED(FW_REG_ADDR_LATCH_SIZE),
"First byte of read data was expected to be 0x%lx but byte read = 0x%x",
FW_REG_ADDR_LATCH_SIZE, l_read_data[0] );
FW_REG_ADDR_LATCH_SIZE, l_tmp_vector[0] );

// Check i2c status after operation
FAPI_TRY(fw_status(i_target),
"Invalid Status after FW_REG_READ operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X",
i_addr, mss::fapi_pos(i_target));

// The OCMB is a 32-bit little endian engine so
// we must convert the buffer that we read into native
// incase native endian is different than LE
readLE(l_read_data, l_index, l_read_value);
o_data_buffer = l_read_value;


// Build uint32_t from bytes 1-4 of the returned data. Bytes are
// returned in BE so no translation neccesary. Faster to just access
// the 4 bytes and shift than to perform vector operations to pop off front
// entry and convert vector to uint32.
o_data_buffer = ( l_tmp_vector[1] << 24 |
l_tmp_vector[2] << 16 |
l_tmp_vector[3] << 8 |
l_tmp_vector[4]);
fapi_try_exit:
return fapi2::current_err;
}
Expand Down

0 comments on commit 0f9a51d

Please sign in to comment.