aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/x86/cpu/ivybridge
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/x86/cpu/ivybridge
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/x86/cpu/ivybridge')
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/Kconfig75
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/Makefile21
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c276
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/cpu.c207
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/early_me.c174
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/fsp_configs.c46
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/ivybridge.c16
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/lpc.c531
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/model_206ax.c455
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/northbridge.c264
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/sata.c259
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/sdram.c563
-rw-r--r--roms/u-boot/arch/x86/cpu/ivybridge/sdram_nop.c19
13 files changed, 2906 insertions, 0 deletions
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/Kconfig b/roms/u-boot/arch/x86/cpu/ivybridge/Kconfig
new file mode 100644
index 000000000..2f4239378
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/Kconfig
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# From Coreboot src/northbridge/intel/sandybridge/Kconfig
+#
+# Copyright (C) 2010 Google Inc.
+#
+
+config NORTHBRIDGE_INTEL_IVYBRIDGE
+ bool
+ select CACHE_MRC_BIN if HAVE_MRC
+ imply HAVE_INTEL_ME
+ imply ENABLE_MRC_CACHE
+ imply AHCI_PCI
+ imply ICH_SPI
+ imply INTEL_ICH6_GPIO
+ imply PINCTRL_ICH6
+ imply SCSI
+ imply SCSI_AHCI
+ imply SPI_FLASH
+ imply USB
+ imply USB_EHCI_HCD
+ imply USB_XHCI_HCD
+ imply VIDEO_VESA
+ imply SOUND_IVYBRIDGE
+
+if NORTHBRIDGE_INTEL_IVYBRIDGE
+
+config DCACHE_RAM_BASE
+ default 0xff7e0000
+
+config DCACHE_RAM_SIZE
+ default 0x20000
+
+config DCACHE_RAM_MRC_VAR_SIZE
+ default 0x4000
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select SMM_TSEG
+ select X86_RAMTEST
+
+config SMM_TSEG_SIZE
+ hex
+ default 0x800000
+
+config ENABLE_VMX
+ bool "Enable VMX for virtualization"
+ default n
+ help
+ Virtual Machine Extensions are provided in many x86 CPUs. These
+ provide various facilities for allowing a host OS to provide an
+ environment where potentially several guest OSes have only
+ limited access to the underlying hardware. This is achieved
+ without resorting to software trapping and/or instruction set
+ emulation (which would be very slow).
+
+ Intel's implementation of this is called VT-x. This option enables
+ VT-x this so that the OS that is booted by U-Boot can make use of
+ these facilities. If this option is not enabled, then the host OS
+ will be unable to support virtualisation, or it will run very
+ slowly.
+
+config FSP_ADDR
+ hex
+ default 0xfff80000
+
+config FSP_USE_UPD
+ bool
+ default n
+
+config FSP_BROKEN_HOB
+ bool
+ default y
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/Makefile b/roms/u-boot/arch/x86/cpu/ivybridge/Makefile
new file mode 100644
index 000000000..716134e9f
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/Makefile
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2014 Google, Inc
+
+ifdef CONFIG_HAVE_FSP
+obj-y += fsp_configs.o ivybridge.o
+else
+obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += cpu.o
+obj-y += early_me.o
+obj-y += lpc.o
+obj-y += northbridge.o
+ifndef CONFIG_SPL_BUILD
+obj-y += sata.o
+endif
+obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += sdram.o
+ifndef CONFIG_$(SPL_)X86_32BIT_INIT
+obj-y += sdram_nop.o
+endif
+endif
+obj-y += model_206ax.o
+obj-y += bd82x6x.o
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c b/roms/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c
new file mode 100644
index 000000000..0540b0216
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Google, Inc
+ */
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <malloc.h>
+#include <pch.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/lpc_common.h>
+#include <asm/pci.h>
+#include <asm/arch/model_206ax.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define GPIO_BASE 0x48
+#define BIOS_CTRL 0xdc
+
+#define RCBA_AUDIO_CONFIG 0x2030
+#define RCBA_AUDIO_CONFIG_HDA BIT(31)
+#define RCBA_AUDIO_CONFIG_MASK 0xfe
+
+#ifndef CONFIG_HAVE_FSP
+static int pch_revision_id = -1;
+static int pch_type = -1;
+
+/**
+ * pch_silicon_revision() - Read silicon revision ID from the PCH
+ *
+ * @dev: PCH device
+ * @return silicon revision ID
+ */
+static int pch_silicon_revision(struct udevice *dev)
+{
+ u8 val;
+
+ if (pch_revision_id < 0) {
+ dm_pci_read_config8(dev, PCI_REVISION_ID, &val);
+ pch_revision_id = val;
+ }
+
+ return pch_revision_id;
+}
+
+int pch_silicon_type(struct udevice *dev)
+{
+ u8 val;
+
+ if (pch_type < 0) {
+ dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val);
+ pch_type = val;
+ }
+
+ return pch_type;
+}
+
+/**
+ * pch_silicon_supported() - Check if a certain revision is supported
+ *
+ * @dev: PCH device
+ * @type: PCH type
+ * @rev: Minimum required resion
+ * @return 0 if not supported, 1 if supported
+ */
+static int pch_silicon_supported(struct udevice *dev, int type, int rev)
+{
+ int cur_type = pch_silicon_type(dev);
+ int cur_rev = pch_silicon_revision(dev);
+
+ switch (type) {
+ case PCH_TYPE_CPT:
+ /* CougarPoint minimum revision */
+ if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
+ return 1;
+ /* PantherPoint any revision */
+ if (cur_type == PCH_TYPE_PPT)
+ return 1;
+ break;
+
+ case PCH_TYPE_PPT:
+ /* PantherPoint minimum revision */
+ if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+#define IOBP_RETRY 1000
+static inline int iobp_poll(void)
+{
+ unsigned try = IOBP_RETRY;
+ u32 data;
+
+ while (try--) {
+ data = readl(RCB_REG(IOBPS));
+ if ((data & 1) == 0)
+ return 1;
+ udelay(10);
+ }
+
+ printf("IOBP timeout\n");
+ return 0;
+}
+
+void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue,
+ u32 orvalue)
+{
+ u32 data;
+
+ /* Set the address */
+ writel(address, RCB_REG(IOBPIRI));
+
+ /* READ OPCODE */
+ if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
+ writel(IOBPS_RW_BX, RCB_REG(IOBPS));
+ else
+ writel(IOBPS_READ_AX, RCB_REG(IOBPS));
+ if (!iobp_poll())
+ return;
+
+ /* Read IOBP data */
+ data = readl(RCB_REG(IOBPD));
+ if (!iobp_poll())
+ return;
+
+ /* Check for successful transaction */
+ if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
+ printf("IOBP read 0x%08x failed\n", address);
+ return;
+ }
+
+ /* Update the data */
+ data &= andvalue;
+ data |= orvalue;
+
+ /* WRITE OPCODE */
+ if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
+ writel(IOBPS_RW_BX, RCB_REG(IOBPS));
+ else
+ writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
+ if (!iobp_poll())
+ return;
+
+ /* Write IOBP data */
+ writel(data, RCB_REG(IOBPD));
+ if (!iobp_poll())
+ return;
+}
+
+static int bd82x6x_probe(struct udevice *dev)
+{
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ /* Cause the SATA device to do its init */
+ uclass_first_device(UCLASS_AHCI, &dev);
+
+ return 0;
+}
+#endif /* CONFIG_HAVE_FSP */
+
+static int bd82x6x_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
+{
+ u32 rcba;
+
+ dm_pci_read_config32(dev, PCH_RCBA, &rcba);
+ /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
+ rcba = rcba & 0xffffc000;
+ *sbasep = rcba + 0x3800;
+
+ return 0;
+}
+
+static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect)
+{
+ return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
+}
+
+static int bd82x6x_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ u32 base;
+
+ /*
+ * GPIO_BASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros.
+ *
+ * Note we don't need check bit0 here, because the Tunnel Creek
+ * GPIO base address register bit0 is reserved (read returns 0),
+ * while on the Ivybridge the bit0 is used to indicate it is an
+ * I/O space.
+ */
+ dm_pci_read_config32(dev, GPIO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ *gbasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
+}
+
+static int bd82x6x_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
+ int size)
+{
+ u32 rcba, val;
+
+ switch (req) {
+ case PCH_REQ_HDA_CONFIG:
+ dm_pci_read_config32(dev, PCH_RCBA, &rcba);
+ val = readl(rcba + RCBA_AUDIO_CONFIG);
+ if (!(val & RCBA_AUDIO_CONFIG_HDA))
+ return -ENOENT;
+
+ return val & RCBA_AUDIO_CONFIG_MASK;
+ case PCH_REQ_PMBASE_INFO: {
+ struct pch_pmbase_info *pm = data;
+ int ret;
+
+ /* Find the base address of the powermanagement registers */
+ ret = dm_pci_read_config16(dev, 0x40, &pm->base);
+ if (ret)
+ return ret;
+ pm->base &= 0xfffe;
+ pm->gpio0_en_ofs = GPE0_EN;
+ pm->pm1_sts_ofs = PM1_STS;
+ pm->pm1_cnt_ofs = PM1_CNT;
+
+ return 0;
+ }
+ default:
+ return -ENOSYS;
+ }
+}
+
+static const struct pch_ops bd82x6x_pch_ops = {
+ .get_spi_base = bd82x6x_pch_get_spi_base,
+ .set_spi_protect = bd82x6x_set_spi_protect,
+ .get_gpio_base = bd82x6x_get_gpio_base,
+ .ioctl = bd82x6x_ioctl,
+};
+
+static const struct udevice_id bd82x6x_ids[] = {
+ { .compatible = "intel,bd82x6x" },
+ { }
+};
+
+U_BOOT_DRIVER(bd82x6x_drv) = {
+ .name = "bd82x6x",
+ .id = UCLASS_PCH,
+ .of_match = bd82x6x_ids,
+#ifndef CONFIG_HAVE_FSP
+ .probe = bd82x6x_probe,
+#endif
+ .ops = &bd82x6x_pch_ops,
+};
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/cpu.c b/roms/u-boot/arch/x86/cpu/ivybridge/cpu.c
new file mode 100644
index 000000000..a02f4f960
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/cpu.c
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2014 Google, Inc
+ * (C) Copyright 2008
+ * 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.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <log.h>
+#include <pch.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/lpc_common.h>
+#include <asm/microcode.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/arch/model_206ax.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int set_flex_ratio_to_tdp_nominal(void)
+{
+ /* Minimum CPU revision for configurable TDP support */
+ if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
+ return -EINVAL;
+
+ return cpu_set_flex_ratio_to_tdp_nominal();
+}
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
+
+int arch_cpu_init_dm(void)
+{
+ struct pci_controller *hose;
+ struct udevice *bus, *dev;
+ int ret;
+
+ post_code(0x70);
+ ret = uclass_get_device(UCLASS_PCI, 0, &bus);
+ post_code(0x71);
+ if (ret)
+ return ret;
+ post_code(0x72);
+ hose = dev_get_uclass_priv(bus);
+
+ /* TODO(sjg@chromium.org): Get rid of gd->hose */
+ gd->hose = hose;
+
+ ret = uclass_first_device_err(UCLASS_LPC, &dev);
+ if (ret)
+ return ret;
+
+ /*
+ * We should do as little as possible before the serial console is
+ * up. Perhaps this should move to later. Our next lot of init
+ * happens in checkcpu() when we have a console
+ */
+ ret = set_flex_ratio_to_tdp_nominal();
+ if (ret)
+ return ret;
+
+ 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(struct udevice *bus)
+{
+ pci_dev_t usb0 = PCH_EHCI1_DEV;
+ pci_dev_t usb1 = PCH_EHCI2_DEV;
+ pci_dev_t usb3 = PCH_XHCI_DEV;
+ ulong cmd;
+
+ /* USB Controller 1 */
+ pci_bus_write_config(bus, usb0, PCI_BASE_ADDRESS_0,
+ PCH_EHCI0_TEMP_BAR0, PCI_SIZE_32);
+ pci_bus_read_config(bus, usb0, PCI_COMMAND, &cmd, PCI_SIZE_32);
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_bus_write_config(bus, usb0, PCI_COMMAND, cmd, PCI_SIZE_32);
+
+ /* USB Controller 2 */
+ pci_bus_write_config(bus, usb1, PCI_BASE_ADDRESS_0,
+ PCH_EHCI1_TEMP_BAR0, PCI_SIZE_32);
+ pci_bus_read_config(bus, usb1, PCI_COMMAND, &cmd, PCI_SIZE_32);
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_bus_write_config(bus, usb1, PCI_COMMAND, cmd, PCI_SIZE_32);
+
+ /* USB3 Controller 1 */
+ pci_bus_write_config(bus, usb3, PCI_BASE_ADDRESS_0,
+ PCH_XHCI_TEMP_BAR0, PCI_SIZE_32);
+ pci_bus_read_config(bus, usb3, PCI_COMMAND, &cmd, PCI_SIZE_32);
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32);
+}
+
+int checkcpu(void)
+{
+ enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
+ struct udevice *dev, *lpc;
+ uint32_t pm1_cnt;
+ uint16_t pm1_sts;
+ int ret;
+
+ /* 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");
+ reset_cpu();
+ }
+
+ ret = cpu_common_init();
+ if (ret) {
+ debug("%s: cpu_common_init() failed\n", __func__);
+ return ret;
+ }
+
+ /* 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) {
+ debug("Resume from S3 detected, but disabled.\n");
+ } 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 = uclass_first_device_err(UCLASS_I2C, &dev);
+ if (ret) {
+ debug("%s: Failed to get I2C (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ /* Prepare USB controller early in S3 resume */
+ if (boot_mode == PEI_BOOT_RESUME) {
+ uclass_first_device(UCLASS_LPC, &lpc);
+ enable_usb_bar(pci_get_controller(lpc->parent));
+ }
+
+ gd->arch.pei_boot_mode = boot_mode;
+
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ char processor_name[CPU_MAX_NAME_LEN];
+ const char *name;
+
+ /* Print processor name */
+ name = cpu_get_name(processor_name);
+ printf("CPU: %s\n", name);
+
+ post_code(POST_CPU_INFO);
+
+ return 0;
+}
+
+void board_debug_uart_init(void)
+{
+ /* This enables the debug UART */
+ pci_x86_write_config(PCH_LPC_DEV, LPC_EN, COMA_LPC_EN, PCI_SIZE_16);
+}
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/early_me.c b/roms/u-boot/arch/x86/cpu/ivybridge/early_me.c
new file mode 100644
index 000000000..bee1671ba
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/early_me.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/early_me.c
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <sysreset.h>
+#include <asm/pci.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/arch/me.h>
+#include <asm/arch/pch.h>
+#include <asm/io.h>
+#include <linux/delay.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"
+};
+
+int intel_early_me_init(struct udevice *me_dev)
+{
+ 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(me_dev, &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(me_dev, &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(struct udevice *me_dev)
+{
+ struct me_uma uma;
+
+ pci_read_dword_ptr(me_dev, &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(struct udevice *dev, int enable)
+{
+ u32 etr3;
+
+ dm_pci_read_config32(dev, ETR3, &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;
+
+ dm_pci_write_config32(dev, ETR3, etr3);
+}
+
+int intel_early_me_init_done(struct udevice *dev, struct udevice *me_dev,
+ uint status)
+{
+ 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] */
+ dm_pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_L, &mebase_l);
+ dm_pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_H, &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(me_dev, &did, PCI_ME_H_GS);
+
+ /* Must wait for ME acknowledgement */
+ for (count = ME_RETRY; count > 0; --count) {
+ pci_read_dword_ptr(me_dev, &hfs, PCI_ME_HFS);
+ if (hfs.bios_msg_ack)
+ break;
+ udelay(ME_DELAY);
+ }
+ if (!count) {
+ printf("ERROR: ME failed to respond\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Return the requested BIOS action */
+ debug("ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]);
+
+ /* Check status after acknowledgement */
+ intel_me_status(me_dev);
+
+ 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(dev, 0);
+ sysreset_walk_halt(SYSRESET_COLD);
+ break;
+ case ME_HFS_ACK_PWR_CYCLE:
+ /* Power cycle reset */
+ set_global_reset(dev, 0);
+ sysreset_walk_halt(SYSRESET_COLD);
+ break;
+ case ME_HFS_ACK_GBL_RESET:
+ /* Global reset */
+ set_global_reset(dev, 1);
+ sysreset_walk_halt(SYSRESET_COLD);
+ break;
+ case ME_HFS_ACK_S3:
+ case ME_HFS_ACK_S4:
+ case ME_HFS_ACK_S5:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static const struct udevice_id ivybridge_syscon_ids[] = {
+ { .compatible = "intel,me", .data = X86_SYSCON_ME },
+ { }
+};
+
+U_BOOT_DRIVER(syscon_intel_me) = {
+ .name = "intel_me_syscon",
+ .id = UCLASS_SYSCON,
+ .of_match = ivybridge_syscon_ids,
+};
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/fsp_configs.c b/roms/u-boot/arch/x86/cpu/ivybridge/fsp_configs.c
new file mode 100644
index 000000000..3c4ea6c26
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/fsp_configs.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/fsp1/fsp_support.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void fsp_update_configs(struct fsp_config_data *config,
+ struct fspinit_rtbuf *rt_buf)
+{
+ struct platform_config *plat_config = &config->plat_config;
+ struct memory_config *mem_config = &config->mem_config;
+ const void *blob = gd->fdt_blob;
+ int node;
+
+ node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IVYBRIDGE_FSP);
+ if (node < 0) {
+ debug("%s: Cannot find FSP node\n", __func__);
+ return;
+ }
+
+ plat_config->enable_ht =
+ fdtdec_get_bool(blob, node, "fsp,enable-ht");
+ plat_config->enable_turbo =
+ fdtdec_get_bool(blob, node, "fsp,enable-turbo");
+ plat_config->enable_memory_down =
+ fdtdec_get_bool(blob, node, "fsp,enable-memory-down");
+ plat_config->enable_fast_boot =
+ fdtdec_get_bool(blob, node, "fsp,enable-fast-boot");
+
+ /* Initialize runtime buffer for fsp_init() */
+ rt_buf->stack_top = config->common.stack_top - 32;
+ rt_buf->boot_mode = config->common.boot_mode;
+ rt_buf->plat_config = plat_config;
+
+ if (plat_config->enable_memory_down)
+ rt_buf->mem_config = mem_config;
+ else
+ rt_buf->mem_config = NULL;
+}
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/ivybridge.c b/roms/u-boot/arch/x86/cpu/ivybridge/ivybridge.c
new file mode 100644
index 000000000..eb3f362e4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/ivybridge.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/lpc.c b/roms/u-boot/arch/x86/cpu/ivybridge/lpc.c
new file mode 100644
index 000000000..f931d2be1
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/lpc.c
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From coreboot southbridge/intel/bd82x6x/lpc.c
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <rtc.h>
+#include <pci.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/interrupt.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
+#include <asm/lpc_common.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NMI_OFF 0
+
+#define ENABLE_ACPI_MODE_IN_COREBOOT 0
+#define TEST_SMM_FLASH_LOCKDOWN 0
+
+static int pch_enable_apic(struct udevice *pch)
+{
+ u32 reg32;
+ int i;
+
+ /* Enable ACPI I/O and power management. Set SCI IRQ to IRQ9 */
+ dm_pci_write_config8(pch, ACPI_CNTL, 0x80);
+
+ writel(0, IO_APIC_INDEX);
+ writel(1 << 25, IO_APIC_DATA);
+
+ /* affirm full set of redirection table entries ("write once") */
+ writel(1, IO_APIC_INDEX);
+ reg32 = readl(IO_APIC_DATA);
+ writel(1, IO_APIC_INDEX);
+ writel(reg32, IO_APIC_DATA);
+
+ writel(0, IO_APIC_INDEX);
+ reg32 = readl(IO_APIC_DATA);
+ debug("PCH APIC ID = %x\n", (reg32 >> 24) & 0x0f);
+ if (reg32 != (1 << 25)) {
+ printf("APIC Error - cannot write to registers\n");
+ return -EPERM;
+ }
+
+ debug("Dumping IOAPIC registers\n");
+ for (i = 0; i < 3; i++) {
+ writel(i, IO_APIC_INDEX);
+ debug(" reg 0x%04x:", i);
+ reg32 = readl(IO_APIC_DATA);
+ debug(" 0x%08x\n", reg32);
+ }
+
+ /* Select Boot Configuration register. */
+ writel(3, IO_APIC_INDEX);
+
+ /* Use Processor System Bus to deliver interrupts. */
+ writel(1, IO_APIC_DATA);
+
+ return 0;
+}
+
+static void pch_enable_serial_irqs(struct udevice *pch)
+{
+ u32 value;
+
+ /* Set packet length and toggle silent mode bit for one frame. */
+ value = (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0);
+#ifdef CONFIG_SERIRQ_CONTINUOUS_MODE
+ dm_pci_write_config8(pch, SERIRQ_CNTL, value);
+#else
+ dm_pci_write_config8(pch, SERIRQ_CNTL, value | (1 << 6));
+#endif
+}
+
+static int pch_pirq_init(struct udevice *pch)
+{
+ uint8_t route[8], *ptr;
+
+ if (fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(pch),
+ "intel,pirq-routing", route, sizeof(route)))
+ return -EINVAL;
+ ptr = route;
+ dm_pci_write_config8(pch, PIRQA_ROUT, *ptr++);
+ dm_pci_write_config8(pch, PIRQB_ROUT, *ptr++);
+ dm_pci_write_config8(pch, PIRQC_ROUT, *ptr++);
+ dm_pci_write_config8(pch, PIRQD_ROUT, *ptr++);
+
+ dm_pci_write_config8(pch, PIRQE_ROUT, *ptr++);
+ dm_pci_write_config8(pch, PIRQF_ROUT, *ptr++);
+ dm_pci_write_config8(pch, PIRQG_ROUT, *ptr++);
+ dm_pci_write_config8(pch, PIRQH_ROUT, *ptr++);
+
+ /*
+ * TODO(sjg@chromium.org): U-Boot does not set up the interrupts
+ * here. It's unclear if it is needed
+ */
+ return 0;
+}
+
+static int pch_gpi_routing(struct udevice *pch)
+{
+ u8 route[16];
+ u32 reg;
+ int gpi;
+
+ if (fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(pch),
+ "intel,gpi-routing", route, sizeof(route)))
+ return -EINVAL;
+
+ for (reg = 0, gpi = 0; gpi < ARRAY_SIZE(route); gpi++)
+ reg |= route[gpi] << (gpi * 2);
+
+ dm_pci_write_config32(pch, 0xb8, reg);
+
+ return 0;
+}
+
+static int pch_power_options(struct udevice *pch)
+{
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(pch);
+ u8 reg8;
+ u16 reg16, pmbase;
+ u32 reg32;
+ const char *state;
+ int pwr_on;
+ int nmi_option;
+ int ret;
+
+ /*
+ * Which state do we want to goto after g3 (power restored)?
+ * 0 == S0 Full On
+ * 1 == S5 Soft Off
+ *
+ * If the option is not existent (Laptops), use Kconfig setting.
+ * TODO(sjg@chromium.org): Make this configurable
+ */
+ pwr_on = MAINBOARD_POWER_ON;
+
+ dm_pci_read_config16(pch, GEN_PMCON_3, &reg16);
+ reg16 &= 0xfffe;
+ switch (pwr_on) {
+ case MAINBOARD_POWER_OFF:
+ reg16 |= 1;
+ state = "off";
+ break;
+ case MAINBOARD_POWER_ON:
+ reg16 &= ~1;
+ state = "on";
+ break;
+ case MAINBOARD_POWER_KEEP:
+ reg16 &= ~1;
+ state = "state keep";
+ break;
+ default:
+ state = "undefined";
+ }
+
+ reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
+ reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
+
+ reg16 &= ~(1 << 10);
+ reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
+
+ reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
+
+ dm_pci_write_config16(pch, GEN_PMCON_3, reg16);
+ debug("Set power %s after power failure.\n", state);
+
+ /* Set up NMI on errors. */
+ reg8 = inb(0x61);
+ reg8 &= 0x0f; /* Higher Nibble must be 0 */
+ reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
+ reg8 |= (1 << 2); /* PCI SERR# Disable for now */
+ outb(reg8, 0x61);
+
+ reg8 = inb(0x70);
+ /* TODO(sjg@chromium.org): Make this configurable */
+ nmi_option = NMI_OFF;
+ if (nmi_option) {
+ debug("NMI sources enabled.\n");
+ reg8 &= ~(1 << 7); /* Set NMI. */
+ } else {
+ debug("NMI sources disabled.\n");
+ /* Can't mask NMI from PCI-E and NMI_NOW */
+ reg8 |= (1 << 7);
+ }
+ outb(reg8, 0x70);
+
+ /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
+ dm_pci_read_config16(pch, GEN_PMCON_1, &reg16);
+ reg16 &= ~(3 << 0); /* SMI# rate 1 minute */
+ reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */
+#if DEBUG_PERIODIC_SMIS
+ /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using periodic SMIs */
+ reg16 |= (3 << 0); /* Periodic SMI every 8s */
+#endif
+ dm_pci_write_config16(pch, GEN_PMCON_1, reg16);
+
+ /* Set the board's GPI routing. */
+ ret = pch_gpi_routing(pch);
+ if (ret)
+ return ret;
+
+ dm_pci_read_config16(pch, 0x40, &pmbase);
+ pmbase &= 0xfffe;
+
+ writel(fdtdec_get_int(blob, node, "intel,gpe0-enable", 0),
+ (ulong)pmbase + GPE0_EN);
+ writew(fdtdec_get_int(blob, node, "intel,alt-gp-smi-enable", 0),
+ (ulong)pmbase + ALT_GP_SMI_EN);
+
+ /* Set up power management block and determine sleep mode */
+ reg32 = inl(pmbase + 0x04); /* PM1_CNT */
+ reg32 &= ~(7 << 10); /* SLP_TYP */
+ reg32 |= (1 << 0); /* SCI_EN */
+ outl(reg32, pmbase + 0x04);
+
+ /* Clear magic status bits to prevent unexpected wake */
+ setbits_le32(RCB_REG(0x3310), (1 << 4) | (1 << 5) | (1 << 0));
+ clrbits_le32(RCB_REG(0x3f02), 0xf);
+
+ return 0;
+}
+
+static void pch_rtc_init(struct udevice *pch)
+{
+ int rtc_failed;
+ u8 reg8;
+
+ dm_pci_read_config8(pch, GEN_PMCON_3, &reg8);
+ rtc_failed = reg8 & RTC_BATTERY_DEAD;
+ if (rtc_failed) {
+ reg8 &= ~RTC_BATTERY_DEAD;
+ dm_pci_write_config8(pch, GEN_PMCON_3, reg8);
+ }
+ debug("rtc_failed = 0x%x\n", rtc_failed);
+
+ /* TODO: Handle power failure */
+ if (rtc_failed)
+ printf("RTC power failed\n");
+}
+
+/* CougarPoint PCH Power Management init */
+static void cpt_pm_init(struct udevice *pch)
+{
+ debug("CougarPoint PM init\n");
+ dm_pci_write_config8(pch, 0xa9, 0x47);
+ setbits_le32(RCB_REG(0x2238), (1 << 6) | (1 << 0));
+
+ setbits_le32(RCB_REG(0x228c), 1 << 0);
+ setbits_le32(RCB_REG(0x1100), (1 << 13) | (1 << 14));
+ setbits_le32(RCB_REG(0x0900), 1 << 14);
+ writel(0xc0388400, RCB_REG(0x2304));
+ setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18));
+ setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1));
+ clrsetbits_le32(RCB_REG(0x3314), ~0x1f, 0xf);
+ writel(0x050f0000, RCB_REG(0x3318));
+ writel(0x04000000, RCB_REG(0x3324));
+ setbits_le32(RCB_REG(0x3340), 0xfffff);
+ setbits_le32(RCB_REG(0x3344), 1 << 1);
+
+ writel(0x0001c000, RCB_REG(0x3360));
+ writel(0x00061100, RCB_REG(0x3368));
+ writel(0x7f8fdfff, RCB_REG(0x3378));
+ writel(0x000003fc, RCB_REG(0x337c));
+ writel(0x00001000, RCB_REG(0x3388));
+ writel(0x0001c000, RCB_REG(0x3390));
+ writel(0x00000800, RCB_REG(0x33a0));
+ writel(0x00001000, RCB_REG(0x33b0));
+ writel(0x00093900, RCB_REG(0x33c0));
+ writel(0x24653002, RCB_REG(0x33cc));
+ writel(0x062108fe, RCB_REG(0x33d0));
+ clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060);
+ writel(0x01010000, RCB_REG(0x3a28));
+ writel(0x01010404, RCB_REG(0x3a2c));
+ writel(0x01041041, RCB_REG(0x3a80));
+ clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001);
+ setbits_le32(RCB_REG(0x3a84), 1 << 24); /* SATA 2/3 disabled */
+ setbits_le32(RCB_REG(0x3a88), 1 << 0); /* SATA 4/5 disabled */
+ writel(0x00000001, RCB_REG(0x3a6c));
+ clrsetbits_le32(RCB_REG(0x2344), ~0x00ffff00, 0xff00000c);
+ clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20);
+ writel(0, RCB_REG(0x33c8));
+ setbits_le32(RCB_REG(0x21b0), 0xf);
+}
+
+/* PantherPoint PCH Power Management init */
+static void ppt_pm_init(struct udevice *pch)
+{
+ debug("PantherPoint PM init\n");
+ dm_pci_write_config8(pch, 0xa9, 0x47);
+ setbits_le32(RCB_REG(0x2238), 1 << 0);
+ setbits_le32(RCB_REG(0x228c), 1 << 0);
+ setbits_le16(RCB_REG(0x1100), (1 << 13) | (1 << 14));
+ setbits_le16(RCB_REG(0x0900), 1 << 14);
+ writel(0xc03b8400, RCB_REG(0x2304));
+ setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18));
+ setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1));
+ clrsetbits_le32(RCB_REG(0x3314), 0x1f, 0xf);
+ writel(0x054f0000, RCB_REG(0x3318));
+ writel(0x04000000, RCB_REG(0x3324));
+ setbits_le32(RCB_REG(0x3340), 0xfffff);
+ setbits_le32(RCB_REG(0x3344), (1 << 1) | (1 << 0));
+ writel(0x0001c000, RCB_REG(0x3360));
+ writel(0x00061100, RCB_REG(0x3368));
+ writel(0x7f8fdfff, RCB_REG(0x3378));
+ writel(0x000003fd, RCB_REG(0x337c));
+ writel(0x00001000, RCB_REG(0x3388));
+ writel(0x0001c000, RCB_REG(0x3390));
+ writel(0x00000800, RCB_REG(0x33a0));
+ writel(0x00001000, RCB_REG(0x33b0));
+ writel(0x00093900, RCB_REG(0x33c0));
+ writel(0x24653002, RCB_REG(0x33cc));
+ writel(0x067388fe, RCB_REG(0x33d0));
+ clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060);
+ writel(0x01010000, RCB_REG(0x3a28));
+ writel(0x01010404, RCB_REG(0x3a2c));
+ writel(0x01040000, RCB_REG(0x3a80));
+ clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001);
+ /* SATA 2/3 disabled */
+ setbits_le32(RCB_REG(0x3a84), 1 << 24);
+ /* SATA 4/5 disabled */
+ setbits_le32(RCB_REG(0x3a88), 1 << 0);
+ writel(0x00000001, RCB_REG(0x3a6c));
+ clrsetbits_le32(RCB_REG(0x2344), 0xff0000ff, 0xff00000c);
+ clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20);
+ setbits_le32(RCB_REG(0x33a4), (1 << 0));
+ writel(0, RCB_REG(0x33c8));
+ setbits_le32(RCB_REG(0x21b0), 0xf);
+}
+
+static void enable_hpet(void)
+{
+ /* Move HPET to default address 0xfed00000 and enable it */
+ clrsetbits_le32(RCB_REG(HPTC), 3 << 0, 1 << 7);
+}
+
+static void enable_clock_gating(struct udevice *pch)
+{
+ u32 reg32;
+ u16 reg16;
+
+ setbits_le32(RCB_REG(0x2234), 0xf);
+
+ dm_pci_read_config16(pch, GEN_PMCON_1, &reg16);
+ reg16 |= (1 << 2) | (1 << 11);
+ dm_pci_write_config16(pch, GEN_PMCON_1, reg16);
+
+ pch_iobp_update(pch, 0xeb007f07, ~0U, 1 << 31);
+ pch_iobp_update(pch, 0xeb004000, ~0U, 1 << 7);
+ pch_iobp_update(pch, 0xec007f07, ~0U, 1 << 31);
+ pch_iobp_update(pch, 0xec004000, ~0U, 1 << 7);
+
+ reg32 = readl(RCB_REG(CG));
+ reg32 |= (1 << 31);
+ reg32 |= (1 << 29) | (1 << 28);
+ reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
+ reg32 |= (1 << 16);
+ reg32 |= (1 << 17);
+ reg32 |= (1 << 18);
+ reg32 |= (1 << 22);
+ reg32 |= (1 << 23);
+ reg32 &= ~(1 << 20);
+ reg32 |= (1 << 19);
+ reg32 |= (1 << 0);
+ reg32 |= (0xf << 1);
+ writel(reg32, RCB_REG(CG));
+
+ setbits_le32(RCB_REG(0x38c0), 0x7);
+ setbits_le32(RCB_REG(0x36d4), 0x6680c004);
+ setbits_le32(RCB_REG(0x3564), 0x3);
+}
+
+static void pch_disable_smm_only_flashing(struct udevice *pch)
+{
+ u8 reg8;
+
+ debug("Enabling BIOS updates outside of SMM... ");
+ dm_pci_read_config8(pch, 0xdc, &reg8); /* BIOS_CNTL */
+ reg8 &= ~(1 << 5);
+ dm_pci_write_config8(pch, 0xdc, reg8);
+}
+
+static void pch_fixups(struct udevice *pch)
+{
+ u8 gen_pmcon_2;
+
+ /* Indicate DRAM init done for MRC S3 to know it can resume */
+ dm_pci_read_config8(pch, GEN_PMCON_2, &gen_pmcon_2);
+ gen_pmcon_2 |= (1 << 7);
+ dm_pci_write_config8(pch, GEN_PMCON_2, gen_pmcon_2);
+
+ /* Enable DMI ASPM in the PCH */
+ clrbits_le32(RCB_REG(0x2304), 1 << 10);
+ setbits_le32(RCB_REG(0x21a4), (1 << 11) | (1 << 10));
+ setbits_le32(RCB_REG(0x21a8), 0x3);
+}
+
+static void set_spi_speed(void)
+{
+ u32 fdod;
+
+ /* Observe SPI Descriptor Component Section 0 */
+ writel(0x1000, RCB_REG(SPI_DESC_COMP0));
+
+ /* Extract the1 Write/Erase SPI Frequency from descriptor */
+ fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
+ fdod >>= 24;
+ fdod &= 7;
+
+ /* Set Software Sequence frequency to match */
+ clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
+}
+
+static int lpc_init_extra(struct udevice *dev)
+{
+ struct udevice *pch = dev->parent;
+
+ debug("pch: lpc_init\n");
+ dm_pci_write_bar32(pch, 0, 0);
+ dm_pci_write_bar32(pch, 1, 0xff800000);
+ dm_pci_write_bar32(pch, 2, 0xfec00000);
+ dm_pci_write_bar32(pch, 3, 0x800);
+ dm_pci_write_bar32(pch, 4, 0x900);
+
+ /* Set the value for PCI command register. */
+ dm_pci_write_config16(pch, PCI_COMMAND, 0x000f);
+
+ /* IO APIC initialization. */
+ pch_enable_apic(pch);
+
+ pch_enable_serial_irqs(pch);
+
+ /* Setup the PIRQ. */
+ pch_pirq_init(pch);
+
+ /* Setup power options. */
+ pch_power_options(pch);
+
+ /* Initialize power management */
+ switch (pch_silicon_type(pch)) {
+ case PCH_TYPE_CPT: /* CougarPoint */
+ cpt_pm_init(pch);
+ break;
+ case PCH_TYPE_PPT: /* PantherPoint */
+ ppt_pm_init(pch);
+ break;
+ default:
+ printf("Unknown Chipset: %s\n", pch->name);
+ return -ENOSYS;
+ }
+
+ /* Initialize the real time clock. */
+ pch_rtc_init(pch);
+
+ /* Initialize the High Precision Event Timers, if present. */
+ enable_hpet();
+
+ /* Initialize Clock Gating */
+ enable_clock_gating(pch);
+
+ pch_disable_smm_only_flashing(pch);
+
+ pch_fixups(pch);
+
+ return 0;
+}
+
+static int bd82x6x_lpc_early_init(struct udevice *dev)
+{
+ set_spi_speed();
+
+ /* Setting up Southbridge. In the northbridge code. */
+ debug("Setting up static southbridge registers\n");
+ dm_pci_write_config32(dev->parent, PCH_RCBA_BASE,
+ RCB_BASE_ADDRESS | 1);
+ dm_pci_write_config32(dev->parent, PMBASE, DEFAULT_PMBASE | 1);
+
+ /* Enable ACPI BAR */
+ dm_pci_write_config8(dev->parent, ACPI_CNTL, 0x80);
+
+ debug("Disabling watchdog reboot\n");
+ setbits_le32(RCB_REG(GCS), 1 >> 5); /* No reset */
+ outw(1 << 11, DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */
+
+ dm_pci_write_config32(dev->parent, GPIO_BASE, DEFAULT_GPIOBASE | 1);
+ dm_pci_write_config32(dev->parent, GPIO_CNTL, 0x10);
+
+ return 0;
+}
+
+static int bd82x6x_lpc_probe(struct udevice *dev)
+{
+ int ret;
+
+ if (!(gd->flags & GD_FLG_RELOC)) {
+ ret = lpc_common_early_init(dev);
+ if (ret) {
+ debug("%s: lpc_early_init() failed\n", __func__);
+ return ret;
+ }
+
+ return bd82x6x_lpc_early_init(dev);
+ }
+
+ return lpc_init_extra(dev);
+}
+
+static const struct udevice_id bd82x6x_lpc_ids[] = {
+ { .compatible = "intel,bd82x6x-lpc" },
+ { }
+};
+
+U_BOOT_DRIVER(bd82x6x_lpc_drv) = {
+ .name = "lpc",
+ .id = UCLASS_LPC,
+ .of_match = bd82x6x_lpc_ids,
+ .probe = bd82x6x_lpc_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/model_206ax.c b/roms/u-boot/arch/x86/cpu/ivybridge/model_206ax.c
new file mode 100644
index 000000000..3906a6979
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/model_206ax.c
@@ -0,0 +1,455 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot file of same name
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The Chromium Authors
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/cpu_x86.h>
+#include <asm/global_data.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+#include <asm/mtrr.h>
+#include <asm/processor.h>
+#include <asm/speedstep.h>
+#include <asm/turbo.h>
+#include <asm/arch/model_206ax.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void enable_vmx(void)
+{
+ struct cpuid_result regs;
+#ifdef CONFIG_ENABLE_VMX
+ int enable = true;
+#else
+ int enable = false;
+#endif
+ msr_t msr;
+
+ regs = cpuid(1);
+ /* Check that the VMX is supported before reading or writing the MSR. */
+ if (!((regs.ecx & CPUID_VMX) || (regs.ecx & CPUID_SMX)))
+ return;
+
+ msr = msr_read(MSR_IA32_FEATURE_CONTROL);
+
+ if (msr.lo & (1 << 0)) {
+ debug("VMX is locked, so %s will do nothing\n", __func__);
+ /* VMX locked. If we set it again we get an illegal
+ * instruction
+ */
+ return;
+ }
+
+ /* The IA32_FEATURE_CONTROL MSR may initialize with random values.
+ * It must be cleared regardless of VMX config setting.
+ */
+ msr.hi = 0;
+ msr.lo = 0;
+
+ debug("%s VMX\n", enable ? "Enabling" : "Disabling");
+
+ /*
+ * Even though the Intel manual says you must set the lock bit in
+ * addition to the VMX bit in order for VMX to work, it is incorrect.
+ * Thus we leave it unlocked for the OS to manage things itself.
+ * This is good for a few reasons:
+ * - No need to reflash the bios just to toggle the lock bit.
+ * - The VMX bits really really should match each other across cores,
+ * so hard locking it on one while another has the opposite setting
+ * can easily lead to crashes as code using VMX migrates between
+ * them.
+ * - Vendors that want to "upsell" from a bios that disables+locks to
+ * one that doesn't is sleazy.
+ * By leaving this to the OS (e.g. Linux), people can do exactly what
+ * they want on the fly, and do it correctly (e.g. across multiple
+ * cores).
+ */
+ if (enable) {
+ msr.lo |= (1 << 2);
+ if (regs.ecx & CPUID_SMX)
+ msr.lo |= (1 << 1);
+ }
+
+ msr_write(MSR_IA32_FEATURE_CONTROL, msr);
+}
+
+/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
+static const u8 power_limit_time_sec_to_msr[] = {
+ [0] = 0x00,
+ [1] = 0x0a,
+ [2] = 0x0b,
+ [3] = 0x4b,
+ [4] = 0x0c,
+ [5] = 0x2c,
+ [6] = 0x4c,
+ [7] = 0x6c,
+ [8] = 0x0d,
+ [10] = 0x2d,
+ [12] = 0x4d,
+ [14] = 0x6d,
+ [16] = 0x0e,
+ [20] = 0x2e,
+ [24] = 0x4e,
+ [28] = 0x6e,
+ [32] = 0x0f,
+ [40] = 0x2f,
+ [48] = 0x4f,
+ [56] = 0x6f,
+ [64] = 0x10,
+ [80] = 0x30,
+ [96] = 0x50,
+ [112] = 0x70,
+ [128] = 0x11,
+};
+
+/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
+static const u8 power_limit_time_msr_to_sec[] = {
+ [0x00] = 0,
+ [0x0a] = 1,
+ [0x0b] = 2,
+ [0x4b] = 3,
+ [0x0c] = 4,
+ [0x2c] = 5,
+ [0x4c] = 6,
+ [0x6c] = 7,
+ [0x0d] = 8,
+ [0x2d] = 10,
+ [0x4d] = 12,
+ [0x6d] = 14,
+ [0x0e] = 16,
+ [0x2e] = 20,
+ [0x4e] = 24,
+ [0x6e] = 28,
+ [0x0f] = 32,
+ [0x2f] = 40,
+ [0x4f] = 48,
+ [0x6f] = 56,
+ [0x10] = 64,
+ [0x30] = 80,
+ [0x50] = 96,
+ [0x70] = 112,
+ [0x11] = 128,
+};
+
+bool cpu_ivybridge_config_tdp_levels(void)
+{
+ struct cpuid_result result;
+
+ /* Minimum CPU revision */
+ result = cpuid(1);
+ if (result.eax < IVB_CONFIG_TDP_MIN_CPUID)
+ return false;
+
+ return cpu_config_tdp_levels();
+}
+
+/*
+ * Configure processor power limits if possible
+ * This must be done AFTER set of BIOS_RESET_CPL
+ */
+void set_power_limits(u8 power_limit_1_time)
+{
+ msr_t msr = msr_read(MSR_PLATFORM_INFO);
+ msr_t limit;
+ unsigned power_unit;
+ unsigned tdp, min_power, max_power, max_time;
+ u8 power_limit_1_val;
+
+ if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
+ return;
+
+ if (!(msr.lo & PLATFORM_INFO_SET_TDP))
+ return;
+
+ /* Get units */
+ msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
+ power_unit = 2 << ((msr.lo & 0xf) - 1);
+
+ /* Get power defaults for this SKU */
+ msr = msr_read(MSR_PKG_POWER_SKU);
+ tdp = msr.lo & 0x7fff;
+ min_power = (msr.lo >> 16) & 0x7fff;
+ max_power = msr.hi & 0x7fff;
+ max_time = (msr.hi >> 16) & 0x7f;
+
+ debug("CPU TDP: %u Watts\n", tdp / power_unit);
+
+ if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
+ power_limit_1_time = power_limit_time_msr_to_sec[max_time];
+
+ if (min_power > 0 && tdp < min_power)
+ tdp = min_power;
+
+ if (max_power > 0 && tdp > max_power)
+ tdp = max_power;
+
+ power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
+
+ /* Set long term power limit to TDP */
+ limit.lo = 0;
+ limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
+ limit.lo |= PKG_POWER_LIMIT_EN;
+ limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
+ PKG_POWER_LIMIT_TIME_SHIFT;
+
+ /* Set short term power limit to 1.25 * TDP */
+ limit.hi = 0;
+ limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
+ limit.hi |= PKG_POWER_LIMIT_EN;
+ /* Power limit 2 time is only programmable on SNB EP/EX */
+
+ msr_write(MSR_PKG_POWER_LIMIT, limit);
+
+ /* Use nominal TDP values for CPUs with configurable TDP */
+ if (cpu_ivybridge_config_tdp_levels()) {
+ msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+ limit.hi = 0;
+ limit.lo = msr.lo & 0xff;
+ msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
+ }
+}
+
+static void configure_c_states(void)
+{
+ struct cpuid_result result;
+ msr_t msr;
+
+ msr = msr_read(MSR_PMG_CST_CONFIG_CTL);
+ msr.lo |= (1 << 28); /* C1 Auto Undemotion Enable */
+ msr.lo |= (1 << 27); /* C3 Auto Undemotion Enable */
+ msr.lo |= (1 << 26); /* C1 Auto Demotion Enable */
+ msr.lo |= (1 << 25); /* C3 Auto Demotion Enable */
+ msr.lo &= ~(1 << 10); /* Disable IO MWAIT redirection */
+ msr.lo |= 7; /* No package C-state limit */
+ msr_write(MSR_PMG_CST_CONFIG_CTL, msr);
+
+ msr = msr_read(MSR_PMG_IO_CAPTURE_ADR);
+ msr.lo &= ~0x7ffff;
+ msr.lo |= (PMB0_BASE + 4); /* LVL_2 base address */
+ msr.lo |= (2 << 16); /* CST Range: C7 is max C-state */
+ msr_write(MSR_PMG_IO_CAPTURE_ADR, msr);
+
+ msr = msr_read(MSR_MISC_PWR_MGMT);
+ msr.lo &= ~(1 << 0); /* Enable P-state HW_ALL coordination */
+ msr_write(MSR_MISC_PWR_MGMT, msr);
+
+ msr = msr_read(MSR_POWER_CTL);
+ msr.lo |= (1 << 18); /* Enable Energy Perf Bias MSR 0x1b0 */
+ msr.lo |= (1 << 1); /* C1E Enable */
+ msr.lo |= (1 << 0); /* Bi-directional PROCHOT# */
+ msr_write(MSR_POWER_CTL, msr);
+
+ /* C3 Interrupt Response Time Limit */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | 0x50;
+ msr_write(MSR_PKGC3_IRTL, msr);
+
+ /* C6 Interrupt Response Time Limit */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | 0x68;
+ msr_write(MSR_PKGC6_IRTL, msr);
+
+ /* C7 Interrupt Response Time Limit */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | 0x6D;
+ msr_write(MSR_PKGC7_IRTL, msr);
+
+ /* Primary Plane Current Limit */
+ msr = msr_read(MSR_PP0_CURRENT_CONFIG);
+ msr.lo &= ~0x1fff;
+ msr.lo |= PP0_CURRENT_LIMIT;
+ msr_write(MSR_PP0_CURRENT_CONFIG, msr);
+
+ /* Secondary Plane Current Limit */
+ msr = msr_read(MSR_PP1_CURRENT_CONFIG);
+ msr.lo &= ~0x1fff;
+ result = cpuid(1);
+ if (result.eax >= 0x30600)
+ msr.lo |= PP1_CURRENT_LIMIT_IVB;
+ else
+ msr.lo |= PP1_CURRENT_LIMIT_SNB;
+ msr_write(MSR_PP1_CURRENT_CONFIG, msr);
+}
+
+static void configure_misc(void)
+{
+ msr_t msr;
+
+ msr = msr_read(IA32_MISC_ENABLE);
+ msr.lo |= (1 << 0); /* Fast String enable */
+ msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
+ msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
+ msr_write(IA32_MISC_ENABLE, msr);
+
+ /* Disable Thermal interrupts */
+ msr.lo = 0;
+ msr.hi = 0;
+ msr_write(IA32_THERM_INTERRUPT, msr);
+
+ /* Enable package critical interrupt only */
+ msr.lo = 1 << 4;
+ msr.hi = 0;
+ msr_write(IA32_PACKAGE_THERM_INTERRUPT, msr);
+}
+
+static void enable_lapic_tpr(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_PIC_MSG_CONTROL);
+ msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
+ msr_write(MSR_PIC_MSG_CONTROL, msr);
+}
+
+static void configure_dca_cap(void)
+{
+ struct cpuid_result cpuid_regs;
+ msr_t msr;
+
+ /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
+ cpuid_regs = cpuid(1);
+ if (cpuid_regs.ecx & (1 << 18)) {
+ msr = msr_read(IA32_PLATFORM_DCA_CAP);
+ msr.lo |= 1;
+ msr_write(IA32_PLATFORM_DCA_CAP, msr);
+ }
+}
+
+static void set_max_ratio(void)
+{
+ msr_t msr;
+ uint ratio;
+
+ /* Check for configurable TDP option */
+ if (cpu_ivybridge_config_tdp_levels()) {
+ /* Set to nominal TDP ratio */
+ msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+ ratio = msr.lo & 0xff;
+ } else {
+ /* Platform Info bits 15:8 give max ratio */
+ msr = msr_read(MSR_PLATFORM_INFO);
+ ratio = (msr.lo & 0xff00) >> 8;
+ }
+ cpu_set_perf_control(ratio);
+}
+
+static void set_energy_perf_bias(u8 policy)
+{
+ msr_t msr;
+
+ /* Energy Policy is bits 3:0 */
+ msr = msr_read(IA32_ENERGY_PERFORMANCE_BIAS);
+ msr.lo &= ~0xf;
+ msr.lo |= policy & 0xf;
+ msr_write(IA32_ENERGY_PERFORMANCE_BIAS, msr);
+
+ debug("model_x06ax: energy policy set to %u\n", policy);
+}
+
+static void configure_mca(void)
+{
+ msr_t msr;
+ int i;
+
+ msr.lo = 0;
+ msr.hi = 0;
+ /* This should only be done on a cold boot */
+ for (i = 0; i < 7; i++)
+ msr_write(IA32_MC0_STATUS + (i * 4), msr);
+}
+
+static int model_206ax_init(struct udevice *dev)
+{
+ int ret;
+
+ /* Clear out pending MCEs */
+ configure_mca();
+
+ /* Enable the local cpu apics */
+ enable_lapic_tpr();
+
+ /* Enable virtualization if enabled in CMOS */
+ enable_vmx();
+
+ /* Configure C States */
+ configure_c_states();
+
+ /* Configure Enhanced SpeedStep and Thermal Sensors */
+ configure_misc();
+
+ /* Thermal throttle activation offset */
+ ret = cpu_configure_thermal_target(dev);
+ if (ret) {
+ debug("Cannot set thermal target\n");
+ if (ret != -ENOENT)
+ return ret;
+ }
+
+ /* Enable Direct Cache Access */
+ configure_dca_cap();
+
+ /* Set energy policy */
+ set_energy_perf_bias(ENERGY_POLICY_NORMAL);
+
+ /* Set Max Ratio */
+ set_max_ratio();
+
+ /* Enable Turbo */
+ turbo_enable();
+
+ return 0;
+}
+
+static int model_206ax_get_info(const struct udevice *dev,
+ struct cpu_info *info)
+{
+ return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+
+ return 0;
+}
+
+static int model_206ax_get_count(const struct udevice *dev)
+{
+ return 4;
+}
+
+static int cpu_x86_model_206ax_probe(struct udevice *dev)
+{
+ if (dev_seq(dev) == 0)
+ model_206ax_init(dev);
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_x86_model_206ax_ops = {
+ .get_desc = cpu_x86_get_desc,
+ .get_info = model_206ax_get_info,
+ .get_count = model_206ax_get_count,
+ .get_vendor = cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_model_206ax_ids[] = {
+ { .compatible = "intel,core-gen3" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_x86_model_206ax_drv) = {
+ .name = "cpu_x86_model_206ax",
+ .id = UCLASS_CPU,
+ .of_match = cpu_x86_model_206ax_ids,
+ .bind = cpu_x86_bind,
+ .probe = cpu_x86_model_206ax_probe,
+ .ops = &cpu_x86_model_206ax_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/northbridge.c b/roms/u-boot/arch/x86/cpu/ivybridge/northbridge.c
new file mode 100644
index 000000000..994f8a4ff
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/northbridge.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot northbridge/intel/sandybridge/northbridge.c
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The Chromium Authors
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/msr.h>
+#include <asm/cpu.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/model_206ax.h>
+#include <asm/arch/sandybridge.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int bridge_silicon_revision(struct udevice *dev)
+{
+ struct cpuid_result result;
+ u16 bridge_id;
+ u8 stepping;
+
+ result = cpuid(1);
+ stepping = result.eax & 0xf;
+ dm_pci_read_config16(dev, PCI_DEVICE_ID, &bridge_id);
+ bridge_id &= 0xf0;
+ return bridge_id | stepping;
+}
+
+static int get_pcie_bar(struct udevice *dev, u32 *base, u32 *len)
+{
+ u32 pciexbar_reg;
+
+ *base = 0;
+ *len = 0;
+
+ dm_pci_read_config32(dev, PCIEXBAR, &pciexbar_reg);
+
+ if (!(pciexbar_reg & (1 << 0)))
+ return 0;
+
+ switch ((pciexbar_reg >> 1) & 3) {
+ case 0: /* 256MB */
+ *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
+ (1 << 28));
+ *len = 256 * 1024 * 1024;
+ return 1;
+ case 1: /* 128M */
+ *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
+ (1 << 28) | (1 << 27));
+ *len = 128 * 1024 * 1024;
+ return 1;
+ case 2: /* 64M */
+ *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
+ (1 << 28) | (1 << 27) | (1 << 26));
+ *len = 64 * 1024 * 1024;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void add_fixed_resources(struct udevice *dev, int index)
+{
+ u32 pcie_config_base, pcie_config_size;
+
+ if (get_pcie_bar(dev, &pcie_config_base, &pcie_config_size)) {
+ debug("Adding PCIe config bar base=0x%08x size=0x%x\n",
+ pcie_config_base, pcie_config_size);
+ }
+}
+
+static void northbridge_dmi_init(struct udevice *dev, int rev)
+{
+ /* Clear error status bits */
+ writel(0xffffffff, DMIBAR_REG(0x1c4));
+ writel(0xffffffff, DMIBAR_REG(0x1d0));
+
+ /* Steps prior to DMI ASPM */
+ if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
+ clrsetbits_le32(DMIBAR_REG(0x250), (1 << 22) | (1 << 20),
+ 1 << 21);
+ }
+
+ setbits_le32(DMIBAR_REG(0x238), 1 << 29);
+
+ if (rev >= SNB_STEP_D0) {
+ setbits_le32(DMIBAR_REG(0x1f8), 1 << 16);
+ } else if (rev >= SNB_STEP_D1) {
+ clrsetbits_le32(DMIBAR_REG(0x1f8), 1 << 26, 1 << 16);
+ setbits_le32(DMIBAR_REG(0x1fc), (1 << 12) | (1 << 23));
+ }
+
+ /* Enable ASPM on SNB link, should happen before PCH link */
+ if ((rev & BASE_REV_MASK) == BASE_REV_SNB)
+ setbits_le32(DMIBAR_REG(0xd04), 1 << 4);
+
+ setbits_le32(DMIBAR_REG(0x88), (1 << 1) | (1 << 0));
+}
+
+static void northbridge_init(struct udevice *dev, int rev)
+{
+ u32 bridge_type;
+
+ add_fixed_resources(dev, 6);
+ northbridge_dmi_init(dev, rev);
+
+ bridge_type = readl(MCHBAR_REG(0x5f10));
+ bridge_type &= ~0xff;
+
+ if ((rev & BASE_REV_MASK) == BASE_REV_IVB) {
+ /* Enable Power Aware Interrupt Routing - fixed priority */
+ clrsetbits_8(MCHBAR_REG(0x5418), 0xf, 0x4);
+
+ /* 30h for IvyBridge */
+ bridge_type |= 0x30;
+ } else {
+ /* 20h for Sandybridge */
+ bridge_type |= 0x20;
+ }
+ writel(bridge_type, MCHBAR_REG(0x5f10));
+
+ /*
+ * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU
+ * that BIOS has initialized memory and power management
+ */
+ setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 1);
+ debug("Set BIOS_RESET_CPL\n");
+
+ /* Configure turbo power limits 1ms after reset complete bit */
+ mdelay(1);
+ set_power_limits(28);
+
+ /*
+ * CPUs with configurable TDP also need power limits set
+ * in MCHBAR. Use same values from MSR_PKG_POWER_LIMIT.
+ */
+ if (cpu_ivybridge_config_tdp_levels()) {
+ msr_t msr = msr_read(MSR_PKG_POWER_LIMIT);
+
+ writel(msr.lo, MCHBAR_REG(0x59A0));
+ writel(msr.hi, MCHBAR_REG(0x59A4));
+ }
+
+ /* Set here before graphics PM init */
+ writel(0x00100001, MCHBAR_REG(0x5500));
+}
+
+static void sandybridge_setup_northbridge_bars(struct udevice *dev)
+{
+ /* Set up all hardcoded northbridge BARs */
+ debug("Setting up static registers\n");
+ dm_pci_write_config32(dev, EPBAR, DEFAULT_EPBAR | 1);
+ dm_pci_write_config32(dev, EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32);
+ dm_pci_write_config32(dev, MCHBAR, MCH_BASE_ADDRESS | 1);
+ dm_pci_write_config32(dev, MCHBAR + 4, (0LL + MCH_BASE_ADDRESS) >> 32);
+ /* 64MB - busses 0-63 */
+ dm_pci_write_config32(dev, PCIEXBAR, DEFAULT_PCIEXBAR | 5);
+ dm_pci_write_config32(dev, PCIEXBAR + 4,
+ (0LL + DEFAULT_PCIEXBAR) >> 32);
+ dm_pci_write_config32(dev, DMIBAR, DEFAULT_DMIBAR | 1);
+ dm_pci_write_config32(dev, DMIBAR + 4, (0LL + DEFAULT_DMIBAR) >> 32);
+
+ /* Set C0000-FFFFF to access RAM on both reads and writes */
+ dm_pci_write_config8(dev, PAM0, 0x30);
+ dm_pci_write_config8(dev, PAM1, 0x33);
+ dm_pci_write_config8(dev, PAM2, 0x33);
+ dm_pci_write_config8(dev, PAM3, 0x33);
+ dm_pci_write_config8(dev, PAM4, 0x33);
+ dm_pci_write_config8(dev, PAM5, 0x33);
+ dm_pci_write_config8(dev, PAM6, 0x33);
+}
+
+/**
+ * sandybridge_init_iommu() - Set up IOMMU so that azalia can be used
+ *
+ * It is not obvious where these values come from. They may be undocumented.
+ */
+static void sandybridge_init_iommu(struct udevice *dev)
+{
+ u32 capid0_a;
+
+ dm_pci_read_config32(dev, 0xe4, &capid0_a);
+ if (capid0_a & (1 << 23)) {
+ log_debug("capid0_a not needed\n");
+ return;
+ }
+
+ /* setup BARs */
+ writel(IOMMU_BASE1 >> 32, MCHBAR_REG(0x5404));
+ writel(IOMMU_BASE1 | 1, MCHBAR_REG(0x5400));
+ writel(IOMMU_BASE2 >> 32, MCHBAR_REG(0x5414));
+ writel(IOMMU_BASE2 | 1, MCHBAR_REG(0x5410));
+
+ /* lock policies */
+ writel(0x80000000, IOMMU_BASE1 + 0xff0);
+
+ /* Enable azalia sound */
+ writel(0x20000000, IOMMU_BASE2 + 0xff0);
+ writel(0xa0000000, IOMMU_BASE2 + 0xff0);
+}
+
+static int bd82x6x_northbridge_early_init(struct udevice *dev)
+{
+ const int chipset_type = SANDYBRIDGE_MOBILE;
+ u32 capid0_a;
+ u8 reg8;
+
+ /* Device ID Override Enable should be done very early */
+ dm_pci_read_config32(dev, 0xe4, &capid0_a);
+ if (capid0_a & (1 << 10)) {
+ dm_pci_read_config8(dev, 0xf3, &reg8);
+ reg8 &= ~7; /* Clear 2:0 */
+
+ if (chipset_type == SANDYBRIDGE_MOBILE)
+ reg8 |= 1; /* Set bit 0 */
+
+ dm_pci_write_config8(dev, 0xf3, reg8);
+ }
+
+ sandybridge_setup_northbridge_bars(dev);
+
+ /* Setup IOMMU BARs */
+ sandybridge_init_iommu(dev);
+
+ /* Device Enable */
+ dm_pci_write_config32(dev, DEVEN, DEVEN_HOST | DEVEN_IGD);
+
+ return 0;
+}
+
+static int bd82x6x_northbridge_probe(struct udevice *dev)
+{
+ int rev;
+
+ if (!(gd->flags & GD_FLG_RELOC))
+ return bd82x6x_northbridge_early_init(dev);
+
+ rev = bridge_silicon_revision(dev);
+ northbridge_init(dev, rev);
+
+ return 0;
+}
+
+static const struct udevice_id bd82x6x_northbridge_ids[] = {
+ { .compatible = "intel,bd82x6x-northbridge" },
+ { }
+};
+
+U_BOOT_DRIVER(bd82x6x_northbridge_drv) = {
+ .name = "bd82x6x_northbridge",
+ .id = UCLASS_NORTHBRIDGE,
+ .of_match = bd82x6x_northbridge_ids,
+ .probe = bd82x6x_northbridge_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/sata.c b/roms/u-boot/arch/x86/cpu/ivybridge/sata.c
new file mode 100644
index 000000000..f47ecdffa
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/sata.c
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot
+ * Copyright (C) 2008-2009 coresystems GmbH
+ */
+
+#include <common.h>
+#include <ahci.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/pch_common.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void common_sata_init(struct udevice *dev, unsigned int port_map)
+{
+ u32 reg32;
+ u16 reg16;
+
+ /* Set IDE I/O Configuration */
+ reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+ dm_pci_write_config32(dev, IDE_CONFIG, reg32);
+
+ /* Port enable */
+ dm_pci_read_config16(dev, 0x92, &reg16);
+ reg16 &= ~0x3f;
+ reg16 |= port_map;
+ dm_pci_write_config16(dev, 0x92, reg16);
+
+ /* SATA Initialization register */
+ port_map &= 0xff;
+ dm_pci_write_config32(dev, 0x94, ((port_map ^ 0x3f) << 24) | 0x183);
+}
+
+static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch)
+{
+ unsigned int port_map, speed_support, port_tx;
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ const char *mode;
+ u32 reg32;
+ u16 reg16;
+
+ debug("SATA: Initializing...\n");
+
+ /* SATA configuration */
+ port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0);
+ speed_support = fdtdec_get_int(blob, node,
+ "sata_interface_speed_support", 0);
+
+ mode = fdt_getprop(blob, node, "intel,sata-mode", NULL);
+ if (!mode || !strcmp(mode, "ahci")) {
+ ulong abar;
+
+ debug("SATA: Controller in AHCI mode\n");
+
+ /* Set timings */
+ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+ IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+ IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+ dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+ IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
+
+ /* Sync DMA */
+ dm_pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0);
+ dm_pci_write_config16(dev, IDE_SDMA_TIM, 0x0001);
+
+ common_sata_init(dev, 0x8000 | port_map);
+
+ /* Initialize AHCI memory-mapped space */
+ abar = dm_pci_read_bar32(dev, 5);
+ debug("ABAR: %08lx\n", abar);
+ /* CAP (HBA Capabilities) : enable power management */
+ reg32 = readl(abar + 0x00);
+ reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */
+ reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */
+ /* Set ISS, if available */
+ if (speed_support) {
+ reg32 &= ~0x00f00000;
+ reg32 |= (speed_support & 0x03) << 20;
+ }
+ writel(reg32, abar + 0x00);
+ /* PI (Ports implemented) */
+ writel(port_map, abar + 0x0c);
+ (void) readl(abar + 0x0c); /* Read back 1 */
+ (void) readl(abar + 0x0c); /* Read back 2 */
+ /* CAP2 (HBA Capabilities Extended)*/
+ reg32 = readl(abar + 0x24);
+ reg32 &= ~0x00000002;
+ writel(reg32, abar + 0x24);
+ /* VSP (Vendor Specific Register */
+ reg32 = readl(abar + 0xa0);
+ reg32 &= ~0x00000005;
+ writel(reg32, abar + 0xa0);
+ } else if (!strcmp(mode, "combined")) {
+ debug("SATA: Controller in combined mode\n");
+
+ /* No AHCI: clear AHCI base */
+ dm_pci_write_bar32(dev, 5, 0x00000000);
+ /* And without AHCI BAR no memory decoding */
+ dm_pci_read_config16(dev, PCI_COMMAND, &reg16);
+ reg16 &= ~PCI_COMMAND_MEMORY;
+ dm_pci_write_config16(dev, PCI_COMMAND, reg16);
+
+ dm_pci_write_config8(dev, 0x09, 0x80);
+
+ /* Set timings */
+ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+ IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
+ dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+ IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+ IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+
+ /* Sync DMA */
+ dm_pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0);
+ dm_pci_write_config16(dev, IDE_SDMA_TIM, 0x0200);
+
+ common_sata_init(dev, port_map);
+ } else {
+ debug("SATA: Controller in plain-ide mode\n");
+
+ /* No AHCI: clear AHCI base */
+ dm_pci_write_bar32(dev, 5, 0x00000000);
+
+ /* And without AHCI BAR no memory decoding */
+ dm_pci_read_config16(dev, PCI_COMMAND, &reg16);
+ reg16 &= ~PCI_COMMAND_MEMORY;
+ dm_pci_write_config16(dev, PCI_COMMAND, reg16);
+
+ /*
+ * Native mode capable on both primary and secondary (0xa)
+ * OR'ed with enabled (0x50) = 0xf
+ */
+ dm_pci_write_config8(dev, 0x09, 0x8f);
+
+ /* Set timings */
+ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+ IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+ IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+ dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+ IDE_SITRE | IDE_ISP_3_CLOCKS |
+ IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0);
+
+ /* Sync DMA */
+ dm_pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0);
+ dm_pci_write_config16(dev, IDE_SDMA_TIM, 0x0201);
+
+ common_sata_init(dev, port_map);
+ }
+
+ /* Set Gen3 Transmitter settings if needed */
+ port_tx = fdtdec_get_int(blob, node, "intel,sata-port0-gen3-tx", 0);
+ if (port_tx)
+ pch_iobp_update(pch, SATA_IOBP_SP0G3IR, 0, port_tx);
+
+ port_tx = fdtdec_get_int(blob, node, "intel,sata-port1-gen3-tx", 0);
+ if (port_tx)
+ pch_iobp_update(pch, SATA_IOBP_SP1G3IR, 0, port_tx);
+
+ /* Additional Programming Requirements */
+ pch_common_sir_write(dev, 0x04, 0x00001600);
+ pch_common_sir_write(dev, 0x28, 0xa0000033);
+ reg32 = pch_common_sir_read(dev, 0x54);
+ reg32 &= 0xff000000;
+ reg32 |= 0x5555aa;
+ pch_common_sir_write(dev, 0x54, reg32);
+ pch_common_sir_write(dev, 0x64, 0xcccc8484);
+ reg32 = pch_common_sir_read(dev, 0x68);
+ reg32 &= 0xffff0000;
+ reg32 |= 0xcccc;
+ pch_common_sir_write(dev, 0x68, reg32);
+ reg32 = pch_common_sir_read(dev, 0x78);
+ reg32 &= 0x0000ffff;
+ reg32 |= 0x88880000;
+ pch_common_sir_write(dev, 0x78, reg32);
+ pch_common_sir_write(dev, 0x84, 0x001c7000);
+ pch_common_sir_write(dev, 0x88, 0x88338822);
+ pch_common_sir_write(dev, 0xa0, 0x001c7000);
+ pch_common_sir_write(dev, 0xc4, 0x0c0c0c0c);
+ pch_common_sir_write(dev, 0xc8, 0x0c0c0c0c);
+ pch_common_sir_write(dev, 0xd4, 0x10000000);
+
+ pch_iobp_update(pch, 0xea004001, 0x3fffffff, 0xc0000000);
+ pch_iobp_update(pch, 0xea00408a, 0xfffffcff, 0x00000100);
+}
+
+static void bd82x6x_sata_enable(struct udevice *dev)
+{
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ unsigned port_map;
+ const char *mode;
+ u16 map = 0;
+
+ /*
+ * Set SATA controller mode early so the resource allocator can
+ * properly assign IO/Memory resources for the controller.
+ */
+ mode = fdt_getprop(blob, node, "intel,sata-mode", NULL);
+ if (mode && !strcmp(mode, "ahci"))
+ map = 0x0060;
+ port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0);
+
+ map |= (port_map ^ 0x3f) << 8;
+ dm_pci_write_config16(dev, 0x90, map);
+}
+
+static int bd82x6x_sata_bind(struct udevice *dev)
+{
+ struct udevice *scsi_dev;
+ int ret;
+
+ if (gd->flags & GD_FLG_RELOC) {
+ ret = ahci_bind_scsi(dev, &scsi_dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bd82x6x_sata_probe(struct udevice *dev)
+{
+ struct udevice *pch;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_PCH, &pch);
+ if (ret)
+ return ret;
+
+ if (!(gd->flags & GD_FLG_RELOC))
+ bd82x6x_sata_enable(dev);
+ else {
+ bd82x6x_sata_init(dev, pch);
+ ret = ahci_probe_scsi_pci(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id bd82x6x_ahci_ids[] = {
+ { .compatible = "intel,pantherpoint-ahci" },
+ { }
+};
+
+U_BOOT_DRIVER(ahci_ivybridge_drv) = {
+ .name = "ahci_ivybridge",
+ .id = UCLASS_AHCI,
+ .of_match = bd82x6x_ahci_ids,
+ .bind = bd82x6x_sata_bind,
+ .probe = bd82x6x_sata_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/sdram.c b/roms/u-boot/arch/x86/cpu/ivybridge/sdram.c
new file mode 100644
index 000000000..dd6b8753d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/sdram.c
@@ -0,0 +1,563 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010,2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * Portions from Coreboot mainboard/google/link/romstage.c
+ * Copyright (C) 2007-2010 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <log.h>
+#include <malloc.h>
+#include <net.h>
+#include <rtc.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <syscon.h>
+#include <sysreset.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/gpio.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/mrccache.h>
+#include <asm/mrc_common.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/report_platform.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;
+
+#define CMOS_OFFSET_MRC_SEED 152
+#define CMOS_OFFSET_MRC_SEED_S3 156
+#define CMOS_OFFSET_MRC_SEED_CHK 160
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return mrc_common_board_get_usable_ram_top(total_size);
+}
+
+int dram_init_banksize(void)
+{
+ mrc_common_dram_init_banksize();
+
+ return 0;
+}
+
+static int read_seed_from_cmos(struct pei_data *pei_data)
+{
+ u16 c1, c2, checksum, seed_checksum;
+ struct udevice *dev;
+ int ret = 0;
+
+ ret = uclass_get_device(UCLASS_RTC, 0, &dev);
+ if (ret) {
+ debug("Cannot find RTC: err=%d\n", ret);
+ return -ENODEV;
+ }
+
+ /*
+ * Read scrambler seeds from CMOS RAM. We don't want to store them in
+ * SPI flash since they change on every boot and that would wear down
+ * the flash too much. So we store these in CMOS and the large MRC
+ * data in SPI flash.
+ */
+ ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed);
+ if (!ret) {
+ ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3,
+ &pei_data->scrambler_seed_s3);
+ }
+ if (ret) {
+ debug("Failed to read from RTC %s\n", dev->name);
+ return ret;
+ }
+
+ debug("Read scrambler seed 0x%08x from CMOS 0x%02x\n",
+ pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
+ debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n",
+ pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
+
+ /* Compute seed checksum and compare */
+ c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed,
+ sizeof(u32));
+ c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3,
+ sizeof(u32));
+ checksum = add_ip_checksums(sizeof(u32), c1, c2);
+
+ seed_checksum = rtc_read8(dev, CMOS_OFFSET_MRC_SEED_CHK);
+ seed_checksum |= rtc_read8(dev, CMOS_OFFSET_MRC_SEED_CHK + 1) << 8;
+
+ if (checksum != seed_checksum) {
+ debug("%s: invalid seed checksum\n", __func__);
+ pei_data->scrambler_seed = 0;
+ pei_data->scrambler_seed_s3 = 0;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int prepare_mrc_cache(struct pei_data *pei_data)
+{
+ struct mrc_data_container *mrc_cache;
+ struct mrc_region entry;
+ int ret;
+
+ ret = read_seed_from_cmos(pei_data);
+ if (ret)
+ return ret;
+ ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
+ if (ret)
+ return ret;
+ mrc_cache = mrccache_find_current(&entry);
+ if (!mrc_cache)
+ return -ENOENT;
+
+ pei_data->mrc_input = mrc_cache->data;
+ pei_data->mrc_input_len = mrc_cache->data_size;
+ debug("%s: at %p, size %x checksum %04x\n", __func__,
+ pei_data->mrc_input, pei_data->mrc_input_len,
+ mrc_cache->checksum);
+
+ return 0;
+}
+
+static int write_seeds_to_cmos(struct pei_data *pei_data)
+{
+ u16 c1, c2, checksum;
+ struct udevice *dev;
+ int ret = 0;
+
+ ret = uclass_get_device(UCLASS_RTC, 0, &dev);
+ if (ret) {
+ debug("Cannot find RTC: err=%d\n", ret);
+ return -ENODEV;
+ }
+
+ /* Save the MRC seed values to CMOS */
+ rtc_write32(dev, CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed);
+ debug("Save scrambler seed 0x%08x to CMOS 0x%02x\n",
+ pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
+
+ rtc_write32(dev, CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3);
+ debug("Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n",
+ pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
+
+ /* Save a simple checksum of the seed values */
+ c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed,
+ sizeof(u32));
+ c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3,
+ sizeof(u32));
+ checksum = add_ip_checksums(sizeof(u32), c1, c2);
+
+ rtc_write8(dev, CMOS_OFFSET_MRC_SEED_CHK, checksum & 0xff);
+ rtc_write8(dev, CMOS_OFFSET_MRC_SEED_CHK + 1, (checksum >> 8) & 0xff);
+
+ return 0;
+}
+
+/* Use this hook to save our SDRAM parameters */
+int misc_init_r(void)
+{
+ int ret;
+
+ ret = mrccache_save();
+ if (ret)
+ printf("Unable to save MRC data: %d\n", ret);
+
+ return 0;
+}
+
+static void post_system_agent_init(struct udevice *dev, struct udevice *me_dev,
+ struct pei_data *pei_data)
+{
+ uint16_t done;
+
+ /*
+ * Send ME init done for SandyBridge here. This is done inside the
+ * SystemAgent binary on IvyBridge
+ */
+ dm_pci_read_config16(dev, PCI_DEVICE_ID, &done);
+ done &= BASE_REV_MASK;
+ if (BASE_REV_SNB == done)
+ intel_early_me_init_done(dev, me_dev, ME_INIT_STATUS_SUCCESS);
+ else
+ intel_me_status(me_dev);
+
+ /* If PCIe init is skipped, set the PEG clock gating */
+ if (!pei_data->pcie_init)
+ setbits_le32(MCHBAR_REG(0x7010), 1);
+}
+
+static int recovery_mode_enabled(void)
+{
+ return false;
+}
+
+static int copy_spd(struct udevice *dev, struct pei_data *peid)
+{
+ const void *data;
+ int ret;
+
+ ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data);
+ if (ret) {
+ debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0]));
+
+ 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
+ *
+ * @dev: Northbridge device
+ */
+static int sdram_find(struct udevice *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;
+ unsigned long long tomk;
+ uint16_t ggc;
+ u32 val;
+
+ /* 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 */
+ dm_pci_read_config32(dev, TOUUD + 4, &val);
+ touud = (uint64_t)val << 32;
+ dm_pci_read_config32(dev, TOUUD, &val);
+ touud |= val;
+
+ /* Top of Lower Usable DRAM */
+ dm_pci_read_config32(dev, TOLUD, &tolud);
+
+ /* Top of Memory - does not account for any UMA */
+ dm_pci_read_config32(dev, 0xa4, &val);
+ tom = (uint64_t)val << 32;
+ dm_pci_read_config32(dev, 0xa0, &val);
+ tom |= val;
+
+ debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom);
+
+ /* ME UMA needs excluding if total memory <4GB */
+ dm_pci_read_config32(dev, 0x74, &val);
+ me_base = (uint64_t)val << 32;
+ dm_pci_read_config32(dev, 0x70, &val);
+ me_base |= val;
+
+ 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;
+ debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10);
+ }
+
+ /* Graphics memory comes next */
+ dm_pci_read_config16(dev, GGC, &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;
+
+ /* GTT Graphics Stolen Memory Size (GGMS) */
+ uma_size = ((ggc >> 8) & 0x3) * 1024ULL;
+ tomk -= uma_size;
+ uma_memory_base = tomk * 1024ULL;
+ debug(" and %uM GTT\n", uma_size >> 10);
+ }
+
+ /* Calculate TSEG size from its base which must be below GTT */
+ dm_pci_read_config32(dev, 0xb8, &tseg_base);
+ uma_size = (uma_memory_base - tseg_base) >> 10;
+ tomk -= uma_size;
+ uma_memory_base = tomk * 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 */
+ mrc_add_memory_area(info, 1 << 20, 2 << 28);
+ mrc_add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28);
+ mrc_add_memory_area(info, (4 << 28) + (2 << 20), tseg_base);
+ mrc_add_memory_area(info, 1ULL << 32, touud);
+
+ /* Add MTRRs for memory */
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
+ mtrr_add_request(MTRR_TYPE_WRBACK, 2ULL << 30, 512 << 20);
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0xaULL << 28, 256 << 20);
+ mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base, 16 << 20);
+ mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base + (16 << 20),
+ 32 << 20);
+
+ /*
+ * 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)
+{
+ struct pei_data _pei_data __aligned(8) = {
+ .pei_version = PEI_VERSION,
+ .mchbar = MCH_BASE_ADDRESS,
+ .dmibar = DEFAULT_DMIBAR,
+ .epbar = DEFAULT_EPBAR,
+ .pciexbar = CONFIG_PCIE_ECAM_BASE,
+ .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 */
+ },
+ };
+ struct pei_data *pei_data = &_pei_data;
+ struct udevice *dev, *me_dev;
+ int ret;
+
+ /* We need the pinctrl set up early */
+ ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev);
+ if (ret) {
+ debug("%s: Could not get pinconf (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
+ if (ret) {
+ debug("%s: Could not get northbridge (ret=%d)\n", __func__,
+ ret);
+ return ret;
+ }
+ ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
+ if (ret) {
+ debug("%s: Could not get ME (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+ ret = copy_spd(dev, pei_data);
+ if (ret) {
+ debug("%s: Could not get SPD (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+ pei_data->boot_mode = gd->arch.pei_boot_mode;
+ debug("Boot mode %d\n", gd->arch.pei_boot_mode);
+ debug("mrc_input %p\n", pei_data->mrc_input);
+
+ /*
+ * Do not pass MRC data in for recovery mode boot,
+ * Always pass it in for S3 resume.
+ */
+ if (!recovery_mode_enabled() ||
+ pei_data->boot_mode == PEI_BOOT_RESUME) {
+ ret = prepare_mrc_cache(pei_data);
+ if (ret)
+ debug("prepare_mrc_cache failed: %d\n", ret);
+ }
+
+ /* 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");
+ sysreset_walk_halt(SYSRESET_COLD);
+ }
+
+ /* Pass console handler in pei_data */
+ pei_data->tx_byte = sdram_console_tx_byte;
+
+ /* Wait for ME to be ready */
+ ret = intel_early_me_init(me_dev);
+ if (ret) {
+ debug("%s: Could not init ME (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+ ret = intel_early_me_uma_size(me_dev);
+ if (ret < 0) {
+ debug("%s: Could not get UMA size (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ ret = mrc_common_init(dev, pei_data, false);
+ if (ret) {
+ debug("%s: mrc_common_init() failed (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ ret = sdram_find(dev);
+ if (ret) {
+ debug("%s: sdram_find() failed (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+ gd->ram_size = gd->arch.meminfo.total_32bit_memory;
+
+ debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len,
+ pei_data->mrc_output);
+
+ post_system_agent_init(dev, me_dev, pei_data);
+ report_memory_config();
+
+ /* S3 resume: don't save scrambler seed or MRC data */
+ if (pei_data->boot_mode != PEI_BOOT_RESUME) {
+ struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
+
+ /*
+ * This will be copied to SDRAM in reserve_arch(), then written
+ * to SPI flash in mrccache_save()
+ */
+ mrc->buf = (char *)pei_data->mrc_output;
+ mrc->len = pei_data->mrc_output_len;
+ ret = write_seeds_to_cmos(pei_data);
+ if (ret)
+ debug("Failed to write seeds to CMOS: %d\n", ret);
+ }
+
+ writew(0xCAFE, MCHBAR_REG(SSKPD));
+ if (ret)
+ return ret;
+
+ rcba_config();
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/ivybridge/sdram_nop.c b/roms/u-boot/arch/x86/cpu/ivybridge/sdram_nop.c
new file mode 100644
index 000000000..51dfe23f9
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ivybridge/sdram_nop.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+ gd->ram_size = 1ULL << 31;
+ gd->bd->bi_dram[0].start = 0;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+
+ return 0;
+}