This patch adds support for the northbridge integrated into the AMD
Geode LX platform, including memory and graphics.

Signed-off-by: Marc Jones <marc.jones@amd.com>
Index: LinuxBIOSv2/src/northbridge/amd/lx/Config.lb
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/Config.lb	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/Config.lb	2007-05-03 10:34:32.000000000 -0600
@@ -1,5 +1,4 @@
 config chip.h
 object northbridge.o
 object northbridgeinit.o
-object chipsetinit.o
 object grphinit.o
Index: LinuxBIOSv2/src/northbridge/amd/lx/chip.h
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/chip.h	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/chip.h	2007-05-03 10:14:32.000000000 -0600
@@ -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;
Index: LinuxBIOSv2/src/northbridge/amd/lx/grphinit.c
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/grphinit.c	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/grphinit.c	2007-05-03 10:34:32.000000000 -0600
@@ -1,31 +1,14 @@
+/*
+*
+* 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.
@@ -40,7 +23,7 @@
 	/* 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 @@
 	 * 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: LinuxBIOSv2/src/northbridge/amd/lx/northbridge.c
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/northbridge.c	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/northbridge.c	2007-05-03 10:34:32.000000000 -0600
@@ -1,3 +1,9 @@
+/*
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+*/
+
 #include <console/console.h>
 #include <arch/io.h>
 #include <stdint.h>
@@ -7,20 +13,20 @@
 #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.*/
 #define IM_QWAIT 0x100000
 
 #define DMCF_WRITE_SERIALIZE_REQUEST (2<<12) /* 2 outstanding */ /* in high */
-#define DMCF_SERIAL_LOAD_MISSES  (2) /* enabled */
+#define DMCF_SERIAL_LOAD_MISSES	 (2) /* enabled */
 
 /* these are the 8-bit attributes for controlling RCONF registers */
 #define CACHE_DISABLE (1<<0)
@@ -56,9 +62,11 @@
 
 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);
 
@@ -86,334 +94,65 @@
 	/* GLIU0 */
 	P2D_BM(MSR_GLIU0_BASE1, 0x1, 0x0, 0x0, 0xfff80),
 	P2D_BM(MSR_GLIU0_BASE2, 0x1, 0x0, 0x80000, 0xfffe0),
-	P2D_SC(MSR_GLIU0_SHADOW, 0x1, 0x0, 0x0,  0xff03, 0xC0000),
+	P2D_SC(MSR_GLIU0_SHADOW, 0x1, 0x0, 0x0,	 0xff03, 0xC0000),
 	/* GLIU1 */
 	P2D_BM(MSR_GLIU1_BASE1, 0x1, 0x0, 0x0, 0xfff80),
 	P2D_BM(MSR_GLIU1_BASE2, 0x1, 0x0, 0x80000, 0xfffe0),
-	P2D_SC(MSR_GLIU1_SHADOW, 0x1, 0x0, 0x0,  0xff03, 0xC0000),
+	P2D_SC(MSR_GLIU1_SHADOW, 0x1, 0x0, 0x0,	 0xff03, 0xC0000),
 	{0}
 };
 
-/* todo: add a resource record. We don't do this here because this may be called when 
+/* 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) 
+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__);
-	
+
 	enable_shadow(dev);
 	/*
 	 * Swiss cheese
 	 */
 	//msr = rdmsr(MSR_GLIU0_SHADOW);
-	
+
 	//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);
@@ -457,18 +196,18 @@
 	if (line) {
 		pci_write_config8(dev, PCI_INTERRUPT_LINE, 0);
 	}
-	
+
 	/* set the cache line size, so far 64 bytes is good for everyone */
 	pci_write_config8(dev, PCI_CACHE_LINE_SIZE, 64 >> 2);
 }
 
 static struct device_operations northbridge_operations = {
-	.read_resources   = pci_dev_read_resources,
-	.set_resources    = northbridge_set_resources,
+	.read_resources	  = pci_dev_read_resources,
+	.set_resources	  = northbridge_set_resources,
 	.enable_resources = pci_dev_enable_resources,
-	.init             = northbridge_init,
-	.enable           = 0,
-	.ops_pci          = 0,
+	.init			  = northbridge_init,
+	.enable			  = 0,
+	.ops_pci		  = 0,
 };
 
 static struct pci_driver northbridge_driver __pci_driver = {
@@ -480,32 +219,32 @@
 
 static void pci_domain_read_resources(device_t dev)
 {
-        struct resource *resource;
+		struct resource *resource;
 	printk_spew(">> Entering northbridge.c: %s\n", __FUNCTION__);
 
-        /* Initialize the system wide io space constraints */
-        resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0,0));
-        resource->limit = 0xffffUL;
-        resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
-
-        /* Initialize the system wide memory resources constraints */
-        resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1,0));
-        resource->limit = 0xffffffffULL;
-        resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+		/* Initialize the system wide io space constraints */
+		resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0,0));
+		resource->limit = 0xffffUL;
+		resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+		/* Initialize the system wide memory resources constraints */
+		resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1,0));
+		resource->limit = 0xffffffffULL;
+		resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
 }
 
 static void ram_resource(device_t dev, unsigned long index,
-        unsigned long basek, unsigned long sizek)
+		unsigned long basek, unsigned long sizek)
 {
-        struct resource *resource;
+		struct resource *resource;
 
 	if (!sizek) return;
-	
-        resource = new_resource(dev, index);
-        resource->base  = ((resource_t)basek) << 10;
-        resource->size  = ((resource_t)sizek) << 10;
+
+		resource = new_resource(dev, index);
+		resource->base	= ((resource_t)basek) << 10;
+		resource->size	= ((resource_t)sizek) << 10;
 	resource->flags =  IORESOURCE_MEM | IORESOURCE_CACHEABLE |
-                IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+				IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
 }
 
 static void pci_domain_set_resources(device_t dev)
@@ -516,12 +255,12 @@
 	printk_spew(">> Entering northbridge.c: %s\n", __FUNCTION__);
 
 	mc_dev = dev->link[0].children;
-	if (mc_dev) 
+	if (mc_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_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);
@@ -557,23 +294,23 @@
 {
 	printk_spew(">> Entering northbridge.c: %s\n", __FUNCTION__);
 
-        max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
-        return max;
+		max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
+		return max;
 }
 
 static struct device_operations pci_domain_ops = {
-        .read_resources   = pci_domain_read_resources,
-        .set_resources    = pci_domain_set_resources,
-        .enable_resources = enable_childrens_resources,
-        .scan_bus         = pci_domain_scan_bus,
-        .enable           = pci_domain_enable,
-};  
+		.read_resources	  = pci_domain_read_resources,
+		.set_resources	  = pci_domain_set_resources,
+		.enable_resources = enable_childrens_resources,
+		.scan_bus		  = pci_domain_scan_bus,
+		.enable			  = pci_domain_enable,
+};
 
 static void cpu_bus_init(device_t dev)
 {
 	printk_spew(">> Entering northbridge.c: %s\n", __FUNCTION__);
 
-        initialize_cpus(&dev->link[0]);
+		initialize_cpus(&dev->link[0]);
 }
 
 static void cpu_bus_noop(device_t dev)
@@ -581,26 +318,26 @@
 }
 
 static struct device_operations cpu_bus_ops = {
-        .read_resources   = cpu_bus_noop,
-        .set_resources    = cpu_bus_noop,
-        .enable_resources = cpu_bus_noop,
-        .init             = cpu_bus_init,
-        .scan_bus         = 0,
+		.read_resources	  = cpu_bus_noop,
+		.set_resources	  = cpu_bus_noop,
+		.enable_resources = cpu_bus_noop,
+		.init			  = cpu_bus_init,
+		.scan_bus		  = 0,
 };
 
 static void enable_dev(struct device *dev)
 {
-	printk_spew(">> Entering northbridge.c: %s with path %d\n", 
+	printk_spew(">> Entering northbridge.c: %s with path %d\n",
 		__FUNCTION__, dev->path.type);
 
-        /* Set the operations if it is a special bus type */
+		/* Set the operations if it is a special bus type */
 	if (dev->path.type == DEVICE_PATH_PCI_DOMAIN)
 		dev->ops = &pci_domain_ops;
 	else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER)
-                dev->ops = &cpu_bus_ops;
+				dev->ops = &cpu_bus_ops;
 }
 
 struct chip_operations northbridge_amd_lx_ops = {
 	CHIP_NAME("AMD LX Northbridge")
-	.enable_dev = enable_dev, 
+	.enable_dev = enable_dev,
 };
Index: LinuxBIOSv2/src/northbridge/amd/lx/northbridgeinit.c
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/northbridgeinit.c	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/northbridgeinit.c	2007-05-03 10:34:32.000000000 -0600
@@ -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;
@@ -22,27 +27,28 @@
 };
 
 struct gliutable gliu0table[] = {
-	{.desc_name=MSR_GLIU0_BASE1,  .desc_type= BM,.hi= MSR_MC + 0x0,.lo=  0x0FFF80},		/*  0-7FFFF to MC*/
-	{.desc_name=MSR_GLIU0_BASE2,  .desc_type= BM,.hi= MSR_MC + 0x0,.lo=(0x80 << 20) + 0x0FFFE0},		/*  80000-9ffff to Mc*/
-	{.desc_name=MSR_GLIU0_SHADOW, .desc_type= SC_SHADOW,.hi=  MSR_MC + 0x0,.lo=  0x03},	/*  C0000-Fffff split to MC and PCI (sub decode) A0000-Bffff handled by SoftVideo*/
-	{.desc_name=MSR_GLIU0_SYSMEM, .desc_type= R_SYSMEM,.hi=  MSR_MC,.lo=  0x0},		/*  Catch and fix dynamicly.*/
-	{.desc_name=MSR_GLIU0_SMM,    .desc_type= BMO_SMM,.hi=  MSR_MC,.lo=  0x0},		/*  Catch and fix dynamicly.*/
+	{.desc_name=MSR_GLIU0_BASE1,  .desc_type= BM,.hi= MSR_MC + 0x0,.lo=	 0x0FFF80},		/*	0-7FFFF to MC*/
+	{.desc_name=MSR_GLIU0_BASE2,  .desc_type= BM,.hi= MSR_MC + 0x0,.lo=(0x80 << 20) + 0x0FFFE0},		/*	80000-9ffff to Mc*/
+	{.desc_name=MSR_GLIU0_SHADOW, .desc_type= SC_SHADOW,.hi=  MSR_MC + 0x0,.lo=	 0x03},	/*	C0000-Fffff split to MC and PCI (sub decode) A0000-Bffff handled by SoftVideo*/
+	{.desc_name=MSR_GLIU0_SYSMEM, .desc_type= R_SYSMEM,.hi=	 MSR_MC,.lo=  0x0},		/*	Catch and fix dynamicly.*/
+	{.desc_name=MSR_GLIU0_SMM,	  .desc_type= BMO_SMM,.hi=	MSR_MC,.lo=	 0x0},		/*	Catch and fix dynamicly.*/
 	{.desc_name=GLIU0_GLD_MSR_COH,.desc_type= OTHER,.hi= 0x0,.lo= GL0_CPU},
-	{.desc_name=GL_END,           .desc_type= GL_END,.hi= 0x0,.lo= 0x0},
+	{.desc_name=GL_END,			  .desc_type= GL_END,.hi= 0x0,.lo= 0x0},
 };
 
 
 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_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},		/*	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},
 };
 
-struct gliutable *gliutables[]  = {gliu0table, gliu1table, 0};
+struct gliutable *gliutables[]	= {gliu0table, gliu1table, 0};
 
 struct msrinit {
 	unsigned long msrnum;
@@ -51,54 +57,36 @@
 
 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
-	{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}},
+	{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}},
 };
 
-	/*  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*/
+/*	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*/
-	{0x0FFFFFFFF, 			{0x0FFFFFFFF, 0x0FFFFFFFF}},	/*  END*/
+	{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 @@
 	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
@@ -120,72 +105,66 @@
 	msr = rdmsr(gl->desc_name);
 
 	if (msr.lo == 0) {
-		writeglmsr(gl); 
+		writeglmsr(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;
 
-	/* 
-	 * Figure out how much RAM is in the machine and alocate all to the 
+	/*
+	 * Figure out how much RAM is in the machine and alocate all to the
 	 * 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;
-	
+	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,58 +172,57 @@
 	/* I don't think this is needed */
 	msr.hi &= 0xffffff00;
 	msr.hi |= (SMM_OFFSET >> 24);
-	msr.lo = SMM_OFFSET << 8;
-	msr.lo |= ((~(SMM_SIZE*1024)+1)>>12)&0xfffff;
-	
+	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){
-		default: 
+		default:
 			/* For Unknown types: Write then read MSR */
 			writeglmsr(gl);
-		case SC_SHADOW: /*  Check for a Shadow entry*/
+		case SC_SHADOW: /*	Check for a Shadow entry*/
 			ShadowInit(gl);
 			break;
-	
+
 		case R_SYSMEM: /*  check for a SYSMEM entry*/
 			SysmemInit(gl);
 			break;
-	
+
 		case BMO_SMM	: /*  check for a SMM entry*/
 			SMMGL0Init(gl);
 			break;
-	
+
 		case BM_SMM	: /*  check for a SMM entry*/
-			SMMGL1Init(gl);	
+			SMMGL1Init(gl);
 			break;
 		}
 		gl++;
 	}
 
 }
-	/* ***************************************************************************/
-	/* **/
-	/* *	GLPCIInit*/
-	/* **/
-	/* *	Set up GLPCI settings for reads/write into memory*/
-	/* *	R0:  0-640KB,*/
-	/* *	R1:  1MB - Top of System Memory*/
-	/* *	R2: SMM Memory*/
-	/* *	R3: Framebuffer? - not set up yet*/
-	/* *	R4: ??*/
-	/* **/
-	/* *	Entry:*/
-	/* *	Exit:*/
-	/* *	Modified:*/
-	/* **/
-	/* ***************************************************************************/
+
+/* ***************************************************************************/
+/* **/
+/* *	GLPCIInit*/
+/* **/
+/* *	Set up GLPCI settings for reads/write into memory*/
+/* *	R0:	 0-640KB,*/
+/* *	R1:	 1MB - Top of System Memory*/
+/* *	R2: SMM Memory*/
+/* *	R3: Framebuffer? - not set up yet*/
+/* *	R4: ??*/
+/* **/
+/* *	Entry:*/
+/* *	Exit:*/
+/* *	Modified:*/
+/* **/
+/* ***************************************************************************/
 static void GLPCIInit(void){
 	struct gliutable *gl = 0;
 	int i;
@@ -253,18 +231,18 @@
 	int nic_grants_control, enable_bus_parking;
 
 	/* */
-	/*  R0 - GLPCI settings for Conventional Memory space.*/
+	/*	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);
 
 	/* */
-	/*  R1 - GLPCI settings for SysMem space.*/
+	/*	R1 - GLPCI settings for SysMem space.*/
 	/* */
-	/*  Get systop from GLIU0 SYSTOP Descriptor*/
+	/* Get systop from GLIU0 SYSTOP Descriptor */
 	for(i = 0; gliu0table[i].desc_name != GL_END; i++) {
 		if (gliu0table[i].desc_type == R_SYSMEM) {
 			gl = &gliu0table[i];
@@ -276,15 +254,14 @@
 		msrnum = gl->desc_name;
 		msr = rdmsr(msrnum);
 		/* example R_SYSMEM value: 20:00:00:0f:fb:f0:01:00
-                 * translates to a base of 0x00100000 and top of 0xffbf0000
-                 * base of 1M and top of around 256M
+				 * translates to a base of 0x00100000 and top of 0xffbf0000
+				 * base of 1M and top of around 256M
 		 */
 		/* we have to create a page-aligned (4KB page) address for base and top */
 		/* 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 @@
 		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*/;
+	/* 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 */
 
 	msrnum = CPU_RCONF_A0_BF;
 	wrmsr(msrnum, msr);
@@ -320,7 +298,7 @@
 	msrnum = CPU_RCONF_E0_FF;
 	wrmsr(msrnum, msr);
 
-	/*  Set Non-Cacheable Read Only for NorthBound Transactions to Memory. The Enable bit is handled in the Shadow setup.*/
+	/* Set Non-Cacheable Read Only for NorthBound Transactions to Memory. The Enable bit is handled in the Shadow setup. */
 	msrnum = GLPCI_A0_BF;
 	msr.hi =  0x35353535;
 	msr.lo =  0x35353535;
@@ -336,22 +314,21 @@
 	msr.lo =  0x35353535;
 	wrmsr(msrnum, msr);
 
-	/*  Set WSREQ*/
+	/* Set WSREQ */
 	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_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;
 	nic_grants_control = (0x4 << GLPCI_ARB_UPPER_R2_SHIFT) | (0x3 << GLPCI_ARB_UPPER_H2_SHIFT );
@@ -360,13 +337,13 @@
 	msr = rdmsr(msrnum);
 
 	msr.hi |=  nic_grants_control;
-	msr.lo |=  enable_cpu_override  | enable_preempt | enable_bus_parking;
+	msr.lo |=  enable_cpu_override	| enable_preempt | enable_bus_parking;
 	wrmsr(msrnum, msr);
 
 	msrnum = GLPCI_CTRL;
 	msr = rdmsr(msrnum);
 
-	msr.lo |=  GLPCI_CTRL_LOWER_ME_SET | GLPCI_CTRL_LOWER_OWC_SET | GLPCI_CTRL_LOWER_PCD_SET; 	/*   (Out will be disabled in CPUBUG649 for < 2.0 parts .)*/
+	msr.lo |=  GLPCI_CTRL_LOWER_ME_SET | GLPCI_CTRL_LOWER_OWC_SET | GLPCI_CTRL_LOWER_PCD_SET;	/* (Out will be disabled in CPUBUG649 for < 2.0 parts .) */
 	msr.lo |=  GLPCI_CTRL_LOWER_LDE_SET;
 
 	msr.lo &=  ~ (0x03 << GLPCI_CTRL_LOWER_IRFC_SHIFT);
@@ -374,84 +351,61 @@
 
 	msr.lo &=  ~ (0x07 << GLPCI_CTRL_LOWER_IRFT_SHIFT);
 	msr.lo |=  0x06 << GLPCI_CTRL_LOWER_IRFT_SHIFT;
-	
+
 	msr.hi &=  ~ (0x0f << GLPCI_CTRL_UPPER_FTH_SHIFT);
 	msr.hi |=  0x0F << GLPCI_CTRL_UPPER_FTH_SHIFT;
-	
+
 	msr.hi &=  ~ (0x0f << GLPCI_CTRL_UPPER_RTH_SHIFT);
 	msr.hi |=  0x0F << GLPCI_CTRL_UPPER_RTH_SHIFT;
-	
+
 	msr.hi &=  ~ (0x0f << GLPCI_CTRL_UPPER_SBRTH_SHIFT);
 	msr.hi |=  0x0F << GLPCI_CTRL_UPPER_SBRTH_SHIFT;
-	
+
 	msr.hi &=  ~ (0x03 << GLPCI_CTRL_UPPER_WTO_SHIFT);
 	msr.hi |=  0x06 << GLPCI_CTRL_UPPER_WTO_SHIFT;
-	
+
 	msr.hi &=  ~ (0x03 << GLPCI_CTRL_UPPER_ILTO_SHIFT);
 	msr.hi |=  0x00 << GLPCI_CTRL_UPPER_ILTO_SHIFT;
 	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*/
+	/* GLPCI_SPARE */
 	msrnum = GLPCI_SPARE;
 	msr = rdmsr(msrnum);
 	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);
-
 }
 
 
 
-	/* ***************************************************************************/
-	/* **/
-	/* *	ClockGatingInit*/
-	/* **/
-	/* *	Enable Clock Gating.*/
-	/* **/
-	/* *	Entry:*/
-	/* *	Exit:*/
-	/* *	Modified:*/
-	/* **/
-	/* ***************************************************************************/
-static void 
-ClockGatingInit (void){
+/* ***************************************************************************/
+/* **/
+/* *	ClockGatingInit*/
+/* **/
+/* *	Enable Clock Gating.*/
+/* **/
+/* *	Entry:*/
+/* *	Exit:*/
+/* *	Modified:*/
+/* **/
+/* ***************************************************************************/
+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__, 
+		/* printk_debug("%s: MSR 0x%08x will be set to	0x%08x:0x%08x\n", __FUNCTION__,
 			gating->msrnum, msr.hi, msr.lo); */ // GX3
 		wrmsr(gating->msrnum, msr);	// MSR - See the table above
 		gating +=1;
@@ -459,35 +413,33 @@
 
 }
 
-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;
-		/* printk_debug("%s: MSR 0x%08x will be set to 0x%08x:0x%08x\n", __FUNCTION__, 
-			prio->msrnum, msr.hi, msr.lo);  */ // GX3
+		/* printk_debug("%s: MSR 0x%08x will be set to 0x%08x:0x%08x\n", __FUNCTION__,
+			prio->msrnum, msr.hi, msr.lo);	*/ // GX3
 		wrmsr(prio->msrnum, msr);	// MSR - See the table above
 		prio +=1;
 	}
 }
 
 
-	
+
 /*
  *	Get the GLIU0 shadow register settings
  *	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 @@
  *	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;
@@ -555,9 +507,8 @@
 static void setShadowGLPCI(uint32_t shadowHi, uint32_t shadowLo)
 {
 	msr_t msr;
-	
-// Set the Enable Register.
 
+	// Set the Enable Register.
 	msr = rdmsr(GLPCI_REN);
 	msr.lo &= 0xFFFF00FF;
 	msr.lo |= ( (shadowLo & 0xFFFF0000) >> 8);
@@ -589,29 +540,16 @@
 
 				msr = rdmsr(pTable->desc_name);
 				msr.lo = (uint32_t) shadowSettings;
-				msr.hi &= 0xFFFF0000;		// maintain PDID in upper EDX
+				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,15 +561,15 @@
 
 /***************************************************************************
  *
- * RCONFInit
+ * L1Init
  *	  Set up RCONF_DEFAULT and any other RCONF registers needed
  *
- *  DEVRC_RCONF_DEFAULT:
- *  ROMRC(63:56) = 04h	 ; write protect ROMBASE
- *  ROMBASE(36:55) = 0FFFC0h ; Top of PCI/bottom of rom chipselect area
- *  DEVRC(35:28) =  39h	 ; cache disabled in PCI memory + WS bit on + Write Combine + write burst.
- *  SYSTOP(27:8) = top of system memory
- *  SYSRC(7:0) = 00h 		 ; writeback, can set to 08h to make writethrough 
+ *	DEVRC_RCONF_DEFAULT:
+ *	ROMRC(63:56) = 04h	 ; write protect ROMBASE
+ *	ROMBASE(36:55) = 0FFFC0h ; Top of PCI/bottom of rom chipselect area
+ *	DEVRC(35:28) =	39h	 ; cache disabled in PCI memory + WS bit on + Write Combine + write burst.
+ *	SYSTOP(27:8) = top of system memory
+ *	SYSRC(7:0) = 00h		 ; writeback, can set to 08h to make writethrough
  *
  ***************************************************************************/
 #define SYSMEM_RCONF_WRITETHROUGH 8
@@ -639,14 +577,12 @@
 #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++) {
@@ -660,26 +596,21 @@
 		while (1);
 	}
 
-// sysdescfound:	
-	/* found the descriptor... get its contents */
+	// sysdescfound:
 	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. 
+	/* 20 bit address -	 The bottom 12 bits go into bits 20-31 in eax, the
+	 * top 8 bits go into 0-7 of edx.
 	 */
 	msr.lo = (msr.lo & 0xFFFFFF00) | (msr.hi & 0xFF);
 	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
@@ -687,9 +618,10 @@
 
 	// Set ROMBASE cache properties.
 	msr.hi |= ((ROMRC_RCONF_DEFAULT >> 8) | (ROMRC_RCONF_DEFAULT << 24));
-	
+
 	// 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.
@@ -698,22 +630,85 @@
 	msr = rdmsr(CPU_RCONF_BYPASS);
 	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:*/
+/* *	Core Logic initialization:	Host bridge*/
 /* **/
 /* ***************************************************************************/
-
 void northbridge_init_early(void)
 {
 	msr_t msr;
@@ -723,34 +718,21 @@
 	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.*/
+	/*	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: LinuxBIOSv2/src/northbridge/amd/lx/pll_reset.c
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/pll_reset.c	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/pll_reset.c	2007-05-03 10:34:32.000000000 -0600
@@ -1,43 +1,90 @@
-#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;
 
-        msrGlcpSysRstpll = rdmsr(GLCP_SYS_RSTPLL);
-	
+	msrGlcpSysRstpll = rdmsr(GLCP_SYS_RSTPLL);
+
 	print_debug("_MSR GLCP_SYS_RSTPLL (");
 		print_debug_hex32(GLCP_SYS_RSTPLL);
 		print_debug(") value is: ");
 		print_debug_hex32(msrGlcpSysRstpll.hi);
 		print_debug(":");
 		print_debug_hex32(msrGlcpSysRstpll.lo);
-		print_debug("\n");
-	
-        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)
+		print_debug("\r\n");
+	POST_CODE(POST_PLL_INIT);
 
-			/* CPU and GLIU mult/div (GLMC_CLK = GLIU_CLK / 2)  */
-		msrGlcpSysRstpll.hi = PLLMSRhi;
+	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;
+			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 |= (1 << RSTPLL_LOWER_SWFLAGS_SHIFT);
 
-			/* Use SWFLAGS to remember: "we've already been here"  */
-			msrGlcpSysRstpll.lo |= 0x80000000;
+		/* "reset the chip" value */
+		msrGlcpSysRstpll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
+		wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
 
-			/* "reset the chip" value */
-			msrGlcpSysRstpll.lo |= 0x00000001;
+		/*	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");
 
-		wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
 	}
+	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: LinuxBIOSv2/src/northbridge/amd/lx/raminit.c
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/raminit.c	2007-05-03 10:28:43.000000000 -0600
+++ LinuxBIOSv2/src/northbridge/amd/lx/raminit.c	2007-05-03 10:34:32.000000000 -0600
@@ -1,123 +1,769 @@
+/*
+* 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 auto_size_dimm(unsigned int dimm){
+	uint32_t dimm_setting;
+	uint16_t dimm_size;
+	uint8_t spd_byte;
+	msr_t msr;
 
+	dimm_setting = 0;
 
-static void sdram_set_registers(const struct mem_controller *ctrl)
-{
+	/* Check that we have a dimm */
+	if (spd_read_byte(dimm, SPD_MEMORY_TYPE) == 0xFF){
+		return;
+	}
+
+	/* 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;
+
+
+	/* 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;
+
+
+	/*; 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
+	*/
+	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");
+	}
+
+	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*/
+
+	/*	 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;
+
+
+/*; 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);
+	if (dimm == DIMM0){
+		msr.hi &= 0xFFFF0000;
+		msr.hi |= dimm_setting;
+	}else{
+		msr.hi &= 0x0000FFFF;
+		msr.hi |= dimm_setting << 16;
+	}
+	wrmsr(MC_CF07_DATA, msr);
 }
 
-/* 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;
+
+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|= ((rate0 * (GeodeLinkSpeed()/2))/16) << CF07_LOWER_REF_INT_SHIFT;
+	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 */
+
+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;
 
-	/* 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.
-
-	/* 2)  Initialize the following GLMC registers:
-	 *	— MSR 2000001Ah[15:8] = C8h
-	 *	— MSR 20002004h[2] = 0, [0] = 1
-	 */
-	msr.hi = 0x00000000;
-	msr.lo = 0x130AD101;
+	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;
+
+
+	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);
 
-	//ok
-	msr.hi = 0x00000000;
-	msr.lo = 0x00000001;
-	wrmsr(MC_GLD_MSR_PM, 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);
+	}
+}
 
-	/* 3) Release MASK_CKE[1:0] (MSR 2000001Dh[9:8] = 11) */
+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.hi = 0x00000000;
-	msr.lo = 0x00000000;
-	wrmsr(MC_CFCLK_DBUG, msr);
-	
-	// reset memory controller
 	msr = rdmsr(MC_CF07_DATA);
-	msr.lo |=  0x00000002;
-	wrmsr(MC_CF07_DATA, msr);
-	msr.lo &= 0xFFFFFFFD;
+		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;
 
-	/* 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++) {
-		msr = rdmsr(MC_CF07_DATA);
-		msr.lo |=  0x00000008;
-		wrmsr(MC_CF07_DATA, msr);
-		msr.lo &= 0xFFFFFFF7;
-		wrmsr(MC_CF07_DATA, 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);
 
-	/* 5) Initialize REF_INT (MSR 20000018h[23:8]) to set refresh interval.	*/
-	msr.lo |= 0x3A00;
-	wrmsr(MC_CF07_DATA, msr);
+	print_debug("Enabled MTest for TLA debug\r\n");
+}
 
-	/* 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 sdram_set_registers(const struct mem_controller *ctrl)
+{
+	msr_t msr;
+	uint32_t msrnum;
 
-	msr.lo &= ~((0x01 << 28) | 0x01);
-	wrmsr(MC_CF07_DATA, msr);
+	/* 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();
+
+	/* Set Extended Mode Registers */
+	set_extended_mode_registers();
+
+	/* 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
 
-	/* 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
+	/* 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 << 27) | 0x01);
-	wrmsr(MC_CF07_DATA, msr);
-	msr.lo &= ~((0x01 << 27) | 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");
+	}
+
+	/*	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)));
+
+
+	/* 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);
 
-	//Delay
-	i=inb(0x61);
-	while (i==inb(0x61));
-	i=inb(0x61);
-	while (i==inb(0x61));
-	i=inb(0x61);
-	while (i==inb(0x61));
 
-	/* 8. load Mode Register by set and clear PROG_DRAM */
+	/* Disable SDCLK DIMM1 slot if no DIMM installed to save power. */
 	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_D1_PSZ_SHIFT)){
+		msrnum = GLCP_DELAY_CONTROLS;
+		msr = rdmsr(msrnum);
+		msr.hi |= (1 << 23);	/* SDCLK bit for 2.0 */
+		wrmsr(msrnum, msr);
+	}
 
-	/* wait 200 SDCLKs */
-	for (i = 0; i < 200; i++)
-		outb(0xaa, 0x80);
+	/* Set PMode0 Sensitivity Counter */
+	msr.lo = 0;			/* pmode 0=0 most aggressive */
+	msr.hi = 0x200;		/* pmode 1=200h */
+	wrmsr(MC_CF_PMCTR, msr);
 
-	print_debug("DRAM controller init done.\r\n");
 
-	/* Fixes from Jordan Crouse of AMD. */
+	/* 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");
+
 
 }
Index: LinuxBIOSv2/src/northbridge/amd/lx/chipsetinit.c
===================================================================
--- LinuxBIOSv2.orig/src/northbridge/amd/lx/chipsetinit.c	2007-05-03 10:28:43.000000000 -0600
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -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
-		}
-	}
-
-}

--
Jordan Crouse
Senior Linux Engineer
Advanced Micro Devices, Inc.
<www.amd.com/embeddedprocessors>




