summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c')
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c439
1 files changed, 439 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c
new file mode 100755
index 0000000..96d5000
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c
@@ -0,0 +1,439 @@
+/***************************************************************************
+*
+* Copyright (c) 2004 Broadcom Corporation, All Rights Reserved.
+* Contains proprietary and confidential information.
+*
+* No portions of this material may be reproduced in any form without the
+* written permission of:
+*
+* Broadcom Corporation
+* 16215 Alton Parkway
+* P.O. Box 57013
+* Irvine, California 92619-7013
+*
+* All information contained in this document is Broadcom Corporation
+* company private, proprietary, and trade secret.
+*
+****************************************************************************/
+#include "lib_types.h"
+#include "bcm_map.h"
+
+// Uncomment out the below line to use MemoryTestSuite()
+// #define EXTENDED_MEMORY_TESTS
+
+/* ---- Private Constants and Types -------------------------------------- */
+#define VCDL_PHASE_DEFAULT 16
+#define VCDL_PHASE_MAX 47 /* 154.69 degree */
+#define VCDL_PHASE_MIN 0 /* 22.5 degree */
+
+typedef unsigned long u;
+
+#define N 32*1024 // Size of the copy operation
+ // Must be at least equal to the L2 cache size
+#define S (1*sizeof(u))
+
+/* ---- Private Function Prototypes -------------------------------------- */
+inline static int MemoryTest(void) __attribute__((always_inline));
+inline static void PI_upper_set(volatile uint32 *, int bitOffset, int shift) __attribute__((always_inline));
+inline static void PI_shmoo(volatile uint32 *PI_reg, int bitOffset, int minValue, int maxValue, int increment) __attribute__((always_inline));
+inline static void shmooVcdl(int minValue, int maxValue, int increment) __attribute__((always_inline));
+
+// #define DEBUG_SHMOO 1
+#if DEBUG_SHMOO
+inline static void dumpChar(uint8 c) __attribute__((always_inline));
+inline static void dumpChar(uint8 c)
+{
+ //wait till tx fifo below threshold
+ while (UART->txf_levl > 14);
+ UART->Data = c;
+}
+
+#else
+#define dumpChar(c)
+#endif
+
+#if defined(EXTENDED_MEMORY_TESTS)
+#include "memtest.c"/* Suite memory tests SCAN, MARCH, SLIDING, SHIFT ADDRESS */
+inline static int MemoryTestSuite(void) __attribute__((always_inline));
+#endif
+
+/* ==== Public Functions ================================================= */
+void sdramDqsPhaseSet(void);
+void vcdlCalibration(void);
+
+/*******************************************************************************/
+void sdramDqsPhaseSet(void)
+{
+ int dqOutPhaseMax;
+ int delay;
+ int ubusPhase, mipsPhase;
+ int equalCount = 0;
+
+ // Reset VCDL
+ DDR->Spare1 |= 0x1;
+ delay = 1000;
+ while(delay--);
+ DDR->Spare1 &= ~0x1;
+
+ // Calculate max phase offset from PLL config register.
+ dqOutPhaseMax = ((DDR->MIPSDDRPLLMDiv & DDR_MDIV_MASK) >> DDR_MDIV_SHFT) * 8;
+
+ dumpChar('\n');
+ dumpChar('\r');
+
+ // Start by setting VCDL to the default. This almost always works.
+ // Enable squelch
+ DDR->WSliceCntl |= (0x1<<20) | (0x1<<4);
+ DDR->VCDLPhaseCntl0 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ DDR->VCDLPhaseCntl1 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4));
+
+ // Now shmoo over DQ phase to find an optimum value.
+ dumpChar('D');dumpChar('D');dumpChar('R');dumpChar('2');
+ dumpChar('\n');
+ dumpChar('\r');
+ PI_shmoo(&DDR->DDR1_2PhaseCntl0, 16, -dqOutPhaseMax, dqOutPhaseMax, 1);
+
+ dumpChar('V');dumpChar('C');dumpChar('D');dumpChar('L');
+ dumpChar('\n');
+ dumpChar('\r');
+ shmooVcdl(VCDL_PHASE_MIN, VCDL_PHASE_MAX, 1);
+
+ // Now setup the UBUS clock
+ dumpChar('U');dumpChar('B');dumpChar('U');dumpChar('S');
+ dumpChar('\n');
+ dumpChar('\r');
+
+ MEMC->RefreshPdControl &= ~MEMC_REFRESH_ENABLE; // Turn off refresh while messing with UBus clock
+
+ DDR->MIPSPhaseCntl &= ~(0x1<<23); // turn off ubus PI auto mode
+
+ mipsPhase = DDR->MIPSPhaseCntl;
+ do {
+ if (DDR->MIPSPhaseCntl == mipsPhase)
+ equalCount++;
+ else {
+ equalCount = 0;
+ mipsPhase = DDR->MIPSPhaseCntl;
+ }
+ } while (equalCount < 3);
+
+ ubusPhase = ((DDR->UBUSPhaseCntl) & 0x3ffe); // make it even and decrease count
+ DDR->UBUSPhaseCntl = ubusPhase;
+
+ // Wait until we match several times in a row, to be sure we wait long enough
+ do {
+ if (DDR->UBUSPhaseCntl == ubusPhase)
+ equalCount++;
+ else
+ equalCount = 0;
+ } while (equalCount < 3);
+
+ MEMC->RefreshPdControl |= MEMC_REFRESH_ENABLE;
+}
+
+
+/* ==== Private Functions ================================================ */
+
+inline static void PI_upper_set(volatile uint32 *PI_reg, int bitOffset, int shift)
+{
+ uint32 oldVal;
+ uint32 newVal;
+ int32 oldPhase;
+ int32 newPhase;
+ int equalCount = 0;
+
+ oldVal = *PI_reg; // get the phase config (may have other controls in other 16 bits)
+
+ oldPhase = ( oldVal >> bitOffset ) & 0x3fff;
+ if ( oldPhase & (0x1<<13) ) {
+ oldPhase |= ~0x3fff; // sign extend
+ }
+
+ newPhase = shift & 0x3fff; // set up phase shift value[13:0]
+ if (shift > oldPhase) { // set up up/down [14], shift is signed value
+ newPhase |= 0x1<<14;
+ }
+
+ newPhase = newPhase << bitOffset;
+ oldVal = oldVal & (0xffff << (16-bitOffset)); // Keep the other control bits
+ newVal = newPhase | oldVal;
+ *PI_reg = newVal;
+
+ // Wait until we match several times in a row, to be sure we wait long enough
+ do {
+ if (*PI_reg == newVal)
+ equalCount++;
+ else
+ equalCount = 0;
+ } while (equalCount < 3);
+}
+
+
+inline static void PI_shmoo(volatile uint32 *PI_reg, int bitOffset, int minValue, int maxValue, int increment)
+{
+ int piPhase, piPhaseCnt, passStatus;
+ int pass1Start, pass1Fail, pass2Start, pass2Fail;
+ int pass1Cnt, pass2Cnt;
+
+ PI_upper_set(PI_reg, bitOffset, minValue);
+
+ passStatus = 0;
+ pass1Start = maxValue;
+ pass1Fail = minValue;
+ pass2Start = minValue;
+ pass2Fail = minValue;
+
+ for (piPhase = minValue; piPhase <= maxValue; piPhase += increment) {
+
+ // if (MemoryTestSuite())
+ if (MemoryTest())
+ {
+ if (passStatus == 0x0) { // first_pass start
+ passStatus = 0x1;
+ pass1Start = piPhase;
+ }
+ else if (passStatus == 0x2) { // second_pass start
+ passStatus = 0x3;
+ pass2Start = piPhase;
+ }
+ dumpChar('p');
+ }
+ else {
+ if (passStatus == 0x1) { // fisrt_pass end
+ passStatus = 0x2;
+ pass1Fail = piPhase;
+ }
+ else if (passStatus == 0x3) { // second_pass end
+ passStatus = 0x4;
+ pass2Fail = piPhase;
+ }
+ dumpChar('.');
+ }
+
+ piPhaseCnt = ( piPhase + 0x01) & 0x3fff;
+ if (increment) {
+ piPhaseCnt |= (0x01<<14);
+ }
+
+ *PI_reg = (*PI_reg & (0xffff << (16-bitOffset))) | (piPhaseCnt<<bitOffset);
+
+ }
+
+ // Figure out the middle point of the pass window
+ // valid window 1 -- .......PPPPPPPPPPPPPP.......
+ // valid window 2 -- PPPPPPP........PPPPPPPPPPPPP
+
+ if ((pass1Start != maxValue) && (pass2Start == minValue)) { // valid window 1
+ if (pass1Fail == minValue) {
+ piPhaseCnt = (pass1Start + maxValue) >> 1; // mid-point of the pass window
+ } else {
+ piPhaseCnt = (pass1Start + pass1Fail - 0x1) >> 1; // mid-point of the pass window
+ }
+ }
+ else if ((pass1Start == minValue) && (pass2Start != minValue) && (pass2Fail == minValue)) { // valid window 2
+ pass1Cnt = pass1Fail - minValue;
+ pass2Cnt = maxValue - pass2Start + 1;
+ passStatus= (pass1Cnt + pass2Cnt) >> 1;
+ if (passStatus < pass1Cnt) { // mid-point of the overall pass window is in sub-window 1
+ piPhaseCnt = minValue + ( pass1Cnt - passStatus );
+ }
+ else {
+ piPhaseCnt = pass2Start - 0x1 + passStatus;
+ }
+ }
+ else {
+ piPhaseCnt = 0x0; // shmoo failed.
+ }
+
+ piPhaseCnt &= ~0x01; // make it even number
+
+ PI_upper_set(PI_reg, bitOffset, piPhaseCnt); // set the final phase value
+
+ dumpChar('\n');
+ dumpChar('\r');
+}
+
+
+inline static void shmooVcdl(int minValue, int maxValue, int increment)
+{
+ UINT32 dqsInPhase;
+ UINT32 dqsInSum = 0;
+ UINT32 passCnt = 0;
+ volatile int delay;
+
+ for (dqsInPhase = minValue; dqsInPhase <= maxValue; dqsInPhase += increment) {
+ delay = 1000;
+ while(delay--);
+ // Enable squelch
+ DDR->WSliceCntl |= (0x1<<20) | (0x1<<4);
+ DDR->VCDLPhaseCntl0 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ DDR->VCDLPhaseCntl1 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4));
+
+ delay = 1000;
+ while(delay--);
+
+#if defined(EXTENDED_MEMORY_TESTS)
+ if (MemoryTestSuite() == MEMTEST_SUCCESS )
+#else
+ if (MemoryTest())
+#endif
+ {
+ dqsInSum += dqsInPhase;
+ passCnt++;
+ dumpChar('p');
+ }
+ else {
+ dumpChar('.');
+ }
+ }
+ delay = 1000;
+ while(delay--);
+ // Enable squelch
+ DDR->WSliceCntl |= (0x1<<20) | (0x1<<4);
+ if (passCnt > 0) {
+ dqsInPhase = dqsInSum / passCnt;
+ DDR->VCDLPhaseCntl0 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ DDR->VCDLPhaseCntl1 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ }
+ else {
+ DDR->VCDLPhaseCntl0 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ DDR->VCDLPhaseCntl1 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ }
+ DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4));
+ dumpChar('\n');
+ dumpChar('\r');
+}
+
+#if defined(EXTENDED_MEMORY_TESTS)
+
+// Define the memory size for use by the memory test suite
+#define MEMORY_SIZE (2 * 1024)
+
+int MemoryTestSuite(void)
+{
+ int test = 1;
+ uint32_t * memory = (uint32_t*) (0xa0000000);
+ Pattern_t pat32, patIx;
+
+ for (patIx = PATTERN_0x00000000; patIx < PATTERN_MAX; patIx++ )
+ {
+ pat32 = pattern[ patIx ];
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanWordValue( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanBulkValue( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanBulkAltInv( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( slidingAltInv( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( slidingDiag( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+ }
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanWordSelf( memory, MEMORY_SIZE ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanBulkSelf( memory, MEMORY_SIZE ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_alt_memory( memory, MEMORY_SIZE, 0XAAAAAAAA, 0x55555555 );
+ if ( memoryBulkCopy( memory, (memory + ((MEMORY_SIZE/2)/sizeof(uint32_t))),
+ MEMORY_SIZE/2 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ // return tests;
+ return MEMTEST_SUCCESS;
+
+exit_tests:
+ return MEMTEST_FAILURE;
+
+}
+#endif /* defined(EXTENDED_MEMORY_TESTS) */
+
+//
+// Returns: 0=FAILURE, 1=SUCCESS
+inline static int MemoryTest(void)
+{
+ // Test 32-bit write/read
+ volatile uint32 *memAddr;
+ uint32 memBase;
+ uint32 testValue;
+ int i;
+ int j;
+ int k;
+
+ memBase = 0xa0000000;
+ for (i = 2; i < 24; i++) {
+ memAddr = (void *) (memBase + (1 << i));
+ for (k = 0; k < 2; k++) {
+ /* walking one */
+ testValue = 1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue <<= 1;
+ }
+ /* walking zero */
+ testValue = ~1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue = (testValue << 1) | 1;
+ }
+ /* shift in zeroes */
+ testValue = -1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ *(uint32*)memBase = 0;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue <<= 1;
+ }
+ /* shift in ones */
+ testValue = 1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ *(uint32*)memBase = 0;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue = (testValue << 1) | 1;
+ }
+ }
+ }
+ return 1;
+}
+