aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c
diff options
context:
space:
mode:
authorZheng Bao <zheng.bao@amd.com>2010-04-23 17:32:48 +0000
committerStefan Reinauer <stepan@openbios.org>2010-04-23 17:32:48 +0000
commiteb75f652d392d2f4f257194e112f3f0db7479145 (patch)
treeaa972907734abcba4ca52f2a3a71f8d81d4bdce0 /src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c
parentfe6c2cda6e6977894d9b668af9509b983c850f68 (diff)
DDR3 support for AMD Fam10.
Signed-off-by: Zheng Bao <zheng.bao@amd.com> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5481 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c')
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c
new file mode 100644
index 0000000000..05b01d7d5b
--- /dev/null
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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
+ */
+
+void InterleaveChannels_D(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstatA)
+{
+
+ u8 Node;
+ u32 DramBase, DctSelBase;
+ u8 DctSelIntLvAddr, DctSelHi;
+ u8 HoleValid = 0;
+ u32 HoleSize, HoleBase = 0;
+ u32 val, tmp;
+ u32 dct0_size, dct1_size;
+ struct DCTStatStruc *pDCTstat;
+
+ /* HoleValid - indicates whether the current Node contains hole.
+ * HoleSize - indicates whether there is IO hole in the whole system
+ * memory.
+ */
+
+ /* call back to wrapper not needed ManualChannelInterleave_D(); */
+ /* call back - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv);*/ /* override interleave */
+ /* Manually set: typ=5, otherwise typ=7. */
+ DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv); /* typ=5: Hash*: exclusive OR of address bits[20:16, 6]. */
+
+ if (DctSelIntLvAddr & 1) {
+ DctSelIntLvAddr >>= 1;
+ HoleSize = 0;
+ if ((pMCTstat->GStatus & (1 << GSB_SoftHole)) ||
+ (pMCTstat->GStatus & (1 << GSB_HWHole))) {
+ if (pMCTstat->HoleBase) {
+ HoleBase = pMCTstat->HoleBase >> 8;
+ HoleSize = HoleBase & 0xFFFF0000;
+ HoleSize |= ((~HoleBase) + 1) & 0xFFFF;
+ }
+ }
+ Node = 0;
+ while (Node < MAX_NODES_SUPPORTED) {
+ pDCTstat = pDCTstatA + Node;
+ val = Get_NB32(pDCTstat->dev_map, 0xF0);
+ if (val & (1 << DramHoleValid))
+ HoleValid = 1;
+ if (!pDCTstat->GangedMode && pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1]) {
+ DramBase = pDCTstat->NodeSysBase >> 8;
+ dct1_size = ((pDCTstat->NodeSysLimit) + 2) >> 8;
+ dct0_size = Get_NB32(pDCTstat->dev_dct, 0x114);
+ if (dct0_size >= 0x10000) {
+ dct0_size -= HoleSize;
+ }
+
+ dct0_size -= DramBase;
+ dct1_size -= dct0_size;
+ DctSelHi = 0x05; /* DctSelHiRngEn = 1, DctSelHi = 0 */
+ if (dct1_size == dct0_size) {
+ dct1_size = 0;
+ DctSelHi = 0x04; /* DctSelHiRngEn = 0 */
+ } else if (dct1_size > dct0_size ) {
+ dct1_size = dct0_size;
+ DctSelHi = 0x07; /* DctSelHiRngEn = 1, DctSelHi = 1 */
+ }
+ dct0_size = dct1_size;
+ dct0_size += DramBase;
+ dct0_size += dct1_size;
+ if (dct0_size >= HoleBase) /* if DctSelBaseAddr > HoleBase */
+ dct0_size += HoleSize;
+ DctSelBase = dct0_size;
+
+ if (dct1_size == 0)
+ dct0_size = 0;
+ dct0_size -= dct1_size; /* DctSelBaseOffset = DctSelBaseAddr - Interleaved region */
+ Set_NB32(pDCTstat->dev_dct, 0x114, dct0_size);
+
+ if (dct1_size == 0)
+ dct1_size = DctSelBase;
+ val = Get_NB32(pDCTstat->dev_dct, 0x110);
+ val &= 0x7F8;
+ val |= dct1_size;
+ val |= DctSelHi;
+ val |= (DctSelIntLvAddr << 6) & 0xFF;
+ Set_NB32(pDCTstat->dev_dct, 0x110, val);
+
+ if (HoleValid) {
+ tmp = DramBase;
+ val = DctSelBase;
+ if (val < HoleBase) { /* DctSelBaseAddr < DramHoleBase */
+ val -= DramBase;
+ val >>= 1;
+ tmp += val;
+ }
+ tmp += HoleSize;
+ val = Get_NB32(pDCTstat->dev_map, 0xF0); /* DramHoleOffset */
+ val &= 0xFFFF007F;
+ val |= (tmp & ~0xFFFF007F);
+ Set_NB32(pDCTstat->dev_map, 0xF0, val);
+ }
+ }
+ printk(BIOS_DEBUG, "InterleaveChannels_D: Node %x\n", Node);
+ printk(BIOS_DEBUG, "InterleaveChannels_D: Status %x\n", pDCTstat->Status);
+ printk(BIOS_DEBUG, "InterleaveChannels_D: ErrStatus %x\n", pDCTstat->ErrStatus);
+ printk(BIOS_DEBUG, "InterleaveChannels_D: ErrCode %x\n", pDCTstat->ErrCode);
+ Node++;
+ }
+ }
+ printk(BIOS_DEBUG, "InterleaveChannels_D: Done\n\n");
+}