aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-07-26 00:55:43 -0500
committerMartin Roth <martinroth@google.com>2015-11-16 17:55:57 +0100
commitf682d0028cb33fc4a085af83344f4a7b9c0e78f2 (patch)
tree84c2289b2ca976c728f2fb42ded31c9f79c7a275 /src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
parent474ff3dee54e81017587f53ce644307e4f655333 (diff)
amd/amdmct/mct_ddr3: Partially fix up registered DIMMs on Fam10h
Sufficient support has been added to allow booting with registered DIMMs on the KGPE-D16 in certain slots. ECC support needs additional work; the ECC data lanes appear to cause boot failures in some slots. Change-Id: Ieaf4cbf351908e5a89760be49a6667dc55dbc575 Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/12017 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mctrci.c')
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctrci.c151
1 files changed, 101 insertions, 50 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
index d7bd3a7cdc..3f6c39d2c5 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
@@ -14,12 +14,39 @@
* GNU General Public License for more details.
*/
+static uint16_t memclk_to_freq(uint16_t memclk) {
+ uint16_t fam10h_freq_tab[] = {0, 0, 0, 400, 533, 667, 800};
+ uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
+
+ uint16_t mem_freq = 0;
+
+ if (is_fam15h()) {
+ if (memclk < 0x17) {
+ mem_freq = fam15h_freq_tab[memclk];
+ }
+ } else {
+ if ((memclk > 0x0) && (memclk < 0x8)) {
+ mem_freq = fam10h_freq_tab[memclk - 1];
+ }
+ }
+
+ return mem_freq;
+}
+
+static uint32_t rc_word_value_to_ctl_bits(uint32_t value) {
+ return ((value >> 2) & 3) << 16 | ((value & 3) << 3);
+}
+
static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u32 MrsChipSel, u32 CtrlWordNum)
{
- u8 Dimms, DimmNum, MaxDimm, Speed;
+ u8 Dimms, DimmNum;
u32 val;
u32 dct = 0;
+ uint8_t ddr_voltage_index;
+ uint16_t mem_freq;
+ uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
+ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
DimmNum = (MrsChipSel >> 20) & 0xFE;
@@ -28,54 +55,64 @@ static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
/* DimmNum ++; */
/* cl +=8; */
- MaxDimm = mctGet_NVbits(NV_MAX_DIMMS);
- Speed = pDCTstat->DIMMAutoSpeed;
+ mem_freq = memclk_to_freq(pDCTstat->DIMMAutoSpeed);
if (pDCTstat->CSPresent_DCT[0] > 0) {
dct = 0;
- } else if (pDCTstat->CSPresent_DCT[1] > 0 ){
+ } else if (pDCTstat->CSPresent_DCT[1] > 0 ) {
dct = 1;
- DimmNum ++;
+ DimmNum++;
}
Dimms = pDCTstat->MAdimms[dct];
+ ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct);
+
val = 0;
if (CtrlWordNum == 0)
- val |= 1 << 1;
+ val = 0x2;
else if (CtrlWordNum == 1) {
if (!((pDCTstat->DimmDRPresent | pDCTstat->DimmQRPresent) & (1 << DimmNum)))
- val |= 0xC; /* if single rank, set DBA1 and DBA0 */
+ val = 0xC; /* if single rank, set DBA1 and DBA0 */
} else if (CtrlWordNum == 2) {
- if (MaxDimm == 4) {
- if (Speed == 4) {
- if (((pDCTstat->DimmQRPresent & (1 << DimmNum)) && (Dimms == 1)) || (Dimms == 2))
- if (!(pDCTstat->MirrPresU_NumRegR & (1 << DimmNum)))
- val |= 1 << 2;
- } else {
- if (pDCTstat->MirrPresU_NumRegR & (1 << DimmNum))
- val |= 1 << 2;
+ if (package_type == PT_GR) {
+ /* Socket G34 */
+ if (MaxDimmsInstallable == 2) {
+ if (Dimms > 1)
+ val = 0x4;
}
- } else {
- if (Dimms > 1)
- val |= 1 << 2;
}
} else if (CtrlWordNum == 3) {
- val |= (pDCTstat->CtrlWrd3 >> (DimmNum << 2)) & 0xFF;
+ val = (pDCTstat->CtrlWrd3 >> (DimmNum << 2)) & 0xFF;
} else if (CtrlWordNum == 4) {
- val |= (pDCTstat->CtrlWrd4 >> (DimmNum << 2)) & 0xFF;
+ val = (pDCTstat->CtrlWrd4 >> (DimmNum << 2)) & 0xFF;
} else if (CtrlWordNum == 5) {
- val |= (pDCTstat->CtrlWrd5 >> (DimmNum << 2)) & 0xFF;
+ val = (pDCTstat->CtrlWrd5 >> (DimmNum << 2)) & 0xFF;
} else if (CtrlWordNum == 8) {
- if (MaxDimm == 4)
- if (Speed == 4)
- if (pDCTstat->MirrPresU_NumRegR & (1 << DimmNum))
- val |= 1 << 2;
+ if (package_type == PT_GR) {
+ /* Socket G34 */
+ if (MaxDimmsInstallable == 2) {
+ val = 0x0;
+ }
+ }
} else if (CtrlWordNum == 9) {
- val |= 0xD; /* DBA1, DBA0, DA3 = 0 */
+ val = 0xD; /* DBA1, DBA0, DA3 = 0 */
+ } else if (CtrlWordNum == 10) {
+ val = 0x0; /* Lowest operating frequency */
+ } else if (CtrlWordNum == 11) {
+ if (ddr_voltage_index & 0x4)
+ val = 0x2; /* 1.25V */
+ else if (ddr_voltage_index & 0x2)
+ val = 0x1; /* 1.35V */
+ else
+ val = 0x0; /* 1.5V */
+ } else if (CtrlWordNum >= 12) {
+ val = 0x0; /* Unset */
}
- val &= 0xffffff0f;
+ val &= 0xf;
+
+ printk(BIOS_SPEW, "Preparing to send DIMM RC%d: %02x\n", CtrlWordNum, val);
- val = MrsChipSel | ((val >> 2) & 3) << 16 | ((val & 3) << 3);
+ val = MrsChipSel | rc_word_value_to_ctl_bits(val);
/* transfer Control word number to address [BA2,A2,A1,A0] */
if (CtrlWordNum > 7) {
@@ -125,18 +162,18 @@ void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
val &= ~(0xF << 8);
switch (MrsChipSel) {
- case 0:
- case 1:
- val |= 3 << 8;
- case 2:
- case 3:
- val |= (3 << 2) << 8;
- case 4:
- case 5:
- val |= (3 << 4) << 8;
- case 6:
- case 7:
- val |= (3 << 6) << 8;
+ case 0:
+ case 1:
+ val |= 3 << 8;
+ case 2:
+ case 3:
+ val |= (3 << 2) << 8;
+ case 4:
+ case 5:
+ val |= (3 << 4) << 8;
+ case 6:
+ case 7:
+ val |= (3 << 6) << 8;
}
Set_NB32_DCT(dev, dct, 0xa8, val);
@@ -160,8 +197,10 @@ void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
u32 MrsChipSel;
u32 dev = pDCTstat->dev_dct;
u32 val;
+ uint16_t mem_freq;
pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
+ mem_freq = memclk_to_freq(pDCTstat->TargetFreq);
for (MrsChipSel=0; MrsChipSel < 8; MrsChipSel++, MrsChipSel++) {
if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
/* 2. Program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects. */
@@ -171,19 +210,31 @@ void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
Set_NB32_DCT(dev, 0, 0xA8, val); /* TODO: dct 0 / 1 select */
/* Resend control word 10 */
+ uint8_t freq_ctl_val = 0;
mct_Wait(1600);
- switch (pDCTstat->TargetFreq) {
- case 5:
- mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x4000A);
- break;
- case 6:
- mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x40012);
- break;
- case 7:
- mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x4001A);
- break;
+ switch (mem_freq) {
+ case 333:
+ case 400:
+ freq_ctl_val = 0x0;
+ break;
+ case 533:
+ freq_ctl_val = 0x1;
+ break;
+ case 667:
+ freq_ctl_val = 0x2;
+ break;
+ case 800:
+ freq_ctl_val = 0x3;
+ break;
+ case 933:
+ freq_ctl_val = 0x4;
+ break;
}
+ printk(BIOS_SPEW, "Preparing to send DIMM RC%d: %02x\n", 10, freq_ctl_val);
+
+ mct_SendCtrlWrd(pMCTstat, pDCTstat, MrsChipSel << 20 | 0x40002 | rc_word_value_to_ctl_bits(freq_ctl_val));
+
mct_Wait(1600);
/* Resend control word 2 */