Here's the VIA vx800 patch from OLPC.
[coreboot.git] / src / northbridge / via / vx800 / ddr2init / vx800 / DrivingSetting.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2009 One Laptop per Child, Association, 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 /*
21       Driving setting:  ODT/DQS/DQ/CS/MAA/MAB/DCLK
22     */
23
24 void DrivingODT(DRAM_SYS_ATTR * DramAttr);
25
26 void DrivingDQS(DRAM_SYS_ATTR * DramAttr);
27
28 void DrivingDQ(DRAM_SYS_ATTR * DramAttr);
29
30 void DrivingCS(DRAM_SYS_ATTR * DramAttr);
31
32 void DrivingMA(DRAM_SYS_ATTR * DramAttr);
33
34 void DrivingDCLK(DRAM_SYS_ATTR * DramAttr);
35
36 /* DRAM Driving Adjustment*/
37 void DRAMDriving(DRAM_SYS_ATTR * DramAttr)
38 {
39         PRINT_DEBUG_MEM("set ODT!\r");
40         DrivingODT(DramAttr);
41
42         PRINT_DEBUG_MEM("set DQS!\r");
43         DrivingDQS(DramAttr);
44
45         PRINT_DEBUG_MEM(("set DQ!\r"));
46         DrivingDQ(DramAttr);
47
48         PRINT_DEBUG_MEM("set CS!\r");
49         DrivingCS(DramAttr);
50
51         PRINT_DEBUG_MEM("set MAA!\r");
52         DrivingMA(DramAttr);
53
54         PRINT_DEBUG_MEM("set DCLK!\r");
55         DrivingDCLK(DramAttr);
56 }
57
58
59 /*
60 ODT     Control for DQ/DQS/CKE/SCMD/DCLKO in ChA & ChB
61 which include driving enable/range and strong/weak selection
62  
63 Processing: According to DRAM frequency to ODT control bits.
64                 Because function enable bit must be the last one to be set.
65                 So the register VIA_NB3DRAM_REGD4 and VIA_NB3DRAM_REGD3 should be
66                 the last register       to be programmed.
67 */
68 //-------------------------------------------------------------------------------
69 //                      ODT Lookup Table
70 //-------------------------------------------------------------------------------
71 #define Rank0_ODT                               0
72 #define Rank1_ODT                               1
73 #define Rank2_ODT                               2
74 #define Rank3_ODT                               3
75 #define NA_ODT                                  0
76 #define NB_ODT_75ohm                    0
77 #define NB_ODT_150ohm                   1
78
79 #define DDR2_ODT_75ohm                  0x20
80 #define DDR2_ODT_150ohm                 0x40
81
82 // Setting of ODT Lookup TBL
83 //                      RankMAP , Rank 3               Rank 2              Rank 1              Rank 0           , DRAM & NB ODT setting
84 //                  db  0000b   , Reserved
85 #define ODTLookup_Tbl_count 8
86 static const u8 ODTLookup_TBL[ODTLookup_Tbl_count][3] = {
87         // 0001b
88         {0x01,
89          (Rank3_ODT << 6) + (Rank2_ODT << 4) + (Rank1_ODT << 2) +
90          Rank0_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
91         // 0010b        , Reserved
92         // 0011b
93         {0x03,
94          (Rank3_ODT << 6) + (Rank2_ODT << 4) + (Rank0_ODT << 2) +
95          Rank1_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
96         // 0100b
97         {0x04,
98          (Rank3_ODT << 6) + (Rank2_ODT << 4) + (Rank1_ODT << 2) +
99          Rank0_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
100         // 0101b
101         {0x05,
102          (Rank3_ODT << 6) + (Rank0_ODT << 4) + (Rank1_ODT << 2) +
103          Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm},
104         // 0110b        , Reserved
105         // 0111b
106         {0x07,
107          (Rank3_ODT << 6) + (Rank0_ODT << 4) + (Rank2_ODT << 2) +
108          Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm},
109         // 1000b        , Reserved
110         // 1001b        , Reserved
111         // 1010b        , Reserved
112         // 1011b        , Reserved
113         // 1100b
114         {0x0c,
115          (Rank2_ODT << 6) + (Rank3_ODT << 4) + (Rank1_ODT << 2) +
116          Rank0_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
117         // 1101b
118         {0x0d,
119          (Rank0_ODT << 6) + (Rank0_ODT << 4) + (Rank1_ODT << 2) +
120          Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm},
121         // 1110b        , Reserved
122         // 1111b
123         {0x0f,
124          (Rank0_ODT << 6) + (Rank0_ODT << 4) + (Rank2_ODT << 2) +
125          Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm}
126 };
127
128 #define ODT_Table_Width_DDR2            4
129 //                                                                                               RxD6   RxD3 
130 static const u8 ODT_Control_DDR2[ODT_Table_Width_DDR2] = { 0xFC, 0x01 };
131
132 void DrivingODT(DRAM_SYS_ATTR * DramAttr)
133 {
134         u8 Data;
135         u8 i;
136         BOOLEAN bFound;
137
138         pci_write_config8(MEMCTRL, 0xD0, 0x88);
139
140         Data = ODT_Control_DDR2[0];
141         pci_write_config8(MEMCTRL, 0xd6, Data);
142
143         Data = ODT_Control_DDR2[1];
144         pci_write_config8(MEMCTRL, 0xd3, Data);
145
146         Data = pci_read_config8(MEMCTRL, 0x9e);
147         //set MD turn_around wait state
148         Data &= 0xCF;           /*clear bit4,5 */
149         if (DIMMFREQ_400 == DramAttr->DramFreq)
150                 Data |= 0x0;
151         else if (DIMMFREQ_533 == DramAttr->DramFreq)
152                 Data |= 0x10;
153         else if (DIMMFREQ_667 == DramAttr->DramFreq)
154                 Data |= 0x20;
155         else if (DIMMFREQ_800 == DramAttr->DramFreq)
156                 Data |= 0x20;
157         else
158                 Data |= 0;
159         pci_write_config8(MEMCTRL, 0x9e, Data);
160
161
162         if (DIMMFREQ_400 == DramAttr->DramFreq)
163                 Data = 0x0;
164         else if (DIMMFREQ_533 == DramAttr->DramFreq)
165                 Data = 0x11;
166         else if (DIMMFREQ_667 == DramAttr->DramFreq)
167                 Data = 0x11;
168         else if (DIMMFREQ_800 == DramAttr->DramFreq)
169                 Data = 0x11;
170         else
171                 Data = 0;
172         pci_write_config8(MEMCTRL, 0x9f, Data);
173
174
175         /*channel A ODT select */
176         if (DramAttr->DimmNumChA > 0) {
177                 Data = pci_read_config8(MEMCTRL, 0xd5);
178                 Data &= 0x5F;   /*clear bit7,5 */
179                 if (DramAttr->RankNumChA > 2)
180                         Data |= 0xA0;   /*if rank number > 2 (3or4), set bit7,5 */
181                 else
182                         Data |= 0x00;   /*if rank number is 1or2, clear bit5 */
183                 pci_write_config8(MEMCTRL, 0xd5, Data);
184
185                 Data = pci_read_config8(MEMCTRL, 0xd7);
186                 Data &= 0xEF;   /*clear bit7 */
187                 if (DramAttr->RankNumChA > 2)
188                         Data |= 0x80;   /*if rank number > 2 (3or4), set bit7 */
189                 else
190                         Data |= 0x00;   /*if rank number is 1or2,  clear bit7 */
191                 pci_write_config8(MEMCTRL, 0xd7, Data);
192
193
194                 /*channel A */
195                 Data = pci_read_config8(MEMCTRL, 0xd5);
196                 Data &= 0xF3;   //bit2,3
197                 if (DramAttr->DimmNumChA == 2)  /*2 Dimm, 3or4 Ranks */
198                         Data |= 0x00;
199                 else if (DramAttr->DimmNumChA == 1)
200                         Data |= 0x04;
201                 pci_write_config8(MEMCTRL, 0xd5, Data);
202
203                 if ((DramAttr->RankPresentMap & 0x0F) != 0) {   /*channel A */
204                         // MAA ODT Lookup Table
205                         bFound = FALSE;
206                         for (i = 0; i < ODTLookup_Tbl_count; i++) {
207                                 if ((DramAttr->RankPresentMap & 0x0F) ==
208                                     ODTLookup_TBL[i][0]) {
209                                         Data = ODTLookup_TBL[i][1];
210                                         bFound = TRUE;
211                                 }
212                         }
213                         if (!bFound) {  /*set default value */
214                                 Data =
215                                     ODTLookup_TBL[ODTLookup_Tbl_count -
216                                                   1][1];
217                         }
218                         pci_write_config8(MEMCTRL, 0x9c, Data);
219
220
221                         //set CHA MD ODT control State Dynamic-on
222                         Data = pci_read_config8(MEMCTRL, 0xD4);
223                         Data &= 0xC9;
224                         Data |= 0x30;
225                         pci_write_config8(MEMCTRL, 0xD4, Data);
226
227                         Data = pci_read_config8(MEMCTRL, 0x9e);
228                         Data |= 0x01;
229                         pci_write_config8(MEMCTRL, 0x9e, Data);
230                 }
231
232         }
233         /*channel B */
234         if (1 == ENABLE_CHC) {
235                 //CHB has not auto compensation mode ,so must set it manual,or else CHB initialization will not successful
236                 //   Data =0x88;
237                 //pci_write_config8(MEMCTRL, 0xd0, Data);
238
239                 Data = pci_read_config8(MEMCTRL, 0xd5);
240                 Data &= 0xAF;
241                 if (DramAttr->RankNumChB > 2)   /*rank number 3 or 4 */
242                         Data |= 0x50;
243                 else
244                         Data |= 0x00;
245                 pci_write_config8(MEMCTRL, 0xd5, Data);
246
247                 Data = pci_read_config8(MEMCTRL, 0xd7);
248                 Data &= 0xBF;   /*clear bit6 */
249                 if (DramAttr->RankNumChB > 2)
250                         Data |= 0x40;   /*if rank number > 2 (3or4), set bit7 */
251                 else
252                         Data |= 0x00;   /*if rank number is 1or2,  clear bit7 */
253                 pci_write_config8(MEMCTRL, 0xd7, Data);
254
255
256                 Data = pci_read_config8(MEMCTRL, 0xd5);
257                 Data &= 0xFC;
258                 if (DramAttr->DimmNumChB == 2)  /*2 Dimm, 3or4 Ranks */
259                         Data |= 0x00;   // 2 dimm RxD5[2,0]=0,0b
260                 else if (DramAttr->DimmNumChB == 1)
261                         Data |= 0x01;   // 1 dimm RxD5[2,0]=1,1b
262                 pci_write_config8(MEMCTRL, 0xd5, Data);
263
264                 //set CHB MD ODT control State Dynamic-on
265                 Data = pci_read_config8(MEMCTRL, 0xD4);
266                 Data &= 0xF6;
267                 Data |= 0x08;
268                 pci_write_config8(MEMCTRL, 0xD4, Data);
269
270
271                 //enable CHB differential DQS input
272                 Data = pci_read_config8(MEMCTRL, 0x9E);
273                 Data |= 0x02;
274                 pci_write_config8(MEMCTRL, 0x9E, Data);
275         }
276         //enable ODT Control
277         Data = pci_read_config8(MEMCTRL, 0x9e);
278         Data |= 0x80;
279         pci_write_config8(MEMCTRL, 0x9e, Data);
280 }
281
282 void DrivingDQS(DRAM_SYS_ATTR * DramAttr)
283 {
284         u8 Data;
285
286         /*channel A */
287         if (DramAttr->RankNumChA > 0) {
288                 Data = DDR2_DQSA_Driving_Table[DramAttr->RankNumChA - 1];
289                 pci_write_config8(MEMCTRL, 0xe0, Data);
290         }
291
292         /*channel B */
293         if (1 == ENABLE_CHC) {
294                 Data = DDR2_DQSB_Driving_Table[DramAttr->RankNumChB - 1];
295                 pci_write_config8(MEMCTRL, 0xe1, Data);
296         }
297
298 }
299
300 void DrivingDQ(DRAM_SYS_ATTR * DramAttr)
301 {
302         u8 Data;
303
304         /*channel A */
305         if (DramAttr->RankNumChA > 0) {
306                 Data = DDR2_DQA_Driving_Table[DramAttr->RankNumChA - 1];
307                 pci_write_config8(MEMCTRL, 0xe2, Data);
308
309         }
310         /*channel B */
311         if (1 == ENABLE_CHC) {
312                 Data = DDR2_DQB_Driving_Table[DramAttr->RankNumChB - 1];
313                 pci_write_config8(MEMCTRL, 0xe3, Data);
314         }
315 }
316
317 void DrivingCS(DRAM_SYS_ATTR * DramAttr)
318 {
319         u8 Data;
320         /*Channel A */
321         if (DramAttr->RankNumChA > 0) {
322                 Data = DDR2_CSA_Driving_Table_x8[DramAttr->RankNumChA - 1];
323                 pci_write_config8(MEMCTRL, 0xe4, Data);
324         }
325         /*channel B */
326         if (1 == ENABLE_CHC) {
327                 Data = DDR2_CSB_Driving_Table_x8[DramAttr->RankNumChB - 1];
328                 pci_write_config8(MEMCTRL, 0xe5, Data);
329         }
330 }
331
332 void DrivingMA(DRAM_SYS_ATTR * DramAttr)
333 {
334         u8 Data;
335         u8 i, FreqId;
336
337         if (DramAttr->RankNumChA > 0) {
338                 if (DIMMFREQ_400 == DramAttr->DramFreq)
339                         FreqId = 1;
340                 else if (DIMMFREQ_533 == DramAttr->DramFreq)
341                         FreqId = 2;
342                 else if (DIMMFREQ_667 == DramAttr->DramFreq)
343                         FreqId = 3;
344                 else if (DIMMFREQ_800 == DramAttr->DramFreq)
345                         FreqId = 4;
346                 else
347                         FreqId = 1;
348                 for (i = 0; i < MA_Table; i++) {
349                         if (DramAttr->LoadNumChA <=
350                             DDR2_MAA_Driving_Table[i][0]) {
351                                 Data = DDR2_MAA_Driving_Table[i][FreqId];
352                                 break;
353                         }
354                 }
355                 pci_write_config8(MEMCTRL, 0xe8, Data);
356         }
357         if (1 == ENABLE_CHC) {
358                 for (i = 0; i < MA_Table; i++) {
359                         if (DramAttr->LoadNumChA <=
360                             DDR2_MAB_Driving_Table[i][0]) {
361                                 Data = DDR2_MAB_Driving_Table[i][1];
362                                 break;
363                         }
364                 }
365                 pci_write_config8(MEMCTRL, 0xe9, Data);
366         }
367 }
368
369 void DrivingDCLK(DRAM_SYS_ATTR * DramAttr)
370 {
371         u8 Data;
372         u8 FreqId;
373
374         if (DIMMFREQ_400 == DramAttr->DramFreq)
375                 FreqId = 0;
376         else if (DIMMFREQ_533 == DramAttr->DramFreq)
377                 FreqId = 1;
378         else if (DIMMFREQ_667 == DramAttr->DramFreq)
379                 FreqId = 2;
380         else if (DIMMFREQ_800 == DramAttr->DramFreq)
381                 FreqId = 4;
382         else
383                 FreqId = 0;
384
385         /*channel A */
386         if (DramAttr->RankNumChA > 0) {
387                 Data = DDR2_DCLKA_Driving_Table[FreqId];
388                 pci_write_config8(MEMCTRL, 0xe6, Data);
389         }
390         /*channel B */
391         if (1 == ENABLE_CHC) {
392                 Data = DDR2_DCLKB_Driving_Table[FreqId];
393                 pci_write_config8(MEMCTRL, 0xe7, Data);
394         }
395
396 }