Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17673
-gerrit
commit c57b4fce3f18bf101681d2ad51ba99207ae2de7e
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Thu Dec 1 10:48:43 2016 +0200
intel/sandybridge: Use postcar_frame for MTRR setup
Adapt implementation from skylake.
Change-Id: Ica3134a2261d3e84c714264cf75557322f9ef5db
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
src/cpu/intel/model_206ax/cache_as_ram.inc | 24 ++++++++--
src/northbridge/intel/sandybridge/ram_calc.c | 71 ++++++----------------------
2 files changed, 36 insertions(+), 59 deletions(-)
diff --git a/src/cpu/intel/model_206ax/cache_as_ram.inc b/src/cpu/intel/model_206ax/cache_as_ram.inc
index f0d4939..149cae6 100644
--- a/src/cpu/intel/model_206ax/cache_as_ram.inc
+++ b/src/cpu/intel/model_206ax/cache_as_ram.inc
@@ -225,12 +225,29 @@ before_romstage:
post_code(0x38)
- /* Get number of MTRRs. */
+ /* Clear all of the variable MTRRs. */
popl %ebx
movl $MTRR_PHYS_BASE(0), %ecx
+ clr %eax
+ clr %edx
+
1:
testl %ebx, %ebx
jz 1f
+ wrmsr /* Write MTRR base. */
+ inc %ecx
+ wrmsr /* Write MTRR mask. */
+ inc %ecx
+ dec %ebx
+ jmp 1b
+
+1:
+ /* Get number of MTRRs. */
+ popl %ebx
+ movl $MTRR_PHYS_BASE(0), %ecx
+2:
+ testl %ebx, %ebx
+ jz 2f
/* Low 32 bits of MTRR base. */
popl %eax
@@ -248,8 +265,9 @@ before_romstage:
inc %ecx
dec %ebx
- jmp 1b
-1:
+ jmp 2b
+2:
+
post_code(0x39)
/* And enable cache again after setting MTRRs. */
diff --git a/src/northbridge/intel/sandybridge/ram_calc.c b/src/northbridge/intel/sandybridge/ram_calc.c
index 026531a..43442f1 100644
--- a/src/northbridge/intel/sandybridge/ram_calc.c
+++ b/src/northbridge/intel/sandybridge/ram_calc.c
@@ -19,6 +19,7 @@
#include <arch/cpu.h>
#include <arch/io.h>
#include <cbmem.h>
+#include <console/console.h>
#include <cpu/intel/romstage.h>
#include <cpu/x86/mtrr.h>
#include <program_loading.h>
@@ -43,83 +44,41 @@ void *cbmem_top(void)
return (void *) smm_region_start();
}
-static inline u32 *stack_push(u32 *stack, u32 value)
-{
- stack = &stack[-1];
- *stack = value;
- return stack;
-}
+#define ROMSTAGE_RAM_STACK_SIZE 0x5000
/* setup_stack_and_mtrrs() determines the stack to use after
* cache-as-ram is torn down as well as the MTRR settings to use. */
void *setup_stack_and_mtrrs(void)
{
- int num_mtrrs;
- u32 *slot;
- u32 mtrr_mask_upper;
- u32 top_of_ram;
+ struct postcar_frame pcf;
+ uintptr_t top_of_ram;
- /* Top of stack needs to be aligned to a 4-byte boundary. */
- slot = (void *)romstage_ram_stack_top();
- num_mtrrs = 0;
-
- /* The upper bits of the MTRR mask need to set according to the number
- * of physical address bits. */
- mtrr_mask_upper = (1 << (cpu_phys_address_size() - 32)) - 1;
-
- /* The order for each MTRR is value then base with upper 32-bits of
- * each value coming before the lower 32-bits. The reasoning for
- * this ordering is to create a stack layout like the following:
- * +0: Number of MTRRs
- * +4: MTRR base 0 31:0
- * +8: MTRR base 0 63:32
- * +12: MTRR mask 0 31:0
- * +16: MTRR mask 0 63:32
- * +20: MTRR base 1 31:0
- * +24: MTRR base 1 63:32
- * +28: MTRR mask 1 31:0
- * +32: MTRR mask 1 63:32
- */
+ if (postcar_frame_init(&pcf, ROMSTAGE_RAM_STACK_SIZE))
+ die("Unable to initialize postcar frame.\n");
/* Cache the ROM as WP just below 4GiB. */
- slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
- slot = stack_push(slot, ~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID);
- slot = stack_push(slot, 0); /* upper base */
- slot = stack_push(slot, ~(CACHE_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
- num_mtrrs++;
+ postcar_frame_add_mtrr(&pcf, -CACHE_ROM_SIZE, CACHE_ROM_SIZE,
+ MTRR_TYPE_WRPROT);
/* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
- slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
- slot = stack_push(slot, ~(CACHE_TMP_RAMTOP - 1) | MTRR_PHYS_MASK_VALID);
- slot = stack_push(slot, 0); /* upper base */
- slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
- num_mtrrs++;
+ postcar_frame_add_mtrr(&pcf, 0, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
- top_of_ram = (uint32_t)cbmem_top();
+ top_of_ram = (uintptr_t)cbmem_top();
/* Cache 8MiB below the top of ram. On sandybridge systems the top of
* ram under 4GiB is the start of the TSEG region. It is required to
* be 8MiB aligned. Set this area as cacheable so it can be used later
* for ramstage before setting up the entire RAM as cacheable. */
- slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
- slot = stack_push(slot, ~((8 << 20) - 1) | MTRR_PHYS_MASK_VALID);
- slot = stack_push(slot, 0); /* upper base */
- slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK);
- num_mtrrs++;
+ postcar_frame_add_mtrr(&pcf, top_of_ram - 8*MiB, 8*MiB, MTRR_TYPE_WRBACK);
/* Cache 8MiB at the top of ram. Top of ram on sandybridge systems
* is where the TSEG region resides. However, it is not restricted
* to SMM mode until SMM has been relocated. By setting the region
* to cacheable it provides faster access when relocating the SMM
* handler as well as using the TSEG region for other purposes. */
- slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
- slot = stack_push(slot, ~((8 << 20) - 1) | MTRR_PHYS_MASK_VALID);
- slot = stack_push(slot, 0); /* upper base */
- slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK);
- num_mtrrs++;
+ postcar_frame_add_mtrr(&pcf, top_of_ram, 8*MiB, MTRR_TYPE_WRBACK);
/* Save the number of MTRRs to setup. Return the stack location
- * pointing to the number of MTRRs. */
- slot = stack_push(slot, num_mtrrs);
-
- return slot;
+ * pointing to the number of MTRRs.
+ */
+ return postcar_commit_mtrrs(&pcf);
}
Nicola Corna (nicola(a)corna.info) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17476
-gerrit
commit 442d43f9b50638737d01099844d417f93ced9509
Author: Nicola Corna <nicola(a)corna.info>
Date: Wed Nov 16 08:57:15 2016 +0100
device/dram/ddr3: add FTB timings
SPD revision 1.1 introduced FTB timings, an extra set of SPD values that
specify a more precise tCKmin, tAAmin, tRCDmin, tRPmin and tRCmin.
For backwards compatibility, the MTB is usually rounded up and the FTB
part is negative. For this reason some memories were not set up optimally,
as the FTB part was ignored and the resulting timing wasn't set to the
minimum value.
The tests were performed on a Lenovo X220 with two Micron 8KTF51264HZ-1G9E
(1866 MHz): reading only the MTB part, Coreboot reported a tCKmin of
1.125 ns, corresponding to a working frequency of 800 MHz; with the
additional tCKmin FTB part (-0.054 ns) the new (rounded) value is
1.070 ns, valid for a 933 MHz operation.
Some manufacturers (like Micron) seems to expect a small rounding on the
timings, so a nearest-value rounding is performed. If this assumption
isn't correct, an error up to ~2 ps can be committed, which is low enough
to be safely ignored.
Change-Id: Ib98f2e70820f207429d04ca6421680109a81f457
Signed-off-by: Nicola Corna <nicola(a)corna.info>
---
src/device/dram/ddr3.c | 37 ++++++++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c
index cb5b685..641220f 100644
--- a/src/device/dram/ddr3.c
+++ b/src/device/dram/ddr3.c
@@ -108,9 +108,10 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
{
int ret;
u16 crc, spd_crc;
- u8 ftb_divisor, ftb_dividend, capacity_shift, bus_width;
+ u8 capacity_shift, bus_width;
u8 reg8;
u32 mtb; /* medium time base */
+ u32 ftb; /* fine time base */
unsigned int val, param;
ret = SPD_STATUS_OK;
@@ -242,12 +243,6 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
dimm->size_mb = ((1 << (capacity_shift + (25 - 20))) * bus_width
* dimm->ranks) / dimm->width;
- /* Fine Timebase (FTB) Dividend/Divisor */
- /* Dividend */
- ftb_dividend = (spd[9] >> 4) & 0x0f;
- /* Divisor */
- ftb_divisor = spd[9] & 0x0f;
-
/* Medium Timebase =
* Medium Timebase (MTB) Dividend /
* Medium Timebase (MTB) Divisor */
@@ -280,6 +275,34 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
/* Minimum Four Activate Window Delay Time (tFAWmin) */
dimm->tFAW = (((spd[28] & 0x0f) << 8) + spd[29]) * mtb;
+ printram(" FTB timings :");
+ /* FTB is introduced in SPD revision 1.1 */
+ if (spd[1] >= 0x11 && spd[9] & 0x0f) {
+ printram(" yes\n");
+
+ /* Fine timebase (1/256 ps) =
+ * Fine Timebase (FTB) Dividend /
+ * Fine Timebase (FTB) Divisor */
+ ftb = (((u16) spd[9] & 0xf0) << 4) / (spd[9] & 0x0f);
+
+ /* SPD recommends to round up the MTB part and use a negative
+ * FTB, so a negative rounding should be always safe */
+
+ /* SDRAM Minimum Cycle Time (tCKmin) correction */
+ dimm->tCK += (s32)((s8) spd[34] * ftb - 500) / 1000;
+ /* Minimum CAS Latency Time (tAAmin) correction */
+ dimm->tAA += (s32)((s8) spd[35] * ftb - 500) / 1000;
+ /* Minimum RAS# to CAS# Delay Time (tRCDmin) correction */
+ dimm->tRCD += (s32)((s8) spd[36] * ftb - 500) / 1000;
+ /* Minimum Row Precharge Delay Time (tRPmin) correction */
+ dimm->tRP += (s32)((s8) spd[37] * ftb - 500) / 1000;
+ /* Minimum Active to Active/Refresh Delay Time (tRCmin) corr. */
+ dimm->tRC += (s32)((s8) spd[38] * ftb - 500) / 1000;
+ }
+ else {
+ printram(" no\n");
+ }
+
/* SDRAM Optional Features */
reg8 = spd[30];
printram(" Optional features :");