📄 44x_spd_ddr.c
字号:
{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}}; 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++) { /* printf("bank enabled base:%x\n", &membase[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])); return 0; } ppcDcbf((unsigned long)&(membase[j])); } if (j < NUMMEMWORDS) return 0; } /* * see if the rdclt value passed */ if (i < NUMMEMTESTS) return 0; } } return 1;}static 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 k; 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; PPC4xx_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; debug("Starting memory test "); 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))); if (short_mem_test()) { 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; } } } } debug("."); if (window_found == TRUE) { break; } tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; rdclt_offset += dly_val; } debug("\n"); /* * make sure we find the window */ if (window_found == FALSE) { printf("ERROR: Cannot determine a common read delay.\n"); spd_ddr_init_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 < 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); debug("tr1: %x\n", tr1); /* * program SDRAM Timing Register 1 TR1 */ mtsdram(mem_tr1, tr1);}static 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 bamboo, the following holds... * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 (soldered onboard) * 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 /* * Ocotea, Ebony and the other IBM/AMCC eval boards have * 2 DIMM slots with each max 2 banks */ ctrl_bank_num[0] = 0; ctrl_bank_num[1] = 2;#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); debug("DIMM%d: row=%d col=%d banks=%d\n", dimm_num, num_row_addr, num_col_addr, num_banks); /* * 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"); spd_ddr_init_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"); spd_ddr_init_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 << 20) * bank_size_id; bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr; debug("DIMM%d-bank %d (SDRAM0_B%dCR): bank_size_bytes=%d\n", dimm_num, i, ctrl_bank_num[dimm_num]+i, bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes); } } } /* 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; debug("SDRAM0_B%dCR=0x%08lx\n", sorted_bank_num[bx_cr_num], temp); } } return(bank_base_addr);}#endif /* CONFIG_SPD_EEPROM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -