summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Schmidt <mashpb@gmail.com>2009-06-06 11:33:58 +0000
committerPatrick Georgi <patrick.georgi@coresystems.de>2009-06-06 11:33:58 +0000
commita774192e22433938d527764531d81a37f985a8f2 (patch)
treece612e72ab0a4d09406c70142ef09e99d13be97a
parentc263b4471dd42895b409652b3f3567fcb5cdaae1 (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
-rw-r--r--src/northbridge/amd/amdmct/mct/mct_d.c2
-rw-r--r--src/northbridge/amd/amdmct/wrappers/mcti_d.c72
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)