aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/via/vx800/detection.c
diff options
context:
space:
mode:
authorUwe Hermann <uwe@hermann-uwe.de>2009-05-27 17:06:54 +0000
committerUwe Hermann <uwe@hermann-uwe.de>2009-05-27 17:06:54 +0000
commit5c044c732fc28b09eb58956a85b141af194f2b94 (patch)
treefde799f7c44df7b06e0ad0f98b06fb54571c265a /src/northbridge/via/vx800/detection.c
parentf2a4e63f926a59759309d93e1af60e3c3f7d5c13 (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.c192
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;
+}