nb/intel/sandybridge: Improve CAS freq selection

The previous code seemed weird and tried to check if its selected
value is supported three times.

This also lower the clock if a selected frequency does not result in a
supported CAS number.

Change-Id: I97244bc3940813c5a5fcbd770d71cca76d21fcae
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19716
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
This commit is contained in:
Arthur Heymans 2017-05-16 17:58:25 +02:00
parent f6934f5c6c
commit dcd3cef874
2 changed files with 65 additions and 56 deletions

View File

@ -39,6 +39,8 @@
* These values are in 1/256 ns units. * These values are in 1/256 ns units.
* @{ * @{
*/ */
#define NS2MHZ_DIV256 1000 << 8
#define TCK_1333MHZ 192 #define TCK_1333MHZ 192
#define TCK_1200MHZ 212 #define TCK_1200MHZ 212
#define TCK_1100MHZ 232 #define TCK_1100MHZ 232

View File

@ -136,16 +136,65 @@ static u32 get_COMP2(u32 tCK)
return frq_comp2_map[get_FRQ(tCK) - 3]; return frq_comp2_map[get_FRQ(tCK) - 3];
} }
static void dram_timing(ramctr_timing * ctrl) static void snb_normalize_tclk(u32 *tclk)
{
if (*tclk <= TCK_1066MHZ) {
*tclk = TCK_1066MHZ;
} else if (*tclk <= TCK_933MHZ) {
*tclk = TCK_933MHZ;
} else if (*tclk <= TCK_800MHZ) {
*tclk = TCK_800MHZ;
} else if (*tclk <= TCK_666MHZ) {
*tclk = TCK_666MHZ;
} else if (*tclk <= TCK_533MHZ) {
*tclk = TCK_533MHZ;
} else if (*tclk <= TCK_400MHZ) {
*tclk = TCK_400MHZ;
} else {
*tclk = 0;
}
}
static void find_cas_tck(ramctr_timing *ctrl)
{ {
u8 val; u8 val;
u32 val32; u32 val32;
/* Find CAS latency */
while (1) {
/* Normalising tCK before computing clock could potentially
* results in lower selected CAS, which is desired.
*/
snb_normalize_tclk(&(ctrl->tCK));
if (!(ctrl->tCK))
die("Couldn't find compatible clock / CAS settings\n");
val = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK);
printk(BIOS_DEBUG, "Trying CAS %u, tCK %u.\n", val, ctrl->tCK);
for (; val <= MAX_CAS; val++)
if ((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
break;
if (val == (MAX_CAS + 1)) {
ctrl->tCK++;
continue;
} else {
printk(BIOS_DEBUG, "Found compatible clock, CAS pair.\n");
break;
}
}
val32 = NS2MHZ_DIV256 / ctrl->tCK;
printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
ctrl->CAS = val;
}
static void dram_timing(ramctr_timing *ctrl)
{
/* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
* we cap it if we have faster DIMMs. * we cap it if we have faster DIMMs.
* Then, align it to the closest JEDEC standard frequency */ * Then, align it to the closest JEDEC standard frequency */
if (ctrl->tCK <= TCK_1066MHZ) { if (ctrl->tCK == TCK_1066MHZ) {
ctrl->tCK = TCK_1066MHZ;
ctrl->edge_offset[0] = 16; ctrl->edge_offset[0] = 16;
ctrl->edge_offset[1] = 7; ctrl->edge_offset[1] = 7;
ctrl->edge_offset[2] = 7; ctrl->edge_offset[2] = 7;
@ -153,8 +202,7 @@ static void dram_timing(ramctr_timing * ctrl)
ctrl->timC_offset[1] = 7; ctrl->timC_offset[1] = 7;
ctrl->timC_offset[2] = 7; ctrl->timC_offset[2] = 7;
ctrl->reg_320c_range_threshold = 13; ctrl->reg_320c_range_threshold = 13;
} else if (ctrl->tCK <= TCK_933MHZ) { } else if (ctrl->tCK == TCK_933MHZ) {
ctrl->tCK = TCK_933MHZ;
ctrl->edge_offset[0] = 14; ctrl->edge_offset[0] = 14;
ctrl->edge_offset[1] = 6; ctrl->edge_offset[1] = 6;
ctrl->edge_offset[2] = 6; ctrl->edge_offset[2] = 6;
@ -162,8 +210,7 @@ static void dram_timing(ramctr_timing * ctrl)
ctrl->timC_offset[1] = 6; ctrl->timC_offset[1] = 6;
ctrl->timC_offset[2] = 6; ctrl->timC_offset[2] = 6;
ctrl->reg_320c_range_threshold = 15; ctrl->reg_320c_range_threshold = 15;
} else if (ctrl->tCK <= TCK_800MHZ) { } else if (ctrl->tCK == TCK_800MHZ) {
ctrl->tCK = TCK_800MHZ;
ctrl->edge_offset[0] = 13; ctrl->edge_offset[0] = 13;
ctrl->edge_offset[1] = 5; ctrl->edge_offset[1] = 5;
ctrl->edge_offset[2] = 5; ctrl->edge_offset[2] = 5;
@ -171,8 +218,7 @@ static void dram_timing(ramctr_timing * ctrl)
ctrl->timC_offset[1] = 5; ctrl->timC_offset[1] = 5;
ctrl->timC_offset[2] = 5; ctrl->timC_offset[2] = 5;
ctrl->reg_320c_range_threshold = 15; ctrl->reg_320c_range_threshold = 15;
} else if (ctrl->tCK <= TCK_666MHZ) { } else if (ctrl->tCK == TCK_666MHZ) {
ctrl->tCK = TCK_666MHZ;
ctrl->edge_offset[0] = 10; ctrl->edge_offset[0] = 10;
ctrl->edge_offset[1] = 4; ctrl->edge_offset[1] = 4;
ctrl->edge_offset[2] = 4; ctrl->edge_offset[2] = 4;
@ -180,8 +226,7 @@ static void dram_timing(ramctr_timing * ctrl)
ctrl->timC_offset[1] = 4; ctrl->timC_offset[1] = 4;
ctrl->timC_offset[2] = 4; ctrl->timC_offset[2] = 4;
ctrl->reg_320c_range_threshold = 16; ctrl->reg_320c_range_threshold = 16;
} else if (ctrl->tCK <= TCK_533MHZ) { } else if (ctrl->tCK == TCK_533MHZ) {
ctrl->tCK = TCK_533MHZ;
ctrl->edge_offset[0] = 8; ctrl->edge_offset[0] = 8;
ctrl->edge_offset[1] = 3; ctrl->edge_offset[1] = 3;
ctrl->edge_offset[2] = 3; ctrl->edge_offset[2] = 3;
@ -206,30 +251,6 @@ static void dram_timing(ramctr_timing * ctrl)
/* DLL_CONFIG_MDLL_W_TIMER */ /* DLL_CONFIG_MDLL_W_TIMER */
ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3; ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
val32 = (1000 << 8) / ctrl->tCK;
printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
/* Find CAS latency */
val = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK);
printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
/* Find lowest supported CAS latency that satisfies the minimum value */
while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
&& (ctrl->cas_supported >> (val - MIN_CAS))) {
val++;
}
/* Is CAS supported */
if (!(ctrl->cas_supported & (1 << (val - MIN_CAS)))) {
printk(BIOS_ERR, "CAS %uT not supported. ", val);
val = MAX_CAS;
/* Find highest supported CAS latency */
while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1))
val--;
printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
}
printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
ctrl->CAS = val;
ctrl->CWL = get_CWL(ctrl->tCK); ctrl->CWL = get_CWL(ctrl->tCK);
printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL); printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
@ -280,32 +301,18 @@ static void dram_timing(ramctr_timing * ctrl)
static void dram_freq(ramctr_timing * ctrl) static void dram_freq(ramctr_timing * ctrl)
{ {
if (ctrl->tCK > TCK_400MHZ) { if (ctrl->tCK > TCK_400MHZ) {
printk(BIOS_ERR, "DRAM frequency is under lowest supported " printk(BIOS_ERR, "DRAM frequency is under lowest supported "
"frequency (400 MHz). Increasing to 400 MHz as last resort"); "frequency (400 MHz). Increasing to 400 MHz as last resort");
ctrl->tCK = TCK_400MHZ; ctrl->tCK = TCK_400MHZ;
} }
while (1) { while (1) {
u8 val2; u8 val2;
u32 reg1 = 0; u32 reg1 = 0;
/* Step 1 - Set target PCU frequency */ find_cas_tck(ctrl);
if (ctrl->tCK <= TCK_1066MHZ) {
ctrl->tCK = TCK_1066MHZ;
} else if (ctrl->tCK <= TCK_933MHZ) {
ctrl->tCK = TCK_933MHZ;
} else if (ctrl->tCK <= TCK_800MHZ) {
ctrl->tCK = TCK_800MHZ;
} else if (ctrl->tCK <= TCK_666MHZ) {
ctrl->tCK = TCK_666MHZ;
} else if (ctrl->tCK <= TCK_533MHZ) {
ctrl->tCK = TCK_533MHZ;
} else if (ctrl->tCK <= TCK_400MHZ) {
ctrl->tCK = TCK_400MHZ;
} else {
die ("No lock frequency found");
}
/* Frequency multiplier. */ /* Frequency multiplier. */
u32 FRQ = get_FRQ(ctrl->tCK); u32 FRQ = get_FRQ(ctrl->tCK);
@ -318,7 +325,7 @@ static void dram_freq(ramctr_timing * ctrl)
if (val2) if (val2)
return; return;
/* Step 2 - Select frequency in the MCU */ /* Step 1 - Select frequency in the MCU */
reg1 = FRQ; reg1 = FRQ;
reg1 |= 0x80000000; // set running bit reg1 |= 0x80000000; // set running bit
MCHBAR32(MC_BIOS_REQ) = reg1; MCHBAR32(MC_BIOS_REQ) = reg1;
@ -331,7 +338,7 @@ static void dram_freq(ramctr_timing * ctrl)
} }
printk(BIOS_DEBUG, "done in %d us\n", i * 10); printk(BIOS_DEBUG, "done in %d us\n", i * 10);
/* Step 3 - Verify lock frequency */ /* Step 2 - Verify lock frequency */
reg1 = MCHBAR32(MC_BIOS_DATA); reg1 = MCHBAR32(MC_BIOS_DATA);
val2 = (u8) reg1; val2 = (u8) reg1;
if (val2 >= FRQ) { if (val2 >= FRQ) {