diff options
author | Thi Tran <thi@us.ibm.com> | 2014-04-23 09:11:57 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-04-25 16:00:49 -0500 |
commit | 6a6243fc44197c1fc1b4e9fd16a3bd1f08819b1e (patch) | |
tree | 99a205d22859d7ad40f9940d04a0b19cb961bd17 /src/usr/hwpf | |
parent | 7063cf778756a511f5ef3903ba0d627cb34cd666 (diff) | |
download | blackbird-hostboot-6a6243fc44197c1fc1b4e9fd16a3bd1f08819b1e.tar.gz blackbird-hostboot-6a6243fc44197c1fc1b4e9fd16a3bd1f08819b1e.zip |
SW258179: INITPROC: Hostboot - Changes for SW255563
Change-Id: Ia974512e50d68e43b9880cc9600c5eba3b712fc3
CQ:SW258179
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/10689
Reviewed-by: Thi N. Tran <thi@us.ibm.com>
Tested-by: Thi N. Tran <thi@us.ibm.com>
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/10709
Tested-by: Jenkins Server
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf')
3 files changed, 201 insertions, 49 deletions
diff --git a/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.C b/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.C index e21c0100e..288bfb2f9 100755 --- a/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.C +++ b/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013 */ +/* COPYRIGHT International Business Machines Corp. 2013,2014 */ /* */ /* p1 */ /* */ @@ -20,7 +20,7 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: p8_occ_control.C,v 1.2 2013/08/13 18:16:59 jimyac Exp $ +// $Id: p8_occ_control.C,v 1.5 2014/04/21 20:17:31 bcbrock Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_occ_control.C,v $ //------------------------------------------------------------------------------ // *! (C) Copyright International Business Machines Corp. 2011 @@ -44,10 +44,13 @@ /// o initialize to Branch Absolute 0xFFF80010 if i_ppc405_boot_ctrl = PPC405_BOOT_SRAM /// o initialize to Branch Absolute 0x00000010 if i_ppc405_boot_ctrl = PPC405_BOOT_MEM /// o initialize to Branch Relative -16 if i_ppc405_boot_ctrl = PPC405_BOOT_OLD -/// o Write PPC405 reset bit per parameteri_ppc405_reset_ctrl (OCR) +/// o Write PPC405 rese/halt bits per parameteri_ppc405_reset_ctrl (OCR, OJCFG) /// o if PPC405_RESET_NULL , do nothing /// o if PPC405_RESET_OFF , write reset bit to 0 (PPC405 not reset) /// o if PPC405_RESET_ON , write reset bit to 1 (PPC405 reset) +/// o if PPC405_HALT_OFF , write halt bit to 0 (PPC405 not halted) +/// o if PPC405_HALT_ON , write halt bit to 1 (PPC405 halted) +/// o if PPC405_RESET_SEQUENCE , Safe halt/reset of OCC (See comments) /// Procedure Prereq: /// o System clocks are running /// \endverbatim @@ -60,6 +63,17 @@ #include "p8_scom_addresses.H" #include "p8_occ_control.H" +// We are not allowed to add new files to fw810, so the BIT() macro is added +// by hand. +//#include "pore_bitmanip.H" + +/// Create a multi-bit mask of \a n bits starting at bit \a b +#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b)) + +/// Create a single bit mask at bit \a b +#define BIT(b) BITS((b), 1) + + extern "C" { using namespace fapi; @@ -80,6 +94,66 @@ using namespace fapi; // Function definitions // ---------------------------------------------------------------------- +// We need to get the FAPI team to provide a simple 32-bit address/64-bit data +// SCOM abstraction. In the meantime, we can't define these as local static +// functions due to PHYP restrictions, so we give these SCOM abstractions +// unique names. + +#define putScom(target, address, data) \ + _occControlPutScom(target, address, data, #address, __FILE__, __LINE__) + +#define getScom(target, address, data) \ + _occControlGetScom(target, address, data, #address, __FILE__, __LINE__) + + fapi::ReturnCode + _occControlPutScom(const Target& i_target, const uint32_t i_address, + const uint64_t i_data, + const char* i_sAddress, const char* i_file, const int i_line) + { + fapi::ReturnCode rc; + uint32_t ecmdRc; + ecmdDataBufferBase data(64); + + do { + ecmdRc = data.setDoubleWord(0, i_data); + if (ecmdRc) { + FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase at %s:%d", + ecmdRc, i_file, i_line); + rc.setEcmdError(ecmdRc); + break; + } + + rc = fapiPutScom(i_target, i_address, data); + if (!rc.ok()) { + FAPI_ERR("putScom() to %s (0x%08x) failed at %s:%d.", + i_sAddress, i_address, i_file, i_line); + break; + } + } while (0); + return rc; + } + + fapi::ReturnCode + _occControlGetScom(const Target& i_target, const uint32_t i_address, + uint64_t& o_data, + const char* i_sAddress, const char* i_file, const int i_line) + { + fapi::ReturnCode rc; + ecmdDataBufferBase data(64); + + do { + rc = fapiGetScom(i_target, i_address, data); + if (!rc.ok()) { + FAPI_ERR("getScom() from %s (0x%08x) failed at %s:%d.", + i_sAddress, i_address, i_file, i_line); + break; + } + o_data = data.getDoubleWord(0); + } while (0); + + return rc; + } + /// \param[in] i_target => Chip Target /// \param[in] i_ppc405_reset_ctrl => PPC405_RESET_NULL : do nothing PPC405_RESET_OFF : set ppc405 reset=0 PPC405_RESET_ON : set ppc405 reset=1 /// \param[in] i_ppc405_boot_ctrl => PPC405_BOOT_NULL : do nothing PPC405_BOOT_SRAM : boot from sram PPC405_BOOT_MEM : boot from memory PPC405_BOOT_OLD : boot from sram (OLD tests) @@ -90,9 +164,10 @@ using namespace fapi; fapi::ReturnCode p8_occ_control(const Target& i_target, const uint8_t i_ppc405_reset_ctrl, const uint8_t i_ppc405_boot_ctrl) { - fapi::ReturnCode rc; + fapi::ReturnCode rc, rc1; ecmdDataBufferBase data(64); uint32_t l_ecmdRc = 0; + uint64_t firMask, occLfir; FAPI_INF("Executing p8_occ_control ...."); @@ -101,7 +176,7 @@ p8_occ_control(const Target& i_target, const uint8_t i_ppc405_reset_ctrl, const // ------------------------------------- // check ppc405_reset_ctrl - if (!(i_ppc405_reset_ctrl <= PPC405_RESET_ON) ) { + if (!(i_ppc405_reset_ctrl <= PPC405_RESET_SEQUENCE) ) { FAPI_ERR("Bad PPC405 Reset Setting Passed to Procedure => %d", i_ppc405_reset_ctrl); const uint8_t& RESET_PARM = i_ppc405_reset_ctrl; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_OCC_CONTROL_BAD_405RESET_PARM); @@ -189,50 +264,124 @@ p8_occ_control(const Target& i_target, const uint8_t i_ppc405_reset_ctrl, const } // ---------------------------------------------------------- - // Set or Clear PPC405 reset in OCC Control register ( - // OCC_CONTROL_0x0006B000 - // OCC_CONTROL_AND_0x0006B001 - // OCC_CONTROL_OR_0x0006B002 - // - // - bit 0 => 0= ppc405 not in reset 1= ppc405 in reset + // Handle the i_ppc405_reset_ctrl parameter // ---------------------------------------------------------- - if (i_ppc405_reset_ctrl == PPC405_RESET_OFF) { - l_ecmdRc |= data.flushTo1(); - l_ecmdRc |= data.clearBit(0); + switch (i_ppc405_reset_ctrl) { - if (l_ecmdRc) { - FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); - rc.setEcmdError(l_ecmdRc); - return rc; - } + case PPC405_RESET_OFF: - FAPI_DBG("Writing OCC Control Register to clear bit 0 (core_reset)"); + rc = putScom(i_target, OCC_CONTROL_AND_0x0006B001, ~BIT(0)); + if (!rc.ok()) return rc; + break; - rc = fapiPutScom(i_target, OCC_CONTROL_AND_0x0006B001, data); - if (!rc.ok()) { - FAPI_ERR("**** ERROR : Unexpected error encountered in write to OCC Control Register => OCC_CONTROL_AND_0x0006B001"); - return rc; - } - } + case PPC405_RESET_ON: - if (i_ppc405_reset_ctrl == PPC405_RESET_ON) { - l_ecmdRc |= data.flushTo0(); - l_ecmdRc |= data.setBit(0); + rc = putScom(i_target, OCC_CONTROL_OR_0x0006B002, BIT(0)); + if (!rc.ok()) return rc; + break; + + case PPC405_HALT_OFF: - if (l_ecmdRc) { - FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", l_ecmdRc); - rc.setEcmdError(l_ecmdRc); - return rc; - } + rc = putScom(i_target, OCC_JTG_PIB_OJCFG_AND_0x0006B005, ~BIT(6)); + if (!rc.ok()) return rc; + break; - FAPI_DBG("Writing OCC Control Register to set bit 0 (core_reset)"); + case PPC405_HALT_ON: - rc = fapiPutScom(i_target, OCC_CONTROL_OR_0x0006B002, data); - if (!rc.ok()) { - FAPI_ERR("**** ERROR : Unexpected error encountered in write to OCC Control Register => OCC_CONTROL_OR_0x0006B002"); - return rc; - } + rc = putScom(i_target, OCC_JTG_PIB_OJCFG_OR_0x0006B006, BIT(6)); + if (!rc.ok()) return rc; + break; + + case PPC405_RESET_SEQUENCE: + + // It is unsafe in general to simply reset the 405, as this is an + // asynchronous reset that can leave OCI slaves in unrecoverable states + // (cf. SW255563). This is a "safe" reset-entry sequence that includes + // halting the 405 (a synchronous operation) before issuing the + // reset. Since this sequence halts/unhalts the 405 and modifies FIRs it + // is coded and called out apart from the simple PPC405_RESET_OFF + // sequence above that simply sets the 405 reset bit. + // + // The sequence: + // + // 1. Mask the "405 halted" FIR bit to avoid FW thinking the halt we're + // about to inject on the 405 is an error. + // + // 2. Halt the 405. If the 405 does not halt in 1ms we note that fact + // but press on, hoping (probably in vain) that any subsequent reset + // actions will clear up the issue. To check if the 405 halted we must + // clear the FIR and verify that the FIR is set again. + // + // 3. Put the 405 into reset. + // + // 4. Clear the halt bit. + // + // 5. Restore the original FIR mask + + // Save the FIR mask, and mask the halted FIR + + rc = getScom(i_target, OCC_LFIR_MASK_0x01010803, firMask); + if (!rc.ok()) return rc; + + rc = putScom(i_target, OCC_LFIR_MASK_OR_0x01010805, BIT(25)); + if (!rc.ok()) return rc; + + do { + + // Halt the 405 and verify that it is halted + + rc = putScom(i_target, OCC_JTG_PIB_OJCFG_OR_0x0006B006, BIT(6)); + if (!rc.ok()) break; + + rc = fapiDelay(1000000, 10000); // 1,000,000 ns = 1ms + if (!rc.ok()) { + FAPI_ERR("fapiDelay() failed"); + break; + } + + rc = putScom(i_target, OCC_LFIR_AND_0x01010801, ~BIT(25)); + if (!rc.ok()) break; + + rc = getScom(i_target, OCC_LFIR_0x01010800, occLfir); + if (!rc.ok()) break; + + if (!(occLfir & BIT(25))) { + FAPI_ERR("OCC will not halt. Pressing on, hoping for the best."); + } + + // Put the 405 into reset, unhalt the 405 and clear the halted FIR + // bit. + + rc = putScom(i_target, OCC_CONTROL_OR_0x0006B002, BIT(0)); + if (!rc.ok()) break; + + rc = putScom(i_target, OCC_JTG_PIB_OJCFG_AND_0x0006B005, ~BIT(6)); + if (!rc.ok()) break; + + rc = putScom(i_target, OCC_LFIR_AND_0x01010801, ~BIT(25)); + if (!rc.ok()) break; + + } while (0); + + // Restore the original FIR mask, then decide which error code (if any) + // to return. + + rc1 = putScom(i_target, OCC_LFIR_MASK_0x01010803, firMask); + + if (!rc.ok() && !rc1.ok()) { + FAPI_ERR("Double fault, returing final error code"); + return rc1; + } else if (!rc.ok()) { + return rc; + } else if (!rc1.ok()) { + return rc1; + } + break; + + + default: + break; } FAPI_INF("Completing p8_occ_control ...."); diff --git a/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.H b/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.H index 38183828e..72454c859 100755 --- a/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.H +++ b/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.H @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013 */ +/* COPYRIGHT International Business Machines Corp. 2013,2014 */ /* */ /* p1 */ /* */ @@ -20,7 +20,7 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: p8_occ_control.H,v 1.3 2013/01/08 13:52:08 jimyac Exp $ +// $Id: p8_occ_control.H,v 1.4 2014/04/21 14:27:53 bcbrock Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_occ_control.H,v $ #ifndef _P8_OCC_CONTROL_H_ #define _P8_OCC_CONTROL_H_ @@ -47,6 +47,9 @@ fapi::ReturnCode p8_occ_control(const fapi::Target& i_target, const uint8_t PPC405_RESET_NULL = 0x00; const uint8_t PPC405_RESET_OFF = 0x01; const uint8_t PPC405_RESET_ON = 0x02; +const uint8_t PPC405_HALT_OFF = 0x03; +const uint8_t PPC405_HALT_ON = 0x04; +const uint8_t PPC405_RESET_SEQUENCE = 0x05; const uint8_t PPC405_BOOT_NULL = 0x00; const uint8_t PPC405_BOOT_SRAM = 0x01; diff --git a/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C b/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C index 2a119c414..739a1597d 100644 --- a/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C +++ b/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C @@ -20,7 +20,7 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: p8_pm_prep_for_reset.C,v 1.29 2014/04/16 05:59:49 daviddu Exp $ +// $Id: p8_pm_prep_for_reset.C,v 1.30 2014/04/21 14:27:53 bcbrock Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_pm_prep_for_reset.C,v $ //------------------------------------------------------------------------------ // *! (C) Copyright International Business Machines Corp. 2011 @@ -41,8 +41,8 @@ /// - call p8_pm_firinit *chiptarget, /// - Mask the PM FIRs /// -/// - call p8_occ_control.C *chiptarget, ENUM:OCC_STOP ppc405_reset_ctrl = 2 -/// - OCC PPC405 put into reset +/// - call p8_occ_control.C *chiptarget, ENUM:OCC_STOP ppc405_reset_ctrl = PPC405_RESET_SEQUENCE +/// - OCC PPC405 put into reset safely /// - PMC moves to Vsafe value due to heartbeat loss /// /// - call p8_cpu_special_wakeup.C *chiptarget, ENUM:OCC_SPECIAL_WAKEUP @@ -341,12 +341,12 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target, } // ****************************************************************** - // Put OCC PPC405 into reset + // Put OCC PPC405 into reset safely // ****************************************************************** - FAPI_INF("Put OCC PPC405 into reset"); + FAPI_INF("Put OCC PPC405 into reset safely"); FAPI_DBG("Executing: p8_occ_control.C"); - FAPI_EXEC_HWP(rc, p8_occ_control, i_primary_chip_target, PPC405_RESET_ON, 0); + FAPI_EXEC_HWP(rc, p8_occ_control, i_primary_chip_target, PPC405_RESET_SEQUENCE, 0); if (rc) { FAPI_ERR("p8_occ_control: Failed to prepare OCC for RESET. With rc = 0x%x", (uint32_t)rc); @@ -355,7 +355,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target, if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { - FAPI_EXEC_HWP(rc, p8_occ_control, i_secondary_chip_target, PPC405_RESET_ON, 0); + FAPI_EXEC_HWP(rc, p8_occ_control, i_secondary_chip_target, PPC405_RESET_SEQUENCE, 0); if (rc) { FAPI_ERR("p8_occ_control: Failed to prepare OCC for RESET. With rc = 0x%x", (uint32_t)rc); |