Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / northbridge / via / vx800 / timing_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     Set Dram Timing functions
22   */
23
24 void SetCL(DRAM_SYS_ATTR * DramAttr);
25
26 void SetTrp(DRAM_SYS_ATTR * DramAttr);
27
28 void SetTrcd(DRAM_SYS_ATTR * DramAttr);
29
30 void SetTras(DRAM_SYS_ATTR * DramAttr);
31
32 void SetTrfc(DRAM_SYS_ATTR * DramAttr);
33
34 void SetTrrd(DRAM_SYS_ATTR * DramAttr);
35
36 void SetTwr(DRAM_SYS_ATTR * DramAttr);
37
38 void SetTwtr(DRAM_SYS_ATTR * DramAttr);
39
40 void SetTrtp(DRAM_SYS_ATTR * DramAttr);
41
42 /* Set DRAM     Timing*/
43 void DRAMTimingSetting(DRAM_SYS_ATTR * DramAttr)
44 {
45         PRINT_DEBUG_MEM("Set CAS latency value!");
46         SetCL(DramAttr);
47
48         PRINT_DEBUG_MEM("Set tRP value!");
49         SetTrp(DramAttr);
50
51         PRINT_DEBUG_MEM("Set tRCD value!");
52         SetTrcd(DramAttr);
53
54         PRINT_DEBUG_MEM("Set tRAS value!");
55         SetTras(DramAttr);
56
57         PRINT_DEBUG_MEM("Set tRFC value!");
58         SetTrfc(DramAttr);
59
60         PRINT_DEBUG_MEM("Set tRRD value!");
61         SetTrrd(DramAttr);
62
63         PRINT_DEBUG_MEM("Set tWR value!");
64         SetTwr(DramAttr);
65
66         PRINT_DEBUG_MEM("Set tWTR value!");
67         SetTwtr(DramAttr);
68
69         PRINT_DEBUG_MEM("Set tRTP value!");
70         SetTrtp(DramAttr);
71 }
72
73 /*
74 Set DRAM Timing: CAS Latency for DDR1
75 D0F3RX62 bit[0:2] for CAS Latency;
76 */
77 void SetCL(DRAM_SYS_ATTR * DramAttr)
78 {
79         u8 Data;
80         u8 CL;
81
82         /*DDR2 CL Value: 20, 30, 40, 50 -> 2, 3, 4, 5 */
83         CL = (u8) ((DramAttr->CL - 20) / 10);   //000,001,010,011
84
85         PRINT_DEBUG_MEM("CAS = ");
86         PRINT_DEBUG_MEM_HEX8(CL);
87         PRINT_DEBUG_MEM("\n");
88         Data = pci_read_config8(MEMCTRL, 0x62);
89         Data = (u8) ((Data & 0xf8) | CL);
90         pci_write_config8(MEMCTRL, 0x62, Data);
91 }
92
93 /*
94  Minimum row precharge time, Trp for DDR1/DDR2
95  D0F3Rx64[3:2] for Trp 2T~5T
96 */
97 #define MAX_TRP 6
98 #define MIN_TRP 2
99
100 void SetTrp(DRAM_SYS_ATTR * DramAttr)
101 {
102         u8 Data;
103         u16 Max, Tmp;
104         u8 Socket;
105
106         /*get the max Trp value from SPD data
107            SPD Byte27, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
108         Max = 0;
109         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
110                 if (DramAttr->DimmInfo[Socket].bPresence) {
111                         Tmp =
112                             (u16) (DramAttr->
113                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRP]);
114                         if (Tmp > Max)
115                                 Max = Tmp;
116                 }
117                 /*Calculate clock,this value should be 2T,3T,4T,5T */
118         }
119         Tmp =
120             (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) -
121                     1) / ((DramAttr->DramCyc) << 2));
122         PRINT_DEBUG_MEM("Trp = ");
123         PRINT_DEBUG_MEM_HEX16(Tmp);
124         PRINT_DEBUG_MEM("\r");
125
126         if (Tmp > MAX_TRP)
127                 Tmp = MAX_TRP;
128         else if (Tmp < MIN_TRP)
129                 Tmp = MIN_TRP;
130
131         Tmp -= 2;               //00->2T, 01->3T, 10->4T, 11->5T
132         Tmp <<= 1;              //bit1,2,3
133
134         Data = pci_read_config8(MEMCTRL, 0x64);
135         Data = (u8) ((Data & 0xf1) | (u8) Tmp);
136         pci_write_config8(MEMCTRL, 0x64, Data);
137
138         //enable DDR2 8-Bank Device Timing Constraint
139         Data = pci_read_config8(MEMCTRL, 0x62);
140         Data = (u8) ((Data & 0xf7) | 0x08);
141         pci_write_config8(MEMCTRL, 0x62, Data);
142 }
143
144 /*
145 Minimum RAS to CAS dely,Trcd for DDR1/DDR2
146 D0F3Rx64[7:6] for Trcd
147 */
148 #define MAX_TRCD 6
149 #define MIN_TRCD 2
150
151 void SetTrcd(DRAM_SYS_ATTR * DramAttr)
152 {
153         u8 Data;
154         u16 Max, Tmp;
155         u8 Socket;
156
157         /*get the max Trcd value from SPD data
158            SPD Byte29, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
159         Max = 0;
160         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
161                 if (DramAttr->DimmInfo[Socket].bPresence) {
162                         Tmp =
163                             (u16) (DramAttr->
164                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRCD]);
165                         if (Tmp > Max)
166                                 Max = Tmp;
167                 }
168         }
169         /*Calculate clock,this value should be 2T,3T,4T,5T */
170         Tmp =
171             (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) -
172                     1) / ((DramAttr->DramCyc) << 2));
173         PRINT_DEBUG_MEM("Trcd =");
174         PRINT_DEBUG_MEM_HEX16(Tmp);
175         PRINT_DEBUG_MEM("\r");
176
177         if (Tmp > MAX_TRCD)
178                 Tmp = MAX_TRCD;
179         else if (Tmp < MIN_TRCD)
180                 Tmp = MIN_TRCD;
181         Tmp -= 2;               //00->2T, 01->3T, 10->4T, 11->5T
182         Tmp <<= 5;              //bit5,6,7
183
184         Data = pci_read_config8(MEMCTRL, 0x64);
185         Data = (u8) ((Data & 0x1f) | (u8) Tmp);
186         pci_write_config8(MEMCTRL, 0x64, Data);
187
188 }
189
190 /*
191  minimum active to precharge time,Tras for DDR1/DDR2
192  D0F3Rx62[7:4] Tras
193 */
194 #define MAX_TRAS 20             //20T
195 #define MIN_TRAS 5              //5T
196 void SetTras(DRAM_SYS_ATTR * DramAttr)
197 {
198         u8 Data;
199         u16 Max, Tmp;
200         u8 Socket;
201
202         /*get the max Tras value from SPD data
203            SPD byte30: bit0:7 1ns~255ns */
204         Max = 0;
205         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
206                 if (DramAttr->DimmInfo[Socket].bPresence) {
207                         Tmp =
208                             (u16) (DramAttr->
209                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRAS]);
210                         if (Tmp > Max)
211                                 Max = Tmp;
212                 }
213         }
214
215         /*Calculate clock,value range 5T-20T */
216         Tmp = (u16) ((Max * 100 + DramAttr->DramCyc - 1) / (DramAttr->DramCyc));
217         PRINT_DEBUG_MEM("Tras =");
218         PRINT_DEBUG_MEM_HEX16(Tmp);
219         PRINT_DEBUG_MEM("\r");
220
221         if (Tmp > MAX_TRAS)
222                 Tmp = MAX_TRAS;
223         else if (Tmp < MIN_TRAS)
224                 Tmp = MIN_TRAS;
225         Tmp -= 5;               //0->5T  ... 1111->20T
226         Tmp <<= 4;              //bit4:7
227
228         Data = pci_read_config8(MEMCTRL, 0x62);
229         Data = (u8) ((Data & 0x0f) | (u8) Tmp);
230         pci_write_config8(MEMCTRL, 0x62, Data);
231 }
232
233 /*
234 Minimum refresh to activate/refresh command period Trfc for DDR1/DDR2
235 D0F3Rx61[5:0] for Trfc
236 */
237
238 #define MAX_TRFC 71             // Max supported,71T
239 #define MIN_TRFC 8              // Min supported,8T
240
241 void SetTrfc(DRAM_SYS_ATTR * DramAttr)
242 {
243
244         u8 Data;
245         u32 Max, Tmp;
246         u8 Byte40;
247         u8 Socket;
248
249         /*get the max Trfc value from SPD data */
250         Max = 0;
251         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
252                 if (DramAttr->DimmInfo[Socket].bPresence) {
253                         Tmp =
254                             (u32) (DramAttr->
255                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRFC])
256                             * 100;
257                         /*only DDR2 need to add byte 40 bit[7:4] */
258                         Byte40 =
259                             (DramAttr->
260                              DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRFC2]);
261                         /*if bit0 = 1, byte42(RFC)+256ns, SPD spec JEDEC standard No.21.c */
262                         if (Byte40 & 0x01)
263                                 Tmp += (256 * 100);
264                         /*bit1,2,3 000->0ns+byte42; 001->0.25ns+byte42; 010->0.33ns+byte42; 011->0.5ns+byte42;100-> 0.75ns+byte42 */
265                         switch ((Byte40 >> 1) & 0x07) { /*bit1,2,3 */
266                         case 1:
267                                 Tmp += 25;
268                                 break;
269                         case 2:
270                                 Tmp += 33;
271                                 break;
272                         case 3:
273                                 Tmp += 50;
274                                 break;
275                         case 4:
276                                 Tmp += 66;
277                                 break;
278                         case 5:
279                                 Tmp += 75;
280                                 break;
281                         case 6: //what is FRU???
282                         default:
283                                 break;
284                         }
285                         if (Tmp > Max)
286                                 Max = Tmp;
287                 }
288         }
289
290         /*Calculate clock,value range 8T-71T */
291         Tmp = (u16) ((Max + DramAttr->DramCyc - 1) / (DramAttr->DramCyc));
292         PRINT_DEBUG_MEM("Trfc = ");
293         PRINT_DEBUG_MEM_HEX16(Tmp);
294         PRINT_DEBUG_MEM("\r");
295         if (Tmp > MAX_TRFC)
296                 Tmp = MAX_TRFC;
297         else if (Tmp < MIN_TRFC) {
298                 // return;
299                 Tmp = 0x40;
300         }
301         /*D0F3Rx61 bit[0:5] 0->8T ... 63->71T */
302         Tmp -= 8;
303
304         Data = pci_read_config8(MEMCTRL, 0x61);
305         Data = (u8) ((Data & 0xc0) | ((u8) Tmp & 0x3f));
306         pci_write_config8(MEMCTRL, 0x61, Data);
307 }
308
309 /*
310 Minimum row active to row active delay: Trrd for DDR1/DDR2
311 D0F3Rx61[7:6]:Trrd  00->2T, 01->3T, 10->4T, 11->5T
312 */
313 #define MAX_TRRD 5
314 #define MIN_TRRD 2
315
316 void SetTrrd(DRAM_SYS_ATTR * DramAttr)
317 {
318         u8 Data;
319         u16 Max, Tmp;
320         u8 Socket;
321
322         /*get the max Trrd value from SPD data
323            SPD Byte28, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
324         Max = 0;
325         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
326                 if (DramAttr->DimmInfo[Socket].bPresence) {
327                         Tmp =
328                             (u16) (DramAttr->
329                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRRD]);
330                         if (Tmp > Max)
331                                 Max = Tmp;
332                 }
333         }
334
335         /*Calculate clock,this value should be 2T,3T,4T,5T */
336         Tmp =
337             (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) -
338                     1) / ((DramAttr->DramCyc) << 2));
339         PRINT_DEBUG_MEM("Trrd =");
340         PRINT_DEBUG_MEM_HEX16(Tmp);
341         PRINT_DEBUG_MEM("\r");
342
343         if (Tmp > MAX_TRRD)
344                 Tmp = MAX_TRRD;
345         else if (Tmp < MIN_TRRD)
346                 Tmp = MIN_TRRD;
347         Tmp -= 2;               //00->2T, 01->3T, 10->4T, 11->5T
348         Tmp <<= 6;
349
350         Data = pci_read_config8(MEMCTRL, 0x61);
351         Data = (u8) ((Data & 0x3f) | (u8) Tmp);
352         pci_write_config8(MEMCTRL, 0x61, Data);
353 }
354
355 /*
356 Write recovery time: Twr for DDR1/DDR2
357 Device 0 Function 3:REG63[7:5]:Twr 00->2T 01->3T 10->4T 11->5T
358 */
359 #define MAX_TWR 6
360 #define MIN_TWR 2
361
362 void SetTwr(DRAM_SYS_ATTR * DramAttr)
363 {
364         u8 Data;
365         u16 Max, Tmp;
366         u8 Socket;
367
368         /*get the max Trtp value from SPD data
369            SPD Byte36, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
370         Max = 0;
371         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
372                 if (DramAttr->DimmInfo[Socket].bPresence) {
373                         Tmp =
374                             (u16) (DramAttr->
375                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TWR]);
376                         if (Tmp > Max)
377                                 Max = Tmp;
378                 }
379         }
380         /*Calculate clock */
381         Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2));        //this value should be 2T,3T,4T,5T
382         PRINT_DEBUG_MEM("Twr = ");
383         PRINT_DEBUG_MEM_HEX16(Tmp);
384         PRINT_DEBUG_MEM("\r");
385
386         if (Tmp > MAX_TWR)
387                 Tmp = MAX_TWR;
388         else if (Tmp < MIN_TWR)
389                 Tmp = MIN_TWR;
390         Tmp -= 2;               //00->2T, 01->3T, 10->4T, 11->5T
391         Tmp <<= 5;
392
393         Data = pci_read_config8(MEMCTRL, 0x63);
394         Data = (u8) ((Data & 0x1f) | (u8) Tmp);
395         pci_write_config8(MEMCTRL, 0x63, Data);
396 }
397
398 /*
399 Internal write to read command delay: Twtr for DDR1/DDR2
400 Device 0 Function 3:REG63[1,0]:Twtr   DDR: 1T or 2T; DDR2 2T or 3T
401 */
402 #define MAX_TWTR 5              //5T
403 #define MIN_TWTR 2              //2T
404
405 void SetTwtr(DRAM_SYS_ATTR * DramAttr)
406 {
407         u8 Data;
408         u16 Max, Tmp;
409         u8 Socket;
410
411         /*get the max Trtp value from SPD data
412            SPD Byte37, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
413         Max = 0;
414         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
415                 if (DramAttr->DimmInfo[Socket].bPresence) {
416                         Tmp =
417                             (u16) (DramAttr->
418                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TWTR]);
419                         if (Tmp > Max)
420                                 Max = Tmp;
421                 }
422         }
423         /*Calculate clock */
424         Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2));        //this value should be 2T or 3T
425
426         PRINT_DEBUG_MEM("Twtr =");
427         PRINT_DEBUG_MEM_HEX16(Tmp);
428         PRINT_DEBUG_MEM("\r");
429
430         if (Tmp > MAX_TWR)
431                 Tmp = MAX_TWTR;
432         else if (Tmp < MIN_TWR)
433                 Tmp = MIN_TWTR;
434         Tmp -= 2;               //00->2T, 01->3T, 10->4T, 11->5T
435         Data = pci_read_config8(MEMCTRL, 0x63);
436         Data = (u8) ((Data & 0xFC) | Tmp);
437         pci_write_config8(MEMCTRL, 0x63, Data);
438 }
439
440 /*
441 Internal read to precharge command delay, Trtp for DDR1/DDR2
442 Device 0 Function 3:REG63[3]:Trtp  2T or 3T
443 */
444 #define MAX_TRTP 3              //3T
445 #define MIN_TRTP 2              //2T
446
447 void SetTrtp(DRAM_SYS_ATTR * DramAttr)
448 {
449         u8 Data;
450         u16 Max, Tmp;
451         u8 Socket;
452
453         /*get the max Trtp value from SPD data
454            SPD Byte38, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
455         Max = 0;
456         for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
457                 if (DramAttr->DimmInfo[Socket].bPresence) {
458                         Tmp =
459                             (u16) (DramAttr->
460                                    DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRTP]);
461                         if (Tmp > Max)
462                                 Max = Tmp;
463                 }
464         }
465         /*Calculate clock */
466         Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2));        //this value should be 2T or 3T
467
468         PRINT_DEBUG_MEM("Trtp =");
469         PRINT_DEBUG_MEM_HEX16(Tmp);
470         PRINT_DEBUG_MEM("\r");
471
472         Data = pci_read_config8(MEMCTRL, 0x63);
473         if (Tmp > MIN_TRTP)
474                 Data = (u8) (Data | 0x08);      /*set bit3, set 3T */
475         else
476                 Data = (u8) (Data & 0xf7);      /*clear bit3, set 2T */
477
478         pci_write_config8(MEMCTRL, 0x63, Data);
479 }