diff options
author | Marco Schmidt <mashpb@gmail.com> | 2009-06-06 11:33:58 +0000 |
---|---|---|
committer | Patrick Georgi <patrick.georgi@coresystems.de> | 2009-06-06 11:33:58 +0000 |
commit | a774192e22433938d527764531d81a37f985a8f2 (patch) | |
tree | ce612e72ab0a4d09406c70142ef09e99d13be97a /src/northbridge/amd | |
parent | c263b4471dd42895b409652b3f3567fcb5cdaae1 (diff) |
Fix for Erratum 350 for AMD Fam10h CPUs.
Compared to posted patch, there are whitespace fixes
(request by Uwe), and a guard to run the erratum only
on AMD_RB_C2 (request by Marc).
Signed-off-by: Marco Schmidt <mashpb@gmail.com>
Acked-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4346 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/amd')
-rw-r--r-- | src/northbridge/amd/amdmct/mct/mct_d.c | 2 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/wrappers/mcti_d.c | 72 |
2 files changed, 71 insertions, 3 deletions
diff --git a/src/northbridge/amd/amdmct/mct/mct_d.c b/src/northbridge/amd/amdmct/mct/mct_d.c index cec708c2b1..105ae662b8 100644 --- a/src/northbridge/amd/amdmct/mct/mct_d.c +++ b/src/northbridge/amd/amdmct/mct/mct_d.c @@ -356,7 +356,7 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat, phyAssistedMemFnceTraining(pMCTstat, pDCTstatA); if (nv_DQSTrainCTL) { - mctHookBeforeAnyTraining(); + mctHookBeforeAnyTraining(pMCTstat, pDCTstatA); print_t("DQSTiming_D: TrainReceiverEn_D FirstPass:\n"); TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c index 7e111917d1..595273ea77 100644 --- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c +++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c @@ -18,7 +18,7 @@ */ /* Call-backs */ - +#include <delay.h> u16 mctGet_NVbits(u8 index) { u16 val = 0; @@ -326,9 +326,77 @@ void mctHookAfterDramInit(void) { } +static void coreDelay (void); + + +/* Erratum 350 */ +void vErrata350(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) +{ + u8 u8Channel; + u8 u8Receiver; + u32 u32Addr; + u8 u8Valid; + u32 u32DctDev; + + // 1. dummy read for each installed DIMM */ + for (u8Channel = 0; u8Channel < 2; u8Channel++) { + // This will be 0 for vaild DIMMS, eles 8 + u8Receiver = mct_InitReceiver_D(pDCTstat, u8Channel); + + for (; u8Receiver < 8; u8Receiver += 2) { + u32Addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, u8Channel, u8Receiver, &u8Valid); + + if(!u8Valid) { /* Address not supported on current CS */ + print_t("vErrara350: Address not supported on current CS\n"); + continue; + } + print_t("vErrara350: dummy read \n"); + read32_fs(u32Addr); + } + } + + print_t("vErrara350: step 2a\n"); + + /* 2. Write 0000_8000h to register F2x[1, 0]9C_xD080F0C. */ + u32DctDev = pDCTstat->dev_dct; + Set_NB32_index_wait(u32DctDev, 0x098, 0x0c, 0x00008000); + /* ^--- value + ^---F2x[1, 0]9C_x0C DRAM Phy Miscellaneous Register + ^----F2x[1, 0]98 DRAM Controller Additional Data Offset Register */ + + if(!pDCTstat->GangedMode) { + print_t("vErrara350: step 2b\n"); + Set_NB32_index_wait(u32DctDev, 0x198, 0x0c, 0x00008000); + /* ^--- value + ^---F2x[1, 0]9C_x0C DRAM Phy Miscellaneous Register + ^----F2x[1, 0]98 DRAM Controller Additional Data Offset Register */ + } + + print_t("vErrara350: step 3\n"); + /* 3. Wait at least 300 nanoseconds. */ + coreDelay(); + + print_t("vErrara350: step 4\n"); + /* 4. Write 0000_0000h to register F2x[1, 0]9C_xD080F0C. */ + Set_NB32_index_wait(u32DctDev, 0x098, 0x0c, 0x00000000); + + if(!pDCTstat->GangedMode) { + print_t("vErrara350: step 4b\n"); + Set_NB32_index_wait(u32DctDev, 0x198, 0x0c, 0x00000000); + } + + print_t("vErrara350: step 5\n"); + /* 5. Wait at least 2 microseconds. */ + coreDelay(); + +} + -void mctHookBeforeAnyTraining(void) +void mctHookBeforeAnyTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) { + if (pDCTstatA->LogicalCPUID & AMD_RB_C2) { + vErrata350(pMCTstat, pDCTstatA); + } } void mctHookAfterAnyTraining(void) |