diff options
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c')
-rwxr-xr-x | cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c | 439 |
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; +} + |