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 static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
21 struct DCTStatStruc *pDCTstat, u32 MrsChipSel, u32 CtrlWordNum)
23 u8 Dimms, DimmNum, MaxDimm, Speed;
26 DimmNum = MrsChipSel >> 20;
33 MaxDimm = mctGet_NVbits(NV_MAX_DIMMS);
34 Speed = pDCTstat->DIMMAutoSpeed;
36 Dimms = pDCTstat->MAdimms[0];
41 else if (CtrlWordNum == 1) {
42 if (!((pDCTstat->DimmDRPresent | pDCTstat->DimmQRPresent) & (1 << DimmNum)))
43 val |= 0xC; /* if single rank, set DBA1 and DBA0 */
45 else if (CtrlWordNum == 2) {
48 if (((pDCTstat->DimmQRPresent & (1 << DimmNum)) && (Dimms == 1)) || Dimms == 2)
49 if (!(pDCTstat->MirrPresU_NumRegR & (1 << DimmNum)))
52 if (pDCTstat->MirrPresU_NumRegR & (1 << DimmNum))
59 } else if (CtrlWordNum == 3) {
60 val = pDCTstat->CtrlWrd3 >> (DimmNum << 2);
61 } else if (CtrlWordNum == 4) {
62 val = pDCTstat->CtrlWrd4 >> (DimmNum << 2);
63 } else if (CtrlWordNum == 5) {
64 val = pDCTstat->CtrlWrd5 >> (DimmNum << 2);
65 } else if (CtrlWordNum == 8) {
68 if (pDCTstat->MirrPresU_NumRegR & (1 << DimmNum))
70 } else if (CtrlWordNum == 9) {
71 val |= 0xD; /* DBA1, DBA0, DA3 = 0 */
75 val = MrsChipSel | ((val >> 2) & 3) << 16 | MrsChipSel | ((val >> 2) & 3);
77 /* transfer Control word number to address [BA2,A2,A1,A0] */
78 if (CtrlWordNum > 7) {
87 static void mct_SendCtrlWrd(struct MCTStatStruc *pMCTstat,
88 struct DCTStatStruc *pDCTstat, u32 val)
90 u32 dev = pDCTstat->dev_dct;
92 val |= Get_NB32(dev, 0x7C) & ~0xFFFFFF;
93 val |= 1 << SendControlWord;
94 Set_NB32(dev, 0x7C, val);
97 val = Get_NB32(dev, 0x7C);
98 } while (val & (1 << SendControlWord));
101 void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
102 struct DCTStatStruc *pDCTstat, u8 dct)
105 u32 dev = pDCTstat->dev_dct;
112 for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel ++, MrsChipSel ++) {
113 if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
114 val = Get_NB32(dev, 0xA8);
117 switch (MrsChipSel) {
123 val |= (3 << 2) << 8;
126 val |= (3 << 4) << 8;
129 val |= (3 << 6) << 8;
131 Set_NB32(dev, 0xA8, val);
133 for (cw=0; cw <=15; cw ++) {
135 if (!(cw==6 || cw==7)) {
136 val = mct_ControlRC(pMCTstat, pDCTstat, MrsChipSel << 20, cw);
137 mct_SendCtrlWrd(pMCTstat, pDCTstat, val);
146 void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
147 struct DCTStatStruc *pDCTstat)
149 u32 SaveSpeed = pDCTstat->DIMMAutoSpeed;
151 u32 dev = pDCTstat->dev_dct;
154 pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
155 for (MrsChipSel=0; MrsChipSel < 8; MrsChipSel++, MrsChipSel++) {
156 if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
157 val = Get_NB32(dev, 0xA8);
159 val |= (0x3 << MrsChipSel) << 8;
160 Set_NB32(dev, 0xA8, val);
163 switch (pDCTstat->TargetFreq) {
165 mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x4000A);
168 mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x40012);
171 mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x4001A);
177 val = mct_ControlRC(pMCTstat, pDCTstat, MrsChipSel << 20, 2);
178 mct_SendCtrlWrd(pMCTstat, pDCTstat, val);
182 /* Resend control word 8 */
183 val = mct_ControlRC(pMCTstat, pDCTstat, MrsChipSel << 20, 8);
184 mct_SendCtrlWrd(pMCTstat, pDCTstat, val);
189 pDCTstat->DIMMAutoSpeed = SaveSpeed;