summaryrefslogtreecommitdiffstats
path: root/src/occ_405/firdata/ast_mboxdd.c
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/occ_405/firdata/ast_mboxdd.c
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/occ_405/firdata/ast_mboxdd.c')
-rw-r--r--src/occ_405/firdata/ast_mboxdd.c365
1 files changed, 365 insertions, 0 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;
+}
OpenPOWER on IntegriCloud