diff options
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0033-cpu-amd-Add-initial-AMD-Family-15h-support.patch')
-rw-r--r-- | resources/libreboot/patch/kgpe-d16/0033-cpu-amd-Add-initial-AMD-Family-15h-support.patch | 16206 |
1 files changed, 0 insertions, 16206 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0033-cpu-amd-Add-initial-AMD-Family-15h-support.patch b/resources/libreboot/patch/kgpe-d16/0033-cpu-amd-Add-initial-AMD-Family-15h-support.patch deleted file mode 100644 index 75aa195..0000000 --- a/resources/libreboot/patch/kgpe-d16/0033-cpu-amd-Add-initial-AMD-Family-15h-support.patch +++ /dev/null @@ -1,16206 +0,0 @@ -From db769f9a54ca4b8a1872c031f29aae31f412e2a2 Mon Sep 17 00:00:00 2001 -From: Timothy Pearson <tpearson@raptorengineeringinc.com> -Date: Fri, 16 Oct 2015 13:51:51 -0500 -Subject: [PATCH 033/139] 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 | 77 +- - src/cpu/amd/family_10h-family_15h/defaults.h | 266 +- - src/cpu/amd/family_10h-family_15h/fidvid.c | 235 +- - 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/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/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 | 42 +- - 70 files changed, 9184 insertions(+), 2064 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..5cab544 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,78 @@ 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(); -+ } -+ -+ /* INVDWBINVD = 1 */ -+ msr = rdmsr(0xc0010015); -+ msr.lo |= (0x1 << 4); -+ wrmsr(0xc0010015, msr); -+ -+ family = amd_fam1x_cpu_family(); -+ -+ if (family >= 0x6f) { -+ /* Family 15h or later */ - -- msr = rdmsr(SYSCFG_MSR); -- msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn); -- wrmsr(SYSCFG_MSR, msr); -+ /* DisSS = 0 */ -+ msr = rdmsr(0xc0011020); -+ msr.lo &= ~(0x1 << 28); -+ wrmsr(0xc0011020, msr); - -- /* Set the default memory type and disable fixed and enable variable MTRRs */ -- msr.hi = 0; -- msr.lo = (1 << 11); -+ if (!skip_sharedc_config) { -+ /* DisSpecTlbRld = 0 */ -+ msr = rdmsr(0xc0011021); -+ msr.lo &= ~(0x1 << 9); -+ wrmsr(0xc0011021, msr); - -- wrmsr(MTRR_DEF_TYPE_MSR, msr); -+ /* Erratum 714: SpecNbReqDis = 0 */ -+ msr = rdmsr(BU_CFG2_MSR); -+ msr.lo &= ~(0x1 << 8); -+ wrmsr(BU_CFG2_MSR, msr); -+ } - -- enable_cache(); -+ /* DisSpecTlbRld = 0 */ -+ /* DisHwPf = 0 */ -+ msr = rdmsr(0xc0011022); -+ msr.lo &= ~(0x1 << 4); -+ msr.lo &= ~(0x1 << 13); -+ wrmsr(0xc0011022, msr); -+ } - } - - 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 99ffcc8..2e26645 100644 ---- a/src/cpu/amd/family_10h-family_15h/fidvid.c -+++ b/src/cpu/amd/family_10h-family_15h/fidvid.c -@@ -44,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) - -@@ -143,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){ -@@ -203,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) -@@ -283,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 -@@ -515,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) -@@ -584,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); -@@ -612,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; -@@ -645,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); -@@ -655,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); -@@ -662,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) - { -@@ -757,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) -@@ -785,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) { -@@ -799,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. */ - -@@ -819,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 -@@ -861,7 +896,7 @@ 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) == 1) { -+ if (((readback & 0x3f) == 1) || ((readback & 0x3f) == F10_APSTATE_ASLEEP)) { - timeout = 0; - break; /* target ap is in stage 1 */ - } -@@ -949,7 +984,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; -@@ -970,15 +1008,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); -+ } - } - - -@@ -1012,8 +1052,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/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/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..a4045bd 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 adcfdf0..baf77d6 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 9f42d54..7ea7901 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[currDimm], 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[currDimm], rank); -+ tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - } - } else { -- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], 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[currDimm]); -+ -+ /* 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[currDimm], rank); -+ } -+ } else { -+ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], 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; - - /* 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 47260f2..1d4eade 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; -@@ -299,10 +309,14 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat) - pDCTstat->PresetmaxFreq = mctGet_NVbits(NV_MAX_MEMCLK); - - /* Determine the number of installed DIMMs */ -+ uint8_t dimm; - int ch1_count = 0; - 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 +335,26 @@ 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 */ -+ 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]; -+ } -+#endif -+ -+ 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]; -+ } -+ } -+ - /* 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 +518,7 @@ static void mctHookAfterAnyTraining(void) - { - } - --static u32 mctGetLogicalCPUID_D(u8 node) -+static uint64_t mctGetLogicalCPUID_D(u8 node) - { - return mctGetLogicalCPUID(node); - } --- -1.9.1 - |