📄 spd_sdram.c
字号:
case 3: tr0 |= SDRAM_TR0_SDRD_3_CLK; break; default: tr0 |= SDRAM_TR0_SDRD_4_CLK; break; }#if 0 printf("tr0: %x\n", tr0);#endif mtsdram(mem_tr0, tr0);}void program_tr1 (void){ unsigned long tr0; unsigned long tr1; unsigned long cfg0; unsigned long ecc_temp; unsigned long dlycal; unsigned long dly_val; unsigned long i, j, k; unsigned long bxcr_num; unsigned long max_pass_length; unsigned long current_pass_length; unsigned long current_fail_length; unsigned long current_start; unsigned long rdclt; unsigned long rdclt_offset; long max_start; long max_end; long rdclt_average; unsigned char window_found; unsigned char fail_found; unsigned char pass_found; unsigned long * membase; PPC440_SYS_INFO sys_info; /* * get the board info */ get_sys_info(&sys_info); /* * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits */ mfsdram(mem_tr1, tr1); tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK | SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK); mfsdram(mem_tr0, tr0); if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) && (sys_info.freqPLB > 100000000)) { tr1 |= SDRAM_TR1_RDSS_TR2; tr1 |= SDRAM_TR1_RDSL_STAGE3; tr1 |= SDRAM_TR1_RDCD_RCD_1_2; } else { tr1 |= SDRAM_TR1_RDSS_TR1; tr1 |= SDRAM_TR1_RDSL_STAGE2; tr1 |= SDRAM_TR1_RDCD_RCD_0_0; } /* * save CFG0 ECC setting to a temporary variable and turn ECC off */ mfsdram(mem_cfg0, cfg0); ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK; mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON); /* * get the delay line calibration register value */ mfsdram(mem_dlycal, dlycal); dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2; max_pass_length = 0; max_start = 0; max_end = 0; current_pass_length = 0; current_fail_length = 0; current_start = 0; rdclt_offset = 0; window_found = FALSE; fail_found = FALSE; pass_found = FALSE;#ifdef DEBUG printf("Starting memory test ");#endif for (k = 0; k < NUMHALFCYCLES; k++) { for (rdclt = 0; rdclt < dly_val; rdclt++) { /* * Set the timing reg for the test. */ mtsdram(mem_tr1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt))); for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) { mtdcr(memcfga, mem_b0cr + (bxcr_num<<2)); if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) { /* Bank is enabled */ membase = (unsigned long*) (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK); /* * Run the short memory test */ for (i = 0; i < NUMMEMTESTS; i++) { for (j = 0; j < NUMMEMWORDS; j++) { membase[j] = test[i][j]; ppcDcbf((unsigned long)&(membase[j])); } for (j = 0; j < NUMMEMWORDS; j++) { if (membase[j] != test[i][j]) { ppcDcbf((unsigned long)&(membase[j])); break; } ppcDcbf((unsigned long)&(membase[j])); } if (j < NUMMEMWORDS) { break; } } /* * see if the rdclt value passed */ if (i < NUMMEMTESTS) { break; } } } if (bxcr_num == MAXBXCR) { if (fail_found == TRUE) { pass_found = TRUE; if (current_pass_length == 0) { current_start = rdclt_offset + rdclt; } current_fail_length = 0; current_pass_length++; if (current_pass_length > max_pass_length) { max_pass_length = current_pass_length; max_start = current_start; max_end = rdclt_offset + rdclt; } } } else { current_pass_length = 0; current_fail_length++; if (current_fail_length >= (dly_val>>2)) { if (fail_found == FALSE) { fail_found = TRUE; } else if (pass_found == TRUE) { window_found = TRUE; break; } } } }#ifdef DEBUG printf(".");#endif if (window_found == TRUE) { break; } tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; rdclt_offset += dly_val; }#ifdef DEBUG printf("\n");#endif /* * make sure we find the window */ if (window_found == FALSE) { printf("ERROR: Cannot determine a common read delay.\n"); hang(); } /* * restore the orignal ECC setting */ mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp); /* * set the SDRAM TR1 RDCD value */ tr1 &= ~SDRAM_TR1_RDCD_MASK; if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) { tr1 |= SDRAM_TR1_RDCD_RCD_1_2; } else { tr1 |= SDRAM_TR1_RDCD_RCD_0_0; } /* * set the SDRAM TR1 RDCLT value */ tr1 &= ~SDRAM_TR1_RDCT_MASK; while (max_end >= (dly_val << 1)) { max_end -= (dly_val << 1); max_start -= (dly_val << 1); } rdclt_average = ((max_start + max_end) >> 1); if (rdclt_average >= 0x60) while (1) ; if (rdclt_average < 0) { rdclt_average = 0; } if (rdclt_average >= dly_val) { rdclt_average -= dly_val; tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; } tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average);#if 0 printf("tr1: %x\n", tr1);#endif /* * program SDRAM Timing Register 1 TR1 */ mtsdram(mem_tr1, tr1);}unsigned long program_bxcr(unsigned long* dimm_populated, unsigned char* iic0_dimm_addr, unsigned long num_dimm_banks){ unsigned long dimm_num; unsigned long bank_base_addr; unsigned long cr; unsigned long i; unsigned long j; unsigned long temp; unsigned char num_row_addr; unsigned char num_col_addr; unsigned char num_banks; unsigned char bank_size_id; unsigned long ctrl_bank_num[MAXBANKS]; unsigned long bx_cr_num; unsigned long largest_size_index; unsigned long largest_size; unsigned long current_size_index; BANKPARMS bank_parms[MAXBXCR]; unsigned long sorted_bank_num[MAXBXCR]; /* DDR Controller bank number table (sorted by size) */ unsigned long sorted_bank_size[MAXBXCR]; /* DDR Controller bank size table (sorted by size)*/ /* * Set the BxCR regs. First, wipe out the bank config registers. */ for (bx_cr_num = 0; bx_cr_num < MAXBXCR; bx_cr_num++) { mtdcr(memcfga, mem_b0cr + (bx_cr_num << 2)); mtdcr(memcfgd, 0x00000000); bank_parms[bx_cr_num].bank_size_bytes = 0; }#ifdef CONFIG_BAMBOO /* * This next section is hardware dependent and must be programmed * to match the hardware. For bammboo, the following holds... * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 * 2. SDRAM0_B1CR: Bank 0 of dimm 1 ctrl_bank_num : 1 * 3. SDRAM0_B2CR: Bank 1 of dimm 1 ctrl_bank_num : 1 * 4. SDRAM0_B3CR: Bank 0 of dimm 2 ctrl_bank_num : 3 * ctrl_bank_num corresponds to the first usable DDR controller bank number by DIMM */ ctrl_bank_num[0] = 0; ctrl_bank_num[1] = 1; ctrl_bank_num[2] = 3;#else ctrl_bank_num[0] = 0; ctrl_bank_num[1] = 1; ctrl_bank_num[2] = 2; ctrl_bank_num[3] = 3;#endif /* * reset the bank_base address */ bank_base_addr = CFG_SDRAM_BASE; for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { if (dimm_populated[dimm_num] == TRUE) { num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3); num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4); num_banks = spd_read(iic0_dimm_addr[dimm_num], 5); bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31); /* * Set the SDRAM0_BxCR regs */ cr = 0; switch (bank_size_id) { case 0x02: cr |= SDRAM_BXCR_SDSZ_8; break; case 0x04: cr |= SDRAM_BXCR_SDSZ_16; break; case 0x08: cr |= SDRAM_BXCR_SDSZ_32; break; case 0x10: cr |= SDRAM_BXCR_SDSZ_64; break; case 0x20: cr |= SDRAM_BXCR_SDSZ_128; break; case 0x40: cr |= SDRAM_BXCR_SDSZ_256; break; case 0x80: cr |= SDRAM_BXCR_SDSZ_512; break; default: printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n", dimm_num); printf("ERROR: Unsupported value for the banksize: %d.\n", bank_size_id); printf("Replace the DIMM module with a supported DIMM.\n\n"); hang(); } switch (num_col_addr) { case 0x08: cr |= SDRAM_BXCR_SDAM_1; break; case 0x09: cr |= SDRAM_BXCR_SDAM_2; break; case 0x0A: cr |= SDRAM_BXCR_SDAM_3; break; case 0x0B: cr |= SDRAM_BXCR_SDAM_4; break; default: printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n", dimm_num); printf("ERROR: Unsupported value for number of " "column addresses: %d.\n", num_col_addr); printf("Replace the DIMM module with a supported DIMM.\n\n"); hang(); } /* * enable the bank */ cr |= SDRAM_BXCR_SDBE; for (i = 0; i < num_banks; i++) { bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes = (4 * 1024 * 1024) * bank_size_id; bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr; } } } /* Initialize sort tables */ for (i = 0; i < MAXBXCR; i++) { sorted_bank_num[i] = i; sorted_bank_size[i] = bank_parms[i].bank_size_bytes; } for (i = 0; i < MAXBXCR-1; i++) { largest_size = sorted_bank_size[i]; largest_size_index = 255; /* Find the largest remaining value */ for (j = i + 1; j < MAXBXCR; j++) { if (sorted_bank_size[j] > largest_size) { /* Save largest remaining value and its index */ largest_size = sorted_bank_size[j]; largest_size_index = j; } } if (largest_size_index != 255) { /* Swap the current and largest values */ current_size_index = sorted_bank_num[largest_size_index]; sorted_bank_size[largest_size_index] = sorted_bank_size[i]; sorted_bank_size[i] = largest_size; sorted_bank_num[largest_size_index] = sorted_bank_num[i]; sorted_bank_num[i] = current_size_index; } } /* Set the SDRAM0_BxCR regs thanks to sort tables */ for (bx_cr_num = 0, bank_base_addr = 0; bx_cr_num < MAXBXCR; bx_cr_num++) { if (bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes) { mtdcr(memcfga, mem_b0cr + (sorted_bank_num[bx_cr_num] << 2)); temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK | SDRAM_BXCR_SDSZ_MASK | SDRAM_BXCR_SDAM_MASK | SDRAM_BXCR_SDBE); temp = temp | (bank_base_addr & SDRAM_BXCR_SDBA_MASK) | bank_parms[sorted_bank_num[bx_cr_num]].cr; mtdcr(memcfgd, temp); bank_base_addr += bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes; } } return(bank_base_addr);}void program_ecc (unsigned long num_bytes){ unsigned long bank_base_addr; unsigned long current_address; unsigned long end_address; unsigned long address_increment; unsigned long cfg0; /* * get Memory Controller Options 0 data */ mfsdram(mem_cfg0, cfg0); /* * reset the bank_base address */ bank_base_addr = CFG_SDRAM_BASE; if ((cfg0 & SDRAM_CFG0_MCHK_MASK) != SDRAM_CFG0_MCHK_NON) { mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_GEN); if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) { address_increment = 4; } else { address_increment = 8; } current_address = (unsigned long)(bank_base_addr); end_address = (unsigned long)(bank_base_addr) + num_bytes; while (current_address < end_address) { *((unsigned long*)current_address) = 0x00000000; current_address += address_increment; } mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_CHK); }}#endif /* CONFIG_440 */#endif /* CONFIG_SPD_EEPROM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -