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/mct_d.c | |
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/mct_d.c')
-rw-r--r-- | src/northbridge/amd/amdmct/mct/mct_d.c | 3980 |
1 files changed, 0 insertions, 3980 deletions
diff --git a/src/northbridge/amd/amdmct/mct/mct_d.c b/src/northbridge/amd/amdmct/mct/mct_d.c deleted file mode 100644 index 60a2c66de3..0000000000 --- a/src/northbridge/amd/amdmct/mct/mct_d.c +++ /dev/null @@ -1,3980 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015-2017 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering - * Copyright (C) 2007-2008 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 2 */ - - -/* 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. - * Instead Trc (course) is rounded up to nearest 1 ns. - * - * Mini and Micro DIMM not supported. Only RDIMM, UDIMM, SO-DIMM defined types - * supported. - */ - -#include <string.h> -#include <console/console.h> -#include <cpu/amd/msr.h> -#include <device/pci_ops.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); -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -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 u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_PlatformSpec(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 u8 Get_DefTrc_k_D(u8 k); -static u16 Get_40Tk_D(u8 k); -static u16 Get_Fk_D(u8 k); -static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat, u8 i, u8 j, u8 k); -static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, int j, int k); -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i); -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 u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg, u32 index); -static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - u32 dev, u32 index_reg); -static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg); -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, u32 index_reg, u32 index); -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 SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u32 mct_NodePresent_D(void); -static void WaitRoutine_D(u32 time); -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); -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -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); - -/*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 Table_T_k[] = {0x00,0x50,0x3D,0x30,0x25, 0x18 }; -static const u8 Table_CL2_j[] = {0x04,0x08,0x10,0x20,0x40, 0x80 }; -static const u8 Tab_defTrc_k[] = {0x0,0x41,0x3C,0x3C,0x3A, 0x3A }; -static const u16 Tab_40T_k[] = {00,200,150,120,100,75 }; -static const u8 Tab_BankAddr[] = {0x0,0x08,0x09,0x10,0x0C,0x0D,0x11,0x0E,0x15,0x16,0x0F,0x17}; -static const u8 Tab_tCL_j[] = {0,2,3,4,5}; -static const u8 Tab_1KTfawT_k[] = {00,8,10,13,14,20}; -static const u8 Tab_2KTfawT_k[] = {00,10,14,17,18,24}; -static const u8 Tab_L1CLKDis[] = {8,8,6,4,2,0,8,8}; -static const u8 Tab_M2CLKDis[] = {2,0,8,8,2,0,2,0}; -static const u8 Tab_S1CLKDis[] = {8,0,8,8,8,0,8,0}; -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}; - -const u8 Table_DQSRcvEn_Offset[] = {0x00,0x01,0x10,0x11,0x2}; - -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. - * - * Run-Time Requirements: - * 1. Complete Hypertransport Bus Configuration - * 2. SMBus Controller Initialized - * 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: - * 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 - */ - u8 Node, NodesWmem; - u32 node_sys_base; - -restartinit: - mctInitMemGPIOs_A_D(); /* Set any required GPIOs*/ - NodesWmem = 0; - node_sys_base = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - 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->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; - } - - print_tx("mctAutoInitMCT_D: mct_init Node ", Node); - mct_init(pMCTstat, pDCTstat); - mctNodeIDDebugPort_D(); - pDCTstat->NodePresent = NodePresent_D(Node); - if (pDCTstat->NodePresent) { /* See if Node is there*/ - print_t("mctAutoInitMCT_D: clear_legacy_Mode\n"); - clear_legacy_Mode(pMCTstat, pDCTstat); - pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node); - - print_t("mctAutoInitMCT_D: mct_InitialMCT_D\n"); - mct_InitialMCT_D(pMCTstat, pDCTstat); - - print_t("mctAutoInitMCT_D: mctSMBhub_Init\n"); - mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/ - - print_t("mctAutoInitMCT_D: mct_initDCT\n"); - mct_initDCT(pMCTstat, pDCTstat); - if (pDCTstat->ErrCode == SC_FatalErr) { - goto fatalexit; /* any fatal errors?*/ - } else if (pDCTstat->ErrCode < SC_StopError) { - NodesWmem++; - } - } /* if Node present */ - node_sys_base = pDCTstat->NodeSysBase; - node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F; - } - if (NodesWmem == 0) { - printk(BIOS_DEBUG, "No Nodes?!\n"); - goto fatalexit; - } - - print_t("mctAutoInitMCT_D: SyncDCTsReady_D\n"); - SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/ - - print_t("mctAutoInitMCT_D: HTMemMapInit_D\n"); - HTMemMapInit_D(pMCTstat, pDCTstatA); /* Map local memory into system address space.*/ - mctHookAfterHTMap(); - - print_t("mctAutoInitMCT_D: CPUMemTyping_D\n"); - CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */ - mctHookAfterCPU(); /* Setup external northbridge(s) */ - - print_t("mctAutoInitMCT_D: DQSTiming_D\n"); - DQSTiming_D(pMCTstat, pDCTstatA); /* Get Receiver Enable and DQS signal timing*/ - - print_t("mctAutoInitMCT_D: UMAMemTyping_D\n"); - UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */ - - print_t("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); - - print_t("mctAutoInitMCT_D: ECCInit_D\n"); - if (ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/ - print_t("mctAutoInitMCT_D: MCTMemClr_D\n"); - MCTMemClr_D(pMCTstat,pDCTstatA); - } - - mct_FinalMCT_D(pMCTstat, (pDCTstatA + 0)); // Node 0 - print_tx("mctAutoInitMCT_D Done: Global Status: ", pMCTstat->GStatus); - return; - -fatalexit: - die("mct_d: fatalexit"); -} - - -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; -} - - -static void DQSTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 nv_DQSTrainCTL; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - return; - } - nv_DQSTrainCTL = mctGet_NVbits(NV_DQSTrainCTL); - /* FIXME: BOZO- DQS training every time*/ - nv_DQSTrainCTL = 1; - - print_t("DQSTiming_D: mct_BeforeDQSTrain_D:\n"); - mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA); - phyAssistedMemFnceTraining(pMCTstat, pDCTstatA); - - if (nv_DQSTrainCTL) { - mctHookBeforeAnyTraining(pMCTstat, pDCTstatA); - - print_t("DQSTiming_D: TrainReceiverEn_D FirstPass:\n"); - TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); - - print_t("DQSTiming_D: mct_TrainDQSPos_D\n"); - mct_TrainDQSPos_D(pMCTstat, pDCTstatA); - - // Second Pass never used for Barcelona! - //print_t("DQSTiming_D: TrainReceiverEn_D SecondPass:\n"); - //TrainReceiverEn_D(pMCTstat, pDCTstatA, SecondPass); - - print_t("DQSTiming_D: mctSetEccDQSRcvrEn_D\n"); - mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA); - - print_t("DQSTiming_D: TrainMaxReadLatency_D\n"); -//FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); - mctHookAfterAnyTraining(); - mctSaveDQSSigTmg_D(); - - print_t("DQSTiming_D: mct_EndDQSTraining_D\n"); - mct_EndDQSTraining_D(pMCTstat, pDCTstatA); - - print_t("DQSTiming_D: MCTMemClr_D\n"); - MCTMemClr_D(pMCTstat, pDCTstatA); - } else { - mctGetDQSSigTmg_D(); /* get values into data structure */ - LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA); /* load values into registers.*/ - //mctDoWarmResetMemClr_D(); - MCTMemClr_D(pMCTstat, pDCTstatA); - } -} - - -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; - - - 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 + Channel * 0x100; - 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 ? */ - - } - } - for (Channel = 0; Channel < 2; Channel++) { - SetEccDQSRcvrEn_D(pDCTstat, Channel); - } - - for (Channel = 0; Channel < 2; Channel++) { - u8 *p; - index_reg = 0x98 + Channel * 0x100; - - /* 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 < 2; DIMM++) { - if (DIMM == 0) { - index = 0; /* CHA Write Data Timing Low */ - } else { - if (pDCTstat->Speed >= 4) { - index = 0x100 * DIMM; - } else { - break; - } - } - for (Dir = 0; Dir < 2; Dir++) {//RD/WR - p = pDCTstat->persistentData.CH_D_DIR_B_DQS[Channel][DIMM][Dir]; - val = stream_to_int(p); /* CHA Read Data Timing High */ - Set_NB32_index_wait(dev, index_reg, index+1, val); - val = stream_to_int(p+4); /* CHA Write Data Timing High */ - Set_NB32_index_wait(dev, index_reg, index+2, val); - val = *(p+8); /* CHA Write ECC Timing */ - Set_NB32_index_wait(dev, index_reg, index+3, val); - index += 4; - } - } - } - - for (Channel = 0; Channel < 2; Channel++) { - reg = 0x78 + Channel * 0x100; - val = Get_NB32(dev, reg); - val &= ~(0x3ff<<22); - val |= ((u32) pDCTstat->CH_MaxRdLat[Channel] << 22); - val &= ~(1 << DqsRcvEnTrain); - Set_NB32(dev, reg, val); /* program MaxRdLatency to correspond with current delay*/ - } - } - } -} - -#ifdef UNUSED_CODE -static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Clear MC4_STS for all Nodes in the system. This is required in some - * circumstances to clear left over garbage from cold reset, shutdown, - * or normal ECC memory conditioning. - */ - - //FIXME: this function depends on pDCTstat Array (with Node id) - Is this really a problem? - - u32 dev; - u8 Node; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - dev = pDCTstat->dev_nbmisc; - /*MCA NB Status Low (alias to MC4_STS[31:0] */ - Set_NB32(dev, 0x48, 0); - /* MCA NB Status High (alias to MC4_STS[63:32] */ - Set_NB32(dev, 0x4C, 0); - } - } -} -#endif - -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 */ - - /* if Node limit > 1GB then set it to 1GB boundary for each node */ - if ((mctSetNodeBoundary_D()) && (limit > 0x00400000)) { - limit++; - limit &= 0xFFC00000; - limit--; - } - val = limit & 0xFFFF0000; - val |= Node; - Set_NB32(dev, 0x44 + (Node << 3), val); /* set DstNode */ - - limit = pDCTstat->DCTSysLimit; - if (limit) { - NextBase = (limit & 0xFFFF0000) + 0x10000; - if ((mctSetNodeBoundary_D()) && (NextBase > 0x00400000)) { - NextBase++; - NextBase &= 0xFFC00000; - NextBase--; - } - } - } - - /* 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; - 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); - } - } - } -} - - -void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u32 dev; - u32 reg; - - /* Initiates a memory clear operation on one node */ - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - reg = 0x110; - - do { - val = Get_NB32(dev, reg); - } while (val & (1 << MemClrBusy)); - - val |= (1 << MemClrInit); - Set_NB32(dev, reg, val); - - } -} - - -void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Ensures that memory clear has completed on all node.*/ - u8 Node; - struct DCTStatStruc *pDCTstat; - - if (!mctGet_NVbits(NV_DQSTrainCTL)) { - // callback to wrapper: mctDoWarmResetMemClr_D - } else { // NV_DQSTrainCTL == 1 - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Sync_D(pMCTstat, pDCTstat); - } - } - } -} - - -static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u32 dev = pDCTstat->dev_dct; - u32 reg; - - /* Ensure that a memory clear operation has completed on one node */ - if (pDCTstat->DCTSysLimit) { - reg = 0x110; - - do { - val = Get_NB32(dev, reg); - } while (val & (1 << MemClrBusy)); - - do { - val = Get_NB32(dev, reg); - } while (!(val & (1 << Dr_MemClrStatus))); - } - - /* Implement BKDG Rev 3.62 recommendations */ - val = 0x0FE40F80; - if (!(mctGetLogicalCPUID(0) & AMD_FAM10_LT_D) && mctGet_NVbits(NV_Unganged)) - val |= (0x18 << 2); - else - val |= (0x10 << 2); - val |= MCCH_FlushWrOnStpGnt; // Set for S3 - Set_NB32(dev, 0x11C, val); -} - - -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 DCTInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* - * Initialize DRAM on single Athlon 64/Opteron Node. - */ - - u8 stopDCTflag; - u32 val; - - ClearDCT_D(pMCTstat, pDCTstat, dct); - stopDCTflag = 1; /*preload flag with 'disable' */ - if (mct_DIMMPresence(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: mct_DIMMPresence Done\n"); - if (mct_SPDCalcWidth(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: mct_SPDCalcWidth Done\n"); - if (AutoCycTiming_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: AutoCycTiming_D Done\n"); - if (AutoConfig_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: AutoConfig_D Done\n"); - if (PlatformSpec_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: PlatformSpec_D Done\n"); - stopDCTflag = 0; - if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) { - print_t("\t\tDCTInit_D: StartupDCT_D\n"); - StartupDCT_D(pMCTstat, pDCTstat, dct); /*yeaahhh! */ - } - } - } - } - } - } - if (stopDCTflag) { - u32 reg_off = dct * 0x100; - val = 1<<DisDramInterface; - Set_NB32(pDCTstat->dev_dct, reg_off+0x94, val); - /*To maximize power savings when DisDramInterface = 1b, - all of the MemClkDis bits should also be set.*/ - val = 0xFF000000; - Set_NB32(pDCTstat->dev_dct, reg_off+0x88, val); - } 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; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - mct_SyncDCTsReady(pDCTstat); - } -} - - -static 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; - u8 byte; - u32 reg; - u32 reg_off = dct * 0x100; - - dev = pDCTstat->dev_dct; - val = Get_NB32(dev, 0x94 + reg_off); - if (val & (1 << MemClkFreqVal)) { - print_t("\t\t\tStartupDCT_D: MemClkFreqVal\n"); - byte = mctGet_NVbits(NV_DQSTrainCTL); - if (byte == 1) { - /* Enable DQSRcvEn training mode */ - print_t("\t\t\tStartupDCT_D: DqsRcvEnTrain set\n"); - reg = 0x78 + reg_off; - val = Get_NB32(dev, reg); - /* Setting this bit forces a 1T window with hard left - * pass/fail edge and a probabilistic right pass/fail - * edge. LEFT edge is referenced for final - * receiver enable position.*/ - val |= 1 << DqsRcvEnTrain; - Set_NB32(dev, reg, val); - } - mctHookBeforeDramInit(); /* generalized Hook */ - print_t("\t\t\tStartupDCT_D: DramInit\n"); - 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 + 0x100 * dct; - u32 val = 0; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - reg_end = 0x78 + 0x100 * dct; - } else { - reg_end = 0xA4 + 0x100 * dct; - } - - while (reg < reg_end) { - Set_NB32(dev, reg, val); - reg += 4; - } - - val = 0; - dev = pDCTstat->dev_map; - reg = 0xF0; - Set_NB32(dev, reg, val); -} - - -static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 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'. - */ - - u8 i; - u8 Twr, Trtp; - u8 Trp, Trrd, Trcd, Tras, Trc, Trfc[4], Rows; - u32 DramTimingLo, DramTimingHi; - u16 Tk40; - u8 Twtr; - u8 LDIMM; - u8 DDR2_1066; - u8 byte; - u32 dword; - u32 dev; - u32 reg; - u32 reg_off; - u32 val; - u16 smbaddr; - - /* 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; - - /* if "manual" memclock mode */ - if (mctGet_NVbits(NV_MCTUSRTMGMODE) == 2) - pDCTstat->Speed = mctGet_NVbits(NV_MemCkVal) + 1; - - } - mct_AfterGetCLT(pMCTstat, pDCTstat, dct); - - /* Gather all DIMM mini-max values for cycle timing data */ - Rows = 0; - Trp = 0; - Trrd = 0; - Trcd = 0; - Trtp = 0; - Tras = 0; - Trc = 0; - Twr = 0; - Twtr = 0; - for (i = 0; i < 4; i++) - Trfc[i] = 0; - - for (i = 0; i< MAX_DIMMS_SUPPORTED; i++) { - LDIMM = i >> 1; - if (pDCTstat->DIMMValid & (1 << i)) { - smbaddr = Get_DIMMAddress_D(pDCTstat, dct + i); - byte = mctRead_SPD(smbaddr, SPD_ROWSZ); - if (Rows < byte) - Rows = byte; /* keep track of largest row sz */ - - byte = mctRead_SPD(smbaddr, SPD_TRP); - if (Trp < byte) - Trp = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRRD); - if (Trrd < byte) - Trrd = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRCD); - if (Trcd < byte) - Trcd = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRTP); - if (Trtp < byte) - Trtp = byte; - - byte = mctRead_SPD(smbaddr, SPD_TWR); - if (Twr < byte) - Twr = byte; - - byte = mctRead_SPD(smbaddr, SPD_TWTR); - if (Twtr < byte) - Twtr = byte; - - val = mctRead_SPD(smbaddr, SPD_TRC); - if ((val == 0) || (val == 0xFF)) { - pDCTstat->ErrStatus |= 1<<SB_NoTrcTrfc; - pDCTstat->ErrCode = SC_VarianceErr; - val = Get_DefTrc_k_D(pDCTstat->Speed); - } else { - byte = mctRead_SPD(smbaddr, SPD_TRCRFC); - if (byte & 0xF0) { - val++; /* round up in case fractional extension is non-zero.*/ - } - } - if (Trc < val) - Trc = val; - - /* dev density = rank size/#devs per rank */ - byte = mctRead_SPD(smbaddr, SPD_BANKSZ); - - val = ((byte >> 5) | (byte << 3)) & 0xFF; - val <<= 2; - - byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE; /* dev density = 2^(rows+columns+banks) */ - if (byte == 4) { - val >>= 4; - } else if (byte == 8) { - val >>= 3; - } else if (byte == 16) { - val >>= 2; - } - - byte = bsr(val); - - if (Trfc[LDIMM] < byte) - Trfc[LDIMM] = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRAS); - if (Tras < byte) - Tras = byte; - } /* Dimm Present */ - } - - /* Convert DRAM CycleTiming values and store into DCT structure */ - DDR2_1066 = 0; - byte = pDCTstat->Speed; - if (byte == 5) - DDR2_1066 = 1; - Tk40 = Get_40Tk_D(byte); - - /* Notes: - 1. All secondary time values given in SPDs are in binary with units of ns. - 2. Some time values are scaled by four, 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, Tk, is scaled by 10 to affect a - least count of 0.1 ns (more accuracy). - 4. SPD values not scaled are multiplied by 10 and then divided by 10T to find - equivalent minimum number of bus clocks (a remainder causes round-up of clocks). - 5. SPD values that are prescaled by 4 are multiplied by 10 and then divided by 40T to find - equivalent minimum number of bus clocks (a remainder causes round-up of clocks).*/ - - /* Tras */ - dword = Tras * 40; - pDCTstat->DIMMTras = (u16)dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrasT_1066) - val = Min_TrasT_1066; - else if (val > Max_TrasT_1066) - val = Max_TrasT_1066; - } else { - if (val < Min_TrasT) - val = Min_TrasT; - else if (val > Max_TrasT) - val = Max_TrasT; - } - pDCTstat->Tras = val; - - /* Trp */ - dword = Trp * 10; - pDCTstat->DIMMTrp = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrasT_1066) - val = Min_TrpT_1066; - else if (val > Max_TrpT_1066) - val = Max_TrpT_1066; - } else { - if (val < Min_TrpT) - val = Min_TrpT; - else if (val > Max_TrpT) - val = Max_TrpT; - } - pDCTstat->Trp = val; - - /*Trrd*/ - dword = Trrd * 10; - pDCTstat->DIMMTrrd = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrrdT_1066) - val = Min_TrrdT_1066; - else if (val > Max_TrrdT_1066) - val = Max_TrrdT_1066; - } else { - if (val < Min_TrrdT) - val = Min_TrrdT; - else if (val > Max_TrrdT) - val = Max_TrrdT; - } - pDCTstat->Trrd = val; - - /* Trcd */ - dword = Trcd * 10; - pDCTstat->DIMMTrcd = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrcdT_1066) - val = Min_TrcdT_1066; - else if (val > Max_TrcdT_1066) - val = Max_TrcdT_1066; - } else { - if (val < Min_TrcdT) - val = Min_TrcdT; - else if (val > Max_TrcdT) - val = Max_TrcdT; - } - pDCTstat->Trcd = val; - - /* Trc */ - dword = Trc * 40; - pDCTstat->DIMMTrc = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrcT_1066) - val = Min_TrcT_1066; - else if (val > Max_TrcT_1066) - val = Max_TrcT_1066; - } else { - if (val < Min_TrcT) - val = Min_TrcT; - else if (val > Max_TrcT) - val = Max_TrcT; - } - pDCTstat->Trc = val; - - /* Trtp */ - dword = Trtp * 10; - pDCTstat->DIMMTrtp = dword; - val = pDCTstat->Speed; - if (val <= 2) { /* 7.75ns / Speed in ns to get clock # */ - val = 2; /* for DDR400/DDR533 */ - } else { /* Note a speed of 3 will be a Trtp of 3 */ - val = 3; /* for DDR667/DDR800/DDR1066 */ - } - pDCTstat->Trtp = val; - - /* Twr */ - dword = Twr * 10; - pDCTstat->DIMMTwr = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TwrT_1066) - val = Min_TwrT_1066; - else if (val > Max_TwrT_1066) - val = Max_TwrT_1066; - } else { - if (val < Min_TwrT) - val = Min_TwrT; - else if (val > Max_TwrT) - val = Max_TwrT; - } - pDCTstat->Twr = val; - - /* Twtr */ - dword = Twtr * 10; - pDCTstat->DIMMTwtr = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TwrT_1066) - val = Min_TwtrT_1066; - else if (val > Max_TwtrT_1066) - val = Max_TwtrT_1066; - } else { - 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]; - - mctAdjustAutoCycTmg_D(); - - /* Program DRAM Timing values */ - DramTimingLo = 0; /* Dram Timing Low init */ - val = pDCTstat->CASL; - val = Tab_tCL_j[val]; - DramTimingLo |= val; - - val = pDCTstat->Trcd; - if (DDR2_1066) - val -= Bias_TrcdT_1066; - else - val -= Bias_TrcdT; - - DramTimingLo |= val << 4; - - val = pDCTstat->Trp; - if (DDR2_1066) - val -= Bias_TrpT_1066; - else { - val -= Bias_TrpT; - val <<= 1; - } - DramTimingLo |= val << 7; - - val = pDCTstat->Trtp; - val -= Bias_TrtpT; - DramTimingLo |= val << 11; - - val = pDCTstat->Tras; - if (DDR2_1066) - val -= Bias_TrasT_1066; - else - val -= Bias_TrasT; - DramTimingLo |= val << 12; - - val = pDCTstat->Trc; - val -= Bias_TrcT; - DramTimingLo |= val << 16; - - if (!DDR2_1066) { - val = pDCTstat->Twr; - val -= Bias_TwrT; - DramTimingLo |= val << 20; - } - - val = pDCTstat->Trrd; - if (DDR2_1066) - val -= Bias_TrrdT_1066; - else - val -= Bias_TrrdT; - DramTimingLo |= val << 22; - - - DramTimingHi = 0; /* Dram Timing Low init */ - val = pDCTstat->Twtr; - if (DDR2_1066) - val -= Bias_TwtrT_1066; - else - val -= Bias_TwtrT; - DramTimingHi |= val << 8; - - val = 2; - DramTimingHi |= val << 16; - - val = 0; - for (i = 4; i > 0; i--) { - val <<= 3; - val |= Trfc[i-1]; - } - DramTimingHi |= val << 20; - - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * dct; - print_tx("AutoCycTiming: DramTimingLo ", DramTimingLo); - print_tx("AutoCycTiming: DramTimingHi ", DramTimingHi); - - Set_NB32(dev, 0x88 + reg_off, DramTimingLo); /*DCT Timing Low*/ - DramTimingHi |=0x0000FC77; - Set_NB32(dev, 0x8c + reg_off, DramTimingHi); /*DCT Timing Hi*/ - - if (DDR2_1066) { - /* Twr */ - dword = pDCTstat->Twr; - dword -= Bias_TwrT_1066; - dword <<= 4; - reg = 0x84 + reg_off; - val = Get_NB32(dev, reg); - val &= 0x8F; - val |= dword; - Set_NB32(dev, reg, val); - } - - print_tx("AutoCycTiming: Status ", pDCTstat->Status); - print_tx("AutoCycTiming: ErrStatus ", pDCTstat->ErrStatus); - print_tx("AutoCycTiming: ErrCode ", pDCTstat->ErrCode); - print_t("AutoCycTiming: Done\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. - */ - - u16 proposedFreq; - u16 word; - - /* Get CPU Si Revision defined limit (NPT) */ - proposedFreq = 533; /* 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; - } -} - - - -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 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). - */ - int i, j, k; - u8 T1min, CL1min; - - /* i={0..7} (std. physical DIMM number) - * j is an integer which enumerates increasing CAS latency. - * k is an integer which enumerates decreasing cycle time. - * CL no. {0,1,2} corresponds to CL X, CL X-.5, or CL X-1 (per individual DIMM) - * Max timing values are per parameter, of all DIMMs, spec'd in ns like the SPD. - */ - - CL1min = 0xFF; - T1min = 0xFF; - for (k = K_MAX; k >= K_MIN; k--) { - for (j = J_MIN; j <= J_MAX; j++) { - if (Sys_Capability_D(pMCTstat, pDCTstat, j, k)) { - /* 1. check to see if DIMMi is populated. - 2. check if DIMMi supports CLj and Tjk */ - for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) { - if (pDCTstat->DIMMValid & (1 << i)) { - if (Dimm_Supports_D(pDCTstat, i, j, k)) - break; - } - } /* while ++i */ - if (i == MAX_DIMMS_SUPPORTED) { - T1min = k; - CL1min = j; - goto got_TCL; - } - } - } /* while ++j */ - } /* while --k */ - -got_TCL: - if (T1min != 0xFF) { - pDCTstat->DIMMCASL = CL1min; /*mfg. optimized */ - pDCTstat->DIMMAutoSpeed = T1min; - print_tx("SPDGetTCL_D: DIMMCASL ", pDCTstat->DIMMCASL); - print_tx("SPDGetTCL_D: DIMMAutoSpeed ", pDCTstat->DIMMAutoSpeed); - - } else { - pDCTstat->DIMMCASL = CL_DEF; /* failsafe values (running in min. mode) */ - pDCTstat->DIMMAutoSpeed = T_DEF; - pDCTstat->ErrStatus |= 1 << SB_DimmMismatchT; - pDCTstat->ErrStatus |= 1 << SB_MinimumMode; - pDCTstat->ErrCode = SC_VarianceErr; - } - print_tx("SPDGetTCL_D: Status ", pDCTstat->Status); - print_tx("SPDGetTCL_D: ErrStatus ", pDCTstat->ErrStatus); - print_tx("SPDGetTCL_D: ErrCode ", pDCTstat->ErrCode); - print_t("SPDGetTCL_D: Done\n"); -} - - -static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev; - u32 reg; - u32 val; - - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct); - - if (pDCTstat->GangedMode) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1); - } - - if (pDCTstat->_2Tmode == 2) { - dev = pDCTstat->dev_dct; - reg = 0x94 + 0x100 * dct; /* Dram Configuration Hi */ - val = Get_NB32(dev, reg); - val |= 1 << 20; /* 2T CMD mode */ - Set_NB32(dev, reg, val); - } - - mct_PlatformSpec(pMCTstat, pDCTstat, dct); - 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 reg_off; - u32 dev; - u16 word; - u32 dword; - u8 byte; - - print_tx("AutoConfig_D: DCT: ", dct); - - 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; - reg_off = 0x100 * dct; - - - /* Build Dram Control Register Value */ - DramConfigMisc2 = Get_NB32 (dev, 0xA8 + reg_off); /* Dram Control*/ - DramControl = Get_NB32 (dev, 0x78 + reg_off); /* Dram Control*/ - - if (mctGet_NVbits(NV_CLKHZAltVidC3)) - DramControl |= 1<<16; - - // FIXME: Add support(skip) for Ax and Cx versions - DramControl |= 5; /* RdPtrInit */ - - - /* Build Dram Config Lo Register Value */ - DramConfigLo |= 1 << 4; /* 75 Ohms ODT */ - if (mctGet_NVbits(NV_MAX_DIMMS) == 8) { - if (pDCTstat->Speed == 3) { - if (pDCTstat->MAdimms[dct] == 4) - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } else if (pDCTstat->Speed == 4) { - if (pDCTstat->MAdimms[dct] != 1) - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - } else { - // FIXME: Skip for Ax versions - if (pDCTstat->MAdimms[dct] == 4) { - if (pDCTstat->DimmQRPresent != 0) { - if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 4)) { - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - } else if (pDCTstat->MAdimms[dct] == 4) { - if (pDCTstat->Speed == 4) { - if (pDCTstat->DimmQRPresent != 0) { - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - } - } - } else if (pDCTstat->MAdimms[dct] == 2) { - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - - } - - // FIXME: Skip for Ax versions - /* callback not required - if (!mctParityControl_D()) */ - if (Status & (1 << SB_PARDIMMs)) { - DramConfigLo |= 1 << ParEn; - DramConfigMisc2 |= 1 << ActiveCmdAtRst; - } else { - DramConfigLo &= ~(1 << ParEn); - DramConfigMisc2 &= ~(1 << ActiveCmdAtRst); - } - - if (mctGet_NVbits(NV_BurstLen32)) { - if (!pDCTstat->GangedMode) - DramConfigLo |= 1 << BurstLength32; - } - - 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))) - DramConfigLo |= 1 << UnBuffDimm; /* Unbuffered DIMMs */ - - 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 */ - dword = pDCTstat->Speed; - DramConfigHi |= dword - 1; /* get MemClk encoding */ - DramConfigHi |= 1 << MemClkFreqVal; - - if (Status & (1 << SB_Registered)) - if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) - /* set only if x8 Registered DIMMs in System*/ - DramConfigHi |= 1 << RDqsEn; - - if (mctGet_NVbits(NV_CKE_PDEN)) { - DramConfigHi |= 1 << 15; /* PowerDownEn */ - if (mctGet_NVbits(NV_CKE_CTL)) - /*Chip Select control of CKE*/ - DramConfigHi |= 1 << 16; - } - - /* 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; - - val = pDCTstat->DIMM2Kpage; - if (pDCTstat->GangedMode != 0) { - if (dct != 0) { - val &= 0x55; - } else { - val &= 0xAA; - } - } - if (val) - val = Tab_2KTfawT_k[pDCTstat->Speed]; - else - val = Tab_1KTfawT_k[pDCTstat->Speed]; - - if (pDCTstat->Speed == 5) - val >>= 1; - - val -= Bias_TfawT; - val <<= 28; - DramConfigHi |= val; /* Tfaw for 1K or 2K paged drams */ - - // FIXME: Skip for Ax versions - 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(dev, 0x88 + reg_off); - if (mctGet_NVbits(NV_AllMemClks) == 0) { - /* Special Jedec SPD diagnostic bit - "enable all clocks" */ - if (!(pDCTstat->Status & (1 << SB_DiagClks))) { - const u8 *p; - byte = mctGet_NVbits(NV_PACK_TYPE); - if (byte == PT_L1) - p = Tab_L1CLKDis; - else if (byte == PT_M2) - p = Tab_M2CLKDis; - else - p = Tab_S1CLKDis; - - dword = 0; - while (dword < MAX_DIMMS_SUPPORTED) { - val = p[dword]; - print_tx("DramTimingLo: val=", val); - if (!(pDCTstat->DIMMValid & (1 << val))) - /*disable memclk*/ - DramTimingLo |= 1 << (dword+24); - dword++; - } - } - } - - print_tx("AutoConfig_D: DramControl: ", DramControl); - print_tx("AutoConfig_D: DramTimingLo: ", DramTimingLo); - print_tx("AutoConfig_D: DramConfigMisc: ", DramConfigMisc); - print_tx("AutoConfig_D: DramConfigMisc2: ", DramConfigMisc2); - print_tx("AutoConfig_D: DramConfigLo: ", DramConfigLo); - print_tx("AutoConfig_D: DramConfigHi: ", DramConfigHi); - - /* Write Values to the registers */ - Set_NB32(dev, 0x78 + reg_off, DramControl); - Set_NB32(dev, 0x88 + reg_off, DramTimingLo); - Set_NB32(dev, 0xA0 + reg_off, DramConfigMisc); - Set_NB32(dev, 0xA8 + reg_off, DramConfigMisc2); - Set_NB32(dev, 0x90 + reg_off, DramConfigLo); - mct_SetDramConfigHi_D(pDCTstat, dct, DramConfigHi); - mct_ForceAutoPrecharge_D(pDCTstat, dct); - mct_EarlyArbEn_D(pMCTstat, pDCTstat); - mctHookAfterAutoCfg(); - - print_tx("AutoConfig: Status ", pDCTstat->Status); - print_tx("AutoConfig: ErrStatus ", pDCTstat->ErrStatus); - print_tx("AutoConfig: ErrCode ", pDCTstat->ErrCode); - print_t("AutoConfig: Done\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; - u32 reg_off; - u8 byte; - u16 word; - u32 dword; - u16 smbaddr; - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * dct; - - BankAddrReg = 0; - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel+=2) { - byte = ChipSel; - if ((pDCTstat->Status & (1 << SB_64MuxedMode)) && ChipSel >=4) - byte -= 3; - - if (pDCTstat->DIMMValid & (1 << byte)) { - smbaddr = Get_DIMMAddress_D(pDCTstat, (ChipSel + dct)); - - byte = mctRead_SPD(smbaddr, SPD_ROWSZ); - Rows = byte & 0x1f; - - byte = mctRead_SPD(smbaddr, SPD_COLSZ); - Cols = byte & 0x1f; - - Banks = mctRead_SPD(smbaddr, SPD_LBANKS); - - byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH); - - byte = mctRead_SPD(smbaddr, SPD_DMBANKS); - Ranks = (byte & 7) + 1; - - /* Configure Bank encoding - * Use a 6-bit key into a lookup table. - * Key (index) = CCCBRR, where CCC is the number of - * Columns minus 9,RR is the number of Rows minus 13, - * and B is the number of banks minus 2. - * See "6-bit Bank Addressing Table" at the end of - * this file.*/ - byte = Cols - 9; /* 9 Cols is smallest dev size */ - byte <<= 3; /* make room for row and bank bits*/ - if (Banks == 8) - byte |= 4; - - /* 13 Rows is smallest dev size */ - byte |= Rows - 13; /* CCCBRR internal encode */ - - for (dword = 0; dword < 12; dword++) { - if (byte == Tab_BankAddr[dword]) - break; - } - - if (dword < 12) { - - /* 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*/ - if (Banks == 8) - byte -= 2; /* 3 banks - 5 */ - else - byte -= 3; /* 2 banks - 5 */ - /* mask size (64-bit rank only) */ - - 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) + reg_off; /*Dram CS Mask Register */ - val = csMask; - val &= 0x1FF83FE0; /* Mask out reserved bits.*/ - Set_NB32(dev, reg, val); - } - } else { - if (pDCTstat->DIMMSPDCSE & (1 << ChipSel)) - pDCTstat->CSTestFail |= (1 << ChipSel); - } /* if DIMMValid*/ - } /* while ChipSel*/ - - SetCSTriState(pMCTstat, pDCTstat, dct); - /* SetCKETriState */ - SetODTTriState(pMCTstat, pDCTstat, dct); - - if (pDCTstat->Status & (1 << SB_128bitmode)) { - SetCSTriState(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 + reg_off; /* Bank Addressing Register */ - Set_NB32(dev, reg, BankAddrReg); - - print_tx("SPDSetBanks: Status ", pDCTstat->Status); - print_tx("SPDSetBanks: ErrStatus ", pDCTstat->ErrStatus); - print_tx("SPDSetBanks: ErrCode ", pDCTstat->ErrCode); - print_t("SPDSetBanks: Done\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 smbaddr, smbaddr1; - 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)))) { - smbaddr = Get_DIMMAddress_D(pDCTstat, i); - smbaddr1 = Get_DIMMAddress_D(pDCTstat, i+1); - - byte = mctRead_SPD(smbaddr, SPD_ROWSZ) & 0x1f; - byte1 = mctRead_SPD(smbaddr1, SPD_ROWSZ) & 0x1f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_COLSZ) & 0x1f; - byte1 = mctRead_SPD(smbaddr1, SPD_COLSZ) & 0x1f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_BANKSZ); - byte1 = mctRead_SPD(smbaddr1, SPD_BANKSZ); - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0x7f; - byte1 = mctRead_SPD(smbaddr1, SPD_DEVWIDTH) & 0x7f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_DMBANKS) & 7; /* #ranks-1 */ - byte1 = mctRead_SPD(smbaddr1, 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 reg_off; - u32 val; - - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * 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) + reg_off; /* Base[q] reg.*/ - val = Get_NB32(dev, reg); - if (!(val & 3)) { /* (CSEnable|Spare == 1)bank is enabled already? */ - reg = 0x60 + ((q << 1) & 0xc) + reg_off; /*Mask[q] reg.*/ - val = Get_NB32(dev, 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) + reg_off; - if (_DSpareEn) { - BiggestBank = 0; - val = 1 << Spare; /* Spare Enable*/ - } else { - val = curcsBase; - val |= 1 << CSEnable; /* Bank Enable */ - } - Set_NB32(dev, 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 + reg_off; - val = 1 << TestFail; - Set_NB32(dev, reg, val); - } - } - - if (nxtcsBase) { - pDCTstat->DCTSysLimit = nxtcsBase - 1; - mct_AfterStitchMemory(pMCTstat, pDCTstat, dct); - } - - print_tx("StitchMemory: Status ", pDCTstat->Status); - print_tx("StitchMemory: ErrStatus ", pDCTstat->ErrStatus); - print_tx("StitchMemory: ErrCode ", pDCTstat->ErrCode); - print_t("StitchMemory: Done\n"); -} - - -static u8 Get_Tk_D(u8 k) -{ - return Table_T_k[k]; -} - - -static u8 Get_CLj_D(u8 j) -{ - return Table_CL2_j[j]; -} - -static u8 Get_DefTrc_k_D(u8 k) -{ - return Tab_defTrc_k[k]; -} - - -static u16 Get_40Tk_D(u8 k) -{ - return Tab_40T_k[k]; /* FIXME: k or k<<1 ?*/ -} - - -static u16 Get_Fk_D(u8 k) -{ - return Table_F_k[k]; /* FIXME: k or k<<1 ? */ -} - - -static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat, - u8 i, u8 j, u8 k) -{ - u8 Tk, CLj, CL_i; - u8 ret = 0; - - u32 DIMMi; - u8 byte; - u16 word, wordx; - - DIMMi = Get_DIMMAddress_D(pDCTstat, i); - - CLj = Get_CLj_D(j); - - /* check if DIMMi supports CLj */ - CL_i = mctRead_SPD(DIMMi, SPD_CASLAT); - byte = CL_i & CLj; - if (byte) { - /*find out if its CL X, CLX-1, or CLX-2 */ - word = bsr(byte); /* bit position of CLj */ - wordx = bsr(CL_i); /* bit position of CLX of CLi */ - wordx -= word; /* CL number (CL no. = 0,1, 2, or 3) */ - wordx <<= 3; /* 8 bits per SPD byte index */ - /*get T from SPD byte 9, 23, 25*/ - word = (EncodedTSPD >> wordx) & 0xFF; - Tk = Get_Tk_D(k); - byte = mctRead_SPD(DIMMi, word); /* DIMMi speed */ - if (Tk < byte) { - ret = 1; - } else if (byte == 0) { - pDCTstat->ErrStatus |= 1 << SB_NoCycTime; - ret = 1; - } else { - ret = 0; /* DIMM is capable! */ - } - } else { - ret = 1; - } - return ret; -} - - -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, Index; - u16 Checksum; - u8 SPDCtrl; - u16 RegDIMMPresent, MaxDimms; - u8 devwidth; - u16 DimmSlots; - u8 byte = 0, bytex; - u16 word; - - /* 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; - pDCTstat->DimmQRPresent = 0; - - for (i = 0; i< MAX_DIMMS_SUPPORTED; i++) { - if (i >= MaxDimms) - break; - - if ((pDCTstat->DimmQRPresent & (1 << i)) || (i < DimmSlots)) { - print_tx("\t DIMMPresence: i=", i); - smbaddr = Get_DIMMAddress_D(pDCTstat, i); - print_tx("\t DIMMPresence: smbaddr=", smbaddr); - if (smbaddr) { - Checksum = 0; - for (Index = 0; Index < 64; Index++) { - int status; - status = mctRead_SPD(smbaddr, Index); - if (status < 0) - break; - byte = status & 0xFF; - if (Index < 63) - Checksum += byte; - } - - if (Index == 64) { - pDCTstat->DIMMPresent |= 1 << i; - if ((Checksum & 0xFF) == byte) { - byte = mctRead_SPD(smbaddr, SPD_TYPE); - if (byte == JED_DDR2SDRAM) { - /*Dimm is 'Present'*/ - pDCTstat->DIMMValid |= 1 << i; - } - } else { - 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 = mctRead_SPD(smbaddr, SPD_TYPE); - if (byte == JED_DDR2SDRAM) - pDCTstat->DIMMValid |= 1 << 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)mctRead_SPD(smbaddr, SPD_MANID_START + k)) << (k * 8); - for (k = 0; k < SPD_PARTN_LENGTH; k++) - pDCTstat->DimmPartNumber[i][k] = mctRead_SPD(smbaddr, SPD_PARTN_START + k); - pDCTstat->DimmPartNumber[i][SPD_PARTN_LENGTH] = 0; - pDCTstat->DimmRevisionNumber[i] = 0; - for (k = 0; k < 2; k++) - pDCTstat->DimmRevisionNumber[i] |= ((uint16_t)mctRead_SPD(smbaddr, SPD_REVNO_START + k)) << (k * 8); - pDCTstat->DimmSerialNumber[i] = 0; - for (k = 0; k < 4; k++) - pDCTstat->DimmSerialNumber[i] |= ((uint32_t)mctRead_SPD(smbaddr, SPD_SERIAL_START + k)) << (k * 8); - pDCTstat->DimmRows[i] = mctRead_SPD(smbaddr, SPD_ROWSZ) & 0xf; - pDCTstat->DimmCols[i] = mctRead_SPD(smbaddr, SPD_COLSZ) & 0xf; - pDCTstat->DimmRanks[i] = (mctRead_SPD(smbaddr, SPD_DMBANKS) & 0x7) + 1; - pDCTstat->DimmBanks[i] = mctRead_SPD(smbaddr, SPD_LBANKS); - pDCTstat->DimmWidth[i] = mctRead_SPD(smbaddr, SPD_DEVWIDTH); - } - /* Check module type */ - byte = mctRead_SPD(smbaddr, SPD_DIMMTYPE); - if (byte & JED_REGADCMSK) { - RegDIMMPresent |= 1 << i; - pDCTstat->DimmRegistered[i] = 1; - } else { - pDCTstat->DimmRegistered[i] = 0; - } - /* Check ECC capable */ - byte = mctRead_SPD(smbaddr, SPD_EDCTYPE); - if (byte & JED_ECC) { - /* DIMM is ECC capable */ - pDCTstat->DimmECCPresent |= 1 << i; - } - if (byte & JED_ADRCPAR) { - /* DIMM is ECC capable */ - pDCTstat->DimmPARPresent |= 1 << i; - } - /* Check if x4 device */ - devwidth = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE; - if (devwidth == 4) { - /* DIMM is made with x4 or x16 drams */ - pDCTstat->Dimmx4Present |= 1 << i; - } else if (devwidth == 8) { - pDCTstat->Dimmx8Present |= 1 << i; - } else if (devwidth == 16) { - pDCTstat->Dimmx16Present |= 1 << i; - } - /* check page size */ - byte = mctRead_SPD(smbaddr, SPD_COLSZ); - byte &= 0x0F; - word = 1 << byte; - word >>= 3; - word *= devwidth; /* (((2^COLBITS) / 8) * ORG) / 2048 */ - word >>= 11; - if (word) - pDCTstat->DIMM2Kpage |= 1 << i; - - /*Check if SPD diag bit 'analysis probe installed' is set */ - byte = mctRead_SPD(smbaddr, SPD_ATTRIB); - if (byte & JED_PROBEMSK) - pDCTstat->Status |= 1 << SB_DiagClks; - - byte = mctRead_SPD(smbaddr, SPD_DMBANKS); - if (!(byte & (1 << SPDPLBit))) - pDCTstat->DimmPlPresent |= 1 << i; - byte &= 7; - byte++; /* ranks */ - if (byte > 2) { - /* 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)); - } - byte = 2; /* upper two ranks of QR DIMM will be counted on another DIMM number iteration*/ - } else if (byte == 2) { - pDCTstat->DimmDRPresent |= 1 << i; - } - bytex = devwidth; - if (devwidth == 16) - bytex = 4; - else if (devwidth == 4) - bytex = 16; - - 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 for DRAM package Year <= 06*/ - byte = mctRead_SPD(smbaddr, SPD_MANDATEYR); - if (byte < MYEAR06) { - /*Year < 06 and hence Week < 24 of 06 */ - pDCTstat->DimmYr06 |= 1 << i; - pDCTstat->DimmWk2406 |= 1 << i; - } else if (byte == MYEAR06) { - /*Year = 06, check if Week <= 24 */ - pDCTstat->DimmYr06 |= 1 << i; - byte = mctRead_SPD(smbaddr, SPD_MANDATEWK); - if (byte <= MWEEK24) - pDCTstat->DimmWk2406 |= 1 << i; - } - } - } - } - } - print_tx("\t DIMMPresence: DIMMValid=", pDCTstat->DIMMValid); - print_tx("\t DIMMPresence: DIMMPresent=", pDCTstat->DIMMPresent); - print_tx("\t DIMMPresence: RegDIMMPresent=", RegDIMMPresent); - print_tx("\t DIMMPresence: DimmECCPresent=", pDCTstat->DimmECCPresent); - print_tx("\t DIMMPresence: DimmPARPresent=", pDCTstat->DimmPARPresent); - print_tx("\t DIMMPresence: Dimmx4Present=", pDCTstat->Dimmx4Present); - print_tx("\t DIMMPresence: Dimmx8Present=", pDCTstat->Dimmx8Present); - print_tx("\t DIMMPresence: Dimmx16Present=", pDCTstat->Dimmx16Present); - print_tx("\t DIMMPresence: DimmPlPresent=", pDCTstat->DimmPlPresent); - print_tx("\t DIMMPresence: DimmDRPresent=", pDCTstat->DimmDRPresent); - print_tx("\t DIMMPresence: DimmQRPresent=", pDCTstat->DimmQRPresent); - print_tx("\t DIMMPresence: DATAload[0]=", pDCTstat->DATAload[0]); - print_tx("\t DIMMPresence: MAload[0]=", pDCTstat->MAload[0]); - print_tx("\t DIMMPresence: MAdimms[0]=", pDCTstat->MAdimms[0]); - print_tx("\t DIMMPresence: DATAload[1]=", pDCTstat->DATAload[1]); - print_tx("\t DIMMPresence: MAload[1]=", pDCTstat->MAload[1]); - print_tx("\t DIMMPresence: MAdimms[1]=", 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 (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; - } - - print_tx("\t DIMMPresence: Status ", pDCTstat->Status); - print_tx("\t DIMMPresence: ErrStatus ", pDCTstat->ErrStatus); - print_tx("\t DIMMPresence: ErrCode ", pDCTstat->ErrCode); - print_t("\t DIMMPresence: Done\n"); - - mctHookAfterDIMMpre(); - - return pDCTstat->ErrCode; -} - - -static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, int j, int k) -{ - /* Determine if system is capable of operating at given input - * parameters for CL, and T. There are three components to - * determining "maximum frequency" in AUTO mode: SPD component, - * Bus load component, and "Preset" max frequency component. - * This procedure is used to help find the SPD component and relies - * on pre-determination of the bus load component and the Preset - * components. The generalized algorithm for finding maximum - * frequency is structured this way so as to optimize for CAS - * latency (which might get better as a result of reduced frequency). - * See "Global relationship between index values and item values" - * for definition of CAS latency index (j) and Frequency index (k). - */ - u8 freqOK, ClOK; - u8 ret = 0; - - if (Get_Fk_D(k) > pDCTstat->PresetmaxFreq) - freqOK = 0; - else - freqOK = 1; - - /* compare proposed CAS latency with AMD Si capabilities */ - if ((j < J_MIN) || (j > J_MAX)) - ClOK = 0; - else - ClOK = 1; - - if (freqOK && ClOK) - ret = 1; - - return ret; -} - - -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i) -{ - u8 *p; - - p = pDCTstat->DIMMAddr; - return p[i]; -} - - -static void mct_initDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u8 err_code; - - /* Config. DCT0 for Ganged or unganged mode */ - print_t("\tmct_initDCT: DCTInit_D 0\n"); - DCTInit_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) { - print_t("\tmct_initDCT: DCTInit_D 1\n"); - err_code = pDCTstat->ErrCode; /* save DCT0 errors */ - pDCTstat->ErrCode = 0; - DCTInit_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(pDCTstat->dev_dct, 0x100 + 0x94, val); - } - } - } -// exitDCTInit: -} - - -static void mct_DramInit(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - - mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat); - // FIXME: for rev A: mct_BeforeDramInit_D(pDCTstat, dct); - - /* Disable auto refresh before Dram init when in ganged mode (Erratum 278) */ - if (pDCTstat->LogicalCPUID & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)) { - if (pDCTstat->GangedMode) { - val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct)); - val |= 1 << DisAutoRefresh; - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - } - } - - mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct); - - /* Re-enable auto refresh after Dram init when in ganged mode - * to ensure both DCTs are in sync (Erratum 278) - */ - - if (pDCTstat->LogicalCPUID & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)) { - if (pDCTstat->GangedMode) { - do { - val = Get_NB32(pDCTstat->dev_dct, 0x90 + (0x100 * dct)); - } while (!(val & (1 << InitDram))); - - WaitRoutine_D(50); - - val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct)); - val &= ~(1 << DisAutoRefresh); - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - val |= 1 << DisAutoRefresh; - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - val &= ~(1 << DisAutoRefresh); - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - } - } -} - - -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 { - if (mctGet_NVbits(NV_Unganged)) - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - - if (!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) { - 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); - print_tx("setMode: DRAM Controller Select Low Register = ", val); - } - } - 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))); - -} - - -static 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. - */ - - u32 dev = pDCTstat->dev_dct; - u32 index_reg; - u8 i, i_start, i_end; - - if (pDCTstat->GangedMode) { - SyncSetting(pDCTstat); - 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 + (i * 0x100); - Set_NB32_index_wait(dev, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A Output Driver Compensation Control */ - Set_NB32_index_wait(dev, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A Output Driver Compensation Control */ - } - - return pDCTstat->ErrCode; - -} - - -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat) -{ - u32 dev; - u32 val; - - if (pDCTstat->NodePresent) { - print_tx("mct_SyncDCTsReady: Node ", pDCTstat->Node_ID); - 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))); - print_t("mct_SyncDCTsReady: DramEnabled\n"); - } - } /* 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; - - if (dct == 0) { - SPDCalcWidth_D(pMCTstat, pDCTstat); - ret = mct_setMode(pMCTstat, pDCTstat); - } else { - ret = pDCTstat->ErrCode; - } - - print_tx("SPDCalcWidth: Status ", pDCTstat->Status); - print_tx("SPDCalcWidth: ErrStatus ", pDCTstat->ErrStatus); - print_tx("SPDCalcWidth: ErrCode ", pDCTstat->ErrCode); - print_t("SPDCalcWidth: Done\n"); - - 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); - print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select Low Register = ", val); - print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select High Register = ", dword); - - 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); - print_tx("AfterStitch DCT1 only: DRAM Controller Select Low Register = ", val); - print_tx("AfterStitch DCT1 only: DRAM Controller Select High Register = ", dword); - } - } - } else { - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - } - print_tx("AfterStitch pDCTstat->NodeSysBase = ", pDCTstat->NodeSysBase); - print_tx("mct_AfterStitchMemory: pDCTstat->NodeSysLimit ", 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 reg_off = 0x100 * dct; - u32 val; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - Get_Trdrd(pMCTstat, pDCTstat, dct); - Get_Twrwr(pMCTstat, pDCTstat, dct); - Get_Twrrd(pMCTstat, pDCTstat, dct); - Get_TrwtTO(pMCTstat, pDCTstat, dct); - Get_TrwtWB(pMCTstat, pDCTstat); - - reg = 0x8C + reg_off; /* Dram Timing Hi */ - val = Get_NB32(dev, reg); - val &= 0xffff0300; - dword = pDCTstat->TrwtTO; //0x07 - val |= dword << 4; - dword = pDCTstat->Twrrd; //0x03 - val |= dword << 10; - dword = pDCTstat->Twrwr; //0x03 - val |= dword << 12; - dword = pDCTstat->Trdrd; //0x03 - val |= dword << 14; - dword = pDCTstat->TrwtWB; //0x07 - val |= dword; - val = OtherTiming_A_D(pDCTstat, val); - Set_NB32(dev, reg, val); - -} - - -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Trdrd; - u8 byte; - u32 dword; - u32 val; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) { - /* mixed (x4 or x8) DIMM types - the largest DqsRcvEnGrossDelay of any DIMM minus the DqsRcvEnGrossDelay - of any other DIMM is equal to the Critical Gross Delay Difference (CGDD) for Trdrd.*/ - byte = Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg); - if (byte == 0) - Trdrd = 1; - else - Trdrd = 2; - - } else { - /* - Trdrd with non-mixed DIMM types - RdDqsTime are the same for all DIMMs and DqsRcvEn difference between - any two DIMMs is less than half of a MEMCLK, BIOS should program Trdrd to 0000b, - else BIOS should program Trdrd to 0001b. - - RdDqsTime are the same for all DIMMs - DDR400~DDR667 only use one set register - DDR800 have two set register for DIMM0 and DIMM1 */ - Trdrd = 1; - if (pDCTstat->Speed > 3) { - /* DIMM0+DIMM1 exist */ //NOTE it should be 5 - val = bsf(pDCTstat->DIMMValid); - dword = bsr(pDCTstat->DIMMValid); - if (dword != val && dword != 0) { - /* DCT Read DQS Timing Control - DIMM0 - Low */ - dword = Get_NB32_index_wait(dev, index_reg, 0x05); - /* DCT Read DQS Timing Control - DIMM1 - Low */ - val = Get_NB32_index_wait(dev, index_reg, 0x105); - if (val != dword) - goto Trdrd_1; - - /* DCT Read DQS Timing Control - DIMM0 - High */ - dword = Get_NB32_index_wait(dev, index_reg, 0x06); - /* DCT Read DQS Timing Control - DIMM1 - High */ - val = Get_NB32_index_wait(dev, index_reg, 0x106); - if (val != dword) - goto Trdrd_1; - } - } - - /* DqsRcvEn difference between any two DIMMs is - less than half of a MEMCLK */ - /* DqsRcvEn byte 1,0*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x10)) - goto Trdrd_1; - /* DqsRcvEn byte 3,2*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x11)) - goto Trdrd_1; - /* DqsRcvEn byte 5,4*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x20)) - goto Trdrd_1; - /* DqsRcvEn byte 7,6*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x21)) - goto Trdrd_1; - /* DqsRcvEn ECC*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x12)) - goto Trdrd_1; - Trdrd = 0; - Trdrd_1: - ; - } - pDCTstat->Trdrd = Trdrd; - -} - - -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Twrwr = 0; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - u32 val; - u32 dword; - - /* WrDatGrossDlyByte only use one set register when DDR400~DDR667 - DDR800 have two set register for DIMM0 and DIMM1 */ - if (pDCTstat->Speed > 3) { - val = bsf(pDCTstat->DIMMValid); - dword = bsr(pDCTstat->DIMMValid); - if (dword != val && dword != 0) { - /*the largest WrDatGrossDlyByte of any DIMM minus the - WrDatGrossDlyByte of any other DIMM is equal to CGDD */ - val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg); - } - if (val == 0) - Twrwr = 2; - else - Twrwr = 3; - } - pDCTstat->Twrwr = Twrwr; -} - - -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 byte, bytex, val; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - /* On any given byte lane, the largest WrDatGrossDlyByte delay of - any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is - equal to the Critical Gross Delay Difference (CGDD) for Twrrd.*/ - - /* WrDatGrossDlyByte only use one set register when DDR400~DDR667 - DDR800 have two set register for DIMM0 and DIMM1 */ - if (pDCTstat->Speed > 3) { - val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg); - } else { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 1); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */ - pDCTstat->WrDatGrossH = (u8) val; /* low byte = max value */ - } - - Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg); - - bytex = pDCTstat->DqsRcvEnGrossL; - byte = pDCTstat->WrDatGrossH; - if (byte > bytex) { - byte -= bytex; - if (byte == 1) - bytex = 1; - else - bytex = 2; - } else { - bytex = 0; - } - pDCTstat->Twrrd = bytex; -} - - -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 byte, bytex; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - /* On any given byte lane, the largest WrDatGrossDlyByte delay of - any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is - equal to the Critical Gross Delay Difference (CGDD) for TrwtTO. */ - Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg); - Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg); - bytex = pDCTstat->DqsRcvEnGrossL; - byte = pDCTstat->WrDatGrossH; - if (bytex > byte) { - bytex -= byte; - if ((bytex == 1) || (bytex == 2)) - bytex = 3; - else - bytex = 4; - } else { - byte -= bytex; - if ((byte == 0) || (byte == 1)) - bytex = 2; - else - bytex = 1; - } - - pDCTstat->TrwtTO = bytex; -} - - -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 + 1; -} - - -static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg, - u32 index) -{ - u8 Smallest_0, Largest_0, Smallest_1, Largest_1; - u8 i; - u32 val; - u8 byte; - u8 ecc_reg = 0; - - Smallest_0 = 0xFF; - Smallest_1 = 0xFF; - Largest_0 = 0; - Largest_1 = 0; - - if (index == 0x12) - ecc_reg = 1; - - for (i = 0; i < 8; i+=2) { - if (pDCTstat->DIMMValid & (1 << i)) { - val = Get_NB32_index_wait(dev, index_reg, index); - byte = val & 0xFF; - if (byte < Smallest_0) - Smallest_0 = byte; - if (byte > Largest_0) - Largest_0 = byte; - if (!(ecc_reg)) { - byte = (val >> 16) & 0xFF; - if (byte < Smallest_1) - Smallest_1 = byte; - if (byte > Largest_1) - Largest_1 = byte; - } - } - index += 3; - } /* while ++i */ - - /* check if total DqsRcvEn delay difference between any - two DIMMs is less than half of a MEMCLK */ - if ((Largest_0 - Smallest_0) > 31) - return 1; - if (!(ecc_reg)) - if ((Largest_1 - Smallest_1) > 31) - return 1; - return 0; -} - - -static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - u32 dev, 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, index_reg, 0x10); - Largest = val & 0xFF; - Smallest = (val >> 8) & 0xFF; - - /* DqsRcvEn byte 3,2 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, 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, 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, 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, index_reg, 0x12); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - - pDCTstat->DqsRcvEnGrossL = Largest; - return Largest - Smallest; -} - - -static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg) -{ - u8 Smallest, Largest; - u32 val; - u8 byte, bytex; - - /* The largest WrDatGrossDlyByte of any DIMM minus the - WrDatGrossDlyByte of any other DIMM is equal to CGDD */ - 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; - 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; - - // FIXME: Add Cx support. - - pDCTstat->WrDatGrossH = Largest; - return Largest - Smallest; -} - -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, 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(dev, 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(dev, 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(dev, 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_FinalMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - print_t("\tmct_FinalMCT_D: Clr Cl, Wb\n"); - - - /* ClrClToNB_D postponed until we're done executing from ROM */ - mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat); -} - - -static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - print_t("\tmct_InitialMCT_D: Set Cl, Wb\n"); - mct_SetClToNB_D(pMCTstat, pDCTstat); - mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat); -} - - -static u32 mct_NodePresent_D(void) -{ - u32 val; - 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(dev, reg); - val &= ~(1<<LegacyBiosMode); - Set_NB32(dev, 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 + 0x100 * dct; - u8 cs; - u32 index; - u16 word; - - /* Tri-state unused chipselects when motherboard - termination is available */ - - // FIXME: skip for Ax - - word = pDCTstat->CSPresent; - if (pDCTstat->Status & (1 << SB_Registered)) { - for (cs = 0; cs < 8; cs++) { - if (word & (1 << cs)) { - if (!(cs & 1)) - word |= 1 << (cs + 1); - } - } - } - word = (~word) & 0xFF; - index = 0x0c; - val = Get_NB32_index_wait(dev, index_reg, index); - val |= word; - Set_NB32_index_wait(dev, index_reg, index, val); -} - - -#ifdef UNUSED_CODE -static void SetCKETriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98 + 0x100 * dct; - u8 cs; - u32 index; - u16 word; - - /* Tri-state unused CKEs when motherboard termination is available */ - - // FIXME: skip for Ax - - dev = pDCTstat->dev_dct; - word = 0x101; - for (cs = 0; cs < 8; cs++) { - if (pDCTstat->CSPresent & (1 << cs)) { - if (!(cs & 1)) - word &= 0xFF00; - else - word &= 0x00FF; - } - } - - index = 0x0c; - val = Get_NB32_index_wait(dev, index_reg, index); - if ((word & 0x00FF) == 1) - val |= 1 << 12; - else - val &= ~(1 << 12); - - if ((word >> 8) == 1) - val |= 1 << 13; - else - val &= ~(1 << 13); - - Set_NB32_index_wait(dev, index_reg, index, val); -} -#endif - -static void SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98 + 0x100 * dct; - u8 cs; - u32 index; - u8 odt; - u8 max_dimms; - - // FIXME: skip for Ax - - dev = pDCTstat->dev_dct; - - /* Tri-state unused ODTs when motherboard termination is available */ - max_dimms = (u8) mctGet_NVbits(NV_MAX_DIMMS); - odt = 0x0F; /* tristate all the pins then clear the used ones. */ - - for (cs = 0; cs < 8; cs += 2) { - if (pDCTstat->CSPresent & (1 << cs)) { - odt &= ~(1 << (cs / 2)); - - /* if quad-rank capable platform clear additional pins */ - if (max_dimms != MAX_CS_SUPPORTED) { - if (pDCTstat->CSPresent & (1 << (cs + 1))) - odt &= ~(4 << (cs / 2)); - } - } - } - - index = 0x0C; - val = Get_NB32_index_wait(dev, index_reg, index); - val |= (odt << 8); - Set_NB32_index_wait(dev, index_reg, index, val); - -} - - -static void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - u32 val; - u32 valx = 0; - u32 dword; - const u8 *p; - - val = Get_NB32_index_wait(dev, index_reg, 0x00); - dword = 0; - for (i = 0; i < 6; i++) { - switch (i) { - case 0: - case 4: - p = Table_Comp_Rise_Slew_15x; - valx = p[(val >> 16) & 3]; - break; - case 1: - case 5: - p = Table_Comp_Fall_Slew_15x; - valx = p[(val >> 16) & 3]; - break; - case 2: - p = Table_Comp_Rise_Slew_20x; - valx = p[(val >> 8) & 3]; - break; - case 3: - p = Table_Comp_Fall_Slew_20x; - valx = p[(val >> 8) & 3]; - break; - - } - dword |= valx << (5 * i); - } - - /* Override/Exception */ - if (!pDCTstat->GangedMode) { - i = 0; /* use i for the dct setting required */ - if (pDCTstat->MAdimms[0] < 4) - i = 1; - if (((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) && (pDCTstat->MAdimms[i] == 4)) { - dword &= 0xF18FFF18; - index_reg = 0x98; /* force dct = 0 */ - } - } - - Set_NB32_index_wait(dev, index_reg, 0x0a, dword); -} - - -static void WaitRoutine_D(u32 time) -{ - while (time) { - _EXECFENCE; - time--; - } -} - - -static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - 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(dev, reg); - - //FIXME: check for Cx - if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat)) - val |= (1 << EarlyArbEn); - - Set_NB32(dev, reg, val); - -} - - -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(dev, reg); - if (!(val & (1 << MemClkFreqVal))) - val = Get_NB32(dev, reg * 0x100); /* 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) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - - /* Initialize Data structures by clearing all entries to 0 */ - memset(pMCTstat, 0x00, sizeof(*pMCTstat)); - - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - - /* Clear all entries except persistentData */ - memset(pDCTstat, 0x00, sizeof(*pDCTstat) - sizeof(pDCTstat->persistentData)); - } -} - - -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 i; - u32 reg_off; - u32 dev = pDCTstat->dev_dct; - - // FIXME: skip for Ax - if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533MHz - for (i = 0; i < 2; i++) { - reg_off = 0x100 * i; - Set_NB32(dev, 0x98 + reg_off, 0x0D000030); - Set_NB32(dev, 0x9C + reg_off, 0x00000806); - Set_NB32(dev, 0x98 + reg_off, 0x4D040F30); - } - } -} - - -void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 *dqs_pos) -{ - // FIXME: Skip for Ax - if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533MHz - *dqs_pos = 32; - } -} - -static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct) -{ - u32 reg_off = 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */ - if (pDCTstat->LogicalCPUID & (AMD_DA_C2 | AMD_RB_C3)) { - Set_NB32(dev, 0x9C + reg_off, 0x7D0); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006); - Set_NB32(dev, 0x9C + reg_off, 0x190); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007); - } - - return DramConfigLo | /* DisDllShutdownSR */ 1 << 27; -} - -static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg_off = 0x100 * dct; - u32 dev = pDCTstat->dev_dct, val; - - /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */ - if (pDCTstat->LogicalCPUID & (AMD_DA_C2 | AMD_RB_C3)) { - Set_NB32(dev, 0x9C + reg_off, 0x1C); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006); - Set_NB32(dev, 0x9C + reg_off, 0x13D); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007); - - val = Get_NB32(dev, 0x90 + reg_off); - val &= ~(1 << 27/* DisDllShutdownSR */); - Set_NB32(dev, 0x90 + reg_off, val); - } -} - -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 mct_SetDramConfigHi_D(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 + 0x100 * dct; - u32 index; - - u32 val; - - index = 0x08; - val = Get_NB32_index_wait(dev, index_reg, index); - Set_NB32_index_wait(dev, index_reg, index, val | (1 << DisAutoComp)); - - //FIXME: check for Bx Cx CPU - // if Ax mct_SetDramConfigHi_Samp_D - - /* errata#177 */ - index = 0x4D014F00; /* F2x[1, 0]9C_x[D0FFFFF:D000000] DRAM Phy Debug Registers */ - index |= 1 << DctAccessWrite; - val = 0; - Set_NB32_index_wait(dev, index_reg, index, val); - - Set_NB32(dev, 0x94 + 0x100 * dct, DramConfigHi); - - index = 0x08; - val = Get_NB32_index_wait(dev, index_reg, index); - Set_NB32_index_wait(dev, index_reg, index, val & (~(1 << DisAutoComp))); -} - -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - 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 DDR2 training. - */ - - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - mct_BeforeDQSTrain_Samp_D(pMCTstat, pDCTstat); - mct_ResetDLL_D(pMCTstat, pDCTstat, 0); - mct_ResetDLL_D(pMCTstat, pDCTstat, 1); - } - } -} - -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Receiver; - u32 dev = pDCTstat->dev_dct; - u32 reg_off = 0x100 * dct; - u32 addr; - u32 lo, hi; - u8 wrap32dis = 0; - u8 valid = 0; - - /* Skip reset DLL for B3 */ - if (pDCTstat->LogicalCPUID & AMD_DR_B3) { - return; - } - - 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 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(dev, 0x98 + reg_off, 0x4D080F0C, 0x00008000); - mct_Wait(80); /* wait >= 300ns */ - - /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */ - Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 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); - } -} - -#ifdef UNUSED_CODE -static void mct_SetupSync_D(struct MCTStatStruc *pMCTstat, - 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 |= ChSetupSync; - Set_NB32(dev, 0x78, val); - } -} -#endif - -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) { - - u32 val; - u32 reg_off = 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) { - 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(dev, 0x90 + reg_off); - val &= ~(1 << Width128); /* Program Width128 = 0 */ - Set_NB32(dev, 0x90 + reg_off, val); - - val = Get_NB32_index_wait(dev, 0x98 + reg_off, 0x05); /* Perform dummy CSR read to F2x09C_x05 */ - - if (pDCTstat->GangedMode) { - val = Get_NB32(dev, 0x90 + reg_off); - val |= 1 << Width128; /* Program Width128 = 0 */ - Set_NB32(dev, 0x90 + reg_off, 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 - */ |