soc/software/liblitedram: refactor centering code into more generic function

This commit is contained in:
Jędrzej Boczar 2021-04-16 15:41:24 +02:00
parent 76d121ea36
commit 2a5973b21f
1 changed files with 45 additions and 107 deletions

View File

@ -802,9 +802,13 @@ static int sdram_read_leveling_scan_module(int module, int bitslip, int show)
return score;
}
static void sdram_read_leveling_module(int module, int show, int show_long)
typedef void (*delay_callback)(int module);
static void sdram_leveling_center_module(
int module, int show_short, int show_long, delay_callback rst_delay, delay_callback inc_delay)
{
int i;
int show;
int working;
int delay, delay_mid, delay_range;
int delay_min = -1, delay_min_next = -1, delay_max = -1;
@ -814,11 +818,15 @@ static void sdram_read_leveling_module(int module, int show, int show_long)
/* Find smallest working delay */
delay = 0;
sdram_read_leveling_rst_delay(module);
rst_delay(module);
while(1) {
working = sdram_write_read_check_test_pattern(module, 42);
working &= sdram_write_read_check_test_pattern(module, 84);
if (show_long)
show = show_long;
#if SDRAM_PHY_DELAYS > 32
show = show && (delay%16 == 0);
#endif
if (show)
printf(working ? "1" : "0");
if(working && delay_min < 0) {
delay_min = delay;
@ -827,25 +835,29 @@ static void sdram_read_leveling_module(int module, int show, int show_long)
delay++;
if(delay >= SDRAM_PHY_DELAYS)
break;
sdram_read_leveling_inc_delay(module);
inc_delay(module);
}
/* Get a bit further into the working zone */
#if SDRAM_PHY_DELAYS > 32
for(i=0;i<16;i++) {
delay += 1;
sdram_read_leveling_inc_delay(module);
inc_delay(module);
}
#else
delay++;
sdram_read_leveling_inc_delay(module);
inc_delay(module);
#endif
/* Find largest working delay */
while(1) {
working = sdram_write_read_check_test_pattern(module, 42);
working &= sdram_write_read_check_test_pattern(module, 84);
if (show_long)
show = show_long;
#if SDRAM_PHY_DELAYS > 32
show = show && (delay%16 == 0);
#endif
if (show)
printf(working ? "1" : "0");
if(!working && delay_max < 0) {
delay_max = delay;
@ -859,7 +871,7 @@ static void sdram_read_leveling_module(int module, int show, int show_long)
delay++;
if(delay >= SDRAM_PHY_DELAYS)
break;
sdram_read_leveling_inc_delay(module);
inc_delay(module);
}
if(delay_max < 0) {
delay_max = delay;
@ -876,7 +888,7 @@ static void sdram_read_leveling_module(int module, int show, int show_long)
delay_mid = (delay_min+delay_max)/2 % SDRAM_PHY_DELAYS;
delay_range = (delay_max-delay_min)/2;
if (show) {
if (show_short) {
if (delay_min < 0)
printf("delays: -");
else
@ -887,13 +899,14 @@ static void sdram_read_leveling_module(int module, int show, int show_long)
printf("\n");
/* Set delay to the middle */
sdram_read_leveling_rst_delay(module);
rst_delay(module);
cdelay(100);
for(i = 0; i < delay_mid; i++) {
sdram_read_leveling_inc_delay(module);
inc_delay(module);
cdelay(100);
}
}
#endif /* CSR_DDRPHY_BASE */
#endif /* CSR_SDRAM_BASE */
@ -918,7 +931,8 @@ void sdram_read_leveling(void)
for(bitslip=0; bitslip<SDRAM_PHY_BITSLIPS; bitslip++) {
/* Compute score */
score = sdram_read_leveling_scan_module(module, bitslip, 1);
sdram_read_leveling_module(module, 1, 0);
sdram_leveling_center_module(module, 1, 0,
sdram_read_leveling_rst_delay, sdram_read_leveling_inc_delay);
printf("\n");
if (score > best_score) {
best_bitslip = bitslip;
@ -938,7 +952,8 @@ void sdram_read_leveling(void)
sdram_read_leveling_inc_bitslip(module);
/* Re-do leveling on best read window*/
sdram_read_leveling_module(module, 1, 0);
sdram_leveling_center_module(module, 1, 0,
sdram_read_leveling_rst_delay, sdram_read_leveling_inc_delay);
printf("\n");
}
}
@ -1017,100 +1032,21 @@ static void sdram_write_latency_calibration(void) {
#ifdef SDRAM_PHY_WRITE_DQ_DQS_TRAINING_CAPABLE
static void sdram_write_dq_dqs_training_module(int module, int show, int show_long)
{
int i;
int working;
int delay, delay_mid, delay_range;
int delay_min = -1, delay_min_next = -1, delay_max = -1;
if (show_long)
printf("m%d: |", module);
static void sdram_write_dq_dqs_training_rst_delay(int module) {
/* Select module */
ddrphy_dly_sel_write(1 << module);
/* Find smallest working delay */
delay = 0;
ddrphy_wdly_dq_rst_write(module);
while(1) {
working = sdram_write_read_check_test_pattern(module, 42);
working &= sdram_write_read_check_test_pattern(module, 84);
if (show_long)
printf(working ? "1" : "0");
if(working && delay_min < 0) {
delay_min = delay;
break;
}
delay++;
if(delay >= SDRAM_PHY_DELAYS)
break;
ddrphy_wdly_dq_inc_write(module);
}
/* Get a bit further into the working zone */
#if SDRAM_PHY_DELAYS > 32
for(i=0;i<16;i++) {
delay += 1;
ddrphy_wdly_dq_inc_write(module);
}
#else
delay++;
ddrphy_wdly_dq_inc_write(module);
#endif
/* Find largest working delay */
while(1) {
working = sdram_write_read_check_test_pattern(module, 42);
working &= sdram_write_read_check_test_pattern(module, 84);
if (show_long)
printf(working ? "1" : "0");
if(!working && delay_max < 0) {
delay_max = delay;
}
/* Store next working delay to include wrapping around */
if (!working) {
delay_min_next = -1;
} else if(working && delay_min_next < 0) {
delay_min_next = delay;
}
delay++;
if(delay >= SDRAM_PHY_DELAYS)
break;
ddrphy_wdly_dq_inc_write(module);
}
if(delay_max < 0) {
delay_max = delay;
}
/* Extend the range if it wraps around */
if (delay_min_next > 0) {
delay_min = delay_min_next;
delay_max += SDRAM_PHY_DELAYS;
}
if (show_long)
printf("| ");
delay_mid = (delay_min+delay_max)/2 % SDRAM_PHY_DELAYS;
delay_range = (delay_max-delay_min)/2;
if (show) {
if (delay_min < 0)
printf("delays: -");
else
printf("delays: %02d+-%02d", delay_mid, delay_range);
}
if (show_long)
printf("\n");
/* Set delay to the middle */
ddrphy_wdly_dq_rst_write(module);
cdelay(100);
for(i = 0; i < delay_mid; i++) {
ddrphy_wdly_dq_inc_write(module);
cdelay(100);
/* Reset delay */
ddrphy_wdly_dq_rst_write(1);
/* Un-select module */
ddrphy_dly_sel_write(0);
}
static void sdram_write_dq_dqs_training_inc_delay(int module) {
/* Select module */
ddrphy_dly_sel_write(1 << module);
/* Increment delay */
ddrphy_wdly_dq_inc_write(1);
/* Un-select module */
ddrphy_dly_sel_write(0);
}
@ -1124,7 +1060,8 @@ static void sdram_read_leveling_best_bitslip(int module)
sdram_read_leveling_rst_bitslip(module);
for(bitslip=0; bitslip<SDRAM_PHY_BITSLIPS; bitslip++) {
score = sdram_read_leveling_scan_module(module, bitslip, 0);
sdram_read_leveling_module(module, 0, 0);
sdram_leveling_center_module(module, 0, 0,
sdram_read_leveling_rst_delay, sdram_read_leveling_inc_delay);
if (score > best_score) {
best_bitslip = bitslip;
best_score = score;
@ -1154,7 +1091,8 @@ static void sdram_write_dq_dqs_training(void)
/* Find best bitslip */
sdram_read_leveling_best_bitslip(module);
/* Center DQ-DQS window */
sdram_write_dq_dqs_training_module(module, show, show);
sdram_leveling_center_module(module, show, show,
sdram_write_dq_dqs_training_rst_delay, sdram_write_dq_dqs_training_inc_delay);
}
}
}