/*----------------------------------------------------------------------------- * Function: initdram * Description: Configures SDRAM memory banks for DDR operation. * Auto Memory Configuration option reads the DDR SDRAM EEPROMs * via the IIC bus and then configures the DDR SDRAM memory * banks appropriately. If Auto Memory Configuration is * not used, it is assumed that no DIMM is plugged *-----------------------------------------------------------------------------*/ phys_size_t initdram(int board_type) { unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; unsigned long dimm_ranks[MAXDIMMS]; unsigned long ranks; unsigned long rows; unsigned long banks; unsigned long cols; unsigned long width; unsigned long const sdram_freq = get_bus_freq(0); unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr); /* on board dimm banks */ unsigned long cas_latency = 0; /* to quiet initialization warning */ unsigned long dram_size; debug("\nEntering initdram()\n"); /*------------------------------------------------------------------ * Stop the DDR-SDRAM controller. *-----------------------------------------------------------------*/ mtsdram(DDR0_02, DDR0_02_START_ENCODE(0)); /* * Make sure I2C controller is initialized * before continuing. */ /* switch to correct I2C bus */ I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); /*------------------------------------------------------------------ * Clear out the serial presence detect buffers. * Perform IIC reads from the dimm. Fill in the spds. * Check to see if the dimm slots are populated *-----------------------------------------------------------------*/ get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks); /*------------------------------------------------------------------ * Check the frequency supported for the dimms plugged. *-----------------------------------------------------------------*/ check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); /*------------------------------------------------------------------ * Check and get size information. *-----------------------------------------------------------------*/ get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks, &cols, &width); /*------------------------------------------------------------------ * Check the voltage type for the dimms plugged. *-----------------------------------------------------------------*/ check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks); /*------------------------------------------------------------------ * Program registers for SDRAM controller. *-----------------------------------------------------------------*/ mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) | DDR0_00_DLL_START_POINT_DECODE(0x0A)); mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) | DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) | DDR0_01_INT_MASK_ENCODE(0xFF)); program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, rows, &cas_latency); program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); /* * TODO: tFAW not found in SPD. Value of 13 taken from Sequoia * board SDRAM, but may be overly conservative. */ mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) | DDR0_07_TFAW_ENCODE(13) | DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) | DDR0_07_AREFRESH_ENCODE(0)); mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) | DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) | DDR0_08_DDRII_ENCODE(1)); mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) | DDR0_09_RTT_0_ENCODE(0x1) | DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) | DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20)); program_ddr0_10(dimm_ranks, ranks); program_ddr0_11(sdram_freq); mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3)); mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) | DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) | DDR0_14_REG_DIMM_ENABLE_ENCODE(0)); mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS)); mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS)); program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width); mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) | DDR0_23_FWC_ENCODE(0)); program_ddr0_24(ranks); program_ddr0_26(sdram_freq); program_ddr0_27(sdram_freq); mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) | DDR0_28_EMRS2_DATA_ENCODE(0x0000)); mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000)); mtsdram(DDR0_42, DDR0_42_ADDR_PINS_DECODE(14 - rows) | DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency)); program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, cols, banks); program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); denali_sdram_register_dump(); dram_size = (width >= 64) ? 8 : 4; dram_size *= 1 << cols; dram_size *= banks; dram_size *= 1 << rows; dram_size *= ranks; debug("dram_size = %lu\n", dram_size); /* Start the SDRAM controler */ mtsdram(DDR0_02, DDR0_02_START_ENCODE(1)); denali_wait_for_dlllock(); #if defined(CONFIG_DDR_DATA_EYE) /* * Map the first 1 MiB of memory in the TLB, and perform the data eye * search. */ program_tlb(0, CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE); denali_core_search_data_eye(); denali_sdram_register_dump(); remove_tlb(CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE); #endif #if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, 0); sync(); /* Zero the memory */ debug("Zeroing SDRAM..."); #if defined(CONFIG_SYS_MEM_TOP_HIDE) dcbz_area(CONFIG_SYS_SDRAM_BASE, dram_size - CONFIG_SYS_MEM_TOP_HIDE); #else #error Please define CONFIG_SYS_MEM_TOP_HIDE (see README) in your board config file #endif /* Write modified dcache lines back to memory */ clean_dcache_range(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_BASE + dram_size - CONFIG_SYS_MEM_TOP_HIDE); debug("Completed\n"); sync(); remove_tlb(CONFIG_SYS_SDRAM_BASE, dram_size); #if defined(CONFIG_DDR_ECC) /* * If ECC is enabled, clear and enable interrupts */ if (is_ecc_enabled()) { u32 val; sync(); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); /* Set 'int_mask' parameter to functionnal value */ mfsdram(DDR0_01, val); mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF); #if defined(CONFIG_DDR_DATA_EYE) /* * Running denali_core_search_data_eye() when ECC is enabled * causes non-ECC machine checks. This clears them. */ print_mcsr(); mtspr(SPRN_MCSR, mfspr(SPRN_MCSR)); print_mcsr(); #endif sync(); } #endif /* defined(CONFIG_DDR_ECC) */ #endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */ program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE); return dram_size; }
/*-----------------------------------------------------------------------------+ * denali_core_search_data_eye. +----------------------------------------------------------------------------*/ void denali_core_search_data_eye(unsigned long memory_size) { int k, j; u32 val; u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X; u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0; u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0; u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0; volatile u32 *ram_pointer; u32 test[NUM_TRIES] = { 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 }; ram_pointer = (volatile u32 *)(CFG_SDRAM_BASE); for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) { /*for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) {*/ /* -----------------------------------------------------------+ * De-assert 'start' parameter. * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_02); val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; mtdcr(ddrcfgd, val); /* -----------------------------------------------------------+ * Set 'wr_dqs_shift' * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_09); val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); mtdcr(ddrcfgd, val); /* -----------------------------------------------------------+ * Set 'dqs_out_shift' = wr_dqs_shift + 32 * ----------------------------------------------------------*/ dqs_out_shift = wr_dqs_shift + 32; mtdcr(ddrcfga, DDR0_22); val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); mtdcr(ddrcfgd, val); passing_cases = 0; for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64; dll_dqs_delay_X++) { /*for (dll_dqs_delay_X=1; dll_dqs_delay_X<128; dll_dqs_delay_X++) {*/ /* -----------------------------------------------------------+ * Set 'dll_dqs_delay_X'. * ----------------------------------------------------------*/ /* dll_dqs_delay_0 */ mtdcr(ddrcfga, DDR0_17); val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); mtdcr(ddrcfgd, val); /* dll_dqs_delay_1 to dll_dqs_delay_4 */ mtdcr(ddrcfga, DDR0_18); val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); mtdcr(ddrcfgd, val); /* dll_dqs_delay_5 to dll_dqs_delay_8 */ mtdcr(ddrcfga, DDR0_19); val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); mtdcr(ddrcfgd, val); ppcMsync(); ppcMbar(); /* -----------------------------------------------------------+ * Assert 'start' parameter. * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_02); val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON; mtdcr(ddrcfgd, val); ppcMsync(); ppcMbar(); /* -----------------------------------------------------------+ * Wait for the DCC master delay line to finish calibration * ----------------------------------------------------------*/ if (wait_for_dlllock() != 0) { printf("dlllock did not occur !!!\n"); printf("denali_core_search_data_eye!!!\n"); printf("wr_dqs_shift = %d - dll_dqs_delay_X = %d\n", wr_dqs_shift, dll_dqs_delay_X); hang(); } ppcMsync(); ppcMbar(); if (wait_for_dram_init_complete() != 0) { printf("dram init complete did not occur !!!\n"); printf("denali_core_search_data_eye!!!\n"); printf("wr_dqs_shift = %d - dll_dqs_delay_X = %d\n", wr_dqs_shift, dll_dqs_delay_X); hang(); } udelay(100); /* wait 100us to ensure init is really completed !!! */ /* write values */ for (j=0; j<NUM_TRIES; j++) { ram_pointer[j] = test[j]; /* clear any cache at ram location */ __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); } /* read values back */ for (j=0; j<NUM_TRIES; j++) { for (k=0; k<NUM_READS; k++) { /* clear any cache at ram location */ __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); if (ram_pointer[j] != test[j]) break; } /* read error */ if (k != NUM_READS) break; } /* See if the dll_dqs_delay_X value passed.*/ if (j < NUM_TRIES) { /* Failed */ passing_cases = 0; /* break; */ } else { /* Passed */ if (passing_cases == 0) dll_dqs_delay_X_sw_val = dll_dqs_delay_X; passing_cases++; if (passing_cases >= max_passing_cases) { max_passing_cases = passing_cases; wr_dqs_shift_with_max_passing_cases = wr_dqs_shift; dll_dqs_delay_X_start_window = dll_dqs_delay_X_sw_val; dll_dqs_delay_X_end_window = dll_dqs_delay_X; } } /* -----------------------------------------------------------+ * De-assert 'start' parameter. * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_02); val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; mtdcr(ddrcfgd, val); } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */ } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */ /* -----------------------------------------------------------+ * Largest passing window is now detected. * ----------------------------------------------------------*/ /* Compute dll_dqs_delay_X value */ dll_dqs_delay_X = (dll_dqs_delay_X_end_window + dll_dqs_delay_X_start_window) / 2; wr_dqs_shift = wr_dqs_shift_with_max_passing_cases; debug("DQS calibration - Window detected:\n"); debug("max_passing_cases = %d\n", max_passing_cases); debug("wr_dqs_shift = %d\n", wr_dqs_shift); debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X); debug("dll_dqs_delay_X window = %d - %d\n", dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window); /* -----------------------------------------------------------+ * De-assert 'start' parameter. * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_02); val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; mtdcr(ddrcfgd, val); /* -----------------------------------------------------------+ * Set 'wr_dqs_shift' * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_09); val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); mtdcr(ddrcfgd, val); debug("DDR0_09=0x%08lx\n", val); /* -----------------------------------------------------------+ * Set 'dqs_out_shift' = wr_dqs_shift + 32 * ----------------------------------------------------------*/ dqs_out_shift = wr_dqs_shift + 32; mtdcr(ddrcfga, DDR0_22); val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); mtdcr(ddrcfgd, val); debug("DDR0_22=0x%08lx\n", val); /* -----------------------------------------------------------+ * Set 'dll_dqs_delay_X'. * ----------------------------------------------------------*/ /* dll_dqs_delay_0 */ mtdcr(ddrcfga, DDR0_17); val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); mtdcr(ddrcfgd, val); debug("DDR0_17=0x%08lx\n", val); /* dll_dqs_delay_1 to dll_dqs_delay_4 */ mtdcr(ddrcfga, DDR0_18); val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); mtdcr(ddrcfgd, val); debug("DDR0_18=0x%08lx\n", val); /* dll_dqs_delay_5 to dll_dqs_delay_8 */ mtdcr(ddrcfga, DDR0_19); val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); mtdcr(ddrcfgd, val); debug("DDR0_19=0x%08lx\n", val); /* -----------------------------------------------------------+ * Assert 'start' parameter. * ----------------------------------------------------------*/ mtdcr(ddrcfga, DDR0_02); val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON; mtdcr(ddrcfgd, val); ppcMsync(); ppcMbar(); /* -----------------------------------------------------------+ * Wait for the DCC master delay line to finish calibration * ----------------------------------------------------------*/ if (wait_for_dlllock() != 0) { printf("dlllock did not occur !!!\n"); hang(); } ppcMsync(); ppcMbar(); if (wait_for_dram_init_complete() != 0) { printf("dram init complete did not occur !!!\n"); hang(); } udelay(100); /* wait 100us to ensure init is really completed !!! */ }