remove trailing whitespace
[coreboot.git] / src / northbridge / via / vx800 / clk_ctrl.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 void DutyCycleCtrl(DRAM_SYS_ATTR *DramAttr)
21 {
22         u8 Data, FreqId, i;
23
24         if (DIMMFREQ_800 == DramAttr->DramFreq)
25                 FreqId = 2;
26         else if (DIMMFREQ_667 == DramAttr->DramFreq)
27                 FreqId = 3;
28         else if (DIMMFREQ_533 == DramAttr->DramFreq)
29                 FreqId = 4;
30         else if (DIMMFREQ_400 == DramAttr->DramFreq)
31                 FreqId = 5;
32         else
33                 FreqId = 5;
34
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);
43                 }
44         }
45
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);
54                 }
55         }
56 }
57
58 /*
59  * DRAM clock phase and delay control
60  */
61
62 /* Subroutine list */
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);
68
69 void DRAMClkCtrl(DRAM_SYS_ATTR *DramAttr)
70 {
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);
78 }
79
80 void ClkPhsCtrlFBMDDR2(DRAM_SYS_ATTR *DramAttr)
81 {
82         u8 Data, FreqId, i;
83
84         if (DramAttr->DramFreq == DIMMFREQ_800)
85                 FreqId = 2;
86         else if (DramAttr->DramFreq == DIMMFREQ_667)
87                 FreqId = 3;
88         else if (DramAttr->DramFreq == DIMMFREQ_533)
89                 FreqId = 4;
90         else if (DramAttr->DramFreq == DIMMFREQ_400)
91                 FreqId = 5;
92         else
93                 FreqId = 5;
94
95         /* Channel A */
96         // 2~4 Rank
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);
105                 }
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);
114                 }
115         }
116 #if ENABLE_CHB
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);
125                 }
126         }
127 #endif
128 }
129
130 void WrtDataPhsCtrl(DRAM_SYS_ATTR *DramAttr)
131 {
132         u8 Data, FreqId, i;
133
134         if (DIMMFREQ_800 == DramAttr->DramFreq)
135                 FreqId = 2;
136         else if (DIMMFREQ_667 == DramAttr->DramFreq)
137                 FreqId = 3;
138         else if (DIMMFREQ_533 == DramAttr->DramFreq)
139                 FreqId = 4;
140         else if (DIMMFREQ_400 == DramAttr->DramFreq)
141                 FreqId = 5;
142         else
143                 FreqId = 5;
144
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);
153                 }
154         }
155 #if ENABLE_CHB
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);
164                 }
165         }
166 #endif
167         Data = pci_read_config8(MEMCTRL, 0x8C);
168         Data &= 0xFC;
169         Data |= 0x03;
170         pci_write_config8(MEMCTRL, 0x8C, Data);
171 }
172
173 void DQDQSOutputDlyCtrl(DRAM_SYS_ATTR *DramAttr)
174 {
175         u8 Data, FreqId;
176
177         if (DIMMFREQ_400 == DramAttr->DramFreq)
178                 FreqId = 0;
179         else if (DIMMFREQ_533 == DramAttr->DramFreq)
180                 FreqId = 1;
181         else if (DIMMFREQ_667 == DramAttr->DramFreq)
182                 FreqId = 2;
183         else if (DIMMFREQ_800 == DramAttr->DramFreq)
184                 FreqId = 2;
185         else
186                 FreqId = 0;
187
188         if (DramAttr->RankNumChA > 0) {
189                 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][0];
190                 pci_write_config8(MEMCTRL, 0xf0, Data);
191
192                 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][1];
193                 pci_write_config8(MEMCTRL, 0xf1, Data);
194
195                 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][2];
196                 pci_write_config8(MEMCTRL, 0xf2, Data);
197
198                 Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][3];
199                 pci_write_config8(MEMCTRL, 0xf3, Data);
200         }
201 #if ENABLE_CHB
202         if (DramAttr->RankNumChB > 0) {
203                 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][0];
204                 pci_write_config8(MEMCTRL, 0xf4, Data);
205
206                 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][1];
207                 pci_write_config8(MEMCTRL, 0xf5, Data);
208
209                 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][2];
210                 pci_write_config8(MEMCTRL, 0xf6, Data);
211
212                 Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][3];
213                 pci_write_config8(MEMCTRL, 0xf7, Data);
214         }
215 #endif
216 }
217
218 void DQSInputCaptureCtrl(DRAM_SYS_ATTR *DramAttr)
219 {
220         u8 Data, FreqId, i;
221
222         if (DIMMFREQ_800 == DramAttr->DramFreq)
223                 FreqId = 2;
224         else if (DIMMFREQ_667 == DramAttr->DramFreq)
225                 FreqId = 3;
226         else if (DIMMFREQ_533 == DramAttr->DramFreq)
227                 FreqId = 4;
228         else if (DIMMFREQ_400 == DramAttr->DramFreq)
229                 FreqId = 5;
230         else
231                 FreqId = 2;
232
233         Data = 0x8A;
234         pci_write_config8(MEMCTRL, 0x77, Data);
235
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);
244                 }
245         }
246 #if ENABLE_CHB
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);
255                 }
256         }
257 #endif
258 }
259
260 /*
261  * This is very important, if you don't set it correctly, DRAM will be
262  * unreliable,
263  *
264  * Set DCLK Phase control(Reg99H[6:1]) according the DDRII in the DIMM.
265  */
266 void DCLKPhsCtrl(DRAM_SYS_ATTR *DramAttr)
267 {
268         u8 Data;
269
270         Data = 0;       /* TODO: Can be dropped? */
271         Data = pci_read_config8(MEMCTRL, 0x99);
272         Data &= 0xE1;
273         /* DDR in Dimm1, MCLKOA[4,3,0] will output MCLK */
274         if (DramAttr->RankPresentMap & 0x03)
275                 Data |= 0x09 << 1;
276         /* DDR in Dimm2, MCLKOA[5,2,1] will output MCLK */
277         if (DramAttr->RankPresentMap & 0x0C)
278                 Data |= 0x06 << 1;
279
280         pci_write_config8(MEMCTRL, 0x99, Data);
281 }