2 * This file is part of the coreboot project.
4 * Copyright (C) 2010 Advanced Micro Devices, 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 void InterleaveChannels_D(struct MCTStatStruc *pMCTstat,
21 struct DCTStatStruc *pDCTstatA)
25 u32 DramBase, DctSelBase;
26 u8 DctSelIntLvAddr, DctSelHi;
28 u32 HoleSize, HoleBase = 0;
30 u32 dct0_size, dct1_size;
31 struct DCTStatStruc *pDCTstat;
33 /* HoleValid - indicates whether the current Node contains hole.
34 * HoleSize - indicates whether there is IO hole in the whole system
38 /* call back to wrapper not needed ManualChannelInterleave_D(); */
39 /* call back - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv);*/ /* override interleave */
40 /* Manually set: typ=5, otherwise typ=7. */
41 DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv); /* typ=5: Hash*: exclusive OR of address bits[20:16, 6]. */
43 if (DctSelIntLvAddr & 1) {
44 DctSelIntLvAddr >>= 1;
46 if ((pMCTstat->GStatus & (1 << GSB_SoftHole)) ||
47 (pMCTstat->GStatus & (1 << GSB_HWHole))) {
48 if (pMCTstat->HoleBase) {
49 HoleBase = pMCTstat->HoleBase >> 8;
50 HoleSize = HoleBase & 0xFFFF0000;
51 HoleSize |= ((~HoleBase) + 1) & 0xFFFF;
55 while (Node < MAX_NODES_SUPPORTED) {
56 pDCTstat = pDCTstatA + Node;
57 val = Get_NB32(pDCTstat->dev_map, 0xF0);
58 if (val & (1 << DramHoleValid))
60 if (!pDCTstat->GangedMode && pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1]) {
61 DramBase = pDCTstat->NodeSysBase >> 8;
62 dct1_size = ((pDCTstat->NodeSysLimit) + 2) >> 8;
63 dct0_size = Get_NB32(pDCTstat->dev_dct, 0x114);
64 if (dct0_size >= 0x10000) {
65 dct0_size -= HoleSize;
68 dct0_size -= DramBase;
69 dct1_size -= dct0_size;
70 DctSelHi = 0x05; /* DctSelHiRngEn = 1, DctSelHi = 0 */
71 if (dct1_size == dct0_size) {
73 DctSelHi = 0x04; /* DctSelHiRngEn = 0 */
74 } else if (dct1_size > dct0_size ) {
75 dct1_size = dct0_size;
76 DctSelHi = 0x07; /* DctSelHiRngEn = 1, DctSelHi = 1 */
78 dct0_size = dct1_size;
79 dct0_size += DramBase;
80 dct0_size += dct1_size;
81 if (dct0_size >= HoleBase) /* if DctSelBaseAddr > HoleBase */
82 dct0_size += HoleSize;
83 DctSelBase = dct0_size;
87 dct0_size -= dct1_size; /* DctSelBaseOffset = DctSelBaseAddr - Interleaved region */
88 Set_NB32(pDCTstat->dev_dct, 0x114, dct0_size);
91 dct1_size = DctSelBase;
92 val = Get_NB32(pDCTstat->dev_dct, 0x110);
96 val |= (DctSelIntLvAddr << 6) & 0xFF;
97 Set_NB32(pDCTstat->dev_dct, 0x110, val);
102 if (val < HoleBase) { /* DctSelBaseAddr < DramHoleBase */
108 val = Get_NB32(pDCTstat->dev_map, 0xF0); /* DramHoleOffset */
110 val |= (tmp & ~0xFFFF007F);
111 Set_NB32(pDCTstat->dev_map, 0xF0, val);
114 printk(BIOS_DEBUG, "InterleaveChannels_D: Node %x\n", Node);
115 printk(BIOS_DEBUG, "InterleaveChannels_D: Status %x\n", pDCTstat->Status);
116 printk(BIOS_DEBUG, "InterleaveChannels_D: ErrStatus %x\n", pDCTstat->ErrStatus);
117 printk(BIOS_DEBUG, "InterleaveChannels_D: ErrCode %x\n", pDCTstat->ErrCode);
121 printk(BIOS_DEBUG, "InterleaveChannels_D: Done\n\n");