f29953a5c60097c36751fe2aa67d942f4c9789b9
[coreboot.git] / src / northbridge / amd / amdmct / mct / mct_d.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 /* Description: Main memory controller system configuration for DDR 2 */
21
22
23 /* KNOWN ISSUES - ERRATA
24  *
25  * Trtp is not calculated correctly when the controller is in 64-bit mode, it
26  * is 1 busclock off.   No fix planned.  The controller is not ordinarily in
27  * 64-bit mode.
28  *
29  * 32 Byte burst not supported. No fix planned. The controller is not
30  * ordinarily in 64-bit mode.
31  *
32  * Trc precision does not use extra Jedec defined fractional component.
33  * InsteadTrc (course) is rounded up to nearest 1 ns.
34  *
35  * Mini and Micro DIMM not supported. Only RDIMM, UDIMM, SO-DIMM defined types
36  * supported.
37  */
38
39 static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat,
40                                         struct DCTStatStruc *pDCTstatA);
41 static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
42                                 struct DCTStatStruc *pDCTstatA);
43 static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
44                                         struct DCTStatStruc *pDCTstatA);
45 static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat,
46                                 struct DCTStatStruc *pDCTstatA);
47 static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
48                                 struct DCTStatStruc *pDCTstatA);
49 static void MCTMemClr_D(struct MCTStatStruc *pMCTstat,
50                                 struct DCTStatStruc *pDCTstatA);
51 static void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
52                                 struct DCTStatStruc *pDCTstat);
53 static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
54                                 struct DCTStatStruc *pDCTstat);
55 static void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
56                                 struct DCTStatStruc *pDCTstatA);
57 static u8 NodePresent_D(u8 Node);
58 static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
59                                 struct DCTStatStruc *pDCTstatA);
60 static void StartupDCT_D(struct MCTStatStruc *pMCTstat,
61                                 struct DCTStatStruc *pDCTstat, u8 dct);
62 static void ClearDCT_D(struct MCTStatStruc *pMCTstat,
63                         struct DCTStatStruc *pDCTstat, u8 dct);
64 static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
65                                 struct DCTStatStruc *pDCTstat, u8 dct);
66 static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
67                                 struct DCTStatStruc *pDCTstat);
68 static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
69                         struct DCTStatStruc *pDCTstat, u8 dct);
70 static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
71                                 struct DCTStatStruc *pDCTstat, u8 dct);
72 static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat,
73                                 struct DCTStatStruc *pDCTstat, u8 dct);
74 static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat,
75                                 struct DCTStatStruc *pDCTstat, u8 dct);
76 static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
77                                 struct DCTStatStruc *pDCTstat, u8 dct);
78 static u8 Get_DefTrc_k_D(u8 k);
79 static u16 Get_40Tk_D(u8 k);
80 static u16 Get_Fk_D(u8 k);
81 static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat, u8 i, u8 j, u8 k);
82 static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat,
83                                 struct DCTStatStruc *pDCTstat, int j, int k);
84 static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i);
85 static void mct_initDCT(struct MCTStatStruc *pMCTstat,
86                                 struct DCTStatStruc *pDCTstat);
87 static void mct_DramInit(struct MCTStatStruc *pMCTstat,
88                                 struct DCTStatStruc *pDCTstat, u8 dct);
89 static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
90                                         struct DCTStatStruc *pDCTstat, u8 dct);
91 static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat);
92 static void Get_Trdrd(struct MCTStatStruc *pMCTstat,
93                         struct DCTStatStruc *pDCTstat, u8 dct);
94 static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat,
95                                 struct DCTStatStruc *pDCTstat, u8 dct);
96 static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,\
97                                         struct DCTStatStruc *pDCTstat, u8 dct);
98 static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat,
99                                         struct DCTStatStruc *pDCTstat, u8 dct);
100 static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat,
101                                         struct DCTStatStruc *pDCTstat, u8 dct);
102 static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
103                                 struct DCTStatStruc *pDCTstat, u8 dct);
104 static void Get_Twrwr(struct MCTStatStruc *pMCTstat,
105                         struct DCTStatStruc *pDCTstat, u8 dct);
106 static void Get_Twrrd(struct MCTStatStruc *pMCTstat,
107                         struct DCTStatStruc *pDCTstat, u8 dct);
108 static void Get_TrwtTO(struct MCTStatStruc *pMCTstat,
109                         struct DCTStatStruc *pDCTstat, u8 dct);
110 static void Get_TrwtWB(struct MCTStatStruc *pMCTstat,
111                         struct DCTStatStruc *pDCTstat);
112 static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat, u8 dct,
113                                 u32 dev, u32 index_reg, u32 index);
114 static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
115                                         u32 dev, u32 index_reg);
116 static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, u8 dct,
117                                         u32 dev, u32 index_reg);
118 static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
119                                 u32 dev, u32 index_reg, u32 index);
120 static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
121                                 struct DCTStatStruc *pDCTstat);
122 static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, u8 dct,
123                                 u32 dev, u32 index_reg, u32 index);
124 static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat,
125                                 struct DCTStatStruc *pDCTstat);
126 static void mct_init(struct MCTStatStruc *pMCTstat,
127                         struct DCTStatStruc *pDCTstat);
128 static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat,
129                                 struct DCTStatStruc *pDCTstat);
130 static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat,
131                                 struct DCTStatStruc *pDCTstatA);
132 static void SetCSTriState(struct MCTStatStruc *pMCTstat,
133                                 struct DCTStatStruc *pDCTstat, u8 dct);
134 static void SetODTTriState(struct MCTStatStruc *pMCTstat,
135                                 struct DCTStatStruc *pDCTstat, u8 dct);
136 static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
137                                         struct DCTStatStruc *pDCTstat, u8 dct);
138 static u32 mct_NodePresent_D(void);
139 static void WaitRoutine_D(u32 time);
140 static void mct_OtherTiming(struct MCTStatStruc *pMCTstat,
141                                 struct DCTStatStruc *pDCTstatA);
142 static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat,
143                                         struct DCTStatStruc *pDCTstatA);
144 static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
145                                         struct DCTStatStruc *pDCTstat);
146 static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
147                                         struct DCTStatStruc *pDCTstat);
148 void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat,
149                         struct DCTStatStruc *pDCTstat);
150 static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
151                                         struct DCTStatStruc *pDCTstat);
152 void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat,
153                                         struct DCTStatStruc *pDCTstat);
154 static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat,
155                                         struct DCTStatStruc *pDCTstatA);
156 static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct);
157 static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
158                                         struct DCTStatStruc *pDCTstat, u8 dct);
159
160
161 /*See mctAutoInitMCT header for index relationships to CL and T*/
162 static const u16 Table_F_k[]    = {00,200,266,333,400,533 };
163 static const u8 Table_T_k[]     = {0x00,0x50,0x3D,0x30,0x25, 0x18 };
164 static const u8 Table_CL2_j[]   = {0x04,0x08,0x10,0x20,0x40, 0x80 };
165 static const u8 Tab_defTrc_k[]  = {0x0,0x41,0x3C,0x3C,0x3A, 0x3A };
166 static const u16 Tab_40T_k[]    = {00,200,150,120,100,75 };
167 static const u8 Tab_TrefT_k[]   = {00,0,1,1,2,2,3,4,5,6,0,0};
168 static const u8 Tab_BankAddr[]  = {0x0,0x08,0x09,0x10,0x0C,0x0D,0x11,0x0E,0x15,0x16,0x0F,0x17};
169 static const u8 Tab_tCL_j[]     = {0,2,3,4,5};
170 static const u8 Tab_1KTfawT_k[] = {00,8,10,13,14,20};
171 static const u8 Tab_2KTfawT_k[] = {00,10,14,17,18,24};
172 static const u8 Tab_L1CLKDis[]  = {8,8,6,4,2,0,8,8};
173 static const u8 Tab_M2CLKDis[]  = {2,0,8,8,2,0,2,0};
174 static const u8 Tab_S1CLKDis[]  = {8,0,8,8,8,0,8,0};
175 static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF};
176 static const u8 Table_Comp_Rise_Slew_15x[] = {7, 7, 3, 2, 0xFF};
177 static const u8 Table_Comp_Fall_Slew_20x[] = {7, 5, 3, 2, 0xFF};
178 static const u8 Table_Comp_Fall_Slew_15x[] = {7, 7, 5, 3, 0xFF};
179
180 void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
181                         struct DCTStatStruc *pDCTstatA)
182 {
183         /*
184          * Memory may be mapped contiguously all the way up to 4GB (depending
185          * on setup options). It is the responsibility of PCI subsystem to
186          * create an uncacheable IO region below 4GB and to adjust TOP_MEM
187          * downward prior to any IO mapping or accesses. It is the same
188          * responsibility of the CPU sub-system prior toaccessing LAPIC.
189          *
190          * Slot Number is an external convention, and is determined by OEM with
191          * accompanying silk screening.  OEM may choose to use Slot number
192          * convention which is consistent with DIMM number conventions.
193          * All AMD engineering
194          * platforms do.
195          *
196          * Run-Time Requirements:
197          * 1. Complete Hypertransport Bus Configuration
198          * 2. SMBus Controller Initialized
199          * 3. Checksummed or Valid NVRAM bits
200          * 4. MCG_CTL=-1, MC4_CTL_EN=0 for all CPUs
201          * 5. MCi_STS from shutdown/warm reset recorded (if desired) prior to
202          *     entry
203          * 6. All var MTRRs reset to zero
204          * 7. State of NB_CFG.DisDatMsk set properly on all CPUs
205          * 8. All CPUs at 2Ghz Speed (unless DQS training is not installed).
206          * 9. All cHT links at max Speed/Width (unless DQS training is not
207          *     installed).
208          *
209          *
210          * Global relationship between index values and item values:
211          * j CL(j)       k   F(k)
212          * --------------------------
213          * 0 2.0         -   -
214          * 1 3.0         1   200 Mhz
215          * 2 4.0         2   266 Mhz
216          * 3 5.0         3   333 Mhz
217          * 4 6.0         4   400 Mhz
218          * 5 7.0         5   533 Mhz
219          */
220         u8 Node, NodesWmem;
221         u32 node_sys_base;
222
223 restartinit:
224         mctInitMemGPIOs_A_D();          /* Set any required GPIOs*/
225         NodesWmem = 0;
226         node_sys_base = 0;
227         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
228                 struct DCTStatStruc *pDCTstat;
229                 pDCTstat = pDCTstatA + Node;
230                 pDCTstat->Node_ID = Node;
231                 pDCTstat->dev_host = PA_HOST(Node);
232                 pDCTstat->dev_map = PA_MAP(Node);
233                 pDCTstat->dev_dct = PA_DCT(Node);
234                 pDCTstat->dev_nbmisc = PA_NBMISC(Node);
235                 pDCTstat->NodeSysBase = node_sys_base;
236
237                 print_tx("mctAutoInitMCT_D: mct_init Node ", Node);
238                 mct_init(pMCTstat, pDCTstat);
239                 mctNodeIDDebugPort_D();
240                 pDCTstat->NodePresent = NodePresent_D(Node);
241                 if (pDCTstat->NodePresent) {            /* See if Node is there*/
242                         print_t("mctAutoInitMCT_D: clear_legacy_Mode\n");
243                         clear_legacy_Mode(pMCTstat, pDCTstat);
244                         pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);
245
246                         print_t("mctAutoInitMCT_D: mct_InitialMCT_D\n");
247                         mct_InitialMCT_D(pMCTstat, pDCTstat);
248
249                         print_t("mctAutoInitMCT_D: mctSMBhub_Init\n");
250                         mctSMBhub_Init(Node);           /* Switch SMBUS crossbar to proper node*/
251
252                         print_t("mctAutoInitMCT_D: mct_initDCT\n");
253                         mct_initDCT(pMCTstat, pDCTstat);
254                         if (pDCTstat->ErrCode == SC_FatalErr) {
255                                 goto fatalexit;         /* any fatal errors?*/
256                         } else if (pDCTstat->ErrCode < SC_StopError) {
257                                 NodesWmem++;
258                         }
259                 }       /* if Node present */
260                 node_sys_base = pDCTstat->NodeSysBase;
261                 node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
262         }
263         if (NodesWmem == 0) {
264                 print_debug("No Nodes?!\n");
265                 goto fatalexit;
266         }
267
268         print_t("mctAutoInitMCT_D: SyncDCTsReady_D\n");
269         SyncDCTsReady_D(pMCTstat, pDCTstatA);   /* Make sure DCTs are ready for accesses.*/
270
271         print_t("mctAutoInitMCT_D: HTMemMapInit_D\n");
272         HTMemMapInit_D(pMCTstat, pDCTstatA);    /* Map local memory into system address space.*/
273         mctHookAfterHTMap();
274
275         print_t("mctAutoInitMCT_D: CPUMemTyping_D\n");
276         CPUMemTyping_D(pMCTstat, pDCTstatA);    /* Map dram into WB/UC CPU cacheability */
277         mctHookAfterCPU();                      /* Setup external northbridge(s) */
278
279         print_t("mctAutoInitMCT_D: DQSTiming_D\n");
280         DQSTiming_D(pMCTstat, pDCTstatA);       /* Get Receiver Enable and DQS signal timing*/
281
282         print_t("mctAutoInitMCT_D: UMAMemTyping_D\n");
283         UMAMemTyping_D(pMCTstat, pDCTstatA);    /* Fix up for UMA sizing */
284
285         print_t("mctAutoInitMCT_D: :OtherTiming\n");
286         mct_OtherTiming(pMCTstat, pDCTstatA);
287
288         if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/
289                 goto restartinit;
290         }
291
292         InterleaveNodes_D(pMCTstat, pDCTstatA);
293         InterleaveChannels_D(pMCTstat, pDCTstatA);
294
295         print_t("mctAutoInitMCT_D: ECCInit_D\n");
296         if (ECCInit_D(pMCTstat, pDCTstatA)) {           /* Setup ECC control and ECC check-bits*/
297                 print_t("mctAutoInitMCT_D: MCTMemClr_D\n");
298                 MCTMemClr_D(pMCTstat,pDCTstatA);
299         }
300
301         mct_FinalMCT_D(pMCTstat, (pDCTstatA + 0) );     // Node 0
302         print_t("All Done\n");
303         return;
304
305 fatalexit:
306         die("mct_d: fatalexit");
307 }
308
309
310 static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat,
311                                         struct DCTStatStruc *pDCTstatA)
312 {
313         u8 ret;
314
315         if (mctGet_NVbits(NV_CS_SpareCTL)) {
316                 if (MCT_DIMM_SPARE_NO_WARM) {
317                         /* Do no warm-reset DIMM spare */
318                         if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
319                                 LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA);
320                                 ret = 0;
321                         } else {
322                                 mct_ResetDataStruct_D(pMCTstat, pDCTstatA);
323                                 pMCTstat->GStatus |= 1 << GSB_EnDIMMSpareNW;
324                                 ret = 1;
325                         }
326                 } else {
327                         /* Do warm-reset DIMM spare */
328                         if (mctGet_NVbits(NV_DQSTrainCTL))
329                                 mctWarmReset_D();
330                         ret = 0;
331                 }
332
333
334         } else {
335                 ret = 0;
336         }
337
338         return ret;
339 }
340
341
342 static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
343                                 struct DCTStatStruc *pDCTstatA)
344 {
345         u8 nv_DQSTrainCTL;
346
347         if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
348                 return;
349         }
350         nv_DQSTrainCTL = mctGet_NVbits(NV_DQSTrainCTL);
351         /* FIXME: BOZO- DQS training every time*/
352         nv_DQSTrainCTL = 1;
353
354         print_t("DQSTiming_D: mct_BeforeDQSTrain_D:\n");
355         mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);;
356         phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
357
358         if (nv_DQSTrainCTL) {
359                 mctHookBeforeAnyTraining();
360
361                 print_t("DQSTiming_D: TrainReceiverEn_D FirstPass:\n");
362                 TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
363
364                 print_t("DQSTiming_D: mct_TrainDQSPos_D\n");
365                 mct_TrainDQSPos_D(pMCTstat, pDCTstatA);
366
367                 // Second Pass never used for Barcelona!
368                 //print_t("DQSTiming_D: TrainReceiverEn_D SecondPass:\n");
369                 //TrainReceiverEn_D(pMCTstat, pDCTstatA, SecondPass);
370
371                 print_t("DQSTiming_D: mctSetEccDQSRcvrEn_D\n");
372                 mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA);
373
374                 print_t("DQSTiming_D: TrainMaxReadLatency_D\n");
375 //FIXME - currently uses calculated value               TrainMaxReadLatency_D(pMCTstat, pDCTstatA);
376                 mctHookAfterAnyTraining();
377                 mctSaveDQSSigTmg_D();
378
379                 print_t("DQSTiming_D: mct_EndDQSTraining_D\n");
380                 mct_EndDQSTraining_D(pMCTstat, pDCTstatA);
381
382                 print_t("DQSTiming_D: MCTMemClr_D\n");
383                 MCTMemClr_D(pMCTstat, pDCTstatA);
384         } else {
385                 mctGetDQSSigTmg_D();    /* get values into data structure */
386                 LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA);       /* load values into registers.*/
387                 //mctDoWarmResetMemClr_D();
388                 MCTMemClr_D(pMCTstat, pDCTstatA);
389         }
390 }
391
392
393 static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
394                                         struct DCTStatStruc *pDCTstatA)
395 {
396         u8 Node, Receiver, Channel, Dir, DIMM;
397         u32 dev;
398         u32 index_reg;
399         u32 reg;
400         u32 index;
401         u32 val;
402
403
404         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
405                 struct DCTStatStruc *pDCTstat;
406                 pDCTstat = pDCTstatA + Node;
407
408                 if (pDCTstat->DCTSysLimit) {
409                         dev = pDCTstat->dev_dct;
410                         for (Channel = 0;Channel < 2; Channel++) {
411                                 /* there are four receiver pairs,
412                                    loosely associated with chipselects.*/
413                                 index_reg = 0x98 + Channel * 0x100;
414                                 for (Receiver = 0; Receiver < 8; Receiver += 2) {
415                                         /* Set Receiver Enable Values */
416                                         mct_SetRcvrEnDly_D(pDCTstat,
417                                                 0, /* RcvrEnDly */
418                                                 1, /* FinalValue, From stack */
419                                                 Channel,
420                                                 Receiver,
421                                                 dev, index_reg,
422                                                 (Receiver >> 1) * 3 + 0x10, /* Addl_Index */
423                                                 2); /* Pass Second Pass ? */
424
425                                 }
426                         }
427                         for (Channel = 0; Channel<2; Channel++) {
428                                 SetEccDQSRcvrEn_D(pDCTstat, Channel);
429                         }
430
431                         for (Channel = 0; Channel < 2; Channel++) {
432                                 u8 *p;
433                                 index_reg = 0x98 + Channel * 0x100;
434
435                                 /* NOTE:
436                                  * when 400, 533, 667, it will support dimm0/1/2/3,
437                                  * and set conf for dimm0, hw will copy to dimm1/2/3
438                                  * set for dimm1, hw will copy to dimm3
439                                  * Rev A/B only support DIMM0/1 when 800Mhz and above
440                                  *   + 0x100 to next dimm
441                                  * Rev C support DIMM0/1/2/3 when 800Mhz and above
442                                  *   + 0x100 to next dimm
443                                 */
444                                 for (DIMM = 0; DIMM < 2; DIMM++) {
445                                         if (DIMM==0) {
446                                                 index = 0;      /* CHA Write Data Timing Low */
447                                         } else {
448                                                 if (pDCTstat->Speed >= 4) {
449                                                         index = 0x100 * DIMM;
450                                                 } else {
451                                                         break;
452                                                 }
453                                         }
454                                         for (Dir=0;Dir<2;Dir++) {//RD/WR
455                                                 p = pDCTstat->CH_D_DIR_B_DQS[Channel][DIMM][Dir];
456                                                 val = stream_to_int(p); /* CHA Read Data Timing High */
457                                                 Set_NB32_index_wait(dev, index_reg, index+1, val);
458                                                 val = stream_to_int(p+4); /* CHA Write Data Timing High */
459                                                 Set_NB32_index_wait(dev, index_reg, index+2, val);
460                                                 val = *(p+8); /* CHA Write ECC Timing */
461                                                 Set_NB32_index_wait(dev, index_reg, index+3, val);
462                                                 index += 4;
463                                         }
464                                 }
465                         }
466
467                         for (Channel = 0; Channel<2; Channel++) {
468                                 reg = 0x78 + Channel * 0x100;
469                                 val = Get_NB32(dev, reg);
470                                 val &= ~(0x3ff<<22);
471                                 val |= ((u32) pDCTstat->CH_MaxRdLat[Channel] << 22);
472                                 val &= ~(1<<DqsRcvEnTrain);
473                                 Set_NB32(dev, reg, val);        /* program MaxRdLatency to correspond with current delay*/
474                         }
475                 }
476         }
477 }
478
479
480 static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat,
481                                 struct DCTStatStruc *pDCTstatA)
482 {
483         /* Clear MC4_STS for all Nodes in the system.  This is required in some
484          * circumstances to clear left over garbage from cold reset, shutdown,
485          * or normal ECC memory conditioning.
486          */
487
488         //FIXME: this function depends on pDCTstat Array ( with Node id ) - Is this really a problem?
489
490         u32 dev;
491         u8 Node;
492
493         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
494                 struct DCTStatStruc *pDCTstat;
495                 pDCTstat = pDCTstatA + Node;
496
497                 if (pDCTstat->NodePresent) {
498                         dev = pDCTstat->dev_nbmisc;
499                         /*MCA NB Status Low (alias to MC4_STS[31:0] */
500                         Set_NB32(dev, 0x48, 0);
501                         /* MCA NB Status High (alias to MC4_STS[63:32] */
502                         Set_NB32(dev, 0x4C, 0);
503                 }
504         }
505 }
506
507
508 static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
509                                 struct DCTStatStruc *pDCTstatA)
510 {
511         u8 Node;
512         u32 NextBase, BottomIO;
513         u8 _MemHoleRemap, DramHoleBase, DramHoleOffset;
514         u32 HoleSize, DramSelBaseAddr;
515
516         u32 val;
517         u32 base;
518         u32 limit;
519         u32 dev, devx;
520         struct DCTStatStruc *pDCTstat;
521
522         _MemHoleRemap = mctGet_NVbits(NV_MemHole);
523
524         if (pMCTstat->HoleBase == 0) {
525                 DramHoleBase = mctGet_NVbits(NV_BottomIO);
526         } else {
527                 DramHoleBase = pMCTstat->HoleBase >> (24-8);
528         }
529
530         BottomIO = DramHoleBase << (24-8);
531
532         NextBase = 0;
533         pDCTstat = pDCTstatA + 0;
534         dev = pDCTstat->dev_map;
535
536
537         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
538                 pDCTstat = pDCTstatA + Node;
539                 devx = pDCTstat->dev_map;
540                 DramSelBaseAddr = 0;
541                 pDCTstat = pDCTstatA + Node;
542                 if (!pDCTstat->GangedMode) {
543                         DramSelBaseAddr = pDCTstat->NodeSysLimit - pDCTstat->DCTSysLimit;
544                         /*In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */
545                         val = pDCTstat->NodeSysLimit;
546                         if ((val & 0xFF) == 0xFE) {
547                                 DramSelBaseAddr++;
548                                 val++;
549                         }
550                         pDCTstat->DCTSysLimit = val;
551                 }
552
553                 base  = pDCTstat->DCTSysBase;
554                 limit = pDCTstat->DCTSysLimit;
555                 if (limit > base) {
556                         base  += NextBase;
557                         limit += NextBase;
558                         DramSelBaseAddr += NextBase;
559                         printk_debug(" Node: %02x  base: %02x  limit: %02x  BottomIO: %02x\n", Node, base, limit, BottomIO);
560
561                         if (_MemHoleRemap) {
562                                 if ((base < BottomIO) && (limit >= BottomIO)) {
563                                         /* HW Dram Remap */
564                                         pDCTstat->Status |= 1 << SB_HWHole;
565                                         pMCTstat->GStatus |= 1 << GSB_HWHole;
566                                         pDCTstat->DCTSysBase = base;
567                                         pDCTstat->DCTSysLimit = limit;
568                                         pDCTstat->DCTHoleBase = BottomIO;
569                                         pMCTstat->HoleBase = BottomIO;
570                                         HoleSize = _4GB_RJ8 - BottomIO; /* HoleSize[39:8] */
571                                         if ((DramSelBaseAddr > 0) && (DramSelBaseAddr < BottomIO))
572                                                 base = DramSelBaseAddr;
573                                         val = ((base + HoleSize) >> (24-8)) & 0xFF;
574                                         DramHoleOffset = val;
575                                         val <<= 8; /* shl 16, rol 24 */
576                                         val |= DramHoleBase << 24;
577                                         val |= 1  << DramHoleValid;
578                                         Set_NB32(devx, 0xF0, val); /* Dram Hole Address Reg */
579                                         pDCTstat->DCTSysLimit += HoleSize;
580                                         base = pDCTstat->DCTSysBase;
581                                         limit = pDCTstat->DCTSysLimit;
582                                 } else if (base == BottomIO) {
583                                         /* SW Node Hoist */
584                                         pMCTstat->GStatus |= 1<<GSB_SpIntRemapHole;
585                                         pDCTstat->Status |= 1<<SB_SWNodeHole;
586                                         pMCTstat->GStatus |= 1<<GSB_SoftHole;
587                                         pMCTstat->HoleBase = base;
588                                         limit -= base;
589                                         base = _4GB_RJ8;
590                                         limit += base;
591                                         pDCTstat->DCTSysBase = base;
592                                         pDCTstat->DCTSysLimit = limit;
593                                 } else {
594                                         /* No Remapping.  Normal Contiguous mapping */
595                                         pDCTstat->DCTSysBase = base;
596                                         pDCTstat->DCTSysLimit = limit;
597                                 }
598                         } else {
599                                 /*No Remapping.  Normal Contiguous mapping*/
600                                 pDCTstat->DCTSysBase = base;
601                                 pDCTstat->DCTSysLimit = limit;
602                         }
603                         base |= 3;              /* set WE,RE fields*/
604                         pMCTstat->SysLimit = limit;
605                 }
606                 Set_NB32(dev, 0x40 + (Node << 3), base); /* [Node] + Dram Base 0 */
607
608                 /* if Node limit > 1GB then set it to 1GB boundary for each node */
609                 if ((mctSetNodeBoundary_D()) && (limit > 0x00400000)) {
610                         limit++;
611                         limit &= 0xFFC00000;
612                         limit--;
613                 }
614                 val = limit & 0xFFFF0000;
615                 val |= Node;
616                 Set_NB32(dev, 0x44 + (Node << 3), val); /* set DstNode */
617
618                 limit = pDCTstat->DCTSysLimit;
619                 if (limit) {
620                         NextBase = (limit & 0xFFFF0000) + 0x10000;
621                         if ((mctSetNodeBoundary_D()) && (NextBase > 0x00400000)) {
622                                 NextBase++;
623                                 NextBase &= 0xFFC00000;
624                                 NextBase--;
625                         }
626                 }
627         }
628
629         /* Copy dram map from Node 0 to Node 1-7 */
630         for (Node = 1; Node < MAX_NODES_SUPPORTED; Node++) {
631                 u32 reg;
632                 pDCTstat = pDCTstatA + Node;
633                 devx = pDCTstat->dev_map;
634
635                 if (pDCTstat->NodePresent) {
636                 printk_debug(" Copy dram map from Node 0 to Node %02x \n", Node);
637                         reg = 0x40;             /*Dram Base 0*/
638                         do {
639                                 val = Get_NB32(dev, reg);
640                                 Set_NB32(devx, reg, val);
641                                 reg += 4;
642                         } while ( reg < 0x80);
643                 } else {
644                         break;                  /* stop at first absent Node */
645                 }
646         }
647
648         /*Copy dram map to F1x120/124*/
649         mct_HTMemMapExt(pMCTstat, pDCTstatA);
650 }
651
652
653 static void MCTMemClr_D(struct MCTStatStruc *pMCTstat,
654                                 struct DCTStatStruc *pDCTstatA)
655 {
656
657         /* Initiates a memory clear operation for all node. The mem clr
658          * is done in paralel. After the memclr is complete, all processors
659          * status are checked to ensure that memclr has completed.
660          */
661         u8 Node;
662         struct DCTStatStruc *pDCTstat;
663
664         if (!mctGet_NVbits(NV_DQSTrainCTL)){
665                 // FIXME: callback to wrapper: mctDoWarmResetMemClr_D
666         } else {        // NV_DQSTrainCTL == 1
667                 for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
668                         pDCTstat = pDCTstatA + Node;
669
670                         if (pDCTstat->NodePresent) {
671                                 DCTMemClr_Init_D(pMCTstat, pDCTstat);
672                         }
673                 }
674                 for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
675                         pDCTstat = pDCTstatA + Node;
676
677                         if (pDCTstat->NodePresent) {
678                                 DCTMemClr_Sync_D(pMCTstat, pDCTstat);
679                         }
680                 }
681         }
682 }
683
684
685 static void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
686                                 struct DCTStatStruc *pDCTstat)
687 {
688         u32 val;
689         u32 dev;
690         u32 reg;
691
692         /* Initiates a memory clear operation on one node */
693         if (pDCTstat->DCTSysLimit) {
694                 dev = pDCTstat->dev_dct;
695                 reg = 0x110;
696
697                 do {
698                         val = Get_NB32(dev, reg);
699                 } while (val & (1 << MemClrBusy));
700
701                 val |= (1 << MemClrInit);
702                 Set_NB32(dev, reg, val);
703
704         }
705 }
706
707
708 static void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
709                                 struct DCTStatStruc *pDCTstatA)
710 {
711         /* Ensures that memory clear has completed on all node.*/
712         u8 Node;
713         struct DCTStatStruc *pDCTstat;
714
715         if (!mctGet_NVbits(NV_DQSTrainCTL)){
716                 // callback to wrapper: mctDoWarmResetMemClr_D
717         } else {        // NV_DQSTrainCTL == 1
718                 for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
719                         pDCTstat = pDCTstatA + Node;
720
721                         if (pDCTstat->NodePresent) {
722                                 DCTMemClr_Sync_D(pMCTstat, pDCTstat);
723                         }
724                 }
725         }
726 }
727
728
729 static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
730                                 struct DCTStatStruc *pDCTstat)
731 {
732         u32 val;
733         u32 dev = pDCTstat->dev_dct;
734         u32 reg;
735
736         /* Ensure that a memory clear operation has completed on one node */
737         if (pDCTstat->DCTSysLimit){
738                 reg = 0x110;
739
740                 do {
741                         val = Get_NB32(dev, reg);
742                 } while (val & (1 << MemClrBusy));
743
744                 do {
745                         val = Get_NB32(dev, reg);
746                 } while (!(val & (1 << Dr_MemClrStatus)));
747         }
748
749         val = 0x0FE40FC0;               // BKDG recommended
750         val |= MCCH_FlushWrOnStpGnt;    // Set for S3
751         Set_NB32(dev, 0x11C, val);
752 }
753
754
755 static u8 NodePresent_D(u8 Node)
756 {
757         /*
758          * Determine if a single Hammer Node exists within the network.
759          */
760
761         u32 dev;
762         u32 val;
763         u32 dword;
764         u8 ret = 0;
765
766         dev = PA_HOST(Node);            /*test device/vendor id at host bridge  */
767         val = Get_NB32(dev, 0);
768         dword = mct_NodePresent_D();    /* FIXME: BOZO -11001022h rev for F */
769         if (val == dword) {             /* AMD Hammer Family CPU HT Configuration */
770                 if (oemNodePresent_D(Node, &ret))
771                         goto finish;
772                 /* Node ID register */
773                 val = Get_NB32(dev, 0x60);
774                 val &= 0x07;
775                 dword = Node;
776                 if (val  == dword)      /* current nodeID = requested nodeID ? */
777                         ret = 1;
778 finish:
779         ;
780         }
781
782         return ret;
783 }
784
785
786 static void DCTInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct)
787 {
788         /*
789          * Initialize DRAM on single Athlon 64/Opteron Node.
790          */
791
792         u8 stopDCTflag;
793         u32 val;
794
795         ClearDCT_D(pMCTstat, pDCTstat, dct);
796         stopDCTflag = 1;                /*preload flag with 'disable' */
797         if (mct_DIMMPresence(pMCTstat, pDCTstat, dct) < SC_StopError) {
798                 print_t("\t\tDCTInit_D: mct_DIMMPresence Done\n");
799                 if (mct_SPDCalcWidth(pMCTstat, pDCTstat, dct) < SC_StopError) {
800                         print_t("\t\tDCTInit_D: mct_SPDCalcWidth Done\n");
801                         if (AutoCycTiming_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
802                                 print_t("\t\tDCTInit_D: AutoCycTiming_D Done\n");
803                                 if (AutoConfig_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
804                                         print_t("\t\tDCTInit_D: AutoConfig_D Done\n");
805                                         if (PlatformSpec_D(pMCTstat, pDCTstat, dct) < SC_StopError) {
806                                                 print_t("\t\tDCTInit_D: PlatformSpec_D Done\n");
807                                                 stopDCTflag = 0;
808                                                 if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) {
809                                                         print_t("\t\tDCTInit_D: StartupDCT_D\n");
810                                                         StartupDCT_D(pMCTstat, pDCTstat, dct);   /*yeaahhh! */
811                                                 }
812                                         }
813                                 }
814                         }
815                 }
816         }
817         if (stopDCTflag) {
818                 u32 reg_off = dct * 0x100;
819                 val = 1<<DisDramInterface;
820                 Set_NB32(pDCTstat->dev_dct, reg_off+0x94, val);
821                 /*To maximize power savings when DisDramInterface=1b,
822                   all of the MemClkDis bits should also be set.*/
823                 val = 0xFF000000;
824                 Set_NB32(pDCTstat->dev_dct, reg_off+0x88, val);
825         }
826 }
827
828
829 static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
830                                 struct DCTStatStruc *pDCTstatA)
831 {
832         /* Wait (and block further access to dram) for all DCTs to be ready,
833          * by polling all InitDram bits and waiting for possible memory clear
834          * operations to be complete.  Read MemClkFreqVal bit to see if
835          * the DIMMs are present in this node.
836          */
837
838         u8 Node;
839
840         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
841                 struct DCTStatStruc *pDCTstat;
842                 pDCTstat = pDCTstatA + Node;
843                 mct_SyncDCTsReady(pDCTstat);
844         }
845 }
846
847
848 static void StartupDCT_D(struct MCTStatStruc *pMCTstat,
849                                 struct DCTStatStruc *pDCTstat, u8 dct)
850 {
851         /* Read MemClkFreqVal bit to see if the DIMMs are present in this node.
852          * If the DIMMs are present then set the DRAM Enable bit for this node.
853          *
854          * Setting dram init starts up the DCT state machine, initializes the
855          * dram devices with MRS commands, and kicks off any
856          * HW memory clear process that the chip is capable of. The sooner
857          * that dram init is set for all nodes, the faster the memory system
858          * initialization can complete. Thus, the init loop is unrolled into
859          * two loops so as to start the processeses for non BSP nodes sooner.
860          * This procedure will not wait for the process to finish.
861          * Synchronization is handled elsewhere.
862          */
863
864         u32 val;
865         u32 dev;
866         u8 byte;
867         u32 reg;
868         u32 reg_off = dct * 0x100;
869
870         dev = pDCTstat->dev_dct;
871         val = Get_NB32(dev, 0x94 + reg_off);
872         if (val & (1<<MemClkFreqVal)) {
873                 print_t("\t\t\tStartupDCT_D: MemClkFreqVal\n");
874                 byte = mctGet_NVbits(NV_DQSTrainCTL);
875                 if (byte == 1) {
876                         /* Enable DQSRcvEn training mode */
877                         print_t("\t\t\tStartupDCT_D: DqsRcvEnTrain set \n");
878                         reg = 0x78 + reg_off;
879                         val = Get_NB32(dev, reg);
880                         /* Setting this bit forces a 1T window with hard left
881                          * pass/fail edge and a probabalistic right pass/fail
882                          * edge.  LEFT edge is referenced for final
883                          * receiver enable position.*/
884                         val |= 1 << DqsRcvEnTrain;
885                         Set_NB32(dev, reg, val);
886                 }
887                 mctHookBeforeDramInit();        /* generalized Hook */
888                 print_t("\t\t\tStartupDCT_D: DramInit \n");
889                 mct_DramInit(pMCTstat, pDCTstat, dct);
890                 AfterDramInit_D(pDCTstat, dct);
891                 mctHookAfterDramInit();         /* generalized Hook*/
892         }
893 }
894
895
896 static void ClearDCT_D(struct MCTStatStruc *pMCTstat,
897                         struct DCTStatStruc *pDCTstat, u8 dct)
898 {
899         u32 reg_end;
900         u32 dev = pDCTstat->dev_dct;
901         u32 reg = 0x40 + 0x100 * dct;
902         u32 val = 0;
903
904         if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
905                 reg_end = 0x78 + 0x100 * dct;
906         } else {
907                 reg_end = 0xA4 + 0x100 * dct;
908         }
909
910         while(reg < reg_end) {
911                 Set_NB32(dev, reg, val);
912                 reg += 4;
913         }
914
915         val = 0;
916         dev = pDCTstat->dev_map;
917         reg = 0xF0;
918         Set_NB32(dev, reg, val);
919 }
920
921
922 static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
923                                 struct DCTStatStruc *pDCTstat, u8 dct)
924 {
925         /* Initialize  DCT Timing registers as per DIMM SPD.
926          * For primary timing (T, CL) use best case T value.
927          * For secondary timing params., use most aggressive settings
928          * of slowest DIMM.
929          *
930          * There are three components to determining "maximum frequency":
931          * SPD component, Bus load component, and "Preset" max frequency
932          * component.
933          *
934          * The SPD component is a function of the min cycle time specified
935          * by each DIMM, and the interaction of cycle times from all DIMMs
936          * in conjunction with CAS latency. The SPD component only applies
937          * when user timing mode is 'Auto'.
938          *
939          * The Bus load component is a limiting factor determined by electrical
940          * characteristics on the bus as a result of varying number of device
941          * loads. The Bus load component is specific to each platform but may
942          * also be a function of other factors. The bus load component only
943          * applies when user timing mode is 'Auto'.
944          *
945          * The Preset component is subdivided into three items and is the
946          * minimum of the set: Silicon revision, user limit setting when user
947          * timing mode is 'Auto' and memclock mode is 'Limit', OEM build
948          * specification of the maximum frequency. The Preset component is only
949          * applies when user timing mode is 'Auto'.
950          */
951
952         u8 i;
953         u8 Twr, Trtp;
954         u8 Trp, Trrd, Trcd, Tras, Trc, Trfc[4], Rows;
955         u32 DramTimingLo, DramTimingHi;
956         u16 Tk10, Tk40;
957         u8 Twtr;
958         u8 LDIMM;
959         u8 DDR2_1066;
960         u8 byte;
961         u32 dword;
962         u32 dev;
963         u32 reg;
964         u32 reg_off;
965         u32 val;
966         u16 smbaddr;
967
968         /* Get primary timing (CAS Latency and Cycle Time) */
969         if (pDCTstat->Speed == 0) {
970                 mctGet_MaxLoadFreq(pDCTstat);
971
972                 /* and Factor in presets (setup options, Si cap, etc.) */
973                 GetPresetmaxF_D(pMCTstat, pDCTstat);
974
975                 /* Go get best T and CL as specified by DIMM mfgs. and OEM */
976                 SPDGetTCL_D(pMCTstat, pDCTstat, dct);
977                 /* skip callback mctForce800to1067_D */
978                 pDCTstat->Speed = pDCTstat->DIMMAutoSpeed;
979                 pDCTstat->CASL = pDCTstat->DIMMCASL;
980
981                 /* if "manual" memclock mode */
982                 if ( mctGet_NVbits(NV_MCTUSRTMGMODE) == 2)
983                         pDCTstat->Speed = mctGet_NVbits(NV_MemCkVal) + 1;
984
985                 mct_AfterGetCLT(pMCTstat, pDCTstat, dct);
986         }
987
988         /* Gather all DIMM mini-max values for cycle timing data */
989         Rows = 0;
990         Trp = 0;
991         Trrd = 0;
992         Trcd = 0;
993         Trtp = 0;
994         Tras = 0;
995         Trc = 0;
996         Twr = 0;
997         Twtr = 0;
998         for (i=0; i < 4; i++)
999                 Trfc[i] = 0;
1000
1001         for ( i = 0; i< MAX_DIMMS_SUPPORTED; i++) {
1002                 LDIMM = i >> 1;
1003                 if (pDCTstat->DIMMValid & (1 << i)) {
1004                         smbaddr = Get_DIMMAddress_D(pDCTstat, i);
1005                         byte = mctRead_SPD(smbaddr, SPD_ROWSZ);
1006                         if (Rows < byte)
1007                                 Rows = byte;    /* keep track of largest row sz */
1008
1009                         byte = mctRead_SPD(smbaddr, SPD_TRP);
1010                         if (Trp < byte)
1011                                 Trp = byte;
1012
1013                         byte = mctRead_SPD(smbaddr, SPD_TRRD);
1014                         if (Trrd < byte)
1015                                 Trrd = byte;
1016
1017                         byte = mctRead_SPD(smbaddr, SPD_TRCD);
1018                         if (Trcd < byte)
1019                                 Trcd = byte;
1020
1021                         byte = mctRead_SPD(smbaddr, SPD_TRTP);
1022                         if (Trtp < byte)
1023                                 Trtp = byte;
1024
1025                         byte = mctRead_SPD(smbaddr, SPD_TWR);
1026                         if (Twr < byte)
1027                                 Twr = byte;
1028
1029                         byte = mctRead_SPD(smbaddr, SPD_TWTR);
1030                         if (Twtr < byte)
1031                                 Twtr = byte;
1032
1033                         val = mctRead_SPD(smbaddr, SPD_TRC);
1034                         if ((val == 0) || (val == 0xFF)) {
1035                                 pDCTstat->ErrStatus |= 1<<SB_NoTrcTrfc;
1036                                 pDCTstat->ErrCode = SC_VarianceErr;
1037                                 val = Get_DefTrc_k_D(pDCTstat->Speed);
1038                         } else {
1039                                 byte = mctRead_SPD(smbaddr, SPD_TRCRFC);
1040                                 if (byte & 0xF0) {
1041                                         val++;  /* round up in case fractional extention is non-zero.*/
1042                                 }
1043                 }
1044                 if (Trc < val)
1045                         Trc = val;
1046
1047                 /* dev density=rank size/#devs per rank */
1048                 byte = mctRead_SPD(smbaddr, SPD_BANKSZ);
1049
1050                 val = ((byte >> 5) | (byte << 3)) & 0xFF;
1051                 val <<= 2;
1052
1053                 byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE;     /* dev density=2^(rows+columns+banks) */
1054                 if (byte == 4) {
1055                         val >>= 4;
1056                 } else if (byte == 8) {
1057                         val >>= 3;
1058                 } else if (byte == 16) {
1059                         val >>= 2;
1060                 }
1061
1062                 byte = bsr(val);
1063
1064                 if (Trfc[LDIMM] < byte)
1065                         Trfc[LDIMM] = byte;
1066
1067                 byte = mctRead_SPD(smbaddr, SPD_TRAS);
1068                 if (Tras < byte)
1069                         Tras = byte;
1070                 }       /* Dimm Present */
1071         }
1072
1073         /* Convert  DRAM CycleTiming values and store into DCT structure */
1074         DDR2_1066 = 0;
1075         byte = pDCTstat->Speed;
1076         if (byte == 5)
1077                 DDR2_1066 = 1;
1078         Tk40 = Get_40Tk_D(byte);
1079         Tk10 = Tk40>>2;
1080
1081         /* Notes:
1082          1. All secondary time values given in SPDs are in binary with units of ns.
1083          2. Some time values are scaled by four, in order to have least count of 0.25 ns
1084             (more accuracy).  JEDEC SPD spec. shows which ones are x1 and x4.
1085          3. Internally to this SW, cycle time, Tk, is scaled by 10 to affect a
1086             least count of 0.1 ns (more accuracy).
1087          4. SPD values not scaled are multiplied by 10 and then divided by 10T to find
1088             equivalent minimum number of bus clocks (a remainder causes round-up of clocks).
1089          5. SPD values that are prescaled by 4 are multiplied by 10 and then divided by 40T to find
1090             equivalent minimum number of bus clocks (a remainder causes round-up of clocks).*/
1091
1092         /* Tras */
1093         dword = Tras * 40;
1094         pDCTstat->DIMMTras = (u16)dword;
1095         val = dword / Tk40;
1096         if (dword % Tk40) {     /* round up number of busclocks */
1097                 val++;
1098         }
1099         if (DDR2_1066) {
1100                 if (val < Min_TrasT_1066)
1101                         val = Min_TrasT_1066;
1102                 else if (val > Max_TrasT_1066)
1103                         val = Max_TrasT_1066;
1104         } else {
1105                 if (val < Min_TrasT)
1106                         val = Min_TrasT;
1107                 else if (val > Max_TrasT)
1108                         val = Max_TrasT;
1109         }
1110         pDCTstat->Tras = val;
1111
1112         /* Trp */
1113         dword = Trp * 10;
1114         pDCTstat->DIMMTrp = dword;
1115         val = dword / Tk40;
1116         if (dword % Tk40) {     /* round up number of busclocks */
1117                 val++;
1118         }
1119         if (DDR2_1066) {
1120                 if (val < Min_TrasT_1066)
1121                         val = Min_TrpT_1066;
1122                 else if (val > Max_TrpT_1066)
1123                         val = Max_TrpT_1066;
1124         } else {
1125                 if (val < Min_TrpT)
1126                         val = Min_TrpT;
1127                 else if (val > Max_TrpT)
1128                         val = Max_TrpT;
1129         }
1130         pDCTstat->Trp = val;
1131
1132          /*Trrd*/
1133         dword = Trrd * 10;
1134         pDCTstat->DIMMTrrd = dword;
1135         val = dword / Tk40;
1136         if (dword % Tk40) {     /* round up number of busclocks */
1137                 val++;
1138         }
1139         if (DDR2_1066) {
1140                 if (val < Min_TrrdT_1066)
1141                         val = Min_TrrdT_1066;
1142                 else if (val > Max_TrrdT_1066)
1143                         val = Max_TrrdT_1066;
1144         } else {
1145                 if (val < Min_TrrdT)
1146                         val = Min_TrrdT;
1147                 else if (val > Max_TrrdT)
1148                         val = Max_TrrdT;
1149         }
1150         pDCTstat->Trrd = val;
1151
1152         /* Trcd */
1153         dword = Trcd * 10;
1154         pDCTstat->DIMMTrcd = dword;
1155         val = dword / Tk40;
1156         if (dword % Tk40) {     /* round up number of busclocks */
1157                 val++;
1158         }
1159         if (DDR2_1066) {
1160                 if (val < Min_TrcdT_1066)
1161                         val = Min_TrcdT_1066;
1162                 else if (val > Max_TrcdT_1066)
1163                         val = Max_TrcdT_1066;
1164         } else {
1165                 if (val < Min_TrcdT)
1166                         val = Min_TrcdT;
1167                 else if (val > Max_TrcdT)
1168                         val = Max_TrcdT;
1169         }
1170         pDCTstat->Trcd = val;
1171
1172         /* Trc */
1173         dword = Trc * 40;
1174         pDCTstat->DIMMTrc = dword;
1175         val = dword / Tk40;
1176         if (dword % Tk40) {     /* round up number of busclocks */
1177                 val++;
1178         }
1179         if (DDR2_1066) {
1180                 if (val < Min_TrcT_1066)
1181                         val = Min_TrcT_1066;
1182                 else if (val > Max_TrcT_1066)
1183                         val = Max_TrcT_1066;
1184         } else {
1185                 if (val < Min_TrcT)
1186                         val = Min_TrcT;
1187                 else if (val > Max_TrcT)
1188                         val = Max_TrcT;
1189         }
1190         pDCTstat->Trc = val;
1191
1192         /* Trtp */
1193         dword = Trtp * 10;
1194         pDCTstat->DIMMTrtp = dword;
1195         val = pDCTstat->Speed;
1196         if (val <= 2) {         /* 7.75ns / Speed in ns to get clock # */
1197                 val = 2;        /* for DDR400/DDR533 */
1198         } else {                /* Note a speed of 3 will be a Trtp of 3 */
1199                 val = 3;        /* for DDR667/DDR800/DDR1066 */
1200         }
1201         pDCTstat->Trtp = val;
1202
1203         /* Twr */
1204         dword = Twr * 10;
1205         pDCTstat->DIMMTwr = dword;
1206         val = dword / Tk40;
1207         if (dword % Tk40) {     /* round up number of busclocks */
1208                 val++;
1209         }
1210         if (DDR2_1066) {
1211                 if (val < Min_TwrT_1066)
1212                         val = Min_TwrT_1066;
1213                 else if (val > Max_TwrT_1066)
1214                         val = Max_TwrT_1066;
1215         } else {
1216                 if (val < Min_TwrT)
1217                         val = Min_TwrT;
1218                 else if (val > Max_TwrT)
1219                         val = Max_TwrT;
1220         }
1221         pDCTstat->Twr = val;
1222
1223         /* Twtr */
1224         dword = Twtr * 10;
1225         pDCTstat->DIMMTwtr = dword;
1226         val = dword / Tk40;
1227         if (dword % Tk40) {     /* round up number of busclocks */
1228                 val++;
1229         }
1230         if (DDR2_1066) {
1231                 if (val < Min_TwrT_1066)
1232                         val = Min_TwtrT_1066;
1233                 else if (val > Max_TwtrT_1066)
1234                         val = Max_TwtrT_1066;
1235         } else {
1236                 if (val < Min_TwtrT)
1237                         val = Min_TwtrT;
1238                 else if (val > Max_TwtrT)
1239                         val = Max_TwtrT;
1240         }
1241         pDCTstat->Twtr = val;
1242
1243
1244         /* Trfc0-Trfc3 */
1245         for (i=0; i<4; i++)
1246                 pDCTstat->Trfc[i] = Trfc[i];
1247
1248         mctAdjustAutoCycTmg_D();
1249
1250         /* Program DRAM Timing values */
1251         DramTimingLo = 0;       /* Dram Timing Low init */
1252         val = pDCTstat->CASL;
1253         val = Tab_tCL_j[val];
1254         DramTimingLo |= val;
1255
1256         val = pDCTstat->Trcd;
1257         if (DDR2_1066)
1258                 val -= Bias_TrcdT_1066;
1259         else
1260                 val -= Bias_TrcdT;
1261
1262         DramTimingLo |= val<<4;
1263
1264         val = pDCTstat->Trp;
1265         if (DDR2_1066)
1266                 val -= Bias_TrpT_1066;
1267         else {
1268                 val -= Bias_TrpT;
1269                 val <<= 1;
1270         }
1271         DramTimingLo |= val<<7;
1272
1273         val = pDCTstat->Trtp;
1274         val -= Bias_TrtpT;
1275         DramTimingLo |= val<<11;
1276
1277         val = pDCTstat->Tras;
1278         if (DDR2_1066)
1279                 val -= Bias_TrasT_1066;
1280         else
1281                 val -= Bias_TrasT;
1282         DramTimingLo |= val<<12;
1283
1284         val = pDCTstat->Trc;
1285         val -= Bias_TrcT;
1286         DramTimingLo |= val<<16;
1287
1288         if (!DDR2_1066) {
1289                 val = pDCTstat->Twr;
1290                 val -= Bias_TwrT;
1291                 DramTimingLo |= val<<20;
1292         }
1293
1294         val = pDCTstat->Trrd;
1295         if (DDR2_1066)
1296                 val -= Bias_TrrdT_1066;
1297         else
1298                 val -= Bias_TrrdT;
1299         DramTimingLo |= val<<22;
1300
1301
1302         DramTimingHi = 0;       /* Dram Timing Low init */
1303         val = pDCTstat->Twtr;
1304         if (DDR2_1066)
1305                 val -= Bias_TwtrT_1066;
1306         else
1307                 val -= Bias_TwtrT;
1308         DramTimingHi |= val<<8;
1309
1310         val = 2;
1311         DramTimingHi |= val<<16;
1312
1313         val = 0;
1314         for (i=4;i>0;i--) {
1315                 val <<= 3;
1316                 val |= Trfc[i-1];
1317         }
1318         DramTimingHi |= val << 20;
1319
1320
1321         dev = pDCTstat->dev_dct;
1322         reg_off = 0x100 * dct;
1323         print_tx("AutoCycTiming: DramTimingLo ", DramTimingLo);
1324         print_tx("AutoCycTiming: DramTimingHi ", DramTimingHi);
1325
1326         Set_NB32(dev, 0x88 + reg_off, DramTimingLo);    /*DCT Timing Low*/
1327         DramTimingHi |=0x0000FC77;
1328         Set_NB32(dev, 0x8c + reg_off, DramTimingHi);    /*DCT Timing Hi*/
1329
1330         if (DDR2_1066) {
1331                 /* Twr */
1332                 dword = pDCTstat->Twr;
1333                 dword -= Bias_TwrT_1066;
1334                 dword <<= 4;
1335                 reg = 0x84 + reg_off;
1336                 val = Get_NB32(dev, reg);
1337                 val &= 0x8F;
1338                 val |= dword;
1339                 Set_NB32(dev, reg, val);
1340         }
1341 //      dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2));
1342
1343         print_tx("AutoCycTiming: Status ", pDCTstat->Status);
1344         print_tx("AutoCycTiming: ErrStatus ", pDCTstat->ErrStatus);
1345         print_tx("AutoCycTiming: ErrCode ", pDCTstat->ErrCode);
1346         print_t("AutoCycTiming: Done\n");
1347
1348         mctHookAfterAutoCycTmg();
1349
1350         return pDCTstat->ErrCode;
1351 }
1352
1353
1354 static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
1355                                 struct DCTStatStruc *pDCTstat)
1356 {
1357         /* Get max frequency from OEM platform definition, from any user
1358          * override (limiting) of max frequency, and from any Si Revision
1359          * Specific information.  Return the least of these three in
1360          * DCTStatStruc.PresetmaxFreq.
1361          */
1362
1363         u16 proposedFreq;
1364         u16 word;
1365
1366         /* Get CPU Si Revision defined limit (NPT) */
1367         proposedFreq = 533;      /* Rev F0 programmable max memclock is */
1368
1369         /*Get User defined limit if  "limit" mode */
1370         if ( mctGet_NVbits(NV_MCTUSRTMGMODE) == 1) {
1371                 word = Get_Fk_D(mctGet_NVbits(NV_MemCkVal) + 1);
1372                 if (word < proposedFreq)
1373                         proposedFreq = word;
1374
1375                 /* Get Platform defined limit */
1376                 word = mctGet_NVbits(NV_MAX_MEMCLK);
1377                 if (word < proposedFreq)
1378                         proposedFreq = word;
1379
1380                 word = pDCTstat->PresetmaxFreq;
1381                 if (word > proposedFreq)
1382                         word = proposedFreq;
1383
1384                 pDCTstat->PresetmaxFreq = word;
1385         }
1386 }
1387
1388
1389
1390 static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
1391                                 struct DCTStatStruc *pDCTstat, u8 dct)
1392 {
1393         /* Find the best T and CL primary timing parameter pair, per Mfg.,
1394          * for the given set of DIMMs, and store into DCTStatStruc
1395          * (.DIMMAutoSpeed and .DIMMCASL). See "Global relationship between
1396          *  index values and item values" for definition of CAS latency
1397          *  index (j) and Frequency index (k).
1398          */
1399         int i, j, k;
1400         u8 T1min, CL1min;
1401
1402         /* i={0..7} (std. physical DIMM number)
1403          * j is an integer which enumerates increasing CAS latency.
1404          * k is an integer which enumerates decreasing cycle time.
1405          * CL no. {0,1,2} corresponds to CL X, CL X-.5, or CL X-1 (per individual DIMM)
1406          * Max timing values are per parameter, of all DIMMs, spec'd in ns like the SPD.
1407          */
1408
1409         CL1min = 0xFF;
1410         T1min = 0xFF;
1411         for (k=K_MAX; k >= K_MIN; k--) {
1412                 for (j = J_MIN; j <= J_MAX; j++) {
1413                         if (Sys_Capability_D(pMCTstat, pDCTstat, j, k) ) {
1414                                 /* 1. check to see if DIMMi is populated.
1415                                    2. check if DIMMi supports CLj and Tjk */
1416                                 for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) {
1417                                         if (pDCTstat->DIMMValid & (1 << i)) {
1418                                                 if (Dimm_Supports_D(pDCTstat, i, j, k))
1419                                                         break;
1420                                         }
1421                                 }       /* while ++i */
1422                                 if (i == MAX_DIMMS_SUPPORTED) {
1423                                         T1min = k;
1424                                         CL1min = j;
1425                                         goto got_TCL;
1426                                 }
1427                         }
1428                 }       /* while ++j */
1429         }       /* while --k */
1430
1431 got_TCL:
1432         if (T1min != 0xFF) {
1433                 pDCTstat->DIMMCASL = CL1min;    /*mfg. optimized */
1434                 pDCTstat->DIMMAutoSpeed = T1min;
1435                 print_tx("SPDGetTCL_D: DIMMCASL ", pDCTstat->DIMMCASL);
1436                 print_tx("SPDGetTCL_D: DIMMAutoSpeed ", pDCTstat->DIMMAutoSpeed);
1437
1438         } else {
1439                 pDCTstat->DIMMCASL = CL_DEF;    /* failsafe values (running in min. mode) */
1440                 pDCTstat->DIMMAutoSpeed = T_DEF;
1441                 pDCTstat->ErrStatus |= 1 << SB_DimmMismatchT;
1442                 pDCTstat->ErrStatus |= 1 << SB_MinimumMode;
1443                 pDCTstat->ErrCode = SC_VarianceErr;
1444         }
1445         print_tx("SPDGetTCL_D: Status ", pDCTstat->Status);
1446         print_tx("SPDGetTCL_D: ErrStatus ", pDCTstat->ErrStatus);
1447         print_tx("SPDGetTCL_D: ErrCode ", pDCTstat->ErrCode);
1448         print_t("SPDGetTCL_D: Done\n");
1449 }
1450
1451
1452 static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat,
1453                                 struct DCTStatStruc *pDCTstat, u8 dct)
1454 {
1455         u32 dev;
1456         u32 reg;
1457         u32 val;
1458
1459         mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct);
1460
1461         if (pDCTstat->GangedMode) {
1462                 mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1);
1463         }
1464
1465         if ( pDCTstat->_2Tmode == 2) {
1466                 dev = pDCTstat->dev_dct;
1467                 reg = 0x94 + 0x100 * dct; /* Dram Configuration Hi */
1468                 val = Get_NB32(dev, reg);
1469                 val |= 1 << 20;                /* 2T CMD mode */
1470                 Set_NB32(dev, reg, val);
1471         }
1472
1473         mct_PlatformSpec(pMCTstat, pDCTstat, dct);
1474         InitPhyCompensation(pMCTstat, pDCTstat, dct);
1475         mctHookAfterPSCfg();
1476         return pDCTstat->ErrCode;
1477 }
1478
1479
1480 static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
1481                                 struct DCTStatStruc *pDCTstat, u8 dct)
1482 {
1483         u32 DramControl, DramTimingLo, Status;
1484         u32 DramConfigLo, DramConfigHi, DramConfigMisc, DramConfigMisc2;
1485         u32 val;
1486         u32 reg_off;
1487         u32 dev;
1488         u16 word;
1489         u32 dword;
1490         u8 byte;
1491
1492         print_tx("AutoConfig_D: DCT: ", dct);
1493
1494         DramConfigLo = 0;
1495         DramConfigHi = 0;
1496         DramConfigMisc = 0;
1497         DramConfigMisc2 = 0;
1498
1499         /* set bank addessing and Masks, plus CS pops */
1500         SPDSetBanks_D(pMCTstat, pDCTstat, dct);
1501         if (pDCTstat->ErrCode == SC_StopError)
1502                 goto AutoConfig_exit;
1503
1504         /* map chip-selects into local address space */
1505         StitchMemory_D(pMCTstat, pDCTstat, dct);
1506         InterleaveBanks_D(pMCTstat, pDCTstat, dct);
1507
1508         /* temp image of status (for convenience). RO usage! */
1509         Status = pDCTstat->Status;
1510
1511         dev = pDCTstat->dev_dct;
1512         reg_off = 0x100 * dct;
1513
1514
1515         /* Build Dram Control Register Value */
1516         DramConfigMisc2 = Get_NB32 (dev, 0xA8 + reg_off);       /* Dram Control*/
1517         DramControl = Get_NB32 (dev, 0x78 + reg_off);           /* Dram Control*/
1518
1519         if (mctGet_NVbits(NV_CLKHZAltVidC3))
1520                 DramControl |= 1<<16;
1521
1522         // FIXME: Add support(skip) for Ax and Cx versions
1523         DramControl |= 5;       /* RdPtrInit */
1524
1525
1526         /* Build Dram Config Lo Register Value */
1527         DramConfigLo |= 1 << 4;                                 /* 75 Ohms ODT */
1528         if (mctGet_NVbits(NV_MAX_DIMMS) == 8) {
1529                 if (pDCTstat->Speed == 3) {
1530                         if ((pDCTstat->MAdimms[dct] == 4))
1531                                 DramConfigLo |= 1 << 5;         /* 50 Ohms ODT */
1532                 } else if (pDCTstat->Speed == 4){
1533                         if ((pDCTstat->MAdimms[dct] != 1))
1534                                 DramConfigLo |= 1 << 5;         /* 50 Ohms ODT */
1535                 }
1536         } else {
1537                 // FIXME: Skip for Ax versions
1538                 if ((pDCTstat->MAdimms[dct] == 4)) {
1539                         if ( pDCTstat->DimmQRPresent != 0) {
1540                                 if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 4)) {
1541                                         DramConfigLo |= 1 << 5; /* 50 Ohms ODT */
1542                                 }
1543                         } else if ((pDCTstat->MAdimms[dct] == 4)) {
1544                                 if (pDCTstat->Speed == 4) {
1545                                         if ( pDCTstat->DimmQRPresent != 0) {
1546                                                 DramConfigLo |= 1 << 5; /* 50 Ohms ODT */
1547                                         }
1548                                 }
1549                         }
1550                 } else if ((pDCTstat->MAdimms[dct] == 2)) {
1551                         DramConfigLo |= 1 << 5;         /* 50 Ohms ODT */
1552                 }
1553
1554         }
1555
1556         // FIXME: Skip for Ax versions
1557         /* callback not required - if (!mctParityControl_D()) */
1558         if (Status & (1 << SB_PARDIMMs)) {
1559                 DramConfigLo |= 1 << ParEn;
1560                 DramConfigMisc2 |= 1 << ActiveCmdAtRst;
1561         } else {
1562                 DramConfigLo  &= ~(1 << ParEn);
1563                 DramConfigMisc2 &= ~(1 << ActiveCmdAtRst);
1564         }
1565
1566         if (mctGet_NVbits(NV_BurstLen32)) {
1567                 if (!pDCTstat->GangedMode)
1568                         DramConfigLo |= 1 << BurstLength32;
1569         }
1570
1571         if (Status & (1 << SB_128bitmode))
1572                 DramConfigLo |= 1 << Width128;  /* 128-bit mode (normal) */
1573
1574         word = dct;
1575         dword = X4Dimm;
1576         while (word < 8) {
1577                 if (pDCTstat->Dimmx4Present & (1 << word))
1578                         DramConfigLo |= 1 << dword;     /* X4Dimm[3:0] */
1579                 word++;
1580                 word++;
1581                 dword++;
1582         }
1583
1584         if (!(Status & (1 << SB_Registered)))
1585                 DramConfigLo |= 1 << UnBuffDimm;        /* Unbufferd DIMMs */
1586
1587         if (mctGet_NVbits(NV_ECC_CAP))
1588                 if (Status & (1 << SB_ECCDIMMs))
1589                         if ( mctGet_NVbits(NV_ECC))
1590                                 DramConfigLo |= 1 << DimmEcEn;
1591
1592
1593
1594         /* Build Dram Config Hi Register Value */
1595         dword = pDCTstat->Speed;
1596         DramConfigHi |= dword - 1;      /* get MemClk encoding */
1597         DramConfigHi |= 1 << MemClkFreqVal;
1598
1599         if (Status & (1 << SB_Registered))
1600                 if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0))
1601                         /* set only if x8 Registered DIMMs in System*/
1602                         DramConfigHi |= 1 << RDqsEn;
1603
1604         if (mctGet_NVbits(NV_CKE_PDEN)) {
1605                 DramConfigHi |= 1 << 15;                /* PowerDownEn */
1606                 if (mctGet_NVbits(NV_CKE_CTL))
1607                         /*Chip Select control of CKE*/
1608                         DramConfigHi |= 1 << 16;
1609         }
1610
1611         /* Control Bank Swizzle */
1612         if (0) /* call back not needed mctBankSwizzleControl_D()) */
1613                 DramConfigHi &= ~(1 << BankSwizzleMode);
1614         else
1615                 DramConfigHi |= 1 << BankSwizzleMode; /* recommended setting (default) */
1616
1617         /* Check for Quadrank DIMM presence */
1618         if ( pDCTstat->DimmQRPresent != 0) {
1619                 byte = mctGet_NVbits(NV_4RANKType);
1620                 if (byte == 2)
1621                         DramConfigHi |= 1 << 17;        /* S4 (4-Rank SO-DIMMs) */
1622                 else if (byte == 1)
1623                         DramConfigHi |= 1 << 18;        /* R4 (4-Rank Registered DIMMs) */
1624         }
1625
1626         if (0) /* call back not needed mctOverrideDcqBypMax_D ) */
1627                 val = mctGet_NVbits(NV_BYPMAX);
1628         else
1629                 val = 0x0f; // recommended setting (default)
1630         DramConfigHi |= val << 24;
1631
1632         val = pDCTstat->DIMM2Kpage;
1633         if (pDCTstat->GangedMode != 0) {
1634                 if (dct != 0) {
1635                         val &= 0x55;
1636                 } else {
1637                         val &= 0xAA;
1638                 }
1639         }
1640         if (val)
1641                 val = Tab_2KTfawT_k[pDCTstat->Speed];
1642         else
1643                 val = Tab_1KTfawT_k[pDCTstat->Speed];
1644
1645         if (pDCTstat->Speed == 5)
1646                 val >>= 1;
1647
1648         val -= Bias_TfawT;
1649         val <<= 28;
1650         DramConfigHi |= val;    /* Tfaw for 1K or 2K paged drams */
1651
1652         // FIXME: Skip for Ax versions
1653         DramConfigHi |= 1 << DcqArbBypassEn;
1654
1655
1656         /* Build MemClkDis Value from Dram Timing Lo and
1657            Dram Config Misc Registers
1658          1. We will assume that MemClkDis field has been preset prior to this
1659             point.
1660          2. We will only set MemClkDis bits if a DIMM is NOT present AND if:
1661             NV_AllMemClks <>0 AND SB_DiagClks ==0 */
1662
1663
1664         /* Dram Timing Low (owns Clock Enable bits) */
1665         DramTimingLo = Get_NB32(dev, 0x88 + reg_off);
1666         if (mctGet_NVbits(NV_AllMemClks) == 0) {
1667                 /* Special Jedec SPD diagnostic bit - "enable all clocks" */
1668                 if (!(pDCTstat->Status & (1<<SB_DiagClks))) {
1669                         const u8 *p;
1670                         byte = mctGet_NVbits(NV_PACK_TYPE);
1671                         if (byte == PT_L1)
1672                                 p = Tab_L1CLKDis;
1673                         else if (byte == PT_M2)
1674                                 p = Tab_M2CLKDis;
1675                         else
1676                                 p = Tab_S1CLKDis;
1677
1678                         dword = 0;
1679                         while(dword < MAX_DIMMS_SUPPORTED) {
1680                                 val = p[dword];
1681                                 print_tx("DramTimingLo: val=", val);
1682                                 if (!(pDCTstat->DIMMValid & (1<<val)))
1683                                         /*disable memclk*/
1684                                         DramTimingLo |= 1<<(dword+24);
1685                                 dword++ ;
1686                         }
1687                 }
1688         }
1689
1690         print_tx("AutoConfig_D: DramControl: ", DramControl);
1691         print_tx("AutoConfig_D: DramTimingLo: ", DramTimingLo);
1692         print_tx("AutoConfig_D: DramConfigMisc: ", DramConfigMisc);
1693         print_tx("AutoConfig_D: DramConfigMisc2: ", DramConfigMisc2);
1694         print_tx("AutoConfig_D: DramConfigLo: ", DramConfigLo);
1695         print_tx("AutoConfig_D: DramConfigHi: ", DramConfigHi);
1696
1697         /* Write Values to the registers */
1698         Set_NB32(dev, 0x78 + reg_off, DramControl);
1699         Set_NB32(dev, 0x88 + reg_off, DramTimingLo);
1700         Set_NB32(dev, 0xA0 + reg_off, DramConfigMisc);
1701         Set_NB32(dev, 0xA8 + reg_off, DramConfigMisc2);
1702         Set_NB32(dev, 0x90 + reg_off, DramConfigLo);
1703         mct_SetDramConfigHi_D(pDCTstat, dct, DramConfigHi);
1704         mct_ForceAutoPrecharge_D(pDCTstat, dct);
1705         mct_EarlyArbEn_D(pMCTstat, pDCTstat);
1706         mctHookAfterAutoCfg();
1707
1708 //      dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2));
1709
1710         print_tx("AutoConfig: Status ", pDCTstat->Status);
1711         print_tx("AutoConfig: ErrStatus ", pDCTstat->ErrStatus);
1712         print_tx("AutoConfig: ErrCode ", pDCTstat->ErrCode);
1713         print_t("AutoConfig: Done\n");
1714 AutoConfig_exit:
1715         return pDCTstat->ErrCode;
1716 }
1717
1718
1719 static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat,
1720                                 struct DCTStatStruc *pDCTstat, u8 dct)
1721 {
1722         /* Set bank addressing, program Mask values and build a chip-select
1723          * population map. This routine programs PCI 0:24N:2x80 config register
1724          * and PCI 0:24N:2x60,64,68,6C config registers (CS Mask 0-3).
1725          */
1726
1727         u8 ChipSel, Rows, Cols, Ranks ,Banks, DevWidth;
1728         u32 BankAddrReg, csMask;
1729
1730         u32 val;
1731         u32 reg;
1732         u32 dev;
1733         u32 reg_off;
1734         u8 byte;
1735         u16 word;
1736         u32 dword;
1737         u16 smbaddr;
1738
1739         dev = pDCTstat->dev_dct;
1740         reg_off = 0x100 * dct;
1741
1742         BankAddrReg = 0;
1743         for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel+=2) {
1744                 byte = ChipSel;
1745                 if ((pDCTstat->Status & (1 << SB_64MuxedMode)) && ChipSel >=4)
1746                         byte -= 3;
1747
1748                 if (pDCTstat->DIMMValid & (1<<byte)) {
1749                         smbaddr = Get_DIMMAddress_D(pDCTstat, (ChipSel + dct));
1750
1751                         byte = mctRead_SPD(smbaddr, SPD_ROWSZ);
1752                         Rows = byte & 0x1f;
1753
1754                         byte = mctRead_SPD(smbaddr, SPD_COLSZ);
1755                         Cols = byte & 0x1f;
1756
1757                         Banks = mctRead_SPD(smbaddr, SPD_LBANKS);
1758
1759                         byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH);
1760                         DevWidth = byte & 0x7f; /* bits 0-6 = bank 0 width */
1761
1762                         byte = mctRead_SPD(smbaddr, SPD_DMBANKS);
1763                         Ranks = (byte & 7) + 1;
1764
1765                         /* Configure Bank encoding
1766                          * Use a 6-bit key into a lookup table.
1767                          * Key (index) = CCCBRR, where CCC is the number of
1768                          * Columns minus 9,RR is the number of Rows minus 13,
1769                          * and B is the number of banks minus 2.
1770                          * See "6-bit Bank Addressing Table" at the end of
1771                          * this file.*/
1772                         byte = Cols - 9;        /* 9 Cols is smallest dev size */
1773                         byte <<= 3;             /* make room for row and bank bits*/
1774                         if (Banks == 8)
1775                                 byte |= 4;
1776
1777                         /* 13 Rows is smallest dev size */
1778                         byte |= Rows - 13;      /* CCCBRR internal encode */
1779
1780                         for (dword=0; dword < 12; dword++) {
1781                                 if (byte == Tab_BankAddr[dword])
1782                                         break;
1783                         }
1784
1785                         if (dword < 12) {
1786
1787                                 /* bit no. of CS field in address mapping reg.*/
1788                                 dword <<= (ChipSel<<1);
1789                                 BankAddrReg |= dword;
1790
1791                                 /* Mask value=(2pow(rows+cols+banks+3)-1)>>8,
1792                                    or 2pow(rows+cols+banks-5)-1*/
1793                                 csMask = 0;
1794
1795                                 byte = Rows + Cols;             /* cl=rows+cols*/
1796                                 if (Banks == 8)
1797                                         byte -= 2;              /* 3 banks - 5 */
1798                                 else
1799                                         byte -= 3;              /* 2 banks - 5 */
1800                                                                 /* mask size (64-bit rank only) */
1801
1802                                 if (pDCTstat->Status & (1 << SB_128bitmode))
1803                                         byte++;         /* double mask size if in 128-bit mode*/
1804
1805                                 csMask |= 1 << byte;
1806                                 csMask--;
1807
1808                                 /*set ChipSelect population indicator even bits*/
1809                                 pDCTstat->CSPresent |= (1<<ChipSel);
1810                                 if (Ranks >= 2)
1811                                         /*set ChipSelect population indicator odd bits*/
1812                                         pDCTstat->CSPresent |= 1 << (ChipSel + 1);
1813
1814                                 reg = 0x60+(ChipSel<<1) + reg_off;      /*Dram CS Mask Register */
1815                                 val = csMask;
1816                                 val &= 0x1FF83FE0;      /* Mask out reserved bits.*/
1817                                 Set_NB32(dev, reg, val);
1818                         }
1819                 } else {
1820                         if (pDCTstat->DIMMSPDCSE & (1<<ChipSel))
1821                                 pDCTstat->CSTestFail |= (1<<ChipSel);
1822                 }       /* if DIMMValid*/
1823         }       /* while ChipSel*/
1824
1825         SetCSTriState(pMCTstat, pDCTstat, dct);
1826         /* SetCKETriState */
1827         SetODTTriState(pMCTstat, pDCTstat, dct);
1828
1829         if (pDCTstat->Status & (1 << SB_128bitmode)) {
1830                 SetCSTriState(pMCTstat, pDCTstat, 1); /* force dct1) */
1831                 SetODTTriState(pMCTstat, pDCTstat, 1); /* force dct1) */
1832         }
1833         word = pDCTstat->CSPresent;
1834         mctGetCS_ExcludeMap();          /* mask out specified chip-selects */
1835         word ^= pDCTstat->CSPresent;
1836         pDCTstat->CSTestFail |= word;   /* enable ODT to disabled DIMMs */
1837         if (!pDCTstat->CSPresent)
1838                 pDCTstat->ErrCode = SC_StopError;
1839
1840         reg = 0x80 + reg_off;           /* Bank Addressing Register */
1841         Set_NB32(dev, reg, BankAddrReg);
1842
1843 //      dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2));
1844
1845         print_tx("SPDSetBanks: Status ", pDCTstat->Status);
1846         print_tx("SPDSetBanks: ErrStatus ", pDCTstat->ErrStatus);
1847         print_tx("SPDSetBanks: ErrCode ", pDCTstat->ErrCode);
1848         print_t("SPDSetBanks: Done\n");
1849 }
1850
1851
1852 static void SPDCalcWidth_D(struct MCTStatStruc *pMCTstat,
1853                                 struct DCTStatStruc *pDCTstat)
1854 {
1855         /* Per SPDs, check the symmetry of DIMM pairs (DIMM on Channel A
1856          *  matching with DIMM on Channel B), the overall DIMM population,
1857          * and determine the width mode: 64-bit, 64-bit muxed, 128-bit.
1858          */
1859
1860         u8 i;
1861         u8 smbaddr, smbaddr1;
1862         u8 byte, byte1;
1863
1864         /* Check Symmetry of Channel A and Channel B DIMMs
1865           (must be matched for 128-bit mode).*/
1866         for (i=0; i < MAX_DIMMS_SUPPORTED; i += 2) {
1867                 if ((pDCTstat->DIMMValid & (1 << i)) && (pDCTstat->DIMMValid & (1<<(i+1)))) {
1868                         smbaddr = Get_DIMMAddress_D(pDCTstat, i);
1869                         smbaddr1 = Get_DIMMAddress_D(pDCTstat, i+1);
1870
1871                         byte = mctRead_SPD(smbaddr, SPD_ROWSZ) & 0x1f;
1872                         byte1 = mctRead_SPD(smbaddr1, SPD_ROWSZ) & 0x1f;
1873                         if (byte != byte1) {
1874                                 pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO);
1875                                 break;
1876                         }
1877
1878                         byte =   mctRead_SPD(smbaddr, SPD_COLSZ) & 0x1f;
1879                         byte1 =  mctRead_SPD(smbaddr1, SPD_COLSZ) & 0x1f;
1880                         if (byte != byte1) {
1881                                 pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO);
1882                                 break;
1883                         }
1884
1885                         byte = mctRead_SPD(smbaddr, SPD_BANKSZ);
1886                         byte1 = mctRead_SPD(smbaddr1, SPD_BANKSZ);
1887                         if (byte != byte1) {
1888                                 pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO);
1889                                 break;
1890                         }
1891
1892                         byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0x7f;
1893                         byte1 = mctRead_SPD(smbaddr1, SPD_DEVWIDTH) & 0x7f;
1894                         if (byte != byte1) {
1895                                 pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO);
1896                                 break;
1897                         }
1898
1899                         byte = mctRead_SPD(smbaddr, SPD_DMBANKS) & 7;    /* #ranks-1 */
1900                         byte1 = mctRead_SPD(smbaddr1, SPD_DMBANKS) & 7;   /* #ranks-1 */
1901                         if (byte != byte1) {
1902                                 pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO);
1903                                 break;
1904                         }
1905
1906                 }
1907         }
1908
1909 }
1910
1911
1912 static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
1913                                 struct DCTStatStruc *pDCTstat, u8 dct)
1914 {
1915         /* Requires that Mask values for each bank be programmed first and that
1916          * the chip-select population indicator is correctly set.
1917          */
1918
1919         u8 b = 0;
1920         u32 nxtcsBase, curcsBase;
1921         u8 p, q;
1922         u32 Sizeq, BiggestBank;
1923         u8 _DSpareEn;
1924
1925         u16 word;
1926         u32 dev;
1927         u32 reg;
1928         u32 reg_off;
1929         u32 val;
1930
1931
1932         dev = pDCTstat->dev_dct;
1933         reg_off = 0x100 * dct;
1934
1935         _DSpareEn = 0;
1936
1937         /* CS Sparing 1=enabled, 0=disabled */
1938         if (mctGet_NVbits(NV_CS_SpareCTL) & 1) {
1939                 if (MCT_DIMM_SPARE_NO_WARM) {
1940                         /* Do no warm-reset DIMM spare */
1941                         if (pMCTstat->GStatus & 1 << GSB_EnDIMMSpareNW) {
1942                                 word = pDCTstat->CSPresent;
1943                                 val = bsf(word);
1944                                 word &= ~(1<<val);
1945                                 if (word)
1946                                         /* Make sure at least two chip-selects are available */
1947                                         _DSpareEn = 1;
1948                                 else
1949                                         pDCTstat->ErrStatus |= 1 << SB_SpareDis;
1950                         }
1951                 } else {
1952                         if (!mctGet_NVbits(NV_DQSTrainCTL)) { /*DQS Training 1=enabled, 0=disabled */
1953                                 word = pDCTstat->CSPresent;
1954                                 val = bsf(word);
1955                                 word &= ~(1 << val);
1956                                 if (word)
1957                                         /* Make sure at least two chip-selects are available */
1958                                         _DSpareEn = 1;
1959                                 else
1960                                         pDCTstat->ErrStatus |= 1 << SB_SpareDis;
1961                         }
1962                 }
1963         }
1964
1965         nxtcsBase = 0;          /* Next available cs base ADDR[39:8] */
1966         for (p=0; p < MAX_DIMMS_SUPPORTED; p++) {
1967                 BiggestBank = 0;
1968                 for (q = 0; q < MAX_CS_SUPPORTED; q++) { /* from DIMMS to CS */
1969                         if (pDCTstat->CSPresent & (1 << q)) {  /* bank present? */
1970                                 reg  = 0x40 + (q << 2) + reg_off;  /* Base[q] reg.*/
1971                                 val = Get_NB32(dev, reg);
1972                                 if (!(val & 3)) {       /* (CSEnable|Spare==1)bank is enabled already? */
1973                                         reg = 0x60 + (q << 1) + reg_off; /*Mask[q] reg.*/
1974                                         val = Get_NB32(dev, reg);
1975                                         val >>= 19;
1976                                         val++;
1977                                         val <<= 19;
1978                                         Sizeq = val;  //never used
1979                                         if (val > BiggestBank) {
1980                                                 /*Bingo! possibly Map this chip-select next! */
1981                                                 BiggestBank = val;
1982                                                 b = q;
1983                                         }
1984                                 }
1985                         }       /*if bank present */
1986                 }       /* while q */
1987                 if (BiggestBank !=0) {
1988                         curcsBase = nxtcsBase;          /* curcsBase=nxtcsBase*/
1989                         /* DRAM CS Base b Address Register offset */
1990                         reg = 0x40 + (b << 2) + reg_off;
1991                         if (_DSpareEn) {
1992                                 BiggestBank = 0;
1993                                 val = 1 << Spare;       /* Spare Enable*/
1994                         } else {
1995                                 val = curcsBase;
1996                                 val |= 1 << CSEnable;   /* Bank Enable */
1997                         }
1998                         Set_NB32(dev, reg, val);
1999                         if (_DSpareEn)
2000                                 _DSpareEn = 0;
2001                         else
2002                                 /* let nxtcsBase+=Size[b] */
2003                                 nxtcsBase += BiggestBank;
2004                 }
2005
2006                 /* bank present but disabled?*/
2007                 if ( pDCTstat->CSTestFail & (1 << p)) {
2008                         /* DRAM CS Base b Address Register offset */
2009                         reg = (p << 2) + 0x40 + reg_off;
2010                         val = 1 << TestFail;
2011                         Set_NB32(dev, reg, val);
2012                 }
2013         }
2014
2015         if (nxtcsBase) {
2016                 pDCTstat->DCTSysLimit = nxtcsBase - 1;
2017                 mct_AfterStitchMemory(pMCTstat, pDCTstat, dct);
2018         }
2019
2020 //      dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2));
2021
2022         print_tx("StitchMemory: Status ", pDCTstat->Status);
2023         print_tx("StitchMemory: ErrStatus ", pDCTstat->ErrStatus);
2024         print_tx("StitchMemory: ErrCode ", pDCTstat->ErrCode);
2025         print_t("StitchMemory: Done\n");
2026 }
2027
2028
2029 static u8 Get_Tk_D(u8 k)
2030 {
2031         return Table_T_k[k];
2032 }
2033
2034
2035 static u8 Get_CLj_D(u8 j)
2036 {
2037         return Table_CL2_j[j];
2038 }
2039
2040 static u8 Get_DefTrc_k_D(u8 k)
2041 {
2042         return Tab_defTrc_k[k];
2043 }
2044
2045
2046 static u16 Get_40Tk_D(u8 k)
2047 {
2048         return Tab_40T_k[k]; /* FIXME: k or k<<1 ?*/
2049 }
2050
2051
2052 static u16 Get_Fk_D(u8 k)
2053 {
2054         return Table_F_k[k]; /* FIXME: k or k<<1 ? */
2055 }
2056
2057
2058 static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat,
2059                                 u8 i, u8 j, u8 k)
2060 {
2061         u8 Tk, CLj, CL_i;
2062         u8 ret = 0;
2063
2064         u32 DIMMi;
2065         u8 byte;
2066         u16 word, wordx;
2067
2068         DIMMi = Get_DIMMAddress_D(pDCTstat, i);
2069
2070         CLj = Get_CLj_D(j);
2071
2072         /* check if DIMMi supports CLj */
2073         CL_i = mctRead_SPD(DIMMi, SPD_CASLAT);
2074         byte = CL_i & CLj;
2075         if (byte) {
2076                 /*find out if its CL X, CLX-1, or CLX-2 */
2077                 word = bsr(byte);       /* bit position of CLj */
2078                 wordx = bsr(CL_i);      /* bit position of CLX of CLi */
2079                 wordx -= word;          /* CL number (CL no. = 0,1, 2, or 3) */
2080                 wordx <<= 3;            /* 8 bits per SPD byte index */
2081                 /*get T from SPD byte 9, 23, 25*/
2082                 word = (EncodedTSPD >> wordx) & 0xFF;
2083                 Tk = Get_Tk_D(k);
2084                 byte = mctRead_SPD(DIMMi, word);        /* DIMMi speed */
2085                 if (Tk < byte) {
2086                         ret = 1;
2087                 } else if (byte == 0){
2088                         pDCTstat->ErrStatus |= 1<<SB_NoCycTime;
2089                         ret = 1;
2090                 } else {
2091                         ret = 0;        /* DIMM is capable! */
2092                 }
2093         } else {
2094                 ret = 1;
2095         }
2096         return ret;
2097 }
2098
2099
2100 static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
2101                                 struct DCTStatStruc *pDCTstat)
2102 {
2103         /* Check DIMMs present, verify checksum, flag SDRAM type,
2104          * build population indicator bitmaps, and preload bus loading
2105          * of DIMMs into DCTStatStruc.
2106          * MAAload=number of devices on the "A" bus.
2107          * MABload=number of devices on the "B" bus.
2108          * MAAdimms=number of DIMMs on the "A" bus slots.
2109          * MABdimms=number of DIMMs on the "B" bus slots.
2110          * DATAAload=number of ranks on the "A" bus slots.
2111          * DATABload=number of ranks on the "B" bus slots.
2112          */
2113
2114         u16 i, j;
2115         u8 smbaddr, Index;
2116         u16 Checksum;
2117         u8 SPDCtrl;
2118         u16 RegDIMMPresent, MaxDimms;
2119         u8 devwidth;
2120         u16 DimmSlots;
2121         u8 byte = 0, bytex;
2122         u16 word;
2123
2124         /* preload data structure with addrs */
2125         mctGet_DIMMAddr(pDCTstat, pDCTstat->Node_ID);
2126
2127         DimmSlots = MaxDimms = mctGet_NVbits(NV_MAX_DIMMS);
2128
2129         SPDCtrl = mctGet_NVbits(NV_SPDCHK_RESTRT);
2130
2131         RegDIMMPresent = 0;
2132         pDCTstat->DimmQRPresent = 0;
2133
2134         for (i = 0;  i< MAX_DIMMS_SUPPORTED; i++) {
2135                 if (i >= MaxDimms)
2136                         break;
2137
2138                 if ((pDCTstat->DimmQRPresent & (1 << i)) || (i < DimmSlots)) {
2139                         print_tx("\t DIMMPresence: i=", i);
2140                         smbaddr = Get_DIMMAddress_D(pDCTstat, i);
2141                         print_tx("\t DIMMPresence: smbaddr=", smbaddr);
2142                         if (smbaddr) {
2143                                 Checksum = 0;
2144                                 for (Index=0; Index < 64; Index++){
2145                                         int status;
2146                                         status = mctRead_SPD(smbaddr, Index);
2147                                         if (status < 0)
2148                                                 break;
2149                                         byte = status & 0xFF;
2150                                         if (Index < 63)
2151                                                 Checksum += byte;
2152                                 }
2153
2154                                 if (Index == 64) {
2155                                         pDCTstat->DIMMPresent |= 1 << i;
2156                                         if ((Checksum & 0xFF) == byte) {
2157                                                 byte = mctRead_SPD(smbaddr, SPD_TYPE);
2158                                                 if (byte == JED_DDR2SDRAM) {
2159                                                         /*Dimm is 'Present'*/
2160                                                         pDCTstat->DIMMValid |= 1 << i;
2161                                                 }
2162                                         } else {
2163                                                 pDCTstat->DIMMSPDCSE = 1 << i;
2164                                                 if (SPDCtrl == 0) {
2165                                                         pDCTstat->ErrStatus |= 1 << SB_DIMMChkSum;
2166                                                         pDCTstat->ErrCode = SC_StopError;
2167                                                 } else {
2168                                                         /*if NV_SPDCHK_RESTRT is set to 1, ignore faulty SPD checksum*/
2169                                                         pDCTstat->ErrStatus |= 1<<SB_DIMMChkSum;
2170                                                         byte = mctRead_SPD(smbaddr, SPD_TYPE);
2171                                                         if (byte == JED_DDR2SDRAM)
2172                                                                 pDCTstat->DIMMValid |= 1 << i;
2173                                                 }
2174                                         }
2175                                         /* Check module type */
2176                                         byte = mctRead_SPD(smbaddr, SPD_DIMMTYPE);
2177                                         if (byte & JED_REGADCMSK)
2178                                                 RegDIMMPresent |= 1 << i;
2179                                         /* Check ECC capable */
2180                                         byte = mctRead_SPD(smbaddr, SPD_EDCTYPE);
2181                                         if (byte & JED_ECC) {
2182                                                 /* DIMM is ECC capable */
2183                                                 pDCTstat->DimmECCPresent |= 1 << i;
2184                                         }
2185                                         if (byte & JED_ADRCPAR) {
2186                                         /* DIMM is ECC capable */
2187                                         pDCTstat->DimmPARPresent |= 1 << i;
2188                                         }
2189                                         /* Check if x4 device */
2190                                         devwidth = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE;
2191                                         if (devwidth == 4) {
2192                                                 /* DIMM is made with x4 or x16 drams */
2193                                                 pDCTstat->Dimmx4Present |= 1 << i;
2194                                         } else if (devwidth == 8) {
2195                                                 pDCTstat->Dimmx8Present |= 1 << i;
2196                                         } else if (devwidth == 16) {
2197                                                 pDCTstat->Dimmx16Present |= 1 << i;
2198                                         }
2199                                         /* check page size */
2200                                         byte = mctRead_SPD(smbaddr, SPD_COLSZ);
2201                                         byte &= 0x0F;
2202                                         word = 1 << byte;
2203                                         word >>= 3;
2204                                         word *= devwidth;       /* (((2^COLBITS) / 8) * ORG) / 2048 */
2205                                         word >>= 11;
2206                                         if (word)
2207                                                 pDCTstat->DIMM2Kpage |= 1 << i;
2208
2209                                         /*Check if SPD diag bit 'analysis probe installed' is set */
2210                                         byte = mctRead_SPD(smbaddr, SPD_ATTRIB);
2211                                         if ( byte & JED_PROBEMSK )
2212                                                 pDCTstat->Status |= 1<<SB_DiagClks;
2213
2214                                         byte = mctRead_SPD(smbaddr, SPD_DMBANKS);
2215                                         if (!(byte & (1<< SPDPLBit)))
2216                                                 pDCTstat->DimmPlPresent |= 1 << i;
2217                                         byte &= 7;
2218                                         byte++;          /* ranks */
2219                                         if (byte > 2) {
2220                                                 /* if any DIMMs are QR, we have to make two passes through DIMMs*/
2221                                                 if ( pDCTstat->DimmQRPresent == 0) {
2222                                                         MaxDimms <<= 1;
2223                                                 }
2224                                                 if (i < DimmSlots) {
2225                                                         pDCTstat->DimmQRPresent |= (1 << i) | (1 << (i+4));
2226                                                 }
2227                                                 byte = 2;       /* upper two ranks of QR DIMM will be counted on another DIMM number iteration*/
2228                                         } else if (byte == 2) {
2229                                                 pDCTstat->DimmDRPresent |= 1 << i;
2230                                         }
2231                                         bytex = devwidth;
2232                                         if (devwidth == 16)
2233                                                 bytex = 4;
2234                                         else if (devwidth == 4)
2235                                                 bytex=16;
2236
2237                                         if (byte == 2)
2238                                                 bytex <<= 1;    /*double Addr bus load value for dual rank DIMMs*/
2239
2240                                         j = i & (1<<0);
2241                                         pDCTstat->DATAload[j] += byte;  /*number of ranks on DATA bus*/
2242                                         pDCTstat->MAload[j] += bytex;   /*number of devices on CMD/ADDR bus*/
2243                                         pDCTstat->MAdimms[j]++;         /*number of DIMMs on A bus */
2244                                         /*check for DRAM package Year <= 06*/
2245                                         byte = mctRead_SPD(smbaddr, SPD_MANDATEYR);
2246                                         if (byte < MYEAR06) {
2247                                                 /*Year < 06 and hence Week < 24 of 06 */
2248                                                 pDCTstat->DimmYr06 |= 1 << i;
2249                                                 pDCTstat->DimmWk2406 |= 1 << i;
2250                                         } else if (byte == MYEAR06) {
2251                                                 /*Year = 06, check if Week <= 24 */
2252                                                 pDCTstat->DimmYr06 |= 1 << i;
2253                                                 byte = mctRead_SPD(smbaddr, SPD_MANDATEWK);
2254                                                 if (byte <= MWEEK24)
2255                                                         pDCTstat->DimmWk2406 |= 1 << i;
2256                                         }
2257                                 }
2258                         }
2259                 }
2260         }
2261         print_tx("\t DIMMPresence: DIMMValid=", pDCTstat->DIMMValid);
2262         print_tx("\t DIMMPresence: DIMMPresent=", pDCTstat->DIMMPresent);
2263         print_tx("\t DIMMPresence: RegDIMMPresent=", RegDIMMPresent);
2264         print_tx("\t DIMMPresence: DimmECCPresent=", pDCTstat->DimmECCPresent);
2265         print_tx("\t DIMMPresence: DimmPARPresent=", pDCTstat->DimmPARPresent);
2266         print_tx("\t DIMMPresence: Dimmx4Present=", pDCTstat->Dimmx4Present);
2267         print_tx("\t DIMMPresence: Dimmx8Present=", pDCTstat->Dimmx8Present);
2268         print_tx("\t DIMMPresence: Dimmx16Present=", pDCTstat->Dimmx16Present);
2269         print_tx("\t DIMMPresence: DimmPlPresent=", pDCTstat->DimmPlPresent);
2270         print_tx("\t DIMMPresence: DimmDRPresent=", pDCTstat->DimmDRPresent);
2271         print_tx("\t DIMMPresence: DimmQRPresent=", pDCTstat->DimmQRPresent);
2272         print_tx("\t DIMMPresence: DATAload[0]=", pDCTstat->DATAload[0]);
2273         print_tx("\t DIMMPresence: MAload[0]=", pDCTstat->MAload[0]);
2274         print_tx("\t DIMMPresence: MAdimms[0]=", pDCTstat->MAdimms[0]);
2275         print_tx("\t DIMMPresence: DATAload[1]=", pDCTstat->DATAload[1]);
2276         print_tx("\t DIMMPresence: MAload[1]=", pDCTstat->MAload[1]);
2277         print_tx("\t DIMMPresence: MAdimms[1]=", pDCTstat->MAdimms[1]);
2278
2279         if (pDCTstat->DIMMValid != 0) { /* If any DIMMs are present...*/
2280                 if (RegDIMMPresent != 0) {
2281                         if ((RegDIMMPresent ^ pDCTstat->DIMMValid) !=0) {
2282                                 /* module type DIMM mismatch (reg'ed, unbuffered) */
2283                                 pDCTstat->ErrStatus |= 1<<SB_DimmMismatchM;
2284                                 pDCTstat->ErrCode = SC_StopError;
2285                         } else{
2286                                 /* all DIMMs are registered */
2287                                 pDCTstat->Status |= 1<<SB_Registered;
2288                         }
2289                 }
2290                 if (pDCTstat->DimmECCPresent != 0) {
2291                         if ((pDCTstat->DimmECCPresent ^ pDCTstat->DIMMValid )== 0) {
2292                                 /* all DIMMs are ECC capable */
2293                                 pDCTstat->Status |= 1<<SB_ECCDIMMs;
2294                         }
2295                 }
2296                 if (pDCTstat->DimmPARPresent != 0) {
2297                         if ((pDCTstat->DimmPARPresent ^ pDCTstat->DIMMValid) == 0) {
2298                                 /*all DIMMs are Parity capable */
2299                                 pDCTstat->Status |= 1<<SB_PARDIMMs;
2300                         }
2301                 }
2302         } else {
2303                 /* no DIMMs present or no DIMMs that qualified. */
2304                 pDCTstat->ErrStatus |= 1<<SB_NoDimms;
2305                 pDCTstat->ErrCode = SC_StopError;
2306         }
2307
2308         print_tx("\t DIMMPresence: Status ", pDCTstat->Status);
2309         print_tx("\t DIMMPresence: ErrStatus ", pDCTstat->ErrStatus);
2310         print_tx("\t DIMMPresence: ErrCode ", pDCTstat->ErrCode);
2311         print_t("\t DIMMPresence: Done\n");
2312
2313         mctHookAfterDIMMpre();
2314
2315         return pDCTstat->ErrCode;
2316 }
2317
2318
2319 static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat,
2320                                 struct DCTStatStruc *pDCTstat, int j, int k)
2321 {
2322         /* Determine if system is capable of operating at given input
2323          * parameters for CL, and T.  There are three components to
2324          * determining "maximum frequency" in AUTO mode: SPD component,
2325          * Bus load component, and "Preset" max frequency component.
2326          * This procedure is used to help find the SPD component and relies
2327          * on pre-determination of the bus load component and the Preset
2328          * components.  The generalized algorithm for finding maximum
2329          * frequency is structured this way so as to optimize for CAS
2330          * latency (which might get better as a result of reduced frequency).
2331          * See "Global relationship between index values and item values"
2332          * for definition of CAS latency index (j) and Frequency index (k).
2333          */
2334         u8 freqOK, ClOK;
2335         u8 ret = 0;
2336
2337         if (Get_Fk_D(k) > pDCTstat->PresetmaxFreq)
2338                 freqOK = 0;
2339         else
2340                 freqOK = 1;
2341
2342         /* compare proposed CAS latency with AMD Si capabilities */
2343         if ((j < J_MIN) || (j > J_MAX))
2344                 ClOK = 0;
2345         else
2346                 ClOK = 1;
2347
2348         if (freqOK && ClOK)
2349                 ret = 1;
2350
2351         return ret;
2352 }
2353
2354
2355 static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i)
2356 {
2357         u8 *p;
2358
2359         p = pDCTstat->DIMMAddr;
2360         //mct_BeforeGetDIMMAddress();
2361         return p[i];
2362 }
2363
2364
2365 static void mct_initDCT(struct MCTStatStruc *pMCTstat,
2366                                 struct DCTStatStruc *pDCTstat)
2367 {
2368         u32 val;
2369         u8 err_code;
2370
2371         /* Config. DCT0 for Ganged or unganged mode */
2372         print_t("\tmct_initDCT: DCTInit_D 0\n");
2373         DCTInit_D(pMCTstat, pDCTstat, 0);
2374         if (pDCTstat->ErrCode == SC_FatalErr) {
2375                 // Do nothing goto exitDCTInit; /* any fatal errors? */
2376         } else {
2377                 /* Configure DCT1 if unganged and enabled*/
2378                 if (!pDCTstat->GangedMode) {
2379                         if ( pDCTstat->DIMMValidDCT[1] > 0) {
2380                                 print_t("\tmct_initDCT: DCTInit_D 1\n");
2381                                 err_code = pDCTstat->ErrCode;           /* save DCT0 errors */
2382                                 pDCTstat->ErrCode = 0;
2383                                 DCTInit_D(pMCTstat, pDCTstat, 1);
2384                                 if (pDCTstat->ErrCode == 2)             /* DCT1 is not Running */
2385                                         pDCTstat->ErrCode = err_code;   /* Using DCT0 Error code to update pDCTstat.ErrCode */
2386                         } else {
2387                                 val = 1 << DisDramInterface;
2388                                 Set_NB32(pDCTstat->dev_dct, 0x100 + 0x94, val);
2389                         }
2390                 }
2391         }
2392 // exitDCTInit:
2393 }
2394
2395
2396 static void mct_DramInit(struct MCTStatStruc *pMCTstat,
2397                                 struct DCTStatStruc *pDCTstat, u8 dct)
2398 {
2399         u32 val;
2400
2401         mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat);
2402         // FIXME: for rev A: mct_BeforeDramInit_D(pDCTstat, dct);
2403
2404         /* Disable auto refresh before Dram init when in ganged mode */
2405         if (pDCTstat->GangedMode) {
2406                 val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
2407                 val |= 1 << DisAutoRefresh;
2408                 Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
2409         }
2410
2411         mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct);
2412
2413         /* Re-enable auto refresh after Dram init when in ganged mode
2414          * to ensure both DCTs are in sync
2415          */
2416
2417         if (pDCTstat->GangedMode) {
2418                 do {
2419                         val = Get_NB32(pDCTstat->dev_dct, 0x90 + (0x100 * dct));
2420                 } while (!(val & (1 << InitDram)));
2421
2422                 WaitRoutine_D(50);
2423
2424                 val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
2425                 val &= ~(1 << DisAutoRefresh);
2426                 val |= 1 << DisAutoRefresh;
2427                 val &= ~(1 << DisAutoRefresh);
2428         }
2429 }
2430
2431
2432 static u8 mct_setMode(struct MCTStatStruc *pMCTstat,
2433                                 struct DCTStatStruc *pDCTstat)
2434 {
2435         u8 byte;
2436         u8 bytex;
2437         u32 val;
2438         u32 reg;
2439
2440         byte = bytex = pDCTstat->DIMMValid;
2441         bytex &= 0x55;          /* CHA DIMM pop */
2442         pDCTstat->DIMMValidDCT[0] = bytex;
2443
2444         byte &= 0xAA;           /* CHB DIMM popa */
2445         byte >>= 1;
2446         pDCTstat->DIMMValidDCT[1] = byte;
2447
2448         if (byte != bytex) {
2449                 pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO);
2450         } else {
2451         if ( mctGet_NVbits(NV_Unganged) )
2452                 pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO);
2453
2454                 if (!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) {
2455                         pDCTstat->GangedMode = 1;
2456                         /* valid 128-bit mode population. */
2457                         pDCTstat->Status |= 1 << SB_128bitmode;
2458                         reg = 0x110;
2459                         val = Get_NB32(pDCTstat->dev_dct, reg);
2460                         val |= 1 << DctGangEn;
2461                         Set_NB32(pDCTstat->dev_dct, reg, val);
2462                         print_tx("setMode: DRAM Controller Select Low Register = ", val);
2463                 }
2464         }
2465         return pDCTstat->ErrCode;
2466 }
2467
2468
2469 u32 Get_NB32(u32 dev, u32 reg)
2470 {
2471         u32 addr;
2472
2473         addr = (dev>>4) | (reg & 0xFF) | ((reg & 0xf00)<<16);
2474         outl((1<<31) | (addr & ~3), 0xcf8);
2475
2476         return inl(0xcfc);
2477 }
2478
2479
2480 void Set_NB32(u32 dev, u32 reg, u32 val)
2481 {
2482         u32 addr;
2483
2484         addr = (dev>>4) | (reg & 0xFF) | ((reg & 0xf00)<<16);
2485         outl((1<<31) | (addr & ~3), 0xcf8);
2486         outl(val, 0xcfc);
2487 }
2488
2489
2490 u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index)
2491 {
2492         u32 dword;
2493
2494         Set_NB32(dev, index_reg, index);
2495         dword = Get_NB32(dev, index_reg+0x4);
2496
2497         return dword;
2498 }
2499
2500 void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data)
2501 {
2502         Set_NB32(dev, index_reg, index);
2503         Set_NB32(dev, index_reg + 0x4, data);
2504 }
2505
2506
2507 u32 Get_NB32_index_wait(u32 dev, u32 index_reg, u32 index)
2508 {
2509
2510         u32 dword;
2511
2512
2513         index &= ~(1 << DctAccessWrite);
2514         Set_NB32(dev, index_reg, index);
2515         do {
2516                 dword = Get_NB32(dev, index_reg);
2517         } while (!(dword & (1 << DctAccessDone)));
2518         dword = Get_NB32(dev, index_reg + 0x4);
2519
2520         return dword;
2521 }
2522
2523
2524 void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data)
2525 {
2526         u32 dword;
2527
2528
2529         Set_NB32(dev, index_reg + 0x4, data);
2530         index |= (1 << DctAccessWrite);
2531         Set_NB32(dev, index_reg, index);
2532         do {
2533                 dword = Get_NB32(dev, index_reg);
2534         } while (!(dword & (1 << DctAccessDone)));
2535
2536 }
2537
2538
2539 static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
2540                                         struct DCTStatStruc *pDCTstat, u8 dct)
2541 {
2542         /* Get platform specific config/timing values from the interface layer
2543          * and program them into DCT.
2544          */
2545
2546         u32 dev = pDCTstat->dev_dct;
2547         u32 index_reg;
2548         u8 i, i_start, i_end;
2549
2550         if (pDCTstat->GangedMode) {
2551                 SyncSetting(pDCTstat);
2552                 i_start = 0;
2553                 i_end = 2;
2554         } else {
2555                 i_start = dct;
2556                 i_end = dct + 1;
2557         }
2558         for (i=i_start; i<i_end; i++) {
2559                 index_reg = 0x98 + (i * 0x100);
2560                 Set_NB32_index_wait(dev, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A Output Driver Compensation Control */
2561                 Set_NB32_index_wait(dev, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A Output Driver Compensation Control */
2562         }
2563
2564         return pDCTstat->ErrCode;
2565
2566 }
2567
2568
2569 static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat)
2570 {
2571         u32 dev;
2572         u32 val;
2573
2574         if (pDCTstat->NodePresent) {
2575                 print_tx("mct_SyncDCTsReady: Node ", pDCTstat->Node_ID);
2576                 dev = pDCTstat->dev_dct;
2577
2578                 if ((pDCTstat->DIMMValidDCT[0] ) || (pDCTstat->DIMMValidDCT[1])) {              /* This Node has dram */
2579                         do {
2580                                 val = Get_NB32(dev, 0x110);
2581                         } while (!(val & (1 << DramEnabled)));
2582                         print_t("mct_SyncDCTsReady: DramEnabled\n");
2583                 }
2584         }       /* Node is present */
2585 }
2586
2587
2588 static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat,
2589                                 struct DCTStatStruc *pDCTstat, u8 dct)
2590 {
2591         if (!pDCTstat->GangedMode) {
2592                 if (dct == 0 ) {
2593                         pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
2594                         if (pDCTstat->DIMMValidDCT[dct] == 0)
2595                                 pDCTstat->ErrCode = SC_StopError;
2596                 } else {
2597                         pDCTstat->CSPresent = 0;
2598                         pDCTstat->CSTestFail = 0;
2599                         pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
2600                         if (pDCTstat->DIMMValidDCT[dct] == 0)
2601                                 pDCTstat->ErrCode = SC_StopError;
2602                 }
2603         }
2604 }
2605
2606 static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,
2607                                         struct DCTStatStruc *pDCTstat, u8 dct)
2608 {
2609         u8 ret;
2610
2611         if ( dct == 0) {
2612                 SPDCalcWidth_D(pMCTstat, pDCTstat);
2613                 ret = mct_setMode(pMCTstat, pDCTstat);
2614         } else {
2615                 ret = pDCTstat->ErrCode;
2616         }
2617
2618         print_tx("SPDCalcWidth: Status ", pDCTstat->Status);
2619         print_tx("SPDCalcWidth: ErrStatus ", pDCTstat->ErrStatus);
2620         print_tx("SPDCalcWidth: ErrCode ", pDCTstat->ErrCode);
2621         print_t("SPDCalcWidth: Done\n");
2622
2623         return ret;
2624 }
2625
2626
2627 static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat,
2628                                         struct DCTStatStruc *pDCTstat, u8 dct)
2629 {
2630         u32 val;
2631         u32 dword;
2632         u32 dev;
2633         u32 reg;
2634         u8 _MemHoleRemap;
2635         u32 DramHoleBase;
2636
2637         _MemHoleRemap = mctGet_NVbits(NV_MemHole);
2638         DramHoleBase = mctGet_NVbits(NV_BottomIO);
2639         DramHoleBase <<= 8;
2640         /* Increase hole size so;[31:24]to[31:16]
2641          * it has granularity of 128MB shl eax,8
2642          * Set 'effective' bottom IOmov DramHoleBase,eax
2643          */
2644         pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
2645
2646         /* In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */
2647         if (!pDCTstat->GangedMode) {
2648                 dev = pDCTstat->dev_dct;
2649                 pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit;
2650                 /* if DCT0 and DCT1 both exist, set DctSelBaseAddr[47:27] to the top of DCT0 */
2651                 if (dct == 0) {
2652                         if (pDCTstat->DIMMValidDCT[1] > 0) {
2653                                 dword = pDCTstat->DCTSysLimit + 1;
2654                                 dword += pDCTstat->NodeSysBase;
2655                                 dword >>= 8; /* scale [39:8] to [47:27],and to F2x110[31:11] */
2656                                 if ((dword >= DramHoleBase) && _MemHoleRemap) {
2657                                         pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
2658                                         val = pMCTstat->HoleBase;
2659                                         val >>= 16;
2660                                         val = (((~val) & 0xFF) + 1);
2661                                         val <<= 8;
2662                                         dword += val;
2663                                 }
2664                                 reg = 0x110;
2665                                 val = Get_NB32(dev, reg);
2666                                 val &= 0x7F;
2667                                 val |= dword;
2668                                 val |= 3;  /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */
2669                                 Set_NB32(dev, reg, val);
2670                                 print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select Low Register = ", val);
2671                                 print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select High Register = ", dword);
2672
2673                                 reg = 0x114;
2674                                 val = dword;
2675                                 Set_NB32(dev, reg, val);
2676                         }
2677                 } else {
2678                         /* Program the DctSelBaseAddr value to 0
2679                            if DCT 0 is disabled */
2680                         if (pDCTstat->DIMMValidDCT[0] == 0) {
2681                                 dword = pDCTstat->NodeSysBase;
2682                                 dword >>= 8;
2683                                 if ((dword >= DramHoleBase) && _MemHoleRemap) {
2684                                         pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
2685                                         val = pMCTstat->HoleBase;
2686                                         val >>= 8;
2687                                         val &= ~(0xFFFF);
2688                                         val |= (((~val) & 0xFFFF) + 1);
2689                                         dword += val;
2690                                 }
2691                                 reg = 0x114;
2692                                 val = dword;
2693                                 Set_NB32(dev, reg, val);
2694
2695                                 reg = 0x110;
2696                                 val |= 3;       /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */
2697                                 Set_NB32(dev, reg, val);
2698                                 print_tx("AfterStitch DCT1 only: DRAM Controller Select Low Register = ", val);
2699                                 print_tx("AfterStitch DCT1 only: DRAM Controller Select High Register = ", dword);
2700                         }
2701                 }
2702         } else {
2703                 pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit;
2704         }
2705         print_tx("AfterStitch pDCTstat->NodeSysBase = ", pDCTstat->NodeSysBase);
2706         print_tx("mct_AfterStitchMemory: pDCTstat->NodeSysLimit ", pDCTstat->NodeSysLimit);
2707 }
2708
2709
2710 static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat,
2711                                         struct DCTStatStruc *pDCTstat, u8 dct)
2712 {
2713         u8 ret;
2714
2715         if ( dct == 0)
2716                 ret = DIMMPresence_D(pMCTstat, pDCTstat);
2717         else
2718                 ret = pDCTstat->ErrCode;
2719
2720         return ret;
2721 }
2722
2723
2724 /* mct_BeforeGetDIMMAddress inline in C */
2725
2726
2727 static void mct_OtherTiming(struct MCTStatStruc *pMCTstat,
2728                                 struct DCTStatStruc *pDCTstatA)
2729 {
2730         u8 Node;
2731
2732         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
2733                 struct DCTStatStruc *pDCTstat;
2734                 pDCTstat = pDCTstatA + Node;
2735                 if (pDCTstat->NodePresent) {
2736                         if (pDCTstat->DIMMValidDCT[0]) {
2737                                 pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[0];
2738                                 Set_OtherTiming(pMCTstat, pDCTstat, 0);
2739                         }
2740                         if (pDCTstat->DIMMValidDCT[1] && !pDCTstat->GangedMode ) {
2741                                 pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[1];
2742                                 Set_OtherTiming(pMCTstat, pDCTstat, 1);
2743                         }
2744                 }       /* Node is present*/
2745         }       /* while Node */
2746 }
2747
2748
2749 static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
2750                                 struct DCTStatStruc *pDCTstat, u8 dct)
2751 {
2752         u32 reg;
2753         u32 reg_off = 0x100 * dct;
2754         u32 val;
2755         u32 dword;
2756         u32 dev = pDCTstat->dev_dct;
2757
2758         Get_Trdrd(pMCTstat, pDCTstat, dct);
2759         Get_Twrwr(pMCTstat, pDCTstat, dct);
2760         Get_Twrrd(pMCTstat, pDCTstat, dct);
2761         Get_TrwtTO(pMCTstat, pDCTstat, dct);
2762         Get_TrwtWB(pMCTstat, pDCTstat);
2763
2764         reg = 0x8C + reg_off;           /* Dram Timing Hi */
2765         val = Get_NB32(dev, reg);
2766         val &= 0xffff0300;
2767         dword = pDCTstat->TrwtTO; //0x07
2768         val |= dword << 4;
2769         dword = pDCTstat->Twrrd; //0x03
2770         val |= dword << 10;
2771         dword = pDCTstat->Twrwr; //0x03
2772         val |= dword << 12;
2773         dword = pDCTstat->Trdrd; //0x03
2774         val |= dword << 14;
2775         dword = pDCTstat->TrwtWB; //0x07
2776         val |= dword;
2777         val = OtherTiming_A_D(pDCTstat, val);
2778         Set_NB32(dev, reg, val);
2779
2780 }
2781
2782
2783 static void Get_Trdrd(struct MCTStatStruc *pMCTstat,
2784                         struct DCTStatStruc *pDCTstat, u8 dct)
2785 {
2786         u8 Trdrd;
2787         u8 byte;
2788         u32 dword;
2789         u32 val;
2790         u32 index_reg = 0x98 + 0x100 * dct;
2791         u32 dev = pDCTstat->dev_dct;
2792
2793         if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) {
2794                 /* mixed (x4 or x8) DIMM types
2795                   the largest DqsRcvEnGrossDelay of any DIMM minus the DqsRcvEnGrossDelay
2796                   of any other DIMM is equal to the Critical Gross Delay Difference (CGDD) for Trdrd.*/
2797                 byte = Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
2798                 if (byte == 0)
2799                         Trdrd = 1;
2800                 else
2801                         Trdrd = 2;
2802
2803         } else {
2804                 /*
2805                  Trdrd with non-mixed DIMM types
2806                  RdDqsTime are the same for all DIMMs and DqsRcvEn difference between
2807                  any two DIMMs is less than half of a MEMCLK, BIOS should program Trdrd to 0000b,
2808                  else BIOS should program Trdrd to 0001b.
2809
2810                  RdDqsTime are the same for all DIMMs
2811                  DDR400~DDR667 only use one set register
2812                  DDR800 have two set register for DIMM0 and DIMM1 */
2813                 Trdrd = 1;
2814                 if (pDCTstat->Speed > 3) {
2815                         /* DIMM0+DIMM1 exist */ //NOTE it should be 5
2816                         val = bsf(pDCTstat->DIMMValid);
2817                         dword = bsr(pDCTstat->DIMMValid);
2818                         if (dword != val && dword != 0)  {
2819                                 /* DCT Read DQS Timing Control - DIMM0 - Low */
2820                                 dword = Get_NB32_index_wait(dev, index_reg, 0x05);
2821                                 /* DCT Read DQS Timing Control - DIMM1 - Low */
2822                                 val = Get_NB32_index_wait(dev, index_reg, 0x105);
2823                                 if (val != dword)
2824                                         goto Trdrd_1;
2825
2826                                 /* DCT Read DQS Timing Control - DIMM0 - High */
2827                                 dword = Get_NB32_index_wait(dev, index_reg, 0x06);
2828                                 /* DCT Read DQS Timing Control - DIMM1 - High */
2829                                 val = Get_NB32_index_wait(dev, index_reg, 0x106);
2830                                 if (val != dword)
2831                                         goto Trdrd_1;
2832                         }
2833                 }
2834
2835                 /* DqsRcvEn difference between any two DIMMs is
2836                    less than half of a MEMCLK */
2837                 /* DqsRcvEn byte 1,0*/
2838                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x10))
2839                         goto Trdrd_1;
2840                 /* DqsRcvEn byte 3,2*/
2841                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x11))
2842                         goto Trdrd_1;
2843                 /* DqsRcvEn byte 5,4*/
2844                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x20))
2845                         goto Trdrd_1;
2846                 /* DqsRcvEn byte 7,6*/
2847                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x21))
2848                         goto Trdrd_1;
2849                 /* DqsRcvEn ECC*/
2850                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x12))
2851                         goto Trdrd_1;
2852                 Trdrd = 0;
2853         Trdrd_1:
2854                 ;
2855         }
2856         pDCTstat->Trdrd = Trdrd;
2857
2858 }
2859
2860
2861 static void Get_Twrwr(struct MCTStatStruc *pMCTstat,
2862                         struct DCTStatStruc *pDCTstat, u8 dct)
2863 {
2864         u8 Twrwr = 0;
2865         u32 index_reg = 0x98 + 0x100 * dct;
2866         u32 dev = pDCTstat->dev_dct;
2867         u32 val;
2868         u32 dword;
2869
2870         /* WrDatGrossDlyByte only use one set register when DDR400~DDR667
2871            DDR800 have two set register for DIMM0 and DIMM1 */
2872         if (pDCTstat->Speed > 3) {
2873                 val = bsf(pDCTstat->DIMMValid);
2874                 dword = bsr(pDCTstat->DIMMValid);
2875                 if (dword != val && dword != 0)  {
2876                         /*the largest WrDatGrossDlyByte of any DIMM minus the
2877                         WrDatGrossDlyByte of any other DIMM is equal to CGDD */
2878                         val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
2879                 }
2880                 if (val == 0)
2881                         Twrwr = 2;
2882                 else
2883                         Twrwr = 3;
2884         }
2885         pDCTstat->Twrwr = Twrwr;
2886 }
2887
2888
2889 static void Get_Twrrd(struct MCTStatStruc *pMCTstat,
2890                         struct DCTStatStruc *pDCTstat, u8 dct)
2891 {
2892         u8 byte, bytex, val;
2893         u32 index_reg = 0x98 + 0x100 * dct;
2894         u32 dev = pDCTstat->dev_dct;
2895
2896         /* On any given byte lane, the largest WrDatGrossDlyByte delay of
2897            any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is
2898            equal to the Critical Gross Delay Difference (CGDD) for Twrrd.*/
2899
2900         /* WrDatGrossDlyByte only use one set register when DDR400~DDR667
2901            DDR800 have two set register for DIMM0 and DIMM1 */
2902         if (pDCTstat->Speed > 3) {
2903                 val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
2904         } else {
2905                 val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 1);  /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */
2906                 pDCTstat->WrDatGrossH = (u8) val; /* low byte = max value */
2907         }
2908
2909         Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
2910
2911         bytex = pDCTstat->DqsRcvEnGrossL;
2912         byte = pDCTstat->WrDatGrossH;
2913         if (byte > bytex) {
2914                 byte -= bytex;
2915                 if (byte == 1)
2916                         bytex = 1;
2917                 else
2918                         bytex = 2;
2919         } else {
2920                 bytex = 0;
2921         }
2922         pDCTstat->Twrrd = bytex;
2923 }
2924
2925
2926 static void Get_TrwtTO(struct MCTStatStruc *pMCTstat,
2927                         struct DCTStatStruc *pDCTstat, u8 dct)
2928 {
2929         u8 byte, bytex;
2930         u32 index_reg = 0x98 + 0x100 * dct;
2931         u32 dev = pDCTstat->dev_dct;
2932
2933         /* On any given byte lane, the largest WrDatGrossDlyByte delay of
2934            any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is
2935            equal to the Critical Gross Delay Difference (CGDD) for TrwtTO. */
2936         Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
2937         Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
2938         bytex = pDCTstat->DqsRcvEnGrossL;
2939         byte = pDCTstat->WrDatGrossH;
2940         if (bytex > byte) {
2941                 bytex -= byte;
2942                 if ((bytex == 1) || (bytex == 2))
2943                         bytex = 3;
2944                 else
2945                         bytex = 4;
2946         } else {
2947                 byte -= bytex;
2948                 if ((byte == 0) || (byte == 1))
2949                         bytex = 2;
2950                 else
2951                         bytex = 1;
2952         }
2953
2954         pDCTstat->TrwtTO = bytex;
2955 }
2956
2957
2958 static void Get_TrwtWB(struct MCTStatStruc *pMCTstat,
2959                         struct DCTStatStruc *pDCTstat)
2960 {
2961         /* TrwtWB ensures read-to-write data-bus turnaround.
2962            This value should be one more than the programmed TrwtTO.*/
2963         pDCTstat->TrwtWB = pDCTstat->TrwtTO + 1;
2964 }
2965
2966
2967 static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat,
2968                                         u8 dct, u32 dev, u32 index_reg,
2969                                         u32 index)
2970 {
2971         u8 Smallest_0, Largest_0, Smallest_1, Largest_1;
2972         u8 i;
2973         u32 val;
2974         u8 byte;
2975         u8 ecc_reg = 0;
2976
2977         Smallest_0 = 0xFF;
2978         Smallest_1 = 0xFF;
2979         Largest_0 = 0;
2980         Largest_1 = 0;
2981
2982         if (index == 0x12)
2983                 ecc_reg = 1;
2984
2985         for (i=0; i < 8; i+=2) {
2986                 if ( pDCTstat->DIMMValid & (1 << i)) {
2987                         val = Get_NB32_index_wait(dev, index_reg, index);
2988                         byte = val & 0xFF;
2989                         if (byte < Smallest_0)
2990                                 Smallest_0 = byte;
2991                         if (byte > Largest_0)
2992                                 Largest_0 = byte;
2993                         if (!(ecc_reg)) {
2994                                 byte = (val >> 16) & 0xFF;
2995                                 if (byte < Smallest_1)
2996                                         Smallest_1 = byte;
2997                                 if (byte > Largest_1)
2998                                         Largest_1 = byte;
2999                         }
3000                 }
3001                 index += 3;
3002         }       /* while ++i */
3003
3004         /* check if total DqsRcvEn delay difference between any
3005            two DIMMs is less than half of a MEMCLK */
3006         if ((Largest_0 - Smallest_0) > 31)
3007                 return 1;
3008         if (!(ecc_reg))
3009                 if ((Largest_1 - Smallest_1) > 31)
3010                         return 1;
3011         return 0;
3012 }
3013
3014
3015 static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
3016                                         u32 dev, u32 index_reg)
3017 {
3018         u8 Smallest, Largest;
3019         u32 val;
3020         u8 byte, bytex;
3021
3022         /* The largest DqsRcvEnGrossDelay of any DIMM minus the
3023            DqsRcvEnGrossDelay of any other DIMM is equal to the Critical
3024            Gross Delay Difference (CGDD) */
3025         /* DqsRcvEn byte 1,0 */
3026         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x10);
3027         Largest = val & 0xFF;
3028         Smallest = (val >> 8) & 0xFF;
3029
3030         /* DqsRcvEn byte 3,2 */
3031         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x11);
3032         byte = val & 0xFF;
3033         bytex = (val >> 8) & 0xFF;
3034         if (bytex < Smallest)
3035                 Smallest = bytex;
3036         if (byte > Largest)
3037                 Largest = byte;
3038
3039         /* DqsRcvEn byte 5,4 */
3040         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x20);
3041         byte = val & 0xFF;
3042         bytex = (val >> 8) & 0xFF;
3043         if (bytex < Smallest)
3044                 Smallest = bytex;
3045         if (byte > Largest)
3046                 Largest = byte;
3047
3048         /* DqsRcvEn byte 7,6 */
3049         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x21);
3050         byte = val & 0xFF;
3051         bytex = (val >> 8) & 0xFF;
3052         if (bytex < Smallest)
3053                 Smallest = bytex;
3054         if (byte > Largest)
3055                 Largest = byte;
3056
3057         if (pDCTstat->DimmECCPresent> 0) {
3058                 /*DqsRcvEn Ecc */
3059                 val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x12);
3060                 byte = val & 0xFF;
3061                 bytex = (val >> 8) & 0xFF;
3062                 if (bytex < Smallest)
3063                         Smallest = bytex;
3064                 if (byte > Largest)
3065                         Largest = byte;
3066         }
3067
3068         pDCTstat->DqsRcvEnGrossL = Largest;
3069         return Largest - Smallest;
3070 }
3071
3072
3073 static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat,
3074                                         u8 dct, u32 dev, u32 index_reg)
3075 {
3076         u8 Smallest, Largest;
3077         u32 val;
3078         u8 byte, bytex;
3079
3080         /* The largest WrDatGrossDlyByte of any DIMM minus the
3081           WrDatGrossDlyByte of any other DIMM is equal to CGDD */
3082         val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x01);       /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */
3083         Largest = val & 0xFF;
3084         Smallest = (val >> 8) & 0xFF;
3085         val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x101);      /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM1 */
3086         byte = val & 0xFF;
3087         bytex = (val >> 8) & 0xFF;
3088         if (bytex < Smallest)
3089                 Smallest = bytex;
3090         if (byte > Largest)
3091                 Largest = byte;
3092
3093         // FIXME: Add Cx support.
3094
3095         pDCTstat->WrDatGrossH = Largest;
3096         return Largest - Smallest;
3097 }
3098
3099 static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
3100                                         u32 dev, u32 index_reg,
3101                                         u32 index)
3102 {
3103         u8 Smallest, Largest;
3104         u8 i;
3105         u8 byte;
3106         u32 val;
3107         u16 word;
3108         u8 ecc_reg = 0;
3109
3110         Smallest = 7;
3111         Largest = 0;
3112
3113         if (index == 0x12)
3114                 ecc_reg = 1;
3115
3116         for (i=0; i < 8; i+=2) {
3117                 if ( pDCTstat->DIMMValid & (1 << i)) {
3118                         val = Get_NB32_index_wait(dev, index_reg, index);
3119                         val &= 0x00E000E0;
3120                         byte = (val >> 5) & 0xFF;
3121                         if (byte < Smallest)
3122                                 Smallest = byte;
3123                         if (byte > Largest)
3124                                 Largest = byte;
3125                         if (!(ecc_reg)) {
3126                                 byte = (val >> (16 + 5)) & 0xFF;
3127                                 if (byte < Smallest)
3128                                         Smallest = byte;
3129                                 if (byte > Largest)
3130                                         Largest = byte;
3131                         }
3132                 }
3133         index += 3;
3134         }       /* while ++i */
3135
3136         word = Smallest;
3137         word <<= 8;
3138         word |= Largest;
3139
3140         return word;
3141 }
3142
3143 static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat,
3144                                         u8 dct, u32 dev, u32 index_reg,
3145                                         u32 index)
3146 {
3147         u8 Smallest, Largest;
3148         u8 i, j;
3149         u32 val;
3150         u8 byte;
3151         u16 word;
3152
3153         Smallest = 3;
3154         Largest = 0;
3155         for (i=0; i < 2; i++) {
3156                 val = Get_NB32_index_wait(dev, index_reg, index);
3157                 val &= 0x60606060;
3158                 val >>= 5;
3159                 for (j=0; j < 4; j++) {
3160                         byte = val & 0xFF;
3161                         if (byte < Smallest)
3162                                 Smallest = byte;
3163                         if (byte > Largest)
3164                                 Largest = byte;
3165                         val >>= 8;
3166                 }       /* while ++j */
3167                 index++;
3168         }       /*while ++i*/
3169
3170         if (pDCTstat->DimmECCPresent > 0) {
3171                 index++;
3172                 val = Get_NB32_index_wait(dev, index_reg, index);
3173                 val &= 0x00000060;
3174                 val >>= 5;
3175                 byte = val & 0xFF;
3176                 if (byte < Smallest)
3177                         Smallest = byte;
3178                 if (byte > Largest)
3179                         Largest = byte;
3180         }
3181
3182         word = Smallest;
3183         word <<= 8;
3184         word |= Largest;
3185
3186         return word;
3187 }
3188
3189
3190
3191 static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
3192                                 struct DCTStatStruc *pDCTstat)
3193 {
3194         print_t("\tmct_FinalMCT_D: Clr Cl, Wb\n");
3195
3196
3197         mct_ClrClToNB_D(pMCTstat, pDCTstat);
3198         mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat);
3199 }
3200
3201
3202 static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
3203 {
3204         print_t("\tmct_InitialMCT_D: Set Cl, Wb\n");
3205         mct_SetClToNB_D(pMCTstat, pDCTstat);
3206         mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat);
3207 }
3208
3209
3210 static u32 mct_NodePresent_D(void)
3211 {
3212         u32 val;
3213         val = 0x12001022;
3214         return val;
3215 }
3216
3217
3218 static void mct_init(struct MCTStatStruc *pMCTstat,
3219                         struct DCTStatStruc *pDCTstat)
3220 {
3221         u32 lo, hi;
3222         u32 addr;
3223
3224         pDCTstat->GangedMode = 0;
3225         pDCTstat->DRPresent = 1;
3226
3227         /* enable extend PCI configuration access */
3228         addr = 0xC001001F;
3229         _RDMSR(addr, &lo, &hi);
3230         if (hi & (1 << (46-32))) {
3231                 pDCTstat->Status |= 1 << SB_ExtConfig;
3232         } else {
3233                 hi |= 1 << (46-32);
3234                 _WRMSR(addr, lo, hi);
3235         }
3236 }
3237
3238
3239 static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat,
3240                                 struct DCTStatStruc *pDCTstat)
3241 {
3242         u32 reg;
3243         u32 val;
3244         u32 dev = pDCTstat->dev_dct;
3245
3246         /* Clear Legacy BIOS Mode bit */
3247         reg = 0x94;
3248         val = Get_NB32(dev, reg);
3249         val &= ~(1<<LegacyBiosMode);
3250         Set_NB32(dev, reg, val);
3251 }
3252
3253
3254 static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat,
3255                                 struct DCTStatStruc *pDCTstatA)
3256 {
3257         u8 Node;
3258         u32 Drambase, Dramlimit;
3259         u32 val;
3260         u32 reg;
3261         u32 dev;
3262         u32 devx;
3263         u32 dword;
3264         struct DCTStatStruc *pDCTstat;
3265
3266         pDCTstat = pDCTstatA + 0;
3267         dev = pDCTstat->dev_map;
3268
3269         /* Copy dram map from F1x40/44,F1x48/4c,
3270           to F1x120/124(Node0),F1x120/124(Node1),...*/
3271         for (Node=0; Node < MAX_NODES_SUPPORTED; Node++) {
3272                 pDCTstat = pDCTstatA + Node;
3273                 devx = pDCTstat->dev_map;
3274
3275                 /* get base/limit from Node0 */
3276                 reg = 0x40 + (Node << 3);               /* Node0/Dram Base 0 */
3277                 val = Get_NB32(dev, reg);
3278                 Drambase = val >> ( 16 + 3);
3279
3280                 reg = 0x44 + (Node << 3);               /* Node0/Dram Base 0 */
3281                 val = Get_NB32(dev, reg);
3282                 Dramlimit = val >> (16 + 3);
3283
3284                 /* set base/limit to F1x120/124 per Node */
3285                 if (pDCTstat->NodePresent) {
3286                         reg = 0x120;            /* F1x120,DramBase[47:27] */
3287                         val = Get_NB32(devx, reg);
3288                         val &= 0xFFE00000;
3289                         val |= Drambase;
3290                         Set_NB32(devx, reg, val);
3291
3292                         reg = 0x124;
3293                         val = Get_NB32(devx, reg);
3294                         val &= 0xFFE00000;
3295                         val |= Dramlimit;
3296                         Set_NB32(devx, reg, val);
3297
3298                         if ( pMCTstat->GStatus & ( 1 << GSB_HWHole)) {
3299                                 reg = 0xF0;
3300                                 val = Get_NB32(devx, reg);
3301                                 val |= (1 << DramMemHoistValid);
3302                                 val &= ~(0xFF << 24);
3303                                 dword = (pMCTstat->HoleBase >> (24 - 8)) & 0xFF;
3304                                 dword <<= 24;
3305                                 val |= dword;
3306                                 Set_NB32(devx, reg, val);
3307                         }
3308
3309                 }
3310         }
3311 }
3312
3313 static void SetCSTriState(struct MCTStatStruc *pMCTstat,
3314                                 struct DCTStatStruc *pDCTstat, u8 dct)
3315 {
3316         u32 val;
3317         u32 dev = pDCTstat->dev_dct;
3318         u32 index_reg = 0x98 + 0x100 * dct;
3319         u8 cs;
3320         u32 index;
3321         u16 word;
3322
3323         /* Tri-state unused chipselects when motherboard
3324            termination is available */
3325
3326         // FIXME: skip for Ax
3327
3328         word = pDCTstat->CSPresent;
3329         if (pDCTstat->Status & (1 << SB_Registered)) {
3330                 for (cs = 0; cs < 8; cs++) {
3331                         if (word & (1 << cs)) {
3332                                 if (!(cs & 1))
3333                                         word |= 1 << (cs + 1);
3334                         }
3335                 }
3336         }
3337         word = (~word) & 0xFF;
3338         index  = 0x0c;
3339         val = Get_NB32_index_wait(dev, index_reg, index);
3340         val |= word;
3341         Set_NB32_index_wait(dev, index_reg, index, val);
3342 }
3343
3344
3345
3346 static void SetCKETriState(struct MCTStatStruc *pMCTstat,
3347                                 struct DCTStatStruc *pDCTstat, u8 dct)
3348 {
3349         u32 val;
3350         u32 dev;
3351         u32 index_reg = 0x98 + 0x100 * dct;
3352         u8 cs;
3353         u32 index;
3354         u16 word;
3355
3356         /* Tri-state unused CKEs when motherboard termination is available */
3357
3358         // FIXME: skip for Ax
3359
3360         dev = pDCTstat->dev_dct;
3361         word = 0x101;
3362         for (cs = 0; cs < 8; cs++) {
3363                 if (pDCTstat->CSPresent & (1 << cs)) {
3364                         if (!(cs & 1))
3365                                 word &= 0xFF00;
3366                         else
3367                                 word &= 0x00FF;
3368                 }
3369         }
3370
3371         index  = 0x0c;
3372         val = Get_NB32_index_wait(dev, index_reg, index);
3373         if ((word & 0x00FF) == 1)
3374                 val |= 1 << 12;
3375         else
3376                 val &= ~(1 << 12);
3377
3378         if ((word >> 8) == 1)
3379                 val |= 1 << 13;
3380         else
3381                 val &= ~(1 << 13);
3382
3383         Set_NB32_index_wait(dev, index_reg, index, val);
3384 }
3385
3386
3387 static void SetODTTriState(struct MCTStatStruc *pMCTstat,
3388                                 struct DCTStatStruc *pDCTstat, u8 dct)
3389 {
3390         u32 val;
3391         u32 dev;
3392         u32 index_reg = 0x98 + 0x100 * dct;
3393         u8 cs;
3394         u32 index;
3395         u8 odt;
3396         u8 max_dimms;
3397
3398         // FIXME: skip for Ax
3399
3400         /* Tri-state unused ODTs when motherboard termination is available */
3401         max_dimms = (u8) mctGet_NVbits(NV_MAX_DIMMS);
3402         odt = 0x0F;     /* tristate all the pins then clear the used ones. */
3403
3404         for (cs = 0; cs < 8; cs += 2) {
3405                 if (pDCTstat->CSPresent & (1 << cs)) {
3406                         odt &= ~(1 << (cs / 2));
3407
3408                         /* if quad-rank capable platform clear adtitional pins */
3409                         if (max_dimms != MAX_CS_SUPPORTED) {
3410                                 if (pDCTstat->CSPresent & (1 << (cs + 1)))
3411                                         odt &= ~(4 << (cs / 2));
3412                         }
3413                 }
3414         }
3415
3416         index  = 0x0C;
3417         val = Get_NB32_index_wait(dev, index_reg, index);
3418         val |= (odt << 8);
3419         Set_NB32_index_wait(dev, index_reg, index, val);
3420
3421 }
3422
3423
3424 static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
3425                                         struct DCTStatStruc *pDCTstat, u8 dct)
3426 {
3427         u8 i;
3428         u32 index_reg = 0x98 + 0x100 * dct;
3429         u32 dev = pDCTstat->dev_dct;
3430         u32 val;
3431         u32 valx = 0;
3432         u32 dword;
3433         const u8 *p;
3434
3435         val = Get_NB32_index_wait(dev, index_reg, 0x00);
3436         dword = 0;
3437         for (i=0; i < 6; i++) {
3438                 switch (i) {
3439                         case 0:
3440                         case 4:
3441                                 p = Table_Comp_Rise_Slew_15x;
3442                                 valx = p[(val >> 16) & 3];
3443                                 break;
3444                         case 1:
3445                         case 5:
3446                                 p = Table_Comp_Fall_Slew_15x;
3447                                 valx = p[(val >> 16) & 3];
3448                                 break;
3449                         case 2:
3450                                 p = Table_Comp_Rise_Slew_20x;
3451                                 valx = p[(val >> 8) & 3];
3452                                 break;
3453                         case 3:
3454                                 p = Table_Comp_Fall_Slew_20x;
3455                                 valx = p[(val >> 8) & 3];
3456                                 break;
3457
3458                 }
3459                 dword |= valx << (5 * i);
3460         }
3461
3462         /* Override/Exception */
3463         if (!pDCTstat->GangedMode) {
3464                 i = 0; /* use i for the dct setting required */
3465                 if (pDCTstat->MAdimms[0] < 4)
3466                         i = 1;
3467                 if (((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) && (pDCTstat->MAdimms[i] == 4))
3468                         dword &= 0xF18FFF18;
3469                         index_reg = 0x98;       /* force dct = 0 */
3470         }
3471
3472         Set_NB32_index_wait(dev, index_reg, 0x0a, dword);
3473 }
3474
3475
3476 static void WaitRoutine_D(u32 time)
3477 {
3478         while(time) {
3479                 _EXECFENCE;
3480                 time--;
3481         }
3482 }
3483
3484
3485 static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
3486                                         struct DCTStatStruc *pDCTstat)
3487 {
3488         u32 reg;
3489         u32 val;
3490         u32 dev = pDCTstat->dev_dct;
3491
3492         /* GhEnhancement #18429 modified by askar: For low NB CLK :
3493          * Memclk ratio, the DCT may need to arbitrate early to avoid
3494          * unnecessary bubbles.
3495          * bit 19 of F2x[1,0]78 Dram  Control Register, set this bit only when
3496          * NB CLK : Memclk ratio is between 3:1 (inclusive) to 4:5 (inclusive)
3497          */
3498
3499         reg = 0x78;
3500         val = Get_NB32(dev, reg);
3501
3502         //FIXME: check for Cx
3503         if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat))
3504                 val |= (1 << EarlyArbEn);
3505
3506         Set_NB32(dev, reg, val);
3507
3508 }
3509
3510
3511 static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
3512                                         struct DCTStatStruc *pDCTstat)
3513 {
3514         u32 reg;
3515         u32 val;
3516         u32 tmp;
3517         u32 rem;
3518         u32 dev = pDCTstat->dev_dct;
3519         u32  hi, lo;
3520         u8 NbDid = 0;
3521
3522         /* Check if NB COF >= 4*Memclk, if it is not, return a fatal error
3523          */
3524
3525         /* 3*(Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */
3526         _RDMSR(0xC0010071, &lo, &hi);
3527         if (lo & (1 << 22))
3528                 NbDid |= 1;
3529
3530
3531         reg = 0x94;
3532         val = Get_NB32(dev, reg);
3533         if (!(val & (1 << MemClkFreqVal)))
3534                 val = Get_NB32(dev, reg * 0x100);       /* get the DCT1 value */
3535
3536         val &= 0x07;
3537         val += 3;
3538         if (NbDid)
3539                 val <<= 1;
3540         tmp = val;
3541
3542         dev = pDCTstat->dev_nbmisc;
3543         reg = 0xD4;
3544         val = Get_NB32(dev, reg);
3545         val &= 0x1F;
3546         val += 3;
3547         val *= 3;
3548         val = val / tmp;
3549         rem = val % tmp;
3550         tmp >>= 1;
3551
3552         // Yes this could be nicer but this was how the asm was....
3553         if (val < 3) {                          /* NClk:MemClk < 3:1 */
3554                 return 0;
3555         } else if (val > 4) {                   /* NClk:MemClk >= 5:1 */
3556                 return 0;
3557         } else if ((val == 4) && (rem > tmp)) { /* NClk:MemClk > 4.5:1 */
3558                 return 0;
3559         } else {
3560                 return 1;                       /* 3:1 <= NClk:MemClk <= 4.5:1*/
3561         }
3562 }
3563
3564
3565 static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat,
3566                                         struct DCTStatStruc *pDCTstatA)
3567 {
3568         u8 Node;
3569         u32 i;
3570         struct DCTStatStruc *pDCTstat;
3571         u16 start, stop;
3572         u8 *p;
3573         u16 host_serv1, host_serv2;
3574
3575         /* Initialize Data structures by clearing all entries to 0 */
3576         p = (u8 *) pMCTstat;
3577         for (i = 0; i < sizeof(struct MCTStatStruc); i++) {
3578                 p[i] = 0;
3579         }
3580
3581         for (Node = 0; Node < 8; Node++) {
3582                 pDCTstat = pDCTstatA + Node;
3583                 host_serv1 = pDCTstat->HostBiosSrvc1;
3584                 host_serv2 = pDCTstat->HostBiosSrvc2;
3585
3586                 p = (u8 *) pDCTstat;
3587                 start = 0;
3588                 stop = ((u16) &((struct DCTStatStruc *)0)->CH_MaxRdLat[2]);
3589                 for (i = start; i < stop ; i++) {
3590                         p[i] = 0;
3591                 }
3592
3593                 start = ((u16) &((struct DCTStatStruc *)0)->CH_D_BC_RCVRDLY[2][4]);
3594                 stop = sizeof(struct DCTStatStruc);
3595                 for (i = start; i < stop; i++) {
3596                         p[i] = 0;
3597                 }
3598                 pDCTstat->HostBiosSrvc1 = host_serv1;
3599                 pDCTstat->HostBiosSrvc2 = host_serv2;
3600         }
3601 }
3602
3603
3604 static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
3605                                         struct DCTStatStruc *pDCTstat)
3606 {
3607         u8 i;
3608         u32 reg_off;
3609         u32 dev = pDCTstat->dev_dct;
3610
3611         // FIXME: skip for Ax
3612         if ((pDCTstat->Speed == 3) || ( pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533Mhz
3613                 for (i=0; i < 2; i++) {
3614                         reg_off = 0x100 * i;
3615                         Set_NB32(dev,  0x98 + reg_off, 0x0D000030);
3616                         Set_NB32(dev,  0x9C + reg_off, 0x00000806);
3617                         Set_NB32(dev,  0x98 + reg_off, 0x4D040F30);
3618                 }
3619         }
3620 }
3621
3622
3623 void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat,
3624                         struct DCTStatStruc *pDCTstat, u8 *dqs_pos)
3625 {
3626         // FIXME: Skip for Ax
3627         if ((pDCTstat->Speed == 3) || ( pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533Mhz
3628                 *dqs_pos = 32;
3629         }
3630 }
3631
3632
3633 void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat,
3634                         struct DCTStatStruc *pDCTstat)
3635 {
3636         u32 lo, hi;
3637         u32 msr;
3638
3639         // FIXME: Maybe check the CPUID? - not for now.
3640         // pDCTstat->LogicalCPUID;
3641
3642         msr = BU_CFG2;
3643         _RDMSR(msr, &lo, &hi);
3644         lo |= 1 << ClLinesToNbDis;
3645         _WRMSR(msr, lo, hi);
3646 }
3647
3648
3649 void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat,
3650                         struct DCTStatStruc *pDCTstat)
3651 {
3652
3653         u32 lo, hi;
3654         u32 msr;
3655
3656         // FIXME: Maybe check the CPUID? - not for now.
3657         // pDCTstat->LogicalCPUID;
3658
3659         msr = BU_CFG2;
3660         _RDMSR(msr, &lo, &hi);
3661         if (!pDCTstat->ClToNB_flag)
3662                 lo &= ~(1<<ClLinesToNbDis);
3663         _WRMSR(msr, lo, hi);
3664
3665 }
3666
3667
3668 void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat,
3669                                 struct DCTStatStruc *pDCTstat)
3670 {
3671         u32 lo, hi;
3672         u32 msr;
3673
3674         // FIXME: Maybe check the CPUID? - not for now.
3675         // pDCTstat->LogicalCPUID;
3676
3677         msr = BU_CFG;
3678         _RDMSR(msr, &lo, &hi);
3679         hi |= (1 << WbEnhWsbDis_D);
3680         _WRMSR(msr, lo, hi);
3681 }
3682
3683
3684 void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat,
3685                                 struct DCTStatStruc *pDCTstat)
3686 {
3687         u32 lo, hi;
3688         u32 msr;
3689
3690         // FIXME: Maybe check the CPUID? - not for now.
3691         // pDCTstat->LogicalCPUID;
3692
3693         msr = BU_CFG;
3694         _RDMSR(msr, &lo, &hi);
3695         hi &= ~(1 << WbEnhWsbDis_D);
3696         _WRMSR(msr, lo, hi);
3697 }
3698
3699
3700 void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct,
3701                                 u32 DramConfigHi)
3702 {
3703         /* Bug#15114: Comp. update interrupted by Freq. change can cause
3704          * subsequent update to be invalid during any MemClk frequency change:
3705          * Solution: From the bug report:
3706          *  1. A software-initiated frequency change should be wrapped into the
3707          *     following sequence :
3708          *      - a) Disable Compensation (F2[1, 0]9C_x08[30] )
3709          *      b) Reset the Begin Compensation bit (D3CMP->COMP_CONFIG[0]) in all the compensation engines
3710          *      c) Do frequency change
3711          *      d) Enable Compensation (F2[1, 0]9C_x08[30] )
3712          *  2. A software-initiated Disable Compensation should always be
3713          *     followed by step b) of the above steps.
3714          * Silicon Status: Fixed In Rev B0
3715          *
3716          * Errata#177: DRAM Phy Automatic Compensation Updates May Be Invalid
3717          * Solution: BIOS should disable the phy automatic compensation prior
3718          * to initiating a memory clock frequency change as follows:
3719          *  1. Disable PhyAutoComp by writing 1'b1 to F2x[1, 0]9C_x08[30]
3720          *  2. Reset the Begin Compensation bits by writing 32'h0 to
3721          *     F2x[1, 0]9C_x4D004F00
3722          *  3. Perform frequency change
3723          *  4. Enable PhyAutoComp by writing 1'b0 to F2x[1, 0]9C_08[30]
3724          *  In addition, any time software disables the automatic phy
3725          *   compensation it should reset the begin compensation bit per step 2.
3726          *   Silicon Status: Fixed in DR-B0
3727          */
3728
3729         u32 dev = pDCTstat->dev_dct;
3730         u32 index_reg = 0x98 + 0x100 * dct;
3731         u32 index;
3732
3733         u32 val;
3734
3735         index = 0x08;
3736         val = Get_NB32_index_wait(dev, index_reg, index);
3737         Set_NB32_index_wait(dev, index_reg, index, val | (1 << DisAutoComp));
3738
3739         //FIXME: check for Bx Cx CPU
3740           // if Ax mct_SetDramConfigHi_Samp_D
3741
3742         /* errata#177 */
3743         index = 0x4D014F00;     /* F2x[1, 0]9C_x[D0FFFFF:D000000] DRAM Phy Debug Registers */
3744         index |= 1 << DctAccessWrite;
3745         val = 0;
3746         Set_NB32_index_wait(dev, index_reg, index, val);
3747
3748         Set_NB32(dev, 0x94 + 0x100 * dct, DramConfigHi);
3749
3750         index = 0x08;
3751         val = Get_NB32_index_wait(dev, index_reg, index);
3752         Set_NB32_index_wait(dev, index_reg, index, val & (~(1 << DisAutoComp)));
3753 }
3754
3755 static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat,
3756                                         struct DCTStatStruc *pDCTstatA)
3757 {
3758         u8 Node;
3759         struct DCTStatStruc *pDCTstat;
3760
3761         /* Errata 178
3762          *
3763          * Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
3764          *            In TX FIFO
3765          * Solution: BIOS should program DRAM Control Register[RdPtrInit] =
3766          *            5h, (F2x[1, 0]78[3:0] = 5h).
3767          * Silicon Status: Fixed In Rev B0
3768          *
3769          * Bug#15880: Determine validity of reset settings for DDR PHY timing.
3770          * Solutiuon: At least, set WrDqs fine delay to be 0 for DDR2 training.
3771          */
3772
3773         for (Node = 0; Node < 8; Node++) {
3774                 pDCTstat = pDCTstatA + Node;
3775
3776                 if (pDCTstat->NodePresent)
3777                         mct_BeforeDQSTrain_Samp_D(pMCTstat, pDCTstat);
3778                         mct_ResetDLL_D(pMCTstat, pDCTstat, 0);
3779                         mct_ResetDLL_D(pMCTstat, pDCTstat, 1);
3780
3781         }
3782 }
3783
3784 static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
3785                                         struct DCTStatStruc *pDCTstat, u8 dct)
3786 {
3787         u8 Receiver;
3788         u32 dev = pDCTstat->dev_dct;
3789         u32 reg_off = 0x100 * dct;
3790         u32 addr;
3791         u32 lo, hi;
3792         u8 wrap32dis = 0;
3793         u8 valid = 0;
3794
3795         /* FIXME: Skip reset DLL for B3 */
3796
3797         addr = HWCR;
3798         _RDMSR(addr, &lo, &hi);
3799         if(lo & (1<<17)) {              /* save the old value */
3800                 wrap32dis = 1;
3801         }
3802         lo |= (1<<17);                  /* HWCR.wrap32dis */
3803         lo &= ~(1<<15);                 /* SSEDIS */
3804         /* Setting wrap32dis allows 64-bit memory references in 32bit mode */
3805         _WRMSR(addr, lo, hi);
3806
3807
3808         pDCTstat->Channel = dct;
3809         Receiver = mct_InitReceiver_D(pDCTstat, dct);
3810         /* there are four receiver pairs, loosely associated with chipselects.*/
3811         for (; Receiver < 8; Receiver += 2) {
3812                 if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) {
3813                         addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, dct, Receiver, &valid);
3814                         if (valid) {
3815                                 mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr);      /* cache fills */
3816
3817                                 /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */
3818                                 Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00008000);
3819                                 mct_Wait(80); /* wait >= 300ns */
3820
3821                                 /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */
3822                                 Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00000000);
3823                                 mct_Wait(800); /* wait >= 2us */
3824                                 break;
3825                         }
3826                 }
3827         }
3828         if(!wrap32dis) {
3829                 addr = HWCR;
3830                 _RDMSR(addr, &lo, &hi);
3831                 lo &= ~(1<<17);         /* restore HWCR.wrap32dis */
3832                 _WRMSR(addr, lo, hi);
3833         }
3834 }
3835
3836
3837 static void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat,
3838                                         struct DCTStatStruc *pDCTstat)
3839 {
3840         u32 dev = pDCTstat->dev_dct;
3841         u32 val;
3842
3843         /*  Enable F2x110[DctDatIntlv] */
3844         // Call back not required mctHookBeforeDatIntlv_D()
3845         // FIXME Skip for Ax
3846         if (!pDCTstat->GangedMode) {
3847                 val = Get_NB32(dev, 0x110);
3848                 val |= 1 << 5;                  // DctDatIntlv
3849                 Set_NB32(dev, 0x110, val);
3850
3851                 // FIXME Skip for Cx
3852                 dev = pDCTstat->dev_nbmisc;
3853                 val = Get_NB32(dev, 0x8C);      // NB Configuration Hi
3854                 val |= 1 << (36-32);            // DisDatMask
3855                 Set_NB32(dev, 0x8C, val);
3856         }
3857 }
3858
3859
3860 static void mct_SetupSync_D(struct MCTStatStruc *pMCTstat,
3861                                         struct DCTStatStruc *pDCTstat)
3862 {
3863         /* set F2x78[ChSetupSync] when F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup,
3864          * CkeSetup] setups for one DCT are all 0s and at least one of the setups,
3865          * F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, CkeSetup], of the other
3866          * controller is 1
3867          */
3868         u32 cha, chb;
3869         u32 dev = pDCTstat->dev_dct;
3870         u32 val;
3871
3872         cha = pDCTstat->CH_ADDR_TMG[0] & 0x0202020;
3873         chb = pDCTstat->CH_ADDR_TMG[1] & 0x0202020;
3874
3875         if ((cha != chb) && ((cha == 0) || (chb == 0))) {
3876                 val = Get_NB32(dev, 0x78);
3877                 val |= ChSetupSync;
3878                 Set_NB32(dev, 0x78, val);
3879         }
3880 }
3881
3882 static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) {
3883
3884         u32 val;
3885         u32 reg_off = 0x100 * dct;
3886         u32 dev = pDCTstat->dev_dct;
3887
3888         /* FIXME: Add B3 */
3889         if (pDCTstat->LogicalCPUID & AMD_DR_B2) {
3890                 mct_Wait(10000);        /* Wait 50 us*/
3891                 val = Get_NB32(dev, 0x110);
3892                 if ( val & (1 << DramEnabled)) {
3893                         /* If 50 us expires while DramEnable =0 then do the following */
3894                         val = Get_NB32(dev, 0x90 + reg_off);
3895                         val &= ~(1 << Width128);                /* Program Width128 = 0 */
3896                         Set_NB32(dev, 0x90 + reg_off, val);
3897
3898                         val = Get_NB32_index_wait(dev, 0x98 + reg_off, 0x05);   /* Perform dummy CSR read to F2x09C_x05 */
3899
3900                         if (pDCTstat->GangedMode) {
3901                                 val = Get_NB32(dev, 0x90 + reg_off);
3902                                 val |= 1 << Width128;           /* Program Width128 = 0 */
3903                                 Set_NB32(dev, 0x90 + reg_off, val);
3904                         }
3905                 }
3906         }
3907 }
3908
3909
3910 /* ==========================================================
3911  *  6-bit Bank Addressing Table
3912  *  RR=rows-13 binary
3913  *  B=Banks-2 binary
3914  *  CCC=Columns-9 binary
3915  * ==========================================================
3916  *  DCT CCCBRR  Rows    Banks   Columns 64-bit CS Size
3917  *  Encoding
3918  *  0000        000000  13      2       9       128MB
3919  *  0001        001000  13      2       10      256MB
3920  *  0010        001001  14      2       10      512MB
3921  *  0011        010000  13      2       11      512MB
3922  *  0100        001100  13      3       10      512MB
3923  *  0101        001101  14      3       10      1GB
3924  *  0110        010001  14      2       11      1GB
3925  *  0111        001110  15      3       10      2GB
3926  *  1000        010101  14      3       11      2GB
3927  *  1001        010110  15      3       11      4GB
3928  *  1010        001111  16      3       10      4GB
3929  *  1011        010111  16      3       11      8GB
3930  */