summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch
diff options
context:
space:
mode:
authorFrancis Rowe <info@gluglug.org.uk>2016-03-08 01:00:09 (EST)
committer Francis Rowe <info@gluglug.org.uk>2016-03-08 02:32:32 (EST)
commitdfa21bb8ee01eac21a2acee79011a634cb67e373 (patch)
tree21cd4f855aa03db13abba91400ad3be212b11602 /resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch
parent2e5e505da125f9d90dd63c1cbcb08bf5316b21ae (diff)
downloadlibreboot-dfa21bb8ee01eac21a2acee79011a634cb67e373.zip
libreboot-dfa21bb8ee01eac21a2acee79011a634cb67e373.tar.gz
libreboot-dfa21bb8ee01eac21a2acee79011a634cb67e373.tar.bz2
Update coreboot (kgpe-d16,kcma-d8,kfsn4-dre,d510mo,ga-g41m-es2l)
Update to the latest coreboot and vboot versions at the time of writing: coreboot 2a3434757ef425dbdfedf1fc69e1a033a6e7310d vboot d187cd3fc792f8bcefbee4587c83eafbd08441fc
Diffstat (limited to 'resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch')
-rw-r--r--resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch16249
1 files changed, 0 insertions, 16249 deletions
diff --git a/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch b/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch
deleted file mode 100644
index fa979fe..0000000
--- a/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch
+++ /dev/null
@@ -1,16249 +0,0 @@
-From 429c96728e6a22e1d53f801c8bd4075a91fe422b Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <tpearson@raptorengineeringinc.com>
-Date: Fri, 16 Oct 2015 13:51:51 -0500
-Subject: [PATCH 034/143] cpu/amd: Add initial AMD Family 15h support
-
-TEST: Booted ASUS KGPE-D16 with single Opteron 6380
- * Unbuffered DDR3 DIMMs tested and working
- * Suspend to RAM (S3) tested and working
-
-Conflicts:
-
- src/cpu/amd/car/disable_cache_as_ram.c
-
-Change-Id: Idffd2ce36ce183fbfa087e5ba69a9148f084b45e
-Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
----
- src/cpu/amd/car/cache_as_ram.inc | 130 +-
- src/cpu/amd/car/disable_cache_as_ram.c | 79 +-
- src/cpu/amd/family_10h-family_15h/defaults.h | 266 +-
- src/cpu/amd/family_10h-family_15h/fidvid.c | 237 +-
- src/cpu/amd/family_10h-family_15h/init_cpus.c | 232 +-
- .../amd/family_10h-family_15h/model_10xxx_init.c | 92 +-
- src/cpu/amd/family_10h-family_15h/powernow_acpi.c | 50 +-
- src/cpu/amd/family_10h-family_15h/processor_name.c | 194 +-
- .../amd/family_10h-family_15h/update_microcode.c | 6 +
- src/cpu/amd/model_fxx/init_cpus.c | 2 +-
- src/cpu/amd/quadcore/quadcore.c | 109 +-
- src/cpu/amd/quadcore/quadcore_id.c | 43 +-
- src/include/cpu/amd/model_10xxx_msr.h | 7 +
- src/mainboard/advansus/a785e-i/romstage.c | 2 +-
- src/mainboard/amd/bimini_fam10/romstage.c | 2 +-
- src/mainboard/amd/mahogany_fam10/romstage.c | 2 +-
- .../amd/serengeti_cheetah_fam10/romstage.c | 2 +-
- src/mainboard/amd/tilapia_fam10/romstage.c | 2 +-
- src/mainboard/asus/kfsn4-dre/romstage.c | 2 +-
- src/mainboard/asus/kgpe-d16/romstage.c | 4 +-
- src/mainboard/asus/m4a78-em/romstage.c | 2 +-
- src/mainboard/asus/m4a785-m/romstage.c | 2 +-
- src/mainboard/asus/m5a88-v/romstage.c | 2 +-
- src/mainboard/avalue/eax-785e/romstage.c | 2 +-
- src/mainboard/gigabyte/ma785gm/romstage.c | 2 +-
- src/mainboard/gigabyte/ma785gmt/romstage.c | 2 +-
- src/mainboard/gigabyte/ma78gm/romstage.c | 2 +-
- src/mainboard/hp/dl165_g6_fam10/romstage.c | 2 +-
- src/mainboard/iei/kino-780am2-fam10/romstage.c | 2 +-
- src/mainboard/jetway/pa78vm5/romstage.c | 2 +-
- src/mainboard/msi/ms9652_fam10/romstage.c | 2 +-
- src/mainboard/supermicro/h8dmr_fam10/romstage.c | 2 +-
- src/mainboard/supermicro/h8qme_fam10/romstage.c | 2 +-
- src/mainboard/supermicro/h8scm_fam10/romstage.c | 2 +-
- src/mainboard/tyan/s2912_fam10/romstage.c | 2 +-
- src/northbridge/amd/amdfam10/Kconfig | 2 +-
- src/northbridge/amd/amdfam10/Makefile.inc | 2 +
- src/northbridge/amd/amdfam10/amdfam10.h | 6 +-
- src/northbridge/amd/amdfam10/amdfam10_util.c | 13 +-
- src/northbridge/amd/amdfam10/link_control.c | 86 +
- src/northbridge/amd/amdfam10/misc_control.c | 7 +
- src/northbridge/amd/amdfam10/nb_control.c | 85 +
- src/northbridge/amd/amdfam10/northbridge.c | 233 +-
- src/northbridge/amd/amdfam10/raminit_amdmct.c | 304 +-
- src/northbridge/amd/amdht/h3ncmn.c | 171 +-
- src/northbridge/amd/amdht/ht_wrapper.c | 43 +-
- src/northbridge/amd/amdmct/amddefs.h | 78 +-
- src/northbridge/amd/amdmct/mct/mct_d.c | 4 +-
- src/northbridge/amd/amdmct/mct/mct_d.h | 20 +-
- src/northbridge/amd/amdmct/mct/mctpro_d.c | 21 +-
- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 3187 ++++++++++++++++----
- src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 124 +-
- src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h | 9 +
- src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c | 21 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c | 27 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c | 1087 ++++++-
- src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c | 55 +-
- src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c | 7 +-
- src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c | 105 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctproc.c | 2 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctrci.c | 24 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c | 585 +++-
- src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c | 1342 ++++++++-
- src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c | 10 +-
- src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c | 20 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctwl.c | 255 +-
- src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c | 1007 +++++--
- src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c | 69 +-
- src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h | 46 +-
- src/northbridge/amd/amdmct/mct_ddr3/s3utils.c | 652 +++-
- src/northbridge/amd/amdmct/wrappers/mcti.h | 14 +-
- src/northbridge/amd/amdmct/wrappers/mcti_d.c | 43 +-
- 72 files changed, 9192 insertions(+), 2067 deletions(-)
- create mode 100644 src/northbridge/amd/amdfam10/link_control.c
- create mode 100644 src/northbridge/amd/amdfam10/nb_control.c
-
-diff --git a/src/cpu/amd/car/cache_as_ram.inc b/src/cpu/amd/car/cache_as_ram.inc
-index 0b2bc60..6542906 100644
---- a/src/cpu/amd/car/cache_as_ram.inc
-+++ b/src/cpu/amd/car/cache_as_ram.inc
-@@ -32,18 +32,23 @@
- #define CacheSizeAPStack CONFIG_DCACHE_AP_STACK_SIZE
-
- #define MSR_MCFG_BASE 0xC0010058
--#define MSR_FAM10 0xC001102A
-+#define MSR_BU_CFG2 0xC001102A
-
- #define jmp_if_k8(x) comisd %xmm2, %xmm1; jb x
-+#define jmp_if_not_fam15h(x) comisd %xmm3, %xmm1; jb x
-+#define jmp_if_fam15h(x) comisd %xmm3, %xmm1; jae x
-
- #define CPUID_MASK 0x0ff00f00
- #define CPUID_VAL_FAM10_ROTATED 0x0f000010
-+#define CPUID_VAL_FAM15_ROTATED 0x0f000060
-
- /*
- * XMM map:
- * xmm1: CPU family
- * xmm2: Fam10h comparison value
-- * xmm3: Backup EBX
-+ * xmm3: Fam15h comparison value
-+ * xmm4: Backup EBX
-+ * xmm5: Coreboot init detect
- */
-
- /* Save the BIST result. */
-@@ -63,7 +68,7 @@ cache_as_ram_setup:
- movl %eax, %cr4
-
- /* Figure out the CPU family. */
-- cvtsi2sd %ebx, %xmm3
-+ cvtsi2sd %ebx, %xmm4
- movl $0x01, %eax
- cpuid
- /* Base family is bits 8..11, extended family is bits 20..27. */
-@@ -73,13 +78,16 @@ cache_as_ram_setup:
- cvtsi2sd %eax, %xmm1
- movl $CPUID_VAL_FAM10_ROTATED, %eax
- cvtsi2sd %eax, %xmm2
-- cvtsd2si %xmm3, %ebx
-+ movl $CPUID_VAL_FAM15_ROTATED, %eax
-+ cvtsi2sd %eax, %xmm3
-+ cvtsd2si %xmm4, %ebx
-
- /* Check if cpu_init_detected. */
- movl $MTRR_DEF_TYPE_MSR, %ecx
- rdmsr
- andl $MTRR_DEF_TYPE_EN, %eax
- movl %eax, %ebx /* We store the status. */
-+ cvtsi2sd %ebx, %xmm5
-
- jmp_if_k8(CAR_FAM10_out_post_errata)
-
-@@ -120,21 +128,24 @@ cache_as_ram_setup:
-
- CAR_FAM10_out:
-
-+ jmp_if_fam15h(CAR_FAM10_errata_applied)
- /*
- * Errata 193: Disable clean copybacks to L3 cache to allow cached ROM.
- * Re-enable it in after RAM is initialized and before CAR is disabled.
- */
-- movl $MSR_FAM10, %ecx
-+ movl $MSR_BU_CFG2, %ecx
- rdmsr
-- bts $15, %eax
-+ bts $15, %eax /* Set bit 15 in EDX:EAX (bit 15 in EAX). */
- wrmsr
-
- /* Erratum 343, RevGuide for Fam10h, Pub#41322 Rev. 3.33 */
-- movl $MSR_FAM10, %ecx
-+ movl $MSR_BU_CFG2, %ecx
- rdmsr
- bts $35-32, %edx /* Set bit 35 in EDX:EAX (bit 3 in EDX). */
- wrmsr
-
-+CAR_FAM10_errata_applied:
-+
- #if CONFIG_MMCONF_SUPPORT
- #if (CONFIG_MMCONF_BASE_ADDRESS > 0xFFFFFFFF)
- #error "MMCONF_BASE_ADDRESS too big"
-@@ -169,6 +180,63 @@ CAR_FAM10_out:
-
- CAR_FAM10_out_post_errata:
-
-+ /* Fam15h APIC IDs do not depend on NB config bit 54 */
-+ jmp_if_not_fam15h(skip_nb54_set)
-+ movl $0xc001001f, %ecx /* NB_CFG_MSR */
-+ rdmsr
-+ bts $(54 - 32), %edx /* Set NB config bit 54 */
-+ wrmsr
-+
-+skip_nb54_set:
-+ /* On Fam15h CPUs each compute unit's MTRRs are shared between two cores */
-+ jmp_if_not_fam15h(skip_cu_check)
-+
-+ /* Get the initial APIC ID. */
-+ movl $1, %eax
-+ cpuid
-+ movl %ebx, %eax
-+
-+ /* Restore init detect */
-+ cvtsd2si %xmm5, %ebx
-+
-+ /* Determine if this is the second core to start in a compute unit; if so, wait for first core start, clear init detect and skip MTRR init */
-+ bt $24, %eax
-+ jnc skip_cu_check /* First core in the compute unit jumps to skip_cu_check */
-+
-+ /* Determine if this is the second core to start in a compute unit; if so, clear init detect and skip MTRR init */
-+ /* Busywait until the first core sets up the MTRRs */
-+check_init_detect_1:
-+ /* Check if cpu_init_detected. */
-+ movl $MTRR_DEF_TYPE_MSR, %ecx
-+ rdmsr
-+ andl $MTRR_DEF_TYPE_EN, %eax
-+ cmp $0x00000000, %eax
-+ je check_init_detect_1 /* First core has not yet started */
-+
-+check_init_detect_2:
-+ movl $SYSCFG_MSR, %ecx
-+ rdmsr
-+ andl $(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrVarDramEn), %eax
-+ cmp $0x00000000, %eax
-+ je check_init_detect_2 /* First core has not yet started */
-+
-+ /* First core has now started */
-+ movl $0x00000000, %ebx /* Clear init detect flag */
-+ cvtsi2sd %ebx, %xmm5
-+ jmp fam10_mtrr_setup_complete
-+
-+skip_cu_check:
-+
-+ jmp_if_not_fam15h(CAR_FAM15_errata_applied)
-+
-+ /* Erratum 714, RevGuide for Fam15h, Pub#48063 Rev. 3.24 */
-+ movl $MSR_BU_CFG2, %ecx
-+ rdmsr
-+ bts $8, %eax /* Set bit 8 in EDX:EAX (bit 8 in EAX). */
-+ wrmsr
-+
-+CAR_FAM15_errata_applied:
-+
- /* Set MtrrFixDramModEn for clear fixed MTRR. */
- enable_fixed_mtrr_dram_modify:
- movl $SYSCFG_MSR, %ecx
-@@ -337,8 +405,42 @@ wbcache_post_fam10_setup:
- orl $(SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn), %eax
- wrmsr
-
-+fam10_mtrr_setup_complete:
- post_code(0xa1)
-
-+ /* Disable conversion of INVD to WBINVD (INVDWBINVD = 0) */
-+ mov $0xc0010015, %ecx
-+ rdmsr
-+ btr $4, %eax
-+ wrmsr
-+
-+jmp_if_not_fam15h(fam15_car_msr_setup_complete)
-+ /* Disable streaming store (DisSS = 1) */
-+ mov $0xc0011020, %ecx
-+ rdmsr
-+ bts $28, %eax
-+ wrmsr
-+
-+ /* Disable speculative ITLB reloads (DisSpecTlbRld = 1) */
-+ mov $0xc0011021, %ecx
-+ rdmsr
-+ bts $9, %eax
-+ wrmsr
-+
-+ /* Disable speculative DTLB reloads (DisSpecTlbRld = 1) and set DisHwPf = 1 */
-+ mov $0xc0011022, %ecx
-+ rdmsr
-+ bts $4, %eax
-+ bts $13, %eax
-+ wrmsr
-+
-+ /* Disable CR0 combining (CombineCr0Cd = 0) */
-+ mov $0xc001102b, %ecx
-+ rdmsr
-+ btr $49-32, %edx
-+ wrmsr
-+fam15_car_msr_setup_complete:
-+
- /* Enable cache. */
- movl %cr0, %eax
- andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
-@@ -393,9 +495,6 @@ CAR_FAM10_ap:
- * to reverse it.
- */
-
-- /* Store our init detected. */
-- movl %ebx, %esi
--
- /* Get the coreid bits at first. */
- movl $0x80000008, %eax
- cpuid
-@@ -414,6 +513,8 @@ CAR_FAM10_ap:
- movl %edi, %ecx /* CoreID bits */
- bt $(54 - 32), %edx
- jc roll_cfg
-+
-+ /* Fam10h NB config bit 54 was not set */
- rolb %cl, %bl
- roll_cfg:
-
-@@ -423,8 +524,8 @@ roll_cfg:
- movl $(CacheBase + (CacheSize - (CacheSizeBSPStack + CacheSizeBSPSlush))), %esp
- subl %eax, %esp
-
-- /* Retrive init detected. */
-- movl %esi, %ebx
-+ /* Restore init detect */
-+ cvtsd2si %xmm5, %ebx
-
- post_code(0xa4)
-
-@@ -437,6 +538,8 @@ CAR_FAM10_ap_out:
- andl $~(3 << 9), %eax
- movl %eax, %cr4
-
-+ post_code(0xa6)
-+
- /* Restore the BIST result. */
- movl %ebp, %eax
-
-@@ -444,6 +547,9 @@ CAR_FAM10_ap_out:
- movl %esp, %ebp
- pushl %ebx /* Init detected. */
- pushl %eax /* BIST */
-+
-+ post_code(0xa7)
-+
- call cache_as_ram_main
-
- /* We will not go back. */
-diff --git a/src/cpu/amd/car/disable_cache_as_ram.c b/src/cpu/amd/car/disable_cache_as_ram.c
-index 5eccf79..86180ee 100644
---- a/src/cpu/amd/car/disable_cache_as_ram.c
-+++ b/src/cpu/amd/car/disable_cache_as_ram.c
-@@ -19,7 +19,7 @@
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.
- *
-- * be warned, this file will be used other cores and core 0 / node 0
-+ * WARNING: this file will be used by both any AP cores and core 0 / node 0
- */
-
- #include <cpu/x86/cache.h>
-@@ -34,41 +34,80 @@ static inline __attribute__((always_inline)) uint32_t amd_fam1x_cpu_family(void)
- return family;
- }
-
--static inline __attribute__((always_inline)) void disable_cache_as_ram(void)
-+static inline __attribute__((always_inline)) void disable_cache_as_ram(uint8_t skip_sharedc_config)
- {
- msr_t msr;
-+ uint32_t family;
-
-- /* disable cache */
-- write_cr0(read_cr0() | CR0_CacheDisable);
-+ if (!skip_sharedc_config) {
-+ /* disable cache */
-+ write_cr0(read_cr0() | CR0_CacheDisable);
-
-- msr.lo = 0;
-- msr.hi = 0;
-- wrmsr(MTRR_FIX_4K_C8000, msr);
-+ msr.lo = 0;
-+ msr.hi = 0;
-+ wrmsr(MTRR_FIX_4K_C8000, msr);
- #if CONFIG_DCACHE_RAM_SIZE > 0x8000
-- wrmsr(MTRR_FIX_4K_C0000, msr);
-+ wrmsr(MTRR_FIX_4K_C0000, msr);
- #endif
- #if CONFIG_DCACHE_RAM_SIZE > 0x10000
-- wrmsr(MTRR_FIX_4K_D0000, msr);
-+ wrmsr(MTRR_FIX_4K_D0000, msr);
- #endif
- #if CONFIG_DCACHE_RAM_SIZE > 0x18000
-- wrmsr(MTRR_FIX_4K_D8000, msr);
-+ wrmsr(MTRR_FIX_4K_D8000, msr);
- #endif
-- /* disable fixed mtrr from now on, it will be enabled by ramstage again*/
-+ /* disable fixed mtrr from now on, it will be enabled by ramstage again */
-+ msr = rdmsr(SYSCFG_MSR);
-+ msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn);
-+ wrmsr(SYSCFG_MSR, msr);
-+
-+ /* Set the default memory type and disable fixed and enable variable MTRRs */
-+ msr.hi = 0;
-+ msr.lo = (1 << 11);
-+
-+ wrmsr(MTRR_DEF_TYPE_MSR, msr);
-+
-+ enable_cache();
-+ }
-
-- msr = rdmsr(SYSCFG_MSR);
-- msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn);
-- wrmsr(SYSCFG_MSR, msr);
-+ /* INVDWBINVD = 1 */
-+ msr = rdmsr(0xc0010015);
-+ msr.lo |= (0x1 << 4);
-+ wrmsr(0xc0010015, msr);
-
-- /* Set the default memory type and disable fixed and enable variable MTRRs */
-- msr.hi = 0;
-- msr.lo = (1 << 11);
-+ family = amd_fam1x_cpu_family();
-
-- wrmsr(MTRR_DEF_TYPE_MSR, msr);
-+#if IS_ENABLED(CPU_AMD_MODEL_10XXX)
-+ if (family >= 0x6f) {
-+ /* Family 15h or later */
-
-- enable_cache();
-+ /* DisSS = 0 */
-+ msr = rdmsr(0xc0011020);
-+ msr.lo &= ~(0x1 << 28);
-+ wrmsr(0xc0011020, msr);
-+
-+ if (!skip_sharedc_config) {
-+ /* DisSpecTlbRld = 0 */
-+ msr = rdmsr(0xc0011021);
-+ msr.lo &= ~(0x1 << 9);
-+ wrmsr(0xc0011021, msr);
-+
-+ /* Erratum 714: SpecNbReqDis = 0 */
-+ msr = rdmsr(BU_CFG2_MSR);
-+ msr.lo &= ~(0x1 << 8);
-+ wrmsr(BU_CFG2_MSR, msr);
-+ }
-+
-+ /* DisSpecTlbRld = 0 */
-+ /* DisHwPf = 0 */
-+ msr = rdmsr(0xc0011022);
-+ msr.lo &= ~(0x1 << 4);
-+ msr.lo &= ~(0x1 << 13);
-+ wrmsr(0xc0011022, msr);
-+ }
-+#endif
- }
-
- static void disable_cache_as_ram_bsp(void)
- {
-- disable_cache_as_ram();
-+ disable_cache_as_ram(0);
- }
-diff --git a/src/cpu/amd/family_10h-family_15h/defaults.h b/src/cpu/amd/family_10h-family_15h/defaults.h
-index 6fd1a7e..24f87ba 100644
---- a/src/cpu/amd/family_10h-family_15h/defaults.h
-+++ b/src/cpu/amd/family_10h-family_15h/defaults.h
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -25,41 +26,65 @@
- */
- static const struct {
- u32 msr;
-- u32 revision;
-+ uint64_t revision;
- u32 platform;
- u32 data_lo;
- u32 data_hi;
- u32 mask_lo;
- u32 mask_hi;
- } fam10_msr_default[] = {
-- { TOP_MEM2, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { TOP_MEM2, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00000000, 0x00000000,
- 0xFFFFFFFF, 0xFFFFFFFF },
-
-- { SYSCFG, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { SYSCFG, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 3 << 21, 0x00000000,
- 3 << 21, 0x00000000 }, /* [MtrrTom2En]=1,[TOM2EnWB] = 1*/
-
-- { HWCR, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-- 1 << 4, 0x00000000,
-- 1 << 4, 0x00000000 }, /* [INVD_WBINVD]=1 */
-+ { MC1_CTL_MASK, AMD_OR_B2, AMD_PTYPE_ALL,
-+ 1 << 18, 0x00000000,
-+ 1 << 18, 0x00000000 }, /* Erratum 586: [DEIBP]=1 */
-
-- { MC4_CTL_MASK, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { MC1_CTL_MASK, AMD_OR_B2, AMD_PTYPE_ALL,
-+ 1 << 15, 0x00000000,
-+ 1 << 15, 0x00000000 }, /* Erratum 593: [BSRP]=1 */
-+
-+ { MC1_CTL_MASK, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 1 << 15, 0x00000000,
-+ 1 << 15, 0x00000000 }, /* Erratum 739: [BSRP]=1 */
-+
-+ { 0xc0011000, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 1 << 16, 0x00000000,
-+ 1 << 16, 0x00000000 }, /* Erratum 608: [bit 16]=1 */
-+
-+ { 0xc0011000, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 1 << 15, 0x00000000,
-+ 1 << 15, 0x00000000 }, /* Erratum 727: [bit 15]=1 */
-+
-+ { MC4_CTL_MASK, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0xF << 19, 0x00000000,
- 0xF << 19, 0x00000000 }, /* [RtryHt[0..3]]=1 */
-
-+ { MC4_CTL_MASK, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
-+ 1 << 10, 0x00000000,
-+ 1 << 10, 0x00000000 }, /* [GartTblWkEn]=1 */
-+
- { DC_CFG, AMD_FAM10_ALL, AMD_PTYPE_SVR,
- 0x00000000, 0x00000004,
-- 0x00000000, 0x0000000C }, /* [REQ_CTR] = 1 for Server */
-+ 0x00000000, 0x0000000C }, /* Family 10h: [REQ_CTR] = 1 for Server */
-
- { DC_CFG, AMD_DR_Bx, AMD_PTYPE_SVR,
- 0x00000000, 0x00000000,
- 0x00000000, 0x00000C00 }, /* Erratum 326 */
-
-- { NB_CFG, AMD_FAM10_ALL, AMD_PTYPE_DC | AMD_PTYPE_MC,
-+ { NB_CFG, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_DC | AMD_PTYPE_MC,
- 0x00000000, 1 << 22,
- 0x00000000, 1 << 22 }, /* [ApicInitIDLo]=1 */
-
-+ { NB_CFG, AMD_FAM15_ALL, AMD_PTYPE_DC | AMD_PTYPE_MC,
-+ 1 << 23, 0x00000000,
-+ 1 << 23, 0x00000000 }, /* Erratum 663: [bit 23]=1 */
-+
- { BU_CFG2, AMD_DR_Bx, AMD_PTYPE_ALL,
- 1 << 29, 0x00000000,
- 1 << 29, 0x00000000 }, /* For Bx Smash1GPages=1 */
-@@ -72,6 +97,14 @@ static const struct {
- 0 << 1, 0x00000000,
- 1 << 1, 0x00000000 }, /* IDX_MATCH_ALL=0 */
-
-+ { IC_CFG, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 0x00000000, 1 << (39-32),
-+ 0x00000000, 1 << (39-32)}, /* C0 or above [DisLoopPredictor]=1 */
-+
-+ { IC_CFG, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 0xf << 1, 0x00000000,
-+ 0xf << 1, 0x00000000}, /* C0 or above [DisIcWayFilter]=0xf */
-+
- { BU_CFG, AMD_DR_LT_B3, AMD_PTYPE_ALL,
- 1 << 21, 0x00000000,
- 1 << 21, 0x00000000 }, /* Erratum #254 DR B1 BU_CFG[21]=1 */
-@@ -80,19 +113,51 @@ static const struct {
- 1 << 23, 0x00000000,
- 1 << 23, 0x00000000 }, /* Erratum #309 BU_CFG[23]=1 */
-
-+ { BU_CFG, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0 << 10, 0x00000000,
-+ 1 << 10, 0x00000000 }, /* [DcacheAgressivePriority]=0 */
-+
- /* CPUID_EXT_FEATURES */
-- { CPUIDFEATURES, AMD_FAM10_ALL, AMD_PTYPE_DC | AMD_PTYPE_MC,
-+ { CPUIDFEATURES, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_DC | AMD_PTYPE_MC,
- 1 << 28, 0x00000000,
- 1 << 28, 0x00000000 }, /* [HyperThreadFeatEn]=1 */
-
-- { CPUIDFEATURES, AMD_FAM10_ALL, AMD_PTYPE_DC,
-+ { CPUIDFEATURES, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_DC,
- 0x00000000, 1 << (33-32),
- 0x00000000, 1 << (33-32) }, /* [ExtendedFeatEn]=1 */
-
-+ { DE_CFG, AMD_OR_B2, AMD_PTYPE_ALL,
-+ 1 << 10, 0x00000000,
-+ 1 << 10, 0x00000000 }, /* Bx [ResyncPredSingleDispDis]=1 */
-+
- { BU_CFG2, AMD_DRBH_Cx, AMD_PTYPE_ALL,
- 0x00000000, 1 << (35-32),
- 0x00000000, 1 << (35-32) }, /* Erratum 343 (set to 0 after CAR, in post_cache_as_ram()/model_10xxx_init() ) */
-
-+ { BU_CFG3, AMD_OR_B2, AMD_PTYPE_ALL,
-+ 0x00000000, 1 << (42-32),
-+ 0x00000000, 1 << (42-32)}, /* Bx [PwcDisableWalkerSharing]=1 */
-+
-+ { BU_CFG3, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 1 << 22, 0x00000000,
-+ 1 << 22, 0x00000000}, /* C0 or above [PfcDoubleStride]=1 */
-+
-+ { EX_CFG, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 0x00000000, 1 << (54-32),
-+ 0x00000000, 1 << (54-32)}, /* C0 or above [LateSbzResync]=1 */
-+
-+ { LS_CFG2, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 1 << 23, 0x00000000,
-+ 1 << 23, 0x00000000}, /* C0 or above [DisScbThreshold]=1 */
-+
-+ { LS_CFG2, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 1 << 14, 0x00000000,
-+ 1 << 14, 0x00000000}, /* C0 or above [ForceSmcCheckFlowStDis]=1 */
-+
-+ { LS_CFG2, AMD_OR_C0, AMD_PTYPE_ALL,
-+ 1 << 12, 0x00000000,
-+ 1 << 12, 0x00000000}, /* C0 or above [ForceBusLockDis]=1 */
-+
- { OSVW_ID_Length, AMD_DR_Bx | AMD_DR_Cx | AMD_DR_Dx, AMD_PTYPE_ALL,
- 0x00000004, 0x00000000,
- 0x00000004, 0x00000000}, /* B0 or Above, OSVW_ID_Length is 0004h */
-@@ -105,9 +170,45 @@ static const struct {
- 0x00000000, 1 << (50-32),
- 0x00000000, 1 << (50-32)}, /* D0 or Above, RdMmExtCfgQwEn*/
-
-+ { BU_CFG2, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000000, 0x0 << (36-32),
-+ 0x00000000, 0x3 << (36-32)}, /* [ThrottleNbInterface]=0 */
-+
-+ { BU_CFG2, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 1 << 10, 0x00000000,
-+ 1 << 10, 0x00000000}, /* [VicResyncChkEn]=1 */
-+
-+ { BU_CFG2, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 1 << 11, 0x00000000,
-+ 1 << 11, 0x00000000}, /* Erratum 503: [bit 11]=1 */
-+
- { CPU_ID_EXT_FEATURES_MSR, AMD_DR_Dx, AMD_PTYPE_ALL,
- 0x00000000, 1 << (51 - 32),
- 0x00000000, 1 << (51 - 32)}, /* G34_PKG | C32_PKG | S1G4_PKG | ASB2_PKG */
-+
-+ { CPU_ID_EXT_FEATURES_MSR, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000000, 1 << (56 - 32),
-+ 0x00000000, 1 << (56 - 32)}, /* [PerfCtrExtNB]=1 */
-+
-+ { CPU_ID_EXT_FEATURES_MSR, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000000, 1 << (55 - 32),
-+ 0x00000000, 1 << (55 - 32)}, /* [PerfCtrExtCore]=1 */
-+
-+ { IBS_OP_DATA3, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0 << 16, 0x00000000,
-+ 1 << 16, 0x00000000}, /* [IbsDcMabHit]=0 */
-+
-+ { MC4_MISC0, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000000, 0x1 << (52-32),
-+ 0x00000000, 0xf << (52-32)}, /* [LvtOffset]=1 */
-+
-+ { MC4_MISC1, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000000, 0x1 << (52-32),
-+ 0x00000000, 0xf << (52-32)}, /* [LvtOffset]=1 */
-+
-+ { MC4_MISC2, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000000, 0x1 << (52-32),
-+ 0x00000000, 0xf << (52-32)}, /* [LvtOffset]=1 */
- };
-
-
-@@ -117,37 +218,46 @@ static const struct {
- static const struct {
- u8 function;
- u16 offset;
-- u32 revision;
-+ uint64_t revision;
- u32 platform;
- u32 data;
- u32 mask;
- } fam10_pci_default[] = {
-
- /* Function 0 - HT Config */
-+ { 0, 0x68, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
-+ 0x000e0000, 0x000e0000 }, /* [19:17] for 8bit APIC config */
-+
-+ { 0, 0x68, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
-+ 0x00400000, 0x00600000 }, /* [22:21] DsNpReqLmt = 10b */
-
-- { 0, 0x68, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-- 0x004E4800, 0x006E6800 }, /* [19:17] for 8bit APIC config,
-- [14:13] BufPriRel = 2h [11] RspPassPW set,
-- [22:21] DsNpReqLmt = 10b */
-+ { 0, 0x68, AMD_FAM10_LT_D, AMD_PTYPE_ALL,
-+ 0x00004000, 0x00006000 }, /* [14:13] BufRelPri = 2h */
-+
-+ { 0, 0x68, (AMD_FAM10_REV_D | AMD_FAM15_ALL), AMD_PTYPE_ALL,
-+ 0x00002000, 0x00006000 }, /* [14:13] BufRelPri = 1h */
-+
-+ { 0, 0x68, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
-+ 0x00000800, 0x00000800 }, /* [11] RspPassPW = 1 */
-
- /* Errata 281 Workaround */
- { 0, 0x68, (AMD_DR_B0 | AMD_DR_B1),
- AMD_PTYPE_SVR, 0x00200000, 0x00600000 }, /* [22:21] DsNpReqLmt0 = 01b */
-
-- { 0, 0x84, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 0, 0x84, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00002000, 0x00002000 }, /* [13] LdtStopTriEn = 1 */
-
-- { 0, 0xA4, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 0, 0xA4, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00002000, 0x00002000 }, /* [13] LdtStopTriEn = 1 */
-
-- { 0, 0xC4, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 0, 0xC4, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00002000, 0x00002000 }, /* [13] LdtStopTriEn = 1 */
-
-- { 0, 0xE4, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 0, 0xE4, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00002000, 0x00002000 }, /* [13] LdtStopTriEn = 1 */
-
- /* Link Global Retry Control Register */
-- { 0, 0x150, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 0, 0x150, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00073900, 0x00073F00 },
-
- /* Errata 351
-@@ -172,13 +282,39 @@ static const struct {
- 0x00000000, 0x00000100 },
- { 0, 0x18C, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0x00000000, 0x00000100 },
-- { 0, 0x170, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-- 0x00000000, 0x00000100 },
-
- /* Link Global Extended Control Register */
- { 0, 0x16C, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0x00000014, 0x0000003F }, /* [15:13] ForceFullT0 = 0b,
-- * Set T0Time 14h per BKDG */
-+ * Set T0Time 14h per BKDG */
-+
-+ { 0, 0x170, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x174, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x178, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x17C, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x180, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x184, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x188, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+ { 0, 0x18C, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000100, 0x00000100 },
-+
-+ /* Link Global Extended Control Register */
-+ { 0, 0x16C, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000014, 0x0000003F }, /* [15:13] ForceFullT0 = 111b,
-+ * Set T0Time 26h per BKDG */
-+
-+ { 0, 0x16C, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x7 << 13, 0x7 << 13 }, /* [15:13] ForceFullT0 = 7h */
-+
-+ { 0, 0x16C, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x26, 0x3f }, /* [5:0] T0Time = 26h */
-
-
- /* Function 1 - Map Init */
-@@ -205,10 +341,10 @@ static const struct {
- /* Function 2 - DRAM Controller */
-
- /* Function 3 - Misc. Control */
-- { 3, 0x40, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0x40, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00000100, 0x00000100 }, /* [8] MstrAbrtEn */
-
-- { 3, 0x44, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0x44, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x4A30005C, 0x4A30005C }, /* [30] SyncOnDramAdrParErrEn = 1,
- [27] NbMcaToMstCpuEn = 1,
- [25] DisPciCfgCpuErrRsp = 1,
-@@ -220,8 +356,12 @@ static const struct {
- [2] SyncOnUcEccEn = 1 */
-
- /* XBAR buffer settings */
-- { 3, 0x6C, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-- 0x00018052, 0x700780F7 },
-+ { 3, 0x6c, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ 0x00018052, 0x700780f7 },
-+
-+ /* XBAR buffer settings */
-+ { 3, 0x6c, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x10010052, 0x700700f7 },
-
- /* Errata 281 Workaround */
- { 3, 0x6C, ( AMD_DR_B0 | AMD_DR_B1),
-@@ -233,12 +373,18 @@ static const struct {
- { 3, 0x70, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0x00041153, 0x777777F7 },
-
-+ { 3, 0x70, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x10171155, 0x777777f7 },
-+
- { 3, 0x70, AMD_FAM10_ALL, AMD_PTYPE_UMA,
- 0x61221151, 0x777777F7 },
-
- { 3, 0x74, AMD_FAM10_ALL, AMD_PTYPE_UMA,
- 0x00080101, 0x000F7777 },
-
-+ { 3, 0x74, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00172111, 0x77ff7777 },
-+
- { 3, 0x7C, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0x00090914, 0x707FFF1F },
-
-@@ -246,12 +392,18 @@ static const struct {
- { 3, 0x7C, ( AMD_DR_B0 | AMD_DR_B1),
- AMD_PTYPE_SVR, 0x00144514, 0x707FFF1F },
-
-+ { 3, 0x7C, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x040d0f16, 0x07ffff1f },
-+
- { 3, 0x7C, AMD_FAM10_ALL, AMD_PTYPE_UMA,
- 0x00070814, 0x007FFF1F },
-
- { 3, 0x140, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0x00800756, 0x00F3FFFF },
-
-+ { 3, 0x140, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00a11755, 0x00f3ffff },
-+
- { 3, 0x140, AMD_FAM10_ALL, AMD_PTYPE_UMA,
- 0x00C37756, 0x00F3FFFF },
-
-@@ -263,6 +415,9 @@ static const struct {
- AMD_PTYPE_SVR, 0x00000001, 0x0000000F },
- /* [3:0] RspTok = 0001b */
-
-+ { 3, 0x144, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x00000028, 0x000000ff },
-+
- { 3, 0x148, AMD_FAM10_ALL, AMD_PTYPE_UMA,
- 0x8000052A, 0xD5FFFFFF },
-
-@@ -270,41 +425,53 @@ static const struct {
- { 3, 0x80, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0xE6002200, 0xFFFFFFFF },
-
-+ /* ACPI Power State Control Reg1 */
-+ { 3, 0x80, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0xe20be200, 0xefefef00 },
-+
- /* ACPI Power State Control Reg2 */
- { 3, 0x84, AMD_FAM10_ALL, AMD_PTYPE_ALL,
- 0xA0E641E6, 0xFFFFFFFF },
-
-+ /* ACPI Power State Control Reg2 */
-+ { 3, 0x84, AMD_FAM15_ALL, AMD_PTYPE_ALL,
-+ 0x01e200e2, 0xefef00ef },
-+
- { 3, 0xA0, AMD_FAM10_ALL, AMD_PTYPE_MOB | AMD_PTYPE_DSK,
- 0x00000080, 0x00000080 }, /* [7] PSIVidEnable */
-
- { 3, 0xA0, AMD_DR_Bx, AMD_PTYPE_ALL,
- 0x00002800, 0x000003800 }, /* [13:11] PllLockTime = 5 */
-
-- { 3, 0xA0, (AMD_FAM10_ALL & ~(AMD_DR_Bx)), AMD_PTYPE_ALL,
-+ { 3, 0xA0, ((AMD_FAM10_ALL | AMD_FAM15_ALL) & ~(AMD_DR_Bx)), AMD_PTYPE_ALL,
- 0x00000800, 0x000003800 }, /* [13:11] PllLockTime = 1 */
-
- /* Reported Temp Control Register */
-- { 3, 0xA4, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0xA4, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00000080, 0x00000080 }, /* [7] TempSlewDnEn = 1 */
-
- /* Clock Power/Timing Control 0 Register */
-- { 3, 0xD4, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0xD4, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0xC0000F00, 0xF0000F00 }, /* [31] NbClkDivApplyAll = 1,
- [30:28] NbClkDiv = 100b,[11:8] ClkRampHystSel = 1111b */
-
- /* Clock Power/Timing Control 1 Register */
-+ { 3, 0xD8, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
-+ 0x03000010, 0x0F000070 }, /* [6:4] VSRampTime = 1,
-+ * [27:24] ReConDel = 3 */
-+
-+ /* Clock Power/Timing Control 1 Register */
- { 3, 0xD8, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-- 0x03000016, 0x0F000077 }, /* [6:4] VSRampTime = 1,
-- [2:0] VSSlamTime = 6, [27:24] ReConDel = 3 */
-+ 0x00000006, 0x00000007 }, /* [2:0] VSSlamTime = 6 */
-
-
- /* Clock Power/Timing Control 2 Register */
-- { 3, 0xDC, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0xDC, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00005000, 0x00007000 }, /* [14:12] NbsynPtrAdj = 5 */
-
-
- /* Extended NB MCA Config Register */
-- { 3, 0x180, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0x180, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x007003E2, 0x007003E2 }, /* [22:20] = SyncFloodOn_Err = 7,
- [9] SyncOnUncNbAryEn = 1 ,
- [8] SyncOnProtEn = 1,
-@@ -319,12 +486,17 @@ static const struct {
- 0x00400000, 0x00400000 },
-
- /* L3 Control Register */
-- { 3, 0x1B8, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0x1b8, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00001000, 0x00001000 }, /* [12] = L3PrivReplEn */
-
- /* IBS Control Register */
-- { 3, 0x1CC, AMD_FAM10_ALL, AMD_PTYPE_ALL,
-+ { 3, 0x1cc, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
- 0x00000100, 0x00000100 }, /* [8] = LvtOffsetVal */
-+
-+ /* Erratum 619 - Family 15h Bx
-+ * System software should set F5x88[14] to 1b. */
-+ { 5, 0x88, AMD_OR_B2, AMD_PTYPE_ALL,
-+ 1 << 14, 1 << 14 },
- };
-
-
-@@ -333,7 +505,7 @@ static const struct {
- */
- static const struct {
- u16 htreg; /* HT Phy Register index */
-- u32 revision;
-+ uint64_t revision;
- u32 platform;
- u32 linktype;
- u32 data;
-@@ -442,38 +614,38 @@ static const struct {
- { 0x530A, AMD_DR_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_ALL,
- 0x00004400, 0x00006400 }, /* HT_PHY_DLL_REG */
-
-- { 0xCF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
-+ { 0xCF, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
- 0x00000000, 0x000000FF }, /* Provide clear setting for logical
- completeness */
-
-- { 0xDF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
-+ { 0xDF, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
- 0x00000000, 0x000000FF }, /* Provide clear setting for logical
- completeness */
-
-- { 0xCF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
-+ { 0xCF, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
- 0x0000006D, 0x000000FF }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */
-
-- { 0xDF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
-+ { 0xDF, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
- 0x0000006D, 0x000000FF }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */
-
- /* Link Phy Receiver Loop Filter Registers */
-- { 0xD1, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
-+ { 0xD1, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
- 0x08040000, 0x3FFFC000 }, /* [29:22] LfcMax = 20h,
- [21:14] LfcMin = 10h */
-
-- { 0xC1, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
-+ { 0xC1, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3,
- 0x08040000, 0x3FFFC000 }, /* [29:22] LfcMax = 20h,
- [21:14] LfcMin = 10h */
-
-- { 0xD1, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
-+ { 0xD1, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
- 0x04020000, 0x3FFFC000 }, /* [29:22] LfcMax = 10h,
- [21:14] LfcMin = 08h */
-
-- { 0xC1, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
-+ { 0xC1, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1,
- 0x04020000, 0x3FFFC000 }, /* [29:22] LfcMax = 10h,
- [21:14] LfcMin = 08h */
-
-- { 0xC0, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_ALL,
-+ { 0xC0, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, HTPHY_LINKTYPE_ALL,
- 0x40040000, 0xe01F0000 }, /* [31:29] RttCtl = 02h,
- [20:16] RttIndex = 04h */
- };
-diff --git a/src/cpu/amd/family_10h-family_15h/fidvid.c b/src/cpu/amd/family_10h-family_15h/fidvid.c
-index 86e3179..e8e0818 100644
---- a/src/cpu/amd/family_10h-family_15h/fidvid.c
-+++ b/src/cpu/amd/family_10h-family_15h/fidvid.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -43,7 +44,7 @@ Fam10 Bios and Kernel Development Guide #31116, rev 3.48, April 22, 2010
-
- 3.- 2.4.2.7 dualPlaneOnly(dev)
-
--4.- 2.4.2.8 applyBoostFIDOffset(dev)
-+4.- 2.4.2.8 applyBoostFIDOffset(dev, nodeid)
-
- 5.- enableNbPState1(dev)
-
-@@ -142,25 +143,33 @@ static void enable_fid_change(u8 fid)
- }
- }
-
--static void applyBoostFIDOffset( device_t dev ) {
-- // BKDG 2.4.2.8
-- // revision E only, but E is apparently not supported yet, therefore untested
-- if ((cpuid_edx(0x80000007) & CPB_MASK)
-- && ((cpuid_ecx(0x80000008) & NC_MASK) ==5) ) {
-- u32 core = get_node_core_id_x().coreid;
-- u32 asymetricBoostThisCore = ((pci_read_config32(dev, 0x10C) >> (core*2))) & 3;
-- msr_t msr = rdmsr(PS_REG_BASE);
-- u32 cpuFid = msr.lo & PS_CPU_FID_MASK;
-- cpuFid = cpuFid + asymetricBoostThisCore;
-- msr.lo &= ~PS_CPU_FID_MASK;
-- msr.lo |= cpuFid ;
-- wrmsr(PS_REG_BASE , msr);
--
-- }
-+static void applyBoostFIDOffset(device_t dev, uint32_t nodeid) {
-+ // BKDG 2.4.2.8
-+ // Fam10h revision E only, but E is apparently not supported yet, therefore untested
-+ if ((cpuid_edx(0x80000007) & CPB_MASK)
-+ && ((cpuid_ecx(0x80000008) & NC_MASK) == 5) ) {
-+ u32 core = get_node_core_id_x().coreid;
-+ u32 asymetricBoostThisCore = ((pci_read_config32(dev, 0x10C) >> (core*2))) & 3;
-+ msr_t msr = rdmsr(PS_REG_BASE);
-+ u32 cpuFid = msr.lo & PS_CPU_FID_MASK;
-+ cpuFid = cpuFid + asymetricBoostThisCore;
-+ msr.lo &= ~PS_CPU_FID_MASK;
-+ msr.lo |= cpuFid ;
-+ wrmsr(PS_REG_BASE , msr);
-+ } else if (is_fam15h()) {
-+ uint32_t dword = pci_read_config32(NODE_PCI(nodeid, 4), 0x15c);
-+ uint8_t boost_count = (dword >> 2) & 0x7;
-+ if (boost_count > 0) {
-+ /* Enable boost */
-+ dword &= ~0x3;
-+ dword |= 0x1;
-+ pci_write_config32(NODE_PCI(nodeid, 4), 0x15c, dword);
-+ }
-+ }
- }
-
- static void enableNbPState1( device_t dev ) {
-- u32 cpuRev = mctGetLogicalCPUID(0xFF);
-+ uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
- if (cpuRev & AMD_FAM10_C3) {
- u32 nbPState = (pci_read_config32(dev, 0x1F0) & NB_PSTATE_MASK);
- if ( nbPState){
-@@ -202,7 +211,7 @@ static u8 setPStateMaxVal( device_t dev ) {
- static void dualPlaneOnly( device_t dev ) {
- // BKDG 2.4.2.7
-
-- u32 cpuRev = mctGetLogicalCPUID(0xFF);
-+ uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
- if ((mctGetProcessorPackageType() == AMD_PKGTYPE_AM3_2r2)
- && (cpuRev & AMD_DR_Cx)) { // should be rev C or rev E but there's no constant for E
- if ( (pci_read_config32(dev, 0x1FC) & DUAL_PLANE_ONLY_MASK)
-@@ -282,12 +291,16 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev)
- */
-
- /* Determine if this is a PVI or SVI system */
-- dtemp = pci_read_config32(dev, 0xA0);
--
-- if (dtemp & PVI_MODE)
-- pviModeFlag = 1;
-- else
-+ if (is_fam15h()) {
- pviModeFlag = 0;
-+ } else {
-+ dtemp = pci_read_config32(dev, 0xa0);
-+
-+ if (dtemp & PVI_MODE)
-+ pviModeFlag = 1;
-+ else
-+ pviModeFlag = 0;
-+ }
-
- /* Get P0's voltage */
- /* MSRC001_00[68:64] are not programmed yet when called from
-@@ -514,59 +527,67 @@ static void config_nb_syn_ptr_adj(device_t dev, u32 cpuRev) {
- }
-
- static void config_acpi_pwr_state_ctrl_regs(device_t dev, u32 cpuRev, u8 procPkg) {
-- /* step 1, chapter 2.4.2.6 of AMD Fam 10 BKDG #31116 Rev 3.48 22.4.2010 */
-- u32 dword;
-- u32 c1= 1;
-- if (cpuRev & (AMD_DR_Bx)) {
-- // will coreboot ever enable cache scrubbing ?
-- // if it does, will it be enough to check the current state
-- // or should we configure for what we'll set up later ?
-- dword = pci_read_config32(dev, 0x58);
-- u32 scrubbingCache = dword &
-- ( (0x1F << 16) // DCacheScrub
-- | (0x1F << 8) ); // L2Scrub
-- if (scrubbingCache) {
-- c1 = 0x80;
-- } else {
-- c1 = 0xA0;
-- }
-- } else { // rev C or later
-- // same doubt as cache scrubbing: ok to check current state ?
-- dword = pci_read_config32(dev, 0xDC);
-- u32 cacheFlushOnHalt = dword & (7 << 16);
-- if (!cacheFlushOnHalt) {
-- c1 = 0x80;
-- }
-- }
-- dword = (c1 << 24) | (0xE641E6);
-- pci_write_config32(dev, 0x84, dword);
--
--
-- /* FIXME: BKDG Table 100 says if the link is at a Gen1
--frequency and the chipset does not support a 10us minimum LDTSTOP
--assertion time, then { If ASB2 && SVI then smaf001 = F6h else
--smaf001=87h. } else ... I hardly know what it means or how to check
--it from here, so I bluntly assume it is false and code here the else,
--which is easier */
--
-- u32 smaf001 = 0xE6;
-- if (cpuRev & AMD_DR_Bx ) {
-- smaf001 = 0xA6;
-- } else {
-- #if CONFIG_SVI_HIGH_FREQ
-- if (cpuRev & (AMD_RB_C3 | AMD_DA_C3)) {
-- smaf001 = 0xF6;
-- }
-- #endif
-- }
-- u32 fidvidChange = 0;
-- if (((cpuRev & AMD_DA_Cx) && (procPkg & AMD_PKGTYPE_S1gX))
-- || (cpuRev & AMD_RB_C3) ) {
-- fidvidChange=0x0B;
-- }
-- dword = (0xE6 << 24) | (fidvidChange << 16)
-- | (smaf001 << 8) | 0x81;
-- pci_write_config32(dev, 0x80, dword);
-+ if (is_fam15h()) {
-+ /* Family 15h BKDG Rev. 3.14 D18F3x80 recommended settings */
-+ pci_write_config32(dev, 0x80, 0xe20be281);
-+
-+ /* Family 15h BKDG Rev. 3.14 D18F3x84 recommended settings */
-+ pci_write_config32(dev, 0x84, 0x01e200e2);
-+ } else {
-+ /* step 1, chapter 2.4.2.6 of AMD Fam 10 BKDG #31116 Rev 3.48 22.4.2010 */
-+ u32 dword;
-+ u32 c1= 1;
-+ if (cpuRev & (AMD_DR_Bx)) {
-+ // will coreboot ever enable cache scrubbing ?
-+ // if it does, will it be enough to check the current state
-+ // or should we configure for what we'll set up later ?
-+ dword = pci_read_config32(dev, 0x58);
-+ u32 scrubbingCache = dword &
-+ ( (0x1F << 16) // DCacheScrub
-+ | (0x1F << 8) ); // L2Scrub
-+ if (scrubbingCache) {
-+ c1 = 0x80;
-+ } else {
-+ c1 = 0xA0;
-+ }
-+ } else { // rev C or later
-+ // same doubt as cache scrubbing: ok to check current state ?
-+ dword = pci_read_config32(dev, 0xDC);
-+ u32 cacheFlushOnHalt = dword & (7 << 16);
-+ if (!cacheFlushOnHalt) {
-+ c1 = 0x80;
-+ }
-+ }
-+ dword = (c1 << 24) | (0xE641E6);
-+ pci_write_config32(dev, 0x84, dword);
-+
-+ /* FIXME: BKDG Table 100 says if the link is at a Gen1
-+ * frequency and the chipset does not support a 10us minimum LDTSTOP
-+ * assertion time, then { If ASB2 && SVI then smaf001 = F6h else
-+ * smaf001=87h. } else ... I hardly know what it means or how to check
-+ * it from here, so I bluntly assume it is false and code here the else,
-+ * which is easier
-+ */
-+
-+ u32 smaf001 = 0xE6;
-+ if (cpuRev & AMD_DR_Bx ) {
-+ smaf001 = 0xA6;
-+ } else {
-+ #if CONFIG_SVI_HIGH_FREQ
-+ if (cpuRev & (AMD_RB_C3 | AMD_DA_C3)) {
-+ smaf001 = 0xF6;
-+ }
-+ #endif
-+ }
-+ u32 fidvidChange = 0;
-+ if (((cpuRev & AMD_DA_Cx) && (procPkg & AMD_PKGTYPE_S1gX))
-+ || (cpuRev & AMD_RB_C3) ) {
-+ fidvidChange=0x0B;
-+ }
-+ dword = (0xE6 << 24) | (fidvidChange << 16)
-+ | (smaf001 << 8) | 0x81;
-+ pci_write_config32(dev, 0x80, dword);
-+ }
- }
-
- static void prep_fid_change(void)
-@@ -583,7 +604,7 @@ static void prep_fid_change(void)
- for (i = 0; i < nodes; i++) {
- printk(BIOS_DEBUG, "Prep FID/VID Node:%02x\n", i);
- dev = NODE_PCI(i, 3);
-- u32 cpuRev = mctGetLogicalCPUID(0xFF) ;
-+ uint64_t cpuRev = mctGetLogicalCPUID(0xFF) ;
- u8 procPkg = mctGetProcessorPackageType();
-
- setVSRamp(dev);
-@@ -611,7 +632,7 @@ static void prep_fid_change(void)
- }
- }
-
--static void waitCurrentPstate(u32 target_pstate){
-+static void waitCurrentPstate(u32 target_pstate) {
- msr_t initial_msr = rdmsr(TSC_MSR);
- msr_t pstate_msr = rdmsr(CUR_PSTATE_MSR);
- msr_t tsc_msr;
-@@ -644,7 +665,7 @@ static void waitCurrentPstate(u32 target_pstate){
-
- if (pstate_msr.lo != target_pstate) {
- msr_t limit_msr = rdmsr(0xc0010061);
-- printk(BIOS_ERR, "*** Time out waiting for P-state %01x. Current P-state %01x P-state current limit MSRC001_0061=%02x\n", target_pstate, pstate_msr.lo, limit_msr.lo);
-+ printk(BIOS_ERR, "*** Time out waiting for P-state %01x. Current P-state %01x P-state current limit MSRC001_0061=%08x %08x\n", target_pstate, pstate_msr.lo, limit_msr.hi, limit_msr.lo);
-
- do { // should we just go on instead ?
- pstate_msr = rdmsr(CUR_PSTATE_MSR);
-@@ -654,6 +675,7 @@ static void waitCurrentPstate(u32 target_pstate){
-
- static void set_pstate(u32 nonBoostedPState) {
- msr_t msr;
-+ uint8_t skip_wait;
-
- // Transition P0 for calling core.
- msr = rdmsr(0xC0010062);
-@@ -661,12 +683,21 @@ static void set_pstate(u32 nonBoostedPState) {
- msr.lo = nonBoostedPState;
- wrmsr(0xC0010062, msr);
-
-- /* Wait for P0 to set. */
-- waitCurrentPstate(nonBoostedPState);
--}
--
--
-+ if (is_fam15h()) {
-+ /* Do not wait for the first (even) set of cores to transition on Family 15h systems */
-+ if ((cpuid_ebx(0x00000001) & 0x01000000))
-+ skip_wait = 0;
-+ else
-+ skip_wait = 1;
-+ } else {
-+ skip_wait = 0;
-+ }
-
-+ if (!skip_wait) {
-+ /* Wait for core to transition to P0 */
-+ waitCurrentPstate(nonBoostedPState);
-+ }
-+}
-
- static void UpdateSinglePlaneNbVid(void)
- {
-@@ -756,11 +787,14 @@ static u32 needs_NB_COF_VID_update(void)
- u8 nodes;
- u8 i;
-
-+ if (is_fam15h())
-+ return 0;
-+
- /* If any node has nb_cof_vid_update set all nodes need an update. */
- nodes = get_nodes();
- nb_cof_vid_update = 0;
- for (i = 0; i < nodes; i++) {
-- u32 cpuRev = mctGetLogicalCPUID(i) ;
-+ uint64_t cpuRev = mctGetLogicalCPUID(i);
- u32 nbCofVidUpdateDefined = (cpuRev & (AMD_FAM10_LT_D));
- if (nbCofVidUpdateDefined
- && (pci_read_config32(NODE_PCI(i, 3), 0x1FC)
-@@ -784,9 +818,11 @@ static u32 init_fidvid_core(u32 nodeid, u32 coreid)
- /* Steps 1-6 of BIOS NB COF and VID Configuration
- * for SVI and Single-Plane PVI Systems. BKDG 2.4.2.9 #31116 rev 3.48
- */
--
- dev = NODE_PCI(nodeid, 3);
-- pvimode = pci_read_config32(dev, PW_CTL_MISC) & PVI_MODE;
-+ if (is_fam15h())
-+ pvimode = 0;
-+ else
-+ pvimode = pci_read_config32(dev, PW_CTL_MISC) & PVI_MODE;
- reg1fc = pci_read_config32(dev, 0x1FC);
-
- if (nb_cof_vid_update) {
-@@ -798,7 +834,7 @@ static u32 init_fidvid_core(u32 nodeid, u32 coreid)
- fid_max = fid_max + ((reg1fc & DUAL_PLANE_NB_FID_OFF_MASK ) >> DUAL_PLANE_NB_FID_SHIFT );
- }
- /* write newNbVid to P-state Reg's NbVid always if NbVidUpdatedAll=1 */
-- fixPsNbVidBeforeWR(vid_max, coreid,dev,pvimode);
-+ fixPsNbVidBeforeWR(vid_max, coreid, dev, pvimode);
-
- /* fid setup is handled by the BSP at the end. */
-
-@@ -818,7 +854,7 @@ static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid)
-
- printk(BIOS_DEBUG, "FIDVID on AP: %02x\n", apicid);
-
-- send = init_fidvid_core(nodeid,coreid);
-+ send = init_fidvid_core(nodeid, coreid);
- send |= (apicid << 24); // ap apicid
-
- // Send signal to BSP about this AP max fid
-@@ -860,7 +896,8 @@ static void init_fidvid_bsp_stage1(u32 ap_apicid, void *gp)
- while (--loop > 0) {
- if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0)
- continue;
-- if ((readback & 0x3f) == F10_APSTATE_RESET) {
-+ if (((readback & 0x3f) == F10_APSTATE_RESET)
-+ || (is_fam15h() && ((readback & 0x3f) == F10_APSTATE_ASLEEP))) {
- timeout = 0;
- break; /* target ap is in stage 1 */
- }
-@@ -948,7 +985,10 @@ static void init_fidvid_stage2(u32 apicid, u32 nodeid)
- /* If any node has nb_cof_vid_update set all nodes need an update. */
-
- dev = NODE_PCI(nodeid, 3);
-- pvimode = (pci_read_config32(dev, 0xA0) >> 8) & 1;
-+ if (is_fam15h())
-+ pvimode = 0;
-+ else
-+ pvimode = (pci_read_config32(dev, 0xA0) >> 8) & 1;
- reg1fc = pci_read_config32(dev, 0x1FC);
- nbvid = (reg1fc >> 7) & 0x7F;
- NbVidUpdateAll = (reg1fc >> 1) & 1;
-@@ -969,15 +1009,17 @@ static void init_fidvid_stage2(u32 apicid, u32 nodeid)
- pci_write_config32(dev, 0xA0, dtemp);
-
- dualPlaneOnly(dev);
-- applyBoostFIDOffset(dev);
-+ applyBoostFIDOffset(dev, nodeid);
- enableNbPState1(dev);
-
- finalPstateChange();
-
-- /* Set TSC to tick at the P0 ndfid rate */
-- msr = rdmsr(HWCR);
-- msr.lo |= 1 << 24;
-- wrmsr(HWCR, msr);
-+ if (!is_fam15h()) {
-+ /* Set TSC to tick at the P0 ndfid rate */
-+ msr = rdmsr(HWCR);
-+ msr.lo |= 1 << 24;
-+ wrmsr(HWCR, msr);
-+ }
- }
-
-
-@@ -1011,8 +1053,7 @@ static int init_fidvid_bsp(u32 bsp_apicid, u32 nodes)
- /* Steps 1-6 of BIOS NB COF and VID Configuration
- * for SVI and Single-Plane PVI Systems.
- */
--
-- fv.common_fid = init_fidvid_core(0,0);
-+ fv.common_fid = init_fidvid_core(0, 0);
-
- print_debug_fv("BSP fid = ", fv.common_fid);
-
-diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c
-index 8de6d25..aced850 100644
---- a/src/cpu/amd/family_10h-family_15h/init_cpus.c
-+++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c
-@@ -30,9 +30,12 @@
- #include <northbridge/amd/amdfam10/raminit_amdmct.c>
- #include <reset.h>
-
-+#if IS_ENABLED(CONFIG_SET_FIDVID)
- static void prep_fid_change(void);
- static void init_fidvid_stage2(u32 apicid, u32 nodeid);
--void cpuSetAMDMSR(void);
-+#endif
-+
-+void cpuSetAMDMSR(uint8_t node_id);
-
- #if CONFIG_PCI_IO_CFG_EXT
- static void set_EnableCf8ExtCfg(void)
-@@ -51,43 +54,38 @@ static void set_EnableCf8ExtCfg(void) { }
-
- typedef void (*process_ap_t) (u32 apicid, void *gp);
-
--//core_range = 0 : all cores
--//core range = 1 : core 0 only
--//core range = 2 : cores other than core0
-+uint32_t get_boot_apic_id(uint8_t node, uint32_t core) {
-+ uint32_t ap_apicid;
-
--static void for_each_ap(u32 bsp_apicid, u32 core_range, process_ap_t process_ap,
-- void *gp)
--{
-- // here assume the OS don't change our apicid
-- u32 ap_apicid;
-+ uint32_t nb_cfg_54;
-+ uint32_t siblings;
-+ uint32_t cores_found;
-
-- u32 nodes;
-- u32 siblings;
-- u32 disable_siblings;
-- u32 cores_found;
-- u32 nb_cfg_54;
-- int i, j;
-- u32 ApicIdCoreIdSize;
-+ uint8_t fam15h = 0;
- uint8_t rev_gte_d = 0;
- uint8_t dual_node = 0;
- uint32_t f3xe8;
-+ uint32_t family;
-+ uint32_t model;
-
-- /* get_nodes define in ht_wrapper.c */
-- nodes = get_nodes();
--
-- if (!CONFIG_LOGICAL_CPUS ||
-- read_option(multi_core, 0) != 0) { // 0 means multi core
-- disable_siblings = 1;
-- } else {
-- disable_siblings = 0;
-- }
-+ uint32_t ApicIdCoreIdSize;
-
- /* Assume that all node are same stepping, otherwise we can use use
- nb_cfg_54 from bsp for all nodes */
- nb_cfg_54 = read_nb_cfg_54();
- f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
-
-- if (cpuid_eax(0x80000001) >= 0x8)
-+ family = model = cpuid_eax(0x80000001);
-+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f) {
-+ /* Family 15h or later */
-+ fam15h = 1;
-+ nb_cfg_54 = 1;
-+ }
-+
-+ if ((model >= 0x8) || fam15h)
- /* Revision D or later */
- rev_gte_d = 1;
-
-@@ -103,10 +101,63 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, process_ap_t process_ap,
- siblings = 3; //quad core
- }
-
-+ cores_found = get_core_num_in_bsp(node);
-+ if (siblings > cores_found)
-+ siblings = cores_found;
-+
-+ if (dual_node) {
-+ ap_apicid = 0;
-+ if (fam15h) {
-+ ap_apicid |= ((node >> 1) & 0x3) << 5; /* Node ID */
-+ ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
-+ } else {
-+ if (nb_cfg_54) {
-+ ap_apicid |= ((node >> 1) & 0x3) << 4; /* Node ID */
-+ ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
-+ } else {
-+ ap_apicid |= node & 0x3; /* Node ID */
-+ ap_apicid |= (((node & 0x1) * (siblings + 1)) + core) << 4; /* Core ID */
-+ }
-+ }
-+ } else {
-+ if (fam15h) {
-+ ap_apicid = (node * (siblings + 1)) + core;
-+ } else {
-+ ap_apicid = node * (nb_cfg_54 ? (siblings + 1) : 1) +
-+ core * (nb_cfg_54 ? 1 : 64);
-+ }
-+ }
-+
-+ return ap_apicid;
-+}
-+
-+//core_range = 0 : all cores
-+//core range = 1 : core 0 only
-+//core range = 2 : cores other than core0
-+
-+static void for_each_ap(u32 bsp_apicid, u32 core_range, process_ap_t process_ap,
-+ void *gp)
-+{
-+ // here assume the OS don't change our apicid
-+ u32 ap_apicid;
-+
-+ u32 nodes;
-+ u32 disable_siblings;
-+ u32 cores_found;
-+ int i, j;
-+
-+ /* get_nodes define in ht_wrapper.c */
-+ nodes = get_nodes();
-+
-+ if (!CONFIG_LOGICAL_CPUS ||
-+ read_option(multi_core, 0) != 0) { // 0 means multi core
-+ disable_siblings = 1;
-+ } else {
-+ disable_siblings = 0;
-+ }
-+
- for (i = 0; i < nodes; i++) {
- cores_found = get_core_num_in_bsp(i);
-- if (siblings > cores_found)
-- siblings = cores_found;
-
- u32 jstart, jend;
-
-@@ -123,21 +174,7 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, process_ap_t process_ap,
- }
-
- for (j = jstart; j <= jend; j++) {
-- if (dual_node) {
-- ap_apicid = 0;
-- if (nb_cfg_54) {
-- ap_apicid |= ((i >> 1) & 0x3) << 4; /* Node ID */
-- ap_apicid |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */
-- } else {
-- ap_apicid |= i & 0x3; /* Node ID */
-- ap_apicid |= (((i & 0x1) * (siblings + 1)) + j) << 4; /* Core ID */
-- }
-- } else {
-- ap_apicid =
-- i * (nb_cfg_54 ? (siblings + 1) : 1) +
-- j * (nb_cfg_54 ? 1 : 64);
-- }
--
-+ ap_apicid = get_boot_apic_id(i, j);
-
- #if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET > 0)
- #if !CONFIG_LIFT_BSP_APIC_ID
-@@ -197,7 +234,7 @@ void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id,
- apicid, id.nodeid, id.coreid);
- }
-
--static u32 wait_cpu_state(u32 apicid, u32 state)
-+uint32_t wait_cpu_state(uint32_t apicid, uint32_t state, uint32_t state2)
- {
- u32 readback = 0;
- u32 timeout = 1;
-@@ -205,7 +242,7 @@ static u32 wait_cpu_state(u32 apicid, u32 state)
- while (--loop > 0) {
- if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0)
- continue;
-- if ((readback & 0x3f) == state || (readback & 0x3f) == F10_APSTATE_RESET) {
-+ if ((readback & 0x3f) == state || (readback & 0x3f) == state2 || (readback & 0x3f) == F10_APSTATE_RESET) {
- timeout = 0;
- break; //target cpu is in stage started
- }
-@@ -222,7 +259,7 @@ static u32 wait_cpu_state(u32 apicid, u32 state)
- static void wait_ap_started(u32 ap_apicid, void *gp)
- {
- u32 timeout;
-- timeout = wait_cpu_state(ap_apicid, F10_APSTATE_STARTED);
-+ timeout = wait_cpu_state(ap_apicid, F10_APSTATE_STARTED, F10_APSTATE_ASLEEP);
- printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
- if (timeout) {
- printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
-@@ -258,16 +295,27 @@ static void enable_apic_ext_id(u32 node)
- pci_write_config32(NODE_HT(node), 0x68, val);
- }
-
--static void STOP_CAR_AND_CPU(void)
-+static void STOP_CAR_AND_CPU(uint8_t skip_sharedc_config, uint32_t apicid)
- {
- msr_t msr;
-+ uint32_t family;
-+
-+ family = amd_fam1x_cpu_family(); // inline
-+
-+ if (family < 0x6f) {
-+ /* Family 10h or earlier */
-+
-+ /* Disable L2 IC to L3 connection (Only for CAR) */
-+ msr = rdmsr(BU_CFG2);
-+ msr.lo &= ~(1 << ClLinesToNbDis);
-+ wrmsr(BU_CFG2, msr);
-+ }
-
-- /* Disable L2 IC to L3 connection (Only for CAR) */
-- msr = rdmsr(BU_CFG2);
-- msr.lo &= ~(1 << ClLinesToNbDis);
-- wrmsr(BU_CFG2, msr);
-+ disable_cache_as_ram(skip_sharedc_config); // inline
-+
-+ /* Mark the core as sleeping */
-+ lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_ASLEEP);
-
-- disable_cache_as_ram(); // inline
- /* stop all cores except node0/core0 the bsp .... */
- stop_this_cpu();
- }
-@@ -276,6 +324,7 @@ static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
- {
- u32 bsp_apicid = 0;
- u32 apicid;
-+ uint8_t set_mtrrs;
- struct node_core_id id;
-
- /* Please refer to the calculations and explaination in cache_as_ram.inc before modifying these values */
-@@ -362,7 +411,7 @@ static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
- */
- update_microcode(cpuid_eax(1));
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(id.nodeid);
-
- #if CONFIG_SET_FIDVID
- #if CONFIG_LOGICAL_CPUS && CONFIG_SET_FIDVID_CORE0_ONLY
-@@ -385,10 +434,29 @@ static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
- }
- #endif
-
-+ if (is_fam15h()) {
-+ /* core 1 on node 0 is special; to avoid corrupting the
-+ * BSP do not alter MTRRs on that core */
-+ if (apicid == 1)
-+ set_mtrrs = 0;
-+ else
-+ set_mtrrs = !!(apicid & 0x1);
-+ } else {
-+ set_mtrrs = 1;
-+ }
-+
- /* AP is ready, configure MTRRs and go to sleep */
-- set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
-+ if (set_mtrrs)
-+ set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
-
-- STOP_CAR_AND_CPU();
-+ printk(BIOS_DEBUG, "Disabling CAR on AP %02x\n", apicid);
-+ if (is_fam15h()) {
-+ /* Only modify the MSRs on the odd cores (the last cores to finish booting) */
-+ STOP_CAR_AND_CPU(!set_mtrrs, apicid);
-+ } else {
-+ /* Modify MSRs on all cores */
-+ STOP_CAR_AND_CPU(0, apicid);
-+ }
-
- printk(BIOS_DEBUG,
- "\nAP %02x should be halted but you are reading this....\n",
-@@ -496,7 +564,7 @@ static void setup_remote_node(u8 node)
- }
- #endif /* CONFIG_MAX_PHYSICAL_CPUS > 1 */
-
--static void AMD_Errata281(u8 node, u32 revision, u32 platform)
-+static void AMD_Errata281(u8 node, uint64_t revision, u32 platform)
- {
- /* Workaround for Transaction Scheduling Conflict in
- * Northbridge Cross Bar. Implement XCS Token adjustment
-@@ -794,7 +862,7 @@ static void AMD_SetHtPhyRegister(u8 node, u8 link, u8 entry)
- } while (!(val & HTPHY_IS_COMPLETE_MASK));
- }
-
--void cpuSetAMDMSR(void)
-+void cpuSetAMDMSR(uint8_t node_id)
- {
- /* This routine loads the CPU with default settings in fam10_msr_default
- * table . It must be run after Cache-As-RAM has been enabled, and
-@@ -804,7 +872,8 @@ void cpuSetAMDMSR(void)
- */
- msr_t msr;
- u8 i;
-- u32 revision, platform;
-+ u32 platform;
-+ uint64_t revision;
-
- printk(BIOS_DEBUG, "cpuSetAMDMSR ");
-
-@@ -824,6 +893,49 @@ void cpuSetAMDMSR(void)
- }
- AMD_Errata298();
-
-+ if (revision & AMD_FAM15_ALL) {
-+ uint32_t f5x80;
-+ uint8_t enabled;
-+ uint8_t compute_unit_count = 0;
-+ f5x80 = pci_read_config32(NODE_PCI(node_id, 5), 0x80);
-+ enabled = f5x80 & 0xf;
-+ if (enabled == 0x1)
-+ compute_unit_count = 1;
-+ if (enabled == 0x3)
-+ compute_unit_count = 2;
-+ if (enabled == 0x7)
-+ compute_unit_count = 3;
-+ if (enabled == 0xf)
-+ compute_unit_count = 4;
-+ msr = rdmsr(BU_CFG2);
-+ msr.lo &= ~(0x3 << 6); /* ThrottleNbInterface[1:0] */
-+ msr.lo |= (((compute_unit_count - 1) & 0x3) << 6);
-+ wrmsr(BU_CFG2, msr);
-+ }
-+
-+ /* Revision C0 and above */
-+ if (revision & AMD_OR_C0) {
-+ uint32_t f3x1fc = pci_read_config32(NODE_PCI(node_id, 3), 0x1fc);
-+ msr = rdmsr(FP_CFG);
-+ msr.hi &= ~(0x7 << (42-32)); /* DiDtCfg4 */
-+ msr.hi |= (((f3x1fc >> 17) & 0x7) << (42-32));
-+ msr.hi &= ~(0x1 << (41-32)); /* DiDtCfg5 */
-+ msr.hi |= (((f3x1fc >> 22) & 0x1) << (41-32));
-+ msr.hi &= ~(0x1 << (40-32)); /* DiDtCfg3 */
-+ msr.hi |= (((f3x1fc >> 16) & 0x1) << (40-32));
-+ msr.hi &= ~(0x7 << (32-32)); /* DiDtCfg1 (1) */
-+ msr.hi |= (((f3x1fc >> 11) & 0x7) << (32-32));
-+ msr.lo &= ~(0x1f << 27); /* DiDtCfg1 (2) */
-+ msr.lo |= (((f3x1fc >> 6) & 0x1f) << 27);
-+ msr.lo &= ~(0x3 << 25); /* DiDtCfg2 */
-+ msr.lo |= (((f3x1fc >> 14) & 0x3) << 25);
-+ msr.lo &= ~(0x1f << 18); /* DiDtCfg0 */
-+ msr.lo |= (((f3x1fc >> 1) & 0x1f) << 18);
-+ msr.lo &= ~(0x1 << 16); /* DiDtMode */
-+ msr.lo |= ((f3x1fc & 0x1) << 16);
-+ wrmsr(FP_CFG, msr);
-+ }
-+
- printk(BIOS_DEBUG, " done\n");
- }
-
-@@ -835,9 +947,10 @@ static void cpuSetAMDPCI(u8 node)
- * that it is run for the first core on each node
- */
- u8 i, j;
-- u32 revision, platform;
-+ u32 platform;
- u32 val;
- u8 offset;
-+ uint64_t revision;
-
- printk(BIOS_DEBUG, "cpuSetAMDPCI %02d", node);
-
-@@ -899,6 +1012,7 @@ static void cpuSetAMDPCI(u8 node)
- }
-
- #ifdef UNUSED_CODE
-+/* Clearing the MCA registers is apparently handled in the ramstage CPU Function 3 driver */
- static void cpuInitializeMCA(void)
- {
- /* Clears Machine Check Architecture (MCA) registers, which power on
-diff --git a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c
-index b942c1a..8a61f13 100644
---- a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c
-+++ b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c
-@@ -39,6 +39,23 @@
-
- #define MCI_STATUS 0x401
-
-+static inline uint8_t is_fam15h(void)
-+{
-+ uint8_t fam15h = 0;
-+ uint32_t family;
-+
-+ family = cpuid_eax(0x80000001);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-+
-+ return fam15h;
-+}
-+
-+static volatile uint8_t fam15h_startup_flags[MAX_NODES_SUPPORTED][MAX_CORES_SUPPORTED] = {{ 0 }};
-+
- static void model_10xxx_init(device_t dev)
- {
- u8 i;
-@@ -47,13 +64,44 @@ static void model_10xxx_init(device_t dev)
- #if CONFIG_LOGICAL_CPUS
- u32 siblings;
- #endif
-+ uint8_t delay_start;
-
- id = get_node_core_id(read_nb_cfg_54()); /* nb_cfg_54 can not be set */
- printk(BIOS_DEBUG, "nodeid = %02d, coreid = %02d\n", id.nodeid, id.coreid);
-
-+ if (is_fam15h())
-+ delay_start = !!(id.coreid & 0x1);
-+ else
-+ delay_start = 0;
-+
- /* Turn on caching if we haven't already */
- x86_enable_cache();
-- amd_setup_mtrrs();
-+
-+ if (!delay_start) {
-+ /* Initialize all variable MTRRs except the first pair.
-+ * This prevents Linux from having to correct an inconsistent
-+ * MTRR setup, which would crash Family 15h CPUs due to the
-+ * compute unit structure sharing MTRR MSRs between AP cores.
-+ */
-+ msr.hi = 0x00000000;
-+ msr.lo = 0x00000000;
-+
-+ disable_cache();
-+
-+ for (i = 0x2; i < 0x10; i++) {
-+ wrmsr(0x00000200 | i, msr);
-+ }
-+
-+ enable_cache();
-+
-+ /* Set up other MTRRs */
-+ amd_setup_mtrrs();
-+ } else {
-+ while (!fam15h_startup_flags[id.nodeid][id.coreid - 1]) {
-+ /* Wait for CU first core startup */
-+ }
-+ }
-+
- x86_mtrr_check();
-
- disable_cache();
-@@ -88,17 +136,24 @@ static void model_10xxx_init(device_t dev)
- printk(BIOS_DEBUG, "siblings = %02d, ", siblings);
- #endif
-
-- /* DisableCf8ExtCfg */
-+ /* Disable Cf8ExtCfg */
- msr = rdmsr(NB_CFG_MSR);
- msr.hi &= ~(1 << (46 - 32));
- wrmsr(NB_CFG_MSR, msr);
-
-- msr = rdmsr(BU_CFG2_MSR);
-- /* Clear ClLinesToNbDis */
-- msr.lo &= ~(1 << 15);
-- /* Clear bit 35 as per Erratum 343 */
-- msr.hi &= ~(1 << (35-32));
-- wrmsr(BU_CFG2_MSR, msr);
-+ if (is_fam15h()) {
-+ msr = rdmsr(BU_CFG3_MSR);
-+ /* Set CombineCr0Cd */
-+ msr.hi |= (1 << (49-32));
-+ wrmsr(BU_CFG3_MSR, msr);
-+ } else {
-+ msr = rdmsr(BU_CFG2_MSR);
-+ /* Clear ClLinesToNbDis */
-+ msr.lo &= ~(1 << 15);
-+ /* Clear bit 35 as per Erratum 343 */
-+ msr.hi &= ~(1 << (35-32));
-+ wrmsr(BU_CFG2_MSR, msr);
-+ }
-
- if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
- printk(BIOS_DEBUG, "Initializing SMM ASeg memory\n");
-@@ -131,6 +186,7 @@ static void model_10xxx_init(device_t dev)
- msr.lo |= (1 << 0);
- wrmsr(HWCR_MSR, msr);
-
-+ fam15h_startup_flags[id.nodeid][id.coreid] = 1;
- }
-
- static struct device_operations cpu_dev_ops = {
-@@ -147,15 +203,17 @@ static struct cpu_device_id cpu_table[] = {
- { X86_VENDOR_AMD, 0x100f22 },
- { X86_VENDOR_AMD, 0x100f23 },
- { X86_VENDOR_AMD, 0x100f40 }, /* RB-C0 */
-- { X86_VENDOR_AMD, 0x100F42 }, /* RB-C2 */
-- { X86_VENDOR_AMD, 0x100F43 }, /* RB-C3 */
-- { X86_VENDOR_AMD, 0x100F52 }, /* BL-C2 */
-- { X86_VENDOR_AMD, 0x100F62 }, /* DA-C2 */
-- { X86_VENDOR_AMD, 0x100F63 }, /* DA-C3 */
-- { X86_VENDOR_AMD, 0x100F80 }, /* HY-D0 */
-- { X86_VENDOR_AMD, 0x100F81 }, /* HY-D1 */
-- { X86_VENDOR_AMD, 0x100F91 }, /* HY-D1 */
-- { X86_VENDOR_AMD, 0x100FA0 }, /* PH-E0 */
-+ { X86_VENDOR_AMD, 0x100f42 }, /* RB-C2 */
-+ { X86_VENDOR_AMD, 0x100f43 }, /* RB-C3 */
-+ { X86_VENDOR_AMD, 0x100f52 }, /* BL-C2 */
-+ { X86_VENDOR_AMD, 0x100f62 }, /* DA-C2 */
-+ { X86_VENDOR_AMD, 0x100f63 }, /* DA-C3 */
-+ { X86_VENDOR_AMD, 0x100f80 }, /* HY-D0 */
-+ { X86_VENDOR_AMD, 0x100f81 }, /* HY-D1 */
-+ { X86_VENDOR_AMD, 0x100f91 }, /* HY-D1 */
-+ { X86_VENDOR_AMD, 0x100fa0 }, /* PH-E0 */
-+ { X86_VENDOR_AMD, 0x600f12 }, /* OR-B2 */
-+ { X86_VENDOR_AMD, 0x600f20 }, /* OR-C0 */
- { 0, 0 },
- };
-
-diff --git a/src/cpu/amd/family_10h-family_15h/powernow_acpi.c b/src/cpu/amd/family_10h-family_15h/powernow_acpi.c
-index 98ef08a..84e5514 100644
---- a/src/cpu/amd/family_10h-family_15h/powernow_acpi.c
-+++ b/src/cpu/amd/family_10h-family_15h/powernow_acpi.c
-@@ -74,8 +74,7 @@ static void write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u32 *pstate_p
- /* Revision C or greater single-link processor */
- cpuid1 = cpuid(0x80000008);
- acpigen_write_PSD_package(0, (cpuid1.ecx & 0xff) + 1, SW_ALL);
-- }
-- else {
-+ } else {
- /* Find the local APIC ID for the specified core ID */
- struct device* cpu;
- int cpu_index = 0;
-@@ -99,7 +98,9 @@ static void write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u32 *pstate_p
- }
-
- /*
--* For details of this algorithm, please refer to the BDKG 3.62 page 69
-+* For details of this algorithm, please refer to:
-+* Family 10h BDKG 3.62 page 69
-+* Family 15h BDKG 3.14 page 74
- *
- * WARNING: The core count algorithm below assumes that all processors
- * are identical, with the same number of active cores. While the BKDG
-@@ -149,6 +150,13 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
- uint8_t node_count;
- uint8_t cores_per_node;
- uint8_t total_core_count;
-+ uint8_t fam15h;
-+ uint8_t fam10h_rev_e = 0;
-+
-+ /* Detect Revision E processors via method used in fidvid.c */
-+ if ((cpuid_edx(0x80000007) & CPB_MASK)
-+ && ((cpuid_ecx(0x80000008) & NC_MASK) == 5))
-+ fam10h_rev_e = 1;
-
- /*
- * Based on the CPU socket type,cmp_cap and pwr_lmt , get the power limit.
-@@ -156,11 +164,17 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
- * cmp_cap : 0x0 SingleCore ; 0x1 DualCore ; 0x2 TripleCore ; 0x3 QuadCore ; 0x4 QuintupleCore ; 0x5 HexCore
- */
- printk(BIOS_INFO, "Pstates algorithm ...\n");
-+ fam15h = !!(mctGetLogicalCPUID(0) & AMD_FAM15_ALL);
- /* Get number of cores */
-- dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8);
-- cmp_cap = (dtemp & 0x3000) >> 12;
-- if (mctGetLogicalCPUID(0) & AMD_FAM10_REV_D) /* revision D */
-- cmp_cap |= (dtemp & 0x8000) >> 13;
-+ if (fam15h) {
-+ cmp_cap = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 5)), 0x84) & 0xff;
-+ } else {
-+ dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xe8);
-+ cmp_cap = (dtemp & 0x3000) >> 12;
-+ if (mctGetLogicalCPUID(0) & (AMD_FAM10_REV_D | AMD_FAM15_ALL)) /* revision D or higher */
-+ cmp_cap |= (dtemp & 0x8000) >> 13;
-+ }
-+
- /* Get number of nodes */
- dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 0)), 0x60);
- node_count = ((dtemp & 0x70) >> 4) + 1;
-@@ -169,6 +183,14 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
- /* Compute total number of cores installed in system */
- total_core_count = cores_per_node * node_count;
-
-+ /* Get number of boost states */
-+ uint8_t boost_count = 0;
-+ dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 4)), 0x15c);
-+ if (fam10h_rev_e)
-+ boost_count = (dtemp >> 2) & 0x1;
-+ else if (mctGetLogicalCPUID(0) & AMD_FAM15_ALL)
-+ boost_count = (dtemp >> 2) & 0x7;
-+
- Pstate_num = 0;
-
- /* See if the CPUID(0x80000007) returned EDX[7]==1b */
-@@ -205,7 +227,7 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
-
- /* Get PSmax's index */
- msr = rdmsr(0xC0010061);
-- Pstate_max = (uint8_t) ((msr.lo >> PS_MAX_VAL_SHFT) & BIT_MASK_3);
-+ Pstate_max = (uint8_t) ((msr.lo >> PS_MAX_VAL_SHFT) & ((fam15h)?BIT_MASK_7:BIT_MASK_3));
-
- /* Determine if all enabled Pstates have the same fidvid */
- uint8_t i;
-@@ -219,10 +241,14 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
- }
- }
-
-+ /* Family 15h uses slightly different PSmax numbering */
-+ if (fam15h)
-+ Pstate_max++;
-+
- /* Populate tables with all Pstate information */
- for (Pstate_num = 0; Pstate_num < Pstate_max; Pstate_num++) {
- /* Get power state information */
-- msr = rdmsr(0xC0010064 + Pstate_num);
-+ msr = rdmsr(0xC0010064 + Pstate_num + boost_count);
- cpufid = (msr.lo & 0x3f);
- cpudid = (msr.lo & 0x1c0) >> 6;
- cpuvid = (msr.lo & 0xfe00) >> 9;
-@@ -232,12 +258,10 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
- if (pviModeFlag) {
- if (cpuvid >= 0x20) {
- core_voltage = 7625 - (((cpuvid - 0x20) * 10000) / 80);
-- }
-- else {
-+ } else {
- core_voltage = 15500 - ((cpuvid * 10000) / 40);
- }
-- }
-- else {
-+ } else {
- cpuvid = cpuvid & 0x7f;
- if (cpuvid >= 0x7c)
- core_voltage = 0;
-diff --git a/src/cpu/amd/family_10h-family_15h/processor_name.c b/src/cpu/amd/family_10h-family_15h/processor_name.c
-index 12c45c9..fbd0452 100644
---- a/src/cpu/amd/family_10h-family_15h/processor_name.c
-+++ b/src/cpu/amd/family_10h-family_15h/processor_name.c
-@@ -33,6 +33,10 @@
- #include <cpu/amd/mtrr.h>
- #include <cpu/cpu.h>
- #include <cpu/amd/model_10xxx_rev.h>
-+#include <device/device.h>
-+#include <device/pci.h>
-+#include <device/pnp.h>
-+#include <device/pci_ops.h>
-
- /* The maximum length of CPU names is 48 bytes, including the final NULL byte.
- * If you change these names your BIOS will _NOT_ pass the AMD validation and
-@@ -212,104 +216,138 @@ static int strcpymax(char *dst, const char *src, int buflen)
- return i;
- }
-
-+#define NAME_STRING_MAXLEN 48
-
- int init_processor_name(void)
- {
-- /* variable names taken from fam10 revision guide for clarity */
-- u32 BrandId; /* CPUID Fn8000_0001_EBX */
-- u8 String1; /* BrandID[14:11] */
-- u8 String2; /* BrandID[3:0] */
-- u8 Model; /* BrandID[10:4] */
-- u8 Pg; /* BrandID[15] */
-- u8 PkgTyp; /* BrandID[31:28] */
-- u8 NC; /* CPUID Fn8000_0008_ECX */
-- const char *processor_name_string = unknown;
-- char program_string[48];
-- u32 *p_program_string = (u32 *)program_string;
- msr_t msr;
-- int i, j = 0, str2_checkNC = 1;
-- const struct str_s *str, *str2;
-+ ssize_t i;
-+ char program_string[NAME_STRING_MAXLEN];
-+ u32 *p_program_string = (u32 *)program_string;
-+ uint8_t fam15h = 0;
-+ uint32_t family;
-
-+ family = cpuid_eax(0x80000001);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-
-- /* Find out which CPU brand it is */
-- BrandId = cpuid_ebx(0x80000001);
-- String1 = (u8)((BrandId >> 11) & 0x0F);
-- String2 = (u8)((BrandId >> 0) & 0x0F);
-- Model = (u8)((BrandId >> 4) & 0x7F);
-- Pg = (u8)((BrandId >> 15) & 0x01);
-- PkgTyp = (u8)((BrandId >> 28) & 0x0F);
-- NC = (u8)(cpuid_ecx(0x80000008) & 0xFF);
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-
- /* null the string */
- memset(program_string, 0, sizeof(program_string));
-
-- if (!Model) {
-- processor_name_string = Pg ? thermal : sample;
-- goto done;
-- }
--
-- switch (PkgTyp) {
-- case 0: /* F1207 */
-- str = String1_socket_F;
-- str2 = String2_socket_F;
-- str2_checkNC = 0;
-- break;
-- case 1: /* AM2 */
-- str = String1_socket_AM2;
-- str2 = String2_socket_AM2;
-- break;
-- case 3: /* G34 */
-- str = String1_socket_G34;
-- str2 = String2_socket_G34;
-- str2_checkNC = 0;
-- break;
-- case 5: /* C32 */
-- str = String1_socket_C32;
-- str2 = String2_socket_C32;
-- break;
-- default:
-- goto done;
-- }
-+ if (fam15h) {
-+ /* Family 15h or later */
-+ uint32_t dword;
-+ device_t cpu_fn5_dev = dev_find_slot(0, PCI_DEVFN(0x18, 5));
-+ pci_write_config32(cpu_fn5_dev, 0x194, 0);
-+ dword = pci_read_config32(cpu_fn5_dev, 0x198);
-+ if (dword == 0) {
-+ strcpymax(program_string, sample, sizeof(program_string));
-+ } else {
-+ /* Assemble the string from PCI configuration register contents */
-+ for (i = 0; i < 12; i++) {
-+ pci_write_config32(cpu_fn5_dev, 0x194, i);
-+ p_program_string[i] = pci_read_config32(cpu_fn5_dev, 0x198);
-+ }
-+
-+ /* Correctly place the null terminator */
-+ for (i = (NAME_STRING_MAXLEN - 2); i > 0; i--) {
-+ if (program_string[i] != 0x20)
-+ break;
-+ }
-+ program_string[i + 1] = 0;
-+ }
-+ } else {
-+ /* variable names taken from fam10 revision guide for clarity */
-+ u32 BrandId; /* CPUID Fn8000_0001_EBX */
-+ u8 String1; /* BrandID[14:11] */
-+ u8 String2; /* BrandID[3:0] */
-+ u8 Model; /* BrandID[10:4] */
-+ u8 Pg; /* BrandID[15] */
-+ u8 PkgTyp; /* BrandID[31:28] */
-+ u8 NC; /* CPUID Fn8000_0008_ECX */
-+ const char *processor_name_string = unknown;
-+ int j = 0, str2_checkNC = 1;
-+ const struct str_s *str, *str2;
-+
-+ /* Find out which CPU brand it is */
-+ BrandId = cpuid_ebx(0x80000001);
-+ String1 = (u8)((BrandId >> 11) & 0x0F);
-+ String2 = (u8)((BrandId >> 0) & 0x0F);
-+ Model = (u8)((BrandId >> 4) & 0x7F);
-+ Pg = (u8)((BrandId >> 15) & 0x01);
-+ PkgTyp = (u8)((BrandId >> 28) & 0x0F);
-+ NC = (u8)(cpuid_ecx(0x80000008) & 0xFF);
-+
-+ if (!Model) {
-+ processor_name_string = Pg ? thermal : sample;
-+ goto done;
-+ }
-
-- /* String1 */
-- for (i = 0; str[i].value; i++) {
-- if ((str[i].Pg == Pg) &&
-- (str[i].NC == NC) &&
-- (str[i].String == String1)) {
-- processor_name_string = str[i].value;
-+ switch (PkgTyp) {
-+ case 0: /* F1207 */
-+ str = String1_socket_F;
-+ str2 = String2_socket_F;
-+ str2_checkNC = 0;
-+ break;
-+ case 1: /* AM2 */
-+ str = String1_socket_AM2;
-+ str2 = String2_socket_AM2;
-+ break;
-+ case 3: /* G34 */
-+ str = String1_socket_G34;
-+ str2 = String2_socket_G34;
-+ str2_checkNC = 0;
-+ break;
-+ case 5: /* C32 */
-+ str = String1_socket_C32;
-+ str2 = String2_socket_C32;
- break;
-+ default:
-+ goto done;
- }
-- }
-
-- if (!str[i].value)
-- goto done;
-+ /* String1 */
-+ for (i = 0; str[i].value; i++) {
-+ if ((str[i].Pg == Pg) &&
-+ (str[i].NC == NC) &&
-+ (str[i].String == String1)) {
-+ processor_name_string = str[i].value;
-+ break;
-+ }
-+ }
-
-- j = strcpymax(program_string, processor_name_string,
-- sizeof(program_string));
-+ if (!str[i].value)
-+ goto done;
-
-- /* Translate Model from 01-99 to ASCII and put it on the end.
-- * Numbers less than 10 should include a leading zero, e.g., 09.*/
-- if (Model < 100 && j < sizeof(program_string) - 2) {
-- program_string[j++] = (Model / 10) + '0';
-- program_string[j++] = (Model % 10) + '0';
-- }
-+ j = strcpymax(program_string, processor_name_string,
-+ sizeof(program_string));
-
-- processor_name_string = unknown2;
--
-- /* String 2 */
-- for(i = 0; str2[i].value; i++) {
-- if ((str2[i].Pg == Pg) &&
-- ((str2[i].NC == NC) || !str2_checkNC) &&
-- (str2[i].String == String2)) {
-- processor_name_string = str2[i].value;
-- break;
-+ /* Translate Model from 01-99 to ASCII and put it on the end.
-+ * Numbers less than 10 should include a leading zero, e.g., 09.*/
-+ if (Model < 100 && j < sizeof(program_string) - 2) {
-+ program_string[j++] = (Model / 10) + '0';
-+ program_string[j++] = (Model % 10) + '0';
- }
-- }
-
-+ processor_name_string = unknown2;
-+
-+ /* String 2 */
-+ for(i = 0; str2[i].value; i++) {
-+ if ((str2[i].Pg == Pg) &&
-+ ((str2[i].NC == NC) || !str2_checkNC) &&
-+ (str2[i].String == String2)) {
-+ processor_name_string = str2[i].value;
-+ break;
-+ }
-+ }
-
--done:
-- strcpymax(&program_string[j], processor_name_string,
-- sizeof(program_string) - j);
-+ done:
-+ strcpymax(&program_string[j], processor_name_string,
-+ sizeof(program_string) - j);
-+ }
-
- printk(BIOS_DEBUG, "CPU model: %s\n", program_string);
-
-diff --git a/src/cpu/amd/family_10h-family_15h/update_microcode.c b/src/cpu/amd/family_10h-family_15h/update_microcode.c
-index 51aca35..3b2f5dd 100644
---- a/src/cpu/amd/family_10h-family_15h/update_microcode.c
-+++ b/src/cpu/amd/family_10h-family_15h/update_microcode.c
-@@ -28,6 +28,7 @@ struct id_mapping {
-
- static u16 get_equivalent_processor_rev_id(u32 orig_id) {
- static const struct id_mapping id_mapping_table[] = {
-+ /* Family 10h */
- { 0x100f00, 0x1000 },
- { 0x100f01, 0x1000 },
- { 0x100f02, 0x1000 },
-@@ -42,8 +43,13 @@ static u16 get_equivalent_processor_rev_id(u32 orig_id) {
- { 0x100f62, 0x1062 }, /* DA-C2 */
- { 0x100f63, 0x1043 }, /* DA-C3 */
- { 0x100f81, 0x1081 }, /* HY-D1 */
-+ { 0x100f91, 0x1081 }, /* HY-D1 */
- { 0x100fa0, 0x10A0 }, /* PH-E0 */
-
-+ /* Family 15h */
-+ { 0x600f12, 0x6012 }, /* OR-B2 */
-+ { 0x600f20, 0x6020 }, /* OR-C0 */
-+
- /* Array terminator */
- { 0xffffff, 0x0000 },
- };
-diff --git a/src/cpu/amd/model_fxx/init_cpus.c b/src/cpu/amd/model_fxx/init_cpus.c
-index 12d3a95..3960c03 100644
---- a/src/cpu/amd/model_fxx/init_cpus.c
-+++ b/src/cpu/amd/model_fxx/init_cpus.c
-@@ -190,7 +190,7 @@ void allow_all_aps_stop(u32 bsp_apicid)
-
- static void STOP_CAR_AND_CPU(void)
- {
-- disable_cache_as_ram(); // inline
-+ disable_cache_as_ram(0); // inline
- /* stop all cores except node0/core0 the bsp .... */
- stop_this_cpu();
- }
-diff --git a/src/cpu/amd/quadcore/quadcore.c b/src/cpu/amd/quadcore/quadcore.c
-index 9c21e94..8a9b5ed 100644
---- a/src/cpu/amd/quadcore/quadcore.c
-+++ b/src/cpu/amd/quadcore/quadcore.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -26,16 +27,41 @@
-
- #include "cpu/amd/quadcore/quadcore_id.c"
-
-+/* get_boot_apic_id and wait_cpu_state located in init_cpus.c */
-+uint32_t get_boot_apic_id(uint8_t node, uint32_t core);
-+uint32_t wait_cpu_state(uint32_t apicid, uint32_t state, uint32_t state2);
-+
-+static inline uint8_t is_fam15h(void)
-+{
-+ uint8_t fam15h = 0;
-+ uint32_t family;
-+
-+ family = cpuid_eax(0x80000001);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-+
-+ return fam15h;
-+}
-+
- static u32 get_core_num_in_bsp(u32 nodeid)
- {
- u32 dword;
-- dword = pci_read_config32(NODE_PCI(nodeid, 3), 0xe8);
-- dword >>= 12;
-- /* Bit 15 is CmpCap[2] since Revision D. */
-- if ((cpuid_ecx(0x80000008) & 0xff) > 3)
-- dword = ((dword & 8) >> 1) | (dword & 3);
-- else
-- dword &= 3;
-+ if (is_fam15h()) {
-+ /* Family 15h moved CmpCap to F5x84 [7:0] */
-+ dword = pci_read_config32(NODE_PCI(nodeid, 5), 0x84);
-+ dword &= 0xff;
-+ } else {
-+ dword = pci_read_config32(NODE_PCI(nodeid, 3), 0xe8);
-+ dword >>= 12;
-+ /* Bit 15 is CmpCap[2] since Revision D. */
-+ if ((cpuid_ecx(0x80000008) & 0xff) > 3)
-+ dword = ((dword & 8) >> 1) | (dword & 3);
-+ else
-+ dword &= 3;
-+ }
- return dword;
- }
-
-@@ -50,28 +76,68 @@ static u8 set_apicid_cpuid_lo(void)
- return 1;
- }
-
--static void real_start_other_core(u32 nodeid, u32 cores)
-+static void real_start_other_core(uint32_t nodeid, uint32_t cores)
- {
-- u32 dword, i;
-+ ssize_t i;
-+ uint32_t dword;
-
- printk(BIOS_DEBUG, "Start other core - nodeid: %02x cores: %02x\n", nodeid, cores);
-
- /* set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4
- accesses and error logging to core0 */
- dword = pci_read_config32(NODE_PCI(nodeid, 3), 0x44);
-- dword |= 1 << 27; // NbMcaToMstCpuEn bit
-+ dword |= 1 << 30; /* SyncFloodOnDramAdrParErr=1 */
-+ dword |= 1 << 27; /* NbMcaToMstCpuEn=1 */
-+ dword |= 1 << 21; /* SyncFloodOnAnyUcErr=1 */
-+ dword |= 1 << 20; /* SyncFloodOnWDT=1 */
-+ dword |= 1 << 2; /* SyncFloodOnDramUcEcc=1 */
- pci_write_config32(NODE_PCI(nodeid, 3), 0x44, dword);
-- // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
-- dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x68);
-- dword |= 1 << 5;
-- pci_write_config32(NODE_PCI(nodeid, 0), 0x68, dword);
--
-- if(cores > 1) {
-- dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x168);
-- for (i = 0; i < cores - 1; i++) {
-- dword |= 1 << i;
-+ if (is_fam15h()) {
-+ uint32_t core_activation_flags = 0;
-+ uint32_t active_cores = 0;
-+
-+ /* Set PCI_DEV(0, 0x18+nodeid, 0), 0x1dc bits 7:1 to start cores */
-+ dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x1dc);
-+ for (i = 1; i < cores + 1; i++) {
-+ core_activation_flags |= 1 << i;
-+ }
-+
-+ /* Start the first core of each compute unit */
-+ active_cores |= core_activation_flags & 0x55;
-+ pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword | active_cores);
-+
-+ /* Each core shares a single set of MTRR registers with
-+ * another core in the same compute unit, therefore, it
-+ * is important that one core in each CU starts in advance
-+ * of the other in order to avoid one core stomping all over
-+ * the other core's settings.
-+ */
-+
-+ /* Wait for the first core of each compute unit to start... */
-+ uint32_t timeout;
-+ for (i = 1; i < cores + 1; i++) {
-+ if (!(i & 0x1)) {
-+ uint32_t ap_apicid = get_boot_apic_id(nodeid, i);
-+ timeout = wait_cpu_state(ap_apicid, F10_APSTATE_ASLEEP, F10_APSTATE_ASLEEP);
-+ }
-+ }
-+
-+ /* Start the second core of each compute unit */
-+ active_cores |= core_activation_flags & 0xaa;
-+ pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword | active_cores);
-+ } else {
-+ // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
-+ dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x68);
-+ dword |= 1 << 5;
-+ pci_write_config32(NODE_PCI(nodeid, 0), 0x68, dword);
-+
-+ if (cores > 1) {
-+ dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x168);
-+ for (i = 0; i < cores - 1; i++) {
-+ dword |= 1 << i;
-+ }
-+ pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword);
- }
-- pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword);
- }
- }
-
-@@ -91,10 +157,9 @@ static void start_other_cores(void)
-
- for (nodeid = 0; nodeid < nodes; nodeid++) {
- u32 cores = get_core_num_in_bsp(nodeid);
-- printk(BIOS_DEBUG, "init node: %02x cores: %02x \n", nodeid, cores);
-+ printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1 \n", nodeid, cores);
- if (cores > 0) {
- real_start_other_core(nodeid, cores);
- }
- }
--
- }
-diff --git a/src/cpu/amd/quadcore/quadcore_id.c b/src/cpu/amd/quadcore/quadcore_id.c
-index c5921de..c0537b3 100644
---- a/src/cpu/amd/quadcore/quadcore_id.c
-+++ b/src/cpu/amd/quadcore/quadcore_id.c
-@@ -43,9 +43,12 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
- {
- struct node_core_id id;
- uint8_t apicid;
-+ uint8_t fam15h = 0;
- uint8_t rev_gte_d = 0;
- uint8_t dual_node = 0;
- uint32_t f3xe8;
-+ uint32_t family;
-+ uint32_t model;
-
- #ifdef __PRE_RAM__
- f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
-@@ -53,7 +56,17 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
- f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
- #endif
-
-- if (cpuid_eax(0x80000001) >= 0x8)
-+ family = model = cpuid_eax(0x80000001);
-+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f) {
-+ /* Family 15h or later */
-+ fam15h = 1;
-+ nb_cfg_54 = 1;
-+ }
-+
-+ if ((model >= 0x8) || fam15h)
- /* Revision D or later */
- rev_gte_d = 1;
-
-@@ -67,7 +80,13 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
- */
- apicid = (cpuid_ebx(1) >> 24) & 0xff;
- if( nb_cfg_54) {
-- if (rev_gte_d && dual_node) {
-+ if (fam15h && dual_node) {
-+ id.coreid = apicid & 0x1f;
-+ id.nodeid = (apicid & 0x60) >> 5;
-+ } else if (fam15h && !dual_node) {
-+ id.coreid = apicid & 0xf;
-+ id.nodeid = (apicid & 0x70) >> 4;
-+ } else if (rev_gte_d && dual_node) {
- id.coreid = apicid & 0xf;
- id.nodeid = (apicid & 0x30) >> 4;
- } else if (rev_gte_d && !dual_node) {
-@@ -90,7 +109,25 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
- }
- }
-
-- if (rev_gte_d && dual_node) {
-+ if (fam15h && dual_node) {
-+ /* Coreboot expects each separate processor die to be on a different nodeid.
-+ * Since the code above returns nodeid 0 even on internal node 1 some fixup is needed...
-+ */
-+ uint32_t f5x84;
-+ uint8_t core_count;
-+
-+#ifdef __PRE_RAM__
-+ f5x84 = pci_read_config32(NODE_PCI(0, 5), 0x84);
-+#else
-+ f5x84 = pci_read_config32(get_node_pci(0, 5), 0x84);
-+#endif
-+ core_count = (f5x84 & 0xff) + 1;
-+ id.nodeid = id.nodeid * 2;
-+ if (id.coreid >= core_count) {
-+ id.nodeid += 1;
-+ id.coreid = id.coreid - core_count;
-+ }
-+ } else if (rev_gte_d && dual_node) {
- /* Coreboot expects each separate processor die to be on a different nodeid.
- * Since the code above returns nodeid 0 even on internal node 1 some fixup is needed...
- */
-diff --git a/src/include/cpu/amd/model_10xxx_msr.h b/src/include/cpu/amd/model_10xxx_msr.h
-index 6c7dece..7d78e2d 100644
---- a/src/include/cpu/amd/model_10xxx_msr.h
-+++ b/src/include/cpu/amd/model_10xxx_msr.h
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -32,7 +33,13 @@
- #define IC_CFG_MSR 0xC0011021
- #define DC_CFG_MSR 0xC0011022
- #define BU_CFG_MSR 0xC0011023
-+#define FP_CFG_MSR 0xC0011028
-+#define DE_CFG_MSR 0xC0011029
- #define BU_CFG2_MSR 0xC001102A
-+#define BU_CFG3_MSR 0xC001102B
-+#define EX_CFG_MSR 0xC001102C
-+#define LS_CFG2_MSR 0xC001102D
-+#define IBS_OP_DATA3_MSR 0xC0011037
-
- #define CPU_ID_FEATURES_MSR 0xC0011004
- #define CPU_ID_HYPER_EXT_FEATURES 0xC001100d
-diff --git a/src/mainboard/advansus/a785e-i/romstage.c b/src/mainboard/advansus/a785e-i/romstage.c
-index 4c2b38a..ab717fd 100644
---- a/src/mainboard/advansus/a785e-i/romstage.c
-+++ b/src/mainboard/advansus/a785e-i/romstage.c
-@@ -131,7 +131,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/amd/bimini_fam10/romstage.c b/src/mainboard/amd/bimini_fam10/romstage.c
-index e2bd351..5e2cf82 100644
---- a/src/mainboard/amd/bimini_fam10/romstage.c
-+++ b/src/mainboard/amd/bimini_fam10/romstage.c
-@@ -123,7 +123,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/amd/mahogany_fam10/romstage.c b/src/mainboard/amd/mahogany_fam10/romstage.c
-index 74bc9d5..025a8bb 100644
---- a/src/mainboard/amd/mahogany_fam10/romstage.c
-+++ b/src/mainboard/amd/mahogany_fam10/romstage.c
-@@ -125,7 +125,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/amd/serengeti_cheetah_fam10/romstage.c b/src/mainboard/amd/serengeti_cheetah_fam10/romstage.c
-index 20d46e6..5063439 100644
---- a/src/mainboard/amd/serengeti_cheetah_fam10/romstage.c
-+++ b/src/mainboard/amd/serengeti_cheetah_fam10/romstage.c
-@@ -231,7 +231,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/amd/tilapia_fam10/romstage.c b/src/mainboard/amd/tilapia_fam10/romstage.c
-index 89100b1..e37bc08 100644
---- a/src/mainboard/amd/tilapia_fam10/romstage.c
-+++ b/src/mainboard/amd/tilapia_fam10/romstage.c
-@@ -125,7 +125,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/asus/kfsn4-dre/romstage.c b/src/mainboard/asus/kfsn4-dre/romstage.c
-index 5d1f5a6..dd5c7dc 100644
---- a/src/mainboard/asus/kfsn4-dre/romstage.c
-+++ b/src/mainboard/asus/kfsn4-dre/romstage.c
-@@ -245,7 +245,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/asus/kgpe-d16/romstage.c b/src/mainboard/asus/kgpe-d16/romstage.c
-index a3f3310..a58fd0f 100644
---- a/src/mainboard/asus/kgpe-d16/romstage.c
-+++ b/src/mainboard/asus/kgpe-d16/romstage.c
-@@ -354,7 +354,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-@@ -512,4 +512,4 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
- BOOL AMD_CB_ManualBUIDSwapList (u8 node, u8 link, const u8 **List)
- {
- return 0;
--}
-\ No newline at end of file
-+}
-diff --git a/src/mainboard/asus/m4a78-em/romstage.c b/src/mainboard/asus/m4a78-em/romstage.c
-index 82f30d9..82b96bf 100644
---- a/src/mainboard/asus/m4a78-em/romstage.c
-+++ b/src/mainboard/asus/m4a78-em/romstage.c
-@@ -127,7 +127,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/asus/m4a785-m/romstage.c b/src/mainboard/asus/m4a785-m/romstage.c
-index 780bf81..30975fa 100644
---- a/src/mainboard/asus/m4a785-m/romstage.c
-+++ b/src/mainboard/asus/m4a785-m/romstage.c
-@@ -127,7 +127,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/asus/m5a88-v/romstage.c b/src/mainboard/asus/m5a88-v/romstage.c
-index 38761a6..4edaba2 100644
---- a/src/mainboard/asus/m5a88-v/romstage.c
-+++ b/src/mainboard/asus/m5a88-v/romstage.c
-@@ -128,7 +128,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/avalue/eax-785e/romstage.c b/src/mainboard/avalue/eax-785e/romstage.c
-index 764a5c6..447012b 100644
---- a/src/mainboard/avalue/eax-785e/romstage.c
-+++ b/src/mainboard/avalue/eax-785e/romstage.c
-@@ -132,7 +132,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/gigabyte/ma785gm/romstage.c b/src/mainboard/gigabyte/ma785gm/romstage.c
-index db4e449..444e59d 100644
---- a/src/mainboard/gigabyte/ma785gm/romstage.c
-+++ b/src/mainboard/gigabyte/ma785gm/romstage.c
-@@ -122,7 +122,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/gigabyte/ma785gmt/romstage.c b/src/mainboard/gigabyte/ma785gmt/romstage.c
-index 4ce7c58..705d7c5 100644
---- a/src/mainboard/gigabyte/ma785gmt/romstage.c
-+++ b/src/mainboard/gigabyte/ma785gmt/romstage.c
-@@ -122,7 +122,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/gigabyte/ma78gm/romstage.c b/src/mainboard/gigabyte/ma78gm/romstage.c
-index d2a0b95..5d21801 100644
---- a/src/mainboard/gigabyte/ma78gm/romstage.c
-+++ b/src/mainboard/gigabyte/ma78gm/romstage.c
-@@ -125,7 +125,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/hp/dl165_g6_fam10/romstage.c b/src/mainboard/hp/dl165_g6_fam10/romstage.c
-index 97e60d5..26c0bb9 100644
---- a/src/mainboard/hp/dl165_g6_fam10/romstage.c
-+++ b/src/mainboard/hp/dl165_g6_fam10/romstage.c
-@@ -137,7 +137,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/iei/kino-780am2-fam10/romstage.c b/src/mainboard/iei/kino-780am2-fam10/romstage.c
-index edbae3a..321eea6 100644
---- a/src/mainboard/iei/kino-780am2-fam10/romstage.c
-+++ b/src/mainboard/iei/kino-780am2-fam10/romstage.c
-@@ -125,7 +125,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/jetway/pa78vm5/romstage.c b/src/mainboard/jetway/pa78vm5/romstage.c
-index 16bb089..93dd2ce 100644
---- a/src/mainboard/jetway/pa78vm5/romstage.c
-+++ b/src/mainboard/jetway/pa78vm5/romstage.c
-@@ -130,7 +130,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/msi/ms9652_fam10/romstage.c b/src/mainboard/msi/ms9652_fam10/romstage.c
-index 4ea3306..5da971f 100644
---- a/src/mainboard/msi/ms9652_fam10/romstage.c
-+++ b/src/mainboard/msi/ms9652_fam10/romstage.c
-@@ -150,7 +150,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/supermicro/h8dmr_fam10/romstage.c b/src/mainboard/supermicro/h8dmr_fam10/romstage.c
-index c224dbc..1425546 100644
---- a/src/mainboard/supermicro/h8dmr_fam10/romstage.c
-+++ b/src/mainboard/supermicro/h8dmr_fam10/romstage.c
-@@ -146,7 +146,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/supermicro/h8qme_fam10/romstage.c b/src/mainboard/supermicro/h8qme_fam10/romstage.c
-index 0f9445b..4721eba 100644
---- a/src/mainboard/supermicro/h8qme_fam10/romstage.c
-+++ b/src/mainboard/supermicro/h8qme_fam10/romstage.c
-@@ -214,7 +214,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/mainboard/supermicro/h8scm_fam10/romstage.c b/src/mainboard/supermicro/h8scm_fam10/romstage.c
-index 4ea14fe..858aca0 100644
---- a/src/mainboard/supermicro/h8scm_fam10/romstage.c
-+++ b/src/mainboard/supermicro/h8scm_fam10/romstage.c
-@@ -136,7 +136,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- /* TODO: The Kernel must support 12 processor, otherwise the interrupt
-diff --git a/src/mainboard/tyan/s2912_fam10/romstage.c b/src/mainboard/tyan/s2912_fam10/romstage.c
-index 0030619..cdf51b1 100644
---- a/src/mainboard/tyan/s2912_fam10/romstage.c
-+++ b/src/mainboard/tyan/s2912_fam10/romstage.c
-@@ -149,7 +149,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
-
- post_code(0x33);
-
-- cpuSetAMDMSR();
-+ cpuSetAMDMSR(0);
- post_code(0x34);
-
- amd_ht_init(sysinfo);
-diff --git a/src/northbridge/amd/amdfam10/Kconfig b/src/northbridge/amd/amdfam10/Kconfig
-index ada5b9f..cb0d109 100644
---- a/src/northbridge/amd/amdfam10/Kconfig
-+++ b/src/northbridge/amd/amdfam10/Kconfig
-@@ -96,7 +96,7 @@ endif
- if HAVE_ACPI_RESUME
- config S3_DATA_SIZE
- int
-- default 16384
-+ default 32768
- endif
-
- if DIMM_DDR2
-diff --git a/src/northbridge/amd/amdfam10/Makefile.inc b/src/northbridge/amd/amdfam10/Makefile.inc
-index b4097b4..4098dce 100644
---- a/src/northbridge/amd/amdfam10/Makefile.inc
-+++ b/src/northbridge/amd/amdfam10/Makefile.inc
-@@ -2,6 +2,8 @@ ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y)
-
- ramstage-y += northbridge.c
- ramstage-y += misc_control.c
-+ramstage-y += link_control.c
-+ramstage-y += nb_control.c
- romstage-y += amdfam10_util.c
- ramstage-y += amdfam10_util.c
-
-diff --git a/src/northbridge/amd/amdfam10/amdfam10.h b/src/northbridge/amd/amdfam10/amdfam10.h
-index a1e08a0..b724394 100644
---- a/src/northbridge/amd/amdfam10/amdfam10.h
-+++ b/src/northbridge/amd/amdfam10/amdfam10.h
-@@ -962,9 +962,12 @@ that are corresponding to 0x01, 0x02, 0x03, 0x05, 0x06, 0x07
-
- #define LAPIC_MSG_REG 0x380
- #define F10_APSTATE_STARTED 0x13 // start of AP execution
--#define F10_APSTATE_STOPPED 0x14 // allow AP to stop
-+#define F10_APSTATE_ASLEEP 0x14 // AP sleeping
-+#define F10_APSTATE_STOPPED 0x15 // allow AP to stop
- #define F10_APSTATE_RESET 0x01 // waiting for warm reset
-
-+#define MAX_CORES_SUPPORTED 128
-+
- #include "nums.h"
-
- #ifdef __PRE_RAM__
-@@ -1038,7 +1041,6 @@ struct sys_info {
-
- struct MCTStatStruc MCTstat;
- struct DCTStatStruc DCTstatA[NODE_NUMS];
--
- } __attribute__((packed));
-
- #ifdef __PRE_RAM__
-diff --git a/src/northbridge/amd/amdfam10/amdfam10_util.c b/src/northbridge/amd/amdfam10/amdfam10_util.c
-index 423bb73..a4045bdf 100644
---- a/src/northbridge/amd/amdfam10/amdfam10_util.c
-+++ b/src/northbridge/amd/amdfam10/amdfam10_util.c
-@@ -34,14 +34,14 @@ u32 Get_NB32(u32 dev, u32 reg)
- }
- #endif
-
--u32 mctGetLogicalCPUID(u32 Node)
-+uint64_t mctGetLogicalCPUID(u32 Node)
- {
- /* Converts the CPUID to a logical ID MASK that is used to check
- CPU version support versions */
- u32 dev;
- u32 val, valx;
- u32 family, model, stepping;
-- u32 ret;
-+ uint64_t ret;
-
- if (Node == 0xFF) { /* current node */
- val = cpuid_eax(0x80000001);
-@@ -100,9 +100,16 @@ u32 mctGetLogicalCPUID(u32 Node)
- case 0x100a0:
- ret = AMD_PH_E0;
- break;
-+ case 0x15012:
-+ case 0x1501f:
-+ ret = AMD_OR_B2;
-+ break;
-+ case 0x15020:
-+ ret = AMD_OR_C0;
-+ break;
- default:
- /* FIXME: mabe we should die() here. */
-- printk(BIOS_ERR, "FIXME! CPU Version unknown or not supported! \n");
-+ printk(BIOS_ERR, "FIXME! CPU Version unknown or not supported! %08x\n", valx);
- ret = 0;
- }
-
-diff --git a/src/northbridge/amd/amdfam10/link_control.c b/src/northbridge/amd/amdfam10/link_control.c
-new file mode 100644
-index 0000000..1091ef4
---- /dev/null
-+++ b/src/northbridge/amd/amdfam10/link_control.c
-@@ -0,0 +1,86 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/* Configure various power control registers, including processor
-+ * boost support.
-+ */
-+
-+#include <console/console.h>
-+#include <device/device.h>
-+#include <device/pci.h>
-+#include <device/pci_ids.h>
-+#include <device/pci_ops.h>
-+#include <pc80/mc146818rtc.h>
-+#include <lib.h>
-+#include <cpu/amd/model_10xxx_rev.h>
-+
-+#include "amdfam10.h"
-+
-+static inline uint8_t is_fam15h(void)
-+{
-+ uint8_t fam15h = 0;
-+ uint32_t family;
-+
-+ family = cpuid_eax(0x80000001);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-+
-+ return fam15h;
-+}
-+
-+static void nb_control_init(struct device *dev)
-+{
-+ uint32_t dword;
-+
-+ printk(BIOS_DEBUG, "NB: Function 4 Link Control.. ");
-+
-+ if (is_fam15h()) {
-+ /* Enable APM */
-+ dword = pci_read_config32(dev, 0x15c);
-+ dword |= (0x1 << 7); /* ApmMasterEn = 1 */
-+ pci_write_config32(dev, 0x15c, dword);
-+ }
-+
-+ printk(BIOS_DEBUG, "done.\n");
-+}
-+
-+
-+static struct device_operations mcf4_ops = {
-+ .read_resources = pci_dev_read_resources,
-+ .set_resources = pci_dev_set_resources,
-+ .enable_resources = pci_dev_enable_resources,
-+ .init = nb_control_init,
-+ .scan_bus = 0,
-+ .ops_pci = 0,
-+};
-+
-+static const struct pci_driver mcf4_driver_fam10 __pci_driver = {
-+ .ops = &mcf4_ops,
-+ .vendor = PCI_VENDOR_ID_AMD,
-+ .device = 0x1204,
-+};
-+
-+static const struct pci_driver mcf4_driver_fam15 __pci_driver = {
-+ .ops = &mcf4_ops,
-+ .vendor = PCI_VENDOR_ID_AMD,
-+ .device = 0x1604,
-+};
-\ No newline at end of file
-diff --git a/src/northbridge/amd/amdfam10/misc_control.c b/src/northbridge/amd/amdfam10/misc_control.c
-index 90a4db1..8777e8f 100644
---- a/src/northbridge/amd/amdfam10/misc_control.c
-+++ b/src/northbridge/amd/amdfam10/misc_control.c
-@@ -4,6 +4,7 @@
- * Copyright (C) 2003 by Eric Biederman
- * Copyright (C) Stefan Reinauer
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -152,3 +153,9 @@ static const struct pci_driver mcf3_driver __pci_driver = {
- .vendor = PCI_VENDOR_ID_AMD,
- .device = 0x1203,
- };
-+
-+static const struct pci_driver mcf3_driver_fam15 __pci_driver = {
-+ .ops = &mcf3_ops,
-+ .vendor = PCI_VENDOR_ID_AMD,
-+ .device = 0x1603,
-+};
-diff --git a/src/northbridge/amd/amdfam10/nb_control.c b/src/northbridge/amd/amdfam10/nb_control.c
-new file mode 100644
-index 0000000..f95b6f8
---- /dev/null
-+++ b/src/northbridge/amd/amdfam10/nb_control.c
-@@ -0,0 +1,85 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/* Configure various power control registers, including processor boost
-+ * and TDP monitoring support.
-+ */
-+
-+#include <console/console.h>
-+#include <device/device.h>
-+#include <device/pci.h>
-+#include <device/pci_ids.h>
-+#include <device/pci_ops.h>
-+#include <pc80/mc146818rtc.h>
-+#include <lib.h>
-+#include <cpu/amd/model_10xxx_rev.h>
-+
-+#include "amdfam10.h"
-+
-+static void nb_control_init(struct device *dev)
-+{
-+ uint32_t dword;
-+ uint32_t f5x80;
-+ uint8_t cu_enabled;
-+ uint8_t compute_unit_count = 0;
-+
-+ printk(BIOS_DEBUG, "NB: Function 5 Northbridge Control.. ");
-+
-+ /* Determine the number of active compute units on this node */
-+ f5x80 = pci_read_config32(dev, 0x80);
-+ cu_enabled = f5x80 & 0xf;
-+ if (cu_enabled == 0x1)
-+ compute_unit_count = 1;
-+ if (cu_enabled == 0x3)
-+ compute_unit_count = 2;
-+ if (cu_enabled == 0x7)
-+ compute_unit_count = 3;
-+ if (cu_enabled == 0xf)
-+ compute_unit_count = 4;
-+
-+ /* Configure Processor TDP Running Average */
-+ dword = pci_read_config32(dev, 0xe0);
-+ dword &= ~0xf; /* RunAvgRange = 0x9 */
-+ dword |= 0x9;
-+ pci_write_config32(dev, 0xe0, dword);
-+
-+ /* Configure northbridge P-states */
-+ dword = pci_read_config32(dev, 0xe0);
-+ dword &= ~(0x7 << 9); /* NbPstateThreshold = compute_unit_count */
-+ dword |= (compute_unit_count & 0x7) << 9;
-+ pci_write_config32(dev, 0xe0, dword);
-+
-+ printk(BIOS_DEBUG, "done.\n");
-+}
-+
-+
-+static struct device_operations mcf5_ops = {
-+ .read_resources = pci_dev_read_resources,
-+ .set_resources = pci_dev_set_resources,
-+ .enable_resources = pci_dev_enable_resources,
-+ .init = nb_control_init,
-+ .scan_bus = 0,
-+ .ops_pci = 0,
-+};
-+
-+static const struct pci_driver mcf5_driver_fam15 __pci_driver = {
-+ .ops = &mcf5_ops,
-+ .vendor = PCI_VENDOR_ID_AMD,
-+ .device = 0x1605,
-+};
-\ No newline at end of file
-diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c
-index fb3b2f7..fcf85a7 100644
---- a/src/northbridge/amd/amdfam10/northbridge.c
-+++ b/src/northbridge/amd/amdfam10/northbridge.c
-@@ -81,6 +81,21 @@ device_t get_node_pci(u32 nodeid, u32 fn)
- #endif
- }
-
-+static inline uint8_t is_fam15h(void)
-+{
-+ uint8_t fam15h = 0;
-+ uint32_t family;
-+
-+ family = cpuid_eax(0x80000001);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-+
-+ return fam15h;
-+}
-+
- static void get_fx_devs(void)
- {
- int i;
-@@ -202,7 +217,7 @@ static void amd_g34_fixup(struct bus *link, device_t dev)
- /* Revision D or later */
- rev_gte_d = 1;
-
-- if (rev_gte_d) {
-+ if (rev_gte_d || is_fam15h()) {
- f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-
- /* Check for dual node capability */
-@@ -215,6 +230,15 @@ static void amd_g34_fixup(struct bus *link, device_t dev)
- */
- f3xe8 = pci_read_config32(get_node_pci(nodeid, 3), 0xe8);
- uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
-+ uint8_t defective_link_number_1;
-+ uint8_t defective_link_number_2;
-+ if (is_fam15h()) {
-+ defective_link_number_1 = 4; /* Link 0 Sublink 1 */
-+ defective_link_number_2 = 7; /* Link 3 Sublink 1 */
-+ } else {
-+ defective_link_number_1 = 6; /* Link 2 Sublink 1 */
-+ defective_link_number_2 = 5; /* Link 1 Sublink 1 */
-+ }
- if (internal_node_number == 0) {
- /* Node 0 */
- if (link->link_num == 6) /* Link 2 Sublink 1 */
-@@ -314,6 +338,46 @@ static void amdfam10_scan_chains(device_t dev)
- {
- struct bus *link;
-
-+#if CONFIG_CPU_AMD_SOCKET_G34_NON_AGESA
-+ if (is_fam15h()) {
-+ uint8_t current_link_number = 0;
-+
-+ for (link = dev->link_list; link; link = link->next) {
-+ /* The following links have changed position in Fam15h G34 processors:
-+ * Fam10 Fam15
-+ * Node 0
-+ * L3 --> L1
-+ * L0 --> L3
-+ * L1 --> L2
-+ * L2 --> L0
-+ * Node 1
-+ * L0 --> L0
-+ * L1 --> L3
-+ * L2 --> L1
-+ * L3 --> L2
-+ */
-+ if (link->link_num == 0)
-+ link->link_num = 3;
-+ else if (link->link_num == 1)
-+ link->link_num = 2;
-+ else if (link->link_num == 2)
-+ link->link_num = 0;
-+ else if (link->link_num == 3)
-+ link->link_num = 1;
-+ else if (link->link_num == 5)
-+ link->link_num = 7;
-+ else if (link->link_num == 6)
-+ link->link_num = 5;
-+ else if (link->link_num == 7)
-+ link->link_num = 6;
-+
-+ current_link_number++;
-+ if (current_link_number > 3)
-+ current_link_number = 0;
-+ }
-+ }
-+#endif
-+
- /* Do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0 */
- trim_ht_chain(dev);
-
-@@ -620,13 +684,21 @@ static const struct pci_driver mcf0_driver __pci_driver = {
- .device = 0x1200,
- };
-
-+
- static void amdfam10_nb_init(void *chip_info)
- {
- relocate_sb_ht_chain();
- }
-
-+static const struct pci_driver mcf0_driver_fam15 __pci_driver = {
-+ .ops = &northbridge_operations,
-+ .vendor = PCI_VENDOR_ID_AMD,
-+ .device = 0x1600,
-+};
-+
-+
- struct chip_operations northbridge_amd_amdfam10_ops = {
-- CHIP_NAME("AMD FAM10 Northbridge")
-+ CHIP_NAME("AMD Family 10h/15h Northbridge")
- .enable_dev = 0,
- .init = amdfam10_nb_init,
- };
-@@ -950,38 +1022,61 @@ static int amdfam10_get_smbios_data16(int* count, int handle, unsigned long *cur
-
- static uint16_t amdmct_mct_speed_enum_to_mhz(uint8_t speed)
- {
-- if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
-- switch (speed) {
-- case 1:
-- return 200;
-- case 2:
-- return 266;
-- case 3:
-- return 333;
-- case 4:
-- return 400;
-- case 5:
-- return 533;
-- default:
-- return 0;
-- }
-- } else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
-- switch (speed) {
-- case 3:
-- return 333;
-- case 4:
-- return 400;
-- case 5:
-- return 533;
-- case 6:
-- return 667;
-- case 7:
-- return 800;
-- default:
-- return 0;
-+ if (is_fam15h()) {
-+ if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
-+ switch (speed) {
-+ case 0x4:
-+ return 333;
-+ case 0x6:
-+ return 400;
-+ case 0xa:
-+ return 533;
-+ case 0xe:
-+ return 667;
-+ case 0x12:
-+ return 800;
-+ case 0x16:
-+ return 933;
-+ default:
-+ return 0;
-+ }
-+ } else {
-+ return 0;
- }
- } else {
-- return 0;
-+ if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
-+ switch (speed) {
-+ case 1:
-+ return 200;
-+ case 2:
-+ return 266;
-+ case 3:
-+ return 333;
-+ case 4:
-+ return 400;
-+ case 5:
-+ return 533;
-+ default:
-+ return 0;
-+ }
-+ } else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
-+ switch (speed) {
-+ case 3:
-+ return 333;
-+ case 4:
-+ return 400;
-+ case 5:
-+ return 533;
-+ case 6:
-+ return 667;
-+ case 7:
-+ return 800;
-+ default:
-+ return 0;
-+ }
-+ } else {
-+ return 0;
-+ }
- }
- }
-
-@@ -1076,6 +1171,8 @@ static int amdfam10_get_smbios_data17(int* count, int handle, int parent_handle,
- #if IS_ENABLED(CONFIG_DIMM_DDR3)
- /* Find the maximum and minimum supported voltages */
- uint8_t supported_voltages = mem_info->dct_stat[node].DimmSupportedVoltages[slot];
-+ uint8_t configured_voltage = mem_info->dct_stat[node].DimmConfiguredVoltage[slot];
-+
- if (supported_voltages & 0x8)
- t->minimum_voltage = 1150;
- else if (supported_voltages & 0x4)
-@@ -1094,7 +1191,14 @@ static int amdfam10_get_smbios_data17(int* count, int handle, int parent_handle,
- else if (supported_voltages & 0x8)
- t->maximum_voltage = 1150;
-
-- t->configured_voltage = mem_info->dct_stat[node].DimmConfiguredVoltage[slot];
-+ if (configured_voltage & 0x8)
-+ t->configured_voltage = 1150;
-+ else if (configured_voltage & 0x4)
-+ t->configured_voltage = 1250;
-+ else if (configured_voltage & 0x2)
-+ t->configured_voltage = 1350;
-+ else if (configured_voltage & 0x1)
-+ t->configured_voltage = 1500;
- #endif
- }
- t->memory_error_information_handle = 0xFFFE; /* no error information handle available */
-@@ -1233,12 +1337,14 @@ static void cpu_bus_scan(device_t dev)
- #if CONFIG_CBB
- device_t pci_domain;
- #endif
-+ int nvram = 0;
- int i,j;
- int nodes;
- unsigned nb_cfg_54;
- unsigned siblings;
- int cores_found;
- int disable_siblings;
-+ uint8_t disable_cu_siblings = 0;
- unsigned ApicIdCoreIdSize;
-
- nb_cfg_54 = 0;
-@@ -1325,14 +1431,23 @@ static void cpu_bus_scan(device_t dev)
- /* Always use the devicetree node with lapic_id 0 for BSP. */
- remap_bsp_lapic(cpu_bus);
-
-+ if (get_option(&nvram, "compute_unit_siblings") == CB_SUCCESS)
-+ disable_cu_siblings = !!nvram;
-+
-+ if (disable_cu_siblings)
-+ printk(BIOS_DEBUG, "Disabling siblings on each compute unit as requested\n");
-+
- for(i = 0; i < nodes; i++) {
- device_t cdb_dev;
- unsigned busn, devn;
- struct bus *pbus;
-
-+ uint8_t fam15h = 0;
- uint8_t rev_gte_d = 0;
- uint8_t dual_node = 0;
- uint32_t f3xe8;
-+ uint32_t family;
-+ uint32_t model;
-
- busn = CONFIG_CBB;
- devn = CONFIG_CDB+i;
-@@ -1372,7 +1487,16 @@ static void cpu_bus_scan(device_t dev)
-
- f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-
-- if (cpuid_eax(0x80000001) >= 0x8)
-+ family = model = cpuid_eax(0x80000001);
-+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
-+
-+ if (is_fam15h()) {
-+ /* Family 15h or later */
-+ fam15h = 1;
-+ nb_cfg_54 = 1;
-+ }
-+
-+ if ((model >= 0x8) || fam15h)
- /* Revision D or later */
- rev_gte_d = 1;
-
-@@ -1382,13 +1506,20 @@ static void cpu_bus_scan(device_t dev)
- dual_node = 1;
-
- cores_found = 0; // one core
-- cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
-+ if (fam15h)
-+ cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 5));
-+ else
-+ cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
- int enable_node = cdb_dev && cdb_dev->enabled;
- if (enable_node) {
-- j = pci_read_config32(cdb_dev, 0xe8);
-- cores_found = (j >> 12) & 3; // dev is func 3
-- if (siblings > 3)
-- cores_found |= (j >> 13) & 4;
-+ if (fam15h) {
-+ cores_found = pci_read_config32(cdb_dev, 0x84) & 0xff;
-+ } else {
-+ j = pci_read_config32(cdb_dev, 0xe8);
-+ cores_found = (j >> 12) & 3; // dev is func 3
-+ if (siblings > 3)
-+ cores_found |= (j >> 13) & 4;
-+ }
- printk(BIOS_DEBUG, " %s siblings=%d\n", dev_path(cdb_dev), cores_found);
- }
-
-@@ -1408,15 +1539,24 @@ static void cpu_bus_scan(device_t dev)
-
- if (dual_node) {
- apic_id = 0;
-- if (nb_cfg_54) {
-- apic_id |= ((i >> 1) & 0x3) << 4; /* Node ID */
-+ if (fam15h) {
-+ apic_id |= ((i >> 1) & 0x3) << 5; /* Node ID */
- apic_id |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */
- } else {
-- apic_id |= i & 0x3; /* Node ID */
-- apic_id |= (((i & 0x1) * (siblings + 1)) + j) << 4; /* Core ID */
-+ if (nb_cfg_54) {
-+ apic_id |= ((i >> 1) & 0x3) << 4; /* Node ID */
-+ apic_id |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */
-+ } else {
-+ apic_id |= i & 0x3; /* Node ID */
-+ apic_id |= (((i & 0x1) * (siblings + 1)) + j) << 4; /* Core ID */
-+ }
- }
- } else {
-- apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:64); // ?
-+ if (fam15h) {
-+ apic_id = (i * (siblings + 1)) + j;
-+ } else {
-+ apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:64); // ?
-+ }
- }
-
- #if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET>0)
-@@ -1426,6 +1566,9 @@ static void cpu_bus_scan(device_t dev)
- }
- }
- #endif
-+ if (disable_cu_siblings && (j & 0x1))
-+ continue;
-+
- device_t cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
- if (cpu)
- amd_cpu_topology(cpu, i, j);
-@@ -1484,6 +1627,6 @@ static void root_complex_enable_dev(struct device *dev)
- }
-
- struct chip_operations northbridge_amd_amdfam10_root_complex_ops = {
-- CHIP_NAME("AMD FAM10 Root Complex")
-+ CHIP_NAME("AMD Family 10h/15h Root Complex")
- .enable_dev = root_complex_enable_dev,
- };
-diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c b/src/northbridge/amd/amdfam10/raminit_amdmct.c
-index 5068e7a..cae228f 100644
---- a/src/northbridge/amd/amdfam10/raminit_amdmct.c
-+++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c
-@@ -44,8 +44,120 @@ static void print_tf(const char *func, const char *strval)
- #endif
- }
-
--static uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t registered, uint16_t freq)
-+static inline void fam15h_switch_dct(uint32_t dev, uint8_t dct)
- {
-+ uint32_t dword;
-+
-+ dword = Get_NB32(dev, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ Set_NB32(dev, 0x10c, dword);
-+}
-+
-+static inline void fam15h_switch_nb_pstate_config_reg(uint32_t dev, uint8_t nb_pstate)
-+{
-+ uint32_t dword;
-+
-+ dword = Get_NB32(dev, 0x10c);
-+ dword &= ~(0x3 << 4);
-+ dword |= (nb_pstate & 0x3) << 4;
-+ Set_NB32(dev, 0x10c, dword);
-+}
-+
-+static inline uint32_t Get_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg)
-+{
-+ if (is_fam15h()) {
-+ /* Obtain address of function 0x1 */
-+ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
-+ fam15h_switch_dct(dev_map, dct);
-+ return Get_NB32(dev, reg);
-+ } else {
-+ return Get_NB32(dev, (0x100 * dct) + reg);
-+ }
-+}
-+
-+static inline void Set_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg, uint32_t val)
-+{
-+ if (is_fam15h()) {
-+ /* Obtain address of function 0x1 */
-+ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
-+ fam15h_switch_dct(dev_map, dct);
-+ Set_NB32(dev, reg, val);
-+ } else {
-+ Set_NB32(dev, (0x100 * dct) + reg, val);
-+ }
-+}
-+
-+static inline uint32_t Get_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg)
-+{
-+ if (is_fam15h()) {
-+ /* Obtain address of function 0x1 */
-+ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
-+ fam15h_switch_dct(dev_map, dct);
-+ fam15h_switch_nb_pstate_config_reg(dev_map, nb_pstate);
-+ return Get_NB32(dev, reg);
-+ } else {
-+ return Get_NB32(dev, (0x100 * dct) + reg);
-+ }
-+}
-+
-+static inline void Set_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg, uint32_t val)
-+{
-+ if (is_fam15h()) {
-+ /* Obtain address of function 0x1 */
-+ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
-+ fam15h_switch_dct(dev_map, dct);
-+ fam15h_switch_nb_pstate_config_reg(dev_map, nb_pstate);
-+ Set_NB32(dev, reg, val);
-+ } else {
-+ Set_NB32(dev, (0x100 * dct) + reg, val);
-+ }
-+}
-+
-+static inline uint32_t Get_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index)
-+{
-+ if (is_fam15h()) {
-+ /* Obtain address of function 0x1 */
-+ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
-+ fam15h_switch_dct(dev_map, dct);
-+ return Get_NB32_index_wait(dev, index_reg, index);
-+ } else {
-+ return Get_NB32_index_wait(dev, (0x100 * dct) + index_reg, index);
-+ }
-+}
-+
-+static inline void Set_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index, uint32_t data)
-+{
-+ if (is_fam15h()) {
-+ /* Obtain address of function 0x1 */
-+ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
-+ fam15h_switch_dct(dev_map, dct);
-+ Set_NB32_index_wait(dev, index_reg, index, data);
-+ } else {
-+ Set_NB32_index_wait(dev, (0x100 * dct) + index_reg, index, data);
-+ }
-+}
-+
-+static uint16_t voltage_index_to_mv(uint8_t index)
-+{
-+ if (index & 0x8)
-+ return 1150;
-+ if (index & 0x4)
-+ return 1250;
-+ else if (index & 0x2)
-+ return 1350;
-+ else
-+ return 1500;
-+}
-+
-+static uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t highest_rank_count, uint8_t registered, uint8_t voltage, uint16_t freq)
-+{
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
- /* Return limited maximum RAM frequency */
- if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
- if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
-@@ -68,34 +180,178 @@ static uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t registered, uint16_t freq
- }
- }
- } else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
-- if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
-- /* K10 BKDG Rev. 3.62 Table 34 */
-- if (count > 2) {
-- /* Limit to DDR3-800 */
-- if (freq > 400) {
-- freq = 400;
-- print_tf(__func__, ": More than 2 registered DIMMs on channel; limiting to DDR3-800\n");
-+ if (voltage == 0) {
-+ printk(BIOS_DEBUG, "%s: WARNING: Mainboard DDR3 voltage unknown, assuming 1.5V!\n", __func__);
-+ voltage = 0x1;
-+ }
-+
-+ if (is_fam15h()) {
-+ if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
-+ /* Fam15h BKDG Rev. 3.14 Table 27 */
-+ if (voltage & 0x4) {
-+ /* 1.25V */
-+ if (count > 1) {
-+ if (highest_rank_count > 1) {
-+ /* Limit to DDR3-1066 */
-+ if (freq > 533) {
-+ freq = 533;
-+ printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else if (voltage & 0x2) {
-+ /* 1.35V */
-+ if (count > 1) {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1600 */
-+ if (freq > 800) {
-+ freq = 800;
-+ printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else if (voltage & 0x1) {
-+ /* 1.50V */
-+ if (count > 1) {
-+ /* Limit to DDR3-1600 */
-+ if (freq > 800) {
-+ freq = 800;
-+ printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1866 */
-+ if (freq > 933) {
-+ freq = 933;
-+ printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1866\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ }
-+ } else {
-+ /* Fam15h BKDG Rev. 3.14 Table 26 */
-+ if (voltage & 0x4) {
-+ /* 1.25V */
-+ if (count > 1) {
-+ if (highest_rank_count > 1) {
-+ /* Limit to DDR3-1066 */
-+ if (freq > 533) {
-+ freq = 533;
-+ printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else if (voltage & 0x2) {
-+ /* 1.35V */
-+ if (MaxDimmsInstallable > 1) {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1600 */
-+ if (freq > 800) {
-+ freq = 800;
-+ printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else if (voltage & 0x1) {
-+ if (MaxDimmsInstallable == 1) {
-+ if (count > 1) {
-+ /* Limit to DDR3-1600 */
-+ if (freq > 800) {
-+ freq = 800;
-+ printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1866 */
-+ if (freq > 933) {
-+ freq = 933;
-+ printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1866\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else {
-+ if (count > 1) {
-+ if (highest_rank_count > 1) {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1600 */
-+ if (freq > 800) {
-+ freq = 800;
-+ printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ } else {
-+ /* Limit to DDR3-1600 */
-+ if (freq > 800) {
-+ freq = 800;
-+ printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ }
-+ }
- }
-- } else if (count == 2) {
-- /* Limit to DDR3-1066 */
-- if (freq > 533) {
-- freq = 533;
-- print_tf(__func__, ": 2 registered DIMMs on channel; limiting to DDR3-1066\n");
-+ }
-+ } else {
-+ if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
-+ /* K10 BKDG Rev. 3.62 Table 34 */
-+ if (count > 2) {
-+ /* Limit to DDR3-800 */
-+ if (freq > 400) {
-+ freq = 400;
-+ printk(BIOS_DEBUG, "%s: More than 2 registered DIMMs on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else if (count == 2) {
-+ /* Limit to DDR3-1066 */
-+ if (freq > 533) {
-+ freq = 533;
-+ printk(BIOS_DEBUG, "%s: 2 registered DIMMs on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
-+ }
-+ } else {
-+ /* Limit to DDR3-1333 */
-+ if (freq > 666) {
-+ freq = 666;
-+ printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
-+ }
- }
- } else {
-+ /* K10 BKDG Rev. 3.62 Table 33 */
- /* Limit to DDR3-1333 */
- if (freq > 666) {
- freq = 666;
-- print_tf(__func__, ": 1 registered DIMM on channel; limiting to DDR3-1333\n");
-+ printk(BIOS_DEBUG, "%s: unbuffered DIMMs on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
- }
- }
-- } else {
-- /* K10 BKDG Rev. 3.62 Table 33 */
-- /* Limit to DDR3-1333 */
-- if (freq > 666) {
-- freq = 666;
-- print_tf(__func__, ": unbuffered DIMMs on channel; limiting to DDR3-1333\n");
-- }
- }
- }
-
-@@ -225,11 +481,13 @@ void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node)
-
- }
-
-+#if IS_ENABLED(CONFIG_SET_FIDVID)
- static u8 mctGetProcessorPackageType(void) {
- /* FIXME: I guess this belongs wherever mctGetLogicalCPUID ends up ? */
-- u32 BrandId = cpuid_ebx(0x80000001);
-- return (u8)((BrandId >> 28) & 0x0F);
-+ u32 BrandId = cpuid_ebx(0x80000001);
-+ return (u8)((BrandId >> 28) & 0x0F);
- }
-+#endif
-
- static void raminit_amdmct(struct sys_info *sysinfo)
- {
-diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c
-index 97f9db8..8f9177f 100644
---- a/src/northbridge/amd/amdht/h3ncmn.c
-+++ b/src/northbridge/amd/amdht/h3ncmn.c
-@@ -43,6 +43,7 @@
- #define CPU_HTNB_FUNC_04 4
- #define CPU_ADDR_FUNC_01 1
- #define CPU_NB_FUNC_03 3
-+#define CPU_NB_FUNC_05 5
-
- /* Function 0 registers */
- #define REG_ROUTE0_0X40 0x40
-@@ -70,6 +71,7 @@
- #define REG_NB_CPUID_3XFC 0xFC
- #define REG_NB_LINK_XCS_TOKEN0_3X148 0x148
- #define REG_NB_DOWNCORE_3X190 0x190
-+#define REG_NB_CAPABILITY_5X84 0x84
-
- /* Function 4 registers */
-
-@@ -555,9 +557,10 @@ static u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
- 15, 12, &temp);
-
- /* bits[15,13,12] specify the cores */
-- /* Support Downcoring */
- temp = ((temp & 8) >> 1) + (temp & 3);
- cores = temp + 1;
-+
-+ /* Support Downcoring */
- AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
- makePCIBusFromNode(node),
- makePCIDeviceFromNode(node),
-@@ -576,6 +579,56 @@ static u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
-
- /***************************************************************************//**
- *
-+ * static u8
-+ * fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb)
-+ *
-+ * Description:
-+ * Return the number of cores (1 based count) on node.
-+ *
-+ * Parameters:
-+ * @param[in] node = the node that will be examined
-+ * @param[in] *nb = this northbridge
-+ * @return = the number of cores
-+ *
-+ *
-+ */
-+static u8 fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb)
-+{
-+ u32 temp, leveling, cores;
-+ u8 i;
-+
-+ ASSERT((node < nb->maxNodes));
-+ /* Read CmpCap [7:0] */
-+ AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
-+ makePCIBusFromNode(node),
-+ makePCIDeviceFromNode(node),
-+ CPU_NB_FUNC_05,
-+ REG_NB_CAPABILITY_5X84),
-+ 7, 0, &temp);
-+
-+ /* bits[7:0] specify the cores */
-+ temp = temp & 0xff;
-+ cores = temp + 1;
-+
-+ /* Support Downcoring */
-+ AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
-+ makePCIBusFromNode(node),
-+ makePCIDeviceFromNode(node),
-+ CPU_NB_FUNC_03,
-+ REG_NB_DOWNCORE_3X190),
-+ 31, 0, &leveling);
-+ for (i=0; i<cores; i++)
-+ {
-+ if (leveling & ((u32) 1 << i))
-+ {
-+ temp--;
-+ }
-+ }
-+ return (u8)(temp+1);
-+}
-+
-+/***************************************************************************//**
-+ *
- * static void
- * setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb)
- *
-@@ -854,6 +907,69 @@ static BOOL fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
-
- /***************************************************************************//**
- *
-+ * static BOOL
-+ * fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
-+ *
-+ * Description:
-+ * Get node capability and update the minimum supported system capability.
-+ * Return whether the current configuration exceeds the capability.
-+ *
-+ * Parameters:
-+ * @param[in] node = the node
-+ * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered
-+ * @param[in] *nb = this northbridge
-+ * @return true: system is capable of current config.
-+ * false: system is not capable of current config.
-+ *
-+ * ---------------------------------------------------------------------------------------
-+ */
-+static BOOL fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
-+{
-+#ifndef HT_BUILD_NC_ONLY
-+ u32 temp;
-+ u8 maxNodes;
-+
-+ ASSERT(node < nb->maxNodes);
-+
-+ AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
-+ makePCIBusFromNode(node),
-+ makePCIDeviceFromNode(node),
-+ CPU_NB_FUNC_03,
-+ REG_NB_CAPABILITY_3XE8),
-+ 18, 16, &temp);
-+
-+ if (temp != 0)
-+ {
-+ maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */
-+ }
-+ else
-+ {
-+ /* Check if CPU package is dual node */
-+ AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
-+ makePCIBusFromNode(node),
-+ makePCIDeviceFromNode(node),
-+ CPU_NB_FUNC_03,
-+ REG_NB_CAPABILITY_3XE8),
-+ 29, 29, &temp);
-+ if (temp)
-+ maxNodes = 4;
-+ else
-+ maxNodes = 8;
-+ }
-+
-+ if (pDat->sysMpCap > maxNodes)
-+ {
-+ pDat->sysMpCap = maxNodes;
-+ }
-+ /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
-+ return (pDat->sysMpCap > pDat->NodesDiscovered);
-+#else
-+ return 1;
-+#endif
-+}
-+
-+/***************************************************************************//**
-+ *
- * static void
- * fam0fStopLink(u8 currentNode, u8 currentLink, cNorthBridge *nb)
- *
-@@ -2068,6 +2184,49 @@ void newNorthBridge(u8 node, cNorthBridge *nb)
- u32 match;
- u32 extFam, baseFam, model;
-
-+ cNorthBridge fam15 =
-+ {
-+#ifdef HT_BUILD_NC_ONLY
-+ 8,
-+ 1,
-+ 12,
-+#else
-+ 8,
-+ 8,
-+ 64,
-+#endif /* HT_BUILD_NC_ONLY*/
-+ writeRoutingTable,
-+ writeNodeID,
-+ readDefLnk,
-+ enableRoutingTables,
-+ verifyLinkIsCoherent,
-+ readTrueLinkFailStatus,
-+ readToken,
-+ writeToken,
-+ fam15GetNumCoresOnNode,
-+ setTotalNodesAndCores,
-+ limitNodes,
-+ writeFullRoutingTable,
-+ isCompatible,
-+ fam15IsCapable,
-+ (void (*)(u8, u8, cNorthBridge*))commonVoid,
-+ (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
-+ readSbLink,
-+ verifyLinkIsNonCoherent,
-+ ht3SetCFGAddrMap,
-+ convertBitsToWidth,
-+ convertWidthToBits,
-+ fam10NorthBridgeFreqMask,
-+ gatherLinkData,
-+ setLinkData,
-+ ht3WriteTrafficDistribution,
-+ fam10BufferOptimizations,
-+ 0x00000001,
-+ 0x00000200,
-+ 18,
-+ 0x00000f06
-+ };
-+
- cNorthBridge fam10 =
- {
- #ifdef HT_BUILD_NC_ONLY
-@@ -2175,8 +2334,14 @@ void newNorthBridge(u8 node, cNorthBridge *nb)
- 7, 4, &model);
- match = (u32)((baseFam << 8) | extFam);
-
-- /* Test each in turn looking for a match. Init the struct if found */
-- if (match == fam10.compatibleKey)
-+ /* Test each in turn looking for a match.
-+ * Initialize the struct if found.
-+ */
-+ if (match == fam15.compatibleKey)
-+ {
-+ Amdmemcpy((void *)nb, (const void *)&fam15, (u32) sizeof(cNorthBridge));
-+ }
-+ else if (match == fam10.compatibleKey)
- {
- Amdmemcpy((void *)nb, (const void *)&fam10, (u32) sizeof(cNorthBridge));
- }
-diff --git a/src/northbridge/amd/amdht/ht_wrapper.c b/src/northbridge/amd/amdht/ht_wrapper.c
-index 389b1b1..c0ccc69 100644
---- a/src/northbridge/amd/amdht/ht_wrapper.c
-+++ b/src/northbridge/amd/amdht/ht_wrapper.c
-@@ -174,16 +174,22 @@ void amd_ht_fixup(struct sys_info *sysinfo) {
- printk(BIOS_DEBUG, "amd_ht_fixup()\n");
- if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) {
- uint8_t rev_gte_d = 0;
-+ uint8_t fam15h = 0;
- uint8_t dual_node = 0;
- uint32_t f3xe8;
- uint32_t family;
- uint32_t model;
-
- family = model = cpuid_eax(0x80000001);
-- model = ((model & 0xf0000) >> 16) | ((model & 0xf0) >> 4);
-+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-
-- if (model >= 0x8)
-- /* Revision D or later */
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-+
-+ if ((model >= 0x8) || fam15h)
-+ /* Family 10h Revision D or later */
- rev_gte_d = 1;
-
- if (rev_gte_d) {
-@@ -195,7 +201,8 @@ void amd_ht_fixup(struct sys_info *sysinfo) {
-
- if (dual_node) {
- /* Each G34 processor contains a defective HT link.
-- * See the BKDG Rev 3.62 section 2.7.1.5 for details.
-+ * See the Family 10h BKDG Rev 3.62 section 2.7.1.5 for details
-+ * For Family 15h see the BKDG Rev. 3.14 section 2.12.1.5 for details.
- */
- uint8_t node;
- uint8_t node_count = get_nodes();
-@@ -205,46 +212,46 @@ void amd_ht_fixup(struct sys_info *sysinfo) {
- uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
- printk(BIOS_DEBUG, "amd_ht_fixup(): node %d (internal node ID %d): disabling defective HT link\n", node, internal_node_number);
- if (internal_node_number == 0) {
-- uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xd8) & 0x1;
-+ uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x98:0xd8) & 0x1;
- if (package_link_3_connected) {
- /* Set WidthIn and WidthOut to 0 */
-- dword = pci_read_config32(NODE_PCI(node, 0), 0xc4);
-+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4);
- dword &= ~0x77000000;
-- pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
-+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4, dword);
- /* Set Ganged to 1 */
-- dword = pci_read_config32(NODE_PCI(node, 0), 0x178);
-+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178);
- dword |= 0x00000001;
-- pci_write_config32(NODE_PCI(node, 0), 0x178, dword);
-+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178, dword);
- } else {
- /* Set ConnDly to 1 */
- dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
- dword |= 0x00000100;
- pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
- /* Set TransOff and EndOfChain to 1 */
-- dword = pci_read_config32(NODE_PCI(node, 4), 0xc4);
-+ dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4);
- dword |= 0x000000c0;
-- pci_write_config32(NODE_PCI(node, 4), 0xc4, dword);
-+ pci_write_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4, dword);
- }
- } else if (internal_node_number == 1) {
-- uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xb8) & 0x1;
-+ uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xf8:0xb8) & 0x1;
- if (package_link_3_connected) {
- /* Set WidthIn and WidthOut to 0 */
-- dword = pci_read_config32(NODE_PCI(node, 0), 0xa4);
-+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4);
- dword &= ~0x77000000;
-- pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
-+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4, dword);
- /* Set Ganged to 1 */
-- dword = pci_read_config32(NODE_PCI(node, 0), 0x174);
-+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174);
- dword |= 0x00000001;
-- pci_write_config32(NODE_PCI(node, 0), 0x174, dword);
-+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174, dword);
- } else {
- /* Set ConnDly to 1 */
- dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
- dword |= 0x00000100;
- pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
- /* Set TransOff and EndOfChain to 1 */
-- dword = pci_read_config32(NODE_PCI(node, 4), 0xa4);
-+ dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4);
- dword |= 0x000000c0;
-- pci_write_config32(NODE_PCI(node, 4), 0xa4, dword);
-+ pci_write_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4, dword);
- }
- }
- }
-diff --git a/src/northbridge/amd/amdmct/amddefs.h b/src/northbridge/amd/amdmct/amddefs.h
-index 117fea5..20a77d3 100644
---- a/src/northbridge/amd/amdmct/amddefs.h
-+++ b/src/northbridge/amd/amdmct/amddefs.h
-@@ -20,33 +20,35 @@
- /* FIXME: this file should be moved to include/cpu/amd/amddefs.h */
-
- /* Public Revisions - USE THESE VERSIONS TO MAKE COMPARE WITH CPULOGICALID RETURN VALUE*/
--#define AMD_SAFEMODE 0x80000000 /* Unknown future revision - SAFE MODE */
--#define AMD_NPT_F0 0x00000001 /* F0 stepping */
--#define AMD_NPT_F1 0x00000002 /* F1 stepping */
--#define AMD_NPT_F2C 0x00000004
--#define AMD_NPT_F2D 0x00000008
--#define AMD_NPT_F2E 0x00000010 /* F2 stepping E */
--#define AMD_NPT_F2G 0x00000020 /* F2 stepping G */
--#define AMD_NPT_F2J 0x00000040
--#define AMD_NPT_F2K 0x00000080
--#define AMD_NPT_F3L 0x00000100 /* F3 Stepping */
--#define AMD_NPT_G0A 0x00000200 /* G0 stepping */
--#define AMD_NPT_G1B 0x00000400 /* G1 stepping */
--#define AMD_DR_A0A 0x00010000 /* Barcelona A0 */
--#define AMD_DR_A1B 0x00020000 /* Barcelona A1 */
--#define AMD_DR_A2 0x00040000 /* Barcelona A2 */
--#define AMD_DR_B0 0x00080000 /* Barcelona B0 */
--#define AMD_DR_B1 0x00100000 /* Barcelona B1 */
--#define AMD_DR_B2 0x00200000 /* Barcelona B2 */
--#define AMD_DR_BA 0x00400000 /* Barcelona BA */
--#define AMD_DR_B3 0x00800000 /* Barcelona B3 */
--#define AMD_RB_C2 0x01000000 /* Shanghai C2 */
--#define AMD_DA_C2 0x02000000 /* XXXX C2 */
--#define AMD_HY_D0 0x04000000 /* Istanbul D0 */
--#define AMD_RB_C3 0x08000000 /* ??? C3 */
--#define AMD_DA_C3 0x10000000 /* XXXX C3 */
--#define AMD_HY_D1 0x20000000 /* Istanbul D1 */
--#define AMD_PH_E0 0x40000000 /* Phenom II X4 X6 */
-+#define AMD_SAFEMODE 0x8000000000000000 /* Unknown future revision - SAFE MODE */
-+#define AMD_NPT_F0 0x0000000000000001 /* F0 stepping */
-+#define AMD_NPT_F1 0x0000000000000002 /* F1 stepping */
-+#define AMD_NPT_F2C 0x0000000000000004
-+#define AMD_NPT_F2D 0x0000000000000008
-+#define AMD_NPT_F2E 0x0000000000000010 /* F2 stepping E */
-+#define AMD_NPT_F2G 0x0000000000000020 /* F2 stepping G */
-+#define AMD_NPT_F2J 0x0000000000000040
-+#define AMD_NPT_F2K 0x0000000000000080
-+#define AMD_NPT_F3L 0x0000000000000100 /* F3 Stepping */
-+#define AMD_NPT_G0A 0x0000000000000200 /* G0 stepping */
-+#define AMD_NPT_G1B 0x0000000000000400 /* G1 stepping */
-+#define AMD_DR_A0A 0x0000000000010000 /* Barcelona A0 */
-+#define AMD_DR_A1B 0x0000000000020000 /* Barcelona A1 */
-+#define AMD_DR_A2 0x0000000000040000 /* Barcelona A2 */
-+#define AMD_DR_B0 0x0000000000080000 /* Barcelona B0 */
-+#define AMD_DR_B1 0x0000000000100000 /* Barcelona B1 */
-+#define AMD_DR_B2 0x0000000000200000 /* Barcelona B2 */
-+#define AMD_DR_BA 0x0000000000400000 /* Barcelona BA */
-+#define AMD_DR_B3 0x0000000000800000 /* Barcelona B3 */
-+#define AMD_RB_C2 0x0000000001000000 /* Shanghai C2 */
-+#define AMD_DA_C2 0x0000000002000000 /* XXXX C2 */
-+#define AMD_HY_D0 0x0000000004000000 /* Istanbul D0 */
-+#define AMD_RB_C3 0x0000000008000000 /* ??? C3 */
-+#define AMD_DA_C3 0x0000000010000000 /* XXXX C3 */
-+#define AMD_HY_D1 0x0000000020000000 /* Istanbul D1 */
-+#define AMD_PH_E0 0x0000000040000000 /* Phenom II X4 X6 */
-+#define AMD_OR_B2 0x0000000080000000 /* Interlagos */
-+#define AMD_OR_C0 0x0000000100000000 /* Abu Dhabi */
-
- /*
- * Groups - Create as many as you wish, from the above public values
-@@ -76,6 +78,7 @@
- #define AMD_DRBH_Cx (AMD_DR_Cx | AMD_HY_D0 )
- #define AMD_DRBA23_RBC2 (AMD_DR_BA | AMD_DR_B2 | AMD_DR_B3 | AMD_RB_C2 )
- #define AMD_DR_DAC2_OR_C3 (AMD_DA_C2 | AMD_DA_C3 | AMD_RB_C3)
-+#define AMD_FAM15_ALL (AMD_OR_B2 | AMD_OR_C0)
-
- /*
- * Public Platforms - USE THESE VERSIONS TO MAKE COMPARE WITH CPUPLATFORMTYPE RETURN VALUE
-@@ -122,23 +125,34 @@
- */
- #define CPUID_EXT_PM 0x80000007
- #define CPUID_MODEL 1
--#define MCG_CAP 0x00000179
-+#define MCG_CAP 0x00000179
- #define MCG_CTL_P 8
--#define MC0_CTL 0x00000400
--#define MC0_STA MC0_CTL + 1
--#define FS_Base 0xC0000100
-+#define MC0_CTL 0x00000400
-+#define MC0_STA (MC0_CTL + 1)
-+#define MC4_MISC0 0x00000413
-+#define MC4_MISC1 0xC0000408
-+#define MC4_MISC2 0xC0000409
-+#define FS_Base 0xC0000100
- #define SYSCFG 0xC0010010
- #define HWCR 0xC0010015
- #define NB_CFG 0xC001001F
- #define FidVidStatus 0xC0010042
-+#define MC1_CTL_MASK 0xC0010045
- #define MC4_CTL_MASK 0xC0010048
- #define OSVW_ID_Length 0xC0010140
- #define OSVW_Status 0xC0010141
- #define CPUIDFEATURES 0xC0011004
- #define LS_CFG 0xC0011020
-+#define IC_CFG 0xC0011021
- #define DC_CFG 0xC0011022
- #define BU_CFG 0xC0011023
--#define BU_CFG2 0xC001102A
-+#define FP_CFG 0xC0011028
-+#define DE_CFG 0xC0011029
-+#define BU_CFG2 0xC001102A
-+#define BU_CFG3 0xC001102B
-+#define EX_CFG 0xC001102C
-+#define LS_CFG2 0xC001102D
-+#define IBS_OP_DATA3 0xC0011037
-
- /*
- * Processor package types
-diff --git a/src/northbridge/amd/amdmct/mct/mct_d.c b/src/northbridge/amd/amdmct/mct/mct_d.c
-index 88910e2..be0af65 100644
---- a/src/northbridge/amd/amdmct/mct/mct_d.c
-+++ b/src/northbridge/amd/amdmct/mct/mct_d.c
-@@ -2189,6 +2189,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- pDCTstat->DimmManufacturerID[i] |= ((uint64_t)mctRead_SPD(smbaddr, SPD_MANID_START + k)) << (k * 8);
- for (k = 0; k < SPD_PARTN_LENGTH; k++)
- pDCTstat->DimmPartNumber[i][k] = mctRead_SPD(smbaddr, SPD_PARTN_START + k);
-+ pDCTstat->DimmPartNumber[i][SPD_PARTN_LENGTH] = 0;
- pDCTstat->DimmRevisionNumber[i] = 0;
- for (k = 0; k < 2; k++)
- pDCTstat->DimmRevisionNumber[i] |= ((uint16_t)mctRead_SPD(smbaddr, SPD_REVNO_START + k)) << (k * 8);
-@@ -2206,8 +2207,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- if (byte & JED_REGADCMSK) {
- RegDIMMPresent |= 1 << i;
- pDCTstat->DimmRegistered[i] = 1;
-- }
-- else {
-+ } else {
- pDCTstat->DimmRegistered[i] = 0;
- }
- /* Check ECC capable */
-diff --git a/src/northbridge/amd/amdmct/mct/mct_d.h b/src/northbridge/amd/amdmct/mct/mct_d.h
-index 132bdc9..6b6194d 100644
---- a/src/northbridge/amd/amdmct/mct/mct_d.h
-+++ b/src/northbridge/amd/amdmct/mct/mct_d.h
-@@ -434,7 +434,7 @@ struct DCTStatStruc { /* A per Node structure*/
- /* CH A byte lane 0 - 7 maximum filtered window passing DQS delay value*/
- /* CH B byte lane 0 - 7 minimum filtered window passing DQS delay value*/
- /* CH B byte lane 0 - 7 maximum filtered window passing DQS delay value*/
-- u32 LogicalCPUID; /* The logical CPUID of the node*/
-+ uint64_t LogicalCPUID; /* The logical CPUID of the node*/
- u16 HostBiosSrvc1; /* Word sized general purpose field for use by host BIOS. Scratch space.*/
- u32 HostBiosSrvc2; /* Dword sized general purpose field for use by host BIOS. Scratch space.*/
- u16 DimmQRPresent; /* QuadRank DIMM present?*/
-@@ -529,7 +529,7 @@ struct DCTStatStruc { /* A per Node structure*/
- uint8_t DimmRegistered[MAX_DIMMS_SUPPORTED];
-
- uint64_t DimmManufacturerID[MAX_DIMMS_SUPPORTED];
-- char DimmPartNumber[MAX_DIMMS_SUPPORTED][SPD_PARTN_LENGTH];
-+ char DimmPartNumber[MAX_DIMMS_SUPPORTED][SPD_PARTN_LENGTH+1];
- uint16_t DimmRevisionNumber[MAX_DIMMS_SUPPORTED];
- uint32_t DimmSerialNumber[MAX_DIMMS_SUPPORTED];
- } __attribute__((packed));
-@@ -598,17 +598,18 @@ struct DCTStatStruc { /* A per Node structure*/
- 266=266MHz (DDR533)
- 333=333MHz (DDR667)
- 400=400MHz (DDR800)*/
--#define NV_ECC_CAP 4 /* Bus ECC capable (1-bits)
-+#define NV_MIN_MEMCLK 4 /* Minimum platform demonstrated Memclock (10-bits) */
-+#define NV_ECC_CAP 5 /* Bus ECC capable (1-bits)
- 0=Platform not capable
- 1=Platform is capable*/
--#define NV_4RANKType 5 /* Quad Rank DIMM slot type (2-bits)
-+#define NV_4RANKType 6 /* Quad Rank DIMM slot type (2-bits)
- 0=Normal
- 1=R4 (4-Rank Registered DIMMs in AMD server configuration)
- 2=S4 (Unbuffered SO-DIMMs)*/
--#define NV_BYPMAX 6 /* Value to set DcqBypassMax field (See Function 2, Offset 94h, [27:24] of BKDG for field definition).
-+#define NV_BYPMAX 7 /* Value to set DcqBypassMax field (See Function 2, Offset 94h, [27:24] of BKDG for field definition).
- 4=4 times bypass (normal for non-UMA systems)
- 7=7 times bypass (normal for UMA systems)*/
--#define NV_RDWRQBYP 7 /* Value to set RdWrQByp field (See Function 2, Offset A0h, [3:2] of BKDG for field definition).
-+#define NV_RDWRQBYP 8 /* Value to set RdWrQByp field (See Function 2, Offset A0h, [3:2] of BKDG for field definition).
- 2=8 times (normal for non-UMA systems)
- 3=16 times (normal for UMA systems)*/
-
-@@ -671,8 +672,9 @@ struct DCTStatStruc { /* A per Node structure*/
- #define NV_ECCRedir 54 /* Dram ECC Redirection enable*/
- #define NV_DramBKScrub 55 /* Dram ECC Background Scrubber CTL*/
- #define NV_L2BKScrub 56 /* L2 ECC Background Scrubber CTL*/
--#define NV_DCBKScrub 57 /* DCache ECC Background Scrubber CTL*/
--#define NV_CS_SpareCTL 58 /* Chip Select Spare Control bit 0:
-+#define NV_L3BKScrub 57 /* L3 ECC Background Scrubber CTL*/
-+#define NV_DCBKScrub 58 /* DCache ECC Background Scrubber CTL*/
-+#define NV_CS_SpareCTL 59 /* Chip Select Spare Control bit 0:
- 0=disable Spare
- 1=enable Spare */
- /* Chip Select Spare Control bit 1-4:
-@@ -712,7 +714,7 @@ u8 mct_Get_Start_RcvrEnDly_1Pass(u8 Pass);
- u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass);
- void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
- void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
--u32 mctGetLogicalCPUID(u32 Node);
-+uint64_t mctGetLogicalCPUID(u32 Node);
- u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
- void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u8 Pass);
- void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
-diff --git a/src/northbridge/amd/amdmct/mct/mctpro_d.c b/src/northbridge/amd/amdmct/mct/mctpro_d.c
-index c332357..fe56201 100644
---- a/src/northbridge/amd/amdmct/mct/mctpro_d.c
-+++ b/src/northbridge/amd/amdmct/mct/mctpro_d.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -23,7 +24,7 @@ void EarlySampleSupport_D(void)
-
- u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val)
- {
-- u32 tmp;
-+ uint64_t tmp;
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
- val &= 0x0FFFFFFF;
-@@ -42,7 +43,7 @@ u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val)
- * ( F2x[1, 0]8C[1:0] > 00b). Silicon Status: Fixed in Rev B
- * FIXME: check if this is still required.
- */
-- u32 tmp;
-+ uint64_t tmp;
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
- if(!(val & (3<<12) ))
-@@ -54,7 +55,7 @@ u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val)
-
- void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct)
- {
-- u32 tmp;
-+ uint64_t tmp;
- u32 reg;
- u32 reg_off;
- u32 dev;
-@@ -96,7 +97,7 @@ void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,
- * FIXME: check this.
- */
-
-- u32 tmp;
-+ uint64_t tmp;
- u32 dev;
- u32 reg;
- u32 val;
-@@ -143,10 +144,9 @@ void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat,
- u32 index;
- u32 reg;
- u32 val;
-- u32 tmp;
-+ uint64_t tmp;
- u32 Channel;
-
--
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
-
-@@ -206,7 +206,7 @@ u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value)
- u32 index_reg;
- u32 index;
- u32 val;
-- u32 tmp;
-+ uint64_t tmp;
-
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
-@@ -237,7 +237,7 @@ void SyncSetting(struct DCTStatStruc *pDCTstat)
- * Silicon Status: Fix TBD
- */
-
-- u32 tmp;
-+ uint64_t tmp;
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
- pDCTstat->CH_ODC_CTL[1] = pDCTstat->CH_ODC_CTL[0];
-@@ -278,7 +278,7 @@ u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct)
-
- void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct)
- {
-- u32 tmp;
-+ uint64_t tmp;
- u32 Speed;
- u32 ch, ch_start, ch_end;
- u32 index_reg;
-@@ -286,7 +286,6 @@ void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct)
- u32 dev;
- u32 val;
-
--
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
- Speed = pDCTstat->Speed;
-@@ -331,7 +330,7 @@ static u8 mct_checkFenceHoleAdjust_D(struct MCTStatStruc *pMCTstat,
- u8 ChipSel, u8 *result)
- {
- u8 ByteLane;
-- u32 tmp;
-+ uint64_t tmp;
-
- tmp = pDCTstat->LogicalCPUID;
- if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-index 12dfff1..74066b1 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-@@ -75,6 +75,8 @@ static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
- static u16 Get_Fk_D(u8 k);
- static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i);
-+static void mct_preInitDCT(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat);
- static void mct_initDCT(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
- static void mct_DramInit(struct MCTStatStruc *pMCTstat,
-@@ -105,11 +107,11 @@ static void Get_TrwtTO(struct MCTStatStruc *pMCTstat,
- static void Get_TrwtWB(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
- static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
-- u32 dev, u32 index_reg);
-+ u32 dev, uint8_t dct, u32 index_reg);
- static void Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, u8 dct,
- u32 dev, u32 index_reg);
- static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
-- u32 dev, u32 index_reg, u32 index);
-+ u32 dev, uint8_t dct, u32 index_reg, u32 index);
- static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
- static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, u8 dct,
-@@ -128,6 +130,8 @@ static void SetCKETriState(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
- static void SetODTTriState(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
-+static void InitDDRPhy(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct);
- static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
- static u32 mct_NodePresent_D(void);
-@@ -138,7 +142,9 @@ static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat,
- static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
- static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstat);
-+ struct DCTStatStruc *pDCTstat, u8 dct);
-+static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct);
- void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
- static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
-@@ -158,6 +164,10 @@ static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct);
- static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
-+static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat);
-+void SetTargetFreq(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat);
-
- static u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel);
-@@ -165,7 +175,8 @@ static u32 mct_DramTermDyn_RDimm(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dimm);
- static u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2);
- static void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat);
--static void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
-+static void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstatA, uint8_t Pass);
- static u8 Get_Latency_Diff(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
- static void SyncSetting(struct DCTStatStruc *pDCTstat);
-@@ -173,6 +184,12 @@ static u8 crcCheck(u8 smbaddr);
- static void mct_ExtMCTConfig_Bx(struct DCTStatStruc *pDCTstat);
- static void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat);
-
-+static void read_dqs_receiver_enable_control_registers(uint16_t* current_total_delay,
-+ uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg);
-+
-+static void read_dqs_write_timing_control_registers(uint16_t* current_total_delay,
-+ uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg);
-+
- /*See mctAutoInitMCT header for index relationships to CL and T*/
- static const u16 Table_F_k[] = {00,200,266,333,400,533 };
- static const u8 Tab_BankAddr[] = {0x3F,0x01,0x09,0x3F,0x3F,0x11,0x0A,0x19,0x12,0x1A,0x21,0x22,0x23};
-@@ -223,6 +240,936 @@ static const u8 Table_Comp_Rise_Slew_15x[] = {7, 7, 3, 2, 0xFF};
- static const u8 Table_Comp_Fall_Slew_20x[] = {7, 5, 3, 2, 0xFF};
- static const u8 Table_Comp_Fall_Slew_15x[] = {7, 7, 5, 3, 0xFF};
-
-+static uint8_t dct_ddr_voltage_index(struct DCTStatStruc *pDCTstat, uint8_t dct)
-+{
-+ uint8_t dimm;
-+ uint8_t ddr_voltage_index = 0;
-+
-+ /* Find current DDR supply voltage for this DCT */
-+ for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) {
-+ if (pDCTstat->DIMMValidDCT[dct] & (1 << dimm))
-+ ddr_voltage_index |= pDCTstat->DimmConfiguredVoltage[dimm];
-+ }
-+ if (ddr_voltage_index > 0x7) {
-+ printk(BIOS_DEBUG, "%s: Insufficient DDR supply voltage indicated! Configuring processor for 1.25V operation, but this attempt may fail...\n", __func__);
-+ ddr_voltage_index = 0x4;
-+ }
-+ if (ddr_voltage_index == 0x0) {
-+ printk(BIOS_DEBUG, "%s: No DDR supply voltage indicated! Configuring processor for 1.5V operation, but this attempt may fail...\n", __func__);
-+ ddr_voltage_index = 0x1;
-+ }
-+
-+ return ddr_voltage_index;
-+}
-+
-+static uint16_t fam15h_mhz_to_memclk_config(uint16_t freq)
-+{
-+ uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
-+ uint16_t iter;
-+
-+ /* Compute the index value for the given frequency */
-+ for (iter = 0; iter <= 0x16; iter++) {
-+ if (fam15h_freq_tab[iter] == freq)
-+ break;
-+ }
-+ if (fam15h_freq_tab[iter] == freq)
-+ freq = iter;
-+ if (freq == 0)
-+ freq = 0x4;
-+
-+ return freq;
-+}
-+
-+static uint16_t fam10h_mhz_to_memclk_config(uint16_t freq)
-+{
-+ uint16_t fam10h_freq_tab[] = {0, 0, 0, 400, 533, 667, 800};
-+ uint16_t iter;
-+
-+ /* Compute the index value for the given frequency */
-+ for (iter = 0; iter <= 0x6; iter++) {
-+ if (fam10h_freq_tab[iter] == freq)
-+ break;
-+ }
-+ if (fam10h_freq_tab[iter] == freq)
-+ freq = iter;
-+ if (freq == 0)
-+ freq = 0x3;
-+
-+ return freq;
-+}
-+
-+static uint16_t mhz_to_memclk_config(uint16_t freq)
-+{
-+ if (is_fam15h())
-+ return fam15h_mhz_to_memclk_config(freq);
-+ else
-+ return fam10h_mhz_to_memclk_config(freq) + 1;
-+}
-+
-+static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t drive_strength)
-+{
-+ uint8_t lrdimm = 0;
-+ uint8_t package_type;
-+ uint8_t ddr_voltage_index;
-+ uint32_t calibration_code = 0;
-+ uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct);
-+ package_type = mctGet_NVbits(NV_PACK_TYPE);
-+
-+ if (!lrdimm) {
-+ /* Not an LRDIMM */
-+ if ((package_type == PT_M2) || (package_type == PT_GR)) {
-+ /* Socket AM3 or G34 */
-+ if (ddr_voltage_index & 0x4) {
-+ /* 1.25V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 43 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xdb6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x924;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xfff;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x2) {
-+ /* 1.35V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 42 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xdb6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xbd6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xdb6;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x1) {
-+ /* 1.5V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 41 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xb6d;
-+ }
-+ }
-+ }
-+ else if (package_type == PT_C3) {
-+ /* Socket C32 */
-+ if (ddr_voltage_index & 0x4) {
-+ /* 1.25V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 46 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xdb6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x924;
-+ } else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xfff;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x2) {
-+ /* 1.35V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 45 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xdb6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xdb6;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x1) {
-+ /* 1.5V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 44 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xfff;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xb6d;
-+ }
-+ }
-+ }
-+ } else {
-+ /* LRDIMM */
-+
-+ /* TODO
-+ * Implement LRDIMM support
-+ * See Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Tables 47 - 49
-+ */
-+ }
-+
-+ return calibration_code;
-+}
-+
-+static uint32_t fam15h_phy_predriver_cmd_addr_calibration_code(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t drive_strength)
-+{
-+ uint8_t ddr_voltage_index;
-+ uint32_t calibration_code = 0;
-+ uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct);
-+
-+ if (ddr_voltage_index & 0x4) {
-+ /* 1.25V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 52 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xdad;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xdad;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xb64;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xb64;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x2) {
-+ /* 1.35V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 51 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x924;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x1) {
-+ /* 1.5V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 50 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x492;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x492;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x6db;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x6db;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xb6d;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xb6d;
-+ }
-+ }
-+
-+ return calibration_code;
-+}
-+
-+static uint32_t fam15h_phy_predriver_clk_calibration_code(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t drive_strength)
-+{
-+ uint8_t ddr_voltage_index;
-+ uint32_t calibration_code = 0;
-+ uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct);
-+
-+ if (ddr_voltage_index & 0x4) {
-+ /* 1.25V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 55 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xdad;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xdad;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x924;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xff6;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xff6;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x2) {
-+ /* 1.35V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 54 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xdad;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xdad;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x924;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xdad;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xdad;
-+ }
-+ }
-+ else if (ddr_voltage_index & 0x1) {
-+ /* 1.5V */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 53 */
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-+ /* DDR3-667 - DDR3-800 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0x924;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0x924;
-+ } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
-+ /* DDR3-1066 - DDR3-1333 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xb6d;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (drive_strength == 0x0)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x1)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x2)
-+ calibration_code = 0xff6;
-+ else if (drive_strength == 0x3)
-+ calibration_code = 0xff6;
-+ }
-+ }
-+
-+ return calibration_code;
-+}
-+
-+static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
-+{
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ uint8_t package_type;
-+ uint32_t calibration_code = 0;
-+
-+ package_type = mctGet_NVbits(NV_PACK_TYPE);
-+ uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ /* Obtain number of DIMMs on channel */
-+ uint8_t dimm_count = pDCTstat->MAdimms[dct];
-+ uint8_t rank_count_dimm0;
-+ uint8_t rank_count_dimm1;
-+
-+ if (package_type == PT_GR) {
-+ /* Socket G34 */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */
-+ if (MaxDimmsInstallable == 1) {
-+ if (MemClkFreq == 0x4) {
-+ /* DDR3-667 */
-+ calibration_code = 0x00112222;
-+ }
-+ else if (MemClkFreq == 0x6) {
-+ /* DDR3-800 */
-+ calibration_code = 0x10112222;
-+ }
-+ else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ calibration_code = 0x20112222;
-+ }
-+ else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
-+ /* DDR3-1333 - DDR3-1600 */
-+ calibration_code = 0x30112222;
-+ }
-+ else if (MemClkFreq == 0x16) {
-+ /* DDR3-1866 */
-+ calibration_code = 0x30332222;
-+ }
-+ } else if (MaxDimmsInstallable == 2) {
-+ if (dimm_count == 1) {
-+ /* 1 DIMM detected */
-+ if (MemClkFreq == 0x4) {
-+ /* DDR3-667 */
-+ calibration_code = 0x00112222;
-+ }
-+ else if (MemClkFreq == 0x6) {
-+ /* DDR3-800 */
-+ calibration_code = 0x10112222;
-+ }
-+ else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ calibration_code = 0x20112222;
-+ }
-+ else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
-+ /* DDR3-1333 - DDR3-1600 */
-+ calibration_code = 0x30112222;
-+ }
-+ } else if (dimm_count == 2) {
-+ /* 2 DIMMs detected */
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[0];
-+ rank_count_dimm1 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if (MemClkFreq == 0x4) {
-+ /* DDR3-667 */
-+ calibration_code = 0x10222222;
-+ }
-+ else if (MemClkFreq == 0x6) {
-+ /* DDR3-800 */
-+ calibration_code = 0x20222222;
-+ }
-+ else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ calibration_code = 0x30222222;
-+ }
-+ else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ calibration_code = 0x30222222;
-+ }
-+ else if (MemClkFreq == 0x12) {
-+ /* DDR3-1600 */
-+ if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1))
-+ calibration_code = 0x30222222;
-+ else
-+ calibration_code = 0x30112222;
-+ }
-+ }
-+ } else if (MaxDimmsInstallable == 3) {
-+ /* TODO
-+ * 3 DIMM/channel support unimplemented
-+ */
-+ }
-+ } else {
-+ /* TODO
-+ * Other socket support unimplemented
-+ */
-+ }
-+
-+ return calibration_code;
-+}
-+
-+static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
-+{
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ uint8_t package_type;
-+ uint32_t calibration_code = 0;
-+
-+ package_type = mctGet_NVbits(NV_PACK_TYPE);
-+ uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ /* Obtain number of DIMMs on channel */
-+ uint8_t dimm_count = pDCTstat->MAdimms[dct];
-+ uint8_t rank_count_dimm0;
-+ uint8_t rank_count_dimm1;
-+
-+ if (package_type == PT_GR) {
-+ /* Socket G34 */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */
-+ if (MaxDimmsInstallable == 1) {
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if (MemClkFreq == 0x4) {
-+ /* DDR3-667 */
-+ if (rank_count_dimm0 == 1)
-+ calibration_code = 0x00000000;
-+ else
-+ calibration_code = 0x003b0000;
-+ } else if (MemClkFreq == 0x6) {
-+ /* DDR3-800 */
-+ if (rank_count_dimm0 == 1)
-+ calibration_code = 0x00000000;
-+ else
-+ calibration_code = 0x003b0000;
-+ } else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ calibration_code = 0x00383837;
-+ } else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ calibration_code = 0x00363635;
-+ } else if (MemClkFreq == 0x12) {
-+ /* DDR3-1600 */
-+ if (rank_count_dimm0 == 1)
-+ calibration_code = 0x00353533;
-+ else
-+ calibration_code = 0x00003533;
-+ } else if (MemClkFreq == 0x16) {
-+ /* DDR3-1866 */
-+ calibration_code = 0x00333330;
-+ }
-+ } else if (MaxDimmsInstallable == 2) {
-+ if (dimm_count == 1) {
-+ /* 1 DIMM detected */
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if (MemClkFreq == 0x4) {
-+ /* DDR3-667 */
-+ if (rank_count_dimm0 == 1)
-+ calibration_code = 0x00000000;
-+ else
-+ calibration_code = 0x003b0000;
-+ } else if (MemClkFreq == 0x6) {
-+ /* DDR3-800 */
-+ if (rank_count_dimm0 == 1)
-+ calibration_code = 0x00000000;
-+ else
-+ calibration_code = 0x003b0000;
-+ } else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ calibration_code = 0x00383837;
-+ } else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ calibration_code = 0x00363635;
-+ } else if (MemClkFreq == 0x12) {
-+ /* DDR3-1600 */
-+ if (rank_count_dimm0 == 1)
-+ calibration_code = 0x00353533;
-+ else
-+ calibration_code = 0x00003533;
-+ }
-+ } else if (dimm_count == 2) {
-+ /* 2 DIMMs detected */
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[0];
-+ rank_count_dimm1 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if (MemClkFreq == 0x4) {
-+ /* DDR3-667 */
-+ calibration_code = 0x00390039;
-+ } else if (MemClkFreq == 0x6) {
-+ /* DDR3-800 */
-+ calibration_code = 0x00390039;
-+ } else if (MemClkFreq == 0xa) {
-+ /* DDR3-1066 */
-+ calibration_code = 0x003a3a3a;
-+ } else if (MemClkFreq == 0xe) {
-+ /* DDR3-1333 */
-+ calibration_code = 0x00003939;
-+ } else if (MemClkFreq == 0x12) {
-+ /* DDR3-1600 */
-+ if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1))
-+ calibration_code = 0x00003738;
-+ }
-+ }
-+ } else if (MaxDimmsInstallable == 3) {
-+ /* TODO
-+ * 3 DIMM/channel support unimplemented
-+ */
-+ }
-+ } else {
-+ /* TODO
-+ * Other socket support unimplemented
-+ */
-+ }
-+
-+ return calibration_code;
-+}
-+
-+static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dct)
-+{
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ uint8_t package_type;
-+ uint32_t slow_access = 0;
-+
-+ package_type = mctGet_NVbits(NV_PACK_TYPE);
-+ uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ /* Obtain number of DIMMs on channel */
-+ uint8_t dimm_count = pDCTstat->MAdimms[dct];
-+ uint8_t rank_count_dimm0;
-+ uint8_t rank_count_dimm1;
-+
-+ if (package_type == PT_GR) {
-+ /* Socket G34 */
-+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */
-+ if (MaxDimmsInstallable == 1) {
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
-+ || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
-+ /* DDR3-667 - DDR3-1333 */
-+ slow_access = 0;
-+ } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
-+ /* DDR3-1600 - DDR3-1866 */
-+ if (rank_count_dimm0 == 1)
-+ slow_access = 0;
-+ else
-+ slow_access = 1;
-+ }
-+ } else if (MaxDimmsInstallable == 2) {
-+ if (dimm_count == 1) {
-+ /* 1 DIMM detected */
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
-+ || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
-+ /* DDR3-667 - DDR3-1333 */
-+ slow_access = 0;
-+ }
-+ else if (MemClkFreq == 0x12) {
-+ /* DDR3-1600 */
-+ if (rank_count_dimm0 == 1)
-+ slow_access = 0;
-+ else
-+ slow_access = 1;
-+ }
-+ } else if (dimm_count == 2) {
-+ /* 2 DIMMs detected */
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[0];
-+ rank_count_dimm1 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+
-+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
-+ || (MemClkFreq == 0xa)) {
-+ /* DDR3-667 - DDR3-1066 */
-+ slow_access = 0;
-+ }
-+ else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
-+ /* DDR3-1333 - DDR3-1600 */
-+ slow_access = 1;
-+ }
-+ }
-+ } else if (MaxDimmsInstallable == 3) {
-+ /* TODO
-+ * 3 DIMM/channel support unimplemented
-+ */
-+ }
-+ } else {
-+ /* TODO
-+ * Other socket support unimplemented
-+ */
-+ }
-+
-+ return slow_access;
-+}
-+
-+static void set_2t_configuration(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct)
-+{
-+ uint32_t dev;
-+ uint32_t reg;
-+ uint32_t dword;
-+
-+ uint8_t enable_slow_access_mode = 0;
-+ dev = pDCTstat->dev_dct;
-+
-+ if (is_fam15h()) {
-+ if (pDCTstat->_2Tmode)
-+ enable_slow_access_mode = 1;
-+ } else {
-+ if (pDCTstat->_2Tmode == 2)
-+ enable_slow_access_mode = 1;
-+ }
-+
-+ reg = 0x94; /* DRAM Configuration High */
-+ dword = Get_NB32_DCT(dev, dct, reg);
-+ if (enable_slow_access_mode)
-+ dword |= (0x1 << 20); /* Set 2T CMD mode */
-+ else
-+ dword &= ~(0x1 << 20); /* Clear 2T CMD mode */
-+ Set_NB32_DCT(dev, dct, reg, dword);
-+}
-+
-+static void precise_ndelay_fam15(struct MCTStatStruc *pMCTstat, uint32_t nanoseconds) {
-+ msr_t tsc_msr;
-+ uint64_t cycle_count = (((uint64_t)pMCTstat->TSCFreq) * nanoseconds) / 1000;
-+ uint64_t start_timestamp;
-+ uint64_t current_timestamp;
-+
-+ tsc_msr = rdmsr(0x00000010);
-+ start_timestamp = (((uint64_t)tsc_msr.hi) << 32) | tsc_msr.lo;
-+ do {
-+ tsc_msr = rdmsr(0x00000010);
-+ current_timestamp = (((uint64_t)tsc_msr.hi) << 32) | tsc_msr.lo;
-+ } while ((current_timestamp - start_timestamp) < cycle_count);
-+}
-+
-+static void precise_memclk_delay_fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t clocks) {
-+ uint16_t memclk_freq;
-+ uint32_t delay_ns;
-+ uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
-+
-+ memclk_freq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+
-+ delay_ns = (((uint64_t)clocks * 1000) / fam15h_freq_tab[memclk_freq]);
-+ precise_ndelay_fam15(pMCTstat, delay_ns);
-+}
-+
- static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA)
- {
-@@ -277,10 +1224,26 @@ static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
- restartinit:
- mctInitMemGPIOs_A_D(); /* Set any required GPIOs*/
- if (s3resume) {
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_En_Fam15\n");
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+
-+ mct_ForceNBPState0_En_Fam15(pMCTstat, pDCTstat);
-+ }
-+
- #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DCT configuration from NVRAM\n");
- restore_mct_information_from_nvram();
- #endif
-+
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n");
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+
-+ mct_ForceNBPState0_Dis_Fam15(pMCTstat, pDCTstat);
-+ }
- } else {
- NodesWmem = 0;
- node_sys_base = 0;
-@@ -297,15 +1260,15 @@ restartinit:
- pDCTstat->dev_map = PA_MAP(Node);
- pDCTstat->dev_dct = PA_DCT(Node);
- pDCTstat->dev_nbmisc = PA_NBMISC(Node);
-+ pDCTstat->dev_link = PA_LINK(Node);
-+ pDCTstat->dev_nbctl = PA_NBCTL(Node);
- pDCTstat->NodeSysBase = node_sys_base;
-
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_init Node %d\n", Node);
- mct_init(pMCTstat, pDCTstat);
- mctNodeIDDebugPort_D();
- pDCTstat->NodePresent = NodePresent_D(Node);
-- if (pDCTstat->NodePresent) { /* See if Node is there*/
-- printk(BIOS_DEBUG, "mctAutoInitMCT_D: clear_legacy_Mode\n");
-- clear_legacy_Mode(pMCTstat, pDCTstat);
-+ if (pDCTstat->NodePresent) {
- pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);
-
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_InitialMCT_D\n");
-@@ -314,6 +1277,26 @@ restartinit:
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: mctSMBhub_Init\n");
- mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/
-
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_preInitDCT\n");
-+ mct_preInitDCT(pMCTstat, pDCTstat);
-+ }
-+ node_sys_base = pDCTstat->NodeSysBase;
-+ node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
-+ }
-+
-+#if IS_ENABLED(DIMM_VOLTAGE_SET_SUPPORT)
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: DIMMSetVoltage\n");
-+ DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */
-+#endif
-+
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+
-+ if (pDCTstat->NodePresent) {
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: mctSMBhub_Init\n");
-+ mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/
-+
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_initDCT\n");
- mct_initDCT(pMCTstat, pDCTstat);
- if (pDCTstat->ErrCode == SC_FatalErr) {
-@@ -321,20 +1304,13 @@ restartinit:
- } else if (pDCTstat->ErrCode < SC_StopError) {
- NodesWmem++;
- }
-- } /* if Node present */
-- node_sys_base = pDCTstat->NodeSysBase;
-- node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
-+ }
- }
- if (NodesWmem == 0) {
- printk(BIOS_DEBUG, "No Nodes?!\n");
- goto fatalexit;
- }
-
--#if IS_ENABLED(DIMM_VOLTAGE_SET_SUPPORT)
-- printk(BIOS_DEBUG, "mctAutoInitMCT_D: DIMMSetVoltage\n");
-- DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */
--#endif
--
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n");
- SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/
-
-@@ -355,7 +1331,6 @@ restartinit:
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: :OtherTiming\n");
- mct_OtherTiming(pMCTstat, pDCTstatA);
-
--
- if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/
- goto restartinit;
- }
-@@ -369,6 +1344,14 @@ restartinit:
- MCTMemClr_D(pMCTstat,pDCTstatA);
- }
-
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n");
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+
-+ mct_ForceNBPState0_Dis_Fam15(pMCTstat, pDCTstat);
-+ }
-+
- mct_FinalMCT_D(pMCTstat, pDCTstatA);
- printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", pMCTstat->GStatus);
- }
-@@ -408,6 +1391,425 @@ static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat,
- return ret;
- }
-
-+/* Enable or disable phy-assisted training mode
-+ * Phy-assisted training mode applies to the follow DRAM training procedures:
-+ * Write Levelization Training (2.10.5.8.1)
-+ * DQS Receiver Enable Training (2.10.5.8.2)
-+ */
-+static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t enable)
-+{
-+ uint8_t index;
-+ uint32_t dword;
-+ uint32_t index_reg = 0x98;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ if (enable) {
-+ /* Enable training mode */
-+ dword = Get_NB32_DCT(dev, dct, 0x78); /* DRAM Control */
-+ dword &= ~(0x1 << 17); /* AddrCmdTriEn = 0 */
-+ Set_NB32_DCT(dev, dct, 0x78, dword); /* DRAM Control */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */
-+ dword |= (0x1 << 18); /* DisAutoRefresh = 1 */
-+ Set_NB32_DCT(dev, dct, 0x8c, dword); /* DRAM Timing High */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x94); /* DRAM Configuration High */
-+ dword &= ~(0xf << 24); /* DcqBypassMax = 0 */
-+ dword &= ~(0x1 << 22); /* BankSwizzleMode = 0 */
-+ dword &= ~(0x1 << 15); /* PowerDownEn = 0 */
-+ dword &= ~(0x3 << 10); /* ZqcsInterval = 0 */
-+ Set_NB32_DCT(dev, dct, 0x94, dword); /* DRAM Configuration High */
-+
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d);
-+ dword &= ~(0xf << 16); /* RxMaxDurDllNoLock = 0 */
-+ dword &= ~(0xf); /* TxMaxDurDllNoLock = 0 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d, dword);
-+
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8));
-+ dword &= ~(0x1 << 12); /* EnRxPadStandby = 0 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8), dword);
-+ }
-+
-+ dword = Get_NB32_DCT(dev, dct, 0xa4); /* DRAM Controller Temperature Throttle */
-+ dword &= ~(0x1 << 11); /* BwCapEn = 0 */
-+ dword &= ~(0x1 << 8); /* ODTSEn = 0 */
-+ Set_NB32_DCT(dev, dct, 0xa4, dword); /* DRAM Controller Temperature Throttle */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x110); /* DRAM Controller Select Low */
-+ dword &= ~(0x1 << 2); /* DctSelIntLvEn = 0 */
-+ Set_NB32_DCT(dev, dct, 0x110, dword); /* DRAM Controller Select Low */
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x58); /* Scrub Rate Control */
-+ dword &= ~(0x1f << 24); /* L3Scrub = 0 */
-+ dword &= ~(0x1f); /* DramScrub = 0 */
-+ Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x58, dword); /* Scrub Rate Control */
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x5c); /* DRAM Scrub Address Low */
-+ dword &= ~(0x1); /* ScrubReDirEn = 0 */
-+ Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x5c, dword); /* DRAM Scrub Address Low */
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x1b8); /* L3 Control 1 */
-+ dword |= (0x1 << 4); /* L3ScrbRedirDis = 1 */
-+ Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x1b8, dword); /* L3 Control 1 */
-+
-+ /* Fam15h BKDG section 2.10.5.5.1 */
-+ dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */
-+ dword &= ~(0xf << 24); /* TrdrdSdSc = 0xb */
-+ dword |= (0xb << 24);
-+ dword &= ~(0xf << 16); /* TrdrdSdDc = 0xb */
-+ dword |= (0xb << 16);
-+ dword &= ~(0xf); /* TrdrdDd = 0xb */
-+ dword |= 0xb;
-+ Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */
-+
-+ /* Fam15h BKDG section 2.10.5.5.2 */
-+ dword = Get_NB32_DCT(dev, dct, 0x214); /* DRAM Timing 4 */
-+ dword &= ~(0xf << 16); /* TwrwrSdSc = 0xb */
-+ dword |= (0xb << 16);
-+ dword &= ~(0xf << 8); /* TwrwrSdDc = 0xb */
-+ dword |= (0xb << 8);
-+ dword &= ~(0xf); /* TwrwrDd = 0xb */
-+ dword |= 0xb;
-+ Set_NB32_DCT(dev, dct, 0x214, dword); /* DRAM Timing 4 */
-+
-+ /* Fam15h BKDG section 2.10.5.5.3 */
-+ dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */
-+ dword &= ~(0xf << 8); /* Twrrd = 0xb */
-+ dword |= (0xb << 8);
-+ Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */
-+
-+ /* Fam15h BKDG section 2.10.5.5.4 */
-+ dword = Get_NB32_DCT(dev, dct, 0x21c); /* DRAM Timing 6 */
-+ dword &= ~(0x1f << 8); /* TrwtTO = 0x16 */
-+ dword |= (0x16 << 8);
-+ dword &= ~(0x1f << 16); /* TrwtWB = TrwtTO + 1 */
-+ dword |= ((((dword >> 8) & 0x1f) + 1) << 16);
-+ Set_NB32_DCT(dev, dct, 0x21c, dword); /* DRAM Timing 6 */
-+ } else {
-+ /* Disable training mode */
-+ uint8_t lane;
-+ uint8_t dimm;
-+ uint8_t receiver;
-+ uint8_t max_lane;
-+ uint8_t ecc_enabled;
-+ uint8_t x4_present = 0;
-+ uint8_t x8_present = 0;
-+ uint8_t memclk_index;
-+ uint8_t interleave_channels = 0;
-+ uint8_t redirect_ecc_scrub = 0;
-+ uint16_t trdrdsddc;
-+ uint16_t trdrddd;
-+ uint16_t cdd_trdrddd;
-+ uint16_t twrwrsddc;
-+ uint16_t twrwrdd;
-+ uint16_t cdd_twrwrdd;
-+ uint16_t twrrd;
-+ uint16_t trwtto;
-+ uint8_t first_dimm;
-+ uint16_t delay;
-+ uint16_t delay2;
-+ uint8_t read_odt_delay;
-+ uint8_t write_odt_delay;
-+ uint16_t difference;
-+ uint16_t current_total_delay_1[MAX_BYTE_LANES];
-+ uint16_t current_total_delay_2[MAX_BYTE_LANES];
-+
-+ /* FIXME
-+ * This should be platform configurable
-+ */
-+ uint8_t dimm_event_l_pin_support = 0;
-+
-+ ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
-+ if (ecc_enabled)
-+ max_lane = 9;
-+ else
-+ max_lane = 8;
-+
-+ if (pDCTstat->Dimmx4Present & ((dct)?0xaa:0x55))
-+ x4_present = 1;
-+ if (pDCTstat->Dimmx8Present & ((dct)?0xaa:0x55))
-+ x8_present = 1;
-+ memclk_index = Get_NB32_DCT(dev, dct, 0x94) & 0x1f;
-+
-+ if (pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1] && mctGet_NVbits(NV_Unganged))
-+ interleave_channels = 1;
-+
-+ if ((pMCTstat->GStatus & 1 << GSB_ECCDIMMs) && mctGet_NVbits(NV_ECCRedir))
-+ redirect_ecc_scrub = 1;
-+
-+ dword = (Get_NB32_DCT(dev, dct, 0x240) >> 4) & 0xf;
-+ if (dword > 6)
-+ read_odt_delay = dword - 6;
-+ else
-+ read_odt_delay = 0;
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x240);
-+ delay = (dword >> 4) & 0xf;
-+ if (delay > 6)
-+ read_odt_delay = delay - 6;
-+ else
-+ read_odt_delay = 0;
-+ delay = (dword >> 12) & 0x7;
-+ if (delay > 6)
-+ write_odt_delay = delay - 6;
-+ else
-+ write_odt_delay = 0;
-+
-+ /* TODO:
-+ * Adjust trdrdsddc if four-rank DIMMs are installed per
-+ * section 2.10.5.5.1 of the Family 15h BKDG.
-+ * cdd_trdrdsddc will also need to be calculated in that process.
-+ */
-+ trdrdsddc = 3;
-+
-+ /* Calculate the Critical Delay Difference for TrdrdDd */
-+ cdd_trdrddd = 0;
-+ first_dimm = 1;
-+ for (receiver = 0; receiver < 8; receiver += 2) {
-+ dimm = (receiver >> 1);
-+
-+ if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, receiver))
-+ continue;
-+
-+ read_dqs_receiver_enable_control_registers(current_total_delay_2, dev, dct, dimm, index_reg);
-+
-+ if (first_dimm) {
-+ memcpy(current_total_delay_1, current_total_delay_2, sizeof(current_total_delay_1));
-+ first_dimm = 0;
-+ }
-+
-+ for (lane = 0; lane < max_lane; lane++) {
-+ if (current_total_delay_1[lane] > current_total_delay_2[lane])
-+ difference = current_total_delay_1[lane] - current_total_delay_2[lane];
-+ else
-+ difference = current_total_delay_2[lane] - current_total_delay_1[lane];
-+
-+ if (difference > cdd_trdrddd)
-+ cdd_trdrddd = difference;
-+ }
-+ }
-+
-+ /* Convert the difference to MEMCLKs */
-+ cdd_trdrddd = (((cdd_trdrddd >> 5) & 0x1f) + 1) / 2;
-+
-+ /* Calculate Trdrddd */
-+ delay = (read_odt_delay + 3) * 2;
-+ delay2 = cdd_trdrddd + 7;
-+ if (delay2 > delay)
-+ delay = delay2;
-+ trdrddd = (delay + 1) / 2; /* + 1 is equivalent to ceiling function here */
-+ if (trdrdsddc > trdrddd)
-+ trdrddd = trdrdsddc;
-+
-+ /* TODO:
-+ * Adjust twrwrsddc if four-rank DIMMs are installed per
-+ * section 2.10.5.5.1 of the Family 15h BKDG.
-+ * cdd_twrwrsddc will also need to be calculated in that process.
-+ */
-+ twrwrsddc = 4;
-+
-+ /* Calculate the Critical Delay Difference for TwrwrDd */
-+ cdd_twrwrdd = 0;
-+ first_dimm = 1;
-+ for (receiver = 0; receiver < 8; receiver += 2) {
-+ dimm = (receiver >> 1);
-+
-+ if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, receiver))
-+ continue;
-+
-+ read_dqs_write_timing_control_registers(current_total_delay_2, dev, dct, dimm, index_reg);
-+
-+ if (first_dimm) {
-+ memcpy(current_total_delay_1, current_total_delay_2, sizeof(current_total_delay_1));
-+ first_dimm = 0;
-+ }
-+
-+ for (lane = 0; lane < max_lane; lane++) {
-+ if (current_total_delay_1[lane] > current_total_delay_2[lane])
-+ difference = current_total_delay_1[lane] - current_total_delay_2[lane];
-+ else
-+ difference = current_total_delay_2[lane] - current_total_delay_1[lane];
-+
-+ if (difference > cdd_twrwrdd)
-+ cdd_twrwrdd = difference;
-+ }
-+ }
-+
-+ /* Convert the difference to MEMCLKs */
-+ cdd_twrwrdd = (((cdd_twrwrdd >> 5) & 0x1f) + 1) / 2;
-+
-+ /* Calculate Twrwrdd */
-+ delay = (write_odt_delay + 3) * 2;
-+ delay2 = cdd_twrwrdd + 7;
-+ if (delay2 > delay)
-+ delay = delay2;
-+ twrwrdd = (delay + 1) / 2; /* + 1 is equivalent to ceiling function here */
-+ if (twrwrsddc > twrwrdd)
-+ twrwrdd = twrwrsddc;
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x78); /* DRAM Control */
-+ dword |= (0x1 << 17); /* AddrCmdTriEn = 1 */
-+ Set_NB32_DCT(dev, dct, 0x78, dword); /* DRAM Control */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */
-+ dword &= ~(0x1 << 18); /* DisAutoRefresh = 0 */
-+ Set_NB32_DCT(dev, dct, 0x8c, dword); /* DRAM Timing High */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x94); /* DRAM Configuration High */
-+ dword |= (0xf << 24); /* DcqBypassMax = 0xf */
-+ dword |= (0x1 << 22); /* BankSwizzleMode = 1 */
-+ dword |= (0x1 << 15); /* PowerDownEn = 1 */
-+ dword &= ~(0x3 << 10); /* ZqcsInterval = 0x2 */
-+ dword |= (0x2 << 10);
-+ Set_NB32_DCT(dev, dct, 0x94, dword); /* DRAM Configuration High */
-+
-+ if (x4_present && x8_present) {
-+ /* Mixed channel of 4x and 8x DIMMs */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d);
-+ dword &= ~(0x3 << 24); /* RxDLLWakeupTime = 0 */
-+ dword &= ~(0x7 << 20); /* RxCPUpdPeriod = 0 */
-+ dword &= ~(0xf << 16); /* RxMaxDurDllNoLock = 0 */
-+ dword &= ~(0x3 << 8); /* TxDLLWakeupTime = 0 */
-+ dword &= ~(0x7 << 4); /* TxCPUpdPeriod = 0 */
-+ dword &= ~(0xf); /* TxMaxDurDllNoLock = 0 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d, dword);
-+ } else {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d);
-+ dword &= ~(0x3 << 24); /* RxDLLWakeupTime = 3 */
-+ dword |= (0x3 << 24);
-+ dword &= ~(0x7 << 20); /* RxCPUpdPeriod = 3 */
-+ dword |= (0x3 << 20);
-+ dword &= ~(0xf << 16); /* RxMaxDurDllNoLock = 7 */
-+ dword |= (0x7 << 16);
-+ dword &= ~(0x3 << 8); /* TxDLLWakeupTime = 3 */
-+ dword |= (0x3 << 8);
-+ dword &= ~(0x7 << 4); /* TxCPUpdPeriod = 3 */
-+ dword |= (0x3 << 4);
-+ dword &= ~(0xf); /* TxMaxDurDllNoLock = 7 */
-+ dword |= 0x7;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d, dword);
-+ }
-+
-+ if ((memclk_index <= 0x12) && (x4_present != x8_present)) {
-+ /* MemClkFreq <= 800MHz
-+ * Not a mixed channel of x4 and x8 DIMMs
-+ */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8));
-+ dword |= (0x1 << 12); /* EnRxPadStandby = 1 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8), dword);
-+ }
-+ } else {
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8));
-+ dword &= ~(0x1 << 12); /* EnRxPadStandby = 0 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8), dword);
-+ }
-+ }
-+
-+ /* TODO
-+ * Calculate Twrrd per section 2.10.5.5.3 of the Family 15h BKDG
-+ */
-+ twrrd = 0xb;
-+
-+ /* TODO
-+ * Calculate TrwtTO per section 2.10.5.5.4 of the Family 15h BKDG
-+ */
-+ trwtto = 0x16;
-+
-+ dword = Get_NB32_DCT(dev, dct, 0xa4); /* DRAM Controller Temperature Throttle */
-+ dword &= ~(0x1 << 11); /* BwCapEn = 0 */
-+ dword &= ~(0x1 << 8); /* ODTSEn = dimm_event_l_pin_support */
-+ dword |= (dimm_event_l_pin_support & 0x1) << 8;
-+ Set_NB32_DCT(dev, dct, 0xa4, dword); /* DRAM Controller Temperature Throttle */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x110); /* DRAM Controller Select Low */
-+ dword &= ~(0x1 << 2); /* DctSelIntLvEn = interleave_channels */
-+ dword |= (interleave_channels & 0x1) << 2;
-+ Set_NB32_DCT(dev, dct, 0x110, dword); /* DRAM Controller Select Low */
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x58); /* Scrub Rate Control */
-+ dword &= ~(0x1f << 24); /* L3Scrub = NV_L3BKScrub */
-+ dword |= (mctGet_NVbits(NV_L3BKScrub) & 0x1f) << 24;
-+ dword &= ~(0x1f); /* DramScrub = NV_DramBKScrub */
-+ dword |= mctGet_NVbits(NV_DramBKScrub) & 0x1f;
-+ Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x58, dword); /* Scrub Rate Control */
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x5c); /* DRAM Scrub Address Low */
-+ dword &= ~(0x1); /* ScrubReDirEn = redirect_ecc_scrub */
-+ dword |= redirect_ecc_scrub & 0x1;
-+ Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x5c, dword); /* DRAM Scrub Address Low */
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x1b8); /* L3 Control 1 */
-+ dword &= ~(0x1 << 4); /* L3ScrbRedirDis = 0 */
-+ Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x1b8, dword); /* L3 Control 1 */
-+
-+ /* FIXME
-+ * The BKDG-recommended settings cause memory corruption on the ASUS KGPE-D16.
-+ * Investigate and fix...
-+ */
-+#if 0
-+ /* Fam15h BKDG section 2.10.5.5.1 */
-+ dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */
-+ dword &= ~(0xf << 24); /* TrdrdSdSc = 0x1 */
-+ dword |= (0x1 << 24);
-+ dword &= ~(0xf << 16); /* TrdrdSdDc = trdrdsddc */
-+ dword |= ((trdrdsddc & 0xf) << 16);
-+ dword &= ~(0xf); /* TrdrdDd = trdrddd */
-+ dword |= (trdrddd & 0xf);
-+ Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */
-+#endif
-+
-+ /* Fam15h BKDG section 2.10.5.5.2 */
-+ dword = Get_NB32_DCT(dev, dct, 0x214); /* DRAM Timing 4 */
-+ dword &= ~(0xf << 16); /* TwrwrSdSc = 0x1 */
-+ dword |= (0x1 << 16);
-+ dword &= ~(0xf << 8); /* TwrwrSdDc = twrwrsddc */
-+ dword |= ((twrwrsddc & 0xf) << 8);
-+ dword &= ~(0xf); /* TwrwrDd = twrwrdd */
-+ dword |= (twrwrdd & 0xf);
-+ Set_NB32_DCT(dev, dct, 0x214, dword); /* DRAM Timing 4 */
-+
-+ /* Fam15h BKDG section 2.10.5.5.3 */
-+ dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */
-+ dword &= ~(0xf << 8); /* Twrrd = twrrd */
-+ dword |= ((twrrd & 0xf) << 8);
-+ Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */
-+
-+ /* Fam15h BKDG section 2.10.5.5.4 */
-+ dword = Get_NB32_DCT(dev, dct, 0x21c); /* DRAM Timing 6 */
-+ dword &= ~(0x1f << 8); /* TrwtTO = trwtto */
-+ dword |= ((trwtto & 0x1f) << 8);
-+ dword &= ~(0x1f << 16); /* TrwtWB = TrwtTO + 1 */
-+ dword |= ((((dword >> 8) & 0x1f) + 1) << 16);
-+ Set_NB32_DCT(dev, dct, 0x21c, dword); /* DRAM Timing 6 */
-+
-+ /* Enable prefetchers */
-+ dword = Get_NB32_DCT(dev, dct, 0x110); /* Memory Controller Configuration High */
-+ dword &= ~(0x1 << 13); /* PrefIoDis = 0 */
-+ dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */
-+ Set_NB32_DCT(dev, dct, 0x110, dword); /* Memory Controller Configuration High */
-+ }
-+}
-+
-+static void exit_training_mode_fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstatA)
-+{
-+ uint8_t node;
-+ uint8_t dct;
-+
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + node;
-+
-+ if (pDCTstat->NodePresent)
-+ for (dct = 0; dct < 2; dct++)
-+ fam15EnableTrainingMode(pMCTstat, pDCTstat, dct, 0);
-+ }
-+}
-+
- static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA)
- {
-@@ -424,6 +1826,20 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
- mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);
- phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
-
-+ if (is_fam15h()) {
-+ uint8_t Node;
-+ struct DCTStatStruc *pDCTstat;
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ pDCTstat = pDCTstatA + Node;
-+ if (pDCTstat->NodePresent) {
-+ if (pDCTstat->DIMMValidDCT[0])
-+ InitPhyCompensation(pMCTstat, pDCTstat, 0);
-+ if (pDCTstat->DIMMValidDCT[1])
-+ InitPhyCompensation(pMCTstat, pDCTstat, 1);
-+ }
-+ }
-+ }
-+
- if (nv_DQSTrainCTL) {
- mctHookBeforeAnyTraining(pMCTstat, pDCTstatA);
- /* TODO: should be in mctHookBeforeAnyTraining */
-@@ -431,16 +1847,35 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
- _WRMSR(0x26D, 0x04040404, 0x04040404);
- _WRMSR(0x26E, 0x04040404, 0x04040404);
- _WRMSR(0x26F, 0x04040404, 0x04040404);
-- mct_WriteLevelization_HW(pMCTstat, pDCTstatA);
-+ mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass);
-
-- TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
-+ if (is_fam15h()) {
-+ /* Receiver Enable Training Pass 1 */
-+ TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
-+ }
-
-- mct_TrainDQSPos_D(pMCTstat, pDCTstatA);
-+ mct_WriteLevelization_HW(pMCTstat, pDCTstatA, SecondPass);
-+
-+ if (is_fam15h()) {
-+ /* Receiver Enable Training Pass 2 */
-+ // TrainReceiverEn_D(pMCTstat, pDCTstatA, SecondPass);
-+
-+ /* TODO:
-+ * Determine why running TrainReceiverEn_D in SecondPass
-+ * mode yields less stable training values than when run
-+ * in FirstPass mode as in the HACK below.
-+ */
-+ TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
-+ } else {
-+ TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
-+ }
-
-- /* Second Pass never used for Barcelona! */
-- /* TrainReceiverEn_D(pMCTstat, pDCTstatA, SecondPass); */
-+ mct_TrainDQSPos_D(pMCTstat, pDCTstatA);
-
-- mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA);
-+ if (is_fam15h())
-+ exit_training_mode_fam15(pMCTstat, pDCTstatA);
-+ else
-+ mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA);
-
- /* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */
- mctHookAfterAnyTraining();
-@@ -476,7 +1911,7 @@ static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
- for (Channel = 0;Channel < 2; Channel++) {
- /* there are four receiver pairs,
- loosely associated with chipselects.*/
-- index_reg = 0x98 + Channel * 0x100;
-+ index_reg = 0x98;
- for (Receiver = 0; Receiver < 8; Receiver += 2) {
- /* Set Receiver Enable Values */
- mct_SetRcvrEnDly_D(pDCTstat,
-@@ -492,7 +1927,7 @@ static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
- txdqs = pDCTstat->CH_D_B_TxDqs[Channel][Receiver >> 1][ByteLane];
- index = Table_DQSRcvEn_Offset[ByteLane >> 1];
- index += (Receiver >> 1) * 3 + 0x10 + 0x20; /* Addl_Index */
-- val = Get_NB32_index_wait(dev, 0x98 + 0x100*Channel, index);
-+ val = Get_NB32_index_wait_DCT(dev, Channel, 0x98, index);
- if (ByteLane & 1) { /* odd byte lane */
- val &= ~(0xFF << 16);
- val |= txdqs << 16;
-@@ -500,7 +1935,7 @@ static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
- val &= ~0xFF;
- val |= txdqs;
- }
-- Set_NB32_index_wait(dev, 0x98 + 0x100*Channel, index, val);
-+ Set_NB32_index_wait_DCT(dev, Channel, 0x98, index, val);
- }
- }
- }
-@@ -510,7 +1945,7 @@ static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
-
- for (Channel = 0; Channel < 2; Channel++) {
- u8 *p;
-- index_reg = 0x98 + Channel * 0x100;
-+ index_reg = 0x98;
-
- /* NOTE:
- * when 400, 533, 667, it will support dimm0/1/2/3,
-@@ -525,7 +1960,7 @@ static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
- if (DIMM == 0) {
- index = 0; /* CHA Write Data Timing Low */
- } else {
-- if (pDCTstat->Speed >= 4) {
-+ if (pDCTstat->Speed >= mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
- index = 0x100 * DIMM;
- } else {
- break;
-@@ -534,23 +1969,23 @@ static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
- for (Dir = 0; Dir < 2; Dir++) {/* RD/WR */
- p = pDCTstat->CH_D_DIR_B_DQS[Channel][DIMM][Dir];
- val = stream_to_int(p); /* CHA Read Data Timing High */
-- Set_NB32_index_wait(dev, index_reg, index+1, val);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+1, val);
- val = stream_to_int(p+4); /* CHA Write Data Timing High */
-- Set_NB32_index_wait(dev, index_reg, index+2, val);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+2, val);
- val = *(p+8); /* CHA Write ECC Timing */
-- Set_NB32_index_wait(dev, index_reg, index+3, val);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+3, val);
- index += 4;
- }
- }
- }
-
- for (Channel = 0; Channel<2; Channel++) {
-- reg = 0x78 + Channel * 0x100;
-- val = Get_NB32(dev, reg);
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, Channel, reg);
- val &= ~(0x3ff<<22);
- val |= ((u32) pDCTstat->CH_MaxRdLat[Channel] << 22);
- val &= ~(1<<DqsRcvEnTrain);
-- Set_NB32(dev, reg, val); /* program MaxRdLatency to correspond with current delay*/
-+ Set_NB32_DCT(dev, Channel, reg, val); /* program MaxRdLatency to correspond with current delay*/
- }
- }
- }
-@@ -812,49 +2247,70 @@ finish:
- return ret;
- }
-
--static void DCTInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct)
-+static void DCTPreInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct)
- {
- /*
-- * Initialize DRAM on single Athlon 64/Opteron Node.
-+ * Run DCT pre-initialization tasks
- */
-- u8 stopDCTflag;
-- u32 val;
-+ uint32_t dword;
-
-+ /* Reset DCT registers */
- ClearDCT_D(pMCTstat, pDCTstat, dct);
-- stopDCTflag = 1; /*preload flag with 'disable' */
-- /* enable DDR3 support */
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + dct * 0x100);
-- val |= 1 << Ddr3Mode;
-- Set_NB32(pDCTstat->dev_dct, 0x94 + dct * 0x100, val);
-+ pDCTstat->stopDCT = 1; /*preload flag with 'disable' */
-+
-+ if (!is_fam15h()) {
-+ /* Enable DDR3 support */
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94);
-+ dword |= 1 << Ddr3Mode;
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword);
-+ }
-+
-+ /* Read the SPD information into the data structures */
- if (mct_DIMMPresence(pMCTstat, pDCTstat, dct) < SC_StopError) {
- printk(BIOS_DEBUG, "\t\tDCTInit_D: mct_DIMMPresence Done\n");
-- if (mct_SPDCalcWidth(pMCTstat, pDCTstat, dct) < SC_StopError) {
-- printk(BIOS_DEBUG, "\t\tDCTInit_D: mct_SPDCalcWidth Done\n");
-- if (AutoCycTiming_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
-- printk(BIOS_DEBUG, "\t\tDCTInit_D: AutoCycTiming_D Done\n");
-- if (AutoConfig_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
-- printk(BIOS_DEBUG, "\t\tDCTInit_D: AutoConfig_D Done\n");
-- if (PlatformSpec_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
-- printk(BIOS_DEBUG, "\t\tDCTInit_D: PlatformSpec_D Done\n");
-- stopDCTflag = 0;
-- if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) {
-- printk(BIOS_DEBUG, "\t\tDCTInit_D: StartupDCT_D\n");
-- StartupDCT_D(pMCTstat, pDCTstat, dct); /*yeaahhh! */
-- }
-+ }
-+}
-+
-+static void DCTInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct)
-+{
-+ /*
-+ * Initialize DRAM on single Athlon 64/Opteron Node.
-+ */
-+ uint32_t dword;
-+
-+ if (!is_fam15h()) {
-+ /* (Re)-enable DDR3 support */
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94);
-+ dword |= 1 << Ddr3Mode;
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword);
-+ }
-+
-+ if (mct_SPDCalcWidth(pMCTstat, pDCTstat, dct) < SC_StopError) {
-+ printk(BIOS_DEBUG, "\t\tDCTInit_D: mct_SPDCalcWidth Done\n");
-+ if (AutoCycTiming_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
-+ printk(BIOS_DEBUG, "\t\tDCTInit_D: AutoCycTiming_D Done\n");
-+ if (AutoConfig_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
-+ printk(BIOS_DEBUG, "\t\tDCTInit_D: AutoConfig_D Done\n");
-+ if (PlatformSpec_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
-+ printk(BIOS_DEBUG, "\t\tDCTInit_D: PlatformSpec_D Done\n");
-+ pDCTstat->stopDCT = 0;
-+ if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) {
-+ printk(BIOS_DEBUG, "\t\tDCTInit_D: StartupDCT_D\n");
-+ StartupDCT_D(pMCTstat, pDCTstat, dct); /*yeaahhh! */
- }
- }
- }
- }
- }
-
-- if (stopDCTflag) {
-- u32 reg_off = dct * 0x100;
-- val = 1<<DisDramInterface;
-- Set_NB32(pDCTstat->dev_dct, reg_off+0x94, val);
-- /*To maximize power savings when DisDramInterface=1b,
-- all of the MemClkDis bits should also be set.*/
-- val = 0xFF000000;
-- Set_NB32(pDCTstat->dev_dct, reg_off+0x88, val);
-+ if (pDCTstat->stopDCT) {
-+ dword = 1 << DisDramInterface;
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword);
-+
-+ /* To maximize power savings when DisDramInterface=1b,
-+ * all of the MemClkDis bits should also be set.
-+ */
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x88, 0xff000000);
- } else {
- mct_EnDllShutdownSR(pMCTstat, pDCTstat, dct);
- }
-@@ -876,20 +2332,24 @@ static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
- pDCTstat = pDCTstatA + Node;
- mct_SyncDCTsReady(pDCTstat);
- }
-- /* v6.1.3 */
-- /* re-enable phy compensation engine when dram init is completed on all nodes. */
-- for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-- struct DCTStatStruc *pDCTstat;
-- pDCTstat = pDCTstatA + Node;
-- if (pDCTstat->NodePresent) {
-- if (pDCTstat->DIMMValidDCT[0] > 0 || pDCTstat->DIMMValidDCT[1] > 0) {
-- /* re-enable phy compensation engine when dram init on both DCTs is completed. */
-- val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98, 0x8);
-- val &= ~(1 << DisAutoComp);
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98, 0x8, val);
-+
-+ if (!is_fam15h()) {
-+ /* v6.1.3 */
-+ /* re-enable phy compensation engine when dram init is completed on all nodes. */
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+ if (pDCTstat->NodePresent) {
-+ if (pDCTstat->DIMMValidDCT[0] > 0 || pDCTstat->DIMMValidDCT[1] > 0) {
-+ /* re-enable phy compensation engine when dram init on both DCTs is completed. */
-+ val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98, 0x8);
-+ val &= ~(1 << DisAutoComp);
-+ Set_NB32_index_wait(pDCTstat->dev_dct, 0x98, 0x8, val);
-+ }
- }
- }
- }
-+
- /* wait 750us before any memory access can be made. */
- mct_Wait(15000);
- }
-@@ -911,10 +2371,9 @@ static void StartupDCT_D(struct MCTStatStruc *pMCTstat,
- */
- u32 val;
- u32 dev;
-- u32 reg_off = dct * 0x100;
-
- dev = pDCTstat->dev_dct;
-- val = Get_NB32(dev, 0x94 + reg_off);
-+ val = Get_NB32_DCT(dev, dct, 0x94);
- if (val & (1<<MemClkFreqVal)) {
- mctHookBeforeDramInit(); /* generalized Hook */
- if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)))
-@@ -929,23 +2388,23 @@ static void ClearDCT_D(struct MCTStatStruc *pMCTstat,
- {
- u32 reg_end;
- u32 dev = pDCTstat->dev_dct;
-- u32 reg = 0x40 + 0x100 * dct;
-+ u32 reg = 0x40;
- u32 val = 0;
-
- if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
-- reg_end = 0x78 + 0x100 * dct;
-+ reg_end = 0x78;
- } else {
-- reg_end = 0xA4 + 0x100 * dct;
-+ reg_end = 0xA4;
- }
-
- while(reg < reg_end) {
- if ((reg & 0xFF) == 0x90) {
- if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
-- val = Get_NB32(dev, reg); /* get DRAMConfigLow */
-+ val = Get_NB32_DCT(dev, dct, reg); /* get DRAMConfigLow */
- val |= 0x08000000; /* preserve value of DisDllShutdownSR for only Rev.D */
- }
- }
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- val = 0;
- reg += 4;
- }
-@@ -964,6 +2423,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
- u16 Trp, Trrd, Trcd, Tras, Trc;
- u8 Trfc[4];
- u16 Tfaw;
-+ u16 Tcwl; /* Fam15h only */
- u32 DramTimingLo, DramTimingHi;
- u8 tCK16x;
- u16 Twtr;
-@@ -972,10 +2432,11 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
- u8 byte;
- u32 dword;
- u32 dev;
-- u32 reg_off;
- u32 val;
- u16 smbaddr;
-
-+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
-+
- /* Gather all DIMM mini-max values for cycle timing data */
- Trp = 0;
- Trrd = 0;
-@@ -1188,88 +2649,164 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
-
- mctAdjustAutoCycTmg_D();
-
-+ if (is_fam15h()) {
-+ /* Compute Tcwl (Fam15h BKDG v3.14 Table 203) */
-+ if (pDCTstat->Speed <= 0x6)
-+ Tcwl = 0x5;
-+ else if (pDCTstat->Speed == 0xa)
-+ Tcwl = 0x6;
-+ else if (pDCTstat->Speed == 0xe)
-+ Tcwl = 0x7;
-+ else if (pDCTstat->Speed == 0x12)
-+ Tcwl = 0x8;
-+ else if (pDCTstat->Speed == 0x16)
-+ Tcwl = 0x9;
-+ else
-+ Tcwl = 0x5; /* Power-on default */
-+ }
-+
- /* Program DRAM Timing values */
-- DramTimingLo = 0; /* Dram Timing Low init */
-- val = pDCTstat->CASL - 4; /* pDCTstat.CASL to reg. definition */
-- DramTimingLo |= val;
-+ if (is_fam15h()) {
-+ dev = pDCTstat->dev_dct;
-
-- val = pDCTstat->Trcd - Bias_TrcdT;
-- DramTimingLo |= val<<4;
-+ dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */
-+ val = 2; /* Tref = 7.8us */
-+ dword &= ~(0x3 << 16);
-+ dword |= (val & 0x3) << 16;
-+ Set_NB32_DCT(dev, dct, 0x8c, dword); /* DRAM Timing High */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x200); /* DRAM Timing 0 */
-+ dword &= ~(0x3f1f1f1f);
-+ dword |= ((pDCTstat->Tras + 0xf) & 0x3f) << 24; /* Tras */
-+ dword |= ((pDCTstat->Trp + 0x5) & 0x1f) << 16; /* Trp */
-+ dword |= ((pDCTstat->Trcd + 0x5) & 0x1f) << 8; /* Trcd */
-+ dword |= (pDCTstat->CASL & 0x1f); /* Tcl */
-+ Set_NB32_DCT(dev, dct, 0x200, dword); /* DRAM Timing 0 */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x204); /* DRAM Timing 1 */
-+ dword &= ~(0x0f3f0f3f);
-+ dword |= ((pDCTstat->Trtp + 0x4) & 0xf) << 24; /* Trtp */
-+ if (pDCTstat->Tfaw != 0)
-+ dword |= ((((pDCTstat->Tfaw - 0x1) * 2) + 0x10) & 0x3f) << 16; /* FourActWindow */
-+ dword |= ((pDCTstat->Trrd + 0x4) & 0xf) << 8; /* Trrd */
-+ dword |= ((pDCTstat->Trc + 0xb) & 0x3f); /* Trc */
-+ Set_NB32_DCT(dev, dct, 0x204, dword); /* DRAM Timing 1 */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x208); /* DRAM Timing 2 */
-+ dword &= ~(0x07070707);
-+ dword |= (pDCTstat->Trfc[3] & 0x7) << 24; /* Trfc3 */
-+ dword |= (pDCTstat->Trfc[2] & 0x7) << 16; /* Trfc2 */
-+ dword |= (pDCTstat->Trfc[1] & 0x7) << 8; /* Trfc1 */
-+ dword |= (pDCTstat->Trfc[0] & 0x7); /* Trfc0 */
-+ Set_NB32_DCT(dev, dct, 0x208, dword); /* DRAM Timing 2 */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x20c); /* DRAM Timing 3 */
-+ dword &= ~(0x00000f00);
-+ dword |= ((pDCTstat->Twtr + 0x4) & 0xf) << 8; /* Twtr */
-+ dword &= ~(0x0000001f);
-+ dword |= (Tcwl & 0x1f); /* Tcwl */
-+ Set_NB32_DCT(dev, dct, 0x20c, dword); /* DRAM Timing 3 */
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x22c); /* DRAM Timing 10 */
-+ dword &= ~(0x0000001f);
-+ dword |= ((pDCTstat->Twr + 0x4) & 0x1f); /* Twr */
-+ Set_NB32_DCT(dev, dct, 0x22c, dword); /* DRAM Timing 10 */
-+
-+ if (pDCTstat->Speed > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
-+ /* Enable phy-assisted training mode */
-+ fam15EnableTrainingMode(pMCTstat, pDCTstat, dct, 1);
-+ }
-
-- val = pDCTstat->Trp - Bias_TrpT;
-- val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val);
-- DramTimingLo |= val<<7;
-+ /* Other setup (not training specific) */
-+ dword = Get_NB32_DCT(dev, dct, 0x90); /* DRAM Configuration Low */
-+ dword &= ~(0x1 << 23); /* ForceAutoPchg = 0 */
-+ dword &= ~(0x1 << 20); /* DynPageCloseEn = 0 */
-+ Set_NB32_DCT(dev, dct, 0x90, dword); /* DRAM Configuration Low */
-
-- val = pDCTstat->Trtp - Bias_TrtpT;
-- DramTimingLo |= val<<10;
-+ Set_NB32_DCT(dev, dct, 0x228, 0x14141414); /* DRAM Timing 9 */
-+ } else {
-+ DramTimingLo = 0; /* Dram Timing Low init */
-+ val = pDCTstat->CASL - 4; /* pDCTstat.CASL to reg. definition */
-+ DramTimingLo |= val;
-
-- val = pDCTstat->Tras - Bias_TrasT;
-- DramTimingLo |= val<<12;
-+ val = pDCTstat->Trcd - Bias_TrcdT;
-+ DramTimingLo |= val<<4;
-
-- val = pDCTstat->Trc - Bias_TrcT;
-- DramTimingLo |= val<<16;
-+ val = pDCTstat->Trp - Bias_TrpT;
-+ val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val);
-+ DramTimingLo |= val<<7;
-
-- val = pDCTstat->Trrd - Bias_TrrdT;
-- DramTimingLo |= val<<22;
-+ val = pDCTstat->Trtp - Bias_TrtpT;
-+ DramTimingLo |= val<<10;
-
-- DramTimingHi = 0; /* Dram Timing High init */
-- val = pDCTstat->Twtr - Bias_TwtrT;
-- DramTimingHi |= val<<8;
-+ val = pDCTstat->Tras - Bias_TrasT;
-+ DramTimingLo |= val<<12;
-
-- val = 2;
-- DramTimingHi |= val<<16;
-+ val = pDCTstat->Trc - Bias_TrcT;
-+ DramTimingLo |= val<<16;
-
-- val = 0;
-- for (i=4;i>0;i--) {
-- val <<= 3;
-- val |= Trfc[i-1];
-- }
-- DramTimingHi |= val << 20;
-+ val = pDCTstat->Trrd - Bias_TrrdT;
-+ DramTimingLo |= val<<22;
-
-- dev = pDCTstat->dev_dct;
-- reg_off = 0x100 * dct;
-- /* Twr */
-- val = pDCTstat->Twr;
-- if (val == 10)
-- val = 9;
-- else if (val == 12)
-- val = 10;
-- val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val);
-- val -= Bias_TwrT;
-- val <<= 4;
-- dword = Get_NB32(dev, 0x84 + reg_off);
-- dword &= ~0x70;
-- dword |= val;
-- Set_NB32(dev, 0x84 + reg_off, dword);
-+ DramTimingHi = 0; /* Dram Timing High init */
-+ val = pDCTstat->Twtr - Bias_TwtrT;
-+ DramTimingHi |= val<<8;
-
-- /* Tfaw */
-- val = pDCTstat->Tfaw;
-- val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val);
-- val -= Bias_TfawT;
-- val >>= 1;
-- val <<= 28;
-- dword = Get_NB32(dev, 0x94 + reg_off);
-- dword &= ~0xf0000000;
-- dword |= val;
-- Set_NB32(dev, 0x94 + reg_off, dword);
--
-- /* dev = pDCTstat->dev_dct; */
-- /* reg_off = 0x100 * dct; */
--
-- if (pDCTstat->Speed > 4) {
-- val = Get_NB32(dev, 0x88 + reg_off);
-- val &= 0xFF000000;
-- DramTimingLo |= val;
-- }
-- Set_NB32(dev, 0x88 + reg_off, DramTimingLo); /*DCT Timing Low*/
-+ val = 2; /* Tref = 7.8us */
-+ DramTimingHi |= val<<16;
-+
-+ val = 0;
-+ for (i=4;i>0;i--) {
-+ val <<= 3;
-+ val |= Trfc[i-1];
-+ }
-+ DramTimingHi |= val << 20;
-+
-+ dev = pDCTstat->dev_dct;
-+ /* Twr */
-+ val = pDCTstat->Twr;
-+ if (val == 10)
-+ val = 9;
-+ else if (val == 12)
-+ val = 10;
-+ val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val);
-+ val -= Bias_TwrT;
-+ val <<= 4;
-+ dword = Get_NB32_DCT(dev, dct, 0x84);
-+ dword &= ~0x70;
-+ dword |= val;
-+ Set_NB32_DCT(dev, dct, 0x84, dword);
-+
-+ /* Tfaw */
-+ val = pDCTstat->Tfaw;
-+ val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val);
-+ val -= Bias_TfawT;
-+ val >>= 1;
-+ val <<= 28;
-+ dword = Get_NB32_DCT(dev, dct, 0x94);
-+ dword &= ~0xf0000000;
-+ dword |= val;
-+ Set_NB32_DCT(dev, dct, 0x94, dword);
-+
-+ /* dev = pDCTstat->dev_dct; */
-+
-+ if (pDCTstat->Speed > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
-+ val = Get_NB32_DCT(dev, dct, 0x88);
-+ val &= 0xFF000000;
-+ DramTimingLo |= val;
-+ }
-+ Set_NB32_DCT(dev, dct, 0x88, DramTimingLo); /*DCT Timing Low*/
-
-- if (pDCTstat->Speed > 4) {
-- DramTimingHi |= 1 << DisAutoRefresh;
-+ if (pDCTstat->Speed > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
-+ DramTimingHi |= 1 << DisAutoRefresh;
-+ }
-+ DramTimingHi |= 0x000018FF;
-+ Set_NB32_DCT(dev, dct, 0x8c, DramTimingHi); /*DCT Timing Hi*/
- }
-- DramTimingHi |= 0x000018FF;
-- Set_NB32(dev, 0x8c + reg_off, DramTimingHi); /*DCT Timing Hi*/
-
- /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */
-+
-+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
- }
-
- static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
-@@ -1303,6 +2840,8 @@ static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
- * timing mode is 'Auto'.
- */
-
-+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
-+
- /* Get primary timing (CAS Latency and Cycle Time) */
- if (pDCTstat->Speed == 0) {
- mctGet_MaxLoadFreq(pDCTstat);
-@@ -1312,6 +2851,7 @@ static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
-
- /* Go get best T and CL as specified by DIMM mfgs. and OEM */
- SPDGetTCL_D(pMCTstat, pDCTstat, dct);
-+
- /* skip callback mctForce800to1067_D */
- pDCTstat->Speed = pDCTstat->DIMMAutoSpeed;
- pDCTstat->CASL = pDCTstat->DIMMCASL;
-@@ -1344,7 +2884,10 @@ static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
- u16 word;
-
- /* Get CPU Si Revision defined limit (NPT) */
-- proposedFreq = 800; /* Rev F0 programmable max memclock is */
-+ if (is_fam15h())
-+ proposedFreq = 933;
-+ else
-+ proposedFreq = 800; /* Rev F0 programmable max memclock is */
-
- /*Get User defined limit if "limit" mode */
- if ( mctGet_NVbits(NV_MCTUSRTMGMODE) == 1) {
-@@ -1381,6 +2924,7 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
- u16 tCKmin16x;
- u16 tCKproposed16x;
- u8 CLactual, CLdesired, CLT_Fail;
-+ uint16_t min_frequency_tck16x;
-
- u8 smbaddr, byte = 0, bytex = 0;
-
-@@ -1390,6 +2934,17 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
- tCKmin16x = 0;
- CLT_Fail = 0;
-
-+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
-+
-+ if (is_fam15h()) {
-+ uint16_t minimum_frequency_mhz = mctGet_NVbits(NV_MIN_MEMCLK);
-+ if (minimum_frequency_mhz == 0)
-+ minimum_frequency_mhz = 333;
-+ min_frequency_tck16x = 16000 / minimum_frequency_mhz;
-+ } else {
-+ min_frequency_tck16x = 40;
-+ }
-+
- for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) {
- if (pDCTstat->DIMMValid & (1 << i)) {
- smbaddr = Get_DIMMAddress_D(pDCTstat, (dct + i));
-@@ -1419,27 +2974,44 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
- tCKmin16x = byte * MTB16x;
- }
- }
-- /* calculate tCKproposed16x */
-+ /* calculate tCKproposed16x (proposed clock period in ns * 16) */
- tCKproposed16x = 16000 / pDCTstat->PresetmaxFreq;
- if (tCKmin16x > tCKproposed16x)
- tCKproposed16x = tCKmin16x;
-
-- /* mctHookTwo1333DimmOverride(); */
-- /* For UDIMM, if there are two DDR3-1333 on the same channel,
-- downgrade DDR speed to 1066. */
--
- /* TODO: get user manual tCK16x(Freq.) and overwrite current tCKproposed16x if manual. */
-- if (tCKproposed16x == 20)
-- pDCTstat->TargetFreq = 7;
-- else if (tCKproposed16x <= 24) {
-- pDCTstat->TargetFreq = 6;
-- tCKproposed16x = 24;
-- } else if (tCKproposed16x <= 30) {
-- pDCTstat->TargetFreq = 5;
-- tCKproposed16x = 30;
-+ if (is_fam15h()) {
-+ if (tCKproposed16x == 17)
-+ pDCTstat->TargetFreq = 0x16;
-+ else if (tCKproposed16x <= 20) {
-+ pDCTstat->TargetFreq = 0x12;
-+ tCKproposed16x = 20;
-+ } else if (tCKproposed16x <= 24) {
-+ pDCTstat->TargetFreq = 0xe;
-+ tCKproposed16x = 24;
-+ } else if (tCKproposed16x <= 30) {
-+ pDCTstat->TargetFreq = 0xa;
-+ tCKproposed16x = 30;
-+ } else if (tCKproposed16x <= 40) {
-+ pDCTstat->TargetFreq = 0x6;
-+ tCKproposed16x = 40;
-+ } else {
-+ pDCTstat->TargetFreq = 0x4;
-+ tCKproposed16x = 48;
-+ }
- } else {
-- pDCTstat->TargetFreq = 4;
-- tCKproposed16x = 40;
-+ if (tCKproposed16x == 20)
-+ pDCTstat->TargetFreq = 7;
-+ else if (tCKproposed16x <= 24) {
-+ pDCTstat->TargetFreq = 6;
-+ tCKproposed16x = 24;
-+ } else if (tCKproposed16x <= 30) {
-+ pDCTstat->TargetFreq = 5;
-+ tCKproposed16x = 30;
-+ } else {
-+ pDCTstat->TargetFreq = 4;
-+ tCKproposed16x = 40;
-+ }
- }
- /* Running through this loop twice:
- - First time find tCL at target frequency
-@@ -1478,27 +3050,42 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
- /* get CL and T */
- if (!CLT_Fail) {
- bytex = CLactual;
-- if (tCKproposed16x == 20)
-- byte = 7;
-- else if (tCKproposed16x == 24)
-- byte = 6;
-- else if (tCKproposed16x == 30)
-- byte = 5;
-- else
-- byte = 4;
-+ if (is_fam15h()) {
-+ if (tCKproposed16x == 17)
-+ byte = 0x16;
-+ else if (tCKproposed16x == 20)
-+ byte = 0x12;
-+ else if (tCKproposed16x == 24)
-+ byte = 0xe;
-+ else if (tCKproposed16x == 30)
-+ byte = 0xa;
-+ else if (tCKproposed16x == 40)
-+ byte = 0x6;
-+ else
-+ byte = 0x4;
-+ } else {
-+ if (tCKproposed16x == 20)
-+ byte = 7;
-+ else if (tCKproposed16x == 24)
-+ byte = 6;
-+ else if (tCKproposed16x == 30)
-+ byte = 5;
-+ else
-+ byte = 4;
-+ }
- } else {
- /* mctHookManualCLOverride */
- /* TODO: */
- }
-
-- if (tCKproposed16x != 40) {
-+ if (tCKproposed16x != min_frequency_tck16x) {
- if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
- pDCTstat->DIMMAutoSpeed = byte;
- pDCTstat->DIMMCASL = bytex;
- break;
- } else {
- pDCTstat->TargetCASL = bytex;
-- tCKproposed16x = 40;
-+ tCKproposed16x = min_frequency_tck16x;
- }
- } else {
- pDCTstat->DIMMAutoSpeed = byte;
-@@ -1519,29 +3106,21 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
- static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 dev;
-- u32 reg;
-- u32 val;
-+ if (!is_fam15h()) {
-+ mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct);
-
-- mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct);
-+ if (pDCTstat->GangedMode == 1) {
-+ mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1);
-+ mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1);
-+ }
-
-- if (pDCTstat->GangedMode == 1) {
-- mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1);
-- mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1);
-- }
-+ set_2t_configuration(pMCTstat, pDCTstat, dct);
-
-- if ( pDCTstat->_2Tmode == 2) {
-- dev = pDCTstat->dev_dct;
-- reg = 0x94 + 0x100 * dct; /* Dram Configuration Hi */
-- val = Get_NB32(dev, reg);
-- val |= 1 << 20; /* 2T CMD mode */
-- Set_NB32(dev, reg, val);
-+ mct_BeforePlatformSpec(pMCTstat, pDCTstat, dct);
-+ mct_PlatformSpec(pMCTstat, pDCTstat, dct);
-+ if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK)))
-+ InitPhyCompensation(pMCTstat, pDCTstat, dct);
- }
--
-- mct_BeforePlatformSpec(pMCTstat, pDCTstat, dct);
-- mct_PlatformSpec(pMCTstat, pDCTstat, dct);
-- if (pDCTstat->DIMMAutoSpeed == 4)
-- InitPhyCompensation(pMCTstat, pDCTstat, dct);
- mctHookAfterPSCfg();
-
- return pDCTstat->ErrCode;
-@@ -1553,11 +3132,11 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- u32 DramControl, DramTimingLo, Status;
- u32 DramConfigLo, DramConfigHi, DramConfigMisc, DramConfigMisc2;
- u32 val;
-- u32 reg_off;
- u32 dev;
- u16 word;
- u32 dword;
- u8 byte;
-+ uint32_t offset;
-
- DramConfigLo = 0;
- DramConfigHi = 0;
-@@ -1577,12 +3156,10 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- Status = pDCTstat->Status;
-
- dev = pDCTstat->dev_dct;
-- reg_off = 0x100 * dct;
--
-
- /* Build Dram Control Register Value */
-- DramConfigMisc2 = Get_NB32 (dev, 0xA8 + reg_off); /* Dram Control*/
-- DramControl = Get_NB32 (dev, 0x78 + reg_off); /* Dram Control*/
-+ DramConfigMisc2 = Get_NB32_DCT(dev, dct, 0xA8); /* Dram Control*/
-+ DramControl = Get_NB32_DCT(dev, dct, 0x78); /* Dram Control*/
-
- /* FIXME: Skip mct_checkForDxSupport */
- /* REV_CALL mct_DoRdPtrInit if not Dx */
-@@ -1624,8 +3201,12 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- DramConfigLo = mct_DisDllShutdownSR(pMCTstat, pDCTstat, DramConfigLo, dct);
-
- /* Build Dram Config Hi Register Value */
-+ if (is_fam15h())
-+ offset = 0x0;
-+ else
-+ offset = 0x1;
- dword = pDCTstat->Speed;
-- DramConfigHi |= dword - 1; /* get MemClk encoding */
-+ DramConfigHi |= dword - offset; /* get MemClk encoding */
- DramConfigHi |= 1 << MemClkFreqVal;
-
- if (Status & (1 << SB_Registered))
-@@ -1658,7 +3239,7 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- val = 0x0f; /* recommended setting (default) */
- DramConfigHi |= val << 24;
-
-- if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx | AMD_DR_Bx))
-+ if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx | AMD_DR_Bx | AMD_FAM15_ALL))
- DramConfigHi |= 1 << DcqArbBypassEn;
-
- /* Build MemClkDis Value from Dram Timing Lo and
-@@ -1669,7 +3250,7 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- NV_AllMemClks <>0 AND SB_DiagClks ==0 */
-
- /* Dram Timing Low (owns Clock Enable bits) */
-- DramTimingLo = Get_NB32(dev, 0x88 + reg_off);
-+ DramTimingLo = Get_NB32_DCT(dev, dct, 0x88);
- if (mctGet_NVbits(NV_AllMemClks) == 0) {
- /* Special Jedec SPD diagnostic bit - "enable all clocks" */
- if (!(pDCTstat->Status & (1<<SB_DiagClks))) {
-@@ -1700,28 +3281,34 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- }
- dword++ ;
- }
-+ DramTimingLo &= ~(0xff << 24);
- DramTimingLo |= byte << 24;
- }
- }
-
-- printk(BIOS_DEBUG, "AutoConfig_D: DramControl: %x\n", DramControl);
-- printk(BIOS_DEBUG, "AutoConfig_D: DramTimingLo: %x\n", DramTimingLo);
-- printk(BIOS_DEBUG, "AutoConfig_D: DramConfigMisc: %x\n", DramConfigMisc);
-- printk(BIOS_DEBUG, "AutoConfig_D: DramConfigMisc2: %x\n", DramConfigMisc2);
-- printk(BIOS_DEBUG, "AutoConfig_D: DramConfigLo: %x\n", DramConfigLo);
-- printk(BIOS_DEBUG, "AutoConfig_D: DramConfigHi: %x\n", DramConfigHi);
-+ printk(BIOS_DEBUG, "AutoConfig_D: DramControl: %08x\n", DramControl);
-+ printk(BIOS_DEBUG, "AutoConfig_D: DramTimingLo: %08x\n", DramTimingLo);
-+ printk(BIOS_DEBUG, "AutoConfig_D: DramConfigMisc: %08x\n", DramConfigMisc);
-+ printk(BIOS_DEBUG, "AutoConfig_D: DramConfigMisc2: %08x\n", DramConfigMisc2);
-+ printk(BIOS_DEBUG, "AutoConfig_D: DramConfigLo: %08x\n", DramConfigLo);
-+ printk(BIOS_DEBUG, "AutoConfig_D: DramConfigHi: %08x\n", DramConfigHi);
-
- /* Write Values to the registers */
-- Set_NB32(dev, 0x78 + reg_off, DramControl);
-- Set_NB32(dev, 0x88 + reg_off, DramTimingLo);
-- Set_NB32(dev, 0xA0 + reg_off, DramConfigMisc);
-+ Set_NB32_DCT(dev, dct, 0x78, DramControl);
-+ Set_NB32_DCT(dev, dct, 0x88, DramTimingLo);
-+ Set_NB32_DCT(dev, dct, 0xa0, DramConfigMisc);
- DramConfigMisc2 = mct_SetDramConfigMisc2(pDCTstat, dct, DramConfigMisc2);
-- Set_NB32(dev, 0xA8 + reg_off, DramConfigMisc2);
-- Set_NB32(dev, 0x90 + reg_off, DramConfigLo);
-+ Set_NB32_DCT(dev, dct, 0xa8, DramConfigMisc2);
-+ Set_NB32_DCT(dev, dct, 0x90, DramConfigLo);
- ProgDramMRSReg_D(pMCTstat, pDCTstat, dct);
-- dword = Get_NB32(dev, 0x94 + reg_off);
-+
-+ if (is_fam15h())
-+ InitDDRPhy(pMCTstat, pDCTstat, dct);
-+
-+ /* Write the DRAM Configuration High register, including memory frequency change */
-+ dword = Get_NB32_DCT(dev, dct, 0x94);
- DramConfigHi |= dword;
-- mct_SetDramConfigHi_D(pDCTstat, dct, DramConfigHi);
-+ mct_SetDramConfigHi_D(pMCTstat, pDCTstat, dct, DramConfigHi);
- mct_EarlyArbEn_D(pMCTstat, pDCTstat, dct);
- mctHookAfterAutoCfg();
-
-@@ -1731,6 +3318,7 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
- printk(BIOS_DEBUG, "AutoConfig: ErrStatus %x\n", pDCTstat->ErrStatus);
- printk(BIOS_DEBUG, "AutoConfig: ErrCode %x\n", pDCTstat->ErrCode);
- printk(BIOS_DEBUG, "AutoConfig: Done\n\n");
-+
- AutoConfig_exit:
- return pDCTstat->ErrCode;
- }
-@@ -1748,14 +3336,12 @@ static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat,
- u32 val;
- u32 reg;
- u32 dev;
-- u32 reg_off;
- u8 byte;
- u16 word;
- u32 dword;
- u16 smbaddr;
-
- dev = pDCTstat->dev_dct;
-- reg_off = 0x100 * dct;
-
- BankAddrReg = 0;
- for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel+=2) {
-@@ -1820,10 +3406,10 @@ static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat,
- /*set ChipSelect population indicator odd bits*/
- pDCTstat->CSPresent |= 1 << (ChipSel + 1);
-
-- reg = 0x60+(ChipSel<<1) + reg_off; /*Dram CS Mask Register */
-+ reg = 0x60+(ChipSel<<1); /*Dram CS Mask Register */
- val = csMask;
- val &= 0x1FF83FE0; /* Mask out reserved bits.*/
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- } else {
- if (pDCTstat->DIMMSPDCSE & (1<<ChipSel))
- pDCTstat->CSTestFail |= (1<<ChipSel);
-@@ -1847,8 +3433,8 @@ static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat,
- if (!pDCTstat->CSPresent)
- pDCTstat->ErrCode = SC_StopError;
-
-- reg = 0x80 + reg_off; /* Bank Addressing Register */
-- Set_NB32(dev, reg, BankAddrReg);
-+ reg = 0x80; /* Bank Addressing Register */
-+ Set_NB32_DCT(dev, dct, reg, BankAddrReg);
-
- pDCTstat->CSPresent_DCT[dct] = pDCTstat->CSPresent;
- /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */
-@@ -1933,11 +3519,9 @@ static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
- u16 word;
- u32 dev;
- u32 reg;
-- u32 reg_off;
- u32 val;
-
- dev = pDCTstat->dev_dct;
-- reg_off = 0x100 * dct;
-
- _DSpareEn = 0;
-
-@@ -1974,11 +3558,11 @@ static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
- BiggestBank = 0;
- for (q = 0; q < MAX_CS_SUPPORTED; q++) { /* from DIMMS to CS */
- if (pDCTstat->CSPresent & (1 << q)) { /* bank present? */
-- reg = 0x40 + (q << 2) + reg_off; /* Base[q] reg.*/
-- val = Get_NB32(dev, reg);
-+ reg = 0x40 + (q << 2); /* Base[q] reg.*/
-+ val = Get_NB32_DCT(dev, dct, reg);
- if (!(val & 3)) { /* (CSEnable|Spare==1)bank is enabled already? */
-- reg = 0x60 + (q << 1) + reg_off; /*Mask[q] reg.*/
-- val = Get_NB32(dev, reg);
-+ reg = 0x60 + (q << 1); /*Mask[q] reg.*/
-+ val = Get_NB32_DCT(dev, dct, reg);
- val >>= 19;
- val++;
- val <<= 19;
-@@ -1994,7 +3578,7 @@ static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
- if (BiggestBank !=0) {
- curcsBase = nxtcsBase; /* curcsBase=nxtcsBase*/
- /* DRAM CS Base b Address Register offset */
-- reg = 0x40 + (b << 2) + reg_off;
-+ reg = 0x40 + (b << 2);
- if (_DSpareEn) {
- BiggestBank = 0;
- val = 1 << Spare; /* Spare Enable*/
-@@ -2013,7 +3597,7 @@ static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
- }
- }
- }
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- if (_DSpareEn)
- _DSpareEn = 0;
- else
-@@ -2024,9 +3608,9 @@ static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
- /* bank present but disabled?*/
- if ( pDCTstat->CSTestFail & (1 << p)) {
- /* DRAM CS Base b Address Register offset */
-- reg = (p << 2) + 0x40 + reg_off;
-+ reg = (p << 2) + 0x40;
- val = 1 << TestFail;
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- }
- }
-
-@@ -2064,7 +3648,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- u16 i, j, k;
- u8 smbaddr;
- u8 SPDCtrl;
-- u16 RegDIMMPresent, MaxDimms;
-+ u16 RegDIMMPresent, LRDIMMPresent, MaxDimms;
- u8 devwidth;
- u16 DimmSlots;
- u8 byte = 0, bytex;
-@@ -2077,6 +3661,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- SPDCtrl = mctGet_NVbits(NV_SPDCHK_RESTRT);
-
- RegDIMMPresent = 0;
-+ LRDIMMPresent = 0;
- pDCTstat->DimmQRPresent = 0;
-
- for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) {
-@@ -2115,6 +3700,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- pDCTstat->DimmManufacturerID[i] |= ((uint64_t)mctRead_SPD(smbaddr, SPD_MANID_START + k)) << (k * 8);
- for (k = 0; k < SPD_PARTN_LENGTH; k++)
- pDCTstat->DimmPartNumber[i][k] = mctRead_SPD(smbaddr, SPD_PARTN_START + k);
-+ pDCTstat->DimmPartNumber[i][SPD_PARTN_LENGTH] = 0;
- pDCTstat->DimmRevisionNumber[i] = 0;
- for (k = 0; k < 2; k++)
- pDCTstat->DimmRevisionNumber[i] |= ((uint16_t)mctRead_SPD(smbaddr, SPD_REVNO_START + k)) << (k * 8);
-@@ -2138,6 +3724,12 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- } else {
- pDCTstat->DimmRegistered[i] = 0;
- }
-+ if (byte == JED_LRDIMM) {
-+ LRDIMMPresent |= 1 << i;
-+ pDCTstat->DimmLoadReduced[i] = 1;
-+ } else {
-+ pDCTstat->DimmLoadReduced[i] = 0;
-+ }
- /* Check ECC capable */
- byte = mctRead_SPD(smbaddr, SPD_BusWidth);
- if (byte & JED_ECC) {
-@@ -2221,6 +3813,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- printk(BIOS_DEBUG, "\t DIMMPresence: DIMMValid=%x\n", pDCTstat->DIMMValid);
- printk(BIOS_DEBUG, "\t DIMMPresence: DIMMPresent=%x\n", pDCTstat->DIMMPresent);
- printk(BIOS_DEBUG, "\t DIMMPresence: RegDIMMPresent=%x\n", RegDIMMPresent);
-+ printk(BIOS_DEBUG, "\t DIMMPresence: LRDIMMPresent=%x\n", LRDIMMPresent);
- printk(BIOS_DEBUG, "\t DIMMPresence: DimmECCPresent=%x\n", pDCTstat->DimmECCPresent);
- printk(BIOS_DEBUG, "\t DIMMPresence: DimmPARPresent=%x\n", pDCTstat->DimmPARPresent);
- printk(BIOS_DEBUG, "\t DIMMPresence: Dimmx4Present=%x\n", pDCTstat->Dimmx4Present);
-@@ -2247,6 +3840,16 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
- pDCTstat->Status |= 1<<SB_Registered;
- }
- }
-+ if (LRDIMMPresent != 0) {
-+ if ((LRDIMMPresent ^ pDCTstat->DIMMValid) !=0) {
-+ /* module type DIMM mismatch (reg'ed, unbuffered) */
-+ pDCTstat->ErrStatus |= 1<<SB_DimmMismatchM;
-+ pDCTstat->ErrCode = SC_StopError;
-+ } else{
-+ /* all DIMMs are registered */
-+ pDCTstat->Status |= 1<<SB_LoadReduced;
-+ }
-+ }
- if (pDCTstat->DimmECCPresent != 0) {
- if ((pDCTstat->DimmECCPresent ^ pDCTstat->DIMMValid )== 0) {
- /* all DIMMs are ECC capable */
-@@ -2284,6 +3887,26 @@ static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i)
- return p[i];
- }
-
-+static void mct_preInitDCT(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat)
-+{
-+ u8 err_code;
-+
-+ /* Preconfigure DCT0 */
-+ DCTPreInit_D(pMCTstat, pDCTstat, 0);
-+
-+ /* Configure DCT1 if unganged and enabled*/
-+ if (!pDCTstat->GangedMode) {
-+ if (pDCTstat->DIMMValidDCT[1] > 0) {
-+ err_code = pDCTstat->ErrCode; /* save DCT0 errors */
-+ pDCTstat->ErrCode = 0;
-+ DCTPreInit_D(pMCTstat, pDCTstat, 1);
-+ if (pDCTstat->ErrCode == 2) /* DCT1 is not Running */
-+ pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */
-+ }
-+ }
-+}
-+
- static void mct_initDCT(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat)
- {
-@@ -2295,7 +3918,7 @@ static void mct_initDCT(struct MCTStatStruc *pMCTstat,
- if (pDCTstat->ErrCode == SC_FatalErr) {
- /* Do nothing goto exitDCTInit; any fatal errors? */
- } else {
-- /* Configure DCT1 if unganged and enabled*/
-+ /* Configure DCT1 if unganged and enabled */
- if (!pDCTstat->GangedMode) {
- if (pDCTstat->DIMMValidDCT[1] > 0) {
- err_code = pDCTstat->ErrCode; /* save DCT0 errors */
-@@ -2305,17 +3928,21 @@ static void mct_initDCT(struct MCTStatStruc *pMCTstat,
- pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */
- } else {
- val = 1 << DisDramInterface;
-- Set_NB32(pDCTstat->dev_dct, 0x100 + 0x94, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
-+
-+ /* To maximize power savings when DisDramInterface=1b,
-+ * all of the MemClkDis bits should also be set.
-+ */
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x88, 0xff000000);
- }
- }
- }
--/* exitDCTInit: */
- }
-
- static void mct_DramInit(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat);
-+ mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat, dct);
- mct_DramInit_Sw_D(pMCTstat, pDCTstat, dct);
- /* mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct); */
- }
-@@ -2343,7 +3970,8 @@ static u8 mct_setMode(struct MCTStatStruc *pMCTstat,
- if (byte)
- pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); /* Set temp. to avoid setting of ganged mode */
-
-- if (!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) {
-+ if ((!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) && (pDCTstat->LogicalCPUID & AMD_FAM10_ALL)) {
-+ /* Ganged channel mode not supported on Family 15h or higher */
- pDCTstat->GangedMode = 1;
- /* valid 128-bit mode population. */
- pDCTstat->Status |= 1 << SB_128bitmode;
-@@ -2387,10 +4015,8 @@ void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data)
-
- u32 Get_NB32_index_wait(u32 dev, u32 index_reg, u32 index)
- {
--
- u32 dword;
-
--
- index &= ~(1 << DctAccessWrite);
- Set_NB32(dev, index_reg, index);
- do {
-@@ -2405,7 +4031,6 @@ void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data)
- {
- u32 dword;
-
--
- Set_NB32(dev, index_reg + 0x4, data);
- index |= (1 << DctAccessWrite);
- Set_NB32(dev, index_reg, index);
-@@ -2420,16 +4045,17 @@ static u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat,
- {
- /* mct_checkForCxDxSupport_D */
- if (pDCTstat->LogicalCPUID & AMD_DR_GT_Bx) {
-+ /* Family 10h Errata 322: Address and Command Fine Delay Values May Be Incorrect */
- /* 1. Write 00000000h to F2x[1,0]9C_xD08E000 */
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98 + dct * 0x100, 0x0D08E000, 0);
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D08E000, 0);
- /* 2. If DRAM Configuration Register[MemClkFreq] (F2x[1,0]94[2:0]) is
- greater than or equal to 011b (DDR-800 and higher),
- then write 00000080h to F2x[1,0]9C_xD02E001,
- else write 00000090h to F2x[1,0]9C_xD02E001. */
-- if (pDCTstat->Speed >= 4)
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98 + dct * 0x100, 0xD02E001, 0x80);
-+ if (pDCTstat->Speed >= mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK)))
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D02E001, 0x80);
- else
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98 + dct * 0x100, 0xD02E001, 0x90);
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D02E001, 0x90);
- }
- return pDCTstat->ErrCode;
- }
-@@ -2455,9 +4081,9 @@ static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
- i_end = dct + 1;
- }
- for (i=i_start; i<i_end; i++) {
-- index_reg = 0x98 + (i * 0x100);
-- Set_NB32_index_wait(dev, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A Output Driver Compensation Control */
-- Set_NB32_index_wait(dev, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A Output Driver Compensation Control */
-+ index_reg = 0x98;
-+ Set_NB32_index_wait_DCT(dev, i, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A Output Driver Compensation Control */
-+ Set_NB32_index_wait_DCT(dev, i, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A Output Driver Compensation Control */
- }
-
- return pDCTstat->ErrCode;
-@@ -2511,14 +4137,14 @@ static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,
- }
-
- if (pDCTstat->DIMMValidDCT[0] == 0) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
- val |= 1 << DisDramInterface;
-- Set_NB32(pDCTstat->dev_dct, 0x94, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);
- }
- if (pDCTstat->DIMMValidDCT[1] == 0) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
- val |= 1 << DisDramInterface;
-- Set_NB32(pDCTstat->dev_dct, 0x94 + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
- }
-
- printk(BIOS_DEBUG, "SPDCalcWidth: Status %x\n", pDCTstat->Status);
-@@ -2648,21 +4274,20 @@ static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
- u32 reg;
-- u32 reg_off = 0x100 * dct;
- u32 val;
- u32 dword;
- u32 dev = pDCTstat->dev_dct;
-
-- Get_DqsRcvEnGross_Diff(pDCTstat, dev, 0x98 + reg_off);
-- Get_WrDatGross_Diff(pDCTstat, dct, dev, 0x98 + reg_off);
-+ Get_DqsRcvEnGross_Diff(pDCTstat, dev, dct, 0x98);
-+ Get_WrDatGross_Diff(pDCTstat, dct, dev, 0x98);
- Get_Trdrd(pMCTstat, pDCTstat, dct);
- Get_Twrwr(pMCTstat, pDCTstat, dct);
- Get_Twrrd(pMCTstat, pDCTstat, dct);
- Get_TrwtTO(pMCTstat, pDCTstat, dct);
- Get_TrwtWB(pMCTstat, pDCTstat);
-
-- reg = 0x8C + reg_off; /* Dram Timing Hi */
-- val = Get_NB32(dev, reg);
-+ reg = 0x8C; /* Dram Timing Hi */
-+ val = Get_NB32_DCT(dev, dct, reg);
- val &= 0xffff0300;
- dword = pDCTstat->TrwtTO;
- val |= dword << 4;
-@@ -2674,10 +4299,10 @@ static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
- val |= dword << 14;
- dword = pDCTstat->TrwtWB;
- val |= dword;
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
-
-- reg = 0x78 + reg_off;
-- val = Get_NB32(dev, reg);
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, dct, reg);
- val &= 0xFFFFC0FF;
- dword = pDCTstat->Twrrd >> 2;
- val |= dword << 8;
-@@ -2685,7 +4310,7 @@ static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
- val |= dword << 10;
- dword = pDCTstat->Trdrd >> 2;
- val |= dword << 12;
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- }
-
- static void Get_Trdrd(struct MCTStatStruc *pMCTstat,
-@@ -2755,18 +4380,17 @@ static void Get_TrwtWB(struct MCTStatStruc *pMCTstat,
- static u8 Get_Latency_Diff(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 val1, val2;
-
-- val1 = Get_NB32(dev, reg_off + 0x88) & 0xF;
-- val2 = (Get_NB32(dev, reg_off + 0x84) >> 20) & 7;
-+ val1 = Get_NB32_DCT(dev, dct, 0x88) & 0xF;
-+ val2 = (Get_NB32_DCT(dev, dct, 0x84) >> 20) & 7;
-
- return val1 - val2;
- }
-
- static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
-- u32 dev, u32 index_reg)
-+ u32 dev, uint8_t dct, u32 index_reg)
- {
- u8 Smallest, Largest;
- u32 val;
-@@ -2776,12 +4400,12 @@ static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
- DqsRcvEnGrossDelay of any other DIMM is equal to the Critical
- Gross Delay Difference (CGDD) */
- /* DqsRcvEn byte 1,0 */
-- val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x10);
-+ val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x10);
- Largest = val & 0xFF;
- Smallest = (val >> 8) & 0xFF;
-
- /* DqsRcvEn byte 3,2 */
-- val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x11);
-+ val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x11);
- byte = val & 0xFF;
- bytex = (val >> 8) & 0xFF;
- if (bytex < Smallest)
-@@ -2790,7 +4414,7 @@ static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
- Largest = byte;
-
- /* DqsRcvEn byte 5,4 */
-- val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x20);
-+ val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x20);
- byte = val & 0xFF;
- bytex = (val >> 8) & 0xFF;
- if (bytex < Smallest)
-@@ -2799,7 +4423,7 @@ static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
- Largest = byte;
-
- /* DqsRcvEn byte 7,6 */
-- val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x21);
-+ val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x21);
- byte = val & 0xFF;
- bytex = (val >> 8) & 0xFF;
- if (bytex < Smallest)
-@@ -2809,7 +4433,7 @@ static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
-
- if (pDCTstat->DimmECCPresent> 0) {
- /*DqsRcvEn Ecc */
-- val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x12);
-+ val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x12);
- byte = val & 0xFF;
- bytex = (val >> 8) & 0xFF;
- if (bytex < Smallest)
-@@ -2873,7 +4497,7 @@ static void Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat,
- }
-
- static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
-- u32 dev, u32 index_reg,
-+ u32 dev, uint8_t dct, u32 index_reg,
- u32 index)
- {
- u8 Smallest, Largest;
-@@ -2891,7 +4515,7 @@ static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
-
- for (i=0; i < 8; i+=2) {
- if ( pDCTstat->DIMMValid & (1 << i)) {
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
- val &= 0x00E000E0;
- byte = (val >> 5) & 0xFF;
- if (byte < Smallest)
-@@ -2929,7 +4553,7 @@ static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat,
- Smallest = 3;
- Largest = 0;
- for (i=0; i < 2; i++) {
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
- val &= 0x60606060;
- val >>= 5;
- for (j=0; j < 4; j++) {
-@@ -2945,7 +4569,7 @@ static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat,
-
- if (pDCTstat->DimmECCPresent > 0) {
- index++;
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
- val &= 0x00000060;
- val >>= 5;
- byte = val & 0xFF;
-@@ -2965,25 +4589,30 @@ static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat,
- static void mct_PhyController_Config(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ uint8_t index;
-+ uint32_t dword;
-+ u32 index_reg = 0x98;
- u32 dev = pDCTstat->dev_dct;
-- u32 val;
-
-- if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3 | AMD_RB_C3)) {
-+ if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3 | AMD_RB_C3 | AMD_FAM15_ALL)) {
- if (pDCTstat->Dimmx4Present == 0) {
-- /* Set bit7 RxDqsUDllPowerDown to register F2x[1, 0]98_x0D0F0F13 for power saving */
-- val = Get_NB32_index_wait(dev, index_reg, 0x0D0F0F13); /* Agesa v3 v6 might be wrong here. */
-- val |= 1 << 7; /* BIOS should set this bit when x4 DIMMs are not present */
-- Set_NB32_index_wait(dev, index_reg, 0x0D0F0F13, val);
-+ /* Set bit7 RxDqsUDllPowerDown to register F2x[1, 0]98_x0D0F0F13 for
-+ * additional power saving when x4 DIMMs are not present.
-+ */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8));
-+ dword |= (0x1 << 7); /* RxDqsUDllPowerDown = 1 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8), dword);
-+ }
- }
- }
-
-- if (pDCTstat->LogicalCPUID & AMD_DR_DAC2_OR_C3) {
-+ if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3 | AMD_FAM15_ALL)) {
- if (pDCTstat->DimmECCPresent == 0) {
- /* Set bit4 PwrDn to register F2x[1, 0]98_x0D0F0830 for power saving */
-- val = Get_NB32_index_wait(dev, index_reg, 0x0D0F0830);
-- val |= 1 << 4; /* BIOS should set this bit if ECC DIMMs are not present */
-- Set_NB32_index_wait(dev, index_reg, 0x0D0F0830, val);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0830);
-+ dword |= 1 << 4; /* BIOS should set this bit if ECC DIMMs are not present */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0830, dword);
- }
- }
-
-@@ -3024,21 +4653,61 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
- val &= ~(1 << 12);
-
- val &= 0x0FFFFFFF;
-- switch (pDCTstat->Speed) {
-- case 4:
-- val |= 0x50000000; /* 5 for DDR800 */
-- break;
-- case 5:
-- val |= 0x60000000; /* 6 for DDR1066 */
-- break;
-- case 6:
-- val |= 0x80000000; /* 8 for DDR800 */
-- break;
-- default:
-- val |= 0x90000000; /* 9 for DDR1600 */
-- break;
-+ if (!is_fam15h()) {
-+ switch (pDCTstat->Speed) {
-+ case 4:
-+ val |= 0x50000000; /* 5 for DDR800 */
-+ break;
-+ case 5:
-+ val |= 0x60000000; /* 6 for DDR1066 */
-+ break;
-+ case 6:
-+ val |= 0x80000000; /* 8 for DDR800 */
-+ break;
-+ default:
-+ val |= 0x90000000; /* 9 for DDR1600 */
-+ break;
-+ }
- }
- Set_NB32(pDCTstat->dev_dct, 0x1B0, val);
-+
-+ if (is_fam15h()) {
-+ uint8_t wm1;
-+ uint8_t wm2;
-+
-+ switch (pDCTstat->Speed) {
-+ case 0x4:
-+ wm1 = 0x3;
-+ wm2 = 0x4;
-+ break;
-+ case 0x6:
-+ wm1 = 0x3;
-+ wm2 = 0x5;
-+ break;
-+ case 0xa:
-+ wm1 = 0x4;
-+ wm2 = 0x6;
-+ break;
-+ case 0xe:
-+ wm1 = 0x5;
-+ wm2 = 0x8;
-+ break;
-+ case 0x12:
-+ wm1 = 0x6;
-+ wm2 = 0x9;
-+ break;
-+ default:
-+ wm1 = 0x7;
-+ wm2 = 0xa;
-+ break;
-+ }
-+
-+ val = Get_NB32(pDCTstat->dev_dct, 0x1B4);
-+ val &= ~(0x3ff);
-+ val |= ((wm2 & 0x1f) << 5);
-+ val |= (wm1 & 0x1f);
-+ Set_NB32(pDCTstat->dev_dct, 0x1B4, val);
-+ }
- }
- }
-
-@@ -3055,16 +4724,103 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
- }
- }
-
-+void mct_ForceNBPState0_En_Fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat)
-+{
-+ /* Force the NB P-state to P0 */
-+ uint32_t dword;
-+ uint32_t dword2;
-+
-+ dword = Get_NB32(pDCTstat->dev_nbctl, 0x174);
-+ if (!(dword & 0x1)) {
-+ dword = Get_NB32(pDCTstat->dev_nbctl, 0x170);
-+ pDCTstat->SwNbPstateLoDis = (dword >> 14) & 0x1;
-+ pDCTstat->NbPstateDisOnP0 = (dword >> 13) & 0x1;
-+ pDCTstat->NbPstateThreshold = (dword >> 9) & 0x7;
-+ pDCTstat->NbPstateHi = (dword >> 6) & 0x3;
-+ dword &= ~(0x1 << 14); /* SwNbPstateLoDis = 0 */
-+ dword &= ~(0x1 << 13); /* NbPstateDisOnP0 = 0 */
-+ dword &= ~(0x7 << 9); /* NbPstateThreshold = 0 */
-+ dword &= ~(0x3 << 3); /* NbPstateLo = NbPstateMaxVal */
-+ dword |= ((dword & 0x3) << 3);
-+ Set_NB32(pDCTstat->dev_nbctl, 0x170, dword);
-+
-+ /* Wait until CurNbPState == NbPstateLo */
-+ do {
-+ dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174);
-+ } while (((dword2 << 19) & 0x7) != (dword & 0x3));
-+
-+ dword = Get_NB32(pDCTstat->dev_nbctl, 0x170);
-+ dword &= ~(0x3 << 6); /* NbPstateHi = 0 */
-+ dword |= (0x3 << 14); /* SwNbPstateLoDis = 1 */
-+ Set_NB32(pDCTstat->dev_nbctl, 0x170, dword);
-+
-+ /* Wait until CurNbPState == 0 */
-+ do {
-+ dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174);
-+ } while (((dword2 << 19) & 0x7) != 0);
-+ }
-+}
-+
-+void mct_ForceNBPState0_Dis_Fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat)
-+{
-+ /* Restore normal NB P-state functionailty */
-+ uint32_t dword;
-+
-+ dword = Get_NB32(pDCTstat->dev_nbctl, 0x174);
-+ if (!(dword & 0x1)) {
-+ dword = Get_NB32(pDCTstat->dev_nbctl, 0x170);
-+ dword &= ~(0x1 << 14); /* SwNbPstateLoDis*/
-+ dword |= ((pDCTstat->SwNbPstateLoDis & 0x1) << 14);
-+ dword &= ~(0x1 << 13); /* NbPstateDisOnP0 */
-+ dword |= ((pDCTstat->NbPstateDisOnP0 & 0x1) << 13);
-+ dword &= ~(0x7 << 9); /* NbPstateThreshold */
-+ dword |= ((pDCTstat->NbPstateThreshold & 0x7) << 9);
-+ dword &= ~(0x3 << 6); /* NbPstateHi */
-+ dword |= ((pDCTstat->NbPstateHi & 0x3) << 3);
-+ Set_NB32(pDCTstat->dev_nbctl, 0x170, dword);
-+ }
-+}
-+
- static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
- {
-- mct_SetClToNB_D(pMCTstat, pDCTstat);
-- mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat);
-+ if (is_fam15h()) {
-+ msr_t p0_state_msr;
-+ uint8_t cpu_fid;
-+ uint8_t cpu_did;
-+ uint32_t cpu_divisor;
-+ uint8_t boost_states;
-+
-+ /* Retrieve the number of boost states */
-+ boost_states = (Get_NB32(pDCTstat->dev_link, 0x15c) >> 2) & 0x7;
-+
-+ /* Retrieve and store the TSC frequency (P0 COF) */
-+ p0_state_msr = rdmsr(0xc0010064 + boost_states);
-+ cpu_fid = p0_state_msr.lo & 0x3f;
-+ cpu_did = (p0_state_msr.lo >> 6) & 0x7;
-+ cpu_divisor = (0x1 << cpu_did);
-+ pMCTstat->TSCFreq = (100 * (cpu_fid + 0x10)) / cpu_divisor;
-+
-+ mct_ForceNBPState0_En_Fam15(pMCTstat, pDCTstat);
-+ } else {
-+ /* K10 BKDG v3.62 section 2.8.9.2 */
-+ printk(BIOS_DEBUG, "mct_InitialMCT_D: clear_legacy_Mode\n");
-+ clear_legacy_Mode(pMCTstat, pDCTstat);
-+
-+ /* Northbridge configuration */
-+ mct_SetClToNB_D(pMCTstat, pDCTstat);
-+ mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat);
-+ }
- }
-
- static u32 mct_NodePresent_D(void)
- {
- u32 val;
-- val = 0x12001022;
-+ if (is_fam15h())
-+ val = 0x16001022;
-+ else
-+ val = 0x12001022;
- return val;
- }
-
-@@ -3097,14 +4853,13 @@ static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat,
-
- /* Clear Legacy BIOS Mode bit */
- reg = 0x94;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 0, reg);
- val &= ~(1<<LegacyBiosMode);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, 0, reg, val);
-
-- reg = 0x94 + 0x100;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 1, reg);
- val &= ~(1<<LegacyBiosMode);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, 1, reg, val);
- }
-
- static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat,
-@@ -3171,7 +4926,7 @@ static void SetCSTriState(struct MCTStatStruc *pMCTstat,
- {
- u32 val;
- u32 dev = pDCTstat->dev_dct;
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ u32 index_reg = 0x98;
- u32 index;
- u16 word;
-
-@@ -3186,9 +4941,9 @@ static void SetCSTriState(struct MCTStatStruc *pMCTstat,
- }
- word = (~word) & 0xFF;
- index = 0x0c;
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
- val |= word;
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
- }
-
- static void SetCKETriState(struct MCTStatStruc *pMCTstat,
-@@ -3196,7 +4951,7 @@ static void SetCKETriState(struct MCTStatStruc *pMCTstat,
- {
- u32 val;
- u32 dev;
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ u32 index_reg = 0x98;
- u32 index;
- u16 word;
-
-@@ -3208,14 +4963,14 @@ static void SetCKETriState(struct MCTStatStruc *pMCTstat,
- word = pDCTstat->CSPresent;
-
- index = 0x0c;
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
- if ((word & 0x55) == 0)
- val |= 1 << 12;
-
- if ((word & 0xAA) == 0)
- val |= 1 << 13;
-
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
- }
-
- static void SetODTTriState(struct MCTStatStruc *pMCTstat,
-@@ -3223,7 +4978,7 @@ static void SetODTTriState(struct MCTStatStruc *pMCTstat,
- {
- u32 val;
- u32 dev;
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ u32 index_reg = 0x98;
- u8 cs;
- u32 index;
- u8 odt;
-@@ -3257,86 +5012,281 @@ static void SetODTTriState(struct MCTStatStruc *pMCTstat,
- }
-
- index = 0x0C;
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
- val |= ((odt & 0xFF) << 8); /* set bits 11:8 ODTTriState[3:0] */
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
-+
-+}
-+
-+/* Family 15h */
-+static void InitDDRPhy(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct)
-+{
-+ uint8_t index;
-+ uint32_t dword;
-+ uint8_t ddr_voltage_index;
-+ uint8_t amd_voltage_level_index = 0;
-+ uint32_t index_reg = 0x98;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
-
-+ /* Find current DDR supply voltage for this DCT */
-+ ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct);
-+
-+ /* Fam15h BKDG v3.14 section 2.10.5.3
-+ * The remainder of the Phy Initialization algorithm picks up in phyAssistedMemFnceTraining
-+ */
-+ for (dct = 0; dct < 2; dct++) {
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000b, 0x80000000);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe013, 0x00000118);
-+
-+ /* Program desired VDDIO level */
-+ if (ddr_voltage_index & 0x4) {
-+ /* 1.25V */
-+ amd_voltage_level_index = 0x2;
-+ } else if (ddr_voltage_index & 0x2) {
-+ /* 1.35V */
-+ amd_voltage_level_index = 0x1;
-+ } else if (ddr_voltage_index & 0x1) {
-+ /* 1.50V */
-+ amd_voltage_level_index = 0x0;
-+ }
-+
-+ /* D18F2x9C_x0D0F_0[F,8:0]1F_dct[1:0][RxVioLvl] */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8));
-+ dword &= ~(0x3 << 3);
-+ dword |= (amd_voltage_level_index << 3);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8), dword);
-+ }
-+
-+ /* D18F2x9C_x0D0F_[C,8,2][2:0]1F_dct[1:0][RxVioLvl] */
-+ for (index = 0; index < 0x3; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8));
-+ dword &= ~(0x3 << 3);
-+ dword |= (amd_voltage_level_index << 3);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8), dword);
-+ }
-+ for (index = 0; index < 0x2; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8));
-+ dword &= ~(0x3 << 3);
-+ dword |= (amd_voltage_level_index << 3);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8), dword);
-+ }
-+ for (index = 0; index < 0x1; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8));
-+ dword &= ~(0x3 << 3);
-+ dword |= (amd_voltage_level_index << 3);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8), dword);
-+ }
-+
-+ /* D18F2x9C_x0D0F_4009_dct[1:0][CmpVioLvl, ComparatorAdjust] */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f4009);
-+ dword &= ~(0x0000c00c);
-+ dword |= (amd_voltage_level_index << 14);
-+ dword |= (amd_voltage_level_index << 2);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f4009, dword);
-+ }
-+
-+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
- }
-
- static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
- u8 i;
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ u32 index_reg = 0x98;
- u32 dev = pDCTstat->dev_dct;
-- u32 val;
- u32 valx = 0;
-- u32 dword;
-+ uint8_t index;
-+ uint32_t dword;
- const u8 *p;
-
-- val = Get_NB32_index_wait(dev, index_reg, 0x00);
-- dword = 0;
-- for (i=0; i < 6; i++) {
-- switch (i) {
-- case 0:
-- case 4:
-- p = Table_Comp_Rise_Slew_15x;
-- valx = p[(val >> 16) & 3];
-- break;
-- case 1:
-- case 5:
-- p = Table_Comp_Fall_Slew_15x;
-- valx = p[(val >> 16) & 3];
-- break;
-- case 2:
-- p = Table_Comp_Rise_Slew_20x;
-- valx = p[(val >> 8) & 3];
-- break;
-- case 3:
-- p = Table_Comp_Fall_Slew_20x;
-- valx = p[(val >> 8) & 3];
-- break;
-+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
-+
-+ if (is_fam15h()) {
-+ /* Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 */
-+ uint32_t tx_pre;
-+ uint32_t drive_strength;
-+
-+ /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisAutoComp, DisablePredriverCal] */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003);
-+ dword |= (0x3 << 13);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003, dword);
-+
-+ /* Determine TxPreP/TxPreN for data lanes (Stage 1) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
-+ drive_strength = (dword >> 20) & 0x7; /* DqsDrvStren */
-+ tx_pre = fam15h_phy_predriver_calibration_code(pDCTstat, dct, drive_strength);
-+
-+ /* Program TxPreP/TxPreN for data lanes (Stage 1) */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0006 | (index << 8));
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0006 | (index << 8), dword);
-+ }
-
-+ /* Determine TxPreP/TxPreN for data lanes (Stage 2) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
-+ drive_strength = (dword >> 16) & 0x7; /* DataDrvStren */
-+ tx_pre = fam15h_phy_predriver_calibration_code(pDCTstat, dct, drive_strength);
-+
-+ /* Program TxPreP/TxPreN for data lanes (Stage 2) */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000a | (index << 8));
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000a | (index << 8), dword);
-+ }
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8));
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8), dword);
- }
-- dword |= valx << (5 * i);
-- }
-
-- /* Override/Exception */
-- if (!pDCTstat->GangedMode) {
-- i = 0; /* use i for the dct setting required */
-- if (pDCTstat->MAdimms[0] < 4)
-- i = 1;
-- if (((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) && (pDCTstat->MAdimms[i] == 4)) {
-- dword &= 0xF18FFF18;
-- index_reg = 0x98; /* force dct = 0 */
-+ /* Determine TxPreP/TxPreN for command/address lines (Stage 1) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
-+ drive_strength = (dword >> 4) & 0x7; /* CsOdtDrvStren */
-+ tx_pre = fam15h_phy_predriver_cmd_addr_calibration_code(pDCTstat, dct, drive_strength);
-+
-+ /* Program TxPreP/TxPreN for command/address lines (Stage 1) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8006);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8006, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f800a);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f800a, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8002);
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8002, dword);
-+
-+ /* Determine TxPreP/TxPreN for command/address lines (Stage 2) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
-+ drive_strength = (dword >> 8) & 0x7; /* AddrCmdDrvStren */
-+ tx_pre = fam15h_phy_predriver_cmd_addr_calibration_code(pDCTstat, dct, drive_strength);
-+
-+ /* Program TxPreP/TxPreN for command/address lines (Stage 2) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8106);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8106, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f810a);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f810a, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc006);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc006, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00a);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00a, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00e);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00e, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc012);
-+ dword &= ~(0xfff);
-+ dword |= tx_pre;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc012, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8102);
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8102, dword);
-+
-+ /* Determine TxPreP/TxPreN for command/address lines (Stage 3) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
-+ drive_strength = (dword >> 0) & 0x7; /* CkeDrvStren */
-+ tx_pre = fam15h_phy_predriver_cmd_addr_calibration_code(pDCTstat, dct, drive_strength);
-+
-+ /* Program TxPreP/TxPreN for command/address lines (Stage 3) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc002);
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc002, dword);
-+
-+ /* Determine TxPreP/TxPreN for clock lines */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
-+ drive_strength = (dword >> 12) & 0x7; /* ClkDrvStren */
-+ tx_pre = fam15h_phy_predriver_clk_calibration_code(pDCTstat, dct, drive_strength);
-+
-+ /* Program TxPreP/TxPreN for clock lines */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2002);
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2002, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2102);
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2102, dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202);
-+ dword &= ~(0xfff);
-+ dword |= (0x8000 | tx_pre);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202, dword);
-+ } else {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00);
-+ dword = 0;
-+ for (i=0; i < 6; i++) {
-+ switch (i) {
-+ case 0:
-+ case 4:
-+ p = Table_Comp_Rise_Slew_15x;
-+ valx = p[(dword >> 16) & 3];
-+ break;
-+ case 1:
-+ case 5:
-+ p = Table_Comp_Fall_Slew_15x;
-+ valx = p[(dword >> 16) & 3];
-+ break;
-+ case 2:
-+ p = Table_Comp_Rise_Slew_20x;
-+ valx = p[(dword >> 8) & 3];
-+ break;
-+ case 3:
-+ p = Table_Comp_Fall_Slew_20x;
-+ valx = p[(dword >> 8) & 3];
-+ break;
-+ }
-+ dword |= valx << (5 * i);
- }
-+
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0a, dword);
- }
-
-- Set_NB32_index_wait(dev, index_reg, 0x0a, dword);
-+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
- }
-
- static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 reg;
-- u32 val;
-- u32 dev = pDCTstat->dev_dct;
--
-- /* GhEnhancement #18429 modified by askar: For low NB CLK :
-- * Memclk ratio, the DCT may need to arbitrate early to avoid
-- * unnecessary bubbles.
-- * bit 19 of F2x[1,0]78 Dram Control Register, set this bit only when
-- * NB CLK : Memclk ratio is between 3:1 (inclusive) to 4:5 (inclusive)
-- */
-- reg = 0x78 + 0x100 * dct;
-- val = Get_NB32(dev, reg);
--
-- if (pDCTstat->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
-- val |= (1 << EarlyArbEn);
-- else if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat))
-- val |= (1 << EarlyArbEn);
--
-- Set_NB32(dev, reg, val);
-+ if (!is_fam15h()) {
-+ u32 reg;
-+ u32 val;
-+ u32 dev = pDCTstat->dev_dct;
-+
-+ /* GhEnhancement #18429 modified by askar: For low NB CLK :
-+ * Memclk ratio, the DCT may need to arbitrate early to avoid
-+ * unnecessary bubbles.
-+ * bit 19 of F2x[1,0]78 Dram Control Register, set this bit only when
-+ * NB CLK : Memclk ratio is between 3:1 (inclusive) to 4:5 (inclusive)
-+ */
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, dct, reg);
-+
-+ if (pDCTstat->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
-+ val |= (1 << EarlyArbEn);
-+ else if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat))
-+ val |= (1 << EarlyArbEn);
-+
-+ Set_NB32_DCT(dev, dct, reg, val);
-+ }
- }
-
- static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
-@@ -3359,9 +5309,9 @@ static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
- NbDid |= 1;
-
- reg = 0x94;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 0, reg);
- if (!(val & (1 << MemClkFreqVal)))
-- val = Get_NB32(dev, reg + 0x100); /* get the DCT1 value */
-+ val = Get_NB32_DCT(dev, 1, reg); /* get the DCT1 value */
-
- val &= 0x07;
- val += 3;
-@@ -3430,28 +5380,204 @@ static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat,
- }
-
- static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstat)
-+ struct DCTStatStruc *pDCTstat, u8 dct)
-+{
-+ mct_ProgramODT_D(pMCTstat, pDCTstat, dct);
-+}
-+
-+static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct)
- {
- u8 i;
-- u32 reg_off, dword;
-+ u32 dword;
- u32 dev = pDCTstat->dev_dct;
-
-- if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ if (is_fam15h()) {
-+ /* Obtain number of DIMMs on channel */
-+ uint8_t dimm_count = pDCTstat->MAdimms[dct];
-+ uint8_t rank_count_dimm0;
-+ uint8_t rank_count_dimm1;
-+ uint32_t odt_pattern_0;
-+ uint32_t odt_pattern_1;
-+ uint32_t odt_pattern_2;
-+ uint32_t odt_pattern_3;
-+ uint8_t write_odt_duration;
-+ uint8_t read_odt_duration;
-+ uint8_t write_odt_delay;
-+ uint8_t read_odt_delay;
-+
-+ /* Select appropriate ODT pattern for installed DIMMs
-+ * Refer to the Fam15h BKDG Rev. 3.14, page 149 onwards
-+ */
-+ if (pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED]) {
-+ if (MaxDimmsInstallable == 2) {
-+ if (dimm_count == 1) {
-+ /* 1 DIMM detected */
-+ rank_count_dimm1 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+ if (rank_count_dimm1 == 1) {
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x00020000;
-+ } else if (rank_count_dimm1 == 2) {
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x08020000;
-+ } else if (rank_count_dimm1 == 4) {
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x020a0000;
-+ odt_pattern_3 = 0x080a0000;
-+ } else {
-+ /* Fallback */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x08020000;
-+ }
-+ } else {
-+ /* 2 DIMMs detected */
-+ rank_count_dimm0 = pDCTstat->C_DCTPtr[dct]->DimmRanks[0];
-+ rank_count_dimm1 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+ if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) {
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x01010202;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x09030603;
-+ } else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) {
-+ odt_pattern_0 = 0x01010000;
-+ odt_pattern_1 = 0x01010a0a;
-+ odt_pattern_2 = 0x01090000;
-+ odt_pattern_3 = 0x01030e0b;
-+ } else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) {
-+ odt_pattern_0 = 0x00000202;
-+ odt_pattern_1 = 0x05050202;
-+ odt_pattern_2 = 0x00000206;
-+ odt_pattern_3 = 0x0d070203;
-+ } else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 == 4)) {
-+ odt_pattern_0 = 0x05050a0a;
-+ odt_pattern_1 = 0x05050a0a;
-+ odt_pattern_2 = 0x050d0a0e;
-+ odt_pattern_3 = 0x05070a0b;
-+ } else {
-+ /* Fallback */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x00000000;
-+ }
-+ }
-+ } else {
-+ /* FIXME
-+ * 3 DIMMs per channel UNIMPLEMENTED
-+ */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x00000000;
-+ }
-+ } else if (pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED]) {
-+ /* TODO
-+ * Load reduced dimms UNIMPLEMENTED
-+ */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x00000000;
-+ } else {
-+ if (MaxDimmsInstallable == 2) {
-+ if (dimm_count == 1) {
-+ /* 1 DIMM detected */
-+ rank_count_dimm1 = pDCTstat->C_DCTPtr[dct]->DimmRanks[1];
-+ if (rank_count_dimm1 == 1) {
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x00020000;
-+ } else if (rank_count_dimm1 == 2) {
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x08020000;
-+ } else {
-+ /* Fallback */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x08020000;
-+ }
-+ } else {
-+ /* 2 DIMMs detected */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x01010202;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x09030603;
-+ }
-+ } else {
-+ /* FIXME
-+ * 3 DIMMs per channel UNIMPLEMENTED
-+ */
-+ odt_pattern_0 = 0x00000000;
-+ odt_pattern_1 = 0x00000000;
-+ odt_pattern_2 = 0x00000000;
-+ odt_pattern_3 = 0x00000000;
-+ }
-+ }
-+
-+ if (pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED]) {
-+ /* TODO
-+ * Load reduced dimms UNIMPLEMENTED
-+ */
-+ write_odt_duration = 0x0;
-+ read_odt_duration = 0x0;
-+ write_odt_delay = 0x0;
-+ read_odt_delay = 0x0;
-+ } else {
-+ uint8_t tcl;
-+ uint8_t tcwl;
-+ tcl = Get_NB32_DCT(dev, dct, 0x200) & 0x1f;
-+ tcwl = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f;
-+
-+ write_odt_duration = 0x6;
-+ read_odt_duration = 0x6;
-+ write_odt_delay = 0x0;
-+ if (tcl > tcwl)
-+ read_odt_delay = tcl - tcwl;
-+ else
-+ read_odt_delay = 0x0;
-+ }
-+
-+ /* Program ODT pattern */
-+ Set_NB32_DCT(dev, dct, 0x230, odt_pattern_1);
-+ Set_NB32_DCT(dev, dct, 0x234, odt_pattern_0);
-+ Set_NB32_DCT(dev, dct, 0x238, odt_pattern_3);
-+ Set_NB32_DCT(dev, dct, 0x23c, odt_pattern_2);
-+ dword = Get_NB32_DCT(dev, dct, 0x240);
-+ dword &= ~(0x7 << 12); /* WrOdtOnDuration = write_odt_duration */
-+ dword |= (write_odt_duration & 0x7) << 12;
-+ dword &= ~(0x7 << 8); /* WrOdtTrnOnDly = write_odt_delay */
-+ dword |= (write_odt_delay & 0x7) << 8;
-+ dword &= ~(0xf << 4); /* RdOdtOnDuration = read_odt_duration */
-+ dword |= (read_odt_duration & 0xf) << 4;
-+ dword &= ~(0xf); /* RdOdtTrnOnDly = read_odt_delay */
-+ dword |= (read_odt_delay & 0xf);
-+ Set_NB32_DCT(dev, dct, 0x240, dword);
-+ } else if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
- if (pDCTstat->Speed == 3)
- dword = 0x00000800;
- else
- dword = 0x00000000;
- for (i=0; i < 2; i++) {
-- reg_off = 0x100 * i;
-- Set_NB32(dev, 0x98 + reg_off, 0x0D000030);
-- Set_NB32(dev, 0x9C + reg_off, dword);
-- Set_NB32(dev, 0x98 + reg_off, 0x4D040F30);
--
-- /* FIXME
-- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-- * For now assume a maximum of 2 DIMMs per channel can be installed
-- */
-- uint8_t MaxDimmsInstallable = 2;
-+ Set_NB32_DCT(dev, i, 0x98, 0x0D000030);
-+ Set_NB32_DCT(dev, i, 0x9C, dword);
-+ Set_NB32_DCT(dev, i, 0x98, 0x4D040F30);
-
- /* Obtain number of DIMMs on channel */
- uint8_t dimm_count = pDCTstat->MAdimms[i];
-@@ -3463,7 +5589,7 @@ static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
- uint32_t odt_pattern_3;
-
- /* Select appropriate ODT pattern for installed DIMMs
-- * Refer to the BKDG Rev. 3.62, page 120 onwards
-+ * Refer to the Fam10h BKDG Rev. 3.62, page 120 onwards
- */
- if (pDCTstat->C_DCTPtr[i]->Status[DCT_STATUS_REGISTERED]) {
- if (MaxDimmsInstallable == 2) {
-@@ -3574,10 +5700,10 @@ static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
- }
-
- /* Program ODT pattern */
-- Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x180, odt_pattern_1);
-- Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x181, odt_pattern_0);
-- Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x182, odt_pattern_3);
-- Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x183, odt_pattern_2);
-+ Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x180, odt_pattern_1);
-+ Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x181, odt_pattern_0);
-+ Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x182, odt_pattern_3);
-+ Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x183, odt_pattern_2);
- }
- }
- }
-@@ -3585,34 +5711,32 @@ static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
- static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct, val;
-
- /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */
- if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3)) {
-- Set_NB32(dev, 0x9C + reg_off, 0x1C);
-- Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006);
-- Set_NB32(dev, 0x9C + reg_off, 0x13D);
-- Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007);
-+ Set_NB32_DCT(dev, dct, 0x9C, 0x1C);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE006);
-+ Set_NB32_DCT(dev, dct, 0x9C, 0x13D);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE007);
-
-- val = Get_NB32(dev, 0x90 + reg_off);
-+ val = Get_NB32_DCT(dev, dct, 0x90);
- val &= ~(1 << 27/* DisDllShutdownSR */);
-- Set_NB32(dev, 0x90 + reg_off, val);
-+ Set_NB32_DCT(dev, dct, 0x90, val);
- }
- }
-
- static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
-
- /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */
- if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3)) {
-- Set_NB32(dev, 0x9C + reg_off, 0x7D0);
-- Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006);
-- Set_NB32(dev, 0x9C + reg_off, 0x190);
-- Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007);
-+ Set_NB32_DCT(dev, dct, 0x9C, 0x7D0);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE006);
-+ Set_NB32_DCT(dev, dct, 0x9C, 0x190);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE007);
-
- DramConfigLo |= /* DisDllShutdownSR */ 1 << 27;
- }
-@@ -3704,52 +5828,61 @@ void ProgDramMRSReg_D(struct MCTStatStruc *pMCTstat,
- DramMRS |= 1 << 23;
- }
- }
-- /*
-- DRAM MRS Register
-- DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7)
-- */
-- DramMRS |= 1 << 2;
-- /* Dram nominal termination: */
-- byte = pDCTstat->MAdimms[dct];
-- if (!(pDCTstat->Status & (1 << SB_Registered))) {
-- DramMRS |= 1 << 7; /* 60 ohms */
-- if (byte & 2) {
-- if (pDCTstat->Speed < 6)
-- DramMRS |= 1 << 8; /* 40 ohms */
-- else
-- DramMRS |= 1 << 9; /* 30 ohms */
-+
-+ if (is_fam15h()) {
-+ DramMRS |= (0x1 << 23); /* PchgPDModeSel = 1 */
-+ } else {
-+ /*
-+ DRAM MRS Register
-+ DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7)
-+ */
-+ DramMRS |= 1 << 2;
-+ /* Dram nominal termination: */
-+ byte = pDCTstat->MAdimms[dct];
-+ if (!(pDCTstat->Status & (1 << SB_Registered))) {
-+ DramMRS |= 1 << 7; /* 60 ohms */
-+ if (byte & 2) {
-+ if (pDCTstat->Speed < 6)
-+ DramMRS |= 1 << 8; /* 40 ohms */
-+ else
-+ DramMRS |= 1 << 9; /* 30 ohms */
-+ }
- }
-- }
-- /* Dram dynamic termination: Disable(1DIMM), 120ohm(>=2DIMM) */
-- if (!(pDCTstat->Status & (1 << SB_Registered))) {
-- if (byte >= 2) {
-- if (pDCTstat->Speed == 7)
-- DramMRS |= 1 << 10;
-- else
-- DramMRS |= 1 << 11;
-+ /* Dram dynamic termination: Disable(1DIMM), 120ohm(>=2DIMM) */
-+ if (!(pDCTstat->Status & (1 << SB_Registered))) {
-+ if (byte >= 2) {
-+ if (pDCTstat->Speed == 7)
-+ DramMRS |= 1 << 10;
-+ else
-+ DramMRS |= 1 << 11;
-+ }
-+ } else {
-+ DramMRS |= mct_DramTermDyn_RDimm(pMCTstat, pDCTstat, byte);
- }
-- } else {
-- DramMRS |= mct_DramTermDyn_RDimm(pMCTstat, pDCTstat, byte);
-+
-+ /* Qoff=0, output buffers enabled */
-+ /* Tcwl */
-+ DramMRS |= (pDCTstat->Speed - 4) << 20;
-+ /* ASR=1, auto self refresh */
-+ /* SRT=0 */
-+ DramMRS |= 1 << 18;
- }
-
- /* burst length control */
- if (pDCTstat->Status & (1 << SB_128bitmode))
- DramMRS |= 1 << 1;
-- /* Qoff=0, output buffers enabled */
-- /* Tcwl */
-- DramMRS |= (pDCTstat->Speed - 4) << 20;
-- /* ASR=1, auto self refresh */
-- /* SRT=0 */
-- DramMRS |= 1 << 18;
--
-- dword = Get_NB32(pDCTstat->dev_dct, 0x100 * dct + 0x84);
-- dword &= ~0x00FC2F8F;
-+
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x84);
-+ if (is_fam15h())
-+ dword &= ~0x00800003;
-+ else
-+ dword &= ~0x00fc2f8f;
- dword |= DramMRS;
-- Set_NB32(pDCTstat->dev_dct, 0x100 * dct + 0x84, dword);
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x84, dword);
- }
-
--void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct,
-- u32 DramConfigHi)
-+void mct_SetDramConfigHi_D(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u32 dct, u32 DramConfigHi)
- {
- /* Bug#15114: Comp. update interrupted by Freq. change can cause
- * subsequent update to be invalid during any MemClk frequency change:
-@@ -3778,45 +5911,86 @@ void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct,
- */
-
- u32 dev = pDCTstat->dev_dct;
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ u32 index_reg = 0x98;
- u32 index;
-
-- u32 val;
-+ uint32_t dword;
-+
-+ if (is_fam15h()) {
-+ /* Initial setup for frequency change
-+ * 9C_x0000_0004 must be configured before MemClkFreqVal is set
-+ */
-
-- index = 0x08;
-- val = Get_NB32_index_wait(dev, index_reg, index);
-- if (!(val & (1 << DisAutoComp)))
-- Set_NB32_index_wait(dev, index_reg, index, val | (1 << DisAutoComp));
-+ /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0x190 */
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006);
-+ dword &= ~(0x0000ffff);
-+ dword |= 0x00000190;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006, dword);
-
-- mct_Wait(100);
-+ dword = Get_NB32_DCT(dev, dct, 0x94);
-+ dword &= ~(1 << MemClkFreqVal);
-+ Set_NB32_DCT(dev, dct, 0x94, dword);
-
-- Set_NB32(dev, 0x94 + 0x100 * dct, DramConfigHi);
-+ dword = DramConfigHi;
-+ dword &= ~(1 << MemClkFreqVal);
-+ Set_NB32_DCT(dev, dct, 0x94, dword);
-+
-+ mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct);
-+ set_2t_configuration(pMCTstat, pDCTstat, dct);
-+ mct_BeforePlatformSpec(pMCTstat, pDCTstat, dct);
-+ mct_PlatformSpec(pMCTstat, pDCTstat, dct);
-+ } else {
-+ index = 0x08;
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
-+ if (!(dword & (1 << DisAutoComp)))
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, index, dword | (1 << DisAutoComp));
-+
-+ mct_Wait(100);
-+ }
-+
-+ /* Program the DRAM Configuration High register */
-+ Set_NB32_DCT(dev, dct, 0x94, DramConfigHi);
-+
-+ if (is_fam15h()) {
-+ /* Wait until F2x[1, 0]94[FreqChgInProg]=0. */
-+ do {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94);
-+ } while (dword & (1 << FreqChgInProg));
-+
-+ /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0xf */
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006);
-+ dword &= ~(0x0000ffff);
-+ dword |= 0x0000000f;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006, dword);
-+ }
- }
-
- static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA)
- {
-- u8 Node;
-- struct DCTStatStruc *pDCTstat;
-+ if (!is_fam15h()) {
-+ u8 Node;
-+ struct DCTStatStruc *pDCTstat;
-
-- /* Errata 178
-- *
-- * Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
-- * In TX FIFO
-- * Solution: BIOS should program DRAM Control Register[RdPtrInit] =
-- * 5h, (F2x[1, 0]78[3:0] = 5h).
-- * Silicon Status: Fixed In Rev B0
-- *
-- * Bug#15880: Determine validity of reset settings for DDR PHY timing.
-- * Solution: At least, set WrDqs fine delay to be 0 for DDR3 training.
-- */
-- for (Node = 0; Node < 8; Node++) {
-- pDCTstat = pDCTstatA + Node;
-+ /* Errata 178
-+ *
-+ * Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
-+ * In TX FIFO
-+ * Solution: BIOS should program DRAM Control Register[RdPtrInit] =
-+ * 5h, (F2x[1, 0]78[3:0] = 5h).
-+ * Silicon Status: Fixed In Rev B0
-+ *
-+ * Bug#15880: Determine validity of reset settings for DDR PHY timing.
-+ * Solution: At least, set WrDqs fine delay to be 0 for DDR3 training.
-+ */
-+ for (Node = 0; Node < 8; Node++) {
-+ pDCTstat = pDCTstatA + Node;
-
-- if (pDCTstat->NodePresent) {
-- mct_BeforeDQSTrainSamp(pDCTstat); /* only Bx */
-- mct_ResetDLL_D(pMCTstat, pDCTstat, 0);
-- mct_ResetDLL_D(pMCTstat, pDCTstat, 1);
-+ if (pDCTstat->NodePresent) {
-+ mct_BeforeDQSTrainSamp(pDCTstat); /* only Bx */
-+ mct_ResetDLL_D(pMCTstat, pDCTstat, 0);
-+ mct_ResetDLL_D(pMCTstat, pDCTstat, 1);
-+ }
- }
- }
- }
-@@ -3827,7 +6001,6 @@ static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
- {
- u8 Receiver;
- u32 dev = pDCTstat->dev_dct;
-- u32 reg_off = 0x100 * dct;
- u32 addr;
- u32 lo, hi;
- u8 wrap32dis = 0;
-@@ -3838,6 +6011,11 @@ static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
- return;
- }
-
-+ /* Skip reset DLL for Family 15h */
-+ if (is_fam15h()) {
-+ return;
-+ }
-+
- addr = HWCR;
- _RDMSR(addr, &lo, &hi);
- if(lo & (1<<17)) { /* save the old value */
-@@ -3857,11 +6035,11 @@ static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
- mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr); /* cache fills */
-
- /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */
-- Set_NB32_index_wait(dev, 0x98 + reg_off, 0xD080F0C, 0x00008000);
-+ Set_NB32_index_wait_DCT(dev, dct, 0x98, 0xD080F0C, 0x00008000);
- mct_Wait(80); /* wait >= 300ns */
-
- /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */
-- Set_NB32_index_wait(dev, 0x98 + reg_off, 0xD080F0C, 0x00000000);
-+ Set_NB32_index_wait_DCT(dev, dct, 0x98, 0xD080F0C, 0x00000000);
- mct_Wait(800); /* wait >= 2us */
- break;
- }
-@@ -3901,39 +6079,39 @@ static void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat,
- static void SetDllSpeedUp_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 val;
-- u32 dev = pDCTstat->dev_dct;
-- u32 reg_off = 0x100 * dct;
--
-- if (pDCTstat->Speed >= 7) { /* DDR1600 and above */
-- /* Set bit13 PowerDown to register F2x[1, 0]98_x0D080F10 */
-- Set_NB32(dev, reg_off + 0x98, 0x0D080F10);
-- val = Get_NB32(dev, reg_off + 0x9C);
-- val |= 1 < 13;
-- Set_NB32(dev, reg_off + 0x9C, val);
-- Set_NB32(dev, reg_off + 0x98, 0x4D080F10);
--
-- /* Set bit13 PowerDown to register F2x[1, 0]98_x0D080F11 */
-- Set_NB32(dev, reg_off + 0x98, 0x0D080F11);
-- val = Get_NB32(dev, reg_off + 0x9C);
-- val |= 1 < 13;
-- Set_NB32(dev, reg_off + 0x9C, val);
-- Set_NB32(dev, reg_off + 0x98, 0x4D080F11);
--
-- /* Set bit13 PowerDown to register F2x[1, 0]98_x0D088F30 */
-- Set_NB32(dev, reg_off + 0x98, 0x0D088F30);
-- val = Get_NB32(dev, reg_off + 0x9C);
-- val |= 1 < 13;
-- Set_NB32(dev, reg_off + 0x9C, val);
-- Set_NB32(dev, reg_off + 0x98, 0x4D088F30);
--
-- /* Set bit13 PowerDown to register F2x[1, 0]98_x0D08CF30 */
-- Set_NB32(dev, reg_off + 0x98, 0x0D08CF30);
-- val = Get_NB32(dev, reg_off + 0x9C);
-- val |= 1 < 13;
-- Set_NB32(dev, reg_off + 0x9C, val);
-- Set_NB32(dev, reg_off + 0x98, 0x4D08CF30);
--
-+ if (!is_fam15h()) {
-+ u32 val;
-+ u32 dev = pDCTstat->dev_dct;
-+
-+ if (pDCTstat->Speed >= mhz_to_memclk_config(800)) { /* DDR1600 and above */
-+ /* Set bit13 PowerDown to register F2x[1, 0]98_x0D080F10 */
-+ Set_NB32_DCT(dev, dct, 0x98, 0x0D080F10);
-+ val = Get_NB32_DCT(dev, dct, 0x9C);
-+ val |= 1 < 13;
-+ Set_NB32_DCT(dev, dct, 0x9C, val);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D080F10);
-+
-+ /* Set bit13 PowerDown to register F2x[1, 0]98_x0D080F11 */
-+ Set_NB32_DCT(dev, dct, 0x98, 0x0D080F11);
-+ val = Get_NB32_DCT(dev, dct, 0x9C);
-+ val |= 1 < 13;
-+ Set_NB32_DCT(dev, dct, 0x9C, val);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D080F11);
-+
-+ /* Set bit13 PowerDown to register F2x[1, 0]98_x0D088F30 */
-+ Set_NB32_DCT(dev, dct, 0x98, 0x0D088F30);
-+ val = Get_NB32_DCT(dev, dct, 0x9C);
-+ val |= 1 < 13;
-+ Set_NB32_DCT(dev, dct, 0x9C, val);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D088F30);
-+
-+ /* Set bit13 PowerDown to register F2x[1, 0]98_x0D08CF30 */
-+ Set_NB32_DCT(dev, dct, 0x98, 0x0D08CF30);
-+ val = Get_NB32_DCT(dev, dct, 0x9C);
-+ val |= 1 < 13;
-+ Set_NB32_DCT(dev, dct, 0x9C, val);
-+ Set_NB32_DCT(dev, dct, 0x98, 0x4D08CF30);
-+ }
- }
- }
-
-@@ -3961,7 +6139,6 @@ static void SyncSetting(struct DCTStatStruc *pDCTstat)
- static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) {
-
- u32 val;
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
-
- if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) {
-@@ -3969,16 +6146,16 @@ static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) {
- val = Get_NB32(dev, 0x110);
- if (!(val & (1 << DramEnabled))) {
- /* If 50 us expires while DramEnable =0 then do the following */
-- val = Get_NB32(dev, 0x90 + reg_off);
-+ val = Get_NB32_DCT(dev, dct, 0x90);
- val &= ~(1 << Width128); /* Program Width128 = 0 */
-- Set_NB32(dev, 0x90 + reg_off, val);
-+ Set_NB32_DCT(dev, dct, 0x90, val);
-
-- val = Get_NB32_index_wait(dev, 0x98 + reg_off, 0x05); /* Perform dummy CSR read to F2x09C_x05 */
-+ val = Get_NB32_index_wait_DCT(dev, dct, 0x98, 0x05); /* Perform dummy CSR read to F2x09C_x05 */
-
- if (pDCTstat->GangedMode) {
-- val = Get_NB32(dev, 0x90 + reg_off);
-+ val = Get_NB32_DCT(dev, dct, 0x90);
- val |= 1 << Width128; /* Program Width128 = 0 */
-- Set_NB32(dev, 0x90 + reg_off, val);
-+ Set_NB32_DCT(dev, dct, 0x90, val);
- }
- }
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-index a947c2d..50fbff7 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-@@ -76,6 +76,8 @@
- /* #define PA_EXT_DCTADDL (((00 << 3)+5) << 8) */ /*Node x DCT function, Additional Registers PCI Address bits [15:0]*/
-
- #define PA_NBMISC(Node) ((((0x18+Node) << 3)+3) << 12) /*Node 0 Misc PCI Address bits [15:0]*/
-+#define PA_LINK(Node) ((((0x18+Node) << 3)+4) << 12) /*Node 0 Link Control bits [15:0]*/
-+#define PA_NBCTL(Node) ((((0x18+Node) << 3)+5) << 12) /*Node 0 NB Control PCI Address bits [15:0]*/
- /* #define PA_NBDEVOP (((00 << 3)+3) << 8) */ /*Node 0 Misc PCI Address bits [15:0]*/
-
- #define DCC_EN 1 /* X:2:0x94[19]*/
-@@ -129,7 +131,7 @@
- #define X4Dimm 12 /* func 2, offset 90h, bit 12*/
- #define UnBuffDimm 16 /* func 2, offset 90h, bit 16*/
- #define DimmEcEn 19 /* func 2, offset 90h, bit 19*/
--#define MemClkFreqVal 3 /* func 2, offset 94h, bit 3*/
-+#define MemClkFreqVal ((is_fam15h())?7:3) /* func 2, offset 94h, bit 3 or 7*/
- #define RDqsEn 12 /* func 2, offset 94h, bit 12*/
- #define DisDramInterface 14 /* func 2, offset 94h, bit 14*/
- #define PowerDownEn 15 /* func 2, offset 94h, bit 15*/
-@@ -204,6 +206,7 @@
- #define JED_PROBEMSK 0x40 /*Analysis Probe installed*/
- #define JED_RDIMM 0x1 /* RDIMM */
- #define JED_MiniRDIMM 0x5 /* Mini-RDIMM */
-+ #define JED_LRDIMM 0xb /* Load-reduced DIMM */
- #define SPD_Density 4 /* Bank address bits,SDRAM capacity */
- #define SPD_Addressing 5 /* Row/Column address bits */
- #define SPD_Voltage 6 /* Supported voltage bitfield */
-@@ -297,6 +300,7 @@ struct MCTStatStruc {
- of sub 4GB dram hole for HW remapping.*/
- u32 Sub4GCacheTop; /* If not zero, the 32-bit top of cacheable memory.*/
- u32 SysLimit; /* LIMIT[39:8] (system address)*/
-+ uint32_t TSCFreq;
- } __attribute__((packed));
-
- /*=============================================================================
-@@ -320,7 +324,8 @@ struct MCTStatStruc {
-
- struct DCTStatStruc { /* A per Node structure*/
- /* DCTStatStruct_F - start */
-- u8 Node_ID; /* Node ID of current controller*/
-+ u8 Node_ID; /* Node ID of current controller */
-+ uint8_t stopDCT; /* Set if the DCT will be stopped */
- u8 ErrCode; /* Current error condition of Node
- 0= no error
- 1= Variance Error, DCT is running but not in an optimal configuration.
-@@ -464,7 +469,7 @@ struct DCTStatStruc { /* A per Node structure*/
- /* CH A byte lane 0 - 7 maximum filtered window passing DQS delay value*/
- /* CH B byte lane 0 - 7 minimum filtered window passing DQS delay value*/
- /* CH B byte lane 0 - 7 maximum filtered window passing DQS delay value*/
-- u32 LogicalCPUID; /* The logical CPUID of the node*/
-+ uint64_t LogicalCPUID; /* The logical CPUID of the node*/
- u16 HostBiosSrvc1; /* Word sized general purpose field for use by host BIOS. Scratch space.*/
- u32 HostBiosSrvc2; /* Dword sized general purpose field for use by host BIOS. Scratch space.*/
- u16 DimmQRPresent; /* QuadRank DIMM present?*/
-@@ -558,12 +563,20 @@ struct DCTStatStruc { /* A per Node structure*/
- u8 ClToNB_flag; /* is used to restore ClLinesToNbDis bit after memory */
- u32 NodeSysBase; /* for channel interleave usage */
-
-+ /* Fam15h specific backup variables */
-+ uint8_t SwNbPstateLoDis;
-+ uint8_t NbPstateDisOnP0;
-+ uint8_t NbPstateThreshold;
-+ uint8_t NbPstateHi;
-+
- /* New for LB Support */
- u8 NodePresent;
- u32 dev_host;
- u32 dev_map;
- u32 dev_dct;
- u32 dev_nbmisc;
-+ u32 dev_link;
-+ u32 dev_nbctl;
- u8 TargetFreq;
- u8 TargetCASL;
- u8 CtrlWrd3;
-@@ -596,9 +609,10 @@ struct DCTStatStruc { /* A per Node structure*/
- uint8_t DimmBanks[MAX_DIMMS_SUPPORTED];
- uint8_t DimmWidth[MAX_DIMMS_SUPPORTED];
- uint8_t DimmRegistered[MAX_DIMMS_SUPPORTED];
-+ uint8_t DimmLoadReduced[MAX_DIMMS_SUPPORTED];
-
- uint64_t DimmManufacturerID[MAX_DIMMS_SUPPORTED];
-- char DimmPartNumber[MAX_DIMMS_SUPPORTED][SPD_PARTN_LENGTH];
-+ char DimmPartNumber[MAX_DIMMS_SUPPORTED][SPD_PARTN_LENGTH+1];
- uint16_t DimmRevisionNumber[MAX_DIMMS_SUPPORTED];
- uint32_t DimmSerialNumber[MAX_DIMMS_SUPPORTED];
- } __attribute__((packed));
-@@ -701,7 +715,64 @@ struct amd_s3_persistent_mct_channel_data {
- /* Other (1 dword) */
- uint32_t f3x58;
-
-- /* TOTAL: 250 dwords */
-+ /* Family 15h-specific registers (90 dwords) */
-+ uint32_t f2x200;
-+ uint32_t f2x204;
-+ uint32_t f2x208;
-+ uint32_t f2x20c;
-+ uint32_t f2x210[4]; /* [nb pstate] */
-+ uint32_t f2x214;
-+ uint32_t f2x218;
-+ uint32_t f2x21c;
-+ uint32_t f2x22c;
-+ uint32_t f2x230;
-+ uint32_t f2x234;
-+ uint32_t f2x238;
-+ uint32_t f2x23c;
-+ uint32_t f2x240;
-+ uint32_t f2x9cx0d0fe003;
-+ uint32_t f2x9cx0d0fe013;
-+ uint32_t f2x9cx0d0f0_8_0_1f[9]; /* [lane]*/
-+ uint32_t f2x9cx0d0f201f;
-+ uint32_t f2x9cx0d0f211f;
-+ uint32_t f2x9cx0d0f221f;
-+ uint32_t f2x9cx0d0f801f;
-+ uint32_t f2x9cx0d0f811f;
-+ uint32_t f2x9cx0d0f821f;
-+ uint32_t f2x9cx0d0fc01f;
-+ uint32_t f2x9cx0d0fc11f;
-+ uint32_t f2x9cx0d0fc21f;
-+ uint32_t f2x9cx0d0f4009;
-+ uint32_t f2x9cx0d0f0_8_0_02[9]; /* [lane]*/
-+ uint32_t f2x9cx0d0f0_8_0_06[9]; /* [lane]*/
-+ uint32_t f2x9cx0d0f0_8_0_0a[9]; /* [lane]*/
-+ uint32_t f2x9cx0d0f2002;
-+ uint32_t f2x9cx0d0f2102;
-+ uint32_t f2x9cx0d0f2202;
-+ uint32_t f2x9cx0d0f8002;
-+ uint32_t f2x9cx0d0f8006;
-+ uint32_t f2x9cx0d0f800a;
-+ uint32_t f2x9cx0d0f8102;
-+ uint32_t f2x9cx0d0f8106;
-+ uint32_t f2x9cx0d0f810a;
-+ uint32_t f2x9cx0d0fc002;
-+ uint32_t f2x9cx0d0fc006;
-+ uint32_t f2x9cx0d0fc00a;
-+ uint32_t f2x9cx0d0fc00e;
-+ uint32_t f2x9cx0d0fc012;
-+ uint32_t f2x9cx0d0f2031;
-+ uint32_t f2x9cx0d0f2131;
-+ uint32_t f2x9cx0d0f2231;
-+ uint32_t f2x9cx0d0f8031;
-+ uint32_t f2x9cx0d0f8131;
-+ uint32_t f2x9cx0d0f8231;
-+ uint32_t f2x9cx0d0fc031;
-+ uint32_t f2x9cx0d0fc131;
-+ uint32_t f2x9cx0d0fc231;
-+ uint32_t f2x9cx0d0f0_0_f_31[9]; /* [lane] */
-+ uint32_t f2x9cx0d0f8021;
-+
-+ /* TOTAL: 340 dwords */
- } __attribute__((packed));
-
- struct amd_s3_persistent_node_data {
-@@ -746,18 +817,19 @@ struct amd_s3_persistent_data {
- Local Configuration Status (DCTStatStruc.Status[31:0])
- ===============================================================================*/
- #define SB_Registered 0 /* All DIMMs are Registered*/
--#define SB_ECCDIMMs 1 /* All banks ECC capable*/
--#define SB_PARDIMMs 2 /* All banks Addr/CMD Parity capable*/
--#define SB_DiagClks 3 /* Jedec ALL slots clock enable diag mode*/
--#define SB_128bitmode 4 /* DCT in 128-bit mode operation*/
--#define SB_64MuxedMode 5 /* DCT in 64-bit mux'ed mode.*/
--#define SB_2TMode 6 /* 2T CMD timing mode is enabled.*/
--#define SB_SWNodeHole 7 /* Remapping of Node Base on this Node to create a gap.*/
--#define SB_HWHole 8 /* Memory Hole created on this Node using HW remapping.*/
--#define SB_Over400MHz 9 /* DCT freq >= 400MHz flag*/
--#define SB_DQSPos_Pass2 10 /* Using for TrainDQSPos DIMM0/1, when freq>=400MHz*/
--#define SB_DQSRcvLimit 11 /* Using for DQSRcvEnTrain to know we have reached to upper bound.*/
--#define SB_ExtConfig 12 /* Indicator the default setting for extend PCI configuration support*/
-+#define SB_LoadReduced 1 /* All DIMMs are Load-Reduced*/
-+#define SB_ECCDIMMs 2 /* All banks ECC capable*/
-+#define SB_PARDIMMs 3 /* All banks Addr/CMD Parity capable*/
-+#define SB_DiagClks 4 /* Jedec ALL slots clock enable diag mode*/
-+#define SB_128bitmode 5 /* DCT in 128-bit mode operation*/
-+#define SB_64MuxedMode 6 /* DCT in 64-bit mux'ed mode.*/
-+#define SB_2TMode 7 /* 2T CMD timing mode is enabled.*/
-+#define SB_SWNodeHole 8 /* Remapping of Node Base on this Node to create a gap.*/
-+#define SB_HWHole 9 /* Memory Hole created on this Node using HW remapping.*/
-+#define SB_Over400MHz 10 /* DCT freq >= 400MHz flag*/
-+#define SB_DQSPos_Pass2 11 /* Using for TrainDQSPos DIMM0/1, when freq>=400MHz*/
-+#define SB_DQSRcvLimit 12 /* Using for DQSRcvEnTrain to know we have reached to upper bound.*/
-+#define SB_ExtConfig 13 /* Indicator the default setting for extend PCI configuration support*/
-
-
- /*===============================================================================
-@@ -775,17 +847,18 @@ struct amd_s3_persistent_data {
- 266=266MHz (DDR533)
- 333=333MHz (DDR667)
- 400=400MHz (DDR800)*/
--#define NV_ECC_CAP 4 /* Bus ECC capable (1-bits)
-+#define NV_MIN_MEMCLK 4 /* Minimum platform demonstrated Memclock (10-bits) */
-+#define NV_ECC_CAP 5 /* Bus ECC capable (1-bits)
- 0=Platform not capable
- 1=Platform is capable*/
--#define NV_4RANKType 5 /* Quad Rank DIMM slot type (2-bits)
-+#define NV_4RANKType 6 /* Quad Rank DIMM slot type (2-bits)
- 0=Normal
- 1=R4 (4-Rank Registered DIMMs in AMD server configuration)
- 2=S4 (Unbuffered SO-DIMMs)*/
--#define NV_BYPMAX 6 /* Value to set DcqBypassMax field (See Function 2, Offset 94h, [27:24] of BKDG for field definition).
-+#define NV_BYPMAX 7 /* Value to set DcqBypassMax field (See Function 2, Offset 94h, [27:24] of BKDG for field definition).
- 4=4 times bypass (normal for non-UMA systems)
- 7=7 times bypass (normal for UMA systems)*/
--#define NV_RDWRQBYP 7 /* Value to set RdWrQByp field (See Function 2, Offset A0h, [3:2] of BKDG for field definition).
-+#define NV_RDWRQBYP 8 /* Value to set RdWrQByp field (See Function 2, Offset A0h, [3:2] of BKDG for field definition).
- 2=8 times (normal for non-UMA systems)
- 3=16 times (normal for UMA systems)*/
-
-@@ -848,8 +921,9 @@ struct amd_s3_persistent_data {
- #define NV_ECCRedir 54 /* Dram ECC Redirection enable*/
- #define NV_DramBKScrub 55 /* Dram ECC Background Scrubber CTL*/
- #define NV_L2BKScrub 56 /* L2 ECC Background Scrubber CTL*/
--#define NV_DCBKScrub 57 /* DCache ECC Background Scrubber CTL*/
--#define NV_CS_SpareCTL 58 /* Chip Select Spare Control bit 0:
-+#define NV_L3BKScrub 57 /* L3 ECC Background Scrubber CTL*/
-+#define NV_DCBKScrub 58 /* DCache ECC Background Scrubber CTL*/
-+#define NV_CS_SpareCTL 59 /* Chip Select Spare Control bit 0:
- 0=disable Spare
- 1=enable Spare */
- /* Chip Select Spare Control bit 1-4:
-@@ -900,10 +974,12 @@ void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u8 FinalVa
- void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel);
- void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 dct);
- void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct);
--void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct, u32 DramConfigHi);
-+void mct_SetDramConfigHi_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 dct, u32 DramConfigHi);
- void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct);
- void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
- void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
-+void mct_ForceNBPState0_En_Fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
-+void mct_ForceNBPState0_Dis_Fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
- void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 Pass);
- void mct_EnableDimmEccEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 _DisableDramECC);
- u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
-index c40ea1a..f6aa755 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
-@@ -98,6 +98,15 @@ static u32 bsf(u32 x)
-
- u32 SetUpperFSbase(u32 addr_hi);
-
-+static void proc_MFENCE(void)
-+{
-+ __asm__ volatile (
-+ "outb %%al, $0xed\n\t" /* _EXECFENCE */
-+ "mfence\n\t"
-+ :::"memory"
-+ );
-+}
-+
- static void proc_CLFLUSH(u32 addr_hi)
- {
- SetUpperFSbase(addr_hi);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c b/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c
-index 126642b..3df262b 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -17,6 +18,8 @@
- * Foundation, Inc.
- */
-
-+/* AM3/ASB2/C32/G34 DDR3 */
-+
- static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
- u32 *AddrTmgCTL, u32 *ODC_CTL,
- u8 *CMDmode);
-@@ -24,17 +27,23 @@ static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
- void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u32 dct)
- {
-- Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed,
-- pDCTstat->MAload[dct],
-- &(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct]),
-- &pDCTstat->_2Tmode);
-+ if (is_fam15h()) {
-+ pDCTstat->CH_ADDR_TMG[dct] = fam15h_address_timing_compensation_code(pDCTstat, dct);
-+ pDCTstat->CH_ODC_CTL[dct] = fam15h_output_driver_compensation_code(pDCTstat, dct);
-+ pDCTstat->_2Tmode = fam15h_slow_access_mode(pDCTstat, dct);
-+ } else {
-+ Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed,
-+ pDCTstat->MAload[dct],
-+ &(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct]),
-+ &pDCTstat->_2Tmode);
-+
-+ pDCTstat->CH_ODC_CTL[dct] |= 0x20000000; /* 60ohms */
-+ }
-
- pDCTstat->CH_EccDQSLike[0] = 0x0403;
- pDCTstat->CH_EccDQSScale[0] = 0x70;
- pDCTstat->CH_EccDQSLike[1] = 0x0403;
- pDCTstat->CH_EccDQSScale[1] = 0x70;
--
-- pDCTstat->CH_ODC_CTL[dct] |= 0x20000000; /* 60ohms */
- }
-
- /*
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c
-index f1fd7a5..a1cdfa6 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -35,7 +36,6 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
-
- u32 dev;
- u32 reg;
-- u32 reg_off;
- u32 val;
- u32 val_lo, val_hi;
-
-@@ -44,16 +44,15 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
- EnChipSels = 0;
-
- dev = pDCTstat->dev_dct;
-- reg_off = 0x100 * dct;
-
- ChipSel = 0; /* Find out if current configuration is capable */
- while (DoIntlv && (ChipSel < MAX_CS_SUPPORTED)) {
-- reg = 0x40+(ChipSel<<2) + reg_off; /* Dram CS Base 0 */
-- val = Get_NB32(dev, reg);
-+ reg = 0x40+(ChipSel<<2); /* Dram CS Base 0 */
-+ val = Get_NB32_DCT(dev, dct, reg);
- if ( val & (1<<CSEnable)) {
- EnChipSels++;
-- reg = 0x60+((ChipSel>>1)<<2)+reg_off; /*Dram CS Mask 0 */
-- val = Get_NB32(dev, reg);
-+ reg = 0x60+((ChipSel>>1)<<2); /*Dram CS Mask 0 */
-+ val = Get_NB32_DCT(dev, dct, reg);
- val >>= 19;
- val &= 0x3ff;
- val++;
-@@ -63,8 +62,8 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
- /*If mask sizes not same then skip */
- if (val != MemSize)
- break;
-- reg = 0x80 + reg_off; /*Dram Bank Addressing */
-- val = Get_NB32(dev, reg);
-+ reg = 0x80; /*Dram Bank Addressing */
-+ val = Get_NB32_DCT(dev, dct, reg);
- val >>= (ChipSel>>1)<<2;
- val &= 0x0f;
- if(EnChipSels == 1)
-@@ -103,8 +102,8 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
- BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask);
-
- for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) {
-- reg = 0x40+(ChipSel<<2) + reg_off; /*Dram CS Base 0 */
-- val = Get_NB32(dev, reg);
-+ reg = 0x40+(ChipSel<<2); /*Dram CS Base 0 */
-+ val = Get_NB32_DCT(dev, dct, reg);
- if (val & 3) {
- val_lo = val & AddrLoMask;
- val_hi = val & AddrHiMask;
-@@ -114,13 +113,13 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
- val_hi >>= BitDelta;
- val |= val_lo;
- val |= val_hi;
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
-
- if(ChipSel & 1)
- continue;
-
-- reg = 0x60 + ((ChipSel>>1)<<2) + reg_off; /*Dram CS Mask 0 */
-- val = Get_NB32(dev, reg);
-+ reg = 0x60 + ((ChipSel>>1)<<2); /*Dram CS Mask 0 */
-+ val = Get_NB32_DCT(dev, dct, reg);
- val_lo = val & AddrLoMask;
- val_hi = val & AddrHiMask;
- val &= AddrLoMaskN;
-@@ -129,7 +128,7 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
- val_hi >>= BitDelta;
- val |= val_lo;
- val |= val_hi;
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- }
- }
- } /* DoIntlv */
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
-index cc2f43a..740edae 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
-@@ -18,6 +18,12 @@
- * Foundation, Inc.
- */
-
-+static void write_dqs_receiver_enable_control_registers(uint16_t* current_total_delay,
-+ uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg);
-+
-+static void read_read_dqs_timing_control_registers(uint16_t* current_total_delay,
-+ uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg);
-+
- static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u16 like,
- u8 scale, u8 ChipSel);
-@@ -37,7 +43,7 @@ static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat,
- u32 addr_lo);
- static void SetTargetWTIO_D(u32 TestAddr);
- static void ResetTargetWTIO_D(void);
--void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index);
-+void ResetDCTWrPtr_D(u32 dev, uint8_t dct, u32 index_reg, u32 index);
- u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
- static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat,
-@@ -54,6 +60,7 @@ static void proc_IOCLFLUSH_D(u32 addr_hi);
- static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 ChipSel);
-
- #define DQS_TRAIN_DEBUG 0
-+// #define PRINT_PASS_FAIL_BITMAPS 1
-
- static void print_debug_dqs(const char *str, u32 val, u8 level)
- {
-@@ -198,18 +205,20 @@ void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat,
- pDCTstat = pDCTstatA + Node;
-
- if (pDCTstat->DCTSysLimit) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x78);
-- val |= 1 <<DqsRcvEnTrain;
-- Set_NB32(pDCTstat->dev_dct, 0x78, val);
-- val = Get_NB32(pDCTstat->dev_dct, 0x78 + 0x100);
-- val |= 1 <<DqsRcvEnTrain;
-- Set_NB32(pDCTstat->dev_dct, 0x78 + 0x100, val);
-+ if (!is_fam15h()) {
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x78);
-+ val |= 1 <<DqsRcvEnTrain;
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x78, val);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x78);
-+ val |= 1 <<DqsRcvEnTrain;
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x78, val);
-+ }
- mct_TrainRcvrEn_D(pMCTstat, pDCTstat, Pass);
- }
- }
- }
-
--static void SetEccDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
-+static void SetEccDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 ChipSel)
- {
- u8 channel;
-@@ -268,68 +277,150 @@ static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat,
- pDCTstat->DQSDelay = (u8)DQSDelay;
- }
-
--static void write_dqs_write_data_timing_registers(uint16_t* delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
-+static void read_dqs_write_data_timing_registers(uint16_t* delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint32_t dword;
-+ uint32_t mask;
-+
-+ if (is_fam15h())
-+ mask = 0xff;
-+ else
-+ mask = 0x7f;
-+
-+ /* Lanes 0 - 3 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x1 | (dimm << 8));
-+ delay[3] = (dword >> 24) & mask;
-+ delay[2] = (dword >> 16) & mask;
-+ delay[1] = (dword >> 8) & mask;
-+ delay[0] = dword & mask;
-+
-+ /* Lanes 4 - 7 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x2 | (dimm << 8));
-+ delay[7] = (dword >> 24) & mask;
-+ delay[6] = (dword >> 16) & mask;
-+ delay[5] = (dword >> 8) & mask;
-+ delay[4] = dword & mask;
-+
-+ /* Lane 8 (ECC) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x3 | (dimm << 8));
-+ delay[8] = dword & mask;
-+}
-+
-+static void write_dqs_write_data_timing_registers(uint16_t* delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
- {
- uint32_t dword;
-+ uint32_t mask;
-+
-+ if (is_fam15h())
-+ mask = 0xff;
-+ else
-+ mask = 0x7f;
-
- /* Lanes 0 - 3 */
-- dword = Get_NB32_index_wait(dev, index_reg, 0x1 | (dimm << 8));
-- dword &= ~0x7f7f7f7f;
-- dword |= (delay[3] & 0x7f) << 24;
-- dword |= (delay[2] & 0x7f) << 16;
-- dword |= (delay[1] & 0x7f) << 8;
-- dword |= delay[0] & 0x7f;
-- Set_NB32_index_wait(dev, index_reg, 0x1 | (dimm << 8), dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x1 | (dimm << 8));
-+ dword &= ~(mask << 24);
-+ dword &= ~(mask << 16);
-+ dword &= ~(mask << 8);
-+ dword &= ~mask;
-+ dword |= (delay[3] & mask) << 24;
-+ dword |= (delay[2] & mask) << 16;
-+ dword |= (delay[1] & mask) << 8;
-+ dword |= delay[0] & mask;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x1 | (dimm << 8), dword);
-
- /* Lanes 4 - 7 */
-- dword = Get_NB32_index_wait(dev, index_reg, 0x2 | (dimm << 8));
-- dword &= ~0x7f7f7f7f;
-- dword |= (delay[7] & 0x7f) << 24;
-- dword |= (delay[6] & 0x7f) << 16;
-- dword |= (delay[5] & 0x7f) << 8;
-- dword |= delay[4] & 0x7f;
-- Set_NB32_index_wait(dev, index_reg, 0x2 | (dimm << 8), dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x2 | (dimm << 8));
-+ dword &= ~(mask << 24);
-+ dword &= ~(mask << 16);
-+ dword &= ~(mask << 8);
-+ dword &= ~mask;
-+ dword |= (delay[7] & mask) << 24;
-+ dword |= (delay[6] & mask) << 16;
-+ dword |= (delay[5] & mask) << 8;
-+ dword |= delay[4] & mask;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x2 | (dimm << 8), dword);
-
- /* Lane 8 (ECC) */
-- dword = Get_NB32_index_wait(dev, index_reg, 0x3 | (dimm << 8));
-- dword &= ~0x0000007f;
-- dword |= delay[8] & 0x7f;
-- Set_NB32_index_wait(dev, index_reg, 0x3 | (dimm << 8), dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x3 | (dimm << 8));
-+ dword &= ~mask;
-+ dword |= delay[8] & mask;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x3 | (dimm << 8), dword);
- }
-
--static void write_dqs_read_data_timing_registers(uint16_t* delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
-+static void read_dqs_read_data_timing_registers(uint16_t* delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
- {
- uint32_t dword;
-+ uint32_t mask;
-+
-+ if (is_fam15h())
-+ mask = 0x3e;
-+ else
-+ mask = 0x3f;
-
- /* Lanes 0 - 3 */
-- dword = Get_NB32_index_wait(dev, index_reg, 0x5 | (dimm << 8));
-- dword &= ~0x3f3f3f3f;
-- dword |= (delay[3] & 0x3f) << 24;
-- dword |= (delay[2] & 0x3f) << 16;
-- dword |= (delay[1] & 0x3f) << 8;
-- dword |= delay[0] & 0x3f;
-- Set_NB32_index_wait(dev, index_reg, 0x5 | (dimm << 8), dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8));
-+ delay[3] = (dword >> 24) & mask;
-+ delay[2] = (dword >> 16) & mask;
-+ delay[1] = (dword >> 8) & mask;
-+ delay[0] = dword & mask;
-
- /* Lanes 4 - 7 */
-- dword = Get_NB32_index_wait(dev, index_reg, 0x6 | (dimm << 8));
-- dword &= ~0x3f3f3f3f;
-- dword |= (delay[7] & 0x3f) << 24;
-- dword |= (delay[6] & 0x3f) << 16;
-- dword |= (delay[5] & 0x3f) << 8;
-- dword |= delay[4] & 0x3f;
-- Set_NB32_index_wait(dev, index_reg, 0x6 | (dimm << 8), dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8));
-+ delay[7] = (dword >> 24) & mask;
-+ delay[6] = (dword >> 16) & mask;
-+ delay[5] = (dword >> 8) & mask;
-+ delay[4] = dword & mask;
-
- /* Lane 8 (ECC) */
-- dword = Get_NB32_index_wait(dev, index_reg, 0x7 | (dimm << 8));
-- dword &= ~0x0000003f;
-- dword |= delay[8] & 0x3f;
-- Set_NB32_index_wait(dev, index_reg, 0x7 | (dimm << 8), dword);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8));
-+ delay[8] = dword & mask;
-+}
-+
-+static void write_dqs_read_data_timing_registers(uint16_t* delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint32_t dword;
-+ uint32_t mask;
-+
-+ if (is_fam15h())
-+ mask = 0x3e;
-+ else
-+ mask = 0x3f;
-+
-+ /* Lanes 0 - 3 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8));
-+ dword &= ~(mask << 24);
-+ dword &= ~(mask << 16);
-+ dword &= ~(mask << 8);
-+ dword &= ~mask;
-+ dword |= (delay[3] & mask) << 24;
-+ dword |= (delay[2] & mask) << 16;
-+ dword |= (delay[1] & mask) << 8;
-+ dword |= delay[0] & mask;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8), dword);
-+
-+ /* Lanes 4 - 7 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8));
-+ dword &= ~(mask << 24);
-+ dword &= ~(mask << 16);
-+ dword &= ~(mask << 8);
-+ dword &= ~mask;
-+ dword |= (delay[7] & mask) << 24;
-+ dword |= (delay[6] & mask) << 16;
-+ dword |= (delay[5] & mask) << 8;
-+ dword |= delay[4] & mask;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8), dword);
-+
-+ /* Lane 8 (ECC) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8));
-+ dword &= ~mask;
-+ dword |= delay[8] & mask;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8), dword);
- }
-
- /* DQS Position Training
- * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.3
- */
--static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
-+static void TrainDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat)
- {
- u32 Errors;
-@@ -406,7 +497,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- if (pDCTstat->DIMMValidDCT[Channel] == 0) /* mct_BeforeTrainDQSRdWrPos_D */
- continue;
-
-- index_reg = 0x98 + 0x100 * Channel;
-+ index_reg = 0x98;
-
- dual_rank = 0;
- Receiver = mct_InitReceiver_D(pDCTstat, Channel);
-@@ -462,7 +553,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- break;
-
- /* Commit the current Write Data Timing settings to the hardware registers */
-- write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, Channel, (Receiver >> 1), index_reg);
-
- /* Write the DRAM training pattern to the base test address */
- WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8);
-@@ -479,7 +570,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- current_read_dqs_delay[lane] = test_read_dqs_delay;
-
- /* Commit the current Read DQS Timing Control settings to the hardware registers */
-- write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, Channel, (Receiver >> 1), index_reg);
-
- /* Initialize test result variable */
- bytelane_test_results = 0xff;
-@@ -545,7 +636,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- passing_dqs_delay_found[lane] = 1;
-
- /* Commit the current Read DQS Timing Control settings to the hardware registers */
-- write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, Channel, (Receiver >> 1), index_reg);
-
- /* Exit the DRAM Write Data Timing Loop */
- write_dqs_delay_stepping_done[lane] = 1;
-@@ -579,7 +670,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- current_write_dqs_delay[lane] = test_write_dqs_delay;
-
- /* Commit the current Write Data Timing settings to the hardware registers */
-- write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, Channel, (Receiver >> 1), index_reg);
-
- /* Write the DRAM training pattern to the base test address */
- WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8);
-@@ -674,7 +765,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- current_read_dqs_delay[lane] = (best_pos + (best_count / 2));
-
- /* Commit the current Read DQS Timing Control settings to the hardware registers */
-- write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, Channel, (Receiver >> 1), index_reg);
-
- /* Save the final Read DQS Timing Control settings for later use */
- pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_READDIR][lane] = current_read_dqs_delay[lane];
-@@ -717,7 +808,7 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- current_write_dqs_delay[lane] = (best_pos + (best_count / 2));
-
- /* Commit the current Write Data Timing settings to the hardware registers */
-- write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, Channel, (Receiver >> 1), index_reg);
-
- /* Save the final Write Data Timing settings for later use */
- pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_WRITEDIR][lane] = current_write_dqs_delay[lane];
-@@ -787,6 +878,831 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
- printk(BIOS_DEBUG, "TrainDQSRdWrPos: Done\n\n");
- }
-
-+/* Calcuate and set MaxRdLatency
-+ * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.5
-+ */
-+static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct)
-+{
-+ uint8_t dimm;
-+ uint8_t lane;
-+ uint32_t dword;
-+ uint32_t dword2;
-+ uint32_t max_delay;
-+ uint8_t mem_clk = 0;
-+ uint8_t nb_pstate;
-+ uint32_t nb_clk;
-+ uint32_t p = 0;
-+ uint32_t n = 0;
-+ uint32_t t = 0;
-+ uint16_t current_phy_phase_delay[MAX_BYTE_LANES];
-+ uint16_t current_read_dqs_delay[MAX_BYTE_LANES];
-+
-+ uint32_t index_reg = 0x98;
-+ uint32_t dev = pDCTstat->dev_dct;
-+ uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
-+
-+ /* P is specified in PhyCLKs (1/2 MEMCLKs) */
-+ for (nb_pstate = 0; nb_pstate < 2; nb_pstate++) {
-+ /* 2.10.5.8.5 (2) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004);
-+ if ((!(dword & (0x1 << 21))) && (!(dword & (0x1 << 13))) && (!(dword & (0x1 << 5))))
-+ p += 1;
-+ else
-+ p += 2;
-+
-+ /* 2.10.5.8.5 (3) */
-+ dword = Get_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210) & 0xf; /* Retrieve RdPtrInit */
-+ p += (9 - dword);
-+
-+ /* 2.10.5.8.5 (4) */
-+ p += 5;
-+
-+ /* 2.10.5.8.5 (5) */
-+ dword = Get_NB32_DCT(dev, dct, 0xa8);
-+ dword2 = Get_NB32_DCT(dev, dct, 0x90);
-+ if ((!(dword & (0x1 << 5))) && (!(dword2 & (0x1 << 16))))
-+ p += 2;
-+
-+ /* 2.10.5.8.5 (6) */
-+ dword = Get_NB32_DCT(dev, dct, 0x200) & 0x1f; /* Retrieve Tcl */
-+ p += (2 * (dword - 1));
-+
-+ /* 2.10.5.8.5 (7) */
-+ max_delay = 0;
-+ for (dimm = 0; dimm < 4; dimm++) {
-+ if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, dimm * 2))
-+ continue;
-+
-+ read_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg);
-+ read_read_dqs_timing_control_registers(current_read_dqs_delay, dev, dct, dimm, index_reg);
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++)
-+ if ((current_phy_phase_delay[lane] + current_read_dqs_delay[lane]) > max_delay)
-+ max_delay = (current_phy_phase_delay[lane] + current_read_dqs_delay[lane]);
-+ }
-+ p += (max_delay >> 5);
-+
-+ /* 2.10.5.8.5 (8) */
-+ p += 5;
-+
-+ /* 2.10.5.8.5 (9) */
-+ t += 800;
-+
-+ /* 2.10.5.8.5 (10) */
-+ mem_clk = Get_NB32_DCT(dev, dct, 0x94) & 0x1f;
-+ dword = Get_NB32(pDCTstat->dev_nbctl, (0x160 + (nb_pstate * 4))); /* Retrieve NbDid, NbFid */
-+ nb_clk = (200 * (((dword >> 1) & 0x1f) + 0x4)) / (((dword >> 7) & 0x1)?2:1);
-+ n = (((((uint64_t)p * 1000000000000ULL)/(((uint64_t)fam15h_freq_tab[mem_clk] * 1000000ULL) * 2)) + ((uint64_t)t)) * ((uint64_t)nb_clk * 1000)) / 1000000000ULL;
-+
-+ /* 2.10.5.8.5 (11) */
-+ n -= 1;
-+
-+ /* 2.10.5.8.5 (12) */
-+ dword = Get_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210);
-+ dword &= ~(0x3ff << 22);
-+ dword |= (((n - 1) & 0x3ff) << 22);
-+ Set_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210, dword);
-+
-+ /* Save result for later use */
-+ pDCTstat->CH_MaxRdLat[dct] = n;
-+ }
-+}
-+
-+static void start_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver)
-+{
-+ uint32_t dword;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ /* 2.10.5.7.1.1
-+ * It appears that the DCT only supports 8-beat burst length mode,
-+ * so do nothing here...
-+ */
-+
-+ /* Wait for CmdSendInProg == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ } while (dword & (0x1 << 12));
-+
-+ /* Set CmdTestEnable = 1 */
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword |= (0x1 << 2);
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ /* 2.10.5.8.6.1.1 Send Activate Command (Target A) */
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */
-+ dword |= ((0x1 << Receiver) << 22);
-+ dword &= ~(0x7 << 19); /* CmdBank = 0 */
-+ dword &= ~(0x3ffff); /* CmdAddress = 0 */
-+ dword |= (0x1 << 31); /* SendActCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x28c, dword);
-+
-+ /* Wait for SendActCmd == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ } while (dword & (0x1 << 31));
-+
-+ /* Wait 75 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 75);
-+
-+ /* 2.10.5.8.6.1.1 Send Activate Command (Target B) */
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */
-+ dword |= ((0x1 << Receiver) << 22);
-+ dword &= ~(0x7 << 19); /* CmdBank = 1 */
-+ dword |= (0x1 << 19);
-+ dword &= ~(0x3ffff); /* CmdAddress = 0 */
-+ dword |= (0x1 << 31); /* SendActCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x28c, dword);
-+
-+ /* Wait for SendActCmd == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ } while (dword & (0x1 << 31));
-+
-+ /* Wait 75 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 75);
-+}
-+
-+static void stop_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver)
-+{
-+ uint32_t dword;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ /* 2.10.5.8.6.1.1 Send Precharge Command */
-+ /* Wait 25 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */
-+ dword |= ((0x1 << Receiver) << 22);
-+ dword &= ~(0x7 << 19); /* CmdBank = 0 */
-+ dword &= ~(0x3ffff); /* CmdAddress = 0x400 */
-+ dword |= 0x400;
-+ dword |= (0x1 << 30); /* SendPchgCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x28c, dword);
-+
-+ /* Wait for SendPchgCmd == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ } while (dword & (0x1 << 30));
-+
-+ /* Wait 25 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25);
-+
-+ /* Set CmdTestEnable = 0 */
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword &= ~(0x1 << 2);
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+}
-+
-+static void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver, uint8_t lane)
-+{
-+ uint32_t dword;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ start_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver);
-+
-+ /* 2.10.5.8.6.1.2 */
-+ /* Configure DQMask */
-+ if (lane < 4) {
-+ Set_NB32_DCT(dev, dct, 0x274, ~(0xff << (lane * 8)));
-+ Set_NB32_DCT(dev, dct, 0x278, ~0x0);
-+ } else if (lane < 8) {
-+ Set_NB32_DCT(dev, dct, 0x274, ~0x0);
-+ Set_NB32_DCT(dev, dct, 0x278, ~(0xff << (lane * 8)));
-+ } else {
-+ Set_NB32_DCT(dev, dct, 0x274, ~0x0);
-+ Set_NB32_DCT(dev, dct, 0x278, ~0x0);
-+ }
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x27c);
-+ dword &= ~(0xff); /* EccMask = 0 */
-+ if ((lane != 8) || (pDCTstat->DimmECCPresent == 0))
-+ dword |= 0xff; /* EccMask = 0xff */
-+ Set_NB32_DCT(dev, dct, 0x27c, dword);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x270);
-+ dword &= ~(0x7ffff); /* DataPrbsSeed = 55555 */
-+// dword |= (0x55555);
-+ dword |= (0x44443); /* Use AGESA seed */
-+ Set_NB32_DCT(dev, dct, 0x270, dword);
-+
-+ /* 2.10.5.8.4 */
-+ dword = Get_NB32_DCT(dev, dct, 0x260);
-+ dword &= ~(0x1fffff); /* CmdCount = 256 */
-+ dword |= 256;
-+ Set_NB32_DCT(dev, dct, 0x260, dword);
-+
-+ /* Configure Target A */
-+ dword = Get_NB32_DCT(dev, dct, 0x254);
-+ dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */
-+ dword |= (Receiver & 0x7) << 24;
-+ dword &= ~(0x7 << 21); /* TgtBank = 0 */
-+ dword &= ~(0x3ff); /* TgtAddress = 0 */
-+ Set_NB32_DCT(dev, dct, 0x254, dword);
-+
-+ /* Configure Target B */
-+ dword = Get_NB32_DCT(dev, dct, 0x258);
-+ dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */
-+ dword |= (Receiver & 0x7) << 24;
-+ dword &= ~(0x7 << 21); /* TgtBank = 1 */
-+ dword |= (0x1 << 21);
-+ dword &= ~(0x3ff); /* TgtAddress = 0 */
-+ Set_NB32_DCT(dev, dct, 0x258, dword);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword |= (0x1 << 3); /* ResetAllErr = 1 */
-+ dword &= ~(0x1 << 4); /* StopOnErr = 0 */
-+ dword &= ~(0x3 << 8); /* CmdTgt = 1 (Alternate between Target A and Target B) */
-+ dword |= (0x1 << 8);
-+ dword &= ~(0x7 << 5); /* CmdType = 0 (Read) */
-+ dword |= (0x1 << 11); /* SendCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ /* 2.10.5.8.6.1.2 Wait for TestStatus == 1 and CmdSendInProg == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ } while ((dword & (0x1 << 12)) || (!(dword & (0x1 << 10))));
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword &= ~(0x1 << 11); /* SendCmd = 0 */
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ stop_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver);
-+}
-+
-+static void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver, uint8_t lane)
-+{
-+ uint32_t dword;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ start_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver);
-+
-+ /* 2.10.5.8.6.1.2 */
-+ /* Configure DQMask */
-+ if (lane < 4) {
-+ Set_NB32_DCT(dev, dct, 0x274, ~(0xff << (lane * 8)));
-+ Set_NB32_DCT(dev, dct, 0x278, ~0x0);
-+ } else if (lane < 8) {
-+ Set_NB32_DCT(dev, dct, 0x274, ~0x0);
-+ Set_NB32_DCT(dev, dct, 0x278, ~(0xff << (lane * 8)));
-+ } else {
-+ Set_NB32_DCT(dev, dct, 0x274, ~0x0);
-+ Set_NB32_DCT(dev, dct, 0x278, ~0x0);
-+ }
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x27c);
-+ dword &= ~(0xff); /* EccMask = 0 */
-+ if ((lane != 8) || (pDCTstat->DimmECCPresent == 0))
-+ dword |= 0xff; /* EccMask = 0xff */
-+ Set_NB32_DCT(dev, dct, 0x27c, dword);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x270);
-+ dword &= ~(0x7ffff); /* DataPrbsSeed = 55555 */
-+// dword |= (0x55555);
-+ dword |= (0x44443); /* Use AGESA seed */
-+ Set_NB32_DCT(dev, dct, 0x270, dword);
-+
-+ /* 2.10.5.8.4 */
-+ dword = Get_NB32_DCT(dev, dct, 0x260);
-+ dword &= ~(0x1fffff); /* CmdCount = 256 */
-+ dword |= 256;
-+ Set_NB32_DCT(dev, dct, 0x260, dword);
-+
-+ /* Configure Target A */
-+ dword = Get_NB32_DCT(dev, dct, 0x254);
-+ dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */
-+ dword |= (Receiver & 0x7) << 24;
-+ dword &= ~(0x7 << 21); /* TgtBank = 0 */
-+ dword &= ~(0x3ff); /* TgtAddress = 0 */
-+ Set_NB32_DCT(dev, dct, 0x254, dword);
-+
-+ /* Configure Target B */
-+ dword = Get_NB32_DCT(dev, dct, 0x258);
-+ dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */
-+ dword |= (Receiver & 0x7) << 24;
-+ dword &= ~(0x7 << 21); /* TgtBank = 1 */
-+ dword |= (0x1 << 21);
-+ dword &= ~(0x3ff); /* TgtAddress = 0 */
-+ Set_NB32_DCT(dev, dct, 0x258, dword);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword |= (0x1 << 3); /* ResetAllErr = 1 */
-+ dword &= ~(0x1 << 4); /* StopOnErr = 0 */
-+ dword &= ~(0x3 << 8); /* CmdTgt = 1 (Alternate between Target A and Target B) */
-+ dword |= (0x1 << 8);
-+ dword &= ~(0x7 << 5); /* CmdType = 1 (Write) */
-+ dword |= (0x1 << 5);
-+ dword |= (0x1 << 11); /* SendCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ /* 2.10.5.8.6.1.2 Wait for TestStatus == 1 and CmdSendInProg == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ } while ((dword & (0x1 << 12)) || (!(dword & (0x1 << 10))));
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword &= ~(0x1 << 11); /* SendCmd = 0 */
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ stop_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver);
-+}
-+
-+/* DQS Position Training
-+ * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.4
-+ */
-+static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t receiver_start, uint8_t receiver_end, uint8_t lane_start, uint8_t lane_end)
-+{
-+ uint8_t dimm;
-+ uint8_t lane;
-+ uint32_t dword;
-+ uint32_t Errors;
-+ uint8_t Receiver;
-+ uint8_t dual_rank;
-+ uint8_t write_iter;
-+ uint8_t read_iter;
-+ uint16_t initial_write_dqs_delay[MAX_BYTE_LANES];
-+ uint16_t initial_read_dqs_delay[MAX_BYTE_LANES];
-+ uint16_t initial_write_data_timing[MAX_BYTE_LANES];
-+ uint16_t current_write_data_delay[MAX_BYTE_LANES];
-+ uint16_t current_read_dqs_delay[MAX_BYTE_LANES];
-+ uint16_t current_write_dqs_delay[MAX_BYTE_LANES];
-+ uint8_t passing_dqs_delay_found[MAX_BYTE_LANES];
-+ uint8_t dqs_results_array[2][(lane_end - lane_start)][32][32]; /* [rank][lane][write step][read step] */
-+
-+ uint8_t last_pos = 0;
-+ uint8_t cur_count = 0;
-+ uint8_t best_pos = 0;
-+ uint8_t best_count = 0;
-+
-+ uint32_t index_reg = 0x98;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ /* Calculate and program MaxRdLatency */
-+ Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct);
-+
-+ Errors = 0;
-+ dual_rank = 0;
-+ Receiver = mct_InitReceiver_D(pDCTstat, dct);
-+ if (receiver_start > Receiver)
-+ Receiver = receiver_start;
-+
-+ /* There are four receiver pairs, loosely associated with chipselects.
-+ * This is essentially looping over each DIMM.
-+ */
-+ for (; Receiver < receiver_end; Receiver += 2) {
-+ dimm = (Receiver >> 1);
-+ if ((Receiver & 0x1) == 0) {
-+ /* Even rank of DIMM */
-+ if(mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver+1))
-+ dual_rank = 1;
-+ else
-+ dual_rank = 0;
-+ }
-+
-+ if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) {
-+ continue;
-+ }
-+
-+ /* Initialize variables */
-+ for (lane = lane_start; lane < lane_end; lane++) {
-+ passing_dqs_delay_found[lane] = 0;
-+ }
-+ memset(dqs_results_array, 0, sizeof(dqs_results_array));
-+
-+ /* Read initial read / write DQS delays */
-+ read_dqs_write_timing_control_registers(initial_write_dqs_delay, dev, dct, dimm, index_reg);
-+ read_dqs_read_data_timing_registers(initial_read_dqs_delay, dev, dct, dimm, index_reg);
-+
-+ /* Read current settings of other (previously trained) lanes */
-+ read_dqs_write_data_timing_registers(initial_write_data_timing, dev, dct, dimm, index_reg);
-+ memcpy(current_write_data_delay, initial_write_data_timing, sizeof(current_write_data_delay));
-+
-+ for (lane = lane_start; lane < lane_end; lane++) {
-+ /* 2.10.5.8.4 (2)
-+ * For each Write Data Delay value from Write DQS Delay to Write DQS Delay + 1 UI
-+ */
-+ for (current_write_data_delay[lane] = initial_write_dqs_delay[lane]; current_write_data_delay[lane] < (initial_write_dqs_delay[lane] + 0x20); current_write_data_delay[lane]++) {
-+ print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 16 current_write_data_delay[lane] ", current_write_data_delay[lane], 6);
-+
-+ /* 2.10.5.8.4 (2 A)
-+ * Commit the current Write Data Timing settings to the hardware registers
-+ */
-+ write_dqs_write_data_timing_registers(current_write_data_delay, dev, dct, dimm, index_reg);
-+
-+ /* 2.10.5.8.4 (2 B)
-+ * Write the DRAM training pattern to the test address
-+ */
-+ write_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver, lane);
-+
-+ /* Read current settings of other (previously trained) lanes */
-+ read_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg);
-+
-+ /* 2.10.5.8.4 (2 C)
-+ * For each Read DQS Delay value from 0 to 1 UI
-+ */
-+ for (current_read_dqs_delay[lane] = 0; current_read_dqs_delay[lane] < 0x40; current_read_dqs_delay[lane] += 2) {
-+ print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 current_read_dqs_delay[lane] ", current_read_dqs_delay[lane], 6);
-+
-+ /* 2.10.5.8.4 (2 A i)
-+ * Commit the current Read DQS Timing Control settings to the hardware registers
-+ */
-+ write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg);
-+
-+ /* 2.10.5.8.4 (2 A ii)
-+ * Read the DRAM training pattern from the test address
-+ */
-+ read_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver, lane);
-+
-+ /* 2.10.5.8.4 (2 A iii)
-+ * Record pass / fail status
-+ */
-+ dword = Get_NB32_DCT(dev, dct, 0x268) & 0x3ffff;
-+ if (dword & (0x3 << (lane * 2)))
-+ dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] >> 1] = 0; /* Fail */
-+ else
-+ dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] >> 1] = 1; /* Pass */
-+ }
-+ }
-+
-+ if (dual_rank && (Receiver & 0x1)) {
-+ /* Overlay the previous rank test results with the current rank */
-+ for (write_iter = 0; write_iter < 32; write_iter++) {
-+ for (read_iter = 0; read_iter < 32; read_iter++) {
-+ if ((dqs_results_array[0][lane - lane_start][write_iter][read_iter])
-+ && (dqs_results_array[1][lane - lane_start][write_iter][read_iter]))
-+ dqs_results_array[1][lane - lane_start][write_iter][read_iter] = 1;
-+ else
-+ dqs_results_array[1][lane - lane_start][write_iter][read_iter] = 0;
-+ }
-+ }
-+ }
-+
-+ /* Determine location and length of longest consecutive string of read passing values
-+ * Output is stored in best_pos and best_count
-+ */
-+ last_pos = 0;
-+ cur_count = 0;
-+ best_pos = 0;
-+ best_count = 0;
-+ for (write_iter = 0; write_iter < 32; write_iter++) {
-+ for (read_iter = 0; read_iter < 32; read_iter++) {
-+ if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (read_iter < 31)) {
-+ /* Pass */
-+ cur_count++;
-+ } else {
-+ /* Failure or end of loop */
-+ if (cur_count > best_count) {
-+ best_count = cur_count;
-+ best_pos = last_pos;
-+ }
-+ cur_count = 0;
-+ last_pos = read_iter;
-+ }
-+ }
-+ last_pos = 0;
-+ }
-+
-+ if (best_count > 2) {
-+ /* Restore current settings of other (previously trained) lanes to the active array */
-+ memcpy(current_read_dqs_delay, initial_read_dqs_delay, sizeof(current_read_dqs_delay));
-+
-+ /* Program the Read DQS Timing Control register with the center of the passing window */
-+ current_read_dqs_delay[lane] = ((best_pos << 1) + ((best_count << 1) / 2));
-+ passing_dqs_delay_found[lane] = 1;
-+
-+ /* Commit the current Read DQS Timing Control settings to the hardware registers */
-+ write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg);
-+
-+ /* Save the final Read DQS Timing Control settings for later use */
-+ pDCTstat->CH_D_DIR_B_DQS[dct][Receiver >> 1][DQS_READDIR][lane] = current_read_dqs_delay[lane];
-+
-+ print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest read passing region ", best_count, 4);
-+ print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest read passing region start ", best_pos, 4);
-+ } else {
-+ /* Reprogram the Read DQS Timing Control register with the original settings */
-+ write_dqs_read_data_timing_registers(initial_read_dqs_delay, dev, dct, dimm, index_reg);
-+ }
-+
-+ /* Determine location and length of longest consecutive string of write passing values
-+ * Output is stored in best_pos and best_count
-+ */
-+ last_pos = 0;
-+ cur_count = 0;
-+ best_pos = 0;
-+ best_count = 0;
-+ for (read_iter = 0; read_iter < 32; read_iter++) {
-+ for (write_iter = 0; write_iter < 32; write_iter++) {
-+ if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (write_iter < 31)) {
-+ /* Pass */
-+ cur_count++;
-+ } else {
-+ /* Failure or end of loop */
-+ if (cur_count > best_count) {
-+ best_count = cur_count;
-+ best_pos = last_pos;
-+ }
-+ cur_count = 0;
-+ last_pos = write_iter;
-+ }
-+ }
-+ last_pos = 0;
-+ }
-+
-+ if (best_count > 2) {
-+ /* Restore current settings of other (previously trained) lanes to the active array */
-+ memcpy(current_write_dqs_delay, initial_write_data_timing, sizeof(current_write_data_delay));
-+
-+ /* Program the Write DQS Timing Control register with the optimal region within the passing window */
-+ if (pDCTstat->Status & (1 << SB_LoadReduced))
-+ current_write_dqs_delay[lane] = ((best_pos + initial_write_dqs_delay[lane]) + (best_count / 3));
-+ else
-+ current_write_dqs_delay[lane] = ((best_pos + initial_write_dqs_delay[lane]) + (best_count / 2));
-+ passing_dqs_delay_found[lane] = 1;
-+
-+ /* Commit the current Write DQS Timing Control settings to the hardware registers */
-+ write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, dct, dimm, index_reg);
-+
-+ /* Save the final Write Data Timing settings for later use */
-+ pDCTstat->CH_D_DIR_B_DQS[dct][Receiver >> 1][DQS_WRITEDIR][lane] = current_write_dqs_delay[lane];
-+
-+ print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest write passing region ", best_count, 4);
-+ print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region start ", best_pos, 4);
-+ } else {
-+ /* Reprogram the Write DQS Timing Control register with the original settings */
-+ write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, dct, dimm, index_reg);
-+ }
-+ }
-+
-+#ifdef PRINT_PASS_FAIL_BITMAPS
-+ for (lane = lane_start; lane < lane_end; lane++) {
-+ for (read_iter = 0; read_iter < 32; read_iter++) {
-+ for (write_iter = 0; write_iter < 32; write_iter++) {
-+ if (dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter])
-+ printk(BIOS_DEBUG, "+");
-+ else
-+ printk(BIOS_DEBUG, ".");
-+ }
-+ printk(BIOS_DEBUG, "\n");
-+ }
-+ printk(BIOS_DEBUG, "\n\n");
-+ }
-+#endif
-+
-+ /* Flag failure(s) if present */
-+ for (lane = lane_start; lane < lane_end; lane++) {
-+ if (!passing_dqs_delay_found[lane]) {
-+ print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 121 Unable to find passing region for lane ", lane, 2);
-+
-+ /* Flag absence of passing window */
-+ Errors |= 1 << SB_NODQSPOS;
-+ }
-+ }
-+
-+ pDCTstat->TrainErrors |= Errors;
-+ pDCTstat->ErrStatus |= Errors;
-+
-+#if DQS_TRAIN_DEBUG > 0
-+ {
-+ u8 val;
-+ u8 i;
-+ u8 ChannelDTD, ReceiverDTD, Dir;
-+ u8 *p;
-+
-+ for (Dir = 0; Dir < 2; Dir++) {
-+ if (Dir == 1) {
-+ printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS WR:\n");
-+ } else {
-+ printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS RD:\n");
-+ }
-+ for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
-+ printk(BIOS_DEBUG, "Channel: %02x\n", ChannelDTD);
-+ for (ReceiverDTD = 0; ReceiverDTD < MAX_CS_SUPPORTED; ReceiverDTD += 2) {
-+ printk(BIOS_DEBUG, "\t\tReceiver: %02x:", ReceiverDTD);
-+ p = pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir];
-+ for (i=0;i<8; i++) {
-+ val = p[i];
-+ printk(BIOS_DEBUG, " %02x", val);
-+ }
-+ printk(BIOS_DEBUG, "\n");
-+ }
-+ }
-+ }
-+
-+ }
-+#endif
-+ }
-+
-+ /* Return 1 on success, 0 on failure */
-+ return !Errors;
-+}
-+
-+/* DQS Receiver Enable Cycle Training
-+ * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.3
-+ */
-+static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat)
-+{
-+ u32 Errors;
-+ u8 Receiver;
-+ u8 _DisableDramECC = 0;
-+ u8 _Wrap32Dis = 0, _SSE2 = 0;
-+
-+ u32 addr;
-+ u32 cr4;
-+ u32 lo, hi;
-+
-+ uint8_t dct;
-+ uint8_t prev;
-+ uint8_t dimm;
-+ uint8_t lane;
-+ uint32_t dword;
-+ uint32_t rx_en_offset;
-+ uint16_t initial_phy_phase_delay[MAX_BYTE_LANES];
-+ uint16_t current_phy_phase_delay[MAX_BYTE_LANES];
-+ uint8_t dqs_results_array[1024];
-+
-+ uint16_t ren_step = 0x40;
-+ uint32_t index_reg = 0x98;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ print_debug_dqs("\nTrainDQSReceiverEnCyc: Node_ID ", pDCTstat->Node_ID, 0);
-+ cr4 = read_cr4();
-+ if (cr4 & (1<<9)) {
-+ _SSE2 = 1;
-+ }
-+ cr4 |= (1<<9); /* OSFXSR enable SSE2 */
-+ write_cr4(cr4);
-+
-+ addr = HWCR;
-+ _RDMSR(addr, &lo, &hi);
-+ if (lo & (1<<17)) {
-+ _Wrap32Dis = 1;
-+ }
-+ lo |= (1<<17); /* HWCR.wrap32dis */
-+ _WRMSR(addr, lo, hi); /* allow 64-bit memory references in real mode */
-+
-+ /* Disable ECC correction of reads on the dram bus. */
-+ _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat);
-+
-+ Errors = 0;
-+
-+ for (dct = 0; dct < 2; dct++) {
-+ /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisAutoComp, DisablePredriverCal] */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003);
-+ dword &= ~(0x3 << 13);
-+ dword |= (0x1 << 13);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003, dword);
-+ }
-+
-+ for (dct = 0; dct < 2; dct++) {
-+ /* 2.10.5.6 */
-+ fam15EnableTrainingMode(pMCTstat, pDCTstat, dct, 1);
-+
-+ /* 2.10.5.8.3 */
-+ Receiver = mct_InitReceiver_D(pDCTstat, dct);
-+
-+ /* There are four receiver pairs, loosely associated with chipselects.
-+ * This is essentially looping over each DIMM.
-+ */
-+ for (; Receiver < 8; Receiver += 2) {
-+ dimm = (Receiver >> 1);
-+
-+ if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) {
-+ continue;
-+ }
-+
-+ /* 2.10.5.8.3 (2) */
-+ read_dqs_receiver_enable_control_registers(initial_phy_phase_delay, dev, dct, dimm, index_reg);
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ /* Initialize variables */
-+ memset(dqs_results_array, 0, sizeof(dqs_results_array));
-+
-+ /* 2.10.5.8.3 (1) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8));
-+ dword |= (0x1 << 8); /* BlockRxDqsLock = 1 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword);
-+
-+ /* 2.10.5.8.3 (3) */
-+ rx_en_offset = (initial_phy_phase_delay[lane] + 0x10) % 0x40;
-+
-+ /* 2.10.5.8.3 (4) */
-+ for (current_phy_phase_delay[lane] = rx_en_offset; current_phy_phase_delay[lane] < 0x3ff; current_phy_phase_delay[lane] += ren_step) {
-+ /* 2.10.5.8.3 (4 A) */
-+ write_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg);
-+
-+ /* Calculate and program MaxRdLatency */
-+ Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct);
-+
-+ /* 2.10.5.8.3 (4 B) */
-+ dqs_results_array[current_phy_phase_delay[lane]] = TrainDQSRdWrPos_D_Fam15(pMCTstat, pDCTstat, dct, Receiver, Receiver + 2, lane, lane + 1);
-+ }
-+
-+#ifdef PRINT_PASS_FAIL_BITMAPS
-+ uint16_t iter;
-+ for (iter = 0; iter < 0x3ff; iter++) {
-+ if (dqs_results_array[iter])
-+ printk(BIOS_DEBUG, "+");
-+ else
-+ printk(BIOS_DEBUG, ".");
-+ }
-+ printk(BIOS_DEBUG, "\n");
-+#endif
-+
-+ /* 2.10.5.8.3 (5) */
-+ prev = 0;
-+ for (current_phy_phase_delay[lane] = rx_en_offset; current_phy_phase_delay[lane] < 0x3ff; current_phy_phase_delay[lane] += ren_step) {
-+ if ((dqs_results_array[current_phy_phase_delay[lane]] == 0) && (prev == 1)) {
-+ /* Restore last known good delay */
-+ current_phy_phase_delay[lane] -= ren_step;
-+
-+ /* 2.10.5.8.3 (5 A B) */
-+ current_phy_phase_delay[lane] -= 0x10;
-+
-+ /* Update hardware registers with final values */
-+ write_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg);
-+ break;
-+ }
-+ prev = dqs_results_array[current_phy_phase_delay[lane]];
-+ }
-+
-+ /* 2.10.5.8.3 (6) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8));
-+ dword &= ~(0x1 << 8); /* BlockRxDqsLock = 0 */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword);
-+ }
-+
-+#if DQS_TRAIN_DEBUG > 0
-+ printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 DQS receiver enable timing: ");
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ printk(BIOS_DEBUG, " %03x", current_phy_phase_delay[lane]);
-+ }
-+ printk(BIOS_DEBUG, "\n");
-+#endif
-+ }
-+ }
-+
-+ pDCTstat->TrainErrors |= Errors;
-+ pDCTstat->ErrStatus |= Errors;
-+
-+#if DQS_TRAIN_DEBUG > 0
-+ {
-+ u8 val;
-+ u8 i;
-+ u8 ChannelDTD, ReceiverDTD, Dir;
-+ u8 *p;
-+
-+ for (Dir = 0; Dir < 2; Dir++) {
-+ if (Dir == 1) {
-+ printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS WR:\n");
-+ } else {
-+ printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS RD:\n");
-+ }
-+ for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
-+ printk(BIOS_DEBUG, "Channel: %02x\n", ChannelDTD);
-+ for (ReceiverDTD = 0; ReceiverDTD < MAX_CS_SUPPORTED; ReceiverDTD += 2) {
-+ printk(BIOS_DEBUG, "\t\tReceiver: %02x:", ReceiverDTD);
-+ p = pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir];
-+ for (i=0;i<8; i++) {
-+ val = p[i];
-+ printk(BIOS_DEBUG, " %02x", val);
-+ }
-+ printk(BIOS_DEBUG, "\n");
-+ }
-+ }
-+ }
-+
-+ }
-+#endif
-+ if (_DisableDramECC) {
-+ mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
-+ }
-+ if (!_Wrap32Dis) {
-+ addr = HWCR;
-+ _RDMSR(addr, &lo, &hi);
-+ lo &= ~(1<<17); /* restore HWCR.wrap32dis */
-+ _WRMSR(addr, lo, hi);
-+ }
-+ if (!_SSE2){
-+ cr4 = read_cr4();
-+ cr4 &= ~(1<<9); /* restore cr4.OSFXSR */
-+ write_cr4(cr4);
-+ }
-+
-+ printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: Status %x\n", pDCTstat->Status);
-+ printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: TrainErrors %x\n", pDCTstat->TrainErrors);
-+ printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: ErrStatus %x\n", pDCTstat->ErrStatus);
-+ printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: ErrCode %x\n", pDCTstat->ErrCode);
-+ printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: Done\n\n");
-+}
-+
- static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u32 *buffer)
- {
-@@ -869,18 +1785,17 @@ static u8 ChipSelPresent_D(struct MCTStatStruc *pMCTstat,
- u32 val;
- u32 reg;
- u32 dev = pDCTstat->dev_dct;
-- u32 reg_off;
-+ uint8_t dct = 0;
- u8 ret = 0;
-
-- if (!pDCTstat->GangedMode) {
-- reg_off = 0x100 * Channel;
-- } else {
-- reg_off = 0;
-- }
-+ if (!pDCTstat->GangedMode)
-+ dct = Channel;
-+ else
-+ dct = 0;
-
- if (ChipSel < MAX_CS_SUPPORTED){
-- reg = 0x40 + (ChipSel << 2) + reg_off;
-- val = Get_NB32(dev, reg);
-+ reg = 0x40 + (ChipSel << 2);
-+ val = Get_NB32_DCT(dev, dct, reg);
- if (val & ( 1 << 0))
- ret = 1;
- }
-@@ -1085,12 +2000,12 @@ u32 SetUpperFSbase(u32 addr_hi)
- return addr_hi << 8;
- }
-
--void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index)
-+void ResetDCTWrPtr_D(u32 dev, uint8_t dct, u32 index_reg, u32 index)
- {
- u32 val;
-
-- val = Get_NB32_index_wait(dev, index_reg, index);
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
- }
-
- void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
-@@ -1103,9 +2018,13 @@ void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
- for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
- pDCTstat = pDCTstatA + Node;
- if (pDCTstat->DCTSysLimit) {
-- TrainDQSRdWrPos_D(pMCTstat, pDCTstat);
-- for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) {
-- SetEccDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel);
-+ if (is_fam15h()) {
-+ TrainDQSReceiverEnCyc_D_Fam15(pMCTstat, pDCTstat);
-+ } else {
-+ TrainDQSRdWrPos_D_Fam10(pMCTstat, pDCTstat);
-+ for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) {
-+ SetEccDQSRdWrPos_D_Fam10(pMCTstat, pDCTstat, ChipSel);
-+ }
- }
- }
- }
-@@ -1126,19 +2045,18 @@ u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat,
-
- dev = pDCTstat->dev_dct;
- reg = 0x90;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 0, reg);
- if (val & (1<<DimmEcEn)) {
- _DisableDramECC |= 0x01;
- val &= ~(1<<DimmEcEn);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, 0, reg, val);
- }
- if (!pDCTstat->GangedMode) {
-- reg = 0x190;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 1, reg);
- if (val & (1<<DimmEcEn)) {
- _DisableDramECC |= 0x02;
- val &= ~(1<<DimmEcEn);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, 1, reg, val);
- }
- }
- return _DisableDramECC;
-@@ -1157,15 +2075,14 @@ void mct_EnableDimmEccEn_D(struct MCTStatStruc *pMCTstat,
-
- if ((_DisableDramECC & 0x01) == 0x01) {
- reg = 0x90;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 0, reg);
- val |= (1<<DimmEcEn);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, 0, reg, val);
- }
- if ((_DisableDramECC & 0x02) == 0x02) {
-- reg = 0x190;
-- val = Get_NB32(dev, reg);
-+ val = Get_NB32_DCT(dev, 1, reg);
- val |= (1<<DimmEcEn);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, 1, reg, val);
- }
- }
-
-@@ -1177,7 +2094,7 @@ static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat,
- {
- u8 ByteLane;
- u32 val;
-- u32 index_reg = 0x98 + 0x100 * pDCTstat->Channel;
-+ u32 index_reg = 0x98;
- u8 shift;
- u32 dqs_delay = (u32)pDCTstat->DQSDelay;
- u32 dev = pDCTstat->dev_dct;
-@@ -1205,7 +2122,7 @@ static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat,
-
- index += (ChipSel>>1) << 8;
-
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, pDCTstat->Channel, index_reg, index);
- if (ByteLane < 8) {
- if (pDCTstat->Direction == DQS_WRITEDIR) {
- dqs_delay += pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][ChipSel>>1][ByteLane];
-@@ -1215,7 +2132,7 @@ static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat,
- }
- val &= ~(0x7f << shift);
- val |= (dqs_delay << shift);
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ Set_NB32_index_wait_DCT(dev, pDCTstat->Channel, index_reg, index, val);
- }
- }
-
-@@ -1241,7 +2158,7 @@ u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
- u8 Channel, u8 receiver, u8 *valid)
- {
- u32 val;
-- u32 reg_off = 0;
-+ uint8_t dct = 0;
- u32 reg;
- u32 dword;
- u32 dev = pDCTstat->dev_dct;
-@@ -1250,12 +2167,12 @@ u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
-
-
- if (!pDCTstat->GangedMode) {
-- reg_off = 0x100 * Channel;
-+ dct = Channel;
- }
-
- /* get the local base addr of the chipselect */
-- reg = 0x40 + (receiver << 2) + reg_off;
-- val = Get_NB32(dev, reg);
-+ reg = 0x40 + (receiver << 2);
-+ val = Get_NB32_DCT(dev, dct, reg);
-
- val &= ~0xe007c01f;
-
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
-index 0c52791..11f1b2c 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -91,19 +92,21 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
-
- /* Construct these booleans, based on setup options, for easy handling
- later in this procedure */
-- OB_NBECC = mctGet_NVbits(NV_NBECC); /* MCA ECC (MCE) enable bit */
-+ OB_NBECC = mctGet_NVbits(NV_NBECC); /* MCA ECC (MCE) enable bit */
-
-- OB_ECCRedir = mctGet_NVbits(NV_ECCRedir); /* ECC Redirection */
-+ OB_ECCRedir = mctGet_NVbits(NV_ECCRedir); /* ECC Redirection */
-
-- OB_ChipKill = mctGet_NVbits(NV_ChipKill); /* ECC Chip-kill mode */
-+ OB_ChipKill = mctGet_NVbits(NV_ChipKill); /* ECC Chip-kill mode */
-+ OF_ScrubCTL = 0; /* Scrub CTL for Dcache, L2, and dram */
-
-- OF_ScrubCTL = 0; /* Scrub CTL for Dcache, L2, and dram */
-- nvbits = mctGet_NVbits(NV_DCBKScrub);
-- /* mct_AdjustScrub_D(pDCTstatA, &nvbits); */ /* Need not adjust */
-- OF_ScrubCTL |= (u32) nvbits << 16;
-+ if (!is_fam15h()) {
-+ nvbits = mctGet_NVbits(NV_DCBKScrub);
-+ /* mct_AdjustScrub_D(pDCTstatA, &nvbits); */ /* Need not adjust */
-+ OF_ScrubCTL |= (u32) nvbits << 16;
-
-- nvbits = mctGet_NVbits(NV_L2BKScrub);
-- OF_ScrubCTL |= (u32) nvbits << 8;
-+ nvbits = mctGet_NVbits(NV_L2BKScrub);
-+ OF_ScrubCTL |= (u32) nvbits << 8;
-+ }
-
- nvbits = mctGet_NVbits(NV_DramBKScrub);
- OF_ScrubCTL |= nvbits;
-@@ -131,7 +134,7 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
- pDCTstat->ErrStatus |= (1 << SB_DramECCDis);
- }
- AllECC = 0;
-- LDramECC =0;
-+ LDramECC = 0;
- }
- } else {
- AllECC = 0;
-@@ -140,7 +143,7 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
- if (OB_NBECC) {
- mct_EnableDatIntlv_D(pMCTstat, pDCTstat);
- dev = pDCTstat->dev_nbmisc;
-- reg =0x44; /* MCA NB Configuration */
-+ reg = 0x44; /* MCA NB Configuration */
- val = Get_NB32(dev, reg);
- val |= 1 << 22; /* EccEn */
- Set_NB32(dev, reg, val);
-@@ -177,6 +180,10 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
- /*WE/RE is checked because memory config may have been */
- if((val & 3)==3) { /* Node has dram populated */
- if (isDramECCEn_D(pDCTstat)) { /* if ECC is enabled on this dram */
-+ if (is_fam15h()) {
-+ /* Erratum 505 */
-+ fam15h_switch_dct(pDCTstat->dev_map, 0);
-+ }
- dev = pDCTstat->dev_nbmisc;
- val = curBase << 8;
- if(OB_ECCRedir) {
-@@ -187,16 +194,18 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
- Set_NB32(dev, 0x60, val); /* Dram Scrub Addr High */
- Set_NB32(dev, 0x58, OF_ScrubCTL); /*Scrub Control */
-
-- /* Divisor should not be set deeper than
-- * divide by 16 when Dcache scrubber or
-- * L2 scrubber is enabled.
-- */
-- if ((OF_ScrubCTL & (0x1F << 16)) || (OF_ScrubCTL & (0x1F << 8))) {
-- val = Get_NB32(dev, 0x84);
-- if ((val & 0xE0000000) > 0x80000000) { /* Get F3x84h[31:29]ClkDivisor for C1 */
-- val &= 0x1FFFFFFF; /* If ClkDivisor is deeper than divide-by-16 */
-- val |= 0x80000000; /* set it to divide-by-16 */
-- Set_NB32(dev, 0x84, val);
-+ if (!is_fam15h()) {
-+ /* Divisor should not be set deeper than
-+ * divide by 16 when Dcache scrubber or
-+ * L2 scrubber is enabled.
-+ */
-+ if ((OF_ScrubCTL & (0x1F << 16)) || (OF_ScrubCTL & (0x1F << 8))) {
-+ val = Get_NB32(dev, 0x84);
-+ if ((val & 0xE0000000) > 0x80000000) { /* Get F3x84h[31:29]ClkDivisor for C1 */
-+ val &= 0x1FFFFFFF; /* If ClkDivisor is deeper than divide-by-16 */
-+ val |= 0x80000000; /* set it to divide-by-16 */
-+ Set_NB32(dev, 0x84, val);
-+ }
- }
- }
- } /* this node has ECC enabled dram */
-@@ -267,8 +276,8 @@ static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat)
- }
- for(i=0; i<ch_end; i++) {
- if(pDCTstat->DIMMValidDCT[i] > 0){
-- reg = 0x90 + i * 0x100; /* Dram Config Low */
-- val = Get_NB32(dev, reg);
-+ reg = 0x90; /* Dram Config Low */
-+ val = Get_NB32_DCT(dev, i, reg);
- if(val & (1<<DimmEcEn)) {
- /* set local flag 'dram ecc capable' */
- isDimmECCEn = 1;
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c
-index 0112732..a6b9dcb 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -25,8 +26,8 @@ void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat,
- u32 dev = pDCTstat->dev_dct;
-
- /*flag for selecting HW/SW DRAM Init HW DRAM Init */
-- reg = 0x90 + 0x100 * dct; /*DRAM Configuration Low */
-- val = Get_NB32(dev, reg);
-+ reg = 0x90; /*DRAM Configuration Low */
-+ val = Get_NB32_DCT(dev, dct, reg);
- val |= (1<<InitDram);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, dct, reg, val);
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
-index 60bc01d..5e81808 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
-@@ -18,10 +18,12 @@
- * Foundation, Inc.
- */
-
--static void SetTargetFreq(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstat);
--static void AgesaHwWlPhase1(sMCTStruct *pMCTData,
-- sDCTStruct *pDCTData, u8 dimm, u8 pass);
-+static void AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass);
-+static void AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass);
-+static void AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass);
- static void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
- static void DisableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
- static void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
-@@ -56,7 +58,7 @@ static void SetEccWrDQS_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pD
- Addl_Index = 0x32;
- Addl_Index += DimmNum * 3;
-
-- val = Get_NB32_index_wait(pDCTstat->dev_dct, Channel * 0x100 + 0x98, Addl_Index);
-+ val = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, Channel, 0x98, Addl_Index);
- if (OddByte)
- val >>= 16;
- /* Save WrDqs to stack for later usage */
-@@ -74,13 +76,13 @@ static void EnableAutoRefresh_D(struct MCTStatStruc *pMCTstat, struct DCTStatStr
- {
- u32 val;
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x8C);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C);
- val &= ~(1 << DisAutoRefresh);
-- Set_NB32(pDCTstat->dev_dct, 0x8C, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C, val);
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x8C + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C);
- val &= ~(1 << DisAutoRefresh);
-- Set_NB32(pDCTstat->dev_dct, 0x8C + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C, val);
- }
-
- static void DisableAutoRefresh_D(struct MCTStatStruc *pMCTstat,
-@@ -88,13 +90,13 @@ static void DisableAutoRefresh_D(struct MCTStatStruc *pMCTstat,
- {
- u32 val;
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x8C);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C);
- val |= 1 << DisAutoRefresh;
-- Set_NB32(pDCTstat->dev_dct, 0x8C, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C, val);
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x8C + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C);
- val |= 1 << DisAutoRefresh;
-- Set_NB32(pDCTstat->dev_dct, 0x8C + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C, val);
- }
-
-
-@@ -118,8 +120,11 @@ static void PhyWLPass1(struct MCTStatStruc *pMCTstat,
- DIMMValid = pDCTstat->DIMMValid;
- PrepareC_DCT(pMCTstat, pDCTstat, dct);
- for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
-- if (DIMMValid & (1 << (dimm << 1)))
-- AgesaHwWlPhase1(pDCTstat->C_MCTPtr, DCTPtr, dimm, FirstPass);
-+ if (DIMMValid & (1 << (dimm << 1))) {
-+ AgesaHwWlPhase1(pMCTstat, pDCTstat, dct, dimm, FirstPass);
-+ AgesaHwWlPhase2(pMCTstat, pDCTstat, dct, dimm, FirstPass);
-+ AgesaHwWlPhase3(pMCTstat, pDCTstat, dct, dimm, FirstPass);
-+ }
- }
- }
- }
-@@ -146,27 +151,40 @@ static void PhyWLPass2(struct MCTStatStruc *pMCTstat,
- pDCTstat->Speed = pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
- pDCTstat->CASL = pDCTstat->DIMMCASL = pDCTstat->TargetCASL;
- SPD2ndTiming(pMCTstat, pDCTstat, dct);
-- ProgDramMRSReg_D(pMCTstat, pDCTstat, dct);
-- PlatformSpec_D(pMCTstat, pDCTstat, dct);
-- fenceDynTraining_D(pMCTstat, pDCTstat, dct);
-+ if (!is_fam15h()) {
-+ ProgDramMRSReg_D(pMCTstat, pDCTstat, dct);
-+ PlatformSpec_D(pMCTstat, pDCTstat, dct);
-+ fenceDynTraining_D(pMCTstat, pDCTstat, dct);
-+ }
- Restore_OnDimmMirror(pMCTstat, pDCTstat);
- StartupDCT_D(pMCTstat, pDCTstat, dct);
- Clear_OnDimmMirror(pMCTstat, pDCTstat);
- SetDllSpeedUp_D(pMCTstat, pDCTstat, dct);
- DisableAutoRefresh_D(pMCTstat, pDCTstat);
- for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
-- if (DIMMValid & (1 << (dimm << 1)))
-- AgesaHwWlPhase1(pDCTstat->C_MCTPtr, pDCTstat->C_DCTPtr[dct], dimm, SecondPass);
-+ if (DIMMValid & (1 << (dimm << 1))) {
-+ AgesaHwWlPhase1(pMCTstat, pDCTstat, dct, dimm, SecondPass);
-+ AgesaHwWlPhase2(pMCTstat, pDCTstat, dct, dimm, SecondPass);
-+ AgesaHwWlPhase3(pMCTstat, pDCTstat, dct, dimm, SecondPass);
-+ }
- }
- }
- }
-
-+static uint16_t fam15h_next_highest_memclk_freq(uint16_t memclk_freq)
-+{
-+ uint16_t fam15h_next_highest_freq_tab[] = {0, 0, 0, 0, 0x6, 0, 0xa, 0, 0, 0, 0xe, 0, 0, 0, 0x12, 0, 0, 0, 0x16, 0, 0, 0, 0x16};
-+ return fam15h_next_highest_freq_tab[memclk_freq];
-+}
-+
- /* Write Levelization Training
- * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.1
- */
- static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstat)
-+ struct DCTStatStruc *pDCTstat, uint8_t Pass)
- {
-+ uint16_t final_target_freq;
-+
- pDCTstat->C_MCTPtr = &(pDCTstat->s_C_MCTPtr);
- pDCTstat->C_DCTPtr[0] = &(pDCTstat->s_C_DCTPtr[0]);
- pDCTstat->C_DCTPtr[1] = &(pDCTstat->s_C_DCTPtr[1]);
-@@ -182,16 +200,39 @@ static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
- pDCTstat->DIMMValidDCT[1] = pDCTstat->DIMMValidDCT[0];
- }
-
-- PhyWLPass1(pMCTstat, pDCTstat, 0);
-- PhyWLPass1(pMCTstat, pDCTstat, 1);
-+ if (Pass == FirstPass) {
-+ PhyWLPass1(pMCTstat, pDCTstat, 0);
-+ PhyWLPass1(pMCTstat, pDCTstat, 1);
-+ }
-+
-+ if (Pass == SecondPass) {
-+ if (pDCTstat->TargetFreq > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
-+ /* 8.Prepare the memory subsystem for the target MEMCLK frequency.
-+ * NOTE: BIOS must program both DCTs to the same frequency.
-+ * NOTE: Fam15h steps the frequency, Fam10h slams the frequency.
-+ */
-+ final_target_freq = pDCTstat->TargetFreq;
-+
-+ while (pDCTstat->Speed != final_target_freq) {
-+ if (is_fam15h())
-+ pDCTstat->TargetFreq = fam15h_next_highest_memclk_freq(pDCTstat->Speed);
-+ else
-+ pDCTstat->TargetFreq = final_target_freq;
-+ SetTargetFreq(pMCTstat, pDCTstat);
-+ PhyWLPass2(pMCTstat, pDCTstat, 0);
-+ PhyWLPass2(pMCTstat, pDCTstat, 1);
-+ }
-+
-+ pDCTstat->TargetFreq = final_target_freq;
-
-- if (pDCTstat->TargetFreq > 4) {
-- /* 8.Prepare the memory subsystem for the target MEMCLK frequency.
-- * Note: BIOS must program both DCTs to the same frequency.
-- */
-- SetTargetFreq(pMCTstat, pDCTstat);
-- PhyWLPass2(pMCTstat, pDCTstat, 0);
-- PhyWLPass2(pMCTstat, pDCTstat, 1);
-+ uint8_t dct;
-+ for (dct = 0; dct < 2; dct++) {
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+ memcpy(pDCTData->WLGrossDelayFinalPass, pDCTData->WLGrossDelayPrevPass, sizeof(pDCTData->WLGrossDelayPrevPass));
-+ memcpy(pDCTData->WLFineDelayFinalPass, pDCTData->WLFineDelayPrevPass, sizeof(pDCTData->WLFineDelayPrevPass));
-+ pDCTData->WLCriticalGrossDelayFinalPass = pDCTData->WLCriticalGrossDelayPrevPass;
-+ }
-+ }
- }
-
- SetEccWrDQS_D(pMCTstat, pDCTstat);
-@@ -200,7 +241,7 @@ static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
- }
-
- void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstatA)
-+ struct DCTStatStruc *pDCTstatA, uint8_t Pass)
- {
- u8 Node;
-
-@@ -211,7 +252,7 @@ void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
- if (pDCTstat->NodePresent) {
- mctSMBhub_Init(Node);
- Clear_OnDimmMirror(pMCTstat, pDCTstat);
-- WriteLevelization_HW(pMCTstat, pDCTstat);
-+ WriteLevelization_HW(pMCTstat, pDCTstat, Pass);
- Restore_OnDimmMirror(pMCTstat, pDCTstat);
- }
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
-index cda9c6b..5ef4a2c 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
-@@ -34,7 +34,7 @@ u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2)
-
- if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
- misc2 |= 1 << OdtSwizzle;
-- val = Get_NB32(pDCTstat->dev_dct, dct * 0x100 + 0x78);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x78);
-
- val &= 7;
- val = ((~val) & 0xff) + 1;
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
-index bd8b7fb..5ea7fa6 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -23,7 +24,6 @@ static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
- u8 Dimms, DimmNum, MaxDimm, Speed;
- u32 val;
- u32 dct = 0;
-- u32 reg_off = 0;
-
- DimmNum = (MrsChipSel >> 20) & 0xFE;
-
-@@ -41,7 +41,6 @@ static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
- dct = 1;
- DimmNum ++;
- }
-- reg_off = 0x100 * dct;
- Dimms = pDCTstat->MAdimms[dct];
-
- val = 0;
-@@ -95,21 +94,21 @@ static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
- static void mct_SendCtrlWrd(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u32 val)
- {
-- u32 reg_off = 0;
-+ uint8_t dct = 0;
- u32 dev = pDCTstat->dev_dct;
-
- if (pDCTstat->CSPresent_DCT[0] > 0) {
-- reg_off = 0;
-+ dct = 0;
- } else if (pDCTstat->CSPresent_DCT[1] > 0 ){
-- reg_off = 0x100;
-+ dct = 1;
- }
-
-- val |= Get_NB32(dev, reg_off + 0x7C) & ~0xFFFFFF;
-+ val |= Get_NB32_DCT(dev, dct, 0x7C) & ~0xFFFFFF;
- val |= 1 << SendControlWord;
-- Set_NB32(dev, reg_off + 0x7C, val);
-+ Set_NB32_DCT(dev, dct, 0x7C, val);
-
- do {
-- val = Get_NB32(dev, reg_off + 0x7C);
-+ val = Get_NB32_DCT(dev, dct, 0x7C);
- } while (val & (1 << SendControlWord));
- }
-
-@@ -119,7 +118,6 @@ void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
- u8 MrsChipSel;
- u32 dev = pDCTstat->dev_dct;
- u32 val, cw;
-- u32 reg_off = 0x100 * dct;
-
- mct_Wait(1600);
-
-@@ -127,7 +125,7 @@ void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
-
- for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel ++, MrsChipSel ++) {
- if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
-- val = Get_NB32(dev, reg_off + 0xA8);
-+ val = Get_NB32_DCT(dev, dct, 0xa8);
- val &= ~(0xF << 8);
-
- switch (MrsChipSel) {
-@@ -144,7 +142,7 @@ void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
- case 7:
- val |= (3 << 6) << 8;
- }
-- Set_NB32(dev, reg_off + 0xA8 , val);
-+ Set_NB32_DCT(dev, dct, 0xa8, val);
-
- for (cw=0; cw <=15; cw ++) {
- mct_Wait(1600);
-@@ -171,10 +169,10 @@ void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
- for (MrsChipSel=0; MrsChipSel < 8; MrsChipSel++, MrsChipSel++) {
- if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
- /* 2. Program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects. */
-- val = Get_NB32(dev, 0xA8); /* TODO: dct * 0x100 + 0xA8 */
-+ val = Get_NB32_DCT(dev, 0, 0xA8); /* TODO: dct 0 / 1 select */
- val &= ~(0xFF << 8);
- val |= (0x3 << (MrsChipSel & 0xFE)) << 8;
-- Set_NB32(dev, 0xA8, val); /* TODO: dct * 0x100 + 0xA8 */
-+ Set_NB32_DCT(dev, 0, 0xA8, val); /* TODO: dct 0 / 1 select */
-
- /* Resend control word 10 */
- mct_Wait(1600);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
-index b21b96a..51cbf16 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
-@@ -18,17 +18,182 @@
- * Foundation, Inc.
- */
-
-+static uint8_t fam15_dimm_dic(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type)
-+{
-+ uint8_t dic;
-+
-+ /* Calculate DIC based on recommendations in MR1_dct[1:0] */
-+ if (pDCTstat->Status & (1 << SB_LoadReduced)) {
-+ /* TODO
-+ * LRDIMM unimplemented
-+ */
-+ dic = 0x0;
-+ } else {
-+ dic = 0x1;
-+ }
-+
-+ return dic;
-+}
-+
-+static uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type)
-+{
-+ uint8_t term = 0;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+ uint8_t number_of_dimms = pDCTData->MaxDimmsInstalled;
-+ uint8_t frequency_index;
-+ uint8_t rank_count = pDCTData->DimmRanks[dimm];
-+
-+ if (is_fam15h())
-+ frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+ else
-+ frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7;
-+
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ if (is_fam15h()) {
-+ if (pDCTstat->Status & (1 << SB_Registered)) {
-+ /* TODO
-+ * RDIMM unimplemented
-+ */
-+ } else {
-+ if (package_type == PT_GR) {
-+ /* Socket G34: Fam15h BKDG v3.14 Table 56 */
-+ if (MaxDimmsInstallable == 1) {
-+ term = 0x0;
-+ } else if (MaxDimmsInstallable == 2) {
-+ if ((number_of_dimms == 2) && (frequency_index == 0x12)) {
-+ term = 0x1;
-+ } else if (number_of_dimms == 1) {
-+ term = 0x0;
-+ } else {
-+ term = 0x2;
-+ }
-+ } else if (MaxDimmsInstallable == 3) {
-+ if (number_of_dimms == 1) {
-+ if (frequency_index <= 0xa) {
-+ term = 0x2;
-+ } else {
-+ if (rank_count < 3) {
-+ term = 0x1;
-+ } else {
-+ term = 0x2;
-+ }
-+ }
-+ } else if (number_of_dimms == 2) {
-+ term = 0x2;
-+ }
-+ }
-+ } else {
-+ /* TODO
-+ * Other sockets unimplemented
-+ */
-+ }
-+ }
-+ }
-+
-+ return term;
-+}
-+
-+static uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type)
-+{
-+ uint8_t term = 0;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+ uint8_t number_of_dimms = pDCTData->MaxDimmsInstalled;
-+ uint8_t frequency_index;
-+
-+ if (is_fam15h())
-+ frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
-+ else
-+ frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7;
-+
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ if (is_fam15h()) {
-+ if (pDCTstat->Status & (1 << SB_LoadReduced)) {
-+ /* TODO
-+ * LRDIMM unimplemented
-+ */
-+ } else if (pDCTstat->Status & (1 << SB_Registered)) {
-+ /* TODO
-+ * RDIMM unimplemented
-+ */
-+ } else {
-+ if (package_type == PT_GR) {
-+ /* Socket G34: Fam15h BKDG v3.14 Table 56 */
-+ if (MaxDimmsInstallable == 1) {
-+ if ((frequency_index == 0x4) || (frequency_index == 0x6))
-+ term = 0x2;
-+ else if ((frequency_index == 0xa) || (frequency_index == 0xe))
-+ term = 0x1;
-+ else
-+ term = 0x3;
-+ }
-+ if (MaxDimmsInstallable == 2) {
-+ if (number_of_dimms == 1) {
-+ if (frequency_index <= 0x6) {
-+ term = 0x2;
-+ } else if (frequency_index <= 0xe) {
-+ term = 0x1;
-+ } else {
-+ term = 0x3;
-+ }
-+ } else {
-+ if (frequency_index <= 0xa) {
-+ term = 0x3;
-+ } else if (frequency_index <= 0xe) {
-+ term = 0x5;
-+ } else {
-+ term = 0x4;
-+ }
-+ }
-+ } else if (MaxDimmsInstallable == 3) {
-+ if (number_of_dimms == 1) {
-+ term = 0x0;
-+ } else if (number_of_dimms == 2) {
-+ if (frequency_index <= 0xa) {
-+ if (rank == 1) {
-+ term = 0x0;
-+ } else {
-+ term = 0x3;
-+ }
-+ } else if (frequency_index <= 0xe) {
-+ if (rank == 1) {
-+ term = 0x0;
-+ } else {
-+ term = 0x5;
-+ }
-+ }
-+ }
-+ }
-+ } else {
-+ /* TODO
-+ * Other sockets unimplemented
-+ */
-+ }
-+ }
-+ }
-+
-+ return term;
-+}
-+
- static void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
-
- static void mct_DCTAccessDone(struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 val;
-
- do {
-- val = Get_NB32(dev, reg_off + 0x98);
-+ val = Get_NB32_DCT(dev, dct, 0x98);
- } while (!(val & (1 << DctAccessDone)));
- }
-
-@@ -54,9 +219,15 @@ static u32 swapAddrBits(struct DCTStatStruc *pDCTstat, u32 MR_register_setting,
- if (MR_register_setting & (1 << 6)) ret |= 1 << 5;
- if (MR_register_setting & (1 << 7)) ret |= 1 << 8;
- if (MR_register_setting & (1 << 8)) ret |= 1 << 7;
-- if (MR_register_setting & (1 << 16)) ret |= 1 << 17;
-- if (MR_register_setting & (1 << 17)) ret |= 1 << 16;
-- MR_register_setting &= ~0x301f8;
-+ if (is_fam15h()) {
-+ if (MR_register_setting & (1 << 18)) ret |= 1 << 19;
-+ if (MR_register_setting & (1 << 19)) ret |= 1 << 18;
-+ MR_register_setting &= ~0x000c01f8;
-+ } else {
-+ if (MR_register_setting & (1 << 16)) ret |= 1 << 17;
-+ if (MR_register_setting & (1 << 17)) ret |= 1 << 16;
-+ MR_register_setting &= ~0x000301f8;
-+ }
- MR_register_setting |= ret;
- }
- }
-@@ -65,47 +236,76 @@ static u32 swapAddrBits(struct DCTStatStruc *pDCTstat, u32 MR_register_setting,
-
- static void mct_SendMrsCmd(struct DCTStatStruc *pDCTstat, u8 dct, u32 EMRS)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 val;
-
-- val = Get_NB32(dev, reg_off + 0x7C);
-- val &= ~0xFFFFFF;
-+ val = Get_NB32_DCT(dev, dct, 0x7c);
-+ val &= ~0x00ffffff;
- val |= EMRS;
- val |= 1 << SendMrsCmd;
-- Set_NB32(dev, reg_off + 0x7C, val);
-+ Set_NB32_DCT(dev, dct, 0x7c, val);
-
- do {
-- val = Get_NB32(dev, reg_off + 0x7C);
-+ val = Get_NB32_DCT(dev, dct, 0x7c);
- } while (val & (1 << SendMrsCmd));
- }
-
- static u32 mct_MR2(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 dword, ret;
-
-- ret = 0x20000;
-- ret |= MrsChipSel;
-+ if (is_fam15h()) {
-+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+
-+ /* The formula for chip select number is: CS = dimm*2+rank */
-+ uint8_t dimm = MrsChipSel / 2;
-+ uint8_t rank = MrsChipSel % 2;
-
-- /* program MrsAddress[5:3]=CAS write latency (CWL):
-- * based on F2x[1,0]84[Tcwl] */
-- dword = Get_NB32(dev, reg_off + 0x84);
-- dword = mct_AdjustSPDTimings(pMCTstat, pDCTstat, dword);
-+ /* FIXME: These parameters should be configurable
-+ * For now, err on the side of caution and enable automatic 2x refresh
-+ * when the DDR temperature rises above the internal limits
-+ */
-+ uint8_t force_2x_self_refresh = 0; /* ASR */
-+ uint8_t auto_2x_self_refresh = 1; /* SRT */
-
-- ret |= ((dword >> 20) & 7) << 3;
-+ ret = 0x80000;
-+ ret |= (MrsChipSel << 21);
-
-- /* program MrsAddress[6]=auto self refresh method (ASR):
-- based on F2x[1,0]84[ASR]
-- program MrsAddress[7]=self refresh temperature range (SRT):
-- based on F2x[1,0]84[ASR and SRT] */
-- ret |= ((dword >> 18) & 3) << 6;
-+ /* Set self refresh parameters */
-+ ret |= (force_2x_self_refresh << 6);
-+ ret |= (auto_2x_self_refresh << 7);
-
-- /* program MrsAddress[10:9]=dynamic termination during writes (RTT_WR)
-- based on F2x[1,0]84[DramTermDyn] */
-- ret |= ((dword >> 10) & 3) << 9;
-+ /* Obtain Tcwl, adjust, and set CWL with the adjusted value */
-+ dword = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f;
-+ ret |= ((dword - 5) << 3);
-+
-+ /* Obtain and set RttWr */
-+ ret |= (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9);
-+ } else {
-+ ret = 0x20000;
-+ ret |= (MrsChipSel << 20);
-+
-+ /* program MrsAddress[5:3]=CAS write latency (CWL):
-+ * based on F2x[1,0]84[Tcwl] */
-+ dword = Get_NB32_DCT(dev, dct, 0x84);
-+ dword = mct_AdjustSPDTimings(pMCTstat, pDCTstat, dword);
-+
-+ ret |= ((dword >> 20) & 7) << 3;
-+
-+ /* program MrsAddress[6]=auto self refresh method (ASR):
-+ * based on F2x[1,0]84[ASR]
-+ * program MrsAddress[7]=self refresh temperature range (SRT):
-+ * based on F2x[1,0]84[ASR and SRT]
-+ */
-+ ret |= ((dword >> 18) & 3) << 6;
-+
-+ /* program MrsAddress[10:9]=dynamic termination during writes (RTT_WR)
-+ * based on F2x[1,0]84[DramTermDyn]
-+ */
-+ ret |= ((dword >> 10) & 3) << 9;
-+ }
-
- return ret;
- }
-@@ -113,20 +313,28 @@ static u32 mct_MR2(struct MCTStatStruc *pMCTstat,
- static u32 mct_MR3(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 dword, ret;
-
-- ret = 0x30000;
-- ret |= MrsChipSel;
-+ if (is_fam15h()) {
-+ ret = 0xc0000;
-+ ret |= (MrsChipSel << 21);
-
-- /* program MrsAddress[1:0]=multi purpose register address location
-- (MPR Location):based on F2x[1,0]84[MprLoc]
-- program MrsAddress[2]=multi purpose register
-- (MPR):based on F2x[1,0]84[MprEn]
-- */
-- dword = Get_NB32(dev, reg_off + 0x84);
-- ret |= (dword >> 24) & 7;
-+ /* Program MPR and MPRLoc to 0 */
-+ // ret |= 0x0; /* MPR */
-+ // ret |= (0x0 << 2); /* MPRLoc */
-+ } else {
-+ ret = 0x30000;
-+ ret |= (MrsChipSel << 20);
-+
-+ /* program MrsAddress[1:0]=multi purpose register address location
-+ * (MPR Location):based on F2x[1,0]84[MprLoc]
-+ * program MrsAddress[2]=multi purpose register
-+ * (MPR):based on F2x[1,0]84[MprEn]
-+ */
-+ dword = Get_NB32_DCT(dev, dct, 0x84);
-+ ret |= (dword >> 24) & 7;
-+ }
-
- return ret;
- }
-@@ -134,48 +342,93 @@ static u32 mct_MR3(struct MCTStatStruc *pMCTstat,
- static u32 mct_MR1(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 dword, ret;
-
-- ret = 0x10000;
-- ret |= MrsChipSel;
--
-- /* program MrsAddress[5,1]=output driver impedance control (DIC):
-- * based on F2x[1,0]84[DrvImpCtrl] */
-- dword = Get_NB32(dev, reg_off + 0x84);
-- if (dword & (1 << 3))
-- ret |= 1 << 5;
-- if (dword & (1 << 2))
-- ret |= 1 << 1;
--
-- /* program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT):
-- based on F2x[1,0]84[DramTerm] */
-- if (!(pDCTstat->Status & (1 << SB_Registered))) {
-- if (dword & (1 << 9))
-- ret |= 1 << 9;
-- if (dword & (1 << 8))
-- ret |= 1 << 6;
-- if (dword & (1 << 7))
-- ret |= 1 << 2;
-+ if (is_fam15h()) {
-+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+
-+ /* Set defaults */
-+ uint8_t qoff = 0; /* Enable output buffers */
-+ uint8_t wrlvl = 0; /* Disable write levelling */
-+ uint8_t tqds = 0;
-+ uint8_t rttnom = 0;
-+ uint8_t dic = 0;
-+ uint8_t additive_latency = 0;
-+ uint8_t dll_enable = 0;
-+
-+ ret = 0x40000;
-+ ret |= (MrsChipSel << 21);
-+
-+ /* The formula for chip select number is: CS = dimm*2+rank */
-+ uint8_t dimm = MrsChipSel / 2;
-+ uint8_t rank = MrsChipSel % 2;
-+
-+ /* Determine if TQDS should be set */
-+ if ((pDCTstat->Dimmx8Present & (1 << dimm))
-+ && (((dimm & 0x1)?(pDCTstat->Dimmx4Present&0x55):(pDCTstat->Dimmx4Present&0xaa)) != 0x0)
-+ && (pDCTstat->Status & (1 << SB_LoadReduced)))
-+ tqds = 1;
-+
-+ /* Obtain RttNom */
-+ rttnom = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type);
-+
-+ /* Obtain DIC */
-+ dic = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type);
-+
-+ /* Load data into MRS word */
-+ ret |= (qoff & 0x1) << 12;
-+ ret |= (tqds & 0x1) << 11;
-+ ret |= ((rttnom & 0x4) >> 2) << 9;
-+ ret |= ((rttnom & 0x2) >> 1) << 6;
-+ ret |= ((rttnom & 0x1) >> 0) << 2;
-+ ret |= (wrlvl & 0x1) << 7;
-+ ret |= ((dic & 0x2) >> 1) << 5;
-+ ret |= ((dic & 0x1) >> 0) << 1;
-+ ret |= (additive_latency & 0x3) << 3;
-+ ret |= (dll_enable & 0x1);
- } else {
-- ret |= mct_MR1Odt_RDimm(pMCTstat, pDCTstat, dct, MrsChipSel);
-- }
-+ ret = 0x10000;
-+ ret |= (MrsChipSel << 20);
-+
-+ /* program MrsAddress[5,1]=output driver impedance control (DIC):
-+ * based on F2x[1,0]84[DrvImpCtrl]
-+ */
-+ dword = Get_NB32_DCT(dev, dct, 0x84);
-+ if (dword & (1 << 3))
-+ ret |= 1 << 5;
-+ if (dword & (1 << 2))
-+ ret |= 1 << 1;
-+
-+ /* program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT):
-+ * based on F2x[1,0]84[DramTerm]
-+ */
-+ if (!(pDCTstat->Status & (1 << SB_Registered))) {
-+ if (dword & (1 << 9))
-+ ret |= 1 << 9;
-+ if (dword & (1 << 8))
-+ ret |= 1 << 6;
-+ if (dword & (1 << 7))
-+ ret |= 1 << 2;
-+ } else {
-+ ret |= mct_MR1Odt_RDimm(pMCTstat, pDCTstat, dct, MrsChipSel);
-+ }
-
-- /* program MrsAddress[11]=TDQS: based on F2x[1,0]94[RDqsEn] */
-- if (Get_NB32(dev, reg_off + 0x94) & (1 << RDqsEn)) {
-- u8 bit;
-- /* Set TDQS=1b for x8 DIMM, TDQS=0b for x4 DIMM, when mixed x8 & x4 */
-- bit = (ret >> 21) << 1;
-- if ((dct & 1) != 0)
-- bit ++;
-- if (pDCTstat->Dimmx8Present & (1 << bit))
-- ret |= 1 << 11;
-- }
-+ /* program MrsAddress[11]=TDQS: based on F2x[1,0]94[RDqsEn] */
-+ if (Get_NB32_DCT(dev, dct, 0x94) & (1 << RDqsEn)) {
-+ u8 bit;
-+ /* Set TDQS=1b for x8 DIMM, TDQS=0b for x4 DIMM, when mixed x8 & x4 */
-+ bit = (ret >> 21) << 1;
-+ if ((dct & 1) != 0)
-+ bit ++;
-+ if (pDCTstat->Dimmx8Present & (1 << bit))
-+ ret |= 1 << 11;
-+ }
-
-- /* program MrsAddress[12]=QOFF: based on F2x[1,0]84[Qoff] */
-- if (dword & (1 << 13))
-- ret |= 1 << 12;
-+ /* program MrsAddress[12]=QOFF: based on F2x[1,0]84[Qoff] */
-+ if (dword & (1 << 13))
-+ ret |= 1 << 12;
-+ }
-
- return ret;
- }
-@@ -183,60 +436,139 @@ static u32 mct_MR1(struct MCTStatStruc *pMCTstat,
- static u32 mct_MR0(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 dword, ret, dword2;
-
-- ret = 0x00000;
-- ret |= MrsChipSel;
--
-- /* program MrsAddress[1:0]=burst length and control method
-- (BL):based on F2x[1,0]84[BurstCtrl] */
-- dword = Get_NB32(dev, reg_off + 0x84);
-- ret |= dword & 3;
--
-- /* program MrsAddress[3]=1 (BT):interleaved */
-- ret |= 1 << 3;
--
-- /* program MrsAddress[6:4,2]=read CAS latency
-- (CL):based on F2x[1,0]88[Tcl] */
-- dword2 = Get_NB32(dev, reg_off + 0x88);
-- ret |= (dword2 & 0x7) << 4; /* F2x88[2:0] to MrsAddress[6:4] */
-- ret |= ((dword2 & 0x8) >> 3) << 2; /* F2x88[3] to MrsAddress[2] */
--
-- /* program MrsAddress[12]=0 (PPD):slow exit */
-- if (dword & (1 << 23))
-- ret |= 1 << 12;
--
-- /* program MrsAddress[11:9]=write recovery for auto-precharge
-- (WR):based on F2x[1,0]84[Twr] */
-- ret |= ((dword >> 4) & 7) << 9;
--
-- /* program MrsAddress[8]=1 (DLL):DLL reset
-- just issue DLL reset at first time */
-- ret |= 1 << 8;
-+ if (is_fam15h()) {
-+ ret = 0x00000;
-+ ret |= (MrsChipSel << 21);
-+
-+ /* Set defaults */
-+ uint8_t ppd = 0;
-+ uint8_t wr_ap = 0;
-+ uint8_t dll_reset = 1;
-+ uint8_t test_mode = 0;
-+ uint8_t cas_latency = 0;
-+ uint8_t read_burst_type = 1;
-+ uint8_t burst_length = 0;
-+
-+ /* Obtain PchgPDModeSel */
-+ dword = Get_NB32_DCT(dev, dct, 0x84);
-+ ppd = (dword >> 23) & 0x1;
-+
-+ /* Obtain Twr */
-+ dword = Get_NB32_DCT(dev, dct, 0x22c) & 0x1f;
-+
-+ /* Calculate wr_ap (Fam15h BKDG v3.14 Table 82) */
-+ if (dword == 0x10)
-+ wr_ap = 0x0;
-+ else if (dword == 0x5)
-+ wr_ap = 0x1;
-+ else if (dword == 0x6)
-+ wr_ap = 0x2;
-+ else if (dword == 0x7)
-+ wr_ap = 0x3;
-+ else if (dword == 0x8)
-+ wr_ap = 0x4;
-+ else if (dword == 0xa)
-+ wr_ap = 0x5;
-+ else if (dword == 0xc)
-+ wr_ap = 0x6;
-+ else if (dword == 0xe)
-+ wr_ap = 0x7;
-+
-+ /* Obtain Tcl */
-+ dword = Get_NB32_DCT(dev, dct, 0x200) & 0x1f;
-+
-+ /* Calculate cas_latency (Fam15h BKDG v3.14 Table 83) */
-+ if (dword == 0x5)
-+ cas_latency = 0x2;
-+ else if (dword == 0x6)
-+ cas_latency = 0x4;
-+ else if (dword == 0x7)
-+ cas_latency = 0x6;
-+ else if (dword == 0x8)
-+ cas_latency = 0x8;
-+ else if (dword == 0x9)
-+ cas_latency = 0xa;
-+ else if (dword == 0xa)
-+ cas_latency = 0xc;
-+ else if (dword == 0xb)
-+ cas_latency = 0xe;
-+ else if (dword == 0xc)
-+ cas_latency = 0x1;
-+ else if (dword == 0xd)
-+ cas_latency = 0x3;
-+ else if (dword == 0xe)
-+ cas_latency = 0x5;
-+ else if (dword == 0xf)
-+ cas_latency = 0x7;
-+ else if (dword == 0x10)
-+ cas_latency = 0x9;
-+
-+ /* Obtain BurstCtrl */
-+ burst_length = Get_NB32_DCT(dev, dct, 0x84) & 0x3;
-+
-+ /* Load data into MRS word */
-+ ret |= (ppd & 0x1) << 12;
-+ ret |= (wr_ap & 0x3) << 9;
-+ ret |= (dll_reset & 0x1) << 8;
-+ ret |= (test_mode & 0x1) << 7;
-+ ret |= ((cas_latency & 0xe) >> 1) << 4;
-+ ret |= ((cas_latency & 0x1) >> 0) << 2;
-+ ret |= (read_burst_type & 0x1) << 3;
-+ ret |= (burst_length & 0x3);
-+ } else {
-+ ret = 0x00000;
-+ ret |= (MrsChipSel << 20);
-+
-+ /* program MrsAddress[1:0]=burst length and control method
-+ (BL):based on F2x[1,0]84[BurstCtrl] */
-+ dword = Get_NB32_DCT(dev, dct, 0x84);
-+ ret |= dword & 3;
-+
-+ /* program MrsAddress[3]=1 (BT):interleaved */
-+ ret |= 1 << 3;
-+
-+ /* program MrsAddress[6:4,2]=read CAS latency
-+ (CL):based on F2x[1,0]88[Tcl] */
-+ dword2 = Get_NB32_DCT(dev, dct, 0x88);
-+ ret |= (dword2 & 0x7) << 4; /* F2x88[2:0] to MrsAddress[6:4] */
-+ ret |= ((dword2 & 0x8) >> 3) << 2; /* F2x88[3] to MrsAddress[2] */
-+
-+ /* program MrsAddress[12]=0 (PPD):slow exit */
-+ if (dword & (1 << 23))
-+ ret |= 1 << 12;
-+
-+ /* program MrsAddress[11:9]=write recovery for auto-precharge
-+ (WR):based on F2x[1,0]84[Twr] */
-+ ret |= ((dword >> 4) & 7) << 9;
-+
-+ /* program MrsAddress[8]=1 (DLL):DLL reset
-+ just issue DLL reset at first time */
-+ ret |= 1 << 8;
-+ }
-
- return ret;
- }
-
- static void mct_SendZQCmd(struct DCTStatStruc *pDCTstat, u8 dct)
- {
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
- u32 dword;
-
- /*1.Program MrsAddress[10]=1
- 2.Set SendZQCmd=1
- */
-- dword = Get_NB32(dev, reg_off + 0x7C);
-+ dword = Get_NB32_DCT(dev, dct, 0x7C);
- dword &= ~0xFFFFFF;
- dword |= 1 << 10;
- dword |= 1 << SendZQCmd;
-- Set_NB32(dev, reg_off + 0x7C, dword);
-+ Set_NB32_DCT(dev, dct, 0x7C, dword);
-
- /* Wait for SendZQCmd=0 */
- do {
-- dword = Get_NB32(dev, reg_off + 0x7C);
-+ dword = Get_NB32_DCT(dev, dct, 0x7C);
- } while (dword & (1 << SendZQCmd));
-
- /* 4.Wait 512 MEMCLKs */
-@@ -248,31 +580,30 @@ void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat,
- {
- u8 MrsChipSel;
- u32 dword;
-- u32 reg_off = 0x100 * dct;
- u32 dev = pDCTstat->dev_dct;
-
-- if (pDCTstat->DIMMAutoSpeed == 4) {
-+ if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
- /* 3.Program F2x[1,0]7C[EnDramInit]=1 */
-- dword = Get_NB32(dev, reg_off + 0x7C);
-+ dword = Get_NB32_DCT(dev, dct, 0x7c);
- dword |= 1 << EnDramInit;
-- Set_NB32(dev, reg_off + 0x7C, dword);
-+ Set_NB32_DCT(dev, dct, 0x7c, dword);
- mct_DCTAccessDone(pDCTstat, dct);
-
- /* 4.wait 200us */
- mct_Wait(40000);
-
-- /* 5.On revision C processors, program F2x[1, 0]7C[DeassertMemRstX] = 1. */
-- dword = Get_NB32(dev, reg_off + 0x7C);
-+ /* 5.Program F2x[1, 0]7C[DeassertMemRstX] = 1. */
-+ dword = Get_NB32_DCT(dev, dct, 0x7c);
- dword |= 1 << DeassertMemRstX;
-- Set_NB32(dev, reg_off + 0x7C, dword);
-+ Set_NB32_DCT(dev, dct, 0x7c, dword);
-
- /* 6.wait 500us */
- mct_Wait(200000);
-
- /* 7.Program F2x[1,0]7C[AssertCke]=1 */
-- dword = Get_NB32(dev, reg_off + 0x7C);
-+ dword = Get_NB32_DCT(dev, dct, 0x7c);
- dword |= 1 << AssertCke;
-- Set_NB32(dev, reg_off + 0x7C, dword);
-+ Set_NB32_DCT(dev, dct, 0x7c, dword);
-
- /* 8.wait 360ns */
- mct_Wait(80);
-@@ -281,6 +612,13 @@ void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat,
- * must be done for each chip select pair */
- if (pDCTstat->Status & (1 << SB_Registered))
- mct_DramControlReg_Init_D(pMCTstat, pDCTstat, dct);
-+
-+ /* The following steps are performed with load reduced DIMMs only and
-+ * must be done for each DIMM */
-+ // if (pDCTstat->Status & (1 << SB_LoadReduced))
-+ /* TODO
-+ * Implement LRDIMM configuration
-+ */
- }
-
- /* The following steps are performed once for unbuffered DIMMs and once for each
-@@ -289,23 +627,23 @@ void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat,
- if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
- u32 EMRS;
- /* 13.Send EMRS(2) */
-- EMRS = mct_MR2(pMCTstat, pDCTstat, dct, MrsChipSel << 20);
-+ EMRS = mct_MR2(pMCTstat, pDCTstat, dct, MrsChipSel);
- EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct);
- mct_SendMrsCmd(pDCTstat, dct, EMRS);
- /* 14.Send EMRS(3). Ordinarily at this time, MrsAddress[2:0]=000b */
-- EMRS= mct_MR3(pMCTstat, pDCTstat, dct, MrsChipSel << 20);
-+ EMRS= mct_MR3(pMCTstat, pDCTstat, dct, MrsChipSel);
- EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct);
- mct_SendMrsCmd(pDCTstat, dct, EMRS);
- /* 15.Send EMRS(1) */
-- EMRS= mct_MR1(pMCTstat, pDCTstat, dct, MrsChipSel << 20);
-+ EMRS= mct_MR1(pMCTstat, pDCTstat, dct, MrsChipSel);
- EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct);
- mct_SendMrsCmd(pDCTstat, dct, EMRS);
- /* 16.Send MRS with MrsAddress[8]=1(reset the DLL) */
-- EMRS= mct_MR0(pMCTstat, pDCTstat, dct, MrsChipSel << 20);
-+ EMRS= mct_MR0(pMCTstat, pDCTstat, dct, MrsChipSel);
- EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct);
- mct_SendMrsCmd(pDCTstat, dct, EMRS);
-
-- if (pDCTstat->DIMMAutoSpeed == 4)
-+ if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK)))
- if (!(pDCTstat->Status & (1 << SB_Registered)))
- break; /* For UDIMM, only send MR commands once per channel */
- }
-@@ -314,16 +652,15 @@ void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat,
- MrsChipSel ++;
- }
-
-- mct_Wait(100000);
--
-- if (pDCTstat->DIMMAutoSpeed == 4) {
-+ if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
- /* 17.Send two ZQCL commands */
- mct_SendZQCmd(pDCTstat, dct);
- mct_SendZQCmd(pDCTstat, dct);
-+
- /* 18.Program F2x[1,0]7C[EnDramInit]=0 */
-- dword = Get_NB32(dev, reg_off + 0x7C);
-+ dword = Get_NB32_DCT(dev, dct, 0x7C);
- dword &= ~(1 << EnDramInit);
-- Set_NB32(dev, reg_off + 0x7C, dword);
-+ Set_NB32_DCT(dev, dct, 0x7C, dword);
- mct_DCTAccessDone(pDCTstat, dct);
- }
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
-index 91e8f77..011a94f 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
-@@ -23,7 +23,10 @@
- Description: Receiver En and DQS Timing Training feature for DDR 3 MCT
- ******************************************************************************/
-
--static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
-+static int32_t abs(int32_t val);
-+static void dqsTrainRcvrEn_SW_Fam10(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 Pass);
-+static void dqsTrainRcvrEn_SW_Fam15(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 Pass);
- static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
-@@ -32,7 +35,7 @@ static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
- static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 Channel);
- static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 DQSRcvEnDly);
--static void fenceDynTraining_D(struct MCTStatStruc *pMCTstat,
-+static uint32_t fenceDynTraining_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct);
- static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat);
-
-@@ -89,11 +92,154 @@ static void SetupRcvrPattern(struct MCTStatStruc *pMCTstat,
- void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 Pass)
- {
-- if(mct_checkNumberOfDqsRcvEn_1Pass(Pass))
-- dqsTrainRcvrEn_SW(pMCTstat, pDCTstat, Pass);
-+ if(mct_checkNumberOfDqsRcvEn_1Pass(Pass)) {
-+ if (is_fam15h())
-+ dqsTrainRcvrEn_SW_Fam15(pMCTstat, pDCTstat, Pass);
-+ else
-+ dqsTrainRcvrEn_SW_Fam10(pMCTstat, pDCTstat, Pass);
-+ }
- }
-
--static void read_dqs_write_timing_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
-+static uint16_t fam15_receiver_enable_training_seed(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type)
-+{
-+ uint32_t dword;
-+ uint16_t seed = 0;
-+
-+ /* FIXME
-+ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
-+ * For now assume a maximum of 2 DIMMs per channel can be installed
-+ */
-+ uint8_t MaxDimmsInstallable = 2;
-+
-+ uint8_t channel = dct;
-+ if (package_type == PT_GR) {
-+ /* Get the internal node number */
-+ dword = Get_NB32(pDCTstat->dev_nbmisc, 0xe8);
-+ dword = (dword >> 30) & 0x3;
-+ if (dword == 1) {
-+ channel += 2;
-+ }
-+ }
-+
-+ if (pDCTstat->Status & (1 << SB_Registered)) {
-+ if (package_type == PT_GR) {
-+ /* Socket G34: Fam15h BKDG v3.14 Table 99 */
-+ if (MaxDimmsInstallable == 1) {
-+ if (channel == 0)
-+ seed = 0x43;
-+ else if (channel == 1)
-+ seed = 0x3f;
-+ else if (channel == 2)
-+ seed = 0x3a;
-+ else if (channel == 3)
-+ seed = 0x35;
-+ } else if (MaxDimmsInstallable == 2) {
-+ if (channel == 0)
-+ seed = 0x54;
-+ else if (channel == 1)
-+ seed = 0x4d;
-+ else if (channel == 2)
-+ seed = 0x45;
-+ else if (channel == 3)
-+ seed = 0x40;
-+ } else if (MaxDimmsInstallable == 3) {
-+ if (channel == 0)
-+ seed = 0x6b;
-+ else if (channel == 1)
-+ seed = 0x5e;
-+ else if (channel == 2)
-+ seed = 0x4b;
-+ else if (channel == 3)
-+ seed = 0x3d;
-+ }
-+ } else if (package_type == PT_C3) {
-+ /* Socket C32: Fam15h BKDG v3.14 Table 100 */
-+ if ((MaxDimmsInstallable == 1) || (MaxDimmsInstallable == 2)) {
-+ if (channel == 0)
-+ seed = 0x3f;
-+ else if (channel == 1)
-+ seed = 0x3e;
-+ } else if (MaxDimmsInstallable == 3) {
-+ if (channel == 0)
-+ seed = 0x47;
-+ else if (channel == 1)
-+ seed = 0x38;
-+ }
-+ }
-+ } else if (pDCTstat->Status & (1 << SB_LoadReduced)) {
-+ if (package_type == PT_GR) {
-+ /* Socket G34: Fam15h BKDG v3.14 Table 99 */
-+ if (MaxDimmsInstallable == 1) {
-+ if (channel == 0)
-+ seed = 0x123;
-+ else if (channel == 1)
-+ seed = 0x122;
-+ else if (channel == 2)
-+ seed = 0x112;
-+ else if (channel == 3)
-+ seed = 0x102;
-+ }
-+ } else if (package_type == PT_C3) {
-+ /* Socket C32: Fam15h BKDG v3.14 Table 100 */
-+ if (channel == 0)
-+ seed = 0x132;
-+ else if (channel == 1)
-+ seed = 0x122;
-+ }
-+ } else {
-+ if (package_type == PT_GR) {
-+ /* Socket G34: Fam15h BKDG v3.14 Table 99 */
-+ if (MaxDimmsInstallable == 1) {
-+ if (channel == 0)
-+ seed = 0x3e;
-+ else if (channel == 1)
-+ seed = 0x38;
-+ else if (channel == 2)
-+ seed = 0x37;
-+ else if (channel == 3)
-+ seed = 0x31;
-+ } else if (MaxDimmsInstallable == 2) {
-+ if (channel == 0)
-+ seed = 0x51;
-+ else if (channel == 1)
-+ seed = 0x4a;
-+ else if (channel == 2)
-+ seed = 0x46;
-+ else if (channel == 3)
-+ seed = 0x3f;
-+ } else if (MaxDimmsInstallable == 3) {
-+ if (channel == 0)
-+ seed = 0x5e;
-+ else if (channel == 1)
-+ seed = 0x52;
-+ else if (channel == 2)
-+ seed = 0x48;
-+ else if (channel == 3)
-+ seed = 0x3c;
-+ }
-+ } else if (package_type == PT_C3) {
-+ /* Socket C32: Fam15h BKDG v3.14 Table 100 */
-+ if ((MaxDimmsInstallable == 1) || (MaxDimmsInstallable == 2)) {
-+ if (channel == 0)
-+ seed = 0x39;
-+ else if (channel == 1)
-+ seed = 0x32;
-+ } else if (MaxDimmsInstallable == 3) {
-+ if (channel == 0)
-+ seed = 0x45;
-+ else if (channel == 1)
-+ seed = 0x37;
-+ }
-+ } else if (package_type == PT_M2) {
-+ /* Socket AM3: Fam15h BKDG v3.14 Table 101 */
-+ seed = 0x3a;
-+ }
-+ }
-+
-+ return seed;
-+}
-+
-+static void read_dqs_write_timing_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
- {
- uint8_t lane;
- uint32_t dword;
-@@ -111,7 +257,7 @@ static void read_dqs_write_timing_control_registers(uint16_t* current_total_dela
- if (lane == 8)
- wdt_reg = 0x32;
- wdt_reg += dimm * 3;
-- dword = Get_NB32_index_wait(dev, index_reg, wdt_reg);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, wdt_reg);
- if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1))
- current_total_delay[lane] = (dword & 0x00ff0000) >> 16;
- if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0))
-@@ -119,12 +265,124 @@ static void read_dqs_write_timing_control_registers(uint16_t* current_total_dela
- }
- }
-
--static void write_dqs_receiver_enable_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
-+#ifdef UNUSED_CODE
-+static void write_dqs_write_timing_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint8_t lane;
-+ uint32_t dword;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint32_t ret_reg;
-+ if ((lane == 0) || (lane == 1))
-+ ret_reg = 0x30;
-+ if ((lane == 2) || (lane == 3))
-+ ret_reg = 0x31;
-+ if ((lane == 4) || (lane == 5))
-+ ret_reg = 0x40;
-+ if ((lane == 6) || (lane == 7))
-+ ret_reg = 0x41;
-+ if (lane == 8)
-+ ret_reg = 0x32;
-+ ret_reg += dimm * 3;
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg);
-+ if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) {
-+ dword &= ~(0xff << 16);
-+ dword |= (current_total_delay[lane] & 0xff) << 16;
-+ }
-+ if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) {
-+ dword &= ~0xff;
-+ dword |= current_total_delay[lane] & 0xff;
-+ }
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg, dword);
-+ }
-+}
-+#endif
-+
-+static void write_write_data_timing_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint8_t lane;
-+ uint32_t dword;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint32_t wdt_reg;
-+
-+ /* Calculate Write Data Timing register location */
-+ if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3))
-+ wdt_reg = 0x1;
-+ if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7))
-+ wdt_reg = 0x2;
-+ if (lane == 8)
-+ wdt_reg = 0x3;
-+ wdt_reg |= (dimm << 8);
-+
-+ /* Set Write Data Timing register values */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, wdt_reg);
-+ if ((lane == 7) || (lane == 3)) {
-+ dword &= ~(0x7f << 24);
-+ dword |= (current_total_delay[lane] & 0x7f) << 24;
-+ }
-+ if ((lane == 6) || (lane == 2)) {
-+ dword &= ~(0x7f << 16);
-+ dword |= (current_total_delay[lane] & 0x7f) << 16;
-+ }
-+ if ((lane == 5) || (lane == 1)) {
-+ dword &= ~(0x7f << 8);
-+ dword |= (current_total_delay[lane] & 0x7f) << 8;
-+ }
-+ if ((lane == 8) || (lane == 4) || (lane == 0)) {
-+ dword &= ~0x7f;
-+ dword |= current_total_delay[lane] & 0x7f;
-+ }
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, wdt_reg, dword);
-+ }
-+}
-+
-+static void read_dqs_receiver_enable_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint8_t lane;
-+ uint32_t mask;
-+ uint32_t dword;
-+
-+ if (is_fam15h())
-+ mask = 0x3ff;
-+ else
-+ mask = 0x1ff;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint32_t ret_reg;
-+ if ((lane == 0) || (lane == 1))
-+ ret_reg = 0x10;
-+ if ((lane == 2) || (lane == 3))
-+ ret_reg = 0x11;
-+ if ((lane == 4) || (lane == 5))
-+ ret_reg = 0x20;
-+ if ((lane == 6) || (lane == 7))
-+ ret_reg = 0x21;
-+ if (lane == 8)
-+ ret_reg = 0x12;
-+ ret_reg += dimm * 3;
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg);
-+ if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) {
-+ current_total_delay[lane] = (dword & (mask << 16)) >> 16;
-+ }
-+ if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) {
-+ current_total_delay[lane] = dword & mask;
-+ }
-+ }
-+}
-+
-+static void write_dqs_receiver_enable_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
- {
- uint8_t lane;
-+ uint32_t mask;
- uint32_t dword;
-
-- for (lane = 0; lane < 8; lane++) {
-+ if (is_fam15h())
-+ mask = 0x3ff;
-+ else
-+ mask = 0x1ff;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
- uint32_t ret_reg;
- if ((lane == 0) || (lane == 1))
- ret_reg = 0x10;
-@@ -134,17 +392,125 @@ static void write_dqs_receiver_enable_control_registers(uint16_t* current_total_
- ret_reg = 0x20;
- if ((lane == 6) || (lane == 7))
- ret_reg = 0x21;
-+ if (lane == 8)
-+ ret_reg = 0x12;
- ret_reg += dimm * 3;
-- dword = Get_NB32_index_wait(dev, index_reg, ret_reg);
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg);
- if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) {
-- dword &= ~(0x1ff << 16);
-- dword |= (current_total_delay[lane] & 0x1ff) << 16;
-+ dword &= ~(mask << 16);
-+ dword |= (current_total_delay[lane] & mask) << 16;
- }
-- if ((lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) {
-- dword &= ~0x1ff;
-- dword |= current_total_delay[lane] & 0x1ff;
-+ if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) {
-+ dword &= ~mask;
-+ dword |= current_total_delay[lane] & mask;
- }
-- Set_NB32_index_wait(dev, index_reg, ret_reg, dword);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg, dword);
-+ }
-+}
-+
-+static void read_dram_phase_recovery_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint8_t lane;
-+ uint32_t dword;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint32_t prc_reg;
-+
-+ /* Calculate DRAM Phase Recovery Control register location */
-+ if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3))
-+ prc_reg = 0x50;
-+ if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7))
-+ prc_reg = 0x51;
-+ if (lane == 8)
-+ prc_reg = 0x52;
-+
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, prc_reg);
-+ if ((lane == 7) || (lane == 3)) {
-+ current_total_delay[lane] = (dword >> 24) & 0x7f;
-+ }
-+ if ((lane == 6) || (lane == 2)) {
-+ current_total_delay[lane] = (dword >> 16) & 0x7f;
-+ }
-+ if ((lane == 5) || (lane == 1)) {
-+ current_total_delay[lane] = (dword >> 8) & 0x7f;
-+ }
-+ if ((lane == 8) || (lane == 4) || (lane == 0)) {
-+ current_total_delay[lane] = dword & 0x7f;
-+ }
-+ }
-+}
-+
-+static void write_dram_phase_recovery_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint8_t lane;
-+ uint32_t dword;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint32_t prc_reg;
-+
-+ /* Calculate DRAM Phase Recovery Control register location */
-+ if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3))
-+ prc_reg = 0x50;
-+ if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7))
-+ prc_reg = 0x51;
-+ if (lane == 8)
-+ prc_reg = 0x52;
-+
-+ /* Set DRAM Phase Recovery Control register values */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, prc_reg);
-+ if ((lane == 7) || (lane == 3)) {
-+ dword &= ~(0x7f << 24);
-+ dword |= (current_total_delay[lane] & 0x7f) << 24;
-+ }
-+ if ((lane == 6) || (lane == 2)) {
-+ dword &= ~(0x7f << 16);
-+ dword |= (current_total_delay[lane] & 0x7f) << 16;
-+ }
-+ if ((lane == 5) || (lane == 1)) {
-+ dword &= ~(0x7f << 8);
-+ dword |= (current_total_delay[lane] & 0x7f) << 8;
-+ }
-+ if ((lane == 8) || (lane == 4) || (lane == 0)) {
-+ dword &= ~0x7f;
-+ dword |= current_total_delay[lane] & 0x7f;
-+ }
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, prc_reg, dword);
-+ }
-+}
-+
-+static void read_read_dqs_timing_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg)
-+{
-+ uint8_t lane;
-+ uint32_t dword;
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint32_t rdt_reg;
-+
-+ /* Calculate DRAM Read DQS Timing register location */
-+ if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3))
-+ rdt_reg = 0x5;
-+ if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7))
-+ rdt_reg = 0x6;
-+ if (lane == 8)
-+ rdt_reg = 0x7;
-+ rdt_reg |= (dimm << 8);
-+
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, rdt_reg);
-+ if ((lane == 7) || (lane == 3)) {
-+ current_total_delay[lane] = (dword >> 24) & 0x3f;
-+ }
-+ if ((lane == 6) || (lane == 2)) {
-+ current_total_delay[lane] = (dword >> 16) & 0x3f;
-+ }
-+ if ((lane == 5) || (lane == 1)) {
-+ current_total_delay[lane] = (dword >> 8) & 0x3f;
-+ }
-+ if ((lane == 8) || (lane == 4) || (lane == 0)) {
-+ current_total_delay[lane] = dword & 0x3f;
-+ }
-+
-+ if (is_fam15h())
-+ current_total_delay[lane] >>= 1;
- }
- }
-
-@@ -160,10 +526,11 @@ static uint32_t convert_testaddr_and_channel_to_address(struct DCTStatStruc *pDC
- return testaddr;
- }
-
--/* DQS Receiver Enable Training
-- * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.2
-+/* DQS Receiver Enable Training (Family 10h)
-+ * Algorithm detailed in:
-+ * The Fam10h BKDG Rev. 3.62 section 2.8.9.9.2
- */
--static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
-+static void dqsTrainRcvrEn_SW_Fam10(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 Pass)
- {
- u8 Channel;
-@@ -171,7 +538,6 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- u8 Addl_Index = 0;
- u8 Receiver;
- u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0;
-- u8 Final_Value;
- u16 CTLRMaxDelay;
- u16 MaxDelay_CH[2];
- u32 TestAddr0, TestAddr1, TestAddr0B, TestAddr1B;
-@@ -188,6 +554,7 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- u32 lo, hi;
-
- uint32_t dword;
-+ uint8_t dimm;
- uint8_t rank;
- uint8_t lane;
- uint16_t current_total_delay[MAX_BYTE_LANES];
-@@ -214,14 +581,13 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- }
-
- for (ch = ch_start; ch < ch_end; ch++) {
-- reg = 0x78 + (0x100 * ch);
-- val = Get_NB32(dev, reg);
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, ch, reg);
- val &= ~(0x3ff << 22);
-- val |= (0x0c8 << 22); /* Max Rd Lat */
-- Set_NB32(dev, reg, val);
-+ val |= (0x0c8 << 22); /* MaxRdLatency = 0xc8 */
-+ Set_NB32_DCT(dev, ch, reg, val);
- }
-
-- Final_Value = 1;
- if (Pass == FirstPass) {
- mct_InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat);
- } else {
-@@ -260,7 +626,7 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
-
- CTLRMaxDelay = 0;
- MaxDelay_CH[Channel] = 0;
-- index_reg = 0x98 + 0x100 * Channel;
-+ index_reg = 0x98;
-
- Receiver = mct_InitReceiver_D(pDCTstat, Channel);
- /* There are four receiver pairs, loosely associated with chipselects.
-@@ -268,6 +634,7 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- */
- for (; Receiver < 8; Receiver += 2) {
- Addl_Index = (Receiver >> 1) * 3 + 0x10;
-+ dimm = (Receiver >> 1);
-
- print_debug_dqs("\t\tTrainRcvEnd52: index ", Addl_Index, 2);
-
-@@ -284,45 +651,14 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- /* 2.8.9.9.2 (1, 6)
- * Retrieve gross and fine timing fields from write DQS registers
- */
-- read_dqs_write_timing_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ read_dqs_write_timing_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-
- /* 2.8.9.9.2 (1)
- * Program the Write Data Timing and Write ECC Timing register to
- * the values stored in the DQS Write Timing Control register
- * for each lane
- */
-- for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-- uint32_t wdt_reg;
--
-- /* Calculate Write Data Timing register location */
-- if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3))
-- wdt_reg = 0x1;
-- if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7))
-- wdt_reg = 0x2;
-- if (lane == 8)
-- wdt_reg = 0x3;
-- wdt_reg |= ((Receiver / 2) << 8);
--
-- /* Set Write Data Timing register values */
-- dword = Get_NB32_index_wait(dev, index_reg, wdt_reg);
-- if ((lane == 7) || (lane == 3)) {
-- dword &= ~(0x7f << 24);
-- dword |= (current_total_delay[lane] & 0x7f) << 24;
-- }
-- if ((lane == 6) || (lane == 2)) {
-- dword &= ~(0x7f << 16);
-- dword |= (current_total_delay[lane] & 0x7f) << 16;
-- }
-- if ((lane == 5) || (lane == 1)) {
-- dword &= ~(0x7f << 8);
-- dword |= (current_total_delay[lane] & 0x7f) << 8;
-- }
-- if ((lane == 8) || (lane == 4) || (lane == 0)) {
-- dword &= ~0x7f;
-- dword |= current_total_delay[lane] & 0x7f;
-- }
-- Set_NB32_index_wait(dev, index_reg, wdt_reg, dword);
-- }
-+ write_write_data_timing_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-
- /* 2.8.9.9.2 (2)
- * Program the Read DQS Timing Control and the Read DQS ECC Timing Control registers
-@@ -336,12 +672,12 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- rdt_reg = 0x6;
- if (lane == 8)
- rdt_reg = 0x7;
-- rdt_reg |= ((Receiver / 2) << 8);
-+ rdt_reg |= (dimm << 8);
- if (lane == 8)
- dword = 0x0000003f;
- else
- dword = 0x3f3f3f3f;
-- Set_NB32_index_wait(dev, index_reg, rdt_reg, dword);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, rdt_reg, dword);
- }
-
- /* 2.8.9.9.2 (3)
-@@ -371,7 +707,7 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- print_debug_dqs("\t\tTrainRcvEn53: TestAddr1B ", TestAddr1B, 2);
-
- /* 2.8.9.9.2 (4, 5)
-- * Write 1 cache line of the appropriate test pattern to each test addresse
-+ * Write 1 cache line of the appropriate test pattern to each test address
- */
- mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0, 0); /* rank 0 of DIMM, testpattern 0 */
- mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0B, 1); /* rank 0 of DIMM, testpattern 1 */
-@@ -390,7 +726,7 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- /* 2.8.9.9.2 (6)
- * Write gross and fine timing fields to read DQS registers
- */
-- write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-
- /* 2.8.9.9.2 (7)
- * Loop over all delay values up to 1 MEMCLK (0x40 delay steps) from the initial delay values
-@@ -417,8 +753,8 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- break;
-
- /* 2.8.9.9.2 (7 A)
-- * Loop over all ranks
-- */
-+ * Loop over all ranks
-+ */
- for (rank = 0; rank < (_2Ranks + 1); rank++) {
- /* 2.8.9.9.2 (7 A a-d)
- * Read the first test address of the current rank
-@@ -434,17 +770,17 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- */
- proc_IOCLFLUSH_D((rank == 0)?TestAddr0B:TestAddr1B);
- result_qword2 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0B:TestAddr1B, Channel));
-- write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
- proc_IOCLFLUSH_D((rank == 0)?TestAddr0:TestAddr1);
- result_qword1 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0:TestAddr1, Channel));
-- write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
- } else {
- proc_IOCLFLUSH_D((rank == 0)?TestAddr0:TestAddr1);
- result_qword1 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0:TestAddr1, Channel));
-- write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
- proc_IOCLFLUSH_D((rank == 0)?TestAddr0B:TestAddr1B);
- result_qword2 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0B:TestAddr1B, Channel));
-- write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
- }
- /* 2.8.9.9.2 (7 A e)
- * Compare both read patterns and flag passing ranks/lanes
-@@ -533,7 +869,7 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- }
-
- /* Update delays in hardware */
-- write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver >> 1), index_reg);
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-
- /* Save previous results for comparison in the next iteration */
- for (lane = 0; lane < 8; lane++)
-@@ -587,7 +923,483 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
- mct_SetMaxLatency_D(pDCTstat, Channel, CTLRMaxDelay); /* program Ch A/B MaxAsyncLat to correspond with max delay */
- }
-
-- ResetDCTWrPtr_D(dev, index_reg, Addl_Index);
-+ for (Channel = 0; Channel < 2; Channel++) {
-+ ResetDCTWrPtr_D(dev, Channel, index_reg, Addl_Index);
-+ }
-+
-+ if(_DisableDramECC) {
-+ mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
-+ }
-+
-+ if (Pass == FirstPass) {
-+ /*Disable DQSRcvrEn training mode */
-+ mct_DisableDQSRcvEn_D(pDCTstat);
-+ }
-+
-+ if(!_Wrap32Dis) {
-+ msr = HWCR;
-+ _RDMSR(msr, &lo, &hi);
-+ lo &= ~(1<<17); /* restore HWCR.wrap32dis */
-+ _WRMSR(msr, lo, hi);
-+ }
-+ if(!_SSE2){
-+ cr4 = read_cr4();
-+ cr4 &= ~(1<<9); /* restore cr4.OSFXSR */
-+ write_cr4(cr4);
-+ }
-+
-+#if DQS_TRAIN_DEBUG > 0
-+ {
-+ u8 ChannelDTD;
-+ printk(BIOS_DEBUG, "TrainRcvrEn: CH_MaxRdLat:\n");
-+ for(ChannelDTD = 0; ChannelDTD<2; ChannelDTD++) {
-+ printk(BIOS_DEBUG, "Channel:%x: %x\n",
-+ ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD]);
-+ }
-+ }
-+#endif
-+
-+#if DQS_TRAIN_DEBUG > 0
-+ {
-+ u16 valDTD;
-+ u8 ChannelDTD, ReceiverDTD;
-+ u8 i;
-+ u16 *p;
-+
-+ printk(BIOS_DEBUG, "TrainRcvrEn: CH_D_B_RCVRDLY:\n");
-+ for(ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
-+ printk(BIOS_DEBUG, "Channel:%x\n", ChannelDTD);
-+ for(ReceiverDTD = 0; ReceiverDTD<8; ReceiverDTD+=2) {
-+ printk(BIOS_DEBUG, "\t\tReceiver:%x:", ReceiverDTD);
-+ p = pDCTstat->CH_D_B_RCVRDLY[ChannelDTD][ReceiverDTD>>1];
-+ for (i=0;i<8; i++) {
-+ valDTD = p[i];
-+ printk(BIOS_DEBUG, " %03x", valDTD);
-+ }
-+ printk(BIOS_DEBUG, "\n");
-+ }
-+ }
-+ }
-+#endif
-+
-+ printk(BIOS_DEBUG, "TrainRcvrEn: Status %x\n", pDCTstat->Status);
-+ printk(BIOS_DEBUG, "TrainRcvrEn: ErrStatus %x\n", pDCTstat->ErrStatus);
-+ printk(BIOS_DEBUG, "TrainRcvrEn: ErrCode %x\n", pDCTstat->ErrCode);
-+ printk(BIOS_DEBUG, "TrainRcvrEn: Done\n\n");
-+}
-+
-+/* DQS Receiver Enable Training Pattern Generation (Family 15h)
-+ * Algorithm detailed in:
-+ * The Fam15h BKDG Rev. 3.14 section 2.10.5.8.2 (4)
-+ */
-+static void generate_dram_receiver_enable_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver)
-+{
-+ uint32_t dword;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ /* 2.10.5.7.1.1
-+ * It appears that the DCT only supports 8-beat burst length mode,
-+ * so do nothing here...
-+ */
-+
-+ /* Wait for CmdSendInProg == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ } while (dword & (0x1 << 12));
-+
-+ /* Set CmdTestEnable = 1 */
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword |= (0x1 << 2);
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ /* 2.10.5.8.6.1.1 Send Activate Command */
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */
-+ dword |= ((0x1 << Receiver) << 22);
-+ dword &= ~(0x7 << 19); /* CmdBank = 0 */
-+ dword &= ~(0x3ffff); /* CmdAddress = 0 */
-+ dword |= (0x1 << 31); /* SendActCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x28c, dword);
-+
-+ /* Wait for SendActCmd == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ } while (dword & (0x1 << 31));
-+
-+ /* Wait 75 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 75);
-+
-+ /* 2.10.5.8.6.1.2 */
-+ Set_NB32_DCT(dev, dct, 0x274, 0x0); /* DQMask = 0 */
-+ Set_NB32_DCT(dev, dct, 0x278, 0x0);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x27c);
-+ dword &= ~(0xff); /* EccMask = 0 */
-+ if (pDCTstat->DimmECCPresent == 0)
-+ dword |= 0xff; /* EccMask = 0xff */
-+ Set_NB32_DCT(dev, dct, 0x27c, dword);
-+
-+ /* 2.10.5.8.6.1.2 */
-+ dword = Get_NB32_DCT(dev, dct, 0x270);
-+ dword &= ~(0x7ffff); /* DataPrbsSeed = 55555 */
-+// dword |= (0x55555);
-+ dword |= (0x44443); /* Use AGESA seed */
-+ Set_NB32_DCT(dev, dct, 0x270, dword);
-+
-+ /* 2.10.5.8.2 (4) */
-+ dword = Get_NB32_DCT(dev, dct, 0x260);
-+ dword &= ~(0x1fffff); /* CmdCount = 192 */
-+ dword |= 192;
-+ Set_NB32_DCT(dev, dct, 0x260, dword);
-+
-+#if 0
-+ /* TODO: This applies to Fam15h model 10h and above only */
-+ /* Program Bubble Count and CmdStreamLen */
-+ dword = Get_NB32_DCT(dev, dct, 0x25c);
-+ dword &= ~(0x3ff << 12); /* BubbleCnt = 0 */
-+ dword &= ~(0x3ff << 22); /* BubbleCnt2 = 0 */
-+ dword &= ~(0xff); /* CmdStreamLen = 1 */
-+ dword |= 0x1;
-+ Set_NB32_DCT(dev, dct, 0x25c, dword);
-+#endif
-+
-+ /* Configure Target A */
-+ dword = Get_NB32_DCT(dev, dct, 0x254);
-+ dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */
-+ dword |= (Receiver & 0x7) << 24;
-+ dword &= ~(0x7 << 21); /* TgtBank = 0 */
-+ dword &= ~(0x3ff); /* TgtAddress = 0 */
-+ Set_NB32_DCT(dev, dct, 0x254, dword);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword |= (0x1 << 3); /* ResetAllErr = 1 */
-+ dword &= ~(0x1 << 4); /* StopOnErr = 0 */
-+ dword &= ~(0x3 << 8); /* CmdTgt = 0 (Target A) */
-+ dword &= ~(0x7 << 5); /* CmdType = 0 (Read) */
-+ dword |= (0x1 << 11); /* SendCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ /* 2.10.5.8.6.1.2 Wait for TestStatus == 1 and CmdSendInProg == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ } while ((dword & (0x1 << 12)) || (!(dword & (0x1 << 10))));
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword &= ~(0x1 << 11); /* SendCmd = 0 */
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+
-+ /* 2.10.5.8.6.1.1 Send Precharge Command */
-+ /* Wait 25 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25);
-+
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */
-+ dword |= ((0x1 << Receiver) << 22);
-+ dword &= ~(0x7 << 19); /* CmdBank = 0 */
-+ dword &= ~(0x3ffff); /* CmdAddress = 0x400 */
-+ dword |= 0x400;
-+ dword |= (0x1 << 30); /* SendPchgCmd = 1 */
-+ Set_NB32_DCT(dev, dct, 0x28c, dword);
-+
-+ /* Wait for SendPchgCmd == 0 */
-+ do {
-+ dword = Get_NB32_DCT(dev, dct, 0x28c);
-+ } while (dword & (0x1 << 30));
-+
-+ /* Wait 25 MEMCLKs. */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25);
-+
-+ /* Set CmdTestEnable = 0 */
-+ dword = Get_NB32_DCT(dev, dct, 0x250);
-+ dword &= ~(0x1 << 2);
-+ Set_NB32_DCT(dev, dct, 0x250, dword);
-+}
-+
-+/* DQS Receiver Enable Training (Family 15h)
-+ * Algorithm detailed in:
-+ * The Fam15h BKDG Rev. 3.14 section 2.10.5.8.2
-+ * This algorithm runs once at the lowest supported MEMCLK,
-+ * then once again at the highest supported MEMCLK.
-+ */
-+static void dqsTrainRcvrEn_SW_Fam15(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat, u8 Pass)
-+{
-+ u8 Channel;
-+ u8 _2Ranks;
-+ u8 Addl_Index = 0;
-+ u8 Receiver;
-+ u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0;
-+ u32 Errors;
-+
-+ u32 val;
-+ u32 dev;
-+ u32 index_reg;
-+ u32 ch_start, ch_end, ch;
-+ u32 msr;
-+ u32 cr4;
-+ u32 lo, hi;
-+
-+ uint32_t dword;
-+ uint8_t dimm;
-+ uint8_t rank;
-+ uint8_t lane;
-+ uint8_t mem_clk;
-+ uint16_t initial_seed;
-+ uint16_t current_total_delay[MAX_BYTE_LANES];
-+ uint16_t dqs_ret_pass1_total_delay[MAX_BYTE_LANES];
-+ uint16_t rank0_current_total_delay[MAX_BYTE_LANES];
-+ uint16_t phase_recovery_delays[MAX_BYTE_LANES];
-+ uint16_t seed[MAX_BYTE_LANES];
-+ uint16_t seed_gross[MAX_BYTE_LANES];
-+ uint16_t seed_fine[MAX_BYTE_LANES];
-+ uint16_t seed_pre_gross[MAX_BYTE_LANES];
-+
-+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+ uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
-+
-+ print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0);
-+ print_debug_dqs("TrainRcvEn: Pass", Pass, 0);
-+
-+ dev = pDCTstat->dev_dct;
-+ index_reg = 0x98;
-+ ch_start = 0;
-+ ch_end = 2;
-+
-+ for (ch = ch_start; ch < ch_end; ch++) {
-+ uint8_t max_rd_latency = 0x55;
-+ uint8_t p_state;
-+
-+ /* 2.10.5.6 */
-+ fam15EnableTrainingMode(pMCTstat, pDCTstat, ch, 1);
-+
-+ /* 2.10.5.2 */
-+ for (p_state = 0; p_state < 3; p_state++) {
-+ val = Get_NB32_DCT_NBPstate(dev, ch, p_state, 0x210);
-+ val &= ~(0x3ff << 22); /* MaxRdLatency = max_rd_latency */
-+ val |= (max_rd_latency & 0x3ff) << 22;
-+ Set_NB32_DCT_NBPstate(dev, ch, p_state, 0x210, val);
-+ }
-+ }
-+
-+ if (Pass != FirstPass) {
-+ pDCTstat->DimmTrainFail = 0;
-+ pDCTstat->CSTrainFail = ~pDCTstat->CSPresent;
-+ }
-+
-+ cr4 = read_cr4();
-+ if(cr4 & ( 1 << 9)) { /* save the old value */
-+ _SSE2 = 1;
-+ }
-+ cr4 |= (1 << 9); /* OSFXSR enable SSE2 */
-+ write_cr4(cr4);
-+
-+ msr = HWCR;
-+ _RDMSR(msr, &lo, &hi);
-+ /* FIXME: Why use SSEDIS */
-+ if(lo & (1 << 17)) { /* save the old value */
-+ _Wrap32Dis = 1;
-+ }
-+ lo |= (1 << 17); /* HWCR.wrap32dis */
-+ lo &= ~(1 << 15); /* SSEDIS */
-+ _WRMSR(msr, lo, hi); /* Setting wrap32dis allows 64-bit memory references in real mode */
-+
-+ _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat);
-+
-+ Errors = 0;
-+ dev = pDCTstat->dev_dct;
-+
-+ for (Channel = 0; Channel < 2; Channel++) {
-+ print_debug_dqs("\tTrainRcvEn51: Node ", pDCTstat->Node_ID, 1);
-+ print_debug_dqs("\tTrainRcvEn51: Channel ", Channel, 1);
-+ pDCTstat->Channel = Channel;
-+
-+ mem_clk = Get_NB32_DCT(dev, Channel, 0x94) & 0x1f;
-+
-+ Receiver = mct_InitReceiver_D(pDCTstat, Channel);
-+ /* There are four receiver pairs, loosely associated with chipselects.
-+ * This is essentially looping over each DIMM.
-+ */
-+ for (; Receiver < 8; Receiver += 2) {
-+ Addl_Index = (Receiver >> 1) * 3 + 0x10;
-+ dimm = (Receiver >> 1);
-+
-+ print_debug_dqs("\t\tTrainRcvEnd52: index ", Addl_Index, 2);
-+
-+ if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) {
-+ continue;
-+ }
-+
-+ /* Retrieve the total delay values from pass 1 of DQS receiver enable training */
-+ if (Pass != FirstPass) {
-+ read_dqs_receiver_enable_control_registers(dqs_ret_pass1_total_delay, dev, Channel, dimm, index_reg);
-+ }
-+
-+ /* 2.10.5.8.2
-+ * Loop over all ranks
-+ */
-+ if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1))
-+ _2Ranks = 1;
-+ else
-+ _2Ranks = 0;
-+ for (rank = 0; rank < (_2Ranks + 1); rank++) {
-+ /* 2.10.5.8.2 (1)
-+ * Specify the target DIMM to be trained
-+ * Set TrNibbleSel = 0
-+ *
-+ * TODO: Add support for x4 DIMMs
-+ */
-+ dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008);
-+ dword &= ~(0x3 << 4); /* TrDimmSel */
-+ dword |= ((dimm & 0x3) << 4);
-+ dword &= ~(0x1 << 2); /* TrNibbleSel */
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008, dword);
-+
-+ /* 2.10.5.8.2 (2)
-+ * Retrieve gross and fine timing fields from write DQS registers
-+ */
-+ read_dqs_write_timing_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-+
-+ /* 2.10.5.8.2.1
-+ * Generate the DQS Receiver Enable Training Seed Values
-+ */
-+ if (Pass == FirstPass) {
-+ initial_seed = fam15_receiver_enable_training_seed(pDCTstat, Channel, dimm, rank, package_type);
-+
-+ /* Adjust seed for the minimum platform supported frequency */
-+ initial_seed = (uint16_t) (((((uint64_t) initial_seed) *
-+ fam15h_freq_tab[mem_clk] * 100) / (mctGet_NVbits(NV_MIN_MEMCLK) * 100)));
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ uint16_t wl_pass1_delay;
-+ wl_pass1_delay = current_total_delay[lane];
-+
-+ seed[lane] = initial_seed + wl_pass1_delay;
-+ }
-+ } else {
-+ uint8_t addr_prelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */
-+ uint16_t register_delay;
-+ int16_t seed_prescaling;
-+
-+ memcpy(current_total_delay, dqs_ret_pass1_total_delay, sizeof(current_total_delay));
-+ if ((pDCTstat->Status & (1 << SB_Registered))) {
-+ if (addr_prelaunch)
-+ register_delay = 0x30;
-+ else
-+ register_delay = 0x20;
-+ } else if ((pDCTstat->Status & (1 << SB_LoadReduced))) {
-+ /* TODO
-+ * Load reduced DIMM support unimplemented
-+ */
-+ register_delay = 0x0;
-+ } else {
-+ register_delay = 0x0;
-+ }
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ seed_prescaling = current_total_delay[lane] - register_delay - 0x20;
-+ seed[lane] = (uint16_t) (register_delay + ((((uint64_t) seed_prescaling) * fam15h_freq_tab[mem_clk] * 100) / (mctGet_NVbits(NV_MIN_MEMCLK) * 100)));
-+ }
-+ }
-+
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ seed_gross[lane] = (seed[lane] >> 5) & 0x1f;
-+ seed_fine[lane] = seed[lane] & 0x1f;
-+
-+ /*if (seed_gross[lane] == 0)
-+ seed_pre_gross[lane] = 0;
-+ else */if (seed_gross[lane] & 0x1)
-+ seed_pre_gross[lane] = 1;
-+ else
-+ seed_pre_gross[lane] = 2;
-+
-+ /* Calculate phase recovery delays */
-+ phase_recovery_delays[lane] = ((seed_pre_gross[lane] & 0x1f) << 5) | (seed_fine[lane] & 0x1f);
-+
-+ /* Set the gross delay.
-+ * NOTE: While the BKDG states to only program DqsRcvEnGrossDelay, this appears
-+ * to have been a misprint as DqsRcvEnFineDelay should be set to zero as well.
-+ */
-+ current_total_delay[lane] = ((seed_gross[lane] & 0x1f) << 5);
-+ }
-+
-+ /* 2.10.5.8.2 (2) / 2.10.5.8.2.1 (5 6)
-+ * Program PhRecFineDly and PhRecGrossDly
-+ */
-+ write_dram_phase_recovery_control_registers(phase_recovery_delays, dev, Channel, dimm, index_reg);
-+
-+ /* 2.10.5.8.2 (2) / 2.10.5.8.2.1 (7)
-+ * Program the DQS Receiver Enable delay values for each lane
-+ */
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-+
-+ /* 2.10.5.8.2 (3)
-+ * Program DqsRcvTrEn = 1
-+ */
-+ dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008);
-+ dword |= (0x1 << 13);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008, dword);
-+
-+ /* 2.10.5.8.2 (4)
-+ * Issue 192 read requests to the target rank
-+ */
-+ generate_dram_receiver_enable_training_pattern_fam15(pMCTstat, pDCTstat, Channel, Receiver + (rank & 0x1));
-+
-+ /* 2.10.5.8.2 (5)
-+ * Program DqsRcvTrEn = 0
-+ */
-+ dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008);
-+ dword &= ~(0x1 << 13);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008, dword);
-+
-+ /* 2.10.5.8.2 (6)
-+ * Read PhRecGrossDly, PhRecFineDly
-+ */
-+ read_dram_phase_recovery_control_registers(phase_recovery_delays, dev, Channel, dimm, index_reg);
-+
-+ /* 2.10.5.8.2 (7)
-+ * Calculate and program the DQS Receiver Enable delay values
-+ */
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ current_total_delay[lane] = (phase_recovery_delays[lane] & 0x1f);
-+ current_total_delay[lane] |= ((seed_gross[lane] + ((phase_recovery_delays[lane] >> 5) & 0x1f) - seed_pre_gross[lane] + 1) << 5);
-+ if (lane == 8)
-+ pDCTstat->CH_D_BC_RCVRDLY[Channel][dimm] = current_total_delay[lane];
-+ else
-+ pDCTstat->CH_D_B_RCVRDLY[Channel][dimm][lane] = current_total_delay[lane];
-+ }
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-+
-+ if (rank == 0) {
-+ /* Back up the Rank 0 delays for later use */
-+ memcpy(rank0_current_total_delay, current_total_delay, sizeof(current_total_delay));
-+ }
-+
-+ if (rank == 1) {
-+ /* 2.10.5.8.2 (8)
-+ * Compute the average delay across both ranks and program the result into
-+ * the DQS Receiver Enable delay registers
-+ */
-+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+ current_total_delay[lane] = (rank0_current_total_delay[lane] + current_total_delay[lane]) / 2;
-+ if (lane == 8)
-+ pDCTstat->CH_D_BC_RCVRDLY[Channel][dimm] = current_total_delay[lane];
-+ else
-+ pDCTstat->CH_D_B_RCVRDLY[Channel][dimm][lane] = current_total_delay[lane];
-+ }
-+ write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
-+ }
-+ }
-+
-+#if DQS_TRAIN_DEBUG > 0
-+ for (lane = 0; lane < 8; lane++)
-+ print_debug_dqs_pair("\t\tTrainRcvEn55: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2);
-+#endif
-+ }
-+ }
-+
-+ /* Calculate and program MaxRdLatency */
-+ Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, Channel);
-
- if(_DisableDramECC) {
- mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
-@@ -674,10 +1486,10 @@ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat)
- }
-
- for (ch=0; ch<ch_end; ch++) {
-- reg = 0x78 + 0x100 * ch;
-- val = Get_NB32(dev, reg);
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, ch, reg);
- val &= ~(1 << DqsRcvEnTrain);
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, ch, reg, val);
- }
- }
-
-@@ -718,7 +1530,7 @@ void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly,
- /* get the register index from table */
- index = Table_DQSRcvEn_Offset[i >> 1];
- index += Addl_Index; /* DIMMx DqsRcvEn byte0 */
-- val = Get_NB32_index_wait(dev, index_reg, index);
-+ val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, index);
- if(i & 1) {
- /* odd byte lane */
- val &= ~(0x1ff << 16);
-@@ -728,7 +1540,7 @@ void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly,
- val &= ~0x1ff;
- val |= (RcvrEnDly & 0x1ff);
- }
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, index, val);
- }
-
- }
-@@ -742,7 +1554,6 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 D
- u32 reg;
- u32 SubTotal;
- u32 index_reg;
-- u32 reg_off;
- u32 val;
-
- uint8_t cpu_val_n;
-@@ -777,17 +1588,16 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 D
- Channel = 0;
-
- dev = pDCTstat->dev_dct;
-- reg_off = 0x100 * Channel;
-- index_reg = 0x98 + reg_off;
-+ index_reg = 0x98;
-
- /* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/
-- val = Get_NB32(dev, 0x88 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x88);
- SubTotal = ((val & 0x0f) + 4) << 1; /* SubTotal is 1/2 Memclk unit */
-
- /* If registered DIMMs are being used then
- * add 1 MEMCLK to the sub-total.
- */
-- val = Get_NB32(dev, 0x90 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x90);
- if(!(val & (1 << UnBuffDimm)))
- SubTotal += 2;
-
-@@ -795,7 +1605,7 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 D
- * add 1, else add 2 to the sub-total.
- * if (AddrCmdSetup || CsOdtSetup || CkeSetup) then K := K + 2;
- */
-- val = Get_NB32_index_wait(dev, index_reg, 0x04);
-+ val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x04);
- if(!(val & 0x00202020))
- SubTotal += 1;
- else
-@@ -803,7 +1613,7 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 D
-
- /* If the F2x[1, 0]78[RdPtrInit] field is 4, 5, 6 or 7 MEMCLKs,
- * then add 4, 3, 2, or 1 MEMCLKs, respectively to the sub-total. */
-- val = Get_NB32(dev, 0x78 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x78);
- SubTotal += 8 - (val & 0x0f);
-
- /* Convert bits 7-5 (also referred to as the coarse delay) of
-@@ -824,7 +1634,7 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 D
- * clocks (NCLKs)
- */
- SubTotal *= 200 * ((Get_NB32(pDCTstat->dev_nbmisc, 0xd4) & 0x1f) + 4);
-- SubTotal /= freq_tab[((Get_NB32(pDCTstat->dev_dct, 0x94 + reg_off) & 0x7) - 3)];
-+ SubTotal /= freq_tab[((Get_NB32_DCT(pDCTstat->dev_dct, Channel, 0x94) & 0x7) - 3)];
- SubTotal = (SubTotal + (2 - 1)) / 2; /* Round up */
-
- /* Add "N" NCLKs to the sub-total. "N" represents part of the
-@@ -841,13 +1651,13 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 D
- /* Program the F2x[1, 0]78[MaxRdLatency] register with
- * the total delay value (in NCLKs).
- */
-- reg = 0x78 + reg_off;
-- val = Get_NB32(dev, reg);
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, Channel, reg);
- val &= ~(0x3ff << 22);
- val |= (SubTotal & 0x3ff) << 22;
-
- /* program MaxRdLatency to correspond with current delay */
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, Channel, reg, val);
- }
-
- static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
-@@ -877,7 +1687,7 @@ static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
- u32 dword;
- u8 dn = 4; /* TODO: Rev C could be 4 */
- u32 dev = pDCTstat->dev_dct;
-- u32 index_reg = 0x98 + 0x100 * Channel;
-+ u32 index_reg = 0x98;
-
- /* FIXME: add Cx support */
- dword = 0x00000000;
-@@ -885,7 +1695,7 @@ static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
- for(j=0; j<dn; j++)
- /* DIMM0 Write Data Timing Low */
- /* DIMM0 Write ECC Timing */
-- Set_NB32_index_wait(dev, index_reg, i + 0x100 * j, dword);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, i + 0x100 * j, dword);
- }
-
- /* errata #180 */
-@@ -893,13 +1703,13 @@ static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
- for(i=5; i<=6; i++) {
- for(j=0; j<dn; j++)
- /* DIMM0 Read DQS Timing Control Low */
-- Set_NB32_index_wait(dev, index_reg, i + 0x100 * j, dword);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, i + 0x100 * j, dword);
- }
-
- dword = 0x0000002f;
- for(j=0; j<dn; j++)
- /* DIMM0 Read DQS ECC Timing Control */
-- Set_NB32_index_wait(dev, index_reg, 7 + 0x100 * j, dword);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, 7 + 0x100 * j, dword);
- }
-
- void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel)
-@@ -912,13 +1722,13 @@ void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel)
- u32 val;
-
- dev = pDCTstat->dev_dct;
-- index_reg = 0x98 + Channel * 0x100;
-+ index_reg = 0x98;
- index = 0x12;
- p = pDCTstat->CH_D_BC_RCVRDLY[Channel];
- print_debug_dqs("\t\tSetEccDQSRcvrPos: Channel ", Channel, 2);
- for(ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) {
- val = p[ChipSel>>1];
-- Set_NB32_index_wait(dev, index_reg, index, val);
-+ Set_NB32_index_wait_DCT(dev, Channel, index_reg, index, val);
- print_debug_dqs_pair("\t\tSetEccDQSRcvrPos: ChipSel ",
- ChipSel, " rcvr_delay ", val, 2);
- index += 3;
-@@ -1002,95 +1812,305 @@ void phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat,
- u8 Node = 0;
- struct DCTStatStruc *pDCTstat;
-
-+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
-+
- /* FIXME: skip for Ax */
-- while (Node < MAX_NODES_SUPPORTED) {
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
- pDCTstat = pDCTstatA + Node;
-+ if (!pDCTstat->NodePresent)
-+ continue;
-+
-+ if (pDCTstat->DCTSysLimit) {
-+ if (is_fam15h()) {
-+ /* Fam15h BKDG v3.14 section 2.10.5.3.3
-+ * This picks up where InitDDRPhy left off
-+ */
-+ uint8_t dct;
-+ uint8_t index;
-+ uint32_t dword;
-+ uint32_t datc_backup;
-+ uint32_t training_dword;
-+ uint32_t fence2_config_dword;
-+ uint32_t fence_tx_pad_config_dword;
-+ uint32_t index_reg = 0x98;
-+ uint32_t dev = pDCTstat->dev_dct;
-+
-+ for (dct = 0; dct < 2; dct++) {
-+ if (!pDCTstat->DIMMValidDCT[dct])
-+ continue;
-+
-+ /* Back up D18F2x9C_x0000_0004_dct[1:0] */
-+ datc_backup = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004);
-+
-+ /* FenceTrSel = 0x2 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008);
-+ dword &= ~(0x3 << 6);
-+ dword |= (0x2 << 6);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008, dword);
-+
-+ /* Set phase recovery seed values */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000050, 0x13131313);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000051, 0x13131313);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000052, 0x00000013);
-+
-+ training_dword = fenceDynTraining_D(pMCTstat, pDCTstat, dct);
-+
-+ /* Save calculated fence value to the TX DLL */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
-+ dword &= ~(0x1f << 26);
-+ dword |= ((training_dword & 0x1f) << 26);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, dword);
-+
-+ /* D18F2x9C_x0D0F_0[F,8:0]0F_dct[1:0][AlwaysEnDllClks]=0x1 */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8));
-+ dword &= ~(0x7 << 12);
-+ dword |= (0x1 << 12);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8), dword);
-+ }
-+
-+ /* FenceTrSel = 0x1 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008);
-+ dword &= ~(0x3 << 6);
-+ dword |= (0x1 << 6);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008, dword);
-+
-+ /* Set phase recovery seed values */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000050, 0x13131313);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000051, 0x13131313);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000052, 0x00000013);
-+
-+ training_dword = fenceDynTraining_D(pMCTstat, pDCTstat, dct);
-+
-+ /* Save calculated fence value to the RX DLL */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
-+ dword &= ~(0x1f << 21);
-+ dword |= ((training_dword & 0x1f) << 21);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, dword);
-+
-+ /* D18F2x9C_x0D0F_0[F,8:0]0F_dct[1:0][AlwaysEnDllClks]=0x0 */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8));
-+ dword &= ~(0x7 << 12);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8), dword);
-+ }
-+
-+ /* FenceTrSel = 0x3 */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008);
-+ dword &= ~(0x3 << 6);
-+ dword |= (0x3 << 6);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008, dword);
-+
-+ /* Set phase recovery seed values */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000050, 0x13131313);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000051, 0x13131313);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000052, 0x00000013);
-+
-+ fence_tx_pad_config_dword = fenceDynTraining_D(pMCTstat, pDCTstat, dct);
-+
-+ /* Save calculated fence value to the TX Pad */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
-+ dword &= ~(0x1f << 16);
-+ dword |= ((fence_tx_pad_config_dword & 0x1f) << 16);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, dword);
-+
-+ /* Program D18F2x9C_x0D0F_[C,8,2][2:0]31_dct[1:0] */
-+ training_dword = fence_tx_pad_config_dword;
-+ if (fence_tx_pad_config_dword < 16)
-+ training_dword |= (0x1 << 4);
-+ else
-+ training_dword = 0;
-+ for (index = 0; index < 0x3; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2031 | (index << 8));
-+ dword &= ~(0x1f);
-+ dword |= (training_dword & 0x1f);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2031 | (index << 8), dword);
-+ }
-+ for (index = 0; index < 0x3; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8031 | (index << 8));
-+ dword &= ~(0x1f);
-+ dword |= (training_dword & 0x1f);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8031 | (index << 8), dword);
-+ }
-+ for (index = 0; index < 0x3; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc031 | (index << 8));
-+ dword &= ~(0x1f);
-+ dword |= (training_dword & 0x1f);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc031 | (index << 8), dword);
-+ }
-+
-+ /* Assemble Fence2 configuration word (Fam15h BKDG v3.14 page 331) */
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
-+ fence2_config_dword = 0;
-+
-+ /* TxPad */
-+ training_dword = (dword >> 16) & 0x1f;
-+ if (training_dword < 16)
-+ training_dword |= 0x10;
-+ else
-+ training_dword = 0;
-+ fence2_config_dword |= training_dword;
-+
-+ /* RxDll */
-+ training_dword = (dword >> 21) & 0x1f;
-+ if (training_dword < 16)
-+ training_dword |= 0x10;
-+ else
-+ training_dword = 0;
-+ fence2_config_dword |= (training_dword << 10);
-+
-+ /* TxDll */
-+ training_dword = (dword >> 26) & 0x1f;
-+ if (training_dword < 16)
-+ training_dword |= 0x10;
-+ else
-+ training_dword = 0;
-+ fence2_config_dword |= (training_dword << 5);
-+
-+ /* Program D18F2x9C_x0D0F_0[F,8:0]31_dct[1:0] */
-+ for (index = 0; index < 0x9; index++) {
-+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0031 | (index << 8));
-+ dword &= ~(0x7fff);
-+ dword |= fence2_config_dword;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0031 | (index << 8), dword);
-+ }
-
-- if(pDCTstat->DCTSysLimit) {
-- fenceDynTraining_D(pMCTstat, pDCTstat, 0);
-- fenceDynTraining_D(pMCTstat, pDCTstat, 1);
-+ /* Restore D18F2x9C_x0000_0004_dct[1:0] */
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004, datc_backup);
-+ }
-+ } else {
-+ fenceDynTraining_D(pMCTstat, pDCTstat, 0);
-+ fenceDynTraining_D(pMCTstat, pDCTstat, 1);
-+ }
- }
-- Node++;
- }
-+
-+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
- }
-
--static void fenceDynTraining_D(struct MCTStatStruc *pMCTstat,
-+static uint32_t fenceDynTraining_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
- {
- u16 avRecValue;
- u32 val;
- u32 dev;
-- u32 index_reg = 0x98 + 0x100 * dct;
-+ u32 index_reg = 0x98;
- u32 index;
-
-- /* BIOS first programs a seed value to the phase recovery engine
-- * (recommended 19) registers.
-- * Dram Phase Recovery Control Register (F2x[1,0]9C_x[51:50] and
-- * F2x[1,0]9C_x52.) .
-- */
- dev = pDCTstat->dev_dct;
-- for (index = 0x50; index <= 0x52; index ++) {
-- val = (FenceTrnFinDlySeed & 0x1F);
-- if (index != 0x52) {
-- val |= val << 8 | val << 16 | val << 24;
-+
-+ if (is_fam15h()) {
-+ /* Set F2x[1,0]9C_x08[PhyFenceTrEn] */
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08);
-+ val |= 1 << PhyFenceTrEn;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val);
-+
-+ /* Wait 2000 MEMCLKs */
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 2000);
-+
-+ /* Clear F2x[1,0]9C_x08[PhyFenceTrEn] */
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08);
-+ val &= ~(1 << PhyFenceTrEn);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val);
-+
-+ /* BIOS reads the phase recovery engine registers
-+ * F2x[1,0]9C_x[51:50] and F2x[1,0]9C_x52.
-+ * Average the fine delay components only.
-+ */
-+ avRecValue = 0;
-+ for (index = 0x50; index <= 0x52; index++) {
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
-+ avRecValue += val & 0x1f;
-+ if (index != 0x52) {
-+ avRecValue += (val >> 8) & 0x1f;
-+ avRecValue += (val >> 16) & 0x1f;
-+ avRecValue += (val >> 24) & 0x1f;
-+ }
- }
-- Set_NB32_index_wait(dev, index_reg, index, val);
-- }
-
-- /* Set F2x[1,0]9C_x08[PhyFenceTrEn]=1. */
-- val = Get_NB32_index_wait(dev, index_reg, 0x08);
-- val |= 1 << PhyFenceTrEn;
-- Set_NB32_index_wait(dev, index_reg, 0x08, val);
--
-- /* Wait 200 MEMCLKs. */
-- mct_Wait(50000); /* wait 200us */
--
-- /* Clear F2x[1,0]9C_x08[PhyFenceTrEn]=0. */
-- val = Get_NB32_index_wait(dev, index_reg, 0x08);
-- val &= ~(1 << PhyFenceTrEn);
-- Set_NB32_index_wait(dev, index_reg, 0x08, val);
--
-- /* BIOS reads the phase recovery engine registers
-- * F2x[1,0]9C_x[51:50] and F2x[1,0]9C_x52. */
-- avRecValue = 0;
-- for (index = 0x50; index <= 0x52; index ++) {
-- val = Get_NB32_index_wait(dev, index_reg, index);
-- avRecValue += val & 0x7F;
-- if (index != 0x52) {
-- avRecValue += (val >> 8) & 0x7F;
-- avRecValue += (val >> 16) & 0x7F;
-- avRecValue += (val >> 24) & 0x7F;
-+ val = avRecValue / 9;
-+ if (avRecValue % 9)
-+ val++;
-+ avRecValue = val;
-+
-+ if (avRecValue < 6)
-+ avRecValue = 0;
-+ else
-+ avRecValue -= 6;
-+
-+ return avRecValue;
-+ } else {
-+ /* BIOS first programs a seed value to the phase recovery engine
-+ * (recommended 19) registers.
-+ * Dram Phase Recovery Control Register (F2x[1,0]9C_x[51:50] and
-+ * F2x[1,0]9C_x52.) .
-+ */
-+ for (index = 0x50; index <= 0x52; index ++) {
-+ val = (FenceTrnFinDlySeed & 0x1F);
-+ if (index != 0x52) {
-+ val |= val << 8 | val << 16 | val << 24;
-+ }
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
- }
-- }
-
-- val = avRecValue / 9;
-- if (avRecValue % 9)
-- val++;
-- avRecValue = val;
-+ /* Set F2x[1,0]9C_x08[PhyFenceTrEn]=1. */
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08);
-+ val |= 1 << PhyFenceTrEn;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val);
-+
-+ /* Wait 200 MEMCLKs. */
-+ mct_Wait(50000); /* wait 200us */
-+
-+ /* Clear F2x[1,0]9C_x08[PhyFenceTrEn]=0. */
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08);
-+ val &= ~(1 << PhyFenceTrEn);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val);
-+
-+ /* BIOS reads the phase recovery engine registers
-+ * F2x[1,0]9C_x[51:50] and F2x[1,0]9C_x52. */
-+ avRecValue = 0;
-+ for (index = 0x50; index <= 0x52; index ++) {
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
-+ avRecValue += val & 0x7F;
-+ if (index != 0x52) {
-+ avRecValue += (val >> 8) & 0x7F;
-+ avRecValue += (val >> 16) & 0x7F;
-+ avRecValue += (val >> 24) & 0x7F;
-+ }
-+ }
-
-- /* Write the (averaged value -8) to F2x[1,0]9C_x0C[PhyFence]. */
-- /* inlined mct_AdjustFenceValue() */
-- /* TODO: The RBC0 is not supported. */
-- /* if (pDCTstat->LogicalCPUID & AMD_RB_C0)
-- avRecValue -= 3;
-- else
-- */
-- if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
-- avRecValue -= 8;
-- else if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
-- avRecValue -= 8;
-- else if (pDCTstat->LogicalCPUID & AMD_DR_Bx)
-- avRecValue -= 8;
--
-- val = Get_NB32_index_wait(dev, index_reg, 0x0C);
-- val &= ~(0x1F << 16);
-- val |= (avRecValue & 0x1F) << 16;
-- Set_NB32_index_wait(dev, index_reg, 0x0C, val);
--
-- /* Rewrite F2x[1,0]9C_x04-DRAM Address/Command Timing Control Register
-- * delays (both channels). */
-- val = Get_NB32_index_wait(dev, index_reg, 0x04);
-- Set_NB32_index_wait(dev, index_reg, 0x04, val);
-+ val = avRecValue / 9;
-+ if (avRecValue % 9)
-+ val++;
-+ avRecValue = val;
-+
-+ /* Write the (averaged value -8) to F2x[1,0]9C_x0C[PhyFence]. */
-+ /* inlined mct_AdjustFenceValue() */
-+ /* TODO: The RBC0 is not supported. */
-+ /* if (pDCTstat->LogicalCPUID & AMD_RB_C0)
-+ avRecValue -= 3;
-+ else
-+ */
-+ if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
-+ avRecValue -= 8;
-+ else if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
-+ avRecValue -= 8;
-+ else if (pDCTstat->LogicalCPUID & AMD_DR_Bx)
-+ avRecValue -= 8;
-+
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0C);
-+ val &= ~(0x1F << 16);
-+ val |= (avRecValue & 0x1F) << 16;
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0C, val);
-+
-+ /* Rewrite F2x[1,0]9C_x04-DRAM Address/Command Timing Control Register
-+ * delays (both channels).
-+ */
-+ val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x04);
-+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x04, val);
-+
-+ return avRecValue;
-+ }
- }
-
- void mct_Wait(u32 cycles)
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
-index f01e011..55068ce 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
-@@ -21,8 +21,14 @@
- u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass)
- {
- u8 ret = 1;
-- if (pass == SecondPass)
-- ret = 0;
-+
-+ if (is_fam15h()) {
-+ /* Fam15h needs two passes */
-+ ret = 1;
-+ } else {
-+ if (pass == SecondPass)
-+ ret = 0;
-+ }
-
- return ret;
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
-index 920f514..68acc75 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
-@@ -218,12 +218,12 @@ static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat,
- }
-
- dev = pDCTstat->dev_dct;
-- reg = 0x78 + Channel * 0x100;
-- val = Get_NB32(dev, reg);
-+ reg = 0x78;
-+ val = Get_NB32_DCT(dev, Channel, reg);
- val &= ~(0x3ff<<22);
- val |= MaxRdLatVal<<22;
- /* program MaxRdLatency to correspond with current delay */
-- Set_NB32(dev, reg, val);
-+ Set_NB32_DCT(dev, Channel, reg, val);
- }
-
- static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr)
-@@ -320,30 +320,28 @@ u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
- u32 valx;
- u32 valxx;
- u32 index_reg;
-- u32 reg_off;
- u32 dev;
-
- if(pDCTstat->GangedMode)
- Channel = 0;
-
-- index_reg = 0x98 + 0x100 * Channel;
-+ index_reg = 0x98;
-
-- reg_off = 0x100 * Channel;
- dev = pDCTstat->dev_dct;
-
- /* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/
-- val = Get_NB32(dev, 0x88 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x88);
- SubTotal = ((val & 0x0f) + 1) << 1; /* SubTotal is 1/2 Memclk unit */
-
- /* If registered DIMMs are being used then add 1 MEMCLK to the sub-total*/
-- val = Get_NB32(dev, 0x90 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x90);
- if(!(val & (1 << UnBuffDimm)))
- SubTotal += 2;
-
- /*If the address prelaunch is setup for 1/2 MEMCLKs then add 1,
- * else add 2 to the sub-total. if (AddrCmdSetup || CsOdtSetup
- * || CkeSetup) then K := K + 2; */
-- val = Get_NB32_index_wait(dev, index_reg, 0x04);
-+ val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x04);
- if(!(val & 0x00202020))
- SubTotal += 1;
- else
-@@ -351,7 +349,7 @@ u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
-
- /* If the F2x[1, 0]78[RdPtrInit] field is 4, 5, 6 or 7 MEMCLKs,
- * then add 4, 3, 2, or 1 MEMCLKs, respectively to the sub-total. */
-- val = Get_NB32(dev, 0x78 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x78);
- SubTotal += 8 - (val & 0x0f);
-
- /* Convert bits 7-5 (also referred to as the course delay) of the current
-@@ -367,7 +365,7 @@ u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
-
- /*New formula:
- SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */
-- val = Get_NB32(dev, 0x94 + reg_off);
-+ val = Get_NB32_DCT(dev, Channel, 0x94);
- /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
- val &= 7;
- if (val >= 3) {
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
-index 1c3e322..0ff4484 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
-@@ -83,6 +83,12 @@ void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
- pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 0;
- }
-
-+ if (pDCTstat->Status & (1 << SB_LoadReduced)) {
-+ pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 1;
-+ } else {
-+ pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 0;
-+ }
-+
- pDCTstat->C_DCTPtr[dct]->RegMan1Present = pDCTstat->RegMan1Present;
-
- for (dimm = 0; dimm < MAX_TOTAL_DIMMS; dimm++) {
-@@ -103,13 +109,13 @@ void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDC
- {
- u32 val;
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
- val |= 1 << 11;
-- Set_NB32(pDCTstat->dev_dct, 0x94, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
- val |= 1 << 11;
-- Set_NB32(pDCTstat->dev_dct, 0x94 + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
- }
-
- void DisableZQcalibration(struct MCTStatStruc *pMCTstat,
-@@ -117,15 +123,15 @@ void DisableZQcalibration(struct MCTStatStruc *pMCTstat,
- {
- u32 val;
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
- val &= ~(1 << 11);
- val &= ~(1 << 10);
-- Set_NB32(pDCTstat->dev_dct, 0x94, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);
-
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
- val &= ~(1 << 11);
- val &= ~(1 << 10);
-- Set_NB32(pDCTstat->dev_dct, 0x94 + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
- }
-
- static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat,
-@@ -142,23 +148,23 @@ static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat,
-
- /* Program F2x[1, 0]90[EnterSelfRefresh]=1. */
- if (DCT0Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
- val |= 1 << EnterSelfRef;
-- Set_NB32(pDCTstat->dev_dct, 0x90, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val);
- }
- if (DCT1Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
- val |= 1 << EnterSelfRef;
-- Set_NB32(pDCTstat->dev_dct, 0x90 + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val);
- }
- /* Wait until the hardware resets F2x[1, 0]90[EnterSelfRefresh]=0. */
- if (DCT0Present)
- do {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
- } while (val & (1 <<EnterSelfRef));
- if (DCT1Present)
- do {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
- } while (val & (1 <<EnterSelfRef));
- }
-
-@@ -168,8 +174,11 @@ static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat,
- static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat)
- {
-- u8 DCT0Present, DCT1Present;
-- u32 val;
-+ uint8_t DCT0Present;
-+ uint8_t DCT1Present;
-+ uint32_t dword;
-+ uint32_t mask;
-+ uint32_t offset;
-
- DCT0Present = pDCTstat->DIMMValidDCT[0];
- if (pDCTstat->GangedMode)
-@@ -177,76 +186,134 @@ static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
- else
- DCT1Present = pDCTstat->DIMMValidDCT[1];
-
-- /* Program F2x[1, 0]90[EnterSelfRefresh]=1. */
-- if (DCT0Present) {
-- val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98, 8);
-- val |= 1 << DisAutoComp;
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98, 8, val);
-- }
-- if (DCT1Present) {
-- val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98 + 0x100, 8);
-- val |= 1 << DisAutoComp;
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98 + 0x100, 8, val);
-+ if (is_fam15h()) {
-+ /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0x190 */
-+ if (DCT0Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006);
-+ dword &= ~(0x0000ffff);
-+ dword |= 0x00000190;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword);
-+ }
-+ if (DCT1Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006);
-+ dword &= ~(0x0000ffff);
-+ dword |= 0x00000190;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword);
-+ }
-+ } else {
-+ /* Program F2x[1, 0]9C[DisAutoComp]=1. */
-+ if (DCT0Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8);
-+ dword |= 1 << DisAutoComp;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword);
-+ mct_Wait(100); /* Wait for 5us */
-+ }
-+ if (DCT1Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8);
-+ dword |= 1 << DisAutoComp;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword);
-+ mct_Wait(100); /* Wait for 5us */
-+ }
- }
-
- /* Program F2x[1, 0]94[MemClkFreqVal] = 0. */
- if (DCT0Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-- val &= ~(1 << MemClkFreqVal);
-- Set_NB32(pDCTstat->dev_dct, 0x94, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
-+ dword &= ~(1 << MemClkFreqVal);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
- }
- if (DCT1Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-- val &= ~(1 << MemClkFreqVal);
-- Set_NB32(pDCTstat->dev_dct, 0x94 + 0x100, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
-+ dword &= ~(1 << MemClkFreqVal);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
- }
-
- /* Program F2x[1, 0]94[MemClkFreq] to specify the target MEMCLK frequency. */
-+ if (is_fam15h()) {
-+ offset = 0x0;
-+ mask = 0x1f;
-+ } else {
-+ offset = 0x1;
-+ mask = 0x7;
-+ }
- if (DCT0Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-- val &= 0xFFFFFFF8;
-- val |= pDCTstat->TargetFreq - 1;
-- Set_NB32(pDCTstat->dev_dct, 0x94, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
-+ dword &= ~mask;
-+ dword |= (pDCTstat->TargetFreq - offset) & mask;
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
- }
- if (DCT1Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-- val &= 0xFFFFFFF8;
-- val |= pDCTstat->TargetFreq - 1;
-- Set_NB32(pDCTstat->dev_dct, 0x94 + 0x100, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
-+ dword &= ~mask;
-+ dword |= (pDCTstat->TargetFreq - offset) & mask;
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
-+ }
-+
-+ if (is_fam15h()) {
-+ if (DCT0Present) {
-+ mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 0);
-+ set_2t_configuration(pMCTstat, pDCTstat, 0);
-+ mct_BeforePlatformSpec(pMCTstat, pDCTstat, 0);
-+ mct_PlatformSpec(pMCTstat, pDCTstat, 0);
-+ }
-+ if (DCT1Present) {
-+ mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1);
-+ set_2t_configuration(pMCTstat, pDCTstat, 1);
-+ mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1);
-+ mct_PlatformSpec(pMCTstat, pDCTstat, 1);
-+ }
- }
-
- /* Program F2x[1, 0]94[MemClkFreqVal] = 1. */
- if (DCT0Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-- val |= 1 << MemClkFreqVal;
-- Set_NB32(pDCTstat->dev_dct, 0x94, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
-+ dword |= 1 << MemClkFreqVal;
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
- }
- if (DCT1Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-- val |= 1 << MemClkFreqVal;
-- Set_NB32(pDCTstat->dev_dct, 0x94 + 0x100, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
-+ dword |= 1 << MemClkFreqVal;
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
- }
-
- /* Wait until F2x[1, 0]94[FreqChgInProg]=0. */
- if (DCT0Present)
- do {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94);
-- } while (val & (1 << FreqChgInProg));
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
-+ } while (dword & (1 << FreqChgInProg));
- if (DCT1Present)
- do {
-- val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100);
-- } while (val & (1 << FreqChgInProg));
--
-- /* Program F2x[1, 0]94[MemClkFreqVal] = 0. */
-- if (DCT0Present) {
-- val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98, 8);
-- val &= ~(1 << DisAutoComp);
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98, 8, val);
-- }
-- if (DCT1Present) {
-- val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98 + 0x100, 8);
-- val &= ~(1 << DisAutoComp);
-- Set_NB32_index_wait(pDCTstat->dev_dct, 0x98 + 0x100, 8, val);
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
-+ } while (dword & (1 << FreqChgInProg));
-+
-+ if (is_fam15h()) {
-+ /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0xf */
-+ if (DCT0Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006);
-+ dword &= ~(0x0000ffff);
-+ dword |= 0x0000000f;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword);
-+ }
-+ if (DCT1Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006);
-+ dword &= ~(0x0000ffff);
-+ dword |= 0x0000000f;
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword);
-+ }
-+ } else {
-+ /* Program F2x[1, 0]9C[DisAutoComp] = 0. */
-+ if (DCT0Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8);
-+ dword &= ~(1 << DisAutoComp);
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword);
-+ mct_Wait(15000); /* Wait for 750us */
-+ }
-+ if (DCT1Present) {
-+ dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8);
-+ dword &= ~(1 << DisAutoComp);
-+ Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword);
-+ mct_Wait(15000); /* Wait for 750us */
-+ }
- }
- }
-
-@@ -267,29 +334,46 @@ static void ExitSelfRefresh(struct MCTStatStruc *pMCTstat,
-
- /* Program F2x[1, 0]90[ExitSelfRef]=1 for both DCTs. */
- if (DCT0Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
- val |= 1 << ExitSelfRef;
-- Set_NB32(pDCTstat->dev_dct, 0x90, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val);
- }
- if (DCT1Present) {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
- val |= 1 << ExitSelfRef;
-- Set_NB32(pDCTstat->dev_dct, 0x90 + 0x100, val);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val);
- }
- /* Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0. */
- if (DCT0Present)
- do {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
- } while (val & (1 << ExitSelfRef));
- if (DCT1Present)
- do {
-- val = Get_NB32(pDCTstat->dev_dct, 0x90 + 0x100);
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
- } while (val & (1 << ExitSelfRef));
- }
-
- void SetTargetFreq(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat)
- {
-+ uint32_t dword;
-+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+
-+ if (is_fam15h()) {
-+ /* Program F2x[1, 0]90[DisDllShutDownSR]=1. */
-+ if (pDCTstat->DIMMValidDCT[0]) {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
-+ dword |= (0x1 << 27);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword);
-+ }
-+ if (pDCTstat->DIMMValidDCT[1]) {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
-+ dword |= (0x1 << 27);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword);
-+ }
-+ }
-+
- /* Program F2x[1,0]90[EnterSelfRefresh]=1.
- * Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0.
- */
-@@ -305,11 +389,38 @@ void SetTargetFreq(struct MCTStatStruc *pMCTstat,
- */
- ChangeMemClk(pMCTstat, pDCTstat);
-
-+ if (is_fam15h()) {
-+ uint8_t dct;
-+ for (dct = 0; dct < 2; dct++) {
-+ if (pDCTstat->DIMMValidDCT[dct]) {
-+ phyAssistedMemFnceTraining(pMCTstat, pDCTstat);
-+ InitPhyCompensation(pMCTstat, pDCTstat, dct);
-+ }
-+ }
-+ }
-+
- /* Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs.
- * Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0.
- */
- ExitSelfRefresh(pMCTstat, pDCTstat);
-
-+ if (is_fam15h()) {
-+ if ((package_type == PT_C3) || (package_type == PT_GR)) {
-+ /* Socket C32 or G34 */
-+ /* Program F2x[1, 0]90[DisDllShutDownSR]=0. */
-+ if (pDCTstat->DIMMValidDCT[0]) {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
-+ dword &= ~(0x1 << 27);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword);
-+ }
-+ if (pDCTstat->DIMMValidDCT[1]) {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
-+ dword &= ~(0x1 << 27);
-+ Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword);
-+ }
-+ }
-+ }
-+
- /* wait for 500 MCLKs after ExitSelfRef, 500*2.5ns=1250ns */
- mct_Wait(250);
-
-@@ -336,13 +447,13 @@ void SetTargetFreq(struct MCTStatStruc *pMCTstat,
- static void Modify_OnDimmMirror(struct DCTStatStruc *pDCTstat, u8 dct, u8 set)
- {
- u32 val;
-- u32 reg_off = dct * 0x100 + 0x44;
-- while (reg_off < (dct * 0x100 + 0x60)) {
-- val = Get_NB32(pDCTstat->dev_dct, reg_off);
-+ u32 reg = 0x44;
-+ while (reg < 0x60) {
-+ val = Get_NB32_DCT(pDCTstat->dev_dct, dct, reg);
- if (val & (1 << CSEnable))
- set ? (val |= 1 << onDimmMirror) : (val &= ~(1<<onDimmMirror));
-- Set_NB32(pDCTstat->dev_dct, reg_off, val);
-- reg_off += 8;
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, reg, val);
-+ reg += 8;
- }
- }
-
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-index 397fd77..35378c8 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-@@ -30,13 +30,22 @@
- *
- *----------------------------------------------------------------------------
- */
--u32 swapAddrBits_wl(sDCTStruct *pDCTData, u32 MRSValue);
--u32 swapBankBits(sDCTStruct *pDCTData, u32 MRSValue);
--void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl);
--void programODT(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm);
--void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass);
--void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm, u8 targetAddr);
--void getWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm);
-+u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue);
-+u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue);
-+void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
-+ u8 dct, u8 dimm, BOOL wl);
-+void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm);
-+void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm, u8 pass);
-+void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass);
-+void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass);
-+
-+static int32_t abs(int32_t val) {
-+ if (val < 0)
-+ val *= -1;
-+
-+ return val;
-+}
-+
- /*
- *-----------------------------------------------------------------------------
- * EXPORTED FUNCTIONS
-@@ -62,34 +71,55 @@ void getWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm);
- * OUT
- *-----------------------------------------------------------------------------
- */
--void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
-- u8 dimm, u8 pass)
-+void AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
-+ u8 dct, u8 dimm, u8 pass)
- {
- u8 ByteLane;
- u32 Value, Addr;
- u16 Addl_Data_Offset, Addl_Data_Port;
-+ sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-
- pDCTData->WLPass = pass;
- /* 1. Specify the target DIMM that is to be trained by programming
- * F2x[1, 0]9C_x08[TrDimmSel].
- */
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_ADD_DCT_PHY_CONTROL_REG, TrDimmSelStart,
-- TrDimmSelEnd,(u32)dimm);
-+ TrDimmSelEnd, (u32)dimm);
-+
-+ if (is_fam15h()) {
-+ /* Set TrNibbleSel = 0
-+ *
-+ * TODO: Add support for x4 DIMMs
-+ */
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_ADD_DCT_PHY_CONTROL_REG, 2,
-+ 2, (u32)0);
-+ }
-+
- /* 2. Prepare the DIMMs for write levelization using DDR3-defined
- * MR commands. */
-- prepareDimms(pMCTData, pDCTData,dimm, TRUE);
-+ prepareDimms(pMCTstat, pDCTstat, dct, dimm, TRUE);
-+
- /* 3. After the DIMMs are configured, BIOS waits 40 MEMCLKs to
- * satisfy DDR3-defined internal DRAM timing.
- */
-- pMCTData->AgesaDelay(40);
-+ if (is_fam15h())
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 40);
-+ else
-+ pMCTData->AgesaDelay(40);
-+
- /* 4. Configure the processor's DDR phy for write levelization training: */
-- procConifg(pMCTData,pDCTData, dimm, pass);
-+ procConfig(pMCTstat, pDCTstat, dct, dimm, pass);
-+
- /* 5. Begin write levelization training:
-- * Program F2x[1, 0]9C_x08[WrtLevelTrEn]=1. */
-- if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ * Program F2x[1, 0]9C_x08[WrtLvTrEn]=1. */
-+ if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx | AMD_FAM15_ALL))
-+ {
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 1);
-+ }
- else
- {
- /* Broadcast write to all D3Dbyte chipset register offset 0xc
-@@ -98,7 +128,7 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
- * retain value of 3:2 (Trdimmsel)
- * reset bit 5 (FrzPR)
- */
-- if (pDCTData->DctTrain)
-+ if (dct)
- {
- Addl_Data_Offset=0x198;
- Addl_Data_Port=0x19C;
-@@ -123,29 +153,127 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
- DctAccessDone, DctAccessDone)) == 0);
- }
-
-+ if (is_fam15h())
-+ proc_MFENCE();
-+
- /* Wait 200 MEMCLKs. If executing pass 2, wait 32 MEMCLKs. */
-- pMCTData->AgesaDelay(140);
-+ if (is_fam15h())
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 200);
-+ else
-+ pMCTData->AgesaDelay(140);
-+
- /* Program F2x[1, 0]9C_x08[WrtLevelTrEn]=0. */
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 0);
-+
- /* Read from registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52
- * to get the gross and fine delay settings
- * for the target DIMM and save these values. */
-- ByteLane = 0;
-- while (ByteLane < MAX_BYTE_LANES)
-- {
-- getWLByteDelay(pDCTData,ByteLane, dimm);
-- setWLByteDelay(pDCTData,ByteLane, dimm, 1);
-- ByteLane++;
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ getWLByteDelay(pDCTstat, dct, ByteLane, dimm, pass);
-+ }
-+
-+ pDCTData->WLCriticalGrossDelayPrevPass = 0x1f;
-+}
-+
-+void AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
-+ u8 dct, u8 dimm, u8 pass)
-+{
-+ u8 ByteLane;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+
-+ if (is_fam15h()) {
-+ int32_t gross_diff[MAX_BYTE_LANES];
-+ int32_t cgd = pDCTData->WLCriticalGrossDelayPrevPass;
-+ uint8_t index = (uint8_t)(MAX_BYTE_LANES * dimm);
-+
-+ /* Calculate the Critical Gross Delay */
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ /* Calculate the gross delay differential for this lane */
-+ gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane];
-+ gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane];
-+
-+ /* WrDqDqsEarly values greater than 2 are reserved */
-+ if (gross_diff[ByteLane] < -2)
-+ gross_diff[ByteLane] = -2;
-+
-+ /* Update the Critical Gross Delay */
-+ if (gross_diff[ByteLane] < cgd)
-+ cgd = gross_diff[ByteLane];
-+ }
-+
-+ pDCTData->WLCriticalGrossDelayPrevPass = cgd;
-+
-+ /* Compensate for occasional noise/instability causing sporadic training failure */
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ uint16_t total_delay_seed = ((pDCTData->WLSeedGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLSeedFineDelay[index+ByteLane] & 0x1f);
-+ uint16_t total_delay_phy = ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f);
-+ if (abs(total_delay_phy - total_delay_seed) > 0x20) {
-+ printk(BIOS_DEBUG, "%s: overriding faulty phy value\n", __func__);
-+ pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane];
-+ pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane];
-+ }
-+ }
-+ }
-+}
-+
-+void AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
-+ u8 dct, u8 dimm, u8 pass)
-+{
-+ u8 ByteLane;
-+ sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+
-+ if (is_fam15h()) {
-+ uint32_t dword;
-+ int32_t gross_diff[MAX_BYTE_LANES];
-+ int32_t cgd = pDCTData->WLCriticalGrossDelayPrevPass;
-+ uint8_t index = (uint8_t)(MAX_BYTE_LANES * dimm);
-+
-+ /* Apply offset(s) if needed */
-+ if (cgd < 0) {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8);
-+ dword &= ~(0x3 << 24); /* WrDqDqsEarly = abs(cgd) */
-+ dword |= ((abs(cgd) & 0x3) << 24);
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8, dword);
-+
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ /* Calculate the gross delay differential for this lane */
-+ gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane];
-+ gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane];
-+
-+ /* Prevent underflow in the presence of noise / instability*/
-+ if (gross_diff[ByteLane] < cgd)
-+ gross_diff[ByteLane] = cgd;
-+
-+ pDCTData->WLGrossDelay[index+ByteLane] = (gross_diff[ByteLane] + (abs(cgd) & 0x3));
-+ }
-+ } else {
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8);
-+ dword &= ~(0x3 << 24); /* WrDqDqsEarly = 0 */
-+ Set_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8, dword);
-+ }
-+ }
-+
-+ /* Write the adjusted gross and fine delay settings
-+ * to the target DIMM. */
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 1, pass);
- }
-
- /* 6. Configure DRAM Phy Control Register so that the phy stops driving
- * write levelization ODT. */
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, 0);
-
-+ if (is_fam15h())
-+ proc_MFENCE();
-+
- /* Wait 10 MEMCLKs to allow for ODT signal settling. */
-- pMCTData->AgesaDelay(10);
-+ if (is_fam15h())
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 10);
-+ else
-+ pMCTData->AgesaDelay(10);
-
- /* 7. Program the target DIMM back to normal operation by configuring
- * the following (See section 2.8.5.4.1.1
-@@ -155,7 +283,7 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
- * For a two DIMM system, program the Rtt value for the target DIMM
- * to the normal operating termination:
- */
-- prepareDimms(pMCTData, pDCTData,dimm,FALSE);
-+ prepareDimms(pMCTstat, pDCTstat, dct, dimm, FALSE);
- }
-
- /*----------------------------------------------------------------------------
-@@ -165,7 +293,7 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
- */
-
- /*-----------------------------------------------------------------------------
-- * u32 swapAddrBits_wl(sDCTStruct *pDCTData, u32 MRSValue)
-+ * u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue)
- *
- * Description:
- * This function swaps the bits in MSR register value
-@@ -177,12 +305,17 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
- *
- * ----------------------------------------------------------------------------
- */
--u32 swapAddrBits_wl(sDCTStruct *pDCTData, u32 MRSValue)
-+u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue)
- {
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
- u32 tempW, tempW1;
-
-- tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_INIT, MrsChipSelStart, MrsChipSelEnd);
-+ if (is_fam15h())
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15);
-+ else
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10);
- if (tempW1 & 1)
- {
- if ((pDCTData->Status[DCT_STATUS_OnDimmMirror]))
-@@ -201,7 +334,7 @@ u32 swapAddrBits_wl(sDCTStruct *pDCTData, u32 MRSValue)
- }
-
- /*-----------------------------------------------------------------------------
-- * u32 swapBankBits(sDCTStruct *pDCTData, u32 MRSValue)
-+ * u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue)
- *
- * Description:
- * This function swaps the bits in MSR register value
-@@ -213,12 +346,17 @@ u32 swapAddrBits_wl(sDCTStruct *pDCTData, u32 MRSValue)
- *
- * ----------------------------------------------------------------------------
- */
--u32 swapBankBits(sDCTStruct *pDCTData, u32 MRSValue)
-+u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue)
- {
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
- u32 tempW, tempW1;
-
-- tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_INIT, MrsChipSelStart, MrsChipSelEnd);
-+ if (is_fam15h())
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15);
-+ else
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10);
- if (tempW1 & 1)
- {
- if ((pDCTData->Status[DCT_STATUS_OnDimmMirror]))
-@@ -269,7 +407,7 @@ static uint16_t unbuffered_dimm_nominal_termination_emrs(uint8_t number_of_dimms
- return term;
- }
-
--static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank)
-+static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t number_of_dimms, uint8_t frequency_index, uint8_t rank_count)
- {
- uint16_t term;
-
-@@ -300,27 +438,27 @@ static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t number_of_dimms
- *
- * Description:
- * This function prepares DIMMS for training
-- *
-- * Parameters:
-- * IN OUT *DCTData - Pointer to buffer with information about each DCT
-- * *SPDData - Pointer to buffer with information about each DIMMs
-- * SPD information
-- * *MCTData - Pointer to buffer with runtime parameters,
-- * IN Dimm - Logical DIMM number
-- * WL - indicates if the routine is used for Write levelization
-- * training
-- *
-- * OUT
-- *
-+ * Fam10h: BKDG Rev. 3.62 section 2.8.9.9.1
-+ * Fam15h: BKDG Rev. 3.14 section 2.10.5.8.1
- * ----------------------------------------------------------------------------
- */
--void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl)
-+void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
-+ u8 dct, u8 dimm, BOOL wl)
- {
- u32 tempW, tempW1, tempW2, MrsBank;
- u8 rank, currDimm, MemClkFreq;
-+ sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+ uint8_t number_of_dimms = pDCTData->MaxDimmsInstalled;
-
-- MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-+ if (is_fam15h()) {
-+ MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_CONFIG_HIGH, 0, 4);
-+ } else {
-+ MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
-+ }
- /* Configure the DCT to send initialization MR commands to the target DIMM
- * by programming the F2x[1,0]7C register using the following steps.
- */
-@@ -328,52 +466,95 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl)
- while ((rank < pDCTData->DimmRanks[dimm]) && (rank < 2))
- {
- /* Program F2x[1, 0]7C[MrsChipSel[2:0]] for the current rank to be trained. */
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsChipSelStart, MrsChipSelEnd, dimm*2+rank);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15, dimm*2+rank);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10, dimm*2+rank);
-+
- /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal DRAM
- * register that defines the required DDR3-defined function for write
- * levelization.
- */
-- MrsBank = swapBankBits(pDCTData,1);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsBankStart, MrsBankEnd, MrsBank);
-+ MrsBank = swapBankBits(pDCTstat, dct, 1);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank);
-+
- /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required DDR3-defined function
- * for write levelization.
- */
- tempW = 0;/* DLL_DIS = 0, DIC = 0, AL = 0, TDQS = 0 */
-
-- /* Set TDQS=1b for x8 DIMM, TDQS=0b for x4 DIMM, when mixed x8 & x4 */
-- tempW2 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_CONFIG_HIGH, RDqsEn, RDqsEn);
-- if (tempW2)
-- {
-- if (pDCTData->DimmX8Present[dimm])
-- tempW |= 0x800;
-+ /* Retrieve normal settings of the MRS control word and clear Rtt_Nom */
-+ if (is_fam15h()) {
-+ tempW = mct_MR1(pMCTstat, pDCTstat, dct, dimm*2+rank) & 0xffff;
-+ tempW &= ~(0x0244);
-+ } else {
-+ /* Set TDQS=1b for x8 DIMM, TDQS=0b for x4 DIMM, when mixed x8 & x4 */
-+ tempW2 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_CONFIG_HIGH, RDqsEn, RDqsEn);
-+ if (tempW2)
-+ {
-+ if (pDCTData->DimmX8Present[dimm])
-+ tempW |= 0x800;
-+ }
- }
-
- /* determine Rtt_Nom for WL & Normal mode */
-- if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-- tempW1 = RttNomTargetRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank);
-- } else {
-+ if (is_fam15h()) {
- if (wl) {
-- if (rank == 0) {
-- /* Get Rtt_WR for the current DIMM and rank */
-- uint16_t dynamic_term = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
--
-- /* Convert dynamic termination code to corresponding nominal termination code */
-- if (dynamic_term == 0x200)
-- tempW1 = 0x04;
-- else if (dynamic_term == 0x400)
-- tempW1 = 0x40;
-- else
-- tempW1 = 0x0;
-+ if (number_of_dimms > 1) {
-+ if (rank == 0) {
-+ /* Get Rtt_WR for the current DIMM and rank */
-+ tempW2 = fam15_rttwr(pDCTstat, dct, dimm, rank, package_type);
-+ } else {
-+ tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type);
-+ }
- } else {
-- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-+ tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type);
- }
- } else {
-- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-+ tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type);
-+ }
-+ tempW1 = 0;
-+ tempW1 |= ((tempW2 & 0x4) >> 2) << 9;
-+ tempW1 |= ((tempW2 & 0x2) >> 1) << 6;
-+ tempW1 |= ((tempW2 & 0x1) >> 0) << 2;
-+ } else {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+ tempW1 = RttNomTargetRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank);
-+ } else {
-+ if (wl) {
-+ if (number_of_dimms > 1) {
-+ if (rank == 0) {
-+ /* Get Rtt_WR for the current DIMM and rank */
-+ uint16_t dynamic_term = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm]);
-+
-+ /* Convert dynamic termination code to corresponding nominal termination code */
-+ if (dynamic_term == 0x200)
-+ tempW1 = 0x04;
-+ else if (dynamic_term == 0x400)
-+ tempW1 = 0x40;
-+ else
-+ tempW1 = 0x0;
-+ } else {
-+ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-+ }
-+ } else {
-+ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-+ }
-+ } else {
-+ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-+ }
- }
- }
-+
-+ /* Apply Rtt_Nom to the MRS control word */
- tempW=tempW|tempW1;
-
- /* All ranks of the target DIMM are set to write levelization mode. */
-@@ -393,68 +574,105 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl)
- tempW = bitTestSet(tempW1, Qoff);
- }
- }
-- /* Program MrsAddress[5,1]=output driver impedance control (DIC):
-- * based on F2x[1,0]84[DrvImpCtrl]
-- */
-- tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, DrvImpCtrlEnd);
-+
-+ /* Program MrsAddress[5,1]=output driver impedance control (DIC) */
-+ if (is_fam15h()) {
-+ tempW1 = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type);
-+ } else {
-+ /* Read DIC from F2x[1,0]84[DrvImpCtrl] */
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, DrvImpCtrlEnd);
-+ }
-+
-+ /* Apply DIC to the MRS control word */
- if (bitTest(tempW1, 1))
- tempW = bitTestSet(tempW, 5);
- if (bitTest(tempW1, 0))
- tempW = bitTestSet(tempW, 1);
-
-- tempW = swapAddrBits_wl(pDCTData, tempW);
-+ tempW = swapAddrBits_wl(pDCTstat, dct, tempW);
-+
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW);
-
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsAddressStart, MrsAddressEnd, tempW);
- /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command to
- * the specified DIMM.
- */
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_INIT, SendMrsCmd, SendMrsCmd, 1);
- /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */
-- while ((get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-+ while ((get_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1)
- {
- }
-+
- /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal DRAM
- * register that defines the required DDR3-defined function for Rtt_WR.
- */
-- MrsBank = swapBankBits(pDCTData,2);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsBankStart, MrsBankEnd, MrsBank);
-+ MrsBank = swapBankBits(pDCTstat, dct, 2);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank);
-+
- /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required DDR3-defined function
- * for Rtt_WR (DRAMTermDyn).
- */
- tempW = 0;/* PASR = 0,*/
-- /* program MrsAddress[7,6,5:3]=SRT,ASR,CWL,
-- * based on F2x[1,0]84[19,18,22:20]=,SRT,ASR,Tcwl */
-- tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_MRS_REGISTER, PCI_MIN_LOW, PCI_MAX_HIGH);
-- if (bitTest(tempW1,19))
-- {tempW = bitTestSet(tempW, 7);}
-- if (bitTest(tempW1,18))
-- {tempW = bitTestSet(tempW, 6);}
-- /* tempW=tempW|(((tempW1>>20)&0x7)<<3); */
-- tempW=tempW|((tempW1&0x00700000)>>17);
-- /* workaround for DR-B0 */
-- if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED]))
-- tempW+=0x8;
-+
-+ /* Retrieve normal settings of the MRS control word and clear Rtt_WR */
-+ if (is_fam15h()) {
-+ tempW = mct_MR2(pMCTstat, pDCTstat, dct, dimm*2+rank) & 0xffff;
-+ tempW &= ~(0x0600);
-+ } else {
-+ /* program MrsAddress[7,6,5:3]=SRT,ASR,CWL,
-+ * based on F2x[1,0]84[19,18,22:20]=,SRT,ASR,Tcwl */
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_MRS_REGISTER, PCI_MIN_LOW, PCI_MAX_HIGH);
-+ if (bitTest(tempW1,19))
-+ {tempW = bitTestSet(tempW, 7);}
-+ if (bitTest(tempW1,18))
-+ {tempW = bitTestSet(tempW, 6);}
-+ /* tempW=tempW|(((tempW1>>20)&0x7)<<3); */
-+ tempW=tempW|((tempW1&0x00700000)>>17);
-+ /* workaround for DR-B0 */
-+ if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED]))
-+ tempW+=0x8;
-+ }
-+
- /* determine Rtt_WR for WL & Normal mode */
-- if (pDCTData->Status[DCT_STATUS_REGISTERED])
-- tempW1 = RttWrRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank);
-- else
-- tempW1 = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-+ if (is_fam15h()) {
-+ tempW1 = (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9);
-+ } else {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED])
-+ tempW1 = RttWrRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank);
-+ else
-+ tempW1 = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm]);
-+ }
-+
-+ /* Apply Rtt_WR to the MRS control word */
- tempW=tempW|tempW1;
-- tempW = swapAddrBits_wl(pDCTData,tempW);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsAddressStart, MrsAddressEnd, tempW);
-+ tempW = swapAddrBits_wl(pDCTstat, dct, tempW);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW);
-+
- /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command to
- the specified DIMM.*/
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_INIT, SendMrsCmd, SendMrsCmd, 1);
-+
- /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */
-- while ((get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-+ while ((get_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1)
- {
- }
-@@ -473,97 +691,163 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl)
- rank = 0;
- while ((rank < pDCTData->DimmRanks[currDimm]) && (rank < 2))
- {
--
- /* Program F2x[1, 0]7C[MrsChipSel[2:0]] for the current rank
- * to be trained.
- */
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_INIT, MrsChipSelStart, MrsChipSelEnd, currDimm*2+rank);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15, currDimm*2+rank);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10, currDimm*2+rank);
-+
- /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal
- * DRAM register that defines the required DDR3-defined function
- * for write levelization.
- */
-- MrsBank = swapBankBits(pDCTData,1);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_INIT, MrsBankStart, MrsBankEnd, MrsBank);
-+ MrsBank = swapBankBits(pDCTstat, dct, 1);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank);
-+
- /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required
- * DDR3-defined function for write levelization.
- */
- tempW = 0;/* DLL_DIS = 0, DIC = 0, AL = 0, TDQS = 0, Level=0, Qoff=0 */
-
-- /* Set TDQS=1b for x8 DIMM, TDQS=0b for x4 DIMM, when mixed x8 & x4 */
-- tempW2 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_CONFIG_HIGH, RDqsEn, RDqsEn);
-- if (tempW2)
-- {
-- if (pDCTData->DimmX8Present[currDimm])
-- tempW |= 0x800;
-+ /* Retrieve normal settings of the MRS control word and clear Rtt_Nom */
-+ if (is_fam15h()) {
-+ tempW = mct_MR1(pMCTstat, pDCTstat, dct, dimm*2+rank) & 0xffff;
-+ tempW &= ~(0x0244);
-+ } else {
-+ /* Set TDQS=1b for x8 DIMM, TDQS=0b for x4 DIMM, when mixed x8 & x4 */
-+ tempW2 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_CONFIG_HIGH, RDqsEn, RDqsEn);
-+ if (tempW2)
-+ {
-+ if (pDCTData->DimmX8Present[currDimm])
-+ tempW |= 0x800;
-+ }
- }
-
- /* determine Rtt_Nom for WL & Normal mode */
-- if (pDCTData->Status[DCT_STATUS_REGISTERED])
-- tempW1 = RttNomNonTargetRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank);
-- else
-- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-+ if (is_fam15h()) {
-+ tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type);
-+ tempW1 = 0;
-+ tempW1 |= ((tempW2 & 0x4) >> 2) << 9;
-+ tempW1 |= ((tempW2 & 0x2) >> 1) << 6;
-+ tempW1 |= ((tempW2 & 0x1) >> 0) << 2;
-+ } else {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED])
-+ tempW1 = RttNomNonTargetRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank);
-+ else
-+ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-+ }
-+
-+ /* Apply Rtt_Nom to the MRS control word */
- tempW=tempW|tempW1;
-- /* program MrsAddress[5,1]=output driver impedance control (DIC):
-- * based on F2x[1,0]84[DrvImpCtrl] */
-- tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, DrvImpCtrlEnd);
-+
-+ /* Program MrsAddress[5,1]=output driver impedance control (DIC) */
-+ if (is_fam15h()) {
-+ tempW1 = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type);
-+ } else {
-+ /* Read DIC from F2x[1,0]84[DrvImpCtrl] */
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, DrvImpCtrlEnd);
-+ }
-+
-+ /* Apply DIC to the MRS control word */
- if (bitTest(tempW1,1))
- {tempW = bitTestSet(tempW, 5);}
- if (bitTest(tempW1,0))
- {tempW = bitTestSet(tempW, 1);}
-- tempW = swapAddrBits_wl(pDCTData,tempW);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_INIT, MrsAddressStart, MrsAddressEnd, tempW);
-+
-+ tempW = swapAddrBits_wl(pDCTstat, dct, tempW);
-+
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW);
-+
- /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command
- * to the specified DIMM.
- */
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-+ set_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd, 1);
-+
- /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */
-- while ((get_Bits(pDCTData, pDCTData->CurrDct,
-+ while ((get_Bits(pDCTData, dct,
- pDCTData->NodeId, FUN_DCT, DRAM_INIT,
- SendMrsCmd, SendMrsCmd)) == 1);
-+
- /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal DRAM
- * register that defines the required DDR3-defined function for Rtt_WR.
- */
-- MrsBank = swapBankBits(pDCTData,2);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsBankStart, MrsBankEnd, MrsBank);
-+ MrsBank = swapBankBits(pDCTstat, dct, 2);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank);
-+
- /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required DDR3-defined function
- * for Rtt_WR (DRAMTermDyn).
- */
- tempW = 0;/* PASR = 0,*/
-- /* program MrsAddress[7,6,5:3]=SRT,ASR,CWL,
-- * based on F2x[1,0]84[19,18,22:20]=,SRT,ASR,Tcwl */
-- tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_MRS_REGISTER, PCI_MIN_LOW, PCI_MAX_HIGH);
-- if (bitTest(tempW1,19))
-- {tempW = bitTestSet(tempW, 7);}
-- if (bitTest(tempW1,18))
-- {tempW = bitTestSet(tempW, 6);}
-- /* tempW=tempW|(((tempW1>>20)&0x7)<<3); */
-- tempW=tempW|((tempW1&0x00700000)>>17);
-- /* workaround for DR-B0 */
-- if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED]))
-- tempW+=0x8;
-+
-+ /* Retrieve normal settings of the MRS control word and clear Rtt_WR */
-+ if (is_fam15h()) {
-+ tempW = mct_MR2(pMCTstat, pDCTstat, dct, dimm*2+rank) & 0xffff;
-+ tempW &= ~(0x0600);
-+ } else {
-+ /* program MrsAddress[7,6,5:3]=SRT,ASR,CWL,
-+ * based on F2x[1,0]84[19,18,22:20]=,SRT,ASR,Tcwl */
-+ tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_MRS_REGISTER, PCI_MIN_LOW, PCI_MAX_HIGH);
-+ if (bitTest(tempW1,19))
-+ {tempW = bitTestSet(tempW, 7);}
-+ if (bitTest(tempW1,18))
-+ {tempW = bitTestSet(tempW, 6);}
-+ /* tempW=tempW|(((tempW1>>20)&0x7)<<3); */
-+ tempW=tempW|((tempW1&0x00700000)>>17);
-+ /* workaround for DR-B0 */
-+ if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED]))
-+ tempW+=0x8;
-+ }
-+
- /* determine Rtt_WR for WL & Normal mode */
-- if (pDCTData->Status[DCT_STATUS_REGISTERED])
-- tempW1 = RttWrRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank);
-- else
-- tempW1 = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-+ if (is_fam15h()) {
-+ tempW1 = (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9);
-+ } else {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED])
-+ tempW1 = RttWrRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank);
-+ else
-+ tempW1 = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm]);
-+ }
-+
-+ /* Apply Rtt_WR to the MRS control word */
- tempW=tempW|tempW1;
-- tempW = swapAddrBits_wl(pDCTData,tempW);
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-- DRAM_INIT, MrsAddressStart, MrsAddressEnd, tempW);
-+ tempW = swapAddrBits_wl(pDCTstat, dct, tempW);
-+ if (is_fam15h())
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW);
-+ else
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
-+ DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW);
-+
- /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command to
- the specified DIMM.*/
-- set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-+ set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_INIT, SendMrsCmd, SendMrsCmd, 1);
-+
- /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */
-- while ((get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-+ while ((get_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1)
- {
- }
-@@ -587,29 +871,60 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl)
- * OUT
- * ----------------------------------------------------------------------------
- */
--void programODT(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm)
-+void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm)
- {
-+ sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+
- u8 WrLvOdt1=0;
-
-- if (pDCTData->Status[DCT_STATUS_REGISTERED] == 0) {
-- if ((pDCTData->DctCSPresent & 0x05) == 0x05) {
-- WrLvOdt1 = 0x03;
-- } else if (bitTest((u32)pDCTData->DctCSPresent,(u8)(dimm*2+1))) {
-- WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, dimm+2);
-+ if (is_fam15h()) {
-+ /* Convert DIMM number to CS */
-+ uint32_t dword;
-+ uint8_t cs;
-+ uint8_t rank = 0;
-+
-+ cs = (dimm * 2) + rank;
-+
-+ /* Fetch preprogammed ODT pattern from configuration registers */
-+ dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, ((cs>3)?0x23c:0x238));
-+ if ((cs == 7) || (cs == 3))
-+ WrLvOdt1 = ((dword >> 24) & 0xf);
-+ else if ((cs == 6) || (cs == 2))
-+ WrLvOdt1 = ((dword >> 16) & 0xf);
-+ else if ((cs == 5) || (cs == 1))
-+ WrLvOdt1 = ((dword >> 8) & 0xf);
-+ else if ((cs == 4) || (cs == 0))
-+ WrLvOdt1 = (dword & 0xf);
-+ } else {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED] == 0) {
-+ if ((pDCTData->DctCSPresent & 0x05) == 0x05) {
-+ WrLvOdt1 = 0x03;
-+ } else if (bitTest((u32)pDCTData->DctCSPresent,(u8)(dimm*2+1))) {
-+ WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, dimm+2);
-+ } else {
-+ WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, dimm);
-+ }
- } else {
-- WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, dimm);
-+ WrLvOdt1 = WrLvOdtRegDimm(pMCTData, pDCTData, dimm);
- }
-- } else {
-- WrLvOdt1 = WrLvOdtRegDimm(pMCTData, pDCTData, dimm);
- }
-
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_ADD_DCT_PHY_CONTROL_REG, 8, 11, (u32)WrLvOdt1);
-
- }
-
-+#ifdef UNUSED_CODE
-+static uint16_t fam15h_next_lowest_memclk_freq(uint16_t memclk_freq)
-+{
-+ uint16_t fam15h_next_lowest_freq_tab[] = {0, 0, 0, 0, 0x4, 0, 0x4, 0, 0, 0, 0x6, 0, 0, 0, 0xa, 0, 0, 0, 0xe, 0, 0, 0, 0x12};
-+ return fam15h_next_lowest_freq_tab[memclk_freq];
-+}
-+#endif
-+
- /*-----------------------------------------------------------------------------
-- * void procConifg(MCTStruct *MCTData,DCTStruct *DCTData, u8 Dimm, u8 Pass)
-+ * void procConfig(MCTStruct *MCTData,DCTStruct *DCTData, u8 Dimm, u8 Pass)
- *
- * Description:
- * This function programs the ODT values for the NB
-@@ -622,31 +937,43 @@ void programODT(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm)
- * OUT
- * ----------------------------------------------------------------------------
- */
--void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
-+void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm, u8 pass)
- {
-- u8 ByteLane, Seed_Gross, Seed_Fine, MemClkFreq;
-+ u8 ByteLane, MemClkFreq;
-+ int32_t Seed_Gross;
-+ int32_t Seed_Fine;
-+ uint8_t Seed_PreGross;
- u32 Value, Addr;
- u16 Addl_Data_Offset, Addl_Data_Port;
-- u16 freq_tab[] = {400, 533, 667, 800};
-+ sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
-+ u16 fam10h_freq_tab[] = {400, 533, 667, 800};
-+ uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
-
-- /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 800MHz */
-- MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-- FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
-+ if (is_fam15h()) {
-+ /* MemClkFreq: 0x4: 333MHz; 0x6: 400MHz; 0xa: 533MHz; 0xe: 667MHz; 0x12: 800MHz; 0x16: 933MHz */
-+ MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_CONFIG_HIGH, 0, 4);
-+ } else {
-+ /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 800MHz */
-+ MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId,
-+ FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
-+ }
-
- /* Program F2x[1, 0]9C_x08[WrLvOdt[3:0]] to the proper ODT settings for the
- * current memory subsystem configuration.
- */
-- programODT(pMCTData, pDCTData, dimm);
-+ programODT(pMCTstat, pDCTstat, dct, dimm);
-
- /* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */
-- if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx)) {
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx | AMD_FAM15_ALL)) {
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, (u32)1);
- }
- else
- {
- /* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 0 for Rev.B */
-- if (pDCTData->DctTrain)
-+ if (dct)
- {
- Addl_Data_Offset=0x198;
- Addl_Data_Port=0x19C;
-@@ -669,33 +996,94 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
- DctAccessDone, DctAccessDone)) == 0);
- }
-
-+ if (is_fam15h())
-+ proc_MFENCE();
-+
- /* Wait 10 MEMCLKs to allow for ODT signal settling. */
-- pMCTData->AgesaDelay(10);
-+ if (is_fam15h())
-+ precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 10);
-+ else
-+ pMCTData->AgesaDelay(10);
-+
-+ /* Program write levelling seed values */
- if (pass == 1)
- {
-- if (pDCTData->Status[DCT_STATUS_REGISTERED])
-- {
-- if(pDCTData->RegMan1Present & ((1<<(dimm*2+pDCTData->DctTrain))))
-+ /* Pass 1 */
-+ if (is_fam15h()) {
-+ uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */
-+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+ uint16_t Seed_Total = 0;
-+ if (package_type == PT_GR) {
-+ /* Socket G34: Fam15h BKDG v3.14 Table 96 */
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+ Seed_Total = 0x41;
-+ } else if (pDCTData->Status[DCT_STATUS_LOAD_REDUCED]) {
-+ Seed_Total = 0x0;
-+ } else {
-+ Seed_Total = 0xf;
-+ }
-+ } else if (package_type == PT_C3) {
-+ /* Socket C32: Fam15h BKDG v3.14 Table 97 */
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+ Seed_Total = 0x3e;
-+ } else if (pDCTData->Status[DCT_STATUS_LOAD_REDUCED]) {
-+ Seed_Total = 0x0;
-+ } else {
-+ Seed_Total = 0x12;
-+ }
-+ } else if (package_type == PT_M2) {
-+ /* Socket AM3: Fam15h BKDG v3.14 Table 98 */
-+ Seed_Total = 0xf;
-+ }
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED])
-+ Seed_Total += ((AddrCmdPrelaunch)?0x10:0x0);
-+
-+ /* Adjust seed for the minimum platform supported frequency */
-+ Seed_Total = (int32_t) (((((int64_t) Seed_Total) *
-+ fam15h_freq_tab[MemClkFreq] * 100) / (mctGet_NVbits(NV_MIN_MEMCLK) * 100)));
-+
-+ Seed_Gross = (Seed_Total >> 5) & 0x1f;
-+ Seed_Fine = Seed_Total & 0x1f;
-+
-+ /* Save seed values for later use */
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ pDCTData->WLSeedGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
-+ pDCTData->WLSeedFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
-+
-+ if (Seed_Gross == 0)
-+ Seed_PreGross = 0;
-+ else if (Seed_Gross & 0x1)
-+ Seed_PreGross = 1;
-+ else
-+ Seed_PreGross = 2;
-+
-+ pDCTData->WLSeedPreGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_PreGross;
-+ }
-+ } else {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED])
- {
-- Seed_Gross = 0x02;
-- Seed_Fine = 0x16;
-+ if(pDCTData->RegMan1Present & ((1<<(dimm*2+dct))))
-+ {
-+ Seed_Gross = 0x02;
-+ Seed_Fine = 0x16;
-+ }
-+ else
-+ {
-+ Seed_Gross = 0x02;
-+ Seed_Fine = 0x00;
-+ }
- }
- else
- {
-- Seed_Gross = 0x02;
-- Seed_Fine = 0x00;
-- }
-- }
-- else
-- {
-- if (MemClkFreq == 6) {
-- /* DDR-800 */
-- Seed_Gross = 0x00;
-- Seed_Fine = 0x1a;
-- } else {
-- /* Use settings for DDR-400 (interpolated from BKDG) */
-- Seed_Gross = 0x00;
-- Seed_Fine = 0x0d;
-+ if (MemClkFreq == 6) {
-+ /* DDR-800 */
-+ Seed_Gross = 0x00;
-+ Seed_Fine = 0x1a;
-+ } else {
-+ /* Use settings for DDR-400 (interpolated from BKDG) */
-+ Seed_Gross = 0x00;
-+ Seed_Fine = 0x0d;
-+ }
- }
- }
- for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
-@@ -711,39 +1099,91 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
- pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
- pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
- }
-- } else { /* Pass 2 */
-+ } else {
-+ /* Pass 2 */
- /* From BKDG, Write Leveling Seed Value. */
-- u32 RegisterDelay, SeedTotal;
-- for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
-- {
-- if (pDCTData->Status[DCT_STATUS_REGISTERED])
-- RegisterDelay = 0x20; /* TODO: ((RCW2 & BIT0) == 0) ? 0x20 : 0x30; */
-- else
-- RegisterDelay = 0;
-- SeedTotal = (pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) |
-- (pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5);
-- /* SeedTotalPreScaling = (the total delay value in F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization
-- training) - RegisterDelay. */
-- SeedTotal = (uint16_t) (RegisterDelay + ((((uint64_t) SeedTotal - RegisterDelay) *
-- freq_tab[MemClkFreq-3] * 100) / (freq_tab[0] * 100)));
-- Seed_Gross = SeedTotal / 32;
-- Seed_Fine = SeedTotal & 0x1f;
-- if (Seed_Gross == 0)
-- Seed_Gross = 0;
-- else if (Seed_Gross & 0x1)
-- Seed_Gross = 1;
-- else
-- Seed_Gross = 2;
-- pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
-- pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
-+ if (is_fam15h()) {
-+ uint32_t RegisterDelay;
-+ int32_t SeedTotal;
-+ int32_t SeedTotalPreScaling;
-+ uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */
-+
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+ if (AddrCmdPrelaunch)
-+ RegisterDelay = 0x30;
-+ else
-+ RegisterDelay = 0x20;
-+ } else {
-+ RegisterDelay = 0;
-+ }
-+ /* Retrieve WrDqDqsEarly */
-+ AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId), FUN_DCT, 0xa8), 25, 24, &Value);
-+
-+ /* Calculate adjusted seed values */
-+ SeedTotal = (pDCTData->WLFineDelayPrevPass[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) |
-+ ((pDCTData->WLGrossDelayPrevPass[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) << 5);
-+ SeedTotalPreScaling = (SeedTotal - RegisterDelay - (0x20 * Value));
-+ SeedTotal = (int32_t) (RegisterDelay + ((((int64_t) SeedTotalPreScaling) *
-+ fam15h_freq_tab[MemClkFreq] * 100) / (fam15h_freq_tab[pDCTData->WLPrevMemclkFreq] * 100)));
-+
-+ if (SeedTotal >= 0) {
-+ Seed_Gross = SeedTotal / 32;
-+ Seed_Fine = SeedTotal % 32;
-+ } else {
-+ Seed_Gross = (SeedTotal / 32) - 1;
-+ Seed_Fine = (SeedTotal % 32) + 32;
-+ }
-+
-+ if (Seed_Gross == 0)
-+ Seed_PreGross = 0;
-+ else if (Seed_Gross & 0x1)
-+ Seed_PreGross = 1;
-+ else
-+ Seed_PreGross = 2;
-+
-+ /* Save seed values for later use */
-+ pDCTData->WLSeedGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
-+ pDCTData->WLSeedFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
-+ pDCTData->WLSeedPreGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_PreGross;
-+
-+ pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_PreGross;
-+ pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
-+ }
-+ } else {
-+ u32 RegisterDelay, SeedTotal;
-+ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
-+ {
-+ if (pDCTData->Status[DCT_STATUS_REGISTERED])
-+ RegisterDelay = 0x20; /* TODO: ((RCW2 & BIT0) == 0) ? 0x20 : 0x30; */
-+ else
-+ RegisterDelay = 0;
-+ SeedTotal = (pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) |
-+ (pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5);
-+ /* SeedTotalPreScaling = (the total delay value in F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization
-+ training) - RegisterDelay. */
-+ SeedTotal = (uint16_t) (RegisterDelay + ((((uint64_t) SeedTotal - RegisterDelay) *
-+ fam10h_freq_tab[MemClkFreq-3] * 100) / (fam10h_freq_tab[0] * 100)));
-+ Seed_Gross = SeedTotal / 32;
-+ Seed_Fine = SeedTotal & 0x1f;
-+ if (Seed_Gross == 0)
-+ Seed_Gross = 0;
-+ else if (Seed_Gross & 0x1)
-+ Seed_Gross = 1;
-+ else
-+ Seed_Gross = 2;
-+ pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
-+ pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
-+ }
- }
- }
-
-- setWLByteDelay(pDCTData, ByteLane, dimm, 0);
-+ pDCTData->WLPrevMemclkFreq = MemClkFreq;
-+ setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 0, pass);
- }
-
- /*-----------------------------------------------------------------------------
-- * void setWLByteDelay(DCTStruct *DCTData, u8 ByteLane, u8 Dimm){
-+ * void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm){
- *
- * Description:
- * This function writes the write levelization byte delay for the Phase
-@@ -763,8 +1203,9 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
- *
- *-----------------------------------------------------------------------------
- */
--void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm, u8 targetAddr)
-+void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass)
- {
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
- u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, index, offsetAddr;
- u32 addr, fineDelayValue, grossDelayValue, ValueLow, ValueHigh, EccValue, tempW;
-
-@@ -777,22 +1218,26 @@ void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm, u8 targetAddr)
- EccValue = 0;
- while (ByteLane < MAX_BYTE_LANES)
- {
-- /* This subtract 0xC workaround might be temporary. */
-- if ((pDCTData->WLPass==2) && (pDCTData->RegMan1Present & (1<<(dimm*2+pDCTData->DctTrain))))
-- {
-- tempW = (pDCTData->WLGrossDelay[index+ByteLane] << 5) | pDCTData->WLFineDelay[index+ByteLane];
-- tempW -= 0xC;
-- pDCTData->WLGrossDelay[index+ByteLane] = (u8)(tempW >> 5);
-- pDCTData->WLFineDelay[index+ByteLane] = (u8)(tempW & 0x1F);
-- }
-- grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane];
-- /* Adjust seed gross delay overflow (greater than 3):
-- * - Program seed gross delay as 2 (gross is 4 or 6) or 1 (gross is 5).
-- * - Keep original seed gross delay for later reference.
-- */
-- if(grossDelayValue >= 3)
-- {
-- grossDelayValue = (grossDelayValue&1)? 1 : 2;
-+ if (is_fam15h()) {
-+ grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane];
-+ } else {
-+ /* This subtract 0xC workaround might be temporary. */
-+ if ((pDCTData->WLPass==2) && (pDCTData->RegMan1Present & (1<<(dimm*2+dct))))
-+ {
-+ tempW = (pDCTData->WLGrossDelay[index+ByteLane] << 5) | pDCTData->WLFineDelay[index+ByteLane];
-+ tempW -= 0xC;
-+ pDCTData->WLGrossDelay[index+ByteLane] = (u8)(tempW >> 5);
-+ pDCTData->WLFineDelay[index+ByteLane] = (u8)(tempW & 0x1F);
-+ }
-+ grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane];
-+ /* Adjust seed gross delay overflow (greater than 3):
-+ * - Program seed gross delay as 2 (gross is 4 or 6) or 1 (gross is 5).
-+ * - Keep original seed gross delay for later reference.
-+ */
-+ if(grossDelayValue >= 3)
-+ {
-+ grossDelayValue = (grossDelayValue&1)? 1 : 2;
-+ }
- }
- fineDelayValue = pDCTData->WLFineDelay[index+ByteLane];
- if (ByteLane < 4)
-@@ -803,15 +1248,16 @@ void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm, u8 targetAddr)
- EccValue = ((grossDelayValue << 5) | fineDelayValue);
- ByteLane++;
- }
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_CONT_ADD_PHASE_REC_CTRL_LOW, 0, 31, (u32)ValueLow);
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH, 0, 31, (u32)ValueHigh);
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- DRAM_CONT_ADD_ECC_PHASE_REC_CTRL, 0, 31, (u32)EccValue);
- }
- else
- {
-+ /* Fam10h BKDG Rev. 3.62 2.8.9.9.1 (6) */
- index = (u8)(MAX_BYTE_LANES * dimm);
- grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane];
- fineDelayValue = pDCTData->WLFineDelay[index+ByteLane];
-@@ -841,16 +1287,24 @@ void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm, u8 targetAddr)
- grossStartLoc = (u8)(fineEndLoc + 1);
- grossEndLoc = (u8)(grossStartLoc + 1);
-
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- (u16)addr, fineStartLoc, fineEndLoc,(u32)fineDelayValue);
-- set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-+ set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
- (u16)addr, grossStartLoc, grossEndLoc, (u32)grossDelayValue);
-+
-+ pDCTData->WLFineDelayPrevPass[index+ByteLane] = fineDelayValue;
-+ pDCTData->WLGrossDelayPrevPass[index+ByteLane] = grossDelayValue;
-+ if (pass == FirstPass) {
-+ pDCTData->WLFineDelayFirstPass[index+ByteLane] = fineDelayValue;
-+ pDCTData->WLGrossDelayFirstPass[index+ByteLane] = grossDelayValue;
-+ pDCTData->WLCriticalGrossDelayFirstPass = pDCTData->WLCriticalGrossDelayPrevPass;
-+ }
- }
-
- }
-
- /*-----------------------------------------------------------------------------
-- * void getWLByteDelay(DCTStruct *DCTData, u8 ByteLane, u8 Dimm)
-+ * void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm)
- *
- * Description:
- * This function reads the write levelization byte delay from the Phase
-@@ -868,8 +1322,9 @@ void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm, u8 targetAddr)
- *
- *-----------------------------------------------------------------------------
- */
--void getWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm)
-+void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass)
- {
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
- u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, tempB1, index;
- u32 addr, fine, gross;
- tempB = 0;
-@@ -890,25 +1345,31 @@ void getWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, u8 dimm)
- grossStartLoc = (u8)(fineEndLoc + 1);
- grossEndLoc = (u8)(grossStartLoc + 1);
-
-- fine = get_ADD_DCT_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId,
-+ fine = get_ADD_DCT_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, (u16)addr, fineStartLoc, fineEndLoc);
-- gross = get_ADD_DCT_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId,
-+ gross = get_ADD_DCT_Bits(pDCTData, dct, pDCTData->NodeId,
- FUN_DCT, (u16)addr, grossStartLoc, grossEndLoc);
-- /* Adjust seed gross delay overflow (greater than 3):
-- * - Adjust the trained gross delay to the original seed gross delay.
-- */
-- if (pDCTData->WLGrossDelay[index+ByteLane] >= 3) {
-- gross += pDCTData->WLGrossDelay[index+ByteLane];
-- if(pDCTData->WLGrossDelay[index+ByteLane] & 1)
-- gross -= 1;
-- else
-- gross -= 2;
-- } else if ((pDCTData->WLGrossDelay[index+ByteLane] == 0) && (gross == 3)) {
-- /* If seed gross delay is 0 but PRE result gross delay is 3, it is negative.
-- * We will then round the negative number to 0.
-+
-+ if (!is_fam15h()) {
-+ /* Adjust seed gross delay overflow (greater than 3):
-+ * - Adjust the trained gross delay to the original seed gross delay.
- */
-- gross = 0;
-- fine = 0;
-+ if(pDCTData->WLGrossDelay[index+ByteLane] >= 3)
-+ {
-+ gross += pDCTData->WLGrossDelay[index+ByteLane];
-+ if(pDCTData->WLGrossDelay[index+ByteLane] & 1)
-+ gross -= 1;
-+ else
-+ gross -= 2;
-+ }
-+ else if((pDCTData->WLGrossDelay[index+ByteLane] == 0) && (gross == 3))
-+ {
-+ /* If seed gross delay is 0 but PRE result gross delay is 3, it is negative.
-+ * We will then round the negative number to 0.
-+ */
-+ gross = 0;
-+ fine = 0;
-+ }
- }
- pDCTData->WLFineDelay[index+ByteLane] = (u8)fine;
- pDCTData->WLGrossDelay[index+ByteLane] = (u8)gross;
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c
-index 0466c77..cf6afaa 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -134,24 +135,48 @@ static u32 get_Bits(sDCTStruct *pDCTData,
- u16 offset, u8 low, u8 high)
- {
- u32 temp;
-+ uint32_t dword;
-+
- /* ASSERT(node < MAX_NODES); */
- if (dct == BOTH_DCTS)
- {
- /* Registers exist on DCT0 only */
-+ if (is_fam15h())
-+ {
-+ /* Select DCT 0 */
-+ AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+ dword &= ~0x1;
-+ AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+ }
-+
- AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
- }
- else
- {
-- if (dct == 1)
-+ if (is_fam15h())
- {
-- /* Write to dct 1 */
-- offset += 0x100;
-+ /* Select DCT */
-+ AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+
-+ /* Read from the selected DCT */
- AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
- }
- else
- {
-- /* Write to dct 0 */
-- AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
-+ if (dct == 1)
-+ {
-+ /* Read from dct 1 */
-+ offset += 0x100;
-+ AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
-+ }
-+ else
-+ {
-+ /* Read from dct 0 */
-+ AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
-+ }
- }
- }
- return temp;
-@@ -184,25 +209,49 @@ static void set_Bits(sDCTStruct *pDCTData,
- u16 offset, u8 low, u8 high, u32 value)
- {
- u32 temp;
-+ uint32_t dword;
-+
- temp = value;
-
- if (dct == BOTH_DCTS)
- {
- /* Registers exist on DCT0 only */
-+ if (is_fam15h())
-+ {
-+ /* Select DCT 0 */
-+ AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+ dword &= ~0x1;
-+ AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+ }
-+
- AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
- }
- else
- {
-- if (dct == 1)
-+ if (is_fam15h())
- {
-- /* Write to dct 1 */
-- offset += 0x100;
-+ /* Select DCT */
-+ AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
-+
-+ /* Write to the selected DCT */
- AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
- }
- else
- {
-- /* Write to dct 0 */
-- AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
-+ if (dct == 1)
-+ {
-+ /* Write to dct 1 */
-+ offset += 0x100;
-+ AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
-+ }
-+ else
-+ {
-+ /* Write to dct 0 */
-+ AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
-+ }
- }
- }
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h
-index f846d87..162340e 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -33,7 +34,8 @@
- #define C_MAX_DIMMS 4 /* Maximum Number of DIMMs on each DCT */
-
- /* STATUS Definition */
--#define DCT_STATUS_REGISTERED 3 /* Registered DIMMs support */
-+#define DCT_STATUS_REGISTERED 3 /* Registered DIMMs support */
-+#define DCT_STATUS_LOAD_REDUCED 4 /* Load-Reduced DIMMs support */
- #define DCT_STATUS_OnDimmMirror 24 /* OnDimmMirror support */
-
- /* PCI Defintions */
-@@ -78,12 +80,18 @@
- #define SendMrsCmd 26
- #define Qoff 12
- #define MRS_Level 7
--#define MrsAddressStart 0
--#define MrsAddressEnd 15
--#define MrsBankStart 16
--#define MrsBankEnd 18
--#define MrsChipSelStart 20
--#define MrsChipSelEnd 22
-+#define MrsAddressStartFam10 0
-+#define MrsAddressEndFam10 15
-+#define MrsAddressStartFam15 0
-+#define MrsAddressEndFam15 17
-+#define MrsBankStartFam10 16
-+#define MrsBankEndFam10 18
-+#define MrsBankStartFam15 18
-+#define MrsBankEndFam15 20
-+#define MrsChipSelStartFam10 20
-+#define MrsChipSelEndFam10 22
-+#define MrsChipSelStartFam15 21
-+#define MrsChipSelEndFam15 23
- #define ASR 18
- #define SRT 19
- #define DramTermDynStart 10
-@@ -115,10 +123,32 @@ typedef struct _sDCTStruct
- u8 DctTrain; /* Current DCT being trained */
- u8 CurrDct; /* Current DCT number (0 or 1) */
- u8 DctCSPresent; /* Current DCT CS mapping */
-+ int32_t WLSeedGrossDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Seed Gross Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ int32_t WLSeedFineDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Seed Fine Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ int32_t WLSeedPreGrossDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Seed Pre-Gross Delay */
-+ /* per byte Lane Per Logical DIMM*/
- u8 WLGrossDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Gross Delay */
- /* per byte Lane Per Logical DIMM*/
- u8 WLFineDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Fine Delay */
- /* per byte Lane Per Logical DIMM*/
-+ u8 WLGrossDelayFirstPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* First-Pass Write Levelization Gross Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ u8 WLFineDelayFirstPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* First-Pass Write Levelization Fine Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ u8 WLGrossDelayPrevPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Previous Pass Write Levelization Gross Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ u8 WLFineDelayPrevPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Previous Pass Write Levelization Fine Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ u8 WLGrossDelayFinalPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Final-Pass Write Levelization Gross Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ u8 WLFineDelayFinalPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Final-Pass Write Levelization Fine Delay */
-+ /* per byte Lane Per Logical DIMM*/
-+ int32_t WLCriticalGrossDelayFirstPass;
-+ int32_t WLCriticalGrossDelayPrevPass;
-+ int32_t WLCriticalGrossDelayFinalPass;
-+ uint16_t WLPrevMemclkFreq;
- u16 RegMan1Present;
- u8 DimmPresent[MAX_TOTAL_DIMMS];/* Indicates which DIMMs are present */
- /* from Total Number of DIMMs(per Node)*/
-@@ -132,7 +162,7 @@ typedef struct _sDCTStruct
- /* per byte lane */
- u8 MaxDimmsInstalled; /* Max Dimms Installed for current DCT */
- u8 DimmRanks[MAX_TOTAL_DIMMS]; /* Total Number of Ranks(per Dimm) */
-- u32 LogicalCPUID;
-+ uint64_t LogicalCPUID;
- u8 WLPass;
- } sDCTStruct;
-
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
-index c9bcac1..aa23951 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
-@@ -18,6 +18,7 @@
- */
-
- #include <string.h>
-+#include <arch/cpu.h>
- #include <arch/acpi.h>
- #include <cpu/x86/msr.h>
- #include <device/device.h>
-@@ -32,6 +33,23 @@
-
- #define S3NV_FILE_NAME "s3nv"
-
-+#ifdef __RAMSTAGE__
-+static inline uint8_t is_fam15h(void)
-+{
-+ uint8_t fam15h = 0;
-+ uint32_t family;
-+
-+ family = cpuid_eax(0x80000001);
-+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
-+
-+ if (family >= 0x6f)
-+ /* Family 15h or later */
-+ fam15h = 1;
-+
-+ return fam15h;
-+}
-+#endif
-+
- static ssize_t get_s3nv_file_offset(void);
-
- ssize_t get_s3nv_file_offset(void)
-@@ -47,6 +65,28 @@ ssize_t get_s3nv_file_offset(void)
- return s3nv_region.region.offset;
- }
-
-+static uint32_t read_config32_dct(device_t dev, uint8_t node, uint8_t dct, uint32_t reg) {
-+ if (is_fam15h()) {
-+ uint32_t dword;
-+#ifdef __PRE_RAM__
-+ device_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1);
-+#else
-+ device_t dev_fn1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1));
-+#endif
-+
-+ /* Select DCT */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+ } else {
-+ /* Apply offset */
-+ reg += dct * 0x100;
-+ }
-+
-+ return pci_read_config32(dev, reg);
-+}
-+
- static uint32_t read_amd_dct_index_register(device_t dev, uint32_t index_ctl_reg, uint32_t index)
- {
- uint32_t dword;
-@@ -61,12 +101,54 @@ static uint32_t read_amd_dct_index_register(device_t dev, uint32_t index_ctl_reg
- return dword;
- }
-
-+static uint32_t read_amd_dct_index_register_dct(device_t dev, uint8_t node, uint8_t dct, uint32_t index_ctl_reg, uint32_t index)
-+{
-+ if (is_fam15h()) {
-+ uint32_t dword;
-+#ifdef __PRE_RAM__
-+ device_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1);
-+#else
-+ device_t dev_fn1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1));
-+#endif
-+
-+ /* Select DCT */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+ } else {
-+ /* Apply offset */
-+ index_ctl_reg += dct * 0x100;
-+ }
-+
-+ return read_amd_dct_index_register(dev, index_ctl_reg, index);
-+}
-+
- #ifdef __RAMSTAGE__
- static uint64_t rdmsr_uint64_t(unsigned long index) {
- msr_t msr = rdmsr(index);
- return (((uint64_t)msr.hi) << 32) | ((uint64_t)msr.lo);
- }
-
-+static uint32_t read_config32_dct_nbpstate(device_t dev, uint8_t node, uint8_t dct, uint8_t nb_pstate, uint32_t reg) {
-+ uint32_t dword;
-+ device_t dev_fn1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1));
-+
-+ /* Select DCT */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+
-+ /* Select NB Pstate index */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~(0x3 << 4);
-+ dword |= (nb_pstate & 0x3) << 4;
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+
-+ return pci_read_config32(dev, reg);
-+}
-+
- void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_data)
- {
- uint8_t i;
-@@ -82,7 +164,8 @@ void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_da
- device_t dev_fn1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1));
- device_t dev_fn2 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 2));
- device_t dev_fn3 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 3));
-- if ((!dev_fn1) || (!dev_fn2) || (!dev_fn3)) {
-+ /* Test for node presence */
-+ if ((!dev_fn1) || (pci_read_config32(dev_fn1, PCI_VENDOR_ID) == 0xffffffff)) {
- persistent_data->node[node].node_present = 0;
- continue;
- }
-@@ -95,22 +178,22 @@ void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_da
- data->f2x110 = pci_read_config32(dev_fn2, 0x110);
-
- /* Stage 2 */
-- data->f1x40 = pci_read_config32(dev_fn1, 0x40 + (0x100 * channel));
-- data->f1x44 = pci_read_config32(dev_fn1, 0x44 + (0x100 * channel));
-- data->f1x48 = pci_read_config32(dev_fn1, 0x48 + (0x100 * channel));
-- data->f1x4c = pci_read_config32(dev_fn1, 0x4c + (0x100 * channel));
-- data->f1x50 = pci_read_config32(dev_fn1, 0x50 + (0x100 * channel));
-- data->f1x54 = pci_read_config32(dev_fn1, 0x54 + (0x100 * channel));
-- data->f1x58 = pci_read_config32(dev_fn1, 0x58 + (0x100 * channel));
-- data->f1x5c = pci_read_config32(dev_fn1, 0x5c + (0x100 * channel));
-- data->f1x60 = pci_read_config32(dev_fn1, 0x60 + (0x100 * channel));
-- data->f1x64 = pci_read_config32(dev_fn1, 0x64 + (0x100 * channel));
-- data->f1x68 = pci_read_config32(dev_fn1, 0x68 + (0x100 * channel));
-- data->f1x6c = pci_read_config32(dev_fn1, 0x6c + (0x100 * channel));
-- data->f1x70 = pci_read_config32(dev_fn1, 0x70 + (0x100 * channel));
-- data->f1x74 = pci_read_config32(dev_fn1, 0x74 + (0x100 * channel));
-- data->f1x78 = pci_read_config32(dev_fn1, 0x78 + (0x100 * channel));
-- data->f1x7c = pci_read_config32(dev_fn1, 0x7c + (0x100 * channel));
-+ data->f1x40 = read_config32_dct(dev_fn1, node, channel, 0x40);
-+ data->f1x44 = read_config32_dct(dev_fn1, node, channel, 0x44);
-+ data->f1x48 = read_config32_dct(dev_fn1, node, channel, 0x48);
-+ data->f1x4c = read_config32_dct(dev_fn1, node, channel, 0x4c);
-+ data->f1x50 = read_config32_dct(dev_fn1, node, channel, 0x50);
-+ data->f1x54 = read_config32_dct(dev_fn1, node, channel, 0x54);
-+ data->f1x58 = read_config32_dct(dev_fn1, node, channel, 0x58);
-+ data->f1x5c = read_config32_dct(dev_fn1, node, channel, 0x5c);
-+ data->f1x60 = read_config32_dct(dev_fn1, node, channel, 0x60);
-+ data->f1x64 = read_config32_dct(dev_fn1, node, channel, 0x64);
-+ data->f1x68 = read_config32_dct(dev_fn1, node, channel, 0x68);
-+ data->f1x6c = read_config32_dct(dev_fn1, node, channel, 0x6c);
-+ data->f1x70 = read_config32_dct(dev_fn1, node, channel, 0x70);
-+ data->f1x74 = read_config32_dct(dev_fn1, node, channel, 0x74);
-+ data->f1x78 = read_config32_dct(dev_fn1, node, channel, 0x78);
-+ data->f1x7c = read_config32_dct(dev_fn1, node, channel, 0x7c);
- data->f1xf0 = pci_read_config32(dev_fn1, 0xf0);
- data->f1x120 = pci_read_config32(dev_fn1, 0x120);
- data->f1x124 = pci_read_config32(dev_fn1, 0x124);
-@@ -134,75 +217,144 @@ void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_da
- data->msrc001001f = rdmsr_uint64_t(0xc001001f);
-
- /* Stage 3 */
-- data->f2x40 = pci_read_config32(dev_fn2, 0x40 + (0x100 * channel));
-- data->f2x44 = pci_read_config32(dev_fn2, 0x44 + (0x100 * channel));
-- data->f2x48 = pci_read_config32(dev_fn2, 0x48 + (0x100 * channel));
-- data->f2x4c = pci_read_config32(dev_fn2, 0x4c + (0x100 * channel));
-- data->f2x50 = pci_read_config32(dev_fn2, 0x50 + (0x100 * channel));
-- data->f2x54 = pci_read_config32(dev_fn2, 0x54 + (0x100 * channel));
-- data->f2x58 = pci_read_config32(dev_fn2, 0x58 + (0x100 * channel));
-- data->f2x5c = pci_read_config32(dev_fn2, 0x5c + (0x100 * channel));
-- data->f2x60 = pci_read_config32(dev_fn2, 0x60 + (0x100 * channel));
-- data->f2x64 = pci_read_config32(dev_fn2, 0x64 + (0x100 * channel));
-- data->f2x68 = pci_read_config32(dev_fn2, 0x68 + (0x100 * channel));
-- data->f2x6c = pci_read_config32(dev_fn2, 0x6c + (0x100 * channel));
-- data->f2x78 = pci_read_config32(dev_fn2, 0x78 + (0x100 * channel));
-- data->f2x7c = pci_read_config32(dev_fn2, 0x7c + (0x100 * channel));
-- data->f2x80 = pci_read_config32(dev_fn2, 0x80 + (0x100 * channel));
-- data->f2x84 = pci_read_config32(dev_fn2, 0x84 + (0x100 * channel));
-- data->f2x88 = pci_read_config32(dev_fn2, 0x88 + (0x100 * channel));
-- data->f2x8c = pci_read_config32(dev_fn2, 0x8c + (0x100 * channel));
-- data->f2x90 = pci_read_config32(dev_fn2, 0x90 + (0x100 * channel));
-- data->f2xa4 = pci_read_config32(dev_fn2, 0xa4 + (0x100 * channel));
-- data->f2xa8 = pci_read_config32(dev_fn2, 0xa8 + (0x100 * channel));
-+ data->f2x40 = read_config32_dct(dev_fn2, node, channel, 0x40);
-+ data->f2x44 = read_config32_dct(dev_fn2, node, channel, 0x44);
-+ data->f2x48 = read_config32_dct(dev_fn2, node, channel, 0x48);
-+ data->f2x4c = read_config32_dct(dev_fn2, node, channel, 0x4c);
-+ data->f2x50 = read_config32_dct(dev_fn2, node, channel, 0x50);
-+ data->f2x54 = read_config32_dct(dev_fn2, node, channel, 0x54);
-+ data->f2x58 = read_config32_dct(dev_fn2, node, channel, 0x58);
-+ data->f2x5c = read_config32_dct(dev_fn2, node, channel, 0x5c);
-+ data->f2x60 = read_config32_dct(dev_fn2, node, channel, 0x60);
-+ data->f2x64 = read_config32_dct(dev_fn2, node, channel, 0x64);
-+ data->f2x68 = read_config32_dct(dev_fn2, node, channel, 0x68);
-+ data->f2x6c = read_config32_dct(dev_fn2, node, channel, 0x6c);
-+ data->f2x78 = read_config32_dct(dev_fn2, node, channel, 0x78);
-+ data->f2x7c = read_config32_dct(dev_fn2, node, channel, 0x7c);
-+ data->f2x80 = read_config32_dct(dev_fn2, node, channel, 0x80);
-+ data->f2x84 = read_config32_dct(dev_fn2, node, channel, 0x84);
-+ data->f2x88 = read_config32_dct(dev_fn2, node, channel, 0x88);
-+ data->f2x8c = read_config32_dct(dev_fn2, node, channel, 0x8c);
-+ data->f2x90 = read_config32_dct(dev_fn2, node, channel, 0x90);
-+ data->f2xa4 = read_config32_dct(dev_fn2, node, channel, 0xa4);
-+ data->f2xa8 = read_config32_dct(dev_fn2, node, channel, 0xa8);
-+
-+ /* Family 15h-specific configuration */
-+ if (is_fam15h()) {
-+ data->f2x200 = read_config32_dct(dev_fn2, node, channel, 0x200);
-+ data->f2x204 = read_config32_dct(dev_fn2, node, channel, 0x204);
-+ data->f2x208 = read_config32_dct(dev_fn2, node, channel, 0x208);
-+ data->f2x20c = read_config32_dct(dev_fn2, node, channel, 0x20c);
-+ for (i=0; i<4; i++)
-+ data->f2x210[i] = read_config32_dct_nbpstate(dev_fn2, node, channel, i, 0x210);
-+ data->f2x214 = read_config32_dct(dev_fn2, node, channel, 0x214);
-+ data->f2x218 = read_config32_dct(dev_fn2, node, channel, 0x218);
-+ data->f2x21c = read_config32_dct(dev_fn2, node, channel, 0x21c);
-+ data->f2x22c = read_config32_dct(dev_fn2, node, channel, 0x22c);
-+ data->f2x230 = read_config32_dct(dev_fn2, node, channel, 0x230);
-+ data->f2x234 = read_config32_dct(dev_fn2, node, channel, 0x234);
-+ data->f2x238 = read_config32_dct(dev_fn2, node, channel, 0x238);
-+ data->f2x23c = read_config32_dct(dev_fn2, node, channel, 0x23c);
-+ data->f2x240 = read_config32_dct(dev_fn2, node, channel, 0x240);
-+
-+ data->f2x9cx0d0fe003 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe003);
-+ data->f2x9cx0d0fe013 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe013);
-+ for (i=0; i<9; i++)
-+ data->f2x9cx0d0f0_8_0_1f[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f001f | (i << 8));
-+ data->f2x9cx0d0f201f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f201f);
-+ data->f2x9cx0d0f211f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f211f);
-+ data->f2x9cx0d0f221f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f221f);
-+ data->f2x9cx0d0f801f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f801f);
-+ data->f2x9cx0d0f811f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f811f);
-+ data->f2x9cx0d0f821f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f821f);
-+ data->f2x9cx0d0fc01f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc01f);
-+ data->f2x9cx0d0fc11f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc11f);
-+ data->f2x9cx0d0fc21f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc21f);
-+ data->f2x9cx0d0f4009 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f4009);
-+ for (i=0; i<9; i++)
-+ data->f2x9cx0d0f0_8_0_02[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0002 | (i << 8));
-+ for (i=0; i<9; i++)
-+ data->f2x9cx0d0f0_8_0_06[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0006 | (i << 8));
-+ for (i=0; i<9; i++)
-+ data->f2x9cx0d0f0_8_0_0a[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f000a | (i << 8));
-+
-+ data->f2x9cx0d0f2002 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2002);
-+ data->f2x9cx0d0f2102 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2102);
-+ data->f2x9cx0d0f2202 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2202);
-+ data->f2x9cx0d0f8002 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8002);
-+ data->f2x9cx0d0f8006 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8006);
-+ data->f2x9cx0d0f800a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f800a);
-+ data->f2x9cx0d0f8102 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8102);
-+ data->f2x9cx0d0f8106 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8106);
-+ data->f2x9cx0d0f810a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f810a);
-+ data->f2x9cx0d0fc002 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc002);
-+ data->f2x9cx0d0fc006 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc006);
-+ data->f2x9cx0d0fc00a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc00a);
-+ data->f2x9cx0d0fc00e = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc00e);
-+ data->f2x9cx0d0fc012 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc012);
-+
-+ data->f2x9cx0d0f2031 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2031);
-+ data->f2x9cx0d0f2131 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2131);
-+ data->f2x9cx0d0f2231 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2231);
-+ data->f2x9cx0d0f8031 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8031);
-+ data->f2x9cx0d0f8131 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8131);
-+ data->f2x9cx0d0f8231 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8231);
-+ data->f2x9cx0d0fc031 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc031);
-+ data->f2x9cx0d0fc131 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc131);
-+ data->f2x9cx0d0fc231 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc231);
-+ for (i=0; i<9; i++)
-+ data->f2x9cx0d0f0_0_f_31[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0031 | (i << 8));
-+
-+ data->f2x9cx0d0f8021 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8021);
-+ }
-
- /* Stage 4 */
-- data->f2x94 = pci_read_config32(dev_fn2, 0x94 + (0x100 * channel));
-+ data->f2x94 = read_config32_dct(dev_fn2, node, channel, 0x94);
-
- /* Stage 6 */
- for (i=0; i<9; i++)
- for (j=0; j<3; j++)
-- data->f2x9cx0d0f0_f_8_0_0_8_4_0[i][j] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0f0000 | (i << 8) | (j * 4));
-- data->f2x9cx00 = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x00);
-- data->f2x9cx0a = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0a);
-- data->f2x9cx0c = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0c);
-+ data->f2x9cx0d0f0_f_8_0_0_8_4_0[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4));
-+ data->f2x9cx00 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x00);
-+ data->f2x9cx0a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0a);
-+ data->f2x9cx0c = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0c);
-
- /* Stage 7 */
-- data->f2x9cx04 = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x04);
-+ data->f2x9cx04 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x04);
-
- /* Stage 9 */
-- data->f2x9cx0d0fe006 = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0fe006);
-- data->f2x9cx0d0fe007 = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0fe007);
-+ data->f2x9cx0d0fe006 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe006);
-+ data->f2x9cx0d0fe007 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe007);
-
- /* Stage 10 */
- for (i=0; i<12; i++)
-- data->f2x9cx10[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x10 + i);
-+ data->f2x9cx10[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x10 + i);
- for (i=0; i<12; i++)
-- data->f2x9cx20[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x20 + i);
-+ data->f2x9cx20[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x20 + i);
- for (i=0; i<4; i++)
- for (j=0; j<3; j++)
-- data->f2x9cx3_0_0_3_1[i][j] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), (0x01 + i) + (0x100 * j));
-+ data->f2x9cx3_0_0_3_1[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, (0x01 + i) + (0x100 * j));
- for (i=0; i<4; i++)
- for (j=0; j<3; j++)
-- data->f2x9cx3_0_0_7_5[i][j] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), (0x05 + i) + (0x100 * j));
-- data->f2x9cx0d = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d);
-+ data->f2x9cx3_0_0_7_5[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, (0x05 + i) + (0x100 * j));
-+ data->f2x9cx0d = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d);
- for (i=0; i<9; i++)
-- data->f2x9cx0d0f0_f_0_13[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0f0013 | (i << 8));
-+ data->f2x9cx0d0f0_f_0_13[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0013 | (i << 8));
- for (i=0; i<9; i++)
-- data->f2x9cx0d0f0_f_0_30[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0f0030 | (i << 8));
-+ data->f2x9cx0d0f0_f_0_30[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0030 | (i << 8));
- for (i=0; i<4; i++)
-- data->f2x9cx0d0f2_f_0_30[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0f2030 | (i << 8));
-+ data->f2x9cx0d0f2_f_0_30[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2030 | (i << 8));
- for (i=0; i<2; i++)
- for (j=0; j<3; j++)
-- data->f2x9cx0d0f8_8_4_0[i][j] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0f0000 | (i << 8) | (j * 4));
-- data->f2x9cx0d0f812f = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x0d0f812f);
-+ data->f2x9cx0d0f8_8_4_0[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4));
-+ data->f2x9cx0d0f812f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f812f);
-
- /* Stage 11 */
- if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
- for (i=0; i<12; i++)
-- data->f2x9cx30[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x30 + i);
-+ data->f2x9cx30[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x30 + i);
- for (i=0; i<12; i++)
-- data->f2x9cx40[i] = read_amd_dct_index_register(dev_fn2, 0x98 + (0x100 * channel), 0x40 + i);
-+ data->f2x9cx40[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x40 + i);
- }
-
- /* Other */
-@@ -212,6 +364,43 @@ void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_da
- }
- }
- #else
-+static void write_config32_dct(device_t dev, uint8_t node, uint8_t dct, uint32_t reg, uint32_t value) {
-+ if (is_fam15h()) {
-+ uint32_t dword;
-+ device_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1);
-+
-+ /* Select DCT */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+ } else {
-+ /* Apply offset */
-+ reg += dct * 0x100;
-+ }
-+
-+ pci_write_config32(dev, reg, value);
-+}
-+
-+static void write_config32_dct_nbpstate(device_t dev, uint8_t node, uint8_t dct, uint8_t nb_pstate, uint32_t reg, uint32_t value) {
-+ uint32_t dword;
-+ device_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1);
-+
-+ /* Select DCT */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+
-+ /* Select NB Pstate index */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~(0x3 << 4);
-+ dword |= (nb_pstate & 0x3) << 4;
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+
-+ pci_write_config32(dev, reg, value);
-+}
-+
- static void write_amd_dct_index_register(device_t dev, uint32_t index_ctl_reg, uint32_t index, uint32_t value)
- {
- uint32_t dword;
-@@ -223,6 +412,25 @@ static void write_amd_dct_index_register(device_t dev, uint32_t index_ctl_reg, u
- dword = pci_read_config32(dev, index_ctl_reg);
- } while (!(dword & (1 << 31)));
- }
-+
-+static void write_amd_dct_index_register_dct(device_t dev, uint8_t node, uint8_t dct, uint32_t index_ctl_reg, uint32_t index, uint32_t value)
-+{
-+ if (is_fam15h()) {
-+ uint32_t dword;
-+ device_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1);
-+
-+ /* Select DCT */
-+ dword = pci_read_config32(dev_fn1, 0x10c);
-+ dword &= ~0x1;
-+ dword |= (dct & 0x1);
-+ pci_write_config32(dev_fn1, 0x10c, dword);
-+ } else {
-+ /* Apply offset */
-+ index_ctl_reg += dct * 0x100;
-+ }
-+
-+ return write_amd_dct_index_register(dev, index_ctl_reg, index, value);
-+}
- #endif
-
- #ifdef __PRE_RAM__
-@@ -262,31 +470,31 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- if (!persistent_data->node[node].node_present)
- continue;
-
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x40 + (0x100 * channel), data->f1x40);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x44 + (0x100 * channel), data->f1x44);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x48 + (0x100 * channel), data->f1x48);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x4c + (0x100 * channel), data->f1x4c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x50 + (0x100 * channel), data->f1x50);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x54 + (0x100 * channel), data->f1x54);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x58 + (0x100 * channel), data->f1x58);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x5c + (0x100 * channel), data->f1x5c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x60 + (0x100 * channel), data->f1x60);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x64 + (0x100 * channel), data->f1x64);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x68 + (0x100 * channel), data->f1x68);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x6c + (0x100 * channel), data->f1x6c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x70 + (0x100 * channel), data->f1x70);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x74 + (0x100 * channel), data->f1x74);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x78 + (0x100 * channel), data->f1x78);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x7c + (0x100 * channel), data->f1x7c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0xf0 + (0x100 * channel), data->f1xf0);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x120 + (0x100 * channel), data->f1x120);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 1), 0x124 + (0x100 * channel), data->f1x124);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x10c + (0x100 * channel), data->f2x10c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x114 + (0x100 * channel), data->f2x114);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x118 + (0x100 * channel), data->f2x118);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x11c + (0x100 * channel), data->f2x11c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x1b0 + (0x100 * channel), data->f2x1b0);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 3), 0x44 + (0x100 * channel), data->f3x44);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x40, data->f1x40);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x44, data->f1x44);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x48, data->f1x48);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x4c, data->f1x4c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x50, data->f1x50);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x54, data->f1x54);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x58, data->f1x58);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x5c, data->f1x5c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x60, data->f1x60);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x64, data->f1x64);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x68, data->f1x68);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x6c, data->f1x6c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x70, data->f1x70);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x74, data->f1x74);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x78, data->f1x78);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x7c, data->f1x7c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0xf0, data->f1xf0);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x120, data->f1x120);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x124, data->f1x124);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x10c, data->f2x10c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x114, data->f2x114);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x118, data->f2x118);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x11c, data->f2x11c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x1b0, data->f2x1b0);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, channel, 0x44, data->f3x44);
- for (i=0; i<16; i++) {
- wrmsr_uint64_t(0x00000200 | i, data->msr0000020[i]);
- }
-@@ -313,31 +521,97 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- if (!persistent_data->node[node].node_present)
- continue;
-
-- ganged = !!(data->f2x110 & 0x10);
-+ if (is_fam15h())
-+ ganged = 0;
-+ else
-+ ganged = !!(data->f2x110 & 0x10);
- if ((ganged == 1) && (channel > 0))
- continue;
-
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x40 + (0x100 * channel), data->f2x40);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x44 + (0x100 * channel), data->f2x44);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x48 + (0x100 * channel), data->f2x48);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x4c + (0x100 * channel), data->f2x4c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x50 + (0x100 * channel), data->f2x50);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x54 + (0x100 * channel), data->f2x54);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x58 + (0x100 * channel), data->f2x58);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x5c + (0x100 * channel), data->f2x5c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x60 + (0x100 * channel), data->f2x60);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x64 + (0x100 * channel), data->f2x64);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x68 + (0x100 * channel), data->f2x68);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x6c + (0x100 * channel), data->f2x6c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x78 + (0x100 * channel), data->f2x78);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x7c + (0x100 * channel), data->f2x7c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x80 + (0x100 * channel), data->f2x80);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x84 + (0x100 * channel), data->f2x84);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x88 + (0x100 * channel), data->f2x88);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x8c + (0x100 * channel), data->f2x8c);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x90 + (0x100 * channel), data->f2x90);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0xa4 + (0x100 * channel), data->f2xa4);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0xa8 + (0x100 * channel), data->f2xa8);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x40, data->f2x40);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x44, data->f2x44);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x48, data->f2x48);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x4c, data->f2x4c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x50, data->f2x50);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x54, data->f2x54);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x58, data->f2x58);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x5c, data->f2x5c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x60, data->f2x60);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x64, data->f2x64);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x68, data->f2x68);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x6c, data->f2x6c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x78, data->f2x78);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x7c, data->f2x7c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x80, data->f2x80);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x84, data->f2x84);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x88, data->f2x88);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x8c, data->f2x8c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90, data->f2x90);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0xa4, data->f2xa4);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0xa8, data->f2xa8);
-+ }
-+ }
-+
-+ /* Family 15h-specific configuration */
-+ if (is_fam15h()) {
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
-+ for (channel = 0; channel < 2; channel++) {
-+ struct amd_s3_persistent_mct_channel_data* data = &persistent_data->node[node].channel[channel];
-+ if (!persistent_data->node[node].node_present)
-+ continue;
-+
-+ /* Initialize DCT */
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0000000b, 0x80000000);
-+ dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe013);
-+ dword &= ~0xffff;
-+ dword |= 0x118;
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe013, dword);
-+
-+ /* Restore values */
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x200, data->f2x200);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x204, data->f2x204);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x208, data->f2x208);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x20c, data->f2x20c);
-+ for (i=0; i<4; i++)
-+ write_config32_dct_nbpstate(PCI_DEV(0, 0x18 + node, 2), node, channel, i, 0x210, data->f2x210[i]);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x214, data->f2x214);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x218, data->f2x218);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x21c, data->f2x21c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x22c, data->f2x22c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x230, data->f2x230);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x234, data->f2x234);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x238, data->f2x238);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x23c, data->f2x23c);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x240, data->f2x240);
-+
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe013, data->f2x9cx0d0fe013);
-+ for (i=0; i<9; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f001f | (i << 8), data->f2x9cx0d0f0_8_0_1f[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f201f, data->f2x9cx0d0f201f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f211f, data->f2x9cx0d0f211f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f221f, data->f2x9cx0d0f221f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f801f, data->f2x9cx0d0f801f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f811f, data->f2x9cx0d0f811f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f821f, data->f2x9cx0d0f821f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc01f, data->f2x9cx0d0fc01f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc11f, data->f2x9cx0d0fc11f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc21f, data->f2x9cx0d0fc21f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f4009, data->f2x9cx0d0f4009);
-+
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2031, data->f2x9cx0d0f2031);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2131, data->f2x9cx0d0f2131);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2231, data->f2x9cx0d0f2231);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8031, data->f2x9cx0d0f8031);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8131, data->f2x9cx0d0f8131);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8231, data->f2x9cx0d0f8231);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc031, data->f2x9cx0d0fc031);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc131, data->f2x9cx0d0fc131);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc231, data->f2x9cx0d0fc231);
-+ for (i=0; i<9; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0031 | (i << 8), data->f2x9cx0d0f0_0_f_31[i]);
-+
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8021, data->f2x9cx0d0f8021);
-+ }
- }
- }
-
-@@ -348,33 +622,44 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- if (!persistent_data->node[node].node_present)
- continue;
-
-- ganged = !!(data->f2x110 & 0x10);
-+ if (is_fam15h())
-+ ganged = 0;
-+ else
-+ ganged = !!(data->f2x110 & 0x10);
- if ((ganged == 1) && (channel > 0))
- continue;
-
-- /* Disable PHY auto-compensation engine */
-- dword = read_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x08);
-- if (!(dword & (1 << 30))) {
-- dword |= (1 << 30);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x08, dword);
--
-- /* Wait for 5us */
-- mct_Wait(100);
-+ if (is_fam15h()) {
-+ /* Program PllLockTime = 0x190 */
-+ dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006);
-+ dword &= ~0xffff;
-+ dword |= 0x190;
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006, dword);
-+
-+ /* Program MemClkFreqVal = 0 */
-+ dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94);
-+ dword &= (0x1 << 7);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94, dword);
-+
-+ /* Restore DRAM Adddress/Timing Control Register */
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x04, data->f2x9cx04);
-+ } else {
-+ /* Disable PHY auto-compensation engine */
-+ dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08);
-+ if (!(dword & (1 << 30))) {
-+ dword |= (1 << 30);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08, dword);
-+
-+ /* Wait for 5us */
-+ mct_Wait(100);
-+ }
- }
-
- /* Restore DRAM Configuration High Register */
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x94 + (0x100 * channel), data->f2x94);
--
-- /* Enable PHY auto-compensation engine */
-- dword = read_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x08);
-- dword &= ~(1 << 30);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x08, dword);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94, data->f2x94);
- }
- }
-
-- /* Wait for 750us */
-- mct_Wait(15000);
--
- /* Stage 5 */
- for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
- for (channel = 0; channel < 2; channel++) {
-@@ -382,17 +667,40 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- if (!persistent_data->node[node].node_present)
- continue;
-
-- ganged = !!(data->f2x110 & 0x10);
-+ if (is_fam15h())
-+ ganged = 0;
-+ else
-+ ganged = !!(data->f2x110 & 0x10);
- if ((ganged == 1) && (channel > 0))
- continue;
-
-+ dct_enabled = !(data->f2x94 & (1 << 14));
-+ if (!dct_enabled)
-+ continue;
-+
- /* Wait for any pending PHY frequency changes to complete */
- do {
-- dword = read_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x08);
-+ dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94);
- } while (dword & (1 << 21));
-+
-+ if (is_fam15h()) {
-+ /* Program PllLockTime = 0xf */
-+ dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006);
-+ dword &= ~0xffff;
-+ dword |= 0xf;
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006, dword);
-+ } else {
-+ /* Enable PHY auto-compensation engine */
-+ dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08);
-+ dword &= ~(1 << 30);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08, dword);
-+ }
- }
- }
-
-+ /* Wait for 750us */
-+ mct_Wait(15000);
-+
- /* Stage 6 */
- for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
- for (channel = 0; channel < 2; channel++) {
-@@ -402,10 +710,49 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
-
- for (i=0; i<9; i++)
- for (j=0; j<3; j++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0f0000 | (i << 8) | (j * 4), data->f2x9cx0d0f0_f_8_0_0_8_4_0[i][j]);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x00, data->f2x9cx00);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0a, data->f2x9cx0a);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0c, data->f2x9cx0c);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4), data->f2x9cx0d0f0_f_8_0_0_8_4_0[i][j]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x00, data->f2x9cx00);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0a, data->f2x9cx0a);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0c, data->f2x9cx0c);
-+ }
-+ }
-+
-+ /* Family 15h-specific configuration */
-+ if (is_fam15h()) {
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
-+ for (channel = 0; channel < 2; channel++) {
-+ struct amd_s3_persistent_mct_channel_data* data = &persistent_data->node[node].channel[channel];
-+ if (!persistent_data->node[node].node_present)
-+ continue;
-+
-+ dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe003);
-+ dword |= (0x3 << 13); /* DisAutoComp, DisablePredriverCal = 1 */
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe003, dword);
-+
-+ for (i=0; i<9; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0006 | (i << 8), data->f2x9cx0d0f0_8_0_06[i]);
-+ for (i=0; i<9; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f000a | (i << 8), data->f2x9cx0d0f0_8_0_0a[i]);
-+ for (i=0; i<9; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0002 | (i << 8), (0x8000 | data->f2x9cx0d0f0_8_0_02[i]));
-+
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8006, data->f2x9cx0d0f8006);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f800a, data->f2x9cx0d0f800a);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8106, data->f2x9cx0d0f8106);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f810a, data->f2x9cx0d0f810a);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc006, data->f2x9cx0d0fc006);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc00a, data->f2x9cx0d0fc00a);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc00e, data->f2x9cx0d0fc00e);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc012, data->f2x9cx0d0fc012);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8002, (0x8000 | data->f2x9cx0d0f8002));
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8102, (0x8000 | data->f2x9cx0d0f8102));
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc002, (0x8000 | data->f2x9cx0d0fc002));
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2002, (0x8000 | data->f2x9cx0d0f2002));
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2102, (0x8000 | data->f2x9cx0d0f2102));
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2202, (0x8000 | data->f2x9cx0d0f2202));
-+
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe003, data->f2x9cx0d0fe003);
-+ }
- }
- }
-
-@@ -416,11 +763,15 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- if (!persistent_data->node[node].node_present)
- continue;
-
-- ganged = !!(data->f2x110 & 0x10);
-+ if (is_fam15h())
-+ ganged = 0;
-+ else
-+ ganged = !!(data->f2x110 & 0x10);
- if ((ganged == 1) && (channel > 0))
- continue;
-
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x04, data->f2x9cx04);
-+ if (!is_fam15h())
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x04, data->f2x9cx04);
- }
- }
-
-@@ -435,16 +786,19 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- if (!dct_enabled)
- continue;
-
-- ganged = !!(data->f2x110 & 0x10);
-+ if (is_fam15h())
-+ ganged = 0;
-+ else
-+ ganged = !!(data->f2x110 & 0x10);
- if ((ganged == 1) && (channel > 0))
- continue;
-
- printk(BIOS_SPEW, "Taking DIMMs out of self refresh node: %d channel: %d\n", node, channel);
-
- /* Exit self refresh mode */
-- dword = pci_read_config32(PCI_DEV(0, 0x18 + node, 2), 0x90 + (0x100 * channel));
-+ dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90);
- dword |= (1 << 1);
-- pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x90 + (0x100 * channel), dword);
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90, dword);
- }
- }
-
-@@ -463,12 +817,12 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
-
- /* Wait for transition from self refresh mode to complete */
- do {
-- dword = pci_read_config32(PCI_DEV(0, 0x18 + node, 2), 0x90 + (0x100 * channel));
-+ dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90);
- } while (dword & (1 << 1));
-
- /* Restore registers */
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0fe006, data->f2x9cx0d0fe006);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0fe007, data->f2x9cx0d0fe007);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006, data->f2x9cx0d0fe006);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe007, data->f2x9cx0d0fe007);
- }
- }
-
-@@ -480,26 +834,26 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- continue;
-
- for (i=0; i<12; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x10 + i, data->f2x9cx10[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x10 + i, data->f2x9cx10[i]);
- for (i=0; i<12; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x20 + i, data->f2x9cx20[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x20 + i, data->f2x9cx20[i]);
- for (i=0; i<4; i++)
- for (j=0; j<3; j++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), (0x01 + i) + (0x100 * j), data->f2x9cx3_0_0_3_1[i][j]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x01 + i) + (0x100 * j), data->f2x9cx3_0_0_3_1[i][j]);
- for (i=0; i<4; i++)
- for (j=0; j<3; j++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), (0x05 + i) + (0x100 * j), data->f2x9cx3_0_0_7_5[i][j]);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d, data->f2x9cx0d);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x05 + i) + (0x100 * j), data->f2x9cx3_0_0_7_5[i][j]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d, data->f2x9cx0d);
- for (i=0; i<9; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0f0013 | (i << 8), data->f2x9cx0d0f0_f_0_13[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0013 | (i << 8), data->f2x9cx0d0f0_f_0_13[i]);
- for (i=0; i<9; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0f0030 | (i << 8), data->f2x9cx0d0f0_f_0_30[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0030 | (i << 8), data->f2x9cx0d0f0_f_0_30[i]);
- for (i=0; i<4; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0f2030 | (i << 8), data->f2x9cx0d0f2_f_0_30[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2030 | (i << 8), data->f2x9cx0d0f2_f_0_30[i]);
- for (i=0; i<2; i++)
- for (j=0; j<3; j++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0f0000 | (i << 8) | (j * 4), data->f2x9cx0d0f8_8_4_0[i][j]);
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x0d0f812f, data->f2x9cx0d0f812f);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4), data->f2x9cx0d0f8_8_4_0[i][j]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f812f, data->f2x9cx0d0f812f);
- }
- }
-
-@@ -512,9 +866,9 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- continue;
-
- for (i=0; i<12; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x30 + i, data->f2x9cx30[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x30 + i, data->f2x9cx30[i]);
- for (i=0; i<12; i++)
-- write_amd_dct_index_register(PCI_DEV(0, 0x18 + node, 2), 0x98 + (0x100 * channel), 0x40 + i, data->f2x9cx40[i]);
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x40 + i, data->f2x9cx40[i]);
- }
- }
- }
-diff --git a/src/northbridge/amd/amdmct/wrappers/mcti.h b/src/northbridge/amd/amdmct/wrappers/mcti.h
-index 38e66e1..2aba377 100644
---- a/src/northbridge/amd/amdmct/wrappers/mcti.h
-+++ b/src/northbridge/amd/amdmct/wrappers/mcti.h
-@@ -2,6 +2,7 @@
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -62,10 +63,15 @@ UPDATE AS NEEDED
- #endif
-
- #ifndef MEM_MAX_LOAD_FREQ
--#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
-- #define MEM_MAX_LOAD_FREQ 800
--#else
-- #define MEM_MAX_LOAD_FREQ 400
-+#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
-+ #define MEM_MAX_LOAD_FREQ 933
-+ #define MEM_MIN_PLATFORM_FREQ_FAM10 400
-+ #define MEM_MIN_PLATFORM_FREQ_FAM15 333
-+#else /* AMD_FAM10_DDR2 */
-+ #define MEM_MAX_LOAD_FREQ 400
-+ #define MEM_MIN_PLATFORM_FREQ_FAM10 200
-+ /* DDR2 not available on Family 15h */
-+ #define MEM_MIN_PLATFORM_FREQ_FAM15 0
- #endif
- #endif
-
-diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-index 444adc5..9969c4f 100644
---- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-+++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-@@ -44,7 +44,7 @@
- #define MINIMUM_DRAM_BELOW_4G 0x1000000
-
- static const uint16_t ddr2_limits[4] = {400, 333, 266, 200};
--static const uint16_t ddr3_limits[4] = {800, 666, 533, 400};
-+static const uint16_t ddr3_limits[16] = {933, 800, 666, 533, 400, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- static u16 mctGet_NVbits(u8 index)
- {
-@@ -81,12 +81,19 @@ static u16 mctGet_NVbits(u8 index)
- if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS) {
- int limit = val;
- if (IS_ENABLED(CONFIG_DIMM_DDR3))
-- limit = ddr3_limits[nvram & 3];
-+ limit = ddr3_limits[nvram & 0xf];
- else if (IS_ENABLED(CONFIG_DIMM_DDR2))
-- limit = ddr2_limits[nvram & 3];
-+ limit = ddr2_limits[nvram & 0x3];
- val = min(limit, val);
- }
- break;
-+ case NV_MIN_MEMCLK:
-+ /* Minimum platform supported memclk */
-+ if (is_fam15h())
-+ val = MEM_MIN_PLATFORM_FREQ_FAM15;
-+ else
-+ val = MEM_MIN_PLATFORM_FREQ_FAM10;
-+ break;
- case NV_ECC_CAP:
- #if SYSTEM_TYPE == SERVER
- val = 1; /* memory bus ECC capable */
-@@ -254,6 +261,9 @@ static u16 mctGet_NVbits(u8 index)
- case NV_L2BKScrub:
- val = 0; /* Disabled - See L2Scrub in BKDG */
- break;
-+ case NV_L3BKScrub:
-+ val = 0; /* Disabled - See L3Scrub in BKDG */
-+ break;
- case NV_DCBKScrub:
- val = 0; /* Disabled - See DcacheScrub in BKDG */
- break;
-@@ -303,6 +313,9 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
- int ch2_count = 0;
- uint8_t ch1_registered = 0;
- uint8_t ch2_registered = 0;
-+ uint8_t ch1_voltage = 0;
-+ uint8_t ch2_voltage = 0;
-+ uint8_t highest_rank_count[2];
- int i;
- for (i = 0; i < 15; i = i + 2) {
- if (pDCTstat->DIMMValid & (1 << i))
-@@ -321,8 +334,28 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
- printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) detected\n", ch2_count);
- }
-
-+#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
-+ uint8_t dimm;
-+
-+ for (i = 0; i < 15; i = i + 2) {
-+ if (pDCTstat->DIMMValid & (1 << i))
-+ ch1_voltage |= pDCTstat->DimmConfiguredVoltage[i];
-+ if (pDCTstat->DIMMValid & (1 << (i + 1)))
-+ ch2_voltage |= pDCTstat->DimmConfiguredVoltage[i + 1];
-+ }
-+
-+ for (i = 0; i < 2; i++) {
-+ sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[i];
-+ highest_rank_count[i] = 0x0;
-+ for (dimm = 0; dimm < 8; dimm++) {
-+ if (pDCTData->DimmRanks[dimm] > highest_rank_count[i])
-+ highest_rank_count[i] = pDCTData->DimmRanks[dimm];
-+ }
-+ }
-+#endif
-+
- /* Set limits if needed */
-- pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), (ch1_registered || ch2_registered), pDCTstat->PresetmaxFreq);
-+ pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), max(highest_rank_count[0], highest_rank_count[1]), (ch1_registered || ch2_registered), (ch1_voltage | ch2_voltage), pDCTstat->PresetmaxFreq);
- }
-
- #ifdef UNUSED_CODE
-@@ -486,7 +519,7 @@ static void mctHookAfterAnyTraining(void)
- {
- }
-
--static u32 mctGetLogicalCPUID_D(u8 node)
-+static uint64_t mctGetLogicalCPUID_D(u8 node)
- {
- return mctGetLogicalCPUID(node);
- }
---
-1.7.9.5
-