2 * This file is part of the coreboot project.
4 * Copyright (C) 2009 One Laptop per Child, Association, Inc.
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.
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.
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
21 Set Dram Timing functions
24 void SetCL(DRAM_SYS_ATTR * DramAttr);
26 void SetTrp(DRAM_SYS_ATTR * DramAttr);
28 void SetTrcd(DRAM_SYS_ATTR * DramAttr);
30 void SetTras(DRAM_SYS_ATTR * DramAttr);
32 void SetTrfc(DRAM_SYS_ATTR * DramAttr);
34 void SetTrrd(DRAM_SYS_ATTR * DramAttr);
36 void SetTwr(DRAM_SYS_ATTR * DramAttr);
38 void SetTwtr(DRAM_SYS_ATTR * DramAttr);
40 void SetTrtp(DRAM_SYS_ATTR * DramAttr);
43 void DRAMTimingSetting(DRAM_SYS_ATTR * DramAttr)
45 PRINT_DEBUG_MEM("Set CAS latency value!");
48 PRINT_DEBUG_MEM("Set tRP value!");
51 PRINT_DEBUG_MEM("Set tRCD value!");
54 PRINT_DEBUG_MEM("Set tRAS value!");
57 PRINT_DEBUG_MEM("Set tRFC value!");
60 PRINT_DEBUG_MEM("Set tRRD value!");
63 PRINT_DEBUG_MEM("Set tWR value!");
66 PRINT_DEBUG_MEM("Set tWTR value!");
69 PRINT_DEBUG_MEM("Set tRTP value!");
74 Set DRAM Timing: CAS Latency for DDR1
75 D0F3RX62 bit[0:2] for CAS Latency;
77 void SetCL(DRAM_SYS_ATTR * DramAttr)
82 /*DDR2 CL Value: 20, 30, 40, 50 -> 2, 3, 4, 5 */
83 CL = (u8) ((DramAttr->CL - 20) / 10); //000,001,010,011
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);
94 Minimum row precharge time, Trp for DDR1/DDR2
95 D0F3Rx64[3:2] for Trp 2T~5T
100 void SetTrp(DRAM_SYS_ATTR * DramAttr)
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 */
109 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
110 if (DramAttr->DimmInfo[Socket].bPresence) {
113 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRP]);
117 /*Calculate clock,this value should be 2T,3T,4T,5T */
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");
128 else if (Tmp < MIN_TRP)
131 Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
132 Tmp <<= 1; //bit1,2,3
134 Data = pci_read_config8(MEMCTRL, 0x64);
135 Data = (u8) ((Data & 0xf1) | (u8) Tmp);
136 pci_write_config8(MEMCTRL, 0x64, Data);
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);
145 Minimum RAS to CAS dely,Trcd for DDR1/DDR2
146 D0F3Rx64[7:6] for Trcd
151 void SetTrcd(DRAM_SYS_ATTR * DramAttr)
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 */
160 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
161 if (DramAttr->DimmInfo[Socket].bPresence) {
164 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRCD]);
169 /*Calculate clock,this value should be 2T,3T,4T,5T */
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");
179 else if (Tmp < MIN_TRCD)
181 Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
182 Tmp <<= 5; //bit5,6,7
184 Data = pci_read_config8(MEMCTRL, 0x64);
185 Data = (u8) ((Data & 0x1f) | (u8) Tmp);
186 pci_write_config8(MEMCTRL, 0x64, Data);
191 minimum active to precharge time,Tras for DDR1/DDR2
194 #define MAX_TRAS 20 //20T
195 #define MIN_TRAS 5 //5T
196 void SetTras(DRAM_SYS_ATTR * DramAttr)
202 /*get the max Tras value from SPD data
203 SPD byte30: bit0:7 1ns~255ns */
205 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
206 if (DramAttr->DimmInfo[Socket].bPresence) {
209 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRAS]);
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");
223 else if (Tmp < MIN_TRAS)
225 Tmp -= 5; //0->5T ... 1111->20T
228 Data = pci_read_config8(MEMCTRL, 0x62);
229 Data = (u8) ((Data & 0x0f) | (u8) Tmp);
230 pci_write_config8(MEMCTRL, 0x62, Data);
234 Minimum refresh to activate/refresh command period Trfc for DDR1/DDR2
235 D0F3Rx61[5:0] for Trfc
238 #define MAX_TRFC 71 // Max supported,71T
239 #define MIN_TRFC 8 // Min supported,8T
241 void SetTrfc(DRAM_SYS_ATTR * DramAttr)
249 /*get the max Trfc value from SPD data */
251 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
252 if (DramAttr->DimmInfo[Socket].bPresence) {
255 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRFC])
257 /*only DDR2 need to add byte 40 bit[7:4] */
260 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRFC2]);
261 /*if bit0 = 1, byte42(RFC)+256ns, SPD spec JEDEC standard No.21.c */
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 */
281 case 6: //what is FRU???
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");
297 else if (Tmp < MIN_TRFC) {
301 /*D0F3Rx61 bit[0:5] 0->8T ... 63->71T */
304 Data = pci_read_config8(MEMCTRL, 0x61);
305 Data = (u8) ((Data & 0xc0) | ((u8) Tmp & 0x3f));
306 pci_write_config8(MEMCTRL, 0x61, Data);
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
316 void SetTrrd(DRAM_SYS_ATTR * DramAttr)
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 */
325 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
326 if (DramAttr->DimmInfo[Socket].bPresence) {
329 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRRD]);
335 /*Calculate clock,this value should be 2T,3T,4T,5T */
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");
345 else if (Tmp < MIN_TRRD)
347 Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
350 Data = pci_read_config8(MEMCTRL, 0x61);
351 Data = (u8) ((Data & 0x3f) | (u8) Tmp);
352 pci_write_config8(MEMCTRL, 0x61, Data);
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
362 void SetTwr(DRAM_SYS_ATTR * DramAttr)
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 */
371 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
372 if (DramAttr->DimmInfo[Socket].bPresence) {
375 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TWR]);
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");
388 else if (Tmp < MIN_TWR)
390 Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
393 Data = pci_read_config8(MEMCTRL, 0x63);
394 Data = (u8) ((Data & 0x1f) | (u8) Tmp);
395 pci_write_config8(MEMCTRL, 0x63, Data);
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
402 #define MAX_TWTR 5 //5T
403 #define MIN_TWTR 2 //2T
405 void SetTwtr(DRAM_SYS_ATTR * DramAttr)
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 */
414 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
415 if (DramAttr->DimmInfo[Socket].bPresence) {
418 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TWTR]);
424 Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2)); //this value should be 2T or 3T
426 PRINT_DEBUG_MEM("Twtr =");
427 PRINT_DEBUG_MEM_HEX16(Tmp);
428 PRINT_DEBUG_MEM("\r");
432 else if (Tmp < MIN_TWR)
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);
441 Internal read to precharge command delay, Trtp for DDR1/DDR2
442 Device 0 Function 3:REG63[3]:Trtp 2T or 3T
444 #define MAX_TRTP 3 //3T
445 #define MIN_TRTP 2 //2T
447 void SetTrtp(DRAM_SYS_ATTR * DramAttr)
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 */
456 for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
457 if (DramAttr->DimmInfo[Socket].bPresence) {
460 DimmInfo[Socket].SPDDataBuf[SPD_SDRAM_TRTP]);
466 Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2)); //this value should be 2T or 3T
468 PRINT_DEBUG_MEM("Trtp =");
469 PRINT_DEBUG_MEM_HEX16(Tmp);
470 PRINT_DEBUG_MEM("\r");
472 Data = pci_read_config8(MEMCTRL, 0x63);
474 Data = (u8) (Data | 0x08); /*set bit3, set 3T */
476 Data = (u8) (Data & 0xf7); /*clear bit3, set 2T */
478 pci_write_config8(MEMCTRL, 0x63, Data);