nb/intel/ivybridge: 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: I1df20a0a723dc515686a766ad1b0567d815f6e89
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19717
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 19:56:49 +02:00
parent dcd3cef874
commit 9ed74b54b5
1 changed files with 101 additions and 99 deletions

View File

@ -287,16 +287,103 @@ static u32 get_COMP2(u32 tCK, u8 base_freq)
return comp2; return comp2;
} }
static void dram_timing(ramctr_timing * ctrl) static void ivb_normalize_tclk(ramctr_timing *ctrl,
bool ref_100mhz_support)
{
if (ctrl->tCK <= TCK_1200MHZ) {
ctrl->tCK = TCK_1200MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_1100MHZ) {
ctrl->tCK = TCK_1100MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_1066MHZ) {
ctrl->tCK = TCK_1066MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_1000MHZ) {
ctrl->tCK = TCK_1000MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_933MHZ) {
ctrl->tCK = TCK_933MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_900MHZ) {
ctrl->tCK = TCK_900MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_800MHZ) {
ctrl->tCK = TCK_800MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_700MHZ) {
ctrl->tCK = TCK_700MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_666MHZ) {
ctrl->tCK = TCK_666MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_533MHZ) {
ctrl->tCK = TCK_533MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_400MHZ) {
ctrl->tCK = TCK_400MHZ;
ctrl->base_freq = 133;
} else {
ctrl->tCK = 0;
return;
}
if (!ref_100mhz_support && ctrl->base_freq == 100) {
/* Skip unsupported frequency. */
ctrl->tCK++;
ivb_normalize_tclk(ctrl, ref_100mhz_support);
}
}
static void find_cas_tck(ramctr_timing *ctrl)
{ {
u8 val; u8 val;
u32 val32; u32 val32;
u32 reg32;
u8 ref_100mhz_support;
/* 100 Mhz reference clock supported */
reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
ref_100mhz_support = !!((reg32 >> 21) & 0x7);
printk(BIOS_DEBUG, "100MHz reference clock support: %s\n",
ref_100mhz_support ? "yes" : "no");
/* Find CAS latency */
while (1) {
/* Normalising tCK before computing clock could potentially
* results in lower selected CAS, which is desired.
*/
ivb_normalize_tclk(ctrl, ref_100mhz_support);
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 1400MHz (DDR3 2800). /* Maximum supported DDR3 frequency is 1400MHz (DDR3 2800).
* We cap it at 1200Mhz (DDR3 2400). * We cap it at 1200Mhz (DDR3 2400).
* Then, align it to the closest JEDEC standard frequency */ * Then, align it to the closest JEDEC standard frequency */
if (ctrl->tCK <= TCK_1200MHZ) { if (ctrl->tCK == TCK_1200MHZ) {
ctrl->tCK = TCK_1200MHZ;
ctrl->edge_offset[0] = 18; //XXX: guessed ctrl->edge_offset[0] = 18; //XXX: guessed
ctrl->edge_offset[1] = 8; ctrl->edge_offset[1] = 8;
ctrl->edge_offset[2] = 8; ctrl->edge_offset[2] = 8;
@ -304,8 +391,7 @@ static void dram_timing(ramctr_timing * ctrl)
ctrl->timC_offset[1] = 8; ctrl->timC_offset[1] = 8;
ctrl->timC_offset[2] = 8; ctrl->timC_offset[2] = 8;
ctrl->reg_320c_range_threshold = 10; ctrl->reg_320c_range_threshold = 10;
} else if (ctrl->tCK <= TCK_1100MHZ) { } else if (ctrl->tCK == TCK_1100MHZ) {
ctrl->tCK = TCK_1100MHZ;
ctrl->edge_offset[0] = 17; //XXX: guessed ctrl->edge_offset[0] = 17; //XXX: guessed
ctrl->edge_offset[1] = 7; ctrl->edge_offset[1] = 7;
ctrl->edge_offset[2] = 7; ctrl->edge_offset[2] = 7;
@ -313,8 +399,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_1066MHZ) { } else 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;
@ -322,8 +407,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_1000MHZ) { } else if (ctrl->tCK == TCK_1000MHZ) {
ctrl->tCK = TCK_1000MHZ;
ctrl->edge_offset[0] = 15; //XXX: guessed ctrl->edge_offset[0] = 15; //XXX: guessed
ctrl->edge_offset[1] = 6; ctrl->edge_offset[1] = 6;
ctrl->edge_offset[2] = 6; ctrl->edge_offset[2] = 6;
@ -331,8 +415,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 = 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;
@ -340,8 +423,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_900MHZ) { } else if (ctrl->tCK == TCK_900MHZ) {
ctrl->tCK = TCK_900MHZ;
ctrl->edge_offset[0] = 14; //XXX: guessed ctrl->edge_offset[0] = 14; //XXX: guessed
ctrl->edge_offset[1] = 6; ctrl->edge_offset[1] = 6;
ctrl->edge_offset[2] = 6; ctrl->edge_offset[2] = 6;
@ -349,8 +431,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 = 12; ctrl->reg_320c_range_threshold = 12;
} 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;
@ -358,8 +439,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_700MHZ) { } else if (ctrl->tCK == TCK_700MHZ) {
ctrl->tCK = TCK_700MHZ;
ctrl->edge_offset[0] = 13; //XXX: guessed ctrl->edge_offset[0] = 13; //XXX: guessed
ctrl->edge_offset[1] = 5; ctrl->edge_offset[1] = 5;
ctrl->edge_offset[2] = 5; ctrl->edge_offset[2] = 5;
@ -367,8 +447,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 = 16; ctrl->reg_320c_range_threshold = 16;
} 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;
@ -376,8 +455,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;
@ -385,8 +463,7 @@ static void dram_timing(ramctr_timing * ctrl)
ctrl->timC_offset[1] = 3; ctrl->timC_offset[1] = 3;
ctrl->timC_offset[2] = 3; ctrl->timC_offset[2] = 3;
ctrl->reg_320c_range_threshold = 17; ctrl->reg_320c_range_threshold = 17;
} else { } else { /* TCK_400MHZ */
ctrl->tCK = TCK_400MHZ;
ctrl->edge_offset[0] = 6; ctrl->edge_offset[0] = 6;
ctrl->edge_offset[1] = 2; ctrl->edge_offset[1] = 2;
ctrl->edge_offset[2] = 2; ctrl->edge_offset[2] = 2;
@ -402,30 +479,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);
@ -476,69 +529,18 @@ static void dram_timing(ramctr_timing * ctrl)
static void dram_freq(ramctr_timing * ctrl) static void dram_freq(ramctr_timing * ctrl)
{ {
bool ref_100mhz_support;
u32 reg32;
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;
} }
/* 100 Mhz reference clock supported */
reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
ref_100mhz_support = !!((reg32 >> 21) & 0x7);
printk(BIOS_DEBUG, "100MHz reference clock support: %s\n",
ref_100mhz_support ? "yes" : "no");
while (1) { while (1) {
u8 val2; u8 val2;
u32 reg1 = 0; u32 reg1 = 0;
/* Step 1 - Set target PCU frequency */ /* Step 1 - Set target PCU frequency */
find_cas_tck(ctrl);
if (ctrl->tCK <= TCK_1200MHZ) {
ctrl->tCK = TCK_1200MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_1100MHZ) {
ctrl->tCK = TCK_1100MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_1066MHZ) {
ctrl->tCK = TCK_1066MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_1000MHZ) {
ctrl->tCK = TCK_1000MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_933MHZ) {
ctrl->tCK = TCK_933MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_900MHZ) {
ctrl->tCK = TCK_900MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_800MHZ) {
ctrl->tCK = TCK_800MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_700MHZ) {
ctrl->tCK = TCK_700MHZ;
ctrl->base_freq = 100;
} else if (ctrl->tCK <= TCK_666MHZ) {
ctrl->tCK = TCK_666MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_533MHZ) {
ctrl->tCK = TCK_533MHZ;
ctrl->base_freq = 133;
} else if (ctrl->tCK <= TCK_400MHZ) {
ctrl->tCK = TCK_400MHZ;
ctrl->base_freq = 133;
} else {
die ("No lock frequency found");
}
if (!ref_100mhz_support && ctrl->base_freq == 100) {
/* Skip unsupported frequency. */
ctrl->tCK++;
continue;
}
/* Frequency multiplier. */ /* Frequency multiplier. */
u32 FRQ = get_FRQ(ctrl->tCK, ctrl->base_freq); u32 FRQ = get_FRQ(ctrl->tCK, ctrl->base_freq);