diff options
author | Uwe Hermann <uwe@hermann-uwe.de> | 2009-05-27 17:06:54 +0000 |
---|---|---|
committer | Uwe Hermann <uwe@hermann-uwe.de> | 2009-05-27 17:06:54 +0000 |
commit | 5c044c732fc28b09eb58956a85b141af194f2b94 (patch) | |
tree | fde799f7c44df7b06e0ad0f98b06fb54571c265a /src/northbridge/via/vx800/detection.c | |
parent | f2a4e63f926a59759309d93e1af60e3c3f7d5c13 (diff) |
Make directory hierarchy flat to match the same layout we use
for other chipsets, as suggested on IRC.
Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4317 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/via/vx800/detection.c')
-rw-r--r-- | src/northbridge/via/vx800/detection.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/northbridge/via/vx800/detection.c b/src/northbridge/via/vx800/detection.c new file mode 100644 index 0000000000..63fc56b845 --- /dev/null +++ b/src/northbridge/via/vx800/detection.c @@ -0,0 +1,192 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 One Laptop per Child, Association, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define SMBUS_ADDR_CH_A_1 0xA0 // Dimmx +#define SMBUS_ADDR_CH_A_2 0xA2 // Dimmx +#define SMBUS_ADDR_CH_B_1 0xA4 // Dimmx +#define SMBUS_ADDR_CH_B_2 0xA6 // Dimmx + +/*read data*/ +CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 * Buf); + +void DRAMCmdRate(DRAM_SYS_ATTR * DramAttr); + + + +CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR * DramAttr); + +CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 * Buf) +{ + // CB_STATUS Status = CB_NOT_READY; + u8 Val; + u8 i; + + if (1 > Length || NULL == Buf) + return CB_INVALID_PARAMETER; + + for (i = 0; i < Length; i++) { + Val = get_spd_data(ctrl.channel0[Slot], i); + *(Buf + i) = Val; + } + return CB_SUCCESS; +} + +CB_STATUS DRAMDetect(DRAM_SYS_ATTR * DramAttr) +{ + CB_STATUS Status = CB_SUCCESS; + + PRINT_DEBUG_MEM("Dram Detection \r"); + + /*Read D0F3Rx6C , detect memory type DDR1 or DDR2 */ + // 353 supports DDR2 only + DramAttr->DramType = RAMTYPE_SDRAMDDR2; + /*get information for SPD */ + Status = GetInfoFromSPD(DramAttr); + if (CB_SUCCESS == Status) { + /*64bit or 128Bit */ + // + // if (RAMTYPE_SDRAMDDR == DramAttr->DramType) + + /*select command rate */ + DRAMCmdRate(DramAttr); + } + return Status; +} + + +// Determine 1T or 2T Command Rate: +// To enable 1T command Rate, the system will satisfy the following 3 conditions: +// 1. Each DRAM channel may have 1 or 2 ranks of DIMM. 3/4 ranks can not support 1T command rate +// It's for loading issue. 1T can supports (a). only one socket with two ranks OR +// (b). two sockets each with 1 rank. +// 2. User wishes to enable 1T command rate mode and turn on by Setup menu +// 3. If 1T command rate can be enabled, just set EBP bit here. +void DRAMCmdRate(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + + // 5.1t/2t command rate, use the stable set + //offset50 + DramAttr->CmdRate = 2; + Data = pci_read_config8(MEMCTRL, 0x50); + Data = (u8) (Data & 0xEE); + pci_write_config8(MEMCTRL, 0x50, Data); +} + +/*get SPD data and set RANK presence map*/ +/* +Sockets0,1 is Channel A / Sockets2,3 is Channel B +socket0 SPD device address 0x50 / socket1 SPD device address 0x51 +socket2 SPD device address 0x52 / socket3 SPD device address 0x53 +*/ +CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR * DramAttr) +{ + CB_STATUS Status; + u8 *pSPDDataBuf; + u8 ModuleDataWidth; + u8 ChipWidth; + u8 RankNum; + u8 LoadNum; + u8 Sockets, i; + BOOLEAN bFind; + bFind = FALSE; + Status = CB_DEVICE_ERROR; + + for (Sockets = 0; Sockets < MAX_SOCKETS; Sockets++) { + pSPDDataBuf = DramAttr->DimmInfo[Sockets].SPDDataBuf; + pSPDDataBuf[SPD_MEMORY_TYPE] = + get_spd_data(ctrl.channel0[Sockets], SPD_MEMORY_TYPE); + if (pSPDDataBuf[SPD_MEMORY_TYPE] == 0) { + Status = CB_NOT_READY; + } else { + Status = + GetSPDData(Sockets, SPD_DATA_SIZE, + pSPDDataBuf); + PRINT_DEBUG_MEM("SPD : \r"); + for (i = 0; i < SPD_DATA_SIZE; i++) { + PRINT_DEBUG_MEM(" "); + PRINT_DEBUG_MEM_HEX8(pSPDDataBuf[i]); + } + } + if (CB_SUCCESS == Status) { + /*if Dram Controller detected type not same as the type got from SPD, There are ERROR */ + if (pSPDDataBuf[SPD_MEMORY_TYPE] != + DramAttr->DramType) { + Status = CB_DEVICE_ERROR; /*Memory int error */ + PRINT_DEBUG_MEM + ("Memory Device ERROR: Dram Controller detected type != type got from SPD \r"); + break; + } + DramAttr->DimmInfo[Sockets].bPresence = TRUE; + /*calculate load number (chips number) */ + ModuleDataWidth = + (u8) (DramAttr->DimmInfo[Sockets]. + SPDDataBuf[SPD_SDRAM_MOD_DATA_WIDTH + + 1]); + ModuleDataWidth = (u8) (ModuleDataWidth << 8); + ModuleDataWidth |= + (u8) (DramAttr->DimmInfo[Sockets]. + SPDDataBuf[SPD_SDRAM_MOD_DATA_WIDTH]); + ChipWidth = + (u8) ((DramAttr->DimmInfo[Sockets]. + SPDDataBuf[SPD_SDRAM_WIDTH]) & 0x7F); + LoadNum = (u8) (ModuleDataWidth / ChipWidth); + + /*set the RANK map */ + RankNum = (u8) (pSPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x3); /*get bit0,1, the Most number of supported RANK is 2 */ + if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType) + RankNum++; /*for DDR bit[0,1] 01->1 RANK 10->2 RANK; for DDR2 bit[0,1] = 00 -> 1 RANK 01 -> 2 RANK */ + if (RankNum != 2 && RankNum != 1) { /*every DIMM have 1 or 2 ranks */ + Status = CB_DEVICE_ERROR; + PRINT_DEBUG_MEM + ("Memory Device ERROR: the number of RANK not support!\r"); + break; + } + + if (Sockets < 2) { /*sockets0,1 is channel A */ + DramAttr->RankNumChA = + (u8) (DramAttr->RankNumChA + RankNum); + DramAttr->DimmNumChA++; + DramAttr->LoadNumChA = + (u8) (DramAttr->LoadNumChA * LoadNum * + RankNum); + } else { /*sockets2,3 is channel B */ + + DramAttr->RankNumChB = + (u8) (DramAttr->RankNumChB + RankNum); + DramAttr->DimmNumChB++; + DramAttr->LoadNumChB = + (u8) (DramAttr->LoadNumChB * LoadNum * + RankNum);; + } + RankNum |= 1; /*set rank map */ + DramAttr->RankPresentMap |= + (RankNum << (Sockets * 2)); + bFind = TRUE; + } + } + PRINT_DEBUG_MEM("Rank Present Map:"); + PRINT_DEBUG_MEM_HEX8(DramAttr->RankPresentMap); + PRINT_DEBUG_MEM("\r"); + + if (bFind) + Status = CB_SUCCESS; + + return Status; +} |