Please bear with me - another rename checkin. This qualifies as trivial, no
[coreboot.git] / src / northbridge / amd / amdmct / mct / mctndi_d.c
1 /*
2  * This file is part of the coreboot 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
22 void InterleaveNodes_D(struct MCTStatStruc *pMCTstat,
23                         struct DCTStatStruc *pDCTstatA)
24 {
25
26         /* Applies Node memory interleaving if enabled and if all criteria are met. */
27         u8 Node;
28         u32 Base;
29         u32 MemSize, MemSize0 = 0;
30         u32 Dct0MemSize = 0, DctSelBase, DctSelBaseOffset;
31         u8 Nodes;
32         u8 NodesWmem;
33         u8 DoIntlv;
34         u8 _NdIntCap;
35         u8 _SWHole;
36         u8 HWHoleSz;
37         u32 DramHoleAddrReg;
38         u32 HoleBase;
39         u32 dev0;
40         u32 reg0;
41         u32 val;
42         u8 i;
43         struct DCTStatStruc *pDCTstat;
44
45         DoIntlv = mctGet_NVbits(NV_NodeIntlv);
46
47         _NdIntCap = 0;
48         HWHoleSz = 0;   /*For HW remapping, NOT Node hoisting. */
49
50         pDCTstat = pDCTstatA + 0;
51         dev0 = pDCTstat->dev_host;
52         Nodes = ((Get_NB32(dev0, 0x60) >> 4) & 0x7) + 1;
53
54
55         dev0 = pDCTstat->dev_map;
56         reg0 = 0x40;
57
58         NodesWmem = 0;
59         Node = 0;
60
61         while (DoIntlv && (Node < Nodes)) {
62                 pDCTstat = pDCTstatA + Node;
63                 if (pMCTstat->GStatus & (1 << GSB_SpIntRemapHole)) {
64                         pMCTstat->GStatus |= 1 << GSB_HWHole;
65                         _SWHole = 0;
66                 } else if (pDCTstat->Status & (1 << SB_SWNodeHole)) {
67                         _SWHole = 1;
68                 } else {
69                         _SWHole = 0;
70                 }
71
72                 if(!_SWHole) {
73                         Base = Get_NB32(dev0, reg0);
74                         if (Base & 1) {
75                                 NodesWmem++;
76                                 Base &= 0xFFFF0000;     /* Base[39:8] */
77
78                                 if (pDCTstat->Status & (1 << SB_HWHole )) {
79
80                                         /* to get true amount of dram,
81                                          * subtract out memory hole if HW dram remapping */
82                                         DramHoleAddrReg = Get_NB32(pDCTstat->dev_map, 0xF0);
83                                         HWHoleSz = DramHoleAddrReg >> 16;
84                                         HWHoleSz = (((~HWHoleSz) + 1) & 0xFF);
85                                         HWHoleSz <<= 24-8;
86                                 }
87                                 /* check to see if the amount of memory on each channel
88                                  * are the same on all nodes */
89
90                                 DctSelBase = Get_NB32(pDCTstat->dev_dct, 0x114);
91                                 if(DctSelBase) {
92                                         DctSelBase <<= 8;
93                                         if ( pDCTstat->Status & (1 << SB_HWHole)) {
94                                                 if (DctSelBase >= 0x1000000) {
95                                                         DctSelBase -= HWHoleSz;
96                                                 }
97                                         }
98                                         DctSelBaseOffset -= Base;
99                                         if (Node == 0) {
100                                                 Dct0MemSize = DctSelBase;
101                                         } else if (DctSelBase != Dct0MemSize) {
102                                                 break;
103                                         }
104                                 }
105
106                                 MemSize = Get_NB32(dev0, reg0 + 4);
107                                 MemSize &= 0xFFFF0000;
108                                 MemSize += 0x00010000;
109                                 MemSize -= Base;
110                                 if ( pDCTstat->Status & (1 << SB_HWHole)) {
111                                         MemSize -= HWHoleSz;
112                                 }
113                                 if (Node == 0) {
114                                         MemSize0 = MemSize;
115                                 } else if (MemSize0 != MemSize) {
116                                         break;
117                                 }
118                         } else {
119                                 break;
120                         }
121                 } else {
122                         break;
123                 }
124         Node++;
125         reg0 += 8;
126         }
127
128         if (Node == Nodes) {
129                 /* if all nodes have memory and no Node had SW memhole */
130                 if (Nodes == 2 || Nodes == 4 || Nodes == 8)
131                         _NdIntCap = 1;
132         }
133
134         if (!_NdIntCap)
135                 DoIntlv = 0;
136
137
138         if (pMCTstat->GStatus & 1 << (GSB_SpIntRemapHole)) {
139                 HWHoleSz = pMCTstat->HoleBase;
140                 if (HWHoleSz == 0) {
141                         HWHoleSz = mctGet_NVbits(NV_BottomIO) & 0xFF;
142                         HWHoleSz <<= 24-8;
143                 }
144                 HWHoleSz = ((~HWHoleSz) + 1) & 0x00FF0000;
145         }
146
147         if (DoIntlv) {
148                 MCTMemClr_D(pMCTstat,pDCTstatA);
149                 /* Program Interleaving enabled on Node 0 map only.*/
150                 MemSize0 <<= bsf(Nodes);        /* MemSize=MemSize*2 (or 4, or 8) */
151                 Dct0MemSize <<= bsf(Nodes);
152                 MemSize0 += HWHoleSz;
153                 Base = ((Nodes - 1) << 8) | 3;
154                 reg0 = 0x40;
155                 Node = 0;
156                 while(Node < Nodes) {
157                         Set_NB32(dev0, reg0, Base);
158                         MemSize = MemSize0;
159                         MemSize--;
160                         MemSize &= 0xFFFF0000;
161                         MemSize |= Node << 8;   /* set IntlvSel[2:0] field */
162                         MemSize |= Node;        /* set DstNode[2:0] field */
163                         Set_NB32(dev0, reg0 + 4, MemSize0);
164                         reg0 += 8;
165                         Node++;
166                 }
167
168                 /*  set base/limit to F1x120/124 per Node */
169                 Node = 0;
170                 while(Node < Nodes) {
171                         pDCTstat = pDCTstatA + Node;
172                         pDCTstat->NodeSysBase = 0;
173                         MemSize = MemSize0;
174                         MemSize -= HWHoleSz;
175                         MemSize--;
176                         pDCTstat->NodeSysLimit = MemSize;
177                         Set_NB32(pDCTstat->dev_map, 0x120, Node << 21);
178                         MemSize = MemSize0;
179                         MemSize--;
180                         MemSize >>= 19;
181                         val = Base;
182                         val &= 0x700;
183                         val <<= 13;
184                         val |= MemSize;
185                         Set_NB32(pDCTstat->dev_map, 0x124, val);
186
187                         if (pMCTstat->GStatus & (1 << GSB_HWHole)) {
188                                 HoleBase = pMCTstat->HoleBase;
189                                 if (Dct0MemSize >= HoleBase) {
190                                         val = HWHoleSz;
191                                         if( Node == 0) {
192                                                 val += Dct0MemSize;
193                                         }
194                                 } else {
195                                         val = HWHoleSz + Dct0MemSize;
196                                 }
197
198                                 val >>= 8;              /* DramHoleOffset */
199                                 HoleBase <<= 8;         /* DramHoleBase */
200                                 val |= HoleBase;
201                                 val |= 1 << DramMemHoistValid;
202                                 val |= 1 << DramHoleValid;
203                                 Set_NB32(pDCTstat->dev_map, 0xF0, val);
204                         }
205
206
207                         Set_NB32(pDCTstat->dev_dct, 0x114, Dct0MemSize >> 8);   /* DctSelBaseOffset */
208                         val = Get_NB32(pDCTstat->dev_dct, 0x110);
209                         val &= 0x7FF;
210                         val |= Dct0MemSize >> 8;
211                         Set_NB32(pDCTstat->dev_dct, 0x110, val);        /* DctSelBaseAddr */
212                         print_tx("InterleaveNodes: DRAM Controller Select Low Register = ", val);
213                         Node++;
214                 }
215
216
217                 /* Copy Node 0 into other Nodes' CSRs */
218                 Node = 1;
219                 while (Node < Nodes) {
220                         pDCTstat = pDCTstatA + Node;
221
222                         for (i = 0x40; i <= 0x80; i++) {
223                                 val = Get_NB32(dev0, i);
224                                 Set_NB32(pDCTstat->dev_map, i, val);
225                         }
226
227                         val = Get_NB32(dev0, 0xF0);
228                         Set_NB32(pDCTstat->dev_map, 0xF0, val);
229                         Node++;
230                 }
231                 pMCTstat->GStatus = (1 << GSB_NodeIntlv);
232         }
233         print_tx("InterleaveNodes_D: Status ", pDCTstat->Status);
234         print_tx("InterleaveNodes_D: ErrStatus ", pDCTstat->ErrStatus);
235         print_tx("InterleaveNodes_D: ErrCode ", pDCTstat->ErrCode);
236         print_t("InterleaveNodes_D: Done\n");
237 }