nb/intel/sandybridge/raminit: prepare raminit for fallback

Return errors to top level ram init function.
Required by the folowing series to implement a fallback.

No functionality is changed.
On error case the system still halts in every test.

Change-Id: I6278c4a1d7b4a96be8988a60671fc3d72cd6cb3d
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/14170
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Patrick Rudolph 2016-03-25 18:19:47 +01:00 committed by Martin Roth
parent 101351fe95
commit 24a845b622
1 changed files with 148 additions and 53 deletions

View File

@ -199,6 +199,8 @@ typedef struct ramctr_timing_st {
#define MAX_TIMB 511 #define MAX_TIMB 511
#define MAX_TIMA 127 #define MAX_TIMA 127
#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
static void program_timings(ramctr_timing * ctrl, int channel); static void program_timings(ramctr_timing * ctrl, int channel);
static const char *ecc_decoder[] = { static const char *ecc_decoder[] = {
@ -1877,7 +1879,7 @@ static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
} }
} }
static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank, static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
int *upperA) int *upperA)
{ {
int works[NUM_LANES]; int works[NUM_LANES];
@ -1895,18 +1897,26 @@ static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank,
all_works = 0; all_works = 0;
} }
if (all_works) if (all_works)
return; return 0;
if (!some_works) { if (!some_works) {
if (ctrl->timings[channel][slotrank].val_4024 < 2) if (ctrl->timings[channel][slotrank].val_4024 < 2) {
die("402x discovery failed"); printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
channel, slotrank);
halt();
return MAKE_ERR;
}
ctrl->timings[channel][slotrank].val_4024 -= 2; ctrl->timings[channel][slotrank].val_4024 -= 2;
printram("4024 -= 2;\n"); printram("4024 -= 2;\n");
continue; continue;
} }
ctrl->timings[channel][slotrank].val_4028 += 2; ctrl->timings[channel][slotrank].val_4028 += 2;
printram("4028 += 2;\n"); printram("4028 += 2;\n");
if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
die("402x discovery failed"); printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
channel, slotrank);
halt();
return MAKE_ERR;
}
FOR_ALL_LANES if (works[lane]) { FOR_ALL_LANES if (works[lane]) {
ctrl->timings[channel][slotrank].lanes[lane].timA += ctrl->timings[channel][slotrank].lanes[lane].timA +=
128; 128;
@ -1915,6 +1925,7 @@ static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank,
slotrank, lane); slotrank, lane);
} }
} }
return 0;
} }
struct timA_minmax { struct timA_minmax {
@ -1983,9 +1994,10 @@ static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
* Once the controller has detected this pattern a bit in the result register is * Once the controller has detected this pattern a bit in the result register is
* set for the current phase shift. * set for the current phase shift.
*/ */
static void read_training(ramctr_timing * ctrl) static int read_training(ramctr_timing * ctrl)
{ {
int channel, slotrank, lane; int channel, slotrank, lane;
int err;
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
int all_high, some_high; int all_high, some_high;
@ -2041,7 +2053,9 @@ static void read_training(ramctr_timing * ctrl)
pre_timA_change(ctrl, channel, slotrank, &mnmx); pre_timA_change(ctrl, channel, slotrank, &mnmx);
discover_402x(ctrl, channel, slotrank, upperA); err = discover_402x(ctrl, channel, slotrank, upperA);
if (err)
return err;
post_timA_change(ctrl, channel, slotrank, &mnmx); post_timA_change(ctrl, channel, slotrank, &mnmx);
pre_timA_change(ctrl, channel, slotrank, &mnmx); pre_timA_change(ctrl, channel, slotrank, &mnmx);
@ -2081,6 +2095,7 @@ static void read_training(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
+ 4 * lane, 0); + 4 * lane, 0);
} }
return 0;
} }
static void test_timC(ramctr_timing * ctrl, int channel, int slotrank) static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
@ -2167,7 +2182,7 @@ static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
wait_428c(channel); wait_428c(channel);
} }
static void discover_timC(ramctr_timing * ctrl, int channel, int slotrank) static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
{ {
int timC; int timC;
int statistics[NUM_LANES][MAX_TIMC + 1]; int statistics[NUM_LANES][MAX_TIMC + 1];
@ -2204,11 +2219,16 @@ static void discover_timC(ramctr_timing * ctrl, int channel, int slotrank)
struct run rn = struct run rn =
get_longest_zero_run(statistics[lane], MAX_TIMC + 1); get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle; ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
if (rn.all) if (rn.all) {
die("timC discovery failed"); printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
}
printram("Cval: %d, %d, %d: %x\n", channel, slotrank, printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
lane, ctrl->timings[channel][slotrank].lanes[lane].timC); lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
} }
return 0;
} }
static int get_precedening_channels(ramctr_timing * ctrl, int target_channel) static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
@ -2402,7 +2422,7 @@ static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
0x1080 | make_mr1(ctrl, slotrank, channel)); 0x1080 | make_mr1(ctrl, slotrank, channel));
} }
static void discover_timB(ramctr_timing * ctrl, int channel, int slotrank) static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
{ {
int timB; int timB;
int statistics[NUM_LANES][128]; int statistics[NUM_LANES][128];
@ -2445,11 +2465,16 @@ static void discover_timB(ramctr_timing * ctrl, int channel, int slotrank)
else if ((rn.start & 0x3F) == 0x3F) else if ((rn.start & 0x3F) == 0x3F)
rn.start += 1; rn.start += 1;
ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start; ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
if (rn.all) if (rn.all) {
die("timB discovery failed"); printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
}
printram("Bval: %d, %d, %d: %x\n", channel, slotrank, printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
lane, ctrl->timings[channel][slotrank].lanes[lane].timB); lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
} }
return 0;
} }
static int get_timB_high_adjust(u64 val) static int get_timB_high_adjust(u64 val)
@ -2606,9 +2631,10 @@ static void write_op(ramctr_timing * ctrl, int channel)
* In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
* sampled value on the data lanes (DQs). * sampled value on the data lanes (DQs).
*/ */
static void write_training(ramctr_timing * ctrl) static int write_training(ramctr_timing * ctrl)
{ {
int channel, slotrank, lane; int channel, slotrank, lane;
int err;
FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_CHANNELS
write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel, write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
@ -2641,8 +2667,11 @@ static void write_training(ramctr_timing * ctrl)
toggle_io_reset(); toggle_io_reset();
/* set any valid value for timB, it gets corrected later */ /* set any valid value for timB, it gets corrected later */
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_timB(ctrl, channel, slotrank); err = discover_timB(ctrl, channel, slotrank);
if (err)
return err;
}
/* disable write leveling on all ranks */ /* disable write leveling on all ranks */
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
@ -2691,8 +2720,11 @@ static void write_training(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0); write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
} }
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_timC(ctrl, channel, slotrank); err = discover_timC(ctrl, channel, slotrank);
if (err)
return err;
}
FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_CHANNELS
program_timings(ctrl, channel); program_timings(ctrl, channel);
@ -2708,6 +2740,7 @@ static void write_training(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
0); 0);
} }
return 0;
} }
static int test_320c(ramctr_timing * ctrl, int channel, int slotrank) static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
@ -2941,19 +2974,20 @@ static int try_cmd_stretch(ramctr_timing * ctrl, int cmd_stretch)
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank]; ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
} }
return MAKE_ERR;
}
}
}
return 0; return 0;
} }
}
}
return 1;
}
/* Adjust CMD phase shift and try multiple command rates. /* Adjust CMD phase shift and try multiple command rates.
* A command rate of 2T doubles the time needed for address and * A command rate of 2T doubles the time needed for address and
* command decode. */ * command decode. */
static void command_training(ramctr_timing * ctrl) static int command_training(ramctr_timing *ctrl)
{ {
int channel; int channel;
int err;
FOR_ALL_POPULATED_CHANNELS { FOR_ALL_POPULATED_CHANNELS {
fill_pattern5(ctrl, channel, 0); fill_pattern5(ctrl, channel, 0);
@ -2961,17 +2995,25 @@ static void command_training(ramctr_timing * ctrl)
} }
/* try command rate 1T and 2T */ /* try command rate 1T and 2T */
if (!try_cmd_stretch(ctrl, 0) && !try_cmd_stretch(ctrl, 2)) err = try_cmd_stretch(ctrl, 0);
die("c320c discovery failed"); if (err) {
err = try_cmd_stretch(ctrl, 2);
if (err) {
printk(BIOS_EMERG, "c320c discovery failed\n");
halt();
return err;
}
}
FOR_ALL_POPULATED_CHANNELS { FOR_ALL_POPULATED_CHANNELS {
program_timings(ctrl, channel); program_timings(ctrl, channel);
} }
reprogram_320c(ctrl); reprogram_320c(ctrl);
return 0;
} }
static void discover_edges_real(ramctr_timing * ctrl, int channel, int slotrank, static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
int *edges) int *edges)
{ {
int edge; int edge;
@ -3044,18 +3086,24 @@ static void discover_edges_real(ramctr_timing * ctrl, int channel, int slotrank,
struct run rn = struct run rn =
get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1); get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
edges[lane] = rn.middle; edges[lane] = rn.middle;
if (rn.all) if (rn.all) {
die("edge discovery failed"); printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
}
printram("eval %d, %d, %d: %02x\n", channel, slotrank, printram("eval %d, %d, %d: %02x\n", channel, slotrank,
lane, edges[lane]); lane, edges[lane]);
} }
return 0;
} }
static void discover_edges(ramctr_timing * ctrl) static int discover_edges(ramctr_timing *ctrl)
{ {
int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
int channel, slotrank, lane; int channel, slotrank, lane;
int err;
write32(DEFAULT_MCHBAR + 0x3400, 0); write32(DEFAULT_MCHBAR + 0x3400, 0);
@ -3210,16 +3258,20 @@ static void discover_edges(ramctr_timing * ctrl)
printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300); printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_edges_real(ctrl, channel, slotrank, err = discover_edges_real(ctrl, channel, slotrank,
falling_edges[channel][slotrank]); falling_edges[channel][slotrank]);
if (err)
return err;
} }
write32(DEFAULT_MCHBAR + 0x4eb0, 0x200); write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200); printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_edges_real(ctrl, channel, slotrank, err = discover_edges_real(ctrl, channel, slotrank,
rising_edges[channel][slotrank]); rising_edges[channel][slotrank]);
if (err)
return err;
} }
write32(DEFAULT_MCHBAR + 0x4eb0, 0); write32(DEFAULT_MCHBAR + 0x4eb0, 0);
@ -3239,9 +3291,10 @@ static void discover_edges(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
0); 0);
} }
return 0;
} }
static void discover_edges_write_real(ramctr_timing * ctrl, int channel, static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
int slotrank, int *edges) int slotrank, int *edges)
{ {
int edge; int edge;
@ -3353,38 +3406,47 @@ static void discover_edges_write_real(ramctr_timing * ctrl, int channel,
upper[lane] = upper[lane] =
min(rn.end - ctrl->edge_offset[i], upper[lane]); min(rn.end - ctrl->edge_offset[i], upper[lane]);
edges[lane] = (lower[lane] + upper[lane]) / 2; edges[lane] = (lower[lane] + upper[lane]) / 2;
if (rn.all || (lower[lane] > upper[lane])) if (rn.all || (lower[lane] > upper[lane])) {
die("edge write discovery failed"); printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
}
} }
} }
} }
write32(DEFAULT_MCHBAR + 0x3000, 0); write32(DEFAULT_MCHBAR + 0x3000, 0);
printram("CPA\n"); printram("CPA\n");
return 0;
} }
static void discover_edges_write(ramctr_timing * ctrl) static int discover_edges_write(ramctr_timing *ctrl)
{ {
int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
int channel, slotrank, lane; int channel, slotrank, lane;
int err;
/* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */ /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
write32(DEFAULT_MCHBAR + 0x4eb0, 0x300); write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300); printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_edges_write_real(ctrl, channel, slotrank, err = discover_edges_write_real(ctrl, channel, slotrank,
falling_edges[channel][slotrank]); falling_edges[channel][slotrank]);
if (err)
return err;
} }
write32(DEFAULT_MCHBAR + 0x4eb0, 0x200); write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200); printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_edges_write_real(ctrl, channel, slotrank, err = discover_edges_write_real(ctrl, channel, slotrank,
rising_edges[channel][slotrank]); rising_edges[channel][slotrank]);
if (err)
return err;
} }
write32(DEFAULT_MCHBAR + 0x4eb0, 0); write32(DEFAULT_MCHBAR + 0x4eb0, 0);
@ -3403,6 +3465,7 @@ static void discover_edges_write(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
0); 0);
} }
return 0;
} }
static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank) static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
@ -3455,7 +3518,7 @@ static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
wait_428c(channel); wait_428c(channel);
} }
static void discover_timC_write(ramctr_timing * ctrl) static int discover_timC_write(ramctr_timing *ctrl)
{ {
const u8 rege3c_b24[3] = { 0, 0xf, 0x2f }; const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
int i, pat; int i, pat;
@ -3509,8 +3572,12 @@ static void discover_timC_write(ramctr_timing * ctrl)
rn = get_longest_zero_run(statistics, rn = get_longest_zero_run(statistics,
MAX_TIMC + 1); MAX_TIMC + 1);
if (rn.all) if (rn.all) {
die("timC write discovery failed"); printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
}
printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n", printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
channel, slotrank, i, rn.start, channel, slotrank, i, rn.start,
rn.middle, rn.end, rn.middle, rn.end,
@ -3551,6 +3618,7 @@ static void discover_timC_write(ramctr_timing * ctrl)
FOR_ALL_POPULATED_CHANNELS { FOR_ALL_POPULATED_CHANNELS {
program_timings(ctrl, channel); program_timings(ctrl, channel);
} }
return 0;
} }
static void normalize_training(ramctr_timing * ctrl) static void normalize_training(ramctr_timing * ctrl)
@ -3585,13 +3653,18 @@ static void write_controller_mr(ramctr_timing * ctrl)
} }
} }
static void channel_test(ramctr_timing * ctrl) static int channel_test(ramctr_timing *ctrl)
{ {
int channel, slotrank, lane; int channel, slotrank, lane;
slotrank = 0;
FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_CHANNELS
if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
die("Mini channel test failed (1)\n"); printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
channel);
halt();
return MAKE_ERR;
}
FOR_ALL_POPULATED_CHANNELS { FOR_ALL_POPULATED_CHANNELS {
fill_pattern0(ctrl, channel, 0x12345678, 0x98765432); fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
@ -3633,10 +3706,15 @@ static void channel_test(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001); write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
wait_428c(channel); wait_428c(channel);
FOR_ALL_LANES FOR_ALL_LANES
if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
die("Mini channel test failed (2)\n"); printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
} }
} }
return 0;
}
static void set_scrambling_seed(ramctr_timing * ctrl) static void set_scrambling_seed(ramctr_timing * ctrl)
{ {
@ -3949,6 +4027,8 @@ static void restore_timings(ramctr_timing * ctrl)
static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume, static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume,
int me_uma_size) int me_uma_size)
{ {
int err;
if (!s3resume) { if (!s3resume) {
/* Find fastest common supported parameters */ /* Find fastest common supported parameters */
dram_find_common_params(ctrl); dram_find_common_params(ctrl);
@ -4016,22 +4096,35 @@ static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume,
/* Prepare for memory training */ /* Prepare for memory training */
prepare_training(ctrl); prepare_training(ctrl);
read_training(ctrl); err = read_training(ctrl);
write_training(ctrl); if (err)
return err;
err = write_training(ctrl);
if (err)
return err;
printram("CP5a\n"); printram("CP5a\n");
discover_edges(ctrl); err = discover_edges(ctrl);
if (err)
return err;
printram("CP5b\n"); printram("CP5b\n");
command_training(ctrl); err = command_training(ctrl);
if (err)
return err;
printram("CP5c\n"); printram("CP5c\n");
discover_edges_write(ctrl); err = discover_edges_write(ctrl);
if (err)
return err;
discover_timC_write(ctrl); err = discover_timC_write(ctrl);
if (err)
return err;
normalize_training(ctrl); normalize_training(ctrl);
} }
@ -4041,7 +4134,9 @@ static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume,
write_controller_mr(ctrl); write_controller_mr(ctrl);
if (!s3resume) { if (!s3resume) {
channel_test(ctrl); err = channel_test(ctrl);
if (err)
return err;
} }
return 0; return 0;