aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/x86/cpu/broadwell
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/broadwell
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/x86/cpu/broadwell')
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/Kconfig42
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/Makefile33
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/adsp.c157
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/cpu.c110
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/cpu_from_spl.c65
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/cpu_full.c671
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/iobp.c144
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/lpc.c78
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/me.c58
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/northbridge.c159
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/pch.c684
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/pinctrl_broadwell.c280
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/power_state.c89
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/refcode.c129
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/sata.c271
-rw-r--r--roms/u-boot/arch/x86/cpu/broadwell/sdram.c211
16 files changed, 3181 insertions, 0 deletions
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/Kconfig b/roms/u-boot/arch/x86/cpu/broadwell/Kconfig
new file mode 100644
index 000000000..5b015c89d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/Kconfig
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2016 Google Inc.
+#
+
+config INTEL_BROADWELL
+ bool
+ select CACHE_MRC_BIN
+ select ARCH_EARLY_INIT_R
+ imply HAVE_INTEL_ME
+ imply ENABLE_MRC_CACHE
+ imply AHCI_PCI
+ imply ICH_SPI
+ imply INTEL_BROADWELL_GPIO
+ imply SCSI
+ imply SCSI_AHCI
+ imply SPI_FLASH
+ imply USB
+ imply USB_EHCI_HCD
+ imply VIDEO_BROADWELL_IGD
+
+if INTEL_BROADWELL
+
+config DCACHE_RAM_BASE
+ default 0xff7c0000
+
+config DCACHE_RAM_SIZE
+ default 0x40000
+
+config DCACHE_RAM_MRC_VAR_SIZE
+ default 0x30000
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select SMM_TSEG
+ select X86_RAMTEST
+
+config SMM_TSEG_SIZE
+ hex
+ default 0x800000
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/Makefile b/roms/u-boot/arch/x86/cpu/broadwell/Makefile
new file mode 100644
index 000000000..52d56c65b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/Makefile
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2016 Google, Inc
+
+obj-y += adsp.o
+obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += cpu.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += cpu_full.o
+
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+obj-y += cpu_from_spl.o
+obj-y += cpu_full.o
+obj-y += refcode.o
+endif
+ifndef CONFIG_SPL_BUILD
+# obj-y += cpu_from_spl.o
+endif
+endif
+
+ifeq ($(CONFIG_$(SPL_TPL_)X86_32BIT_INIT),)
+#obj-y += cpu_from_spl.o
+endif
+
+obj-y += iobp.o
+obj-y += lpc.o
+obj-y += me.o
+obj-y += northbridge.o
+obj-y += pch.o
+obj-y += pinctrl_broadwell.o
+obj-y += power_state.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += refcode.o
+obj-y += sata.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += sdram.o
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/adsp.c b/roms/u-boot/arch/x86/cpu/broadwell/adsp.c
new file mode 100644
index 000000000..1fa182378
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/adsp.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for Intel Application Digital Signal Processor
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot file of the same name
+ */
+
+#define LOG_CATEGORY UCLASS_SYSCON
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/cpu.h>
+#include <asm/intel_regs.h>
+#include <asm/arch/adsp.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/rcb.h>
+
+enum pci_type_t {
+ LYNX_POINT,
+ WILDCAT_POINT,
+};
+
+struct broadwell_adsp_priv {
+ bool adsp_d3_pg_enable;
+ bool adsp_sram_pg_enable;
+ bool sio_acpi_mode;
+};
+
+static int broadwell_adsp_probe(struct udevice *dev)
+{
+ struct broadwell_adsp_priv *priv = dev_get_priv(dev);
+ enum pci_type_t type;
+ u32 bar0, bar1;
+ u32 tmp32;
+
+ /* Find BAR0 and BAR1 */
+ bar0 = dm_pci_read_bar32(dev, 0);
+ if (!bar0)
+ return -EINVAL;
+ bar1 = dm_pci_read_bar32(dev, 1);
+ if (!bar1)
+ return -EINVAL;
+
+ /*
+ * Set LTR value in DSP shim LTR control register to 3ms
+ * SNOOP_REQ[13]=1b SNOOP_SCALE[12:10]=100b (1ms) SNOOP_VAL[9:0]=3h
+ */
+ type = dev_get_driver_data(dev);
+ tmp32 = type == WILDCAT_POINT ? ADSP_SHIM_BASE_WPT : ADSP_SHIM_BASE_LPT;
+ writel(ADSP_SHIM_LTRC_VALUE, bar0 + tmp32);
+
+ /* Program VDRTCTL2 D19:F0:A8[31:0] = 0x00000fff */
+ dm_pci_write_config32(dev, ADSP_PCI_VDRTCTL2, ADSP_VDRTCTL2_VALUE);
+
+ /* Program ADSP IOBP VDLDAT1 to 0x040100 */
+ pch_iobp_write(ADSP_IOBP_VDLDAT1, ADSP_VDLDAT1_VALUE);
+
+ /* Set D3 Power Gating Enable in D19:F0:A0 based on PCH type */
+ dm_pci_read_config32(dev, ADSP_PCI_VDRTCTL0, &tmp32);
+ if (type == WILDCAT_POINT) {
+ if (priv->adsp_d3_pg_enable) {
+ tmp32 &= ~ADSP_VDRTCTL0_D3PGD_WPT;
+ if (priv->adsp_sram_pg_enable)
+ tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_WPT;
+ else
+ tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_WPT;
+ } else {
+ tmp32 |= ADSP_VDRTCTL0_D3PGD_WPT;
+ }
+ } else {
+ if (priv->adsp_d3_pg_enable) {
+ tmp32 &= ~ADSP_VDRTCTL0_D3PGD_LPT;
+ if (priv->adsp_sram_pg_enable)
+ tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_LPT;
+ else
+ tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_LPT;
+ } else {
+ tmp32 |= ADSP_VDRTCTL0_D3PGD_LPT;
+ }
+ }
+ dm_pci_write_config32(dev, ADSP_PCI_VDRTCTL0, tmp32);
+
+ /* Set PSF Snoop to SA, RCBA+0x3350[10]=1b */
+ setbits_le32(RCB_REG(0x3350), 1 << 10);
+
+ /* Set DSP IOBP PMCTL 0x1e0=0x3f */
+ pch_iobp_write(ADSP_IOBP_PMCTL, ADSP_PMCTL_VALUE);
+
+ if (priv->sio_acpi_mode) {
+ /* Configure for ACPI mode */
+ log_info("ADSP: Enable ACPI Mode IRQ3\n");
+
+ /* Set interrupt de-assert/assert opcode override to IRQ3 */
+ pch_iobp_write(ADSP_IOBP_VDLDAT2, ADSP_IOBP_ACPI_IRQ3);
+
+ /* Enable IRQ3 in RCBA */
+ setbits_le32(RCB_REG(ACPIIRQEN), ADSP_ACPI_IRQEN);
+
+ /* Set ACPI Interrupt Enable Bit */
+ pch_iobp_update(ADSP_IOBP_PCICFGCTL, ~ADSP_PCICFGCTL_SPCBAD,
+ ADSP_PCICFGCTL_ACPIIE);
+
+ /* Put ADSP in D3hot */
+ clrbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
+ } else {
+ log_info("ADSP: Enable PCI Mode IRQ23\n");
+
+ /* Configure for PCI mode */
+ dm_pci_write_config32(dev, PCI_INTERRUPT_LINE, ADSP_PCI_IRQ);
+
+ /* Clear ACPI Interrupt Enable Bit */
+ pch_iobp_update(ADSP_IOBP_PCICFGCTL,
+ ~(ADSP_PCICFGCTL_SPCBAD |
+ ADSP_PCICFGCTL_ACPIIE), 0);
+ }
+
+ return 0;
+}
+
+static int broadwell_adsp_of_to_plat(struct udevice *dev)
+{
+ struct broadwell_adsp_priv *priv = dev_get_priv(dev);
+
+ priv->adsp_d3_pg_enable = dev_read_bool(dev, "intel,adsp-d3-pg-enable");
+ priv->adsp_sram_pg_enable = dev_read_bool(dev,
+ "intel,adsp-sram-pg-enable");
+ priv->sio_acpi_mode = dev_read_bool(dev, "intel,sio-acpi-mode");
+
+ return 0;
+}
+
+static const struct udevice_id broadwell_adsp_ids[] = {
+ { .compatible = "intel,wildcatpoint-adsp", .data = WILDCAT_POINT },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_adsp_drv) = {
+ .name = "adsp",
+ .id = UCLASS_SYSCON,
+ .of_to_plat = broadwell_adsp_of_to_plat,
+ .of_match = broadwell_adsp_ids,
+ .bind = dm_scan_fdt_dev,
+ .probe = broadwell_adsp_probe,
+};
+
+static struct pci_device_id broadwell_adsp_supported[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_WILDCATPOINT_ADSP) },
+ { },
+};
+
+U_BOOT_PCI_DEVICE(broadwell_adsp_drv, broadwell_adsp_supported);
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/cpu.c b/roms/u-boot/arch/x86/cpu/broadwell/cpu.c
new file mode 100644
index 000000000..3832a97f2
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/cpu.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * Based on code from coreboot src/soc/intel/broadwell/cpu.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cpu.h>
+#include <init.h>
+#include <log.h>
+#include <asm/cpu.h>
+#include <asm/cpu_x86.h>
+#include <asm/cpu_common.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/lpc_common.h>
+#include <asm/msr.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/turbo.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/rcb.h>
+
+int arch_cpu_init_dm(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ /* Start up the LPC so we have serial */
+ ret = uclass_first_device(UCLASS_LPC, &dev);
+ if (ret)
+ return ret;
+ if (!dev)
+ return -ENODEV;
+ ret = cpu_set_flex_ratio_to_tdp_nominal();
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void set_max_freq(void)
+{
+ msr_t msr, perf_ctl;
+
+ if (cpu_config_tdp_levels()) {
+ /* Set to nominal TDP ratio */
+ msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else {
+ /* Platform Info bits 15:8 give max ratio */
+ msr = msr_read(MSR_PLATFORM_INFO);
+ perf_ctl.lo = msr.lo & 0xff00;
+ }
+
+ perf_ctl.hi = 0;
+ msr_write(MSR_IA32_PERF_CTL, perf_ctl);
+
+ debug("CPU: frequency set to %d MHz\n",
+ ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ);
+}
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+#ifdef CONFIG_TPL
+ /* Do a mini-init if TPL has already done the full init */
+ return x86_cpu_reinit_f();
+#else
+ return x86_cpu_init_f();
+#endif
+}
+
+int checkcpu(void)
+{
+ int ret;
+
+ set_max_freq();
+
+ ret = cpu_common_init();
+ if (ret)
+ return ret;
+ gd->arch.pei_boot_mode = PEI_BOOT_NONE;
+
+ 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);
+
+ return 0;
+}
+
+void board_debug_uart_init(void)
+{
+ /* com1 / com2 decode range */
+ pci_x86_write_config(PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16);
+
+ pci_x86_write_config(PCH_DEV_LPC, LPC_EN, COMA_LPC_EN, PCI_SIZE_16);
+}
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/cpu_from_spl.c b/roms/u-boot/arch/x86/cpu/broadwell/cpu_from_spl.c
new file mode 100644
index 000000000..e5f62e718
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/cpu_from_spl.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <cpu_func.h>
+#include <debug_uart.h>
+#include <handoff.h>
+#include <init.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/mtrr.h>
+
+int misc_init_r(void)
+{
+ return 0;
+}
+
+int dram_init(void)
+{
+ struct spl_handoff *ho;
+
+ ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(*ho));
+ if (!ho)
+ return log_msg_ret("Missing SPL hand-off info", -ENOENT);
+ handoff_load_dram_size(ho);
+#ifdef CONFIG_TPL
+ /* TODO(sjg@chromium.org): MTRR cannot be adjusted without a hang */
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
+#else
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0, gd->ram_size);
+ mtrr_commit(true);
+#endif
+
+ return 0;
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return 0;
+}
+
+void board_debug_uart_init(void)
+{
+}
+
+int dram_init_banksize(void)
+{
+ struct spl_handoff *ho;
+
+ ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(*ho));
+ if (!ho)
+ return log_msg_ret("Missing SPL hand-off info", -ENOENT);
+ handoff_load_dram_banks(ho);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/cpu_full.c b/roms/u-boot/arch/x86/cpu/broadwell/cpu_full.c
new file mode 100644
index 000000000..2049dbfe2
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/cpu_full.c
@@ -0,0 +1,671 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * Based on code from coreboot src/soc/intel/broadwell/cpu.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cpu.h>
+#include <init.h>
+#include <log.h>
+#include <asm/cpu.h>
+#include <asm/cpu_x86.h>
+#include <asm/cpu_common.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/msr.h>
+#include <asm/post.h>
+#include <asm/turbo.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/rcb.h>
+#include <linux/delay.h>
+
+struct cpu_broadwell_priv {
+ bool ht_disabled;
+};
+
+/* 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,
+};
+
+#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
+int arch_cpu_init(void)
+{
+ return 0;
+}
+#endif
+
+/*
+ * The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
+ * the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
+ * when a core is woken up
+ */
+static int pcode_ready(void)
+{
+ int wait_count;
+ const int delay_step = 10;
+
+ wait_count = 0;
+ do {
+ if (!(readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) &
+ MAILBOX_RUN_BUSY))
+ return 0;
+ wait_count += delay_step;
+ udelay(delay_step);
+ } while (wait_count < 1000);
+
+ return -ETIMEDOUT;
+}
+
+static u32 pcode_mailbox_read(u32 command)
+{
+ int ret;
+
+ ret = pcode_ready();
+ if (ret) {
+ debug("PCODE: mailbox timeout on wait ready\n");
+ return ret;
+ }
+
+ /* Send command and start transaction */
+ writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+ ret = pcode_ready();
+ if (ret) {
+ debug("PCODE: mailbox timeout on completion\n");
+ return ret;
+ }
+
+ /* Read mailbox */
+ return readl(MCHBAR_REG(BIOS_MAILBOX_DATA));
+}
+
+static int pcode_mailbox_write(u32 command, u32 data)
+{
+ int ret;
+
+ ret = pcode_ready();
+ if (ret) {
+ debug("PCODE: mailbox timeout on wait ready\n");
+ return ret;
+ }
+
+ writel(data, MCHBAR_REG(BIOS_MAILBOX_DATA));
+
+ /* Send command and start transaction */
+ writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+ ret = pcode_ready();
+ if (ret) {
+ debug("PCODE: mailbox timeout on completion\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* @dev is the CPU device */
+static void initialize_vr_config(struct udevice *dev)
+{
+ int ramp, min_vid;
+ msr_t msr;
+
+ debug("Initializing VR config\n");
+
+ /* Configure VR_CURRENT_CONFIG */
+ msr = msr_read(MSR_VR_CURRENT_CONFIG);
+ /*
+ * Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid
+ * on ULT systems
+ */
+ msr.hi &= 0xc0000000;
+ msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A */
+ msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A */
+ msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A */
+ msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */
+ /* Leave the max instantaneous current limit (12:0) to default */
+ msr_write(MSR_VR_CURRENT_CONFIG, msr);
+
+ /* Configure VR_MISC_CONFIG MSR */
+ msr = msr_read(MSR_VR_MISC_CONFIG);
+ /* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format */
+ msr.hi &= ~(0x3ff << (40 - 32));
+ msr.hi |= (0x200 << (40 - 32)); /* 1.0 */
+ /* Set IOUT_OFFSET to 0 */
+ msr.hi &= ~0xff;
+ /* Set entry ramp rate to slow */
+ msr.hi &= ~(1 << (51 - 32));
+ /* Enable decay mode on C-state entry */
+ msr.hi |= (1 << (52 - 32));
+ /* Set the slow ramp rate */
+ msr.hi &= ~(0x3 << (53 - 32));
+ /* Configure the C-state exit ramp rate */
+ ramp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "intel,slow-ramp", -1);
+ if (ramp != -1) {
+ /* Configured slow ramp rate */
+ msr.hi |= ((ramp & 0x3) << (53 - 32));
+ /* Set exit ramp rate to slow */
+ msr.hi &= ~(1 << (50 - 32));
+ } else {
+ /* Fast ramp rate / 4 */
+ msr.hi |= (0x01 << (53 - 32));
+ /* Set exit ramp rate to fast */
+ msr.hi |= (1 << (50 - 32));
+ }
+ /* Set MIN_VID (31:24) to allow CPU to have full control */
+ msr.lo &= ~0xff000000;
+ min_vid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "intel,min-vid", 0);
+ msr.lo |= (min_vid & 0xff) << 24;
+ msr_write(MSR_VR_MISC_CONFIG, msr);
+
+ /* Configure VR_MISC_CONFIG2 MSR */
+ msr = msr_read(MSR_VR_MISC_CONFIG2);
+ msr.lo &= ~0xffff;
+ /*
+ * Allow CPU to control minimum voltage completely (15:8) and
+ * set the fast ramp voltage in 10mV steps
+ */
+ if (cpu_get_family_model() == BROADWELL_FAMILY_ULT)
+ msr.lo |= 0x006a; /* 1.56V */
+ else
+ msr.lo |= 0x006f; /* 1.60V */
+ msr_write(MSR_VR_MISC_CONFIG2, msr);
+
+ /* Set C9/C10 VCC Min */
+ pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
+}
+
+static int calibrate_24mhz_bclk(void)
+{
+ int err_code;
+ int ret;
+
+ ret = pcode_ready();
+ if (ret)
+ return ret;
+
+ /* A non-zero value initiates the PCODE calibration */
+ writel(~0, MCHBAR_REG(BIOS_MAILBOX_DATA));
+ writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL,
+ MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+ ret = pcode_ready();
+ if (ret)
+ return ret;
+
+ err_code = readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) & 0xff;
+
+ debug("PCODE: 24MHz BLCK calibration response: %d\n", err_code);
+
+ /* Read the calibrated value */
+ writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION,
+ MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
+
+ ret = pcode_ready();
+ if (ret)
+ return ret;
+
+ debug("PCODE: 24MHz BLCK calibration value: 0x%08x\n",
+ readl(MCHBAR_REG(BIOS_MAILBOX_DATA)));
+
+ return 0;
+}
+
+static void configure_pch_power_sharing(void)
+{
+ u32 pch_power, pch_power_ext, pmsync, pmsync2;
+ int i;
+
+ /* Read PCH Power levels from PCODE */
+ pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER);
+ pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT);
+
+ debug("PCH Power: PCODE Levels 0x%08x 0x%08x\n", pch_power,
+ pch_power_ext);
+
+ pmsync = readl(RCB_REG(PMSYNC_CONFIG));
+ pmsync2 = readl(RCB_REG(PMSYNC_CONFIG2));
+
+ /*
+ * Program PMSYNC_TPR_CONFIG PCH power limit values
+ * pmsync[0:4] = mailbox[0:5]
+ * pmsync[8:12] = mailbox[6:11]
+ * pmsync[16:20] = mailbox[12:17]
+ */
+ for (i = 0; i < 3; i++) {
+ u32 level = pch_power & 0x3f;
+
+ pch_power >>= 6;
+ pmsync &= ~(0x1f << (i * 8));
+ pmsync |= (level & 0x1f) << (i * 8);
+ }
+ writel(pmsync, RCB_REG(PMSYNC_CONFIG));
+
+ /*
+ * Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values
+ * pmsync2[0:4] = mailbox[23:18]
+ * pmsync2[8:12] = mailbox_ext[6:11]
+ * pmsync2[16:20] = mailbox_ext[12:17]
+ * pmsync2[24:28] = mailbox_ext[18:22]
+ */
+ pmsync2 &= ~0x1f;
+ pmsync2 |= pch_power & 0x1f;
+
+ for (i = 1; i < 4; i++) {
+ u32 level = pch_power_ext & 0x3f;
+
+ pch_power_ext >>= 6;
+ pmsync2 &= ~(0x1f << (i * 8));
+ pmsync2 |= (level & 0x1f) << (i * 8);
+ }
+ writel(pmsync2, RCB_REG(PMSYNC_CONFIG2));
+}
+
+static int bsp_init_before_ap_bringup(struct udevice *dev)
+{
+ int ret;
+
+ initialize_vr_config(dev);
+ ret = calibrate_24mhz_bclk();
+ if (ret)
+ return ret;
+ configure_pch_power_sharing();
+
+ return 0;
+}
+
+static void set_max_ratio(void)
+{
+ msr_t msr, perf_ctl;
+
+ perf_ctl.hi = 0;
+
+ /* Check for configurable TDP option */
+ if (turbo_get_state() == TURBO_ENABLED) {
+ msr = msr_read(MSR_TURBO_RATIO_LIMIT);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else if (cpu_config_tdp_levels()) {
+ /* Set to nominal TDP ratio */
+ msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else {
+ /* Platform Info bits 15:8 give max ratio */
+ msr = msr_read(MSR_PLATFORM_INFO);
+ perf_ctl.lo = msr.lo & 0xff00;
+ }
+ msr_write(MSR_IA32_PERF_CTL, perf_ctl);
+
+ debug("cpu: frequency set to %d\n",
+ ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ);
+}
+
+int broadwell_init(struct udevice *dev)
+{
+ struct cpu_broadwell_priv *priv = dev_get_priv(dev);
+ int num_threads;
+ int num_cores;
+ msr_t msr;
+ int ret;
+
+ msr = msr_read(CORE_THREAD_COUNT_MSR);
+ num_threads = (msr.lo >> 0) & 0xffff;
+ num_cores = (msr.lo >> 16) & 0xffff;
+ debug("CPU has %u cores, %u threads enabled\n", num_cores,
+ num_threads);
+
+ priv->ht_disabled = num_threads == num_cores;
+
+ ret = bsp_init_before_ap_bringup(dev);
+ if (ret)
+ return ret;
+
+ set_max_ratio();
+
+ return ret;
+}
+
+static void configure_mca(void)
+{
+ msr_t msr;
+ const unsigned int mcg_cap_msr = 0x179;
+ int i;
+ int num_banks;
+
+ msr = msr_read(mcg_cap_msr);
+ num_banks = msr.lo & 0xff;
+ msr.lo = 0;
+ msr.hi = 0;
+ /*
+ * TODO(adurbin): This should only be done on a cold boot. Also, some
+ * of these banks are core vs package scope. For now every CPU clears
+ * every bank
+ */
+ for (i = 0; i < num_banks; i++)
+ msr_write(MSR_IA32_MC0_STATUS + (i * 4), 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_c_states(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_PMG_CST_CONFIG_CONTROL);
+ msr.lo |= (1 << 31); /* Timed MWAIT Enable */
+ msr.lo |= (1 << 30); /* Package c-state Undemotion Enable */
+ msr.lo |= (1 << 29); /* Package c-state Demotion Enable */
+ 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 */
+ /* The deepest package c-state defaults to factory-configured value */
+ msr_write(MSR_PMG_CST_CONFIG_CONTROL, 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);
+
+ /* C-state Interrupt Response Latency Control 0 - package C3 latency */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
+ msr_write(MSR_C_STATE_LATENCY_CONTROL_0, msr);
+
+ /* C-state Interrupt Response Latency Control 1 */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
+ msr_write(MSR_C_STATE_LATENCY_CONTROL_1, msr);
+
+ /* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
+ msr_write(MSR_C_STATE_LATENCY_CONTROL_2, msr);
+
+ /* C-state Interrupt Response Latency Control 3 - package C8 */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_3_LIMIT;
+ msr_write(MSR_C_STATE_LATENCY_CONTROL_3, msr);
+
+ /* C-state Interrupt Response Latency Control 4 - package C9 */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_4_LIMIT;
+ msr_write(MSR_C_STATE_LATENCY_CONTROL_4, msr);
+
+ /* C-state Interrupt Response Latency Control 5 - package C10 */
+ msr.hi = 0;
+ msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_5_LIMIT;
+ msr_write(MSR_C_STATE_LATENCY_CONTROL_5, msr);
+}
+
+static void configure_misc(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ msr.lo |= MISC_ENABLE_FAST_STRING;
+ msr.lo |= MISC_ENABLE_TM1;
+ msr.lo |= MISC_ENABLE_ENHANCED_SPEEDSTEP;
+ msr_write(MSR_IA32_MISC_ENABLE, msr);
+
+ /* Disable thermal interrupts */
+ msr.lo = 0;
+ msr.hi = 0;
+ msr_write(MSR_IA32_THERM_INTERRUPT, msr);
+
+ /* Enable package critical interrupt only */
+ msr.lo = 1 << 4;
+ msr.hi = 0;
+ msr_write(MSR_IA32_PACKAGE_THERM_INTERRUPT, 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(MSR_IA32_PLATFORM_DCA_CAP);
+ msr.lo |= 1;
+ msr_write(MSR_IA32_PLATFORM_DCA_CAP, msr);
+ }
+}
+
+static void set_energy_perf_bias(u8 policy)
+{
+ msr_t msr;
+ int ecx;
+
+ /* Determine if energy efficient policy is supported */
+ ecx = cpuid_ecx(0x6);
+ if (!(ecx & (1 << 3)))
+ return;
+
+ /* Energy Policy is bits 3:0 */
+ msr = msr_read(MSR_IA32_ENERGY_PERFORMANCE_BIAS);
+ msr.lo &= ~0xf;
+ msr.lo |= policy & 0xf;
+ msr_write(MSR_IA32_ENERGY_PERFORMANCE_BIAS, msr);
+
+ debug("cpu: energy policy set to %u\n", policy);
+}
+
+/* All CPUs including BSP will run the following function */
+static void cpu_core_init(struct udevice *dev)
+{
+ /* Clear out pending MCEs */
+ configure_mca();
+
+ /* Enable the local cpu apics */
+ enable_lapic_tpr();
+
+ /* Configure C States */
+ configure_c_states();
+
+ /* Configure Enhanced SpeedStep and Thermal Sensors */
+ configure_misc();
+
+ /* Thermal throttle activation offset */
+ cpu_configure_thermal_target(dev);
+
+ /* Enable Direct Cache Access */
+ configure_dca_cap();
+
+ /* Set energy policy */
+ set_energy_perf_bias(ENERGY_POLICY_NORMAL);
+
+ /* Enable Turbo */
+ turbo_enable();
+}
+
+/*
+ * Configure processor power limits if possible
+ * This must be done AFTER set of BIOS_RESET_CPL
+ */
+void cpu_set_power_limits(int power_limit_1_time)
+{
+ msr_t msr;
+ msr_t limit;
+ uint power_unit;
+ uint tdp, min_power, max_power, max_time;
+ u8 power_limit_1_val;
+
+ msr = msr_read(MSR_PLATFORM_INFO);
+ if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
+ power_limit_1_time = 28;
+
+ 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 server SKU */
+
+ msr_write(MSR_PKG_POWER_LIMIT, limit);
+
+ /* Set power limit values in MCHBAR as well */
+ writel(limit.lo, MCHBAR_REG(MCH_PKG_POWER_LIMIT_LO));
+ writel(limit.hi, MCHBAR_REG(MCH_PKG_POWER_LIMIT_HI));
+
+ /* Set DDR RAPL power limit by copying from MMIO to MSR */
+ msr.lo = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_LO));
+ msr.hi = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_HI));
+ msr_write(MSR_DDR_RAPL_LIMIT, msr);
+
+ /* Use nominal TDP values for CPUs with configurable TDP */
+ if (cpu_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 int broadwell_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+}
+
+static int broadwell_get_count(const struct udevice *dev)
+{
+ return 4;
+}
+
+static int cpu_x86_broadwell_probe(struct udevice *dev)
+{
+ if (dev_seq(dev) == 0) {
+ cpu_core_init(dev);
+ return broadwell_init(dev);
+ }
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_x86_broadwell_ops = {
+ .get_desc = cpu_x86_get_desc,
+ .get_info = broadwell_get_info,
+ .get_count = broadwell_get_count,
+ .get_vendor = cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_broadwell_ids[] = {
+ { .compatible = "intel,core-i3-gen5" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
+ .name = "cpu_x86_broadwell",
+ .id = UCLASS_CPU,
+ .of_match = cpu_x86_broadwell_ids,
+ .bind = cpu_x86_bind,
+ .probe = cpu_x86_broadwell_probe,
+ .ops = &cpu_x86_broadwell_ops,
+ .priv_auto = sizeof(struct cpu_broadwell_priv),
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/iobp.c b/roms/u-boot/arch/x86/cpu/broadwell/iobp.c
new file mode 100644
index 000000000..cb5595c93
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/iobp.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * Modified from coreboot
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/arch/pch.h>
+#include <linux/delay.h>
+
+#define IOBP_RETRY 1000
+
+/* IO Buffer Programming */
+#define IOBPIRI 0x2330
+#define IOBPD 0x2334
+#define IOBPS 0x2338
+#define IOBPS_READY 0x0001
+#define IOBPS_TX_MASK 0x0006
+#define IOBPS_MASK 0xff00
+#define IOBPS_READ 0x0600
+#define IOBPS_WRITE 0x0700
+#define IOBPU 0x233a
+#define IOBPU_MAGIC 0xf000
+#define IOBP_PCICFG_READ 0x0400
+#define IOBP_PCICFG_WRITE 0x0500
+
+static inline int iobp_poll(void)
+{
+ unsigned try;
+
+ for (try = IOBP_RETRY; try > 0; try--) {
+ u16 status = readw(RCB_REG(IOBPS));
+ if ((status & IOBPS_READY) == 0)
+ return 1;
+ udelay(10);
+ }
+
+ printf("IOBP: timeout waiting for transaction to complete\n");
+ return 0;
+}
+
+int pch_iobp_trans_start(u32 address, int op)
+{
+ if (!iobp_poll())
+ return 0;
+
+ /* Set the address */
+ writel(address, RCB_REG(IOBPIRI));
+
+ /* READ OPCODE */
+ clrsetbits_le16(RCB_REG(IOBPS), IOBPS_MASK, op);
+
+ return 1;
+}
+
+int pch_iobp_trans_finish(void)
+{
+ u16 status;
+
+ /* Undocumented magic */
+ writew(IOBPU_MAGIC, RCB_REG(IOBPU));
+
+ /* Set ready bit */
+ setbits_le16(RCB_REG(IOBPS), IOBPS_READY);
+
+ if (!iobp_poll())
+ return 1;
+
+ /* Check for successful transaction */
+ status = readw(RCB_REG(IOBPS));
+ if (status & IOBPS_TX_MASK)
+ return 1;
+
+ return 0;
+}
+
+u32 pch_iobp_read(u32 address)
+{
+ if (!pch_iobp_trans_start(address, IOBPS_READ))
+ return 0;
+ if (pch_iobp_trans_finish()) {
+ printf("IOBP: read 0x%08x failed\n", address);
+ return 0;
+ }
+
+ /* Read IOBP data */
+ return readl(RCB_REG(IOBPD));
+}
+
+int pch_iobp_write(u32 address, u32 data)
+{
+ if (!pch_iobp_trans_start(address, IOBPS_WRITE))
+ return -EIO;
+
+ writel(data, RCB_REG(IOBPD));
+
+ if (pch_iobp_trans_finish()) {
+ printf("IOBP: write 0x%08x failed\n", address);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
+{
+ u32 data = pch_iobp_read(address);
+
+ /* Update the data */
+ data &= andvalue;
+ data |= orvalue;
+
+ return pch_iobp_write(address, data);
+}
+
+int pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp)
+{
+ if (!data || !resp)
+ return 0;
+
+ *resp = -1;
+ if (!iobp_poll())
+ return -EIO;
+
+ writel(addr, RCB_REG(IOBPIRI));
+ clrsetbits_le16(RCB_REG(IOBPS), 0xff00, op_code);
+ writew(IOBPU_MAGIC | route_id, RCB_REG(IOBPU));
+
+ writel(*data, RCB_REG(IOBPD));
+ /* Set IOBPS[0] to trigger IOBP transaction*/
+ setbits_le16(RCB_REG(IOBPS), 1);
+
+ if (!iobp_poll())
+ return -EIO;
+
+ *resp = (readw(RCB_REG(IOBPS)) & IOBPS_TX_MASK) >> 1;
+ *data = readl(RCB_REG(IOBPD));
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/lpc.c b/roms/u-boot/arch/x86/cpu/broadwell/lpc.c
new file mode 100644
index 000000000..d2638a4e7
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/lpc.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * From coreboot broadwell support
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <pch.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/lpc_common.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/spi.h>
+
+static void set_spi_speed(void)
+{
+ u32 fdod;
+ u8 ssfc;
+
+ /* Observe SPI Descriptor Component Section 0 */
+ writel(0x1000, SPI_REG(SPIBAR_FDOC));
+
+ /* Extract the Write/Erase SPI Frequency from descriptor */
+ fdod = readl(SPI_REG(SPIBAR_FDOD));
+ fdod >>= 24;
+ fdod &= 7;
+
+ /* Set Software Sequence frequency to match */
+ ssfc = readb(SPI_REG(SPIBAR_SSFC + 2));
+ ssfc &= ~7;
+ ssfc |= fdod;
+ writeb(ssfc, SPI_REG(SPIBAR_SSFC + 2));
+}
+
+static int broadwell_lpc_early_init(struct udevice *dev)
+{
+ set_spi_speed();
+
+ return 0;
+}
+
+static int lpc_init_extra(struct udevice *dev)
+{
+ return 0;
+}
+
+static int broadwell_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 broadwell_lpc_early_init(dev);
+ }
+
+ return lpc_init_extra(dev);
+}
+
+static const struct udevice_id broadwell_lpc_ids[] = {
+ { .compatible = "intel,broadwell-lpc" },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_lpc_drv) = {
+ .name = "lpc",
+ .id = UCLASS_LPC,
+ .of_match = broadwell_lpc_ids,
+ .probe = broadwell_lpc_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/me.c b/roms/u-boot/arch/x86/cpu/broadwell/me.c
new file mode 100644
index 000000000..ae16ce264
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/me.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * Based on code from coreboot src/soc/intel/broadwell/me_status.c
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <log.h>
+#include <asm/arch/me.h>
+#include <linux/delay.h>
+
+static inline void me_read_dword_ptr(struct udevice *dev, void *ptr, int offset)
+{
+ u32 dword;
+
+ dm_pci_read_config32(dev, offset, &dword);
+ memcpy(ptr, &dword, sizeof(dword));
+}
+
+int intel_me_hsio_version(struct udevice *dev, uint16_t *versionp,
+ uint16_t *checksump)
+{
+ int count;
+ u32 hsiover;
+ struct me_hfs hfs;
+
+ /* Query for HSIO version, overloads H_GS and HFS */
+ dm_pci_write_config32(dev, PCI_ME_H_GS,
+ ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER);
+
+ /* Must wait for ME acknowledgement */
+ for (count = ME_RETRY; count > 0; --count) {
+ me_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
+ if (hfs.bios_msg_ack)
+ break;
+ udelay(ME_DELAY);
+ }
+ if (!count) {
+ debug("ERROR: ME failed to respond\n");
+ return -ETIMEDOUT;
+ }
+
+ /* HSIO version should be in HFS_5 */
+ dm_pci_read_config32(dev, PCI_ME_HFS5, &hsiover);
+ *versionp = hsiover >> 16;
+ *checksump = hsiover & 0xffff;
+
+ debug("ME: HSIO Version : %d (CRC 0x%04x)\n",
+ *versionp, *checksump);
+
+ /* Reset registers to normal behavior */
+ dm_pci_write_config32(dev, PCI_ME_H_GS,
+ ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/northbridge.c b/roms/u-boot/arch/x86/cpu/broadwell/northbridge.c
new file mode 100644
index 000000000..141babc51
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/northbridge.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2011 The Chromium Authors
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/mrc_common.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/pei_data.h>
+
+__weak asmlinkage void sdram_console_tx_byte(unsigned char byte)
+{
+#ifdef DEBUG
+ putc(byte);
+#endif
+}
+
+void broadwell_fill_pei_data(struct pei_data *pei_data)
+{
+ pei_data->pei_version = PEI_VERSION;
+ pei_data->board_type = BOARD_TYPE_ULT;
+ pei_data->pciexbar = MCFG_BASE_ADDRESS;
+ pei_data->smbusbar = SMBUS_BASE_ADDRESS;
+ pei_data->ehcibar = EARLY_EHCI_BAR;
+ pei_data->xhcibar = EARLY_XHCI_BAR;
+ pei_data->gttbar = EARLY_GTT_BAR;
+ pei_data->pmbase = ACPI_BASE_ADDRESS;
+ pei_data->gpiobase = GPIO_BASE_ADDRESS;
+ pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE;
+ pei_data->temp_mmio_base = EARLY_TEMP_MMIO;
+ pei_data->tx_byte = sdram_console_tx_byte;
+ pei_data->ddr_refresh_2x = 1;
+}
+
+static void pei_data_usb2_port(struct pei_data *pei_data, int port, uint length,
+ uint enable, uint oc_pin, uint location)
+{
+ pei_data->usb2_ports[port].length = length;
+ pei_data->usb2_ports[port].enable = enable;
+ pei_data->usb2_ports[port].oc_pin = oc_pin;
+ pei_data->usb2_ports[port].location = location;
+}
+
+static void pei_data_usb3_port(struct pei_data *pei_data, int port, uint enable,
+ uint oc_pin, uint fixed_eq)
+{
+ pei_data->usb3_ports[port].enable = enable;
+ pei_data->usb3_ports[port].oc_pin = oc_pin;
+ pei_data->usb3_ports[port].fixed_eq = fixed_eq;
+}
+
+void mainboard_fill_pei_data(struct pei_data *pei_data)
+{
+ /* DQ byte map for Samus board */
+ const u8 dq_map[2][6][2] = {
+ { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
+ { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } },
+ { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
+ { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } };
+ /* DQS CPU<>DRAM map for Samus board */
+ const u8 dqs_map[2][8] = {
+ { 2, 0, 1, 3, 6, 4, 7, 5 },
+ { 2, 1, 0, 3, 6, 5, 4, 7 } };
+
+ pei_data->ec_present = 1;
+
+ /* One installed DIMM per channel */
+ pei_data->dimm_channel0_disabled = 2;
+ pei_data->dimm_channel1_disabled = 2;
+
+ memcpy(pei_data->dq_map, dq_map, sizeof(dq_map));
+ memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map));
+
+ /* P0: HOST PORT */
+ pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0,
+ USB_PORT_BACK_PANEL);
+ /* P1: HOST PORT */
+ pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1,
+ USB_PORT_BACK_PANEL);
+ /* P2: RAIDEN */
+ pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP,
+ USB_PORT_BACK_PANEL);
+ /* P3: SD CARD */
+ pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP,
+ USB_PORT_INTERNAL);
+ /* P4: RAIDEN */
+ pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP,
+ USB_PORT_BACK_PANEL);
+ /* P5: WWAN (Disabled) */
+ pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP,
+ USB_PORT_SKIP);
+ /* P6: CAMERA */
+ pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP,
+ USB_PORT_INTERNAL);
+ /* P7: BT */
+ pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP,
+ USB_PORT_INTERNAL);
+
+ /* P1: HOST PORT */
+ pei_data_usb3_port(pei_data, 0, 1, 0, 0);
+ /* P2: HOST PORT */
+ pei_data_usb3_port(pei_data, 1, 1, 1, 0);
+ /* P3: RAIDEN */
+ pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0);
+ /* P4: RAIDEN */
+ pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0);
+}
+
+static int broadwell_northbridge_early_init(struct udevice *dev)
+{
+ /* Move earlier? */
+ dm_pci_write_config32(dev, PCIEXBAR + 4, 0);
+ /* 64MiB - 0-63 buses */
+ dm_pci_write_config32(dev, PCIEXBAR, MCFG_BASE_ADDRESS | 4 | 1);
+
+ dm_pci_write_config32(dev, MCHBAR, MCH_BASE_ADDRESS | 1);
+ dm_pci_write_config32(dev, DMIBAR, DMI_BASE_ADDRESS | 1);
+ dm_pci_write_config32(dev, EPBAR, EP_BASE_ADDRESS | 1);
+ writel(EDRAM_BASE_ADDRESS | 1, MCH_BASE_ADDRESS + EDRAMBAR);
+ writel(GDXC_BASE_ADDRESS | 1, MCH_BASE_ADDRESS + GDXCBAR);
+
+ /* 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);
+
+ /* Device enable: IGD and Mini-HD */
+ dm_pci_write_config32(dev, DEVEN, DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN);
+
+ return 0;
+}
+
+static int broadwell_northbridge_probe(struct udevice *dev)
+{
+ if (!(gd->flags & GD_FLG_RELOC))
+ return broadwell_northbridge_early_init(dev);
+
+ return 0;
+}
+
+static const struct udevice_id broadwell_northbridge_ids[] = {
+ { .compatible = "intel,broadwell-northbridge" },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_northbridge_drv) = {
+ .name = "broadwell_northbridge",
+ .id = UCLASS_NORTHBRIDGE,
+ .of_match = broadwell_northbridge_ids,
+ .probe = broadwell_northbridge_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/pch.c b/roms/u-boot/arch/x86/cpu/broadwell/pch.c
new file mode 100644
index 000000000..f012db9de
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/pch.c
@@ -0,0 +1,684 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <pch.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <asm/i8259.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
+#include <asm/lpc_common.h>
+#include <asm/pch_common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/rcb.h>
+#include <asm/arch/serialio.h>
+#include <asm/arch/spi.h>
+#include <dm/uclass-internal.h>
+#include <linux/delay.h>
+
+#define BIOS_CTRL 0xdc
+
+bool cpu_is_ult(void)
+{
+ u32 fm = cpu_get_family_model();
+
+ return fm == BROADWELL_FAMILY_ULT || fm == HASWELL_FAMILY_ULT;
+}
+
+static int broadwell_pch_early_init(struct udevice *dev)
+{
+ struct gpio_desc desc;
+ struct udevice *bus;
+ pci_dev_t bdf;
+ int ret;
+
+ dm_pci_write_config32(dev, PCH_RCBA, RCB_BASE_ADDRESS | 1);
+
+ dm_pci_write_config32(dev, PMBASE, ACPI_BASE_ADDRESS | 1);
+ dm_pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
+ dm_pci_write_config32(dev, GPIO_BASE, GPIO_BASE_ADDRESS | 1);
+ dm_pci_write_config8(dev, GPIO_CNTL, GPIO_EN);
+
+ /* Enable IOAPIC */
+ writew(0x1000, RCB_REG(OIC));
+ /* Read back for posted write */
+ readw(RCB_REG(OIC));
+
+ /* Set HPET address and enable it */
+ clrsetbits_le32(RCB_REG(HPTC), 3, 1 << 7);
+ /* Read back for posted write */
+ readl(RCB_REG(HPTC));
+ /* Enable HPET to start counter */
+ setbits_le32(HPET_BASE_ADDRESS + 0x10, 1 << 0);
+
+ setbits_le32(RCB_REG(GCS), 1 << 5);
+
+ /*
+ * Enable PP3300_AUTOBAHN_EN after initial GPIO setup
+ * to prevent possible brownout. This will cause the GPIOs to be set
+ * up if it has not been done already.
+ */
+ ret = gpio_request_by_name(dev, "power-enable-gpio", 0, &desc,
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+ if (ret)
+ return ret;
+
+ /* 8.14 Additional PCI Express Programming Steps, step #1 */
+ bdf = PCI_BDF(0, 0x1c, 0);
+ bus = pci_get_controller(dev);
+ pci_bus_clrset_config32(bus, bdf, 0xf4, 0x60, 0);
+ pci_bus_clrset_config32(bus, bdf, 0xf4, 0x80, 0x80);
+ pci_bus_clrset_config32(bus, bdf, 0xe2, 0x30, 0x30);
+
+ return 0;
+}
+
+static void pch_misc_init(struct udevice *dev)
+{
+ /* Setup SLP signal assertion, SLP_S4=4s, SLP_S3=50ms */
+ dm_pci_clrset_config8(dev, GEN_PMCON_3, 3 << 4 | 1 << 10,
+ 1 << 3 | 1 << 11 | 1 << 12);
+ /* Prepare sleep mode */
+ clrsetio_32(ACPI_BASE_ADDRESS + PM1_CNT, SLP_TYP, SCI_EN);
+
+ /* Setup NMI on errors, disable SERR */
+ clrsetio_8(0x61, 0xf0, 1 << 2);
+ /* Disable NMI sources */
+ setio_8(0x70, 1 << 7);
+ /* Indicate DRAM init done for MRC */
+ dm_pci_clrset_config8(dev, GEN_PMCON_2, 0, 1 << 7);
+
+ /* Clear status bits to prevent unexpected wake */
+ setbits_le32(RCB_REG(0x3310), 0x0000002f);
+ clrsetbits_le32(RCB_REG(0x3f02), 0x0000000f, 0);
+ /* Enable PCIe Relaxed Order */
+ setbits_le32(RCB_REG(0x2314), 1 << 31 | 1 << 7);
+ setbits_le32(RCB_REG(0x1114), 1 << 15 | 1 << 14);
+ /* Setup SERIRQ, enable continuous mode */
+ dm_pci_clrset_config8(dev, SERIRQ_CNTL, 0, 1 << 7 | 1 << 6);
+};
+
+static void pch_enable_ioapic(void)
+{
+ u32 reg32;
+
+ /* Make sure this is a unique ID within system */
+ io_apic_set_id(0x04);
+
+ /* affirm full set of redirection table entries ("write once") */
+ reg32 = io_apic_read(0x01);
+
+ /* PCH-LP has 39 redirection entries */
+ reg32 &= ~0x00ff0000;
+ reg32 |= 0x00270000;
+
+ io_apic_write(0x01, reg32);
+
+ /*
+ * Select Boot Configuration register (0x03) and
+ * use Processor System Bus (0x01) to deliver interrupts.
+ */
+ io_apic_write(0x03, 0x01);
+}
+
+/* Enable all requested GPE */
+void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
+{
+ outl(set1, ACPI_BASE_ADDRESS + GPE0_EN(GPE_31_0));
+ outl(set2, ACPI_BASE_ADDRESS + GPE0_EN(GPE_63_32));
+ outl(set3, ACPI_BASE_ADDRESS + GPE0_EN(GPE_94_64));
+ outl(set4, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
+}
+
+/*
+ * Enable GPIO SMI events - it would be good to put this in the GPIO driver
+ * but it would need a new driver operation.
+ */
+int enable_alt_smi(struct udevice *pch, u32 mask)
+{
+ struct pch_lp_gpio_regs *regs;
+ u32 gpiobase;
+ int ret;
+
+ ret = pch_get_gpio_base(pch, &gpiobase);
+ if (ret) {
+ debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
+ gpiobase);
+ return -EINVAL;
+ }
+
+ regs = (struct pch_lp_gpio_regs *)gpiobase;
+ setio_32(regs->alt_gpi_smi_en, mask);
+
+ return 0;
+}
+
+static int pch_power_options(struct udevice *dev)
+{
+ int pwr_on_after_power_fail = MAINBOARD_POWER_OFF;
+ const char *state;
+ u32 enable[4];
+ u16 reg16;
+ int ret;
+
+ dm_pci_read_config16(dev, GEN_PMCON_3, &reg16);
+ reg16 &= 0xfffe;
+ switch (pwr_on_after_power_fail) {
+ 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";
+ }
+ dm_pci_write_config16(dev, GEN_PMCON_3, reg16);
+ debug("Set power %s after power failure.\n", state);
+
+ /* GPE setup based on device tree configuration */
+ ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
+ "intel,gpe0-en", enable, ARRAY_SIZE(enable));
+ if (ret)
+ return -EINVAL;
+ enable_all_gpe(enable[0], enable[1], enable[2], enable[3]);
+
+ /* SMI setup based on device tree configuration */
+ enable_alt_smi(dev, fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "intel,alt-gp-smi-enable", 0));
+
+ return 0;
+}
+
+/* Magic register settings for power management */
+static void pch_pm_init_magic(struct udevice *dev)
+{
+ dm_pci_write_config8(dev, 0xa9, 0x46);
+ clrbits_le32(RCB_REG(0x232c), 1),
+ setbits_le32(RCB_REG(0x1100), 0x0000c13f);
+ clrsetbits_le32(RCB_REG(0x2320), 0x60, 0x10);
+ writel(0x00012fff, RCB_REG(0x3314));
+ clrsetbits_le32(RCB_REG(0x3318), 0x000f0330, 0x0dcf0400);
+ writel(0x04000000, RCB_REG(0x3324));
+ writel(0x00041400, RCB_REG(0x3368));
+ writel(0x3f8ddbff, RCB_REG(0x3388));
+ writel(0x00007001, RCB_REG(0x33ac));
+ writel(0x00181900, RCB_REG(0x33b0));
+ writel(0x00060A00, RCB_REG(0x33c0));
+ writel(0x06200840, RCB_REG(0x33d0));
+ writel(0x01010101, RCB_REG(0x3a28));
+ writel(0x040c0404, RCB_REG(0x3a2c));
+ writel(0x9000000a, RCB_REG(0x3a9c));
+ writel(0x03808033, RCB_REG(0x2b1c));
+ writel(0x80000009, RCB_REG(0x2b34));
+ writel(0x022ddfff, RCB_REG(0x3348));
+ writel(0x00000001, RCB_REG(0x334c));
+ writel(0x0001c000, RCB_REG(0x3358));
+ writel(0x3f8ddbff, RCB_REG(0x3380));
+ writel(0x0001c7e1, RCB_REG(0x3384));
+ writel(0x0001c7e1, RCB_REG(0x338c));
+ writel(0x0001c000, RCB_REG(0x3398));
+ writel(0x00181900, RCB_REG(0x33a8));
+ writel(0x00080000, RCB_REG(0x33dc));
+ writel(0x00000001, RCB_REG(0x33e0));
+ writel(0x0000040c, RCB_REG(0x3a20));
+ writel(0x01010101, RCB_REG(0x3a24));
+ writel(0x01010101, RCB_REG(0x3a30));
+ dm_pci_clrset_config32(dev, 0xac, 0x00200000, 0);
+ setbits_le32(RCB_REG(0x0410), 0x00000003);
+ setbits_le32(RCB_REG(0x2618), 0x08000000);
+ setbits_le32(RCB_REG(0x2300), 0x00000002);
+ setbits_le32(RCB_REG(0x2600), 0x00000008);
+ writel(0x00007001, RCB_REG(0x33b4));
+ writel(0x022ddfff, RCB_REG(0x3350));
+ writel(0x00000001, RCB_REG(0x3354));
+ /* Power Optimizer */
+ setbits_le32(RCB_REG(0x33d4), 0x08000000);
+ /*
+ * This stops the LCD from turning on:
+ * setbits_le32(RCB_REG(0x33c8), 0x08000080);
+ */
+ writel(0x0000883c, RCB_REG(0x2b10));
+ writel(0x1e0a4616, RCB_REG(0x2b14));
+ writel(0x40000005, RCB_REG(0x2b24));
+ writel(0x0005db01, RCB_REG(0x2b20));
+ writel(0x05145005, RCB_REG(0x3a80));
+ writel(0x00001005, RCB_REG(0x3a84));
+ setbits_le32(RCB_REG(0x33d4), 0x2fff2fb1);
+ setbits_le32(RCB_REG(0x33c8), 0x00008000);
+};
+
+static int pch_type(struct udevice *dev)
+{
+ u16 type;
+
+ dm_pci_read_config16(dev, PCI_DEVICE_ID, &type);
+
+ return type;
+}
+
+/* Return 1 if PCH type is WildcatPoint */
+static int pch_is_wpt(struct udevice *dev)
+{
+ return ((pch_type(dev) & 0xfff0) == 0x9cc0) ? 1 : 0;
+}
+
+/* Return 1 if PCH type is WildcatPoint ULX */
+static int pch_is_wpt_ulx(struct udevice *dev)
+{
+ u16 lpcid = pch_type(dev);
+
+ switch (lpcid) {
+ case PCH_WPT_BDW_Y_SAMPLE:
+ case PCH_WPT_BDW_Y_PREMIUM:
+ case PCH_WPT_BDW_Y_BASE:
+ return 1;
+ }
+
+ return 0;
+}
+
+static u32 pch_read_soft_strap(int id)
+{
+ clrbits_le32(SPI_REG(SPIBAR_FDOC), 0x00007ffc);
+ setbits_le32(SPI_REG(SPIBAR_FDOC), 0x00004000 | id * 4);
+
+ return readl(SPI_REG(SPIBAR_FDOD));
+}
+
+static void pch_enable_mphy(struct udevice *dev)
+{
+ u32 data_and = 0xffffffff;
+ u32 data_or = (1 << 14) | (1 << 13) | (1 << 12);
+
+ data_or |= (1 << 0);
+ if (pch_is_wpt(dev)) {
+ data_and &= ~((1 << 7) | (1 << 6) | (1 << 3));
+ data_or |= (1 << 5) | (1 << 4);
+
+ if (pch_is_wpt_ulx(dev)) {
+ /* Check if SATA and USB3 MPHY are enabled */
+ u32 strap19 = pch_read_soft_strap(19);
+ strap19 &= ((1 << 31) | (1 << 30));
+ strap19 >>= 30;
+ if (strap19 == 3) {
+ data_or |= (1 << 3);
+ debug("Enable ULX MPHY PG control in single domain\n");
+ } else if (strap19 == 0) {
+ debug("Enable ULX MPHY PG control in split domains\n");
+ } else {
+ debug("Invalid PCH Soft Strap 19 configuration\n");
+ }
+ } else {
+ data_or |= (1 << 3);
+ }
+ }
+
+ pch_iobp_update(0xCF000000, data_and, data_or);
+}
+
+static void pch_init_deep_sx(bool deep_sx_enable_ac, bool deep_sx_enable_dc)
+{
+ if (deep_sx_enable_ac) {
+ setbits_le32(RCB_REG(DEEP_S3_POL), DEEP_S3_EN_AC);
+ setbits_le32(RCB_REG(DEEP_S5_POL), DEEP_S5_EN_AC);
+ }
+
+ if (deep_sx_enable_dc) {
+ setbits_le32(RCB_REG(DEEP_S3_POL), DEEP_S3_EN_DC);
+ setbits_le32(RCB_REG(DEEP_S5_POL), DEEP_S5_EN_DC);
+ }
+
+ if (deep_sx_enable_ac || deep_sx_enable_dc) {
+ setbits_le32(RCB_REG(DEEP_SX_CONFIG),
+ DEEP_SX_WAKE_PIN_EN | DEEP_SX_GP27_PIN_EN);
+ }
+}
+
+/* Power Management init */
+static void pch_pm_init(struct udevice *dev)
+{
+ debug("PCH PM init\n");
+
+ pch_init_deep_sx(false, false);
+ pch_enable_mphy(dev);
+ pch_pm_init_magic(dev);
+
+ if (pch_is_wpt(dev)) {
+ setbits_le32(RCB_REG(0x33e0), 1 << 4 | 1 << 1);
+ setbits_le32(RCB_REG(0x2b1c), 1 << 22 | 1 << 14 | 1 << 13);
+ writel(0x16bf0002, RCB_REG(0x33e4));
+ setbits_le32(RCB_REG(0x33e4), 0x1);
+ }
+
+ pch_iobp_update(0xCA000000, ~0UL, 0x00000009);
+
+ /* Set RCBA 0x2b1c[29]=1 if DSP disabled */
+ if (readl(RCB_REG(FD)) & PCH_DISABLE_ADSPD)
+ setbits_le32(RCB_REG(0x2b1c), 1 << 29);
+}
+
+static void pch_cg_init(struct udevice *dev)
+{
+ struct udevice *bus = pci_get_controller(dev);
+ u32 reg32;
+ u16 reg16;
+ ulong val;
+
+ /* DMI */
+ setbits_le32(RCB_REG(0x2234), 0xf);
+
+ dm_pci_read_config16(dev, GEN_PMCON_1, &reg16);
+ reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */
+ if (pch_is_wpt(dev))
+ reg16 &= ~(1 << 11);
+ else
+ reg16 |= 1 << 11;
+ reg16 |= 1 << 5 | 1 << 6 | 1 << 7 | 1 << 12;
+ reg16 |= 1 << 2; /* PCI CLKRUN# Enable */
+ dm_pci_write_config16(dev, GEN_PMCON_1, reg16);
+
+ /*
+ * RCBA + 0x2614[27:25,14:13,10,8] = 101,11,1,1
+ * RCBA + 0x2614[23:16] = 0x20
+ * RCBA + 0x2614[30:28] = 0x0
+ * RCBA + 0x2614[26] = 1 (IF 0:2.0@0x08 >= 0x0b)
+ */
+ clrsetbits_le32(RCB_REG(0x2614), 0x64ff0000, 0x0a206500);
+
+ /* Check for 0:2.0@0x08 >= 0x0b */
+ pci_bus_read_config(bus, PCI_BDF(0, 0x2, 0), 0x8, &val, PCI_SIZE_8);
+ if (pch_is_wpt(dev) || val >= 0x0b)
+ setbits_le32(RCB_REG(0x2614), 1 << 26);
+
+ setbits_le32(RCB_REG(0x900), 0x0000031f);
+
+ reg32 = readl(RCB_REG(CG));
+ if (readl(RCB_REG(0x3454)) & (1 << 4))
+ reg32 &= ~(1 << 29); /* LPC Dynamic */
+ else
+ reg32 |= (1 << 29); /* LPC Dynamic */
+ reg32 |= 1 << 31; /* LP LPC */
+ reg32 |= 1 << 30; /* LP BLA */
+ if (readl(RCB_REG(0x3454)) & (1 << 4))
+ reg32 &= ~(1 << 29);
+ else
+ reg32 |= 1 << 29;
+ reg32 |= 1 << 28; /* GPIO Dynamic */
+ reg32 |= 1 << 27; /* HPET Dynamic */
+ reg32 |= 1 << 26; /* Generic Platform Event Clock */
+ if (readl(RCB_REG(BUC)) & PCH_DISABLE_GBE)
+ reg32 |= 1 << 23; /* GbE Static */
+ if (readl(RCB_REG(FD)) & PCH_DISABLE_HD_AUDIO)
+ reg32 |= 1 << 21; /* HDA Static */
+ reg32 |= 1 << 22; /* HDA Dynamic */
+ writel(reg32, RCB_REG(CG));
+
+ /* PCH-LP LPC */
+ if (pch_is_wpt(dev))
+ clrsetbits_le32(RCB_REG(0x3434), 0x1f, 0x17);
+ else
+ setbits_le32(RCB_REG(0x3434), 0x7);
+
+ /* SPI */
+ setbits_le32(RCB_REG(0x38c0), 0x3c07);
+
+ pch_iobp_update(0xCE00C000, ~1UL, 0x00000000);
+}
+
+static void systemagent_init(void)
+{
+ /* Enable Power Aware Interrupt Routing */
+ clrsetbits_8(MCHBAR_REG(MCH_PAIR), 0x7, 0x4); /* Fixed Priority */
+
+ /*
+ * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
+ * that BIOS has initialized memory and power management
+ */
+ setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 3);
+ debug("Set BIOS_RESET_CPL\n");
+
+ /* Configure turbo power limits 1ms after reset complete bit */
+ mdelay(1);
+
+ cpu_set_power_limits(28);
+}
+
+/* Enable LTR Auto Mode for D21:F1-F6 */
+static void serialio_d21_ltr(u32 bar0)
+{
+ /* 1. Program BAR0 + 808h[2] = 0b */
+ clrbits_le32(bar0 + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_LTR_MODE_MASK);
+
+ /* 2. Program BAR0 + 804h[1:0] = 00b */
+ clrbits_le32(bar0 + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
+
+ /* 3. Program BAR0 + 804h[1:0] = 11b */
+ setbits_le32(bar0 + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
+
+ /* 4. Program BAR0 + 814h[31:0] = 00000000h */
+ writel(0, bar0 + SIO_REG_AUTO_LTR);
+}
+
+/* Select I2C voltage of 1.8V or 3.3V */
+static void serialio_i2c_voltage_sel(u32 bar0, uint voltage)
+{
+ clrsetbits_le32(bar0 + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_VOLTAGE_MASK,
+ SIO_REG_PPR_GEN_VOLTAGE(voltage));
+}
+
+/* Put Serial IO D21:F0-F6 device into desired mode */
+static void serialio_d21_mode(int sio_index, int int_pin, bool acpi_mode)
+{
+ u32 portctrl = SIO_IOBP_PORTCTRL_PM_CAP_PRSNT;
+
+ /* Snoop select 1 */
+ portctrl |= SIO_IOBP_PORTCTRL_SNOOP_SELECT(1);
+
+ /* Set interrupt pin */
+ portctrl |= SIO_IOBP_PORTCTRL_INT_PIN(int_pin);
+
+ if (acpi_mode) {
+ /* Enable ACPI interrupt mode */
+ portctrl |= SIO_IOBP_PORTCTRL_ACPI_IRQ_EN;
+ }
+
+ pch_iobp_update(SIO_IOBP_PORTCTRLX(sio_index), 0, portctrl);
+}
+
+/* Init sequence to be run once, done as part of D21:F0 (SDMA) init */
+static void serialio_init_once(bool acpi_mode)
+{
+ if (acpi_mode) {
+ /* Enable ACPI IRQ for IRQ13, IRQ7, IRQ6, IRQ5 in RCBA */
+ setbits_le32(RCB_REG(ACPIIRQEN),
+ 1 << 13 | 1 << 7 | 1 << 6 | 1 << 5);
+ }
+
+ /* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b */
+ pch_iobp_update(SIO_IOBP_GPIODF, ~0x0000131f, 0x0000131f);
+
+ /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
+ pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
+}
+
+/**
+ * pch_serialio_init() - set up serial I/O devices
+ *
+ * @return 0 if OK, -ve on error
+ */
+static int pch_serialio_init(void)
+{
+ struct udevice *dev, *hda;
+ bool acpi_mode = true;
+ u32 bar0, bar1;
+ int ret;
+
+ ret = uclass_find_first_device(UCLASS_I2C, &dev);
+ if (ret)
+ return ret;
+ bar0 = dm_pci_read_bar32(dev, 0);
+ if (!bar0)
+ return -EINVAL;
+ bar1 = dm_pci_read_bar32(dev, 1);
+ if (!bar1)
+ return -EINVAL;
+
+ serialio_init_once(acpi_mode);
+ serialio_d21_mode(SIO_ID_SDMA, SIO_PIN_INTB, acpi_mode);
+
+ serialio_d21_ltr(bar0);
+ serialio_i2c_voltage_sel(bar0, 1); /* Select 1.8V always */
+ serialio_d21_mode(SIO_ID_I2C0, SIO_PIN_INTC, acpi_mode);
+ setbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
+
+ clrbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
+
+ setbits_le32(bar0 + SIO_REG_PPR_CLOCK, SIO_REG_PPR_CLOCK_EN);
+
+ /* Manually find the High-definition audio, to turn it off */
+ ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1b, 0), &hda);
+ if (ret)
+ return -ENOENT;
+ dm_pci_clrset_config8(hda, 0x43, 0, 0x6f);
+
+ /* Route I/O buffers to ADSP function */
+ dm_pci_clrset_config8(hda, 0x42, 0, 1 << 7 | 1 << 6);
+ log_debug("HDA disabled, I/O buffers routed to ADSP\n");
+
+ return 0;
+}
+
+static int broadwell_pch_init(struct udevice *dev)
+{
+ int ret;
+
+ /* Enable upper 128 bytes of CMOS */
+ setbits_le32(RCB_REG(RC), 1 << 2);
+
+ /*
+ * TODO: TCO timer halt - this hangs
+ * setio_16(ACPI_BASE_ADDRESS + TCO1_CNT, TCO_TMR_HLT);
+ */
+
+ /* Disable unused device (always) */
+ setbits_le32(RCB_REG(FD), PCH_DISABLE_ALWAYS);
+
+ pch_misc_init(dev);
+
+ /* Interrupt configuration */
+ pch_enable_ioapic();
+
+ /* Initialize power management */
+ ret = pch_power_options(dev);
+ if (ret)
+ return ret;
+ pch_pm_init(dev);
+ pch_cg_init(dev);
+ ret = pch_serialio_init();
+ if (ret)
+ return ret;
+ systemagent_init();
+
+ return 0;
+}
+
+static int broadwell_pch_probe(struct udevice *dev)
+{
+ if (CONFIG_IS_ENABLED(X86_32BIT_INIT)) {
+ if (!(gd->flags & GD_FLG_RELOC))
+ return broadwell_pch_early_init(dev);
+ else
+ return broadwell_pch_init(dev);
+ } else if (IS_ENABLED(CONFIG_SPL) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
+ return broadwell_pch_init(dev);
+ } else {
+ return 0;
+ }
+}
+
+static int broadwell_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 broadwell_set_spi_protect(struct udevice *dev, bool protect)
+{
+ return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
+}
+
+static int broadwell_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ dm_pci_read_config32(dev, GPIO_BASE, gbasep);
+ *gbasep &= PCI_BASE_ADDRESS_IO_MASK;
+
+ return 0;
+}
+
+static int broadwell_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
+ int size)
+{
+ switch (req) {
+ 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(0);
+ pm->pm1_sts_ofs = PM1_STS;
+ pm->pm1_cnt_ofs = PM1_CNT;
+
+ return 0;
+ }
+ default:
+ return -ENOSYS;
+ }
+}
+
+static const struct pch_ops broadwell_pch_ops = {
+ .get_spi_base = broadwell_pch_get_spi_base,
+ .set_spi_protect = broadwell_set_spi_protect,
+ .get_gpio_base = broadwell_get_gpio_base,
+ .ioctl = broadwell_ioctl,
+};
+
+static const struct udevice_id broadwell_pch_ids[] = {
+ { .compatible = "intel,broadwell-pch" },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_pch) = {
+ .name = "broadwell_pch",
+ .id = UCLASS_PCH,
+ .of_match = broadwell_pch_ids,
+ .probe = broadwell_pch_probe,
+ .ops = &broadwell_pch_ops,
+};
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/pinctrl_broadwell.c b/roms/u-boot/arch/x86/cpu/broadwell/pinctrl_broadwell.c
new file mode 100644
index 000000000..85bd37101
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/pinctrl_broadwell.c
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <pch.h>
+#include <pci.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/gpio.h>
+#include <dt-bindings/gpio/x86-gpio.h>
+#include <dm/pinctrl.h>
+#include <dm/uclass-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+ MAX_GPIOS = 95,
+};
+
+#define PIRQ_SHIFT 16
+#define CONF_MASK 0xffff
+
+struct pin_info {
+ int node;
+ int phandle;
+ bool mode_gpio;
+ bool dir_input;
+ bool invert;
+ bool trigger_level;
+ bool output_high;
+ bool sense_disable;
+ bool owner_gpio;
+ bool route_smi;
+ bool irq_enable;
+ bool reset_rsmrst;
+ bool pirq_apic_route;
+};
+
+static int broadwell_pinctrl_read_configs(struct udevice *dev,
+ struct pin_info *conf, int max_pins)
+{
+ const void *blob = gd->fdt_blob;
+ int count = 0;
+ int node;
+
+ debug("%s: starting\n", __func__);
+ for (node = fdt_first_subnode(blob, dev_of_offset(dev));
+ node > 0;
+ node = fdt_next_subnode(blob, node)) {
+ int phandle = fdt_get_phandle(blob, node);
+
+ if (!phandle)
+ continue;
+ if (count == max_pins)
+ return -ENOSPC;
+
+ /* We've found a new configuration */
+ memset(conf, '\0', sizeof(*conf));
+ conf->node = node;
+ conf->phandle = phandle;
+ conf->mode_gpio = fdtdec_get_bool(blob, node, "mode-gpio");
+ if (fdtdec_get_int(blob, node, "direction", -1) == PIN_INPUT)
+ conf->dir_input = true;
+ conf->invert = fdtdec_get_bool(blob, node, "invert");
+ if (fdtdec_get_int(blob, node, "trigger", -1) == TRIGGER_LEVEL)
+ conf->trigger_level = true;
+ if (fdtdec_get_int(blob, node, "output-value", -1) == 1)
+ conf->output_high = true;
+ conf->sense_disable = fdtdec_get_bool(blob, node,
+ "sense-disable");
+ if (fdtdec_get_int(blob, node, "owner", -1) == OWNER_GPIO)
+ conf->owner_gpio = true;
+ if (fdtdec_get_int(blob, node, "route", -1) == ROUTE_SMI)
+ conf->route_smi = true;
+ conf->irq_enable = fdtdec_get_bool(blob, node, "irq-enable");
+ conf->reset_rsmrst = fdtdec_get_bool(blob, node,
+ "reset-rsmrst");
+ if (fdtdec_get_int(blob, node, "pirq-apic", -1) ==
+ PIRQ_APIC_ROUTE)
+ conf->pirq_apic_route = true;
+ debug("config: phandle=%d\n", phandle);
+ count++;
+ conf++;
+ }
+ debug("%s: Found %d configurations\n", __func__, count);
+
+ return count;
+}
+
+static int broadwell_pinctrl_lookup_phandle(struct pin_info *conf,
+ int conf_count, int phandle)
+{
+ int i;
+
+ for (i = 0; i < conf_count; i++) {
+ if (conf[i].phandle == phandle)
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+static int broadwell_pinctrl_read_pins(struct udevice *dev,
+ struct pin_info *conf, int conf_count, int gpio_conf[],
+ int num_gpios)
+{
+ const void *blob = gd->fdt_blob;
+ int count = 0;
+ int node;
+
+ for (node = fdt_first_subnode(blob, dev_of_offset(dev));
+ node > 0;
+ node = fdt_next_subnode(blob, node)) {
+ int len, i;
+ const u32 *prop = fdt_getprop(blob, node, "config", &len);
+
+ if (!prop)
+ continue;
+
+ /* There are three cells per pin */
+ count = len / (sizeof(u32) * 3);
+ debug("Found %d GPIOs to configure\n", count);
+ for (i = 0; i < count; i++) {
+ uint gpio = fdt32_to_cpu(prop[i * 3]);
+ uint phandle = fdt32_to_cpu(prop[i * 3 + 1]);
+ int val;
+
+ if (gpio >= num_gpios) {
+ debug("%s: GPIO %d out of range\n", __func__,
+ gpio);
+ return -EDOM;
+ }
+ val = broadwell_pinctrl_lookup_phandle(conf, conf_count,
+ phandle);
+ if (val < 0) {
+ debug("%s: Cannot find phandle %d\n", __func__,
+ phandle);
+ return -EINVAL;
+ }
+ gpio_conf[gpio] = val |
+ fdt32_to_cpu(prop[i * 3 + 2]) << PIRQ_SHIFT;
+ }
+ }
+
+ return 0;
+}
+
+static void broadwell_pinctrl_commit(struct pch_lp_gpio_regs *regs,
+ struct pin_info *pin_info,
+ int gpio_conf[], int count)
+{
+ u32 owner_gpio[GPIO_BANKS] = {0};
+ u32 route_smi[GPIO_BANKS] = {0};
+ u32 irq_enable[GPIO_BANKS] = {0};
+ u32 reset_rsmrst[GPIO_BANKS] = {0};
+ u32 pirq2apic = 0;
+ int set, bit, gpio = 0;
+
+ for (gpio = 0; gpio < MAX_GPIOS; gpio++) {
+ int confnum = gpio_conf[gpio] & CONF_MASK;
+ struct pin_info *pin = &pin_info[confnum];
+ u32 val;
+
+ val = pin->mode_gpio << CONFA_MODE_SHIFT |
+ pin->dir_input << CONFA_DIR_SHIFT |
+ pin->invert << CONFA_INVERT_SHIFT |
+ pin->trigger_level << CONFA_TRIGGER_SHIFT |
+ pin->output_high << CONFA_OUTPUT_SHIFT;
+ outl(val, &regs->config[gpio].conf_a);
+ outl(pin->sense_disable << CONFB_SENSE_SHIFT,
+ &regs->config[gpio].conf_b);
+
+ /* Determine set and bit based on GPIO number */
+ set = gpio / GPIO_PER_BANK;
+ bit = gpio % GPIO_PER_BANK;
+
+ /* Apply settings to set specific bits */
+ owner_gpio[set] |= pin->owner_gpio << bit;
+ route_smi[set] |= pin->route_smi << bit;
+ irq_enable[set] |= pin->irq_enable << bit;
+ reset_rsmrst[set] |= pin->reset_rsmrst << bit;
+
+ /* PIRQ to IO-APIC map */
+ if (pin->pirq_apic_route)
+ pirq2apic |= gpio_conf[gpio] >> PIRQ_SHIFT;
+ debug("gpio %d: conf %d, mode_gpio %d, dir_input %d, output_high %d\n",
+ gpio, confnum, pin->mode_gpio, pin->dir_input,
+ pin->output_high);
+ }
+
+ for (set = 0; set < GPIO_BANKS; set++) {
+ outl(owner_gpio[set], &regs->own[set]);
+ outl(route_smi[set], &regs->gpi_route[set]);
+ outl(irq_enable[set], &regs->gpi_ie[set]);
+ outl(reset_rsmrst[set], &regs->rst_sel[set]);
+ }
+
+ outl(pirq2apic, &regs->pirq_to_ioxapic);
+}
+
+static int broadwell_pinctrl_probe(struct udevice *dev)
+{
+ struct pch_lp_gpio_regs *regs;
+ struct pin_info conf[12];
+ int gpio_conf[MAX_GPIOS];
+ struct udevice *pch;
+ int conf_count;
+ u32 gpiobase;
+ int ret;
+
+ ret = uclass_find_first_device(UCLASS_PCH, &pch);
+ if (ret)
+ return ret;
+ if (!pch)
+ return -ENODEV;
+ debug("%s: start\n", __func__);
+
+ /* Only init once, before relocation */
+ if (gd->flags & GD_FLG_RELOC)
+ return 0;
+
+ /*
+ * Get the memory/io base address to configure every pins.
+ * IOBASE is used to configure the mode/pads
+ * GPIOBASE is used to configure the direction and default value
+ */
+ ret = pch_get_gpio_base(pch, &gpiobase);
+ if (ret) {
+ debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
+ gpiobase);
+ return -EINVAL;
+ }
+
+ conf_count = broadwell_pinctrl_read_configs(dev, conf,
+ ARRAY_SIZE(conf));
+ if (conf_count < 0) {
+ debug("%s: Cannot read configs: err=%d\n", __func__, ret);
+ return conf_count;
+ }
+
+ /*
+ * Assume that pin settings are provided for every pin. Pins not
+ * mentioned will get the first config mentioned in the list.
+ */
+ ret = broadwell_pinctrl_read_pins(dev, conf, conf_count, gpio_conf,
+ MAX_GPIOS);
+ if (ret) {
+ debug("%s: Cannot read pin settings: err=%d\n", __func__, ret);
+ return ret;
+ }
+
+ regs = (struct pch_lp_gpio_regs *)gpiobase;
+ broadwell_pinctrl_commit(regs, conf, gpio_conf, ARRAY_SIZE(conf));
+
+ debug("%s: done\n", __func__);
+
+ return 0;
+}
+
+static const struct udevice_id broadwell_pinctrl_match[] = {
+ { .compatible = "intel,x86-broadwell-pinctrl",
+ .data = X86_SYSCON_PINCONF },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(broadwell_pinctrl) = {
+ .name = "broadwell_pinctrl",
+ .id = UCLASS_SYSCON,
+ .of_match = broadwell_pinctrl_match,
+ .probe = broadwell_pinctrl_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/power_state.c b/roms/u-boot/arch/x86/cpu/broadwell/power_state.c
new file mode 100644
index 000000000..62fd2e8d2
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/power_state.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From coreboot src/soc/intel/broadwell/romstage/power_state.c
+ *
+ * Copyright (C) 2016 Google, Inc.
+ */
+
+#include <common.h>
+#include <log.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/intel_regs.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/lpc.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/pm.h>
+
+/* Return 0, 3, or 5 to indicate the previous sleep state. */
+static int prev_sleep_state(struct chipset_power_state *ps)
+{
+ /* Default to S0. */
+ int prev_sleep_state = SLEEP_STATE_S0;
+
+ if (ps->pm1_sts & WAK_STS) {
+ switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) {
+ case SLP_TYP_S3:
+ if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME))
+ prev_sleep_state = SLEEP_STATE_S3;
+ break;
+ case SLP_TYP_S5:
+ prev_sleep_state = SLEEP_STATE_S5;
+ break;
+ }
+ /* Clear SLP_TYP. */
+ outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
+ }
+
+ if (ps->gen_pmcon3 & (PWR_FLR | SUS_PWR_FLR))
+ prev_sleep_state = SLEEP_STATE_S5;
+
+ return prev_sleep_state;
+}
+
+static void dump_power_state(struct chipset_power_state *ps)
+{
+ debug("PM1_STS: %04x\n", ps->pm1_sts);
+ debug("PM1_EN: %04x\n", ps->pm1_en);
+ debug("PM1_CNT: %08x\n", ps->pm1_cnt);
+ debug("TCO_STS: %04x %04x\n", ps->tco1_sts, ps->tco2_sts);
+
+ debug("GPE0_STS: %08x %08x %08x %08x\n",
+ ps->gpe0_sts[0], ps->gpe0_sts[1],
+ ps->gpe0_sts[2], ps->gpe0_sts[3]);
+ debug("GPE0_EN: %08x %08x %08x %08x\n",
+ ps->gpe0_en[0], ps->gpe0_en[1],
+ ps->gpe0_en[2], ps->gpe0_en[3]);
+
+ debug("GEN_PMCON: %04x %04x %04x\n",
+ ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3);
+
+ debug("Previous Sleep State: S%d\n",
+ ps->prev_sleep_state);
+}
+
+/* Fill power state structure from ACPI PM registers */
+void power_state_get(struct udevice *pch_dev, struct chipset_power_state *ps)
+{
+ ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
+ ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN);
+ ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
+ ps->tco1_sts = inw(ACPI_BASE_ADDRESS + TCO1_STS);
+ ps->tco2_sts = inw(ACPI_BASE_ADDRESS + TCO2_STS);
+ ps->gpe0_sts[0] = inl(ACPI_BASE_ADDRESS + GPE0_STS(0));
+ ps->gpe0_sts[1] = inl(ACPI_BASE_ADDRESS + GPE0_STS(1));
+ ps->gpe0_sts[2] = inl(ACPI_BASE_ADDRESS + GPE0_STS(2));
+ ps->gpe0_sts[3] = inl(ACPI_BASE_ADDRESS + GPE0_STS(3));
+ ps->gpe0_en[0] = inl(ACPI_BASE_ADDRESS + GPE0_EN(0));
+ ps->gpe0_en[1] = inl(ACPI_BASE_ADDRESS + GPE0_EN(1));
+ ps->gpe0_en[2] = inl(ACPI_BASE_ADDRESS + GPE0_EN(2));
+ ps->gpe0_en[3] = inl(ACPI_BASE_ADDRESS + GPE0_EN(3));
+
+ dm_pci_read_config16(pch_dev, GEN_PMCON_1, &ps->gen_pmcon1);
+ dm_pci_read_config16(pch_dev, GEN_PMCON_2, &ps->gen_pmcon2);
+ dm_pci_read_config16(pch_dev, GEN_PMCON_3, &ps->gen_pmcon3);
+
+ ps->prev_sleep_state = prev_sleep_state(ps);
+
+ dump_power_state(ps);
+}
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/refcode.c b/roms/u-boot/arch/x86/cpu/broadwell/refcode.c
new file mode 100644
index 000000000..6c04dde99
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/refcode.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Read a coreboot rmodule and execute it.
+ * The rmodule_header struct is from coreboot.
+ *
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <init.h>
+#include <log.h>
+#include <asm/arch/pei_data.h>
+
+#define RMODULE_MAGIC 0xf8fe
+#define RMODULE_VERSION_1 1
+
+/*
+ * All fields with '_offset' in the name are byte offsets into the flat blob.
+ * The linker and the linker script takes are of assigning the values.
+ */
+struct rmodule_header {
+ uint16_t magic;
+ uint8_t version;
+ uint8_t type;
+ /* The payload represents the program's loadable code and data */
+ uint32_t payload_begin_offset;
+ uint32_t payload_end_offset;
+ /* Begin and of relocation information about the program module */
+ uint32_t relocations_begin_offset;
+ uint32_t relocations_end_offset;
+ /*
+ * The starting address of the linked program. This address is vital
+ * for determining relocation offsets as the relocation info and other
+ * symbols (bss, entry point) need this value as a basis to calculate
+ * the offsets.
+ */
+ uint32_t module_link_start_address;
+ /*
+ * The module_program_size is the size of memory used while running
+ * the program. The program is assumed to consume a contiguous amount
+ * of memory
+ */
+ uint32_t module_program_size;
+ /* This is program's execution entry point */
+ uint32_t module_entry_point;
+ /*
+ * Optional parameter structure that can be used to pass data into
+ * the module
+ */
+ uint32_t parameters_begin;
+ uint32_t parameters_end;
+ /* BSS section information so the loader can clear the bss */
+ uint32_t bss_begin;
+ uint32_t bss_end;
+ /* Add some room for growth */
+ uint32_t padding[4];
+} __packed;
+
+/**
+ * cpu_run_reference_code() - Run the platform reference code
+ *
+ * Some platforms require a binary blob to be executed once SDRAM is
+ * available. This is used to set up various platform features, such as the
+ * platform controller hub (PCH). This function should be implemented by the
+ * CPU-specific code.
+ *
+ * @return 0 on success, -ve on failure
+ */
+static int cpu_run_reference_code(void)
+{
+ struct pei_data _pei_data __aligned(8);
+ struct pei_data *pei_data = &_pei_data;
+ asmlinkage int (*func)(void *);
+ struct rmodule_header *hdr;
+ char *src, *dest;
+ int ret, dummy;
+ int size;
+
+ hdr = (struct rmodule_header *)CONFIG_X86_REFCODE_ADDR;
+ debug("Extracting code from rmodule at %p\n", hdr);
+ if (hdr->magic != RMODULE_MAGIC) {
+ debug("Invalid rmodule magic\n");
+ return -EINVAL;
+ }
+ if (hdr->module_link_start_address != 0) {
+ debug("Link start address must be 0\n");
+ return -EPERM;
+ }
+ if (hdr->module_entry_point != 0) {
+ debug("Entry point must be 0\n");
+ return -EPERM;
+ }
+
+ memset(pei_data, '\0', sizeof(struct pei_data));
+ broadwell_fill_pei_data(pei_data);
+ mainboard_fill_pei_data(pei_data);
+ pei_data->saved_data = (void *)&dummy;
+
+ src = (char *)hdr + hdr->payload_begin_offset;
+ dest = (char *)CONFIG_X86_REFCODE_RUN_ADDR;
+
+ size = hdr->payload_end_offset - hdr->payload_begin_offset;
+ debug("Copying refcode from %p to %p, size %x\n", src, dest, size);
+ memcpy(dest, src, size);
+
+ size = hdr->bss_end - hdr->bss_begin;
+ debug("Zeroing BSS at %p, size %x\n", dest + hdr->bss_begin, size);
+ memset(dest + hdr->bss_begin, '\0', size);
+
+ func = (asmlinkage int (*)(void *))dest;
+ debug("Running reference code at %p\n", func);
+#ifdef DEBUG
+ print_buffer(CONFIG_X86_REFCODE_RUN_ADDR, (void *)func, 1, 0x40, 0);
+#endif
+ ret = func(pei_data);
+ if (ret != 0) {
+ debug("Reference code returned %d\n", ret);
+ return -EL2HLT;
+ }
+ debug("Refereence code completed\n");
+
+ return 0;
+}
+
+int arch_early_init_r(void)
+{
+ return cpu_run_reference_code();
+}
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/sata.c b/roms/u-boot/arch/x86/cpu/broadwell/sata.c
new file mode 100644
index 000000000..be3c9e764
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/sata.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * From coreboot src/soc/intel/broadwell/sata.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/intel_regs.h>
+#include <asm/lpc_common.h>
+#include <asm/pch_common.h>
+#include <asm/pch_common.h>
+#include <asm/arch/pch.h>
+#include <linux/delay.h>
+
+struct sata_plat {
+ int port_map;
+ uint port0_gen3_tx;
+ uint port1_gen3_tx;
+ uint port0_gen3_dtle;
+ uint port1_gen3_dtle;
+
+ /*
+ * SATA DEVSLP Mux
+ * 0 = port 0 DEVSLP on DEVSLP0/GPIO33
+ * 1 = port 3 DEVSLP on DEVSLP0/GPIO33
+ */
+ int devslp_mux;
+
+ /*
+ * DEVSLP Disable
+ * 0: DEVSLP is enabled
+ * 1: DEVSLP is disabled
+ */
+ int devslp_disable;
+};
+
+static void broadwell_sata_init(struct udevice *dev)
+{
+ struct sata_plat *plat = dev_get_plat(dev);
+ u32 reg32;
+ u8 *abar;
+ u16 reg16;
+ int port;
+
+ debug("SATA: Initializing controller in AHCI mode.\n");
+
+ /* Set timings */
+ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE);
+ dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE);
+
+ /* for AHCI, Port Enable is managed in memory mapped space */
+ dm_pci_read_config16(dev, 0x92, &reg16);
+ reg16 &= ~0xf;
+ reg16 |= 0x8000 | plat->port_map;
+ dm_pci_write_config16(dev, 0x92, reg16);
+ udelay(2);
+
+ /* Setup register 98h */
+ dm_pci_read_config32(dev, 0x98, &reg32);
+ reg32 &= ~((1 << 31) | (1 << 30));
+ reg32 |= 1 << 23;
+ reg32 |= 1 << 24; /* Enable MPHY Dynamic Power Gating */
+ dm_pci_write_config32(dev, 0x98, reg32);
+
+ /* Setup register 9Ch */
+ reg16 = 0; /* Disable alternate ID */
+ reg16 = 1 << 5; /* BWG step 12 */
+ dm_pci_write_config16(dev, 0x9c, reg16);
+
+ /* SATA Initialization register */
+ reg32 = 0x183;
+ reg32 |= (plat->port_map ^ 0xf) << 24;
+ reg32 |= (plat->devslp_mux & 1) << 15;
+ dm_pci_write_config32(dev, 0x94, reg32);
+
+ /* Initialize AHCI memory-mapped space */
+ dm_pci_read_config32(dev, PCI_BASE_ADDRESS_5, &reg32);
+ abar = (u8 *)reg32;
+ debug("ABAR: %p\n", abar);
+
+ /* CAP (HBA Capabilities) : enable power management */
+ clrsetbits_le32(abar + 0x00, 0x00020060 /* SXS+EMS+PMS */,
+ 0x0c006000 /* PSC+SSC+SALP+SSS */ |
+ 1 << 18); /* SAM: SATA AHCI MODE ONLY */
+
+ /* PI (Ports implemented) */
+ writel(plat->port_map, abar + 0x0c);
+ (void) readl(abar + 0x0c); /* Read back 1 */
+ (void) readl(abar + 0x0c); /* Read back 2 */
+
+ /* CAP2 (HBA Capabilities Extended)*/
+ if (plat->devslp_disable) {
+ clrbits_le32(abar + 0x24, 1 << 3);
+ } else {
+ /* Enable DEVSLP */
+ setbits_le32(abar + 0x24, 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2);
+
+ for (port = 0; port < 4; port++) {
+ if (!(plat->port_map & (1 << port)))
+ continue;
+ /* DEVSLP DSP */
+ setbits_le32(abar + 0x144 + (0x80 * port), 1 << 1);
+ }
+ }
+
+ /* Static Power Gating for unused ports */
+ reg32 = readl(RCB_REG(0x3a84));
+ /* Port 3 and 2 disabled */
+ if ((plat->port_map & ((1 << 3)|(1 << 2))) == 0)
+ reg32 |= (1 << 24) | (1 << 26);
+ /* Port 1 and 0 disabled */
+ if ((plat->port_map & ((1 << 1)|(1 << 0))) == 0)
+ reg32 |= (1 << 20) | (1 << 18);
+ writel(reg32, RCB_REG(0x3a84));
+
+ /* Set Gen3 Transmitter settings if needed */
+ if (plat->port0_gen3_tx)
+ pch_iobp_update(SATA_IOBP_SP0_SECRT88,
+ ~(SATA_SECRT88_VADJ_MASK <<
+ SATA_SECRT88_VADJ_SHIFT),
+ (plat->port0_gen3_tx &
+ SATA_SECRT88_VADJ_MASK)
+ << SATA_SECRT88_VADJ_SHIFT);
+
+ if (plat->port1_gen3_tx)
+ pch_iobp_update(SATA_IOBP_SP1_SECRT88,
+ ~(SATA_SECRT88_VADJ_MASK <<
+ SATA_SECRT88_VADJ_SHIFT),
+ (plat->port1_gen3_tx &
+ SATA_SECRT88_VADJ_MASK)
+ << SATA_SECRT88_VADJ_SHIFT);
+
+ /* Set Gen3 DTLE DATA / EDGE registers if needed */
+ if (plat->port0_gen3_dtle) {
+ pch_iobp_update(SATA_IOBP_SP0DTLE_DATA,
+ ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT),
+ (plat->port0_gen3_dtle & SATA_DTLE_MASK)
+ << SATA_DTLE_DATA_SHIFT);
+
+ pch_iobp_update(SATA_IOBP_SP0DTLE_EDGE,
+ ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT),
+ (plat->port0_gen3_dtle & SATA_DTLE_MASK)
+ << SATA_DTLE_EDGE_SHIFT);
+ }
+
+ if (plat->port1_gen3_dtle) {
+ pch_iobp_update(SATA_IOBP_SP1DTLE_DATA,
+ ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT),
+ (plat->port1_gen3_dtle & SATA_DTLE_MASK)
+ << SATA_DTLE_DATA_SHIFT);
+
+ pch_iobp_update(SATA_IOBP_SP1DTLE_EDGE,
+ ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT),
+ (plat->port1_gen3_dtle & SATA_DTLE_MASK)
+ << SATA_DTLE_EDGE_SHIFT);
+ }
+
+ /*
+ * Additional Programming Requirements for Power Optimizer
+ */
+
+ /* Step 1 */
+ pch_common_sir_write(dev, 0x64, 0x883c9003);
+
+ /* Step 2: SIR 68h[15:0] = 880Ah */
+ reg32 = pch_common_sir_read(dev, 0x68);
+ reg32 &= 0xffff0000;
+ reg32 |= 0x880a;
+ pch_common_sir_write(dev, 0x68, reg32);
+
+ /* Step 3: SIR 60h[3] = 1 */
+ reg32 = pch_common_sir_read(dev, 0x60);
+ reg32 |= (1 << 3);
+ pch_common_sir_write(dev, 0x60, reg32);
+
+ /* Step 4: SIR 60h[0] = 1 */
+ reg32 = pch_common_sir_read(dev, 0x60);
+ reg32 |= (1 << 0);
+ pch_common_sir_write(dev, 0x60, reg32);
+
+ /* Step 5: SIR 60h[1] = 1 */
+ reg32 = pch_common_sir_read(dev, 0x60);
+ reg32 |= (1 << 1);
+ pch_common_sir_write(dev, 0x60, reg32);
+
+ /* Clock Gating */
+ pch_common_sir_write(dev, 0x70, 0x3f00bf1f);
+ pch_common_sir_write(dev, 0x54, 0xcf000f0f);
+ pch_common_sir_write(dev, 0x58, 0x00190000);
+ clrsetbits_le32(RCB_REG(0x333c), 0x00300000, 0x00c00000);
+
+ dm_pci_read_config32(dev, 0x300, &reg32);
+ reg32 |= 1 << 17 | 1 << 16 | 1 << 19;
+ reg32 |= 1 << 31 | 1 << 30 | 1 << 29;
+ dm_pci_write_config32(dev, 0x300, reg32);
+
+ dm_pci_read_config32(dev, 0x98, &reg32);
+ reg32 |= 1 << 29;
+ dm_pci_write_config32(dev, 0x98, reg32);
+
+ /* Register Lock */
+ dm_pci_read_config32(dev, 0x9c, &reg32);
+ reg32 |= 1 << 31;
+ dm_pci_write_config32(dev, 0x9c, reg32);
+}
+
+static int broadwell_sata_enable(struct udevice *dev)
+{
+ struct sata_plat *plat = dev_get_plat(dev);
+ struct gpio_desc desc;
+ u16 map;
+ int ret;
+
+ /*
+ * Set SATA controller mode early so the resource allocator can
+ * properly assign IO/Memory resources for the controller.
+ */
+ map = 0x0060;
+
+ map |= (plat->port_map ^ 0x3f) << 8;
+ dm_pci_write_config16(dev, 0x90, map);
+
+ ret = gpio_request_by_name(dev, "reset-gpio", 0, &desc, GPIOD_IS_OUT);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int broadwell_sata_of_to_plat(struct udevice *dev)
+{
+ struct sata_plat *plat = dev_get_plat(dev);
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+
+ plat->port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0);
+ plat->port0_gen3_tx = fdtdec_get_int(blob, node,
+ "intel,sata-port0-gen3-tx", 0);
+
+ return 0;
+}
+
+static int broadwell_sata_probe(struct udevice *dev)
+{
+ if (!(gd->flags & GD_FLG_RELOC))
+ return broadwell_sata_enable(dev);
+ else
+ broadwell_sata_init(dev);
+
+ return 0;
+}
+
+static const struct udevice_id broadwell_ahci_ids[] = {
+ { .compatible = "intel,wildcatpoint-ahci" },
+ { }
+};
+
+U_BOOT_DRIVER(ahci_broadwell_drv) = {
+ .name = "ahci_broadwell",
+ .id = UCLASS_AHCI,
+ .of_match = broadwell_ahci_ids,
+ .of_to_plat = broadwell_sata_of_to_plat,
+ .probe = broadwell_sata_probe,
+ .plat_auto = sizeof(struct sata_plat),
+};
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/sdram.c b/roms/u-boot/arch/x86/cpu/broadwell/sdram.c
new file mode 100644
index 000000000..c104a849a
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/broadwell/sdram.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * From coreboot src/soc/intel/broadwell/romstage/raminit.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <init.h>
+#include <log.h>
+#include <pci.h>
+#include <syscon.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/lpc_common.h>
+#include <asm/mrccache.h>
+#include <asm/mrc_common.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/me.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/pei_data.h>
+#include <asm/arch/pm.h>
+
+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 unsigned long get_top_of_ram(struct udevice *dev)
+{
+ /*
+ * Base of DPR is top of usable DRAM below 4GiB. The register has
+ * 1 MiB alignment and reports the TOP of the range, the base
+ * must be calculated from the size in MiB in bits 11:4.
+ */
+ u32 dpr, tom;
+
+ dm_pci_read_config32(dev, DPR, &dpr);
+ tom = dpr & ~((1 << 20) - 1);
+
+ debug("dpt %08x tom %08x\n", dpr, tom);
+ /* Subtract DMA Protected Range size if enabled */
+ if (dpr & DPR_EPM)
+ tom -= (dpr & DPR_SIZE_MASK) << 16;
+
+ return (unsigned long)tom;
+}
+
+/**
+ * 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;
+ ulong top_of_ram;
+
+ top_of_ram = get_top_of_ram(dev);
+ mrc_add_memory_area(info, 0, top_of_ram);
+
+ /* Add MTRRs for memory */
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
+
+ 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 = 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->saved_data = mrc_cache->data;
+ pei_data->saved_data_size = mrc_cache->data_size;
+ debug("%s: at %p, size %x checksum %04x\n", __func__,
+ pei_data->saved_data, pei_data->saved_data_size,
+ mrc_cache->checksum);
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ struct pei_data _pei_data __aligned(8);
+ struct pei_data *pei_data = &_pei_data;
+ struct udevice *dev, *me_dev, *pch_dev;
+ struct chipset_power_state ps;
+ const void *spd_data;
+ int ret, size;
+
+ memset(pei_data, '\0', sizeof(struct pei_data));
+
+ /* Print ME state before MRC */
+ ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
+ if (ret) {
+ debug("Cannot get ME (err=%d)\n", ret);
+ return ret;
+ }
+ intel_me_status(me_dev);
+
+ /* Save ME HSIO version */
+ ret = uclass_first_device_err(UCLASS_PCH, &pch_dev);
+ if (ret) {
+ debug("Cannot get PCH (err=%d)\n", ret);
+ return ret;
+ }
+ power_state_get(pch_dev, &ps);
+
+ intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum);
+
+ broadwell_fill_pei_data(pei_data);
+ mainboard_fill_pei_data(pei_data);
+
+ ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
+ if (ret) {
+ debug("Cannot get Northbridge (err=%d)\n", ret);
+ return ret;
+ }
+ size = 256;
+ ret = mrc_locate_spd(dev, size, &spd_data);
+ if (ret) {
+ debug("Cannot locate SPD (err=%d)\n", ret);
+ return ret;
+ }
+ memcpy(pei_data->spd_data[0][0], spd_data, size);
+ memcpy(pei_data->spd_data[1][0], spd_data, size);
+
+ ret = prepare_mrc_cache(pei_data);
+ if (ret)
+ debug("prepare_mrc_cache failed: %d\n", ret);
+
+ debug("PEI version %#x\n", pei_data->pei_version);
+ ret = mrc_common_init(dev, pei_data, true);
+ if (ret) {
+ debug("mrc_common_init() failed(err=%d)\n", ret);
+ return ret;
+ }
+ debug("Memory init done\n");
+
+ ret = sdram_find(dev);
+ if (ret) {
+ debug("sdram_find() failed (err=%d)\n", ret);
+ return ret;
+ }
+ gd->ram_size = gd->arch.meminfo.total_32bit_memory;
+ debug("RAM size %llx\n", (unsigned long long)gd->ram_size);
+
+ debug("MRC output data length %#x at %p\n", pei_data->data_to_save_size,
+ pei_data->data_to_save);
+ /* S3 resume: don't save scrambler seed or MRC data */
+ if (pei_data->boot_mode != SLEEP_STATE_S3) {
+ 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->data_to_save;
+ mrc->len = pei_data->data_to_save_size;
+ }
+ gd->arch.pei_meminfo = pei_data->meminfo;
+
+ 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);
+ else
+ debug("Saved MRC cache data\n");
+
+ return 0;
+}
+
+static const struct udevice_id broadwell_syscon_ids[] = {
+ { .compatible = "intel,me", .data = X86_SYSCON_ME },
+ { }
+};
+
+U_BOOT_DRIVER(syscon_intel_me) = {
+ .name = "intel_me_syscon",
+ .id = UCLASS_SYSCON,
+ .of_match = broadwell_syscon_ids,
+};