/*************************************************************************** * * 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<> 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; }