From 915c2f417ad87389c4ac531603e1d7763397e214 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 10 Oct 2018 10:42:56 +0200 Subject: [PATCH] bios/sdram: improve write/read leveling write_leveling: select last 0 to 1 transition. read_leveling: do it by module (select best bitslip for each module) --- litex/soc/software/bios/sdram.c | 263 +++++++++++++++----------------- 1 file changed, 119 insertions(+), 144 deletions(-) diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index ff9009c95..b640a387d 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -207,6 +207,8 @@ void sdrwr(char *startaddr) #endif #define ERR_DDRPHY_BITSLIP 8 +#define NBMODULES DFII_PIX_DATA_SIZE/2 + #ifdef CSR_DDRPHY_WLEVEL_EN_ADDR void sdrwlon(void) @@ -238,22 +240,20 @@ int write_level(void) int one_window_active; int one_window_start; - int one_window_len; - int best_one_window_len; - int delays[DFII_PIX_DATA_SIZE/2]; + int delays[NBMODULES]; int ok; err_ddrphy_wdly = ERR_DDRPHY_DELAY - ddrphy_half_sys8x_taps_read(); - printf("Write leveling scan:\n"); + printf("Write leveling:\n"); sdrwlon(); cdelay(100); - for(i=0;i best_one_window_len) { - delays[i] = one_window_start; - best_one_window_len = one_window_len; - } + if (taps_scan[j] == 0) one_window_active = 0; - } } else { if (taps_scan[j]) { one_window_active = 1; @@ -299,6 +291,7 @@ int write_level(void) } } } + delays[i] = one_window_start; /* configure delays */ ddrphy_wdly_dq_rst_write(1); @@ -311,23 +304,18 @@ int write_level(void) ddrphy_wdly_dq_inc_write(1); ddrphy_wdly_dqs_inc_write(1); } + + printf(" delay: %02d\n", delays[i]); } sdrwloff(); ok = 1; - printf("Write leveling: "); - for(i=DFII_PIX_DATA_SIZE/2-1;i>=0;i--) { - printf("%2d ", delays[i]); + for(i=NBMODULES-1;i>=0;i--) { if(delays[i] < 0) ok = 0; } - if(ok) - printf("completed\n"); - else - printf("failed\n"); - return ok; } @@ -346,16 +334,13 @@ static void read_bitslip_inc(char m) #endif } -static int read_level_scan(int silent) +static int read_level_scan(int module, int silent) { unsigned int prv; unsigned char prs[DFII_NPHASES*DFII_PIX_DATA_SIZE]; int p, i, j; int score; - if (!silent) - printf("Read delays scan:\n"); - /* Generate pseudo-random sequence */ prv = 42; for(i=0;i=0;i--) { - if (!silent) - printf("m%d: ", (DFII_PIX_DATA_SIZE/2-i-1)); - ddrphy_dly_sel_write(1 << (DFII_PIX_DATA_SIZE/2-i-1)); - ddrphy_rdly_dq_rst_write(1); - for(j=0; j= ERR_DDRPHY_DELAY) - break; - ddrphy_rdly_dq_inc_write(1); - } - delay_min = delay; + ddrphy_dly_sel_write(1 << module); + delay = 0; - /* Get a bit further into the working zone */ -#ifdef KUSDDRPHY - for(j=0;j<16;j++) { - delay += 1; - ddrphy_rdly_dq_inc_write(1); + /* Find smallest working delay */ + ddrphy_rdly_dq_rst_write(1); + while(1) { + command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); + cdelay(15); + working = 1; + for(p=0;p= ERR_DDRPHY_DELAY) + break; ddrphy_rdly_dq_inc_write(1); + } + delay_min = delay; + + /* Get a bit further into the working zone */ +#ifdef KUSDDRPHY + for(j=0;j<16;j++) { + delay += 1; + ddrphy_rdly_dq_inc_write(1); + } +#else + delay++; + ddrphy_rdly_dq_inc_write(1); #endif - /* Find largest working delay */ - while(1) { - command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); - cdelay(15); - working = 1; - for(p=0;p= ERR_DDRPHY_DELAY) - break; - ddrphy_rdly_dq_inc_write(1); + /* Find largest working delay */ + while(1) { + command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); + cdelay(15); + working = 1; + for(p=0;p= ERR_DDRPHY_DELAY) + break; + ddrphy_rdly_dq_inc_write(1); } + delay_max = delay; + + printf("%02d+-%02d", (delay_min+delay_max)/2, (delay_max-delay_min)/2); + + /* Set delay to the middle */ + ddrphy_rdly_dq_rst_write(1); + for(j=0;j<(delay_min+delay_max)/2;j++) + ddrphy_rdly_dq_inc_write(1); /* Precharge */ sdram_dfii_pi0_address_write(0); sdram_dfii_pi0_baddress_write(0); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS); cdelay(15); - - printf("completed\n"); } #endif /* CSR_DDRPHY_BASE */ @@ -566,7 +547,7 @@ static int memtest_bus(void) if(rdata != ONEZERO) { errors++; #ifdef MEMTEST_BUS_DEBUG - printf("[bus: %0x]: %08x vs %08x\n", i, rdata, ONEZERO); + printf("[bus: 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ONEZERO); #endif } } @@ -581,7 +562,7 @@ static int memtest_bus(void) if(rdata != ZEROONE) { errors++; #ifdef MEMTEST_BUS_DEBUG - printf("[bus %0x]: %08x vs %08x\n", i, rdata, ZEROONE); + printf("[bus 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ZEROONE); #endif } } @@ -620,7 +601,7 @@ static int memtest_data(void) if(rdata != seed_32) { errors++; #ifdef MEMTEST_DATA_DEBUG - printf("[data %0x]: %08x vs %08x\n", i, rdata, seed_32); + printf("[data 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, seed_32); #endif } } @@ -658,7 +639,7 @@ static int memtest_addr(void) if(rdata != i) { errors++; #ifdef MEMTEST_ADDR_DEBUG - printf("[addr %0x]: %08x vs %08x\n", i, rdata, i); + printf("[addr 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, i); #endif } } @@ -701,7 +682,7 @@ int sdrlevel(int silent) sdrsw(); - for(i=0; i best_score) { - best_bitslip = bitslip; - best_score = score; - } - /* exit */ - if (bitslip == ERR_DDRPHY_BITSLIP-1) - break; - /* increment bitslip */ - for(i=0; i best_score) { + best_bitslip = bitslip; + best_score = score; + } + /* exit */ + if (bitslip == ERR_DDRPHY_BITSLIP-1) + break; + /* increment bitslip */ read_bitslip_inc(i); - } + } - /* select best read window */ - printf("Best read bitslip: %d\n", best_bitslip); - for(i=0; i