summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBill Hoffa <wghoffa@us.ibm.com>2017-05-30 15:25:20 -0500
committerWilliam A. Bryan <wilbryan@us.ibm.com>2017-06-06 16:56:17 -0400
commitf5d0529142ff4edc716d080f6c8aada028f9ceeb (patch)
tree6f1e1d31147be4d1ad389f595619057a23f137e5 /src
parent852d3b94da35cfa28c08f871df6eff4a21681d60 (diff)
downloadtalos-occ-f5d0529142ff4edc716d080f6c8aada028f9ceeb.tar.gz
talos-occ-f5d0529142ff4edc716d080f6c8aada028f9ceeb.zip
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 <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/occ_405/firdata/ast_mboxdd.c365
-rw-r--r--src/occ_405/firdata/ast_mboxdd.h266
-rw-r--r--src/occ_405/firdata/norflash.h10
-rw-r--r--src/occ_405/firdata/pnor_mboxdd.c396
-rw-r--r--src/occ_405/firdata/pnor_mboxdd.h135
-rw-r--r--src/occ_405/firdata/pnor_util.c46
-rw-r--r--src/occ_405/firdata/sfc_ast2400.c728
-rw-r--r--src/occ_405/firdata/sfc_ast2400.h298
-rw-r--r--src/occ_405/topfiles.mk4
9 files changed, 1179 insertions, 1069 deletions
diff --git a/src/occ_405/firdata/ast_mboxdd.c b/src/occ_405/firdata/ast_mboxdd.c
new file mode 100644
index 0000000..4541a76
--- /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 <native.h>
+#include <norflash.h>
+#include <ast_mboxdd.h>
+#include <lpc.h>
+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 0000000..d48e50e
--- /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 <assert.h>
+
+/** @file ast_mboxdd.H
+ * @brief Provides the interfaces Aspeed MBOX hardware
+ */
+
+/**
+ * @brief Provides the interface to exchange Mbox
+ * messages with the BMC.
+ */
+
+enum
+{
+ BMC_MBOX_DATA_REGS = 14,
+ BMC_MBOX_ARGS_REGS = 11,
+
+ /* Commands */
+ MBOX_C_RESET_STATE = 0x01,
+ MBOX_C_GET_MBOX_INFO = 0x02,
+ MBOX_C_GET_FLASH_INFO = 0x03,
+ MBOX_C_CREATE_READ_WINDOW = 0x04,
+ MBOX_C_CLOSE_WINDOW = 0x05,
+ MBOX_C_CREATE_WRITE_WINDOW = 0x06,
+ MBOX_C_MARK_WRITE_DIRTY = 0x07,
+ MBOX_C_WRITE_FLUSH = 0x08,
+ MBOX_C_BMC_EVENT_ACK = 0x09,
+ MBOX_C_MARK_WRITE_ERASED = 0x0a,
+
+ /* Responses */
+ MBOX_R_SUCCESS = 0x01,
+ MBOX_R_PARAM_ERROR = 0x02,
+ MBOX_R_WRITE_ERROR = 0x03,
+ MBOX_R_SYSTEM_ERROR = 0x04,
+ MBOX_R_TIMEOUT = 0x05,
+ MBOX_R_BUSY = 0x06,
+ MBOX_R_WINDOW_ERROR = 0x07,
+
+};
+
+enum{
+ SIO_DEVICE_SELECT_REG = 0x07, /**< Regsiter to select SIO device */
+ SIO_ADDR_REG_2E = 0x2E, /**< SuperIO address register */
+ SIO_DATA_REG_2F = 0x2F, /**< SuperIO data register */
+ SIO_PASSWORD_REG = 0xA5, /**< SuperIO password register (to be unlocked to access SIO) */
+ SIO_MB = 0x0E, /**< SIO device: Mailbox */
+ SIO_ENABLE_DEVICE = 0x01, /**< Enable SIO device by writing 1 to reg 30 of device */
+ SIO_DISABLE_DEVICE = 0x00, /**< Disable SIO device by writing 0 to reg 30 of device */
+};
+
+
+typedef struct
+{
+ uint8_t iv_cmd;
+ uint8_t iv_seq;
+ uint8_t iv_args[BMC_MBOX_ARGS_REGS];
+ uint8_t iv_resp;
+
+} mboxMessage_t;
+
+/**
+ * @brief Write a single byte into an SIO register
+ *
+ * @param[in] i_reg: Register to write
+ * @param[in] i_data: Data to write
+ *
+ * @return Error from operation
+ */
+errorHndl_t writeRegSIO(uint8_t i_regAddr,
+ uint8_t i_data );
+
+/**
+ * @brief Read a single byte from an SIO register
+ *
+ * @param[in] i_reg: Register to read
+ * @param[in] o_data: Data that was read
+ *
+ * @return Error from operation
+ */
+errorHndl_t readRegSIO(uint8_t i_regAddr,
+ uint8_t* o_data );
+
+
+//Helper functions to create mbox messages to send to the BMC
+
+/**
+ * @brief 8-bit read accessor of the args section
+ *
+ * @param[in] i_msg: mboxMessage_t pointer to access args section
+ * @param[in] i_index: Index into args section to be read from
+ *
+ * @return data requested
+ */
+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 d41c878..c4c9cdc 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 <native.h>
-#include <sfc_ast2400.h>
+#include <pnor_mboxdd.h>
/** @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 0000000..a5624ff
--- /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 <native.h>
+#include <norflash.h>
+#include <pnor_mboxdd.h>
+#include <lpc.h>
+#include <assert.h>
+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 0000000..ab8f05d
--- /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 <ast_mboxdd.h>
+
+/** @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 bf32480..f27dbb7 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 <native.h>
-#include <sfc_ast2400.h>
+#include <pnor_mboxdd.H>
#include <ecc.h>
#include <pnor_util.h>
#include <norflash.h>
@@ -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 fbdb0b3..0000000
--- 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 <native.h>
-#include <norflash.h>
-/*#include <string.h> */
-#include <sfc_ast2400.h>
-#include <lpc.h>
-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<sizeof(i_data); i++ )
- {
- l_err = writeRegSIO( i_sfc, 0xF4+i, /*F4,F5,F6,F7 */
- ptr8[i] );
- if( l_err ) { break; }
- }
- if( l_err ) { break; }
-
- /* Trigger the write operation by writing the magic 0xCF value */
- l_err = writeRegSIO( i_sfc, 0xFE, 0xCF );
- if( l_err ) { break; }
-
- } while(0);
-
- /*TRACDCOMP( EXIT_MRK"writeRegSPIC> 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<sizeof(*o_data); i++ )
- {
- l_err = readRegSIO( i_sfc, 0xF4+i, /*F4,F5,F6,F7 */
- &(ptr8[i]) );
- if( l_err ) { break; }
- }
- if( l_err ) { break; }
-
- } while(0);
-
- /*TRACDCOMP( EXIT_MRK"readRegSPIC> 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 30a9052..0000000
--- 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 <native.h>
-#include <homerData_common.h>
-
-/** @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 d471509..9eb45cd 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 \
OpenPOWER on IntegriCloud