summaryrefslogtreecommitdiffstats
path: root/src/usr/console/ast2400.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/console/ast2400.C')
-rw-r--r--src/usr/console/ast2400.C441
1 files changed, 395 insertions, 46 deletions
diff --git a/src/usr/console/ast2400.C b/src/usr/console/ast2400.C
index db0bf40ae..b2b63c395 100644
--- a/src/usr/console/ast2400.C
+++ b/src/usr/console/ast2400.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -26,80 +26,235 @@
#include <devicefw/userif.H>
#include <lpc/lpcif.H>
#include <errl/errlmanager.H>
+#include <kernel/console.H>
+#include <devicefw/driverif.H>
+#include <initservice/bootconfigif.H>
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;
-/** Overload the base class with Ast2400 specifices.
- *
- * In initialization we need to program the SIO device on the AST2400 to
- * enable the Uart device.
- */
-class Ast2400Uart : public Uart
-{
- private:
+ 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;
+ /** Overload the base class with Ast2400 specifics.
+ *
+ * In initialization we need to program the SIO device on the AST2400 to
+ * enable the Uart device.
+ */
+ class Ast2400Uart : public Uart
+ {
+
+ public:
+ enum consoleConfig_t
+ {
+ NONE = 0x00, // No output selected
+ SELECT_SUART = 0x40, // SIO Uart
+ SELECT_VUART = 0x80, // SOL virtual uart
+ RESERVED = 0xc0, // Reserved
+ };
+
+ 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(uint64_t i_addr, uint8_t i_byte)
+ 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));
+ &i_byte,
+ len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO, i_addr));
}
- public:
+ // write i_data to register i_reg
+ errlHndl_t writeSIOReg( uint8_t i_reg, uint8_t i_data )
+ {
+ errlHndl_t l_err = NULL;
+
+ do{
- virtual void initialize()
+ l_err = _writeReg( SIO_ADDR_REG_2E, i_data );
+
+ if(l_err) { break; }
+
+ l_err = _writeReg( SIO_DATA_REG_2F, i_reg );
+
+ }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;
do
{
-
- // Unlock the SIO registers
- // (write 0xA5 password to offset 0x2E two times)
- l_errl = _writeReg( 0x2e, 0xA5 );
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2e, 0xA5 );
- if (l_errl) { break; }
-
- // Select logical device 2 (SUART1) in SIO
- l_errl = _writeReg( 0x2e, 0x07 ); // select logical dev number
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, 0x02 ); // write device 2
+ // Select logical device 2 (SUART1) in SI)
+ l_errl = writeSIOReg( 0x07, 0x02);
if (l_errl) { break; }
// Disable SUART1 to change settings
- l_errl = _writeReg( 0x2e, 0x30 ); // select SIO base enable
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, 0x00 ); // clear enable
+ l_errl = writeSIOReg( 0x30, 0x00 );
if (l_errl) { break; }
// Set SUART1 addr to g_uartBase
- l_errl = _writeReg( 0x2e, 0x60 ); // select SIO addr[7:3]
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, (g_uartBase >> 8) & 0xFF );
+ l_errl = writeSIOReg( 0x60, (g_uartBase >> 8) & 0xFF );
if (l_errl) { break; }
- l_errl = _writeReg( 0x2e, 0x61 ); // select SIO addr[15:8]
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, (g_uartBase & 0xFF) );
+
+ l_errl = writeSIOReg( 61, (g_uartBase & 0xFF) );
if (l_errl) { break; }
// Set the SerIRQ
- l_errl = _writeReg( 0x2e, 0x70 );
+ l_errl = writeSIOReg( 0x70, SERIAL_IRQ );
if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, 0x04 );
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2e, 0x71 );
+
+ l_errl = writeSIOReg( 0x71, 0x01 );
if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, 0x01 );
+
// Enable SUART1
- l_errl = _writeReg( 0x2e, 0x30 ); // select SIO base enable
- if (l_errl) { break; }
- l_errl = _writeReg( 0x2f, 0x01 ); // write enable
+ l_errl = writeSIOReg( 0x30, 0x01 ); // select SIO base enable
if (l_errl) { break; }
//@fixme-RTC:115576 - Leaving SIO unlocked for now to allow
@@ -119,8 +274,202 @@ class Ast2400Uart : public Uart
Uart::initialize();
}
-};
+ // initialize for SOL support
+ void initializeVUART()
+ {
+ errlHndl_t l_err = NULL;
+
+ do{
+ uint32_t v;
+
+ /* configure IRQ level as low */
+ l_err = ahbSioRead(VUART1_GCTRLA, v);
+ if(l_err){break;}
+ v = v & ~2u;
+ l_err = ahbSioWrite(VUART1_GCTRLA, v);
+ if(l_err){break;}
+
+ /* configure the IRQ number */
+ l_err = ahbSioRead(VUART1_GCTRLB, v);
+ if(l_err){break;}
+
+ v = (v & ~0xf0u) | ((SERIAL_IRQ << 4));
+ l_err = ahbSioWrite(VUART1_GCTRLB,v);
+ if(l_err){break;}
+
+ /* configure the address */
+ l_err = ahbSioWrite(VUART1_ADDRL, g_uartBase & 0xff);
+ if(l_err){break;}
+
+ l_err = ahbSioWrite(VUART1_ADDRH, g_uartBase >> 8);
+
+ }while(0);
+
+ if (l_err)
+ {
+ printk("VUART: config failed at\n");
+ setFailed();
+ errlCommit(l_err, CONSOLE_COMP_ID);
+ }
+ else
+ {
+ printk("VUART: config SUCCESS\n" );
+ }
+
+ Uart::initialize();
+ }
+
+ void disableVUART()
+ {
+ errlHndl_t l_err = NULL;
+
+ do{
+ // read the control reg, mask off the enabled bit
+ // and write it back
+ uint32_t reg_value = 0;
+
+ 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 );
+ if(l_err){break;}
+
+
+
+ }while(0);
+
+ if (l_err)
+ {
+ errlCommit(l_err, CONSOLE_COMP_ID);
+ }
+ };
+
+ void disableSUART()
+ {
+ errlHndl_t l_err = NULL;
+
+ do{
+
+ // select device 2 - UART1
+ l_err = writeSIOReg(0x07, 0x02);
+ if(l_err){break;}
+
+ // clear the uart enable from base ctl reg
+ l_err = writeSIOReg(0x30, 0);
+
+ }while(0);
+
+ if (l_err)
+ {
+ errlCommit(l_err, CONSOLE_COMP_ID);
+ }
+ };
+
+ 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:
+
+ 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;
+
+ uint8_t uart_config = 0x00;
+
+ do{
+ // allow access to the registers
+ unlockSIO();
+
+ // verify the boot flags version from register 0x28
+ l_err = readSIOReg( 0x28, this_version );
+
+ if (l_err) { break; }
+
+ // is it the version we expected?
+ if( expected_version == this_version )
+ {
+ l_err = readSIOReg(0x2d, uart_config);
+
+ if (l_err) { break; }
+
+ // determine which config has been selected
+ consoleConfig_t config =
+ static_cast<consoleConfig_t>(uart_config & CONFIG_MASK);
+
+ switch ( config )
+ {
+ case SELECT_SUART:
+ {
+ printk("ast2400: SUART config in process\n");
+ disableVUART();
+ initializeSUART();
+ break;
+ }
+ case SELECT_VUART:
+ {
+ printk("ast2400: VUART config in process\n");
+ disableSUART();
+ initializeVUART();
+ break;
+ }
+ case NONE:
+ {
+ // no config selected disable both
+ disableSUART();
+ disableVUART();
+ printk("ast2400: no config selected, "
+ "disable console output.\n");
+ }
+ default:
+ {
+ printk("ast2400: invalid config data"
+ " default to SUART configuration\n");
+ initializeSUART();
+ }
+ }
+ }
+ else
+ {
+ // invalid version read from SIO register 0x28
+ printk("ast2400: Invalid boot config version %d\n", this_version);
+ initializeSUART();
+ }
+
+ }while(0);
+
+ if (l_err)
+ {
+ setFailed();
+ errlCommit(l_err, CONSOLE_COMP_ID);
+ }
+ }
+ };
CONSOLE_UART_DEFINE_DEVICE(Ast2400Uart);
-}
+};
OpenPOWER on IntegriCloud