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_TIMA 127
#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
static void program_timings(ramctr_timing * ctrl, int channel);
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 works[NUM_LANES];
@ -1895,18 +1897,26 @@ static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank,
all_works = 0;
}
if (all_works)
return;
return 0;
if (!some_works) {
if (ctrl->timings[channel][slotrank].val_4024 < 2)
die("402x discovery failed");
if (ctrl->timings[channel][slotrank].val_4024 < 2) {
printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
channel, slotrank);
halt();
return MAKE_ERR;
}
ctrl->timings[channel][slotrank].val_4024 -= 2;
printram("4024 -= 2;\n");
continue;
}
ctrl->timings[channel][slotrank].val_4028 += 2;
printram("4028 += 2;\n");
if (ctrl->timings[channel][slotrank].val_4028 >= 0x10)
die("402x discovery failed");
if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
channel, slotrank);
halt();
return MAKE_ERR;
}
FOR_ALL_LANES if (works[lane]) {
ctrl->timings[channel][slotrank].lanes[lane].timA +=
128;
@ -1915,6 +1925,7 @@ static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank,
slotrank, lane);
}
}
return 0;
}
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
* 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 err;
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
int all_high, some_high;
@ -2041,7 +2053,9 @@ static void read_training(ramctr_timing * ctrl)
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);
pre_timA_change(ctrl, channel, slotrank, &mnmx);
@ -2081,6 +2095,7 @@ static void read_training(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
+ 4 * lane, 0);
}
return 0;
}
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);
}
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 statistics[NUM_LANES][MAX_TIMC + 1];
@ -2204,11 +2219,16 @@ static void discover_timC(ramctr_timing * ctrl, int channel, int slotrank)
struct run rn =
get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
if (rn.all)
die("timC discovery failed");
if (rn.all) {
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,
lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
}
return 0;
}
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));
}
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 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)
rn.start += 1;
ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
if (rn.all)
die("timB discovery failed");
if (rn.all) {
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,
lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
}
return 0;
}
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
* 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 err;
FOR_ALL_POPULATED_CHANNELS
write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
@ -2641,8 +2667,11 @@ static void write_training(ramctr_timing * ctrl)
toggle_io_reset();
/* set any valid value for timB, it gets corrected later */
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
discover_timB(ctrl, channel, slotrank);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
err = discover_timB(ctrl, channel, slotrank);
if (err)
return err;
}
/* disable write leveling on all 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);
}
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
discover_timC(ctrl, channel, slotrank);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
err = discover_timC(ctrl, channel, slotrank);
if (err)
return err;
}
FOR_ALL_POPULATED_CHANNELS
program_timings(ctrl, channel);
@ -2708,6 +2740,7 @@ static void write_training(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
0);
}
return 0;
}
static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
@ -2876,7 +2909,7 @@ static void reprogram_320c(ramctr_timing * ctrl)
#define MIN_C320C_LEN 13
static int try_cmd_stretch(ramctr_timing * ctrl, int cmd_stretch)
static int try_cmd_stretch(ramctr_timing *ctrl, int cmd_stretch)
{
struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
int channel, slotrank;
@ -2941,19 +2974,20 @@ static int try_cmd_stretch(ramctr_timing * ctrl, int cmd_stretch)
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
}
return 0;
return MAKE_ERR;
}
}
}
return 1;
return 0;
}
/* Adjust CMD phase shift and try multiple command rates.
* A command rate of 2T doubles the time needed for address and
* command decode. */
static void command_training(ramctr_timing * ctrl)
static int command_training(ramctr_timing *ctrl)
{
int channel;
int err;
FOR_ALL_POPULATED_CHANNELS {
fill_pattern5(ctrl, channel, 0);
@ -2961,17 +2995,25 @@ static void command_training(ramctr_timing * ctrl)
}
/* try command rate 1T and 2T */
if (!try_cmd_stretch(ctrl, 0) && !try_cmd_stretch(ctrl, 2))
die("c320c discovery failed");
err = try_cmd_stretch(ctrl, 0);
if (err) {
err = try_cmd_stretch(ctrl, 2);
if (err) {
printk(BIOS_EMERG, "c320c discovery failed\n");
halt();
return err;
}
}
FOR_ALL_POPULATED_CHANNELS {
program_timings(ctrl, channel);
}
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 edge;
@ -3044,18 +3086,24 @@ static void discover_edges_real(ramctr_timing * ctrl, int channel, int slotrank,
struct run rn =
get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
edges[lane] = rn.middle;
if (rn.all)
die("edge discovery failed");
if (rn.all) {
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,
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 rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
int channel, slotrank, lane;
int err;
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);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_edges_real(ctrl, channel, slotrank,
err = discover_edges_real(ctrl, channel, slotrank,
falling_edges[channel][slotrank]);
if (err)
return err;
}
write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
discover_edges_real(ctrl, channel, slotrank,
err = discover_edges_real(ctrl, channel, slotrank,
rising_edges[channel][slotrank]);
if (err)
return err;
}
write32(DEFAULT_MCHBAR + 0x4eb0, 0);
@ -3239,9 +3291,10 @@ static void discover_edges(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
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 edge;
@ -3353,38 +3406,47 @@ static void discover_edges_write_real(ramctr_timing * ctrl, int channel,
upper[lane] =
min(rn.end - ctrl->edge_offset[i], upper[lane]);
edges[lane] = (lower[lane] + upper[lane]) / 2;
if (rn.all || (lower[lane] > upper[lane]))
die("edge write discovery failed");
if (rn.all || (lower[lane] > upper[lane])) {
printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
channel, slotrank, lane);
halt();
return MAKE_ERR;
}
}
}
}
write32(DEFAULT_MCHBAR + 0x3000, 0);
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 rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
int channel, slotrank, lane;
int err;
/* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
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]);
if (err)
return err;
}
write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
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]);
if (err)
return err;
}
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,
0);
}
return 0;
}
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);
}
static void discover_timC_write(ramctr_timing * ctrl)
static int discover_timC_write(ramctr_timing *ctrl)
{
const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
int i, pat;
@ -3509,8 +3572,12 @@ static void discover_timC_write(ramctr_timing * ctrl)
rn = get_longest_zero_run(statistics,
MAX_TIMC + 1);
if (rn.all)
die("timC write discovery failed");
if (rn.all) {
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",
channel, slotrank, i, rn.start,
rn.middle, rn.end,
@ -3551,6 +3618,7 @@ static void discover_timC_write(ramctr_timing * ctrl)
FOR_ALL_POPULATED_CHANNELS {
program_timings(ctrl, channel);
}
return 0;
}
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;
slotrank = 0;
FOR_ALL_POPULATED_CHANNELS
if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000)
die("Mini channel test failed (1)\n");
if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
channel);
halt();
return MAKE_ERR;
}
FOR_ALL_POPULATED_CHANNELS {
fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
@ -3633,9 +3706,14 @@ static void channel_test(ramctr_timing * ctrl)
write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
wait_428c(channel);
FOR_ALL_LANES
if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane))
die("Mini channel test failed (2)\n");
if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
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)
@ -3949,6 +4027,8 @@ static void restore_timings(ramctr_timing * ctrl)
static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume,
int me_uma_size)
{
int err;
if (!s3resume) {
/* Find fastest common supported parameters */
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_training(ctrl);
read_training(ctrl);
write_training(ctrl);
err = read_training(ctrl);
if (err)
return err;
err = write_training(ctrl);
if (err)
return err;
printram("CP5a\n");
discover_edges(ctrl);
err = discover_edges(ctrl);
if (err)
return err;
printram("CP5b\n");
command_training(ctrl);
err = command_training(ctrl);
if (err)
return err;
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);
}
@ -4041,7 +4134,9 @@ static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume,
write_controller_mr(ctrl);
if (!s3resume) {
channel_test(ctrl);
err = channel_test(ctrl);
if (err)
return err;
}
return 0;