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 /* FIXME this should go away */
21 static const struct mem_controller ctrl = {
22 .channel0 = {DIMM0, DIMM1},
26 CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 *Buf);
27 void DRAMCmdRate(DRAM_SYS_ATTR *DramAttr);
28 CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR *DramAttr);
30 CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 *Buf)
32 // CB_STATUS Status = CB_NOT_READY;
35 if (1 > Length || NULL == Buf)
36 return CB_INVALID_PARAMETER;
38 for (i = 0; i < Length; i++) {
39 Val = get_spd_data(ctrl.channel0[Slot], i);
45 CB_STATUS DRAMDetect(DRAM_SYS_ATTR *DramAttr)
47 CB_STATUS Status = CB_SUCCESS;
49 PRINT_DEBUG_MEM("DRAM detection \r");
51 /* Read D0F3Rx6C, detect memory type DDR1 or DDR2. */
52 /* 353 supports DDR2 only */
53 DramAttr->DramType = RAMTYPE_SDRAMDDR2;
54 /* Get information for SPD. */
55 Status = GetInfoFromSPD(DramAttr);
56 if (CB_SUCCESS == Status) {
59 // if (RAMTYPE_SDRAMDDR == DramAttr->DramType)
61 /* Select command rate. */
62 DRAMCmdRate(DramAttr);
68 * Determine 1T or 2T command rate.
70 * To enable 1T command rate, the system will satisfy the following
73 * 1. Each DRAM channel may have 1 or 2 ranks of DIMM. 3/4 ranks can not
74 * support 1T command rate. It's for loading issue. 1T can supports
75 * (a) only one socket with two ranks, OR
76 * (b) two sockets each with 1 rank.
77 * 2. User wishes to enable 1T command rate mode and turn on by setup menu.
78 * 3. If 1T command rate can be enabled, just set EBP bit here.
80 void DRAMCmdRate(DRAM_SYS_ATTR *DramAttr)
84 // 5.1t/2t command rate, use the stable set
86 DramAttr->CmdRate = 2;
87 Data = pci_read_config8(MEMCTRL, 0x50);
88 Data = (u8) (Data & 0xEE);
89 pci_write_config8(MEMCTRL, 0x50, Data);
93 * Get SPD data and set RANK presence map.
95 * Sockets0,1 is Channel A / Sockets2,3 is Channel B.
97 * Socket0 SPD device address 0x50 / socket1 SPD device address 0x51
98 * Socket2 SPD device address 0x52 / socket3 SPD device address 0x53
100 CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR *DramAttr)
104 u8 ModuleDataWidth, ChipWidth, RankNum, LoadNum, Sockets, i;
105 BOOLEAN bFind; /* FIXME: We don't have/want BOOLEAN. */
107 bFind = FALSE; /* FIXME: We don't have/want FALSE. */
108 Status = CB_DEVICE_ERROR;
110 for (Sockets = 0; Sockets < MAX_SOCKETS; Sockets++) {
111 pSPDDataBuf = DramAttr->DimmInfo[Sockets].SPDDataBuf;
112 pSPDDataBuf[SPD_MEMORY_TYPE] =
113 get_spd_data(ctrl.channel0[Sockets], SPD_MEMORY_TYPE);
114 if (pSPDDataBuf[SPD_MEMORY_TYPE] == 0) {
115 Status = CB_NOT_READY;
118 GetSPDData(Sockets, SPD_DATA_SIZE, pSPDDataBuf);
119 PRINT_DEBUG_MEM("SPD : \r");
120 for (i = 0; i < SPD_DATA_SIZE; i++) {
121 PRINT_DEBUG_MEM(" ");
122 PRINT_DEBUG_MEM_HEX8(pSPDDataBuf[i]);
125 if (CB_SUCCESS == Status) {
127 * If DRAM controller detected type not same as the
128 * type got from SPD, there are ERROR.
130 if (pSPDDataBuf[SPD_MEMORY_TYPE] != DramAttr->DramType) {
131 Status = CB_DEVICE_ERROR; /* memory int error */
132 PRINT_DEBUG_MEM("Memory Device ERROR: DRAM "
133 "controller detected type != "
134 "type got from SPD\r");
137 DramAttr->DimmInfo[Sockets].bPresence = TRUE;
139 /* Calculate load number (chips number). */
140 ModuleDataWidth = (u8) (DramAttr->
141 DimmInfo[Sockets].SPDDataBuf
142 [SPD_SDRAM_MOD_DATA_WIDTH + 1]);
143 ModuleDataWidth = (u8) (ModuleDataWidth << 8);
144 ModuleDataWidth |= (u8) (DramAttr->
145 DimmInfo[Sockets].SPDDataBuf
146 [SPD_SDRAM_MOD_DATA_WIDTH]);
147 ChipWidth = (u8) ((DramAttr->
148 DimmInfo[Sockets].SPDDataBuf
149 [SPD_SDRAM_WIDTH]) & 0x7F);
150 LoadNum = (u8) (ModuleDataWidth / ChipWidth);
152 /* Set the RANK map. */
153 /* Get bit0,1, the most number of supported RANK is 2. */
154 RankNum = (u8) (pSPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x3);
155 if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType)
157 * For DDR bit[0,1]: 01->1 RANK, 10->2 RANK
158 * For DDR2 bit[0,1]: 00->1 RANK, 01->2 RANK
162 /* Every DIMM have 1 or 2 ranks. */
163 if (RankNum != 2 && RankNum != 1) {
164 Status = CB_DEVICE_ERROR;
165 PRINT_DEBUG_MEM("Memory Device ERROR: Number "
166 "of RANK not supported!\r");
170 if (Sockets < 2) { /* Sockets0,1 is channel A */
171 DramAttr->RankNumChA =
172 (u8) (DramAttr->RankNumChA + RankNum);
173 DramAttr->DimmNumChA++;
174 DramAttr->LoadNumChA =
175 (u8) (DramAttr->LoadNumChA * LoadNum *
177 } else { /* Sockets2,3 is channel B */
178 DramAttr->RankNumChB =
179 (u8) (DramAttr->RankNumChB + RankNum);
180 DramAttr->DimmNumChB++;
181 DramAttr->LoadNumChB =
182 (u8) (DramAttr->LoadNumChB * LoadNum *
185 RankNum |= 1; /* Set rank map. */
186 DramAttr->RankPresentMap |= (RankNum << (Sockets * 2));
191 PRINT_DEBUG_MEM("Rank Present Map:");
192 PRINT_DEBUG_MEM_HEX8(DramAttr->RankPresentMap);
193 PRINT_DEBUG_MEM("\r");