This patch adds support for the northbridge integrated into the AMD
authorMarc Jones <marc.jones@amd.com>
Fri, 4 May 2007 18:58:42 +0000 (18:58 +0000)
committerStefan Reinauer <stepan@openbios.org>
Fri, 4 May 2007 18:58:42 +0000 (18:58 +0000)
Geode LX platform, including memory and graphics. (rediffed for whitespace)

Signed-off-by: Marc Jones <marc.jones@amd.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2630 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/northbridge/amd/lx/Config.lb
src/northbridge/amd/lx/chip.h
src/northbridge/amd/lx/chipsetinit.c [deleted file]
src/northbridge/amd/lx/grphinit.c
src/northbridge/amd/lx/northbridge.c
src/northbridge/amd/lx/northbridgeinit.c
src/northbridge/amd/lx/pll_reset.c
src/northbridge/amd/lx/raminit.c

index ee8cd206f936db045dda3997c6103b7be35bfc17..dc7c15962ce38d3106fa1241c3a849049b1fdbc3 100644 (file)
@@ -1,5 +1,4 @@
 config chip.h
 object northbridge.o
 object northbridgeinit.o
-object chipsetinit.o
 object grphinit.o
index 1a237d72767c0bc092d86857ab6d2b1e3b8fbe0c..5fa7948c189e2d760f9151ac5f07e26f385d6e71 100644 (file)
@@ -1,7 +1,12 @@
+/*
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+*/
+
 struct northbridge_amd_lx_config
 {
-       uint16_t irqmap;
-       int setupflash;
+
 };
 
 extern struct chip_operations northbridge_amd_lx_ops;
diff --git a/src/northbridge/amd/lx/chipsetinit.c b/src/northbridge/amd/lx/chipsetinit.c
deleted file mode 100644 (file)
index 4e0d329..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-#include <console/console.h>
-#include <arch/io.h>
-#include <stdint.h>
-#include <device/device.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bitops.h>
-#include "chip.h"
-#include "northbridge.h"
-#include <cpu/amd/lxdef.h>
-#include <cpu/x86/msr.h>
-#include <cpu/x86/cache.h>
-
-
-/* the structs in this file only set msr.lo. But ... that may not always be true */
-
-struct msrinit {
-       unsigned long msrnum;
-       msr_t msr;
-};
-
-/*  Master Configuration Register for Bus Masters.*/
-struct msrinit SB_MASTER_CONF_TABLE[] = {
-       {USB1_SB_GLD_MSR_CONF,  {.hi=0,.lo=0x00008f000}},       /*  NOTE: Must be 1st entry in table*/
-       {USB2_SB_GLD_MSR_CONF,  {.hi=0,.lo=0x00008f000}},
-       {ATA_SB_GLD_MSR_CONF,   {.hi=0,.lo=0x00048f000}},
-       {AC97_SB_GLD_MSR_CONF,  {.hi=0,.lo=0x00008f000}},
-       {MDD_SB_GLD_MSR_CONF,   {.hi=0,.lo=0x00000f000}},
-/* GLPCI_SB_GLD_MSR_CONF,      0x0FFFFFFFF*/
-/* GLCP_SB_GLD_MSR_CONF,       0x0FFFFFFFF*/
-/* GLIU_SB_GLD_MSR_CONF,       0x0*/
-       {0,{0,0}}
-};
-
-/*  5535_A3 Clock Gating*/
-struct msrinit CS5535_CLOCK_GATING_TABLE[] = {
-       {      USB1_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000005}},
-       {      USB2_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000005}},
-       {      GLIU_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000004}},
-       {      GLPCI_SB_GLD_MSR_PM,     {.hi=0,.lo=0x000000005}},
-       {      GLCP_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000004}},
-       {      MDD_SB_GLD_MSR_PM,       {.hi=0,.lo=0x050554111}},
-       {      ATA_SB_GLD_MSR_PM,       {.hi=0,.lo=0x000000005}},
-       {       AC97_SB_GLD_MSR_PM,     {.hi=0,.lo=0x000000005}},
-       {0,{0,0}}
-};
-
-/*  5536 Clock Gating*/
-struct msrinit CS5536_CLOCK_GATING_TABLE[] = {
-/* MSR           Setting*/
-       {      GLIU_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000004}},
-       {      GLPCI_SB_GLD_MSR_PM,     {.hi=0,.lo=0x000000005}},
-       {      GLCP_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000004}},
-       {      MDD_SB_GLD_MSR_PM,       {.hi=0,.lo=0x050554111}}, /*  SMBus clock gating errata (PBZ 2226 & SiBZ 3977)*/
-       {      ATA_SB_GLD_MSR_PM,       {.hi=0,.lo=0x000000005}},
-       {      AC97_SB_GLD_MSR_PM,      {.hi=0,.lo=0x000000005}},
-       {0,{0,0}}
-};
-
-struct acpiinit {
-       unsigned short ioreg; 
-       unsigned long regdata;
-       unsigned short iolen;
-};
-
-struct acpiinit acpi_init_table[] = {
-       {ACPI_BASE+0x00, 0x01000000, 4},
-       {ACPI_BASE+0x08, 0, 4},
-       {ACPI_BASE+0x0C, 0, 4},
-       {ACPI_BASE+0x1C, 0, 4},
-       {ACPI_BASE+0x18, 0x0FFFFFFFF, 4},
-       {ACPI_BASE+0x00, 0x0000FFFF, 4},
-
-       {PM_SCLK, 0x000000E00, 4},
-       {PM_SED,  0x000004601, 4},
-       {PM_SIDD, 0x000008C02, 4},
-       {PM_WKD,  0x0000000A0, 4},
-       {PM_WKXD, 0x0000000A0, 4},
-       {0,0,0}
-};
-
-/* return 1 if we are a 5536-based system */
-static int is_5536(void){
-       msr_t msr;
-       msr = rdmsr(GLIU_SB_GLD_MSR_CAP);
-       msr.lo >>= 20;
-       printk_debug("is_5536: msr.lo is 0x%x(==5 means 5536)\n", msr.lo&0xf);
-       return ((msr.lo&0xf) == 5);
-}
-/* ***************************************************************************/
-/* **/
-/* *   pmChipsetInit*/
-/* **/
-/* *   Program ACPI LBAR and initialize ACPI registers.*/
-/* *  */
-/* **/
-/* *   Entry:*/
-/* *           None*/
-/* **/
-/* *   Exit:*/
-/* *           None*/
-/* **/
-/* *   Destroys:*/
-/* *           None*/
-/* **/
-/* ***************************************************************************/
-static void
-pmChipsetInit(void) {
-       unsigned long val = 0;
-       unsigned short port;
-
-       port =  (PMLogic_BASE + 0x010);
-       val =  0x0E00           ; /*  1ms*/
-       outl(val, port);
-
-       /*  PM_WKXD*/
-       /*  Make sure bits[3:0]=0000b to clear the*/
-       /*  saved Sx state*/
-       port =  (PMLogic_BASE + 0x034);
-       val =  0x0A0            ; /*  5ms*/
-       outl(val, port);
-       
-       /*  PM_WKD*/
-       port =  (PMLogic_BASE + 0x030);
-       outl(val, port);
-               
-       /*  PM_SED*/
-       port =  (PMLogic_BASE + 0x014);
-/*     mov             eax, 0x057642   ; 100ms, works*/
-       val =  0x04601          ; /*  5ms*/
-       outl(val, port);
-       
-       /*  PM_SIDD*/
-       port =  (PMLogic_BASE + 0x020);
-/*     mov             eax, 0x0AEC84   ; 200ms, works*/
-       val =  0x08C02          ; /*  10ms*/
-       outl(val, port);
-       
-       /*  GPIO24 OUT_AUX1 function is the external signal for 5535's vsb_working_aux*/
-       /*  which is de-asserted when 5535 enters Standby(S3 or S5) state.*/
-       /*  On Hawk, GPIO24 controls all voltage rails except Vmem and Vstandby.  This means*/
-       /*  GX2 will be fully de-powered if this control de-asserts in S3/S5.*/
-       /* */
-       /*  GPIO24 is setup in preChipsetInit for two reasons*/
-       /*  1. GPIO24 at reset defaults to disabled, since this signal is vsb_work_aux on*/
-       /*     Hawk it controls the FET's for all voltage rails except Vstanby & Vmem.*/
-       /*     BIOS needs to enable GPIO24 as OUT_AUX1 & OUTPUT_EN early so it is driven*/
-       /*     by 5535.*/
-       /*  2. Non-PM builds will require GPIO24 enabled for instant-off power button*/
-       /* */
-
-       /*  GPIO11 OUT_AUX1 function is the external signal for 5535's slp_clk_n which is asserted*/
-       /*  when 5535 enters Sleep(S1) state.*/
-       /*  On Hawk, GPIO11 is connected to control input of external clock generator*/
-       /*  for 14MHz, PCI, USB & LPC clocks.*/
-       /*  Programming of GPIO11 will be done by VSA PM code.  During VSA Init. BIOS writes*/
-       /*  PM Core Virual Register indicating if S1 Clocks should be On or Off. This is based*/
-       /*  on a Setup item.  We do not want to leave GPIO11 enabled because of a Hawk board*/
-       /*  problem.  With GPIO11 enabled in S3, something is back-driving GPIO11 causing it to*/
-       /*  float to 1.6-1.7V.*/
-
-}
-
-struct FLASH_DEVICE {
-       unsigned char fType;            /* Flash type: NOR or NAND */
-       unsigned char fInterface;       /* Flash interface: I/O or Memory */
-       unsigned long fMask;            /* Flash size/mask */
-};
-
-struct FLASH_DEVICE FlashInitTable[] = {
-       { FLASH_TYPE_NAND, FLASH_IF_MEM, FLASH_MEM_4K },        /* CS0, or Flash Device 0 */
-       { FLASH_TYPE_NONE, 0, 0 },      /* CS1, or Flash Device 1 */
-       { FLASH_TYPE_NONE, 0, 0 },      /* CS2, or Flash Device 2 */
-       { FLASH_TYPE_NONE, 0, 0 },      /* CS3, or Flash Device 3 */
-};
-
-#define FlashInitTableLen (sizeof(FlashInitTable)/sizeof(FlashInitTable[0]))
-
-uint32_t FlashPort[] = {
-       MDD_LBAR_FLSH0,
-       MDD_LBAR_FLSH1,
-       MDD_LBAR_FLSH2,
-       MDD_LBAR_FLSH3
-       };
-
-/***************************************************************************
- *
- *     ChipsetFlashSetup
- *
- *     Flash LBARs need to be setup before VSA init so the PCI BARs have
- *     correct size info.  Call this routine only if flash needs to be 
- *     configured (don't call it if you want IDE).
- *
- *     Entry:
- *     Exit:
- *     Destroys:
- *
- **************************************************************************/
-static void ChipsetFlashSetup(void)
-{
-       msr_t msr;
-       int i;
-       int numEnabled = 0;
-
-       printk_debug("ChipsetFlashSetup++\n");
-       for (i = 0; i < FlashInitTableLen; i++) {
-               if (FlashInitTable[i].fType != FLASH_TYPE_NONE) {
-                       printk_debug("Enable CS%d\n", i);
-                       /* we need to configure the memory/IO mask */
-                       msr = rdmsr(FlashPort[i]);
-                       msr.hi = 0;     /* start with the "enabled" bit clear */
-                       if (FlashInitTable[i].fType == FLASH_TYPE_NAND)
-                               msr.hi |= 0x00000002;
-                       else
-                               msr.hi &= ~0x00000002;
-                       if (FlashInitTable[i].fInterface == FLASH_IF_MEM)
-                               msr.hi |= 0x00000004;
-                       else
-                               msr.hi &= ~0x00000004;
-                       msr.hi |= FlashInitTable[i].fMask;
-                       printk_debug("WRMSR(0x%08X, %08X_%08X)\n", FlashPort[i], msr.hi, msr.lo);
-                       wrmsr(FlashPort[i], msr);
-
-                       /* now write-enable the device */
-                       msr = rdmsr(MDD_NORF_CNTRL);
-                       msr.lo |= (1 << i);
-                       printk_debug("WRMSR(0x%08X, %08X_%08X)\n", MDD_NORF_CNTRL, msr.hi, msr.lo);
-                       wrmsr(MDD_NORF_CNTRL, msr);
-
-                       /* update the number enabled */
-                       numEnabled++;
-               }
-       }
-
-       /* enable the flash */
-       if (0 != numEnabled) {
-               msr = rdmsr(MDD_PIN_OPT);
-               msr.lo &= ~1; /* PIN_OPT_IDE */
-               printk_debug("WRMSR(0x%08X, %08X_%08X)\n", MDD_PIN_OPT, msr.hi, msr.lo);
-               wrmsr(MDD_PIN_OPT, msr);
-       }
-       printk_debug("ChipsetFlashSetup--\n");
-
-}
-
-
-/* ***************************************************************************/
-/* **/
-/* *   ChipsetGeodeLinkInit*/
-/* *   Handle chipset specific GeodeLink settings here. */
-/* *   Called from GeodeLink init code.*/
-/* **/
-/* *   Entry:*/
-/* *   Exit:*/
-/* *   Destroys: GS*/
-/* **/
-/* ***************************************************************************/
-static void 
-ChipsetGeodeLinkInit(void){
-       msr_t msr;
-       unsigned long msrnum;
-       unsigned long totalmem;
-
-       if (is_5536())
-               return;
-       /*  SWASIF for A1 DMA */
-       /*  Set all memory to  "just above systop" PCI so DMA will work*/
-       /*  check A1*/
-       msrnum = MSR_SB_GLCP + 0x17;
-       msr = rdmsr(msrnum);
-       if ((msr.lo&0xff) == 0x11)
-               return;
-
-       totalmem = (sizeram() << 20) - 1;
-       totalmem >>= 12; 
-       totalmem = ~totalmem;
-       totalmem &= 0xfffff;
-       msr.lo = totalmem;
-       msr.hi = 0x20000000;                            /*  Port 1 (PCI)*/
-       msrnum = MSR_SB_GLIU + 0x20;            /*  */;
-       wrmsr(msrnum, msr);
-}
-
-void
-chipsetinit (struct northbridge_amd_lx_config *nb){
-       msr_t msr;
-       struct msrinit *csi;
-       int i;
-       unsigned long msrnum;
-
-       outb( P80_CHIPSET_INIT, 0x80);
-       ChipsetGeodeLinkInit();
-#if 0
-       /* we hope NEVER to be in linuxbios when S3 resumes 
-       if (! IsS3Resume()) */
-       {
-               struct acpiinit *aci = acpi_init_table;
-               while (aci->ioreg){
-                       if (aci->iolen == 2) {
-                               outw(aci->regdata, aci->ioreg);
-                               inw(aci->ioreg);
-                       } else {
-                               outl(aci->regdata, aci->ioreg);
-                               inl(aci->ioreg);
-                       }
-               }
-
-               pmChipsetInit();
-       }
-#endif
-
-
-       if (!is_5536()) {
-               /*  Setup USB. Need more details. #118.18*/
-               msrnum = MSR_SB_USB1 + 8;
-               msr.lo =  0x00012090;
-               msr.hi = 0;
-               wrmsr(msrnum, msr);
-               msrnum = MSR_SB_USB2 + 8;
-               wrmsr(msrnum, msr);
-       }
-       
-       /* set hd IRQ */
-       outl    (GPIOL_2_SET, GPIOL_INPUT_ENABLE);
-       outl    (GPIOL_2_SET, GPIOL_IN_AUX1_SELECT);
-
-       /*  Allow IO read and writes during a ATA DMA operation.*/
-       /*   This could be done in the HD rom but do it here for easier debugging.*/
-       
-       msrnum = ATA_SB_GLD_MSR_ERR;
-       msr = rdmsr(msrnum);
-       msr.lo &= ~0x100;
-       wrmsr(msrnum, msr);
-
-       /*  Enable Post Primary IDE.*/
-       msrnum = GLPCI_SB_CTRL;
-       msr = rdmsr(msrnum);
-       msr.lo |=  GLPCI_CRTL_PPIDE_SET;
-       wrmsr(msrnum, msr);
-
-
-       /*  Set up Master Configuration Register*/
-       /*  If 5536, use same master config settings as 5535, except for OHCI MSRs*/
-       if (is_5536()) 
-               i = 2;
-       else
-               i = 0;
-
-       csi = &SB_MASTER_CONF_TABLE[i];
-       for(; csi->msrnum; csi++){
-               msr.lo = csi->msr.lo;
-               msr.hi = csi->msr.hi;
-               wrmsr(csi->msrnum, msr); // MSR - see table above
-       }
-
-
-       /*  Flash Setup*/
-       printk_err("%sDOING ChipsetFlashSetup()!!!!!!!!!!!!!!!!!!\n", nb->setupflash? " " : "NOT");
-       if (nb->setupflash)
-               ChipsetFlashSetup();
-
-
-
-       /* */
-       /*  Set up Hardware Clock Gating*/
-       /* */
-       /* if (getnvram(TOKEN_SB_CLK_GATE) != TVALUE_DISABLE) */
-       {
-               if (is_5536())
-                       csi = CS5536_CLOCK_GATING_TABLE;
-               else
-                       csi = CS5535_CLOCK_GATING_TABLE;
-
-               for(; csi->msrnum; csi++){
-                       msr.lo = csi->msr.lo;
-                       msr.hi = csi->msr.hi;
-                       wrmsr(csi->msrnum, msr);        // MSR - see table above
-               }
-       }
-
-}
index af9e9fef42775abb883957b3252782028d1f7aa8..038ee8d532040edfda6c12ccf9e09341cfcd9279 100644 (file)
@@ -1,33 +1,16 @@
+/*
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+*/
+
 #include <arch/io.h>
 #include <stdint.h>
 #include <cpu/amd/vr.h>
 #include <console/console.h>
 
-/*
- * Write to a Virtual Register
- * AX = Class/Index
- * CX = data to write
- */
-void vrWrite(uint16_t wClassIndex, uint16_t wData)
-{
-       outl(((uint32_t) VR_UNLOCK << 16) | wClassIndex, VRC_INDEX);
-       outw(wData, VRC_DATA);
-}
 
  /*
- * Read from a Virtual Register
- * AX = Class/Index
- * Returns a 16-bit word of data
- */
-uint16_t vrRead(uint16_t wClassIndex)
-{
-       uint16_t wData;
-       outl(((uint32_t) VR_UNLOCK << 16) | wClassIndex, VRC_INDEX);
-       wData = inw(VRC_DATA);
-       return wData;
-}
-
-/*
  * This function mirrors the Graphics_Init routine in GeodeROM.
  */
 void graphics_init(void)
@@ -40,7 +23,7 @@ void graphics_init(void)
        /* Call SoftVG with the main configuration parameters. */
        /* NOTE: SoftVG expects the memory size to be given in 2MB blocks */
        
-       wClassIndex = (VRC_VG <<  8) + VG_MEM_SIZE;
+       wClassIndex = (VRC_VG <<  8) + VG_CONFIG;
        
        /*
         * Graphics Driver Enabled (13)                         0, NO (lets BIOS controls the GP)
@@ -52,12 +35,12 @@ void graphics_init(void)
         * PLL Reference Clock Bypass(0)                        0, Default
         */
 
-       /*       video RAM has to be given in 2MB chunks
+       /* Video RAM has to be given in 2MB chunks
         *   the value is read @ 7:1 (value in 7:0 looks like /2)
         *   so we can add the real value in megabytes
         */
         
-       wData =  0x0800 | (CONFIG_VIDEO_MB & VG_MEM_MASK);
+       wData =  VG_CFG_DRIVER | VG_CFG_PRIORITY | VG_CFG_DSCRT | (CONFIG_VIDEO_MB & VG_MEM_MASK);
        vrWrite(wClassIndex, wData);
        
        res = vrRead(wClassIndex);
index b014118da84c2103ae170044987f732c475c839b..88dfe12523313d1b8eb2e161319a21307fae63bf 100644 (file)
@@ -1,3 +1,9 @@
+/*
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+*/
+
 #include <console/console.h>
 #include <arch/io.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <bitops.h>
-#include "chip.h"
-#include "northbridge.h"
 #include <cpu/cpu.h>
 #include <cpu/amd/lxdef.h>
 #include <cpu/x86/msr.h>
 #include <cpu/x86/cache.h>
 #include <cpu/amd/vr.h>
+#include "chip.h"
+#include "northbridge.h"
 
 
 /* here is programming for the various MSRs.*/
 
 extern void graphics_init(void);
 extern void cpubug(void);
+extern void chipsetinit(void);
+extern void print_conf(void);
+extern uint32_t get_systop(void);
 
 void northbridge_init_early(void);
-void chipsetinit(struct northbridge_amd_lx_config *nb);
 void setup_realmode_idt(void);
 void do_vsmbios(void);
 
@@ -97,309 +105,42 @@ struct msr_defaults {
 /* todo: add a resource record. We don't do this here because this may be called when 
   * very little of the platform is actually working.
   */
-int
-sizeram(void)
+int sizeram(void)
 {
        msr_t msr;
        int sizem = 0;
        unsigned short dimm;
 
-       msr = rdmsr(0x20000018);
-       printk_debug("sizeram: %08x:%08x\n", msr.hi, msr.lo);
+       msr = rdmsr(MC_CF07_DATA);
+       printk_debug("sizeram: _MSR MC_CF07_DATA: %08x:%08x\n", msr.hi, msr.lo);
 
        /* dimm 0 */
        dimm = msr.hi;
-       sizem = (1 << ((dimm >> 12)-1)) * 8;
-
+       /* installed? */
+       if ((dimm & 7) != 7){
+               sizem = 4 << ((dimm >> 12) & 0x0F);
+       }
 
        /* dimm 1*/
        dimm = msr.hi >> 16;
        /* installed? */
-       if ((dimm & 7) != 7)
-               sizem += (1 << ((dimm >> 12)-1)) * 8;
+       if ((dimm & 7) != 7){
+               sizem += 4 << ((dimm >> 12) & 0x0F);
+       }
 
-       printk_debug("sizeram: sizem 0x%x\n", sizem);
+       printk_debug("sizeram: sizem 0x%xMB\n", sizem);
        return sizem;
 }
 
-/* note that dev is NOT used -- yet */
-static void irq_init_steering(struct device *dev, uint16_t irq_map) {
-       /* Set up IRQ steering */
-       uint32_t pciAddr = 0x80000000 | (CHIPSET_DEV_NUM << 11) | 0x5C;
-
-       printk_debug("%s(%08X [%08X], %04X)\n", __FUNCTION__, dev, pciAddr, irq_map);
-
-       /* The IRQ steering values (in hex) are effectively dcba, where:
-        *    <a> represents the IRQ for INTA, 
-        *    <b> represents the IRQ for INTB,
-        *    <c> represents the IRQ for INTC, and
-        *    <d> represents the IRQ for INTD.
-        * Thus, a value of irq_map = 0xAA5B translates to:
-        *    INTA = IRQB (IRQ 11)
-        *    INTB = IRQ5 (IRQ 5)
-        *    INTC = IRQA (IRQ 10)
-        *    INTD = IRQA (IRQ 10)
-        */
-       outl(pciAddr & ~3, 0xCF8);
-       outl(irq_map,      0xCFC);
-}
 
 
-/*
- * setup_lx_cache
- *
- * Returns the amount of memory (in KB) available to the system.  This is the 
- * total amount of memory less the amount of memory reserved for SMM use.
- *
- */ 
-static int
-setup_lx_cache(void)
-{
-       msr_t msr;
-       unsigned long long val;
-       int sizekbytes, sizereg;
-
-       sizekbytes = sizeram() * 1024;
-       printk_debug("setup_lx_cache: enable for %d KB\n", sizekbytes);
-       /* build up the rconf word. */
-       /* the SYSTOP bits 27:8 are actually the top bits from 31:12. Book fails to say that */
-       /* set romrp */
-       val = ((unsigned long long) ROM_PROPERTIES) << 56;
-       /* make rom base useful for 1M roms */
-       /* Flash base address -- sized for 1M for now*/
-       val |= ((unsigned long long) 0xfff00)<<36;
-       /* set the devrp properties */
-       val |= ((unsigned long long) DEVICE_PROPERTIES) << 28;
-       /* Take our TOM, RIGHT shift 12, since it page-aligned, then LEFT-shift 8 for reg. */
-       /* yank off memory for the SMM handler */
-       sizekbytes -= SMM_SIZE;
-       sizereg = sizekbytes;
-       sizereg >>= 2;
-       sizereg <<= 8;
-       val |= sizereg;
-       val |= RAM_PROPERTIES;
-       msr.lo = val;
-       msr.hi = (val >> 32);
-       
-       // GX3
-       //msr.hi = 0x04FFFC02;
-       //msr.lo = 0x1077BE00;
-       
-       //sizekbytes = 122616;
-
-       printk_debug("msr 0x%08X will be set to %08x:%08x\n", CPU_RCONF_DEFAULT, msr.hi, msr.lo);
-       wrmsr(CPU_RCONF_DEFAULT, msr);
-
-       enable_cache();
-       wbinvd();
-       return sizekbytes;
-}
-
-/* we have to do this here. We have not found a nicer way to do it */
-void
-setup_lx(void)
-{
-
-       unsigned long tmp, tmp2;
-       msr_t msr;
-       unsigned long size_kb, membytes;
-
-       size_kb = setup_lx_cache();
-
-#if 0  // andrei: this is done in northbridge.c SMMGL0Init and SystemInit!
-       membytes = size_kb * 1024;
-       /* NOTE! setup_lx_cache returns the SIZE OF RAM - RAMADJUST!
-         * so it is safe to use. You should NOT at this point call     
-         * sizeram() directly. 
-         */
-
-       /* we need to set 0x10000028 and 0x40000029 */
-       /*
-        * These two descriptors cover the range from 1 MB (0x100000) to 
-        * SYSTOP (a.k.a. TOM, or Top of Memory)
-        */
-
-
-       /* fixme: SMM MSR 0x10000026 and 0x400000023 */
-       /* calculate the OFFSET field */
-       tmp = membytes - SMM_OFFSET;
-       tmp >>= 12;
-       tmp <<= 8;
-       tmp |= 0x20000000;
-       tmp |= (SMM_OFFSET >> 24);
-
-       /* calculate the PBASE and PMASK fields */
-       tmp2 = (SMM_OFFSET << 8) & 0xFFF00000; /* shift right 12 then left 20  == left 8 */
-       tmp2 |= (((~(SMM_SIZE * 1024) + 1) >> 12) & 0xfffff);
-       printk_debug("MSR 0x%x is now 0x%x:0x%x\n", 0x10000026, tmp, tmp2);
-       msr.hi = tmp;
-       msr.lo = tmp2;
-       wrmsr(0x10000026, msr);
-#endif
-}
-
 static void enable_shadow(device_t dev)
 {
 }
 
-void print_conf(void) {
-       int i;
-       unsigned long iol;
-       msr_t msr;
-       
-       int cpu_msr_defs[] =  { L2_CONFIG_MSR, CPU_IM_CONFIG, 
-                                                       CPU_DM_CONFIG0, CPU_DM_CONFIG1, CPU_DM_PFLOCK, CPU_RCONF_DEFAULT,
-                                                       CPU_RCONF_BYPASS, CPU_RCONF_A0_BF, CPU_RCONF_C0_DF, CPU_RCONF_E0_FF,
-                                                       CPU_RCONF_SMM, CPU_RCONF_DMM, GLCP_DELAY_CONTROLS, GL_END
-                                                       };
-
-       int gliu0_msr_defs[] = {MSR_GLIU0_BASE1, MSR_GLIU0_BASE2, MSR_GLIU0_BASE3, MSR_GLIU0_BASE4, MSR_GLIU0_BASE5, MSR_GLIU0_BASE6,
-                                                        GLIU0_P2D_BMO_0, GLIU0_P2D_BMO_1, MSR_GLIU0_SYSMEM,
-                                                        GLIU0_P2D_RO_0, GLIU0_P2D_RO_1, GLIU0_P2D_RO_2, MSR_GLIU0_SHADOW,
-                                                        GLIU0_IOD_BM_0, GLIU0_IOD_BM_1, GLIU0_IOD_BM_2,
-                                                        GLIU0_IOD_SC_0, GLIU0_IOD_SC_1, GLIU0_IOD_SC_2, GLIU0_IOD_SC_3, GLIU0_IOD_SC_4, GLIU0_IOD_SC_5,
-                                                        GLIU0_GLD_MSR_COH, GL_END
-                                                       };
-
-       int gliu1_msr_defs[] = {MSR_GLIU1_BASE1, MSR_GLIU1_BASE2, MSR_GLIU1_BASE3, MSR_GLIU1_BASE4, MSR_GLIU1_BASE5, MSR_GLIU1_BASE6,
-                                                        MSR_GLIU1_BASE7, MSR_GLIU1_BASE8, MSR_GLIU1_BASE9, MSR_GLIU1_BASE10,
-                                                        GLIU1_P2D_R_0, GLIU1_P2D_R_1, GLIU1_P2D_R_2, GLIU1_P2D_R_3, MSR_GLIU1_SHADOW,
-                                                        GLIU1_IOD_BM_0, GLIU1_IOD_BM_1, GLIU1_IOD_BM_2,
-                                                        GLIU1_IOD_SC_0, GLIU1_IOD_SC_1, GLIU1_IOD_SC_2, GLIU1_IOD_SC_3,
-                                                        GLIU1_GLD_MSR_COH, GL_END
-                                                       };
-
-       int rconf_msr[] = { CPU_RCONF0, CPU_RCONF1, CPU_RCONF2, CPU_RCONF3, CPU_RCONF4,
-                                               CPU_RCONF5, CPU_RCONF6, CPU_RCONF7, GL_END
-                                                       };
-                                                       
-       int cs5536_msr[] = { MDD_LBAR_GPIO, MDD_LBAR_FLSH0, MDD_LBAR_FLSH1, MDD_LEG_IO, MDD_PIN_OPT,
-                                                MDD_IRQM_ZLOW, MDD_IRQM_ZHIGH, MDD_IRQM_PRIM, GL_END
-                                                       };
-                                                       
-       int pci_msr[] = { GLPCI_CTRL, GLPCI_ARB, GLPCI_REN, GLPCI_A0_BF, GLPCI_C0_DF, GLPCI_E0_FF,
-                                         GLPCI_RC0, GLPCI_RC1, GLPCI_RC2, GLPCI_RC3, GLPCI_EXT_MSR, GLPCI_SPARE,
-                                                GL_END
-                                                       };
-
-       int dma_msr[] =  { MDD_DMA_MAP, MDD_DMA_SHAD1, MDD_DMA_SHAD2, MDD_DMA_SHAD3, MDD_DMA_SHAD4,
-                                                       MDD_DMA_SHAD5, MDD_DMA_SHAD6, MDD_DMA_SHAD7, MDD_DMA_SHAD8,
-                                                       MDD_DMA_SHAD9, GL_END
-                                                       };
-
-
-       printk_debug("---------- CPU ------------\n");
-
-       for(i = 0; cpu_msr_defs[i] != GL_END; i++) {
-               msr = rdmsr(cpu_msr_defs[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", cpu_msr_defs[i], msr.hi, msr.lo);
-       }
-
-       printk_debug("---------- GLIU 0 ------------\n");
-
-       for(i = 0; gliu0_msr_defs[i] != GL_END; i++) {
-               msr = rdmsr(gliu0_msr_defs[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", gliu0_msr_defs[i], msr.hi, msr.lo);
-       }
-
-       printk_debug("---------- GLIU 1 ------------\n");
-
-       for(i = 0; gliu1_msr_defs[i] != GL_END; i++) {
-               msr = rdmsr(gliu1_msr_defs[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", gliu1_msr_defs[i], msr.hi, msr.lo);
-       }
-
-       printk_debug("---------- RCONF ------------\n");
-
-       for(i = 0; rconf_msr[i] != GL_END; i++) {
-               msr = rdmsr(rconf_msr[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", rconf_msr[i], msr.hi, msr.lo);
-       }
-
-       printk_debug("---------- VARIA ------------\n");
-       msr = rdmsr(0x51300010);
-       printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", 0x51300010, msr.hi, msr.lo);
-
-       msr = rdmsr(0x51400015);
-       printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", 0x51400015, msr.hi, msr.lo);
-
-       printk_debug("---------- DIVIL IRQ ------------\n");
-       msr = rdmsr(MDD_IRQM_YLOW);
-       printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", MDD_IRQM_YLOW, msr.hi, msr.lo);
-       msr = rdmsr(MDD_IRQM_YHIGH);
-       printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", MDD_IRQM_YHIGH, msr.hi, msr.lo);
-       msr = rdmsr(MDD_IRQM_ZLOW);
-       printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", MDD_IRQM_ZLOW, msr.hi, msr.lo);
-       msr = rdmsr(MDD_IRQM_ZHIGH);
-       printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", MDD_IRQM_ZHIGH, msr.hi, msr.lo);
-
-
-       printk_debug("---------- PCI ------------\n");
-
-       for(i = 0; pci_msr[i] != GL_END; i++) {
-               msr = rdmsr(pci_msr[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", pci_msr[i], msr.hi, msr.lo);
-       }
-
-       printk_debug("---------- LPC/UART DMA ------------\n");
-
-       for(i = 0; dma_msr[i] != GL_END; i++) {
-               msr = rdmsr(dma_msr[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", dma_msr[i], msr.hi, msr.lo);
-       }
-
-       printk_debug("---------- CS5536 ------------\n");
-
-       for(i = 0; cs5536_msr[i] != GL_END; i++) {
-               msr = rdmsr(cs5536_msr[i]);
-               printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", cs5536_msr[i], msr.hi, msr.lo);
-       }
-       
-       iol = inl(GPIOL_INPUT_ENABLE);
-       printk_debug("IOR 0x%08X is now 0x%08X\n", GPIOL_INPUT_ENABLE, iol);
-       iol = inl(GPIOL_EVENTS_ENABLE);
-       printk_debug("IOR 0x%08X is now 0x%08X\n", GPIOL_EVENTS_ENABLE, iol);
-       iol = inl(GPIOL_INPUT_INVERT_ENABLE);
-       printk_debug("IOR 0x%08X is now 0x%08X\n", GPIOL_INPUT_INVERT_ENABLE, iol);
-       iol = inl(GPIO_MAPPER_X);
-       printk_debug("IOR 0x%08X is now 0x%08X\n", GPIO_MAPPER_X, iol);
-       
-}
-
-static void enable_L2_cache(void) {
-       msr_t msr;
-
-       /* Instruction Memory Configuration register
-        * set EBE bit, required when L2 cache is enabled
-        */ 
-       msr = rdmsr(CPU_IM_CONFIG);
-       msr.lo |= 0x400;
-       wrmsr(CPU_IM_CONFIG, msr);
-       
-       /* Data Memory Subsystem Configuration register
-        * set EVCTONRPL bit, required when L2 cache is enabled in victim mode
-        */
-       msr = rdmsr(CPU_DM_CONFIG0);
-       msr.lo |= 0x4000;
-       wrmsr(CPU_DM_CONFIG0, msr);
-
-       /* invalidate L2 cache */
-       msr.hi = 0x00;
-       msr.lo = 0x10;
-       wrmsr(L2_CONFIG_MSR, msr);
-
-       /* Enable L2 cache */   
-       msr.hi = 0x00;
-       msr.lo = 0x0f;  
-       wrmsr(L2_CONFIG_MSR, msr);
-       
-       printk_debug("L2 cache enabled\n");
-}
-
 static void northbridge_init(device_t dev) 
 {
        //msr_t msr;
-       struct northbridge_amd_lx_config *nb = (struct northbridge_amd_lx_config *)dev->chip_info;
 
        printk_spew(">> Entering northbridge.c: %s\n", __FUNCTION__);
        
@@ -412,8 +153,6 @@ static void northbridge_init(device_t dev)
        //msr.hi |= 0x3;
        //msr.lo |= 0x30000;
        
-// not needed (also irq steering is in legacy vsm so it wouldnt work either)
-//     irq_init_steering(dev, nb->irqmap);
 
        //printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", MSR_GLIU0_SHADOW, msr.hi, msr.lo);
        //printk_debug("MSR 0x%08X is now 0x%08X:0x%08X\n", MSR_GLIU1_SHADOW, msr.hi, msr.lo);
@@ -521,7 +260,7 @@ static void pci_domain_set_resources(device_t dev)
                /* Report the memory regions */
                idx = 10;
                ram_resource(dev, idx++, 0, 640);
-               ram_resource(dev, idx++, 1024, ((sizeram() - CONFIG_VIDEO_MB) * 1024) - SMM_SIZE - 1024);
+               ram_resource(dev, idx++, 1024, (get_systop()- 0x100000)/1024 ); // Systop - 1 MB -> KB
        }
 
        assign_resources(&dev->link[0]);
@@ -529,25 +268,23 @@ static void pci_domain_set_resources(device_t dev)
 
 static void pci_domain_enable(device_t dev)
 {
-       struct northbridge_amd_lx_config *nb = (struct northbridge_amd_lx_config *)dev->chip_info;
 
        printk_spew(">> Entering northbridge.c: %s\n", __FUNCTION__);
 
        // do this here for now -- this chip really breaks our device model
-       enable_L2_cache();
        northbridge_init_early();
        cpubug();
-       chipsetinit(nb);
-       setup_lx();
+       chipsetinit();
+
        setup_realmode_idt();
 
        printk_debug("Before VSA:\n");
-       print_conf();
+       // print_conf();
 
        do_vsmbios();   // do the magic stuff here, so prepare your tambourine ;)
        
        printk_debug("After VSA:\n");
-       print_conf();
+       // print_conf();
 
        graphics_init();
        pci_set_method(dev);
index 21d2736bcbe017cb5da41812688b7ac3582a0411..52fab514af3ed9f031fcf433deba2252bea73760 100644 (file)
@@ -1,3 +1,9 @@
+/*
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+*/
+
 #include <console/console.h>
 #include <arch/io.h>
 #include <stdint.h>
@@ -13,7 +19,6 @@
 #include <cpu/x86/msr.h>
 #include <cpu/x86/cache.h>
 
-/* put this here for now, we are not sure where it belongs */
 
 struct gliutable {
        unsigned long desc_name;
@@ -36,9 +41,10 @@ struct gliutable gliu1table[] = {
        {.desc_name=MSR_GLIU1_BASE1,.desc_type=  BM,.hi=  MSR_GL0 + 0x0,.lo=  0x0FFF80},        /*  0-7FFFF to MC*/
        {.desc_name=MSR_GLIU1_BASE2,.desc_type=  BM,.hi=  MSR_GL0 + 0x0,.lo= (0x80 << 20) +0x0FFFE0},   /*  80000-9ffff to Mc*/
        {.desc_name=MSR_GLIU1_SHADOW,.desc_type=  SC_SHADOW,.hi=  MSR_GL0 + 0x0,.lo=  0x03}, /*  C0000-Fffff split to MC and PCI (sub decode)*/
-       {.desc_name=MSR_GLIU1_SYSMEM,.desc_type=  R_SYSMEM,.hi=  MSR_GL0,.lo=  0x0},            /*  Cat0xc and fix dynamicly.*/
-       {.desc_name=MSR_GLIU1_SMM,.desc_type=  BM_SMM,.hi=  MSR_GL0,.lo=  0x0},                 /*  Cat0xc and fix dynamicly.*/
+       {.desc_name=MSR_GLIU1_SYSMEM,.desc_type=  R_SYSMEM,.hi=  MSR_GL0,.lo=  0x0},            /*      Catch and fix dynamicly.*/
+       {.desc_name=MSR_GLIU1_SMM,.desc_type=  BM_SMM,.hi=      MSR_GL0,.lo=  0x0},                     /*      Catch and fix dynamicly.*/
        {.desc_name=GLIU1_GLD_MSR_COH,.desc_type= OTHER,.hi= 0x0,.lo= GL1_GLIU0},
+       {.desc_name=MSR_GLIU1_FPU_TRAP,.desc_type=  SCIO,.hi=  (GL1_GLCP << 29) + 0x0,.lo=  0x033000F0},        /*  FooGlue FPU 0xF0*/
        {.desc_name=GL_END,.desc_type= GL_END,.hi= 0x0,.lo= 0x0},
 };
 
@@ -51,54 +57,36 @@ struct msrinit {
 
 struct msrinit ClockGatingDefault [] = {
        {GLIU0_GLD_MSR_PM,      {.hi=0x00,.lo=0x0005}},
-                       /*  MC must stay off in SDR mode. It is turned on in CPUBug??? lotus #77.142*/
-       {MC_GLD_MSR_PM,         {.hi=0x00,.lo=0x0000}},
-       {GLIU1_GLD_MSR_PM,      {.hi=0x00,.lo=0x0005}},
-       {VG_GLD_MSR_PM,         {.hi=0x00,.lo=0x0000}},                 /*  lotus #77.163*/
+       {MC_GLD_MSR_PM,         {.hi=0x00,.lo=0x0001}},
+       {VG_GLD_MSR_PM,         {.hi=0x00,.lo=0x0015}},
        {GP_GLD_MSR_PM,         {.hi=0x00,.lo=0x0001}},
-       /*{DF_GLD_MSR_PM,               {.hi=0x00,.lo=0x0155}},*/ //GX3 
-       {GLCP_GLD_MSR_PM,       {.hi=0x00,.lo=0x0015}},
+       {DF_GLD_MSR_PM,         {.hi=0x00,.lo=0x0555}},
+       {GLIU1_GLD_MSR_PM,      {.hi=0x00,.lo=0x0005}},
+       {GLCP_GLD_MSR_PM,       {.hi=0x00,.lo=0x0014}},
        {GLPCI_GLD_MSR_PM,      {.hi=0x00,.lo=0x0015}},
-       /*{FG_GLD_MSR_PM,               {.hi=0x00,.lo=0x0000}}, */              /* Always on*/ //GX3
+       {VIP_GLD_MSR_PM,        {.hi=0x00,.lo=0x0005}},
+       {AES_GLD_MSR_PM,        {.hi=0x00,.lo=0x0015}},
+       {CPU_BC_PMODE_MSR,      {.hi=0x00,.lo=0x70303}},
        {0xffffffff,                            {0xffffffff, 0xffffffff}},
 };
-       /*  All On*/
-struct msrinit ClockGatingAllOn[] = {
-       {GLIU0_GLD_MSR_PM,      {.hi=0x00,.lo=0x0FFFFFFFF}},
-       {MC_GLD_MSR_PM,         {.hi=0x00,.lo=0x0FFFFFFFF}},
-       {GLIU1_GLD_MSR_PM,      {.hi=0x00,.lo=0x0FFFFFFFF}},
-       {VG_GLD_MSR_PM,         {.hi=0x00, .lo=0x00}},
-       {GP_GLD_MSR_PM,         {.hi=0x00,.lo=0x000000001}},
-       /*{DF_GLD_MSR_PM,               {.hi=0x00,.lo=0x0FFFFFFFF}}, */ //GX3
-       {GLCP_GLD_MSR_PM,       {.hi=0x00,.lo=0x0FFFFFFFF}},
-       {GLPCI_GLD_MSR_PM,      {.hi=0x00,.lo=0x0FFFFFFFF}},
-       /*{FG_GLD_MSR_PM,               {.hi=0x00,.lo=0x0000}}, */ //GX3
-       {0xffffffff,                            {0xffffffff, 0xffffffff}},
-};
 
-       /*  Performance*/
-struct msrinit ClockGatingPerformance[] = {
-       {VG_GLD_MSR_PM,         {.hi=0x00,.lo=0x0000}},         /*  lotus #77.163*/
-       {GP_GLD_MSR_PM,         {.hi=0x00,.lo=0x0001}},
-       /*{DF_GLD_MSR_PM,               {.hi=0x00,.lo=0x0155}}, */ //GX3
-       {GLCP_GLD_MSR_PM,       {.hi=0x00,.lo=0x0015}},
-       {0xffffffff,                            {0xffffffff, 0xffffffff}},
-};
 /* */
 /*  SET GeodeLink PRIORITY*/
 /* */
 struct msrinit GeodeLinkPriorityTable [] = {
-       {CPU_GLD_MSR_CONFIG,            {.hi=0x00,.lo=0x0220}}, /*  CPU Priority.*/
-       /*{DF_GLD_MSR_MASTER_CONF,      {.hi=0x00,.lo=0x0000}},*/       /*  DF Priority.*/              //GX3
-       {VG_GLD_MSR_CONFIG,             {.hi=0x00,.lo=0x0720}}, /*  VG Primary and Secondary Priority.*/
-       {GP_GLD_MSR_CONFIG,             {.hi=0x00,.lo=0x0010}}, /*  Graphics Priority.*/
-       {GLPCI_GLD_MSR_CONFIG,          {.hi=0x00,.lo=0x0027}}, /*  GLPCI Priority + PID*/
-       {GLCP_GLD_MSR_CONF,             {.hi=0x00,.lo=0x0001}}, /*  GLCP Priority + PID*/
-       {VIP_GLD_MSR_CONFIG,            {.hi=0x00,.lo=0x0622}}, /*  VIP PID*/
-       {AES_GLD_MSR_CONFIG,            {.hi=0x00,.lo=0x0013}}, /*  AES PID*/
+       {CPU_GLD_MSR_CONFIG,            {.hi=0x00,.lo=0x0220}},
+       {DF_GLD_MSR_MASTER_CONF,        {.hi=0x00,.lo=0x0000}},
+       {VG_GLD_MSR_CONFIG,                     {.hi=0x00,.lo=0x0720}},
+       {GP_GLD_MSR_CONFIG,                     {.hi=0x00,.lo=0x0010}},
+       {GLPCI_GLD_MSR_CONFIG,          {.hi=0x00,.lo=0x0017}},
+       {GLCP_GLD_MSR_CONF,                     {.hi=0x00,.lo=0x0001}},
+       {VIP_GLD_MSR_CONFIG,            {.hi=0x00,.lo=0x0622}},
+       {AES_GLD_MSR_CONFIG,            {.hi=0x00,.lo=0x0013}},
        {0x0FFFFFFFF,                   {0x0FFFFFFFF, 0x0FFFFFFFF}},    /*  END*/
 };
 
+extern int sizeram(void);
+
 static void
 writeglmsr(struct gliutable *gl){
        msr_t msr;
@@ -106,10 +94,7 @@ writeglmsr(struct gliutable *gl){
        msr.lo = gl->lo;
        msr.hi = gl->hi;
        wrmsr(gl->desc_name, msr);      // MSR - see table above
-       // printk_debug("%s: write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); //GX3
-       /* they do this, so we do this */
-       msr = rdmsr(gl->desc_name);
-       // printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); // GX3
+       printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo); // GX3
 }
 
 static void
@@ -124,14 +109,8 @@ ShadowInit(struct gliutable *gl)
        }
 }
 
-/* NOTE: transcribed from assembly code. There is the usual redundant assembly nonsense in here. 
-  * CLEAN ME UP
-   */
-/* yes, this duplicates later code, but it seems that is how they want it done. 
-  */
 extern int sizeram(void);
-static void
-SysmemInit(struct gliutable *gl)
+static void SysmemInit(struct gliutable *gl)
 {
        msr_t msr;
        int sizembytes, sizebytes;
@@ -141,51 +120,51 @@ SysmemInit(struct gliutable *gl)
         * system. We will adjust for SMM now and Frame Buffer later.
         */
        sizembytes = sizeram();
-       printk_debug("%s: enable for %dm bytes\n", __FUNCTION__, sizembytes);
+       printk_debug("%s: enable for %dMBytes\n", __FUNCTION__, sizembytes);
        sizebytes = sizembytes << 20;
 
-       sizebytes -= ((SMM_SIZE)<<10);
+       sizebytes -= ((SMM_SIZE * 1024) + 1);
        printk_debug("usable RAM: %d bytes\n", sizebytes);
 
+       /* 20 bit address The bottom 12 bits go into bits 20-31 in msr.lo
+        The top 8 bits go into 0-7 of msr.hi. */
+       sizebytes--;
        msr.hi = (gl->hi & 0xFFFFFF00) | (sizebytes >> 24);
-       /* set up sizebytes to fit into msr.lo */
-       sizebytes <<= 8; /* what? well, we want bits 23:12 in bits 31:20. */
+       sizebytes <<= 8;                /* move bits 23:12 in bits 31:20. */
        sizebytes &= 0xfff00000;
-       sizebytes |= 0x100;
+       sizebytes |= 0x100;             /* start at 1MB */
        msr.lo = sizebytes;
 
        wrmsr(gl->desc_name, msr);      // MSR - see table above
-       msr = rdmsr(gl->desc_name);
-       /* printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, 
-                               gl->desc_name, msr.hi, msr.lo); */ // GX3       
+       printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__,
+                               gl->desc_name, msr.hi, msr.lo);
 }
 
-static void
-SMMGL0Init(struct gliutable *gl) {
+static void SMMGL0Init(struct gliutable *gl) {
        msr_t msr;
        int sizebytes = sizeram()<<20;
        long offset;
 
-       sizebytes -= ((SMM_SIZE)<<10);
+       sizebytes -= (SMM_SIZE*1024);
 
        printk_debug("%s: %d bytes\n", __FUNCTION__, sizebytes);
 
+       /* calculate the Two's complement offset */
        offset = sizebytes - SMM_OFFSET;
        offset = (offset >> 12) & 0x000fffff;
-       printk_debug("%s: offset is 0x%08x\n", __FUNCTION__, offset);
+       printk_debug("%s: offset is 0x%08x\n", __FUNCTION__, SMM_OFFSET);
 
-       msr.hi = offset << 8 | MSR_MC;
+       msr.hi = offset << 8 | gl->hi;
        msr.hi |= SMM_OFFSET>>24;
 
        msr.lo = SMM_OFFSET << 8;
        msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff;
        
        wrmsr(gl->desc_name, msr);      // MSR - See table above
-       msr = rdmsr(gl->desc_name);
-       printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
+       printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
 }
-static void
-SMMGL1Init(struct gliutable *gl) {
+
+static void SMMGL1Init(struct gliutable *gl) {
        msr_t msr;
        printk_debug("%s:\n", __FUNCTION__ );
 
@@ -193,16 +172,14 @@ SMMGL1Init(struct gliutable *gl) {
        /* I don't think this is needed */
        msr.hi &= 0xffffff00;
        msr.hi |= (SMM_OFFSET >> 24);
-       msr.lo = SMM_OFFSET << 8;
+       msr.lo = (SMM_OFFSET << 8) & 0xFFF00000;
        msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff;
        
        wrmsr(gl->desc_name, msr);      // MSR - See table above
-       msr = rdmsr(gl->desc_name);
-       printk_debug("%s: AFTER write msr 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
+       printk_debug("%s: MSR 0x%08x, val 0x%08x:0x%08x\n", __FUNCTION__, gl->desc_name, msr.hi, msr.lo);
 }
 
-static void
-GLIUInit(struct gliutable *gl){
+static void GLIUInit(struct gliutable *gl){
 
        while (gl->desc_type != GL_END){
                switch(gl->desc_type){
@@ -229,6 +206,7 @@ GLIUInit(struct gliutable *gl){
        }
 
 }
+
        /* ***************************************************************************/
        /* **/
        /* *    GLPCIInit*/
@@ -255,8 +233,8 @@ static void GLPCIInit(void){
        /* */
        /*  R0 - GLPCI settings for Conventional Memory space.*/
        /* */
-       msr.hi =  (0x09F000 >> 12) << GLPCI_RC_UPPER_TOP_SHIFT          /*  640*/;
-       msr.lo =  0                                                     /*  0*/;
+       msr.hi =  (0x09F000 >> 12) << GLPCI_RC_UPPER_TOP_SHIFT;         /* 640 */
+       msr.lo =  0;                                                    /* 0*/
        msr.lo |= GLPCI_RC_LOWER_EN_SET+ GLPCI_RC_LOWER_PF_SET + GLPCI_RC_LOWER_WC_SET;
        msrnum = GLPCI_RC0;
        wrmsr(msrnum, msr);
@@ -283,8 +261,7 @@ static void GLPCIInit(void){
                /* So we need a high page aligned addresss (pah) and low page aligned address (pal)
                 * pah is from msr.hi << 12 | msr.low >> 20. pal is msr.lo << 12
                 */
-               printk_debug("GLPCI r1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi);
-               pah = ((msr.hi &0xff) << 12) | ((msr.lo >> 20) & 0xfff);
+               pah = ((msr.hi & 0xFF) << 12) | ((msr.lo >> 20) & 0xFFF);
                /* we have the page address. Now make it a page-aligned address */
                pah <<= 12;
 
@@ -292,24 +269,25 @@ static void GLPCIInit(void){
                msr.hi =  pah;
                msr.lo =  pal;
                msr.lo |= GLPCI_RC_LOWER_EN_SET | GLPCI_RC_LOWER_PF_SET | GLPCI_RC_LOWER_WC_SET;
-               printk_debug("GLPCI r1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi);
+               printk_debug("GLPCI R1: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi);
                msrnum = GLPCI_RC1;
                wrmsr(msrnum, msr);
        }
 
        /* */
-       /*  R2 - GLPCI settings for SMM space.*/
+       /*      R2 - GLPCI settings for SMM space */
        /* */
        msr.hi =  ((SMM_OFFSET+(SMM_SIZE*1024-1)) >> 12) << GLPCI_RC_UPPER_TOP_SHIFT;
        msr.lo =  (SMM_OFFSET >> 12) << GLPCI_RC_LOWER_BASE_SHIFT;
        msr.lo |= GLPCI_RC_LOWER_EN_SET | GLPCI_RC_LOWER_PF_SET;
+       printk_debug("GLPCI R2: system msr.lo 0x%08x msr.hi 0x%08x\n", msr.lo, msr.hi);
        msrnum = GLPCI_RC2;
        wrmsr(msrnum, msr);
 
        /* this is done elsewhere already, but it does no harm to do it more than once */
        /*  write serialize memory hole to PCI. Need to to unWS when something is shadowed regardless of cachablility.*/
-       msr.lo =  0x021212121                                                           /*  cache disabled and write serialized*/;
-       msr.hi =  0x021212121                                                           /*  cache disabled and write serialized*/;
+       msr.lo =  0x021212121;                                                          /* cache disabled and write serialized */
+       msr.hi =  0x021212121;                                                          /* cache disabled and write serialized */
 
        msrnum = CPU_RCONF_A0_BF;
        wrmsr(msrnum, msr);
@@ -340,17 +318,16 @@ static void GLPCIInit(void){
        msrnum = CPU_DM_CONFIG0;
        msr = rdmsr(msrnum);
        msr.hi &= ~ (7 << DM_CONFIG0_UPPER_WSREQ_SHIFT);
-       msr.hi |= 2 << DM_CONFIG0_UPPER_WSREQ_SHIFT     ;       /*  reduce to 1 for safe mode.*/
+       msr.hi |= 2 << DM_CONFIG0_UPPER_WSREQ_SHIFT;    /* reduce to 1 for safe mode */
        wrmsr(msrnum, msr);
 
        /* we are ignoring the 5530 case for now, and perhaps forever. */
 
        /* */
-       /* 5535 NB Init*/
+       /* 553x NB Init*/
        /* */   
 
        /* Arbiter setup */
-
        enable_preempt = GLPCI_ARB_LOWER_PRE0_SET | GLPCI_ARB_LOWER_PRE1_SET | GLPCI_ARB_LOWER_PRE2_SET | GLPCI_ARB_LOWER_CPRE_SET; 
        enable_cpu_override = GLPCI_ARB_LOWER_COV_SET;
        enable_bus_parking = GLPCI_ARB_LOWER_PARK_SET;
@@ -392,10 +369,10 @@ static void GLPCIInit(void){
        wrmsr(msrnum, msr);
 
 
-       /*  Set GLPCI Latency Timer.*/
+       /* Set GLPCI Latency Timer */
        msrnum = GLPCI_CTRL;
        msr = rdmsr(msrnum);
-       msr.hi |=  0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT;  /*  Change once 1.x is gone.*/
+       msr.hi |=  0x1F << GLPCI_CTRL_UPPER_LAT_SHIFT;  /* Change once 1.x is gone */
        wrmsr(msrnum, msr);
 
        /*  GLPCI_SPARE*/
@@ -404,7 +381,6 @@ static void GLPCIInit(void){
        msr.lo &=  ~ 0x7;
        msr.lo |=  GLPCI_SPARE_LOWER_AILTO_SET | GLPCI_SPARE_LOWER_PPD_SET | GLPCI_SPARE_LOWER_PPC_SET | GLPCI_SPARE_LOWER_MPC_SET | GLPCI_SPARE_LOWER_NSE_SET | GLPCI_SPARE_LOWER_SUPO_SET;
        wrmsr(msrnum, msr);
-
 }
 
 
@@ -420,35 +396,13 @@ static void GLPCIInit(void){
        /* *    Modified:*/
        /* **/
        /* ***************************************************************************/
-static void 
-ClockGatingInit (void){
+static void ClockGatingInit (void){
        msr_t msr;
        struct msrinit *gating = ClockGatingDefault;
        int i;
 
-#if 0
-       mov     cx, TOKEN_CLK_GATE
-       NOSTACK bx, GetNVRAMValueBX
-       cmp     al, TVALUE_CG_OFF
-       je      gatingdone
-       
-       cmp     al, TVALUE_CG_DEFAULT
-       jb      allon
-       ja      performance
-       lea     si, ClockGatingDefault
-       jmp     nextdevice
-
-allon:
-       lea     si, ClockGatingAllOn
-       jmp     nextdevice
-
-performance:
-       lea     si, ClockGatingPerformance
-#endif
-
        for(i = 0; gating->msrnum != 0xffffffff; i++) {
                msr = rdmsr(gating->msrnum);
-               //printk_debug("%s: MSR 0x%08x is 0x%08x:0x%08x\n", __FUNCTION__, gating->msrnum, msr.hi, msr.lo); //GX3 
                msr.hi |= gating->msr.hi;
                msr.lo |= gating->msr.lo;
                /* printk_debug("%s: MSR 0x%08x will be set to  0x%08x:0x%08x\n", __FUNCTION__, 
@@ -459,15 +413,13 @@ performance:
 
 }
 
-static void 
-GeodeLinkPriority(void){
+static void GeodeLinkPriority(void){
        msr_t msr;
        struct msrinit *prio = GeodeLinkPriorityTable;
        int i;
 
        for(i = 0; prio->msrnum != 0xffffffff; i++) {
                msr = rdmsr(prio->msrnum);
-               // printk_debug("%s: MSR 0x%08x is 0x%08x:0x%08x\n", __FUNCTION__, prio->msrnum, msr.hi, msr.lo); // GX3
                msr.hi |= prio->msr.hi;
                msr.lo &= ~0xfff;
                msr.lo |= prio->msr.lo;
@@ -485,9 +437,9 @@ GeodeLinkPriority(void){
  *     If the setShadow function is used then all shadow descriptors
  *       will stay sync'ed.
  */
-static uint64_t getShadow(void)
-{
+static uint64_t getShadow(void){
        msr_t msr;
+
        msr = rdmsr(MSR_GLIU0_SHADOW);
        return ( ( (uint64_t) msr.hi ) << 32 ) | msr.lo;
 }
@@ -499,8 +451,8 @@ static uint64_t getShadow(void)
  *     This is part of the PCI lockup solution
  *     Entry: EDX:EAX is the shadow settings
  */
-static void setShadowRCONF(uint32_t shadowHi, uint32_t shadowLo)
-{
+static void setShadowRCONF(uint32_t shadowHi, uint32_t shadowLo){
+
        // ok this is whacky bit translation time.
        int bit;
        uint8_t shadowByte;
@@ -557,7 +509,6 @@ static void setShadowGLPCI(uint32_t shadowHi, uint32_t shadowLo)
        msr_t msr;
        
 // Set the Enable Register.
-
        msr = rdmsr(GLPCI_REN);
        msr.lo &= 0xFFFF00FF;
        msr.lo |= ( (shadowLo & 0xFFFF0000) >> 8);
@@ -592,26 +543,13 @@ static void setShadow(uint64_t shadowSettings)
                                msr.hi &= 0xFFFF0000;           // maintain PDID in upper EDX
                                msr.hi |= ((uint32_t) (shadowSettings >> 32)) & 0x0000FFFF;
                                wrmsr(pTable->desc_name, msr);  // MSR - See the table above
-
                        }
                }
        }
 }
 
-/**************************************************************************
- *
- *     shadowRom
- *
- *     Set up a stack for ease of further testing
- *
- *     Entry:
- *     Exit:
- *     Destroys:
- *
- **************************************************************************/
-static void 
-shadowRom(void)
-{
+static void rom_shadow_settings(void){
+
        uint64_t shadowSettings = getShadow();
        shadowSettings &= (uint64_t) 0xFFFF00000000FFFFULL;     // Disable read & writes
        shadowSettings |= (uint64_t) 0x00000000F0000000ULL;     // Enable reads for F0000-FFFFF
@@ -623,7 +561,7 @@ shadowRom(void)
 
 /***************************************************************************
  *
- * RCONFInit
+ * L1Init
  *       Set up RCONF_DEFAULT and any other RCONF registers needed
  *
  *  DEVRC_RCONF_DEFAULT:
@@ -639,14 +577,12 @@ shadowRom(void)
 #define ROMBASE_RCONF_DEFAULT 0xFFFC0000
 #define ROMRC_RCONF_DEFAULT 0x25
 
-static void
-RCONFInit(void)
+static void enable_L1_cache(void)
 {
        struct gliutable *gl = 0;
        int i;
        msr_t msr;
        uint8_t SysMemCacheProp;
-       //uint8_t RegionProp;
 
        /* Locate SYSMEM entry in GLIU0table */
        for(i = 0; gliu0table[i].desc_name != GL_END; i++) {
@@ -661,11 +597,8 @@ RCONFInit(void)
        }
 
 // sysdescfound:       
-       /* found the descriptor... get its contents */
        msr = rdmsr(gl->desc_name);
 
-       printk_debug("SYSDESC: 0x%08X:0x%08X\n",msr.hi,msr.lo);
-
        /* 20 bit address -  The bottom 12 bits go into bits 20-31 in eax, the 
         * top 8 bits go into 0-7 of edx. 
         */
@@ -673,13 +606,11 @@ RCONFInit(void)
        msr.lo = ((msr.lo << 12) | (msr.lo >> 20)) & 0x000FFFFF;
        msr.lo <<= RCONF_DEFAULT_LOWER_SYSTOP_SHIFT;    // 8
        
-       printk_debug("RCONF LO: 0x%08X\n",msr.lo);
-       
        // Set Default SYSMEM region properties
-       msr.lo &= ~SYSMEM_RCONF_WRITETHROUGH;   // 8 (or ~8)
+       msr.lo &= ~SYSMEM_RCONF_WRITETHROUGH;   // NOT writethrough == writeback 8 (or ~8)
 
        // Set PCI space cache properties
-       msr.hi = (DEVRC_RCONF_DEFAULT >> 4);    // only need the bottom bits and lets clean the rest of edx
+       msr.hi = (DEVRC_RCONF_DEFAULT >> 4);    // setting is split betwwen hi and lo...
        msr.lo |= (DEVRC_RCONF_DEFAULT << 28);
 
        // Set the ROMBASE. This is usually FFFC0000h
@@ -690,6 +621,7 @@ RCONFInit(void)
        
        // now program RCONF_DEFAULT
        wrmsr(CPU_RCONF_DEFAULT, msr);
+       printk_debug("CPU_RCONF_DEFAULT (1808): 0x%08X:0x%08X\n",msr.hi,msr.lo);
 
        // RCONF_BYPASS: Cache tablewalk properties and SMM/DMM header access properties.
        // Set to match system memory cache properties.
@@ -699,21 +631,84 @@ RCONFInit(void)
        msr.lo = (msr.lo & 0xFFFF0000) | (SysMemCacheProp << 8) | SysMemCacheProp;
        wrmsr(CPU_RCONF_BYPASS, msr);
        
-       printk_debug("CPU_RCONF_SMM (180E)  0x%08x : 0x%08x\n", msr.hi, msr.lo);
+       printk_debug("CPU_RCONF_BYPASS (180A): 0x%08x : 0x%08x\n", msr.hi, msr.lo);
 }
 
+static void enable_L2_cache(void) {
+       msr_t msr;
+
+       /* Instruction Memory Configuration register
+        * set EBE bit, required when L2 cache is enabled
+        */
+       msr = rdmsr(CPU_IM_CONFIG);
+       msr.lo |= 0x400;
+       wrmsr(CPU_IM_CONFIG, msr);
+
+       /* Data Memory Subsystem Configuration register
+        * set EVCTONRPL bit, required when L2 cache is enabled in victim mode
+        */
+       msr = rdmsr(CPU_DM_CONFIG0);
+       msr.lo |= 0x4000;
+       wrmsr(CPU_DM_CONFIG0, msr);
+
+       /* invalidate L2 cache */
+       msr.hi = 0x00;
+       msr.lo = 0x10;
+       wrmsr(CPU_BC_L2_CONF, msr);
+
+       /* Enable L2 cache */
+       msr.hi = 0x00;
+       msr.lo = 0x0f;
+       wrmsr(CPU_BC_L2_CONF, msr);
+
+       printk_debug("L2 cache enabled\n");
+}
+
+static void setup_lx_cache(void)
+{
+       msr_t msr;
+
+       enable_L1_cache();
+       enable_L2_cache();
+
+       // Make sure all INVD instructions are treated as WBINVD.  We do this
+       // because we've found some programs which require this behavior.
+       msr = rdmsr(CPU_DM_CONFIG0);
+       msr.lo |= DM_CONFIG0_LOWER_WBINVD_SET;
+       wrmsr(CPU_DM_CONFIG0, msr);
+
+       x86_enable_cache();
+       wbinvd();
+}
+
+uint32_t get_systop(void) {
+       struct gliutable *gl = 0;
+       uint32_t systop;
+       msr_t msr;
+       int i;
+
+       for(i = 0; gliu0table[i].desc_name != GL_END; i++) {
+               if (gliu0table[i].desc_type == R_SYSMEM) {
+                       gl = &gliu0table[i];
+                       break;
+               }
+       }
+       if (gl) {
+               msr = rdmsr(gl->desc_name);
+               systop = ((msr.hi & 0xFF) << 24) | ((msr.lo & 0xFFF00000) >> 8);
+               systop += 0x1000;               /* 4K */
+       }else{
+               systop = ((sizeram() - CONFIG_VIDEO_MB) * 1024) - SMM_SIZE - 1024;
+       }
+       return systop;
+}
 
 /****************************************************************************/
 /* *   northbridge_init_early */
 /* **/
 /* *   Core Logic initialization:  Host bridge*/
 /* **/
-/* *   Entry:*/
-/* *   Exit:*/
-/* *   Modified:*/
-/* **/
 /* ***************************************************************************/
-
 void northbridge_init_early(void)
 {
        msr_t msr;
@@ -723,34 +718,21 @@ void northbridge_init_early(void)
        for(i = 0; gliutables[i]; i++)
                GLIUInit(gliutables[i]);
 
-       GeodeLinkPriority();
-       
-       shadowRom();
-       
-       // GeodeROM ensures that the BIOS waits the required 1 second before 
-       // allowing anything to access PCI
-       // PCIDelay();
-       
-       RCONFInit();
-       
-       // The cacheInit function in GeodeROM tests cache and, among other things,
-       // makes sure all INVD instructions are treated as WBINVD.  We do this
-       // because we've found some programs which require this behavior.
-       // That subset of cacheInit() is implemented here:
-       
-       /* GX3 OK */
-       msr = rdmsr(CPU_DM_CONFIG0);
-       msr.lo |= DM_CONFIG0_LOWER_WBINVD_SET;
-       wrmsr(CPU_DM_CONFIG0, msr);
-       
        /*  Now that the descriptor to memory is set up.*/
        /*  The memory controller needs one read to synch its lines before it can be used.*/
        i = *(int *) 0;
 
+       GeodeLinkPriority();
+
+       setup_lx_cache();
+
+       rom_shadow_settings();
+
        GLPCIInit();
+
        ClockGatingInit();
-       __asm__("FINIT\n");
-       /* CPUBugsFix -- called elsewhere */
+
+       __asm__ __volatile__("FINIT\n");
        printk_debug("Exit %s\n", __FUNCTION__);
 }
 
index 13e21be8de54e9b55ccbc4223435e57edbab1573..39a2e270fc0ad18282b77a22815f870ab0e52865 100644 (file)
@@ -1,6 +1,10 @@
-#define POST_CODE(x) outb(0x80, x)
+/*
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+*/
 
-static void pll_reset(void)
+static void pll_reset(char manualconf)
 {
        msr_t msrGlcpSysRstpll;
 
@@ -12,32 +16,75 @@ static void pll_reset(void)
                print_debug_hex32(msrGlcpSysRstpll.hi);
                print_debug(":");
                print_debug_hex32(msrGlcpSysRstpll.lo);
-               print_debug("\n");
+               print_debug("\r\n");
+       POST_CODE(POST_PLL_INIT);
        
-        msrGlcpSysRstpll.lo &= 0x80000000;
-
-       // If the "we've already been here" flag is set, don't reconfigure the pll
-        if ( !(msrGlcpSysRstpll.lo) )
-       { // we haven't configured the PLL; do it now
-           print_debug("CONFIGURING PLL");
-       
-                POST_CODE(0x77);
-       
-               // HARDCODED VALUES MOVED BACK TO auto.c AS THEY HAVE TO BE BOARD-SPECIFIC
-               // (this file is included from there)
-
+       if (!(msrGlcpSysRstpll.lo & (1 << RSTPLL_LOWER_SWFLAGS_SHIFT))){
+               print_debug("Configuring PLL\n");
+               if(manualconf){
+                       POST_CODE(POST_PLL_MANUAL);
                        /* CPU and GLIU mult/div (GLMC_CLK = GLIU_CLK / 2)  */
                msrGlcpSysRstpll.hi = PLLMSRhi;
 
                        /* Hold Count - how long we will sit in reset */
                msrGlcpSysRstpll.lo = PLLMSRlo;
-
+               }
+               else{
+                       /*automatic configuration (straps)*/
+                       POST_CODE(POST_PLL_STRAP);
+                       msrGlcpSysRstpll.lo &= ~(0xFF << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
+                       msrGlcpSysRstpll.lo |= (0xDE << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
+                       msrGlcpSysRstpll.lo &= ~(RSTPPL_LOWER_COREBYPASS_SET | RSTPPL_LOWER_MBBYPASS_SET);
+                       msrGlcpSysRstpll.lo |= RSTPPL_LOWER_COREPD_SET | RSTPPL_LOWER_CLPD_SET;
+               }
                        /* Use SWFLAGS to remember: "we've already been here"  */
-                       msrGlcpSysRstpll.lo |= 0x80000000;
+               msrGlcpSysRstpll.lo |= (1 << RSTPLL_LOWER_SWFLAGS_SHIFT);
 
                        /* "reset the chip" value */
-                       msrGlcpSysRstpll.lo |= 0x00000001;
-
+               msrGlcpSysRstpll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
                wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+               /*      You should never get here..... The chip has reset.*/
+               print_debug("CONFIGURING PLL FAILURE\n");
+               POST_CODE(POST_PLL_RESET_FAIL);
+               __asm__ __volatile__("hlt\n");
+
+       }
+       print_debug("Done cpuRegInit\n");
+       return;
+}
+
+static unsigned int CPUSpeed(void){
+       unsigned int speed;
+       msr_t msr;
+
+       msr = rdmsr(GLCP_SYS_RSTPLL);
+       speed = ((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & 0x1F)+1)*333)/10;
+       if((((((msr.hi >> RSTPLL_UPPER_CPUMULT_SHIFT) & 0x1F)+1)*333)%10) > 5){
+               ++speed;
+       }
+       return(speed);
+}
+static unsigned int GeodeLinkSpeed(void){
+       unsigned int speed;
+       msr_t msr;
+
+       msr = rdmsr(GLCP_SYS_RSTPLL);
+       speed = ((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & 0x1F)+1)*333)/10;
+       if((((((msr.hi >> RSTPLL_UPPER_GLMULT_SHIFT) & 0x1F)+1)*333)%10) > 5){
+               ++speed;
        }
+       return(speed);
 }
+static unsigned int PCISpeed(void){
+       msr_t msr;
+
+       msr = rdmsr(GLCP_SYS_RSTPLL);
+       if (msr.hi & (1 << RSTPPL_LOWER_PCISPEED_SHIFT)){
+               return(66);
+       }
+       else{
+               return(33);
+       }
+}
+
index f1ae87d69ee0c7990824fceb94e23433b5c2c143..39ae1de577bf56b8ba399ede72f18106d6a8d51d 100644 (file)
+/*
+* This file is part of the LinuxBIOS project.
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA     02110-1301 USA
+*/
+
 #include <cpu/amd/lxdef.h>
+#include <arch/io.h>
+#include <spd.h>
+#include "southbridge/amd/cs5536/cs5536.h"
 
+static const unsigned char NumColAddr[] = {0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
 
-static void sdram_set_registers(const struct mem_controller *ctrl)
-{
+static void auto_size_dimm(unsigned int dimm){
+       uint32_t dimm_setting;
+       uint16_t dimm_size;
+       uint8_t spd_byte;
+       msr_t msr;
+
+       dimm_setting = 0;
+
+       /* Check that we have a dimm */
+       if (spd_read_byte(dimm, SPD_MEMORY_TYPE) == 0xFF){
+               return;
 }
 
-/* Section 6.1.3, LX processor databooks, BIOS Initialization Sequence
- * Section 4.1.4, GX/CS5535 GeodeROM Porting guide */
-static void sdram_enable(int controllers, const struct mem_controller *ctrl)
-{
-       int i;
-       msr_t msr;
+       /* Field: Module Banks per DIMM */
+       /* EEPROM byte usage: (5) Number of DIMM Banks */
+       spd_byte = spd_read_byte(dimm, SPD_NUM_DIMM_BANKS);
+       if ((MIN_MOD_BANKS > spd_byte) && (spd_byte > MAX_MOD_BANKS)){
+               print_debug("Number of module banks not compatible\r\n");
+               POST_CODE(ERROR_BANK_SET);
+               __asm__ __volatile__("hlt\n");
+       }
+       dimm_setting |= (spd_byte >> 1) << CF07_UPPER_D0_MB_SHIFT;
 
-       /* DRAM initialization sequence according to the documentation:
-        * 1)  Initialize the following GLMC registers/bits based on Serial Presence Detect (SPD) values:
-        *  â€” MSR 20000018h except REF_INT bits [23:8]
-        *   â€” MSR 20000019h
-        */
        
-       // This is done by sdram_set_spd_registers() that is called by sdram/generic_sdram.c just before this
-       // sdram_set_spd_registers is responsible for reading ram settings from spd rom and configuring sdram conrtoller
-       // Here follows generic sdram initialization procedure.
+       /* Field: Banks per SDRAM device */
+       /* EEPROM byte usage: (17) Number of Banks on SDRAM Device */
+       spd_byte = spd_read_byte(dimm, SPD_NUM_BANKS_PER_SDRAM);
+       if ((MIN_DEV_BANKS > spd_byte) && (spd_byte > MAX_DEV_BANKS)){
+               print_debug("Number of device banks not compatible\r\n");
+               POST_CODE(ERROR_BANK_SET);
+               __asm__ __volatile__("hlt\n");
+       }
+       dimm_setting |= (spd_byte >> 2) << CF07_UPPER_D0_CB_SHIFT;
 
-       /* 2)  Initialize the following GLMC registers:
-        *      â€” MSR 2000001Ah[15:8] = C8h
-        *      â€” MSR 20002004h[2] = 0, [0] = 1
+
+       /*; Field: DIMM size
+       *; EEPROM byte usage: (3)  Number or Row Addresses
+       *;                                        (4)  Number of Column Addresses
+       *;                                        (5)  Number of DIMM Banks
+       *;                                        (31) Module Bank Density
+       *; Size = Module Density * Module Banks
         */
-       msr.hi = 0x00000000;
-       msr.lo = 0x130AD101;
-       wrmsr(MC_CF1017_DATA, msr);
+       if ((spd_read_byte(dimm, SPD_NUM_ROWS) & 0xF0) || (spd_read_byte(dimm, SPD_NUM_COLUMNS) & 0xF0)){
+               print_debug("Assymetirc DIMM not compatible\r\n");
+               POST_CODE(ERROR_UNSUPPORTED_DIMM);
+               __asm__ __volatile__("hlt\n");
+       }
 
-       //ok
-       msr.hi = 0x00000000;
-       msr.lo = 0x00000001;
-       wrmsr(MC_GLD_MSR_PM, msr);
+       dimm_size = spd_read_byte(dimm, SPD_BANK_DENSITY);
+       dimm_size |= (dimm_size << 8);  /* align so 1GB(bit0) is bit 8, this is a little weird to get gcc to not optimize this out*/
+       dimm_size &= 0x01FC;            /* and off 2GB DIMM size : not supported and the 1GB size we just moved up to bit 8 as well as all the extra on top*/
 
-       /* 3) Release MASK_CKE[1:0] (MSR 2000001Dh[9:8] = 11) */
+       /*       Module Density * Module Banks */
+       dimm_size <<= (dimm_setting >> CF07_UPPER_D0_MB_SHIFT) & 1; /* shift to multiply by # DIMM banks */
+       dimm_size = __builtin_ctz(dimm_size);
+       if (dimm_size > 8){             /* 8 is 1GB only support 1GB per DIMM */
+               print_debug("Only support up to 1 GB per DIMM\r\n");
+               POST_CODE(ERROR_DENSITY_DIMM);
+               __asm__ __volatile__("hlt\n");
+       }
+       dimm_setting |= dimm_size << CF07_UPPER_D0_SZ_SHIFT;
 
-       msr.hi = 0x00000000;
-       msr.lo = 0x00000000;
-       wrmsr(MC_CFCLK_DBUG, msr);
        
-       // reset memory controller
+/*; Field: PAGE size
+*; EEPROM byte usage: (4)  Number of Column Addresses
+*; PageSize = 2^# Column Addresses * Data width in bytes (should be 8bytes for a normal DIMM)
+*
+*; But this really works by magic.
+*;If ma[12:0] is the memory address pins, and pa[12:0] is the physical column address
+*;that MC generates, here is how the MC assigns the pa onto the ma pins:
+*
+*;ma  12 11 10 09 08 07 06 05 04 03 02 01 00
+*;-------------------------------------------
+*;pa                                   09 08 07 06 05 04 03    (7 col addr bits = 1K page size)
+*;pa                            10 09 08 07 06 05 04 03        (8 col addr bits = 2K page size)
+*;pa                     11 10 09 08 07 06 05 04 03    (9 col addr bits = 4K page size)
+*;pa              12 11 10 09 08 07 06 05 04 03        (10 col addr bits = 8K page size)
+*;pa    13 AP 12 11 10 09 08 07 06 05 04 03    (11 col addr bits = 16K page size)
+*;pa  14 13 AP 12 11 10 09 08 07 06 05 04 03   (12 col addr bits = 32K page size)
+*; *AP=autoprecharge bit
+*
+*;Remember that pa[2:0] are zeroed out since it's a 64-bit data bus (8 bytes),
+*;so lower 3 address bits are dont_cares.So from the table above,
+*;it's easier to see what the old code is doing: if for example,#col_addr_bits=7(06h),
+*;it adds 3 to get 10, then does 2^10=1K.  Get it?*/
+
+       spd_byte = NumColAddr[spd_read_byte(dimm, SPD_NUM_COLUMNS) & 0xF];
+       if (spd_byte > MAX_COL_ADDR) {
+               print_debug("DIMM page size not compatible\r\n");
+               POST_CODE(ERROR_SET_PAGE);
+               __asm__ __volatile__("hlt\n");
+       }
+       spd_byte -=7;
+       if (spd_byte > 5){                      /* if the value is above 6 it means >12 address lines */
+               spd_byte = 7;                   /* which means >32k so set to disabled */
+       }
+       dimm_setting |= spd_byte << CF07_UPPER_D0_PSZ_SHIFT; /* 0=1k,1=2k,2=4k,etc */
+
        msr = rdmsr(MC_CF07_DATA);
-       msr.lo |=  0x00000002;
-       wrmsr(MC_CF07_DATA, msr);
-       msr.lo &= 0xFFFFFFFD;
+       if (dimm == DIMM0){
+               msr.hi &= 0xFFFF0000;
+               msr.hi |= dimm_setting;
+       }else{
+               msr.hi &= 0x0000FFFF;
+               msr.hi |= dimm_setting << 16;
+       }
        wrmsr(MC_CF07_DATA, msr);
+}
 
-       /* 4. set and clear REF_TST 16 times, more shouldn't hurt
-        * why this is before EMRS and MRS ? */
         
-       for (i = 0; i < 19; i++) {
+static void checkDDRMax(void){
+       uint8_t spd_byte0, spd_byte1;
+       uint16_t speed;
+
+        /* PC133 identifier */
+       spd_byte0 = spd_read_byte(DIMM0, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+
+       /* I don't think you need this check.
+       if (spd_byte0 < 0xA0 || spd_byte0 < 0xA0){
+               print_debug("DIMM overclocked. Check GeodeLink Speed\r\n");
+               POST_CODE(POST_PLL_MEM_FAIL);
+               __asm__  __volatile__("hlt\n");
+       }*/
+
+
+       /* Use the slowest DIMM */
+       if (spd_byte0 < spd_byte1){
+               spd_byte0 = spd_byte1;
+       }
+
+       /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
+       speed = 2*((10000/(((spd_byte0 >> 4) * 10) + (spd_byte0 & 0x0F))));
+
+       /* current speed > max speed? */
+       if (GeodeLinkSpeed() > speed){
+               print_debug("DIMM overclocked. Check GeodeLink Speed\r\n");
+               POST_CODE(POST_PLL_MEM_FAIL);
+               __asm__ __volatile__("hlt\n");
+       }
+}
+
+
+const uint16_t REF_RATE[] = {15, 3, 7, 31, 62, 125}; /* ns */
+
+static void set_refresh_rate(void){
+       uint8_t spd_byte0, spd_byte1;
+       uint16_t rate0, rate1;
+       msr_t msr;
+
+       spd_byte0 = spd_read_byte(DIMM0, SPD_REFRESH);
+       spd_byte0 &= 0xF;
+       if (spd_byte0 > 5){
+               spd_byte0 = 5;
+       }
+       rate0 = REF_RATE[spd_byte0];
+
+       spd_byte1 = spd_read_byte(DIMM1, SPD_REFRESH);
+       spd_byte1 &= 0xF;
+       if (spd_byte1 > 5){
+               spd_byte1 = 5;
+       }
+       rate1 = REF_RATE[spd_byte1];
+
+       /* Use the faster rate (lowest number) */
+       if (rate0 > rate1){
+               rate0 = rate1;
+       }
+
                msr = rdmsr(MC_CF07_DATA);
-               msr.lo |=  0x00000008;
-               wrmsr(MC_CF07_DATA, msr);
-               msr.lo &= 0xFFFFFFF7;
+       msr.lo|= ((rate0 * (GeodeLinkSpeed()/2))/16) << CF07_LOWER_REF_INT_SHIFT;
                wrmsr(MC_CF07_DATA, msr);
        }
 
 
-       /* 5) Initialize REF_INT (MSR 20000018h[23:8]) to set refresh interval. */
-       msr.lo |= 0x3A00;
-       wrmsr(MC_CF07_DATA, msr);
+const uint8_t CASDDR[] = {5, 5, 2, 6, 3, 7, 4, 0}; /* 1(1.5), 1.5, 2, 2.5, 3, 3.5, 4, 0 */
 
-       /* 6) Perform load-mode with MSR_BA = 01 (MSR 200000018h[29:28] = 01) 
-        * to initialize DIMM Extended Mode register. 
-        * Load-mode is performed by setting/clearing PROG_DRAM (MSR 200000018h[0]).
-        */
-// eeldus et bit29 = 0, mida ta praegu ka on
-       msr.lo |=  ((0x01 << 28) | 0x01);
-       wrmsr(MC_CF07_DATA, msr);
+static void setCAS(void){
+/*;*****************************************************************************
+;*
+;*     setCAS
+;*     EEPROM byte usage: (18) SDRAM device attributes - CAS latency
+;*     EEPROM byte usage: (23) SDRAM Minimum Clock Cycle Time @ CLX -.5
+;*     EEPROM byte usage: (25) SDRAM Minimum Clock Cycle Time @ CLX -1
+;*
+;*     The CAS setting is based on the information provided in each DIMMs SPD.
+;*      The speed at which a DIMM can run is described relative to the slowest
+;*      CAS the DIMM supports. Each speed for the relative CAS settings is
+;*      checked that it is within the GeodeLink speed. If it isn't within the GeodeLink
+;*      speed, the CAS setting  is removed from the list of good settings for
+;*      the DIMM. This is done for both DIMMs and the lists are compared to
+;*      find the lowest common CAS latency setting. If there are no CAS settings
+;*      in common we out a ERROR_DIFF_DIMMS (78h) to port 80h and halt.
+;*
+;*     Entry:
+;*     Exit: Set fastest CAS Latency based on GeodeLink speed and SPD information.
+;*     Destroys: We really use everything !
+;*****************************************************************************/
+       uint16_t glspeed, dimm_speed;
+       uint8_t spd_byte, casmap0, casmap1;
+       msr_t msr;
 
-       msr.lo &= ~((0x01 << 28) | 0x01);
-       wrmsr(MC_CF07_DATA, msr);
+       glspeed = GeodeLinkSpeed();
+
+       /**************************      DIMM0  **********************************/
+       casmap0 = spd_read_byte(DIMM0, SPD_ACCEPTABLE_CAS_LATENCIES);
+       if (casmap0 != 0xFF){
+               /* IF -.5 timing is supported, check -.5 timing > GeodeLink */
+               spd_byte = spd_read_byte(DIMM0, SPD_SDRAM_CYCLE_TIME_2ND);
+               if(spd_byte != 0){
+                       /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
+                       dimm_speed = 2*(10000/(((spd_byte >> 4) * 10) + (spd_byte & 0x0F)));
+                       if (dimm_speed >= glspeed){
+                               /* IF -1 timing is supported, check -1 timing > GeodeLink */
+                               spd_byte = spd_read_byte(DIMM0, SPD_SDRAM_CYCLE_TIME_3RD);
+                               if(spd_byte != 0){
+                                       /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
+                                       dimm_speed = 2*(10000/(((spd_byte >> 4) * 10) + (spd_byte & 0x0F)));
+                                       if (dimm_speed <= glspeed){
+                                               /* set we can use -.5 timing but not -1 */
+                                               spd_byte = 31 - __builtin_clz((uint32_t)casmap0); /* just want bits in the lower byte since we have to cast to a 32 */
+                                               casmap0 &= 0xFF << (--spd_byte);
+                                       }
+                               }               /*MIN_CYCLE_10 !=0 */
+                       }
+                       else{           /* Timing_05 < GLspeed, can't use -.5 or -1 timing */
+                               spd_byte = 31 - __builtin_clz((uint32_t)casmap0); /* just want bits in the lower byte since we have to cast to a 32 */
+                               casmap0 &= 0xFF << (spd_byte);
+                       }
+               }                               /*MIN_CYCLE_05 !=0 */
+       }
+       else{                           /* No DIMM */
+               casmap0=0;
+       }
+
+       /**************************      DIMM1  **********************************/
+       casmap1 = spd_read_byte(DIMM1, SPD_ACCEPTABLE_CAS_LATENCIES);
+       if (casmap1 != 0xFF){
+               /* IF -.5 timing is supported, check -.5 timing > GeodeLink */
+               spd_byte = spd_read_byte(DIMM1, SPD_SDRAM_CYCLE_TIME_2ND);
+               if(spd_byte != 0){
+                       /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
+                       dimm_speed = 2*(10000/(((spd_byte >> 4) * 10) + (spd_byte & 0x0F)));
+                       if (dimm_speed >= glspeed){
+                               /* IF -1 timing is supported, check -1 timing > GeodeLink */
+                               spd_byte = spd_read_byte(DIMM1, SPD_SDRAM_CYCLE_TIME_3RD);
+                               if(spd_byte != 0){
+                                       /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
+                                       dimm_speed = 2*(10000/(((spd_byte >> 4) * 10) + (spd_byte & 0x0F)));
+                                       if (dimm_speed <= glspeed){
+                                               /* set we can use -.5 timing but not -1 */
+                                               spd_byte =31 - __builtin_clz((uint32_t)casmap1); /* just want bits in the lower byte since we have to cast to a 32 */
+                                               casmap1 &= 0xFF << (--spd_byte);
+                                       }
+                               }               /*MIN_CYCLE_10 !=0 */
+                       }
+                       else{           /* Timing_05 < GLspeed, can't use -.5 or -1 timing */
+                               spd_byte = 31 - __builtin_clz((uint32_t)casmap1); /* just want bits in the lower byte since we have to cast to a 32 */
+                               casmap1 &= 0xFF << (spd_byte);
+                       }
+               }                               /*MIN_CYCLE_05 !=0 */
+       }
+       else{                           /* No DIMM */
+               casmap1=0;
+       }
+
+       /*********************  CAS_LAT MAP COMPARE     ***************************/
+       if (casmap0 == 0){
+               spd_byte = CASDDR[__builtin_ctz((uint32_t)casmap1)];
+       }
+       else if (casmap1 == 0){
+               spd_byte = CASDDR[__builtin_ctz((uint32_t)casmap0)];
+       }
+       else if ((casmap0 &= casmap1)){
+               spd_byte = CASDDR[__builtin_ctz((uint32_t)casmap0)];
+       }
+       else{
+               print_debug("DIMM CAS Latencies not compatible\r\n");
+               POST_CODE(ERROR_DIFF_DIMMS);
+               __asm__ __volatile__("hlt\n");
+       }
+
+
+       msr = rdmsr(MC_CF8F_DATA);
+       msr.lo &= ~(7 << CF8F_LOWER_CAS_LAT_SHIFT);
+       msr.lo |= spd_byte << CF8F_LOWER_CAS_LAT_SHIFT;
+       wrmsr(MC_CF8F_DATA, msr);
+}
+
+
+static void set_latencies(void){
+       uint32_t memspeed, dimm_setting;
+       uint8_t spd_byte0, spd_byte1;
+       msr_t msr;
+
+       memspeed = GeodeLinkSpeed()/2;
+       dimm_setting=0;
+
+       /* MC_CF8F setup */
+       /* tRAS */
+       spd_byte0 = spd_read_byte(DIMM0, SPD_tRAS);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_tRAS);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+       if (spd_byte0 < spd_byte1){
+               spd_byte0 = spd_byte1;
+       }
+
+       /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
+       spd_byte1 = (spd_byte0 * memspeed)/1000;
+       if(((spd_byte0 * memspeed)%1000)){
+               ++spd_byte1;
+       }
+       dimm_setting |= spd_byte1 << CF8F_LOWER_ACT2PRE_SHIFT;
+
+
+       /* tRP */
+       spd_byte0 = spd_read_byte(DIMM0, SPD_tRP);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_tRP);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+       if (spd_byte0 < spd_byte1){
+               spd_byte0 = spd_byte1;
+       }
+
+       /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
+       spd_byte1 = ((spd_byte0 >> 2) * memspeed)/1000;
+       if((((spd_byte0 >> 2) * memspeed)%1000)){
+               ++spd_byte1;
+       }
+       dimm_setting |= spd_byte1 << CF8F_LOWER_PRE2ACT_SHIFT;
+
+
+       /* tRCD */
+       spd_byte0 = spd_read_byte(DIMM0, SPD_tRCD);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_tRCD);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+       if (spd_byte0 < spd_byte1){
+               spd_byte0 = spd_byte1;
+       }
+
+       /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
+       spd_byte1 = ((spd_byte0 >> 2) * memspeed)/1000;
+       if((((spd_byte0 >> 2) * memspeed)%1000)){
+               ++spd_byte1;
+       }
+       dimm_setting |= spd_byte1 << CF8F_LOWER_ACT2CMD_SHIFT;
+
+
+       /* tRRD */
+       spd_byte0 = spd_read_byte(DIMM0, SPD_tRRD);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_tRRD);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+       if (spd_byte0 < spd_byte1){
+               spd_byte0 = spd_byte1;
+       }
+
+       /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
+       spd_byte1 = ((spd_byte0 >> 2) * memspeed)/1000;
+       if((((spd_byte0 >> 2) * memspeed)%1000)){
+               ++spd_byte1;
+       }
+       dimm_setting |= spd_byte1 << CF8F_LOWER_ACT2ACT_SHIFT;
+
+
+       /* tRC = tRP + tRAS */
+       dimm_setting |= (((dimm_setting >> CF8F_LOWER_ACT2PRE_SHIFT) & 0x0F) + ((dimm_setting >> CF8F_LOWER_PRE2ACT_SHIFT) & 0x07)) \
+                                        << CF8F_LOWER_ACT2ACTREF_SHIFT;
 
 
-       /* 7. Reset DLL, Bit 27 is undocumented in GX datasheet,
-        * it is documented in LX datasheet  */ 
-       /* load Mode Register by set and clear PROG_DRAM */
-// eeldus et bit27:28=00, mida nad ka on
+       msr = rdmsr(MC_CF8F_DATA);
+       msr.lo &= 0xF00000FF;
+       msr.lo |= dimm_setting;
+       msr.hi |=  CF8F_UPPER_REORDER_DIS_SET;
+       wrmsr(MC_CF8F_DATA, msr);
+
+       /* MC_CF1017 setup */
+       /* tRFC */
+       spd_byte0 = spd_read_byte(DIMM0, SPD_tRFC);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_tRFC);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+       if (spd_byte0 < spd_byte1){
+               spd_byte0 = spd_byte1;
+       }
+
+       if (spd_byte0){
+               /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
+               spd_byte1 = (spd_byte0 * memspeed)/1000;
+               if(((spd_byte0 * memspeed)%1000)){
+                       ++spd_byte1;
+               }
+       }
+       else{   /* Not all SPDs have tRFC setting. Use this formula tRFC = tRC + 1 clk */
+               spd_byte1 = ((dimm_setting >> CF8F_LOWER_ACT2ACTREF_SHIFT) & 0x0F) + 1;
+       }
+       dimm_setting = spd_byte1 << CF1017_LOWER_REF2ACT_SHIFT;         /* note this clears the cf8f dimm setting */
+       msr = rdmsr(MC_CF1017_DATA);
+       msr.lo &= ~(0x1F << CF1017_LOWER_REF2ACT_SHIFT);
+       msr.lo |= dimm_setting;
+       wrmsr(MC_CF1017_DATA, msr);
+
+       /* tWTR: Set tWTR to 2 for 400MHz and above GLBUS (200Mhz mem) other wise it stay default(1) */
+       if (memspeed > 198){
+               msr = rdmsr(MC_CF1017_DATA);
+               msr.lo &= ~(0x7 << CF1017_LOWER_WR_TO_RD_SHIFT);
+               msr.lo |= 2 << CF1017_LOWER_WR_TO_RD_SHIFT;
+               wrmsr(MC_CF1017_DATA, msr);
+       }
+}
+
+static void set_extended_mode_registers(void){
+       uint8_t spd_byte0, spd_byte1;
+       msr_t msr;
+       spd_byte0 = spd_read_byte(DIMM0, SPD_DEVICE_ATTRIBUTES_GENERAL);
+       if (spd_byte0 == 0xFF){
+               spd_byte0=0;
+       }
+       spd_byte1 = spd_read_byte(DIMM1, SPD_DEVICE_ATTRIBUTES_GENERAL);
+       if (spd_byte1 == 0xFF){
+               spd_byte1=0;
+       }
+       spd_byte1 &= spd_byte0;
+
        msr = rdmsr(MC_CF07_DATA);
-       msr.lo |=  ((0x01 << 27) | 0x01);
-       wrmsr(MC_CF07_DATA, msr);
-       msr.lo &= ~((0x01 << 27) | 0x01);
+               if (spd_byte1 & 1){             /* Drive Strength Control */
+               msr.lo |= CF07_LOWER_EMR_DRV_SET;
+       }
+       if (spd_byte1 & 2){                     /* FET Control */
+               msr.lo |= CF07_LOWER_EMR_QFC_SET;
+       }
        wrmsr(MC_CF07_DATA, msr);
+}
+
+static void EnableMTest (void){
+       msr_t msr;
+
+       msr = rdmsr(GLCP_DELAY_CONTROLS);
+       msr.hi &= ~(7 << 20);                           /* clear bits 54:52 */
+       if (GeodeLinkSpeed() < 200){
+               msr.hi |= 2 << 20;
+       }
+       wrmsr(GLCP_DELAY_CONTROLS, msr);
+
+       msr = rdmsr(MC_CFCLK_DBUG);
+       msr.hi |= CFCLK_UPPER_MTST_B2B_DIS_SET | CFCLK_UPPER_MTEST_EN_SET | CFCLK_UPPER_MTST_RBEX_EN_SET;
+       msr.lo |= CFCLK_LOWER_TRISTATE_DIS_SET;
+       wrmsr(MC_CFCLK_DBUG, msr);
+
+       print_debug("Enabled MTest for TLA debug\r\n");
+}
+
+static void sdram_set_registers(const struct mem_controller *ctrl)
+{
+       msr_t msr;
+       uint32_t msrnum;
+
+       /* Set Timing Control */
+       msrnum = MC_CF1017_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo &= ~(7 << CF1017_LOWER_RD_TMG_CTL_SHIFT);
+       if (GeodeLinkSpeed() < 334){
+               msr.lo |= (3 << CF1017_LOWER_RD_TMG_CTL_SHIFT);
+       }
+       else{
+               msr.lo |= (4 << CF1017_LOWER_RD_TMG_CTL_SHIFT);
+       }
+       wrmsr(msrnum, msr);
+
+       /* Set Refresh Staggering */
+       msrnum = MC_CF07_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo &= ~0xF0;
+       msr.lo |= 0x40;                 /* set refresh to 4SDRAM clocks */
+       wrmsr(msrnum, msr);
+
+       /* Memory Interleave: Set HOI here otherwise default is LOI */
+       /* msrnum = MC_CF8F_DATA;
+       msr = rdmsr(msrnum);
+       msr.hi |= CF8F_UPPER_HOI_LOI_SET;
+       wrmsr(msrnum, msr); */
+}
+
+
+static void sdram_set_spd_registers(const struct mem_controller *ctrl)
+{
+       uint8_t spd_byte;
+
+       POST_CODE(POST_MEM_SETUP);              // post_70h
+
+       spd_byte = spd_read_byte(DIMM0, SPD_MODULE_ATTRIBUTES);
+       /* Check DIMM is not Register and not Buffered DIMMs. */
+       if ((spd_byte != 0xFF) && (spd_byte & 3) ){
+               print_debug("DIMM0 NOT COMPATIBLE\r\n");
+               POST_CODE(ERROR_UNSUPPORTED_DIMM);
+               __asm__ __volatile__("hlt\n");
+       }
+       spd_byte = spd_read_byte(DIMM1, SPD_MODULE_ATTRIBUTES);
+       if ((spd_byte != 0xFF) && (spd_byte & 3)){
+               print_debug("DIMM1 NOT COMPATIBLE\r\n");
+               POST_CODE(ERROR_UNSUPPORTED_DIMM);
+               __asm__ __volatile__("hlt\n");
+       }
+
+       POST_CODE(POST_MEM_SETUP2);             // post_72h
+
+       /* Check that the memory is not overclocked. */
+       checkDDRMax();
+
+       /* Size the DIMMS */
+       POST_CODE(POST_MEM_SETUP3);             // post_73h
+       auto_size_dimm(DIMM0);
+       POST_CODE(POST_MEM_SETUP4);             // post_74h
+       auto_size_dimm(DIMM1);
+
+       /* Set CAS latency */
+       POST_CODE(POST_MEM_SETUP5);             // post_75h
+       setCAS();
+
+       /* Set all the other latencies here (tRAS, tRP....) */
+       set_latencies();
 
-       //Delay
-       i=inb(0x61);
-       while (i==inb(0x61));
-       i=inb(0x61);
-       while (i==inb(0x61));
-       i=inb(0x61);
-       while (i==inb(0x61));
+       /* Set Extended Mode Registers */
+       set_extended_mode_registers();
 
-       /* 8. load Mode Register by set and clear PROG_DRAM */
+       /* Set Memory Refresh Rate */
+       set_refresh_rate();
+
+}
+
+/* Section 6.1.3, LX processor databooks, BIOS Initialization Sequence
+ * Section 4.1.4, GX/CS5535 GeodeROM Porting guide */
+static void sdram_enable(int controllers, const struct mem_controller *ctrl)
+{
+       uint32_t i, msrnum;
+       msr_t msr;
+
+/*********************************************************************
+;* Turn on MC/DIMM interface per JEDEC
+;* 1) Clock stabilizes > 200us
+;* 2) Assert CKE
+;* 3) Precharge All to put all banks into an idles state
+;* 4) EMRS to enable DLL
+;* 6) MRS w/ memory config & reset DLL set
+;* 7) Wait 200 clocks (2us)
+;* 8) Precharge All and 2 Auto refresh
+;* 9) MRS w/ memory config & reset DLL clear
+;* 8) DDR SDRAM ready for normal operation
+;********************************************************************/
+       POST_CODE(POST_MEM_ENABLE);             // post_76h
+
+       /* Only enable MTest for TLA memory debug */
+       /*EnableMTest();*/
+
+       /* If both Page Size = "Not Installed" we have a problems and should halt. */
        msr = rdmsr(MC_CF07_DATA);
-       msr.lo |=  0x01;
-       wrmsr(MC_CF07_DATA, msr);
-       msr.lo &= ~0x01;
-       wrmsr(MC_CF07_DATA, msr);
+       if ((msr.hi & ((7 << CF07_UPPER_D1_PSZ_SHIFT) | (7 << CF07_UPPER_D0_PSZ_SHIFT))) \
+               == ((7 << CF07_UPPER_D1_PSZ_SHIFT) | (7 << CF07_UPPER_D0_PSZ_SHIFT))){
+               print_debug("No memory in the system\r\n");
+               POST_CODE(ERROR_NO_DIMMS);
+               __asm__ __volatile__("hlt\n");
+       }
 
-       /* wait 200 SDCLKs */
-       for (i = 0; i < 200; i++)
-               outb(0xaa, 0x80);
+       /*      Set CKEs */
+       msrnum = MC_CFCLK_DBUG;
+       msr = rdmsr(msrnum);
+       msr.lo &= ~(CFCLK_LOWER_MASK_CKE_SET0 | CFCLK_LOWER_MASK_CKE_SET1);
+       wrmsr(msrnum, msr);
+
+
+       /* Force Precharge All on next command, EMRS */
+       msrnum = MC_CFCLK_DBUG;
+       msr = rdmsr(msrnum);
+       msr.lo |= CFCLK_LOWER_FORCE_PRE_SET;
+       wrmsr(msrnum,msr);
+
+
+       /* EMRS to enable DLL (pre-setup done in setExtendedModeRegisters) */
+       msrnum =  MC_CF07_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo |= CF07_LOWER_PROG_DRAM_SET | CF07_LOWER_LOAD_MODE_DDR_SET;
+       wrmsr(msrnum, msr);
+       msr.lo &= ~(CF07_LOWER_PROG_DRAM_SET | CF07_LOWER_LOAD_MODE_DDR_SET);
+       wrmsr(msrnum, msr);
+
+
+       /* Clear Force Precharge All */
+       msrnum = MC_CFCLK_DBUG;
+       msr = rdmsr(msrnum);
+       msr.lo &= ~CFCLK_LOWER_FORCE_PRE_SET;
+       wrmsr(msrnum, msr);
+
+
+       /* MRS Reset DLL - set */
+       msrnum = MC_CF07_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo |= CF07_LOWER_PROG_DRAM_SET | CF07_LOWER_LOAD_MODE_DLL_RESET;
+       wrmsr(msrnum,msr);
+       msr.lo &= ~(CF07_LOWER_PROG_DRAM_SET | CF07_LOWER_LOAD_MODE_DLL_RESET);
+       wrmsr(msrnum, msr);
+
+
+       /* 2us delay (200 clocks @ 200Mhz). We probably really don't need this but.... better safe. */
+       /* Wait 2 PORT61 ticks. between 15us and 30us */
+       /* This would be endless if the timer is stuck. */
+       while ((inb(0x61)));  /* find the first edge */
+       while (!(~inb(0x61)));
 
-       print_debug("DRAM controller init done.\r\n");
 
-       /* Fixes from Jordan Crouse of AMD. */
+       /* Force Precharge All on the next command, auto-refresh */
+       msrnum = MC_CFCLK_DBUG;
+       msr = rdmsr(msrnum);
+       msr.lo |= CFCLK_LOWER_FORCE_PRE_SET;
+       wrmsr(msrnum, msr);
+
+
+       /* Manually AUTO refresh #1 */
+       /* If auto refresh was not enabled above we would need to do 8 refreshes to prime the pump before these 2. */
+       msrnum = MC_CF07_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo |= CF07_LOWER_REF_TEST_SET;
+       wrmsr(msrnum, msr);
+       msr.lo &= ~CF07_LOWER_REF_TEST_SET;
+       wrmsr(msrnum, msr);
+
+       /* Clear Force Precharge All */
+       msrnum = MC_CFCLK_DBUG;
+       msr = rdmsr(msrnum);
+       msr.lo &= ~CFCLK_LOWER_FORCE_PRE_SET;
+       wrmsr(msrnum, msr);
+
+
+       /* Manually AUTO refresh */
+       /* The MC should insert the right delay between the refreshes */
+       msrnum = MC_CF07_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo |= CF07_LOWER_REF_TEST_SET;
+       wrmsr(msrnum, msr);
+       msr.lo &= ~CF07_LOWER_REF_TEST_SET;
+       wrmsr(msrnum, msr);
+
+
+       /* MRS Reset DLL - clear */
+       msrnum = MC_CF07_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo |= CF07_LOWER_PROG_DRAM_SET;
+       wrmsr(msrnum, msr);
+       msr.lo &= ~CF07_LOWER_PROG_DRAM_SET;
+       wrmsr(msrnum, msr);
+
+
+       /* Allow MC to tristate during idle cycles with MTEST OFF */
+       msrnum = MC_CFCLK_DBUG;
+       msr = rdmsr(msrnum);
+       msr.lo &= ~CFCLK_LOWER_TRISTATE_DIS_SET;
+       wrmsr(msrnum, msr);
+
+
+       /* Disable SDCLK DIMM1 slot if no DIMM installed to save power. */
+       msr = rdmsr(MC_CF07_DATA);
+       if ((msr.hi & (7 << CF07_UPPER_D1_PSZ_SHIFT)) == (7 << CF07_UPPER_D1_PSZ_SHIFT)){
+               msrnum = GLCP_DELAY_CONTROLS;
+               msr = rdmsr(msrnum);
+               msr.hi |= (1 << 23);    /* SDCLK bit for 2.0 */
+               wrmsr(msrnum, msr);
+       }
+
+       /* Set PMode0 Sensitivity Counter */
+       msr.lo = 0;                     /* pmode 0=0 most aggressive */
+       msr.hi = 0x200;         /* pmode 1=200h */
+       wrmsr(MC_CF_PMCTR, msr);
+
+
+       /* Set PMode1 Up delay enable */
+       msrnum = MC_CF1017_DATA;
+       msr = rdmsr(msrnum);
+       msr.lo |= (209 << 8);   /* bits[15:8] = 209 */
+       wrmsr(msrnum, msr);
+
+       print_debug("DRAM controller init done.\r\n");
+       POST_CODE(POST_MEM_SETUP_GOOD);         //0x7E
 
        /* make sure there is nothing stale in the cache */
-       __asm__("wbinvd\n");
+       /* CAR stack is in the cache __asm__ __volatile__("wbinvd\n");*/
 
-       print_debug("RAM DLL lock\r\n");
        /* The RAM dll needs a write to lock on so generate a few dummy writes */
+       /* Note: The descriptor needs to be enabled to point at memory */
        volatile unsigned long *ptr;
        for (i=0;i<5;i++) {
                ptr = (void *)i;
                *ptr = (unsigned long)i;
        }
+       /* SWAPSiF for PBZ 4112 (Errata 34) */
+       /* check for failed DLL settings now that we have done a memory write. */
+       msrnum = GLCP_DELAY_CONTROLS;
+       msr = rdmsr(msrnum);
+       if ((msr.lo & 0x7FF) == 0x104) {
+
+               /* If you had it you would need to clear out the fail boot count flag */
+               /*       (depending on where it counts from etc).*/
+
+               /* The reset we are about to perform clears the PM_SSC register in the */
+               /*       5536 so will need to store the S3 resume flag in NVRAM otherwise */
+               /*       it would do a normal boot */
+
+               /* Reset the system */
+               msrnum = MDD_SOFT_RESET;
+               msr = rdmsr(msrnum);
+               msr.lo |= 1;
+               wrmsr(msrnum, msr);
+}
+       print_debug("RAM DLL lock\r\n");
+
 
 }