这两天调试了自己公司做的fsl T2081板子,遇到了一些坑,不过最后还是搞定了,记录之已备候查。
主要是时钟问题,由于我们的在一块主板上兼容了1022、1042和2081三种平台。所以SYS/DDR reference clock也是一样的,都是100M的SYS clock和66.66M的DDR clock。
之前调试1042的时候没有问题,但是在调试2081的时候,SD卡启动打印了一堆乱码,经过比较感觉乱发就是CPU送出来的启动信息,于是用示波器量之,发现每个bit为5.6us,和115200想比,差不多为对方的2/3。于是直接修改”board/freescale/t208xqds/spl.c”文件中board_init_f函数的16550的初始化,如下:
1 2 3 4 5 6 7 |
NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1, - ccb_clk / 16 / CONFIG_BAUDRATE); + ccb_clk / 16 / CONFIG_BAUDRATE * 3 / 2); #if defined(CONFIG_SPL_MMC_BOOT) |
重新烧写便可以显示正常信息。
但是,是什么原因导致基准时钟的问题呢?因为时钟差2/3,所以我开始怀疑是否是主板上DDR和SYS的时钟芯片焊反了,不过发现并没有焊反。
后来想到,评估板是66.66/133.33的时钟,而且CPU肯定允许一定范围的时钟输入,所以这个参考时钟CPU肯定不知道,需要人工设置,于是查查BSP代码,
在”board/freescale/t208xqds/spl.c”中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
unsigned long get_board_sys_clk(void) { u8 sysclk_conf = QIXIS_READ(brdcfg[1]); switch (sysclk_conf & 0x0F) { case QIXIS_SYSCLK_83: return 83333333; case QIXIS_SYSCLK_100: return 100000000; case QIXIS_SYSCLK_125: return 125000000; case QIXIS_SYSCLK_133: return 133333333; case QIXIS_SYSCLK_150: return 150000000; case QIXIS_SYSCLK_160: return 160000000; case QIXIS_SYSCLK_166: return 166666666; } return 66666666; } unsigned long get_board_ddr_clk(void) { u8 ddrclk_conf = QIXIS_READ(brdcfg[1]); switch ((ddrclk_conf & 0x30) >> 4) { case QIXIS_DDRCLK_100: return 100000000; case QIXIS_DDRCLK_125: return 125000000; case QIXIS_DDRCLK_133: return 133333333; } return 66666666; } |
同样在”board/freescale/t208xqds/t208xqds.c”中也有,只是spl.c是给FPL用的,t208xqds.c是给NOR启动或者SPL使用的。
查了一下QIXIS_READ是读CPLD寄存器信息,原来FSL通过这种方法就可以在不改代码的前提下通过拨码修改参考时钟。
于是直接写死sys/ddr为100/66.66。启动后显示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
SD boot... Initializing....using SPD DDR clock (MCLK cycle 625 ps) is faster than the slowest DIMM(s) (tCKmin 1250 ps) can support. The choosen cas latency 37 is too large WARNING: Calling __hwconfig without a buffer and before environment is ready WARNING: Calling __hwconfig without a buffer and before environment is ready WARNING: Calling __hwconfig without a buffer and before environment is ready WARNING: Calling __hwconfig without a buffer and before environment is ready Error: board specific timing not foundfor data rate 3199 MT/s Trying to use the highest speed (2140) parameters Error: WRREC doesn't support 24 clocks Warning: CWL is out of range Error: unsupported write recovery for mode register wr_mclk = 24 Error: unsupported cas latency for mode register Warning: CWL is out of range Waiting for D_INIT timeout. Memory may not work. |
显示CPU的DDR clock太快,这个问题之前在T4240上遇到过,是因为RCW配置DDR pll和DDR Latency的问题,但是查了RCW配置字中的MEM_PLL_RAT和DRAM LAT都没有问题,只能跟踪代码了。
调用流程为:
board/freescale/t208xqds/ddr.c: ddr_freq = get_ddr_freq(0) / 1000000;
arch/powerpc/cpu/mpc85xx/speed.c: gd->mem_clk = sys_info.freq_ddrbus;
在”get_sys_info”函数中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/* T4240/T4160 Rev2.0 MEM_PLL_RAT uses a value which is half of * T4240/T4160 Rev1.0. eg. It's 12 in Rev1.0, however, for Rev2.0 * it uses 6. * T2080 rev 1.1 and later also use half mem_pll comparing with rev 1.0 */ #if defined(CONFIG_PPC_T4240) || defined(CONFIG_PPC_T4160) || \ defined(CONFIG_PPC_T4080) || defined(CONFIG_PPC_T2080) || \ defined(CONFIG_PPC_T2081) svr = get_svr(); switch (SVR_SOC_VER(svr)) { case SVR_T4240: case SVR_T4160: case SVR_T4120: case SVR_T4080: if (SVR_MAJ(svr) >= 2) mem_pll_rat *= 2; break; case SVR_T2080: case SVR_T2081: if ((SVR_MAJ(svr) > 1) || (SVR_MIN(svr) >= 1)) mem_pll_rat *= 2; break; default: break; } #endif |
原来T2080 rev 1.1和以上版本有一个BUG,在此版本上需要配置正常PLL的一半,搞定。