int
        default 36
 
+config HPET_ADDRESS
+       hex
+       default 0xfed00000 if !HPET_ADDRESS_OVERRIDE
+
+config SMM_TSEG
+       bool
+       default n
+
+config SMM_TSEG_SIZE
+       hex
+
 config ROM_SIZE
        hex
        default 0x800000
          SPI flash format. You will need to supply the me.bin file in
          your board directory.
 
+config X86_RAMTEST
+       bool "Perform a simple RAM test after SDRAM initialisation"
+       help
+         If there is something wrong with SDRAM then the platform will
+         often crash within U-Boot or the kernel. This option enables a
+         very simple RAM test that quickly checks whether the SDRAM seems
+         to work correctly. It is not exhaustive but can save time by
+         detecting obvious failures.
+
 source "arch/x86/cpu/ivybridge/Kconfig"
 
 source "board/chromebook-x86/coreboot/Kconfig"
 
        select CPU_MICROCODE_IN_CBFS
        select TSC_SYNC_MFENCE
        select HAVE_INTEL_ME
+       select X86_RAMTEST
 
 config SMM_TSEG_SIZE
        hex
 
 obj-y += car.o
 obj-y += cpu.o
 obj-y += early_init.o
+obj-y += early_me.o
 obj-y += lpc.o
+obj-y += me_status.o
 obj-y += microcode_intel.o
 obj-y += pci.o
+obj-y += report_platform.o
 obj-y += sdram.o
 
--- /dev/null
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/early_me.c
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/arch/me.h>
+#include <asm/arch/pch.h>
+#include <asm/io.h>
+
+static const char *const me_ack_values[] = {
+       [ME_HFS_ACK_NO_DID]     = "No DID Ack received",
+       [ME_HFS_ACK_RESET]      = "Non-power cycle reset",
+       [ME_HFS_ACK_PWR_CYCLE]  = "Power cycle reset",
+       [ME_HFS_ACK_S3]         = "Go to S3",
+       [ME_HFS_ACK_S4]         = "Go to S4",
+       [ME_HFS_ACK_S5]         = "Go to S5",
+       [ME_HFS_ACK_GBL_RESET]  = "Global Reset",
+       [ME_HFS_ACK_CONTINUE]   = "Continue to boot"
+};
+
+static inline void pci_read_dword_ptr(void *ptr, int offset)
+{
+       u32 dword;
+
+       dword = pci_read_config32(PCH_ME_DEV, offset);
+       memcpy(ptr, &dword, sizeof(dword));
+}
+
+static inline void pci_write_dword_ptr(void *ptr, int offset)
+{
+       u32 dword = 0;
+       memcpy(&dword, ptr, sizeof(dword));
+       pci_write_config32(PCH_ME_DEV, offset, dword);
+}
+
+void intel_early_me_status(void)
+{
+       struct me_hfs hfs;
+       struct me_gmes gmes;
+
+       pci_read_dword_ptr(&hfs, PCI_ME_HFS);
+       pci_read_dword_ptr(&gmes, PCI_ME_GMES);
+
+       intel_me_status(&hfs, &gmes);
+}
+
+int intel_early_me_init(void)
+{
+       int count;
+       struct me_uma uma;
+       struct me_hfs hfs;
+
+       debug("Intel ME early init\n");
+
+       /* Wait for ME UMA SIZE VALID bit to be set */
+       for (count = ME_RETRY; count > 0; --count) {
+               pci_read_dword_ptr(&uma, PCI_ME_UMA);
+               if (uma.valid)
+                       break;
+               udelay(ME_DELAY);
+       }
+       if (!count) {
+               printf("ERROR: ME is not ready!\n");
+               return -EBUSY;
+       }
+
+       /* Check for valid firmware */
+       pci_read_dword_ptr(&hfs, PCI_ME_HFS);
+       if (hfs.fpt_bad) {
+               printf("WARNING: ME has bad firmware\n");
+               return -EBADF;
+       }
+
+       debug("Intel ME firmware is ready\n");
+
+       return 0;
+}
+
+int intel_early_me_uma_size(void)
+{
+       struct me_uma uma;
+
+       pci_read_dword_ptr(&uma, PCI_ME_UMA);
+       if (uma.valid) {
+               debug("ME: Requested %uMB UMA\n", uma.size);
+               return uma.size;
+       }
+
+       debug("ME: Invalid UMA size\n");
+       return -EINVAL;
+}
+
+static inline void set_global_reset(int enable)
+{
+       u32 etr3;
+
+       etr3 = pci_read_config32(PCH_LPC_DEV, ETR3);
+
+       /* Clear CF9 Without Resume Well Reset Enable */
+       etr3 &= ~ETR3_CWORWRE;
+
+       /* CF9GR indicates a Global Reset */
+       if (enable)
+               etr3 |= ETR3_CF9GR;
+       else
+               etr3 &= ~ETR3_CF9GR;
+
+       pci_write_config32(PCH_LPC_DEV, ETR3, etr3);
+}
+
+int intel_early_me_init_done(u8 status)
+{
+       u8 reset;
+       int count;
+       u32 mebase_l, mebase_h;
+       struct me_hfs hfs;
+       struct me_did did = {
+               .init_done = ME_INIT_DONE,
+               .status = status
+       };
+
+       /* MEBASE from MESEG_BASE[35:20] */
+       mebase_l = pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_L);
+       mebase_h = pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_H);
+       mebase_h &= 0xf;
+       did.uma_base = (mebase_l >> 20) | (mebase_h << 12);
+
+       /* Send message to ME */
+       debug("ME: Sending Init Done with status: %d, UMA base: 0x%04x\n",
+             status, did.uma_base);
+
+       pci_write_dword_ptr(&did, PCI_ME_H_GS);
+
+       /* Must wait for ME acknowledgement */
+       for (count = ME_RETRY; count > 0; --count) {
+               pci_read_dword_ptr(&hfs, PCI_ME_HFS);
+               if (hfs.bios_msg_ack)
+                       break;
+               udelay(ME_DELAY);
+       }
+       if (!count) {
+               printf("ERROR: ME failed to respond\n");
+               return -1;
+       }
+
+       /* Return the requested BIOS action */
+       debug("ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]);
+
+       /* Check status after acknowledgement */
+       intel_early_me_status();
+
+       reset = 0;
+       switch (hfs.ack_data) {
+       case ME_HFS_ACK_CONTINUE:
+               /* Continue to boot */
+               return 0;
+       case ME_HFS_ACK_RESET:
+               /* Non-power cycle reset */
+               set_global_reset(0);
+               reset = 0x06;
+               break;
+       case ME_HFS_ACK_PWR_CYCLE:
+               /* Power cycle reset */
+               set_global_reset(0);
+               reset = 0x0e;
+               break;
+       case ME_HFS_ACK_GBL_RESET:
+               /* Global reset */
+               set_global_reset(1);
+               reset = 0x0e;
+               break;
+       case ME_HFS_ACK_S3:
+       case ME_HFS_ACK_S4:
+       case ME_HFS_ACK_S5:
+               break;
+       }
+
+       /* Perform the requested reset */
+       if (reset) {
+               outb(reset, 0xcf9);
+               cpu_hlt();
+       }
+       return -1;
+}
 
--- /dev/null
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/me_status.c
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/arch/me.h>
+
+/* HFS1[3:0] Current Working State Values */
+static const char *const me_cws_values[] = {
+       [ME_HFS_CWS_RESET]      = "Reset",
+       [ME_HFS_CWS_INIT]       = "Initializing",
+       [ME_HFS_CWS_REC]        = "Recovery",
+       [ME_HFS_CWS_NORMAL]     = "Normal",
+       [ME_HFS_CWS_WAIT]       = "Platform Disable Wait",
+       [ME_HFS_CWS_TRANS]      = "OP State Transition",
+       [ME_HFS_CWS_INVALID]    = "Invalid CPU Plugged In"
+};
+
+/* HFS1[8:6] Current Operation State Values */
+static const char *const me_opstate_values[] = {
+       [ME_HFS_STATE_PREBOOT]  = "Preboot",
+       [ME_HFS_STATE_M0_UMA]   = "M0 with UMA",
+       [ME_HFS_STATE_M3]       = "M3 without UMA",
+       [ME_HFS_STATE_M0]       = "M0 without UMA",
+       [ME_HFS_STATE_BRINGUP]  = "Bring up",
+       [ME_HFS_STATE_ERROR]    = "M0 without UMA but with error"
+};
+
+/* HFS[19:16] Current Operation Mode Values */
+static const char *const me_opmode_values[] = {
+       [ME_HFS_MODE_NORMAL]    = "Normal",
+       [ME_HFS_MODE_DEBUG]     = "Debug",
+       [ME_HFS_MODE_DIS]       = "Soft Temporary Disable",
+       [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper",
+       [ME_HFS_MODE_OVER_MEI]  = "Security Override via MEI Message"
+};
+
+/* HFS[15:12] Error Code Values */
+static const char *const me_error_values[] = {
+       [ME_HFS_ERROR_NONE]     = "No Error",
+       [ME_HFS_ERROR_UNCAT]    = "Uncategorized Failure",
+       [ME_HFS_ERROR_IMAGE]    = "Image Failure",
+       [ME_HFS_ERROR_DEBUG]    = "Debug Failure"
+};
+
+/* GMES[31:28] ME Progress Code */
+static const char *const me_progress_values[] = {
+       [ME_GMES_PHASE_ROM]     = "ROM Phase",
+       [ME_GMES_PHASE_BUP]     = "BUP Phase",
+       [ME_GMES_PHASE_UKERNEL] = "uKernel Phase",
+       [ME_GMES_PHASE_POLICY]  = "Policy Module",
+       [ME_GMES_PHASE_MODULE]  = "Module Loading",
+       [ME_GMES_PHASE_UNKNOWN] = "Unknown",
+       [ME_GMES_PHASE_HOST]    = "Host Communication"
+};
+
+/* GMES[27:24] Power Management Event */
+static const char *const me_pmevent_values[] = {
+       [0x00] = "Clean Moff->Mx wake",
+       [0x01] = "Moff->Mx wake after an error",
+       [0x02] = "Clean global reset",
+       [0x03] = "Global reset after an error",
+       [0x04] = "Clean Intel ME reset",
+       [0x05] = "Intel ME reset due to exception",
+       [0x06] = "Pseudo-global reset",
+       [0x07] = "S0/M0->Sx/M3",
+       [0x08] = "Sx/M3->S0/M0",
+       [0x09] = "Non-power cycle reset",
+       [0x0a] = "Power cycle reset through M3",
+       [0x0b] = "Power cycle reset through Moff",
+       [0x0c] = "Sx/Mx->Sx/Moff"
+};
+
+/* Progress Code 0 states */
+static const char *const me_progress_rom_values[] = {
+       [0x00] = "BEGIN",
+       [0x06] = "DISABLE"
+};
+
+/* Progress Code 1 states */
+static const char *const me_progress_bup_values[] = {
+       [0x00] = "Initialization starts",
+       [0x01] = "Disable the host wake event",
+       [0x04] = "Flow determination start process",
+       [0x08] = "Error reading/matching the VSCC table in the descriptor",
+       [0x0a] = "Check to see if straps say ME DISABLED",
+       [0x0b] = "Timeout waiting for PWROK",
+       [0x0d] = "Possibly handle BUP manufacturing override strap",
+       [0x11] = "Bringup in M3",
+       [0x12] = "Bringup in M0",
+       [0x13] = "Flow detection error",
+       [0x15] = "M3 clock switching error",
+       [0x18] = "M3 kernel load",
+       [0x1c] = "T34 missing - cannot program ICC",
+       [0x1f] = "Waiting for DID BIOS message",
+       [0x20] = "Waiting for DID BIOS message failure",
+       [0x21] = "DID reported an error",
+       [0x22] = "Enabling UMA",
+       [0x23] = "Enabling UMA error",
+       [0x24] = "Sending DID Ack to BIOS",
+       [0x25] = "Sending DID Ack to BIOS error",
+       [0x26] = "Switching clocks in M0",
+       [0x27] = "Switching clocks in M0 error",
+       [0x28] = "ME in temp disable",
+       [0x32] = "M0 kernel load",
+};
+
+/* Progress Code 3 states */
+static const char *const me_progress_policy_values[] = {
+       [0x00] = "Entery into Policy Module",
+       [0x03] = "Received S3 entry",
+       [0x04] = "Received S4 entry",
+       [0x05] = "Received S5 entry",
+       [0x06] = "Received UPD entry",
+       [0x07] = "Received PCR entry",
+       [0x08] = "Received NPCR entry",
+       [0x09] = "Received host wake",
+       [0x0a] = "Received AC<>DC switch",
+       [0x0b] = "Received DRAM Init Done",
+       [0x0c] = "VSCC Data not found for flash device",
+       [0x0d] = "VSCC Table is not valid",
+       [0x0e] = "Flash Partition Boundary is outside address space",
+       [0x0f] = "ME cannot access the chipset descriptor region",
+       [0x10] = "Required VSCC values for flash parts do not match",
+};
+
+void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes)
+{
+       /* Check Current States */
+       debug("ME: FW Partition Table      : %s\n",
+             hfs->fpt_bad ? "BAD" : "OK");
+       debug("ME: Bringup Loader Failure  : %s\n",
+             hfs->ft_bup_ld_flr ? "YES" : "NO");
+       debug("ME: Firmware Init Complete  : %s\n",
+             hfs->fw_init_complete ? "YES" : "NO");
+       debug("ME: Manufacturing Mode      : %s\n",
+             hfs->mfg_mode ? "YES" : "NO");
+       debug("ME: Boot Options Present    : %s\n",
+             hfs->boot_options_present ? "YES" : "NO");
+       debug("ME: Update In Progress      : %s\n",
+             hfs->update_in_progress ? "YES" : "NO");
+       debug("ME: Current Working State   : %s\n",
+             me_cws_values[hfs->working_state]);
+       debug("ME: Current Operation State : %s\n",
+             me_opstate_values[hfs->operation_state]);
+       debug("ME: Current Operation Mode  : %s\n",
+             me_opmode_values[hfs->operation_mode]);
+       debug("ME: Error Code              : %s\n",
+             me_error_values[hfs->error_code]);
+       debug("ME: Progress Phase          : %s\n",
+             me_progress_values[gmes->progress_code]);
+       debug("ME: Power Management Event  : %s\n",
+             me_pmevent_values[gmes->current_pmevent]);
+
+       debug("ME: Progress Phase State    : ");
+       switch (gmes->progress_code) {
+       case ME_GMES_PHASE_ROM:         /* ROM Phase */
+               debug("%s", me_progress_rom_values[gmes->current_state]);
+               break;
+
+       case ME_GMES_PHASE_BUP:         /* Bringup Phase */
+               if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values) &&
+                   me_progress_bup_values[gmes->current_state])
+                       debug("%s",
+                             me_progress_bup_values[gmes->current_state]);
+               else
+                       debug("0x%02x", gmes->current_state);
+               break;
+
+       case ME_GMES_PHASE_POLICY:      /* Policy Module Phase */
+               if (gmes->current_state <
+                               ARRAY_SIZE(me_progress_policy_values) &&
+                   me_progress_policy_values[gmes->current_state])
+                       debug("%s",
+                             me_progress_policy_values[gmes->current_state]);
+               else
+                       debug("0x%02x", gmes->current_state);
+               break;
+
+       case ME_GMES_PHASE_HOST:        /* Host Communication Phase */
+               if (!gmes->current_state)
+                       debug("Host communication established");
+               else
+                       debug("0x%02x", gmes->current_state);
+               break;
+
+       default:
+               debug("Unknown 0x%02x", gmes->current_state);
+       }
+       debug("\n");
+}
 
--- /dev/null
+/*
+ * From Coreboot src/northbridge/intel/sandybridge/report_platform.c
+ *
+ * Copyright (C) 2012 Google Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/cpu.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+static void report_cpu_info(void)
+{
+       char cpu_string[CPU_MAX_NAME_LEN], *cpu_name;
+       const char *mode[] = {"NOT ", ""};
+       struct cpuid_result cpuidr;
+       int vt, txt, aes;
+       u32 index;
+
+       index = 0x80000000;
+       cpuidr = cpuid(index);
+       if (cpuidr.eax < 0x80000004) {
+               strcpy(cpu_string, "Platform info not available");
+               cpu_name = cpu_string;
+       } else {
+               cpu_name = cpu_get_name(cpu_string);
+       }
+
+       cpuidr = cpuid(1);
+       debug("CPU id(%x): %s\n", cpuidr.eax, cpu_name);
+       aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
+       txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
+       vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
+       debug("AES %ssupported, TXT %ssupported, VT %ssupported\n",
+             mode[aes], mode[txt], mode[vt]);
+}
+
+/* The PCI id name match comes from Intel document 472178 */
+static struct {
+       u16 dev_id;
+       const char *dev_name;
+} pch_table[] = {
+       {0x1E41, "Desktop Sample"},
+       {0x1E42, "Mobile Sample"},
+       {0x1E43, "SFF Sample"},
+       {0x1E44, "Z77"},
+       {0x1E45, "H71"},
+       {0x1E46, "Z75"},
+       {0x1E47, "Q77"},
+       {0x1E48, "Q75"},
+       {0x1E49, "B75"},
+       {0x1E4A, "H77"},
+       {0x1E53, "C216"},
+       {0x1E55, "QM77"},
+       {0x1E56, "QS77"},
+       {0x1E58, "UM77"},
+       {0x1E57, "HM77"},
+       {0x1E59, "HM76"},
+       {0x1E5D, "HM75"},
+       {0x1E5E, "HM70"},
+       {0x1E5F, "NM70"},
+};
+
+static void report_pch_info(void)
+{
+       const char *pch_type = "Unknown";
+       int i;
+       u16 dev_id;
+       uint8_t rev_id;
+
+       dev_id = pci_read_config16(PCH_LPC_DEV, 2);
+       for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
+               if (pch_table[i].dev_id == dev_id) {
+                       pch_type = pch_table[i].dev_name;
+                       break;
+               }
+       }
+       rev_id = pci_read_config8(PCH_LPC_DEV, 8);
+       debug("PCH type: %s, device id: %x, rev id %x\n", pch_type, dev_id,
+             rev_id);
+}
+
+void report_platform_info(void)
+{
+       report_cpu_info();
+       report_pch_info();
+}
 
  */
 
 #include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/processor.h>
+#include <asm/gpio.h>
+#include <asm/global_data.h>
+#include <asm/pci.h>
+#include <asm/arch/me.h>
+#include <asm/arch/pei_data.h>
+#include <asm/arch/pch.h>
+#include <asm/post.h>
+#include <asm/arch/sandybridge.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+       struct memory_info *info = &gd->arch.meminfo;
+       uintptr_t dest_addr = 0;
+       struct memory_area *largest = NULL;
+       int i;
+
+       /* Find largest area of memory below 4GB */
+
+       for (i = 0; i < info->num_areas; i++) {
+               struct memory_area *area = &info->area[i];
+
+               if (area->start >= 1ULL << 32)
+                       continue;
+               if (!largest || area->size > largest->size)
+                       largest = area;
+       }
+
+       /* If no suitable area was found, return an error. */
+       assert(largest);
+       if (!largest || largest->size < (2 << 20))
+               panic("No available memory found for relocation");
+
+       dest_addr = largest->start + largest->size;
+
+       return (ulong)dest_addr;
+}
+
+void dram_init_banksize(void)
+{
+       struct memory_info *info = &gd->arch.meminfo;
+       int num_banks;
+       int i;
+
+       for (i = 0, num_banks = 0; i < info->num_areas; i++) {
+               struct memory_area *area = &info->area[i];
+
+               if (area->start >= 1ULL << 32)
+                       continue;
+               gd->bd->bi_dram[num_banks].start = area->start;
+               gd->bd->bi_dram[num_banks].size = area->size;
+               num_banks++;
+       }
+}
+
+static const char *const ecc_decoder[] = {
+       "inactive",
+       "active on IO",
+       "disabled on IO",
+       "active"
+};
+
+/*
+ * Dump in the log memory controller configuration as read from the memory
+ * controller registers.
+ */
+static void report_memory_config(void)
+{
+       u32 addr_decoder_common, addr_decode_ch[2];
+       int i;
+
+       addr_decoder_common = readl(MCHBAR_REG(0x5000));
+       addr_decode_ch[0] = readl(MCHBAR_REG(0x5004));
+       addr_decode_ch[1] = readl(MCHBAR_REG(0x5008));
+
+       debug("memcfg DDR3 clock %d MHz\n",
+             (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100);
+       debug("memcfg channel assignment: A: %d, B % d, C % d\n",
+             addr_decoder_common & 3,
+             (addr_decoder_common >> 2) & 3,
+             (addr_decoder_common >> 4) & 3);
+
+       for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
+               u32 ch_conf = addr_decode_ch[i];
+               debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf);
+               debug("   ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]);
+               debug("   enhanced interleave mode %s\n",
+                     ((ch_conf >> 22) & 1) ? "on" : "off");
+               debug("   rank interleave %s\n",
+                     ((ch_conf >> 21) & 1) ? "on" : "off");
+               debug("   DIMMA %d MB width x%d %s rank%s\n",
+                     ((ch_conf >> 0) & 0xff) * 256,
+                     ((ch_conf >> 19) & 1) ? 16 : 8,
+                     ((ch_conf >> 17) & 1) ? "dual" : "single",
+                     ((ch_conf >> 16) & 1) ? "" : ", selected");
+               debug("   DIMMB %d MB width x%d %s rank%s\n",
+                     ((ch_conf >> 8) & 0xff) * 256,
+                     ((ch_conf >> 20) & 1) ? 16 : 8,
+                     ((ch_conf >> 18) & 1) ? "dual" : "single",
+                     ((ch_conf >> 16) & 1) ? ", selected" : "");
+       }
+}
+
+static void post_system_agent_init(struct pei_data *pei_data)
+{
+       /* If PCIe init is skipped, set the PEG clock gating */
+       if (!pei_data->pcie_init)
+               setbits_le32(MCHBAR_REG(0x7010), 1);
+}
+
+static asmlinkage void console_tx_byte(unsigned char byte)
+{
+#ifdef DEBUG
+       putc(byte);
+#endif
+}
+
+/**
+ * Find the PEI executable in the ROM and execute it.
+ *
+ * @param pei_data: configuration data for UEFI PEI reference code
+ */
+int sdram_initialise(struct pei_data *pei_data)
+{
+       unsigned version;
+       const char *data;
+       uint16_t done;
+       int ret;
+
+       report_platform_info();
+
+       /* Wait for ME to be ready */
+       ret = intel_early_me_init();
+       if (ret)
+               return ret;
+       ret = intel_early_me_uma_size();
+       if (ret < 0)
+               return ret;
+
+       debug("Starting UEFI PEI System Agent\n");
+
+       /* If MRC data is not found we cannot continue S3 resume. */
+       if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) {
+               debug("Giving up in sdram_initialize: No MRC data\n");
+               outb(0x6, PORT_RESET);
+               cpu_hlt();
+       }
+
+       /* Pass console handler in pei_data */
+       pei_data->tx_byte = console_tx_byte;
+
+       debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data));
+
+       data = (char *)CONFIG_X86_MRC_START;
+       if (data) {
+               int rv;
+               int (*func)(struct pei_data *);
+
+               debug("Calling MRC at %p\n", data);
+               post_code(POST_PRE_MRC);
+               func = (int (*)(struct pei_data *))data;
+               rv = func(pei_data);
+               post_code(POST_MRC);
+               if (rv) {
+                       switch (rv) {
+                       case -1:
+                               printf("PEI version mismatch.\n");
+                               break;
+                       case -2:
+                               printf("Invalid memory frequency.\n");
+                               break;
+                       default:
+                               printf("MRC returned %x.\n", rv);
+                       }
+                       printf("Nonzero MRC return value.\n");
+                       return -EFAULT;
+               }
+       } else {
+               printf("UEFI PEI System Agent not found.\n");
+               return -ENOSYS;
+       }
+
+#if CONFIG_USBDEBUG
+       /* mrc.bin reconfigures USB, so reinit it to have debug */
+       early_usbdebug_init();
+#endif
+
+       version = readl(MCHBAR_REG(0x5034));
+       debug("System Agent Version %d.%d.%d Build %d\n",
+             version >> 24 , (version >> 16) & 0xff,
+             (version >> 8) & 0xff, version & 0xff);
+
+       /*
+        * Send ME init done for SandyBridge here.  This is done inside the
+        * SystemAgent binary on IvyBridge
+        */
+       done = pci_read_config32(PCH_DEV, PCI_DEVICE_ID);
+       done &= BASE_REV_MASK;
+       if (BASE_REV_SNB == done)
+               intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
+       else
+               intel_early_me_status();
+
+       post_system_agent_init(pei_data);
+       report_memory_config();
+
+       return 0;
+}
+
+static int copy_spd(struct pei_data *peid)
+{
+       const int gpio_vector[] = {41, 42, 43, 10, -1};
+       int spd_index;
+       const void *blob = gd->fdt_blob;
+       int node, spd_node;
+       int ret, i;
+
+       for (i = 0; ; i++) {
+               if (gpio_vector[i] == -1)
+                       break;
+               ret = gpio_requestf(gpio_vector[i], "spd_id%d", i);
+               if (ret) {
+                       debug("%s: Could not request gpio %d\n", __func__,
+                             gpio_vector[i]);
+                       return ret;
+               }
+       }
+       spd_index = gpio_get_values_as_int(gpio_vector);
+       debug("spd index %d\n", spd_index);
+       node = fdtdec_next_compatible(blob, 0, COMPAT_MEMORY_SPD);
+       if (node < 0) {
+               printf("SPD data not found.\n");
+               return -ENOENT;
+       }
+
+       for (spd_node = fdt_first_subnode(blob, node);
+            spd_node > 0;
+            spd_node = fdt_next_subnode(blob, spd_node)) {
+               const char *data;
+               int len;
+
+               if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index)
+                       continue;
+               data = fdt_getprop(blob, spd_node, "data", &len);
+               if (len < sizeof(peid->spd_data[0])) {
+                       printf("Missing SPD data\n");
+                       return -EINVAL;
+               }
+
+               debug("Using SDRAM SPD data for '%s'\n",
+                     fdt_get_name(blob, spd_node, NULL));
+               memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0]));
+               break;
+       }
+
+       if (spd_node < 0) {
+               printf("No SPD data found for index %d\n", spd_index);
+               return -ENOENT;
+       }
+
+       return 0;
+}
+
+/**
+ * add_memory_area() - Add a new usable memory area to our list
+ *
+ * Note: @start and @end must not span the first 4GB boundary
+ *
+ * @info:      Place to store memory info
+ * @start:     Start of this memory area
+ * @end:       End of this memory area + 1
+ */
+static int add_memory_area(struct memory_info *info,
+                          uint64_t start, uint64_t end)
+{
+       struct memory_area *ptr;
+
+       if (info->num_areas == CONFIG_NR_DRAM_BANKS)
+               return -ENOSPC;
+
+       ptr = &info->area[info->num_areas];
+       ptr->start = start;
+       ptr->size = end - start;
+       info->total_memory += ptr->size;
+       if (ptr->start < (1ULL << 32))
+               info->total_32bit_memory += ptr->size;
+       debug("%d: memory %llx size %llx, total now %llx / %llx\n",
+             info->num_areas, ptr->start, ptr->size,
+             info->total_32bit_memory, info->total_memory);
+       info->num_areas++;
+
+       return 0;
+}
+
+/**
+ * sdram_find() - Find available memory
+ *
+ * This is a bit complicated since on x86 there are system memory holes all
+ * over the place. We create a list of available memory blocks
+ */
+static int sdram_find(pci_dev_t dev)
+{
+       struct memory_info *info = &gd->arch.meminfo;
+       uint32_t tseg_base, uma_size, tolud;
+       uint64_t tom, me_base, touud;
+       uint64_t uma_memory_base = 0;
+       uint64_t uma_memory_size;
+       unsigned long long tomk;
+       uint16_t ggc;
+
+       /* Total Memory 2GB example:
+        *
+        *  00000000  0000MB-1992MB  1992MB  RAM     (writeback)
+        *  7c800000  1992MB-2000MB     8MB  TSEG    (SMRR)
+        *  7d000000  2000MB-2002MB     2MB  GFX GTT (uncached)
+        *  7d200000  2002MB-2034MB    32MB  GFX UMA (uncached)
+        *  7f200000   2034MB TOLUD
+        *  7f800000   2040MB MEBASE
+        *  7f800000  2040MB-2048MB     8MB  ME UMA  (uncached)
+        *  80000000   2048MB TOM
+        * 100000000  4096MB-4102MB     6MB  RAM     (writeback)
+        *
+        * Total Memory 4GB example:
+        *
+        *  00000000  0000MB-2768MB  2768MB  RAM     (writeback)
+        *  ad000000  2768MB-2776MB     8MB  TSEG    (SMRR)
+        *  ad800000  2776MB-2778MB     2MB  GFX GTT (uncached)
+        *  ada00000  2778MB-2810MB    32MB  GFX UMA (uncached)
+        *  afa00000   2810MB TOLUD
+        *  ff800000   4088MB MEBASE
+        *  ff800000  4088MB-4096MB     8MB  ME UMA  (uncached)
+        * 100000000   4096MB TOM
+        * 100000000  4096MB-5374MB  1278MB  RAM     (writeback)
+        * 14fe00000   5368MB TOUUD
+        */
+
+       /* Top of Upper Usable DRAM, including remap */
+       touud = pci_read_config32(dev, TOUUD+4);
+       touud <<= 32;
+       touud |= pci_read_config32(dev, TOUUD);
+
+       /* Top of Lower Usable DRAM */
+       tolud = pci_read_config32(dev, TOLUD);
+
+       /* Top of Memory - does not account for any UMA */
+       tom = pci_read_config32(dev, 0xa4);
+       tom <<= 32;
+       tom |= pci_read_config32(dev, 0xa0);
+
+       debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom);
+
+       /* ME UMA needs excluding if total memory <4GB */
+       me_base = pci_read_config32(dev, 0x74);
+       me_base <<= 32;
+       me_base |= pci_read_config32(dev, 0x70);
+
+       debug("MEBASE %llx\n", me_base);
+
+       /* TODO: Get rid of all this shifting by 10 bits */
+       tomk = tolud >> 10;
+       if (me_base == tolud) {
+               /* ME is from MEBASE-TOM */
+               uma_size = (tom - me_base) >> 10;
+               /* Increment TOLUD to account for ME as RAM */
+               tolud += uma_size << 10;
+               /* UMA starts at old TOLUD */
+               uma_memory_base = tomk * 1024ULL;
+               uma_memory_size = uma_size * 1024ULL;
+               debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10);
+       }
+
+       /* Graphics memory comes next */
+       ggc = pci_read_config16(dev, GGC);
+       if (!(ggc & 2)) {
+               debug("IGD decoded, subtracting ");
+
+               /* Graphics memory */
+               uma_size = ((ggc >> 3) & 0x1f) * 32 * 1024ULL;
+               debug("%uM UMA", uma_size >> 10);
+               tomk -= uma_size;
+               uma_memory_base = tomk * 1024ULL;
+               uma_memory_size += uma_size * 1024ULL;
+
+               /* GTT Graphics Stolen Memory Size (GGMS) */
+               uma_size = ((ggc >> 8) & 0x3) * 1024ULL;
+               tomk -= uma_size;
+               uma_memory_base = tomk * 1024ULL;
+               uma_memory_size += uma_size * 1024ULL;
+               debug(" and %uM GTT\n", uma_size >> 10);
+       }
+
+       /* Calculate TSEG size from its base which must be below GTT */
+       tseg_base = pci_read_config32(dev, 0xb8);
+       uma_size = (uma_memory_base - tseg_base) >> 10;
+       tomk -= uma_size;
+       uma_memory_base = tomk * 1024ULL;
+       uma_memory_size += uma_size * 1024ULL;
+       debug("TSEG base 0x%08x size %uM\n", tseg_base, uma_size >> 10);
+
+       debug("Available memory below 4GB: %lluM\n", tomk >> 10);
+
+       /* Report the memory regions */
+       add_memory_area(info, 1 << 20, 2 << 28);
+       add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28);
+       add_memory_area(info, (4 << 28) + (2 << 20), tseg_base);
+       add_memory_area(info, 1ULL << 32, touud);
+       /*
+        * If >= 4GB installed then memory from TOLUD to 4GB
+        * is remapped above TOM, TOUUD will account for both
+        */
+       if (touud > (1ULL << 32ULL)) {
+               debug("Available memory above 4GB: %lluM\n",
+                     (touud >> 20) - 4096);
+       }
+
+       return 0;
+}
+
+static void rcba_config(void)
+{
+       /*
+        *             GFX    INTA -> PIRQA (MSI)
+        * D28IP_P3IP  WLAN   INTA -> PIRQB
+        * D29IP_E1P   EHCI1  INTA -> PIRQD
+        * D26IP_E2P   EHCI2  INTA -> PIRQF
+        * D31IP_SIP   SATA   INTA -> PIRQF (MSI)
+        * D31IP_SMIP  SMBUS  INTB -> PIRQH
+        * D31IP_TTIP  THRT   INTC -> PIRQA
+        * D27IP_ZIP   HDA    INTA -> PIRQA (MSI)
+        *
+        * TRACKPAD                -> PIRQE (Edge Triggered)
+        * TOUCHSCREEN             -> PIRQG (Edge Triggered)
+        */
+
+       /* Device interrupt pin register (board specific) */
+       writel((INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) |
+              (INTB << D31IP_SMIP) | (INTA << D31IP_SIP), RCB_REG(D31IP));
+       writel(NOINT << D30IP_PIP, RCB_REG(D30IP));
+       writel(INTA << D29IP_E1P, RCB_REG(D29IP));
+       writel(INTA << D28IP_P3IP, RCB_REG(D28IP));
+       writel(INTA << D27IP_ZIP, RCB_REG(D27IP));
+       writel(INTA << D26IP_E2P, RCB_REG(D26IP));
+       writel(NOINT << D25IP_LIP, RCB_REG(D25IP));
+       writel(NOINT << D22IP_MEI1IP, RCB_REG(D22IP));
+
+       /* Device interrupt route registers */
+       writel(DIR_ROUTE(PIRQB, PIRQH, PIRQA, PIRQC), RCB_REG(D31IR));
+       writel(DIR_ROUTE(PIRQD, PIRQE, PIRQF, PIRQG), RCB_REG(D29IR));
+       writel(DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQE), RCB_REG(D28IR));
+       writel(DIR_ROUTE(PIRQA, PIRQH, PIRQA, PIRQB), RCB_REG(D27IR));
+       writel(DIR_ROUTE(PIRQF, PIRQE, PIRQG, PIRQH), RCB_REG(D26IR));
+       writel(DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD), RCB_REG(D25IR));
+       writel(DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD), RCB_REG(D22IR));
+
+       /* Enable IOAPIC (generic) */
+       writew(0x0100, RCB_REG(OIC));
+       /* PCH BWG says to read back the IOAPIC enable register */
+       (void)readw(RCB_REG(OIC));
+
+       /* Disable unused devices (board specific) */
+       setbits_le32(RCB_REG(FD), PCH_DISABLE_ALWAYS);
+}
 
 int dram_init(void)
 {
-       /* TODO: Set up DRAM */
+       struct pei_data pei_data __aligned(8) = {
+               .pei_version = PEI_VERSION,
+               .mchbar = DEFAULT_MCHBAR,
+               .dmibar = DEFAULT_DMIBAR,
+               .epbar = DEFAULT_EPBAR,
+               .pciexbar = CONFIG_MMCONF_BASE_ADDRESS,
+               .smbusbar = SMBUS_IO_BASE,
+               .wdbbar = 0x4000000,
+               .wdbsize = 0x1000,
+               .hpet_address = CONFIG_HPET_ADDRESS,
+               .rcba = DEFAULT_RCBABASE,
+               .pmbase = DEFAULT_PMBASE,
+               .gpiobase = DEFAULT_GPIOBASE,
+               .thermalbase = 0xfed08000,
+               .system_type = 0, /* 0 Mobile, 1 Desktop/Server */
+               .tseg_size = CONFIG_SMM_TSEG_SIZE,
+               .ts_addresses = { 0x00, 0x00, 0x00, 0x00 },
+               .ec_present = 1,
+               .ddr3lv_support = 1,
+               /*
+                * 0 = leave channel enabled
+                * 1 = disable dimm 0 on channel
+                * 2 = disable dimm 1 on channel
+                * 3 = disable dimm 0+1 on channel
+                */
+               .dimm_channel0_disabled = 2,
+               .dimm_channel1_disabled = 2,
+               .max_ddr3_freq = 1600,
+               .usb_port_config = {
+                       /*
+                        * Empty and onboard Ports 0-7, set to un-used pin
+                        * OC3
+                        */
+                       { 0, 3, 0x0000 }, /* P0= Empty */
+                       { 1, 0, 0x0040 }, /* P1= Left USB 1  (OC0) */
+                       { 1, 1, 0x0040 }, /* P2= Left USB 2  (OC1) */
+                       { 1, 3, 0x0040 }, /* P3= SDCARD      (no OC) */
+                       { 0, 3, 0x0000 }, /* P4= Empty */
+                       { 1, 3, 0x0040 }, /* P5= WWAN        (no OC) */
+                       { 0, 3, 0x0000 }, /* P6= Empty */
+                       { 0, 3, 0x0000 }, /* P7= Empty */
+                       /*
+                        * Empty and onboard Ports 8-13, set to un-used pin
+                        * OC4
+                        */
+                       { 1, 4, 0x0040 }, /* P8= Camera      (no OC) */
+                       { 1, 4, 0x0040 }, /* P9= Bluetooth   (no OC) */
+                       { 0, 4, 0x0000 }, /* P10= Empty */
+                       { 0, 4, 0x0000 }, /* P11= Empty */
+                       { 0, 4, 0x0000 }, /* P12= Empty */
+                       { 0, 4, 0x0000 }, /* P13= Empty */
+               },
+       };
+       pci_dev_t dev = PCI_BDF(0, 0, 0);
+       int ret;
+
+       debug("Boot mode %d\n", gd->arch.pei_boot_mode);
+       debug("mcr_input %p\n", pei_data.mrc_input);
+       pei_data.boot_mode = gd->arch.pei_boot_mode;
+       ret = copy_spd(&pei_data);
+       if (!ret)
+               ret = sdram_initialise(&pei_data);
+       if (ret)
+               return ret;
+
+       rcba_config();
+       quick_ram_check();
+
+       writew(0xCAFE, MCHBAR_REG(SSKPD));
+
+       post_code(POST_DRAM);
+
+       ret = sdram_find(dev);
+       if (ret)
+               return ret;
+
+       gd->ram_size = gd->arch.meminfo.total_32bit_memory;
 
        return 0;
 }
 
         * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
         * or fully initialised SDRAM - we really don't care which)
         * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
-        * and early malloc area.
+        * and early malloc area. The MRC requires some space at the top.
         *
         * Stack grows down from top of CAR. We have:
         *
         * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
+        *      MRC area
         *      global_data
         *      x86 global descriptor table
         *      early malloc area
         *      stack
         * bottom-> CONFIG_SYS_CAR_ADDR
         */
-
-       /* Stack grows down from top of CAR */
-       movl    $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE), %esp
+       movl    $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+       subl    $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
+#endif
 
        /* Reserve space on stack for global data */
        subl    $GENERATED_GBL_DATA_SIZE, %esp
 
        chosen { };
        memory { device_type = "memory"; reg = <0 0>; };
 
+       spd {
+               compatible = "memory-spd";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               elpida_4Gb_1600_x16 {
+                       reg = <0>;
+                       data = [92 10 0b 03 04 19 02 02
+                               03 52 01 08 0a 00 fe 00
+                               69 78 69 3c 69 11 18 81
+                               20 08 3c 3c 01 40 83 81
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 0f 11 42 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 02 fe 00
+                               11 52 00 00 00 07 7f 37
+                               45 42 4a 32 30 55 47 36
+                               45 42 55 30 2d 47 4e 2d
+                               46 20 30 20 02 fe 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00];
+               };
+               samsung_4Gb_1600_1.35v_x16 {
+                       reg = <1>;
+                       data = [92 11 0b 03 04 19 02 02
+                               03 11 01 08 0a 00 fe 00
+                               69 78 69 3c 69 11 18 81
+                               f0 0a 3c 3c 01 40 83 01
+                               00 80 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 0f 11 02 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 80 ce 01
+                               00 00 00 00 00 00 6a 04
+                               4d 34 37 31 42 35 36 37
+                               34 42 48 30 2d 59 4b 30
+                               20 20 00 00 80 ce 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00];
+                       };
+               micron_4Gb_1600_1.35v_x16 {
+                       reg = <2>;
+                       data = [92 11 0b 03 04 19 02 02
+                               03 11 01 08 0a 00 fe 00
+                               69 78 69 3c 69 11 18 81
+                               20 08 3c 3c 01 40 83 05
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 0f 01 02 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 80 2c 00
+                               00 00 00 00 00 00 ad 75
+                               34 4b 54 46 32 35 36 36
+                               34 48 5a 2d 31 47 36 45
+                               31 20 45 31 80 2c 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               00 00 00 00 00 00 00 00
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff
+                               ff ff ff ff ff ff ff ff];
+               };
+       };
+
        spi {
                #address-cells = <1>;
                #size-cells = <0>;
 
--- /dev/null
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/me.h
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ASM_INTEL_ME_H
+#define _ASM_INTEL_ME_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#define ME_RETRY               100000  /* 1 second */
+#define ME_DELAY               10      /* 10 us */
+
+/*
+ * Management Engine PCI registers
+ */
+
+#define PCI_CPU_MEBASE_L       0x70    /* Set by MRC */
+#define PCI_CPU_MEBASE_H       0x74    /* Set by MRC */
+
+#define PCI_ME_HFS             0x40
+#define  ME_HFS_CWS_RESET      0
+#define  ME_HFS_CWS_INIT       1
+#define  ME_HFS_CWS_REC                2
+#define  ME_HFS_CWS_NORMAL     5
+#define  ME_HFS_CWS_WAIT       6
+#define  ME_HFS_CWS_TRANS      7
+#define  ME_HFS_CWS_INVALID    8
+#define  ME_HFS_STATE_PREBOOT  0
+#define  ME_HFS_STATE_M0_UMA   1
+#define  ME_HFS_STATE_M3       4
+#define  ME_HFS_STATE_M0       5
+#define  ME_HFS_STATE_BRINGUP  6
+#define  ME_HFS_STATE_ERROR    7
+#define  ME_HFS_ERROR_NONE     0
+#define  ME_HFS_ERROR_UNCAT    1
+#define  ME_HFS_ERROR_IMAGE    3
+#define  ME_HFS_ERROR_DEBUG    4
+#define  ME_HFS_MODE_NORMAL    0
+#define  ME_HFS_MODE_DEBUG     2
+#define  ME_HFS_MODE_DIS       3
+#define  ME_HFS_MODE_OVER_JMPR 4
+#define  ME_HFS_MODE_OVER_MEI  5
+#define  ME_HFS_BIOS_DRAM_ACK  1
+#define  ME_HFS_ACK_NO_DID     0
+#define  ME_HFS_ACK_RESET      1
+#define  ME_HFS_ACK_PWR_CYCLE  2
+#define  ME_HFS_ACK_S3         3
+#define  ME_HFS_ACK_S4         4
+#define  ME_HFS_ACK_S5         5
+#define  ME_HFS_ACK_GBL_RESET  6
+#define  ME_HFS_ACK_CONTINUE   7
+
+struct me_hfs {
+       u32 working_state:4;
+       u32 mfg_mode:1;
+       u32 fpt_bad:1;
+       u32 operation_state:3;
+       u32 fw_init_complete:1;
+       u32 ft_bup_ld_flr:1;
+       u32 update_in_progress:1;
+       u32 error_code:4;
+       u32 operation_mode:4;
+       u32 reserved:4;
+       u32 boot_options_present:1;
+       u32 ack_data:3;
+       u32 bios_msg_ack:4;
+} __packed;
+
+#define PCI_ME_UMA             0x44
+
+struct me_uma {
+       u32 size:6;
+       u32 reserved_1:10;
+       u32 valid:1;
+       u32 reserved_0:14;
+       u32 set_to_one:1;
+} __packed;
+
+#define PCI_ME_H_GS            0x4c
+#define  ME_INIT_DONE          1
+#define  ME_INIT_STATUS_SUCCESS        0
+#define  ME_INIT_STATUS_NOMEM  1
+#define  ME_INIT_STATUS_ERROR  2
+
+struct me_did {
+       u32 uma_base:16;
+       u32 reserved:8;
+       u32 status:4;
+       u32 init_done:4;
+} __packed;
+
+#define PCI_ME_GMES            0x48
+#define  ME_GMES_PHASE_ROM     0
+#define  ME_GMES_PHASE_BUP     1
+#define  ME_GMES_PHASE_UKERNEL 2
+#define  ME_GMES_PHASE_POLICY  3
+#define  ME_GMES_PHASE_MODULE  4
+#define  ME_GMES_PHASE_UNKNOWN 5
+#define  ME_GMES_PHASE_HOST    6
+
+struct me_gmes {
+       u32 bist_in_prog:1;
+       u32 icc_prog_sts:2;
+       u32 invoke_mebx:1;
+       u32 cpu_replaced_sts:1;
+       u32 mbp_rdy:1;
+       u32 mfs_failure:1;
+       u32 warm_rst_req_for_df:1;
+       u32 cpu_replaced_valid:1;
+       u32 reserved_1:2;
+       u32 fw_upd_ipu:1;
+       u32 reserved_2:4;
+       u32 current_state:8;
+       u32 current_pmevent:4;
+       u32 progress_code:4;
+} __packed;
+
+#define PCI_ME_HERES           0xbc
+#define  PCI_ME_EXT_SHA1       0x00
+#define  PCI_ME_EXT_SHA256     0x02
+#define PCI_ME_HER(x)          (0xc0+(4*(x)))
+
+struct me_heres {
+       u32 extend_reg_algorithm:4;
+       u32 reserved:26;
+       u32 extend_feature_present:1;
+       u32 extend_reg_valid:1;
+} __packed;
+
+/*
+ * Management Engine MEI registers
+ */
+
+#define MEI_H_CB_WW            0x00
+#define MEI_H_CSR              0x04
+#define MEI_ME_CB_RW           0x08
+#define MEI_ME_CSR_HA          0x0c
+
+struct mei_csr {
+       u32 interrupt_enable:1;
+       u32 interrupt_status:1;
+       u32 interrupt_generate:1;
+       u32 ready:1;
+       u32 reset:1;
+       u32 reserved:3;
+       u32 buffer_read_ptr:8;
+       u32 buffer_write_ptr:8;
+       u32 buffer_depth:8;
+} __packed;
+
+#define MEI_ADDRESS_CORE       0x01
+#define MEI_ADDRESS_AMT                0x02
+#define MEI_ADDRESS_RESERVED   0x03
+#define MEI_ADDRESS_WDT                0x04
+#define MEI_ADDRESS_MKHI       0x07
+#define MEI_ADDRESS_ICC                0x08
+#define MEI_ADDRESS_THERMAL    0x09
+
+#define MEI_HOST_ADDRESS       0
+
+struct mei_header {
+       u32 client_address:8;
+       u32 host_address:8;
+       u32 length:9;
+       u32 reserved:6;
+       u32 is_complete:1;
+} __packed;
+
+#define MKHI_GROUP_ID_CBM      0x00
+#define MKHI_GROUP_ID_FWCAPS   0x03
+#define MKHI_GROUP_ID_MDES     0x08
+#define MKHI_GROUP_ID_GEN      0xff
+
+#define MKHI_GLOBAL_RESET      0x0b
+
+#define MKHI_FWCAPS_GET_RULE   0x02
+
+#define MKHI_MDES_ENABLE       0x09
+
+#define MKHI_GET_FW_VERSION    0x02
+#define MKHI_END_OF_POST       0x0c
+#define MKHI_FEATURE_OVERRIDE  0x14
+
+struct mkhi_header {
+       u32 group_id:8;
+       u32 command:7;
+       u32 is_response:1;
+       u32 reserved:8;
+       u32 result:8;
+} __packed;
+
+struct me_fw_version {
+       u16 code_minor;
+       u16 code_major;
+       u16 code_build_number;
+       u16 code_hot_fix;
+       u16 recovery_minor;
+       u16 recovery_major;
+       u16 recovery_build_number;
+       u16 recovery_hot_fix;
+} __packed;
+
+
+#define HECI_EOP_STATUS_SUCCESS       0x0
+#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1
+
+#define CBM_RR_GLOBAL_RESET    0x01
+
+#define GLOBAL_RESET_BIOS_MRC  0x01
+#define GLOBAL_RESET_BIOS_POST 0x02
+#define GLOBAL_RESET_MEBX      0x03
+
+struct me_global_reset {
+       u8 request_origin;
+       u8 reset_type;
+} __packed;
+
+enum me_bios_path {
+       ME_NORMAL_BIOS_PATH,
+       ME_S3WAKE_BIOS_PATH,
+       ME_ERROR_BIOS_PATH,
+       ME_RECOVERY_BIOS_PATH,
+       ME_DISABLE_BIOS_PATH,
+       ME_FIRMWARE_UPDATE_BIOS_PATH,
+};
+
+struct __packed mbp_fw_version_name {
+       u32 major_version:16;
+       u32 minor_version:16;
+       u32 hotfix_version:16;
+       u32 build_version:16;
+};
+
+struct __packed mbp_icc_profile {
+       u8 num_icc_profiles;
+       u8 icc_profile_soft_strap;
+       u8 icc_profile_index;
+       u8 reserved;
+       u32 register_lock_mask[3];
+};
+
+struct __packed mefwcaps_sku {
+       u32 full_net:1;
+       u32 std_net:1;
+       u32 manageability:1;
+       u32 small_business:1;
+       u32 l3manageability:1;
+       u32 intel_at:1;
+       u32 intel_cls:1;
+       u32 reserved:3;
+       u32 intel_mpc:1;
+       u32 icc_over_clocking:1;
+       u32 pavp:1;
+       u32 reserved_1:4;
+       u32 ipv6:1;
+       u32 kvm:1;
+       u32 och:1;
+       u32 vlan:1;
+       u32 tls:1;
+       u32 reserved_4:1;
+       u32 wlan:1;
+       u32 reserved_5:8;
+};
+
+struct __packed tdt_state_flag {
+       u16 lock_state:1;
+       u16 authenticate_module:1;
+       u16 s3authentication:1;
+       u16 flash_wear_out:1;
+       u16 flash_variable_security:1;
+       u16 wwan3gpresent:1;
+       u16 wwan3goob:1;
+       u16 reserved:9;
+};
+
+struct __packed tdt_state_info {
+       u8 state;
+       u8 last_theft_trigger;
+       struct tdt_state_flag flags;
+};
+
+struct __packed platform_type_rule_data {
+       u32 platform_target_usage_type:4;
+       u32 platform_target_market_type:2;
+       u32 super_sku:1;
+       u32 reserved:1;
+       u32 intel_me_fw_image_type:4;
+       u32 platform_brand:4;
+       u32 reserved_1:16;
+};
+
+struct __packed mbp_fw_caps {
+       struct mefwcaps_sku fw_capabilities;
+       u8 available;
+};
+
+struct __packed mbp_rom_bist_data {
+       u16 device_id;
+       u16 fuse_test_flags;
+       u32 umchid[4];
+};
+
+struct __packed mbp_platform_key {
+       u32 key[8];
+};
+
+struct __packed mbp_plat_type {
+       struct platform_type_rule_data rule_data;
+       u8 available;
+};
+
+struct __packed me_bios_payload {
+       struct mbp_fw_version_name fw_version_name;
+       struct mbp_fw_caps fw_caps_sku;
+       struct mbp_rom_bist_data rom_bist_data;
+       struct mbp_platform_key platform_key;
+       struct mbp_plat_type fw_plat_type;
+       struct mbp_icc_profile icc_profile;
+       struct tdt_state_info at_state;
+       u32 mfsintegrity;
+};
+
+struct __packed mbp_header {
+       u32 mbp_size:8;
+       u32 num_entries:8;
+       u32 rsvd:16;
+};
+
+struct __packed mbp_item_header {
+       u32 app_id:8;
+       u32 item_id:8;
+       u32 length:8;
+       u32 rsvd:8;
+};
+
+struct __packed me_fwcaps {
+       u32 id;
+       u8 length;
+       struct mefwcaps_sku caps_sku;
+       u8 reserved[3];
+};
+
+/* Defined in me_status.c for both romstage and ramstage */
+void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes);
+
+void intel_early_me_status(void);
+int intel_early_me_init(void);
+int intel_early_me_uma_size(void);
+int intel_early_me_init_done(u8 status);
+
+#endif
 
 /* PCI Configuration Space (D31:F0): LPC */
 #define PCH_LPC_DEV            PCI_BDF(0, 0x1f, 0)
 
+#define GEN_PMCON_1            0xa0
+#define GEN_PMCON_2            0xa2
+#define GEN_PMCON_3            0xa4
+#define ETR3                   0xac
+#define  ETR3_CWORWRE          (1 << 18)
+#define  ETR3_CF9GR            (1 << 20)
+
 #define PMBASE                 0x40
 #define ACPI_CNTL              0x44
 #define BIOS_CNTL              0xDC
 #define RPC            0x0400  /* 32bit */
 #define RPFN           0x0404  /* 32bit */
 
+#define TRSR           0x1e00  /*  8bit */
+#define TRCR           0x1e10  /* 64bit */
+#define TWDR           0x1e18  /* 64bit */
+
+#define IOTR0          0x1e80  /* 64bit */
+#define IOTR1          0x1e88  /* 64bit */
+#define IOTR2          0x1e90  /* 64bit */
+#define IOTR3          0x1e98  /* 64bit */
+
+#define TCTL           0x3000  /*  8bit */
+
+#define NOINT          0
+#define INTA           1
+#define INTB           2
+#define INTC           3
+#define INTD           4
+
+#define DIR_IDR                12      /* Interrupt D Pin Offset */
+#define DIR_ICR                8       /* Interrupt C Pin Offset */
+#define DIR_IBR                4       /* Interrupt B Pin Offset */
+#define DIR_IAR                0       /* Interrupt A Pin Offset */
+
+#define PIRQA          0
+#define PIRQB          1
+#define PIRQC          2
+#define PIRQD          3
+#define PIRQE          4
+#define PIRQF          5
+#define PIRQG          6
+#define PIRQH          7
+
+/* IO Buffer Programming */
+#define IOBPIRI                0x2330
+#define IOBPD          0x2334
+#define IOBPS          0x2338
+#define  IOBPS_RW_BX    ((1 << 9)|(1 << 10))
+#define  IOBPS_WRITE_AX        ((1 << 9)|(1 << 10))
+#define  IOBPS_READ_AX ((1 << 8)|(1 << 9)|(1 << 10))
+
+#define D31IP          0x3100  /* 32bit */
+#define D31IP_TTIP     24      /* Thermal Throttle Pin */
+#define D31IP_SIP2     20      /* SATA Pin 2 */
+#define D31IP_SMIP     12      /* SMBUS Pin */
+#define D31IP_SIP      8       /* SATA Pin */
+#define D30IP          0x3104  /* 32bit */
+#define D30IP_PIP      0       /* PCI Bridge Pin */
+#define D29IP          0x3108  /* 32bit */
+#define D29IP_E1P      0       /* EHCI #1 Pin */
+#define D28IP          0x310c  /* 32bit */
+#define D28IP_P8IP     28      /* PCI Express Port 8 */
+#define D28IP_P7IP     24      /* PCI Express Port 7 */
+#define D28IP_P6IP     20      /* PCI Express Port 6 */
+#define D28IP_P5IP     16      /* PCI Express Port 5 */
+#define D28IP_P4IP     12      /* PCI Express Port 4 */
+#define D28IP_P3IP     8       /* PCI Express Port 3 */
+#define D28IP_P2IP     4       /* PCI Express Port 2 */
+#define D28IP_P1IP     0       /* PCI Express Port 1 */
+#define D27IP          0x3110  /* 32bit */
+#define D27IP_ZIP      0       /* HD Audio Pin */
+#define D26IP          0x3114  /* 32bit */
+#define D26IP_E2P      0       /* EHCI #2 Pin */
+#define D25IP          0x3118  /* 32bit */
+#define D25IP_LIP      0       /* GbE LAN Pin */
+#define D22IP          0x3124  /* 32bit */
+#define D22IP_KTIP     12      /* KT Pin */
+#define D22IP_IDERIP   8       /* IDE-R Pin */
+#define D22IP_MEI2IP   4       /* MEI #2 Pin */
+#define D22IP_MEI1IP   0       /* MEI #1 Pin */
+#define D20IP          0x3128  /* 32bit */
+#define D20IP_XHCIIP   0
+#define D31IR          0x3140  /* 16bit */
+#define D30IR          0x3142  /* 16bit */
+#define D29IR          0x3144  /* 16bit */
+#define D28IR          0x3146  /* 16bit */
+#define D27IR          0x3148  /* 16bit */
+#define D26IR          0x314c  /* 16bit */
+#define D25IR          0x3150  /* 16bit */
+#define D22IR          0x315c  /* 16bit */
+#define D20IR          0x3160  /* 16bit */
+#define OIC            0x31fe  /* 16bit */
+
 #define SPI_FREQ_SWSEQ 0x3893
 #define SPI_DESC_COMP0 0x38b0
 #define SPI_FREQ_WR_ERA        0x38b4
 #define SOFT_RESET_CTRL 0x38f4
 #define SOFT_RESET_DATA 0x38f8
 
+#define DIR_ROUTE(a, b, c, d) \
+               (((d) << DIR_IDR) | ((c) << DIR_ICR) | \
+                       ((b) << DIR_IBR) | ((a) << DIR_IAR))
+
 #define RC             0x3400  /* 32bit */
 #define HPTC           0x3404  /* 32bit */
 #define GCS            0x3410  /* 32bit */
 #define FD2            0x3428  /* 32bit */
 #define CG             0x341c  /* 32bit */
 
+/* Function Disable 1 RCBA 0x3418 */
+#define PCH_DISABLE_ALWAYS     ((1 << 0)|(1 << 26))
+#define PCH_DISABLE_P2P                (1 << 1)
+#define PCH_DISABLE_SATA1      (1 << 2)
+#define PCH_DISABLE_SMBUS      (1 << 3)
+#define PCH_DISABLE_HD_AUDIO   (1 << 4)
+#define PCH_DISABLE_EHCI2      (1 << 13)
+#define PCH_DISABLE_LPC                (1 << 14)
+#define PCH_DISABLE_EHCI1      (1 << 15)
+#define PCH_DISABLE_PCIE(x)    (1 << (16 + x))
+#define PCH_DISABLE_THERMAL    (1 << 24)
+#define PCH_DISABLE_SATA2      (1 << 25)
+#define PCH_DISABLE_XHCI       (1 << 27)
+
+/* Function Disable 2 RCBA 0x3428 */
+#define PCH_DISABLE_KT         (1 << 4)
+#define PCH_DISABLE_IDER       (1 << 3)
+#define PCH_DISABLE_MEI2       (1 << 2)
+#define PCH_DISABLE_MEI1       (1 << 1)
+#define PCH_ENABLE_DBDF                (1 << 0)
+
 /* ICH7 GPIOBASE */
 #define GPIO_USE_SEL   0x00
 #define GP_IO_SEL      0x04
 
--- /dev/null
+/*
+ * Copyright (c) 2011, Google Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef ASM_ARCH_PEI_DATA_H
+#define ASM_ARCH_PEI_DATA_H
+
+struct pch_usb3_controller_settings {
+       /* 0: Disable, 1: Enable, 2: Auto, 3: Smart Auto */
+       uint16_t mode;
+       /* 4 bit mask, 1: switchable, 0: not switchable */
+       uint16_t hs_port_switch_mask;
+       /* 0: No xHCI preOS driver, 1: xHCI preOS driver */
+       uint16_t preboot_support;
+       /* 0: Disable, 1: Enable */
+       uint16_t xhci_streams;
+};
+
+typedef asmlinkage void (*tx_byte_func)(unsigned char byte);
+
+#define PEI_VERSION 6
+
+struct __packed pei_data {
+       uint32_t pei_version;
+       uint32_t mchbar;
+       uint32_t dmibar;
+       uint32_t epbar;
+       uint32_t pciexbar;
+       uint16_t smbusbar;
+       uint32_t wdbbar;
+       uint32_t wdbsize;
+       uint32_t hpet_address;
+       uint32_t rcba;
+       uint32_t pmbase;
+       uint32_t gpiobase;
+       uint32_t thermalbase;
+       uint32_t system_type; /* 0 Mobile, 1 Desktop/Server */
+       uint32_t tseg_size;
+       uint8_t spd_addresses[4];
+       uint8_t ts_addresses[4];
+       int boot_mode;
+       int ec_present;
+       int gbe_enable;
+       /*
+        * 0 = leave channel enabled
+        * 1 = disable dimm 0 on channel
+        * 2 = disable dimm 1 on channel
+        * 3 = disable dimm 0+1 on channel
+        */
+       int dimm_channel0_disabled;
+       int dimm_channel1_disabled;
+       /* Seed values saved in CMOS */
+       uint32_t scrambler_seed;
+       uint32_t scrambler_seed_s3;
+       /* Data read from flash and passed into MRC */
+       unsigned char *mrc_input;
+       unsigned int mrc_input_len;
+       /* Data from MRC that should be saved to flash */
+       unsigned char *mrc_output;
+       unsigned int mrc_output_len;
+       /*
+        * Max frequency DDR3 could be ran at. Could be one of four values:
+        * 800, 1067, 1333, 1600
+        */
+       uint32_t max_ddr3_freq;
+       /*
+        * USB Port Configuration:
+        *  [0] = enable
+        *  [1] = overcurrent pin
+        *  [2] = length
+        *
+        * Ports 0-7 can be mapped to OC0-OC3
+        * Ports 8-13 can be mapped to OC4-OC7
+        *
+        * Port Length
+        *  MOBILE:
+        *   < 0x050 = Setting 1 (back panel, 1-5in, lowest tx amplitude)
+        *   < 0x140 = Setting 2 (back panel, 5-14in, highest tx amplitude)
+        *  DESKTOP:
+        *   < 0x080 = Setting 1 (front/back panel, <8in, lowest tx amplitude)
+        *   < 0x130 = Setting 2 (back panel, 8-13in, higher tx amplitude)
+        *   < 0x150 = Setting 3 (back panel, 13-15in, higest tx amplitude)
+        */
+       uint16_t usb_port_config[16][3];
+       /* See the usb3 struct above for details */
+       struct pch_usb3_controller_settings usb3;
+       /*
+        * SPD data array for onboard RAM. Specify address 0xf0,
+        * 0xf1, 0xf2, 0xf3 to index one of the 4 slots in
+        * spd_address for a given "DIMM".
+        */
+       uint8_t spd_data[4][256];
+       tx_byte_func tx_byte;
+       int ddr3lv_support;
+       /*
+        * pcie_init needs to be set to 1 to have the system agent initialise
+        * PCIe. Note: This should only be required if your system has Gen3
+        * devices and it will increase your boot time by at least 100ms.
+        */
+       int pcie_init;
+       /*
+        * N mode functionality. Leave this setting at 0.
+        * 0 Auto
+        * 1 1N
+        * 2 2N
+        */
+       int nmode;
+       /*
+        * DDR refresh rate config. JEDEC Standard No.21-C Annex K allows
+        * for DIMM SPD data to specify whether double-rate is required for
+        * extended operating temperature range.
+        * 0 Enable double rate based upon temperature thresholds
+        * 1 Normal rate
+        * 2 Always enable double rate
+        */
+       int ddr_refresh_rate_config;
+};
+
+#endif
 
 #define SSKPD          0x5d14  /* 16bit (scratchpad) */
 #define BIOS_RESET_CPL 0x5da8  /* 8bit */
 
+void report_platform_info(void);
+
 void sandybridge_early_init(int chipset_type);
 
 #endif
 
 #define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#define asmlinkage __attribute__((regparm(0)))
 
 #endif
 
 
 };
 
+struct memory_area {
+       uint64_t start;
+       uint64_t size;
+};
+
+struct memory_info {
+       int num_areas;
+       uint64_t total_memory;
+       uint64_t total_32bit_memory;
+       struct memory_area area[CONFIG_NR_DRAM_BANKS];
+};
+
 /* Architecture-specific global data */
 struct arch_global_data {
        struct global_data *gd_addr;            /* Location of Global Data */
        struct pci_controller *hose;    /* PCI hose for early use */
        enum pei_boot_mode_t pei_boot_mode;
        const struct pch_gpio_map *gpio_map;    /* board GPIO map */
+       struct memory_info meminfo;     /* Memory information */
 };
 
 #endif
 
 #define POST_CPU_INIT          0x2b
 #define POST_EARLY_INIT                0x2c
 #define POST_CPU_INFO          0x2d
+#define POST_PRE_MRC           0x2e
+#define POST_MRC               0x2f
+#define POST_DRAM              0x2f
+
+#define POST_RAM_FAILURE       0xea
 
 /* Output a post code using al - value must be 0 to 0xff */
 #ifdef __ASSEMBLY__
 
 void timer_set_tsc_base(uint64_t new_base);
 uint64_t timer_get_tsc(void);
 
+void quick_ram_check(void);
+
 #endif /* _U_BOOT_I386_H_ */
 
 obj-$(CONFIG_PCI) += pci_type1.o
 obj-y  += relocate.o
 obj-y += physmem.o
+obj-$(CONFIG_X86_RAMTEST) += ramtest.o
 obj-y  += string.o
 obj-$(CONFIG_SYS_X86_TSC_TIMER)        += tsc_timer.o
 obj-$(CONFIG_VIDEO_VGA)        += video.o
 
--- /dev/null
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot src/lib/ramtest.c
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/post.h>
+
+static void write_phys(unsigned long addr, u32 value)
+{
+#if CONFIG_SSE2
+       asm volatile(
+               "movnti %1, (%0)"
+               : /* outputs */
+               : "r" (addr), "r" (value) /* inputs */
+               : /* clobbers */
+               );
+#else
+       writel(value, addr);
+#endif
+}
+
+static u32 read_phys(unsigned long addr)
+{
+       return readl(addr);
+}
+
+static void phys_memory_barrier(void)
+{
+#if CONFIG_SSE2
+       /* Needed for movnti */
+       asm volatile(
+               "sfence"
+               :
+               :
+               : "memory"
+       );
+#else
+       asm volatile(""
+               :
+               :
+               : "memory");
+#endif
+}
+
+void quick_ram_check(void)
+{
+       int fail = 0;
+       u32 backup;
+
+       backup = read_phys(CONFIG_RAMBASE);
+       write_phys(CONFIG_RAMBASE, 0x55555555);
+       phys_memory_barrier();
+       if (read_phys(CONFIG_RAMBASE) != 0x55555555)
+               fail = 1;
+       write_phys(CONFIG_RAMBASE, 0xaaaaaaaa);
+       phys_memory_barrier();
+       if (read_phys(CONFIG_RAMBASE) != 0xaaaaaaaa)
+               fail = 1;
+       write_phys(CONFIG_RAMBASE, 0x00000000);
+       phys_memory_barrier();
+       if (read_phys(CONFIG_RAMBASE) != 0x00000000)
+               fail = 1;
+       write_phys(CONFIG_RAMBASE, 0xffffffff);
+       phys_memory_barrier();
+       if (read_phys(CONFIG_RAMBASE) != 0xffffffff)
+               fail = 1;
+
+       write_phys(CONFIG_RAMBASE, backup);
+       if (fail) {
+               post_code(POST_RAM_FAILURE);
+               panic("RAM INIT FAILURE!\n");
+       }
+       phys_memory_barrier();
+}
 
 #define CONFIG_SYS_CAR_ADDR                    0xff7e0000
 #define CONFIG_SYS_CAR_SIZE                    (128 * 1024)
 #define CONFIG_SYS_MONITOR_LEN                 (1 << 20)
+#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE         0x4000
 #define CONFIG_SYS_X86_START16                 0xfffff800
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_BOARD_EARLY_INIT_R
+#define CONFIG_DISPLAY_CPUINFO
 
 #define CONFIG_X86_RESET_VECTOR
 #define CONFIG_NR_DRAM_BANKS                   8
+#define CONFIG_X86_MRC_START                   0xfffa0000
+#define CONFIG_CACHE_MRC_SIZE_KB               512
 
 #define CONFIG_COREBOOT_SERIAL
 
 
 #define CONFIG_SYS_STACK_SIZE                  (32 * 1024)
 #define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_MALLOC_LEN                  0x200000
-#define CONFIG_SYS_MALLOC_F_LEN                        (1 << 10)
+#define CONFIG_SYS_MALLOC_F_LEN                        (2 << 10)
 
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 
        COMPAT_PARADE_PS8625,           /* Parade PS8622 EDP->LVDS bridge */
        COMPAT_INTEL_LPC,               /* Intel Low Pin Count I/F */
        COMPAT_INTEL_MICROCODE,         /* Intel microcode update */
+       COMPAT_MEMORY_SPD,              /* Memory SPD information */
 
        COMPAT_COUNT,
 };
 
        COMPAT(PARADE_PS8625, "parade,ps8625"),
        COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
        COMPAT(INTEL_MICROCODE, "intel,microcode"),
+       COMPAT(MEMORY_SPD, "memory-spd"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)