diff options
author | Arthur Heymans <arthur@aheymans.xyz> | 2019-11-19 15:46:49 +0100 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2019-11-20 19:08:30 +0000 |
commit | ffcac3eb502bbe0acbb30d6fe804f00e07461a7a (patch) | |
tree | d5deda572bb252a683a5ece24a5c4916ee198836 /src/northbridge/amd/amdmct/mct_ddr3 | |
parent | 1ca978ee6529251ed80b47da679be7adc75fa46a (diff) |
nb/amd/fam10: Drop support
Relocatable ramstage, postcar stage and C_ENVIRONMENT_BOOTBLOCK are
now mandatory features, which this platform lacks.
Change-Id: If36ef0749dbb661f731fb04829bd7e2202ebb422
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36962
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3')
33 files changed, 0 insertions, 23187 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/Makefile.inc b/src/northbridge/amd/amdmct/mct_ddr3/Makefile.inc deleted file mode 100644 index 65c146a662..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/Makefile.inc +++ /dev/null @@ -1,31 +0,0 @@ -ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y) - -# DDR3 -romstage-$(CONFIG_HAVE_ACPI_RESUME) += s3utils.c -romstage-y += mct_d.c mctmtr_d.c mctcsi_d.c mctecc_d.c mctdqs_d.c mctsrc.c -romstage-y += mctsdi.c mctprod.c mctproc.c mctprob.c mcthwl.c mctwl.c -romstage-y += mport_d.c mutilc_d.c modtrdim.c mhwlc_d.c mctrci.c mctsrc1p.c -romstage-y += mcttmrl.c mcthdi.c mctndi_d.c mctchi_d.c modtrd.c mct_d_gcc.c - -ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x11) -romstage-y += mctardk5.c -endif -ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x13) -romstage-y += mctardk5.c -endif -ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x14) -romstage-y += mctardk5.c -endif -ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x15) -romstage-y += mctardk5.c -endif -ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x16) -romstage-y += mctardk5.c -endif -ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x12) -romstage-y += mctardk6.c -endif - -ramstage-$(CONFIG_HAVE_ACPI_RESUME) += s3utils.c - -endif diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c deleted file mode 100644 index fa8c71447b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ /dev/null @@ -1,8220 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015-2017 Raptor Engineering, LLC - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -/* Description: Main memory controller system configuration for DDR 3 */ - -/* KNOWN ISSUES - ERRATA - * - * Trtp is not calculated correctly when the controller is in 64-bit mode, it - * is 1 busclock off. No fix planned. The controller is not ordinarily in - * 64-bit mode. - * - * 32 Byte burst not supported. No fix planned. The controller is not - * ordinarily in 64-bit mode. - * - * Trc precision does not use extra Jedec defined fractional component. - * InsteadTrc (course) is rounded up to nearest 1 ns. - * - * Mini and Micro DIMM not supported. Only RDIMM, UDIMM, SO-DIMM defined types - * supported. - */ - -#include <console/console.h> -#include <northbridge/amd/amdfam10/debug.h> -#include <northbridge/amd/amdfam10/raminit.h> -#include <northbridge/amd/amdfam10/amdfam10.h> -#include <southbridge/amd/common/reset.h> -#include <cpu/x86/msr.h> -#include <cpu/amd/msr.h> -#include <cpu/x86/mtrr.h> -#include <device/pci_ops.h> -#include <arch/acpi.h> -#include <string.h> -#include <types.h> -#include <device/dram/ddr3.h> - -#include "s3utils.h" -#include "mct_d_gcc.h" -#include "mct_d.h" - -static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void DQSTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, - uint8_t allow_config_restore); -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void ClearDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -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, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat); -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,\ - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_TrwtWB(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - 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, 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, - u32 dev, u32 index_reg, u32 index); -static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_init(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void SetCSTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -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 u32 mct_NodePresent_D(void); -static void mct_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -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, 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, - struct DCTStatStruc *pDCTstat); -void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -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); -void ChangeMemClk(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); - -static u8 Get_Latency_Diff(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SyncSetting(struct DCTStatStruc *pDCTstat); -static uint8_t crcCheck(struct DCTStatStruc *pDCTstat, uint8_t dimm); - -uint8_t is_ecc_enabled(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); - -/*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}; -const u8 Table_DQSRcvEn_Offset[] = {0x00,0x01,0x10,0x11,0x2}; - -/**************************************************************************** - Describe how platform maps MemClk pins to logical DIMMs. The MemClk pins - are identified based on BKDG definition of Fn2x88[MemClkDis] bitmap. - AGESA will base on this value to disable unused MemClk to save power. - - If MEMCLK_MAPPING or MEMCLK_MAPPING contains all zeroes, AGESA will use - default MemClkDis setting based on package type. - - Example: - BKDG definition of Fn2x88[MemClkDis] bitmap for AM3 package is like below: - Bit AM3/S1g3 pin name - 0 M[B,A]_CLK_H/L[0] - 1 M[B,A]_CLK_H/L[1] - 2 M[B,A]_CLK_H/L[2] - 3 M[B,A]_CLK_H/L[3] - 4 M[B,A]_CLK_H/L[4] - 5 M[B,A]_CLK_H/L[5] - 6 M[B,A]_CLK_H/L[6] - 7 M[B,A]_CLK_H/L[7] - - And platform has the following routing: - CS0 M[B,A]_CLK_H/L[4] - CS1 M[B,A]_CLK_H/L[2] - CS2 M[B,A]_CLK_H/L[3] - CS3 M[B,A]_CLK_H/L[5] - - Then: - ; CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7 - MEMCLK_MAPPING EQU 00010000b, 00000100b, 00001000b, 00100000b, 00000000b, 00000000b, 00000000b, 00000000b -*/ - -/* ========================================================================================== - * Set up clock pin to DIMM mappings, - * NOTE: If you are not sure about the pin mappings, you can keep all MemClk signals active, - * just set all entries in the relevant table(s) to 0xff. - * ========================================================================================== - */ -static const u8 Tab_L1CLKDis[] = {0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04}; -static const u8 Tab_AM3CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; -static const u8 Tab_S1CLKDis[] = {0xA2, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -/* C32: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */ -static const u8 Tab_C32CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -/* G34: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */ -static const u8 Tab_G34CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -/* FM2: Enable all the clocks for the dimms */ -static const u8 Tab_FM2CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -static const u8 Tab_ManualCLKDis[]= {0x10, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00}; -/* ========================================================================================== */ - -static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF}; -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}; - -uint8_t dct_ddr_voltage_index(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t dimm; - uint8_t ddr_voltage_index = 0; - - /* If no DIMMs are present on this DCT, report 1.5V operation and skip checking the hardware */ - if (pDCTstat->DIMMValidDCT[dct] == 0) - return 0x1; - - /* 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) { - freq = iter; - break; - } - } - 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) { - freq = iter; - break; - } - } - if (freq == 0) - freq = 0x3; - - return freq; -} - -static inline uint8_t is_model10_1f(void) -{ - uint8_t model101f = 0; - uint32_t family; - - family = cpuid_eax(0x80000001); - family = ((family & 0x0ff000) >> 12); - - if (family >= 0x10 && family <= 0x1f) - /* Model 0x10 to 0x1f */ - model101f = 1; - - return model101f; -} - -uint8_t is_ecc_enabled(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - uint8_t ecc_enabled = 1; - - if (!pMCTstat->try_ecc) - ecc_enabled = 0; - - if (pDCTstat->NodePresent && (pDCTstat->DIMMValidDCT[0] || pDCTstat->DIMMValidDCT[1])) - if (!(pDCTstat->Status & (1 << SB_ECCDIMMs))) - ecc_enabled = 0; - - return !!ecc_enabled; -} - -uint8_t get_available_lane_count(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - if (is_ecc_enabled(pMCTstat, pDCTstat)) - return 9; - else - return 8; -} - -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; -} - -uint32_t fam10h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - 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) & 0x7) + 1; - - /* 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 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam10h BKDG Rev. 3.62 section 2.8.9.5.8 Tables 60 - 61 */ - if (MaxDimmsInstallable == 1) { - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x003a3c3a; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x00383a38; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* UDIMM */ - /* Fam10h BKDG Rev. 3.62 section 2.8.9.5.8 Table 56 */ - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00380000; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00360000; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x00350037; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x00000035; - } - } - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return calibration_code; -} - -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 if (package_type == PT_FM2) { - /* Socket FM2 */ - if (ddr_voltage_index & 0x1) { - /* 1.5V */ - /* Fam15h BKDG Rev. 3.12 section 2.9.5.4.4 Table 22 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0xb24; - } else if (MemClkFreq >= 0xa) { - /* DDR3-1066 or higher */ - calibration_code = 0xff6; - } - } - } - } 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; -} - -uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - 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 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 74 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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; - } - - if (rank_count_dimm0 == 4) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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; - } - - if ((rank_count_dimm0 == 4) || (rank_count_dimm1 == 4)) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 */ - calibration_code = 0x30222222; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* 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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 77 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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; - } - - if (rank_count_dimm0 == 4) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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; - } - - if ((rank_count_dimm0 == 4) || (rank_count_dimm1 == 4)) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 */ - calibration_code = 0x30222222; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* 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 (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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 if (package_type == PT_FM2) { - /* Socket FM2 */ - /* Assume UDIMM */ - /* Fam15h Model10h BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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) { - /* DDR3-1333 or higher */ - calibration_code = 0x30112222; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 or DDR3-800 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x20112222; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - calibration_code = 0x30112222; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x10222322; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x20222322; - } else if (MemClkFreq >= 0xa) { - /* DDR3-1066 or higher */ - calibration_code = 0x30222322; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return calibration_code; -} - -uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - 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 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 74 */ - if (MaxDimmsInstallable == 1) { - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - calibration_code = 0x00393939; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00393c39; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00373a37; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00363936; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003a3c3a; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00383a38; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00353935; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 76 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 77 */ - if (MaxDimmsInstallable == 1) { - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - calibration_code = 0x00393939; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00393c39; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00373a37; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00363936; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003a3c3a; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00383a38; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00353935; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 76 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 if (package_type == PT_FM2) { - /* Socket FM2 */ - /* Assume UDIMM */ - /* Fam15h Model10h BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */ - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 or DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00380000; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00360000; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - calibration_code = 0x00000000; - } - - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 or DDR3-800 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00350037; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00000035; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x0000002b; - } else if (MemClkFreq > 0x12) { - /* DDR3-1866 or greater */ - calibration_code = 0x00000031; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return calibration_code; -} - -uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - 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 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 74 */ - slow_access = 0; - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 75 */ - slow_access = 0; - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 77 */ - slow_access = 0; - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 78 */ - slow_access = 0; - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 76 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(1 * 2) + dct]; - - 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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - 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 if (package_type == PT_FM2) { - /* Socket FM2 */ - /* UDIMM */ - /* Fam15h Model10 BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - 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->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa)) { - /* DDR3-667 - DDR3-1066 */ - slow_access = 0; - } else if (MemClkFreq >= 0xe) { - /* DDR3-1333 or higher */ - slow_access = 1; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return slow_access; -} - -static uint8_t fam15h_odt_tristate_enable_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint8_t odt_tristate_code = 0; - - package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* 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 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 104 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 >= 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 >= 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 105 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 103 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 107 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 >= 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 >= 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 108 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 106 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* UDIMM */ - odt_tristate_code = 0x0; - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return odt_tristate_code; -} - -static uint8_t fam15h_cs_tristate_enable_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint8_t cs_tristate_code = 0; - - package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* 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 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 104 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 < 4) - cs_tristate_code = 0xfc; - else - cs_tristate_code = 0xcc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 < 4) - cs_tristate_code = 0xf3; - else - cs_tristate_code = 0x33; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xf0; - else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) - cs_tristate_code = 0x30; - else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xc0; - else - cs_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 105 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 103 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfe; - else - cs_tristate_code = 0xfc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfb; - else - cs_tristate_code = 0xf3; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xfa; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - cs_tristate_code = 0xf2; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xf8; - else - cs_tristate_code = 0xf0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 107 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 < 4) - cs_tristate_code = 0xfc; - else - cs_tristate_code = 0xcc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 < 4) - cs_tristate_code = 0xf3; - else - cs_tristate_code = 0x33; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xf0; - else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) - cs_tristate_code = 0x30; - else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xc0; - else - cs_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 108 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 106 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfe; - else - cs_tristate_code = 0xfc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfb; - else - cs_tristate_code = 0xf3; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xfa; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - cs_tristate_code = 0xf2; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xf8; - else - cs_tristate_code = 0xf0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* UDIMM */ - cs_tristate_code = 0x0; - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return cs_tristate_code; -} - -void set_2t_configuration(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - 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); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -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(TSC_MSR); - start_timestamp = (((uint64_t)tsc_msr.hi) << 32) | tsc_msr.lo; - do { - tsc_msr = rdmsr(TSC_MSR); - current_timestamp = (((uint64_t)tsc_msr.hi) << 32) | tsc_msr.lo; - } while ((current_timestamp - start_timestamp) < cycle_count); -} - -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; - - if (fam15h_freq_tab[memclk_freq] == 0) { - printk(BIOS_DEBUG, "ERROR: precise_memclk_delay_fam15 for DCT %d (delay %d clocks) failed to obtain valid memory frequency!" - " (pDCTstat: %p pDCTstat->dev_dct: %08x memclk_freq: %02x)\n", dct, clocks, pDCTstat, pDCTstat->dev_dct, memclk_freq); - } - delay_ns = (((uint64_t)clocks * 1000) / fam15h_freq_tab[memclk_freq]); - precise_ndelay_fam15(pMCTstat, delay_ns); -} - -static void read_spd_bytes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dimm) -{ - uint8_t addr; - uint16_t byte; - - addr = Get_DIMMAddress_D(pDCTstat, dimm); - pDCTstat->spd_data.spd_address[dimm] = addr; - - for (byte = 0; byte < 256; byte++) { - pDCTstat->spd_data.spd_bytes[dimm][byte] = mctRead_SPD(addr, byte); - } -} - -#ifdef DEBUG_DIMM_SPD -static void dump_spd_bytes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dimm) -{ - uint16_t byte; - - printk(BIOS_DEBUG, "SPD dump for DIMM %d\n ", dimm); - for (byte = 0; byte < 16; byte++) { - printk(BIOS_DEBUG, "%02x ", byte); - } - for (byte = 0; byte < 256; byte++) { - if ((byte & 0xf) == 0x0) { - printk(BIOS_DEBUG, "\n%02x ", byte >> 4); - } - printk(BIOS_DEBUG, "%02x ", pDCTstat->spd_data.spd_bytes[dimm][byte]); - } - printk(BIOS_DEBUG, "\n"); -} -#endif - -static void set_up_cc6_storage_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t num_nodes) -{ - uint8_t interleaved; - uint8_t destination_node; - int8_t range; - int8_t max_range; - uint8_t max_node; - uint64_t max_range_limit; - uint8_t byte; - uint32_t dword; - uint32_t dword2; - uint64_t qword; - - interleaved = 0; - if (pMCTstat->GStatus & (1 << GSB_NodeIntlv)) - interleaved = 1; - - printk(BIOS_INFO, - "%s: Initializing CC6 DRAM storage area for node %d" - " (interleaved: %d)\n", - __func__, pDCTstat->Node_ID, interleaved); - - /* Find highest DRAM range (DramLimitAddr) */ - max_node = 0; - max_range = -1; - max_range_limit = 0; - for (range = 0; range < 8; range++) { - dword = Get_NB32(pDCTstat->dev_map, 0x40 + (range * 0x8)); - if (!(dword & 0x3)) - continue; - - dword = Get_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8)); - dword2 = Get_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8)); - qword = 0xffffff; - qword |= ((((uint64_t)dword) >> 16) & 0xffff) << 24; - qword |= (((uint64_t)dword2) & 0xff) << 40; - - if (qword > max_range_limit) { - max_range = range; - max_range_limit = qword; - max_node = dword & 0x7; - } - } - - if (max_range >= 0) { - printk(BIOS_INFO, - "%s:\toriginal (node %d) max_range_limit: %16llx DRAM" - " limit: %16llx\n", - __func__, max_node, max_range_limit, - (((uint64_t)(Get_NB32(pDCTstat->dev_map, 0x124) - & 0x1fffff)) << 27) | 0x7ffffff); - - if (interleaved) - /* Move upper limit down by 16M * the number of nodes */ - max_range_limit -= (0x1000000ULL * num_nodes); - else - /* Move upper limit down by 16M */ - max_range_limit -= 0x1000000ULL; - - printk(BIOS_INFO, "%s:\tnew max_range_limit: %16llx\n", - __func__, max_range_limit); - - /* Disable the range */ - dword = Get_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8)); - byte = dword & 0x3; - dword &= ~(0x3); - Set_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8), dword); - - /* Store modified range */ - dword = Get_NB32(pDCTstat->dev_map, 0x44 + (max_range * 0x8)); - dword &= ~(0xffff << 16); /* DramLimit[39:24] = max_range_limit[39:24] */ - dword |= ((max_range_limit >> 24) & 0xffff) << 16; - Set_NB32(pDCTstat->dev_map, 0x44 + (max_range * 0x8), dword); - - dword = Get_NB32(pDCTstat->dev_map, 0x144 + (max_range * 0x8)); - dword &= ~0xff; /* DramLimit[47:40] = max_range_limit[47:40] */ - dword |= (max_range_limit >> 40) & 0xff; - Set_NB32(pDCTstat->dev_map, 0x144 + (max_range * 0x8), dword); - - /* Reenable the range */ - dword = Get_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8)); - dword |= byte; - Set_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8), dword); - } - - /* Determine save state destination node */ - if (interleaved) - destination_node = Get_NB32(pDCTstat->dev_host, 0x60) & 0x7; - else - destination_node = max_node; - - /* Set save state destination node */ - dword = Get_NB32(pDCTstat->dev_link, 0x128); - dword &= ~(0x3f << 12); /* CoreSaveStateDestNode = destination_node */ - dword |= (destination_node & 0x3f) << 12; - Set_NB32(pDCTstat->dev_link, 0x128, dword); - - printk(BIOS_INFO, "%s:\tTarget node: %d\n", __func__, destination_node); - - printk(BIOS_INFO, "%s:\tDone\n", __func__); -} - -static void lock_dram_config(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint32_t dword; - - dword = Get_NB32(pDCTstat->dev_dct, 0x118); - dword |= 0x1 << 19; /* LockDramCfg = 1 */ - Set_NB32(pDCTstat->dev_dct, 0x118, dword); -} - -static void set_cc6_save_enable(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t enable) -{ - uint32_t dword; - - dword = Get_NB32(pDCTstat->dev_dct, 0x118); - dword &= ~(0x1 << 18); /* CC6SaveEn = enable */ - dword |= (enable & 0x1) << 18; - Set_NB32(pDCTstat->dev_dct, 0x118, dword); -} - -void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* - * Memory may be mapped contiguously all the way up to 4GB (depending on setup - * options). It is the responsibility of PCI subsystem to create an uncacheable - * IO region below 4GB and to adjust TOP_MEM downward prior to any IO mapping or - * accesses. It is the same responsibility of the CPU sub-system prior to - * accessing LAPIC. - * - * Slot Number is an external convention, and is determined by OEM with accompanying - * silk screening. OEM may choose to use Slot number convention which is consistent - * with DIMM number conventions. All AMD engineering platforms do. - * - * Build Requirements: - * 1. MCT_SEG0_START and MCT_SEG0_END macros to begin and end the code segment, - * defined in mcti.inc. - * - * Run-Time Requirements: - * 1. Complete Hypertransport Bus Configuration - * 2. SMBus Controller Initialized - * 1. BSP in Big Real Mode - * 2. Stack at SS:SP, located somewhere between A000:0000 and F000:FFFF - * 3. Checksummed or Valid NVRAM bits - * 4. MCG_CTL = -1, MC4_CTL_EN = 0 for all CPUs - * 5. MCi_STS from shutdown/warm reset recorded (if desired) prior to entry - * 6. All var MTRRs reset to zero - * 7. State of NB_CFG.DisDatMsk set properly on all CPUs - * 8. All CPUs at 2GHz Speed (unless DQS training is not installed). - * 9. All cHT links at max Speed/Width (unless DQS training is not installed). - * - * - * Global relationship between index values and item values: - * - * pDCTstat.CASL pDCTstat.Speed - * j CL(j) k F(k) - * -------------------------- - * 0 2.0 - - - * 1 3.0 1 200 MHz - * 2 4.0 2 266 MHz - * 3 5.0 3 333 MHz - * 4 6.0 4 400 MHz - * 5 7.0 5 533 MHz - * 6 8.0 6 667 MHz - * 7 9.0 7 800 MHz - */ - u8 Node, NodesWmem; - u32 node_sys_base; - uint8_t dimm; - uint8_t nvram; - uint8_t enable_cc6; - uint8_t ecc_enabled; - uint8_t allow_config_restore; - - uint8_t s3resume = acpi_is_wakeup_s3(); - -restartinit: - - if (!mctGet_NVbits(NV_ECC_CAP) || !mctGet_NVbits(NV_ECC)) - pMCTstat->try_ecc = 0; - else - pMCTstat->try_ecc = 1; - - 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 CONFIG(HAVE_ACPI_RESUME) - printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DCT configuration from NVRAM\n"); - if (restore_mct_information_from_nvram(0) != 0) - printk(BIOS_CRIT, "%s: ERROR: Unable to restore DCT configuration from NVRAM\n", __func__); - pMCTstat->GStatus |= 1 << GSB_ConfigRestored; -#endif - - if (is_fam15h()) { - 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; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - /* Zero out data structures to avoid false detection of DIMMs */ - memset(pDCTstat, 0, sizeof(struct DCTStatStruc)); - - /* Initialize data structures */ - pDCTstat->Node_ID = Node; - pDCTstat->dev_host = PA_HOST(Node); - 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; - - if (mctGet_NVbits(NV_PACK_TYPE) == PT_GR) { - uint32_t dword; - pDCTstat->Dual_Node_Package = 1; - - /* Get the internal node number */ - dword = Get_NB32(pDCTstat->dev_nbmisc, 0xe8); - dword = (dword >> 30) & 0x3; - pDCTstat->Internal_Node_ID = dword; - } else { - pDCTstat->Dual_Node_Package = 0; - } - - printk(BIOS_DEBUG, "%s: mct_init Node %d\n", __func__, Node); - mct_init(pMCTstat, pDCTstat); - mctNodeIDDebugPort_D(); - pDCTstat->NodePresent = NodePresent_D(Node); - if (pDCTstat->NodePresent) { - pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node); - - printk(BIOS_DEBUG, "%s: mct_InitialMCT_D\n", __func__); - mct_InitialMCT_D(pMCTstat, pDCTstat); - - printk(BIOS_DEBUG, "%s: mctSMBhub_Init\n", __func__); - mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node */ - - printk(BIOS_DEBUG, "%s: mct_preInitDCT\n", __func__); - mct_preInitDCT(pMCTstat, pDCTstat); - } - node_sys_base = pDCTstat->NodeSysBase; - node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F; - } - - /* If the boot fails make sure training is attempted after reset */ - nvram = 0; - set_option("allow_spd_nvram_cache_restore", &nvram); - -#if CONFIG(DIMM_VOLTAGE_SET_SUPPORT) - printk(BIOS_DEBUG, "%s: DIMMSetVoltage\n", __func__); - DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */ -#endif - if (!CONFIG(DIMM_VOLTAGE_SET_SUPPORT)) { - /* Assume 1.5V operation */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (!pDCTstat->NodePresent) - continue; - - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - if (pDCTstat->DIMMValid & (1 << dimm)) - pDCTstat->DimmConfiguredVoltage[dimm] = 0x1; - } - } - } - - /* If DIMM configuration has not changed since last boot restore training values */ - allow_config_restore = 1; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - if (!pDCTstat->spd_data.nvram_spd_match) - allow_config_restore = 0; - } - - /* FIXME - * Stability issues have arisen on multiple Family 15h systems - * when configuration restoration is enabled. In all cases these - * stability issues resolved by allowing the RAM to go through a - * full training cycle. - * - * Debug and reenable this! - */ - allow_config_restore = 0; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - printk(BIOS_DEBUG, "%s: mctSMBhub_Init\n", __func__); - mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/ - - printk(BIOS_DEBUG, "%s: mct_initDCT\n", __func__); - mct_initDCT(pMCTstat, pDCTstat); - if (pDCTstat->ErrCode == SC_FatalErr) { - goto fatalexit; /* any fatal errors?*/ - } else if (pDCTstat->ErrCode < SC_StopError) { - NodesWmem++; - } - } - } - if (NodesWmem == 0) { - printk(BIOS_ALERT, "Unable to detect valid memory on any nodes. Halting!\n"); - goto fatalexit; - } - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n"); - SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: HTMemMapInit_D\n"); - HTMemMapInit_D(pMCTstat, pDCTstatA); /* Map local memory into system address space.*/ - mctHookAfterHTMap(); - - if (!is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: CPUMemTyping_D\n"); - CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */ - } - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: mctHookAfterCPU\n"); - mctHookAfterCPU(); /* Setup external northbridge(s) */ - - /* FIXME - * Previous training values should only be used if the current desired - * speed is the same as the speed used in the previous boot. - * How to get the desired speed at this point in the code? - */ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: DQSTiming_D\n"); - DQSTiming_D(pMCTstat, pDCTstatA, allow_config_restore); /* Get Receiver Enable and DQS signal timing*/ - - if (!is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n"); - UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */ - } - - if (!allow_config_restore) { - 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; - } - - InterleaveNodes_D(pMCTstat, pDCTstatA); - InterleaveChannels_D(pMCTstat, pDCTstatA); - - ecc_enabled = 1; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - if (!is_ecc_enabled(pMCTstat, pDCTstat)) - ecc_enabled = 0; - } - - if (ecc_enabled) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n"); - if (!ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/ - /* Memory was not cleared during ECC setup */ - /* mctDoWarmResetMemClr_D(); */ - printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n"); - MCTMemClr_D(pMCTstat,pDCTstatA); - } - } - - if (is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: CPUMemTyping_D\n"); - CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n"); - UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */ - - 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); - } - } - - if (is_fam15h()) { - enable_cc6 = 0; - if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) - enable_cc6 = !!nvram; - - if (enable_cc6) { - uint8_t num_nodes; - - num_nodes = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - num_nodes++; - } - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - set_up_cc6_storage_fam15(pMCTstat, pDCTstat, num_nodes); - } - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - set_cc6_save_enable(pMCTstat, pDCTstat, 1); - lock_dram_config(pMCTstat, pDCTstat); - } - } - } - } - - mct_FinalMCT_D(pMCTstat, pDCTstatA); - printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", pMCTstat->GStatus); - } - - return; - -fatalexit: - die("mct_d: fatalexit"); -} - -void initialize_mca(uint8_t bsp, uint8_t suppress_errors) { - uint8_t node; - uint32_t mc4_status_high; - uint32_t mc4_status_low; - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - if (bsp && (node > 0)) - break; - - mc4_status_high = pci_read_config32(PCI_DEV(0, 0x18 + node, 3), 0x4c); - mc4_status_low = pci_read_config32(PCI_DEV(0, 0x18 + node, 3), 0x48); - if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) { - if (!suppress_errors) - printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected on node %d!\n" - "Signature: %08x%08x\n", node, mc4_status_high, mc4_status_low); - - /* Clear MC4 error status */ - pci_write_config32(PCI_DEV(0, 0x18 + node, 3), 0x48, 0x0); - pci_write_config32(PCI_DEV(0, 0x18 + node, 3), 0x4c, 0x0); - } - } -} - -static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 ret; - - if (mctGet_NVbits(NV_CS_SpareCTL)) { - if (MCT_DIMM_SPARE_NO_WARM) { - /* Do no warm-reset DIMM spare */ - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA); - ret = 0; - } else { - mct_ResetDataStruct_D(pMCTstat, pDCTstatA); - pMCTstat->GStatus |= 1 << GSB_EnDIMMSpareNW; - ret = 1; - } - } else { - /* Do warm-reset DIMM spare */ - if (mctGet_NVbits(NV_DQSTrainCTL)) - mctWarmReset_D(); - ret = 0; - } - } else { - ret = 0; - } - - 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) - */ -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; - int16_t max_cdd_we_delta; - int16_t cdd_trwtto_we_delta; - uint8_t receiver; - uint8_t lane_count; - uint8_t x4_present = 0; - uint8_t x8_present = 0; - uint8_t memclk_index; - uint8_t interleave_channels = 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 cdd_twrrd; - uint16_t cdd_trwtto; - uint16_t trwtto; - uint8_t first_dimm; - uint16_t delay; - uint16_t delay2; - uint8_t min_value; - uint8_t write_early; - uint8_t read_odt_delay; - uint8_t write_odt_delay; - uint8_t buffer_data_delay; - int16_t latency_difference; - uint16_t difference; - uint16_t current_total_delay_1[MAX_BYTE_LANES]; - uint16_t current_total_delay_2[MAX_BYTE_LANES]; - uint8_t ddr_voltage_index; - uint8_t max_dimms_installable; - - /* FIXME - * This should be platform configurable - */ - uint8_t dimm_event_l_pin_support = 0; - - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - max_dimms_installable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - 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; - - 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; - - dword = (Get_NB32_DCT(dev, dct, 0xa8) >> 24) & 0x3; - write_early = dword / 2; - - latency_difference = Get_NB32_DCT(dev, dct, 0x200) & 0x1f; - dword = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f; - latency_difference -= dword; - - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.5 - */ - } else { - buffer_data_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 < lane_count; 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 + (1 << 6) - 1) >> 6) & 0xf); - - /* 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 < lane_count; 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 + (1 << 6) - 1) >> 6) & 0xf); - - /* 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 */ - - /* Configure power saving options */ - dword = Get_NB32_DCT(dev, dct, 0xa8); /* Dram Miscellaneous 2 */ - dword |= (0x1 << 22); /* PrtlChPDEnhEn = 0x1 */ - dword |= (0x1 << 21); /* AggrPDEn = 0x1 */ - Set_NB32_DCT(dev, dct, 0xa8, dword); /* Dram Miscellaneous 2 */ - - /* Configure partial power down delay */ - dword = Get_NB32(dev, 0x244); /* DRAM Controller Miscellaneous 3 */ - dword &= ~0xf; /* PrtlChPDDynDly = 0x2 */ - dword |= 0x2; - Set_NB32(dev, 0x244, dword); /* DRAM Controller Miscellaneous 3 */ - - /* Configure power save delays */ - delay = 0xa; - delay2 = 0x3; - - /* Family 15h BKDG Table 214 */ - if ((pDCTstat->Status & (1 << SB_Registered)) - || (pDCTstat->Status & (1 << SB_LoadReduced))) { - if (memclk_index <= 0x6) { - if (ddr_voltage_index < 0x4) - /* 1.5 or 1.35V */ - delay2 = 0x3; - else - /* 1.25V */ - delay2 = 0x4; - } - else if ((memclk_index == 0xa) - || (memclk_index == 0xe)) - delay2 = 0x4; - else if (memclk_index == 0x12) - delay2 = 0x5; - else if (memclk_index == 0x16) - delay2 = 0x6; - } else { - if (memclk_index <= 0x6) - delay2 = 0x3; - else if ((memclk_index == 0xa) - || (memclk_index == 0xe)) - delay2 = 0x4; - else if (memclk_index == 0x12) - delay2 = 0x5; - else if (memclk_index == 0x16) - delay2 = 0x6; - } - - /* Family 15h BKDG Table 215 */ - if (memclk_index <= 0x6) - delay = 0xa; - else if (memclk_index == 0xa) - delay = 0xd; - else if (memclk_index == 0xe) - delay = 0x10; - else if (memclk_index == 0x12) - delay = 0x14; - else if (memclk_index == 0x16) - delay = 0x17; - - dword = Get_NB32_DCT(dev, dct, 0x248); /* Dram Power Management 0 */ - dword &= ~(0x3f << 24); /* AggrPDDelay = 0x0 */ - dword &= ~(0x3f << 16); /* PchgPDEnDelay = 0x1 */ - dword |= (0x1 << 16); - dword &= ~(0x1f << 8); /* Txpdll = delay */ - dword |= ((delay & 0x1f) << 8); - dword &= ~0xf; /* Txp = delay2 */ - dword |= delay2 & 0xf; - Set_NB32_DCT(dev, dct, 0x248, dword); /* Dram Power Management 0 */ - - /* Family 15h BKDG Table 216 */ - if (memclk_index <= 0x6) { - delay = 0x5; - delay2 = 0x3; - } else if (memclk_index == 0xa) { - delay = 0x6; - delay2 = 0x3; - } else if (memclk_index == 0xe) { - delay = 0x7; - delay2 = 0x4; - } else if (memclk_index == 0x12) { - delay = 0x8; - delay2 = 0x4; - } else if (memclk_index == 0x16) { - delay = 0xa; - delay2 = 0x5; - } - - dword = Get_NB32_DCT(dev, dct, 0x24c); /* Dram Power Management 1 */ - dword &= ~(0x3f << 24); /* Tcksrx = delay */ - dword |= ((delay & 0x3f) << 24); - dword &= ~(0x3f << 16); /* Tcksre = delay */ - dword |= ((delay & 0x3f) << 16); - dword &= ~(0x3f << 8); /* Tckesr = delay2 + 1 */ - dword |= (((delay2 + 1) & 0x3f) << 8); - dword &= ~0xf; /* Tpd = delay2 */ - dword |= delay2 & 0xf; - Set_NB32_DCT(dev, dct, 0x24c, dword); /* Dram Power Management 1 */ - - 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); - } - } - - /* Calculate the Critical Delay Difference for Twrrd */ - cdd_twrrd = 0; - 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_1, dev, dct, dimm, index_reg); - read_dqs_receiver_enable_control_registers(current_total_delay_2, dev, dct, dimm, index_reg); - - for (lane = 0; lane < lane_count; 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_twrrd) - cdd_twrrd = difference; - } - } - - /* Convert the difference to MEMCLKs */ - cdd_twrrd = (((cdd_twrrd + (1 << 6) - 1) >> 6) & 0xf); - - /* Fam15h BKDG section 2.10.5.5.3 */ - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.5 - */ - twrrd = 0xb; - } else { - max_cdd_we_delta = (((int16_t)cdd_twrrd + 1 - ((int16_t)write_early * 2)) + 1) / 2; - if (max_cdd_we_delta < 0) - max_cdd_we_delta = 0; - if (((uint16_t)max_cdd_we_delta) > write_odt_delay) - dword = max_cdd_we_delta; - else - dword = write_odt_delay; - dword += 3; - if (latency_difference < dword) { - dword -= latency_difference; - if (dword < 1) - twrrd = 1; - else - twrrd = dword; - } else { - twrrd = 1; - } - } - - /* Calculate the Critical Delay Difference for TrwtTO */ - cdd_trwtto = 0; - 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_1, dev, dct, dimm, index_reg); - read_dqs_write_timing_control_registers(current_total_delay_2, dev, dct, dimm, index_reg); - - for (lane = 0; lane < lane_count; 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_trwtto) - cdd_trwtto = difference; - } - } - - /* Convert the difference to MEMCLKs */ - cdd_trwtto = (((cdd_trwtto + (1 << 6) - 1) >> 6) & 0xf); - - /* Fam15h BKDG section 2.10.5.5.4 */ - if (max_dimms_installable == 1) - min_value = 0; - else - min_value = read_odt_delay + buffer_data_delay; - cdd_trwtto_we_delta = (((int16_t)cdd_trwtto - 1 + ((int16_t)write_early * 2)) + 1) / 2; - cdd_trwtto_we_delta += latency_difference + 3; - if (cdd_trwtto_we_delta < 0) - cdd_trwtto_we_delta = 0; - if ((cdd_trwtto_we_delta) > min_value) - trwtto = cdd_trwtto_we_delta; - else - trwtto = min_value; - - 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; - dword |= (0x3 << 6); /* DctSelIntLvAddr = 0x3 */ - Set_NB32_DCT(dev, dct, 0x110, dword); /* DRAM Controller Select Low */ - - /* NOTE - * ECC-related setup is performed as part of ECCInit_D and must not be located here, - * otherwise semi-random lockups will occur due to misconfigured scrubbing hardware! - */ - - /* 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 << 24); /* TrdrdSdSc = 0x1 */ - dword |= (0x1 << 24); - dword &= ~(0xf << 16); /* TrdrdSdDc = trdrdsddc */ - dword |= ((trdrdsddc & 0xf) << 16); - dword &= ~(0xf << 8); /* Twrrd = twrrd */ - dword |= ((twrrd & 0xf) << 8); - dword &= ~(0xf); /* TrdrdDd = trdrddd */ - dword |= (trdrddd & 0xf); - 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(dev, 0x11c); /* Memory Controller Configuration High */ - dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ - dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */ - Set_NB32(dev, 0x11c, 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, uint8_t allow_config_restore) -{ - uint8_t Node; - u8 nv_DQSTrainCTL; - uint8_t retry_requested; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - return; - } - - /* Set initial TCWL offset to zero */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - uint8_t dct; - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - for (dct = 0; dct < 2; dct++) - pDCTstat->tcwl_delay[dct] = 0; - } - -retry_dqs_training_and_levelization: - nv_DQSTrainCTL = !allow_config_restore; - - mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA); - phyAssistedMemFnceTraining(pMCTstat, pDCTstatA, -1); - - if (is_fam15h()) { - 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); - } - } - } - - mctHookBeforeAnyTraining(pMCTstat, pDCTstatA); - if (!is_fam15h()) { - /* TODO: should be in mctHookBeforeAnyTraining */ - _WRMSR(MTRR_FIX_4K_E0000, 0x04040404, 0x04040404); - _WRMSR(MTRR_FIX_4K_E8000, 0x04040404, 0x04040404); - _WRMSR(MTRR_FIX_4K_F0000, 0x04040404, 0x04040404); - _WRMSR(MTRR_FIX_4K_F8000, 0x04040404, 0x04040404); - } - - if (nv_DQSTrainCTL) { - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass); - - if (is_fam15h()) { - /* Receiver Enable Training Pass 1 */ - TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); - } - - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, SecondPass); - - if (is_fam15h()) { - - /* 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); - } - - mct_TrainDQSPos_D(pMCTstat, pDCTstatA); - - /* Determine if DQS training requested a retrain attempt */ - retry_requested = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - if (pDCTstat->TrainErrors & (1 << SB_FatalError)) { - printk(BIOS_ERR, "DIMM training FAILED! Restarting system..."); - soft_reset(); - } - if (pDCTstat->TrainErrors & (1 << SB_RetryConfigTrain)) { - retry_requested = 1; - - /* Clear previous errors */ - pDCTstat->TrainErrors &= ~(1 << SB_RetryConfigTrain); - pDCTstat->TrainErrors &= ~(1 << SB_NODQSPOS); - pDCTstat->ErrStatus &= ~(1 << SB_RetryConfigTrain); - pDCTstat->ErrStatus &= ~(1 << SB_NODQSPOS); - } - } - } - - /* Retry training and levelization if requested */ - if (retry_requested) { - printk(BIOS_DEBUG, "%s: Restarting training on algorithm request\n", __func__); - /* Reset frequency to minimum */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - uint8_t original_target_freq = pDCTstat->TargetFreq; - uint8_t original_auto_speed = pDCTstat->DIMMAutoSpeed; - pDCTstat->TargetFreq = mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK)); - pDCTstat->Speed = pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq; - SetTargetFreq(pMCTstat, pDCTstatA, Node); - pDCTstat->TargetFreq = original_target_freq; - pDCTstat->DIMMAutoSpeed = original_auto_speed; - } - } - /* Apply any DIMM timing changes */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - AutoCycTiming_D(pMCTstat, pDCTstat, 0); - if (!pDCTstat->GangedMode) - if (pDCTstat->DIMMValidDCT[1] > 0) - AutoCycTiming_D(pMCTstat, pDCTstat, 1); - } - } - goto retry_dqs_training_and_levelization; - } - - TrainMaxRdLatency_En_D(pMCTstat, pDCTstatA); - - if (is_fam15h()) - exit_training_mode_fam15(pMCTstat, pDCTstatA); - else - mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA); - } else { - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass); - - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, SecondPass); - -#if CONFIG(HAVE_ACPI_RESUME) - printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DIMM training configuration from NVRAM\n"); - if (restore_mct_information_from_nvram(1) != 0) - printk(BIOS_CRIT, "%s: ERROR: Unable to restore DCT configuration from NVRAM\n", __func__); -#endif - - if (is_fam15h()) - exit_training_mode_fam15(pMCTstat, pDCTstatA); - - pMCTstat->GStatus |= 1 << GSB_ConfigRestored; - } - - if (is_fam15h()) { - struct DCTStatStruc *pDCTstat; - - /* Switch DCT control register to DCT 0 per Erratum 505 */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - fam15h_switch_dct(pDCTstat->dev_map, 0); - } - } - } - - /* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */ - mctHookAfterAnyTraining(); -} - -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node, Receiver, Channel, Dir, DIMM; - u32 dev; - u32 index_reg; - u32 reg; - u32 index; - u32 val; - u8 ByteLane; - u8 txdqs; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - for (Channel = 0;Channel < 2; Channel++) { - /* there are four receiver pairs, - loosely associated with chipselects.*/ - index_reg = 0x98; - for (Receiver = 0; Receiver < 8; Receiver += 2) { - /* Set Receiver Enable Values */ - mct_SetRcvrEnDly_D(pDCTstat, - 0, /* RcvrEnDly */ - 1, /* FinalValue, From stack */ - Channel, - Receiver, - dev, index_reg, - (Receiver >> 1) * 3 + 0x10, /* Addl_Index */ - 2); /* Pass Second Pass ? */ - /* Restore Write levelization training data */ - for (ByteLane = 0; ByteLane < 9; ByteLane ++) { - txdqs = pDCTstat->persistentData.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_DCT(dev, Channel, 0x98, index); - if (ByteLane & 1) { /* odd byte lane */ - val &= ~(0xFF << 16); - val |= txdqs << 16; - } else { - val &= ~0xFF; - val |= txdqs; - } - Set_NB32_index_wait_DCT(dev, Channel, 0x98, index, val); - } - } - } - for (Channel = 0; Channel < 2; Channel++) { - SetEccDQSRcvrEn_D(pDCTstat, Channel); - } - - for (Channel = 0; Channel < 2; Channel++) { - u8 *p; - index_reg = 0x98; - - /* NOTE: - * when 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above - * + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above - * + 0x100 to next dimm - */ - for (DIMM = 0; DIMM < 4; DIMM++) { - if (DIMM == 0) { - index = 0; /* CHA Write Data Timing Low */ - } else { - if (pDCTstat->Speed >= mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - index = 0x100 * DIMM; - } else { - break; - } - } - 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_DCT(dev, Channel, index_reg, index+1, val); - val = stream_to_int(p+4); /* CHA Write Data Timing High */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+2, val); - val = *(p+8); /* CHA Write ECC Timing */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+3, val); - index += 4; - } - } - } - - for (Channel = 0; Channel < 2; Channel++) { - reg = 0x78; - val = Get_NB32_DCT(dev, Channel, reg); - val &= ~(0x3ff<<22); - val |= ((u32) pDCTstat->CH_MaxRdLat[Channel][0] << 22); - val &= ~(1<<DqsRcvEnTrain); - Set_NB32_DCT(dev, Channel, reg, val); /* program MaxRdLatency to correspond with current delay*/ - } - } - } -} - -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u32 NextBase, BottomIO; - u8 _MemHoleRemap, DramHoleBase; - u32 HoleSize, DramSelBaseAddr; - - u32 val; - u32 base; - u32 limit; - u32 dev, devx; - struct DCTStatStruc *pDCTstat; - - _MemHoleRemap = mctGet_NVbits(NV_MemHole); - - if (pMCTstat->HoleBase == 0) { - DramHoleBase = mctGet_NVbits(NV_BottomIO); - } else { - DramHoleBase = pMCTstat->HoleBase >> (24-8); - } - - BottomIO = DramHoleBase << (24-8); - - NextBase = 0; - pDCTstat = pDCTstatA + 0; - dev = pDCTstat->dev_map; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - DramSelBaseAddr = 0; - if (!pDCTstat->GangedMode) { - DramSelBaseAddr = pDCTstat->NodeSysLimit - pDCTstat->DCTSysLimit; - /*In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */ - val = pDCTstat->NodeSysLimit; - if ((val & 0xFF) == 0xFE) { - DramSelBaseAddr++; - val++; - } - pDCTstat->DCTSysLimit = val; - } - - base = pDCTstat->DCTSysBase; - limit = pDCTstat->DCTSysLimit; - if (limit > base) { - base += NextBase; - limit += NextBase; - DramSelBaseAddr += NextBase; - printk(BIOS_DEBUG, " Node: %02x base: %02x limit: %02x BottomIO: %02x\n", Node, base, limit, BottomIO); - - if (_MemHoleRemap) { - if ((base < BottomIO) && (limit >= BottomIO)) { - /* HW Dram Remap */ - pDCTstat->Status |= 1 << SB_HWHole; - pMCTstat->GStatus |= 1 << GSB_HWHole; - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - pDCTstat->DCTHoleBase = BottomIO; - pMCTstat->HoleBase = BottomIO; - HoleSize = _4GB_RJ8 - BottomIO; /* HoleSize[39:8] */ - if ((DramSelBaseAddr > 0) && (DramSelBaseAddr < BottomIO)) - base = DramSelBaseAddr; - val = ((base + HoleSize) >> (24-8)) & 0xFF; - val <<= 8; /* shl 16, rol 24 */ - val |= DramHoleBase << 24; - val |= 1 << DramHoleValid; - Set_NB32(devx, 0xF0, val); /* Dram Hole Address Reg */ - pDCTstat->DCTSysLimit += HoleSize; - base = pDCTstat->DCTSysBase; - limit = pDCTstat->DCTSysLimit; - } else if (base == BottomIO) { - /* SW Node Hoist */ - pMCTstat->GStatus |= 1<<GSB_SpIntRemapHole; - pDCTstat->Status |= 1<<SB_SWNodeHole; - pMCTstat->GStatus |= 1<<GSB_SoftHole; - pMCTstat->HoleBase = base; - limit -= base; - base = _4GB_RJ8; - limit += base; - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } else { - /* No Remapping. Normal Contiguous mapping */ - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } - } else { - /*No Remapping. Normal Contiguous mapping*/ - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } - base |= 3; /* set WE,RE fields*/ - pMCTstat->SysLimit = limit; - } - Set_NB32(dev, 0x40 + (Node << 3), base); /* [Node] + Dram Base 0 */ - - val = limit & 0xFFFF0000; - val |= Node; - Set_NB32(dev, 0x44 + (Node << 3), val); /* set DstNode */ - - printk(BIOS_DEBUG, " Node: %02x base: %02x limit: %02x\n", Node, base, limit); - limit = pDCTstat->DCTSysLimit; - if (limit) { - NextBase = (limit & 0xFFFF0000) + 0x10000; - } - } - - /* Copy dram map from Node 0 to Node 1-7 */ - for (Node = 1; Node < MAX_NODES_SUPPORTED; Node++) { - u32 reg; - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - - if (pDCTstat->NodePresent) { - printk(BIOS_DEBUG, " Copy dram map from Node 0 to Node %02x\n", Node); - reg = 0x40; /*Dram Base 0*/ - do { - val = Get_NB32(dev, reg); - Set_NB32(devx, reg, val); - reg += 4; - } while (reg < 0x80); - } else { - break; /* stop at first absent Node */ - } - } - - /*Copy dram map to F1x120/124*/ - mct_HTMemMapExt(pMCTstat, pDCTstatA); -} - -void MCTMemClr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - - /* Initiates a memory clear operation for all node. The mem clr - * is done in parallel. After the memclr is complete, all processors - * status are checked to ensure that memclr has completed. - */ - u8 Node; - uint32_t dword; - struct DCTStatStruc *pDCTstat; - - if (!mctGet_NVbits(NV_DQSTrainCTL)) { - /* FIXME: callback to wrapper: mctDoWarmResetMemClr_D */ - } else { /* NV_DQSTrainCTL == 1 */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Init_D(pMCTstat, pDCTstat); - } - } - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Sync_D(pMCTstat, pDCTstat); - } - } - } - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - /* Enable prefetchers */ - dword = Get_NB32(pDCTstat->dev_dct, 0x11c); /* Memory Controller Configuration High */ - dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ - dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */ - Set_NB32(pDCTstat->dev_dct, 0x11c, dword); /* Memory Controller Configuration High */ - } -} - -void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u32 dev; - uint32_t dword; - - /* Initiates a memory clear operation on one node */ - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - - /* Disable prefetchers */ - dword = Get_NB32(dev, 0x11c); /* Memory Controller Configuration High */ - dword |= 0x1 << 13; /* PrefIoDis = 1 */ - dword |= 0x1 << 12; /* PrefCpuDis = 1 */ - Set_NB32(dev, 0x11c, dword); /* Memory Controller Configuration High */ - - do { - val = Get_NB32(dev, 0x110); - } while (val & (1 << MemClrBusy)); - - val |= (1 << MemClrInit); - Set_NB32(dev, 0x110, val); - } -} - -void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Ensure that a memory clear operation has completed on one node */ - if (pDCTstat->DCTSysLimit) { - printk(BIOS_DEBUG, "%s: Waiting for memory clear to complete", __func__); - do { - dword = Get_NB32(dev, 0x110); - - printk(BIOS_DEBUG, "."); - } while (dword & (1 << MemClrBusy)); - - printk(BIOS_DEBUG, "\n"); - do { - printk(BIOS_DEBUG, "."); - dword = Get_NB32(dev, 0x110); - } while (!(dword & (1 << Dr_MemClrStatus))); - printk(BIOS_DEBUG, "\n"); - } - - /* Enable prefetchers */ - dword = Get_NB32(dev, 0x11c); /* Memory Controller Configuration High */ - dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ - dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */ - Set_NB32(dev, 0x11c, dword); /* Memory Controller Configuration High */ - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -u8 NodePresent_D(u8 Node) -{ - /* - * Determine if a single Hammer Node exists within the network. - */ - u32 dev; - u32 val; - u32 dword; - u8 ret = 0; - - dev = PA_HOST(Node); /*test device/vendor id at host bridge */ - val = Get_NB32(dev, 0); - dword = mct_NodePresent_D(); /* FIXME: BOZO -11001022h rev for F */ - if (val == dword) { /* AMD Hammer Family CPU HT Configuration */ - if (oemNodePresent_D(Node, &ret)) - goto finish; - /* Node ID register */ - val = Get_NB32(dev, 0x60); - val &= 0x07; - dword = Node; - if (val == dword) /* current nodeID = requested nodeID ? */ - ret = 1; - } -finish: - return ret; -} - -static void DCTPreInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* - * Run DCT pre-initialization tasks - */ - uint32_t dword; - - /* Reset DCT registers */ - ClearDCT_D(pMCTstat, pDCTstat, dct); - pDCTstat->stopDCT[dct] = 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\tDCTPreInit_D: mct_DIMMPresence Done\n"); - } -} - -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"); - - /* SkewMemClk must be set before MemClkFreqVal is set - * This relies on DCTInit_D being called for DCT 1 after - * it has already been called for DCT 0... - */ - if (is_fam15h()) { - /* Set memory clock skew if needed */ - if (dct == 1) { - if (!pDCTstat->stopDCT[0]) { - printk(BIOS_DEBUG, "\t\tDCTInit_D: enabling intra-channel clock skew\n"); - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe00a); - dword |= (0x1 << 4); /* SkewMemClk = 1 */ - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe00a, dword); - } - } - } - - 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[dct] = 0; - } - } - } - } -} - -static void DCTFinalInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - uint32_t dword; - - /* Finalize DRAM init on a single node */ - if (!pDCTstat->stopDCT[dct]) { - if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) { - printk(BIOS_DEBUG, "\t\tDCTFinalInit_D: StartupDCT_D Start\n"); - StartupDCT_D(pMCTstat, pDCTstat, dct); - printk(BIOS_DEBUG, "\t\tDCTFinalInit_D: StartupDCT_D Done\n"); - } - } - - if (pDCTstat->stopDCT[dct]) { - dword = 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword); - - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x90); - dword &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x90, 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); - } -} - -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Wait (and block further access to dram) for all DCTs to be ready, - * by polling all InitDram bits and waiting for possible memory clear - * operations to be complete. Read MemClkFreqVal bit to see if - * the DIMMs are present in this node. - */ - u8 Node; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - mct_SyncDCTsReady(pDCTstat); - } - - 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); -} - -void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Read MemClkFreqVal bit to see if the DIMMs are present in this node. - * If the DIMMs are present then set the DRAM Enable bit for this node. - * - * Setting dram init starts up the DCT state machine, initializes the - * dram devices with MRS commands, and kicks off any - * HW memory clear process that the chip is capable of. The sooner - * that dram init is set for all nodes, the faster the memory system - * initialization can complete. Thus, the init loop is unrolled into - * two loops so as to start the processes for non BSP nodes sooner. - * This procedure will not wait for the process to finish. - * Synchronization is handled elsewhere. - */ - u32 val; - u32 dev; - - dev = pDCTstat->dev_dct; - val = Get_NB32_DCT(dev, dct, 0x94); - if (val & (1<<MemClkFreqVal)) { - mctHookBeforeDramInit(); /* generalized Hook */ - if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) - mct_DramInit(pMCTstat, pDCTstat, dct); - AfterDramInit_D(pDCTstat, dct); - mctHookAfterDramInit(); /* generalized Hook*/ - } -} - -static void ClearDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg_end; - u32 dev = pDCTstat->dev_dct; - u32 reg = 0x40; - u32 val = 0; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - reg_end = 0x78; - } else { - reg_end = 0xA4; - } - - while (reg < reg_end) { - if ((reg & 0xFF) == 0x84) { - if (is_fam15h()) { - val = Get_NB32_DCT(dev, dct, reg); - val &= ~(0x1 << 23); /* Clear PchgPDModeSel */ - val &= ~0x3; /* Clear BurstCtrl */ - } - } - if ((reg & 0xFF) == 0x90) { - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - val = Get_NB32_DCT(dev, dct, reg); /* get DRAMConfigLow */ - val |= 0x08000000; /* preserve value of DisDllShutdownSR for only Rev.D */ - } - } - Set_NB32_DCT(dev, dct, reg, val); - val = 0; - reg += 4; - } - - val = 0; - dev = pDCTstat->dev_map; - reg = 0xF0; - Set_NB32(dev, reg, val); -} - -void SPD2ndTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u16 Twr, Trtp; - u16 Trp, Trrd, Trcd, Tras, Trc; - u8 Trfc[4]; - u16 Tfaw; - u16 Tcwl; /* Fam15h only */ - u32 DramTimingLo, DramTimingHi; - u8 tCK16x; - u16 Twtr; - uint8_t Etr[2]; - u8 LDIMM; - u8 MTB16x; - u8 byte; - u32 dword; - u32 dev; - u32 val; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Gather all DIMM mini-max values for cycle timing data */ - Trp = 0; - Trrd = 0; - Trcd = 0; - Trtp = 0; - Tras = 0; - Trc = 0; - Twr = 0; - Twtr = 0; - for (i = 0; i < 2; i++) - Etr[i] = 0; - for (i = 0; i < 4; i++) - Trfc[i] = 0; - Tfaw = 0; - - for (i = 0; i< MAX_DIMMS_SUPPORTED; i++) { - LDIMM = i >> 1; - if (pDCTstat->DIMMValid & (1 << i)) { - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDivisor]; /* MTB = Dividend/Divisor */ - MTB16x = ((pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDividend] & 0xff) << 4); - MTB16x /= val; /* transfer to MTB*16 */ - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRPmin]; - val = byte * MTB16x; - if (Trp < val) - Trp = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRRDmin]; - val = byte * MTB16x; - if (Trrd < val) - Trrd = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRCDmin]; - val = byte * MTB16x; - if (Trcd < val) - Trcd = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRTPmin]; - val = byte * MTB16x; - if (Trtp < val) - Trtp = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tWRmin]; - val = byte * MTB16x; - if (Twr < val) - Twr = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tWTRmin]; - val = byte * MTB16x; - if (Twtr < val) - Twtr = val; - - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Upper_tRAS_tRC] & 0xff; - val >>= 4; - val <<= 8; - val |= pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRCmin] & 0xff; - val *= MTB16x; - if (Trc < val) - Trc = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Density] & 0xf; - if (Trfc[LDIMM] < byte) - Trfc[LDIMM] = byte; - - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Upper_tRAS_tRC] & 0xf; - val <<= 8; - val |= (pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRASmin] & 0xff); - val *= MTB16x; - if (Tras < val) - Tras = val; - - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Upper_tFAW] & 0xf; - val <<= 8; - val |= pDCTstat->spd_data.spd_bytes[dct + i][SPD_tFAWmin] & 0xff; - val *= MTB16x; - if (Tfaw < val) - Tfaw = val; - - /* Determine if the DIMMs on this channel support 95°C ETR */ - if (pDCTstat->spd_data.spd_bytes[dct + i][SPD_Thermal] & 0x1) - Etr[dct] = 1; - } /* Dimm Present */ - } - - /* Convert DRAM CycleTiming values and store into DCT structure */ - byte = pDCTstat->DIMMAutoSpeed; - if (is_fam15h()) { - if (byte == 0x16) - tCK16x = 17; - else if (byte == 0x12) - tCK16x = 20; - else if (byte == 0xe) - tCK16x = 24; - else if (byte == 0xa) - tCK16x = 30; - else if (byte == 0x6) - tCK16x = 40; - else - tCK16x = 48; - } else { - if (byte == 7) - tCK16x = 20; - else if (byte == 6) - tCK16x = 24; - else if (byte == 5) - tCK16x = 30; - else - tCK16x = 40; - } - - /* Notes: - 1. All secondary time values given in SPDs are in binary with units of ns. - 2. Some time values are scaled by 16, in order to have least count of 0.25 ns - (more accuracy). JEDEC SPD spec. shows which ones are x1 and x4. - 3. Internally to this SW, cycle time, tCK16x, is scaled by 16 to match time values - */ - - /* Tras */ - pDCTstat->DIMMTras = (u16)Tras; - val = Tras / tCK16x; - if (Tras % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrasT) - val = Min_TrasT; - else if (val > Max_TrasT) - val = Max_TrasT; - pDCTstat->Tras = val; - - /* Trp */ - pDCTstat->DIMMTrp = Trp; - val = Trp / tCK16x; - if (Trp % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrpT) - val = Min_TrpT; - else if (val > Max_TrpT) - val = Max_TrpT; - pDCTstat->Trp = val; - - /* Trrd */ - pDCTstat->DIMMTrrd = Trrd; - val = Trrd / tCK16x; - if (Trrd % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrrdT) - val = Min_TrrdT; - else if (val > Max_TrrdT) - val = Max_TrrdT; - pDCTstat->Trrd = val; - - /* Trcd */ - pDCTstat->DIMMTrcd = Trcd; - val = Trcd / tCK16x; - if (Trcd % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrcdT) - val = Min_TrcdT; - else if (val > Max_TrcdT) - val = Max_TrcdT; - pDCTstat->Trcd = val; - - /* Trc */ - pDCTstat->DIMMTrc = Trc; - val = Trc / tCK16x; - if (Trc % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrcT) - val = Min_TrcT; - else if (val > Max_TrcT) - val = Max_TrcT; - pDCTstat->Trc = val; - - /* Trtp */ - pDCTstat->DIMMTrtp = Trtp; - val = Trtp / tCK16x; - if (Trtp % tCK16x) { - val ++; - } - if (val < Min_TrtpT) - val = Min_TrtpT; - else if (val > Max_TrtpT) - val = Max_TrtpT; - pDCTstat->Trtp = val; - - /* Twr */ - pDCTstat->DIMMTwr = Twr; - val = Twr / tCK16x; - if (Twr % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TwrT) - val = Min_TwrT; - else if (val > Max_TwrT) - val = Max_TwrT; - pDCTstat->Twr = val; - - /* Twtr */ - pDCTstat->DIMMTwtr = Twtr; - val = Twtr / tCK16x; - if (Twtr % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TwtrT) - val = Min_TwtrT; - else if (val > Max_TwtrT) - val = Max_TwtrT; - pDCTstat->Twtr = val; - - /* Trfc0-Trfc3 */ - for (i = 0; i < 4; i++) - pDCTstat->Trfc[i] = Trfc[i]; - - /* Tfaw */ - pDCTstat->DIMMTfaw = Tfaw; - val = Tfaw / tCK16x; - if (Tfaw % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TfawT) - val = Min_TfawT; - else if (val > Max_TfawT) - val = Max_TfawT; - pDCTstat->Tfaw = val; - - 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 */ - - /* Apply offset */ - Tcwl += pDCTstat->tcwl_delay[dct]; - } - - /* Program DRAM Timing values */ - if (is_fam15h()) { - dev = pDCTstat->dev_dct; - - dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */ - if (Etr[dct]) - val = 3; /* Tref = 3.9us */ - else - 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 & 0x3f) << 24; /* Tras */ - val = pDCTstat->Trp; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - dword |= (val & 0x1f) << 16; /* Trp */ - dword |= (pDCTstat->Trcd & 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 & 0xf) << 24; /* Trtp */ - if (pDCTstat->Tfaw != 0) { - val = pDCTstat->Tfaw; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - if ((val > 0x5) && (val < 0x2b)) - dword |= (val & 0x3f) << 16; /* FourActWindow */ - } - dword |= (pDCTstat->Trrd & 0xf) << 8; /* Trrd */ - dword |= (pDCTstat->Trc & 0x3f); /* Trc */ - Set_NB32_DCT(dev, dct, 0x204, dword); /* DRAM Timing 1 */ - - /* Trfc0-Trfc3 */ - for (i = 0; i < 4; i++) - if (pDCTstat->Trfc[i] == 0x0) - pDCTstat->Trfc[i] = 0x1; - 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 & 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 & 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); - } - - /* 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 */ - - 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->Trcd - Bias_TrcdT; - DramTimingLo |= val<<4; - - val = pDCTstat->Trp - Bias_TrpT; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - DramTimingLo |= val<<7; - - val = pDCTstat->Trtp - Bias_TrtpT; - DramTimingLo |= val<<10; - - val = pDCTstat->Tras - Bias_TrasT; - DramTimingLo |= val<<12; - - val = pDCTstat->Trc - Bias_TrcT; - DramTimingLo |= val<<16; - - val = pDCTstat->Trrd - Bias_TrrdT; - DramTimingLo |= val<<22; - - DramTimingHi = 0; /* Dram Timing High init */ - val = pDCTstat->Twtr - Bias_TwtrT; - DramTimingHi |= val<<8; - - 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 > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - DramTimingHi |= 1 << DisAutoRefresh; - } - DramTimingHi |= 0x000018FF; - Set_NB32_DCT(dev, dct, 0x8c, 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, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - /* Initialize DCT Timing registers as per DIMM SPD. - * For primary timing (T, CL) use best case T value. - * For secondary timing params., use most aggressive settings - * of slowest DIMM. - * - * There are three components to determining "maximum frequency": - * SPD component, Bus load component, and "Preset" max frequency - * component. - * - * The SPD component is a function of the min cycle time specified - * by each DIMM, and the interaction of cycle times from all DIMMs - * in conjunction with CAS latency. The SPD component only applies - * when user timing mode is 'Auto'. - * - * The Bus load component is a limiting factor determined by electrical - * characteristics on the bus as a result of varying number of device - * loads. The Bus load component is specific to each platform but may - * also be a function of other factors. The bus load component only - * applies when user timing mode is 'Auto'. - * - * The Preset component is subdivided into three items and is - * the minimum of the set: Silicon revision, user limit - * setting when user timing mode is 'Auto' and memclock mode - * is 'Limit', OEM build specification of the maximum - * frequency. The Preset component is only applies when user - * 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); - - /* and Factor in presets (setup options, Si cap, etc.) */ - GetPresetmaxF_D(pMCTstat, pDCTstat); - - /* 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; - - } - mct_AfterGetCLT(pMCTstat, pDCTstat, dct); - - SPD2ndTiming(pMCTstat, pDCTstat, dct); - - printk(BIOS_DEBUG, "AutoCycTiming: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "AutoCycTiming: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "AutoCycTiming: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "AutoCycTiming: Done\n\n"); - - mctHookAfterAutoCycTmg(); - - return pDCTstat->ErrCode; -} - -static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Get max frequency from OEM platform definition, from any user - * override (limiting) of max frequency, and from any Si Revision - * Specific information. Return the least of these three in - * DCTStatStruc.PresetmaxFreq. - */ - /* TODO: Set the proper max frequency in wrappers/mcti_d.c. */ - u16 proposedFreq; - u16 word; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Get CPU Si Revision defined limit (NPT) */ - 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) { - word = Get_Fk_D(mctGet_NVbits(NV_MemCkVal) + 1); - if (word < proposedFreq) - proposedFreq = word; - - /* Get Platform defined limit */ - word = mctGet_NVbits(NV_MAX_MEMCLK); - if (word < proposedFreq) - proposedFreq = word; - - word = pDCTstat->PresetmaxFreq; - if (word > proposedFreq) - word = proposedFreq; - - pDCTstat->PresetmaxFreq = word; - } - /* Check F3xE8[DdrMaxRate] for maximum DRAM data rate support */ - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - /* Find the best T and CL primary timing parameter pair, per Mfg., - * for the given set of DIMMs, and store into DCTStatStruc - * (.DIMMAutoSpeed and .DIMMCASL). See "Global relationship between - * index values and item values" for definition of CAS latency - * index (j) and Frequency index (k). - */ - u8 i, CASLatLow, CASLatHigh; - u16 tAAmin16x; - u8 MTB16x; - u16 tCKmin16x; - u16 tCKproposed16x; - u8 CLactual, CLdesired, CLT_Fail; - uint16_t min_frequency_tck16x; - - u8 byte = 0, bytex = 0; - - CASLatLow = 0xFF; - CASLatHigh = 0xFF; - tAAmin16x = 0; - 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)) { - /* Step 1: Determine the common set of supported CAS Latency - * values for all modules on the memory channel using the CAS - * Latencies Supported in SPD bytes 14 and 15. - */ - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_CASLow]; - CASLatLow &= byte; - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_CASHigh]; - CASLatHigh &= byte; - /* Step 2: Determine tAAmin(all) which is the largest tAAmin - value for all modules on the memory channel (SPD byte 16). */ - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDivisor]; - - MTB16x = ((pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDividend] & 0xFF)<<4); - MTB16x /= byte; /* transfer to MTB*16 */ - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tAAmin]; - if (tAAmin16x < byte * MTB16x) - tAAmin16x = byte * MTB16x; - /* Step 3: Determine tCKmin(all) which is the largest tCKmin - value for all modules on the memory channel (SPD byte 12). */ - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tCKmin]; - - if (tCKmin16x < byte * MTB16x) - tCKmin16x = byte * MTB16x; - } - } - /* calculate tCKproposed16x (proposed clock period in ns * 16) */ - tCKproposed16x = 16000 / pDCTstat->PresetmaxFreq; - if (tCKmin16x > tCKproposed16x) - tCKproposed16x = tCKmin16x; - - /* TODO: get user manual tCK16x(Freq.) and overwrite current tCKproposed16x if manual. */ - 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 { - 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 - - Second time find tCL at 400MHz */ - - for (;;) { - CLT_Fail = 0; - /* Step 4: For a proposed tCK value (tCKproposed) between tCKmin(all) and tCKmax, - determine the desired CAS Latency. If tCKproposed is not a standard JEDEC - value (2.5, 1.875, 1.5, or 1.25 ns) then tCKproposed must be adjusted to the - next lower standard tCK value for calculating CLdesired. - CLdesired = ceiling (tAAmin(all) / tCKproposed) - where tAAmin is defined in Byte 16. The ceiling function requires that the - quotient be rounded up always. */ - CLdesired = tAAmin16x / tCKproposed16x; - if (tAAmin16x % tCKproposed16x) - CLdesired ++; - /* Step 5: Chose an actual CAS Latency (CLactual) that is greather than or equal - to CLdesired and is supported by all modules on the memory channel as - determined in step 1. If no such value exists, choose a higher tCKproposed - value and repeat steps 4 and 5 until a solution is found. */ - for (i = 0, CLactual = 4; i < 15; i++, CLactual++) { - if ((CASLatHigh << 8 | CASLatLow) & (1 << i)) { - if (CLdesired <= CLactual) - break; - } - } - if (i == 15) - CLT_Fail = 1; - /* Step 6: Once the calculation of CLactual is completed, the BIOS must also - verify that this CAS Latency value does not exceed tAAmax, which is 20 ns - for all DDR3 speed grades, by multiplying CLactual times tCKproposed. If - not, choose a lower CL value and repeat steps 5 and 6 until a solution is found. */ - if (CLactual * tCKproposed16x > 320) - CLT_Fail = 1; - /* get CL and T */ - if (!CLT_Fail) { - bytex = CLactual; - 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 != min_frequency_tck16x) { - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - pDCTstat->DIMMAutoSpeed = byte; - pDCTstat->DIMMCASL = bytex; - break; - } else { - pDCTstat->TargetCASL = bytex; - tCKproposed16x = min_frequency_tck16x; - } - } else { - pDCTstat->DIMMAutoSpeed = byte; - pDCTstat->DIMMCASL = bytex; - break; - } - } - - printk(BIOS_DEBUG, "SPDGetTCL_D: DIMMCASL %x\n", pDCTstat->DIMMCASL); - printk(BIOS_DEBUG, "SPDGetTCL_D: DIMMAutoSpeed %x\n", pDCTstat->DIMMAutoSpeed); - - printk(BIOS_DEBUG, "SPDGetTCL_D: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "SPDGetTCL_D: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "SPDGetTCL_D: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "SPDGetTCL_D: Done\n\n"); -} - -u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (!is_fam15h()) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct); - - if (pDCTstat->GangedMode == 1) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1); - mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1); - } - - set_2t_configuration(pMCTstat, pDCTstat, dct); - - 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); - } - mctHookAfterPSCfg(); - - return pDCTstat->ErrCode; -} - -static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 DramControl, DramTimingLo, Status; - u32 DramConfigLo, DramConfigHi, DramConfigMisc, DramConfigMisc2; - u32 val; - u32 dev; - u16 word; - u32 dword; - u8 byte; - uint32_t offset; - - DramConfigLo = 0; - DramConfigHi = 0; - DramConfigMisc = 0; - DramConfigMisc2 = 0; - - /* set bank addressing and Masks, plus CS pops */ - SPDSetBanks_D(pMCTstat, pDCTstat, dct); - if (pDCTstat->ErrCode == SC_StopError) - goto AutoConfig_exit; - - /* map chip-selects into local address space */ - StitchMemory_D(pMCTstat, pDCTstat, dct); - InterleaveBanks_D(pMCTstat, pDCTstat, dct); - - /* temp image of status (for convenience). RO usage! */ - Status = pDCTstat->Status; - - dev = pDCTstat->dev_dct; - - /* Build Dram Control Register Value */ - DramConfigMisc2 = Get_NB32_DCT(dev, dct, 0xa8); /* Dram Miscellaneous 2 */ - DramControl = Get_NB32_DCT(dev, dct, 0x78); /* Dram Control */ - - /* FIXME: Skip mct_checkForDxSupport */ - /* REV_CALL mct_DoRdPtrInit if not Dx */ - if (pDCTstat->LogicalCPUID & AMD_DR_Bx) - val = 5; - else - val = 6; - DramControl &= ~0xFF; - DramControl |= val; /* RdPtrInit = 6 for Cx CPU */ - - if (mctGet_NVbits(NV_CLKHZAltVidC3)) - DramControl |= 1<<16; /* check */ - - DramControl |= 0x00002A00; - - /* FIXME: Skip for Ax versions */ - /* callback not required - if (!mctParityControl_D()) */ - if (Status & (1 << SB_128bitmode)) - DramConfigLo |= 1 << Width128; /* 128-bit mode (normal) */ - - word = dct; - dword = X4Dimm; - while (word < 8) { - if (pDCTstat->Dimmx4Present & (1 << word)) - DramConfigLo |= 1 << dword; /* X4Dimm[3:0] */ - word++; - word++; - dword++; - } - - if (Status & (1 << SB_Registered)) { - /* Registered DIMMs */ - if (!is_fam15h()) { - DramConfigLo |= 1 << ParEn; - } - } else { - /* Unbuffered DIMMs */ - DramConfigLo |= 1 << UnBuffDimm; - } - - if (mctGet_NVbits(NV_ECC_CAP)) - if (Status & (1 << SB_ECCDIMMs)) - if (mctGet_NVbits(NV_ECC)) - DramConfigLo |= 1 << DimmEcEn; - - 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 - offset; /* get MemClk encoding */ - DramConfigHi |= 1 << MemClkFreqVal; - - if (!is_fam15h()) - if (Status & (1 << SB_Registered)) - if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) - /* set only if x8 Registered DIMMs in System*/ - DramConfigHi |= 1 << RDqsEn; - - if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) { - DramConfigLo |= 1 << 25; /* PendRefPaybackS3En = 1 */ - DramConfigLo |= 1 << 24; /* StagRefEn = 1 */ - DramConfigHi |= 1 << 16; /* PowerDownMode = 1 */ - } else { - if (mctGet_NVbits(NV_CKE_CTL)) - /*Chip Select control of CKE*/ - DramConfigHi |= 1 << 16; - } - - if (!is_fam15h()) { - /* Control Bank Swizzle */ - if (0) /* call back not needed mctBankSwizzleControl_D()) */ - DramConfigHi &= ~(1 << BankSwizzleMode); - else - DramConfigHi |= 1 << BankSwizzleMode; /* recommended setting (default) */ - } - - /* Check for Quadrank DIMM presence */ - if (pDCTstat->DimmQRPresent != 0) { - byte = mctGet_NVbits(NV_4RANKType); - if (byte == 2) - DramConfigHi |= 1 << 17; /* S4 (4-Rank SO-DIMMs) */ - else if (byte == 1) - DramConfigHi |= 1 << 18; /* R4 (4-Rank Registered DIMMs) */ - } - - if (0) /* call back not needed mctOverrideDcqBypMax_D) */ - val = mctGet_NVbits(NV_BYPMAX); - else - val = 0x0f; /* recommended setting (default) */ - DramConfigHi |= val << 24; - - 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 - Dram Config Misc Registers - 1. We will assume that MemClkDis field has been preset prior to this - point. - 2. We will only set MemClkDis bits if a DIMM is NOT present AND if: - NV_AllMemClks <>0 AND SB_DiagClks == 0 */ - - /* Dram Timing Low (owns Clock Enable bits) */ - 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))) { - const u8 *p; - p = Tab_ManualCLKDis; - - byte = mctGet_NVbits(NV_PACK_TYPE); - if (byte == PT_L1) - p = Tab_L1CLKDis; - else if (byte == PT_M2 || byte == PT_AS) - p = Tab_AM3CLKDis; - else if (byte == PT_C3) - p = Tab_C32CLKDis; - else if (byte == PT_GR) - p = Tab_G34CLKDis; - else if (byte == PT_FM2) - p = Tab_FM2CLKDis; - else - p = Tab_S1CLKDis; - - dword = 0; - byte = 0xFF; - while (dword < MAX_CS_SUPPORTED) { - if (pDCTstat->CSPresent & (1<<dword)) { - /* re-enable clocks for the enabled CS */ - val = p[dword]; - byte &= ~val; - } - dword++; - } - DramTimingLo &= ~(0xff << 24); - DramTimingLo |= byte << 24; - } - } - - DramConfigMisc2 = mct_SetDramConfigMisc2(pDCTstat, dct, DramConfigMisc2, DramControl); - - 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_DCT(dev, dct, 0x78, DramControl); - Set_NB32_DCT(dev, dct, 0x88, DramTimingLo); - Set_NB32_DCT(dev, dct, 0xa0, DramConfigMisc); - Set_NB32_DCT(dev, dct, 0xa8, DramConfigMisc2); - Set_NB32_DCT(dev, dct, 0x90, DramConfigLo); - ProgDramMRSReg_D(pMCTstat, pDCTstat, dct); - - 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(pMCTstat, pDCTstat, dct, DramConfigHi); - mct_EarlyArbEn_D(pMCTstat, pDCTstat, dct); - mctHookAfterAutoCfg(); - - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "AutoConfig: Status %x\n", pDCTstat->Status); - 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; -} - -static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Set bank addressing, program Mask values and build a chip-select - * population map. This routine programs PCI 0:24N:2x80 config register - * and PCI 0:24N:2x60,64,68,6C config registers (CS Mask 0-3). - */ - u8 ChipSel, Rows, Cols, Ranks, Banks; - u32 BankAddrReg, csMask; - - u32 val; - u32 reg; - u32 dev; - u8 byte; - u16 word; - u32 dword; - - dev = pDCTstat->dev_dct; - - BankAddrReg = 0; - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel+=2) { - byte = ChipSel; - if ((pDCTstat->Status & (1 << SB_64MuxedMode)) && ChipSel >=4) - byte -= 3; - - if (pDCTstat->DIMMValid & (1<<byte)) { - byte = pDCTstat->spd_data.spd_bytes[ChipSel + dct][SPD_Addressing]; - Rows = (byte >> 3) & 0x7; /* Rows:0b = 12-bit,... */ - Cols = byte & 0x7; /* Cols:0b = 9-bit,... */ - - byte = pDCTstat->spd_data.spd_bytes[ChipSel + dct][SPD_Density]; - Banks = (byte >> 4) & 7; /* Banks:0b = 3-bit,... */ - - byte = pDCTstat->spd_data.spd_bytes[ChipSel + dct][SPD_Organization]; - Ranks = ((byte >> 3) & 7) + 1; - - /* Configure Bank encoding - * Use a 6-bit key into a lookup table. - * Key (index) = RRRBCC, where CC is the number of Columns minus 9, - * RRR is the number of Rows minus 12, and B is the number of banks - * minus 3. - */ - byte = Cols; - if (Banks == 1) - byte |= 4; - - byte |= Rows << 3; /* RRRBCC internal encode */ - - for (dword = 0; dword < 13; dword++) { - if (byte == Tab_BankAddr[dword]) - break; - } - - if (dword > 12) - continue; - - /* bit no. of CS field in address mapping reg.*/ - dword <<= (ChipSel<<1); - BankAddrReg |= dword; - - /* Mask value=(2pow(rows+cols+banks+3)-1)>>8, - or 2pow(rows+cols+banks-5)-1*/ - csMask = 0; - - byte = Rows + Cols; /* cl = rows+cols*/ - byte += 21; /* row:12+col:9 */ - byte -= 2; /* 3 banks - 5 */ - - if (pDCTstat->Status & (1 << SB_128bitmode)) - byte++; /* double mask size if in 128-bit mode*/ - - csMask |= 1 << byte; - csMask--; - - /*set ChipSelect population indicator even bits*/ - pDCTstat->CSPresent |= (1<<ChipSel); - if (Ranks >= 2) - /*set ChipSelect population indicator odd bits*/ - pDCTstat->CSPresent |= 1 << (ChipSel + 1); - - reg = 0x60+(ChipSel<<1); /*Dram CS Mask Register */ - val = csMask; - val &= 0x1FF83FE0; /* Mask out reserved bits.*/ - Set_NB32_DCT(dev, dct, reg, val); - } else { - if (pDCTstat->DIMMSPDCSE & (1<<ChipSel)) - pDCTstat->CSTestFail |= (1<<ChipSel); - } /* if DIMMValid*/ - } /* while ChipSel*/ - - SetCSTriState(pMCTstat, pDCTstat, dct); - SetCKETriState(pMCTstat, pDCTstat, dct); - SetODTTriState(pMCTstat, pDCTstat, dct); - - if (pDCTstat->Status & (1 << SB_128bitmode)) { - SetCSTriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - SetCKETriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - SetODTTriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - } - - word = pDCTstat->CSPresent; - mctGetCS_ExcludeMap(); /* mask out specified chip-selects */ - word ^= pDCTstat->CSPresent; - pDCTstat->CSTestFail |= word; /* enable ODT to disabled DIMMs */ - if (!pDCTstat->CSPresent) - pDCTstat->ErrCode = SC_StopError; - - 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)); */ - - printk(BIOS_DEBUG, "SPDSetBanks: CSPresent %x\n", pDCTstat->CSPresent_DCT[dct]); - printk(BIOS_DEBUG, "SPDSetBanks: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "SPDSetBanks: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "SPDSetBanks: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "SPDSetBanks: Done\n\n"); -} - -static void SPDCalcWidth_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Per SPDs, check the symmetry of DIMM pairs (DIMM on Channel A - * matching with DIMM on Channel B), the overall DIMM population, - * and determine the width mode: 64-bit, 64-bit muxed, 128-bit. - */ - u8 i; - u8 byte, byte1; - - /* Check Symmetry of Channel A and Channel B DIMMs - (must be matched for 128-bit mode).*/ - for (i = 0; i < MAX_DIMMS_SUPPORTED; i += 2) { - if ((pDCTstat->DIMMValid & (1 << i)) && (pDCTstat->DIMMValid & (1<<(i+1)))) { - byte = pDCTstat->spd_data.spd_bytes[i][SPD_Addressing] & 0x7; - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_Addressing] & 0x7; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0x0f; - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_Density] & 0x0f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7; - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_Organization] & 0x7; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = (pDCTstat->spd_data.spd_bytes[i][SPD_Organization] >> 3) & 0x7; - byte1 = (pDCTstat->spd_data.spd_bytes[i + 1][SPD_Organization] >> 3) & 0x7; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = pDCTstat->spd_data.spd_bytes[i][SPD_DMBANKS] & 7; /* #ranks-1 */ - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_DMBANKS] & 7; /* #ranks-1 */ - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - } - } - -} - -static void StitchMemory_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Requires that Mask values for each bank be programmed first and that - * the chip-select population indicator is correctly set. - */ - u8 b = 0; - u32 nxtcsBase, curcsBase; - u8 p, q; - u32 BiggestBank; - u8 _DSpareEn; - - u16 word; - u32 dev; - u32 reg; - u32 val; - - dev = pDCTstat->dev_dct; - - _DSpareEn = 0; - - /* CS Sparing 1 = enabled, 0 = disabled */ - if (mctGet_NVbits(NV_CS_SpareCTL) & 1) { - if (MCT_DIMM_SPARE_NO_WARM) { - /* Do no warm-reset DIMM spare */ - if (pMCTstat->GStatus & 1 << GSB_EnDIMMSpareNW) { - word = pDCTstat->CSPresent; - val = bsf(word); - word &= ~(1<<val); - if (word) - /* Make sure at least two chip-selects are available */ - _DSpareEn = 1; - else - pDCTstat->ErrStatus |= 1 << SB_SpareDis; - } - } else { - if (!mctGet_NVbits(NV_DQSTrainCTL)) { /*DQS Training 1 = enabled, 0 = disabled */ - word = pDCTstat->CSPresent; - val = bsf(word); - word &= ~(1 << val); - if (word) - /* Make sure at least two chip-selects are available */ - _DSpareEn = 1; - else - pDCTstat->ErrStatus |= 1 << SB_SpareDis; - } - } - } - - nxtcsBase = 0; /* Next available cs base ADDR[39:8] */ - for (p = 0; p < MAX_DIMMS_SUPPORTED; p++) { - 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); /* Base[q] reg.*/ - val = Get_NB32_DCT(dev, dct, reg); - if (!(val & 3)) { /* (CSEnable|Spare == 1)bank is enabled already? */ - reg = 0x60 + (q << 1); /*Mask[q] reg.*/ - val = Get_NB32_DCT(dev, dct, reg); - val >>= 19; - val++; - val <<= 19; - if (val > BiggestBank) { - /*Bingo! possibly Map this chip-select next! */ - BiggestBank = val; - b = q; - } - } - } /*if bank present */ - } /* while q */ - if (BiggestBank !=0) { - curcsBase = nxtcsBase; /* curcsBase = nxtcsBase*/ - /* DRAM CS Base b Address Register offset */ - reg = 0x40 + (b << 2); - if (_DSpareEn) { - BiggestBank = 0; - val = 1 << Spare; /* Spare Enable*/ - } else { - val = curcsBase; - val |= 1 << CSEnable; /* Bank Enable */ - } - if (((reg - 0x40) >> 2) & 1) { - if (!(pDCTstat->Status & (1 << SB_Registered))) { - u16 dimValid; - dimValid = pDCTstat->DIMMValid; - if (dct & 1) - dimValid <<= 1; - if ((dimValid & pDCTstat->MirrPresU_NumRegR) != 0) { - val |= 1 << onDimmMirror; - } - } - } - Set_NB32_DCT(dev, dct, reg, val); - if (_DSpareEn) - _DSpareEn = 0; - else - /* let nxtcsBase+=Size[b] */ - nxtcsBase += BiggestBank; - } - - /* bank present but disabled?*/ - if (pDCTstat->CSTestFail & (1 << p)) { - /* DRAM CS Base b Address Register offset */ - reg = (p << 2) + 0x40; - val = 1 << TestFail; - Set_NB32_DCT(dev, dct, reg, val); - } - } - - if (nxtcsBase) { - pDCTstat->DCTSysLimit = nxtcsBase - 1; - mct_AfterStitchMemory(pMCTstat, pDCTstat, dct); - } - - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "StitchMemory: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "StitchMemory: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "StitchMemory: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "StitchMemory: Done\n\n"); -} - -static u16 Get_Fk_D(u8 k) -{ - return Table_F_k[k]; /* FIXME: k or k<<1 ? */ -} - -static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Check DIMMs present, verify checksum, flag SDRAM type, - * build population indicator bitmaps, and preload bus loading - * of DIMMs into DCTStatStruc. - * MAAload = number of devices on the "A" bus. - * MABload = number of devices on the "B" bus. - * MAAdimms = number of DIMMs on the "A" bus slots. - * MABdimms = number of DIMMs on the "B" bus slots. - * DATAAload = number of ranks on the "A" bus slots. - * DATABload = number of ranks on the "B" bus slots. - */ - u16 i, j, k; - u8 smbaddr; - u8 SPDCtrl; - u16 RegDIMMPresent, LRDIMMPresent, MaxDimms; - u8 devwidth; - u16 DimmSlots; - u8 byte = 0, bytex; - uint8_t crc_status; - - /* preload data structure with addrs */ - mctGet_DIMMAddr(pDCTstat, pDCTstat->Node_ID); - - DimmSlots = MaxDimms = mctGet_NVbits(NV_MAX_DIMMS); - - SPDCtrl = mctGet_NVbits(NV_SPDCHK_RESTRT); - - RegDIMMPresent = 0; - LRDIMMPresent = 0; - pDCTstat->DimmQRPresent = 0; - - for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) { - if (i >= MaxDimms) - break; - - if ((pDCTstat->DimmQRPresent & (1 << i)) || (i < DimmSlots)) { - int status; - smbaddr = Get_DIMMAddress_D(pDCTstat, i); - status = mctRead_SPD(smbaddr, SPD_ByteUse); - if (status >= 0) { - /* Verify result */ - status = mctRead_SPD(smbaddr, SPD_ByteUse); - } - if (status >= 0) { /* SPD access is ok */ - pDCTstat->DIMMPresent |= 1 << i; - read_spd_bytes(pMCTstat, pDCTstat, i); -#ifdef DEBUG_DIMM_SPD - dump_spd_bytes(pMCTstat, pDCTstat, i); -#endif - crc_status = crcCheck(pDCTstat, i); - if (!crc_status) { - /* Try again in case there was a transient glitch */ - read_spd_bytes(pMCTstat, pDCTstat, i); - crc_status = crcCheck(pDCTstat, i); - } - if ((crc_status) || (SPDCtrl == 2)) { /* CRC is OK */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_TYPE]; - if (byte == JED_DDR3SDRAM) { - /*Dimm is 'Present'*/ - pDCTstat->DIMMValid |= 1 << i; - } - } else { - printk(BIOS_WARNING, "Node %d DIMM %d: SPD checksum invalid\n", pDCTstat->Node_ID, i); - pDCTstat->DIMMSPDCSE = 1 << i; - if (SPDCtrl == 0) { - pDCTstat->ErrStatus |= 1 << SB_DIMMChkSum; - pDCTstat->ErrCode = SC_StopError; - } else { - /*if NV_SPDCHK_RESTRT is set to 1, ignore faulty SPD checksum*/ - pDCTstat->ErrStatus |= 1<<SB_DIMMChkSum; - byte = pDCTstat->spd_data.spd_bytes[i][SPD_TYPE]; - if (byte == JED_DDR3SDRAM) - pDCTstat->DIMMValid |= 1 << i; - } - } - - /* Zero DIMM SPD data cache if DIMM not present / valid */ - if (!(pDCTstat->DIMMValid & (1 << i))) - memset(pDCTstat->spd_data.spd_bytes[i], 0, sizeof(pDCTstat->spd_data.spd_bytes[i])); - - /* Get module information for SMBIOS */ - if (pDCTstat->DIMMValid & (1 << i)) { - pDCTstat->DimmManufacturerID[i] = 0; - for (k = 0; k < 8; k++) - pDCTstat->DimmManufacturerID[i] |= ((uint64_t)pDCTstat->spd_data.spd_bytes[i][SPD_MANID_START + k]) << (k * 8); - for (k = 0; k < SPD_PARTN_LENGTH; k++) - pDCTstat->DimmPartNumber[i][k] = pDCTstat->spd_data.spd_bytes[i][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)pDCTstat->spd_data.spd_bytes[i][SPD_REVNO_START + k]) << (k * 8); - pDCTstat->DimmSerialNumber[i] = 0; - for (k = 0; k < 4; k++) - pDCTstat->DimmSerialNumber[i] |= ((uint32_t)pDCTstat->spd_data.spd_bytes[i][SPD_SERIAL_START + k]) << (k * 8); - pDCTstat->DimmRows[i] = (pDCTstat->spd_data.spd_bytes[i][SPD_Addressing] & 0x38) >> 3; - pDCTstat->DimmCols[i] = pDCTstat->spd_data.spd_bytes[i][SPD_Addressing] & 0x7; - pDCTstat->DimmRanks[i] = ((pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x38) >> 3) + 1; - pDCTstat->DimmBanks[i] = 1ULL << (((pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0x70) >> 4) + 3); - pDCTstat->DimmWidth[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_BusWidth] & 0x7) + 3); - pDCTstat->DimmChipSize[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0xf) + 28); - pDCTstat->DimmChipWidth[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7) + 2); - } - /* Check supported voltage(s) */ - pDCTstat->DimmSupportedVoltages[i] = pDCTstat->spd_data.spd_bytes[i][SPD_Voltage] & 0x7; - pDCTstat->DimmSupportedVoltages[i] ^= 0x1; /* Invert LSB to convert from SPD format to internal bitmap format */ - /* Check module type */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_DIMMTYPE] & 0x7; - if (byte == JED_RDIMM || byte == JED_MiniRDIMM) { - RegDIMMPresent |= 1 << i; - pDCTstat->DimmRegistered[i] = 1; - } 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 = pDCTstat->spd_data.spd_bytes[i][SPD_BusWidth]; - if (byte & JED_ECC) { - /* DIMM is ECC capable */ - pDCTstat->DimmECCPresent |= 1 << i; - } - /* Check if x4 device */ - devwidth = pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7; /* 0:x4,1:x8,2:x16 */ - if (devwidth == 0) { - /* DIMM is made with x4 or x16 drams */ - pDCTstat->Dimmx4Present |= 1 << i; - } else if (devwidth == 1) { - pDCTstat->Dimmx8Present |= 1 << i; - } else if (devwidth == 2) { - pDCTstat->Dimmx16Present |= 1 << i; - } - - byte = (pDCTstat->spd_data.spd_bytes[i][SPD_Organization] >> 3); - byte &= 7; - if (byte == 3) { /* 4ranks */ - /* if any DIMMs are QR, we have to make two passes through DIMMs*/ - if (pDCTstat->DimmQRPresent == 0) { - MaxDimms <<= 1; - } - if (i < DimmSlots) { - pDCTstat->DimmQRPresent |= (1 << i) | (1 << (i+4)); - } else { - pDCTstat->MAdimms[i & 1] --; - } - byte = 1; /* upper two ranks of QR DIMM will be counted on another DIMM number iteration*/ - } else if (byte == 1) { /* 2ranks */ - pDCTstat->DimmDRPresent |= 1 << i; - } - bytex = devwidth; - if (devwidth == 0) - bytex = 16; - else if (devwidth == 1) - bytex = 8; - else if (devwidth == 2) - bytex = 4; - - byte++; /* al+1 = rank# */ - if (byte == 2) - bytex <<= 1; /*double Addr bus load value for dual rank DIMMs*/ - - j = i & (1<<0); - pDCTstat->DATAload[j] += byte; /*number of ranks on DATA bus*/ - pDCTstat->MAload[j] += bytex; /*number of devices on CMD/ADDR bus*/ - pDCTstat->MAdimms[j]++; /*number of DIMMs on A bus */ - - /* check address mirror support for unbuffered dimm */ - /* check number of registers on a dimm for registered dimm */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_AddressMirror]; - if (RegDIMMPresent & (1 << i)) { - if ((byte & 3) > 1) - pDCTstat->MirrPresU_NumRegR |= 1 << i; - } else { - if ((byte & 1) == 1) - pDCTstat->MirrPresU_NumRegR |= 1 << i; - } - /* Get byte62: Reference Raw Card information. We dont need it now. */ - /* byte = pDCTstat->spd_data.spd_bytes[i][SPD_RefRawCard]; */ - /* Get Byte65/66 for register manufacture ID code */ - if ((0x97 == pDCTstat->spd_data.spd_bytes[i][SPD_RegManufactureID_H]) && - (0x80 == pDCTstat->spd_data.spd_bytes[i][SPD_RegManufactureID_L])) { - if (0x16 == pDCTstat->spd_data.spd_bytes[i][SPD_RegManRevID]) - pDCTstat->RegMan2Present |= 1 << i; - else - pDCTstat->RegMan1Present |= 1 << i; - } - /* Get control word value for RC3 */ - byte = pDCTstat->spd_data.spd_bytes[i][70]; - pDCTstat->CtrlWrd3 |= ((byte >> 4) & 0xf) << (i << 2); /* RC3 = SPD byte 70 [7:4] */ - /* Get control word values for RC4 and RC5 */ - byte = pDCTstat->spd_data.spd_bytes[i][71]; - pDCTstat->CtrlWrd4 |= (byte & 0xf) << (i << 2); /* RC4 = SPD byte 71 [3:0] */ - pDCTstat->CtrlWrd5 |= ((byte >> 4) & 0xf) << (i << 2); /* RC5 = SPD byte 71 [7:4] */ - } - } - } - 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); - printk(BIOS_DEBUG, "\t DIMMPresence: Dimmx8Present=%x\n", pDCTstat->Dimmx8Present); - printk(BIOS_DEBUG, "\t DIMMPresence: Dimmx16Present=%x\n", pDCTstat->Dimmx16Present); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmPlPresent=%x\n", pDCTstat->DimmPlPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmDRPresent=%x\n", pDCTstat->DimmDRPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmQRPresent=%x\n", pDCTstat->DimmQRPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DATAload[0]=%x\n", pDCTstat->DATAload[0]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAload[0]=%x\n", pDCTstat->MAload[0]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAdimms[0]=%x\n", pDCTstat->MAdimms[0]); - printk(BIOS_DEBUG, "\t DIMMPresence: DATAload[1]=%x\n", pDCTstat->DATAload[1]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAload[1]=%x\n", pDCTstat->MAload[1]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAdimms[1]=%x\n", pDCTstat->MAdimms[1]); - - if (pDCTstat->DIMMValid != 0) { /* If any DIMMs are present...*/ - if (RegDIMMPresent != 0) { - if ((RegDIMMPresent ^ 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_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 */ - pDCTstat->Status |= 1<<SB_ECCDIMMs; - } - } - if (pDCTstat->DimmPARPresent != 0) { - if ((pDCTstat->DimmPARPresent ^ pDCTstat->DIMMValid) == 0) { - /*all DIMMs are Parity capable */ - pDCTstat->Status |= 1<<SB_PARDIMMs; - } - } - } else { - /* no DIMMs present or no DIMMs that qualified. */ - pDCTstat->ErrStatus |= 1<<SB_NoDimms; - pDCTstat->ErrCode = SC_StopError; - } - - printk(BIOS_DEBUG, "\t DIMMPresence: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "\t DIMMPresence: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "\t DIMMPresence: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "\t DIMMPresence: Done\n\n"); - - mctHookAfterDIMMpre(); - - return pDCTstat->ErrCode; -} - -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i) -{ - u8 *p; - - p = pDCTstat->DIMMAddr; - /* mct_BeforeGetDIMMAddress(); */ - return p[i]; -} - -static void mct_preInitDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 err_code; - uint8_t nvram; - uint8_t allow_config_restore; - - /* 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 */ - } - } - -#if CONFIG(HAVE_ACPI_RESUME) - calculate_and_store_spd_hashes(pMCTstat, pDCTstat); - - if (load_spd_hashes_from_nvram(pMCTstat, pDCTstat) < 0) { - pDCTstat->spd_data.nvram_spd_match = 0; - } else { - compare_nvram_spd_hashes(pMCTstat, pDCTstat); - } -#else - pDCTstat->spd_data.nvram_spd_match = 0; -#endif - - /* Check to see if restoration of SPD data from NVRAM is allowed */ - allow_config_restore = 0; - if (get_option(&nvram, "allow_spd_nvram_cache_restore") == CB_SUCCESS) - allow_config_restore = !!nvram; - -#if CONFIG(HAVE_ACPI_RESUME) - if (pMCTstat->nvram_checksum != calculate_nvram_mct_hash()) - allow_config_restore = 0; -#else - allow_config_restore = 0; -#endif - - if (!allow_config_restore) - pDCTstat->spd_data.nvram_spd_match = 0; -} - -static void mct_initDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u8 err_code; - - /* Config. DCT0 for Ganged or unganged mode */ - DCTInit_D(pMCTstat, pDCTstat, 0); - DCTFinalInit_D(pMCTstat, pDCTstat, 0); - if (pDCTstat->ErrCode == SC_FatalErr) { - /* Do nothing goto exitDCTInit; any fatal errors? */ - } else { - /* Configure DCT1 if unganged and enabled */ - if (!pDCTstat->GangedMode) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - err_code = pDCTstat->ErrCode; /* save DCT0 errors */ - pDCTstat->ErrCode = 0; - DCTInit_D(pMCTstat, pDCTstat, 1); - DCTFinalInit_D(pMCTstat, pDCTstat, 1); - if (pDCTstat->ErrCode == 2) /* DCT1 is not Running */ - pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */ - } else { - val = 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, 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); - } - } - } -} - -static void mct_DramInit(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat, dct); - mct_DramInit_Sw_D(pMCTstat, pDCTstat, dct); - /* mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct); */ -} - -static u8 mct_setMode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 byte; - u8 bytex; - u32 val; - u32 reg; - - byte = bytex = pDCTstat->DIMMValid; - bytex &= 0x55; /* CHA DIMM pop */ - pDCTstat->DIMMValidDCT[0] = bytex; - - byte &= 0xAA; /* CHB DIMM popa */ - byte >>= 1; - pDCTstat->DIMMValidDCT[1] = byte; - - if (byte != bytex) { - pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); - } else { - byte = mctGet_NVbits(NV_Unganged); - if (byte) - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); /* Set temp. to avoid setting of ganged mode */ - - 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; - reg = 0x110; - val = Get_NB32(pDCTstat->dev_dct, reg); - val |= 1 << DctGangEn; - Set_NB32(pDCTstat->dev_dct, reg, val); - } - if (byte) /* NV_Unganged */ - pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); /* Clear so that there is no DIMM mismatch error */ - } - - return pDCTstat->ErrCode; -} - -u32 Get_NB32(u32 dev, u32 reg) -{ - return pci_read_config32(dev, reg); -} - -void Set_NB32(u32 dev, u32 reg, u32 val) -{ - pci_write_config32(dev, reg, val); -} - - -u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index) -{ - u32 dword; - - Set_NB32(dev, index_reg, index); - dword = Get_NB32(dev, index_reg+0x4); - - return dword; -} - -void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data) -{ - Set_NB32(dev, index_reg, index); - Set_NB32(dev, index_reg + 0x4, 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 { - dword = Get_NB32(dev, index_reg); - } while (!(dword & (1 << DctAccessDone))); - dword = Get_NB32(dev, index_reg + 0x4); - - return dword; -} - -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); - do { - dword = Get_NB32(dev, index_reg); - } while (!(dword & (1 << DctAccessDone))); - -} - -u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* 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_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 >= 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_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D02E001, 0x90); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); - - return pDCTstat->ErrCode; -} - -u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Get platform specific config/timing values from the interface layer - * and program them into DCT. - */ - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - u32 dev = pDCTstat->dev_dct; - u32 index_reg; - u8 i, i_start, i_end; - - if (pDCTstat->GangedMode) { - SyncSetting(pDCTstat); - /* mct_SetupSync_D */ - i_start = 0; - i_end = 2; - } else { - i_start = dct; - i_end = dct + 1; - } - for (i = i_start; i < i_end; i++) { - index_reg = 0x98; - Set_NB32_index_wait_DCT(dev, i, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A/B Output Driver Compensation Control */ - Set_NB32_index_wait_DCT(dev, i, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A/B Output Driver Compensation Control */ - printk(BIOS_SPEW, "Programmed DCT %d timing/termination pattern %08x %08x\n", dct, pDCTstat->CH_ADDR_TMG[i], pDCTstat->CH_ODC_CTL[i]); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); - - return pDCTstat->ErrCode; -} - -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat) -{ - u32 dev; - u32 val; - - if (pDCTstat->NodePresent) { - dev = pDCTstat->dev_dct; - - if ((pDCTstat->DIMMValidDCT[0]) || (pDCTstat->DIMMValidDCT[1])) { - /* This Node has DRAM */ - do { - val = Get_NB32(dev, 0x110); - } while (!(val & (1 << DramEnabled))); - } - } /* Node is present */ -} - -static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (!pDCTstat->GangedMode) { - if (dct == 0) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - if (pDCTstat->DIMMValidDCT[dct] == 0) - pDCTstat->ErrCode = SC_StopError; - } else { - pDCTstat->CSPresent = 0; - pDCTstat->CSTestFail = 0; - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - if (pDCTstat->DIMMValidDCT[dct] == 0) - pDCTstat->ErrCode = SC_StopError; - } - } -} - -static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ret; - u32 val; - - if (dct == 0) { - SPDCalcWidth_D(pMCTstat, pDCTstat); - ret = mct_setMode(pMCTstat, pDCTstat); - } else { - ret = pDCTstat->ErrCode; - } - - if (pDCTstat->DIMMValidDCT[0] == 0) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - val |= 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - val &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val); - } - if (pDCTstat->DIMMValidDCT[1] == 0) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - val |= 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val); - } - - printk(BIOS_DEBUG, "SPDCalcWidth: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "SPDCalcWidth: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "SPDCalcWidth: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "SPDCalcWidth: Done\n"); - /* Disable dram interface before DRAM init */ - - return ret; -} - -static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dword; - u32 dev; - u32 reg; - u8 _MemHoleRemap; - u32 DramHoleBase; - - _MemHoleRemap = mctGet_NVbits(NV_MemHole); - DramHoleBase = mctGet_NVbits(NV_BottomIO); - DramHoleBase <<= 8; - /* Increase hole size so;[31:24]to[31:16] - * it has granularity of 128MB shl eax,8 - * Set 'effective' bottom IOmov DramHoleBase,eax - */ - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - - /* In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */ - if (!pDCTstat->GangedMode) { - dev = pDCTstat->dev_dct; - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - /* if DCT0 and DCT1 both exist, set DctSelBaseAddr[47:27] to the top of DCT0 */ - if (dct == 0) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - dword = pDCTstat->DCTSysLimit + 1; - dword += pDCTstat->NodeSysBase; - dword >>= 8; /* scale [39:8] to [47:27],and to F2x110[31:11] */ - if ((dword >= DramHoleBase) && _MemHoleRemap) { - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - val = pMCTstat->HoleBase; - val >>= 16; - val = (((~val) & 0xFF) + 1); - val <<= 8; - dword += val; - } - reg = 0x110; - val = Get_NB32(dev, reg); - val &= 0x7F; - val |= dword; - val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */ - Set_NB32(dev, reg, val); - - reg = 0x114; - val = dword; - Set_NB32(dev, reg, val); - } - } else { - /* Program the DctSelBaseAddr value to 0 - if DCT 0 is disabled */ - if (pDCTstat->DIMMValidDCT[0] == 0) { - dword = pDCTstat->NodeSysBase; - dword >>= 8; - if ((dword >= DramHoleBase) && _MemHoleRemap) { - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - val = pMCTstat->HoleBase; - val >>= 8; - val &= ~(0xFFFF); - val |= (((~val) & 0xFFFF) + 1); - dword += val; - } - reg = 0x114; - val = dword; - Set_NB32(dev, reg, val); - - reg = 0x110; - val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */ - Set_NB32(dev, reg, val); - } - } - } else { - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - } - printk(BIOS_DEBUG, "AfterStitch pDCTstat->NodeSysBase = %x\n", pDCTstat->NodeSysBase); - printk(BIOS_DEBUG, "mct_AfterStitchMemory: pDCTstat->NodeSysLimit = %x\n", pDCTstat->NodeSysLimit); -} - -static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ret; - - if (dct == 0) - ret = DIMMPresence_D(pMCTstat, pDCTstat); - else - ret = pDCTstat->ErrCode; - - return ret; -} - -/* mct_BeforeGetDIMMAddress inline in C */ - -static void mct_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - if (pDCTstat->DIMMValidDCT[0]) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[0]; - Set_OtherTiming(pMCTstat, pDCTstat, 0); - } - if (pDCTstat->DIMMValidDCT[1] && !pDCTstat->GangedMode) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[1]; - Set_OtherTiming(pMCTstat, pDCTstat, 1); - } - } /* Node is present*/ - } /* while Node */ -} - -static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg; - u32 val; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - 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); - - if (!is_fam15h()) { - reg = 0x8c; /* Dram Timing Hi */ - val = Get_NB32_DCT(dev, dct, reg); - val &= 0xffff0300; - dword = pDCTstat->TrwtTO; - val |= dword << 4; - dword = pDCTstat->Twrrd & 3; - val |= dword << 10; - dword = pDCTstat->Twrwr & 3; - val |= dword << 12; - dword = (pDCTstat->Trdrd - 0x3) & 3; - val |= dword << 14; - dword = pDCTstat->TrwtWB; - val |= dword; - Set_NB32_DCT(dev, dct, reg, val); - - reg = 0x78; - val = Get_NB32_DCT(dev, dct, reg); - val &= 0xffffc0ff; - dword = pDCTstat->Twrrd >> 2; - val |= dword << 8; - dword = pDCTstat->Twrwr >> 2; - val |= dword << 10; - dword = (pDCTstat->Trdrd - 0x3) >> 2; - val |= dword << 12; - Set_NB32_DCT(dev, dct, reg, val); - } -} - -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - int8_t Trdrd; - - Trdrd = ((int8_t)(pDCTstat->DqsRcvEnGrossMax - pDCTstat->DqsRcvEnGrossMin) >> 1) + 1; - if (Trdrd > 8) - Trdrd = 8; - if (Trdrd < 3) - Trdrd = 3; - pDCTstat->Trdrd = Trdrd; -} - -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - int8_t Twrwr = 0; - - Twrwr = ((int8_t)(pDCTstat->WrDatGrossMax - pDCTstat->WrDatGrossMin) >> 1) + 2; - - if (Twrwr < 2) - Twrwr = 2; - else if (Twrwr > 9) - Twrwr = 9; - - pDCTstat->Twrwr = Twrwr; -} - -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 LDplus1; - int8_t Twrrd; - - LDplus1 = Get_Latency_Diff(pMCTstat, pDCTstat, dct); - - Twrrd = ((int8_t)(pDCTstat->WrDatGrossMax - pDCTstat->DqsRcvEnGrossMin) >> 1) + 4 - LDplus1; - - if (Twrrd < 2) - Twrrd = 2; - else if (Twrrd > 10) - Twrrd = 10; - pDCTstat->Twrrd = Twrrd; -} - -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 LDplus1; - int8_t TrwtTO; - - LDplus1 = Get_Latency_Diff(pMCTstat, pDCTstat, dct); - - TrwtTO = ((int8_t)(pDCTstat->DqsRcvEnGrossMax - pDCTstat->WrDatGrossMin) >> 1) + LDplus1; - - pDCTstat->TrwtTO = TrwtTO; -} - -static void Get_TrwtWB(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* TrwtWB ensures read-to-write data-bus turnaround. - This value should be one more than the programmed TrwtTO.*/ - pDCTstat->TrwtWB = pDCTstat->TrwtTO; -} - -static u8 Get_Latency_Diff(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - u32 val1, val2; - - 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, uint8_t dct, u32 index_reg) -{ - u8 Smallest, Largest; - u32 val; - u8 byte, bytex; - - /* The largest DqsRcvEnGrossDelay of any DIMM minus the - DqsRcvEnGrossDelay of any other DIMM is equal to the Critical - Gross Delay Difference (CGDD) */ - /* DqsRcvEn byte 1,0 */ - 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, dct, index_reg, 0x11); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - /* DqsRcvEn byte 5,4 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x20); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - /* DqsRcvEn byte 7,6 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x21); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - if (pDCTstat->DimmECCPresent> 0) { - /*DqsRcvEn Ecc */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x12); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - - pDCTstat->DqsRcvEnGrossMax = Largest; - pDCTstat->DqsRcvEnGrossMin = Smallest; -} - -static void Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg) -{ - u8 Smallest = 0, Largest = 0; - u32 val; - u8 byte, bytex; - - /* The largest WrDatGrossDlyByte of any DIMM minus the - WrDatGrossDlyByte of any other DIMM is equal to CGDD */ - if (pDCTstat->DIMMValid & (1 << 0)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x01); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */ - Largest = val & 0xFF; - Smallest = (val >> 8) & 0xFF; - } - if (pDCTstat->DIMMValid & (1 << 2)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x101); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM1 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - - /* If Cx, 2 more dimm need to be checked to find out the largest and smallest */ - if (pDCTstat->LogicalCPUID & AMD_DR_Cx) { - if (pDCTstat->DIMMValid & (1 << 4)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x201); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM2 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - if (pDCTstat->DIMMValid & (1 << 6)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x301); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM2 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - } - - pDCTstat->WrDatGrossMax = Largest; - pDCTstat->WrDatGrossMin = Smallest; -} - -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, uint8_t dct, u32 index_reg, - u32 index) -{ - u8 Smallest, Largest; - u8 i; - u8 byte; - u32 val; - u16 word; - u8 ecc_reg = 0; - - Smallest = 7; - Largest = 0; - - if (index == 0x12) - ecc_reg = 1; - - for (i = 0; i < 8; i+=2) { - if (pDCTstat->DIMMValid & (1 << i)) { - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - val &= 0x00E000E0; - byte = (val >> 5) & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - if (!(ecc_reg)) { - byte = (val >> (16 + 5)) & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - } - } - index += 3; - } /* while ++i */ - - word = Smallest; - word <<= 8; - word |= Largest; - - return word; -} - -static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg, - u32 index) -{ - u8 Smallest, Largest; - u8 i, j; - u32 val; - u8 byte; - u16 word; - - Smallest = 3; - Largest = 0; - for (i = 0; i < 2; i++) { - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - val &= 0x60606060; - val >>= 5; - for (j = 0; j < 4; j++) { - byte = val & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - val >>= 8; - } /* while ++j */ - index++; - } /*while ++i*/ - - if (pDCTstat->DimmECCPresent > 0) { - index++; - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - val &= 0x00000060; - val >>= 5; - byte = val & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - } - - word = Smallest; - word <<= 8; - word |= Largest; - - return word; -} - -static void mct_PhyController_Config(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - uint8_t index; - uint32_t dword; - u32 index_reg = 0x98; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3 | AMD_RB_C3 | AMD_FAM15_ALL)) { - if (is_fam15h()) { - /* Set F2x[1, 0]98_x0D0F0F13 DllDisEarlyU and DllDisEarlyL to save power */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8)); - dword |= (0x1 << 1); /* DllDisEarlyU = 1 */ - dword |= 0x1; /* DllDisEarlyL = 1 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8), dword); - } - } - - if (pDCTstat->Dimmx4Present == 0) { - /* 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 | AMD_FAM15_ALL)) { - if (pDCTstat->DimmECCPresent == 0) { - /* Set bit4 PwrDn to register F2x[1, 0]98_x0D0F0830 for power saving */ - 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); - } - } - -} - -static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - mct_PhyController_Config(pMCTstat, pDCTstat, 0); - mct_PhyController_Config(pMCTstat, pDCTstat, 1); - - if (!is_fam15h()) { - /* Family 10h CPUs */ - mct_ExtMCTConfig_Cx(pDCTstat); - mct_ExtMCTConfig_Bx(pDCTstat); - mct_ExtMCTConfig_Dx(pDCTstat); - } else { - /* Family 15h CPUs */ - uint8_t nvram; - uint8_t enable_experimental_memory_speed_boost; - - /* Check to see if cache partitioning is allowed */ - enable_experimental_memory_speed_boost = 0; - if (get_option(&nvram, "experimental_memory_speed_boost") == CB_SUCCESS) - enable_experimental_memory_speed_boost = !!nvram; - - val = 0x0ce00f00; /* FlushWrOnStpGnt = 0x0 */ - val |= 0x10 << 2; /* MctWrLimit = 0x10 */ - val |= 0x1; /* DctWrLimit = 0x1 */ - Set_NB32(pDCTstat->dev_dct, 0x11c, val); - - val = Get_NB32(pDCTstat->dev_dct, 0x1b0); - val &= ~0x3; /* AdapPrefMissRatio = 0x1 */ - val |= 0x1; - val &= ~(0x3 << 2); /* AdapPrefPositiveStep = 0x0 */ - val &= ~(0x3 << 4); /* AdapPrefNegativeStep = 0x0 */ - val &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x1 */ - val |= (0x1 << 8); - val |= (0x1 << 12); /* EnSplitDctLimits = 0x1 */ - if (enable_experimental_memory_speed_boost) - val |= (0x1 << 20); /* DblPrefEn = 0x1 */ - val |= (0x7 << 22); /* PrefFourConf = 0x7 */ - val |= (0x7 << 25); /* PrefFiveConf = 0x7 */ - val &= ~(0xf << 28); /* DcqBwThrotWm = 0x0 */ - Set_NB32(pDCTstat->dev_dct, 0x1b0, val); - - 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); - } - } - } - - /* ClrClToNB_D postponed until we're done executing from ROM */ - mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat); - - /* set F3x8C[DisFastTprWr] on all DR, if L3Size = 0 */ - if (pDCTstat->LogicalCPUID & AMD_DR_ALL) { - if (!(cpuid_edx(0x80000006) & 0xFFFC0000)) { - val = Get_NB32(pDCTstat->dev_nbmisc, 0x8C); - val |= 1 << 24; - Set_NB32(pDCTstat->dev_nbmisc, 0x8C, val); - } - } -} - -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); - - if (!is_model10_1f()) { - /* 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); - - if (!is_model10_1f()) { - /* 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) -{ - 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(PSTATE_0_MSR + 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; - - printk(BIOS_DEBUG, "mct_InitialMCT_D: mct_ForceNBPState0_En_Fam15\n"); - 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; - if (is_fam15h()) { - if (is_model10_1f()) { - val = 0x14001022; - } else { - val = 0x16001022; - } - } else { - val = 0x12001022; - } - return val; -} - -static void mct_init(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 addr; - - pDCTstat->GangedMode = 0; - pDCTstat->DRPresent = 1; - - /* enable extend PCI configuration access */ - addr = NB_CFG_MSR; - _RDMSR(addr, &lo, &hi); - if (hi & (1 << (46-32))) { - pDCTstat->Status |= 1 << SB_ExtConfig; - } else { - hi |= 1 << (46-32); - _WRMSR(addr, lo, hi); - } -} - -static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 dev = pDCTstat->dev_dct; - - /* Clear Legacy BIOS Mode bit */ - reg = 0x94; - val = Get_NB32_DCT(dev, 0, reg); - val &= ~(1<<LegacyBiosMode); - Set_NB32_DCT(dev, 0, reg, val); - - val = Get_NB32_DCT(dev, 1, reg); - val &= ~(1<<LegacyBiosMode); - Set_NB32_DCT(dev, 1, reg, val); -} - -static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u32 Drambase, Dramlimit; - u32 val; - u32 reg; - u32 dev; - u32 devx; - u32 dword; - struct DCTStatStruc *pDCTstat; - - pDCTstat = pDCTstatA + 0; - dev = pDCTstat->dev_map; - - /* Copy dram map from F1x40/44,F1x48/4c, - to F1x120/124(Node0),F1x120/124(Node1),...*/ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - - /* get base/limit from Node0 */ - reg = 0x40 + (Node << 3); /* Node0/Dram Base 0 */ - val = Get_NB32(dev, reg); - Drambase = val >> (16 + 3); - - reg = 0x44 + (Node << 3); /* Node0/Dram Base 0 */ - val = Get_NB32(dev, reg); - Dramlimit = val >> (16 + 3); - - /* set base/limit to F1x120/124 per Node */ - if (pDCTstat->NodePresent) { - reg = 0x120; /* F1x120,DramBase[47:27] */ - val = Get_NB32(devx, reg); - val &= 0xFFE00000; - val |= Drambase; - Set_NB32(devx, reg, val); - - reg = 0x124; - val = Get_NB32(devx, reg); - val &= 0xFFE00000; - val |= Dramlimit; - Set_NB32(devx, reg, val); - - if (pMCTstat->GStatus & (1 << GSB_HWHole)) { - reg = 0xF0; - val = Get_NB32(devx, reg); - val |= (1 << DramMemHoistValid); - val &= ~(0xFF << 24); - dword = (pMCTstat->HoleBase >> (24 - 8)) & 0xFF; - dword <<= 24; - val |= dword; - Set_NB32(devx, reg, val); - } - - } - } -} - -static void SetCSTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98; - u16 word; - - if (is_fam15h()) { - word = fam15h_cs_tristate_enable_code(pDCTstat, dct); - } else { - /* Tri-state unused chipselects when motherboard - termination is available */ - - /* FIXME: skip for Ax */ - - word = pDCTstat->CSPresent; - if (pDCTstat->Status & (1 << SB_Registered)) { - word |= (word & 0x55) << 1; - } - word = (~word) & 0xff; - } - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - val &= ~0xff; - val |= word; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val); -} - -static void SetCKETriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98; - u16 word; - - /* Tri-state unused CKEs when motherboard termination is available */ - - /* FIXME: skip for Ax */ - - dev = pDCTstat->dev_dct; - word = pDCTstat->CSPresent; - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - val &= ~(0x3 << 12); - if ((word & 0x55) == 0) - val |= 1 << 12; - if ((word & 0xaa) == 0) - val |= 1 << 13; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val); -} - -static void SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98; - u8 cs; - u8 odt; - - dev = pDCTstat->dev_dct; - - if (is_fam15h()) { - odt = fam15h_odt_tristate_enable_code(pDCTstat, dct); - } else { - /* FIXME: skip for Ax */ - - /* Tri-state unused ODTs when motherboard termination is available */ - odt = 0x0f; /* ODT tri-state setting */ - - if (pDCTstat->Status & (1 <<SB_Registered)) { - for (cs = 0; cs < 8; cs += 2) { - if (pDCTstat->CSPresent & (1 << cs)) { - odt &= ~(1 << (cs / 2)); - if (mctGet_NVbits(NV_4RANKType) != 0) { /* quad-rank capable platform */ - if (pDCTstat->CSPresent & (1 << (cs + 1))) - odt &= ~(4 << (cs / 2)); - } - } - } - } else { /* AM3 package */ - val = ~(pDCTstat->CSPresent); - odt = val & 9; /* swap bits 1 and 2 */ - if (val & (1 << 1)) - odt |= 1 << 2; - if (val & (1 << 2)) - odt |= 1 << 1; - } - } - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - val &= ~(0xf << 8); /* ODTTri = odt */ - val |= (odt & 0xf) << 8; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, 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 - */ - 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] */ - /* NOTE: CmpVioLvl and ComparatorAdjust only take effect when set on DCT 0 */ - dword = Get_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0f4009); - dword &= ~(0x0000c00c); - dword |= (amd_voltage_level_index << 14); - dword |= (amd_voltage_level_index << 2); - Set_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0f4009, dword); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u32 index_reg = 0x98; - u32 dev = pDCTstat->dev_dct; - u32 valx = 0; - uint8_t index; - uint32_t dword; - const u8 *p; - - printk(BIOS_DEBUG, "%s: DCT %d: Start\n", __func__, dct); - - 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] */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003); - dword |= (0x1 << 14); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003, dword); - - /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisablePredriverCal] */ - /* NOTE: DisablePredriverCal only takes effect when set on DCT 0 */ - dword = Get_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0fe003); - dword |= (0x1 << 13); - Set_NB32_index_wait_DCT(dev, 0, 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8), dword); - } - - /* 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - 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 &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202, dword); - - if (!is_model10_1f()) { - /* Be extra safe and wait for the predriver calibration - * to be applied to the hardware. The BKDG does not - * require this, but it does take some time for the - * data to propagate, so it's probably a good idea. - */ - uint8_t predriver_cal_pending = 1; - printk(BIOS_DEBUG, "Waiting for predriver calibration to be applied..."); - while (predriver_cal_pending) { - predriver_cal_pending = 0; - for (index = 0; index < 0x9; index++) { - if (Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8)) & 0x8000) - predriver_cal_pending = 1; - } - } - printk(BIOS_DEBUG, "done!\n"); - } - } 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); - } - - printk(BIOS_DEBUG, "%s: DCT %d: Done\n", __func__, dct); -} - -static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - 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); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 tmp; - u32 rem; - u32 dev = pDCTstat->dev_dct; - u32 hi, lo; - u8 NbDid = 0; - - /* Check if NB COF >= 4*Memclk, if it is not, return a fatal error - */ - - /* 3*(Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */ - _RDMSR(MSR_COFVID_STS, &lo, &hi); - if (lo & (1 << 22)) - NbDid |= 1; - - reg = 0x94; - val = Get_NB32_DCT(dev, 0, reg); - if (!(val & (1 << MemClkFreqVal))) - val = Get_NB32_DCT(dev, 1, reg); /* get the DCT1 value */ - - val &= 0x07; - val += 3; - if (NbDid) - val <<= 1; - tmp = val; - - dev = pDCTstat->dev_nbmisc; - reg = 0xD4; - val = Get_NB32(dev, reg); - val &= 0x1F; - val += 3; - val *= 3; - val = val / tmp; - rem = val % tmp; - tmp >>= 1; - - /* Yes this could be nicer but this was how the asm was.... */ - if (val < 3) { /* NClk:MemClk < 3:1 */ - return 0; - } else if (val > 4) { /* NClk:MemClk >= 5:1 */ - return 0; - } else if ((val == 4) && (rem > tmp)) { /* NClk:MemClk > 4.5:1 */ - return 0; - } else { - return 1; /* 3:1 <= NClk:MemClk <= 4.5:1*/ - } -} - -static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - uint8_t Node; - struct DCTStatStruc *pDCTstat; - - /* Initialize Data structures by clearing all entries to 0 */ - memset(pMCTstat, 0, sizeof(*pMCTstat)); - - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - memset(pDCTstat, 0, sizeof(*pDCTstat) - sizeof(pDCTstat->persistentData)); - } -} - -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - mct_ProgramODT_D(pMCTstat, pDCTstat, dct); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - 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; - - /* NOTE - * Rank count per DIMM and DCT is encoded by pDCTstat->DimmRanks[(<dimm number> * 2) + dct] - */ - - /* Select appropriate ODT pattern for installed DIMMs - * Refer to the Fam15h BKDG Rev. 3.14, page 149 onwards - */ - if (pDCTstat->Status & (1 << SB_Registered)) { - if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - 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->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - 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->Status & (1 << SB_LoadReduced)) { - /* 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->DimmRanks[(1 * 2) + dct]; - 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->Status & (1 << SB_LoadReduced)) { - /* 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); - - printk(BIOS_SPEW, "Programmed DCT %d ODT pattern %08x %08x %08x %08x\n", dct, odt_pattern_0, odt_pattern_1, odt_pattern_2, odt_pattern_3); - } else if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - if (pDCTstat->Speed == 3) - dword = 0x00000800; - else - dword = 0x00000000; - for (i = 0; i < 2; i++) { - 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]; - 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; - - /* Select appropriate ODT pattern for installed DIMMs - * Refer to the Fam10h BKDG Rev. 3.62, page 120 onwards - */ - if (pDCTstat->Status & (1 << SB_Registered)) { - if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + i]; - 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 = 0x02080000; - } 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 = 0x00000000; - } - } else { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + i]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + i]; - 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 (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + i]; - 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 = 0x02080000; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } 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; - } - } - - /* Program ODT pattern */ - 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); - - printk(BIOS_SPEW, "Programmed ODT pattern %08x %08x %08x %08x\n", odt_pattern_0, odt_pattern_1, odt_pattern_2, odt_pattern_3); - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 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_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_DCT(dev, dct, 0x90); - val &= ~(1 << 27/* DisDllShutdownSR */); - Set_NB32_DCT(dev, dct, 0x90, val); - } -} - -static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 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_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; - } - - return DramConfigLo; -} - -void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG2_MSR; - _RDMSR(msr, &lo, &hi); - lo |= 1 << ClLinesToNbDis; - _WRMSR(msr, lo, hi); -} - -void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG2_MSR; - _RDMSR(msr, &lo, &hi); - if (!pDCTstat->ClToNB_flag) - lo &= ~(1<<ClLinesToNbDis); - _WRMSR(msr, lo, hi); - -} - -void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG_MSR; - _RDMSR(msr, &lo, &hi); - hi |= (1 << WbEnhWsbDis_D); - _WRMSR(msr, lo, hi); -} - -void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG_MSR; - _RDMSR(msr, &lo, &hi); - hi &= ~(1 << WbEnhWsbDis_D); - _WRMSR(msr, lo, hi); -} - -void ProgDramMRSReg_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 DramMRS, dword; - u8 byte; - - DramMRS = 0; - - /* Set chip select CKE control mode */ - if (mctGet_NVbits(NV_CKE_CTL)) { - if (pDCTstat->CSPresent == 3) { - u16 word; - word = pDCTstat->DIMMSPDCSE; - if (dct == 0) - word &= 0b01010100; - else - word &= 0b10101000; - if (word == 0) - DramMRS |= 1 << 23; - } - } - - 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; - } - } 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; - - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x84); - if (is_fam15h()) { - dword &= ~0x00800003; - dword |= DramMRS; - } else { - dword &= ~0x00fc2f8f; - dword |= DramMRS; - } - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x84, dword); -} - -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: - * Solution: From the bug report: - * 1. A software-initiated frequency change should be wrapped into the - * following sequence : - * a) Disable Compensation (F2[1, 0]9C_x08[30]) - * b) Reset the Begin Compensation bit (D3CMP->COMP_CONFIG[0]) in - * all the compensation engines - * c) Do frequency change - * d) Enable Compensation (F2[1, 0]9C_x08[30]) - * 2. A software-initiated Disable Compensation should always be - * followed by step b) of the above steps. - * Silicon Status: Fixed In Rev B0 - * - * Errata#177: DRAM Phy Automatic Compensation Updates May Be Invalid - * Solution: BIOS should disable the phy automatic compensation prior - * to initiating a memory clock frequency change as follows: - * 1. Disable PhyAutoComp by writing 1'b1 to F2x[1, 0]9C_x08[30] - * 2. Reset the Begin Compensation bits by writing 32'h0 to - * F2x[1, 0]9C_x4D004F00 - * 3. Perform frequency change - * 4. Enable PhyAutoComp by writing 1'b0 to F2x[1, 0]9C_08[30] - * In addition, any time software disables the automatic phy - * compensation it should reset the begin compensation bit per step 2. - * Silicon Status: Fixed in DR-B0 - */ - - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98; - u32 index; - - uint32_t dword; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - if (is_fam15h()) { - /* Initial setup for frequency change - * 9C_x0000_0004 must be configured before MemClkFreqVal is set - */ - - /* 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); - - dword = Get_NB32_DCT(dev, dct, 0x94); - dword &= ~(1 << MemClkFreqVal); - Set_NB32_DCT(dev, dct, 0x94, dword); - - 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); - } - - printk(BIOS_DEBUG, "mct_SetDramConfigHi_D: DramConfigHi: %08x\n", DramConfigHi); - - /* 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 { - printk(BIOS_DEBUG, "*"); - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94); - } while (dword & (1 << FreqChgInProg)); - printk(BIOS_DEBUG, "\n"); - - /* 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); - } - - /* Clear MC4 error status */ - pci_write_config32(pDCTstat->dev_nbmisc, 0x48, 0x0); - pci_write_config32(pDCTstat->dev_nbmisc, 0x4c, 0x0); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - 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; - - if (pDCTstat->NodePresent) { - mct_BeforeDQSTrainSamp(pDCTstat); /* only Bx */ - mct_ResetDLL_D(pMCTstat, pDCTstat, 0); - mct_ResetDLL_D(pMCTstat, pDCTstat, 1); - } - } - } -} - -/* Erratum 350 */ -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Receiver; - u32 dev = pDCTstat->dev_dct; - u32 addr; - u32 lo, hi; - u8 wrap32dis = 0; - u8 valid = 0; - - /* Skip reset DLL for B3 */ - if (pDCTstat->LogicalCPUID & AMD_DR_B3) { - return; - } - - /* Skip reset DLL for Family 15h */ - if (is_fam15h()) { - return; - } - - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - if (lo & (1<<17)) { /* save the old value */ - wrap32dis = 1; - } - lo |= (1<<17); /* HWCR.wrap32dis */ - /* Setting wrap32dis allows 64-bit memory references in 32bit mode */ - _WRMSR(addr, lo, hi); - - pDCTstat->Channel = dct; - Receiver = mct_InitReceiver_D(pDCTstat, dct); - /* there are four receiver pairs, loosely associated with chipselects.*/ - for (; Receiver < 8; Receiver += 2) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) { - addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, dct, Receiver, &valid); - if (valid) { - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr); /* cache fills */ - - /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */ - 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_DCT(dev, dct, 0x98, 0xD080F0C, 0x00000000); - mct_Wait(800); /* wait >= 2us */ - break; - } - } - } - - if (!wrap32dis) { - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - _WRMSR(addr, lo, hi); - } -} - -void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - /* Enable F2x110[DctDatIntlv] */ - /* Call back not required mctHookBeforeDatIntlv_D() */ - /* FIXME Skip for Ax */ - if (!pDCTstat->GangedMode) { - val = Get_NB32(dev, 0x110); - val |= 1 << 5; /* DctDatIntlv */ - Set_NB32(dev, 0x110, val); - - /* FIXME Skip for Cx */ - dev = pDCTstat->dev_nbmisc; - val = Get_NB32(dev, 0x8C); /* NB Configuration Hi */ - val |= 1 << (36-32); /* DisDatMask */ - Set_NB32(dev, 0x8C, val); - } -} - -void SetDllSpeedUp_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - 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); - } - } -} - -static void SyncSetting(struct DCTStatStruc *pDCTstat) -{ - /* set F2x78[ChSetupSync] when F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, - * CkeSetup] setups for one DCT are all 0s and at least one of the setups, - * F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, CkeSetup], of the other - * controller is 1 - */ - u32 cha, chb; - u32 dev = pDCTstat->dev_dct; - u32 val; - - cha = pDCTstat->CH_ADDR_TMG[0] & 0x0202020; - chb = pDCTstat->CH_ADDR_TMG[1] & 0x0202020; - - if ((cha != chb) && ((cha == 0) || (chb == 0))) { - val = Get_NB32(dev, 0x78); - val |= 1 << ChSetupSync; - Set_NB32(dev, 0x78, val); - } -} - -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) { - - u32 val; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) { - mct_Wait(10000); /* Wait 50 us*/ - val = Get_NB32(dev, 0x110); - if (!(val & (1 << DramEnabled))) { - /* If 50 us expires while DramEnable =0 then do the following */ - val = Get_NB32_DCT(dev, dct, 0x90); - val &= ~(1 << Width128); /* Program Width128 = 0 */ - Set_NB32_DCT(dev, dct, 0x90, val); - - val = Get_NB32_index_wait_DCT(dev, dct, 0x98, 0x05); /* Perform dummy CSR read to F2x09C_x05 */ - - if (pDCTstat->GangedMode) { - val = Get_NB32_DCT(dev, dct, 0x90); - val |= 1 << Width128; /* Program Width128 = 0 */ - Set_NB32_DCT(dev, dct, 0x90, val); - } - } - } -} - -/* ========================================================== - * 6-bit Bank Addressing Table - * RR = rows-13 binary - * B = Banks-2 binary - * CCC = Columns-9 binary - * ========================================================== - * DCT CCCBRR Rows Banks Columns 64-bit CS Size - * Encoding - * 0000 000000 13 2 9 128MB - * 0001 001000 13 2 10 256MB - * 0010 001001 14 2 10 512MB - * 0011 010000 13 2 11 512MB - * 0100 001100 13 3 10 512MB - * 0101 001101 14 3 10 1GB - * 0110 010001 14 2 11 1GB - * 0111 001110 15 3 10 2GB - * 1000 010101 14 3 11 2GB - * 1001 010110 15 3 11 4GB - * 1010 001111 16 3 10 4GB - * 1011 010111 16 3 11 8GB - */ -uint8_t crcCheck(struct DCTStatStruc *pDCTstat, uint8_t dimm) -{ - u16 crc_calc = spd_ddr3_calc_crc(pDCTstat->spd_data.spd_bytes[dimm], - sizeof(pDCTstat->spd_data.spd_bytes[dimm])); - u16 checksum_spd = pDCTstat->spd_data.spd_bytes[dimm][SPD_byte_127] << 8 - | pDCTstat->spd_data.spd_bytes[dimm][SPD_byte_126]; - - return crc_calc == checksum_spd; -} - -int32_t abs(int32_t val) -{ - if (val < 0) - return -val; - return val; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h deleted file mode 100644 index 952a66f71a..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015-2017 Raptor Engineering, LLC - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -/* - * Description: Include file for all generic DDR 3 MCT files. - */ -#ifndef MCT_D_H -#define MCT_D_H - -#define DQS_TRAIN_DEBUG 0 - -#include <stdint.h> -#include <northbridge/amd/amdfam10/raminit.h> - -/*=========================================================================== - CPU - K8/FAM10 -===========================================================================*/ -#define PT_L1 0 /* CPU Package Type */ -#define PT_M2 1 -#define PT_S1 2 -#define PT_GR 3 -#define PT_AS 4 -#define PT_C3 5 -#define PT_FM2 6 - -#define J_MIN 0 /* j loop constraint. 1 = CL 2.0 T*/ -#define J_MAX 5 /* j loop constraint. 5 = CL 7.0 T*/ -#define K_MIN 1 /* k loop constraint. 1 = 200 MHz*/ -#define K_MAX 5 /* k loop constraint. 5 = 533 MHz*/ -#define CL_DEF 2 /* Default value for failsafe operation. 2 = CL 4.0 T*/ -#define T_DEF 1 /* Default value for failsafe operation. 1 = 5ns (cycle time)*/ - -#define BSCRate 1 /* reg bit field = rate of dram scrubber for ecc*/ - /* memory initialization (ecc and check-bits).*/ - /* 1 = 40 ns/64 bytes.*/ -#define FirstPass 1 /* First pass through RcvEn training*/ -#define SecondPass 2 /* Second pass through Rcven training*/ - -#define RCVREN_MARGIN 6 /* number of DLL taps to delay beyond first passing position*/ -#define MAXASYNCLATCTL_2 2 /* Max Async Latency Control value*/ -#define MAXASYNCLATCTL_3 3 /* Max Async Latency Control value*/ - -#define DQS_FAIL 1 -#define DQS_PASS 0 -#define DQS_WRITEDIR 1 -#define DQS_READDIR 0 -#define MIN_DQS_WNDW 3 -#define secPassOffset 6 -#define Pass1MemClkDly 0x20 /* Add 1/2 Memlock delay */ -#define MAX_RD_LAT 0x3FF -#define MIN_FENCE 14 -#define MAX_FENCE 20 -#define MIN_DQS_WR_FENCE 14 -#define MAX_DQS_WR_FENCE 20 -#define FenceTrnFinDlySeed 19 -#define EarlyArbEn 19 - -#define PA_HOST(Node) ((((0x18+Node) << 3)+0) << 12) /* Node 0 Host Bus function PCI Address bits [15:0]*/ -#define PA_MAP(Node) ((((0x18+Node) << 3)+1) << 12) /* Node 0 MAP function PCI Address bits [15:0]*/ -#define PA_DCT(Node) ((((0x18+Node) << 3)+2) << 12) /* Node 0 DCT function PCI Address bits [15:0]*/ -/* #define PA_EXT_DCT (((00 << 3)+4) << 8) */ /*Node 0 DCT extended configuration registers*/ -/* #define PA_DCTADDL (((00 << 3)+2) << 8) */ /*Node x DCT function, Additional Registers PCI Address bits [15:0]*/ -/* #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]*/ -#define ILD_Lmt 3 /* X:2:0x94[18:16]*/ - -#define EncodedTSPD 0x00191709 /* encodes which SPD byte to get T from*/ - /* versus CL X, CL X-.5, and CL X-1*/ - -#define Bias_TrpT 5 /* bias to convert bus clocks to bit field value*/ -#define Bias_TrrdT 4 -#define Bias_TrcdT 5 -#define Bias_TrasT 15 -#define Bias_TrcT 11 -#define Bias_TrtpT 4 -#define Bias_TwrT 4 -#define Bias_TwtrT 4 -#define Bias_TfawT 14 - -#define Min_TrpT 5 /* min programmable value in busclocks */ -#define Max_TrpT 12 /* max programmable value in busclocks */ -#define Min_TrrdT 4 -#define Max_TrrdT 7 -#define Min_TrcdT 5 -#define Max_TrcdT 12 -#define Min_TrasT 15 -#define Max_TrasT 30 -#define Min_TrcT 11 -#define Max_TrcT 42 -#define Min_TrtpT 4 -#define Max_TrtpT 7 -#define Min_TwrT 5 -#define Max_TwrT 12 -#define Min_TwtrT 4 -#define Max_TwtrT 7 -#define Min_TfawT 16 -#define Max_TfawT 32 - -/*common register bit names*/ -#define DramHoleValid 0 /* func 1, offset F0h, bit 0*/ -#define DramMemHoistValid 1 /* func 1, offset F0h, bit 1*/ -#define CSEnable 0 /* func 2, offset 40h-5C, bit 0*/ -#define Spare 1 /* func 2, offset 40h-5C, bit 1*/ -#define TestFail 2 /* func 2, offset 40h-5C, bit 2*/ -#define DqsRcvEnTrain 18 /* func 2, offset 78h, bit 18*/ -#define EnDramInit 31 /* func 2, offset 7Ch, bit 31*/ -#define PchgPDModeSel 23 /* func 2, offset 84h, bit 23 */ -#define DisAutoRefresh 18 /* func 2, offset 8Ch, bit 18*/ -#define InitDram 0 /* func 2, offset 90h, bit 0*/ -#define BurstLength32 10 /* func 2, offset 90h, bit 10*/ -#define Width128 11 /* func 2, offset 90h, bit 11*/ -#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 ((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*/ -#define DctAccessWrite 30 /* func 2, offset 98h, bit 30*/ -#define DctAccessDone 31 /* func 2, offset 98h, bit 31*/ -#define MemClrStatus 0 /* func 2, offset A0h, bit 0*/ -#define PwrSavingsEn 10 /* func 2, offset A0h, bit 10*/ -#define Mod64BitMux 4 /* func 2, offset A0h, bit 4*/ -#define DisableJitter 1 /* func 2, offset A0h, bit 1*/ -#define MemClrDis 1 /* func 3, offset F8h, FNC 4, bit 1*/ -#define SyncOnUcEccEn 2 /* func 3, offset 44h, bit 2*/ -#define Dr_MemClrStatus 10 /* func 3, offset 110h, bit 10*/ -#define MemClrBusy 9 /* func 3, offset 110h, bit 9*/ -#define DctGangEn 4 /* func 3, offset 110h, bit 4*/ -#define MemClrInit 3 /* func 3, offset 110h, bit 3*/ -#define SendZQCmd 29 /* func 2, offset 7Ch, bit 29 */ -#define AssertCke 28 /* func 2, offset 7Ch, bit 28*/ -#define DeassertMemRstX 27 /* func 2, offset 7Ch, bit 27*/ -#define SendMrsCmd 26 /* func 2, offset 7Ch, bit 26*/ -#define SendAutoRefresh 25 /* func 2, offset 7Ch, bit 25*/ -#define SendPchgAll 24 /* func 2, offset 7Ch, bit 24*/ -#define DisDqsBar 6 /* func 2, offset 90h, bit 6*/ -#define DramEnabled 8 /* func 2, offset 110h, bit 8*/ -#define LegacyBiosMode 9 /* func 2, offset 94h, bit 9*/ -#define PrefDramTrainMode 28 /* func 2, offset 11Ch, bit 28*/ -#define FlushWr 30 /* func 2, offset 11Ch, bit 30*/ -#define DisAutoComp 30 /* func 2, offset 9Ch, Index 8, bit 30*/ -#define DqsRcvTrEn 13 /* func 2, offset 9Ch, Index 8, bit 13*/ -#define ForceAutoPchg 23 /* func 2, offset 90h, bit 23*/ -#define ClLinesToNbDis 15 /* Bu_CFG2, bit 15*/ -#define WbEnhWsbDis_D (48-32) -#define PhyFenceTrEn 3 /* func 2, offset 9Ch, Index 8, bit 3 */ -#define ParEn 8 /* func 2, offset 90h, bit 8 */ -#define DcqArbBypassEn 19 /* func 2, offset 94h, bit 19 */ -#define ActiveCmdAtRst 1 /* func 2, offset A8H, bit 1 */ -#define FlushWrOnStpGnt 29 /* func 2, offset 11Ch, bit 29 */ -#define BankSwizzleMode 22 /* func 2, offset 94h, bit 22 */ -#define ChSetupSync 15 /* func 2, offset 78h, bit 15 */ - -#define Ddr3Mode 8 /* func 2, offset 94h, bit 8 */ -#define EnterSelfRef 17 /* func 2, offset 90h, bit 17 */ -#define onDimmMirror 3 /* func 2, offset 5C:40h, bit 3 */ -#define OdtSwizzle 6 /* func 2, offset A8h, bit 6 */ -#define FreqChgInProg 21 /* func 2, offset 94h, bit 21 */ -#define ExitSelfRef 1 /* func 2, offset 90h, bit 1 */ - -#define SubMemclkRegDly 5 /* func 2, offset A8h, bit 5 */ -#define Ddr3FourSocketCh 2 /* func 2, offset A8h, bit 2 */ -#define SendControlWord 30 /* func 2, offset 7Ch, bit 30 */ - -#define NB_GfxNbPstateDis 62 /* MSRC001_001F Northbridge Configuration Register (NB_CFG) bit 62 GfxNbPstateDis disable northbridge p-state transitions */ -/*============================================================================= - SW Initialization -============================================================================*/ -#define DLL_Enable 1 -#define OCD_Default 2 -#define OCD_Exit 3 - -/*============================================================================= - Jedec DDR II -=============================================================================*/ -#define SPD_ByteUse 0 -#define SPD_TYPE 2 /*SPD byte read location*/ - #define JED_DDRSDRAM 0x07 /*Jedec defined bit field*/ - #define JED_DDR2SDRAM 0x08 /*Jedec defined bit field*/ - #define JED_DDR3SDRAM 0x0B /* Jedec defined bit field*/ - -#define SPD_DIMMTYPE 3 -#define SPD_ATTRIB 21 - #define JED_DIFCKMSK 0x20 /*Differential Clock Input*/ - #define JED_REGADCMSK 0x11 /*Registered Address/Control*/ - #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 */ -#define SPD_Organization 7 /* rank#,Device width */ -#define SPD_BusWidth 8 /* ECC, Bus width */ - #define JED_ECC 8 /* ECC capability */ - -#define SPD_MTBDividend 10 -#define SPD_MTBDivisor 11 -#define SPD_tCKmin 12 -#define SPD_CASLow 14 -#define SPD_CASHigh 15 -#define SPD_tAAmin 16 - -#define SPD_DEVATTRIB 22 -#define SPD_EDCTYPE 11 - #define JED_ADRCPAR 0x04 - -#define SPD_tWRmin 17 -#define SPD_tRCDmin 18 -#define SPD_tRRDmin 19 -#define SPD_tRPmin 20 -#define SPD_Upper_tRAS_tRC 21 -#define SPD_tRASmin 22 -#define SPD_tRCmin 23 -#define SPD_tWTRmin 26 -#define SPD_tRTPmin 27 -#define SPD_Upper_tFAW 28 -#define SPD_tFAWmin 29 -#define SPD_Thermal 31 - -#define SPD_RefRawCard 62 -#define SPD_AddressMirror 63 -#define SPD_RegManufactureID_L 65 /* not used */ -#define SPD_RegManufactureID_H 66 /* not used */ -#define SPD_RegManRevID 67 /* not used */ - -#define SPD_byte_126 126 -#define SPD_byte_127 127 - -#define SPD_ROWSZ 3 -#define SPD_COLSZ 4 -#define SPD_LBANKS 17 /*number of [logical] banks on each device*/ -#define SPD_DMBANKS 5 /*number of physical banks on dimm*/ - #define SPDPLBit 4 /* Dram package bit*/ -#define SPD_BANKSZ 31 /*capacity of physical bank*/ -#define SPD_DEVWIDTH 13 -#define SPD_CASLAT 18 -#define SPD_TRP 27 -#define SPD_TRRD 28 -#define SPD_TRCD 29 -#define SPD_TRAS 30 -#define SPD_TWR 36 -#define SPD_TWTR 37 -#define SPD_TRTP 38 -#define SPD_TRCRFC 40 -#define SPD_TRC 41 -#define SPD_TRFC 42 - -#define SPD_MANDATEYR 93 /*Module Manufacturing Year (BCD)*/ - -#define SPD_MANDATEWK 94 /*Module Manufacturing Week (BCD)*/ - -#define SPD_MANID_START 117 -#define SPD_SERIAL_START 122 -#define SPD_PARTN_START 128 -#define SPD_PARTN_LENGTH 18 -#define SPD_REVNO_START 146 - -/*----------------------------- - Jedec DDR II related equates ------------------------------*/ -#define MYEAR06 6 /* Manufacturing Year BCD encoding of 2006 - 06d*/ -#define MWEEK24 0x24 /* Manufacturing Week BCD encoding of June - 24d*/ - -/*============================================================================= - Macros -=============================================================================*/ - -#define _2GB_RJ8 (2<<(30-8)) -#define _4GB_RJ8 (4<<(30-8)) -#define _4GB_RJ4 (4<<(30-4)) - -#define BigPagex8_RJ8 (1<<(17+3-8)) /*128KB * 8 >> 8 */ - -/*============================================================================= - Global MCT Status Structure -=============================================================================*/ -struct MCTStatStruc { - u32 GStatus; /* Global Status bitfield*/ - u32 HoleBase; /* If not zero, BASE[39:8] (system address) - 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; - uint16_t nvram_checksum; - uint8_t try_ecc; -} __attribute__((packed, aligned(4))); - -/*============================================================================= - Global MCT Configuration Status Word (GStatus) -=============================================================================*/ -/*These should begin at bit 0 of GStatus[31:0]*/ -#define GSB_MTRRshort 0 /* Ran out of MTRRs while mapping memory*/ -#define GSB_ECCDIMMs 1 /* All banks of all Nodes are ECC capable*/ -#define GSB_DramECCDis 2 /* Dram ECC requested but not enabled.*/ -#define GSB_SoftHole 3 /* A Node Base gap was created*/ -#define GSB_HWHole 4 /* A HW dram remap was created*/ -#define GSB_NodeIntlv 5 /* Node Memory interleaving was enabled*/ -#define GSB_SpIntRemapHole 16 /* Special condition for Node Interleave and HW remapping*/ -#define GSB_EnDIMMSpareNW 17 /* Indicates that DIMM Spare can be used without a warm reset */ - /* NOTE: This is a local bit used by memory code */ -#define GSB_ConfigRestored 18 /* Training configuration was restored from NVRAM */ - -/*=============================================================================== - Local DCT Status structure (a structure for each DCT) -===============================================================================*/ -#include "mwlc_d.h" /* I have to */ - -struct amd_spd_node_data { - uint8_t spd_bytes[MAX_DIMMS_SUPPORTED][256]; /* [DIMM][byte] */ - uint8_t spd_address[MAX_DIMMS_SUPPORTED]; /* [DIMM] */ - uint64_t spd_hash[MAX_DIMMS_SUPPORTED]; /* [DIMM] */ - uint64_t nvram_spd_hash[MAX_DIMMS_SUPPORTED]; /* [DIMM] */ - uint8_t nvram_spd_match; - uint8_t nvram_memclk[2]; /* [channel] */ -} __attribute__((packed, aligned(4))); - -struct DCTPersistentStatStruc { - u8 CH_D_B_TxDqs[2][4][9]; /* [A/B] [DIMM1-4] [DQS] */ - /* CHA DIMM0 Byte 0 - 7 TxDqs */ - /* CHA DIMM0 Byte 0 - 7 TxDqs */ - /* CHA DIMM1 Byte 0 - 7 TxDqs */ - /* CHA DIMM1 Byte 0 - 7 TxDqs */ - /* CHB DIMM0 Byte 0 - 7 TxDqs */ - /* CHB DIMM0 Byte 0 - 7 TxDqs */ - /* CHB DIMM1 Byte 0 - 7 TxDqs */ - /* CHB DIMM1 Byte 0 - 7 TxDqs */ - 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.*/ -} __attribute__((packed, aligned(4))); - -struct DCTStatStruc { /* A per Node structure*/ -/* DCTStatStruct_F - start */ - u8 Node_ID; /* Node ID of current controller */ - uint8_t Internal_Node_ID; /* Internal Node ID of the current controller */ - uint8_t Dual_Node_Package; /* 1 = Dual node package (G34) */ - uint8_t stopDCT[2]; /* 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. - 2= Stop Error, DCT is NOT running - 3= Fatal Error, DCT/MCT initialization has been halted.*/ - u32 ErrStatus; /* Error Status bit Field */ - u32 Status; /* Status bit Field*/ - u8 DIMMAddr[8]; /* SPD address of DIMM controlled by MA0_CS_L[0,1]*/ - /* SPD address of..MB0_CS_L[0,1]*/ - /* SPD address of..MA1_CS_L[0,1]*/ - /* SPD address of..MB1_CS_L[0,1]*/ - /* SPD address of..MA2_CS_L[0,1]*/ - /* SPD address of..MB2_CS_L[0,1]*/ - /* SPD address of..MA3_CS_L[0,1]*/ - /* SPD address of..MB3_CS_L[0,1]*/ - u16 DIMMPresent; /*For each bit n 0..7, 1 = DIMM n is present. - DIMM# Select Signal - 0 MA0_CS_L[0,1] - 1 MB0_CS_L[0,1] - 2 MA1_CS_L[0,1] - 3 MB1_CS_L[0,1] - 4 MA2_CS_L[0,1] - 5 MB2_CS_L[0,1] - 6 MA3_CS_L[0,1] - 7 MB3_CS_L[0,1]*/ - u16 DIMMValid; /* For each bit n 0..7, 1 = DIMM n is valid and is/will be configured*/ - u16 DIMMMismatch; /* For each bit n 0..7, 1 = DIMM n is mismatched, channel B is always considered the mismatch */ - u16 DIMMSPDCSE; /* For each bit n 0..7, 1 = DIMM n SPD checksum error*/ - u16 DimmECCPresent; /* For each bit n 0..7, 1 = DIMM n is ECC capable.*/ - u16 DimmPARPresent; /* For each bit n 0..7, 1 = DIMM n is ADR/CMD Parity capable.*/ - u16 Dimmx4Present; /* For each bit n 0..7, 1 = DIMM n contains x4 data devices.*/ - u16 Dimmx8Present; /* For each bit n 0..7, 1 = DIMM n contains x8 data devices.*/ - u16 Dimmx16Present; /* For each bit n 0..7, 1 = DIMM n contains x16 data devices.*/ - u16 DIMM2Kpage; /* For each bit n 0..7, 1 = DIMM n contains 1K page devices.*/ - u8 MAload[2]; /* Number of devices loading MAA bus*/ - /* Number of devices loading MAB bus*/ - u8 MAdimms[2]; /*Number of DIMMs loading CH A*/ - /* Number of DIMMs loading CH B*/ - u8 DATAload[2]; /*Number of ranks loading CH A DATA*/ - /* Number of ranks loading CH B DATA*/ - u8 DIMMAutoSpeed; /*Max valid Mfg. Speed of DIMMs - 1 = 200MHz - 2 = 266MHz - 3 = 333MHz - 4 = 400MHz - 5 = 533MHz*/ - u8 DIMMCASL; /* Min valid Mfg. CL bitfield - 0 = 2.0 - 1 = 3.0 - 2 = 4.0 - 3 = 5.0 - 4 = 6.0 */ - u16 DIMMTrcd; /* Minimax Trcd*40 (ns) of DIMMs*/ - u16 DIMMTrp; /* Minimax Trp*40 (ns) of DIMMs*/ - u16 DIMMTrtp; /* Minimax Trtp*40 (ns) of DIMMs*/ - u16 DIMMTras; /* Minimax Tras*40 (ns) of DIMMs*/ - u16 DIMMTrc; /* Minimax Trc*40 (ns) of DIMMs*/ - u16 DIMMTwr; /* Minimax Twr*40 (ns) of DIMMs*/ - u16 DIMMTrrd; /* Minimax Trrd*40 (ns) of DIMMs*/ - u16 DIMMTwtr; /* Minimax Twtr*40 (ns) of DIMMs*/ - u8 Speed; /* Bus Speed (to set Controller) - 1 = 200MHz - 2 = 266MHz - 3 = 333MHz - 4 = 400MHz */ - u8 CASL; /* CAS latency DCT setting - 0 = 2.0 - 1 = 3.0 - 2 = 4.0 - 3 = 5.0 - 4 = 6.0 */ - u8 Trcd; /* DCT Trcd (busclocks) */ - u8 Trp; /* DCT Trp (busclocks) */ - u8 Trtp; /* DCT Trtp (busclocks) */ - u8 Tras; /* DCT Tras (busclocks) */ - u8 Trc; /* DCT Trc (busclocks) */ - u8 Twr; /* DCT Twr (busclocks) */ - u8 Trrd; /* DCT Trrd (busclocks) */ - u8 Twtr; /* DCT Twtr (busclocks) */ - u8 Trfc[4]; /* DCT Logical DIMM0 Trfc - 0 = 75ns (for 256Mb devs) - 1 = 105ns (for 512Mb devs) - 2 = 127.5ns (for 1Gb devs) - 3 = 195ns (for 2Gb devs) - 4 = 327.5ns (for 4Gb devs) */ - /* DCT Logical DIMM1 Trfc (see Trfc0 for format) */ - /* DCT Logical DIMM2 Trfc (see Trfc0 for format) */ - /* DCT Logical DIMM3 Trfc (see Trfc0 for format) */ - u16 CSPresent; /* For each bit n 0..7, 1 = Chip-select n is present */ - u16 CSTestFail; /* For each bit n 0..7, 1 = Chip-select n is present but disabled */ - u32 DCTSysBase; /* BASE[39:8] (system address) of this Node's DCTs. */ - u32 DCTHoleBase; /* If not zero, BASE[39:8] (system address) of dram hole for HW remapping. Dram hole exists on this Node's DCTs. */ - u32 DCTSysLimit; /* LIMIT[39:8] (system address) of this Node's DCTs */ - u16 PresetmaxFreq; /* Maximum OEM defined DDR frequency - 200 = 200MHz (DDR400) - 266 = 266MHz (DDR533) - 333 = 333MHz (DDR667) - 400 = 400MHz (DDR800) */ - u8 _2Tmode; /* 1T or 2T CMD mode (slow access mode) - 1 = 1T - 2 = 2T */ - u8 TrwtTO; /* DCT TrwtTO (busclocks)*/ - u8 Twrrd; /* DCT Twrrd (busclocks)*/ - u8 Twrwr; /* DCT Twrwr (busclocks)*/ - u8 Trdrd; /* DCT Trdrd (busclocks)*/ - u32 CH_ODC_CTL[2]; /* Output Driver Strength (see BKDG FN2:Offset 9Ch, index 00h*/ - u32 CH_ADDR_TMG[2]; /* Address Bus Timing (see BKDG FN2:Offset 9Ch, index 04h*/ - /* Output Driver Strength (see BKDG FN2:Offset 9Ch, index 20h*/ - /* Address Bus Timing (see BKDG FN2:Offset 9Ch, index 24h*/ - u16 CH_EccDQSLike[2]; /* CHA DQS ECC byte like...*/ - u8 CH_EccDQSScale[2]; /* CHA DQS ECC byte scale*/ - /* CHA DQS ECC byte like...*/ - /* CHA DQS ECC byte scale*/ - u8 MaxAsyncLat; /* Max Asynchronous Latency (ns)*/ - /* NOTE: Not used in Barcelona - u8 CH_D_RCVRDLY[2][4]; */ - /* CHA DIMM 0 - 4 Receiver Enable Delay*/ - /* CHB DIMM 0 - 4 Receiver Enable Delay */ - /* NOTE: Not used in Barcelona - u8 CH_D_B_DQS[2][2][8]; */ - /* CHA Byte 0-7 Write DQS Delay */ - /* CHA Byte 0-7 Read DQS Delay */ - /* CHB Byte 0-7 Write DQS Delay */ - /* CHB Byte 0-7 Read DQS Delay */ - u32 PtrPatternBufA; /* Ptr on stack to aligned DQS testing pattern*/ - u32 PtrPatternBufB; /* Ptr on stack to aligned DQS testing pattern*/ - u8 Channel; /* Current Channel (0= CH A, 1 = CH B)*/ - u8 ByteLane; /* Current Byte Lane (0..7)*/ - u8 Direction; /* Current DQS-DQ training write direction (0 = read, 1 = write)*/ - u8 Pattern; /* Current pattern*/ - u8 DQSDelay; /* Current DQS delay value*/ - u32 TrainErrors; /* Current Training Errors*/ - - u32 AMC_TSC_DeltaLo; /* Time Stamp Counter measurement of AMC, Low dword*/ - u32 AMC_TSC_DeltaHi; /* Time Stamp Counter measurement of AMC, High dword*/ - /* NOTE: Not used in Barcelona - */ - u8 CH_D_DIR_MaxMin_B_Dly[2][2][2][8]; - /* CH A byte lane 0 - 7 minimum filtered window passing DQS delay value*/ - /* 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*/ - /* CH A byte lane 0 - 7 minimum filtered window passing DQS delay value*/ - /* 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*/ - uint64_t LogicalCPUID; /* The logical CPUID of the node*/ - u16 DimmQRPresent; /* QuadRank DIMM present?*/ - u16 DimmTrainFail; /* Bitmap showing which dimms failed training*/ - u16 CSTrainFail; /* Bitmap showing which chipselects failed training*/ - u16 DimmYr06; /* Bitmap indicating which Dimms have a manufactur's year code <= 2006*/ - u16 DimmWk2406; /* Bitmap indicating which Dimms have a manufactur's week code <= 24 of 2006 (June)*/ - u16 DimmDRPresent; /* Bitmap indicating that Dual Rank Dimms are present*/ - u16 DimmPlPresent; /* Bitmap indicating that Planar (1) or Stacked (0) Dimms are present.*/ - u16 ChannelTrainFai; /* Bitmap showing the channel information about failed Chip Selects - 0 in any bit field indicates Channel 0 - 1 in any bit field indicates Channel 1 */ - u16 DIMMTfaw; /* Minimax Tfaw*16 (ns) of DIMMs */ - u8 Tfaw; /* DCT Tfaw (busclocks) */ - u16 CSUsrTestFail; /* Chip selects excluded by user */ -/* DCTStatStruct_F - end */ - - u16 CH_MaxRdLat[2][2]; /* Max Read Latency (nclks) [dct][pstate] */ - /* Max Read Latency (ns) for DCT 1*/ - u8 CH_D_DIR_B_DQS[2][4][2][9]; /* [A/B] [DIMM1-4] [R/W] [DQS] */ - /* CHA DIMM0 Byte 0 - 7 and Check Write DQS Delay*/ - /* CHA DIMM0 Byte 0 - 7 and Check Read DQS Delay*/ - /* CHA DIMM1 Byte 0 - 7 and Check Write DQS Delay*/ - /* CHA DIMM1 Byte 0 - 7 and Check Read DQS Delay*/ - /* CHB DIMM0 Byte 0 - 7 and Check Write DQS Delay*/ - /* CHB DIMM0 Byte 0 - 7 and Check Read DQS Delay*/ - /* CHB DIMM1 Byte 0 - 7 and Check Write DQS Delay*/ - /* CHB DIMM1 Byte 0 - 7 and Check Read DQS Delay*/ - u16 CH_D_B_RCVRDLY[2][4][8]; /* [A/B] [DIMM0-3] [DQS] */ - /* CHA DIMM 0 Receiver Enable Delay*/ - /* CHA DIMM 1 Receiver Enable Delay*/ - /* CHA DIMM 2 Receiver Enable Delay*/ - /* CHA DIMM 3 Receiver Enable Delay*/ - - /* CHB DIMM 0 Receiver Enable Delay*/ - /* CHB DIMM 1 Receiver Enable Delay*/ - /* CHB DIMM 2 Receiver Enable Delay*/ - /* CHB DIMM 3 Receiver Enable Delay*/ - u16 CH_D_BC_RCVRDLY[2][4]; - /* CHA DIMM 0 - 4 Check Byte Receiver Enable Delay*/ - /* CHB DIMM 0 - 4 Check Byte Receiver Enable Delay*/ - u8 DIMMValidDCT[2]; /* DIMM# in DCT0*/ - /* DIMM# in DCT1*/ - u16 CSPresent_DCT[2]; /* DCT# CS mapping */ - u16 MirrPresU_NumRegR; /* Address mapping from edge connect to DIMM present for unbuffered dimm - Number of registers on the dimm for registered dimm */ - u8 MaxDCTs; /* Max number of DCTs in system*/ - /* NOTE: removed u8 DCT. Use ->dev_ for pci R/W; */ /*DCT pointer*/ - u8 GangedMode; /* Ganged mode enabled, 0 = disabled, 1 = enabled*/ - u8 DRPresent; /* Family 10 present flag, 0 = not Fam10, 1 = Fam10*/ - u32 NodeSysLimit; /* BASE[39:8],for DCT0+DCT1 system address*/ - u8 WrDatGrossH; - u8 DqsRcvEnGrossL; - /* NOTE: Not used - u8 NodeSpeed */ /* Bus Speed (to set Controller) */ - /* 1 = 200MHz */ - /* 2 = 266MHz */ - /* 3 = 333MHz */ - /* NOTE: Not used - u8 NodeCASL */ /* CAS latency DCT setting */ - /* 0 = 2.0 */ - /* 1 = 3.0 */ - /* 2 = 4.0 */ - /* 3 = 5.0 */ - /* 4 = 6.0 */ - u8 TrwtWB; - u8 CurrRcvrCHADelay; /* for keep current RcvrEnDly of chA*/ - u16 T1000; /* get the T1000 figure (cycle time (ns)*1K)*/ - u8 DqsRcvEn_Pass; /* for TrainRcvrEn byte lane pass flag*/ - u8 DqsRcvEn_Saved; /* for TrainRcvrEn byte lane saved flag*/ - u8 SeedPass1Remainder; /* for Phy assisted DQS receiver enable training*/ - - /* for second pass - Second pass should never run for Fam10*/ - /* NOTE: Not used for Barcelona - u8 CH_D_B_RCVRDLY_1[2][4][8]; */ /* CHA DIMM 0 Receiver Enable Delay */ - /* CHA DIMM 1 Receiver Enable Delay*/ - /* CHA DIMM 2 Receiver Enable Delay*/ - /* CHA DIMM 3 Receiver Enable Delay*/ - - /* CHB DIMM 0 Receiver Enable Delay*/ - /* CHB DIMM 1 Receiver Enable Delay*/ - /* CHB DIMM 2 Receiver Enable Delay*/ - /* CHB DIMM 3 Receiver Enable Delay*/ - - 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; - uint32_t CtrlWrd3; - uint32_t CtrlWrd4; - uint32_t CtrlWrd5; - u8 DqsRdWrPos_Saved; - u8 DqsRcvEnGrossMax; - u8 DqsRcvEnGrossMin; - u8 WrDatGrossMax; - u8 WrDatGrossMin; - uint8_t tcwl_delay[2]; - - u16 RegMan1Present; /* DIMM present bitmap of Register manufacture 1 */ - u16 RegMan2Present; /* DIMM present bitmap of Register manufacture 2 */ - - struct _sMCTStruct *C_MCTPtr; - struct _sDCTStruct *C_DCTPtr[2]; - /* struct _sDCTStruct *C_DCT1Ptr; */ - - struct _sMCTStruct s_C_MCTPtr; - struct _sDCTStruct s_C_DCTPtr[2]; - /* struct _sDCTStruct s_C_DCT1Ptr[8]; */ - - /* DIMM supported voltage bitmap ([2:0]: 1.25V, 1.35V, 1.5V) */ - uint8_t DimmSupportedVoltages[MAX_DIMMS_SUPPORTED]; - uint32_t DimmConfiguredVoltage[MAX_DIMMS_SUPPORTED]; /* mV */ - - uint8_t DimmRows[MAX_DIMMS_SUPPORTED]; - uint8_t DimmCols[MAX_DIMMS_SUPPORTED]; - uint8_t DimmRanks[MAX_DIMMS_SUPPORTED]; - uint8_t DimmBanks[MAX_DIMMS_SUPPORTED]; - uint8_t DimmWidth[MAX_DIMMS_SUPPORTED]; - uint64_t DimmChipSize[MAX_DIMMS_SUPPORTED]; - uint32_t DimmChipWidth[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+1]; - uint16_t DimmRevisionNumber[MAX_DIMMS_SUPPORTED]; - uint32_t DimmSerialNumber[MAX_DIMMS_SUPPORTED]; - - struct amd_spd_node_data spd_data; - - /* NOTE: This must remain the last entry in this structure */ - struct DCTPersistentStatStruc persistentData; -} __attribute__((packed, aligned(4))); - -struct amd_s3_persistent_mct_channel_data { - /* Stage 1 (1 dword) */ - uint32_t f2x110; - - /* Stage 2 (88 dwords) */ - uint32_t f1x40; - uint32_t f1x44; - uint32_t f1x48; - uint32_t f1x4c; - uint32_t f1x50; - uint32_t f1x54; - uint32_t f1x58; - uint32_t f1x5c; - uint32_t f1x60; - uint32_t f1x64; - uint32_t f1x68; - uint32_t f1x6c; - uint32_t f1x70; - uint32_t f1x74; - uint32_t f1x78; - uint32_t f1x7c; - uint32_t f1xf0; - uint32_t f1x120; - uint32_t f1x124; - uint32_t f2x10c; - uint32_t f2x114; - uint32_t f2x118; - uint32_t f2x11c; - uint32_t f2x1b0; - uint32_t f3x44; - uint64_t msr0000020[16]; - uint64_t msr00000250; - uint64_t msr00000258; - uint64_t msr0000026[8]; - uint64_t msr000002ff; - uint64_t msrc0010010; - uint64_t msrc001001a; - uint64_t msrc001001d; - uint64_t msrc001001f; - - /* Stage 3 (21 dwords) */ - uint32_t f2x40; - uint32_t f2x44; - uint32_t f2x48; - uint32_t f2x4c; - uint32_t f2x50; - uint32_t f2x54; - uint32_t f2x58; - uint32_t f2x5c; - uint32_t f2x60; - uint32_t f2x64; - uint32_t f2x68; - uint32_t f2x6c; - uint32_t f2x78; - uint32_t f2x7c; - uint32_t f2x80; - uint32_t f2x84; - uint32_t f2x88; - uint32_t f2x8c; - uint32_t f2x90; - uint32_t f2xa4; - uint32_t f2xa8; - - /* Stage 4 (1 dword) */ - uint32_t f2x94; - - /* Stage 6 (33 dwords) */ - uint32_t f2x9cx0d0f0_f_8_0_0_8_4_0[9][3]; /* [lane][setting] */ - uint32_t f2x9cx00; - uint32_t f2x9cx0a; - uint32_t f2x9cx0c; - - /* Stage 7 (1 dword) */ - uint32_t f2x9cx04; - - /* Stage 9 (2 dwords) */ - uint32_t f2x9cx0d0fe006; - uint32_t f2x9cx0d0fe007; - - /* Stage 10 (78 dwords) */ - uint32_t f2x9cx10[12]; - uint32_t f2x9cx20[12]; - uint32_t f2x9cx3_0_0_3_1[4][3]; /* [dimm][setting] */ - uint32_t f2x9cx3_0_0_7_5[4][3]; /* [dimm][setting] */ - uint32_t f2x9cx0d; - uint32_t f2x9cx0d0f0_f_0_13[9]; /* [lane] */ - uint32_t f2x9cx0d0f0_f_0_30[9]; /* [lane] */ - uint32_t f2x9cx0d0f2_f_0_30[4]; /* [pad select] */ - uint32_t f2x9cx0d0f8_8_4_0[2][3]; /* [offset][pad select] */ - uint32_t f2x9cx0d0f812f; - - /* Stage 11 (24 dwords) */ - uint32_t f2x9cx30[12]; - uint32_t f2x9cx40[12]; - - /* Other (3 dwords) */ - uint32_t f3x58; - uint32_t f3x5c; - uint32_t f3x60; - - /* Family 15h-specific registers (91 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; - uint32_t f2x9cx0d0fe00a; - - /* TOTAL: 343 dwords */ -} __attribute__((packed, aligned(4))); - -struct amd_s3_persistent_node_data { - uint32_t node_present; - uint64_t spd_hash[MAX_DIMMS_SUPPORTED]; - uint8_t memclk[2]; - struct amd_s3_persistent_mct_channel_data channel[2]; -} __attribute__((packed, aligned(4))); - -struct amd_s3_persistent_data { - struct amd_s3_persistent_node_data node[MAX_NODES_SUPPORTED]; - uint16_t nvram_checksum; -} __attribute__((packed, aligned(4))); - -/*=============================================================================== - Local Error Status Codes (DCTStatStruc.ErrCode) -===============================================================================*/ -#define SC_RunningOK 0 -#define SC_VarianceErr 1 /* Running non-optimally*/ -#define SC_StopError 2 /* Not Running*/ -#define SC_FatalErr 3 /* Fatal Error, MCTB has exited immediately*/ - -/*=============================================================================== - Local Error Status (DCTStatStruc.ErrStatus[31:0]) -===============================================================================*/ -#define SB_NoDimms 0 -#define SB_DIMMChkSum 1 -#define SB_DimmMismatchM 2 /* dimm module type(buffer) mismatch*/ -#define SB_DimmMismatchT 3 /* dimm CL/T mismatch*/ -#define SB_DimmMismatchO 4 /* dimm organization mismatch (128-bit)*/ -#define SB_NoTrcTrfc 5 /* SPD missing Trc or Trfc info*/ -#define SB_NoCycTime 6 /* SPD missing byte 23 or 25*/ -#define SB_BkIntDis 7 /* Bank interleave requested but not enabled*/ -#define SB_DramECCDis 8 /* Dram ECC requested but not enabled*/ -#define SB_SpareDis 9 /* Online spare requested but not enabled*/ -#define SB_MinimumMode 10 /* Running in Minimum Mode*/ -#define SB_NORCVREN 11 /* No DQS Receiver Enable pass window found*/ -#define SB_CHA2BRCVREN 12 /* DQS Rcvr En pass window CHA to CH B too large*/ -#define SB_SmallRCVR 13 /* DQS Rcvr En pass window too small (far right of dynamic range)*/ -#define SB_NODQSPOS 14 /* No DQS-DQ passing positions*/ -#define SB_SMALLDQS 15 /* DQS-DQ passing window too small*/ -#define SB_DCBKScrubDis 16 /* DCache scrub requested but not enabled */ -#define SB_RetryConfigTrain 17 /* Retry configuration and training */ -#define SB_FatalError 18 /* Fatal training error detected */ - -/*=============================================================================== - Local Configuration Status (DCTStatStruc.Status[31:0]) -===============================================================================*/ -#define SB_Registered 0 /* All DIMMs are Registered*/ -#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*/ - - -/*=============================================================================== - NVRAM/run-time-configurable Items -===============================================================================*/ -/*Platform Configuration*/ -#define NV_PACK_TYPE 0 /* CPU Package Type (2-bits) - 0 = NPT L1 - 1 = NPT M2 - 2 = NPT S1*/ -#define NV_MAX_NODES 1 /* Number of Nodes/Sockets (4-bits)*/ -#define NV_MAX_DIMMS 2 /* Number of DIMM slots for the specified Node ID (4-bits)*/ -#define NV_MAX_MEMCLK 3 /* Maximum platform demonstrated Memclock (10-bits) - 200 = 200MHz (DDR400) - 266 = 266MHz (DDR533) - 333 = 333MHz (DDR667) - 400 = 400MHz (DDR800)*/ -#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 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 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 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)*/ - - -/*Dram Timing*/ -#define NV_MCTUSRTMGMODE 10 /* User Memclock Mode (2-bits) - 0 = Auto, no user limit - 1 = Auto, user limit provided in NV_MemCkVal - 2 = Manual, user value provided in NV_MemCkVal*/ -#define NV_MemCkVal 11 /* Memory Clock Value (2-bits) - 0 = 200MHz - 1 = 266MHz - 2 = 333MHz - 3 = 400MHz*/ - -/*Dram Configuration*/ -#define NV_BankIntlv 20 /* Dram Bank (chip-select) Interleaving (1-bits) - 0 = disable - 1 = enable*/ -#define NV_AllMemClks 21 /* Turn on All DIMM clocks (1-bits) - 0 = normal - 1 = enable all memclocks*/ -#define NV_SPDCHK_RESTRT 22 /* SPD Check control bitmap (1-bits) - 0 = Exit current node init if any DIMM has SPD checksum error - 1 = Ignore faulty SPD checksums (Note: DIMM cannot be enabled)*/ -#define NV_DQSTrainCTL 23 /* DQS Signal Timing Training Control - 0 = skip DQS training - 1 = perform DQS training*/ -#define NV_NodeIntlv 24 /* Node Memory Interleaving (1-bits) - 0 = disable - 1 = enable*/ -#define NV_BurstLen32 25 /* BurstLength32 for 64-bit mode (1-bits) - 0 = disable (normal) - 1 = enable (4 beat burst when width is 64-bits)*/ - -/*Dram Power*/ -#define NV_CKE_PDEN 30 /* CKE based power down mode (1-bits) - 0 = disable - 1 = enable*/ -#define NV_CKE_CTL 31 /* CKE based power down control (1-bits) - 0 = per Channel control - 1 = per Chip select control*/ -#define NV_CLKHZAltVidC3 32 /* Memclock tri-stating during C3 and Alt VID (1-bits) - 0 = disable - 1 = enable*/ - -/*Memory Map/Mgt.*/ -#define NV_BottomIO 40 /* Bottom of 32-bit IO space (8-bits) - NV_BottomIO[7:0]=Addr[31:24]*/ -#define NV_BottomUMA 41 /* Bottom of shared graphics dram (8-bits) - NV_BottomUMA[7:0]=Addr[31:24]*/ -#define NV_MemHole 42 /* Memory Hole Remapping (1-bits) - 0 = disable - 1 = enable */ - -/*ECC*/ -#define NV_ECC 50 /* Dram ECC enable*/ -#define NV_NBECC 52 /* ECC MCE enable*/ -#define NV_ChipKill 53 /* Chip-Kill ECC Mode enable*/ -#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_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: - Reserved, must be zero*/ -#define NV_SyncOnUnEccEn 61 /* SyncOnUnEccEn control - 0 = disable - 1 = enable*/ -#define NV_Unganged 62 - -#define NV_ChannelIntlv 63 /* Channel Interleaving (3-bits) - xx0b = disable - yy1b = enable with DctSelIntLvAddr set to yyb */ - -#define NV_MAX_DIMMS_PER_CH 64 /* Maximum number of DIMMs per channel */ - -/*=============================================================================== - CBMEM storage -===============================================================================*/ -struct amdmct_memory_info { - struct MCTStatStruc mct_stat; - struct DCTStatStruc dct_stat[MAX_NODES_SUPPORTED]; - uint16_t ecc_enabled; - uint16_t ecc_scrub_rate; -} __attribute__((packed, aligned(4))); - -extern const u8 Table_DQSRcvEn_Offset[]; -extern const u32 TestPattern0_D[]; -extern const u32 TestPattern1_D[]; -extern const u32 TestPattern2_D[]; - -u32 Get_NB32(u32 dev, u32 reg); -void Set_NB32(u32 dev, u32 reg, u32 val); -u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index); -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); -void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data); -u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val); -void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct); -u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value); -u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass); -u32 SetupDqsPattern_1PassA(u8 Pass); -u32 SetupDqsPattern_1PassB(u8 Pass); -u8 mct_Get_Start_RcvrEnDly_1Pass(u8 Pass); -u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u16 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass); -void initialize_mca(uint8_t bsp, uint8_t suppress_errors); -void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -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 TrainMaxRdLatency_En_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,struct DCTStatStruc *pDCTstatA); -void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u8 FinalValue, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 Pass); -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 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); -void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct); -void DIMMSetVoltages(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void InterleaveNodes_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); - -void phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, int16_t Node); -u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, u8 pass); -u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 dct); -void mct_Wait(u32 cycles); -u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 Channel, u8 ChipSel); -u32 mct_GetRcvrSysAddr_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 channel, u8 receiver, u8 *valid); -void mct_Read1LTestPattern_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 addr); -void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash); -int8_t load_spd_hashes_from_nvram(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -int8_t restore_mct_information_from_nvram(uint8_t training_only); -uint16_t calculate_nvram_mct_hash(void); - -uint32_t fam10h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct); -uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct); -uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct); -uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dct); -void precise_memclk_delay_fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t clocks); -void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void SetDllSpeedUp_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -uint8_t get_available_lane_count(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -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); -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); -void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t enable); -void read_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, - uint8_t dct, uint8_t dimm, uint32_t index_reg); -void write_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, - uint8_t dct, uint8_t dimm, uint32_t index_reg); -void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void proc_IOCLFLUSH_D(u32 addr_hi); -u8 ChipSelPresent_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel); -void mct_Write1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr, u8 pattern); -u8 NodePresent_D(u8 Node); -void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void SPD2ndTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void ProgDramMRSReg_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -uint16_t mhz_to_memclk_config(uint16_t freq); -void SetTargetFreq(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Node); -void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Pass); -uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass); -uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t pass); -uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass); -void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void DisableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void PrepareC_DCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct); -void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void MCTMemClr_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat); -void mct_ExtMCTConfig_Bx(struct DCTStatStruc *pDCTstat); -void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat); -void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat); -u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, - uint8_t dct, uint32_t misc2, uint32_t DramControl); - -uint8_t dct_ddr_voltage_index(struct DCTStatStruc *pDCTstat, uint8_t dct); -void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct); -void precise_ndelay_fam15(struct MCTStatStruc *pMCTstat, uint32_t nanoseconds); -void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct); -u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); -void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void print_debug_dqs(const char *str, u32 val, u8 level); -void print_debug_dqs_pair(const char *str, u32 val, const char *str2, u32 val2, u8 level); -u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void ResetDCTWrPtr_D(u32 dev, uint8_t dct, u32 index_reg, u32 index); -void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t calc_min); -void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error); -void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error); -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); - -uint32_t fenceDynTraining_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct); -int32_t abs(int32_t val); -void SetTargetWTIO_D(u32 TestAddr); -void ResetTargetWTIO_D(void); -u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 receiver, u8 *valid); -void set_2t_configuration(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u32 mct_MR1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); -u32 mct_MR2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); -uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type); -uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type); -uint8_t fam15_dimm_dic(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type); -u32 mct_DramTermDyn_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dimm); - -void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persistent_data, uint8_t training_only); -#endif diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.c deleted file mode 100644 index ccea732709..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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 - * 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. - */ - -#include "mct_d_gcc.h" -#include <stdint.h> -#include <arch/cpu.h> - -void _WRMSR(u32 addr, u32 lo, u32 hi) -{ - __asm__ volatile ( - "wrmsr" - : - :"c"(addr),"a"(lo), "d" (hi) - ); -} - -void _RDMSR(u32 addr, u32 *lo, u32 *hi) -{ - __asm__ volatile ( - "rdmsr" - :"=a"(*lo), "=d" (*hi) - :"c"(addr) - ); -} - -void _RDTSC(u32 *lo, u32 *hi) -{ - __asm__ volatile ( - "rdtsc" - : "=a" (*lo), "=d"(*hi) - ); -} - -void _cpu_id(u32 addr, u32 *val) -{ - __asm__ volatile( - "cpuid" - : "=a" (val[0]), - "=b" (val[1]), - "=c" (val[2]), - "=d" (val[3]) - : "0" (addr)); - -} - -u32 bsr(u32 x) -{ - u8 i; - u32 ret = 0; - - for (i = 31; i > 0; i--) { - if (x & (1<<i)) { - ret = i; - break; - } - } - - return ret; - -} - -u32 bsf(u32 x) -{ - u8 i; - u32 ret = 32; - - for (i = 0; i < 32; i++) { - if (x & (1<<i)) { - ret = i; - break; - } - } - - return ret; -} - -void proc_MFENCE(void) -{ - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "mfence\n\t" - :::"memory" - ); -} - -void proc_CLFLUSH(u32 addr_hi) -{ - SetUpperFSbase(addr_hi); - - __asm__ volatile ( - /* clflush fs:[eax] */ - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "clflush %%fs:(%0)\n\t" - "mfence\n\t" - ::"a" (addr_hi<<8) - ); -} - - -void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num) -{ - uint32_t step = 16; - uint32_t count = line_num * 4; - - __asm__ volatile ( - /*prevent speculative execution of following instructions*/ - /* FIXME: needed ? */ - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "1:\n\t" - "movdqa (%3), %%xmm0\n\t" - "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */ - "addl %1, %0\n\t" - "addl %1, %3\n\t" - "loop 1b\n\t" - "mfence\n\t" - - : "+a" (addr_lo), "+d" (step), "+c" (count), "+b" (buf_a) : : - ); - -} - -u32 read32_fs(u32 addr_lo) -{ - u32 value; - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "movl %%fs:(%1), %0\n\t" - :"=b"(value): "a" (addr_lo) - ); - return value; -} - -uint64_t read64_fs(uint32_t addr_lo) -{ - uint64_t value = 0; - uint32_t value_lo; - uint32_t value_hi; - - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "mfence\n\t" - "movl %%fs:(%2), %0\n\t" - "movl %%fs:(%3), %1\n\t" - :"=c"(value_lo), "=d"(value_hi): "a" (addr_lo), "b" (addr_lo + 4) : "memory" - ); - value |= value_lo; - value |= ((uint64_t)value_hi) << 32; - return value; -} - -void FlushDQSTestPattern_L9(u32 addr_lo) -{ - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "clflush %%fs:-128(%%ecx)\n\t" - "clflush %%fs:-64(%%ecx)\n\t" - "clflush %%fs:(%%ecx)\n\t" - "clflush %%fs:64(%%ecx)\n\t" - - "clflush %%fs:-128(%%eax)\n\t" - "clflush %%fs:-64(%%eax)\n\t" - "clflush %%fs:(%%eax)\n\t" - "clflush %%fs:64(%%eax)\n\t" - - "clflush %%fs:-128(%%ebx)\n\t" - - :: "b" (addr_lo+128+8*64), "c"(addr_lo+128), - "a"(addr_lo+128+4*64) - ); - -} - -__attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo) -{ - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "clflush %%fs:-128(%%eax)\n\t" - "clflush %%fs:-64(%%eax)\n\t" - "clflush %%fs:(%%eax)\n\t" - "clflush %%fs:64(%%eax)\n\t" - - "clflush %%fs:-128(%%edi)\n\t" - "clflush %%fs:-64(%%edi)\n\t" - "clflush %%fs:(%%edi)\n\t" - "clflush %%fs:64(%%edi)\n\t" - - "clflush %%fs:-128(%%ebx)\n\t" - "clflush %%fs:-64(%%ebx)\n\t" - "clflush %%fs:(%%ebx)\n\t" - "clflush %%fs:64(%%ebx)\n\t" - - "clflush %%fs:-128(%%ecx)\n\t" - "clflush %%fs:-64(%%ecx)\n\t" - "clflush %%fs:(%%ecx)\n\t" - "clflush %%fs:64(%%ecx)\n\t" - - "clflush %%fs:-128(%%edx)\n\t" - "clflush %%fs:-64(%%edx)\n\t" - - :: "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64), - "d" (addr_lo +128+16*64), "a"(addr_lo+128), - "D"(addr_lo+128+4*64) - ); -} - -void ReadMaxRdLat1CLTestPattern_D(u32 addr) -{ - SetUpperFSbase(addr); - - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "movl %%fs:-128(%%esi), %%eax\n\t" /* TestAddr cache line */ - "movl %%fs:-64(%%esi), %%eax\n\t" /* +1 */ - "movl %%fs:(%%esi), %%eax\n\t" /* +2 */ - "mfence\n\t" - :: "a"(0), "S"((addr<<8)+128) - ); - -} - -void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr) -{ - uint32_t addr_phys = addr << 8; - uint32_t step = 16; - uint32_t count = 3 * 4; - - SetUpperFSbase(addr); - - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "1:\n\t" - "movdqa (%3), %%xmm0\n\t" - "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */ - "addl %1, %0\n\t" - "addl %1, %3\n\t" - "loop 1b\n\t" - "mfence\n\t" - - : "+a" (addr_phys), "+d" (step), "+c" (count), "+b" (buf) : : - ); -} - -void FlushMaxRdLatTestPattern_D(u32 addr) -{ - /* Flush a pattern of 72 bit times (per DQ) from cache. - * This procedure is used to ensure cache miss on the next read training. - */ - - SetUpperFSbase(addr); - - __asm__ volatile ( - "outb %%al, $0xed\n\t" /* _EXECFENCE */ - "clflush %%fs:-128(%%esi)\n\t" /* TestAddr cache line */ - "clflush %%fs:-64(%%esi)\n\t" /* +1 */ - "clflush %%fs:(%%esi)\n\t" /* +2 */ - "mfence\n\t" - - :: "S"((addr<<8)+128) - ); -} - -u32 stream_to_int(u8 *p) -{ - int i; - u32 val; - u32 valx; - - val = 0; - - for (i = 3; i >= 0; i--) { - val <<= 8; - valx = *(p+i); - val |= valx; - } - - return val; -} - -u8 oemNodePresent_D(u8 Node, u8 *ret) -{ - *ret = 0; - return 0; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h deleted file mode 100644 index 629e6e639b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 - * Copyright (C) 2016 Damien Zammit <damien@zamaudio.com> - * - * 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. - */ -#ifndef MCT_D_GCC_H -#define MCT_D_GCC_H - -#include <stdint.h> -#include <cpu/x86/cr.h> - -void _WRMSR(u32 addr, u32 lo, u32 hi); -void _RDMSR(u32 addr, u32 *lo, u32 *hi); -void _RDTSC(u32 *lo, u32 *hi); -void _cpu_id(u32 addr, u32 *val); -u32 bsr(u32 x); -u32 bsf(u32 x); -#define _MFENCE asm volatile ("mfence") -#define _SFENCE asm volatile ("sfence") - -/* prevent speculative execution of following instructions */ -#define _EXECFENCE asm volatile ("outb %al, $0xed") - -u32 SetUpperFSbase(u32 addr_hi); - -void proc_MFENCE(void); -void proc_CLFLUSH(u32 addr_hi); -void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num); -u32 read32_fs(u32 addr_lo); -uint64_t read64_fs(uint32_t addr_lo); -void FlushDQSTestPattern_L9(u32 addr_lo); -__attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo); -void ReadMaxRdLat1CLTestPattern_D(u32 addr); -void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr); -void FlushMaxRdLatTestPattern_D(u32 addr); -u32 stream_to_int(u8 *p); -u8 oemNodePresent_D(u8 Node, u8 *ret); - -#endif diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c b/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c deleted file mode 100644 index e8116340c4..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 - * 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. - */ - -/* AM3/ASB2/C32/G34 DDR3 */ - -#include <arch/cpu.h> -#include <stdint.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -static 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_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload, - u32 *ODC_CTL, - u8 *CMDmode); - -void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 dct) -{ - 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_ODC_CTL[dct]), - &pDCTstat->_2Tmode); - - if (pDCTstat->Status & (1 << SB_Registered)) { - pDCTstat->_2Tmode = 1; /* Disable slow access mode */ - } - pDCTstat->CH_ADDR_TMG[dct] = fam10h_address_timing_compensation_code(pDCTstat, dct); - - 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; -} - -/* - * In: MAAdimms - number of DIMMs on the channel - * : Speed - Speed (see DCTStatstruc.Speed for definition) - * : MAAload - number of address bus loads on the channel - * Out: AddrTmgCTL - Address Timing Control Register Value - * : ODC_CTL - Output Driver Compensation Control Register Value - * : CMDmode - CMD mode - */ -static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload, - u32 *ODC_CTL, - u8 *CMDmode) -{ - *ODC_CTL = 0; - *CMDmode = 1; - - if (MAAdimms == 1) { - *ODC_CTL = 0x00113222; - *CMDmode = 1; - } else /* if (MAAdimms == 0) */ { - if (Speed == 4) { - *CMDmode = 1; - } else if (Speed == 5) { - *CMDmode = 1; - } else if (Speed == 6) { - *CMDmode = 2; - } else { - *CMDmode = 2; - } - *ODC_CTL = 0x00223323; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c b/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c deleted file mode 100644 index d6480ab91a..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 - * 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. - */ - -/* The socket type Fr2, G (1207) are not tested. - */ - -static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload, - u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL, - u8 *CMDmode); - - -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->DATAload[dct], - &(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct]), - &pDCTstat->_2Tmode); - - if (pDCTstat->GangedMode == 1 && dct == 0) - Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[1], pDCTstat->Speed, - pDCTstat->MAload[1], pDCTstat->DATAload[1], - &(pDCTstat->CH_ADDR_TMG[1]), &(pDCTstat->CH_ODC_CTL[1]), - &pDCTstat->_2Tmode); - - pDCTstat->CH_EccDQSLike[0] = 0x0302; - pDCTstat->CH_EccDQSLike[1] = 0x0302; - -} - -/* - * In: MAAdimms - number of DIMMs on the channel - * : Speed - Speed (see DCTStatstruc.Speed for definition) - * : MAAload - number of address bus loads on the channel - * : DATAAload - number of ranks on the channel - * Out: AddrTmgCTL - Address Timing Control Register Value - * : ODC_CTL - Output Driver Compensation Control Register Value - * : CMDmode - CMD mode - */ -static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload, - u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL, - u8 *CMDmode) -{ - *AddrTmgCTL = 0; - *ODC_CTL = 0; - *CMDmode = 1; - - if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { - if (Speed == 4) { - *AddrTmgCTL = 0x00000000; - } else if (Speed == 5) { - *AddrTmgCTL = 0x003C3C3C; - if (MAAdimms > 1) - *AddrTmgCTL = 0x003A3C3A; - } else if (Speed == 6) { - if (MAAdimms == 1) - *AddrTmgCTL = 0x003A3A3A; - else - *AddrTmgCTL = 0x00383A38; - } else { - if (MAAdimms == 1) - *AddrTmgCTL = 0x00373937; - else - *AddrTmgCTL = 0x00353935; - } - } else { - if (Speed == 4) { - *AddrTmgCTL = 0x00000000; - if (MAAdimms == 3) - *AddrTmgCTL = 0x00380038; - } else if (Speed == 5) { - if (MAAdimms == 1) - *AddrTmgCTL = 0x003C3C3C; - else if (MAAdimms == 2) - *AddrTmgCTL = 0x003A3C3A; - else - *AddrTmgCTL = 0x00373C37; - } else if (Speed == 6) { - if (MAAdimms == 1) - *AddrTmgCTL = 0x003A3A3A; - else if (MAAdimms == 2) - *AddrTmgCTL = 0x00383A38; - else - *AddrTmgCTL = 0x00343A34; - } else { - if (MAAdimms == 1) - *AddrTmgCTL = 0x00393939; - else if (MAAdimms == 2) - *AddrTmgCTL = 0x00363936; - else - *AddrTmgCTL = 0x00303930; - } - } - - if ((MAAdimms == 1) && (MAAload < 4)) - *ODC_CTL = 0x20113222; - else - *ODC_CTL = 0x20223222; - - *CMDmode = 1; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c deleted file mode 100644 index d458f3a48e..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -#include <stdint.h> -#include "mct_d.h" -#include "mct_d_gcc.h" -#include <console/console.h> - -void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - - u8 Node; - u32 DramBase, DctSelBase; - u8 DctSelIntLvAddr, DctSelHi; - u8 HoleValid = 0; - u32 HoleSize, HoleBase = 0; - u32 val, tmp; - u32 dct0_size, dct1_size; - struct DCTStatStruc *pDCTstat; - - /* HoleValid - indicates whether the current Node contains hole. - * HoleSize - indicates whether there is IO hole in the whole system - * memory. - */ - - /* call back to wrapper not needed ManualChannelInterleave_D(); */ - /* call back - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv);*/ /* override interleave */ - /* Manually set: typ = 5, otherwise typ = 7. */ - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv); /* typ = 5: Hash*: exclusive OR of address bits[20:16, 6]. */ - - if (DctSelIntLvAddr & 1) { - DctSelIntLvAddr >>= 1; - HoleSize = 0; - if ((pMCTstat->GStatus & (1 << GSB_SoftHole)) || - (pMCTstat->GStatus & (1 << GSB_HWHole))) { - if (pMCTstat->HoleBase) { - HoleBase = pMCTstat->HoleBase >> 8; - HoleSize = HoleBase & 0xFFFF0000; - HoleSize |= ((~HoleBase) + 1) & 0xFFFF; - } - } - Node = 0; - while (Node < MAX_NODES_SUPPORTED) { - pDCTstat = pDCTstatA + Node; - val = Get_NB32(pDCTstat->dev_map, 0xF0); - if (val & (1 << DramHoleValid)) - HoleValid = 1; - if (!pDCTstat->GangedMode && pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1]) { - DramBase = pDCTstat->NodeSysBase >> 8; - dct1_size = ((pDCTstat->NodeSysLimit) + 2) >> 8; - dct0_size = Get_NB32(pDCTstat->dev_dct, 0x114); - if (dct0_size >= 0x10000) { - dct0_size -= HoleSize; - } - - dct0_size -= DramBase; - dct1_size -= dct0_size; - DctSelHi = 0x05; /* DctSelHiRngEn = 1, DctSelHi = 0 */ - if (dct1_size == dct0_size) { - dct1_size = 0; - DctSelHi = 0x04; /* DctSelHiRngEn = 0 */ - } else if (dct1_size > dct0_size) { - dct1_size = dct0_size; - DctSelHi = 0x07; /* DctSelHiRngEn = 1, DctSelHi = 1 */ - } - dct0_size = dct1_size; - dct0_size += DramBase; - dct0_size += dct1_size; - if (dct0_size >= HoleBase) /* if DctSelBaseAddr > HoleBase */ - dct0_size += HoleSize; - DctSelBase = dct0_size; - - if (dct1_size == 0) - dct0_size = 0; - dct0_size -= dct1_size; /* DctSelBaseOffset = DctSelBaseAddr - Interleaved region */ - Set_NB32(pDCTstat->dev_dct, 0x114, dct0_size); - - if (dct1_size == 0) - dct1_size = DctSelBase; - val = Get_NB32(pDCTstat->dev_dct, 0x110); - val &= 0x7F8; - val |= dct1_size; - val |= DctSelHi; - val |= (DctSelIntLvAddr << 6) & 0xFF; - Set_NB32(pDCTstat->dev_dct, 0x110, val); - - if (HoleValid) { - tmp = DramBase; - val = DctSelBase; - if (val < HoleBase) { /* DctSelBaseAddr < DramHoleBase */ - val -= DramBase; - val >>= 1; - tmp += val; - } - tmp += HoleSize; - val = Get_NB32(pDCTstat->dev_map, 0xF0); /* DramHoleOffset */ - val &= 0xFFFF007F; - val |= (tmp & ~0xFFFF007F); - Set_NB32(pDCTstat->dev_map, 0xF0, val); - } - } - printk(BIOS_DEBUG, "InterleaveChannels_D: Node %x\n", Node); - printk(BIOS_DEBUG, "InterleaveChannels_D: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "InterleaveChannels_D: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "InterleaveChannels_D: ErrCode %x\n", pDCTstat->ErrCode); - Node++; - } - } - printk(BIOS_DEBUG, "InterleaveChannels_D: Done\n\n"); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c deleted file mode 100644 index 85e7930b24..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 - * 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. - */ - -/* Low swap bit vs bank size encoding (physical, not logical address bit) - * ;To calculate the number by hand, add the number of Bank address bits - * ;(2 or 3) to the number of column address bits, plus 3 (the logical - * ;page size), and subtract 8. - */ - -#include <stdint.h> -#include "mct_d.h" -#include "mct_d_gcc.h" -#include <console/console.h> - -static const u8 Tab_int_D[] = {6,7,7,8,8,8,8,8,9,9,8,9}; - -void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ChipSel, EnChipSels; - u32 AddrLoMask, AddrHiMask; - u32 AddrLoMaskN, AddrHiMaskN, MemSize = 0; - u8 DoIntlv, _CsIntCap; - u32 BitDelta, BankEncd = 0; - - u32 dev; - u32 reg; - u32 val; - u32 val_lo, val_hi; - - DoIntlv = mctGet_NVbits(NV_BankIntlv); - _CsIntCap = 0; - EnChipSels = 0; - - dev = pDCTstat->dev_dct; - - ChipSel = 0; /* Find out if current configuration is capable */ - while (DoIntlv && (ChipSel < MAX_CS_SUPPORTED)) { - 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); /*Dram CS Mask 0 */ - val = Get_NB32_DCT(dev, dct, reg); - val >>= 19; - val &= 0x3ff; - val++; - if (EnChipSels == 1) - MemSize = val; - else - /*If mask sizes not same then skip */ - if (val != MemSize) - break; - reg = 0x80; /*Dram Bank Addressing */ - val = Get_NB32_DCT(dev, dct, reg); - val >>= (ChipSel>>1)<<2; - val &= 0x0f; - if (EnChipSels == 1) - BankEncd = val; - else - /*If number of Rows/Columns not equal, skip */ - if (val != BankEncd) - break; - } - ChipSel++; - } - if (ChipSel == MAX_CS_SUPPORTED) { - if ((EnChipSels == 2) || (EnChipSels == 4) || (EnChipSels == 8)) - _CsIntCap = 1; - } - - if (DoIntlv) { - if (!_CsIntCap) { - pDCTstat->ErrStatus |= 1<<SB_BkIntDis; - DoIntlv = 0; - } - } - - if (DoIntlv) { - val = Tab_int_D[BankEncd]; - if (pDCTstat->Status & (1<<SB_128bitmode)) - val++; - - AddrLoMask = (EnChipSels - 1) << val; - AddrLoMaskN = ~AddrLoMask; - - val = bsf(MemSize) + 19; - AddrHiMask = (EnChipSels -1) << val; - AddrHiMaskN = ~AddrHiMask; - - BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask); - - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) { - 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; - val &= AddrLoMaskN; - val &= AddrHiMaskN; - val_lo <<= BitDelta; - val_hi >>= BitDelta; - val |= val_lo; - val |= val_hi; - Set_NB32_DCT(dev, dct, reg, val); - - if (ChipSel & 1) - continue; - - 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; - val &= AddrHiMaskN; - val_lo <<= BitDelta; - val_hi >>= BitDelta; - val |= val_lo; - val |= val_hi; - Set_NB32_DCT(dev, dct, reg, val); - } - } - } /* DoIntlv */ - - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "InterleaveBanks_D: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "InterleaveBanks_D: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "InterleaveBanks_D: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "InterleaveBanks_D: Done\n\n"); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c deleted file mode 100644 index d34b2dc2ba..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c +++ /dev/null @@ -1,2493 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2015 - 2016 Raptor Engineering, LLC - * - * 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. - */ - -#include <stdint.h> -#include <console/console.h> -#include <cpu/x86/cr.h> -#include <string.h> -#include <arch/cpu.h> -#include <cpu/amd/msr.h> -#include <cpu/amd/mtrr.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u16 like, - u8 scale, u8 ChipSel); -static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel); -static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void WriteL18TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void WriteL9TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static u16 CompareDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 addr_lo); -static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat, - u32 addr_lo); -static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 ChipSel); -static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 *buffer); - -static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 ChipSel); - -static 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; -} - -#define DQS_TRAIN_DEBUG 0 -// #define PRINT_PASS_FAIL_BITMAPS 1 - -void print_debug_dqs(const char *str, u32 val, u8 level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG >= level) { - printk(BIOS_DEBUG, "%s%x\n", str, val); - } -#endif -} - -void print_debug_dqs_pair(const char *str, u32 val, const char *str2, u32 val2, u8 level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG >= level) { - printk(BIOS_DEBUG, "%s%08x%s%08x\n", str, val, str2, val2); - } -#endif -} - -/*Warning: These must be located so they do not cross a logical 16-bit segment boundary!*/ -static const u32 TestPatternJD1a_D[] = { - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, /* QW0-1, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW2-3, ALL-EVEN */ - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, /* QW4-5, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW6-7, ALL-EVEN */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW0-1, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW2-3, DQ0-ODD */ - 0x01010101,0x01010101,0xFeFeFeFe,0xFeFeFeFe, /* QW4-5, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW6-7, DQ0-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW0-1, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW2-3, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0x02020202,0x02020202, /* QW4-5, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW6-7, DQ1-ODD */ - 0x04040404,0x04040404,0xfBfBfBfB,0xfBfBfBfB, /* QW0-1, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW2-3, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW4-5, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW6-7, DQ2-ODD */ - 0x08080808,0x08080808,0xF7F7F7F7,0xF7F7F7F7, /* QW0-1, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW2-3, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0x08080808,0x08080808, /* QW4-5, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW6-7, DQ3-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW0-1, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, /* QW2-3, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW4-5, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, /* QW6-7, DQ4-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW0-1, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0x20202020,0x20202020, /* QW2-3, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW4-5, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW6-7, DQ5-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW0-1, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW2-3, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW4-5, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW6-7, DQ6-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW0-1, DQ7-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW2-3, DQ7-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW4-5, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080 /* QW6-7, DQ7-ODD */ -}; -static const u32 TestPatternJD1b_D[] = { - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW0,CHA-B, ALL-EVEN */ - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, /* QW1,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW2,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW3,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW4,CHA-B, ALL-EVEN */ - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, /* QW5,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW6,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW7,CHA-B, ALL-EVEN */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW0,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW1,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW2,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW3,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW4,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW5,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW6,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW7,CHA-B, DQ0-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW0,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW1,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW2,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW3,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW4,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW5,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW6,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW7,CHA-B, DQ1-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW0,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW1,CHA-B, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW2,CHA-B, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW3,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW4,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW5,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW6,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW7,CHA-B, DQ2-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW0,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW1,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW2,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW3,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW4,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW5,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW6,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW7,CHA-B, DQ3-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW0,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW1,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW2,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW3,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW4,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW5,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW6,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW7,CHA-B, DQ4-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW0,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW1,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW2,CHA-B, DQ5-ODD */ - 0x20202020,0x20202020,0x20202020,0x20202020, /* QW3,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW4,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW5,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW6,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW7,CHA-B, DQ5-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW0,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW1,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW2,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW3,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW4,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW5,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW6,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW7,CHA-B, DQ6-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW0,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW1,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW2,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW3,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW4,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW5,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW6,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080 /* QW7,CHA-B, DQ7-ODD */ -}; - -void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, u8 Pass) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->DCTSysLimit) { - 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); - } - } -} - -void TrainMaxRdLatency_En_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - uint8_t node; - struct DCTStatStruc *pDCTstat; - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - pDCTstat = pDCTstatA + node; - - if (pDCTstat->DCTSysLimit) { - if (is_fam15h()) { - dqsTrainMaxRdLatency_SW_Fam15(pMCTstat, pDCTstat); - } else { - /* FIXME - * Implement Family 10h MaxRdLatency training - */ - } - } - } -} - -static void SetEccDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 channel; - u8 direction; - - for (channel = 0; channel < 2; channel++) { - for (direction = 0; direction < 2; direction++) { - pDCTstat->Channel = channel; /* Channel A or B */ - pDCTstat->Direction = direction; /* Read or write */ - CalcEccDQSPos_D(pMCTstat, pDCTstat, pDCTstat->CH_EccDQSLike[channel], pDCTstat->CH_EccDQSScale[channel], ChipSel); - print_debug_dqs_pair("\t\tSetEccDQSRdWrPos: channel ", channel, direction == DQS_READDIR? " R dqs_delay":" W dqs_delay", pDCTstat->DQSDelay, 2); - pDCTstat->ByteLane = 8; - StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, ChipSel); - } - } -} - -static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u16 like, u8 scale, u8 ChipSel) -{ - uint8_t DQSDelay0, DQSDelay1; - int16_t delay_differential; - uint16_t DQSDelay; - - if (pDCTstat->Status & (1 << SB_Registered)) { - pDCTstat->ByteLane = 0x2; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay0 = pDCTstat->DQSDelay; - - pDCTstat->ByteLane = 0x3; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay1 = pDCTstat->DQSDelay; - - if (pDCTstat->Direction == DQS_READDIR) { - DQSDelay = DQSDelay1; - } else { - delay_differential = (int16_t)DQSDelay1 - (int16_t)DQSDelay0; - delay_differential += (int16_t)DQSDelay1; - - DQSDelay = delay_differential; - } - } else { - pDCTstat->ByteLane = like & 0xff; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay0 = pDCTstat->DQSDelay; - - pDCTstat->ByteLane = (like >> 8) & 0xff; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay1 = pDCTstat->DQSDelay; - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay0 - DQSDelay1; - } else { - DQSDelay = DQSDelay1 - DQSDelay0; - } - - DQSDelay = DQSDelay * (~scale); - - DQSDelay += 0x80; /* round it */ - - DQSDelay >>= 8; /* 256 */ - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay1 - DQSDelay; - } else { - DQSDelay += DQSDelay1; - } - } - - pDCTstat->DQSDelay = (u8)DQSDelay; -} - -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_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_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_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); -} - -/* DQS Position Training - * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.3 - */ -static void TrainDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 Errors; - u8 Channel; - u8 Receiver; - u8 _DisableDramECC = 0; - u32 PatternBuffer[304]; /* 288 + 16 */ - u8 _Wrap32Dis = 0, _SSE2 = 0; - - u32 dev; - u32 addr; - u8 valid; - CRx_TYPE cr4; - u32 lo, hi; - u32 index_reg; - uint32_t TestAddr; - - uint8_t dual_rank; - uint8_t iter; - uint8_t lane; - uint16_t bytelane_test_results; - uint16_t current_write_dqs_delay[MAX_BYTE_LANES]; - uint16_t current_read_dqs_delay[MAX_BYTE_LANES]; - uint16_t write_dqs_delay_stepping_done[MAX_BYTE_LANES]; - uint8_t dqs_read_results_array[2][MAX_BYTE_LANES][64]; /* [rank][lane][step] */ - uint8_t dqs_write_results_array[2][MAX_BYTE_LANES][128]; /* [rank][lane][step] */ - - uint8_t last_pos = 0; - uint8_t cur_count = 0; - uint8_t best_pos = 0; - uint8_t best_count = 0; - - print_debug_dqs("\nTrainDQSRdWrPos: 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_MSR; - _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); - - SetupDqsPattern_D(pMCTstat, pDCTstat, PatternBuffer); - - /* mct_BeforeTrainDQSRdWrPos_D */ - - dev = pDCTstat->dev_dct; - pDCTstat->Direction = DQS_READDIR; - - /* 2.8.9.9.3 (2) - * Loop over each channel, lane, and rank - */ - - /* NOTE - * The BKDG originally stated to iterate over lane, then rank, however this process is quite slow - * compared to an equivalent loop over rank, then lane as the latter allows multiple lanes to be - * tested simultaneously, thus improving performance by around 8x. - */ - - Errors = 0; - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - if (pDCTstat->DIMMValidDCT[Channel] == 0) /* mct_BeforeTrainDQSRdWrPos_D */ - continue; - - index_reg = 0x98; - - dual_rank = 0; - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each rank of each DIMM. - */ - for (; Receiver < 8; Receiver++) { - if ((Receiver & 0x1) == 0) { - /* Even rank of DIMM */ - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1)) - dual_rank = 1; - else - dual_rank = 0; - } - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - continue; - } - - /* Select the base test address for the current rank */ - TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver, &valid); - if (!valid) { /* Address not supported on current CS */ - continue; - } - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 14 TestAddr ", TestAddr, 4); - SetUpperFSbase(TestAddr); /* fs:eax = far ptr to target */ - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 12 Receiver ", Receiver, 2); - - /* 2.8.9.9.3 (DRAM Write Data Timing Loop) - * Iterate over all possible DQS delay values (0x0 - 0x7f) - */ - uint8_t test_write_dqs_delay = 0; - uint8_t test_read_dqs_delay = 0; - uint8_t passing_dqs_delay_found[MAX_BYTE_LANES]; - - /* Initialize variables */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - current_write_dqs_delay[lane] = 0; - passing_dqs_delay_found[lane] = 0; - write_dqs_delay_stepping_done[lane] = 0; - } - - for (test_write_dqs_delay = 0; test_write_dqs_delay < 128; test_write_dqs_delay++) { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 16 test_write_dqs_delay ", test_write_dqs_delay, 6); - - /* Break out of loop if passing window already found, */ - if (write_dqs_delay_stepping_done[0] && write_dqs_delay_stepping_done[1] - && write_dqs_delay_stepping_done[2] && write_dqs_delay_stepping_done[3] - && write_dqs_delay_stepping_done[4] && write_dqs_delay_stepping_done[5] - && write_dqs_delay_stepping_done[6] && write_dqs_delay_stepping_done[7]) - break; - - /* Commit the current Write Data Timing settings to the hardware registers */ - 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); - - /* 2.8.9.9.3 (DRAM Read DQS Timing Control Loop) - * Iterate over all possible DQS delay values (0x0 - 0x3f) - */ - for (test_read_dqs_delay = 0; test_read_dqs_delay < 64; test_read_dqs_delay++) { - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 test_read_dqs_delay ", test_read_dqs_delay, 6); - - /* Initialize Read DQS Timing Control settings for this iteration */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) - if (!write_dqs_delay_stepping_done[lane]) - 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, Channel, (Receiver >> 1), index_reg); - - /* Initialize test result variable */ - bytelane_test_results = 0xff; - - /* Read the DRAM training pattern from the base test address three times - * NOTE - * While the BKDG states to read three times this is probably excessive! - * Decrease training time by only reading the test pattern once per iteration - */ - for (iter = 0; iter < 1; iter++) { - /* Flush caches */ - SetTargetWTIO_D(TestAddr); - FlushDQSTestPattern_D(pDCTstat, TestAddr << 8); - ResetTargetWTIO_D(); - - /* Read and compare pattern */ - bytelane_test_results &= (CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 :: Lane 0] 0 = fail, 1 = pass */ - - /* If all lanes have already failed testing bypass remaining re-read attempt(s) */ - if (bytelane_test_results == 0x0) - break; - } - - /* Store any lanes that passed testing for later use */ - for (lane = 0; lane < 8; lane++) - if (!write_dqs_delay_stepping_done[lane]) - dqs_read_results_array[Receiver & 0x1][lane][test_read_dqs_delay] = (!!(bytelane_test_results & (1 << lane))); - - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 162 bytelane_test_results ", bytelane_test_results, 6); - } - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - if (write_dqs_delay_stepping_done[lane]) - continue; - - /* Determine location and length of longest consecutive string of passing values - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (iter = 0; iter < 64; iter++) { - if ((dqs_read_results_array[Receiver & 0x1][lane][iter]) && (iter < 63)) { - /* 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 = iter; - } - } - - if (best_count > 2) { - /* Exit the DRAM Write Data Timing Loop after programming the Read DQS Timing Control - * register with the center of the passing window - */ - current_read_dqs_delay[lane] = (best_pos + (best_count / 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, Channel, (Receiver >> 1), index_reg); - - /* Exit the DRAM Write Data Timing Loop */ - write_dqs_delay_stepping_done[lane] = 1; - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest passing region ", best_count, 4); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest passing region start ", best_pos, 4); - } - - /* Increment the DQS Write Delay value if needed for the next DRAM Write Data Timing Loop iteration */ - if (!write_dqs_delay_stepping_done[lane]) - current_write_dqs_delay[lane]++; - } - } - - /* Flag failure(s) if present */ - for (lane = 0; lane < 8; 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; - } - } - - /* Iterate over all possible Write Data Timing values (0x0 - 0x7f) - * Note that the Read DQS Timing Control was calibrated / centered in the prior nested loop - */ - for (test_write_dqs_delay = 0; test_write_dqs_delay < 128; test_write_dqs_delay++) { - /* Initialize Write Data Timing settings for this iteration */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) - 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, Channel, (Receiver >> 1), index_reg); - - /* Write the DRAM training pattern to the base test address */ - WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); - - /* Flush caches */ - SetTargetWTIO_D(TestAddr); - FlushDQSTestPattern_D(pDCTstat, TestAddr << 8); - ResetTargetWTIO_D(); - - /* Read and compare pattern from the base test address */ - bytelane_test_results = (CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 :: Lane 0] 0 = fail, 1 = pass */ - - /* Store any lanes that passed testing for later use */ - for (lane = 0; lane < 8; lane++) - dqs_write_results_array[Receiver & 0x1][lane][test_write_dqs_delay] = (!!(bytelane_test_results & (1 << lane))); - } - - for (lane = 0; lane < 8; lane++) { - if ((!dual_rank) || (dual_rank && (Receiver & 0x1))) { - -#ifdef PRINT_PASS_FAIL_BITMAPS - for (iter = 0; iter < 64; iter++) { - if (dqs_read_results_array[0][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n"); - for (iter = 0; iter < 64; iter++) { - if (dqs_read_results_array[1][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n\n"); - for (iter = 0; iter < 128; iter++) { - if (dqs_write_results_array[0][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n"); - for (iter = 0; iter < 128; iter++) { - if (dqs_write_results_array[1][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n\n"); -#endif - - /* Base rank of single-rank DIMM, or odd rank of dual-rank DIMM */ - if (dual_rank) { - /* Intersect the passing windows of both ranks */ - for (iter = 0; iter < 64; iter++) - if (!dqs_read_results_array[1][lane][iter]) - dqs_read_results_array[0][lane][iter] = 0; - for (iter = 0; iter < 128; iter++) - if (!dqs_write_results_array[1][lane][iter]) - dqs_write_results_array[0][lane][iter] = 0; - } - - /* Determine location and length of longest consecutive string of passing values for read DQS timing - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (iter = 0; iter < 64; iter++) { - if ((dqs_read_results_array[0][lane][iter]) && (iter < 63)) { - /* 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 = iter; - } - } - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region ", best_count, 4); - if (best_count > 0) { - if (best_count < MIN_DQS_WNDW) { - /* Flag excessively small passing window */ - Errors |= 1 << SB_SMALLDQS; - } - - /* Find the center of the passing window */ - 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, 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]; - } else { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 122 Unable to find read passing region for lane ", lane, 2); - - /* Flag absence of passing window */ - Errors |= 1 << SB_NODQSPOS; - } - - /* Determine location and length of longest consecutive string of passing values for write DQS timing - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (iter = 0; iter < 128; iter++) { - if ((dqs_write_results_array[0][lane][iter]) && (iter < 127)) { - /* 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 = iter; - } - } - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region ", best_count, 4); - if (best_count > 0) { - if (best_count < MIN_DQS_WNDW) { - /* Flag excessively small passing window */ - Errors |= 1 << SB_SMALLDQS; - } - - /* Find the center of the passing window */ - 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, 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]; - } else { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 123 Unable to find write 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 - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - if (!_Wrap32Dis) { - addr = HWCR_MSR; - _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, "TrainDQSRdWrPos: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: TrainErrors %x\n", pDCTstat->TrainErrors); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: ErrCode %x\n", pDCTstat->ErrCode); - 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 - */ -void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t calc_min) -{ - 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}; - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: Start\n", __func__); -#endif - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - mem_clk = Get_NB32_DCT(dev, dct, 0x94) & 0x1f; - if (fam15h_freq_tab[mem_clk] == 0) { - pDCTstat->CH_MaxRdLat[dct][0] = 0x55; - pDCTstat->CH_MaxRdLat[dct][1] = 0x55; - return; - } - - /* 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) */ - if (!calc_min) - 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_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - for (lane = 0; lane < lane_count; 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) */ - if (!calc_min) - p += 5; - - /* 2.10.5.8.5 (9) */ - t += 800; - - /* 2.10.5.8.5 (10) */ - 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) */ - if (!calc_min) - n -= 1; - - /* 2.10.5.8.5 (12) */ - if (!calc_min) { - 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][nb_pstate] = n - 1; - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: CH_MaxRdLat[%d][%d]: %03x\n", __func__, dct, nb_pstate, pDCTstat->CH_MaxRdLat[dct][nb_pstate]); -#endif - } - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: Done\n", __func__); -#endif -} - -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); -} - -void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error) -{ - 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); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane < 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~(0xff << ((lane - 4) * 8))); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 0xff) { - Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); - Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); - dword = Get_NB32_DCT(dev, dct, 0x27c); - if (get_available_lane_count(pMCTstat, pDCTstat) < 9) - dword |= 0xff; /* EccMask = 0xff */ - else - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } 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 = 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 = stop_on_error */ - dword |= (stop_on_error & 0x1) << 4; - 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); -} - -void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error) -{ - 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); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane < 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~(0xff << ((lane - 4) * 8))); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 0xff) { - Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); - Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); - dword = Get_NB32_DCT(dev, dct, 0x27c); - if (get_available_lane_count(pMCTstat, pDCTstat) < 9) - dword |= 0xff; /* EccMask = 0xff */ - else - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } 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 = 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 = stop_on_error */ - dword |= (stop_on_error & 0x1) << 4; - 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); -} - -#define LANE_DIFF 1 - -/* 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 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; - uint8_t check_antiphase; - uint8_t passing_read_dqs_delay_found; - uint8_t passing_write_dqs_delay_found; - 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]; - /* [rank][lane][write step][read step + 16] */ - uint8_t dqs_results_array[2][LANE_DIFF][32][48]; - - 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; - - uint8_t lane_end = lane_start + LANE_DIFF; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - /* Calculate and program MaxRdLatency */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct, 0); - - Errors = 0; - dual_rank = 0; - - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each rank within each DIMM. - */ - for (Receiver = receiver_start; Receiver < receiver_end; Receiver++) { - 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; - } - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "TrainDQSRdWrPos: Training DQS read/write position for receiver %d (DIMM %d)\n", Receiver, dimm); -#endif - - /* Initialize variables */ - for (lane = lane_start; lane < lane_end; lane++) { - passing_dqs_delay_found[lane] = 0; - } - if ((Receiver & 0x1) == 0) { - /* Even rank of DIMM */ - 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); - } - - /* Initialize iterators */ - memcpy(current_write_data_delay, initial_write_data_timing, sizeof(current_write_data_delay)); - - for (lane = lane_start; lane < lane_end; lane++) { - passing_read_dqs_delay_found = 0; - passing_write_dqs_delay_found = 0; - - /* 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, 0); - - /* 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] < 0x20; current_read_dqs_delay[lane]++) { - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 current_read_dqs_delay[lane] ", current_read_dqs_delay[lane], 6); - - if (current_read_dqs_delay[lane] >= (32 - 16)) { - check_antiphase = 1; - } else { - check_antiphase = 0; - } - - /* 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, ((check_antiphase == 0)?1:0)); - - if (check_antiphase == 0) { - /* Check for early abort before analyzing per-nibble status */ - dword = Get_NB32_DCT(dev, dct, 0x264); - if ((dword & 0x1ffffff) != 0) { - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 162 early abort: F2x264 ", dword, 6); - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] + 16] = 0; /* Fail */ - continue; - } - } - - /* 2.10.5.8.4 (2 A iii) - * Record pass / fail status - */ - dword = Get_NB32_DCT(dev, dct, 0x268) & 0x3ffff; - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 163 read results: F2x268 ", dword, 6); - 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] + 16] = 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] + 16] = 1; /* Pass */ - if (check_antiphase == 1) { - /* Check antiphase results */ - dword = Get_NB32_DCT(dev, dct, 0x26c) & 0x3ffff; - if (dword & (0x3 << (lane * 2))) - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][16 - (32 - current_read_dqs_delay[lane])] = 0; /* Fail */ - else - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][16 - (32 - current_read_dqs_delay[lane])] = 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 < 48; 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 < 48; read_iter++) { - if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (read_iter < 47)) { - /* 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 + 1; - } - } - last_pos = 0; - } - - if (best_count > 2) { - uint16_t region_center = (best_pos + (best_count / 2)); - - if (region_center < 16) { - printk(BIOS_WARNING, "TrainDQSRdWrPos: negative DQS recovery delay detected!" - " Attempting to continue but your system may be unstable...\n"); - region_center = 0; - } else { - region_center -= 16; - } - - /* 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] = region_center; - 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); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region center (raw hardware value) ", region_center, 4); - } else { - /* 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)); - - /* 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 < 48; 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 + 1; - } - } - 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_write_dqs_delay_found = 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: 145 largest write passing region ", best_count, 4); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 146 largest write passing region start ", best_pos, 4); - } else { - /* 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)); - - /* 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); - } - - if (passing_read_dqs_delay_found && passing_write_dqs_delay_found) - passing_dqs_delay_found[lane] = 1; - } - -#ifdef PRINT_PASS_FAIL_BITMAPS - for (lane = lane_start; lane < lane_end; lane++) { - for (write_iter = 0; write_iter < 32; write_iter++) { - for (read_iter = 0; read_iter < 48; read_iter++) { - if (dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) { - printk(BIOS_DEBUG, "+"); - } else { - if (read_iter < 16) - 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; - CRx_TYPE cr4; - u32 lo, hi; - - uint8_t dct; - uint8_t prev; - uint8_t dimm; - uint8_t lane; - uint32_t dword; - uint32_t rx_en_offset; - uint8_t internal_lane; - uint8_t dct_training_success; - uint8_t lane_success_count; - uint16_t initial_phy_phase_delay[MAX_BYTE_LANES]; - uint16_t current_phy_phase_delay[MAX_BYTE_LANES]; - uint16_t current_read_dqs_delay[MAX_BYTE_LANES]; - uint8_t lane_training_success[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; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - 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_MSR; - _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] */ - /* NOTE: DisablePredriverCal only takes effect when set on DCT 0 */ - 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); - - /* Indicate success unless training the DCT explicitly fails */ - dct_training_success = 1; - - /* 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; - } - - /* Initialize variables */ - memset(lane_training_success, 0, sizeof(lane_training_success)); - memset(current_phy_phase_delay, 0, sizeof(current_phy_phase_delay)); - - /* 2.10.5.8.3 (2) */ - read_dqs_receiver_enable_control_registers(initial_phy_phase_delay, dev, dct, dimm, index_reg); - - /* Reset the read data timing registers to 1UI before calculating MaxRdLatency */ - for (internal_lane = 0; internal_lane < MAX_BYTE_LANES; internal_lane++) - current_read_dqs_delay[internal_lane] = 0x20; - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - - for (lane = 0; lane < lane_count; lane++) { - /* Initialize variables */ - memset(dqs_results_array, 0, sizeof(dqs_results_array)); - lane_success_count = 0; - - /* 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) */ -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 Receiver %d lane %d initial phy delay %04x: iterating from %04x to %04x\n", Receiver, lane, initial_phy_phase_delay[lane], rx_en_offset, 0x3ff); -#endif - for (current_phy_phase_delay[lane] = rx_en_offset; current_phy_phase_delay[lane] < 0x3ff; current_phy_phase_delay[lane] += ren_step) { -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: Receiver %d lane %d current phy delay: %04x\n", __func__, Receiver, lane, current_phy_phase_delay[lane]); -#endif - - /* 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, 0); - - /* 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); - - if (dqs_results_array[current_phy_phase_delay[lane]]) - lane_success_count++; - - /* Don't bother testing larger values if the end of the passing window was already found */ - if (!dqs_results_array[current_phy_phase_delay[lane]] && (lane_success_count > 1)) - break; - } - - uint16_t phase_delay; - for (phase_delay = 0; phase_delay < 0x3ff; phase_delay++) - if (dqs_results_array[phase_delay]) - lane_training_success[lane] = 1; - - if (!lane_training_success[lane]) { - if (pDCTstat->tcwl_delay[dct] >= 1) { - Errors |= 1 << SB_FatalError; - printk(BIOS_ERR, "%s: lane %d failed to train! " - "Training for receiver %d on DCT %d aborted\n", - __func__, lane, Receiver, dct); - } - - /* Restore BlockRxDqsLock setting to normal operation in preparation for retraining */ - 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); - - break; - } - -#ifdef PRINT_PASS_FAIL_BITMAPS - for (phase_delay = 0; phase_delay < 0x3ff; phase_delay++) { - if (dqs_results_array[phase_delay]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n"); -#endif - - /* 2.10.5.8.3 (5) */ - prev = dqs_results_array[rx_en_offset]; - for (current_phy_phase_delay[lane] = rx_en_offset + ren_step; 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) */ - if (current_phy_phase_delay[lane] < 0x10) - current_phy_phase_delay[lane] = 0x0; - else - 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); - TrainDQSRdWrPos_D_Fam15(pMCTstat, pDCTstat, dct, - Receiver, Receiver + 2, - lane); - 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); - } - - for (lane = 0; lane < lane_count; lane++) { - if (!lane_training_success[lane]) { - dct_training_success = 0; - Errors |= 1 << SB_NODQSPOS; - } - } - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 DQS receiver enable timing: "); - for (lane = 0; lane < lane_count; lane++) { - printk(BIOS_DEBUG, " %03x", current_phy_phase_delay[lane]); - } - printk(BIOS_DEBUG, "\n"); -#endif - } - - if (!dct_training_success) { - if (pDCTstat->tcwl_delay[dct] < 1) { - /* Increase TCWL */ - pDCTstat->tcwl_delay[dct]++; - /* Request retraining */ - Errors |= 1 << SB_RetryConfigTrain; - } - } - } - - 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_MSR; - _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) -{ - /* 1. Set the Pattern type (0 or 1) in DCTStatstruc.Pattern - * 2. Copy the pattern from ROM to Cache, aligning on 16 byte boundary - * 3. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufA - */ - - u32 *buf; - u16 i; - - buf = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - if (pDCTstat->Status & (1<<SB_128bitmode)) { - pDCTstat->Pattern = 1; /* 18 cache lines, alternating qwords */ - for (i = 0; i < 16*18; i++) - buf[i] = TestPatternJD1b_D[i]; - } else { - pDCTstat->Pattern = 0; /* 9 cache lines, sequential qwords */ - for (i = 0; i < 16*9; i++) - buf[i] = TestPatternJD1a_D[i]; - } - pDCTstat->PtrPatternBufA = (u32)buf; -} - -static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - /* Store the DQSDelay value, found during a training sweep, into the DCT - * status structure for this node - */ - - /* When 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above + 0x100 to next dimm - */ - - /* FindDQSDatDimmVal_D is not required since we use an array */ - u8 dn = 0; - - dn = ChipSel>>1; /* if odd or even logical DIMM */ - - pDCTstat->CH_D_DIR_B_DQS[pDCTstat->Channel][dn][pDCTstat->Direction][pDCTstat->ByteLane] = - pDCTstat->DQSDelay; -} - -static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 dn = 0; - - /* When 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above + 0x100 to next dimm - */ - - /* FindDQSDatDimmVal_D is not required since we use an array */ - dn = ChipSel >> 1; /*if odd or even logical DIMM */ - - pDCTstat->DQSDelay = - pDCTstat->CH_D_DIR_B_DQS[pDCTstat->Channel][dn][pDCTstat->Direction][pDCTstat->ByteLane]; -} - -/* FindDQSDatDimmVal_D is not required since we use an array */ - -void proc_IOCLFLUSH_D(u32 addr_hi) -{ - SetTargetWTIO_D(addr_hi); - proc_CLFLUSH(addr_hi); - ResetTargetWTIO_D(); -} - -u8 ChipSelPresent_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel) -{ - u32 val; - u32 reg; - u32 dev = pDCTstat->dev_dct; - uint8_t dct = 0; - u8 ret = 0; - - if (!pDCTstat->GangedMode) - dct = Channel; - else - dct = 0; - - if (ChipSel < MAX_CS_SUPPORTED) { - reg = 0x40 + (ChipSel << 2); - val = Get_NB32_DCT(dev, dct, reg); - if (val & (1 << 0)) - ret = 1; - } - - return ret; -} - -/* proc_CLFLUSH_D located in mct_gcc.h */ - -static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - /* Write a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - if (pDCTstat->Pattern == 0) - WriteL9TestPattern_D(pDCTstat, TestAddr_lo); - else - WriteL18TestPattern_D(pDCTstat, TestAddr_lo); -} - -static void WriteL18TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - u8 *buf; - - buf = (u8 *)pDCTstat->PtrPatternBufA; - WriteLNTestPattern(TestAddr_lo, buf, 18); - -} - -static void WriteL9TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - u8 *buf; - - buf = (u8 *)pDCTstat->PtrPatternBufA; - WriteLNTestPattern(TestAddr_lo, buf, 9); -} - -static u16 CompareDQSTestPattern_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 addr_lo) -{ - /* Compare a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - - u32 *test_buf; - u16 MEn1Results, bitmap; - u8 bytelane; - u8 i; - u32 value; - u8 j; - u32 value_test; - u32 value_r = 0, value_r_test = 0; - u8 pattern, channel, BeatCnt; - struct DCTStatStruc *ptrAddr; - - ptrAddr = pDCTstat; - pattern = pDCTstat->Pattern; - channel = pDCTstat->Channel; - test_buf = (u32 *)pDCTstat->PtrPatternBufA; - - if (pattern && channel) { - addr_lo += 8; /* second channel */ - test_buf += 2; - } - - bytelane = 0; /* bytelane counter */ - bitmap = 0xFFFF; /* bytelane test bitmap, 1 = pass */ - MEn1Results = 0xFFFF; - BeatCnt = 0; - for (i = 0; i < (9 * 64 / 4); i++) { /* sizeof testpattern. /4 due to next loop */ - value = read32_fs(addr_lo); - value_test = *test_buf; - - print_debug_dqs_pair("\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value = ", value_test, 7); - print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value = ", value, 7); - - if (pDCTstat->Direction == DQS_READDIR) { - if (BeatCnt != 0) { - value_r = *test_buf; - if (pattern) /* if multi-channel */ - value_r_test = read32_fs(addr_lo - 16); - else - value_r_test = read32_fs(addr_lo - 8); - } - print_debug_dqs_pair("\t\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value_r_test = ", value_r, 7); - print_debug_dqs_pair("\t\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value_r = ", value_r_test, 7); - } - - for (j = 0; j < (4 * 8); j += 8) { /* go through a 32bit data, on 1 byte step. */ - if (((value >> j) & 0xff) != ((value_test >> j) & 0xff)) { - bitmap &= ~(1 << bytelane); - } - - if (pDCTstat->Direction == DQS_READDIR) { - if (BeatCnt != 0) { - if (((value_r >> j) & 0xff) != ((value_r_test >> j) & 0xff)) { - MEn1Results &= ~(1 << bytelane); - } - } - } - bytelane++; - bytelane &= 0x7; - } - - print_debug_dqs("\t\t\t\t\t\tbitmap = ", bitmap, 7); - print_debug_dqs("\t\t\t\t\t\tMEn1Results = ", MEn1Results, 7); - - if (!bitmap) - break; - - if (bytelane == 0) { - BeatCnt += 4; - if (!(pDCTstat->Status & (1 << SB_128bitmode))) { - if (BeatCnt == 8) BeatCnt = 0; /* 8 beat burst */ - } else { - if (BeatCnt == 4) BeatCnt = 0; /* 4 beat burst */ - } - if (pattern == 1) { /* dual channel */ - addr_lo += 8; /* skip over other channel's data */ - test_buf += 2; - } - } - addr_lo += 4; - test_buf += 1; - } - - if (pDCTstat->Direction == DQS_READDIR) { - bitmap &= 0xFF; - bitmap |= MEn1Results << 8; - } - - print_debug_dqs("\t\t\t\t\t\tbitmap = ", bitmap, 6); - - return bitmap; -} - -static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat, - u32 addr_lo) -{ - /* Flush functions in mct_gcc.h */ - if (pDCTstat->Pattern == 0) { - FlushDQSTestPattern_L9(addr_lo); - } else { - FlushDQSTestPattern_L18(addr_lo); - } -} - -void SetTargetWTIO_D(u32 TestAddr) -{ - u32 lo, hi; - hi = TestAddr >> 24; - lo = TestAddr << 8; - _WRMSR(MTRR_IORR0_BASE, lo, hi); /* IORR0 Base */ - hi = 0xFF; - lo = 0xFC000800; /* 64MB Mask */ - _WRMSR(MTRR_IORR0_MASK, lo, hi); /* IORR0 Mask */ -} - -void ResetTargetWTIO_D(void) -{ - u32 lo, hi; - - hi = 0; - lo = 0; - _WRMSR(MTRR_IORR0_MASK, lo, hi); /* IORR0 Mask */ -} - -u32 SetUpperFSbase(u32 addr_hi) -{ - /* Set the upper 32-bits of the Base address, 4GB aligned) for the - * FS selector. - */ - u32 lo, hi; - u32 addr; - lo = 0; - hi = addr_hi>>24; - addr = FS_Base; - _WRMSR(addr, lo, hi); - return addr_hi << 8; -} - -void ResetDCTWrPtr_D(u32 dev, uint8_t dct, u32 index_reg, u32 index) -{ - u32 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, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 ChipSel; - struct DCTStatStruc *pDCTstat; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - if (pDCTstat->DCTSysLimit) { - 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); - } - } - } - } -} - -/* mct_BeforeTrainDQSRdWrPos_D - * Function is inline. - */ -u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 _DisableDramECC = 0; - u32 val; - u32 reg; - u32 dev; - - /*Disable ECC correction of reads on the dram bus. */ - - dev = pDCTstat->dev_dct; - reg = 0x90; - val = Get_NB32_DCT(dev, 0, reg); - if (val & (1<<DimmEcEn)) { - _DisableDramECC |= 0x01; - val &= ~(1<<DimmEcEn); - Set_NB32_DCT(dev, 0, reg, val); - } - if (!pDCTstat->GangedMode) { - val = Get_NB32_DCT(dev, 1, reg); - if (val & (1<<DimmEcEn)) { - _DisableDramECC |= 0x02; - val &= ~(1<<DimmEcEn); - Set_NB32_DCT(dev, 1, reg, val); - } - } - return _DisableDramECC; -} - -void mct_EnableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 _DisableDramECC) -{ - u32 val; - u32 dev; - - /* Enable ECC correction if it was previously disabled */ - dev = pDCTstat->dev_dct; - - if ((_DisableDramECC & 0x01) == 0x01) { - val = Get_NB32_DCT(dev, 0, 0x90); - val |= (1<<DimmEcEn); - Set_NB32_DCT(dev, 0, 0x90, val); - } - if ((_DisableDramECC & 0x02) == 0x02) { - val = Get_NB32_DCT(dev, 1, 0x90); - val |= (1<<DimmEcEn); - Set_NB32_DCT(dev, 1, 0x90, val); - } -} - -/* - * Set DQS delay value to related register - */ -static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 ByteLane; - u32 val; - u32 index_reg = 0x98; - u8 shift; - u32 dqs_delay = (u32)pDCTstat->DQSDelay; - u32 dev = pDCTstat->dev_dct; - u32 index; - - ByteLane = pDCTstat->ByteLane; - - if (!(pDCTstat->DqsRdWrPos_Saved & (1 << ByteLane))) { - /* Channel is offset */ - if (ByteLane < 4) { - index = 1; - } else if (ByteLane <8) { - index = 2; - } else { - index = 3; - } - - if (pDCTstat->Direction == DQS_READDIR) { - index += 4; - } - - /* get the proper register index */ - shift = ByteLane % 4; - shift <<= 3; /* get bit position of bytelane, 8 bit */ - - index += (ChipSel>>1) << 8; - - val = Get_NB32_index_wait_DCT(dev, pDCTstat->Channel, index_reg, index); - if (ByteLane < 8) { - if (pDCTstat->Direction == DQS_WRITEDIR) { - dqs_delay += pDCTstat->persistentData.CH_D_B_TxDqs[pDCTstat->Channel][ChipSel>>1][ByteLane]; - } else { - dqs_delay <<= 1; - } - } - val &= ~(0x7f << shift); - val |= (dqs_delay << shift); - Set_NB32_index_wait_DCT(dev, pDCTstat->Channel, index_reg, index, val); - } -} - -u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel) -{ - u8 ret; - - ret = ChipSelPresent_D(pMCTstat, pDCTstat, Channel, ChipSel); - return ret; -} - -u32 mct_GetRcvrSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 channel, u8 receiver, u8 *valid) -{ - return mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, channel, receiver, valid); -} - -u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 receiver, u8 *valid) -{ - u32 val; - uint8_t dct = 0; - u32 reg; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - *valid = 0; - - - if (!pDCTstat->GangedMode) { - dct = Channel; - } - - /* get the local base addr of the chipselect */ - reg = 0x40 + (receiver << 2); - val = Get_NB32_DCT(dev, dct, reg); - - val &= ~0xe007c01f; - - /* unganged mode DCT0+DCT1, sys addr of DCT1 = node - * base+DctSelBaseAddr+local ca base*/ - if ((Channel) && (pDCTstat->GangedMode == 0) && (pDCTstat->DIMMValidDCT[0] > 0)) { - reg = 0x110; - dword = Get_NB32(dev, reg); - dword &= 0xfffff800; - dword <<= 8; /* scale [47:27] of F2x110[31:11] to [39:8]*/ - val += dword; - - /* if DCTSelBaseAddr < Hole, and eax > HoleBase, then add Hole size to test address */ - if ((val >= pDCTstat->DCTHoleBase) && (pDCTstat->DCTHoleBase > dword)) { - dword = (~(pDCTstat->DCTHoleBase >> (24 - 8)) + 1) & 0xFF; - dword <<= (24 - 8); - val += dword; - } - } else { - /* sys addr = node base+local cs base */ - val += pDCTstat->DCTSysBase; - - /* New stuff */ - if (pDCTstat->DCTHoleBase && (val >= pDCTstat->DCTHoleBase)) { - val -= pDCTstat->DCTSysBase; - dword = Get_NB32(pDCTstat->dev_map, 0xF0); /* get Hole Offset */ - val += (dword & 0x0000ff00) << (24-8-8); - } - } - - /* New stuff */ - val += ((1 << 21) >> 8); /* Add 2MB offset to avoid compat area */ - if (val >= MCT_TRNG_KEEPOUT_START) { - while (val < MCT_TRNG_KEEPOUT_END) - val += (1 << (15-8)); /* add 32K */ - } - - /* Add a node seed */ - val += (((1 * pDCTstat->Node_ID) << 20) >> 8); /* Add 1MB per node to avoid aliases */ - - /* HW remap disabled? */ - if (!(pDCTstat->Status & (1 << SB_HWHole))) { - if (!(pDCTstat->Status & (1 << SB_SWNodeHole))) { - /* SW memhole disabled */ - u32 lo, hi; - _RDMSR(TOP_MEM, &lo, &hi); - lo >>= 8; - if ((val >= lo) && (val < _4GB_RJ8)) { - val = 0; - *valid = 0; - goto exitGetAddr; - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - -exitGetAddrWNoError: - - /* Skip if Address is in UMA region */ - dword = pMCTstat->Sub4GCacheTop; - dword >>= 8; - if (dword != 0) { - if ((val >= dword) && (val < _4GB_RJ8)) { - val = 0; - *valid = 0; - } else { - *valid = 1; - } - } - print_debug_dqs("mct_GetMCTSysAddr_D: receiver ", receiver, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: Channel ", Channel, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: base_addr ", val, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: valid ", *valid, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: status ", pDCTstat->Status, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: SysBase ", pDCTstat->DCTSysBase, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: HoleBase ", pDCTstat->DCTHoleBase, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: Cachetop ", pMCTstat->Sub4GCacheTop, 2); - -exitGetAddr: - return val; -} - -void mct_Write1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr, u8 pattern) -{ - - u8 *buf; - - /* Issue the stream of writes. When F2x11C[MctWrLimit] is reached - * (or when F2x11C[FlushWr] is set again), all the writes are written - * to DRAM. - */ - - SetUpperFSbase(TestAddr); - - if (pattern) - buf = (u8 *)pDCTstat->PtrPatternBufB; - else - buf = (u8 *)pDCTstat->PtrPatternBufA; - - WriteLNTestPattern(TestAddr << 8, buf, 1); -} - -void mct_Read1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 addr) -{ - u32 value; - - /* BIOS issues the remaining (Ntrain - 2) reads after checking that - * F2x11C[PrefDramTrainMode] is cleared. These reads must be to - * consecutive cache lines (i.e., 64 bytes apart) and must not cross - * a naturally aligned 4KB boundary. These reads hit the prefetches and - * read the data from the prefetch buffer. - */ - - /* get data from DIMM */ - SetUpperFSbase(addr); - - /* 1st move causes read fill (to exclusive or shared)*/ - value = read32_fs(addr << 8); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c deleted file mode 100644 index 4c33b9e4b6..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2015 - 2016 Raptor Engineering, LLC - * - * 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. - */ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> -#include <device/pci_ops.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -static void setSyncOnUnEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat); - -static 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; -} - -/* Initialize ECC modes of Integrated Dram+Memory Controllers of a network of - * Hammer processors. Use Dram background scrubber to fast initialize ECC bits - * of all dram. - * - * Notes: - * - * Order that items are set: - * 1. eccen bit in NB - * 2. Scrub Base - * 3. Temp Node Base - * 4. Temp Node Limit - * 5. Redir bit in NB - * 6. Scrub CTL - * - * Conditions for setting background scrubber. - * 1. node is present - * 2. node has dram functioning (WE = RE = 1) - * 3. all eccdimms (or bit 17 of offset 90,fn 2) - * 4. no chip-select gap exists - * - * The dram background scrubber is used under very controlled circumstances to - * initialize all the ECC bits on the DIMMs of the entire dram address map - * (including hidden or lost dram and dram above 4GB). We will turn the scrub - * rate up to maximum, which should clear 4GB of dram in about 2.7 seconds. - * We will activate the scrubbers of all nodes with ecc dram and let them run in - * parallel, thereby reducing even further the time required to condition dram. - * Finally, we will go through each node and either disable background scrubber, - * or set the scrub rate to the user setup specified rate. - * - * To allow the NB to scrub, we need to wait a time period long enough to - * guarantee that the NB scrubs the entire dram on its node. Do do this, we - * simply sample the scrub ADDR once, for an initial value, then we sample and poll until the polled value of scrub ADDR - * has wrapped around at least once: Scrub ADDRi+1 < Scrub ADDRi. Since we let all - * Nodes run in parallel, we need to guarantee that all nodes have wrapped. To do - * this efficiently, we need only to sample one of the nodes, the node with the - * largest ammount of dram populated is the one which will take the longest amount - * of time (the scrub rate is set to max, the same rate, on all nodes). So, - * during setup of scrub Base, we determine how much memory and which node has - * the largest memory installed. - * - * Scrubbing should not ordinarily be enabled on a Node with a chip-select gap - * (aka SW memhole, cs hoisting, etc..).To init ECC memory on this node, the - * scrubber is used in two steps. First, the Dram Limit for the node is adjusted - * down to the bottom of the gap, and that ECC dram is initialized. Second, the - * original Limit is restored, the Scrub base is set to 4GB, and scrubber is - * allowed to run until the Scrub Addr wraps around to zero. - */ -u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 AllECC; - u16 OB_NBECC; - u32 curBase; - u16 OB_ECCRedir; - u32 LDramECC; - u32 OF_ScrubCTL; - u16 OB_ChipKill; - u8 MemClrECC; - - u32 dev; - u32 reg; - u32 val; - u16 nvbits; - - uint32_t dword; - uint8_t sync_flood_on_dram_err[MAX_NODES_SUPPORTED]; - uint8_t sync_flood_on_any_uc_err[MAX_NODES_SUPPORTED]; - - mctHookBeforeECC(); - - /* 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_ECCRedir = mctGet_NVbits(NV_ECCRedir); /* ECC Redirection */ - - OB_ChipKill = mctGet_NVbits(NV_ChipKill); /* ECC Chip-kill mode */ - OF_ScrubCTL = 0; /* Scrub CTL for Dcache, L2, and dram */ - - 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_L3BKScrub); - OF_ScrubCTL |= (nvbits & 0x1f) << 24; /* L3Scrub = NV_L3BKScrub */ - - nvbits = mctGet_NVbits(NV_DramBKScrub); - OF_ScrubCTL |= nvbits; /* DramScrub = NV_DramBKScrub */ - - /* Prevent lockups on DRAM errors during ECC init */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (NodePresent_D(Node)) { - dword = Get_NB32(pDCTstat->dev_nbmisc, 0x44); - sync_flood_on_dram_err[Node] = (dword >> 30) & 0x1; - sync_flood_on_any_uc_err[Node] = (dword >> 21) & 0x1; - dword &= ~(0x1 << 30); - dword &= ~(0x1 << 21); - Set_NB32(pDCTstat->dev_nbmisc, 0x44, dword); - - uint32_t mc4_status_high = pci_read_config32(pDCTstat->dev_nbmisc, 0x4c); - uint32_t mc4_status_low = pci_read_config32(pDCTstat->dev_nbmisc, 0x48); - if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) { - printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected!\n" - "Signature: %08x%08x\n", mc4_status_high, mc4_status_low); - } - - /* Clear MC4 error status */ - pci_write_config32(pDCTstat->dev_nbmisc, 0x48, 0x0); - pci_write_config32(pDCTstat->dev_nbmisc, 0x4c, 0x0); - } - } - - AllECC = 1; - MemClrECC = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - LDramECC = 0; - if (NodePresent_D(Node)) { /*If Node is present */ - dev = pDCTstat->dev_map; - reg = 0x40+(Node << 3); /* Dram Base Node 0 + index */ - val = Get_NB32(dev, reg); - - /* WE/RE is checked */ - if ((val & 3) == 3) { /* Node has dram populated */ - /* Negate 'all nodes/dimms ECC' flag if non ecc - memory populated */ - if (pDCTstat->Status & (1 << SB_ECCDIMMs)) { - LDramECC = isDramECCEn_D(pDCTstat); - if (pDCTstat->ErrCode != SC_RunningOK) { - pDCTstat->Status &= ~(1 << SB_ECCDIMMs); - if (!OB_NBECC) { - pDCTstat->ErrStatus |= (1 << SB_DramECCDis); - } - AllECC = 0; - LDramECC = 0; - } - } else { - AllECC = 0; - } - if (LDramECC) { /* if ECC is enabled on this dram */ - if (OB_NBECC) { - mct_EnableDatIntlv_D(pMCTstat, pDCTstat); - val = Get_NB32(pDCTstat->dev_dct, 0x110); - val |= 1 << 5; /* DctDatIntLv = 1 */ - Set_NB32(pDCTstat->dev_dct, 0x110, val); - dev = pDCTstat->dev_nbmisc; - reg = 0x44; /* MCA NB Configuration */ - val = Get_NB32(dev, reg); - val |= 1 << 22; /* EccEn */ - Set_NB32(dev, reg, val); - DCTMemClr_Init_D(pMCTstat, pDCTstat); - MemClrECC = 1; - printk(BIOS_DEBUG, " ECC enabled on node: %02x\n", Node); - } - } /* this node has ECC enabled dram */ - - if (MemClrECC) { - DCTMemClr_Sync_D(pMCTstat, pDCTstat); - } - } else { - LDramECC = 0; - } /* Node has Dram */ - } /* if Node present */ - } - - if (AllECC) - pMCTstat->GStatus |= 1 << GSB_ECCDIMMs; - else - pMCTstat->GStatus &= ~(1 << GSB_ECCDIMMs); - - /* Program the Dram BKScrub CTL to the proper (user selected) value.*/ - /* Reset MC4_STS. */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - LDramECC = 0; - if (NodePresent_D(Node)) { /* If Node is present */ - reg = 0x40+(Node << 3); /* Dram Base Node 0 + index */ - val = Get_NB32(pDCTstat->dev_map, reg); - curBase = val & 0xffff0000; - /*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 */ - dev = pDCTstat->dev_nbmisc; - val = curBase << 8; - if (OB_ECCRedir) { - val |= (1 << 0); /* Enable redirection */ - } - Set_NB32(dev, 0x5c, val); /* Dram Scrub Addr Low */ - val = curBase >> 24; - Set_NB32(dev, 0x60, val); /* Dram Scrub Addr High */ - - /* Set scrub rate controls */ - if (is_fam15h()) { - /* Erratum 505 */ - fam15h_switch_dct(pDCTstat->dev_map, 0); - } - Set_NB32(dev, 0x58, OF_ScrubCTL); /* Scrub Control */ - if (is_fam15h()) { - fam15h_switch_dct(pDCTstat->dev_map, 1); /* Erratum 505 */ - Set_NB32(dev, 0x58, OF_ScrubCTL); /* Scrub Control */ - fam15h_switch_dct(pDCTstat->dev_map, 0); /* Erratum 505 */ - } - - 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); - } - } - } - - if (pDCTstat->LogicalCPUID & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) { - /* Set up message triggered C1E */ - val = pci_read_config32(pDCTstat->dev_nbmisc, 0xd4); - val &= ~(0x1 << 15); /* StutterScrubEn = DRAM scrub enabled */ - val |= (mctGet_NVbits(NV_DramBKScrub)?1:0) << 15; - pci_write_config32(pDCTstat->dev_nbmisc, 0xd4, val); - } - } /* this node has ECC enabled dram */ - } /*Node has Dram */ - } /*if Node present */ - } - - /* Restore previous MCA error handling settings */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (NodePresent_D(Node)) { - dev = pDCTstat->dev_map; - reg = 0x40 + (Node << 3); /* Dram Base Node 0 + index */ - val = Get_NB32(dev, reg); - - /* WE/RE is checked */ - if ((val & 0x3) == 0x3) { /* Node has dram populated */ - uint32_t mc4_status_high = pci_read_config32(pDCTstat->dev_nbmisc, 0x4c); - uint32_t mc4_status_low = pci_read_config32(pDCTstat->dev_nbmisc, 0x48); - if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) { - printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected!\n" - "Signature: %08x%08x\n", mc4_status_high, mc4_status_low); - } - - /* Clear MC4 error status */ - pci_write_config32(pDCTstat->dev_nbmisc, 0x48, 0x0); - pci_write_config32(pDCTstat->dev_nbmisc, 0x4c, 0x0); - - /* Restore previous MCA error handling settings */ - dword = Get_NB32(pDCTstat->dev_nbmisc, 0x44); - dword |= (sync_flood_on_dram_err[Node] & 0x1) << 30; - dword |= (sync_flood_on_any_uc_err[Node] & 0x1) << 21; - Set_NB32(pDCTstat->dev_nbmisc, 0x44, dword); - } - } - } - - if (mctGet_NVbits(NV_SyncOnUnEccEn)) - setSyncOnUnEccEn_D(pMCTstat, pDCTstatA); - - mctHookAfterECC(); - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (NodePresent_D(Node)) { - printk(BIOS_DEBUG, "ECCInit: Node %02x\n", Node); - printk(BIOS_DEBUG, "ECCInit: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "ECCInit: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "ECCInit: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "ECCInit: Done\n"); - } - } - return MemClrECC; -} - -static void setSyncOnUnEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u32 Node; - u32 reg; - u32 dev; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (NodePresent_D(Node)) { /* If Node is present*/ - reg = 0x40+(Node << 3); /* Dram Base Node 0 + index*/ - val = Get_NB32(pDCTstat->dev_map, reg); - /*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*/ - dev = pDCTstat->dev_nbmisc; - reg = 0x44; /* MCA NB Configuration*/ - val = Get_NB32(dev, reg); - val |= (1 << SyncOnUcEccEn); - Set_NB32(dev, reg, val); - } - } /* Node has Dram*/ - } /* if Node present*/ - } -} - -static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u8 i; - u32 dev = pDCTstat->dev_dct; - u8 ch_end; - u8 isDimmECCEn = 0; - - if (pDCTstat->GangedMode) { - ch_end = 1; - } else { - ch_end = 2; - } - for (i = 0; i < ch_end; i++) { - if (pDCTstat->DIMMValidDCT[i] > 0) { - reg = 0x90; /* Dram Config Low */ - val = Get_NB32_DCT(dev, i, reg); - if (val & (1 << DimmEcEn)) { - /* set local flag 'dram ecc capable' */ - isDimmECCEn = 1; - break; - } - } - } - return isDimmECCEn; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c deleted file mode 100644 index c821ec0628..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <stdint.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 reg; - u32 dev = pDCTstat->dev_dct; - - /*flag for selecting HW/SW DRAM Init HW DRAM Init */ - reg = 0x90; /*DRAM Configuration Low */ - val = Get_NB32_DCT(dev, dct, reg); - val |= (1<<InitDram); - 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 deleted file mode 100644 index 1ee10608b9..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> -#include <string.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -static 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 SetEccWrDQS_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - u8 ByteLane, DimmNum, OddByte, Addl_Index, Channel; - u8 EccRef1, EccRef2, EccDQSScale; - u32 val; - u16 word; - - for (Channel = 0; Channel < 2; Channel ++) { - for (DimmNum = 0; DimmNum < C_MAX_DIMMS; DimmNum ++) { /* we use DimmNum instead of DimmNumx3 */ - for (ByteLane = 0; ByteLane < 9; ByteLane ++) { - /* Get RxEn initial value from WrDqs */ - if (ByteLane & 1) - OddByte = 1; - else - OddByte = 0; - if (ByteLane < 2) - Addl_Index = 0x30; - else if (ByteLane < 4) - Addl_Index = 0x31; - else if (ByteLane < 6) - Addl_Index = 0x40; - else if (ByteLane < 8) - Addl_Index = 0x41; - else - Addl_Index = 0x32; - Addl_Index += DimmNum * 3; - - val = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, Channel, 0x98, Addl_Index); - if (OddByte) - val >>= 16; - /* Save WrDqs to stack for later usage */ - pDCTstat->persistentData.CH_D_B_TxDqs[Channel][DimmNum][ByteLane] = val & 0xFF; - EccDQSScale = pDCTstat->CH_EccDQSScale[Channel]; - word = pDCTstat->CH_EccDQSLike[Channel]; - if ((word & 0xFF) == ByteLane) EccRef1 = val & 0xFF; - if (((word >> 8) & 0xFF) == ByteLane) EccRef2 = val & 0xFF; - } - } - } -} - -static void EnableAutoRefresh_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - u32 val; - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C); - val &= ~(1 << DisAutoRefresh); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C); - val &= ~(1 << DisAutoRefresh); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C, val); -} - -static void DisableAutoRefresh_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C); - val |= 1 << DisAutoRefresh; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C); - val |= 1 << DisAutoRefresh; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C, val); -} - - -static uint8_t PhyWLPass1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 dimm; - u16 DIMMValid; - uint8_t status = 0; - void *DCTPtr; - - dct &= 1; - - DCTPtr = (void *)(pDCTstat->C_DCTPtr[dct]); - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct]; - - if (pDCTstat->GangedMode & 1) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - - if (pDCTstat->DIMMValid) { - DIMMValid = pDCTstat->DIMMValid; - PrepareC_DCT(pMCTstat, pDCTstat, dct); - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) { - if (DIMMValid & (1 << (dimm << 1))) { - status |= AgesaHwWlPhase1(pMCTstat, pDCTstat, dct, dimm, FirstPass); - status |= AgesaHwWlPhase2(pMCTstat, pDCTstat, dct, dimm, FirstPass); - status |= AgesaHwWlPhase3(pMCTstat, pDCTstat, dct, dimm, FirstPass); - } - } - } - - return status; -} - -static uint8_t PhyWLPass2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t final) -{ - u8 dimm; - u16 DIMMValid; - uint8_t status = 0; - void *DCTPtr; - - dct &= 1; - - DCTPtr = (void *)&(pDCTstat->C_DCTPtr[dct]); /* todo: */ - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct]; - - if (pDCTstat->GangedMode & 1) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - - if (pDCTstat->DIMMValid) { - DIMMValid = pDCTstat->DIMMValid; - PrepareC_DCT(pMCTstat, pDCTstat, dct); - pDCTstat->Speed = pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq; - pDCTstat->CASL = pDCTstat->DIMMCASL = pDCTstat->TargetCASL; - SPD2ndTiming(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))) { - status |= AgesaHwWlPhase1(pMCTstat, pDCTstat, dct, dimm, SecondPass); - status |= AgesaHwWlPhase2(pMCTstat, pDCTstat, dct, dimm, SecondPass); - status |= AgesaHwWlPhase3(pMCTstat, pDCTstat, dct, dimm, SecondPass); - } - } - } - - return status; -} - -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 *pDCTstatA, uint8_t Node, uint8_t Pass) -{ - uint8_t status; - uint8_t timeout; - uint16_t final_target_freq; - - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - 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]); - - /* Disable auto refresh by configuring F2x[1, 0]8C[DisAutoRefresh] = 1 */ - DisableAutoRefresh_D(pMCTstat, pDCTstat); - - /* Disable ZQ calibration short command by F2x[1,0]94[ZqcsInterval]=00b */ - DisableZQcalibration(pMCTstat, pDCTstat); - PrepareC_MCT(pMCTstat, pDCTstat); - - if (pDCTstat->GangedMode & (1 << 0)) { - pDCTstat->DIMMValidDCT[1] = pDCTstat->DIMMValidDCT[0]; - } - - if (Pass == FirstPass) { - timeout = 0; - do { - status = 0; - timeout++; - status |= PhyWLPass1(pMCTstat, pDCTstat, 0); - status |= PhyWLPass1(pMCTstat, pDCTstat, 1); - if (status) - printk(BIOS_INFO, - "%s: Retrying write levelling due to invalid value(s) detected in first phase\n", - __func__); - } while (status && (timeout < 8)); - if (status) - printk(BIOS_INFO, - "%s: Uncorrectable invalid value(s) detected in first phase of write levelling\n", - __func__); - } - - 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. - */ - uint8_t global_phy_training_status = 0; - 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, pDCTstatA, Node); - timeout = 0; - do { - status = 0; - timeout++; - status |= PhyWLPass2(pMCTstat, pDCTstat, 0, (pDCTstat->TargetFreq == final_target_freq)); - status |= PhyWLPass2(pMCTstat, pDCTstat, 1, (pDCTstat->TargetFreq == final_target_freq)); - if (status) - printk(BIOS_INFO, - "%s: Retrying write levelling due to invalid value(s) detected in last phase\n", - __func__); - } while (status && (timeout < 8)); - global_phy_training_status |= status; - } - - pDCTstat->TargetFreq = final_target_freq; - - if (global_phy_training_status) - printk(BIOS_WARNING, - "%s: Uncorrectable invalid value(s) detected in second phase of write levelling; " - "continuing but system may be unstable!\n", - __func__); - - 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); - EnableAutoRefresh_D(pMCTstat, pDCTstat); - EnableZQcalibration(pMCTstat, pDCTstat); -} - -void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Pass) -{ - u8 Node; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - mctSMBhub_Init(Node); - Clear_OnDimmMirror(pMCTstat, pDCTstat); - WriteLevelization_HW(pMCTstat, pDCTstatA, Node, Pass); - Restore_OnDimmMirror(pMCTstat, pDCTstat); - } - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c deleted file mode 100644 index 73370e715b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <stdint.h> -#include <console/console.h> -#include <cpu/amd/mtrr.h> -#include <cpu/x86/mtrr.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr); -static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType); - -void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* BSP only. Set the fixed MTRRs for common legacy ranges. - * Set TOP_MEM and TOM2. - * Set some variable MTRRs with WB Uncacheable type. - */ - - u32 Bottom32bIO, Bottom40bIO, Cache32bTOP; - u32 val; - u32 addr; - u32 lo, hi; - - /* Set temporary top of memory from Node structure data. - * Adjust temp top of memory down to accommodate 32-bit IO space. - * Bottom40bIO = top of memory, right justified 8 bits - * (defines dram versus IO space type) - * Bottom32bIO = sub 4GB top of memory, right justified 8 bits - * (defines dram versus IO space type) - * Cache32bTOP = sub 4GB top of WB cacheable memory, - * right justified 8 bits - */ - - val = mctGet_NVbits(NV_BottomIO); - if (val == 0) - val++; - - Bottom32bIO = val << (24-8); - - val = pMCTstat->SysLimit + 1; - if (val <= _4GB_RJ8) { - Bottom40bIO = 0; - if (Bottom32bIO >= val) - Bottom32bIO = val; - } else { - Bottom40bIO = val; - } - - Cache32bTOP = Bottom32bIO; - - /*====================================================================== - Set default values for CPU registers - ======================================================================*/ - - /* NOTE : For coreboot, we don't need to set mtrr enables here because - they are still enable from cache_as_ram.inc */ - - addr = MTRR_FIX_64K_00000; - lo = 0x1E1E1E1E; - hi = lo; - _WRMSR(addr, lo, hi); /* 0 - 512K = WB Mem */ - addr = MTRR_FIX_16K_80000; - _WRMSR(addr, lo, hi); /* 512K - 640K = WB Mem */ - - /*====================================================================== - Set variable MTRR values - ======================================================================*/ - /* NOTE: for coreboot change from 0x200 to 0x204: coreboot is using - 0x200, 0x201 for [1M, CONFIG_TOP_MEM) - 0x202, 0x203 for ROM Caching - */ - addr = MTRR_PHYS_BASE(2); /* MTRR phys base 2*/ - /* use TOP_MEM as limit*/ - /* Limit = TOP_MEM|TOM2*/ - /* Base = 0*/ - printk(BIOS_DEBUG, "\t CPUMemTyping: Cache32bTOP:%x\n", Cache32bTOP); - SetMTRRrangeWB_D(0, &Cache32bTOP, &addr); - /* Base */ - /* Limit */ - /* MtrrAddr */ - if (addr == -1) /* ran out of MTRRs?*/ - pMCTstat->GStatus |= 1<<GSB_MTRRshort; - - pMCTstat->Sub4GCacheTop = Cache32bTOP<<8; - - /*====================================================================== - Set TOP_MEM and TOM2 CPU registers - ======================================================================*/ - addr = TOP_MEM; - lo = Bottom32bIO<<8; - hi = Bottom32bIO>>24; - _WRMSR(addr, lo, hi); - printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom32bIO:%x\n", Bottom32bIO); - printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom40bIO:%x\n", Bottom40bIO); - if (Bottom40bIO) { - hi = Bottom40bIO >> 24; - lo = Bottom40bIO << 8; - addr += 3; /* TOM2 */ - _WRMSR(addr, lo, hi); - } - addr = SYSCFG_MSR; /* SYS_CFG */ - _RDMSR(addr, &lo, &hi); - if (Bottom40bIO) { - lo |= SYSCFG_MSR_TOM2En; /* MtrrTom2En = 1 */ - lo |= SYSCFG_MSR_TOM2WB; /* Tom2ForceMemTypeWB */ - } else { - lo &= ~SYSCFG_MSR_TOM2En; /* MtrrTom2En = 0 */ - lo &= ~SYSCFG_MSR_TOM2WB; /* Tom2ForceMemTypeWB */ - } - _WRMSR(addr, lo, hi); -} - -static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr) -{ - /*set WB type*/ - SetMTRRrange_D(Base, pLimit, pMtrrAddr, 6); -} - -static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType) -{ - /* Program MTRRs to describe given range as given cache type. - * Use MTRR pairs starting with the given MTRRphys Base address, - * and use as many as is required up to (excluding) MSR 020C, which - * is reserved for OS. - * - * "Limit" in the context of this procedure is not the numerically - * correct limit, but rather the Last address+1, for purposes of coding - * efficiency and readability. Size of a region is then Limit-Base. - * - * 1. Size of each range must be a power of two - * 2. Each range must be naturally aligned (Base is same as size) - * - * There are two code paths: the ascending path and descending path - * (analogous to bsf and bsr), where the next limit is a function of the - * next set bit in a forward or backward sequence of bits (as a function - * of the Limit). We start with the ascending path, to ensure that - * regions are naturally aligned, then we switch to the descending path - * to maximize MTRR usage efficiency. Base = 0 is a special case where we - * start with the descending path. Correct Mask for region is - * 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1 - */ - - u32 curBase, curLimit, curSize; - u32 val, valx; - u32 addr; - - val = curBase = Base; - curLimit = *pLimit; - addr = *pMtrrAddr; - while ((addr >= 0x200) && (addr < 0x20C) && (val < *pLimit)) { - /* start with "ascending" code path */ - /* alignment (largest block size)*/ - valx = 1 << bsf(curBase); - curSize = valx; - - /* largest legal limit, given current non-zero range Base*/ - valx += curBase; - if ((curBase == 0) || (*pLimit < valx)) { - /* flop direction to "descending" code path*/ - valx = 1<<bsr(*pLimit - curBase); - curSize = valx; - valx += curBase; - } - curLimit = valx; /*eax = curBase, edx = curLimit*/ - valx = val>>24; - val <<= 8; - - /* now program the MTRR */ - val |= MtrrType; /* set cache type (UC or WB)*/ - _WRMSR(addr, val, valx); /* prog. MTRR with current region Base*/ - val = ((~(curSize - 1))+1) - 1; /* Size-1*/ /*Mask = 2comp(Size-1)-1*/ - valx = (val >> 24) | (0xff00); /* GH have 48 bits addr */ - val <<= 8; - val |= (1 << 11); /* set MTRR valid*/ - addr++; - _WRMSR(addr, val, valx); /* prog. MTRR with current region Mask*/ - val = curLimit; - curBase = val; /* next Base = current Limit (loop exit)*/ - addr++; /* next MTRR pair addr */ - } - if (val < *pLimit) { - *pLimit = val; - addr = -1; - } - *pMtrrAddr = addr; -} - -void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) -{ - /* UMA memory size may need splitting the MTRR configuration into two - * Before training use NB_BottomIO or the physical memory size to set the MTRRs. - * After training, add UMAMemTyping function to reconfigure the MTRRs based on - * NV_BottomUMA (for UMA systems only). - * This two-step process allows all memory to be cached for training - */ - - u32 Bottom32bIO, Cache32bTOP; - u32 val; - u32 addr; - u32 lo, hi; - - /*====================================================================== - * Adjust temp top of memory down to accommodate UMA memory start - *======================================================================*/ - /* Bottom32bIO = sub 4GB top of memory, right justified 8 bits - * (defines dram versus IO space type) - * Cache32bTOP = sub 4GB top of WB cacheable memory, right justified 8 bits */ - - Bottom32bIO = pMCTstat->Sub4GCacheTop >> 8; - - val = mctGet_NVbits(NV_BottomUMA); - if (val == 0) - val++; - - val <<= (24-8); - if (val < Bottom32bIO) { - Cache32bTOP = val; - pMCTstat->Sub4GCacheTop = val; - - /*====================================================================== - * Clear variable MTRR values - *======================================================================*/ - addr = MTRR_PHYS_BASE(0); - lo = 0; - hi = lo; - while (addr < MTRR_PHYS_BASE(6)) { - _WRMSR(addr, lo, hi); /* prog. MTRR with current region Mask */ - addr++; /* next MTRR pair addr */ - } - - /*====================================================================== - * Set variable MTRR values - *======================================================================*/ - printk(BIOS_DEBUG, "\t UMAMemTyping_D: Cache32bTOP:%x\n", Cache32bTOP); - SetMTRRrangeWB_D(0, &Cache32bTOP, &addr); - if (addr == -1) /* ran out of MTRRs?*/ - pMCTstat->GStatus |= 1<<GSB_MTRRshort; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c deleted file mode 100644 index 29949e02d4..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <stdint.h> -#include <console/console.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -void InterleaveNodes_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Applies Node memory interleaving if enabled and if all criteria are met. */ - u8 Node; - u32 Base; - u32 MemSize, MemSize0 = 0; - u32 Dct0MemSize = 0, DctSelBase, DctSelBaseOffset = 0; - u8 Nodes; - u8 NodesWmem; - u8 DoIntlv; - u8 _NdIntCap; - u8 _SWHole; - u32 HWHoleSz; - u32 DramHoleAddrReg; - u32 HoleBase; - u32 dev0; - u32 reg0; - u32 val; - u8 i; - struct DCTStatStruc *pDCTstat; - - DoIntlv = mctGet_NVbits(NV_NodeIntlv); - - _NdIntCap = 0; - HWHoleSz = 0; /*For HW remapping, NOT Node hoisting. */ - - pDCTstat = pDCTstatA + 0; - dev0 = pDCTstat->dev_host; - Nodes = ((Get_NB32(dev0, 0x60) >> 4) & 0x7) + 1; - - dev0 = pDCTstat->dev_map; - reg0 = 0x40; - - NodesWmem = 0; - Node = 0; - - while (DoIntlv && (Node < Nodes)) { - pDCTstat = pDCTstatA + Node; - if (pMCTstat->GStatus & (1 << GSB_SpIntRemapHole)) { - pMCTstat->GStatus |= 1 << GSB_HWHole; - _SWHole = 0; - } else if (pDCTstat->Status & (1 << SB_SWNodeHole)) { - _SWHole = 1; - } else { - _SWHole = 0; - } - - if (!_SWHole) { - Base = Get_NB32(dev0, reg0); - if (Base & 1) { - NodesWmem++; - Base &= 0xFFFF0000; /* Base[39:8] */ - - if (pDCTstat->Status & (1 << SB_HWHole)) { - - /* to get true amount of dram, - * subtract out memory hole if HW dram remapping */ - DramHoleAddrReg = Get_NB32(pDCTstat->dev_map, 0xF0); - HWHoleSz = DramHoleAddrReg >> 16; - HWHoleSz = (((~HWHoleSz) + 1) & 0xFF); - HWHoleSz <<= 24-8; - } - /* check to see if the amount of memory on each channel - * are the same on all nodes */ - - DctSelBase = Get_NB32(pDCTstat->dev_dct, 0x114); - if (DctSelBase) { - DctSelBase <<= 8; - if (pDCTstat->Status & (1 << SB_HWHole)) { - if (DctSelBase >= 0x1000000) { - DctSelBase -= HWHoleSz; - } - } - DctSelBaseOffset -= Base; - if (Node == 0) { - Dct0MemSize = DctSelBase; - } else if (DctSelBase != Dct0MemSize) { - break; - } - } - - MemSize = Get_NB32(dev0, reg0 + 4); - MemSize &= 0xFFFF0000; - MemSize += 0x00010000; - MemSize -= Base; - if (pDCTstat->Status & (1 << SB_HWHole)) { - MemSize -= HWHoleSz; - } - if (Node == 0) { - MemSize0 = MemSize; - } else if (MemSize0 != MemSize) { - break; - } - } else { - break; - } - } else { - break; - } - Node++; - reg0 += 8; - } - - if (Node == Nodes) { - /* if all nodes have memory and no Node had SW memhole */ - if (Nodes == 2 || Nodes == 4 || Nodes == 8) - _NdIntCap = 1; - } - - if (!_NdIntCap) - DoIntlv = 0; - - if (pMCTstat->GStatus & 1 << (GSB_SpIntRemapHole)) { - HWHoleSz = pMCTstat->HoleBase; - if (HWHoleSz == 0) { - HWHoleSz = mctGet_NVbits(NV_BottomIO) & 0xFF; - HWHoleSz <<= 24-8; - } - HWHoleSz = ((~HWHoleSz) + 1) & 0x00FF0000; - } - - if (DoIntlv) { - MCTMemClr_D(pMCTstat, pDCTstatA); - /* Program Interleaving enabled on Node 0 map only.*/ - MemSize0 <<= bsf(Nodes); /* MemSize = MemSize*2 (or 4, or 8) */ - Dct0MemSize <<= bsf(Nodes); - MemSize0 += HWHoleSz; - Base = ((Nodes - 1) << 8) | 3; - reg0 = 0x40; - Node = 0; - while (Node < Nodes) { - Set_NB32(dev0, reg0, Base); - MemSize = MemSize0; - MemSize--; - MemSize &= 0xFFFF0000; - MemSize |= Node << 8; /* set IntlvSel[2:0] field */ - MemSize |= Node; /* set DstNode[2:0] field */ - Set_NB32(dev0, reg0 + 4, MemSize0); - reg0 += 8; - Node++; - } - - /* set base/limit to F1x120/124 per Node */ - Node = 0; - while (Node < Nodes) { - pDCTstat = pDCTstatA + Node; - pDCTstat->NodeSysBase = 0; - MemSize = MemSize0; - MemSize -= HWHoleSz; - MemSize--; - pDCTstat->NodeSysLimit = MemSize; - Set_NB32(pDCTstat->dev_map, 0x120, Node << 21); - MemSize = MemSize0; - MemSize--; - MemSize >>= 19; - val = Base; - val &= 0x700; - val <<= 13; - val |= MemSize; - Set_NB32(pDCTstat->dev_map, 0x124, val); - - if (pMCTstat->GStatus & (1 << GSB_HWHole)) { - HoleBase = pMCTstat->HoleBase; - if (Dct0MemSize >= HoleBase) { - val = HWHoleSz; - if (Node == 0) { - val += Dct0MemSize; - } - } else { - val = HWHoleSz + Dct0MemSize; - } - - val >>= 8; /* DramHoleOffset */ - HoleBase <<= 8; /* DramHoleBase */ - val |= HoleBase; - val |= 1 << DramMemHoistValid; - val |= 1 << DramHoleValid; - Set_NB32(pDCTstat->dev_map, 0xF0, val); - } - - Set_NB32(pDCTstat->dev_dct, 0x114, Dct0MemSize >> 8); /* DctSelBaseOffset */ - val = Get_NB32(pDCTstat->dev_dct, 0x110); - val &= 0x7FF; - val |= Dct0MemSize >> 8; - Set_NB32(pDCTstat->dev_dct, 0x110, val); /* DctSelBaseAddr */ - printk(BIOS_DEBUG, "InterleaveNodes: DRAM Controller Select Low Register = %x\n", val); - Node++; - } - - /* Copy Node 0 into other Nodes' CSRs */ - Node = 1; - while (Node < Nodes) { - pDCTstat = pDCTstatA + Node; - - for (i = 0x40; i <= 0x80; i++) { - val = Get_NB32(dev0, i); - Set_NB32(pDCTstat->dev_map, i, val); - } - - val = Get_NB32(dev0, 0xF0); - Set_NB32(pDCTstat->dev_map, 0xF0, val); - Node++; - } - pMCTstat->GStatus = (1 << GSB_NodeIntlv); - } - printk(BIOS_DEBUG, "InterleaveNodes_D: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "InterleaveNodes_D: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "InterleaveNodes_D: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "InterleaveNodes_D: Done\n\n"); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctprob.c b/src/northbridge/amd/amdmct/mct_ddr3/mctprob.c deleted file mode 100644 index 3cb75675df..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctprob.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat) -{ - u32 val; - - if (pDCTstat->LogicalCPUID & AMD_DR_Bx) { - Set_NB32(pDCTstat->dev_dct, 0x98, 0x0D004007); - val = Get_NB32(pDCTstat->dev_dct, 0x9C); - val |= 0x3FF; - Set_NB32(pDCTstat->dev_dct, 0x9C, val); - Set_NB32(pDCTstat->dev_dct, 0x98, 0x4D0F4F07); - - Set_NB32(pDCTstat->dev_dct, 0x198, 0x0D004007); - val = Get_NB32(pDCTstat->dev_dct, 0x19C); - val |= 0x3FF; - Set_NB32(pDCTstat->dev_dct, 0x19C, val); - Set_NB32(pDCTstat->dev_dct, 0x198, 0x4D0F4F07); - } -} - -void mct_ExtMCTConfig_Bx(struct DCTStatStruc *pDCTstat) -{ - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx)) { - Set_NB32(pDCTstat->dev_dct, 0x11C, 0x0FE40FC0 | 1 << 29/* FlushWrOnStpGnt */); - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c deleted file mode 100644 index ddaaaab8d5..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -/* mct_SetDramConfigMisc2_Cx & mct_SetDramConfigMisc2_Dx */ -u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, - uint8_t dct, uint32_t misc2, uint32_t DramControl) -{ - u32 val; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) { - uint8_t cs_mux_45; - uint8_t cs_mux_67; - uint32_t f2x80; - - misc2 &= ~(0x1 << 28); /* FastSelfRefEntryDis = 0x0 */ - if (MaxDimmsInstallable == 3) { - /* FIXME 3 DIMMS per channel unimplemented */ - cs_mux_45 = 0; - } else { - uint32_t f2x60 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x60); - f2x80 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x80); - if ((((f2x80 & 0xf) == 0x7) || ((f2x80 & 0xf) == 0x9)) - && ((f2x60 & 0x3) == 0x3)) - cs_mux_45 = 1; - else if ((((f2x80 & 0xf) == 0xa) || ((f2x80 & 0xf) == 0xb)) - && ((f2x60 & 0x3) > 0x1)) - cs_mux_45 = 1; - else - cs_mux_45 = 0; - } - - if (MaxDimmsInstallable == 1) { - cs_mux_67 = 0; - } else if (MaxDimmsInstallable == 2) { - uint32_t f2x64 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x64); - f2x80 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x80); - if (((((f2x80 >> 4) & 0xf) == 0x7) || (((f2x80 >> 4) & 0xf) == 0x9)) - && ((f2x64 & 0x3) == 0x3)) - cs_mux_67 = 1; - else if (((((f2x80 >> 4) & 0xf) == 0xa) || (((f2x80 >> 4) & 0xf) == 0xb)) - && ((f2x64 & 0x3) > 0x1)) - cs_mux_67 = 1; - else - cs_mux_67 = 0; - } else { - /* FIXME 3 DIMMS per channel unimplemented */ - cs_mux_67 = 0; - } - - misc2 &= ~(0x1 << 27); /* CsMux67 = cs_mux_67 */ - misc2 |= ((cs_mux_67 & 0x1) << 27); - misc2 &= ~(0x1 << 26); /* CsMux45 = cs_mux_45 */ - misc2 |= ((cs_mux_45 & 0x1) << 26); - } else if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx)) { - if (pDCTstat->Status & (1 << SB_Registered)) { - misc2 |= 1 << SubMemclkRegDly; - if (mctGet_NVbits(NV_MAX_DIMMS) == 8) - misc2 |= 1 << Ddr3FourSocketCh; - else - misc2 &= ~(1 << Ddr3FourSocketCh); - } - - if (pDCTstat->LogicalCPUID & AMD_DR_Cx) - misc2 |= 1 << OdtSwizzle; - - val = DramControl; - val &= 7; - val = ((~val) & 0xff) + 1; - val += 6; - val &= 0x7; - misc2 &= 0xfff8ffff; - misc2 |= val << 16; /* DataTxFifoWrDly */ - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) - misc2 |= 1 << 7; /* ProgOdtEn */ - } - return misc2; -} - -void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat) -{ - u32 val; - - if (pDCTstat->LogicalCPUID & (AMD_DR_Cx)) { - /* Revision C */ - Set_NB32(pDCTstat->dev_dct, 0x11c, 0x0ce00fc0 | 1 << 29/* FlushWrOnStpGnt */); - - val = Get_NB32(pDCTstat->dev_dct, 0x1b0); - val &= ~0x73f; - val |= 0x101; /* BKDG recommended settings */ - - Set_NB32(pDCTstat->dev_dct, 0x1b0, val); - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c b/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c deleted file mode 100644 index b203942058..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat) -{ - uint32_t dword; - - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - dword = 0x0ce00f00 | 0x1 << 29; /* FlushWrOnStpGnt */ - if (!(pDCTstat->GangedMode)) - dword |= 0x18 << 2; /* MctWrLimit = 0x18 for unganged mode */ - else - dword |= 0x10 << 2; /* MctWrLimit = 0x10 for ganged mode */ - Set_NB32(pDCTstat->dev_dct, 0x11c, dword); - - dword = Get_NB32(pDCTstat->dev_dct, 0x1b0); - dword &= ~0x3; /* AdapPrefMissRatio = 0x1 */ - dword |= 0x1; - dword &= ~(0x3 << 2); /* AdapPrefPositiveStep = 0x0 */ - dword &= ~(0x3 << 4); /* AdapPrefNegativeStep = 0x0 */ - dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x1 */ - dword |= (0x1 << 8); - dword |= (0x7 << 22); /* PrefFourConf = 0x7 */ - dword |= (0x7 << 25); /* PrefFiveConf = 0x7 */ - - if (!(pDCTstat->GangedMode)) - dword |= (0x1 << 12); /* EnSplitDctLimits = 0x1 */ - else - dword &= ~(0x1 << 12); /* EnSplitDctLimits = 0x0 */ - - dword &= ~(0xf << 28); /* DcqBwThrotWm = ... */ - switch (pDCTstat->Speed) { - case 4: - dword |= (0x5 << 28); /* ...5 for DDR800 */ - break; - case 5: - dword |= (0x6 << 28); /* ...6 for DDR1066 */ - break; - case 6: - dword |= (0x8 << 28); /* ...8 for DDR800 */ - break; - default: - dword |= (0x9 << 28); /* ...9 for DDR1600 */ - break; - } - Set_NB32(pDCTstat->dev_dct, 0x1b0, dword); - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c deleted file mode 100644 index 93cfb4bf1b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2015 - 2016 Raptor Engineering, LLC - * - * 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. - */ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -static 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 uint8_t fam15h_rdimm_rc2_ibt_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint8_t control_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]; - - /* FIXME - * Assume there is only one register on the RDIMM for now - */ - uint8_t num_registers = 1; - - if (package_type == PT_GR) { - /* Socket G34 */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.7.1.2.1 Table 85 */ - if (MaxDimmsInstallable == 1) { - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - control_code = 0x1; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (num_registers == 1) { - control_code = 0x0; - } else { - control_code = 0x1; - } - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - control_code = 0x0; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - control_code = 0x1; - } else if ((MemClkFreq >= 0xa) && (MemClkFreq <= 0x12)) { - /* DDR3-1066 - DDR3-1600 */ - if (num_registers == 1) { - control_code = 0x0; - } else { - control_code = 0x1; - } - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if (num_registers == 1) { - control_code = 0x1; - } else { - control_code = 0x8; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.7.1.2.1 Table 86 */ - if (MaxDimmsInstallable == 1) { - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - control_code = 0x1; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (num_registers == 1) { - control_code = 0x0; - } else { - control_code = 0x1; - } - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - control_code = 0x0; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - control_code = 0x1; - } else if ((MemClkFreq >= 0xa) && (MemClkFreq <= 0x12)) { - /* DDR3-1066 - DDR3-1600 */ - if (num_registers == 1) { - control_code = 0x0; - } else { - control_code = 0x1; - } - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if (num_registers == 1) { - control_code = 0x1; - } else { - control_code = 0x8; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - printk(BIOS_SPEW, "%s: DCT %d IBT code: %01x\n", __func__, dct, control_code); - return control_code; -} - -static uint16_t memclk_to_freq(uint16_t memclk) { - uint16_t fam10h_freq_tab[] = {0, 0, 0, 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}; - - uint16_t mem_freq = 0; - - if (is_fam15h()) { - if (memclk < 0x17) { - mem_freq = fam15h_freq_tab[memclk]; - } - } else { - if ((memclk > 0x0) && (memclk < 0x8)) { - mem_freq = fam10h_freq_tab[memclk - 1]; - } - } - - return mem_freq; -} - -static uint8_t rc_word_chip_select_lower_bit(void) { - if (is_fam15h()) { - return 21; - } else { - return 20; - } -} - -static uint32_t rc_word_address_to_ctl_bits(uint32_t address) { - if (is_fam15h()) { - return (((address >> 3) & 0x1) << 2) << 18 | (address & 0x7); - } else { - return (((address >> 3) & 0x1) << 2) << 16 | (address & 0x7); - } -} - -static uint32_t rc_word_value_to_ctl_bits(uint32_t value) { - if (is_fam15h()) { - return ((value >> 2) & 0x3) << 18 | ((value & 0x3) << 3); - } else { - return ((value >> 2) & 0x3) << 16 | ((value & 0x3) << 3); - } -} - -static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MrsChipSel, u32 CtrlWordNum) -{ - u8 Dimms, DimmNum; - u32 val; - uint8_t ddr_voltage_index; - uint16_t mem_freq; - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - DimmNum = (MrsChipSel >> rc_word_chip_select_lower_bit()) & 0x7; - - if (dct == 1) - DimmNum++; - - mem_freq = memclk_to_freq(pDCTstat->DIMMAutoSpeed); - Dimms = pDCTstat->MAdimms[dct]; - - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - - val = 0; - if (CtrlWordNum == 0) - val = 0x2; - else if (CtrlWordNum == 1) { - if (!((pDCTstat->DimmDRPresent | pDCTstat->DimmQRPresent) & (1 << DimmNum))) - val = 0xc; /* if single rank, set DBA1 and DBA0 */ - } else if (CtrlWordNum == 2) { - if (is_fam15h()) { - val = (fam15h_rdimm_rc2_ibt_code(pDCTstat, dct) & 0x1) << 2; - } else { - if (package_type == PT_GR) { - /* Socket G34 */ - if (MaxDimmsInstallable == 2) { - if (Dimms > 1) - val = 0x4; - } - } - else if (package_type == PT_C3) { - /* Socket C32 */ - if (MaxDimmsInstallable == 2) { - if (Dimms > 1) - val = 0x4; - } - } - } - } else if (CtrlWordNum == 3) { - val = (pDCTstat->CtrlWrd3 >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 4) { - val = (pDCTstat->CtrlWrd4 >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 5) { - val = (pDCTstat->CtrlWrd5 >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 6) { - val = ((pDCTstat->spd_data.spd_bytes[DimmNum][72] & 0xf) >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 7) { - val = (((pDCTstat->spd_data.spd_bytes[DimmNum][72] >> 4) & 0xf) >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 8) { - if (is_fam15h()) { - val = (fam15h_rdimm_rc2_ibt_code(pDCTstat, dct) & 0xe) >> 1; - } else { - if (package_type == PT_GR) { - /* Socket G34 */ - if (MaxDimmsInstallable == 2) { - val = 0x0; - } - } - else if (package_type == PT_C3) { - /* Socket C32 */ - if (MaxDimmsInstallable == 2) { - val = 0x0; - } - } - } - } else if (CtrlWordNum == 9) { - val = 0xd; /* DBA1, DBA0, DA3 = 0 */ - } else if (CtrlWordNum == 10) { - val = 0x0; /* Lowest operating frequency */ - } else if (CtrlWordNum == 11) { - if (ddr_voltage_index & 0x4) - val = 0x2; /* 1.25V */ - else if (ddr_voltage_index & 0x2) - val = 0x1; /* 1.35V */ - else - val = 0x0; /* 1.5V */ - } else if (CtrlWordNum == 12) { - val = ((pDCTstat->spd_data.spd_bytes[DimmNum][75] & 0xf) >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 13) { - val = (((pDCTstat->spd_data.spd_bytes[DimmNum][75] >> 4) & 0xf) >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 14) { - val = ((pDCTstat->spd_data.spd_bytes[DimmNum][76] & 0xf) >> (DimmNum << 2)) & 0xff; - } else if (CtrlWordNum == 15) { - val = (((pDCTstat->spd_data.spd_bytes[DimmNum][76] >> 4) & 0xf) >> (DimmNum << 2)) & 0xff; - } - val &= 0xf; - - printk(BIOS_SPEW, "%s: Preparing to send DCT %d DIMM %d RC%d: %02x\n", __func__, dct, DimmNum >> 1, CtrlWordNum, val); - - val = MrsChipSel | rc_word_value_to_ctl_bits(val); - val |= rc_word_address_to_ctl_bits(CtrlWordNum); - - return val; -} - -static void mct_SendCtrlWrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t val) -{ - u32 dev = pDCTstat->dev_dct; - - val |= Get_NB32_DCT(dev, dct, 0x7c) & ~0xffffff; - val |= 1 << SendControlWord; - Set_NB32_DCT(dev, dct, 0x7c, val); - - do { - val = Get_NB32_DCT(dev, dct, 0x7c); - } while (val & (1 << SendControlWord)); -} - -void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - u8 MrsChipSel; - u32 dev = pDCTstat->dev_dct; - u32 val, cw; - - printk(BIOS_SPEW, "%s: Start\n", __func__); - - if (!is_fam15h()) { - mct_Wait(1600); - mct_Wait(1200); - } - - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct]; - if (pDCTstat->GangedMode & 1) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - - for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel += 2) { - if (pDCTstat->CSPresent & (1 << MrsChipSel)) { - val = Get_NB32_DCT(dev, dct, 0xa8); - val &= ~(0xff << 8); - - switch (MrsChipSel) { - case 0: - case 1: - val |= 3 << 8; - break; - case 2: - case 3: - val |= (3 << 2) << 8; - break; - case 4: - case 5: - val |= (3 << 4) << 8; - break; - case 6: - case 7: - val |= (3 << 6) << 8; - break; - } - Set_NB32_DCT(dev, dct, 0xa8, val); - printk(BIOS_SPEW, "%s: F2xA8: %08x\n", __func__, val); - - if (is_fam15h()) { - for (cw = 0; cw <=15; cw ++) { - val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), cw); - mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val); - if ((cw == 2) || (cw == 8) || (cw == 10)) - precise_ndelay_fam15(pMCTstat, 6000); - } - } else { - for (cw = 0; cw <=15; cw ++) { - mct_Wait(1600); - val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), cw); - mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val); - } - } - } - } - - mct_Wait(1200); - - printk(BIOS_SPEW, "%s: Done\n", __func__); -} - -void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - u32 SaveSpeed = pDCTstat->DIMMAutoSpeed; - u32 MrsChipSel; - u32 dev = pDCTstat->dev_dct; - u32 val; - uint16_t mem_freq; - - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct]; - if (pDCTstat->GangedMode & 1) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - - pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq; - mem_freq = memclk_to_freq(pDCTstat->TargetFreq); - for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel += 2) { - if (pDCTstat->CSPresent & (1 << MrsChipSel)) { - /* 2. Program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects. */ - val = Get_NB32_DCT(dev, dct, 0xa8); - val &= ~(0xff << 8); - - switch (MrsChipSel) { - case 0: - case 1: - val |= 3 << 8; - break; - case 2: - case 3: - val |= (3 << 2) << 8; - break; - case 4: - case 5: - val |= (3 << 4) << 8; - break; - case 6: - case 7: - val |= (3 << 6) << 8; - break; - } - Set_NB32_DCT(dev, dct, 0xa8, val); - - /* Resend control word 10 */ - uint8_t freq_ctl_val = 0; - mct_Wait(1600); - switch (mem_freq) { - case 333: - case 400: - freq_ctl_val = 0x0; - break; - case 533: - freq_ctl_val = 0x1; - break; - case 667: - freq_ctl_val = 0x2; - break; - case 800: - freq_ctl_val = 0x3; - break; - case 933: - freq_ctl_val = 0x4; - break; - } - - printk(BIOS_SPEW, "Preparing to send DCT %d DIMM %d RC%d: %02x (F2xA8: %08x)\n", dct, MrsChipSel >> 1, 10, freq_ctl_val, val); - - mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, (MrsChipSel << rc_word_chip_select_lower_bit()) | rc_word_address_to_ctl_bits(10) | rc_word_value_to_ctl_bits(freq_ctl_val)); - - if (is_fam15h()) - precise_ndelay_fam15(pMCTstat, 6000); - else - mct_Wait(1600); - - /* Resend control word 2 */ - val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), 2); - mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val); - - if (is_fam15h()) - precise_ndelay_fam15(pMCTstat, 6000); - else - mct_Wait(1600); - - /* Resend control word 8 */ - val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), 8); - mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val); - - if (is_fam15h()) - precise_ndelay_fam15(pMCTstat, 6000); - else - mct_Wait(1600); - } - } - pDCTstat->DIMMAutoSpeed = SaveSpeed; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c deleted file mode 100644 index f215695580..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -static 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; -} - -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; -} - -uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) -{ - uint8_t term = 0; - uint8_t number_of_dimms = pDCTstat->MAdimms[dct]; - uint8_t frequency_index; - uint8_t rank_count = pDCTstat->DimmRanks[(dimm * 2) + dct]; - - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - uint8_t rank_count_dimm2; - - 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; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (is_fam15h()) { - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * LRDIMM unimplemented - */ - } else if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 57 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) || (frequency_index == 0x6) - || (frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - if (rank_count < 3) - term = 0x0; - else - term = 0x2; - } else { - /* DDR3-1600 */ - term = 0x0; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if ((number_of_dimms == 1) && ((rank_count_dimm0 < 4) - && (rank_count_dimm1 < 4))) - term = 0x0; - else - term = 0x2; - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x0; - else - term = 0x2; - } else { - term = 0x1; - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - term = 0x2; - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x0; - else - term = 0x1; - } - } else if (MaxDimmsInstallable == 3) { - rank_count_dimm2 = pDCTstat->DimmRanks[(2 * 2) + dct]; - - if ((frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (rank_count_dimm2 < 4) - term = 0x1; - else - term = 0x2; - } else if (frequency_index == 0x12) { - /* DDR3-1600 */ - term = 0x1; - } else { - term = 0x2; - } - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 60 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) || (frequency_index == 0x6) - || (frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - if (rank_count < 3) - term = 0x0; - else - term = 0x2; - } else { - /* DDR3-1600 */ - term = 0x0; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if ((number_of_dimms == 1) && ((rank_count_dimm0 < 4) - && (rank_count_dimm1 < 4))) - term = 0x0; - else - term = 0x2; - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x0; - else - term = 0x2; - } else { - term = 0x1; - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - term = 0x2; - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x0; - else - term = 0x1; - } - } else if (MaxDimmsInstallable == 3) { - rank_count_dimm2 = pDCTstat->DimmRanks[(2 * 2) + dct]; - - if ((frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (rank_count_dimm2 < 4) - term = 0x1; - else - term = 0x2; - } else if (frequency_index == 0x12) { - /* DDR3-1600 */ - term = 0x1; - } else { - term = 0x2; - } - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } else { - /* UDIMM */ - 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 if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 59 */ - 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 if (package_type == PT_FM2) { - /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 32 */ - 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 { - /* TODO - * Other sockets unimplemented - */ - } - } - } - - printk(BIOS_INFO, "DIMM %d RttWr: %01x\n", dimm, term); - - return term; -} - -uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) -{ - uint8_t term = 0; - uint8_t number_of_dimms = pDCTstat->MAdimms[dct]; - uint8_t frequency_index; - - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - 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; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (is_fam15h()) { - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * LRDIMM unimplemented - */ - } else if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 57 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (rank_count_dimm0 < 4) { - term = 0x2; - } else { - if (!rank) - term = 0x2; - else - term = 0x0; - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - term = 0x1; - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (rank_count_dimm0 < 4) { - term = 0x1; - } else { - if (!rank) - term = 0x3; - else - term = 0x0; - } - } else { - term = 0x3; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x2; - else if (rank) - term = 0x0; - else - term = 0x2; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x1; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x3; - } else { - term = 0x5; - } - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x3; - else - term = 0x4; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 60 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (rank_count_dimm0 < 4) { - term = 0x2; - } else { - if (!rank) - term = 0x2; - else - term = 0x0; - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - term = 0x1; - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (rank_count_dimm0 < 4) { - term = 0x1; - } else { - if (!rank) - term = 0x3; - else - term = 0x0; - } - } else { - term = 0x3; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x2; - else if (rank) - term = 0x0; - else - term = 0x2; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x1; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x3; - } else { - term = 0x5; - } - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x3; - else - term = 0x4; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } else { - /* UDIMM */ - 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 if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 62 */ - 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 if (package_type == PT_FM2) { - /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 32 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) - || (frequency_index == 0x6) - || (frequency_index == 0xa)) - term = 0x4; - else if (frequency_index == 0xe) - term = 0x3; - else if (frequency_index >= 0x12) - term = 0x2; - } - if (MaxDimmsInstallable == 2) { - if (number_of_dimms == 1) { - if (frequency_index <= 0xa) { - term = 0x4; - } else if (frequency_index <= 0xe) { - term = 0x3; - } else { - term = 0x2; - } - } else { - if (frequency_index <= 0xa) { - term = 0x2; - } else if (frequency_index <= 0xe) { - term = 0x1; - } else { - term = 0x0; - } - } - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } - } - - printk(BIOS_INFO, "DIMM %d RttNom: %01x\n", dimm, term); - return term; -} - -static void mct_DCTAccessDone(struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - do { - val = Get_NB32_DCT(dev, dct, 0x98); - } while (!(val & (1 << DctAccessDone))); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static u32 swapAddrBits(struct DCTStatStruc *pDCTstat, u32 MR_register_setting, u8 MrsChipSel, u8 dct) -{ - u16 word; - u32 ret; - - if (!(pDCTstat->Status & (1 << SB_Registered))) { - word = pDCTstat->MirrPresU_NumRegR; - if (dct == 0) { - word &= 0x55; - word <<= 1; - } else - word &= 0xAA; - - if (word & (1 << MrsChipSel)) { - /* A3<->A4,A5<->A6,A7<->A8,BA0<->BA1 */ - ret = 0; - if (MR_register_setting & (1 << 3)) ret |= 1 << 4; - if (MR_register_setting & (1 << 4)) ret |= 1 << 3; - if (MR_register_setting & (1 << 5)) ret |= 1 << 6; - 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 (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; - } - } - return MR_register_setting; -} - -static void mct_SendMrsCmd(struct DCTStatStruc *pDCTstat, u8 dct, u32 EMRS) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - val = Get_NB32_DCT(dev, dct, 0x7c); - val &= ~0x00ffffff; - val |= EMRS; - val |= 1 << SendMrsCmd; - Set_NB32_DCT(dev, dct, 0x7c, val); - - do { - val = Get_NB32_DCT(dev, dct, 0x7c); - } while (val & (1 << SendMrsCmd)); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -u32 mct_MR2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - if (is_fam15h()) { - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* 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 = 0x80000; - ret |= (MrsChipSel << 21); - - /* Set self refresh parameters */ - ret |= (force_2x_self_refresh << 6); - ret |= (auto_2x_self_refresh << 7); - - /* Obtain Tcwl, adjust, and set CWL with the adjusted value */ - dword = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f; - dword -= pDCTstat->tcwl_delay[dct]; - 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; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR2 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -static u32 mct_MR3(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - if (is_fam15h()) { - ret = 0xc0000; - ret |= (MrsChipSel << 21); - - /* 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; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR3 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -u32 mct_MR1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 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); - - /* 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 = 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_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; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR1 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -static u32 mct_MR0(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret, dword2; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - 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 & 0x7) << 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; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR0 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -static void mct_SendZQCmd(struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /*1.Program MrsAddress[10]=1 - 2.Set SendZQCmd = 1 - */ - dword = Get_NB32_DCT(dev, dct, 0x7C); - dword &= ~0xFFFFFF; - dword |= 1 << 10; - dword |= 1 << SendZQCmd; - Set_NB32_DCT(dev, dct, 0x7C, dword); - - /* Wait for SendZQCmd = 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x7C); - } while (dword & (1 << SendZQCmd)); - - /* 4.Wait 512 MEMCLKs */ - mct_Wait(300); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 MrsChipSel; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - /* 3.Program F2x[1,0]7C[EnDramInit]=1 */ - dword = Get_NB32_DCT(dev, dct, 0x7c); - dword |= 1 << EnDramInit; - Set_NB32_DCT(dev, dct, 0x7c, dword); - mct_DCTAccessDone(pDCTstat, dct); - - /* 4.wait 200us */ - mct_Wait(40000); - - /* 5.Program F2x[1, 0]7C[DeassertMemRstX] = 1. */ - dword = Get_NB32_DCT(dev, dct, 0x7c); - dword |= 1 << DeassertMemRstX; - Set_NB32_DCT(dev, dct, 0x7c, dword); - - /* 6.wait 500us */ - mct_Wait(200000); - - /* 7.Program F2x[1,0]7C[AssertCke]=1 */ - dword = Get_NB32_DCT(dev, dct, 0x7c); - dword |= 1 << AssertCke; - Set_NB32_DCT(dev, dct, 0x7c, dword); - - /* 8.wait 360ns */ - mct_Wait(80); - - /* Set up address parity */ - if ((pDCTstat->Status & (1 << SB_Registered)) - || (pDCTstat->Status & (1 << SB_LoadReduced))) { - if (is_fam15h()) { - dword = Get_NB32_DCT(dev, dct, 0x90); - dword |= 1 << ParEn; - Set_NB32_DCT(dev, dct, 0x90, dword); - } - } - - /* The following steps are performed with registered DIMMs only and - * 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 - */ - } - - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct]; - if (pDCTstat->GangedMode & 1) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - - /* The following steps are performed once for unbuffered DIMMs and once for each - * chip select on registered DIMMs: */ - for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel++) { - if (pDCTstat->CSPresent & (1 << MrsChipSel)) { - u32 EMRS; - /* 13.Send EMRS(2) */ - 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); - EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct); - mct_SendMrsCmd(pDCTstat, dct, EMRS); - /* 15.Send EMRS(1) */ - 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); - EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct); - mct_SendMrsCmd(pDCTstat, dct, EMRS); - - 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 */ - } - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx/* | AMD_RB_C0 */)) /* TODO: We dont support RB_C0 now. need to be added and tested. */ - if (!(pDCTstat->Status & (1 << SB_Registered))) - MrsChipSel ++; - } - - 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_DCT(dev, dct, 0x7C); - dword &= ~(1 << EnDramInit); - Set_NB32_DCT(dev, dct, 0x7C, dword); - mct_DCTAccessDone(pDCTstat, dct); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c deleted file mode 100644 index dbb989fe3d..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c +++ /dev/null @@ -1,2438 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2015 - 2016 Raptor Engineering, LLC - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - */ - -/****************************************************************************** - Description: Receiver En and DQS Timing Training feature for DDR 3 MCT -******************************************************************************/ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> -#include <cpu/x86/cr.h> -#include <string.h> -#include <cpu/x86/msr.h> -#include <cpu/amd/msr.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -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); -static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel); -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 mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat); - -static 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; -} - -/* Warning: These must be located so they do not cross a logical 16-bit - segment boundary! */ -const u32 TestPattern0_D[] = { - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, -}; -const u32 TestPattern1_D[] = { - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, -}; -const u32 TestPattern2_D[] = { - 0x12345678, 0x87654321, 0x23456789, 0x98765432, - 0x59385824, 0x30496724, 0x24490795, 0x99938733, - 0x40385642, 0x38465245, 0x29432163, 0x05067894, - 0x12349045, 0x98723467, 0x12387634, 0x34587623, -}; - -static void SetupRcvrPattern(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 *buffer, u8 pass) -{ - /* - * 1. Copy the alpha and Beta patterns from ROM to Cache, - * aligning on 16 byte boundary - * 2. Set the ptr to DCTStatstruc.PtrPatternBufA for Alpha - * 3. Set the ptr to DCTStatstruc.PtrPatternBufB for Beta - */ - u32 *buf_a; - u32 *buf_b; - u32 *p_A; - u32 *p_B; - u8 i; - - buf_a = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - buf_b = buf_a + 32; /* ?? */ - p_A = (u32 *)SetupDqsPattern_1PassB(pass); - p_B = (u32 *)SetupDqsPattern_1PassA(pass); - - for (i = 0; i < 16; i++) { - buf_a[i] = p_A[i]; - buf_b[i] = p_B[i]; - } - - pDCTstat->PtrPatternBufA = (u32)buf_a; - pDCTstat->PtrPatternBufB = (u32)buf_b; -} - -void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass) -{ - if (mct_checkNumberOfDqsRcvEn_1Pass(Pass)) { - if (is_fam15h()) - dqsTrainRcvrEn_SW_Fam15(pMCTstat, pDCTstat, Pass); - else - dqsTrainRcvrEn_SW_Fam10(pMCTstat, pDCTstat, Pass); - } -} - -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; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - 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; - } else if (package_type == PT_FM2) { - /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 43 */ - seed = 0x32; - } - } - - printk(BIOS_DEBUG, "%s: using seed: %04x\n", __func__, seed); - - return seed; -} - -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; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t wdt_reg; - if ((lane == 0) || (lane == 1)) - wdt_reg = 0x30; - if ((lane == 2) || (lane == 3)) - wdt_reg = 0x31; - if ((lane == 4) || (lane == 5)) - wdt_reg = 0x40; - if ((lane == 6) || (lane == 7)) - wdt_reg = 0x41; - if (lane == 8) - wdt_reg = 0x32; - wdt_reg += dimm * 3; - 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)) - current_total_delay[lane] = dword & 0x000000ff; - } -} - -#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); - } -} - -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; - } - } -} - -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; - - 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)) { - dword &= ~(mask << 16); - dword |= (current_total_delay[lane] & mask) << 16; - } - if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) { - dword &= ~mask; - dword |= current_total_delay[lane] & mask; - } - 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); - } -} - -void read_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t shift; - uint32_t dword; - uint32_t mask; - - if (is_fam15h()) { - mask = 0x3e; - shift = 1; - } - else { - mask = 0x3f; - shift = 0; - } - - /* Lanes 0 - 3 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8)); - delay[3] = ((dword >> 24) & mask) >> shift; - delay[2] = ((dword >> 16) & mask) >> shift; - delay[1] = ((dword >> 8) & mask) >> shift; - delay[0] = (dword & mask) >> shift; - - /* Lanes 4 - 7 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8)); - delay[7] = ((dword >> 24) & mask) >> shift; - delay[6] = ((dword >> 16) & mask) >> shift; - delay[5] = ((dword >> 8) & mask) >> shift; - delay[4] = (dword & mask) >> shift; - - /* Lane 8 (ECC) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8)); - delay[8] = (dword & mask) >> shift; -} - -void write_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t shift; - uint32_t dword; - uint32_t mask; - - if (is_fam15h()) { - mask = 0x3e; - shift = 1; - } - else { - mask = 0x3f; - shift = 0; - } - - /* 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] << shift) & mask) << 24; - dword |= ((delay[2] << shift) & mask) << 16; - dword |= ((delay[1] << shift) & mask) << 8; - dword |= (delay[0] << shift) & 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] << shift) & mask) << 24; - dword |= ((delay[6] << shift) & mask) << 16; - dword |= ((delay[5] << shift) & mask) << 8; - dword |= (delay[4] << shift) & 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] << shift) & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8), dword); -} - -static uint32_t convert_testaddr_and_channel_to_address(struct DCTStatStruc *pDCTstat, uint32_t testaddr, uint8_t channel) -{ - SetUpperFSbase(testaddr); - testaddr <<= 8; - - if ((pDCTstat->Status & (1<<SB_128bitmode)) && channel) { - testaddr += 8; /* second channel */ - } - - return testaddr; -} - -/* 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_Fam10(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; - u16 CTLRMaxDelay; - u16 MaxDelay_CH[2]; - u32 TestAddr0, TestAddr1, TestAddr0B, TestAddr1B; - u32 PatternBuffer[64+4]; /* FIXME: need increase 8? */ - u32 Errors; - - u32 val; - u32 reg; - u32 dev; - u32 index_reg; - u32 ch_start, ch_end, ch; - msr_t msr; - CRx_TYPE cr4; - - uint32_t dword; - uint8_t dimm; - uint8_t rank; - uint8_t lane; - uint16_t current_total_delay[MAX_BYTE_LANES]; - uint16_t candidate_total_delay[8]; - uint8_t data_test_pass_sr[2][8]; /* [rank][lane] */ - uint8_t data_test_pass[8]; /* [lane] */ - uint8_t data_test_pass_prev[8]; /* [lane] */ - uint8_t window_det_toggle[8]; - uint8_t trained[8]; - uint64_t result_qword1; - uint64_t result_qword2; - - u8 valid; - - print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0); - print_debug_dqs("TrainRcvEn: Pass", Pass, 0); - - dev = pDCTstat->dev_dct; - ch_start = 0; - if (!pDCTstat->GangedMode) { - ch_end = 2; - } else { - ch_end = 1; - } - - for (ch = ch_start; ch < ch_end; ch++) { - reg = 0x78; - val = Get_NB32_DCT(dev, ch, reg); - val &= ~(0x3ff << 22); - val |= (0x0c8 << 22); /* MaxRdLatency = 0xc8 */ - Set_NB32_DCT(dev, ch, reg, val); - } - - if (Pass == FirstPass) { - mct_InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat); - } else { - 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 = rdmsr(HWCR_MSR); - /* FIXME: Why use SSEDIS */ - if (msr.lo & (1 << 17)) { /* save the old value */ - _Wrap32Dis = 1; - } - msr.lo |= (1 << 17); /* HWCR.wrap32dis */ - msr.lo &= ~(1 << 15); /* SSEDIS */ - wrmsr(HWCR_MSR, msr); /* Setting wrap32dis allows 64-bit memory - references in real mode */ - - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - SetupRcvrPattern(pMCTstat, pDCTstat, PatternBuffer, Pass); - - 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; - - CTLRMaxDelay = 0; - MaxDelay_CH[Channel] = 0; - index_reg = 0x98; - - 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; - } - - /* Clear data structures */ - for (lane = 0; lane < 8; lane++) { - data_test_pass_prev[lane] = 0; - trained[lane] = 0; - } - - /* 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, 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 - */ - 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 - * to 1/2 MEMCLK for all lanes - */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t rdt_reg; - 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); - if (lane == 8) - dword = 0x0000003f; - else - dword = 0x3f3f3f3f; - Set_NB32_index_wait_DCT(dev, Channel, index_reg, rdt_reg, dword); - } - - /* 2.8.9.9.2 (3) - * Select two test addresses for each rank present - */ - TestAddr0 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver, &valid); - if (!valid) { /* Address not supported on current CS */ - continue; - } - - TestAddr0B = TestAddr0 + (BigPagex8_RJ8 << 3); - - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1)) { - TestAddr1 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver+1, &valid); - if (!valid) { /* Address not supported on current CS */ - continue; - } - TestAddr1B = TestAddr1 + (BigPagex8_RJ8 << 3); - _2Ranks = 1; - } else { - _2Ranks = TestAddr1 = TestAddr1B = 0; - } - - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0 ", TestAddr0, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0B ", TestAddr0B, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr1 ", TestAddr1, 2); - 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 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 */ - if (_2Ranks) { - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1, 0); /*rank 1 of DIMM, testpattern 0 */ - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1B, 1); /*rank 1 of DIMM, testpattern 1 */ - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < 8; lane++) { - print_debug_dqs("\t\tTrainRcvEn54: lane: ", lane, 2); - print_debug_dqs("\t\tTrainRcvEn54: current_total_delay ", current_total_delay[lane], 2); - } -#endif - - /* 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, 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 - * - * FIXME - * It is not clear if training should be discontinued if any test failures occur in the first - * 1 MEMCLK window, or if it should be discontinued if no successes occur in the first 1 MEMCLK - * window. Therefore, loop over up to 2 MEMCLK (0x80 delay steps) to be on the safe side. - */ - uint16_t current_delay_step; - - for (current_delay_step = 0; current_delay_step < 0x80; current_delay_step++) { - print_debug_dqs("\t\t\tTrainRcvEn541: current_delay_step ", current_delay_step, 3); - - /* 2.8.9.9.2 (7 D) - * Terminate if all lanes are trained - */ - uint8_t all_lanes_trained = 1; - for (lane = 0; lane < 8; lane++) - if (!trained[lane]) - all_lanes_trained = 0; - - if (all_lanes_trained) - break; - - /* 2.8.9.9.2 (7 A) - * 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 - * Store the first data beat for analysis - * Reset read pointer in the DRAM controller FIFO - * Read the second test address of the current rank - * Store the first data beat for analysis - * Reset read pointer in the DRAM controller FIFO - */ - if (rank & 1) { - /* 2.8.9.9.2 (7 D) - * Invert read instructions to alternate data read order on the bus - */ - 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, 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, 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, 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, Channel, dimm, index_reg); - } - /* 2.8.9.9.2 (7 A e) - * Compare both read patterns and flag passing ranks/lanes - */ - uint8_t result_lane_byte1; - uint8_t result_lane_byte2; - for (lane = 0; lane < 8; lane++) { - if (trained[lane] == 1) { -#if DQS_TRAIN_DEBUG > 0 - print_debug_dqs("\t\t\t\t\t\t\t\t lane already trained: ", lane, 4); -#endif - continue; - } - - result_lane_byte1 = (result_qword1 >> (lane * 8)) & 0xff; - result_lane_byte2 = (result_qword2 >> (lane * 8)) & 0xff; - if ((result_lane_byte1 == 0x55) && (result_lane_byte2 == 0xaa)) - data_test_pass_sr[rank][lane] = 1; - else - data_test_pass_sr[rank][lane] = 0; -#if DQS_TRAIN_DEBUG > 0 - print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0x55, " | ", result_lane_byte1, 4); - print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0xaa, " | ", result_lane_byte2, 4); -#endif - } - } - - /* 2.8.9.9.2 (7 B) - * If DIMM is dual rank, only use delays that pass testing for both ranks - */ - for (lane = 0; lane < 8; lane++) { - if (_2Ranks) { - if ((data_test_pass_sr[0][lane]) && (data_test_pass_sr[1][lane])) - data_test_pass[lane] = 1; - else - data_test_pass[lane] = 0; - } else { - data_test_pass[lane] = data_test_pass_sr[0][lane]; - } - } - - /* 2.8.9.9.2 (7 E) - * For each lane, update the DQS receiver delay setting in support of next iteration - */ - for (lane = 0; lane < 8; lane++) { - if (trained[lane] == 1) - continue; - - /* 2.8.9.9.2 (7 C a) - * Save the total delay of the first success after a failure for later use - */ - if ((data_test_pass[lane] == 1) && (data_test_pass_prev[lane] == 0)) { - candidate_total_delay[lane] = current_total_delay[lane]; - window_det_toggle[lane] = 0; - } - - /* 2.8.9.9.2 (7 C b) - * If the current delay failed testing add 1/8 UI to the current delay - */ - if (data_test_pass[lane] == 0) - current_total_delay[lane] += 0x4; - - /* 2.8.9.9.2 (7 C c) - * If the current delay passed testing alternately add either 1/32 UI or 1/4 UI to the current delay - * If 1.25 UI of delay have been added with no failures the lane is considered trained - */ - if (data_test_pass[lane] == 1) { - /* See if lane is trained */ - if ((current_total_delay[lane] - candidate_total_delay[lane]) >= 0x28) { - trained[lane] = 1; - - /* Calculate and set final lane delay value - * The final delay is the candidate delay + 7/8 UI - */ - current_total_delay[lane] = candidate_total_delay[lane] + 0x1c; - } else { - if (window_det_toggle[lane] == 0) { - current_total_delay[lane] += 0x1; - window_det_toggle[lane] = 1; - } else { - current_total_delay[lane] += 0x8; - window_det_toggle[lane] = 0; - } - } - } - } - - /* Update delays in hardware */ - 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++) - data_test_pass_prev[lane] = data_test_pass[lane]; - } - -#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 - - /* Find highest delay value and save for later use */ - for (lane = 0; lane < 8; lane++) - if (current_total_delay[lane] > CTLRMaxDelay) - CTLRMaxDelay = current_total_delay[lane]; - - /* See if any lanes failed training, and set error flags appropriately - * For all trained lanes, save delay values for later use - */ - for (lane = 0; lane < 8; lane++) { - if (trained[lane]) { - pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1][lane] = current_total_delay[lane]; - } else { - printk(BIOS_WARNING, "TrainRcvrEn: WARNING: Lane %d of receiver %d on channel %d failed training!\n", lane, Receiver, Channel); - - /* Set error flags */ - pDCTstat->ErrStatus |= 1 << SB_NORCVREN; - Errors |= 1 << SB_NORCVREN; - pDCTstat->ErrCode = SC_FatalErr; - pDCTstat->CSTrainFail |= 1 << Receiver; - pDCTstat->DimmTrainFail |= 1 << (Receiver + Channel); - } - } - - /* 2.8.9.9.2 (8) - * Flush the receiver FIFO - * Write one full cache line of non-0x55/0xaa data to one of the test addresses, then read it back to flush the FIFO - */ - /* FIXME - * This does not seem to be needed, and has a tendency to lock up the - * boot process while attempting to write the test pattern. - */ - } - MaxDelay_CH[Channel] = CTLRMaxDelay; - } - - CTLRMaxDelay = MaxDelay_CH[0]; - if (MaxDelay_CH[1] > CTLRMaxDelay) - CTLRMaxDelay = MaxDelay_CH[1]; - - for (Channel = 0; Channel < 2; Channel++) { - mct_SetMaxLatency_D(pDCTstat, Channel, CTLRMaxDelay); /* program Ch A/B MaxAsyncLat to correspond with max delay */ - } - - 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 = rdmsr(HWCR_MSR); - msr.lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - wrmsr(HWCR_MSR, msr); - } - 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][0]); - } - } -#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 |= (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); - - /* 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; - CRx_TYPE cr4; - u32 lo, hi; - - uint32_t dword; - uint8_t dimm; - uint8_t rank; - uint8_t lane; - uint8_t nibble; - uint8_t mem_clk; - uint16_t min_mem_clk; - uint16_t initial_seed; - uint8_t train_both_nibbles; - uint16_t current_total_delay[MAX_BYTE_LANES]; - uint16_t nibble0_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}; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0); - print_debug_dqs("TrainRcvEn: Pass", Pass, 0); - - min_mem_clk = mctGet_NVbits(NV_MIN_MEMCLK); - - train_both_nibbles = 0; - if (pDCTstat->Dimmx4Present) - if (is_fam15h()) - train_both_nibbles = 1; - - 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_MSR; - _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++) { - for (nibble = 0; nibble < (train_both_nibbles + 1); nibble++) { - /* 2.10.5.8.2 (1) - * Specify the target DIMM and nibble to be trained - */ - dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008); - dword &= ~(0x3 << 4); /* TrDimmSel = dimm */ - dword |= ((dimm & 0x3) << 4); - dword &= ~(0x1 << 2); /* TrNibbleSel = nibble */ - dword |= ((nibble & 0x1) << 2); - 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) / (min_mem_clk * 100))); - - for (lane = 0; lane < lane_count; 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 < lane_count; 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) / (min_mem_clk * 100))); - } - } - - for (lane = 0; lane < lane_count; 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 < lane_count; 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 (nibble == 1) { - /* 2.10.5.8.2 (1) - * Average the trained values of both nibbles on x4 DIMMs - */ - current_total_delay[lane] = (nibble0_current_total_delay[lane] + current_total_delay[lane]) / 2; - } - } - -#if DQS_TRAIN_DEBUG > 1 - for (lane = 0; lane < 8; lane++) - printk(BIOS_DEBUG, "\t\tTrainRcvEn55: Channel: %d dimm: %d nibble: %d lane %d current_total_delay: %04x CH_D_B_RCVRDLY: %04x\n", - Channel, dimm, nibble, lane, current_total_delay[lane], pDCTstat->CH_D_B_RCVRDLY[Channel][dimm][lane]); -#endif - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - if (nibble == 0) { - /* Back up the Nibble 0 delays for later use */ - memcpy(nibble0_current_total_delay, current_total_delay, sizeof(current_total_delay)); - } - - /* Exit nibble training if current DIMM is not x4 */ - if ((pDCTstat->Dimmx4Present & (1 << (dimm + Channel))) == 0) - break; - } - - if (_2Ranks) { - 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 < lane_count; 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); - } - } else { - /* Save the current delay for later use by other routines */ - for (lane = 0; lane < lane_count; lane++) { - 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]; - } - } - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < 8; lane++) - print_debug_dqs_pair("\t\tTrainRcvEn56: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2); -#endif - } - } - - /* Calculate and program MaxRdLatency for both channels */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, 0, 0); - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, 1, 0); - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (Pass == FirstPass) { - /*Disable DQSRcvrEn training mode */ - mct_DisableDQSRcvEn_D(pDCTstat); - } - - if (!_Wrap32Dis) { - msr = HWCR_MSR; - _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][0]); - } - } -#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"); -} - -static void write_max_read_latency_to_registers(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint16_t *latency) -{ - uint32_t dword; - uint8_t nb_pstate; - - for (nb_pstate = 0; nb_pstate < 2; nb_pstate++) { - dword = Get_NB32_DCT_NBPstate(pDCTstat->dev_dct, dct, nb_pstate, 0x210); - dword &= ~(0x3ff << 22); - dword |= ((latency[nb_pstate] & 0x3ff) << 22); - Set_NB32_DCT_NBPstate(pDCTstat->dev_dct, dct, nb_pstate, 0x210, dword); - } -} - -/* DQS MaxRdLatency Training (Family 15h) - * Algorithm detailed in: - * The Fam15h BKDG Rev. 3.14 section 2.10.5.8.5.1 - * This algorithm runs at the highest supported MEMCLK. - */ -void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 Channel; - u8 Receiver; - u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; - u32 Errors; - - u32 dev; - u32 index_reg; - u32 ch_start, ch_end; - u32 msr; - CRx_TYPE cr4; - u32 lo, hi; - - uint32_t dword; - uint8_t dimm; - uint8_t lane; - uint8_t mem_clk; - uint32_t nb_clk; - uint8_t nb_pstate; - uint16_t current_total_delay[MAX_BYTE_LANES]; - uint16_t current_rdqs_total_delay[MAX_BYTE_LANES]; - uint8_t current_worst_case_total_delay_dimm; - uint16_t current_worst_case_total_delay_value; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - 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("\nTrainMaxRdLatency: Node", pDCTstat->Node_ID, 0); - - dev = pDCTstat->dev_dct; - index_reg = 0x98; - ch_start = 0; - ch_end = 2; - - cr4 = read_cr4(); - if (cr4 & (1 << 9)) { /* save the old value */ - _SSE2 = 1; - } - cr4 |= (1 << 9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - msr = HWCR_MSR; - _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("\tTrainMaxRdLatency51: Node ", pDCTstat->Node_ID, 1); - print_debug_dqs("\tTrainMaxRdLatency51: Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - if (pDCTstat->DIMMValidDCT[Channel] == 0) - continue; - - mem_clk = Get_NB32_DCT(dev, Channel, 0x94) & 0x1f; - - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - - /* Find DIMM with worst case receiver enable delays */ - current_worst_case_total_delay_dimm = 0; - current_worst_case_total_delay_value = 0; - - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each DIMM. - */ - for (; Receiver < 8; Receiver += 2) { - dimm = (Receiver >> 1); - - print_debug_dqs("\t\tTrainMaxRdLatency52: Receiver ", Receiver, 2); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - continue; - } - - /* Retrieve the total delay values from pass 1 of DQS receiver enable training */ - read_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - read_dqs_read_data_timing_registers(current_rdqs_total_delay, dev, Channel, dimm, index_reg); - - for (lane = 0; lane < lane_count; lane++) { - current_total_delay[lane] += current_rdqs_total_delay[lane]; - if (current_total_delay[lane] > current_worst_case_total_delay_value) { - current_worst_case_total_delay_dimm = dimm; - current_worst_case_total_delay_value = current_total_delay[lane]; - } - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < lane_count; lane++) - print_debug_dqs_pair("\t\tTrainMaxRdLatency56: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2); -#endif - } - - /* 2.10.5.8.5.1.1 */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, Channel, 1); - - /* 2.10.5.8.5.1.[2,3] - * Write the DRAM training pattern to the test address - */ - write_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, Channel, current_worst_case_total_delay_dimm << 1, 0xff, 0); - - /* 2.10.5.8.5.1.4 - * Incrementally test each MaxRdLatency candidate - */ - for (; pDCTstat->CH_MaxRdLat[Channel][0] < 0x3ff; pDCTstat->CH_MaxRdLat[Channel][0]++) { - write_max_read_latency_to_registers(pMCTstat, pDCTstat, Channel, pDCTstat->CH_MaxRdLat[Channel]); - read_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, Channel, current_worst_case_total_delay_dimm << 1, 0xff, 0); - dword = Get_NB32_DCT(dev, Channel, 0x268) & 0x3ffff; - if (!dword) - break; - Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000050, 0x13131313); - } - dword = Get_NB32_DCT(dev, Channel, 0x268) & 0x3ffff; - if (dword) - printk(BIOS_ERR, "WARNING: MaxRdLatency training FAILED! Attempting to continue but your system may be unstable...\n"); - - /* 2.10.5.8.5.1.5 */ - nb_pstate = 0; - mem_clk = Get_NB32_DCT(dev, Channel, 0x94) & 0x1f; - if (fam15h_freq_tab[mem_clk] == 0) { - return; - } - 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); - - pDCTstat->CH_MaxRdLat[Channel][0]++; - pDCTstat->CH_MaxRdLat[Channel][0] += ((((uint64_t)15 * 100000000000ULL) / ((uint64_t)fam15h_freq_tab[mem_clk] * 1000000ULL)) - * ((uint64_t)nb_clk * 1000)) / 1000000000ULL; - - write_max_read_latency_to_registers(pMCTstat, pDCTstat, Channel, pDCTstat->CH_MaxRdLat[Channel]); - } - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (!_Wrap32Dis) { - msr = HWCR_MSR; - _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, "TrainMaxRdLatency: CH_MaxRdLat:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel:%x: %x\n", - ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD][0]); - } - } -#endif - - printk(BIOS_DEBUG, "TrainMaxRdLatency: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainMaxRdLatency: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainMaxRdLatency: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "TrainMaxRdLatency: Done\n\n"); -} - -u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (pDCTstat->DIMMValidDCT[dct] == 0) { - return 8; - } else { - return 0; - } -} - -static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat) -{ - u8 ch_end, ch; - u32 reg; - u32 dev; - u32 val; - - dev = pDCTstat->dev_dct; - if (pDCTstat->GangedMode) { - ch_end = 1; - } else { - ch_end = 2; - } - - for (ch = 0; ch < ch_end; ch++) { - reg = 0x78; - val = Get_NB32_DCT(dev, ch, reg); - val &= ~(1 << DqsRcvEnTrain); - Set_NB32_DCT(dev, ch, reg, val); - } -} - -/* mct_ModifyIndex_D - * Function only used once so it was inlined. - */ - -/* mct_GetInitFlag_D - * Function only used once so it was inlined. - */ - -/* Set F2x[1, 0]9C_x[2B:10] DRAM DQS Receiver Enable Timing Control Registers - * See BKDG Rev. 3.62 page 268 for more information - */ -void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, - u8 FinalValue, u8 Channel, u8 Receiver, u32 dev, - u32 index_reg, u8 Addl_Index, u8 Pass) -{ - u32 index; - u8 i; - u16 *p; - u32 val; - - if (RcvrEnDly == 0x1fe) { - /*set the boundary flag */ - pDCTstat->Status |= 1 << SB_DQSRcvLimit; - } - - /* DimmOffset not needed for CH_D_B_RCVRDLY array */ - for (i = 0; i < 8; i++) { - if (FinalValue) { - /*calculate dimm offset */ - p = pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1]; - RcvrEnDly = p[i]; - } - - /* if flag = 0, set DqsRcvEn value to reg. */ - /* get the register index from table */ - index = Table_DQSRcvEn_Offset[i >> 1]; - index += Addl_Index; /* DIMMx DqsRcvEn byte0 */ - val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, index); - if (i & 1) { - /* odd byte lane */ - val &= ~(0x1ff << 16); - val |= ((RcvrEnDly & 0x1ff) << 16); - } else { - /* even byte lane */ - val &= ~0x1ff; - val |= (RcvrEnDly & 0x1ff); - } - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index, val); - } - -} - -/* Calculate MaxRdLatency - * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.5 - */ -static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 DQSRcvEnDly) -{ - u32 dev; - u32 reg; - u32 SubTotal; - u32 index_reg; - u32 val; - - uint8_t cpu_val_n; - uint8_t cpu_val_p; - - u16 freq_tab[] = {400, 533, 667, 800}; - - /* Set up processor-dependent values */ - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - /* Revision D and above */ - cpu_val_n = 4; - cpu_val_p = 29; - } else if (pDCTstat->LogicalCPUID & AMD_DR_Cx) { - /* Revision C */ - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - if ((package_type == PT_L1) /* Socket F (1207) */ - || (package_type == PT_M2) /* Socket AM3 */ - || (package_type == PT_S1)) { /* Socket S1g <x> */ - cpu_val_n = 10; - cpu_val_p = 11; - } else { - cpu_val_n = 4; - cpu_val_p = 29; - } - } else { - /* Revision B and below */ - cpu_val_n = 10; - cpu_val_p = 11; - } - - if (pDCTstat->GangedMode) - Channel = 0; - - dev = pDCTstat->dev_dct; - index_reg = 0x98; - - /* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/ - 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_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_DCT(dev, Channel, index_reg, 0x04); - if (!(val & 0x00202020)) - SubTotal += 1; - else - SubTotal += 2; - - /* 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_DCT(dev, Channel, 0x78); - SubTotal += 8 - (val & 0x0f); - - /* Convert bits 7-5 (also referred to as the coarse delay) of - * the current (or worst case) DQS receiver enable delay to - * 1/2 MEMCLKs units, rounding up, and add this to the sub-total. - */ - SubTotal += DQSRcvEnDly >> 5; /* Retrieve gross delay portion of value */ - - /* Add "P" to the sub-total. "P" represents part of the - * processor specific constant delay value in the DRAM - * clock domain. - */ - SubTotal <<= 1; /*scale 1/2 MemClk to 1/4 MemClk */ - SubTotal += cpu_val_p; /*add "P" 1/2MemClk */ - SubTotal >>= 1; /*scale 1/4 MemClk back to 1/2 MemClk */ - - /* Convert the sub-total (in 1/2 MEMCLKs) to northbridge - * clocks (NCLKs) - */ - SubTotal *= 200 * ((Get_NB32(pDCTstat->dev_nbmisc, 0xd4) & 0x1f) + 4); - 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 - * processor specific constant value in the northbridge - * clock domain. - */ - SubTotal += (cpu_val_n) / 2; - - pDCTstat->CH_MaxRdLat[Channel][0] = SubTotal; - if (pDCTstat->GangedMode) { - pDCTstat->CH_MaxRdLat[1][0] = SubTotal; - } - - /* Program the F2x[1, 0]78[MaxRdLatency] register with - * the total delay value (in NCLKs). - */ - 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_DCT(dev, Channel, reg, val); -} - -static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Initialize the DQS Positions in preparation for - * Receiver Enable Training. - * Write Position is 1/2 Memclock Delay - * Read Position is 1/2 Memclock Delay - */ - u8 i; - for (i = 0; i < 2; i++) { - InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat, i); - } -} - -static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel) -{ - /* Initialize the DQS Positions in preparation for - * Receiver Enable Training. - * Write Position is no Delay - * Read Position is 1/2 Memclock Delay - */ - - u8 i, j; - u32 dword; - u8 dn = 4; /* TODO: Rev C could be 4 */ - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98; - - /* FIXME: add Cx support */ - dword = 0x00000000; - for (i = 1; i <= 3; i++) { - for (j = 0; j < dn; j++) - /* DIMM0 Write Data Timing Low */ - /* DIMM0 Write ECC Timing */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, i + 0x100 * j, dword); - } - - /* errata #180 */ - dword = 0x2f2f2f2f; - for (i = 5; i <= 6; i++) { - for (j = 0; j < dn; j++) - /* DIMM0 Read DQS Timing Control Low */ - 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_DCT(dev, Channel, index_reg, 7 + 0x100 * j, dword); -} - -void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel) -{ - u32 dev; - u32 index_reg; - u32 index; - u8 ChipSel; - u16 *p; - u32 val; - - dev = pDCTstat->dev_dct; - 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_DCT(dev, Channel, index_reg, index, val); - print_debug_dqs_pair("\t\tSetEccDQSRcvrPos: ChipSel ", - ChipSel, " rcvr_delay ", val, 2); - index += 3; - } -} - -static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel) -{ - u8 ChipSel; - u16 EccDQSLike; - u8 EccDQSScale; - u32 val, val0, val1; - int16_t delay_differential; - - EccDQSLike = pDCTstat->CH_EccDQSLike[Channel]; - EccDQSScale = pDCTstat->CH_EccDQSScale[Channel]; - - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, ChipSel)) { - u16 *p; - p = pDCTstat->CH_D_B_RCVRDLY[Channel][ChipSel>>1]; - - if (pDCTstat->Status & (1 << SB_Registered)) { - val0 = p[0x2]; - val1 = p[0x3]; - - delay_differential = (int16_t)val1 - (int16_t)val0; - delay_differential += (int16_t)val1; - - val = delay_differential; - } else { - /* DQS Delay Value of Data Bytelane - * most like ECC byte lane */ - val0 = p[EccDQSLike & 0x07]; - /* DQS Delay Value of Data Bytelane - * 2nd most like ECC byte lane */ - val1 = p[(EccDQSLike>>8) & 0x07]; - - if (val0 > val1) { - val = val0 - val1; - } else { - val = val1 - val0; - } - - val *= ~EccDQSScale; - val >>= 8; /* /256 */ - - if (val0 > val1) { - val -= val1; - } else { - val += val0; - } - } - - pDCTstat->CH_D_BC_RCVRDLY[Channel][ChipSel>>1] = val; - } - } - SetEccDQSRcvrEn_D(pDCTstat, Channel); -} - -/* 2.8.9.9.4 - * ECC Byte Lane Training - * DQS Receiver Enable Delay - */ -void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 i; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (!pDCTstat->NodePresent) - break; - if (pDCTstat->DCTSysLimit) { - for (i = 0; i < 2; i++) - CalcEccDQSRcvrEn_D(pMCTstat, pDCTstat, i); - } - } -} - -void phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, int16_t single_node_number) -{ - u8 Node = 0; - struct DCTStatStruc *pDCTstat; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint8_t start_node = 0; - uint8_t end_node = MAX_NODES_SUPPORTED; - - if (single_node_number >= 0) { - start_node = single_node_number; - end_node = single_node_number + 1; - } - - /* FIXME: skip for Ax */ - for (Node = start_node; Node < end_node; 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; - - printk(BIOS_SPEW, "%s: training node %d DCT %d\n", __func__, Node, dct); - - /* 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); - } - - /* Restore D18F2x9C_x0000_0004_dct[1:0] */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004, datc_backup); - - printk(BIOS_SPEW, "%s: done training node %d DCT %d\n", __func__, Node, dct); - } - } else { - fenceDynTraining_D(pMCTstat, pDCTstat, 0); - fenceDynTraining_D(pMCTstat, pDCTstat, 1); - } - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -uint32_t fenceDynTraining_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - u16 avRecValue; - u32 val; - u32 dev; - u32 index_reg = 0x98; - u32 index; - - dev = pDCTstat->dev_dct; - - 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; - } - } - - 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); - } - - /* 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; - } - } - - 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) -{ - u32 saved; - u32 hi, lo, msr; - - /* Wait # of 50ns cycles - This seems like a hack to me... */ - - cycles <<= 3; /* x8 (number of 1.25ns ticks) */ - - msr = TSC_MSR; /* TSC */ - _RDMSR(msr, &lo, &hi); - saved = lo; - do { - _RDMSR(msr, &lo, &hi); - } while (lo - saved < cycles); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c deleted file mode 100644 index 98aadddc6c..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * 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. - */ - -#include <arch/cpu.h> -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -static 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; -} - -u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass) -{ - u8 ret = 1; - - if (is_fam15h()) { - /* Fam15h needs two passes */ - ret = 1; - } else { - if (pass == SecondPass) - ret = 0; - } - - return ret; -} - -u32 SetupDqsPattern_1PassA(u8 pass) -{ - return (u32) TestPattern1_D; -} - -u32 SetupDqsPattern_1PassB(u8 pass) -{ - return (u32) TestPattern0_D; -} - -static u16 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 Channel, u8 Receiver, - u8 Pass) -{ - u16 i, MaxValue; - u16 *p; - u16 val; - - MaxValue = 0; - p = pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1]; - - for (i = 0; i < 8; i++) { - /* get left value from DCTStatStruc.CHA_D0_B0_RCVRDLY*/ - val = p[i]; - /* get right value from DCTStatStruc.CHA_D0_B0_RCVRDLY_1*/ - val += Pass1MemClkDly; - /* write back the value to stack */ - if (val > MaxValue) - MaxValue = val; - - p[i] = val; - } - /* pDCTstat->DimmTrainFail &= ~(1<<Receiver+Channel); */ - - return MaxValue; -} - -u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, u8 pass) -{ - u8 ret; - ret = 0; - if ((pDCTstat->DqsRcvEn_Pass == 0xff) && (pass== FirstPass)) - ret = 2; - return ret; -} - -u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, - u16 RcvrEnDly, u16 RcvrEnDlyLimit, - u8 Channel, u8 Receiver, u8 Pass) - -{ - return mct_Average_RcvrEnDly_1Pass(pDCTstat, Channel, Receiver, Pass); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c deleted file mode 100644 index 8eeb93ff78..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - */ - -u8 mct_checkNumberOfDqsRcvEn_Pass(u8 pass) -{ - return 1; -} - -u32 SetupDqsPattern_PassA(u8 Pass) -{ - u32 ret; - if (Pass == FirstPass) - ret = (u32) TestPattern1_D; - else - ret = (u32) TestPattern2_D; - - return ret; -} - -u32 SetupDqsPattern_PassB(u8 Pass) -{ - u32 ret; - if (Pass == FirstPass) - ret = (u32) TestPattern0_D; - else - ret = (u32) TestPattern2_D; - - return ret; -} - -u8 mct_Get_Start_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, - u8 Channel, u8 Receiver, - u8 Pass) -{ - u8 RcvrEnDly; - - if (Pass == FirstPass) - RcvrEnDly = 0; - else { - u8 max = 0; - u8 val; - u8 i; - u8 *p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1]; - u8 bn; - bn = 8; - - for (i = 0; i < bn; i++) { - val = p[i]; - - if (val > max) { - max = val; - } - } - RcvrEnDly = max; - } - - return RcvrEnDly; -} - -u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, - u16 RcvrEnDly, u16 RcvrEnDlyLimit, - u8 Channel, u8 Receiver, u8 Pass) -{ - u8 i; - u16 *p; - u16 *p_1; - u16 val; - u16 val_1; - u8 valid = 1; - u8 bn; - - bn = 8; - - p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1]; - - if (Pass == SecondPass) { /* second pass must average values */ - /* FIXME: which byte? */ - p_1 = pDCTstat->B_RCVRDLY_1; - /* p_1 = pDCTstat->persistentData.CH_D_B_RCVRDLY_1[Channel][Receiver>>1]; */ - for (i = 0; i < bn; i++) { - val = p[i]; - /* left edge */ - if (val != (RcvrEnDlyLimit - 1)) { - val -= Pass1MemClkDly; - val_1 = p_1[i]; - val += val_1; - val >>= 1; - p[i] = val; - } else { - valid = 0; - break; - } - } - if (!valid) { - pDCTstat->ErrStatus |= 1<<SB_NORCVREN; - } else { - pDCTstat->DimmTrainFail &= ~(1<<(Receiver + Channel)); - } - } else { - for (i = 0; i < bn; i++) { - val = p[i]; - /* Add 1/2 Memlock delay */ - /* val += Pass1MemClkDly; */ - val += 0x5; /* NOTE: middle value with DQSRCVEN_SAVED_GOOD_TIMES */ - /* val += 0x02; */ - p[i] = val; - pDCTstat->DimmTrainFail &= ~(1<<(Receiver + Channel)); - } - } - - return RcvrEnDly; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c deleted file mode 100644 index b6ab65e2f8..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * 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 - * 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. - */ - -/* - * Description: Max Read Latency Training feature for DDR 3 MCT - */ - -#include <stdint.h> -#include <console/console.h> -#include <cpu/amd/msr.h> -#include <cpu/x86/cr.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr); -static u32 GetMaxRdLatTestAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel, - u8 *MaxRcvrEnDly, u8 *valid); -u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel, - u8 DQSRcvEnDly, u32 *Margin); -static void maxRdLatencyTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat, u8 Channel, - u16 MaxRdLatVal); - -/*Warning: These must be located so they do not cross a logical 16-bit - segment boundary!*/ -static const u32 TestMaxRdLAtPattern_D[] = { - 0x6E0E3FAC, 0x0C3CFF52, - 0x4A688181, 0x49C5B613, - 0x7C780BA6, 0x5C1650E3, - 0x0C4F9D76, 0x0C6753E6, - 0x205535A5, 0xBABFB6CA, - 0x610E6E5F, 0x0C5F1C87, - 0x488493CE, 0x14C9C383, - 0xF5B9A5CD, 0x9CE8F615, - - 0xAAD714B5, 0xC38F1B4C, - 0x72ED647C, 0x669F7562, - 0x5233F802, 0x4A898B30, - 0x10A40617, 0x3326B465, - 0x55386E04, 0xC807E3D3, - 0xAB49E193, 0x14B4E63A, - 0x67DF2495, 0xEA517C45, - 0x7624CE51, 0xF8140C51, - - 0x4824BD23, 0xB61DD0C9, - 0x072BCFBE, 0xE8F3807D, - 0x919EA373, 0x25E30C47, - 0xFEB12958, 0x4DA80A5A, - 0xE9A0DDF8, 0x792B0076, - 0xE81C73DC, 0xF025B496, - 0x1DB7E627, 0x808594FE, - 0x82668268, 0x655C7783, -}; - -static u32 SetupMaxRdPattern(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 *buffer) -{ - /* 1. Copy the alpha and Beta patterns from ROM to Cache, - * aligning on 16 byte boundary - * 2. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufA - * for Alpha - * 3. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufB - * for Beta - */ - u32 *buf; - u8 i; - - buf = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - - for (i = 0; i < (16 * 3); i++) { - buf[i] = TestMaxRdLAtPattern_D[i]; - } - - return (u32)buf; -} - -void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (!pDCTstat->NodePresent) - break; - - if (pDCTstat->DCTSysLimit) - maxRdLatencyTrain_D(pMCTstat, pDCTstat); - } -} - -static void maxRdLatencyTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 Channel; - u32 TestAddr0; - u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; - u16 MaxRdLatDly; - u8 RcvrEnDly = 0; - u32 PatternBuffer[60]; /* FIXME: why not 48 + 4 */ - u32 Margin; - u32 addr; - CRx_TYPE cr4; - u32 lo, hi; - - u8 valid; - u32 pattern_buf; - - cr4 = read_cr4(); - if (cr4 & (1<<9)) { /* save the old value */ - _SSE2 = 1; - } - cr4 |= (1<<9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - if (lo & (1<<17)) { /* save the old value */ - _Wrap32Dis = 1; - } - lo |= (1<<17); /* HWCR.wrap32dis */ - lo &= ~(1<<15); /* SSEDIS */ - /* Setting wrap32dis allows 64-bit memory references in - real mode */ - _WRMSR(addr, lo, hi); - - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - pattern_buf = SetupMaxRdPattern(pMCTstat, pDCTstat, PatternBuffer); - - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tMaxRdLatencyTrain51: Channel ",Channel, 1); - pDCTstat->Channel = Channel; - - if ((pDCTstat->Status & (1 << SB_128bitmode)) && Channel) - break; /*if ganged mode, skip DCT 1 */ - - TestAddr0 = GetMaxRdLatTestAddr_D(pMCTstat, pDCTstat, Channel, &RcvrEnDly, &valid); - if (!valid) /* Address not supported on current CS */ - continue; - /* rank 1 of DIMM, testpattern 0 */ - WriteMaxRdLat1CLTestPattern_D(pattern_buf, TestAddr0); - - MaxRdLatDly = mct_GetStartMaxRdLat_D(pMCTstat, pDCTstat, Channel, RcvrEnDly, &Margin); - print_debug_dqs("\tMaxRdLatencyTrain52: MaxRdLatDly start ", MaxRdLatDly, 2); - print_debug_dqs("\tMaxRdLatencyTrain52: MaxRdLatDly Margin ", Margin, 2); - while (MaxRdLatDly < MAX_RD_LAT) { /* sweep Delay value here */ - mct_setMaxRdLatTrnVal_D(pDCTstat, Channel, MaxRdLatDly); - ReadMaxRdLat1CLTestPattern_D(TestAddr0); - if (CompareMaxRdLatTestPattern_D(pattern_buf, TestAddr0) == DQS_PASS) - break; - SetTargetWTIO_D(TestAddr0); - FlushMaxRdLatTestPattern_D(TestAddr0); - ResetTargetWTIO_D(); - MaxRdLatDly++; - } - print_debug_dqs("\tMaxRdLatencyTrain53: MaxRdLatDly end ", MaxRdLatDly, 2); - mct_setMaxRdLatTrnVal_D(pDCTstat, Channel, MaxRdLatDly + Margin); - } - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (!_Wrap32Dis) { - addr = HWCR_MSR; - _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); - } - -#if DQS_TRAIN_DEBUG > 0 - { - u8 ChannelDTD; - printk(BIOS_DEBUG, "maxRdLatencyTrain: CH_MaxRdLat:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel: %02x: %02x\n", ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD][0]); - } - } -#endif -} - -static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat, - u8 Channel, u16 MaxRdLatVal) -{ - u8 i; - u32 reg; - u32 dev; - u32 val; - - if (pDCTstat->GangedMode) { - Channel = 0; /* for safe */ - for (i = 0; i < 2; i++) - pDCTstat->CH_MaxRdLat[i][0] = MaxRdLatVal; - } else { - pDCTstat->CH_MaxRdLat[Channel][0] = MaxRdLatVal; - } - - dev = pDCTstat->dev_dct; - reg = 0x78; - val = Get_NB32_DCT(dev, Channel, reg); - val &= ~(0x3ff<<22); - val |= MaxRdLatVal<<22; - /* program MaxRdLatency to correspond with current delay */ - Set_NB32_DCT(dev, Channel, reg, val); -} - -static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr) -{ - /* Compare only the first beat of data. Since target addrs are cache - * line aligned, the Channel parameter is used to determine which cache - * QW to compare. - */ - - u32 *test_buf = (u32 *)pattern_buf; - u32 addr_lo; - u32 val, val_test; - int i; - u8 ret = DQS_PASS; - - SetUpperFSbase(addr); - addr_lo = addr<<8; - - _EXECFENCE; - for (i = 0; i < 16*3; i++) { - val = read32_fs(addr_lo); - val_test = test_buf[i]; - - print_debug_dqs_pair("\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value = ", val_test, 5); - print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value = ", val, 5); - if (val != val_test) { - ret = DQS_FAIL; - break; - } - addr_lo += 4; - } - - return ret; -} - -static u32 GetMaxRdLatTestAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 *MaxRcvrEnDly, - u8 *valid) -{ - u8 Max = 0; - - u8 Channel_Max = 0; - u8 d; - u8 d_Max = 0; - - u8 Byte; - u32 TestAddr0 = 0; - u8 ch, ch_start, ch_end; - u8 bn; - - bn = 8; - - if (pDCTstat->Status & (1 << SB_128bitmode)) { - ch_start = 0; - ch_end = 2; - } else { - ch_start = Channel; - ch_end = Channel + 1; - } - - *valid = 0; - - for (ch = ch_start; ch < ch_end; ch++) { - for (d = 0; d < 4; d++) { - for (Byte = 0; Byte < bn; Byte++) { - u8 tmp; - tmp = pDCTstat->CH_D_B_RCVRDLY[ch][d][Byte]; - if (tmp > Max) { - Max = tmp; - Channel_Max = Channel; - d_Max = d; - } - } - } - } - - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel_Max, d_Max << 1)) { - TestAddr0 = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, Channel_Max, d_Max << 1, valid); - } - - if (*valid) - *MaxRcvrEnDly = Max; - - return TestAddr0; -} - -u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 DQSRcvEnDly, u32 *Margin) -{ - u32 SubTotal; - u32 val; - u32 valx; - u32 valxx; - u32 index_reg; - u32 dev; - - if (pDCTstat->GangedMode) - Channel = 0; - - index_reg = 0x98; - - dev = pDCTstat->dev_dct; - - /* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/ - 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_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_DCT(dev, Channel, index_reg, 0x04); - if (!(val & 0x00202020)) - SubTotal += 1; - else - SubTotal += 2; - - /* 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_DCT(dev, Channel, 0x78); - SubTotal += 8 - (val & 0x0f); - - /* Convert bits 7-5 (also referred to as the course delay) of the current - * (or worst case) DQS receiver enable delay to 1/2 MEMCLKs units, - * rounding up, and add this to the sub-total. */ - SubTotal += DQSRcvEnDly >> 5; /*BOZO-no rounding up */ - - SubTotal <<= 1; /*scale 1/2 MemClk to 1/4 MemClk */ - - /* Convert the sub-total (in 1/2 MEMCLKs) to northbridge clocks (NCLKs) - * as follows (assuming DDR400 and assuming that no P-state or link speed - * changes have occurred). */ - - /*New formula: - SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */ - val = Get_NB32_DCT(dev, Channel, 0x94); - /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */ - val &= 7; - if (val >= 3) { - val <<= 1; - } else - val += 3; - valx = (val) << 2; /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */ - - val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4); - val = ((val & 0x1f) + 4) * 3; - - /* Calculate 1 MemClk + 1 NCLK delay in NCLKs for margin */ - valxx = val << 2; - valxx /= valx; - if (valxx % valx) - valxx++; /* round up */ - valxx++; /* add 1NCLK */ - *Margin = valxx; /* one MemClk delay in NCLKs and one additional NCLK */ - - val *= SubTotal; - - val /= valx; - if (val % valx) - val++; /* round up */ - - return val; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c deleted file mode 100644 index 82523e01b8..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2015 - 2016 Raptor Engineering, LLC - * - * 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. - */ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -static 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 AgesaDelay(u32 msec) -{ - mct_Wait(msec*10); -} - -void PrepareC_MCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - pDCTstat->C_MCTPtr->AgesaDelay = AgesaDelay; -} - -void PrepareC_DCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 dimm; - u16 DimmValid; - u16 Dimmx8Present; - - dct &= 1; - - pDCTstat->C_DCTPtr[dct]->DctTrain = dct; - - if (dct == 1) { - Dimmx8Present = pDCTstat->Dimmx8Present >> 1; - } else - Dimmx8Present = pDCTstat->Dimmx8Present; - Dimmx8Present &= 0x55; - - pDCTstat->C_DCTPtr[dct]->MaxDimmsInstalled = pDCTstat->MAdimms[dct]; - DimmValid = pDCTstat->DIMMValidDCT[dct]; - - pDCTstat->C_DCTPtr[dct]->NodeId = pDCTstat->Node_ID; - pDCTstat->C_DCTPtr[dct]->LogicalCPUID = pDCTstat->LogicalCPUID; - - for (dimm = 0; dimm < MAX_DIMMS; dimm++) { - if (DimmValid & (1 << (dimm << 1))) - pDCTstat->C_DCTPtr[dct]->DimmPresent[dimm] = 1; - if (Dimmx8Present & (1 << (dimm << 1))) - pDCTstat->C_DCTPtr[dct]->DimmX8Present[dimm] = 1; - } - - if (pDCTstat->GangedMode & (1 << 0)) - pDCTstat->C_DCTPtr[dct]->CurrDct = 0; - else - pDCTstat->C_DCTPtr[dct]->CurrDct = dct; - - pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[dct]; - if (!(pDCTstat->GangedMode & (1 << 0)) && (dct == 1)) - pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[0]; - - if (pDCTstat->Status & (1 << SB_Registered)) { - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 1; - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 0; - } else { - if (pDCTstat->MirrPresU_NumRegR > 0) - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 1; - 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++) { - u8 DimmRanks; - if (DimmValid & (1 << (dimm << 1))) { - DimmRanks = 1; - if (pDCTstat->DimmDRPresent & (1 << ((dimm << 1) + dct))) - DimmRanks = 2; - else if (pDCTstat->DimmQRPresent & (1 << ((dimm << 1) + dct))) - DimmRanks = 4; - } else - DimmRanks = 0; - pDCTstat->C_DCTPtr[dct]->DimmRanks[dimm] = DimmRanks; - } -} - -void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - u32 val; - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - val |= 1 << 11; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - val |= 1 << 11; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); -} - -void DisableZQcalibration(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - val &= ~(1 << 11); - val &= ~(1 << 10); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - val &= ~(1 << 11); - val &= ~(1 << 10); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); -} - -static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 DCT0Present, DCT1Present; - u32 val; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - /* Program F2x[1, 0]90[EnterSelfRefresh]=1. */ - if (DCT0Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - val |= 1 << EnterSelfRef; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val); - } - if (DCT1Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val |= 1 << EnterSelfRef; - 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_DCT(pDCTstat->dev_dct, 0, 0x90); - } while (val & (1 <<EnterSelfRef)); - if (DCT1Present) - do { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - } while (val & (1 <<EnterSelfRef)); -} - -/* - * Change memclk for write levelization pass 2 - */ -static void ChangeMemClk(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint8_t DCT0Present; - uint8_t DCT1Present; - uint32_t dword; - uint32_t mask; - uint32_t offset; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - 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) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - dword &= ~(1 << MemClkFreqVal); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword); - } - if (DCT1Present) { - 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) { - 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) { - 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) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - dword |= 1 << MemClkFreqVal; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword); - } - if (DCT1Present) { - 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 { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - } while (dword & (1 << FreqChgInProg)); - if (DCT1Present) - do { - 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 */ - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -/* - * the DRAM controller to bring the DRAMs out of self refresh mode. - */ -static void ExitSelfRefresh(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 DCT0Present, DCT1Present; - u32 val; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - /* Program F2x[1, 0]90[ExitSelfRef]=1 for both DCTs. */ - if (DCT0Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - val |= 1 << ExitSelfRef; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val); - } - if (DCT1Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val |= 1 << ExitSelfRef; - 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_DCT(pDCTstat->dev_dct, 0, 0x90); - } while (val & (1 << ExitSelfRef)); - if (DCT1Present) - do { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - } while (val & (1 << ExitSelfRef)); -} - -void SetTargetFreq(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Node) -{ - uint32_t dword; - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - printk(BIOS_DEBUG, "%s: Node %d: New frequency code: %04x\n", __func__, Node, pDCTstat->TargetFreq); - - 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. - */ - EnterSelfRefresh(pMCTstat, pDCTstat); - - /* - * Program F2x[1,0]9C_x08[DisAutoComp]=1 - * Program F2x[1,0]94[MemClkFreqVal] = 0. - * Program F2x[1,0]94[MemClkFreq] to specify the target MEMCLK frequency. - * Program F2x[1,0]94[MemClkFreqVal] = 1. - * Wait until F2x[1,0]94[FreqChgInProg]=0. - * Program F2x[1,0]9C_x08[DisAutoComp]=0 - */ - ChangeMemClk(pMCTstat, pDCTstat); - - if (is_fam15h()) { - uint8_t dct; - for (dct = 0; dct < 2; dct++) { - if (pDCTstat->DIMMValidDCT[dct]) { - phyAssistedMemFnceTraining(pMCTstat, pDCTstatA, Node); - 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); - - if (pDCTstat->Status & (1 << SB_Registered)) { - u8 DCT0Present, DCT1Present; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - if (!DCT1Present) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - else if (pDCTstat->GangedMode) - pDCTstat->CSPresent = 0; - else - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1]; - - if (pDCTstat->DIMMValidDCT[0]) { - FreqChgCtrlWrd(pMCTstat, pDCTstat, 0); - } - if (pDCTstat->DIMMValidDCT[1]) { - FreqChgCtrlWrd(pMCTstat, pDCTstat, 1); - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void Modify_OnDimmMirror(struct DCTStatStruc *pDCTstat, u8 dct, u8 set) -{ - u32 val; - 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_DCT(pDCTstat->dev_dct, dct, reg, val); - reg += 8; - } -} - -void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */ - if (pDCTstat->MirrPresU_NumRegR & 0x55) - Modify_OnDimmMirror(pDCTstat, 0, 1); /* dct = 0, set */ - if (pDCTstat->MirrPresU_NumRegR & 0xAA) - Modify_OnDimmMirror(pDCTstat, 1, 1); /* dct = 1, set */ - } -} -void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */ - if (pDCTstat->MirrPresU_NumRegR & 0x55) - Modify_OnDimmMirror(pDCTstat, 0, 0); /* dct = 0, clear */ - if (pDCTstat->MirrPresU_NumRegR & 0xAA) - Modify_OnDimmMirror(pDCTstat, 1, 0); /* dct = 1, clear */ - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c deleted file mode 100644 index 353aa7a1cf..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c +++ /dev/null @@ -1,1519 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2015 - 2016 Raptor Engineering, LLC - * - * 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. - */ - -#include <stdint.h> -#include <assert.h> -#include <console/console.h> -#include <northbridge/amd/amdfam10/amdfam10.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" -#include "mwlc_d.h" - -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, uint8_t dimm, uint8_t pass, uint8_t nibble); -void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass, uint8_t lane_count); -void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass, uint8_t nibble, uint8_t lane_count); - -#define MAX_LANE_COUNT 9 - -/*----------------------------------------------------------------------------- - * uint8_t AgesaHwWlPhase1(SPDStruct *SPDData,MCTStruct *MCTData, DCTStruct *DCTData, - * u8 Dimm, u8 Pass) - * - * Description: - * This function initialized Hardware based write levelization phase 1 - * - * Parameters: - * IN OUT *SPDData - Pointer to buffer with information about each DIMMs - * SPD information - * *MCTData - Pointer to buffer with runtime parameters, - * *DCTData - Pointer to buffer with information about each DCT - * - * IN DIMM - Logical DIMM number - * Pass - First or Second Pass - * OUT - *----------------------------------------------------------------------------- - */ -uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - u8 dct, u8 dimm, u8 pass) -{ - u8 ByteLane; - u32 Value, Addr; - uint8_t nibble = 0; - uint8_t train_both_nibbles; - u16 Addl_Data_Offset, Addl_Data_Port; - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - 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, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, TrDimmSelStart, - TrDimmSelEnd, (u32)dimm); - - train_both_nibbles = 0; - if (pDCTstat->Dimmx4Present) - if (is_fam15h()) - train_both_nibbles = 1; - - for (nibble = 0; nibble < (train_both_nibbles + 1); nibble++) { - printk(BIOS_SPEW, "AgesaHwWlPhase1: training nibble %d\n", nibble); - - if (is_fam15h()) { - /* Program F2x[1, 0]9C_x08[WrtLvTrEn]=0 */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 0); - - /* Set TrNibbleSel */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, 2, - 2, (uint32_t)nibble); - } - - /* 2. Prepare the DIMMs for write levelization using DDR3-defined - * MR commands. */ - prepareDimms(pMCTstat, pDCTstat, dct, dimm, TRUE); - - /* 3. After the DIMMs are configured, BIOS waits 40 MEMCLKs to - * satisfy DDR3-defined internal DRAM timing. - */ - 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: */ - procConfig(pMCTstat, pDCTstat, dct, dimm, pass, nibble); - - /* 5. Begin write levelization training: - * 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 - * Set bit 0 (wrTrain) - * Program bit 4 to nibble being trained (only matters for x4dimms) - * retain value of 3:2 (Trdimmsel) - * reset bit 5 (FrzPR) - */ - if (dct) - { - Addl_Data_Offset = 0x198; - Addl_Data_Port = 0x19C; - } - else - { - Addl_Data_Offset = 0x98; - Addl_Data_Port = 0x9C; - } - Addr = 0x0D00000C; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Value = bitTestSet(Value, 0); /* enable WL training */ - Value = bitTestReset(Value, 4); /* for x8 only */ - Value = bitTestReset(Value, 5); /* for hardware WL training */ - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Addr = 0x4D030F0C; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - } - - if (is_fam15h()) - proc_MFENCE(); - - /* Wait 200 MEMCLKs. If executing pass 2, wait 32 MEMCLKs. */ - 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, 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. */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - getWLByteDelay(pDCTstat, dct, ByteLane, dimm, pass, nibble, lane_count); - } - - pDCTData->WLCriticalGrossDelayPrevPass = 0x0; - - /* Exit nibble training if current DIMM is not x4 */ - if ((pDCTstat->Dimmx4Present & (1 << (dimm + dct))) == 0) - break; - } - - return 0; -} - -uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - uint8_t dct, uint8_t dimm, uint8_t pass) -{ - u8 ByteLane; - uint8_t status = 0; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - assert(lane_count <= MAX_LANE_COUNT); - - if (is_fam15h()) { - int32_t gross_diff[MAX_LANE_COUNT]; - int32_t cgd = pDCTData->WLCriticalGrossDelayPrevPass; - uint8_t index = (uint8_t)(lane_count * dimm); - - printk(BIOS_SPEW, "\toriginal critical gross delay: %d\n", cgd); - - /* FIXME - * For now, disable CGD adjustment as it seems to interfere with registered DIMM training - */ - - /* Calculate the Critical Gross Delay */ - for (ByteLane = 0; ByteLane < lane_count; 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]; - } - - printk(BIOS_SPEW, "\tnew critical gross delay: %d\n", cgd); - - pDCTData->WLCriticalGrossDelayPrevPass = cgd; - - if (pDCTstat->Speed != pDCTstat->TargetFreq) { - /* FIXME - * Using the Pass 1 training values causes major phy training problems on - * all Family 15h processors I tested (Pass 1 values are randomly too high, - * and Pass 2 cannot lock). - * Figure out why this is and fix it, then remove the bypass code below... - */ - if (pass == FirstPass) { - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane]; - pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane]; - } - return 0; - } - } - - /* Compensate for occasional noise/instability causing sporadic training failure */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - uint8_t faulty_value_detected = 0; - 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 (pass == FirstPass) { - /* Allow a somewhat higher step threshold on the first pass - * For the most part, as long as the phy isn't stepping - * several clocks at once the values are probably valid. - */ - if (abs(total_delay_phy - total_delay_seed) > 0x30) - faulty_value_detected = 1; - } else { - /* Stepping memory clocks between adjacent allowed frequencies - * should not yield large phy value differences... - */ - - if (abs(total_delay_phy - total_delay_seed) > 0x20) - faulty_value_detected = 1; - } - if (faulty_value_detected) { - printk(BIOS_INFO, "%s: overriding faulty phy value (seed: %04x phy: %04x step: %04x)\n", __func__, - total_delay_seed, total_delay_phy, abs(total_delay_phy - total_delay_seed)); - pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane]; - pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane]; - status = 1; - } - } - } - - return status; -} - -uint8_t 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]; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - assert(lane_count <= MAX_LANE_COUNT); - - if (is_fam15h()) { - uint32_t dword; - int32_t gross_diff[MAX_LANE_COUNT]; - int32_t cgd = pDCTData->WLCriticalGrossDelayPrevPass; - uint8_t index = (uint8_t)(lane_count * 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 < lane_count; 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 = pDCTData->WrDqsGrossDlyBaseOffset */ - dword |= ((pDCTData->WrDqsGrossDlyBaseOffset & 0x3) << 24); - 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 < lane_count; ByteLane++) { - setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 1, pass, lane_count); - } - - /* 6. Configure DRAM Phy Control Register so that the phy stops driving - * write levelization ODT. */ - 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. */ - 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 - * [Phy Assisted Write Levelization] on page 97 pass 1, step #2): - * Configure all ranks of the target DIMM for normal operation. - * Enable the output drivers of all ranks of the target DIMM. - * For a two DIMM system, program the Rtt value for the target DIMM - * to the normal operating termination: - */ - prepareDimms(pMCTstat, pDCTstat, dct, dimm, FALSE); - - return 0; -} - -/*---------------------------------------------------------------------------- - * LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ - -/*----------------------------------------------------------------------------- - * u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue) - * - * Description: - * This function swaps the bits in MSR register value - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN u32: MRS value - * OUT u32: Swapped BANK BITS - * - * ---------------------------------------------------------------------------- - */ -u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u32 tempW, tempW1; - - 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])) - { - /* swap A3/A4,A5/A6,A7/A8 */ - tempW = MRSValue; - tempW1 = MRSValue; - tempW &= 0x0A8; - tempW1 &= 0x0150; - MRSValue &= 0xFE07; - MRSValue |= (tempW << 1); - MRSValue |= (tempW1 >> 1); - } - } - return MRSValue; -} - -/*----------------------------------------------------------------------------- - * u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue) - * - * Description: - * This function swaps the bits in MSR register value - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN u32: MRS value - * OUT u32: Swapped BANK BITS - * - * ---------------------------------------------------------------------------- - */ -u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u32 tempW, tempW1; - - 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])) - { - /* swap BA0/BA1 */ - tempW = MRSValue; - tempW1 = MRSValue; - tempW &= 0x01; - tempW1 &= 0x02; - MRSValue = 0; - MRSValue |= (tempW << 1); - MRSValue |= (tempW1 >> 1); - } - } - return MRSValue; -} - -static uint16_t unbuffered_dimm_nominal_termination_emrs(uint8_t number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank) -{ - uint16_t term; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (number_of_dimms == 1) { - if (MaxDimmsInstallable < 3) { - term = 0x04; /* Rtt_Nom = RZQ/4 = 60 Ohm */ - } else { - if (rank_count == 1) { - term = 0x04; /* Rtt_Nom = RZQ/4 = 60 Ohm */ - } else { - if (rank == 0) - term = 0x04; /* Rtt_Nom = RZQ/4 = 60 Ohm */ - else - term = 0x00; /* Rtt_Nom = OFF */ - } - } - } else { - if (frequency_index < 5) - term = 0x0044; /* Rtt_Nom = RZQ/6 = 40 Ohm */ - else - term = 0x0204; /* Rtt_Nom = RZQ/8 = 30 Ohm */ - } - - return term; -} - -static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t number_of_dimms, uint8_t frequency_index, uint8_t rank_count) -{ - uint16_t term; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (number_of_dimms == 1) { - if (MaxDimmsInstallable < 3) { - term = 0x00; /* Rtt_WR = off */ - } else { - if (rank_count == 1) - term = 0x00; /* Rtt_WR = off */ - else - term = 0x200; /* Rtt_WR = RZQ/4 = 60 Ohm */ - } - } else { - term = 0x400; /* Rtt_WR = RZQ/2 = 120 Ohm */ - } - - return term; -} - -/*----------------------------------------------------------------------------- - * void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *DCTData, u8 Dimm, BOOL WL) - * - * Description: - * This function prepares DIMMS for training - * Fam10h: BKDG Rev. 3.62 section 2.8.9.9.1 - * Fam15h: BKDG Rev. 3.14 section 2.10.5.8.1 - * ---------------------------------------------------------------------------- - */ -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; - - 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. - */ - rank = 0; - while ((rank < pDCTData->DimmRanks[dimm]) && (rank < 2)) - { - /* Program F2x[1, 0]7C[MrsChipSel[2:0]] for the current rank to be trained. */ - 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(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 */ - - /* 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 (is_fam15h()) { - if (wl) { - 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 { - tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - } - } else { - tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - } - tempW1 = 0; - tempW1 |= ((tempW2 & 0x4) >> 2) << 9; - tempW1 |= ((tempW2 & 0x2) >> 1) << 6; - tempW1 |= ((tempW2 & 0x1) >> 0) << 2; - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - tempW1 = RttNomTargetRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank); - } else { - if (wl) { - if (number_of_dimms > 1) { - if (rank == 0) { - /* Get Rtt_WR for the current DIMM and rank */ - uint16_t dynamic_term = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm]); - - /* Convert dynamic termination code to corresponding nominal termination code */ - if (dynamic_term == 0x200) - tempW1 = 0x04; - else if (dynamic_term == 0x400) - tempW1 = 0x40; - else - tempW1 = 0x0; - } else { - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank); - } - } else { - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank); - } - } else { - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank); - } - } - } - - /* Apply Rtt_Nom to the MRS control word */ - tempW = tempW|tempW1; - - /* All ranks of the target DIMM are set to write levelization mode. */ - if (wl) - { - tempW1 = bitTestSet(tempW, MRS_Level); - if (rank == 0) - { - /* Enable the output driver of the first rank of the target DIMM. */ - tempW = tempW1; - } - else - { - /* Disable the output drivers of all other ranks for - * the target DIMM. - */ - tempW = bitTestSet(tempW1, Qoff); - } - } - - /* 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(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, 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, 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(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,*/ - - /* 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 (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(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, 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, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1) - { - } - - rank++; - } - - /* Configure the non-target DIMM normally. */ - currDimm = 0; - while (currDimm < MAX_LDIMMS) - { - if (pDCTData->DimmPresent[currDimm]) - { - if (currDimm != dimm) - { - rank = 0; - while ((rank < pDCTData->DimmRanks[currDimm]) && (rank < 2)) - { - /* Program F2x[1, 0]7C[MrsChipSel[2:0]] for the current rank - * to be trained. - */ - 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(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 */ - - /* Retrieve normal settings of the MRS control word and clear Rtt_Nom */ - if (is_fam15h()) { - tempW = mct_MR1(pMCTstat, pDCTstat, dct, currDimm*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 (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) */ - 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(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, 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, 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(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,*/ - - /* Retrieve normal settings of the MRS control word and clear Rtt_WR */ - if (is_fam15h()) { - tempW = mct_MR2(pMCTstat, pDCTstat, dct, currDimm*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 (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(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, 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, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1) - { - } - rank++; - } - } - } - currDimm++; - } -} - -/*----------------------------------------------------------------------------- - * void programODT(sMCTStruct *pMCTData, DCTStruct *DCTData, u8 dimm) - * - * Description: - * This function programs the ODT values for the NB - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN - * OUT - * ---------------------------------------------------------------------------- - */ -void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm) -{ - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - - u8 WrLvOdt1 = 0; - - if (is_fam15h()) { - /* On Family15h processors, the value for the specific CS being targeted - * is taken from F2x238 / F2x23C as appropriate, then loaded into F2x9C_x0000_0008 - */ - - /* 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]) { - WrLvOdt1 = WrLvOdtRegDimm(pMCTData, pDCTData, dimm); - } else { - 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); - } - } - } - - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, 8, 11, (u32)WrLvOdt1); - - printk(BIOS_SPEW, "Programmed DCT %d write levelling ODT pattern %08x from DIMM %d data\n", dct, WrLvOdt1, dimm); - -} - -#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 procConfig(MCTStruct *MCTData,DCTStruct *DCTData, u8 Dimm, u8 Pass, u8 Nibble) - * - * Description: - * This function programs the ODT values for the NB - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * *MCTData - Pointer to buffer with runtime parameters, - * IN Dimm - Logical DIMM - * Pass - First of Second Pass - * OUT - * ---------------------------------------------------------------------------- - */ -void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t pass, uint8_t nibble) -{ - u8 ByteLane, MemClkFreq; - int32_t Seed_Gross; - int32_t Seed_Fine; - uint8_t Seed_PreGross; - u32 Value, Addr; - uint32_t dword; - u16 Addl_Data_Offset, Addl_Data_Port; - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint16_t fam10h_freq_tab[] = {0, 0, 0, 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}; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - assert(lane_count <= MAX_LANE_COUNT); - - 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(pMCTstat, pDCTstat, dct, dimm); - - /* Program F2x[1,0]9C_x08[WrLvOdtEn]=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, WrLvOdtEn, WrLvOdtEn, (u32)1); - } - else - { - /* Program WrLvOdtEn = 1 through set bit 12 of D3CSODT reg offset 0 for Rev.B */ - if (dct) - { - Addl_Data_Offset = 0x198; - Addl_Data_Port = 0x19C; - } - else - { - Addl_Data_Offset = 0x98; - Addl_Data_Port = 0x9C; - } - Addr = 0x0D008000; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Value = bitTestSet(Value, 12); - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Addr = 0x4D088F00; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - } - - if (is_fam15h()) - proc_MFENCE(); - - /* Wait 10 MEMCLKs to allow for ODT signal settling. */ - if (is_fam15h()) - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 10); - else - pMCTData->AgesaDelay(10); - - /* Program write levelling seed values */ - if (pass == 1) - { - /* 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; - pDCTData->WrDqsGrossDlyBaseOffset = 0x0; - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 96 */ - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - /* TODO - * Implement mainboard-specific seed and - * WrDqsGrossDly base overrides. - * 0x41 and 0x0 are the "stock" values - */ - Seed_Total = 0x41; - pDCTData->WrDqsGrossDlyBaseOffset = 0x2; - } 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; - } else if (package_type == PT_FM2) { - /* Socket FM2: Fam15h M10 BKDG 3.12 Table 42 */ - Seed_Total = 0x15; - } - 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 < lane_count; ByteLane++) { - pDCTData->WLSeedGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLSeedFineDelay[lane_count*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[lane_count*dimm+ByteLane] = Seed_PreGross; - } - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - - /* The seed values below assume Pass 1 utilizes a 400MHz clock frequency (DDR3-800) */ - if (AddrCmdPrelaunch == 0) { - Seed_Gross = 0x02; - Seed_Fine = 0x01; - } else { - Seed_Gross = 0x02; - Seed_Fine = 0x11; - } - } 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; - } - } - } - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) - { - /* Program an initialization value to registers F2x[1, 0]9C_x[51:50] and - * F2x[1, 0]9C_x52 to set the gross and fine delay for all the byte lane fields - * If the target frequency is different than 400MHz, BIOS must - * execute two training passes for each DIMM. - * For pass 1 at a 400MHz MEMCLK frequency, use an initial total delay value - * of 01Fh. This represents a 1UI (UI=.5MEMCLK) delay and is determined - * by design. - */ - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - printk(BIOS_SPEW, "\tLane %02x initial seed: %04x\n", ByteLane, ((Seed_Gross & 0x1f) << 5) | (Seed_Fine & 0x1f)); - } - } else { - if (nibble == 0) { - /* Pass 2 */ - /* From BKDG, Write Leveling Seed Value. */ - if (is_fam15h()) { - uint32_t RegisterDelay; - int32_t SeedTotal[MAX_LANE_COUNT]; - int32_t SeedTotalPreScaling[MAX_LANE_COUNT]; - uint32_t WrDqDqsEarly; - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - if (AddrCmdPrelaunch) - RegisterDelay = 0x30; - else - RegisterDelay = 0x20; - } else { - RegisterDelay = 0; - } - - /* Retrieve WrDqDqsEarly */ - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8); - WrDqDqsEarly = (dword >> 24) & 0x3; - - /* FIXME - * Ignore WrDqDqsEarly for now to work around training issues - */ - WrDqDqsEarly = 0; - - /* Generate new seed values */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - /* Calculate adjusted seed values */ - SeedTotal[ByteLane] = (pDCTData->WLFineDelayPrevPass[lane_count*dimm+ByteLane] & 0x1f) | - ((pDCTData->WLGrossDelayPrevPass[lane_count*dimm+ByteLane] & 0x1f) << 5); - SeedTotalPreScaling[ByteLane] = (SeedTotal[ByteLane] - RegisterDelay - (0x20 * WrDqDqsEarly)); - SeedTotal[ByteLane] = (int32_t) (RegisterDelay + ((((int64_t) SeedTotalPreScaling[ByteLane]) * - fam15h_freq_tab[MemClkFreq] * 100) / (fam15h_freq_tab[pDCTData->WLPrevMemclkFreq[dimm]] * 100))); - } - - /* Generate register values from seeds */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - printk(BIOS_SPEW, "\tLane %02x scaled delay: %04x\n", ByteLane, SeedTotal[ByteLane]); - - if (SeedTotal[ByteLane] >= 0) { - Seed_Gross = SeedTotal[ByteLane] / 32; - Seed_Fine = SeedTotal[ByteLane] % 32; - } else { - Seed_Gross = (SeedTotal[ByteLane] / 32) - 1; - Seed_Fine = (SeedTotal[ByteLane] % 32) + 32; - } - - /* The BKDG-recommended algorithm causes problems with registered DIMMs on some systems - * due to the long register delays causing premature total delay wrap-around. - * Attempt to work around this... - */ - Seed_PreGross = Seed_Gross; - - /* Save seed values for later use */ - pDCTData->WLSeedGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLSeedFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane] = Seed_PreGross; - - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = Seed_PreGross; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } else { - uint32_t RegisterDelay; - uint32_t SeedTotalPreScaling; - uint32_t SeedTotal; - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) - { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - if (AddrCmdPrelaunch == 0) - RegisterDelay = 0x20; - else - RegisterDelay = 0x30; - } else { - RegisterDelay = 0; - } - SeedTotalPreScaling = ((pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f) | - (pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] << 5)) - RegisterDelay; - /* SeedTotalPreScaling = (the total delay value in F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization - training) - RegisterDelay. */ - SeedTotal = (uint16_t) ((((uint64_t) SeedTotalPreScaling) * - fam10h_freq_tab[MemClkFreq] * 100) / (fam10h_freq_tab[3] * 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; - - /* The BKDG-recommended algorithm causes problems with registered DIMMs on some systems - * due to the long register delays causing premature total delay wrap-around. - * Attempt to work around this... - */ - SeedTotal = ((Seed_Gross & 0x1f) << 5) | (Seed_Fine & 0x1f); - SeedTotal += RegisterDelay; - Seed_Gross = SeedTotal / 32; - Seed_Fine = SeedTotal & 0x1f; - - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } - - /* Save initial seeds for upper nibble pass */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLSeedPreGrossPrevNibble[lane_count*dimm+ByteLane] = pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane]; - pDCTData->WLSeedGrossPrevNibble[lane_count*dimm+ByteLane] = pDCTData->WLGrossDelay[lane_count*dimm+ByteLane]; - pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane] = pDCTData->WLFineDelay[lane_count*dimm+ByteLane]; - } - } else { - /* Restore seed values from lower nibble pass */ - if (is_fam15h()) { - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLSeedGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedGrossPrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLSeedFineDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedPreGrossPrevNibble[lane_count*dimm+ByteLane]; - - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedPreGrossPrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane]; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } else { - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedGrossPrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane]; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } - } - } - - pDCTData->WLPrevMemclkFreq[dimm] = MemClkFreq; - setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 0, pass, lane_count); -} - -/*----------------------------------------------------------------------------- - * void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm, uint8_t lane_count){ - * - * Description: - * This function writes the write levelization byte delay for the Phase - * Recovery control registers - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN Dimm - Dimm Number - * DCTData->WLGrossDelay[index+ByteLane] - gross write delay for each - * logical DIMM - * DCTData->WLFineDelay[index+ByteLane] - fine write delay for each - * logical DIMM - * ByteLane - target byte lane to write - * targetAddr - 0: write to DRAM phase recovery control register - * 1: write to DQS write register - * OUT - * - *----------------------------------------------------------------------------- - */ -void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass, uint8_t lane_count) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, index, offsetAddr; - u32 addr, fineDelayValue, grossDelayValue, ValueLow, ValueHigh, EccValue, tempW; - - if (targetAddr == 0) - { - index = (u8)(lane_count * dimm); - ValueLow = 0; - ValueHigh = 0; - ByteLane = 0; - EccValue = 0; - while (ByteLane < lane_count) - { - /* 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) - ValueLow |= ((grossDelayValue << 5) | fineDelayValue) << 8*ByteLane; - else if (ByteLane < 8) - ValueHigh |= ((grossDelayValue << 5) | fineDelayValue) << 8*(ByteLane-4); - else - EccValue = ((grossDelayValue << 5) | fineDelayValue); - ByteLane++; - } - 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, dct, pDCTData->NodeId, FUN_DCT, - DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH, 0, 31, (u32)ValueHigh); - 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) - * Fam15h BKDG: Rev. 3.14 2.10.5.8.1 - */ - index = (u8)(lane_count * dimm); - grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane]; - fineDelayValue = pDCTData->WLFineDelay[index+ByteLane]; - - tempB = 0; - offsetAddr = (u8)(3 * dimm); - if (ByteLane < 2) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01; - } else if (ByteLane <4) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 + 1; - } else if (ByteLane <6) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45; - } else if (ByteLane <8) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45 + 1; - } else { - tempB = 0; - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 + 2; - } - addr += offsetAddr; - - fineStartLoc = (u8)(tempB % 32); - fineEndLoc = (u8)(fineStartLoc + 4); - grossStartLoc = (u8)(fineEndLoc + 1); - grossEndLoc = (u8)(grossStartLoc + 2); - - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - (u16)addr, fineStartLoc, fineEndLoc,(u32)fineDelayValue); - 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(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm, u8 Nibble, uint8_t lane_count) - * - * Description: - * This function reads the write levelization byte delay from the Phase - * Recovery control registers - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN Dimm - Dimm Number - * ByteLane - target byte lane to read - * OUT - * DCTData->WLGrossDelay[index+ByteLane] - gross write delay for current - * byte for logical DIMM - * DCTData->WLFineDelay[index+ByteLane] - fine write delay for current - * byte for logical DIMM - * - *----------------------------------------------------------------------------- - */ -void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass, uint8_t nibble, uint8_t lane_count) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, tempB1, index; - u32 addr, fine, gross; - tempB = 0; - index = (u8)(lane_count*dimm); - if (ByteLane < 4) { - tempB = (u8)(8 * ByteLane); - addr = DRAM_CONT_ADD_PHASE_REC_CTRL_LOW; - } else if (ByteLane < 8) { - tempB1 = (u8)(ByteLane - 4); - tempB = (u8)(8 * tempB1); - addr = DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH; - } else { - tempB = 0; - addr = DRAM_CONT_ADD_ECC_PHASE_REC_CTRL; - } - fineStartLoc = tempB; - fineEndLoc = (u8)(fineStartLoc + 4); - grossStartLoc = (u8)(fineEndLoc + 1); - grossEndLoc = (u8)(grossStartLoc + 1); - - fine = get_ADD_DCT_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, (u16)addr, fineStartLoc, fineEndLoc); - gross = get_ADD_DCT_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, (u16)addr, grossStartLoc, grossEndLoc); - - printk(BIOS_SPEW, "\tLane %02x nibble %01x raw readback: %04x\n", ByteLane, nibble, ((gross & 0x1f) << 5) | (fine & 0x1f)); - - /* 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. - */ - gross = 0; - fine = 0; - } - printk(BIOS_SPEW, "\tLane %02x nibble %01x adjusted value (pre nibble): %04x\n", ByteLane, nibble, ((gross & 0x1f) << 5) | (fine & 0x1f)); - - /* Nibble adjustments */ - if (nibble == 0) { - pDCTData->WLFineDelay[index+ByteLane] = (uint8_t)fine; - pDCTData->WLGrossDelay[index+ByteLane] = (uint8_t)gross; - } else { - uint32_t WLTotalDelay = ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f); - WLTotalDelay += ((gross & 0x1f) << 5) | (fine & 0x1f); - WLTotalDelay /= 2; - pDCTData->WLFineDelay[index+ByteLane] = (uint8_t)(WLTotalDelay & 0x1f); - pDCTData->WLGrossDelay[index+ByteLane] = (uint8_t)((WLTotalDelay >> 5) & 0x1f); - } - printk(BIOS_SPEW, "\tLane %02x nibble %01x adjusted value (post nibble): %04x\n", ByteLane, nibble, ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f)); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/modtrd.c b/src/northbridge/amd/amdmct/mct_ddr3/modtrd.c deleted file mode 100644 index 954dd6f2ef..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/modtrd.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u8 Speed = pDCTstat->Speed; - u32 ret; - u8 DimmsInstalled, DimmNum, ChipSelect; - - ChipSelect = (MrsChipSel >> 20) & 0xF; - DimmNum = ChipSelect & 0xFE; - DimmsInstalled = pDCTstat->MAdimms[dct]; - if (dct == 1) - DimmNum ++; - ret = 0; - - if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { - if (DimmsInstalled == 1) - ret |= 1 << 2; - else { - if (pDCTstat->CSPresent & 0xF0) { - if (pDCTstat->DimmQRPresent & (1 << DimmNum)) { - if (!(ChipSelect & 1)) - ret |= 1 << 2; - } else - ret |= 0x204; - } else { - if (Speed < 6) - ret |= 0x44; - else - ret |= 0x204; - } - } - } else if (DimmsInstalled == 1) - ret |= 1 << 2; - else if (Speed < 6) - ret |= 0x44; - else - ret |= 0x204; - - //ret = 0; - return ret; -} - -u32 mct_DramTermDyn_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dimm) -{ - u8 DimmsInstalled = dimm; - u32 DramTermDyn = 0; - u8 Speed = pDCTstat->Speed; - - if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { - if (pDCTstat->CSPresent & 0xF0) { - if (DimmsInstalled == 1) - if (Speed == 7) - DramTermDyn |= 1 << 10; - else - DramTermDyn |= 1 << 11; - else - if (Speed == 4) - DramTermDyn |= 1 << 11; - else - DramTermDyn |= 1 << 10; - } else { - if (DimmsInstalled != 1) { - if (Speed == 7) - DramTermDyn |= 1 << 10; - else - DramTermDyn |= 1 << 11; - } - } - } else { - if (DimmsInstalled != 1) - DramTermDyn |= 1 << 11; - } - return DramTermDyn; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c b/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c deleted file mode 100644 index 06bfdba84f..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * 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 - * 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. - */ - -/* This file contains functions for odt setting on registered DDR3 dimms */ - -#include <stdint.h> -#include <console/console.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -/** - * - * - * This function set Rtt_Nom for registered DDR3 dimms on targeted dimm. - * - * @param *pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - targeted dimm - * @param wl - current mode, either write levelization mode or normal mode - * @param MemClkFreq - current frequency - * @param rank - * - * @return tempW1 - Rtt_Nom - */ -u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) -{ - u32 tempW1; - tempW1 = 0; - if (wl) { - switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { - case 2: - /* 2 dimms per channel */ - if (pDCTData->MaxDimmsInstalled == 1) { - if ((pDCTData->DimmRanks[dimm] == 2) && (rank == 0)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if (pDCTData->DimmRanks[dimm] == 4) { - if (rank == 1) { - tempW1 = 0x00; /* Rtt_Nom = OFF on second and forth rank of QR dimm */ - } else { - if (MemClkFreq == 6) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } - } - } else { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } - } else if (pDCTData->MaxDimmsInstalled == 2) { - if (((pDCTData->DimmRanks[dimm] == 2) || (pDCTData->DimmRanks[dimm] == 4)) && (rank == 1)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if ((pDCTData->DimmRanks[dimm] == 4) || (pDCTData->DctCSPresent & 0xF0)) { - if (MemClkFreq == 3) { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } else { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } - } else { - if (MemClkFreq == 6) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } - } - } - break; - case 3: - /* 3 dimms per channel */ - /* QR not supported in this case on L1 package. */ - if (pDCTData->MaxDimmsInstalled == 1) { - if ((pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } - } else { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } - break; - default: - die("modtrdim.c: WTF?"); - } - } else { - switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { - case 2: - /* 2 dimms per channel */ - if ((pDCTData->DimmRanks[dimm] == 4) && (rank == 1)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if ((pDCTData->MaxDimmsInstalled == 1) || (pDCTData->DimmRanks[dimm] == 4)) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else { - if (pDCTData->DctCSPresent & 0xF0) { - tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ - } else { - if (MemClkFreq < 5) { - tempW1 = 0x44; /* Rtt_Nom = 40 ohms */ - } else { - tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ - } - } - } - break; - case 3: - /* 3 dimms per channel */ - /* L1 package does not support QR dimms this case. */ - if (rank == 1) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if (pDCTData->MaxDimmsInstalled == 1) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else if ((MemClkFreq < 5) || (pDCTData->MaxDimmsInstalled == 3)) { - tempW1 = 0x44; /* Rtt_Nom = 40 ohms */ - } else { - tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ - } - break; - default: - die("modtrdim.c: WTF?"); - } - } - return tempW1; -} - -/* -----------------------------------------------------------------------------*/ -/** - * - * - * This function set Rtt_Nom for registered DDR3 dimms on non-targeted dimm. - * - * @param *pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - non-targeted dimm - * @param wl - current mode, either write levelization mode or normal mode - * @param MemClkFreq - current frequency - * @param rank - * - * @return tempW1 - Rtt_Nom - */ -u32 RttNomNonTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) -{ - if ((wl) && (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) && (pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) { - return 0x00; /* for non-target dimm during WL, the second rank of a DR dimm need to have Rtt_Nom = OFF */ - } else { - return RttNomTargetRegDimm (pMCTData, pDCTData, dimm, FALSE, MemClkFreq, rank); /* otherwise, the same as target dimm in normal mode. */ - } -} - -/* -----------------------------------------------------------------------------*/ -/** - * - * - * This function set Rtt_Wr for registered DDR3 dimms. - * - * @param pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - targeted dimm - * @param wl - current mode, either write levelization mode or normal mode - * @param MemClkFreq - current frequency - * @param rank - * - * @return tempW1 - Rtt_Wr - */ - -u32 RttWrRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) -{ - u32 tempW1; - tempW1 = 0; - if (wl) { - tempW1 = 0x00; /* Rtt_WR = OFF */ - } else { - switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { - case 2: - if (pDCTData->MaxDimmsInstalled == 1) { - if (pDCTData->DimmRanks[dimm] != 4) { - tempW1 = 0x00; - } else { - if (MemClkFreq == 6) { - tempW1 = 0x200; /* Rtt_WR = 60 ohms */ - } else { - tempW1 = 0x400; /* Rtt_WR = 120 ohms */ - } - } - } else { - if ((pDCTData->DimmRanks[dimm] == 4) || (pDCTData->DctCSPresent & 0xF0)) { - if (MemClkFreq == 3) { - tempW1 = 0x400; /* Rtt_WR = 120 ohms */ - } else { - tempW1 = 0x200; /* Rtt_WR = 60 ohms */ - } - } else { - if (MemClkFreq == 6) { - tempW1 = 0x200; /* Rtt_WR = 60 ohms */ - } else { - tempW1 = 0x400; /* Rtt_Nom = 120 ohms */ - } - } - } - break; - case 3: - if (pDCTData->MaxDimmsInstalled == 1) { - tempW1 = 0x00; /* Rtt_WR = OFF */ - } else { - tempW1 = 0x400; /* Rtt_Nom = 120 ohms */ - } - break; - default: - die("modtrdim.c: WTF?"); - } - } - return tempW1; -} - -/* -----------------------------------------------------------------------------*/ -/** - * - * - * This function set WrLvOdt for registered DDR3 dimms. - * - * @param *pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - targeted dimm - * - * @return WrLvOdt - */ -u8 WrLvOdtRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm) -{ - u8 WrLvOdt1, i; - WrLvOdt1 = 0; - i = 0; - while (i < 8) { - if (pDCTData->DctCSPresent & (1 << i)) { - WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, i/2); - } - i += 2; - } - if (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) { - if ((pDCTData->DimmRanks[dimm] == 4) && (pDCTData->MaxDimmsInstalled != 1)) { - if (dimm >= 2) { - WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm - 2)); - } else { - WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm + 2)); - } - } else if ((pDCTData->DimmRanks[dimm] == 2) && (pDCTData->MaxDimmsInstalled == 1)) { - /* the case for one DR on a 2 dimms per channel is special */ - WrLvOdt1 = 0x8; - } - } - return WrLvOdt1; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mport_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mport_d.c deleted file mode 100644 index 999cb94f24..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mport_d.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * - * 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. - */ - -#include <arch/io.h> -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" -#include "mwlc_d.h" - -void AmdMemPCIRead(SBDFO loc, u32 *Value) -{ - /* Convert SBDFO into a CF8 Address */ - loc = (loc >> 4 & 0xFFFFFF00) | (loc & 0xFF) | ((loc & 0xF00) << 16); - loc |= 0x80000000; - - outl(loc, 0xCF8); - - *Value = inl(0xCFC); -} - -void AmdMemPCIWrite(SBDFO loc, u32 *Value) -{ - /* Convert SBDFO into a CF8 Address */ - loc = (loc >> 4 & 0xFFFFFF00) | (loc & 0xFF) | ((loc & 0xF00) << 16); - loc |= 0x80000000; - - outl(loc, 0xCF8); - outl(*Value, 0xCFC); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c deleted file mode 100644 index 0420b660b9..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * 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 - * 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. - */ - -/* This file contains functions for common utility functions */ - -#include <arch/cpu.h> -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" -#include "mwlc_d.h" - -static 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; -} - -void AmdMemPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue) -{ - /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */ - - AmdMemPCIRead(loc, pValue); - *pValue = *pValue >> lowbit; /* Shift */ - - /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */ - if ((highbit-lowbit) != 31) - *pValue &= (((u32)1 << (highbit-lowbit+1))-1); -} - -void AmdMemPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue) -{ - u32 temp, mask; - - /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */ - - /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */ - if ((highbit-lowbit) != 31) - mask = (((u32)1 << (highbit-lowbit+1))-1); - else - mask = (u32)0xFFFFFFFF; - - AmdMemPCIRead(loc, &temp); - temp &= ~(mask << lowbit); - temp |= (*pValue & mask) << lowbit; - AmdMemPCIWrite(loc, &temp); -} - -/*----------------------------------------------------------------------------- - * u32 bitTestSet(u32 csMask,u32 tempD) - * - * Description: - * This routine sets a bit in a u32 - * - * Parameters: - * IN csMask = Target value in which the bit will be set - * IN tempD = Bit that will be set - * OUT value = Target value with the bit set - *----------------------------------------------------------------------------- - */ -u32 bitTestSet(u32 csMask,u32 tempD) -{ - u32 localTemp; - /* ASSERT(tempD < 32); */ - localTemp = 1; - csMask |= localTemp << tempD; - return csMask; -} - -/*----------------------------------------------------------------------------- - * u32 bitTestReset(u32 csMask,u32 tempD) - * - * Description: - * This routine re-sets a bit in a u32 - * - * Parameters: - * IN csMask = Target value in which the bit will be re-set - * IN tempD = Bit that will be re-set - * OUT value = Target value with the bit re-set - *----------------------------------------------------------------------------- - */ -u32 bitTestReset(u32 csMask,u32 tempD) -{ - u32 temp, localTemp; - /* ASSERT(tempD < 32); */ - localTemp = 1; - temp = localTemp << tempD; - temp = ~temp; - csMask &= temp; - return csMask; -} - -/*----------------------------------------------------------------------------- - * u32 get_Bits(DCTStruct *DCTData, u8 DCT, u8 Node, u8 func, u16 offset, - * u8 low, u8 high) - * - * Description: - * This routine Gets the PCT bits from the specified Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT value = Value read from PCI space - *----------------------------------------------------------------------------- - */ -u32 get_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - 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 (is_fam15h()) - { - /* 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 - { - 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; -} - -/*----------------------------------------------------------------------------- - * void set_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func, u16 offset, - * u8 low, u8 high, u32 value) - * - * Description: - * This routine Sets the PCT bits from the specified Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT - *----------------------------------------------------------------------------- - */ -void set_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - 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 (is_fam15h()) - { - /* 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 - { - 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); - } - } - } -} - -/*------------------------------------------------- - * u32 get_ADD_DCT_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func, - * u16 offset,u8 low, u8 high) - * - * Description: - * This routine gets the Additional PCT register from Function 2 by specified - * Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - Additional PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT - *------------------------------------------------- - */ -u32 get_ADD_DCT_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high) -{ - u32 tempD; - tempD = offset; - tempD = bitTestReset(tempD,DctAccessWrite); - set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - PCI_MIN_LOW, PCI_MAX_HIGH, offset); - while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - DctAccessDone, DctAccessDone)) == 0); - return (get_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG, - low, high)); -} - -/*------------------------------------------------- - * void set_DCT_ADDR_Bits(DCTStruct *DCTData, u8 DCT,u8 Node,u8 func, - * u16 offset,u8 low, u8 high, u32 value) - * - * Description: - * This routine sets the Additional PCT register from Function 2 by specified - * Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - Additional PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT - *------------------------------------------------- - */ -void set_DCT_ADDR_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value) -{ - u32 tempD; - - set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - PCI_MIN_LOW, PCI_MAX_HIGH, offset); - while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - DctAccessDone, DctAccessDone)) == 0); - - set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG, - low, high, value); - tempD = offset; - tempD = bitTestSet(tempD,DctAccessWrite); - set_Bits(pDCTData, dct, node, FUN_DCT,DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - PCI_MIN_LOW, PCI_MAX_HIGH, tempD); - while ((get_Bits(pDCTData,dct, pDCTData->NodeId, FUN_DCT, - DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, DctAccessDone, - DctAccessDone)) == 0); -} - -/*------------------------------------------------- - * BOOL bitTest(u32 value, u8 bitLoc) - * - * Description: - * This routine tests the value to determine if the bitLoc is set - * - * Parameters: - * IN Value - value to be tested - * bitLoc - bit location to be tested - * OUT TRUE - bit is set - * FALSE - bit is clear - *------------------------------------------------- - */ -BOOL bitTest(u32 value, u8 bitLoc) -{ - u32 tempD, compD; - tempD = value; - compD = 0; - compD = bitTestSet(compD,bitLoc); - tempD &= compD; - if (compD == tempD) - { - return TRUE; - } - else - { - return FALSE; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h deleted file mode 100644 index aa0446f090..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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 - * 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. - */ -/* IBV defined Structure */ /* IBV Specific Options */ -#ifndef MWLC_D_H -#define MWLC_D_H - -#include <northbridge/amd/amdht/porting.h> - -#define MAX_TOTAL_DIMMS 8 /* Maximum Number of DIMMs in systems */ - /* (DCT0 + DCT1) */ -#define MAX_DIMMS 4 /* Maximum Number of DIMMs on each DCT */ -#define MAX_LDIMMS 4 /* Maximum number of Logical DIMMs per DCT */ - -/*MCT Max variables */ -#define MAX_ERRORS 32 /* Maximum number of Errors Reported */ -#define MAX_STATUS 32 /* Maximum number of Status variables*/ -#define MAX_BYTE_LANES (8+1) /* Maximum number of Byte Lanes - include ECC */ - -#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_LOAD_REDUCED 4 /* Load-Reduced DIMMs support */ -#define DCT_STATUS_OnDimmMirror 24 /* OnDimmMirror support */ - -/* PCI Definitions */ -#define FUN_HT 0 /* Function 0 Access */ -#define FUN_MAP 1 /* Function 1 Access */ -#define FUN_DCT 2 /* Function 2 Access */ -#define FUN_MISC 3 /* Function 3 Access */ -#define FUN_ADD_DCT 0xF /* Function 2 Additional Register Access */ -#define BOTH_DCTS 2 /* The access is independent of DCTs */ -#define PCI_MIN_LOW 0 /* Lowest possible PCI register location */ -#define PCI_MAX_HIGH 31 /* Highest possible PCI register location */ - -/*Function 2 */ -/* #define DRAM_INIT 0x7C */ -#define DRAM_MRS_REGISTER 0x84 -#define DRAM_CONFIG_HIGH 0x94 -#define DRAM_CONTROLLER_ADD_DATA_OFFSET_REG 0x98 -#define DRAM_CONTROLLER_ADD_DATA_PORT_REG 0x9C - -/*Function 2 Additional DRAM control registers */ -#define DRAM_ADD_DCT_PHY_CONTROL_REG 0x8 -#define DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 0x30 -#define DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45 0x40 -#define DRAM_CONT_ADD_PHASE_REC_CTRL_LOW 0x50 -#define DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH 0x51 -#define DRAM_CONT_ADD_ECC_PHASE_REC_CTRL 0x52 -#define DRAM_CONT_ADD_WRITE_LEV_ERROR_REG 0x53 - -/* CPU Register definitions */ - -/* Register Bit Location */ -#define DctAccessDone 31 -#define DctAccessWrite 30 -#define RDqsEn 12 -#define TrDimmSelStart 4 -#define TrDimmSelEnd 5 -#define WrLvTrMode 1 -#define TrNibbleSel 2 -#define WrLvOdtEn 12 -#define WrLvErrStart 0 -#define WrLvErrEnd 8 -#define SendMrsCmd 26 -#define Qoff 12 -#define MRS_Level 7 -#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 -#define DramTermDynEnd 11 -#define WrtLvTrMode 1 -#define TrNibbleSel 2 -#define TrDimmSelStart 4 -#define TrDimmSelEnd 5 -#define WrtLvTrEn 0 -#define DrvImpCtrlStart 2 -#define DrvImpCtrlEnd 3 -#define DramTermNbStart 7 -#define DramTermNbEnd 9 -#define onDimmMirror 3 - -typedef struct _sMCTStruct -{ - void (*AgesaDelay)(u32 delayval); /* IBV defined Delay Function */ -} __attribute__((packed, aligned(4))) sMCTStruct; - -/* DCT 0 and DCT 1 Data structure */ -typedef struct _sDCTStruct -{ - u8 NodeId; /* Node ID */ - u8 DctTrain; /* Current DCT being trained */ - u8 CurrDct; /* Current DCT number (0 or 1) */ - u8 DctCSPresent; /* Current DCT CS mapping */ - uint8_t WrDqsGrossDlyBaseOffset; - 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*/ - uint8_t WLSeedPreGrossPrevNibble[MAX_BYTE_LANES*MAX_LDIMMS]; - uint8_t WLSeedGrossPrevNibble[MAX_BYTE_LANES*MAX_LDIMMS]; - uint8_t WLSeedFinePrevNibble[MAX_BYTE_LANES*MAX_LDIMMS]; - /* 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[MAX_TOTAL_DIMMS]; - u16 RegMan1Present; - u8 DimmPresent[MAX_TOTAL_DIMMS];/* Indicates which DIMMs are present */ - /* from Total Number of DIMMs(per Node)*/ - u8 DimmX8Present[MAX_TOTAL_DIMMS]; /* Which DIMMs x8 devices */ - u8 Status[MAX_STATUS]; /* Status for DCT0 and 1 */ - u8 ErrCode[MAX_ERRORS]; /* Major Error codes for DCT0 and 1 */ - u8 ErrStatus[MAX_ERRORS]; /* Minor Error codes for DCT0 and 1 */ - u8 DimmValid[MAX_TOTAL_DIMMS]; /* Indicates which DIMMs are valid for */ - /* Total Number of DIMMs(per Node) */ - u8 WLTotalDelay[MAX_BYTE_LANES];/* Write Levelization Total Delay */ - /* per byte lane */ - u8 MaxDimmsInstalled; /* Max Dimms Installed for current DCT */ - u8 DimmRanks[MAX_TOTAL_DIMMS]; /* Total Number of Ranks(per Dimm) */ - uint64_t LogicalCPUID; - u8 WLPass; -} __attribute__((packed, aligned(4))) sDCTStruct; - -void set_DCT_ADDR_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value); -void AmdMemPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue); -u32 get_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high); -void AmdMemPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue); -u32 bitTestSet(u32 csMask,u32 tempD); -u32 bitTestReset(u32 csMask,u32 tempD); -void set_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value); -BOOL bitTest(u32 value, u8 bitLoc); -u32 RttNomNonTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank); -u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank); -u32 RttWrRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank); -u8 WrLvOdtRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm); -u32 get_ADD_DCT_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high); -void AmdMemPCIRead(SBDFO loc, u32 *Value); -void AmdMemPCIWrite(SBDFO loc, u32 *Value); - -#endif diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c deleted file mode 100644 index 52032e9362..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * 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. - */ - -#include <string.h> -#include <arch/cpu.h> -#include <arch/acpi.h> -#include <cpu/x86/msr.h> -#include <cpu/amd/msr.h> -#include <cpu/x86/mtrr.h> -#include <cpu/amd/mtrr.h> -#include <device/device.h> -#include <device/pci_def.h> -#include <device/pci_ops.h> -#include <console/console.h> -#include <cbfs.h> -#include <cbmem.h> -#include <spi-generic.h> -#include <spi_flash.h> -#include <pc80/mc146818rtc.h> -#include <stdint.h> -#include <types.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -#include "s3utils.h" - -#define S3NV_FILE_NAME "s3nv" - -static 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 ssize_t get_s3nv_file_offset(void); - -ssize_t get_s3nv_file_offset(void) -{ - struct region_device s3nv_region; - struct cbfsf s3nv_cbfs_file; - if (cbfs_boot_locate(&s3nv_cbfs_file, S3NV_FILE_NAME, NULL)) { - printk(BIOS_DEBUG, "S3 state file not found in CBFS: %s\n", S3NV_FILE_NAME); - return -1; - } - cbfs_file_data(&s3nv_region, &s3nv_cbfs_file); - - return s3nv_region.region.offset; -} - -#if ENV_PCI_SIMPLE_DEVICE -static uint32_t read_config32_dct(pci_devfn_t dev, uint8_t node, uint8_t dct, - uint32_t reg) -#else -static uint32_t read_config32_dct(struct device *dev, uint8_t node, uint8_t dct, - uint32_t reg) -#endif -{ - if (is_fam15h()) { - uint32_t dword; -#if ENV_PCI_SIMPLE_DEVICE - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); -#else - struct device *dev_fn1 = pcidev_on_root(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); -} - -#if ENV_PCI_SIMPLE_DEVICE -static void write_config32_dct(pci_devfn_t dev, uint8_t node, uint8_t dct, - uint32_t reg, uint32_t value) -#else -static void write_config32_dct(struct device *dev, uint8_t node, uint8_t dct, - uint32_t reg, uint32_t value) -#endif -{ - if (is_fam15h()) { - uint32_t dword; -#if ENV_PCI_SIMPLE_DEVICE - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); -#else - struct device *dev_fn1 = pcidev_on_root(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; - } - - pci_write_config32(dev, reg, value); -} - -#if ENV_PCI_SIMPLE_DEVICE -static uint32_t read_amd_dct_index_register(pci_devfn_t dev, - uint32_t index_ctl_reg, uint32_t index) -#else -static uint32_t read_amd_dct_index_register(struct device *dev, - uint32_t index_ctl_reg, uint32_t index) -#endif -{ - uint32_t dword; - - index &= ~(1 << 30); - pci_write_config32(dev, index_ctl_reg, index); - do { - dword = pci_read_config32(dev, index_ctl_reg); - } while (!(dword & (1 << 31))); - dword = pci_read_config32(dev, index_ctl_reg + 0x04); - - return dword; -} - -#if ENV_PCI_SIMPLE_DEVICE -static uint32_t read_amd_dct_index_register_dct(pci_devfn_t dev, uint8_t node, - uint8_t dct, uint32_t index_ctl_reg, uint32_t index) -#else -static uint32_t read_amd_dct_index_register_dct(struct device *dev, - uint8_t node, uint8_t dct, uint32_t index_ctl_reg, - uint32_t index) -#endif -{ - if (is_fam15h()) { - uint32_t dword; -#if ENV_PCI_SIMPLE_DEVICE - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); -#else - struct device *dev_fn1 = pcidev_on_root(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); -} - -/* Non-cryptographic 64-bit hash function taken from Stack Overflow: - * http://stackoverflow.com/a/13326345 - * Any 64-bit hash with sufficiently low collision potential - * could be used instead. - */ -void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash) -{ - const unsigned long long prime = 2654435789ULL; - uint16_t byte; - *spd_hash = 104395301; - - for (byte = 0; byte < 256; byte++) - *spd_hash += (spd_data[byte] * prime) ^ (*spd_hash >> 23); - - *spd_hash = *spd_hash ^ (*spd_hash << 37); -} - -uint16_t calculate_nvram_mct_hash(void) -{ - uint32_t nvram; - uint16_t ret; - - ret = 0; - if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS) - ret |= nvram & 0xf; - if (get_option(&nvram, "minimum_memory_voltage") == CB_SUCCESS) - ret |= (nvram & 0x3) << 4; - if (get_option(&nvram, "ECC_memory") == CB_SUCCESS) - ret |= (nvram & 0x1) << 6; - if (get_option(&nvram, "ECC_redirection") == CB_SUCCESS) - ret |= (nvram & 0x1) << 7; - if (get_option(&nvram, "ecc_scrub_rate") == CB_SUCCESS) - ret |= (nvram & 0x1) << 8; - if (get_option(&nvram, "interleave_chip_selects") == CB_SUCCESS) - ret |= (nvram & 0x1) << 9; - if (get_option(&nvram, "interleave_nodes") == CB_SUCCESS) - ret |= (nvram & 0x1) << 10; - if (get_option(&nvram, "interleave_memory_channels") == CB_SUCCESS) - ret |= (nvram & 0x1) << 11; - if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS) - ret |= (nvram & 0x1) << 12; - if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) - ret |= (nvram & 0x1) << 13; - - return ret; -} - -static struct amd_s3_persistent_data *map_s3nv_in_nvram(void) -{ - ssize_t s3nv_offset; - ssize_t s3nv_file_offset; - void *s3nv_cbfs_file_ptr; - struct amd_s3_persistent_data *persistent_data; - - /* Obtain CBFS file offset */ - s3nv_offset = get_s3nv_file_offset(); - if (s3nv_offset == -1) - return NULL; - - /* Align flash pointer to nearest boundary */ - s3nv_file_offset = s3nv_offset; - s3nv_offset &= ~(CONFIG_S3_DATA_SIZE-1); - s3nv_offset += CONFIG_S3_DATA_SIZE; - s3nv_file_offset = s3nv_offset - s3nv_file_offset; - - /* Map data structure in CBFS and restore settings */ - s3nv_cbfs_file_ptr = cbfs_boot_map_with_leak(S3NV_FILE_NAME, CBFS_TYPE_RAW, NULL); - if (!s3nv_cbfs_file_ptr) { - printk(BIOS_DEBUG, "S3 state file could not be mapped: %s\n", S3NV_FILE_NAME); - return NULL; - } - persistent_data = (s3nv_cbfs_file_ptr + s3nv_file_offset); - - return persistent_data; -} - -int8_t load_spd_hashes_from_nvram(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - struct amd_s3_persistent_data *persistent_data; - - persistent_data = map_s3nv_in_nvram(); - if (!persistent_data) - return -1; - - memcpy(pDCTstat->spd_data.nvram_spd_hash, persistent_data->node[pDCTstat->Node_ID].spd_hash, sizeof(pDCTstat->spd_data.nvram_spd_hash)); - memcpy(pDCTstat->spd_data.nvram_memclk, persistent_data->node[pDCTstat->Node_ID].memclk, sizeof(pDCTstat->spd_data.nvram_memclk)); - - pMCTstat->nvram_checksum = persistent_data->nvram_checksum; - - return 0; -} - -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 void wrmsr_uint64_t(unsigned long index, uint64_t value) -{ - msr_t msr; - msr.hi = (value & 0xffffffff00000000ULL) >> 32; - msr.lo = (value & 0xffffffff); - wrmsr(index, msr); -} - -static uint32_t read_config32_dct_nbpstate(struct device *dev, uint8_t node, - uint8_t dct, uint8_t nb_pstate, - uint32_t reg) -{ - uint32_t dword; - struct device *dev_fn1 = pcidev_on_root(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); -} - -static void copy_cbmem_spd_data_to_save_variable(struct amd_s3_persistent_data *persistent_data, uint8_t *restored) -{ - uint8_t node; - uint8_t dimm; - uint8_t channel; - struct amdmct_memory_info *mem_info; - mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO); - if (mem_info == NULL) { - /* can't find amdmct information in cbmem */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) - persistent_data->node[node].spd_hash[dimm] = 0xffffffffffffffffULL; - - return; - } - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) - calculate_spd_hash(mem_info->dct_stat[node].spd_data.spd_bytes[dimm], &persistent_data->node[node].spd_hash[dimm]); - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - for (channel = 0; channel < 2; channel++) - persistent_data->node[node].memclk[channel] = mem_info->dct_stat[node].Speed; - - persistent_data->nvram_checksum = calculate_nvram_mct_hash(); - - if (restored) { - if (mem_info->mct_stat.GStatus & (1 << GSB_ConfigRestored)) - *restored = 1; - else - *restored = 0; - } -} - -void copy_mct_data_to_save_variable(struct amd_s3_persistent_data *persistent_data) -{ - uint8_t i; - uint8_t j; - uint8_t node; - uint8_t channel; - - /* Zero out data structure */ - memset(persistent_data, 0, sizeof(struct amd_s3_persistent_data)); - - /* Load data from DCTs into data structure */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - struct device *dev_fn1 = pcidev_on_root(0x18 + node, 1); - struct device *dev_fn2 = pcidev_on_root(0x18 + node, 2); - struct device *dev_fn3 = pcidev_on_root(0x18 + node, 3); - /* Test for node presence */ - if ((!dev_fn1) || (pci_read_config32(dev_fn1, PCI_VENDOR_ID) == 0xffffffff)) { - persistent_data->node[node].node_present = 0; - continue; - } - persistent_data->node[node].node_present = 1; - - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - - /* Stage 1 */ - data->f2x110 = pci_read_config32(dev_fn2, 0x110); - - /* Stage 2 */ - 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); - data->f2x10c = pci_read_config32(dev_fn2, 0x10c); - data->f2x114 = pci_read_config32(dev_fn2, 0x114); - data->f2x118 = pci_read_config32(dev_fn2, 0x118); - data->f2x11c = pci_read_config32(dev_fn2, 0x11c); - data->f2x1b0 = pci_read_config32(dev_fn2, 0x1b0); - data->f3x44 = pci_read_config32(dev_fn3, 0x44); - for (i = 0; i < 16; i++) { - data->msr0000020[i] = - rdmsr_uint64_t(MTRR_PHYS_BASE(0) | i); - } - data->msr00000250 = rdmsr_uint64_t(MTRR_FIX_64K_00000); - data->msr00000258 = rdmsr_uint64_t(MTRR_FIX_16K_80000); - for (i = 0; i < 8; i++) - data->msr0000026[i] = rdmsr_uint64_t(0x00000260 | (i + 8)); - data->msr000002ff = rdmsr_uint64_t(MTRR_DEF_TYPE_MSR); - data->msrc0010010 = rdmsr_uint64_t(SYSCFG_MSR); - data->msrc001001a = rdmsr_uint64_t(TOP_MEM); - data->msrc001001d = rdmsr_uint64_t(TOP_MEM2); - data->msrc001001f = rdmsr_uint64_t(NB_CFG_MSR); - - /* Stage 3 */ - 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); - - if (channel == 1) - data->f2x9cx0d0fe00a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe00a); - } - - /* Stage 4 */ - 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_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_dct(dev_fn2, node, channel, 0x98, 0x04); - - /* Stage 9 */ - 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_dct(dev_fn2, node, channel, 0x98, 0x10 + i); - for (i = 0; i < 12; 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_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_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_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_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_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_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 (CONFIG(DIMM_DDR3)) { - for (i = 0; i < 12; 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_dct(dev_fn2, node, channel, 0x98, 0x40 + i); - } - - /* Other */ - /* ECC scrub rate control */ - data->f3x58 = read_config32_dct(dev_fn3, node, 0, 0x58); - - /* ECC scrub location */ - write_config32_dct(dev_fn3, node, 0, 0x58, 0x0); /* Disable sequential scrub to work around non-atomic location read */ - data->f3x5c = read_config32_dct(dev_fn3, node, 0, 0x5c); - data->f3x60 = read_config32_dct(dev_fn3, node, 0, 0x60); - write_config32_dct(dev_fn3, node, 0, 0x58, data->f3x58); /* Re-enable sequential scrub */ - } - } -} - -static void write_config32_dct_nbpstate(pci_devfn_t dev, uint8_t node, - uint8_t dct, uint8_t nb_pstate, - uint32_t reg, uint32_t value) -{ - uint32_t dword; - pci_devfn_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(pci_devfn_t dev, - uint32_t index_ctl_reg, uint32_t index, - uint32_t value) -{ - uint32_t dword; - - pci_write_config32(dev, index_ctl_reg + 0x04, value); - index |= (1 << 30); - pci_write_config32(dev, index_ctl_reg, index); - do { - dword = pci_read_config32(dev, index_ctl_reg); - } while (!(dword & (1 << 31))); -} - -static void write_amd_dct_index_register_dct(pci_devfn_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; - pci_devfn_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); -} - -void restore_mct_data_from_save_variable(struct amd_s3_persistent_data *persistent_data, uint8_t training_only) -{ - uint8_t i; - uint8_t j; - uint8_t node; - uint8_t channel; - uint8_t ganged; - uint8_t dct_enabled; - uint32_t dword; - - if (training_only) { - /* Only restore the Receiver Enable and DQS training registers */ - 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; - - /* Restore training parameters */ - for (i = 0; i < 4; i++) - for (j = 0; j < 3; 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_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x05 + i) + (0x100 * j), data->f2x9cx3_0_0_7_5[i][j]); - - for (i = 0; i < 12; 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_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x20 + i, data->f2x9cx20[i]); - - if (CONFIG(DIMM_DDR3)) { - for (i = 0; i < 12; 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_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x40 + i, data->f2x9cx40[i]); - } - - /* Restore MaxRdLatency */ - if (is_fam15h()) { - for (i = 0; i < 4; i++) - write_config32_dct_nbpstate(PCI_DEV(0, 0x18 + node, 2), node, channel, i, 0x210, data->f2x210[i]); - } else { - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x78, data->f2x78); - } - - /* Other timing control registers */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x8c, data->f2x8c); - } - } - - return; - } - - /* Load data from data structure into DCTs */ - /* Stage 1 */ - 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; - - pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x110, data->f2x110); - } - } - - /* Stage 2 */ - 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; - - 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); - if (is_fam15h()) - /* Do not set LockDramCfg or CC6SaveEn at this time */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x118, data->f2x118 & ~(0x3 << 18)); - else - 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(MTRR_PHYS_BASE(0) | i, - data->msr0000020[i]); - } - wrmsr_uint64_t(MTRR_FIX_64K_00000, data->msr00000250); - wrmsr_uint64_t(MTRR_FIX_16K_80000, data->msr00000258); - /* FIXME - * Restoring these MSRs causes a hang on resume due to - * destroying CAR while still executing from CAR! - * For now, skip restoration... - */ - // for (i = 0; i < 8; i++) - // wrmsr_uint64_t(0x00000260 | (i + 8), data->msr0000026[i]); - wrmsr_uint64_t(MTRR_DEF_TYPE_MSR, data->msr000002ff); - wrmsr_uint64_t(SYSCFG_MSR, data->msrc0010010); - wrmsr_uint64_t(TOP_MEM, data->msrc001001a); - wrmsr_uint64_t(TOP_MEM2, data->msrc001001d); - wrmsr_uint64_t(NB_CFG_MSR, data->msrc001001f); - } - } - - /* Stage 3 */ - 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; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - 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); - - if (channel == 1) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe00a, data->f2x9cx0d0fe00a); - } - } - } - - /* Stage 4 */ - 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; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - 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 Address/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 */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94, data->f2x94); - } - } - - /* Stage 5 */ - 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; - - 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_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++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - for (i = 0; i < 9; i++) - for (j = 0; j < 3; j++) - 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); - } - } - } - - /* Stage 7 */ - 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; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - if (!is_fam15h()) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x04, data->f2x9cx04); - } - } - - /* Stage 8 */ - 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; - - dct_enabled = !(data->f2x94 & (1 << 14)); - if (!dct_enabled) - continue; - - 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 = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90); - dword |= (1 << 1); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90, dword); - } - } - - /* Stage 9 */ - 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; - - dct_enabled = !(data->f2x94 & (1 << 14)); - if (!dct_enabled) - continue; - - printk(BIOS_SPEW, "Waiting for DIMMs to exit self refresh node: %d channel: %d\n", node, channel); - - /* Wait for transition from self refresh mode to complete */ - do { - dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90); - } while (dword & (1 << 1)); - - /* Restore registers */ - 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); - } - } - - /* Stage 10 */ - 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; - - for (i = 0; i < 12; 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_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_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_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_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_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_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_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); - } - } - - /* Stage 11 */ - if (CONFIG(DIMM_DDR3)) { - 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; - - for (i = 0; i < 12; 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_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x40 + i, data->f2x9cx40[i]); - } - } - } - - /* Other */ - 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; - - /* ECC scrub location */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, 0, 0x5c, data->f3x5c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, 0, 0x60, data->f3x60); - - /* ECC scrub rate control */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, 0, 0x58, data->f3x58); - - if (is_fam15h()) - /* Set LockDramCfg and CC6SaveEn */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x118, data->f2x118); - } - } -} - -int8_t save_mct_information_to_nvram(void) -{ - uint8_t nvram; - uint8_t restored = 0; - - if (acpi_is_wakeup_s3()) - return 0; - - printk(BIOS_DEBUG, "Writing AMD DCT configuration to Flash\n"); - - struct spi_flash flash; - ssize_t s3nv_offset; - struct amd_s3_persistent_data *persistent_data; - - /* Allocate temporary data structures */ - persistent_data = malloc(sizeof(struct amd_s3_persistent_data)); - if (!persistent_data) { - printk(BIOS_DEBUG, "Could not allocate S3 data structure in RAM\n"); - return -1; - } - - /* Obtain MCT configuration data */ - copy_mct_data_to_save_variable(persistent_data); - - /* Save RAM SPD data at the same time */ - copy_cbmem_spd_data_to_save_variable(persistent_data, &restored); - - if (restored) { - /* Allow training bypass if DIMM configuration is unchanged on next boot */ - nvram = 1; - set_option("allow_spd_nvram_cache_restore", &nvram); - - printk(BIOS_DEBUG, "Hardware configuration unchanged since last boot; skipping write\n"); - free(persistent_data); - return 0; - } - - /* Obtain CBFS file offset */ - s3nv_offset = get_s3nv_file_offset(); - if (s3nv_offset == -1) { - free(persistent_data); - return -1; - } - - /* Align flash pointer to nearest boundary */ - s3nv_offset &= ~(CONFIG_S3_DATA_SIZE-1); - s3nv_offset += CONFIG_S3_DATA_SIZE; - - /* Initialize SPI and detect devices */ - spi_init(); - if (spi_flash_probe(0, 0, &flash)) { - printk(BIOS_DEBUG, "Could not find SPI device\n"); - return -1; - } - - spi_flash_volatile_group_begin(&flash); - - /* Erase and write data structure */ - spi_flash_erase(&flash, s3nv_offset, CONFIG_S3_DATA_SIZE); - spi_flash_write(&flash, s3nv_offset, - sizeof(struct amd_s3_persistent_data), persistent_data); - - /* Deallocate temporary data structures */ - free(persistent_data); - - spi_flash_volatile_group_end(&flash); - - /* Allow training bypass if DIMM configuration is unchanged on next boot */ - nvram = 1; - set_option("allow_spd_nvram_cache_restore", &nvram); - - return 0; -} - -int8_t restore_mct_information_from_nvram(uint8_t training_only) -{ - struct amd_s3_persistent_data *persistent_data; - - persistent_data = map_s3nv_in_nvram(); - if (!persistent_data) - return -1; - - restore_mct_data_from_save_variable(persistent_data, training_only); - - return 0; -} - -void calculate_and_store_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint8_t dimm; - - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - calculate_spd_hash(pDCTstat->spd_data.spd_bytes[dimm], &pDCTstat->spd_data.spd_hash[dimm]); - } -} - -void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint8_t dimm; - - pDCTstat->spd_data.nvram_spd_match = 1; - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - if (pDCTstat->spd_data.spd_hash[dimm] != pDCTstat->spd_data.nvram_spd_hash[dimm]) - pDCTstat->spd_data.nvram_spd_match = 0; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h deleted file mode 100644 index d13cb23c80..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ -#ifndef S3UTILS_H -#define S3UTILS_H - -#include "../wrappers/mcti.h" -#include "mct_d.h" - -#ifdef __RAMSTAGE__ -int8_t save_mct_information_to_nvram(void); -void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_data); -#endif - -void calculate_and_store_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); - -#endif |