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
20 void DutyCycleCtrl(DRAM_SYS_ATTR *DramAttr)
24 if (DIMMFREQ_800 == DramAttr->DramFreq)
26 else if (DIMMFREQ_667 == DramAttr->DramFreq)
28 else if (DIMMFREQ_533 == DramAttr->DramFreq)
30 else if (DIMMFREQ_400 == DramAttr->DramFreq)
35 if (DramAttr->RankNumChA > 0) { /* 1 rank */
36 for (i = 0; i < DUTY_CYCLE_REG_NUM; i++) {
37 Data = pci_read_config8(MEMCTRL,
38 ChA_Duty_Control_DDR2[i][0]);
39 Data &= ChA_Duty_Control_DDR2[i][1]; /* mask */
40 Data |= ChA_Duty_Control_DDR2[i][FreqId]; /* set val */
41 pci_write_config8(MEMCTRL,
42 ChA_Duty_Control_DDR2[i][0], Data);
46 if (1 == ENABLE_CHC) { /* 1 rank */
47 for (i = 0; i < DUTY_CYCLE_REG_NUM; i++) {
48 Data = pci_read_config8(MEMCTRL,
49 ChB_Duty_Control_DDR2[i][0]);
50 Data &= ChB_Duty_Control_DDR2[i][1]; /* mask */
51 Data |= ChB_Duty_Control_DDR2[i][FreqId]; /* set val */
52 pci_write_config8(MEMCTRL,
53 ChB_Duty_Control_DDR2[i][0], Data);
59 * DRAM clock phase and delay control
63 void ClkPhsCtrlFBMDDR2(DRAM_SYS_ATTR *DramAttr);
64 void WrtDataPhsCtrl(DRAM_SYS_ATTR *DramAttr);
65 void DQDQSOutputDlyCtrl(DRAM_SYS_ATTR *DramAttr);
66 void DQSInputCaptureCtrl(DRAM_SYS_ATTR *DramAttr);
67 void DCLKPhsCtrl(DRAM_SYS_ATTR *DramAttr);
69 void DRAMClkCtrl(DRAM_SYS_ATTR *DramAttr)
71 /* Write data clock phase control. */
72 WrtDataPhsCtrl(DramAttr);
73 /* Clock phase control */
74 ClkPhsCtrlFBMDDR2(DramAttr);
75 /**/ DQDQSOutputDlyCtrl(DramAttr);
76 /**/ DQSInputCaptureCtrl(DramAttr);
77 DCLKPhsCtrl(DramAttr);
80 void ClkPhsCtrlFBMDDR2(DRAM_SYS_ATTR *DramAttr)
84 if (DramAttr->DramFreq == DIMMFREQ_800)
86 else if (DramAttr->DramFreq == DIMMFREQ_667)
88 else if (DramAttr->DramFreq == DIMMFREQ_533)
90 else if (DramAttr->DramFreq == DIMMFREQ_400)
97 if (DramAttr->RankNumChA == 1) { /* 1 rank */
98 for (i = 0; i < 3; i++) {
99 Data = pci_read_config8(MEMCTRL,
100 DDR2_ChA_Clk_Phase_Table_1R[i][0]);
101 Data &= DDR2_ChA_Clk_Phase_Table_1R[i][1]; /* mask */
102 Data |= DDR2_ChA_Clk_Phase_Table_1R[i][FreqId]; /* set val */
103 pci_write_config8(MEMCTRL,
104 DDR2_ChA_Clk_Phase_Table_1R[i][0], Data);
106 } else if (DramAttr->RankNumChA > 1) { /* 2~4 Rank */
107 for (i = 0; i < 3; i++) {
108 Data = pci_read_config8(MEMCTRL,
109 DDR2_ChA_Clk_Phase_Table_2R[i][0]);
110 Data &= DDR2_ChA_Clk_Phase_Table_2R[i][1]; /* mask */
111 Data |= DDR2_ChA_Clk_Phase_Table_2R[i][FreqId]; /* set val */
112 pci_write_config8(MEMCTRL,
113 DDR2_ChA_Clk_Phase_Table_2R[i][0], Data);
117 if (DramAttr->RankNumChB > 0) { /* 1 rank */
118 for (i = 0; i < 3; i++) {
119 Data = pci_read_config8(MEMCTRL,
120 DDR2_ChB_Clk_Phase_Table_1R[i][0]);
121 Data &= DDR2_ChB_Clk_Phase_Table_1R[i][1]; /* mask */
122 Data |= DDR2_ChB_Clk_Phase_Table_1R[i][FreqId]; /* set val */
123 pci_write_config8(MEMCTRL,
124 DDR2_ChB_Clk_Phase_Table_1R[i][0], Data);
130 void WrtDataPhsCtrl(DRAM_SYS_ATTR *DramAttr)
134 if (DIMMFREQ_800 == DramAttr->DramFreq)
136 else if (DIMMFREQ_667 == DramAttr->DramFreq)
138 else if (DIMMFREQ_533 == DramAttr->DramFreq)
140 else if (DIMMFREQ_400 == DramAttr->DramFreq)
145 if (DramAttr->RankNumChA > 0) { /* 1 rank */
146 for (i = 0; i < WrtData_REG_NUM; i++) {
147 Data = pci_read_config8(MEMCTRL,
148 DDR2_ChA_WrtData_Phase_Table[i][0]);
149 Data &= DDR2_ChA_WrtData_Phase_Table[i][1]; /* mask */
150 Data |= DDR2_ChA_WrtData_Phase_Table[i][FreqId]; /* set val */
151 pci_write_config8(MEMCTRL,
152 DDR2_ChA_WrtData_Phase_Table[i][0], Data);
156 if (DramAttr->RankNumChB > 0) { /* 1 rank */
157 for (i = 0; i < WrtData_REG_NUM; i++) {
158 Data = pci_read_config8(MEMCTRL,
159 DDR2_ChB_WrtData_Phase_Table[i][0]);
160 Data &= DDR2_ChB_WrtData_Phase_Table[i][1]; /* mask */
161 Data |= DDR2_ChB_WrtData_Phase_Table[i][FreqId]; /* set val */
162 pci_write_config8(MEMCTRL,
163 DDR2_ChB_WrtData_Phase_Table[i][0], Data);
167 Data = pci_read_config8(MEMCTRL, 0x8C);
170 pci_write_config8(MEMCTRL, 0x8C, Data);
173 void DQDQSOutputDlyCtrl(DRAM_SYS_ATTR *DramAttr)
177 if (DIMMFREQ_400 == DramAttr->DramFreq)
179 else if (DIMMFREQ_533 == DramAttr->DramFreq)
181 else if (DIMMFREQ_667 == DramAttr->DramFreq)
183 else if (DIMMFREQ_800 == DramAttr->DramFreq)
188 if (DramAttr->RankNumChA > 0) {
189 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][0];
190 pci_write_config8(MEMCTRL, 0xf0, Data);
192 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][1];
193 pci_write_config8(MEMCTRL, 0xf1, Data);
195 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][2];
196 pci_write_config8(MEMCTRL, 0xf2, Data);
198 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][3];
199 pci_write_config8(MEMCTRL, 0xf3, Data);
202 if (DramAttr->RankNumChB > 0) {
203 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][0];
204 pci_write_config8(MEMCTRL, 0xf4, Data);
206 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][1];
207 pci_write_config8(MEMCTRL, 0xf5, Data);
209 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][2];
210 pci_write_config8(MEMCTRL, 0xf6, Data);
212 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][3];
213 pci_write_config8(MEMCTRL, 0xf7, Data);
218 void DQSInputCaptureCtrl(DRAM_SYS_ATTR *DramAttr)
222 if (DIMMFREQ_800 == DramAttr->DramFreq)
224 else if (DIMMFREQ_667 == DramAttr->DramFreq)
226 else if (DIMMFREQ_533 == DramAttr->DramFreq)
228 else if (DIMMFREQ_400 == DramAttr->DramFreq)
234 pci_write_config8(MEMCTRL, 0x77, Data);
236 if (DramAttr->RankNumChA > 0) { /* 1 rank */
237 for (i = 0; i < DQS_INPUT_CAPTURE_REG_NUM; i++) {
238 Data = pci_read_config8(MEMCTRL,
239 DDR2_ChA_DQS_Input_Capture_Tbl[i][0]);
240 Data &= DDR2_ChA_DQS_Input_Capture_Tbl[i][1]; /* mask */
241 Data |= DDR2_ChA_DQS_Input_Capture_Tbl[i][FreqId]; /* set val */
242 pci_write_config8(MEMCTRL,
243 DDR2_ChA_DQS_Input_Capture_Tbl[i][0], Data);
247 if (DramAttr->RankNumChB > 0) { /* 1 rank */
248 for (i = 0; i < DQS_INPUT_CAPTURE_REG_NUM; i++) {
249 Data = pci_read_config8(MEMCTRL,
250 DDR2_ChB_DQS_Input_Capture_Tbl[i][0]);
251 Data &= DDR2_ChB_DQS_Input_Capture_Tbl[i][1]; /* mask */
252 Data |= DDR2_ChB_DQS_Input_Capture_Tbl[i][FreqId]; /* set val */
253 pci_write_config8(MEMCTRL,
254 DDR2_ChB_DQS_Input_Capture_Tbl[i][0], Data);
261 * This is very important, if you don't set it correctly, DRAM will be
264 * Set DCLK Phase control(Reg99H[6:1]) according the DDRII in the DIMM.
266 void DCLKPhsCtrl(DRAM_SYS_ATTR *DramAttr)
270 Data = 0; /* TODO: Can be dropped? */
271 Data = pci_read_config8(MEMCTRL, 0x99);
273 /* DDR in Dimm1, MCLKOA[4,3,0] will output MCLK */
274 if (DramAttr->RankPresentMap & 0x03)
276 /* DDR in Dimm2, MCLKOA[5,2,1] will output MCLK */
277 if (DramAttr->RankPresentMap & 0x0C)
280 pci_write_config8(MEMCTRL, 0x99, Data);