DDR3 support for AMD Fam10.
[coreboot.git] / src / northbridge / amd / amdmct / wrappers / mcti_d.c
index 41afed52ff504b93cbb5faa136ffbf32a51b6780..a4a87fca01dc7cdacd2ae9f30147411d0ea58c40 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * This file is part of the LinuxBIOS project.
+ * This file is part of the coreboot project.
  *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 
 /* Call-backs */
-
-u16 mctGet_NVbits(u8 index)
+#include <delay.h>
+static u16 mctGet_NVbits(u8 index)
 {
        u16 val = 0;
 
        switch (index) {
        case NV_PACK_TYPE:
-#if SYSTEM_TYPE == SERVER
+#if CONFIG_CPU_SOCKET_TYPE == 0x10     /* Socket F */
                val = 0;
-#elif SYSTEM_TYPE == DESKTOP
+#elif CONFIG_CPU_SOCKET_TYPE == 0x11   /* AM3 */
                val = 1;
+#elif CONFIG_CPU_SOCKET_TYPE == 0x13   /* ASB2 */
+               val = 4;
 //#elif SYSTEM_TYPE == MOBILE
 //             val = 2;
 #endif
@@ -129,11 +131,11 @@ u16 mctGet_NVbits(u8 index)
                //val = 1;      /* enable */
                break;
        case NV_BottomIO:
-               val = 0xC0;     /* address bits [31:24] */
+               val = 0xE0;     /* address bits [31:24] */
                break;
        case NV_BottomUMA:
 #if (UMA_SUPPORT == 0)
-               val = 0xC0;     /* address bits [31:24] */
+               val = 0xE0;     /* address bits [31:24] */
 #elif (UMA_SUPPORT == 1)
                val = 0xB0;     /* address bits [31:24] */
 #endif
@@ -197,15 +199,18 @@ u16 mctGet_NVbits(u8 index)
        case NV_CS_SpareCTL:
                val = 0;        /* Disabled */
                //val = 1;      /* Enabled */
+               break;
        case NV_SyncOnUnEccEn:
                val = 0;        /* Disabled */
                //val = 1;      /* Enabled */
+               break;
        case NV_Unganged:
                /* channel interleave is better performance than ganged mode at this time */
                val = 1;                /* Enabled */
                //val = 0;      /* Disabled */
+               break;
        case NV_ChannelIntlv:
-               val = 5;        /* Disabled */ /* Not currently checked in mctchi_d.c */
+               val = 5;        /* Not currently checked in mctchi_d.c */
        /* Bit 0 =     0 - Disable
         *             1 - Enable
         * Bits[2:1] = 00b - Address bits 6
@@ -213,126 +218,218 @@ u16 mctGet_NVbits(u8 index)
         *             10b - Hash*, XOR of address bits [20:16, 6]
         *             11b - Hash*, XOR of address bits [20:16, 9]
         */
-
+               break;
        }
 
        return val;
 }
 
 
-void mctHookAfterDIMMpre(void)
+static void mctHookAfterDIMMpre(void)
 {
 }
 
 
-void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
+static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
 {
        pDCTstat->PresetmaxFreq = 400;
 }
 
-
-void mctAdjustAutoCycTmg(void)
+#ifdef UNUSED_CODE
+static void mctAdjustAutoCycTmg(void)
 {
 }
+#endif
 
-void mctAdjustAutoCycTmg_D(void)
+
+static void mctAdjustAutoCycTmg_D(void)
 {
 }
 
 
-void mctHookAfterAutoCycTmg(void)
+static void mctHookAfterAutoCycTmg(void)
 {
 }
 
 
-void mctGetCS_ExcludeMap(void)
+static void mctGetCS_ExcludeMap(void)
 {
 }
 
 
-void mctHookAfterAutoCfg(void)
+static void mctHookAfterAutoCfg(void)
 {
 }
 
 
-void mctHookAfterPSCfg(void)
+static void mctHookAfterPSCfg(void)
 {
 }
 
 
-void mctHookAfterHTMap(void)
+static void mctHookAfterHTMap(void)
 {
 }
 
 
-void mctHookAfterCPU(void)
+static void mctHookAfterCPU(void)
 {
 }
 
 
-void mctSaveDQSSigTmg_D(void)
+static void mctSaveDQSSigTmg_D(void)
 {
 }
 
 
-void mctGetDQSSigTmg_D(void)
+static void mctGetDQSSigTmg_D(void)
 {
 }
 
 
-void mctHookBeforeECC(void)
+static void mctHookBeforeECC(void)
 {
 }
 
 
-void mctHookAfterECC(void)
+static void mctHookAfterECC(void)
 {
 }
 
+#ifdef UNUSED_CODE
+static void mctInitMemGPIOs_A(void)
+{
+}
+#endif
+
 
-void mctInitMemGPIOs_A(void)
+static void mctInitMemGPIOs_A_D(void)
 {
 }
 
 
-void mctInitMemGPIOs_A_D(void)
+static void mctNodeIDDebugPort_D(void)
 {
 }
 
 
-void mctNodeIDDebugPort_D(void)
+#ifdef UNUSED_CODE
+static void mctWarmReset(void)
 {
 }
+#endif
 
 
-void mctWarmReset(void)
+static void mctWarmReset_D(void)
 {
 }
 
-void mctWarmReset_D(void)
+
+static void mctHookBeforeDramInit(void)
 {
 }
 
 
-void mctHookBeforeDramInit(void)
+static void mctHookAfterDramInit(void)
 {
 }
 
+static void coreDelay (void);
 
-void mctHookAfterDramInit(void)
+
+/* Erratum 350 */
+static 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("vErrata350: Address not supported on current CS\n");
+                               continue;
+                       }
+                       print_t("vErrata350: dummy read \n");
+                       read32_fs(u32Addr);
+               }
+       }
+
+       print_t("vErrata350: step 2a\n");
+
+       /* 2. Write 0000_8000h to register F2x[1, 0]9C_xD080F0C. */
+       u32DctDev = pDCTstat->dev_dct;
+       Set_NB32_index_wait(u32DctDev, 0x098, 0xD080F0C, 0x00008000);
+       /*                                                ^--- value
+                                               ^---F2x[1, 0]9C_x0D080F0C, No description in BKDG.
+                                        ^----F2x[1, 0]98 DRAM Controller Additional Data Offset Register */
+
+       if(!pDCTstat->GangedMode) {
+               print_t("vErrata350: step 2b\n");
+               Set_NB32_index_wait(u32DctDev, 0x198, 0xD080F0C, 0x00008000);
+               /*                                                ^--- value
+                                                       ^---F2x[1, 0]9C_x0D080F0C, No description in BKDG
+                                               ^----F2x[1, 0]98 DRAM Controller Additional Data Offset Register */
+       }
+
+       print_t("vErrata350: step 3\n");
+       /* 3. Wait at least 300 nanoseconds. */
+       coreDelay();
+
+       print_t("vErrata350: step 4\n");
+       /* 4. Write 0000_0000h to register F2x[1, 0]9C_xD080F0C. */
+       Set_NB32_index_wait(u32DctDev, 0x098, 0xD080F0C, 0x00000000);
+
+       if(!pDCTstat->GangedMode) {
+               print_t("vErrata350: step 4b\n");
+               Set_NB32_index_wait(u32DctDev, 0x198, 0xD080F0C, 0x00000000);
+       }
+
+       print_t("vErrata350: step 5\n");
+       /* 5. Wait at least 2 microseconds. */
+       coreDelay();
+
 }
 
 
-void mctHookBeforeAnyTraining(void)
+static void mctHookBeforeAnyTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
 {
+#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
+       if (pDCTstatA->LogicalCPUID & (AMD_RB_C2 | AMD_DA_C2 | AMD_DA_C3)) {
+               vErrata350(pMCTstat, pDCTstatA);
+       }
+#endif
 }
 
-void mctHookAfterAnyTraining(void)
+static u32 mct_AdjustSPDTimings(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u32 val)
+{
+       if (pDCTstatA->LogicalCPUID & AMD_DR_Bx) {
+               if (pDCTstatA->Status & (1 << SB_Registered)) {
+                       val ++;
+               }
+       }
+       return val;
+}
+
+static void mctHookAfterAnyTraining(void)
 {
 }
 
-u32 mctGetLogicalCPUID_D(u8 node)
+static u32 mctGetLogicalCPUID_D(u8 node)
 {
        return mctGetLogicalCPUID(node);
 }
+
+static u8 mctSetNodeBoundary_D(void)
+{
+       return 0;
+}
+