meminit.c

来自「TP-LINK公司TL-WR941N无线路由器的Bootloader U_BOO」· C语言 代码 · 共 238 行

C
238
字号
/*  * Memory controller config: * Assumes that the caches are initialized. * * 0) Figah out the Tap controller settings. * 1) Figure out whether the interface is 16bit or 32bit. * 2) Size the DRAM * *  0) Tap controller settings *  -------------------------- * The Table below provides all possible values of TAP controllers. We need to * find the extreme left and extreme right of the spectrum (of max_udelay and * min_udelay). We then program the TAP to be in the middle. * Note for this we would need to be able to read and write memory. So,  * initially we assume that a 16bit interface, which will always work unless * there is exactly _1_ 32 bit part...for now we assume this is not the case. *  * The algo: * 0) Program the controller in 16bit mode. * 1) Start with the extreme left of the table * 2) Write 0xa4, 0xb5, 0xc6, 0xd7 to 0, 2, 4, 6 * 3) Read 0 - this will fetch the entire cacheline. * 4) If the value at address 4 is good, record this table entry, goto 6 * 5) Increment to get the next table entry. Goto 2. * 6) Start with extreme right. Do the same as above. * * 1) 16bit or 32bit * ----------------- *  31st bit of reg 0x1800_0000 will  determine the mode. By default,  *  controller is set to 32-bit mode. In 32 bit mode, full data bus DQ [31:0]  *  will be used to write 32 bit data. Suppose you have 16bit DDR memory *  (it will have 16bit wide data bus). If you try to write 16 bit DDR in 32  *  bit mode, you are going to miss upper 16 bits of data. Reading to that  *  location will give you only lower 16 bits correctly, upper 16 bits will  *  have some junk value. E.g., * *  write to 0x0000_0000 0x12345678 *  write to 0x0000_1000 0x00000000 (just to discharge DQ[31:16] ) *  read from 0x0000_0000 *  if u see something like 0x0000_5678 (or XXXX_5678 but not equal to  *  0x12345678) - its a 16 bit interface * *  2) Size the DRAM *  ------------------- *  DDR wraps around. Write a pattern to 0x0000_0000. Write an address  *  pattern at 4M, 8M, 16M etc. and check when 0x0000_0000 gets overwritten. * * *  We can use #define's for all these addresses and patterns but its easier *  to see what's going on without :) */#include <common.h>#include <asm/addrspace.h>#include "ar7100_soc.h"uint8_t     tap_settings[] =             {0x40, 0x41, 0x10, 0x12, 0x13, 0x15, 0x1a, 0x1c, 0x1f, 0x2f, 0x3f};uint16_t    tap_pattern[] = {0xa5, 0xb6, 0xc7, 0xd8};voidar7100_ddr_tap_set(uint8_t set){    ar7100_reg_wr_nf(AR7100_DDR_TAP_CONTROL0, set);    ar7100_reg_wr_nf(AR7100_DDR_TAP_CONTROL1, set);    ar7100_reg_wr_nf(AR7100_DDR_TAP_CONTROL2, set);    ar7100_reg_wr_nf(AR7100_DDR_TAP_CONTROL3, set);}/* * We use 0xa0003000, because the first way is locked into cache to give * us a rudimentary stack */voidar7100_ddr_tap_config(){    uint8_t set, prev, dummy;    int i, j, k, floor, ceiling;    uint16_t *p = 0xa0003000, *p_ca = 0x80003000;    ar7100_reg_rmw_set(AR7100_DDR_CONFIG, AR7100_DDR_CONFIG_16BIT);    for(i = 0; i < sizeof(tap_settings); i++) {        set = tap_settings[i];        ar7100_ddr_tap_set(set);        printf("trying %#x...", set);        for(j = 0; j < 4; j++)            *(p + j) = tap_pattern[j];        /*         * get the cacheline         */        dummy = *p_ca;        if ((*(p_ca + 2)) == tap_pattern[2]) {            floor = i;            printf("worked; floor %d\n", i);            break;        }        printf("didnt work written %#x read %#x\n", tap_pattern[2],                 *(p_ca + 2));        flush_cache(p_ca, 8);    }    for(k = sizeof(tap_settings) - 1; k > i; k--) {        set = tap_settings[k];        ar7100_ddr_tap_set(set);        printf("trying %#x...", set);        for(j = 0; j < 4; j++)            *(p + j) = tap_pattern[j];        dummy = *p_ca;        if ((*(p_ca + 2)) == tap_pattern[2]) {            ceiling = k;            printf("worked; ceiling %d\n", k);            break;        }        printf("didnt work written %#x read %#x\n", tap_pattern[2],                 *(p_ca + 2));        flush_cache(p_ca, 8);    }    /*     * If the min and max delay both worked, lets pick a default     */    printf("floor %d ceil %d size-1 %d\n",            floor, ceiling, (sizeof(tap_settings) - 1));    if ((floor == 0) && (ceiling == (sizeof(tap_settings) - 1)))         set = AR7100_DDR_TAP_DEFAULT;    else {        i = ((ceiling - floor)/2) + floor;        set = tap_settings[i];        printf("i %d\n", i);    }    printf("Setting Tap to %#x\n", set);    ar7100_ddr_tap_set(set);    udelay(1);}ar7100_ddr_width_tar7100_ddr_get_width(){    volatile uint32_t *p = 0xa0000000, *p1 = 0xa0001000;    uint32_t pat = 0x12345678, rd;    *p  = pat;    *p1 = 0;    asm("sync");    /*     * discharge DQ[31:16]     */    rd  = *p;    if (rd == pat)        return AR7100_DDR_32B;    if ((rd & 0xffff) == (pat & 0xffff))        return AR7100_DDR_16B_LOW;    if ((rd & 0xffff0000) == (pat & 0xffff0000))        return AR7100_DDR_16B_HIGH;    /*     * If Some'n's hosed this early cant do much; silence the compiler :)     */    printf("something's wrong. rd %#x pat %#x\n", rd, pat);    return AR7100_DDR_32B;}/* * We check for size in 4M increments */#define AR7100_DDR_SIZE_INCR    (4*1024*1024)intar7100_ddr_find_size(){    uint8_t  *p = KSEG1, pat = 0x77;    int i, incr = AR7100_DDR_SIZE_INCR;    *p = pat;    for(i = 1; ; i++) {        *(p + i * AR7100_DDR_SIZE_INCR) = (uint8_t)(i);        if (*p != pat) {            break;        }    }    return (i*AR7100_DDR_SIZE_INCR);}voidar7100_ddr_initial_config(uint32_t refresh){    printf("\nsri\n");#if 0    ar7100_reg_wr(AR7100_RESET, AR7100_RESET_DDR);    udelay(10);#endif    ar7100_reg_wr_nf(AR7100_DDR_CONFIG, CFG_DDR_CONFIG_VAL);    udelay(100);    ar7100_reg_wr_nf(AR7100_DDR_CONFIG2, CFG_DDR_CONFIG2_VAL);    udelay(100);    ar7100_reg_wr_nf(AR7100_DDR_CONTROL, 0x8);    udelay(10);#ifdef AR9100    ar7100_reg_wr_nf(AR7100_DDR_MODE, CFG_DDR_MODE_VAL_INIT);    udelay(1000);#endif    ar7100_reg_wr_nf(AR7100_DDR_CONTROL, 0x1);    udelay(10);    ar7100_reg_wr_nf(AR7100_DDR_EXT_MODE, CFG_DDR_EXT_MODE_VAL);    udelay(100);    ar7100_reg_wr_nf(AR7100_DDR_CONTROL, 0x2);    udelay(10);    ar7100_reg_wr_nf(AR7100_DDR_CONTROL, 0x8);    udelay(10);    ar7100_reg_wr_nf(AR7100_DDR_MODE, CFG_DDR_MODE_VAL);    udelay(100);    ar7100_reg_wr_nf(AR7100_DDR_CONTROL, 0x1);    udelay(10);    ar7100_reg_wr_nf(AR7100_DDR_REFRESH, refresh);    udelay(100);    ar7100_reg_wr_nf(AR7100_DDR_RD_DATA_THIS_CYCLE,                             CFG_DDR_RD_DATA_THIS_CYCLE_VAL);    udelay(100);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?