/**   mem_test_5854.c
 **
 **   This module includes all the low-level DDR2 RAM tests for the 
 ** NPA5854 AMC card which contains a Cavium processor.
 **
 **   These tests run from FLASH after the DDR2 controller is set up but 
 ** before the Uboot code is moved into RAM.
 **
 ** Created by Ted Schmitz, October 9, 2008
 **
 **/

#include <common.h>
//#include <asm-mips/global_data.h>

#include "mem_test_npa5854.h"
#include "phase1_error_handler.h"
#include "diag_mon/errcodes.h"
#include "ll_bist.h"
#include "ll_post_types.h"
#include "common_mem_test.h"
//#include "ll_post_utils.h"

#include "cvmx.h"

/* macros to force write to complete */
#define sync() asm volatile("sync")
#define syncs() asm volatile("syncs")
#define syncw() asm volatile("syncw")
#define syncws() asm volatile("syncws")
#define invalidate_L1_Dcache() asm volatile("cache 9, 0($0)")

/* local variables */
/* cannot use globals in phase I tests */
//static uint64_t ddr_mem_size;   /* total number of bytes of DDR RAM */
//static int test_results_flag;   /* flag indicating test passed or failed */
extern void octeon_flush_l2_cache(void);

  /*-------------------*/
  /*  form_evict_addr  */
  /*-------------------*/
  /* Returns an address that when written to will cause the L2Cache to flush
   * 'addr' from the cache. 'Increment' controls how far away and in what
   * direction to find the evicting cache block. To use the next higher
   * cache block, set 'Increment' to 0x80; while to use the next lower cachce
   * block, set 'Increment' to -0x80.
   */
uint64_t
form_evict_addr (uint64_t p1, uint64_t increment)
{
    uint64_t    p2, l2cSet, mid, high;

    if (OCTEON_IS_MODEL (OCTEON_CN38XX) ||
	OCTEON_IS_MODEL (OCTEON_CN56XX) ||
	OCTEON_IS_MODEL (OCTEON_CN58XX)   ) {
          /* These devices use an 11-bit wide cache index. */
        l2cSet = ((p1 >> 17) & 0x3FFll) ^ ((p1 >> 7) & 0x3FFll);

        p2 = p1 + increment;  /* One cache block more */

        mid = (p2 >> 7) & 0x3FFLL;
        high = mid ^ l2cSet;

        p2 = (p2 & 0xFF801FFFFLL) | (high << 17);
    } else if (OCTEON_IS_MODEL (OCTEON_CN31XX) ||
               OCTEON_IS_MODEL (OCTEON_CN30XX) ||
               OCTEON_IS_MODEL (OCTEON_CN52XX) ||
               //OCTEON_IS_MODEL (OCTEON_CN51XX) ||
               OCTEON_IS_MODEL (OCTEON_CN50XX)   ) {
          /* These devices use an 9-bit wide cache index. */
        l2cSet = ((p1 >> 16) & 0x1FFll) ^ ((p1 >> 7) & 0x1FFll);

        p2 = p1 + increment;  /* One cache block more */

        mid = (p2 >> 7) & 0x1FFLL;
        high = mid ^ l2cSet;
        p2 = (p2 & 0xFFC00FFFFLL) | (high << 16);
    } else {
	p2 = 0;
    //fatal ("form_evict_address: unrecognized Octeon version\n");
    printf("\nIn 'form_evict_address()' unrecognized Octeon version\n");
    }

    //printf("\np1 = %08lX\n",(u32) p1);
    //printf("\np2 = %08lX\n",(u32) p2);
    return (p2);
}

#if 0 /* don't think I need this any more */
/*****************************************************************************
 **                Main Memory Test Function                                **
 **                                                                         **
 **   This is the main function that calls all the DDR memory tests in the  **
 ** proper order.                                                           **
 **                                                                         **
 ** NOTE:  It would help to know how many and the length, in bytes, of each **
 **        DIMM.  Some tests use this information to properly test the      **
 **        boundaries of each DIMM and to help determine which DIMM is bad  **
 **        when a malfunction is detected.                                  **
 **                                                                         **
 ****************************************************************************/
void run_memory_tests(void)
{
  //DECLARE_GLOBAL_DATA_PTR;      /* setup gbl data ptr, need some global data */
  //test_results_flag = PASS;     /* init test results flag */

  //ddr_mem_size = gd->ram_size;  /* get total size of ddr RAM in bytes */

  /**  Set up l2C, core icache & dcache, and ecc hardware as you need it
       for this test.
       Individual tests may have to adjust and/or monitor various memory
       registers for their needs.

       Make sure the Icache & Dcache is on for Core 0 or the RAM tests will 
       run too slow.
  **/

  ram_data_lines_test();        /* test data lines on all DIMMs */
  ram_address_lines_test();     /* test address lines on all DIMMs */
  ram_cells_test();             /* test each location of RAM on all DIMMs */
  ddr_ram_ecc_test();           /* test the DDR RAM ECC Cells */
}
#endif

/*****************************************************************************
 **                    Cavium RAM Data Lines Test
 **
 **   This function verifies the data lines to the DDR RAM by writing and
 ** reading a variety of test patterns designed to verify each data pin 
 ** connected to the DDR memory.
 **
 **  The Cavium processor has 128 data bits.  The first 64 are connected to one
 ** DIMM the last 64 are connected to the 2nd DIMM.
 **
 ** NOTE:  This function assumes there are four DIMMs available for now.
 **
 ** INPUT - "test_no" = test number for this test.
 **       - "exec_count" = current execution count.
 **
 ** OUTPUT - The data lines in at least the first four DIMM sockets will be
 **          verified to be working.
 **        - Module global variable "test_results_flag" will be set to "FAIL"
 **          if any problems are detected by the data lines test.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void data_lines_test(int test_no, int exec_count)
{
  uint64_t * tp;                /* pointer to test patterns */
  volatile uint64_t * llptr;    /* 64-bit data working pointer */
  /* NOTE: All pointers are still only 32-bits long even though they may
           point to 64-bit data!!!
  */
  uint64_t cur_lo_test_pat;     /* current lower 64-bit test pattern */
  uint64_t data_read;           /* data read back from DIMM */
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  int test_results_flag;        /* flag indicating test passed or failed */
  union b64_data b64;           /* union to manage a 64-bit test pattern */
  struct error_data eh;         /* create an err hand struct */
  int i;

  test_results_flag = PASS;     /* init flag */

  /**   Start out by writing and verifying some basic patterns to see if we 
   ** have any stuck-ats or stuck-to's.
   **/
  tp = (uint64_t *) &data_test_pats_64b[0]; /* get pointer to test patterns */
  llptr = (uint64_t *) BEG_DATA_LINES_TEST_ADDR; /* data lines test beg adrs */

  while(*tp != (uint64_t) END_OF_TABLE)
    {
    cur_lo_test_pat = *tp;      /* get next test pat from table */
#if 0
    printf("tp = %08lX\n",(unsigned long) tp);
    printf("test pat = %08lX%08lX\n",(unsigned long) 
           ((cur_lo_test_pat >> 32) & 0xFFFFFFFF), 
           (cur_lo_test_pat & 0xFFFFFFFF));
#endif
    llptr[0] = cur_lo_test_pat; /* write next test pat to lower DIMM */
    llptr[1] = ~cur_lo_test_pat; /* write inverse of test pat to upper DIMM */

    /**
     ** NOTE: We really need to know how many DIMMS there are and the 
     **       beginning and ending address of each to test the data lines
     **       on each DIMM.  But for now we will assume four DIMMs.
     **/
    //llptr[0] += 0x2030405060708090ull; /* DEBUG - mess up the data in ram */

    diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */

    /* read data back on lower DIMM and verify it */
    data_read = llptr[0];       /* read back lower 64 bits (1st DIMM ) */

    if (data_read != cur_lo_test_pat)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0080;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = cur_lo_test_pat;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    /* read data back on upper DIMM and verify it */
    data_read = llptr[1];       /* read back upper 64 bits (2nd DIMM ) */

    if (data_read != ~cur_lo_test_pat)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0085;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork+8;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = cur_lo_test_pat;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    /**
     ** Do it again but reverse which DIMM gets what test pattern.
     **/
    llptr[0] = ~cur_lo_test_pat; /* write inverse of test pat to lower DIMM */
    llptr[1] = cur_lo_test_pat; /* write cur test pat to upper DIMM */

    diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */

    /* read data back on lower DIMM and verify it */
    data_read = llptr[0];       /* read back lower 64 bits (1st DIMM ) */

    if (data_read != ~cur_lo_test_pat)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0080;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = ~cur_lo_test_pat;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    /* read data back on upper DIMM and verify it */
    data_read = llptr[1];       /* read back upper 64 bits (2nd DIMM ) */

    if (data_read != cur_lo_test_pat)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0085;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork+8;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = cur_lo_test_pat;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    tp++;                       /* inc pointer to next test pattern */
    } /* end while */

  /** Okay so far.  Now walk a one and a zero through the data lines to
   ** check for any single bit being stuck to any other bit.
   **/
  i = 0;

  do /* walking 1's on lower DIMM, walking 0's on upper DIMM */
    {/* calc next walking 1's pattern for lower 32-bits */
    if (i <= 32)
      {
      b64.llwork = 0;
      b64.ul.lo_work = ((1 << i) & 0xFFFFFFFF);
      }
    else
      { /* calc next walking 1's pattern for upper 32-bits */
      b64.llwork = 0;
      b64.ul.up_work = ((1 << (i-32)) & 0xFFFFFFFF);
      }

    llptr[0] = b64.llwork;          /* write walking 1's to lower DIMM */
    llptr[1] = ~b64.llwork;         /* write walking 0's to upper DIMM */

#if 0
    printf("i = %0d\n",i);
    printf("next W2 pattern = %08lX%08lX\n",
           b64.ul.up_work,b64.ul.lo_work);
#endif


    diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */

    /* read data back on lower DIMM and verify it */
    data_read = llptr[0];       /* read back lower 64 bits (1st DIMM ) */

    if (data_read != b64.llwork)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0080;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = b64.llwork;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    /* read data back on upper DIMM and verify it */
    data_read = llptr[1];       /* read back upper 64 bits (2nd DIMM ) */

    if (data_read != ~b64.llwork)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0085;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork+8;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = ~b64.llwork;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    i++;
    } while (b64.llwork != 0x8000000000000000ull);
    //} while (i < 64); /* this also works */

  i = 0;
  do /* walking 0's on lower DIMM, walking 1's on upper DIMM */
    {
    if (i <= 32)
      {/* calc next walking 1's pattern for lower 32-bits */
      b64.llwork = 0;
      b64.ul.lo_work = ((1 << i) & 0xFFFFFFFF);
      }
    else
      { /* calc next walking 1's pattern for upper 32-bits */
      lwork = (unsigned long) ((1 << (i-32)) & 0xFFFFFFFF);
      b64.llwork = 0;
      b64.ul.up_work = ((1 << (i-32)) & 0xFFFFFFFF);
      }

    llptr[0] = ~b64.llwork;         /* write walking 0's to lower DIMM */
    llptr[1] = b64.llwork;          /* write walking 1's to upper DIMM */

    diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */

    /* read data back on lower DIMM and verify it */
    data_read = llptr[0];       /* read back lower 64 bits (1st DIMM ) */

    if (data_read != ~b64.llwork)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0080;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = ~b64.llwork;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    /* read data back on upper DIMM and verify it */
    data_read = llptr[1];       /* read back upper 64 bits (2nd DIMM ) */

    if (data_read != b64.llwork)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0085;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork+8;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = b64.llwork;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      test_results_flag = FAIL;
      return;
      }

    i++;
    } while (b64.llwork != 0x8000000000000000ull);
    //} while (i < 64); /* this also works */


  /* everything passed */
  if (test_results_flag == PASS)
    printf("Passed\n");

}

/*****************************************************************************
 **                    Cavium RAM Address Lines Test
 **
 **   This function verifies the address lines to the DDR RAM by writing and
 ** reading a specific test patterns designed to verify each address pin 
 ** connected to the DDR memory.
 **
 **  The Cavium processor has 128 data bits.  The first 64 are connected to one
 ** DIMM the last 64 are connected to the 2nd DIMM.  Therefore, each DIMM has
 ** its own address and data lines the require verification.
 **
 ** NOTE:  This function assumes there are four DIMMs available for now.
 **
 ** INPUT - "test_no" = test number for this test.
 **       - "exec_count" = current execution count.
 **       - Global variable "ddr_mem_size" must contain the total bytes
 **         of DDR RAM available in the system.
 **
 ** OUTPUT - The data lines in at least the first four DIMM sockets will be
 **          verified to be working.
 **        - Module global variable "test_results_flag" will be set to "FAIL"
 **          if any problems are detected by the data lines test.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void address_lines_test(int test_no, int exec_count)
{
  /* NOTE: All pointers are still only 32-bits long even though they may
           point to 64-bit data!!!
  */
  DECLARE_GLOBAL_DATA_PTR;      /* setup gbl data ptr, need some global data */
  uint64_t ddr_mem_size;        /* total number of bytes of DDR RAM */
  volatile uint64_t * llptr;    /* 64-bit data working pointer */
  volatile uint64_t * llptr2;   /* 2nd 64-bit data working pointer */
  u32 * lptr;                   /* 32-bit data working pointer */
  unsigned short * sptr;        /* 16-bit data working pointer */
  unsigned char * bptr;         /* 8-bit pointer */
  uint64_t next_po2_adrs;       /* calculated next "power Of 2" address */
  uint64_t llwork;              /* 64-bit working reg */
  uint64_t data_read;           /* data read back from DIMM */
  uint64_t exp_data;            /* data expected back from DIMM */
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  unsigned short swork;         /* 16-bit working reg */
  unsigned char bwork;          /* 8-bit working reg */
  int test_results_flag;        /* flag indicating test passed or failed */
  union b64_data b64;           /* union to manage a 64-bit test pattern */
  struct error_data eh;         /* create an err hand struct */
  u32 i;

  /* DEBUG - flush to start with */
  //invalidate_L1_Dcache();
  //diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */
  //octeon_flush_l2_cache(); /* call Uboots flush utility */
  //invalidate_L1_Dcache();

#if 0
  /* flush garbage from L2 cache to start with */
  llptr = (volatile u64 *) 0x10000000;
  for (i = 0; i < 0x00100000;  i +=8 )
    {
    *llptr = (u64) i;
    llptr++;
    }
   wmb();                             /* force the write to the hardware */
   syncs();
   syncw();
   syncws();

  llptr = (volatile u64 *) BEG_ADRS_LINES_TEST_ADDR;
  *llptr = 0x01234567876543210ull;
   wmb();                             /* force the write to the hardware */
   syncs();
   syncw();
   syncws();
#endif

   //printf("\nHalted!\n");
   //while(1);
  test_results_flag = PASS;     /* init the flag */

  ddr_mem_size = gd->ram_size;  /* get total size of ddr RAM in bytes */

  ddr_mem_size = 0x00400000; /* DEBUG - set max RAM size */
  //ddr_mem_size = 0x00200000; /* DEBUG - set max RAM size */

  printf("\nddr_mem_size = %08lX\n", (u32) ddr_mem_size);
  /* init all of RAM with same data */

  /* begin debug code */
  llptr = (volatile u64 *) BEG_ADRS_LINES_TEST_ADDR;
  llptr2 = (volatile u64 *) form_evict_addr((u64) llptr, 0x80LL);
  if ((u64) llptr2 >= ddr_mem_size)
    llptr2 = (volatile u64 *) form_evict_addr((u64) llptr, -0x80LL);

#if 0
#if 0
  *llptr = (uint64_t) 0x0102030405060708ull;
  llptr++;
  *llptr = (uint64_t) 0x0202030405060708ull;
  llptr++;
  *llptr = (uint64_t) 0x0302030405060708ull;
  printf("llptr = %08lX\n",(u32) llptr);
  while(1);
  return;
#else
  do
    {
      //*llptr = (uint64_t) 0x0102030405060708ull;
    *llptr = (uint64_t) llptr; /* write own address */
    llptr++;
    if ((0x00020000 % (u32) llptr) == 0)
      printf("adrs: %08lX\n",(u32) llptr);

    } while (llptr < (uint64_t) ddr_mem_size);
#endif
#endif
  /* end debug code */

#if 0 /* original code */
  for (i = 0; i < ((u32) ddr_mem_size / 8); i++)
  //for (i = 0; i < lwork ; i++)
    //llptr[i] = (uint64_t) ADRS_LINES_TEST_FILL_VAL;
    llptr[i] = (uint64_t) 0x0102030405060708ull;
#else
  do
    {
      //*llptr = (uint64_t) 0x0102030405060708ull;
      /* calculate evict address */
    llptr2 = (volatile u64 *) form_evict_addr((u64) llptr, 0x80LL);
    if ((u64) llptr2 >= ddr_mem_size)
      llptr2 = (volatile u64 *) form_evict_addr((u64) llptr, -0x80LL);

    *llptr = (uint64_t) ADRS_LINES_TEST_FILL_VAL;
    //*llptr2 = (uint64_t) ADRS_LINES_TEST_FILL_VAL; /* evict previous write */
    wmb();                             /* force the write to the hardware */
    syncs();
    syncw();
    syncws();
    llptr++;
    if ((0x00020000 % (u32) llptr) == 0)
      printf("adrs: %08lX\n",(u32) llptr);

    } while (llptr < (uint64_t) ((u64)BEG_ADRS_LINES_TEST_ADDR + ddr_mem_size));

#endif

  printf("llptr = %08lX\n",(u32) llptr);

  /**
   ** Put a unique pattern at every "power of 2" location 
   **/
  bptr = (unsigned char *) BEG_ADRS_LINES_TEST_ADDR;
  lwork = (unsigned long) bptr +1;
  bwork = (unsigned char) (lwork & 0xFF);
  bptr[1] = bwork;                     /* 2^0 (1-byte) */
  wmb();                             /* force the write to the hardware */

  sptr = (unsigned short *) BEG_ADRS_LINES_TEST_ADDR;
  lwork = (unsigned long) sptr;
  swork = (unsigned short) (lwork +2);
  sptr[1] = swork;                    /* 2^1 (2-bytes) */
  wmb();                             /* force the write to the hardware */

  lptr = (u32 *) BEG_ADRS_LINES_TEST_ADDR;
  lwork = (unsigned long) lptr;
  lptr[1] = (lwork + 4);                    /* 2^2 (4-bytes) */
  wmb();                             /* force the write to the hardware */

  /**    Fill all remaining "power-of-2" locations with an 
   ** 8-byte value of it's own address.
   **/
  llptr = (uint64_t *) (BEG_ADRS_LINES_TEST_ADDR +8);
  b64.llwork = (uint64_t) llptr;
#if 0 /* orig */
  do
    {
    lwork = (u32) llptr;   /* get a 32-working copy of test adrs pointer */
    llwork = (u64) lwork;  /* convert it to a 64-bit value */
    *llptr = (u64) llwork; /* write pointer's value to its own adrs */

    lwork = (u32) llptr;   /* get a 32-working copy of test adrs pointer */
    lwork = (lwork << 1);/* cal next power of 2 address */
    //lwork = (u32) llwork;  /* 64-bit data pointers are only 32-bits long */
    llptr = (u64 *) lwork; /* set pointer to new adrs */
    } while (llwork < ddr_mem_size);
#else /* new way - this works */
  do
    {
    llptr2 = (volatile u64 *) form_evict_addr((u64) llptr, 0x80LL);
    if ((u64) llptr2 >= ddr_mem_size)
      llptr2 = (volatile u64 *) form_evict_addr((u64) llptr, -0x80LL);

    *llptr = b64.llwork;    /* write pointer's value to its own adrs */
    //*llptr2 = b64.llwork;    /* evict previous write from L2 cache */
    wmb();                             /* force the write to the hardware */
    syncs();
    syncw();
    syncws();

    b64.ul.lo_work = (b64.ul.lo_work << 1); /* cal next power of 2 address */
    llptr = (u64 *) b64.llwork; /* set pointer to new adrs */

    } while (b64.llwork < ((u64)BEG_ADRS_LINES_TEST_ADDR + ddr_mem_size));
#endif

  //diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */
    //octeon_flush_l2_cache(); /* call Uboots flush utility */

  /**   Every location is now written with either the fill value or
   ** its own address as shown below:
   ** adrs      value
   ** --------- ------------------
   ** 00000000  0x00                fill value
   ** 00000001  0x01                2^0
   ** 00000002  0x0002              2^1
   ** 00000004  0x00000004          2^2
   ** 00000008  0x0000000000000008  2^3
   ** 00000010  0x0000000000000010  2^4
   ** 00000018  0x0000000000000000  fill value
   ** 00000020  0x0000000000000020  2^5
   **    :                          fill value
   ** 00000040  0x0000000000000040  2^6
   **   etc
   **
   ** All other locations contain the fill value.
   **
   ** Verify every location contains the val written as described above.
   **/

  /*  manually verify the first few locations */

  /**
   **  Verify byte fill value @ adrs: 0x00000000 
   **/
  bptr = (unsigned char *) BEG_ADRS_LINES_TEST_ADDR;
  lwork = (u32) bptr;
  data_read = (uint64_t) lwork;     /* verify fill value @ adrs: 0 */
  if (data_read != (uint64_t) ADRS_LINES_TEST_FILL_VAL)
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0090;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) bptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = (u64) ADRS_LINES_TEST_FILL_VAL;
    eh.rec_data = data_read;
    eh.length = BYTES_1;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    test_results_flag = FAIL;
    return;
    }

  /**
   **  Verify byte "Power Of 2" location @ adrs: 0x00000001
   **/
  bptr = (unsigned char *) (BEG_ADRS_LINES_TEST_ADDR +1);
  lwork = (u32) bptr;
  exp_data = (u64) lwork;
  exp_data = (exp_data & 0xFF);           /* calc exp data */
  data_read = (uint64_t) *bptr;     /* 2^0 (1-byte) @ adrs: 0x01 */

  if (data_read != exp_data)
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0090;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) bptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = exp_data;
    eh.rec_data = data_read;
    eh.length = BYTES_1;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    test_results_flag = FAIL;
    return;
    }

  /**
   **  Verify short "Power Of 2" location @ adrs: 0x00000002
   **/
  sptr = (unsigned short *) (BEG_ADRS_LINES_TEST_ADDR + 2);
  lwork = (u32) sptr;
  exp_data = (u64) lwork;          /* calc expected data */
  data_read = (uint64_t) *sptr;    /* 2^1 (2-bytes) */

  if (data_read != exp_data)
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0090;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) sptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = exp_data;
    eh.rec_data = data_read;
    eh.length = BYTES_2;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    test_results_flag = FAIL;
    return;
    }

  /**
   **  Verify short "Power Of 2" location @ adrs: 0x00000004
   **/
  lptr = (u32 *) (BEG_ADRS_LINES_TEST_ADDR + 4);
  lwork = (u32) lptr;
  exp_data = (u64) lwork;          /* calc expected data */
  data_read = (uint64_t) *lptr;    /* 2^2 (4-bytes) */

  if (data_read != exp_data)
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0090;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) lptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = exp_data;
    eh.rec_data = data_read;
    eh.length = BYTES_4;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    test_results_flag = FAIL;
    return;
    }

  /**
   **  Verify all remaining data, starting on the 1st 8-byte boundary,
   ** is correct.
   **/
  llptr = (uint64_t *) (BEG_ADRS_LINES_TEST_ADDR + 8); /* beg adrs of verify */
  next_po2_adrs = 0x0000000000000008ull;               /* init next PO2 adrs */
  exp_data = (u64) ADRS_LINES_TEST_FILL_VAL;           /* set exp fill data */

  do
    {
    data_read = *llptr;             /* read next 8-byte location */

    if ((u32) llptr == (u32) next_po2_adrs)
      { /* verify this location contains next PO2 adrs */
      if (data_read != next_po2_adrs)
        {
        eh.call_type = EH_DISP_TYP_INFO;
        eh.error_stop = ES0090;
        eh.sup_error_stop = SES0000;
        lwork = (uint32_t) llptr;
        fail_adrs = (uint64_t) lwork;
        eh.fail_adrs = fail_adrs;
        eh.exp_data = next_po2_adrs;
        eh.rec_data = data_read;
        eh.length = BYTES_8;
        eh.test_no = test_no;
        eh.exec_count = exec_count;

        p1_error_handler(&eh);        /* report the error to the system */
        test_results_flag = FAIL;
        return;
        }
      next_po2_adrs = (next_po2_adrs << 1);   /* calc next PO2 adrs */
      }
    else
      { /* verify this location still contains fill value */
      if (data_read != exp_data)
        {
        eh.call_type = EH_DISP_TYP_INFO;
        eh.error_stop = ES0090;
        eh.sup_error_stop = SES0000;
        lwork = (uint32_t) llptr;
        fail_adrs = (uint64_t) lwork;
        eh.fail_adrs = fail_adrs;
        eh.exp_data = exp_data;
        eh.rec_data = data_read;
        eh.length = BYTES_8;
        eh.test_no = test_no;
        eh.exec_count = exec_count;

        p1_error_handler(&eh);        /* report the error to the system */
        test_results_flag = FAIL;
        return;
        }
      }

    llptr++;                        /* inc pointer to next 8-byte adrs */

    /* loop till reach end of DDR2 RAM */
    } while ((u32) llptr < (u32) ((u64)BEG_ADRS_LINES_TEST_ADDR + ddr_mem_size));

 /* everything passed */
  if (test_results_flag == PASS)
    printf("Passed\n");

}

/*****************************************************************************
 **                       Cavium RAM Cells Test
 **
 **   This function verifies every location (single cell) in every DDR DIMM 
 ** is capable of reading and writing a variety of test patterns proving each
 ** cell has no stuck-ats or stuck-to bits.  In this case, each Cell is
 ** 64-bits long.
 **
 **  The Cavium processor has 128 data bits.  The first 64 are connected to one
 ** DIMM the last 64 are connected to the 2nd DIMM.  Therefore, each DIMM has
 ** its own address and data lines the require verification.
 **
 ** NOTE:  This function assumes there are four DIMMs available for now.
 **
 ** INPUT - "test_no" = test number for this test.
 **       - "exec_count" = current execution count.
 **       - Global variable "ddr_mem_size" must contain the total bytes
 **         of DDR RAM available in the system.
 **
 ** OUTPUT - The RAM cells in at least the first four DIMM sockets will be
 **          verified to be working.
 **        - Module global variable "test_results_flag" will be set to "FAIL"
 **          if any problems are detected by the cells test.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void ram_cells_test(int test_no, int exec_count)
{
  /* NOTE: All pointers are still only 32-bits long even though they may
           point to 64-bit data!!!
  */
  DECLARE_GLOBAL_DATA_PTR;      /* setup gbl data ptr, need some global data */
  uint64_t ddr_mem_size;        /* total number of bytes of DDR RAM */
  uint64_t * llptr;             /* 64-bit data working pointer */
  uint64_t * tp   ;             /* pointer to 64-bit test patterns */
  uint64_t data_read;           /* data read back from DIMM */
  uint64_t exp_data;            /* data expected back from DIMM */
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  int test_results_flag;        /* flag indicating test passed or failed */
  struct error_data eh;         /* create an err hand struct */
  u32 i;

  test_results_flag = PASS;     /* init the flag */

  ddr_mem_size = gd->ram_size;  /* get total size of ddr RAM in bytes */

  tp = (u64 *) data_test_pats_64b;    /* point to beg of test patterns */

  do
    {
    llptr = (u64 *) BEG_ADRS_LINES_TEST_ADDR; /* point to beg of RAM */
    exp_data = *tp;                      /* load next test pattern */

    /* fill RAM with next test pattern */
    for (i = 0; i < (u32) ddr_mem_size; i++)
      llptr[i] = exp_data;

    /* read back and verify every location */
    do
      {
      data_read = *llptr;             /* read next 8-byte location */

      if (data_read != exp_data)
        {
        eh.call_type = EH_DISP_TYP_INFO;
        eh.error_stop = ES0110;
        eh.sup_error_stop = SES0000;
        lwork = (uint32_t) llptr;
        fail_adrs = (uint64_t) lwork;
        eh.fail_adrs = fail_adrs;
        eh.exp_data = exp_data;
        eh.rec_data = data_read;
        eh.length = BYTES_8;
        eh.test_no = test_no;
        eh.exec_count = exec_count;

        p1_error_handler(&eh);        /* report the error to the system */
        //report_error(0x00, fail_adrs, exp_data, data_read, BYTES_8);
        test_results_flag = FAIL;
        return;
        }

      llptr++;                        /* inc pointer to next 8-byte adrs */
      } while ((u32) llptr < (u32) ddr_mem_size); /* loop till reach end of DDR2 RAM */

    tp++;                             /* inc pointer to next test pattern */
    } while (*tp != (u64) END_OF_TABLE);

  /* everything passed */
  if (test_results_flag == PASS)
    printf("Passed\n");

}

/*****************************************************************************
 **                       Cavium RAM ECC Cells Test
 **
 **   This function verifies the ECC generation and verification logic is
 ** working and every ECC location (single cell) in every DDR DIMM 
 ** is capable of reading and writing a variety of test patterns proving each
 ** ECC cell has no stuck-ats or stuck-to bits.  ECC cells are each 32-bits 
 ** long and contain the syndrome bits for each 12-bit DDR2 RAM cell.
 ** Test:
 ** - ECC single bit detection.  
 **   There is no way to force a single bit error because we do not have
 **   the ability to write data to RAM and leave the ECC bits alone.  When
 **   ECC is disabled, all ECC bits get written to zero.
 **   So we will have to settle for forcing multi-bit errors.  To do this
 **   we will write data to a location with ECC disabled (forcing all ECC
 **   bits to zero).  Then enable ECC checking and read the data back from
 **   that same location.  We had better get at least a single-bit error
 **   but much more likely get multi-bit errors proving the ECC generation
 **   and checking is working.
 ** - ECC Data Lines test
 **   Verifiy all 32 ECC data bits, on each DIMM, are connected.  This is
 **   a little difficult because we cannot read the actual ECC Data bits back
 **   from the ECC cell but we can read the data the was supposably written
 **   to that cell on the last data write to memory when ECC generation was
 **   enabled.
 ** - ECC Address Lines test
 **   We do not run an ECC address lines test because we have no ability to 
 **   view was is in the ECC cells.  Instead we rely on the normal DDR RAM
 **   address lines test, with ECC enabled, to verify the ECC cells address
 **   lines as well.
 ** - ECC Cells test
 **    ~ Enable ECC generation and checking.
 **    ~ Clear all ECC error registers.
 **    ~ Write a series of special data test patterns that will in turn write
 **      an appropriate test pattern to the ECC cells to verify not bits are
 **      stuck low or high or stuck to another bit.
 **    ~ Verify no ECC failures were detected.
 ** - Clean up any lingering EC failure registers.
 ** - Enable ECC generation/detection again and clear all of memory to 
 **   reset all data and set up initial ECC cells.
 **
 ** NOTE:  This function assumes there are four DIMMs available for now.
 **
 ** INPUT - "test_no" = test number for this test.
 **       - "exec_count" = current execution count.
 **       - Global variable "ddr_mem_size" must contain the total bytes
 **         of DDR RAM available in the system.
 **
 ** OUTPUT - The ECC cells in at least the first four DIMM sockets will be
 **          verified to be working.
 **        - Module global variable "test_results_flag" will be set to "FAIL"
 **          if any problems are detected by the cells test.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void ddr_ram_ecc_test(int test_no, int exec_count)
{
  /* NOTE: All pointers are still only 32-bits long even though they may
           point to 64-bit data!!!
  */
  DECLARE_GLOBAL_DATA_PTR;      /* setup gbl data ptr, need some global data */
  uint64_t ddr_mem_size;        /* total number of bytes of DDR RAM */
  uint64_t * llptr;             /* 64-bit data working pointer */
  uint64_t * tp   ;             /* pointer to 64-bit test patterns */
  uint64_t data_read;           /* data read back from DIMM */
  uint64_t exp_data;            /* data expected back from DIMM */
  uint64_t data_read_sav;       /* saved data read back from DIMM */
  uint64_t exp_data_sav;        /* saved data expected back from DIMM */
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  uint64_t llwork;              /* 64-bit working reg */
  char umsg[80];                /* user created message */
  int test_results_flag;        /* flag indicating test passed or failed */
  struct error_data eh;         /* create an err hand struct */
  u32 i;

  test_results_flag = PASS;     /* init the flag */
  ddr_mem_size = gd->ram_size;  /* get total size of ddr RAM in bytes */

  /**
   ** Disable ECC & clear all ECC errror registers 
   **/
  llwork = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); /* read DDR CFG 0 reg */
  llwork &= ~LMC_MEM_CFG0_ECC_ENA;  /* clear ECC enable bit */
  llwork &= ~LMC_MEM_CFG0_DED_ERR;  /* clear any double-bit ECC errores */
  llwork &= ~LMC_MEM_CFG0_SEC_ERR;  /* clear any single-bit ECC errores */
  cvmx_write_csr(CVMX_LMCX_MEM_CFG0(0), llwork); /* disable ECC & clr errors */

  llptr = (u64 *) BEG_ADRS_LINES_TEST_ADDR; /* point to beg of RAM */

  /* write data and force ECC syndrome bits to zero */
  *llptr = 0x1234567887654321ull;
  diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */

  /* verify there are no ECC errors detected */
  data_read = (cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)) & LMC_MEM_CFG0_ECC_ERRS);
  exp_data = 0x0ull; /* no ecc error bits should be set at this point */

  if (data_read != exp_data)
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0150;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) llptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = exp_data;
    eh.rec_data = data_read;
    eh.length = BYTES_8;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    //report_error(0x00, fail_adrs, exp_data, data_read, BYTES_8);
    test_results_flag = FAIL;
    clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
    return;
    }

  /**
   **    Now turn on ECC checking, read the same address we wrote above.
   ** Should see an ECC error proving the ECC logic is actually working.
   **/
  llwork = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); /* read DDR CFG 0 reg */
  llwork |= LMC_MEM_CFG0_ECC_ENA;
  cvmx_write_csr(CVMX_LMCX_MEM_CFG0(0), llwork); /* enable ECC gen/checking */

  llwork = *llptr;               /* read data from loc with bad ECC bits */

  /* read DDR config reg */
  data_read = (cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)) & LMC_MEM_CFG0_ECC_ERRS);
  exp_data = 0x0ull; /* set up "no ECC error bits active" for compare */

  if (data_read == exp_data)  /* if no ECC errors, report an error */
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0160;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) llptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = exp_data;
    eh.rec_data = data_read;
    eh.length = BYTES_8;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    //report_error(0x00, fail_adrs, exp_data, data_read, BYTES_8);
    test_results_flag = FAIL;
    clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
    return;
    }

  /* Verify ECC error address captured the correct failure address */
  llwork = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); /* read DDR CFG 0 reg */
  llwork |= LMC_MEM_CFG0_ECC_ENA;
  cvmx_write_csr(CVMX_LMCX_MEM_CFG0(0), llwork); /* enable ECC gen/checking */

  llwork = *llptr;               /* read data from loc with bad ECC bits */

  /* read the "Failing Address" register */
  data_read = cvmx_read_csr(CVMX_LMCX_FADR(0));
  exp_data = EXP_FAIL_ADRS_REG; /* set up expected data in "LMC_FADR" reg */

  if (data_read != exp_data)  /* correct address captured? */
    {
    eh.call_type = EH_DISP_TYP_INFO;
    eh.error_stop = ES0170;
    eh.sup_error_stop = SES0000;
    lwork = (uint32_t) llptr;
    fail_adrs = (uint64_t) lwork;
    eh.fail_adrs = fail_adrs;
    eh.exp_data = exp_data;
    eh.rec_data = data_read;
    eh.length = BYTES_8;
    eh.test_no = test_no;
    eh.exec_count = exec_count;

    p1_error_handler(&eh);        /* report the error to the system */
    //report_error(0x00, fail_adrs, exp_data, data_read, BYTES_8);
    test_results_flag = FAIL;
    clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
    return;
    }

  /* clear all ECC errors but leave ECC enabled */
  llwork = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); /* read DDR CFG 0 reg */
  llwork &= ~LMC_MEM_CFG0_DED_ERR;  /* clear any double-bit ECC errores */
  llwork &= ~LMC_MEM_CFG0_SEC_ERR;  /* clear any single-bit ECC errores */
  cvmx_write_csr(CVMX_LMCX_MEM_CFG0(0), llwork); /* clr all ECC errors */

  /**
   **  Verify the data lines to the ECC cells by writing then reading a
   ** special set of data patterns that will produce the appropriate
   ** bit patterns to verify the data lines to the ECC cells.
   **/
  tp = (u64 *) ecc_data_test_pats_64b;    /* point to beg of test patterns */

  do
    {
    exp_data = *tp;                      /* load next test pattern */
    *llptr = exp_data;                   /* write it to test location */
    diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */
    data_read = *llptr;                  /* read it back */

    /* verify data did not change */
    data_read_sav = data_read;      /* save copies in case we need it later */
    exp_data_sav = exp_data;
    if (data_read != exp_data)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0180;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = exp_data;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      //report_error(0x00, fail_adrs, exp_data, data_read, BYTES_8);
      test_results_flag = FAIL;
      clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
      return;
      }

    /* verify no ECC errors are detected using this test pattern */
    data_read = (cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)) & LMC_MEM_CFG0_ECC_ERRS);
    exp_data = 0x0ull; /* no ecc error bits should be set */

    if (data_read != exp_data)
      {
      eh.call_type = EH_DISP_TYP_INFO_MSG;
      eh.error_stop = ES0150;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = exp_data;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      /* create an additional msg to be displayed */
      sprintf(umsg, "Data exp = %016X\nData rec = %016X\n",exp_data_sav, 
              data_read_sav);
      p1_error_handler(&eh);        /* report the error to the system */
      //report_error(umsg, fail_adrs, exp_data, data_read, BYTES_8);
      test_results_flag = FAIL;
      clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
      return;
      }

    tp++;                             /* inc pointer to next test pattern */
    } while (*tp != (u64) END_OF_TABLE);

  /**  Write a variety of special test patterns to RAM that will verify the
   ** data lines in each ECC cell are not stuck at any level or stuck to 
   ** another bit.
   **/
  tp = (u64 *) ecc_data_test_pats_64b;    /* point to beg of test patterns */

  do
    {
    llptr = (u64 *) BEG_ADRS_LINES_TEST_ADDR; /* point to beg of RAM */
    exp_data = *tp;                      /* load next test pattern */

    /* fill ECC Cells with next test pattern */
    for (i = 0; i < (u32) ddr_mem_size; i++)
      llptr[i] = exp_data;

    //diag_flush_cache(CACHE_FLUSH_ADR_DATA_LINES_TEST); /* flush Dcache to RAM */

    /* read back and verify every location */
    exp_data = *tp;                      /* load exp data */
    do
      {
      data_read = *llptr;             /* read next 8-byte location */

      if (data_read != exp_data)
        {
        eh.call_type = EH_DISP_TYP_INFO;
        eh.error_stop = ES0190;
        eh.sup_error_stop = SES0000;
        lwork = (uint32_t) llptr;
        fail_adrs = (uint64_t) lwork;
        eh.fail_adrs = fail_adrs;
        eh.exp_data = exp_data;
        eh.rec_data = data_read;
        eh.length = BYTES_8;
        eh.test_no = test_no;
        eh.exec_count = exec_count;

        p1_error_handler(&eh);        /* report the error to the system */
        //report_error(0x00, fail_adrs, exp_data, data_read, BYTES_8);
        test_results_flag = FAIL;
        clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
        return;
        }

      llptr++;                        /* inc pointer to next 8-byte adrs */
      } while ((u32) llptr < (u32) ddr_mem_size); /* loop till reach end of DDR2 RAM */

    /* verify no ECC errors are detected using this test pattern */
    data_read = (cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)) & LMC_MEM_CFG0_ECC_ERRS);
    exp_data = 0x0ull; /* no ecc error bits should be set */

    if (data_read != exp_data)
      {
      eh.call_type = EH_DISP_TYP_INFO;
      eh.error_stop = ES0200;
      eh.sup_error_stop = SES0000;
      lwork = (uint32_t) llptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.exp_data = exp_data;
      eh.rec_data = data_read;
      eh.length = BYTES_8;
      eh.test_no = test_no;
      eh.exec_count = exec_count;

      p1_error_handler(&eh);        /* report the error to the system */
      //report_error(umsg, fail_adrs, exp_data, data_read, BYTES_8);
      test_results_flag = FAIL;
      clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */
      return;
      }

    tp++;                             /* inc pointer to next test pattern */
    } while (*tp != (u64) END_OF_TABLE);

  clear_and_enable_ecc(); /* clear all ECC errors & enable ECC */

  /* everything passed */
  if (test_results_flag == PASS)
    printf("Passed\n");

}

/*****************************************************************************
 **                   Clear ECC Failures & Enable ECC
 **
 **   This function clears all ECC failure bits in all the appropriate
 ** registers and enables ECC.
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - All ECC error registers and error status bits are cleared
 **          or set as follows:
 **          - clear LMC_MEM_CFG0[DED_ERR]
 **          - clear LMC_MEM_CFG0[SEC_ERR]
 **          - clear LMC_FADR
 **          - set LMC_MEM_CFG0[ECC_ENA]
 **
 ** RETURN - Nothing
 **/
void clear_and_enable_ecc(void)
{
  uint64_t llwork;              /* 64-bit working reg */

  /* clear all ECC errors and enable ECC */
  llwork = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); /* read DDR CFG 0 reg */
  llwork &= ~LMC_MEM_CFG0_DED_ERR;  /* clear any double-bit ECC errores */
  llwork &= ~LMC_MEM_CFG0_SEC_ERR;  /* clear any single-bit ECC errores */
  llwork |= LMC_MEM_CFG0_ECC_ENA;
  cvmx_write_csr(CVMX_LMCX_MEM_CFG0(0), llwork); /* clr all ECC errors */

}
