mpc83xx: Store and display Arbiter Event Register values
authorNick Spence <nick.spence@freescale.com>
Thu, 28 Aug 2008 21:09:19 +0000 (14:09 -0700)
committerKim Phillips <kim.phillips@freescale.com>
Wed, 3 Sep 2008 21:06:57 +0000 (16:06 -0500)
Record the Arbiter Event Register values and optionally display them.

The Arbiter Event Register can record the type and effective address of
an arbiter error, even through an HRESET. This patch stores the values in
the global data structure.

Display of the Arbiter Event registers immediately after the RSR value
can be enabled with defines. The Arbiter values will only be displayed
if an arbiter event has occured since the last Power On Reset, and either
of the following defines exist:
 #define CONFIG_DISPLAY_AER_BRIEF - display only the arbiter address and
                                    and type register values
 #define CONFIG_DISPLAY_AER_FULL  - display and interpret the arbiter
                                    event register values

Address Only transactions are one of the trapped events that can register
as an arbiter event. They occur with some cache manipulation instructions
if the HID0_ABE (Address Broadcast Enable) is set and the memory region
has the MEMORY_COHERENCE WIMG bit set. Setting:
 #define CONFIG_MASK_AER_AO - prevents the arbiter from recording address
                              only events, so that it can still capture
                              other real problems.

Signed-off-by: Nick Spence <nick.spence@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
cpu/mpc83xx/cpu_init.c
cpu/mpc83xx/start.S
include/asm-ppc/global_data.h

index 4514dbb7df2f24c71bc6bf808f272ad298e13a1e..ff01cf10f55f062aa6ec7ea5bbadea70ef19173a 100644 (file)
@@ -167,6 +167,10 @@ void cpu_init_f (volatile immap_t * im)
        gd->reset_status = im->reset.rsr;
        im->reset.rsr = ~(RSR_RES);
 
+       /* AER - Arbiter Event Register - store status */
+       gd->arbiter_event_attributes = im->arbiter.aeatr;
+       gd->arbiter_event_address = im->arbiter.aeadr;
+
        /*
         * RMR - Reset Mode Register
         * contains checkstop reset enable (4.6.1.4)
@@ -302,6 +306,130 @@ int cpu_init_r (void)
        return 0;
 }
 
+/*
+ * Print out the bus arbiter event
+ */
+#if defined(CONFIG_DISPLAY_AER_FULL)
+static int print_83xx_arb_event(int force)
+{
+       static char* event[] = {
+               "Address Time Out",
+               "Data Time Out",
+               "Address Only Transfer Type",
+               "External Control Word Transfer Type",
+               "Reserved Transfer Type",
+               "Transfer Error",
+               "reserved",
+               "reserved"
+       };
+       static char* master[] = {
+               "e300 Core Data Transaction",
+               "reserved",
+               "e300 Core Instruction Fetch",
+               "reserved",
+               "TSEC1",
+               "TSEC2",
+               "USB MPH",
+               "USB DR",
+               "Encryption Core",
+               "I2C Boot Sequencer",
+               "JTAG",
+               "reserved",
+               "eSDHC",
+               "PCI1",
+               "PCI2",
+               "DMA",
+               "QUICC Engine 00",
+               "QUICC Engine 01",
+               "QUICC Engine 10",
+               "QUICC Engine 11",
+               "reserved",
+               "reserved",
+               "reserved",
+               "reserved",
+               "SATA1",
+               "SATA2",
+               "SATA3",
+               "SATA4",
+               "reserved",
+               "PCI Express 1",
+               "PCI Express 2",
+               "TDM-DMAC"
+       };
+       static char *transfer[] = {
+               "Address-only, Clean Block",
+               "Address-only, lwarx reservation set",
+               "Single-beat or Burst write",
+               "reserved",
+               "Address-only, Flush Block",
+               "reserved",
+               "Burst write",
+               "reserved",
+               "Address-only, sync",
+               "Address-only, tlbsync",
+               "Single-beat or Burst read",
+               "Single-beat or Burst read",
+               "Address-only, Kill Block",
+               "Address-only, icbi",
+               "Burst read",
+               "reserved",
+               "Address-only, eieio",
+               "reserved",
+               "Single-beat write",
+               "reserved",
+               "ecowx - Illegal single-beat write",
+               "reserved",
+               "reserved",
+               "reserved",
+               "Address-only, TLB Invalidate",
+               "reserved",
+               "Single-beat or Burst read",
+               "reserved",
+               "eciwx - Illegal single-beat read",
+               "reserved",
+               "Burst read",
+               "reserved"
+       };
+
+       int etype = (gd->arbiter_event_attributes & AEATR_EVENT)
+                   >> AEATR_EVENT_SHIFT;
+       int mstr_id = (gd->arbiter_event_attributes & AEATR_MSTR_ID)
+                     >> AEATR_MSTR_ID_SHIFT;
+       int tbst = (gd->arbiter_event_attributes & AEATR_TBST)
+                  >> AEATR_TBST_SHIFT;
+       int tsize = (gd->arbiter_event_attributes & AEATR_TSIZE)
+                   >> AEATR_TSIZE_SHIFT;
+       int ttype = (gd->arbiter_event_attributes & AEATR_TTYPE)
+                   >> AEATR_TTYPE_SHIFT;
+
+       if (!force && !gd->arbiter_event_address)
+               return 0;
+
+       puts("Arbiter Event Status:\n");
+       printf("       Event Address: 0x%08lX\n", gd->arbiter_event_address);
+       printf("       Event Type:    0x%1x  = %s\n", etype, event[etype]);
+       printf("       Master ID:     0x%02x = %s\n", mstr_id, master[mstr_id]);
+       printf("       Transfer Size: 0x%1x  = %d bytes\n", (tbst<<3) | tsize,
+                               tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize);
+       printf("       Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]);
+
+       return gd->arbiter_event_address;
+}
+
+#elif defined(CONFIG_DISPLAY_AER_BRIEF)
+
+static int print_83xx_arb_event(int force)
+{
+       if (!force && !gd->arbiter_event_address)
+               return 0;
+
+       printf("Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
+               gd->arbiter_event_attributes, gd->arbiter_event_address);
+
+       return gd->arbiter_event_address;
+}
+#endif /* CONFIG_DISPLAY_AER_xxxx */
+
 /*
  * Figure out the cause of the reset
  */
@@ -334,6 +462,12 @@ int prt_83xx_rsr(void)
                        printf("%s%s", sep, bits[i].desc);
                        sep = ", ";
                }
-       puts("\n\n");
+       puts("\n");
+
+#if defined(CONFIG_DISPLAY_AER_FULL) || defined(CONFIG_DISPLAY_AER_BRIEF)
+       print_83xx_arb_event(rsr & RSR_BMRS);
+#endif
+       puts("\n");
+
        return 0;
 }
index 75ad36cb3dbdd4ded9fc22dd0552e6e2a4543575..e452bfbc5e07294bbc8fed92f0dfdc4814b15d64 100644 (file)
@@ -483,6 +483,17 @@ init_e300_core: /* time t 10 */
 1:
 #endif /* CONFIG_WATCHDOG */
 
+#if defined(CONFIG_MASK_AER_AO)
+       /* Write the Arbiter Event Enable to mask Address Only traps. */
+       /* This prevents the dcbz instruction from being trapped when */
+       /* HID0_ABE Address Broadcast Enable is set and the MEMORY    */
+       /* COHERENCY bit is set in the WIMG bits, which is often      */
+       /* needed for PCI operation.                                  */
+       lwz     r4, 0x0808(r3)
+       rlwinm  r0, r4, 0, ~AER_AO
+       stw     r0, 0x0808(r3)
+#endif /* CONFIG_MASK_AER_AO */
+
        /* Initialize the Hardware Implementation-dependent Registers */
        /* HID0 also contains cache control                     */
        /*------------------------------------------------------*/
index c09b07d36a066282b0fe995a6a920210737321e0..a9366c36735e3f90f94c5d2f164124eed07a5067 100644 (file)
@@ -122,6 +122,10 @@ typedef    struct  global_data {
        phys_size_t     ram_size;       /* RAM size */
        unsigned long   reloc_off;      /* Relocation Offset */
        unsigned long   reset_status;   /* reset status register at boot        */
+#if defined(CONFIG_MPC83XX)
+       unsigned long   arbiter_event_attributes;
+       unsigned long   arbiter_event_address;
+#endif
        unsigned long   env_addr;       /* Address  of Environment struct       */
        unsigned long   env_valid;      /* Checksum of Environment valid?       */
        unsigned long   have_console;   /* serial_init() was called             */