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 = {0x50, 0x51},
25 #define SMBUS_ADDR_CH_A_1 0xA0 /* Dimmx */
26 #define SMBUS_ADDR_CH_A_2 0xA2 /* Dimmx */
27 #define SMBUS_ADDR_CH_B_1 0xA4 /* Dimmx */
28 #define SMBUS_ADDR_CH_B_2 0xA6 /* Dimmx */
31 CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 *Buf);
32 void DRAMCmdRate(DRAM_SYS_ATTR *DramAttr);
33 CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR *DramAttr);
35 CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 *Buf)
37 // CB_STATUS Status = CB_NOT_READY;
40 if (1 > Length || NULL == Buf)
41 return CB_INVALID_PARAMETER;
43 for (i = 0; i < Length; i++) {
44 Val = get_spd_data(ctrl.channel0[Slot], i);
50 CB_STATUS DRAMDetect(DRAM_SYS_ATTR *DramAttr)
52 CB_STATUS Status = CB_SUCCESS;
54 PRINT_DEBUG_MEM("DRAM detection \r");
56 /* Read D0F3Rx6C, detect memory type DDR1 or DDR2. */
57 /* 353 supports DDR2 only */
58 DramAttr->DramType = RAMTYPE_SDRAMDDR2;
59 /* Get information for SPD. */
60 Status = GetInfoFromSPD(DramAttr);
61 if (CB_SUCCESS == Status) {
64 // if (RAMTYPE_SDRAMDDR == DramAttr->DramType)
66 /* Select command rate. */
67 DRAMCmdRate(DramAttr);
73 * Determine 1T or 2T command rate.
75 * To enable 1T command rate, the system will satisfy the following
78 * 1. Each DRAM channel may have 1 or 2 ranks of DIMM. 3/4 ranks can not
79 * support 1T command rate. It's for loading issue. 1T can supports
80 * (a) only one socket with two ranks, OR
81 * (b) two sockets each with 1 rank.
82 * 2. User wishes to enable 1T command rate mode and turn on by setup menu.
83 * 3. If 1T command rate can be enabled, just set EBP bit here.
85 void DRAMCmdRate(DRAM_SYS_ATTR *DramAttr)
89 // 5.1t/2t command rate, use the stable set
91 DramAttr->CmdRate = 2;
92 Data = pci_read_config8(MEMCTRL, 0x50);
93 Data = (u8) (Data & 0xEE);
94 pci_write_config8(MEMCTRL, 0x50, Data);
98 * Get SPD data and set RANK presence map.
100 * Sockets0,1 is Channel A / Sockets2,3 is Channel B.
102 * Socket0 SPD device address 0x50 / socket1 SPD device address 0x51
103 * Socket2 SPD device address 0x52 / socket3 SPD device address 0x53
105 CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR *DramAttr)
109 u8 ModuleDataWidth, ChipWidth, RankNum, LoadNum, Sockets, i;
110 BOOLEAN bFind; /* FIXME: We don't have/want BOOLEAN. */
112 bFind = FALSE; /* FIXME: We don't have/want FALSE. */
113 Status = CB_DEVICE_ERROR;
115 for (Sockets = 0; Sockets < MAX_SOCKETS; Sockets++) {
116 pSPDDataBuf = DramAttr->DimmInfo[Sockets].SPDDataBuf;
117 pSPDDataBuf[SPD_MEMORY_TYPE] =
118 get_spd_data(ctrl.channel0[Sockets], SPD_MEMORY_TYPE);
119 if (pSPDDataBuf[SPD_MEMORY_TYPE] == 0) {
120 Status = CB_NOT_READY;
123 GetSPDData(Sockets, SPD_DATA_SIZE, pSPDDataBuf);
124 PRINT_DEBUG_MEM("SPD : \r");
125 for (i = 0; i < SPD_DATA_SIZE; i++) {
126 PRINT_DEBUG_MEM(" ");
127 PRINT_DEBUG_MEM_HEX8(pSPDDataBuf[i]);
130 if (CB_SUCCESS == Status) {
132 * If DRAM controller detected type not same as the
133 * type got from SPD, there are ERROR.
135 if (pSPDDataBuf[SPD_MEMORY_TYPE] != DramAttr->DramType) {
136 Status = CB_DEVICE_ERROR; /* memory int error */
137 PRINT_DEBUG_MEM("Memory Device ERROR: DRAM "
138 "controller detected type != "
139 "type got from SPD\r");
142 DramAttr->DimmInfo[Sockets].bPresence = TRUE;
144 /* Calculate load number (chips number). */
145 ModuleDataWidth = (u8) (DramAttr->
146 DimmInfo[Sockets].SPDDataBuf
147 [SPD_SDRAM_MOD_DATA_WIDTH + 1]);
148 ModuleDataWidth = (u8) (ModuleDataWidth << 8);
149 ModuleDataWidth |= (u8) (DramAttr->
150 DimmInfo[Sockets].SPDDataBuf
151 [SPD_SDRAM_MOD_DATA_WIDTH]);
152 ChipWidth = (u8) ((DramAttr->
153 DimmInfo[Sockets].SPDDataBuf
154 [SPD_SDRAM_WIDTH]) & 0x7F);
155 LoadNum = (u8) (ModuleDataWidth / ChipWidth);
157 /* Set the RANK map. */
158 /* Get bit0,1, the most number of supported RANK is 2. */
159 RankNum = (u8) (pSPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x3);
160 if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType)
162 * For DDR bit[0,1]: 01->1 RANK, 10->2 RANK
163 * For DDR2 bit[0,1]: 00->1 RANK, 01->2 RANK
167 /* Every DIMM have 1 or 2 ranks. */
168 if (RankNum != 2 && RankNum != 1) {
169 Status = CB_DEVICE_ERROR;
170 PRINT_DEBUG_MEM("Memory Device ERROR: Number "
171 "of RANK not supported!\r");
175 if (Sockets < 2) { /* Sockets0,1 is channel A */
176 DramAttr->RankNumChA =
177 (u8) (DramAttr->RankNumChA + RankNum);
178 DramAttr->DimmNumChA++;
179 DramAttr->LoadNumChA =
180 (u8) (DramAttr->LoadNumChA * LoadNum *
182 } else { /* Sockets2,3 is channel B */
183 DramAttr->RankNumChB =
184 (u8) (DramAttr->RankNumChB + RankNum);
185 DramAttr->DimmNumChB++;
186 DramAttr->LoadNumChB =
187 (u8) (DramAttr->LoadNumChB * LoadNum *
190 RankNum |= 1; /* Set rank map. */
191 DramAttr->RankPresentMap |= (RankNum << (Sockets * 2));
196 PRINT_DEBUG_MEM("Rank Present Map:");
197 PRINT_DEBUG_MEM_HEX8(DramAttr->RankPresentMap);
198 PRINT_DEBUG_MEM("\r");