- Cleanups on the romcc side including a pci interface that uses
  fewer registers, and is easier to hardcode.


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@838 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/src/arch/i386/boot/linuxbios_table.c b/src/arch/i386/boot/linuxbios_table.c
index 1925f2d..3b14488 100644
--- a/src/arch/i386/boot/linuxbios_table.c
+++ b/src/arch/i386/boot/linuxbios_table.c
@@ -115,7 +115,7 @@
 		{ LB_TAG_LINKER,         linuxbios_linker,         },
 		{ LB_TAG_ASSEMBLER,      linuxbios_assembler,      },
 	};
-	int i;
+	unsigned int i;
 	for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
 		struct lb_string *rec;
 		size_t len;
diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h
index 02cc272..66e6dc0 100644
--- a/src/arch/i386/include/arch/romcc_io.h
+++ b/src/arch/i386/include/arch/romcc_io.h
@@ -35,50 +35,56 @@
 	__builtin_hlt();
 }
 
-static unsigned int config_cmd(unsigned char bus, unsigned devfn, unsigned where)
+typedef __builtin_msr_t msr_t;
+
+static msr_t rdmsr(unsigned long index)
 {
-	return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3);
+	return __builtin_rdmsr(index);
 }
 
-static unsigned char pcibios_read_config_byte(
-	unsigned char bus, unsigned devfn, unsigned where)
+static void wrmsr(unsigned long index, msr_t msr)
 {
-	outl(config_cmd(bus, devfn, where), 0xCF8);
-	return inb(0xCFC + (where & 3));
+	__builtin_wrmsr(index, msr.lo, msr.hi);
 }
 
-static unsigned short pcibios_read_config_word(
-	unsigned char bus, unsigned devfn, unsigned where)
+#define PCI_ADDR(BUS, DEV, FN, WHERE) ( \
+	(((BUS) & 0xFF) << 16) | \
+	(((DEV) & 0x1f) << 11) | \
+	(((FN) & 0x07) << 8) | \
+	((WHERE) & 0xFF))
+
+static unsigned char pci_read_config8(unsigned addr)
 {
-	outl(config_cmd(bus, devfn, where), 0xCF8);
-	return inw(0xCFC + (where & 2));
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	return inb(0xCFC + (addr & 3));
 }
 
-static unsigned int pcibios_read_config_dword(
-	unsigned char bus, unsigned devfn, unsigned where)
+static unsigned short pci_read_config16(unsigned addr)
 {
-	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	return inw(0xCFC + (addr & 2));
+}
+
+static unsigned int pci_read_config32(unsigned addr)
+{
+	outl(0x80000000 | (addr & ~3), 0xCF8);
 	return inl(0xCFC);
 }
 
-
-static void pcibios_write_config_byte(
-	unsigned char bus, unsigned devfn, unsigned where, unsigned char value)
+static void pci_write_config8(unsigned addr, unsigned char value)
 {
-	outl(config_cmd(bus, devfn, where), 0xCF8);
-	outb(value, 0xCFC + (where & 3));
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	outb(value, 0xCFC + (addr & 3));
 }
 
-static void pcibios_write_config_word(
-	unsigned char bus, unsigned devfn, unsigned where, unsigned short value)
+static void pci_write_config16(unsigned addr, unsigned short value)
 {
-	outl(config_cmd(bus, devfn, where), 0xCF8);
-	outw(value, 0xCFC + (where & 2));
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	outw(value, 0xCFC + (addr & 2));
 }
 
-static void pcibios_write_config_dword(
-	unsigned char bus, unsigned devfn, unsigned where, unsigned int value)
+static void pci_write_config32(unsigned addr, unsigned int value)
 {
-	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outl(0x80000000 | (addr & ~3), 0xCF8);
 	outl(value, 0xCFC);
 }
diff --git a/src/arch/i386/include/stdint.h b/src/arch/i386/include/stdint.h
index 58d7519..0fc4346 100644
--- a/src/arch/i386/include/stdint.h
+++ b/src/arch/i386/include/stdint.h
@@ -1,6 +1,12 @@
 #ifndef I386_STDINT_H
 #define I386_STDINT_H
 
+#if defined(__GNUC__)
+#define __HAVE_LONG_LONG__ 1
+#else
+#define __HAVE_LONG_LONG__ 0
+#endif
+
 /* Exact integral types */
 typedef unsigned char      uint8_t;
 typedef signed char        int8_t; 
@@ -11,8 +17,10 @@
 typedef unsigned int       uint32_t;
 typedef signed int         int32_t;
 
+#if __HAVE_LONG_LONG__
 typedef unsigned long long uint64_t;
 typedef signed long long   int64_t;
+#endif
 
 /* Small types */
 typedef unsigned char      uint_least8_t;
@@ -24,8 +32,10 @@
 typedef unsigned int       uint_least32_t;
 typedef signed int         int_least32_t;
 
+#if __HAVE_LONG_LONG__
 typedef unsigned long long uint_least64_t;
 typedef signed long long   int_least64_t;
+#endif
 
 /* Fast Types */
 typedef unsigned char      uint_fast8_t;
@@ -37,16 +47,25 @@
 typedef unsigned int       uint_fast32_t;
 typedef signed int         int_fast32_t;
 
+#if __HAVE_LONG_LONG__
 typedef unsigned long long uint_fast64_t;
 typedef signed long long   int_fast64_t;
+#endif 
 
 /* Types for `void *' pointers.  */
 typedef int                intptr_t;
 typedef unsigned int       uintptr_t;
 
 /* Largest integral types */
+#if __HAVE_LONG_LONG__
 typedef long long int      intmax_t;
 typedef unsigned long long uintmax_t;
+#else
+typedef long int           intmax_t;
+typedef unsigned long int  uintmax_t;
+#endif
+
+#undef __HAVE_LONG_LONG__
 
 
 #endif /* I386_STDINT_H */
diff --git a/src/arch/i386/lib/console.c b/src/arch/i386/lib/console.c
index 8c8eccd..83502ea 100644
--- a/src/arch/i386/lib/console.c
+++ b/src/arch/i386/lib/console.c
@@ -22,11 +22,21 @@
 	}
 }
 
-static void __console_tx_hex8(int loglevel, unsigned char byte)
+static void __console_tx_hex8(int loglevel, unsigned char value)
 {
 	if (ASM_CONSOLE_LOGLEVEL > loglevel) {
-		__console_tx_nibble(byte >> 4U);
-		__console_tx_nibble(byte & 0x0fU);
+		__console_tx_nibble((value >>  4U) & 0x0fU);
+		__console_tx_nibble(value & 0x0fU);
+	}
+}
+
+static void __console_tx_hex16(int loglevel, unsigned short value)
+{
+	if (ASM_CONSOLE_LOGLEVEL > loglevel) {
+		__console_tx_nibble((value >> 12U) & 0x0fU);
+		__console_tx_nibble((value >>  8U) & 0x0fU);
+		__console_tx_nibble((value >>  4U) & 0x0fU);
+		__console_tx_nibble(value & 0x0fU);
 	}
 }
 
@@ -56,46 +66,55 @@
 
 static void print_emerg_char(unsigned char byte) { __console_tx_char(BIOS_EMERG, byte); }
 static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(BIOS_EMERG, value); }
+static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(BIOS_EMERG, value); }
 static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(BIOS_EMERG, value); }
 static void print_emerg(const char *str) { __console_tx_string(BIOS_EMERG, str); }
 
 static void print_alert_char(unsigned char byte) { __console_tx_char(BIOS_ALERT, byte); }
 static void print_alert_hex8(unsigned char value) { __console_tx_hex8(BIOS_ALERT, value); }
+static void print_alert_hex16(unsigned short value){ __console_tx_hex16(BIOS_ALERT, value); }
 static void print_alert_hex32(unsigned int value) { __console_tx_hex32(BIOS_ALERT, value); }
 static void print_alert(const char *str) { __console_tx_string(BIOS_ALERT, str); }
 
 static void print_crit_char(unsigned char byte) { __console_tx_char(BIOS_CRIT, byte); }
 static void print_crit_hex8(unsigned char value) { __console_tx_hex8(BIOS_CRIT, value); }
+static void print_crit_hex16(unsigned short value){ __console_tx_hex16(BIOS_CRIT, value); }
 static void print_crit_hex32(unsigned int value) { __console_tx_hex32(BIOS_CRIT, value); }
 static void print_crit(const char *str) { __console_tx_string(BIOS_CRIT, str); }
 
 static void print_err_char(unsigned char byte) { __console_tx_char(BIOS_ERR, byte); }
 static void print_err_hex8(unsigned char value) { __console_tx_hex8(BIOS_ERR, value); }
+static void print_err_hex16(unsigned short value){ __console_tx_hex16(BIOS_ERR, value); }
 static void print_err_hex32(unsigned int value) { __console_tx_hex32(BIOS_ERR, value); }
 static void print_err(const char *str) { __console_tx_string(BIOS_ERR, str); }
 
 static void print_warning_char(unsigned char byte) { __console_tx_char(BIOS_WARNING, byte); }
 static void print_warning_hex8(unsigned char value) { __console_tx_hex8(BIOS_WARNING, value); }
+static void print_warning_hex16(unsigned short value){ __console_tx_hex16(BIOS_WARNING, value); }
 static void print_warning_hex32(unsigned int value) { __console_tx_hex32(BIOS_WARNING, value); }
 static void print_warning(const char *str) { __console_tx_string(BIOS_WARNING, str); }
 
 static void print_notice_char(unsigned char byte) { __console_tx_char(BIOS_NOTICE, byte); }
 static void print_notice_hex8(unsigned char value) { __console_tx_hex8(BIOS_NOTICE, value); }
+static void print_notice_hex16(unsigned short value){ __console_tx_hex16(BIOS_NOTICE, value); }
 static void print_notice_hex32(unsigned int value) { __console_tx_hex32(BIOS_NOTICE, value); }
 static void print_notice(const char *str) { __console_tx_string(BIOS_NOTICE, str); }
 
 static void print_info_char(unsigned char byte) { __console_tx_char(BIOS_INFO, byte); }
 static void print_info_hex8(unsigned char value) { __console_tx_hex8(BIOS_INFO, value); }
+static void print_info_hex16(unsigned short value){ __console_tx_hex16(BIOS_INFO, value); }
 static void print_info_hex32(unsigned int value) { __console_tx_hex32(BIOS_INFO, value); }
 static void print_info(const char *str) { __console_tx_string(BIOS_INFO, str); }
 
 static void print_debug_char(unsigned char byte) { __console_tx_char(BIOS_DEBUG, byte); }
 static void print_debug_hex8(unsigned char value) { __console_tx_hex8(BIOS_DEBUG, value); }
+static void print_debug_hex16(unsigned short value){ __console_tx_hex16(BIOS_DEBUG, value); }
 static void print_debug_hex32(unsigned int value) { __console_tx_hex32(BIOS_DEBUG, value); }
 static void print_debug(const char *str) { __console_tx_string(BIOS_DEBUG, str); }
 
 static void print_spew_char(unsigned char byte) { __console_tx_char(BIOS_SPEW, byte); }
 static void print_spew_hex8(unsigned char value) { __console_tx_hex8(BIOS_SPEW, value); }
+static void print_spew_hex16(unsigned short value){ __console_tx_hex16(BIOS_SPEW, value); }
 static void print_spew_hex32(unsigned int value) { __console_tx_hex32(BIOS_SPEW, value); }
 static void print_spew(const char *str) { __console_tx_string(BIOS_SPEW, str); }
 
diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c
index d64acef..4e7b9e3 100644
--- a/src/boot/hardwaremain.c
+++ b/src/boot/hardwaremain.c
@@ -161,7 +161,7 @@
 #endif
 #if 1
 
-	// pick how to scan the bus. This is first so we can get at memory size.
+	/* pick how to scan the bus. This is first so we can get at memory size. */
 	printk_info("Finding PCI configuration type.\n");
 	pci_set_method();
 	post_code(0x5f);
@@ -170,13 +170,15 @@
 #endif
 	dev_enumerate();
 	post_code(0x66);
-	// Now do the real bus
-	// we round the total ram up a lot for thing like the SISFB, which 
-	// shares high memory with the CPU. 
+	/* Now do the real bus.
+	 * We round the total ram up a lot for thing like the SISFB, which 
+	 * shares high memory with the CPU. 
+	 */
 	dev_configure();
 	post_code(0x88);
 
 	dev_enable();
+
 	dev_initialize();
 	post_code(0x89);
 #endif
diff --git a/src/cpu/k8/earlymtrr.inc b/src/cpu/k8/earlymtrr.inc
index 7cd8443..903405b 100644
--- a/src/cpu/k8/earlymtrr.inc
+++ b/src/cpu/k8/earlymtrr.inc
@@ -46,12 +46,12 @@
 	wrmsr
 
 #if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
-	/* enable write protect caching so we can do execute in place
+	/* enable write back cachine so we can do execute in place
 	 * on the flash rom.
 	 */
 	movl	$0x202, %ecx
 	xorl	%edx, %edx
-	movl	$(XIP_ROM_BASE | 0x005), %eax
+	movl	$(XIP_ROM_BASE | 0x006), %eax
 	wrmsr	
 
 	movl	$0x203, %ecx
diff --git a/src/cpu/p5/cpuid.c b/src/cpu/p5/cpuid.c
index d90cc2c..d98ce13 100644
--- a/src/cpu/p5/cpuid.c
+++ b/src/cpu/p5/cpuid.c
@@ -1,7 +1,3 @@
-#ifndef lint
-static char rcsid[] = "$Id$";
-#endif
-
 #include <console/console.h>
 #include <cpu/p5/cpuid.h>
 #ifdef i586
diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c
index b88e174..59de9b5 100644
--- a/src/cpu/p6/mtrr.c
+++ b/src/cpu/p6/mtrr.c
@@ -25,10 +25,6 @@
  * $Id$
  */
 
-#ifndef lint
-static char rcsid[] = "$Id$";
-#endif
-
 #include <console/console.h>
 #include <mem.h>
 #include <cpu/p6/msr.h>
@@ -128,8 +124,6 @@
 /* setting variable mtrr, comes from linux kernel source */
 void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type)
 {
-	unsigned int tmp;
-
 	if (reg >= 8)
 		return;
 
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index dd24bac..2f1c9bd 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -537,7 +537,7 @@
 
 	/* probe all devices on this bus with some optimization for non-existance and 
 	   single funcion devices */
-	for (devfn = 0; devfn < 0xff; devfn++) {
+	for (devfn = 0; devfn <= 0xff; devfn++) {
 		struct device dummy;
 		uint32_t id, class;
 		uint8_t cmd, tmp, hdr_type;
diff --git a/src/include/device/pci.h b/src/include/device/pci.h
index fe0ef7c..c49a2bd 100644
--- a/src/include/device/pci.h
+++ b/src/include/device/pci.h
@@ -17,267 +17,7 @@
 #ifndef PCI_H
 #define PCI_H
 
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_VENDOR_ID		0x00	/* 16 bits */
-#define PCI_DEVICE_ID		0x02	/* 16 bits */
-#define PCI_COMMAND		0x04	/* 16 bits */
-#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
-#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
-#define  PCI_COMMAND_MASTER	0x4	/* Enable bus mastering */
-#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
-#define  PCI_COMMAND_INVALIDATE	0x10	/* Use memory write and invalidate */
-#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
-#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
-#define  PCI_COMMAND_WAIT 	0x80	/* Enable address/data stepping */
-#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
-#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
-
-#define PCI_STATUS		0x06	/* 16 bits */
-#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
-#define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
-#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features [obsolete] */
-#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
-#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
-#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
-#define  PCI_STATUS_DEVSEL_FAST	0x000	
-#define  PCI_STATUS_DEVSEL_MEDIUM 0x200
-#define  PCI_STATUS_DEVSEL_SLOW 0x400
-#define  PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
-#define  PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
-#define  PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
-#define  PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
-#define  PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
-
-#define PCI_CLASS_REVISION	0x08	/* High 24 bits are class, low 8
-					   revision */
-#define PCI_REVISION_ID         0x08    /* Revision ID */
-#define PCI_CLASS_PROG          0x09    /* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE        0x0a    /* Device class */
-
-#define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
-#define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
-#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
-#define  PCI_HEADER_TYPE_NORMAL	0
-#define  PCI_HEADER_TYPE_BRIDGE 1
-#define  PCI_HEADER_TYPE_CARDBUS 2
-
-#define PCI_BIST		0x0f	/* 8 bits */
-#define PCI_BIST_CODE_MASK	0x0f	/* Return result */
-#define PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
-#define PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of 
- * 0xffffffff to the register, and reading it back.  Only 
- * 1 bits are decoded.
- */
-#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
-#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
-#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
-#define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
-#define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
-#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
-#define  PCI_BASE_ADDRESS_SPACE	0x01	/* 0 = memory, 1 = I/O */
-#define  PCI_BASE_ADDRESS_SPACE_IO 0x01
-#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
-#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
-#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
-#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
-#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
-#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-/* Header type 0 (normal devices) */
-#define PCI_CARDBUS_CIS		0x28
-#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
-#define PCI_SUBSYSTEM_ID	0x2e  
-#define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
-#define  PCI_ROM_ADDRESS_ENABLE	0x01
-#define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
-
-#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
-
-/* 0x35-0x3b are reserved */
-#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
-#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
-#define PCI_MIN_GNT		0x3e	/* 8 bits */
-#define PCI_MAX_LAT		0x3f	/* 8 bits */
-
-/* Header type 1 (PCI-to-PCI bridges) */
-#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
-#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
-#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
-#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
-#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
-#define PCI_IO_LIMIT		0x1d
-#define  PCI_IO_RANGE_TYPE_MASK	0x0f	/* I/O bridging type */
-#define  PCI_IO_RANGE_TYPE_16	0x00
-#define  PCI_IO_RANGE_TYPE_32	0x01
-#define  PCI_IO_RANGE_MASK	~0x0f
-#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
-#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
-#define PCI_MEMORY_LIMIT	0x22
-#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
-#define  PCI_MEMORY_RANGE_MASK	~0x0f
-#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
-#define PCI_PREF_MEMORY_LIMIT	0x26
-#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
-#define  PCI_PREF_RANGE_TYPE_32	0x00
-#define  PCI_PREF_RANGE_TYPE_64	0x01
-#define  PCI_PREF_RANGE_MASK	~0x0f
-#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
-#define PCI_PREF_LIMIT_UPPER32	0x2c
-#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
-#define PCI_IO_LIMIT_UPPER16	0x32
-/* 0x34 same as for htype 0 */
-/* 0x35-0x3b is reserved */
-#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_BRIDGE_CONTROL	0x3e
-#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
-#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
-#define  PCI_BRIDGE_CTL_NO_ISA	0x04	/* Disable bridging of ISA ports */
-#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
-#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
-#define  PCI_BRIDGE_CTL_BUS_RESET 0x40	/* Secondary bus reset */
-#define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
-
-/* Header type 2 (CardBus bridges) */
-#define PCI_CB_CAPABILITY_LIST	0x14
-/* 0x15 reserved */
-#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
-#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
-#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
-#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
-#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
-#define PCI_CB_MEMORY_BASE_0	0x1c
-#define PCI_CB_MEMORY_LIMIT_0	0x20
-#define PCI_CB_MEMORY_BASE_1	0x24
-#define PCI_CB_MEMORY_LIMIT_1	0x28
-#define PCI_CB_IO_BASE_0	0x2c
-#define PCI_CB_IO_BASE_0_HI	0x2e
-#define PCI_CB_IO_LIMIT_0	0x30
-#define PCI_CB_IO_LIMIT_0_HI	0x32
-#define PCI_CB_IO_BASE_1	0x34
-#define PCI_CB_IO_BASE_1_HI	0x36
-#define PCI_CB_IO_LIMIT_1	0x38
-#define PCI_CB_IO_LIMIT_1_HI	0x3a
-#define  PCI_CB_IO_RANGE_MASK	~0x03
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_CB_BRIDGE_CONTROL	0x3e
-#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
-#define  PCI_CB_BRIDGE_CTL_SERR		0x02
-#define  PCI_CB_BRIDGE_CTL_ISA		0x04
-#define  PCI_CB_BRIDGE_CTL_VGA		0x08
-#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
-#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
-#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
-#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
-#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
-#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
-#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
-#define PCI_CB_SUBSYSTEM_ID	0x42
-#define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
-/* 0x48-0x7f reserved */
-
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID		0	/* Capability ID */
-#define  PCI_CAP_ID_PM		0x01	/* Power Management */
-#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
-#define  PCI_CAP_ID_VPD		0x03	/* Vital Product Data */
-#define  PCI_CAP_ID_SLOTID	0x04	/* Slot Identification */
-#define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
-#define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
-#define  PCI_CAP_ID_HT          0x08
-#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
-#define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF		4
-
-/* Power Management Registers */
-
-#define  PCI_PM_CAP_VER_MASK	0x0007	/* Version */
-#define  PCI_PM_CAP_PME_CLOCK	0x0008	/* PME clock required */
-#define  PCI_PM_CAP_AUX_POWER	0x0010	/* Auxilliary power support */
-#define  PCI_PM_CAP_DSI		0x0020	/* Device specific initialization */
-#define  PCI_PM_CAP_D1		0x0200	/* D1 power state support */
-#define  PCI_PM_CAP_D2		0x0400	/* D2 power state support */
-#define  PCI_PM_CAP_PME		0x0800	/* PME pin supported */
-#define PCI_PM_CTRL		4	/* PM control and status register */
-#define  PCI_PM_CTRL_STATE_MASK	0x0003	/* Current power state (D0 to D3) */
-#define  PCI_PM_CTRL_PME_ENABLE	0x0100	/* PME pin enable */
-#define  PCI_PM_CTRL_DATA_SEL_MASK	0x1e00	/* Data select (??) */
-#define  PCI_PM_CTRL_DATA_SCALE_MASK	0x6000	/* Data scale (??) */
-#define  PCI_PM_CTRL_PME_STATUS	0x8000	/* PME pin status */
-#define PCI_PM_PPB_EXTENSIONS	6	/* PPB support extensions (??) */
-#define  PCI_PM_PPB_B2_B3	0x40	/* Stop clock when in D3hot (??) */
-#define  PCI_PM_BPCC_ENABLE	0x80	/* Bus power/clock control enable (??) */
-#define PCI_PM_DATA_REGISTER	7	/* (??) */
-#define PCI_PM_SIZEOF		8
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION		2	/* BCD version number */
-#define PCI_AGP_RFU		3	/* Rest of capability flags */
-#define PCI_AGP_STATUS		4	/* Status register */
-#define  PCI_AGP_STATUS_RQ_MASK	0xff000000	/* Maximum number of requests - 1 */
-#define  PCI_AGP_STATUS_SBA	0x0200	/* Sideband addressing supported */
-#define  PCI_AGP_STATUS_64BIT	0x0020	/* 64-bit addressing supported */
-#define  PCI_AGP_STATUS_FW	0x0010	/* FW transfers supported */
-#define  PCI_AGP_STATUS_RATE4	0x0004	/* 4x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE2	0x0002	/* 2x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE1	0x0001	/* 1x transfer rate supported */
-#define PCI_AGP_COMMAND		8	/* Control register */
-#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
-#define  PCI_AGP_COMMAND_SBA	0x0200	/* Sideband addressing enabled */
-#define  PCI_AGP_COMMAND_AGP	0x0100	/* Allow processing of AGP transactions */
-#define  PCI_AGP_COMMAND_64BIT	0x0020 	/* Allow processing of 64-bit addresses */
-#define  PCI_AGP_COMMAND_FW	0x0010 	/* Force FW transfers */
-#define  PCI_AGP_COMMAND_RATE4	0x0004	/* Use 4x rate */
-#define  PCI_AGP_COMMAND_RATE2	0x0002	/* Use 4x rate */
-#define  PCI_AGP_COMMAND_RATE1	0x0001	/* Use 4x rate */
-#define PCI_AGP_SIZEOF		12
-
-/* Slot Identification */
-
-#define PCI_SID_ESR		2	/* Expansion Slot Register */
-#define  PCI_SID_ESR_NSLOTS	0x1f	/* Number of expansion slots available */
-#define  PCI_SID_ESR_FIC	0x20	/* First In Chassis Flag */
-#define PCI_SID_CHASSIS_NR	3	/* Chassis Number */
-
-/* Message Signalled Interrupts registers */
-
-#define PCI_MSI_FLAGS		2	/* Various flags */
-#define  PCI_MSI_FLAGS_64BIT	0x80	/* 64-bit addresses allowed */
-#define  PCI_MSI_FLAGS_QSIZE	0x70	/* Message queue size configured */
-#define  PCI_MSI_FLAGS_QMASK	0x0e	/* Maximum queue size available */
-#define  PCI_MSI_FLAGS_ENABLE	0x01	/* MSI feature enabled */
-#define PCI_MSI_RFU		3	/* Rest of capability flags */
-#define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
-#define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
-#define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
-#define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
-
-/*
- * The PCI interface treats multi-function devices as independent
- * devices.  The slot/function address of each device is encoded
- * in a single byte as follows:
- *
- *	7:3 = slot
- *	2:0 = function
- */
-#define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
-#define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
-#define PCI_FUNC(devfn)		((devfn) & 0x07)
-#define PCI_BDF(bus,dev,func)	((bus) << 16 | (dev) << 11 | (func) << 8)
-
-
+#include <device/pci_def.h>
 #include <device/resource.h>
 #include <device/device.h>
 #include <device/pci_ops.h>
diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
index 91831b5..6b638fe 100644
--- a/src/include/device/pci_ids.h
+++ b/src/include/device/pci_ids.h
@@ -402,6 +402,15 @@
 #define PCI_DEVICE_ID_AMD_VIPER_7448	0x7448
 #define PCI_DEVICE_ID_AMD_VIPER_7449	0x7449
 
+#define PCI_DEVICE_ID_AMD_8151_SYSCTRL  0x7454
+#define PCI_DEVICE_ID_AMD_8151_AGP      0x7455
+#define PCI_DEVICE_ID_AMD_8111_PCI      0x7460
+#define PCI_DEVICE_ID_AMD_8111_USB      0x7464
+#define PCI_DEVICE_ID_AMD_8111_ISA      0x7468
+#define PCI_DEVICE_ID_AMD_8111_IDE      0x7469
+#define PCI_DEVICE_ID_AMD_8111_SMB      0x746a
+#define PCI_DEVICE_ID_AMD_8111_ACPI     0x746b
+
 #define PCI_VENDOR_ID_TRIDENT		0x1023
 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX	0x2000
 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX	0x2001
diff --git a/src/mainboard/amd/solo/auto.c b/src/mainboard/amd/solo/auto.c
index 61cf7cd..c2d5b88 100644
--- a/src/mainboard/amd/solo/auto.c
+++ b/src/mainboard/amd/solo/auto.c
@@ -1,18 +1,861 @@
 #define ASSEMBLY 1
+#include <stdint.h>
+#include <device/pci_def.h>
 #include "arch/romcc_io.h"
 #include "pc80/serial.c"
 #include "arch/i386/lib/console.c"
 #include "ram/ramtest.c"
 
+static void die(const char *str)
+{
+	print_emerg(str);
+	do {
+		hlt();
+	} while(1);
+}
 
 #define MEMORY_512MB  0  /* SuSE Solo configuration */
 #define MEMORY_1024MB 1  /* LNXI Solo configuration */
 
-
-
 static void sdram_set_registers(void)
 {
 	static const unsigned int register_values[] = {
+	/* Careful set limit registers before base registers which contain the enables */
+	/* DRAM Limit i Registers
+	 * F1:0x44 i = 0
+	 * F1:0x4C i = 1
+	 * F1:0x54 i = 2
+	 * F1:0x5C i = 3
+	 * F1:0x64 i = 4
+	 * F1:0x6C i = 5
+	 * F1:0x74 i = 6
+	 * F1:0x7C i = 7
+	 * [ 2: 0] Destination Node ID
+	 *         000 = Node 0
+	 *         001 = Node 1
+	 *         010 = Node 2
+	 *         011 = Node 3
+	 *         100 = Node 4
+	 *         101 = Node 5
+	 *         110 = Node 6
+	 *         111 = Node 7
+	 * [ 7: 3] Reserved
+	 * [10: 8] Interleave select
+	 *         specifies the values of A[14:12] to use with interleave enable.
+	 * [15:11] Reserved
+	 * [31:16] DRAM Limit Address i Bits 39-24
+	 *         This field defines the upper address bits of a 40 bit  address
+	 *         that define the end of the DRAM region.
+	 */
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x003f0000,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x001f0000,
+#endif
+	PCI_ADDR(0, 0x18, 1, 0x4C), 0x0000f8f8, 0x00000001,
+	PCI_ADDR(0, 0x18, 1, 0x54), 0x0000f8f8, 0x00000002,
+	PCI_ADDR(0, 0x18, 1, 0x5C), 0x0000f8f8, 0x00000003,
+	PCI_ADDR(0, 0x18, 1, 0x64), 0x0000f8f8, 0x00000004,
+	PCI_ADDR(0, 0x18, 1, 0x6C), 0x0000f8f8, 0x00000005,
+	PCI_ADDR(0, 0x18, 1, 0x74), 0x0000f8f8, 0x00000006,
+	PCI_ADDR(0, 0x18, 1, 0x7C), 0x0000f8f8, 0x00000007,
+	/* DRAM Base i Registers
+	 * F1:0x40 i = 0
+	 * F1:0x48 i = 1
+	 * F1:0x50 i = 2
+	 * F1:0x58 i = 3
+	 * F1:0x60 i = 4
+	 * F1:0x68 i = 5
+	 * F1:0x70 i = 6
+	 * F1:0x78 i = 7
+	 * [ 0: 0] Read Enable
+	 *         0 = Reads Disabled
+	 *         1 = Reads Enabled
+	 * [ 1: 1] Write Enable
+	 *         0 = Writes Disabled
+	 *         1 = Writes Enabled
+	 * [ 7: 2] Reserved
+	 * [10: 8] Interleave Enable
+	 *         000 = No interleave
+	 *         001 = Interleave on A[12] (2 nodes)
+	 *         010 = reserved
+	 *         011 = Interleave on A[12] and A[14] (4 nodes)
+	 *         100 = reserved
+	 *         101 = reserved
+	 *         110 = reserved
+	 *         111 = Interleve on A[12] and A[13] and A[14] (8 nodes)
+	 * [15:11] Reserved
+	 * [13:16] DRAM Base Address i Bits 39-24
+	 *         This field defines the upper address bits of a 40-bit address
+	 *         that define the start of the DRAM region.
+	 */
+	PCI_ADDR(0, 0x18, 1, 0x40), 0x0000f8fc, 0x00000003,
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00400000,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00200000,
+#endif
+
+	/* Memory-Mapped I/O Limit i Registers
+	 * F1:0x84 i = 0
+	 * F1:0x8C i = 1
+	 * F1:0x94 i = 2
+	 * F1:0x9C i = 3
+	 * F1:0xA4 i = 4
+	 * F1:0xAC i = 5
+	 * F1:0xB4 i = 6
+	 * F1:0xBC i = 7
+	 * [ 2: 0] Destination Node ID
+	 *         000 = Node 0
+	 *         001 = Node 1
+	 *         010 = Node 2
+	 *         011 = Node 3
+	 *         100 = Node 4
+	 *         101 = Node 5
+	 *         110 = Node 6
+	 *         111 = Node 7
+	 * [ 3: 3] Reserved
+	 * [ 5: 4] Destination Link ID
+	 *         00 = Link 0
+	 *         01 = Link 1
+	 *         10 = Link 2
+	 *         11 = Reserved
+	 * [ 6: 6] Reserved
+	 * [ 7: 7] Non-Posted
+	 *         0 = CPU writes may be posted
+	 *         1 = CPU writes must be non-posted
+	 * [31: 8] Memory-Mapped I/O Limit Address i (39-16)
+	 *         This field defines the upp adddress bits of a 40-bit address that
+	 *         defines the end of a memory-mapped I/O region n
+	 */
+	PCI_ADDR(0, 0x18, 1, 0x84), 0x00000048, 0x00e1ff00,
+	PCI_ADDR(0, 0x18, 1, 0x8C), 0x00000048, 0x00dfff00,
+	PCI_ADDR(0, 0x18, 1, 0x94), 0x00000048, 0x00e3ff00,
+	PCI_ADDR(0, 0x18, 1, 0x9C), 0x00000048, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xA4), 0x00000048, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xAC), 0x00000048, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xB4), 0x00000048, 0x00000b00,
+	PCI_ADDR(0, 0x18, 1, 0xBC), 0x00000048, 0x00fe0b00,
+
+	/* Memory-Mapped I/O Base i Registers
+	 * F1:0x80 i = 0
+	 * F1:0x88 i = 1
+	 * F1:0x90 i = 2
+	 * F1:0x98 i = 3
+	 * F1:0xA0 i = 4
+	 * F1:0xA8 i = 5
+	 * F1:0xB0 i = 6
+	 * F1:0xB8 i = 7
+	 * [ 0: 0] Read Enable
+	 *         0 = Reads disabled
+	 *         1 = Reads Enabled
+	 * [ 1: 1] Write Enable
+	 *         0 = Writes disabled
+	 *         1 = Writes Enabled
+	 * [ 2: 2] Cpu Disable
+	 *         0 = Cpu can use this I/O range
+	 *         1 = Cpu requests do not use this I/O range
+	 * [ 3: 3] Lock
+	 *         0 = base/limit registers i are read/write
+	 *         1 = base/limit registers i are read-only
+	 * [ 7: 4] Reserved
+	 * [31: 8] Memory-Mapped I/O Base Address i (39-16)
+	 *         This field defines the upper address bits of a 40bit address 
+	 *         that defines the start of memory-mapped I/O region i
+	 */
+	PCI_ADDR(0, 0x18, 1, 0x80), 0x000000f0, 0x00e00003,
+	PCI_ADDR(0, 0x18, 1, 0x88), 0x000000f0, 0x00d80003,
+	PCI_ADDR(0, 0x18, 1, 0x90), 0x000000f0, 0x00e20003,
+	PCI_ADDR(0, 0x18, 1, 0x98), 0x000000f0, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xA0), 0x000000f0, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xA8), 0x000000f0, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xB0), 0x000000f0, 0x00000a03,
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00400003,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00200003,
+#endif
+
+	/* PCI I/O Limit i Registers
+	 * F1:0xC4 i = 0
+	 * F1:0xCC i = 1
+	 * F1:0xD4 i = 2
+	 * F1:0xDC i = 3
+	 * [ 2: 0] Destination Node ID
+	 *         000 = Node 0
+	 *         001 = Node 1
+	 *         010 = Node 2
+	 *         011 = Node 3
+	 *         100 = Node 4
+	 *         101 = Node 5
+	 *         110 = Node 6
+	 *         111 = Node 7
+	 * [ 3: 3] Reserved
+	 * [ 5: 4] Destination Link ID
+	 *         00 = Link 0
+	 *         01 = Link 1
+	 *         10 = Link 2
+	 *         11 = reserved
+	 * [11: 6] Reserved
+	 * [24:12] PCI I/O Limit Address i
+	 *         This field defines the end of PCI I/O region n
+	 * [31:25] Reserved
+	 */
+	PCI_ADDR(0, 0x18, 1, 0xC4), 0xFE000FC8, 0x0000d000,
+	PCI_ADDR(0, 0x18, 1, 0xCC), 0xFE000FC8, 0x000ff000,
+	PCI_ADDR(0, 0x18, 1, 0xD4), 0xFE000FC8, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xDC), 0xFE000FC8, 0x00000000,
+
+	/* PCI I/O Base i Registers
+	 * F1:0xC0 i = 0
+	 * F1:0xC8 i = 1
+	 * F1:0xD0 i = 2
+	 * F1:0xD8 i = 3
+	 * [ 0: 0] Read Enable
+	 *         0 = Reads Disabled
+	 *         1 = Reads Enabled
+	 * [ 1: 1] Write Enable
+	 *         0 = Writes Disabled
+	 *         1 = Writes Enabled
+	 * [ 3: 2] Reserved
+	 * [ 4: 4] VGA Enable
+	 *         0 = VGA matches Disabled
+	 *         1 = matches all address < 64K and where A[9:0] is in the 
+	 *             range 3B0-3BB or 3C0-3DF independen of the base & limit registers
+	 * [ 5: 5] ISA Enable
+	 *         0 = ISA matches Disabled
+	 *         1 = Blocks address < 64K and in the last 768 bytes of eack 1K block
+	 *             from matching agains this base/limit pair
+	 * [11: 6] Reserved
+	 * [24:12] PCI I/O Base i
+	 *         This field defines the start of PCI I/O region n 
+	 * [31:25] Reserved
+	 */
+	PCI_ADDR(0, 0x18, 1, 0xC0), 0xFE000FCC, 0x0000d003,
+	PCI_ADDR(0, 0x18, 1, 0xC8), 0xFE000FCC, 0x00001013,
+	PCI_ADDR(0, 0x18, 1, 0xD0), 0xFE000FCC, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xD8), 0xFE000FCC, 0x00000000,
+
+	/* Config Base and Limit i Registers
+	 * F1:0xE0 i = 0
+	 * F1:0xE4 i = 1
+	 * F1:0xE8 i = 2
+	 * F1:0xEC i = 3
+	 * [ 0: 0] Read Enable
+	 *         0 = Reads Disabled
+	 *         1 = Reads Enabled
+	 * [ 1: 1] Write Enable
+	 *         0 = Writes Disabled
+	 *         1 = Writes Enabled
+	 * [ 2: 2] Device Number Compare Enable
+	 *         0 = The ranges are based on bus number
+	 *         1 = The ranges are ranges of devices on bus 0
+	 * [ 3: 3] Reserved
+	 * [ 6: 4] Destination Node
+	 *         000 = Node 0
+	 *         001 = Node 1
+	 *         010 = Node 2
+	 *         011 = Node 3
+	 *         100 = Node 4
+	 *         101 = Node 5
+	 *         110 = Node 6
+	 *         111 = Node 7
+	 * [ 7: 7] Reserved
+	 * [ 9: 8] Destination Link
+	 *         00 = Link 0
+	 *         01 = Link 1
+	 *         10 = Link 2
+	 *         11 - Reserved
+	 * [15:10] Reserved
+	 * [23:16] Bus Number Base i
+	 *         This field defines the lowest bus number in configuration region i
+	 * [31:24] Bus Number Limit i
+	 *         This field defines the highest bus number in configuration regin i
+	 */
+	PCI_ADDR(0, 0x18, 1, 0xE0), 0x0000FC88, 0xff000003,
+	PCI_ADDR(0, 0x18, 1, 0xE4), 0x0000FC88, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xE8), 0x0000FC88, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xEC), 0x0000FC88, 0x00000000,
+
+	/* DRAM CS Base Address i Registers
+	 * F2:0x40 i = 0
+	 * F2:0x44 i = 1
+	 * F2:0x48 i = 2
+	 * F2:0x4C i = 3
+	 * F2:0x50 i = 4
+	 * F2:0x54 i = 5
+	 * F2:0x58 i = 6
+	 * F2:0x5C i = 7
+	 * [ 0: 0] Chip-Select Bank Enable
+	 *         0 = Bank Disabled
+	 *         1 = Bank Enabled
+	 * [ 8: 1] Reserved
+	 * [15: 9] Base Address (19-13)
+	 *         An optimization used when all DIMM are the same size...
+	 * [20:16] Reserved
+	 * [31:21] Base Address (35-25)
+	 *         This field defines the top 11 addresses bit of a 40-bit
+	 *         address that define the memory address space.  These
+	 *         bits decode 32-MByte blocks of memory.
+	 */
+	PCI_ADDR(0, 0x18, 2, 0x40), 0x001f01fe, 0x00000001,
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 2, 0x44), 0x001f01fe, 0x01000001,
+	PCI_ADDR(0, 0x18, 2, 0x48), 0x001f01fe, 0x02000001,
+	PCI_ADDR(0, 0x18, 2, 0x4C), 0x001f01fe, 0x03000001,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 2, 0x44), 0x001f01fe, 0x00800001,
+	PCI_ADDR(0, 0x18, 2, 0x48), 0x001f01fe, 0x01000001,
+	PCI_ADDR(0, 0x18, 2, 0x4C), 0x001f01fe, 0x01800001,
+#endif
+	PCI_ADDR(0, 0x18, 2, 0x50), 0x001f01fe, 0x00000000,
+	PCI_ADDR(0, 0x18, 2, 0x54), 0x001f01fe, 0x00000000,
+	PCI_ADDR(0, 0x18, 2, 0x58), 0x001f01fe, 0x00000000,
+	PCI_ADDR(0, 0x18, 2, 0x5C), 0x001f01fe, 0x00000000,
+	/* DRAM CS Mask Address i Registers
+	 * F2:0x60 i = 0
+	 * F2:0x64 i = 1
+	 * F2:0x68 i = 2
+	 * F2:0x6C i = 3
+	 * F2:0x70 i = 4
+	 * F2:0x74 i = 5
+	 * F2:0x78 i = 6
+	 * F2:0x7C i = 7
+	 * Select bits to exclude from comparison with the DRAM Base address register.
+	 * [ 8: 0] Reserved
+	 * [15: 9] Address Mask (19-13)
+	 *         Address to be excluded from the optimized case
+	 * [20:16] Reserved
+	 * [29:21] Address Mask (33-25)
+	 *         The bits with an address mask of 1 are excluded from address comparison
+	 * [31:30] Reserved
+	 * 
+	 */
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 2, 0x60), 0xC01f01ff, 0x00e0fe00,
+	PCI_ADDR(0, 0x18, 2, 0x64), 0xC01f01ff, 0x00e0fe00,
+	PCI_ADDR(0, 0x18, 2, 0x68), 0xC01f01ff, 0x00e0fe00,
+	PCI_ADDR(0, 0x18, 2, 0x6C), 0xC01f01ff, 0x00e0fe00,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 2, 0x60), 0xC01f01ff, 0x0060fe00,
+	PCI_ADDR(0, 0x18, 2, 0x64), 0xC01f01ff, 0x0060fe00,
+	PCI_ADDR(0, 0x18, 2, 0x68), 0xC01f01ff, 0x0060fe00,
+	PCI_ADDR(0, 0x18, 2, 0x6C), 0xC01f01ff, 0x0060fe00,
+#endif
+	PCI_ADDR(0, 0x18, 2, 0x70), 0xC01f01ff, 0x00000000,
+	PCI_ADDR(0, 0x18, 2, 0x74), 0xC01f01ff, 0x00000000,
+	PCI_ADDR(0, 0x18, 2, 0x78), 0xC01f01ff, 0x00000000,
+	PCI_ADDR(0, 0x18, 2, 0x7C), 0xC01f01ff, 0x00000000,
+	/* DRAM Bank Address Mapping Register
+	 * F2:0x80
+	 * Specify the memory module size
+	 * [ 2: 0] CS1/0 
+	 * [ 6: 4] CS3/2
+	 * [10: 8] CS5/4
+	 * [14:12] CS7/6
+	 *         000 = 32Mbyte  (Rows = 12 & Col =  8)
+	 *         001 = 64Mbyte  (Rows = 12 & Col =  9)
+	 *         010 = 128Mbyte (Rows = 13 & Col =  9)|(Rows = 12 & Col = 10)
+	 *         011 = 256Mbyte (Rows = 13 & Col = 10)|(Rows = 12 & Col = 11)
+	 *         100 = 512Mbyte (Rows = 13 & Col = 11)|(Rows = 14 & Col = 10)
+	 *         101 = 1Gbyte   (Rows = 14 & Col = 11)|(Rows = 13 & Col = 12)
+	 *         110 = 2Gbyte   (Rows = 14 & Col = 12)
+	 *         111 = reserved 
+	 * [ 3: 3] Reserved
+	 * [ 7: 7] Reserved
+	 * [11:11] Reserved
+	 * [31:15]
+	 */
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 2, 0x80), 0xffff8888, 0x00000033,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 2, 0x80), 0xffff8888, 0x00000022,
+#endif
+	/* DRAM Timing Low Register
+	 * F2:0x88
+	 * [ 2: 0] Tcl (Cas# Latency, Cas# to read-data-valid)
+	 *         000 = reserved
+	 *         001 = CL 2
+	 *         010 = CL 3
+	 *         011 = reserved
+	 *         100 = reserved
+	 *         101 = CL 2.5
+	 *         110 = reserved
+	 *         111 = reserved
+	 * [ 3: 3] Reserved
+	 * [ 7: 4] Trc (Row Cycle Time, Ras#-active to Ras#-active/bank auto refresh)
+	 *         0000 =  7 bus clocks
+	 *         0001 =  8 bus clocks
+	 *         ...
+	 *         1110 = 21 bus clocks
+	 *         1111 = 22 bus clocks
+	 * [11: 8] Trfc (Row refresh Cycle time, Auto-refresh-active to RAS#-active or RAS#auto-refresh)
+	 *         0000 = 9 bus clocks
+	 *         0010 = 10 bus clocks
+	 *         ....
+	 *         1110 = 23 bus clocks
+	 *         1111 = 24 bus clocks
+	 * [14:12] Trcd (Ras#-active to Case#-read/write Delay)
+	 *         000 = reserved
+	 *         001 = reserved
+	 *         010 = 2 bus clocks
+	 *         011 = 3 bus clocks
+	 *         100 = 4 bus clocks
+	 *         101 = 5 bus clocks
+	 *         110 = 6 bus clocks
+	 *         111 = reserved
+	 * [15:15] Reserved
+	 * [18:16] Trrd (Ras# to Ras# Delay)
+	 *         000 = reserved
+	 *         001 = reserved
+	 *         010 = 2 bus clocks
+	 *         011 = 3 bus clocks
+	 *         100 = 4 bus clocks
+	 *         101 = reserved
+	 *         110 = reserved
+	 *         111 = reserved
+	 * [19:19] Reserved
+	 * [23:20] Tras (Minmum Ras# Active Time)
+	 *         0000 to 0100 = reserved
+	 *         0101 = 5 bus clocks
+	 *         ...
+	 *         1111 = 15 bus clocks
+	 * [26:24] Trp (Row Precharge Time)
+	 *         000 = reserved
+	 *         001 = reserved
+	 *         010 = 2 bus clocks
+	 *         011 = 3 bus clocks
+	 *         100 = 4 bus clocks
+	 *         101 = 5 bus clocks
+	 *         110 = 6 bus clocks
+	 *         111 = reserved
+	 * [27:27] Reserved
+	 * [28:28] Twr (Write Recovery Time)
+	 *         0 = 2 bus clocks
+	 *         1 = 3 bus clocks
+	 * [31:29] Reserved
+	 */
+	PCI_ADDR(0, 0x18, 2, 0x88), 0xe8088008, 0x03623125,
+	/* DRAM Timing High Register
+	 * F2:0x8C
+	 * [ 0: 0] Twtr (Write to Read Delay)
+	 *         0 = 1 bus Clocks
+	 *         1 = 2 bus Clocks
+	 * [ 3: 1] Reserved
+	 * [ 6: 4] Trwf (Read to Write Delay)
+	 *         000 = 1 bus clocks
+	 *         001 = 2 bus clocks
+	 *         010 = 3 bus clocks
+	 *         011 = 4 bus clocks
+	 *         100 = 5 bus clocks
+	 *         101 = 6 bus clocks
+	 *         110 = reserved
+	 *         111 = reserved
+	 * [ 7: 7] Reserved
+	 * [12: 8] Tref (Refresh Rate)
+	 *         00000 = 100Mhz 4K rows
+	 *         00001 = 133Mhz 4K rows
+	 *         00010 = 166Mhz 4K rows
+	 *         01000 = 100Mhz 8K/16K rows
+	 *         01001 = 133Mhz 8K/16K rows
+	 *         01010 = 166Mhz 8K/16K rows
+	 * [19:13] Reserved
+	 * [22:20] Twcl (Write CAS Latency)
+	 *         000 = 1 Mem clock after CAS# (Unbuffered Dimms)
+	 *         001 = 2 Mem clocks after CAS# (Registered Dimms)
+	 * [31:23] Reserved
+	 */
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 2, 0x8c), 0xff8fe08e, 0x00000930,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 2, 0x8c), 0xff8fe08e, 0x00000130,
+#endif
+
+	/* DRAM Config Low Register
+	 * F2:0x90
+	 * [ 0: 0] DLL Disable
+	 *         0 = Enabled
+	 *         1 = Disabled
+	 * [ 1: 1] D_DRV
+	 *         0 = Normal Drive
+	 *         1 = Weak Drive
+	 * [ 2: 2] QFC_EN
+	 *         0 = Disabled
+	 *         1 = Enabled
+	 * [ 3: 3] Disable DQS Hystersis  (FIXME handle this one carefully)
+	 *         0 = Enable DQS input filter 
+	 *         1 = Disable DQS input filtering 
+	 * [ 7: 4] Reserved
+	 * [ 8: 8] DRAM_Init
+	 *         0 = Initialization done or not yet started.
+	 *         1 = Initiate DRAM intialization sequence
+	 * [ 9: 9] SO-Dimm Enable
+	 *         0 = Do nothing
+	 *         1 = SO-Dimms present
+	 * [10:10] DramEnable
+	 *         0 = DRAM not enabled
+	 *         1 = DRAM initialized and enabled
+	 * [11:11] Memory Clear Status
+	 *         0 = Memory Clear function has not completed
+	 *         1 = Memory Clear function has completed
+	 * [12:12] Exit Self-Refresh
+	 *         0 = Exit from self-refresh done or not yet started
+	 *         1 = DRAM exiting from self refresh
+	 * [13:13] Self-Refresh Status
+	 *         0 = Normal Operation
+	 *         1 = Self-refresh mode active
+	 * [15:14] Read/Write Queue Bypass Count
+	 *         00 = 2
+	 *         01 = 4
+	 *         10 = 8
+	 *         11 = 16
+	 * [16:16] 128-bit/64-Bit
+	 *         0 = 64bit Interface to DRAM
+	 *         1 = 128bit Interface to DRAM
+	 * [17:17] DIMM ECC Enable
+	 *         0 = Some DIMMs do not have ECC
+	 *         1 = ALL DIMMS have ECC bits
+	 * [18:18] UnBuffered DIMMs
+	 *         0 = Buffered DIMMS
+	 *         1 = Unbuffered DIMMS
+	 * [19:19] Enable 32-Byte Granularity
+	 *         0 = Optimize for 64byte bursts
+	 *         1 = Optimize for 32byte bursts
+	 * [20:20] DIMM 0 is x4
+	 * [21:21] DIMM 1 is x4
+	 * [22:22] DIMM 2 is x4
+	 * [23:23] DIMM 3 is x4
+	 *         0 = DIMM is not x4
+	 *         1 = x4 DIMM present
+	 * [24:24] Disable DRAM Receivers
+	 *         0 = Receivers enabled
+	 *         1 = Receivers disabled
+	 * [27:25] Bypass Max
+	 *         000 = Arbiters chois is always respected
+	 *         001 = Oldest entry in DCQ can be bypassed 1 time
+	 *         010 = Oldest entry in DCQ can be bypassed 2 times
+	 *         011 = Oldest entry in DCQ can be bypassed 3 times
+	 *         100 = Oldest entry in DCQ can be bypassed 4 times
+	 *         101 = Oldest entry in DCQ can be bypassed 5 times
+	 *         110 = Oldest entry in DCQ can be bypassed 6 times
+	 *         111 = Oldest entry in DCQ can be bypassed 7 times
+	 * [31:28] Reserved
+	 */
+	PCI_ADDR(0, 0x18, 2, 0x90), 0xf0000000, 
+	(4 << 25)|(0 << 24)| 
+	(0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| 
+	(1 << 19)|(1 << 18)|(0 << 17)|(0 << 16)| 
+	(2 << 14)|(0 << 13)|(0 << 12)| 
+	(0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| 
+	(0 << 3) |(0 << 1) |(0 << 0),
+	/* DRAM Config High Register
+	 * F2:0x94
+	 * [ 0: 3] Maximum Asynchronous Latency
+	 *         0000 = 0 ns
+	 *         ...
+	 *         1111 = 15 ns
+	 * [ 7: 4] Reserved
+	 * [11: 8] Read Preamble
+	 *         0000 = 2.0 ns
+	 *         0001 = 2.5 ns
+	 *         0010 = 3.0 ns
+	 *         0011 = 3.5 ns
+	 *         0100 = 4.0 ns
+	 *         0101 = 4.5 ns
+	 *         0110 = 5.0 ns
+	 *         0111 = 5.5 ns
+	 *         1000 = 6.0 ns
+	 *         1001 = 6.5 ns
+	 *         1010 = 7.0 ns
+	 *         1011 = 7.5 ns
+	 *         1100 = 8.0 ns
+	 *         1101 = 8.5 ns
+	 *         1110 = 9.0 ns
+	 *         1111 = 9.5 ns
+	 * [15:12] Reserved
+	 * [18:16] Idle Cycle Limit
+	 *         000 = 0 cycles
+	 *         001 = 4 cycles
+	 *         010 = 8 cycles
+	 *         011 = 16 cycles
+	 *         100 = 32 cycles
+	 *         101 = 64 cycles
+	 *         110 = 128 cycles
+	 *         111 = 256 cycles
+	 * [19:19] Dynamic Idle Cycle Center Enable
+	 *         0 = Use Idle Cycle Limit
+	 *         1 = Generate a dynamic Idle cycle limit
+	 * [22:20] DRAM MEMCLK Frequency
+	 *         000 = 100Mhz
+	 *         001 = reserved
+	 *         010 = 133Mhz
+	 *         011 = reserved
+	 *         100 = reserved
+	 *         101 = 166Mhz
+	 *         110 = reserved
+	 *         111 = reserved
+	 * [24:23] Reserved
+	 * [25:25] Memory Clock Ratio Valid (FIXME carefully enable memclk)
+	 *         0 = Disable MemClks
+	 *         1 = Enable MemClks
+	 * [26:26] Memory Clock 0 Enable
+	 *         0 = Disabled
+	 *         1 = Enabled
+	 * [27:27] Memory Clock 1 Enable
+	 *         0 = Disabled
+	 *         1 = Enabled
+	 * [28:28] Memory Clock 2 Enable
+	 *         0 = Disabled
+	 *         1 = Enabled
+	 * [29:29] Memory Clock 3 Enable
+	 *         0 = Disabled
+	 *         1 = Enabled
+	 * [31:30] Reserved
+	 */
+#if MEMORY_1024MB
+	PCI_ADDR(0, 0x18, 2, 0x94), 0xc180f0f0, 0x0e2b0a05,
+#endif
+#if MEMORY_512MB
+	PCI_ADDR(0, 0x18, 2, 0x94), 0xc180f0f0, 0x0e2b0a06,
+#endif
+	/* DRAM Delay Line Register
+	 * F2:0x98
+	 * Adjust the skew of the input DQS strobe relative to DATA
+	 * [15: 0] Reserved
+	 * [23:16] Delay Line Adjust
+	 *         Adjusts the DLL derived PDL delay by one or more delay stages
+	 *         in either the faster or slower direction.
+	 * [24:24} Adjust Slower
+	 *         0 = Do Nothing
+	 *         1 = Adj is used to increase the PDL delay
+	 * [25:25] Adjust Faster
+	 *         0 = Do Nothing
+	 *         1 = Adj is used to decrease the PDL delay
+	 * [31:26] Reserved
+	 */
+	PCI_ADDR(0, 0x18, 2, 0x98), 0xfc00ffff, 0x00000000,
+	/* DRAM Scrub Control Register
+	 * F3:0x58
+	 * [ 4: 0] DRAM Scrube Rate
+	 * [ 7: 5] reserved
+	 * [12: 8] L2 Scrub Rate
+	 * [15:13] reserved
+	 * [20:16] Dcache Scrub
+	 * [31:21] reserved
+	 *         Scrub Rates
+	 *         00000 = Do not scrub
+	 *         00001 =  40.00 ns
+	 *         00010 =  80.00 ns
+	 *         00011 = 160.00 ns
+	 *         00100 = 320.00 ns
+	 *         00101 = 640.00 ns
+	 *         00110 =   1.28 us
+	 *         00111 =   2.56 us
+	 *         01000 =   5.12 us
+	 *         01001 =  10.20 us
+	 *         01011 =  41.00 us
+	 *         01100 =  81.90 us
+	 *         01101 = 163.80 us
+	 *         01110 = 327.70 us
+	 *         01111 = 655.40 us
+	 *         10000 =   1.31 ms
+	 *         10001 =   2.62 ms
+	 *         10010 =   5.24 ms
+	 *         10011 =  10.49 ms
+	 *         10100 =  20.97 ms
+	 *         10101 =  42.00 ms
+	 *         10110 =  84.00 ms
+	 *         All Others = Reserved
+	 */
+	PCI_ADDR(0, 0x18, 3, 0x58), 0xffe0e0e0, 0x00000000,
+	/* DRAM Scrub Address Low Register
+	 * F3:0x5C
+	 * [ 0: 0] DRAM Scrubber Redirect Enable
+	 *         0 = Do nothing
+	 *         1 = Scrubber Corrects errors found in normal operation
+	 * [ 5: 1] Reserved
+	 * [31: 6] DRAM Scrub Address 31-6
+	 */
+	PCI_ADDR(0, 0x18, 3, 0x5C), 0x0000003e, 0x00000000,
+	/* DRAM Scrub Address High Register
+	 * F3:0x60
+	 * [ 7: 0] DRAM Scrubb Address 39-32
+	 * [31: 8] Reserved
+	 */
+	PCI_ADDR(0, 0x18, 3, 0x60), 0xffffff00, 0x00000000,
+	};
+	int i;
+	int max;
+	print_debug("setting up CPU0 northbridge registers\r\n");
+	max = sizeof(register_values)/sizeof(register_values[0]);
+	for(i = 0; i < max; i += 3) {
+		unsigned long reg;
+#if 0
+		print_debug_hex32(register_values[i]);
+		print_debug(" <-");
+		print_debug_hex32(register_values[i+2]);
+		print_debug("\r\n");
+#endif
+		reg = pci_read_config32(register_values[i]);
+		reg &= register_values[i+1];
+		reg |= register_values[i+2];
+		pci_write_config32(register_values[i], reg);
+	}
+	print_debug("done.\r\n");
+}
+
+#define DRAM_CONFIG_LOW 0x90
+#define  DCL_DLL_Disable   (1<<0)
+#define  DCL_D_DRV         (1<<1)
+#define  DCL_QFC_EN        (1<<2)
+#define  DCL_DisDqsHys     (1<<3)
+#define  DCL_DramInit      (1<<8)
+#define  DCL_DramEnable    (1<<10)
+#define  DCL_MemClrStatus  (1<<11)
+#define  DCL_DimmEcEn      (1<<17)
+
+#define NODE_ID		0x60
+#define	HT_INIT_CONTROL 0x6c
+
+#define HTIC_ColdR_Detect  (1<<4)
+#define HTIC_BIOSR_Detect  (1<<5)
+#define HTIC_INIT_Detect   (1<<6)
+
+static void sdram_set_spd_registers(void) 
+{
+	unsigned long dcl;
+	dcl = pci_read_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW));
+	/* Until I know what is going on disable ECC support */
+	dcl &= ~DCL_DimmEcEn;
+	pci_write_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW), dcl);
+}
+
+#define TIMEOUT_LOOPS 300000
+static void sdram_enable(void)
+{
+	unsigned long dcl;
+
+	/* Toggle DisDqsHys to get it working */
+	dcl = pci_read_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW));
+	print_debug("dcl: ");
+	print_debug_hex32(dcl);
+	print_debug("\r\n");
+	dcl |= DCL_DisDqsHys;
+	pci_write_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW), dcl);
+	dcl &= ~DCL_DisDqsHys;
+	dcl &= ~DCL_DLL_Disable;
+	dcl &= ~DCL_D_DRV;
+	dcl &= ~DCL_QFC_EN;
+	dcl |= DCL_DramInit;
+	pci_write_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW), dcl);
+	
+	print_debug("Initializing memory: ");
+	int loops = 0;
+	do {
+		dcl = pci_read_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW));
+		loops += 1;
+		if ((loops & 1023) == 0) {
+			print_debug(".");
+		}
+	} while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS));
+	if (loops >= TIMEOUT_LOOPS) {
+		print_debug(" failed\r\n");
+	} else {
+		print_debug(" done\r\n");
+	}
+
+#if 0
+	print_debug("Clearing memory: ");
+	loops = 0;
+	do {
+		dcl = pci_read_config32(PCI_ADDR(0, 0x18, 2, DRAM_CONFIG_LOW));
+		loops += 1;
+		if ((loops & 1023) == 0) {
+			print_debug(" ");
+			print_debug_hex32(loops);
+		}
+	} while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS));
+	if (loops >= TIMEOUT_LOOPS) {
+		print_debug("failed\r\n");
+	} else {
+		print_debug("done\r\n");
+	}
+#endif
+}
+
+static void sdram_first_normal_reference(void) {}
+static void sdram_enable_refresh(void) {}
+static void sdram_special_finishup(void) {}
+
+#include "sdram/generic_sdram.c"
+
+static int boot_cpu(void)
+{
+	volatile unsigned long *local_apic;
+	unsigned long apic_id;
+	int bsp;
+	msr_t msr;
+	msr = rdmsr(0x1b);
+	bsp = !!(msr.lo & (1 << 8));
+	if (bsp) {
+		print_debug("Bootstrap cpu\r\n");
+	}
+
+	return bsp;
+}
+
+static int cpu_init_detected(void)
+{
+	unsigned long dcl;
+	int cpu_init;
+
+	unsigned long htic;
+
+	htic = pci_read_config32(PCI_ADDR(0, 0x18, 0, HT_INIT_CONTROL));
+#if 0
+	print_debug("htic: ");
+	print_debug_hex32(htic);
+	print_debug("\r\n");
+
+	if (!(htic & HTIC_ColdR_Detect)) {
+		print_debug("Cold Reset.\r\n");
+	}
+	if ((htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect)) {
+		print_debug("BIOS generated Reset.\r\n");
+	}
+	if (htic & HTIC_INIT_Detect) {
+		print_debug("Init event.\r\n");
+	}
+#endif
+	cpu_init = (htic & HTIC_INIT_Detect);
+	if (cpu_init) {
+		print_debug("CPU INIT Detected.\r\n");
+	}
+	return cpu_init;
+}
+
+static void setup_coherent_ht_domain(void)
+{
+	static const unsigned int register_values[] = {
 	/* Routing Table Node i 
 	 * F0:0x40 i = 0, 
 	 * F0:0x44 i = 1,
@@ -38,14 +881,14 @@
 	 *     [2] Route to Link 1
 	 *     [3] Route to Link 2
 	 */
-	0xc040, 0xfff0f0f0, 0x00010101,
-	0xc044, 0xfff0f0f0, 0x00010101,
-	0xc048, 0xfff0f0f0, 0x00010101,
-	0xc04c, 0xfff0f0f0, 0x00010101,
-	0xc050, 0xfff0f0f0, 0x00010101,
-	0xc054, 0xfff0f0f0, 0x00010101,
-	0xc058, 0xfff0f0f0, 0x00010101,
-	0xc05c, 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x40), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x44), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x48), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x4c), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x50), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x54), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x58), 0xfff0f0f0, 0x00010101,
+	PCI_ADDR(0, 0x18, 0, 0x5c), 0xfff0f0f0, 0x00010101,
 
 	/* Hypetransport Transaction Control Register 
 	 * F0:0x68
@@ -58,7 +901,7 @@
 	 * [ 2: 2] Disable write byte probes
 	 *         0 = Probes issued
 	 *         1 = Probes not issued
-	 * [ 3: 3] Disalbe Write Doubleword Probes
+	 * [ 3: 3] Disable Write Doubleword Probes
 	 *         0 = Probes issued
 	 *         1 = Probes not issued.
 	 * [ 4: 4] Disable Memroy Controller Target Start
@@ -137,9 +980,9 @@
 	 *         0 = Isochronous writes are medium are high
 	 *         1 = With bit 30 set makes Isochrouns writes low priority.
 	 */
-	0xc068, 0x00800000, 0x0f00840f,
+	PCI_ADDR(0, 0x18, 0, 0x68), 0x00800000, 0x0f00840f,
 	/* HT Initialization Control Register
-	 * F0:0x68
+	 * F0:0x6C
 	 * [ 0: 0] Routing Table Disable
 	 *         0 = Packets are routed according to routing tables
 	 *         1 = Packets are routed according to the default link field
@@ -159,7 +1002,7 @@
 	 *         - Scratch bit cleared by a warm or cold reset not by an INIT
 	 *
 	 */
-	0xc06C, 0xffffff8c, 0x00000000,
+	PCI_ADDR(0, 0x18, 0, 0x6C), 0xffffff8c, 0x00000000 | (1 << 6) |(1 << 5)| (1 << 4),
 	/* LDTi Capabilities Registers
 	 * F0:0x80 i = 0,
 	 * F0:0xA0 i = 1,
@@ -236,7 +1079,7 @@
 	 *         0 = Doubleworld flow control disabled
 	 *         1 = Doubleword flow control enabled (Not currently supported)
 	 */
-	0xc084, 0x00009c05, 0x11110020,
+	PCI_ADDR(0, 0x18, 0, 0x84), 0x00009c05, 0x11110020,
 	/* LDTi Frequency/Revision Registers
 	 * F0:0x88 i = 0,
 	 * F0:0xA8 i = 1,
@@ -281,7 +1124,7 @@
 	 *         [30] = 1 encoding 1110 of freq supported
 	 *         [31] = 1 encoding 1111 of freq supported
 	 */
-	0xC088, 0xfffff0ff, 0x00000200,
+	PCI_ADDR(0, 0x18, 0, 0x88), 0xfffff0ff, 0x00000200,
 	/* LDTi Feature Capability
 	 * F0:0x8C i = 0,
 	 * F0:0xAC i = 1,
@@ -302,7 +1145,7 @@
 	 * [23:15] Subordiante Bus Number
 	 * [31:24] reserved
 	 */
-	0xC094, 0xff000000, 0x00ff0000,
+	PCI_ADDR(0, 0x18, 0, 0x94), 0xff000000, 0x00ff0000,
 	/* LDTi Type Registers
 	 * F0:0x98 i = 0,
 	 * F0:0xB8 i = 1,
@@ -336,18 +1179,18 @@
 	 *         that define the end of the DRAM region.
 	 */
 #if MEMORY_1024MB
-	0xC144, 0x0000f8f8, 0x003f0000,
+	PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x003f0000,
 #endif
 #if MEMORY_512MB
-	0xC144, 0x0000f8f8, 0x001f0000,
+	PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x001f0000,
 #endif
-	0xC14C, 0x0000f8f8, 0x00000001,
-	0xC154, 0x0000f8f8, 0x00000002,
-	0xC15C, 0x0000f8f8, 0x00000003,
-	0xC164, 0x0000f8f8, 0x00000004,
-	0xC16C, 0x0000f8f8, 0x00000005,
-	0xC174, 0x0000f8f8, 0x00000006,
-	0xC17C, 0x0000f8f8, 0x00000007,
+	PCI_ADDR(0, 0x18, 1, 0x4C), 0x0000f8f8, 0x00000001,
+	PCI_ADDR(0, 0x18, 1, 0x54), 0x0000f8f8, 0x00000002,
+	PCI_ADDR(0, 0x18, 1, 0x5C), 0x0000f8f8, 0x00000003,
+	PCI_ADDR(0, 0x18, 1, 0x64), 0x0000f8f8, 0x00000004,
+	PCI_ADDR(0, 0x18, 1, 0x6C), 0x0000f8f8, 0x00000005,
+	PCI_ADDR(0, 0x18, 1, 0x74), 0x0000f8f8, 0x00000006,
+	PCI_ADDR(0, 0x18, 1, 0x7C), 0x0000f8f8, 0x00000007,
 	/* DRAM Base i Registers
 	 * F1:0x40 i = 0
 	 * F1:0x48 i = 1
@@ -378,24 +1221,24 @@
 	 *         This field defines the upper address bits of a 40-bit address
 	 *         that define the start of the DRAM region.
 	 */
-	0xC140, 0x0000f8fc, 0x00000003,
+	PCI_ADDR(0, 0x18, 1, 0x40), 0x0000f8fc, 0x00000003,
 #if MEMORY_1024MB
-	0xC148, 0x0000f8fc, 0x00400000,
-	0xC150, 0x0000f8fc, 0x00400000,
-	0xC158, 0x0000f8fc, 0x00400000,
-	0xC160, 0x0000f8fc, 0x00400000,
-	0xC168, 0x0000f8fc, 0x00400000,
-	0xC170, 0x0000f8fc, 0x00400000,
-	0xC178, 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00400000,
+	PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00400000,
 #endif
 #if MEMORY_512MB
-	0xC148, 0x0000f8fc, 0x00200000,
-	0xC150, 0x0000f8fc, 0x00200000,
-	0xC158, 0x0000f8fc, 0x00200000,
-	0xC160, 0x0000f8fc, 0x00200000,
-	0xC168, 0x0000f8fc, 0x00200000,
-	0xC170, 0x0000f8fc, 0x00200000,
-	0xC178, 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00200000,
+	PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00200000,
 #endif
 
 	/* Memory-Mapped I/O Limit i Registers
@@ -430,14 +1273,14 @@
 	 *         This field defines the upp adddress bits of a 40-bit address that
 	 *         defines the end of a memory-mapped I/O region n
 	 */
-	0xC184, 0x00000048, 0x00e1ff00,
-	0xC18C, 0x00000048, 0x00dfff00,
-	0xC194, 0x00000048, 0x00e3ff00,
-	0xC19C, 0x00000048, 0x00000000,
-	0xC1A4, 0x00000048, 0x00000000,
-	0xC1AC, 0x00000048, 0x00000000,
-	0xC1B4, 0x00000048, 0x00000b00,
-	0xC1BC, 0x00000048, 0x00fe0b00,
+	PCI_ADDR(0, 0x18, 1, 0x84), 0x00000048, 0x00e1ff00,
+	PCI_ADDR(0, 0x18, 1, 0x8C), 0x00000048, 0x00dfff00,
+	PCI_ADDR(0, 0x18, 1, 0x94), 0x00000048, 0x00e3ff00,
+	PCI_ADDR(0, 0x18, 1, 0x9C), 0x00000048, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xA4), 0x00000048, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xAC), 0x00000048, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xB4), 0x00000048, 0x00000b00,
+	PCI_ADDR(0, 0x18, 1, 0xBC), 0x00000048, 0x00fe0b00,
 
 	/* Memory-Mapped I/O Base i Registers
 	 * F1:0x80 i = 0
@@ -465,18 +1308,18 @@
 	 *         This field defines the upper address bits of a 40bit address 
 	 *         that defines the start of memory-mapped I/O region i
 	 */
-	0xC180, 0x000000f0, 0x00e00003,
-	0xC188, 0x000000f0, 0x00d80003,
-	0xC190, 0x000000f0, 0x00e20003,
-	0xC198, 0x000000f0, 0x00000000,
-	0xC1A0, 0x000000f0, 0x00000000,
-	0xC1A8, 0x000000f0, 0x00000000,
-	0xC1B0, 0x000000f0, 0x00000a03,
+	PCI_ADDR(0, 0x18, 1, 0x80), 0x000000f0, 0x00e00003,
+	PCI_ADDR(0, 0x18, 1, 0x88), 0x000000f0, 0x00d80003,
+	PCI_ADDR(0, 0x18, 1, 0x90), 0x000000f0, 0x00e20003,
+	PCI_ADDR(0, 0x18, 1, 0x98), 0x000000f0, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xA0), 0x000000f0, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xA8), 0x000000f0, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xB0), 0x000000f0, 0x00000a03,
 #if MEMORY_1024MB
-	0xC1B8, 0x000000f0, 0x00400003,
+	PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00400003,
 #endif
 #if MEMORY_512MB
-	0xC1B8, 0x000000f0, 0x00200003,
+	PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00200003,
 #endif
 
 	/* PCI I/O Limit i Registers
@@ -504,10 +1347,10 @@
 	 *         This field defines the end of PCI I/O region n
 	 * [31:25] Reserved
 	 */
-	0xC1C4, 0xFE000FC8, 0x0000d000,
-	0xC1CC, 0xFE000FC8, 0x000ff000,
-	0xC1D4, 0xFE000FC8, 0x00000000,
-	0xC1DC, 0xFE000FC8, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xC4), 0xFE000FC8, 0x0000d000,
+	PCI_ADDR(0, 0x18, 1, 0xCC), 0xFE000FC8, 0x000ff000,
+	PCI_ADDR(0, 0x18, 1, 0xD4), 0xFE000FC8, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xDC), 0xFE000FC8, 0x00000000,
 
 	/* PCI I/O Base i Registers
 	 * F1:0xC0 i = 0
@@ -534,10 +1377,10 @@
 	 *         This field defines the start of PCI I/O region n 
 	 * [31:25] Reserved
 	 */
-	0xC1C0, 0xFE000FCC, 0x0000d003,
-	0xC1C8, 0xFE000FCC, 0x00001013,
-	0xC1D0, 0xFE000FCC, 0x00000000,
-	0xC1D8, 0xFE000FCC, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xC0), 0xFE000FCC, 0x0000d003,
+	PCI_ADDR(0, 0x18, 1, 0xC8), 0xFE000FCC, 0x00001013,
+	PCI_ADDR(0, 0x18, 1, 0xD0), 0xFE000FCC, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xD8), 0xFE000FCC, 0x00000000,
 
 	/* Config Base and Limit i Registers
 	 * F1:0xE0 i = 0
@@ -575,425 +1418,15 @@
 	 * [31:24] Bus Number Limit i
 	 *         This field defines the highest bus number in configuration regin i
 	 */
-	0xC1E0, 0x0000FC88, 0xff000003,
-	0xC1E4, 0x0000FC88, 0x00000000,
-	0xC1E8, 0x0000FC88, 0x00000000,
-	0xC1EC, 0x0000FC88, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xE0), 0x0000FC88, 0xff000003,
+	PCI_ADDR(0, 0x18, 1, 0xE4), 0x0000FC88, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xE8), 0x0000FC88, 0x00000000,
+	PCI_ADDR(0, 0x18, 1, 0xEC), 0x0000FC88, 0x00000000,
 
-	/* DRAM CS Base Address i Registers
-	 * F2:0x40 i = 0
-	 * F2:0x44 i = 1
-	 * F2:0x48 i = 2
-	 * F2:0x4C i = 3
-	 * F2:0x50 i = 4
-	 * F2:0x54 i = 5
-	 * F2:0x58 i = 6
-	 * F2:0x5C i = 7
-	 * [ 0: 0] Chip-Select Bank Enable
-	 *         0 = Bank Disabled
-	 *         1 = Bank Enabled
-	 * [ 8: 1] Reserved
-	 * [15: 9] Base Address (19-13)
-	 *         An optimization used when all DIMM are the same size...
-	 * [20:16] Reserved
-	 * [31:21] Base Address (35-25)
-	 *         This field defines the top 11 addresses bit of a 40-bit
-	 *         address that define the memory address space.  These
-	 *         bits decode 32-MByte blocks of memory.
-	 */
-	0xC240, 0x001f01fe, 0x00000001,
-#if MEMORY_1024MB
-	0xC244, 0x001f01fe, 0x01000001,
-	0xC248, 0x001f01fe, 0x02000001,
-	0xC24C, 0x001f01fe, 0x03000001,
-#endif
-#if MEMORY_512MB
-	0xC244, 0x001f01fe, 0x00800001,
-	0xC248, 0x001f01fe, 0x01000001,
-	0xC24C, 0x001f01fe, 0x01800001,
-#endif
-	0xC250, 0x001f01fe, 0x00000000,
-	0xC254, 0x001f01fe, 0x00000000,
-	0xC258, 0x001f01fe, 0x00000000,
-	0xC25C, 0x001f01fe, 0x00000000,
-	/* DRAM CS Mask Address i Registers
-	 * F2:0x60 i = 0
-	 * F2:0x64 i = 1
-	 * F2:0x68 i = 2
-	 * F2:0x6C i = 3
-	 * F2:0x70 i = 4
-	 * F2:0x74 i = 5
-	 * F2:0x78 i = 6
-	 * F2:0x7C i = 7
-	 * Select bits to exclude from comparison with the DRAM Base address register.
-	 * [ 8: 0] Reserved
-	 * [15: 9] Address Mask (19-13)
-	 *         Address to be excluded from the optimized case
-	 * [20:16] Reserved
-	 * [29:21] Address Mask (33-25)
-	 *         The bits with an address mask of 1 are excluded from address comparison
-	 * [31:30] Reserved
-	 * 
-	 */
-#if MEMORY_1024MB
-	0xC260, 0xC01f01ff, 0x00e0fe00,
-	0xC264, 0xC01f01ff, 0x00e0fe00,
-	0xC268, 0xC01f01ff, 0x00e0fe00,
-	0xC26C, 0xC01f01ff, 0x00e0fe00,
-#endif
-#if MEMORY_512MB
-	0xC260, 0xC01f01ff, 0x0060fe00,
-	0xC264, 0xC01f01ff, 0x0060fe00,
-	0xC268, 0xC01f01ff, 0x0060fe00,
-	0xC26C, 0xC01f01ff, 0x0060fe00,
-#endif
-	0xC270, 0xC01f01ff, 0x00000000,
-	0xC274, 0xC01f01ff, 0x00000000,
-	0xC278, 0xC01f01ff, 0x00000000,
-	0xC27C, 0xC01f01ff, 0x00000000,
-	/* DRAM Bank Address Mapping Register
-	 * F2:0x80
-	 * Specify the memory module size
-	 * [ 2: 0] CS1/0 
-	 * [ 6: 4] CS3/2
-	 * [10: 8] CS5/4
-	 * [14:12] CS7/6
-	 *         000 = 32Mbyte  (Rows = 12 & Col =  8)
-	 *         001 = 64Mbyte  (Rows = 12 & Col =  9)
-	 *         010 = 128Mbyte (Rows = 13 & Col =  9)|(Rows = 12 & Col = 10)
-	 *         011 = 256Mbyte (Rows = 13 & Col = 10)|(Rows = 12 & Col = 11)
-	 *         100 = 512Mbyte (Rows = 13 & Col = 11)|(Rows = 14 & Col = 10)
-	 *         101 = 1Gbyte   (Rows = 14 & Col = 11)|(Rows = 13 & Col = 12)
-	 *         110 = 2Gbyte   (Rows = 14 & Col = 12)
-	 *         111 = reserved 
-	 * [ 3: 3] Reserved
-	 * [ 7: 7] Reserved
-	 * [11:11] Reserved
-	 * [31:15]
-	 */
-#if MEMORY_1024MB
-	0xC280, 0xffff8888, 0x00000033,
-#endif
-#if MEMORY_512MB
-	0xC280, 0xffff8888, 0x00000022,
-#endif
-	/* DRAM Timing Low Register
-	 * F2:0x88
-	 * [ 2: 0] Tcl (Cas# Latency, Cas# to read-data-valid)
-	 *         000 = reserved
-	 *         001 = CL 2
-	 *         010 = CL 3
-	 *         011 = reserved
-	 *         100 = reserved
-	 *         101 = CL 2.5
-	 *         110 = reserved
-	 *         111 = reserved
-	 * [ 3: 3] Reserved
-	 * [ 7: 4] Trc (Row Cycle Time, Ras#-active to Ras#-active/bank auto refresh)
-	 *         0000 =  7 bus clocks
-	 *         0001 =  8 bus clocks
-	 *         ...
-	 *         1110 = 21 bus clocks
-	 *         1111 = 22 bus clocks
-	 * [11: 8] Trfc (Row refresh Cycle time, Auto-refresh-active to RAS#-active or RAS#auto-refresh)
-	 *         0000 = 9 bus clocks
-	 *         0010 = 10 bus clocks
-	 *         ....
-	 *         1110 = 23 bus clocks
-	 *         1111 = 24 bus clocks
-	 * [14:12] Trcd (Ras#-active to Case#-read/write Delay)
-	 *         000 = reserved
-	 *         001 = reserved
-	 *         010 = 2 bus clocks
-	 *         011 = 3 bus clocks
-	 *         100 = 4 bus clocks
-	 *         101 = 5 bus clocks
-	 *         110 = 6 bus clocks
-	 *         111 = reserved
-	 * [15:15] Reserved
-	 * [18:16] Trrd (Ras# to Ras# Delay)
-	 *         000 = reserved
-	 *         001 = reserved
-	 *         010 = 2 bus clocks
-	 *         011 = 3 bus clocks
-	 *         100 = 4 bus clocks
-	 *         101 = reserved
-	 *         110 = reserved
-	 *         111 = reserved
-	 * [19:19] Reserved
-	 * [23:20] Tras (Minmum Ras# Active Time)
-	 *         0000 to 0100 = reserved
-	 *         0101 = 5 bus clocks
-	 *         ...
-	 *         1111 = 15 bus clocks
-	 * [26:24] Trp (Row Precharge Time)
-	 *         000 = reserved
-	 *         001 = reserved
-	 *         010 = 2 bus clocks
-	 *         011 = 3 bus clocks
-	 *         100 = 4 bus clocks
-	 *         101 = 5 bus clocks
-	 *         110 = 6 bus clocks
-	 *         111 = reserved
-	 * [27:27] Reserved
-	 * [28:28] Twr (Write Recovery Time)
-	 *         0 = 2 bus clocks
-	 *         1 = 3 bus clocks
-	 * [31:29] Reserved
-	 */
-	0xC288, 0xe8088008, 0x03623125,
-	/* DRAM Timing High Register
-	 * F2:0x8C
-	 * [ 0: 0] Twtr (Write to Read Delay)
-	 *         0 = 1 bus Clocks
-	 *         1 = 2 bus Clocks
-	 * [ 3: 1] Reserved
-	 * [ 6: 4] Trwf (Read to Write Delay)
-	 *         000 = 1 bus clocks
-	 *         001 = 2 bus clocks
-	 *         010 = 3 bus clocks
-	 *         011 = 4 bus clocks
-	 *         100 = 5 bus clocks
-	 *         101 = 6 bus clocks
-	 *         110 = reserved
-	 *         111 = reserved
-	 * [ 7: 7] Reserved
-	 * [12: 8] Tref (Refresh Rate)
-	 *         00000 = 100Mhz 4K rows
-	 *         00001 = 133Mhz 4K rows
-	 *         00010 = 166Mhz 4K rows
-	 *         01000 = 100Mhz 8K/16K rows
-	 *         01001 = 133Mhz 8K/16K rows
-	 *         01010 = 166Mhz 8K/16K rows
-	 * [19:13] Reserved
-	 * [22:20] Twcl (Write CAS Latency)
-	 *         000 = 1 Mem clock after CAS# (Unbuffered Dimms)
-	 *         001 = 2 Mem clocks after CAS# (Registered Dimms)
-	 * [31:23] Reserved
-	 */
-#if MEMORY_1024MB
-	0xC28c, 0xff8fe08e, 0x00000930,
-#endif
-#if MEMORY_512MB
-	0xC28c, 0xff8fe08e, 0x00000130,
-#endif
-
-	/* DRAM Config Low Register
-	 * F2:0x90
-	 * [ 0: 0] DLL Disable
-	 *         0 = Enabled
-	 *         1 = Disabled
-	 * [ 1: 1] D_DRV
-	 *         0 = Normal Drive
-	 *         1 = Weak Drive
-	 * [ 2: 2] QFC_EN
-	 *         0 = Disabled
-	 *         1 = Enabled
-	 * [ 3: 3] Disable DQS Hystersis  (FIXME handle this one carefully)
-	 *         0 = Enable DQS input filter 
-	 *         1 = Disable DQS input filtering 
-	 * [ 7: 4] Reserved
-	 * [ 8: 8] DRAM_Init
-	 *         0 = Initialization done or not yet started.
-	 *         1 = Initiate DRAM intialization sequence
-	 * [ 9: 9] SO-Dimm Enable
-	 *         0 = Do nothing
-	 *         1 = SO-Dimms present
-	 * [10:10] DramEnable
-	 *         0 = DRAM not enabled
-	 *         1 = DRAM initialized and enabled
-	 * [11:11] Memory Clear Status
-	 *         0 = Memory Clear function has not completed
-	 *         1 = Memory Clear function has completed
-	 * [12:12] Exit Self-Refresh
-	 *         0 = Exit from self-refresh done or not yet started
-	 *         1 = DRAM exiting from self refresh
-	 * [13:13] Self-Refresh Status
-	 *         0 = Normal Operation
-	 *         1 = Self-refresh mode active
-	 * [15:14] Read/Write Queue Bypass Count
-	 *         00 = 2
-	 *         01 = 4
-	 *         10 = 8
-	 *         11 = 16
-	 * [16:16] 128-bit/64-Bit
-	 *         0 = 64bit Interface to DRAM
-	 *         1 = 128bit Interface to DRAM
-	 * [17:17] DIMM ECC Enable
-	 *         0 = Some DIMMs do not have ECC
-	 *         1 = ALL DIMMS have ECC bits
-	 * [18:18] UnBuffered DIMMs
-	 *         0 = Buffered DIMMS
-	 *         1 = Unbuffered DIMMS
-	 * [19:19] Enable 32-Byte Granularity
-	 *         0 = Optimize for 64byte bursts
-	 *         1 = Optimize for 32byte bursts
-	 * [20:20] DIMM 0 is x4
-	 * [21:21] DIMM 1 is x4
-	 * [22:22] DIMM 2 is x4
-	 * [23:23] DIMM 3 is x4
-	 *         0 = DIMM is not x4
-	 *         1 = x4 DIMM present
-	 * [24:24] Disable DRAM Receivers
-	 *         0 = Receivers enabled
-	 *         1 = Receivers disabled
-	 * [27:25] Bypass Max
-	 *         000 = Arbiters chois is always respected
-	 *         001 = Oldest entry in DCQ can be bypassed 1 time
-	 *         010 = Oldest entry in DCQ can be bypassed 2 times
-	 *         011 = Oldest entry in DCQ can be bypassed 3 times
-	 *         100 = Oldest entry in DCQ can be bypassed 4 times
-	 *         101 = Oldest entry in DCQ can be bypassed 5 times
-	 *         110 = Oldest entry in DCQ can be bypassed 6 times
-	 *         111 = Oldest entry in DCQ can be bypassed 7 times
-	 * [31:28] Reserved
-	 */
-	0xC290, 0xf0000000, 
-	(4 << 25)|(0 << 24)| 
-	(0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| 
-	(1 << 19)|(1 << 18)|(0 << 17)|(0 << 16)| 
-	(2 << 14)|(0 << 13)|(0 << 12)| 
-	(0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| 
-	(0 << 3) |(0 << 1) |(0 << 0),
-	/* DRAM Config High Register
-	 * F2:0x94
-	 * [ 0: 3] Maximum Asynchronous Latency
-	 *         0000 = 0 ns
-	 *         ...
-	 *         1111 = 15 ns
-	 * [ 7: 4] Reserved
-	 * [11: 8] Read Preamble
-	 *         0000 = 2.0 ns
-	 *         0001 = 2.5 ns
-	 *         0010 = 3.0 ns
-	 *         0011 = 3.5 ns
-	 *         0100 = 4.0 ns
-	 *         0101 = 4.5 ns
-	 *         0110 = 5.0 ns
-	 *         0111 = 5.5 ns
-	 *         1000 = 6.0 ns
-	 *         1001 = 6.5 ns
-	 *         1010 = 7.0 ns
-	 *         1011 = 7.5 ns
-	 *         1100 = 8.0 ns
-	 *         1101 = 8.5 ns
-	 *         1110 = 9.0 ns
-	 *         1111 = 9.5 ns
-	 * [15:12] Reserved
-	 * [18:16] Idle Cycle Limit
-	 *         000 = 0 cycles
-	 *         001 = 4 cycles
-	 *         010 = 8 cycles
-	 *         011 = 16 cycles
-	 *         100 = 32 cycles
-	 *         101 = 64 cycles
-	 *         110 = 128 cycles
-	 *         111 = 256 cycles
-	 * [19:19] Dynamic Idle Cycle Center Enable
-	 *         0 = Use Idle Cycle Limit
-	 *         1 = Generate a dynamic Idle cycle limit
-	 * [22:20] DRAM MEMCLK Frequency
-	 *         000 = 100Mhz
-	 *         001 = reserved
-	 *         010 = 133Mhz
-	 *         011 = reserved
-	 *         100 = reserved
-	 *         101 = 166Mhz
-	 *         110 = reserved
-	 *         111 = reserved
-	 * [24:23] Reserved
-	 * [25:25] Memory Clock Ratio Valid (FIXME carefully enable memclk)
-	 *         0 = Disable MemClks
-	 *         1 = Enable MemClks
-	 * [26:26] Memory Clock 0 Enable
-	 *         0 = Disabled
-	 *         1 = Enabled
-	 * [27:27] Memory Clock 1 Enable
-	 *         0 = Disabled
-	 *         1 = Enabled
-	 * [28:28] Memory Clock 2 Enable
-	 *         0 = Disabled
-	 *         1 = Enabled
-	 * [29:29] Memory Clock 3 Enable
-	 *         0 = Disabled
-	 *         1 = Enabled
-	 * [31:30] Reserved
-	 */
-#if MEMORY_1024MB
-	0xC294, 0xc180f0f0, 0x0e2b0a05,
-#endif
-#if MEMORY_512MB
-	0xC294, 0xc180f0f0, 0x0e2b0a06,
-#endif
-	/* DRAM Delay Line Register
-	 * F2:0x98
-	 * Adjust the skew of the input DQS strobe relative to DATA
-	 * [15: 0] Reserved
-	 * [23:16] Delay Line Adjust
-	 *         Adjusts the DLL derived PDL delay by one or more delay stages
-	 *         in either the faster or slower direction.
-	 * [24:24} Adjust Slower
-	 *         0 = Do Nothing
-	 *         1 = Adj is used to increase the PDL delay
-	 * [25:25] Adjust Faster
-	 *         0 = Do Nothing
-	 *         1 = Adj is used to decrease the PDL delay
-	 * [31:26] Reserved
-	 */
-	0xC298, 0xfc00ffff, 0x00000000,
-	/* DRAM Scrub Control Register
-	 * F3:0x58
-	 * [ 4: 0] DRAM Scrube Rate
-	 * [ 7: 5] reserved
-	 * [12: 8] L2 Scrub Rate
-	 * [15:13] reserved
-	 * [20:16] Dcache Scrub
-	 * [31:21] reserved
-	 *         Scrub Rates
-	 *         00000 = Do not scrub
-	 *         00001 =  40.00 ns
-	 *         00010 =  80.00 ns
-	 *         00011 = 160.00 ns
-	 *         00100 = 320.00 ns
-	 *         00101 = 640.00 ns
-	 *         00110 =   1.28 us
-	 *         00111 =   2.56 us
-	 *         01000 =   5.12 us
-	 *         01001 =  10.20 us
-	 *         01011 =  41.00 us
-	 *         01100 =  81.90 us
-	 *         01101 = 163.80 us
-	 *         01110 = 327.70 us
-	 *         01111 = 655.40 us
-	 *         10000 =   1.31 ms
-	 *         10001 =   2.62 ms
-	 *         10010 =   5.24 ms
-	 *         10011 =  10.49 ms
-	 *         10100 =  20.97 ms
-	 *         10101 =  42.00 ms
-	 *         10110 =  84.00 ms
-	 *         All Others = Reserved
-	 */
-	0xC358, 0xffe0e0e0, 0x00000000,
-	/* DRAM Scrub Address Low Register
-	 * F3:0x5C
-	 * [ 0: 0] DRAM Scrubber Redirect Enable
-	 *         0 = Do nothing
-	 *         1 = Scrubber Corrects errors found in normal operation
-	 * [ 5: 1] Reserved
-	 * [31: 6] DRAM Scrub Address 31-6
-	 */
-	0xC35C, 0x0000003e, 0x00000000,
-	/* DRAM Scrub Address High Register
-	 * F3:0x60
-	 * [ 7: 0] DRAM Scrubb Address 39-32
-	 * [31: 8] Reserved
-	 */
-	0xC360, 0xffffff00, 0x00000000,
 	};
 	int i;
 	int max;
-	print_debug("setting up northbridge registers\r\n");
+	print_debug("setting up coherent ht domain....\r\n");
 	max = sizeof(register_values)/sizeof(register_values[0]);
 	for(i = 0; i < max; i += 3) {
 		unsigned long reg;
@@ -1003,123 +1436,302 @@
 		print_debug_hex32(register_values[i+2]);
 		print_debug("\r\n");
 #endif
-		reg = pcibios_read_config_dword(
-			0, register_values[i] >> 8, register_values[i] & 0xff);
+		reg = pci_read_config32(register_values[i]);
 		reg &= register_values[i+1];
 		reg |= register_values[i+2] & ~register_values[i+1];
-		pcibios_write_config_dword(
-			0, register_values[i] >> 8, register_values[i] & 0xff, reg);
+		pci_write_config32(register_values[i], reg);
 	}
-	print_debug("setting up northbridge registers done. hurray!\r\n");
+	print_debug("done.\r\n");
 }
 
-#define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
-
-#define DRAM_CONFIG_LOW 0x90
-#define  DCL_DLL_Disable   (1<<0)
-#define  DCL_D_DRV         (1<<1)
-#define  DCL_QFC_EN        (1<<2)
-#define  DCL_DisDqsHys     (1<<3)
-#define  DCL_DramInit      (1<<8)
-#define  DCL_DramEnable    (1<<10)
-#define  DCL_MemClrStatus  (1<<11)
-#define  DCL_DimmEcEn      (1<<17)
-
-static void sdram_set_spd_registers(void) 
+static void enumerate_ht_chain(void)
 {
-	unsigned long dcl;
-	dcl = pcibios_read_config_dword(0, PCI_DEVFN(0x18,2), DRAM_CONFIG_LOW);
-	/* Until I know what is going on disable ECC support */
-	dcl &= ~DCL_DimmEcEn;
-	pcibios_write_config_dword(0, PCI_DEVFN(0x18,2), DRAM_CONFIG_LOW, dcl);
+	unsigned next_unitid, last_unitid;;
+	next_unitid = 1;
+	do {
+		uint32_t id;
+		uint8_t hdr_type, pos;
+		last_unitid = next_unitid;
+
+		id = pci_read_config32(PCI_ADDR(0,0,0,PCI_VENDOR_ID));
+		/* If the chain is enumerated quit */
+		if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0x0000)) {
+			break;
+		}
+		hdr_type = pci_read_config8(PCI_ADDR(0,0,0,PCI_HEADER_TYPE));
+		pos = 0;
+		hdr_type &= 0x7f;
+
+		if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
+			(hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
+			pos = pci_read_config8(PCI_ADDR(0,0,0, PCI_CAPABILITY_LIST));
+		}
+		while(pos != 0) {
+			uint8_t cap;
+			cap = pci_read_config8(PCI_ADDR(0,0,0, pos + PCI_CAP_LIST_ID));
+			if (cap == PCI_CAP_ID_HT) {
+				uint16_t flags;
+				flags = pci_read_config16(PCI_ADDR(0,0,0, pos + PCI_CAP_FLAGS));
+				if ((flags >> 13) == 0) {
+					unsigned count;
+					flags &= ~0x1f;
+					flags |= next_unitid & 0x1f;
+					count = (flags >> 5) & 0x1f;
+					pci_write_config16(PCI_ADDR(0, 0, 0, pos + PCI_CAP_FLAGS), flags);
+					next_unitid += count;
+					break;
+				}
+			}
+			pos = pci_read_config8(PCI_ADDR(0, 0, 0, pos + PCI_CAP_LIST_NEXT));
+		}
+	} while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
 }
 
-#define TIMEOUT_LOOPS 300000
-static void sdram_enable(void)
+static void print_pci_devices(void)
 {
-	unsigned long dcl;
+	uint32_t addr;
+	for(addr = PCI_ADDR(0, 0, 0, 0); 
+		addr <= PCI_ADDR(0, 0x1f, 0x7, 0); 
+		addr += PCI_ADDR(0,0,1,0)) {
+		uint32_t id;
+		id = pci_read_config32(addr + PCI_VENDOR_ID);
+		if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0x0000)) {
+			continue;
+		}
+		print_debug("PCI: 00:");
+		print_debug_hex8(addr >> 11);
+		print_debug_char('.');
+		print_debug_hex8((addr >> 8) & 7);
+		print_debug("\r\n");
+	}
+}
 
-	/* Toggle DisDqsHys to get it working */
-	dcl = pcibios_read_config_dword(0, PCI_DEVFN(0x18,2), DRAM_CONFIG_LOW);
-	print_debug("dcl: ");
-	print_debug_hex32(dcl);
-	print_debug("\r\n");
-	dcl |= DCL_DisDqsHys;
-	pcibios_write_config_dword(0, PCI_DEVFN(0x18, 2), DRAM_CONFIG_LOW, dcl);
-	dcl &= ~DCL_DisDqsHys;
-	dcl &= ~DCL_DLL_Disable;
-	dcl &= ~DCL_D_DRV;
-	dcl &= ~DCL_QFC_EN;
-	dcl |= DCL_DramInit;
-	pcibios_write_config_dword(0, PCI_DEVFN(0x18, 2), DRAM_CONFIG_LOW, dcl);
+#define PCI_ID(VENDOR_ID, DEVICE_ID) ((DEVICE_ID << 16) | (VENDOR_ID))
+#define SMBUS_IO_BASE 0x1000
+
+#define SMBGSTATUS 0xe0
+#define SMBGCTL    0xe2
+#define SMBHSTADDR 0xe4
+#define SMBHSTDAT  0xe6
+#define SMBHSTCMD  0xe8
+#define SMBHSTFIFO 0xe9
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+static void enable_smbus(void)
+{
+	uint32_t addr;
+	for(addr = PCI_ADDR(0, 0, 0, 0);
+		addr <= PCI_ADDR(0, 0x1f, 0x7, 0);
+		addr += PCI_ADDR(0,0,1,0)) {
+		uint32_t id;
+		id = pci_read_config32(addr);
+		if (id == PCI_ID(0x1022, 0x746b)) {
+			break;
+		}
+	}
+	if (addr > PCI_ADDR(0, 0x1f, 0x7, 0)) {
+		die("SMBUS controller not found\r\n");
+	}
+	uint8_t enable;
+	print_debug("SMBus controller enabled\r\n");
+	pci_write_config32(addr + 0x58, SMBUS_IO_BASE | 1);
+	enable = pci_read_config8(addr + 0x41);
+	pci_write_config8(addr + 0x41, enable | (1 << 7));
+}
+
+
+static inline void smbus_delay(void)
+{
+	outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(void)
+{
+	unsigned long loops;
+	loops = SMBUS_TIMEOUT;
+	do {
+		unsigned short val;
+		smbus_delay();
+		val = inw(SMBUS_IO_BASE + SMBGSTATUS);
+		if ((val & 0x800) == 0) {
+			break;
+		}
+	} while(--loops);
+	return loops?0:-1;
+}
+
+static int smbus_wait_until_done(void)
+{
+	unsigned long loops;
+	loops = SMBUS_TIMEOUT;
+	do {
+		unsigned short val;
+		smbus_delay();
+		
+		val = inw(SMBUS_IO_BASE + SMBGSTATUS);
+		if (((val & 0x8) == 0) || ((val & 0x437) != 0)) {
+			break;
+		}
+	} while(--loops);
+	return loops?0:-1;
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+	unsigned char global_control_register;
+	unsigned char global_status_register;
+	unsigned char byte;
+
+	if (smbus_wait_until_ready() < 0) {
+		return -1;
+	}
 	
-	print_debug("Initializing memory: ");
-	int loops = 0;
-	do {
-		dcl = pcibios_read_config_dword(0, PCI_DEVFN(0x18, 2), DRAM_CONFIG_LOW);
-		loops += 1;
-		if ((loops & 1023) == 0) {
-			print_debug(" ");
-			print_debug_hex32(loops);
-		}
-	} while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS));
-	if (loops >= TIMEOUT_LOOPS) {
-		print_debug(" failed\r\n");
-	} else {
-		print_debug(" done\r\n");
+	/* setup transaction */
+	/* disable interrupts */
+	outw(inw(SMBUS_IO_BASE + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), SMBUS_IO_BASE + SMBGCTL);
+	/* set the device I'm talking too */
+	outw(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADDR);
+	/* set the command/address... */
+	outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+	/* set up for a byte data read */
+	outw((inw(SMBUS_IO_BASE + SMBGCTL) & ~7) | (0x2), SMBUS_IO_BASE + SMBGCTL);
+
+	/* clear any lingering errors, so the transaction will run */
+	/* Do I need to write the bits to a 1 to clear an error? */
+	outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS);
+
+	/* clear the data word...*/
+	outw(0, SMBUS_IO_BASE + SMBHSTDAT);
+
+	/* start the command */
+	outw((inw(SMBUS_IO_BASE + SMBGCTL) | (1 << 3)), SMBUS_IO_BASE + SMBGCTL);
+
+
+	/* poll for transaction completion */
+	if (smbus_wait_until_done() < 0) {
+		return -1;
 	}
 
-#if 0
-	print_debug("Clearing memory: ");
-	loops = 0;
-	do {
-		dcl = pcibios_read_config_dword(0, PCI_DEVFN(0x18, 2), DRAM_CONFIG_LOW);
-		loops += 1;
-		if ((loops & 1023) == 0) {
-			print_debug(" ");
-			print_debug_hex32(loops);
-		}
-	} while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS));
-	if (loops >= TIMEOUT_LOOPS) {
-		print_debug("failed\r\n");
-	} else {
-		print_debug("done\r\n");
+	global_status_register = inw(SMBUS_IO_BASE + SMBGSTATUS);
+
+	/* read results of transaction */
+	byte = inw(SMBUS_IO_BASE + SMBHSTDAT) & 0xff;
+
+	if (global_status_register != (1 << 4)) {
+		return -1;
 	}
-#endif
+	return byte;
 }
 
-static void sdram_first_normal_reference(void) {}
-static void sdram_enable_refresh(void) {}
-static void sdram_special_finishup(void) {}
-
-static int sdram_enabled(void)
+static void dump_spd_registers(void)
 {
-	unsigned long dcl;
-	int enabled;
-	dcl = pcibios_read_config_dword(0, PCI_DEVFN(0x18, 2), DRAM_CONFIG_LOW);
-	enabled = !!(dcl & DCL_DramEnable);
-	if (enabled) {
-		print_debug("DRAM already enabled.");
+	unsigned device;
+	device = SMBUS_MEM_DEVICE_START;
+	print_debug("\r\n");
+	while(device <= SMBUS_MEM_DEVICE_END) {
+		int i;
+		print_debug("dimm: "); 
+		print_debug_hex8(device); 
+		for(i = 0; i < 256; i++) {
+			int status;
+			unsigned char byte;
+			if ((i & 0xf) == 0) {
+				print_debug("\r\n");
+				print_debug_hex8(i);
+				print_debug(": ");
+			}
+			status = smbus_read_byte(device, i);
+			if (status < 0) {
+				print_debug("bad device\r\n");
+				continue;
+			}
+			byte = status & 0xff;
+			print_debug_hex8(byte);
+			print_debug_char(' ');
+		}
+		device += SMBUS_MEM_DEVICE_INC;
+		print_debug("\r\n");
 	}
-	return enabled;
+}
+
+static void dump_spd_registers1(void)
+{
+	int i;
+	print_debug("dimm: "); 
+	print_debug_hex8(SMBUS_MEM_DEVICE_START); 
+	for(i = 0; i < 256; i++) {
+		int status;
+		unsigned char byte;
+		if ((i & 0xf) == 0) {
+			print_debug("\r\n");
+			print_debug_hex8(i);
+			print_debug(": ");
+		}
+		status = smbus_read_byte(SMBUS_MEM_DEVICE_START, i);
+		if (status < 0) {
+			print_debug("bad device\r\n");
+			break;
+		}
+		byte = status & 0xff;
+		print_debug_hex8(byte);
+		print_debug_char(' ');
+	}
+	print_debug("\r\n");
 }
 
 
-#include "sdram/generic_sdram.c"
+
+static void dump_spd_registers2(void)
+{
+	unsigned dev;
+	print_debug("\r\n");
+	for(dev = SMBUS_MEM_DEVICE_START; dev <= SMBUS_MEM_DEVICE_END; dev += SMBUS_MEM_DEVICE_INC) {
+		print_debug("dimm: "); 
+		print_debug_hex8(dev); 
+		int status;
+		unsigned char byte;
+		status = smbus_read_byte(dev, 0);
+		if (status < 0) {
+			print_debug("bad device\r\n");
+			continue;
+		}
+		byte = status & 0xff;
+		print_debug_hex8(byte);
+		print_debug("\r\n");
+	}
+}
 
 static void main(void)
 {
 	uart_init();
 	console_init();
-	if (!sdram_enabled()) {
+	if (boot_cpu() && !cpu_init_detected()) {
+		setup_coherent_ht_domain();
+		enumerate_ht_chain();
+		print_pci_devices();
+		enable_smbus();
 		sdram_initialize();
 #if 0
+		dump_spd_registers();
+#endif
+		dump_spd_registers1();
+		dump_spd_registers2();
+#if 0
 		ram_fill(  0x00100000, 0x00180000);
 		ram_verify(0x00100000, 0x00180000);
 #endif
-#if 1
+#ifdef MEMORY_1024MB
 		ram_fill(  0x00000000, 0x00001000);
 		ram_verify(0x00000000, 0x00001000);
 #endif
+#ifdef MEMROY_512MB
+		ram_fill(  0x00000000, 0x01ffffff);
+		ram_verify(0x00000000, 0x01ffffff);
+#endif
 	}
 }
diff --git a/src/mainboard/amd/solo/mainboard.c b/src/mainboard/amd/solo/mainboard.c
index 6578ef6..5690bd5 100644
--- a/src/mainboard/amd/solo/mainboard.c
+++ b/src/mainboard/amd/solo/mainboard.c
@@ -9,129 +9,3 @@
 {
 	0
 };
-
-void
-mainboard_fixup(void)
-{
-}
-
-void
-final_mainboard_fixup(void)
-{
-#if 0
-//	void final_southbridge_fixup(void);
-//	void final_superio_fixup(void);
-
-	printk_info("AMD Solo initializing...");
-
-//	final_southbridge_fixup();
-
-//#ifndef USE_NEW_SUPERIO_INTERFACE
-//final_superio_fixup();
-//#endif
-#endif
-}
-
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{0x00, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT | 0, 0},
-	{0x01, DISABLED, NONE},
-	{0x02, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | INT | 0,  0},
-	{0x03, DISABLED, NONE},
-	{0x04, DISABLED, NONE},
-	{0x05, DISABLED, NONE},
-	{0x06, DISABLED, NONE},
-	{0x07, DISABLED, NONE},
-	{0x08, DISABLED, NONE},
-	{0x09, DISABLED, NONE},
-	{0x0a, DISABLED, NONE},
-	{0x0b, DISABLED, NONE},
-	{0x0c, DISABLED, NONE},
-	{0x0d, DISABLED, NONE},
-	{0x0e, DISABLED, NONE},
-	{0x0f, DISABLED, NONE},
-	{0x10, DISABLED, NONE},
-	{0x11, DISABLED, NONE},
-	{0x12, DISABLED, NONE},
-	{0x13, DISABLED, NONE},
-	{0x14, DISABLED, NONE},
-	{0x14, DISABLED, NONE},
-	{0x15, DISABLED, NONE},
-	{0x16, DISABLED, NONE},
-	{0x17, DISABLED, NONE},
-	{0x18, DISABLED, NONE},
-	{0x19, DISABLED, NONE},
-	{0x20, DISABLED, NONE},
-	{0x21, DISABLED, NONE},
-	{0x22, DISABLED, NONE},
-	{0x23, DISABLED, NONE},
-};
-
-static void setup_ioapic(void)
-{
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapic_base = 0xfec00000;
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
-
-	l = (unsigned long *) ioapic_base;
-	for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]);
-	     i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg *2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i==0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
-			a->reg, a->value_low, a->value_high);
-	}
-}
-
-static void lpc_init(struct device *dev)
-{
-	uint8_t byte;
-	printk_debug("lpc_init\n");
-#if 0
-	pci_read_config_byte(dev, 0x4B, &byte);
-	byte |= 1;
-	pci_write_config_byte(dev, 0x4B, byte);
-	setup_ioapic();
-#endif
-}
-
-static struct device_operations lpc_ops  = {
-	.read_resources = pci_dev_read_resources,
-	.set_resources  = pci_dev_set_resources,
-	.init = lpc_init,
-	.scan_bus = 0,
-};
-
-static struct pci_driver lpc_driver __pci_driver = {
-	.ops    = &lpc_ops,
-	.vendor = PCI_VENDOR_ID_AMD,
-	.device = 0x7468,
-};
diff --git a/src/ram/ramtest.c b/src/ram/ramtest.c
index 0e5e698..55c22e7 100644
--- a/src/ram/ramtest.c
+++ b/src/ram/ramtest.c
@@ -1,13 +1,13 @@
 static void write_phys(unsigned long addr, unsigned long value)
 {
-	unsigned long *ptr;
+	volatile unsigned long *ptr;
 	ptr = (void *)addr;
 	*ptr = value;
 }
 
 static unsigned long read_phys(unsigned long addr)
 {
-	unsigned long *ptr;
+	volatile unsigned long *ptr;
 	ptr = (void *)addr;
 	return *ptr;
 }
diff --git a/src/southbridge/amd/amd8111/amd8111_acpi.c b/src/southbridge/amd/amd8111/amd8111_acpi.c
new file mode 100644
index 0000000..120e0ee
--- /dev/null
+++ b/src/southbridge/amd/amd8111/amd8111_acpi.c
@@ -0,0 +1,53 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+static void acpi_init(struct device *dev)
+{
+	uint8_t byte;
+	uint16_t word;
+
+#if 0
+	printk_debug("ACPI: disabling NMI watchdog.. ");
+	pci_read_config_byte(dev, 0x49, &byte);
+	pci_write_config_byte(dev, 0x49, byte | (1<<2));
+
+
+	pci_read_config_byte(dev, 0x41, &byte);
+	pci_write_config_byte(dev, 0x41, byte | (1<<6)|(1<<2));
+
+	/* added from sourceforge */
+	pci_read_config_byte(dev, 0x48, &byte);
+	pci_write_config_byte(dev, 0x48, byte | (1<<3));
+
+	printk_debug("done.\n");
+
+
+	printk_debug("ACPI: Routing IRQ 12 to PS2 port.. ");
+	pci_read_config_word(dev, 0x46, &word);
+	pci_write_config_word(dev, 0x46, word | (1<<9));
+	printk_debug("done.\n");
+
+	
+	printk_debug("ACPI: setting PM class code.. ");
+	pci_write_config_dword(dev, 0x60, 0x06800000);
+	printk_debug("done.\n");
+#endif
+
+}
+
+static struct device_operations acpi_ops  = {
+	.read_resources = pci_dev_read_resources,
+	.set_resources  = pci_dev_set_resources,
+	.init = acpi_init,
+	.scan_bus = 0,
+};
+
+static struct pci_driver acpi_driver __pci_driver = {
+	.ops    = &acpi_ops,
+	.vendor = PCI_VENDOR_ID_AMD,
+	.device = PCI_DEVICE_ID_AMD_8111_ACPI,
+};
+
diff --git a/src/southbridge/amd/amd8111/amd8111_ide.c b/src/southbridge/amd/amd8111/amd8111_ide.c
new file mode 100644
index 0000000..f351606
--- /dev/null
+++ b/src/southbridge/amd/amd8111/amd8111_ide.c
@@ -0,0 +1,65 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+static void ide_init(struct device *dev)
+{
+
+	/* Enable ide devices so the linux ide driver will work */
+	uint16_t word;
+	int enable_a=1, enable_b=1;
+
+
+        printk_debug("ide_init\n");
+
+	pci_read_config_word(dev, 0x40, &word);
+	/* Ensure prefetch is disabled */
+	word &= ~((1 << 15) | (1 << 13));
+	if (enable_b) {
+		/* Enable secondary ide interface */
+		word |= (1<<0);
+		printk_debug("IDE1 ");
+	}
+	if (enable_a) {
+		/* Enable primary ide interface */
+		word |= (1<<1);
+		printk_debug("IDE0 ");
+	}
+
+	word |= (1<<12);
+	word |= (1<<14);
+
+	pci_write_config_word(dev, 0x40, word);
+
+	word = 0x0f;
+	pci_write_config_word(dev, 0x42, word);
+
+	/* The AMD768 has a bug where the BM DMA address must be
+	 * 256 byte aligned while it is only 16 bytes long.
+	 * Hard code this to a valid address below 0x1000
+	 * where automatic port address assignment starts.
+	 * FIXME: I assume the 8111 does the same thing. We should
+	 * clarify. stepan@suse.de
+	 */
+	pci_write_config_dword(dev, 0x20, 0xf01);
+
+	pci_write_config_dword(dev, 0x48, 0x205e5e5e);
+	word = 0x06a;
+	pci_write_config_word(dev, 0x4c, word);
+}
+
+static struct device_operations ide_ops  = {
+	.read_resources = pci_dev_read_resources,
+	.set_resources  = pci_dev_set_resources,
+	.init = ide_init,
+	.scan_bus = 0,
+};
+
+static struct pci_driver ide_driver __pci_driver = {
+	.ops    = &ide_ops,
+	.vendor = PCI_VENDOR_ID_AMD,
+	.device = PCI_DEVICE_ID_AMD_8111_IDE,
+};
+
diff --git a/src/southbridge/amd/amd8111/amd8111_lpc.c b/src/southbridge/amd/amd8111/amd8111_lpc.c
new file mode 100644
index 0000000..d8b4ba1
--- /dev/null
+++ b/src/southbridge/amd/amd8111/amd8111_lpc.c
@@ -0,0 +1,130 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+
+struct ioapicreg {
+	unsigned int reg;
+	unsigned int value_low, value_high;
+};
+
+static struct ioapicreg ioapicregvalues[] = {
+#define ALL		(0xff << 24)
+#define NONE		(0)
+#define DISABLED	(1 << 16)
+#define ENABLED		(0 << 16)
+#define TRIGGER_EDGE	(0 << 15)
+#define TRIGGER_LEVEL	(1 << 15)
+#define POLARITY_HIGH	(0 << 13)
+#define POLARITY_LOW	(1 << 13)
+#define PHYSICAL_DEST	(0 << 11)
+#define LOGICAL_DEST	(1 << 11)
+#define ExtINT		(7 << 8)
+#define NMI		(4 << 8)
+#define SMI		(2 << 8)
+#define INT		(1 << 8)
+	/* mask, trigger, polarity, destination, delivery, vector */
+	{0x00, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT | 0, 0},
+	{0x01, DISABLED, NONE},
+	{0x02, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | INT | 0,  0},
+	{0x03, DISABLED, NONE},
+	{0x04, DISABLED, NONE},
+	{0x05, DISABLED, NONE},
+	{0x06, DISABLED, NONE},
+	{0x07, DISABLED, NONE},
+	{0x08, DISABLED, NONE},
+	{0x09, DISABLED, NONE},
+	{0x0a, DISABLED, NONE},
+	{0x0b, DISABLED, NONE},
+	{0x0c, DISABLED, NONE},
+	{0x0d, DISABLED, NONE},
+	{0x0e, DISABLED, NONE},
+	{0x0f, DISABLED, NONE},
+	{0x10, DISABLED, NONE},
+	{0x11, DISABLED, NONE},
+	{0x12, DISABLED, NONE},
+	{0x13, DISABLED, NONE},
+	{0x14, DISABLED, NONE},
+	{0x14, DISABLED, NONE},
+	{0x15, DISABLED, NONE},
+	{0x16, DISABLED, NONE},
+	{0x17, DISABLED, NONE},
+	{0x18, DISABLED, NONE},
+	{0x19, DISABLED, NONE},
+	{0x20, DISABLED, NONE},
+	{0x21, DISABLED, NONE},
+	{0x22, DISABLED, NONE},
+	{0x23, DISABLED, NONE},
+};
+
+static void setup_ioapic(void)
+{
+	int i;
+	unsigned long value_low, value_high;
+	unsigned long ioapic_base = 0xfec00000;
+	volatile unsigned long *l;
+	struct ioapicreg *a = ioapicregvalues;
+
+	l = (unsigned long *) ioapic_base;
+	for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]);
+	     i++, a++) {
+		l[0] = (a->reg * 2) + 0x10;
+		l[4] = a->value_low;
+		value_low = l[4];
+		l[0] = (a->reg *2) + 0x11;
+		l[4] = a->value_high;
+		value_high = l[4];
+		if ((i==0) && (value_low == 0xffffffff)) {
+			printk_warning("IO APIC not responding.\n");
+			return;
+		}
+		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
+			a->reg, a->value_low, a->value_high);
+	}
+}
+
+static void lpc_init(struct device *dev)
+{
+	uint8_t byte;
+	int pwr_on=-1;
+
+	printk_debug("lpc_init\n");
+
+#if 0
+	/* IO APIC initialization */
+	pci_read_config_byte(dev, 0x4B, &byte);
+	byte |= 1;
+	pci_write_config_byte(dev, 0x4B, byte);
+	setup_ioapic();
+#endif
+
+	/* posted memory write enable */
+	pci_read_config_byte(dev, 0x46, &byte);
+	pci_write_config_byte(dev, 0x46, byte | (1<<0));
+
+	/* power after power fail */
+	pci_read_config_byte(dev, 0x43, &byte);
+	if (pwr_on) { 
+		byte &= ~(1<<6);
+	} else {
+		byte |= (1<<6);
+	}
+	pci_write_config_byte(dev, 0x43, byte);
+
+
+}
+
+static struct device_operations lpc_ops  = {
+	.read_resources = pci_dev_read_resources,
+	.set_resources  = pci_dev_set_resources,
+	.init = lpc_init,
+	.scan_bus = 0,
+};
+
+static struct pci_driver lpc_driver __pci_driver = {
+	.ops    = &lpc_ops,
+	.vendor = PCI_VENDOR_ID_AMD,
+	.device = PCI_DEVICE_ID_AMD_8111_ISA,
+};
diff --git a/src/southbridge/amd/amd8111/amd8111_smbus.c b/src/southbridge/amd/amd8111/amd8111_smbus.c
new file mode 100644
index 0000000..4b938d1
--- /dev/null
+++ b/src/southbridge/amd/amd8111/amd8111_smbus.c
@@ -0,0 +1,96 @@
+#include <smbus.h>
+#include <pci.h>
+#include <arch/io.h>
+
+#define PM_BUS 0
+#define PM_DEVFN (AMD8111_DEVFN+3)
+
+#define SMBUS_IO_BASE 0x1000
+#define SMBHSTSTAT 0
+#define SMBHSTCTL  2
+#define SMBHSTCMD  3
+#define SMBHSTADD  4
+#define SMBHSTDAT0 5
+#define SMBHSTDAT1 6
+#define SMBBLKDAT  7
+
+void smbus_enable(void)
+{
+	unsigned char byte;
+#if 0
+	/* iobase addr */
+	pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x90, SMBUS_IO_BASE | 1);
+	/* smbus enable */
+	pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0xd2, (0x4 << 1) | 1);
+	/* iospace enable */
+	pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
+#endif
+	/* Set PMIOEN, leaving default address 0xDD00 in 0x58 */
+	byte=pcibios_read_config_byte(0,PCI_DEVFN(0x7,3), 0x41);
+	pcibios_write_config_byte(0,PCI_DEVFN(0x7,3), byte | 0x80 );
+
+
+	/* cont reading 207 */
+}
+
+void smbus_setup(void)
+{
+	outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
+}
+
+static void smbus_wait_until_ready(void)
+{
+	while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
+		/* nop */
+	}
+}
+
+static void smbus_wait_until_done(void)
+{
+	unsigned char byte;
+	do {
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}
+	while((byte &1) == 1);
+	while( (byte & ~1) == 0) {
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}
+}
+
+int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
+{
+	unsigned char host_status_register;
+	unsigned char byte;
+
+	smbus_wait_until_ready();
+
+	/* setup transaction */
+	/* disable interrupts */
+	outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+	/* set the device I'm talking too */
+	outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD);
+	/* set the command/address... */
+	outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+	/* set up for a byte data read */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* clear any lingering errors, so the transaction will run */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+
+	/* clear the data byte...*/
+	outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
+
+	/* start the command */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* poll for transaction completion */
+	smbus_wait_until_done();
+
+	host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+
+	/* read results of transaction */
+	byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+
+	*result = byte;
+	return host_status_register != 0x02;
+}
diff --git a/src/southbridge/amd/amd8111/amd8111_usb.c b/src/southbridge/amd/amd8111/amd8111_usb.c
new file mode 100644
index 0000000..a6d3c4e
--- /dev/null
+++ b/src/southbridge/amd/amd8111/amd8111_usb.c
@@ -0,0 +1,34 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+static void usb_init(struct device *dev)
+{
+	uint32_t cmd;
+
+	printk_debug("USB: Setting up controller.. ");
+	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+	pci_write_config_dword(dev, PCI_COMMAND, 
+		cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | 
+		PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+
+
+	printk_debug("done.\n");
+
+}
+
+static struct device_operations usb_ops  = {
+	.read_resources = pci_dev_read_resources,
+	.set_resources  = pci_dev_set_resources,
+	.init = usb_init,
+	.scan_bus = 0,
+};
+
+static struct pci_driver usb_driver __pci_driver = {
+	.ops    = &usb_ops,
+	.vendor = PCI_VENDOR_ID_AMD,
+	.device = PCI_DEVICE_ID_AMD_8111_USB,
+};
+