Initial AMD Barcelona support for rev Bx.
[coreboot.git] / src / northbridge / amd / amdmct / mct / mctcsi_d.c
1 /*
2  * This file is part of the LinuxBIOS project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
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.
9  *
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.
14  *
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
18  */
19
20
21 /* Low swap bit vs bank size encoding (physical, not logical address bit)
22  * ;To calculate the number by hand, add the number of Bank address bits
23  * ;(2 or 3) to the number of column address bits, plus 3 (the logical
24  * ;page size), and subtract 8.
25  */
26 static const u8 Tab_int_D[] = { 6,7,7,8,8,8,8,8,9,9,8,9 };
27
28 void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
29                         struct DCTStatStruc *pDCTstat, u8 dct)
30 {
31         u8 ChipSel, EnChipSels;
32         u32 AddrLoMask, AddrHiMask;
33         u32 AddrLoMaskN, AddrHiMaskN, MemSize = 0;
34         u8 DoIntlv, _CsIntCap;
35         u32 BitDelta, BankEncd = 0;
36
37         u32 dev;
38         u32 reg;
39         u32 reg_off;
40         u32 val;
41         u32 val_lo, val_hi;
42
43         DoIntlv = mctGet_NVbits(NV_BankIntlv);
44         _CsIntCap = 0;
45         EnChipSels = 0;
46
47         dev = pDCTstat->dev_dct;
48         reg_off = 0x100 * dct;
49
50         ChipSel = 0;            /* Find out if current configuration is capable */
51         while (DoIntlv && (ChipSel < MAX_CS_SUPPORTED)) {
52                 reg = 0x40+(ChipSel<<2) + reg_off;      /* Dram CS Base 0 */
53                 val = Get_NB32(dev, reg);
54                 if ( val & (1<<CSEnable)) {
55                         EnChipSels++;
56                         reg = 0x60+((ChipSel>>1)<<2)+reg_off; /*Dram CS Mask 0 */
57                         val = Get_NB32(dev, reg);
58                         val >>= 19;
59                         val &= 0x3ff;
60                         val++;
61                         if (EnChipSels == 1)
62                                 MemSize = val;
63                         else
64                                 /*If mask sizes not same then skip */
65                                 if (val != MemSize)
66                                         break;
67                         reg = 0x80 + reg_off;           /*Dram Bank Addressing */
68                         val = Get_NB32(dev, reg);
69                         val >>= (ChipSel>>1)<<2;
70                         val &= 0x0f;
71                         if(EnChipSels == 1)
72                                 BankEncd = val;
73                         else
74                                 /*If number of Rows/Columns not equal, skip */
75                                 if (val != BankEncd)
76                                         break;
77                 }
78                 ChipSel++;
79         }
80         if (ChipSel == MAX_CS_SUPPORTED) {
81                 if ((EnChipSels == 2) || (EnChipSels == 4) || (EnChipSels == 8))
82                         _CsIntCap = 1;
83         }
84
85         if (DoIntlv) {
86                 if(!_CsIntCap) {
87                         pDCTstat->ErrStatus |= 1<<SB_BkIntDis;
88                         DoIntlv = 0;
89                 }
90         }
91
92         if(DoIntlv) {
93                 val = Tab_int_D[BankEncd];
94                 if (pDCTstat->Status & (1<<SB_128bitmode))
95                         val++;
96
97                 AddrLoMask = (EnChipSels - 1)  << val;
98                 AddrLoMaskN = ~AddrLoMask;
99
100                 val = bsf(MemSize) + 19;
101                 AddrHiMask = (EnChipSels -1) << val;
102                 AddrHiMaskN = ~AddrHiMask;
103
104                 BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask);
105
106                 for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) {
107                         reg = 0x40+(ChipSel<<2) + reg_off;      /*Dram CS Base 0 */
108                         val = Get_NB32(dev, reg);
109                         if (val & 3) {
110                                 val_lo = val & AddrLoMask;
111                                 val_hi = val & AddrHiMask;
112                                 val &= AddrLoMaskN;
113                                 val &= AddrHiMaskN;
114                                 val_lo <<= BitDelta;
115                                 val_hi >>= BitDelta;
116                                 val |= val_lo;
117                                 val |= val_hi;
118                                 Set_NB32(dev, reg, val);
119
120                                 if(ChipSel & 1)
121                                         continue;
122
123                                 reg = 0x60 + ((ChipSel>>1)<<2) + reg_off; /*Dram CS Mask 0 */
124                                 val = Get_NB32(dev, reg);
125                                 val_lo = val & AddrLoMask;
126                                 val_hi = val & AddrHiMask;
127                                 val &= AddrLoMaskN;
128                                 val &= AddrHiMaskN;
129                                 val_lo <<= BitDelta;
130                                 val_hi >>= BitDelta;
131                                 val |= val_lo;
132                                 val |= val_hi;
133                                 Set_NB32(dev, reg, val);
134                         }
135                 }
136                 print_t("InterleaveBanks_D: Banks Interleaved ");
137         }       /* DoIntlv */
138
139 //      dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2));
140
141         print_tx("InterleaveBanks_D: Status ", pDCTstat->Status);
142         print_tx("InterleaveBanks_D: ErrStatus ", pDCTstat->ErrStatus);
143         print_tx("InterleaveBanks_D: ErrCode ", pDCTstat->ErrCode);
144         print_t("InterleaveBanks_D: Done\n");
145 }
146
147