From 9ed74b54b573d9f26ccd1ec382206c5c0c8048ff Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 16 May 2017 19:56:49 +0200 Subject: 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 Reviewed-on: https://review.coreboot.org/19717 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/northbridge/intel/sandybridge/raminit_ivy.c | 200 ++++++++++++------------ 1 file changed, 101 insertions(+), 99 deletions(-) (limited to 'src/northbridge/intel/sandybridge') diff --git a/src/northbridge/intel/sandybridge/raminit_ivy.c b/src/northbridge/intel/sandybridge/raminit_ivy.c index 97bf50b52d..675ac7181c 100644 --- a/src/northbridge/intel/sandybridge/raminit_ivy.c +++ b/src/northbridge/intel/sandybridge/raminit_ivy.c @@ -287,16 +287,103 @@ static u32 get_COMP2(u32 tCK, u8 base_freq) 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; 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). * We cap it at 1200Mhz (DDR3 2400). * Then, align it to the closest JEDEC standard frequency */ - if (ctrl->tCK <= TCK_1200MHZ) { - ctrl->tCK = TCK_1200MHZ; + if (ctrl->tCK == TCK_1200MHZ) { ctrl->edge_offset[0] = 18; //XXX: guessed ctrl->edge_offset[1] = 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[2] = 8; ctrl->reg_320c_range_threshold = 10; - } else if (ctrl->tCK <= TCK_1100MHZ) { - ctrl->tCK = TCK_1100MHZ; + } else if (ctrl->tCK == TCK_1100MHZ) { ctrl->edge_offset[0] = 17; //XXX: guessed ctrl->edge_offset[1] = 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[2] = 7; ctrl->reg_320c_range_threshold = 13; - } else if (ctrl->tCK <= TCK_1066MHZ) { - ctrl->tCK = TCK_1066MHZ; + } else if (ctrl->tCK == TCK_1066MHZ) { ctrl->edge_offset[0] = 16; ctrl->edge_offset[1] = 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[2] = 7; ctrl->reg_320c_range_threshold = 13; - } else if (ctrl->tCK <= TCK_1000MHZ) { - ctrl->tCK = TCK_1000MHZ; + } else if (ctrl->tCK == TCK_1000MHZ) { ctrl->edge_offset[0] = 15; //XXX: guessed ctrl->edge_offset[1] = 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[2] = 6; ctrl->reg_320c_range_threshold = 13; - } else if (ctrl->tCK <= TCK_933MHZ) { - ctrl->tCK = TCK_933MHZ; + } else if (ctrl->tCK == TCK_933MHZ) { ctrl->edge_offset[0] = 14; ctrl->edge_offset[1] = 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[2] = 6; ctrl->reg_320c_range_threshold = 15; - } else if (ctrl->tCK <= TCK_900MHZ) { - ctrl->tCK = TCK_900MHZ; + } else if (ctrl->tCK == TCK_900MHZ) { ctrl->edge_offset[0] = 14; //XXX: guessed ctrl->edge_offset[1] = 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[2] = 6; ctrl->reg_320c_range_threshold = 12; - } else if (ctrl->tCK <= TCK_800MHZ) { - ctrl->tCK = TCK_800MHZ; + } else if (ctrl->tCK == TCK_800MHZ) { ctrl->edge_offset[0] = 13; ctrl->edge_offset[1] = 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[2] = 5; ctrl->reg_320c_range_threshold = 15; - } else if (ctrl->tCK <= TCK_700MHZ) { - ctrl->tCK = TCK_700MHZ; + } else if (ctrl->tCK == TCK_700MHZ) { ctrl->edge_offset[0] = 13; //XXX: guessed ctrl->edge_offset[1] = 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[2] = 5; ctrl->reg_320c_range_threshold = 16; - } else if (ctrl->tCK <= TCK_666MHZ) { - ctrl->tCK = TCK_666MHZ; + } else if (ctrl->tCK == TCK_666MHZ) { ctrl->edge_offset[0] = 10; ctrl->edge_offset[1] = 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[2] = 4; ctrl->reg_320c_range_threshold = 16; - } else if (ctrl->tCK <= TCK_533MHZ) { - ctrl->tCK = TCK_533MHZ; + } else if (ctrl->tCK == TCK_533MHZ) { ctrl->edge_offset[0] = 8; ctrl->edge_offset[1] = 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[2] = 3; ctrl->reg_320c_range_threshold = 17; - } else { - ctrl->tCK = TCK_400MHZ; + } else { /* TCK_400MHZ */ ctrl->edge_offset[0] = 6; ctrl->edge_offset[1] = 2; ctrl->edge_offset[2] = 2; @@ -402,30 +479,6 @@ static void dram_timing(ramctr_timing * ctrl) /* DLL_CONFIG_MDLL_W_TIMER */ 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); 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) { - bool ref_100mhz_support; - u32 reg32; - if (ctrl->tCK > TCK_400MHZ) { printk (BIOS_ERR, "DRAM frequency is under lowest supported " "frequency (400 MHz). Increasing to 400 MHz as last resort"); 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) { u8 val2; u32 reg1 = 0; /* Step 1 - Set target PCU frequency */ - - 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; - } + find_cas_tck(ctrl); /* Frequency multiplier. */ u32 FRQ = get_FRQ(ctrl->tCK, ctrl->base_freq); -- cgit v1.2.3