[coreboot-gerrit] Patch set updated for coreboot: 3177bbb AMD: Isolate AGESA and PI build environments

Kyösti Mälkki (kyosti.malkki@gmail.com) gerrit at coreboot.org
Wed Oct 22 16:36:21 CEST 2014


Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7149

-gerrit

commit 3177bbbe76858073741aa5164dd14d9aa2f5dd93
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date:   Tue Oct 21 18:22:32 2014 +0300

    AMD: Isolate AGESA and PI build environments
    
    To backport features introduced with recent Chromebooks and/or Intel
    boards in general, heavy work on the AMD AGESA platform infrastructure
    is required. With the AGESA PI available in binary form only, community
    members have little means to verify, debug and develop for the said
    platforms.
    
    Thus it makes sense to fork the existing agesawrapper interfaces, to give
    AMD PI platforms a clean and independent sandbox. New directory layout
    reflects the separation already taken place under 3rdparty/ and vendorcode/.
    
    Change-Id: Ib60861266f8a70666617dde811663f2d5891a9e0
    Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
 src/cpu/amd/Kconfig                                |    1 +
 src/cpu/amd/Makefile.inc                           |    1 +
 src/cpu/amd/agesa/00730F01/Kconfig                 |   69 --
 src/cpu/amd/agesa/00730F01/Makefile.inc            |   29 -
 src/cpu/amd/agesa/00730F01/acpi/cpu.asl            |   83 --
 src/cpu/amd/agesa/00730F01/chip_name.c             |   24 -
 src/cpu/amd/agesa/00730F01/model_16_init.c         |  133 ---
 src/cpu/amd/agesa/Kconfig                          |    2 -
 src/cpu/amd/agesa/Makefile.inc                     |    1 -
 src/cpu/amd/agesa/amd_late_init.c                  |    5 +-
 src/cpu/amd/pi/00730F01/Kconfig                    |   69 ++
 src/cpu/amd/pi/00730F01/Makefile.inc               |   29 +
 src/cpu/amd/pi/00730F01/acpi/cpu.asl               |   83 ++
 src/cpu/amd/pi/00730F01/chip_name.c                |   24 +
 src/cpu/amd/pi/00730F01/model_16_init.c            |  133 +++
 src/cpu/amd/pi/Kconfig                             |   76 ++
 src/cpu/amd/pi/Makefile.inc                        |   45 +
 src/cpu/amd/pi/amd_late_init.c                     |   60 +
 src/cpu/amd/pi/cache_as_ram.inc                    |  110 ++
 src/cpu/amd/pi/heapmanager.c                       |  342 ++++++
 src/cpu/amd/pi/s3_resume.c                         |  311 ++++++
 src/cpu/amd/pi/s3_resume.h                         |   38 +
 src/cpu/amd/pi/spi.c                               |   49 +
 src/include/cpu/amd/car.h                          |    2 +-
 src/mainboard/amd/olivehillplus/BiosCallOuts.c     |    2 +-
 src/mainboard/amd/olivehillplus/Kconfig            |    4 +-
 src/mainboard/amd/olivehillplus/agesawrapper.c     |    4 +-
 src/mainboard/amd/olivehillplus/devicetree.cb      |   14 +-
 src/mainboard/amd/olivehillplus/dsdt.asl           |    4 +-
 src/mainboard/amd/olivehillplus/mainboard.c        |    4 +-
 src/mainboard/amd/olivehillplus/romstage.c         |    4 +-
 src/northbridge/amd/Kconfig                        |    2 +
 src/northbridge/amd/Makefile.inc                   |    1 +
 src/northbridge/amd/agesa/00730F01/Kconfig         |   53 -
 src/northbridge/amd/agesa/00730F01/Makefile.inc    |   22 -
 .../amd/agesa/00730F01/acpi/northbridge.asl        |  100 --
 src/northbridge/amd/agesa/00730F01/chip.h          |   28 -
 src/northbridge/amd/agesa/00730F01/dimmSpd.c       |   59 -
 src/northbridge/amd/agesa/00730F01/northbridge.c   | 1154 --------------------
 src/northbridge/amd/agesa/00730F01/northbridge.h   |   26 -
 src/northbridge/amd/agesa/BiosCallOuts.h           |    2 +-
 src/northbridge/amd/agesa/Kconfig                  |    1 -
 src/northbridge/amd/agesa/Makefile.inc             |    1 -
 src/northbridge/amd/agesa/def_callouts.c           |    2 +-
 src/northbridge/amd/pi/00730F01/Kconfig            |   53 +
 src/northbridge/amd/pi/00730F01/Makefile.inc       |   22 +
 .../amd/pi/00730F01/acpi/northbridge.asl           |  100 ++
 src/northbridge/amd/pi/00730F01/chip.h             |   28 +
 src/northbridge/amd/pi/00730F01/dimmSpd.c          |   59 +
 src/northbridge/amd/pi/00730F01/northbridge.c      | 1154 ++++++++++++++++++++
 src/northbridge/amd/pi/00730F01/northbridge.h      |   26 +
 src/northbridge/amd/pi/BiosCallOuts.h              |   80 ++
 src/northbridge/amd/pi/Kconfig                     |   36 +
 src/northbridge/amd/pi/Makefile.inc                |   23 +
 src/northbridge/amd/pi/agesawrapper_call.h         |   62 ++
 src/northbridge/amd/pi/def_callouts.c              |  145 +++
 src/northbridge/amd/pi/dimmSpd.h                   |   30 +
 src/southbridge/amd/agesa/hudson/Kconfig           |    4 +-
 src/southbridge/amd/agesa/hudson/Makefile.inc      |    4 +-
 src/vendorcode/amd/Kconfig                         |   15 +-
 src/vendorcode/amd/pi/00730F01/Kconfig             |    6 +-
 src/vendorcode/amd/pi/Makefile.inc                 |    2 +-
 62 files changed, 3226 insertions(+), 1829 deletions(-)

diff --git a/src/cpu/amd/Kconfig b/src/cpu/amd/Kconfig
index 5603f41..ab2d1f2 100644
--- a/src/cpu/amd/Kconfig
+++ b/src/cpu/amd/Kconfig
@@ -19,3 +19,4 @@ source src/cpu/amd/geode_lx/Kconfig
 source src/cpu/amd/sc520/Kconfig
 
 source src/cpu/amd/agesa/Kconfig
+source src/cpu/amd/pi/Kconfig
diff --git a/src/cpu/amd/Makefile.inc b/src/cpu/amd/Makefile.inc
index 85ce7f6..6257615 100644
--- a/src/cpu/amd/Makefile.inc
+++ b/src/cpu/amd/Makefile.inc
@@ -15,3 +15,4 @@ subdirs-$(CONFIG_CPU_AMD_SC520) += sc520
 subdirs-$(CONFIG_CPU_AMD_SOCKET_S1G1) += socket_S1G1
 
 subdirs-$(CONFIG_CPU_AMD_AGESA) += agesa
+subdirs-$(CONFIG_CPU_AMD_PI) += pi
diff --git a/src/cpu/amd/agesa/00730F01/Kconfig b/src/cpu/amd/agesa/00730F01/Kconfig
deleted file mode 100644
index ccc44d6..0000000
--- a/src/cpu/amd/agesa/00730F01/Kconfig
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# This file is part of the coreboot project.
-#
-# Copyright (C) 2012 Advanced Micro Devices, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-config CPU_AMD_AGESA_00730F01
-	bool
-	select PCI_IO_CFG_EXT
-	select X86_AMD_FIXED_MTRRS
-
-if CPU_AMD_AGESA_00730F01
-
-config CPU_ADDR_BITS
-	int
-	default 40
-
-config CPU_SOCKET_TYPE
-	hex
-	default 0x10
-
-# DDR2 and REG
-config DIMM_SUPPORT
-	hex
-	default 0x0104
-
-config EXT_RT_TBL_SUPPORT
-	bool
-	default n
-
-config EXT_CONF_SUPPORT
-	bool
-	default n
-
-config CBB
-	hex
-	default 0x0
-
-config CDB
-	hex
-	default 0x18
-
-config XIP_ROM_BASE
-	hex
-	default 0xfff80000
-
-config XIP_ROM_SIZE
-	hex
-	default 0x100000
-
-config HIGH_SCRATCH_MEMORY_SIZE
-	hex
-	# Assume the maximum size of stack as (0xA0000 - 0x30000 + 0x1000)
-	default 0xA1000
-
-endif
diff --git a/src/cpu/amd/agesa/00730F01/Makefile.inc b/src/cpu/amd/agesa/00730F01/Makefile.inc
deleted file mode 100644
index fba2185..0000000
--- a/src/cpu/amd/agesa/00730F01/Makefile.inc
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# This file is part of the coreboot project.
-#
-# Copyright (C) 2012 Advanced Micro Devices, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-ramstage-y += chip_name.c
-ramstage-y += model_16_init.c
-
-subdirs-y += ../../mtrr
-subdirs-y += ../../../x86/tsc
-subdirs-y += ../../../x86/lapic
-subdirs-y += ../../../x86/cache
-subdirs-y += ../../../x86/mtrr
-subdirs-y += ../../../x86/pae
-subdirs-y += ../../../x86/smm
diff --git a/src/cpu/amd/agesa/00730F01/acpi/cpu.asl b/src/cpu/amd/agesa/00730F01/acpi/cpu.asl
deleted file mode 100644
index dc86df5..0000000
--- a/src/cpu/amd/agesa/00730F01/acpi/cpu.asl
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 Sage Electronic Engineering, LLC
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-	/*
-	 * Processor Object
-	 *
-	 */
-	Scope (\_PR) {		/* define processor scope */
-		Processor(
-			P000,		/* name space name */
-			0,		/* Unique number for this processor */
-			0x810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-
-		Processor(
-			P001,		/* name space name */
-			1,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-		Processor(
-			P002,		/* name space name */
-			2,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-		Processor(
-			P003,		/* name space name */
-			3,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-		Processor(
-			P004,		/* name space name */
-			4,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-		Processor(
-			P005,		/* name space name */
-			5,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-		Processor(
-			P006,		/* name space name */
-			6,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-		Processor(
-			P007,		/* name space name */
-			7,		/* Unique number for this processor */
-			0x0810,		/* PBLK system I/O address !hardcoded! */
-			0x06		/* PBLKLEN for boot processor */
-			) {
-		}
-	} /* End _PR scope */
-
diff --git a/src/cpu/amd/agesa/00730F01/chip_name.c b/src/cpu/amd/agesa/00730F01/chip_name.c
deleted file mode 100644
index 7a1c06c..0000000
--- a/src/cpu/amd/agesa/00730F01/chip_name.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <device/device.h>
-
-struct chip_operations cpu_amd_agesa_00730F01_ops = {
-	CHIP_NAME("AMD CPU Family 16h")
-};
diff --git a/src/cpu/amd/agesa/00730F01/model_16_init.c b/src/cpu/amd/agesa/00730F01/model_16_init.c
deleted file mode 100644
index 8053fd1..0000000
--- a/src/cpu/amd/agesa/00730F01/model_16_init.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <console/console.h>
-#include <cpu/x86/msr.h>
-#include <cpu/amd/mtrr.h>
-#include <device/device.h>
-#include <device/pci.h>
-#include <string.h>
-#include <cpu/x86/msr.h>
-#include <cpu/x86/pae.h>
-#include <pc80/mc146818rtc.h>
-#include <cpu/x86/lapic.h>
-
-#include <cpu/cpu.h>
-#include <cpu/x86/cache.h>
-#include <cpu/x86/mtrr.h>
-#include <cpu/amd/amdfam16.h>
-#include <arch/acpi.h>
-#if CONFIG_HAVE_ACPI_RESUME
-#include <cpu/amd/agesa/s3_resume.h>
-#endif
-
-static void model_16_init(device_t dev)
-{
-	printk(BIOS_DEBUG, "Model 16 Init.\n");
-
-	u8 i;
-	msr_t msr;
-	int msrno;
-#if CONFIG_LOGICAL_CPUS
-	u32 siblings;
-#endif
-
-	//x86_enable_cache();
-	//amd_setup_mtrrs();
-	//x86_mtrr_check();
-	disable_cache ();
-	/* Enable access to AMD RdDram and WrDram extension bits */
-	msr = rdmsr(SYSCFG_MSR);
-	msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
-	msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
-	wrmsr(SYSCFG_MSR, msr);
-
-	// BSP: make a0000-bffff UC, c0000-fffff WB, same as OntarioApMtrrSettingsList for APs
-	msr.lo = msr.hi = 0;
-	wrmsr (0x259, msr);
-	msr.lo = msr.hi = 0x1e1e1e1e;
-	wrmsr(0x250, msr);
-	wrmsr(0x258, msr);
-	for (msrno = 0x268; msrno <= 0x26f; msrno++)
-		wrmsr (msrno, msr);
-
-	msr = rdmsr(SYSCFG_MSR);
-	msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
-	msr.lo |= SYSCFG_MSR_MtrrFixDramEn;
-	wrmsr(SYSCFG_MSR, msr);
-
-#if CONFIG_HAVE_ACPI_RESUME
-	if (acpi_slp_type == 3)
-		restore_mtrr();
-#endif
-
-	x86_mtrr_check();
-	x86_enable_cache();
-
-	/* zero the machine check error status registers */
-	msr.lo = 0;
-	msr.hi = 0;
-	for (i = 0; i < 6; i++) {
-		wrmsr(MCI_STATUS + (i * 4), msr);
-	}
-
-
-	/* Enable the local cpu apics */
-	setup_lapic();
-
-#if CONFIG_LOGICAL_CPUS
-	siblings = cpuid_ecx(0x80000008) & 0xff;
-
-	if (siblings > 0) {
-		msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
-		msr.lo |= 1 << 28;
-		wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
-
-		msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
-		msr.hi |= 1 << (33 - 32);
-		wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
-	}
-	printk(BIOS_DEBUG, "siblings = %02d, ", siblings);
-#endif
-
-	/* DisableCf8ExtCfg */
-	msr = rdmsr(NB_CFG_MSR);
-	msr.hi &= ~(1 << (46 - 32));
-	wrmsr(NB_CFG_MSR, msr);
-
-
-	/* Write protect SMM space with SMMLOCK. */
-	msr = rdmsr(HWCR_MSR);
-	msr.lo |= (1 << 0);
-	wrmsr(HWCR_MSR, msr);
-}
-
-static struct device_operations cpu_dev_ops = {
-	.init = model_16_init,
-};
-
-static struct cpu_device_id cpu_table[] = {
-	{ X86_VENDOR_AMD, 0x730f00 },	  /* ML-A0, Guess, TODO: */
-	{ 0, 0 },
-};
-
-static const struct cpu_driver model_16 __cpu_driver = {
-	.ops      = &cpu_dev_ops,
-	.id_table = cpu_table,
-};
diff --git a/src/cpu/amd/agesa/Kconfig b/src/cpu/amd/agesa/Kconfig
index d288fef..fcba0cf 100644
--- a/src/cpu/amd/agesa/Kconfig
+++ b/src/cpu/amd/agesa/Kconfig
@@ -25,7 +25,6 @@ config CPU_AMD_AGESA
 	default y if CPU_AMD_AGESA_FAMILY15
 	default y if CPU_AMD_AGESA_FAMILY15_TN
 	default y if CPU_AMD_AGESA_FAMILY16_KB
-	default y if CPU_AMD_AGESA_00730F01
 	default n
 	select ARCH_BOOTBLOCK_X86_32
 	select ARCH_ROMSTAGE_X86_32
@@ -85,5 +84,4 @@ source src/cpu/amd/agesa/family14/Kconfig
 source src/cpu/amd/agesa/family15/Kconfig
 source src/cpu/amd/agesa/family15tn/Kconfig
 source src/cpu/amd/agesa/family16kb/Kconfig
-source src/cpu/amd/agesa/00730F01/Kconfig
 
diff --git a/src/cpu/amd/agesa/Makefile.inc b/src/cpu/amd/agesa/Makefile.inc
index 800f8e7..beba040 100644
--- a/src/cpu/amd/agesa/Makefile.inc
+++ b/src/cpu/amd/agesa/Makefile.inc
@@ -22,7 +22,6 @@ subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY14) += family14
 subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY15) += family15
 subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY15_TN) += family15tn
 subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY16_KB) += family16kb
-subdirs-$(CONFIG_CPU_AMD_AGESA_00730F01) += 00730F01
 
 romstage-y += s3_resume.c
 ramstage-y += s3_resume.c
diff --git a/src/cpu/amd/agesa/amd_late_init.c b/src/cpu/amd/agesa/amd_late_init.c
index cab03a3..4fa2e4e 100644
--- a/src/cpu/amd/agesa/amd_late_init.c
+++ b/src/cpu/amd/agesa/amd_late_init.c
@@ -31,9 +31,6 @@
 #include <sb_cimx.h>
 #endif
 
-#define NORTHBRIDGE_00700F00 IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY_16KB)
-#define NORTHBRIDGE_00730F01 IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AGESA_00730F01)
-
 static void agesawrapper_post_device(void *unused)
 {
 	if (acpi_is_wakeup_s3())
@@ -41,7 +38,7 @@ static void agesawrapper_post_device(void *unused)
 
 	AGESAWRAPPER(amdinitlate);
 
-#if (NORTHBRIDGE_00700F00) || (NORTHBRIDGE_00730F01)
+#if IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY_16KB)
 	device_t dev;
 	u32 value;
 	dev = dev_find_slot(0, PCI_DEVFN(0, 0)); /* clear IoapicSbFeatureEn */
diff --git a/src/cpu/amd/pi/00730F01/Kconfig b/src/cpu/amd/pi/00730F01/Kconfig
new file mode 100644
index 0000000..e610ea2
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/Kconfig
@@ -0,0 +1,69 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+config CPU_AMD_PI_00730F01
+	bool
+	select PCI_IO_CFG_EXT
+	select X86_AMD_FIXED_MTRRS
+
+if CPU_AMD_PI_00730F01
+
+config CPU_ADDR_BITS
+	int
+	default 40
+
+config CPU_SOCKET_TYPE
+	hex
+	default 0x10
+
+# DDR2 and REG
+config DIMM_SUPPORT
+	hex
+	default 0x0104
+
+config EXT_RT_TBL_SUPPORT
+	bool
+	default n
+
+config EXT_CONF_SUPPORT
+	bool
+	default n
+
+config CBB
+	hex
+	default 0x0
+
+config CDB
+	hex
+	default 0x18
+
+config XIP_ROM_BASE
+	hex
+	default 0xfff80000
+
+config XIP_ROM_SIZE
+	hex
+	default 0x100000
+
+config HIGH_SCRATCH_MEMORY_SIZE
+	hex
+	# Assume the maximum size of stack as (0xA0000 - 0x30000 + 0x1000)
+	default 0xA1000
+
+endif
diff --git a/src/cpu/amd/pi/00730F01/Makefile.inc b/src/cpu/amd/pi/00730F01/Makefile.inc
new file mode 100644
index 0000000..fba2185
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/Makefile.inc
@@ -0,0 +1,29 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+ramstage-y += chip_name.c
+ramstage-y += model_16_init.c
+
+subdirs-y += ../../mtrr
+subdirs-y += ../../../x86/tsc
+subdirs-y += ../../../x86/lapic
+subdirs-y += ../../../x86/cache
+subdirs-y += ../../../x86/mtrr
+subdirs-y += ../../../x86/pae
+subdirs-y += ../../../x86/smm
diff --git a/src/cpu/amd/pi/00730F01/acpi/cpu.asl b/src/cpu/amd/pi/00730F01/acpi/cpu.asl
new file mode 100644
index 0000000..dc86df5
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/acpi/cpu.asl
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+	/*
+	 * Processor Object
+	 *
+	 */
+	Scope (\_PR) {		/* define processor scope */
+		Processor(
+			P000,		/* name space name */
+			0,		/* Unique number for this processor */
+			0x810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+
+		Processor(
+			P001,		/* name space name */
+			1,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+		Processor(
+			P002,		/* name space name */
+			2,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+		Processor(
+			P003,		/* name space name */
+			3,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+		Processor(
+			P004,		/* name space name */
+			4,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+		Processor(
+			P005,		/* name space name */
+			5,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+		Processor(
+			P006,		/* name space name */
+			6,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+		Processor(
+			P007,		/* name space name */
+			7,		/* Unique number for this processor */
+			0x0810,		/* PBLK system I/O address !hardcoded! */
+			0x06		/* PBLKLEN for boot processor */
+			) {
+		}
+	} /* End _PR scope */
+
diff --git a/src/cpu/amd/pi/00730F01/chip_name.c b/src/cpu/amd/pi/00730F01/chip_name.c
new file mode 100644
index 0000000..4a2c3ea
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/chip_name.c
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+
+struct chip_operations cpu_amd_pi_00730F01_ops = {
+	CHIP_NAME("AMD CPU Family 16h")
+};
diff --git a/src/cpu/amd/pi/00730F01/model_16_init.c b/src/cpu/amd/pi/00730F01/model_16_init.c
new file mode 100644
index 0000000..8053fd1
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/model_16_init.c
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/mtrr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <string.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/pae.h>
+#include <pc80/mc146818rtc.h>
+#include <cpu/x86/lapic.h>
+
+#include <cpu/cpu.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/amdfam16.h>
+#include <arch/acpi.h>
+#if CONFIG_HAVE_ACPI_RESUME
+#include <cpu/amd/agesa/s3_resume.h>
+#endif
+
+static void model_16_init(device_t dev)
+{
+	printk(BIOS_DEBUG, "Model 16 Init.\n");
+
+	u8 i;
+	msr_t msr;
+	int msrno;
+#if CONFIG_LOGICAL_CPUS
+	u32 siblings;
+#endif
+
+	//x86_enable_cache();
+	//amd_setup_mtrrs();
+	//x86_mtrr_check();
+	disable_cache ();
+	/* Enable access to AMD RdDram and WrDram extension bits */
+	msr = rdmsr(SYSCFG_MSR);
+	msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+
+	// BSP: make a0000-bffff UC, c0000-fffff WB, same as OntarioApMtrrSettingsList for APs
+	msr.lo = msr.hi = 0;
+	wrmsr (0x259, msr);
+	msr.lo = msr.hi = 0x1e1e1e1e;
+	wrmsr(0x250, msr);
+	wrmsr(0x258, msr);
+	for (msrno = 0x268; msrno <= 0x26f; msrno++)
+		wrmsr (msrno, msr);
+
+	msr = rdmsr(SYSCFG_MSR);
+	msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+	msr.lo |= SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+
+#if CONFIG_HAVE_ACPI_RESUME
+	if (acpi_slp_type == 3)
+		restore_mtrr();
+#endif
+
+	x86_mtrr_check();
+	x86_enable_cache();
+
+	/* zero the machine check error status registers */
+	msr.lo = 0;
+	msr.hi = 0;
+	for (i = 0; i < 6; i++) {
+		wrmsr(MCI_STATUS + (i * 4), msr);
+	}
+
+
+	/* Enable the local cpu apics */
+	setup_lapic();
+
+#if CONFIG_LOGICAL_CPUS
+	siblings = cpuid_ecx(0x80000008) & 0xff;
+
+	if (siblings > 0) {
+		msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
+		msr.lo |= 1 << 28;
+		wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
+
+		msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
+		msr.hi |= 1 << (33 - 32);
+		wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
+	}
+	printk(BIOS_DEBUG, "siblings = %02d, ", siblings);
+#endif
+
+	/* DisableCf8ExtCfg */
+	msr = rdmsr(NB_CFG_MSR);
+	msr.hi &= ~(1 << (46 - 32));
+	wrmsr(NB_CFG_MSR, msr);
+
+
+	/* Write protect SMM space with SMMLOCK. */
+	msr = rdmsr(HWCR_MSR);
+	msr.lo |= (1 << 0);
+	wrmsr(HWCR_MSR, msr);
+}
+
+static struct device_operations cpu_dev_ops = {
+	.init = model_16_init,
+};
+
+static struct cpu_device_id cpu_table[] = {
+	{ X86_VENDOR_AMD, 0x730f00 },	  /* ML-A0, Guess, TODO: */
+	{ 0, 0 },
+};
+
+static const struct cpu_driver model_16 __cpu_driver = {
+	.ops      = &cpu_dev_ops,
+	.id_table = cpu_table,
+};
diff --git a/src/cpu/amd/pi/Kconfig b/src/cpu/amd/pi/Kconfig
new file mode 100644
index 0000000..366beb4
--- /dev/null
+++ b/src/cpu/amd/pi/Kconfig
@@ -0,0 +1,76 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2011 - 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+config CPU_AMD_PI
+	bool
+	default y if CPU_AMD_PI_00730F01
+	default n
+	select ARCH_BOOTBLOCK_X86_32
+	select ARCH_ROMSTAGE_X86_32
+	select ARCH_RAMSTAGE_X86_32
+	select TSC_SYNC_LFENCE
+	select UDELAY_LAPIC
+	select LAPIC_MONOTONIC_TIMER
+	select BROKEN_CAR_MIGRATE
+	select SPI_FLASH if HAVE_ACPI_RESUME
+
+if CPU_AMD_PI
+
+config UDELAY_IO
+	bool
+	default n
+
+config XIP_ROM_SIZE
+	hex
+	default 0x100000
+	help
+	  Overwride the default write through caching size as 1M Bytes.
+	  On some AMD platforms, one socket supports 2 or more kinds of
+	  processor family, compiling several CPU families agesa code
+	  will increase the romstage size.
+	  In order to execute romstage in place on the flash ROM,
+	  more space is required to be set as write through caching.
+
+config UDELAY_LAPIC_FIXED_FSB
+	int
+	default 200
+
+# TODO: Sync these with definitions in PI vendorcode.
+# DCACHE_RAM_BASE must equal BSP_STACK_BASE_ADDR.
+# DCACHE_RAM_SIZE must equal BSP_STACK_SIZE.
+
+config DCACHE_RAM_BASE
+	hex
+	default 0x30000
+
+config DCACHE_RAM_SIZE
+	hex
+	default 0x10000
+
+config S3_DATA_POS
+	hex
+	default 0xFFFF0000
+
+config S3_DATA_SIZE
+	int
+	default 32768
+
+endif # CPU_AMD_PI
+
+source src/cpu/amd/pi/00730F01/Kconfig
diff --git a/src/cpu/amd/pi/Makefile.inc b/src/cpu/amd/pi/Makefile.inc
new file mode 100644
index 0000000..8228b12
--- /dev/null
+++ b/src/cpu/amd/pi/Makefile.inc
@@ -0,0 +1,45 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2011 - 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+subdirs-$(CONFIG_CPU_AMD_PI_00730F01) += 00730F01
+
+romstage-y += s3_resume.c
+ramstage-y += s3_resume.c
+ramstage-$(CONFIG_SPI_FLASH) += spi.c
+
+cpu_incs += $(src)/cpu/amd/pi/cache_as_ram.inc
+
+romstage-y += heapmanager.c
+ramstage-y += heapmanager.c
+ramstage-y += amd_late_init.c
+
+ifeq ($(CONFIG_HAVE_ACPI_RESUME), y)
+
+$(obj)/coreboot_s3nv.rom: $(obj)/config.h
+	echo "    S3 NVRAM   $(CONFIG_S3_DATA_POS) (S3 storage area)"
+	# force C locale, so cygwin awk doesn't try to interpret the 0xff below as UTF-8 (or worse)
+	printf %d $(CONFIG_S3_DATA_SIZE) | LC_ALL=C awk '{for (i=0; i<$$1; i++) {printf "%c", 255}}' > $@.tmp
+	mv $@.tmp $@
+
+cbfs-files-y += s3nv
+s3nv-file := $(obj)/coreboot_s3nv.rom
+s3nv-position := $(CONFIG_S3_DATA_POS)
+s3nv-type := raw
+
+endif # CONFIG_HAVE_ACPI_RESUME == y
diff --git a/src/cpu/amd/pi/amd_late_init.c b/src/cpu/amd/pi/amd_late_init.c
new file mode 100644
index 0000000..efb1667
--- /dev/null
+++ b/src/cpu/amd/pi/amd_late_init.c
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/acpi.h>
+#include <bootstate.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <device/pci_ops.h>
+
+#include <agesawrapper.h>
+#include <northbridge/amd/pi/agesawrapper_call.h>
+
+static void agesawrapper_post_device(void *unused)
+{
+	if (acpi_is_wakeup_s3())
+		return;
+
+	AGESAWRAPPER(amdinitlate);
+
+#if (1) /* NORTHBRIDGE_00730F01 */
+	device_t dev;
+	u32 value;
+	dev = dev_find_slot(0, PCI_DEVFN(0, 0)); /* clear IoapicSbFeatureEn */
+	pci_write_config32(dev, 0xF8, 0);
+	pci_write_config32(dev, 0xFC, 5); /* TODO: move it to dsdt.asl */
+
+	/* disable No Snoop */
+	dev = dev_find_slot(0, PCI_DEVFN(1, 1));
+	value = pci_read_config32(dev, 0x60);
+	value &= ~(1 << 11);
+	pci_write_config32(dev, 0x60, value);
+#endif
+
+	if (!acpi_s3_resume_allowed())
+		return;
+
+	AGESAWRAPPER(amdS3Save);
+}
+
+BOOT_STATE_INIT_ENTRIES(agesa_bscb) = {
+	BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT,
+	                      agesawrapper_post_device, NULL),
+};
diff --git a/src/cpu/amd/pi/cache_as_ram.inc b/src/cpu/amd/pi/cache_as_ram.inc
new file mode 100644
index 0000000..449cf69
--- /dev/null
+++ b/src/cpu/amd/pi/cache_as_ram.inc
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/******************************************************************************
+ * AMD Generic Encapsulated Software Architecture
+ *
+ * $Workfile:: cache_as_ram.inc
+ *
+ * Description: cache_as_ram.inc - AGESA Module Entry Point for GCC complier
+ *
+ ******************************************************************************
+ */
+
+#include "gcccar.inc"
+#include <cpu/x86/cache.h>
+
+/*
+ * XMM map:
+ *   xmm0: BIST
+ *   xmm1: backup ebx -- cpu_init_detected
+ */
+
+.code32
+.globl cache_as_ram_setup, disable_cache_as_ram, cache_as_ram_setup_out
+
+cache_as_ram_setup:
+
+  post_code(0xa0)
+
+  /* enable SSE2 128bit instructions */
+  /* Turn on OSFXSR [BIT9] and OSXMMEXCPT [BIT10] onto CR4 register */
+
+  movl %cr4, %eax
+  orl $(3<<9), %eax
+  movl %eax, %cr4
+
+  /* Get the cpu_init_detected */
+  mov $1, %eax
+  cpuid
+  shr $24, %ebx
+
+  /* Save the BIST result */
+  cvtsi2sd  %ebp, %xmm0
+
+  /* for normal part %ebx already contain cpu_init_detected from fallback call */
+
+  /* Save the cpu_init_detected */
+  cvtsi2sd  %ebx, %xmm1
+
+  post_code(0xa1)
+  AMD_ENABLE_STACK
+
+  post_code(0xa1)
+
+  /* Restore the BIST result */
+  cvtsd2si  %xmm0, %edx
+
+  /* Restore the  cpu_init_detected */
+  cvtsd2si  %xmm1, %ebx
+
+  pushl %ebx  /* init detected */
+  pushl %edx  /* bist */
+  call  cache_as_ram_main
+
+  /* Should never see this postcode */
+  post_code(0xaf)
+stop:
+  jmp stop
+
+disable_cache_as_ram:
+  /* Save return stack */
+  movd 0(%esp), %xmm1
+  movd %esp, %xmm0
+
+  /* Disable cache */
+  movl	%cr0, %eax
+  orl	$CR0_CacheDisable, %eax
+  movl	%eax, %cr0
+
+  AMD_DISABLE_STACK
+
+  /* enable cache */
+  movl %cr0, %eax
+  andl $0x9fffffff, %eax
+  movl %eax, %cr0
+  xorl %eax, %eax
+
+  /* Restore the return stack */
+  wbinvd
+  movd %xmm0, %esp
+  movd %xmm1, (%esp)
+  ret
+
+cache_as_ram_setup_out:
diff --git a/src/cpu/amd/pi/heapmanager.c b/src/cpu/amd/pi/heapmanager.c
new file mode 100644
index 0000000..d2c3931
--- /dev/null
+++ b/src/cpu/amd/pi/heapmanager.c
@@ -0,0 +1,342 @@
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include <northbridge/amd/agesa/BiosCallOuts.h>
+#include "heapManager.h"
+
+#include <cbmem.h>
+#include <arch/acpi.h>
+#include <string.h>
+
+UINT32 GetHeapBase(AMD_CONFIG_PARAMS *StdHeader)
+{
+	UINT32 heap = BIOS_HEAP_START_ADDRESS;
+
+#if CONFIG_HAVE_ACPI_RESUME
+	/* Both romstage and ramstage has this S3 detect. */
+	if (acpi_get_sleep_type() == 3)
+		heap = (UINT32) cbmem_find(CBMEM_ID_RESUME_SCRATCH) +
+		 (CONFIG_HIGH_SCRATCH_MEMORY_SIZE - BIOS_HEAP_SIZE);
+		  /* himem_heap_base + high_stack_size */
+#endif
+	return heap;
+}
+
+void EmptyHeap(void)
+{
+	void *BiosManagerPtr = (void *) GetHeapBase(NULL);
+	memset(BiosManagerPtr, 0, BIOS_HEAP_SIZE);
+}
+
+#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
+
+#define AGESA_RUNTIME_SIZE 4096
+
+static AGESA_STATUS alloc_cbmem(AGESA_BUFFER_PARAMS *AllocParams) {
+	static unsigned int used = 0;
+	void *p = cbmem_find(CBMEM_ID_AGESA_RUNTIME);
+
+	if ((AGESA_RUNTIME_SIZE - used) < AllocParams->BufferLength) {
+		return AGESA_BOUNDS_CHK;
+	}
+
+	/* first time allocation */
+	if (!p) {
+		p = cbmem_add(CBMEM_ID_AGESA_RUNTIME, AGESA_RUNTIME_SIZE);
+		if (!p)
+			return AGESA_BOUNDS_CHK;
+	}
+
+	AllocParams->BufferPointer = p + used;
+	used += AllocParams->BufferLength;
+	return AGESA_SUCCESS;
+}
+#endif
+
+AGESA_STATUS agesa_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	UINT32              AvailableHeapSize;
+	UINT8               *BiosHeapBaseAddr;
+	UINT32              CurrNodeOffset;
+	UINT32              PrevNodeOffset;
+	UINT32              FreedNodeOffset;
+	UINT32              BestFitNodeOffset;
+	UINT32              BestFitPrevNodeOffset;
+	UINT32              NextFreeOffset;
+	BIOS_BUFFER_NODE   *CurrNodePtr;
+	BIOS_BUFFER_NODE   *FreedNodePtr;
+	BIOS_BUFFER_NODE   *BestFitNodePtr;
+	BIOS_BUFFER_NODE   *BestFitPrevNodePtr;
+	BIOS_BUFFER_NODE   *NextFreePtr;
+	BIOS_HEAP_MANAGER  *BiosHeapBasePtr;
+	AGESA_BUFFER_PARAMS *AllocParams;
+
+	AllocParams = ((AGESA_BUFFER_PARAMS *) ConfigPtr);
+	AllocParams->BufferPointer = NULL;
+
+#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
+	/* if the allocation is for runtime use simple CBMEM data */
+	if (Data == HEAP_CALLOUT_RUNTIME)
+		return alloc_cbmem(AllocParams);
+#endif
+
+	AvailableHeapSize = BIOS_HEAP_SIZE - sizeof (BIOS_HEAP_MANAGER);
+	BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
+	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
+
+	if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) {
+		/* First allocation */
+		CurrNodeOffset = sizeof (BIOS_HEAP_MANAGER);
+		CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
+		CurrNodePtr->BufferHandle = AllocParams->BufferHandle;
+		CurrNodePtr->BufferSize = AllocParams->BufferLength;
+		CurrNodePtr->NextNodeOffset = 0;
+		AllocParams->BufferPointer = (UINT8 *) CurrNodePtr + sizeof (BIOS_BUFFER_NODE);
+
+		/* Update the remaining free space */
+		FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize + sizeof (BIOS_BUFFER_NODE);
+		FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
+		FreedNodePtr->BufferSize = AvailableHeapSize - sizeof (BIOS_BUFFER_NODE) - CurrNodePtr->BufferSize;
+		FreedNodePtr->NextNodeOffset = 0;
+
+		/* Update the offsets for Allocated and Freed nodes */
+		BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset;
+		BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset;
+	} else {
+		/* Find out whether BufferHandle has been allocated on the heap.
+		 * If it has, return AGESA_BOUNDS_CHK.
+		 */
+		CurrNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
+		CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
+
+		while (CurrNodeOffset != 0) {
+			CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
+			if (CurrNodePtr->BufferHandle == AllocParams->BufferHandle) {
+				return AGESA_BOUNDS_CHK;
+			}
+			CurrNodeOffset = CurrNodePtr->NextNodeOffset;
+			/* If BufferHandle has not been allocated on the heap, CurrNodePtr here points
+			 * to the end of the allocated nodes list.
+			 */
+		}
+		/* Find the node that best fits the requested buffer size */
+		FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
+		PrevNodeOffset = FreedNodeOffset;
+		BestFitNodeOffset = 0;
+		BestFitPrevNodeOffset = 0;
+		while (FreedNodeOffset != 0) {
+			FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
+			if (FreedNodePtr->BufferSize >= (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) {
+				if (BestFitNodeOffset == 0) {
+					/* First node that fits the requested buffer size */
+					BestFitNodeOffset = FreedNodeOffset;
+					BestFitPrevNodeOffset = PrevNodeOffset;
+				} else {
+					/* Find out whether current node is a better fit than the previous nodes */
+					BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset);
+					if (BestFitNodePtr->BufferSize > FreedNodePtr->BufferSize) {
+						BestFitNodeOffset = FreedNodeOffset;
+						BestFitPrevNodeOffset = PrevNodeOffset;
+					}
+				}
+			}
+			PrevNodeOffset = FreedNodeOffset;
+			FreedNodeOffset = FreedNodePtr->NextNodeOffset;
+		} /* end of while loop */
+
+		if (BestFitNodeOffset == 0) {
+			/* If we could not find a node that fits the requested buffer
+			 * size, return AGESA_BOUNDS_CHK.
+			 */
+			return AGESA_BOUNDS_CHK;
+		} else {
+			BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset);
+			BestFitPrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitPrevNodeOffset);
+
+			/* If BestFitNode is larger than the requested buffer, fragment the node further */
+			if (BestFitNodePtr->BufferSize > (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) {
+				NextFreeOffset = BestFitNodeOffset + AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE);
+
+				NextFreePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextFreeOffset);
+				NextFreePtr->BufferSize = BestFitNodePtr->BufferSize - (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE));
+				NextFreePtr->NextNodeOffset = BestFitNodePtr->NextNodeOffset;
+			} else {
+				/* Otherwise, next free node is NextNodeOffset of BestFitNode */
+				NextFreeOffset = BestFitNodePtr->NextNodeOffset;
+			}
+
+			/* If BestFitNode is the first buffer in the list, then update
+			 * StartOfFreedNodes to reflect the new free node.
+			 */
+			if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes) {
+				BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset;
+			} else {
+				BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset;
+			}
+
+			/* Add BestFitNode to the list of Allocated nodes */
+			CurrNodePtr->NextNodeOffset = BestFitNodeOffset;
+			BestFitNodePtr->BufferSize = AllocParams->BufferLength;
+			BestFitNodePtr->BufferHandle = AllocParams->BufferHandle;
+			BestFitNodePtr->NextNodeOffset = 0;
+
+			/* Remove BestFitNode from list of Freed nodes */
+			AllocParams->BufferPointer = (UINT8 *) BestFitNodePtr + sizeof (BIOS_BUFFER_NODE);
+		}
+	}
+
+	return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_DeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+
+	UINT8               *BiosHeapBaseAddr;
+	UINT32              AllocNodeOffset;
+	UINT32              PrevNodeOffset;
+	UINT32              NextNodeOffset;
+	UINT32              FreedNodeOffset;
+	UINT32              EndNodeOffset;
+	BIOS_BUFFER_NODE   *AllocNodePtr;
+	BIOS_BUFFER_NODE   *PrevNodePtr;
+	BIOS_BUFFER_NODE   *FreedNodePtr;
+	BIOS_BUFFER_NODE   *NextNodePtr;
+	BIOS_HEAP_MANAGER  *BiosHeapBasePtr;
+	AGESA_BUFFER_PARAMS *AllocParams;
+
+	AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
+
+	BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
+	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
+
+	/* Find target node to deallocate in list of allocated nodes.
+	 * Return AGESA_BOUNDS_CHK if the BufferHandle is not found.
+	 */
+	AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
+	AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
+	PrevNodeOffset = AllocNodeOffset;
+
+	while (AllocNodePtr->BufferHandle !=  AllocParams->BufferHandle) {
+		if (AllocNodePtr->NextNodeOffset == 0) {
+			return AGESA_BOUNDS_CHK;
+		}
+		PrevNodeOffset = AllocNodeOffset;
+		AllocNodeOffset = AllocNodePtr->NextNodeOffset;
+		AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
+	}
+
+	/* Remove target node from list of allocated nodes */
+	PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset);
+	PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
+
+	/* Zero out the buffer, and clear the BufferHandle */
+	LibAmdMemFill ((UINT8 *)AllocNodePtr + sizeof (BIOS_BUFFER_NODE), 0, AllocNodePtr->BufferSize, &(AllocParams->StdHeader));
+	AllocNodePtr->BufferHandle = 0;
+	AllocNodePtr->BufferSize += sizeof (BIOS_BUFFER_NODE);
+
+	/* Add deallocated node in order to the list of freed nodes */
+	FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
+	FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
+
+	EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize;
+
+	if (AllocNodeOffset < FreedNodeOffset) {
+		/* Add to the start of the freed list */
+		if (EndNodeOffset == FreedNodeOffset) {
+			/* If the freed node is adjacent to the first node in the list, concatenate both nodes */
+			AllocNodePtr->BufferSize += FreedNodePtr->BufferSize;
+			AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset;
+
+			/* Clear the BufferSize and NextNodeOffset of the previous first node */
+			FreedNodePtr->BufferSize = 0;
+			FreedNodePtr->NextNodeOffset = 0;
+
+		} else {
+			/* Otherwise, add freed node to the start of the list
+			 * Update NextNodeOffset and BufferSize to include the
+			 * size of BIOS_BUFFER_NODE.
+			 */
+			AllocNodePtr->NextNodeOffset = FreedNodeOffset;
+		}
+		/* Update StartOfFreedNodes to the new first node */
+		BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset;
+	} else {
+		/* Traverse list of freed nodes to find where the deallocated node
+		 * should be placed.
+		 */
+		NextNodeOffset = FreedNodeOffset;
+		NextNodePtr = FreedNodePtr;
+		while (AllocNodeOffset > NextNodeOffset) {
+			PrevNodeOffset = NextNodeOffset;
+			if (NextNodePtr->NextNodeOffset == 0) {
+				break;
+			}
+			NextNodeOffset = NextNodePtr->NextNodeOffset;
+			NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset);
+		}
+
+		/* If deallocated node is adjacent to the next node,
+		 * concatenate both nodes.
+		 */
+		if (NextNodeOffset == EndNodeOffset) {
+			NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset);
+			AllocNodePtr->BufferSize += NextNodePtr->BufferSize;
+			AllocNodePtr->NextNodeOffset = NextNodePtr->NextNodeOffset;
+
+			NextNodePtr->BufferSize = 0;
+			NextNodePtr->NextNodeOffset = 0;
+		} else {
+			/*AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; */
+			AllocNodePtr->NextNodeOffset = NextNodeOffset;
+		}
+		/* If deallocated node is adjacent to the previous node,
+		 * concatenate both nodes.
+		 */
+		PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset);
+		EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize;
+		if (AllocNodeOffset == EndNodeOffset) {
+			PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
+			PrevNodePtr->BufferSize += AllocNodePtr->BufferSize;
+
+			AllocNodePtr->BufferSize = 0;
+			AllocNodePtr->NextNodeOffset = 0;
+		} else {
+			PrevNodePtr->NextNodeOffset = AllocNodeOffset;
+		}
+	}
+	return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_LocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	UINT32              AllocNodeOffset;
+	UINT8               *BiosHeapBaseAddr;
+	BIOS_BUFFER_NODE   *AllocNodePtr;
+	BIOS_HEAP_MANAGER  *BiosHeapBasePtr;
+	AGESA_BUFFER_PARAMS *AllocParams;
+
+	AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
+
+	BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
+	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
+
+	AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
+	AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
+
+	while (AllocParams->BufferHandle != AllocNodePtr->BufferHandle) {
+		if (AllocNodePtr->NextNodeOffset == 0) {
+			AllocParams->BufferPointer = NULL;
+			AllocParams->BufferLength = 0;
+			return AGESA_BOUNDS_CHK;
+		} else {
+			AllocNodeOffset = AllocNodePtr->NextNodeOffset;
+			AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
+		}
+	}
+
+	AllocParams->BufferPointer = (UINT8 *) ((UINT8 *) AllocNodePtr + sizeof (BIOS_BUFFER_NODE));
+	AllocParams->BufferLength = AllocNodePtr->BufferSize;
+
+	return AGESA_SUCCESS;
+
+}
diff --git a/src/cpu/amd/pi/s3_resume.c b/src/cpu/amd/pi/s3_resume.c
new file mode 100644
index 0000000..fc619f7
--- /dev/null
+++ b/src/cpu/amd/pi/s3_resume.c
@@ -0,0 +1,311 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,  MA 02110-1301 USA
+ */
+
+#include <AGESA.h>
+#include <Lib/amdlib.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/car.h>
+#include <cpu/amd/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cbmem.h>
+#include <device/device.h>
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <string.h>
+#include "Porting.h"
+#include <northbridge/amd/agesa/BiosCallOuts.h>
+#include "s3_resume.h"
+
+/* The size needs to be 4k aligned, which is the sector size of most flashes. */
+#define S3_DATA_VOLATILE_SIZE		0x6000
+#define S3_DATA_MTRR_SIZE		0x1000
+#define S3_DATA_NONVOLATILE_SIZE	0x1000
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) && \
+	(S3_DATA_VOLATILE_SIZE + S3_DATA_MTRR_SIZE + S3_DATA_NONVOLATILE_SIZE) > CONFIG_S3_DATA_SIZE
+#error "Please increase the value of S3_DATA_SIZE"
+#endif
+
+static void get_s3nv_data(S3_DATA_TYPE S3DataType, u32 *pos, u32 *len)
+{
+	/* FIXME: Find file from CBFS. */
+	u32 s3_data = CONFIG_S3_DATA_POS;
+
+	switch (S3DataType) {
+	case S3DataTypeVolatile:
+		*pos = s3_data;
+		*len = S3_DATA_VOLATILE_SIZE;
+		break;
+	case S3DataTypeMTRR:
+		*pos = s3_data + S3_DATA_VOLATILE_SIZE;
+		*len = S3_DATA_MTRR_SIZE;
+		break;
+	case S3DataTypeNonVolatile:
+		*pos = s3_data + S3_DATA_VOLATILE_SIZE + S3_DATA_MTRR_SIZE;
+		*len = S3_DATA_NONVOLATILE_SIZE;
+		break;
+	default:
+		*pos = 0;
+		*len = 0;
+		break;
+	}
+}
+
+void restore_mtrr(void)
+{
+	u32 msr;
+	volatile UINT32 *msrPtr;
+	msr_t msr_data;
+
+	printk(BIOS_SPEW, "%s\n", __func__);
+
+	u32 pos, size;
+	get_s3nv_data(S3DataTypeMTRR, &pos, &size);
+	msrPtr = (UINT32 *)(pos + sizeof(UINT32));
+
+	disable_cache();
+
+	/* Enable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Now restore the Fixed MTRRs */
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(0x250, msr_data);
+
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(0x258, msr_data);
+
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(0x259, msr_data);
+
+	for (msr = 0x268; msr <= 0x26F; msr++) {
+		msr_data.lo = *msrPtr;
+		msrPtr ++;
+		msr_data.hi = *msrPtr;
+		msrPtr ++;
+		wrmsr(msr, msr_data);
+	}
+
+	/* Disable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Restore the Variable MTRRs */
+	for (msr = 0x200; msr <= 0x20F; msr++) {
+		msr_data.lo = *msrPtr;
+		msrPtr ++;
+		msr_data.hi = *msrPtr;
+		msrPtr ++;
+		wrmsr(msr, msr_data);
+	}
+
+	/* Restore SYSCFG MTRR */
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(SYS_CFG, msr_data);
+}
+
+#ifdef __PRE_RAM__
+static void *backup_resume(void)
+{
+	void *resume_backup_memory;
+
+	if (cbmem_recovery(1))
+		return NULL;
+
+	resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+	if (((u32) resume_backup_memory == 0)
+	    || ((u32) resume_backup_memory == -1)) {
+		printk(BIOS_ERR, "Error: resume_backup_memory: %x\n",
+		       (u32) resume_backup_memory);
+		for (;;) ;
+	}
+
+	return resume_backup_memory;
+}
+
+static void move_stack_high_mem(void)
+{
+	void *high_stack;
+
+	high_stack = cbmem_find(CBMEM_ID_RESUME_SCRATCH);
+	memcpy(high_stack, (void *)BSP_STACK_BASE_ADDR,
+		(CONFIG_HIGH_SCRATCH_MEMORY_SIZE - BIOS_HEAP_SIZE));
+
+	__asm__
+	    volatile ("add	%0, %%esp; add %0, %%ebp; invd"::"g"
+		      (high_stack - BSP_STACK_BASE_ADDR)
+		      :);
+}
+#endif
+
+#ifndef __PRE_RAM__
+/* FIXME: Why store MTRR in SPI, just use CBMEM ? */
+static u8 mtrr_store[S3_DATA_MTRR_SIZE];
+
+static void write_mtrr(u8 **p_nvram_pos, unsigned idx)
+{
+	msr_t  msr_data;
+	msr_data = rdmsr(idx);
+
+	memcpy(*p_nvram_pos, &msr_data, sizeof(msr_data));
+	*p_nvram_pos += sizeof(msr_data);
+}
+
+void OemAgesaSaveMtrr(void)
+{
+	msr_t  msr_data;
+	u32 i;
+
+	u8 *nvram_pos = (u8 *) mtrr_store;
+
+	/* Enable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Fixed MTRRs */
+	write_mtrr(&nvram_pos, 0x250);
+	write_mtrr(&nvram_pos, 0x258);
+	write_mtrr(&nvram_pos, 0x259);
+
+	for (i = 0x268; i < 0x270; i++)
+		write_mtrr(&nvram_pos, i);
+
+	/* Disable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Variable MTRRs */
+	for (i = 0x200; i < 0x210; i++)
+		write_mtrr(&nvram_pos, i);
+
+	/* SYS_CFG */
+	write_mtrr(&nvram_pos, 0xC0010010);
+	/* TOM */
+	write_mtrr(&nvram_pos, 0xC001001A);
+	/* TOM2 */
+	write_mtrr(&nvram_pos, 0xC001001D);
+
+#if IS_ENABLED(CONFIG_SPI_FLASH)
+	u32 pos, size;
+	get_s3nv_data(S3DataTypeMTRR, &pos, &size);
+	spi_SaveS3info(pos, size, mtrr_store, nvram_pos - (u8 *) mtrr_store);
+#endif
+}
+
+u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data)
+{
+#if IS_ENABLED(CONFIG_SPI_FLASH)
+	u32 pos, size;
+	get_s3nv_data(S3DataType, &pos, &size);
+	spi_SaveS3info(pos, size, Data, DataSize);
+#endif
+	return AGESA_SUCCESS;
+}
+#endif
+
+void OemAgesaGetS3Info(S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data)
+{
+	AMD_CONFIG_PARAMS StdHeader;
+
+	u32 pos, size;
+	get_s3nv_data(S3DataType, &pos, &size);
+
+	if (S3DataType == S3DataTypeNonVolatile) {
+		*DataSize = *(UINT32 *) pos;
+		*Data = (void *) (pos + sizeof(UINT32));
+	} else if (S3DataType == S3DataTypeVolatile) {
+		u32 len = *(UINT32 *) pos;
+		void *src = (void *) (pos + sizeof(UINT32));
+		void *dst = (void *) GetHeapBase(&StdHeader);
+		memcpy(dst, src, len);
+		*DataSize = len;
+		*Data = dst;
+	}
+}
+
+#ifdef __PRE_RAM__
+static void set_resume_cache(void)
+{
+	msr_t msr;
+
+	/* disable fixed mtrr for now,  it will be enabled by mtrr restore */
+	msr = rdmsr(SYSCFG_MSR);
+	msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn);
+	wrmsr(SYSCFG_MSR, msr);
+
+	/* Enable caching for 0 - coreboot ram using variable mtrr */
+	msr.lo = 0 | MTRR_TYPE_WRBACK;
+	msr.hi = 0;
+	wrmsr(MTRRphysBase_MSR(0), msr);
+	msr.lo = ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid;
+	msr.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
+	wrmsr(MTRRphysMask_MSR(0), msr);
+
+	/* Set the default memory type and disable fixed and enable variable MTRRs */
+	msr.hi = 0;
+	msr.lo = (1 << 11);
+	wrmsr(MTRRdefType_MSR, msr);
+
+	enable_cache();
+}
+
+void prepare_for_resume(void)
+{
+	printk(BIOS_DEBUG, "Find resume memory location\n");
+	void *resume_backup_memory = backup_resume();
+
+	post_code(0x62);
+	printk(BIOS_DEBUG, "Move CAR stack.\n");
+	move_stack_high_mem();
+	printk(BIOS_DEBUG, "stack moved to: 0x%x\n", (u32) (resume_backup_memory + HIGH_MEMORY_SAVE));
+
+	post_code(0x63);
+	disable_cache_as_ram();
+	printk(BIOS_DEBUG, "CAR disabled.\n");
+	set_resume_cache();
+
+	/*
+	 * Copy the system memory that is in the ramstage area to the
+	 * reserved area.
+	 */
+	if (resume_backup_memory)
+		memcpy(resume_backup_memory, (void *)(CONFIG_RAMBASE), HIGH_MEMORY_SAVE);
+
+	printk(BIOS_DEBUG, "System memory saved. OK to load ramstage.\n");
+}
+#endif
diff --git a/src/cpu/amd/pi/s3_resume.h b/src/cpu/amd/pi/s3_resume.h
new file mode 100644
index 0000000..14984df
--- /dev/null
+++ b/src/cpu/amd/pi/s3_resume.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,  MA 02110-1301 USA
+ */
+
+#ifndef S3_RESUME_H
+#define S3_RESUME_H
+
+typedef enum {
+	S3DataTypeNonVolatile=0,	///< NonVolatile Data Type
+	S3DataTypeVolatile,		///< Volatile Data Type
+	S3DataTypeMTRR			///< MTRR storage
+} S3_DATA_TYPE;
+
+void restore_mtrr(void);
+void prepare_for_resume(void);
+
+u32 OemAgesaSaveS3Info (S3_DATA_TYPE S3DataType, u32 DataSize, void *Data);
+void OemAgesaGetS3Info (S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data);
+void OemAgesaSaveMtrr (void);
+
+void spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len);
+
+#endif
diff --git a/src/cpu/amd/pi/spi.c b/src/cpu/amd/pi/spi.c
new file mode 100644
index 0000000..1c652fd
--- /dev/null
+++ b/src/cpu/amd/pi/spi.c
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,  MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <spi-generic.h>
+#include <spi_flash.h>
+
+#include "s3_resume.h"
+
+void spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
+{
+	struct spi_flash *flash;
+
+	spi_init();
+	flash = spi_flash_probe(0, 0);
+	if (!flash) {
+		printk(BIOS_DEBUG, "Could not find SPI device\n");
+		/* Dont make flow stop. */
+		return;
+	}
+
+	flash->spi->rw = SPI_WRITE_FLAG;
+	spi_claim_bus(flash->spi);
+
+	flash->erase(flash, pos, size);
+	flash->write(flash, pos, sizeof(len), &len);
+	flash->write(flash, pos + sizeof(len), len, buf);
+
+	flash->spi->rw = SPI_WRITE_FLAG;
+	spi_release_bus(flash->spi);
+
+	return;
+}
diff --git a/src/include/cpu/amd/car.h b/src/include/cpu/amd/car.h
index a001c93..89244c5 100644
--- a/src/include/cpu/amd/car.h
+++ b/src/include/cpu/amd/car.h
@@ -8,7 +8,7 @@ void post_cache_as_ram(void);
 void cache_as_ram_switch_stack(void *resume_backup_memory);
 void cache_as_ram_new_stack(void *resume_backup_memory);
 
-#if CONFIG_CPU_AMD_AGESA
+#if CONFIG_CPU_AMD_AGESA || CONFIG_CPU_AMD_PI
 void disable_cache_as_ram(void);
 #endif
 
diff --git a/src/mainboard/amd/olivehillplus/BiosCallOuts.c b/src/mainboard/amd/olivehillplus/BiosCallOuts.c
index 5720250..ca63719 100644
--- a/src/mainboard/amd/olivehillplus/BiosCallOuts.c
+++ b/src/mainboard/amd/olivehillplus/BiosCallOuts.c
@@ -19,7 +19,7 @@
 
 #include "AGESA.h"
 #include "amdlib.h"
-#include <northbridge/amd/agesa/BiosCallOuts.h>
+#include <northbridge/amd/pi/BiosCallOuts.h>
 #include "Ids.h"
 #include "OptionsIds.h"
 #include "heapManager.h"
diff --git a/src/mainboard/amd/olivehillplus/Kconfig b/src/mainboard/amd/olivehillplus/Kconfig
index a61859f..caa361a 100644
--- a/src/mainboard/amd/olivehillplus/Kconfig
+++ b/src/mainboard/amd/olivehillplus/Kconfig
@@ -21,8 +21,8 @@ if BOARD_AMD_OLIVEHILLPLUS
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
-	select CPU_AMD_AGESA_00730F01
-	select NORTHBRIDGE_AMD_AGESA_00730F01
+	select CPU_AMD_PI_00730F01
+	select NORTHBRIDGE_AMD_PI_00730F01
 	select SOUTHBRIDGE_AMD_AGESA_AVALON
 	select HAVE_OPTION_TABLE
 	select HAVE_PIRQ_TABLE
diff --git a/src/mainboard/amd/olivehillplus/agesawrapper.c b/src/mainboard/amd/olivehillplus/agesawrapper.c
index 45670bd..9d433db 100644
--- a/src/mainboard/amd/olivehillplus/agesawrapper.c
+++ b/src/mainboard/amd/olivehillplus/agesawrapper.c
@@ -22,7 +22,7 @@
 #include <config.h>
 #include <cpu/x86/mtrr.h>
 #include "agesawrapper.h"
-#include <northbridge/amd/agesa/BiosCallOuts.h>
+#include <northbridge/amd/pi/BiosCallOuts.h>
 #include "cpuRegisters.h"
 #include "cpuCacheInit.h"
 #include "cpuApicUtilities.h"
@@ -36,7 +36,7 @@
 #include "heapManager.h"
 #include "FchPlatform.h"
 #include "Fch.h"
-#include <cpu/amd/agesa/s3_resume.h>
+#include <cpu/amd/pi/s3_resume.h>
 #include <arch/io.h>
 #include <device/device.h>
 #include "hudson.h"
diff --git a/src/mainboard/amd/olivehillplus/devicetree.cb b/src/mainboard/amd/olivehillplus/devicetree.cb
index a00e2ba..aec71f9 100644
--- a/src/mainboard/amd/olivehillplus/devicetree.cb
+++ b/src/mainboard/amd/olivehillplus/devicetree.cb
@@ -16,18 +16,18 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 #
-chip northbridge/amd/agesa/00730F01/root_complex
+chip northbridge/amd/pi/00730F01/root_complex
 	device cpu_cluster 0 on
-		chip cpu/amd/agesa/00730F01
+		chip cpu/amd/pi/00730F01
 			device lapic 0 on  end
 		end
 	end
 
 	device domain 0 on
 		subsystemid 0x1022 0x1410 inherit
-		chip northbridge/amd/agesa/00730F01 # CPU side of HT root complex
+		chip northbridge/amd/pi/00730F01 # CPU side of HT root complex
 
-			chip northbridge/amd/agesa/00730F01 # PCI side of HT root complex
+			chip northbridge/amd/pi/00730F01 # PCI side of HT root complex
 				device pci 0.0 on  end # Root Complex
 				device pci 1.0 on  end # Internal Graphics P2P bridge 0x9804
 				device pci 1.1 on  end # Internal Multimedia
@@ -37,7 +37,7 @@ chip northbridge/amd/agesa/00730F01/root_complex
 				device pci 2.3 on  end # Realtek NIC
 				device pci 2.4 on  end # Edge Connector
 				device pci 2.5 on  end # Edge Connector
-			end	#chip northbridge/amd/agesa/00730F01
+			end	#chip northbridge/amd/pi/00730F01
 
 			chip southbridge/amd/agesa/hudson # it is under NB/SB Link, but on the same pci bus
 				device pci 10.0 on  end # XHCI HC0
@@ -70,6 +70,6 @@ chip northbridge/amd/agesa/00730F01/root_complex
 				{ {0xA0, 0xA2} }, // socket 0, channel 0, slots 0 & 1 - 8-bit SPD addresses
 			}"
 
-		end #chip northbridge/amd/agesa/00730F01 # CPU side of HT root complex
+		end #chip northbridge/amd/pi/00730F01 # CPU side of HT root complex
 	end #domain
-end #northbridge/amd/agesa/00730F01/root_complex
+end #northbridge/amd/pi/00730F01/root_complex
diff --git a/src/mainboard/amd/olivehillplus/dsdt.asl b/src/mainboard/amd/olivehillplus/dsdt.asl
index 15bcd3d..b74dac6 100644
--- a/src/mainboard/amd/olivehillplus/dsdt.asl
+++ b/src/mainboard/amd/olivehillplus/dsdt.asl
@@ -40,7 +40,7 @@ DefinitionBlock (
 	#include <southbridge/amd/agesa/hudson/acpi/pcie.asl>
 
 	/* Describe the processor tree (\_PR) */
-	#include <cpu/amd/agesa/00730F01/acpi/cpu.asl>
+	#include <cpu/amd/pi/00730F01/acpi/cpu.asl>
 
 	/* Contains the supported sleep states for this chipset */
 	#include <southbridge/amd/agesa/hudson/acpi/sleepstates.asl>
@@ -65,7 +65,7 @@ DefinitionBlock (
 
 		Device(PCI0) {
 			/* Describe the AMD Northbridge */
-			#include <northbridge/amd/agesa/00730F01/acpi/northbridge.asl>
+			#include <northbridge/amd/pi/00730F01/acpi/northbridge.asl>
 
 			/* Describe the AMD Fusion Controller Hub Southbridge */
 			#include <southbridge/amd/agesa/hudson/acpi/fch.asl>
diff --git a/src/mainboard/amd/olivehillplus/mainboard.c b/src/mainboard/amd/olivehillplus/mainboard.c
index 6073fd4..f4fbb92 100644
--- a/src/mainboard/amd/olivehillplus/mainboard.c
+++ b/src/mainboard/amd/olivehillplus/mainboard.c
@@ -23,8 +23,8 @@
 #include <arch/io.h>
 #include <device/pci_def.h>
 #include <arch/acpi.h>
-#include <northbridge/amd/agesa/BiosCallOuts.h>
-#include <cpu/amd/agesa/s3_resume.h>
+#include <northbridge/amd/pi/BiosCallOuts.h>
+#include <cpu/amd/pi/s3_resume.h>
 #include "agesawrapper.h"
 #include <cpu/x86/msr.h>
 #include <cpu/amd/mtrr.h>
diff --git a/src/mainboard/amd/olivehillplus/romstage.c b/src/mainboard/amd/olivehillplus/romstage.c
index 6f300ce..8e3cbad 100644
--- a/src/mainboard/amd/olivehillplus/romstage.c
+++ b/src/mainboard/amd/olivehillplus/romstage.c
@@ -31,11 +31,11 @@
 #include <console/loglevel.h>
 #include "cpu/amd/car.h"
 #include "agesawrapper.h"
-#include <northbridge/amd/agesa/agesawrapper_call.h>
+#include <northbridge/amd/pi/agesawrapper_call.h>
 #include "cpu/x86/bist.h"
 #include "cpu/x86/lapic.h"
 #include "southbridge/amd/agesa/hudson/hudson.h"
-#include "cpu/amd/agesa/s3_resume.h"
+#include "cpu/amd/pi/s3_resume.h"
 
 void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 {
diff --git a/src/northbridge/amd/Kconfig b/src/northbridge/amd/Kconfig
index 33e19c2..c75e82c 100644
--- a/src/northbridge/amd/Kconfig
+++ b/src/northbridge/amd/Kconfig
@@ -5,6 +5,8 @@ source src/northbridge/amd/amdfam10/Kconfig
 source src/northbridge/amd/lx/Kconfig
 source src/northbridge/amd/agesa/Kconfig
 source src/northbridge/amd/cimx/Kconfig
+source src/northbridge/amd/pi/Kconfig
+
 menu "HyperTransport setup"
 	#could be implemented for K8 (NORTHBRIDGE_AMD_AMDK8)
 	depends on (NORTHBRIDGE_AMD_AMDFAM10) && EXPERT
diff --git a/src/northbridge/amd/Makefile.inc b/src/northbridge/amd/Makefile.inc
index 7e85d08..edb4038 100644
--- a/src/northbridge/amd/Makefile.inc
+++ b/src/northbridge/amd/Makefile.inc
@@ -4,5 +4,6 @@ subdirs-$(CONFIG_NORTHBRIDGE_AMD_GX1) += gx1
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_GX2) += gx2
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_LX) += lx
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA) += agesa
+subdirs-$(CONFIG_NORTHBRIDGE_AMD_PI) += pi
 
 subdirs-$(CONFIG_AMD_NB_CIMX) += cimx
diff --git a/src/northbridge/amd/agesa/00730F01/Kconfig b/src/northbridge/amd/agesa/00730F01/Kconfig
deleted file mode 100644
index 36bc0fc..0000000
--- a/src/northbridge/amd/agesa/00730F01/Kconfig
+++ /dev/null
@@ -1,53 +0,0 @@
-##
-## This file is part of the coreboot project.
-##
-## Copyright (C) 2007-2009 coresystems GmbH
-## Copyright (C) 2014 Sage Electronic Engineering, LLC
-##
-## This program is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation; version 2 of the License.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-##
-config NORTHBRIDGE_AMD_AGESA_00730F01
-	bool
-	select MMCONF_SUPPORT
-
-if NORTHBRIDGE_AMD_AGESA_00730F01
-
-config HW_MEM_HOLE_SIZEK
-	hex
-	default 0x100000
-
-config HW_MEM_HOLE_SIZE_AUTO_INC
-	bool
-	default n
-
-config MMCONF_BASE_ADDRESS
-	hex
-	default 0xF8000000
-
-config MMCONF_BUS_NUMBER
-	int
-	default 64
-
-config VGA_BIOS_ID
-	string
-	default "1002,9850"
-	help
-	  The default VGA BIOS PCI vendor/device ID should be set to the
-	  result of the map_oprom_vendev() function in northbridge.c.
-
-config VGA_BIOS_FILE
-	string
-	default "3rdparty/northbridge/amd/00730F01/VBIOS.bin"
-
-endif
diff --git a/src/northbridge/amd/agesa/00730F01/Makefile.inc b/src/northbridge/amd/agesa/00730F01/Makefile.inc
deleted file mode 100644
index 4a75499..0000000
--- a/src/northbridge/amd/agesa/00730F01/Makefile.inc
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# This file is part of the coreboot project.
-#
-# Copyright (C) 2012 Advanced Micro Devices, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-romstage-y += dimmSpd.c
-
-ramstage-y += northbridge.c
diff --git a/src/northbridge/amd/agesa/00730F01/acpi/northbridge.asl b/src/northbridge/amd/agesa/00730F01/acpi/northbridge.asl
deleted file mode 100644
index 37aba9a..0000000
--- a/src/northbridge/amd/agesa/00730F01/acpi/northbridge.asl
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 Sage Electronic Engineering, LLC
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* Note: Only need HID on Primary Bus */
-External (TOM1)
-External (TOM2)
-Name(_HID, EISAID("PNP0A08"))	/* PCI Express Root Bridge */
-Name(_CID, EISAID("PNP0A03"))	/* PCI Root Bridge */
-Name(_ADR, 0x00180000)	/* Dev# = BSP Dev#, Func# = 0 */
-
-/* Describe the Northbridge devices */
-
-Method(_BBN, 0, NotSerialized)	/* Bus number = 0 */
-{
-	Return(Zero)
-}
-
-Method(_STA, 0, NotSerialized)
-{
-	Return(0x0B)	/* Status is visible */
-}
-
-Method(_PRT,0, NotSerialized)
-{
-	If(PMOD)
-	{
-		Return(APR0)	/* APIC mode */
-	}
-	Return (PR0)		/* PIC Mode */
-}
-
-Device(AMRT) {
-	Name(_ADR, 0x00000000)
-} /* end AMRT */
-
-/* Gpp 0 */
-Device(PBR4) {
-	Name(_ADR, 0x00020001)
-	Name(_PRW, Package() {0x18, 4})
-	Method(_PRT,0) {
-		If(PMOD){ Return(APS4) }	/* APIC mode */
-		Return (PS4)			/* PIC Mode */
-	} /* end _PRT */
-} /* end PBR4 */
-
-/* Gpp 1 */
-Device(PBR5) {
-	Name(_ADR, 0x00020002)
-	Name(_PRW, Package() {0x18, 4})
-	Method(_PRT,0) {
-		If(PMOD){ Return(APS5) }	/* APIC mode */
-		Return (PS5)			/* PIC Mode */
-	} /* end _PRT */
-} /* end PBR5 */
-
-/* Gpp 2 */
-Device(PBR6) {
-	Name(_ADR, 0x00020003)
-	Name(_PRW, Package() {0x18, 4})
-	Method(_PRT,0) {
-		If(PMOD){ Return(APS6) }	/* APIC mode */
-		Return (PS6)			/* PIC Mode */
-	} /* end _PRT */
-} /* end PBR6 */
-
-/* Gpp 3 */
-Device(PBR7) {
-	Name(_ADR, 0x00020004)
-	Name(_PRW, Package() {0x18, 4})
-	Method(_PRT,0) {
-		If(PMOD){ Return(APS7) }	/* APIC mode */
-		Return (PS7)			/* PIC Mode */
-	} /* end _PRT */
-} /* end PBR7 */
-
-/* Gpp 4 */
-Device(PBR8) {
-	Name(_ADR, 0x00020005)
-	Name(_PRW, Package() {0x18, 4})
-	Method(_PRT,0) {
-		If(PMOD){ Return(APS8) }	/* APIC mode */
-		Return (PS8)			/* PIC Mode */
-	} /* end _PRT */
-} /* end PBR8 */
diff --git a/src/northbridge/amd/agesa/00730F01/chip.h b/src/northbridge/amd/agesa/00730F01/chip.h
deleted file mode 100644
index 4b6fc2c..0000000
--- a/src/northbridge/amd/agesa/00730F01/chip.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 Sage Electronic Engineering, LLC
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _AGESA_00730F01_CHIP_H_
-#define _AGESA_00730F01_CHIP_H_
-
-struct northbridge_amd_agesa_00730F01_config
-{
-	u8 spdAddrLookup[1][1][2];
-};
-
-#endif	/* _AGESA_00730F01_CHIP_H_ */
diff --git a/src/northbridge/amd/agesa/00730F01/dimmSpd.c b/src/northbridge/amd/agesa/00730F01/dimmSpd.c
deleted file mode 100644
index 4cfbb7f..0000000
--- a/src/northbridge/amd/agesa/00730F01/dimmSpd.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <device/pci_def.h>
-#include <device/device.h>
-
-/* warning: Porting.h includes an open #pragma pack(1) */
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "chip.h"
-
-#include "northbridge/amd/agesa/dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
-	int spdAddress;
-	ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
-	ROMSTAGE_CONST struct northbridge_amd_agesa_00730F01_config *config = dev->chip_info;
-
-	if ((dev == 0) || (config == 0))
-		return AGESA_ERROR;
-
-	if (info->SocketId     >= DIMENSION(config->spdAddrLookup      ))
-		return AGESA_ERROR;
-	if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0]   ))
-		return AGESA_ERROR;
-	if (info->DimmId       >= DIMENSION(config->spdAddrLookup[0][0]))
-		return AGESA_ERROR;
-
-	spdAddress = config->spdAddrLookup
-		[info->SocketId] [info->MemChannelId] [info->DimmId];
-
-	if (spdAddress == 0)
-		return AGESA_ERROR;
-
-	int err = hudson_readSpd(spdAddress, (void *) info->Buffer, 128);
-	if (err)
-		return AGESA_ERROR;
-	return AGESA_SUCCESS;
-}
diff --git a/src/northbridge/amd/agesa/00730F01/northbridge.c b/src/northbridge/amd/agesa/00730F01/northbridge.c
deleted file mode 100644
index 2689569..0000000
--- a/src/northbridge/amd/agesa/00730F01/northbridge.c
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <console/console.h>
-#include <arch/io.h>
-#include <arch/acpi.h>
-#include <stdint.h>
-#include <device/device.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/hypertransport.h>
-#include <stdlib.h>
-#include <string.h>
-#include <lib.h>
-#include <cpu/cpu.h>
-#include <cbmem.h>
-
-#include <Porting.h>
-#include <AGESA.h>
-#include <FieldAccessors.h>
-#include <Options.h>
-#include <Topology.h>
-#include <cpu/amd/amdfam16.h>
-#include <cpuRegisters.h>
-#include "agesawrapper.h"
-#include <northbridge/amd/agesa/agesawrapper_call.h>
-#include "northbridge.h"
-
-#include <cpu/x86/lapic.h>
-#include <cpu/amd/mtrr.h>
-
-#define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
-
-#if (defined CONFIG_EXT_CONF_SUPPORT) && CONFIG_EXT_CONF_SUPPORT == 1
-#error CONFIG_EXT_CONF_SUPPORT == 1 not support anymore!
-#endif
-
-typedef struct dram_base_mask {
-	u32 base; //[47:27] at [28:8]
-	u32 mask; //[47:27] at [28:8] and enable at bit 0
-} dram_base_mask_t;
-
-static unsigned node_nums;
-static unsigned sblink;
-static device_t __f0_dev[MAX_NODE_NUMS];
-static device_t __f1_dev[MAX_NODE_NUMS];
-static device_t __f2_dev[MAX_NODE_NUMS];
-static device_t __f4_dev[MAX_NODE_NUMS];
-static unsigned fx_devs = 0;
-
-static dram_base_mask_t get_dram_base_mask(u32 nodeid)
-{
-	device_t dev;
-	dram_base_mask_t d;
-	dev = __f1_dev[0];
-	u32 temp;
-	temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16]
-	d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out  DramMask [26:24] too
-	temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
-	d.mask |= temp<<21;
-	temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16]
-	d.mask |= (temp & 1); // enable bit
-	d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too
-	temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
-	d.base |= temp<<21;
-	return d;
-}
-
-static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
-			u32 io_min, u32 io_max)
-{
-	u32 i;
-	u32 tempreg;
-	/* io range allocation */
-	tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit
-	for (i=0; i<node_nums; i++)
-		pci_write_config32(__f1_dev[i], reg+4, tempreg);
-	tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4));	      //base :ISA and VGA ?
-#if 0
-	// FIXME: can we use VGA reg instead?
-	if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
-		printk(BIOS_SPEW, "%s, enabling legacy VGA IO forwarding for %s link %s\n",
-				__func__, dev_path(dev), link);
-		tempreg |= PCI_IO_BASE_VGA_EN;
-	}
-	if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
-		tempreg |= PCI_IO_BASE_NO_ISA;
-	}
-#endif
-	for (i=0; i<node_nums; i++)
-		pci_write_config32(__f1_dev[i], reg, tempreg);
-}
-
-static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
-{
-	u32 i;
-	u32 tempreg;
-	/* io range allocation */
-	tempreg = (nodeid&0xf) | (linkn<<4) |	 (mmio_max&0xffffff00); //limit
-	for (i=0; i<nodes; i++)
-		pci_write_config32(__f1_dev[i], reg+4, tempreg);
-	tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
-	for (i=0; i<node_nums; i++)
-		pci_write_config32(__f1_dev[i], reg, tempreg);
-}
-
-static device_t get_node_pci(u32 nodeid, u32 fn)
-{
-#if MAX_NODE_NUMS + CONFIG_CDB >= 32
-	if ((CONFIG_CDB + nodeid) < 32) {
-		return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
-	} else {
-		return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn));
-	}
-#else
-	return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
-#endif
-}
-
-static void get_fx_devs(void)
-{
-	int i;
-	for (i = 0; i < MAX_NODE_NUMS; i++) {
-		__f0_dev[i] = get_node_pci(i, 0);
-		__f1_dev[i] = get_node_pci(i, 1);
-		__f2_dev[i] = get_node_pci(i, 2);
-		__f4_dev[i] = get_node_pci(i, 4);
-		if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
-			fx_devs = i+1;
-	}
-	if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
-		die("Cannot find 0:0x18.[0|1]\n");
-	}
-	printk(BIOS_DEBUG, "fx_devs=0x%x\n", fx_devs);
-}
-
-static u32 f1_read_config32(unsigned reg)
-{
-	if (fx_devs == 0)
-		get_fx_devs();
-	return pci_read_config32(__f1_dev[0], reg);
-}
-
-static void f1_write_config32(unsigned reg, u32 value)
-{
-	int i;
-	if (fx_devs == 0)
-		get_fx_devs();
-	for(i = 0; i < fx_devs; i++) {
-		device_t dev;
-		dev = __f1_dev[i];
-		if (dev && dev->enabled) {
-			pci_write_config32(dev, reg, value);
-		}
-	}
-}
-
-static u32 amdfam16_nodeid(device_t dev)
-{
-#if MAX_NODE_NUMS == 64
-	unsigned busn;
-	busn = dev->bus->secondary;
-	if (busn != CONFIG_CBB) {
-		return (dev->path.pci.devfn >> 3) - CONFIG_CDB + 32;
-	} else {
-		return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
-	}
-
-#else
-	return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
-#endif
-}
-
-static void set_vga_enable_reg(u32 nodeid, u32 linkn)
-{
-	u32 val;
-
-	val =  1 | (nodeid<<4) | (linkn<<12);
-	/* it will routing
-	 * (1)mmio 0xa0000:0xbffff
-	 * (2)io   0x3b0:0x3bb, 0x3c0:0x3df
-	 */
-	f1_write_config32(0xf4, val);
-
-}
-
-/**
- * @return
- *  @retval 2  resoure does not exist, usable
- *  @retval 0  resource exists, not usable
- *  @retval 1  resource exist, resource has been allocated before
- */
-static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
-			unsigned goal_link)
-{
-	struct resource *res;
-	unsigned nodeid, link = 0;
-	int result;
-	res = 0;
-	for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
-		device_t dev;
-		dev = __f0_dev[nodeid];
-		if (!dev)
-			continue;
-		for (link = 0; !res && (link < 8); link++) {
-			res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
-		}
-	}
-	result = 2;
-	if (res) {
-		result = 0;
-		if ((goal_link == (link - 1)) &&
-			(goal_nodeid == (nodeid - 1)) &&
-			(res->flags <= 1)) {
-			result = 1;
-		}
-	}
-	return result;
-}
-
-static struct resource *amdfam16_find_iopair(device_t dev, unsigned nodeid, unsigned link)
-{
-	struct resource *resource;
-	u32 free_reg, reg;
-	resource = 0;
-	free_reg = 0;
-	for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
-		int result;
-		result = reg_useable(reg, dev, nodeid, link);
-		if (result == 1) {
-			/* I have been allocated this one */
-			break;
-		}
-		else if (result > 1) {
-			/* I have a free register pair */
-			free_reg = reg;
-		}
-	}
-	if (reg > 0xd8) {
-		reg = free_reg; // if no free, the free_reg still be 0
-	}
-
-	resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
-
-	return resource;
-}
-
-static struct resource *amdfam16_find_mempair(device_t dev, u32 nodeid, u32 link)
-{
-	struct resource *resource;
-	u32 free_reg, reg;
-	resource = 0;
-	free_reg = 0;
-	for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
-		int result;
-		result = reg_useable(reg, dev, nodeid, link);
-		if (result == 1) {
-			/* I have been allocated this one */
-			break;
-		}
-		else if (result > 1) {
-			/* I have a free register pair */
-			free_reg = reg;
-		}
-	}
-	if (reg > 0xb8) {
-		reg = free_reg;
-	}
-
-	resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
-	return resource;
-}
-
-static void amdfam16_link_read_bases(device_t dev, u32 nodeid, u32 link)
-{
-	struct resource *resource;
-
-	/* Initialize the io space constraints on the current bus */
-	resource = amdfam16_find_iopair(dev, nodeid, link);
-	if (resource) {
-		u32 align;
-		align = log2(HT_IO_HOST_ALIGN);
-		resource->base	= 0;
-		resource->size	= 0;
-		resource->align = align;
-		resource->gran	= align;
-		resource->limit = 0xffffUL;
-		resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
-	}
-
-	/* Initialize the prefetchable memory constraints on the current bus */
-	resource = amdfam16_find_mempair(dev, nodeid, link);
-	if (resource) {
-		resource->base = 0;
-		resource->size = 0;
-		resource->align = log2(HT_MEM_HOST_ALIGN);
-		resource->gran = log2(HT_MEM_HOST_ALIGN);
-		resource->limit = 0xffffffffffULL;
-		resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-		resource->flags |= IORESOURCE_BRIDGE;
-	}
-
-	/* Initialize the memory constraints on the current bus */
-	resource = amdfam16_find_mempair(dev, nodeid, link);
-	if (resource) {
-		resource->base = 0;
-		resource->size = 0;
-		resource->align = log2(HT_MEM_HOST_ALIGN);
-		resource->gran = log2(HT_MEM_HOST_ALIGN);
-		resource->limit = 0xffffffffffULL;
-		resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
-	}
-
-}
-
-static void read_resources(device_t dev)
-{
-	u32 nodeid;
-	struct bus *link;
-
-	nodeid = amdfam16_nodeid(dev);
-	for (link = dev->link_list; link; link = link->next) {
-		if (link->children) {
-			amdfam16_link_read_bases(dev, nodeid, link->link_num);
-		}
-	}
-}
-
-static void set_resource(device_t dev, struct resource *resource, u32 nodeid)
-{
-	resource_t rbase, rend;
-	unsigned reg, link_num;
-	char buf[50];
-
-	/* Make certain the resource has actually been set */
-	if (!(resource->flags & IORESOURCE_ASSIGNED)) {
-		return;
-	}
-
-	/* If I have already stored this resource don't worry about it */
-	if (resource->flags & IORESOURCE_STORED) {
-		return;
-	}
-
-	/* Only handle PCI memory and IO resources */
-	if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
-		return;
-
-	/* Ensure I am actually looking at a resource of function 1 */
-	if ((resource->index & 0xffff) < 0x1000) {
-		return;
-	}
-	/* Get the base address */
-	rbase = resource->base;
-
-	/* Get the limit (rounded up) */
-	rend  = resource_end(resource);
-
-	/* Get the register and link */
-	reg  = resource->index & 0xfff; // 4k
-	link_num = IOINDEX_LINK(resource->index);
-
-	if (resource->flags & IORESOURCE_IO) {
-		set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
-	}
-	else if (resource->flags & IORESOURCE_MEM) {
-		set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, node_nums) ;// [39:8]
-	}
-	resource->flags |= IORESOURCE_STORED;
-	snprintf(buf, sizeof (buf), " <node %x link %x>",
-			nodeid, link_num);
-	report_resource_stored(dev, resource, buf);
-}
-
-/**
- * I tried to reuse the resource allocation code in set_resource()
- * but it is too difficult to deal with the resource allocation magic.
- */
-
-static void create_vga_resource(device_t dev, unsigned nodeid)
-{
-	struct bus *link;
-
-	/* find out which link the VGA card is connected,
-	 * we only deal with the 'first' vga card */
-	for (link = dev->link_list; link; link = link->next) {
-		if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
-#if CONFIG_MULTIPLE_VGA_ADAPTERS
-			extern device_t vga_pri; // the primary vga device, defined in device.c
-			printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
-					link->secondary,link->subordinate);
-			/* We need to make sure the vga_pri is under the link */
-			if((vga_pri->bus->secondary >= link->secondary ) &&
-					(vga_pri->bus->secondary <= link->subordinate )
-			  )
-#endif
-				break;
-		}
-	}
-
-	/* no VGA card installed */
-	if (link == NULL)
-		return;
-
-	printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, sblink);
-	set_vga_enable_reg(nodeid, sblink);
-}
-
-static void set_resources(device_t dev)
-{
-	unsigned nodeid;
-	struct bus *bus;
-	struct resource *res;
-
-	/* Find the nodeid */
-	nodeid = amdfam16_nodeid(dev);
-
-	create_vga_resource(dev, nodeid); //TODO: do we need this?
-
-	/* Set each resource we have found */
-	for (res = dev->resource_list; res; res = res->next) {
-		set_resource(dev, res, nodeid);
-	}
-
-	for (bus = dev->link_list; bus; bus = bus->next) {
-		if (bus->children) {
-			assign_resources(bus);
-		}
-	}
-}
-
-static void northbridge_init(struct device *dev)
-{
-}
-#if 0				/* TODO: Check if needed. */
-static unsigned scan_chains(device_t dev, unsigned max)
-{
-	unsigned nodeid;
-	struct bus *link;
-	device_t io_hub = NULL;
-	u32 next_unitid = 0x18;
-	nodeid = amdfam16_nodeid(dev);
-	if (nodeid == 0) {
-		for (link = dev->link_list; link; link = link->next) {
-			//if (link->link_num == sblink) { /* devicetree put IO Hub on link_lsit[sblink] */
-			if (link->link_num == 0) { /* devicetree put IO Hub on link_lsit[0] */
-				io_hub = link->children;
-				if (!io_hub || !io_hub->enabled) {
-					die("I can't find the IO Hub, or IO Hub not enabled, please check the device tree.\n");
-				}
-				/* Now that nothing is overlapping it is safe to scan the children. */
-				max = pci_scan_bus(link, 0x00, ((next_unitid - 1) << 3) | 7, 0);
-			}
-		}
-	}
-	return max;
-}
-#endif
-static struct device_operations northbridge_operations = {
-	.read_resources	  = read_resources,
-	.set_resources	  = set_resources,
-	.enable_resources = pci_dev_enable_resources,
-	.init		  = northbridge_init,
-	//.scan_bus	  = scan_chains, /* TODO: */
-	.enable		  = 0,
-	.ops_pci	  = 0,
-};
-
-static const struct pci_driver family16_northbridge __pci_driver = {
-	.ops	= &northbridge_operations,
-	.vendor = PCI_VENDOR_ID_AMD,
-	.device = PCI_DEVICE_ID_AMD_16H_MODEL_003F_NB_HT,
-};
-
-static const struct pci_driver family10_northbridge __pci_driver = {
-	.ops	= &northbridge_operations,
-	.vendor = PCI_VENDOR_ID_AMD,
-	.device = PCI_DEVICE_ID_AMD_10H_NB_HT,
-};
-
-struct chip_operations northbridge_amd_agesa_00730F01_ops = {
-	CHIP_NAME("AMD FAM16 Northbridge")
-	.enable_dev = 0,
-};
-
-static void domain_read_resources(device_t dev)
-{
-	unsigned reg;
-
-	/* Find the already assigned resource pairs */
-	get_fx_devs();
-	for (reg = 0x80; reg <= 0xd8; reg+= 0x08) {
-		u32 base, limit;
-		base  = f1_read_config32(reg);
-		limit = f1_read_config32(reg + 0x04);
-		/* Is this register allocated? */
-		if ((base & 3) != 0) {
-			unsigned nodeid, reg_link;
-			device_t reg_dev;
-			if (reg<0xc0) { // mmio
-				nodeid = (limit & 0xf) + (base&0x30);
-			} else { // io
-				nodeid =  (limit & 0xf) + ((base>>4)&0x30);
-			}
-			reg_link = (limit >> 4) & 7;
-			reg_dev = __f0_dev[nodeid];
-			if (reg_dev) {
-				/* Reserve the resource  */
-				struct resource *res;
-				res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
-				if (res) {
-					res->flags = 1;
-				}
-			}
-		}
-	}
-	/* FIXME: do we need to check extend conf space?
-	   I don't believe that much preset value */
-
-#if !CONFIG_PCI_64BIT_PREF_MEM
-	pci_domain_read_resources(dev);
-
-#else
-	struct bus *link;
-	struct resource *resource;
-	for (link=dev->link_list; link; link = link->next) {
-		/* Initialize the system wide io space constraints */
-		resource = new_resource(dev, 0|(link->link_num<<2));
-		resource->base	= 0x400;
-		resource->limit = 0xffffUL;
-		resource->flags = IORESOURCE_IO;
-
-		/* Initialize the system wide prefetchable memory resources constraints */
-		resource = new_resource(dev, 1|(link->link_num<<2));
-		resource->limit = 0xfcffffffffULL;
-		resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-
-		/* Initialize the system wide memory resources constraints */
-		resource = new_resource(dev, 2|(link->link_num<<2));
-		resource->limit = 0xfcffffffffULL;
-		resource->flags = IORESOURCE_MEM;
-	}
-#endif
-}
-
-static void domain_enable_resources(device_t dev)
-{
-	if (acpi_is_wakeup_s3())
-		AGESAWRAPPER(fchs3laterestore);
-
-	/* Must be called after PCI enumeration and resource allocation */
-	if (!acpi_is_wakeup_s3())
-		AGESAWRAPPER(amdinitmid);
-
-	printk(BIOS_DEBUG, "  ader - leaving domain_enable_resources.\n");
-}
-
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
-struct hw_mem_hole_info {
-	unsigned hole_startk;
-	int node_id;
-};
-static struct hw_mem_hole_info get_hw_mem_hole_info(void)
-{
-	struct hw_mem_hole_info mem_hole;
-	int i;
-	mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
-	mem_hole.node_id = -1;
-	for (i = 0; i < node_nums; i++) {
-		dram_base_mask_t d;
-		u32 hole;
-		d = get_dram_base_mask(i);
-		if (!(d.mask & 1)) continue; // no memory on this node
-		hole = pci_read_config32(__f1_dev[i], 0xf0);
-		if (hole & 2) { // we find the hole
-			mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
-			mem_hole.node_id = i; // record the node No with hole
-			break; // only one hole
-		}
-	}
-
-	/* We need to double check if there is special set on base reg and limit reg
-	 * are not continuous instead of hole, it will find out its hole_startk.
-	 */
-	if (mem_hole.node_id == -1) {
-		resource_t limitk_pri = 0;
-		for (i=0; i<node_nums; i++) {
-			dram_base_mask_t d;
-			resource_t base_k, limit_k;
-			d = get_dram_base_mask(i);
-			if (!(d.base & 1)) continue;
-			base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
-			if (base_k > 4 *1024 * 1024) break; // don't need to go to check
-			if (limitk_pri != base_k) { // we find the hole
-				mem_hole.hole_startk = (unsigned)limitk_pri; // must beblow 4G
-				mem_hole.node_id = i;
-				break; //only one hole
-			}
-			limit_k = ((resource_t)(((d.mask & ~1) + 0x000FF) & 0x1fffff00)) << 9;
-			limitk_pri = limit_k;
-		}
-	}
-	return mem_hole;
-}
-#endif
-
-#define ONE_MB_SHIFT  20
-#define ONE_GB_SHIFT  30
-
-static void setup_uma_memory(void)
-{
-#if CONFIG_GFXUMA
-	uint64_t topmem = bsp_topmem();
-	uint64_t topmem2 = bsp_topmem2();
-	uint32_t sysmem_mb, sysmem_gb;
-
-	/* refer to UMA_AUTO size computation in Family16h BKDG. */
-	/* Please reference MemNGetUmaSizeML() */
-	/*
-	 *     Total system memory   UMASize
-	 *     >= 6G                  1024M
-	 *     >= 4G                   512M
-	 *     >= 2G                   256M
-	 *     < 2G                    128M
-	 */
-
-	sysmem_mb = (topmem + (16ull << ONE_MB_SHIFT)) >> ONE_MB_SHIFT;   // Ignore 16MB allocated for C6 when finding UMA size
-	sysmem_mb += topmem2 ? ((topmem2 >> ONE_MB_SHIFT) - 4096) : 0;
-	sysmem_gb = sysmem_mb >> (ONE_GB_SHIFT - ONE_MB_SHIFT);
-	printk(BIOS_SPEW, "%s: system memory size %luGB, topmem2 size %lluMB, topmem size %lluMB\n", __func__, (unsigned long)sysmem_gb, (topmem2 >> ONE_MB_SHIFT), (topmem >> ONE_MB_SHIFT));
-	if (sysmem_gb >= 6) {
-		uma_memory_size = 1024 << ONE_MB_SHIFT;
-	} else if (sysmem_gb >= 4) {
-		uma_memory_size = 512 << ONE_MB_SHIFT;
-	} else if (sysmem_gb >= 2) {
-		uma_memory_size = 256 << ONE_MB_SHIFT;
-	} else {
-		uma_memory_size = 128 << ONE_MB_SHIFT;
-	}
-	uma_memory_base = topmem - uma_memory_size; /* TOP_MEM1 */
-
-	printk(BIOS_INFO, "%s: uma size 0x%08llx, memory start 0x%08llx\n",
-			__func__, uma_memory_size, uma_memory_base);
-
-	/* TODO: TOP_MEM2 */
-#endif
-}
-
-
-static void domain_set_resources(device_t dev)
-{
-#if CONFIG_PCI_64BIT_PREF_MEM
-	struct resource *io, *mem1, *mem2;
-	struct resource *res;
-#endif
-	unsigned long mmio_basek;
-	u32 pci_tolm;
-	u64 ramtop = 0;
-	int i, idx;
-	struct bus *link;
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
-	struct hw_mem_hole_info mem_hole;
-	u32 reset_memhole = 1;
-#endif
-
-#if CONFIG_PCI_64BIT_PREF_MEM
-
-	for (link = dev->link_list; link; link = link->next) {
-		/* Now reallocate the pci resources memory with the
-		 * highest addresses I can manage.
-		 */
-		mem1 = find_resource(dev, 1|(link->link_num<<2));
-		mem2 = find_resource(dev, 2|(link->link_num<<2));
-
-		printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
-				mem1->base, mem1->limit, mem1->size, mem1->align);
-		printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
-				mem2->base, mem2->limit, mem2->size, mem2->align);
-
-		/* See if both resources have roughly the same limits */
-		if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) ||
-				((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)))
-		{
-			/* If so place the one with the most stringent alignment first */
-			if (mem2->align > mem1->align) {
-				struct resource *tmp;
-				tmp = mem1;
-				mem1 = mem2;
-				mem2 = tmp;
-			}
-			/* Now place the memory as high up as it will go */
-			mem2->base = resource_max(mem2);
-			mem1->limit = mem2->base - 1;
-			mem1->base = resource_max(mem1);
-		}
-		else {
-			/* Place the resources as high up as they will go */
-			mem2->base = resource_max(mem2);
-			mem1->base = resource_max(mem1);
-		}
-
-		printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
-				mem1->base, mem1->limit, mem1->size, mem1->align);
-		printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
-				mem2->base, mem2->limit, mem2->size, mem2->align);
-	}
-
-	for (res = &dev->resource_list; res; res = res->next)
-	{
-		res->flags |= IORESOURCE_ASSIGNED;
-		res->flags |= IORESOURCE_STORED;
-		report_resource_stored(dev, res, "");
-	}
-#endif
-
-	pci_tolm = 0xffffffffUL;
-	for (link = dev->link_list; link; link = link->next) {
-		pci_tolm = find_pci_tolm(link);
-	}
-
-	// FIXME handle interleaved nodes. If you fix this here, please fix
-	// amdk8, too.
-	mmio_basek = pci_tolm >> 10;
-	/* Round mmio_basek to something the processor can support */
-	mmio_basek &= ~((1 << 6) -1);
-
-	// FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
-	// MMIO hole. If you fix this here, please fix amdk8, too.
-	/* Round the mmio hole to 64M */
-	mmio_basek &= ~((64*1024) - 1);
-
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
-	/* if the hw mem hole is already set in raminit stage, here we will compare
-	 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
-	 * use hole_basek as mmio_basek and we don't need to reset hole.
-	 * otherwise We reset the hole to the mmio_basek
-	 */
-
-	mem_hole = get_hw_mem_hole_info();
-
-	// Use hole_basek as mmio_basek, and we don't need to reset hole anymore
-	if ((mem_hole.node_id !=  -1) && (mmio_basek > mem_hole.hole_startk)) {
-		mmio_basek = mem_hole.hole_startk;
-		reset_memhole = 0;
-	}
-#endif
-
-	idx = 0x10;
-	for (i = 0; i < node_nums; i++) {
-		dram_base_mask_t d;
-		resource_t basek, limitk, sizek; // 4 1T
-
-		d = get_dram_base_mask(i);
-
-		if (!(d.mask & 1)) continue;
-		basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here
-		limitk = ((resource_t)(((d.mask & ~1) + 0x000FF) & 0x1fffff00)) << 9 ;
-
-		sizek = limitk - basek;
-
-		/* see if we need a hole from 0xa0000 to 0xbffff */
-		if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
-			ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek);
-			idx += 0x10;
-			basek = (8*64)+(16*16);
-			sizek = limitk - ((8*64)+(16*16));
-
-		}
-
-		//printk(BIOS_DEBUG, "node %d : mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", i, mmio_basek, basek, limitk);
-
-		/* split the region to accommodate pci memory space */
-		if ((basek < 4*1024*1024 ) && (limitk > mmio_basek)) {
-			if (basek <= mmio_basek) {
-				unsigned pre_sizek;
-				pre_sizek = mmio_basek - basek;
-				if (pre_sizek>0) {
-					ram_resource(dev, (idx | i), basek, pre_sizek);
-					idx += 0x10;
-					sizek -= pre_sizek;
-					if (!ramtop)
-						ramtop = mmio_basek * 1024;
-				}
-				basek = mmio_basek;
-			}
-			if ((basek + sizek) <= 4*1024*1024) {
-				sizek = 0;
-			}
-			else {
-				uint64_t topmem2 = bsp_topmem2();
-				basek = 4*1024*1024;
-				sizek = topmem2/1024 - basek;
-			}
-		}
-
-		ram_resource(dev, (idx | i), basek, sizek);
-		idx += 0x10;
-		printk(BIOS_DEBUG, "node %d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
-				i, mmio_basek, basek, limitk);
-		if (!ramtop)
-			ramtop = limitk * 1024;
-	}
-
-#if CONFIG_GFXUMA
-	set_top_of_ram(uma_memory_base);
-	uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10);
-#else
-	set_top_of_ram(ramtop);
-#endif
-
-	for(link = dev->link_list; link; link = link->next) {
-		if (link->children) {
-			assign_resources(link);
-		}
-	}
-}
-
-static struct device_operations pci_domain_ops = {
-	.read_resources	  = domain_read_resources,
-	.set_resources	  = domain_set_resources,
-	.enable_resources = domain_enable_resources,
-	.init		  = NULL,
-	.scan_bus	  = pci_domain_scan_bus,
-	.ops_pci_bus	  = pci_bus_default_ops,
-};
-
-static void sysconf_init(device_t dev) // first node
-{
-	sblink = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1
-	node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0]
-}
-
-static void add_more_links(device_t dev, unsigned total_links)
-{
-	struct bus *link, *last = NULL;
-	int link_num;
-
-	for (link = dev->link_list; link; link = link->next)
-		last = link;
-
-	if (last) {
-		int links = total_links - last->link_num;
-		link_num = last->link_num;
-		if (links > 0) {
-			link = malloc(links*sizeof(*link));
-			if (!link)
-				die("Couldn't allocate more links!\n");
-			memset(link, 0, links*sizeof(*link));
-			last->next = link;
-		}
-	}
-	else {
-		link_num = -1;
-		link = malloc(total_links*sizeof(*link));
-		memset(link, 0, total_links*sizeof(*link));
-		dev->link_list = link;
-	}
-
-	for (link_num = link_num + 1; link_num < total_links; link_num++) {
-		link->link_num = link_num;
-		link->dev = dev;
-		link->next = link + 1;
-		last = link;
-		link = link->next;
-	}
-	last->next = NULL;
-}
-
-static u32 cpu_bus_scan(device_t dev, u32 max)
-{
-	struct bus *cpu_bus;
-	device_t dev_mc;
-#if CONFIG_CBB
-	device_t pci_domain;
-#endif
-	int i,j;
-	int coreid_bits;
-	int core_max = 0;
-	unsigned ApicIdCoreIdSize;
-	unsigned core_nums;
-	int siblings = 0;
-	unsigned int family;
-	u32 modules = 0;
-	VOID* modules_ptr = &modules;
-	BUILD_OPT_CFG* options = NULL;
-	int ioapic_count = 0;
-
-	// TODO Remove the printk's.
-	printk(BIOS_SPEW, "MullinsPI Debug: Grabbing the AMD Topology Information.\n");
-	AmdGetValue(AMD_GLOBAL_USER_OPTIONS, (VOID**)&options, sizeof(options));
-	AmdGetValue(AMD_GLOBAL_NUM_MODULES, &modules_ptr, sizeof(modules));
-	modules = (*(u32*)modules_ptr) && ((1ull << (sizeof(modules) * 8)) - 1);
-	ASSERT(modules > 0);
-	ASSERT(options);
-	ioapic_count = (int)options->CfgPlatNumIoApics;
-	ASSERT(ioapic_count > 0);
-	printk(BIOS_SPEW, "MullinsPI Debug: AMD Topology Number of Modules (@0x%p) is %d\n", modules_ptr, modules);
-	printk(BIOS_SPEW, "MullinsPI Debug: AMD Topology Number of IOAPICs (@0x%p) is %d\n", options, (int)options->CfgPlatNumIoApics);
-
-#if CONFIG_CBB
-	dev_mc = dev_find_slot(0, PCI_DEVFN(CONFIG_CDB, 0)); //0x00
-	if (dev_mc && dev_mc->bus) {
-		printk(BIOS_DEBUG, "%s found", dev_path(dev_mc));
-		pci_domain = dev_mc->bus->dev;
-		if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
-			printk(BIOS_DEBUG, "\n%s move to ",dev_path(dev_mc));
-			dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
-			printk(BIOS_DEBUG, "%s",dev_path(dev_mc));
-		} else {
-			printk(BIOS_DEBUG, " but it is not under pci_domain directly ");
-		}
-		printk(BIOS_DEBUG, "\n");
-	}
-	dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
-	if (!dev_mc) {
-		dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0));
-		if (dev_mc && dev_mc->bus) {
-			printk(BIOS_DEBUG, "%s found\n", dev_path(dev_mc));
-			pci_domain = dev_mc->bus->dev;
-			if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
-				if ((pci_domain->link_list) && (pci_domain->link_list->children == dev_mc)) {
-					printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
-					dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
-					printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
-					while (dev_mc) {
-						printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
-						dev_mc->path.pci.devfn -= PCI_DEVFN(0x18,0);
-						printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
-						dev_mc = dev_mc->sibling;
-					}
-				}
-			}
-		}
-	}
-#endif
-	dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
-	if (!dev_mc) {
-		printk(BIOS_ERR, "%02x:%02x.0 not found", CONFIG_CBB, CONFIG_CDB);
-		die("");
-	}
-	sysconf_init(dev_mc);
-#if CONFIG_CBB && (MAX_NODE_NUMS > 32)
-	if (node_nums>32) { // need to put node 32 to node 63 to bus 0xfe
-		if (pci_domain->link_list && !pci_domain->link_list->next) {
-			struct bus *new_link = new_link(pci_domain);
-			pci_domain->link_list->next = new_link;
-			new_link->link_num = 1;
-			new_link->dev = pci_domain;
-			new_link->children = 0;
-			printk(BIOS_DEBUG, "%s links now 2\n", dev_path(pci_domain));
-		}
-		pci_domain->link_list->next->secondary = CONFIG_CBB - 1;
-	}
-#endif
-
-	/* Get Max Number of cores(MNC) */
-	coreid_bits = (cpuid_ecx(AMD_CPUID_ASIZE_PCCOUNT) & 0x0000F000) >> 12;
-	core_max = 1 << (coreid_bits & 0x000F); //mnc
-
-	ApicIdCoreIdSize = ((cpuid_ecx(0x80000008)>>12) & 0xF);
-	if (ApicIdCoreIdSize) {
-		core_nums = (1 << ApicIdCoreIdSize) - 1;
-	} else {
-		core_nums = 3; //quad core
-	}
-
-	/* Find which cpus are present */
-	cpu_bus = dev->link_list;
-	for (i = 0; i < node_nums; i++) {
-		device_t cdb_dev;
-		unsigned busn, devn;
-		struct bus *pbus;
-
-		busn = CONFIG_CBB;
-		devn = CONFIG_CDB + i;
-		pbus = dev_mc->bus;
-#if CONFIG_CBB && (MAX_NODE_NUMS > 32)
-		if (i >= 32) {
-			busn--;
-			devn -= 32;
-			pbus = pci_domain->link_list->next;
-		}
-#endif
-
-		/* Find the cpu's pci device */
-		cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
-		if (!cdb_dev) {
-			/* If I am probing things in a weird order
-			 * ensure all of the cpu's pci devices are found.
-			 */
-			int fn;
-			for(fn = 0; fn <= 5; fn++) { //FBDIMM?
-				cdb_dev = pci_probe_dev(NULL, pbus,
-							PCI_DEVFN(devn, fn));
-			}
-			cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
-		} else {
-			/* Ok, We need to set the links for that device.
-			 * otherwise the device under it will not be scanned
-			 */
-			int linknum;
-#if CONFIG_HT3_SUPPORT
-			linknum = 8;
-#else
-			linknum = 4;
-#endif
-			add_more_links(cdb_dev, linknum);
-		}
-
-		family = cpuid_eax(1);
-		family = (family >> 20) & 0xFF;
-		if (family == 1) { //f10
-			u32 dword;
-			cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
-			dword = pci_read_config32(cdb_dev, 0xe8);
-			siblings = ((dword & BIT15) >> 13) | ((dword & (BIT13 | BIT12)) >> 12);
-		} else if (family == 7) {//f16
-			cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 5));
-			if (cdb_dev && cdb_dev->enabled) {
-				siblings = pci_read_config32(cdb_dev, 0x84);
-				siblings &= 0xFF;
-			}
-		} else {
-			siblings = 0; //default one core
-		}
-		int enable_node = cdb_dev && cdb_dev->enabled;
-		printk(BIOS_SPEW, "%s family%xh, core_max=0x%x, core_nums=0x%x, siblings=0x%x\n",
-				dev_path(cdb_dev), 0x0f + family, core_max, core_nums, siblings);
-
-		for (j = 0; j <= siblings; j++ ) {
-			u32 lapicid_start = 0;
-
-			/*
-			 * APIC ID calucation is tightly coupled with AGESA v5 code.
-			 * This calculation MUST match the assignment calculation done
-			 * in LocalApicInitializationAtEarly() function.
-			 * And reference GetLocalApicIdForCore()
-			 *
-			 * Apply apic enumeration rules
-			 * For systems with >= 16 APICs, put the IO-APICs at 0..n and
-			 * put the local-APICs at m..z
-			 *
-			 * This is needed because many IO-APIC devices only have 4 bits
-			 * for their APIC id and therefore must reside at 0..15
-                         */
-			if ((node_nums * core_max) + ioapic_count >= 0x10) {
-				lapicid_start = (ioapic_count - 1) / core_max;
-				lapicid_start = (lapicid_start + 1) * core_max;
-				printk(BIOS_SPEW, "lpaicid_start=0x%x ", lapicid_start);
-			}
-			u32 apic_id = (lapicid_start * (i/modules + 1)) + ((i % modules) ? (j + (siblings + 1)) : j);
-			printk(BIOS_SPEW, "node 0x%x core 0x%x apicid=0x%x\n",
-					i, j, apic_id);
-
-			device_t cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
-			if (cpu)
-				amd_cpu_topology(cpu, i, j);
-		} //j
-	}
-	return max;
-}
-
-static void cpu_bus_init(device_t dev)
-{
-	initialize_cpus(dev->link_list);
-}
-
-static void cpu_bus_noop(device_t dev)
-{
-}
-
-static void cpu_bus_read_resources(device_t dev)
-{
-#if CONFIG_MMCONF_SUPPORT
-	struct resource *resource = new_resource(dev, 0xc0010058);
-	resource->base = CONFIG_MMCONF_BASE_ADDRESS;
-	resource->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256;
-	resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
-		IORESOURCE_FIXED | IORESOURCE_STORED |  IORESOURCE_ASSIGNED;
-#endif
-}
-
-static void cpu_bus_set_resources(device_t dev)
-{
-	struct resource *resource = find_resource(dev, 0xc0010058);
-	if (resource) {
-		report_resource_stored(dev, resource, " <mmconfig>");
-	}
-	pci_dev_set_resources(dev);
-}
-
-static struct device_operations cpu_bus_ops = {
-	.read_resources	  = cpu_bus_read_resources,
-	.set_resources	  = cpu_bus_set_resources,
-	.enable_resources = cpu_bus_noop,
-	.init		  = cpu_bus_init,
-	.scan_bus	  = cpu_bus_scan,
-};
-
-static void root_complex_enable_dev(struct device *dev)
-{
-	static int done = 0;
-
-	/* Do not delay UMA setup, as a device on the PCI bus may evaluate
-	   the global uma_memory variables already in its enable function. */
-	if (!done) {
-		setup_bsp_ramtop();
-		setup_uma_memory();
-		done = 1;
-	}
-
-	/* Set the operations if it is a special bus type */
-	if (dev->path.type == DEVICE_PATH_DOMAIN) {
-		dev->ops = &pci_domain_ops;
-	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
-		dev->ops = &cpu_bus_ops;
-	}
-}
-
-struct chip_operations northbridge_amd_agesa_00730F01_root_complex_ops = {
-	CHIP_NAME("AMD FAM16 Root Complex")
-	.enable_dev = root_complex_enable_dev,
-};
-
-/*********************************************************************
- * Change the vendor / device IDs to match the generic VBIOS header. *
- *********************************************************************/
-u32 map_oprom_vendev(u32 vendev)
-{
-	u32 new_vendev;
-	new_vendev =
-		((0x10029850 <= vendev) && (vendev <= 0x1002986F)) ? 0x10029850 : vendev;
-
-	if (vendev != new_vendev)
-		printk(BIOS_NOTICE, "Mapping PCI device %8x to %8x\n", vendev, new_vendev);
-
-	return new_vendev;
-}
diff --git a/src/northbridge/amd/agesa/00730F01/northbridge.h b/src/northbridge/amd/agesa/00730F01/northbridge.h
deleted file mode 100644
index 6fa8164..0000000
--- a/src/northbridge/amd/agesa/00730F01/northbridge.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef NORTHBRIDGE_AMD_AGESA_FAM16H_H
-#define NORTHBRIDGE_AMD_AGESA_FAM16H_H
-
-static struct device_operations pci_domain_ops;
-static struct device_operations cpu_bus_ops;
-
-#endif /* NORTHBRIDGE_AMD_AGESA_FAM16H_H */
diff --git a/src/northbridge/amd/agesa/BiosCallOuts.h b/src/northbridge/amd/agesa/BiosCallOuts.h
index 60299b7..feabf98 100644
--- a/src/northbridge/amd/agesa/BiosCallOuts.h
+++ b/src/northbridge/amd/agesa/BiosCallOuts.h
@@ -24,7 +24,7 @@
 #include "Porting.h"
 #include "AGESA.h"
 
-#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB || CONFIG_NORTHBRIDGE_AMD_AGESA_00730F01
+#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
 
 #define BIOS_HEAP_START_ADDRESS 	0x010000000
 #define BIOS_HEAP_SIZE			0x30000
diff --git a/src/northbridge/amd/agesa/Kconfig b/src/northbridge/amd/agesa/Kconfig
index 6caff0f..d5c039f 100644
--- a/src/northbridge/amd/agesa/Kconfig
+++ b/src/northbridge/amd/agesa/Kconfig
@@ -37,6 +37,5 @@ source src/northbridge/amd/agesa/family14/Kconfig
 source src/northbridge/amd/agesa/family15/Kconfig
 source src/northbridge/amd/agesa/family15tn/Kconfig
 source src/northbridge/amd/agesa/family16kb/Kconfig
-source src/northbridge/amd/agesa/00730F01/Kconfig
 
 endif # NORTHBRIDGE_AMD_AGESA
diff --git a/src/northbridge/amd/agesa/Makefile.inc b/src/northbridge/amd/agesa/Makefile.inc
index f1be023..8f10664 100644
--- a/src/northbridge/amd/agesa/Makefile.inc
+++ b/src/northbridge/amd/agesa/Makefile.inc
@@ -22,7 +22,6 @@ subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY14) += family14
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15) += family15
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN) += family15tn
 subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB) += family16kb
-subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_00730F01) += 00730F01
 
 romstage-y += def_callouts.c
 ramstage-y += def_callouts.c
diff --git a/src/northbridge/amd/agesa/def_callouts.c b/src/northbridge/amd/agesa/def_callouts.c
index ee79be2..5d1b2be 100644
--- a/src/northbridge/amd/agesa/def_callouts.c
+++ b/src/northbridge/amd/agesa/def_callouts.c
@@ -104,7 +104,7 @@ AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 	return Status;
 }
 
-#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB || CONFIG_NORTHBRIDGE_AMD_AGESA_00730F01
+#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
 /* FIXME: we would like GFX disable for fam14 too for headless systems. */
 AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
 {
diff --git a/src/northbridge/amd/pi/00730F01/Kconfig b/src/northbridge/amd/pi/00730F01/Kconfig
new file mode 100644
index 0000000..c053111
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/Kconfig
@@ -0,0 +1,53 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 coresystems GmbH
+## Copyright (C) 2014 Sage Electronic Engineering, LLC
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+config NORTHBRIDGE_AMD_PI_00730F01
+	bool
+	select MMCONF_SUPPORT
+
+if NORTHBRIDGE_AMD_PI_00730F01
+
+config HW_MEM_HOLE_SIZEK
+	hex
+	default 0x100000
+
+config HW_MEM_HOLE_SIZE_AUTO_INC
+	bool
+	default n
+
+config MMCONF_BASE_ADDRESS
+	hex
+	default 0xF8000000
+
+config MMCONF_BUS_NUMBER
+	int
+	default 64
+
+config VGA_BIOS_ID
+	string
+	default "1002,9850"
+	help
+	  The default VGA BIOS PCI vendor/device ID should be set to the
+	  result of the map_oprom_vendev() function in northbridge.c.
+
+config VGA_BIOS_FILE
+	string
+	default "3rdparty/northbridge/amd/00730F01/VBIOS.bin"
+
+endif
diff --git a/src/northbridge/amd/pi/00730F01/Makefile.inc b/src/northbridge/amd/pi/00730F01/Makefile.inc
new file mode 100644
index 0000000..4a75499
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/Makefile.inc
@@ -0,0 +1,22 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+romstage-y += dimmSpd.c
+
+ramstage-y += northbridge.c
diff --git a/src/northbridge/amd/pi/00730F01/acpi/northbridge.asl b/src/northbridge/amd/pi/00730F01/acpi/northbridge.asl
new file mode 100644
index 0000000..37aba9a
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/acpi/northbridge.asl
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Note: Only need HID on Primary Bus */
+External (TOM1)
+External (TOM2)
+Name(_HID, EISAID("PNP0A08"))	/* PCI Express Root Bridge */
+Name(_CID, EISAID("PNP0A03"))	/* PCI Root Bridge */
+Name(_ADR, 0x00180000)	/* Dev# = BSP Dev#, Func# = 0 */
+
+/* Describe the Northbridge devices */
+
+Method(_BBN, 0, NotSerialized)	/* Bus number = 0 */
+{
+	Return(Zero)
+}
+
+Method(_STA, 0, NotSerialized)
+{
+	Return(0x0B)	/* Status is visible */
+}
+
+Method(_PRT,0, NotSerialized)
+{
+	If(PMOD)
+	{
+		Return(APR0)	/* APIC mode */
+	}
+	Return (PR0)		/* PIC Mode */
+}
+
+Device(AMRT) {
+	Name(_ADR, 0x00000000)
+} /* end AMRT */
+
+/* Gpp 0 */
+Device(PBR4) {
+	Name(_ADR, 0x00020001)
+	Name(_PRW, Package() {0x18, 4})
+	Method(_PRT,0) {
+		If(PMOD){ Return(APS4) }	/* APIC mode */
+		Return (PS4)			/* PIC Mode */
+	} /* end _PRT */
+} /* end PBR4 */
+
+/* Gpp 1 */
+Device(PBR5) {
+	Name(_ADR, 0x00020002)
+	Name(_PRW, Package() {0x18, 4})
+	Method(_PRT,0) {
+		If(PMOD){ Return(APS5) }	/* APIC mode */
+		Return (PS5)			/* PIC Mode */
+	} /* end _PRT */
+} /* end PBR5 */
+
+/* Gpp 2 */
+Device(PBR6) {
+	Name(_ADR, 0x00020003)
+	Name(_PRW, Package() {0x18, 4})
+	Method(_PRT,0) {
+		If(PMOD){ Return(APS6) }	/* APIC mode */
+		Return (PS6)			/* PIC Mode */
+	} /* end _PRT */
+} /* end PBR6 */
+
+/* Gpp 3 */
+Device(PBR7) {
+	Name(_ADR, 0x00020004)
+	Name(_PRW, Package() {0x18, 4})
+	Method(_PRT,0) {
+		If(PMOD){ Return(APS7) }	/* APIC mode */
+		Return (PS7)			/* PIC Mode */
+	} /* end _PRT */
+} /* end PBR7 */
+
+/* Gpp 4 */
+Device(PBR8) {
+	Name(_ADR, 0x00020005)
+	Name(_PRW, Package() {0x18, 4})
+	Method(_PRT,0) {
+		If(PMOD){ Return(APS8) }	/* APIC mode */
+		Return (PS8)			/* PIC Mode */
+	} /* end _PRT */
+} /* end PBR8 */
diff --git a/src/northbridge/amd/pi/00730F01/chip.h b/src/northbridge/amd/pi/00730F01/chip.h
new file mode 100644
index 0000000..aa08cff
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/chip.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _PI_00730F01_CHIP_H_
+#define _PI_00730F01_CHIP_H_
+
+struct northbridge_amd_pi_00730F01_config
+{
+	u8 spdAddrLookup[1][1][2];
+};
+
+#endif	/* _PI_00730F01_CHIP_H_ */
diff --git a/src/northbridge/amd/pi/00730F01/dimmSpd.c b/src/northbridge/amd/pi/00730F01/dimmSpd.c
new file mode 100644
index 0000000..45a1b50
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/dimmSpd.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/pci_def.h>
+#include <device/device.h>
+
+/* warning: Porting.h includes an open #pragma pack(1) */
+#include "Porting.h"
+#include "AGESA.h"
+#include "amdlib.h"
+#include "chip.h"
+
+#include "northbridge/amd/agesa/dimmSpd.h"
+
+#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
+
+AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
+{
+	int spdAddress;
+	ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+	ROMSTAGE_CONST struct northbridge_amd_pi_00730F01_config *config = dev->chip_info;
+
+	if ((dev == 0) || (config == 0))
+		return AGESA_ERROR;
+
+	if (info->SocketId     >= DIMENSION(config->spdAddrLookup      ))
+		return AGESA_ERROR;
+	if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0]   ))
+		return AGESA_ERROR;
+	if (info->DimmId       >= DIMENSION(config->spdAddrLookup[0][0]))
+		return AGESA_ERROR;
+
+	spdAddress = config->spdAddrLookup
+		[info->SocketId] [info->MemChannelId] [info->DimmId];
+
+	if (spdAddress == 0)
+		return AGESA_ERROR;
+
+	int err = hudson_readSpd(spdAddress, (void *) info->Buffer, 128);
+	if (err)
+		return AGESA_ERROR;
+	return AGESA_SUCCESS;
+}
diff --git a/src/northbridge/amd/pi/00730F01/northbridge.c b/src/northbridge/amd/pi/00730F01/northbridge.c
new file mode 100644
index 0000000..bfef6c3
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/northbridge.c
@@ -0,0 +1,1154 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/hypertransport.h>
+#include <stdlib.h>
+#include <string.h>
+#include <lib.h>
+#include <cpu/cpu.h>
+#include <cbmem.h>
+
+#include <Porting.h>
+#include <AGESA.h>
+#include <FieldAccessors.h>
+#include <Options.h>
+#include <Topology.h>
+#include <cpu/amd/amdfam16.h>
+#include <cpuRegisters.h>
+#include "agesawrapper.h"
+#include <northbridge/amd/pi/agesawrapper_call.h>
+#include "northbridge.h"
+
+#include <cpu/x86/lapic.h>
+#include <cpu/amd/mtrr.h>
+
+#define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
+
+#if (defined CONFIG_EXT_CONF_SUPPORT) && CONFIG_EXT_CONF_SUPPORT == 1
+#error CONFIG_EXT_CONF_SUPPORT == 1 not support anymore!
+#endif
+
+typedef struct dram_base_mask {
+	u32 base; //[47:27] at [28:8]
+	u32 mask; //[47:27] at [28:8] and enable at bit 0
+} dram_base_mask_t;
+
+static unsigned node_nums;
+static unsigned sblink;
+static device_t __f0_dev[MAX_NODE_NUMS];
+static device_t __f1_dev[MAX_NODE_NUMS];
+static device_t __f2_dev[MAX_NODE_NUMS];
+static device_t __f4_dev[MAX_NODE_NUMS];
+static unsigned fx_devs = 0;
+
+static dram_base_mask_t get_dram_base_mask(u32 nodeid)
+{
+	device_t dev;
+	dram_base_mask_t d;
+	dev = __f1_dev[0];
+	u32 temp;
+	temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16]
+	d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out  DramMask [26:24] too
+	temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
+	d.mask |= temp<<21;
+	temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16]
+	d.mask |= (temp & 1); // enable bit
+	d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too
+	temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
+	d.base |= temp<<21;
+	return d;
+}
+
+static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
+			u32 io_min, u32 io_max)
+{
+	u32 i;
+	u32 tempreg;
+	/* io range allocation */
+	tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit
+	for (i=0; i<node_nums; i++)
+		pci_write_config32(__f1_dev[i], reg+4, tempreg);
+	tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4));	      //base :ISA and VGA ?
+#if 0
+	// FIXME: can we use VGA reg instead?
+	if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+		printk(BIOS_SPEW, "%s, enabling legacy VGA IO forwarding for %s link %s\n",
+				__func__, dev_path(dev), link);
+		tempreg |= PCI_IO_BASE_VGA_EN;
+	}
+	if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
+		tempreg |= PCI_IO_BASE_NO_ISA;
+	}
+#endif
+	for (i=0; i<node_nums; i++)
+		pci_write_config32(__f1_dev[i], reg, tempreg);
+}
+
+static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
+{
+	u32 i;
+	u32 tempreg;
+	/* io range allocation */
+	tempreg = (nodeid&0xf) | (linkn<<4) |	 (mmio_max&0xffffff00); //limit
+	for (i=0; i<nodes; i++)
+		pci_write_config32(__f1_dev[i], reg+4, tempreg);
+	tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
+	for (i=0; i<node_nums; i++)
+		pci_write_config32(__f1_dev[i], reg, tempreg);
+}
+
+static device_t get_node_pci(u32 nodeid, u32 fn)
+{
+#if MAX_NODE_NUMS + CONFIG_CDB >= 32
+	if ((CONFIG_CDB + nodeid) < 32) {
+		return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
+	} else {
+		return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn));
+	}
+#else
+	return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
+#endif
+}
+
+static void get_fx_devs(void)
+{
+	int i;
+	for (i = 0; i < MAX_NODE_NUMS; i++) {
+		__f0_dev[i] = get_node_pci(i, 0);
+		__f1_dev[i] = get_node_pci(i, 1);
+		__f2_dev[i] = get_node_pci(i, 2);
+		__f4_dev[i] = get_node_pci(i, 4);
+		if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
+			fx_devs = i+1;
+	}
+	if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
+		die("Cannot find 0:0x18.[0|1]\n");
+	}
+	printk(BIOS_DEBUG, "fx_devs=0x%x\n", fx_devs);
+}
+
+static u32 f1_read_config32(unsigned reg)
+{
+	if (fx_devs == 0)
+		get_fx_devs();
+	return pci_read_config32(__f1_dev[0], reg);
+}
+
+static void f1_write_config32(unsigned reg, u32 value)
+{
+	int i;
+	if (fx_devs == 0)
+		get_fx_devs();
+	for(i = 0; i < fx_devs; i++) {
+		device_t dev;
+		dev = __f1_dev[i];
+		if (dev && dev->enabled) {
+			pci_write_config32(dev, reg, value);
+		}
+	}
+}
+
+static u32 amdfam16_nodeid(device_t dev)
+{
+#if MAX_NODE_NUMS == 64
+	unsigned busn;
+	busn = dev->bus->secondary;
+	if (busn != CONFIG_CBB) {
+		return (dev->path.pci.devfn >> 3) - CONFIG_CDB + 32;
+	} else {
+		return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
+	}
+
+#else
+	return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
+#endif
+}
+
+static void set_vga_enable_reg(u32 nodeid, u32 linkn)
+{
+	u32 val;
+
+	val =  1 | (nodeid<<4) | (linkn<<12);
+	/* it will routing
+	 * (1)mmio 0xa0000:0xbffff
+	 * (2)io   0x3b0:0x3bb, 0x3c0:0x3df
+	 */
+	f1_write_config32(0xf4, val);
+
+}
+
+/**
+ * @return
+ *  @retval 2  resoure does not exist, usable
+ *  @retval 0  resource exists, not usable
+ *  @retval 1  resource exist, resource has been allocated before
+ */
+static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
+			unsigned goal_link)
+{
+	struct resource *res;
+	unsigned nodeid, link = 0;
+	int result;
+	res = 0;
+	for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
+		device_t dev;
+		dev = __f0_dev[nodeid];
+		if (!dev)
+			continue;
+		for (link = 0; !res && (link < 8); link++) {
+			res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
+		}
+	}
+	result = 2;
+	if (res) {
+		result = 0;
+		if ((goal_link == (link - 1)) &&
+			(goal_nodeid == (nodeid - 1)) &&
+			(res->flags <= 1)) {
+			result = 1;
+		}
+	}
+	return result;
+}
+
+static struct resource *amdfam16_find_iopair(device_t dev, unsigned nodeid, unsigned link)
+{
+	struct resource *resource;
+	u32 free_reg, reg;
+	resource = 0;
+	free_reg = 0;
+	for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
+		int result;
+		result = reg_useable(reg, dev, nodeid, link);
+		if (result == 1) {
+			/* I have been allocated this one */
+			break;
+		}
+		else if (result > 1) {
+			/* I have a free register pair */
+			free_reg = reg;
+		}
+	}
+	if (reg > 0xd8) {
+		reg = free_reg; // if no free, the free_reg still be 0
+	}
+
+	resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
+
+	return resource;
+}
+
+static struct resource *amdfam16_find_mempair(device_t dev, u32 nodeid, u32 link)
+{
+	struct resource *resource;
+	u32 free_reg, reg;
+	resource = 0;
+	free_reg = 0;
+	for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
+		int result;
+		result = reg_useable(reg, dev, nodeid, link);
+		if (result == 1) {
+			/* I have been allocated this one */
+			break;
+		}
+		else if (result > 1) {
+			/* I have a free register pair */
+			free_reg = reg;
+		}
+	}
+	if (reg > 0xb8) {
+		reg = free_reg;
+	}
+
+	resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
+	return resource;
+}
+
+static void amdfam16_link_read_bases(device_t dev, u32 nodeid, u32 link)
+{
+	struct resource *resource;
+
+	/* Initialize the io space constraints on the current bus */
+	resource = amdfam16_find_iopair(dev, nodeid, link);
+	if (resource) {
+		u32 align;
+		align = log2(HT_IO_HOST_ALIGN);
+		resource->base	= 0;
+		resource->size	= 0;
+		resource->align = align;
+		resource->gran	= align;
+		resource->limit = 0xffffUL;
+		resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
+	}
+
+	/* Initialize the prefetchable memory constraints on the current bus */
+	resource = amdfam16_find_mempair(dev, nodeid, link);
+	if (resource) {
+		resource->base = 0;
+		resource->size = 0;
+		resource->align = log2(HT_MEM_HOST_ALIGN);
+		resource->gran = log2(HT_MEM_HOST_ALIGN);
+		resource->limit = 0xffffffffffULL;
+		resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		resource->flags |= IORESOURCE_BRIDGE;
+	}
+
+	/* Initialize the memory constraints on the current bus */
+	resource = amdfam16_find_mempair(dev, nodeid, link);
+	if (resource) {
+		resource->base = 0;
+		resource->size = 0;
+		resource->align = log2(HT_MEM_HOST_ALIGN);
+		resource->gran = log2(HT_MEM_HOST_ALIGN);
+		resource->limit = 0xffffffffffULL;
+		resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
+	}
+
+}
+
+static void read_resources(device_t dev)
+{
+	u32 nodeid;
+	struct bus *link;
+
+	nodeid = amdfam16_nodeid(dev);
+	for (link = dev->link_list; link; link = link->next) {
+		if (link->children) {
+			amdfam16_link_read_bases(dev, nodeid, link->link_num);
+		}
+	}
+}
+
+static void set_resource(device_t dev, struct resource *resource, u32 nodeid)
+{
+	resource_t rbase, rend;
+	unsigned reg, link_num;
+	char buf[50];
+
+	/* Make certain the resource has actually been set */
+	if (!(resource->flags & IORESOURCE_ASSIGNED)) {
+		return;
+	}
+
+	/* If I have already stored this resource don't worry about it */
+	if (resource->flags & IORESOURCE_STORED) {
+		return;
+	}
+
+	/* Only handle PCI memory and IO resources */
+	if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+		return;
+
+	/* Ensure I am actually looking at a resource of function 1 */
+	if ((resource->index & 0xffff) < 0x1000) {
+		return;
+	}
+	/* Get the base address */
+	rbase = resource->base;
+
+	/* Get the limit (rounded up) */
+	rend  = resource_end(resource);
+
+	/* Get the register and link */
+	reg  = resource->index & 0xfff; // 4k
+	link_num = IOINDEX_LINK(resource->index);
+
+	if (resource->flags & IORESOURCE_IO) {
+		set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
+	}
+	else if (resource->flags & IORESOURCE_MEM) {
+		set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, node_nums) ;// [39:8]
+	}
+	resource->flags |= IORESOURCE_STORED;
+	snprintf(buf, sizeof (buf), " <node %x link %x>",
+			nodeid, link_num);
+	report_resource_stored(dev, resource, buf);
+}
+
+/**
+ * I tried to reuse the resource allocation code in set_resource()
+ * but it is too difficult to deal with the resource allocation magic.
+ */
+
+static void create_vga_resource(device_t dev, unsigned nodeid)
+{
+	struct bus *link;
+
+	/* find out which link the VGA card is connected,
+	 * we only deal with the 'first' vga card */
+	for (link = dev->link_list; link; link = link->next) {
+		if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+#if CONFIG_MULTIPLE_VGA_ADAPTERS
+			extern device_t vga_pri; // the primary vga device, defined in device.c
+			printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
+					link->secondary,link->subordinate);
+			/* We need to make sure the vga_pri is under the link */
+			if((vga_pri->bus->secondary >= link->secondary ) &&
+					(vga_pri->bus->secondary <= link->subordinate )
+			  )
+#endif
+				break;
+		}
+	}
+
+	/* no VGA card installed */
+	if (link == NULL)
+		return;
+
+	printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, sblink);
+	set_vga_enable_reg(nodeid, sblink);
+}
+
+static void set_resources(device_t dev)
+{
+	unsigned nodeid;
+	struct bus *bus;
+	struct resource *res;
+
+	/* Find the nodeid */
+	nodeid = amdfam16_nodeid(dev);
+
+	create_vga_resource(dev, nodeid); //TODO: do we need this?
+
+	/* Set each resource we have found */
+	for (res = dev->resource_list; res; res = res->next) {
+		set_resource(dev, res, nodeid);
+	}
+
+	for (bus = dev->link_list; bus; bus = bus->next) {
+		if (bus->children) {
+			assign_resources(bus);
+		}
+	}
+}
+
+static void northbridge_init(struct device *dev)
+{
+}
+#if 0				/* TODO: Check if needed. */
+static unsigned scan_chains(device_t dev, unsigned max)
+{
+	unsigned nodeid;
+	struct bus *link;
+	device_t io_hub = NULL;
+	u32 next_unitid = 0x18;
+	nodeid = amdfam16_nodeid(dev);
+	if (nodeid == 0) {
+		for (link = dev->link_list; link; link = link->next) {
+			//if (link->link_num == sblink) { /* devicetree put IO Hub on link_lsit[sblink] */
+			if (link->link_num == 0) { /* devicetree put IO Hub on link_lsit[0] */
+				io_hub = link->children;
+				if (!io_hub || !io_hub->enabled) {
+					die("I can't find the IO Hub, or IO Hub not enabled, please check the device tree.\n");
+				}
+				/* Now that nothing is overlapping it is safe to scan the children. */
+				max = pci_scan_bus(link, 0x00, ((next_unitid - 1) << 3) | 7, 0);
+			}
+		}
+	}
+	return max;
+}
+#endif
+static struct device_operations northbridge_operations = {
+	.read_resources	  = read_resources,
+	.set_resources	  = set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init		  = northbridge_init,
+	//.scan_bus	  = scan_chains, /* TODO: */
+	.enable		  = 0,
+	.ops_pci	  = 0,
+};
+
+static const struct pci_driver family16_northbridge __pci_driver = {
+	.ops	= &northbridge_operations,
+	.vendor = PCI_VENDOR_ID_AMD,
+	.device = PCI_DEVICE_ID_AMD_16H_MODEL_003F_NB_HT,
+};
+
+static const struct pci_driver family10_northbridge __pci_driver = {
+	.ops	= &northbridge_operations,
+	.vendor = PCI_VENDOR_ID_AMD,
+	.device = PCI_DEVICE_ID_AMD_10H_NB_HT,
+};
+
+struct chip_operations northbridge_amd_pi_00730F01_ops = {
+	CHIP_NAME("AMD FAM16 Northbridge")
+	.enable_dev = 0,
+};
+
+static void domain_read_resources(device_t dev)
+{
+	unsigned reg;
+
+	/* Find the already assigned resource pairs */
+	get_fx_devs();
+	for (reg = 0x80; reg <= 0xd8; reg+= 0x08) {
+		u32 base, limit;
+		base  = f1_read_config32(reg);
+		limit = f1_read_config32(reg + 0x04);
+		/* Is this register allocated? */
+		if ((base & 3) != 0) {
+			unsigned nodeid, reg_link;
+			device_t reg_dev;
+			if (reg<0xc0) { // mmio
+				nodeid = (limit & 0xf) + (base&0x30);
+			} else { // io
+				nodeid =  (limit & 0xf) + ((base>>4)&0x30);
+			}
+			reg_link = (limit >> 4) & 7;
+			reg_dev = __f0_dev[nodeid];
+			if (reg_dev) {
+				/* Reserve the resource  */
+				struct resource *res;
+				res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
+				if (res) {
+					res->flags = 1;
+				}
+			}
+		}
+	}
+	/* FIXME: do we need to check extend conf space?
+	   I don't believe that much preset value */
+
+#if !CONFIG_PCI_64BIT_PREF_MEM
+	pci_domain_read_resources(dev);
+
+#else
+	struct bus *link;
+	struct resource *resource;
+	for (link=dev->link_list; link; link = link->next) {
+		/* Initialize the system wide io space constraints */
+		resource = new_resource(dev, 0|(link->link_num<<2));
+		resource->base	= 0x400;
+		resource->limit = 0xffffUL;
+		resource->flags = IORESOURCE_IO;
+
+		/* Initialize the system wide prefetchable memory resources constraints */
+		resource = new_resource(dev, 1|(link->link_num<<2));
+		resource->limit = 0xfcffffffffULL;
+		resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+
+		/* Initialize the system wide memory resources constraints */
+		resource = new_resource(dev, 2|(link->link_num<<2));
+		resource->limit = 0xfcffffffffULL;
+		resource->flags = IORESOURCE_MEM;
+	}
+#endif
+}
+
+static void domain_enable_resources(device_t dev)
+{
+	if (acpi_is_wakeup_s3())
+		AGESAWRAPPER(fchs3laterestore);
+
+	/* Must be called after PCI enumeration and resource allocation */
+	if (!acpi_is_wakeup_s3())
+		AGESAWRAPPER(amdinitmid);
+
+	printk(BIOS_DEBUG, "  ader - leaving domain_enable_resources.\n");
+}
+
+#if CONFIG_HW_MEM_HOLE_SIZEK != 0
+struct hw_mem_hole_info {
+	unsigned hole_startk;
+	int node_id;
+};
+static struct hw_mem_hole_info get_hw_mem_hole_info(void)
+{
+	struct hw_mem_hole_info mem_hole;
+	int i;
+	mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
+	mem_hole.node_id = -1;
+	for (i = 0; i < node_nums; i++) {
+		dram_base_mask_t d;
+		u32 hole;
+		d = get_dram_base_mask(i);
+		if (!(d.mask & 1)) continue; // no memory on this node
+		hole = pci_read_config32(__f1_dev[i], 0xf0);
+		if (hole & 2) { // we find the hole
+			mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
+			mem_hole.node_id = i; // record the node No with hole
+			break; // only one hole
+		}
+	}
+
+	/* We need to double check if there is special set on base reg and limit reg
+	 * are not continuous instead of hole, it will find out its hole_startk.
+	 */
+	if (mem_hole.node_id == -1) {
+		resource_t limitk_pri = 0;
+		for (i=0; i<node_nums; i++) {
+			dram_base_mask_t d;
+			resource_t base_k, limit_k;
+			d = get_dram_base_mask(i);
+			if (!(d.base & 1)) continue;
+			base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
+			if (base_k > 4 *1024 * 1024) break; // don't need to go to check
+			if (limitk_pri != base_k) { // we find the hole
+				mem_hole.hole_startk = (unsigned)limitk_pri; // must beblow 4G
+				mem_hole.node_id = i;
+				break; //only one hole
+			}
+			limit_k = ((resource_t)(((d.mask & ~1) + 0x000FF) & 0x1fffff00)) << 9;
+			limitk_pri = limit_k;
+		}
+	}
+	return mem_hole;
+}
+#endif
+
+#define ONE_MB_SHIFT  20
+#define ONE_GB_SHIFT  30
+
+static void setup_uma_memory(void)
+{
+#if CONFIG_GFXUMA
+	uint64_t topmem = bsp_topmem();
+	uint64_t topmem2 = bsp_topmem2();
+	uint32_t sysmem_mb, sysmem_gb;
+
+	/* refer to UMA_AUTO size computation in Family16h BKDG. */
+	/* Please reference MemNGetUmaSizeML() */
+	/*
+	 *     Total system memory   UMASize
+	 *     >= 6G                  1024M
+	 *     >= 4G                   512M
+	 *     >= 2G                   256M
+	 *     < 2G                    128M
+	 */
+
+	sysmem_mb = (topmem + (16ull << ONE_MB_SHIFT)) >> ONE_MB_SHIFT;   // Ignore 16MB allocated for C6 when finding UMA size
+	sysmem_mb += topmem2 ? ((topmem2 >> ONE_MB_SHIFT) - 4096) : 0;
+	sysmem_gb = sysmem_mb >> (ONE_GB_SHIFT - ONE_MB_SHIFT);
+	printk(BIOS_SPEW, "%s: system memory size %luGB, topmem2 size %lluMB, topmem size %lluMB\n", __func__, (unsigned long)sysmem_gb, (topmem2 >> ONE_MB_SHIFT), (topmem >> ONE_MB_SHIFT));
+	if (sysmem_gb >= 6) {
+		uma_memory_size = 1024 << ONE_MB_SHIFT;
+	} else if (sysmem_gb >= 4) {
+		uma_memory_size = 512 << ONE_MB_SHIFT;
+	} else if (sysmem_gb >= 2) {
+		uma_memory_size = 256 << ONE_MB_SHIFT;
+	} else {
+		uma_memory_size = 128 << ONE_MB_SHIFT;
+	}
+	uma_memory_base = topmem - uma_memory_size; /* TOP_MEM1 */
+
+	printk(BIOS_INFO, "%s: uma size 0x%08llx, memory start 0x%08llx\n",
+			__func__, uma_memory_size, uma_memory_base);
+
+	/* TODO: TOP_MEM2 */
+#endif
+}
+
+
+static void domain_set_resources(device_t dev)
+{
+#if CONFIG_PCI_64BIT_PREF_MEM
+	struct resource *io, *mem1, *mem2;
+	struct resource *res;
+#endif
+	unsigned long mmio_basek;
+	u32 pci_tolm;
+	u64 ramtop = 0;
+	int i, idx;
+	struct bus *link;
+#if CONFIG_HW_MEM_HOLE_SIZEK != 0
+	struct hw_mem_hole_info mem_hole;
+	u32 reset_memhole = 1;
+#endif
+
+#if CONFIG_PCI_64BIT_PREF_MEM
+
+	for (link = dev->link_list; link; link = link->next) {
+		/* Now reallocate the pci resources memory with the
+		 * highest addresses I can manage.
+		 */
+		mem1 = find_resource(dev, 1|(link->link_num<<2));
+		mem2 = find_resource(dev, 2|(link->link_num<<2));
+
+		printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
+				mem1->base, mem1->limit, mem1->size, mem1->align);
+		printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
+				mem2->base, mem2->limit, mem2->size, mem2->align);
+
+		/* See if both resources have roughly the same limits */
+		if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) ||
+				((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)))
+		{
+			/* If so place the one with the most stringent alignment first */
+			if (mem2->align > mem1->align) {
+				struct resource *tmp;
+				tmp = mem1;
+				mem1 = mem2;
+				mem2 = tmp;
+			}
+			/* Now place the memory as high up as it will go */
+			mem2->base = resource_max(mem2);
+			mem1->limit = mem2->base - 1;
+			mem1->base = resource_max(mem1);
+		}
+		else {
+			/* Place the resources as high up as they will go */
+			mem2->base = resource_max(mem2);
+			mem1->base = resource_max(mem1);
+		}
+
+		printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
+				mem1->base, mem1->limit, mem1->size, mem1->align);
+		printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
+				mem2->base, mem2->limit, mem2->size, mem2->align);
+	}
+
+	for (res = &dev->resource_list; res; res = res->next)
+	{
+		res->flags |= IORESOURCE_ASSIGNED;
+		res->flags |= IORESOURCE_STORED;
+		report_resource_stored(dev, res, "");
+	}
+#endif
+
+	pci_tolm = 0xffffffffUL;
+	for (link = dev->link_list; link; link = link->next) {
+		pci_tolm = find_pci_tolm(link);
+	}
+
+	// FIXME handle interleaved nodes. If you fix this here, please fix
+	// amdk8, too.
+	mmio_basek = pci_tolm >> 10;
+	/* Round mmio_basek to something the processor can support */
+	mmio_basek &= ~((1 << 6) -1);
+
+	// FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
+	// MMIO hole. If you fix this here, please fix amdk8, too.
+	/* Round the mmio hole to 64M */
+	mmio_basek &= ~((64*1024) - 1);
+
+#if CONFIG_HW_MEM_HOLE_SIZEK != 0
+	/* if the hw mem hole is already set in raminit stage, here we will compare
+	 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
+	 * use hole_basek as mmio_basek and we don't need to reset hole.
+	 * otherwise We reset the hole to the mmio_basek
+	 */
+
+	mem_hole = get_hw_mem_hole_info();
+
+	// Use hole_basek as mmio_basek, and we don't need to reset hole anymore
+	if ((mem_hole.node_id !=  -1) && (mmio_basek > mem_hole.hole_startk)) {
+		mmio_basek = mem_hole.hole_startk;
+		reset_memhole = 0;
+	}
+#endif
+
+	idx = 0x10;
+	for (i = 0; i < node_nums; i++) {
+		dram_base_mask_t d;
+		resource_t basek, limitk, sizek; // 4 1T
+
+		d = get_dram_base_mask(i);
+
+		if (!(d.mask & 1)) continue;
+		basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here
+		limitk = ((resource_t)(((d.mask & ~1) + 0x000FF) & 0x1fffff00)) << 9 ;
+
+		sizek = limitk - basek;
+
+		/* see if we need a hole from 0xa0000 to 0xbffff */
+		if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
+			ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek);
+			idx += 0x10;
+			basek = (8*64)+(16*16);
+			sizek = limitk - ((8*64)+(16*16));
+
+		}
+
+		//printk(BIOS_DEBUG, "node %d : mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", i, mmio_basek, basek, limitk);
+
+		/* split the region to accommodate pci memory space */
+		if ((basek < 4*1024*1024 ) && (limitk > mmio_basek)) {
+			if (basek <= mmio_basek) {
+				unsigned pre_sizek;
+				pre_sizek = mmio_basek - basek;
+				if (pre_sizek>0) {
+					ram_resource(dev, (idx | i), basek, pre_sizek);
+					idx += 0x10;
+					sizek -= pre_sizek;
+					if (!ramtop)
+						ramtop = mmio_basek * 1024;
+				}
+				basek = mmio_basek;
+			}
+			if ((basek + sizek) <= 4*1024*1024) {
+				sizek = 0;
+			}
+			else {
+				uint64_t topmem2 = bsp_topmem2();
+				basek = 4*1024*1024;
+				sizek = topmem2/1024 - basek;
+			}
+		}
+
+		ram_resource(dev, (idx | i), basek, sizek);
+		idx += 0x10;
+		printk(BIOS_DEBUG, "node %d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
+				i, mmio_basek, basek, limitk);
+		if (!ramtop)
+			ramtop = limitk * 1024;
+	}
+
+#if CONFIG_GFXUMA
+	set_top_of_ram(uma_memory_base);
+	uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10);
+#else
+	set_top_of_ram(ramtop);
+#endif
+
+	for(link = dev->link_list; link; link = link->next) {
+		if (link->children) {
+			assign_resources(link);
+		}
+	}
+}
+
+static struct device_operations pci_domain_ops = {
+	.read_resources	  = domain_read_resources,
+	.set_resources	  = domain_set_resources,
+	.enable_resources = domain_enable_resources,
+	.init		  = NULL,
+	.scan_bus	  = pci_domain_scan_bus,
+	.ops_pci_bus	  = pci_bus_default_ops,
+};
+
+static void sysconf_init(device_t dev) // first node
+{
+	sblink = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1
+	node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0]
+}
+
+static void add_more_links(device_t dev, unsigned total_links)
+{
+	struct bus *link, *last = NULL;
+	int link_num;
+
+	for (link = dev->link_list; link; link = link->next)
+		last = link;
+
+	if (last) {
+		int links = total_links - last->link_num;
+		link_num = last->link_num;
+		if (links > 0) {
+			link = malloc(links*sizeof(*link));
+			if (!link)
+				die("Couldn't allocate more links!\n");
+			memset(link, 0, links*sizeof(*link));
+			last->next = link;
+		}
+	}
+	else {
+		link_num = -1;
+		link = malloc(total_links*sizeof(*link));
+		memset(link, 0, total_links*sizeof(*link));
+		dev->link_list = link;
+	}
+
+	for (link_num = link_num + 1; link_num < total_links; link_num++) {
+		link->link_num = link_num;
+		link->dev = dev;
+		link->next = link + 1;
+		last = link;
+		link = link->next;
+	}
+	last->next = NULL;
+}
+
+static u32 cpu_bus_scan(device_t dev, u32 max)
+{
+	struct bus *cpu_bus;
+	device_t dev_mc;
+#if CONFIG_CBB
+	device_t pci_domain;
+#endif
+	int i,j;
+	int coreid_bits;
+	int core_max = 0;
+	unsigned ApicIdCoreIdSize;
+	unsigned core_nums;
+	int siblings = 0;
+	unsigned int family;
+	u32 modules = 0;
+	VOID* modules_ptr = &modules;
+	BUILD_OPT_CFG* options = NULL;
+	int ioapic_count = 0;
+
+	// TODO Remove the printk's.
+	printk(BIOS_SPEW, "MullinsPI Debug: Grabbing the AMD Topology Information.\n");
+	AmdGetValue(AMD_GLOBAL_USER_OPTIONS, (VOID**)&options, sizeof(options));
+	AmdGetValue(AMD_GLOBAL_NUM_MODULES, &modules_ptr, sizeof(modules));
+	modules = (*(u32*)modules_ptr) && ((1ull << (sizeof(modules) * 8)) - 1);
+	ASSERT(modules > 0);
+	ASSERT(options);
+	ioapic_count = (int)options->CfgPlatNumIoApics;
+	ASSERT(ioapic_count > 0);
+	printk(BIOS_SPEW, "MullinsPI Debug: AMD Topology Number of Modules (@0x%p) is %d\n", modules_ptr, modules);
+	printk(BIOS_SPEW, "MullinsPI Debug: AMD Topology Number of IOAPICs (@0x%p) is %d\n", options, (int)options->CfgPlatNumIoApics);
+
+#if CONFIG_CBB
+	dev_mc = dev_find_slot(0, PCI_DEVFN(CONFIG_CDB, 0)); //0x00
+	if (dev_mc && dev_mc->bus) {
+		printk(BIOS_DEBUG, "%s found", dev_path(dev_mc));
+		pci_domain = dev_mc->bus->dev;
+		if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
+			printk(BIOS_DEBUG, "\n%s move to ",dev_path(dev_mc));
+			dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
+			printk(BIOS_DEBUG, "%s",dev_path(dev_mc));
+		} else {
+			printk(BIOS_DEBUG, " but it is not under pci_domain directly ");
+		}
+		printk(BIOS_DEBUG, "\n");
+	}
+	dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
+	if (!dev_mc) {
+		dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0));
+		if (dev_mc && dev_mc->bus) {
+			printk(BIOS_DEBUG, "%s found\n", dev_path(dev_mc));
+			pci_domain = dev_mc->bus->dev;
+			if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
+				if ((pci_domain->link_list) && (pci_domain->link_list->children == dev_mc)) {
+					printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
+					dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
+					printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
+					while (dev_mc) {
+						printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
+						dev_mc->path.pci.devfn -= PCI_DEVFN(0x18,0);
+						printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
+						dev_mc = dev_mc->sibling;
+					}
+				}
+			}
+		}
+	}
+#endif
+	dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
+	if (!dev_mc) {
+		printk(BIOS_ERR, "%02x:%02x.0 not found", CONFIG_CBB, CONFIG_CDB);
+		die("");
+	}
+	sysconf_init(dev_mc);
+#if CONFIG_CBB && (MAX_NODE_NUMS > 32)
+	if (node_nums>32) { // need to put node 32 to node 63 to bus 0xfe
+		if (pci_domain->link_list && !pci_domain->link_list->next) {
+			struct bus *new_link = new_link(pci_domain);
+			pci_domain->link_list->next = new_link;
+			new_link->link_num = 1;
+			new_link->dev = pci_domain;
+			new_link->children = 0;
+			printk(BIOS_DEBUG, "%s links now 2\n", dev_path(pci_domain));
+		}
+		pci_domain->link_list->next->secondary = CONFIG_CBB - 1;
+	}
+#endif
+
+	/* Get Max Number of cores(MNC) */
+	coreid_bits = (cpuid_ecx(AMD_CPUID_ASIZE_PCCOUNT) & 0x0000F000) >> 12;
+	core_max = 1 << (coreid_bits & 0x000F); //mnc
+
+	ApicIdCoreIdSize = ((cpuid_ecx(0x80000008)>>12) & 0xF);
+	if (ApicIdCoreIdSize) {
+		core_nums = (1 << ApicIdCoreIdSize) - 1;
+	} else {
+		core_nums = 3; //quad core
+	}
+
+	/* Find which cpus are present */
+	cpu_bus = dev->link_list;
+	for (i = 0; i < node_nums; i++) {
+		device_t cdb_dev;
+		unsigned busn, devn;
+		struct bus *pbus;
+
+		busn = CONFIG_CBB;
+		devn = CONFIG_CDB + i;
+		pbus = dev_mc->bus;
+#if CONFIG_CBB && (MAX_NODE_NUMS > 32)
+		if (i >= 32) {
+			busn--;
+			devn -= 32;
+			pbus = pci_domain->link_list->next;
+		}
+#endif
+
+		/* Find the cpu's pci device */
+		cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
+		if (!cdb_dev) {
+			/* If I am probing things in a weird order
+			 * ensure all of the cpu's pci devices are found.
+			 */
+			int fn;
+			for(fn = 0; fn <= 5; fn++) { //FBDIMM?
+				cdb_dev = pci_probe_dev(NULL, pbus,
+							PCI_DEVFN(devn, fn));
+			}
+			cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
+		} else {
+			/* Ok, We need to set the links for that device.
+			 * otherwise the device under it will not be scanned
+			 */
+			int linknum;
+#if CONFIG_HT3_SUPPORT
+			linknum = 8;
+#else
+			linknum = 4;
+#endif
+			add_more_links(cdb_dev, linknum);
+		}
+
+		family = cpuid_eax(1);
+		family = (family >> 20) & 0xFF;
+		if (family == 1) { //f10
+			u32 dword;
+			cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
+			dword = pci_read_config32(cdb_dev, 0xe8);
+			siblings = ((dword & BIT15) >> 13) | ((dword & (BIT13 | BIT12)) >> 12);
+		} else if (family == 7) {//f16
+			cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 5));
+			if (cdb_dev && cdb_dev->enabled) {
+				siblings = pci_read_config32(cdb_dev, 0x84);
+				siblings &= 0xFF;
+			}
+		} else {
+			siblings = 0; //default one core
+		}
+		int enable_node = cdb_dev && cdb_dev->enabled;
+		printk(BIOS_SPEW, "%s family%xh, core_max=0x%x, core_nums=0x%x, siblings=0x%x\n",
+				dev_path(cdb_dev), 0x0f + family, core_max, core_nums, siblings);
+
+		for (j = 0; j <= siblings; j++ ) {
+			u32 lapicid_start = 0;
+
+			/*
+			 * APIC ID calucation is tightly coupled with AGESA v5 code.
+			 * This calculation MUST match the assignment calculation done
+			 * in LocalApicInitializationAtEarly() function.
+			 * And reference GetLocalApicIdForCore()
+			 *
+			 * Apply apic enumeration rules
+			 * For systems with >= 16 APICs, put the IO-APICs at 0..n and
+			 * put the local-APICs at m..z
+			 *
+			 * This is needed because many IO-APIC devices only have 4 bits
+			 * for their APIC id and therefore must reside at 0..15
+                         */
+			if ((node_nums * core_max) + ioapic_count >= 0x10) {
+				lapicid_start = (ioapic_count - 1) / core_max;
+				lapicid_start = (lapicid_start + 1) * core_max;
+				printk(BIOS_SPEW, "lpaicid_start=0x%x ", lapicid_start);
+			}
+			u32 apic_id = (lapicid_start * (i/modules + 1)) + ((i % modules) ? (j + (siblings + 1)) : j);
+			printk(BIOS_SPEW, "node 0x%x core 0x%x apicid=0x%x\n",
+					i, j, apic_id);
+
+			device_t cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
+			if (cpu)
+				amd_cpu_topology(cpu, i, j);
+		} //j
+	}
+	return max;
+}
+
+static void cpu_bus_init(device_t dev)
+{
+	initialize_cpus(dev->link_list);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static void cpu_bus_read_resources(device_t dev)
+{
+#if CONFIG_MMCONF_SUPPORT
+	struct resource *resource = new_resource(dev, 0xc0010058);
+	resource->base = CONFIG_MMCONF_BASE_ADDRESS;
+	resource->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256;
+	resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+		IORESOURCE_FIXED | IORESOURCE_STORED |  IORESOURCE_ASSIGNED;
+#endif
+}
+
+static void cpu_bus_set_resources(device_t dev)
+{
+	struct resource *resource = find_resource(dev, 0xc0010058);
+	if (resource) {
+		report_resource_stored(dev, resource, " <mmconfig>");
+	}
+	pci_dev_set_resources(dev);
+}
+
+static struct device_operations cpu_bus_ops = {
+	.read_resources	  = cpu_bus_read_resources,
+	.set_resources	  = cpu_bus_set_resources,
+	.enable_resources = cpu_bus_noop,
+	.init		  = cpu_bus_init,
+	.scan_bus	  = cpu_bus_scan,
+};
+
+static void root_complex_enable_dev(struct device *dev)
+{
+	static int done = 0;
+
+	/* Do not delay UMA setup, as a device on the PCI bus may evaluate
+	   the global uma_memory variables already in its enable function. */
+	if (!done) {
+		setup_bsp_ramtop();
+		setup_uma_memory();
+		done = 1;
+	}
+
+	/* Set the operations if it is a special bus type */
+	if (dev->path.type == DEVICE_PATH_DOMAIN) {
+		dev->ops = &pci_domain_ops;
+	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+		dev->ops = &cpu_bus_ops;
+	}
+}
+
+struct chip_operations northbridge_amd_pi_00730F01_root_complex_ops = {
+	CHIP_NAME("AMD FAM16 Root Complex")
+	.enable_dev = root_complex_enable_dev,
+};
+
+/*********************************************************************
+ * Change the vendor / device IDs to match the generic VBIOS header. *
+ *********************************************************************/
+u32 map_oprom_vendev(u32 vendev)
+{
+	u32 new_vendev;
+	new_vendev =
+		((0x10029850 <= vendev) && (vendev <= 0x1002986F)) ? 0x10029850 : vendev;
+
+	if (vendev != new_vendev)
+		printk(BIOS_NOTICE, "Mapping PCI device %8x to %8x\n", vendev, new_vendev);
+
+	return new_vendev;
+}
diff --git a/src/northbridge/amd/pi/00730F01/northbridge.h b/src/northbridge/amd/pi/00730F01/northbridge.h
new file mode 100644
index 0000000..6fa8164
--- /dev/null
+++ b/src/northbridge/amd/pi/00730F01/northbridge.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef NORTHBRIDGE_AMD_AGESA_FAM16H_H
+#define NORTHBRIDGE_AMD_AGESA_FAM16H_H
+
+static struct device_operations pci_domain_ops;
+static struct device_operations cpu_bus_ops;
+
+#endif /* NORTHBRIDGE_AMD_AGESA_FAM16H_H */
diff --git a/src/northbridge/amd/pi/BiosCallOuts.h b/src/northbridge/amd/pi/BiosCallOuts.h
new file mode 100644
index 0000000..feabf98
--- /dev/null
+++ b/src/northbridge/amd/pi/BiosCallOuts.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011,2012 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef CALLOUTS_AMD_AGESA_H
+#define CALLOUTS_AMD_AGESA_H
+
+#include "Porting.h"
+#include "AGESA.h"
+
+#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
+
+#define BIOS_HEAP_START_ADDRESS 	0x010000000
+#define BIOS_HEAP_SIZE			0x30000
+#define BSP_STACK_BASE_ADDR		0x30000
+
+#else
+
+#define BIOS_HEAP_START_ADDRESS		0x10000 /* HEAP during cold boot */
+#define BIOS_HEAP_SIZE			0x20000
+#define BSP_STACK_BASE_ADDR		0x30000
+
+#endif
+
+typedef struct _BIOS_HEAP_MANAGER {
+	UINT32 StartOfAllocatedNodes;
+	UINT32 StartOfFreedNodes;
+} BIOS_HEAP_MANAGER;
+
+typedef struct _BIOS_BUFFER_NODE {
+	UINT32 BufferHandle;
+	UINT32 BufferSize;
+	UINT32 NextNodeOffset;
+} BIOS_BUFFER_NODE;
+
+UINT32 GetHeapBase(AMD_CONFIG_PARAMS *StdHeader);
+void EmptyHeap(void);
+
+
+AGESA_STATUS agesa_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_DeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_LocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+
+AGESA_STATUS agesa_NoopUnsupported (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_NoopSuccess (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_EmptyIdsInitData (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_Reset (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt);
+
+AGESA_STATUS agesa_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_ReadSpd_from_cbfs(UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+
+AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
+
+typedef struct {
+	UINT32 CalloutName;
+	AGESA_STATUS (*CalloutPtr) (UINT32 Func, UINT32 Data, VOID* ConfigPtr);
+} BIOS_CALLOUT_STRUCT;
+
+extern const BIOS_CALLOUT_STRUCT BiosCallouts[];
+extern const int BiosCalloutsLen;
+
+#endif /* CALLOUTS_AMD_AGESA_H */
diff --git a/src/northbridge/amd/pi/Kconfig b/src/northbridge/amd/pi/Kconfig
new file mode 100644
index 0000000..8af4872
--- /dev/null
+++ b/src/northbridge/amd/pi/Kconfig
@@ -0,0 +1,36 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2011 - 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+config NORTHBRIDGE_AMD_PI
+        bool
+        default CPU_AMD_PI
+
+if NORTHBRIDGE_AMD_PI
+
+config CONSOLE_VGA_MULTI
+	bool
+	default n
+
+config S3_VGA_ROM_RUN
+	bool
+	default n
+
+source src/northbridge/amd/pi/00730F01/Kconfig
+
+endif # NORTHBRIDGE_AMD_PI
diff --git a/src/northbridge/amd/pi/Makefile.inc b/src/northbridge/amd/pi/Makefile.inc
new file mode 100644
index 0000000..294673c
--- /dev/null
+++ b/src/northbridge/amd/pi/Makefile.inc
@@ -0,0 +1,23 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2011 - 2012 Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+subdirs-$(CONFIG_NORTHBRIDGE_AMD_PI_00730F01) += 00730F01
+
+romstage-y += def_callouts.c
+ramstage-y += def_callouts.c
diff --git a/src/northbridge/amd/pi/agesawrapper_call.h b/src/northbridge/amd/pi/agesawrapper_call.h
new file mode 100644
index 0000000..792c3b1
--- /dev/null
+++ b/src/northbridge/amd/pi/agesawrapper_call.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _AGESAWRAPPER_CALL_H_
+#define _AGESAWRAPPER_CALL_H_
+
+#include <stdint.h>
+#include <console/console.h>
+#include "AGESA.h"
+
+/*
+ * Possible AGESA_STATUS values:
+ *
+ * 0x0 = AGESA_SUCCESS
+ * 0x1 = AGESA_UNSUPPORTED
+ * 0x2 = AGESA_BOUNDS_CHK
+ * 0x3 = AGESA_ALERT
+ * 0x4 = AGESA_WARNING
+ * 0x5 = AGESA_ERROR
+ * 0x6 = AGESA_CRITICAL
+ * 0x7 = AGESA_FATAL
+ */
+static const char * decodeAGESA_STATUS(AGESA_STATUS sret)
+{
+	const char* statusStrings[] = { "AGESA_SUCCESS", "AGESA_UNSUPPORTED",
+					"AGESA_BOUNDS_CHK", "AGESA_ALERT",
+					"AGESA_WARNING", "AGESA_ERROR",
+					"AGESA_CRITICAL", "AGESA_FATAL"
+					};
+	if (sret > 7) return "unknown"; /* Non-AGESA error code */
+	return statusStrings[sret];
+}
+
+static inline u32 do_agesawrapper(AGESA_STATUS (*func)(void), const char *name)
+{
+	AGESA_STATUS ret;
+	printk(BIOS_DEBUG, "agesawrapper_%s() entry\n", name);
+	ret = func();
+	printk(BIOS_DEBUG, "agesawrapper_%s() returned %s\n",
+			name, decodeAGESA_STATUS(ret));
+	return (u32)ret;
+}
+
+#define AGESAWRAPPER(func) do_agesawrapper(agesawrapper_ ## func, #func)
+
+#define AGESAWRAPPER_PRE_CONSOLE(func) agesawrapper_ ## func()
+
+#endif
diff --git a/src/northbridge/amd/pi/def_callouts.c b/src/northbridge/amd/pi/def_callouts.c
new file mode 100644
index 0000000..225bf53
--- /dev/null
+++ b/src/northbridge/amd/pi/def_callouts.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cbfs.h>
+#include <spd_cache.h>
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "agesawrapper.h"
+#include "BiosCallOuts.h"
+#include "dimmSpd.h"
+
+AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	UINTN i;
+
+	for (i = 0; i < BiosCalloutsLen; i++) {
+		if (BiosCallouts[i].CalloutName == Func)
+			break;
+	}
+	if(i >= BiosCalloutsLen)
+		return AGESA_UNSUPPORTED;
+
+	return BiosCallouts[i].CalloutPtr (Func, Data, ConfigPtr);
+}
+
+AGESA_STATUS agesa_NoopUnsupported (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	return AGESA_UNSUPPORTED;
+}
+
+AGESA_STATUS agesa_NoopSuccess (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_EmptyIdsInitData (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	IDS_NV_ITEM *IdsPtr = ((IDS_CALLOUT_STRUCT *) ConfigPtr)->IdsNvPtr;
+	if (Data == IDS_CALLOUT_INIT)
+		IdsPtr[0].IdsNvValue = IdsPtr[0].IdsNvId = 0xffff;
+	return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_Reset (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	AGESA_STATUS        Status;
+	UINT8                 Value;
+	UINTN               ResetType;
+	AMD_CONFIG_PARAMS   *StdHeader;
+
+	ResetType = Data;
+	StdHeader = ConfigPtr;
+
+	//
+	// Perform the RESET based upon the ResetType. In case of
+	// WARM_RESET_WHENVER and COLD_RESET_WHENEVER, the request will go to
+	// AmdResetManager. During the critical condition, where reset is required
+	// immediately, the reset will be invoked directly by writing 0x04 to port
+	// 0xCF9 (Reset Port).
+	//
+	switch (ResetType) {
+	case WARM_RESET_WHENEVER:
+	case COLD_RESET_WHENEVER:
+		break;
+
+	case WARM_RESET_IMMEDIATELY:
+	case COLD_RESET_IMMEDIATELY:
+		Value = 0x06;
+		LibAmdIoWrite (AccessWidth8, 0xCf9, &Value, StdHeader);
+		break;
+
+	default:
+		break;
+	}
+
+	Status = 0;
+	return Status;
+}
+
+AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	AGESA_STATUS        Status;
+
+	Status = agesawrapper_amdlaterunaptask (Func, Data, ConfigPtr);
+	return Status;
+}
+
+AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
+{
+	GFX_VBIOS_IMAGE_INFO  *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
+	pVbiosImageInfo->ImagePtr = cbfs_get_file_content(
+			CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom",
+			CBFS_TYPE_OPTIONROM, NULL);
+	/* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */
+	return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	AGESA_STATUS Status = AGESA_UNSUPPORTED;
+#ifdef __PRE_RAM__
+	Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
+#endif
+	return Status;
+}
+
+AGESA_STATUS agesa_ReadSpd_from_cbfs(UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+	AGESA_STATUS Status = AGESA_UNSUPPORTED;
+#ifdef __PRE_RAM__
+	AGESA_READ_SPD_PARAMS *info = ConfigPtr;
+	if (info->MemChannelId > 0)
+		return AGESA_UNSUPPORTED;
+	if (info->SocketId != 0)
+		return AGESA_UNSUPPORTED;
+	if (info->DimmId != 0)
+		return AGESA_UNSUPPORTED;
+
+	/* Read index 0, first SPD_SIZE bytes of spd.bin file. */
+	if (read_spd_from_cbfs((u8*)info->Buffer, 0) < 0)
+		die("No SPD data\n");
+
+	Status = AGESA_SUCCESS;
+#endif
+	return Status;
+}
diff --git a/src/northbridge/amd/pi/dimmSpd.h b/src/northbridge/amd/pi/dimmSpd.h
new file mode 100644
index 0000000..3af6720
--- /dev/null
+++ b/src/northbridge/amd/pi/dimmSpd.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _DIMMSPD_H_
+#define _DIMMSPD_H_
+
+AGESA_STATUS
+AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
+
+int hudson_readSpd(int spdAddress, char *buf, size_t len);
+
+int smbus_readSpd(int spdAddress, char *buf, size_t len);
+
+#endif
diff --git a/src/southbridge/amd/agesa/hudson/Kconfig b/src/southbridge/amd/agesa/hudson/Kconfig
index 9ff6ef1..76a46cc 100644
--- a/src/southbridge/amd/agesa/hudson/Kconfig
+++ b/src/southbridge/amd/agesa/hudson/Kconfig
@@ -85,7 +85,7 @@ config HUDSON_GEC_FWM
 
 config HUDSON_PSP
 	bool
-	default y if CPU_AMD_AGESA_00730F01
+	default y if CPU_AMD_PI_00730F01
 
 config HUDSON_XHCI_FWM_FILE
         string "XHCI firmware path and filename"
@@ -138,7 +138,7 @@ endif # HUDSON_FWM
 config AMD_PUBKEY_FILE
         depends on HUDSON_PSP
         string "AMD public Key"
-        default "3rdparty/southbridge/amd/avalon/PSP/AmdPubKey.bin" if CPU_AMD_AGESA_00730F01
+        default "3rdparty/southbridge/amd/avalon/PSP/AmdPubKey.bin" if CPU_AMD_PI_00730F01
 
 choice
 	prompt "SATA Mode"
diff --git a/src/southbridge/amd/agesa/hudson/Makefile.inc b/src/southbridge/amd/agesa/hudson/Makefile.inc
index eb02936..a62282b 100644
--- a/src/southbridge/amd/agesa/hudson/Makefile.inc
+++ b/src/southbridge/amd/agesa/hudson/Makefile.inc
@@ -103,7 +103,7 @@ HUDSON_IMC_POSITION=0
 endif
 
 HUDSON_PSP_DIRECTORY_POSITION=0
-ifeq ($(CONFIG_CPU_AMD_AGESA_00730F01), y)
+ifeq ($(CONFIG_CPU_AMD_PI_00730F01), y)
 HUDSON_PSP_DIRECTORY_POSITION=$(shell echo $(HUDSON_FWM_POSITION) 262144 |  awk '{printf("%.0f", $$1 + $$2)}')
 endif
 
@@ -168,7 +168,7 @@ ifeq ($(CONFIG_HUDSON_PSP), y)
 AMDPUBKEY_POS=$(shell echo $(HUDSON_PSP_DIRECTORY_POSITION) | awk '{printf("%.0f", $$1 + 0x100)}')   #$(shell printf %u 0xFFb00100)
 AMDPUBKEY_SIZE=$(word 5,$(shell ls -l $(CONFIG_AMD_PUBKEY_FILE)))
 
-ifeq ($(CONFIG_CPU_AMD_AGESA_00730F01), y)
+ifeq ($(CONFIG_CPU_AMD_PI_00730F01), y)
 FIRMWARE_LOCATE=$(dir $(call strip_quotes, $(CONFIG_AMD_PUBKEY_FILE)))
 FIRMWARE_TYPE=
 endif
diff --git a/src/vendorcode/amd/Kconfig b/src/vendorcode/amd/Kconfig
index 6cc4b2c..d9ac731 100644
--- a/src/vendorcode/amd/Kconfig
+++ b/src/vendorcode/amd/Kconfig
@@ -17,7 +17,7 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 #
 
-if 	CPU_AMD_AGESA_00730F01
+if CPU_AMD_PI
 
 menu "AMD Platform Initialization"
 
@@ -25,8 +25,7 @@ source src/vendorcode/amd/pi/Kconfig
 
 choice
 	prompt "AGESA source"
-	depends on CPU_AMD_AGESA
-	default CPU_AMD_AGESA_BINARY_PI if CPU_AMD_AGESA_00730F01
+	default CPU_AMD_AGESA_BINARY_PI if CPU_AMD_PI
 	default CPU_AMD_AGESA_OPENSOURCE
 	help
 	  Select the method for including the AMD Platform Initialization
@@ -50,14 +49,14 @@ config CPU_AMD_AGESA_OPENSOURCE
 
 endchoice
 
+if CPU_AMD_AGESA_BINARY_PI
+
 config AGESA_BINARY_PI_PATH_DEFAULT_SELECTED
 	bool
-	depends on CPU_AMD_AGESA_BINARY_PI
 	default n
 
 config AGESA_BINARY_PI_PATH
 	string "AGESA PI directory path"
-	depends on CPU_AMD_AGESA_BINARY_PI
 	default AGESA_BINARY_PI_PATH_DEFAULT if AGESA_BINARY_PI_PATH_DEFAULT_SELECTED
 	help
 	  Specify where to find the AGESA headers and binary file
@@ -65,29 +64,27 @@ config AGESA_BINARY_PI_PATH
 
 config AGESA_BINARY_PI_FILE_DEFAULT_SELECTED
 	bool
-	depends on CPU_AMD_AGESA_BINARY_PI
 	default n
 
 config AGESA_BINARY_PI_FILE
 	string "AGESA PI binary file name"
-	depends on CPU_AMD_AGESA_BINARY_PI
 	default AGESA_BINARY_PI_FILE_DEFAULT if AGESA_BINARY_PI_FILE_DEFAULT_SELECTED
 	help
 	  Specify the binary file to use for AMD platform initialization.
 
 config AGESA_BINARY_PI_LOCATION_DEFAULT_SELECTED
 	bool
-	depends on CPU_AMD_AGESA_BINARY_PI
 	default n
 
 config AGESA_BINARY_PI_LOCATION
 	string "AGESA PI binary address in ROM"
-	depends on CPU_AMD_AGESA_BINARY_PI
 	default AGESA_BINARY_PI_LOCATION_DEFAULT if AGESA_BINARY_PI_FILE_DEFAULT_SELECTED
 	help
 	  Specify the ROM address at which to store the binary Platform
 	  Initialization code.
 
+endif
+
 endmenu
 
 endif
diff --git a/src/vendorcode/amd/pi/00730F01/Kconfig b/src/vendorcode/amd/pi/00730F01/Kconfig
index 0b37294..c630a24 100644
--- a/src/vendorcode/amd/pi/00730F01/Kconfig
+++ b/src/vendorcode/amd/pi/00730F01/Kconfig
@@ -25,32 +25,28 @@
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
 
-if CPU_AMD_AGESA_00730F01
+if CPU_AMD_PI_00730F01
 
 config AGESA_BINARY_PI_DEFAULTS # dummy
 	def_bool y
-	depends on CPU_AMD_AGESA_00730F01
 	select AGESA_BINARY_PI_LOCATION_DEFAULT_SELECTED
 	select AGESA_BINARY_PI_PATH_DEFAULT_SELECTED
 	select AGESA_BINARY_PI_FILE_DEFAULT_SELECTED
 
 config AGESA_BINARY_PI_PATH_DEFAULT
 	string
-	depends on CPU_AMD_AGESA_00730F01
 	default "3rdparty/pi/amd/00730F01"
 	help
 	  The default binary file name to use for AMD platform initialization.
 
 config AGESA_BINARY_PI_FILE_DEFAULT
 	string
-	depends on CPU_AMD_AGESA_00730F01
 	default "FT3b/AGESA.bin"
 	help
 	  The default binary file name to use for AMD platform initialization.
 
 config AGESA_BINARY_PI_LOCATION_DEFAULT
 	hex
-	depends on CPU_AMD_AGESA_00730F01
 	default 0xFFE00000
 	help
 	  The default ROM address at which to store the binary Platform
diff --git a/src/vendorcode/amd/pi/Makefile.inc b/src/vendorcode/amd/pi/Makefile.inc
index 0d28d19..424e674 100644
--- a/src/vendorcode/amd/pi/Makefile.inc
+++ b/src/vendorcode/amd/pi/Makefile.inc
@@ -1 +1 @@
-subdirs-$(CONFIG_CPU_AMD_AGESA_00730F01) += 00730F01
+subdirs-$(CONFIG_CPU_AMD_PI_00730F01) += 00730F01



More information about the coreboot-gerrit mailing list