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 extern void DRAMSetVRNum(DRAM_SYS_ATTR * DramAttr,
21 u8 PhyRank, u8 VirRank, BOOLEAN Enable);
23 extern void SetEndingAddr(DRAM_SYS_ATTR * DramAttr, u8 VirRank, // Ending address register number indicator (INDEX
24 INT8 Value); // (value) add or subtract value to this and after banks
27 void DRAMClearEndingAddress(DRAM_SYS_ATTR * DramAttr);
29 void DRAMSizingEachRank(DRAM_SYS_ATTR * DramAttr);
31 BOOLEAN DoDynamicSizing1XM(DRAM_SYS_ATTR * DramAttr,
32 u8 * nRA, u8 * nCA, u8 * nBS, u8 PhyRank);
34 void DRAMSetRankMAType(DRAM_SYS_ATTR * DramAttr);
36 void DRAMSetEndingAddress(DRAM_SYS_ATTR * DramAttr);
38 void DRAMPRToVRMapping(DRAM_SYS_ATTR * DramAttr);
40 /*===================================================================
41 Function : DRAMBankInterleave()
44 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
46 Purpose : STEP 13 Set Bank Interleave VIANB3DRAMREG69[7:6] 00:No Interleave 01:2 Bank 10:4 Bank 11:8 Bank
47 Scan all DIMMs on board to find out the lowest Bank Interleave among these DIMMs and set register.
48 ===================================================================*/
49 void DRAMBankInterleave(DRAM_SYS_ATTR * DramAttr)
52 DIMM_INFO *CurrentDimminfo;
53 u8 Bank = 3, Shift, RankNO, Count;
55 for (RankNO = 0; RankNO < 4; RankNO += 2) //all_even 0 RankNO 4 6
57 if ((DramAttr->RankPresentMap & Shift) != 0) {
58 CurrentDimminfo = &(DramAttr->DimmInfo[RankNO >> 1]); //this Rank in a dimm
60 (u8) (CurrentDimminfo->
61 SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]);
64 else if (SpdBAData == 8)
74 Data = pci_read_config8(MEMCTRL, 0x69);
77 pci_write_config8(MEMCTRL, 0x69, Data);
80 if (DramAttr->DimmNumChB > 0) {
81 CurrentDimminfo = &(DramAttr->DimmInfo[3]); //this Rank in a dimm
83 (u8) (CurrentDimminfo->
84 SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]);
87 else if (SpdBAData == 2)
91 pci_write_config8(MEMCTRL, 0x87, Bank);
95 /*===================================================================
96 Function : DRAMSizingMATypeM()
99 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
101 Purpose : STEP 14 1 DRAM Sizing 2 Fill MA type 3 Prank to vrankMapping
102 ===================================================================*/
103 void DRAMSizingMATypeM(DRAM_SYS_ATTR * DramAttr)
105 DRAMClearEndingAddress(DramAttr);
106 DRAMSizingEachRank(DramAttr);
107 //DRAMReInitDIMMBL (DramAttr);
108 DRAMSetRankMAType(DramAttr);
109 DRAMSetEndingAddress(DramAttr);
110 DRAMPRToVRMapping(DramAttr);
113 /*===================================================================
114 Function : DRAMClearEndingAddress()
117 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
119 Purpose : clear Ending and Start adress from 0x40-4f to zero
120 ===================================================================*/
121 void DRAMClearEndingAddress(DRAM_SYS_ATTR * DramAttr)
125 for (Reg = 0x40; Reg <= 0x4f; Reg++) {
126 pci_write_config8(MEMCTRL, Reg, Data);
130 /*===================================================================
131 Function : DRAMSizingEachRank()
134 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
136 Purpose : Sizing each Rank invidually, by number of rows column banks pins, be care about 128bit
137 ===================================================================*/
138 void DRAMSizingEachRank(DRAM_SYS_ATTR * DramAttr)
140 u8 Slot, RankIndex, Rows, Columns, Banks;
142 BOOLEAN HasThreeBitBA;
146 HasThreeBitBA = FALSE;
147 for (Slot = 0; Slot < 2; Slot++) {
148 if (!DramAttr->DimmInfo[Slot].bPresence)
151 DramAttr->DimmInfo[Slot].
152 SPDDataBuf[SPD_SDRAM_ROW_ADDR];
154 DramAttr->DimmInfo[Slot].
155 SPDDataBuf[SPD_SDRAM_COL_ADDR];
156 Banks = DramAttr->DimmInfo[Slot].SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]; //this is Bank number not Bank address bit
163 Size = (u32) (1 << (Rows + Columns + Banks + 3));
164 RankIndex = 2 * Slot;
165 DramAttr->RankSize[RankIndex] = Size;
166 //if this module have two ranks
167 if ((DramAttr->DimmInfo[Slot].
168 SPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x07) == 0x01) {
170 DramAttr->RankSize[RankIndex] = Size;
173 PRINT_DEBUG_MEM("rows: ");
174 PRINT_DEBUG_MEM_HEX8(Rows);
175 PRINT_DEBUG_MEM(", columns:");
176 PRINT_DEBUG_MEM_HEX8(Columns);
177 PRINT_DEBUG_MEM(", banks:");
178 PRINT_DEBUG_MEM_HEX8(Banks);
179 PRINT_DEBUG_MEM("\r");
182 HasThreeBitBA = TRUE;
185 //must set BA2 enable if any 8-bank device exists
187 Data = pci_read_config8(MEMCTRL, 0x53);
189 pci_write_config8(MEMCTRL, 0x53, Data);
192 for (RankIndex = 0; DramAttr->RankSize[RankIndex] != 0;
194 PRINT_DEBUG_MEM("Rank:");
195 PRINT_DEBUG_MEM_HEX8(RankIndex);
196 PRINT_DEBUG_MEM(", Size:");
197 PRINT_DEBUG_MEM_HEX32(DramAttr->RankSize[RankIndex] >> 20);
198 PRINT_DEBUG_MEM("\r");
203 /*===================================================================
204 Function : DRAMSetRankMAType()
207 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
209 Purpose : set the matype Reg by MAMapTypeTbl, which the rule can be found in memoryinit
210 ===================================================================*/
211 void DRAMSetRankMAType(DRAM_SYS_ATTR * DramAttr)
213 u8 SlotNum, Data, j, Reg, or, and;
214 u8 ShiftBits[] = { 5, 1, 5, 1 }; /* Rank 0/1 MA Map Type is 7:5, Rank 2/3 MA Map Type is 3:1. See Fun3Rx50. */
215 u8 MAMapTypeTbl[] = { /* Table 12 of P4M800 Pro DataSheet. */
216 2, 9, 0, /* Bank Address Bits, Column Address Bits, Rank MA Map Type */
225 Data = pci_read_config8(MEMCTRL, 0x50);
227 pci_write_config8(MEMCTRL, 0x50, Data);
228 // disable MA32/16 MA33/17 swap in memory init it has this Reg fill
229 Data = pci_read_config8(MEMCTRL, 0x6b);
231 pci_write_config8(MEMCTRL, 0x6b, Data);
234 for (SlotNum = 0; SlotNum < MAX_DIMMS; SlotNum++) {
235 if (DramAttr->DimmInfo[SlotNum].bPresence) {
236 for (j = 0; MAMapTypeTbl[j] != 0; j += 3) {
237 if ((1 << MAMapTypeTbl[j]) ==
238 DramAttr->DimmInfo[SlotNum].
239 SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]
240 && MAMapTypeTbl[j + 1] ==
241 DramAttr->DimmInfo[SlotNum].
242 SPDDataBuf[SPD_SDRAM_COL_ADDR]) {
246 if (0 == MAMapTypeTbl[j]) {
248 ("UNSUPPORTED Bank, Row and Column Addr Bits!\r");
251 or = MAMapTypeTbl[j + 2] << ShiftBits[SlotNum];
252 if (DramAttr->CmdRate == 1)
253 or |= 0x01 << (ShiftBits[SlotNum] - 1);
256 if ((SlotNum & 0x01) == 0x01) {
257 and = 0xf1; // BUGBUG: it should be 0xf0
259 and = 0x1f; // BUGBUG: it should be 0x0f
261 Data = pci_read_config8(MEMCTRL, 0x50 + Reg);
264 pci_write_config8(MEMCTRL, 0x50 + Reg, Data);
267 //may have some Reg filling at add 3-52 11 and 3-53 in his function
270 /*===================================================================
271 Function : DRAMSetEndingAddress()
274 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
276 Purpose : realize the Vrank 40...Reg (Start and Ending Regs). Vrank have same order with phy Rank, Size is actual Size
277 ===================================================================*/
278 void DRAMSetEndingAddress(DRAM_SYS_ATTR * DramAttr)
280 u8 Shift = 1, Data, RankNO, Size, Start = 0, End = 0, Vrank;
281 for (RankNO = 0; RankNO < 4; RankNO++) {
282 if ((DramAttr->RankPresentMap & Shift) != 0) {
283 Size = (u8) (DramAttr->RankSize[RankNO] >> 26); // current Size in the unit of 64M
286 End = End + Size; // calculate current ending address, add the current Size to ending
287 Vrank = RankNO; // get virtual Rank
288 Data = End; // set begin/End address register to correspondig virtual Rank #
289 pci_write_config8(MEMCTRL, 0x40 + Vrank,
292 pci_write_config8(MEMCTRL, 0x48 + Vrank,
294 PRINT_DEBUG_MEM("Rank: ");
295 PRINT_DEBUG_MEM_HEX8(Vrank);
296 PRINT_DEBUG_MEM(", Start:");
297 PRINT_DEBUG_MEM_HEX8(Start);
298 PRINT_DEBUG_MEM(", End:");
299 PRINT_DEBUG_MEM_HEX8(End);
300 PRINT_DEBUG_MEM("\r");
308 if (DramAttr->RankNumChB > 0) {
309 //this is a bug,fixed is to 2,so the max LL size is 128M
311 pci_write_config8(MEMCTRL, 0x44, Data);
314 pci_write_config8(PCI_DEV(0, 17, 7), 0x60, Data);
315 // We should directly write to south Bridge, not in north bridge
316 // program LOW TOP Address
317 Data = pci_read_config8(MEMCTRL, 0x88);
318 pci_write_config8(MEMCTRL, 0x85, Data);
320 // also program vlink mirror
321 // We should directly write to south Bridge, not in north bridge
322 pci_write_config8(PCI_DEV(0, 17, 7), 0xe5, Data);
325 /*===================================================================
326 Function : DRAMPRToVRMapping()
329 DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
331 Purpose : set the Vrank-prank map with the same order
332 ===================================================================*/
333 void DRAMPRToVRMapping(DRAM_SYS_ATTR * DramAttr)
335 u8 Shift, Data, and, or, DimmNO = 0, PhyRankNO, Reg;
337 for (Reg = 0x54; Reg <= 0x57; Reg++) //clear the map-reg
340 pci_write_config8(MEMCTRL, Reg, Data);
344 for (PhyRankNO = 0; PhyRankNO < MAX_RANKS; PhyRankNO++) {
345 if ((DramAttr->RankPresentMap & Shift) != 0) {
346 or = PhyRankNO; // get virtual Rank ,same with PhyRank
349 if ((PhyRankNO & 0x01) == 0x01) // get mask for register
355 DimmNO = (PhyRankNO >> 1);
356 Data = pci_read_config8(MEMCTRL, 0x54 + DimmNO);
359 pci_write_config8(MEMCTRL, 0x54 + DimmNO, Data);