From f5d0529142ff4edc716d080f6c8aada028f9ceeb Mon Sep 17 00:00:00 2001 From: Bill Hoffa Date: Tue, 30 May 2017 15:25:20 -0500 Subject: [PATCH] PNOR MBOX Read/Write Support for Firdata - Create base AST Mbox functionality for interacting with the BMC MBOX - Create base PNOR Mbox functionality that uses the AST Mbox functionality to do full PNOR reads/writes - Updated PNOR utility flow to use new MBOX functionality Change-Id: I332c9b3524b8f2d6d9458fdd60611893a8945efc RTC: 173635 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/41138 Tested-by: FSP CI Jenkins Reviewed-by: Prachi Gupta Reviewed-by: Martha Broyles Reviewed-by: William A. Bryan --- src/occ_405/firdata/ast_mboxdd.c | 365 +++++++++++++++ src/occ_405/firdata/ast_mboxdd.h | 266 +++++++++++ src/occ_405/firdata/norflash.h | 10 +- src/occ_405/firdata/pnor_mboxdd.c | 396 ++++++++++++++++ src/occ_405/firdata/pnor_mboxdd.h | 135 ++++++ src/occ_405/firdata/pnor_util.c | 46 +- src/occ_405/firdata/sfc_ast2400.c | 728 ------------------------------ src/occ_405/firdata/sfc_ast2400.h | 298 ------------ src/occ_405/topfiles.mk | 4 +- 9 files changed, 1179 insertions(+), 1069 deletions(-) create mode 100644 src/occ_405/firdata/ast_mboxdd.c create mode 100644 src/occ_405/firdata/ast_mboxdd.h create mode 100644 src/occ_405/firdata/pnor_mboxdd.c create mode 100644 src/occ_405/firdata/pnor_mboxdd.h delete mode 100644 src/occ_405/firdata/sfc_ast2400.c delete mode 100644 src/occ_405/firdata/sfc_ast2400.h diff --git a/src/occ_405/firdata/ast_mboxdd.c b/src/occ_405/firdata/ast_mboxdd.c new file mode 100644 index 00000000..4541a76c --- /dev/null +++ b/src/occ_405/firdata/ast_mboxdd.c @@ -0,0 +1,365 @@ +/* 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 +extern int TRACE_LPC; +int TRACE_MBOX = 0; + +/*****************************************************************************/ +/* C o n s t a n t s */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* G l o b a l s */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* M e t h o d s */ +/*****************************************************************************/ + +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(o_byte); + + 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*)((char*)&io_msg)); + errorHndl_t l_err = NO_ERROR; + uint8_t l_stat1; + uint8_t l_flags; + uint32_t l_loops = 0; + bool l_prot_error = false; + int i; + + TRAC_INFO( "doMessage(0x%02x)", io_msg->iv_cmd ); + 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; + } + + TRAC_INFO( "Command sent, waiting for response..."); + + /* Wait for response */ + while ( l_loops++ < MBOX_MAX_RESP_WAIT_US && !l_err ) + { + l_err = mboxIn(MBOX_STATUS_1, &l_stat1); + + if ( l_err ) + { + break; + } + + l_err = mboxIn(MBOX_FLAG_REG, &l_flags); + + if ( l_err ) + { + break; + } + + if ( l_stat1 & MBOX_STATUS1_RESP ) + { + break; + } + + sleep(1000); + } + + if ( l_err ) + { + TRAC_INFO( "Got error waiting for response !"); + break; + } + + if ( !(l_stat1 & MBOX_STATUS1_RESP) ) + { + TRAC_INFO( "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_INFO( "Error communicating with MBOX daemon"); + TRAC_INFO( "Mbox status 1 reg: %x", l_stat1); + TRAC_INFO( "Mbox flag reg: %x", l_flags); + } + + // 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_INFO( "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 + TRAC_INFO( "Reading response data..."); + + for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++) + { + l_err = mboxIn(i, &l_data[i]); + } + + if ( l_err ) + { + TRAC_INFO( "Got error reading response !"); + break; + } + + TRAC_INFO( "Message: cmd:%02x seq:%02x a:%02x %02x %02x %02x %02x..resp:%02x", + io_msg->iv_cmd, io_msg->iv_seq, io_msg->iv_args[0], + io_msg->iv_args[1], io_msg->iv_args[2], io_msg->iv_args[3], + io_msg->iv_args[4], io_msg->iv_resp); + + if (old_seq != io_msg->iv_seq) + { + TRAC_INFO( "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_INFO( "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 ) + { + } + + TRAC_INFO( "doMessage() resp=0x%02x", + io_msg->iv_resp ); + return l_err; +} + +errorHndl_t initializeMbox(void) +{ + errorHndl_t l_errl = NO_ERROR; + + TRAC_INFO("initializeMBOX()"); + + 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 new file mode 100644 index 00000000..d48e50eb --- /dev/null +++ b/src/occ_405/firdata/ast_mboxdd.h @@ -0,0 +1,266 @@ +/* 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 + +#include + +/** @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 + */ +inline uint8_t get8( mboxMessage_t *i_msg, uint8_t i_index) +{ + assert( i_index < BMC_MBOX_ARGS_REGS); + 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 + */ +inline void put8( mboxMessage_t *i_msg, uint8_t i_index, uint8_t i_value ) +{ + assert( i_index < BMC_MBOX_ARGS_REGS); + 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 + */ +inline uint16_t get16( mboxMessage_t *i_msg, uint8_t i_index ) +{ + assert( i_index < (BMC_MBOX_ARGS_REGS - 1)); + 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 + */ +inline void put16( mboxMessage_t *i_msg, uint8_t i_index, uint16_t i_value ) +{ + assert( i_index < (BMC_MBOX_ARGS_REGS - 1)); + 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 + */ +inline uint32_t get32( mboxMessage_t *i_msg, uint8_t i_index ) +{ + assert( i_index < (BMC_MBOX_ARGS_REGS - 3)); + 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 + */ +inline void put32( mboxMessage_t *i_msg, uint8_t i_index, uint32_t i_value ) +{ + assert( i_index < (BMC_MBOX_ARGS_REGS - 3)); + 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/norflash.h b/src/occ_405/firdata/norflash.h index d41c8785..c4c9cdcd 100644 --- a/src/occ_405/firdata/norflash.h +++ b/src/occ_405/firdata/norflash.h @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/firdata/norflash.H $ */ +/* $Source: src/occ_405/firdata/norflash.h $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -27,7 +27,7 @@ #define __PNOR_NORFLASH_H #include -#include +#include /** @file norflash.H * @brief Contains constants related to specific types of @@ -142,11 +142,11 @@ enum * Status register be read after a read or erase operation, * otherwise all future operations won't work.. * - * @parm i_sfc SFC driver to operate on + * @parm i_pnorMbox Pnor Mbox Struct to operate on * * @return Error from operation */ -errorHndl_t micronFlagStatus( Sfc_t* i_sfc ); +errorHndl_t micronFlagStatus( pnorMbox_t* i_pnorMbox ); diff --git a/src/occ_405/firdata/pnor_mboxdd.c b/src/occ_405/firdata/pnor_mboxdd.c new file mode 100644 index 00000000..a5624ff9 --- /dev/null +++ b/src/occ_405/firdata/pnor_mboxdd.c @@ -0,0 +1,396 @@ +/* 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 +#include +extern int TRACE_PNOR_MBOX; +int TRACE_PNOR_MBOX = 0; + +errorHndl_t hwInit(pnorMbox_t* i_pnorMbox) +{ + errorHndl_t l_err = NO_ERROR; + + //Current window starts closed + i_pnorMbox->iv_curWindowOpen = false; + i_pnorMbox->iv_mbox.iv_mboxMsgSeq = 1; + initializeMbox(); + + //Send message to BMC Mbox to get MBOX info + // This message gets the MBOX protocol version + mboxMessage_t l_getInfoMsg; + l_getInfoMsg.iv_cmd = MBOX_C_GET_MBOX_INFO; + put8(&l_getInfoMsg, 0, 2); + doMessage(&i_pnorMbox->iv_mbox, &l_getInfoMsg); + 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); + } + + TRAC_INFO("mboxPnor: protocolVersion=%d blockShift=%d", + i_pnorMbox->iv_protocolVersion, + i_pnorMbox->iv_blockShift); + + //Now get the size of the flash + mboxMessage_t l_getSizeMsg; + l_getSizeMsg.iv_cmd = MBOX_C_GET_FLASH_INFO; + doMessage(&i_pnorMbox->iv_mbox, &l_getSizeMsg); + + 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; + } + + 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 + assert( i_size % 4 == 0); + + TRAC_INFO("readFlash(i_addr=0x%.8X)> ", i_addr); + + 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 + assert( i_size % 4 == 0 ); + + TRAC_INFO(ENTER_MRK"writeFlash(i_address=0x%llx)> ", i_addr); + + 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; + } + + TRAC_INFO("writeFlash(i_address=0x%llx)> i_size=%.8X", + i_addr, i_size); + + 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 + */ + TRAC_INFO("astMboxDD::adjustMboxWindow using protocol version: %d", + i_pnorMbox->iv_protocolVersion); + 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; + } + + TRAC_INFO("adjustMboxWindow opening %s window at 0x%08x" + " for addr 0x%08x req_size 0x%08x", + i_isWrite ? "write" : "read", l_pos, i_reqAddr, l_reqSize); + + 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; + + TRAC_INFO(" curWindowOffset = %08x", i_pnorMbox->iv_curWindowOffset); + TRAC_INFO(" curWindowSize = %08x", i_pnorMbox->iv_curWindowSize); + TRAC_INFO(" curWindowLpcOffset = %08x", + i_pnorMbox->iv_curWindowLpcOffset); + + } + 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 new file mode 100644 index 00000000..ab8f05d3 --- /dev/null +++ b/src/occ_405/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_405/firdata/pnor_util.c b/src/occ_405/firdata/pnor_util.c index bf32480f..f27dbb74 100644 --- a/src/occ_405/firdata/pnor_util.c +++ b/src/occ_405/firdata/pnor_util.c @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/firdata/pnor_util.C $ */ +/* $Source: src/occ_405/firdata/pnor_util.c $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -26,7 +26,7 @@ /* Interfaces to write into PNOR */ #include -#include +#include #include #include #include @@ -36,8 +36,9 @@ uint32_t g_next_byte = 0xFFFFFFFF; /* Size of the FIRDATA section of PNOR */ uint32_t g_pnor_size = 0; -/* Global SFC object */ -Sfc_t g_sfc; +/* 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 */ @@ -74,10 +75,10 @@ int32_t pnor_write_8B( uint64_t i_data ) memcpy( &(g_write_cache[g_write_cache_index]), data9, cpsz ); g_write_cache_index += cpsz; - /* Write a complete chunk into the flash */ + /* Write a complete chunk into the flash */ if( g_write_cache_index == PAGE_PROGRAM_BYTES ) { - errorHndl_t tmp = writeFlash( &g_sfc, + errorHndl_t tmp = writeFlash( &g_pnorMbox, g_next_byte, PAGE_PROGRAM_BYTES, g_write_cache ); @@ -113,9 +114,6 @@ errorHndl_t pnor_prep( HOMER_PnorInfo_t* i_pnorInfo ) { errorHndl_t l_err = NO_ERROR; - g_sfc.iv_mmioOffset = i_pnorInfo->mmioOffset; - g_sfc.iv_flashWorkarounds = i_pnorInfo->norWorkarounds; - /* 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; @@ -123,7 +121,7 @@ errorHndl_t pnor_prep( HOMER_PnorInfo_t* i_pnorInfo ) memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); /* Can we rely on skiboot leaving things in a good state? */ - l_err = hwInit(&g_sfc); + l_err = hwInit(&g_pnorMbox); if( l_err ) { TRACFCOMP("hwInit failed"); @@ -132,17 +130,6 @@ errorHndl_t pnor_prep( HOMER_PnorInfo_t* i_pnorInfo ) g_pnor_size = 0; } - /* Future Improvement - Enable write mode once at the beginning to avoid extra - reg operations turning it on and off - l_err = enableWriteMode(g_sfc); - if( l_err ) - { - g_next_byte = 0xFFFFFFFF; - g_pnor_size = 0; - } - */ - return l_err; } @@ -166,21 +153,6 @@ int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, } uint32_t idx = 0; - - /* Erase the section. */ - for( idx = i_pnorInfo.pnorOffset; - idx < (i_pnorInfo.pnorOffset+i_pnorInfo.pnorSize); - idx += 4096 ) - { - l_err = eraseFlash(&g_sfc,idx); - if( l_err ) - { - TRACFCOMP("eraseFlash failed"); - rc = FAIL; - break; /*nothing more to do here*/ - } - } - uint64_t dataChunk = 0; size_t sz_dataChunk = sizeof(uint64_t); diff --git a/src/occ_405/firdata/sfc_ast2400.c b/src/occ_405/firdata/sfc_ast2400.c deleted file mode 100644 index fbdb0b34..00000000 --- a/src/occ_405/firdata/sfc_ast2400.c +++ /dev/null @@ -1,728 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/sfc_ast2400.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 */ - -/*****************************************************************************/ -/* I n c l u d e s */ -/*****************************************************************************/ -#include -#include -/*#include */ -#include -#include -extern int TRACE_LPC; -int TRACE_SFC = 0; - -/*****************************************************************************/ -/* C o n s t a n t s */ -/*****************************************************************************/ - - - - -/*****************************************************************************/ -/* G l o b a l s */ -/*****************************************************************************/ - - -/*****************************************************************************/ -/* M e t h o d s */ -/*****************************************************************************/ - -/** - * @brief Read data from the flash - */ -errorHndl_t readFlash( Sfc_t* i_sfc, - uint32_t i_addr, - size_t i_size, - void* o_data ) -{ - /*TRACDCOMP( ENTER_MRK"readFlash> i_addr=0x%.8x, i_size=0x%.8x", i_addr, i_size ); */ - errorHndl_t l_err = 0; - - do{ - uint32_t* word_ptr = (uint32_t*)(o_data); - uint32_t word_size = (ALIGN_4(i_size))/4; - uint32_t words_read = 0; - for( words_read = 0; - words_read < word_size; - words_read ++ ) - { - /*Read directly from MMIO space */ - uint32_t lpc_addr = i_sfc->iv_mmioOffset | (i_addr + words_read*4); - size_t reg_size = sizeof(uint32_t); - l_err = lpc_read( LPC_TRANS_FW, - lpc_addr, - (uint8_t*)&(word_ptr[words_read]), - reg_size ); - if( l_err ) { break; } - } - if( l_err ) { break; } - }while(0); - - /*TRACDCOMP( EXIT_MRK"readFlash> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - - -/** - * @brief Write data into flash - */ -errorHndl_t writeFlash( Sfc_t* i_sfc, - uint32_t i_addr, - size_t i_size, - void* i_data ) -{ - TRACFCOMP( "writeFlash> i_addr=0x%.8x, i_size=0x%.8x", i_addr, i_size ); - errorHndl_t l_err = 0; - size_t l_bytes_left = i_size; - size_t l_bytes_to_write = 0; - uint32_t l_addr_to_write = i_addr; - uint8_t* l_dataptr = (uint8_t*)(i_data); - - do { - /* Enable write mode */ - l_err = enableWriteMode(i_sfc); - if( l_err ) { break; } - - /* Page Program (PP) command only supports 256 bytes at a time */ - if( l_bytes_left <= PAGE_PROGRAM_BYTES ) - { - l_bytes_to_write = l_bytes_left; - l_bytes_left = 0; - } - else - { - l_bytes_to_write = PAGE_PROGRAM_BYTES; - l_bytes_left -= PAGE_PROGRAM_BYTES; - } - - /* Send in the Page Program command with the data to write */ - uint8_t opcode = SPI_JEDEC_PAGE_PROGRAM; - l_err = sendSpiCmd( i_sfc, opcode, l_addr_to_write, - l_bytes_to_write, - l_dataptr, - 0, NULL ); - if( l_err ) { break; } - - /* Move to the next chunk */ - l_addr_to_write += l_bytes_to_write; - l_dataptr += l_bytes_to_write; - - /* Wait for idle */ - l_err = pollOpComplete(i_sfc); - if( l_err ) { break; } - - /*check for special Micron Flag Status reg */ - if(i_sfc->iv_flashWorkarounds & HWWK_MICRON_WRT_ERASE) - { - l_err = micronFlagStatus(i_sfc); - if(l_err) { break; } - } - - } while(l_bytes_left); - - /*TRACDCOMP( EXIT_MRK"writeFlash> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Erase a block of flash - */ -errorHndl_t eraseFlash( Sfc_t* i_sfc, - uint32_t i_addr ) -{ - TRACFCOMP(">>eraseFlash> Block 0x%.8X", i_addr ); - errorHndl_t l_err = 0; - - do { - // Enable write mode - l_err = enableWriteMode(i_sfc); - if( l_err ) { break; } - - // Send erase command - uint8_t opcode = SPI_JEDEC_SECTOR_ERASE; - l_err = sendSpiCmd( i_sfc, opcode, i_addr, 0, 0, 0, NULL ); - if( l_err ) { break; } - - // Wait for idle - l_err = pollOpComplete(i_sfc); - if( l_err ) { break; } - - //check for special Micron Flag Status reg - if(i_sfc->iv_flashWorkarounds & HWWK_MICRON_WRT_ERASE) - { - l_err = micronFlagStatus(i_sfc); - if(l_err) { break; } - } - } while(0); - - return l_err; -} - - -/** - * @brief Initialize and configure the SFC hardware - */ -errorHndl_t hwInit( Sfc_t* i_sfc ) -{ - TRACFCOMP( ENTER_MRK"hwInit>" ); - errorHndl_t l_err = NO_ERROR; - - do { - size_t reg_size = sizeof(uint8_t); - - /*** Initialize the LPC2AHB logic */ - - /* Send SuperIO password - send A5 twice */ - uint8_t data = 0xA5; - l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_2E, - &data, reg_size ); - if( l_err ) { break; } - - l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_2E, - &data, reg_size ); - if( l_err ) { break; } - - - /* Select logical device D (iLPC2AHB) */ - l_err = writeRegSIO( i_sfc, 0x07, 0x0D ); - if( l_err ) { break; } - - - /* Enable iLPC->AHB */ - l_err = writeRegSIO( i_sfc, 0x30, 0x01 ); - if( l_err ) { break; } - - - /*** Setup the SPI Controller */ - - /* Enable writing to the controller */ - SpiControlReg04_t ctlreg; - l_err = readRegSPIC( i_sfc, CTLREG_04, &ctlreg.data32 ); - if( l_err ) { break; } - TRACFCOMP("dc99> First read of CTLREG_04=%.8X", ctlreg.data32); - ctlreg.cmdMode = 2;/*0b10; //10:Normal Write (CMD + Address + Write data) */ - l_err = writeRegSPIC( i_sfc, CTLREG_04, ctlreg.data32 ); - if( l_err ) { break; } - - SpiConfigReg00_t confreg; - l_err = readRegSPIC( i_sfc, CONFREG_00, &confreg.data32 ); - if( l_err ) { break; } - confreg.inactiveX2mode = 1; /*Enable CE# Inactive pulse width X2 mode */ - confreg.enableWrite = 1; /*Enable flash memory write */ - l_err = writeRegSPIC( i_sfc, CONFREG_00, confreg.data32 ); - if( l_err ) { break; } - - - /* - * Setup control reg and for our use, switching - * to 1-bit mode, clearing user mode if set, etc... - * - * Also configure SPI clock to something safe - * like HCLK/8 (24Mhz) - */ - ctlreg.fourByteMode = 1; - ctlreg.ioMode = 0;/*0b00; //single bit or controlled by bit[3] */ - ctlreg.pulseWidth = 0x0; /*0000: 16T (1T = 1 HCLK clock) */ - ctlreg.cmdData = 0x00; - ctlreg.spiClkFreq = 0x4; /*HCLK/8 */ - ctlreg.dummyCycleRead1 = 0; /*no dummy cycles */ - ctlreg.dummyCycleRead2 = 0;/*0b00; //no dummy cycles */ - ctlreg.cmdMode = 0;/*0b00; //00:Normal Read (03h + Address + Read data) */ - i_sfc->iv_ctlRegDefault = ctlreg; /* Default setup is regular read mode */ - - /* Configure for read */ - l_err = writeRegSPIC( i_sfc, CTLREG_04, ctlreg.data32 ); - if( l_err ) { break; } - - /* Setup flash-specific settings here, if there are any */ - - } while(0); - - TRACFCOMP( "hwInit> err=%.8X", l_err ); - return l_err; -} - -/** - * @brief Send a SPI command - */ -errorHndl_t sendSpiCmd( Sfc_t* i_sfc, - uint8_t i_opCode, - uint32_t i_address, - size_t i_writeCnt, - const uint8_t* i_writeData, - size_t i_readCnt, - uint8_t* o_readData ) -{ - errorHndl_t l_err = NO_ERROR; - size_t opsize = 0; - if(TRACE_SFC){ - TRACFCOMP( ENTER_MRK"sendSpiCmd> i_opCode=%.2X, i_address=%.8X, i_writeCnt=0x%X, i_writeData=%p", i_opCode, i_address, i_writeCnt, i_writeData ); - TRACFCOMP( " , i_readCnt=0x%X, o_readData=%p", i_readCnt, o_readData ); - } - - do { - /*Do a read of flash address zero to workaround */ - /* a micron bug with extended reads */ - if( (HWWK_MICRON_EXT_READ & i_sfc->iv_flashWorkarounds) - && (i_readCnt > 4) ) - { - uint32_t ignored = 0; - l_err = readFlash( i_sfc, 0, 1, &ignored ); - if(l_err) { break; } - } - - /* Put controller into command mode (instead of read mode) */ - l_err = commandMode( i_sfc, true ); - if( l_err ) { break; } - - /* Write command to the beginning of the flash space */ - opsize = sizeof(i_opCode); - l_err = lpc_write( LPC_TRANS_FW, i_sfc->iv_mmioOffset, - &i_opCode, - opsize ); /*just send opcode */ - if( l_err ) { break; } - - /* Send address if there is one */ - if( i_address != NO_ADDRESS ) - { - /* Write address to the beginning of the flash space */ - opsize = sizeof(i_address); - l_err = lpc_write( LPC_TRANS_FW, i_sfc->iv_mmioOffset, - (uint8_t*)&i_address, - opsize ); /*only supporting 4-byte addresses */ - if( l_err ) { break; } - } - - /* Send in the rest of the write data */ - if( i_writeCnt && i_writeData ) - { - size_t bytes_left = i_writeCnt; - uint8_t* curptr = (uint8_t*)(i_writeData); - while( bytes_left ) - { - /* Write the last partial word if there is one */ - if( bytes_left < 4 ) - { - opsize = bytes_left; - l_err = lpc_write( LPC_TRANS_FW, i_sfc->iv_mmioOffset, - curptr, - opsize ); - break; - } - - /* Write data into the beginning of the flash space, */ - /* in command mode this doesn't write the flash */ - /* but instead is a pass-through to the area we */ - /* really want to write */ - opsize = sizeof(uint32_t); - l_err = lpc_write( LPC_TRANS_FW, i_sfc->iv_mmioOffset, - curptr, - opsize ); - if( l_err ) { break; } - - curptr += 4; - bytes_left -= 4; - } - if( l_err ) { break; } - } - - /* Read back the results */ - if( i_readCnt && o_readData ) - { - size_t bytes_left = i_readCnt; - uint8_t* curptr = o_readData; - while( bytes_left ) - { - /* Grab the last partial word if there is one */ - if( bytes_left < 4 ) - { - opsize = bytes_left; - l_err = lpc_read( LPC_TRANS_FW, i_sfc->iv_mmioOffset, - curptr, - opsize ); - break; - } - - /* Read data from the beginning of the flash space, */ - /* in command mode this doesn't read the flash */ - /* but instead is a pass-through to the data we */ - /* really want */ - opsize = sizeof(uint32_t); - l_err = lpc_read( LPC_TRANS_FW, i_sfc->iv_mmioOffset, - curptr, - opsize ); - if( l_err ) { break; } - - curptr += 4; - bytes_left -= 4; - } - if( l_err ) { break; } - } - } while(0); - - - /* No matter what, put the logic back into read mode */ - int tmp_err = commandMode( i_sfc, false ); - if( tmp_err ) - { - if( !l_err ) - { - l_err = tmp_err; - } - } - - /*TRACDCOMP( EXIT_MRK"sendSpiCmd> o_readData=%.2X, err=%.8X", o_readData == NULL ? 0 : o_readData[0], ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Enter/exit command mode - */ -errorHndl_t commandMode( Sfc_t* i_sfc, - bool i_enter ) -{ - errorHndl_t l_err = NO_ERROR; - /*TRACDCOMP( ENTER_MRK"commandMode(%d)", i_enter ); */ - - /* - * There is only a limited addressable window within LPC space. The AST - * has its control register space at too far of a distance from the read - * space for them both to fit in a single window. Rather than moving the - * window around we will use the iLPC2AHB backdoor inside the SuperIO - * controller to do both register accesses and to write into the flash. - * - * High level flow to write into control space: - * Stop active control (SPI04 Control Reg) - * Enable command mode (SPI04 Control Reg) - * Write actual command into flash base addr (0x0E000000) - */ - - do { - SpiControlReg04_t ctlreg = i_sfc->iv_ctlRegDefault; - - /* Switch to user mode, CE# dropped */ - ctlreg.stopActiveCtl = 1; - ctlreg.cmdMode = 3;/*0b11; //User Mode (Read/Write Data) */ - l_err = writeRegSPIC( i_sfc, CTLREG_04, ctlreg.data32 ); - if( l_err ) { break; } - - if( i_enter ) /*ast_sf_start_cmd */ - { - /* user mode, CE# active */ - ctlreg.stopActiveCtl = 0; - l_err = writeRegSPIC( i_sfc, CTLREG_04, ctlreg.data32 ); - if( l_err ) { break; } - } - else /*ast_sf_end_cmd */ - { - /* Switch back to read mode */ - l_err = writeRegSPIC( i_sfc, CTLREG_04, i_sfc->iv_ctlRegDefault.data32 ); - if( l_err ) { break; } - } - } while(0); - - /*TRACDCOMP( EXIT_MRK"commandMode> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Enable write mode - */ -errorHndl_t enableWriteMode( Sfc_t* i_sfc ) -{ - errorHndl_t l_err = NO_ERROR; - /*TRACDCOMP( ENTER_MRK"enableWriteMode>" ); */ - - /* Some flashes need it to be hammered */ - NorStatusReg_t status; -// status.data8 = 0x55; - size_t i = 0; - for( i = 0; i < 10; i++ ) - { - /* Send the command to enable writes */ - uint8_t opcode = SPI_JEDEC_WRITE_ENABLE; - l_err = sendSpiCmd( i_sfc, opcode, NO_ADDRESS, 0, NULL, 0, NULL ); - if( l_err ) { break; } - - /* Check to see if it worked */ - opcode = SPI_JEDEC_READ_STATUS; - l_err = sendSpiCmd( i_sfc, opcode, NO_ADDRESS, 0, NULL, 1, &(status.data8) ); - if( l_err ) { break; } - TRACDCOMP( "SPI_JEDEC_READ_STATUS=%.2X", status.data8 ); - - if( status.writeEnable ) - { - break; - } - } - - if( !l_err && !status.writeEnable ) - { - TRACFCOMP( "Could not enable writes" ); - l_err = -1; - } - - /*TRACDCOMP( EXIT_MRK"enableWriteMode> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Write a single byte into the SIO - */ -errorHndl_t writeRegSIO( Sfc_t* i_sfc, - uint8_t i_regAddr, - uint8_t i_data ) -{ /*lpc_sio_outb */ - errorHndl_t l_err = NO_ERROR; - /*TRACFCOMP( "writeRegSIO> i_regAddr=0x%.2X, i_data=0x%.2X", i_regAddr, i_data );*/ - - do { - size_t reg_size = sizeof(uint8_t); - - /* AST2400 integrates a Super I/O module with */ - /* LPC protocol (I/O cycle 0x2E/0x2F) */ - - /* Write out the register address */ - l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_2E, - &i_regAddr, - reg_size ); - if( l_err ) { break; } - - /* Write out the register data */ - l_err = lpc_write( LPC_TRANS_IO, SIO_DATA_2F, - &i_data, - reg_size ); - if( l_err ) { break; } - - } while(0); - - /*TRACDCOMP( EXIT_MRK"writeRegSIO> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Read a single byte from the SIO - */ -errorHndl_t readRegSIO( Sfc_t* i_sfc, - uint8_t i_regAddr, - uint8_t* o_data ) -{ - errorHndl_t l_err = NO_ERROR; - /*TRACDCOMP( ENTER_MRK"readRegSIO> i_regAddr=0x%.2X", i_regAddr ); */ - - do { - size_t reg_size = sizeof(uint8_t); - - /* AST2400 integrates a Super I/O module with */ - /* LPC protocol (I/O cycle 0x2E/0x2F) */ - - /* Write out the register address */ - l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_2E, - &i_regAddr, - reg_size ); - if( l_err ) { break; } - - /* Read in the register data */ - l_err = lpc_read( LPC_TRANS_IO, SIO_DATA_2F, - o_data, - reg_size ); - if( l_err ) { break; } - - } while(0); - - /*TRACDCOMP( EXIT_MRK"readRegSIO> o_data=0x%.2X, err-%.8X", *o_data, ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Prepare the iLPC2AHB address regs - */ -errorHndl_t setupAddrLPC2AHB( Sfc_t* i_sfc, - uint32_t i_addr ) -{ - errorHndl_t l_err = NO_ERROR; - /*TRACDCOMP( ENTER_MRK"setupAddrLPC2AHB> i_addr=0x%X", i_addr ); */ - - do { - /* Select logical device D (iLPC2AHB) */ - l_err = writeRegSIO( i_sfc, 0x07, 0x0D ); - if( l_err ) { break; } - - /* Push 4 address bytes into SIO regs 0xF0-0xF3 */ - size_t i; - for( i=sizeof(i_addr); i>0; i-- ) - { - l_err = writeRegSIO( i_sfc, 0xF3-(i-1), /*F0,F1,F2,F3 */ - (uint8_t)(i_addr >> ((i-1)*8)) ); - if( l_err ) { break; } - } - if( l_err ) { break; } - - /* Configure 4 byte length */ - l_err = writeRegSIO( i_sfc, 0xF8, 0x02 ); - if( l_err ) { break; } - - } while(0); - - /*TRACDCOMP( EXIT_MRK"setupAddrLPC2AHB> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Write SPI Controller Register - */ -errorHndl_t writeRegSPIC( Sfc_t* i_sfc, - SpicReg_t i_reg, - uint32_t i_data ) -{ - errorHndl_t l_err = NO_ERROR; - //TRACFCOMP( "writeRegSPIC> i_reg=0x%.2X, i_data=0x%.8X", i_reg, i_data ); - - do { - /* Compute the full LPC address */ - uint32_t lpc_addr = i_reg | SPIC_BASE_ADDR_AHB; - - /* Setup the logic for the write */ - l_err = setupAddrLPC2AHB( i_sfc, lpc_addr ); - if( l_err ) { break; } - - /* Push 4 data bytes into SIO regs 0xF4-0xF7 */ - uint8_t* ptr8 = (uint8_t*)(&i_data); - size_t i; - for( i=0; i err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Read SPI Controller Register - */ -errorHndl_t readRegSPIC( Sfc_t* i_sfc, - SpicReg_t i_reg, - uint32_t* o_data ) -{ - //TRACFCOMP( "readRegSPIC> i_reg=0x%.2X", i_reg ); - errorHndl_t l_err = NO_ERROR; - - do { - /* Compute the full LPC address */ - uint32_t lpc_addr = i_reg | SPIC_BASE_ADDR_AHB; - - /* Setup the logic for the write */ - l_err = setupAddrLPC2AHB( i_sfc, lpc_addr ); - if( l_err ) { break; } - - /* Trigger the write operation by reading the magic register */ - uint8_t ignored = 0; - l_err = readRegSIO( i_sfc, 0xFE, &ignored ); - if( l_err ) { break; } - - /* Read 4 data bytes into SIO regs 0xF4-0xF7 */ - uint8_t* ptr8 = (uint8_t*)(o_data); - size_t i; - for( i=0; i o_data=0x%.8X, l_err=%.8X", *o_data, ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - -/** - * @brief Poll for completion of SPI operation - */ -errorHndl_t pollOpComplete( Sfc_t* i_sfc ) -{ - errorHndl_t l_err = NO_ERROR; - /* TRACDCOMP( "pollOpComplete>" ); */ -int trace_lpc=TRACE_LPC; TRACE_LPC=0; -int trace_sfc=TRACE_SFC; TRACE_SFC=0; - - do { - /* Send RDSR command until write-in-progress clears */ - NorStatusReg_t status; - uint64_t poll_time = 0; - uint64_t loop = 0; - while( poll_time < MAX_WRITE_TIME_NS ) - { - uint8_t opcode = SPI_JEDEC_READ_STATUS; - l_err = sendSpiCmd( i_sfc, opcode, - NO_ADDRESS, - 0, NULL, - 1, &(status.data8) ); - if( l_err ) { break; } - - /* check if any op is still going */ - if( !status.writeInProgress ) - { - 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 */ - ++loop; - sleep( 100*loop ); - poll_time += 100*loop; - } - if( l_err ) { break; } - - /*TRACDCOMP(g_trac_pnor,"pollOpComplete> command took %d ns", poll_time); */ - - /* No status regs to check so just look for timeout */ - if( status.writeInProgress ) - { - TRACFCOMP( "pollOpComplete> Timeout during write or erase" ); - l_err = -1; - break; - } - } while(0); - -TRACE_LPC=trace_lpc; -TRACE_SFC=trace_sfc; - /*TRACDCOMP( EXIT_MRK"pollOpComplete> err=%.8X", ERRL_GETEID_SAFE(l_err) ); */ - return l_err; -} - diff --git a/src/occ_405/firdata/sfc_ast2400.h b/src/occ_405/firdata/sfc_ast2400.h deleted file mode 100644 index 30a90527..00000000 --- a/src/occ_405/firdata/sfc_ast2400.h +++ /dev/null @@ -1,298 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ/firdata/sfc_ast2400.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_SFCAST2400_H -#define __PNOR_SFCAST2400_H - -#include -#include - -/** @file sfc_ast2400.H - * @brief Provides the logic to access and configure the - * AST2400 BMC in order to access the PNOR - */ - -/** - * @brief SPI04 Control Register - */ -typedef union -{ - uint32_t data32; - struct - { /*Little-endian bit positions*/ - uint32_t rsvd : 2; /*31:30*/ - uint32_t ioMode : 2; /*29:28*/ - uint32_t pulseWidth : 4; /*27:24*/ - uint32_t cmdData : 8; /*23:16*/ - uint32_t dummyCycleCmd : 1; /*15*/ - uint32_t dummyCycleRead1 : 1; /*14*/ - uint32_t fourByteMode : 1; /*13*/ - uint32_t disableCmdMerge : 1; /*12*/ - uint32_t spiClkFreq : 4; /*11:8*/ - uint32_t dummyCycleRead2 : 2; /*7:6*/ - uint32_t lsbFirst : 1; /*5*/ - uint32_t useClkMode3 : 1; /*4*/ - uint32_t dualInputMode : 1; /*3*/ - uint32_t stopActiveCtl : 1; /*2*/ - uint32_t cmdMode : 2; /*1:0*/ - }; -} SpiControlReg04_t; - - -/** - * @brief Structure to hold information about the SFC - */ -typedef struct -{ - /** - * @brief Default value of SPI04 (saves a read) - */ - SpiControlReg04_t iv_ctlRegDefault; - - /** - * @brief Hardware workarounds - */ - uint32_t iv_flashWorkarounds; - - /** - * @brief LPC address that marks the beginning of flash - */ - uint32_t iv_mmioOffset; -} Sfc_t; - - -/** - * @brief Initialize the SFC Hardware - * @param[in] Pointer to Sfc struct - * - * @return void - */ -errorHndl_t hwInit(Sfc_t* i_sfc); - -/** - * @brief Read data from the PNOR flash - * - * @param[in] Pointer to Sfc 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(Sfc_t* i_sfc, - uint32_t i_addr, - size_t i_size, - void* o_data); - -/** - * @brief Write data to the PNOR flash - * - * @param[in] Pointer to Sfc 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(Sfc_t* i_sfc, - uint32_t i_addr, - size_t i_size, - void* i_data); - -/** - * @brief Erase a block of flash - */ -errorHndl_t eraseFlash( Sfc_t* i_sfc, - uint32_t i_addr ); - -/** @brief Constant for sendSpiCmd parameter */ -static const uint32_t NO_ADDRESS = UINT32_MAX; - - -/** - * @brief Send a SPI command - * - * @param[in] Pointer to Sfc struct - * @parm[in] i_opCode: command to send into controller first - * @parm[in] i_address: address for those commands that need it - * @parm[in] i_writeCnt: number of bytes to write to device - * @parm[in] i_writeData: write data buffer - * @parm[in] i_readCnt: number of bytes to read from device - * @parm[out] o_readData: read data buffer - * - * @return Error from operation - */ -errorHndl_t sendSpiCmd( Sfc_t* i_sfc, - uint8_t i_opCode, - uint32_t i_address, - size_t i_writeCnt, - const uint8_t* i_writeData, - size_t i_readCnt, - uint8_t* o_readData ); - -/** - * @brief List of registers in the SPI Controller logic - */ -typedef enum -{ - CONFREG_00 = 0x00, - CTLREG_04 = 0x04, - MISCCTLREG_10 = 0x10, - READTIMEREG_14 = 0x14 -} SpicReg_t; - -/** - * @brief Write a SPI Controller register - * - * @param[in] Pointer to Sfc struct - * @param[in] i_reg: Register to write - * @param[in] i_data: Data to write - * - * @return Error from operation - */ -errorHndl_t writeRegSPIC( Sfc_t* i_sfc, - SpicReg_t i_reg, - uint32_t i_data ); - -/** - * @brief Write a SPI Controller register - * - * @param[in] Pointer to Sfc struct - * @param[in] i_reg: Register to write - * @param[in] o_data: Data that was read - * - * @return Error from operation - */ -errorHndl_t readRegSPIC( Sfc_t* i_sfc, - SpicReg_t i_reg, - uint32_t* o_data ); - -/** - * @brief Write a single byte into a SIO register - * - * @param[in] Pointer to Sfc struct - * @param[in] i_reg: Register to write - * @param[in] i_data: Data to write - * - * @return Error from operation - */ -errorHndl_t writeRegSIO( Sfc_t* i_sfc, - uint8_t i_regAddr, - uint8_t i_data ); - -/** - * @brief Read a single byte from a SIO register - * - * @param[in] Pointer to Sfc struct - * @param[in] i_reg: Register to read - * @param[in] o_data: Data that was read - * - * @return Error from operation - */ -errorHndl_t readRegSIO( Sfc_t* i_sfc, - uint8_t i_regAddr, - uint8_t* o_data ); - -/** - * @brief Enable write mode - * - * @param[in] Pointer to Sfc struct - * @return Error from operation - */ -errorHndl_t enableWriteMode( Sfc_t* i_sfc ); - -/** - * @brief Enter/exit command mode - * - * @param[in] Pointer to Sfc struct - * @param[in] i_enter: true=enter cmd mode, false=exit cmd mode - * - * @return Error from operation - */ -errorHndl_t commandMode( Sfc_t* i_sfc, - bool i_enter ); - -/** - * @brief Poll for completion of SPI operation - * - * @param[in] Pointer to Sfc struct - * @return Error from operation - */ -errorHndl_t pollOpComplete( Sfc_t* i_sfc ); - -/** - * @brief Prepare the iLPC2AHB address regs - * - * @param[in] Pointer to Sfc struct - * @param[in] i_addr: LPC address to access - * - * @return Error from operation - */ -errorHndl_t setupAddrLPC2AHB( Sfc_t* i_sfc, - uint32_t i_addr ); - - -/** - * @brief SPI0 Configuration Register - */ -typedef union -{ - uint32_t data32; - struct - { /*Little-endian bit positions*/ - uint32_t rsvd : 30; /*31:2*/ - uint32_t inactiveX2mode : 1; /*1*/ - uint32_t enableWrite : 1; /*0*/ - }; -} SpiConfigReg00_t; - -/** @brief General Constants */ -enum -{ - LPC_TOP_OF_FLASH_OFFSET = 0x0FFFFFFF, - - /**< Offset to SPI Controller Register Space */ - LPC_SFC_CTLR_BASE = 0x1E789000, - - /**< AHB address of SPI Flash controller */ - SPIC_BASE_ADDR_AHB = 0x1E630000, - - /**< AHB address of flash */ - FLASH_BASE_ADDR_AHB = 0x30000000, - - /**< AHB address of LPC registers */ - LPC_CTLR_BASE_ADDR_AHB = 0x1E789000, - - /**< Maximum time to wait for a write/erase */ - MAX_WRITE_TIME_NS = NS_PER_SEC, - - /**< SuperIO Address Cycle */ - SIO_ADDR_2E = 0x2E, - - /**< SuperIO Data Cycle */ - SIO_DATA_2F = 0x2F, -}; - - -#endif diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk index d471509a..9eb45cd6 100644 --- a/src/occ_405/topfiles.mk +++ b/src/occ_405/topfiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015,2016 +# Contributors Listed Below - COPYRIGHT 2015,2017 # [+] International Business Machines Corp. # # @@ -65,6 +65,8 @@ TOP-C-SOURCES = amec/amec_analytics.c \ dimm/dimm_control.c \ errl/errl.c \ firdata/fir_data_collect.c \ + firdata/ast_mboxdd.c \ + firdata/pnor_mboxdd.c \ homer.c \ lock/lock.c \ main.c \