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