aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/x86/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/arch/x86/cpu')
-rw-r--r--roms/u-boot/arch/x86/cpu/Makefile77
-rw-r--r--roms/u-boot/arch/x86/cpu/acpi_gpe.c114
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/Kconfig113
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/Makefile27
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/acpi.c226
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/cpu.c202
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/cpu_common.c102
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/cpu_spl.c196
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/fsp_bindings.c1856
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/fsp_m.c67
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/fsp_s.c229
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/hostbridge.c395
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/lpc.c144
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/pch.c38
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/pmc.c224
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/punit.c97
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/spl.c157
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/systemagent.c23
-rw-r--r--roms/u-boot/arch/x86/cpu/apollolake/uart.c142
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/Kconfig42
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/Makefile9
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/acpi.c207
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/cpu.c209
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/early_uart.c86
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/fsp_configs.c171
-rw-r--r--roms/u-boot/arch/x86/cpu/baytrail/valleyview.c59
-rw-r--r--roms/u-boot/arch/x86/cpu/braswell/Kconfig33
-rw-r--r--roms/u-boot/arch/x86/cpu/braswell/Makefile5
-rw-r--r--roms/u-boot/arch/x86/cpu/braswell/braswell.c30
-rw-r--r--roms/u-boot/arch/x86/cpu/braswell/early_uart.c81
-rw-r--r--roms/u-boot/arch/x86/cpu/braswell/fsp_configs.c165
-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
-rw-r--r--roms/u-boot/arch/x86/cpu/call32.S61
-rw-r--r--roms/u-boot/arch/x86/cpu/config.mk15
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/Kconfig30
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/Makefile23
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/car.S12
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/coreboot.c87
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/coreboot_spl.c12
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/sdram.c103
-rw-r--r--roms/u-boot/arch/x86/cpu/coreboot/timestamp.c74
-rw-r--r--roms/u-boot/arch/x86/cpu/cpu.c358
-rw-r--r--roms/u-boot/arch/x86/cpu/cpu_x86.c99
-rw-r--r--roms/u-boot/arch/x86/cpu/efi/Kconfig11
-rw-r--r--roms/u-boot/arch/x86/cpu/efi/Makefile13
-rw-r--r--roms/u-boot/arch/x86/cpu/efi/app.c34
-rw-r--r--roms/u-boot/arch/x86/cpu/efi/car.S9
-rw-r--r--roms/u-boot/arch/x86/cpu/efi/payload.c294
-rw-r--r--roms/u-boot/arch/x86/cpu/efi/sdram.c32
-rw-r--r--roms/u-boot/arch/x86/cpu/i386/Makefile11
-rw-r--r--roms/u-boot/arch/x86/cpu/i386/call64.S99
-rw-r--r--roms/u-boot/arch/x86/cpu/i386/cpu.c669
-rw-r--r--roms/u-boot/arch/x86/cpu/i386/interrupt.c638
-rw-r--r--roms/u-boot/arch/x86/cpu/i386/setjmp.S60
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/Makefile46
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/acpi.c377
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/car.S244
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/car2.S448
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/car2_uninit.S87
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/cpu.c328
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/cpu_from_spl.c35
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/fast_spi.c82
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/generic_wifi.c120
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/intel_opregion.c168
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/itss.c232
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/lpc.c101
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/lpss.c44
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/me_status.c213
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/microcode.c188
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/mrc.c268
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/p2sb.c199
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/pch.c24
-rw-r--r--roms/u-boot/arch/x86/cpu/intel_common/report_platform.c90
-rw-r--r--roms/u-boot/arch/x86/cpu/ioapic.c37
-rw-r--r--roms/u-boot/arch/x86/cpu/irq.c367
-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
-rw-r--r--roms/u-boot/arch/x86/cpu/lapic.c159
-rw-r--r--roms/u-boot/arch/x86/cpu/mp_init.c902
-rw-r--r--roms/u-boot/arch/x86/cpu/mtrr.c319
-rw-r--r--roms/u-boot/arch/x86/cpu/pci.c101
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/Kconfig34
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/Makefile10
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/car.S25
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/cpu.c50
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/dram.c77
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/e820.c69
-rw-r--r--roms/u-boot/arch/x86/cpu/qemu/qemu.c150
-rw-r--r--roms/u-boot/arch/x86/cpu/qfw_cpu.c87
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/Kconfig138
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/Makefile7
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/acpi.c143
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/car.S104
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/dram.c190
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/hte.c395
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/hte.h43
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/mrc.c204
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/mrc_util.c1472
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/mrc_util.h120
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/msg_port.c76
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/quark.c384
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/smc.c2615
-rw-r--r--roms/u-boot/arch/x86/cpu/quark/smc.h532
-rw-r--r--roms/u-boot/arch/x86/cpu/queensbay/Kconfig67
-rw-r--r--roms/u-boot/arch/x86/cpu/queensbay/Makefile6
-rw-r--r--roms/u-boot/arch/x86/cpu/queensbay/fsp_configs.c19
-rw-r--r--roms/u-boot/arch/x86/cpu/queensbay/tnc.c150
-rw-r--r--roms/u-boot/arch/x86/cpu/resetvec.S18
-rw-r--r--roms/u-boot/arch/x86/cpu/sipi_vector.S215
-rw-r--r--roms/u-boot/arch/x86/cpu/slimbootloader/Kconfig20
-rw-r--r--roms/u-boot/arch/x86/cpu/slimbootloader/Makefile5
-rw-r--r--roms/u-boot/arch/x86/cpu/slimbootloader/car.S14
-rw-r--r--roms/u-boot/arch/x86/cpu/slimbootloader/sdram.c153
-rw-r--r--roms/u-boot/arch/x86/cpu/slimbootloader/serial.c66
-rw-r--r--roms/u-boot/arch/x86/cpu/slimbootloader/slimbootloader.c62
-rw-r--r--roms/u-boot/arch/x86/cpu/start.S316
-rw-r--r--roms/u-boot/arch/x86/cpu/start16.S122
-rw-r--r--roms/u-boot/arch/x86/cpu/start64.S28
-rw-r--r--roms/u-boot/arch/x86/cpu/start_from_spl.S89
-rw-r--r--roms/u-boot/arch/x86/cpu/start_from_tpl.S50
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/Kconfig32
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/Makefile6
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/acpi.c127
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/car.S12
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/pinmux.c195
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/sdram.c252
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/sysreset.c47
-rw-r--r--roms/u-boot/arch/x86/cpu/tangier/tangier.c27
-rw-r--r--roms/u-boot/arch/x86/cpu/turbo.c104
-rw-r--r--roms/u-boot/arch/x86/cpu/u-boot-64.lds111
-rw-r--r--roms/u-boot/arch/x86/cpu/u-boot-spl.lds103
-rw-r--r--roms/u-boot/arch/x86/cpu/u-boot.lds126
-rw-r--r--roms/u-boot/arch/x86/cpu/wakeup.S77
-rw-r--r--roms/u-boot/arch/x86/cpu/x86_64/Makefile6
-rw-r--r--roms/u-boot/arch/x86/cpu/x86_64/cpu.c77
-rw-r--r--roms/u-boot/arch/x86/cpu/x86_64/interrupts.c29
-rw-r--r--roms/u-boot/arch/x86/cpu/x86_64/setjmp.S49
163 files changed, 29241 insertions, 0 deletions
diff --git a/roms/u-boot/arch/x86/cpu/Makefile b/roms/u-boot/arch/x86/cpu/Makefile
new file mode 100644
index 000000000..16e67e3da
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/Makefile
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+
+ifeq ($(CONFIG_$(SPL_)X86_64),y)
+extra-y = start64.o
+else
+ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
+extra-y = start.o
+else
+ifndef CONFIG_SPL
+extra-y = start.o
+else
+ifdef CONFIG_SPL_BUILD
+extra-y = start_from_tpl.o
+else
+extra-y = start_from_spl.o
+endif
+endif
+endif
+endif
+
+extra-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += resetvec.o start16.o
+
+obj-y += cpu.o
+ifndef CONFIG_TPL_BUILD
+obj-y += cpu_x86.o
+endif
+
+ifndef CONFIG_$(SPL_)X86_64
+AFLAGS_REMOVE_call32.o := -mregparm=3 \
+ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
+AFLAGS_call32.o := -fpic -fshort-wchar \
+ $(if $(CONFIG_EFI_STUB_64BIT),-m64)
+
+extra-y += call32.o
+endif
+
+obj-y += intel_common/
+obj-$(CONFIG_INTEL_APOLLOLAKE) += apollolake/
+obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
+obj-$(CONFIG_INTEL_BRASWELL) += braswell/
+obj-$(CONFIG_INTEL_BROADWELL) += broadwell/
+obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_SYS_SLIMBOOTLOADER) += slimbootloader/
+obj-$(CONFIG_EFI) += efi/
+obj-$(CONFIG_QEMU) += qemu/
+obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
+obj-$(CONFIG_INTEL_QUARK) += quark/
+obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
+obj-$(CONFIG_INTEL_TANGIER) += tangier/
+obj-$(CONFIG_APIC) += lapic.o ioapic.o
+obj-$(CONFIG_$(SPL_TPL_)ACPI_GPE) += acpi_gpe.o
+obj-$(CONFIG_QFW) += qfw_cpu.o
+ifndef CONFIG_SYS_COREBOOT
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += irq.o
+endif
+ifndef CONFIG_$(SPL_)X86_64
+obj-$(CONFIG_$(SPL_)SMP) += mp_init.o
+endif
+obj-y += mtrr.o
+obj-$(CONFIG_PCI) += pci.o
+ifndef CONFIG_$(SPL_)X86_64
+obj-$(CONFIG_SMP) += sipi_vector.o
+endif
+obj-y += turbo.o
+obj-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.o
+
+ifeq ($(CONFIG_$(SPL_)X86_64),y)
+obj-y += x86_64/
+else
+obj-y += i386/
+endif
diff --git a/roms/u-boot/arch/x86/cpu/acpi_gpe.c b/roms/u-boot/arch/x86/cpu/acpi_gpe.c
new file mode 100644
index 000000000..da01e7133
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/acpi_gpe.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google, LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_IRQ
+
+#include <common.h>
+#include <dm.h>
+#include <irq.h>
+#include <log.h>
+#include <acpi/acpi_device.h>
+#include <asm/io.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/x86-irq.h>
+
+/**
+ * struct acpi_gpe_priv - private driver information
+ *
+ * @acpi_base: Base I/O address of ACPI registers
+ */
+struct acpi_gpe_priv {
+ ulong acpi_base;
+};
+
+#define GPE0_STS(x) (0x20 + ((x) * 4))
+
+static int acpi_gpe_read_and_clear(struct irq *irq)
+{
+ struct acpi_gpe_priv *priv = dev_get_priv(irq->dev);
+ u32 mask, sts;
+ ulong start;
+ int ret = 0;
+ int bank;
+
+ bank = irq->id / 32;
+ mask = 1 << (irq->id % 32);
+
+ /* Wait up to 1ms for GPE status to clear */
+ start = get_timer(0);
+ do {
+ if (get_timer(start) > 1)
+ return ret;
+
+ sts = inl(priv->acpi_base + GPE0_STS(bank));
+ if (sts & mask) {
+ outl(mask, priv->acpi_base + GPE0_STS(bank));
+ ret = 1;
+ }
+ } while (sts & mask);
+
+ return ret;
+}
+
+static int acpi_gpe_of_to_plat(struct udevice *dev)
+{
+ struct acpi_gpe_priv *priv = dev_get_priv(dev);
+
+ priv->acpi_base = dev_read_addr(dev);
+ if (!priv->acpi_base || priv->acpi_base == FDT_ADDR_T_NONE)
+ return log_msg_ret("acpi_base", -EINVAL);
+
+ return 0;
+}
+
+static int acpi_gpe_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
+{
+ irq->id = args->args[0];
+ irq->flags = args->args[1];
+
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(ACPIGEN)
+static int acpi_gpe_get_acpi(const struct irq *irq, struct acpi_irq *acpi_irq)
+{
+ memset(acpi_irq, '\0', sizeof(*acpi_irq));
+ acpi_irq->pin = irq->id;
+ acpi_irq->mode = irq->flags & IRQ_TYPE_EDGE_BOTH ?
+ ACPI_IRQ_EDGE_TRIGGERED : ACPI_IRQ_LEVEL_TRIGGERED;
+ acpi_irq->polarity = irq->flags &
+ (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW) ?
+ ACPI_IRQ_ACTIVE_LOW : ACPI_IRQ_ACTIVE_HIGH;
+ acpi_irq->shared = irq->flags & X86_IRQ_TYPE_SHARED ?
+ ACPI_IRQ_SHARED : ACPI_IRQ_EXCLUSIVE;
+ acpi_irq->wake = irq->flags & X86_IRQ_TYPE_WAKE ? ACPI_IRQ_WAKE :
+ ACPI_IRQ_NO_WAKE;
+
+ return 0;
+}
+#endif
+
+static const struct irq_ops acpi_gpe_ops = {
+ .read_and_clear = acpi_gpe_read_and_clear,
+ .of_xlate = acpi_gpe_of_xlate,
+#if CONFIG_IS_ENABLED(ACPIGEN)
+ .get_acpi = acpi_gpe_get_acpi,
+#endif
+};
+
+static const struct udevice_id acpi_gpe_ids[] = {
+ { .compatible = "intel,acpi-gpe", .data = X86_IRQT_ACPI_GPE },
+ { }
+};
+
+U_BOOT_DRIVER(intel_acpi_gpe) = {
+ .name = "intel_acpi_gpe",
+ .id = UCLASS_IRQ,
+ .of_match = acpi_gpe_ids,
+ .ops = &acpi_gpe_ops,
+ .of_to_plat = acpi_gpe_of_to_plat,
+ .priv_auto = sizeof(struct acpi_gpe_priv),
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/Kconfig b/roms/u-boot/arch/x86/cpu/apollolake/Kconfig
new file mode 100644
index 000000000..b3ce05317
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/Kconfig
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC
+#
+
+config INTEL_APOLLOLAKE
+ bool
+ select FSP_VERSION2
+ select HAVE_FSP
+ select ARCH_MISC_INIT
+ select USE_CAR
+ select INTEL_SOC
+ select INTEL_PMC
+ select TPL_X86_TSC_TIMER_NATIVE
+ select SPL_PCH_SUPPORT
+ select TPL_PCH_SUPPORT
+ select PCIEX_LENGTH_256MB
+ select PCH_SUPPORT
+ select P2SB
+ select SMP_AP_WORK
+ select INTEL_GMA_SWSMISCI
+ select ACPI_GNVS_EXTERNAL
+ select TPL_OF_PLATDATA_PARENT
+ select TPL_OF_PLATDATA_INST
+ select TPL_READ_ONLY
+ imply ENABLE_MRC_CACHE
+ imply AHCI_PCI
+ imply SCSI
+ imply SCSI_AHCI
+ imply SPI_FLASH
+ imply USB
+ imply USB_EHCI_HCD
+ imply TPL
+ imply SPL
+ imply TPL_X86_16BIT_INIT
+ imply TPL_OF_PLATDATA
+ imply ACPI_PMC
+ imply MMC
+ imply DM_MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply CMD_MMC
+ imply VIDEO_FSP
+ imply PINCTRL_INTEL
+ imply PINCTRL_INTEL_APL
+ imply HAVE_VBT
+ imply HAVE_X86_FIT
+ imply INTEL_GPIO
+ imply SMP
+ imply HAVE_ITSS
+ imply HAVE_P2SB
+ imply CLK
+ imply CMD_CLK
+ imply CLK_INTEL
+ imply ACPI_GPE
+ imply INTEL_GMA_ACPI
+
+if INTEL_APOLLOLAKE
+
+config DCACHE_RAM_BASE
+ default 0xfef00000
+
+config DCACHE_RAM_SIZE
+ default 0xc0000
+
+config DCACHE_RAM_MRC_VAR_SIZE
+ default 0xb0000
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select SMM_TSEG
+ select X86_RAMTEST
+
+config SMM_TSEG_SIZE
+ hex
+ default 0x800000
+
+config MMCONF_BASE_ADDRESS
+ hex
+ default 0xe0000000
+
+config TPL_SIZE_LIMIT
+ default 0x7800
+
+config CPU_ADDR_BITS
+ default 39
+
+config APL_SPI_FLASH_BOOT
+ bool "Support booting with SPI-flash driver instead memory-mapped SPI"
+ select TPL_SPI_FLASH_SUPPORT
+ select TPL_SPI_SUPPORT
+ select TPL_DM_SPI
+ select TPL_DM_SPI_FLASH
+ help
+ This enables SPI and SPI flash in TPL. Without the this only
+ available boot method is to use memory-mapped SPI. Since this is
+ actually fast and produces a TPL which is 7KB smaller, memory-mapped
+ SPI is the default.
+
+config APL_BOOT_FROM_FAST_SPI_FLASH
+ bool "Boot using SPI flash driver"
+ select APL_SPI_FLASH_BOOT
+ help
+ This option is separate from APL_SPI_FLASH_BOOT since it is useful to
+ be able to compare booting speed with the same build. Enable this to
+ use the SPI-flash driver to load SPL, U-Boot and FSP-M. For technical
+ reasons FSP-S is currently always loaded from memory-mapped SPI. See
+ Apollo Lake's arch_fsp_init_r() for details about that.
+
+config VBT_ADDR
+ default 0xff3f1000
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/Makefile b/roms/u-boot/arch/x86/cpu/apollolake/Makefile
new file mode 100644
index 000000000..2ddf4af62
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/Makefile
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2019 Google LLC
+
+obj-$(CONFIG_SPL_BUILD) += cpu_spl.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+obj-$(CONFIG_SPL_BUILD) += systemagent.o
+obj-y += cpu_common.o
+
+ifndef CONFIG_TPL_BUILD
+obj-y += cpu.o
+obj-y += punit.o
+obj-y += fsp_bindings.o
+ifdef CONFIG_SPL_BUILD
+obj-y += fsp_m.o
+endif
+endif
+ifndef CONFIG_SPL_BUILD
+obj-y += acpi.o
+obj-y += fsp_s.o
+endif
+
+obj-y += hostbridge.o
+obj-y += lpc.o
+obj-y += pch.o
+obj-y += pmc.o
+obj-y += uart.o
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/acpi.c b/roms/u-boot/arch/x86/cpu/apollolake/acpi.c
new file mode 100644
index 000000000..fd21c0b49
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/acpi.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * Copyright (C) 2017-2019 Siemens AG
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot apollolake/acpi.c
+ */
+
+#define LOG_CATEGORY LOGC_ACPI
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <log.h>
+#include <p2sb.h>
+#include <pci.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_s3.h>
+#include <asm/acpi_table.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_acpi.h>
+#include <asm/intel_gnvs.h>
+#include <asm/intel_pinctrl.h>
+#include <asm/intel_pinctrl_defs.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/systemagent.h>
+#include <dm/acpi.h>
+#include <dm/uclass-internal.h>
+#include <power/acpi_pmc.h>
+
+int arch_read_sci_irq_select(void)
+{
+ struct acpi_pmc_upriv *upriv;
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev);
+ if (ret)
+ return log_msg_ret("pmc", ret);
+ upriv = dev_get_uclass_priv(dev);
+
+ return readl(upriv->pmc_bar0 + IRQ_REG);
+}
+
+int arch_write_sci_irq_select(uint scis)
+{
+ struct acpi_pmc_upriv *upriv;
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev);
+ if (ret)
+ return log_msg_ret("pmc", ret);
+ upriv = dev_get_uclass_priv(dev);
+ writel(scis, upriv->pmc_bar0 + IRQ_REG);
+
+ return 0;
+}
+
+/**
+ * chromeos_init_acpi() - Initialise basic data to boot Chrome OS
+ *
+ * This tells Chrome OS to boot in developer mode
+ *
+ * @cros: Structure to initialise
+ */
+static void chromeos_init_acpi(struct chromeos_acpi_gnvs *cros)
+{
+ cros->active_main_fw = 1;
+ cros->active_main_fw = 1; /* A */
+ cros->switches = CHSW_DEVELOPER_SWITCH;
+ cros->main_fw_type = 2; /* Developer */
+}
+
+int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+ struct udevice *cpu;
+ int ret;
+
+ /* Clear out GNV */
+ memset(gnvs, '\0', sizeof(*gnvs));
+
+ /* TODO(sjg@chromium.org): Add the console log to gnvs->cbmc */
+
+ if (IS_ENABLED(CONFIG_CHROMEOS))
+ chromeos_init_acpi(&gnvs->chromeos);
+
+ /* Set unknown wake source */
+ gnvs->pm1i = ~0ULL;
+
+ /* CPU core count */
+ gnvs->pcnt = 1;
+ ret = uclass_find_first_device(UCLASS_CPU, &cpu);
+ if (cpu) {
+ ret = cpu_get_count(cpu);
+ if (ret > 0)
+ gnvs->pcnt = ret;
+ }
+
+ gnvs->dpte = 1;
+
+ return 0;
+}
+
+uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en)
+{
+ /*
+ * WAK_STS bit is set when the system is in one of the sleep states
+ * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting
+ * this bit, the PMC will transition the system to the ON state and
+ * can only be set by hardware and can only be cleared by writing a one
+ * to this bit position.
+ */
+ generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN;
+
+ return generic_pm1_en;
+}
+
+int arch_madt_sci_irq_polarity(int sci)
+{
+ return MP_IRQ_POLARITY_LOW;
+}
+
+void fill_fadt(struct acpi_fadt *fadt)
+{
+ fadt->pm_tmr_blk = IOMAP_ACPI_BASE + PM1_TMR;
+
+ fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+ fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+
+ fadt->pm_tmr_len = 4;
+ fadt->duty_width = 3;
+
+ fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+
+ fadt->x_pm_tmr_blk.space_id = 1;
+ fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
+ fadt->x_pm_tmr_blk.addrl = IOMAP_ACPI_BASE + PM1_TMR;
+}
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+ void *dsdt)
+{
+ struct acpi_table_header *header = &fadt->header;
+
+ acpi_fadt_common(fadt, facs, dsdt);
+ intel_acpi_fill_fadt(fadt);
+ fill_fadt(fadt);
+ header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+int apl_acpi_fill_dmar(struct acpi_ctx *ctx)
+{
+ struct udevice *dev, *sa_dev;
+ u64 gfxvtbar = readq(MCHBAR_REG(GFXVTBAR)) & VTBAR_MASK;
+ u64 defvtbar = readq(MCHBAR_REG(DEFVTBAR)) & VTBAR_MASK;
+ bool gfxvten = readl(MCHBAR_REG(GFXVTBAR)) & VTBAR_ENABLED;
+ bool defvten = readl(MCHBAR_REG(DEFVTBAR)) & VTBAR_ENABLED;
+ void *tmp;
+ int ret;
+
+ uclass_find_first_device(UCLASS_VIDEO, &dev);
+ ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa_dev);
+ if (ret)
+ return log_msg_ret("no sa", ret);
+
+ /* IGD has to be enabled, GFXVTBAR set and enabled */
+ if (dev && device_active(dev) && gfxvtbar && gfxvten) {
+ tmp = ctx->current;
+
+ acpi_create_dmar_drhd(ctx, 0, 0, gfxvtbar);
+ ret = acpi_create_dmar_ds_pci(ctx, PCI_BDF(0, 2, 0));
+ if (ret)
+ return log_msg_ret("ds_pci", ret);
+ acpi_dmar_drhd_fixup(ctx, tmp);
+
+ /* Add RMRR entry */
+ tmp = ctx->current;
+ acpi_create_dmar_rmrr(ctx->current, 0, sa_get_gsm_base(sa_dev),
+ sa_get_tolud_base(sa_dev) - 1);
+ acpi_create_dmar_ds_pci(ctx->current, PCI_BDF(0, 2, 0));
+ acpi_dmar_rmrr_fixup(ctx, tmp);
+ }
+
+ /* DEFVTBAR has to be set and enabled */
+ if (defvtbar && defvten) {
+ struct udevice *p2sb_dev;
+ u16 ibdf, hbdf;
+ uint ioapic, hpet;
+ int ret;
+
+ tmp = ctx->current;
+ /*
+ * P2SB may already be hidden. There's no clear rule, when.
+ * It is needed to get bus, device and function for IOAPIC and
+ * HPET device which is stored in P2SB device. So unhide it to
+ * get the info and hide it again when done.
+ *
+ * TODO(sjg@chromium.org): p2sb_unhide() ?
+ */
+ ret = uclass_first_device_err(UCLASS_P2SB, &p2sb_dev);
+ if (ret)
+ return log_msg_ret("p2sb", ret);
+
+ dm_pci_read_config16(p2sb_dev, PCH_P2SB_IBDF, &ibdf);
+ ioapic = PCI_TO_BDF(ibdf);
+ dm_pci_read_config16(p2sb_dev, PCH_P2SB_HBDF, &hbdf);
+ hpet = PCI_TO_BDF(hbdf);
+ /* TODO(sjg@chromium.org): p2sb_hide() ? */
+
+ acpi_create_dmar_drhd(ctx, DRHD_INCLUDE_PCI_ALL, 0, defvtbar);
+ acpi_create_dmar_ds_ioapic(ctx, 2, ioapic);
+ acpi_create_dmar_ds_msi_hpet(ctx, 0, hpet);
+ acpi_dmar_drhd_fixup(tmp, ctx->current);
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/cpu.c b/roms/u-boot/arch/x86/cpu/apollolake/cpu.c
new file mode 100644
index 000000000..647c9df6a
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/cpu.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <log.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_table.h>
+#include <asm/cpu_common.h>
+#include <asm/cpu_x86.h>
+#include <asm/global_data.h>
+#include <asm/intel_acpi.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/iomap.h>
+#include <dm/acpi.h>
+
+#ifdef CONFIG_ACPIGEN
+#define CSTATE_RES(address_space, width, offset, address) \
+ { \
+ .space_id = address_space, \
+ .bit_width = width, \
+ .bit_offset = offset, \
+ .addrl = address, \
+ }
+
+static struct acpi_cstate cstate_map[] = {
+ {
+ /* C1 */
+ .ctype = 1, /* ACPI C1 */
+ .latency = 1,
+ .power = 1000,
+ .resource = {
+ .space_id = ACPI_ADDRESS_SPACE_FIXED,
+ },
+ }, {
+ .ctype = 2, /* ACPI C2 */
+ .latency = 50,
+ .power = 10,
+ .resource = {
+ .space_id = ACPI_ADDRESS_SPACE_IO,
+ .bit_width = 8,
+ .addrl = 0x415,
+ },
+ }, {
+ .ctype = 3, /* ACPI C3 */
+ .latency = 150,
+ .power = 10,
+ .resource = {
+ .space_id = ACPI_ADDRESS_SPACE_IO,
+ .bit_width = 8,
+ .addrl = 0x419,
+ },
+ },
+};
+
+static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ uint core_id = dev_seq(dev);
+ int cores_per_package;
+ int ret;
+
+ cores_per_package = cpu_get_cores_per_package();
+ ret = acpi_generate_cpu_header(ctx, core_id, cstate_map,
+ ARRAY_SIZE(cstate_map));
+
+ /* Generate P-state tables */
+ generate_p_state_entries(ctx, core_id, cores_per_package);
+
+ /* Generate T-state tables */
+ generate_t_state_entries(ctx, core_id, cores_per_package, NULL, 0);
+
+ acpigen_pop_len(ctx);
+
+ if (device_is_last_sibling(dev)) {
+ ret = acpi_generate_cpu_package_final(ctx, cores_per_package);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_ACPIGEN */
+
+static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+}
+
+static void update_fixed_mtrrs(void)
+{
+ native_write_msr(MTRR_FIX_64K_00000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_16K_80000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_E0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_E8000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_F0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_F8000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+}
+
+static void setup_core_msrs(void)
+{
+ wrmsrl(MSR_PMG_CST_CONFIG_CONTROL,
+ PKG_C_STATE_LIMIT_C2_MASK | CORE_C_STATE_LIMIT_C10_MASK |
+ IO_MWAIT_REDIRECT_MASK | CST_CFG_LOCK_MASK);
+ /* Power Management I/O base address for I/O trapping to C-states */
+ wrmsrl(MSR_PMG_IO_CAPTURE_ADR, ACPI_PMIO_CST_REG |
+ (PMG_IO_BASE_CST_RNG_BLK_SIZE << 16));
+ /* Disable C1E */
+ msr_clrsetbits_64(MSR_POWER_CTL, 0x2, 0);
+ /* Disable support for MONITOR and MWAIT instructions */
+ msr_clrsetbits_64(MSR_IA32_MISC_ENABLE, MISC_ENABLE_MWAIT, 0);
+ /*
+ * Enable and Lock the Advanced Encryption Standard (AES-NI)
+ * feature register
+ */
+ msr_clrsetbits_64(MSR_FEATURE_CONFIG, FEATURE_CONFIG_RESERVED_MASK,
+ FEATURE_CONFIG_LOCK);
+
+ update_fixed_mtrrs();
+}
+
+static int soc_core_init(void)
+{
+ struct udevice *pmc;
+ int ret;
+
+ /* Clear out pending MCEs */
+ cpu_mca_configure();
+
+ /* Set core MSRs */
+ setup_core_msrs();
+ /*
+ * Enable ACPI PM timer emulation, which also lets microcode know
+ * location of ACPI_BASE_ADDRESS. This also enables other features
+ * implemented in microcode.
+ */
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
+ if (ret)
+ return log_msg_ret("PMC", ret);
+ enable_pm_timer_emulation(pmc);
+
+ return 0;
+}
+
+static int cpu_apl_probe(struct udevice *dev)
+{
+ if (gd->flags & GD_FLG_RELOC) {
+ int ret;
+
+ ret = soc_core_init();
+ if (ret)
+ return log_ret(ret);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_ACPIGEN
+struct acpi_ops apl_cpu_acpi_ops = {
+ .fill_ssdt = acpi_cpu_fill_ssdt,
+};
+#endif
+
+static const struct cpu_ops cpu_x86_apl_ops = {
+ .get_desc = cpu_x86_get_desc,
+ .get_info = apl_get_info,
+ .get_count = cpu_x86_get_count,
+ .get_vendor = cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_apl_ids[] = {
+ { .compatible = "intel,apl-cpu" },
+ { }
+};
+
+U_BOOT_DRIVER(intel_apl_cpu) = {
+ .name = "intel_apl_cpu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_x86_apl_ids,
+ .bind = cpu_x86_bind,
+ .probe = cpu_apl_probe,
+ .ops = &cpu_x86_apl_ops,
+ ACPI_OPS_PTR(&apl_cpu_acpi_ops)
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/cpu_common.c b/roms/u-boot/arch/x86/cpu/apollolake/cpu_common.c
new file mode 100644
index 000000000..5d7d26b14
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/cpu_common.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/cpu_common.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/pci.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/uart.h>
+#include <power/acpi_pmc.h>
+
+/* Define this here to avoid referencing any drivers for the debug UART 1 */
+#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0)
+
+void cpu_flush_l1d_to_l2(void)
+{
+ struct msr_t msr;
+
+ msr = msr_read(MSR_POWER_MISC);
+ msr.lo |= FLUSH_DL1_L2;
+ msr_write(MSR_POWER_MISC, msr);
+}
+
+void enable_pm_timer_emulation(const struct udevice *pmc)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
+ msr_t msr;
+
+ /*
+ * The derived frequency is calculated as follows:
+ * (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
+ *
+ * Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
+ * used.
+ */
+ msr.hi = (3579545ULL << 32) / CTC_FREQ;
+
+ /* Set PM1 timer IO port and enable */
+ msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
+ debug("PM timer %x %x\n", msr.hi, msr.lo);
+ msr_write(MSR_EMULATE_PM_TIMER, msr);
+}
+
+static void pch_uart_init(void)
+{
+ /*
+ * Set up the pinmux so that the UART rx/tx signals are connected
+ * outside the SoC.
+ *
+ * There are about 500 lines of code required to program the GPIO
+ * configuration for the UARTs. But it boils down to four writes, and
+ * for the debug UART we want the minimum possible amount of code before
+ * the UART is running. So just add the magic writes here. See
+ * apl_hostbridge_early_init_pinctrl() for the full horror.
+ */
+ if (PCI_FUNC(PCH_DEV_UART) == 1) {
+ writel(0x40000402, 0xd0c50650);
+ writel(0x3c47, 0xd0c50654);
+ writel(0x40000400, 0xd0c50658);
+ writel(0x3c48, 0xd0c5065c);
+ } else { /* UART2 */
+ writel(0x40000402, 0xd0c50670);
+ writel(0x3c4b, 0xd0c50674);
+ writel(0x40000400, 0xd0c50678);
+ writel(0x3c4c, 0xd0c5067c);
+ }
+
+#ifdef CONFIG_DEBUG_UART
+ apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
+#endif
+}
+
+static void p2sb_enable_bar(ulong bar)
+{
+ /* Enable PCR Base address in PCH */
+ pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
+ PCI_SIZE_32);
+ pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+ /* Enable P2SB MSE */
+ pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
+ PCI_SIZE_8);
+}
+
+/*
+ * board_debug_uart_init() - Init the debug UART ready for use
+ *
+ * This is the minimum init needed to get the UART running. It avoids any
+ * drivers or complex code, so that the UART is running as soon as possible.
+ */
+void board_debug_uart_init(void)
+{
+ p2sb_enable_bar(IOMAP_P2SB_BAR);
+ pch_uart_init();
+}
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/cpu_spl.c b/roms/u-boot/arch/x86/cpu/apollolake/cpu_spl.c
new file mode 100644
index 000000000..8f48457ee
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/cpu_spl.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Portions taken from coreboot
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ec_commands.h>
+#include <init.h>
+#include <log.h>
+#include <spi_flash.h>
+#include <spl.h>
+#include <syscon.h>
+#include <acpi/acpi_s3.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/cpu_x86.h>
+#include <asm/fast_spi.h>
+#include <asm/global_data.h>
+#include <asm/intel_pinctrl.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/lpc.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/systemagent.h>
+#include <asm/fsp2/fsp_api.h>
+#include <linux/sizes.h>
+#include <power/acpi_pmc.h>
+
+static int fast_spi_cache_bios_region(void)
+{
+ uint map_size, offset;
+ ulong map_base, base;
+ int ret;
+
+ ret = fast_spi_early_init(PCH_DEV_SPI, IOMAP_SPI_BASE);
+ if (ret)
+ return log_msg_ret("early_init", ret);
+
+ ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
+ &offset);
+ if (ret)
+ return log_msg_ret("get_mmap", ret);
+
+ base = SZ_4G - map_size;
+ mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
+ log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
+
+ return 0;
+}
+
+static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
+{
+ uint base;
+ uint size;
+
+ if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) {
+ base = MEC_EMI_BASE;
+ size = MEC_EMI_SIZE;
+ } else {
+ base = EC_HOST_CMD_REGION0;
+ size = 2 * EC_HOST_CMD_REGION_SIZE;
+ /* Make sure MEMMAP region follows host cmd region */
+ assert(base + size == EC_LPC_ADDR_MEMMAP);
+ size += EC_MEMMAP_SIZE;
+ }
+
+ *out_basep = base;
+ *out_sizep = size;
+}
+
+static void early_ec_init(void)
+{
+ uint base, size;
+
+ /*
+ * Set up LPC decoding for the Chrome OS EC I/O port ranges:
+ * - Ports 62/66, 60/64, and 200->208
+ * - Chrome OS EC communication I/O ports
+ */
+ lpc_enable_fixed_io_ranges(LPC_IOE_EC_62_66 | LPC_IOE_KBC_60_64 |
+ LPC_IOE_LGE_200);
+ google_chromeec_ioport_range(&base, &size);
+ lpc_open_pmio_window(base, size);
+}
+
+static int arch_cpu_init_tpl(void)
+{
+ struct udevice *pmc, *sa, *p2sb, *serial, *spi, *lpc;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
+ if (ret)
+ return log_msg_ret("PMC", ret);
+
+ /* Clear global reset promotion bit */
+ ret = pmc_global_reset_set_enable(pmc, false);
+ if (ret)
+ return log_msg_ret("disable global reset", ret);
+
+ enable_pm_timer_emulation(pmc);
+
+ ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
+ if (ret)
+ return log_msg_ret("p2sb", ret);
+ ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa);
+ if (ret)
+ return log_msg_ret("northbridge", ret);
+ gd->baudrate = CONFIG_BAUDRATE;
+ ret = uclass_first_device_err(UCLASS_SERIAL, &serial);
+ if (ret)
+ return log_msg_ret("serial", ret);
+ if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
+ ret = uclass_first_device_err(UCLASS_SPI, &spi);
+ if (ret)
+ return log_msg_ret("SPI", ret);
+ } else {
+ /* Alternative code if we don't have SPI in TPL */
+ if (IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH))
+ printf("Warning: Enable APL_SPI_FLASHBOOT to use SPI-flash driver in TPL");
+ ret = fast_spi_cache_bios_region();
+ if (ret)
+ return log_msg_ret("BIOS cache", ret);
+ }
+ ret = pmc_disable_tco(pmc);
+ if (ret)
+ return log_msg_ret("disable TCO", ret);
+ ret = pmc_gpe_init(pmc);
+ if (ret)
+ return log_msg_ret("pmc_gpe", ret);
+ ret = uclass_first_device_err(UCLASS_LPC, &lpc);
+ if (ret)
+ return log_msg_ret("lpc", ret);
+
+ early_ec_init();
+
+ return 0;
+}
+
+/*
+ * Enables several BARs and devices which are needed for memory init
+ * - MCH_BASE_ADDR is needed in order to talk to the memory controller
+ * - HPET is enabled because FSP wants to store a pointer to global data in the
+ * HPET comparator register
+ */
+static int arch_cpu_init_spl(void)
+{
+ struct udevice *pmc, *p2sb;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
+ if (ret)
+ return log_msg_ret("Could not probe PMC", ret);
+ ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
+ if (ret)
+ return log_msg_ret("Cannot set up p2sb", ret);
+
+ lpc_io_setup_comm_a_b();
+
+ /* TODO(sjg@chromium.org): Enable upper RTC bank here */
+
+ ret = pmc_init(pmc);
+ if (ret < 0)
+ return log_msg_ret("Could not init PMC", ret);
+ if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
+ ret = pmc_prev_sleep_state(pmc);
+ if (ret < 0)
+ return log_msg_ret("Could not get PMC sleep state",
+ ret);
+ gd->arch.prev_sleep_state = ret;
+ }
+
+ return 0;
+}
+
+int arch_cpu_init(void)
+{
+ int ret = 0;
+
+ if (spl_phase() == PHASE_TPL)
+ ret = arch_cpu_init_tpl();
+ else if (spl_phase() == PHASE_SPL)
+ ret = arch_cpu_init_spl();
+ if (ret)
+ printf("%s: Error %d\n", __func__, ret);
+
+ return ret;
+}
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/fsp_bindings.c b/roms/u-boot/arch/x86/cpu/apollolake/fsp_bindings.c
new file mode 100644
index 000000000..319c78b95
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/fsp_bindings.c
@@ -0,0 +1,1856 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020 B&R Industrial Automation GmbH - http://www.br-automation.com
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/arch/fsp_bindings.h>
+
+/**
+ * read_u8_prop() - Read an u8 property from devicetree (scalar or array)
+ * @node: Valid node reference to read property from
+ * @name: Name of the property to read from
+ * @count: If the property is expected to be an array, this is the
+ * number of expected elements
+ * Set to 0 if the property is expected to be a scalar
+ * @dst: Pointer to destination of where to save the value(s) read
+ * from devicetree
+ */
+static void read_u8_prop(ofnode node, char *name, size_t count, u8 *dst)
+{
+ u32 tmp;
+ const u8 *buf;
+ int ret;
+
+ if (count == 0) {
+ ret = ofnode_read_u32(node, name, &tmp);
+ if (ret == 0)
+ *dst = tmp;
+ } else {
+ buf = ofnode_read_u8_array_ptr(node, name, count);
+ if (buf)
+ memcpy(dst, buf, count);
+ }
+}
+
+/**
+ * read_u16_prop() - Read an u16 property from devicetree (scalar or array)
+ * @node: Valid node reference to read property from
+ * @name: Name of the property to read from
+ * @count: If the property is expected to be an array, this is the
+ * number of expected elements
+ * Set to 0 if the property is expected to be a scalar
+ * @dst: Pointer to destination of where to save the value(s) read
+ * from devicetree
+ * @return 0 on success, -ve on error
+ */
+static int read_u16_prop(ofnode node, char *name, size_t count, u16 *dst)
+{
+ u32 tmp;
+ u32 buf[32];
+ int ret;
+
+ if (ARRAY_SIZE(buf) < count) {
+ debug("ERROR: %s buffer to small!\n", __func__);
+ return -ENOSPC;
+ }
+
+ if (count == 0) {
+ ret = ofnode_read_u32(node, name, &tmp);
+ if (ret == 0)
+ *dst = tmp;
+ } else {
+ ret = ofnode_read_u32_array(node, name, buf, count);
+ if (ret == 0)
+ for (int i = 0; i < count; i++)
+ dst[i] = buf[i];
+ }
+
+ return 0;
+}
+
+/**
+ * read_u32_prop() - Read an u32 property from devicetree (scalar or array)
+ * @node: Valid node reference to read property from
+ * @name: Name of the property to read from
+ * @count: If the property is expected to be an array, this is the
+ * number of expected elements
+ * set to 0 if the property is expected to be a scalar
+ * @dst: Pointer to destination of where to save the value(s) read
+ * from devicetree
+ */
+static void read_u32_prop(ofnode node, char *name, size_t count, u32 *dst)
+{
+ if (count == 0)
+ ofnode_read_u32(node, name, dst);
+ else
+ ofnode_read_u32_array(node, name, dst, count);
+}
+
+/**
+ * read_u64_prop() - Read an u64 property from devicetree (scalar or array)
+ * @node: Valid node reference to read property from
+ * @name: Name of the property to read from
+ * @count: If the property is expected to be an array, this is the
+ * number of expected elements
+ * set to 0 if the property is expected to be a scalar
+ * @dst: Pointer to destination of where to save the value(s) read
+ * from devicetree
+ */
+static int read_u64_prop(ofnode node, char *name, size_t count, u64 *dst)
+{
+ if (count == 0) {
+ ofnode_read_u64(node, name, dst);
+ } else {
+ debug("ERROR: %s u64 arrays not supported!\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * read_string_prop() - Read a string property from devicetree
+ * @node: Valid node reference to read property from
+ * @name: Name of the property to read from
+ * @count: Size of the destination buffer
+ * @dst: Pointer to destination of where to save the values read
+ * from devicetree
+ */
+static void read_string_prop(ofnode node, char *name, size_t count, char *dst)
+{
+ const char *string_buf;
+
+ if (count > 0) {
+ string_buf = ofnode_read_string(node, name);
+ if (string_buf)
+ strlcpy(dst, string_buf, count);
+ }
+}
+
+/**
+ * read_swizzle_prop() - Read a swizzle property from devicetree
+ * @node: Valid node reference to read property from
+ * @name: Name of the property to read from
+ * @count: Number of elements in the swizzle configuration
+ * @dst: pointer to destination of where to save the values read
+ * from devicetree
+ */
+static void read_swizzle_prop(ofnode node, char *name, size_t count, u8 *dst)
+{
+ const struct lpddr4_chan_swizzle_cfg *sch;
+ /* Number of bytes to copy per DQS */
+ const size_t sz = DQ_BITS_PER_DQS;
+ const struct lpddr4_swizzle_cfg *swizzle_cfg;
+
+ swizzle_cfg = (const struct lpddr4_swizzle_cfg *)
+ ofnode_read_u8_array_ptr(node, name, count);
+
+ if (!swizzle_cfg)
+ return;
+ /*
+ * CH0_DQB byte lanes in the bit swizzle configuration field are
+ * not 1:1. The mapping within the swizzling field is:
+ * indices [0:7] - byte lane 1 (DQS1) DQ[8:15]
+ * indices [8:15] - byte lane 0 (DQS0) DQ[0:7]
+ * indices [16:23] - byte lane 3 (DQS3) DQ[24:31]
+ * indices [24:31] - byte lane 2 (DQS2) DQ[16:23]
+ */
+ sch = &swizzle_cfg->phys[LP4_PHYS_CH0B];
+ memcpy(&dst[0 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz);
+ memcpy(&dst[1 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz);
+ memcpy(&dst[2 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz);
+ memcpy(&dst[3 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz);
+
+ /*
+ * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
+ */
+ sch = &swizzle_cfg->phys[LP4_PHYS_CH0A];
+ memcpy(&dst[4 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz);
+ memcpy(&dst[5 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz);
+ memcpy(&dst[6 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz);
+ memcpy(&dst[7 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz);
+
+ sch = &swizzle_cfg->phys[LP4_PHYS_CH1B];
+ memcpy(&dst[8 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz);
+ memcpy(&dst[9 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz);
+ memcpy(&dst[10 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz);
+ memcpy(&dst[11 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz);
+
+ /*
+ * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
+ */
+ sch = &swizzle_cfg->phys[LP4_PHYS_CH1A];
+ memcpy(&dst[12 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz);
+ memcpy(&dst[13 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz);
+ memcpy(&dst[14 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz);
+ memcpy(&dst[15 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz);
+}
+
+/**
+ * fsp_update_config_from_dtb() - Read FSP config from devicetree node
+ * @node: Valid node reference to read property from
+ * @cfg: Pointer to FSP config structure
+ * @fsp_bindings: Binding describing which devicetree properties should
+ * be stored where in the FSP configuration structure
+ * The end of the list is declared by a NULL pointer in propname
+ * @return 0 on success, -ve on error
+ *
+ * This function reads the configuration for FSP from the provided
+ * devicetree node and saves it in the FSP configuration structure.
+ * Configuration options that are not present in the devicetree are
+ * left at their current value.
+ */
+__maybe_unused
+static int fsp_update_config_from_dtb(ofnode node, u8 *cfg,
+ const struct fsp_binding *fsp_bindings)
+{
+ const struct fsp_binding *fspb;
+ int ret;
+
+ for (int i = 0; fsp_bindings[i].propname; i++) {
+ fspb = &fsp_bindings[i];
+
+ switch (fspb->type) {
+ case FSP_UINT8:
+ read_u8_prop(node, fspb->propname, fspb->count,
+ &cfg[fspb->offset]);
+ break;
+ case FSP_UINT16:
+ ret = read_u16_prop(node, fspb->propname, fspb->count,
+ (u16 *)&cfg[fspb->offset]);
+ if (ret)
+ return ret;
+ break;
+ case FSP_UINT32:
+ read_u32_prop(node, fspb->propname, fspb->count,
+ (u32 *)&cfg[fspb->offset]);
+ break;
+ case FSP_UINT64:
+ ret = read_u64_prop(node, fspb->propname, fspb->count,
+ (u64 *)&cfg[fspb->offset]);
+ if (ret)
+ return ret;
+ break;
+ case FSP_STRING:
+ read_string_prop(node, fspb->propname, fspb->count,
+ (char *)&cfg[fspb->offset]);
+ break;
+ case FSP_LPDDR4_SWIZZLE:
+ read_swizzle_prop(node, fspb->propname, fspb->count,
+ &cfg[fspb->offset]);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_SPL_BUILD)
+const struct fsp_binding fsp_m_bindings[] = {
+ {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, serial_debug_port_address),
+ .propname = "fspm,serial-debug-port-address",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, serial_debug_port_type),
+ .propname = "fspm,serial-debug-port-type",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, serial_debug_port_device),
+ .propname = "fspm,serial-debug-port-device",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, serial_debug_port_stride_size),
+ .propname = "fspm,serial-debug-port-stride-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, mrc_fast_boot),
+ .propname = "fspm,mrc-fast-boot",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, igd),
+ .propname = "fspm,igd",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, igd_dvmt50_pre_alloc),
+ .propname = "fspm,igd-dvmt50-pre-alloc",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, igd_aperture_size),
+ .propname = "fspm,igd-aperture-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, gtt_size),
+ .propname = "fspm,gtt-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, primary_video_adaptor),
+ .propname = "fspm,primary-video-adaptor",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, package),
+ .propname = "fspm,package",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, profile),
+ .propname = "fspm,profile",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, memory_down),
+ .propname = "fspm,memory-down",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, ddr3_l_page_size),
+ .propname = "fspm,ddr3-l-page-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, ddr3_lasr),
+ .propname = "fspm,ddr3-lasr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, scrambler_support),
+ .propname = "fspm,scrambler-support",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, interleaved_mode),
+ .propname = "fspm,interleaved-mode",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_m_config, channel_hash_mask),
+ .propname = "fspm,channel-hash-mask",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_m_config, slice_hash_mask),
+ .propname = "fspm,slice-hash-mask",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, channels_slices_enable),
+ .propname = "fspm,channels-slices-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, min_ref_rate2x_enable),
+ .propname = "fspm,min-ref-rate2x-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, dual_rank_support_enable),
+ .propname = "fspm,dual-rank-support-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, rmt_mode),
+ .propname = "fspm,rmt-mode",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_m_config, memory_size_limit),
+ .propname = "fspm,memory-size-limit",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_m_config, low_memory_max_value),
+ .propname = "fspm,low-memory-max-value",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_m_config, high_memory_max_value),
+ .propname = "fspm,high-memory-max-value",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, disable_fast_boot),
+ .propname = "fspm,disable-fast-boot",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, dimm0_spd_address),
+ .propname = "fspm,dimm0-spd-address",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, dimm1_spd_address),
+ .propname = "fspm,dimm1-spd-address",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].rank_enable),
+ .propname = "fspm,ch0-rank-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].device_width),
+ .propname = "fspm,ch0-device-width",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].dram_density),
+ .propname = "fspm,ch0-dram-density",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].option),
+ .propname = "fspm,ch0-option",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].odt_config),
+ .propname = "fspm,ch0-odt-config",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].tristate_clk1),
+ .propname = "fspm,ch0-tristate-clk1",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].mode2_n),
+ .propname = "fspm,ch0-mode2-n",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[0].odt_levels),
+ .propname = "fspm,ch0-odt-levels",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].rank_enable),
+ .propname = "fspm,ch1-rank-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].device_width),
+ .propname = "fspm,ch1-device-width",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].dram_density),
+ .propname = "fspm,ch1-dram-density",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].option),
+ .propname = "fspm,ch1-option",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].odt_config),
+ .propname = "fspm,ch1-odt-config",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].tristate_clk1),
+ .propname = "fspm,ch1-tristate-clk1",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].mode2_n),
+ .propname = "fspm,ch1-mode2-n",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[1].odt_levels),
+ .propname = "fspm,ch1-odt-levels",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].rank_enable),
+ .propname = "fspm,ch2-rank-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].device_width),
+ .propname = "fspm,ch2-device-width",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].dram_density),
+ .propname = "fspm,ch2-dram-density",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].option),
+ .propname = "fspm,ch2-option",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].odt_config),
+ .propname = "fspm,ch2-odt-config",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].tristate_clk1),
+ .propname = "fspm,ch2-tristate-clk1",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].mode2_n),
+ .propname = "fspm,ch2-mode2-n",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[2].odt_levels),
+ .propname = "fspm,ch2-odt-levels",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].rank_enable),
+ .propname = "fspm,ch3-rank-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].device_width),
+ .propname = "fspm,ch3-device-width",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].dram_density),
+ .propname = "fspm,ch3-dram-density",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].option),
+ .propname = "fspm,ch3-option",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].odt_config),
+ .propname = "fspm,ch3-odt-config",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].tristate_clk1),
+ .propname = "fspm,ch3-tristate-clk1",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].mode2_n),
+ .propname = "fspm,ch3-mode2-n",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, chan[3].odt_levels),
+ .propname = "fspm,ch3-odt-levels",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, rmt_check_run),
+ .propname = "fspm,rmt-check-run",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_m_config,
+ rmt_margin_check_scale_high_threshold),
+ .propname = "fspm,rmt-margin-check-scale-high-threshold",
+ }, {
+ .type = FSP_LPDDR4_SWIZZLE,
+ .offset = offsetof(struct fsp_m_config, ch_bit_swizzling),
+ .propname = "fspm,ch-bit-swizzling",
+ .count = SIZE_OF_MEMBER(struct fsp_m_config, ch_bit_swizzling) /
+ SIZE_OF_MEMBER(struct fsp_m_config, ch_bit_swizzling[0][0])
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, msg_level_mask),
+ .propname = "fspm,msg-level-mask",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, pre_mem_gpio_table_pin_num),
+ .propname = "fspm,pre-mem-gpio-table-pin-num",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_m_config,
+ pre_mem_gpio_table_pin_num),
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, pre_mem_gpio_table_ptr),
+ .propname = "fspm,pre-mem-gpio-table-ptr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, pre_mem_gpio_table_entry_num),
+ .propname = "fspm,pre-mem-gpio-table-entry-num",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, enhance_port8xh_decoding),
+ .propname = "fspm,enhance-port8xh-decoding",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, spd_write_enable),
+ .propname = "fspm,spd-write-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, mrc_data_saving),
+ .propname = "fspm,mrc-data-saving",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, oem_loading_base),
+ .propname = "fspm,oem-loading-base",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, oem_file_name),
+ .propname = "fspm,oem-file-name",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_m_config, oem_file_name),
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, mrc_boot_data_ptr),
+ .propname = "fspm,mrc-boot-data-ptr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, e_mmc_trace_len),
+ .propname = "fspm,emmc-trace-len",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, skip_cse_rbp),
+ .propname = "fspm,skip-cse-rbp",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, npk_en),
+ .propname = "fspm,npk-en",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, fw_trace_en),
+ .propname = "fspm,fw-trace-en",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, fw_trace_destination),
+ .propname = "fspm,fw-trace-destination",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, recover_dump),
+ .propname = "fspm,recover-dump",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, msc0_wrap),
+ .propname = "fspm,msc0-wrap",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, msc1_wrap),
+ .propname = "fspm,msc1-wrap",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, msc0_size),
+ .propname = "fspm,msc0-size",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, msc1_size),
+ .propname = "fspm,msc1-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, pti_mode),
+ .propname = "fspm,pti-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, pti_training),
+ .propname = "fspm,pti-training",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, pti_speed),
+ .propname = "fspm,pti-speed",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, punit_mlvl),
+ .propname = "fspm,punit-mlvl",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, pmc_mlvl),
+ .propname = "fspm,pmc-mlvl",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, sw_trace_en),
+ .propname = "fspm,sw-trace-en",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, periodic_retraining_disable),
+ .propname = "fspm,periodic-retraining-disable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, enable_reset_system),
+ .propname = "fspm,enable-reset-system",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, enable_s3_heci2),
+ .propname = "fspm,enable-s3-heci2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_m_config, variable_nvs_buffer_ptr),
+ .propname = "fspm,variable-nvs-buffer-ptr",
+ }, {
+ .type = FSP_UINT64,
+ .offset = offsetof(struct fsp_m_config, start_timer_ticker_of_pfet_assert),
+ .propname = "fspm,start-timer-ticker-of-pfet-assert",
+ }, {
+ .type = FSP_UINT8, .offset = offsetof(struct fsp_m_config, rt_en),
+ .propname = "fspm,rt-en",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_m_config, skip_pcie_power_sequence),
+ .propname = "fspm,skip-pcie-power-sequence",
+ }, {
+ .propname = NULL
+ }
+};
+
+int fsp_m_update_config_from_dtb(ofnode node, struct fsp_m_config *cfg)
+{
+ return fsp_update_config_from_dtb(node, (u8 *)cfg, fsp_m_bindings);
+}
+#endif
+
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
+const struct fsp_binding fsp_s_bindings[] = {
+ {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, active_processor_cores),
+ .propname = "fsps,active-processor-cores",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, disable_core1),
+ .propname = "fsps,disable-core1",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, disable_core2),
+ .propname = "fsps,disable-core2",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, disable_core3),
+ .propname = "fsps,disable-core3",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, vmx_enable),
+ .propname = "fsps,vmx-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, proc_trace_mem_size),
+ .propname = "fsps,proc-trace-mem-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, proc_trace_enable),
+ .propname = "fsps,proc-trace-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, eist),
+ .propname = "fsps,eist",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, boot_p_state),
+ .propname = "fsps,boot-p-state",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, enable_cx),
+ .propname = "fsps,enable-cx",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, c1e),
+ .propname = "fsps,c1e",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, bi_proc_hot),
+ .propname = "fsps,bi-proc-hot",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pkg_c_state_limit),
+ .propname = "fsps,pkg-c-state-limit",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, c_state_auto_demotion),
+ .propname = "fsps,c-state-auto-demotion",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, c_state_un_demotion),
+ .propname = "fsps,c-state-un-demotion",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, max_core_c_state),
+ .propname = "fsps,max-core-c-state",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pkg_c_state_demotion),
+ .propname = "fsps,pkg-c-state-demotion",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pkg_c_state_un_demotion),
+ .propname = "fsps,pkg-c-state-un-demotion",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, turbo_mode),
+ .propname = "fsps,turbo-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hda_verb_table_entry_num),
+ .propname = "fsps,hda-verb-table-entry-num",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, hda_verb_table_ptr),
+ .propname = "fsps,hda-verb-table-ptr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, p2sb_unhide),
+ .propname = "fsps,p2sb-unhide",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ipu_en),
+ .propname = "fsps,ipu-en",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ipu_acpi_mode),
+ .propname = "fsps,ipu-acpi-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, force_wake),
+ .propname = "fsps,force-wake",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, gtt_mm_adr),
+ .propname = "fsps,gtt-mm-adr",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, gm_adr),
+ .propname = "fsps,gm-adr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pavp_lock),
+ .propname = "fsps,pavp-lock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, graphics_freq_modify),
+ .propname = "fsps,graphics-freq-modify",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, graphics_freq_req),
+ .propname = "fsps,graphics-freq-req",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, graphics_video_freq),
+ .propname = "fsps,graphics-video-freq",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pm_lock),
+ .propname = "fsps,pm-lock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dop_clock_gating),
+ .propname = "fsps,dop-clock-gating",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, unsolicited_attack_override),
+ .propname = "fsps,unsolicited-attack-override",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, wopcm_support),
+ .propname = "fsps,wopcm-support",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, wopcm_size),
+ .propname = "fsps,wopcm-size",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, power_gating),
+ .propname = "fsps,power-gating",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, unit_level_clock_gating),
+ .propname = "fsps,unit-level-clock-gating",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, fast_boot),
+ .propname = "fsps,fast-boot",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dyn_sr),
+ .propname = "fsps,dyn-sr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sa_ipu_enable),
+ .propname = "fsps,sa-ipu-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pm_support),
+ .propname = "fsps,pm-support",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, enable_render_standby),
+ .propname = "fsps,enable-render-standby",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, logo_size),
+ .propname = "fsps,logo-size",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, logo_ptr),
+ .propname = "fsps,logo-ptr",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, graphics_config_ptr),
+ .propname = "fsps,graphics-config-ptr",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pavp_enable),
+ .propname = "fsps,pavp-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pavp_pr3),
+ .propname = "fsps,pavp-pr3",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, cd_clock),
+ .propname = "fsps,cd-clock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pei_graphics_peim_init),
+ .propname = "fsps,pei-graphics-peim-init",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, write_protection_enable),
+ .propname = "fsps,write-protection-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ write_protection_enable),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, read_protection_enable),
+ .propname = "fsps,read-protection-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ read_protection_enable),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, protected_range_limit),
+ .propname = "fsps,protected-range-limit",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ protected_range_limit),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, protected_range_base),
+ .propname = "fsps,protected-range-base",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ protected_range_base),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, gmm),
+ .propname = "fsps,gmm",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_pgcb_clk_trunk),
+ .propname = "fsps,clk-gating-pgcb-clk-trunk",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_sb),
+ .propname = "fsps,clk-gating-sb",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_sb_clk_trunk),
+ .propname = "fsps,clk-gating-sb-clk-trunk",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_sb_clk_partition),
+ .propname = "fsps,clk-gating-sb-clk-partition",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_core),
+ .propname = "fsps,clk-gating-core",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_dma),
+ .propname = "fsps,clk-gating-dma",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_reg_access),
+ .propname = "fsps,clk-gating-reg-access",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_host),
+ .propname = "fsps,clk-gating-host",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_partition),
+ .propname = "fsps,clk-gating-partition",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, clk_gating_trunk),
+ .propname = "fsps,clk-gating-trunk",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hda_enable),
+ .propname = "fsps,hda-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dsp_enable),
+ .propname = "fsps,dsp-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pme),
+ .propname = "fsps,pme",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_io_buffer_ownership),
+ .propname = "fsps,hd-audio-io-buffer-ownership",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_io_buffer_voltage),
+ .propname = "fsps,hd-audio-io-buffer-voltage",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_vc_type),
+ .propname = "fsps,hd-audio-vc-type",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_link_frequency),
+ .propname = "fsps,hd-audio-link-frequency",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_i_disp_link_frequency),
+ .propname = "fsps,hd-audio-i-disp-link-frequency",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_i_disp_link_tmode),
+ .propname = "fsps,hd-audio-i-disp-link-tmode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dsp_endpoint_dmic),
+ .propname = "fsps,dsp-endpoint-dmic",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dsp_endpoint_bluetooth),
+ .propname = "fsps,dsp-endpoint-bluetooth",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dsp_endpoint_i2s_skp),
+ .propname = "fsps,dsp-endpoint-i2s-skp",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dsp_endpoint_i2s_hp),
+ .propname = "fsps,dsp-endpoint-i2s-hp",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, audio_ctl_pwr_gate),
+ .propname = "fsps,audio-ctl-pwr-gate",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, audio_dsp_pwr_gate),
+ .propname = "fsps,audio-dsp-pwr-gate",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, mmt),
+ .propname = "fsps,mmt",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hmt),
+ .propname = "fsps,hmt",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_pwr_gate),
+ .propname = "fsps,hd-audio-pwr-gate",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_clk_gate),
+ .propname = "fsps,hd-audio-clk-gate",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, dsp_feature_mask),
+ .propname = "fsps,dsp-feature-mask",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, dsp_pp_module_mask),
+ .propname = "fsps,dsp-pp-module-mask",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, bios_cfg_lock_down),
+ .propname = "fsps,bios-cfg-lock-down",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hpet),
+ .propname = "fsps,hpet",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hpet_bdf_valid),
+ .propname = "fsps,hpet-bdf-valid",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hpet_bus_number),
+ .propname = "fsps,hpet-bus-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hpet_device_number),
+ .propname = "fsps,hpet-device-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hpet_function_number),
+ .propname = "fsps,hpet-function-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_bdf_valid),
+ .propname = "fsps,io-apic-bdf-valid",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_bus_number),
+ .propname = "fsps,io-apic-bus-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_device_number),
+ .propname = "fsps,io-apic-device-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_function_number),
+ .propname = "fsps,io-apic-function-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_entry24_119),
+ .propname = "fsps,io-apic-entry24-119",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_id),
+ .propname = "fsps,io-apic-id",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, io_apic_range_select),
+ .propname = "fsps,io-apic-range-select",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ish_enable),
+ .propname = "fsps,ish-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, bios_interface),
+ .propname = "fsps,bios-interface",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, bios_lock),
+ .propname = "fsps,bios-lock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, spi_eiss),
+ .propname = "fsps,spi-eiss",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, bios_lock_sw_smi_number),
+ .propname = "fsps,bios-lock-sw-smi-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, lpss_s0ix_enable),
+ .propname = "fsps,lpss-s0ix-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c_clk_gate_cfg),
+ .propname = "fsps,i2c-clk-gate-cfg",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, i2c_clk_gate_cfg),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hsuart_clk_gate_cfg),
+ .propname = "fsps,hsuart-clk-gate-cfg",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, hsuart_clk_gate_cfg),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, spi_clk_gate_cfg),
+ .propname = "fsps,spi-clk-gate-cfg",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, spi_clk_gate_cfg),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c0_enable),
+ .propname = "fsps,i2c0-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c1_enable),
+ .propname = "fsps,i2c1-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c2_enable),
+ .propname = "fsps,i2c2-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c3_enable),
+ .propname = "fsps,i2c3-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c4_enable),
+ .propname = "fsps,i2c4-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c5_enable),
+ .propname = "fsps,i2c5-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c6_enable),
+ .propname = "fsps,i2c6-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, i2c7_enable),
+ .propname = "fsps,i2c7-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hsuart0_enable),
+ .propname = "fsps,hsuart0-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hsuart1_enable),
+ .propname = "fsps,hsuart1-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hsuart2_enable),
+ .propname = "fsps,hsuart2-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hsuart3_enable),
+ .propname = "fsps,hsuart3-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, spi0_enable),
+ .propname = "fsps,spi0-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, spi1_enable),
+ .propname = "fsps,spi1-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, spi2_enable),
+ .propname = "fsps,spi2-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, os_dbg_enable),
+ .propname = "fsps,os-dbg-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dci_en),
+ .propname = "fsps,dci-en",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config,
+ uart2_kernel_debug_base_address),
+ .propname = "fsps,uart2-kernel-debug-base-address",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_clock_gating_disabled),
+ .propname = "fsps,pcie-clock-gating-disabled",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_root_port8xh_decode),
+ .propname = "fsps,pcie-root-port8xh-decode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie8xh_decode_port_index),
+ .propname = "fsps,pcie8xh-decode-port-index",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_root_port_peer_memory_write_enable),
+ .propname = "fsps,pcie-root-port-peer-memory-write-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_aspm_sw_smi_number),
+ .propname = "fsps,pcie-aspm-sw-smi-number",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_root_port_en),
+ .propname = "fsps,pcie-root-port-en",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_root_port_en),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_hide),
+ .propname = "fsps,pcie-rp-hide",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_hide),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_slot_implemented),
+ .propname = "fsps,pcie-rp-slot-implemented",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_slot_implemented),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_hot_plug),
+ .propname = "fsps,pcie-rp-hot-plug",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_hot_plug),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_pm_sci),
+ .propname = "fsps,pcie-rp-pm-sci",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_pm_sci),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_ext_sync),
+ .propname = "fsps,pcie-rp-ext-sync",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_ext_sync),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_transmitter_half_swing),
+ .propname = "fsps,pcie-rp-transmitter-half-swing",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_transmitter_half_swing),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_acs_enabled),
+ .propname = "fsps,pcie-rp-acs-enabled",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_acs_enabled),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_clk_req_supported),
+ .propname = "fsps,pcie-rp-clk-req-supported",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_clk_req_supported),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_clk_req_number),
+ .propname = "fsps,pcie-rp-clk-req-number",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_clk_req_number),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_clk_req_detect),
+ .propname = "fsps,pcie-rp-clk-req-detect",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_clk_req_detect),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, advanced_error_reporting),
+ .propname = "fsps,advanced-error-reporting",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ advanced_error_reporting),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pme_interrupt),
+ .propname = "fsps,pme-interrupt",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pme_interrupt),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, unsupported_request_report),
+ .propname = "fsps,unsupported-request-report",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ unsupported_request_report),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, fatal_error_report),
+ .propname = "fsps,fatal-error-report",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, fatal_error_report),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, no_fatal_error_report),
+ .propname = "fsps,no-fatal-error-report",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ no_fatal_error_report),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, correctable_error_report),
+ .propname = "fsps,correctable-error-report",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ correctable_error_report),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ system_error_on_fatal_error),
+ .propname = "fsps,system-error-on-fatal-error",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ system_error_on_fatal_error),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ system_error_on_non_fatal_error),
+ .propname = "fsps,system-error-on-non-fatal-error",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ system_error_on_non_fatal_error),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ system_error_on_correctable_error),
+ .propname = "fsps,system-error-on-correctable-error",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ system_error_on_correctable_error),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_speed),
+ .propname = "fsps,pcie-rp-speed",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_speed),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, physical_slot_number),
+ .propname = "fsps,physical-slot-number",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ physical_slot_number),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_completion_timeout),
+ .propname = "fsps,pcie-rp-completion-timeout",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_completion_timeout),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ptm_enable),
+ .propname = "fsps,ptm-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, ptm_enable),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_aspm),
+ .propname = "fsps,pcie-rp-aspm",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_aspm),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_l1_substates),
+ .propname = "fsps,pcie-rp-l1-substates",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_l1_substates),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_ltr_enable),
+ .propname = "fsps,pcie-rp-ltr-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, pcie_rp_ltr_enable),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_ltr_config_lock),
+ .propname = "fsps,pcie-rp-ltr-config-lock",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_ltr_config_lock),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pme_b0_s5_dis),
+ .propname = "fsps,pme-b0-s5-dis",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pci_clock_run),
+ .propname = "fsps,pci-clock-run",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, timer8254_clk_setting),
+ .propname = "fsps,timer8254-clk-setting",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, enable_sata),
+ .propname = "fsps,enable-sata",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_mode),
+ .propname = "fsps,sata-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_salp_support),
+ .propname = "fsps,sata-salp-support",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_pwr_opt_enable),
+ .propname = "fsps,sata-pwr-opt-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, e_sata_speed_limit),
+ .propname = "fsps,e-sata-speed-limit",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, speed_limit),
+ .propname = "fsps,speed-limit",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_enable),
+ .propname = "fsps,sata-ports-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_enable),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_dev_slp),
+ .propname = "fsps,sata-ports-dev-slp",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_dev_slp),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_hot_plug),
+ .propname = "fsps,sata-ports-hot-plug",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_hot_plug),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_interlock_sw),
+ .propname = "fsps,sata-ports-interlock-sw",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ sata_ports_interlock_sw),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_external),
+ .propname = "fsps,sata-ports-external",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_external),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_spin_up),
+ .propname = "fsps,sata-ports-spin-up",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_spin_up),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_solid_state_drive),
+ .propname = "fsps,sata-ports-solid-state-drive",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ sata_ports_solid_state_drive),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_enable_dito_config),
+ .propname = "fsps,sata-ports-enable-dito-config",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ sata_ports_enable_dito_config),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_dm_val),
+ .propname = "fsps,sata-ports-dm-val",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_dm_val),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, sata_ports_dito_val),
+ .propname = "fsps,sata-ports-dito-val",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, sata_ports_dito_val),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, sub_system_vendor_id),
+ .propname = "fsps,sub-system-vendor-id",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, sub_system_id),
+ .propname = "fsps,sub-system-id",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, crid_settings),
+ .propname = "fsps,crid-settings",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, reset_select),
+ .propname = "fsps,reset-select",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sdcard_enabled),
+ .propname = "fsps,sdcard-enabled",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, e_mmc_enabled),
+ .propname = "fsps,emmc-enabled",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, e_mmc_host_max_speed),
+ .propname = "fsps,emmc-host-max-speed",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ufs_enabled),
+ .propname = "fsps,ufs-enabled",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sdio_enabled),
+ .propname = "fsps,sdio-enabled",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, gpp_lock),
+ .propname = "fsps,gpp-lock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sirq_enable),
+ .propname = "fsps,sirq-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sirq_mode),
+ .propname = "fsps,sirq-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, start_frame_pulse),
+ .propname = "fsps,start-frame-pulse",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, smbus_enable),
+ .propname = "fsps,smbus-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, arp_enable),
+ .propname = "fsps,arp-enable",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, num_rsvd_smbus_addresses),
+ .propname = "fsps,num-rsvd-smbus-addresses",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, rsvd_smbus_address_table),
+ .propname = "fsps,rsvd-smbus-address-table",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ rsvd_smbus_address_table),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, disable_compliance_mode),
+ .propname = "fsps,disable-compliance-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, usb_per_port_ctl),
+ .propname = "fsps,usb-per-port-ctl",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, usb30_mode),
+ .propname = "fsps,usb30-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb20_enable),
+ .propname = "fsps,port-usb20-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, port_usb20_enable),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_us20b_over_current_pin),
+ .propname = "fsps,port-us20b-over-current-pin",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_us20b_over_current_pin),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, usb_otg),
+ .propname = "fsps,usb-otg",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hsic_support_enable),
+ .propname = "fsps,hsic-support-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb30_enable),
+ .propname = "fsps,port-usb30-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, port_usb30_enable),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_us30b_over_current_pin),
+ .propname = "fsps,port-us30b-over-current-pin",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_us30b_over_current_pin),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ssic_port_enable),
+ .propname = "fsps,ssic-port-enable",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, ssic_port_enable),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, dlane_pwr_gating),
+ .propname = "fsps,dlane-pwr-gating",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, vtd_enable),
+ .propname = "fsps,vtd-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, lock_down_global_smi),
+ .propname = "fsps,lock-down-global-smi",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, reset_wait_timer),
+ .propname = "fsps,reset-wait-timer",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, rtc_lock),
+ .propname = "fsps,rtc-lock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_test_mode),
+ .propname = "fsps,sata-test-mode",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, ssic_rate),
+ .propname = "fsps,ssic-rate",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, ssic_rate),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, dynamic_power_gating),
+ .propname = "fsps,dynamic-power-gating",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_ltr_max_snoop_latency),
+ .propname = "fsps,pcie-rp-ltr-max-snoop-latency",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_ltr_max_snoop_latency),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_snoop_latency_override_mode),
+ .propname = "fsps,pcie-rp-snoop-latency-override-mode",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_snoop_latency_override_mode),
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_snoop_latency_override_value),
+ .propname = "fsps,pcie-rp-snoop-latency-override-value",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_snoop_latency_override_value),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_snoop_latency_override_multiplier),
+ .propname = "fsps,pcie-rp-snoop-latency-override-multiplier",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_snoop_latency_override_multiplier),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, skip_mp_init),
+ .propname = "fsps,skip-mp-init",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dci_auto_detect),
+ .propname = "fsps,dci-auto-detect",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_ltr_max_non_snoop_latency),
+ .propname = "fsps,pcie-rp-ltr-max-non-snoop-latency",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_ltr_max_non_snoop_latency),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_non_snoop_latency_override_mode),
+ .propname = "fsps,pcie-rp-non-snoop-latency-override-mode",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_non_snoop_latency_override_mode),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, tco_timer_halt_lock),
+ .propname = "fsps,tco-timer-halt-lock",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pwr_btn_override_period),
+ .propname = "fsps,pwr-btn-override-period",
+ }, {
+ .type = FSP_UINT16,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_non_snoop_latency_override_value),
+ .propname = "fsps,pcie-rp-non-snoop-latency-override-value",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_non_snoop_latency_override_value),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ pcie_rp_non_snoop_latency_override_multiplier),
+ .propname = "fsps,pcie-rp-non-snoop-latency-override-multiplier",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_non_snoop_latency_override_multiplier),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_slot_power_limit_scale),
+ .propname = "fsps,pcie-rp-slot-power-limit-scale",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_slot_power_limit_scale),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_slot_power_limit_value),
+ .propname = "fsps,pcie-rp-slot-power-limit-value",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_slot_power_limit_value),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, disable_native_power_button),
+ .propname = "fsps,disable-native-power-button",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, power_butter_debounce_mode),
+ .propname = "fsps,power-butter-debounce-mode",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdio_tx_cmd_cntl),
+ .propname = "fsps,sdio-tx-cmd-cntl",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdio_tx_data_cntl1),
+ .propname = "fsps,sdio-tx-data-cntl1",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdio_tx_data_cntl2),
+ .propname = "fsps,sdio-tx-data-cntl2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdio_rx_cmd_data_cntl1),
+ .propname = "fsps,sdio-rx-cmd-data-cntl1",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdio_rx_cmd_data_cntl2),
+ .propname = "fsps,sdio-rx-cmd-data-cntl2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdcard_tx_cmd_cntl),
+ .propname = "fsps,sdcard-tx-cmd-cntl",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdcard_tx_data_cntl1),
+ .propname = "fsps,sdcard-tx-data-cntl1",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdcard_tx_data_cntl2),
+ .propname = "fsps,sdcard-tx-data-cntl2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdcard_rx_cmd_data_cntl1),
+ .propname = "fsps,sdcard-rx-cmd-data-cntl1",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdcard_rx_strobe_cntl),
+ .propname = "fsps,sdcard-rx-strobe-cntl",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, sdcard_rx_cmd_data_cntl2),
+ .propname = "fsps,sdcard-rx-cmd-data-cntl2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_tx_cmd_cntl),
+ .propname = "fsps,emmc-tx-cmd-cntl",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_tx_data_cntl1),
+ .propname = "fsps,emmc-tx-data-cntl1",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_tx_data_cntl2),
+ .propname = "fsps,emmc-tx-data-cntl2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_rx_cmd_data_cntl1),
+ .propname = "fsps,emmc-rx-cmd-data-cntl1",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_rx_strobe_cntl),
+ .propname = "fsps,emmc-rx-strobe-cntl",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_rx_cmd_data_cntl2),
+ .propname = "fsps,emmc-rx-cmd-data-cntl2",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, emmc_master_sw_cntl),
+ .propname = "fsps,emmc-master-sw-cntl",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pcie_rp_selectable_deemphasis),
+ .propname = "fsps,pcie-rp-selectable-deemphasis",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ pcie_rp_selectable_deemphasis),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, monitor_mwait_enable),
+ .propname = "fsps,monitor-mwait-enable",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, hd_audio_dsp_uaa_compliance),
+ .propname = "fsps,hd-audio-dsp-uaa-compliance",
+ }, {
+ .type = FSP_UINT32,
+ .offset = offsetof(struct fsp_s_config, ipc),
+ .propname = "fsps,ipc",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config, ipc),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, sata_ports_disable_dynamic_pg),
+ .propname = "fsps,sata-ports-disable-dynamic-pg",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ sata_ports_disable_dynamic_pg),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, init_s3_cpu),
+ .propname = "fsps,init-s3-cpu",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, skip_punit_init),
+ .propname = "fsps,skip-punit-init",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb20_per_port_tx_pe_half),
+ .propname = "fsps,port-usb20-per-port-tx-pe-half",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_per_port_tx_pe_half),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb20_per_port_pe_txi_set),
+ .propname = "fsps,port-usb20-per-port-pe-txi-set",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_per_port_pe_txi_set),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb20_per_port_txi_set),
+ .propname = "fsps,port-usb20-per-port-txi-set",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_per_port_txi_set),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb20_hs_skew_sel),
+ .propname = "fsps,port-usb20-hs-skew-sel",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_hs_skew_sel),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ port_usb20_i_usb_tx_emphasis_en),
+ .propname = "fsps,port-usb20-i-usb-tx-emphasis-en",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_i_usb_tx_emphasis_en),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config,
+ port_usb20_per_port_rxi_set),
+ .propname = "fsps,port-usb20-per-port-rxi-set",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_per_port_rxi_set),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, port_usb20_hs_npre_drv_sel),
+ .propname = "fsps,port-usb20-hs-npre-drv-sel",
+ .count = ARRAY_SIZE_OF_MEMBER(struct fsp_s_config,
+ port_usb20_hs_npre_drv_sel),
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, os_selection),
+ .propname = "fsps,os-selection",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, dptf_enabled),
+ .propname = "fsps,dptf-enabled",
+ }, {
+ .type = FSP_UINT8,
+ .offset = offsetof(struct fsp_s_config, pwm_enabled),
+ .propname = "fsps,pwm-enabled",
+ }, {
+ .propname = NULL
+ }
+};
+
+int fsp_s_update_config_from_dtb(ofnode node, struct fsp_s_config *cfg)
+{
+ return fsp_update_config_from_dtb(node, (u8 *)cfg, fsp_s_bindings);
+}
+#endif
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/fsp_m.c b/roms/u-boot/arch/x86/cpu/apollolake/fsp_m.c
new file mode 100644
index 000000000..c6be707e4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/fsp_m.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/fsp_bindings.h>
+#include <asm/fsp2/fsp_internal.h>
+#include <dm/uclass-internal.h>
+
+int fspm_update_config(struct udevice *dev, struct fspm_upd *upd)
+{
+ struct fsp_m_config *cfg = &upd->config;
+ struct fspm_arch_upd *arch = &upd->arch;
+ int cache_ret = 0;
+ ofnode node;
+ int ret;
+
+ arch->nvs_buffer_ptr = NULL;
+ cache_ret = prepare_mrc_cache(upd);
+ if (cache_ret && cache_ret != -ENOENT)
+ return log_msg_ret("mrc", cache_ret);
+ arch->stack_base = (void *)(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE -
+ arch->stack_size);
+ arch->boot_loader_tolum_size = 0;
+ arch->boot_mode = cache_ret ? FSP_BOOT_WITH_FULL_CONFIGURATION :
+ FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
+
+ node = dev_ofnode(dev);
+ if (!ofnode_valid(node))
+ return log_msg_ret("node", -ENOENT);
+ node = ofnode_find_subnode(node, "fsp-m");
+ if (!ofnode_valid(node))
+ return log_msg_ret("fspm", -ENOENT);
+
+ ret = fsp_m_update_config_from_dtb(node, cfg);
+ if (ret)
+ return log_msg_ret("dtb", cache_ret);
+
+ return cache_ret;
+}
+
+/*
+ * The FSP-M binary appears to break the SPI controller. It can be fixed by
+ * writing the BAR again, so do that here
+ */
+int fspm_done(struct udevice *dev)
+{
+ struct udevice *spi;
+ int ret;
+
+ /* Don't probe the device, since that reads the BAR */
+ ret = uclass_find_first_device(UCLASS_SPI, &spi);
+ if (ret)
+ return log_msg_ret("SPI", ret);
+ if (!spi)
+ return log_msg_ret("no SPI", -ENODEV);
+
+ dm_pci_write_config32(spi, PCI_BASE_ADDRESS_0,
+ IOMAP_SPI_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/fsp_s.c b/roms/u-boot/arch/x86/cpu/apollolake/fsp_s.c
new file mode 100644
index 000000000..a9b13c0c7
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/fsp_s.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <bootstage.h>
+#include <dm.h>
+#include <init.h>
+#include <irq.h>
+#include <log.h>
+#include <malloc.h>
+#include <p2sb.h>
+#include <acpi/acpi_s3.h>
+#include <asm/global_data.h>
+#include <asm/intel_pinctrl.h>
+#include <asm/io.h>
+#include <asm/intel_regs.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+#include <asm/pci.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/systemagent.h>
+#include <asm/arch/fsp_bindings.h>
+#include <asm/arch/fsp/fsp_configs.h>
+#include <asm/arch/fsp/fsp_s_upd.h>
+#include <dm/uclass-internal.h>
+#include <linux/bitops.h>
+
+#define PCH_P2SB_E0 0xe0
+#define HIDE_BIT BIT(0)
+
+int fsps_update_config(struct udevice *dev, ulong rom_offset,
+ struct fsps_upd *upd)
+{
+ struct fsp_s_config *cfg = &upd->config;
+ ofnode node;
+
+ if (IS_ENABLED(CONFIG_HAVE_VBT)) {
+ void *buf;
+ int ret;
+
+ ret = binman_entry_map(ofnode_null(), "intel-vbt", &buf, NULL);
+ if (ret)
+ return log_msg_ret("Cannot find VBT", ret);
+ if (*(u32 *)buf != VBT_SIGNATURE)
+ return log_msg_ret("VBT signature", -EINVAL);
+
+ /*
+ * Load VBT before devicetree-specific config. This only
+ * supports memory-mapped SPI at present.
+ */
+ cfg->graphics_config_ptr = (ulong)buf;
+ }
+
+ node = dev_read_subnode(dev, "fsp-s");
+ if (!ofnode_valid(node))
+ return log_msg_ret("fsp-s settings", -ENOENT);
+
+ return fsp_s_update_config_from_dtb(node, cfg);
+}
+
+/* Configure package power limits */
+static int set_power_limits(struct udevice *dev)
+{
+ msr_t rapl_msr_reg, limit;
+ u32 power_unit;
+ u32 tdp, min_power, max_power;
+ u32 pl2_val;
+ u32 override_tdp[2];
+ int ret;
+
+ /* Get units */
+ rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU_UNIT);
+ power_unit = 1 << (rapl_msr_reg.lo & 0xf);
+
+ /* Get power defaults for this SKU */
+ rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU);
+ tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK;
+ pl2_val = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
+ min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK;
+ max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
+
+ if (min_power > 0 && tdp < min_power)
+ tdp = min_power;
+
+ if (max_power > 0 && tdp > max_power)
+ tdp = max_power;
+
+ ret = dev_read_u32_array(dev, "tdp-pl-override-mw", override_tdp,
+ ARRAY_SIZE(override_tdp));
+ if (ret)
+ return log_msg_ret("tdp-pl-override-mw", ret);
+
+ /* Set PL1 override value */
+ if (override_tdp[0])
+ tdp = override_tdp[0] * power_unit / 1000;
+
+ /* Set PL2 override value */
+ if (override_tdp[1])
+ pl2_val = override_tdp[1] * power_unit / 1000;
+
+ /* Set long term power limit to TDP */
+ limit.lo = tdp & PKG_POWER_LIMIT_MASK;
+ /* Set PL1 Pkg Power clamp bit */
+ limit.lo |= PKG_POWER_LIMIT_CLAMP;
+
+ limit.lo |= PKG_POWER_LIMIT_EN;
+ limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT &
+ PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT;
+
+ /* Set short term power limit PL2 */
+ limit.hi = pl2_val & PKG_POWER_LIMIT_MASK;
+ limit.hi |= PKG_POWER_LIMIT_EN;
+
+ /* Program package power limits in RAPL MSR */
+ msr_write(MSR_PKG_POWER_LIMIT, limit);
+ log_debug("RAPL PL1 %d.%dW\n", tdp / power_unit,
+ 100 * (tdp % power_unit) / power_unit);
+ log_debug("RAPL PL2 %d.%dW\n", pl2_val / power_unit,
+ 100 * (pl2_val % power_unit) / power_unit);
+
+ /*
+ * Sett RAPL MMIO register for Power limits. RAPL driver is using MSR
+ * instead of MMIO, so disable LIMIT_EN bit for MMIO
+ */
+ writel(limit.lo & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL));
+ writel(limit.hi & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL + 4));
+
+ return 0;
+}
+
+int p2sb_unhide(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_find_first_device(UCLASS_P2SB, &dev);
+ if (ret)
+ return log_msg_ret("p2sb", ret);
+ ret = p2sb_set_hide(dev, false);
+ if (ret)
+ return log_msg_ret("hide", ret);
+
+ return 0;
+}
+
+/* Overwrites the SCI IRQ if another IRQ number is given by device tree */
+static void set_sci_irq(void)
+{
+ /* Skip this for now */
+}
+
+int arch_fsps_preinit(void)
+{
+ struct udevice *itss;
+ int ret;
+
+ if (!ll_boot_init())
+ return 0;
+ ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
+ if (ret)
+ return log_msg_ret("no itss", ret);
+
+ /*
+ * Clear the GPI interrupt status and enable registers. These
+ * registers do not get reset to default state when booting from S5.
+ */
+ ret = pinctrl_gpi_clear_int_cfg();
+ if (ret)
+ return log_msg_ret("gpi_clear", ret);
+
+ return 0;
+}
+
+int arch_fsp_init_r(void)
+{
+ bool s3wake;
+ struct udevice *dev, *itss;
+ int ret;
+
+ if (!ll_boot_init())
+ return 0;
+
+ s3wake = IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) &&
+ gd->arch.prev_sleep_state == ACPI_S3;
+
+ /*
+ * This must be called before any devices are probed. Put any probing
+ * into arch_fsps_preinit() above.
+ *
+ * We don't use CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH here since it will
+ * force PCI to be probed.
+ */
+ ret = fsp_silicon_init(s3wake, false);
+ if (ret)
+ return ret;
+
+ ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
+ if (ret)
+ return log_msg_ret("no itss", ret);
+
+ /*
+ * Restore GPIO IRQ polarities back to previous settings. This was
+ * stored in reserve_arch() - see X86_IRQT_ITSS
+ */
+ irq_restore_polarities(itss);
+
+ /* soc_init() */
+ ret = p2sb_unhide();
+ if (ret)
+ return log_msg_ret("unhide p2sb", ret);
+
+ /* Set RAPL MSR for Package power limits*/
+ ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
+ if (ret)
+ return log_msg_ret("Cannot get northbridge", ret);
+ set_power_limits(dev);
+
+ /*
+ * FSP-S routes SCI to IRQ 9. With the help of this function you can
+ * select another IRQ for SCI.
+ */
+ set_sci_irq();
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/hostbridge.c b/roms/u-boot/arch/x86/cpu/apollolake/hostbridge.c
new file mode 100644
index 000000000..9decab7aa
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/hostbridge.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ * Copyright (C) 2015 - 2017 Intel Corp.
+ * Copyright (C) 2017 - 2019 Siemens AG
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
+ *
+ * Portions from coreboot soc/intel/apollolake/chip.c
+ */
+
+#define LOG_CATEGORY UCLASS_NORTHBRIDGE
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <log.h>
+#include <spl.h>
+#include <tables_csum.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpi_nhlt.h>
+#include <asm/intel_pinctrl.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/acpi.h>
+#include <asm/arch/hostbridge.h>
+#include <asm/arch/systemagent.h>
+#include <dt-bindings/sound/nhlt.h>
+#include <dm/acpi.h>
+
+enum {
+ PCIEXBAR = 0x60,
+ PCIEXBAR_LENGTH_256MB = 0,
+ PCIEXBAR_LENGTH_128MB,
+ PCIEXBAR_LENGTH_64MB,
+
+ PCIEXBAR_PCIEXBAREN = 1 << 0,
+
+ BGSM = 0xb4, /* Base GTT Stolen Memory */
+ TSEG = 0xb8, /* TSEG base */
+ TOLUD = 0xbc,
+};
+
+#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+static const struct nhlt_format_config dmic_1ch_formats[] = {
+ /* 48 KHz 16-bits per sample. */
+ {
+ .num_channels = 1,
+ .sample_freq_khz = 48,
+ .container_bits_per_sample = 16,
+ .valid_bits_per_sample = 16,
+ .settings_file = "dmic-1ch-48khz-16b.dat",
+ },
+};
+
+static const struct nhlt_dmic_array_config dmic_1ch_mic_config = {
+ .tdm_config = {
+ .config_type = NHLT_TDM_MIC_ARRAY,
+ },
+ .array_type = NHLT_MIC_ARRAY_VENDOR_DEFINED,
+};
+
+static const struct nhlt_endp_descriptor dmic_1ch_descriptors[] = {
+ {
+ .link = NHLT_LINK_PDM,
+ .device = NHLT_PDM_DEV,
+ .direction = NHLT_DIR_CAPTURE,
+ .vid = NHLT_VID,
+ .did = NHLT_DID_DMIC,
+ .cfg = &dmic_1ch_mic_config,
+ .cfg_size = sizeof(dmic_1ch_mic_config),
+ .formats = dmic_1ch_formats,
+ .num_formats = ARRAY_SIZE(dmic_1ch_formats),
+ },
+};
+
+static const struct nhlt_format_config dmic_2ch_formats[] = {
+ /* 48 KHz 16-bits per sample. */
+ {
+ .num_channels = 2,
+ .sample_freq_khz = 48,
+ .container_bits_per_sample = 16,
+ .valid_bits_per_sample = 16,
+ .settings_file = "dmic-2ch-48khz-16b.dat",
+ },
+};
+
+static const struct nhlt_dmic_array_config dmic_2ch_mic_config = {
+ .tdm_config = {
+ .config_type = NHLT_TDM_MIC_ARRAY,
+ },
+ .array_type = NHLT_MIC_ARRAY_2CH_SMALL,
+};
+
+static const struct nhlt_endp_descriptor dmic_2ch_descriptors[] = {
+ {
+ .link = NHLT_LINK_PDM,
+ .device = NHLT_PDM_DEV,
+ .direction = NHLT_DIR_CAPTURE,
+ .vid = NHLT_VID,
+ .did = NHLT_DID_DMIC,
+ .cfg = &dmic_2ch_mic_config,
+ .cfg_size = sizeof(dmic_2ch_mic_config),
+ .formats = dmic_2ch_formats,
+ .num_formats = ARRAY_SIZE(dmic_2ch_formats),
+ },
+};
+
+static const struct nhlt_format_config dmic_4ch_formats[] = {
+ /* 48 KHz 16-bits per sample. */
+ {
+ .num_channels = 4,
+ .sample_freq_khz = 48,
+ .container_bits_per_sample = 16,
+ .valid_bits_per_sample = 16,
+ .settings_file = "dmic-4ch-48khz-16b.dat",
+ },
+};
+
+static const struct nhlt_dmic_array_config dmic_4ch_mic_config = {
+ .tdm_config = {
+ .config_type = NHLT_TDM_MIC_ARRAY,
+ },
+ .array_type = NHLT_MIC_ARRAY_4CH_L_SHAPED,
+};
+
+static const struct nhlt_endp_descriptor dmic_4ch_descriptors[] = {
+ {
+ .link = NHLT_LINK_PDM,
+ .device = NHLT_PDM_DEV,
+ .direction = NHLT_DIR_CAPTURE,
+ .vid = NHLT_VID,
+ .did = NHLT_DID_DMIC,
+ .cfg = &dmic_4ch_mic_config,
+ .cfg_size = sizeof(dmic_4ch_mic_config),
+ .formats = dmic_4ch_formats,
+ .num_formats = ARRAY_SIZE(dmic_4ch_formats),
+ },
+};
+#endif
+
+static int apl_hostbridge_early_init_pinctrl(struct udevice *dev)
+{
+ struct apl_hostbridge_plat *plat = dev_get_plat(dev);
+ struct udevice *pinctrl;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_PINCTRL, &pinctrl);
+ if (ret)
+ return log_msg_ret("no hostbridge pinctrl", ret);
+
+ return pinctrl_config_pads(pinctrl, plat->early_pads,
+ plat->early_pads_count);
+}
+
+static int apl_hostbridge_early_init(struct udevice *dev)
+{
+ struct apl_hostbridge_plat *plat = dev_get_plat(dev);
+ u32 region_size;
+ ulong base;
+ u32 reg;
+ int ret;
+
+ /* Set up the MCHBAR */
+ pci_x86_read_config(plat->bdf, MCHBAR, &base, PCI_SIZE_32);
+ base = MCH_BASE_ADDRESS;
+ pci_x86_write_config(plat->bdf, MCHBAR, base | 1, PCI_SIZE_32);
+
+ /*
+ * The PCIEXBAR is assumed to live in the memory mapped IO space under
+ * 4GiB
+ */
+ pci_x86_write_config(plat->bdf, PCIEXBAR + 4, 0, PCI_SIZE_32);
+
+ switch (plat->pciex_region_size >> 20) {
+ default:
+ case 256:
+ region_size = PCIEXBAR_LENGTH_256MB;
+ break;
+ case 128:
+ region_size = PCIEXBAR_LENGTH_128MB;
+ break;
+ case 64:
+ region_size = PCIEXBAR_LENGTH_64MB;
+ break;
+ }
+
+ reg = CONFIG_MMCONF_BASE_ADDRESS | (region_size << 1)
+ | PCIEXBAR_PCIEXBAREN;
+ pci_x86_write_config(plat->bdf, PCIEXBAR, reg, PCI_SIZE_32);
+
+ /*
+ * TSEG defines the base of SMM range. BIOS determines the base
+ * of TSEG memory which must be at or below Graphics base of GTT
+ * Stolen memory, hence its better to clear TSEG register early
+ * to avoid power on default non-zero value (if any).
+ */
+ pci_x86_write_config(plat->bdf, TSEG, 0, PCI_SIZE_32);
+
+ ret = apl_hostbridge_early_init_pinctrl(dev);
+ if (ret)
+ return log_msg_ret("pinctrl", ret);
+
+ return 0;
+}
+
+static int apl_hostbridge_of_to_plat(struct udevice *dev)
+{
+ struct apl_hostbridge_plat *plat = dev_get_plat(dev);
+ struct udevice *pinctrl;
+ int ret;
+
+ /*
+ * The host bridge holds the early pad data needed to get through TPL.
+ * This is a small amount of data, enough to fit in TPL, so we keep it
+ * separate from the full pad data, stored in the fsp-s subnode. That
+ * subnode is not present in TPL, to save space.
+ */
+ ret = uclass_first_device_err(UCLASS_PINCTRL, &pinctrl);
+ if (ret)
+ return log_msg_ret("no hostbridge PINCTRL", ret);
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ int root;
+
+ /* Get length of PCI Express Region */
+ plat->pciex_region_size = dev_read_u32_default(dev, "pciex-region-size",
+ 256 << 20);
+
+ root = pci_get_devfn(dev);
+ if (root < 0)
+ return log_msg_ret("Cannot get host-bridge PCI address", root);
+ plat->bdf = root;
+
+ ret = pinctrl_read_pads(pinctrl, dev_ofnode(dev), "early-pads",
+ &plat->early_pads, &plat->early_pads_count);
+ if (ret)
+ return log_msg_ret("early-pads", ret);
+#else
+ struct dtd_intel_apl_hostbridge *dtplat = &plat->dtplat;
+ int size;
+
+ plat->pciex_region_size = dtplat->pciex_region_size;
+ plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
+
+ /* Assume that if everything is 0, it is empty */
+ plat->early_pads = dtplat->early_pads;
+ size = ARRAY_SIZE(dtplat->early_pads);
+ plat->early_pads_count = pinctrl_count_pads(pinctrl, plat->early_pads,
+ size);
+
+#endif
+
+ return 0;
+}
+
+static int apl_hostbridge_probe(struct udevice *dev)
+{
+ if (spl_phase() == PHASE_TPL)
+ return apl_hostbridge_early_init(dev);
+
+ return 0;
+}
+
+static int apl_acpi_hb_get_name(const struct udevice *dev, char *out_name)
+{
+ return acpi_copy_name(out_name, "RHUB");
+}
+
+#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+static int apl_acpi_hb_write_tables(const struct udevice *dev,
+ struct acpi_ctx *ctx)
+{
+ struct acpi_table_header *header;
+ struct acpi_dmar *dmar;
+ u32 val;
+
+ /*
+ * Create DMAR table only if virtualization is enabled. Due to some
+ * constraints on Apollo Lake SoC (some stepping affected), VTD could
+ * not be enabled together with IPU. Doing so will override and disable
+ * VTD while leaving CAPID0_A still reporting that VTD is available.
+ * As in this case FSP will lock VTD to disabled state, we need to make
+ * sure that DMAR table generation only happens when at least DEFVTBAR
+ * is enabled. Otherwise the DMAR header will be generated while the
+ * content of the table will be missing.
+ */
+ dm_pci_read_config32(dev, CAPID0_A, &val);
+ if ((val & VTD_DISABLE) ||
+ !(readl(MCHBAR_REG(DEFVTBAR)) & VTBAR_ENABLED))
+ return 0;
+
+ log_debug("ACPI: * DMAR\n");
+ dmar = (struct acpi_dmar *)ctx->current;
+ header = &dmar->header;
+ acpi_create_dmar(dmar, DMAR_INTR_REMAP);
+ ctx->current += sizeof(struct acpi_dmar);
+ apl_acpi_fill_dmar(ctx);
+
+ /* (Re)calculate length and checksum */
+ header->length = ctx->current - (void *)dmar;
+ header->checksum = table_compute_checksum((void *)dmar, header->length);
+
+ acpi_align(ctx);
+ acpi_add_table(ctx, dmar);
+
+ return 0;
+}
+
+static int apl_acpi_setup_nhlt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct nhlt *nhlt = ctx->nhlt;
+ u32 channels;
+ ofnode node;
+
+ node = ofnode_find_subnode(dev_ofnode(dev), "nhlt");
+ if (ofnode_read_u32(node, "intel,dmic-channels", &channels))
+ return log_msg_ret("channels", -EINVAL);
+ switch (channels) {
+ case 1:
+ return nhlt_add_endpoints(nhlt, dmic_1ch_descriptors,
+ ARRAY_SIZE(dmic_1ch_descriptors));
+ case 2:
+ return nhlt_add_endpoints(nhlt, dmic_2ch_descriptors,
+ ARRAY_SIZE(dmic_2ch_descriptors));
+ case 4:
+ return nhlt_add_endpoints(nhlt, dmic_4ch_descriptors,
+ ARRAY_SIZE(dmic_4ch_descriptors));
+ }
+
+ return log_msg_ret("channels", -EINVAL);
+}
+#endif
+
+static int apl_hostbridge_remove(struct udevice *dev)
+{
+ /*
+ * TODO(sjg@chromium.org): Consider adding code from coreboot's
+ * platform_fsp_notify_status()
+ */
+
+ return 0;
+}
+
+static ulong sa_read_reg(struct udevice *dev, int reg)
+{
+ u32 val;
+
+ /* All regions concerned for have 1 MiB alignment */
+ dm_pci_read_config32(dev, BGSM, &val);
+
+ return ALIGN_DOWN(val, 1 << 20);
+}
+
+ulong sa_get_tolud_base(struct udevice *dev)
+{
+ return sa_read_reg(dev, TOLUD);
+}
+
+ulong sa_get_gsm_base(struct udevice *dev)
+{
+ return sa_read_reg(dev, BGSM);
+}
+
+ulong sa_get_tseg_base(struct udevice *dev)
+{
+ return sa_read_reg(dev, TSEG);
+}
+
+struct acpi_ops apl_hostbridge_acpi_ops = {
+ .get_name = apl_acpi_hb_get_name,
+#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+ .write_tables = apl_acpi_hb_write_tables,
+ .setup_nhlt = apl_acpi_setup_nhlt,
+#endif
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id apl_hostbridge_ids[] = {
+ { .compatible = "intel,apl-hostbridge" },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(intel_apl_hostbridge) = {
+ .name = "intel_apl_hostbridge",
+ .id = UCLASS_NORTHBRIDGE,
+ .of_match = of_match_ptr(apl_hostbridge_ids),
+ .of_to_plat = apl_hostbridge_of_to_plat,
+ .probe = apl_hostbridge_probe,
+ .remove = apl_hostbridge_remove,
+ .plat_auto = sizeof(struct apl_hostbridge_plat),
+ ACPI_OPS_PTR(&apl_hostbridge_acpi_ops)
+ .flags = DM_FLAG_OS_PREPARE,
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/lpc.c b/roms/u-boot/arch/x86/cpu/apollolake/lpc.c
new file mode 100644
index 000000000..e085890d6
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/lpc.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ *
+ * From coreboot Apollo Lake support lpc.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <spl.h>
+#include <acpi/acpi_table.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_acpi.h>
+#include <asm/lpc_common.h>
+#include <asm/pci.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/lpc.h>
+#include <dm/acpi.h>
+#include <linux/log2.h>
+
+void lpc_enable_fixed_io_ranges(uint io_enables)
+{
+ pci_x86_clrset_config(PCH_DEV_LPC, LPC_IO_ENABLES, 0, io_enables,
+ PCI_SIZE_16);
+}
+
+/*
+ * Find the first unused IO window.
+ * Returns -1 if not found, 0 for reg 0x84, 1 for reg 0x88 ...
+ */
+static int find_unused_pmio_window(void)
+{
+ int i;
+ ulong lgir;
+
+ for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) {
+ pci_x86_read_config(PCH_DEV_LPC, LPC_GENERIC_IO_RANGE(i),
+ &lgir, PCI_SIZE_32);
+
+ if (!(lgir & LPC_LGIR_EN))
+ return i;
+ }
+
+ return -1;
+}
+
+int lpc_open_pmio_window(uint base, uint size)
+{
+ int i, lgir_reg_num;
+ u32 lgir_reg_offset, lgir, window_size, alignment;
+ ulong bridged_size, bridge_base;
+ ulong reg;
+
+ log_debug("LPC: Trying to open IO window from %x size %x\n", base,
+ size);
+
+ bridged_size = 0;
+ bridge_base = base;
+
+ while (bridged_size < size) {
+ /* Each IO range register can only open a 256-byte window */
+ window_size = min(size, (uint)LPC_LGIR_MAX_WINDOW_SIZE);
+
+ /* Window size must be a power of two for the AMASK to work */
+ alignment = 1UL << (order_base_2(window_size));
+ window_size = ALIGN(window_size, alignment);
+
+ /* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18] */
+ lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN;
+ lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK;
+
+ /* Skip programming if same range already programmed */
+ for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) {
+ pci_x86_read_config(PCH_DEV_LPC,
+ LPC_GENERIC_IO_RANGE(i), &reg,
+ PCI_SIZE_32);
+ if (lgir == reg)
+ return -EALREADY;
+ }
+
+ lgir_reg_num = find_unused_pmio_window();
+ if (lgir_reg_num < 0) {
+ if (spl_phase() > PHASE_TPL) {
+ log_err("LPC: Cannot open IO window: %lx size %lx\n",
+ bridge_base, size - bridged_size);
+ log_err("No more IO windows\n");
+ }
+ return -ENOSPC;
+ }
+ lgir_reg_offset = LPC_GENERIC_IO_RANGE(lgir_reg_num);
+
+ pci_x86_write_config(PCH_DEV_LPC, lgir_reg_offset, lgir,
+ PCI_SIZE_32);
+
+ log_debug("LPC: Opened IO window LGIR%d: base %lx size %x\n",
+ lgir_reg_num, bridge_base, window_size);
+
+ bridged_size += window_size;
+ bridge_base += window_size;
+ }
+
+ return 0;
+}
+
+void lpc_io_setup_comm_a_b(void)
+{
+ /* ComA Range 3F8h-3FFh [2:0] */
+ u16 com_ranges = LPC_IOD_COMA_RANGE;
+ u16 com_enable = LPC_IOE_COMA_EN;
+
+ /* Setup I/O Decode Range Register for LPC */
+ pci_write_config16(PCH_DEV_LPC, LPC_IO_DECODE, com_ranges);
+ /* Enable ComA and ComB Port */
+ lpc_enable_fixed_io_ranges(com_enable);
+}
+
+static int apl_acpi_lpc_get_name(const struct udevice *dev, char *out_name)
+{
+ return acpi_copy_name(out_name, "LPCB");
+}
+
+struct acpi_ops apl_lpc_acpi_ops = {
+ .get_name = apl_acpi_lpc_get_name,
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+ .write_tables = intel_southbridge_write_acpi_tables,
+#endif
+ .inject_dsdt = southbridge_inject_dsdt,
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id apl_lpc_ids[] = {
+ { .compatible = "intel,apl-lpc" },
+ { }
+};
+#endif
+
+/* All pads are LPC already configured by the hostbridge, so no probing here */
+U_BOOT_DRIVER(intel_apl_lpc) = {
+ .name = "intel_apl_lpc",
+ .id = UCLASS_LPC,
+ .of_match = of_match_ptr(apl_lpc_ids),
+ ACPI_OPS_PTR(&apl_lpc_acpi_ops)
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/pch.c b/roms/u-boot/arch/x86/cpu/apollolake/pch.c
new file mode 100644
index 000000000..39d6ad5ed
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/pch.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pch.h>
+#include <spl.h>
+#include <asm/lpc_common.h>
+
+#define BIOS_CTRL 0xdc
+
+static int apl_set_spi_protect(struct udevice *dev, bool protect)
+{
+ if (spl_phase() == PHASE_SPL)
+ return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
+
+ return 0;
+}
+
+static const struct pch_ops apl_pch_ops = {
+ .set_spi_protect = apl_set_spi_protect,
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id apl_pch_ids[] = {
+ { .compatible = "intel,apl-pch" },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(intel_apl_pch) = {
+ .name = "intel_apl_pch",
+ .id = UCLASS_PCH,
+ .of_match = of_match_ptr(apl_pch_ids),
+ .ops = &apl_pch_ops,
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/pmc.c b/roms/u-boot/arch/x86/cpu/apollolake/pmc.c
new file mode 100644
index 000000000..1d21187c9
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/pmc.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot pmclib.c, pmc.c and pmutil.c
+ */
+
+#define LOG_CATEGORY UCLASS_ACPI_PMC
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <log.h>
+#include <spl.h>
+#include <acpi/acpi_s3.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pmc.h>
+#include <linux/bitops.h>
+#include <power/acpi_pmc.h>
+
+#define GPIO_GPE_CFG 0x1050
+
+/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
+#define PRSTS 0x1000
+#define GEN_PMCON1 0x1020
+#define COLD_BOOT_STS BIT(27)
+#define COLD_RESET_STS BIT(26)
+#define WARM_RESET_STS BIT(25)
+#define GLOBAL_RESET_STS BIT(24)
+#define SRS BIT(20)
+#define MS4V BIT(18)
+#define RPS BIT(2)
+#define GEN_PMCON1_CLR1_BITS (COLD_BOOT_STS | COLD_RESET_STS | \
+ WARM_RESET_STS | GLOBAL_RESET_STS | \
+ SRS | MS4V)
+#define GEN_PMCON2 0x1024
+#define GEN_PMCON3 0x1028
+
+/* Offset of TCO registers from ACPI base I/O address */
+#define TCO_REG_OFFSET 0x60
+#define TCO1_STS 0x64
+#define DMISCI_STS BIT(9)
+#define BOOT_STS BIT(18)
+#define TCO2_STS 0x66
+#define TCO1_CNT 0x68
+#define TCO_LOCK BIT(12)
+#define TCO2_CNT 0x6a
+
+enum {
+ ETR = 0x1048,
+ CF9_LOCK = 1UL << 31,
+ CF9_GLB_RST = 1 << 20,
+};
+
+static int apl_pmc_fill_power_state(struct udevice *dev)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+ upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS);
+ upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS);
+
+ upriv->prsts = readl(upriv->pmc_bar0 + PRSTS);
+ upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1);
+ upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2);
+ upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3);
+
+ return 0;
+}
+
+static int apl_prev_sleep_state(struct udevice *dev, int prev_sleep_state)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+ /* WAK_STS bit will not be set when waking from G3 state */
+ if (!(upriv->pm1_sts & WAK_STS) &&
+ (upriv->gen_pmcon1 & COLD_BOOT_STS))
+ prev_sleep_state = ACPI_S5;
+
+ return prev_sleep_state;
+}
+
+static int apl_disable_tco(struct udevice *dev)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+ pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET);
+
+ return 0;
+}
+
+static int apl_global_reset_set_enable(struct udevice *dev, bool enable)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+ if (enable)
+ setbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
+ else
+ clrbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
+
+ return 0;
+}
+
+int apl_pmc_ofdata_to_uc_plat(struct udevice *dev)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+ struct apl_pmc_plat *plat = dev_get_plat(dev);
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ u32 base[6];
+ int size;
+ int ret;
+
+ ret = dev_read_u32_array(dev, "early-regs", base,
+ ARRAY_SIZE(base));
+ if (ret)
+ return log_msg_ret("Missing/short early-regs", ret);
+ if (spl_phase() == PHASE_TPL) {
+ upriv->pmc_bar0 = (void *)base[0];
+ upriv->pmc_bar2 = (void *)base[2];
+
+ /* Since PCI is not enabled, we must get the BDF manually */
+ plat->bdf = pci_get_devfn(dev);
+ if (plat->bdf < 0)
+ return log_msg_ret("Cannot get PMC PCI address",
+ plat->bdf);
+ }
+ upriv->acpi_base = base[4];
+
+ /* Get the dwX values for pmc gpe settings */
+ size = dev_read_size(dev, "gpe0-dw");
+ if (size < 0)
+ return log_msg_ret("Cannot read gpe0-dm", size);
+ upriv->gpe0_count = size / sizeof(u32);
+ ret = dev_read_u32_array(dev, "gpe0-dw", upriv->gpe0_dw,
+ upriv->gpe0_count);
+ if (ret)
+ return log_msg_ret("Bad gpe0-dw", ret);
+
+ return pmc_ofdata_to_uc_plat(dev);
+#else
+ struct dtd_intel_apl_pmc *dtplat = &plat->dtplat;
+
+ plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
+ upriv->pmc_bar0 = (void *)dtplat->early_regs[0];
+ upriv->pmc_bar2 = (void *)dtplat->early_regs[2];
+ upriv->acpi_base = dtplat->early_regs[4];
+ upriv->gpe0_dwx_mask = dtplat->gpe0_dwx_mask;
+ upriv->gpe0_dwx_shift_base = dtplat->gpe0_dwx_shift_base;
+ upriv->gpe0_sts_reg = dtplat->gpe0_sts;
+ upriv->gpe0_sts_reg += upriv->acpi_base;
+ upriv->gpe0_en_reg = dtplat->gpe0_en;
+ upriv->gpe0_en_reg += upriv->acpi_base;
+ upriv->gpe0_count = min((int)ARRAY_SIZE(dtplat->gpe0_dw), GPE0_REG_MAX);
+ memcpy(upriv->gpe0_dw, dtplat->gpe0_dw, sizeof(dtplat->gpe0_dw));
+#endif
+ upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG);
+
+ return 0;
+}
+
+static int enable_pmcbar(struct udevice *dev)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+ struct apl_pmc_plat *priv = dev_get_plat(dev);
+ pci_dev_t pmc = priv->bdf;
+
+ /*
+ * Set PMC base addresses and enable decoding. BARs 1 and 3 are 64-bit
+ * BARs.
+ */
+ pci_x86_write_config(pmc, PCI_BASE_ADDRESS_0, (ulong)upriv->pmc_bar0,
+ PCI_SIZE_32);
+ pci_x86_write_config(pmc, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+ pci_x86_write_config(pmc, PCI_BASE_ADDRESS_2, (ulong)upriv->pmc_bar2,
+ PCI_SIZE_32);
+ pci_x86_write_config(pmc, PCI_BASE_ADDRESS_3, 0, PCI_SIZE_32);
+ pci_x86_write_config(pmc, PCI_BASE_ADDRESS_4, upriv->acpi_base,
+ PCI_SIZE_16);
+ pci_x86_write_config(pmc, PCI_COMMAND, PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
+ PCI_SIZE_16);
+
+ return 0;
+}
+
+static int apl_pmc_probe(struct udevice *dev)
+{
+ if (spl_phase() == PHASE_TPL) {
+ return enable_pmcbar(dev);
+ } else {
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
+
+ upriv->pmc_bar0 = (void *)dm_pci_read_bar32(dev, 0);
+ upriv->pmc_bar2 = (void *)dm_pci_read_bar32(dev, 2);
+ }
+
+ return 0;
+}
+
+static const struct acpi_pmc_ops apl_pmc_ops = {
+ .init = apl_pmc_fill_power_state,
+ .prev_sleep_state = apl_prev_sleep_state,
+ .disable_tco = apl_disable_tco,
+ .global_reset_set_enable = apl_global_reset_set_enable,
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id apl_pmc_ids[] = {
+ { .compatible = "intel,apl-pmc" },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(intel_apl_pmc) = {
+ .name = "intel_apl_pmc",
+ .id = UCLASS_ACPI_PMC,
+ .of_match = of_match_ptr(apl_pmc_ids),
+ .of_to_plat = apl_pmc_ofdata_to_uc_plat,
+ .probe = apl_pmc_probe,
+ .ops = &apl_pmc_ops,
+ .plat_auto = sizeof(struct apl_pmc_plat),
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/punit.c b/roms/u-boot/arch/x86/cpu/apollolake/punit.c
new file mode 100644
index 000000000..5ed796357
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/punit.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <spl.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/systemagent.h>
+#include <linux/delay.h>
+
+/*
+ * Punit Initialisation code. This all isn't documented, but
+ * this is the recipe.
+ */
+static int punit_init(struct udevice *dev)
+{
+ struct udevice *cpu;
+ u32 reg;
+ ulong start;
+ int ret;
+
+ /* Thermal throttle activation offset */
+ ret = uclass_first_device_err(UCLASS_CPU, &cpu);
+ if (ret)
+ return log_msg_ret("Cannot find CPU", ret);
+ cpu_configure_thermal_target(cpu);
+
+ /*
+ * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
+ * Enable all cores here.
+ */
+ writel(0, MCHBAR_REG(CORE_DISABLE_MASK));
+
+ /* P-Unit bring up */
+ reg = readl(MCHBAR_REG(BIOS_RESET_CPL));
+ if (reg == 0xffffffff) {
+ /* P-unit not found */
+ debug("Punit MMIO not available\n");
+ return -ENOENT;
+ }
+
+ /* Set Punit interrupt pin IPIN offset 3D */
+ dm_pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x2);
+
+ /* Set PUINT IRQ to 24 and INTPIN LOCK */
+ writel(PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
+ PUINT_THERMAL_DEVICE_IRQ_LOCK,
+ MCHBAR_REG(PUNIT_THERMAL_DEVICE_IRQ));
+
+ /* Stage0 BIOS Reset Complete (RST_CPL) */
+ enable_bios_reset_cpl();
+
+ /*
+ * Poll for bit 8 to check if PCODE has completed its action in response
+ * to BIOS Reset complete. We wait here till 1 ms for the bit to get
+ * set.
+ */
+ start = get_timer(0);
+ while (!(readl(MCHBAR_REG(BIOS_RESET_CPL)) & PCODE_INIT_DONE)) {
+ if (get_timer(start) > 1) {
+ debug("PCODE Init Done timeout\n");
+ return -ETIMEDOUT;
+ }
+ udelay(100);
+ }
+ debug("PUNIT init complete\n");
+
+ return 0;
+}
+
+static int apl_punit_probe(struct udevice *dev)
+{
+ if (spl_phase() == PHASE_SPL)
+ return punit_init(dev);
+
+ return 0;
+}
+
+static const struct udevice_id apl_syscon_ids[] = {
+ { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
+ { }
+};
+
+U_BOOT_DRIVER(intel_apl_punit) = {
+ .name = "intel_apl_punit",
+ .id = UCLASS_SYSCON,
+ .of_match = apl_syscon_ids,
+ .probe = apl_punit_probe,
+ DM_HEADER(<asm/cpu.h>) /* for X86_SYSCON_PUNIT */
+};
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/spl.c b/roms/u-boot/arch/x86/cpu/apollolake/spl.c
new file mode 100644
index 000000000..f2d25734c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/spl.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY LOGC_BOOT
+
+#include <common.h>
+#include <binman_sym.h>
+#include <bootstage.h>
+#include <dm.h>
+#include <image.h>
+#include <log.h>
+#include <malloc.h>
+#include <spi.h>
+#include <spl.h>
+#include <spi_flash.h>
+#include <asm/fast_spi.h>
+#include <asm/spl.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/iomap.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* This reads the next phase from mapped SPI flash */
+static int rom_load_image(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev)
+{
+ ulong spl_pos = spl_get_image_pos();
+ ulong spl_size = spl_get_image_size();
+ struct udevice *dev;
+ ulong map_base;
+ size_t map_size;
+ uint offset;
+ int ret;
+
+ spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
+ spl_image->entry_point = spl_get_image_text_base();
+ spl_image->load_addr = spl_image->entry_point;
+ spl_image->os = IH_OS_U_BOOT;
+ spl_image->name = "U-Boot";
+ log_debug("Reading from mapped SPI %lx, size %lx\n", spl_pos, spl_size);
+
+ if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
+ ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
+ if (ret)
+ return log_msg_ret("spi_flash", ret);
+ if (!dev)
+ return log_msg_ret("spi_flash dev", -ENODEV);
+ ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
+ if (ret)
+ return log_msg_ret("mmap", ret);
+ } else {
+ ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
+ &offset);
+ if (ret)
+ return ret;
+ }
+ spl_pos += map_base & ~0xff000000;
+ log_debug(", base %lx, pos %lx, load %lx\n", map_base, spl_pos,
+ spl_image->load_addr);
+ bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
+ memcpy((void *)spl_image->load_addr, (void *)spl_pos, spl_size);
+ cpu_flush_l1d_to_l2();
+ bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
+
+ return 0;
+}
+SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image);
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)
+
+static int apl_flash_std_read(struct udevice *dev, u32 offset, size_t len,
+ void *buf)
+{
+ struct spi_flash *flash = dev_get_uclass_priv(dev);
+ struct mtd_info *mtd = &flash->mtd;
+ size_t retlen;
+
+ return log_ret(mtd->_read(mtd, offset, len, &retlen, buf));
+}
+
+static int apl_flash_probe(struct udevice *dev)
+{
+ return spi_flash_std_probe(dev);
+}
+
+static const struct dm_spi_flash_ops apl_flash_ops = {
+ .read = apl_flash_std_read,
+};
+
+static const struct udevice_id apl_flash_ids[] = {
+ { .compatible = "jedec,spi-nor" },
+ { }
+};
+
+U_BOOT_DRIVER(winbond_w25q128fw) = {
+ .name = "winbond_w25q128fw",
+ .id = UCLASS_SPI_FLASH,
+ .of_match = apl_flash_ids,
+ .probe = apl_flash_probe,
+ .priv_auto = sizeof(struct spi_nor),
+ .ops = &apl_flash_ops,
+};
+
+/* This uses a SPI flash device to read the next phase */
+static int spl_fast_spi_load_image(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev)
+{
+ ulong spl_pos = spl_get_image_pos();
+ ulong spl_size = spl_get_image_size();
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
+ if (ret)
+ return ret;
+
+ spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
+ spl_image->entry_point = spl_phase() == PHASE_TPL ?
+ CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
+ spl_image->load_addr = spl_image->entry_point;
+ spl_image->os = IH_OS_U_BOOT;
+ spl_image->name = "U-Boot";
+ spl_pos &= ~0xff000000;
+ log_debug("Reading from flash %lx, size %lx\n", spl_pos, spl_size);
+ ret = spi_flash_read_dm(dev, spl_pos, spl_size,
+ (void *)spl_image->load_addr);
+ cpu_flush_l1d_to_l2();
+ if (ret)
+ return ret;
+
+ return 0;
+}
+SPL_LOAD_IMAGE_METHOD("Fast SPI", 1, BOOT_DEVICE_FAST_SPI,
+ spl_fast_spi_load_image);
+
+void board_boot_order(u32 *spl_boot_list)
+{
+ bool use_spi_flash = IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH);
+
+ if (use_spi_flash) {
+ spl_boot_list[0] = BOOT_DEVICE_FAST_SPI;
+ spl_boot_list[1] = BOOT_DEVICE_SPI_MMAP;
+ } else {
+ spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
+ spl_boot_list[1] = BOOT_DEVICE_FAST_SPI;
+ }
+}
+
+#else
+
+void board_boot_order(u32 *spl_boot_list)
+{
+ spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
+}
+#endif
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/systemagent.c b/roms/u-boot/arch/x86/cpu/apollolake/systemagent.c
new file mode 100644
index 000000000..b6bc2ba14
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/systemagent.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ * Take from coreboot project file of the same name
+ */
+
+#include <common.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/arch/systemagent.h>
+
+void enable_bios_reset_cpl(void)
+{
+ /*
+ * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
+ * that BIOS has initialised memory and power management
+ *
+ * The FSP-S does not do this. If we leave this as zero then I believe
+ * the power-aware interrupts don't work in Linux, and CPU 0 always gets
+ * the interrupt.
+ */
+ setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 3);
+}
diff --git a/roms/u-boot/arch/x86/cpu/apollolake/uart.c b/roms/u-boot/arch/x86/cpu/apollolake/uart.c
new file mode 100644
index 000000000..876fa592b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/apollolake/uart.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Special driver to handle of-platdata
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Some code from coreboot lpss.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <malloc.h>
+#include <ns16550.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/lpss.h>
+#include <dm/device-internal.h>
+#include <asm/arch/uart.h>
+
+/* Low-power Subsystem (LPSS) clock register */
+enum {
+ LPSS_CLOCK_CTL_REG = 0x200,
+ LPSS_CNT_CLOCK_EN = 1,
+ LPSS_CNT_CLK_UPDATE = 1U << 31,
+ LPSS_CLOCK_DIV_N_SHIFT = 16,
+ LPSS_CLOCK_DIV_N_MASK = 0x7fff << LPSS_CLOCK_DIV_N_SHIFT,
+ LPSS_CLOCK_DIV_M_SHIFT = 1,
+ LPSS_CLOCK_DIV_M_MASK = 0x7fff << LPSS_CLOCK_DIV_M_SHIFT,
+
+ /* These set the UART input clock speed */
+ LPSS_UART_CLK_M_VAL = 0x25a,
+ LPSS_UART_CLK_N_VAL = 0x7fff,
+};
+
+static void lpss_clk_update(void *regs, u32 clk_m_val, u32 clk_n_val)
+{
+ u32 clk_sel;
+
+ clk_sel = clk_n_val << LPSS_CLOCK_DIV_N_SHIFT |
+ clk_m_val << LPSS_CLOCK_DIV_M_SHIFT;
+ clk_sel |= LPSS_CNT_CLK_UPDATE | LPSS_CNT_CLOCK_EN;
+
+ writel(clk_sel, regs + LPSS_CLOCK_CTL_REG);
+}
+
+static void uart_lpss_init(void *regs)
+{
+ /* Take UART out of reset */
+ lpss_reset_release(regs);
+
+ /* Set M and N divisor inputs and enable clock */
+ lpss_clk_update(regs, LPSS_UART_CLK_M_VAL, LPSS_UART_CLK_N_VAL);
+}
+
+void apl_uart_init(pci_dev_t bdf, ulong base)
+{
+ /* Set UART base address */
+ pci_x86_write_config(bdf, PCI_BASE_ADDRESS_0, base, PCI_SIZE_32);
+
+ /* Enable memory access and bus master */
+ pci_x86_write_config(bdf, PCI_COMMAND, PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER, PCI_SIZE_32);
+
+ uart_lpss_init((void *)base);
+}
+
+/*
+ * This driver uses its own compatible string but almost everything else from
+ * the standard ns16550 driver. This allows us to provide an of-platdata
+ * implementation, since the platdata produced by of-platdata does not match
+ * struct apl_ns16550_plat.
+ *
+ * When running with of-platdata (generally TPL), the platdata is converted to
+ * something that ns16550 expects. When running withoutof-platdata (SPL, U-Boot
+ * proper), we use ns16550's of_to_plat routine.
+ */
+
+static int apl_ns16550_probe(struct udevice *dev)
+{
+ struct apl_ns16550_plat *plat = dev_get_plat(dev);
+
+ if (!CONFIG_IS_ENABLED(PCI))
+ apl_uart_init(plat->ns16550.bdf, plat->ns16550.base);
+
+ return ns16550_serial_probe(dev);
+}
+
+static int apl_ns16550_of_to_plat(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_intel_apl_ns16550 *dtplat;
+ struct apl_ns16550_plat *plat = dev_get_plat(dev);
+ struct ns16550_plat ns;
+
+ /*
+ * The device's plat uses struct apl_ns16550_plat which starts with the
+ * dtd struct, but the ns16550 driver expects it to be struct ns16550.
+ * Set up what that driver expects. Note that this means that the values
+ * cannot be read in this driver when using of-platdata.
+ *
+ * TODO(sjg@chromium.org): Consider having a separate plat pointer for
+ * of-platdata so that it is not necessary to overwrite this.
+ */
+ dtplat = &plat->dtplat;
+ ns.base = dtplat->early_regs[0];
+ ns.reg_width = 1;
+ ns.reg_shift = dtplat->reg_shift;
+ ns.reg_offset = 0;
+ ns.clock = dtplat->clock_frequency;
+ ns.fcr = UART_FCR_DEFVAL;
+ ns.bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
+ memcpy(plat, &ns, sizeof(ns));
+#else
+ int ret;
+
+ ret = ns16550_serial_of_to_plat(dev);
+ if (ret)
+ return ret;
+#endif /* OF_PLATDATA */
+
+ return 0;
+}
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id apl_ns16550_serial_ids[] = {
+ { .compatible = "intel,apl-ns16550" },
+ { },
+};
+#endif
+
+U_BOOT_DRIVER(intel_apl_ns16550) = {
+ .name = "intel_apl_ns16550",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(apl_ns16550_serial_ids),
+ .plat_auto = sizeof(struct apl_ns16550_plat),
+ .priv_auto = sizeof(struct ns16550),
+ .ops = &ns16550_serial_ops,
+ .of_to_plat = apl_ns16550_of_to_plat,
+ .probe = apl_ns16550_probe,
+};
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/Kconfig b/roms/u-boot/arch/x86/cpu/baytrail/Kconfig
new file mode 100644
index 000000000..d2c3473d6
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/Kconfig
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015 Google, Inc
+
+config INTEL_BAYTRAIL
+ bool
+ select HAVE_FSP
+ select ARCH_MISC_INIT
+ select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+ imply HAVE_INTEL_ME
+ imply ENABLE_MRC_CACHE
+ imply AHCI_PCI
+ imply ICH_SPI
+ imply INTEL_ICH6_GPIO
+ imply PINCTRL_ICH6
+ imply MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply SCSI
+ imply SCSI_AHCI
+ imply SPI_FLASH
+ imply SYS_NS16550
+ imply USB
+ imply USB_EHCI_HCD
+ imply USB_XHCI_HCD
+ imply VIDEO_VESA
+
+if INTEL_BAYTRAIL
+config INTERNAL_UART
+ bool "Enable the SoC integrated legacy UART"
+ help
+ There is a legacy UART integrated into the Bay Trail SoC.
+ A maximum baud rate of 115200 bps is supported. For this
+ reason, it is recommended that the UART port be used for
+ debug purposes only, eg: U-Boot console.
+
+config DEBUG_UART
+ bool
+ select DEBUG_UART_BOARD_INIT
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/Makefile b/roms/u-boot/arch/x86/cpu/baytrail/Makefile
new file mode 100644
index 000000000..ce5d6178c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015 Google, Inc
+
+obj-y += cpu.o
+obj-y += early_uart.o
+obj-y += fsp_configs.o
+obj-y += valleyview.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/acpi.c b/roms/u-boot/arch/x86/cpu/baytrail/acpi.c
new file mode 100644
index 000000000..07757b88a
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/acpi.c
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <log.h>
+#include <acpi/acpi_s3.h>
+#include <acpi/acpi_table.h>
+#include <asm/io.h>
+#include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
+#include <asm/arch/iomap.h>
+#include <dm/uclass-internal.h>
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+ void *dsdt)
+{
+ struct acpi_table_header *header = &(fadt->header);
+ u16 pmbase = ACPI_BASE_ADDRESS;
+
+ memset((void *)fadt, 0, sizeof(struct acpi_fadt));
+
+ acpi_fill_header(header, "FACP");
+ header->length = sizeof(struct acpi_fadt);
+ header->revision = 4;
+
+ fadt->firmware_ctrl = (u32)facs;
+ fadt->dsdt = (u32)dsdt;
+ fadt->preferred_pm_profile = ACPI_PM_MOBILE;
+ fadt->sci_int = 9;
+ fadt->smi_cmd = 0;
+ fadt->acpi_enable = 0;
+ fadt->acpi_disable = 0;
+ fadt->s4bios_req = 0;
+ fadt->pstate_cnt = 0;
+ fadt->pm1a_evt_blk = pmbase;
+ fadt->pm1b_evt_blk = 0x0;
+ fadt->pm1a_cnt_blk = pmbase + 0x4;
+ fadt->pm1b_cnt_blk = 0x0;
+ fadt->pm2_cnt_blk = pmbase + 0x50;
+ fadt->pm_tmr_blk = pmbase + 0x8;
+ fadt->gpe0_blk = pmbase + 0x20;
+ fadt->gpe1_blk = 0;
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm2_cnt_len = 1;
+ fadt->pm_tmr_len = 4;
+ fadt->gpe0_blk_len = 8;
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 0;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+ fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+ fadt->flush_size = 0;
+ fadt->flush_stride = 0;
+ fadt->duty_offset = 1;
+ fadt->duty_width = 0;
+ fadt->day_alrm = 0x0d;
+ fadt->mon_alrm = 0x00;
+ fadt->century = 0x00;
+ fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+ fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_RESET_REGISTER |
+ ACPI_FADT_PLATFORM_CLOCK;
+
+ fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->reset_reg.addrl = IO_PORT_RESET;
+ fadt->reset_reg.addrh = 0;
+ fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
+
+ fadt->x_firmware_ctl_l = (u32)facs;
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (u32)dsdt;
+ fadt->x_dsdt_h = 0;
+
+ fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
+ fadt->x_pm1a_evt_blk.bit_offset = 0;
+ fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
+ fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_evt_blk.bit_width = 0;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.access_size = 0;
+ fadt->x_pm1b_evt_blk.addrl = 0x0;
+ fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
+ fadt->x_pm1a_cnt_blk.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+ fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
+ fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_cnt_blk.bit_width = 0;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.access_size = 0;
+ fadt->x_pm1b_cnt_blk.addrl = 0x0;
+ fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
+ fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
+ fadt->x_pm_tmr_blk.bit_offset = 0;
+ fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
+ fadt->x_pm_tmr_blk.addrh = 0x0;
+
+ fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
+ fadt->x_gpe0_blk.addrh = 0x0;
+
+ fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.access_size = 0;
+ fadt->x_gpe1_blk.addrl = 0x0;
+ fadt->x_gpe1_blk.addrh = 0x0;
+
+ header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+ struct udevice *dev;
+ int ret;
+
+ /* at least we have one processor */
+ gnvs->pcnt = 1;
+ /* override the processor count with actual number */
+ ret = uclass_find_first_device(UCLASS_CPU, &dev);
+ if (ret == 0 && dev != NULL) {
+ ret = cpu_get_count(dev);
+ if (ret > 0)
+ gnvs->pcnt = ret;
+ }
+
+ /* determine whether internal uart is on */
+ if (IS_ENABLED(CONFIG_INTERNAL_UART))
+ gnvs->iuart_en = 1;
+ else
+ gnvs->iuart_en = 0;
+
+ return 0;
+}
+
+/*
+ * The following two routines are called at a very early stage, even before
+ * FSP 2nd phase API fsp_init() is called. Registers off ACPI_BASE_ADDRESS
+ * and PMC_BASE_ADDRESS are accessed, so we need make sure the base addresses
+ * of these two blocks are programmed by either U-Boot or FSP.
+ *
+ * It has been verified that 1st phase API (see arch/x86/lib/fsp1/fsp_car.S)
+ * on Intel BayTrail SoC already initializes these two base addresses so
+ * we are safe to access these registers here.
+ */
+
+enum acpi_sleep_state chipset_prev_sleep_state(void)
+{
+ u32 pm1_sts;
+ u32 pm1_cnt;
+ u32 gen_pmcon1;
+ enum acpi_sleep_state prev_sleep_state = ACPI_S0;
+
+ /* Read Power State */
+ pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
+ pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
+ gen_pmcon1 = readl(PMC_BASE_ADDRESS + GEN_PMCON1);
+
+ debug("PM1_STS = 0x%x PM1_CNT = 0x%x GEN_PMCON1 = 0x%x\n",
+ pm1_sts, pm1_cnt, gen_pmcon1);
+
+ if (pm1_sts & WAK_STS)
+ prev_sleep_state = acpi_sleep_from_pm1(pm1_cnt);
+
+ if (gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR))
+ prev_sleep_state = ACPI_S5;
+
+ return prev_sleep_state;
+}
+
+void chipset_clear_sleep_state(void)
+{
+ u32 pm1_cnt;
+
+ pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
+ outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
+}
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/cpu.c b/roms/u-boot/arch/x86/cpu/baytrail/cpu.c
new file mode 100644
index 000000000..309a50a11
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/cpu.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * Based on code from coreboot
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <init.h>
+#include <log.h>
+#include <pci.h>
+#include <asm/cpu.h>
+#include <asm/cpu_x86.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/msr.h>
+#include <asm/turbo.h>
+
+#define BYT_PRV_CLK 0x800
+#define BYT_PRV_CLK_EN (1 << 0)
+#define BYT_PRV_CLK_M_VAL_SHIFT 1
+#define BYT_PRV_CLK_N_VAL_SHIFT 16
+#define BYT_PRV_CLK_UPDATE (1 << 31)
+
+static void hsuart_clock_set(void *base)
+{
+ u32 m, n, reg;
+
+ /*
+ * Configure the BayTrail UART clock for the internal HS UARTs
+ * (PCI devices) to 58982400 Hz
+ */
+ m = 0x2400;
+ n = 0x3d09;
+ reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
+ writel(reg, base + BYT_PRV_CLK);
+ reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
+ writel(reg, base + BYT_PRV_CLK);
+}
+
+/*
+ * Configure the internal clock of both SIO HS-UARTs, if they are enabled
+ * via FSP
+ */
+int arch_cpu_init_dm(void)
+{
+ struct udevice *dev;
+ void *base;
+ int ret;
+ int i;
+
+ /* Loop over the 2 HS-UARTs */
+ for (i = 0; i < 2; i++) {
+ ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1e, 3 + i), &dev);
+ if (!ret) {
+ base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+ PCI_REGION_MEM);
+ hsuart_clock_set(base);
+ }
+ }
+
+ return 0;
+}
+
+static void set_max_freq(void)
+{
+ msr_t perf_ctl;
+ msr_t msr;
+
+ /* Enable speed step */
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ msr.lo |= MISC_ENABLE_ENHANCED_SPEEDSTEP;
+ msr_write(MSR_IA32_MISC_ENABLE, msr);
+
+ /*
+ * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
+ * the PERF_CTL
+ */
+ msr = msr_read(MSR_IACORE_RATIOS);
+ perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
+
+ /*
+ * Set guaranteed vid [22:16] from IACORE_VIDS to bits [7:0] of
+ * the PERF_CTL
+ */
+ msr = msr_read(MSR_IACORE_VIDS);
+ perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
+ perf_ctl.hi = 0;
+
+ msr_write(MSR_IA32_PERF_CTL, perf_ctl);
+}
+
+static int cpu_x86_baytrail_probe(struct udevice *dev)
+{
+ if (!ll_boot_init())
+ return 0;
+ debug("Init BayTrail core\n");
+
+ /*
+ * On BayTrail the turbo disable bit is actually scoped at the
+ * building-block level, not package. For non-BSP cores that are
+ * within a building block, enable turbo. The cores within the BSP's
+ * building block will just see it already enabled and move on.
+ */
+ if (lapicid())
+ turbo_enable();
+
+ /* Dynamic L2 shrink enable and threshold */
+ msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
+
+ /* Disable C1E */
+ msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
+ msr_setbits_64(MSR_POWER_MISC, 0x44);
+
+ /* Set this core to max frequency ratio */
+ set_max_freq();
+
+ return 0;
+}
+
+static unsigned bus_freq(void)
+{
+ msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
+ switch (clk_info.lo & 0x3) {
+ case 0:
+ return 83333333;
+ case 1:
+ return 100000000;
+ case 2:
+ return 133333333;
+ case 3:
+ return 116666666;
+ default:
+ return 0;
+ }
+}
+
+static unsigned long tsc_freq(void)
+{
+ msr_t platform_info;
+ ulong bclk = bus_freq();
+
+ if (!bclk)
+ return 0;
+
+ platform_info = msr_read(MSR_PLATFORM_INFO);
+
+ return bclk * ((platform_info.lo >> 8) & 0xff);
+}
+
+static int baytrail_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ info->cpu_freq = tsc_freq();
+ info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
+
+ return 0;
+}
+
+static int baytrail_get_count(const struct udevice *dev)
+{
+ int ecx = 0;
+
+ /*
+ * Use the algorithm described in Intel 64 and IA-32 Architectures
+ * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
+ * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
+ * of CPUID Extended Topology Leaf.
+ */
+ while (1) {
+ struct cpuid_result leaf_b;
+
+ leaf_b = cpuid_ext(0xb, ecx);
+
+ /*
+ * Bay Trail doesn't have hyperthreading so just determine the
+ * number of cores by from level type (ecx[15:8] == * 2)
+ */
+ if ((leaf_b.ecx & 0xff00) == 0x0200)
+ return leaf_b.ebx & 0xffff;
+
+ ecx++;
+ }
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_x86_baytrail_ops = {
+ .get_desc = cpu_x86_get_desc,
+ .get_info = baytrail_get_info,
+ .get_count = baytrail_get_count,
+ .get_vendor = cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_baytrail_ids[] = {
+ { .compatible = "intel,baytrail-cpu" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
+ .name = "cpu_x86_baytrail",
+ .id = UCLASS_CPU,
+ .of_match = cpu_x86_baytrail_ids,
+ .bind = cpu_x86_bind,
+ .probe = cpu_x86_baytrail_probe,
+ .ops = &cpu_x86_baytrail_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/early_uart.c b/roms/u-boot/arch/x86/cpu/baytrail/early_uart.c
new file mode 100644
index 000000000..08dbd5538
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/early_uart.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+
+#define PCI_DEV_CONFIG(segbus, dev, fn) ( \
+ (((segbus) & 0xfff) << 20) | \
+ (((dev) & 0x1f) << 15) | \
+ (((fn) & 0x07) << 12))
+
+/* Platform Controller Unit */
+#define LPC_DEV 0x1f
+#define LPC_FUNC 0
+
+/* Enable UART */
+#define UART_CONT 0x80
+
+/* SCORE Pad definitions */
+#define UART_RXD_PAD 82
+#define UART_TXD_PAD 83
+
+/* Pad base: PAD_CONF0[n]= PAD_BASE + 16 * n */
+#define GPSCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSCORE)
+
+/* IO Memory */
+#define IO_BASE_ADDRESS 0xfed0c000
+#define IO_BASE_OFFSET_GPSCORE 0x0000
+#define IO_BASE_OFFSET_GPNCORE 0x1000
+#define IO_BASE_OFFSET_GPSSUS 0x2000
+#define IO_BASE_SIZE 0x4000
+
+static inline unsigned int score_pconf0(int pad_num)
+{
+ return GPSCORE_PAD_BASE + pad_num * 16;
+}
+
+static void score_select_func(int pad, int func)
+{
+ uint32_t reg;
+ uint32_t pconf0_addr = score_pconf0(pad);
+
+ reg = readl(pconf0_addr);
+ reg &= ~0x7;
+ reg |= func & 0x7;
+ writel(reg, pconf0_addr);
+}
+
+static void x86_pci_write_config32(int dev, unsigned int where, u32 value)
+{
+ unsigned long addr;
+
+ addr = CONFIG_PCIE_ECAM_BASE | dev | (where & ~3);
+ writel(value, addr);
+}
+
+/* This can be called after memory-mapped PCI is working */
+int setup_internal_uart(int enable)
+{
+ /* Enable or disable the legacy UART hardware */
+ x86_pci_write_config32(PCI_DEV_CONFIG(0, LPC_DEV, LPC_FUNC), UART_CONT,
+ enable);
+
+ /* All done for the disable part, so just return */
+ if (!enable)
+ return 0;
+
+ /*
+ * Set up the pads to the UART function. This allows the signals to
+ * leave the chip
+ */
+ score_select_func(UART_RXD_PAD, 1);
+ score_select_func(UART_TXD_PAD, 1);
+
+ /* TODO(sjg@chromium.org): Call debug_uart_init() */
+
+ return 0;
+}
+
+void board_debug_uart_init(void)
+{
+ setup_internal_uart(1);
+}
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/fsp_configs.c b/roms/u-boot/arch/x86/cpu/baytrail/fsp_configs.c
new file mode 100644
index 000000000..fb3f946c4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/fsp_configs.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2015, Kodak Alaris, Inc
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/fsp1/fsp_support.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * Override the FSP's Azalia configuration data
+ *
+ * @azalia: pointer to be updated to point to a ROM address where Azalia
+ * configuration data is stored
+ */
+__weak void update_fsp_azalia_configs(struct azalia_config **azalia)
+{
+ *azalia = NULL;
+}
+
+/**
+ * Override the FSP's configuration data.
+ * If the device tree does not specify an integer setting, use the default
+ * provided in Intel's Baytrail_FSP_Gold4.tgz release FSP/BayleyBayFsp.bsf file.
+ */
+void fsp_update_configs(struct fsp_config_data *config,
+ struct fspinit_rtbuf *rt_buf)
+{
+ struct upd_region *fsp_upd = &config->fsp_upd;
+ struct memory_down_data *mem;
+ const void *blob = gd->fdt_blob;
+ int node;
+
+ /* Initialize runtime buffer for fsp_init() */
+ rt_buf->common.stack_top = config->common.stack_top - 32;
+ rt_buf->common.boot_mode = config->common.boot_mode;
+ rt_buf->common.upd_data = &config->fsp_upd;
+
+ node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_BAYTRAIL_FSP);
+ if (node < 0) {
+ debug("%s: Cannot find FSP node\n", __func__);
+ return;
+ }
+
+ fsp_upd->mrc_init_tseg_size = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-tseg-size",
+ MRC_INIT_TSEG_SIZE_1MB);
+ fsp_upd->mrc_init_mmio_size = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-mmio-size",
+ MRC_INIT_MMIO_SIZE_2048MB);
+ fsp_upd->mrc_init_spd_addr1 = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-spd-addr1",
+ 0xa0);
+ fsp_upd->mrc_init_spd_addr2 = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-spd-addr2",
+ 0xa2);
+ fsp_upd->emmc_boot_mode = fdtdec_get_int(blob, node,
+ "fsp,emmc-boot-mode",
+ EMMC_BOOT_MODE_EMMC41);
+ fsp_upd->enable_sdio = fdtdec_get_bool(blob, node, "fsp,enable-sdio");
+ fsp_upd->enable_sdcard = fdtdec_get_bool(blob, node,
+ "fsp,enable-sdcard");
+ fsp_upd->enable_hsuart0 = fdtdec_get_bool(blob, node,
+ "fsp,enable-hsuart0");
+ fsp_upd->enable_hsuart1 = fdtdec_get_bool(blob, node,
+ "fsp,enable-hsuart1");
+ fsp_upd->enable_spi = fdtdec_get_bool(blob, node, "fsp,enable-spi");
+ fsp_upd->enable_sata = fdtdec_get_bool(blob, node, "fsp,enable-sata");
+ fsp_upd->sata_mode = fdtdec_get_int(blob, node, "fsp,sata-mode",
+ SATA_MODE_AHCI);
+ fsp_upd->enable_azalia = fdtdec_get_bool(blob, node,
+ "fsp,enable-azalia");
+ if (fsp_upd->enable_azalia)
+ update_fsp_azalia_configs(&fsp_upd->azalia_cfg_ptr);
+ fsp_upd->enable_xhci = fdtdec_get_bool(blob, node, "fsp,enable-xhci");
+ fsp_upd->lpe_mode = fdtdec_get_int(blob, node, "fsp,lpe-mode",
+ LPE_MODE_PCI);
+ fsp_upd->lpss_sio_mode = fdtdec_get_int(blob, node, "fsp,lpss-sio-mode",
+ LPSS_SIO_MODE_PCI);
+ fsp_upd->enable_dma0 = fdtdec_get_bool(blob, node, "fsp,enable-dma0");
+ fsp_upd->enable_dma1 = fdtdec_get_bool(blob, node, "fsp,enable-dma1");
+ fsp_upd->enable_i2_c0 = fdtdec_get_bool(blob, node, "fsp,enable-i2c0");
+ fsp_upd->enable_i2_c1 = fdtdec_get_bool(blob, node, "fsp,enable-i2c1");
+ fsp_upd->enable_i2_c2 = fdtdec_get_bool(blob, node, "fsp,enable-i2c2");
+ fsp_upd->enable_i2_c3 = fdtdec_get_bool(blob, node, "fsp,enable-i2c3");
+ fsp_upd->enable_i2_c4 = fdtdec_get_bool(blob, node, "fsp,enable-i2c4");
+ fsp_upd->enable_i2_c5 = fdtdec_get_bool(blob, node, "fsp,enable-i2c5");
+ fsp_upd->enable_i2_c6 = fdtdec_get_bool(blob, node, "fsp,enable-i2c6");
+ fsp_upd->enable_pwm0 = fdtdec_get_bool(blob, node, "fsp,enable-pwm0");
+ fsp_upd->enable_pwm1 = fdtdec_get_bool(blob, node, "fsp,enable-pwm1");
+ fsp_upd->enable_hsi = fdtdec_get_bool(blob, node, "fsp,enable-hsi");
+ fsp_upd->igd_dvmt50_pre_alloc = fdtdec_get_int(blob, node,
+ "fsp,igd-dvmt50-pre-alloc", IGD_DVMT50_PRE_ALLOC_64MB);
+ fsp_upd->aperture_size = fdtdec_get_int(blob, node, "fsp,aperture-size",
+ APERTURE_SIZE_256MB);
+ fsp_upd->gtt_size = fdtdec_get_int(blob, node, "fsp,gtt-size",
+ GTT_SIZE_2MB);
+ fsp_upd->mrc_debug_msg = fdtdec_get_bool(blob, node,
+ "fsp,mrc-debug-msg");
+ fsp_upd->isp_enable = fdtdec_get_bool(blob, node, "fsp,isp-enable");
+ fsp_upd->scc_mode = fdtdec_get_int(blob, node, "fsp,scc-mode",
+ SCC_MODE_PCI);
+ fsp_upd->igd_render_standby = fdtdec_get_bool(blob, node,
+ "fsp,igd-render-standby");
+ fsp_upd->txe_uma_enable = fdtdec_get_bool(blob, node,
+ "fsp,txe-uma-enable");
+ fsp_upd->os_selection = fdtdec_get_int(blob, node, "fsp,os-selection",
+ OS_SELECTION_LINUX);
+ fsp_upd->emmc45_ddr50_enabled = fdtdec_get_bool(blob, node,
+ "fsp,emmc45-ddr50-enabled");
+ fsp_upd->emmc45_hs200_enabled = fdtdec_get_bool(blob, node,
+ "fsp,emmc45-hs200-enabled");
+ fsp_upd->emmc45_retune_timer_value = fdtdec_get_int(blob, node,
+ "fsp,emmc45-retune-timer-value", 8);
+ fsp_upd->enable_igd = fdtdec_get_bool(blob, node, "fsp,enable-igd");
+
+ mem = &fsp_upd->memory_params;
+ mem->enable_memory_down = fdtdec_get_bool(blob, node,
+ "fsp,enable-memory-down");
+ if (mem->enable_memory_down) {
+ node = fdtdec_next_compatible(blob, node,
+ COMPAT_INTEL_BAYTRAIL_FSP_MDP);
+ if (node < 0) {
+ debug("%s: Cannot find FSP memory-down-params node\n",
+ __func__);
+ } else {
+ mem->dram_speed = fdtdec_get_int(blob, node,
+ "fsp,dram-speed",
+ DRAM_SPEED_1333MTS);
+ mem->dram_type = fdtdec_get_int(blob, node,
+ "fsp,dram-type",
+ DRAM_TYPE_DDR3L);
+ mem->dimm_0_enable = fdtdec_get_bool(blob, node,
+ "fsp,dimm-0-enable");
+ mem->dimm_1_enable = fdtdec_get_bool(blob, node,
+ "fsp,dimm-1-enable");
+ mem->dimm_width = fdtdec_get_int(blob, node,
+ "fsp,dimm-width",
+ DIMM_WIDTH_X8);
+ mem->dimm_density = fdtdec_get_int(blob, node,
+ "fsp,dimm-density",
+ DIMM_DENSITY_2GBIT);
+ mem->dimm_bus_width = fdtdec_get_int(blob, node,
+ "fsp,dimm-bus-width",
+ DIMM_BUS_WIDTH_64BITS);
+ mem->dimm_sides = fdtdec_get_int(blob, node,
+ "fsp,dimm-sides",
+ DIMM_SIDES_1RANKS);
+ mem->dimm_tcl = fdtdec_get_int(blob, node,
+ "fsp,dimm-tcl", 0x09);
+ mem->dimm_trpt_rcd = fdtdec_get_int(blob, node,
+ "fsp,dimm-trpt-rcd", 0x09);
+ mem->dimm_twr = fdtdec_get_int(blob, node,
+ "fsp,dimm-twr", 0x0a);
+ mem->dimm_twtr = fdtdec_get_int(blob, node,
+ "fsp,dimm-twtr", 0x05);
+ mem->dimm_trrd = fdtdec_get_int(blob, node,
+ "fsp,dimm-trrd", 0x04);
+ mem->dimm_trtp = fdtdec_get_int(blob, node,
+ "fsp,dimm-trtp", 0x05);
+ mem->dimm_tfaw = fdtdec_get_int(blob, node,
+ "fsp,dimm-tfaw", 0x14);
+ }
+ }
+}
diff --git a/roms/u-boot/arch/x86/cpu/baytrail/valleyview.c b/roms/u-boot/arch/x86/cpu/baytrail/valleyview.c
new file mode 100644
index 000000000..f73738ce5
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/baytrail/valleyview.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mmc.h>
+#include <pci_ids.h>
+#include <asm/irq.h>
+#include <asm/mrccache.h>
+#include <asm/post.h>
+#include <asm/arch/iomap.h>
+#include <linux/bitops.h>
+
+/* GPIO SUS */
+#define GPIO_SUS_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSSUS)
+#define GPIO_SUS_DFX5_CONF0 0x150
+#define BYT_TRIG_LVL BIT(24)
+#define BYT_TRIG_POS BIT(25)
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
+
+int arch_misc_init(void)
+{
+ if (!ll_boot_init())
+ return 0;
+
+#ifdef CONFIG_ENABLE_MRC_CACHE
+ /*
+ * We intend not to check any return value here, as even MRC cache
+ * is not saved successfully, it is not a severe error that will
+ * prevent system from continuing to boot.
+ */
+ mrccache_save();
+#endif
+
+ /*
+ * For some unknown reason, FSP (gold4) for BayTrail configures
+ * the GPIO DFX5 PAD to enable level interrupt (bit 24 and 25).
+ * This does not cause any issue when Linux kernel runs w/ or w/o
+ * the pinctrl driver for BayTrail. However this causes unstable
+ * S3 resume if the pinctrl driver is included in the kernel build.
+ * As this pin keeps generating interrupts during an S3 resume,
+ * and there is no IRQ requester in the kernel to handle it, the
+ * kernel seems to hang and does not continue resuming.
+ *
+ * Clear the mysterious interrupt bits for this pin.
+ */
+ clrbits_le32(GPIO_SUS_PAD_BASE + GPIO_SUS_DFX5_CONF0,
+ BYT_TRIG_LVL | BYT_TRIG_POS);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/braswell/Kconfig b/roms/u-boot/arch/x86/cpu/braswell/Kconfig
new file mode 100644
index 000000000..2676fe6e1
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/braswell/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+
+config INTEL_BRASWELL
+ bool
+ select HAVE_FSP
+ select ARCH_MISC_INIT
+ select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+ imply HAVE_INTEL_ME
+ imply HAVE_VBT
+ imply ENABLE_MRC_CACHE
+ imply AHCI_PCI
+ imply ICH_SPI
+ imply MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply SCSI
+ imply SCSI_AHCI
+ imply SPI_FLASH
+ imply SYS_NS16550
+ imply USB
+ imply USB_XHCI_HCD
+ imply VIDEO_FSP
+
+if INTEL_BRASWELL
+
+config FSP_ADDR
+ hex
+ default 0xfff20000
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/braswell/Makefile b/roms/u-boot/arch/x86/cpu/braswell/Makefile
new file mode 100644
index 000000000..277f81e6d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/braswell/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+
+obj-y += braswell.o early_uart.o fsp_configs.o
diff --git a/roms/u-boot/arch/x86/cpu/braswell/braswell.c b/roms/u-boot/arch/x86/cpu/braswell/braswell.c
new file mode 100644
index 000000000..334504999
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/braswell/braswell.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/mrccache.h>
+#include <asm/post.h>
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
+
+int arch_misc_init(void)
+{
+#ifdef CONFIG_ENABLE_MRC_CACHE
+ /*
+ * We intend not to check any return value here, as even MRC cache
+ * is not saved successfully, it is not a severe error that will
+ * prevent system from continuing to boot.
+ */
+ mrccache_save();
+#endif
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/braswell/early_uart.c b/roms/u-boot/arch/x86/cpu/braswell/early_uart.c
new file mode 100644
index 000000000..d78c6b0fe
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/braswell/early_uart.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#define PCI_DEV_CONFIG(segbus, dev, fn) ( \
+ (((segbus) & 0xfff) << 20) | \
+ (((dev) & 0x1f) << 15) | \
+ (((fn) & 0x07) << 12))
+
+/* Platform Controller Unit */
+#define LPC_DEV 0x1f
+#define LPC_FUNC 0
+
+/* Enable UART */
+#define UART_CONT 0x80
+
+/* UART PAD definitions */
+#define UART_RXD_COMMUITY 1
+#define UART_TXD_COMMUITY 1
+#define UART_RXD_FAMILY 4
+#define UART_TXD_FAMILY 4
+#define UART_RXD_PAD 2
+#define UART_TXD_PAD 7
+#define UART_RXD_FUNC 3
+#define UART_TXD_FUNC 3
+
+/* IO Memory */
+#define IO_BASE_ADDRESS 0xfed80000
+
+static inline uint32_t gpio_pconf0(int community, int family, int pad)
+{
+ return IO_BASE_ADDRESS + community * 0x8000 + 0x4400 +
+ family * 0x400 + pad * 8;
+}
+
+static void gpio_select_func(int community, int family, int pad, int func)
+{
+ uint32_t pconf0_addr = gpio_pconf0(community, family, pad);
+
+ clrsetbits_le32(pconf0_addr, 0xf << 16, func << 16);
+}
+
+static void x86_pci_write_config32(int dev, unsigned int where, u32 value)
+{
+ unsigned long addr;
+
+ addr = CONFIG_PCIE_ECAM_BASE | dev | (where & ~3);
+ writel(value, addr);
+}
+
+/* This can be called after memory-mapped PCI is working */
+int setup_internal_uart(int enable)
+{
+ /* Enable or disable the legacy UART hardware */
+ x86_pci_write_config32(PCI_DEV_CONFIG(0, LPC_DEV, LPC_FUNC), UART_CONT,
+ enable);
+
+ /* All done for the disable part, so just return */
+ if (!enable)
+ return 0;
+
+ /*
+ * Set up the pads to the UART function. This allows the signals to
+ * leave the chip
+ */
+ gpio_select_func(UART_RXD_COMMUITY, UART_RXD_FAMILY,
+ UART_RXD_PAD, UART_RXD_FUNC);
+ gpio_select_func(UART_TXD_COMMUITY, UART_TXD_FAMILY,
+ UART_TXD_PAD, UART_TXD_FUNC);
+
+ return 0;
+}
+
+void board_debug_uart_init(void)
+{
+ setup_internal_uart(1);
+}
diff --git a/roms/u-boot/arch/x86/cpu/braswell/fsp_configs.c b/roms/u-boot/arch/x86/cpu/braswell/fsp_configs.c
new file mode 100644
index 000000000..243298fd5
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/braswell/fsp_configs.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017, 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;
+
+/**
+ * Override the FSP's Azalia configuration data
+ *
+ * @azalia: pointer to be updated to point to a ROM address where Azalia
+ * configuration data is stored
+ */
+__weak void update_fsp_azalia_configs(struct azalia_config **azalia)
+{
+ *azalia = NULL;
+}
+
+/**
+ * Override the FSP's GPIO configuration data
+ *
+ * @family: pointer to be updated to point to a ROM address where GPIO
+ * family configuration data is stored
+ * @pad: pointer to be updated to point to a ROM address where GPIO
+ * pad configuration data is stored
+ */
+__weak void update_fsp_gpio_configs(struct gpio_family **family,
+ struct gpio_pad **pad)
+{
+ *family = NULL;
+ *pad = NULL;
+}
+
+/**
+ * Override the FSP's configuration data.
+ * If the device tree does not specify an integer setting, use the default
+ * provided in Intel's Braswell release FSP/BraswellFsp.bsf file.
+ */
+void fsp_update_configs(struct fsp_config_data *config,
+ struct fspinit_rtbuf *rt_buf)
+{
+ struct upd_region *fsp_upd = &config->fsp_upd;
+ struct memory_upd *memory_upd = &fsp_upd->memory_upd;
+ struct silicon_upd *silicon_upd = &fsp_upd->silicon_upd;
+ const void *blob = gd->fdt_blob;
+ int node;
+
+ /* Initialize runtime buffer for fsp_init() */
+ rt_buf->common.stack_top = config->common.stack_top - 32;
+ rt_buf->common.boot_mode = config->common.boot_mode;
+ rt_buf->common.upd_data = &config->fsp_upd;
+
+ node = fdt_node_offset_by_compatible(blob, 0, "intel,braswell-fsp");
+ if (node < 0) {
+ debug("%s: Cannot find FSP node\n", __func__);
+ return;
+ }
+
+ node = fdt_node_offset_by_compatible(blob, node,
+ "intel,braswell-fsp-memory");
+ if (node < 0) {
+ debug("%s: Cannot find FSP memory node\n", __func__);
+ return;
+ }
+
+ /* Override memory UPD contents */
+ memory_upd->mrc_init_tseg_size = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-tseg-size", MRC_INIT_TSEG_SIZE_4MB);
+ memory_upd->mrc_init_mmio_size = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-mmio-size", MRC_INIT_MMIO_SIZE_2048MB);
+ memory_upd->mrc_init_spd_addr1 = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-spd-addr1", 0xa0);
+ memory_upd->mrc_init_spd_addr2 = fdtdec_get_int(blob, node,
+ "fsp,mrc-init-spd-addr2", 0xa2);
+ memory_upd->igd_dvmt50_pre_alloc = fdtdec_get_int(blob, node,
+ "fsp,igd-dvmt50-pre-alloc", IGD_DVMT50_PRE_ALLOC_32MB);
+ memory_upd->aperture_size = fdtdec_get_int(blob, node,
+ "fsp,aperture-size", APERTURE_SIZE_256MB);
+ memory_upd->gtt_size = fdtdec_get_int(blob, node,
+ "fsp,gtt-size", GTT_SIZE_1MB);
+ memory_upd->legacy_seg_decode = fdtdec_get_bool(blob, node,
+ "fsp,legacy-seg-decode");
+ memory_upd->enable_dvfs = fdtdec_get_bool(blob, node,
+ "fsp,enable-dvfs");
+ memory_upd->memory_type = fdtdec_get_int(blob, node,
+ "fsp,memory-type", DRAM_TYPE_DDR3);
+ memory_upd->enable_ca_mirror = fdtdec_get_bool(blob, node,
+ "fsp,enable-ca-mirror");
+
+ node = fdt_node_offset_by_compatible(blob, node,
+ "intel,braswell-fsp-silicon");
+ if (node < 0) {
+ debug("%s: Cannot find FSP silicon node\n", __func__);
+ return;
+ }
+
+ /* Override silicon UPD contents */
+ silicon_upd->sdcard_mode = fdtdec_get_int(blob, node,
+ "fsp,sdcard-mode", SDCARD_MODE_PCI);
+ silicon_upd->enable_hsuart0 = fdtdec_get_bool(blob, node,
+ "fsp,enable-hsuart0");
+ silicon_upd->enable_hsuart1 = fdtdec_get_bool(blob, node,
+ "fsp,enable-hsuart1");
+ silicon_upd->enable_azalia = fdtdec_get_bool(blob, node,
+ "fsp,enable-azalia");
+ if (silicon_upd->enable_azalia)
+ update_fsp_azalia_configs(&silicon_upd->azalia_cfg_ptr);
+ silicon_upd->enable_sata = fdtdec_get_bool(blob, node,
+ "fsp,enable-sata");
+ silicon_upd->enable_xhci = fdtdec_get_bool(blob, node,
+ "fsp,enable-xhci");
+ silicon_upd->lpe_mode = fdtdec_get_int(blob, node,
+ "fsp,lpe-mode", LPE_MODE_PCI);
+ silicon_upd->enable_dma0 = fdtdec_get_bool(blob, node,
+ "fsp,enable-dma0");
+ silicon_upd->enable_dma1 = fdtdec_get_bool(blob, node,
+ "fsp,enable-dma1");
+ silicon_upd->enable_i2c0 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c0");
+ silicon_upd->enable_i2c1 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c1");
+ silicon_upd->enable_i2c2 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c2");
+ silicon_upd->enable_i2c3 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c3");
+ silicon_upd->enable_i2c4 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c4");
+ silicon_upd->enable_i2c5 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c5");
+ silicon_upd->enable_i2c6 = fdtdec_get_bool(blob, node,
+ "fsp,enable-i2c6");
+#ifdef CONFIG_HAVE_VBT
+ silicon_upd->graphics_config_ptr = CONFIG_VBT_ADDR;
+#endif
+ update_fsp_gpio_configs(&silicon_upd->gpio_familiy_ptr,
+ &silicon_upd->gpio_pad_ptr);
+ /*
+ * For Braswell B0 stepping, disable_punit_pwr_config must be set to 1
+ * otherwise it just hangs in fsp_init().
+ */
+ if (gd->arch.x86_mask == 2)
+ silicon_upd->disable_punit_pwr_config = 1;
+ silicon_upd->emmc_mode = fdtdec_get_int(blob, node,
+ "fsp,emmc-mode", EMMC_MODE_PCI);
+ silicon_upd->sata_speed = fdtdec_get_int(blob, node,
+ "fsp,sata-speed", SATA_SPEED_GEN3);
+ silicon_upd->pmic_i2c_bus = fdtdec_get_int(blob, node,
+ "fsp,pmic-i2c-bus", 0);
+ silicon_upd->enable_isp = fdtdec_get_bool(blob, node,
+ "fsp,enable-isp");
+ silicon_upd->isp_pci_dev_config = fdtdec_get_int(blob, node,
+ "fsp,isp-pci-dev-config", ISP_PCI_DEV_CONFIG_2);
+ silicon_upd->turbo_mode = fdtdec_get_bool(blob, node,
+ "fsp,turbo-mode");
+ silicon_upd->pnp_settings = fdtdec_get_int(blob, node,
+ "fsp,pnp-settings", PNP_SETTING_POWER_AND_PERF);
+ silicon_upd->sd_detect_chk = fdtdec_get_bool(blob, node,
+ "fsp,sd-detect-chk");
+}
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,
+};
diff --git a/roms/u-boot/arch/x86/cpu/call32.S b/roms/u-boot/arch/x86/cpu/call32.S
new file mode 100644
index 000000000..b28d58a31
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/call32.S
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <asm/msr-index.h>
+#include <asm/processor-flags.h>
+
+ /*
+ * rdi - 32-bit code segment selector
+ * rsi - target address
+ * rdx - table address (0 if none)
+ */
+.code64
+.globl cpu_call32
+cpu_call32:
+ cli
+
+ /* Save table pointer */
+ mov %edx, %ebx
+
+ /*
+ * Debugging option, this outputs characters to the console UART
+ * mov $0x3f8,%edx
+ * mov $'a',%al
+ * out %al,(%dx)
+ */
+
+ pushf
+ push %rdi /* 32-bit code segment */
+ lea compat(%rip), %rax
+ push %rax
+ retfq
+.code32
+compat:
+ /*
+ * We are now in compatibility mode with a default operand size of
+ * 32 bits. First disable paging.
+ */
+ movl %cr0, %eax
+ andl $~X86_CR0_PG, %eax
+ movl %eax, %cr0
+
+ /* Invalidate TLB */
+ xorl %eax, %eax
+ movl %eax, %cr3
+
+ /* Disable Long mode in EFER (Extended Feature Enable Register) */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btr $_EFER_LME, %eax
+ wrmsr
+
+ /* Set up table pointer for _x86boot_start */
+ mov %ebx, %ecx
+
+ /* Jump to the required target */
+ pushl %edi /* 32-bit code segment */
+ pushl %esi /* 32-bit target address */
+ retfl
diff --git a/roms/u-boot/arch/x86/cpu/config.mk b/roms/u-boot/arch/x86/cpu/config.mk
new file mode 100644
index 000000000..d3033b416
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/config.mk
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+
+# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
+LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
+LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
+LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16)
+
+ifdef CONFIG_X86_64
+ifndef CONFIG_SPL_BUILD
+LDSCRIPT = $(srctree)/arch/x86/cpu/u-boot-64.lds
+endif
+endif
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/Kconfig b/roms/u-boot/arch/x86/cpu/coreboot/Kconfig
new file mode 100644
index 000000000..497d6284a
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/Kconfig
@@ -0,0 +1,30 @@
+if TARGET_COREBOOT
+
+config SYS_COREBOOT
+ bool
+ default y
+ imply SYS_NS16550
+ imply SCSI
+ imply SCSI_AHCI
+ imply AHCI_PCI
+ imply MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply USB
+ imply USB_EHCI_HCD
+ imply USB_XHCI_HCD
+ imply USB_STORAGE
+ imply USB_KEYBOARD
+ imply VIDEO_COREBOOT
+ imply E1000
+ imply ETH_DESIGNWARE
+ imply PCH_GBE
+ imply RTL8169
+ imply CMD_CBFS
+ imply FS_CBFS
+ imply CBMEM_CONSOLE
+ imply X86_TSC_READ_BASE
+ select BINMAN if X86_64
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/Makefile b/roms/u-boot/arch/x86/cpu/coreboot/Makefile
new file mode 100644
index 000000000..a6cdb9a14
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/Makefile
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2011 The Chromium OS Authors.
+#
+# (C) Copyright 2008
+# Graeme Russ, graeme.russ@gmail.com.
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+
+ifndef CONFIG_SPL
+obj-y += car.o
+endif
+ifdef CONFIG_SPL_BUILD
+obj-y += coreboot_spl.o
+else
+obj-y += sdram.o
+endif
+obj-y += coreboot.o
+obj-y += timestamp.o
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/car.S b/roms/u-boot/arch/x86/cpu/coreboot/car.S
new file mode 100644
index 000000000..7163b69a4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/car.S
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ */
+
+.section .text
+
+.globl car_init
+car_init:
+ jmp car_init_ret
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/coreboot.c b/roms/u-boot/arch/x86/cpu/coreboot/coreboot.c
new file mode 100644
index 000000000..69cf8f417
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/coreboot.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008
+ * Graeme Russ, graeme.russ@gmail.com.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <usb.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/cb_sysinfo.h>
+#include <asm/arch/timestamp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_cpu_init(void)
+{
+ int ret = get_coreboot_info(&lib_sysinfo);
+ if (ret != 0) {
+ printf("Failed to parse coreboot tables.\n");
+ return ret;
+ }
+
+ timestamp_init();
+
+ return IS_ENABLED(CONFIG_X86_RUN_64BIT) ? x86_cpu_reinit_f() :
+ x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return default_print_cpuinfo();
+}
+
+static void board_final_init(void)
+{
+ /*
+ * Un-cache the ROM so the kernel has one
+ * more MTRR available.
+ *
+ * Coreboot should have assigned this to the
+ * top available variable MTRR.
+ */
+ u8 top_mtrr = (native_read_msr(MTRR_CAP_MSR) & 0xff) - 1;
+ u8 top_type = native_read_msr(MTRR_PHYS_BASE_MSR(top_mtrr)) & 0xff;
+
+ /* Make sure this MTRR is the correct Write-Protected type */
+ if (top_type == MTRR_TYPE_WRPROT) {
+ struct mtrr_state state;
+
+ mtrr_open(&state, true);
+ wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0);
+ wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0);
+ mtrr_close(&state, true);
+ }
+
+ if (!fdtdec_get_config_bool(gd->fdt_blob, "u-boot,no-apm-finalize")) {
+ /*
+ * Issue SMI to coreboot to lock down ME and registers
+ * when allowed via device tree
+ */
+ printf("Finalizing coreboot\n");
+ outb(0xcb, 0xb2);
+ }
+}
+
+int last_stage_init(void)
+{
+ /* start usb so that usb keyboard can be used as input device */
+ if (CONFIG_IS_ENABLED(USB_KEYBOARD))
+ usb_init();
+
+ board_final_init();
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/coreboot_spl.c b/roms/u-boot/arch/x86/cpu/coreboot/coreboot_spl.c
new file mode 100644
index 000000000..36661871e
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/coreboot_spl.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Google LLC
+ */
+
+#include <common.h>
+#include <init.h>
+
+int dram_init(void)
+{
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/sdram.c b/roms/u-boot/arch/x86/cpu/coreboot/sdram.c
new file mode 100644
index 000000000..4a256bad4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/sdram.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010,2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/e820.h>
+#include <asm/cb_sysinfo.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned int install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ return cb_install_e820_map(max_entries, entries);
+}
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary. It
+ * overrides the default implementation found elsewhere which simply picks the
+ * end of ram, wherever that may be. The location of the stack, the relocation
+ * address, and how far U-Boot is moved by relocation are set in the global
+ * data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ uintptr_t dest_addr = 0;
+ int i;
+
+ for (i = 0; i < lib_sysinfo.n_memranges; i++) {
+ struct memrange *memrange = &lib_sysinfo.memrange[i];
+ /* Force U-Boot to relocate to a page aligned address. */
+ uint64_t start = roundup(memrange->base, 1 << 12);
+ uint64_t end = memrange->base + memrange->size;
+
+ /* Ignore non-memory regions. */
+ if (memrange->type != CB_MEM_RAM)
+ continue;
+
+ /* Filter memory over 4GB. */
+ if (end > 0xffffffffULL)
+ end = 0x100000000ULL;
+ /* Skip this region if it's too small. */
+ if (end - start < total_size)
+ continue;
+
+ /* Use this address if it's the largest so far. */
+ if (end > dest_addr)
+ dest_addr = end;
+ }
+
+ /* If no suitable area was found, return an error. */
+ if (!dest_addr)
+ panic("No available memory found for relocation");
+
+ return (ulong)dest_addr;
+}
+
+int dram_init(void)
+{
+ int i;
+ phys_size_t ram_size = 0;
+
+ for (i = 0; i < lib_sysinfo.n_memranges; i++) {
+ struct memrange *memrange = &lib_sysinfo.memrange[i];
+ unsigned long long end = memrange->base + memrange->size;
+
+ if (memrange->type == CB_MEM_RAM && end > ram_size)
+ ram_size += memrange->size;
+ }
+
+ gd->ram_size = ram_size;
+ if (ram_size == 0)
+ return -1;
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ int i, j;
+
+ if (CONFIG_NR_DRAM_BANKS) {
+ for (i = 0, j = 0; i < lib_sysinfo.n_memranges; i++) {
+ struct memrange *memrange = &lib_sysinfo.memrange[i];
+
+ if (memrange->type == CB_MEM_RAM) {
+ gd->bd->bi_dram[j].start = memrange->base;
+ gd->bd->bi_dram[j].size = memrange->size;
+ j++;
+ if (j >= CONFIG_NR_DRAM_BANKS)
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/coreboot/timestamp.c b/roms/u-boot/arch/x86/cpu/coreboot/timestamp.c
new file mode 100644
index 000000000..3ad611a53
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/coreboot/timestamp.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ *
+ * Modified from the coreboot version
+ */
+
+#include <common.h>
+#include <bootstage.h>
+#include <asm/arch/timestamp.h>
+#include <asm/cb_sysinfo.h>
+#include <linux/compiler.h>
+
+static struct timestamp_table *ts_table __section(".data");
+
+void timestamp_init(void)
+{
+ timestamp_add_now(TS_U_BOOT_INITTED);
+}
+
+void timestamp_add(enum timestamp_id id, uint64_t ts_time)
+{
+ struct timestamp_entry *tse;
+
+ if (!ts_table || (ts_table->num_entries == ts_table->max_entries))
+ return;
+
+ tse = &ts_table->entries[ts_table->num_entries++];
+ tse->entry_id = id;
+ tse->entry_stamp = ts_time - ts_table->base_time;
+}
+
+void timestamp_add_now(enum timestamp_id id)
+{
+ timestamp_add(id, rdtsc());
+}
+
+int timestamp_add_to_bootstage(void)
+{
+ uint i;
+
+ if (!ts_table)
+ return -1;
+
+ for (i = 0; i < ts_table->num_entries; i++) {
+ struct timestamp_entry *tse = &ts_table->entries[i];
+ const char *name = NULL;
+
+ switch (tse->entry_id) {
+ case TS_START_ROMSTAGE:
+ name = "start-romstage";
+ break;
+ case TS_BEFORE_INITRAM:
+ name = "before-initram";
+ break;
+ case TS_DEVICE_INITIALIZE:
+ name = "device-initialize";
+ break;
+ case TS_DEVICE_DONE:
+ name = "device-done";
+ break;
+ case TS_SELFBOOT_JUMP:
+ name = "selfboot-jump";
+ break;
+ }
+ if (name) {
+ bootstage_add_record(0, name, BOOTSTAGEF_ALLOC,
+ tse->entry_stamp /
+ get_tbclk_mhz());
+ }
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/cpu.c b/roms/u-boot/arch/x86/cpu/cpu.c
new file mode 100644
index 000000000..9c4edfcbf
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/cpu.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Part of this file is adapted from coreboot
+ * src/arch/x86/lib/cpu.c
+ */
+
+#define LOG_CATEGORY UCLASS_CPU
+
+#include <common.h>
+#include <bootstage.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <init.h>
+#include <irq.h>
+#include <log.h>
+#include <malloc.h>
+#include <syscon.h>
+#include <acpi/acpi_s3.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpi.h>
+#include <asm/control_regs.h>
+#include <asm/coreboot_tables.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/lapic.h>
+#include <asm/microcode.h>
+#include <asm/mp.h>
+#include <asm/mrccache.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include <asm/interrupt.h>
+#include <asm/tables.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_TPL_BUILD
+static const char *const x86_vendor_name[] = {
+ [X86_VENDOR_INTEL] = "Intel",
+ [X86_VENDOR_CYRIX] = "Cyrix",
+ [X86_VENDOR_AMD] = "AMD",
+ [X86_VENDOR_UMC] = "UMC",
+ [X86_VENDOR_NEXGEN] = "NexGen",
+ [X86_VENDOR_CENTAUR] = "Centaur",
+ [X86_VENDOR_RISE] = "Rise",
+ [X86_VENDOR_TRANSMETA] = "Transmeta",
+ [X86_VENDOR_NSC] = "NSC",
+ [X86_VENDOR_SIS] = "SiS",
+};
+#endif
+
+int __weak x86_cleanup_before_linux(void)
+{
+ int ret;
+
+ ret = mp_park_aps();
+ if (ret)
+ return log_msg_ret("park", ret);
+ bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
+ CONFIG_BOOTSTAGE_STASH_SIZE);
+
+ return 0;
+}
+
+int x86_init_cache(void)
+{
+ enable_caches();
+
+ return 0;
+}
+int init_cache(void) __attribute__((weak, alias("x86_init_cache")));
+
+void flush_cache(unsigned long dummy1, unsigned long dummy2)
+{
+ asm("wbinvd\n");
+}
+
+/* Define these functions to allow ehch-hcd to function */
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void dcache_enable(void)
+{
+ enable_caches();
+}
+
+void dcache_disable(void)
+{
+ disable_caches();
+}
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+ return 1;
+}
+
+#ifndef CONFIG_TPL_BUILD
+const char *cpu_vendor_name(int vendor)
+{
+ const char *name;
+ name = "<invalid cpu vendor>";
+ if (vendor < ARRAY_SIZE(x86_vendor_name) &&
+ x86_vendor_name[vendor])
+ name = x86_vendor_name[vendor];
+
+ return name;
+}
+#endif
+
+char *cpu_get_name(char *name)
+{
+ unsigned int *name_as_ints = (unsigned int *)name;
+ struct cpuid_result regs;
+ char *ptr;
+ int i;
+
+ /* This bit adds up to 48 bytes */
+ for (i = 0; i < 3; i++) {
+ regs = cpuid(0x80000002 + i);
+ name_as_ints[i * 4 + 0] = regs.eax;
+ name_as_ints[i * 4 + 1] = regs.ebx;
+ name_as_ints[i * 4 + 2] = regs.ecx;
+ name_as_ints[i * 4 + 3] = regs.edx;
+ }
+ name[CPU_MAX_NAME_LEN - 1] = '\0';
+
+ /* Skip leading spaces. */
+ ptr = name;
+ while (*ptr == ' ')
+ ptr++;
+
+ return ptr;
+}
+
+int default_print_cpuinfo(void)
+{
+ printf("CPU: %s, vendor %s, device %xh\n",
+ cpu_has_64bit() ? "x86_64" : "x86",
+ cpu_vendor_name(gd->arch.x86_vendor), gd->arch.x86_device);
+
+ if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
+ debug("ACPI previous sleep state: %s\n",
+ acpi_ss_string(gd->arch.prev_sleep_state));
+ }
+
+ return 0;
+}
+
+void show_boot_progress(int val)
+{
+ outb(val, POST_PORT);
+}
+
+#if !defined(CONFIG_SYS_COREBOOT) && !defined(CONFIG_EFI_STUB)
+/*
+ * Implement a weak default function for boards that need to do some final init
+ * before the system is ready.
+ */
+__weak void board_final_init(void)
+{
+}
+
+/*
+ * Implement a weak default function for boards that need to do some final
+ * processing before booting the OS.
+ */
+__weak void board_final_cleanup(void)
+{
+}
+
+int last_stage_init(void)
+{
+ struct acpi_fadt __maybe_unused *fadt;
+ int ret;
+
+ board_final_init();
+
+ if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
+ fadt = acpi_find_fadt();
+
+ if (fadt && gd->arch.prev_sleep_state == ACPI_S3)
+ acpi_resume(fadt);
+ }
+
+ ret = write_tables();
+ if (ret) {
+ log_err("Failed to write tables\n");
+ return log_msg_ret("table", ret);
+ }
+
+ if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
+ fadt = acpi_find_fadt();
+
+ /* Don't touch ACPI hardware on HW reduced platforms */
+ if (fadt && !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI)) {
+ /*
+ * Other than waiting for OSPM to request us to switch
+ * to ACPI * mode, do it by ourselves, since SMI will
+ * not be triggered.
+ */
+ enter_acpi_mode(fadt->pm1a_cnt_blk);
+ }
+ }
+
+ /*
+ * TODO(sjg@chromium.org): Move this to bootm_announce_and_cleanup()
+ * once APL FSP-S at 0x200000 does not overlap with the bzimage at
+ * 0x100000.
+ */
+ board_final_cleanup();
+
+ return 0;
+}
+#endif
+
+static int x86_init_cpus(void)
+{
+ if (IS_ENABLED(CONFIG_SMP)) {
+ debug("Init additional CPUs\n");
+ x86_mp_init();
+ } else {
+ struct udevice *dev;
+
+ /*
+ * This causes the cpu-x86 driver to be probed.
+ * We don't check return value here as we want to allow boards
+ * which have not been converted to use cpu uclass driver to
+ * boot.
+ */
+ uclass_first_device(UCLASS_CPU, &dev);
+ }
+
+ return 0;
+}
+
+int cpu_init_r(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ if (!ll_boot_init()) {
+ uclass_first_device(UCLASS_PCI, &dev);
+ return 0;
+ }
+
+ ret = x86_init_cpus();
+ if (ret)
+ return ret;
+
+ /*
+ * Set up the northbridge, PCH and LPC if available. Note that these
+ * may have had some limited pre-relocation init if they were probed
+ * before relocation, but this is post relocation.
+ */
+ uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
+ uclass_first_device(UCLASS_PCH, &dev);
+ uclass_first_device(UCLASS_LPC, &dev);
+
+ /* Set up pin control if available */
+ ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev);
+ debug("%s, pinctrl=%p, ret=%d\n", __func__, dev, ret);
+
+ return 0;
+}
+
+#ifndef CONFIG_EFI_STUB
+int reserve_arch(void)
+{
+ struct udevice *itss;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
+ mrccache_reserve();
+
+ if (IS_ENABLED(CONFIG_SEABIOS))
+ high_table_reserve();
+
+ if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
+ acpi_s3_reserve();
+
+ if (IS_ENABLED(CONFIG_HAVE_FSP)) {
+ /*
+ * Save stack address to CMOS so that at next S3 boot,
+ * we can use it as the stack address for fsp_contiue()
+ */
+ fsp_save_s3_stack();
+ }
+ }
+ ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
+ if (!ret) {
+ /*
+ * Snapshot the current GPIO IRQ polarities. FSP-S is about to
+ * run and will set a default policy that doesn't honour boards'
+ * requirements
+ */
+ irq_snapshot_polarities(itss);
+ }
+
+ return 0;
+}
+#endif
+
+long detect_coreboot_table_at(ulong start, ulong size)
+{
+ u32 *ptr, *end;
+
+ size /= 4;
+ for (ptr = (void *)start, end = ptr + size; ptr < end; ptr += 4) {
+ if (*ptr == 0x4f49424c) /* "LBIO" */
+ return (long)ptr;
+ }
+
+ return -ENOENT;
+}
+
+long locate_coreboot_table(void)
+{
+ long addr;
+
+ /* We look for LBIO in the first 4K of RAM and again at 960KB */
+ addr = detect_coreboot_table_at(0x0, 0x1000);
+ if (addr < 0)
+ addr = detect_coreboot_table_at(0xf0000, 0x1000);
+
+ return addr;
+}
diff --git a/roms/u-boot/arch/x86/cpu/cpu_x86.c b/roms/u-boot/arch/x86/cpu/cpu_x86.c
new file mode 100644
index 000000000..59da41f38
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/cpu_x86.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int cpu_x86_bind(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ struct cpuid_result res;
+
+ plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "intel,apic-id", -1);
+ plat->family = gd->arch.x86;
+ res = cpuid(1);
+ plat->id[0] = res.eax;
+ plat->id[1] = res.edx;
+
+ return 0;
+}
+
+int cpu_x86_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ const char *vendor = cpu_vendor_name(gd->arch.x86_vendor);
+
+ if (size < (strlen(vendor) + 1))
+ return -ENOSPC;
+
+ strcpy(buf, vendor);
+
+ return 0;
+}
+
+int cpu_x86_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ char *ptr;
+
+ if (size < CPU_MAX_NAME_LEN)
+ return -ENOSPC;
+
+ ptr = cpu_get_name(buf);
+ if (ptr != buf)
+ strcpy(buf, ptr);
+
+ return 0;
+}
+
+int cpu_x86_get_count(const struct udevice *dev)
+{
+ int node, cpu;
+ int num = 0;
+
+ node = fdt_path_offset(gd->fdt_blob, "/cpus");
+ if (node < 0)
+ return -ENOENT;
+
+ for (cpu = fdt_first_subnode(gd->fdt_blob, node);
+ cpu >= 0;
+ cpu = fdt_next_subnode(gd->fdt_blob, cpu)) {
+ const char *device_type;
+
+ device_type = fdt_getprop(gd->fdt_blob, cpu,
+ "device_type", NULL);
+ if (!device_type)
+ continue;
+ if (strcmp(device_type, "cpu") == 0)
+ num++;
+ }
+
+ return num;
+}
+
+static const struct cpu_ops cpu_x86_ops = {
+ .get_desc = cpu_x86_get_desc,
+ .get_count = cpu_x86_get_count,
+ .get_vendor = cpu_x86_get_vendor,
+};
+
+static const struct udevice_id cpu_x86_ids[] = {
+ { .compatible = "cpu-x86" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_x86_drv) = {
+ .name = "cpu_x86",
+ .id = UCLASS_CPU,
+ .of_match = cpu_x86_ids,
+ .bind = cpu_x86_bind,
+ .ops = &cpu_x86_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/arch/x86/cpu/efi/Kconfig b/roms/u-boot/arch/x86/cpu/efi/Kconfig
new file mode 100644
index 000000000..e0975d34d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/efi/Kconfig
@@ -0,0 +1,11 @@
+if EFI
+
+config SYS_CAR_ADDR
+ hex
+ default 0x100000
+
+config SYS_CAR_SIZE
+ hex
+ default 0x20000
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/efi/Makefile b/roms/u-boot/arch/x86/cpu/efi/Makefile
new file mode 100644
index 000000000..9716a4ebe
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/efi/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2015 Google, Inc
+
+ifdef CONFIG_EFI_APP
+obj-y += app.o
+obj-y += sdram.o
+endif
+
+ifdef CONFIG_EFI_STUB
+obj-y += car.o
+obj-y += payload.o
+endif
diff --git a/roms/u-boot/arch/x86/cpu/efi/app.c b/roms/u-boot/arch/x86/cpu/efi/app.c
new file mode 100644
index 000000000..f75448978
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/efi/app.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <netdev.h>
+
+int arch_cpu_init(void)
+{
+ return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return default_print_cpuinfo();
+}
+
+void board_final_init(void)
+{
+}
+
+int misc_init_r(void)
+{
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/efi/car.S b/roms/u-boot/arch/x86/cpu/efi/car.S
new file mode 100644
index 000000000..488dcde66
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/efi/car.S
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+.globl car_init
+car_init:
+ jmp car_init_ret
diff --git a/roms/u-boot/arch/x86/cpu/efi/payload.c b/roms/u-boot/arch/x86/cpu/efi/payload.c
new file mode 100644
index 000000000..9a73b768e
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/efi/payload.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <efi.h>
+#include <errno.h>
+#include <init.h>
+#include <log.h>
+#include <usb.h>
+#include <asm/bootparam.h>
+#include <asm/e820.h>
+#include <asm/global_data.h>
+#include <asm/post.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ struct efi_mem_desc *desc, *end;
+ struct efi_entry_memmap *map;
+ int ret, size;
+ uintptr_t dest_addr = 0;
+ struct efi_mem_desc *largest = NULL;
+
+ /*
+ * Find largest area of memory below 4GB. We could
+ * call efi_build_mem_table() for a more accurate picture since it
+ * merges areas together where possible. But that function uses more
+ * pre-relocation memory, and it's not critical that we find the
+ * absolute largest region.
+ */
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ if (ret) {
+ /* We should have stopped in dram_init(), something is wrong */
+ debug("%s: Missing memory map\n", __func__);
+ goto err;
+ }
+
+ end = (struct efi_mem_desc *)((ulong)map + size);
+ desc = map->desc;
+ for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
+ if (desc->type != EFI_CONVENTIONAL_MEMORY ||
+ desc->physical_start >= 1ULL << 32)
+ continue;
+ if (!largest || desc->num_pages > largest->num_pages)
+ largest = desc;
+ }
+
+ /* If no suitable area was found, return an error. */
+ assert(largest);
+ if (!largest || (largest->num_pages << EFI_PAGE_SHIFT) < (2 << 20))
+ goto err;
+
+ dest_addr = largest->physical_start + (largest->num_pages <<
+ EFI_PAGE_SHIFT);
+
+ return (ulong)dest_addr;
+err:
+ panic("No available memory found for relocation");
+ return 0;
+}
+
+int dram_init(void)
+{
+ struct efi_mem_desc *desc, *end;
+ struct efi_entry_memmap *map;
+ int size, ret;
+
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ if (ret) {
+ printf("Cannot find EFI memory map tables, ret=%d\n", ret);
+
+ return -ENODEV;
+ }
+
+ end = (struct efi_mem_desc *)((ulong)map + size);
+ gd->ram_size = 0;
+ desc = map->desc;
+ for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
+ if (desc->type < EFI_MMAP_IO)
+ gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT;
+ }
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ struct efi_mem_desc *desc, *end;
+ struct efi_entry_memmap *map;
+ int ret, size;
+ int num_banks;
+
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ if (ret) {
+ /* We should have stopped in dram_init(), something is wrong */
+ debug("%s: Missing memory map\n", __func__);
+ return -ENXIO;
+ }
+ end = (struct efi_mem_desc *)((ulong)map + size);
+ desc = map->desc;
+ for (num_banks = 0;
+ desc < end && num_banks < CONFIG_NR_DRAM_BANKS;
+ desc = efi_get_next_mem_desc(map, desc)) {
+ /*
+ * We only use conventional memory and ignore
+ * anything less than 1MB.
+ */
+ if (desc->type != EFI_CONVENTIONAL_MEMORY ||
+ (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20)
+ continue;
+ gd->bd->bi_dram[num_banks].start = desc->physical_start;
+ gd->bd->bi_dram[num_banks].size = desc->num_pages <<
+ EFI_PAGE_SHIFT;
+ num_banks++;
+ }
+
+ return 0;
+}
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return default_print_cpuinfo();
+}
+
+/* Find any available tables and copy them to a safe place */
+int reserve_arch(void)
+{
+ struct efi_info_hdr *hdr;
+
+ debug("table=%lx\n", gd->arch.table);
+ if (!gd->arch.table)
+ return 0;
+
+ hdr = (struct efi_info_hdr *)gd->arch.table;
+
+ gd->start_addr_sp -= hdr->total_size;
+ memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size);
+ debug("Stashing EFI table at %lx to %lx, size %x\n",
+ gd->arch.table, gd->start_addr_sp, hdr->total_size);
+ gd->arch.table = gd->start_addr_sp;
+
+ return 0;
+}
+
+int last_stage_init(void)
+{
+ /* start usb so that usb keyboard can be used as input device */
+ if (CONFIG_IS_ENABLED(USB_KEYBOARD))
+ usb_init();
+
+ return 0;
+}
+
+unsigned int install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ struct efi_mem_desc *desc, *end;
+ struct efi_entry_memmap *map;
+ int size, ret;
+ efi_physical_addr_t last_end_addr = 0;
+ struct e820_entry *last_entry = NULL;
+ __u32 e820_type;
+ unsigned int num_entries = 0;
+
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ if (ret) {
+ printf("Cannot find EFI memory map tables, ret=%d\n", ret);
+
+ return -ENODEV;
+ }
+
+ end = (struct efi_mem_desc *)((ulong)map + size);
+ for (desc = map->desc; desc < end;
+ desc = efi_get_next_mem_desc(map, desc)) {
+ if (desc->num_pages == 0)
+ continue;
+
+ switch (desc->type) {
+ case EFI_LOADER_CODE:
+ case EFI_LOADER_DATA:
+ case EFI_BOOT_SERVICES_CODE:
+ case EFI_BOOT_SERVICES_DATA:
+ case EFI_CONVENTIONAL_MEMORY:
+ e820_type = E820_RAM;
+ break;
+
+ case EFI_RESERVED_MEMORY_TYPE:
+ case EFI_RUNTIME_SERVICES_CODE:
+ case EFI_RUNTIME_SERVICES_DATA:
+ case EFI_MMAP_IO:
+ case EFI_MMAP_IO_PORT:
+ case EFI_PAL_CODE:
+ e820_type = E820_RESERVED;
+ break;
+
+ case EFI_ACPI_RECLAIM_MEMORY:
+ e820_type = E820_ACPI;
+ break;
+
+ case EFI_ACPI_MEMORY_NVS:
+ e820_type = E820_NVS;
+ break;
+
+ case EFI_UNUSABLE_MEMORY:
+ e820_type = E820_UNUSABLE;
+ break;
+
+ default:
+ printf("Invalid EFI memory descriptor type (0x%x)!\n",
+ desc->type);
+ continue;
+ }
+
+ if (last_entry != NULL && last_entry->type == e820_type &&
+ desc->physical_start == last_end_addr) {
+ last_entry->size += (desc->num_pages << EFI_PAGE_SHIFT);
+ last_end_addr += (desc->num_pages << EFI_PAGE_SHIFT);
+ } else {
+ if (num_entries >= E820MAX)
+ break;
+
+ entries[num_entries].addr = desc->physical_start;
+ entries[num_entries].size = desc->num_pages;
+ entries[num_entries].size <<= EFI_PAGE_SHIFT;
+ entries[num_entries].type = e820_type;
+ last_entry = &entries[num_entries];
+ last_end_addr = last_entry->addr + last_entry->size;
+ num_entries++;
+ }
+ }
+
+ return num_entries;
+}
+
+void setup_efi_info(struct efi_info *efi_info)
+{
+ struct efi_entry_systable *table;
+ struct efi_entry_memmap *map;
+ char *signature;
+ int size, ret;
+
+ memset(efi_info, 0, sizeof(struct efi_info));
+
+ ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size);
+ if (ret) {
+ printf("Cannot find EFI system table, ret=%d\n", ret);
+ return;
+ }
+ efi_info->efi_systab = (u32)(table->sys_table);
+
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ if (ret) {
+ printf("Cannot find EFI memory map tables, ret=%d\n", ret);
+ return;
+ }
+ efi_info->efi_memdesc_size = map->desc_size;
+ efi_info->efi_memdesc_version = map->version;
+ efi_info->efi_memmap = (u32)(map->desc);
+ efi_info->efi_memmap_size = size - sizeof(struct efi_entry_memmap);
+
+#ifdef CONFIG_EFI_STUB_64BIT
+ efi_info->efi_systab_hi = table->sys_table >> 32;
+ efi_info->efi_memmap_hi = (u64)(u32)(map->desc) >> 32;
+ signature = EFI64_LOADER_SIGNATURE;
+#else
+ signature = EFI32_LOADER_SIGNATURE;
+#endif
+ memcpy(&efi_info->efi_loader_signature, signature, 4);
+}
diff --git a/roms/u-boot/arch/x86/cpu/efi/sdram.c b/roms/u-boot/arch/x86/cpu/efi/sdram.c
new file mode 100644
index 000000000..af65982fd
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/efi/sdram.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <efi.h>
+#include <init.h>
+#include <asm/global_data.h>
+#include <asm/u-boot-x86.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return (ulong)efi_get_ram_base() + gd->ram_size;
+}
+
+int dram_init(void)
+{
+ /* gd->ram_size is set as part of EFI init */
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = efi_get_ram_base();
+ gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE;
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/i386/Makefile b/roms/u-boot/arch/x86/cpu/i386/Makefile
new file mode 100644
index 000000000..18e152074
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/i386/Makefile
@@ -0,0 +1,11 @@
+#
+# (C) Copyright 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+obj-y += call64.o
+obj-y += cpu.o
+ifndef CONFIG_TPL_BUILD
+obj-y += interrupt.o
+endif
+obj-y += setjmp.o
diff --git a/roms/u-boot/arch/x86/cpu/i386/call64.S b/roms/u-boot/arch/x86/cpu/i386/call64.S
new file mode 100644
index 000000000..d81bcc6f8
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/i386/call64.S
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014 Google, Inc
+ * Copyright (C) 1991, 1992, 1993 Linus Torvalds
+ *
+ * Parts of this copied from Linux arch/x86/boot/compressed/head_64.S
+ */
+
+#include <asm/msr-index.h>
+#include <asm/processor-flags.h>
+
+.code32
+.section .text_call64
+.globl cpu_call64
+cpu_call64:
+ /*
+ * cpu_call64(ulong pgtable, ulong setup_base, ulong target)
+ *
+ * eax - pgtable
+ * edx - setup_base
+ * ecx - target
+ */
+ cli
+ push %ecx /* arg2 = target */
+ push %edx /* arg1 = setup_base */
+ mov %eax, %ebx
+
+ /* Load new GDT with the 64bit segments using 32bit descriptor */
+ leal gdt, %eax
+ movl %eax, gdt+2
+ lgdt gdt
+
+ /* Enable PAE mode */
+ movl $(X86_CR4_PAE), %eax
+ movl %eax, %cr4
+
+ /* Enable the boot page tables */
+ leal (%ebx), %eax
+ movl %eax, %cr3
+
+ /* Enable Long mode in EFER (Extended Feature Enable Register) */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btsl $_EFER_LME, %eax
+ wrmsr
+
+ /* After gdt is loaded */
+ xorl %eax, %eax
+ lldt %ax
+ movl $0x20, %eax
+ ltr %ax
+
+ /*
+ * Setup for the jump to 64bit mode
+ *
+ * When the jump is performed we will be in long mode but
+ * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
+ * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
+ * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+ * We place all of the values on our mini stack so lret can
+ * used to perform that far jump. See the gdt below.
+ */
+ pop %esi /* setup_base */
+
+ pushl $0x10
+ leal lret_target, %eax
+ pushl %eax
+
+ /* Enter paged protected Mode, activating Long Mode */
+ movl $(X86_CR0_PG | X86_CR0_PE), %eax
+ movl %eax, %cr0
+
+ /* Jump from 32bit compatibility mode into 64bit mode. */
+ lret
+
+code64:
+lret_target:
+ pop %eax /* target */
+ mov %eax, %eax /* Clear bits 63:32 */
+ jmp *%eax /* Jump to the 64-bit target */
+
+.globl call64_stub_size
+call64_stub_size:
+ .long . - cpu_call64
+
+ .data
+ .align 16
+ .globl gdt64
+gdt64:
+gdt:
+ .word gdt_end - gdt - 1
+ .long gdt /* Fixed up by code above */
+ .word 0
+ .quad 0x0000000000000000 /* NULL descriptor */
+ .quad 0x00af9a000000ffff /* __KERNEL_CS */
+ .quad 0x00cf92000000ffff /* __KERNEL_DS */
+ .quad 0x0080890000000000 /* TS descriptor */
+ .quad 0x0000000000000000 /* TS continued */
+gdt_end:
diff --git a/roms/u-boot/arch/x86/cpu/i386/cpu.c b/roms/u-boot/arch/x86/cpu/i386/cpu.c
new file mode 100644
index 000000000..e59215cc2
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/i386/cpu.c
@@ -0,0 +1,669 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Part of this file is adapted from coreboot
+ * src/arch/x86/lib/cpu.c
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <log.h>
+#include <malloc.h>
+#include <spl.h>
+#include <asm/control_regs.h>
+#include <asm/coreboot_tables.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/processor-flags.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CPUID_FEATURE_PAE BIT(6)
+#define CPUID_FEATURE_PSE36 BIT(17)
+#define CPUID_FEAURE_HTT BIT(28)
+
+/*
+ * Constructor for a conventional segment GDT (or LDT) entry
+ * This is a macro so it can be used in initialisers
+ */
+#define GDT_ENTRY(flags, base, limit) \
+ ((((base) & 0xff000000ULL) << (56-24)) | \
+ (((flags) & 0x0000f0ffULL) << 40) | \
+ (((limit) & 0x000f0000ULL) << (48-16)) | \
+ (((base) & 0x00ffffffULL) << 16) | \
+ (((limit) & 0x0000ffffULL)))
+
+struct gdt_ptr {
+ u16 len;
+ u32 ptr;
+} __packed;
+
+struct cpu_device_id {
+ unsigned vendor;
+ unsigned device;
+};
+
+struct cpuinfo_x86 {
+ uint8_t x86; /* CPU family */
+ uint8_t x86_vendor; /* CPU vendor */
+ uint8_t x86_model;
+ uint8_t x86_mask;
+};
+
+/* gcc 7.3 does not wwant to drop x86_vendors, so use #ifdef */
+#ifndef CONFIG_TPL_BUILD
+/*
+ * List of cpu vendor strings along with their normalized
+ * id values.
+ */
+static const struct {
+ int vendor;
+ const char *name;
+} x86_vendors[] = {
+ { X86_VENDOR_INTEL, "GenuineIntel", },
+ { X86_VENDOR_CYRIX, "CyrixInstead", },
+ { X86_VENDOR_AMD, "AuthenticAMD", },
+ { X86_VENDOR_UMC, "UMC UMC UMC ", },
+ { X86_VENDOR_NEXGEN, "NexGenDriven", },
+ { X86_VENDOR_CENTAUR, "CentaurHauls", },
+ { X86_VENDOR_RISE, "RiseRiseRise", },
+ { X86_VENDOR_TRANSMETA, "GenuineTMx86", },
+ { X86_VENDOR_TRANSMETA, "TransmetaCPU", },
+ { X86_VENDOR_NSC, "Geode by NSC", },
+ { X86_VENDOR_SIS, "SiS SiS SiS ", },
+};
+#endif
+
+static void load_ds(u32 segment)
+{
+ asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_es(u32 segment)
+{
+ asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_fs(u32 segment)
+{
+ asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_gs(u32 segment)
+{
+ asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_ss(u32 segment)
+{
+ asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_gdt(const u64 *boot_gdt, u16 num_entries)
+{
+ struct gdt_ptr gdt;
+
+ gdt.len = (num_entries * X86_GDT_ENTRY_SIZE) - 1;
+ gdt.ptr = (ulong)boot_gdt;
+
+ asm volatile("lgdtl %0\n" : : "m" (gdt));
+}
+
+void arch_setup_gd(gd_t *new_gd)
+{
+ u64 *gdt_addr;
+
+ gdt_addr = new_gd->arch.gdt;
+
+ /*
+ * CS: code, read/execute, 4 GB, base 0
+ *
+ * Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS
+ */
+ gdt_addr[X86_GDT_ENTRY_UNUSED] = GDT_ENTRY(0xc09b, 0, 0xfffff);
+ gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff);
+
+ /* DS: data, read/write, 4 GB, base 0 */
+ gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff);
+
+ /*
+ * FS: data, read/write, sizeof (Global Data Pointer),
+ * base (Global Data Pointer)
+ */
+ new_gd->arch.gd_addr = new_gd;
+ gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0x8093,
+ (ulong)&new_gd->arch.gd_addr,
+ sizeof(new_gd->arch.gd_addr) - 1);
+
+ /* 16-bit CS: code, read/execute, 64 kB, base 0 */
+ gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff);
+
+ /* 16-bit DS: data, read/write, 64 kB, base 0 */
+ gdt_addr[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x0093, 0, 0x0ffff);
+
+ gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff);
+ gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff);
+
+ load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES);
+ load_ds(X86_GDT_ENTRY_32BIT_DS);
+ load_es(X86_GDT_ENTRY_32BIT_DS);
+ load_gs(X86_GDT_ENTRY_32BIT_DS);
+ load_ss(X86_GDT_ENTRY_32BIT_DS);
+ load_fs(X86_GDT_ENTRY_32BIT_FS);
+}
+
+#ifdef CONFIG_HAVE_FSP
+/*
+ * Setup FSP execution environment GDT
+ *
+ * Per Intel FSP external architecture specification, before calling any FSP
+ * APIs, we need make sure the system is in flat 32-bit mode and both the code
+ * and data selectors should have full 4GB access range. Here we reuse the one
+ * we used in arch/x86/cpu/start16.S, and reload the segment registers.
+ */
+void setup_fsp_gdt(void)
+{
+ load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4);
+ load_ds(X86_GDT_ENTRY_32BIT_DS);
+ load_ss(X86_GDT_ENTRY_32BIT_DS);
+ load_es(X86_GDT_ENTRY_32BIT_DS);
+ load_fs(X86_GDT_ENTRY_32BIT_DS);
+ load_gs(X86_GDT_ENTRY_32BIT_DS);
+}
+#endif
+
+/*
+ * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
+ * by the fact that they preserve the flags across the division of 5/2.
+ * PII and PPro exhibit this behavior too, but they have cpuid available.
+ */
+
+/*
+ * Perform the Cyrix 5/2 test. A Cyrix won't change
+ * the flags, while other 486 chips will.
+ */
+static inline int test_cyrix_52div(void)
+{
+ unsigned int test;
+
+ __asm__ __volatile__(
+ "sahf\n\t" /* clear flags (%eax = 0x0005) */
+ "div %b2\n\t" /* divide 5 by 2 */
+ "lahf" /* store flags into %ah */
+ : "=a" (test)
+ : "0" (5), "q" (2)
+ : "cc");
+
+ /* AH is 0x02 on Cyrix after the divide.. */
+ return (unsigned char) (test >> 8) == 0x02;
+}
+
+#ifndef CONFIG_TPL_BUILD
+/*
+ * Detect a NexGen CPU running without BIOS hypercode new enough
+ * to have CPUID. (Thanks to Herbert Oppmann)
+ */
+static int deep_magic_nexgen_probe(void)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ " movw $0x5555, %%ax\n"
+ " xorw %%dx,%%dx\n"
+ " movw $2, %%cx\n"
+ " divw %%cx\n"
+ " movl $0, %%eax\n"
+ " jnz 1f\n"
+ " movl $1, %%eax\n"
+ "1:\n"
+ : "=a" (ret) : : "cx", "dx");
+ return ret;
+}
+#endif
+
+static bool has_cpuid(void)
+{
+ return flag_is_changeable_p(X86_EFLAGS_ID);
+}
+
+static bool has_mtrr(void)
+{
+ return cpuid_edx(0x00000001) & (1 << 12) ? true : false;
+}
+
+#ifndef CONFIG_TPL_BUILD
+static int build_vendor_name(char *vendor_name)
+{
+ struct cpuid_result result;
+ result = cpuid(0x00000000);
+ unsigned int *name_as_ints = (unsigned int *)vendor_name;
+
+ name_as_ints[0] = result.ebx;
+ name_as_ints[1] = result.edx;
+ name_as_ints[2] = result.ecx;
+
+ return result.eax;
+}
+#endif
+
+static void identify_cpu(struct cpu_device_id *cpu)
+{
+ cpu->device = 0; /* fix gcc 4.4.4 warning */
+
+ /*
+ * Do a quick and dirty check to save space - Intel and AMD only and
+ * just the vendor. This is enough for most TPL code.
+ */
+ if (spl_phase() == PHASE_TPL) {
+ struct cpuid_result result;
+
+ result = cpuid(0x00000000);
+ switch (result.ecx >> 24) {
+ case 'l': /* GenuineIntel */
+ cpu->vendor = X86_VENDOR_INTEL;
+ break;
+ case 'D': /* AuthenticAMD */
+ cpu->vendor = X86_VENDOR_AMD;
+ break;
+ default:
+ cpu->vendor = X86_VENDOR_ANY;
+ break;
+ }
+ return;
+ }
+
+/* gcc 7.3 does not want to drop x86_vendors, so use #ifdef */
+#ifndef CONFIG_TPL_BUILD
+ char vendor_name[16];
+ int i;
+
+ vendor_name[0] = '\0'; /* Unset */
+
+ /* Find the id and vendor_name */
+ if (!has_cpuid()) {
+ /* Its a 486 if we can modify the AC flag */
+ if (flag_is_changeable_p(X86_EFLAGS_AC))
+ cpu->device = 0x00000400; /* 486 */
+ else
+ cpu->device = 0x00000300; /* 386 */
+ if ((cpu->device == 0x00000400) && test_cyrix_52div()) {
+ memcpy(vendor_name, "CyrixInstead", 13);
+ /* If we ever care we can enable cpuid here */
+ }
+ /* Detect NexGen with old hypercode */
+ else if (deep_magic_nexgen_probe())
+ memcpy(vendor_name, "NexGenDriven", 13);
+ } else {
+ int cpuid_level;
+
+ cpuid_level = build_vendor_name(vendor_name);
+ vendor_name[12] = '\0';
+
+ /* Intel-defined flags: level 0x00000001 */
+ if (cpuid_level >= 0x00000001) {
+ cpu->device = cpuid_eax(0x00000001);
+ } else {
+ /* Have CPUID level 0 only unheard of */
+ cpu->device = 0x00000400;
+ }
+ }
+ cpu->vendor = X86_VENDOR_UNKNOWN;
+ for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) {
+ if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) {
+ cpu->vendor = x86_vendors[i].vendor;
+ break;
+ }
+ }
+#endif
+}
+
+static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
+{
+ c->x86 = (tfms >> 8) & 0xf;
+ c->x86_model = (tfms >> 4) & 0xf;
+ c->x86_mask = tfms & 0xf;
+ if (c->x86 == 0xf)
+ c->x86 += (tfms >> 20) & 0xff;
+ if (c->x86 >= 0x6)
+ c->x86_model += ((tfms >> 16) & 0xF) << 4;
+}
+
+u32 cpu_get_family_model(void)
+{
+ return gd->arch.x86_device & 0x0fff0ff0;
+}
+
+u32 cpu_get_stepping(void)
+{
+ return gd->arch.x86_mask;
+}
+
+/* initialise FPU, reset EM, set MP and NE */
+static void setup_cpu_features(void)
+{
+ const u32 em_rst = ~X86_CR0_EM;
+ const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
+
+ asm ("fninit\n" \
+ "movl %%cr0, %%eax\n" \
+ "andl %0, %%eax\n" \
+ "orl %1, %%eax\n" \
+ "movl %%eax, %%cr0\n" \
+ : : "i" (em_rst), "i" (mp_ne_set) : "eax");
+}
+
+void cpu_reinit_fpu(void)
+{
+ asm ("fninit\n");
+}
+
+static void setup_identity(void)
+{
+ /* identify CPU via cpuid and store the decoded info into gd->arch */
+ if (has_cpuid()) {
+ struct cpu_device_id cpu;
+ struct cpuinfo_x86 c;
+
+ identify_cpu(&cpu);
+ get_fms(&c, cpu.device);
+ gd->arch.x86 = c.x86;
+ gd->arch.x86_vendor = cpu.vendor;
+ gd->arch.x86_model = c.x86_model;
+ gd->arch.x86_mask = c.x86_mask;
+ gd->arch.x86_device = cpu.device;
+
+ gd->arch.has_mtrr = has_mtrr();
+ }
+}
+
+static uint cpu_cpuid_extended_level(void)
+{
+ return cpuid_eax(0x80000000);
+}
+
+int cpu_phys_address_size(void)
+{
+ if (!has_cpuid())
+ return 32;
+
+ if (cpu_cpuid_extended_level() >= 0x80000008)
+ return cpuid_eax(0x80000008) & 0xff;
+
+ if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36))
+ return 36;
+
+ return 32;
+}
+
+/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
+static void setup_pci_ram_top(void)
+{
+ gd->pci_ram_top = 0x80000000U;
+}
+
+static void setup_mtrr(void)
+{
+ u64 mtrr_cap;
+
+ /* Configure fixed range MTRRs for some legacy regions */
+ if (!gd->arch.has_mtrr)
+ return;
+
+ mtrr_cap = native_read_msr(MTRR_CAP_MSR);
+ if (mtrr_cap & MTRR_CAP_FIX) {
+ /* Mark the VGA RAM area as uncacheable */
+ native_write_msr(MTRR_FIX_16K_A0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
+ MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+
+ /*
+ * Mark the PCI ROM area as cacheable to improve ROM
+ * execution performance.
+ */
+ native_write_msr(MTRR_FIX_4K_C0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_C8000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_D0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_D8000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+
+ /* Enable the fixed range MTRRs */
+ msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
+ }
+}
+
+int x86_cpu_init_tpl(void)
+{
+ setup_cpu_features();
+ setup_identity();
+
+ return 0;
+}
+
+int x86_cpu_init_f(void)
+{
+ if (ll_boot_init())
+ setup_cpu_features();
+ setup_identity();
+ setup_mtrr();
+ setup_pci_ram_top();
+
+ /* Set up the i8254 timer if required */
+ if (IS_ENABLED(CONFIG_I8254_TIMER))
+ i8254_init();
+
+ return 0;
+}
+
+int x86_cpu_reinit_f(void)
+{
+ long addr;
+
+ setup_identity();
+ setup_pci_ram_top();
+ addr = locate_coreboot_table();
+ if (addr >= 0) {
+ gd->arch.coreboot_table = addr;
+ gd->flags |= GD_FLG_SKIP_LL_INIT;
+ }
+
+ return 0;
+}
+
+void x86_enable_caches(void)
+{
+ unsigned long cr0;
+
+ cr0 = read_cr0();
+ cr0 &= ~(X86_CR0_NW | X86_CR0_CD);
+ write_cr0(cr0);
+ wbinvd();
+}
+void enable_caches(void) __attribute__((weak, alias("x86_enable_caches")));
+
+void x86_disable_caches(void)
+{
+ unsigned long cr0;
+
+ cr0 = read_cr0();
+ cr0 |= X86_CR0_NW | X86_CR0_CD;
+ wbinvd();
+ write_cr0(cr0);
+ wbinvd();
+}
+void disable_caches(void) __attribute__((weak, alias("x86_disable_caches")));
+
+int dcache_status(void)
+{
+ return !(read_cr0() & X86_CR0_CD);
+}
+
+void cpu_enable_paging_pae(ulong cr3)
+{
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n"
+ /* Enable pae */
+ "movl %%cr4, %%eax\n"
+ "orl $0x00000020, %%eax\n"
+ "movl %%eax, %%cr4\n"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n"
+ "orl $0x80000000, %%eax\n"
+ "movl %%eax, %%cr0\n"
+ :
+ : "r" (cr3)
+ : "eax");
+}
+
+void cpu_disable_paging_pae(void)
+{
+ /* Turn off paging */
+ __asm__ __volatile__ (
+ /* Disable paging */
+ "movl %%cr0, %%eax\n"
+ "andl $0x7fffffff, %%eax\n"
+ "movl %%eax, %%cr0\n"
+ /* Disable pae */
+ "movl %%cr4, %%eax\n"
+ "andl $0xffffffdf, %%eax\n"
+ "movl %%eax, %%cr4\n"
+ :
+ :
+ : "eax");
+}
+
+static bool can_detect_long_mode(void)
+{
+ return cpuid_eax(0x80000000) > 0x80000000UL;
+}
+
+static bool has_long_mode(void)
+{
+ return cpuid_edx(0x80000001) & (1 << 29) ? true : false;
+}
+
+int cpu_has_64bit(void)
+{
+ return has_cpuid() && can_detect_long_mode() &&
+ has_long_mode();
+}
+
+#define PAGETABLE_BASE 0x80000
+#define PAGETABLE_SIZE (6 * 4096)
+
+/**
+ * build_pagetable() - build a flat 4GiB page table structure for 64-bti mode
+ *
+ * @pgtable: Pointer to a 24iKB block of memory
+ */
+static void build_pagetable(uint32_t *pgtable)
+{
+ uint i;
+
+ memset(pgtable, '\0', PAGETABLE_SIZE);
+
+ /* Level 4 needs a single entry */
+ pgtable[0] = (ulong)&pgtable[1024] + 7;
+
+ /* Level 3 has one 64-bit entry for each GiB of memory */
+ for (i = 0; i < 4; i++)
+ pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + 7;
+
+ /* Level 2 has 2048 64-bit entries, each repesenting 2MiB */
+ for (i = 0; i < 2048; i++)
+ pgtable[2048 + i * 2] = 0x183 + (i << 21UL);
+}
+
+int cpu_jump_to_64bit(ulong setup_base, ulong target)
+{
+ uint32_t *pgtable;
+
+ pgtable = memalign(4096, PAGETABLE_SIZE);
+ if (!pgtable)
+ return -ENOMEM;
+
+ build_pagetable(pgtable);
+ cpu_call64((ulong)pgtable, setup_base, target);
+ free(pgtable);
+
+ return -EFAULT;
+}
+
+/*
+ * Jump from SPL to U-Boot
+ *
+ * This function is work-in-progress with many issues to resolve.
+ *
+ * It works by setting up several regions:
+ * ptr - a place to put the code that jumps into 64-bit mode
+ * gdt - a place to put the global descriptor table
+ * pgtable - a place to put the page tables
+ *
+ * The cpu_call64() code is copied from ROM and then manually patched so that
+ * it has the correct GDT address in RAM. U-Boot is copied from ROM into
+ * its pre-relocation address. Then we jump to the cpu_call64() code in RAM,
+ * which changes to 64-bit mode and starts U-Boot.
+ */
+int cpu_jump_to_64bit_uboot(ulong target)
+{
+ typedef void (*func_t)(ulong pgtable, ulong setup_base, ulong target);
+ uint32_t *pgtable;
+ func_t func;
+ char *ptr;
+
+ pgtable = (uint32_t *)PAGETABLE_BASE;
+
+ build_pagetable(pgtable);
+
+ extern long call64_stub_size;
+ ptr = malloc(call64_stub_size);
+ if (!ptr) {
+ printf("Failed to allocate the cpu_call64 stub\n");
+ return -ENOMEM;
+ }
+ memcpy(ptr, cpu_call64, call64_stub_size);
+
+ func = (func_t)ptr;
+
+ /* Jump to U-Boot */
+ func((ulong)pgtable, 0, (ulong)target);
+
+ return -EFAULT;
+}
+
+int x86_mp_init(void)
+{
+ int ret;
+
+ ret = mp_init();
+ if (ret) {
+ printf("Warning: MP init failure\n");
+ return log_ret(ret);
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/i386/interrupt.c b/roms/u-boot/arch/x86/cpu/i386/interrupt.c
new file mode 100644
index 000000000..fae2544c4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/i386/interrupt.c
@@ -0,0 +1,638 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * Portions of this file are derived from the Linux kernel source
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <hang.h>
+#include <init.h>
+#include <irq.h>
+#include <irq_func.h>
+#include <asm/control_regs.h>
+#include <asm/global_data.h>
+#include <asm/i8259.h>
+#include <asm/interrupt.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/processor-flags.h>
+#include <asm/ptrace.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DECLARE_INTERRUPT(x) \
+ ".globl irq_"#x"\n" \
+ ".hidden irq_"#x"\n" \
+ ".type irq_"#x", @function\n" \
+ "irq_"#x":\n" \
+ "pushl $"#x"\n" \
+ "jmp.d32 irq_common_entry\n"
+
+static char *exceptions[] = {
+ "Divide Error",
+ "Debug",
+ "NMI Interrupt",
+ "Breakpoint",
+ "Overflow",
+ "BOUND Range Exceeded",
+ "Invalid Opcode (Undefined Opcode)",
+ "Device Not Available (No Math Coprocessor)",
+ "Double Fault",
+ "Coprocessor Segment Overrun",
+ "Invalid TSS",
+ "Segment Not Present",
+ "Stack Segment Fault",
+ "General Protection",
+ "Page Fault",
+ "Reserved",
+ "x87 FPU Floating-Point Error",
+ "Alignment Check",
+ "Machine Check",
+ "SIMD Floating-Point Exception",
+ "Virtualization Exception",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved"
+};
+
+/**
+ * show_efi_loaded_images() - show loaded UEFI images
+ *
+ * List all loaded UEFI images.
+ *
+ * @eip: instruction pointer
+ */
+static void show_efi_loaded_images(uintptr_t eip)
+{
+ efi_print_image_infos((void *)eip);
+}
+
+static void dump_regs(struct irq_regs *regs)
+{
+ unsigned long cs, eip, eflags;
+ unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+ unsigned long d0, d1, d2, d3, d6, d7;
+ unsigned long sp;
+
+ /*
+ * Some exceptions cause an error code to be saved on the current stack
+ * after the EIP value. We should extract CS/EIP/EFLAGS from different
+ * position on the stack based on the exception number.
+ */
+ switch (regs->irq_id) {
+ case EXC_DF:
+ case EXC_TS:
+ case EXC_NP:
+ case EXC_SS:
+ case EXC_GP:
+ case EXC_PF:
+ case EXC_AC:
+ cs = regs->context.ctx2.xcs;
+ eip = regs->context.ctx2.eip;
+ eflags = regs->context.ctx2.eflags;
+ /* We should fix up the ESP due to error code */
+ regs->esp += 4;
+ break;
+ default:
+ cs = regs->context.ctx1.xcs;
+ eip = regs->context.ctx1.eip;
+ eflags = regs->context.ctx1.eflags;
+ break;
+ }
+
+ printf("EIP: %04x:[<%08lx>] EFLAGS: %08lx\n",
+ (u16)cs, eip, eflags);
+ if (gd->flags & GD_FLG_RELOC)
+ printf("Original EIP :[<%08lx>]\n", eip - gd->reloc_off);
+
+ printf("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+ regs->eax, regs->ebx, regs->ecx, regs->edx);
+ printf("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+ regs->esi, regs->edi, regs->ebp, regs->esp);
+ printf(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+ (u16)regs->xds, (u16)regs->xes, (u16)regs->xfs,
+ (u16)regs->xgs, (u16)regs->xss);
+
+ cr0 = read_cr0();
+ cr2 = read_cr2();
+ cr3 = read_cr3();
+ cr4 = read_cr4();
+
+ printf("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
+ cr0, cr2, cr3, cr4);
+
+ d0 = get_debugreg(0);
+ d1 = get_debugreg(1);
+ d2 = get_debugreg(2);
+ d3 = get_debugreg(3);
+
+ printf("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
+ d0, d1, d2, d3);
+
+ d6 = get_debugreg(6);
+ d7 = get_debugreg(7);
+ printf("DR6: %08lx DR7: %08lx\n",
+ d6, d7);
+
+ printf("Stack:\n");
+ sp = regs->esp;
+
+ sp += 64;
+
+ while (sp > (regs->esp - 16)) {
+ if (sp == regs->esp)
+ printf("--->");
+ else
+ printf(" ");
+ printf("0x%8.8lx : 0x%8.8lx\n", sp, (ulong)readl(sp));
+ sp -= 4;
+ }
+ show_efi_loaded_images(eip);
+}
+
+static void do_exception(struct irq_regs *regs)
+{
+ printf("%s\n", exceptions[regs->irq_id]);
+ dump_regs(regs);
+ hang();
+}
+
+struct idt_entry {
+ u16 base_low;
+ u16 selector;
+ u8 res;
+ u8 access;
+ u16 base_high;
+} __packed;
+
+struct idt_entry idt[256] __aligned(16);
+
+struct idt_ptr idt_ptr;
+
+static inline void load_idt(const struct idt_ptr *dtr)
+{
+ asm volatile("cs lidt %0" : : "m" (*dtr));
+}
+
+void set_vector(u8 intnum, void *routine)
+{
+ idt[intnum].base_high = (u16)((ulong)(routine) >> 16);
+ idt[intnum].base_low = (u16)((ulong)(routine) & 0xffff);
+}
+
+/*
+ * Ideally these would be defined static to avoid a checkpatch warning, but
+ * the compiler cannot see them in the inline asm and complains that they
+ * aren't defined
+ */
+void irq_0(void);
+void irq_1(void);
+
+int cpu_init_interrupts(void)
+{
+ int i;
+
+ int irq_entry_size = irq_1 - irq_0;
+ void *irq_entry = (void *)irq_0;
+
+ /* Setup the IDT */
+ for (i = 0; i < 256; i++) {
+ idt[i].access = 0x8e;
+ idt[i].res = 0;
+ idt[i].selector = X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE;
+ set_vector(i, irq_entry);
+ irq_entry += irq_entry_size;
+ }
+
+ idt_ptr.size = 256 * 8 - 1;
+ idt_ptr.address = (unsigned long) idt;
+
+ load_idt(&idt_ptr);
+
+ return 0;
+}
+
+void interrupt_read_idt(struct idt_ptr *ptr)
+{
+ asm volatile("sidt %0" : : "m" (*ptr));
+}
+
+void *x86_get_idt(void)
+{
+ return &idt_ptr;
+}
+
+void __do_irq(int irq)
+{
+ printf("Unhandled IRQ : %d\n", irq);
+}
+void do_irq(int irq) __attribute__((weak, alias("__do_irq")));
+
+void enable_interrupts(void)
+{
+ asm("sti\n");
+}
+
+int disable_interrupts(void)
+{
+ long flags;
+
+#if CONFIG_IS_ENABLED(X86_64)
+ asm volatile ("pushfq ; popq %0 ; cli\n" : "=g" (flags) : );
+#else
+ asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : );
+#endif
+ return flags & X86_EFLAGS_IF;
+}
+
+int interrupt_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ if (!ll_boot_init())
+ return 0;
+
+ /* Try to set up the interrupt router, but don't require one */
+ ret = irq_first_device_type(X86_IRQT_BASE, &dev);
+ if (ret && ret != -ENODEV)
+ return ret;
+
+ /*
+ * When running as an EFI application we are not in control of
+ * interrupts and should leave them alone.
+ */
+#ifndef CONFIG_EFI_APP
+ /* Just in case... */
+ disable_interrupts();
+
+#ifdef CONFIG_I8259_PIC
+ /* Initialize the master/slave i8259 pic */
+ i8259_init();
+#endif
+
+#ifdef CONFIG_APIC
+ lapic_setup();
+#endif
+
+ /* Initialize core interrupt and exception functionality of CPU */
+ cpu_init_interrupts();
+
+ /*
+ * It is now safe to enable interrupts.
+ *
+ * TODO(sjg@chromium.org): But we don't handle these correctly when
+ * booted from EFI.
+ */
+ enable_interrupts();
+#endif
+
+ return 0;
+}
+
+/* IRQ Low-Level Service Routine */
+void irq_llsr(struct irq_regs *regs)
+{
+ /*
+ * For detailed description of each exception, refer to:
+ * Intel® 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 1: Basic Architecture
+ * Order Number: 253665-029US, November 2008
+ * Table 6-1. Exceptions and Interrupts
+ */
+ if (regs->irq_id < 32) {
+ /* Architecture defined exception */
+ do_exception(regs);
+ } else {
+ /* Hardware or User IRQ */
+ do_irq(regs->irq_id);
+ }
+}
+
+/*
+ * OK - This looks really horrible, but it serves a purpose - It helps create
+ * fully relocatable code.
+ * - The call to irq_llsr will be a relative jump
+ * - The IRQ entries will be guaranteed to be in order
+ * Interrupt entries are now very small (a push and a jump) but they are
+ * now slower (all registers pushed on stack which provides complete
+ * crash dumps in the low level handlers
+ *
+ * Interrupt Entry Point:
+ * - Interrupt has caused eflags, CS and EIP to be pushed
+ * - Interrupt Vector Handler has pushed orig_eax
+ * - pt_regs.esp needs to be adjusted by 40 bytes:
+ * 12 bytes pushed by CPU (EFLAGSF, CS, EIP)
+ * 4 bytes pushed by vector handler (irq_id)
+ * 24 bytes pushed before SP (SS, GS, FS, ES, DS, EAX)
+ * NOTE: Only longs are pushed on/popped off the stack!
+ */
+asm(".globl irq_common_entry\n" \
+ ".hidden irq_common_entry\n" \
+ ".type irq_common_entry, @function\n" \
+ "irq_common_entry:\n" \
+ "cld\n" \
+ "pushl %ss\n" \
+ "pushl %gs\n" \
+ "pushl %fs\n" \
+ "pushl %es\n" \
+ "pushl %ds\n" \
+ "pushl %eax\n" \
+ "movl %esp, %eax\n" \
+ "addl $40, %eax\n" \
+ "pushl %eax\n" \
+ "pushl %ebp\n" \
+ "pushl %edi\n" \
+ "pushl %esi\n" \
+ "pushl %edx\n" \
+ "pushl %ecx\n" \
+ "pushl %ebx\n" \
+ "mov %esp, %eax\n" \
+ "call irq_llsr\n" \
+ "popl %ebx\n" \
+ "popl %ecx\n" \
+ "popl %edx\n" \
+ "popl %esi\n" \
+ "popl %edi\n" \
+ "popl %ebp\n" \
+ "popl %eax\n" \
+ "popl %eax\n" \
+ "popl %ds\n" \
+ "popl %es\n" \
+ "popl %fs\n" \
+ "popl %gs\n" \
+ "popl %ss\n" \
+ "add $4, %esp\n" \
+ "iret\n" \
+ DECLARE_INTERRUPT(0) \
+ DECLARE_INTERRUPT(1) \
+ DECLARE_INTERRUPT(2) \
+ DECLARE_INTERRUPT(3) \
+ DECLARE_INTERRUPT(4) \
+ DECLARE_INTERRUPT(5) \
+ DECLARE_INTERRUPT(6) \
+ DECLARE_INTERRUPT(7) \
+ DECLARE_INTERRUPT(8) \
+ DECLARE_INTERRUPT(9) \
+ DECLARE_INTERRUPT(10) \
+ DECLARE_INTERRUPT(11) \
+ DECLARE_INTERRUPT(12) \
+ DECLARE_INTERRUPT(13) \
+ DECLARE_INTERRUPT(14) \
+ DECLARE_INTERRUPT(15) \
+ DECLARE_INTERRUPT(16) \
+ DECLARE_INTERRUPT(17) \
+ DECLARE_INTERRUPT(18) \
+ DECLARE_INTERRUPT(19) \
+ DECLARE_INTERRUPT(20) \
+ DECLARE_INTERRUPT(21) \
+ DECLARE_INTERRUPT(22) \
+ DECLARE_INTERRUPT(23) \
+ DECLARE_INTERRUPT(24) \
+ DECLARE_INTERRUPT(25) \
+ DECLARE_INTERRUPT(26) \
+ DECLARE_INTERRUPT(27) \
+ DECLARE_INTERRUPT(28) \
+ DECLARE_INTERRUPT(29) \
+ DECLARE_INTERRUPT(30) \
+ DECLARE_INTERRUPT(31) \
+ DECLARE_INTERRUPT(32) \
+ DECLARE_INTERRUPT(33) \
+ DECLARE_INTERRUPT(34) \
+ DECLARE_INTERRUPT(35) \
+ DECLARE_INTERRUPT(36) \
+ DECLARE_INTERRUPT(37) \
+ DECLARE_INTERRUPT(38) \
+ DECLARE_INTERRUPT(39) \
+ DECLARE_INTERRUPT(40) \
+ DECLARE_INTERRUPT(41) \
+ DECLARE_INTERRUPT(42) \
+ DECLARE_INTERRUPT(43) \
+ DECLARE_INTERRUPT(44) \
+ DECLARE_INTERRUPT(45) \
+ DECLARE_INTERRUPT(46) \
+ DECLARE_INTERRUPT(47) \
+ DECLARE_INTERRUPT(48) \
+ DECLARE_INTERRUPT(49) \
+ DECLARE_INTERRUPT(50) \
+ DECLARE_INTERRUPT(51) \
+ DECLARE_INTERRUPT(52) \
+ DECLARE_INTERRUPT(53) \
+ DECLARE_INTERRUPT(54) \
+ DECLARE_INTERRUPT(55) \
+ DECLARE_INTERRUPT(56) \
+ DECLARE_INTERRUPT(57) \
+ DECLARE_INTERRUPT(58) \
+ DECLARE_INTERRUPT(59) \
+ DECLARE_INTERRUPT(60) \
+ DECLARE_INTERRUPT(61) \
+ DECLARE_INTERRUPT(62) \
+ DECLARE_INTERRUPT(63) \
+ DECLARE_INTERRUPT(64) \
+ DECLARE_INTERRUPT(65) \
+ DECLARE_INTERRUPT(66) \
+ DECLARE_INTERRUPT(67) \
+ DECLARE_INTERRUPT(68) \
+ DECLARE_INTERRUPT(69) \
+ DECLARE_INTERRUPT(70) \
+ DECLARE_INTERRUPT(71) \
+ DECLARE_INTERRUPT(72) \
+ DECLARE_INTERRUPT(73) \
+ DECLARE_INTERRUPT(74) \
+ DECLARE_INTERRUPT(75) \
+ DECLARE_INTERRUPT(76) \
+ DECLARE_INTERRUPT(77) \
+ DECLARE_INTERRUPT(78) \
+ DECLARE_INTERRUPT(79) \
+ DECLARE_INTERRUPT(80) \
+ DECLARE_INTERRUPT(81) \
+ DECLARE_INTERRUPT(82) \
+ DECLARE_INTERRUPT(83) \
+ DECLARE_INTERRUPT(84) \
+ DECLARE_INTERRUPT(85) \
+ DECLARE_INTERRUPT(86) \
+ DECLARE_INTERRUPT(87) \
+ DECLARE_INTERRUPT(88) \
+ DECLARE_INTERRUPT(89) \
+ DECLARE_INTERRUPT(90) \
+ DECLARE_INTERRUPT(91) \
+ DECLARE_INTERRUPT(92) \
+ DECLARE_INTERRUPT(93) \
+ DECLARE_INTERRUPT(94) \
+ DECLARE_INTERRUPT(95) \
+ DECLARE_INTERRUPT(97) \
+ DECLARE_INTERRUPT(96) \
+ DECLARE_INTERRUPT(98) \
+ DECLARE_INTERRUPT(99) \
+ DECLARE_INTERRUPT(100) \
+ DECLARE_INTERRUPT(101) \
+ DECLARE_INTERRUPT(102) \
+ DECLARE_INTERRUPT(103) \
+ DECLARE_INTERRUPT(104) \
+ DECLARE_INTERRUPT(105) \
+ DECLARE_INTERRUPT(106) \
+ DECLARE_INTERRUPT(107) \
+ DECLARE_INTERRUPT(108) \
+ DECLARE_INTERRUPT(109) \
+ DECLARE_INTERRUPT(110) \
+ DECLARE_INTERRUPT(111) \
+ DECLARE_INTERRUPT(112) \
+ DECLARE_INTERRUPT(113) \
+ DECLARE_INTERRUPT(114) \
+ DECLARE_INTERRUPT(115) \
+ DECLARE_INTERRUPT(116) \
+ DECLARE_INTERRUPT(117) \
+ DECLARE_INTERRUPT(118) \
+ DECLARE_INTERRUPT(119) \
+ DECLARE_INTERRUPT(120) \
+ DECLARE_INTERRUPT(121) \
+ DECLARE_INTERRUPT(122) \
+ DECLARE_INTERRUPT(123) \
+ DECLARE_INTERRUPT(124) \
+ DECLARE_INTERRUPT(125) \
+ DECLARE_INTERRUPT(126) \
+ DECLARE_INTERRUPT(127) \
+ DECLARE_INTERRUPT(128) \
+ DECLARE_INTERRUPT(129) \
+ DECLARE_INTERRUPT(130) \
+ DECLARE_INTERRUPT(131) \
+ DECLARE_INTERRUPT(132) \
+ DECLARE_INTERRUPT(133) \
+ DECLARE_INTERRUPT(134) \
+ DECLARE_INTERRUPT(135) \
+ DECLARE_INTERRUPT(136) \
+ DECLARE_INTERRUPT(137) \
+ DECLARE_INTERRUPT(138) \
+ DECLARE_INTERRUPT(139) \
+ DECLARE_INTERRUPT(140) \
+ DECLARE_INTERRUPT(141) \
+ DECLARE_INTERRUPT(142) \
+ DECLARE_INTERRUPT(143) \
+ DECLARE_INTERRUPT(144) \
+ DECLARE_INTERRUPT(145) \
+ DECLARE_INTERRUPT(146) \
+ DECLARE_INTERRUPT(147) \
+ DECLARE_INTERRUPT(148) \
+ DECLARE_INTERRUPT(149) \
+ DECLARE_INTERRUPT(150) \
+ DECLARE_INTERRUPT(151) \
+ DECLARE_INTERRUPT(152) \
+ DECLARE_INTERRUPT(153) \
+ DECLARE_INTERRUPT(154) \
+ DECLARE_INTERRUPT(155) \
+ DECLARE_INTERRUPT(156) \
+ DECLARE_INTERRUPT(157) \
+ DECLARE_INTERRUPT(158) \
+ DECLARE_INTERRUPT(159) \
+ DECLARE_INTERRUPT(160) \
+ DECLARE_INTERRUPT(161) \
+ DECLARE_INTERRUPT(162) \
+ DECLARE_INTERRUPT(163) \
+ DECLARE_INTERRUPT(164) \
+ DECLARE_INTERRUPT(165) \
+ DECLARE_INTERRUPT(166) \
+ DECLARE_INTERRUPT(167) \
+ DECLARE_INTERRUPT(168) \
+ DECLARE_INTERRUPT(169) \
+ DECLARE_INTERRUPT(170) \
+ DECLARE_INTERRUPT(171) \
+ DECLARE_INTERRUPT(172) \
+ DECLARE_INTERRUPT(173) \
+ DECLARE_INTERRUPT(174) \
+ DECLARE_INTERRUPT(175) \
+ DECLARE_INTERRUPT(176) \
+ DECLARE_INTERRUPT(177) \
+ DECLARE_INTERRUPT(178) \
+ DECLARE_INTERRUPT(179) \
+ DECLARE_INTERRUPT(180) \
+ DECLARE_INTERRUPT(181) \
+ DECLARE_INTERRUPT(182) \
+ DECLARE_INTERRUPT(183) \
+ DECLARE_INTERRUPT(184) \
+ DECLARE_INTERRUPT(185) \
+ DECLARE_INTERRUPT(186) \
+ DECLARE_INTERRUPT(187) \
+ DECLARE_INTERRUPT(188) \
+ DECLARE_INTERRUPT(189) \
+ DECLARE_INTERRUPT(190) \
+ DECLARE_INTERRUPT(191) \
+ DECLARE_INTERRUPT(192) \
+ DECLARE_INTERRUPT(193) \
+ DECLARE_INTERRUPT(194) \
+ DECLARE_INTERRUPT(195) \
+ DECLARE_INTERRUPT(196) \
+ DECLARE_INTERRUPT(197) \
+ DECLARE_INTERRUPT(198) \
+ DECLARE_INTERRUPT(199) \
+ DECLARE_INTERRUPT(200) \
+ DECLARE_INTERRUPT(201) \
+ DECLARE_INTERRUPT(202) \
+ DECLARE_INTERRUPT(203) \
+ DECLARE_INTERRUPT(204) \
+ DECLARE_INTERRUPT(205) \
+ DECLARE_INTERRUPT(206) \
+ DECLARE_INTERRUPT(207) \
+ DECLARE_INTERRUPT(208) \
+ DECLARE_INTERRUPT(209) \
+ DECLARE_INTERRUPT(210) \
+ DECLARE_INTERRUPT(211) \
+ DECLARE_INTERRUPT(212) \
+ DECLARE_INTERRUPT(213) \
+ DECLARE_INTERRUPT(214) \
+ DECLARE_INTERRUPT(215) \
+ DECLARE_INTERRUPT(216) \
+ DECLARE_INTERRUPT(217) \
+ DECLARE_INTERRUPT(218) \
+ DECLARE_INTERRUPT(219) \
+ DECLARE_INTERRUPT(220) \
+ DECLARE_INTERRUPT(221) \
+ DECLARE_INTERRUPT(222) \
+ DECLARE_INTERRUPT(223) \
+ DECLARE_INTERRUPT(224) \
+ DECLARE_INTERRUPT(225) \
+ DECLARE_INTERRUPT(226) \
+ DECLARE_INTERRUPT(227) \
+ DECLARE_INTERRUPT(228) \
+ DECLARE_INTERRUPT(229) \
+ DECLARE_INTERRUPT(230) \
+ DECLARE_INTERRUPT(231) \
+ DECLARE_INTERRUPT(232) \
+ DECLARE_INTERRUPT(233) \
+ DECLARE_INTERRUPT(234) \
+ DECLARE_INTERRUPT(235) \
+ DECLARE_INTERRUPT(236) \
+ DECLARE_INTERRUPT(237) \
+ DECLARE_INTERRUPT(238) \
+ DECLARE_INTERRUPT(239) \
+ DECLARE_INTERRUPT(240) \
+ DECLARE_INTERRUPT(241) \
+ DECLARE_INTERRUPT(242) \
+ DECLARE_INTERRUPT(243) \
+ DECLARE_INTERRUPT(244) \
+ DECLARE_INTERRUPT(245) \
+ DECLARE_INTERRUPT(246) \
+ DECLARE_INTERRUPT(247) \
+ DECLARE_INTERRUPT(248) \
+ DECLARE_INTERRUPT(249) \
+ DECLARE_INTERRUPT(250) \
+ DECLARE_INTERRUPT(251) \
+ DECLARE_INTERRUPT(252) \
+ DECLARE_INTERRUPT(253) \
+ DECLARE_INTERRUPT(254) \
+ DECLARE_INTERRUPT(255));
diff --git a/roms/u-boot/arch/x86/cpu/i386/setjmp.S b/roms/u-boot/arch/x86/cpu/i386/setjmp.S
new file mode 100644
index 000000000..40b10dc8d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/i386/setjmp.S
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Written by H. Peter Anvin <hpa@zytor.com>
+ * Brought in from Linux v4.4 and modified for U-Boot
+ * From Linux arch/um/sys-i386/setjmp.S
+ */
+
+#define _REGPARM
+
+/*
+ * The jmp_buf is assumed to contain the following, in order:
+ * %ebx
+ * %esp
+ * %ebp
+ * %esi
+ * %edi
+ * <return address>
+ */
+
+ .text
+ .align 4
+ .globl setjmp
+ .type setjmp, @function
+setjmp:
+#ifdef _REGPARM
+ movl %eax, %edx
+#else
+ movl 4(%esp), %edx
+#endif
+ popl %ecx /* Return address, and adjust the stack */
+ xorl %eax, %eax /* Return value */
+ movl %ebx, (%edx)
+ movl %esp, 4(%edx) /* Post-return %esp! */
+ pushl %ecx /* Make the call/return stack happy */
+ movl %ebp, 8(%edx)
+ movl %esi, 12(%edx)
+ movl %edi, 16(%edx)
+ movl %ecx, 20(%edx) /* Return address */
+ ret
+
+ /* Provide function size if needed */
+ .size setjmp, .-setjmp
+
+ .align 4
+ .globl longjmp
+ .type longjmp, @function
+longjmp:
+#ifdef _REGPARM
+ xchgl %eax, %edx
+#else
+ movl 4(%esp), %edx /* jmp_ptr address */
+#endif
+ movl (%edx), %ebx
+ movl 4(%edx), %esp
+ movl 8(%edx), %ebp
+ movl 12(%edx), %esi
+ movl 16(%edx), %edi
+ jmp *20(%edx)
+
+ .size longjmp, .-longjmp
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/Makefile b/roms/u-boot/arch/x86/cpu/intel_common/Makefile
new file mode 100644
index 000000000..8b9a810f6
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/Makefile
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2016 Google, Inc
+
+obj-$(CONFIG_INTEL_ACPIGEN) += acpi.o
+
+ifdef CONFIG_HAVE_MRC
+obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += car.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
+endif
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_INTEL_GMA_ACPI) += intel_opregion.o
+endif
+
+ifdef CONFIG_INTEL_CAR_CQOS
+obj-$(CONFIG_TPL_BUILD) += car2.o
+ifndef CONFIG_SPL_BUILD
+obj-y += car2_uninit.o
+endif
+endif
+
+obj-y += cpu.o
+obj-y += fast_spi.o
+obj-y += lpc.o
+obj-y += lpss.o
+obj-$(CONFIG_$(SPL_)INTEL_GENERIC_WIFI) += generic_wifi.o
+ifndef CONFIG_TARGET_EFI_APP
+obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
+ifndef CONFIG_$(SPL_)X86_64
+obj-y += microcode.o
+endif
+endif
+obj-y += pch.o
+obj-$(CONFIG_HAVE_ITSS) += itss.o
+obj-$(CONFIG_HAVE_P2SB) += p2sb.o
+
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+ifndef CONFIG_SYS_COREBOOT
+obj-y += cpu_from_spl.o
+endif
+endif
+endif
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/acpi.c b/roms/u-boot/arch/x86/cpu/intel_common/acpi.c
new file mode 100644
index 000000000..15f19da20
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/acpi.c
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generic Intel ACPI table generation
+ *
+ * Copyright (C) 2017 Intel Corp.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot src/soc/intel/common/block/acpi.c
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <cpu.h>
+#include <dm.h>
+#include <acpi/acpigen.h>
+#include <asm/acpigen.h>
+#include <asm/acpi_table.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/global_data.h>
+#include <asm/intel_acpi.h>
+#include <asm/ioapic.h>
+#include <asm/mpspec.h>
+#include <asm/smm.h>
+#include <asm/turbo.h>
+#include <asm/intel_gnvs.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/systemagent.h>
+#include <dm/acpi.h>
+#include <linux/err.h>
+#include <power/acpi_pmc.h>
+
+u32 acpi_fill_mcfg(u32 current)
+{
+ /* PCI Segment Group 0, Start Bus Number 0, End Bus Number is 255 */
+ current += acpi_create_mcfg_mmconfig((void *)current,
+ CONFIG_MMCONF_BASE_ADDRESS, 0, 0,
+ (CONFIG_SA_PCIEX_LENGTH >> 20)
+ - 1);
+ return current;
+}
+
+static int acpi_sci_irq(void)
+{
+ int sci_irq = 9;
+ uint scis;
+ int ret;
+
+ ret = arch_read_sci_irq_select();
+ if (IS_ERR_VALUE(ret))
+ return log_msg_ret("sci_irq", ret);
+ scis = ret;
+ scis &= SCI_IRQ_MASK;
+ scis >>= SCI_IRQ_SHIFT;
+
+ /* Determine how SCI is routed. */
+ switch (scis) {
+ case SCIS_IRQ9:
+ case SCIS_IRQ10:
+ case SCIS_IRQ11:
+ sci_irq = scis - SCIS_IRQ9 + 9;
+ break;
+ case SCIS_IRQ20:
+ case SCIS_IRQ21:
+ case SCIS_IRQ22:
+ case SCIS_IRQ23:
+ sci_irq = scis - SCIS_IRQ20 + 20;
+ break;
+ default:
+ log_warning("Invalid SCI route! Defaulting to IRQ9\n");
+ sci_irq = 9;
+ break;
+ }
+
+ log_debug("SCI is IRQ%d\n", sci_irq);
+
+ return sci_irq;
+}
+
+static unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+ int sci = acpi_sci_irq();
+ u16 flags = MP_IRQ_TRIGGER_LEVEL;
+
+ if (sci < 0)
+ return log_msg_ret("sci irq", sci);
+
+ /* INT_SRC_OVR */
+ current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
+
+ flags |= arch_madt_sci_irq_polarity(sci);
+
+ /* SCI */
+ current +=
+ acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
+
+ return current;
+}
+
+u32 acpi_fill_madt(u32 current)
+{
+ /* Local APICs */
+ current += acpi_create_madt_lapics(current);
+
+ /* IOAPIC */
+ current += acpi_create_madt_ioapic((void *)current, 2, IO_APIC_ADDR, 0);
+
+ return acpi_madt_irq_overrides(current);
+}
+
+void intel_acpi_fill_fadt(struct acpi_fadt *fadt)
+{
+ const u16 pmbase = IOMAP_ACPI_BASE;
+
+ /* Use ACPI 3.0 revision. */
+ fadt->header.revision = acpi_get_table_revision(ACPITAB_FADT);
+
+ fadt->sci_int = acpi_sci_irq();
+ fadt->smi_cmd = APM_CNT;
+ fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+ fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+ fadt->s4bios_req = 0x0;
+ fadt->pstate_cnt = 0;
+
+ fadt->pm1a_evt_blk = pmbase + PM1_STS;
+ fadt->pm1b_evt_blk = 0x0;
+ fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
+ fadt->pm1b_cnt_blk = 0x0;
+
+ fadt->gpe0_blk = pmbase + GPE0_STS;
+
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+
+ /* GPE0 STS/EN pairs each 32 bits wide. */
+ fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
+
+ fadt->flush_size = 0x400; /* twice of cache size */
+ fadt->flush_stride = 0x10; /* Cache line width */
+ fadt->duty_offset = 1;
+ fadt->day_alrm = 0xd;
+
+ fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE |
+ ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+ fadt->reset_reg.space_id = 1;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.addrl = IO_PORT_RESET;
+ fadt->reset_value = RST_CPU | SYS_RST;
+
+ fadt->x_pm1a_evt_blk.space_id = 1;
+ fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
+ fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS;
+
+ fadt->x_pm1b_evt_blk.space_id = 1;
+
+ fadt->x_pm1a_cnt_blk.space_id = 1;
+ fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
+ fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT;
+
+ fadt->x_pm1b_cnt_blk.space_id = 1;
+
+ fadt->x_gpe1_blk.space_id = 1;
+}
+
+int intel_southbridge_write_acpi_tables(const struct udevice *dev,
+ struct acpi_ctx *ctx)
+{
+ int ret;
+
+ ret = acpi_write_dbg2_pci_uart(ctx, gd->cur_serial_dev,
+ ACPI_ACCESS_SIZE_DWORD_ACCESS);
+ if (ret)
+ return log_msg_ret("dbg2", ret);
+
+ ret = acpi_write_hpet(ctx);
+ if (ret)
+ return log_msg_ret("hpet", ret);
+
+ return 0;
+}
+
+__weak u32 acpi_fill_soc_wake(u32 generic_pm1_en,
+ const struct chipset_power_state *ps)
+{
+ return generic_pm1_en;
+}
+
+__weak int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+ return 0;
+}
+
+int southbridge_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_global_nvs *gnvs;
+ int ret;
+
+ ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs), 0,
+ (void **)&gnvs);
+ if (ret)
+ return log_msg_ret("bloblist", ret);
+
+ ret = acpi_create_gnvs(gnvs);
+ if (ret)
+ return log_msg_ret("gnvs", ret);
+
+ /*
+ * TODO(sjg@chromum.org): tell SMI about it
+ * smm_setup_structures(gnvs, NULL, NULL);
+ */
+
+ /* Add it to DSDT */
+ acpigen_write_scope(ctx, "\\");
+ acpigen_write_name_dword(ctx, "NVSA", (uintptr_t)gnvs);
+ acpigen_pop_len(ctx);
+
+ return 0;
+}
+
+static int calculate_power(int tdp, int p1_ratio, int ratio)
+{
+ u32 m;
+ u32 power;
+
+ /*
+ * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
+ *
+ * Power = (ratio / p1_ratio) * m * tdp
+ */
+
+ m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
+ m = (m * m) / 1000;
+
+ power = ((ratio * 100000 / p1_ratio) / 100);
+ power *= (m / 100) * (tdp / 1000);
+ power /= 1000;
+
+ return power;
+}
+
+void generate_p_state_entries(struct acpi_ctx *ctx, int core,
+ int cores_per_package)
+{
+ int ratio_min, ratio_max, ratio_turbo, ratio_step;
+ int coord_type, power_max, num_entries;
+ int ratio, power, clock, clock_max;
+ bool turbo;
+
+ coord_type = cpu_get_coord_type();
+ ratio_min = cpu_get_min_ratio();
+ ratio_max = cpu_get_max_ratio();
+ clock_max = (ratio_max * cpu_get_bus_clock_khz()) / 1000;
+ turbo = (turbo_get_state() == TURBO_ENABLED);
+
+ /* Calculate CPU TDP in mW */
+ power_max = cpu_get_power_max();
+
+ /* Write _PCT indicating use of FFixedHW */
+ acpigen_write_empty_pct(ctx);
+
+ /* Write _PPC with no limit on supported P-state */
+ acpigen_write_ppc_nvs(ctx);
+ /* Write PSD indicating configured coordination type */
+ acpigen_write_psd_package(ctx, core, 1, coord_type);
+
+ /* Add P-state entries in _PSS table */
+ acpigen_write_name(ctx, "_PSS");
+
+ /* Determine ratio points */
+ ratio_step = PSS_RATIO_STEP;
+ do {
+ num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
+ if (((ratio_max - ratio_min) % ratio_step) > 0)
+ num_entries += 1;
+ if (turbo)
+ num_entries += 1;
+ if (num_entries > PSS_MAX_ENTRIES)
+ ratio_step += 1;
+ } while (num_entries > PSS_MAX_ENTRIES);
+
+ /* _PSS package count depends on Turbo */
+ acpigen_write_package(ctx, num_entries);
+
+ /* P[T] is Turbo state if enabled */
+ if (turbo) {
+ ratio_turbo = cpu_get_max_turbo_ratio();
+
+ /* Add entry for Turbo ratio */
+ acpigen_write_pss_package(ctx, clock_max + 1, /* MHz */
+ power_max, /* mW */
+ PSS_LATENCY_TRANSITION,/* lat1 */
+ PSS_LATENCY_BUSMASTER,/* lat2 */
+ ratio_turbo << 8, /* control */
+ ratio_turbo << 8); /* status */
+ num_entries -= 1;
+ }
+
+ /* First regular entry is max non-turbo ratio */
+ acpigen_write_pss_package(ctx, clock_max, /* MHz */
+ power_max, /* mW */
+ PSS_LATENCY_TRANSITION,/* lat1 */
+ PSS_LATENCY_BUSMASTER,/* lat2 */
+ ratio_max << 8, /* control */
+ ratio_max << 8); /* status */
+ num_entries -= 1;
+
+ /* Generate the remaining entries */
+ for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
+ ratio >= ratio_min; ratio -= ratio_step) {
+ /* Calculate power at this ratio */
+ power = calculate_power(power_max, ratio_max, ratio);
+ clock = (ratio * cpu_get_bus_clock_khz()) / 1000;
+
+ acpigen_write_pss_package(ctx, clock, /* MHz */
+ power, /* mW */
+ PSS_LATENCY_TRANSITION,/* lat1 */
+ PSS_LATENCY_BUSMASTER,/* lat2 */
+ ratio << 8, /* control */
+ ratio << 8); /* status */
+ }
+ /* Fix package length */
+ acpigen_pop_len(ctx);
+}
+
+void generate_t_state_entries(struct acpi_ctx *ctx, int core,
+ int cores_per_package, struct acpi_tstate *entry,
+ int nentries)
+{
+ if (!nentries)
+ return;
+
+ /* Indicate SW_ALL coordination for T-states */
+ acpigen_write_tsd_package(ctx, core, cores_per_package, SW_ALL);
+
+ /* Indicate FixedHW so OS will use MSR */
+ acpigen_write_empty_ptc(ctx);
+
+ /* Set NVS controlled T-state limit */
+ acpigen_write_tpc(ctx, "\\TLVL");
+
+ /* Write TSS table for MSR access */
+ acpigen_write_tss_package(ctx, entry, nentries);
+}
+
+int acpi_generate_cpu_header(struct acpi_ctx *ctx, int core_id,
+ const struct acpi_cstate *c_state_map,
+ int num_cstates)
+{
+ bool is_first = !core_id;
+
+ /* Generate processor \_PR.CPUx */
+ acpigen_write_processor(ctx, core_id, is_first ? ACPI_BASE_ADDRESS : 0,
+ is_first ? 6 : 0);
+
+ /* Generate C-state tables */
+ acpigen_write_cst_package(ctx, c_state_map, num_cstates);
+
+ return 0;
+}
+
+int acpi_generate_cpu_package_final(struct acpi_ctx *ctx, int cores_per_package)
+{
+ /*
+ * PPKG is usually used for thermal management of the first and only
+ * package
+ */
+ acpigen_write_processor_package(ctx, "PPKG", 0, cores_per_package);
+
+ /* Add a method to notify processor nodes */
+ acpigen_write_processor_cnot(ctx, cores_per_package);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/car.S b/roms/u-boot/arch/x86/cpu/intel_common/car.S
new file mode 100644
index 000000000..00308dbde
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/car.S
@@ -0,0 +1,244 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan)
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/microcode.h>
+#include <asm/msr-index.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+
+#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
+#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
+#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
+
+/* Cache 4GB - MRC_SIZE_KB for MRC */
+#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1)
+#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES)
+#define CACHE_MRC_MASK (~CACHE_MRC_BYTES)
+
+#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1)
+
+#define NOEVICTMOD_MSR 0x2e0
+
+ /*
+ * Note: ebp must not be touched in this code as it holds the BIST
+ * value (built-in self test). We preserve this value until it can
+ * be written to global_data when CAR is ready for use.
+ */
+.globl car_init
+car_init:
+ post_code(POST_CAR_START)
+
+ /* Send INIT IPI to all excluding ourself */
+ movl $0x000C4500, %eax
+ movl $0xFEE00300, %esi
+ movl %eax, (%esi)
+
+ /* TODO: Load microcode later - the 'no eviction' mode breaks this */
+ movl $MSR_IA32_UCODE_WRITE, %ecx
+ xorl %edx, %edx
+ movl $_dt_ucode_base_size, %eax
+ movl (%eax), %eax
+ addl $UCODE_HEADER_LEN, %eax
+ wrmsr
+
+ post_code(POST_CAR_SIPI)
+ /* Zero out all fixed range and variable range MTRRs */
+ movl $mtrr_table, %esi
+ movl $((mtrr_table_end - mtrr_table) / 2), %edi
+ xorl %eax, %eax
+ xorl %edx, %edx
+clear_mtrrs:
+ movw (%esi), %bx
+ movzx %bx, %ecx
+ wrmsr
+ add $2, %esi
+ dec %edi
+ jnz clear_mtrrs
+
+ post_code(POST_CAR_MTRR)
+ /* Configure the default memory type to uncacheable */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ andl $(~0x00000cff), %eax
+ wrmsr
+
+ post_code(POST_CAR_UNCACHEABLE)
+ /* Set Cache-as-RAM base address */
+ movl $(MTRR_PHYS_BASE_MSR(0)), %ecx
+ movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
+ xorl %edx, %edx
+ wrmsr
+
+ post_code(POST_CAR_BASE_ADDRESS)
+ /* Set Cache-as-RAM mask */
+ movl $(MTRR_PHYS_MASK_MSR(0)), %ecx
+ movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
+ movl $CPU_PHYSMASK_HI, %edx
+ wrmsr
+
+ post_code(POST_CAR_MASK)
+
+ /* Enable MTRR */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ orl $MTRR_DEF_TYPE_EN, %eax
+ wrmsr
+
+ /* Enable cache (CR0.CD = 0, CR0.NW = 0) */
+ movl %cr0, %eax
+ andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax
+ invd
+ movl %eax, %cr0
+
+ /* enable the 'no eviction' mode */
+ movl $NOEVICTMOD_MSR, %ecx
+ rdmsr
+ orl $1, %eax
+ andl $~2, %eax
+ wrmsr
+
+ /* Clear the cache memory region. This will also fill up the cache */
+ movl $CACHE_AS_RAM_BASE, %esi
+ movl %esi, %edi
+ movl $(CACHE_AS_RAM_SIZE / 4), %ecx
+ xorl %eax, %eax
+ rep stosl
+
+ /* enable the 'no eviction run' state */
+ movl $NOEVICTMOD_MSR, %ecx
+ rdmsr
+ orl $3, %eax
+ wrmsr
+
+ post_code(POST_CAR_FILL)
+ /* Enable Cache-as-RAM mode by disabling cache */
+ movl %cr0, %eax
+ orl $X86_CR0_CD, %eax
+ movl %eax, %cr0
+
+ /* Enable cache for our code in Flash because we do XIP here */
+ movl $MTRR_PHYS_BASE_MSR(1), %ecx
+ xorl %edx, %edx
+ movl $car_init_ret, %eax
+ andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
+ orl $MTRR_TYPE_WRPROT, %eax
+ wrmsr
+
+ movl $MTRR_PHYS_MASK_MSR(1), %ecx
+ movl $CPU_PHYSMASK_HI, %edx
+ movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
+ wrmsr
+
+ post_code(POST_CAR_ROM_CACHE)
+#ifdef CONFIG_CACHE_MRC_BIN
+ /* Enable caching for ram init code to run faster */
+ movl $MTRR_PHYS_BASE_MSR(2), %ecx
+ movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
+ xorl %edx, %edx
+ wrmsr
+ movl $MTRR_PHYS_MASK_MSR(2), %ecx
+ movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax
+ movl $CPU_PHYSMASK_HI, %edx
+ wrmsr
+#endif
+
+ post_code(POST_CAR_MRC_CACHE)
+ /* Enable cache */
+ movl %cr0, %eax
+ andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax
+ movl %eax, %cr0
+
+ post_code(POST_CAR_CPU_CACHE)
+
+ /* All CPUs need to be in Wait for SIPI state */
+wait_for_sipi:
+ movl (%esi), %eax
+ bt $12, %eax
+ jc wait_for_sipi
+
+ /* return */
+ jmp car_init_ret
+
+.globl car_uninit
+car_uninit:
+ /* Disable cache */
+ movl %cr0, %eax
+ orl $X86_CR0_CD, %eax
+ movl %eax, %cr0
+
+ /* Disable MTRRs */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ andl $(~MTRR_DEF_TYPE_EN), %eax
+ wrmsr
+
+ /* Disable the no-eviction run state */
+ movl $NOEVICTMOD_MSR, %ecx
+ rdmsr
+ andl $~2, %eax
+ wrmsr
+
+ invd
+
+ /* Disable the no-eviction mode */
+ rdmsr
+ andl $~1, %eax
+ wrmsr
+
+#ifdef CONFIG_CACHE_MRC_BIN
+ /* Clear the MTRR that was used to cache MRC */
+ xorl %eax, %eax
+ xorl %edx, %edx
+ movl $MTRR_PHYS_BASE_MSR(2), %ecx
+ wrmsr
+ movl $MTRR_PHYS_MASK_MSR(2), %ecx
+ wrmsr
+#endif
+
+ /* Enable MTRRs */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ orl $MTRR_DEF_TYPE_EN, %eax
+ wrmsr
+
+ invd
+
+ ret
+
+mtrr_table:
+ /* Fixed MTRRs */
+ .word 0x250, 0x258, 0x259
+ .word 0x268, 0x269, 0x26A
+ .word 0x26B, 0x26C, 0x26D
+ .word 0x26E, 0x26F
+ /* Variable MTRRs */
+ .word 0x200, 0x201, 0x202, 0x203
+ .word 0x204, 0x205, 0x206, 0x207
+ .word 0x208, 0x209, 0x20A, 0x20B
+ .word 0x20C, 0x20D, 0x20E, 0x20F
+ .word 0x210, 0x211, 0x212, 0x213
+mtrr_table_end:
+
+ .align 4
+_dt_ucode_base_size:
+ /* These next two fields are filled in by binman */
+.globl ucode_base
+ucode_base: /* Declared in microcode.h */
+ .long 0 /* microcode base */
+.globl ucode_size
+ucode_size: /* Declared in microcode.h */
+ .long 0 /* microcode size */
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/car2.S b/roms/u-boot/arch/x86/cpu/intel_common/car2.S
new file mode 100644
index 000000000..086f98747
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/car2.S
@@ -0,0 +1,448 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file was modified from the coreboot version.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ */
+
+#include <config.h>
+#include <asm/msr-index.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+
+#define KiB 1024
+
+#define IS_POWER_OF_2(x) (!((x) & ((x) - 1)))
+
+.global car_init
+car_init:
+ post_code(POST_CAR_START)
+
+ /*
+ * Use the MTRR default type MSR as a proxy for detecting INIT#.
+ * Reset the system if any known bits are set in that MSR. That is
+ * an indication of the CPU not being properly reset.
+ */
+check_for_clean_reset:
+ mov $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ and $(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax
+ cmp $0, %eax
+ jz no_reset
+ /* perform warm reset */
+ movw $IO_PORT_RESET, %dx
+ movb $(SYS_RST | RST_CPU), %al
+ outb %al, %dx
+
+no_reset:
+ post_code(POST_CAR_SIPI)
+
+ /* Clear/disable fixed MTRRs */
+ mov $fixed_mtrr_list_size, %ebx
+ xor %eax, %eax
+ xor %edx, %edx
+
+clear_fixed_mtrr:
+ add $-2, %ebx
+ movzwl fixed_mtrr_list(%ebx), %ecx
+ wrmsr
+ jnz clear_fixed_mtrr
+
+ post_code(POST_CAR_MTRR)
+
+ /* Figure put how many MTRRs we have, and clear them out */
+ mov $MTRR_CAP_MSR, %ecx
+ rdmsr
+ movzb %al, %ebx /* Number of variable MTRRs */
+ mov $MTRR_PHYS_BASE_MSR(0), %ecx
+ xor %eax, %eax
+ xor %edx, %edx
+
+clear_var_mtrr:
+ wrmsr
+ inc %ecx
+ wrmsr
+ inc %ecx
+ dec %ebx
+ jnz clear_var_mtrr
+
+ post_code(POST_CAR_UNCACHEABLE)
+
+ /* Configure default memory type to uncacheable (UC) */
+ mov $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ /* Clear enable bits and set default type to UC */
+ and $~(MTRR_DEF_TYPE_MASK | MTRR_DEF_TYPE_EN | \
+ MTRR_DEF_TYPE_FIX_EN), %eax
+ wrmsr
+
+ /*
+ * Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
+ * based on the physical address size supported for this processor
+ * This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
+ *
+ * Examples:
+ * MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing
+ * MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing
+ */
+
+ movl $0x80000008, %eax /* Address sizes leaf */
+ cpuid
+ sub $32, %al
+ movzx %al, %eax
+ xorl %esi, %esi
+ bts %eax, %esi
+ dec %esi /* esi <- MTRR_PHYS_MASK_HIGH */
+
+ post_code(POST_CAR_BASE_ADDRESS)
+
+#if IS_POWER_OF_2(CONFIG_DCACHE_RAM_SIZE)
+ /* Configure CAR region as write-back (WB) */
+ mov $MTRR_PHYS_BASE_MSR(0), %ecx
+ mov $CONFIG_DCACHE_RAM_BASE, %eax
+ or $MTRR_TYPE_WRBACK, %eax
+ xor %edx,%edx
+ wrmsr
+
+ /* Configure the MTRR mask for the size region */
+ mov $MTRR_PHYS_MASK(0), %ecx
+ mov $CONFIG_DCACHE_RAM_SIZE, %eax /* size mask */
+ dec %eax
+ not %eax
+ or $MTRR_PHYS_MASK_VALID, %eax
+ movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
+ wrmsr
+#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
+ /* Configure CAR region as write-back (WB) */
+ mov $MTRR_PHYS_BASE_MSR(0), %ecx
+ mov $CONFIG_DCACHE_RAM_BASE, %eax
+ or $MTRR_TYPE_WRBACK, %eax
+ xor %edx,%edx
+ wrmsr
+
+ mov $MTRR_PHYS_MASK_MSR(0), %ecx
+ mov $(512 * KiB), %eax /* size mask */
+ dec %eax
+ not %eax
+ or $MTRR_PHYS_MASK_VALID, %eax
+ movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
+ wrmsr
+
+ mov $MTRR_PHYS_BASE_MSR(1), %ecx
+ mov $(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
+ or $MTRR_TYPE_WRBACK, %eax
+ xor %edx,%edx
+ wrmsr
+
+ mov $MTRR_PHYS_MASK_MSR(1), %ecx
+ mov $(256 * KiB), %eax /* size mask */
+ dec %eax
+ not %eax
+ or $MTRR_PHYS_MASK_VALID, %eax
+ movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
+ wrmsr
+#else
+#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
+#endif
+ post_code(POST_CAR_FILL)
+
+ /* Enable variable MTRRs */
+ mov $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ or $MTRR_DEF_TYPE_EN, %eax
+ wrmsr
+
+ /* Enable caching */
+ mov %cr0, %eax
+ and $~(X86_CR0_CD | X86_CR0_NW), %eax
+ invd
+ mov %eax, %cr0
+
+#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
+ jmp car_nem
+#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
+ jmp car_cqos
+#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
+ jmp car_nem_enhanced
+#else
+#error "No CAR mechanism selected:
+#endif
+ jmp car_init_ret
+
+fixed_mtrr_list:
+ .word MTRR_FIX_64K_00000_MSR
+ .word MTRR_FIX_16K_80000_MSR
+ .word MTRR_FIX_16K_A0000_MSR
+ .word MTRR_FIX_4K_C0000_MSR
+ .word MTRR_FIX_4K_C8000_MSR
+ .word MTRR_FIX_4K_D0000_MSR
+ .word MTRR_FIX_4K_D8000_MSR
+ .word MTRR_FIX_4K_E0000_MSR
+ .word MTRR_FIX_4K_E8000_MSR
+ .word MTRR_FIX_4K_F0000_MSR
+ .word MTRR_FIX_4K_F8000_MSR
+fixed_mtrr_list_size = . - fixed_mtrr_list
+
+#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
+.global car_nem
+car_nem:
+ /* Disable cache eviction (setup stage) */
+ mov $MSR_EVICT_CTL, %ecx
+ rdmsr
+ or $0x1, %eax
+ wrmsr
+
+ post_code(0x26)
+
+ /* Clear the cache memory region. This will also fill up the cache */
+ movl $CONFIG_DCACHE_RAM_BASE, %edi
+ movl $CONFIG_DCACHE_RAM_SIZE, %ecx
+ shr $0x02, %ecx
+ xor %eax, %eax
+ cld
+ rep stosl
+
+ post_code(0x27)
+
+ /* Disable cache eviction (run stage) */
+ mov $MSR_EVICT_CTL, %ecx
+ rdmsr
+ or $0x2, %eax
+ wrmsr
+
+ post_code(0x28)
+
+ jmp car_init_ret
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
+.global car_cqos
+car_cqos:
+ /*
+ * Create CBM_LEN_MASK based on CBM_LEN
+ * Get CPUID.(EAX=10H, ECX=2H):EAX.CBM_LEN[bits 4:0]
+ */
+ mov $0x10, %eax
+ mov $0x2, %ecx
+ cpuid
+ and $0x1f, %eax
+ add $1, %al
+
+ mov $1, %ebx
+ mov %al, %cl
+ shl %cl, %ebx
+ sub $1, %ebx
+
+ /* Store the CBM_LEN_MASK in mm3 for later use */
+ movd %ebx, %mm3
+
+ /*
+ * Disable both L1 and L2 prefetcher. For yet-to-understood reason,
+ * prefetchers slow down filling cache with rep stos in CQOS mode.
+ */
+ mov $MSR_PREFETCH_CTL, %ecx
+ rdmsr
+ or $(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
+ wrmsr
+
+#if (CONFIG_DCACHE_RAM_SIZE == CONFIG_L2_CACHE_SIZE)
+/*
+ * If CAR size is set to full L2 size, mask is calculated as all-zeros.
+ * This is not supported by the CPU/uCode.
+ */
+#error "CQOS CAR may not use whole L2 cache area"
+#endif
+
+ /* Calculate how many bits to be used for CAR */
+ xor %edx, %edx
+ mov $CONFIG_DCACHE_RAM_SIZE, %eax /* dividend */
+ mov $CONFIG_CACHE_QOS_SIZE_PER_BIT, %ecx /* divisor */
+ div %ecx /* result is in eax */
+ mov %eax, %ecx /* save to ecx */
+ mov $1, %ebx
+ shl %cl, %ebx
+ sub $1, %ebx /* resulting mask is is in ebx */
+
+ /* Set this mask for initial cache fill */
+ mov $MSR_L2_QOS_MASK(0), %ecx
+ rdmsr
+ mov %ebx, %eax
+ wrmsr
+
+ /* Set CLOS selector to 0 */
+ mov $MSR_IA32_PQR_ASSOC, %ecx
+ rdmsr
+ and $~MSR_IA32_PQR_ASSOC_MASK, %edx /* select mask 0 */
+ wrmsr
+
+ /* We will need to block CAR region from evicts */
+ mov $MSR_L2_QOS_MASK(1), %ecx
+ rdmsr
+ /* Invert bits that are to be used for cache */
+ mov %ebx, %eax
+ xor $~0, %eax /* invert 32 bits */
+
+ /*
+ * Use CBM_LEN_MASK stored in mm3 to set bits based on Capacity Bit
+ * Mask Length.
+ */
+ movd %mm3, %ebx
+ and %ebx, %eax
+ wrmsr
+
+ post_code(0x26)
+
+ /* Clear the cache memory region. This will also fill up the cache */
+ movl $CONFIG_DCACHE_RAM_BASE, %edi
+ movl $CONFIG_DCACHE_RAM_SIZE, %ecx
+ shr $0x02, %ecx
+ xor %eax, %eax
+ cld
+ rep stosl
+
+ post_code(0x27)
+
+ /* Cache is populated. Use mask 1 that will block evicts */
+ mov $MSR_IA32_PQR_ASSOC, %ecx
+ rdmsr
+ and $~MSR_IA32_PQR_ASSOC_MASK, %edx /* clear index bits first */
+ or $1, %edx /* select mask 1 */
+ wrmsr
+
+ /* Enable prefetchers */
+ mov $MSR_PREFETCH_CTL, %ecx
+ rdmsr
+ and $~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
+ wrmsr
+
+ post_code(0x28)
+
+ jmp car_init_ret
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
+.global car_nem_enhanced
+car_nem_enhanced:
+ /* Disable cache eviction (setup stage) */
+ mov $MSR_EVICT_CTL, %ecx
+ rdmsr
+ or $0x1, %eax
+ wrmsr
+ post_code(0x26)
+
+ /* Create n-way set associativity of cache */
+ xorl %edi, %edi
+find_llc_subleaf:
+ movl %edi, %ecx
+ movl $0x04, %eax
+ cpuid
+ inc %edi
+ and $0xe0, %al /* EAX[7:5] = Cache Level */
+ cmp $0x60, %al /* Check to see if it is LLC */
+ jnz find_llc_subleaf
+
+ /*
+ * Set MSR 0xC91 IA32_L3_MASK_! = 0xE/0xFE/0xFFE/0xFFFE
+ * for 4/8/16 way of LLC
+ */
+ shr $22, %ebx
+ inc %ebx
+ /* Calculate n-way associativity of LLC */
+ mov %bl, %cl
+
+ /*
+ * Maximizing RO cacheability while locking in the CAR to a
+ * single way since that particular way won't be victim candidate
+ * for evictions.
+ * This has been done after programing LLC_WAY_MASK_1 MSR
+ * with desired LLC way as mentioned below.
+ *
+ * Hence create Code and Data Size as per request
+ * Code Size (RO) : Up to 16M
+ * Data Size (RW) : Up to 256K
+ */
+ movl $0x01, %eax
+ /*
+ * LLC Ways -> LLC_WAY_MASK_1:
+ * 4: 0x000E
+ * 8: 0x00FE
+ * 12: 0x0FFE
+ * 16: 0xFFFE
+ *
+ * These MSRs contain one bit per each way of LLC
+ * - If this bit is '0' - the way is protected from eviction
+ * - If this bit is '1' - the way is not protected from eviction
+ */
+ shl %cl, %eax
+ subl $0x02, %eax
+ movl $MSR_IA32_L3_MASK_1, %ecx
+ xorl %edx, %edx
+ wrmsr
+ /*
+ * Set MSR 0xC92 IA32_L3_MASK_2 = 0x1
+ *
+ * For SKL SOC, data size remains 256K consistently.
+ * Hence, creating 1-way associative cache for Data
+ */
+ mov $MSR_IA32_L3_MASK_2, %ecx
+ mov $0x01, %eax
+ xorl %edx, %edx
+ wrmsr
+ /*
+ * Set MSR_IA32_PQR_ASSOC = 0x02
+ *
+ * Possible values:
+ * 0: Default value, no way mask should be applied
+ * 1: Apply way mask 1 to LLC
+ * 2: Apply way mask 2 to LLC
+ * 3: Shouldn't be use in NEM Mode
+ */
+ movl $MSR_IA32_PQR_ASSOC, %ecx
+ movl $0x02, %eax
+ xorl %edx, %edx
+ wrmsr
+
+ movl $CONFIG_DCACHE_RAM_BASE, %edi
+ movl $CONFIG_DCACHE_RAM_SIZE, %ecx
+ shr $0x02, %ecx
+ xor %eax, %eax
+ cld
+ rep stosl
+ /*
+ * Set MSR_IA32_PQR_ASSOC = 0x01
+ * At this stage we apply LLC_WAY_MASK_1 to the cache.
+ * i.e. way 0 is protected from eviction.
+ */
+ movl $MSR_IA32_PQR_ASSOC, %ecx
+ movl $0x01, %eax
+ xorl %edx, %edx
+ wrmsr
+
+ post_code(0x27)
+ /*
+ * Enable No-Eviction Mode Run State by setting
+ * NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
+ */
+
+ movl $MSR_EVICT_CTL, %ecx
+ rdmsr
+ orl $0x02, %eax
+ wrmsr
+
+ post_code(0x28)
+
+ jmp car_init_ret
+#endif
+
+#if CONFIG_IS_ENABLED(X86_16BIT_INIT)
+_dt_ucode_base_size:
+ /* These next two fields are filled in by binman */
+.globl ucode_base
+ucode_base: /* Declared in microcode.h */
+ .long 0 /* microcode base */
+.globl ucode_size
+ucode_size: /* Declared in microcode.h */
+ .long 0 /* microcode size */
+ .long CONFIG_SYS_MONITOR_BASE /* code region base */
+ .long CONFIG_SYS_MONITOR_LEN /* code region size */
+#endif
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/car2_uninit.S b/roms/u-boot/arch/x86/cpu/intel_common/car2_uninit.S
new file mode 100644
index 000000000..aba3a5381
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/car2_uninit.S
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2017 Intel Corp.
+ * Copyright 2019 Google LLC
+ * Taken from coreboot file exit_car.S
+ */
+
+#include <config.h>
+#include <asm/msr-index.h>
+#include <asm/mtrr.h>
+
+.text
+.global car_uninit
+car_uninit:
+
+ /*
+ * Retrieve return address from stack as it will get trashed below if
+ * execution is utilizing the cache-as-ram stack.
+ */
+ pop %ebx
+
+ /* Disable MTRRs */
+ mov $(MTRR_DEF_TYPE_MSR), %ecx
+ rdmsr
+ and $(~(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN)), %eax
+ wrmsr
+
+#ifdef CONFIG_INTEL_CAR_NEM
+.global car_nem_teardown
+car_nem_teardown:
+
+ /* invalidate cache contents */
+ invd
+
+ /* Knock down bit 1 then bit 0 of NEM control not combining steps */
+ mov $(MSR_EVICT_CTL), %ecx
+ rdmsr
+ and $(~(1 << 1)), %eax
+ wrmsr
+ and $(~(1 << 0)), %eax
+ wrmsr
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
+.global car_cqos_teardown
+car_cqos_teardown:
+
+ /* Go back to all-evicting mode, set both masks to all-1s */
+ mov $MSR_L2_QOS_MASK(0), %ecx
+ rdmsr
+ mov $~0, %al
+ wrmsr
+
+ mov $MSR_L2_QOS_MASK(1), %ecx
+ rdmsr
+ mov $~0, %al
+ wrmsr
+
+ /* Reset CLOS selector to 0 */
+ mov $MSR_IA32_PQR_ASSOC, %ecx
+ rdmsr
+ and $~MSR_IA32_PQR_ASSOC_MASK, %edx
+ wrmsr
+
+#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
+.global car_nem_enhanced_teardown
+car_nem_enhanced_teardown:
+
+ /* invalidate cache contents */
+ invd
+
+ /* Knock down bit 1 then bit 0 of NEM control not combining steps */
+ mov $(MSR_EVICT_CTL), %ecx
+ rdmsr
+ and $(~(1 << 1)), %eax
+ wrmsr
+ and $(~(1 << 0)), %eax
+ wrmsr
+
+ /* Reset CLOS selector to 0 */
+ mov $IA32_PQR_ASSOC, %ecx
+ rdmsr
+ and $~IA32_PQR_ASSOC_MASK, %edx
+ wrmsr
+#endif
+
+ /* Return to caller */
+ jmp *%ebx
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/cpu.c b/roms/u-boot/arch/x86/cpu/intel_common/cpu.c
new file mode 100644
index 000000000..96d05e2eb
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/cpu.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (c) 2016 Google, Inc
+ * Copyright (C) 2015-2018 Intel Corporation.
+ * Copyright (C) 2018 Siemens AG
+ * Some code taken from coreboot cpulib.c
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <acpi/acpigen.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/lapic.h>
+#include <asm/lpc_common.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/microcode.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int report_bist_failure(void)
+{
+ if (gd->arch.bist != 0) {
+ post_code(POST_BIST_FAILURE);
+ printf("BIST failed: %08x\n", gd->arch.bist);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int cpu_common_init(void)
+{
+ struct udevice *dev, *lpc;
+ int ret;
+
+ /* Halt if there was a built in self test failure */
+ ret = report_bist_failure();
+ if (ret)
+ return ret;
+
+ enable_lapic();
+
+ ret = microcode_update_intel();
+ if (ret && ret != -EEXIST) {
+ debug("%s: Microcode update failure (err=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ /* Enable upper 128bytes of CMOS */
+ writel(1 << 2, RCB_REG(RC));
+
+ /* Early chipset init required before RAM init can work */
+ uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
+
+ ret = uclass_first_device(UCLASS_LPC, &lpc);
+ if (ret)
+ return ret;
+ if (!lpc)
+ return -ENODEV;
+
+ /* Cause the SATA device to do its early init */
+ uclass_first_device(UCLASS_AHCI, &dev);
+
+ return 0;
+}
+
+int cpu_set_flex_ratio_to_tdp_nominal(void)
+{
+ msr_t flex_ratio, msr;
+ u8 nominal_ratio;
+
+ /* Check for Flex Ratio support */
+ flex_ratio = msr_read(MSR_FLEX_RATIO);
+ if (!(flex_ratio.lo & FLEX_RATIO_EN))
+ return -EINVAL;
+
+ /* Check for >0 configurable TDPs */
+ msr = msr_read(MSR_PLATFORM_INFO);
+ if (((msr.hi >> 1) & 3) == 0)
+ return -EINVAL;
+
+ /* Use nominal TDP ratio for flex ratio */
+ msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+ nominal_ratio = msr.lo & 0xff;
+
+ /* See if flex ratio is already set to nominal TDP ratio */
+ if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
+ return 0;
+
+ /* Set flex ratio to nominal TDP ratio */
+ flex_ratio.lo &= ~0xff00;
+ flex_ratio.lo |= nominal_ratio << 8;
+ flex_ratio.lo |= FLEX_RATIO_LOCK;
+ msr_write(MSR_FLEX_RATIO, flex_ratio);
+
+ /* Set flex ratio in soft reset data register bits 11:6 */
+ clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
+ (nominal_ratio & 0x3f) << 6);
+
+ debug("CPU: Soft reset to set up flex ratio\n");
+
+ /* Set soft reset control to use register value */
+ setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
+
+ /* Issue warm reset, will be "CPU only" due to soft reset data */
+ outb(0x0, IO_PORT_RESET);
+ outb(SYS_RST | RST_CPU, IO_PORT_RESET);
+ cpu_hlt();
+
+ /* Not reached */
+ return -EINVAL;
+}
+
+int cpu_intel_get_info(struct cpu_info *info, int bclk)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_PERF_CTL);
+ info->cpu_freq = ((msr.lo >> 8) & 0xff) * bclk * 1000000;
+ info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU |
+ 1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID;
+ info->address_width = cpu_phys_address_size();
+
+ return 0;
+}
+
+int cpu_configure_thermal_target(struct udevice *dev)
+{
+ u32 tcc_offset;
+ msr_t msr;
+ int ret;
+
+ ret = dev_read_u32(dev, "tcc-offset", &tcc_offset);
+ if (!ret)
+ return -ENOENT;
+
+ /* Set TCC activaiton offset if supported */
+ msr = msr_read(MSR_PLATFORM_INFO);
+ if (msr.lo & (1 << 30)) {
+ msr = msr_read(MSR_TEMPERATURE_TARGET);
+ msr.lo &= ~(0xf << 24); /* Bits 27:24 */
+ msr.lo |= (tcc_offset & 0xf) << 24;
+ msr_write(MSR_TEMPERATURE_TARGET, msr);
+ }
+
+ return 0;
+}
+
+void cpu_set_perf_control(uint clk_ratio)
+{
+ msr_t perf_ctl;
+
+ perf_ctl.lo = (clk_ratio & 0xff) << 8;
+ perf_ctl.hi = 0;
+ msr_write(MSR_IA32_PERF_CTL, perf_ctl);
+ debug("CPU: frequency set to %d MHz\n", clk_ratio * INTEL_BCLK_MHZ);
+}
+
+bool cpu_config_tdp_levels(void)
+{
+ msr_t platform_info;
+
+ /* Bits 34:33 indicate how many levels supported */
+ platform_info = msr_read(MSR_PLATFORM_INFO);
+
+ return ((platform_info.hi >> 1) & 3) != 0;
+}
+
+void cpu_set_p_state_to_turbo_ratio(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_TURBO_RATIO_LIMIT);
+ cpu_set_perf_control(msr.lo);
+}
+
+enum burst_mode_t cpu_get_burst_mode_state(void)
+{
+ enum burst_mode_t state;
+ int burst_en, burst_cap;
+ msr_t msr;
+ uint eax;
+
+ eax = cpuid_eax(0x6);
+ burst_cap = eax & 0x2;
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ burst_en = !(msr.hi & BURST_MODE_DISABLE);
+
+ if (!burst_cap && burst_en)
+ state = BURST_MODE_UNAVAILABLE;
+ else if (burst_cap && !burst_en)
+ state = BURST_MODE_DISABLED;
+ else if (burst_cap && burst_en)
+ state = BURST_MODE_ENABLED;
+ else
+ state = BURST_MODE_UNKNOWN;
+
+ return state;
+}
+
+void cpu_set_burst_mode(bool burst_mode)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ if (burst_mode)
+ msr.hi &= ~BURST_MODE_DISABLE;
+ else
+ msr.hi |= BURST_MODE_DISABLE;
+ msr_write(MSR_IA32_MISC_ENABLE, msr);
+}
+
+void cpu_set_eist(bool eist_status)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ if (eist_status)
+ msr.lo |= MISC_ENABLE_ENHANCED_SPEEDSTEP;
+ else
+ msr.lo &= ~MISC_ENABLE_ENHANCED_SPEEDSTEP;
+ msr_write(MSR_IA32_MISC_ENABLE, msr);
+}
+
+int cpu_get_coord_type(void)
+{
+ return HW_ALL;
+}
+
+int cpu_get_min_ratio(void)
+{
+ msr_t msr;
+
+ /* Get bus ratio limits and calculate clock speeds */
+ msr = msr_read(MSR_PLATFORM_INFO);
+
+ return (msr.hi >> 8) & 0xff; /* Max Efficiency Ratio */
+}
+
+int cpu_get_max_ratio(void)
+{
+ u32 ratio_max;
+ msr_t msr;
+
+ if (cpu_config_tdp_levels()) {
+ /* Set max ratio to nominal TDP ratio */
+ msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+ ratio_max = msr.lo & 0xff;
+ } else {
+ msr = msr_read(MSR_PLATFORM_INFO);
+ /* Max Non-Turbo Ratio */
+ ratio_max = (msr.lo >> 8) & 0xff;
+ }
+
+ return ratio_max;
+}
+
+int cpu_get_bus_clock_khz(void)
+{
+ /*
+ * CPU bus clock is set by default here to 100MHz. This function returns
+ * the bus clock in KHz.
+ */
+ return INTEL_BCLK_MHZ * 1000;
+}
+
+int cpu_get_power_max(void)
+{
+ int power_unit;
+ msr_t msr;
+
+ msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
+ power_unit = 2 << ((msr.lo & 0xf) - 1);
+ msr = msr_read(MSR_PKG_POWER_SKU);
+
+ return (msr.lo & 0x7fff) * 1000 / power_unit;
+}
+
+int cpu_get_max_turbo_ratio(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_TURBO_RATIO_LIMIT);
+
+ return msr.lo & 0xff;
+}
+
+int cpu_get_cores_per_package(void)
+{
+ struct cpuid_result result;
+ int cores = 1;
+
+ if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
+ return 1;
+
+ result = cpuid_ext(0xb, 1);
+ cores = result.ebx & 0xff;
+
+ return cores;
+}
+
+void cpu_mca_configure(void)
+{
+ msr_t msr;
+ int i;
+ int num_banks;
+
+ msr = msr_read(MSR_IA32_MCG_CAP);
+ num_banks = msr.lo & 0xff;
+ msr.lo = 0;
+ msr.hi = 0;
+ for (i = 0; i < num_banks; i++) {
+ /* Clear the machine check status */
+ msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
+ /* Initialise machine checks */
+ msr_write(MSR_IA32_MC0_CTL + i * 4,
+ (msr_t) {.lo = 0xffffffff, .hi = 0xffffffff});
+ }
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/cpu_from_spl.c b/roms/u-boot/arch/x86/cpu/intel_common/cpu_from_spl.c
new file mode 100644
index 000000000..1c0dcedb5
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/cpu_from_spl.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <handoff.h>
+#include <init.h>
+#include <asm/cpu_common.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/lapic.h>
+#include <asm/lpc_common.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/microcode.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_cpu_init(void)
+{
+ int ret;
+
+#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB)
+ struct spl_handoff *ho = gd->spl_handoff;
+
+ gd->arch.hob_list = ho->arch.hob_list;
+#endif
+ ret = x86_cpu_reinit_f();
+
+ return ret;
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/fast_spi.c b/roms/u-boot/arch/x86/cpu/intel_common/fast_spi.c
new file mode 100644
index 000000000..5d3944dee
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/fast_spi.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/cpu_common.h>
+#include <asm/fast_spi.h>
+#include <asm/pci.h>
+
+/*
+ * Returns bios_start and fills in size of the BIOS region.
+ */
+static ulong fast_spi_get_bios_region(struct fast_spi_regs *regs,
+ uint *bios_size)
+{
+ ulong bios_start, bios_end;
+
+ /*
+ * BIOS_BFPREG provides info about BIOS-Flash Primary Region Base and
+ * Limit. Base and Limit fields are in units of 4K.
+ */
+ u32 val = readl(&regs->bfp);
+
+ bios_start = (val & SPIBAR_BFPREG_PRB_MASK) << 12;
+ bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
+ SPIBAR_BFPREG_PRL_SHIFT) + 1) << 12;
+ *bios_size = bios_end - bios_start;
+
+ return bios_start;
+}
+
+int fast_spi_get_bios_mmap_regs(struct fast_spi_regs *regs, ulong *map_basep,
+ uint *map_sizep, uint *offsetp)
+{
+ ulong base;
+
+ base = fast_spi_get_bios_region(regs, map_sizep);
+ *map_basep = (u32)-*map_sizep - base;
+ *offsetp = base;
+
+ return 0;
+}
+
+int fast_spi_get_bios_mmap(pci_dev_t pdev, ulong *map_basep, uint *map_sizep,
+ uint *offsetp)
+{
+ struct fast_spi_regs *regs;
+ ulong bar, mmio_base;
+
+ /* Special case to find mapping without probing the device */
+ pci_x86_read_config(pdev, PCI_BASE_ADDRESS_0, &bar, PCI_SIZE_32);
+ mmio_base = bar & PCI_BASE_ADDRESS_MEM_MASK;
+ regs = (struct fast_spi_regs *)mmio_base;
+
+ return fast_spi_get_bios_mmap_regs(regs, map_basep, map_sizep, offsetp);
+}
+
+int fast_spi_early_init(pci_dev_t pdev, ulong mmio_base)
+{
+ /* Program Temporary BAR for SPI */
+ pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
+ mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY,
+ PCI_SIZE_32);
+
+ /* Enable Bus Master and MMIO Space */
+ pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY, PCI_SIZE_8);
+
+ /*
+ * Disable the BIOS write protect so write commands are allowed.
+ * Enable Prefetching and caching.
+ */
+ pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
+ SPIBAR_BIOS_CONTROL_EISS |
+ SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
+ SPIBAR_BIOS_CONTROL_WPD |
+ SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/generic_wifi.c b/roms/u-boot/arch/x86/cpu/intel_common/generic_wifi.c
new file mode 100644
index 000000000..61ec5391b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/generic_wifi.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generic WiFi ACPI info
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/drivers/wifi/generic.c
+ */
+
+#include <common.h>
+#include <log.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_device.h>
+#include <dm.h>
+#include <dm/acpi.h>
+
+/* WRDS Spec Revision */
+#define WRDS_REVISION 0x0
+
+/* EWRD Spec Revision */
+#define EWRD_REVISION 0x0
+
+/* WRDS Domain type */
+#define WRDS_DOMAIN_TYPE_WIFI 0x7
+
+/* EWRD Domain type */
+#define EWRD_DOMAIN_TYPE_WIFI 0x7
+
+/* WGDS Domain type */
+#define WGDS_DOMAIN_TYPE_WIFI 0x7
+
+/*
+ * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
+ * The above representation returns unique and consistent name every time
+ * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
+ * chosen since it contains the bus address of the device.
+ */
+#define WIFI_ACPI_NAME_MAX_LEN 5
+
+/**
+ * struct generic_wifi_config - Data structure to contain common wifi config
+ * @wake: Wake pin for ACPI _PRW
+ * @maxsleep: Maximum sleep state to wake from
+ */
+struct generic_wifi_config {
+ unsigned int wake;
+ unsigned int maxsleep;
+};
+
+static int generic_wifi_fill_ssdt(struct acpi_ctx *ctx,
+ const struct udevice *dev,
+ const struct generic_wifi_config *config)
+{
+ char name[ACPI_NAME_MAX];
+ char path[ACPI_PATH_MAX];
+ pci_dev_t bdf;
+ u32 address;
+ int ret;
+
+ ret = acpi_device_path(dev_get_parent(dev), path, sizeof(path));
+ if (ret)
+ return log_msg_ret("path", ret);
+ ret = acpi_get_name(dev, name);
+ if (ret)
+ return log_msg_ret("name", ret);
+
+ /* Device */
+ acpigen_write_scope(ctx, path);
+ acpigen_write_device(ctx, name);
+ acpigen_write_name_integer(ctx, "_UID", 0);
+ acpigen_write_name_string(ctx, "_DDN",
+ dev_read_string(dev, "acpi,ddn"));
+
+ /* Address */
+ bdf = dm_pci_get_bdf(dev);
+ address = (PCI_DEV(bdf) << 16) | PCI_FUNC(bdf);
+ acpigen_write_name_dword(ctx, "_ADR", address);
+
+ /* Wake capabilities */
+ if (config)
+ acpigen_write_prw(ctx, config->wake, config->maxsleep);
+
+ acpigen_pop_len(ctx); /* Device */
+ acpigen_pop_len(ctx); /* Scope */
+
+ return 0;
+}
+
+static int intel_wifi_acpi_fill_ssdt(const struct udevice *dev,
+ struct acpi_ctx *ctx)
+{
+ struct generic_wifi_config config;
+ bool have_config;
+ int ret;
+
+ ret = dev_read_u32(dev, "acpi,wake", &config.wake);
+ have_config = !ret;
+ /* By default, all intel wifi chips wake from S3 */
+ config.maxsleep = 3;
+ ret = generic_wifi_fill_ssdt(ctx, dev, have_config ? &config : NULL);
+ if (ret)
+ return log_msg_ret("wifi", ret);
+
+ return 0;
+}
+
+struct acpi_ops wifi_acpi_ops = {
+ .fill_ssdt = intel_wifi_acpi_fill_ssdt,
+};
+
+static const struct udevice_id intel_wifi_ids[] = {
+ { .compatible = "intel,generic-wifi" },
+ { }
+};
+
+U_BOOT_DRIVER(intel_wifi) = {
+ .name = "intel_wifi",
+ .id = UCLASS_MISC,
+ .of_match = intel_wifi_ids,
+ ACPI_OPS_PTR(&wifi_acpi_ops)
+};
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/intel_opregion.c b/roms/u-boot/arch/x86/cpu/intel_common/intel_opregion.c
new file mode 100644
index 000000000..1eed21d8c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/intel_opregion.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Writing IntelGraphicsMem table for ACPI
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/soc/intel/gma/opregion.c
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <bloblist.h>
+#include <dm.h>
+#include <spi_flash.h>
+#include <asm/intel_opregion.h>
+
+static char vbt_data[8 << 10];
+
+static int locate_vbt(char **vbtp, int *sizep)
+{
+ struct binman_entry vbt;
+ struct udevice *dev;
+ u32 vbtsig = 0;
+ int size;
+ int ret;
+
+ ret = binman_entry_find("intel-vbt", &vbt);
+ if (ret)
+ return log_msg_ret("find VBT", ret);
+ ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
+ if (ret)
+ return log_msg_ret("find flash", ret);
+ size = vbt.size;
+ if (size > sizeof(vbt_data))
+ return log_msg_ret("vbt", -E2BIG);
+ ret = spi_flash_read_dm(dev, vbt.image_pos, size, vbt_data);
+ if (ret)
+ return log_msg_ret("read", ret);
+
+ memcpy(&vbtsig, vbt_data, sizeof(vbtsig));
+ if (vbtsig != VBT_SIGNATURE) {
+ log_err("Missing/invalid signature in VBT data file!\n");
+ return -EINVAL;
+ }
+
+ log_debug("Found a VBT of %u bytes\n", size);
+ *sizep = size;
+ *vbtp = vbt_data;
+
+ return 0;
+}
+
+/* Write ASLS PCI register and prepare SWSCI register */
+static int intel_gma_opregion_register(struct udevice *dev, ulong opregion)
+{
+ int sci_reg;
+
+ if (!device_active(dev))
+ return -ENOENT;
+
+ /*
+ * Intel BIOS Specification
+ * Chapter 5.3.7 "Initialise Hardware State"
+ */
+ dm_pci_write_config32(dev, ASLS, opregion);
+
+ /*
+ * Atom-based platforms use a combined SMI/SCI register,
+ * whereas non-Atom platforms use a separate SCI register
+ */
+ if (IS_ENABLED(CONFIG_INTEL_GMA_SWSMISCI))
+ sci_reg = SWSMISCI;
+ else
+ sci_reg = SWSCI;
+
+ /*
+ * Intel's Windows driver relies on this:
+ * Intel BIOS Specification
+ * Chapter 5.4 "ASL Software SCI Handler"
+ */
+ dm_pci_clrset_config16(dev, sci_reg, GSSCIE, SMISCISEL);
+
+ return 0;
+}
+
+int intel_gma_init_igd_opregion(struct udevice *dev,
+ struct igd_opregion *opregion)
+{
+ struct optionrom_vbt *vbt = NULL;
+ char *vbt_buf;
+ int vbt_size;
+ int ret;
+
+ ret = locate_vbt(&vbt_buf, &vbt_size);
+ if (ret) {
+ log_err("GMA: VBT couldn't be found\n");
+ return log_msg_ret("find vbt", ret);
+ }
+ vbt = (struct optionrom_vbt *)vbt_buf;
+
+ memset(opregion, '\0', sizeof(struct igd_opregion));
+
+ memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE,
+ sizeof(opregion->header.signature));
+ memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild,
+ ARRAY_SIZE(vbt->coreblock_biosbuild));
+ /* Extended VBT support */
+ if (vbt->hdr_vbt_size > sizeof(opregion->vbt.gvd1)) {
+ struct optionrom_vbt *ext_vbt;
+
+ ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT,
+ vbt->hdr_vbt_size, 0,
+ (void **)&ext_vbt);
+ if (ret) {
+ log_err("GMA: Unable to add Ext VBT to bloblist\n");
+ return log_msg_ret("blob", ret);
+ }
+
+ memcpy(ext_vbt, vbt, vbt->hdr_vbt_size);
+ opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+ opregion->mailbox3.rvds = vbt->hdr_vbt_size;
+ } else {
+ /* Raw VBT size which can fit in gvd1 */
+ printf("copy to %p\n", opregion->vbt.gvd1);
+ memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size);
+ }
+
+ /* 8kb */
+ opregion->header.size = sizeof(struct igd_opregion) / 1024;
+
+ /*
+ * Left-shift version field to accommodate Intel Windows driver quirk
+ * when not using a VBIOS.
+ * Required for Legacy boot + NGI, UEFI + NGI, and UEFI + GOP driver.
+ *
+ * No adverse effects when using VBIOS or booting Linux.
+ */
+ opregion->header.version = IGD_OPREGION_VERSION << 24;
+
+ /* We just assume we're mobile for now */
+ opregion->header.mailboxes = MAILBOXES_MOBILE;
+
+ /* Initialise Mailbox 1 */
+ opregion->mailbox1.clid = 1;
+
+ /* Initialise Mailbox 3 */
+ opregion->mailbox3.bclp = IGD_BACKLIGHT_BRIGHTNESS;
+ opregion->mailbox3.pfit = IGD_FIELD_VALID | IGD_PFIT_STRETCH;
+ opregion->mailbox3.pcft = 0; /* should be (IMON << 1) & 0x3e */
+ opregion->mailbox3.cblv = IGD_FIELD_VALID | IGD_INITIAL_BRIGHTNESS;
+ opregion->mailbox3.bclm[0] = IGD_WORD_FIELD_VALID + 0x0000;
+ opregion->mailbox3.bclm[1] = IGD_WORD_FIELD_VALID + 0x0a19;
+ opregion->mailbox3.bclm[2] = IGD_WORD_FIELD_VALID + 0x1433;
+ opregion->mailbox3.bclm[3] = IGD_WORD_FIELD_VALID + 0x1e4c;
+ opregion->mailbox3.bclm[4] = IGD_WORD_FIELD_VALID + 0x2866;
+ opregion->mailbox3.bclm[5] = IGD_WORD_FIELD_VALID + 0x327f;
+ opregion->mailbox3.bclm[6] = IGD_WORD_FIELD_VALID + 0x3c99;
+ opregion->mailbox3.bclm[7] = IGD_WORD_FIELD_VALID + 0x46b2;
+ opregion->mailbox3.bclm[8] = IGD_WORD_FIELD_VALID + 0x50cc;
+ opregion->mailbox3.bclm[9] = IGD_WORD_FIELD_VALID + 0x5ae5;
+ opregion->mailbox3.bclm[10] = IGD_WORD_FIELD_VALID + 0x64ff;
+
+ /* Write ASLS PCI register and prepare SWSCI register */
+ ret = intel_gma_opregion_register(dev, (ulong)opregion);
+ if (ret)
+ return log_msg_ret("write asls", ret);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/itss.c b/roms/u-boot/arch/x86/cpu/intel_common/itss.c
new file mode 100644
index 000000000..1eff03098
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/itss.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interrupt Timer Subsystem
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ * Copyright (C) 2017 Siemens AG
+ * Copyright 2019 Google LLC
+ *
+ * Taken from coreboot itss.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <irq.h>
+#include <log.h>
+#include <malloc.h>
+#include <p2sb.h>
+#include <spl.h>
+#include <asm/global_data.h>
+#include <asm/itss.h>
+
+static int set_polarity(struct udevice *dev, uint irq, bool active_low)
+{
+ u32 mask;
+ uint reg;
+
+ if (irq > ITSS_MAX_IRQ)
+ return -EINVAL;
+
+ reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * (irq / IRQS_PER_IPC);
+ mask = 1 << (irq % IRQS_PER_IPC);
+
+ pcr_clrsetbits32(dev, reg, mask, active_low ? mask : 0);
+
+ return 0;
+}
+
+#ifndef CONFIG_TPL_BUILD
+static int snapshot_polarities(struct udevice *dev)
+{
+ struct itss_priv *priv = dev_get_priv(dev);
+ const int start = GPIO_IRQ_START;
+ const int end = GPIO_IRQ_END;
+ int reg_start;
+ int reg_end;
+ int i;
+
+ reg_start = start / IRQS_PER_IPC;
+ reg_end = DIV_ROUND_UP(end, IRQS_PER_IPC);
+
+ log_debug("ITSS IRQ Polarities snapshot %p\n", priv->irq_snapshot);
+ for (i = reg_start; i < reg_end; i++) {
+ uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+
+ priv->irq_snapshot[i] = pcr_read32(dev, reg);
+ log_debug(" - %d, reg %x: irq_snapshot[i] %x\n", i, reg,
+ priv->irq_snapshot[i]);
+ }
+
+ /* Save the snapshot for use after relocation */
+ gd->start_addr_sp -= sizeof(*priv);
+ gd->start_addr_sp &= ~0xf;
+ gd->arch.itss_priv = (void *)gd->start_addr_sp;
+ memcpy(gd->arch.itss_priv, priv, sizeof(*priv));
+
+ return 0;
+}
+
+static void show_polarities(struct udevice *dev, const char *msg)
+{
+ int i;
+
+ log_debug("ITSS IRQ Polarities %s:\n", msg);
+ for (i = 0; i < NUM_IPC_REGS; i++) {
+ uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+
+ log_debug("IPC%d: 0x%08x\n", i, pcr_read32(dev, reg));
+ }
+}
+
+static int restore_polarities(struct udevice *dev)
+{
+ struct itss_priv *priv = dev_get_priv(dev);
+ struct itss_priv *old_priv;
+ const int start = GPIO_IRQ_START;
+ const int end = GPIO_IRQ_END;
+ int reg_start;
+ int reg_end;
+ int i;
+
+ /* Get the snapshot which was stored by the pre-reloc device */
+ old_priv = gd->arch.itss_priv;
+ if (!old_priv)
+ return log_msg_ret("priv", -EFAULT);
+ memcpy(priv->irq_snapshot, old_priv->irq_snapshot,
+ sizeof(priv->irq_snapshot));
+
+ show_polarities(dev, "Before");
+ log_debug("priv->irq_snapshot %p\n", priv->irq_snapshot);
+
+ reg_start = start / IRQS_PER_IPC;
+ reg_end = DIV_ROUND_UP(end, IRQS_PER_IPC);
+
+
+ for (i = reg_start; i < reg_end; i++) {
+ u32 mask;
+ u16 reg;
+ int irq_start;
+ int irq_end;
+
+ irq_start = i * IRQS_PER_IPC;
+ irq_end = min(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ);
+
+ if (start > irq_end)
+ continue;
+ if (end < irq_start)
+ break;
+
+ /* Track bits within the bounds of of the register */
+ irq_start = max(start, irq_start) % IRQS_PER_IPC;
+ irq_end = min(end, irq_end) % IRQS_PER_IPC;
+
+ /* Create bitmask of the inclusive range of start and end */
+ mask = (((1U << irq_end) - 1) | (1U << irq_end));
+ mask &= ~((1U << irq_start) - 1);
+
+ reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+ log_debug(" - %d, reg %x: mask %x, irq_snapshot[i] %x\n",
+ i, reg, mask, priv->irq_snapshot[i]);
+ pcr_clrsetbits32(dev, reg, mask, mask & priv->irq_snapshot[i]);
+ }
+
+ show_polarities(dev, "After");
+
+ return 0;
+}
+#endif
+
+static int route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
+{
+ struct itss_priv *priv = dev_get_priv(dev);
+ struct pmc_route *route;
+ int i;
+
+ for (i = 0, route = priv->route; i < priv->route_count; i++, route++) {
+ if (pmc_gpe_num == route->pmc)
+ return route->gpio;
+ }
+
+ return -ENOENT;
+}
+
+static int itss_bind(struct udevice *dev)
+{
+ /* This is not set with basic of-platdata, so set it manually */
+ if (CONFIG_IS_ENABLED(OF_PLATDATA) &&
+ !CONFIG_IS_ENABLED(OF_PLATDATA_INST))
+ dev->driver_data = X86_IRQT_ITSS;
+
+ return 0;
+}
+
+static int itss_of_to_plat(struct udevice *dev)
+{
+ struct itss_priv *priv = dev_get_priv(dev);
+ int ret;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct itss_plat *plat = dev_get_plat(dev);
+ struct dtd_intel_itss *dtplat = &plat->dtplat;
+
+ /*
+ * It would be nice to do this in the bind() method, but with
+ * of-platdata binding happens in the order that DM finds things in the
+ * linker list (i.e. alphabetical order by driver name). So the GPIO
+ * device may well be bound before its parent (p2sb), and this call
+ * will fail if p2sb is not bound yet.
+ *
+ * TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc
+ */
+ ret = p2sb_set_port_id(dev, dtplat->intel_p2sb_port_id);
+ if (ret)
+ return log_msg_ret("Could not set port id", ret);
+ priv->route = (struct pmc_route *)dtplat->intel_pmc_routes;
+ priv->route_count = ARRAY_SIZE(dtplat->intel_pmc_routes) /
+ sizeof(struct pmc_route);
+#else
+ int size;
+
+ size = dev_read_size(dev, "intel,pmc-routes");
+ if (size < 0)
+ return size;
+ priv->route = malloc(size);
+ if (!priv->route)
+ return -ENOMEM;
+ ret = dev_read_u32_array(dev, "intel,pmc-routes", (u32 *)priv->route,
+ size / sizeof(fdt32_t));
+ if (ret)
+ return log_msg_ret("Cannot read pmc-routes", ret);
+ priv->route_count = size / sizeof(struct pmc_route);
+#endif
+
+ return 0;
+}
+
+static const struct irq_ops itss_ops = {
+ .route_pmc_gpio_gpe = route_pmc_gpio_gpe,
+ .set_polarity = set_polarity,
+#ifndef CONFIG_TPL_BUILD
+ .snapshot_polarities = snapshot_polarities,
+ .restore_polarities = restore_polarities,
+#endif
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id itss_ids[] = {
+ { .compatible = "intel,itss", .data = X86_IRQT_ITSS },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(intel_itss) = {
+ .name = "intel_itss",
+ .id = UCLASS_IRQ,
+ .of_match = of_match_ptr(itss_ids),
+ .ops = &itss_ops,
+ .bind = itss_bind,
+ .of_to_plat = itss_of_to_plat,
+ .plat_auto = sizeof(struct itss_plat),
+ .priv_auto = sizeof(struct itss_priv),
+};
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/lpc.c b/roms/u-boot/arch/x86/cpu/intel_common/lpc.c
new file mode 100644
index 000000000..f31fddb6f
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/lpc.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <pch.h>
+#include <pci.h>
+#include <asm/global_data.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/lpc_common.h>
+#include <linux/bitops.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Enable Prefetching and Caching */
+static void enable_spi_prefetch(struct udevice *pch)
+{
+ u8 reg8;
+
+ dm_pci_read_config8(pch, 0xdc, &reg8);
+ reg8 &= ~(3 << 2);
+ reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
+ dm_pci_write_config8(pch, 0xdc, reg8);
+}
+
+static void enable_port80_on_lpc(struct udevice *pch)
+{
+ /* Enable port 80 POST on LPC */
+ dm_pci_write_config32(pch, PCH_RCBA_BASE, RCB_BASE_ADDRESS | 1);
+ clrbits_le32(RCB_REG(GCS), 4);
+}
+
+/**
+ * lpc_early_init() - set up LPC serial ports and other early things
+ *
+ * @dev: LPC device
+ * @return 0 if OK, -ve on error
+ */
+int lpc_common_early_init(struct udevice *dev)
+{
+ struct udevice *pch = dev->parent;
+ struct reg_info {
+ u32 base;
+ u32 size;
+ } values[4], *ptr;
+ int count;
+ int i;
+
+ count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev),
+ "intel,gen-dec", (u32 *)values,
+ sizeof(values) / (sizeof(u32)));
+ if (count < 0)
+ return -EINVAL;
+
+ /* Set COM1/COM2 decode range */
+ dm_pci_write_config16(pch, LPC_IO_DEC, 0x0010);
+
+ /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */
+ dm_pci_write_config16(pch, LPC_EN, KBC_LPC_EN | MC_LPC_EN |
+ GAMEL_LPC_EN | COMA_LPC_EN);
+
+ /* Write all registers but use 0 if we run out of data */
+ count = count * sizeof(u32) / sizeof(values[0]);
+ for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) {
+ u32 reg = 0;
+
+ if (i < count)
+ reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16);
+ dm_pci_write_config32(pch, LPC_GENX_DEC(i), reg);
+ }
+
+ enable_spi_prefetch(pch);
+
+ /* This is already done in start.S, but let's do it in C */
+ enable_port80_on_lpc(pch);
+
+ return 0;
+}
+
+int lpc_set_spi_protect(struct udevice *dev, int bios_ctrl, bool protect)
+{
+ uint8_t bios_cntl;
+
+ /* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */
+ dm_pci_read_config8(dev, bios_ctrl, &bios_cntl);
+ if (protect) {
+ bios_cntl &= ~BIOS_CTRL_BIOSWE;
+ bios_cntl |= BIT(5);
+ } else {
+ bios_cntl |= BIOS_CTRL_BIOSWE;
+ bios_cntl &= ~BIT(5);
+ }
+ dm_pci_write_config8(dev, bios_ctrl, bios_cntl);
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/lpss.c b/roms/u-boot/arch/x86/cpu/intel_common/lpss.c
new file mode 100644
index 000000000..26a2d2d1e
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/lpss.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Special driver to handle of-platdata
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Some code from coreboot lpss.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/lpss.h>
+
+enum {
+ LPSS_RESET_CTL_REG = 0x204,
+
+ /*
+ * Bit 1:0 controls LPSS controller reset.
+ *
+ * 00 ->LPSS Host Controller is in reset (Reset Asserted)
+ * 01/10 ->Reserved
+ * 11 ->LPSS Host Controller is NOT at reset (Reset Released)
+ */
+ LPSS_CNT_RST_RELEASE = 3,
+
+ /* Power management control and status register */
+ PME_CTRL_STATUS = 0x84,
+
+ /* Bit 1:0 Powerstate, controls D0 and D3 state */
+ POWER_STATE_MASK = 3,
+};
+
+/* Take controller out of reset */
+void lpss_reset_release(void *regs)
+{
+ writel(LPSS_CNT_RST_RELEASE, regs + LPSS_RESET_CTL_REG);
+}
+
+void lpss_set_power_state(struct udevice *dev, enum lpss_pwr_state state)
+{
+ dm_pci_clrset_config8(dev, PME_CTRL_STATUS, POWER_STATE_MASK, state);
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/me_status.c b/roms/u-boot/arch/x86/cpu/intel_common/me_status.c
new file mode 100644
index 000000000..abc5f6fbc
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/me_status.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/me_status.c
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ */
+
+#include <common.h>
+#include <log.h>
+#include <asm/arch/me.h>
+
+/* HFS1[3:0] Current Working State Values */
+static const char *const me_cws_values[] = {
+ [ME_HFS_CWS_RESET] = "Reset",
+ [ME_HFS_CWS_INIT] = "Initializing",
+ [ME_HFS_CWS_REC] = "Recovery",
+ [ME_HFS_CWS_NORMAL] = "Normal",
+ [ME_HFS_CWS_WAIT] = "Platform Disable Wait",
+ [ME_HFS_CWS_TRANS] = "OP State Transition",
+ [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In"
+};
+
+/* HFS1[8:6] Current Operation State Values */
+static const char *const me_opstate_values[] = {
+ [ME_HFS_STATE_PREBOOT] = "Preboot",
+ [ME_HFS_STATE_M0_UMA] = "M0 with UMA",
+ [ME_HFS_STATE_M3] = "M3 without UMA",
+ [ME_HFS_STATE_M0] = "M0 without UMA",
+ [ME_HFS_STATE_BRINGUP] = "Bring up",
+ [ME_HFS_STATE_ERROR] = "M0 without UMA but with error"
+};
+
+/* HFS[19:16] Current Operation Mode Values */
+static const char *const me_opmode_values[] = {
+ [ME_HFS_MODE_NORMAL] = "Normal",
+ [ME_HFS_MODE_DEBUG] = "Debug",
+ [ME_HFS_MODE_DIS] = "Soft Temporary Disable",
+ [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper",
+ [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message"
+};
+
+/* HFS[15:12] Error Code Values */
+static const char *const me_error_values[] = {
+ [ME_HFS_ERROR_NONE] = "No Error",
+ [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure",
+ [ME_HFS_ERROR_IMAGE] = "Image Failure",
+ [ME_HFS_ERROR_DEBUG] = "Debug Failure"
+};
+
+/* GMES[31:28] ME Progress Code */
+static const char *const me_progress_values[] = {
+ [ME_GMES_PHASE_ROM] = "ROM Phase",
+ [ME_GMES_PHASE_BUP] = "BUP Phase",
+ [ME_GMES_PHASE_UKERNEL] = "uKernel Phase",
+ [ME_GMES_PHASE_POLICY] = "Policy Module",
+ [ME_GMES_PHASE_MODULE] = "Module Loading",
+ [ME_GMES_PHASE_UNKNOWN] = "Unknown",
+ [ME_GMES_PHASE_HOST] = "Host Communication"
+};
+
+/* GMES[27:24] Power Management Event */
+static const char *const me_pmevent_values[] = {
+ [0x00] = "Clean Moff->Mx wake",
+ [0x01] = "Moff->Mx wake after an error",
+ [0x02] = "Clean global reset",
+ [0x03] = "Global reset after an error",
+ [0x04] = "Clean Intel ME reset",
+ [0x05] = "Intel ME reset due to exception",
+ [0x06] = "Pseudo-global reset",
+ [0x07] = "S0/M0->Sx/M3",
+ [0x08] = "Sx/M3->S0/M0",
+ [0x09] = "Non-power cycle reset",
+ [0x0a] = "Power cycle reset through M3",
+ [0x0b] = "Power cycle reset through Moff",
+ [0x0c] = "Sx/Mx->Sx/Moff"
+};
+
+/* Progress Code 0 states */
+static const char *const me_progress_rom_values[] = {
+ [0x00] = "BEGIN",
+ [0x06] = "DISABLE"
+};
+
+/* Progress Code 1 states */
+static const char *const me_progress_bup_values[] = {
+ [0x00] = "Initialization starts",
+ [0x01] = "Disable the host wake event",
+ [0x04] = "Flow determination start process",
+ [0x08] = "Error reading/matching the VSCC table in the descriptor",
+ [0x0a] = "Check to see if straps say ME DISABLED",
+ [0x0b] = "Timeout waiting for PWROK",
+ [0x0d] = "Possibly handle BUP manufacturing override strap",
+ [0x11] = "Bringup in M3",
+ [0x12] = "Bringup in M0",
+ [0x13] = "Flow detection error",
+ [0x15] = "M3 clock switching error",
+ [0x18] = "M3 kernel load",
+ [0x1c] = "T34 missing - cannot program ICC",
+ [0x1f] = "Waiting for DID BIOS message",
+ [0x20] = "Waiting for DID BIOS message failure",
+ [0x21] = "DID reported an error",
+ [0x22] = "Enabling UMA",
+ [0x23] = "Enabling UMA error",
+ [0x24] = "Sending DID Ack to BIOS",
+ [0x25] = "Sending DID Ack to BIOS error",
+ [0x26] = "Switching clocks in M0",
+ [0x27] = "Switching clocks in M0 error",
+ [0x28] = "ME in temp disable",
+ [0x32] = "M0 kernel load",
+};
+
+/* Progress Code 3 states */
+static const char *const me_progress_policy_values[] = {
+ [0x00] = "Entery into Policy Module",
+ [0x03] = "Received S3 entry",
+ [0x04] = "Received S4 entry",
+ [0x05] = "Received S5 entry",
+ [0x06] = "Received UPD entry",
+ [0x07] = "Received PCR entry",
+ [0x08] = "Received NPCR entry",
+ [0x09] = "Received host wake",
+ [0x0a] = "Received AC<>DC switch",
+ [0x0b] = "Received DRAM Init Done",
+ [0x0c] = "VSCC Data not found for flash device",
+ [0x0d] = "VSCC Table is not valid",
+ [0x0e] = "Flash Partition Boundary is outside address space",
+ [0x0f] = "ME cannot access the chipset descriptor region",
+ [0x10] = "Required VSCC values for flash parts do not match",
+};
+
+
+/**
+ * _intel_me_status() - Check Intel Management Engine status
+ *
+ * struct hfs: Firmware status
+ * struct gmes: Management engine status
+ */
+static void _intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes)
+{
+ /* Check Current States */
+ debug("ME: FW Partition Table : %s\n",
+ hfs->fpt_bad ? "BAD" : "OK");
+ debug("ME: Bringup Loader Failure : %s\n",
+ hfs->ft_bup_ld_flr ? "YES" : "NO");
+ debug("ME: Firmware Init Complete : %s\n",
+ hfs->fw_init_complete ? "YES" : "NO");
+ debug("ME: Manufacturing Mode : %s\n",
+ hfs->mfg_mode ? "YES" : "NO");
+ debug("ME: Boot Options Present : %s\n",
+ hfs->boot_options_present ? "YES" : "NO");
+ debug("ME: Update In Progress : %s\n",
+ hfs->update_in_progress ? "YES" : "NO");
+ debug("ME: Current Working State : %s\n",
+ me_cws_values[hfs->working_state]);
+ debug("ME: Current Operation State : %s\n",
+ me_opstate_values[hfs->operation_state]);
+ debug("ME: Current Operation Mode : %s\n",
+ me_opmode_values[hfs->operation_mode]);
+ debug("ME: Error Code : %s\n",
+ me_error_values[hfs->error_code]);
+ debug("ME: Progress Phase : %s\n",
+ me_progress_values[gmes->progress_code]);
+ debug("ME: Power Management Event : %s\n",
+ me_pmevent_values[gmes->current_pmevent]);
+
+ debug("ME: Progress Phase State : ");
+ switch (gmes->progress_code) {
+ case ME_GMES_PHASE_ROM: /* ROM Phase */
+ debug("%s", me_progress_rom_values[gmes->current_state]);
+ break;
+
+ case ME_GMES_PHASE_BUP: /* Bringup Phase */
+ if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values) &&
+ me_progress_bup_values[gmes->current_state])
+ debug("%s",
+ me_progress_bup_values[gmes->current_state]);
+ else
+ debug("0x%02x", gmes->current_state);
+ break;
+
+ case ME_GMES_PHASE_POLICY: /* Policy Module Phase */
+ if (gmes->current_state <
+ ARRAY_SIZE(me_progress_policy_values) &&
+ me_progress_policy_values[gmes->current_state])
+ debug("%s",
+ me_progress_policy_values[gmes->current_state]);
+ else
+ debug("0x%02x", gmes->current_state);
+ break;
+
+ case ME_GMES_PHASE_HOST: /* Host Communication Phase */
+ if (!gmes->current_state)
+ debug("Host communication established");
+ else
+ debug("0x%02x", gmes->current_state);
+ break;
+
+ default:
+ debug("Unknown 0x%02x", gmes->current_state);
+ }
+ debug("\n");
+}
+
+void intel_me_status(struct udevice *me_dev)
+{
+ struct me_hfs hfs;
+ struct me_gmes gmes;
+
+ pci_read_dword_ptr(me_dev, &hfs, PCI_ME_HFS);
+ pci_read_dword_ptr(me_dev, &gmes, PCI_ME_GMES);
+
+ _intel_me_status(&hfs, &gmes);
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/microcode.c b/roms/u-boot/arch/x86/cpu/intel_common/microcode.c
new file mode 100644
index 000000000..4d8e1d210
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/microcode.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2014 Google, Inc
+ * Copyright (C) 2000 Ronald G. Minnich
+ *
+ * Microcode update for Intel PIII and later CPUs
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+#include <asm/cpu.h>
+#include <asm/microcode.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * struct microcode_update - standard microcode header from Intel
+ *
+ * We read this information out of the device tree and use it to determine
+ * whether the update is applicable or not. We also use the same structure
+ * to read information from the CPU.
+ */
+struct microcode_update {
+ uint header_version;
+ uint update_revision;
+ uint date_code;
+ uint processor_signature;
+ uint checksum;
+ uint loader_revision;
+ uint processor_flags;
+ const void *data;
+ int size;
+};
+
+static int microcode_decode_node(const void *blob, int node,
+ struct microcode_update *update)
+{
+ update->data = fdt_getprop(blob, node, "data", &update->size);
+ if (!update->data)
+ return -ENOENT;
+
+ update->header_version = fdtdec_get_int(blob, node,
+ "intel,header-version", 0);
+ update->update_revision = fdtdec_get_int(blob, node,
+ "intel,update-revision", 0);
+ update->date_code = fdtdec_get_int(blob, node,
+ "intel,date-code", 0);
+ update->processor_signature = fdtdec_get_int(blob, node,
+ "intel,processor-signature", 0);
+ update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0);
+ update->loader_revision = fdtdec_get_int(blob, node,
+ "intel,loader-revision", 0);
+ update->processor_flags = fdtdec_get_int(blob, node,
+ "intel,processor-flags", 0);
+
+ return 0;
+}
+
+int microcode_read_rev(void)
+{
+ /* Quark does not have microcode MSRs */
+#ifdef CONFIG_INTEL_QUARK
+ return 0;
+#else
+ /*
+ * Some Intel CPUs can be very finicky about the CPUID sequence used.
+ * So this is implemented in assembly so that it works reliably.
+ */
+ uint32_t low, high;
+
+ asm volatile (
+ "xorl %%eax, %%eax\n"
+ "xorl %%edx, %%edx\n"
+ "movl %2, %%ecx\n"
+ "wrmsr\n"
+ "movl $0x01, %%eax\n"
+ "cpuid\n"
+ "movl %2, %%ecx\n"
+ "rdmsr\n"
+ : /* outputs */
+ "=a" (low), "=d" (high)
+ : /* inputs */
+ "i" (MSR_IA32_UCODE_REV)
+ : /* clobbers */
+ "ebx", "ecx"
+ );
+
+ return high;
+#endif
+}
+
+static void microcode_read_cpu(struct microcode_update *cpu)
+{
+ /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
+ unsigned int x86_model, x86_family;
+ struct cpuid_result result;
+ uint32_t low, high;
+
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+ result = cpuid(1);
+ rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision);
+ x86_model = (result.eax >> 4) & 0x0f;
+ x86_family = (result.eax >> 8) & 0x0f;
+ cpu->processor_signature = result.eax;
+
+ cpu->processor_flags = 0;
+ if ((x86_model >= 5) || (x86_family > 6)) {
+ rdmsr(0x17, low, high);
+ cpu->processor_flags = 1 << ((high >> 18) & 7);
+ }
+ debug("microcode: sig=%#x pf=%#x revision=%#x\n",
+ cpu->processor_signature, cpu->processor_flags,
+ cpu->update_revision);
+}
+
+/* Get a microcode update from the device tree and apply it */
+int microcode_update_intel(void)
+{
+ struct microcode_update cpu, update;
+ ulong address;
+ const void *blob = gd->fdt_blob;
+ int skipped;
+ int count;
+ int node;
+ int ret;
+ int rev;
+
+ microcode_read_cpu(&cpu);
+ node = 0;
+ count = 0;
+ skipped = 0;
+ do {
+ node = fdtdec_next_compatible(blob, node,
+ COMPAT_INTEL_MICROCODE);
+ if (node < 0) {
+ debug("%s: Found %d updates\n", __func__, count);
+ return count ? 0 : skipped ? -EEXIST : -ENOENT;
+ }
+
+ ret = microcode_decode_node(blob, node, &update);
+ if (ret == -ENOENT && ucode_base) {
+ /*
+ * The microcode has been removed from the device tree
+ * in the build system. In that case it will have
+ * already been updated in car_init().
+ */
+ debug("%s: Microcode data not available\n", __func__);
+ skipped++;
+ continue;
+ }
+ if (ret) {
+ debug("%s: Unable to decode update: %d\n", __func__,
+ ret);
+ return ret;
+ }
+ if (!(update.processor_signature == cpu.processor_signature &&
+ (update.processor_flags & cpu.processor_flags))) {
+ debug("%s: Skipping non-matching update, sig=%x, pf=%x\n",
+ __func__, update.processor_signature,
+ update.processor_flags);
+ skipped++;
+ continue;
+ }
+ address = (ulong)update.data + UCODE_HEADER_LEN;
+ wrmsr(MSR_IA32_UCODE_WRITE, address, 0);
+ rev = microcode_read_rev();
+ debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
+ rev, update.date_code & 0xffff,
+ (update.date_code >> 24) & 0xff,
+ (update.date_code >> 16) & 0xff);
+ if (update.update_revision != rev) {
+ printf("Microcode update failed\n");
+ return -EFAULT;
+ }
+ count++;
+ if (!ucode_base) {
+ ucode_base = (ulong)update.data;
+ ucode_size = update.size;
+ }
+ } while (1);
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/mrc.c b/roms/u-boot/arch/x86/cpu/intel_common/mrc.c
new file mode 100644
index 000000000..a97b0b7ce
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/mrc.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <init.h>
+#include <log.h>
+#include <syscon.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <asm/intel_regs.h>
+#include <asm/mrc_common.h>
+#include <asm/pch_common.h>
+#include <asm/post.h>
+#include <asm/arch/me.h>
+#include <asm/report_platform.h>
+
+static const char *const ecc_decoder[] = {
+ "inactive",
+ "active on IO",
+ "disabled on IO",
+ "active"
+};
+
+ulong mrc_common_board_get_usable_ram_top(ulong total_size)
+{
+ struct memory_info *info = &gd->arch.meminfo;
+ uintptr_t dest_addr = 0;
+ struct memory_area *largest = NULL;
+ int i;
+
+ /* Find largest area of memory below 4GB */
+
+ for (i = 0; i < info->num_areas; i++) {
+ struct memory_area *area = &info->area[i];
+
+ if (area->start >= 1ULL << 32)
+ continue;
+ if (!largest || area->size > largest->size)
+ largest = area;
+ }
+
+ /* If no suitable area was found, return an error. */
+ assert(largest);
+ if (!largest || largest->size < (2 << 20))
+ panic("No available memory found for relocation");
+
+ dest_addr = largest->start + largest->size;
+
+ return (ulong)dest_addr;
+}
+
+void mrc_common_dram_init_banksize(void)
+{
+ struct memory_info *info = &gd->arch.meminfo;
+ int num_banks;
+ int i;
+
+ for (i = 0, num_banks = 0; i < info->num_areas; i++) {
+ struct memory_area *area = &info->area[i];
+
+ if (area->start >= 1ULL << 32)
+ continue;
+ gd->bd->bi_dram[num_banks].start = area->start;
+ gd->bd->bi_dram[num_banks].size = area->size;
+ num_banks++;
+ }
+}
+
+int mrc_add_memory_area(struct memory_info *info, uint64_t start,
+ uint64_t end)
+{
+ struct memory_area *ptr;
+
+ if (info->num_areas == CONFIG_NR_DRAM_BANKS)
+ return -ENOSPC;
+
+ ptr = &info->area[info->num_areas];
+ ptr->start = start;
+ ptr->size = end - start;
+ info->total_memory += ptr->size;
+ if (ptr->start < (1ULL << 32))
+ info->total_32bit_memory += ptr->size;
+ debug("%d: memory %llx size %llx, total now %llx / %llx\n",
+ info->num_areas, ptr->start, ptr->size,
+ info->total_32bit_memory, info->total_memory);
+ info->num_areas++;
+
+ return 0;
+}
+
+/*
+ * Dump in the log memory controller configuration as read from the memory
+ * controller registers.
+ */
+void report_memory_config(void)
+{
+ u32 addr_decoder_common, addr_decode_ch[2];
+ int i;
+
+ addr_decoder_common = readl(MCHBAR_REG(0x5000));
+ addr_decode_ch[0] = readl(MCHBAR_REG(0x5004));
+ addr_decode_ch[1] = readl(MCHBAR_REG(0x5008));
+
+ debug("memcfg DDR3 clock %d MHz\n",
+ (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100);
+ debug("memcfg channel assignment: A: %d, B % d, C % d\n",
+ addr_decoder_common & 3,
+ (addr_decoder_common >> 2) & 3,
+ (addr_decoder_common >> 4) & 3);
+
+ for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
+ u32 ch_conf = addr_decode_ch[i];
+ debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf);
+ debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]);
+ debug(" enhanced interleave mode %s\n",
+ ((ch_conf >> 22) & 1) ? "on" : "off");
+ debug(" rank interleave %s\n",
+ ((ch_conf >> 21) & 1) ? "on" : "off");
+ debug(" DIMMA %d MB width x%d %s rank%s\n",
+ ((ch_conf >> 0) & 0xff) * 256,
+ ((ch_conf >> 19) & 1) ? 16 : 8,
+ ((ch_conf >> 17) & 1) ? "dual" : "single",
+ ((ch_conf >> 16) & 1) ? "" : ", selected");
+ debug(" DIMMB %d MB width x%d %s rank%s\n",
+ ((ch_conf >> 8) & 0xff) * 256,
+ ((ch_conf >> 20) & 1) ? 16 : 8,
+ ((ch_conf >> 18) & 1) ? "dual" : "single",
+ ((ch_conf >> 16) & 1) ? ", selected" : "");
+ }
+}
+
+int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap)
+{
+ const void *blob = gd->fdt_blob;
+ int spd_index;
+ struct gpio_desc desc[4];
+ int spd_node;
+ int node;
+ int ret;
+
+ ret = gpio_request_list_by_name(dev, "board-id-gpios", desc,
+ ARRAY_SIZE(desc), GPIOD_IS_IN);
+ if (ret < 0) {
+ debug("%s: gpio ret=%d\n", __func__, ret);
+ return ret;
+ }
+ spd_index = dm_gpio_get_values_as_int(desc, ret);
+ debug("spd index %d\n", spd_index);
+
+ node = fdt_first_subnode(blob, dev_of_offset(dev));
+ if (node < 0)
+ return -EINVAL;
+ for (spd_node = fdt_first_subnode(blob, node);
+ spd_node > 0;
+ spd_node = fdt_next_subnode(blob, spd_node)) {
+ int len;
+
+ if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index)
+ continue;
+ *spd_datap = fdt_getprop(blob, spd_node, "data", &len);
+ if (len < size) {
+ printf("Missing SPD data\n");
+ return -EINVAL;
+ }
+
+ debug("Using SDRAM SPD data for '%s'\n",
+ fdt_get_name(blob, spd_node, NULL));
+ return 0;
+ }
+
+ printf("No SPD data found for index %d\n", spd_index);
+ return -ENOENT;
+}
+
+asmlinkage void sdram_console_tx_byte(unsigned char byte)
+{
+#ifdef DEBUG
+ putc(byte);
+#endif
+}
+
+/**
+ * Find the PEI executable in the ROM and execute it.
+ *
+ * @me_dev: Management Engine device
+ * @pei_data: configuration data for UEFI PEI reference code
+ */
+static int sdram_initialise(struct udevice *dev, struct udevice *me_dev,
+ void *pei_data, bool use_asm_linkage)
+{
+ unsigned version;
+ const char *data;
+
+ report_platform_info(dev);
+ debug("Starting UEFI PEI System Agent\n");
+
+ debug("PEI data at %p:\n", pei_data);
+
+ data = (char *)CONFIG_X86_MRC_ADDR;
+ if (data) {
+ int rv;
+ ulong start;
+
+ debug("Calling MRC at %p\n", data);
+ post_code(POST_PRE_MRC);
+ start = get_timer(0);
+ if (use_asm_linkage) {
+ asmlinkage int (*func)(void *);
+
+ func = (asmlinkage int (*)(void *))data;
+ rv = func(pei_data);
+ } else {
+ int (*func)(void *);
+
+ func = (int (*)(void *))data;
+ rv = func(pei_data);
+ }
+ post_code(POST_MRC);
+ if (rv) {
+ switch (rv) {
+ case -1:
+ printf("PEI version mismatch.\n");
+ break;
+ case -2:
+ printf("Invalid memory frequency.\n");
+ break;
+ default:
+ printf("MRC returned %x.\n", rv);
+ }
+ printf("Nonzero MRC return value.\n");
+ return -EFAULT;
+ }
+ debug("MRC execution time %lu ms\n", get_timer(start));
+ } else {
+ printf("UEFI PEI System Agent not found.\n");
+ return -ENOSYS;
+ }
+
+ version = readl(MCHBAR_REG(MCHBAR_PEI_VERSION));
+ debug("System Agent Version %d.%d.%d Build %d\n",
+ version >> 24 , (version >> 16) & 0xff,
+ (version >> 8) & 0xff, version & 0xff);
+
+ return 0;
+}
+
+int mrc_common_init(struct udevice *dev, void *pei_data, bool use_asm_linkage)
+{
+ struct udevice *me_dev;
+ int ret;
+
+ ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
+ if (ret)
+ return ret;
+
+ ret = sdram_initialise(dev, me_dev, pei_data, use_asm_linkage);
+ if (ret)
+ return ret;
+ quick_ram_check();
+ post_code(POST_DRAM);
+ report_memory_config();
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/p2sb.c b/roms/u-boot/arch/x86/cpu/intel_common/p2sb.c
new file mode 100644
index 000000000..d73ae438b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/p2sb.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Primary-to-Sideband Bridge
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_P2SB
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <log.h>
+#include <p2sb.h>
+#include <spl.h>
+#include <asm/p2sb.h>
+#include <asm/pci.h>
+#include <linux/bitops.h>
+
+#define PCH_P2SB_E0 0xe0
+#define HIDE_BIT BIT(0)
+
+/* PCI config space registers */
+#define HPTC_OFFSET 0x60
+#define HPTC_ADDR_ENABLE_BIT BIT(7)
+
+/* High Performance Event Timer Configuration */
+#define P2SB_HPTC 0x60
+#define P2SB_HPTC_ADDRESS_ENABLE BIT(7)
+
+/*
+ * ADDRESS_SELECT ENCODING_RANGE
+ * 0 0xfed0 0000 - 0xfed0 03ff
+ * 1 0xfed0 1000 - 0xfed0 13ff
+ * 2 0xfed0 2000 - 0xfed0 23ff
+ * 3 0xfed0 3000 - 0xfed0 33ff
+ */
+#define P2SB_HPTC_ADDRESS_SELECT_0 (0 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_1 (1 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_2 (2 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_3 (3 << 0)
+
+/*
+ * p2sb_early_init() - Enable decoding for HPET range
+ *
+ * This is needed by FSP-M which uses the High Precision Event Timer.
+ *
+ * @dev: P2SB device
+ * @return 0 if OK, -ve on error
+ */
+static int p2sb_early_init(struct udevice *dev)
+{
+ struct p2sb_plat *plat = dev_get_plat(dev);
+ pci_dev_t pdev = plat->bdf;
+
+ /*
+ * Enable decoding for HPET memory address range.
+ * HPTC_OFFSET(0x60) bit 7, when set the P2SB will decode
+ * the High Performance Timer memory address range
+ * selected by bits 1:0
+ */
+ pci_x86_write_config(pdev, HPTC_OFFSET, HPTC_ADDR_ENABLE_BIT,
+ PCI_SIZE_8);
+
+ /* Enable PCR Base address in PCH */
+ pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0, plat->mmio_base,
+ PCI_SIZE_32);
+ pci_x86_write_config(pdev, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+ /* Enable P2SB MSE */
+ pci_x86_write_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY, PCI_SIZE_8);
+
+ return 0;
+}
+
+static int p2sb_spl_init(struct udevice *dev)
+{
+ /* Enable decoding for HPET. Needed for FSP global pointer storage */
+ dm_pci_write_config(dev, P2SB_HPTC, P2SB_HPTC_ADDRESS_SELECT_0 |
+ P2SB_HPTC_ADDRESS_ENABLE, PCI_SIZE_8);
+
+ return 0;
+}
+
+int p2sb_of_to_plat(struct udevice *dev)
+{
+ struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev);
+ struct p2sb_plat *plat = dev_get_plat(dev);
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ int ret;
+ u32 base[2];
+
+ ret = dev_read_u32_array(dev, "early-regs", base, ARRAY_SIZE(base));
+ if (ret)
+ return log_msg_ret("Missing/short early-regs", ret);
+ plat->mmio_base = base[0];
+ /* TPL sets up the initial BAR */
+ if (spl_phase() == PHASE_TPL) {
+ plat->bdf = pci_get_devfn(dev);
+ if (plat->bdf < 0)
+ return log_msg_ret("Cannot get p2sb PCI address",
+ plat->bdf);
+ }
+ upriv->mmio_base = plat->mmio_base;
+#else
+ plat->mmio_base = plat->dtplat.early_regs[0];
+ plat->bdf = pci_ofplat_get_devfn(plat->dtplat.reg[0]);
+ upriv->mmio_base = plat->mmio_base;
+#endif
+
+ return 0;
+}
+
+static int p2sb_probe(struct udevice *dev)
+{
+ if (spl_phase() == PHASE_TPL)
+ return p2sb_early_init(dev);
+ else if (spl_phase() == PHASE_SPL)
+ return p2sb_spl_init(dev);
+
+ return 0;
+}
+
+static void p2sb_set_hide_bit(struct udevice *dev, bool hide)
+{
+ dm_pci_clrset_config8(dev, PCH_P2SB_E0 + 1, HIDE_BIT,
+ hide ? HIDE_BIT : 0);
+}
+
+static int intel_p2sb_set_hide(struct udevice *dev, bool hide)
+{
+ u16 vendor;
+
+ if (!CONFIG_IS_ENABLED(PCI))
+ return -EPERM;
+ p2sb_set_hide_bit(dev, hide);
+
+ dm_pci_read_config16(dev, PCI_VENDOR_ID, &vendor);
+ if (hide && vendor != 0xffff)
+ return log_msg_ret("hide", -EEXIST);
+ else if (!hide && vendor != PCI_VENDOR_ID_INTEL)
+ return log_msg_ret("unhide", -ENOMEDIUM);
+
+ return 0;
+}
+
+static int p2sb_remove(struct udevice *dev)
+{
+ int ret;
+
+ ret = intel_p2sb_set_hide(dev, true);
+ if (ret)
+ return log_msg_ret("hide", ret);
+
+ return 0;
+}
+
+static int p2sb_child_post_bind(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct p2sb_child_plat *pplat = dev_get_parent_plat(dev);
+ int ret;
+ u32 pid;
+
+ ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
+ if (ret)
+ return ret;
+ pplat->pid = pid;
+#endif
+
+ return 0;
+}
+
+static const struct p2sb_ops p2sb_ops = {
+ .set_hide = intel_p2sb_set_hide,
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct udevice_id p2sb_ids[] = {
+ { .compatible = "intel,p2sb" },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(intel_p2sb) = {
+ .name = "intel_p2sb",
+ .id = UCLASS_P2SB,
+ .of_match = of_match_ptr(p2sb_ids),
+ .probe = p2sb_probe,
+ .remove = p2sb_remove,
+ .ops = &p2sb_ops,
+ .of_to_plat = p2sb_of_to_plat,
+ .plat_auto = sizeof(struct p2sb_plat),
+ .per_child_plat_auto = sizeof(struct p2sb_child_plat),
+ .child_post_bind = p2sb_child_post_bind,
+ .flags = DM_FLAG_OS_PREPARE,
+};
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/pch.c b/roms/u-boot/arch/x86/cpu/intel_common/pch.c
new file mode 100644
index 000000000..af82b64a1
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/pch.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/pch_common.h>
+
+u32 pch_common_sir_read(struct udevice *dev, int idx)
+{
+ u32 data;
+
+ dm_pci_write_config32(dev, SATA_SIRI, idx);
+ dm_pci_read_config32(dev, SATA_SIRD, &data);
+
+ return data;
+}
+
+void pch_common_sir_write(struct udevice *dev, int idx, u32 value)
+{
+ dm_pci_write_config32(dev, SATA_SIRI, idx);
+ dm_pci_write_config32(dev, SATA_SIRD, value);
+}
diff --git a/roms/u-boot/arch/x86/cpu/intel_common/report_platform.c b/roms/u-boot/arch/x86/cpu/intel_common/report_platform.c
new file mode 100644
index 000000000..a3612817c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/intel_common/report_platform.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot src/northbridge/intel/sandybridge/report_platform.c
+ *
+ * Copyright (C) 2012 Google Inc.
+ */
+
+#include <common.h>
+#include <log.h>
+#include <asm/cpu.h>
+#include <asm/pci.h>
+#include <asm/report_platform.h>
+#include <asm/arch/pch.h>
+
+static void report_cpu_info(void)
+{
+ char cpu_string[CPU_MAX_NAME_LEN], *cpu_name;
+ const char *mode[] = {"NOT ", ""};
+ struct cpuid_result cpuidr;
+ int vt, txt, aes;
+ u32 index;
+
+ index = 0x80000000;
+ cpuidr = cpuid(index);
+ if (cpuidr.eax < 0x80000004) {
+ strcpy(cpu_string, "Platform info not available");
+ cpu_name = cpu_string;
+ } else {
+ cpu_name = cpu_get_name(cpu_string);
+ }
+
+ cpuidr = cpuid(1);
+ debug("CPU id(%x): %s\n", cpuidr.eax, cpu_name);
+ aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
+ txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
+ vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
+ debug("AES %ssupported, TXT %ssupported, VT %ssupported\n",
+ mode[aes], mode[txt], mode[vt]);
+}
+
+/* The PCI id name match comes from Intel document 472178 */
+static struct {
+ u16 dev_id;
+ const char *dev_name;
+} pch_table[] = {
+ {0x1E41, "Desktop Sample"},
+ {0x1E42, "Mobile Sample"},
+ {0x1E43, "SFF Sample"},
+ {0x1E44, "Z77"},
+ {0x1E45, "H71"},
+ {0x1E46, "Z75"},
+ {0x1E47, "Q77"},
+ {0x1E48, "Q75"},
+ {0x1E49, "B75"},
+ {0x1E4A, "H77"},
+ {0x1E53, "C216"},
+ {0x1E55, "QM77"},
+ {0x1E56, "QS77"},
+ {0x1E58, "UM77"},
+ {0x1E57, "HM77"},
+ {0x1E59, "HM76"},
+ {0x1E5D, "HM75"},
+ {0x1E5E, "HM70"},
+ {0x1E5F, "NM70"},
+};
+
+static void report_pch_info(struct udevice *dev)
+{
+ const char *pch_type = "Unknown";
+ int i;
+ u16 dev_id;
+ uint8_t rev_id;
+
+ dm_pci_read_config16(dev, 2, &dev_id);
+ for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
+ if (pch_table[i].dev_id == dev_id) {
+ pch_type = pch_table[i].dev_name;
+ break;
+ }
+ }
+ dm_pci_read_config8(dev, 8, &rev_id);
+ debug("PCH type: %s, device id: %x, rev id %x\n", pch_type, dev_id,
+ rev_id);
+}
+
+void report_platform_info(struct udevice *dev)
+{
+ report_cpu_info();
+ report_pch_info(dev);
+}
diff --git a/roms/u-boot/arch/x86/cpu/ioapic.c b/roms/u-boot/arch/x86/cpu/ioapic.c
new file mode 100644
index 000000000..4f99de6ec
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/ioapic.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
+#include <asm/lapic.h>
+
+u32 io_apic_read(u32 reg)
+{
+ writel(reg, IO_APIC_INDEX);
+ return readl(IO_APIC_DATA);
+}
+
+void io_apic_write(u32 reg, u32 val)
+{
+ writel(reg, IO_APIC_INDEX);
+ writel(val, IO_APIC_DATA);
+}
+
+void io_apic_set_id(int ioapic_id)
+{
+ int bsp_lapicid = lapicid();
+
+ debug("IOAPIC: Initialising IOAPIC at %08x\n", IO_APIC_ADDR);
+ debug("IOAPIC: Bootstrap Processor Local APIC = %#02x\n", bsp_lapicid);
+
+ if (ioapic_id) {
+ debug("IOAPIC: ID = 0x%02x\n", ioapic_id);
+ /* Set IOAPIC ID if it has been specified */
+ io_apic_write(0x00, (io_apic_read(0x00) & 0xf0ffffff) |
+ (ioapic_id << 24));
+ }
+}
diff --git a/roms/u-boot/arch/x86/cpu/irq.c b/roms/u-boot/arch/x86/cpu/irq.c
new file mode 100644
index 000000000..766b2451a
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/irq.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <irq.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/pirq_routing.h>
+#include <asm/tables.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number
+ *
+ * @priv: IRQ router driver's priv data
+ * @reg: PIRQ routing register offset from the base address
+ * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc)
+ */
+static inline int pirq_reg_to_linkno(struct irq_router *priv, int reg)
+{
+ int linkno = 0;
+
+ if (priv->has_regmap) {
+ struct pirq_regmap *map = priv->regmap;
+ int i;
+
+ for (i = 0; i < priv->link_num; i++) {
+ if (reg - priv->link_base == map->offset) {
+ linkno = map->link;
+ break;
+ }
+ map++;
+ }
+ } else {
+ linkno = reg - priv->link_base;
+ }
+
+ return linkno;
+}
+
+/**
+ * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset
+ *
+ * @priv: IRQ router driver's priv data
+ * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc)
+ * @return: PIRQ routing register offset from the base address
+ */
+static inline int pirq_linkno_to_reg(struct irq_router *priv, int linkno)
+{
+ int reg = 0;
+
+ if (priv->has_regmap) {
+ struct pirq_regmap *map = priv->regmap;
+ int i;
+
+ for (i = 0; i < priv->link_num; i++) {
+ if (linkno == map->link) {
+ reg = map->offset + priv->link_base;
+ break;
+ }
+ map++;
+ }
+ } else {
+ reg = linkno + priv->link_base;
+ }
+
+ return reg;
+}
+
+bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq)
+{
+ struct irq_router *priv = dev_get_priv(dev);
+ u8 pirq;
+
+ if (priv->config == PIRQ_VIA_PCI)
+ dm_pci_read_config8(dev->parent,
+ pirq_linkno_to_reg(priv, link), &pirq);
+ else
+ pirq = readb((uintptr_t)priv->ibase +
+ pirq_linkno_to_reg(priv, link));
+
+ pirq &= 0xf;
+
+ /* IRQ# 0/1/2/8/13 are reserved */
+ if (pirq < 3 || pirq == 8 || pirq == 13)
+ return false;
+
+ return pirq == irq ? true : false;
+}
+
+int pirq_translate_link(struct udevice *dev, int link)
+{
+ struct irq_router *priv = dev_get_priv(dev);
+
+ return pirq_reg_to_linkno(priv, link);
+}
+
+void pirq_assign_irq(struct udevice *dev, int link, u8 irq)
+{
+ struct irq_router *priv = dev_get_priv(dev);
+
+ /* IRQ# 0/1/2/8/13 are reserved */
+ if (irq < 3 || irq == 8 || irq == 13)
+ return;
+
+ if (priv->config == PIRQ_VIA_PCI)
+ dm_pci_write_config8(dev->parent,
+ pirq_linkno_to_reg(priv, link), irq);
+ else
+ writeb(irq, (uintptr_t)priv->ibase +
+ pirq_linkno_to_reg(priv, link));
+}
+
+static struct irq_info *check_dup_entry(struct irq_info *slot_base,
+ int entry_num, int bus, int device)
+{
+ struct irq_info *slot = slot_base;
+ int i;
+
+ for (i = 0; i < entry_num; i++) {
+ if (slot->bus == bus && slot->devfn == (device << 3))
+ break;
+ slot++;
+ }
+
+ return (i == entry_num) ? NULL : slot;
+}
+
+static inline void fill_irq_info(struct irq_router *priv, struct irq_info *slot,
+ int bus, int device, int pin, int pirq)
+{
+ slot->bus = bus;
+ slot->devfn = (device << 3) | 0;
+ slot->irq[pin - 1].link = pirq_linkno_to_reg(priv, pirq);
+ slot->irq[pin - 1].bitmap = priv->irq_mask;
+}
+
+static int create_pirq_routing_table(struct udevice *dev)
+{
+ struct irq_router *priv = dev_get_priv(dev);
+ const void *blob = gd->fdt_blob;
+ int node;
+ int len, count;
+ const u32 *cell;
+ struct pirq_regmap *map;
+ struct irq_routing_table *rt;
+ struct irq_info *slot, *slot_base;
+ int irq_entries = 0;
+ int i;
+ int ret;
+
+ node = dev_of_offset(dev);
+
+ /* extract the bdf from fdt_pci_addr */
+ priv->bdf = dm_pci_get_bdf(dev->parent);
+
+ ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci");
+ if (!ret) {
+ priv->config = PIRQ_VIA_PCI;
+ } else {
+ ret = fdt_stringlist_search(blob, node, "intel,pirq-config",
+ "ibase");
+ if (!ret)
+ priv->config = PIRQ_VIA_IBASE;
+ else
+ return -EINVAL;
+ }
+
+ cell = fdt_getprop(blob, node, "intel,pirq-link", &len);
+ if (!cell || len != 8)
+ return -EINVAL;
+ priv->link_base = fdt_addr_to_cpu(cell[0]);
+ priv->link_num = fdt_addr_to_cpu(cell[1]);
+ if (priv->link_num > CONFIG_MAX_PIRQ_LINKS) {
+ debug("Limiting supported PIRQ link number from %d to %d\n",
+ priv->link_num, CONFIG_MAX_PIRQ_LINKS);
+ priv->link_num = CONFIG_MAX_PIRQ_LINKS;
+ }
+
+ cell = fdt_getprop(blob, node, "intel,pirq-regmap", &len);
+ if (cell) {
+ if (len % sizeof(struct pirq_regmap))
+ return -EINVAL;
+
+ count = len / sizeof(struct pirq_regmap);
+ if (count < priv->link_num) {
+ printf("Number of pirq-regmap entires is wrong\n");
+ return -EINVAL;
+ }
+
+ count = priv->link_num;
+ priv->regmap = calloc(count, sizeof(struct pirq_regmap));
+ if (!priv->regmap)
+ return -ENOMEM;
+
+ priv->has_regmap = true;
+ map = priv->regmap;
+ for (i = 0; i < count; i++) {
+ map->link = fdt_addr_to_cpu(cell[0]);
+ map->offset = fdt_addr_to_cpu(cell[1]);
+
+ cell += sizeof(struct pirq_regmap) / sizeof(u32);
+ map++;
+ }
+ }
+
+ priv->irq_mask = fdtdec_get_int(blob, node,
+ "intel,pirq-mask", PIRQ_BITMAP);
+
+ if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
+ /* Reserve IRQ9 for SCI */
+ priv->irq_mask &= ~(1 << 9);
+ }
+
+ if (priv->config == PIRQ_VIA_IBASE) {
+ int ibase_off;
+
+ ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0);
+ if (!ibase_off)
+ return -EINVAL;
+
+ /*
+ * Here we assume that the IBASE register has already been
+ * properly configured by U-Boot before.
+ *
+ * By 'valid' we mean:
+ * 1) a valid memory space carved within system memory space
+ * assigned to IBASE register block.
+ * 2) memory range decoding is enabled.
+ * Hence we don't do any santify test here.
+ */
+ dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase);
+ priv->ibase &= ~0xf;
+ }
+
+ priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit");
+ priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0);
+
+ cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
+ if (!cell || len % sizeof(struct pirq_routing))
+ return -EINVAL;
+ count = len / sizeof(struct pirq_routing);
+
+ rt = calloc(1, sizeof(struct irq_routing_table));
+ if (!rt)
+ return -ENOMEM;
+
+ /* Populate the PIRQ table fields */
+ rt->signature = PIRQ_SIGNATURE;
+ rt->version = PIRQ_VERSION;
+ rt->rtr_bus = PCI_BUS(priv->bdf);
+ rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf);
+ rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
+ rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;
+
+ slot_base = rt->slots;
+
+ /* Now fill in the irq_info entries in the PIRQ table */
+ for (i = 0; i < count;
+ i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) {
+ struct pirq_routing pr;
+
+ pr.bdf = fdt_addr_to_cpu(cell[0]);
+ pr.pin = fdt_addr_to_cpu(cell[1]);
+ pr.pirq = fdt_addr_to_cpu(cell[2]);
+
+ debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n",
+ i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
+ PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
+ 'A' + pr.pirq);
+
+ slot = check_dup_entry(slot_base, irq_entries,
+ PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
+ if (slot) {
+ debug("found entry for bus %d device %d, ",
+ PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
+
+ if (slot->irq[pr.pin - 1].link) {
+ debug("skipping\n");
+
+ /*
+ * Sanity test on the routed PIRQ pin
+ *
+ * If they don't match, show a warning to tell
+ * there might be something wrong with the PIRQ
+ * routing information in the device tree.
+ */
+ if (slot->irq[pr.pin - 1].link !=
+ pirq_linkno_to_reg(priv, pr.pirq))
+ debug("WARNING: Inconsistent PIRQ routing information\n");
+ continue;
+ }
+ } else {
+ slot = slot_base + irq_entries++;
+ }
+ debug("writing INT%c\n", 'A' + pr.pin - 1);
+ fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
+ pr.pin, pr.pirq);
+ }
+
+ rt->size = irq_entries * sizeof(struct irq_info) + 32;
+
+ /* Fix up the table checksum */
+ rt->checksum = table_compute_checksum(rt, rt->size);
+
+ gd->arch.pirq_routing_table = rt;
+
+ return 0;
+}
+
+static void irq_enable_sci(struct udevice *dev)
+{
+ struct irq_router *priv = dev_get_priv(dev);
+
+ if (priv->actl_8bit) {
+ /* Bit7 must be turned on to enable ACPI */
+ dm_pci_write_config8(dev->parent, priv->actl_addr, 0x80);
+ } else {
+ /* Write 0 to enable SCI on IRQ9 */
+ if (priv->config == PIRQ_VIA_PCI)
+ dm_pci_write_config32(dev->parent, priv->actl_addr, 0);
+ else
+ writel(0, (uintptr_t)priv->ibase + priv->actl_addr);
+ }
+}
+
+int irq_router_probe(struct udevice *dev)
+{
+ int ret;
+
+ ret = create_pirq_routing_table(dev);
+ if (ret) {
+ debug("Failed to create pirq routing table\n");
+ return ret;
+ }
+ /* Route PIRQ */
+ pirq_route_irqs(dev, gd->arch.pirq_routing_table->slots,
+ get_irq_slot_count(gd->arch.pirq_routing_table));
+
+ if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE))
+ irq_enable_sci(dev);
+
+ return 0;
+}
+
+static const struct udevice_id irq_router_ids[] = {
+ { .compatible = "intel,irq-router", .data = X86_IRQT_BASE },
+ { }
+};
+
+U_BOOT_DRIVER(irq_router_drv) = {
+ .name = "intel_irq",
+ .id = UCLASS_IRQ,
+ .of_match = irq_router_ids,
+ .probe = irq_router_probe,
+ .priv_auto = sizeof(struct irq_router),
+};
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;
+}
diff --git a/roms/u-boot/arch/x86/cpu/lapic.c b/roms/u-boot/arch/x86/cpu/lapic.c
new file mode 100644
index 000000000..c0691454f
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/lapic.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From coreboot file of same name
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2014 Google, Inc
+ */
+
+#include <common.h>
+#include <log.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+#include <asm/post.h>
+
+unsigned long lapic_read(unsigned long reg)
+{
+ return readl(LAPIC_DEFAULT_BASE + reg);
+}
+
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+ sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+/*
+ * Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
+ *
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ * but generally the primitive is invalid, *ptr is output argument.
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+ int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ : "=q" (x)
+ : "m" (*__xg(ptr)), "0" (x)
+ : "memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ : "=r" (x)
+ : "m" (*__xg(ptr)), "0" (x)
+ : "memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %0,%1"
+ : "=r" (x)
+ : "m" (*__xg(ptr)), "0" (x)
+ : "memory");
+ break;
+ }
+
+ return x;
+}
+
+void lapic_write(unsigned long reg, unsigned long v)
+{
+ (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
+}
+
+void enable_lapic(void)
+{
+ if (!IS_ENABLED(CONFIG_INTEL_QUARK)) {
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_APICBASE);
+ msr.hi &= 0xffffff00;
+ msr.lo |= MSR_IA32_APICBASE_ENABLE;
+ msr.lo &= ~MSR_IA32_APICBASE_BASE;
+ msr.lo |= LAPIC_DEFAULT_BASE;
+ msr_write(MSR_IA32_APICBASE, msr);
+ }
+}
+
+void disable_lapic(void)
+{
+ if (!IS_ENABLED(CONFIG_INTEL_QUARK)) {
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_APICBASE);
+ msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
+ msr_write(MSR_IA32_APICBASE, msr);
+ }
+}
+
+unsigned long lapicid(void)
+{
+ return lapic_read(LAPIC_ID) >> 24;
+}
+
+static void lapic_wait_icr_idle(void)
+{
+ do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
+}
+
+int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
+{
+ int timeout;
+ unsigned long status;
+ int result;
+
+ lapic_wait_icr_idle();
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+ lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
+
+ timeout = 0;
+ do {
+ status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
+ } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
+
+ result = -1;
+ if (status == LAPIC_ICR_RR_VALID) {
+ *pvalue = lapic_read(LAPIC_RRR);
+ result = 0;
+ }
+
+ return result;
+}
+
+void lapic_setup(void)
+{
+ /* Only Pentium Pro and later have those MSR stuff */
+ debug("Setting up local apic: ");
+
+ /* Enable the local apic */
+ enable_lapic();
+
+ /* Set Task Priority to 'accept all' */
+ lapic_write(LAPIC_TASKPRI,
+ lapic_read(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
+
+ /* Put the local apic in virtual wire mode */
+ lapic_write(LAPIC_SPIV, (lapic_read(LAPIC_SPIV) &
+ ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
+ lapic_write(LAPIC_LVT0, (lapic_read(LAPIC_LVT0) &
+ ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
+ LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
+ LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
+ LAPIC_DELIVERY_MODE_MASK)) |
+ (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
+ LAPIC_DELIVERY_MODE_EXTINT));
+ lapic_write(LAPIC_LVT1, (lapic_read(LAPIC_LVT1) &
+ ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
+ LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
+ LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
+ LAPIC_DELIVERY_MODE_MASK)) |
+ (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
+ LAPIC_DELIVERY_MODE_NMI));
+
+ debug("apic_id: 0x%02lx, ", lapicid());
+
+ debug("done.\n");
+ post_code(POST_LAPIC);
+}
diff --git a/roms/u-boot/arch/x86/cpu/mp_init.c b/roms/u-boot/arch/x86/cpu/mp_init.c
new file mode 100644
index 000000000..c09762aee
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/mp_init.c
@@ -0,0 +1,902 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * Based on code from the coreboot file of the same name
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <qfw.h>
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/interrupt.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/microcode.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/processor.h>
+#include <asm/sipi.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <linux/delay.h>
+#include <linux/linkage.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Setting up multiprocessing
+ *
+ * See https://www.intel.com/content/www/us/en/intelligent-systems/intel-boot-loader-development-kit/minimal-intel-architecture-boot-loader-paper.html
+ *
+ * Note that this file refers to the boot CPU (the one U-Boot is running on) as
+ * the BSP (BootStrap Processor) and the others as APs (Application Processors).
+ *
+ * This module works by loading some setup code into RAM at AP_DEFAULT_BASE and
+ * telling each AP to execute it. The code that each AP runs is in
+ * sipi_vector.S (see ap_start16) which includes a struct sipi_params at the
+ * end of it. Those parameters are set up by the C code.
+
+ * Setting up is handled by load_sipi_vector(). It inits the common block of
+ * parameters (sipi_params) which tell the APs what to do. This block includes
+ * microcode and the MTTRs (Memory-Type-Range Registers) from the main CPU.
+ * There is also an ap_count which each AP increments as it starts up, so the
+ * BSP can tell how many checked in.
+ *
+ * The APs are started with a SIPI (Startup Inter-Processor Interrupt) which
+ * tells an AP to start executing at a particular address, in this case
+ * AP_DEFAULT_BASE which contains the code copied from ap_start16. This protocol
+ * is handled by start_aps().
+ *
+ * After being started, each AP runs the code in ap_start16, switches to 32-bit
+ * mode, runs the code at ap_start, then jumps to c_handler which is ap_init().
+ * This runs a very simple 'flight plan' described in mp_steps(). This sets up
+ * the CPU and waits for further instructions by looking at its entry in
+ * ap_callbacks[]. Note that the flight plan is only actually run for each CPU
+ * in bsp_do_flight_plan(): once the BSP completes each flight record, it sets
+ * mp_flight_record->barrier to 1 to allow the APs to executed the record one
+ * by one.
+ *
+ * CPUS are numbered sequentially from 0 using the device tree:
+ *
+ * cpus {
+ * u-boot,dm-pre-reloc;
+ * #address-cells = <1>;
+ * #size-cells = <0>;
+ *
+ * cpu@0 {
+ * u-boot,dm-pre-reloc;
+ * device_type = "cpu";
+ * compatible = "intel,apl-cpu";
+ * reg = <0>;
+ * intel,apic-id = <0>;
+ * };
+ *
+ * cpu@1 {
+ * device_type = "cpu";
+ * compatible = "intel,apl-cpu";
+ * reg = <1>;
+ * intel,apic-id = <2>;
+ * };
+ *
+ * Here the 'reg' property is the CPU number and then is placed in dev_seq(cpu)
+ * so that we can index into ap_callbacks[] using that. The APIC ID is different
+ * and may not be sequential (it typically is if hyperthreading is supported).
+ *
+ * Once APs are inited they wait in ap_wait_for_instruction() for instructions.
+ * Instructions come in the form of a function to run. This logic is in
+ * mp_run_on_cpus() which supports running on any one AP, all APs, just the BSP
+ * or all CPUs. The BSP logic is handled directly in mp_run_on_cpus(), by
+ * calling the function. For the APs, callback information is stored in a
+ * single, common struct mp_callback and a pointer to this is written to each
+ * AP's slot in ap_callbacks[] by run_ap_work(). All APs get the message even
+ * if it is only for one of them. When an AP notices a message it checks whether
+ * it should call the function (see check in ap_wait_for_instruction()) and then
+ * does so if needed. After that it sets its slot to NULL to indicate it is
+ * done.
+ *
+ * While U-Boot is running it can use mp_run_on_cpus() to run code on the APs.
+ * An example of this is the 'mtrr' command which allows reading and changing
+ * the MTRRs on all CPUs.
+ *
+ * Before U-Boot exits it calls mp_park_aps() which tells all CPUs to halt by
+ * executing a 'hlt' instruction. That allows them to be used by Linux when it
+ * starts up.
+ */
+
+/* This also needs to match the sipi.S assembly code for saved MSR encoding */
+struct __packed saved_msr {
+ uint32_t index;
+ uint32_t lo;
+ uint32_t hi;
+};
+
+/**
+ * struct mp_flight_plan - Holds the flight plan
+ *
+ * @num_records: Number of flight records
+ * @records: Pointer to each record
+ */
+struct mp_flight_plan {
+ int num_records;
+ struct mp_flight_record *records;
+};
+
+/**
+ * struct mp_callback - Callback information for APs
+ *
+ * @func: Function to run
+ * @arg: Argument to pass to the function
+ * @logical_cpu_number: Either a CPU number (i.e. dev_seq(cpu) or a special
+ * value like MP_SELECT_BSP. It tells the AP whether it should process this
+ * callback
+ */
+struct mp_callback {
+ mp_run_func func;
+ void *arg;
+ int logical_cpu_number;
+};
+
+/* Stores the flight plan so that APs can find it */
+static struct mp_flight_plan mp_info;
+
+/*
+ * ap_callbacks - Callback mailbox array
+ *
+ * Array of callback, one entry for each available CPU, indexed by the CPU
+ * number, which is dev_seq(cpu). The entry for the main CPU is never used.
+ * When this is NULL, there is no pending work for the CPU to run. When
+ * non-NULL it points to the mp_callback structure. This is shared between all
+ * CPUs, so should only be written by the main CPU.
+ */
+static struct mp_callback **ap_callbacks;
+
+static inline void barrier_wait(atomic_t *b)
+{
+ while (atomic_read(b) == 0)
+ asm("pause");
+ mfence();
+}
+
+static inline void release_barrier(atomic_t *b)
+{
+ mfence();
+ atomic_set(b, 1);
+}
+
+static inline void stop_this_cpu(void)
+{
+ /* Called by an AP when it is ready to halt and wait for a new task */
+ for (;;)
+ cpu_hlt();
+}
+
+/* Returns 1 if timeout waiting for APs. 0 if target APs found */
+static int wait_for_aps(atomic_t *val, int target, int total_delay,
+ int delay_step)
+{
+ int timeout = 0;
+ int delayed = 0;
+
+ while (atomic_read(val) != target) {
+ udelay(delay_step);
+ delayed += delay_step;
+ if (delayed >= total_delay) {
+ timeout = 1;
+ break;
+ }
+ }
+
+ return timeout;
+}
+
+static void ap_do_flight_plan(struct udevice *cpu)
+{
+ int i;
+
+ for (i = 0; i < mp_info.num_records; i++) {
+ struct mp_flight_record *rec = &mp_info.records[i];
+
+ atomic_inc(&rec->cpus_entered);
+ barrier_wait(&rec->barrier);
+
+ if (rec->ap_call != NULL)
+ rec->ap_call(cpu, rec->ap_arg);
+ }
+}
+
+static int find_cpu_by_apic_id(int apic_id, struct udevice **devp)
+{
+ struct udevice *dev;
+
+ *devp = NULL;
+ for (uclass_find_first_device(UCLASS_CPU, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ if (plat->cpu_id == apic_id) {
+ *devp = dev;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+/*
+ * By the time APs call ap_init() caching has been setup, and microcode has
+ * been loaded
+ */
+static void ap_init(unsigned int cpu_index)
+{
+ struct udevice *dev;
+ int apic_id;
+ int ret;
+
+ /* Ensure the local apic is enabled */
+ enable_lapic();
+
+ apic_id = lapicid();
+ ret = find_cpu_by_apic_id(apic_id, &dev);
+ if (ret) {
+ debug("Unknown CPU apic_id %x\n", apic_id);
+ goto done;
+ }
+
+ debug("AP: slot %d apic_id %x, dev %s\n", cpu_index, apic_id,
+ dev ? dev->name : "(apic_id not found)");
+
+ /*
+ * Walk the flight plan, which only returns if CONFIG_SMP_AP_WORK is not
+ * enabled
+ */
+ ap_do_flight_plan(dev);
+
+done:
+ stop_this_cpu();
+}
+
+static const unsigned int fixed_mtrrs[NUM_FIXED_MTRRS] = {
+ MTRR_FIX_64K_00000_MSR, MTRR_FIX_16K_80000_MSR, MTRR_FIX_16K_A0000_MSR,
+ MTRR_FIX_4K_C0000_MSR, MTRR_FIX_4K_C8000_MSR, MTRR_FIX_4K_D0000_MSR,
+ MTRR_FIX_4K_D8000_MSR, MTRR_FIX_4K_E0000_MSR, MTRR_FIX_4K_E8000_MSR,
+ MTRR_FIX_4K_F0000_MSR, MTRR_FIX_4K_F8000_MSR,
+};
+
+static inline struct saved_msr *save_msr(int index, struct saved_msr *entry)
+{
+ msr_t msr;
+
+ msr = msr_read(index);
+ entry->index = index;
+ entry->lo = msr.lo;
+ entry->hi = msr.hi;
+
+ /* Return the next entry */
+ entry++;
+ return entry;
+}
+
+static int save_bsp_msrs(char *start, int size)
+{
+ int msr_count;
+ int num_var_mtrrs;
+ struct saved_msr *msr_entry;
+ int i;
+ msr_t msr;
+
+ /* Determine number of MTRRs need to be saved */
+ msr = msr_read(MTRR_CAP_MSR);
+ num_var_mtrrs = msr.lo & 0xff;
+
+ /* 2 * num_var_mtrrs for base and mask. +1 for IA32_MTRR_DEF_TYPE */
+ msr_count = 2 * num_var_mtrrs + NUM_FIXED_MTRRS + 1;
+
+ if ((msr_count * sizeof(struct saved_msr)) > size) {
+ printf("Cannot mirror all %d msrs\n", msr_count);
+ return -ENOSPC;
+ }
+
+ msr_entry = (void *)start;
+ for (i = 0; i < NUM_FIXED_MTRRS; i++)
+ msr_entry = save_msr(fixed_mtrrs[i], msr_entry);
+
+ for (i = 0; i < num_var_mtrrs; i++) {
+ msr_entry = save_msr(MTRR_PHYS_BASE_MSR(i), msr_entry);
+ msr_entry = save_msr(MTRR_PHYS_MASK_MSR(i), msr_entry);
+ }
+
+ msr_entry = save_msr(MTRR_DEF_TYPE_MSR, msr_entry);
+
+ return msr_count;
+}
+
+static int load_sipi_vector(atomic_t **ap_countp, int num_cpus)
+{
+ struct sipi_params_16bit *params16;
+ struct sipi_params *params;
+ static char msr_save[512];
+ char *stack;
+ ulong addr;
+ int code_len;
+ int size;
+ int ret;
+
+ /* Copy in the code */
+ code_len = ap_start16_code_end - ap_start16;
+ debug("Copying SIPI code to %x: %d bytes\n", AP_DEFAULT_BASE,
+ code_len);
+ memcpy((void *)AP_DEFAULT_BASE, ap_start16, code_len);
+
+ addr = AP_DEFAULT_BASE + (ulong)sipi_params_16bit - (ulong)ap_start16;
+ params16 = (struct sipi_params_16bit *)addr;
+ params16->ap_start = (uint32_t)ap_start;
+ params16->gdt = (uint32_t)gd->arch.gdt;
+ params16->gdt_limit = X86_GDT_SIZE - 1;
+ debug("gdt = %x, gdt_limit = %x\n", params16->gdt, params16->gdt_limit);
+
+ params = (struct sipi_params *)sipi_params;
+ debug("SIPI 32-bit params at %p\n", params);
+ params->idt_ptr = (uint32_t)x86_get_idt();
+
+ params->stack_size = CONFIG_AP_STACK_SIZE;
+ size = params->stack_size * num_cpus;
+ stack = memalign(4096, size);
+ if (!stack)
+ return -ENOMEM;
+ params->stack_top = (u32)(stack + size);
+#if !defined(CONFIG_QEMU) && !defined(CONFIG_HAVE_FSP) && \
+ !defined(CONFIG_INTEL_MID)
+ params->microcode_ptr = ucode_base;
+ debug("Microcode at %x\n", params->microcode_ptr);
+#endif
+ params->msr_table_ptr = (u32)msr_save;
+ ret = save_bsp_msrs(msr_save, sizeof(msr_save));
+ if (ret < 0)
+ return ret;
+ params->msr_count = ret;
+
+ params->c_handler = (uint32_t)&ap_init;
+
+ *ap_countp = &params->ap_count;
+ atomic_set(*ap_countp, 0);
+ debug("SIPI vector is ready\n");
+
+ return 0;
+}
+
+static int check_cpu_devices(int expected_cpus)
+{
+ int i;
+
+ for (i = 0; i < expected_cpus; i++) {
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_find_device(UCLASS_CPU, i, &dev);
+ if (ret) {
+ debug("Cannot find CPU %d in device tree\n", i);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* Returns 1 for timeout. 0 on success */
+static int apic_wait_timeout(int total_delay, const char *msg)
+{
+ int total = 0;
+
+ if (!(lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY))
+ return 0;
+
+ debug("Waiting for %s...", msg);
+ while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY) {
+ udelay(50);
+ total += 50;
+ if (total >= total_delay) {
+ debug("timed out: aborting\n");
+ return -ETIMEDOUT;
+ }
+ }
+ debug("done\n");
+
+ return 0;
+}
+
+/**
+ * start_aps() - Start up the APs and count how many we find
+ *
+ * This is called on the boot processor to start up all the other processors
+ * (here called APs).
+ *
+ * @num_aps: Number of APs we expect to find
+ * @ap_count: Initially zero. Incremented by this function for each AP found
+ * @return 0 if all APs were set up correctly or there are none to set up,
+ * -ENOSPC if the SIPI vector is too high in memory,
+ * -ETIMEDOUT if the ICR is busy or the second SIPI fails to complete
+ * -EIO if not all APs check in correctly
+ */
+static int start_aps(int num_aps, atomic_t *ap_count)
+{
+ int sipi_vector;
+ /* Max location is 4KiB below 1MiB */
+ const int max_vector_loc = ((1 << 20) - (1 << 12)) >> 12;
+
+ if (num_aps == 0)
+ return 0;
+
+ /* The vector is sent as a 4k aligned address in one byte */
+ sipi_vector = AP_DEFAULT_BASE >> 12;
+
+ if (sipi_vector > max_vector_loc) {
+ printf("SIPI vector too large! 0x%08x\n",
+ sipi_vector);
+ return -ENOSPC;
+ }
+
+ debug("Attempting to start %d APs\n", num_aps);
+
+ if (apic_wait_timeout(1000, "ICR not to be busy"))
+ return -ETIMEDOUT;
+
+ /* Send INIT IPI to all but self */
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+ LAPIC_DM_INIT);
+ debug("Waiting for 10ms after sending INIT\n");
+ mdelay(10);
+
+ /* Send 1st SIPI */
+ if (apic_wait_timeout(1000, "ICR not to be busy"))
+ return -ETIMEDOUT;
+
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+ LAPIC_DM_STARTUP | sipi_vector);
+ if (apic_wait_timeout(10000, "first SIPI to complete"))
+ return -ETIMEDOUT;
+
+ /* Wait for CPUs to check in up to 200 us */
+ wait_for_aps(ap_count, num_aps, 200, 15);
+
+ /* Send 2nd SIPI */
+ if (apic_wait_timeout(1000, "ICR not to be busy"))
+ return -ETIMEDOUT;
+
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+ LAPIC_DM_STARTUP | sipi_vector);
+ if (apic_wait_timeout(10000, "second SIPI to complete"))
+ return -ETIMEDOUT;
+
+ /* Wait for CPUs to check in */
+ if (wait_for_aps(ap_count, num_aps, 10000, 50)) {
+ debug("Not all APs checked in: %d/%d\n",
+ atomic_read(ap_count), num_aps);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * bsp_do_flight_plan() - Do the flight plan on the BSP
+ *
+ * This runs the flight plan on the main CPU used to boot U-Boot
+ *
+ * @cpu: Device for the main CPU
+ * @plan: Flight plan to run
+ * @num_aps: Number of APs (CPUs other than the BSP)
+ * @returns 0 on success, -ETIMEDOUT if an AP failed to come up
+ */
+static int bsp_do_flight_plan(struct udevice *cpu, struct mp_flight_plan *plan,
+ int num_aps)
+{
+ int i;
+ int ret = 0;
+ const int timeout_us = 100000;
+ const int step_us = 100;
+
+ for (i = 0; i < plan->num_records; i++) {
+ struct mp_flight_record *rec = &plan->records[i];
+
+ /* Wait for APs if the record is not released */
+ if (atomic_read(&rec->barrier) == 0) {
+ /* Wait for the APs to check in */
+ if (wait_for_aps(&rec->cpus_entered, num_aps,
+ timeout_us, step_us)) {
+ debug("MP record %d timeout\n", i);
+ ret = -ETIMEDOUT;
+ }
+ }
+
+ if (rec->bsp_call != NULL)
+ rec->bsp_call(cpu, rec->bsp_arg);
+
+ release_barrier(&rec->barrier);
+ }
+
+ return ret;
+}
+
+/**
+ * get_bsp() - Get information about the bootstrap processor
+ *
+ * @devp: If non-NULL, returns CPU device corresponding to the BSP
+ * @cpu_countp: If non-NULL, returns the total number of CPUs
+ * @return CPU number of the BSP, or -ve on error. If multiprocessing is not
+ * enabled, returns 0
+ */
+static int get_bsp(struct udevice **devp, int *cpu_countp)
+{
+ char processor_name[CPU_MAX_NAME_LEN];
+ struct udevice *dev;
+ int apic_id;
+ int ret;
+
+ cpu_get_name(processor_name);
+ debug("CPU: %s\n", processor_name);
+
+ apic_id = lapicid();
+ ret = find_cpu_by_apic_id(apic_id, &dev);
+ if (ret < 0) {
+ printf("Cannot find boot CPU, APIC ID %d\n", apic_id);
+ return ret;
+ }
+ ret = cpu_get_count(dev);
+ if (ret < 0)
+ return log_msg_ret("count", ret);
+ if (devp)
+ *devp = dev;
+ if (cpu_countp)
+ *cpu_countp = ret;
+
+ return dev_seq(dev) >= 0 ? dev_seq(dev) : 0;
+}
+
+/**
+ * read_callback() - Read the pointer in a callback slot
+ *
+ * This is called by APs to read their callback slot to see if there is a
+ * pointer to new instructions
+ *
+ * @slot: Pointer to the AP's callback slot
+ * @return value of that pointer
+ */
+static struct mp_callback *read_callback(struct mp_callback **slot)
+{
+ dmb();
+
+ return *slot;
+}
+
+/**
+ * store_callback() - Store a pointer to the callback slot
+ *
+ * This is called by APs to write NULL into the callback slot when they have
+ * finished the work requested by the BSP.
+ *
+ * @slot: Pointer to the AP's callback slot
+ * @val: Value to write (e.g. NULL)
+ */
+static void store_callback(struct mp_callback **slot, struct mp_callback *val)
+{
+ *slot = val;
+ dmb();
+}
+
+/**
+ * run_ap_work() - Run a callback on selected APs
+ *
+ * This writes @callback to all APs and waits for them all to acknowledge it,
+ * Note that whether each AP actually calls the callback depends on the value
+ * of logical_cpu_number (see struct mp_callback). The logical CPU number is
+ * the CPU device's req->seq value.
+ *
+ * @callback: Callback information to pass to all APs
+ * @bsp: CPU device for the BSP
+ * @num_cpus: The number of CPUs in the system (= number of APs + 1)
+ * @expire_ms: Timeout to wait for all APs to finish, in milliseconds, or 0 for
+ * no timeout
+ * @return 0 if OK, -ETIMEDOUT if one or more APs failed to respond in time
+ */
+static int run_ap_work(struct mp_callback *callback, struct udevice *bsp,
+ int num_cpus, uint expire_ms)
+{
+ int cur_cpu = dev_seq(bsp);
+ int num_aps = num_cpus - 1; /* number of non-BSPs to get this message */
+ int cpus_accepted;
+ ulong start;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_SMP_AP_WORK)) {
+ printf("APs already parked. CONFIG_SMP_AP_WORK not enabled\n");
+ return -ENOTSUPP;
+ }
+
+ /* Signal to all the APs to run the func. */
+ for (i = 0; i < num_cpus; i++) {
+ if (cur_cpu != i)
+ store_callback(&ap_callbacks[i], callback);
+ }
+ mfence();
+
+ /* Wait for all the APs to signal back that call has been accepted. */
+ start = get_timer(0);
+
+ do {
+ mdelay(1);
+ cpus_accepted = 0;
+
+ for (i = 0; i < num_cpus; i++) {
+ if (cur_cpu == i)
+ continue;
+ if (!read_callback(&ap_callbacks[i]))
+ cpus_accepted++;
+ }
+
+ if (expire_ms && get_timer(start) >= expire_ms) {
+ log(UCLASS_CPU, LOGL_CRIT,
+ "AP call expired; %d/%d CPUs accepted\n",
+ cpus_accepted, num_aps);
+ return -ETIMEDOUT;
+ }
+ } while (cpus_accepted != num_aps);
+
+ /* Make sure we can see any data written by the APs */
+ mfence();
+
+ return 0;
+}
+
+/**
+ * ap_wait_for_instruction() - Wait for and process requests from the main CPU
+ *
+ * This is called by APs (here, everything other than the main boot CPU) to
+ * await instructions. They arrive in the form of a function call and argument,
+ * which is then called. This uses a simple mailbox with atomic read/set
+ *
+ * @cpu: CPU that is waiting
+ * @unused: Optional argument provided by struct mp_flight_record, not used here
+ * @return Does not return
+ */
+static int ap_wait_for_instruction(struct udevice *cpu, void *unused)
+{
+ struct mp_callback lcb;
+ struct mp_callback **per_cpu_slot;
+
+ if (!IS_ENABLED(CONFIG_SMP_AP_WORK))
+ return 0;
+
+ per_cpu_slot = &ap_callbacks[dev_seq(cpu)];
+
+ while (1) {
+ struct mp_callback *cb = read_callback(per_cpu_slot);
+
+ if (!cb) {
+ asm ("pause");
+ continue;
+ }
+
+ /* Copy to local variable before using the value */
+ memcpy(&lcb, cb, sizeof(lcb));
+ mfence();
+ if (lcb.logical_cpu_number == MP_SELECT_ALL ||
+ lcb.logical_cpu_number == MP_SELECT_APS ||
+ dev_seq(cpu) == lcb.logical_cpu_number)
+ lcb.func(lcb.arg);
+
+ /* Indicate we are finished */
+ store_callback(per_cpu_slot, NULL);
+ }
+
+ return 0;
+}
+
+static int mp_init_cpu(struct udevice *cpu, void *unused)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(cpu);
+
+ plat->ucode_version = microcode_read_rev();
+ plat->device_id = gd->arch.x86_device;
+
+ return device_probe(cpu);
+}
+
+static struct mp_flight_record mp_steps[] = {
+ MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
+ MP_FR_BLOCK_APS(ap_wait_for_instruction, NULL, NULL, NULL),
+};
+
+int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg)
+{
+ struct mp_callback lcb = {
+ .func = func,
+ .arg = arg,
+ .logical_cpu_number = cpu_select,
+ };
+ struct udevice *dev;
+ int num_cpus;
+ int ret;
+
+ ret = get_bsp(&dev, &num_cpus);
+ if (ret < 0)
+ return log_msg_ret("bsp", ret);
+ if (cpu_select == MP_SELECT_ALL || cpu_select == MP_SELECT_BSP ||
+ cpu_select == ret) {
+ /* Run on BSP first */
+ func(arg);
+ }
+
+ if (!IS_ENABLED(CONFIG_SMP_AP_WORK) ||
+ !(gd->flags & GD_FLG_SMP_READY)) {
+ /* Allow use of this function on the BSP only */
+ if (cpu_select == MP_SELECT_BSP || !cpu_select)
+ return 0;
+ return -ENOTSUPP;
+ }
+
+ /* Allow up to 1 second for all APs to finish */
+ ret = run_ap_work(&lcb, dev, num_cpus, 1000 /* ms */);
+ if (ret)
+ return log_msg_ret("aps", ret);
+
+ return 0;
+}
+
+static void park_this_cpu(void *unused)
+{
+ stop_this_cpu();
+}
+
+int mp_park_aps(void)
+{
+ int ret;
+
+ ret = mp_run_on_cpus(MP_SELECT_APS, park_this_cpu, NULL);
+ if (ret)
+ return log_ret(ret);
+
+ return 0;
+}
+
+int mp_first_cpu(int cpu_select)
+{
+ struct udevice *dev;
+ int num_cpus;
+ int ret;
+
+ /*
+ * This assumes that CPUs are numbered from 0. This function tries to
+ * avoid assuming the CPU 0 is the boot CPU
+ */
+ if (cpu_select == MP_SELECT_ALL)
+ return 0; /* start with the first one */
+
+ ret = get_bsp(&dev, &num_cpus);
+ if (ret < 0)
+ return log_msg_ret("bsp", ret);
+
+ /* Return boot CPU if requested */
+ if (cpu_select == MP_SELECT_BSP)
+ return ret;
+
+ /* Return something other than the boot CPU, if APs requested */
+ if (cpu_select == MP_SELECT_APS && num_cpus > 1)
+ return ret == 0 ? 1 : 0;
+
+ /* Try to check for an invalid value */
+ if (cpu_select < 0 || cpu_select >= num_cpus)
+ return -EINVAL;
+
+ return cpu_select; /* return the only selected one */
+}
+
+int mp_next_cpu(int cpu_select, int prev_cpu)
+{
+ struct udevice *dev;
+ int num_cpus;
+ int ret;
+ int bsp;
+
+ /* If we selected the BSP or a particular single CPU, we are done */
+ if (!IS_ENABLED(CONFIG_SMP_AP_WORK) || cpu_select == MP_SELECT_BSP ||
+ cpu_select >= 0)
+ return -EFBIG;
+
+ /* Must be doing MP_SELECT_ALL or MP_SELECT_APS; return the next CPU */
+ ret = get_bsp(&dev, &num_cpus);
+ if (ret < 0)
+ return log_msg_ret("bsp", ret);
+ bsp = ret;
+
+ /* Move to the next CPU */
+ assert(prev_cpu >= 0);
+ ret = prev_cpu + 1;
+
+ /* Skip the BSP if needed */
+ if (cpu_select == MP_SELECT_APS && ret == bsp)
+ ret++;
+ if (ret >= num_cpus)
+ return -EFBIG;
+
+ return ret;
+}
+
+int mp_init(void)
+{
+ int num_aps, num_cpus;
+ atomic_t *ap_count;
+ struct udevice *cpu;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_QFW)) {
+ ret = qemu_cpu_fixup();
+ if (ret)
+ return ret;
+ }
+
+ ret = get_bsp(&cpu, &num_cpus);
+ if (ret < 0) {
+ debug("Cannot init boot CPU: err=%d\n", ret);
+ return ret;
+ }
+
+ if (num_cpus < 2)
+ debug("Warning: Only 1 CPU is detected\n");
+
+ ret = check_cpu_devices(num_cpus);
+ if (ret)
+ log_warning("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
+
+ ap_callbacks = calloc(num_cpus, sizeof(struct mp_callback *));
+ if (!ap_callbacks)
+ return -ENOMEM;
+
+ /* Copy needed parameters so that APs have a reference to the plan */
+ mp_info.num_records = ARRAY_SIZE(mp_steps);
+ mp_info.records = mp_steps;
+
+ /* Load the SIPI vector */
+ ret = load_sipi_vector(&ap_count, num_cpus);
+ if (ap_count == NULL)
+ return -ENOENT;
+
+ /*
+ * Make sure SIPI data hits RAM so the APs that come up will see
+ * the startup code even if the caches are disabled
+ */
+ wbinvd();
+
+ /* Start the APs providing number of APs and the cpus_entered field */
+ num_aps = num_cpus - 1;
+ ret = start_aps(num_aps, ap_count);
+ if (ret) {
+ mdelay(1000);
+ debug("%d/%d eventually checked in?\n", atomic_read(ap_count),
+ num_aps);
+ return ret;
+ }
+
+ /* Walk the flight plan for the BSP */
+ ret = bsp_do_flight_plan(cpu, &mp_info, num_aps);
+ if (ret) {
+ debug("CPU init failed: err=%d\n", ret);
+ return ret;
+ }
+ gd->flags |= GD_FLG_SMP_READY;
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/mtrr.c b/roms/u-boot/arch/x86/cpu/mtrr.c
new file mode 100644
index 000000000..166aff380
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/mtrr.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * Memory Type Range Regsters - these are used to tell the CPU whether
+ * memory is cacheable and if so the cache write mode to use.
+ *
+ * These can speed up booting. See the mtrr command.
+ *
+ * Reference: Intel Architecture Software Developer's Manual, Volume 3:
+ * System Programming
+ */
+
+/*
+ * Note that any console output (e.g. debug()) in this file will likely fail
+ * since the MTRR registers are sometimes in flux.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <log.h>
+#include <sort.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Prepare to adjust MTRRs */
+void mtrr_open(struct mtrr_state *state, bool do_caches)
+{
+ if (!gd->arch.has_mtrr)
+ return;
+
+ if (do_caches) {
+ state->enable_cache = dcache_status();
+
+ if (state->enable_cache)
+ disable_caches();
+ }
+ state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
+ wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
+}
+
+/* Clean up after adjusting MTRRs, and enable them */
+void mtrr_close(struct mtrr_state *state, bool do_caches)
+{
+ if (!gd->arch.has_mtrr)
+ return;
+
+ wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
+ if (do_caches && state->enable_cache)
+ enable_caches();
+}
+
+static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
+{
+ u64 mask;
+
+ wrmsrl(MTRR_PHYS_BASE_MSR(reg), start | type);
+ mask = ~(size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask | MTRR_PHYS_MASK_VALID);
+}
+
+void mtrr_read_all(struct mtrr_info *info)
+{
+ int reg_count = mtrr_get_var_count();
+ int i;
+
+ for (i = 0; i < reg_count; i++) {
+ info->mtrr[i].base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
+ info->mtrr[i].mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
+ }
+}
+
+void mtrr_write_all(struct mtrr_info *info)
+{
+ int reg_count = mtrr_get_var_count();
+ struct mtrr_state state;
+ int i;
+
+ for (i = 0; i < reg_count; i++) {
+ mtrr_open(&state, true);
+ wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base);
+ wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask);
+ mtrr_close(&state, true);
+ }
+}
+
+static void write_mtrrs(void *arg)
+{
+ struct mtrr_info *info = arg;
+
+ mtrr_write_all(info);
+}
+
+static void read_mtrrs(void *arg)
+{
+ struct mtrr_info *info = arg;
+
+ mtrr_read_all(info);
+}
+
+/**
+ * mtrr_copy_to_aps() - Copy the MTRRs from the boot CPU to other CPUs
+ *
+ * @return 0 on success, -ve on failure
+ */
+static int mtrr_copy_to_aps(void)
+{
+ struct mtrr_info info;
+ int ret;
+
+ ret = mp_run_on_cpus(MP_SELECT_BSP, read_mtrrs, &info);
+ if (ret == -ENXIO)
+ return 0;
+ else if (ret)
+ return log_msg_ret("bsp", ret);
+
+ ret = mp_run_on_cpus(MP_SELECT_APS, write_mtrrs, &info);
+ if (ret)
+ return log_msg_ret("bsp", ret);
+
+ return 0;
+}
+
+static int h_comp_mtrr(const void *p1, const void *p2)
+{
+ const struct mtrr_request *req1 = p1;
+ const struct mtrr_request *req2 = p2;
+
+ s64 diff = req1->start - req2->start;
+
+ return diff < 0 ? -1 : diff > 0 ? 1 : 0;
+}
+
+int mtrr_commit(bool do_caches)
+{
+ struct mtrr_request *req = gd->arch.mtrr_req;
+ struct mtrr_state state;
+ int ret;
+ int i;
+
+ debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr,
+ gd->arch.mtrr_req_count);
+ if (!gd->arch.has_mtrr)
+ return -ENOSYS;
+
+ debug("open\n");
+ mtrr_open(&state, do_caches);
+ debug("open done\n");
+ qsort(req, gd->arch.mtrr_req_count, sizeof(*req), h_comp_mtrr);
+ for (i = 0; i < gd->arch.mtrr_req_count; i++, req++)
+ set_var_mtrr(i, req->type, req->start, req->size);
+
+ /* Clear the ones that are unused */
+ debug("clear\n");
+ for (; i < mtrr_get_var_count(); i++)
+ wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
+ debug("close\n");
+ mtrr_close(&state, do_caches);
+ debug("mtrr done\n");
+
+ if (gd->flags & GD_FLG_RELOC) {
+ ret = mtrr_copy_to_aps();
+ if (ret)
+ return log_msg_ret("copy", ret);
+ }
+
+ return 0;
+}
+
+int mtrr_add_request(int type, uint64_t start, uint64_t size)
+{
+ struct mtrr_request *req;
+ uint64_t mask;
+
+ debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count);
+ if (!gd->arch.has_mtrr)
+ return -ENOSYS;
+
+ if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
+ return -ENOSPC;
+ req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
+ req->type = type;
+ req->start = start;
+ req->size = size;
+ debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1,
+ req->type, req->start, req->size);
+ mask = ~(req->size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ mask |= MTRR_PHYS_MASK_VALID;
+ debug(" %016llx %016llx\n", req->start | req->type, mask);
+
+ return 0;
+}
+
+int mtrr_get_var_count(void)
+{
+ return msr_read(MSR_MTRR_CAP_MSR).lo & MSR_MTRR_CAP_VCNT;
+}
+
+static int get_free_var_mtrr(void)
+{
+ struct msr_t maskm;
+ int vcnt;
+ int i;
+
+ vcnt = mtrr_get_var_count();
+
+ /* Identify the first var mtrr which is not valid */
+ for (i = 0; i < vcnt; i++) {
+ maskm = msr_read(MTRR_PHYS_MASK_MSR(i));
+ if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0)
+ return i;
+ }
+
+ /* No free var mtrr */
+ return -ENOSPC;
+}
+
+int mtrr_set_next_var(uint type, uint64_t start, uint64_t size)
+{
+ int mtrr;
+
+ mtrr = get_free_var_mtrr();
+ if (mtrr < 0)
+ return mtrr;
+
+ set_var_mtrr(mtrr, type, start, size);
+ debug("MTRR %x: start=%x, size=%x\n", mtrr, (uint)start, (uint)size);
+
+ return 0;
+}
+
+/** enum mtrr_opcode - supported operations for mtrr_do_oper() */
+enum mtrr_opcode {
+ MTRR_OP_SET,
+ MTRR_OP_SET_VALID,
+};
+
+/**
+ * struct mtrr_oper - An MTRR operation to perform on a CPU
+ *
+ * @opcode: Indicates operation to perform
+ * @reg: MTRR reg number to select (0-7, -1 = all)
+ * @valid: Valid value to write for MTRR_OP_SET_VALID
+ * @base: Base value to write for MTRR_OP_SET
+ * @mask: Mask value to write for MTRR_OP_SET
+ */
+struct mtrr_oper {
+ enum mtrr_opcode opcode;
+ int reg;
+ bool valid;
+ u64 base;
+ u64 mask;
+};
+
+static void mtrr_do_oper(void *arg)
+{
+ struct mtrr_oper *oper = arg;
+ u64 mask;
+
+ switch (oper->opcode) {
+ case MTRR_OP_SET_VALID:
+ mask = native_read_msr(MTRR_PHYS_MASK_MSR(oper->reg));
+ if (oper->valid)
+ mask |= MTRR_PHYS_MASK_VALID;
+ else
+ mask &= ~MTRR_PHYS_MASK_VALID;
+ wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), mask);
+ break;
+ case MTRR_OP_SET:
+ wrmsrl(MTRR_PHYS_BASE_MSR(oper->reg), oper->base);
+ wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), oper->mask);
+ break;
+ }
+}
+
+static int mtrr_start_op(int cpu_select, struct mtrr_oper *oper)
+{
+ struct mtrr_state state;
+ int ret;
+
+ mtrr_open(&state, true);
+ ret = mp_run_on_cpus(cpu_select, mtrr_do_oper, oper);
+ mtrr_close(&state, true);
+ if (ret)
+ return log_msg_ret("run", ret);
+
+ return 0;
+}
+
+int mtrr_set_valid(int cpu_select, int reg, bool valid)
+{
+ struct mtrr_oper oper;
+
+ oper.opcode = MTRR_OP_SET_VALID;
+ oper.reg = reg;
+ oper.valid = valid;
+
+ return mtrr_start_op(cpu_select, &oper);
+}
+
+int mtrr_set(int cpu_select, int reg, u64 base, u64 mask)
+{
+ struct mtrr_oper oper;
+
+ oper.opcode = MTRR_OP_SET;
+ oper.reg = reg;
+ oper.base = base;
+ oper.mask = mask;
+
+ return mtrr_start_op(cpu_select, &oper);
+}
diff --git a/roms/u-boot/arch/x86/cpu/pci.c b/roms/u-boot/arch/x86/cpu/pci.c
new file mode 100644
index 000000000..d4f9290ca
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/pci.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008,2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+int pci_x86_read_config(pci_dev_t bdf, uint offset, ulong *valuep,
+ enum pci_size_t size)
+{
+ outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
+ switch (size) {
+ case PCI_SIZE_8:
+ *valuep = inb(PCI_REG_DATA + (offset & 3));
+ break;
+ case PCI_SIZE_16:
+ *valuep = inw(PCI_REG_DATA + (offset & 2));
+ break;
+ case PCI_SIZE_32:
+ *valuep = inl(PCI_REG_DATA);
+ break;
+ }
+
+ return 0;
+}
+
+int pci_x86_write_config(pci_dev_t bdf, uint offset, ulong value,
+ enum pci_size_t size)
+{
+ outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
+ switch (size) {
+ case PCI_SIZE_8:
+ outb(value, PCI_REG_DATA + (offset & 3));
+ break;
+ case PCI_SIZE_16:
+ outw(value, PCI_REG_DATA + (offset & 2));
+ break;
+ case PCI_SIZE_32:
+ outl(value, PCI_REG_DATA);
+ break;
+ }
+
+ return 0;
+}
+
+int pci_x86_clrset_config(pci_dev_t bdf, uint offset, ulong clr, ulong set,
+ enum pci_size_t size)
+{
+ ulong value;
+ int ret;
+
+ ret = pci_x86_read_config(bdf, offset, &value, size);
+ if (ret)
+ return ret;
+ value &= ~clr;
+ value |= set;
+
+ return pci_x86_write_config(bdf, offset, value, size);
+}
+
+void pci_assign_irqs(int bus, int device, u8 irq[4])
+{
+ pci_dev_t bdf;
+ int func;
+ u16 vendor;
+ u8 pin, line;
+
+ for (func = 0; func < 8; func++) {
+ bdf = PCI_BDF(bus, device, func);
+ pci_read_config16(bdf, PCI_VENDOR_ID, &vendor);
+ if (vendor == 0xffff || vendor == 0x0000)
+ continue;
+
+ pci_read_config8(bdf, PCI_INTERRUPT_PIN, &pin);
+
+ /* PCI spec says all values except 1..4 are reserved */
+ if ((pin < 1) || (pin > 4))
+ continue;
+
+ line = irq[pin - 1];
+ if (!line)
+ continue;
+
+ debug("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n",
+ line, bus, device, func, 'A' + pin - 1);
+
+ pci_write_config8(bdf, PCI_INTERRUPT_LINE, line);
+ }
+}
diff --git a/roms/u-boot/arch/x86/cpu/qemu/Kconfig b/roms/u-boot/arch/x86/cpu/qemu/Kconfig
new file mode 100644
index 000000000..f8f2f6473
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/Kconfig
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+
+config QEMU
+ bool
+ select ARCH_EARLY_INIT_R
+ imply AHCI_PCI
+ imply E1000
+ imply SCSI
+ imply SCSI_AHCI
+ imply SYS_NS16550
+ imply USB
+ imply USB_EHCI_HCD
+ imply VIDEO_VESA
+
+if QEMU
+
+config SYS_CAR_ADDR
+ hex
+ default 0x10000
+
+config SYS_CAR_SIZE
+ hex
+ default 0x10000
+
+config ACPI_PM1_BASE
+ hex
+ default 0xe400
+ help
+ ACPI Power Management 1 (PM1) i/o-mapped base address.
+ This device is defined in ACPI specification, with 16 bytes in size.
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/qemu/Makefile b/roms/u-boot/arch/x86/cpu/qemu/Makefile
new file mode 100644
index 000000000..b7dd5bd46
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+
+ifndef CONFIG_$(SPL_)X86_64
+obj-y += car.o
+endif
+obj-y += dram.o
+obj-y += qemu.o
+obj-$(CONFIG_QFW) += cpu.o e820.o
diff --git a/roms/u-boot/arch/x86/cpu/qemu/car.S b/roms/u-boot/arch/x86/cpu/qemu/car.S
new file mode 100644
index 000000000..466b4876e
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/car.S
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <config.h>
+#include <asm/post.h>
+
+.globl car_init
+car_init:
+ /* Save the BIST result */
+ movl %eax, %ebp
+
+ post_code(POST_CAR_START)
+
+ /*
+ * Since we know we are running inside emulator,
+ * we can do nothing here for CAR initialization.
+ */
+
+ /* Restore the BIST result */
+ movl %ebp, %eax
+
+ post_code(POST_CAR_CPU_CACHE)
+ jmp car_init_ret
diff --git a/roms/u-boot/arch/x86/cpu/qemu/cpu.c b/roms/u-boot/arch/x86/cpu/qemu/cpu.c
new file mode 100644
index 000000000..735b65608
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/cpu.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Miao Yan <yanmiaobest@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <qfw.h>
+#include <asm/cpu.h>
+
+int cpu_qemu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ if (size < CPU_MAX_NAME_LEN)
+ return -ENOSPC;
+
+ cpu_get_name(buf);
+
+ return 0;
+}
+
+static int cpu_qemu_get_count(const struct udevice *dev)
+{
+ int ret;
+ struct udevice *qfw_dev;
+
+ ret = qfw_get_dev(&qfw_dev);
+ if (ret)
+ return ret;
+
+ return qfw_online_cpus(qfw_dev);
+}
+
+static const struct cpu_ops cpu_qemu_ops = {
+ .get_desc = cpu_qemu_get_desc,
+ .get_count = cpu_qemu_get_count,
+};
+
+static const struct udevice_id cpu_qemu_ids[] = {
+ { .compatible = "cpu-qemu" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_qemu_drv) = {
+ .name = "cpu_qemu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_qemu_ids,
+ .ops = &cpu_qemu_ops,
+};
diff --git a/roms/u-boot/arch/x86/cpu/qemu/dram.c b/roms/u-boot/arch/x86/cpu/qemu/dram.c
new file mode 100644
index 000000000..c17455012
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/dram.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/global_data.h>
+#include <asm/post.h>
+#include <asm/arch/qemu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 qemu_get_low_memory_size(void)
+{
+ u32 ram;
+
+ outb(HIGH_RAM_ADDR, CMOS_ADDR_PORT);
+ ram = ((u32)inb(CMOS_DATA_PORT)) << 14;
+ outb(LOW_RAM_ADDR, CMOS_ADDR_PORT);
+ ram |= ((u32)inb(CMOS_DATA_PORT)) << 6;
+ ram += 16 * 1024;
+
+ return ram * 1024;
+}
+
+u64 qemu_get_high_memory_size(void)
+{
+ u64 ram;
+
+ outb(HIGH_HIGHRAM_ADDR, CMOS_ADDR_PORT);
+ ram = ((u64)inb(CMOS_DATA_PORT)) << 22;
+ outb(MID_HIGHRAM_ADDR, CMOS_ADDR_PORT);
+ ram |= ((u64)inb(CMOS_DATA_PORT)) << 14;
+ outb(LOW_HIGHRAM_ADDR, CMOS_ADDR_PORT);
+ ram |= ((u64)inb(CMOS_DATA_PORT)) << 6;
+
+ return ram * 1024;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = qemu_get_low_memory_size();
+ gd->ram_size += qemu_get_high_memory_size();
+ post_code(POST_DRAM);
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ u64 high_mem_size;
+
+ gd->bd->bi_dram[0].start = 0;
+ gd->bd->bi_dram[0].size = qemu_get_low_memory_size();
+
+ high_mem_size = qemu_get_high_memory_size();
+ if (high_mem_size) {
+ gd->bd->bi_dram[1].start = SZ_4G;
+ gd->bd->bi_dram[1].size = high_mem_size;
+ }
+
+ return 0;
+}
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return qemu_get_low_memory_size();
+}
diff --git a/roms/u-boot/arch/x86/cpu/qemu/e820.c b/roms/u-boot/arch/x86/cpu/qemu/e820.c
new file mode 100644
index 000000000..19e54c520
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/e820.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * QEMU x86 specific E820 table generation
+ *
+ * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
+ * (C) Copyright 2019 Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <env_internal.h>
+#include <malloc.h>
+#include <asm/e820.h>
+#include <asm/arch/qemu.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned int install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ u64 high_mem_size;
+ int n = 0;
+
+ entries[n].addr = 0;
+ entries[n].size = ISA_START_ADDRESS;
+ entries[n].type = E820_RAM;
+ n++;
+
+ entries[n].addr = ISA_START_ADDRESS;
+ entries[n].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
+ entries[n].type = E820_RESERVED;
+ n++;
+
+ /*
+ * since we use memalign(malloc) to allocate high memory for
+ * storing ACPI tables, we need to reserve them in e820 tables,
+ * otherwise kernel will reclaim them and data will be corrupted
+ */
+ entries[n].addr = ISA_END_ADDRESS;
+ entries[n].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS;
+ entries[n].type = E820_RAM;
+ n++;
+
+ /* for simplicity, reserve entire malloc space */
+ entries[n].addr = gd->relocaddr - TOTAL_MALLOC_LEN;
+ entries[n].size = TOTAL_MALLOC_LEN;
+ entries[n].type = E820_RESERVED;
+ n++;
+
+ entries[n].addr = gd->relocaddr;
+ entries[n].size = qemu_get_low_memory_size() - gd->relocaddr;
+ entries[n].type = E820_RESERVED;
+ n++;
+
+ entries[n].addr = CONFIG_PCIE_ECAM_BASE;
+ entries[n].size = CONFIG_PCIE_ECAM_SIZE;
+ entries[n].type = E820_RESERVED;
+ n++;
+
+ high_mem_size = qemu_get_high_memory_size();
+ if (high_mem_size) {
+ entries[n].addr = SZ_4G;
+ entries[n].size = high_mem_size;
+ entries[n].type = E820_RAM;
+ n++;
+ }
+
+ return n;
+}
diff --git a/roms/u-boot/arch/x86/cpu/qemu/qemu.c b/roms/u-boot/arch/x86/cpu/qemu/qemu.c
new file mode 100644
index 000000000..e54082df7
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qemu/qemu.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <pci.h>
+#include <qfw.h>
+#include <dm/platdata.h>
+#include <asm/irq.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/arch/device.h>
+#include <asm/arch/qemu.h>
+
+static bool i440fx;
+
+#if CONFIG_IS_ENABLED(QFW_PIO)
+U_BOOT_DRVINFO(x86_qfw_pio) = {
+ .name = "qfw_pio",
+};
+#endif
+
+static void enable_pm_piix(void)
+{
+ u8 en;
+ u16 cmd;
+
+ /* Set the PM I/O base */
+ pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
+
+ /* Enable access to the PM I/O space */
+ pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_IO;
+ pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
+
+ /* PM I/O Space Enable (PMIOSE) */
+ pci_read_config8(PIIX_PM, PMREGMISC, &en);
+ en |= PMIOSE;
+ pci_write_config8(PIIX_PM, PMREGMISC, en);
+}
+
+static void enable_pm_ich9(void)
+{
+ /* Set the PM I/O base */
+ pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
+}
+
+static void qemu_chipset_init(void)
+{
+ u16 device, xbcs;
+ int pam, i;
+
+ /*
+ * i440FX and Q35 chipset have different PAM register offset, but with
+ * the same bitfield layout. Here we determine the offset based on its
+ * PCI device ID.
+ */
+ pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
+ i440fx = (device == PCI_DEVICE_ID_INTEL_82441);
+ pam = i440fx ? I440FX_PAM : Q35_PAM;
+
+ /*
+ * Initialize Programmable Attribute Map (PAM) Registers
+ *
+ * Configure legacy segments C/D/E/F to system RAM
+ */
+ for (i = 0; i < PAM_NUM; i++)
+ pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
+
+ if (i440fx) {
+ /*
+ * Enable legacy IDE I/O ports decode
+ *
+ * Note: QEMU always decode legacy IDE I/O port on PIIX chipset.
+ * However Linux ata_piix driver does sanity check on these two
+ * registers to see whether legacy ports decode is turned on.
+ * This is to make Linux ata_piix driver happy.
+ */
+ pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
+ pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
+
+ /* Enable I/O APIC */
+ pci_read_config16(PIIX_ISA, XBCS, &xbcs);
+ xbcs |= APIC_EN;
+ pci_write_config16(PIIX_ISA, XBCS, xbcs);
+
+ enable_pm_piix();
+ } else {
+ /* Configure PCIe ECAM base address */
+ pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
+ CONFIG_PCIE_ECAM_BASE | BAR_EN);
+
+ enable_pm_ich9();
+ }
+}
+
+#if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT)
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ post_code(POST_CPU_INFO);
+ return default_print_cpuinfo();
+}
+#endif
+
+int arch_early_init_r(void)
+{
+ qemu_chipset_init();
+
+ return 0;
+}
+
+#ifdef CONFIG_GENERATE_MP_TABLE
+int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
+{
+ u8 irq;
+
+ if (i440fx) {
+ /*
+ * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
+ * connected to I/O APIC INTPIN#16-19. Instead they are routed
+ * to an irq number controled by the PIRQ routing register.
+ */
+ pci_read_config8(PCI_BDF(bus, dev, func),
+ PCI_INTERRUPT_LINE, &irq);
+ } else {
+ /*
+ * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
+ * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
+ */
+ irq = pirq < 8 ? pirq + 16 : pirq + 12;
+ }
+
+ return irq;
+}
+#endif
diff --git a/roms/u-boot/arch/x86/cpu/qfw_cpu.c b/roms/u-boot/arch/x86/cpu/qfw_cpu.c
new file mode 100644
index 000000000..ee00b8fe7
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/qfw_cpu.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <malloc.h>
+#include <qfw.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+#include <dm/root.h>
+
+int qemu_cpu_fixup(void)
+{
+ int ret;
+ int cpu_num;
+ int cpu_online;
+ struct uclass *uc;
+ struct udevice *dev, *pdev, *qfwdev;
+ struct cpu_plat *plat;
+ char *cpu;
+
+ /* This will cause the CPUs devices to be bound */
+ ret = uclass_get(UCLASS_CPU, &uc);
+ if (ret)
+ return ret;
+
+ /* first we need to find '/cpus' */
+ for (device_find_first_child(dm_root(), &pdev);
+ pdev;
+ device_find_next_child(&pdev)) {
+ if (!strcmp(pdev->name, "cpus"))
+ break;
+ }
+ if (!pdev) {
+ printf("unable to find cpus device\n");
+ return -ENODEV;
+ }
+
+ /* get qfw dev */
+ ret = qfw_get_dev(&qfwdev);
+ if (ret) {
+ printf("unable to find qfw device\n");
+ return ret;
+ }
+
+ /* calculate cpus that are already bound */
+ cpu_num = 0;
+ for (uclass_find_first_device(UCLASS_CPU, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ cpu_num++;
+ }
+
+ /* get actual cpu number */
+ cpu_online = qfw_online_cpus(qfwdev);
+ if (cpu_online < 0) {
+ printf("unable to get online cpu number: %d\n", cpu_online);
+ return cpu_online;
+ }
+
+ /* bind addtional cpus */
+ dev = NULL;
+ for (; cpu_num < cpu_online; cpu_num++) {
+ /*
+ * allocate device name here as device_bind_driver() does
+ * not copy device name, 8 bytes are enough for
+ * sizeof("cpu@") + 3 digits cpu number + '\0'
+ */
+ cpu = malloc(8);
+ if (!cpu) {
+ printf("unable to allocate device name\n");
+ return -ENOMEM;
+ }
+ sprintf(cpu, "cpu@%d", cpu_num);
+ ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev);
+ if (ret) {
+ printf("binding cpu@%d failed: %d\n", cpu_num, ret);
+ return ret;
+ }
+ plat = dev_get_parent_plat(dev);
+ plat->cpu_id = cpu_num;
+ }
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/Kconfig b/roms/u-boot/arch/x86/cpu/quark/Kconfig
new file mode 100644
index 000000000..2fee38aed
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/Kconfig
@@ -0,0 +1,138 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+
+config INTEL_QUARK
+ bool
+ select HAVE_RMU
+ select ARCH_EARLY_INIT_R
+ select ARCH_MISC_INIT
+ imply ENABLE_MRC_CACHE
+ imply ETH_DESIGNWARE
+ imply ICH_SPI
+ imply INTEL_ICH6_GPIO
+ imply MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply SPI_FLASH
+ imply SYS_NS16550
+ imply USB
+ imply USB_EHCI_HCD
+
+if INTEL_QUARK
+
+config HAVE_RMU
+ bool "Add a Remote Management Unit (RMU) binary"
+ select ROM_NEEDS_BLOBS
+ help
+ Select this option to add a Remote Management Unit (RMU) binary
+ to the resulting U-Boot image. It is a data block (up to 64K) of
+ machine-specific code which must be put in the flash for the RMU
+ within the Quark SoC processor to access when powered up before
+ system BIOS is executed.
+
+config RMU_FILE
+ string "Remote Management Unit (RMU) binary filename"
+ depends on HAVE_RMU
+ default "rmu.bin"
+ help
+ The filename of the file to use as Remote Management Unit (RMU)
+ binary in the board directory.
+
+config RMU_ADDR
+ hex "Remote Management Unit (RMU) binary location"
+ depends on HAVE_RMU
+ default 0xfff00000
+ help
+ The location of the RMU binary is determined by a strap. It must be
+ put in flash at a location matching the strap-determined base address.
+
+ The default base address of 0xfff00000 indicates that the binary must
+ be located at offset 0 from the beginning of a 1MB flash device.
+
+config HAVE_CMC
+ bool
+ default HAVE_RMU
+
+config CMC_FILE
+ string
+ depends on HAVE_CMC
+ default RMU_FILE
+
+config CMC_ADDR
+ hex
+ depends on HAVE_CMC
+ default RMU_ADDR
+
+config ESRAM_BASE
+ hex
+ default 0x80000000
+ help
+ Embedded SRAM (eSRAM) memory-mapped base address.
+
+config PCIE_ECAM_BASE
+ hex
+ default 0xe0000000
+
+config RCBA_BASE
+ hex
+ default 0xfed1c000
+ help
+ Root Complex register block memory-mapped base address.
+
+config ACPI_PM1_BASE
+ hex
+ default 0x1000
+ help
+ ACPI Power Management 1 (PM1) i/o-mapped base address.
+ This device is defined in ACPI specification, with 16 bytes in size.
+
+config ACPI_PBLK_BASE
+ hex
+ default 0x1010
+ help
+ ACPI Processor Block (PBLK) i/o-mapped base address.
+ This device is defined in ACPI specification, with 16 bytes in size.
+
+config SPI_DMA_BASE
+ hex
+ default 0x1020
+ help
+ SPI DMA i/o-mapped base address.
+
+config GPIO_BASE
+ hex
+ default 0x1080
+ help
+ GPIO i/o-mapped base address.
+
+config ACPI_GPE0_BASE
+ hex
+ default 0x1100
+ help
+ ACPI General Purpose Event 0 (GPE0) i/o-mapped base address.
+ This device is defined in ACPI specification, with 64 bytes in size.
+
+config WDT_BASE
+ hex
+ default 0x1140
+ help
+ Watchdog timer i/o-mapped base address.
+
+config SYS_CAR_ADDR
+ hex
+ default ESRAM_BASE
+
+config SYS_CAR_SIZE
+ hex
+ default 0x8000
+ help
+ Space in bytes in eSRAM used as Cache-As-ARM (CAR).
+ Note this size must not exceed eSRAM's total size.
+
+config X86_TSC_TIMER_EARLY_FREQ
+ int
+ default 400
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/quark/Makefile b/roms/u-boot/arch/x86/cpu/quark/Makefile
new file mode 100644
index 000000000..7039f8b9b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+
+obj-y += car.o dram.o msg_port.o quark.o
+obj-y += mrc.o mrc_util.o hte.o smc.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
diff --git a/roms/u-boot/arch/x86/cpu/quark/acpi.c b/roms/u-boot/arch/x86/cpu/quark/acpi.c
new file mode 100644
index 000000000..82b776ff6
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/acpi.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <acpi/acpi_table.h>
+#include <asm/processor.h>
+#include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
+#include <asm/arch/iomap.h>
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+ void *dsdt)
+{
+ struct acpi_table_header *header = &(fadt->header);
+ u16 pmbase = ACPI_PM1_BASE_ADDRESS;
+
+ memset((void *)fadt, 0, sizeof(struct acpi_fadt));
+
+ acpi_fill_header(header, "FACP");
+ header->length = sizeof(struct acpi_fadt);
+ header->revision = 4;
+
+ fadt->firmware_ctrl = (u32)facs;
+ fadt->dsdt = (u32)dsdt;
+ fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
+ fadt->sci_int = 9;
+ fadt->smi_cmd = 0;
+ fadt->acpi_enable = 0;
+ fadt->acpi_disable = 0;
+ fadt->s4bios_req = 0;
+ fadt->pstate_cnt = 0;
+ fadt->pm1a_evt_blk = pmbase;
+ fadt->pm1b_evt_blk = 0x0;
+ fadt->pm1a_cnt_blk = pmbase + 0x4;
+ fadt->pm1b_cnt_blk = 0x0;
+ fadt->pm2_cnt_blk = 0x0;
+ fadt->pm_tmr_blk = pmbase + 0x8;
+ fadt->gpe0_blk = ACPI_GPE0_BASE_ADDRESS;
+ fadt->gpe1_blk = 0;
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm2_cnt_len = 0;
+ fadt->pm_tmr_len = 4;
+ fadt->gpe0_blk_len = 8;
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 0;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+ fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+ fadt->flush_size = 0;
+ fadt->flush_stride = 0;
+ fadt->duty_offset = 1;
+ fadt->duty_width = 3;
+ fadt->day_alrm = 0x00;
+ fadt->mon_alrm = 0x00;
+ fadt->century = 0x00;
+ fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES;
+ fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_RESET_REGISTER |
+ ACPI_FADT_PLATFORM_CLOCK;
+
+ fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->reset_reg.addrl = IO_PORT_RESET;
+ fadt->reset_reg.addrh = 0;
+ fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
+
+ fadt->x_firmware_ctl_l = (u32)facs;
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (u32)dsdt;
+ fadt->x_dsdt_h = 0;
+
+ fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
+ fadt->x_pm1a_evt_blk.bit_offset = 0;
+ fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
+ fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_evt_blk.bit_width = 0;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.access_size = 0;
+ fadt->x_pm1b_evt_blk.addrl = 0x0;
+ fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
+ fadt->x_pm1a_cnt_blk.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+ fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
+ fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_cnt_blk.bit_width = 0;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.access_size = 0;
+ fadt->x_pm1b_cnt_blk.addrl = 0x0;
+ fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
+ fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
+ fadt->x_pm_tmr_blk.bit_offset = 0;
+ fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
+ fadt->x_pm_tmr_blk.addrh = 0x0;
+
+ fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
+ fadt->x_gpe0_blk.addrh = 0x0;
+
+ fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.access_size = 0;
+ fadt->x_gpe1_blk.addrl = 0x0;
+ fadt->x_gpe1_blk.addrh = 0x0;
+
+ header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+ /* quark is a uni-processor */
+ gnvs->pcnt = 1;
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/car.S b/roms/u-boot/arch/x86/cpu/quark/car.S
new file mode 100644
index 000000000..48d5167c7
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/car.S
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <config.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/arch/quark.h>
+#include <asm/arch/msg_port.h>
+
+.globl car_init
+car_init:
+ post_code(POST_CAR_START)
+
+ /*
+ * Quark SoC contains an embedded 512KiB SRAM (eSRAM) that is
+ * initialized by hardware. eSRAM is the ideal place to be used
+ * for Cache-As-RAM (CAR) before system memory is available.
+ *
+ * Relocate this eSRAM to a suitable location in the physical
+ * memory map and enable it.
+ */
+
+ /* Host Memory Bound Register P03h:R08h */
+ mov $((MSG_PORT_HOST_BRIDGE << 16) | (HM_BOUND << 8)), %eax
+ mov $(DRAM_BASE + DRAM_MAX_SIZE + ESRAM_SIZE), %edx
+ lea 1f, %esp
+ jmp msg_port_write
+1:
+
+ /* eSRAM Block Page Control Register P05h:R82h */
+ mov $((MSG_PORT_MEM_MGR << 16) | (ESRAM_BLK_CTRL << 8)), %eax
+ mov $(ESRAM_BLOCK_MODE | (CONFIG_ESRAM_BASE >> 24)), %edx
+ lea 2f, %esp
+ jmp msg_port_write
+2:
+
+ post_code(POST_CAR_CPU_CACHE)
+ jmp car_init_ret
+
+msg_port_read:
+ /*
+ * Parameter:
+ * eax[23:16] - Message Port ID
+ * eax[15:08] - Register Address
+ *
+ * Return Value:
+ * eax - Message Port Register value
+ *
+ * Return Address: esp
+ */
+
+ or $((MSG_OP_READ << 24) | MSG_BYTE_ENABLE), %eax
+ mov %eax, %ebx
+
+ /* Write MCR B0:D0:F0:RD0 */
+ mov $(PCI_CFG_EN | MSG_CTRL_REG), %eax
+ mov $PCI_REG_ADDR, %dx
+ out %eax, %dx
+ mov $PCI_REG_DATA, %dx
+ mov %ebx, %eax
+ out %eax, %dx
+
+ /* Read MDR B0:D0:F0:RD4 */
+ mov $(PCI_CFG_EN | MSG_DATA_REG), %eax
+ mov $PCI_REG_ADDR, %dx
+ out %eax, %dx
+ mov $PCI_REG_DATA, %dx
+ in %dx, %eax
+
+ jmp *%esp
+
+msg_port_write:
+ /*
+ * Parameter:
+ * eax[23:16] - Message Port ID
+ * eax[15:08] - Register Address
+ * edx - Message Port Register value to write
+ *
+ * Return Address: esp
+ */
+
+ or $((MSG_OP_WRITE << 24) | MSG_BYTE_ENABLE), %eax
+ mov %eax, %esi
+ mov %edx, %edi
+
+ /* Write MDR B0:D0:F0:RD4 */
+ mov $(PCI_CFG_EN | MSG_DATA_REG), %eax
+ mov $PCI_REG_ADDR, %dx
+ out %eax, %dx
+ mov $PCI_REG_DATA, %dx
+ mov %edi, %eax
+ out %eax, %dx
+
+ /* Write MCR B0:D0:F0:RD0 */
+ mov $(PCI_CFG_EN | MSG_CTRL_REG), %eax
+ mov $PCI_REG_ADDR, %dx
+ out %eax, %dx
+ mov $PCI_REG_DATA, %dx
+ mov %esi, %eax
+ out %eax, %dx
+
+ jmp *%esp
diff --git a/roms/u-boot/arch/x86/cpu/quark/dram.c b/roms/u-boot/arch/x86/cpu/quark/dram.c
new file mode 100644
index 000000000..2287dce12
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/dram.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
+#include <asm/mrccache.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params)
+{
+ struct mrc_data_container *cache;
+ struct mrc_region entry;
+ int ret;
+
+ ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
+ if (ret)
+ return ret;
+
+ cache = mrccache_find_current(&entry);
+ if (!cache)
+ return -ENOENT;
+
+ debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
+ cache->data, cache->data_size, cache->checksum);
+
+ /* copy mrc cache to the mrc_params */
+ memcpy(&mrc_params->timings, cache->data, cache->data_size);
+
+ return 0;
+}
+
+static int mrc_configure_params(struct mrc_params *mrc_params)
+{
+ const void *blob = gd->fdt_blob;
+ int node;
+ int mrc_flags;
+
+ node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_QRK_MRC);
+ if (node < 0) {
+ debug("%s: Cannot find MRC node\n", __func__);
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_ENABLE_MRC_CACHE
+ mrc_params->boot_mode = prepare_mrc_cache(mrc_params);
+ if (mrc_params->boot_mode)
+ mrc_params->boot_mode = BM_COLD;
+ else
+ mrc_params->boot_mode = BM_FAST;
+#else
+ mrc_params->boot_mode = BM_COLD;
+#endif
+
+ /*
+ * TODO:
+ *
+ * We need determine ECC by pin strap state
+ *
+ * Disable ECC by default for now
+ */
+ mrc_params->ecc_enables = 0;
+
+ mrc_flags = fdtdec_get_int(blob, node, "flags", 0);
+ if (mrc_flags & MRC_FLAG_SCRAMBLE_EN)
+ mrc_params->scrambling_enables = 1;
+ else
+ mrc_params->scrambling_enables = 0;
+
+ mrc_params->dram_width = fdtdec_get_int(blob, node, "dram-width", 0);
+ mrc_params->ddr_speed = fdtdec_get_int(blob, node, "dram-speed", 0);
+ mrc_params->ddr_type = fdtdec_get_int(blob, node, "dram-type", 0);
+
+ mrc_params->rank_enables = fdtdec_get_int(blob, node, "rank-mask", 0);
+ mrc_params->channel_enables = fdtdec_get_int(blob, node,
+ "chan-mask", 0);
+ mrc_params->channel_width = fdtdec_get_int(blob, node,
+ "chan-width", 0);
+ mrc_params->address_mode = fdtdec_get_int(blob, node, "addr-mode", 0);
+
+ mrc_params->refresh_rate = fdtdec_get_int(blob, node,
+ "refresh-rate", 0);
+ mrc_params->sr_temp_range = fdtdec_get_int(blob, node,
+ "sr-temp-range", 0);
+ mrc_params->ron_value = fdtdec_get_int(blob, node,
+ "ron-value", 0);
+ mrc_params->rtt_nom_value = fdtdec_get_int(blob, node,
+ "rtt-nom-value", 0);
+ mrc_params->rd_odt_value = fdtdec_get_int(blob, node,
+ "rd-odt-value", 0);
+
+ mrc_params->params.density = fdtdec_get_int(blob, node,
+ "dram-density", 0);
+ mrc_params->params.cl = fdtdec_get_int(blob, node, "dram-cl", 0);
+ mrc_params->params.ras = fdtdec_get_int(blob, node, "dram-ras", 0);
+ mrc_params->params.wtr = fdtdec_get_int(blob, node, "dram-wtr", 0);
+ mrc_params->params.rrd = fdtdec_get_int(blob, node, "dram-rrd", 0);
+ mrc_params->params.faw = fdtdec_get_int(blob, node, "dram-faw", 0);
+
+ debug("MRC dram_width %d\n", mrc_params->dram_width);
+ debug("MRC rank_enables %d\n", mrc_params->rank_enables);
+ debug("MRC ddr_speed %d\n", mrc_params->ddr_speed);
+ debug("MRC flags: %s\n",
+ (mrc_params->scrambling_enables) ? "SCRAMBLE_EN" : "");
+
+ debug("MRC density=%d tCL=%d tRAS=%d tWTR=%d tRRD=%d tFAW=%d\n",
+ mrc_params->params.density, mrc_params->params.cl,
+ mrc_params->params.ras, mrc_params->params.wtr,
+ mrc_params->params.rrd, mrc_params->params.faw);
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ struct mrc_params mrc_params;
+#ifdef CONFIG_ENABLE_MRC_CACHE
+ char *cache;
+#endif
+ int ret;
+
+ memset(&mrc_params, 0, sizeof(struct mrc_params));
+ ret = mrc_configure_params(&mrc_params);
+ if (ret)
+ return ret;
+
+ /* Set up the DRAM by calling the memory reference code */
+ mrc_init(&mrc_params);
+ if (mrc_params.status)
+ return -EIO;
+
+ gd->ram_size = mrc_params.mem_size;
+ post_code(POST_DRAM);
+
+ /* variable range MTRR#2: RAM area */
+ disable_caches();
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_RAM),
+ 0 | MTRR_TYPE_WRBACK);
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_RAM),
+ (~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID);
+ enable_caches();
+
+#ifdef CONFIG_ENABLE_MRC_CACHE
+ cache = malloc(sizeof(struct mrc_timings));
+ if (cache) {
+ struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
+
+ memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings));
+ mrc->buf = cache;
+ mrc->len = sizeof(struct mrc_timings);
+ }
+#endif
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = 0;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+
+ return 0;
+}
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return gd->ram_size;
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/hte.c b/roms/u-boot/arch/x86/cpu/quark/hte.c
new file mode 100644
index 000000000..df1477935
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/hte.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+#include <common.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "hte.h"
+
+/**
+ * Enable HTE to detect all possible errors for the given training parameters
+ * (per-bit or full byte lane).
+ */
+static void hte_enable_all_errors(void)
+{
+ msg_port_write(HTE, 0x000200a2, 0xffffffff);
+ msg_port_write(HTE, 0x000200a3, 0x000000ff);
+ msg_port_write(HTE, 0x000200a4, 0x00000000);
+}
+
+/**
+ * Go and read the HTE register in order to find any error
+ *
+ * @return: The errors detected in the HTE status register
+ */
+static u32 hte_check_errors(void)
+{
+ return msg_port_read(HTE, 0x000200a7);
+}
+
+/**
+ * Wait until HTE finishes
+ */
+static void hte_wait_for_complete(void)
+{
+ u32 tmp;
+
+ ENTERFN();
+
+ do {} while ((msg_port_read(HTE, 0x00020012) & (1 << 30)) != 0);
+
+ tmp = msg_port_read(HTE, 0x00020011);
+ tmp |= (1 << 9);
+ tmp &= ~((1 << 12) | (1 << 13));
+ msg_port_write(HTE, 0x00020011, tmp);
+
+ LEAVEFN();
+}
+
+/**
+ * Clear registers related with errors in the HTE
+ */
+static void hte_clear_error_regs(void)
+{
+ u32 tmp;
+
+ /*
+ * Clear all HTE errors and enable error checking
+ * for burst and chunk.
+ */
+ tmp = msg_port_read(HTE, 0x000200a1);
+ tmp |= (1 << 8);
+ msg_port_write(HTE, 0x000200a1, tmp);
+}
+
+/**
+ * Execute a basic single-cache-line memory write/read/verify test using simple
+ * constant pattern, different for READ_TRAIN and WRITE_TRAIN modes.
+ *
+ * See hte_basic_write_read() which is the external visible wrapper.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ * assumed configuration is done and we just re-run the test
+ * @mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+static u16 hte_basic_data_cmp(struct mrc_params *mrc_params, u32 addr,
+ u8 first_run, u8 mode)
+{
+ u32 pattern;
+ u32 offset;
+
+ if (first_run) {
+ msg_port_write(HTE, 0x00020020, 0x01b10021);
+ msg_port_write(HTE, 0x00020021, 0x06000000);
+ msg_port_write(HTE, 0x00020022, addr >> 6);
+ msg_port_write(HTE, 0x00020062, 0x00800015);
+ msg_port_write(HTE, 0x00020063, 0xaaaaaaaa);
+ msg_port_write(HTE, 0x00020064, 0xcccccccc);
+ msg_port_write(HTE, 0x00020065, 0xf0f0f0f0);
+ msg_port_write(HTE, 0x00020061, 0x00030008);
+
+ if (mode == WRITE_TRAIN)
+ pattern = 0xc33c0000;
+ else /* READ_TRAIN */
+ pattern = 0xaa5555aa;
+
+ for (offset = 0x80; offset <= 0x8f; offset++)
+ msg_port_write(HTE, offset, pattern);
+ }
+
+ msg_port_write(HTE, 0x000200a1, 0xffff1000);
+ msg_port_write(HTE, 0x00020011, 0x00011000);
+ msg_port_write(HTE, 0x00020011, 0x00011100);
+
+ hte_wait_for_complete();
+
+ /*
+ * Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for
+ * any bytelane errors.
+ */
+ return (hte_check_errors() >> 8) & 0xff;
+}
+
+/**
+ * Examine a single-cache-line memory with write/read/verify test using multiple
+ * data patterns (victim-aggressor algorithm).
+ *
+ * See hte_write_stress_bit_lanes() which is the external visible wrapper.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @loop_cnt: number of test iterations
+ * @seed_victim: victim data pattern seed
+ * @seed_aggressor: aggressor data pattern seed
+ * @victim_bit: should be 0 as auto-rotate feature is in use
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ * assumed configuration is done and we just re-run the test
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+static u16 hte_rw_data_cmp(struct mrc_params *mrc_params, u32 addr,
+ u8 loop_cnt, u32 seed_victim, u32 seed_aggressor,
+ u8 victim_bit, u8 first_run)
+{
+ u32 offset;
+ u32 tmp;
+
+ if (first_run) {
+ msg_port_write(HTE, 0x00020020, 0x00910024);
+ msg_port_write(HTE, 0x00020023, 0x00810024);
+ msg_port_write(HTE, 0x00020021, 0x06070000);
+ msg_port_write(HTE, 0x00020024, 0x06070000);
+ msg_port_write(HTE, 0x00020022, addr >> 6);
+ msg_port_write(HTE, 0x00020025, addr >> 6);
+ msg_port_write(HTE, 0x00020062, 0x0000002a);
+ msg_port_write(HTE, 0x00020063, seed_victim);
+ msg_port_write(HTE, 0x00020064, seed_aggressor);
+ msg_port_write(HTE, 0x00020065, seed_victim);
+
+ /*
+ * Write the pattern buffers to select the victim bit
+ *
+ * Start with bit0
+ */
+ for (offset = 0x80; offset <= 0x8f; offset++) {
+ if ((offset % 8) == victim_bit)
+ msg_port_write(HTE, offset, 0x55555555);
+ else
+ msg_port_write(HTE, offset, 0xcccccccc);
+ }
+
+ msg_port_write(HTE, 0x00020061, 0x00000000);
+ msg_port_write(HTE, 0x00020066, 0x03440000);
+ msg_port_write(HTE, 0x000200a1, 0xffff1000);
+ }
+
+ tmp = 0x10001000 | (loop_cnt << 16);
+ msg_port_write(HTE, 0x00020011, tmp);
+ msg_port_write(HTE, 0x00020011, tmp | (1 << 8));
+
+ hte_wait_for_complete();
+
+ /*
+ * Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for
+ * any bytelane errors.
+ */
+ return (hte_check_errors() >> 8) & 0xff;
+}
+
+/**
+ * Use HW HTE engine to initialize or test all memory attached to a given DUNIT.
+ * If flag is MRC_MEM_INIT, this routine writes 0s to all memory locations to
+ * initialize ECC. If flag is MRC_MEM_TEST, this routine will send an 5AA55AA5
+ * pattern to all memory locations on the RankMask and then read it back.
+ * Then it sends an A55AA55A pattern to all memory locations on the RankMask
+ * and reads it back.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @flag: MRC_MEM_INIT or MRC_MEM_TEST
+ *
+ * @return: errors register showing HTE failures. Also prints out which rank
+ * failed the HTE test if failure occurs. For rank detection to work,
+ * the address map must be left in its default state. If MRC changes
+ * the address map, this function must be modified to change it back
+ * to default at the beginning, then restore it at the end.
+ */
+u32 hte_mem_init(struct mrc_params *mrc_params, u8 flag)
+{
+ u32 offset;
+ int test_num;
+ int i;
+
+ /*
+ * Clear out the error registers at the start of each memory
+ * init or memory test run.
+ */
+ hte_clear_error_regs();
+
+ msg_port_write(HTE, 0x00020062, 0x00000015);
+
+ for (offset = 0x80; offset <= 0x8f; offset++)
+ msg_port_write(HTE, offset, ((offset & 1) ? 0xa55a : 0x5aa5));
+
+ msg_port_write(HTE, 0x00020021, 0x00000000);
+ msg_port_write(HTE, 0x00020022, (mrc_params->mem_size >> 6) - 1);
+ msg_port_write(HTE, 0x00020063, 0xaaaaaaaa);
+ msg_port_write(HTE, 0x00020064, 0xcccccccc);
+ msg_port_write(HTE, 0x00020065, 0xf0f0f0f0);
+ msg_port_write(HTE, 0x00020066, 0x03000000);
+
+ switch (flag) {
+ case MRC_MEM_INIT:
+ /*
+ * Only 1 write pass through memory is needed
+ * to initialize ECC
+ */
+ test_num = 1;
+ break;
+ case MRC_MEM_TEST:
+ /* Write/read then write/read with inverted pattern */
+ test_num = 4;
+ break;
+ default:
+ DPF(D_INFO, "Unknown parameter for flag: %d\n", flag);
+ return 0xffffffff;
+ }
+
+ DPF(D_INFO, "hte_mem_init");
+
+ for (i = 0; i < test_num; i++) {
+ DPF(D_INFO, ".");
+
+ if (i == 0) {
+ msg_port_write(HTE, 0x00020061, 0x00000000);
+ msg_port_write(HTE, 0x00020020, 0x00110010);
+ } else if (i == 1) {
+ msg_port_write(HTE, 0x00020061, 0x00000000);
+ msg_port_write(HTE, 0x00020020, 0x00010010);
+ } else if (i == 2) {
+ msg_port_write(HTE, 0x00020061, 0x00010100);
+ msg_port_write(HTE, 0x00020020, 0x00110010);
+ } else {
+ msg_port_write(HTE, 0x00020061, 0x00010100);
+ msg_port_write(HTE, 0x00020020, 0x00010010);
+ }
+
+ msg_port_write(HTE, 0x00020011, 0x00111000);
+ msg_port_write(HTE, 0x00020011, 0x00111100);
+
+ hte_wait_for_complete();
+
+ /* If this is a READ pass, check for errors at the end */
+ if ((i % 2) == 1) {
+ /* Return immediately if error */
+ if (hte_check_errors())
+ break;
+ }
+ }
+
+ DPF(D_INFO, "done\n");
+
+ return hte_check_errors();
+}
+
+/**
+ * Execute a basic single-cache-line memory write/read/verify test using simple
+ * constant pattern, different for READ_TRAIN and WRITE_TRAIN modes.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ * assumed configuration is done and we just re-run the test
+ * @mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+u16 hte_basic_write_read(struct mrc_params *mrc_params, u32 addr,
+ u8 first_run, u8 mode)
+{
+ u16 errors;
+
+ ENTERFN();
+
+ /* Enable all error reporting in preparation for HTE test */
+ hte_enable_all_errors();
+ hte_clear_error_regs();
+
+ errors = hte_basic_data_cmp(mrc_params, addr, first_run, mode);
+
+ LEAVEFN();
+
+ return errors;
+}
+
+/**
+ * Examine a single-cache-line memory with write/read/verify test using multiple
+ * data patterns (victim-aggressor algorithm).
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ * assumed configuration is done and we just re-run the test
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+u16 hte_write_stress_bit_lanes(struct mrc_params *mrc_params,
+ u32 addr, u8 first_run)
+{
+ u16 errors;
+ u8 victim_bit = 0;
+
+ ENTERFN();
+
+ /* Enable all error reporting in preparation for HTE test */
+ hte_enable_all_errors();
+ hte_clear_error_regs();
+
+ /*
+ * Loop through each bit in the bytelane.
+ *
+ * Each pass creates a victim bit while keeping all other bits the same
+ * as aggressors. AVN HTE adds an auto-rotate feature which allows us
+ * to program the entire victim/aggressor sequence in 1 step.
+ *
+ * The victim bit rotates on each pass so no need to have software
+ * implement a victim bit loop like on VLV.
+ */
+ errors = hte_rw_data_cmp(mrc_params, addr, HTE_LOOP_CNT,
+ HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED,
+ victim_bit, first_run);
+
+ LEAVEFN();
+
+ return errors;
+}
+
+/**
+ * Execute a basic single-cache-line memory write or read.
+ * This is just for receive enable / fine write-levelling purpose.
+ *
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ * assumed configuration is done and we just re-run the test
+ * @is_write: when non-zero memory write operation executed, otherwise read
+ */
+void hte_mem_op(u32 addr, u8 first_run, u8 is_write)
+{
+ u32 offset;
+ u32 tmp;
+
+ hte_enable_all_errors();
+ hte_clear_error_regs();
+
+ if (first_run) {
+ tmp = is_write ? 0x01110021 : 0x01010021;
+ msg_port_write(HTE, 0x00020020, tmp);
+
+ msg_port_write(HTE, 0x00020021, 0x06000000);
+ msg_port_write(HTE, 0x00020022, addr >> 6);
+ msg_port_write(HTE, 0x00020062, 0x00800015);
+ msg_port_write(HTE, 0x00020063, 0xaaaaaaaa);
+ msg_port_write(HTE, 0x00020064, 0xcccccccc);
+ msg_port_write(HTE, 0x00020065, 0xf0f0f0f0);
+ msg_port_write(HTE, 0x00020061, 0x00030008);
+
+ for (offset = 0x80; offset <= 0x8f; offset++)
+ msg_port_write(HTE, offset, 0xc33c0000);
+ }
+
+ msg_port_write(HTE, 0x000200a1, 0xffff1000);
+ msg_port_write(HTE, 0x00020011, 0x00011000);
+ msg_port_write(HTE, 0x00020011, 0x00011100);
+
+ hte_wait_for_complete();
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/hte.h b/roms/u-boot/arch/x86/cpu/quark/hte.h
new file mode 100644
index 000000000..b4ea488f3
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/hte.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+#ifndef _HTE_H_
+#define _HTE_H_
+
+enum {
+ MRC_MEM_INIT,
+ MRC_MEM_TEST
+};
+
+enum {
+ READ_TRAIN,
+ WRITE_TRAIN
+};
+
+/*
+ * EXP_LOOP_CNT field of HTE_CMD_CTL
+ *
+ * This CANNOT be less than 4!
+ */
+#define HTE_LOOP_CNT 5
+
+/* random seed for victim */
+#define HTE_LFSR_VICTIM_SEED 0xf294ba21
+
+/* random seed for aggressor */
+#define HTE_LFSR_AGRESSOR_SEED 0xeba7492d
+
+u32 hte_mem_init(struct mrc_params *mrc_params, u8 flag);
+u16 hte_basic_write_read(struct mrc_params *mrc_params, u32 addr,
+ u8 first_run, u8 mode);
+u16 hte_write_stress_bit_lanes(struct mrc_params *mrc_params,
+ u32 addr, u8 first_run);
+void hte_mem_op(u32 addr, u8 first_run, u8 is_write);
+
+#endif /* _HTE_H_ */
diff --git a/roms/u-boot/arch/x86/cpu/quark/mrc.c b/roms/u-boot/arch/x86/cpu/quark/mrc.c
new file mode 100644
index 000000000..3e8c0bc28
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/mrc.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+/*
+ * This is the main Quark Memory Reference Code (MRC)
+ *
+ * These functions are generic and should work for any Quark-based board.
+ *
+ * MRC requires two data structures to be passed in which are initialized by
+ * mrc_adjust_params().
+ *
+ * The basic flow is as follows:
+ * 01) Check for supported DDR speed configuration
+ * 02) Set up Memory Manager buffer as pass-through (POR)
+ * 03) Set Channel Interleaving Mode and Channel Stride to the most aggressive
+ * setting possible
+ * 04) Set up the Memory Controller logic
+ * 05) Set up the DDR_PHY logic
+ * 06) Initialise the DRAMs (JEDEC)
+ * 07) Perform the Receive Enable Calibration algorithm
+ * 08) Perform the Write Leveling algorithm
+ * 09) Perform the Read Training algorithm (includes internal Vref)
+ * 10) Perform the Write Training algorithm
+ * 11) Set Channel Interleaving Mode and Channel Stride to the desired settings
+ *
+ * DRAM unit configuration based on Valleyview MRC.
+ */
+
+#include <common.h>
+#include <version.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "smc.h"
+
+static const struct mem_init init[] = {
+ { 0x0101, BM_COLD | BM_FAST | BM_WARM | BM_S3, clear_self_refresh },
+ { 0x0200, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_ddr_timing_control },
+ { 0x0103, BM_COLD | BM_FAST , prog_decode_before_jedec },
+ { 0x0104, BM_COLD | BM_FAST , perform_ddr_reset },
+ { 0x0300, BM_COLD | BM_FAST | BM_S3, ddrphy_init },
+ { 0x0400, BM_COLD | BM_FAST , perform_jedec_init },
+ { 0x0105, BM_COLD | BM_FAST , set_ddr_init_complete },
+ { 0x0106, BM_FAST | BM_WARM | BM_S3, restore_timings },
+ { 0x0106, BM_COLD , default_timings },
+ { 0x0500, BM_COLD , rcvn_cal },
+ { 0x0600, BM_COLD , wr_level },
+ { 0x0120, BM_COLD , prog_page_ctrl },
+ { 0x0700, BM_COLD , rd_train },
+ { 0x0800, BM_COLD , wr_train },
+ { 0x010b, BM_COLD , store_timings },
+ { 0x010c, BM_COLD | BM_FAST | BM_WARM | BM_S3, enable_scrambling },
+ { 0x010d, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_ddr_control },
+ { 0x010e, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_dra_drb },
+ { 0x010f, BM_WARM | BM_S3, perform_wake },
+ { 0x0110, BM_COLD | BM_FAST | BM_WARM | BM_S3, change_refresh_period },
+ { 0x0111, BM_COLD | BM_FAST | BM_WARM | BM_S3, set_auto_refresh },
+ { 0x0112, BM_COLD | BM_FAST | BM_WARM | BM_S3, ecc_enable },
+ { 0x0113, BM_COLD | BM_FAST , memory_test },
+ { 0x0114, BM_COLD | BM_FAST | BM_WARM | BM_S3, lock_registers }
+};
+
+/* Adjust configuration parameters before initialization sequence */
+static void mrc_adjust_params(struct mrc_params *mrc_params)
+{
+ const struct dram_params *dram_params;
+ uint8_t dram_width;
+ uint32_t rank_enables;
+ uint32_t channel_width;
+
+ ENTERFN();
+
+ /* initially expect success */
+ mrc_params->status = MRC_SUCCESS;
+
+ dram_width = mrc_params->dram_width;
+ rank_enables = mrc_params->rank_enables;
+ channel_width = mrc_params->channel_width;
+
+ /*
+ * Setup board layout (must be reviewed as is selecting static timings)
+ * 0 == R0 (DDR3 x16), 1 == R1 (DDR3 x16),
+ * 2 == DV (DDR3 x8), 3 == SV (DDR3 x8).
+ */
+ if (dram_width == X8)
+ mrc_params->board_id = 2; /* select x8 layout */
+ else
+ mrc_params->board_id = 0; /* select x16 layout */
+
+ /* initially no memory */
+ mrc_params->mem_size = 0;
+
+ /* begin of channel settings */
+ dram_params = &mrc_params->params;
+
+ /*
+ * Determine column bits:
+ *
+ * Column: 11 for 8Gbx8, else 10
+ */
+ mrc_params->column_bits[0] =
+ (dram_params[0].density == 4) &&
+ (dram_width == X8) ? 11 : 10;
+
+ /*
+ * Determine row bits:
+ *
+ * 512Mbx16=12 512Mbx8=13
+ * 1Gbx16=13 1Gbx8=14
+ * 2Gbx16=14 2Gbx8=15
+ * 4Gbx16=15 4Gbx8=16
+ * 8Gbx16=16 8Gbx8=16
+ */
+ mrc_params->row_bits[0] = 12 + dram_params[0].density +
+ (dram_params[0].density < 4) &&
+ (dram_width == X8) ? 1 : 0;
+
+ /*
+ * Determine per-channel memory size:
+ *
+ * (For 2 RANKs, multiply by 2)
+ * (For 16 bit data bus, divide by 2)
+ *
+ * DENSITY WIDTH MEM_AVAILABLE
+ * 512Mb x16 0x008000000 ( 128MB)
+ * 512Mb x8 0x010000000 ( 256MB)
+ * 1Gb x16 0x010000000 ( 256MB)
+ * 1Gb x8 0x020000000 ( 512MB)
+ * 2Gb x16 0x020000000 ( 512MB)
+ * 2Gb x8 0x040000000 (1024MB)
+ * 4Gb x16 0x040000000 (1024MB)
+ * 4Gb x8 0x080000000 (2048MB)
+ */
+ mrc_params->channel_size[0] = 1 << dram_params[0].density;
+ mrc_params->channel_size[0] *= (dram_width == X8) ? 2 : 1;
+ mrc_params->channel_size[0] *= (rank_enables == 0x3) ? 2 : 1;
+ mrc_params->channel_size[0] *= (channel_width == X16) ? 1 : 2;
+
+ /* Determine memory size (convert number of 64MB/512Mb units) */
+ mrc_params->mem_size += mrc_params->channel_size[0] << 26;
+
+ LEAVEFN();
+}
+
+static void mrc_mem_init(struct mrc_params *mrc_params)
+{
+ int i;
+
+ ENTERFN();
+
+ /* MRC started */
+ mrc_post_code(0x01, 0x00);
+
+ if (mrc_params->boot_mode != BM_COLD) {
+ if (mrc_params->ddr_speed != mrc_params->timings.ddr_speed) {
+ /* full training required as frequency changed */
+ mrc_params->boot_mode = BM_COLD;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(init); i++) {
+ uint64_t my_tsc;
+
+ if (mrc_params->boot_mode & init[i].boot_path) {
+ uint8_t major = init[i].post_code >> 8 & 0xff;
+ uint8_t minor = init[i].post_code >> 0 & 0xff;
+ mrc_post_code(major, minor);
+
+ my_tsc = rdtsc();
+ init[i].init_fn(mrc_params);
+ DPF(D_TIME, "Execution time %llx", rdtsc() - my_tsc);
+ }
+ }
+
+ /* display the timings */
+ print_timings(mrc_params);
+
+ /* MRC complete */
+ mrc_post_code(0x01, 0xff);
+
+ LEAVEFN();
+}
+
+void mrc_init(struct mrc_params *mrc_params)
+{
+ ENTERFN();
+
+ DPF(D_INFO, "MRC Version %04x %s %s\n", MRC_VERSION,
+ U_BOOT_DATE, U_BOOT_TIME);
+
+ /* Set up the data structures used by mrc_mem_init() */
+ mrc_adjust_params(mrc_params);
+
+ /* Initialize system memory */
+ mrc_mem_init(mrc_params);
+
+ LEAVEFN();
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/mrc_util.c b/roms/u-boot/arch/x86/cpu/quark/mrc_util.c
new file mode 100644
index 000000000..b0bc59b71
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/mrc_util.c
@@ -0,0 +1,1472 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+#include <common.h>
+#include <hang.h>
+#include <asm/arch/device.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
+#include "mrc_util.h"
+#include "hte.h"
+#include "smc.h"
+
+static const uint8_t vref_codes[64] = {
+ /* lowest to highest */
+ 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
+ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
+ 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
+ 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+void mrc_write_mask(u32 unit, u32 addr, u32 data, u32 mask)
+{
+ msg_port_write(unit, addr,
+ (msg_port_read(unit, addr) & ~(mask)) |
+ ((data) & (mask)));
+}
+
+void mrc_alt_write_mask(u32 unit, u32 addr, u32 data, u32 mask)
+{
+ msg_port_alt_write(unit, addr,
+ (msg_port_alt_read(unit, addr) & ~(mask)) |
+ ((data) & (mask)));
+}
+
+void mrc_post_code(uint8_t major, uint8_t minor)
+{
+ /* send message to UART */
+ DPF(D_INFO, "POST: 0x%01x%02x\n", major, minor);
+
+ /* error check */
+ if (major == 0xee)
+ hang();
+}
+
+/* Delay number of nanoseconds */
+void delay_n(uint32_t ns)
+{
+ /* 1000 MHz clock has 1ns period --> no conversion required */
+ uint64_t final_tsc = rdtsc();
+
+ final_tsc += ((get_tbclk_mhz() * ns) / 1000);
+
+ while (rdtsc() < final_tsc)
+ ;
+}
+
+/* Delay number of microseconds */
+void delay_u(uint32_t ms)
+{
+ /* 64-bit math is not an option, just use loops */
+ while (ms--)
+ delay_n(1000);
+}
+
+/* Select Memory Manager as the source for PRI interface */
+void select_mem_mgr(void)
+{
+ u32 dco;
+
+ ENTERFN();
+
+ dco = msg_port_read(MEM_CTLR, DCO);
+ dco &= ~DCO_PMICTL;
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ LEAVEFN();
+}
+
+/* Select HTE as the source for PRI interface */
+void select_hte(void)
+{
+ u32 dco;
+
+ ENTERFN();
+
+ dco = msg_port_read(MEM_CTLR, DCO);
+ dco |= DCO_PMICTL;
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ LEAVEFN();
+}
+
+/*
+ * Send DRAM command
+ * data should be formated using DCMD_Xxxx macro or emrsXCommand structure
+ */
+void dram_init_command(uint32_t data)
+{
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, data);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, 0);
+ msg_port_setup(MSG_OP_DRAM_INIT, MEM_CTLR, 0);
+
+ DPF(D_REGWR, "WR32 %03X %08X %08X\n", MEM_CTLR, 0, data);
+}
+
+/* Send DRAM wake command using special MCU side-band WAKE opcode */
+void dram_wake_command(void)
+{
+ ENTERFN();
+
+ msg_port_setup(MSG_OP_DRAM_WAKE, MEM_CTLR, 0);
+
+ LEAVEFN();
+}
+
+void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+ /* send message to UART */
+ DPF(D_INFO, "CH%01X RK%01X BL%01X\n", channel, rank, byte_lane);
+}
+
+/*
+ * This function will program the RCVEN delays
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_rcvn(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+
+ DPF(D_TRN, "Rcvn ch%d rnk%d ln%d : pi=%03X\n",
+ channel, rank, byte_lane, pi_count);
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
+ * BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
+ */
+ reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ msk = (byte_lane & 1) ? 0xf00000 : 0xf00;
+ temp = (byte_lane & 1) ? (pi_count / HALF_CLK) << 20 :
+ (pi_count / HALF_CLK) << 8;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* Adjust PI_COUNT */
+ pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
+ * BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
+ */
+ reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ msk = 0x3f000000;
+ temp = pi_count << 24;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /*
+ * DEADBAND
+ * BL0/1 -> B01DBCTL1[08/11] (+1 select)
+ * BL0/1 -> B01DBCTL1[02/05] (enable)
+ */
+ reg = B01DBCTL1 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ msk = 0x00;
+ temp = 0x00;
+
+ /* enable */
+ msk |= (byte_lane & 1) ? (1 << 5) : (1 << 2);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (byte_lane & 1) ? (1 << 11) : (1 << 8);
+ if (pi_count < EARLY_DB)
+ temp |= msk;
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check */
+ if (pi_count > 0x3f) {
+ training_message(channel, rank, byte_lane);
+ mrc_post_code(0xee, 0xe0);
+ }
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the current RCVEN delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
+ * BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
+ */
+ reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= (byte_lane & 1) ? 20 : 8;
+ temp &= 0xf;
+
+ /* Adjust PI_COUNT */
+ pi_count = temp * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
+ * BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
+ */
+ reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 24;
+ temp &= 0x3f;
+
+ /* Adjust PI_COUNT */
+ pi_count += temp;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the RDQS delays based on an absolute
+ * amount of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_rdqs(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+ DPF(D_TRN, "Rdqs ch%d rnk%d ln%d : pi=%03X\n",
+ channel, rank, byte_lane, pi_count);
+
+ /*
+ * PI (1/128 MCLK)
+ * BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
+ * BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
+ */
+ reg = (byte_lane & 1) ? B1RXDQSPICODE : B0RXDQSPICODE;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ msk = 0x7f;
+ temp = pi_count << 0;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check (shouldn't go above 0x3F) */
+ if (pi_count > 0x47) {
+ training_message(channel, rank, byte_lane);
+ mrc_post_code(0xee, 0xe1);
+ }
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the current RDQS delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * PI (1/128 MCLK)
+ * BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
+ * BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
+ */
+ reg = (byte_lane & 1) ? B1RXDQSPICODE : B0RXDQSPICODE;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ temp = msg_port_alt_read(DDRPHY, reg);
+
+ /* Adjust PI_COUNT */
+ pi_count = temp & 0x7f;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the WDQS delays based on an absolute
+ * amount of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_wdqs(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+
+ DPF(D_TRN, "Wdqs ch%d rnk%d ln%d : pi=%03X\n",
+ channel, rank, byte_lane, pi_count);
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
+ * BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
+ */
+ reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ msk = (byte_lane & 1) ? 0xf0000 : 0xf0;
+ temp = pi_count / HALF_CLK;
+ temp <<= (byte_lane & 1) ? 16 : 4;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* Adjust PI_COUNT */
+ pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
+ * BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
+ */
+ reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ msk = 0x3f0000;
+ temp = pi_count << 16;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /*
+ * DEADBAND
+ * BL0/1 -> B01DBCTL1[07/10] (+1 select)
+ * BL0/1 -> B01DBCTL1[01/04] (enable)
+ */
+ reg = B01DBCTL1 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ msk = 0x00;
+ temp = 0x00;
+
+ /* enable */
+ msk |= (byte_lane & 1) ? (1 << 4) : (1 << 1);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (byte_lane & 1) ? (1 << 10) : (1 << 7);
+ if (pi_count < EARLY_DB)
+ temp |= msk;
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check */
+ if (pi_count > 0x3f) {
+ training_message(channel, rank, byte_lane);
+ mrc_post_code(0xee, 0xe2);
+ }
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WDQS delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
+ * BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
+ */
+ reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= (byte_lane & 1) ? 16 : 4;
+ temp &= 0xf;
+
+ /* Adjust PI_COUNT */
+ pi_count = (temp * HALF_CLK);
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
+ * BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
+ */
+ reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 16;
+ temp &= 0x3f;
+
+ /* Adjust PI_COUNT */
+ pi_count += temp;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the WDQ delays based on an absolute
+ * number of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_wdq(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+
+ DPF(D_TRN, "Wdq ch%d rnk%d ln%d : pi=%03X\n",
+ channel, rank, byte_lane, pi_count);
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
+ * BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
+ */
+ reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ msk = (byte_lane & 1) ? 0xf000 : 0xf;
+ temp = pi_count / HALF_CLK;
+ temp <<= (byte_lane & 1) ? 12 : 0;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* Adjust PI_COUNT */
+ pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
+ * BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
+ */
+ reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ msk = 0x3f00;
+ temp = pi_count << 8;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /*
+ * DEADBAND
+ * BL0/1 -> B01DBCTL1[06/09] (+1 select)
+ * BL0/1 -> B01DBCTL1[00/03] (enable)
+ */
+ reg = B01DBCTL1 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ msk = 0x00;
+ temp = 0x00;
+
+ /* enable */
+ msk |= (byte_lane & 1) ? (1 << 3) : (1 << 0);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (byte_lane & 1) ? (1 << 9) : (1 << 6);
+ if (pi_count < EARLY_DB)
+ temp |= msk;
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check */
+ if (pi_count > 0x3f) {
+ training_message(channel, rank, byte_lane);
+ mrc_post_code(0xee, 0xe3);
+ }
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WDQ delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
+ * BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
+ */
+ reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= (byte_lane & 1) ? 12 : 0;
+ temp &= 0xf;
+
+ /* Adjust PI_COUNT */
+ pi_count = temp * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
+ * BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
+ */
+ reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 8;
+ temp &= 0x3f;
+
+ /* Adjust PI_COUNT */
+ pi_count += temp;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the WCMD delays based on an absolute
+ * number of PIs.
+ */
+void set_wcmd(uint8_t channel, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * CMDPTRREG[11:08] (0x0-0xF)
+ */
+ reg = CMDPTRREG + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0xf00;
+ temp = pi_count / HALF_CLK;
+ temp <<= 8;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* Adjust PI_COUNT */
+ pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
+ * CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
+ * CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
+ * CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
+ * CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
+ * CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
+ * CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
+ * CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
+ */
+ reg = CMDDLLPICODER1 + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0x3f3f3f3f;
+ temp = (pi_count << 24) | (pi_count << 16) |
+ (pi_count << 8) | (pi_count << 0);
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+ reg = CMDDLLPICODER0 + channel * DDRIOCCC_CH_OFFSET; /* PO */
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /*
+ * DEADBAND
+ * CMDCFGREG0[17] (+1 select)
+ * CMDCFGREG0[16] (enable)
+ */
+ reg = CMDCFGREG0 + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0x00;
+ temp = 0x00;
+
+ /* enable */
+ msk |= (1 << 16);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (1 << 17);
+ if (pi_count < EARLY_DB)
+ temp |= msk;
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check */
+ if (pi_count > 0x3f)
+ mrc_post_code(0xee, 0xe4);
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WCMD delay on the given
+ * channel as an absolute PI count.
+ */
+uint32_t get_wcmd(uint8_t channel)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * CMDPTRREG[11:08] (0x0-0xF)
+ */
+ reg = CMDPTRREG + channel * DDRIOCCC_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 8;
+ temp &= 0xf;
+
+ /* Adjust PI_COUNT */
+ pi_count = temp * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
+ * CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
+ * CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
+ * CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
+ * CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
+ * CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
+ * CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
+ * CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
+ */
+ reg = CMDDLLPICODER1 + channel * DDRIOCCC_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 16;
+ temp &= 0x3f;
+
+ /* Adjust PI_COUNT */
+ pi_count += temp;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the WCLK delays based on an absolute
+ * number of PIs.
+ */
+void set_wclk(uint8_t channel, uint8_t rank, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * CCPTRREG[15:12] -> CLK1 (0x0-0xF)
+ * CCPTRREG[11:08] -> CLK0 (0x0-0xF)
+ */
+ reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0xff00;
+ temp = ((pi_count / HALF_CLK) << 12) | ((pi_count / HALF_CLK) << 8);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* Adjust PI_COUNT */
+ pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
+ * ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
+ */
+ reg = rank ? ECCB1DLLPICODER0 : ECCB1DLLPICODER0;
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ msk = 0x3f3f00;
+ temp = (pi_count << 16) | (pi_count << 8);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ reg = rank ? ECCB1DLLPICODER1 : ECCB1DLLPICODER1;
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ reg = rank ? ECCB1DLLPICODER2 : ECCB1DLLPICODER2;
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ reg = rank ? ECCB1DLLPICODER3 : ECCB1DLLPICODER3;
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /*
+ * DEADBAND
+ * CCCFGREG1[11:08] (+1 select)
+ * CCCFGREG1[03:00] (enable)
+ */
+ reg = CCCFGREG1 + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0x00;
+ temp = 0x00;
+
+ /* enable */
+ msk |= 0xf;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= 0xf00;
+ if (pi_count < EARLY_DB)
+ temp |= msk;
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check */
+ if (pi_count > 0x3f)
+ mrc_post_code(0xee, 0xe5);
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the amout of WCLK delay on the given
+ * channel, rank as an absolute PI count.
+ */
+uint32_t get_wclk(uint8_t channel, uint8_t rank)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * CCPTRREG[15:12] -> CLK1 (0x0-0xF)
+ * CCPTRREG[11:08] -> CLK0 (0x0-0xF)
+ */
+ reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= rank ? 12 : 8;
+ temp &= 0xf;
+
+ /* Adjust PI_COUNT */
+ pi_count = temp * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
+ * ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
+ */
+ reg = rank ? ECCB1DLLPICODER0 : ECCB1DLLPICODER0;
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= rank ? 16 : 8;
+ temp &= 0x3f;
+
+ pi_count += temp;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the WCTL delays based on an absolute
+ * number of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t temp;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * CCPTRREG[31:28] (0x0-0xF)
+ * CCPTRREG[27:24] (0x0-0xF)
+ */
+ reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0xff000000;
+ temp = ((pi_count / HALF_CLK) << 28) | ((pi_count / HALF_CLK) << 24);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* Adjust PI_COUNT */
+ pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ */
+ reg = ECCB1DLLPICODER0 + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0x3f000000;
+ temp = (pi_count << 24);
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ reg = ECCB1DLLPICODER1 + channel * DDRIOCCC_CH_OFFSET;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ reg = ECCB1DLLPICODER2 + channel * DDRIOCCC_CH_OFFSET;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ reg = ECCB1DLLPICODER3 + channel * DDRIOCCC_CH_OFFSET;
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /*
+ * DEADBAND
+ * CCCFGREG1[13:12] (+1 select)
+ * CCCFGREG1[05:04] (enable)
+ */
+ reg = CCCFGREG1 + channel * DDRIOCCC_CH_OFFSET;
+ msk = 0x00;
+ temp = 0x00;
+
+ /* enable */
+ msk |= 0x30;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= 0x3000;
+ if (pi_count < EARLY_DB)
+ temp |= msk;
+
+ mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+ /* error check */
+ if (pi_count > 0x3f)
+ mrc_post_code(0xee, 0xe6);
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WCTL delay on the given
+ * channel, rank as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_wctl(uint8_t channel, uint8_t rank)
+{
+ uint32_t reg;
+ uint32_t temp;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ /*
+ * RDPTR (1/2 MCLK, 64 PIs)
+ * CCPTRREG[31:28] (0x0-0xF)
+ * CCPTRREG[27:24] (0x0-0xF)
+ */
+ reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 24;
+ temp &= 0xf;
+
+ /* Adjust PI_COUNT */
+ pi_count = temp * HALF_CLK;
+
+ /*
+ * PI (1/64 MCLK, 1 PIs)
+ * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ */
+ reg = ECCB1DLLPICODER0 + channel * DDRIOCCC_CH_OFFSET;
+ temp = msg_port_alt_read(DDRPHY, reg);
+ temp >>= 24;
+ temp &= 0x3f;
+
+ /* Adjust PI_COUNT */
+ pi_count += temp;
+
+ LEAVEFN();
+
+ return pi_count;
+}
+
+/*
+ * This function will program the internal Vref setting in a given
+ * byte lane in a given channel.
+ */
+void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting)
+{
+ uint32_t reg = (byte_lane & 0x1) ? B1VREFCTL : B0VREFCTL;
+
+ ENTERFN();
+
+ DPF(D_TRN, "Vref ch%d ln%d : val=%03X\n",
+ channel, byte_lane, setting);
+
+ mrc_alt_write_mask(DDRPHY, reg + channel * DDRIODQ_CH_OFFSET +
+ (byte_lane >> 1) * DDRIODQ_BL_OFFSET,
+ vref_codes[setting] << 2, 0xfc);
+
+ /*
+ * need to wait ~300ns for Vref to settle
+ * (check that this is necessary)
+ */
+ delay_n(300);
+
+ /* ??? may need to clear pointers ??? */
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return the internal Vref setting for the given
+ * channel, byte_lane.
+ */
+uint32_t get_vref(uint8_t channel, uint8_t byte_lane)
+{
+ uint8_t j;
+ uint32_t ret_val = sizeof(vref_codes) / 2;
+ uint32_t reg = (byte_lane & 0x1) ? B1VREFCTL : B0VREFCTL;
+ uint32_t temp;
+
+ ENTERFN();
+
+ temp = msg_port_alt_read(DDRPHY, reg + channel * DDRIODQ_CH_OFFSET +
+ (byte_lane >> 1) * DDRIODQ_BL_OFFSET);
+ temp >>= 2;
+ temp &= 0x3f;
+
+ for (j = 0; j < sizeof(vref_codes); j++) {
+ if (vref_codes[j] == temp) {
+ ret_val = j;
+ break;
+ }
+ }
+
+ LEAVEFN();
+
+ return ret_val;
+}
+
+/*
+ * This function will return a 32-bit address in the desired
+ * channel and rank.
+ */
+uint32_t get_addr(uint8_t channel, uint8_t rank)
+{
+ uint32_t offset = 32 * 1024 * 1024; /* 32MB */
+
+ /* Begin product specific code */
+ if (channel > 0) {
+ DPF(D_ERROR, "ILLEGAL CHANNEL\n");
+ DEAD_LOOP();
+ }
+
+ if (rank > 1) {
+ DPF(D_ERROR, "ILLEGAL RANK\n");
+ DEAD_LOOP();
+ }
+
+ /* use 256MB lowest density as per DRP == 0x0003 */
+ offset += rank * (256 * 1024 * 1024);
+
+ return offset;
+}
+
+/*
+ * This function will sample the DQTRAINSTS registers in the given
+ * channel/rank SAMPLE_SIZE times looking for a valid '0' or '1'.
+ *
+ * It will return an encoded 32-bit date in which each bit corresponds to
+ * the sampled value on the byte lane.
+ */
+uint32_t sample_dqs(struct mrc_params *mrc_params, uint8_t channel,
+ uint8_t rank, bool rcvn)
+{
+ uint8_t j; /* just a counter */
+ uint8_t bl; /* which BL in the module (always 2 per module) */
+ uint8_t bl_grp; /* which BL module */
+ /* byte lane divisor */
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+ uint32_t msk[2]; /* BLx in module */
+ /* DQTRAINSTS register contents for each sample */
+ uint32_t sampled_val[SAMPLE_SIZE];
+ uint32_t num_0s; /* tracks the number of '0' samples */
+ uint32_t num_1s; /* tracks the number of '1' samples */
+ uint32_t ret_val = 0x00; /* assume all '0' samples */
+ uint32_t address = get_addr(channel, rank);
+
+ /* initialise msk[] */
+ msk[0] = rcvn ? (1 << 1) : (1 << 9); /* BL0 */
+ msk[1] = rcvn ? (1 << 0) : (1 << 8); /* BL1 */
+
+ /* cycle through each byte lane group */
+ for (bl_grp = 0; bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2; bl_grp++) {
+ /* take SAMPLE_SIZE samples */
+ for (j = 0; j < SAMPLE_SIZE; j++) {
+ hte_mem_op(address, mrc_params->first_run,
+ rcvn ? 0 : 1);
+ mrc_params->first_run = 0;
+
+ /*
+ * record the contents of the proper
+ * DQTRAINSTS register
+ */
+ sampled_val[j] = msg_port_alt_read(DDRPHY,
+ DQTRAINSTS +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET);
+ }
+
+ /*
+ * look for a majority value (SAMPLE_SIZE / 2) + 1
+ * on the byte lane and set that value in the corresponding
+ * ret_val bit
+ */
+ for (bl = 0; bl < 2; bl++) {
+ num_0s = 0x00; /* reset '0' tracker for byte lane */
+ num_1s = 0x00; /* reset '1' tracker for byte lane */
+ for (j = 0; j < SAMPLE_SIZE; j++) {
+ if (sampled_val[j] & msk[bl])
+ num_1s++;
+ else
+ num_0s++;
+ }
+ if (num_1s > num_0s)
+ ret_val |= (1 << (bl + bl_grp * 2));
+ }
+ }
+
+ /*
+ * "ret_val.0" contains the status of BL0
+ * "ret_val.1" contains the status of BL1
+ * "ret_val.2" contains the status of BL2
+ * etc.
+ */
+ return ret_val;
+}
+
+/* This function will find the rising edge transition on RCVN or WDQS */
+void find_rising_edge(struct mrc_params *mrc_params, uint32_t delay[],
+ uint8_t channel, uint8_t rank, bool rcvn)
+{
+ bool all_edges_found; /* determines stop condition */
+ bool direction[NUM_BYTE_LANES]; /* direction indicator */
+ uint8_t sample; /* sample counter */
+ uint8_t bl; /* byte lane counter */
+ /* byte lane divisor */
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+ uint32_t sample_result[SAMPLE_CNT]; /* results of sample_dqs() */
+ uint32_t temp;
+ uint32_t transition_pattern;
+
+ ENTERFN();
+
+ /* select hte and request initial configuration */
+ select_hte();
+ mrc_params->first_run = 1;
+
+ /* Take 3 sample points (T1,T2,T3) to obtain a transition pattern */
+ for (sample = 0; sample < SAMPLE_CNT; sample++) {
+ /* program the desired delays for sample */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ /* increase sample delay by 26 PI (0.2 CLK) */
+ if (rcvn) {
+ set_rcvn(channel, rank, bl,
+ delay[bl] + sample * SAMPLE_DLY);
+ } else {
+ set_wdqs(channel, rank, bl,
+ delay[bl] + sample * SAMPLE_DLY);
+ }
+ }
+
+ /* take samples (Tsample_i) */
+ sample_result[sample] = sample_dqs(mrc_params,
+ channel, rank, rcvn);
+
+ DPF(D_TRN,
+ "Find rising edge %s ch%d rnk%d: #%d dly=%d dqs=%02X\n",
+ rcvn ? "RCVN" : "WDQS", channel, rank, sample,
+ sample * SAMPLE_DLY, sample_result[sample]);
+ }
+
+ /*
+ * This pattern will help determine where we landed and ultimately
+ * how to place RCVEN/WDQS.
+ */
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ /* build transition_pattern (MSB is 1st sample) */
+ transition_pattern = 0;
+ for (sample = 0; sample < SAMPLE_CNT; sample++) {
+ transition_pattern |=
+ ((sample_result[sample] & (1 << bl)) >> bl) <<
+ (SAMPLE_CNT - 1 - sample);
+ }
+
+ DPF(D_TRN, "=== transition pattern %d\n", transition_pattern);
+
+ /*
+ * set up to look for rising edge based on
+ * transition_pattern
+ */
+ switch (transition_pattern) {
+ case 0: /* sampled 0->0->0 */
+ /* move forward from T3 looking for 0->1 */
+ delay[bl] += 2 * SAMPLE_DLY;
+ direction[bl] = FORWARD;
+ break;
+ case 1: /* sampled 0->0->1 */
+ case 5: /* sampled 1->0->1 (bad duty cycle) *HSD#237503* */
+ /* move forward from T2 looking for 0->1 */
+ delay[bl] += 1 * SAMPLE_DLY;
+ direction[bl] = FORWARD;
+ break;
+ case 2: /* sampled 0->1->0 (bad duty cycle) *HSD#237503* */
+ case 3: /* sampled 0->1->1 */
+ /* move forward from T1 looking for 0->1 */
+ delay[bl] += 0 * SAMPLE_DLY;
+ direction[bl] = FORWARD;
+ break;
+ case 4: /* sampled 1->0->0 (assumes BL8, HSD#234975) */
+ /* move forward from T3 looking for 0->1 */
+ delay[bl] += 2 * SAMPLE_DLY;
+ direction[bl] = FORWARD;
+ break;
+ case 6: /* sampled 1->1->0 */
+ case 7: /* sampled 1->1->1 */
+ /* move backward from T1 looking for 1->0 */
+ delay[bl] += 0 * SAMPLE_DLY;
+ direction[bl] = BACKWARD;
+ break;
+ default:
+ mrc_post_code(0xee, 0xee);
+ break;
+ }
+
+ /* program delays */
+ if (rcvn)
+ set_rcvn(channel, rank, bl, delay[bl]);
+ else
+ set_wdqs(channel, rank, bl, delay[bl]);
+ }
+
+ /*
+ * Based on the observed transition pattern on the byte lane,
+ * begin looking for a rising edge with single PI granularity.
+ */
+ do {
+ all_edges_found = true; /* assume all byte lanes passed */
+ /* take a sample */
+ temp = sample_dqs(mrc_params, channel, rank, rcvn);
+ /* check all each byte lane for proper edge */
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ if (temp & (1 << bl)) {
+ /* sampled "1" */
+ if (direction[bl] == BACKWARD) {
+ /*
+ * keep looking for edge
+ * on this byte lane
+ */
+ all_edges_found = false;
+ delay[bl] -= 1;
+ if (rcvn) {
+ set_rcvn(channel, rank,
+ bl, delay[bl]);
+ } else {
+ set_wdqs(channel, rank,
+ bl, delay[bl]);
+ }
+ }
+ } else {
+ /* sampled "0" */
+ if (direction[bl] == FORWARD) {
+ /*
+ * keep looking for edge
+ * on this byte lane
+ */
+ all_edges_found = false;
+ delay[bl] += 1;
+ if (rcvn) {
+ set_rcvn(channel, rank,
+ bl, delay[bl]);
+ } else {
+ set_wdqs(channel, rank,
+ bl, delay[bl]);
+ }
+ }
+ }
+ }
+ } while (!all_edges_found);
+
+ /* restore DDR idle state */
+ dram_init_command(DCMD_PREA(rank));
+
+ DPF(D_TRN, "Delay %03X %03X %03X %03X\n",
+ delay[0], delay[1], delay[2], delay[3]);
+
+ LEAVEFN();
+}
+
+/*
+ * This function will return a 32 bit mask that will be used to
+ * check for byte lane failures.
+ */
+uint32_t byte_lane_mask(struct mrc_params *mrc_params)
+{
+ uint32_t j;
+ uint32_t ret_val = 0x00;
+
+ /*
+ * set ret_val based on NUM_BYTE_LANES such that you will check
+ * only BL0 in result
+ *
+ * (each bit in result represents a byte lane)
+ */
+ for (j = 0; j < MAX_BYTE_LANES; j += NUM_BYTE_LANES)
+ ret_val |= (1 << ((j / NUM_BYTE_LANES) * NUM_BYTE_LANES));
+
+ /*
+ * HSD#235037
+ * need to adjust the mask for 16-bit mode
+ */
+ if (mrc_params->channel_width == X16)
+ ret_val |= (ret_val << 2);
+
+ return ret_val;
+}
+
+/*
+ * Check memory executing simple write/read/verify at the specified address.
+ *
+ * Bits in the result indicate failure on specific byte lane.
+ */
+uint32_t check_rw_coarse(struct mrc_params *mrc_params, uint32_t address)
+{
+ uint32_t result = 0;
+ uint8_t first_run = 0;
+
+ if (mrc_params->hte_setup) {
+ mrc_params->hte_setup = 0;
+ first_run = 1;
+ select_hte();
+ }
+
+ result = hte_basic_write_read(mrc_params, address, first_run,
+ WRITE_TRAIN);
+
+ DPF(D_TRN, "check_rw_coarse result is %x\n", result);
+
+ return result;
+}
+
+/*
+ * Check memory executing write/read/verify of many data patterns
+ * at the specified address. Bits in the result indicate failure
+ * on specific byte lane.
+ */
+uint32_t check_bls_ex(struct mrc_params *mrc_params, uint32_t address)
+{
+ uint32_t result;
+ uint8_t first_run = 0;
+
+ if (mrc_params->hte_setup) {
+ mrc_params->hte_setup = 0;
+ first_run = 1;
+ select_hte();
+ }
+
+ result = hte_write_stress_bit_lanes(mrc_params, address, first_run);
+
+ DPF(D_TRN, "check_bls_ex result is %x\n", result);
+
+ return result;
+}
+
+/*
+ * 32-bit LFSR with characteristic polynomial: X^32 + X^22 +X^2 + X^1
+ *
+ * The function takes pointer to previous 32 bit value and
+ * modifies it to next value.
+ */
+void lfsr32(uint32_t *lfsr_ptr)
+{
+ uint32_t bit;
+ uint32_t lfsr;
+ int i;
+
+ lfsr = *lfsr_ptr;
+
+ for (i = 0; i < 32; i++) {
+ bit = 1 ^ (lfsr & 1);
+ bit = bit ^ ((lfsr & 2) >> 1);
+ bit = bit ^ ((lfsr & 4) >> 2);
+ bit = bit ^ ((lfsr & 0x400000) >> 22);
+
+ lfsr = ((lfsr >> 1) | (bit << 31));
+ }
+
+ *lfsr_ptr = lfsr;
+}
+
+/* Clear the pointers in a given byte lane in a given channel */
+void clear_pointers(void)
+{
+ uint8_t channel;
+ uint8_t bl;
+
+ ENTERFN();
+
+ for (channel = 0; channel < NUM_CHANNELS; channel++) {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+ mrc_alt_write_mask(DDRPHY,
+ B01PTRCTL1 +
+ channel * DDRIODQ_CH_OFFSET +
+ (bl >> 1) * DDRIODQ_BL_OFFSET,
+ ~(1 << 8), (1 << 8));
+
+ mrc_alt_write_mask(DDRPHY,
+ B01PTRCTL1 +
+ channel * DDRIODQ_CH_OFFSET +
+ (bl >> 1) * DDRIODQ_BL_OFFSET,
+ (1 << 8), (1 << 8));
+ }
+ }
+
+ LEAVEFN();
+}
+
+static void print_timings_internal(uint8_t algo, uint8_t channel, uint8_t rank,
+ uint8_t bl_divisor)
+{
+ uint8_t bl;
+
+ switch (algo) {
+ case RCVN:
+ DPF(D_INFO, "\nRCVN[%02d:%02d]", channel, rank);
+ break;
+ case WDQS:
+ DPF(D_INFO, "\nWDQS[%02d:%02d]", channel, rank);
+ break;
+ case WDQX:
+ DPF(D_INFO, "\nWDQx[%02d:%02d]", channel, rank);
+ break;
+ case RDQS:
+ DPF(D_INFO, "\nRDQS[%02d:%02d]", channel, rank);
+ break;
+ case VREF:
+ DPF(D_INFO, "\nVREF[%02d:%02d]", channel, rank);
+ break;
+ case WCMD:
+ DPF(D_INFO, "\nWCMD[%02d:%02d]", channel, rank);
+ break;
+ case WCTL:
+ DPF(D_INFO, "\nWCTL[%02d:%02d]", channel, rank);
+ break;
+ case WCLK:
+ DPF(D_INFO, "\nWCLK[%02d:%02d]", channel, rank);
+ break;
+ default:
+ break;
+ }
+
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ switch (algo) {
+ case RCVN:
+ DPF(D_INFO, " %03d", get_rcvn(channel, rank, bl));
+ break;
+ case WDQS:
+ DPF(D_INFO, " %03d", get_wdqs(channel, rank, bl));
+ break;
+ case WDQX:
+ DPF(D_INFO, " %03d", get_wdq(channel, rank, bl));
+ break;
+ case RDQS:
+ DPF(D_INFO, " %03d", get_rdqs(channel, rank, bl));
+ break;
+ case VREF:
+ DPF(D_INFO, " %03d", get_vref(channel, bl));
+ break;
+ case WCMD:
+ DPF(D_INFO, " %03d", get_wcmd(channel));
+ break;
+ case WCTL:
+ DPF(D_INFO, " %03d", get_wctl(channel, rank));
+ break;
+ case WCLK:
+ DPF(D_INFO, " %03d", get_wclk(channel, rank));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void print_timings(struct mrc_params *mrc_params)
+{
+ uint8_t algo;
+ uint8_t channel;
+ uint8_t rank;
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+
+ DPF(D_INFO, "\n---------------------------");
+ DPF(D_INFO, "\nALGO[CH:RK] BL0 BL1 BL2 BL3");
+ DPF(D_INFO, "\n===========================");
+
+ for (algo = 0; algo < MAX_ALGOS; algo++) {
+ for (channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (mrc_params->channel_enables & (1 << channel)) {
+ for (rank = 0; rank < NUM_RANKS; rank++) {
+ if (mrc_params->rank_enables &
+ (1 << rank)) {
+ print_timings_internal(algo,
+ channel, rank,
+ bl_divisor);
+ }
+ }
+ }
+ }
+ }
+
+ DPF(D_INFO, "\n---------------------------");
+ DPF(D_INFO, "\n");
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/mrc_util.h b/roms/u-boot/arch/x86/cpu/quark/mrc_util.h
new file mode 100644
index 000000000..e6e69c49d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/mrc_util.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+#ifndef _MRC_UTIL_H_
+#define _MRC_UTIL_H_
+
+#include <log.h>
+
+/* Turn on this macro to enable MRC debugging output */
+#undef MRC_DEBUG
+
+/* MRC Debug Support */
+#define DPF debug_cond
+
+/* debug print type */
+
+#ifdef MRC_DEBUG
+#define D_ERROR 0x0001
+#define D_INFO 0x0002
+#define D_REGRD 0x0004
+#define D_REGWR 0x0008
+#define D_FCALL 0x0010
+#define D_TRN 0x0020
+#define D_TIME 0x0040
+#else
+#define D_ERROR 0
+#define D_INFO 0
+#define D_REGRD 0
+#define D_REGWR 0
+#define D_FCALL 0
+#define D_TRN 0
+#define D_TIME 0
+#endif
+
+#define ENTERFN(...) debug_cond(D_FCALL, "<%s>\n", __func__)
+#define LEAVEFN(...) debug_cond(D_FCALL, "</%s>\n", __func__)
+#define REPORTFN(...) debug_cond(D_FCALL, "<%s/>\n", __func__)
+
+/* Message Bus Port */
+#define MEM_CTLR 0x01
+#define HOST_BRIDGE 0x03
+#define MEM_MGR 0x05
+#define HTE 0x11
+#define DDRPHY 0x12
+
+/* number of sample points */
+#define SAMPLE_CNT 3
+/* number of PIs to increment per sample */
+#define SAMPLE_DLY 26
+
+enum {
+ /* indicates to decrease delays when looking for edge */
+ BACKWARD,
+ /* indicates to increase delays when looking for edge */
+ FORWARD
+};
+
+enum {
+ RCVN,
+ WDQS,
+ WDQX,
+ RDQS,
+ VREF,
+ WCMD,
+ WCTL,
+ WCLK,
+ MAX_ALGOS,
+};
+
+void mrc_write_mask(u32 unit, u32 addr, u32 data, u32 mask);
+void mrc_alt_write_mask(u32 unit, u32 addr, u32 data, u32 mask);
+void mrc_post_code(uint8_t major, uint8_t minor);
+void delay_n(uint32_t ns);
+void delay_u(uint32_t ms);
+void select_mem_mgr(void);
+void select_hte(void);
+void dram_init_command(uint32_t data);
+void dram_wake_command(void);
+void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+
+void set_rcvn(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_rdqs(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_wdqs(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_wdq(uint8_t channel, uint8_t rank,
+ uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_wcmd(uint8_t channel, uint32_t pi_count);
+uint32_t get_wcmd(uint8_t channel);
+void set_wclk(uint8_t channel, uint8_t rank, uint32_t pi_count);
+uint32_t get_wclk(uint8_t channel, uint8_t rank);
+void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count);
+uint32_t get_wctl(uint8_t channel, uint8_t rank);
+void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting);
+uint32_t get_vref(uint8_t channel, uint8_t byte_lane);
+
+uint32_t get_addr(uint8_t channel, uint8_t rank);
+uint32_t sample_dqs(struct mrc_params *mrc_params, uint8_t channel,
+ uint8_t rank, bool rcvn);
+void find_rising_edge(struct mrc_params *mrc_params, uint32_t delay[],
+ uint8_t channel, uint8_t rank, bool rcvn);
+uint32_t byte_lane_mask(struct mrc_params *mrc_params);
+uint32_t check_rw_coarse(struct mrc_params *mrc_params, uint32_t address);
+uint32_t check_bls_ex(struct mrc_params *mrc_params, uint32_t address);
+void lfsr32(uint32_t *lfsr_ptr);
+void clear_pointers(void);
+void print_timings(struct mrc_params *mrc_params);
+
+#endif /* _MRC_UTIL_H_ */
diff --git a/roms/u-boot/arch/x86/cpu/quark/msg_port.c b/roms/u-boot/arch/x86/cpu/quark/msg_port.c
new file mode 100644
index 000000000..d4f8c082f
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/msg_port.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/arch/device.h>
+#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
+
+void msg_port_setup(int op, int port, int reg)
+{
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
+ (((op) << 24) | ((port) << 16) |
+ (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
+}
+
+u32 msg_port_read(u8 port, u32 reg)
+{
+ u32 value;
+
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_READ, port, reg);
+ qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+ return value;
+}
+
+void msg_port_write(u8 port, u32 reg, u32 value)
+{
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_WRITE, port, reg);
+}
+
+u32 msg_port_alt_read(u8 port, u32 reg)
+{
+ u32 value;
+
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_ALT_READ, port, reg);
+ qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+ return value;
+}
+
+void msg_port_alt_write(u8 port, u32 reg, u32 value)
+{
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_ALT_WRITE, port, reg);
+}
+
+u32 msg_port_io_read(u8 port, u32 reg)
+{
+ u32 value;
+
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_IO_READ, port, reg);
+ qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+ return value;
+}
+
+void msg_port_io_write(u8 port, u32 reg, u32 value)
+{
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_IO_WRITE, port, reg);
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/quark.c b/roms/u-boot/arch/x86/cpu/quark/quark.c
new file mode 100644
index 000000000..30b4711b9
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/quark.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <mmc.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
+#include <asm/irq.h>
+#include <asm/mrccache.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/arch/device.h>
+#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
+#include <linux/delay.h>
+
+static void quark_setup_mtrr(void)
+{
+ u32 base, mask;
+ int i;
+
+ disable_caches();
+
+ /* mark the VGA RAM area as uncacheable */
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_A0000,
+ MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_B0000,
+ MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+
+ /* mark other fixed range areas as cacheable */
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_00000,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_40000,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_80000,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_90000,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ for (i = MTRR_FIX_4K_C0000; i <= MTRR_FIX_4K_FC000; i++)
+ msg_port_write(MSG_PORT_HOST_BRIDGE, i,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+
+ /* variable range MTRR#0: ROM area */
+ mask = ~(CONFIG_SYS_MONITOR_LEN - 1);
+ base = CONFIG_SYS_TEXT_BASE & mask;
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ROM),
+ base | MTRR_TYPE_WRBACK);
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ROM),
+ mask | MTRR_PHYS_MASK_VALID);
+
+ /* variable range MTRR#1: eSRAM area */
+ mask = ~(ESRAM_SIZE - 1);
+ base = CONFIG_ESRAM_BASE & mask;
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ESRAM),
+ base | MTRR_TYPE_WRBACK);
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ESRAM),
+ mask | MTRR_PHYS_MASK_VALID);
+
+ /* enable both variable and fixed range MTRRs */
+ msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_DEF_TYPE,
+ MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN);
+
+ enable_caches();
+}
+
+static void quark_setup_bars(void)
+{
+ /* GPIO - D31:F0:R44h */
+ qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
+ CONFIG_GPIO_BASE | IO_BAR_EN);
+
+ /* ACPI PM1 Block - D31:F0:R48h */
+ qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
+ CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
+
+ /* GPE0 - D31:F0:R4Ch */
+ qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
+ CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
+
+ /* WDT - D31:F0:R84h */
+ qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
+ CONFIG_WDT_BASE | IO_BAR_EN);
+
+ /* RCBA - D31:F0:RF0h */
+ qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA,
+ CONFIG_RCBA_BASE | MEM_BAR_EN);
+
+ /* ACPI P Block - Msg Port 04:R70h */
+ msg_port_write(MSG_PORT_RMU, PBLK_BA,
+ CONFIG_ACPI_PBLK_BASE | IO_BAR_EN);
+
+ /* SPI DMA - Msg Port 04:R7Ah */
+ msg_port_write(MSG_PORT_RMU, SPI_DMA_BA,
+ CONFIG_SPI_DMA_BASE | IO_BAR_EN);
+
+ /* PCIe ECAM */
+ msg_port_write(MSG_PORT_MEM_ARBITER, AEC_CTRL,
+ CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
+ msg_port_write(MSG_PORT_HOST_BRIDGE, HEC_REG,
+ CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
+}
+
+static void quark_pcie_early_init(void)
+{
+ /*
+ * Step1: Assert PCIe signal PERST#
+ *
+ * The CPU interface to the PERST# signal is platform dependent.
+ * Call the board-specific codes to perform this task.
+ */
+ board_assert_perst();
+
+ /* Step2: PHY common lane reset */
+ msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_PHY_LANE_RST);
+ /* wait 1 ms for PHY common lane reset */
+ mdelay(1);
+
+ /* Step3: PHY sideband interface reset and controller main reset */
+ msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG,
+ PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST);
+ /* wait 80ms for PLL to lock */
+ mdelay(80);
+
+ /* Step4: Controller sideband interface reset */
+ msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_CTLR_SB_RST);
+ /* wait 20ms for controller sideband interface reset */
+ mdelay(20);
+
+ /* Step5: De-assert PERST# */
+ board_deassert_perst();
+
+ /* Step6: Controller primary interface reset */
+ msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_CTLR_PRI_RST);
+
+ /* Mixer Load Lane 0 */
+ msg_port_io_clrbits(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0,
+ (1 << 6) | (1 << 7));
+
+ /* Mixer Load Lane 1 */
+ msg_port_io_clrbits(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1,
+ (1 << 6) | (1 << 7));
+}
+
+static void quark_usb_early_init(void)
+{
+ /* The sequence below comes from Quark firmware writer guide */
+
+ msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT,
+ 1 << 1, (1 << 6) | (1 << 7));
+
+ msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_COMPBG,
+ (1 << 8) | (1 << 9), (1 << 7) | (1 << 10));
+
+ msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 29);
+
+ msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL1, 1 << 1);
+
+ msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_PLL1,
+ (1 << 3) | (1 << 4) | (1 << 5), 1 << 6);
+
+ msg_port_alt_clrbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 29);
+
+ msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 24);
+}
+
+static void quark_thermal_early_init(void)
+{
+ /* The sequence below comes from Quark firmware writer guide */
+
+ /* thermal sensor mode config */
+ msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG1,
+ (1 << 3) | (1 << 4) | (1 << 5), 1 << 5);
+ msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG1,
+ (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) |
+ (1 << 12), 1 << 9);
+ msg_port_alt_setbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 14);
+ msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 17);
+ msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 18);
+ msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG2, 0xffff, 0x011f);
+ msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG3, 0xff, 0x17);
+ msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG3,
+ (1 << 8) | (1 << 9), 1 << 8);
+ msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG3, 0xff000000);
+ msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG4,
+ 0x7ff800, 0xc8 << 11);
+
+ /* thermal monitor catastrophic trip set point (105 celsius) */
+ msg_port_clrsetbits(MSG_PORT_RMU, TS_TRIP, 0xff, 155);
+
+ /* thermal monitor catastrophic trip clear point (0 celsius) */
+ msg_port_clrsetbits(MSG_PORT_RMU, TS_TRIP, 0xff0000, 50 << 16);
+
+ /* take thermal sensor out of reset */
+ msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG4, 1 << 0);
+
+ /* enable thermal monitor */
+ msg_port_setbits(MSG_PORT_RMU, TS_MODE, 1 << 15);
+
+ /* lock all thermal configuration */
+ msg_port_setbits(MSG_PORT_RMU, RMU_CTRL, (1 << 5) | (1 << 6));
+}
+
+static void quark_enable_legacy_seg(void)
+{
+ msg_port_setbits(MSG_PORT_HOST_BRIDGE, HMISC2,
+ HMISC2_SEGE | HMISC2_SEGF | HMISC2_SEGAB);
+}
+
+int arch_cpu_init(void)
+{
+ int ret;
+
+ post_code(POST_CPU_INIT);
+
+ ret = x86_cpu_init_f();
+ if (ret)
+ return ret;
+
+ /*
+ * Quark SoC does not support MSR MTRRs. Fixed and variable range MTRRs
+ * are accessed indirectly via the message port and not the traditional
+ * MSR mechanism. Only UC, WT and WB cache types are supported.
+ */
+ quark_setup_mtrr();
+
+ /*
+ * Quark SoC has some non-standard BARs (excluding PCI standard BARs)
+ * which need be initialized with suggested values
+ */
+ quark_setup_bars();
+
+ /* Initialize USB2 PHY */
+ quark_usb_early_init();
+
+ /* Initialize thermal sensor */
+ quark_thermal_early_init();
+
+ /* Turn on legacy segments (A/B/E/F) decode to system RAM */
+ quark_enable_legacy_seg();
+
+ return 0;
+}
+
+int arch_cpu_init_dm(void)
+{
+ /*
+ * Initialize PCIe controller
+ *
+ * Quark SoC holds the PCIe controller in reset following a power on.
+ * U-Boot needs to release the PCIe controller from reset. The PCIe
+ * controller (D23:F0/F1) will not be visible in PCI configuration
+ * space and any access to its PCI configuration registers will cause
+ * system hang while it is held in reset.
+ */
+ quark_pcie_early_init();
+
+ return 0;
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ post_code(POST_CPU_INFO);
+ return default_print_cpuinfo();
+}
+
+static void quark_pcie_init(void)
+{
+ u32 val;
+
+ /* PCIe upstream non-posted & posted request size */
+ qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_CCFG,
+ CCFG_UPRS | CCFG_UNRS);
+ qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_CCFG,
+ CCFG_UPRS | CCFG_UNRS);
+
+ /* PCIe packet fast transmit mode (IPF) */
+ qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MPC2, MPC2_IPF);
+ qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MPC2, MPC2_IPF);
+
+ /* PCIe message bus idle counter (SBIC) */
+ qrk_pci_read_config_dword(QUARK_PCIE0, PCIE_RP_MBC, &val);
+ val |= MBC_SBIC;
+ qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MBC, val);
+ qrk_pci_read_config_dword(QUARK_PCIE1, PCIE_RP_MBC, &val);
+ val |= MBC_SBIC;
+ qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MBC, val);
+}
+
+static void quark_usb_init(void)
+{
+ u32 bar;
+
+ /* Change USB EHCI packet buffer OUT/IN threshold */
+ qrk_pci_read_config_dword(QUARK_USB_EHCI, PCI_BASE_ADDRESS_0, &bar);
+ writel((0x7f << 16) | 0x7f, bar + EHCI_INSNREG01);
+
+ /* Disable USB device interrupts */
+ qrk_pci_read_config_dword(QUARK_USB_DEVICE, PCI_BASE_ADDRESS_0, &bar);
+ writel(0x7f, bar + USBD_INT_MASK);
+ writel((0xf << 16) | 0xf, bar + USBD_EP_INT_MASK);
+ writel((0xf << 16) | 0xf, bar + USBD_EP_INT_STS);
+}
+
+static void quark_irq_init(void)
+{
+ struct quark_rcba *rcba;
+ u32 base;
+
+ qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
+ base &= ~MEM_BAR_EN;
+ rcba = (struct quark_rcba *)base;
+
+ /*
+ * Route Quark PCI device interrupt pin to PIRQ
+ *
+ * Route device#23's INTA/B/C/D to PIRQA/B/C/D
+ * Route device#20,21's INTA/B/C/D to PIRQE/F/G/H
+ */
+ writew(PIRQC, &rcba->rmu_ir);
+ writew(PIRQA | (PIRQB << 4) | (PIRQC << 8) | (PIRQD << 12),
+ &rcba->d23_ir);
+ writew(PIRQD, &rcba->core_ir);
+ writew(PIRQE | (PIRQF << 4) | (PIRQG << 8) | (PIRQH << 12),
+ &rcba->d20d21_ir);
+}
+
+int arch_early_init_r(void)
+{
+ quark_pcie_init();
+
+ quark_usb_init();
+
+ quark_irq_init();
+
+ return 0;
+}
+
+int arch_misc_init(void)
+{
+#ifdef CONFIG_ENABLE_MRC_CACHE
+ /*
+ * We intend not to check any return value here, as even MRC cache
+ * is not saved successfully, it is not a severe error that will
+ * prevent system from continuing to boot.
+ */
+ mrccache_save();
+#endif
+
+ /* Assign a unique I/O APIC ID */
+ io_apic_set_id(1);
+
+ return 0;
+}
+
+void board_final_init(void)
+{
+ struct quark_rcba *rcba;
+ u32 base, val;
+
+ qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
+ base &= ~MEM_BAR_EN;
+ rcba = (struct quark_rcba *)base;
+
+ /* Initialize 'Component ID' to zero */
+ val = readl(&rcba->esd);
+ val &= ~0xff0000;
+ writel(val, &rcba->esd);
+
+ /* Lock HMBOUND for security */
+ msg_port_setbits(MSG_PORT_HOST_BRIDGE, HM_BOUND, HM_BOUND_LOCK);
+
+ return;
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/smc.c b/roms/u-boot/arch/x86/cpu/quark/smc.c
new file mode 100644
index 000000000..b4b3e1204
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/smc.c
@@ -0,0 +1,2615 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/arch/device.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "hte.h"
+#include "smc.h"
+
+/* t_ck clock period in picoseconds per speed index 800, 1066, 1333 */
+static const uint32_t t_ck[3] = {
+ 2500,
+ 1875,
+ 1500
+};
+
+/* Global variables */
+static const uint16_t ddr_wclk[] = {193, 158};
+#ifdef BACKUP_WCTL
+static const uint16_t ddr_wctl[] = {1, 217};
+#endif
+#ifdef BACKUP_WCMD
+static const uint16_t ddr_wcmd[] = {1, 220};
+#endif
+
+#ifdef BACKUP_RCVN
+static const uint16_t ddr_rcvn[] = {129, 498};
+#endif
+
+#ifdef BACKUP_WDQS
+static const uint16_t ddr_wdqs[] = {65, 289};
+#endif
+
+#ifdef BACKUP_RDQS
+static const uint8_t ddr_rdqs[] = {32, 24};
+#endif
+
+#ifdef BACKUP_WDQ
+static const uint16_t ddr_wdq[] = {32, 257};
+#endif
+
+/* Stop self refresh driven by MCU */
+void clear_self_refresh(struct mrc_params *mrc_params)
+{
+ ENTERFN();
+
+ /* clear the PMSTS Channel Self Refresh bits */
+ mrc_write_mask(MEM_CTLR, PMSTS, PMSTS_DISR, PMSTS_DISR);
+
+ LEAVEFN();
+}
+
+/* It will initialize timing registers in the MCU (DTR0..DTR4) */
+void prog_ddr_timing_control(struct mrc_params *mrc_params)
+{
+ uint8_t tcl, wl;
+ uint8_t trp, trcd, tras, twr, twtr, trrd, trtp, tfaw;
+ uint32_t tck;
+ u32 dtr0, dtr1, dtr2, dtr3, dtr4;
+ u32 tmp1, tmp2;
+
+ ENTERFN();
+
+ /* mcu_init starts */
+ mrc_post_code(0x02, 0x00);
+
+ dtr0 = msg_port_read(MEM_CTLR, DTR0);
+ dtr1 = msg_port_read(MEM_CTLR, DTR1);
+ dtr2 = msg_port_read(MEM_CTLR, DTR2);
+ dtr3 = msg_port_read(MEM_CTLR, DTR3);
+ dtr4 = msg_port_read(MEM_CTLR, DTR4);
+
+ tck = t_ck[mrc_params->ddr_speed]; /* Clock in picoseconds */
+ tcl = mrc_params->params.cl; /* CAS latency in clocks */
+ trp = tcl; /* Per CAT MRC */
+ trcd = tcl; /* Per CAT MRC */
+ tras = MCEIL(mrc_params->params.ras, tck);
+
+ /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
+ twr = MCEIL(15000, tck);
+
+ twtr = MCEIL(mrc_params->params.wtr, tck);
+ trrd = MCEIL(mrc_params->params.rrd, tck);
+ trtp = 4; /* Valid for 800 and 1066, use 5 for 1333 */
+ tfaw = MCEIL(mrc_params->params.faw, tck);
+
+ wl = 5 + mrc_params->ddr_speed;
+
+ dtr0 &= ~DTR0_DFREQ_MASK;
+ dtr0 |= mrc_params->ddr_speed;
+ dtr0 &= ~DTR0_TCL_MASK;
+ tmp1 = tcl - 5;
+ dtr0 |= ((tcl - 5) << 12);
+ dtr0 &= ~DTR0_TRP_MASK;
+ dtr0 |= ((trp - 5) << 4); /* 5 bit DRAM Clock */
+ dtr0 &= ~DTR0_TRCD_MASK;
+ dtr0 |= ((trcd - 5) << 8); /* 5 bit DRAM Clock */
+
+ dtr1 &= ~DTR1_TWCL_MASK;
+ tmp2 = wl - 3;
+ dtr1 |= (wl - 3);
+ dtr1 &= ~DTR1_TWTP_MASK;
+ dtr1 |= ((wl + 4 + twr - 14) << 8); /* Change to tWTP */
+ dtr1 &= ~DTR1_TRTP_MASK;
+ dtr1 |= ((MMAX(trtp, 4) - 3) << 28); /* 4 bit DRAM Clock */
+ dtr1 &= ~DTR1_TRRD_MASK;
+ dtr1 |= ((trrd - 4) << 24); /* 4 bit DRAM Clock */
+ dtr1 &= ~DTR1_TCMD_MASK;
+ dtr1 |= (1 << 4);
+ dtr1 &= ~DTR1_TRAS_MASK;
+ dtr1 |= ((tras - 14) << 20); /* 6 bit DRAM Clock */
+ dtr1 &= ~DTR1_TFAW_MASK;
+ dtr1 |= ((((tfaw + 1) >> 1) - 5) << 16);/* 4 bit DRAM Clock */
+ /* Set 4 Clock CAS to CAS delay (multi-burst) */
+ dtr1 &= ~DTR1_TCCD_MASK;
+
+ dtr2 &= ~DTR2_TRRDR_MASK;
+ dtr2 |= 1;
+ dtr2 &= ~DTR2_TWWDR_MASK;
+ dtr2 |= (2 << 8);
+ dtr2 &= ~DTR2_TRWDR_MASK;
+ dtr2 |= (2 << 16);
+
+ dtr3 &= ~DTR3_TWRDR_MASK;
+ dtr3 |= 2;
+ dtr3 &= ~DTR3_TXXXX_MASK;
+ dtr3 |= (2 << 4);
+
+ dtr3 &= ~DTR3_TRWSR_MASK;
+ if (mrc_params->ddr_speed == DDRFREQ_800) {
+ /* Extended RW delay (+1) */
+ dtr3 |= ((tcl - 5 + 1) << 8);
+ } else if (mrc_params->ddr_speed == DDRFREQ_1066) {
+ /* Extended RW delay (+1) */
+ dtr3 |= ((tcl - 5 + 1) << 8);
+ }
+
+ dtr3 &= ~DTR3_TWRSR_MASK;
+ dtr3 |= ((4 + wl + twtr - 11) << 13);
+
+ dtr3 &= ~DTR3_TXP_MASK;
+ if (mrc_params->ddr_speed == DDRFREQ_800)
+ dtr3 |= ((MMAX(0, 1 - 1)) << 22);
+ else
+ dtr3 |= ((MMAX(0, 2 - 1)) << 22);
+
+ dtr4 &= ~DTR4_WRODTSTRT_MASK;
+ dtr4 |= 1;
+ dtr4 &= ~DTR4_WRODTSTOP_MASK;
+ dtr4 |= (1 << 4);
+ dtr4 &= ~DTR4_XXXX1_MASK;
+ dtr4 |= ((1 + tmp1 - tmp2 + 2) << 8);
+ dtr4 &= ~DTR4_XXXX2_MASK;
+ dtr4 |= ((1 + tmp1 - tmp2 + 2) << 12);
+ dtr4 &= ~(DTR4_ODTDIS | DTR4_TRGSTRDIS);
+
+ msg_port_write(MEM_CTLR, DTR0, dtr0);
+ msg_port_write(MEM_CTLR, DTR1, dtr1);
+ msg_port_write(MEM_CTLR, DTR2, dtr2);
+ msg_port_write(MEM_CTLR, DTR3, dtr3);
+ msg_port_write(MEM_CTLR, DTR4, dtr4);
+
+ LEAVEFN();
+}
+
+/* Configure MCU before jedec init sequence */
+void prog_decode_before_jedec(struct mrc_params *mrc_params)
+{
+ u32 drp;
+ u32 drfc;
+ u32 dcal;
+ u32 dsch;
+ u32 dpmc0;
+
+ ENTERFN();
+
+ /* Disable power saving features */
+ dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+ dpmc0 |= (DPMC0_CLKGTDIS | DPMC0_DISPWRDN);
+ dpmc0 &= ~DPMC0_PCLSTO_MASK;
+ dpmc0 &= ~DPMC0_DYNSREN;
+ msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+ /* Disable out of order transactions */
+ dsch = msg_port_read(MEM_CTLR, DSCH);
+ dsch |= (DSCH_OOODIS | DSCH_NEWBYPDIS);
+ msg_port_write(MEM_CTLR, DSCH, dsch);
+
+ /* Disable issuing the REF command */
+ drfc = msg_port_read(MEM_CTLR, DRFC);
+ drfc &= ~DRFC_TREFI_MASK;
+ msg_port_write(MEM_CTLR, DRFC, drfc);
+
+ /* Disable ZQ calibration short */
+ dcal = msg_port_read(MEM_CTLR, DCAL);
+ dcal &= ~DCAL_ZQCINT_MASK;
+ dcal &= ~DCAL_SRXZQCL_MASK;
+ msg_port_write(MEM_CTLR, DCAL, dcal);
+
+ /*
+ * Training performed in address mode 0, rank population has limited
+ * impact, however simulator complains if enabled non-existing rank.
+ */
+ drp = 0;
+ if (mrc_params->rank_enables & 1)
+ drp |= DRP_RKEN0;
+ if (mrc_params->rank_enables & 2)
+ drp |= DRP_RKEN1;
+ msg_port_write(MEM_CTLR, DRP, drp);
+
+ LEAVEFN();
+}
+
+/*
+ * After Cold Reset, BIOS should set COLDWAKE bit to 1 before
+ * sending the WAKE message to the Dunit.
+ *
+ * For Standby Exit, or any other mode in which the DRAM is in
+ * SR, this bit must be set to 0.
+ */
+void perform_ddr_reset(struct mrc_params *mrc_params)
+{
+ ENTERFN();
+
+ /* Set COLDWAKE bit before sending the WAKE message */
+ mrc_write_mask(MEM_CTLR, DRMC, DRMC_COLDWAKE, DRMC_COLDWAKE);
+
+ /* Send wake command to DUNIT (MUST be done before JEDEC) */
+ dram_wake_command();
+
+ /* Set default value */
+ msg_port_write(MEM_CTLR, DRMC,
+ mrc_params->rd_odt_value == 0 ? DRMC_ODTMODE : 0);
+
+ LEAVEFN();
+}
+
+
+/*
+ * This function performs some initialization on the DDRIO unit.
+ * This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.
+ */
+void ddrphy_init(struct mrc_params *mrc_params)
+{
+ uint32_t temp;
+ uint8_t ch; /* channel counter */
+ uint8_t rk; /* rank counter */
+ uint8_t bl_grp; /* byte lane group counter (2 BLs per module) */
+ uint8_t bl_divisor = 1; /* byte lane divisor */
+ /* For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333 */
+ uint8_t speed = mrc_params->ddr_speed & 3;
+ uint8_t cas;
+ uint8_t cwl;
+
+ ENTERFN();
+
+ cas = mrc_params->params.cl;
+ cwl = 5 + mrc_params->ddr_speed;
+
+ /* ddrphy_init starts */
+ mrc_post_code(0x03, 0x00);
+
+ /*
+ * HSD#231531
+ * Make sure IOBUFACT is deasserted before initializing the DDR PHY
+ *
+ * HSD#234845
+ * Make sure WRPTRENABLE is deasserted before initializing the DDR PHY
+ */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* Deassert DDRPHY Initialization Complete */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
+ ~(1 << 20), 1 << 20); /* SPID_INIT_COMPLETE=0 */
+ /* Deassert IOBUFACT */
+ mrc_alt_write_mask(DDRPHY,
+ CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
+ ~(1 << 2), 1 << 2); /* IOBUFACTRST_N=0 */
+ /* Disable WRPTR */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
+ ~(1 << 0), 1 << 0); /* WRPTRENABLE=0 */
+ }
+ }
+
+ /* Put PHY in reset */
+ mrc_alt_write_mask(DDRPHY, MASTERRSTN, 0, 1);
+
+ /* Initialize DQ01, DQ23, CMD, CLK-CTL, COMP modules */
+
+ /* STEP0 */
+ mrc_post_code(0x03, 0x10);
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* DQ01-DQ23 */
+ for (bl_grp = 0;
+ bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
+ bl_grp++) {
+ /* Analog MUX select - IO2xCLKSEL */
+ mrc_alt_write_mask(DDRPHY,
+ DQOBSCKEBBCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ bl_grp ? 0 : (1 << 22), 1 << 22);
+
+ /* ODT Strength */
+ switch (mrc_params->rd_odt_value) {
+ case 1:
+ temp = 0x3;
+ break; /* 60 ohm */
+ case 2:
+ temp = 0x3;
+ break; /* 120 ohm */
+ case 3:
+ temp = 0x3;
+ break; /* 180 ohm */
+ default:
+ temp = 0x3;
+ break; /* 120 ohm */
+ }
+
+ /* ODT strength */
+ mrc_alt_write_mask(DDRPHY,
+ B0RXIOBUFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp << 5, 0x60);
+ /* ODT strength */
+ mrc_alt_write_mask(DDRPHY,
+ B1RXIOBUFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp << 5, 0x60);
+
+ /* Dynamic ODT/DIFFAMP */
+ temp = (cas << 24) | (cas << 16) |
+ (cas << 8) | (cas << 0);
+ switch (speed) {
+ case 0:
+ temp -= 0x01010101;
+ break; /* 800 */
+ case 1:
+ temp -= 0x02020202;
+ break; /* 1066 */
+ case 2:
+ temp -= 0x03030303;
+ break; /* 1333 */
+ case 3:
+ temp -= 0x04040404;
+ break; /* 1600 */
+ }
+
+ /* Launch Time: ODT, DIFFAMP, ODT, DIFFAMP */
+ mrc_alt_write_mask(DDRPHY,
+ B01LATCTL1 +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp, 0x1f1f1f1f);
+ switch (speed) {
+ /* HSD#234715 */
+ case 0:
+ temp = (0x06 << 16) | (0x07 << 8);
+ break; /* 800 */
+ case 1:
+ temp = (0x07 << 16) | (0x08 << 8);
+ break; /* 1066 */
+ case 2:
+ temp = (0x09 << 16) | (0x0a << 8);
+ break; /* 1333 */
+ case 3:
+ temp = (0x0a << 16) | (0x0b << 8);
+ break; /* 1600 */
+ }
+
+ /* On Duration: ODT, DIFFAMP */
+ mrc_alt_write_mask(DDRPHY,
+ B0ONDURCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp, 0x003f3f00);
+ /* On Duration: ODT, DIFFAMP */
+ mrc_alt_write_mask(DDRPHY,
+ B1ONDURCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp, 0x003f3f00);
+
+ switch (mrc_params->rd_odt_value) {
+ case 0:
+ /* override DIFFAMP=on, ODT=off */
+ temp = (0x3f << 16) | (0x3f << 10);
+ break;
+ default:
+ /* override DIFFAMP=on, ODT=on */
+ temp = (0x3f << 16) | (0x2a << 10);
+ break;
+ }
+
+ /* Override: DIFFAMP, ODT */
+ mrc_alt_write_mask(DDRPHY,
+ B0OVRCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp, 0x003ffc00);
+ /* Override: DIFFAMP, ODT */
+ mrc_alt_write_mask(DDRPHY,
+ B1OVRCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp, 0x003ffc00);
+
+ /* DLL Setup */
+
+ /* 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ B0LATCTL0 +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ ((cas + 7) << 16) | ((cas - 4) << 8) |
+ ((cwl - 2) << 0), 0x003f1f1f);
+ mrc_alt_write_mask(DDRPHY,
+ B1LATCTL0 +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ ((cas + 7) << 16) | ((cas - 4) << 8) |
+ ((cwl - 2) << 0), 0x003f1f1f);
+
+ /* RCVEN Bypass (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ B0RXIOBUFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0, 0x81);
+ mrc_alt_write_mask(DDRPHY,
+ B1RXIOBUFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0, 0x81);
+
+ /* TX */
+ mrc_alt_write_mask(DDRPHY,
+ DQCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 1 << 16, 1 << 16);
+ mrc_alt_write_mask(DDRPHY,
+ B01PTRCTL1 +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 1 << 8, 1 << 8);
+
+ /* RX (PO) */
+ /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
+ mrc_alt_write_mask(DDRPHY,
+ B0VREFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ (0x03 << 2) | (0x0 << 1) | (0x0 << 0),
+ 0xff);
+ /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
+ mrc_alt_write_mask(DDRPHY,
+ B1VREFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ (0x03 << 2) | (0x0 << 1) | (0x0 << 0),
+ 0xff);
+ /* Per-Bit De-Skew Enable */
+ mrc_alt_write_mask(DDRPHY,
+ B0RXIOBUFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0, 0x10);
+ /* Per-Bit De-Skew Enable */
+ mrc_alt_write_mask(DDRPHY,
+ B1RXIOBUFCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0, 0x10);
+ }
+
+ /* CLKEBB */
+ mrc_alt_write_mask(DDRPHY,
+ CMDOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
+ 0, 1 << 23);
+
+ /* Enable tristate control of cmd/address bus */
+ mrc_alt_write_mask(DDRPHY,
+ CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
+ 0, 0x03);
+
+ /* ODT RCOMP */
+ mrc_alt_write_mask(DDRPHY,
+ CMDRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
+ (0x03 << 5) | (0x03 << 0), 0x3ff);
+
+ /* CMDPM* registers must be programmed in this order */
+
+ /* Turn On Delays: SFR (regulator), MPLL */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMDLYREG4 + ch * DDRIOCCC_CH_OFFSET,
+ 0xffffffff, 0xffffffff);
+ /*
+ * Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3,
+ * VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT
+ * for_PM_MSG_gt0, MDLL Turn On
+ */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMDLYREG3 + ch * DDRIOCCC_CH_OFFSET,
+ 0xfffff616, 0xffffffff);
+ /* MPLL Divider Reset Delays */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMDLYREG2 + ch * DDRIOCCC_CH_OFFSET,
+ 0xffffffff, 0xffffffff);
+ /* Turn Off Delays: VREG, Staggered MDLL, MDLL, PI */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMDLYREG1 + ch * DDRIOCCC_CH_OFFSET,
+ 0xffffffff, 0xffffffff);
+ /* Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMDLYREG0 + ch * DDRIOCCC_CH_OFFSET,
+ 0xffffffff, 0xffffffff);
+ /* Allow PUnit signals */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
+ (0x6 << 8) | (0x1 << 6) | (0x4 << 0),
+ 0xffe00f4f);
+ /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
+ mrc_alt_write_mask(DDRPHY,
+ CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
+ (0x3 << 4) | (0x7 << 0), 0x7f);
+
+ /* CLK-CTL */
+ mrc_alt_write_mask(DDRPHY,
+ CCOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
+ 0, 1 << 24); /* CLKEBB */
+ /* Buffer Enable: CS,CKE,ODT,CLK */
+ mrc_alt_write_mask(DDRPHY,
+ CCCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
+ 0x1f, 0x000ffff1);
+ /* ODT RCOMP */
+ mrc_alt_write_mask(DDRPHY,
+ CCRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
+ (0x03 << 8) | (0x03 << 0), 0x00001f1f);
+ /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
+ mrc_alt_write_mask(DDRPHY,
+ CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
+ (0x3 << 4) | (0x7 << 0), 0x7f);
+
+ /*
+ * COMP (RON channel specific)
+ * - DQ/DQS/DM RON: 32 Ohm
+ * - CTRL/CMD RON: 27 Ohm
+ * - CLK RON: 26 Ohm
+ */
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x08 << 24) | (0x03 << 16), 0x3f3f0000);
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ CMDVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x0C << 24) | (0x03 << 16), 0x3f3f0000);
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x0F << 24) | (0x03 << 16), 0x3f3f0000);
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x08 << 24) | (0x03 << 16), 0x3f3f0000);
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ CTLVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x0C << 24) | (0x03 << 16), 0x3f3f0000);
+
+ /* DQS Swapped Input Enable */
+ mrc_alt_write_mask(DDRPHY,
+ COMPEN1CH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 19) | (1 << 17), 0xc00ac000);
+
+ /* ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50) */
+ /* ODT Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x32 << 8) | (0x03 << 0), 0x00003f3f);
+ /* ODT Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x32 << 8) | (0x03 << 0), 0x00003f3f);
+ /* ODT Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x0E << 8) | (0x05 << 0), 0x00003f3f);
+
+ /*
+ * Slew rate settings are frequency specific,
+ * numbers below are for 800Mhz (speed == 0)
+ * - DQ/DQS/DM/CLK SR: 4V/ns,
+ * - CTRL/CMD SR: 1.5V/ns
+ */
+ temp = (0x0e << 16) | (0x0e << 12) | (0x08 << 8) |
+ (0x0b << 4) | (0x0b << 0);
+ /* DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ */
+ mrc_alt_write_mask(DDRPHY,
+ DLYSELCH0 + ch * DDRCOMP_CH_OFFSET,
+ temp, 0x000fffff);
+ /* TCO Vref CLK,DQS,DQ */
+ mrc_alt_write_mask(DDRPHY,
+ TCOVREFCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x05 << 16) | (0x05 << 8) | (0x05 << 0),
+ 0x003f3f3f);
+ /* ODTCOMP CMD/CTL PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ CCBUFODTCH0 + ch * DDRCOMP_CH_OFFSET,
+ (0x03 << 8) | (0x03 << 0),
+ 0x00001f1f);
+ /* COMP */
+ mrc_alt_write_mask(DDRPHY,
+ COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
+ 0, 0xc0000100);
+
+#ifdef BACKUP_COMPS
+ /* DQ COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x10 << 16),
+ 0x801f0000);
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x10 << 16),
+ 0x801f0000);
+ /* ODTCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0b << 16),
+ 0x801f0000);
+ /* ODTCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0b << 16),
+ 0x801f0000);
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 31, 1 << 31);
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 31, 1 << 31);
+
+ /* DQS COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQSDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQSDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x10 << 16),
+ 0x801f0000);
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x10 << 16),
+ 0x801f0000);
+ /* ODTCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQSODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0b << 16),
+ 0x801f0000);
+ /* ODTCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0b << 16),
+ 0x801f0000);
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 31, 1 << 31);
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 31, 1 << 31);
+
+ /* CLK COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CLKDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0c << 16),
+ 0x801f0000);
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0c << 16),
+ 0x801f0000);
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CLKDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x07 << 16),
+ 0x801f0000);
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x07 << 16),
+ 0x801f0000);
+ /* ODTCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CLKODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0b << 16),
+ 0x801f0000);
+ /* ODTCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0b << 16),
+ 0x801f0000);
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 31, 1 << 31);
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 31, 1 << 31);
+
+ /* CMD COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CMDDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0d << 16),
+ 0x803f0000);
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CMDDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0d << 16),
+ 0x803f0000);
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CMDDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CMDDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+
+ /* CTL COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CTLDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0d << 16),
+ 0x803f0000);
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CTLDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0d << 16),
+ 0x803f0000);
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CTLDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CTLDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x0a << 16),
+ 0x801f0000);
+#else
+ /* DQ TCOCOMP Overrides */
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x1f << 16),
+ 0x801f0000);
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x1f << 16),
+ 0x801f0000);
+
+ /* DQS TCOCOMP Overrides */
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x1f << 16),
+ 0x801f0000);
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x1f << 16),
+ 0x801f0000);
+
+ /* CLK TCOCOMP Overrides */
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x1f << 16),
+ 0x801f0000);
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
+ (1 << 31) | (0x1f << 16),
+ 0x801f0000);
+#endif
+
+ /* program STATIC delays */
+#ifdef BACKUP_WCMD
+ set_wcmd(ch, ddr_wcmd[PLATFORM_ID]);
+#else
+ set_wcmd(ch, ddr_wclk[PLATFORM_ID] + HALF_CLK);
+#endif
+
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ set_wclk(ch, rk, ddr_wclk[PLATFORM_ID]);
+#ifdef BACKUP_WCTL
+ set_wctl(ch, rk, ddr_wctl[PLATFORM_ID]);
+#else
+ set_wctl(ch, rk, ddr_wclk[PLATFORM_ID] + HALF_CLK);
+#endif
+ }
+ }
+ }
+ }
+
+ /* COMP (non channel specific) */
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQANADRVPUCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQANADRVPDCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CMDANADRVPUCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CMDANADRVPDCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANADRVPUCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANADRVPDCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANADRVPUCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANADRVPDCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CTLANADRVPUCTL, 1 << 30, 1 << 30);
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CTLANADRVPDCTL, 1 << 30, 1 << 30);
+ /* ODT: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQANAODTPUCTL, 1 << 30, 1 << 30);
+ /* ODT: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQANAODTPDCTL, 1 << 30, 1 << 30);
+ /* ODT: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANAODTPUCTL, 1 << 30, 1 << 30);
+ /* ODT: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANAODTPDCTL, 1 << 30, 1 << 30);
+ /* ODT: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANAODTPUCTL, 1 << 30, 1 << 30);
+ /* ODT: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANAODTPDCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQANADLYPUCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQANADLYPDCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CMDANADLYPUCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CMDANADLYPDCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANADLYPUCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANADLYPDCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANADLYPUCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANADLYPDCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CTLANADLYPUCTL, 1 << 30, 1 << 30);
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CTLANADLYPDCTL, 1 << 30, 1 << 30);
+ /* TCO: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQANATCOPUCTL, 1 << 30, 1 << 30);
+ /* TCO: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQANATCOPDCTL, 1 << 30, 1 << 30);
+ /* TCO: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANATCOPUCTL, 1 << 30, 1 << 30);
+ /* TCO: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, CLKANATCOPDCTL, 1 << 30, 1 << 30);
+ /* TCO: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANATCOPUCTL, 1 << 30, 1 << 30);
+ /* TCO: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, DQSANATCOPDCTL, 1 << 30, 1 << 30);
+ /* TCOCOMP: Pulse Count */
+ mrc_alt_write_mask(DDRPHY, TCOCNTCTRL, 1, 3);
+ /* ODT: CMD/CTL PD/PU */
+ mrc_alt_write_mask(DDRPHY, CHNLBUFSTATIC,
+ (0x03 << 24) | (0x03 << 16), 0x1f1f0000);
+ /* Set 1us counter */
+ mrc_alt_write_mask(DDRPHY, MSCNTR, 0x64, 0xff);
+ mrc_alt_write_mask(DDRPHY, LATCH1CTL, 0x1 << 28, 0x70000000);
+
+ /* Release PHY from reset */
+ mrc_alt_write_mask(DDRPHY, MASTERRSTN, 1, 1);
+
+ /* STEP1 */
+ mrc_post_code(0x03, 0x11);
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* DQ01-DQ23 */
+ for (bl_grp = 0;
+ bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
+ bl_grp++) {
+ mrc_alt_write_mask(DDRPHY,
+ DQMDLLCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 1 << 13,
+ 1 << 13); /* Enable VREG */
+ delay_n(3);
+ }
+
+ /* ECC */
+ mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
+ 1 << 13, 1 << 13); /* Enable VREG */
+ delay_n(3);
+ /* CMD */
+ mrc_alt_write_mask(DDRPHY,
+ CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 13, 1 << 13); /* Enable VREG */
+ delay_n(3);
+ /* CLK-CTL */
+ mrc_alt_write_mask(DDRPHY,
+ CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 13, 1 << 13); /* Enable VREG */
+ delay_n(3);
+ }
+ }
+
+ /* STEP2 */
+ mrc_post_code(0x03, 0x12);
+ delay_n(200);
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* DQ01-DQ23 */
+ for (bl_grp = 0;
+ bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
+ bl_grp++) {
+ mrc_alt_write_mask(DDRPHY,
+ DQMDLLCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 1 << 17,
+ 1 << 17); /* Enable MCDLL */
+ delay_n(50);
+ }
+
+ /* ECC */
+ mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
+ 1 << 17, 1 << 17); /* Enable MCDLL */
+ delay_n(50);
+ /* CMD */
+ mrc_alt_write_mask(DDRPHY,
+ CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 18, 1 << 18); /* Enable MCDLL */
+ delay_n(50);
+ /* CLK-CTL */
+ mrc_alt_write_mask(DDRPHY,
+ CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 18, 1 << 18); /* Enable MCDLL */
+ delay_n(50);
+ }
+ }
+
+ /* STEP3: */
+ mrc_post_code(0x03, 0x13);
+ delay_n(100);
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* DQ01-DQ23 */
+ for (bl_grp = 0;
+ bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
+ bl_grp++) {
+#ifdef FORCE_16BIT_DDRIO
+ temp = (bl_grp &&
+ (mrc_params->channel_width == X16)) ?
+ 0x11ff : 0xffff;
+#else
+ temp = 0xffff;
+#endif
+ /* Enable TXDLL */
+ mrc_alt_write_mask(DDRPHY,
+ DQDLLTXCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ temp, 0xffff);
+ delay_n(3);
+ /* Enable RXDLL */
+ mrc_alt_write_mask(DDRPHY,
+ DQDLLRXCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0xf, 0xf);
+ delay_n(3);
+ /* Enable RXDLL Overrides BL0 */
+ mrc_alt_write_mask(DDRPHY,
+ B0OVRCTL +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0xf, 0xf);
+ }
+
+ /* ECC */
+ temp = 0xffff;
+ mrc_alt_write_mask(DDRPHY, ECCDLLTXCTL,
+ temp, 0xffff);
+ delay_n(3);
+
+ /* CMD (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ CMDDLLTXCTL + ch * DDRIOCCC_CH_OFFSET,
+ temp, 0xffff);
+ delay_n(3);
+ }
+ }
+
+ /* STEP4 */
+ mrc_post_code(0x03, 0x14);
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* Host To Memory Clock Alignment (HMC) for 800/1066 */
+ for (bl_grp = 0;
+ bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
+ bl_grp++) {
+ /* CLK_ALIGN_MOD_ID */
+ mrc_alt_write_mask(DDRPHY,
+ DQCLKALIGNREG2 +
+ bl_grp * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ bl_grp ? 3 : 1,
+ 0xf);
+ }
+
+ mrc_alt_write_mask(DDRPHY,
+ ECCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
+ 0x2, 0xf);
+ mrc_alt_write_mask(DDRPHY,
+ CMDCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
+ 0x0, 0xf);
+ mrc_alt_write_mask(DDRPHY,
+ CCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
+ 0x2, 0xf);
+ mrc_alt_write_mask(DDRPHY,
+ CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
+ 0x20, 0x30);
+ /*
+ * NUM_SAMPLES, MAX_SAMPLES,
+ * MACRO_PI_STEP, MICRO_PI_STEP
+ */
+ mrc_alt_write_mask(DDRPHY,
+ CMDCLKALIGNREG1 + ch * DDRIOCCC_CH_OFFSET,
+ (0x18 << 16) | (0x10 << 8) |
+ (0x8 << 2) | (0x1 << 0),
+ 0x007f7fff);
+ /* TOTAL_NUM_MODULES, FIRST_U_PARTITION */
+ mrc_alt_write_mask(DDRPHY,
+ CMDCLKALIGNREG2 + ch * DDRIOCCC_CH_OFFSET,
+ (0x10 << 16) | (0x4 << 8) | (0x2 << 4),
+ 0x001f0ff0);
+#ifdef HMC_TEST
+ /* START_CLK_ALIGN=1 */
+ mrc_alt_write_mask(DDRPHY,
+ CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 24, 1 << 24);
+ while (msg_port_alt_read(DDRPHY,
+ CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET) &
+ (1 << 24))
+ ; /* wait for START_CLK_ALIGN=0 */
+#endif
+
+ /* Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
+ 1, 1); /* WRPTRENABLE=1 */
+
+ /* COMP initial */
+ /* enable bypass for CLK buffer (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
+ 1 << 5, 1 << 5);
+ /* Initial COMP Enable */
+ mrc_alt_write_mask(DDRPHY, CMPCTRL, 1, 1);
+ /* wait for Initial COMP Enable = 0 */
+ while (msg_port_alt_read(DDRPHY, CMPCTRL) & 1)
+ ;
+ /* disable bypass for CLK buffer (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
+ ~(1 << 5), 1 << 5);
+
+ /* IOBUFACT */
+
+ /* STEP4a */
+ mrc_alt_write_mask(DDRPHY,
+ CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 2, 1 << 2); /* IOBUFACTRST_N=1 */
+
+ /* DDRPHY initialization complete */
+ mrc_alt_write_mask(DDRPHY,
+ CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
+ 1 << 20, 1 << 20); /* SPID_INIT_COMPLETE=1 */
+ }
+ }
+
+ LEAVEFN();
+}
+
+/* This function performs JEDEC initialization on all enabled channels */
+void perform_jedec_init(struct mrc_params *mrc_params)
+{
+ uint8_t twr, wl, rank;
+ uint32_t tck;
+ u32 dtr0;
+ u32 drp;
+ u32 drmc;
+ u32 mrs0_cmd = 0;
+ u32 emrs1_cmd = 0;
+ u32 emrs2_cmd = 0;
+ u32 emrs3_cmd = 0;
+
+ ENTERFN();
+
+ /* jedec_init starts */
+ mrc_post_code(0x04, 0x00);
+
+ /* DDR3_RESET_SET=0, DDR3_RESET_RESET=1 */
+ mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, 2, 0x102);
+
+ /* Assert RESET# for 200us */
+ delay_u(200);
+
+ /* DDR3_RESET_SET=1, DDR3_RESET_RESET=0 */
+ mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, 0x100, 0x102);
+
+ dtr0 = msg_port_read(MEM_CTLR, DTR0);
+
+ /*
+ * Set CKEVAL for populated ranks
+ * then send NOP to each rank (#4550197)
+ */
+
+ drp = msg_port_read(MEM_CTLR, DRP);
+ drp &= 0x3;
+
+ drmc = msg_port_read(MEM_CTLR, DRMC);
+ drmc &= 0xfffffffc;
+ drmc |= (DRMC_CKEMODE | drp);
+
+ msg_port_write(MEM_CTLR, DRMC, drmc);
+
+ for (rank = 0; rank < NUM_RANKS; rank++) {
+ /* Skip to next populated rank */
+ if ((mrc_params->rank_enables & (1 << rank)) == 0)
+ continue;
+
+ dram_init_command(DCMD_NOP(rank));
+ }
+
+ msg_port_write(MEM_CTLR, DRMC,
+ (mrc_params->rd_odt_value == 0 ? DRMC_ODTMODE : 0));
+
+ /*
+ * setup for emrs 2
+ * BIT[15:11] --> Always "0"
+ * BIT[10:09] --> Rtt_WR: want "Dynamic ODT Off" (0)
+ * BIT[08] --> Always "0"
+ * BIT[07] --> SRT: use sr_temp_range
+ * BIT[06] --> ASR: want "Manual SR Reference" (0)
+ * BIT[05:03] --> CWL: use oem_tCWL
+ * BIT[02:00] --> PASR: want "Full Array" (0)
+ */
+ emrs2_cmd |= (2 << 3);
+ wl = 5 + mrc_params->ddr_speed;
+ emrs2_cmd |= ((wl - 5) << 9);
+ emrs2_cmd |= (mrc_params->sr_temp_range << 13);
+
+ /*
+ * setup for emrs 3
+ * BIT[15:03] --> Always "0"
+ * BIT[02] --> MPR: want "Normal Operation" (0)
+ * BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)
+ */
+ emrs3_cmd |= (3 << 3);
+
+ /*
+ * setup for emrs 1
+ * BIT[15:13] --> Always "0"
+ * BIT[12:12] --> Qoff: want "Output Buffer Enabled" (0)
+ * BIT[11:11] --> TDQS: want "Disabled" (0)
+ * BIT[10:10] --> Always "0"
+ * BIT[09,06,02] --> Rtt_nom: use rtt_nom_value
+ * BIT[08] --> Always "0"
+ * BIT[07] --> WR_LVL: want "Disabled" (0)
+ * BIT[05,01] --> DIC: use ron_value
+ * BIT[04:03] --> AL: additive latency want "0" (0)
+ * BIT[00] --> DLL: want "Enable" (0)
+ *
+ * (BIT5|BIT1) set Ron value
+ * 00 --> RZQ/6 (40ohm)
+ * 01 --> RZQ/7 (34ohm)
+ * 1* --> RESERVED
+ *
+ * (BIT9|BIT6|BIT2) set Rtt_nom value
+ * 000 --> Disabled
+ * 001 --> RZQ/4 ( 60ohm)
+ * 010 --> RZQ/2 (120ohm)
+ * 011 --> RZQ/6 ( 40ohm)
+ * 1** --> RESERVED
+ */
+ emrs1_cmd |= (1 << 3);
+ emrs1_cmd &= ~(1 << 6);
+
+ if (mrc_params->ron_value == 0)
+ emrs1_cmd |= (1 << 7);
+ else
+ emrs1_cmd &= ~(1 << 7);
+
+ if (mrc_params->rtt_nom_value == 0)
+ emrs1_cmd |= (DDR3_EMRS1_RTTNOM_40 << 6);
+ else if (mrc_params->rtt_nom_value == 1)
+ emrs1_cmd |= (DDR3_EMRS1_RTTNOM_60 << 6);
+ else if (mrc_params->rtt_nom_value == 2)
+ emrs1_cmd |= (DDR3_EMRS1_RTTNOM_120 << 6);
+
+ /* save MRS1 value (excluding control fields) */
+ mrc_params->mrs1 = emrs1_cmd >> 6;
+
+ /*
+ * setup for mrs 0
+ * BIT[15:13] --> Always "0"
+ * BIT[12] --> PPD: for Quark (1)
+ * BIT[11:09] --> WR: use oem_tWR
+ * BIT[08] --> DLL: want "Reset" (1, self clearing)
+ * BIT[07] --> MODE: want "Normal" (0)
+ * BIT[06:04,02] --> CL: use oem_tCAS
+ * BIT[03] --> RD_BURST_TYPE: want "Interleave" (1)
+ * BIT[01:00] --> BL: want "8 Fixed" (0)
+ * WR:
+ * 0 --> 16
+ * 1 --> 5
+ * 2 --> 6
+ * 3 --> 7
+ * 4 --> 8
+ * 5 --> 10
+ * 6 --> 12
+ * 7 --> 14
+ * CL:
+ * BIT[02:02] "0" if oem_tCAS <= 11 (1866?)
+ * BIT[06:04] use oem_tCAS-4
+ */
+ mrs0_cmd |= (1 << 14);
+ mrs0_cmd |= (1 << 18);
+ mrs0_cmd |= ((((dtr0 >> 12) & 7) + 1) << 10);
+
+ tck = t_ck[mrc_params->ddr_speed];
+ /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
+ twr = MCEIL(15000, tck);
+ mrs0_cmd |= ((twr - 4) << 15);
+
+ for (rank = 0; rank < NUM_RANKS; rank++) {
+ /* Skip to next populated rank */
+ if ((mrc_params->rank_enables & (1 << rank)) == 0)
+ continue;
+
+ emrs2_cmd |= (rank << 22);
+ dram_init_command(emrs2_cmd);
+
+ emrs3_cmd |= (rank << 22);
+ dram_init_command(emrs3_cmd);
+
+ emrs1_cmd |= (rank << 22);
+ dram_init_command(emrs1_cmd);
+
+ mrs0_cmd |= (rank << 22);
+ dram_init_command(mrs0_cmd);
+
+ dram_init_command(DCMD_ZQCL(rank));
+ }
+
+ LEAVEFN();
+}
+
+/*
+ * Dunit Initialization Complete
+ *
+ * Indicates that initialization of the Dunit has completed.
+ *
+ * Memory accesses are permitted and maintenance operation begins.
+ * Until this bit is set to a 1, the memory controller will not accept
+ * DRAM requests from the MEMORY_MANAGER or HTE.
+ */
+void set_ddr_init_complete(struct mrc_params *mrc_params)
+{
+ u32 dco;
+
+ ENTERFN();
+
+ dco = msg_port_read(MEM_CTLR, DCO);
+ dco &= ~DCO_PMICTL;
+ dco |= DCO_IC;
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ LEAVEFN();
+}
+
+/*
+ * This function will retrieve relevant timing data
+ *
+ * This data will be used on subsequent boots to speed up boot times
+ * and is required for Suspend To RAM capabilities.
+ */
+void restore_timings(struct mrc_params *mrc_params)
+{
+ uint8_t ch, rk, bl;
+ const struct mrc_timings *mt = &mrc_params->timings;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+ set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]);
+ set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]);
+ set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]);
+ set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]);
+ if (rk == 0) {
+ /* VREF (RANK0 only) */
+ set_vref(ch, bl, mt->vref[ch][bl]);
+ }
+ }
+ set_wctl(ch, rk, mt->wctl[ch][rk]);
+ }
+ set_wcmd(ch, mt->wcmd[ch]);
+ }
+}
+
+/*
+ * Configure default settings normally set as part of read training
+ *
+ * Some defaults have to be set earlier as they may affect earlier
+ * training steps.
+ */
+void default_timings(struct mrc_params *mrc_params)
+{
+ uint8_t ch, rk, bl;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+ set_rdqs(ch, rk, bl, 24);
+ if (rk == 0) {
+ /* VREF (RANK0 only) */
+ set_vref(ch, bl, 32);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * This function will perform our RCVEN Calibration Algorithm.
+ * We will only use the 2xCLK domain timings to perform RCVEN Calibration.
+ * All byte lanes will be calibrated "simultaneously" per channel per rank.
+ */
+void rcvn_cal(struct mrc_params *mrc_params)
+{
+ uint8_t ch; /* channel counter */
+ uint8_t rk; /* rank counter */
+ uint8_t bl; /* byte lane counter */
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+
+#ifdef R2R_SHARING
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+#ifndef BACKUP_RCVN
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+#ifdef BACKUP_RCVN
+#else
+ uint32_t temp;
+ /* absolute PI value to be programmed on the byte lane */
+ uint32_t delay[NUM_BYTE_LANES];
+ u32 dtr1, dtr1_save;
+#endif
+
+ ENTERFN();
+
+ /* rcvn_cal starts */
+ mrc_post_code(0x05, 0x00);
+
+#ifndef BACKUP_RCVN
+ /* need separate burst to sample DQS preamble */
+ dtr1 = msg_port_read(MEM_CTLR, DTR1);
+ dtr1_save = dtr1;
+ dtr1 |= DTR1_TCCD_12CLK;
+ msg_port_write(MEM_CTLR, DTR1, dtr1);
+#endif
+
+#ifdef R2R_SHARING
+ /* need to set "final_delay[][]" elements to "0" */
+ memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+ /* loop through each enabled channel */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* perform RCVEN Calibration on a per rank basis */
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ /*
+ * POST_CODE here indicates the current
+ * channel and rank being calibrated
+ */
+ mrc_post_code(0x05, 0x10 + ((ch << 4) | rk));
+
+#ifdef BACKUP_RCVN
+ /* et hard-coded timing values */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++)
+ set_rcvn(ch, rk, bl, ddr_rcvn[PLATFORM_ID]);
+#else
+ /* enable FIFORST */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
+ mrc_alt_write_mask(DDRPHY,
+ B01PTRCTL1 +
+ (bl >> 1) * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 0, 1 << 8);
+ }
+ /* initialize the starting delay to 128 PI (cas +1 CLK) */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ /* 1x CLK domain timing is cas-4 */
+ delay[bl] = (4 + 1) * FULL_CLK;
+
+ set_rcvn(ch, rk, bl, delay[bl]);
+ }
+
+ /* now find the rising edge */
+ find_rising_edge(mrc_params, delay, ch, rk, true);
+
+ /* Now increase delay by 32 PI (1/4 CLK) to place in center of high pulse */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ delay[bl] += QRTR_CLK;
+ set_rcvn(ch, rk, bl, delay[bl]);
+ }
+ /* Now decrement delay by 128 PI (1 CLK) until we sample a "0" */
+ do {
+ temp = sample_dqs(mrc_params, ch, rk, true);
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ if (temp & (1 << bl)) {
+ if (delay[bl] >= FULL_CLK) {
+ delay[bl] -= FULL_CLK;
+ set_rcvn(ch, rk, bl, delay[bl]);
+ } else {
+ /* not enough delay */
+ training_message(ch, rk, bl);
+ mrc_post_code(0xee, 0x50);
+ }
+ }
+ }
+ } while (temp & 0xff);
+
+#ifdef R2R_SHARING
+ /* increment "num_ranks_enabled" */
+ num_ranks_enabled++;
+ /* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ delay[bl] += QRTR_CLK;
+ /* add "delay[]" values to "final_delay[][]" for rolling average */
+ final_delay[ch][bl] += delay[bl];
+ /* set timing based on rolling average values */
+ set_rcvn(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
+ }
+#else
+ /* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ delay[bl] += QRTR_CLK;
+ set_rcvn(ch, rk, bl, delay[bl]);
+ }
+#endif
+
+ /* disable FIFORST */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
+ mrc_alt_write_mask(DDRPHY,
+ B01PTRCTL1 +
+ (bl >> 1) * DDRIODQ_BL_OFFSET +
+ ch * DDRIODQ_CH_OFFSET,
+ 1 << 8, 1 << 8);
+ }
+#endif
+ }
+ }
+ }
+ }
+
+#ifndef BACKUP_RCVN
+ /* restore original */
+ msg_port_write(MEM_CTLR, DTR1, dtr1_save);
+#endif
+
+ LEAVEFN();
+}
+
+/*
+ * This function will perform the Write Levelling algorithm
+ * (align WCLK and WDQS).
+ *
+ * This algorithm will act on each rank in each channel separately.
+ */
+void wr_level(struct mrc_params *mrc_params)
+{
+ uint8_t ch; /* channel counter */
+ uint8_t rk; /* rank counter */
+ uint8_t bl; /* byte lane counter */
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+
+#ifdef R2R_SHARING
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+#ifndef BACKUP_WDQS
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+#ifdef BACKUP_WDQS
+#else
+ /* determines stop condition for CRS_WR_LVL */
+ bool all_edges_found;
+ /* absolute PI value to be programmed on the byte lane */
+ uint32_t delay[NUM_BYTE_LANES];
+ /*
+ * static makes it so the data is loaded in the heap once by shadow(),
+ * where non-static copies the data onto the stack every time this
+ * function is called
+ */
+ uint32_t address; /* address to be checked during COARSE_WR_LVL */
+ u32 dtr4, dtr4_save;
+#endif
+
+ ENTERFN();
+
+ /* wr_level starts */
+ mrc_post_code(0x06, 0x00);
+
+#ifdef R2R_SHARING
+ /* need to set "final_delay[][]" elements to "0" */
+ memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+ /* loop through each enabled channel */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ /* perform WRITE LEVELING algorithm on a per rank basis */
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ /*
+ * POST_CODE here indicates the current
+ * rank and channel being calibrated
+ */
+ mrc_post_code(0x06, 0x10 + ((ch << 4) | rk));
+
+#ifdef BACKUP_WDQS
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ set_wdqs(ch, rk, bl, ddr_wdqs[PLATFORM_ID]);
+ set_wdq(ch, rk, bl, ddr_wdqs[PLATFORM_ID] - QRTR_CLK);
+ }
+#else
+ /*
+ * perform a single PRECHARGE_ALL command to
+ * make DRAM state machine go to IDLE state
+ */
+ dram_init_command(DCMD_PREA(rk));
+
+ /*
+ * enable Write Levelling Mode
+ * (EMRS1 w/ Write Levelling Mode Enable)
+ */
+ dram_init_command(DCMD_MRS1(rk, 0x82));
+
+ /*
+ * set ODT DRAM Full Time Termination
+ * disable in MCU
+ */
+
+ dtr4 = msg_port_read(MEM_CTLR, DTR4);
+ dtr4_save = dtr4;
+ dtr4 |= DTR4_ODTDIS;
+ msg_port_write(MEM_CTLR, DTR4, dtr4);
+
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
+ /*
+ * Enable Sandy Bridge Mode (WDQ Tri-State) &
+ * Ensure 5 WDQS pulses during Write Leveling
+ */
+ mrc_alt_write_mask(DDRPHY,
+ DQCTL + DDRIODQ_BL_OFFSET * bl + DDRIODQ_CH_OFFSET * ch,
+ 0x10000154,
+ 0x100003fc);
+ }
+
+ /* Write Leveling Mode enabled in IO */
+ mrc_alt_write_mask(DDRPHY,
+ CCDDR3RESETCTL + DDRIOCCC_CH_OFFSET * ch,
+ 1 << 16, 1 << 16);
+
+ /* Initialize the starting delay to WCLK */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ /*
+ * CLK0 --> RK0
+ * CLK1 --> RK1
+ */
+ delay[bl] = get_wclk(ch, rk);
+
+ set_wdqs(ch, rk, bl, delay[bl]);
+ }
+
+ /* now find the rising edge */
+ find_rising_edge(mrc_params, delay, ch, rk, false);
+
+ /* disable Write Levelling Mode */
+ mrc_alt_write_mask(DDRPHY,
+ CCDDR3RESETCTL + DDRIOCCC_CH_OFFSET * ch,
+ 0, 1 << 16);
+
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
+ /* Disable Sandy Bridge Mode & Ensure 4 WDQS pulses during normal operation */
+ mrc_alt_write_mask(DDRPHY,
+ DQCTL + DDRIODQ_BL_OFFSET * bl + DDRIODQ_CH_OFFSET * ch,
+ 0x00000154,
+ 0x100003fc);
+ }
+
+ /* restore original DTR4 */
+ msg_port_write(MEM_CTLR, DTR4, dtr4_save);
+
+ /*
+ * restore original value
+ * (Write Levelling Mode Disable)
+ */
+ dram_init_command(DCMD_MRS1(rk, mrc_params->mrs1));
+
+ /*
+ * perform a single PRECHARGE_ALL command to
+ * make DRAM state machine go to IDLE state
+ */
+ dram_init_command(DCMD_PREA(rk));
+
+ mrc_post_code(0x06, 0x30 + ((ch << 4) | rk));
+
+ /*
+ * COARSE WRITE LEVEL:
+ * check that we're on the correct clock edge
+ */
+
+ /* hte reconfiguration request */
+ mrc_params->hte_setup = 1;
+
+ /* start CRS_WR_LVL with WDQS = WDQS + 128 PI */
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ delay[bl] = get_wdqs(ch, rk, bl) + FULL_CLK;
+ set_wdqs(ch, rk, bl, delay[bl]);
+ /*
+ * program WDQ timings based on WDQS
+ * (WDQ = WDQS - 32 PI)
+ */
+ set_wdq(ch, rk, bl, (delay[bl] - QRTR_CLK));
+ }
+
+ /* get an address in the targeted channel/rank */
+ address = get_addr(ch, rk);
+ do {
+ uint32_t coarse_result = 0x00;
+ uint32_t coarse_result_mask = byte_lane_mask(mrc_params);
+ /* assume pass */
+ all_edges_found = true;
+
+ mrc_params->hte_setup = 1;
+ coarse_result = check_rw_coarse(mrc_params, address);
+
+ /* check for failures and margin the byte lane back 128 PI (1 CLK) */
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ if (coarse_result & (coarse_result_mask << bl)) {
+ all_edges_found = false;
+ delay[bl] -= FULL_CLK;
+ set_wdqs(ch, rk, bl, delay[bl]);
+ /* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
+ set_wdq(ch, rk, bl, delay[bl] - QRTR_CLK);
+ }
+ }
+ } while (!all_edges_found);
+
+#ifdef R2R_SHARING
+ /* increment "num_ranks_enabled" */
+ num_ranks_enabled++;
+ /* accumulate "final_delay[][]" values from "delay[]" values for rolling average */
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ final_delay[ch][bl] += delay[bl];
+ set_wdqs(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
+ /* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
+ set_wdq(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled - QRTR_CLK);
+ }
+#endif
+#endif
+ }
+ }
+ }
+ }
+
+ LEAVEFN();
+}
+
+void prog_page_ctrl(struct mrc_params *mrc_params)
+{
+ u32 dpmc0;
+
+ ENTERFN();
+
+ dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+ dpmc0 &= ~DPMC0_PCLSTO_MASK;
+ dpmc0 |= (4 << 16);
+ dpmc0 |= DPMC0_PREAPWDEN;
+ msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+}
+
+/*
+ * This function will perform the READ TRAINING Algorithm on all
+ * channels/ranks/byte_lanes simultaneously to minimize execution time.
+ *
+ * The idea here is to train the VREF and RDQS (and eventually RDQ) values
+ * to achieve maximum READ margins. The algorithm will first determine the
+ * X coordinate (RDQS setting). This is done by collapsing the VREF eye
+ * until we find a minimum required RDQS eye for VREF_MIN and VREF_MAX.
+ * Then we take the averages of the RDQS eye at VREF_MIN and VREF_MAX,
+ * then average those; this will be the final X coordinate. The algorithm
+ * will then determine the Y coordinate (VREF setting). This is done by
+ * collapsing the RDQS eye until we find a minimum required VREF eye for
+ * RDQS_MIN and RDQS_MAX. Then we take the averages of the VREF eye at
+ * RDQS_MIN and RDQS_MAX, then average those; this will be the final Y
+ * coordinate.
+ *
+ * NOTE: this algorithm assumes the eye curves have a one-to-one relationship,
+ * meaning for each X the curve has only one Y and vice-a-versa.
+ */
+void rd_train(struct mrc_params *mrc_params)
+{
+ uint8_t ch; /* channel counter */
+ uint8_t rk; /* rank counter */
+ uint8_t bl; /* byte lane counter */
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+#ifdef BACKUP_RDQS
+#else
+ uint8_t side_x; /* tracks LEFT/RIGHT approach vectors */
+ uint8_t side_y; /* tracks BOTTOM/TOP approach vectors */
+ /* X coordinate data (passing RDQS values) for approach vectors */
+ uint8_t x_coordinate[2][2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ /* Y coordinate data (passing VREF values) for approach vectors */
+ uint8_t y_coordinate[2][2][NUM_CHANNELS][NUM_BYTE_LANES];
+ /* centered X (RDQS) */
+ uint8_t x_center[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ /* centered Y (VREF) */
+ uint8_t y_center[NUM_CHANNELS][NUM_BYTE_LANES];
+ uint32_t address; /* target address for check_bls_ex() */
+ uint32_t result; /* result of check_bls_ex() */
+ uint32_t bl_mask; /* byte lane mask for result checking */
+#ifdef R2R_SHARING
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+ /* rd_train starts */
+ mrc_post_code(0x07, 0x00);
+
+ ENTERFN();
+
+#ifdef BACKUP_RDQS
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ for (bl = 0;
+ bl < NUM_BYTE_LANES / bl_divisor;
+ bl++) {
+ set_rdqs(ch, rk, bl, ddr_rdqs[PLATFORM_ID]);
+ }
+ }
+ }
+ }
+ }
+#else
+ /* initialize x/y_coordinate arrays */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ for (bl = 0;
+ bl < NUM_BYTE_LANES / bl_divisor;
+ bl++) {
+ /* x_coordinate */
+ x_coordinate[L][B][ch][rk][bl] = RDQS_MIN;
+ x_coordinate[R][B][ch][rk][bl] = RDQS_MAX;
+ x_coordinate[L][T][ch][rk][bl] = RDQS_MIN;
+ x_coordinate[R][T][ch][rk][bl] = RDQS_MAX;
+ /* y_coordinate */
+ y_coordinate[L][B][ch][bl] = VREF_MIN;
+ y_coordinate[R][B][ch][bl] = VREF_MIN;
+ y_coordinate[L][T][ch][bl] = VREF_MAX;
+ y_coordinate[R][T][ch][bl] = VREF_MAX;
+ }
+ }
+ }
+ }
+ }
+
+ /* initialize other variables */
+ bl_mask = byte_lane_mask(mrc_params);
+ address = get_addr(0, 0);
+
+#ifdef R2R_SHARING
+ /* need to set "final_delay[][]" elements to "0" */
+ memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+ /* look for passing coordinates */
+ for (side_y = B; side_y <= T; side_y++) {
+ for (side_x = L; side_x <= R; side_x++) {
+ mrc_post_code(0x07, 0x10 + side_y * 2 + side_x);
+
+ /* find passing values */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (0x1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables &
+ (0x1 << rk)) {
+ /* set x/y_coordinate search starting settings */
+ for (bl = 0;
+ bl < NUM_BYTE_LANES / bl_divisor;
+ bl++) {
+ set_rdqs(ch, rk, bl,
+ x_coordinate[side_x][side_y][ch][rk][bl]);
+ set_vref(ch, bl,
+ y_coordinate[side_x][side_y][ch][bl]);
+ }
+
+ /* get an address in the target channel/rank */
+ address = get_addr(ch, rk);
+
+ /* request HTE reconfiguration */
+ mrc_params->hte_setup = 1;
+
+ /* test the settings */
+ do {
+ /* result[07:00] == failing byte lane (MAX 8) */
+ result = check_bls_ex(mrc_params, address);
+
+ /* check for failures */
+ if (result & 0xff) {
+ /* at least 1 byte lane failed */
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ if (result &
+ (bl_mask << bl)) {
+ /* adjust the RDQS values accordingly */
+ if (side_x == L)
+ x_coordinate[L][side_y][ch][rk][bl] += RDQS_STEP;
+ else
+ x_coordinate[R][side_y][ch][rk][bl] -= RDQS_STEP;
+
+ /* check that we haven't closed the RDQS_EYE too much */
+ if ((x_coordinate[L][side_y][ch][rk][bl] > (RDQS_MAX - MIN_RDQS_EYE)) ||
+ (x_coordinate[R][side_y][ch][rk][bl] < (RDQS_MIN + MIN_RDQS_EYE)) ||
+ (x_coordinate[L][side_y][ch][rk][bl] ==
+ x_coordinate[R][side_y][ch][rk][bl])) {
+ /*
+ * not enough RDQS margin available at this VREF
+ * update VREF values accordingly
+ */
+ if (side_y == B)
+ y_coordinate[side_x][B][ch][bl] += VREF_STEP;
+ else
+ y_coordinate[side_x][T][ch][bl] -= VREF_STEP;
+
+ /* check that we haven't closed the VREF_EYE too much */
+ if ((y_coordinate[side_x][B][ch][bl] > (VREF_MAX - MIN_VREF_EYE)) ||
+ (y_coordinate[side_x][T][ch][bl] < (VREF_MIN + MIN_VREF_EYE)) ||
+ (y_coordinate[side_x][B][ch][bl] == y_coordinate[side_x][T][ch][bl])) {
+ /* VREF_EYE collapsed below MIN_VREF_EYE */
+ training_message(ch, rk, bl);
+ mrc_post_code(0xEE, 0x70 + side_y * 2 + side_x);
+ } else {
+ /* update the VREF setting */
+ set_vref(ch, bl, y_coordinate[side_x][side_y][ch][bl]);
+ /* reset the X coordinate to begin the search at the new VREF */
+ x_coordinate[side_x][side_y][ch][rk][bl] =
+ (side_x == L) ? RDQS_MIN : RDQS_MAX;
+ }
+ }
+
+ /* update the RDQS setting */
+ set_rdqs(ch, rk, bl, x_coordinate[side_x][side_y][ch][rk][bl]);
+ }
+ }
+ }
+ } while (result & 0xff);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mrc_post_code(0x07, 0x20);
+
+ /* find final RDQS (X coordinate) & final VREF (Y coordinate) */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ uint32_t temp1;
+ uint32_t temp2;
+
+ /* x_coordinate */
+ DPF(D_INFO,
+ "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n",
+ rk, bl,
+ x_coordinate[L][T][ch][rk][bl],
+ x_coordinate[R][T][ch][rk][bl],
+ x_coordinate[L][B][ch][rk][bl],
+ x_coordinate[R][B][ch][rk][bl]);
+
+ /* average the TOP side LEFT & RIGHT values */
+ temp1 = (x_coordinate[R][T][ch][rk][bl] + x_coordinate[L][T][ch][rk][bl]) / 2;
+ /* average the BOTTOM side LEFT & RIGHT values */
+ temp2 = (x_coordinate[R][B][ch][rk][bl] + x_coordinate[L][B][ch][rk][bl]) / 2;
+ /* average the above averages */
+ x_center[ch][rk][bl] = (uint8_t) ((temp1 + temp2) / 2);
+
+ /* y_coordinate */
+ DPF(D_INFO,
+ "VREF R/L eye lane%d : %d-%d %d-%d\n",
+ bl,
+ y_coordinate[R][B][ch][bl],
+ y_coordinate[R][T][ch][bl],
+ y_coordinate[L][B][ch][bl],
+ y_coordinate[L][T][ch][bl]);
+
+ /* average the RIGHT side TOP & BOTTOM values */
+ temp1 = (y_coordinate[R][T][ch][bl] + y_coordinate[R][B][ch][bl]) / 2;
+ /* average the LEFT side TOP & BOTTOM values */
+ temp2 = (y_coordinate[L][T][ch][bl] + y_coordinate[L][B][ch][bl]) / 2;
+ /* average the above averages */
+ y_center[ch][bl] = (uint8_t) ((temp1 + temp2) / 2);
+ }
+ }
+ }
+ }
+ }
+
+#ifdef RX_EYE_CHECK
+ /* perform an eye check */
+ for (side_y = B; side_y <= T; side_y++) {
+ for (side_x = L; side_x <= R; side_x++) {
+ mrc_post_code(0x07, 0x30 + side_y * 2 + side_x);
+
+ /* update the settings for the eye check */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ if (side_x == L)
+ set_rdqs(ch, rk, bl, x_center[ch][rk][bl] - (MIN_RDQS_EYE / 2));
+ else
+ set_rdqs(ch, rk, bl, x_center[ch][rk][bl] + (MIN_RDQS_EYE / 2));
+
+ if (side_y == B)
+ set_vref(ch, bl, y_center[ch][bl] - (MIN_VREF_EYE / 2));
+ else
+ set_vref(ch, bl, y_center[ch][bl] + (MIN_VREF_EYE / 2));
+ }
+ }
+ }
+ }
+ }
+
+ /* request HTE reconfiguration */
+ mrc_params->hte_setup = 1;
+
+ /* check the eye */
+ if (check_bls_ex(mrc_params, address) & 0xff) {
+ /* one or more byte lanes failed */
+ mrc_post_code(0xee, 0x74 + side_x * 2 + side_y);
+ }
+ }
+ }
+#endif
+
+ mrc_post_code(0x07, 0x40);
+
+ /* set final placements */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+#ifdef R2R_SHARING
+ /* increment "num_ranks_enabled" */
+ num_ranks_enabled++;
+#endif
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+ /* x_coordinate */
+#ifdef R2R_SHARING
+ final_delay[ch][bl] += x_center[ch][rk][bl];
+ set_rdqs(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
+#else
+ set_rdqs(ch, rk, bl, x_center[ch][rk][bl]);
+#endif
+ /* y_coordinate */
+ set_vref(ch, bl, y_center[ch][bl]);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ LEAVEFN();
+}
+
+/*
+ * This function will perform the WRITE TRAINING Algorithm on all
+ * channels/ranks/byte_lanes simultaneously to minimize execution time.
+ *
+ * The idea here is to train the WDQ timings to achieve maximum WRITE margins.
+ * The algorithm will start with WDQ at the current WDQ setting (tracks WDQS
+ * in WR_LVL) +/- 32 PIs (+/- 1/4 CLK) and collapse the eye until all data
+ * patterns pass. This is because WDQS will be aligned to WCLK by the
+ * Write Leveling algorithm and WDQ will only ever have a 1/2 CLK window
+ * of validity.
+ */
+void wr_train(struct mrc_params *mrc_params)
+{
+ uint8_t ch; /* channel counter */
+ uint8_t rk; /* rank counter */
+ uint8_t bl; /* byte lane counter */
+ uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+#ifdef BACKUP_WDQ
+#else
+ uint8_t side; /* LEFT/RIGHT side indicator (0=L, 1=R) */
+ uint32_t temp; /* temporary DWORD */
+ /* 2 arrays, for L & R side passing delays */
+ uint32_t delay[2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t address; /* target address for check_bls_ex() */
+ uint32_t result; /* result of check_bls_ex() */
+ uint32_t bl_mask; /* byte lane mask for result checking */
+#ifdef R2R_SHARING
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+ /* used to find placement for rank2rank sharing configs */
+ uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+ /* wr_train starts */
+ mrc_post_code(0x08, 0x00);
+
+ ENTERFN();
+
+#ifdef BACKUP_WDQ
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ for (bl = 0;
+ bl < NUM_BYTE_LANES / bl_divisor;
+ bl++) {
+ set_wdq(ch, rk, bl, ddr_wdq[PLATFORM_ID]);
+ }
+ }
+ }
+ }
+ }
+#else
+ /* initialize "delay" */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+ for (bl = 0;
+ bl < NUM_BYTE_LANES / bl_divisor;
+ bl++) {
+ /*
+ * want to start with
+ * WDQ = (WDQS - QRTR_CLK)
+ * +/- QRTR_CLK
+ */
+ temp = get_wdqs(ch, rk, bl) - QRTR_CLK;
+ delay[L][ch][rk][bl] = temp - QRTR_CLK;
+ delay[R][ch][rk][bl] = temp + QRTR_CLK;
+ }
+ }
+ }
+ }
+ }
+
+ /* initialize other variables */
+ bl_mask = byte_lane_mask(mrc_params);
+ address = get_addr(0, 0);
+
+#ifdef R2R_SHARING
+ /* need to set "final_delay[][]" elements to "0" */
+ memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+ /*
+ * start algorithm on the LEFT side and train each channel/bl
+ * until no failures are observed, then repeat for the RIGHT side.
+ */
+ for (side = L; side <= R; side++) {
+ mrc_post_code(0x08, 0x10 + side);
+
+ /* set starting values */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables &
+ (1 << rk)) {
+ for (bl = 0;
+ bl < NUM_BYTE_LANES / bl_divisor;
+ bl++) {
+ set_wdq(ch, rk, bl, delay[side][ch][rk][bl]);
+ }
+ }
+ }
+ }
+ }
+
+ /* find passing values */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables &
+ (1 << rk)) {
+ /* get an address in the target channel/rank */
+ address = get_addr(ch, rk);
+
+ /* request HTE reconfiguration */
+ mrc_params->hte_setup = 1;
+
+ /* check the settings */
+ do {
+ /* result[07:00] == failing byte lane (MAX 8) */
+ result = check_bls_ex(mrc_params, address);
+ /* check for failures */
+ if (result & 0xff) {
+ /* at least 1 byte lane failed */
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ if (result &
+ (bl_mask << bl)) {
+ if (side == L)
+ delay[L][ch][rk][bl] += WDQ_STEP;
+ else
+ delay[R][ch][rk][bl] -= WDQ_STEP;
+
+ /* check for algorithm failure */
+ if (delay[L][ch][rk][bl] != delay[R][ch][rk][bl]) {
+ /*
+ * margin available
+ * update delay setting
+ */
+ set_wdq(ch, rk, bl,
+ delay[side][ch][rk][bl]);
+ } else {
+ /*
+ * no margin available
+ * notify the user and halt
+ */
+ training_message(ch, rk, bl);
+ mrc_post_code(0xee, 0x80 + side);
+ }
+ }
+ }
+ }
+ /* stop when all byte lanes pass */
+ } while (result & 0xff);
+ }
+ }
+ }
+ }
+ }
+
+ /* program WDQ to the middle of passing window */
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ if (mrc_params->channel_enables & (1 << ch)) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ if (mrc_params->rank_enables & (1 << rk)) {
+#ifdef R2R_SHARING
+ /* increment "num_ranks_enabled" */
+ num_ranks_enabled++;
+#endif
+ for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
+ DPF(D_INFO,
+ "WDQ eye rank%d lane%d : %d-%d\n",
+ rk, bl,
+ delay[L][ch][rk][bl],
+ delay[R][ch][rk][bl]);
+
+ temp = (delay[R][ch][rk][bl] + delay[L][ch][rk][bl]) / 2;
+
+#ifdef R2R_SHARING
+ final_delay[ch][bl] += temp;
+ set_wdq(ch, rk, bl,
+ final_delay[ch][bl] / num_ranks_enabled);
+#else
+ set_wdq(ch, rk, bl, temp);
+#endif
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ LEAVEFN();
+}
+
+/*
+ * This function will store relevant timing data
+ *
+ * This data will be used on subsequent boots to speed up boot times
+ * and is required for Suspend To RAM capabilities.
+ */
+void store_timings(struct mrc_params *mrc_params)
+{
+ uint8_t ch, rk, bl;
+ struct mrc_timings *mt = &mrc_params->timings;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++) {
+ for (rk = 0; rk < NUM_RANKS; rk++) {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+ mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl);
+ mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl);
+ mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl);
+ mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl);
+
+ if (rk == 0)
+ mt->vref[ch][bl] = get_vref(ch, bl);
+ }
+
+ mt->wctl[ch][rk] = get_wctl(ch, rk);
+ }
+
+ mt->wcmd[ch] = get_wcmd(ch);
+ }
+
+ /* need to save for a case of changing frequency after warm reset */
+ mt->ddr_speed = mrc_params->ddr_speed;
+}
+
+/*
+ * The purpose of this function is to ensure the SEC comes out of reset
+ * and IA initiates the SEC enabling Memory Scrambling.
+ */
+void enable_scrambling(struct mrc_params *mrc_params)
+{
+ uint32_t lfsr = 0;
+ uint8_t i;
+
+ if (mrc_params->scrambling_enables == 0)
+ return;
+
+ ENTERFN();
+
+ /* 32 bit seed is always stored in BIOS NVM */
+ lfsr = mrc_params->timings.scrambler_seed;
+
+ if (mrc_params->boot_mode == BM_COLD) {
+ /*
+ * factory value is 0 and in first boot,
+ * a clock based seed is loaded.
+ */
+ if (lfsr == 0) {
+ /*
+ * get seed from system clock
+ * and make sure it is not all 1's
+ */
+ lfsr = rdtsc() & 0x0fffffff;
+ } else {
+ /*
+ * Need to replace scrambler
+ *
+ * get next 32bit LFSR 16 times which is the last
+ * part of the previous scrambler vector
+ */
+ for (i = 0; i < 16; i++)
+ lfsr32(&lfsr);
+ }
+
+ /* save new seed */
+ mrc_params->timings.scrambler_seed = lfsr;
+ }
+
+ /*
+ * In warm boot or S3 exit, we have the previous seed.
+ * In cold boot, we have the last 32bit LFSR which is the new seed.
+ */
+ lfsr32(&lfsr); /* shift to next value */
+ msg_port_write(MEM_CTLR, SCRMSEED, (lfsr & 0x0003ffff));
+
+ for (i = 0; i < 2; i++)
+ msg_port_write(MEM_CTLR, SCRMLO + i, (lfsr & 0xaaaaaaaa));
+
+ LEAVEFN();
+}
+
+/*
+ * Configure MCU Power Management Control Register
+ * and Scheduler Control Register
+ */
+void prog_ddr_control(struct mrc_params *mrc_params)
+{
+ u32 dsch;
+ u32 dpmc0;
+
+ ENTERFN();
+
+ dsch = msg_port_read(MEM_CTLR, DSCH);
+ dsch &= ~(DSCH_OOODIS | DSCH_OOOST3DIS | DSCH_NEWBYPDIS);
+ msg_port_write(MEM_CTLR, DSCH, dsch);
+
+ dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+ dpmc0 &= ~DPMC0_DISPWRDN;
+ dpmc0 |= (mrc_params->power_down_disable << 25);
+ dpmc0 &= ~DPMC0_CLKGTDIS;
+ dpmc0 &= ~DPMC0_PCLSTO_MASK;
+ dpmc0 |= (4 << 16);
+ dpmc0 |= DPMC0_PREAPWDEN;
+ msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+ /* CMDTRIST = 2h - CMD/ADDR are tristated when no valid command */
+ mrc_write_mask(MEM_CTLR, DPMC1, 0x20, 0x30);
+
+ LEAVEFN();
+}
+
+/*
+ * After training complete configure MCU Rank Population Register
+ * specifying: ranks enabled, device width, density, address mode
+ */
+void prog_dra_drb(struct mrc_params *mrc_params)
+{
+ u32 drp;
+ u32 dco;
+ u8 density = mrc_params->params.density;
+
+ ENTERFN();
+
+ dco = msg_port_read(MEM_CTLR, DCO);
+ dco &= ~DCO_IC;
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ drp = 0;
+ if (mrc_params->rank_enables & 1)
+ drp |= DRP_RKEN0;
+ if (mrc_params->rank_enables & 2)
+ drp |= DRP_RKEN1;
+ if (mrc_params->dram_width == X16) {
+ drp |= (1 << 4);
+ drp |= (1 << 9);
+ }
+
+ /*
+ * Density encoding in struct dram_params: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
+ * has to be mapped RANKDENSx encoding (0=1Gb)
+ */
+ if (density == 0)
+ density = 4;
+
+ drp |= ((density - 1) << 6);
+ drp |= ((density - 1) << 11);
+
+ /* Address mode can be overwritten if ECC enabled */
+ drp |= (mrc_params->address_mode << 14);
+
+ msg_port_write(MEM_CTLR, DRP, drp);
+
+ dco &= ~DCO_PMICTL;
+ dco |= DCO_IC;
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ LEAVEFN();
+}
+
+/* Send DRAM wake command */
+void perform_wake(struct mrc_params *mrc_params)
+{
+ ENTERFN();
+
+ dram_wake_command();
+
+ LEAVEFN();
+}
+
+/*
+ * Configure refresh rate and short ZQ calibration interval
+ * Activate dynamic self refresh
+ */
+void change_refresh_period(struct mrc_params *mrc_params)
+{
+ u32 drfc;
+ u32 dcal;
+ u32 dpmc0;
+
+ ENTERFN();
+
+ drfc = msg_port_read(MEM_CTLR, DRFC);
+ drfc &= ~DRFC_TREFI_MASK;
+ drfc |= (mrc_params->refresh_rate << 12);
+ drfc |= DRFC_REFDBTCLR;
+ msg_port_write(MEM_CTLR, DRFC, drfc);
+
+ dcal = msg_port_read(MEM_CTLR, DCAL);
+ dcal &= ~DCAL_ZQCINT_MASK;
+ dcal |= (3 << 8); /* 63ms */
+ msg_port_write(MEM_CTLR, DCAL, dcal);
+
+ dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+ dpmc0 |= (DPMC0_DYNSREN | DPMC0_ENPHYCLKGATE);
+ msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+ LEAVEFN();
+}
+
+/*
+ * Configure DDRPHY for Auto-Refresh, Periodic Compensations,
+ * Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
+ */
+void set_auto_refresh(struct mrc_params *mrc_params)
+{
+ uint32_t channel;
+ uint32_t rank;
+ uint32_t bl;
+ uint32_t bl_divisor = 1;
+ uint32_t temp;
+
+ ENTERFN();
+
+ /*
+ * Enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp,
+ * ZQSPERIOD, Auto-Precharge, CKE Power-Down
+ */
+ for (channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (mrc_params->channel_enables & (1 << channel)) {
+ /* Enable Periodic RCOMPS */
+ mrc_alt_write_mask(DDRPHY, CMPCTRL, 2, 2);
+
+ /* Enable Dynamic DiffAmp & Set Read ODT Value */
+ switch (mrc_params->rd_odt_value) {
+ case 0:
+ temp = 0x3f; /* OFF */
+ break;
+ default:
+ temp = 0x00; /* Auto */
+ break;
+ }
+
+ for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
+ /* Override: DIFFAMP, ODT */
+ mrc_alt_write_mask(DDRPHY,
+ B0OVRCTL + bl * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET,
+ temp << 10,
+ 0x003ffc00);
+
+ /* Override: DIFFAMP, ODT */
+ mrc_alt_write_mask(DDRPHY,
+ B1OVRCTL + bl * DDRIODQ_BL_OFFSET +
+ channel * DDRIODQ_CH_OFFSET,
+ temp << 10,
+ 0x003ffc00);
+ }
+
+ /* Issue ZQCS command */
+ for (rank = 0; rank < NUM_RANKS; rank++) {
+ if (mrc_params->rank_enables & (1 << rank))
+ dram_init_command(DCMD_ZQCS(rank));
+ }
+ }
+ }
+
+ clear_pointers();
+
+ LEAVEFN();
+}
+
+/*
+ * Depending on configuration enables ECC support
+ *
+ * Available memory size is decreased, and updated with 0s
+ * in order to clear error status. Address mode 2 forced.
+ */
+void ecc_enable(struct mrc_params *mrc_params)
+{
+ u32 drp;
+ u32 dsch;
+ u32 ecc_ctrl;
+
+ if (mrc_params->ecc_enables == 0)
+ return;
+
+ ENTERFN();
+
+ /* Configuration required in ECC mode */
+ drp = msg_port_read(MEM_CTLR, DRP);
+ drp &= ~DRP_ADDRMAP_MASK;
+ drp |= DRP_ADDRMAP_MAP1;
+ drp |= DRP_PRI64BSPLITEN;
+ msg_port_write(MEM_CTLR, DRP, drp);
+
+ /* Disable new request bypass */
+ dsch = msg_port_read(MEM_CTLR, DSCH);
+ dsch |= DSCH_NEWBYPDIS;
+ msg_port_write(MEM_CTLR, DSCH, dsch);
+
+ /* Enable ECC */
+ ecc_ctrl = (DECCCTRL_SBEEN | DECCCTRL_DBEEN | DECCCTRL_ENCBGEN);
+ msg_port_write(MEM_CTLR, DECCCTRL, ecc_ctrl);
+
+ /* Assume 8 bank memory, one bank is gone for ECC */
+ mrc_params->mem_size -= mrc_params->mem_size / 8;
+
+ /* For S3 resume memory content has to be preserved */
+ if (mrc_params->boot_mode != BM_S3) {
+ select_hte();
+ hte_mem_init(mrc_params, MRC_MEM_INIT);
+ select_mem_mgr();
+ }
+
+ LEAVEFN();
+}
+
+/*
+ * Execute memory test
+ * if error detected it is indicated in mrc_params->status
+ */
+void memory_test(struct mrc_params *mrc_params)
+{
+ uint32_t result = 0;
+
+ ENTERFN();
+
+ select_hte();
+ result = hte_mem_init(mrc_params, MRC_MEM_TEST);
+ select_mem_mgr();
+
+ DPF(D_INFO, "Memory test result %x\n", result);
+ mrc_params->status = ((result == 0) ? MRC_SUCCESS : MRC_E_MEMTEST);
+ LEAVEFN();
+}
+
+/* Lock MCU registers at the end of initialization sequence */
+void lock_registers(struct mrc_params *mrc_params)
+{
+ u32 dco;
+
+ ENTERFN();
+
+ dco = msg_port_read(MEM_CTLR, DCO);
+ dco &= ~(DCO_PMICTL | DCO_PMIDIS);
+ dco |= (DCO_DRPLOCK | DCO_CPGCLOCK);
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ LEAVEFN();
+}
diff --git a/roms/u-boot/arch/x86/cpu/quark/smc.h b/roms/u-boot/arch/x86/cpu/quark/smc.h
new file mode 100644
index 000000000..eee27564c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/quark/smc.h
@@ -0,0 +1,532 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ */
+
+#ifndef _SMC_H_
+#define _SMC_H_
+
+/* System Memory Controller Register Defines */
+
+/* Memory Controller Message Bus Registers Offsets */
+#define DRP 0x00
+#define DTR0 0x01
+#define DTR1 0x02
+#define DTR2 0x03
+#define DTR3 0x04
+#define DTR4 0x05
+#define DPMC0 0x06
+#define DPMC1 0x07
+#define DRFC 0x08
+#define DSCH 0x09
+#define DCAL 0x0a
+#define DRMC 0x0b
+#define PMSTS 0x0c
+#define DCO 0x0f
+#define DSTAT 0x20
+#define SSKPD0 0x4a
+#define SSKPD1 0x4b
+#define DECCCTRL 0x60
+#define DECCSTAT 0x61
+#define DECCSBECNT 0x62
+#define DECCSBECA 0x68
+#define DECCSBECS 0x69
+#define DECCDBECA 0x6a
+#define DECCDBECS 0x6b
+#define DFUSESTAT 0x70
+#define SCRMSEED 0x80
+#define SCRMLO 0x81
+#define SCRMHI 0x82
+
+/* DRP register defines */
+#define DRP_RKEN0 (1 << 0)
+#define DRP_RKEN1 (1 << 1)
+#define DRP_PRI64BSPLITEN (1 << 13)
+#define DRP_ADDRMAP_MAP0 (1 << 14)
+#define DRP_ADDRMAP_MAP1 (1 << 15)
+#define DRP_ADDRMAP_MASK 0x0000c000
+
+/* DTR0 register defines */
+#define DTR0_DFREQ_MASK 0x00000003
+#define DTR0_TRP_MASK 0x000000f0
+#define DTR0_TRCD_MASK 0x00000f00
+#define DTR0_TCL_MASK 0x00007000
+
+/* DTR1 register defines */
+#define DTR1_TWCL_MASK 0x00000007
+#define DTR1_TCMD_MASK 0x00000030
+#define DTR1_TWTP_MASK 0x00000f00
+#define DTR1_TCCD_12CLK (1 << 12)
+#define DTR1_TCCD_18CLK (1 << 13)
+#define DTR1_TCCD_MASK 0x00003000
+#define DTR1_TFAW_MASK 0x000f0000
+#define DTR1_TRAS_MASK 0x00f00000
+#define DTR1_TRRD_MASK 0x03000000
+#define DTR1_TRTP_MASK 0x70000000
+
+/* DTR2 register defines */
+#define DTR2_TRRDR_MASK 0x00000007
+#define DTR2_TWWDR_MASK 0x00000700
+#define DTR2_TRWDR_MASK 0x000f0000
+
+/* DTR3 register defines */
+#define DTR3_TWRDR_MASK 0x00000007
+#define DTR3_TXXXX_MASK 0x00000070
+#define DTR3_TRWSR_MASK 0x00000f00
+#define DTR3_TWRSR_MASK 0x0001e000
+#define DTR3_TXP_MASK 0x00c00000
+
+/* DTR4 register defines */
+#define DTR4_WRODTSTRT_MASK 0x00000003
+#define DTR4_WRODTSTOP_MASK 0x00000070
+#define DTR4_XXXX1_MASK 0x00000700
+#define DTR4_XXXX2_MASK 0x00007000
+#define DTR4_ODTDIS (1 << 15)
+#define DTR4_TRGSTRDIS (1 << 16)
+
+/* DPMC0 register defines */
+#define DPMC0_PCLSTO_MASK 0x00070000
+#define DPMC0_PREAPWDEN (1 << 21)
+#define DPMC0_DYNSREN (1 << 23)
+#define DPMC0_CLKGTDIS (1 << 24)
+#define DPMC0_DISPWRDN (1 << 25)
+#define DPMC0_ENPHYCLKGATE (1 << 29)
+
+/* DRFC register defines */
+#define DRFC_TREFI_MASK 0x00007000
+#define DRFC_REFDBTCLR (1 << 21)
+
+/* DSCH register defines */
+#define DSCH_OOODIS (1 << 8)
+#define DSCH_OOOST3DIS (1 << 9)
+#define DSCH_NEWBYPDIS (1 << 12)
+
+/* DCAL register defines */
+#define DCAL_ZQCINT_MASK 0x00000700
+#define DCAL_SRXZQCL_MASK 0x00003000
+
+/* DRMC register defines */
+#define DRMC_CKEMODE (1 << 4)
+#define DRMC_ODTMODE (1 << 12)
+#define DRMC_COLDWAKE (1 << 16)
+
+/* PMSTS register defines */
+#define PMSTS_DISR (1 << 0)
+
+/* DCO register defines */
+#define DCO_DRPLOCK (1 << 0)
+#define DCO_CPGCLOCK (1 << 8)
+#define DCO_PMICTL (1 << 28)
+#define DCO_PMIDIS (1 << 29)
+#define DCO_IC (1 << 31)
+
+/* DECCCTRL register defines */
+#define DECCCTRL_SBEEN (1 << 0)
+#define DECCCTRL_DBEEN (1 << 1)
+#define DECCCTRL_ENCBGEN (1 << 17)
+
+/* DRAM init command */
+#define DCMD_MRS1(rnk, dat) (0 | ((rnk) << 22) | (1 << 3) | ((dat) << 6))
+#define DCMD_REF(rnk) (1 | ((rnk) << 22))
+#define DCMD_PRE(rnk) (2 | ((rnk) << 22))
+#define DCMD_PREA(rnk) (2 | ((rnk) << 22) | (0x400 << 6))
+#define DCMD_ACT(rnk, row) (3 | ((rnk) << 22) | ((row) << 6))
+#define DCMD_WR(rnk, col) (4 | ((rnk) << 22) | ((col) << 6))
+#define DCMD_RD(rnk, col) (5 | ((rnk) << 22) | ((col) << 6))
+#define DCMD_ZQCS(rnk) (6 | ((rnk) << 22))
+#define DCMD_ZQCL(rnk) (6 | ((rnk) << 22) | (0x400 << 6))
+#define DCMD_NOP(rnk) (7 | ((rnk) << 22))
+
+#define DDR3_EMRS1_DIC_40 0
+#define DDR3_EMRS1_DIC_34 1
+
+#define DDR3_EMRS1_RTTNOM_0 0
+#define DDR3_EMRS1_RTTNOM_60 0x04
+#define DDR3_EMRS1_RTTNOM_120 0x40
+#define DDR3_EMRS1_RTTNOM_40 0x44
+#define DDR3_EMRS1_RTTNOM_20 0x200
+#define DDR3_EMRS1_RTTNOM_30 0x204
+
+#define DDR3_EMRS2_RTTWR_60 (1 << 9)
+#define DDR3_EMRS2_RTTWR_120 (1 << 10)
+
+/* BEGIN DDRIO Registers */
+
+/* DDR IOs & COMPs */
+#define DDRIODQ_BL_OFFSET 0x0800
+#define DDRIODQ_CH_OFFSET ((NUM_BYTE_LANES / 2) * DDRIODQ_BL_OFFSET)
+#define DDRIOCCC_CH_OFFSET 0x0800
+#define DDRCOMP_CH_OFFSET 0x0100
+
+/* CH0-BL01-DQ */
+#define DQOBSCKEBBCTL 0x0000
+#define DQDLLTXCTL 0x0004
+#define DQDLLRXCTL 0x0008
+#define DQMDLLCTL 0x000c
+#define B0RXIOBUFCTL 0x0010
+#define B0VREFCTL 0x0014
+#define B0RXOFFSET1 0x0018
+#define B0RXOFFSET0 0x001c
+#define B1RXIOBUFCTL 0x0020
+#define B1VREFCTL 0x0024
+#define B1RXOFFSET1 0x0028
+#define B1RXOFFSET0 0x002c
+#define DQDFTCTL 0x0030
+#define DQTRAINSTS 0x0034
+#define B1DLLPICODER0 0x0038
+#define B0DLLPICODER0 0x003c
+#define B1DLLPICODER1 0x0040
+#define B0DLLPICODER1 0x0044
+#define B1DLLPICODER2 0x0048
+#define B0DLLPICODER2 0x004c
+#define B1DLLPICODER3 0x0050
+#define B0DLLPICODER3 0x0054
+#define B1RXDQSPICODE 0x0058
+#define B0RXDQSPICODE 0x005c
+#define B1RXDQPICODER32 0x0060
+#define B1RXDQPICODER10 0x0064
+#define B0RXDQPICODER32 0x0068
+#define B0RXDQPICODER10 0x006c
+#define B01PTRCTL0 0x0070
+#define B01PTRCTL1 0x0074
+#define B01DBCTL0 0x0078
+#define B01DBCTL1 0x007c
+#define B0LATCTL0 0x0080
+#define B1LATCTL0 0x0084
+#define B01LATCTL1 0x0088
+#define B0ONDURCTL 0x008c
+#define B1ONDURCTL 0x0090
+#define B0OVRCTL 0x0094
+#define B1OVRCTL 0x0098
+#define DQCTL 0x009c
+#define B0RK2RKCHGPTRCTRL 0x00a0
+#define B1RK2RKCHGPTRCTRL 0x00a4
+#define DQRK2RKCTL 0x00a8
+#define DQRK2RKPTRCTL 0x00ac
+#define B0RK2RKLAT 0x00b0
+#define B1RK2RKLAT 0x00b4
+#define DQCLKALIGNREG0 0x00b8
+#define DQCLKALIGNREG1 0x00bc
+#define DQCLKALIGNREG2 0x00c0
+#define DQCLKALIGNSTS0 0x00c4
+#define DQCLKALIGNSTS1 0x00c8
+#define DQCLKGATE 0x00cc
+#define B0COMPSLV1 0x00d0
+#define B1COMPSLV1 0x00d4
+#define B0COMPSLV2 0x00d8
+#define B1COMPSLV2 0x00dc
+#define B0COMPSLV3 0x00e0
+#define B1COMPSLV3 0x00e4
+#define DQVISALANECR0TOP 0x00e8
+#define DQVISALANECR1TOP 0x00ec
+#define DQVISACONTROLCRTOP 0x00f0
+#define DQVISALANECR0BL 0x00f4
+#define DQVISALANECR1BL 0x00f8
+#define DQVISACONTROLCRBL 0x00fc
+#define DQTIMINGCTRL 0x010c
+
+/* CH0-ECC */
+#define ECCDLLTXCTL 0x2004
+#define ECCDLLRXCTL 0x2008
+#define ECCMDLLCTL 0x200c
+#define ECCB1DLLPICODER0 0x2038
+#define ECCB1DLLPICODER1 0x2040
+#define ECCB1DLLPICODER2 0x2048
+#define ECCB1DLLPICODER3 0x2050
+#define ECCB01DBCTL0 0x2078
+#define ECCB01DBCTL1 0x207c
+#define ECCCLKALIGNREG0 0x20b8
+#define ECCCLKALIGNREG1 0x20bc
+#define ECCCLKALIGNREG2 0x20c0
+
+/* CH0-CMD */
+#define CMDOBSCKEBBCTL 0x4800
+#define CMDDLLTXCTL 0x4808
+#define CMDDLLRXCTL 0x480c
+#define CMDMDLLCTL 0x4810
+#define CMDRCOMPODT 0x4814
+#define CMDDLLPICODER0 0x4820
+#define CMDDLLPICODER1 0x4824
+#define CMDCFGREG0 0x4840
+#define CMDPTRREG 0x4844
+#define CMDCLKALIGNREG0 0x4850
+#define CMDCLKALIGNREG1 0x4854
+#define CMDCLKALIGNREG2 0x4858
+#define CMDPMCONFIG0 0x485c
+#define CMDPMDLYREG0 0x4860
+#define CMDPMDLYREG1 0x4864
+#define CMDPMDLYREG2 0x4868
+#define CMDPMDLYREG3 0x486c
+#define CMDPMDLYREG4 0x4870
+#define CMDCLKALIGNSTS0 0x4874
+#define CMDCLKALIGNSTS1 0x4878
+#define CMDPMSTS0 0x487c
+#define CMDPMSTS1 0x4880
+#define CMDCOMPSLV 0x4884
+#define CMDBONUS0 0x488c
+#define CMDBONUS1 0x4890
+#define CMDVISALANECR0 0x4894
+#define CMDVISALANECR1 0x4898
+#define CMDVISACONTROLCR 0x489c
+#define CMDCLKGATE 0x48a0
+#define CMDTIMINGCTRL 0x48a4
+
+/* CH0-CLK-CTL */
+#define CCOBSCKEBBCTL 0x5800
+#define CCRCOMPIO 0x5804
+#define CCDLLTXCTL 0x5808
+#define CCDLLRXCTL 0x580c
+#define CCMDLLCTL 0x5810
+#define CCRCOMPODT 0x5814
+#define CCDLLPICODER0 0x5820
+#define CCDLLPICODER1 0x5824
+#define CCDDR3RESETCTL 0x5830
+#define CCCFGREG0 0x5838
+#define CCCFGREG1 0x5840
+#define CCPTRREG 0x5844
+#define CCCLKALIGNREG0 0x5850
+#define CCCLKALIGNREG1 0x5854
+#define CCCLKALIGNREG2 0x5858
+#define CCPMCONFIG0 0x585c
+#define CCPMDLYREG0 0x5860
+#define CCPMDLYREG1 0x5864
+#define CCPMDLYREG2 0x5868
+#define CCPMDLYREG3 0x586c
+#define CCPMDLYREG4 0x5870
+#define CCCLKALIGNSTS0 0x5874
+#define CCCLKALIGNSTS1 0x5878
+#define CCPMSTS0 0x587c
+#define CCPMSTS1 0x5880
+#define CCCOMPSLV1 0x5884
+#define CCCOMPSLV2 0x5888
+#define CCCOMPSLV3 0x588c
+#define CCBONUS0 0x5894
+#define CCBONUS1 0x5898
+#define CCVISALANECR0 0x589c
+#define CCVISALANECR1 0x58a0
+#define CCVISACONTROLCR 0x58a4
+#define CCCLKGATE 0x58a8
+#define CCTIMINGCTL 0x58ac
+
+/* COMP */
+#define CMPCTRL 0x6800
+#define SOFTRSTCNTL 0x6804
+#define MSCNTR 0x6808
+#define NMSCNTRL 0x680c
+#define LATCH1CTL 0x6814
+#define COMPVISALANECR0 0x681c
+#define COMPVISALANECR1 0x6820
+#define COMPVISACONTROLCR 0x6824
+#define COMPBONUS0 0x6830
+#define TCOCNTCTRL 0x683c
+#define DQANAODTPUCTL 0x6840
+#define DQANAODTPDCTL 0x6844
+#define DQANADRVPUCTL 0x6848
+#define DQANADRVPDCTL 0x684c
+#define DQANADLYPUCTL 0x6850
+#define DQANADLYPDCTL 0x6854
+#define DQANATCOPUCTL 0x6858
+#define DQANATCOPDCTL 0x685c
+#define CMDANADRVPUCTL 0x6868
+#define CMDANADRVPDCTL 0x686c
+#define CMDANADLYPUCTL 0x6870
+#define CMDANADLYPDCTL 0x6874
+#define CLKANAODTPUCTL 0x6880
+#define CLKANAODTPDCTL 0x6884
+#define CLKANADRVPUCTL 0x6888
+#define CLKANADRVPDCTL 0x688c
+#define CLKANADLYPUCTL 0x6890
+#define CLKANADLYPDCTL 0x6894
+#define CLKANATCOPUCTL 0x6898
+#define CLKANATCOPDCTL 0x689c
+#define DQSANAODTPUCTL 0x68a0
+#define DQSANAODTPDCTL 0x68a4
+#define DQSANADRVPUCTL 0x68a8
+#define DQSANADRVPDCTL 0x68ac
+#define DQSANADLYPUCTL 0x68b0
+#define DQSANADLYPDCTL 0x68b4
+#define DQSANATCOPUCTL 0x68b8
+#define DQSANATCOPDCTL 0x68bc
+#define CTLANADRVPUCTL 0x68c8
+#define CTLANADRVPDCTL 0x68cc
+#define CTLANADLYPUCTL 0x68d0
+#define CTLANADLYPDCTL 0x68d4
+#define CHNLBUFSTATIC 0x68f0
+#define COMPOBSCNTRL 0x68f4
+#define COMPBUFFDBG0 0x68f8
+#define COMPBUFFDBG1 0x68fc
+#define CFGMISCCH0 0x6900
+#define COMPEN0CH0 0x6904
+#define COMPEN1CH0 0x6908
+#define COMPEN2CH0 0x690c
+#define STATLEGEN0CH0 0x6910
+#define STATLEGEN1CH0 0x6914
+#define DQVREFCH0 0x6918
+#define CMDVREFCH0 0x691c
+#define CLKVREFCH0 0x6920
+#define DQSVREFCH0 0x6924
+#define CTLVREFCH0 0x6928
+#define TCOVREFCH0 0x692c
+#define DLYSELCH0 0x6930
+#define TCODRAMBUFODTCH0 0x6934
+#define CCBUFODTCH0 0x6938
+#define RXOFFSETCH0 0x693c
+#define DQODTPUCTLCH0 0x6940
+#define DQODTPDCTLCH0 0x6944
+#define DQDRVPUCTLCH0 0x6948
+#define DQDRVPDCTLCH0 0x694c
+#define DQDLYPUCTLCH0 0x6950
+#define DQDLYPDCTLCH0 0x6954
+#define DQTCOPUCTLCH0 0x6958
+#define DQTCOPDCTLCH0 0x695c
+#define CMDDRVPUCTLCH0 0x6968
+#define CMDDRVPDCTLCH0 0x696c
+#define CMDDLYPUCTLCH0 0x6970
+#define CMDDLYPDCTLCH0 0x6974
+#define CLKODTPUCTLCH0 0x6980
+#define CLKODTPDCTLCH0 0x6984
+#define CLKDRVPUCTLCH0 0x6988
+#define CLKDRVPDCTLCH0 0x698c
+#define CLKDLYPUCTLCH0 0x6990
+#define CLKDLYPDCTLCH0 0x6994
+#define CLKTCOPUCTLCH0 0x6998
+#define CLKTCOPDCTLCH0 0x699c
+#define DQSODTPUCTLCH0 0x69a0
+#define DQSODTPDCTLCH0 0x69a4
+#define DQSDRVPUCTLCH0 0x69a8
+#define DQSDRVPDCTLCH0 0x69ac
+#define DQSDLYPUCTLCH0 0x69b0
+#define DQSDLYPDCTLCH0 0x69b4
+#define DQSTCOPUCTLCH0 0x69b8
+#define DQSTCOPDCTLCH0 0x69bc
+#define CTLDRVPUCTLCH0 0x69c8
+#define CTLDRVPDCTLCH0 0x69cc
+#define CTLDLYPUCTLCH0 0x69d0
+#define CTLDLYPDCTLCH0 0x69d4
+#define FNLUPDTCTLCH0 0x69f0
+
+/* PLL */
+#define MPLLCTRL0 0x7800
+#define MPLLCTRL1 0x7808
+#define MPLLCSR0 0x7810
+#define MPLLCSR1 0x7814
+#define MPLLCSR2 0x7820
+#define MPLLDFT 0x7828
+#define MPLLMON0CTL 0x7830
+#define MPLLMON1CTL 0x7838
+#define MPLLMON2CTL 0x783c
+#define SFRTRIM 0x7850
+#define MPLLDFTOUT0 0x7858
+#define MPLLDFTOUT1 0x785c
+#define MASTERRSTN 0x7880
+#define PLLLOCKDEL 0x7884
+#define SFRDEL 0x7888
+#define CRUVISALANECR0 0x78f0
+#define CRUVISALANECR1 0x78f4
+#define CRUVISACONTROLCR 0x78f8
+#define IOSFVISALANECR0 0x78fc
+#define IOSFVISALANECR1 0x7900
+#define IOSFVISACONTROLCR 0x7904
+
+/* END DDRIO Registers */
+
+/* DRAM Specific Message Bus OpCodes */
+#define MSG_OP_DRAM_INIT 0x68
+#define MSG_OP_DRAM_WAKE 0xca
+
+#define SAMPLE_SIZE 6
+
+/* must be less than this number to enable early deadband */
+#define EARLY_DB 0x12
+/* must be greater than this number to enable late deadband */
+#define LATE_DB 0x34
+
+#define CHX_REGS (11 * 4)
+#define FULL_CLK 128
+#define HALF_CLK 64
+#define QRTR_CLK 32
+
+#define MCEIL(num, den) ((uint8_t)((num + den - 1) / den))
+#define MMAX(a, b) ((a) > (b) ? (a) : (b))
+#define DEAD_LOOP() for (;;);
+
+#define MIN_RDQS_EYE 10 /* in PI Codes */
+#define MIN_VREF_EYE 10 /* in VREF Codes */
+/* how many RDQS codes to jump while margining */
+#define RDQS_STEP 1
+/* how many VREF codes to jump while margining */
+#define VREF_STEP 1
+/* offset into "vref_codes[]" for minimum allowed VREF setting */
+#define VREF_MIN 0x00
+/* offset into "vref_codes[]" for maximum allowed VREF setting */
+#define VREF_MAX 0x3f
+#define RDQS_MIN 0x00 /* minimum RDQS delay value */
+#define RDQS_MAX 0x3f /* maximum RDQS delay value */
+
+/* how many WDQ codes to jump while margining */
+#define WDQ_STEP 1
+
+enum {
+ B, /* BOTTOM VREF */
+ T /* TOP VREF */
+};
+
+enum {
+ L, /* LEFT RDQS */
+ R /* RIGHT RDQS */
+};
+
+/* Memory Options */
+
+/* enable STATIC timing settings for RCVN (BACKUP_MODE) */
+#undef BACKUP_RCVN
+/* enable STATIC timing settings for WDQS (BACKUP_MODE) */
+#undef BACKUP_WDQS
+/* enable STATIC timing settings for RDQS (BACKUP_MODE) */
+#undef BACKUP_RDQS
+/* enable STATIC timing settings for WDQ (BACKUP_MODE) */
+#undef BACKUP_WDQ
+/* enable *COMP overrides (BACKUP_MODE) */
+#undef BACKUP_COMPS
+/* enable the RD_TRAIN eye check */
+#undef RX_EYE_CHECK
+
+/* enable Host to Memory Clock Alignment */
+#define HMC_TEST
+/* enable multi-rank support via rank2rank sharing */
+#define R2R_SHARING
+/* disable signals not used in 16bit mode of DDRIO */
+#define FORCE_16BIT_DDRIO
+
+#define PLATFORM_ID 1
+
+void clear_self_refresh(struct mrc_params *mrc_params);
+void prog_ddr_timing_control(struct mrc_params *mrc_params);
+void prog_decode_before_jedec(struct mrc_params *mrc_params);
+void perform_ddr_reset(struct mrc_params *mrc_params);
+void ddrphy_init(struct mrc_params *mrc_params);
+void perform_jedec_init(struct mrc_params *mrc_params);
+void set_ddr_init_complete(struct mrc_params *mrc_params);
+void restore_timings(struct mrc_params *mrc_params);
+void default_timings(struct mrc_params *mrc_params);
+void rcvn_cal(struct mrc_params *mrc_params);
+void wr_level(struct mrc_params *mrc_params);
+void prog_page_ctrl(struct mrc_params *mrc_params);
+void rd_train(struct mrc_params *mrc_params);
+void wr_train(struct mrc_params *mrc_params);
+void store_timings(struct mrc_params *mrc_params);
+void enable_scrambling(struct mrc_params *mrc_params);
+void prog_ddr_control(struct mrc_params *mrc_params);
+void prog_dra_drb(struct mrc_params *mrc_params);
+void perform_wake(struct mrc_params *mrc_params);
+void change_refresh_period(struct mrc_params *mrc_params);
+void set_auto_refresh(struct mrc_params *mrc_params);
+void ecc_enable(struct mrc_params *mrc_params);
+void memory_test(struct mrc_params *mrc_params);
+void lock_registers(struct mrc_params *mrc_params);
+
+#endif /* _SMC_H_ */
diff --git a/roms/u-boot/arch/x86/cpu/queensbay/Kconfig b/roms/u-boot/arch/x86/cpu/queensbay/Kconfig
new file mode 100644
index 000000000..c9e0fda03
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/queensbay/Kconfig
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+
+config INTEL_QUEENSBAY
+ bool
+ select HAVE_FSP
+ select HAVE_CMC
+ select ARCH_EARLY_INIT_R
+ imply AHCI_PCI
+ imply ICH_SPI
+ imply INTEL_ICH6_GPIO
+ imply MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply PCH_GBE
+ imply SCSI
+ imply SCSI_AHCI
+ imply SPI_FLASH
+ imply SYS_NS16550
+ imply USB
+ imply USB_EHCI_HCD
+ imply VIDEO_VESA
+
+if INTEL_QUEENSBAY
+
+config HAVE_CMC
+ bool "Add a Chipset Micro Code state machine binary"
+ help
+ Select this option to add a Chipset Micro Code state machine binary
+ to the resulting U-Boot image. It is a 64K data block of machine
+ specific code which must be put in the flash for the processor to
+ access when powered up before system BIOS is executed.
+
+config CMC_FILE
+ string "Chipset Micro Code state machine filename"
+ depends on HAVE_CMC
+ default "cmc.bin"
+ help
+ The filename of the file to use as Chipset Micro Code state machine
+ binary in the board directory.
+
+config CMC_ADDR
+ hex "Chipset Micro Code state machine binary location"
+ depends on HAVE_CMC
+ default 0xfffb0000
+ help
+ The location of the CMC binary is determined by a strap. It must be
+ put in flash at a location matching the strap-determined base address.
+
+ The default base address of 0xfffb0000 indicates that the binary must
+ be located at offset 0xb0000 from the beginning of a 1MB flash device.
+
+config CPU_ADDR_BITS
+ int
+ default 32
+
+config DISABLE_IGD
+ bool "Disable Integrated Graphics Device (IGD)"
+ help
+ Disable the Integrated Graphics Device (IGD) so that it does not
+ show in the PCI configuration space as a VGA disaplay controller.
+ This gives a chance for U-Boot to run PCI/PCIe based graphics
+ card's VGA BIOS and use that card for the graphics console.
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/queensbay/Makefile b/roms/u-boot/arch/x86/cpu/queensbay/Makefile
new file mode 100644
index 000000000..ac2961356
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/queensbay/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+
+obj-y += fsp_configs.o
+obj-y += tnc.o
diff --git a/roms/u-boot/arch/x86/cpu/queensbay/fsp_configs.c b/roms/u-boot/arch/x86/cpu/queensbay/fsp_configs.c
new file mode 100644
index 000000000..381edd076
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/queensbay/fsp_configs.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/fsp1/fsp_support.h>
+
+void fsp_update_configs(struct fsp_config_data *config,
+ struct fspinit_rtbuf *rt_buf)
+{
+ /* Initialize runtime buffer for fsp_init() */
+ rt_buf->common.stack_top = config->common.stack_top - 32;
+ rt_buf->common.boot_mode = config->common.boot_mode;
+ rt_buf->common.upd_data = &config->fsp_upd;
+
+ /* Override any UPD setting if required */
+}
diff --git a/roms/u-boot/arch/x86/cpu/queensbay/tnc.c b/roms/u-boot/arch/x86/cpu/queensbay/tnc.c
new file mode 100644
index 000000000..782ed863f
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/queensbay/tnc.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <init.h>
+#include <dm/device-internal.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/post.h>
+#include <asm/arch/device.h>
+#include <asm/arch/tnc.h>
+#include <asm/fsp1/fsp_support.h>
+#include <asm/processor.h>
+
+static int __maybe_unused disable_igd(void)
+{
+ struct udevice *igd, *sdvo;
+ int ret;
+
+ ret = dm_pci_bus_find_bdf(TNC_IGD, &igd);
+ if (ret)
+ return ret;
+ if (!igd)
+ return 0;
+
+ ret = dm_pci_bus_find_bdf(TNC_SDVO, &sdvo);
+ if (ret)
+ return ret;
+ if (!sdvo)
+ return 0;
+
+ /*
+ * According to Atom E6xx datasheet, setting VGA Disable (bit17)
+ * of Graphics Controller register (offset 0x50) prevents IGD
+ * (D2:F0) from reporting itself as a VGA display controller
+ * class in the PCI configuration space, and should also prevent
+ * it from responding to VGA legacy memory range and I/O addresses.
+ *
+ * However test result shows that with just VGA Disable bit set and
+ * a PCIe graphics card connected to one of the PCIe controllers on
+ * the E6xx, accessing the VGA legacy space still causes system hang.
+ * After a number of attempts, it turns out besides VGA Disable bit,
+ * the SDVO (D3:F0) device should be disabled to make it work.
+ *
+ * To simplify, use the Function Disable register (offset 0xc4)
+ * to disable both IGD (D2:F0) and SDVO (D3:F0) devices. Now these
+ * two devices will be completely disabled (invisible in the PCI
+ * configuration space) unless a system reset is performed.
+ */
+ dm_pci_write_config32(igd, IGD_FD, FUNC_DISABLE);
+ dm_pci_write_config32(sdvo, IGD_FD, FUNC_DISABLE);
+
+ /*
+ * After setting the function disable bit, IGD and SDVO devices will
+ * disappear in the PCI configuration space. This however creates an
+ * inconsistent state from a driver model PCI controller point of view,
+ * as these two PCI devices are still attached to its parent's child
+ * device list as maintained by the driver model. Some driver model PCI
+ * APIs like dm_pci_find_class(), are referring to the list to speed up
+ * the finding process instead of re-enumerating the whole PCI bus, so
+ * it gets the stale cached data which is wrong.
+ *
+ * Note x86 PCI enueration normally happens twice, in pre-relocation
+ * phase and post-relocation. One option might be to call disable_igd()
+ * in one of the pre-relocation initialization hooks so that it gets
+ * disabled in the first round, and when it comes to the second round
+ * driver model PCI will construct a correct list. Unfortunately this
+ * does not work as Intel FSP is used on this platform to perform low
+ * level initialization, and fsp_init_phase_pci() is called only once
+ * in the post-relocation phase. If we disable IGD and SDVO devices,
+ * fsp_init_phase_pci() simply hangs and never returns.
+ *
+ * So the only option we have is to manually remove these two devices.
+ */
+ ret = device_remove(igd, DM_REMOVE_NORMAL);
+ if (ret)
+ return ret;
+ ret = device_unbind(igd);
+ if (ret)
+ return ret;
+ ret = device_remove(sdvo, DM_REMOVE_NORMAL);
+ if (ret)
+ return ret;
+ ret = device_unbind(sdvo);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int arch_cpu_init(void)
+{
+ post_code(POST_CPU_INIT);
+
+ return x86_cpu_init_f();
+}
+
+static void tnc_irq_init(void)
+{
+ struct tnc_rcba *rcba;
+ u32 base;
+
+ pci_read_config32(TNC_LPC, LPC_RCBA, &base);
+ base &= ~MEM_BAR_EN;
+ rcba = (struct tnc_rcba *)base;
+
+ /* Make sure all internal PCI devices are using INTA */
+ writel(INTA, &rcba->d02ip);
+ writel(INTA, &rcba->d03ip);
+ writel(INTA, &rcba->d27ip);
+ writel(INTA, &rcba->d31ip);
+ writel(INTA, &rcba->d23ip);
+ writel(INTA, &rcba->d24ip);
+ writel(INTA, &rcba->d25ip);
+ writel(INTA, &rcba->d26ip);
+
+ /*
+ * Route TunnelCreek PCI device interrupt pin to PIRQ
+ *
+ * Since PCIe downstream ports received INTx are routed to PIRQ
+ * A/B/C/D directly and not configurable, we have to route PCIe
+ * root ports' INTx to PIRQ A/B/C/D as well. For other devices
+ * on TunneCreek, route them to PIRQ E/F/G/H.
+ */
+ writew(PIRQE, &rcba->d02ir);
+ writew(PIRQF, &rcba->d03ir);
+ writew(PIRQG, &rcba->d27ir);
+ writew(PIRQH, &rcba->d31ir);
+ writew(PIRQA, &rcba->d23ir);
+ writew(PIRQB, &rcba->d24ir);
+ writew(PIRQC, &rcba->d25ir);
+ writew(PIRQD, &rcba->d26ir);
+}
+
+int arch_early_init_r(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_DISABLE_IGD
+ ret = disable_igd();
+#endif
+
+ tnc_irq_init();
+
+ return ret;
+}
diff --git a/roms/u-boot/arch/x86/cpu/resetvec.S b/roms/u-boot/arch/x86/cpu/resetvec.S
new file mode 100644
index 000000000..cf972738b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/resetvec.S
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * U-Boot - x86 Startup Code
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ */
+
+/* Reset vector, jumps to start16.S */
+
+.extern start16
+
+.section .resetvec, "ax"
+.code16
+reset_vector:
+ cli
+ cld
+ jmp start16
diff --git a/roms/u-boot/arch/x86/cpu/sipi_vector.S b/roms/u-boot/arch/x86/cpu/sipi_vector.S
new file mode 100644
index 000000000..6d2da963b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/sipi_vector.S
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * Taken from coreboot file of the same name
+ */
+
+/*
+ * The SIPI vector is responsible for initializing the APs in the sytem. It
+ * loads microcode, sets up MSRs, and enables caching before calling into
+ * C code
+ */
+
+#include <asm/msr-index.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include <asm/sipi.h>
+
+#define CODE_SEG (X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE)
+#define DATA_SEG (X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE)
+
+/*
+ * First we have the 16-bit section. Every AP process starts here.
+ * The simple task is to load U-Boot's Global Descriptor Table (GDT) to allow
+ * U-Boot's 32-bit code to become visible, then jump to ap_start.
+ *
+ * Note that this code is copied to RAM below 1MB in mp_init.c, and runs from
+ * there, but the 32-bit code (ap_start and onwards) is part of U-Boot and
+ * is therefore relocated to the top of RAM with other U-Boot code. This
+ * means that for the 16-bit code we must write relocatable code, but for the
+ * rest, we can do what we like.
+ */
+.text
+.code16
+.globl ap_start16
+ap_start16:
+ cli
+ xorl %eax, %eax
+ movl %eax, %cr3 /* Invalidate TLB */
+
+ /* setup the data segment */
+ movw %cs, %ax
+ movw %ax, %ds
+
+ /* Use an address relative to the data segment for the GDT */
+ movl $gdtaddr, %ebx
+ subl $ap_start16, %ebx
+
+ data32 lgdt (%ebx)
+
+ movl %cr0, %eax
+ andl $(~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_NE | \
+ X86_CR0_TS | X86_CR0_EM | X86_CR0_MP)), %eax
+ orl $(X86_CR0_NW | X86_CR0_CD | X86_CR0_PE), %eax
+ movl %eax, %cr0
+
+ movl $ap_start_jmp, %eax
+ subl $ap_start16, %eax
+ movw %ax, %bp
+
+ /* Jump to ap_start within U-Boot */
+data32 cs ljmp *(%bp)
+
+ .align 4
+.globl sipi_params_16bit
+sipi_params_16bit:
+ /* 48-bit far pointer */
+ap_start_jmp:
+ .long 0 /* offset set to ap_start by U-Boot */
+ .word CODE_SEG /* segment */
+
+ .word 0 /* padding */
+gdtaddr:
+ .word 0 /* limit */
+ .long 0 /* table */
+ .word 0 /* unused */
+
+.globl ap_start16_code_end
+ap_start16_code_end:
+
+/*
+ * Set up the special 'fs' segment for global_data. Then jump to ap_continue
+ * to set up the AP.
+ */
+.globl ap_start
+ap_start:
+ .code32
+ movw $DATA_SEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %gs
+
+ movw $(X86_GDT_ENTRY_32BIT_FS * X86_GDT_ENTRY_SIZE), %ax
+ movw %ax, %fs
+
+ /* Load the Interrupt descriptor table */
+ mov idt_ptr, %ebx
+ lidt (%ebx)
+
+ /* Obtain cpu number */
+ movl ap_count, %eax
+1:
+ movl %eax, %ecx
+ inc %ecx
+ lock cmpxchg %ecx, ap_count
+ jnz 1b
+
+ /* Setup stacks for each CPU */
+ movl stack_size, %eax
+ mul %ecx
+ movl stack_top, %edx
+ subl %eax, %edx
+ mov %edx, %esp
+ /* Save cpu number */
+ mov %ecx, %esi
+
+ /* Determine if one should check microcode versions */
+ mov microcode_ptr, %edi
+ test %edi, %edi
+ jz microcode_done /* Bypass if no microde exists */
+
+ /* Get the Microcode version */
+ mov $1, %eax
+ cpuid
+ mov $MSR_IA32_UCODE_REV, %ecx
+ rdmsr
+ /* If something already loaded skip loading again */
+ test %edx, %edx
+ jnz microcode_done
+
+ /* Determine if parallel microcode loading is allowed */
+ cmpl $0xffffffff, microcode_lock
+ je load_microcode
+
+ /* Protect microcode loading */
+lock_microcode:
+ lock btsl $0, microcode_lock
+ jc lock_microcode
+
+load_microcode:
+ /* Load new microcode */
+ mov $MSR_IA32_UCODE_WRITE, %ecx
+ xor %edx, %edx
+ mov %edi, %eax
+ /*
+ * The microcode pointer is passed in pointing to the header. Adjust
+ * pointer to reflect the payload (header size is 48 bytes)
+ */
+ add $UCODE_HEADER_LEN, %eax
+ pusha
+ wrmsr
+ popa
+
+ /* Unconditionally unlock microcode loading */
+ cmpl $0xffffffff, microcode_lock
+ je microcode_done
+
+ xor %eax, %eax
+ mov %eax, microcode_lock
+
+microcode_done:
+ /*
+ * Load MSRs. Each entry in the table consists of:
+ * 0: index,
+ * 4: value[31:0]
+ * 8: value[63:32]
+ * See struct saved_msr in mp_init.c.
+ */
+ mov msr_table_ptr, %edi
+ mov msr_count, %ebx
+ test %ebx, %ebx
+ jz 1f
+load_msr:
+ mov (%edi), %ecx
+ mov 4(%edi), %eax
+ mov 8(%edi), %edx
+ wrmsr
+ add $12, %edi
+ dec %ebx
+ jnz load_msr
+
+1:
+ /* Enable caching */
+ mov %cr0, %eax
+ andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax
+ mov %eax, %cr0
+
+ /* c_handler(cpu_num) */
+ movl %esi, %eax /* cpu_num */
+ mov c_handler, %esi
+ call *%esi
+
+ /* This matches struct sipi_param */
+ .align 4
+.globl sipi_params
+sipi_params:
+idt_ptr:
+ .long 0
+stack_top:
+ .long 0
+stack_size:
+ .long 0
+microcode_lock:
+ .long 0
+microcode_ptr:
+ .long 0
+msr_table_ptr:
+ .long 0
+msr_count:
+ .long 0
+c_handler:
+ .long 0
+ap_count:
+ .long 0
diff --git a/roms/u-boot/arch/x86/cpu/slimbootloader/Kconfig b/roms/u-boot/arch/x86/cpu/slimbootloader/Kconfig
new file mode 100644
index 000000000..58a9ca01a
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/slimbootloader/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+config SYS_SLIMBOOTLOADER
+ bool
+ select USE_HOB
+ imply SYS_NS16550
+ imply AHCI_PCI
+ imply SCSI
+ imply SCSI_AHCI
+ imply MMC
+ imply MMC_PCI
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply USB
+ imply USB_EHCI_HCD
+ imply USB_XHCI_HCD
+ imply E1000
+ imply X86_TSC_READ_BASE
diff --git a/roms/u-boot/arch/x86/cpu/slimbootloader/Makefile b/roms/u-boot/arch/x86/cpu/slimbootloader/Makefile
new file mode 100644
index 000000000..aac9fa3db
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/slimbootloader/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+obj-y += car.o slimbootloader.o sdram.o serial.o
diff --git a/roms/u-boot/arch/x86/cpu/slimbootloader/car.S b/roms/u-boot/arch/x86/cpu/slimbootloader/car.S
new file mode 100644
index 000000000..6e0304333
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/slimbootloader/car.S
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <generated/asm-offsets.h>
+
+.section .text
+
+.globl car_init
+car_init:
+ /* Get hob pointer parameter from previous stage's stack */
+ mov 0x4(%esp), %esi
+ jmp car_init_ret
diff --git a/roms/u-boot/arch/x86/cpu/slimbootloader/sdram.c b/roms/u-boot/arch/x86/cpu/slimbootloader/sdram.c
new file mode 100644
index 000000000..36d0d4da5
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/slimbootloader/sdram.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/global_data.h>
+#include <linux/sizes.h>
+#include <asm/e820.h>
+#include <asm/arch/slimbootloader.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * This returns a data pointer of memory map info from the guid hob.
+ *
+ * @return: A data pointer of memory map info hob
+ */
+static struct sbl_memory_map_info *get_memory_map_info(void)
+{
+ struct sbl_memory_map_info *data;
+ const efi_guid_t guid = SBL_MEMORY_MAP_INFO_GUID;
+
+ if (!gd->arch.hob_list)
+ return NULL;
+
+ data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+ if (!data)
+ panic("memory map info hob not found\n");
+ if (!data->count)
+ panic("invalid number of memory map entries\n");
+
+ return data;
+}
+
+#define for_each_if(condition) if (!(condition)) {} else
+
+#define for_each_memory_map_entry_reversed(iter, entries) \
+ for (iter = entries->count - 1; iter >= 0; iter--) \
+ for_each_if(entries->entry[iter].type == E820_RAM)
+
+/**
+ * This is to give usable memory region information for u-boot relocation.
+ * so search usable memory region lower than 4GB.
+ * The memory map entries from Slim Bootloader hob are already sorted.
+ *
+ * @total_size: The memory size that u-boot occupies
+ * @return : The top available memory address lower than 4GB
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ struct sbl_memory_map_info *data;
+ int i;
+ u64 addr_start;
+ u64 addr_end;
+ ulong ram_top;
+
+ data = get_memory_map_info();
+
+ /**
+ * sorted memory map entries from Slim Bootloader based on physical
+ * start memory address, from low to high. So do reversed search to
+ * get highest usable, suitable size, 4KB aligned available memory
+ * under 4GB.
+ */
+ ram_top = 0;
+ for_each_memory_map_entry_reversed(i, data) {
+ addr_start = data->entry[i].addr;
+ addr_end = addr_start + data->entry[i].size;
+
+ if (addr_start > SZ_4G)
+ continue;
+
+ if (addr_end > SZ_4G)
+ addr_end = SZ_4G;
+
+ if (addr_end < total_size)
+ continue;
+
+ /* to relocate u-boot at 4K aligned memory */
+ addr_end = rounddown(addr_end - total_size, SZ_4K);
+ if (addr_end >= addr_start) {
+ ram_top = (ulong)addr_end + total_size;
+ break;
+ }
+ }
+
+ if (!ram_top)
+ panic("failed to find available memory for relocation!");
+
+ return ram_top;
+}
+
+/**
+ * The memory initialization has already been done in previous Slim Bootloader
+ * stage thru FSP-M. Instead, this sets the ram_size from the memory map info
+ * hob.
+ */
+int dram_init(void)
+{
+ struct sbl_memory_map_info *data;
+ int i;
+ u64 ram_size;
+
+ data = get_memory_map_info();
+
+ /**
+ * sorted memory map entries from Slim Bootloader based on physical
+ * start memory address, from low to high. So do reversed search to
+ * simply get highest usable memory address as RAM size
+ */
+ ram_size = 0;
+ for_each_memory_map_entry_reversed(i, data) {
+ /* simply use the highest usable memory address as RAM size */
+ ram_size = data->entry[i].addr + data->entry[i].size;
+ break;
+ }
+
+ if (!ram_size)
+ panic("failed to detect memory size");
+
+ gd->ram_size = ram_size;
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ if (!CONFIG_NR_DRAM_BANKS)
+ return 0;
+
+ /* simply use a single bank to have whole size for now */
+ gd->bd->bi_dram[0].start = 0;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+ return 0;
+}
+
+unsigned int install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ struct sbl_memory_map_info *data;
+ unsigned int i;
+
+ data = get_memory_map_info();
+
+ for (i = 0; i < data->count; i++) {
+ entries[i].addr = data->entry[i].addr;
+ entries[i].size = data->entry[i].size;
+ entries[i].type = data->entry[i].type;
+ }
+
+ return i;
+}
diff --git a/roms/u-boot/arch/x86/cpu/slimbootloader/serial.c b/roms/u-boot/arch/x86/cpu/slimbootloader/serial.c
new file mode 100644
index 000000000..d28b28089
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/slimbootloader/serial.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/slimbootloader.h>
+#include <asm/global_data.h>
+
+/**
+ * The serial port info hob is generated by Slim Bootloader, so eligible for
+ * Slim Bootloader based boards only.
+ */
+static int slimbootloader_serial_of_to_plat(struct udevice *dev)
+{
+ const efi_guid_t guid = SBL_SERIAL_PORT_INFO_GUID;
+ struct sbl_serial_port_info *data;
+ struct ns16550_plat *plat = dev_get_plat(dev);
+
+ if (!gd->arch.hob_list)
+ panic("hob list not found!");
+
+ data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+ if (!data) {
+ debug("failed to get serial port information\n");
+ return -ENOENT;
+ }
+ debug("type:%d base=0x%08x baudrate=%d stride=%d clk=%d\n",
+ data->type,
+ data->base,
+ data->baud,
+ data->stride,
+ data->clk);
+
+ plat->base = data->base;
+ /* ns16550 uses reg_shift, then covert stride to shift */
+ plat->reg_shift = data->stride >> 1;
+ plat->reg_width = data->stride;
+ plat->clock = data->clk;
+ plat->fcr = UART_FCR_DEFVAL;
+ plat->flags = 0;
+ if (data->type == 1)
+ plat->flags |= NS16550_FLAG_IO;
+
+ return 0;
+}
+
+static const struct udevice_id slimbootloader_serial_ids[] = {
+ { .compatible = "intel,slimbootloader-uart" },
+ {}
+};
+
+U_BOOT_DRIVER(serial_slimbootloader) = {
+ .name = "serial_slimbootloader",
+ .id = UCLASS_SERIAL,
+ .of_match = slimbootloader_serial_ids,
+ .of_to_plat = slimbootloader_serial_of_to_plat,
+ .plat_auto = sizeof(struct ns16550_plat),
+ .priv_auto = sizeof(struct ns16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+};
diff --git a/roms/u-boot/arch/x86/cpu/slimbootloader/slimbootloader.c b/roms/u-boot/arch/x86/cpu/slimbootloader/slimbootloader.c
new file mode 100644
index 000000000..ec5b87cfd
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/slimbootloader/slimbootloader.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <log.h>
+#include <asm/arch/slimbootloader.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * This sets tsc_base and clock_rate for early_timer and tsc_timer.
+ * The performance info guid hob has all performance timestamp data, but
+ * the only tsc frequency info is used for the timer driver for now.
+ *
+ * Slim Bootloader already calibrated TSC and provides it to U-Boot.
+ * Therefore, U-Boot does not have to re-calibrate TSC.
+ * Configuring tsc_base and clock_rate here makes x86 tsc_timer driver
+ * bypass TSC calibration and use the provided TSC frequency.
+ */
+static void tsc_init(void)
+{
+ struct sbl_performance_info *data;
+ const efi_guid_t guid = SBL_PERFORMANCE_INFO_GUID;
+
+ if (!gd->arch.hob_list)
+ panic("hob list not found!");
+
+ gd->arch.tsc_base = rdtsc();
+ debug("tsc_base=0x%llx\n", gd->arch.tsc_base);
+
+ data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+ if (!data) {
+ debug("performance info hob not found\n");
+ return;
+ }
+
+ /* frequency is in KHz, so to Hz */
+ gd->arch.clock_rate = data->frequency * 1000;
+ debug("freq=0x%lx\n", gd->arch.clock_rate);
+}
+
+int arch_cpu_init(void)
+{
+ tsc_init();
+
+ return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return default_print_cpuinfo();
+}
diff --git a/roms/u-boot/arch/x86/cpu/start.S b/roms/u-boot/arch/x86/cpu/start.S
new file mode 100644
index 000000000..897fd926c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/start.S
@@ -0,0 +1,316 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * U-Boot - x86 Startup Code
+ *
+ * This is always the first code to run from the U-Boot source. To spell it out:
+ *
+ * 1. When TPL (Tertiary Program Loader) is enabled, the boot flow is
+ * TPL->SPL->U-Boot and this file is used for TPL. Then start_from_tpl.S is used
+ * for SPL and start_from_spl.S is used for U-Boot proper.
+ *
+ * 2. When SPL (Secondary Program Loader) is enabled, but not TPL, the boot
+ * flow is SPL->U-Boot and this file is used for SPL. Then start_from_spl.S is
+ * used for U-Boot proper.
+ *
+ * 3. When neither TPL nor SPL is used, this file is used for U-Boot proper.
+ *
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ */
+
+#include <config.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include <generated/generic-asm-offsets.h>
+#include <generated/asm-offsets.h>
+#include <linux/linkage.h>
+
+.section .text.start
+.code32
+.globl _start
+.type _start, @function
+.globl _x86boot_start
+_x86boot_start:
+ /*
+ * This is the fail-safe 32-bit bootstrap entry point.
+ *
+ * This code is used when booting from another boot loader like
+ * coreboot or EFI. So we repeat some of the same init found in
+ * start16.
+ */
+ cli
+ cld
+
+ /* Turn off cache (this might require a 486-class CPU) */
+ movl %cr0, %eax
+ orl $(X86_CR0_NW | X86_CR0_CD), %eax
+ movl %eax, %cr0
+ wbinvd
+
+ /*
+ * Zero the BIST (Built-In Self Test) value since we don't have it.
+ * It must be 0 or the previous loader would have reported an error.
+ */
+ movl $0, %ebp
+
+ jmp 1f
+
+ /* Add a way for tools to discover the _start entry point */
+ .align 4
+ .long 0x12345678
+_start:
+ /* This is the 32-bit cold-reset entry point, coming from start16 */
+
+ /* Save BIST */
+ movl %eax, %ebp
+1:
+
+ /* Save table pointer */
+ movl %ecx, %esi
+
+#ifdef CONFIG_X86_LOAD_FROM_32_BIT
+ lgdt gdt_ptr2
+#endif
+
+ /* Load the segment registers to match the GDT loaded in start16.S */
+ movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
+ movw %ax, %fs
+ movw %ax, %ds
+ movw %ax, %gs
+ movw %ax, %es
+ movw %ax, %ss
+
+ /* Clear the interrupt vectors */
+ lidt blank_idt_ptr
+
+#ifdef CONFIG_USE_EARLY_BOARD_INIT
+ /*
+ * Critical early platform init - generally not used, we prefer init
+ * to happen later when we have a console, in case something goes
+ * wrong.
+ */
+ jmp early_board_init
+.globl early_board_init_ret
+early_board_init_ret:
+#endif
+
+ post_code(POST_START)
+
+ /* Initialise Cache-As-RAM */
+ jmp car_init
+.globl car_init_ret
+car_init_ret:
+#ifdef CONFIG_USE_CAR
+ /*
+ * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
+ * or fully initialised SDRAM - we really don't care which)
+ * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
+ * and early malloc() area. The MRC requires some space at the top.
+ *
+ * Stack grows down from top of CAR. We have:
+ *
+ * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
+ * MRC area
+ * global_data with x86 global descriptor table
+ * early malloc area
+ * stack
+ * bottom-> CONFIG_SYS_CAR_ADDR
+ */
+ movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+ subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
+#endif
+#else
+ /*
+ * Instructions for FSP1, but not FSP2:
+ * U-Boot enters here twice. For the first time it comes from
+ * car_init_done() with esp points to a temporary stack and esi
+ * set to zero. For the second time it comes from fsp_init_done()
+ * with esi holding the HOB list address returned by the FSP.
+ */
+#endif
+ /* Set up global data */
+ mov %esp, %eax
+ call board_init_f_alloc_reserve
+ mov %eax, %esp
+ call board_init_f_init_reserve
+
+#ifdef CONFIG_DEBUG_UART
+ call debug_uart_init
+#endif
+
+ /* Get address of global_data */
+ mov %fs:0, %edx
+#if defined(CONFIG_USE_HOB) && !defined(CONFIG_USE_CAR)
+ /* Store the HOB list if we have one */
+ test %esi, %esi
+ jz skip_hob
+ movl %esi, GD_HOB_LIST(%edx)
+
+#ifdef CONFIG_HAVE_FSP
+ /*
+ * After fsp_init() returns, the stack has already been switched to a
+ * place within system memory as defined by CONFIG_FSP_TEMP_RAM_ADDR.
+ * Enlarge the size of malloc() pool before relocation since we have
+ * plenty of memory now.
+ */
+ subl $CONFIG_FSP_SYS_MALLOC_F_LEN, %esp
+ movl %esp, GD_MALLOC_BASE(%edx)
+#endif
+skip_hob:
+#else
+ /* Store table pointer */
+ movl %esi, GD_TABLE(%edx)
+#endif
+ /* Store BIST */
+ movl %ebp, GD_BIST(%edx)
+
+ /* Set parameter to board_init_f() to boot flags */
+ post_code(POST_START_DONE)
+ xorl %eax, %eax
+
+ /* Enter, U-Boot! */
+ call board_init_f
+
+ /* indicate (lack of) progress */
+ movw $0x85, %ax
+ jmp die
+
+.globl board_init_f_r_trampoline
+.type board_init_f_r_trampoline, @function
+board_init_f_r_trampoline:
+ /*
+ * SDRAM has been initialised, U-Boot code has been copied into
+ * RAM, BSS has been cleared and relocation adjustments have been
+ * made. It is now time to jump into the in-RAM copy of U-Boot
+ *
+ * %eax = Address of top of new stack
+ */
+
+ /* Stack grows down from top of SDRAM */
+ movl %eax, %esp
+
+ /* See if we need to disable CAR */
+ call car_uninit
+
+ /* Re-enter U-Boot by calling board_init_f_r() */
+ call board_init_f_r
+
+#ifdef CONFIG_TPL
+.globl jump_to_spl
+.type jump_to_spl, @function
+jump_to_spl:
+ /* Reset stack to the top of CAR space */
+ movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+ subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
+#endif
+
+ jmp *%eax
+#endif
+
+die:
+ hlt
+ jmp die
+ hlt
+
+WEAK(car_uninit)
+ ret
+ENDPROC(car_uninit)
+
+blank_idt_ptr:
+ .word 0 /* limit */
+ .long 0 /* base */
+
+ .p2align 2 /* force 4-byte alignment */
+
+ /* Add a multiboot header so U-Boot can be loaded by GRUB2 */
+multiboot_header:
+ /* magic */
+ .long 0x1badb002
+ /* flags */
+ .long (1 << 16)
+ /* checksum */
+ .long -0x1BADB002 - (1 << 16)
+ /* header addr */
+ .long multiboot_header - _x86boot_start + CONFIG_SYS_TEXT_BASE
+ /* load addr */
+ .long CONFIG_SYS_TEXT_BASE
+ /* load end addr */
+ .long 0
+ /* bss end addr */
+ .long 0
+ /* entry addr */
+ .long CONFIG_SYS_TEXT_BASE
+
+#ifdef CONFIG_X86_LOAD_FROM_32_BIT
+ /*
+ * The following Global Descriptor Table is just enough to get us into
+ * 'Flat Protected Mode' - It will be discarded as soon as the final
+ * GDT is setup in a safe location in RAM
+ */
+gdt_ptr2:
+ .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
+ .long gdt_rom2 /* base */
+
+ /* Some CPUs are picky about GDT alignment... */
+ .align 16
+.globl gdt_rom2
+gdt_rom2:
+ /*
+ * The GDT table ...
+ *
+ * Selector Type
+ * 0x00 NULL
+ * 0x08 Unused
+ * 0x10 32bit code
+ * 0x18 32bit data/stack
+ */
+ /* The NULL Desciptor - Mandatory */
+ .word 0x0000 /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x00 /* access */
+ .byte 0x00 /* flags + limit_high */
+ .byte 0x00 /* base_high */
+
+ /* Unused Desciptor - (matches Linux) */
+ .word 0x0000 /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x00 /* access */
+ .byte 0x00 /* flags + limit_high */
+ .byte 0x00 /* base_high */
+
+ /*
+ * The Code Segment Descriptor:
+ * - Base = 0x00000000
+ * - Size = 4GB
+ * - Access = Present, Ring 0, Exec (Code), Readable
+ * - Flags = 4kB Granularity, 32-bit
+ */
+ .word 0xffff /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x9b /* access */
+ .byte 0xcf /* flags + limit_high */
+ .byte 0x00 /* base_high */
+
+ /*
+ * The Data Segment Descriptor:
+ * - Base = 0x00000000
+ * - Size = 4GB
+ * - Access = Present, Ring 0, Non-Exec (Data), Writable
+ * - Flags = 4kB Granularity, 32-bit
+ */
+ .word 0xffff /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x93 /* access */
+ .byte 0xcf /* flags + limit_high */
+ .byte 0x00 /* base_high */
+#endif
diff --git a/roms/u-boot/arch/x86/cpu/start16.S b/roms/u-boot/arch/x86/cpu/start16.S
new file mode 100644
index 000000000..865a49731
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/start16.S
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * U-Boot - x86 Startup Code
+ *
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002,2003
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ */
+
+#include <asm/processor-flags.h>
+
+#define BOOT_SEG 0xffff0000 /* linear segment of boot code */
+
+.section .start16, "ax"
+.code16
+.globl start16
+start16:
+ /* Save BIST */
+ movl %eax, %ecx
+
+ xorl %eax, %eax
+ movl %eax, %cr3 /* Invalidate TLB */
+
+ /* Turn off cache (this might require a 486-class CPU) */
+ movl %cr0, %eax
+ orl $(X86_CR0_NW | X86_CR0_CD), %eax
+ movl %eax, %cr0
+ wbinvd
+
+ /* load the temporary Global Descriptor Table */
+data32 cs lidt idt_ptr
+data32 cs lgdt gdt_ptr
+
+ /* Now, we enter protected mode */
+ movl %cr0, %eax
+ orl $X86_CR0_PE, %eax
+ movl %eax, %cr0
+
+ /* Flush the prefetch queue */
+ jmp ff
+ff:
+
+ /* Finally restore BIST and jump to the 32-bit initialization code */
+ movl %ecx, %eax
+data32 cs ljmp *code32start
+
+ /* 48-bit far pointer */
+code32start:
+ .long _start /* offset */
+ .word 0x10 /* segment */
+
+idt_ptr:
+ .word 0 /* limit */
+ .long 0 /* base */
+
+ /*
+ * The following Global Descriptor Table is just enough to get us into
+ * 'Flat Protected Mode' - It will be discarded as soon as the final
+ * GDT is setup in a safe location in RAM
+ */
+gdt_ptr:
+ .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
+ .long BOOT_SEG + gdt_rom /* base */
+
+ /* Some CPUs are picky about GDT alignment... */
+ .align 16
+.globl gdt_rom
+gdt_rom:
+ /*
+ * The GDT table ...
+ *
+ * Selector Type
+ * 0x00 NULL
+ * 0x08 Unused
+ * 0x10 32bit code
+ * 0x18 32bit data/stack
+ */
+ /* The NULL Desciptor - Mandatory */
+ .word 0x0000 /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x00 /* access */
+ .byte 0x00 /* flags + limit_high */
+ .byte 0x00 /* base_high */
+
+ /* Unused Desciptor - (matches Linux) */
+ .word 0x0000 /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x00 /* access */
+ .byte 0x00 /* flags + limit_high */
+ .byte 0x00 /* base_high */
+
+ /*
+ * The Code Segment Descriptor:
+ * - Base = 0x00000000
+ * - Size = 4GB
+ * - Access = Present, Ring 0, Exec (Code), Readable
+ * - Flags = 4kB Granularity, 32-bit
+ */
+ .word 0xffff /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x9b /* access */
+ .byte 0xcf /* flags + limit_high */
+ .byte 0x00 /* base_high */
+
+ /*
+ * The Data Segment Descriptor:
+ * - Base = 0x00000000
+ * - Size = 4GB
+ * - Access = Present, Ring 0, Non-Exec (Data), Writable
+ * - Flags = 4kB Granularity, 32-bit
+ */
+ .word 0xffff /* limit_low */
+ .word 0x0000 /* base_low */
+ .byte 0x00 /* base_middle */
+ .byte 0x93 /* access */
+ .byte 0xcf /* flags + limit_high */
+ .byte 0x00 /* base_high */
diff --git a/roms/u-boot/arch/x86/cpu/start64.S b/roms/u-boot/arch/x86/cpu/start64.S
new file mode 100644
index 000000000..7be834788
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/start64.S
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 64-bit x86 Startup Code
+ *
+ * Copyright 2019 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <config.h>
+
+.section .text.start
+.code64
+.globl _start
+.type _start, @function
+_start:
+ /* Set up memory using the existing stack */
+ mov %rsp, %rdi
+ call board_init_f_alloc_reserve
+ mov %rax, %rsp
+
+ call board_init_f_init_reserve
+
+ xor %rdi, %rdi
+ call board_init_f
+ call board_init_f_r
+
+ /* Should not return here */
+ jmp .
diff --git a/roms/u-boot/arch/x86/cpu/start_from_spl.S b/roms/u-boot/arch/x86/cpu/start_from_spl.S
new file mode 100644
index 000000000..abfd4abb6
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/start_from_spl.S
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 32-bit x86 Startup Code when running from SPL. This is the startup code in
+ * U-Boot proper, when SPL is used.
+
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <config.h>
+
+.section .text.start
+.code32
+.globl _start
+.type _start, @function
+_start:
+ /*
+ * If running from coreboot, CAR is no-longer available. Use the
+ * existing stack, which is large enough.
+ */
+ call locate_coreboot_table
+ cmp $0, %eax
+ jge use_existing_stack
+
+ movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %eax
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+ subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %eax
+#endif
+ jmp 2f
+ /*
+ * We don't subtract CONFIG_DCACHE_RAM_MRC_VAR_SIZE since memory is
+ * already set up. This has the happy side-effect of putting gd in a
+ * new place separate from SPL, so the memset() in
+ * board_init_f_init_reserve() does not cause any problems (otherwise
+ * it would zero out the gd and crash)
+ */
+ /* Set up memory using the existing stack */
+use_existing_stack:
+ mov %esp, %eax
+2:
+ call board_init_f_alloc_reserve
+ mov %eax, %esp
+
+ call board_init_f_init_reserve
+
+#ifdef CONFIG_DEBUG_UART
+ call debug_uart_init
+#endif
+
+ call x86_cpu_reinit_f
+ xorl %eax, %eax
+ call board_init_f
+ call board_init_f_r
+
+ /* Should not return here */
+ jmp .
+
+.globl board_init_f_r_trampoline
+.type board_init_f_r_trampoline, @function
+board_init_f_r_trampoline:
+ /*
+ * SPL has been executed and SDRAM has been initialised, U-Boot code
+ * has been copied into RAM, BSS has been cleared and relocation
+ * adjustments have been made. It is now time to jump into the in-RAM
+ * copy of U-Boot
+ *
+ * %eax = Address of top of new stack
+ */
+
+ /* Stack grows down from top of SDRAM */
+ movl %eax, %esp
+
+ /* Re-enter U-Boot by calling board_init_f_r() */
+ call board_init_f_r
+
+die:
+ hlt
+ jmp die
+ hlt
+
+ .align 4
+_dt_ucode_base_size:
+ /* These next two fields are filled in by binman */
+.globl ucode_base
+ucode_base: /* Declared in microcode.h */
+ .long 0 /* microcode base */
+.globl ucode_size
+ucode_size: /* Declared in microcode.h */
+ .long 0 /* microcode size */
diff --git a/roms/u-boot/arch/x86/cpu/start_from_tpl.S b/roms/u-boot/arch/x86/cpu/start_from_tpl.S
new file mode 100644
index 000000000..9a4974a5f
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/start_from_tpl.S
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 32-bit x86 Startup Code when running from TPL. This is the startup code in
+ * SPL, when TPL is used.
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <config.h>
+
+.section .text.start
+.code32
+.globl _start
+.type _start, @function
+_start:
+ /* Set up memory using the existing stack */
+ mov %esp, %eax
+ call board_init_f_alloc_reserve
+ mov %eax, %esp
+
+ call board_init_f_init_reserve
+
+ xorl %eax, %eax
+ call board_init_f
+ call board_init_f_r
+
+ /* Should not return here */
+ jmp .
+
+.globl board_init_f_r_trampoline
+.type board_init_f_r_trampoline, @function
+board_init_f_r_trampoline:
+ /*
+ * TPL has been executed: SDRAM has been initialised, BSS has been
+ * cleared.
+ *
+ * %eax = Address of top of new stack
+ */
+
+ /* Stack grows down from top of SDRAM */
+ movl %eax, %esp
+
+ /* Re-enter SPL by calling board_init_f_r() */
+ call board_init_f_r
+
+die:
+ hlt
+ jmp die
+ hlt
diff --git a/roms/u-boot/arch/x86/cpu/tangier/Kconfig b/roms/u-boot/arch/x86/cpu/tangier/Kconfig
new file mode 100644
index 000000000..19aaf165d
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/Kconfig
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2017 Intel Corporation
+
+config INTEL_TANGIER
+ bool
+ depends on INTEL_MID
+ imply INTEL_MID_SERIAL
+ imply MMC
+ imply MMC_SDHCI
+ imply MMC_SDHCI_SDMA
+ imply MMC_SDHCI_TANGIER
+ imply MISC
+ imply USB
+ imply USB_XHCI_HCD
+ imply USB_DWC3
+ imply USB_DWC3_GENERIC
+
+if INTEL_TANGIER
+
+config SYS_CAR_ADDR
+ hex
+ default 0x19200000
+
+config SYS_CAR_SIZE
+ hex
+ default 0x4000
+ help
+ Space in bytes in eSRAM used as Cache-As-RAM (CAR).
+ Note this size must not exceed eSRAM's total size.
+
+endif
diff --git a/roms/u-boot/arch/x86/cpu/tangier/Makefile b/roms/u-boot/arch/x86/cpu/tangier/Makefile
new file mode 100644
index 000000000..68f4a326e
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2017 Intel Corporation
+
+obj-y += car.o tangier.o sdram.o sysreset.o pinmux.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
diff --git a/roms/u-boot/arch/x86/cpu/tangier/acpi.c b/roms/u-boot/arch/x86/cpu/tangier/acpi.c
new file mode 100644
index 000000000..41bd177e0
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/acpi.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on acpi.c for other x86 platforms
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <acpi/acpi_table.h>
+#include <asm/ioapic.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
+#include <asm/arch/iomap.h>
+#include <dm/uclass-internal.h>
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+ void *dsdt)
+{
+ struct acpi_table_header *header = &(fadt->header);
+
+ memset((void *)fadt, 0, sizeof(struct acpi_fadt));
+
+ acpi_fill_header(header, "FACP");
+ header->length = sizeof(struct acpi_fadt);
+ header->revision = 6;
+
+ fadt->firmware_ctrl = (u32)facs;
+ fadt->dsdt = (u32)dsdt;
+ fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
+
+ fadt->iapc_boot_arch = ACPI_FADT_VGA_NOT_PRESENT |
+ ACPI_FADT_NO_PCIE_ASPM_CONTROL;
+ fadt->flags =
+ ACPI_FADT_WBINVD |
+ ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_SEALED_CASE | ACPI_FADT_HEADLESS |
+ ACPI_FADT_HW_REDUCED_ACPI;
+
+ fadt->minor_revision = 2;
+
+ fadt->x_firmware_ctl_l = (u32)facs;
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (u32)dsdt;
+ fadt->x_dsdt_h = 0;
+
+ header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+u32 acpi_fill_madt(u32 current)
+{
+ current += acpi_create_madt_lapics(current);
+
+ current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
+ io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
+
+ return current;
+}
+
+u32 acpi_fill_mcfg(u32 current)
+{
+ /* TODO: Derive parameters from SFI MCFG table */
+ current += acpi_create_mcfg_mmconfig
+ ((struct acpi_mcfg_mmconfig *)current,
+ MCFG_BASE_ADDRESS, 0x0, 0x0, 0x0);
+
+ return current;
+}
+
+static u32 acpi_fill_csrt_dma(struct acpi_csrt_group *grp)
+{
+ struct acpi_csrt_shared_info *si = (struct acpi_csrt_shared_info *)&grp[1];
+
+ /* Fill the Resource Group with Shared Information attached */
+ memset(grp, 0, sizeof(*grp));
+ grp->shared_info_length = sizeof(struct acpi_csrt_shared_info);
+ grp->length = sizeof(struct acpi_csrt_group) + grp->shared_info_length;
+ /* TODO: All values below should come from U-Boot DT somehow */
+ sprintf((char *)&grp->vendor_id, "%04X", 0x8086);
+ grp->device_id = 0x11a2;
+
+ /* Fill the Resource Group Shared Information */
+ memset(si, 0, sizeof(*si));
+ si->major_version = 1;
+ si->minor_version = 0;
+ /* TODO: All values below should come from U-Boot DT somehow */
+ si->mmio_base_low = 0xff192000;
+ si->mmio_base_high = 0;
+ si->gsi_interrupt = 32;
+ si->interrupt_polarity = 1;
+ si->interrupt_mode = 0;
+ si->num_channels = 8;
+ si->dma_address_width = 32;
+ si->base_request_line = 0;
+ si->num_handshake_signals = 16;
+ si->max_block_size = 0x1ffff;
+
+ return grp->length;
+}
+
+u32 acpi_fill_csrt(u32 current)
+{
+ current += acpi_fill_csrt_dma((struct acpi_csrt_group *)current);
+
+ return current;
+}
+
+int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+ struct udevice *dev;
+ int ret;
+
+ /* at least we have one processor */
+ gnvs->pcnt = 1;
+
+ /* override the processor count with actual number */
+ ret = uclass_find_first_device(UCLASS_CPU, &dev);
+ if (ret == 0 && dev != NULL) {
+ ret = cpu_get_count(dev);
+ if (ret > 0)
+ gnvs->pcnt = ret;
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/tangier/car.S b/roms/u-boot/arch/x86/cpu/tangier/car.S
new file mode 100644
index 000000000..7163b69a4
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/car.S
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ */
+
+.section .text
+
+.globl car_init
+car_init:
+ jmp car_init_ret
diff --git a/roms/u-boot/arch/x86/cpu/tangier/pinmux.c b/roms/u-boot/arch/x86/cpu/tangier/pinmux.c
new file mode 100644
index 000000000..acf97e3af
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/pinmux.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Emlid Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <dm/pinctrl.h>
+#include <dm/read.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/cpu.h>
+#include <asm/scu.h>
+#include <linux/io.h>
+
+#define BUFCFG_OFFSET 0x100
+
+#define MRFLD_FAMILY_LEN 0x400
+
+/* These are taken from Linux kernel */
+#define MRFLD_PINMODE_MASK 0x07
+
+#define pin_to_bufno(f, p) ((p) - (f)->pin_base)
+
+struct mrfld_family {
+ unsigned int family_number;
+ unsigned int pin_base;
+ size_t npins;
+ void __iomem *regs;
+};
+
+#define MRFLD_FAMILY(b, s, e) \
+ { \
+ .family_number = (b), \
+ .pin_base = (s), \
+ .npins = (e) - (s) + 1, \
+ }
+
+/* Now we only support I2C family of pins */
+static struct mrfld_family mrfld_families[] = {
+ MRFLD_FAMILY(7, 101, 114),
+};
+
+struct mrfld_pinctrl {
+ const struct mrfld_family *families;
+ size_t nfamilies;
+};
+
+static const struct mrfld_family *
+mrfld_get_family(struct mrfld_pinctrl *mp, unsigned int pin)
+{
+ const struct mrfld_family *family;
+ unsigned int i;
+
+ for (i = 0; i < mp->nfamilies; i++) {
+ family = &mp->families[i];
+ if (pin >= family->pin_base &&
+ pin < family->pin_base + family->npins)
+ return family;
+ }
+
+ pr_err("failed to find family for pin %u\n", pin);
+ return NULL;
+}
+
+static void __iomem *
+mrfld_get_bufcfg(struct mrfld_pinctrl *pinctrl, unsigned int pin)
+{
+ const struct mrfld_family *family;
+ unsigned int bufno;
+
+ family = mrfld_get_family(pinctrl, pin);
+ if (!family)
+ return NULL;
+
+ bufno = pin_to_bufno(family, pin);
+
+ return family->regs + BUFCFG_OFFSET + bufno * 4;
+}
+
+static void
+mrfld_setup_families(void *base_addr,
+ struct mrfld_family *families, unsigned int nfam)
+{
+ for (int i = 0; i < nfam; i++) {
+ struct mrfld_family *family = &families[i];
+
+ family->regs = base_addr +
+ family->family_number * MRFLD_FAMILY_LEN;
+ }
+}
+
+static int mrfld_pinconfig_protected(unsigned int pin, u32 mask, u32 bits)
+{
+ struct mrfld_pinctrl *pinctrl;
+ struct udevice *dev;
+ void __iomem *bufcfg;
+ u32 v, value;
+ int ret;
+
+ ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev);
+ if (ret)
+ return ret;
+
+ pinctrl = dev_get_priv(dev);
+
+ bufcfg = mrfld_get_bufcfg(pinctrl, pin);
+ if (!bufcfg)
+ return -EINVAL;
+
+ value = readl(bufcfg);
+
+ v = (value & ~mask) | (bits & mask);
+
+ debug("scu: v: 0x%x p: 0x%x bits: %d, mask: %d bufcfg: 0x%p\n",
+ v, (u32)bufcfg, bits, mask, bufcfg);
+
+ ret = scu_ipc_raw_command(IPCMSG_INDIRECT_WRITE, 0, &v, 4,
+ NULL, 0, (u32)bufcfg, 0);
+ if (ret)
+ pr_err("Failed to set mode via SCU for pin %u (%d)\n",
+ pin, ret);
+
+ return ret;
+}
+
+static int mrfld_pinctrl_cfg_pin(ofnode pin_node)
+{
+ bool is_protected;
+ int pad_offset;
+ int mode;
+ u32 mask;
+ int ret;
+
+ /* For now we only support just protected Family of pins */
+ is_protected = ofnode_read_bool(pin_node, "protected");
+ if (!is_protected)
+ return -ENOTSUPP;
+
+ pad_offset = ofnode_read_s32_default(pin_node, "pad-offset", -1);
+ if (pad_offset == -1)
+ return -EINVAL;
+
+ mode = ofnode_read_s32_default(pin_node, "mode-func", -1);
+ if (mode == -1)
+ return -EINVAL;
+
+ mask = MRFLD_PINMODE_MASK;
+
+ /* We don't support modes not in range 0..7 */
+ if (mode & ~mask)
+ return -ENOTSUPP;
+
+ ret = mrfld_pinconfig_protected(pad_offset, mask, mode);
+
+ return ret;
+}
+
+static int tangier_pinctrl_probe(struct udevice *dev)
+{
+ void *base_addr = syscon_get_first_range(X86_SYSCON_PINCONF);
+ struct mrfld_pinctrl *pinctrl = dev_get_priv(dev);
+ ofnode pin_node;
+ int ret;
+
+ mrfld_setup_families(base_addr, mrfld_families,
+ ARRAY_SIZE(mrfld_families));
+
+ pinctrl->families = mrfld_families;
+ pinctrl->nfamilies = ARRAY_SIZE(mrfld_families);
+
+ ofnode_for_each_subnode(pin_node, dev_ofnode(dev)) {
+ ret = mrfld_pinctrl_cfg_pin(pin_node);
+ if (ret) {
+ pr_err("%s: invalid configuration for the pin %ld\n",
+ __func__, pin_node.of_offset);
+ }
+ }
+
+ return 0;
+}
+
+static const struct udevice_id tangier_pinctrl_match[] = {
+ { .compatible = "intel,pinctrl-tangier", .data = X86_SYSCON_PINCONF },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(tangier_pinctrl) = {
+ .name = "tangier_pinctrl",
+ .id = UCLASS_SYSCON,
+ .of_match = tangier_pinctrl_match,
+ .probe = tangier_pinctrl_probe,
+ .priv_auto = sizeof(struct mrfld_pinctrl),
+};
diff --git a/roms/u-boot/arch/x86/cpu/tangier/sdram.c b/roms/u-boot/arch/x86/cpu/tangier/sdram.c
new file mode 100644
index 000000000..afb08476e
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/sdram.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ */
+
+#include <common.h>
+#include <init.h>
+#include <log.h>
+#include <asm/e820.h>
+#include <asm/global_data.h>
+#include <asm/sfi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * SFI tables are part of the first stage bootloader.
+ *
+ * U-Boot finds the System Table by searching 16-byte boundaries between
+ * physical address 0x000E0000 and 0x000FFFFF. U-Boot shall search this region
+ * starting at the low address and shall stop searching when the 1st valid SFI
+ * System Table is found.
+ */
+#define SFI_BASE_ADDR 0x000E0000
+#define SFI_LENGTH 0x00020000
+#define SFI_TABLE_LENGTH 16
+
+static int sfi_table_check(struct sfi_table_header *sbh)
+{
+ char chksum = 0;
+ char *pos = (char *)sbh;
+ u32 i;
+
+ if (sbh->len < SFI_TABLE_LENGTH)
+ return -ENXIO;
+
+ if (sbh->len > SFI_LENGTH)
+ return -ENXIO;
+
+ for (i = 0; i < sbh->len; i++)
+ chksum += *pos++;
+
+ if (chksum)
+ pr_err("sfi: Invalid checksum\n");
+
+ /* Checksum is OK if zero */
+ return chksum ? -EILSEQ : 0;
+}
+
+static int sfi_table_is_type(struct sfi_table_header *sbh, const char *signature)
+{
+ return !strncmp(sbh->sig, signature, SFI_SIGNATURE_SIZE) &&
+ !sfi_table_check(sbh);
+}
+
+static struct sfi_table_simple *sfi_get_table_by_sig(unsigned long addr,
+ const char *signature)
+{
+ struct sfi_table_simple *sb;
+ u32 i;
+
+ for (i = 0; i < SFI_LENGTH; i += SFI_TABLE_LENGTH) {
+ sb = (struct sfi_table_simple *)(addr + i);
+ if (sfi_table_is_type(&sb->header, signature))
+ return sb;
+ }
+
+ return NULL;
+}
+
+static struct sfi_table_simple *sfi_search_mmap(void)
+{
+ struct sfi_table_header *sbh;
+ struct sfi_table_simple *sb;
+ u32 sys_entry_cnt;
+ u32 i;
+
+ /* Find SYST table */
+ sb = sfi_get_table_by_sig(SFI_BASE_ADDR, SFI_SIG_SYST);
+ if (!sb) {
+ pr_err("sfi: failed to locate SYST table\n");
+ return NULL;
+ }
+
+ sys_entry_cnt = (sb->header.len - sizeof(*sbh)) / 8;
+
+ /* Search through each SYST entry for MMAP table */
+ for (i = 0; i < sys_entry_cnt; i++) {
+ sbh = (struct sfi_table_header *)(unsigned long)sb->pentry[i];
+
+ if (sfi_table_is_type(sbh, SFI_SIG_MMAP))
+ return (struct sfi_table_simple *)sbh;
+ }
+
+ pr_err("sfi: failed to locate SFI MMAP table\n");
+ return NULL;
+}
+
+#define sfi_for_each_mentry(i, sb, mentry) \
+ for (i = 0, mentry = (struct sfi_mem_entry *)sb->pentry; \
+ i < SFI_GET_NUM_ENTRIES(sb, struct sfi_mem_entry); \
+ i++, mentry++) \
+
+static unsigned int sfi_setup_e820(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_mem_entry *mentry;
+ unsigned long long start, end, size;
+ int type, total = 0;
+ u32 i;
+
+ sb = sfi_search_mmap();
+ if (!sb)
+ return 0;
+
+ sfi_for_each_mentry(i, sb, mentry) {
+ start = mentry->phys_start;
+ size = mentry->pages << 12;
+ end = start + size;
+
+ if (start > end)
+ continue;
+
+ /* translate SFI mmap type to E820 map type */
+ switch (mentry->type) {
+ case SFI_MEM_CONV:
+ type = E820_RAM;
+ break;
+ case SFI_MEM_UNUSABLE:
+ case SFI_RUNTIME_SERVICE_DATA:
+ continue;
+ default:
+ type = E820_RESERVED;
+ }
+
+ if (total == E820MAX)
+ break;
+ entries[total].addr = start;
+ entries[total].size = size;
+ entries[total].type = type;
+
+ total++;
+ }
+
+ return total;
+}
+
+static int sfi_get_bank_size(void)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_mem_entry *mentry;
+ int bank = 0;
+ u32 i;
+
+ sb = sfi_search_mmap();
+ if (!sb)
+ return 0;
+
+ sfi_for_each_mentry(i, sb, mentry) {
+ if (mentry->type != SFI_MEM_CONV)
+ continue;
+
+ gd->bd->bi_dram[bank].start = mentry->phys_start;
+ gd->bd->bi_dram[bank].size = mentry->pages << 12;
+ bank++;
+ }
+
+ return bank;
+}
+
+static phys_size_t sfi_get_ram_size(void)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_mem_entry *mentry;
+ phys_size_t ram = 0;
+ u32 i;
+
+ sb = sfi_search_mmap();
+ if (!sb)
+ return 0;
+
+ sfi_for_each_mentry(i, sb, mentry) {
+ if (mentry->type != SFI_MEM_CONV)
+ continue;
+
+ ram += mentry->pages << 12;
+ }
+
+ debug("sfi: RAM size %llu\n", ram);
+ return ram;
+}
+
+unsigned int install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ return sfi_setup_e820(max_entries, entries);
+}
+
+/*
+ * This function looks for the highest region of memory lower than 2GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary. It
+ * overrides the default implementation found elsewhere which simply picks the
+ * end of RAM, wherever that may be. The location of the stack, the relocation
+ * address, and how far U-Boot is moved by relocation are set in the global
+ * data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_mem_entry *mentry;
+ ulong dest_addr = 0;
+ u32 i;
+
+ sb = sfi_search_mmap();
+ if (!sb)
+ panic("No available memory found for relocation");
+
+ sfi_for_each_mentry(i, sb, mentry) {
+ unsigned long long start, end;
+
+ if (mentry->type != SFI_MEM_CONV)
+ continue;
+
+ start = mentry->phys_start;
+ end = start + (mentry->pages << 12);
+
+ /* Filter memory over 2GB. */
+ if (end > 0x7fffffffULL)
+ end = 0x80000000ULL;
+ /* Skip this region if it's too small. */
+ if (end - start < total_size)
+ continue;
+
+ /* Use this address if it's the largest so far. */
+ if (end > dest_addr)
+ dest_addr = end;
+ }
+
+ return dest_addr;
+}
+
+int dram_init_banksize(void)
+{
+ sfi_get_bank_size();
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = sfi_get_ram_size();
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/tangier/sysreset.c b/roms/u-boot/arch/x86/cpu/tangier/sysreset.c
new file mode 100644
index 000000000..b03bc28f9
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/sysreset.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Reset driver for tangier processor
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sysreset.h>
+#include <asm/scu.h>
+
+static int tangier_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+ int value;
+
+ switch (type) {
+ case SYSRESET_WARM:
+ value = IPCMSG_WARM_RESET;
+ break;
+ case SYSRESET_COLD:
+ value = IPCMSG_COLD_RESET;
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ scu_ipc_simple_command(value, 0);
+
+ return -EINPROGRESS;
+}
+
+static const struct udevice_id tangier_sysreset_ids[] = {
+ { .compatible = "intel,reset-tangier" },
+ { }
+};
+
+static struct sysreset_ops tangier_sysreset_ops = {
+ .request = tangier_sysreset_request,
+};
+
+U_BOOT_DRIVER(tangier_sysreset) = {
+ .name = "tangier-sysreset",
+ .id = UCLASS_SYSRESET,
+ .of_match = tangier_sysreset_ids,
+ .ops = &tangier_sysreset_ops,
+};
diff --git a/roms/u-boot/arch/x86/cpu/tangier/tangier.c b/roms/u-boot/arch/x86/cpu/tangier/tangier.c
new file mode 100644
index 000000000..1e2f6cc8b
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/tangier/tangier.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <asm/u-boot-x86.h>
+
+/*
+ * Miscellaneous platform dependent initializations
+ */
+int arch_cpu_init(void)
+{
+ return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return default_print_cpuinfo();
+}
diff --git a/roms/u-boot/arch/x86/cpu/turbo.c b/roms/u-boot/arch/x86/cpu/turbo.c
new file mode 100644
index 000000000..e2c84cdde
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/turbo.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2011 The Chromium Authors.
+ */
+
+#include <common.h>
+#include <log.h>
+#include <asm/cpu.h>
+#include <asm/global_data.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/turbo.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+static inline int get_global_turbo_state(void)
+{
+ return TURBO_UNKNOWN;
+}
+
+static inline void set_global_turbo_state(int state)
+{
+}
+#else
+static inline int get_global_turbo_state(void)
+{
+ return gd->arch.turbo_state;
+}
+
+static inline void set_global_turbo_state(int state)
+{
+ gd->arch.turbo_state = state;
+}
+#endif
+
+/* gcc 7.3 does not wwant to drop strings, so use #ifdef */
+#ifndef CONFIG_TPL_BUILD
+static const char *const turbo_state_desc[] = {
+ [TURBO_UNKNOWN] = "unknown",
+ [TURBO_UNAVAILABLE] = "unavailable",
+ [TURBO_DISABLED] = "available but hidden",
+ [TURBO_ENABLED] = "available and visible"
+};
+#endif
+
+/*
+ * Determine the current state of Turbo and cache it for later.
+ * Turbo is a package level config so it does not need to be
+ * enabled on every core.
+ */
+int turbo_get_state(void)
+{
+ struct cpuid_result cpuid_regs;
+ int turbo_en, turbo_cap;
+ msr_t msr;
+ int turbo_state = get_global_turbo_state();
+
+ /* Return cached state if available */
+ if (turbo_state != TURBO_UNKNOWN)
+ return turbo_state;
+
+ cpuid_regs = cpuid(CPUID_LEAF_PM);
+ turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
+
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ turbo_en = !(msr.hi & MISC_DISABLE_TURBO);
+
+ if (!turbo_cap && turbo_en) {
+ /* Unavailable */
+ turbo_state = TURBO_UNAVAILABLE;
+ } else if (!turbo_cap && !turbo_en) {
+ /* Available but disabled */
+ turbo_state = TURBO_DISABLED;
+ } else if (turbo_cap && turbo_en) {
+ /* Available */
+ turbo_state = TURBO_ENABLED;
+ }
+
+ set_global_turbo_state(turbo_state);
+#ifndef CONFIG_TPL_BUILD
+ debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
+#endif
+ return turbo_state;
+}
+
+void turbo_enable(void)
+{
+ msr_t msr;
+
+ /* Only possible if turbo is available but hidden */
+ if (turbo_get_state() == TURBO_DISABLED) {
+ /* Clear Turbo Disable bit in Misc Enables */
+ msr = msr_read(MSR_IA32_MISC_ENABLE);
+ msr.hi &= ~MISC_DISABLE_TURBO;
+ msr_write(MSR_IA32_MISC_ENABLE, msr);
+
+ /* Update cached turbo state */
+ set_global_turbo_state(TURBO_ENABLED);
+ debug("Turbo has been enabled\n");
+ }
+}
diff --git a/roms/u-boot/arch/x86/cpu/u-boot-64.lds b/roms/u-boot/arch/x86/cpu/u-boot-64.lds
new file mode 100644
index 000000000..ee0812aef
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/u-boot-64.lds
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ */
+
+#include <config.h>
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+
+SECTIONS
+{
+#ifndef CONFIG_CMDLINE
+ /DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+#endif
+
+ . = CONFIG_SYS_TEXT_BASE; /* Location of bootcode in flash */
+ __text_start = .;
+
+ .text.start : { *(.text.start); }
+
+ .__efi_runtime_start : {
+ *(.__efi_runtime_start)
+ }
+
+ .efi_runtime : {
+ *(.text.efi_runtime*)
+ *(.rodata.efi_runtime*)
+ *(.data.efi_runtime*)
+ }
+
+ .__efi_runtime_stop : {
+ *(.__efi_runtime_stop)
+ }
+
+ .text : { *(.text*); }
+
+ . = ALIGN(4);
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = ALIGN(4);
+ .rodata : {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ KEEP(*(.rodata.efi.init));
+ }
+
+ . = ALIGN(4);
+ .data : { *(.data*) }
+
+ . = ALIGN(4);
+ .hash : { *(.hash*) }
+
+ . = ALIGN(4);
+ .got : { *(.got*) }
+
+ .efi_runtime_rel_start :
+ {
+ *(.__efi_runtime_rel_start)
+ }
+
+ .efi_runtime_rel : {
+ *(.rel*.efi_runtime)
+ *(.rel*.efi_runtime.*)
+ }
+
+ .efi_runtime_rel_stop :
+ {
+ *(.__efi_runtime_rel_stop)
+ }
+
+ . = ALIGN(4);
+ __data_end = .;
+ __init_end = .;
+
+ . = ALIGN(4);
+ .dynsym : { *(.dynsym*) }
+
+ . = ALIGN(4);
+ __rel_dyn_start = .;
+ .rela.dyn : {
+ *(.rela*)
+ }
+ __rel_dyn_end = .;
+ . = ALIGN(4);
+
+ .dynamic : { *(.dynamic) }
+
+ . = ALIGN(4);
+ _end = .;
+
+ .bss __rel_dyn_start (OVERLAY) : {
+ __bss_start = .;
+ *(.bss*)
+ *(COM*)
+ . = ALIGN(4);
+ __bss_end = .;
+ }
+
+ /DISCARD/ : { *(.dynsym) }
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.note.gnu.property) }
+}
diff --git a/roms/u-boot/arch/x86/cpu/u-boot-spl.lds b/roms/u-boot/arch/x86/cpu/u-boot-spl.lds
new file mode 100644
index 000000000..346f60bda
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/u-boot-spl.lds
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ */
+
+#include <config.h>
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+#ifndef CONFIG_CMDLINE
+ /DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+#endif
+
+ . = IMAGE_TEXT_BASE; /* Location of bootcode in flash */
+ __text_start = .;
+ .text : {
+ __image_copy_start = .;
+ *(.text*);
+ }
+
+ . = ALIGN(4);
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+
+ .priv_data : {
+ __priv_data_start = .;
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*)))
+ __priv_data_end = .;
+ }
+
+ . = ALIGN(4);
+ .data : { *(.data*) }
+
+ . = ALIGN(4);
+ __data_end = .;
+ __init_end = .;
+ . = ALIGN(4);
+ .binman_sym_table : {
+ __binman_sym_start = .;
+ KEEP(*(SORT(.binman_sym*)));
+ __binman_sym_end = .;
+
+ /*
+ * Force 32-byte alignment so that it lines up with the start of
+ * bss, which may have up to 32-byte alignment. This ensures
+ * that the end of the .bin file matches up with
+ * _image_binary_end or __bss_end - see board_fdt_blob_setup().
+ * The alignment of BSS depends on what is in it, so can range
+ * from 4 to 32 bytes.
+ */
+ . = ALIGN(32);
+ }
+
+ _image_binary_end = .;
+
+#if CONFIG_IS_ENABLED(SEPARATE_BSS)
+ . = 0x120000;
+#endif
+ .bss (OVERLAY) : {
+ __bss_start = .;
+ *(.bss*)
+ *(COM*)
+ . = ALIGN(4);
+ __bss_end = .;
+ }
+ __bss_size = __bss_end - __bss_start;
+
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.note.gnu.property) }
+
+#if defined(CONFIG_SPL_X86_16BIT_INIT) || defined(CONFIG_TPL_X86_16BIT_INIT)
+ /*
+ * The following expressions place the 16-bit Real-Mode code and
+ * Reset Vector at the end of the Flash ROM
+ */
+ . = START_16 - RESET_SEG_START;
+ .start16 : AT (START_16) {
+ KEEP(*(.start16));
+ }
+
+ . = RESET_VEC_LOC - RESET_SEG_START;
+ .resetvec : AT (RESET_VEC_LOC) {
+ KEEP(*(.resetvec));
+ }
+#endif
+
+}
diff --git a/roms/u-boot/arch/x86/cpu/u-boot.lds b/roms/u-boot/arch/x86/cpu/u-boot.lds
new file mode 100644
index 000000000..22fde01e7
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/u-boot.lds
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ */
+
+#include <config.h>
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+#ifndef CONFIG_CMDLINE
+ /DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+#endif
+
+ . = CONFIG_SYS_TEXT_BASE; /* Location of bootcode in flash */
+ __text_start = .;
+
+ .text.start : { *(.text.start); }
+
+ .__efi_runtime_start : {
+ *(.__efi_runtime_start)
+ }
+
+ .efi_runtime : {
+ *(.text.efi_runtime*)
+ *(.rodata.efi_runtime*)
+ *(.data.efi_runtime*)
+ }
+
+ .__efi_runtime_stop : {
+ *(.__efi_runtime_stop)
+ }
+
+ .text : { *(.text*); }
+
+ . = ALIGN(4);
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = ALIGN(4);
+ .rodata : {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ KEEP(*(.rodata.efi.init));
+ }
+
+ . = ALIGN(4);
+ .data : { *(.data*) }
+
+ . = ALIGN(4);
+ .hash : { *(.hash*) }
+
+ . = ALIGN(4);
+ .got : { *(.got*) }
+
+ . = ALIGN(4);
+
+ .efi_runtime_rel_start :
+ {
+ *(.__efi_runtime_rel_start)
+ }
+
+ .efi_runtime_rel : {
+ *(.rel*.efi_runtime)
+ *(.rel*.efi_runtime.*)
+ }
+
+ .efi_runtime_rel_stop :
+ {
+ *(.__efi_runtime_rel_stop)
+ }
+
+ . = ALIGN(4);
+
+ __data_end = .;
+ __init_end = .;
+
+ . = ALIGN(4);
+ .dynsym : { *(.dynsym*) }
+
+ . = ALIGN(4);
+ __rel_dyn_start = .;
+ .rel.dyn : {
+ *(.rel*)
+ }
+ __rel_dyn_end = .;
+ . = ALIGN(4);
+ _end = .;
+
+ .bss __rel_dyn_start (OVERLAY) : {
+ __bss_start = .;
+ *(.bss*)
+ *(COM*)
+ . = ALIGN(4);
+ __bss_end = .;
+ }
+
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.note.gnu.property) }
+
+#ifdef CONFIG_X86_16BIT_INIT
+ /*
+ * The following expressions place the 16-bit Real-Mode code and
+ * Reset Vector at the end of the Flash ROM
+ */
+ . = START_16 - RESET_SEG_START;
+ .start16 : AT (START_16) {
+ KEEP(*(.start16));
+ }
+
+ . = RESET_VEC_LOC - RESET_SEG_START;
+ .resetvec : AT (RESET_VEC_LOC) {
+ KEEP(*(.resetvec));
+ }
+#endif
+
+}
diff --git a/roms/u-boot/arch/x86/cpu/wakeup.S b/roms/u-boot/arch/x86/cpu/wakeup.S
new file mode 100644
index 000000000..093bf3bcc
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/wakeup.S
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * From coreboot src/arch/x86/wakeup.S
+ */
+
+#include <acpi/acpi_s3.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+
+#define RELOCATED(x) ((x) - __wakeup + WAKEUP_BASE)
+
+#define CODE_SEG (X86_GDT_ENTRY_16BIT_CS * X86_GDT_ENTRY_SIZE)
+#define DATA_SEG (X86_GDT_ENTRY_16BIT_DS * X86_GDT_ENTRY_SIZE)
+
+ .code32
+ .globl __wakeup
+__wakeup:
+ /* First prepare the jmp to the resume vector */
+ mov 0x4(%esp), %eax /* vector */
+ /* last 4 bits of linear addr are taken as offset */
+ andw $0x0f, %ax
+ movw %ax, (__wakeup_offset)
+ mov 0x4(%esp), %eax
+ /* the rest is taken as segment */
+ shr $4, %eax
+ movw %ax, (__wakeup_segment)
+
+ /* Activate the right segment descriptor real mode */
+ ljmp $CODE_SEG, $RELOCATED(1f)
+1:
+ /* 16 bit code from here on... */
+ .code16
+
+ /*
+ * Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off.
+ */
+ mov $DATA_SEG, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+
+ /* Turn off protection */
+ movl %cr0, %eax
+ andl $~X86_CR0_PE, %eax
+ movl %eax, %cr0
+
+ /* Now really going into real mode */
+ ljmp $0, $RELOCATED(1f)
+1:
+ movw $0x0, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %fs
+ movw %ax, %gs
+
+ /*
+ * This is a FAR JMP to the OS waking vector.
+ * The C code changes the address to be correct.
+ */
+ .byte 0xea
+
+__wakeup_offset = RELOCATED(.)
+ .word 0x0000
+
+__wakeup_segment = RELOCATED(.)
+ .word 0x0000
+
+ .globl __wakeup_size
+__wakeup_size:
+ .long . - __wakeup
diff --git a/roms/u-boot/arch/x86/cpu/x86_64/Makefile b/roms/u-boot/arch/x86/cpu/x86_64/Makefile
new file mode 100644
index 000000000..400f0ffe3
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/x86_64/Makefile
@@ -0,0 +1,6 @@
+#
+# (C) Copyright 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+obj-y += cpu.o interrupts.o setjmp.o
diff --git a/roms/u-boot/arch/x86/cpu/x86_64/cpu.c b/roms/u-boot/arch/x86/cpu/x86_64/cpu.c
new file mode 100644
index 000000000..90a766c3c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/x86_64/cpu.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <debug_uart.h>
+#include <init.h>
+
+/*
+ * Global declaration of gd.
+ *
+ * As we write to it before relocation we have to make sure it is not put into
+ * a .bss section which may overlap a .rela section. Initialization forces it
+ * into a .data section which cannot overlap any .rela section.
+ */
+struct global_data *global_data_ptr = (struct global_data *)~0;
+
+void arch_setup_gd(gd_t *new_gd)
+{
+ global_data_ptr = new_gd;
+}
+
+int cpu_has_64bit(void)
+{
+ return true;
+}
+
+void enable_caches(void)
+{
+ /* Not implemented */
+}
+
+void disable_caches(void)
+{
+ /* Not implemented */
+}
+
+int dcache_status(void)
+{
+ return true;
+}
+
+int x86_mp_init(void)
+{
+ /* Not implemented */
+ return 0;
+}
+
+int misc_init_r(void)
+{
+ return 0;
+}
+
+#ifndef CONFIG_SYS_COREBOOT
+int checkcpu(void)
+{
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ return 0;
+}
+#endif
+
+int x86_cpu_reinit_f(void)
+{
+ return 0;
+}
+
+int cpu_phys_address_size(void)
+{
+ return CONFIG_CPU_ADDR_BITS;
+}
diff --git a/roms/u-boot/arch/x86/cpu/x86_64/interrupts.c b/roms/u-boot/arch/x86/cpu/x86_64/interrupts.c
new file mode 100644
index 000000000..634f7660c
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/x86_64/interrupts.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <irq_func.h>
+#include <asm/processor-flags.h>
+
+void enable_interrupts(void)
+{
+ asm("sti\n");
+}
+
+int disable_interrupts(void)
+{
+ long flags;
+
+ asm volatile ("pushfq ; popq %0 ; cli\n" : "=g" (flags) : );
+
+ return flags & X86_EFLAGS_IF;
+}
+
+int interrupt_init(void)
+{
+ /* Nothing to do - this was already done in SPL */
+ return 0;
+}
diff --git a/roms/u-boot/arch/x86/cpu/x86_64/setjmp.S b/roms/u-boot/arch/x86/cpu/x86_64/setjmp.S
new file mode 100644
index 000000000..97b812854
--- /dev/null
+++ b/roms/u-boot/arch/x86/cpu/x86_64/setjmp.S
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * See arch/x86/include/asm/setjmp.h for jmp_buf format
+ */
+
+#include <linux/linkage.h>
+
+.text
+.align 8
+
+ENTRY(setjmp)
+
+ pop %rcx
+ movq %rcx, (%rdi) /* Return address */
+ movq %rsp, 8(%rdi)
+ movq %rbp, 16(%rdi)
+ movq %rbx, 24(%rdi)
+ movq %r12, 32(%rdi)
+ movq %r13, 40(%rdi)
+ movq %r14, 48(%rdi)
+ movq %r15, 56(%rdi)
+ xorq %rax, %rax /* Direct invocation returns 0 */
+ jmpq *%rcx
+
+ENDPROC(setjmp)
+
+.align 8
+
+ENTRY(longjmp)
+
+ movq (%rdi), %rcx /* Return address */
+ movq 8(%rdi), %rsp
+ movq 16(%rdi), %rbp
+ movq 24(%rdi), %rbx
+ movq 32(%rdi), %r12
+ movq 40(%rdi), %r13
+ movq 48(%rdi), %r14
+ movq 56(%rdi), %r15
+
+ movq %rsi, %rax /* Value to be returned by setjmp() */
+ testq %rax, %rax /* cannot be 0 in this case */
+ jnz 1f
+ incq %rax /* Return 1 instead */
+1:
+ jmpq *%rcx
+
+ENDPROC(longjmp)