Complete the code which was missing.
[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 HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
46                                 struct DCTStatStruc *pDCTstatA);
47 static void MCTMemClr_D(struct MCTStatStruc *pMCTstat,
48                                 struct DCTStatStruc *pDCTstatA);
49 static void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
50                                 struct DCTStatStruc *pDCTstat);
51 static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
52                                 struct DCTStatStruc *pDCTstat);
53 static void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
54                                 struct DCTStatStruc *pDCTstatA);
55 static u8 NodePresent_D(u8 Node);
56 static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
57                                 struct DCTStatStruc *pDCTstatA);
58 static void StartupDCT_D(struct MCTStatStruc *pMCTstat,
59                                 struct DCTStatStruc *pDCTstat, u8 dct);
60 static void ClearDCT_D(struct MCTStatStruc *pMCTstat,
61                         struct DCTStatStruc *pDCTstat, u8 dct);
62 static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
63                                 struct DCTStatStruc *pDCTstat, u8 dct);
64 static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
65                                 struct DCTStatStruc *pDCTstat);
66 static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
67                         struct DCTStatStruc *pDCTstat, u8 dct);
68 static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
69                                 struct DCTStatStruc *pDCTstat, u8 dct);
70 static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat,
71                                 struct DCTStatStruc *pDCTstat, u8 dct);
72 static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat,
73                                 struct DCTStatStruc *pDCTstat, u8 dct);
74 static void StitchMemory_D(struct MCTStatStruc *pMCTstat,
75                                 struct DCTStatStruc *pDCTstat, u8 dct);
76 static u8 Get_DefTrc_k_D(u8 k);
77 static u16 Get_40Tk_D(u8 k);
78 static u16 Get_Fk_D(u8 k);
79 static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat, u8 i, u8 j, u8 k);
80 static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat,
81                                 struct DCTStatStruc *pDCTstat, int j, int k);
82 static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i);
83 static void mct_initDCT(struct MCTStatStruc *pMCTstat,
84                                 struct DCTStatStruc *pDCTstat);
85 static void mct_DramInit(struct MCTStatStruc *pMCTstat,
86                                 struct DCTStatStruc *pDCTstat, u8 dct);
87 static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
88                                         struct DCTStatStruc *pDCTstat, u8 dct);
89 static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat);
90 static void Get_Trdrd(struct MCTStatStruc *pMCTstat,
91                         struct DCTStatStruc *pDCTstat, u8 dct);
92 static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat,
93                                 struct DCTStatStruc *pDCTstat, u8 dct);
94 static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,\
95                                         struct DCTStatStruc *pDCTstat, u8 dct);
96 static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat,
97                                         struct DCTStatStruc *pDCTstat, u8 dct);
98 static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat,
99                                         struct DCTStatStruc *pDCTstat, u8 dct);
100 static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
101                                 struct DCTStatStruc *pDCTstat, u8 dct);
102 static void Get_Twrwr(struct MCTStatStruc *pMCTstat,
103                         struct DCTStatStruc *pDCTstat, u8 dct);
104 static void Get_Twrrd(struct MCTStatStruc *pMCTstat,
105                         struct DCTStatStruc *pDCTstat, u8 dct);
106 static void Get_TrwtTO(struct MCTStatStruc *pMCTstat,
107                         struct DCTStatStruc *pDCTstat, u8 dct);
108 static void Get_TrwtWB(struct MCTStatStruc *pMCTstat,
109                         struct DCTStatStruc *pDCTstat);
110 static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat, u8 dct,
111                                 u32 dev, u32 index_reg, u32 index);
112 static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
113                                         u32 dev, u32 index_reg);
114 static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, u8 dct,
115                                         u32 dev, u32 index_reg);
116 static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
117                                 u32 dev, u32 index_reg, u32 index);
118 static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
119                                 struct DCTStatStruc *pDCTstat);
120 static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, u8 dct,
121                                 u32 dev, u32 index_reg, u32 index);
122 static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat,
123                                 struct DCTStatStruc *pDCTstat);
124 static void mct_init(struct MCTStatStruc *pMCTstat,
125                         struct DCTStatStruc *pDCTstat);
126 static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat,
127                                 struct DCTStatStruc *pDCTstat);
128 static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat,
129                                 struct DCTStatStruc *pDCTstatA);
130 static void SetCSTriState(struct MCTStatStruc *pMCTstat,
131                                 struct DCTStatStruc *pDCTstat, u8 dct);
132 static void SetODTTriState(struct MCTStatStruc *pMCTstat,
133                                 struct DCTStatStruc *pDCTstat, u8 dct);
134 static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
135                                         struct DCTStatStruc *pDCTstat, u8 dct);
136 static u32 mct_NodePresent_D(void);
137 static void WaitRoutine_D(u32 time);
138 static void mct_OtherTiming(struct MCTStatStruc *pMCTstat,
139                                 struct DCTStatStruc *pDCTstatA);
140 static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat,
141                                         struct DCTStatStruc *pDCTstatA);
142 static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
143                                         struct DCTStatStruc *pDCTstat);
144 static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
145                                         struct DCTStatStruc *pDCTstat);
146 void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat,
147                         struct DCTStatStruc *pDCTstat);
148 static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
149                                         struct DCTStatStruc *pDCTstat);
150 void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat,
151                                         struct DCTStatStruc *pDCTstat);
152 static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat,
153                                         struct DCTStatStruc *pDCTstatA);
154 static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct);
155 static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
156                                         struct DCTStatStruc *pDCTstat, u8 dct);
157
158
159 /*See mctAutoInitMCT header for index relationships to CL and T*/
160 static const u16 Table_F_k[]    = {00,200,266,333,400,533 };
161 static const u8 Table_T_k[]     = {0x00,0x50,0x3D,0x30,0x25, 0x18 };
162 static const u8 Table_CL2_j[]   = {0x04,0x08,0x10,0x20,0x40, 0x80 };
163 static const u8 Tab_defTrc_k[]  = {0x0,0x41,0x3C,0x3C,0x3A, 0x3A };
164 static const u16 Tab_40T_k[]    = {00,200,150,120,100,75 };
165 static const u8 Tab_TrefT_k[]   = {00,0,1,1,2,2,3,4,5,6,0,0};
166 static const u8 Tab_BankAddr[]  = {0x0,0x08,0x09,0x10,0x0C,0x0D,0x11,0x0E,0x15,0x16,0x0F,0x17};
167 static const u8 Tab_tCL_j[]     = {0,2,3,4,5};
168 static const u8 Tab_1KTfawT_k[] = {00,8,10,13,14,20};
169 static const u8 Tab_2KTfawT_k[] = {00,10,14,17,18,24};
170 static const u8 Tab_L1CLKDis[]  = {8,8,6,4,2,0,8,8};
171 static const u8 Tab_M2CLKDis[]  = {2,0,8,8,2,0,2,0};
172 static const u8 Tab_S1CLKDis[]  = {8,0,8,8,8,0,8,0};
173 static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF};
174 static const u8 Table_Comp_Rise_Slew_15x[] = {7, 7, 3, 2, 0xFF};
175 static const u8 Table_Comp_Fall_Slew_20x[] = {7, 5, 3, 2, 0xFF};
176 static const u8 Table_Comp_Fall_Slew_15x[] = {7, 7, 5, 3, 0xFF};
177
178 static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
179                         struct DCTStatStruc *pDCTstatA)
180 {
181         /*
182          * Memory may be mapped contiguously all the way up to 4GB (depending
183          * on setup options). It is the responsibility of PCI subsystem to
184          * create an uncacheable IO region below 4GB and to adjust TOP_MEM
185          * downward prior to any IO mapping or accesses. It is the same
186          * responsibility of the CPU sub-system prior toaccessing LAPIC.
187          *
188          * Slot Number is an external convention, and is determined by OEM with
189          * accompanying silk screening.  OEM may choose to use Slot number
190          * convention which is consistent with DIMM number conventions.
191          * All AMD engineering
192          * platforms do.
193          *
194          * Run-Time Requirements:
195          * 1. Complete Hypertransport Bus Configuration
196          * 2. SMBus Controller Initialized
197          * 3. Checksummed or Valid NVRAM bits
198          * 4. MCG_CTL=-1, MC4_CTL_EN=0 for all CPUs
199          * 5. MCi_STS from shutdown/warm reset recorded (if desired) prior to
200          *     entry
201          * 6. All var MTRRs reset to zero
202          * 7. State of NB_CFG.DisDatMsk set properly on all CPUs
203          * 8. All CPUs at 2Ghz Speed (unless DQS training is not installed).
204          * 9. All cHT links at max Speed/Width (unless DQS training is not
205          *     installed).
206          *
207          *
208          * Global relationship between index values and item values:
209          * j CL(j)       k   F(k)
210          * --------------------------
211          * 0 2.0         -   -
212          * 1 3.0         1   200 Mhz
213          * 2 4.0         2   266 Mhz
214          * 3 5.0         3   333 Mhz
215          * 4 6.0         4   400 Mhz
216          * 5 7.0         5   533 Mhz
217          */
218         u8 Node, NodesWmem;
219         u32 node_sys_base;
220
221 restartinit:
222         mctInitMemGPIOs_A_D();          /* Set any required GPIOs*/
223         NodesWmem = 0;
224         node_sys_base = 0;
225         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
226                 struct DCTStatStruc *pDCTstat;
227                 pDCTstat = pDCTstatA + Node;
228                 pDCTstat->Node_ID = Node;
229                 pDCTstat->dev_host = PA_HOST(Node);
230                 pDCTstat->dev_map = PA_MAP(Node);
231                 pDCTstat->dev_dct = PA_DCT(Node);
232                 pDCTstat->dev_nbmisc = PA_NBMISC(Node);
233                 pDCTstat->NodeSysBase = node_sys_base;
234
235                 print_tx("mctAutoInitMCT_D: mct_init Node ", Node);
236                 mct_init(pMCTstat, pDCTstat);
237                 mctNodeIDDebugPort_D();
238                 pDCTstat->NodePresent = NodePresent_D(Node);
239                 if (pDCTstat->NodePresent) {            /* See if Node is there*/
240                         print_t("mctAutoInitMCT_D: clear_legacy_Mode\n");
241                         clear_legacy_Mode(pMCTstat, pDCTstat);
242                         pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);
243
244                         print_t("mctAutoInitMCT_D: mct_InitialMCT_D\n");
245                         mct_InitialMCT_D(pMCTstat, pDCTstat);
246
247                         print_t("mctAutoInitMCT_D: mctSMBhub_Init\n");
248                         mctSMBhub_Init(Node);           /* Switch SMBUS crossbar to proper node*/
249
250                         print_t("mctAutoInitMCT_D: mct_initDCT\n");
251                         mct_initDCT(pMCTstat, pDCTstat);
252                         if (pDCTstat->ErrCode == SC_FatalErr) {
253                                 goto fatalexit;         /* any fatal errors?*/
254                         } else if (pDCTstat->ErrCode < SC_StopError) {
255                                 NodesWmem++;
256                         }
257                 }       /* if Node present */
258                 node_sys_base = pDCTstat->NodeSysBase;
259                 node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
260         }
261         if (NodesWmem == 0) {
262                 print_debug("No Nodes?!\n");
263                 goto fatalexit;
264         }
265
266         print_t("mctAutoInitMCT_D: SyncDCTsReady_D\n");
267         SyncDCTsReady_D(pMCTstat, pDCTstatA);   /* Make sure DCTs are ready for accesses.*/
268
269         print_t("mctAutoInitMCT_D: HTMemMapInit_D\n");
270         HTMemMapInit_D(pMCTstat, pDCTstatA);    /* Map local memory into system address space.*/
271         mctHookAfterHTMap();
272
273         print_t("mctAutoInitMCT_D: CPUMemTyping_D\n");
274         CPUMemTyping_D(pMCTstat, pDCTstatA);    /* Map dram into WB/UC CPU cacheability */
275         mctHookAfterCPU();                      /* Setup external northbridge(s) */
276
277         print_t("mctAutoInitMCT_D: DQSTiming_D\n");
278         DQSTiming_D(pMCTstat, pDCTstatA);       /* Get Receiver Enable and DQS signal timing*/
279
280         print_t("mctAutoInitMCT_D: UMAMemTyping_D\n");
281         UMAMemTyping_D(pMCTstat, pDCTstatA);    /* Fix up for UMA sizing */
282
283         print_t("mctAutoInitMCT_D: :OtherTiming\n");
284         mct_OtherTiming(pMCTstat, pDCTstatA);
285
286         if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/
287                 goto restartinit;
288         }
289
290         InterleaveNodes_D(pMCTstat, pDCTstatA);
291         InterleaveChannels_D(pMCTstat, pDCTstatA);
292
293         print_t("mctAutoInitMCT_D: ECCInit_D\n");
294         if (ECCInit_D(pMCTstat, pDCTstatA)) {           /* Setup ECC control and ECC check-bits*/
295                 print_t("mctAutoInitMCT_D: MCTMemClr_D\n");
296                 MCTMemClr_D(pMCTstat,pDCTstatA);
297         }
298
299         mct_FinalMCT_D(pMCTstat, (pDCTstatA + 0) );     // Node 0
300         print_t("All Done\n");
301         return;
302
303 fatalexit:
304         die("mct_d: fatalexit");
305 }
306
307
308 static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat,
309                                         struct DCTStatStruc *pDCTstatA)
310 {
311         u8 ret;
312
313         if (mctGet_NVbits(NV_CS_SpareCTL)) {
314                 if (MCT_DIMM_SPARE_NO_WARM) {
315                         /* Do no warm-reset DIMM spare */
316                         if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
317                                 LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA);
318                                 ret = 0;
319                         } else {
320                                 mct_ResetDataStruct_D(pMCTstat, pDCTstatA);
321                                 pMCTstat->GStatus |= 1 << GSB_EnDIMMSpareNW;
322                                 ret = 1;
323                         }
324                 } else {
325                         /* Do warm-reset DIMM spare */
326                         if (mctGet_NVbits(NV_DQSTrainCTL))
327                                 mctWarmReset_D();
328                         ret = 0;
329                 }
330
331
332         } else {
333                 ret = 0;
334         }
335
336         return ret;
337 }
338
339
340 static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
341                                 struct DCTStatStruc *pDCTstatA)
342 {
343         u8 nv_DQSTrainCTL;
344
345         if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) {
346                 return;
347         }
348         nv_DQSTrainCTL = mctGet_NVbits(NV_DQSTrainCTL);
349         /* FIXME: BOZO- DQS training every time*/
350         nv_DQSTrainCTL = 1;
351
352         print_t("DQSTiming_D: mct_BeforeDQSTrain_D:\n");
353         mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);
354         phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
355
356         if (nv_DQSTrainCTL) {
357                 mctHookBeforeAnyTraining(pMCTstat, pDCTstatA);
358
359                 print_t("DQSTiming_D: TrainReceiverEn_D FirstPass:\n");
360                 TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
361
362                 print_t("DQSTiming_D: mct_TrainDQSPos_D\n");
363                 mct_TrainDQSPos_D(pMCTstat, pDCTstatA);
364
365                 // Second Pass never used for Barcelona!
366                 //print_t("DQSTiming_D: TrainReceiverEn_D SecondPass:\n");
367                 //TrainReceiverEn_D(pMCTstat, pDCTstatA, SecondPass);
368
369                 print_t("DQSTiming_D: mctSetEccDQSRcvrEn_D\n");
370                 mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA);
371
372                 print_t("DQSTiming_D: TrainMaxReadLatency_D\n");
373 //FIXME - currently uses calculated value               TrainMaxReadLatency_D(pMCTstat, pDCTstatA);
374                 mctHookAfterAnyTraining();
375                 mctSaveDQSSigTmg_D();
376
377                 print_t("DQSTiming_D: mct_EndDQSTraining_D\n");
378                 mct_EndDQSTraining_D(pMCTstat, pDCTstatA);
379
380                 print_t("DQSTiming_D: MCTMemClr_D\n");
381                 MCTMemClr_D(pMCTstat, pDCTstatA);
382         } else {
383                 mctGetDQSSigTmg_D();    /* get values into data structure */
384                 LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA);       /* load values into registers.*/
385                 //mctDoWarmResetMemClr_D();
386                 MCTMemClr_D(pMCTstat, pDCTstatA);
387         }
388 }
389
390
391 static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
392                                         struct DCTStatStruc *pDCTstatA)
393 {
394         u8 Node, Receiver, Channel, Dir, DIMM;
395         u32 dev;
396         u32 index_reg;
397         u32 reg;
398         u32 index;
399         u32 val;
400
401
402         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
403                 struct DCTStatStruc *pDCTstat;
404                 pDCTstat = pDCTstatA + Node;
405
406                 if (pDCTstat->DCTSysLimit) {
407                         dev = pDCTstat->dev_dct;
408                         for (Channel = 0;Channel < 2; Channel++) {
409                                 /* there are four receiver pairs,
410                                    loosely associated with chipselects.*/
411                                 index_reg = 0x98 + Channel * 0x100;
412                                 for (Receiver = 0; Receiver < 8; Receiver += 2) {
413                                         /* Set Receiver Enable Values */
414                                         mct_SetRcvrEnDly_D(pDCTstat,
415                                                 0, /* RcvrEnDly */
416                                                 1, /* FinalValue, From stack */
417                                                 Channel,
418                                                 Receiver,
419                                                 dev, index_reg,
420                                                 (Receiver >> 1) * 3 + 0x10, /* Addl_Index */
421                                                 2); /* Pass Second Pass ? */
422
423                                 }
424                         }
425                         for (Channel = 0; Channel<2; Channel++) {
426                                 SetEccDQSRcvrEn_D(pDCTstat, Channel);
427                         }
428
429                         for (Channel = 0; Channel < 2; Channel++) {
430                                 u8 *p;
431                                 index_reg = 0x98 + Channel * 0x100;
432
433                                 /* NOTE:
434                                  * when 400, 533, 667, it will support dimm0/1/2/3,
435                                  * and set conf for dimm0, hw will copy to dimm1/2/3
436                                  * set for dimm1, hw will copy to dimm3
437                                  * Rev A/B only support DIMM0/1 when 800Mhz and above
438                                  *   + 0x100 to next dimm
439                                  * Rev C support DIMM0/1/2/3 when 800Mhz and above
440                                  *   + 0x100 to next dimm
441                                 */
442                                 for (DIMM = 0; DIMM < 2; DIMM++) {
443                                         if (DIMM==0) {
444                                                 index = 0;      /* CHA Write Data Timing Low */
445                                         } else {
446                                                 if (pDCTstat->Speed >= 4) {
447                                                         index = 0x100 * DIMM;
448                                                 } else {
449                                                         break;
450                                                 }
451                                         }
452                                         for (Dir=0;Dir<2;Dir++) {//RD/WR
453                                                 p = pDCTstat->CH_D_DIR_B_DQS[Channel][DIMM][Dir];
454                                                 val = stream_to_int(p); /* CHA Read Data Timing High */
455                                                 Set_NB32_index_wait(dev, index_reg, index+1, val);
456                                                 val = stream_to_int(p+4); /* CHA Write Data Timing High */
457                                                 Set_NB32_index_wait(dev, index_reg, index+2, val);
458                                                 val = *(p+8); /* CHA Write ECC Timing */
459                                                 Set_NB32_index_wait(dev, index_reg, index+3, val);
460                                                 index += 4;
461                                         }
462                                 }
463                         }
464
465                         for (Channel = 0; Channel<2; Channel++) {
466                                 reg = 0x78 + Channel * 0x100;
467                                 val = Get_NB32(dev, reg);
468                                 val &= ~(0x3ff<<22);
469                                 val |= ((u32) pDCTstat->CH_MaxRdLat[Channel] << 22);
470                                 val &= ~(1<<DqsRcvEnTrain);
471                                 Set_NB32(dev, reg, val);        /* program MaxRdLatency to correspond with current delay*/
472                         }
473                 }
474         }
475 }
476
477 #ifdef UNUSED_CODE
478 static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat,
479                                 struct DCTStatStruc *pDCTstatA);
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 #endif
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(BIOS_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(BIOS_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         }
986         mct_AfterGetCLT(pMCTstat, pDCTstat, dct);
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, dct + 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) & 0xc) + 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 (Erratum 278) */
2405         if (pDCTstat->LogicalCPUID & AMD_DR_LT_B2) {
2406                 if (pDCTstat->GangedMode) {
2407                         val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
2408                         val |= 1 << DisAutoRefresh;
2409                         Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
2410                 }
2411         }
2412
2413         mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct);
2414
2415         /* Re-enable auto refresh after Dram init when in ganged mode
2416          * to ensure both DCTs are in sync (Erratum 278)
2417          */
2418
2419         if (pDCTstat->LogicalCPUID & AMD_DR_LT_B2) {
2420                 if (pDCTstat->GangedMode) {
2421                         do {
2422                                 val = Get_NB32(pDCTstat->dev_dct, 0x90 + (0x100 * dct));
2423                         } while (!(val & (1 << InitDram)));
2424
2425                         WaitRoutine_D(50);
2426
2427                         val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
2428                         val &= ~(1 << DisAutoRefresh);
2429                         Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
2430                         val |= 1 << DisAutoRefresh;
2431                         Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
2432                         val &= ~(1 << DisAutoRefresh);
2433                         Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
2434                 }
2435         }
2436 }
2437
2438
2439 static u8 mct_setMode(struct MCTStatStruc *pMCTstat,
2440                                 struct DCTStatStruc *pDCTstat)
2441 {
2442         u8 byte;
2443         u8 bytex;
2444         u32 val;
2445         u32 reg;
2446
2447         byte = bytex = pDCTstat->DIMMValid;
2448         bytex &= 0x55;          /* CHA DIMM pop */
2449         pDCTstat->DIMMValidDCT[0] = bytex;
2450
2451         byte &= 0xAA;           /* CHB DIMM popa */
2452         byte >>= 1;
2453         pDCTstat->DIMMValidDCT[1] = byte;
2454
2455         if (byte != bytex) {
2456                 pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO);
2457         } else {
2458         if ( mctGet_NVbits(NV_Unganged) )
2459                 pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO);
2460
2461                 if (!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) {
2462                         pDCTstat->GangedMode = 1;
2463                         /* valid 128-bit mode population. */
2464                         pDCTstat->Status |= 1 << SB_128bitmode;
2465                         reg = 0x110;
2466                         val = Get_NB32(pDCTstat->dev_dct, reg);
2467                         val |= 1 << DctGangEn;
2468                         Set_NB32(pDCTstat->dev_dct, reg, val);
2469                         print_tx("setMode: DRAM Controller Select Low Register = ", val);
2470                 }
2471         }
2472         return pDCTstat->ErrCode;
2473 }
2474
2475
2476 u32 Get_NB32(u32 dev, u32 reg)
2477 {
2478         return pci_read_config32(dev, reg);
2479 }
2480
2481
2482 void Set_NB32(u32 dev, u32 reg, u32 val)
2483 {
2484         pci_write_config32(dev, reg, val);
2485 }
2486
2487
2488 u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index)
2489 {
2490         u32 dword;
2491
2492         Set_NB32(dev, index_reg, index);
2493         dword = Get_NB32(dev, index_reg+0x4);
2494
2495         return dword;
2496 }
2497
2498 void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data)
2499 {
2500         Set_NB32(dev, index_reg, index);
2501         Set_NB32(dev, index_reg + 0x4, data);
2502 }
2503
2504
2505 u32 Get_NB32_index_wait(u32 dev, u32 index_reg, u32 index)
2506 {
2507
2508         u32 dword;
2509
2510
2511         index &= ~(1 << DctAccessWrite);
2512         Set_NB32(dev, index_reg, index);
2513         do {
2514                 dword = Get_NB32(dev, index_reg);
2515         } while (!(dword & (1 << DctAccessDone)));
2516         dword = Get_NB32(dev, index_reg + 0x4);
2517
2518         return dword;
2519 }
2520
2521
2522 void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data)
2523 {
2524         u32 dword;
2525
2526
2527         Set_NB32(dev, index_reg + 0x4, data);
2528         index |= (1 << DctAccessWrite);
2529         Set_NB32(dev, index_reg, index);
2530         do {
2531                 dword = Get_NB32(dev, index_reg);
2532         } while (!(dword & (1 << DctAccessDone)));
2533
2534 }
2535
2536
2537 static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
2538                                         struct DCTStatStruc *pDCTstat, u8 dct)
2539 {
2540         /* Get platform specific config/timing values from the interface layer
2541          * and program them into DCT.
2542          */
2543
2544         u32 dev = pDCTstat->dev_dct;
2545         u32 index_reg;
2546         u8 i, i_start, i_end;
2547
2548         if (pDCTstat->GangedMode) {
2549                 SyncSetting(pDCTstat);
2550                 i_start = 0;
2551                 i_end = 2;
2552         } else {
2553                 i_start = dct;
2554                 i_end = dct + 1;
2555         }
2556         for (i=i_start; i<i_end; i++) {
2557                 index_reg = 0x98 + (i * 0x100);
2558                 Set_NB32_index_wait(dev, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A Output Driver Compensation Control */
2559                 Set_NB32_index_wait(dev, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A Output Driver Compensation Control */
2560         }
2561
2562         return pDCTstat->ErrCode;
2563
2564 }
2565
2566
2567 static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat)
2568 {
2569         u32 dev;
2570         u32 val;
2571
2572         if (pDCTstat->NodePresent) {
2573                 print_tx("mct_SyncDCTsReady: Node ", pDCTstat->Node_ID);
2574                 dev = pDCTstat->dev_dct;
2575
2576                 if ((pDCTstat->DIMMValidDCT[0] ) || (pDCTstat->DIMMValidDCT[1])) {              /* This Node has dram */
2577                         do {
2578                                 val = Get_NB32(dev, 0x110);
2579                         } while (!(val & (1 << DramEnabled)));
2580                         print_t("mct_SyncDCTsReady: DramEnabled\n");
2581                 }
2582         }       /* Node is present */
2583 }
2584
2585
2586 static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat,
2587                                 struct DCTStatStruc *pDCTstat, u8 dct)
2588 {
2589         if (!pDCTstat->GangedMode) {
2590                 if (dct == 0 ) {
2591                         pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
2592                         if (pDCTstat->DIMMValidDCT[dct] == 0)
2593                                 pDCTstat->ErrCode = SC_StopError;
2594                 } else {
2595                         pDCTstat->CSPresent = 0;
2596                         pDCTstat->CSTestFail = 0;
2597                         pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
2598                         if (pDCTstat->DIMMValidDCT[dct] == 0)
2599                                 pDCTstat->ErrCode = SC_StopError;
2600                 }
2601         }
2602 }
2603
2604 static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,
2605                                         struct DCTStatStruc *pDCTstat, u8 dct)
2606 {
2607         u8 ret;
2608
2609         if ( dct == 0) {
2610                 SPDCalcWidth_D(pMCTstat, pDCTstat);
2611                 ret = mct_setMode(pMCTstat, pDCTstat);
2612         } else {
2613                 ret = pDCTstat->ErrCode;
2614         }
2615
2616         print_tx("SPDCalcWidth: Status ", pDCTstat->Status);
2617         print_tx("SPDCalcWidth: ErrStatus ", pDCTstat->ErrStatus);
2618         print_tx("SPDCalcWidth: ErrCode ", pDCTstat->ErrCode);
2619         print_t("SPDCalcWidth: Done\n");
2620
2621         return ret;
2622 }
2623
2624
2625 static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat,
2626                                         struct DCTStatStruc *pDCTstat, u8 dct)
2627 {
2628         u32 val;
2629         u32 dword;
2630         u32 dev;
2631         u32 reg;
2632         u8 _MemHoleRemap;
2633         u32 DramHoleBase;
2634
2635         _MemHoleRemap = mctGet_NVbits(NV_MemHole);
2636         DramHoleBase = mctGet_NVbits(NV_BottomIO);
2637         DramHoleBase <<= 8;
2638         /* Increase hole size so;[31:24]to[31:16]
2639          * it has granularity of 128MB shl eax,8
2640          * Set 'effective' bottom IOmov DramHoleBase,eax
2641          */
2642         pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
2643
2644         /* In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */
2645         if (!pDCTstat->GangedMode) {
2646                 dev = pDCTstat->dev_dct;
2647                 pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit;
2648                 /* if DCT0 and DCT1 both exist, set DctSelBaseAddr[47:27] to the top of DCT0 */
2649                 if (dct == 0) {
2650                         if (pDCTstat->DIMMValidDCT[1] > 0) {
2651                                 dword = pDCTstat->DCTSysLimit + 1;
2652                                 dword += pDCTstat->NodeSysBase;
2653                                 dword >>= 8; /* scale [39:8] to [47:27],and to F2x110[31:11] */
2654                                 if ((dword >= DramHoleBase) && _MemHoleRemap) {
2655                                         pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
2656                                         val = pMCTstat->HoleBase;
2657                                         val >>= 16;
2658                                         val = (((~val) & 0xFF) + 1);
2659                                         val <<= 8;
2660                                         dword += val;
2661                                 }
2662                                 reg = 0x110;
2663                                 val = Get_NB32(dev, reg);
2664                                 val &= 0x7F;
2665                                 val |= dword;
2666                                 val |= 3;  /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */
2667                                 Set_NB32(dev, reg, val);
2668                                 print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select Low Register = ", val);
2669                                 print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select High Register = ", dword);
2670
2671                                 reg = 0x114;
2672                                 val = dword;
2673                                 Set_NB32(dev, reg, val);
2674                         }
2675                 } else {
2676                         /* Program the DctSelBaseAddr value to 0
2677                            if DCT 0 is disabled */
2678                         if (pDCTstat->DIMMValidDCT[0] == 0) {
2679                                 dword = pDCTstat->NodeSysBase;
2680                                 dword >>= 8;
2681                                 if ((dword >= DramHoleBase) && _MemHoleRemap) {
2682                                         pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
2683                                         val = pMCTstat->HoleBase;
2684                                         val >>= 8;
2685                                         val &= ~(0xFFFF);
2686                                         val |= (((~val) & 0xFFFF) + 1);
2687                                         dword += val;
2688                                 }
2689                                 reg = 0x114;
2690                                 val = dword;
2691                                 Set_NB32(dev, reg, val);
2692
2693                                 reg = 0x110;
2694                                 val |= 3;       /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */
2695                                 Set_NB32(dev, reg, val);
2696                                 print_tx("AfterStitch DCT1 only: DRAM Controller Select Low Register = ", val);
2697                                 print_tx("AfterStitch DCT1 only: DRAM Controller Select High Register = ", dword);
2698                         }
2699                 }
2700         } else {
2701                 pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit;
2702         }
2703         print_tx("AfterStitch pDCTstat->NodeSysBase = ", pDCTstat->NodeSysBase);
2704         print_tx("mct_AfterStitchMemory: pDCTstat->NodeSysLimit ", pDCTstat->NodeSysLimit);
2705 }
2706
2707
2708 static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat,
2709                                         struct DCTStatStruc *pDCTstat, u8 dct)
2710 {
2711         u8 ret;
2712
2713         if ( dct == 0)
2714                 ret = DIMMPresence_D(pMCTstat, pDCTstat);
2715         else
2716                 ret = pDCTstat->ErrCode;
2717
2718         return ret;
2719 }
2720
2721
2722 /* mct_BeforeGetDIMMAddress inline in C */
2723
2724
2725 static void mct_OtherTiming(struct MCTStatStruc *pMCTstat,
2726                                 struct DCTStatStruc *pDCTstatA)
2727 {
2728         u8 Node;
2729
2730         for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
2731                 struct DCTStatStruc *pDCTstat;
2732                 pDCTstat = pDCTstatA + Node;
2733                 if (pDCTstat->NodePresent) {
2734                         if (pDCTstat->DIMMValidDCT[0]) {
2735                                 pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[0];
2736                                 Set_OtherTiming(pMCTstat, pDCTstat, 0);
2737                         }
2738                         if (pDCTstat->DIMMValidDCT[1] && !pDCTstat->GangedMode ) {
2739                                 pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[1];
2740                                 Set_OtherTiming(pMCTstat, pDCTstat, 1);
2741                         }
2742                 }       /* Node is present*/
2743         }       /* while Node */
2744 }
2745
2746
2747 static void Set_OtherTiming(struct MCTStatStruc *pMCTstat,
2748                                 struct DCTStatStruc *pDCTstat, u8 dct)
2749 {
2750         u32 reg;
2751         u32 reg_off = 0x100 * dct;
2752         u32 val;
2753         u32 dword;
2754         u32 dev = pDCTstat->dev_dct;
2755
2756         Get_Trdrd(pMCTstat, pDCTstat, dct);
2757         Get_Twrwr(pMCTstat, pDCTstat, dct);
2758         Get_Twrrd(pMCTstat, pDCTstat, dct);
2759         Get_TrwtTO(pMCTstat, pDCTstat, dct);
2760         Get_TrwtWB(pMCTstat, pDCTstat);
2761
2762         reg = 0x8C + reg_off;           /* Dram Timing Hi */
2763         val = Get_NB32(dev, reg);
2764         val &= 0xffff0300;
2765         dword = pDCTstat->TrwtTO; //0x07
2766         val |= dword << 4;
2767         dword = pDCTstat->Twrrd; //0x03
2768         val |= dword << 10;
2769         dword = pDCTstat->Twrwr; //0x03
2770         val |= dword << 12;
2771         dword = pDCTstat->Trdrd; //0x03
2772         val |= dword << 14;
2773         dword = pDCTstat->TrwtWB; //0x07
2774         val |= dword;
2775         val = OtherTiming_A_D(pDCTstat, val);
2776         Set_NB32(dev, reg, val);
2777
2778 }
2779
2780
2781 static void Get_Trdrd(struct MCTStatStruc *pMCTstat,
2782                         struct DCTStatStruc *pDCTstat, u8 dct)
2783 {
2784         u8 Trdrd;
2785         u8 byte;
2786         u32 dword;
2787         u32 val;
2788         u32 index_reg = 0x98 + 0x100 * dct;
2789         u32 dev = pDCTstat->dev_dct;
2790
2791         if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) {
2792                 /* mixed (x4 or x8) DIMM types
2793                   the largest DqsRcvEnGrossDelay of any DIMM minus the DqsRcvEnGrossDelay
2794                   of any other DIMM is equal to the Critical Gross Delay Difference (CGDD) for Trdrd.*/
2795                 byte = Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
2796                 if (byte == 0)
2797                         Trdrd = 1;
2798                 else
2799                         Trdrd = 2;
2800
2801         } else {
2802                 /*
2803                  Trdrd with non-mixed DIMM types
2804                  RdDqsTime are the same for all DIMMs and DqsRcvEn difference between
2805                  any two DIMMs is less than half of a MEMCLK, BIOS should program Trdrd to 0000b,
2806                  else BIOS should program Trdrd to 0001b.
2807
2808                  RdDqsTime are the same for all DIMMs
2809                  DDR400~DDR667 only use one set register
2810                  DDR800 have two set register for DIMM0 and DIMM1 */
2811                 Trdrd = 1;
2812                 if (pDCTstat->Speed > 3) {
2813                         /* DIMM0+DIMM1 exist */ //NOTE it should be 5
2814                         val = bsf(pDCTstat->DIMMValid);
2815                         dword = bsr(pDCTstat->DIMMValid);
2816                         if (dword != val && dword != 0)  {
2817                                 /* DCT Read DQS Timing Control - DIMM0 - Low */
2818                                 dword = Get_NB32_index_wait(dev, index_reg, 0x05);
2819                                 /* DCT Read DQS Timing Control - DIMM1 - Low */
2820                                 val = Get_NB32_index_wait(dev, index_reg, 0x105);
2821                                 if (val != dword)
2822                                         goto Trdrd_1;
2823
2824                                 /* DCT Read DQS Timing Control - DIMM0 - High */
2825                                 dword = Get_NB32_index_wait(dev, index_reg, 0x06);
2826                                 /* DCT Read DQS Timing Control - DIMM1 - High */
2827                                 val = Get_NB32_index_wait(dev, index_reg, 0x106);
2828                                 if (val != dword)
2829                                         goto Trdrd_1;
2830                         }
2831                 }
2832
2833                 /* DqsRcvEn difference between any two DIMMs is
2834                    less than half of a MEMCLK */
2835                 /* DqsRcvEn byte 1,0*/
2836                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x10))
2837                         goto Trdrd_1;
2838                 /* DqsRcvEn byte 3,2*/
2839                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x11))
2840                         goto Trdrd_1;
2841                 /* DqsRcvEn byte 5,4*/
2842                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x20))
2843                         goto Trdrd_1;
2844                 /* DqsRcvEn byte 7,6*/
2845                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x21))
2846                         goto Trdrd_1;
2847                 /* DqsRcvEn ECC*/
2848                 if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x12))
2849                         goto Trdrd_1;
2850                 Trdrd = 0;
2851         Trdrd_1:
2852                 ;
2853         }
2854         pDCTstat->Trdrd = Trdrd;
2855
2856 }
2857
2858
2859 static void Get_Twrwr(struct MCTStatStruc *pMCTstat,
2860                         struct DCTStatStruc *pDCTstat, u8 dct)
2861 {
2862         u8 Twrwr = 0;
2863         u32 index_reg = 0x98 + 0x100 * dct;
2864         u32 dev = pDCTstat->dev_dct;
2865         u32 val;
2866         u32 dword;
2867
2868         /* WrDatGrossDlyByte only use one set register when DDR400~DDR667
2869            DDR800 have two set register for DIMM0 and DIMM1 */
2870         if (pDCTstat->Speed > 3) {
2871                 val = bsf(pDCTstat->DIMMValid);
2872                 dword = bsr(pDCTstat->DIMMValid);
2873                 if (dword != val && dword != 0)  {
2874                         /*the largest WrDatGrossDlyByte of any DIMM minus the
2875                         WrDatGrossDlyByte of any other DIMM is equal to CGDD */
2876                         val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
2877                 }
2878                 if (val == 0)
2879                         Twrwr = 2;
2880                 else
2881                         Twrwr = 3;
2882         }
2883         pDCTstat->Twrwr = Twrwr;
2884 }
2885
2886
2887 static void Get_Twrrd(struct MCTStatStruc *pMCTstat,
2888                         struct DCTStatStruc *pDCTstat, u8 dct)
2889 {
2890         u8 byte, bytex, val;
2891         u32 index_reg = 0x98 + 0x100 * dct;
2892         u32 dev = pDCTstat->dev_dct;
2893
2894         /* On any given byte lane, the largest WrDatGrossDlyByte delay of
2895            any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is
2896            equal to the Critical Gross Delay Difference (CGDD) for Twrrd.*/
2897
2898         /* WrDatGrossDlyByte only use one set register when DDR400~DDR667
2899            DDR800 have two set register for DIMM0 and DIMM1 */
2900         if (pDCTstat->Speed > 3) {
2901                 val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
2902         } else {
2903                 val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 1);  /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */
2904                 pDCTstat->WrDatGrossH = (u8) val; /* low byte = max value */
2905         }
2906
2907         Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
2908
2909         bytex = pDCTstat->DqsRcvEnGrossL;
2910         byte = pDCTstat->WrDatGrossH;
2911         if (byte > bytex) {
2912                 byte -= bytex;
2913                 if (byte == 1)
2914                         bytex = 1;
2915                 else
2916                         bytex = 2;
2917         } else {
2918                 bytex = 0;
2919         }
2920         pDCTstat->Twrrd = bytex;
2921 }
2922
2923
2924 static void Get_TrwtTO(struct MCTStatStruc *pMCTstat,
2925                         struct DCTStatStruc *pDCTstat, u8 dct)
2926 {
2927         u8 byte, bytex;
2928         u32 index_reg = 0x98 + 0x100 * dct;
2929         u32 dev = pDCTstat->dev_dct;
2930
2931         /* On any given byte lane, the largest WrDatGrossDlyByte delay of
2932            any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is
2933            equal to the Critical Gross Delay Difference (CGDD) for TrwtTO. */
2934         Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
2935         Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
2936         bytex = pDCTstat->DqsRcvEnGrossL;
2937         byte = pDCTstat->WrDatGrossH;
2938         if (bytex > byte) {
2939                 bytex -= byte;
2940                 if ((bytex == 1) || (bytex == 2))
2941                         bytex = 3;
2942                 else
2943                         bytex = 4;
2944         } else {
2945                 byte -= bytex;
2946                 if ((byte == 0) || (byte == 1))
2947                         bytex = 2;
2948                 else
2949                         bytex = 1;
2950         }
2951
2952         pDCTstat->TrwtTO = bytex;
2953 }
2954
2955
2956 static void Get_TrwtWB(struct MCTStatStruc *pMCTstat,
2957                         struct DCTStatStruc *pDCTstat)
2958 {
2959         /* TrwtWB ensures read-to-write data-bus turnaround.
2960            This value should be one more than the programmed TrwtTO.*/
2961         pDCTstat->TrwtWB = pDCTstat->TrwtTO + 1;
2962 }
2963
2964
2965 static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat,
2966                                         u8 dct, u32 dev, u32 index_reg,
2967                                         u32 index)
2968 {
2969         u8 Smallest_0, Largest_0, Smallest_1, Largest_1;
2970         u8 i;
2971         u32 val;
2972         u8 byte;
2973         u8 ecc_reg = 0;
2974
2975         Smallest_0 = 0xFF;
2976         Smallest_1 = 0xFF;
2977         Largest_0 = 0;
2978         Largest_1 = 0;
2979
2980         if (index == 0x12)
2981                 ecc_reg = 1;
2982
2983         for (i=0; i < 8; i+=2) {
2984                 if ( pDCTstat->DIMMValid & (1 << i)) {
2985                         val = Get_NB32_index_wait(dev, index_reg, index);
2986                         byte = val & 0xFF;
2987                         if (byte < Smallest_0)
2988                                 Smallest_0 = byte;
2989                         if (byte > Largest_0)
2990                                 Largest_0 = byte;
2991                         if (!(ecc_reg)) {
2992                                 byte = (val >> 16) & 0xFF;
2993                                 if (byte < Smallest_1)
2994                                         Smallest_1 = byte;
2995                                 if (byte > Largest_1)
2996                                         Largest_1 = byte;
2997                         }
2998                 }
2999                 index += 3;
3000         }       /* while ++i */
3001
3002         /* check if total DqsRcvEn delay difference between any
3003            two DIMMs is less than half of a MEMCLK */
3004         if ((Largest_0 - Smallest_0) > 31)
3005                 return 1;
3006         if (!(ecc_reg))
3007                 if ((Largest_1 - Smallest_1) > 31)
3008                         return 1;
3009         return 0;
3010 }
3011
3012
3013 static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat,
3014                                         u32 dev, u32 index_reg)
3015 {
3016         u8 Smallest, Largest;
3017         u32 val;
3018         u8 byte, bytex;
3019
3020         /* The largest DqsRcvEnGrossDelay of any DIMM minus the
3021            DqsRcvEnGrossDelay of any other DIMM is equal to the Critical
3022            Gross Delay Difference (CGDD) */
3023         /* DqsRcvEn byte 1,0 */
3024         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x10);
3025         Largest = val & 0xFF;
3026         Smallest = (val >> 8) & 0xFF;
3027
3028         /* DqsRcvEn byte 3,2 */
3029         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x11);
3030         byte = val & 0xFF;
3031         bytex = (val >> 8) & 0xFF;
3032         if (bytex < Smallest)
3033                 Smallest = bytex;
3034         if (byte > Largest)
3035                 Largest = byte;
3036
3037         /* DqsRcvEn byte 5,4 */
3038         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x20);
3039         byte = val & 0xFF;
3040         bytex = (val >> 8) & 0xFF;
3041         if (bytex < Smallest)
3042                 Smallest = bytex;
3043         if (byte > Largest)
3044                 Largest = byte;
3045
3046         /* DqsRcvEn byte 7,6 */
3047         val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x21);
3048         byte = val & 0xFF;
3049         bytex = (val >> 8) & 0xFF;
3050         if (bytex < Smallest)
3051                 Smallest = bytex;
3052         if (byte > Largest)
3053                 Largest = byte;
3054
3055         if (pDCTstat->DimmECCPresent> 0) {
3056                 /*DqsRcvEn Ecc */
3057                 val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x12);
3058                 byte = val & 0xFF;
3059                 bytex = (val >> 8) & 0xFF;
3060                 if (bytex < Smallest)
3061                         Smallest = bytex;
3062                 if (byte > Largest)
3063                         Largest = byte;
3064         }
3065
3066         pDCTstat->DqsRcvEnGrossL = Largest;
3067         return Largest - Smallest;
3068 }
3069
3070
3071 static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat,
3072                                         u8 dct, u32 dev, u32 index_reg)
3073 {
3074         u8 Smallest, Largest;
3075         u32 val;
3076         u8 byte, bytex;
3077
3078         /* The largest WrDatGrossDlyByte of any DIMM minus the
3079           WrDatGrossDlyByte of any other DIMM is equal to CGDD */
3080         val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x01);       /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */
3081         Largest = val & 0xFF;
3082         Smallest = (val >> 8) & 0xFF;
3083         val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x101);      /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM1 */
3084         byte = val & 0xFF;
3085         bytex = (val >> 8) & 0xFF;
3086         if (bytex < Smallest)
3087                 Smallest = bytex;
3088         if (byte > Largest)
3089                 Largest = byte;
3090
3091         // FIXME: Add Cx support.
3092
3093         pDCTstat->WrDatGrossH = Largest;
3094         return Largest - Smallest;
3095 }
3096
3097 static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat,
3098                                         u32 dev, u32 index_reg,
3099                                         u32 index)
3100 {
3101         u8 Smallest, Largest;
3102         u8 i;
3103         u8 byte;
3104         u32 val;
3105         u16 word;
3106         u8 ecc_reg = 0;
3107
3108         Smallest = 7;
3109         Largest = 0;
3110
3111         if (index == 0x12)
3112                 ecc_reg = 1;
3113
3114         for (i=0; i < 8; i+=2) {
3115                 if ( pDCTstat->DIMMValid & (1 << i)) {
3116                         val = Get_NB32_index_wait(dev, index_reg, index);
3117                         val &= 0x00E000E0;
3118                         byte = (val >> 5) & 0xFF;
3119                         if (byte < Smallest)
3120                                 Smallest = byte;
3121                         if (byte > Largest)
3122                                 Largest = byte;
3123                         if (!(ecc_reg)) {
3124                                 byte = (val >> (16 + 5)) & 0xFF;
3125                                 if (byte < Smallest)
3126                                         Smallest = byte;
3127                                 if (byte > Largest)
3128                                         Largest = byte;
3129                         }
3130                 }
3131         index += 3;
3132         }       /* while ++i */
3133
3134         word = Smallest;
3135         word <<= 8;
3136         word |= Largest;
3137
3138         return word;
3139 }
3140
3141 static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat,
3142                                         u8 dct, u32 dev, u32 index_reg,
3143                                         u32 index)
3144 {
3145         u8 Smallest, Largest;
3146         u8 i, j;
3147         u32 val;
3148         u8 byte;
3149         u16 word;
3150
3151         Smallest = 3;
3152         Largest = 0;
3153         for (i=0; i < 2; i++) {
3154                 val = Get_NB32_index_wait(dev, index_reg, index);
3155                 val &= 0x60606060;
3156                 val >>= 5;
3157                 for (j=0; j < 4; j++) {
3158                         byte = val & 0xFF;
3159                         if (byte < Smallest)
3160                                 Smallest = byte;
3161                         if (byte > Largest)
3162                                 Largest = byte;
3163                         val >>= 8;
3164                 }       /* while ++j */
3165                 index++;
3166         }       /*while ++i*/
3167
3168         if (pDCTstat->DimmECCPresent > 0) {
3169                 index++;
3170                 val = Get_NB32_index_wait(dev, index_reg, index);
3171                 val &= 0x00000060;
3172                 val >>= 5;
3173                 byte = val & 0xFF;
3174                 if (byte < Smallest)
3175                         Smallest = byte;
3176                 if (byte > Largest)
3177                         Largest = byte;
3178         }
3179
3180         word = Smallest;
3181         word <<= 8;
3182         word |= Largest;
3183
3184         return word;
3185 }
3186
3187
3188
3189 static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
3190                                 struct DCTStatStruc *pDCTstat)
3191 {
3192         print_t("\tmct_FinalMCT_D: Clr Cl, Wb\n");
3193
3194
3195         /* ClrClToNB_D postponed until we're done executing from ROM */
3196         mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat);
3197 }
3198
3199
3200 static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
3201 {
3202         print_t("\tmct_InitialMCT_D: Set Cl, Wb\n");
3203         mct_SetClToNB_D(pMCTstat, pDCTstat);
3204         mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat);
3205 }
3206
3207
3208 static u32 mct_NodePresent_D(void)
3209 {
3210         u32 val;
3211         val = 0x12001022;
3212         return val;
3213 }
3214
3215
3216 static void mct_init(struct MCTStatStruc *pMCTstat,
3217                         struct DCTStatStruc *pDCTstat)
3218 {
3219         u32 lo, hi;
3220         u32 addr;
3221
3222         pDCTstat->GangedMode = 0;
3223         pDCTstat->DRPresent = 1;
3224
3225         /* enable extend PCI configuration access */
3226         addr = 0xC001001F;
3227         _RDMSR(addr, &lo, &hi);
3228         if (hi & (1 << (46-32))) {
3229                 pDCTstat->Status |= 1 << SB_ExtConfig;
3230         } else {
3231                 hi |= 1 << (46-32);
3232                 _WRMSR(addr, lo, hi);
3233         }
3234 }
3235
3236
3237 static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat,
3238                                 struct DCTStatStruc *pDCTstat)
3239 {
3240         u32 reg;
3241         u32 val;
3242         u32 dev = pDCTstat->dev_dct;
3243
3244         /* Clear Legacy BIOS Mode bit */
3245         reg = 0x94;
3246         val = Get_NB32(dev, reg);
3247         val &= ~(1<<LegacyBiosMode);
3248         Set_NB32(dev, reg, val);
3249 }
3250
3251
3252 static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat,
3253                                 struct DCTStatStruc *pDCTstatA)
3254 {
3255         u8 Node;
3256         u32 Drambase, Dramlimit;
3257         u32 val;
3258         u32 reg;
3259         u32 dev;
3260         u32 devx;
3261         u32 dword;
3262         struct DCTStatStruc *pDCTstat;
3263
3264         pDCTstat = pDCTstatA + 0;
3265         dev = pDCTstat->dev_map;
3266
3267         /* Copy dram map from F1x40/44,F1x48/4c,
3268           to F1x120/124(Node0),F1x120/124(Node1),...*/
3269         for (Node=0; Node < MAX_NODES_SUPPORTED; Node++) {
3270                 pDCTstat = pDCTstatA + Node;
3271                 devx = pDCTstat->dev_map;
3272
3273                 /* get base/limit from Node0 */
3274                 reg = 0x40 + (Node << 3);               /* Node0/Dram Base 0 */
3275                 val = Get_NB32(dev, reg);
3276                 Drambase = val >> ( 16 + 3);
3277
3278                 reg = 0x44 + (Node << 3);               /* Node0/Dram Base 0 */
3279                 val = Get_NB32(dev, reg);
3280                 Dramlimit = val >> (16 + 3);
3281
3282                 /* set base/limit to F1x120/124 per Node */
3283                 if (pDCTstat->NodePresent) {
3284                         reg = 0x120;            /* F1x120,DramBase[47:27] */
3285                         val = Get_NB32(devx, reg);
3286                         val &= 0xFFE00000;
3287                         val |= Drambase;
3288                         Set_NB32(devx, reg, val);
3289
3290                         reg = 0x124;
3291                         val = Get_NB32(devx, reg);
3292                         val &= 0xFFE00000;
3293                         val |= Dramlimit;
3294                         Set_NB32(devx, reg, val);
3295
3296                         if ( pMCTstat->GStatus & ( 1 << GSB_HWHole)) {
3297                                 reg = 0xF0;
3298                                 val = Get_NB32(devx, reg);
3299                                 val |= (1 << DramMemHoistValid);
3300                                 val &= ~(0xFF << 24);
3301                                 dword = (pMCTstat->HoleBase >> (24 - 8)) & 0xFF;
3302                                 dword <<= 24;
3303                                 val |= dword;
3304                                 Set_NB32(devx, reg, val);
3305                         }
3306
3307                 }
3308         }
3309 }
3310
3311 static void SetCSTriState(struct MCTStatStruc *pMCTstat,
3312                                 struct DCTStatStruc *pDCTstat, u8 dct)
3313 {
3314         u32 val;
3315         u32 dev = pDCTstat->dev_dct;
3316         u32 index_reg = 0x98 + 0x100 * dct;
3317         u8 cs;
3318         u32 index;
3319         u16 word;
3320
3321         /* Tri-state unused chipselects when motherboard
3322            termination is available */
3323
3324         // FIXME: skip for Ax
3325
3326         word = pDCTstat->CSPresent;
3327         if (pDCTstat->Status & (1 << SB_Registered)) {
3328                 for (cs = 0; cs < 8; cs++) {
3329                         if (word & (1 << cs)) {
3330                                 if (!(cs & 1))
3331                                         word |= 1 << (cs + 1);
3332                         }
3333                 }
3334         }
3335         word = (~word) & 0xFF;
3336         index  = 0x0c;
3337         val = Get_NB32_index_wait(dev, index_reg, index);
3338         val |= word;
3339         Set_NB32_index_wait(dev, index_reg, index, val);
3340 }
3341
3342
3343 #ifdef UNUSED_CODE
3344 static void SetCKETriState(struct MCTStatStruc *pMCTstat,
3345                                 struct DCTStatStruc *pDCTstat, u8 dct)
3346 {
3347         u32 val;
3348         u32 dev;
3349         u32 index_reg = 0x98 + 0x100 * dct;
3350         u8 cs;
3351         u32 index;
3352         u16 word;
3353
3354         /* Tri-state unused CKEs when motherboard termination is available */
3355
3356         // FIXME: skip for Ax
3357
3358         dev = pDCTstat->dev_dct;
3359         word = 0x101;
3360         for (cs = 0; cs < 8; cs++) {
3361                 if (pDCTstat->CSPresent & (1 << cs)) {
3362                         if (!(cs & 1))
3363                                 word &= 0xFF00;
3364                         else
3365                                 word &= 0x00FF;
3366                 }
3367         }
3368
3369         index  = 0x0c;
3370         val = Get_NB32_index_wait(dev, index_reg, index);
3371         if ((word & 0x00FF) == 1)
3372                 val |= 1 << 12;
3373         else
3374                 val &= ~(1 << 12);
3375
3376         if ((word >> 8) == 1)
3377                 val |= 1 << 13;
3378         else
3379                 val &= ~(1 << 13);
3380
3381         Set_NB32_index_wait(dev, index_reg, index, val);
3382 }
3383 #endif
3384
3385 static void SetODTTriState(struct MCTStatStruc *pMCTstat,
3386                                 struct DCTStatStruc *pDCTstat, u8 dct)
3387 {
3388         u32 val;
3389         u32 dev;
3390         u32 index_reg = 0x98 + 0x100 * dct;
3391         u8 cs;
3392         u32 index;
3393         u8 odt;
3394         u8 max_dimms;
3395
3396         // FIXME: skip for Ax
3397
3398         dev = pDCTstat->dev_dct;
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
3473         Set_NB32_index_wait(dev, index_reg, 0x0a, dword);
3474 }
3475
3476
3477 static void WaitRoutine_D(u32 time)
3478 {
3479         while(time) {
3480                 _EXECFENCE;
3481                 time--;
3482         }
3483 }
3484
3485
3486 static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
3487                                         struct DCTStatStruc *pDCTstat)
3488 {
3489         u32 reg;
3490         u32 val;
3491         u32 dev = pDCTstat->dev_dct;
3492
3493         /* GhEnhancement #18429 modified by askar: For low NB CLK :
3494          * Memclk ratio, the DCT may need to arbitrate early to avoid
3495          * unnecessary bubbles.
3496          * bit 19 of F2x[1,0]78 Dram  Control Register, set this bit only when
3497          * NB CLK : Memclk ratio is between 3:1 (inclusive) to 4:5 (inclusive)
3498          */
3499
3500         reg = 0x78;
3501         val = Get_NB32(dev, reg);
3502
3503         //FIXME: check for Cx
3504         if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat))
3505                 val |= (1 << EarlyArbEn);
3506
3507         Set_NB32(dev, reg, val);
3508
3509 }
3510
3511
3512 static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
3513                                         struct DCTStatStruc *pDCTstat)
3514 {
3515         u32 reg;
3516         u32 val;
3517         u32 tmp;
3518         u32 rem;
3519         u32 dev = pDCTstat->dev_dct;
3520         u32  hi, lo;
3521         u8 NbDid = 0;
3522
3523         /* Check if NB COF >= 4*Memclk, if it is not, return a fatal error
3524          */
3525
3526         /* 3*(Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */
3527         _RDMSR(0xC0010071, &lo, &hi);
3528         if (lo & (1 << 22))
3529                 NbDid |= 1;
3530
3531
3532         reg = 0x94;
3533         val = Get_NB32(dev, reg);
3534         if (!(val & (1 << MemClkFreqVal)))
3535                 val = Get_NB32(dev, reg * 0x100);       /* get the DCT1 value */
3536
3537         val &= 0x07;
3538         val += 3;
3539         if (NbDid)
3540                 val <<= 1;
3541         tmp = val;
3542
3543         dev = pDCTstat->dev_nbmisc;
3544         reg = 0xD4;
3545         val = Get_NB32(dev, reg);
3546         val &= 0x1F;
3547         val += 3;
3548         val *= 3;
3549         val = val / tmp;
3550         rem = val % tmp;
3551         tmp >>= 1;
3552
3553         // Yes this could be nicer but this was how the asm was....
3554         if (val < 3) {                          /* NClk:MemClk < 3:1 */
3555                 return 0;
3556         } else if (val > 4) {                   /* NClk:MemClk >= 5:1 */
3557                 return 0;
3558         } else if ((val == 4) && (rem > tmp)) { /* NClk:MemClk > 4.5:1 */
3559                 return 0;
3560         } else {
3561                 return 1;                       /* 3:1 <= NClk:MemClk <= 4.5:1*/
3562         }
3563 }
3564
3565
3566 static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat,
3567                                         struct DCTStatStruc *pDCTstatA)
3568 {
3569         u8 Node;
3570         u32 i;
3571         struct DCTStatStruc *pDCTstat;
3572         u32 start, stop;
3573         u8 *p;
3574         u16 host_serv1, host_serv2;
3575
3576         /* Initialize Data structures by clearing all entries to 0 */
3577         p = (u8 *) pMCTstat;
3578         for (i = 0; i < sizeof(struct MCTStatStruc); i++) {
3579                 p[i] = 0;
3580         }
3581
3582         for (Node = 0; Node < 8; Node++) {
3583                 pDCTstat = pDCTstatA + Node;
3584                 host_serv1 = pDCTstat->HostBiosSrvc1;
3585                 host_serv2 = pDCTstat->HostBiosSrvc2;
3586
3587                 p = (u8 *) pDCTstat;
3588                 start = 0;
3589                 stop = (u32)(&((struct DCTStatStruc *)0)->CH_MaxRdLat[2]);
3590                 for (i = start; i < stop ; i++) {
3591                         p[i] = 0;
3592                 }
3593
3594                 start = (u32)(&((struct DCTStatStruc *)0)->CH_D_BC_RCVRDLY[2][4]);
3595                 stop = sizeof(struct DCTStatStruc);
3596                 for (i = start; i < stop; i++) {
3597                         p[i] = 0;
3598                 }
3599                 pDCTstat->HostBiosSrvc1 = host_serv1;
3600                 pDCTstat->HostBiosSrvc2 = host_serv2;
3601         }
3602 }
3603
3604
3605 static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat,
3606                                         struct DCTStatStruc *pDCTstat)
3607 {
3608         u8 i;
3609         u32 reg_off;
3610         u32 dev = pDCTstat->dev_dct;
3611
3612         // FIXME: skip for Ax
3613         if ((pDCTstat->Speed == 3) || ( pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533Mhz
3614                 for (i=0; i < 2; i++) {
3615                         reg_off = 0x100 * i;
3616                         Set_NB32(dev,  0x98 + reg_off, 0x0D000030);
3617                         Set_NB32(dev,  0x9C + reg_off, 0x00000806);
3618                         Set_NB32(dev,  0x98 + reg_off, 0x4D040F30);
3619                 }
3620         }
3621 }
3622
3623
3624 static void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat,
3625                         struct DCTStatStruc *pDCTstat, u8 *dqs_pos)
3626 {
3627         // FIXME: Skip for Ax
3628         if ((pDCTstat->Speed == 3) || ( pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533Mhz
3629                 *dqs_pos = 32;
3630         }
3631 }
3632
3633
3634 void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat,
3635                         struct DCTStatStruc *pDCTstat)
3636 {
3637         u32 lo, hi;
3638         u32 msr;
3639
3640         // FIXME: Maybe check the CPUID? - not for now.
3641         // pDCTstat->LogicalCPUID;
3642
3643         msr = BU_CFG2;
3644         _RDMSR(msr, &lo, &hi);
3645         lo |= 1 << ClLinesToNbDis;
3646         _WRMSR(msr, lo, hi);
3647 }
3648
3649
3650 void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat,
3651                         struct DCTStatStruc *pDCTstat)
3652 {
3653
3654         u32 lo, hi;
3655         u32 msr;
3656
3657         // FIXME: Maybe check the CPUID? - not for now.
3658         // pDCTstat->LogicalCPUID;
3659
3660         msr = BU_CFG2;
3661         _RDMSR(msr, &lo, &hi);
3662         if (!pDCTstat->ClToNB_flag)
3663                 lo &= ~(1<<ClLinesToNbDis);
3664         _WRMSR(msr, lo, hi);
3665
3666 }
3667
3668
3669 void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat,
3670                                 struct DCTStatStruc *pDCTstat)
3671 {
3672         u32 lo, hi;
3673         u32 msr;
3674
3675         // FIXME: Maybe check the CPUID? - not for now.
3676         // pDCTstat->LogicalCPUID;
3677
3678         msr = BU_CFG;
3679         _RDMSR(msr, &lo, &hi);
3680         hi |= (1 << WbEnhWsbDis_D);
3681         _WRMSR(msr, lo, hi);
3682 }
3683
3684
3685 void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat,
3686                                 struct DCTStatStruc *pDCTstat)
3687 {
3688         u32 lo, hi;
3689         u32 msr;
3690
3691         // FIXME: Maybe check the CPUID? - not for now.
3692         // pDCTstat->LogicalCPUID;
3693
3694         msr = BU_CFG;
3695         _RDMSR(msr, &lo, &hi);
3696         hi &= ~(1 << WbEnhWsbDis_D);
3697         _WRMSR(msr, lo, hi);
3698 }
3699
3700
3701 void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct,
3702                                 u32 DramConfigHi)
3703 {
3704         /* Bug#15114: Comp. update interrupted by Freq. change can cause
3705          * subsequent update to be invalid during any MemClk frequency change:
3706          * Solution: From the bug report:
3707          *  1. A software-initiated frequency change should be wrapped into the
3708          *     following sequence :
3709          *      - a) Disable Compensation (F2[1, 0]9C_x08[30] )
3710          *      b) Reset the Begin Compensation bit (D3CMP->COMP_CONFIG[0]) in all the compensation engines
3711          *      c) Do frequency change
3712          *      d) Enable Compensation (F2[1, 0]9C_x08[30] )
3713          *  2. A software-initiated Disable Compensation should always be
3714          *     followed by step b) of the above steps.
3715          * Silicon Status: Fixed In Rev B0
3716          *
3717          * Errata#177: DRAM Phy Automatic Compensation Updates May Be Invalid
3718          * Solution: BIOS should disable the phy automatic compensation prior
3719          * to initiating a memory clock frequency change as follows:
3720          *  1. Disable PhyAutoComp by writing 1'b1 to F2x[1, 0]9C_x08[30]
3721          *  2. Reset the Begin Compensation bits by writing 32'h0 to
3722          *     F2x[1, 0]9C_x4D004F00
3723          *  3. Perform frequency change
3724          *  4. Enable PhyAutoComp by writing 1'b0 to F2x[1, 0]9C_08[30]
3725          *  In addition, any time software disables the automatic phy
3726          *   compensation it should reset the begin compensation bit per step 2.
3727          *   Silicon Status: Fixed in DR-B0
3728          */
3729
3730         u32 dev = pDCTstat->dev_dct;
3731         u32 index_reg = 0x98 + 0x100 * dct;
3732         u32 index;
3733
3734         u32 val;
3735
3736         index = 0x08;
3737         val = Get_NB32_index_wait(dev, index_reg, index);
3738         Set_NB32_index_wait(dev, index_reg, index, val | (1 << DisAutoComp));
3739
3740         //FIXME: check for Bx Cx CPU
3741           // if Ax mct_SetDramConfigHi_Samp_D
3742
3743         /* errata#177 */
3744         index = 0x4D014F00;     /* F2x[1, 0]9C_x[D0FFFFF:D000000] DRAM Phy Debug Registers */
3745         index |= 1 << DctAccessWrite;
3746         val = 0;
3747         Set_NB32_index_wait(dev, index_reg, index, val);
3748
3749         Set_NB32(dev, 0x94 + 0x100 * dct, DramConfigHi);
3750
3751         index = 0x08;
3752         val = Get_NB32_index_wait(dev, index_reg, index);
3753         Set_NB32_index_wait(dev, index_reg, index, val & (~(1 << DisAutoComp)));
3754 }
3755
3756 static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat,
3757                                         struct DCTStatStruc *pDCTstatA)
3758 {
3759         u8 Node;
3760         struct DCTStatStruc *pDCTstat;
3761
3762         /* Errata 178
3763          *
3764          * Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
3765          *            In TX FIFO
3766          * Solution: BIOS should program DRAM Control Register[RdPtrInit] =
3767          *            5h, (F2x[1, 0]78[3:0] = 5h).
3768          * Silicon Status: Fixed In Rev B0
3769          *
3770          * Bug#15880: Determine validity of reset settings for DDR PHY timing.
3771          * Solutiuon: At least, set WrDqs fine delay to be 0 for DDR2 training.
3772          */
3773
3774         for (Node = 0; Node < 8; Node++) {
3775                 pDCTstat = pDCTstatA + Node;
3776
3777                 if (pDCTstat->NodePresent)
3778                         mct_BeforeDQSTrain_Samp_D(pMCTstat, pDCTstat);
3779                         mct_ResetDLL_D(pMCTstat, pDCTstat, 0);
3780                         mct_ResetDLL_D(pMCTstat, pDCTstat, 1);
3781
3782         }
3783 }
3784
3785 static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
3786                                         struct DCTStatStruc *pDCTstat, u8 dct)
3787 {
3788         u8 Receiver;
3789         u32 dev = pDCTstat->dev_dct;
3790         u32 reg_off = 0x100 * dct;
3791         u32 addr;
3792         u32 lo, hi;
3793         u8 wrap32dis = 0;
3794         u8 valid = 0;
3795
3796         /* Skip reset DLL for B3 */
3797         if (pDCTstat->LogicalCPUID & AMD_DR_B3) {
3798                 return;
3799         }
3800
3801         addr = HWCR;
3802         _RDMSR(addr, &lo, &hi);
3803         if(lo & (1<<17)) {              /* save the old value */
3804                 wrap32dis = 1;
3805         }
3806         lo |= (1<<17);                  /* HWCR.wrap32dis */
3807         lo &= ~(1<<15);                 /* SSEDIS */
3808         /* Setting wrap32dis allows 64-bit memory references in 32bit mode */
3809         _WRMSR(addr, lo, hi);
3810
3811
3812         pDCTstat->Channel = dct;
3813         Receiver = mct_InitReceiver_D(pDCTstat, dct);
3814         /* there are four receiver pairs, loosely associated with chipselects.*/
3815         for (; Receiver < 8; Receiver += 2) {
3816                 if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) {
3817                         addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, dct, Receiver, &valid);
3818                         if (valid) {
3819                                 mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr);      /* cache fills */
3820
3821                                 /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */
3822                                 Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00008000);
3823                                 mct_Wait(80); /* wait >= 300ns */
3824
3825                                 /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */
3826                                 Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00000000);
3827                                 mct_Wait(800); /* wait >= 2us */
3828                                 break;
3829                         }
3830                 }
3831         }
3832         if(!wrap32dis) {
3833                 addr = HWCR;
3834                 _RDMSR(addr, &lo, &hi);
3835                 lo &= ~(1<<17);         /* restore HWCR.wrap32dis */
3836                 _WRMSR(addr, lo, hi);
3837         }
3838 }
3839
3840
3841 static void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat,
3842                                         struct DCTStatStruc *pDCTstat)
3843 {
3844         u32 dev = pDCTstat->dev_dct;
3845         u32 val;
3846
3847         /*  Enable F2x110[DctDatIntlv] */
3848         // Call back not required mctHookBeforeDatIntlv_D()
3849         // FIXME Skip for Ax
3850         if (!pDCTstat->GangedMode) {
3851                 val = Get_NB32(dev, 0x110);
3852                 val |= 1 << 5;                  // DctDatIntlv
3853                 Set_NB32(dev, 0x110, val);
3854
3855                 // FIXME Skip for Cx
3856                 dev = pDCTstat->dev_nbmisc;
3857                 val = Get_NB32(dev, 0x8C);      // NB Configuration Hi
3858                 val |= 1 << (36-32);            // DisDatMask
3859                 Set_NB32(dev, 0x8C, val);
3860         }
3861 }
3862
3863 #ifdef UNUSED_CODE
3864 static void mct_SetupSync_D(struct MCTStatStruc *pMCTstat,
3865                                         struct DCTStatStruc *pDCTstat)
3866 {
3867         /* set F2x78[ChSetupSync] when F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup,
3868          * CkeSetup] setups for one DCT are all 0s and at least one of the setups,
3869          * F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, CkeSetup], of the other
3870          * controller is 1
3871          */
3872         u32 cha, chb;
3873         u32 dev = pDCTstat->dev_dct;
3874         u32 val;
3875
3876         cha = pDCTstat->CH_ADDR_TMG[0] & 0x0202020;
3877         chb = pDCTstat->CH_ADDR_TMG[1] & 0x0202020;
3878
3879         if ((cha != chb) && ((cha == 0) || (chb == 0))) {
3880                 val = Get_NB32(dev, 0x78);
3881                 val |= ChSetupSync;
3882                 Set_NB32(dev, 0x78, val);
3883         }
3884 }
3885 #endif
3886
3887 static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) {
3888
3889         u32 val;
3890         u32 reg_off = 0x100 * dct;
3891         u32 dev = pDCTstat->dev_dct;
3892
3893         if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) {
3894                 mct_Wait(10000);        /* Wait 50 us*/
3895                 val = Get_NB32(dev, 0x110);
3896                 if ( val & (1 << DramEnabled)) {
3897                         /* If 50 us expires while DramEnable =0 then do the following */
3898                         val = Get_NB32(dev, 0x90 + reg_off);
3899                         val &= ~(1 << Width128);                /* Program Width128 = 0 */
3900                         Set_NB32(dev, 0x90 + reg_off, val);
3901
3902                         val = Get_NB32_index_wait(dev, 0x98 + reg_off, 0x05);   /* Perform dummy CSR read to F2x09C_x05 */
3903
3904                         if (pDCTstat->GangedMode) {
3905                                 val = Get_NB32(dev, 0x90 + reg_off);
3906                                 val |= 1 << Width128;           /* Program Width128 = 0 */
3907                                 Set_NB32(dev, 0x90 + reg_off, val);
3908                         }
3909                 }
3910         }
3911 }
3912
3913
3914 /* ==========================================================
3915  *  6-bit Bank Addressing Table
3916  *  RR=rows-13 binary
3917  *  B=Banks-2 binary
3918  *  CCC=Columns-9 binary
3919  * ==========================================================
3920  *  DCT CCCBRR  Rows    Banks   Columns 64-bit CS Size
3921  *  Encoding
3922  *  0000        000000  13      2       9       128MB
3923  *  0001        001000  13      2       10      256MB
3924  *  0010        001001  14      2       10      512MB
3925  *  0011        010000  13      2       11      512MB
3926  *  0100        001100  13      3       10      512MB
3927  *  0101        001101  14      3       10      1GB
3928  *  0110        010001  14      2       11      1GB
3929  *  0111        001110  15      3       10      2GB
3930  *  1000        010101  14      3       11      2GB
3931  *  1001        010110  15      3       11      4GB
3932  *  1010        001111  16      3       10      4GB
3933  *  1011        010111  16      3       11      8GB
3934  */