x86: ivybridge: Add early init for PCH devices

Many PCH devices are hard-coded to a particular PCI address. Set these
up early in case they are needed.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
index 74f01e8..e5c0751 100644
--- a/arch/x86/cpu/ivybridge/Makefile
+++ b/arch/x86/cpu/ivybridge/Makefile
@@ -6,6 +6,7 @@
 
 obj-y += car.o
 obj-y += cpu.o
+obj-y += early_init.o
 obj-y += lpc.o
 obj-y += microcode_intel.o
 obj-y += pci.o
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index 0aca2f0..d5be2f5 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -4,6 +4,7 @@
  * Graeme Russ, graeme.russ@gmail.com.
  *
  * Some portions from coreboot src/mainboard/google/link/romstage.c
+ * and src/cpu/intel/model_206ax/bootblock.c
  * Copyright (C) 2007-2010 coresystems GmbH
  * Copyright (C) 2011 Google Inc.
  *
@@ -23,6 +24,7 @@
 #include <asm/arch/model_206ax.h>
 #include <asm/arch/microcode.h>
 #include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -180,6 +182,83 @@
 	return 0;
 }
 
+static int enable_smbus(void)
+{
+	pci_dev_t dev;
+	uint16_t value;
+
+	/* Set the SMBus device statically. */
+	dev = PCI_BDF(0x0, 0x1f, 0x3);
+
+	/* Check to make sure we've got the right device. */
+	value = pci_read_config16(dev, 0x0);
+	if (value != 0x8086) {
+		printf("SMBus controller not found\n");
+		return -ENOSYS;
+	}
+
+	/* Set SMBus I/O base. */
+	pci_write_config32(dev, SMB_BASE,
+			   SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
+
+	/* Set SMBus enable. */
+	pci_write_config8(dev, HOSTC, HST_EN);
+
+	/* Set SMBus I/O space enable. */
+	pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
+
+	/* Disable interrupt generation. */
+	outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* Clear any lingering errors, so transactions can run. */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+	debug("SMBus controller enabled\n");
+
+	return 0;
+}
+
+#define PCH_EHCI0_TEMP_BAR0 0xe8000000
+#define PCH_EHCI1_TEMP_BAR0 0xe8000400
+#define PCH_XHCI_TEMP_BAR0  0xe8001000
+
+/*
+ * Setup USB controller MMIO BAR to prevent the reference code from
+ * resetting the controller.
+ *
+ * The BAR will be re-assigned during device enumeration so these are only
+ * temporary.
+ *
+ * This is used to speed up the resume path.
+ */
+static void enable_usb_bar(void)
+{
+	pci_dev_t usb0 = PCH_EHCI1_DEV;
+	pci_dev_t usb1 = PCH_EHCI2_DEV;
+	pci_dev_t usb3 = PCH_XHCI_DEV;
+	u32 cmd;
+
+	/* USB Controller 1 */
+	pci_write_config32(usb0, PCI_BASE_ADDRESS_0,
+			   PCH_EHCI0_TEMP_BAR0);
+	cmd = pci_read_config32(usb0, PCI_COMMAND);
+	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config32(usb0, PCI_COMMAND, cmd);
+
+	/* USB Controller 1 */
+	pci_write_config32(usb1, PCI_BASE_ADDRESS_0,
+			   PCH_EHCI1_TEMP_BAR0);
+	cmd = pci_read_config32(usb1, PCI_COMMAND);
+	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config32(usb1, PCI_COMMAND, cmd);
+
+	/* USB3 Controller */
+	pci_write_config32(usb3, PCI_BASE_ADDRESS_0,
+			   PCH_XHCI_TEMP_BAR0);
+	cmd = pci_read_config32(usb3, PCI_COMMAND);
+	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config32(usb3, PCI_COMMAND, cmd);
+}
+
 static int report_bist_failure(void)
 {
 	if (gd->arch.bist != 0) {
@@ -192,8 +271,11 @@
 
 int print_cpuinfo(void)
 {
+	enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
 	char processor_name[CPU_MAX_NAME_LEN];
 	const char *name;
+	uint32_t pm1_cnt;
+	uint16_t pm1_sts;
 	int ret;
 
 	/* Halt if there was a built in self test failure */
@@ -205,9 +287,68 @@
 	if (ret && ret != -ENOENT && ret != -EEXIST)
 		return ret;
 
+	/* Enable upper 128bytes of CMOS */
+	writel(1 << 2, RCB_REG(RC));
+
+	/* TODO: cmos_post_init() */
+	if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
+		debug("soft reset detected\n");
+		boot_mode = PEI_BOOT_SOFT_RESET;
+
+		/* System is not happy after keyboard reset... */
+		debug("Issuing CF9 warm reset\n");
+		outb(0x6, 0xcf9);
+		cpu_hlt();
+	}
+
+	/* Early chipset init required before RAM init can work */
+	sandybridge_early_init(SANDYBRIDGE_MOBILE);
+
+	/* Check PM1_STS[15] to see if we are waking from Sx */
+	pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
+
+	/* Read PM1_CNT[12:10] to determine which Sx state */
+	pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
+
+	if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
+#if CONFIG_HAVE_ACPI_RESUME
+		debug("Resume from S3 detected.\n");
+		boot_mode = PEI_BOOT_RESUME;
+		/* Clear SLP_TYPE. This will break stage2 but
+		 * we care for that when we get there.
+		 */
+		outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT);
+#else
+		debug("Resume from S3 detected, but disabled.\n");
+#endif
+	} else {
+		/*
+		 * TODO: An indication of life might be possible here (e.g.
+		 * keyboard light)
+		 */
+	}
+	post_code(POST_EARLY_INIT);
+
+	/* Enable SPD ROMs and DDR-III DRAM */
+	ret = enable_smbus();
+	if (ret)
+		return ret;
+
+	/* Prepare USB controller early in S3 resume */
+	if (boot_mode == PEI_BOOT_RESUME)
+		enable_usb_bar();
+
+	gd->arch.pei_boot_mode = boot_mode;
+
+	/* TODO: Move this to the board or driver */
+	pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1);
+	pci_write_config32(PCH_LPC_DEV, GPIO_CNTL, 0x10);
+
 	/* Print processor name */
 	name = cpu_get_name(processor_name);
 	printf("CPU:   %s\n", name);
 
+	post_code(POST_CPU_INFO);
+
 	return 0;
 }
diff --git a/arch/x86/cpu/ivybridge/early_init.c b/arch/x86/cpu/ivybridge/early_init.c
new file mode 100644
index 0000000..eb8f613
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/early_init.c
@@ -0,0 +1,145 @@
+/*
+ * From Coreboot
+ *
+ * Copyright (C) 2007-2010 coresystems GmbH
+ * Copyright (C) 2011 Google Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+
+static void sandybridge_setup_bars(pci_dev_t pch_dev, pci_dev_t lpc_dev)
+{
+	/* Setting up Southbridge. In the northbridge code. */
+	debug("Setting up static southbridge registers\n");
+	pci_write_config32(lpc_dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
+
+	pci_write_config32(lpc_dev, PMBASE, DEFAULT_PMBASE | 1);
+	pci_write_config8(lpc_dev, ACPI_CNTL, 0x80); /* Enable ACPI BAR */
+
+	debug("Disabling watchdog reboot\n");
+	setbits_le32(RCB_REG(GCS), 1 >> 5);	/* No reset */
+	outw(1 << 11, DEFAULT_PMBASE | 0x60 | 0x08);	/* halt timer */
+
+	/* Set up all hardcoded northbridge BARs */
+	debug("Setting up static registers\n");
+	pci_write_config32(pch_dev, EPBAR, DEFAULT_EPBAR | 1);
+	pci_write_config32(pch_dev, EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32);
+	pci_write_config32(pch_dev, MCHBAR, DEFAULT_MCHBAR | 1);
+	pci_write_config32(pch_dev, MCHBAR + 4, (0LL + DEFAULT_MCHBAR) >> 32);
+	/* 64MB - busses 0-63 */
+	pci_write_config32(pch_dev, PCIEXBAR, DEFAULT_PCIEXBAR | 5);
+	pci_write_config32(pch_dev, PCIEXBAR + 4,
+			   (0LL + DEFAULT_PCIEXBAR) >> 32);
+	pci_write_config32(pch_dev, DMIBAR, DEFAULT_DMIBAR | 1);
+	pci_write_config32(pch_dev, DMIBAR + 4, (0LL + DEFAULT_DMIBAR) >> 32);
+
+	/* Set C0000-FFFFF to access RAM on both reads and writes */
+	pci_write_config8(pch_dev, PAM0, 0x30);
+	pci_write_config8(pch_dev, PAM1, 0x33);
+	pci_write_config8(pch_dev, PAM2, 0x33);
+	pci_write_config8(pch_dev, PAM3, 0x33);
+	pci_write_config8(pch_dev, PAM4, 0x33);
+	pci_write_config8(pch_dev, PAM5, 0x33);
+	pci_write_config8(pch_dev, PAM6, 0x33);
+}
+
+static void sandybridge_setup_graphics(pci_dev_t pch_dev, pci_dev_t video_dev)
+{
+	u32 reg32;
+	u16 reg16;
+	u8 reg8;
+
+	reg16 = pci_read_config16(video_dev, PCI_DEVICE_ID);
+	switch (reg16) {
+	case 0x0102: /* GT1 Desktop */
+	case 0x0106: /* GT1 Mobile */
+	case 0x010a: /* GT1 Server */
+	case 0x0112: /* GT2 Desktop */
+	case 0x0116: /* GT2 Mobile */
+	case 0x0122: /* GT2 Desktop >=1.3GHz */
+	case 0x0126: /* GT2 Mobile >=1.3GHz */
+	case 0x0156: /* IvyBridge */
+	case 0x0166: /* IvyBridge */
+		break;
+	default:
+		debug("Graphics not supported by this CPU/chipset\n");
+		return;
+	}
+
+	debug("Initialising Graphics\n");
+
+	/* Setup IGD memory by setting GGC[7:3] = 1 for 32MB */
+	reg16 = pci_read_config16(pch_dev, GGC);
+	reg16 &= ~0x00f8;
+	reg16 |= 1 << 3;
+	/* Program GTT memory by setting GGC[9:8] = 2MB */
+	reg16 &= ~0x0300;
+	reg16 |= 2 << 8;
+	/* Enable VGA decode */
+	reg16 &= ~0x0002;
+	pci_write_config16(pch_dev, GGC, reg16);
+
+	/* Enable 256MB aperture */
+	reg8 = pci_read_config8(video_dev, MSAC);
+	reg8 &= ~0x06;
+	reg8 |= 0x02;
+	pci_write_config8(video_dev, MSAC, reg8);
+
+	/* Erratum workarounds */
+	reg32 = readl(MCHBAR_REG(0x5f00));
+	reg32 |= (1 << 9) | (1 << 10);
+	writel(reg32, MCHBAR_REG(0x5f00));
+
+	/* Enable SA Clock Gating */
+	reg32 = readl(MCHBAR_REG(0x5f00));
+	writel(reg32 | 1, MCHBAR_REG(0x5f00));
+
+	/* GPU RC6 workaround for sighting 366252 */
+	reg32 = readl(MCHBAR_REG(0x5d14));
+	reg32 |= (1 << 31);
+	writel(reg32, MCHBAR_REG(0x5d14));
+
+	/* VLW */
+	reg32 = readl(MCHBAR_REG(0x6120));
+	reg32 &= ~(1 << 0);
+	writel(reg32, MCHBAR_REG(0x6120));
+
+	reg32 = readl(MCHBAR_REG(0x5418));
+	reg32 |= (1 << 4) | (1 << 5);
+	writel(reg32, MCHBAR_REG(0x5418));
+}
+
+void sandybridge_early_init(int chipset_type)
+{
+	pci_dev_t pch_dev = PCH_DEV;
+	pci_dev_t video_dev = PCH_VIDEO_DEV;
+	pci_dev_t lpc_dev = PCH_LPC_DEV;
+	u32 capid0_a;
+	u8 reg8;
+
+	/* Device ID Override Enable should be done very early */
+	capid0_a = pci_read_config32(pch_dev, 0xe4);
+	if (capid0_a & (1 << 10)) {
+		reg8 = pci_read_config8(pch_dev, 0xf3);
+		reg8 &= ~7; /* Clear 2:0 */
+
+		if (chipset_type == SANDYBRIDGE_MOBILE)
+			reg8 |= 1; /* Set bit 0 */
+
+		pci_write_config8(pch_dev, 0xf3, reg8);
+	}
+
+	/* Setup all BARs required for early PCIe and raminit */
+	sandybridge_setup_bars(pch_dev, lpc_dev);
+
+	/* Device Enable */
+	pci_write_config32(pch_dev, DEVEN, DEVEN_HOST | DEVEN_IGD);
+
+	sandybridge_setup_graphics(pch_dev, video_dev);
+}
diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
index c572f76..290a737 100644
--- a/arch/x86/include/asm/arch-ivybridge/pch.h
+++ b/arch/x86/include/asm/arch-ivybridge/pch.h
@@ -14,9 +14,30 @@
 
 #include <pci.h>
 
+#define DEFAULT_GPIOBASE	0x0480
+#define DEFAULT_PMBASE		0x0500
+
+#define SMBUS_IO_BASE		0x0400
+
+#define PCH_EHCI1_DEV		PCI_BDF(0, 0x1d, 0)
+#define PCH_EHCI2_DEV		PCI_BDF(0, 0x1a, 0)
+#define PCH_XHCI_DEV		PCI_BDF(0, 0x14, 0)
+#define PCH_ME_DEV		PCI_BDF(0, 0x16, 0)
+#define PCH_PCIE_DEV_SLOT	28
+
+#define PCH_DEV			PCI_BDF(0, 0, 0)
+#define PCH_VIDEO_DEV		PCI_BDF(0, 2, 0)
+
 /* PCI Configuration Space (D31:F0): LPC */
 #define PCH_LPC_DEV		PCI_BDF(0, 0x1f, 0)
 
+#define PMBASE			0x40
+#define ACPI_CNTL		0x44
+#define BIOS_CNTL		0xDC
+#define GPIO_BASE		0x48 /* LPC GPIO Base Address Register */
+#define GPIO_CNTL		0x4C /* LPC GPIO Control Register */
+#define GPIO_ROUT		0xb8
+
 #define LPC_IO_DEC		0x80 /* IO Decode Ranges Register */
 #define LPC_EN			0x82 /* LPC IF Enables Register */
 #define  CNF2_LPC_EN		(1 << 13) /* 0x4e/0x4f */
@@ -35,9 +56,35 @@
 #define LPC_GEN4_DEC		0x90 /* LPC IF Generic Decode Range 4 */
 #define LPC_GENX_DEC(x)		(0x84 + 4 * (x))
 
-#define DEFAULT_RCBA		0xfed1c000
+/* PCI Configuration Space (D31:F3): SMBus */
+#define PCH_SMBUS_DEV		PCI_BDF(0, 0x1f, 3)
+#define SMB_BASE		0x20
+#define HOSTC			0x40
+#define SMB_RCV_SLVA		0x09
+
+/* HOSTC bits */
+#define I2C_EN			(1 << 2)
+#define SMB_SMI_EN		(1 << 1)
+#define HST_EN			(1 << 0)
+
+/* SMBus I/O bits. */
+#define SMBHSTSTAT		0x0
+#define SMBHSTCTL		0x2
+#define SMBHSTCMD		0x3
+#define SMBXMITADD		0x4
+#define SMBHSTDAT0		0x5
+#define SMBHSTDAT1		0x6
+#define SMBBLKDAT		0x7
+#define SMBTRNSADD		0x9
+#define SMBSLVDATA		0xa
+#define SMLINK_PIN_CTL		0xe
+#define SMBUS_PIN_CTL		0xf
+
+#define SMBUS_TIMEOUT		(10 * 1000 * 100)
+
 
 /* Root Complex Register Block */
+#define DEFAULT_RCBA		0xfed1c000
 #define RCB_REG(reg)		(DEFAULT_RCBA + (reg))
 
 #define PCH_RCBA_BASE		0xf0
@@ -95,6 +142,78 @@
 #define FD2		0x3428	/* 32bit */
 #define CG		0x341c	/* 32bit */
 
+/* ICH7 PMBASE */
+#define PM1_STS		0x00
+#define   WAK_STS	(1 << 15)
+#define   PCIEXPWAK_STS	(1 << 14)
+#define   PRBTNOR_STS	(1 << 11)
+#define   RTC_STS	(1 << 10)
+#define   PWRBTN_STS	(1 << 8)
+#define   GBL_STS	(1 << 5)
+#define   BM_STS	(1 << 4)
+#define   TMROF_STS	(1 << 0)
+#define PM1_EN		0x02
+#define   PCIEXPWAK_DIS	(1 << 14)
+#define   RTC_EN	(1 << 10)
+#define   PWRBTN_EN	(1 << 8)
+#define   GBL_EN	(1 << 5)
+#define   TMROF_EN	(1 << 0)
+#define PM1_CNT		0x04
+#define   SLP_EN	(1 << 13)
+#define   SLP_TYP	(7 << 10)
+#define    SLP_TYP_S0	0
+#define    SLP_TYP_S1	1
+#define    SLP_TYP_S3	5
+#define    SLP_TYP_S4	6
+#define    SLP_TYP_S5	7
+#define   GBL_RLS	(1 << 2)
+#define   BM_RLD	(1 << 1)
+#define   SCI_EN	(1 << 0)
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define LV4		0x16
+#define PM2_CNT		0x50 /* mobile only */
+#define GPE0_STS	0x20
+#define   PME_B0_STS	(1 << 13)
+#define   PME_STS	(1 << 11)
+#define   BATLOW_STS	(1 << 10)
+#define   PCI_EXP_STS	(1 << 9)
+#define   RI_STS	(1 << 8)
+#define   SMB_WAK_STS	(1 << 7)
+#define   TCOSCI_STS	(1 << 6)
+#define   SWGPE_STS	(1 << 2)
+#define   HOT_PLUG_STS	(1 << 1)
+#define GPE0_EN		0x28
+#define   PME_B0_EN	(1 << 13)
+#define   PME_EN	(1 << 11)
+#define   TCOSCI_EN	(1 << 6)
+#define SMI_EN		0x30
+#define   INTEL_USB2_EN	 (1 << 18) /* Intel-Specific USB2 SMI logic */
+#define   LEGACY_USB2_EN (1 << 17) /* Legacy USB2 SMI logic */
+#define   PERIODIC_EN	 (1 << 14) /* SMI on PERIODIC_STS in SMI_STS */
+#define   TCO_EN	 (1 << 13) /* Enable TCO Logic (BIOSWE et al) */
+#define   MCSMI_EN	 (1 << 11) /* Trap microcontroller range access */
+#define   BIOS_RLS	 (1 <<  7) /* asserts SCI on bit set */
+#define   SWSMI_TMR_EN	 (1 <<  6) /* start software smi timer on bit set */
+#define   APMC_EN	 (1 <<  5) /* Writes to APM_CNT cause SMI# */
+#define   SLP_SMI_EN	 (1 <<  4) /* Write SLP_EN in PM1_CNT asserts SMI# */
+#define   LEGACY_USB_EN  (1 <<  3) /* Legacy USB circuit SMI logic */
+#define   BIOS_EN	 (1 <<  2) /* Assert SMI# on setting GBL_RLS bit */
+#define   EOS		 (1 <<  1) /* End of SMI (deassert SMI#) */
+#define   GBL_SMI_EN	 (1 <<  0) /* SMI# generation at all? */
+#define SMI_STS		0x34
+#define ALT_GP_SMI_EN	0x38
+#define ALT_GP_SMI_STS	0x3a
+#define GPE_CNTL	0x42
+#define DEVACT_STS	0x44
+#define SS_CNT		0x50
+#define C3_RES		0x54
+#define TCO1_STS	0x64
+#define   DMISCI_STS	(1 << 9)
+#define TCO2_STS	0x66
+
 /**
  * lpc_early_init() - set up LPC serial ports and other early things
  *
diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
new file mode 100644
index 0000000..a1072f2
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ACH_ASM_SANDYBRIDGE_H
+#define _ACH_ASM_SANDYBRIDGE_H
+
+/* Chipset types */
+#define SANDYBRIDGE_MOBILE	0
+#define SANDYBRIDGE_DESKTOP	1
+#define SANDYBRIDGE_SERVER	2
+
+/* Device ID for SandyBridge and IvyBridge */
+#define BASE_REV_SNB	0x00
+#define BASE_REV_IVB	0x50
+#define BASE_REV_MASK	0x50
+
+/* SandyBridge CPU stepping */
+#define SNB_STEP_D0	(BASE_REV_SNB + 5) /* Also J0 */
+#define SNB_STEP_D1	(BASE_REV_SNB + 6)
+#define SNB_STEP_D2	(BASE_REV_SNB + 7) /* Also J1/Q0 */
+
+/* IvyBridge CPU stepping */
+#define IVB_STEP_A0	(BASE_REV_IVB + 0)
+#define IVB_STEP_B0	(BASE_REV_IVB + 2)
+#define IVB_STEP_C0	(BASE_REV_IVB + 4)
+#define IVB_STEP_K0	(BASE_REV_IVB + 5)
+#define IVB_STEP_D0	(BASE_REV_IVB + 6)
+
+/* Intel Enhanced Debug region must be 4MB */
+#define IED_SIZE	0x400000
+
+/* Northbridge BARs */
+#define DEFAULT_MCHBAR		0xfed10000	/* 16 KB */
+#define DEFAULT_DMIBAR		0xfed18000	/* 4 KB */
+#define DEFAULT_EPBAR		0xfed19000	/* 4 KB */
+#define DEFAULT_RCBABASE	0xfed1c000
+/* 4 KB per PCIe device */
+#define DEFAULT_PCIEXBAR	CONFIG_MMCONF_BASE_ADDRESS
+
+/* Device 0:0.0 PCI configuration space (Host Bridge) */
+#define EPBAR		0x40
+#define MCHBAR		0x48
+#define PCIEXBAR	0x60
+#define DMIBAR		0x68
+#define X60BAR		0x60
+
+#define GGC		0x50			/* GMCH Graphics Control */
+
+#define DEVEN		0x54			/* Device Enable */
+#define  DEVEN_PEG60	(1 << 13)
+#define  DEVEN_IGD	(1 << 4)
+#define  DEVEN_PEG10	(1 << 3)
+#define  DEVEN_PEG11	(1 << 2)
+#define  DEVEN_PEG12	(1 << 1)
+#define  DEVEN_HOST	(1 << 0)
+
+#define PAM0		0x80
+#define PAM1		0x81
+#define PAM2		0x82
+#define PAM3		0x83
+#define PAM4		0x84
+#define PAM5		0x85
+#define PAM6		0x86
+
+#define LAC		0x87	/* Legacy Access Control */
+#define SMRAM		0x88	/* System Management RAM Control */
+#define  D_OPEN		(1 << 6)
+#define  D_CLS		(1 << 5)
+#define  D_LCK		(1 << 4)
+#define  G_SMRAME	(1 << 3)
+#define  C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
+
+#define TOM		0xa0
+#define TOUUD		0xa8	/* Top of Upper Usable DRAM */
+#define TSEG		0xb8	/* TSEG base */
+#define TOLUD		0xbc	/* Top of Low Used Memory */
+
+#define SKPAD		0xdc	/* Scratchpad Data */
+
+/* Device 0:1.0 PCI configuration space (PCI Express) */
+#define BCTRL1		0x3e	/* 16bit */
+
+/* Device 0:2.0 PCI configuration space (Graphics Device) */
+
+#define MSAC		0x62	/* Multi Size Aperture Control */
+#define SWSCI		0xe8	/* SWSCI  enable */
+#define ASLS		0xfc	/* OpRegion Base */
+
+/*
+ * MCHBAR
+ */
+#define MCHBAR_REG(reg)		(DEFAULT_RCBA + (reg))
+
+#define SSKPD		0x5d14	/* 16bit (scratchpad) */
+#define BIOS_RESET_CPL	0x5da8	/* 8bit */
+
+void sandybridge_early_init(int chipset_type);
+
+#endif
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index d32987b..ff9574c 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -10,6 +10,13 @@
 
 #ifndef __ASSEMBLY__
 
+enum pei_boot_mode_t {
+	PEI_BOOT_NONE = 0,
+	PEI_BOOT_SOFT_RESET,
+	PEI_BOOT_RESUME,
+
+};
+
 /* Architecture-specific global data */
 struct arch_global_data {
 	struct global_data *gd_addr;		/* Location of Global Data */
@@ -25,6 +32,7 @@
 	void *new_fdt;			/* Relocated FDT */
 	uint32_t bist;			/* Built-in self test value */
 	struct pci_controller *hose;	/* PCI hose for early use */
+	enum pei_boot_mode_t pei_boot_mode;
 };
 
 #endif
diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h
index b203dc9..61dcda1 100644
--- a/arch/x86/include/asm/post.h
+++ b/arch/x86/include/asm/post.h
@@ -25,6 +25,8 @@
 #define POST_START_STACK	0x29
 #define POST_START_DONE		0x2a
 #define POST_CPU_INIT		0x2b
+#define POST_EARLY_INIT		0x2c
+#define POST_CPU_INFO		0x2d
 
 /* Output a post code using al - value must be 0 to 0xff */
 #ifdef __ASSEMBLY__