summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf
diff options
context:
space:
mode:
authorThi Tran <thi@us.ibm.com>2014-04-23 09:11:57 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-04-25 16:00:49 -0500
commit6a6243fc44197c1fc1b4e9fd16a3bd1f08819b1e (patch)
tree99a205d22859d7ad40f9940d04a0b19cb961bd17 /src/usr/hwpf
parent7063cf778756a511f5ef3903ba0d627cb34cd666 (diff)
downloadtalos-hostboot-6a6243fc44197c1fc1b4e9fd16a3bd1f08819b1e.tar.gz
talos-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')
-rwxr-xr-xsrc/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.C229
-rwxr-xr-xsrc/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.H7
-rw-r--r--src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C14
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);
OpenPOWER on IntegriCloud