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