⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spd_sdram.c

📁 AT91RM9200的完整启动代码:包括loader, boot及U-boot三部分均已编译通过!欢迎下载使用!
💻 C
📖 第 1 页 / 共 4 页
字号:
        break;    case 9:        tr0 |= SDRAM_TR0_SDRA_9_CLK;        break;    case 10:        tr0 |= SDRAM_TR0_SDRA_10_CLK;        break;    case 11:        tr0 |= SDRAM_TR0_SDRA_11_CLK;        break;    case 12:        tr0 |= SDRAM_TR0_SDRA_12_CLK;        break;    default:        tr0 |= SDRAM_TR0_SDRA_13_CLK;        break;    }    /*     * Program SD_RCD field     */    t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION;    plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns;    if (sys_info.freqPLB != plb_check) {        t_rcd_clk++;    }    switch (t_rcd_clk) {    case 0:    case 1:    case 2:        tr0 |= SDRAM_TR0_SDRD_2_CLK;        break;    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 bxcr_num;    unsigned long bank_base_addr;    unsigned long bank_size_bytes;    unsigned long cr;    unsigned long i;    unsigned long temp;    unsigned char num_row_addr;    unsigned char num_col_addr;    unsigned char num_banks;    unsigned char bank_size_id;    /*     * Set the BxCR regs.  First, wipe out the bank config registers.     */    for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {        mtdcr(memcfga, mem_b0cr + (bxcr_num << 2));        mtdcr(memcfgd, 0x00000000);    }    /*     * 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;            bank_size_bytes = 4 * 1024 * 1024 * bank_size_id;            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;            /*------------------------------------------------------------------            | This next section is hardware dependent and must be programmed            | to match the hardware.            +-----------------------------------------------------------------*/            if (dimm_num == 0) {                for (i = 0; i < num_banks; i++) {                    mtdcr(memcfga, mem_b0cr + (i << 2));                    temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK |                                              SDRAM_BXCR_SDSZ_MASK |                                              SDRAM_BXCR_SDAM_MASK |                                              SDRAM_BXCR_SDBE);                    cr |= temp;                    cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK;                    mtdcr(memcfgd, cr);                    bank_base_addr += bank_size_bytes;                }            }            else {                for (i = 0; i < num_banks; i++) {                    mtdcr(memcfga, mem_b2cr + (i << 2));                    temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK |                                              SDRAM_BXCR_SDSZ_MASK |                                              SDRAM_BXCR_SDAM_MASK |                                              SDRAM_BXCR_SDBE);                    cr |= temp;                    cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK;                    mtdcr(memcfgd, cr);                    bank_base_addr += 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 + -