summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorManali Kumar <mkkumar@us.ibm.com>2015-09-24 18:52:00 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2015-12-08 10:24:35 -0600
commit1fbe5e7bf5042ee9e7353a169d13eec54c270f04 (patch)
tree3cb9fc58e569fa0d22f7f16a6d8b32900e9de2da /src
parentdee70f6f25fb4ed099942b1b3b0a340bd643ff06 (diff)
downloadtalos-hostboot-1fbe5e7bf5042ee9e7353a169d13eec54c270f04.tar.gz
talos-hostboot-1fbe5e7bf5042ee9e7353a169d13eec54c270f04.zip
superio driver to control accesss to SIO registers
The SuperIO driver makes accesses to the SIO chip from the console and pnor module thread safe. Change-Id: Ib07dea2867d14684806c56cd965b26c95810f7f3 RTC:115576 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20928 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: PRACHI GUPTA <pragupta@us.ibm.com> Reviewed-by: Richard J. Knight <rjknight@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/devicefw/userif.H17
-rw-r--r--src/include/usr/hbotcompid.H8
-rw-r--r--src/include/usr/sio/sio.H51
-rw-r--r--src/makefile2
-rw-r--r--src/usr/console/HBconfig8
-rw-r--r--src/usr/console/ast2400.C379
-rw-r--r--src/usr/initservice/bootconfig/bootconfig_ast2400.C173
-rw-r--r--src/usr/initservice/bootconfig/bootconfig_ast2400.H33
-rw-r--r--src/usr/makefile3
-rw-r--r--src/usr/pnor/sfc_ast2400.C285
-rw-r--r--src/usr/pnor/sfc_ast2400.H44
-rw-r--r--src/usr/pnor/test/sfc_ast2400test.H138
-rw-r--r--src/usr/sio/HBconfig4
-rwxr-xr-xsrc/usr/sio/makefile33
-rwxr-xr-xsrc/usr/sio/siodd.C434
-rw-r--r--src/usr/sio/siodd.H183
-rw-r--r--src/usr/sio/test/makefile30
-rw-r--r--src/usr/sio/test/sioddtest.H452
18 files changed, 1452 insertions, 825 deletions
diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H
index 55751d97d..e30595e40 100644
--- a/src/include/usr/devicefw/userif.H
+++ b/src/include/usr/devicefw/userif.H
@@ -63,6 +63,8 @@ namespace DeviceFW
IPMIBT, // As opposed to other phy's
PVPD,
TPM,
+ SIO,
+ AHB_SIO,
LAST_ACCESS_TYPE,
};
@@ -214,6 +216,21 @@ namespace DeviceFW
DeviceFW::LPC, static_cast<uint64_t>(( i_trans_type )),\
static_cast<uint64_t>(( i_address ))
+ /**
+ * Construct the device addressing parameters for the SIO device ops.
+ * @param[i] i_device - SIO device to operate on
+ * @param[i] i_address - SIO address to operate on
+ */
+ #define DEVICE_SIO_ADDRESS(i_device, i_address)\
+ DeviceFW::SIO, static_cast<uint64_t>((i_device)),\
+ static_cast<uint64_t>((i_address))
+
+ /**
+ * Construct the device addressing parameters for the AHB_SIO device ops.
+ * @param[i] i_address - AHB_SIO address to operate on
+ */
+ #define DEVICE_AHB_SIO_ADDRESS(i_address)\
+ DeviceFW::AHB_SIO, static_cast<uint64_t>((i_address))
/**
* Construct the device addressing parameters for the EEPROM device ops.
diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H
index 88cd49dbd..dc5b79d41 100644
--- a/src/include/usr/hbotcompid.H
+++ b/src/include/usr/hbotcompid.H
@@ -383,6 +383,14 @@ const compId_t FIPS_ERRL_COMP_ID = 0x3100;
const char FIPS_ERRL_COMP_NAME[] = "hb-trace";
//@}
+/** @name SIO
+ * SIO driver
+ */
+//@{
+const compId_t SIO_COMP_ID = 0x3200;
+const char SIO_COMP_NAME[] = "sio";
+//@}
+
/** @name PRDF
* PRDF component
* @Note PRDF_COMP_ID=0xE500 matches with what
diff --git a/src/include/usr/sio/sio.H b/src/include/usr/sio/sio.H
new file mode 100644
index 000000000..52f752da7
--- /dev/null
+++ b/src/include/usr/sio/sio.H
@@ -0,0 +1,51 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/sio/sio.H $ */
+/* */
+/* OpenPOWER HostBoot 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 __SIO_SIO_H
+#define __SIO_SIO_H
+
+namespace SIO
+{
+ /**
+ * SIO constants
+ */
+ 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) */
+ SUART1 = 0x02, /**< SIO device */
+ iLPC2AHB = 0x0D, /**< SIO device */
+ KBC = 0x05, /**< SIO device: Keyboard Controller */
+ MB = 0x0E, /**< SIO device: Mailbox */
+ DONT_CARE = 0x02, /**< SIO device: Don't care for boot flags version */
+ ENABLE_DEVICE = 0x01, /**< Enable SIO device by writing 1 to reg 30 of device */
+ DISABLE_DEVICE = 0x00, /**< Disable SIO device by writing 0 to reg 30 of device */
+ SIO_iLPC2AHB_LENGTH = 0x02, /**< SIO to iLPC2AHB length */
+ SIO_ILPC2AHB_TRIGGER = 0xCF, /**< Read/Write 0xCF to reg FE of iLPC2AHB to trigger read/write for SIO/iLPC2AHB */
+ SIO_SCRATCH_REG1 = 0x21, /**< Scratch Reg */
+ SIO_SCRATCH_REG2 = 0x22, /**< Scratch Reg */
+ };
+}
+#endif
diff --git a/src/makefile b/src/makefile
index 8f986862c..f581ebafb 100644
--- a/src/makefile
+++ b/src/makefile
@@ -115,6 +115,7 @@ BASE_MODULES += secureboot_base
BASE_MODULES += lpc
BASE_MODULES += pnor
BASE_MODULES += vfs
+BASE_MODULES += $(if $(CONFIG_AST2400), sio)
EXTENDED_MODULES += targeting
EXTENDED_MODULES += ecmddatabuffer
@@ -208,6 +209,7 @@ TESTCASE_MODULES += testrtloader
TESTCASE_MODULES += testsbe
TESTCASE_MODULES += testlpc
TESTCASE_MODULES += $(if $(CONFIG_HTMGT),testhtmgt)
+TESTCASE_MODULES += $(if $(CONFIG_AST2400), testsio)
RUNTIME_OBJECTS += rt_start.o
RUNTIME_OBJECTS += rt_main.o
diff --git a/src/usr/console/HBconfig b/src/usr/console/HBconfig
index e6b1ebda7..664febd86 100644
--- a/src/usr/console/HBconfig
+++ b/src/usr/console/HBconfig
@@ -1,4 +1,10 @@
config CONSOLE
- default y if BMC_AST2400
+ default y if (BMC_AST2400 || CONSOLE_DEFAULT_UART)
help
Enable console support.
+
+config CONSOLE_DEFAULT_UART
+ default n
+ depends on !BMC_AST2400
+ help
+ Enable a default UART driver for the console.
diff --git a/src/usr/console/ast2400.C b/src/usr/console/ast2400.C
index 243c9bec1..c56bf02c4 100644
--- a/src/usr/console/ast2400.C
+++ b/src/usr/console/ast2400.C
@@ -22,6 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+#include <sio/sio.H>
#include "uart.H"
#include <devicefw/userif.H>
#include <lpc/lpcif.H>
@@ -32,19 +33,21 @@
namespace CONSOLE
{
- const uint32_t VUART1_BASE = 0x1E787000;
- const uint32_t VUART1_GCTRLA = VUART1_BASE + 0x20;
- const uint32_t VUART1_GCTRLB = VUART1_BASE + 0x24;
- const uint32_t VUART1_ADDRL = VUART1_BASE + 0x28;
- const uint32_t VUART1_ADDRH = VUART1_BASE + 0x2c;
-
- const uint8_t SERIAL_IRQ = 4;
-
- const uint8_t SIO_ADDR_REG_2E = 0x2E;
- const uint8_t SIO_DATA_REG_2F = 0x2F;
-
- // used to test config flags related to console outup selection
- const uint8_t CONFIG_MASK = 0xC0;
+ const uint32_t VUART1_BASE = 0x1E787000;
+ const uint32_t VUART1_GCTRLA = VUART1_BASE + 0x20;
+ const uint32_t VUART1_GCTRLB = VUART1_BASE + 0x24;
+ const uint32_t VUART1_ADDRL = VUART1_BASE + 0x28;
+ const uint32_t VUART1_ADDRH = VUART1_BASE + 0x2c;
+
+ const uint8_t SERIAL_IRQ = 4;
+
+ // Host SerlIRQ interrupt type for SUART1
+ const uint8_t RESERVED = 0x00;
+ const uint8_t LOW_LEVEL_TRIG = 0x01;
+ const uint8_t RISING_EDGE_TRIG = 0x02;
+ const uint8_t HIGH_LEVEL_TRIG = 0x03;
+ // used to test config flags related to console output selection
+ const uint8_t CONFIG_MASK = 0xC0;
/** Overload the base class with Ast2400 specifics.
*
@@ -53,7 +56,6 @@ namespace CONSOLE
*/
class Ast2400Uart : public Uart
{
-
public:
enum consoleConfig_t
{
@@ -64,205 +66,65 @@ namespace CONSOLE
};
private:
- // $TODO RTC:115576 remove these sio write functions when SIO dd code
- // is completed
- // Perform raw LPC writes to SIO region.
- errlHndl_t _writeReg(uint8_t i_addr, uint8_t i_byte)
- {
- size_t len = sizeof(i_byte);
- return deviceWrite(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &i_byte,
- len,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, i_addr));
- }
-
- // write i_data to register i_reg
- errlHndl_t writeSIOReg( uint8_t i_reg, uint8_t i_data )
- {
- errlHndl_t l_err = NULL;
-
- do{
-
- l_err = _writeReg( SIO_ADDR_REG_2E, i_reg );
-
- if(l_err) { break; }
-
- l_err = _writeReg( SIO_DATA_REG_2F, i_data );
-
- }while(0);
-
- return l_err;
- }
-
- // Perform reads from the SIO register region.
- errlHndl_t readSIOReg(uint8_t i_reg, uint8_t &o_byte)
- {
- errlHndl_t l_err = NULL;
-
- size_t len = sizeof(o_byte);
-
- do{
- l_err = deviceWrite(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &i_reg,
- len,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO_ADDR_REG_2E));
-
- if(l_err) { break; }
-
- l_err = deviceRead(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &o_byte,
- len,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO_DATA_REG_2F));
- }while(0);
-
- return l_err;
- }
-
- // setup the AHB access
- errlHndl_t ahbSioAddressPrep(uint32_t reg)
- {
- errlHndl_t l_err = NULL;
-
- do{
- // Select logical device D (LPC2AHB)
- l_err = writeSIOReg( 0x07, 0x0D );
- if( l_err ) { break; }
-
- /* Enable iLPC->AHB */
- l_err = writeSIOReg( 0x30, 0x01 );
- if( l_err ) { break; }
-
- /* Address */
- l_err = writeSIOReg(0xF0, (reg >> 24) & 0xff);
- if( l_err ) {break; }
-
- l_err = writeSIOReg(0xF1, (reg >> 16) & 0xff);
- if( l_err ) {break; }
-
- l_err = writeSIOReg(0xF2, (reg >> 8) & 0xff);
- if( l_err ) {break; }
-
- l_err = writeSIOReg(0xF3, (reg ) & 0xff);
- if( l_err ) {break; }
-
- /* bytes per cycle type */
- l_err = writeSIOReg(0xF8, 0x02);
- if( l_err ) {break; }
-
- }while(0);
-
- return l_err;
- }
-
- errlHndl_t ahbSioWrite(uint32_t reg, uint32_t val )
- {
- errlHndl_t l_err = NULL;
-
- do{
-
- l_err = ahbSioAddressPrep( reg);
- if( l_err ) { break; }
-
- /* Write data */
- l_err = writeSIOReg(0xF4, val >> 24);
- if( l_err ) { break; }
- l_err = writeSIOReg(0xF5, val >> 16);
- if( l_err ) { break; }
- l_err = writeSIOReg(0xF6, val >> 8);
- if( l_err ) { break; }
- l_err = writeSIOReg(0xF7, val);
- if( l_err ) { break; }
-
- /* Trigger the write with the magic number */
- l_err = writeSIOReg(0xFe, 0xcf);
-
- }while(0);
-
- return l_err;
- }
-
- errlHndl_t ahbSioRead( uint32_t reg, uint32_t &o_data )
- {
- errlHndl_t l_err = NULL;
- uint8_t tmp_data = 0;
- o_data = 0;
-
- do{
-
- l_err = ahbSioAddressPrep(reg);
- if(l_err){break;}
-
- /* Trigger the read - ignore the output data */
- l_err = readSIOReg(0xFE, tmp_data);
- if(l_err){break;}
-
- tmp_data = 0;
-
- /* Read results */
- l_err = readSIOReg(0xF4, tmp_data );
- if(l_err){;break;}
- o_data = tmp_data;
-
- l_err = readSIOReg(0xF5, tmp_data );
- if(l_err){break;}
- o_data = (o_data << 8) | tmp_data;
-
- l_err = readSIOReg(0xF6, tmp_data );
- if(l_err){break;}
- o_data = (o_data << 8) | tmp_data;
-
- l_err = readSIOReg(0xF7, tmp_data );
- if(l_err){break;}
- o_data = (o_data << 8) | tmp_data;
-
- }while(0);
-
- return l_err;
- }
-
- private:
-
void initializeSUART()
{
errlHndl_t l_errl = NULL;
-
+ uint8_t l_data;
+ size_t l_len = sizeof(uint8_t);
do
{
- // Select logical device 2 (SUART1) in SI)
- l_errl = writeSIOReg( 0x07, 0x02);
- if (l_errl) { break; }
-
// Disable SUART1 to change settings
- l_errl = writeSIOReg( 0x30, 0x00 );
+ l_data = SIO::DISABLE_DEVICE;
+ l_errl = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x30));
if (l_errl) { break; }
// Set SUART1 addr to g_uartBase
- l_errl = writeSIOReg( 0x60, (g_uartBase >> 8) & 0xFF );
+ l_data =(g_uartBase >> 8) & 0xFF;
+ l_errl = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x60));
if (l_errl) { break; }
- l_errl = writeSIOReg( 0x61, (g_uartBase & 0xFF) );
+ l_data = g_uartBase & 0xFF;
+ l_errl = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x61));
if (l_errl) { break; }
// Set the SerIRQ
- l_errl = writeSIOReg( 0x70, SERIAL_IRQ );
+ l_data = SERIAL_IRQ;
+ l_errl = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x70));
if (l_errl) { break; }
- l_errl = writeSIOReg( 0x71, 0x01 );
+ l_data = LOW_LEVEL_TRIG;
+ l_errl = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x71));
if (l_errl) { break; }
-
// Enable SUART1
- l_errl = writeSIOReg( 0x30, 0x01 ); // select SIO base enable
+ l_data = SIO::ENABLE_DEVICE;
+ l_errl = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x30));
if (l_errl) { break; }
- //@fixme-RTC:115576 - Leaving SIO unlocked for now to allow
- // PNOR write/erase to work
- // Lock the SIO registers
- //l_errl = _writeReg( 0x2e, 0xAA );
- //if (l_errl) { break; }
-
} while(0);
if (l_errl)
@@ -279,29 +141,66 @@ namespace CONSOLE
{
errlHndl_t l_err = NULL;
- do{
+ do
+ {
uint32_t v;
-
+ size_t l_len = sizeof(v);
+ /* Enable device 0x0D*/
+ uint8_t l_data = SIO::ENABLE_DEVICE;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ (&l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::iLPC2AHB,0x30));
+ if(l_err) { break; }
/* configure IRQ level as low */
- l_err = ahbSioRead(VUART1_GCTRLA, v);
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(v),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_GCTRLA));
if(l_err){break;}
v = v & ~2u;
- l_err = ahbSioWrite(VUART1_GCTRLA, v);
+ l_err = deviceOp(DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(v),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_GCTRLA));
+
if(l_err){break;}
/* configure the IRQ number */
- l_err = ahbSioRead(VUART1_GCTRLB, v);
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(v),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_GCTRLB));
if(l_err){break;}
v = (v & ~0xf0u) | ((SERIAL_IRQ << 4));
- l_err = ahbSioWrite(VUART1_GCTRLB,v);
+ l_err = deviceOp(DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(v),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_GCTRLB));
if(l_err){break;}
/* configure the address */
- l_err = ahbSioWrite(VUART1_ADDRL, g_uartBase & 0xff);
+ v = g_uartBase & 0xff;
+ l_err = deviceOp(DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(v),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_ADDRL));
if(l_err){break;}
- l_err = ahbSioWrite(VUART1_ADDRH, g_uartBase >> 8);
+ v = g_uartBase >> 8;
+ l_err = deviceOp(DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(v),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_ADDRH));
+ if(l_err){break;}
}while(0);
@@ -323,21 +222,29 @@ namespace CONSOLE
{
errlHndl_t l_err = NULL;
- do{
+ do
+ {
// read the control reg, mask off the enabled bit
// and write it back
uint32_t reg_value = 0;
+ size_t l_len = sizeof(reg_value);
+ l_err = deviceOp(DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(reg_value),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_GCTRLA));
- l_err = ahbSioRead(VUART1_GCTRLA, reg_value );
if(l_err){break;}
// mask off the low order bit to mark the vuart as disabled
reg_value &= 0xFE;
- l_err = ahbSioWrite(VUART1_GCTRLA, reg_value );
+ l_err = deviceOp(DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(reg_value),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(VUART1_GCTRLA));
if(l_err){break;}
-
-
}while(0);
if (l_err)
@@ -350,14 +257,16 @@ namespace CONSOLE
{
errlHndl_t l_err = NULL;
- do{
-
- // select device 2 - UART1
- l_err = writeSIOReg(0x07, 0x02);
- if(l_err){break;}
-
+ do
+ {
// clear the uart enable from base ctl reg
- l_err = writeSIOReg(0x30, 0);
+ uint8_t l_data = SIO::DISABLE_DEVICE;
+ size_t l_len = sizeof(uint8_t);
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x30));
}while(0);
@@ -367,54 +276,36 @@ namespace CONSOLE
}
};
- virtual void unlockSIO()
- {
- errlHndl_t l_err = NULL;
- do{
- // Unlock the SIO registers
- // (write 0xA5 password to offset 0x2E two times)
- l_err = _writeReg( SIO_ADDR_REG_2E, 0xA5 );
- if (l_err) { break; }
-
- l_err = _writeReg( SIO_ADDR_REG_2E, 0xA5 );
-
- }while(0);
-
- if (l_err)
- {
- errlCommit(l_err, CONSOLE_COMP_ID);
- }
-
- }
-
- public:
+ public:
virtual void initialize()
{
// read the SIO register set by the BMC to determine uart config
const uint8_t expected_version =
INITSERVICE::BOOTCONFIG::BOOT_FLAGS_VERSION_1;
-
uint8_t this_version = 0x00;
errlHndl_t l_err = NULL;
-
+ size_t l_len = sizeof(uint8_t);
uint8_t uart_config = 0x00;
- do{
- // allow access to the registers
- unlockSIO();
-
+ do
+ {
// verify the boot flags version from register 0x28
- l_err = readSIOReg( 0x28, this_version );
-
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(this_version),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x28));
if (l_err) { break; }
-
// is it the version we expected?
if( expected_version == this_version )
{
- l_err = readSIOReg(0x2d, uart_config);
-
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(uart_config),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, 0x2d));
if (l_err) { break; }
// determine which config has been selected
diff --git a/src/usr/initservice/bootconfig/bootconfig_ast2400.C b/src/usr/initservice/bootconfig/bootconfig_ast2400.C
index 56f6c8500..25eba8685 100644
--- a/src/usr/initservice/bootconfig/bootconfig_ast2400.C
+++ b/src/usr/initservice/bootconfig/bootconfig_ast2400.C
@@ -26,6 +26,7 @@
// Includes
/******************************************************************************/
#include "bootconfig_ast2400.H"
+
#include <lpc/lpcif.H>
#include <devicefw/userif.H>
#include <errl/errlentry.H>
@@ -33,6 +34,8 @@
#include <hwas/common/deconfigGard.H>
#include <console/consoleif.H>
#include <config.h>
+#include <sio/sio.H>
+#include <devicefw/driverif.H>
namespace INITSERVICE
{
@@ -181,22 +184,21 @@ errlHndl_t AST2400BootConfig::readAndProcessBootConfig()
errlHndl_t l_err = NULL;
uint8_t register_data = 0;
-
- do{
-
- l_err = unlockSIORegisters();
-
- if(l_err)
- {
- TRACFCOMP(g_bc_trace, "readAndProcessBootConfig()"
- " call to unlock SIO registers failed");
- break;
- }
-
+ size_t l_len = sizeof(uint8_t);
+ do
+ {
// read the register holding the agreed upon magic
// number to indicate registers have been configured
- l_err = readSIORegister( BOOT_FLAGS_VERSION_REG, register_data );
+ // Registers below 0x30 do not belong to any particular SIO device.
+ // Device field advised to be set to SUART1 or iLPC2AHB as these are the
+ // only two devices currently in use and will thereby save additional
+ // SIO before and after this call.
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(register_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::DONT_CARE, BOOT_FLAGS_VERSION_REG));
if( l_err )
{
TRACFCOMP(g_bc_trace,"Failed reading the boot flags version, skip processing");
@@ -219,8 +221,11 @@ errlHndl_t AST2400BootConfig::readAndProcessBootConfig()
}
// read the SIO register holding the boot flags
- l_err = readSIORegister( BOOT_FLAGS_REG, register_data );
-
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(register_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::DONT_CARE, BOOT_FLAGS_REG));
if( l_err )
{
TRACFCOMP(g_bc_trace,"Failed reading the boot flags, leave"
@@ -233,9 +238,6 @@ errlHndl_t AST2400BootConfig::readAndProcessBootConfig()
}while(0);
- // leave SIO registers unlocked, pnor code is dependant on
- // having access to them
-
TRACDCOMP(g_bc_trace, EXIT_MRK"readAndProcessBootConfig()");
return l_err;
@@ -259,20 +261,31 @@ void AST2400BootConfig::processBootFlagsV1( uint8_t i_flags )
errlHndl_t AST2400BootConfig::readIstepControl( istepControl_t &o_stepInfo )
{
errlHndl_t l_err = NULL;
-
+ size_t l_len = sizeof(uint8_t);
do
{
// read istep control from 0x2a
- l_err = readSIORegister( ISTEP_CONTROL_REG, o_stepInfo.istepControl );
-
- if(l_err) break;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(o_stepInfo.istepControl),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_CONTROL_REG));
+ if(l_err) { break; }
// read major number from 0x2b
- l_err = readSIORegister( ISTEP_MAJOR_REG, o_stepInfo.istepMajorNumber );
- if(l_err) break;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(o_stepInfo.istepMajorNumber),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_MAJOR_REG));
+ if(l_err) { break; }
// read minor number from 0x2c
- l_err = readSIORegister( ISTEP_MINOR_REG, o_stepInfo.istepMinorNumber );
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(o_stepInfo.istepMinorNumber),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::DONT_CARE, ISTEP_MINOR_REG));
}
while(0);
@@ -280,115 +293,5 @@ errlHndl_t AST2400BootConfig::readIstepControl( istepControl_t &o_stepInfo )
}
-// $TODO RTC:115576 remove these functions
-errlHndl_t AST2400BootConfig::readSIORegister( uint8_t i_addr,
- uint8_t &o_data )
-{
-
- errlHndl_t l_err = NULL;
-
- o_data = 0;
-
- size_t length = sizeof(o_data);
-
- // write the value of the read register
- l_err = deviceWrite( TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &i_addr,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO_ADDR_REG));
-
- if( l_err == NULL )
- {
-
- // get the register contents.
- l_err = deviceRead(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- (void *)&o_data,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO_DATA_REG));
- }
-
- return l_err;
-
-}
-
-// $TODO RTC:115576 remove these function
-errlHndl_t AST2400BootConfig::writeSIORegister( uint8_t i_addr,
- uint8_t i_data )
-{
-
- size_t length = sizeof(i_data);
-
- errlHndl_t l_err = NULL;
-
- l_err = deviceWrite(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &i_addr,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO_ADDR_REG ));
-
- if( l_err == NULL )
- {
- l_err = deviceWrite(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &i_data,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO_DATA_REG ));
- }
-
- return l_err;
-}
-
-// $TODO RTC:115576 remove these function
-errlHndl_t AST2400BootConfig::unlockSIORegisters()
-{
- errlHndl_t l_err = NULL;
- uint8_t key = SIO_REG_UNLOCK_KEY;
- size_t length = sizeof(key);
-
- do {
-
- // Write out the register address
- l_err = deviceWrite(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &key,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_REG) );
-
- if(l_err) break;
-
- // Write out the register address
- l_err = deviceWrite(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &key,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_REG) );
-
- }while(0);
-
- return l_err;
-}
-
-// $TODO RTC:115576 remove these function
-void AST2400BootConfig::lockSIORegisters()
-{
- // write the data to lock it back up..
- uint8_t key = SIO_REG_LOCK_KEY;
- size_t length = sizeof(uint8_t);
-
- // Write out the register address
- errlHndl_t l_err = deviceWrite(
- TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
- &key,
- length,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_REG) );
-
- if(l_err)
- {
- TRACFCOMP(g_bc_trace, "FAILED locking SIO registers");
- errlCommit(l_err, ISTEP_COMP_ID);
- }
-}
-
};
};
diff --git a/src/usr/initservice/bootconfig/bootconfig_ast2400.H b/src/usr/initservice/bootconfig/bootconfig_ast2400.H
index 68c46149f..d11ae2c26 100644
--- a/src/usr/initservice/bootconfig/bootconfig_ast2400.H
+++ b/src/usr/initservice/bootconfig/bootconfig_ast2400.H
@@ -191,39 +191,6 @@ public:
*/
void processBootFlagsV1( uint8_t i_flags );
- // $TODO RTC:115576 remove these temporary SIO related functions
- /**
- * @brief read a byte from an SIO register
- *
- * @param[i] i_addr - address of SIO register to read
- * @param[o] o_data - SIO register contents
- *
- * @return errlHndl_t
- */
- errlHndl_t readSIORegister( uint8_t i_addr, uint8_t &register_value );
-
- /**
- * @brief Write a byte to an SIO register
- *
- * @param[i] i_addr - address of SIO register to write
- * @param[i] i_data - SIO register contents
- *
- * @return errlHndl_t
- */
- errlHndl_t writeSIORegister( uint8_t i_addr, uint8_t i_data );
-
- /**
- * @brief Allow read/write access to the SIO registers
- *
- * @return errlHndl_t
- */
- errlHndl_t unlockSIORegisters();
-
- /**
- * @brief Lock the SIO registers
- */
- void lockSIORegisters();
-
};
};
diff --git a/src/usr/makefile b/src/usr/makefile
index a56abd3f7..d71b4b73c 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2010,2014
+# Contributors Listed Below - COPYRIGHT 2010,2015
# [+] Google Inc.
# [+] International Business Machines Corp.
#
@@ -29,6 +29,7 @@ ROOTPATH = ../..
HOSTBOOT_PROFILE_NO_INSTRUMENT = 1
OBJS += module_init.o
+SUBDIRS += sio.d
SUBDIRS += trace.d
SUBDIRS += cxxtest.d
SUBDIRS += testcore.d
diff --git a/src/usr/pnor/sfc_ast2400.C b/src/usr/pnor/sfc_ast2400.C
index 8ceb391cc..14d01bfba 100644
--- a/src/usr/pnor/sfc_ast2400.C
+++ b/src/usr/pnor/sfc_ast2400.C
@@ -26,6 +26,7 @@
/*****************************************************************************/
// I n c l u d e s
/*****************************************************************************/
+#include <sio/sio.H>
#include <sys/mmio.h>
#include <sys/task.h>
#include <sys/sync.h>
@@ -50,22 +51,16 @@
/*****************************************************************************/
-
-
/*****************************************************************************/
// G l o b a l s
/*****************************************************************************/
// Initialized in pnorrp.C
extern trace_desc_t* g_trac_pnor;
-
/*****************************************************************************/
// M e t h o d s
/*****************************************************************************/
-
-
namespace PNOR {
-
/**
* @brief Wrapper for device driver constructor
*/
@@ -89,7 +84,6 @@ SfcAST2400::SfcAST2400( errlHndl_t& o_err,
{
}
-
/**
* @brief Read data from the flash
*/
@@ -99,8 +93,8 @@ errlHndl_t SfcAST2400::readFlash( uint32_t i_addr,
{
errlHndl_t l_err = NULL;
TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::readFlash> i_addr=0x%.8x, i_size=0x%.8x", i_addr, i_size );
-
- do{
+ do
+ {
uint32_t* word_ptr = static_cast<uint32_t*>(o_data);
uint32_t word_size = (ALIGN_4(i_size))/4;
for( uint32_t words_read = 0;
@@ -120,8 +114,8 @@ errlHndl_t SfcAST2400::readFlash( uint32_t i_addr,
lpc_addr) );
if( l_err ) { break; }
}
- if( l_err ) { break; }
- }while(0);
+ if( l_err ) { break; }
+ } while(0);
TRACDCOMP( g_trac_pnor, EXIT_MRK"SfcAST2400::readFlash> err=%.8X", ERRL_GETEID_SAFE(l_err) );
return l_err;
@@ -228,6 +222,28 @@ errlHndl_t SfcAST2400::eraseFlash( uint32_t i_addr )
return l_err;
}
+//function to call SIO dd for ahb sio read
+errlHndl_t ahbSioReadWrapper(uint32_t i_ahb_sio_data, uint32_t i_lpc_addr)
+{
+ size_t l_ahb_sio_len = sizeof(i_ahb_sio_data);
+ return deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(i_ahb_sio_data),
+ l_ahb_sio_len,
+ DEVICE_AHB_SIO_ADDRESS(i_lpc_addr));
+}
+
+//function to call SIO dd for ahb sio write
+errlHndl_t ahbSioWriteWrapper(uint32_t i_ahb_sio_data, uint32_t i_lpc_addr)
+{
+ size_t l_ahb_sio_len = sizeof(i_ahb_sio_data);
+ return deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(i_ahb_sio_data),
+ l_ahb_sio_len,
+ DEVICE_AHB_SIO_ADDRESS(i_lpc_addr));
+}
+
/**
* @brief Initialize and configure the SFC hardware
*/
@@ -235,55 +251,38 @@ errlHndl_t SfcAST2400::hwInit( )
{
TRACFCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::hwInit>" );
errlHndl_t l_err = NULL;
-
- do {
- size_t reg_size = sizeof(uint8_t);
-
- //** Initialize the LPC2AHB logic
-
- // Send SuperIO password - send A5 twice
- uint8_t data = 0xA5;
- l_err = deviceOp( DeviceFW::WRITE,
- iv_proc,
- &data,
- reg_size,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_2E) );
- if( l_err ) { break; }
-
+ uint32_t l_lpc_addr;
+ do
+ {
+ /* Enable device 0x0D*/
+ uint8_t l_data = SIO::ENABLE_DEVICE;
+ size_t l_len = sizeof(l_data);
l_err = deviceOp( DeviceFW::WRITE,
- iv_proc,
- &data,
- reg_size,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_2E) );
- if( l_err ) { break; }
-
-
- // Select logical device D (iLPC2AHB)
- l_err = writeRegSIO( 0x07, 0x0D );
- if( l_err ) { break; }
-
-
- // Enable iLPC->AHB
- l_err = writeRegSIO( 0x30, 0x01 );
- if( l_err ) { break; }
-
-
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ (&l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::iLPC2AHB,0x30));
+ if(l_err) { break; }
//** Setup the SPI Controller
/* Enable writing to the controller */
SpiControlReg04_t ctlreg;
- l_err = readRegSPIC( CTLREG_04, ctlreg.data32 );
+ l_lpc_addr = CTLREG_04 | SPIC_BASE_ADDR_AHB;
+ l_err = ahbSioReadWrapper(ctlreg.data32, l_lpc_addr);
if( l_err ) { break; }
+
ctlreg.cmdMode = 0b10; //10:Normal Write (CMD + Address + Write data)
- l_err = writeRegSPIC( CTLREG_04, ctlreg.data32 );
+ l_err = ahbSioWriteWrapper(ctlreg.data32, l_lpc_addr);
if( l_err ) { break; }
SpiConfigReg00_t confreg;
- l_err = readRegSPIC( CONFREG_00, confreg.data32 );
+ l_lpc_addr = CONFREG_00 | SPIC_BASE_ADDR_AHB;
+ l_err = ahbSioReadWrapper(confreg.data32, l_lpc_addr);
if( l_err ) { break; }
+
confreg.inactiveX2mode = 1; //Enable CE# Inactive pulse width X2 mode
confreg.enableWrite = 1; //Enable flash memory write
- l_err = writeRegSPIC( CONFREG_00, confreg.data32 );
+ l_err = ahbSioWriteWrapper(confreg.data32, l_lpc_addr);
if( l_err ) { break; }
@@ -305,7 +304,8 @@ errlHndl_t SfcAST2400::hwInit( )
iv_ctlRegDefault = ctlreg; // Default setup is regular read mode
// Configure for read
- l_err = writeRegSPIC( CTLREG_04, ctlreg.data32 );
+ l_lpc_addr = CTLREG_04 | SPIC_BASE_ADDR_AHB;
+ l_err = ahbSioWriteWrapper(ctlreg.data32, l_lpc_addr);
if( l_err ) { break; }
// Figure out what flash chip we have
@@ -482,6 +482,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode,
errlHndl_t SfcAST2400::commandMode( bool i_enter )
{
errlHndl_t l_err = NULL;
+ uint32_t l_lpc_addr;
TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::commandMode(%d)", i_enter );
/*
@@ -503,20 +504,21 @@ errlHndl_t SfcAST2400::commandMode( bool i_enter )
// Switch to user mode, CE# dropped
ctlreg.stopActiveCtl = 1;
ctlreg.cmdMode = 0b11; //User Mode (Read/Write Data)
- l_err = writeRegSPIC( CTLREG_04, ctlreg.data32 );
+ l_lpc_addr = CTLREG_04 | SPIC_BASE_ADDR_AHB;
+ l_err = ahbSioWriteWrapper(ctlreg.data32, l_lpc_addr);
if( l_err ) { break; }
if( i_enter ) //ast_sf_start_cmd
{
// user mode, CE# active
ctlreg.stopActiveCtl = 0;
- l_err = writeRegSPIC( CTLREG_04, ctlreg.data32 );
+ l_err = ahbSioWriteWrapper(ctlreg.data32, l_lpc_addr);
if( l_err ) { break; }
}
else //ast_sf_end_cmd
{
// Switch back to read mode
- l_err = writeRegSPIC( CTLREG_04, iv_ctlRegDefault.data32 );
+ l_err = ahbSioWriteWrapper(iv_ctlRegDefault.data32, l_lpc_addr);
if( l_err ) { break; }
}
} while(0);
@@ -587,187 +589,6 @@ errlHndl_t SfcAST2400::enableWriteMode( void )
}
/**
- * @brief Write a single byte into the SIO
- */
-errlHndl_t SfcAST2400::writeRegSIO( uint8_t i_regAddr,
- uint8_t i_data )
-{ //lpc_sio_outb
- errlHndl_t l_err = NULL;
- TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::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 = deviceOp( DeviceFW::WRITE,
- iv_proc,
- &i_regAddr,
- reg_size,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_2E) );
- if( l_err ) { break; }
-
- // Write out the register data
- l_err = deviceOp( DeviceFW::WRITE,
- iv_proc,
- &i_data,
- reg_size,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_DATA_2F) );
- if( l_err ) { break; }
-
- } while(0);
-
- TRACDCOMP( g_trac_pnor, EXIT_MRK"SfcAST2400::writeRegSIO> err=%.8X", ERRL_GETEID_SAFE(l_err) );
- return l_err;
-}
-
-/**
- * @brief Read a single byte from the SIO
- */
-errlHndl_t SfcAST2400::readRegSIO( uint8_t i_regAddr,
- uint8_t& o_data )
-{ //lpc_sio_inb
- errlHndl_t l_err = NULL;
- TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::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 = deviceOp( DeviceFW::WRITE,
- iv_proc,
- &i_regAddr,
- reg_size,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_ADDR_2E) );
- if( l_err ) { break; }
-
- // Read in the register data
- l_err = deviceOp( DeviceFW::READ,
- iv_proc,
- &o_data,
- reg_size,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO,SIO_DATA_2F) );
- if( l_err ) { break; }
-
- } while(0);
-
- TRACDCOMP( g_trac_pnor, EXIT_MRK"SfcAST2400::readRegSIO> o_data=0x%.2X, err-%.8X", o_data, ERRL_GETEID_SAFE(l_err) );
- return l_err;
-}
-
-/**
- * @brief Prepare the iLPC2AHB address regs
- */
-errlHndl_t SfcAST2400::setupAddrLPC2AHB( uint32_t i_addr )
-{ //lpc_ahb_prep
- errlHndl_t l_err = NULL;
- TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::setupAddrLPC2AHB> i_addr=0x%X", i_addr );
-
- do {
- // Select logical device D (iLPC2AHB)
- l_err = writeRegSIO( 0x07, 0x0D );
- if( l_err ) { break; }
-
- // Push 4 address bytes into SIO regs 0xF0-0xF3
- for( size_t i=sizeof(i_addr); i>0; i-- )
- {
- l_err = writeRegSIO( 0xF3-(i-1), //F0,F1,F2,F3
- static_cast<uint8_t>(i_addr >> ((i-1)*8)) );
- if( l_err ) { break; }
- }
- if( l_err ) { break; }
-
- // Configure 4 byte length
- l_err = writeRegSIO( 0xF8, 0x02 );
- if( l_err ) { break; }
-
- } while(0);
-
- TRACDCOMP( g_trac_pnor, EXIT_MRK"SfcAST2400::setupAddrLPC2AHB> err=%.8X", ERRL_GETEID_SAFE(l_err) );
- return l_err;
-}
-
-/**
- * @brief Write SPI Controller Register
- */
-errlHndl_t SfcAST2400::writeRegSPIC( SpicReg_t i_reg,
- uint32_t i_data )
-{
- errlHndl_t l_err = NULL;
- TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::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( lpc_addr );
- if( l_err ) { break; }
-
- // Push 4 data bytes into SIO regs 0xF4-0xF7
- uint8_t* ptr8 = reinterpret_cast<uint8_t*>(&i_data);
- for( size_t i=0; i<sizeof(i_data); i++ )
- {
- l_err = writeRegSIO( 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( 0xFE, 0xCF );
- if( l_err ) { break; }
-
- } while(0);
-
- TRACDCOMP( g_trac_pnor, EXIT_MRK"SfcAST2400::writeRegSPIC> err=%.8X", ERRL_GETEID_SAFE(l_err) );
- return l_err;
-}
-
-/**
- * @brief Read SPI Controller Register
- */
-errlHndl_t SfcAST2400::readRegSPIC( SpicReg_t i_reg,
- uint32_t& o_data )
-{
- TRACDCOMP( g_trac_pnor, ENTER_MRK"SfcAST2400::readRegSPIC> i_reg=0x%.2X", i_reg );
- errlHndl_t l_err = NULL;
-
- 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( lpc_addr );
- if( l_err ) { break; }
-
- // Trigger the write operation by reading the magic register
- uint8_t ignored = 0;
- l_err = readRegSIO( 0xFE, ignored );
- if( l_err ) { break; }
-
- // Read 4 data bytes into SIO regs 0xF4-0xF7
- uint8_t* ptr8 = reinterpret_cast<uint8_t*>(&o_data);
- for( size_t i=0; i<sizeof(o_data); i++ )
- {
- l_err = readRegSIO( 0xF4+i, //F4,F5,F6,F7
- ptr8[i] );
- if( l_err ) { break; }
- }
- if( l_err ) { break; }
-
- } while(0);
-
- TRACDCOMP( g_trac_pnor, EXIT_MRK"SfcAST2400::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
*/
errlHndl_t SfcAST2400::pollOpComplete( void )
diff --git a/src/usr/pnor/sfc_ast2400.H b/src/usr/pnor/sfc_ast2400.H
index 79d18c1ba..28719425e 100644
--- a/src/usr/pnor/sfc_ast2400.H
+++ b/src/usr/pnor/sfc_ast2400.H
@@ -138,50 +138,6 @@ class SfcAST2400 : public SfcDD
};
/**
- * @brief Write a SPI Controller register
- *
- * @param[in] i_reg: Register to write
- * @param[in] i_data: Data to write
- *
- * @return Error from operation
- */
- errlHndl_t writeRegSPIC( SpicReg_t i_reg,
- uint32_t i_data );
-
- /**
- * @brief Write a SPI Controller register
- *
- * @param[in] i_reg: Register to write
- * @param[in] o_data: Data that was read
- *
- * @return Error from operation
- */
- errlHndl_t readRegSPIC( SpicReg_t i_reg,
- uint32_t& o_data );
-
- /**
- * @brief Write a single byte into a SIO register
- *
- * @param[in] i_reg: Register to write
- * @param[in] i_data: Data to write
- *
- * @return Error from operation
- */
- errlHndl_t writeRegSIO( uint8_t i_regAddr,
- uint8_t i_data );
-
- /**
- * @brief Read a single byte from a SIO register
- *
- * @param[in] i_reg: Register to read
- * @param[in] o_data: Data that was read
- *
- * @return Error from operation
- */
- errlHndl_t readRegSIO( uint8_t i_regAddr,
- uint8_t& o_data );
-
- /**
* @brief Enable write mode
*
* @return Error from operation
diff --git a/src/usr/pnor/test/sfc_ast2400test.H b/src/usr/pnor/test/sfc_ast2400test.H
index 4dc69e68e..70e0d340b 100644
--- a/src/usr/pnor/test/sfc_ast2400test.H
+++ b/src/usr/pnor/test/sfc_ast2400test.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -42,6 +42,7 @@
#include <targeting/common/attributes.H>
#include <lpc/lpcif.H>
#include "../sfc_ast2400.H"
+#include <sio/sio.H>
extern trace_desc_t* g_trac_pnor;
@@ -92,8 +93,8 @@ class SfcAST2400Test : public CxxTest::TestSuite
section_found = true;
}while(0);
-
return section_found;
+
}
/**
@@ -167,139 +168,6 @@ class SfcAST2400Test : public CxxTest::TestSuite
}
}
- /**
- * @brief Test SIO access
- * Use a SIO scratch register to verify reads and writes
- */
- void test_SIO(void)
- {
- SfcAST2400* sfc = reinterpret_cast<SfcAST2400*>(
- Singleton<PnorDD>::instance().iv_sfc );
- errlHndl_t l_err = NULL;
-
- // Read SIO to BMC scratch reg 1,2 and save off values
- uint8_t scratch1 = 0;
- l_err = sfc->readRegSIO( 0x21, scratch1 );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> readRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
- uint8_t scratch2 = 0;
- l_err = sfc->readRegSIO( 0x22, scratch2 );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> readRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
-
- // Write test patterns into registers
- uint8_t testdata = 0xA5;
- l_err = sfc->writeRegSIO( 0x21, testdata );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> writeRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
- testdata = 0x12;
- l_err = sfc->writeRegSIO( 0x22, testdata );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> writeRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
-
- // Read the data back and compare to expected results
- l_err = sfc->readRegSIO( 0x21, testdata );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> readRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
- if( testdata != 0xA5 )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> Data mismatch on SIO 0x21 : Exp=0xA5, Act=%.2X", testdata);
- }
- l_err = sfc->readRegSIO( 0x22, testdata );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> readRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
- if( testdata != 0x12 )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> Data mismatch on SIO 0x22 : Exp=0x12, Act=%.2X", testdata);
- }
-
- // Restore the original data
- l_err = sfc->writeRegSIO( 0x21, scratch1 );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> writeRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
- l_err = sfc->writeRegSIO( 0x22, scratch2 );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SIO> writeRegSIO failed");
- errlCommit(l_err,PNOR_COMP_ID);
- }
- }
-
- /**
- * @brief Test SPIC access
- * Read and write data to the SPI Control register
- */
- void test_SPIC( void )
- {
- SfcAST2400* sfc = reinterpret_cast<SfcAST2400*>(
- Singleton<PnorDD>::instance().iv_sfc );
- mutex_t* l_mutex = Singleton<PnorDD>::instance().iv_mutex_ptr;
- errlHndl_t l_err = NULL;
-
- mutex_lock(l_mutex);
-
- uint32_t first = 0;
- l_err = sfc->readRegSPIC( SfcAST2400::CTLREG_04, first );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SPIC> readRegSIO failed");
- mutex_unlock(l_mutex);//unlock before commit
- errlCommit(l_err,PNOR_COMP_ID);
- mutex_lock(l_mutex);//lock again for next op
- }
- uint32_t data1 = 0x12345678;
- l_err = sfc->writeRegSPIC( SfcAST2400::CTLREG_04, data1 );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SPIC> readRegSIO failed");
- mutex_unlock(l_mutex);//unlock before commit
- errlCommit(l_err,PNOR_COMP_ID);
- mutex_lock(l_mutex);//lock again for next op
- }
- l_err = sfc->readRegSPIC( SfcAST2400::CTLREG_04, data1 );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SPIC> readRegSIO failed");
- mutex_unlock(l_mutex);//unlock before commit
- errlCommit(l_err,PNOR_COMP_ID);
- mutex_lock(l_mutex);//lock again for next op
- }
- if( data1 != 0x12345678 )
- {
- TS_FAIL("SfcAST2400Test::test_SPIC> Unexpected result of %.8X (exp 0x12345678)",data1);
- }
- //put back the original
- l_err = sfc->writeRegSPIC( SfcAST2400::CTLREG_04, first );
- if( l_err )
- {
- TS_FAIL("SfcAST2400Test::test_SPIC> readRegSIO failed");
- mutex_unlock(l_mutex);//unlock before commit
- errlCommit(l_err,PNOR_COMP_ID);
- }
-
- mutex_unlock(l_mutex);
- }
};
#endif
diff --git a/src/usr/sio/HBconfig b/src/usr/sio/HBconfig
new file mode 100644
index 000000000..69a2f0b1c
--- /dev/null
+++ b/src/usr/sio/HBconfig
@@ -0,0 +1,4 @@
+config AST2400
+ default y if (BMC_AST2400 || SFC_IS_AST2400)
+ help
+ Enables superIO driver.
diff --git a/src/usr/sio/makefile b/src/usr/sio/makefile
new file mode 100755
index 000000000..2b751162c
--- /dev/null
+++ b/src/usr/sio/makefile
@@ -0,0 +1,33 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/sio/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2014,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
+
+ROOTPATH = ../../..
+MODULE = sio
+
+SUBDIRS += test.d
+OBJS += siodd.o
+
+include $(ROOTPATH)/config.mk
+
diff --git a/src/usr/sio/siodd.C b/src/usr/sio/siodd.C
new file mode 100755
index 000000000..5301d9e1c
--- /dev/null
+++ b/src/usr/sio/siodd.C
@@ -0,0 +1,434 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sio/siodd.C $ */
+/* */
+/* OpenPOWER HostBoot 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 */
+#include <sio/sio.H>
+#include "siodd.H"
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <trace/interface.H>
+#include <sys/sync.h>
+#include <devicefw/userif.H>
+#include <lpc/lpcif.H>
+#include <kernel/console.H>
+#include <devicefw/driverif.H>
+#include <initservice/bootconfigif.H>
+#include <sys/time.h>
+#include <hbotcompid.H>
+#include <stdarg.h>
+#include <targeting/common/target.H>
+
+// Trace definition
+trace_desc_t* g_trac_sio = NULL;
+TRAC_INIT(&g_trac_sio, SIO_COMP_NAME, 2*KILOBYTE, TRACE::BUFFER_SLOW); //2K
+
+/**
+ * This function performs an SIO Read operation. It follows a pre-defined
+ * prototype functions in order to be registered with the device-driver
+ * framework.
+ *
+ * @param[in] i_opTypeOperation type, see DeviceFW::OperationType in
+ * driverif.H
+ * @param[in] i_targetSIO target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessTypeDeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * @return errlHndl_t
+ */
+errlHndl_t SIORead(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType, va_list i_args)
+{
+ assert(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ errlHndl_t l_err = NULL;
+ uint8_t l_dev = va_arg(i_args,uint64_t);
+ uint8_t l_addr = va_arg(i_args,uint64_t);
+ l_err = Singleton<SioDD>::instance().readSIO(i_target, l_dev, l_addr,
+ static_cast<uint8_t*>(io_buffer));
+ return l_err;
+}
+
+/**
+ * This function performs an SIO Write operation. It follows a pre-defined
+ * prototype functions in order to be registered with the device-driver
+ * framework.
+ *
+ * param[in] i_opType Operation type, see DeviceFW::OperationType in
+ * driverif.H
+ * @param[in] i_targetSIO target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessTypeDeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * @return errlHndl_t
+ */
+errlHndl_t SIOWrite(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ assert(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ errlHndl_t l_err = NULL;
+ uint8_t l_dev = va_arg(i_args,uint64_t);
+ uint8_t l_addr = va_arg(i_args,uint64_t);
+ l_err = Singleton<SioDD>::instance().writeSIO(i_target, l_dev, l_addr,
+ static_cast<uint8_t*>(io_buffer));
+ return l_err;
+}
+
+/**
+ * This function performs an LPC to AHB read operation using superIO accesses.
+ * It follows a pre-defined prototype functions in order to be registered
+ * with the device-driver framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType in
+ * driverif.H
+ * @param[in] i_targetSIO target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessTypeDeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * @return errlHndl_t
+ */
+errlHndl_t ahbSioReadDD(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ assert(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ errlHndl_t l_err = NULL;
+ uint32_t l_reg = va_arg(i_args,uint64_t);
+ l_err = Singleton<SioDD>::instance().ahbSioRead(i_target, l_reg,
+ static_cast<uint32_t*>(io_buffer));
+ return l_err;
+}
+
+/**
+ * This function performs an LPC to AHB read operation using superIO accesses.
+ * It follows a pre-defined prototype functions in order to be registered
+ * with the device-driver framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType in
+ * driverif.H
+ * @param[in] i_targetSIO target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessTypeDeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * @return errlHndl_t
+ */
+errlHndl_t ahbSioWriteDD(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ assert(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ errlHndl_t l_err = NULL;
+ uint32_t l_reg = va_arg(i_args,uint64_t);
+ l_err = Singleton<SioDD>::instance().ahbSioWrite(i_target, l_reg,
+ static_cast<uint32_t*>(io_buffer));
+ return l_err;
+}
+
+// Register SIO access functions to DD framework
+DEVICE_REGISTER_ROUTE( DeviceFW::READ,
+ DeviceFW::SIO,
+ TARGETING::TYPE_PROC,
+ SIORead );
+DEVICE_REGISTER_ROUTE( DeviceFW::WRITE,
+ DeviceFW::SIO,
+ TARGETING::TYPE_PROC,
+ SIOWrite );
+
+// Register AHB_SIO access functions to DD framework
+DEVICE_REGISTER_ROUTE( DeviceFW::READ,
+ DeviceFW::AHB_SIO,
+ TARGETING::TYPE_PROC,
+ ahbSioReadDD );
+DEVICE_REGISTER_ROUTE( DeviceFW::WRITE,
+ DeviceFW::AHB_SIO,
+ TARGETING::TYPE_PROC,
+ ahbSioWriteDD );
+
+//function to unlock superIO password register
+void SioDD::unlock_SIO(TARGETING::Target* i_target)
+{
+ uint8_t l_byte = SIO::SIO_PASSWORD_REG;
+ errlHndl_t l_err = NULL;
+ do
+ {
+ // Unlock the SIO registers
+ // (write 0xA5 password to offset 0x2E two times)
+ size_t l_len = sizeof(uint8_t);
+ l_err = deviceWrite(i_target,
+ &l_byte,
+ l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_ADDR_REG_2E));
+ if(l_err) { break; }
+ l_err = deviceWrite(i_target,
+ &l_byte,
+ l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_ADDR_REG_2E));
+ } while(0);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_sio,"Error in unlocking SIO password register\n");
+ errlCommit(l_err, SIO_COMP_ID);
+ }
+}
+
+//SioDD constructor
+SioDD::SioDD(TARGETING::Target* i_target)
+{
+ assert(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+ mutex_init(&iv_sio_mutex);
+ iv_prev_dev = 0x00;
+ unlock_SIO(i_target);
+}
+
+//SioDD destructor
+SioDD::~SioDD()
+{
+ mutex_destroy(&iv_sio_mutex);
+}
+
+//internal write function
+errlHndl_t SioDD::_writeSIO(TARGETING::Target* i_target,
+ uint8_t i_reg, uint8_t* i_data)
+{
+ errlHndl_t l_err = NULL;
+ do
+ {
+ size_t l_len = sizeof(uint8_t);
+ l_err = deviceWrite(i_target,
+ &i_reg,
+ l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_ADDR_REG_2E));
+ if(l_err) { break; }
+ l_err = deviceWrite(i_target,
+ i_data,
+ l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_DATA_REG_2F));
+ } while(0);
+ return l_err;
+}
+
+//internal read function
+errlHndl_t SioDD::_readSIO(TARGETING::Target* i_target,
+ uint8_t i_reg, uint8_t* o_byte)
+{
+ errlHndl_t l_err = NULL;
+ size_t l_len = sizeof(uint8_t);
+ do
+ {
+ l_err = deviceWrite(i_target,
+ &i_reg,
+ l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_ADDR_REG_2E));
+ if(l_err) { break; }
+ l_err = deviceRead(i_target,
+ o_byte,
+ l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_DATA_REG_2F));
+ } while(0);
+ return l_err;
+}
+
+//function to change logical device in SIO
+errlHndl_t SioDD::changeDevice(TARGETING::Target* i_target, uint8_t i_dev)
+{
+ uint8_t l_reg = SIO::SIO_DEVICE_SELECT_REG;
+ return _writeSIO(i_target, l_reg, &i_dev);
+}
+
+//function to read from SIO register
+errlHndl_t SioDD::readSIO(TARGETING::Target* i_target, uint8_t i_dev,
+ uint8_t i_reg, uint8_t* o_byte)
+{
+ mutex_lock(&iv_sio_mutex);
+ errlHndl_t l_err = NULL;
+
+ if(iv_prev_dev!=i_dev)
+ {
+ l_err = changeDevice(i_target, i_dev);
+ if(!l_err)
+ {
+ iv_prev_dev = i_dev;
+ l_err = _readSIO(i_target, i_reg, o_byte);
+ }
+ }
+ else
+ {
+ l_err = _readSIO(i_target, i_reg, o_byte);
+ }
+ mutex_unlock(&iv_sio_mutex);
+ return l_err;
+}
+
+
+//function to write to SIO register
+errlHndl_t SioDD::writeSIO(TARGETING::Target* i_target,
+ uint8_t i_dev, uint8_t i_reg, uint8_t* i_data)
+{
+ mutex_lock(&iv_sio_mutex);
+ errlHndl_t l_err = NULL;
+ if(iv_prev_dev!=i_dev)
+ {
+ l_err = changeDevice(i_target, i_dev);
+ if(!l_err)
+ {
+ iv_prev_dev = i_dev;
+ l_err = _writeSIO(i_target, i_reg, i_data);
+ }
+ }
+ else
+ {
+ l_err = _writeSIO(i_target, i_reg, i_data);
+ }
+ mutex_unlock(&iv_sio_mutex);
+ return l_err;
+}
+
+//function to translate address from LPC to AHB space
+errlHndl_t SioDD::_ahbSioAddrPrep(TARGETING::Target* i_target,
+ uint32_t i_addr)
+{
+ errlHndl_t l_err = NULL;
+ uint8_t l_dev = SIO::iLPC2AHB;
+ uint8_t l_data;
+ do
+ {
+ //select device 0x0D
+ l_err = changeDevice(i_target, l_dev);
+ if(l_err) { break; }
+
+ //write to f0-f3
+ for (size_t i = sizeof(i_addr); i>0; i--)
+ {
+ l_data = i_addr>>((i-1)*8);
+ l_err = _writeSIO(i_target, (0xF3-(i-1)), &l_data);
+ if( l_err ) { break; }
+ }
+
+ //byte length
+ l_data = SIO::SIO_iLPC2AHB_LENGTH;
+ l_err = _writeSIO(i_target, 0xF8, &l_data);
+ if( l_err ) { break; }
+ }
+ while(0);
+ return l_err;
+}
+
+errlHndl_t SioDD::_ahbSioRead(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* o_data)
+{
+ errlHndl_t l_err = NULL;
+ uint8_t tmp_data = 0;
+ do
+ {
+ l_err = _ahbSioAddrPrep(i_target, i_reg);
+ if( l_err ) { break; }
+
+ //trigger operation by reading from 0xFE
+ l_err = _readSIO(i_target, 0xFE, &tmp_data);
+ if( l_err ) { break; }
+ uint8_t* ptr8 = (uint8_t*)(o_data);
+ for( size_t i=0; i<sizeof(uint32_t); i++ )
+ {
+ l_err = _readSIO(i_target, 0xF4+i, &ptr8[i]);
+ if(l_err) { break; }
+ }
+ }
+ while(0);
+ return l_err;
+}
+
+errlHndl_t SioDD::_ahbSioWrite(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* i_val)
+{
+ errlHndl_t l_err = NULL;
+ uint8_t l_data;
+ do
+ {
+ l_err = _ahbSioAddrPrep(i_target, i_reg);
+ if( l_err ) { break; }
+
+ uint8_t* ptr8 = reinterpret_cast<uint8_t*>(i_val);
+ for (size_t i = 0; i<sizeof(uint32_t); i++)
+ {
+ l_err = _writeSIO(i_target, (0xF4+i), &ptr8[i]);
+ if( l_err ) { break; }
+ }
+ //trigger operation by writing to 0xFE
+ l_data = 0xCF;
+ l_err = _writeSIO(i_target, 0xFE, &l_data);
+ if( l_err ) { break; }
+ }
+ while(0);
+ return l_err;
+}
+
+//function to perform AHB to SIO read
+errlHndl_t SioDD::ahbSioRead(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* o_data)
+{
+ mutex_lock(&iv_sio_mutex);
+ errlHndl_t l_err = NULL;
+ l_err = _ahbSioRead(i_target, i_reg, o_data);
+ mutex_unlock(&iv_sio_mutex);
+ return l_err;
+}
+
+//function to perform AHB to SIO write
+errlHndl_t SioDD::ahbSioWrite(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* i_val)
+{
+ mutex_lock(&iv_sio_mutex);
+ errlHndl_t l_err = NULL;
+ l_err = _ahbSioWrite(i_target, i_reg, i_val);
+ mutex_unlock(&iv_sio_mutex);
+ return l_err;
+}
+
diff --git a/src/usr/sio/siodd.H b/src/usr/sio/siodd.H
new file mode 100644
index 000000000..664935921
--- /dev/null
+++ b/src/usr/sio/siodd.H
@@ -0,0 +1,183 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sio/siodd.H $ */
+/* */
+/* OpenPOWER HostBoot 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 __SIO_SIODD_H
+#define __SIO_SIODD_H
+
+#include <limits.h>
+#include <sys/sync.h>
+#include <stdint.h>
+#include <errl/errlentry.H>
+#include <lpc/lpcif.H>
+#include <targeting/common/targetservice.H>
+
+/**
+ * class describing accesses to AST2400 BMC chip
+ */
+class SioDD
+{
+ public:
+ /** @brief Constructor
+ * @param[in] i_target: SIO target
+ */
+ SioDD(TARGETING::Target* i_target =
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+
+ /* @brief Destructor */
+ ~SioDD();
+
+ /**
+ * @brief Read a single byte from a SIO register
+ * @param[in] i_target: SIO target
+ * @param[in] i_dev: Device to read from
+ * @param[in] i_reg: Register to read
+ * @param[in] o_byte: Data that was read
+ *
+ * @return Error from operation
+ */
+ errlHndl_t readSIO(TARGETING::Target* i_target,
+ uint8_t i_dev, uint8_t i_reg, uint8_t* o_byte);
+
+ /**
+ * @brief Write a single byte into a SIO register
+ * @param[in] i_target: SIO target
+ * @param[in] i_dev: Device to write to
+ * @param[in] i_reg: Register to write
+ * @param[in] i_data: Data to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t writeSIO(TARGETING::Target* i_target,
+ uint8_t i_dev, uint8_t i_reg, uint8_t* i_data);
+
+ /**
+ * @brief AHB SIO read operation
+ * @param[in] i_target: SIO target
+ * @param[in] i_reg: Register to read
+ * @param[in] o_data: Data that was read
+ *
+ * @return Error from operation
+ */
+ errlHndl_t ahbSioRead(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* o_data);
+
+ /**
+ * @brief AHB SIO write operation
+ * @param[in] i_target: SIO target
+ * @param[in] i_reg: Register to write
+ * @param[in] i_val: Data to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t ahbSioWrite(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* i_val);
+
+ friend class SioDDTest;
+
+ private:
+ /**
+ * @brief Change device pointed to by SIO
+ * @param[in] i_target: SIO target
+ * @param[in] i_dev: Device to point to
+ *
+ * @return Error from operation
+ */
+ errlHndl_t changeDevice(TARGETING::Target* i_target,
+ uint8_t i_dev);
+
+ /**
+ * @brief Internal write function
+ * assumes mutex is locked
+ * @param[in] i_target: SIO target
+ * @param[in] i_reg: Register to write
+ * @param[in] i_data: Data to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _writeSIO(TARGETING::Target* i_target,
+ uint8_t i_reg, uint8_t* i_data);
+
+ /**
+ * @brief Internal read function
+ * assumes mutex is locked
+ * @param[in] i_target: SIO target
+ * @param[in] i_reg: Register to read
+ * @param[in] o_byte: Data that was read
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _readSIO(TARGETING::Target* i_target,
+ uint8_t i_reg, uint8_t* o_byte);
+
+ /**
+ * @brief LPC to AHB address translation
+ * @param[in] i_target: SIO target
+ * @param[in] i_addr: Address for subsequent AHB SIO read/write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _ahbSioAddrPrep(TARGETING::Target* i_target,
+ uint32_t i_addr);
+
+ /**
+ * @brief Internal write function
+ * assumes mutex is locked
+ * @param[in] i_target: SIO target
+ * @param[in] i_reg: Register to write to
+ * @param[in] i_val: Data that is to be written
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _ahbSioWrite(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* i_val);
+
+ /**
+ * @brief Internal read function
+ * assumes mutex is locked
+ * @param[in] i_target: SIO target
+ * @param[in] i_reg: Register to read from
+ * @param[in] i_val: Data that was read
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _ahbSioRead(TARGETING::Target* i_target,
+ uint32_t i_reg, uint32_t* o_data);
+
+ /**
+ * @brief Unlock SIO password register
+ * @param[in] i_target: SIO target
+ */
+ void unlock_SIO(TARGETING::Target* i_target);
+
+ /**
+ * @brief Previous device accessed by SIO
+ */
+ uint8_t iv_prev_dev;
+
+ /**
+ * @brief Mutex to prevent concurrent accesses to SIO
+ */
+ mutex_t iv_sio_mutex;
+ };
+#endif
diff --git a/src/usr/sio/test/makefile b/src/usr/sio/test/makefile
new file mode 100644
index 000000000..4337c81b1
--- /dev/null
+++ b/src/usr/sio/test/makefile
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/sio/test/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2014,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
+ROOTPATH = ../../../..
+
+MODULE = testsio
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/sio/test/sioddtest.H b/src/usr/sio/test/sioddtest.H
new file mode 100644
index 000000000..2bd91b291
--- /dev/null
+++ b/src/usr/sio/test/sioddtest.H
@@ -0,0 +1,452 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sio/test/sioddtest.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,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 __SIODDTEST_H
+#define __SIODDTEST_H
+
+/**
+ * @file sioddtest.H
+ *
+ * @brief Test case for SuperIO Driver
+*/
+#include <devicefw/driverif.H>
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <devicefw/userif.H>
+#include <sys/time.h>
+#include <list>
+#include <targeting/common/attributes.H>
+#include <sio/sio.H>
+#include "../siodd.H"
+
+const uint8_t CTLREG_04 = 0x04;
+const uint32_t SPIC_BASE_ADDR_AHB = 0x1E630000;
+class SioDDTest : public CxxTest::TestSuite
+{
+ public:
+ /**
+ * @brief Test SIO access
+ * Use a SIO scratch register to verify reads and writes
+ */
+ void test_SIO(void)
+ {
+ errlHndl_t l_err = NULL;
+ size_t l_len = sizeof(uint8_t);
+ mutex_t l_lock = Singleton<SioDD>::instance().iv_sio_mutex;
+ mutex_lock(&l_lock);
+ // Read SIO to BMC scratch reg 1,2 and save off values
+ uint8_t scratch1 = 0;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(scratch1),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG1));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ uint8_t scratch2 = 0;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(scratch2),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG2));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ // Write test patterns into registers
+ uint8_t testdata = 0xA5;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG1));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ testdata = 0x12;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG2));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ // Read the data back and compare to expected results
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG1));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ if( testdata != 0xA5 )
+ {
+ TS_FAIL("SioDDTest::test_SIO> Data mismatch on SIO 0x21\
+ : Exp=0xA5, Act=%.2X", testdata);
+ }
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG2));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ if( testdata != 0x12 )
+ {
+ TS_FAIL("SioDDTest::test_SIO> Data mismatch on SIO 0x22 :/\
+ Exp=0x12, Act=%.2X", testdata);
+ }
+
+ // Restore the original data
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(scratch1),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG1));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(scratch2),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::SUART1, SIO::SIO_SCRATCH_REG2));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_SIO> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ mutex_unlock(&l_lock);
+ }
+
+ /**
+ * @brief Concurrency test for SIO registers using devices Key Board
+ * Controller and MailBox
+ */
+ void test_concurrency()
+ {
+ mutex_t l_lock = Singleton<SioDD>::instance().iv_sio_mutex;
+ mutex_lock(&l_lock);
+ errlHndl_t l_err = NULL;
+ uint8_t l_data;
+ size_t l_len = sizeof(l_data);
+ //Enable additional SIO test devices 5 and E
+ l_data = SIO::ENABLE_DEVICE;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x30));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::MB, 0x30));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ //Read current values from devices
+ //KBC
+ uint8_t kbc_base_add_msb = 0;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(kbc_base_add_msb),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ //MB
+ uint8_t mb_base_add_msb = 0;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(mb_base_add_msb),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::MB, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ //Write new values to registers 0x60
+ //KBC
+ uint8_t testdata1 = 0xAA;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata1),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ //MB
+ uint8_t testdata2 = 0x05;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata2),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::MB, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ //Read and compare
+ uint8_t testdata;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ if( testdata != 0xAA )
+ {
+ TS_FAIL("SioDDTest::SIO_concurreny> Data mismatch on SIO device KBC\
+ reg 0x60 : Exp=0xAA, Act=%.2X", testdata);
+ }
+
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(testdata),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::MB, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ if( testdata != 0x05 )
+ {
+ TS_FAIL("SioDDTest::SIO_concurreny> Data mismatch on SIO device MB\
+ reg 0x60 : Exp=0x05, Act=%.2X", testdata);
+ }
+
+ //Write original data back
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(kbc_base_add_msb),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+
+ //MB
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(mb_base_add_msb),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::MB, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::SIO_concurrency> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ mutex_unlock(&l_lock);
+ }
+
+ /** @brief test simultaneous accesses to same logical device
+ */
+ void test_same_dev()
+ {
+ uint8_t l_data;
+ errlHndl_t l_err = NULL;
+ size_t l_len = sizeof(l_data);
+ mutex_t l_lock = Singleton<SioDD>::instance().iv_sio_mutex;
+ mutex_lock(&l_lock);
+
+ //enable device Key Board Controller
+ l_data = SIO::ENABLE_DEVICE;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(l_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x30));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_same_dev> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ //Read value at key board controller, reg 0x60
+ uint8_t current_data = 0;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(current_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_same_dev> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ //Write new test value to key board controller, reg 0x60
+ uint8_t test_data = 0x10;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(test_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_same_dev> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ //Read and compare
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(test_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_same_dev> read from SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ if(test_data != 0x10)
+ {
+ TS_FAIL("SioDDTest::test_same_dev> Data mismatch on SIO KBC, 0x60\
+ : Exp=0x10, Act=%.2X", test_data);
+ }
+ //Write back original data
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(current_data),
+ l_len,
+ DEVICE_SIO_ADDRESS(SIO::KBC, 0x60));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_same_dev> write to SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ mutex_unlock(&l_lock);
+ }
+
+ /**
+ * @brief AHB_SIO access
+ * Read and write data to the SPI Control register
+ */
+ void test_AHB_SIO( void )
+ {
+ errlHndl_t l_err = NULL;
+ uint32_t l_lpc_addr;
+ size_t l_len = sizeof(uint32_t);
+ mutex_t l_lock = Singleton<SioDD>::instance().iv_sio_mutex;
+ mutex_lock(&l_lock);
+
+ uint32_t first = 0;
+ l_lpc_addr = CTLREG_04 | SPIC_BASE_ADDR_AHB;
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(first),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(l_lpc_addr));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_AHB_SIO> read from AHB_SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ uint32_t data1 = 0x12345678;
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(data1),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(l_lpc_addr));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_AHB_SIO> write to AHB_SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ l_err = deviceOp( DeviceFW::READ,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(data1),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(l_lpc_addr));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_AHB_SIO> read from AHB_SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ if( data1 != 0x12345678 )
+ {
+ TS_FAIL("SioDDTest::test_SPIC> Unexpected result of %.8X\
+ (exp 0x12345678)",data1);
+ }
+ //put back the original
+ l_err = deviceOp( DeviceFW::WRITE,
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(first),
+ l_len,
+ DEVICE_AHB_SIO_ADDRESS(l_lpc_addr));
+ if( l_err )
+ {
+ TS_FAIL("SioDDTest::test_AHB_SIO> write to AHB_SIO failed");
+ errlCommit(l_err,SIO_COMP_ID);
+ }
+ mutex_unlock(&l_lock);
+ }
+};
+#endif
OpenPOWER on IntegriCloud