summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Rini <trini@ti.com>2015-02-10 10:42:56 -0500
committerTom Rini <trini@ti.com>2015-02-10 10:42:56 -0500
commitdb7a7dee6878fe7539d5967de1caff83246254e0 (patch)
tree27a94cac552d2015cc53cd29658f15f834475a5c
parentc956662cc3e2475b451afa9a8b639c0ccc49d432 (diff)
parentba877efb802edb7080703e4dd99e51a437e44f26 (diff)
downloadtalos-obmc-uboot-db7a7dee6878fe7539d5967de1caff83246254e0.tar.gz
talos-obmc-uboot-db7a7dee6878fe7539d5967de1caff83246254e0.zip
Merge branch 'master' of git://git.denx.de/u-boot-x86
-rw-r--r--Makefile5
-rw-r--r--arch/x86/Kconfig96
-rw-r--r--arch/x86/cpu/Makefile2
-rw-r--r--arch/x86/cpu/baytrail/Kconfig9
-rw-r--r--arch/x86/cpu/baytrail/Makefile10
-rw-r--r--arch/x86/cpu/baytrail/early_uart.c77
-rw-r--r--arch/x86/cpu/baytrail/fsp_configs.c156
-rw-r--r--arch/x86/cpu/baytrail/pci.c46
-rw-r--r--arch/x86/cpu/baytrail/valleyview.c38
-rw-r--r--arch/x86/cpu/ivybridge/gma.c3
-rw-r--r--arch/x86/cpu/ivybridge/sdram.c2
-rw-r--r--arch/x86/cpu/quark/Kconfig126
-rw-r--r--arch/x86/cpu/quark/Makefile9
-rw-r--r--arch/x86/cpu/quark/car.S105
-rw-r--r--arch/x86/cpu/quark/dram.c134
-rw-r--r--arch/x86/cpu/quark/hte.c396
-rw-r--r--arch/x86/cpu/quark/hte.h44
-rw-r--r--arch/x86/cpu/quark/mrc.c204
-rw-r--r--arch/x86/cpu/quark/mrc_util.c1475
-rw-r--r--arch/x86/cpu/quark/mrc_util.h153
-rw-r--r--arch/x86/cpu/quark/msg_port.c77
-rw-r--r--arch/x86/cpu/quark/pci.c70
-rw-r--r--arch/x86/cpu/quark/quark.c118
-rw-r--r--arch/x86/cpu/quark/smc.c2764
-rw-r--r--arch/x86/cpu/quark/smc.h446
-rw-r--r--arch/x86/cpu/queensbay/Kconfig38
-rw-r--r--arch/x86/cpu/queensbay/Makefile4
-rw-r--r--arch/x86/cpu/queensbay/fsp_configs.c2
-rw-r--r--arch/x86/cpu/queensbay/tnc.c29
-rw-r--r--arch/x86/cpu/queensbay/tnc_pci.c17
-rw-r--r--arch/x86/cpu/queensbay/topcliff.c33
-rw-r--r--arch/x86/dts/Makefile4
-rw-r--r--arch/x86/dts/galileo.dts95
-rw-r--r--arch/x86/dts/microcode/m0130673322.dtsi3284
-rw-r--r--arch/x86/dts/minnowmax.dts45
-rw-r--r--arch/x86/dts/serial.dtsi2
-rw-r--r--arch/x86/include/asm/arch-baytrail/fsp/azalia.h39
-rw-r--r--arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h95
-rw-r--r--arch/x86/include/asm/arch-baytrail/gpio.h13
-rw-r--r--arch/x86/include/asm/arch-ivybridge/sandybridge.h2
-rw-r--r--arch/x86/include/asm/arch-quark/device.h28
-rw-r--r--arch/x86/include/asm/arch-quark/gpio.h13
-rw-r--r--arch/x86/include/asm/arch-quark/mrc.h187
-rw-r--r--arch/x86/include/asm/arch-quark/msg_port.h106
-rw-r--r--arch/x86/include/asm/arch-quark/quark.h72
-rw-r--r--arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h2
-rw-r--r--arch/x86/include/asm/fsp/fsp_api.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h)6
-rw-r--r--arch/x86/include/asm/fsp/fsp_bootmode.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h)0
-rw-r--r--arch/x86/include/asm/fsp/fsp_ffs.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h)0
-rw-r--r--arch/x86/include/asm/fsp/fsp_fv.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h)0
-rw-r--r--arch/x86/include/asm/fsp/fsp_hob.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h)0
-rw-r--r--arch/x86/include/asm/fsp/fsp_infoheader.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h)0
-rw-r--r--arch/x86/include/asm/fsp/fsp_platform.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h)0
-rw-r--r--arch/x86/include/asm/fsp/fsp_support.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h)6
-rw-r--r--arch/x86/include/asm/fsp/fsp_types.h (renamed from arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h)0
-rw-r--r--arch/x86/include/asm/pci.h13
-rw-r--r--arch/x86/include/asm/u-boot-x86.h3
-rw-r--r--arch/x86/lib/Makefile1
-rw-r--r--arch/x86/lib/cmd_hob.c2
-rw-r--r--arch/x86/lib/fsp/Makefile10
-rw-r--r--arch/x86/lib/fsp/fsp_car.S (renamed from arch/x86/cpu/queensbay/tnc_car.S)0
-rw-r--r--arch/x86/lib/fsp/fsp_common.c55
-rw-r--r--arch/x86/lib/fsp/fsp_dram.c (renamed from arch/x86/cpu/queensbay/tnc_dram.c)2
-rw-r--r--arch/x86/lib/fsp/fsp_support.c (renamed from arch/x86/cpu/queensbay/fsp_support.c)20
-rw-r--r--arch/x86/lib/pci_type1.c7
-rw-r--r--board/google/chromebook_link/Kconfig3
-rw-r--r--board/intel/galileo/Kconfig21
-rw-r--r--board/intel/galileo/MAINTAINERS6
-rw-r--r--board/intel/galileo/Makefile7
-rw-r--r--board/intel/galileo/galileo.c19
-rw-r--r--board/intel/galileo/start.S9
-rw-r--r--board/intel/minnowmax/Kconfig24
-rw-r--r--board/intel/minnowmax/MAINTAINERS6
-rw-r--r--board/intel/minnowmax/Makefile7
-rw-r--r--board/intel/minnowmax/minnowmax.c32
-rw-r--r--board/intel/minnowmax/start.S9
-rw-r--r--common/cmd_scsi.c2
-rw-r--r--configs/galileo_defconfig6
-rw-r--r--configs/minnowmax_defconfig13
-rw-r--r--doc/README.x86137
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/pci_mmc.c42
-rw-r--r--drivers/pci/pci.c43
-rw-r--r--drivers/pci/pci_rom.c32
-rw-r--r--drivers/spi/ich.c59
-rw-r--r--drivers/spi/ich.h11
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-pci.c53
-rw-r--r--drivers/usb/host/xhci-pci.c60
-rw-r--r--drivers/video/vesa_fb.c9
-rw-r--r--include/bootstage.h5
-rw-r--r--include/configs/galileo.h60
-rw-r--r--include/configs/minnowmax.h72
-rw-r--r--include/configs/x86-common.h4
-rw-r--r--include/dt-bindings/mrc/quark.h83
-rw-r--r--include/fdtdec.h1
-rw-r--r--include/mmc.h14
-rw-r--r--include/pci.h3
-rw-r--r--include/pci_ids.h9
-rw-r--r--include/pci_rom.h15
-rw-r--r--lib/fdtdec.c1
-rwxr-xr-xtools/microcode-tool.py90
102 files changed, 11497 insertions, 272 deletions
diff --git a/Makefile b/Makefile
index 76bae8b6d5..6da42157b5 100644
--- a/Makefile
+++ b/Makefile
@@ -729,8 +729,9 @@ ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
endif
ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
-# We can't do this yet due to the need for binary blobs
-# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+ifneq ($(BUILD_ROM),)
+ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+endif
# enable combined SPL/u-boot/dtb rules for tegra
ifneq ($(CONFIG_TEGRA),)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 90e828a26e..fef11f3552 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -41,6 +41,30 @@ config TARGET_CROWNBAY
Intel Platform Controller Hub EG20T, other system components and
peripheral connectors for PCIe/SATA/USB/LAN/SD/UART/Audio/LVDS.
+config TARGET_MINNOWMAX
+ bool "Support Intel Minnowboard MAX"
+ help
+ This is the Intel Minnowboard MAX. It contains an Atom E3800
+ processor in a small form factor with Ethernet, micro-SD, USB 2,
+ USB 3, SATA, serial console, some GPIOs and HDMI 1.3 video out.
+ It requires some binary blobs - see README.x86 for details.
+
+ Note that PCIE_ECAM_BASE is set up by the FSP so the value used
+ by U-Boot matches that value.
+
+config TARGET_GALILEO
+ bool "Support Intel Galileo"
+ help
+ This is the Intel Galileo board, which is the first in a family of
+ Arduino-certified development and prototyping boards based on Intel
+ architecture. It includes an Intel Quark SoC X1000 processor, a 32-bit
+ single-core, single-thread, Intel Pentium processor instrunction set
+ architecture (ISA) compatible, operating at speeds up to 400Mhz,
+ along with 256MB DDR3 memory. It supports a wide range of industry
+ standard I/O interfaces, including a full-sized mini-PCIe slot,
+ one 100Mb Ethernet port, a microSD card slot, a USB host port and
+ a USB client port.
+
endchoice
config RAMBASE
@@ -324,6 +348,54 @@ config FRAMEBUFFER_VESA_MODE
endmenu
+config HAVE_FSP
+ bool "Add an Firmware Support Package binary"
+ help
+ Select this option to add an Firmware Support Package binary to
+ the resulting U-Boot image. It is a binary blob which U-Boot uses
+ to set up SDRAM and other chipset specific initialization.
+
+ Note: Without this binary U-Boot will not be able to set up its
+ SDRAM so will not boot.
+
+config FSP_FILE
+ string "Firmware Support Package binary filename"
+ depends on HAVE_FSP
+ default "fsp.bin"
+ help
+ The filename of the file to use as Firmware Support Package binary
+ in the board directory.
+
+config FSP_ADDR
+ hex "Firmware Support Package binary location"
+ depends on HAVE_FSP
+ default 0xfffc0000
+ help
+ FSP is not Position Independent Code (PIC) and the whole FSP has to
+ be rebased if it is placed at a location which is different from the
+ perferred base address specified during the FSP build. Use Intel's
+ Binary Configuration Tool (BCT) to do the rebase.
+
+ The default base address of 0xfffc0000 indicates that the binary must
+ be located at offset 0xc0000 from the beginning of a 1MB flash device.
+
+config FSP_TEMP_RAM_ADDR
+ hex
+ default 0x2000000
+ help
+ Stack top address which is used in FspInit after DRAM is ready and
+ CAR is disabled.
+
+source "arch/x86/cpu/baytrail/Kconfig"
+
+source "arch/x86/cpu/coreboot/Kconfig"
+
+source "arch/x86/cpu/ivybridge/Kconfig"
+
+source "arch/x86/cpu/quark/Kconfig"
+
+source "arch/x86/cpu/queensbay/Kconfig"
+
config TSC_CALIBRATION_BYPASS
bool "Bypass Time-Stamp Counter (TSC) calibration"
default n
@@ -344,16 +416,28 @@ config TSC_FREQ_IN_MHZ
help
The running frequency in MHz of Time-Stamp Counter (TSC).
-source "arch/x86/cpu/coreboot/Kconfig"
-
-source "arch/x86/cpu/ivybridge/Kconfig"
-
-source "arch/x86/cpu/queensbay/Kconfig"
-
source "board/coreboot/coreboot/Kconfig"
source "board/google/chromebook_link/Kconfig"
source "board/intel/crownbay/Kconfig"
+source "board/intel/minnowmax/Kconfig"
+
+source "board/intel/galileo/Kconfig"
+
+config PCIE_ECAM_BASE
+ hex
+ default 0xe0000000
+ help
+ This is the memory-mapped address of PCI configuration space, which
+ is only available through the Enhanced Configuration Access
+ Mechanism (ECAM) with PCI Express. It can be set up almost
+ anywhere. Before it is set up, it is possible to access PCI
+ configuration space through I/O access, but memory access is more
+ convenient. Using this, PCI can be scanned and configured. This
+ should be set to a region that does not conflict with memory
+ assigned to PCI devices - i.e. the memory and prefetch regions, as
+ passed to pci_set_region().
+
endmenu
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 62e43c04e5..6ded0a7f0f 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -12,9 +12,11 @@ extra-y = start.o
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
obj-y += interrupts.o cpu.o call64.o
+obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_SYS_COREBOOT) += coreboot/
obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
+obj-$(CONFIG_INTEL_QUARK) += quark/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += lapic.o
obj-y += mtrr.o
diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig
new file mode 100644
index 0000000000..e86cc01115
--- /dev/null
+++ b/arch/x86/cpu/baytrail/Kconfig
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2015 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+config INTEL_BAYTRAIL
+ bool
+ select HAVE_FSP
diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile
new file mode 100644
index 0000000000..8914e8b6d5
--- /dev/null
+++ b/arch/x86/cpu/baytrail/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2015 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += early_uart.o
+obj-y += fsp_configs.o
+obj-y += pci.o
+obj-y += valleyview.o
diff --git a/arch/x86/cpu/baytrail/early_uart.c b/arch/x86/cpu/baytrail/early_uart.c
new file mode 100644
index 0000000000..41992105fe
--- /dev/null
+++ b/arch/x86/cpu/baytrail/early_uart.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#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 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_early_uart(void)
+{
+ /* Enable the legacy UART hardware. */
+ pci_write_config32(PCI_DEV_CONFIG(0, LPC_DEV, LPC_FUNC), UART_CONT, 1);
+
+ /*
+ * 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;
+}
diff --git a/arch/x86/cpu/baytrail/fsp_configs.c b/arch/x86/cpu/baytrail/fsp_configs.c
new file mode 100644
index 0000000000..86b6926272
--- /dev/null
+++ b/arch/x86/cpu/baytrail/fsp_configs.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#include <common.h>
+#include <asm/arch/fsp/azalia.h>
+#include <asm/fsp/fsp_support.h>
+
+/* ALC262 Verb Table - 10EC0262 */
+static const uint32_t verb_table_data13[] = {
+ /* Pin Complex (NID 0x11) */
+ 0x01171cf0,
+ 0x01171d11,
+ 0x01171e11,
+ 0x01171f41,
+ /* Pin Complex (NID 0x12) */
+ 0x01271cf0,
+ 0x01271d11,
+ 0x01271e11,
+ 0x01271f41,
+ /* Pin Complex (NID 0x14) */
+ 0x01471c10,
+ 0x01471d40,
+ 0x01471e01,
+ 0x01471f01,
+ /* Pin Complex (NID 0x15) */
+ 0x01571cf0,
+ 0x01571d11,
+ 0x01571e11,
+ 0x01571f41,
+ /* Pin Complex (NID 0x16) */
+ 0x01671cf0,
+ 0x01671d11,
+ 0x01671e11,
+ 0x01671f41,
+ /* Pin Complex (NID 0x18) */
+ 0x01871c20,
+ 0x01871d98,
+ 0x01871ea1,
+ 0x01871f01,
+ /* Pin Complex (NID 0x19) */
+ 0x01971c21,
+ 0x01971d98,
+ 0x01971ea1,
+ 0x01971f02,
+ /* Pin Complex (NID 0x1A) */
+ 0x01a71c2f,
+ 0x01a71d30,
+ 0x01a71e81,
+ 0x01a71f01,
+ /* Pin Complex */
+ 0x01b71c1f,
+ 0x01b71d40,
+ 0x01b71e21,
+ 0x01b71f02,
+ /* Pin Complex */
+ 0x01c71cf0,
+ 0x01c71d11,
+ 0x01c71e11,
+ 0x01c71f41,
+ /* Pin Complex */
+ 0x01d71c01,
+ 0x01d71dc6,
+ 0x01d71e14,
+ 0x01d71f40,
+ /* Pin Complex */
+ 0x01e71cf0,
+ 0x01e71d11,
+ 0x01e71e11,
+ 0x01e71f41,
+ /* Pin Complex */
+ 0x01f71cf0,
+ 0x01f71d11,
+ 0x01f71e11,
+ 0x01f71f41,
+};
+
+/*
+ * This needs to be in ROM since if we put it in CAR, FSP init loses it when
+ * it drops CAR.
+ *
+ * TODO(sjg@chromium.org): Move to device tree when FSP allows it
+ *
+ * VerbTable: (RealTek ALC262)
+ * Revision ID = 0xFF, support all steps
+ * Codec Verb Table For AZALIA
+ * Codec Address: CAd value (0/1/2)
+ * Codec Vendor: 0x10EC0262
+ */
+static const struct pch_azalia_verb_table azalia_verb_table[] = {
+ {
+ {
+ 0x10ec0262,
+ 0x0000,
+ 0xff,
+ 0x01,
+ 0x000b,
+ 0x0002,
+ },
+ verb_table_data13
+ }
+};
+
+const struct pch_azalia_config azalia_config = {
+ .pme_enable = 1,
+ .docking_supported = 1,
+ .docking_attached = 0,
+ .hdmi_codec_enable = 1,
+ .azalia_v_ci_enable = 1,
+ .rsvdbits = 0,
+ .azalia_verb_table_num = 1,
+ .azalia_verb_table = azalia_verb_table,
+ .reset_wait_timer_us = 300
+};
+
+void update_fsp_upd(struct upd_region *fsp_upd)
+{
+ struct memory_down_data *mem;
+
+ /*
+ * Configure everything here to avoid the poor hard-pressed user
+ * needing to run Intel's binary configuration tool. It may also allow
+ * us to support the 1GB single core variant easily.
+ *
+ * TODO(sjg@chromium.org): Move to device tree
+ */
+ fsp_upd->mrc_init_tseg_size = 8;
+ fsp_upd->mrc_init_mmio_size = 0x800;
+ fsp_upd->emmc_boot_mode = 0xff;
+ fsp_upd->enable_sdio = 1;
+ fsp_upd->enable_sdcard = 1;
+ fsp_upd->enable_hsuart0 = 1;
+ fsp_upd->azalia_config_ptr = (uint32_t)&azalia_config;
+ fsp_upd->enable_i2_c0 = 0;
+ fsp_upd->enable_i2_c2 = 0;
+ fsp_upd->enable_i2_c3 = 0;
+ fsp_upd->enable_i2_c4 = 0;
+ fsp_upd->enable_xhci = 0;
+ fsp_upd->igd_render_standby = 1;
+
+ mem = &fsp_upd->memory_params;
+ mem->enable_memory_down = 1;
+ mem->dram_speed = 1;
+ mem->dimm_width = 1;
+ mem->dimm_density = 2;
+ mem->dimm_tcl = 0xb;
+ mem->dimm_trpt_rcd = 0xb;
+ mem->dimm_twr = 0xc;
+ mem->dimm_twtr = 6;
+ mem->dimm_trrd = 6;
+ mem->dimm_trtp = 6;
+ mem->dimm_tfaw = 0x14;
+}
diff --git a/arch/x86/cpu/baytrail/pci.c b/arch/x86/cpu/baytrail/pci.c
new file mode 100644
index 0000000000..6c291f9ee9
--- /dev/null
+++ b/arch/x86/cpu/baytrail/pci.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/pci.h>
+#include <asm/fsp/fsp_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_pci_setup_hose(struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0;
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_PCI_MEM_BUS,
+ CONFIG_PCI_MEM_PHYS,
+ CONFIG_PCI_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 1,
+ CONFIG_PCI_IO_BUS,
+ CONFIG_PCI_IO_PHYS,
+ CONFIG_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ pci_set_region(hose->regions + 2,
+ CONFIG_PCI_PREF_BUS,
+ CONFIG_PCI_PREF_PHYS,
+ CONFIG_PCI_PREF_SIZE,
+ PCI_REGION_PREFETCH);
+
+ pci_set_region(hose->regions + 3,
+ 0,
+ 0,
+ gd->ram_size,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ hose->region_count = 4;
+}
diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c
new file mode 100644
index 0000000000..a3e837d43e
--- /dev/null
+++ b/arch/x86/cpu/baytrail/valleyview.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <pci_ids.h>
+#include <asm/post.h>
+
+static struct pci_device_id mmc_supported[] = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD },
+};
+
+int cpu_mmc_init(bd_t *bis)
+{
+ printf("mmc init\n");
+ return pci_mmc_init("ValleyView SDHCI", mmc_supported,
+ ARRAY_SIZE(mmc_supported));
+}
+
+int arch_cpu_init(void)
+{
+ int ret;
+
+ post_code(POST_CPU_INIT);
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+ timer_set_base(rdtsc());
+#endif
+
+ ret = x86_cpu_init_f();
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c
index 6cf9654e02..821ea25019 100644
--- a/arch/x86/cpu/ivybridge/gma.c
+++ b/arch/x86/cpu/ivybridge/gma.c
@@ -758,7 +758,8 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
#ifdef CONFIG_VIDEO
start = get_timer(0);
- ret = pci_run_vga_bios(dev, int15_handler, false);
+ ret = pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE |
+ PCI_ROM_ALLOW_FALLBACK);
debug("BIOS ran in %lums\n", get_timer(start));
#endif
/* Post VBIOS init */
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index 49634485f3..766b385c25 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -757,7 +757,7 @@ int dram_init(void)
.mchbar = DEFAULT_MCHBAR,
.dmibar = DEFAULT_DMIBAR,
.epbar = DEFAULT_EPBAR,
- .pciexbar = CONFIG_MMCONF_BASE_ADDRESS,
+ .pciexbar = CONFIG_PCIE_ECAM_BASE,
.smbusbar = SMBUS_IO_BASE,
.wdbbar = 0x4000000,
.wdbsize = 0x1000,
diff --git a/arch/x86/cpu/quark/Kconfig b/arch/x86/cpu/quark/Kconfig
new file mode 100644
index 0000000000..bc961ef07c
--- /dev/null
+++ b/arch/x86/cpu/quark/Kconfig
@@ -0,0 +1,126 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+config INTEL_QUARK
+ bool
+ select HAVE_RMU
+ select TSC_CALIBRATION_BYPASS
+
+if INTEL_QUARK
+
+config HAVE_RMU
+ bool "Add a Remote Management Unit (RMU) binary"
+ 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 Managment 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 TSC_FREQ_IN_MHZ
+ int
+ default 400
+
+endif
diff --git a/arch/x86/cpu/quark/Makefile b/arch/x86/cpu/quark/Makefile
new file mode 100644
index 0000000000..e87b4248e6
--- /dev/null
+++ b/arch/x86/cpu/quark/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += car.o dram.o msg_port.o quark.o
+obj-y += mrc.o mrc_util.o hte.o smc.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/x86/cpu/quark/car.S b/arch/x86/cpu/quark/car.S
new file mode 100644
index 0000000000..3432ffa081
--- /dev/null
+++ b/arch/x86/cpu/quark/car.S
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#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/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c
new file mode 100644
index 0000000000..9cac846c69
--- /dev/null
+++ b/arch/x86/cpu/quark/dram.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/post.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/quark.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+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;
+ }
+
+ /*
+ * TODO:
+ *
+ * We need support fast boot (MRC cache) in the future.
+ *
+ * Set boot mode to cold boot for now
+ */
+ mrc_params->boot_mode = BM_COLD;
+
+ /*
+ * 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;
+ 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);
+
+ return 0;
+}
+
+void dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = 0;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+}
+
+/*
+ * 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/arch/x86/cpu/quark/hte.c b/arch/x86/cpu/quark/hte.c
new file mode 100644
index 0000000000..372815d8c1
--- /dev/null
+++ b/arch/x86/cpu/quark/hte.c
@@ -0,0 +1,396 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#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) & BIT30) != 0);
+
+ tmp = msg_port_read(HTE, 0x00020011);
+ tmp |= BIT9;
+ tmp &= ~(BIT12 | BIT13);
+ 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 |= BIT8;
+ 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 | BIT8);
+
+ 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/arch/x86/cpu/quark/hte.h b/arch/x86/cpu/quark/hte.h
new file mode 100644
index 0000000000..6577796fd6
--- /dev/null
+++ b/arch/x86/cpu/quark/hte.h
@@ -0,0 +1,44 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#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/arch/x86/cpu/quark/mrc.c b/arch/x86/cpu/quark/mrc.c
new file mode 100644
index 0000000000..7eb34c5302
--- /dev/null
+++ b/arch/x86/cpu/quark/mrc.c
@@ -0,0 +1,204 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+/*
+ * 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 <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,
+ __DATE__, __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/arch/x86/cpu/quark/mrc_util.c b/arch/x86/cpu/quark/mrc_util.c
new file mode 100644
index 0000000000..3a79ae551b
--- /dev/null
+++ b/arch/x86/cpu/quark/mrc_util.c
@@ -0,0 +1,1475 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#include <common.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"
+
+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 &= ~BIT28;
+ 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 |= BIT28;
+ 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)
+{
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, data);
+ 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 & BIT0) ? (BIT23 | BIT22 | BIT21 | BIT20) :
+ (BIT11 | BIT10 | BIT9 | BIT8);
+ temp = (byte_lane & BIT0) ? ((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 & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+ (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+ 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 & BIT0) ? BIT5 : BIT2;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (byte_lane & BIT0) ? BIT11 : BIT8;
+ 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 & BIT0) ? 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 & BIT0) ? 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 & BIT0) ? B1RXDQSPICODE : B0RXDQSPICODE;
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+ (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+ 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 & BIT0) ? 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 & BIT0) ? (BIT19 | BIT18 | BIT17 | BIT16) :
+ (BIT7 | BIT6 | BIT5 | BIT4);
+ temp = pi_count / HALF_CLK;
+ temp <<= (byte_lane & BIT0) ? 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 & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+ (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16);
+ 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 & BIT0) ? BIT4 : BIT1;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (byte_lane & BIT0) ? BIT10 : BIT7;
+ 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 & BIT0) ? 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 & BIT0) ? 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 & BIT0) ? (BIT15 | BIT14 | BIT13 | BIT12) :
+ (BIT3 | BIT2 | BIT1 | BIT0);
+ temp = pi_count / HALF_CLK;
+ temp <<= (byte_lane & BIT0) ? 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 & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+ (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+ 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 & BIT0) ? BIT3 : BIT0;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (byte_lane & BIT0) ? BIT9 : BIT6;
+ 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 & BIT0) ? (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 & BIT0) ? 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 = (BIT11 | BIT10 | BIT9 | BIT8);
+ 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 = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24 |
+ BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+ BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+
+ 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 |= BIT16;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= BIT17;
+ 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 = (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+ 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 = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+ BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+ 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 |= (BIT3 | BIT2 | BIT1 | BIT0);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (BIT11 | BIT10 | BIT9 | BIT8);
+ 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 = (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+ 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 = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+ 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 |= (BIT5 | BIT4);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ temp |= msk;
+
+ /* select */
+ msk |= (BIT13 | BIT12);
+ 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),
+ (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+
+ /*
+ * 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 = 0x02000000; /* 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 ? BIT1 : BIT9; /* BL0 */
+ msk[1] = rcvn ? BIT0 : BIT8; /* 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 & BIT0);
+ bit = bit ^ ((lfsr & BIT1) >> 1);
+ bit = bit ^ ((lfsr & BIT2) >> 2);
+ bit = bit ^ ((lfsr & BIT22) >> 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)),
+ ~BIT8, BIT8);
+
+ mrc_alt_write_mask(DDRPHY,
+ (B01PTRCTL1 +
+ (channel * DDRIODQ_CH_OFFSET) +
+ ((bl >> 1) * DDRIODQ_BL_OFFSET)),
+ BIT8, BIT8);
+ }
+ }
+
+ 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/arch/x86/cpu/quark/mrc_util.h b/arch/x86/cpu/quark/mrc_util.h
new file mode 100644
index 0000000000..f0ddbce3c5
--- /dev/null
+++ b/arch/x86/cpu/quark/mrc_util.h
@@ -0,0 +1,153 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#ifndef _MRC_UTIL_H_
+#define _MRC_UTIL_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__)
+
+/* Generic Register Bits */
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+/* 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/arch/x86/cpu/quark/msg_port.c b/arch/x86/cpu/quark/msg_port.c
new file mode 100644
index 0000000000..31713e321f
--- /dev/null
+++ b/arch/x86/cpu/quark/msg_port.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/arch/device.h>
+#include <asm/arch/msg_port.h>
+
+void msg_port_setup(int op, int port, int reg)
+{
+ 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;
+
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_READ, port, reg);
+ pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+ return value;
+}
+
+void msg_port_write(u8 port, u32 reg, u32 value)
+{
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ 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;
+
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_ALT_READ, port, reg);
+ pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+ return value;
+}
+
+void msg_port_alt_write(u8 port, u32 reg, u32 value)
+{
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ 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;
+
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
+ msg_port_setup(MSG_OP_IO_READ, port, reg);
+ pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+ return value;
+}
+
+void msg_port_io_write(u8 port, u32 reg, u32 value)
+{
+ pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ 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/arch/x86/cpu/quark/pci.c b/arch/x86/cpu/quark/pci.c
new file mode 100644
index 0000000000..354e15a990
--- /dev/null
+++ b/arch/x86/cpu/quark/pci.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/pci.h>
+#include <asm/arch/device.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_pci_setup_hose(struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0;
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_PCI_MEM_BUS,
+ CONFIG_PCI_MEM_PHYS,
+ CONFIG_PCI_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 1,
+ CONFIG_PCI_IO_BUS,
+ CONFIG_PCI_IO_PHYS,
+ CONFIG_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ pci_set_region(hose->regions + 2,
+ CONFIG_PCI_PREF_BUS,
+ CONFIG_PCI_PREF_PHYS,
+ CONFIG_PCI_PREF_SIZE,
+ PCI_REGION_PREFETCH);
+
+ pci_set_region(hose->regions + 3,
+ 0,
+ 0,
+ gd->ram_size,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ hose->region_count = 4;
+}
+
+int board_pci_post_scan(struct pci_controller *hose)
+{
+ return 0;
+}
+
+int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+{
+ /*
+ * TODO:
+ *
+ * For some unknown reason, the PCI enumeration process hangs
+ * when it scans to the PCIe root port 0 (D23:F0) & 1 (D23:F1).
+ *
+ * For now we just skip these two devices, and this needs to
+ * be revisited later.
+ */
+ if (dev == QUARK_HOST_BRIDGE ||
+ dev == QUARK_PCIE0 || dev == QUARK_PCIE1) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c
new file mode 100644
index 0000000000..dccf7ac5f5
--- /dev/null
+++ b/arch/x86/cpu/quark/quark.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/arch/device.h>
+#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
+
+static struct pci_device_id mmc_supported[] = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO },
+};
+
+/*
+ * TODO:
+ *
+ * This whole routine should be removed until we fully convert the ICH SPI
+ * driver to DM and make use of DT to pass the bios control register offset
+ */
+static void unprotect_spi_flash(void)
+{
+ u32 bc;
+
+ bc = pci_read_config32(QUARK_LEGACY_BRIDGE, 0xd8);
+ bc |= 0x1; /* unprotect the flash */
+ pci_write_config32(QUARK_LEGACY_BRIDGE, 0xd8, bc);
+}
+
+static void quark_setup_bars(void)
+{
+ /* GPIO - D31:F0:R44h */
+ pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
+ CONFIG_GPIO_BASE | IO_BAR_EN);
+
+ /* ACPI PM1 Block - D31:F0:R48h */
+ pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
+ CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
+
+ /* GPE0 - D31:F0:R4Ch */
+ pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
+ CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
+
+ /* WDT - D31:F0:R84h */
+ pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
+ CONFIG_WDT_BASE | IO_BAR_EN);
+
+ /* RCBA - D31:F0:RF0h */
+ 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);
+}
+
+int arch_cpu_init(void)
+{
+ struct pci_controller *hose;
+ int ret;
+
+ post_code(POST_CPU_INIT);
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+ timer_set_base(rdtsc());
+#endif
+
+ ret = x86_cpu_init_f();
+ if (ret)
+ return ret;
+
+ ret = pci_early_init_hose(&hose);
+ if (ret)
+ return ret;
+
+ /*
+ * Quark SoC has some non-standard BARs (excluding PCI standard BARs)
+ * which need be initialized with suggested values
+ */
+ quark_setup_bars();
+
+ unprotect_spi_flash();
+
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ post_code(POST_CPU_INFO);
+ return default_print_cpuinfo();
+}
+
+void reset_cpu(ulong addr)
+{
+ /* cold reset */
+ outb(0x08, PORT_RESET);
+}
+
+int cpu_mmc_init(bd_t *bis)
+{
+ return pci_mmc_init("Quark SDHCI", mmc_supported,
+ ARRAY_SIZE(mmc_supported));
+}
diff --git a/arch/x86/cpu/quark/smc.c b/arch/x86/cpu/quark/smc.c
new file mode 100644
index 0000000000..e34bec4c80
--- /dev/null
+++ b/arch/x86/cpu/quark/smc.c
@@ -0,0 +1,2764 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#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_rfc values (in picoseconds) per density */
+static const uint32_t t_rfc[5] = {
+ 90000, /* 512Mb */
+ 110000, /* 1Gb */
+ 160000, /* 2Gb */
+ 300000, /* 4Gb */
+ 350000, /* 8Gb */
+};
+
+/* 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};
+static const uint16_t ddr_wctl[] = {1, 217};
+static const uint16_t ddr_wcmd[] = {1, 220};
+
+#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, BIT0, BIT0);
+
+ 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 &= ~(BIT0 | BIT1);
+ dtr0 |= mrc_params->ddr_speed;
+ dtr0 &= ~(BIT12 | BIT13 | BIT14);
+ tmp1 = tcl - 5;
+ dtr0 |= ((tcl - 5) << 12);
+ dtr0 &= ~(BIT4 | BIT5 | BIT6 | BIT7);
+ dtr0 |= ((trp - 5) << 4); /* 5 bit DRAM Clock */
+ dtr0 &= ~(BIT8 | BIT9 | BIT10 | BIT11);
+ dtr0 |= ((trcd - 5) << 8); /* 5 bit DRAM Clock */
+
+ dtr1 &= ~(BIT0 | BIT1 | BIT2);
+ tmp2 = wl - 3;
+ dtr1 |= (wl - 3);
+ dtr1 &= ~(BIT8 | BIT9 | BIT10 | BIT11);
+ dtr1 |= ((wl + 4 + twr - 14) << 8); /* Change to tWTP */
+ dtr1 &= ~(BIT28 | BIT29 | BIT30);
+ dtr1 |= ((MMAX(trtp, 4) - 3) << 28); /* 4 bit DRAM Clock */
+ dtr1 &= ~(BIT24 | BIT25);
+ dtr1 |= ((trrd - 4) << 24); /* 4 bit DRAM Clock */
+ dtr1 &= ~(BIT4 | BIT5);
+ dtr1 |= (1 << 4);
+ dtr1 &= ~(BIT20 | BIT21 | BIT22 | BIT23);
+ dtr1 |= ((tras - 14) << 20); /* 6 bit DRAM Clock */
+ dtr1 &= ~(BIT16 | BIT17 | BIT18 | BIT19);
+ dtr1 |= ((((tfaw + 1) >> 1) - 5) << 16);/* 4 bit DRAM Clock */
+ /* Set 4 Clock CAS to CAS delay (multi-burst) */
+ dtr1 &= ~(BIT12 | BIT13);
+
+ dtr2 &= ~(BIT0 | BIT1 | BIT2);
+ dtr2 |= 1;
+ dtr2 &= ~(BIT8 | BIT9 | BIT10);
+ dtr2 |= (2 << 8);
+ dtr2 &= ~(BIT16 | BIT17 | BIT18 | BIT19);
+ dtr2 |= (2 << 16);
+
+ dtr3 &= ~(BIT0 | BIT1 | BIT2);
+ dtr3 |= 2;
+ dtr3 &= ~(BIT4 | BIT5 | BIT6);
+ dtr3 |= (2 << 4);
+
+ dtr3 &= ~(BIT8 | BIT9 | BIT10 | BIT11);
+ 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 &= ~(BIT13 | BIT14 | BIT15 | BIT16);
+ dtr3 |= ((4 + wl + twtr - 11) << 13);
+
+ dtr3 &= ~(BIT22 | BIT23);
+ if (mrc_params->ddr_speed == DDRFREQ_800)
+ dtr3 |= ((MMAX(0, 1 - 1)) << 22);
+ else
+ dtr3 |= ((MMAX(0, 2 - 1)) << 22);
+
+ dtr4 &= ~(BIT0 | BIT1);
+ dtr4 |= 1;
+ dtr4 &= ~(BIT4 | BIT5 | BIT6);
+ dtr4 |= (1 << 4);
+ dtr4 &= ~(BIT8 | BIT9 | BIT10);
+ dtr4 |= ((1 + tmp1 - tmp2 + 2) << 8);
+ dtr4 &= ~(BIT12 | BIT13 | BIT14);
+ dtr4 |= ((1 + tmp1 - tmp2 + 2) << 12);
+ dtr4 &= ~(BIT15 | BIT16);
+
+ 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 |= (BIT24 | BIT25);
+ dpmc0 &= ~(BIT16 | BIT17 | BIT18);
+ dpmc0 &= ~BIT23;
+ msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+ /* Disable out of order transactions */
+ dsch = msg_port_read(MEM_CTLR, DSCH);
+ dsch |= (BIT8 | BIT12);
+ msg_port_write(MEM_CTLR, DSCH, dsch);
+
+ /* Disable issuing the REF command */
+ drfc = msg_port_read(MEM_CTLR, DRFC);
+ drfc &= ~(BIT12 | BIT13 | BIT14);
+ msg_port_write(MEM_CTLR, DRFC, drfc);
+
+ /* Disable ZQ calibration short */
+ dcal = msg_port_read(MEM_CTLR, DCAL);
+ dcal &= ~(BIT8 | BIT9 | BIT10);
+ dcal &= ~(BIT12 | BIT13);
+ 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 |= BIT0;
+ if (mrc_params->rank_enables & 2)
+ drp |= BIT1;
+ 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, BIT16, BIT16);
+
+ /* 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 ? BIT12 : 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 & (BIT1 | BIT0);
+ 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)),
+ ~BIT20, BIT20); /* SPID_INIT_COMPLETE=0 */
+ /* Deassert IOBUFACT */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ ~BIT2, BIT2); /* IOBUFACTRST_N=0 */
+ /* Disable WRPTR */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPTRREG + (ch * DDRIOCCC_CH_OFFSET)),
+ ~BIT0, BIT0); /* WRPTRENABLE=0 */
+ }
+ }
+
+ /* Put PHY in reset */
+ mrc_alt_write_mask(DDRPHY, MASTERRSTN, 0, BIT0);
+
+ /* 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) ? (0x00) : (BIT22)), (BIT22));
+
+ /* 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), (BIT6 | BIT5));
+ /* ODT strength */
+ mrc_alt_write_mask(DDRPHY,
+ (B1RXIOBUFCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (temp << 5), (BIT6 | BIT5));
+
+ /* 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,
+ (BIT28 | BIT27 | BIT26 | BIT25 | BIT24 |
+ BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+ BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+ 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,
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT13 | BIT12 | BIT11 | BIT10 |
+ BIT9 | BIT8));
+ /* On Duration: ODT, DIFFAMP */
+ mrc_alt_write_mask(DDRPHY,
+ (B1ONDURCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ temp,
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT13 | BIT12 | BIT11 | BIT10 |
+ BIT9 | BIT8));
+
+ 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,
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT15 | BIT14 | BIT13 | BIT12 |
+ BIT11 | BIT10));
+ /* Override: DIFFAMP, ODT */
+ mrc_alt_write_mask(DDRPHY,
+ (B1OVRCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ temp,
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT15 | BIT14 | BIT13 | BIT12 |
+ BIT11 | BIT10));
+
+ /* 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)),
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT12 | BIT11 | BIT10 | BIT9 |
+ BIT8 | BIT4 | BIT3 | BIT2 | BIT1 |
+ BIT0));
+ mrc_alt_write_mask(DDRPHY,
+ (B1LATCTL0 +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (((cas + 7) << 16) | ((cas - 4) << 8) |
+ ((cwl - 2) << 0)),
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT12 | BIT11 | BIT10 | BIT9 |
+ BIT8 | BIT4 | BIT3 | BIT2 | BIT1 |
+ BIT0));
+
+ /* RCVEN Bypass (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ (B0RXIOBUFCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ ((0x0 << 7) | (0x0 << 0)),
+ (BIT7 | BIT0));
+ mrc_alt_write_mask(DDRPHY,
+ (B1RXIOBUFCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ ((0x0 << 7) | (0x0 << 0)),
+ (BIT7 | BIT0));
+
+ /* TX */
+ mrc_alt_write_mask(DDRPHY,
+ (DQCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (BIT16), (BIT16));
+ mrc_alt_write_mask(DDRPHY,
+ (B01PTRCTL1 +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (BIT8), (BIT8));
+
+ /* 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)),
+ (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 |
+ BIT2 | BIT1 | BIT0));
+ /* 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)),
+ (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 |
+ BIT2 | BIT1 | BIT0));
+ /* Per-Bit De-Skew Enable */
+ mrc_alt_write_mask(DDRPHY,
+ (B0RXIOBUFCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (0), (BIT4));
+ /* Per-Bit De-Skew Enable */
+ mrc_alt_write_mask(DDRPHY,
+ (B1RXIOBUFCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (0), (BIT4));
+ }
+
+ /* CLKEBB */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDOBSCKEBBCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ 0, (BIT23));
+
+ /* Enable tristate control of cmd/address bus */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ 0, (BIT1 | BIT0));
+
+ /* ODT RCOMP */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDRCOMPODT + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x03 << 5) | (0x03 << 0)),
+ (BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 |
+ BIT3 | BIT2 | BIT1 | BIT0));
+
+ /* CMDPM* registers must be programmed in this order */
+
+ /* Turn On Delays: SFR (regulator), MPLL */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPMDLYREG4 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0xFFFFU << 16) | (0xFFFF << 0)),
+ 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)),
+ ((0xFU << 28) | (0xFFF << 16) | (0xF << 12) |
+ (0x616 << 0)), 0xFFFFFFFF);
+ /* MPLL Divider Reset Delays */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPMDLYREG2 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0xFFU << 24) | (0xFF << 16) | (0xFF << 8) |
+ (0xFF << 0)), 0xFFFFFFFF);
+ /* Turn Off Delays: VREG, Staggered MDLL, MDLL, PI */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPMDLYREG1 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0xFFU << 24) | (0xFF << 16) | (0xFF << 8) |
+ (0xFF << 0)), 0xFFFFFFFF);
+ /* Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPMDLYREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0xFFU << 24) | (0xFF << 16) | (0xFF << 8) |
+ (0xFF << 0)), 0xFFFFFFFF);
+ /* Allow PUnit signals */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPMCONFIG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x6 << 8) | BIT6 | (0x4 << 0)),
+ (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 |
+ BIT25 | BIT24 | BIT23 | BIT22 | BIT21 | BIT11 |
+ BIT10 | BIT9 | BIT8 | BIT6 | BIT3 | BIT2 |
+ BIT1 | BIT0));
+ /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x3 << 4) | (0x7 << 0)),
+ (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 |
+ BIT0));
+
+ /* CLK-CTL */
+ mrc_alt_write_mask(DDRPHY,
+ (CCOBSCKEBBCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ 0, BIT24); /* CLKEBB */
+ /* Buffer Enable: CS,CKE,ODT,CLK */
+ mrc_alt_write_mask(DDRPHY,
+ (CCCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x0 << 16) | (0x0 << 12) | (0x0 << 8) |
+ (0xF << 4) | BIT0),
+ (BIT19 | BIT18 | BIT17 | BIT16 | BIT15 | BIT14 |
+ BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT7 | BIT6 | BIT5 | BIT4 | BIT0));
+ /* ODT RCOMP */
+ mrc_alt_write_mask(DDRPHY,
+ (CCRCOMPODT + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x03 << 8) | (0x03 << 0)),
+ (BIT12 | BIT11 | BIT10 | BIT9 | BIT8 | BIT4 |
+ BIT3 | BIT2 | BIT1 | BIT0));
+ /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
+ mrc_alt_write_mask(DDRPHY,
+ (CCMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x3 << 4) | (0x7 << 0)),
+ (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 |
+ BIT0));
+
+ /*
+ * 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)),
+ (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+ BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16));
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x0C << 24) | (0x03 << 16)),
+ (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+ BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16));
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x0F << 24) | (0x03 << 16)),
+ (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+ BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16));
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x08 << 24) | (0x03 << 16)),
+ (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+ BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16));
+ /* RCOMP Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CTLVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x0C << 24) | (0x03 << 16)),
+ (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+ BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16));
+
+ /* DQS Swapped Input Enable */
+ mrc_alt_write_mask(DDRPHY,
+ (COMPEN1CH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT19 | BIT17),
+ (BIT31 | BIT30 | BIT19 | BIT17 |
+ BIT15 | BIT14));
+
+ /* 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)),
+ (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+ /* ODT Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x32 << 8) | (0x03 << 0)),
+ (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+ /* ODT Vref PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x0E << 8) | (0x05 << 0)),
+ (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+
+ /*
+ * 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,
+ (BIT19 | BIT18 | BIT17 | BIT16 | BIT15 |
+ BIT14 | BIT13 | BIT12 | BIT11 | BIT10 |
+ BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 |
+ BIT3 | BIT2 | BIT1 | BIT0));
+ /* TCO Vref CLK,DQS,DQ */
+ mrc_alt_write_mask(DDRPHY,
+ (TCOVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x05 << 16) | (0x05 << 8) | (0x05 << 0)),
+ (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT13 | BIT12 | BIT11 | BIT10 |
+ BIT9 | BIT8 | BIT5 | BIT4 | BIT3 | BIT2 |
+ BIT1 | BIT0));
+ /* ODTCOMP CMD/CTL PU/PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CCBUFODTCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ((0x03 << 8) | (0x03 << 0)),
+ (BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+ BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+ /* COMP */
+ mrc_alt_write_mask(DDRPHY,
+ (COMPEN0CH0 + (ch * DDRCOMP_CH_OFFSET)),
+ 0, (BIT31 | BIT30 | BIT8));
+
+#ifdef BACKUP_COMPS
+ /* DQ COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x10 << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x10 << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* ODTCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQODTPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* ODTCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQODTPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31), (BIT31));
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31), (BIT31));
+
+ /* DQS COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x10 << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x10 << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* ODTCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSODTPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* ODTCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSODTPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31), (BIT31));
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31), (BIT31));
+
+ /* CLK COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0C << 16)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0C << 16)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x07 << 16)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x07 << 16)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* ODTCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKODTPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* ODTCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKODTPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | (0x0B << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31), (BIT31));
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31), (BIT31));
+
+ /* CMD COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0D << 16)),
+ (BIT31 | BIT21 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0D << 16)),
+ (BIT31 | BIT21 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+
+ /* CTL COMP Overrides */
+ /* RCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CTLDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0D << 16)),
+ (BIT31 | BIT21 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* RCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CTLDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0D << 16)),
+ (BIT31 | BIT21 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CTLDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* DCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CTLDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x0A << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+#else
+ /* DQ TCOCOMP Overrides */
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x1F << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x1F << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+
+ /* DQS TCOCOMP Overrides */
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x1F << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (DQSTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x1F << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+
+ /* CLK TCOCOMP Overrides */
+ /* TCOCOMP PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x1F << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+ /* TCOCOMP PD */
+ mrc_alt_write_mask(DDRPHY,
+ (CLKTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+ (BIT31 | (0x1F << 16)),
+ (BIT31 | BIT20 | BIT19 |
+ BIT18 | BIT17 | BIT16));
+#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), (BIT30), (BIT30));
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANADRVPDCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CMDANADRVPUCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CMDANADRVPDCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANADRVPUCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANADRVPDCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANADRVPUCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANADRVPDCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CTLANADRVPUCTL), (BIT30), (BIT30));
+ /* RCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CTLANADRVPDCTL), (BIT30), (BIT30));
+ /* ODT: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANAODTPUCTL), (BIT30), (BIT30));
+ /* ODT: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANAODTPDCTL), (BIT30), (BIT30));
+ /* ODT: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANAODTPUCTL), (BIT30), (BIT30));
+ /* ODT: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANAODTPDCTL), (BIT30), (BIT30));
+ /* ODT: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANAODTPUCTL), (BIT30), (BIT30));
+ /* ODT: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANAODTPDCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANADLYPUCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANADLYPDCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CMDANADLYPUCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CMDANADLYPDCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANADLYPUCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANADLYPDCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANADLYPUCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANADLYPDCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CTLANADLYPUCTL), (BIT30), (BIT30));
+ /* DCOMP: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CTLANADLYPDCTL), (BIT30), (BIT30));
+ /* TCO: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANATCOPUCTL), (BIT30), (BIT30));
+ /* TCO: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQANATCOPDCTL), (BIT30), (BIT30));
+ /* TCO: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANATCOPUCTL), (BIT30), (BIT30));
+ /* TCO: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (CLKANATCOPDCTL), (BIT30), (BIT30));
+ /* TCO: Dither PU Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANATCOPUCTL), (BIT30), (BIT30));
+ /* TCO: Dither PD Enable */
+ mrc_alt_write_mask(DDRPHY, (DQSANATCOPDCTL), (BIT30), (BIT30));
+ /* TCOCOMP: Pulse Count */
+ mrc_alt_write_mask(DDRPHY, (TCOCNTCTRL), (0x1 << 0), (BIT1 | BIT0));
+ /* ODT: CMD/CTL PD/PU */
+ mrc_alt_write_mask(DDRPHY,
+ (CHNLBUFSTATIC), ((0x03 << 24) | (0x03 << 16)),
+ (BIT28 | BIT27 | BIT26 | BIT25 | BIT24 |
+ BIT20 | BIT19 | BIT18 | BIT17 | BIT16));
+ /* Set 1us counter */
+ mrc_alt_write_mask(DDRPHY,
+ (MSCNTR), (0x64 << 0),
+ (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+ mrc_alt_write_mask(DDRPHY,
+ (LATCH1CTL), (0x1 << 28),
+ (BIT30 | BIT29 | BIT28));
+
+ /* Release PHY from reset */
+ mrc_alt_write_mask(DDRPHY, MASTERRSTN, BIT0, BIT0);
+
+ /* 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)),
+ (BIT13),
+ (BIT13)); /* Enable VREG */
+ delay_n(3);
+ }
+
+ /* ECC */
+ mrc_alt_write_mask(DDRPHY, (ECCMDLLCTL),
+ (BIT13), (BIT13)); /* Enable VREG */
+ delay_n(3);
+ /* CMD */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ (BIT13), (BIT13)); /* Enable VREG */
+ delay_n(3);
+ /* CLK-CTL */
+ mrc_alt_write_mask(DDRPHY,
+ (CCMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ (BIT13), (BIT13)); /* 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)),
+ (BIT17),
+ (BIT17)); /* Enable MCDLL */
+ delay_n(50);
+ }
+
+ /* ECC */
+ mrc_alt_write_mask(DDRPHY, (ECCMDLLCTL),
+ (BIT17), (BIT17)); /* Enable MCDLL */
+ delay_n(50);
+ /* CMD */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ (BIT18), (BIT18)); /* Enable MCDLL */
+ delay_n(50);
+ /* CLK-CTL */
+ mrc_alt_write_mask(DDRPHY,
+ (CCMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+ (BIT18), (BIT18)); /* 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)) ?
+ ((0x1 << 12) | (0x1 << 8) |
+ (0xF << 4) | (0xF << 0)) :
+ ((0xF << 12) | (0xF << 8) |
+ (0xF << 4) | (0xF << 0));
+#else
+ temp = ((0xF << 12) | (0xF << 8) |
+ (0xF << 4) | (0xF << 0));
+#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)),
+ (BIT3 | BIT2 | BIT1 | BIT0),
+ (BIT3 | BIT2 | BIT1 | BIT0));
+ delay_n(3);
+ /* Enable RXDLL Overrides BL0 */
+ mrc_alt_write_mask(DDRPHY,
+ (B0OVRCTL +
+ (bl_grp * DDRIODQ_BL_OFFSET) +
+ (ch * DDRIODQ_CH_OFFSET)),
+ (BIT3 | BIT2 | BIT1 | BIT0),
+ (BIT3 | BIT2 | BIT1 | BIT0));
+ }
+
+ /* ECC */
+ temp = ((0xF << 12) | (0xF << 8) |
+ (0xF << 4) | (0xF << 0));
+ 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) ? (0x3) : (0x1),
+ (BIT3 | BIT2 | BIT1 | BIT0));
+ }
+
+ mrc_alt_write_mask(DDRPHY,
+ (ECCCLKALIGNREG2 + (ch * DDRIODQ_CH_OFFSET)),
+ 0x2,
+ (BIT3 | BIT2 | BIT1 | BIT0));
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCLKALIGNREG2 + (ch * DDRIODQ_CH_OFFSET)),
+ 0x0,
+ (BIT3 | BIT2 | BIT1 | BIT0));
+ mrc_alt_write_mask(DDRPHY,
+ (CCCLKALIGNREG2 + (ch * DDRIODQ_CH_OFFSET)),
+ 0x2,
+ (BIT3 | BIT2 | BIT1 | BIT0));
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCLKALIGNREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ (0x2 << 4), (BIT5 | BIT4));
+ /*
+ * 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)),
+ (BIT22 | BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+ BIT16 | BIT14 | BIT13 | BIT12 | BIT11 | BIT10 |
+ BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 |
+ BIT2 | BIT1 | BIT0));
+ /* TOTAL_NUM_MODULES, FIRST_U_PARTITION */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCLKALIGNREG2 + (ch * DDRIOCCC_CH_OFFSET)),
+ ((0x10 << 16) | (0x4 << 8) | (0x2 << 4)),
+ (BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+ BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 |
+ BIT5 | BIT4));
+#ifdef HMC_TEST
+ /* START_CLK_ALIGN=1 */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCLKALIGNREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ BIT24, BIT24);
+ while (msg_port_alt_read(DDRPHY,
+ (CMDCLKALIGNREG0 + (ch * DDRIOCCC_CH_OFFSET))) &
+ BIT24)
+ ; /* wait for START_CLK_ALIGN=0 */
+#endif
+
+ /* Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPTRREG + (ch * DDRIOCCC_CH_OFFSET)),
+ BIT0, BIT0); /* WRPTRENABLE=1 */
+
+ /* COMP initial */
+ /* enable bypass for CLK buffer (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ (COMPEN0CH0 + (ch * DDRCOMP_CH_OFFSET)),
+ BIT5, BIT5);
+ /* Initial COMP Enable */
+ mrc_alt_write_mask(DDRPHY, (CMPCTRL),
+ (BIT0), (BIT0));
+ /* wait for Initial COMP Enable = 0 */
+ while (msg_port_alt_read(DDRPHY, (CMPCTRL)) & BIT0)
+ ;
+ /* disable bypass for CLK buffer (PO) */
+ mrc_alt_write_mask(DDRPHY,
+ (COMPEN0CH0 + (ch * DDRCOMP_CH_OFFSET)),
+ ~BIT5, BIT5);
+
+ /* IOBUFACT */
+
+ /* STEP4a */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ BIT2, BIT2); /* IOBUFACTRST_N=1 */
+
+ /* DDRPHY initialization complete */
+ mrc_alt_write_mask(DDRPHY,
+ (CMDPMCONFIG0 + (ch * DDRIOCCC_CH_OFFSET)),
+ BIT20, BIT20); /* 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, BIT1, (BIT8 | BIT1));
+
+ /* Assert RESET# for 200us */
+ delay_u(200);
+
+ /* DDR3_RESET_SET=1, DDR3_RESET_RESET=0 */
+ mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, BIT8, (BIT8 | BIT1));
+
+ 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 |= (BIT4 | 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 ? BIT12 : 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 &= ~BIT6;
+
+ if (mrc_params->ron_value == 0)
+ emrs1_cmd |= BIT7;
+ else
+ emrs1_cmd &= ~BIT7;
+
+ 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 |= BIT14;
+ mrs0_cmd |= BIT18;
+ 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 &= ~BIT28;
+ dco |= BIT31;
+ 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 |= BIT12;
+ 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, BIT8);
+ }
+ /* 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)),
+ BIT8, BIT8);
+ }
+#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, 0x0082));
+
+ /*
+ * set ODT DRAM Full Time Termination
+ * disable in MCU
+ */
+
+ dtr4 = msg_port_read(MEM_CTLR, DTR4);
+ dtr4_save = dtr4;
+ dtr4 |= BIT15;
+ 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),
+ (BIT28 | BIT8 | BIT6 | BIT4 | BIT2),
+ (BIT28 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+ }
+
+ /* Write Leveling Mode enabled in IO */
+ mrc_alt_write_mask(DDRPHY,
+ CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * ch),
+ BIT16, BIT16);
+
+ /* 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, BIT16);
+
+ 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),
+ (BIT8 | BIT6 | BIT4 | BIT2),
+ (BIT28 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+ }
+
+ /* 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 &= ~(BIT16 | BIT17 | BIT18);
+ dpmc0 |= (4 << 16);
+ dpmc0 |= BIT21;
+ 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 &= ~(BIT8 | BIT9 | BIT12);
+ msg_port_write(MEM_CTLR, DSCH, dsch);
+
+ dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+ dpmc0 &= ~BIT25;
+ dpmc0 |= (mrc_params->power_down_disable << 25);
+ dpmc0 &= ~BIT24;
+ dpmc0 &= ~(BIT16 | BIT17 | BIT18);
+ dpmc0 |= (4 << 16);
+ dpmc0 |= BIT21;
+ msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+ /* CMDTRIST = 2h - CMD/ADDR are tristated when no valid command */
+ mrc_write_mask(MEM_CTLR, DPMC1, 2 << 4, BIT4 | BIT5);
+
+ 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 &= ~BIT31;
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ drp = 0;
+ if (mrc_params->rank_enables & 1)
+ drp |= BIT0;
+ if (mrc_params->rank_enables & 2)
+ drp |= BIT1;
+ 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 &= ~BIT28;
+ dco |= BIT31;
+ 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 &= ~(BIT12 | BIT13 | BIT14);
+ drfc |= (mrc_params->refresh_rate << 12);
+ drfc |= BIT21;
+ msg_port_write(MEM_CTLR, DRFC, drfc);
+
+ dcal = msg_port_read(MEM_CTLR, DCAL);
+ dcal &= ~(BIT8 | BIT9 | BIT10);
+ dcal |= (3 << 8); /* 63ms */
+ msg_port_write(MEM_CTLR, DCAL, dcal);
+
+ dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+ dpmc0 |= (BIT23 | BIT29);
+ 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, BIT1, BIT1);
+
+ /* 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)),
+ (0x00 << 16) | (temp << 10),
+ (BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16 | BIT15 | BIT14 |
+ BIT13 | BIT12 | BIT11 | BIT10));
+
+ /* Override: DIFFAMP, ODT */
+ mrc_alt_write_mask(DDRPHY,
+ (B1OVRCTL + (bl * DDRIODQ_BL_OFFSET) +
+ (channel * DDRIODQ_CH_OFFSET)),
+ (0x00 << 16) | (temp << 10),
+ (BIT21 | BIT20 | BIT19 | BIT18 |
+ BIT17 | BIT16 | BIT15 | BIT14 |
+ BIT13 | BIT12 | BIT11 | BIT10));
+ }
+
+ /* 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 &= ~(BIT14 | BIT15);
+ drp |= BIT15;
+ drp |= BIT13;
+ msg_port_write(MEM_CTLR, DRP, drp);
+
+ /* Disable new request bypass */
+ dsch = msg_port_read(MEM_CTLR, DSCH);
+ dsch |= BIT12;
+ msg_port_write(MEM_CTLR, DSCH, dsch);
+
+ /* Enable ECC */
+ ecc_ctrl = (BIT0 | BIT1 | BIT17);
+ 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 &= ~(BIT28 | BIT29);
+ dco |= (BIT0 | BIT8);
+ msg_port_write(MEM_CTLR, DCO, dco);
+
+ LEAVEFN();
+}
diff --git a/arch/x86/cpu/quark/smc.h b/arch/x86/cpu/quark/smc.h
new file mode 100644
index 0000000000..46017a1ccb
--- /dev/null
+++ b/arch/x86/cpu/quark/smc.h
@@ -0,0 +1,446 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#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
+
+/* 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) | (BIT10 << 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) | (BIT10 << 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/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig
index f6b52010c3..397e599f93 100644
--- a/arch/x86/cpu/queensbay/Kconfig
+++ b/arch/x86/cpu/queensbay/Kconfig
@@ -11,44 +11,6 @@ config INTEL_QUEENSBAY
if INTEL_QUEENSBAY
-config HAVE_FSP
- bool "Add an Firmware Support Package binary"
- help
- Select this option to add an Firmware Support Package binary to
- the resulting U-Boot image. It is a binary blob which U-Boot uses
- to set up SDRAM and other chipset specific initialization.
-
- Note: Without this binary U-Boot will not be able to set up its
- SDRAM so will not boot.
-
-config FSP_FILE
- string "Firmware Support Package binary filename"
- depends on HAVE_FSP
- default "fsp.bin"
- help
- The filename of the file to use as Firmware Support Package binary
- in the board directory.
-
-config FSP_ADDR
- hex "Firmware Support Package binary location"
- depends on HAVE_FSP
- default 0xfffc0000
- help
- FSP is not Position Independent Code (PIC) and the whole FSP has to
- be rebased if it is placed at a location which is different from the
- perferred base address specified during the FSP build. Use Intel's
- Binary Configuration Tool (BCT) to do the rebase.
-
- The default base address of 0xfffc0000 indicates that the binary must
- be located at offset 0xc0000 from the beginning of a 1MB flash device.
-
-config FSP_TEMP_RAM_ADDR
- hex
- default 0x2000000
- help
- Stack top address which is used in FspInit after DRAM is ready and
- CAR is disabled.
-
config HAVE_CMC
bool "Add a Chipset Micro Code state machine binary"
help
diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile
index 2c2ec01ed2..d8761fdfbd 100644
--- a/arch/x86/cpu/queensbay/Makefile
+++ b/arch/x86/cpu/queensbay/Makefile
@@ -4,6 +4,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y += tnc_car.o tnc_dram.o tnc.o topcliff.o
-obj-y += fsp_configs.o fsp_support.o
+obj-y += fsp_configs.o
+obj-y += tnc.o topcliff.o
obj-$(CONFIG_PCI) += tnc_pci.o
diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c
index af28e457f6..78bc966bbd 100644
--- a/arch/x86/cpu/queensbay/fsp_configs.c
+++ b/arch/x86/cpu/queensbay/fsp_configs.c
@@ -6,7 +6,7 @@
*/
#include <common.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
void update_fsp_upd(struct upd_region *fsp_upd)
{
diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 8637cdca2d..30ab725bb9 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -9,7 +9,7 @@
#include <asm/pci.h>
#include <asm/post.h>
#include <asm/arch/tnc.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
#include <asm/processor.h>
static void unprotect_spi_flash(void)
@@ -43,30 +43,3 @@ int arch_cpu_init(void)
return 0;
}
-
-int print_cpuinfo(void)
-{
- post_code(POST_CPU_INFO);
- return default_print_cpuinfo();
-}
-
-void reset_cpu(ulong addr)
-{
- /* cold reset */
- outb(0x06, PORT_RESET);
-}
-
-void board_final_cleanup(void)
-{
- u32 status;
-
- /* call into FspNotify */
- debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
- status = fsp_notify(NULL, INIT_PHASE_BOOT);
- if (status != FSP_SUCCESS)
- debug("fail, error code %x\n", status);
- else
- debug("OK\n");
-
- return;
-}
diff --git a/arch/x86/cpu/queensbay/tnc_pci.c b/arch/x86/cpu/queensbay/tnc_pci.c
index 39bff49c8d..6c291f9ee9 100644
--- a/arch/x86/cpu/queensbay/tnc_pci.c
+++ b/arch/x86/cpu/queensbay/tnc_pci.c
@@ -7,7 +7,7 @@
#include <common.h>
#include <pci.h>
#include <asm/pci.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -44,18 +44,3 @@ void board_pci_setup_hose(struct pci_controller *hose)
hose->region_count = 4;
}
-
-int board_pci_post_scan(struct pci_controller *hose)
-{
- u32 status;
-
- /* call into FspNotify */
- debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
- status = fsp_notify(NULL, INIT_PHASE_PCI);
- if (status != FSP_SUCCESS)
- debug("fail, error code %x\n", status);
- else
- debug("OK\n");
-
- return 0;
-}
diff --git a/arch/x86/cpu/queensbay/topcliff.c b/arch/x86/cpu/queensbay/topcliff.c
index b01422a965..9faf1b92bb 100644
--- a/arch/x86/cpu/queensbay/topcliff.c
+++ b/arch/x86/cpu/queensbay/topcliff.c
@@ -5,43 +5,16 @@
*/
#include <common.h>
-#include <errno.h>
-#include <malloc.h>
-#include <pci.h>
+#include <mmc.h>
#include <pci_ids.h>
-#include <sdhci.h>
static struct pci_device_id mmc_supported[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1 },
- { }
};
int cpu_mmc_init(bd_t *bis)
{
- struct sdhci_host *mmc_host;
- pci_dev_t devbusfn;
- u32 iobase;
- int ret;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mmc_supported); i++) {
- devbusfn = pci_find_devices(mmc_supported, i);
- if (devbusfn == -1)
- return -ENODEV;
-
- mmc_host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
- if (!mmc_host)
- return -ENOMEM;
-
- mmc_host->name = "Topcliff SDHCI";
- pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
- mmc_host->ioaddr = (void *)iobase;
- mmc_host->quirks = 0;
- ret = add_sdhci(mmc_host, 0, 0);
- if (ret)
- return ret;
- }
-
- return 0;
+ return pci_mmc_init("Topcliff SDHCI", mmc_supported,
+ ARRAY_SIZE(mmc_supported));
}
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 97ed884288..7a66133555 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -1,5 +1,7 @@
dtb-y += chromebook_link.dtb \
- crownbay.dtb
+ crownbay.dtb \
+ galileo.dtb \
+ minnowmax.dtb
targets += $(dtb-y)
diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts
new file mode 100644
index 0000000000..66af64abda
--- /dev/null
+++ b/arch/x86/dts/galileo.dts
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/mrc/quark.h>
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Intel Galileo";
+ compatible = "intel,galileo", "intel,quark";
+
+ config {
+ silent_console = <0>;
+ };
+
+ chosen {
+ stdout-path = &pciuart0;
+ };
+
+ mrc {
+ compatible = "intel,quark-mrc";
+ flags = <MRC_FLAG_SCRAMBLE_EN>;
+ dram-width = <DRAM_WIDTH_X8>;
+ dram-speed = <DRAM_FREQ_800>;
+ dram-type = <DRAM_TYPE_DDR3>;
+ rank-mask = <DRAM_RANK(0)>;
+ chan-mask = <DRAM_CHANNEL(0)>;
+ chan-width = <DRAM_CHANNEL_WIDTH_X16>;
+ addr-mode = <DRAM_ADDR_MODE0>;
+ refresh-rate = <DRAM_REFRESH_RATE_785US>;
+ sr-temp-range = <DRAM_SRT_RANGE_NORMAL>;
+ ron-value = <DRAM_RON_34OHM>;
+ rtt-nom-value = <DRAM_RTT_NOM_120OHM>;
+ rd-odt-value = <DRAM_RD_ODT_OFF>;
+ dram-density = <DRAM_DENSITY_1G>;
+ dram-cl = <6>;
+ dram-ras = <0x0000927c>;
+ dram-wtr = <0x00002710>;
+ dram-rrd = <0x00002710>;
+ dram-faw = <0x00009c40>;
+ };
+
+ pci {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "intel,pci";
+ device_type = "pci";
+
+ pciuart0: uart@14,5 {
+ compatible = "pci8086,0936.00",
+ "pci8086,0936",
+ "pciclass,070002",
+ "pciclass,0700",
+ "x86-uart";
+ reg = <0x0000a500 0x0 0x0 0x0 0x0
+ 0x0200a510 0x0 0x0 0x0 0x0>;
+ reg-shift = <2>;
+ clock-frequency = <44236800>;
+ current-speed = <115200>;
+ };
+ };
+
+ gpioa {
+ compatible = "intel,ich6-gpio";
+ u-boot,dm-pre-reloc;
+ reg = <0 0x20>;
+ bank-name = "A";
+ };
+
+ gpiob {
+ compatible = "intel,ich6-gpio";
+ u-boot,dm-pre-reloc;
+ reg = <0x20 0x20>;
+ bank-name = "B";
+ };
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ich-spi";
+ spi-flash@0 {
+ #size-cells = <1>;
+ #address-cells = <1>;
+ reg = <0>;
+ compatible = "winbond,w25q64", "spi-flash";
+ memory-map = <0xff800000 0x00800000>;
+ };
+ };
+
+};
diff --git a/arch/x86/dts/microcode/m0130673322.dtsi b/arch/x86/dts/microcode/m0130673322.dtsi
new file mode 100644
index 0000000000..90bf2fb712
--- /dev/null
+++ b/arch/x86/dts/microcode/m0130673322.dtsi
@@ -0,0 +1,3284 @@
+/*
+ * ---
+ * This is a device tree fragment. Use #include to add these properties to a
+ * node.
+ *
+ * Date:
+ */
+
+compatible = "intel,microcode";
+intel,header-version = <1>;
+intel,update-revision = <0x322>;
+intel,date-code = <0x4012014>;
+intel,processor-signature = <0x30673>;
+intel,checksum = <0x17b0d914>;
+intel,loader-revision = <1>;
+intel,processor-flags = <0x1>;
+
+/* The first 48-bytes are the public header which repeats the above data */
+data = <
+ 0x01000000 0x22030000 0x14200104 0x73060300
+ 0x14d9b017 0x01000000 0x01000000 0xd0cb0000
+ 0x00cc0000 0x00000000 0x00000000 0x00000000
+ 0x00000000 0xa1000000 0x01000200 0x22030000
+ 0x00000000 0x00000000 0x31031420 0x11320000
+ 0x01000000 0x73060300 0x00000000 0x00000000
+ 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x00000000 0xf4320000 0x00000000 0x00000000
+ 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x0ae10178 0x7c98f9d1 0x41962d85 0x19391270
+ 0xcf3c0336 0xc1f13d6f 0xe46abaf6 0x3b65ca6b
+ 0xdb666815 0x5a17bfc4 0x4fca009d 0x099ae8b3
+ 0x198e2c7d 0x7c665bbf 0xc07a1a7a 0x7dbcee26
+ 0x867296b2 0xc885b6ce 0xe602baff 0x68544b14
+ 0xc928c400 0x3add156d 0x531946f9 0x92a03216
+ 0xda352322 0xd967ee1f 0x3c5170a7 0xf6de834e
+ 0x5a2ed8b3 0x9fb8f050 0x450de17f 0xfd5ef070
+ 0x4954575f 0xa3a071ab 0xb56e2afb 0xe2b48302
+ 0x6655a958 0x57c9a438 0x1b2f688a 0x09309bc4
+ 0x0be95612 0x529c1633 0xc48515d9 0x29eb78df
+ 0x9933409f 0xda58dea9 0x58c805fd 0xbc110f5a
+ 0x40780ec0 0x6ad59bb3 0xc7387fb8 0x591c1490
+ 0xf9335932 0x32130e0b 0xef4b3c96 0xacd903f2
+ 0x5b362539 0xe7f85529 0xcb17c41f 0xe7e440d8
+ 0xfaf7e925 0x969b76fb 0x5edab8c7 0xf00012e8
+ 0x121c2971 0xe5b18959 0xadfd07c0 0x1f09c9d7
+ 0x9781006a 0x39550073 0x6c438b6d 0x436f60bc
+ 0x11000000 0x8514b971 0x40df7b4a 0x6a6b7285
+ 0x7978ef59 0x319bddf5 0x04c68e5a 0xe1c28b10
+ 0x172f63dc 0x306fb95d 0x31d881e8 0x69f8e08d
+ 0x617a99e1 0x1ab6b574 0x2951fa5b 0xcc7e3e94
+ 0xff379d19 0x5c035dec 0xe28ed726 0x22b8a5ac
+ 0xd08b3ac5 0x45c03b9e 0xcea4083c 0xc26758aa
+ 0xbe7cf81e 0x43d898f3 0x5c45a635 0xc9cac095
+ 0xb89aea20 0x2c02b40e 0xe3a8b48d 0xeabfb60e
+ 0x776ed2a9 0x080ae6d5 0x7f64b1df 0x00e40ee6
+ 0x0f1c10f4 0x792e5423 0x787f5459 0x63a8b02c
+ 0x3fd6a255 0x049cae26 0x0949f5ff 0x9aebb236
+ 0xecc01775 0x91b57b84 0xe0e45ea3 0x5a8bf79e
+ 0x356a843a 0x2406795f 0x8aaae5d8 0x6a8c877c
+ 0xa8b2b8f4 0x04cf8f49 0x422d9e2c 0xf09f9896
+ 0xe9b92215 0x9c98fb44 0x88556b7f 0x519d6f4c
+ 0x9e8a016b 0xcb18d16c 0x419b4ee7 0x080b49c8
+ 0xc51b875e 0x46aabc9c 0x262d27eb 0x93ea189d
+ 0xdd0da69d 0x3e5b17e8 0xcc78509a 0x00b07e6e
+ 0x363d5a70 0x64572070 0x8a84abc4 0x1cb03838
+ 0x965fd76a 0x540aafc9 0x83a91654 0x1a722e67
+ 0x4bf98ce1 0x2b3c2ff9 0x972cebd4 0xf3a68395
+ 0x2613e422 0xf8d031d7 0xb1c79a0f 0xfd44f65b
+ 0xa7012a9b 0xd9a15a60 0xc311fc0c 0x6f52f878
+ 0x3d68381d 0xd2a035d7 0xb790c50e 0x9f1e5010
+ 0x41877064 0xa9d1e4ae 0xfe9abbd5 0x60c2c748
+ 0x8167e5ad 0x022dbfb3 0x75abe483 0x51c37170
+ 0x09b8590d 0xc1bb323d 0x2c7336b1 0xd4d0d49b
+ 0xc7f6152b 0x7919d596 0x1e1ff62e 0xc49604a0
+ 0x33857369 0xeaa3f382 0x98b8cd86 0x176e1bf3
+ 0x1a68867b 0x6af0a11c 0x69a82b25 0x48c72525
+ 0xa00aae2d 0xb09f67f4 0x1a99f83d 0x7266cca3
+ 0x8d03a7da 0x2e1d7c49 0x01ac68ae 0x93188770
+ 0x0609e769 0x982ed28d 0xe40999e0 0x8932ebab
+ 0x5637ad5a 0x2725e8ad 0x56d7caaf 0xc351faa2
+ 0x09dbd737 0x0d2f3bf0 0x0623330d 0xdd547489
+ 0xcca7e722 0xa9096d13 0x95b17818 0xc092cb81
+ 0x72c6eefc 0x1811c37e 0x78161497 0x8be0c4c6
+ 0xd63aeb19 0x91ab68df 0x8f2e5e4d 0xf4c74566
+ 0x7677a553 0x19698ac3 0xedca0620 0x77f32470
+ 0x031e011b 0x751f6696 0xb277d06e 0x3eae2742
+ 0x133e621a 0x38fa3172 0x9398cc1c 0xf42a507b
+ 0x4547d933 0x63a91eb0 0xf5bcf6a4 0x926ba056
+ 0x0adf5bce 0x140f53e4 0x7ff6bb5c 0x87dd79ba
+ 0xbba240ac 0x694f743d 0x709cdb20 0x5b4d4401
+ 0xc9693610 0x55f9f268 0x1142bc3f 0xf8fe3689
+ 0x04a93c4c 0x33dedc46 0xdc73c725 0x2f5ba264
+ 0x5b7a6a69 0x024b64f5 0x6e8bfa12 0x62bf2aa7
+ 0x520f5a07 0x3c7c4292 0xb7ad2613 0x1f78fc87
+ 0xd5284e4e 0x2c730f33 0x8861e947 0x8bacef7d
+ 0xbafa2608 0x14ed0b5b 0x3b9bfb02 0x24ced271
+ 0x002b2941 0x22d4431c 0x855f4248 0x5ec46e29
+ 0x6f1f42fb 0x5dd24fe0 0x290961f6 0xf392dbaf
+ 0xa1a8d9c2 0x61e18f4e 0xfda59a70 0x5498daa5
+ 0x5ae7ea6f 0xf058c635 0x6817ebee 0x8e30dc8b
+ 0x7c8d79be 0x5fb15b9b 0xeed64741 0xe2642a94
+ 0x680d7e6e 0x3cbad7aa 0x808c415f 0xe9323aa2
+ 0xaadf5b25 0xf60abf13 0xd5c47967 0xc248d0b3
+ 0x0f232cbd 0x84092449 0x5744384b 0x5e153ded
+ 0x8bb19817 0x34430271 0x917d2315 0x1fc790c7
+ 0xc21b5db6 0xec578b1f 0x903a286e 0xca0c59bc
+ 0x03e95c7a 0x8c659e99 0x7b09da0a 0xd61e7517
+ 0x90b1c519 0x8deac92c 0xf99c7bec 0xb6257d92
+ 0x3d61c16e 0xebd58be0 0xb470e655 0xa44bbf4f
+ 0xfebe5313 0x4662110a 0x5d42ccd9 0x140845ec
+ 0xc80329a9 0x915ca966 0x71e33828 0xe46c870a
+ 0x7da9a490 0x255544da 0xa20fb8df 0xf94062b3
+ 0xb2df5870 0xebf31e88 0x6e723e2f 0xe6ba9cf1
+ 0x7e7084c2 0x1782ac71 0x0a0b0127 0xe9234e38
+ 0x881356d6 0xb27a54b6 0x5594730e 0x9a14bd8f
+ 0x6dba7da9 0x1069e285 0x02a52798 0x61ea7d86
+ 0x665b2572 0x29d41eb5 0x1d211169 0x1218b345
+ 0xbfbd264c 0x5b8b0625 0xbbfdcf39 0x6768dfce
+ 0x0b5f10cb 0xe159414c 0x74356ed6 0x70077f49
+ 0x672107e8 0x11616856 0x824e6f2f 0x99614958
+ 0x5857305d 0x416a193f 0x010d266c 0xe5194f03
+ 0x152d6516 0xeb83872e 0x4923cc1f 0x1191d1ca
+ 0x23feb738 0x6817c1d7 0xe49129ed 0x4a53132a
+ 0xdb46b95b 0x3f970366 0x93f1a518 0xae8d72ae
+ 0xb689d915 0x0bdfda17 0x2ac7238d 0x1c4291e7
+ 0xc5b11085 0x3c51c1ba 0x9fd63edd 0xe464d740
+ 0xc17f2789 0x0adef6b9 0xf9aaf83e 0xfb2a9798
+ 0x7f16268b 0x4c8ca6c5 0x2b17be52 0x00c91157
+ 0xb69eb5db 0xe55ed94a 0xdf13b5a5 0xbb52d1e3
+ 0x651bb017 0xc7795724 0x0dfd4711 0x02d2d6e0
+ 0xc835e771 0x8ab5dd50 0x7caca109 0xd5c18d6e
+ 0xbef0e727 0xaff2dd07 0xf1062a32 0x26d14796
+ 0x97f6e36c 0xf845278e 0x185eb5b3 0xcde4e201
+ 0x13166ab7 0xcdcebcdc 0x143ef0c7 0x2349893f
+ 0x9dfcb70e 0x7ef72725 0x141c5b71 0x7da0f5d3
+ 0x76bebb67 0x28bc0a83 0xb67ecf0f 0xd60a1303
+ 0x9391b279 0x6ad41154 0x317896b0 0x1237efa6
+ 0x7b2a2e6c 0x3ad9a110 0xb44357d4 0xb32e39fe
+ 0x2358d28e 0x76e847d9 0x3e85db01 0x6c74e466
+ 0x9e4e6b32 0x13072a53 0x5972132e 0xd97cb04d
+ 0x55ee6a0b 0xc1434b92 0x772f6a1d 0x0f81f7a6
+ 0x072aa8f7 0x179da0e0 0x976bd78c 0x2e43c16b
+ 0x4f4a6b51 0x92d9c61b 0xa9c15fe4 0x3f8a527a
+ 0x3a232408 0x543d7957 0x21cbd682 0x896de3b0
+ 0xba6b3df6 0x2ec86e51 0x2be889e3 0xae764ff0
+ 0x3a2f0003 0x7a5f7949 0x577fb5ce 0xb5cbd1a6
+ 0xc910ffe2 0x7fd76712 0xfc1e93ff 0xbee7b15c
+ 0x5db2356d 0x9721a3fd 0x0d408aed 0x4df4c922
+ 0x45d5be91 0x6c79b1fc 0xf0bf73bd 0x3f6a73b6
+ 0xdcc1b51e 0x2049fe2d 0xf2b2ad4b 0xd0484d3a
+ 0x1f097d3f 0xced1bf3d 0x10f4416b 0x73cb307c
+ 0x4b4d94b4 0x2918ece0 0x0cfe69f3 0xb7e86cfb
+ 0xa6c373b4 0x0d862b62 0x1735cd72 0xef23c127
+ 0x09809c16 0x86cfb70b 0xe67c6903 0x743223a7
+ 0x13c7d27f 0xb70a58cc 0x82c57566 0x2ead3c65
+ 0xf9409863 0xf2b578ef 0x1622a34d 0x5ae8e861
+ 0xf4384016 0x443ff5f4 0x088b8510 0xd738d1c5
+ 0x577d624b 0x5adf3973 0x5f79add3 0xed7e7145
+ 0x29008fc0 0xd5b278cf 0x5b4c08c2 0xb063af5c
+ 0x67d41bd9 0x2d11424a 0x727924de 0x8903a86f
+ 0xb122d314 0xd9675c8b 0xc2eb1382 0x4c4185da
+ 0x257a0fe1 0xc3fd536b 0xadbfc223 0xc940dab4
+ 0x2e83d4b0 0xf1135ad4 0xfeb1cc1a 0x9178ae04
+ 0x996d72ba 0x07f6bf0f 0x6588f833 0x44f95205
+ 0xee4e6897 0xa9006735 0xa5f5502c 0xeb61aca6
+ 0xf2ceddb5 0x40ef9001 0xf862c3d7 0x73deaad3
+ 0x7b1d8b1d 0x467bcbcf 0x7f76f969 0x6c8e7f8c
+ 0xfb8e27c3 0x5075ce65 0x1c8628a8 0x7b6e3e32
+ 0x4885fc9f 0xa9fa768c 0x15426120 0x1df9d006
+ 0x31c52df4 0x1457f5c6 0xde5f2daa 0xfa250108
+ 0xbcf7e460 0x565d4679 0x82c94142 0xae76342a
+ 0x85aca7c7 0x8bc49e03 0x73f03da3 0x1e500b4c
+ 0x250288a2 0x25a39951 0x66087700 0x6317754b
+ 0x6ff62bdc 0xa519ad4f 0xa537b8ac 0xea6292ab
+ 0xb5d66b68 0x15997d1f 0x0fdbf04a 0xaa2b1a25
+ 0x74b72321 0xf8b1753a 0x33658d1e 0xb1cc5d96
+ 0x5b0da6af 0x48f24997 0xb031146e 0xfe98e8d1
+ 0x9bd75bf0 0x0ae088fe 0xb8fce721 0x964bc398
+ 0xe82daef6 0x393884b5 0xa814f792 0xb3667bde
+ 0x1d1cf32d 0xce862720 0x7b69e921 0xabd26f33
+ 0x61fad35f 0xd7144eeb 0x74016bce 0x1d56277b
+ 0x7f934eed 0xb1a3396a 0xd5090c7a 0x4ea94d12
+ 0x1455ac10 0x7c37294c 0x06c60a9a 0xa735ab29
+ 0xbffb880f 0x59e2cb48 0x54cca9d7 0xb569da05
+ 0x595e72ec 0x7c82f204 0x7690420d 0xe02fbb37
+ 0x4dbf4e68 0x221eda99 0x31868046 0xda435487
+ 0xb4c0dcc4 0x37610096 0x35569b02 0xefcd4ecf
+ 0x7b6917bf 0x45946a25 0x5d42a84a 0x8c3801b7
+ 0x5ac838fa 0x7a7f252d 0xbccf3cb5 0x99a54c4c
+ 0x39145831 0xfd5c1af3 0xcabb180c 0x8f0fe9dd
+ 0xabd42357 0x3b6d9aa9 0x0e87ede1 0x65ea46ae
+ 0xd89b618e 0x1e5cc772 0xfb43c9b4 0xdad3fdb2
+ 0x96be6600 0x4887696e 0x82a4e73a 0xb2ca2cf0
+ 0xc6840738 0x397d27a9 0xce971271 0x067e4de6
+ 0xb593f079 0x6a77de2f 0xf9a92497 0xdc3e94aa
+ 0x03239a80 0x7f38430a 0xf7f87908 0x682a8425
+ 0x2d491962 0xb5737b4b 0xa26434e5 0x238ced20
+ 0x1ed9fcbe 0x283a8f7b 0x18f33cf6 0x29f27cd5
+ 0xd95018aa 0x883dbd25 0xfb216723 0xe939d42c
+ 0xf4b1207d 0x54f5e102 0xbe2e46eb 0xb2ca8219
+ 0xab181ad4 0x3a7dc3e6 0xf3713256 0x53f081ab
+ 0xd630a7a3 0x07c40bc3 0x7a1fde0c 0xb368bab8
+ 0xc0baaad3 0xf070baac 0xe4ab7a4f 0x82a8cf5e
+ 0x9c3d7bb5 0xfe5f74a3 0x02548e86 0x2710ff5d
+ 0x1b42a8c4 0x34d4f5d8 0x8dfde8f2 0xf2949298
+ 0xe9d711bf 0x44d91e17 0x51ba8b32 0xbc3f60cc
+ 0xa0d6c440 0xf71959b4 0x3b5f0603 0x02465794
+ 0xff5d9b8a 0xd4a4abcf 0x8123626c 0x883ed4e4
+ 0x9eaeaa09 0x91c38865 0xa0aaeebf 0xc48983ab
+ 0x1df7a001 0x7519a65e 0x5ef3cd1d 0x8348225d
+ 0x0f318b0b 0xbab1d51b 0x15ba9b84 0xef8c57bf
+ 0x15d0a8c1 0x0b542fb4 0x1d51ccc8 0x6c297041
+ 0xf3bee946 0x6a8c3d64 0x6e16361d 0xed50ca69
+ 0x8c1f66ba 0xff7220e0 0x84a87cba 0x15d75922
+ 0x77546d82 0x7bd456e3 0x10166195 0x55604f1f
+ 0x894280d2 0x0ed406c4 0xc1b4058e 0x645252e5
+ 0x670ea74e 0xd5b07337 0x9944e2cf 0xf2ac2579
+ 0xd00c3ae8 0x2df3146d 0x4ee1c72a 0x3a3621cf
+ 0x8c099145 0xf5f530e6 0x210da136 0x7908cec6
+ 0xc6e47e22 0xe9bcbe4e 0x94cbcb12 0xb81f0792
+ 0x1111f81e 0x4df4ac93 0x335c69be 0x9e3546b9
+ 0x06c046b4 0x6f29a99c 0xbcd48ee7 0xeb011efe
+ 0x41e80474 0xcee30bf4 0xad4e2ae0 0x6929a359
+ 0xbdaa88e3 0x9e68a38e 0x16bbdac7 0x020d8d61
+ 0x7bab6738 0x559cddbd 0xa6ae3d0c 0xe032c355
+ 0xcb45a045 0x9f7680b2 0xc1cb73da 0x466052f7
+ 0x488cb929 0xd93f0307 0xb2c9d81c 0xe25fdcd9
+ 0xfe8b08c4 0xae6230bd 0x5238b335 0x3474b2a5
+ 0x480ce0b7 0xd9a2942f 0xe830fa5b 0x3efa774f
+ 0x84e53e93 0xf49e7d79 0x59897b26 0x75b1080f
+ 0xc2212b0f 0xe5fe56bd 0x4556e908 0x1bd0bb17
+ 0x2f159d20 0x866477e5 0x4e95a374 0xbdc9fd65
+ 0x2ff87073 0x5d7dceea 0x69ada0c7 0x89f16ad0
+ 0x97da55d8 0xe4457728 0x5ab7613e 0xf6bbe6ec
+ 0x56b83617 0x9119b521 0x4fabf948 0x2e1ab994
+ 0xd16363f0 0xaee14b3f 0x5461ea55 0x55d95d02
+ 0xf72c902c 0x1ede6c56 0x697006d9 0x4d15007f
+ 0x0c1cb5e5 0x55d3d5d5 0x1f18d76f 0x55c9f017
+ 0x3e1d3b5b 0x8f775636 0x97e6bf8f 0x360a9fb5
+ 0x1e080721 0xf9825356 0x30e900f3 0x55453bfe
+ 0xbd8f1df0 0x35b43ba8 0x45db013f 0x20484d34
+ 0x944ca654 0x79c2c151 0xd4e9b39b 0x1b2e79b6
+ 0x554314d6 0xce4ee44d 0xd0394232 0x9da4db20
+ 0xa70beed6 0x4ae4ed10 0x4c244770 0x4b91208c
+ 0x39a01e0b 0x5eea0a55 0x4b36ffbe 0x6fd18df2
+ 0x43fd13e3 0xa99302bc 0x63762b5d 0xd014d6b4
+ 0xbf0e53d2 0x0f5b5aa5 0x3c23f5b7 0x16335036
+ 0xe011bd10 0x66e596a3 0xf463e3ad 0x9670c0a3
+ 0x4004e177 0xbd2b3260 0x01967017 0x1159a682
+ 0x62931eb8 0xc581df9e 0x6710932f 0xfb2bb0b2
+ 0xb8a0339c 0xc66f0fff 0x333f5ee3 0xc06f8586
+ 0x7b9f47f1 0x9aaedaa3 0x6044562a 0x26c73565
+ 0x82c6e5b2 0x39d4eed0 0x83b7432e 0x0c4f0e4a
+ 0x4d9df788 0x989e7f41 0x61cacc3b 0xdc34efeb
+ 0x240b22a8 0x70a508b0 0x7554f517 0x7269f02b
+ 0xd27ffcf6 0x96a5879f 0x0650f7e4 0xdc1fc1ac
+ 0x80781334 0x04ab3381 0x8bad17c1 0x18311833
+ 0x65f06ee9 0xfaac30e1 0xe39b8b54 0x20b988ce
+ 0xa6a818f3 0x75ac753b 0x66f815a4 0x224d7121
+ 0x63dc6031 0xcfeed2c7 0x3ccd07d7 0x9df44157
+ 0xb9dcca97 0xcf5178f1 0x10e8fb28 0xa1faa527
+ 0x8851846e 0x01f56075 0x2dd4fff2 0x40786960
+ 0x41aa9e6c 0xf7c85573 0x64a36432 0x4449e726
+ 0x7aa7bb0d 0x08f596cc 0x248e1eb3 0x5c5567cb
+ 0x62ffd012 0x2d79ce59 0xf9ed4239 0xe98e107a
+ 0x4da25561 0xc6f83333 0x1ca0482d 0xcc3f3b69
+ 0xa9f48711 0x99139510 0xc5777d2b 0x9c80814d
+ 0xab47fbe4 0xf302d145 0x20aecccc 0x3be9e431
+ 0x7dc34793 0x4d38171c 0xaa34e505 0xc32e492b
+ 0x4f31bd0b 0xb7549889 0xdb3da9cf 0x084d0791
+ 0xa4c63c9f 0x62e770e9 0x862fdb93 0x52c45b9e
+ 0xf21019a5 0xdde6aa07 0xcb46386e 0x830693a8
+ 0x651510c8 0xf3af66a4 0x78775e07 0xc9f22414
+ 0x5769f089 0xac2ae873 0x044357d8 0x9fdc76f8
+ 0xea16ade5 0x144e9211 0x181ade72 0xba50ce80
+ 0x4573571a 0x5437c668 0x39c3b81d 0x013d766d
+ 0xc1754b48 0xa611fa3b 0x725eae72 0x04b02ca9
+ 0x186a2541 0xa2784e47 0x8b7601bb 0x7f9132e3
+ 0x3295d5b5 0x4b470dee 0xaf5ec559 0xc4c442d6
+ 0x5b07293d 0x9a68b079 0xc1408c0c 0xc2371025
+ 0x4af99e8c 0x332c416a 0xec04321b 0xb8493ffb
+ 0x51eab7de 0x26d7e9db 0x7880126e 0x439be5e3
+ 0x7e8910f0 0xa8ba727b 0x88cb04df 0x70750495
+ 0xc13413f6 0x684312db 0x0579d5b1 0x05fe44f7
+ 0x627e04f3 0xe85b47da 0xbf646f0b 0x2ddf4932
+ 0x1bcb6fc0 0x611de27d 0xb3ee1bed 0x247dad06
+ 0xa7107d34 0xba434b88 0x6eb90466 0x45a65871
+ 0xa9a67088 0x6af3b796 0xf5b73689 0xcab03ca4
+ 0xca1f25e6 0xd4b7c32b 0x5908c88d 0xac6c1fa3
+ 0x653184a5 0x062bc0bf 0x383de594 0x17064fc6
+ 0x0650dbad 0xaec15153 0xab0572ff 0xab8c6f3c
+ 0x37a93f91 0xbe51b8c5 0xabcd8573 0x05b3ad78
+ 0xad6c9ecc 0xf302c7ab 0x4b3b88f7 0x805a0107
+ 0xa5821ddd 0xc36f10ad 0x374b1056 0x79e69f8c
+ 0x8368b6cf 0xf69458a7 0x9fad691d 0xb937724e
+ 0xc542bfb1 0x37c0178d 0xc4707414 0xd6c7fa86
+ 0xb3933710 0x227800f4 0x6dca3e39 0xd88bdb91
+ 0x03755bda 0xa7f2d11d 0x4ab40803 0xf353e7ed
+ 0xf2464ee4 0x8e58cea4 0xd05807fd 0xd8d8da5f
+ 0x1a461333 0x5e84830d 0xb94ea4bc 0x5bf3506f
+ 0x76461ba7 0xabe88c54 0x124c2e39 0xc3b01867
+ 0xc6b0d4d1 0x9cc3c7be 0x8039ce38 0xfceb0e88
+ 0xa965c5ce 0x9ff3811a 0x1af1c60e 0xae9c5f9b
+ 0xee28bd50 0x202cbd2e 0x340a1312 0xa8f7115e
+ 0xb000cf3a 0x21ff4052 0xa555f08f 0x1bead4d7
+ 0xac14e135 0x449e208c 0x05ef8d94 0xb555a613
+ 0x9d65a902 0x3ad8cc2a 0x55170533 0x75782927
+ 0xefd4b5e5 0x6127ef1e 0x23fb5114 0x7ca3e1bc
+ 0xc08957ba 0x44c4e2cd 0xc0b97ef9 0xea99db5a
+ 0x53fdeb31 0x61721ee2 0xe41ef3c1 0x5f4788f5
+ 0xa8543eca 0x3f36d642 0xda6eccef 0x0341c756
+ 0xbfe7d2b9 0x66bb5cef 0xbfb43507 0xbd9c878e
+ 0x94f307bc 0x7cd56198 0xf98596ba 0x21e9c50b
+ 0xb9c9d725 0xf16211c2 0xe594b398 0x7e01aefc
+ 0x745e5ddb 0x00bae556 0xc317ed35 0x4269b4c6
+ 0x02f6b67d 0xccb4aa57 0x8a3fa0fa 0xcc660149
+ 0x57cf5e87 0x4ed03819 0x77286134 0x631cc0a5
+ 0x877fe8e0 0xa48856dc 0xe1c57e93 0xef04482a
+ 0x40cd9ac8 0xc7f43528 0x473306c8 0x01eb339e
+ 0x52612a88 0x65c3212f 0x7cc5f5e6 0xd3efbc2a
+ 0xf2537dbc 0xa9428ffd 0x76ff40f9 0x0ad4a8e6
+ 0x2020fbab 0xf8c5bbe4 0xb409e5a0 0x358d7b37
+ 0x08220bd3 0xd3707d96 0x5e2f5edc 0x638feed5
+ 0x045afa36 0x4f1604b4 0xd4dc85c7 0x37f97cef
+ 0xe1c8f5a6 0xd16fdbbc 0x986137fd 0x25b3e84c
+ 0x7f73be76 0xe25dbdcb 0x1f13d28a 0x7a31215b
+ 0x241967d2 0x2c5b4063 0xe8339988 0x13689262
+ 0x0b6d2b79 0x58773464 0xe822e560 0x77d6ba8e
+ 0x6ae6c07f 0x105e1e88 0x0045bc6d 0x88ad198e
+ 0xa350b9de 0xd5d0b3e6 0xc4e1cd14 0x47ca431a
+ 0x2ee94476 0xa2aae1f9 0xfa2042a7 0x37b0cf82
+ 0xb1aca28e 0x9a019883 0xbfb11afb 0x754ffff9
+ 0xf065a9b5 0x916e14f2 0x93fba80f 0x1dd82da0
+ 0xe41c950a 0x12b374bb 0x0f4d533f 0xbef539e2
+ 0x1eb5c86a 0x577dd484 0x98900e2f 0xcaec8695
+ 0x6a6ab336 0x135e9e68 0xc9b62a35 0xb8982b6c
+ 0x5bcdb533 0x389b1517 0xbb106e40 0xd402a301
+ 0x7446687b 0x35eda3ec 0xd44ceb2a 0xcfa4e441
+ 0x29664690 0x598a273e 0xf2a144b1 0x68f81403
+ 0xca53e666 0x064e69a4 0x87bb8ca8 0x58193c68
+ 0x9b34b17a 0xde2bffc7 0xf72594dc 0x388d3f3f
+ 0x638a1273 0x5ccf3567 0xcf1017a9 0xe616a6fd
+ 0x64cab73c 0xd209b022 0x6f08cd26 0xc30f57b1
+ 0xac2295b2 0x0c05b1c8 0xf7915ad8 0x9bcf836f
+ 0x56d8b57a 0xc8b65a2c 0x11868dd3 0xea4764f8
+ 0xa7bd30e8 0x8c895321 0xd276a894 0x86042daa
+ 0xaf6cd261 0x18cc4ea4 0x2c2185f6 0x2bf3ae70
+ 0xf3023c31 0x49f4b0e2 0x1e00afc3 0x2053b3c6
+ 0xb188c9cc 0x7437a27a 0x1b29925e 0xbc488906
+ 0x81cd9003 0x332fcf9b 0xeb20987a 0x831f912a
+ 0x857387da 0xaf1edccb 0xfe01d809 0x05351b4a
+ 0x31ec96ac 0x4f064e52 0x10ec8119 0x96c2d29f
+ 0xc6e1f3fe 0x15b0d45f 0xdca23bc6 0x7b672563
+ 0xa94fdc1b 0x7dd22f4f 0xd4d2260f 0xc9e055ff
+ 0x89e066cc 0x98200d25 0xcba82cf7 0xffb8475b
+ 0x26550a20 0xf5b4f84a 0x506cb84b 0x00d92997
+ 0x7a5c5535 0xe11194eb 0x1ff21f4b 0x725d2be5
+ 0xbe89242f 0x0b18afa7 0x6f5b1433 0x829bdaf9
+ 0x42db07b9 0x479493cb 0xabd2ead3 0xea6afa58
+ 0xf994c740 0x4cb77f7e 0xb946cbdc 0xfe558e82
+ 0xa2ed5c20 0x7012b99c 0x72a41e08 0x2058815b
+ 0x0528d06d 0xe6dbd7e1 0x3d1f6f9e 0xca78b63c
+ 0x91fa57a2 0xb6d524a7 0x1a61863d 0x89c25c5f
+ 0x16960596 0x6ebed63e 0xfcd617d1 0x0a927121
+ 0x887fdc75 0xec27c8de 0x8c91a821 0xd6bb116d
+ 0x51fe2c18 0x4af774d9 0x7aa13fdb 0xfc6ff59d
+ 0x27dd287b 0xe7e3151c 0x835552ea 0xe628aa1c
+ 0xe0edda2a 0x1957ade4 0x52336fae 0x9cecef28
+ 0x2be84cbf 0xa5959450 0x65299682 0x8151d4f8
+ 0x716a5209 0x0a8ca663 0x2187bc46 0x000767f5
+ 0xe7295b8d 0xa8bc7a6c 0x2b4d2f10 0xf251372f
+ 0x92ff27ff 0x9bfd83e8 0x8e2b593e 0x8915fd15
+ 0x1e44eed0 0x4a3a4679 0xce135f45 0xf996ec1b
+ 0xfd86c8ac 0x25b008fa 0x8973cf58 0x481512ae
+ 0xf2bc46f1 0x8b3a92bf 0xbf2a7b24 0xb19e88be
+ 0x1823f658 0xa8486c11 0x237771c0 0x6f5f0da2
+ 0xb05a42e3 0xb562583c 0xa13d37f7 0xe8eede16
+ 0xc5154af2 0xfdf7f9b9 0x0b907685 0x1f567e56
+ 0x19987b40 0xc82974ab 0xf02ae429 0x9c356634
+ 0xb85ba9e9 0xda2141b7 0xd44e331f 0x1dd722d3
+ 0x68fd2f4e 0x4e7f88a2 0xab7314b3 0x3dd05c4e
+ 0x1bb4093f 0xff73db9b 0xf917c6e0 0xae822501
+ 0x05cab9fe 0x67c91c76 0x1ebd2575 0x1ae193fd
+ 0x6f154ae6 0x13780ac7 0x6ff5bf0c 0x6b664594
+ 0x494a71d1 0x9bc35a0f 0xb34f175b 0x0069468c
+ 0x9b125042 0x7df22e49 0xf39cf8ed 0xbe020df1
+ 0xe206848b 0x8c428e75 0xc76c05d4 0x0089e2c4
+ 0x5bf9a75a 0x30677869 0x544797ed 0x68456dbd
+ 0x45b8f0aa 0xac5c82d1 0x05aefb75 0x6d5c28bf
+ 0x009ddb3b 0x551ff144 0xd19127ea 0xfc860071
+ 0x30c93457 0xa4c4b56a 0x6928a07c 0x9f63e6a7
+ 0x9fa2b174 0x7c1b2fa4 0x4a5a1f25 0x24acb022
+ 0x0c3c11f4 0xc7d4cec8 0x4484a031 0x6d3cc1c7
+ 0x2eb86733 0x8cd4f77d 0x7b551519 0x124b6805
+ 0x57385eef 0x3efd3da9 0xea300d5d 0xe64fc82d
+ 0x7d33386b 0x3933c4d3 0xe3cb61f8 0xc6fe8846
+ 0xbe0df669 0x8646e4cf 0x194a444a 0x404c81af
+ 0x9448791e 0x586f2132 0x3def508a 0xa3edebe5
+ 0x2f3b0b5c 0xc974f91f 0x400ec25b 0xf1513ffb
+ 0xc13b8859 0x32ac4d39 0xf8f334b2 0xab53ba5d
+ 0x9e196996 0xf14d8046 0x22fcb441 0xf27ac4c8
+ 0xbbdf5623 0x255df428 0xd95a2352 0x8d26f0dd
+ 0x60a301d1 0x4a2e3e49 0x4654b081 0xf775e35f
+ 0x592b5eba 0x6a3f9583 0x6ec3d395 0xc8ab02e8
+ 0xf343f806 0x62745498 0xb499dbf3 0xd427334a
+ 0xdf0b61e7 0xda67999e 0x14f9be12 0xf164898a
+ 0xd6347aa7 0x079a537e 0x294542e1 0x687b7b6b
+ 0x8478cffc 0xf335963f 0x6c1b9ac2 0x68ff2779
+ 0xe3d3f8a8 0x5453c548 0xd968189b 0x13ad95b4
+ 0xd71bee24 0x3939f36e 0xb19b3595 0x001961aa
+ 0x5f2f001a 0x77137eea 0x477698a0 0x1c07c440
+ 0x9606b6d3 0x6ce95229 0x25445629 0x5a935f13
+ 0x3e2154aa 0x6876442c 0xd9175c78 0xc94d2535
+ 0xf2070dd4 0xd4d1f50b 0xa04d18e5 0x3456cfa4
+ 0xc7610f62 0xb705a1a8 0xb8766e3e 0x225642de
+ 0x4be5b1b5 0x44d32453 0x80b8a9d4 0x7297d633
+ 0x09e8aa04 0x540929ec 0xbcc58c41 0x6dcf7b61
+ 0x6992928c 0xcd40ff22 0x13e4a724 0xd331d5f3
+ 0xa512aeb5 0x1c1c4ae8 0x5f0fe5d2 0x3d539538
+ 0x383c214c 0xd0a983e9 0x977e8682 0xf38a571d
+ 0xdb92de78 0x04ba543f 0xb531e880 0xfea55473
+ 0xd6d17b05 0xbdd676ed 0xfc7d4f68 0x8b5170ed
+ 0xa738734f 0x8a25fff2 0xb1b0239f 0x60545acb
+ 0xcfb00725 0x35f58585 0xcce4ed42 0x05da1c3f
+ 0x29428b1b 0x099680c9 0xb4608916 0xa9f177b7
+ 0x3b393c9d 0x92d19426 0x472dfe73 0x7b12de81
+ 0x557ec0f2 0x166fa28f 0xfb6855da 0x592d3e69
+ 0x373a1dba 0x9c76abae 0x13c7f717 0xbc53e796
+ 0xb2d39602 0xf1efa3b2 0x00046c93 0x1faf82fa
+ 0x55dec395 0x22a034c8 0x576bd5f2 0x97c36a45
+ 0x08a1a923 0x9ac2f22c 0xb029e4bf 0x6c4ca958
+ 0xed7276cb 0xa0924918 0x1894c9d8 0xdb993c42
+ 0xc31c6e18 0xbadc738b 0x57f95d64 0x4d766a25
+ 0xea41493b 0x60c19727 0xe7c63d8a 0xcbc52763
+ 0x7882b244 0xe2da61e5 0xd19111df 0x526d01d2
+ 0x4e7021db 0xa13fb9fb 0x23e082cd 0xb426b603
+ 0x9cac0cdc 0x44a94870 0xd0adbbe2 0x9b77a80b
+ 0xe1845f75 0xa1704da3 0x2d1c6207 0xba3ee883
+ 0x0c3089d8 0x0cba7fdb 0xcb069fb0 0x38738df4
+ 0x89971c2a 0xfbaeb7e6 0x459e1365 0x45fba877
+ 0x02046ea3 0xd9d0bdb7 0x83c74383 0xc248e9d5
+ 0xaae85a56 0x33092ec7 0x6bece02b 0x3b7af1d3
+ 0xc92b6e83 0xba032588 0x70e61198 0xa5eb1239
+ 0x4d9a6456 0x7d3fe964 0xdb3eb780 0x7e188648
+ 0x511a6402 0x48c4ade9 0xba7e9153 0x09490df7
+ 0x11b5ea7c 0x4e63145f 0x07ca7947 0xc337360a
+ 0x2b399632 0x5d1fef78 0x9b1e439e 0x8daa70b7
+ 0xf55a59bb 0xc3a8c84c 0x4d18eb22 0x74568737
+ 0xf0419b6a 0xbab459a5 0x0cb07a0a 0xeeb8e086
+ 0x0a9241a7 0x419c5ce5 0xec841275 0x3ec13615
+ 0x49e42b6f 0x2dae6c7d 0x3fc35088 0x1b92ff9e
+ 0x573b1cda 0x54381503 0x29a5b7b6 0x82994130
+ 0xffb93c4c 0xc0a66aa1 0x68889181 0x0826e555
+ 0xe81cdf31 0x740109a6 0xb8835558 0xaa5d9aac
+ 0x0d97ea3b 0x89f744c6 0x2b702162 0x992fe0ea
+ 0xab3a585a 0x3e7554db 0x9d97ebdc 0x9939bce8
+ 0x486a5f50 0x804ccd06 0xff2e15cc 0x67bf77cb
+ 0xf9beadd4 0x2da33477 0x18adbaf0 0xdb00dae4
+ 0xe727033c 0xd10ce1ac 0x4f8c4a29 0x281bf150
+ 0x764e1387 0x8c65a901 0x841521e3 0x31d9dfd7
+ 0x1e7ba122 0xe8fd6d3b 0x4bfe880b 0xd2c1c20f
+ 0x9a07169f 0xedbb94b8 0xe9cbcd9e 0x33cac378
+ 0xa42fef1e 0xf0e5ff32 0xa86b9038 0x7dbec0cd
+ 0x7ad1abe8 0x5e3e4e8f 0xc4dfe8cd 0x86630ba1
+ 0x02003c6f 0xbcb50d9c 0x65d874b1 0x01a09ddd
+ 0xc97d3d65 0x2d02bedf 0x6fc63309 0x214b421b
+ 0x72e0a28d 0xd9c8a577 0x1c8665a1 0xd33b4583
+ 0xfa004d9b 0x5c2470b7 0xc671fed3 0xe033617a
+ 0x5a86c333 0x13388e4e 0x3bccdcda 0xc62fd60b
+ 0xcae17379 0xf6d84d27 0xaaa52422 0x5771e380
+ 0xeb1feaf3 0x3c28e7fe 0xa0fded4c 0x5f63a3c7
+ 0x3b42ed09 0x1748d617 0xbc2d4fd6 0x3416fabc
+ 0xc1e60e41 0x48ffe41d 0x4ea5532b 0xba7dba76
+ 0x21378ac1 0x7425d0f3 0x426b3153 0xdc57d14a
+ 0x54997f9a 0xeda2a56a 0xfcec5ef5 0x6fd7acb3
+ 0xf2691009 0xc1a219e3 0x09a82589 0xc6e1792c
+ 0xb4674578 0x0aaf55d2 0x23c7e9dc 0x7607d612
+ 0x580fc695 0xd24b2629 0x0a8726a1 0x3544e0a2
+ 0xc1de7011 0x30982b80 0x9cf4f328 0x02b22d26
+ 0x78e33c10 0x2ce6bb5a 0x92280ed7 0x2ce5b007
+ 0x64552836 0xda4a7b51 0xa6122870 0x00b28bb1
+ 0xb98cda46 0x84cbe910 0xeccb62a8 0xe13c3645
+ 0x2f4494e4 0xed0da7b1 0xb8aa8a1a 0x1adcbc0a
+ 0xdab03e90 0x904d9041 0xaa8fe377 0x087cf59e
+ 0xa123b5aa 0x633c29c0 0x36d915d6 0x8f5cacbb
+ 0x8834d1b5 0xa2c12731 0xfab5176b 0xe1888d76
+ 0x4875b9d7 0x5747b32c 0x73fc6d36 0x202ffb90
+ 0x62900e06 0xa5f2a41f 0x497589c6 0x7ec701fd
+ 0x45801f09 0x1833e8fd 0x734acfc5 0x2f65bdb8
+ 0xe6add84d 0x4ad6dfaa 0xf59dd63b 0xb2150e00
+ 0xed32ddd6 0x370ce8d7 0x5fec9315 0xb8e6ba73
+ 0xccb15a6b 0x302a0084 0x9e49e2ce 0x7af3bc8b
+ 0x488e6ee3 0xcdbf0b31 0x762ce0d4 0xc50a111c
+ 0xd07d6e3e 0x18c391a2 0x1a7a559d 0x10b4b3bd
+ 0xd0703a3d 0x4e431eb9 0xf78edbe3 0x896604ba
+ 0xc0e8d4c9 0xd42f2292 0x5414ea6f 0x0ce7d429
+ 0xbb659e0d 0x46fa830f 0xdad39c12 0x0f65fa5b
+ 0xa002e598 0x5408cfcf 0xc1c3a5e0 0x28ca35fc
+ 0x52b2b588 0xb76e1f54 0xb6c355c7 0x08e3ba79
+ 0xfd89c1f8 0x6ebf03a9 0x51ebb756 0x729e1c5c
+ 0x1ed0cce2 0x29733f1c 0x42b76fcc 0xd94022b4
+ 0x3efc8ac9 0x3f23eae1 0xa0ccf230 0x9da59cf1
+ 0x5f6db360 0x922686e1 0xc9138d5d 0xda43fd20
+ 0xe0757988 0xa315c62f 0xe3642291 0xc45d9701
+ 0x2c394ee3 0xab92e7bf 0xf6037b8e 0x1f523243
+ 0xe91791d1 0x19961c4d 0x35d3b069 0x1596143c
+ 0x203bca40 0xd26d72c1 0x94c059c2 0xae0df468
+ 0x3b0909a4 0x34aa916f 0xe0c254e6 0xd0969c55
+ 0xa9b0b923 0x80a9dd5c 0xe79b8d8a 0x3599f269
+ 0x623c20dd 0x41e11b9c 0x40fcee5d 0x65dfa8f5
+ 0xbffa7357 0xa5b8f59e 0x2bb8191f 0x226a1b43
+ 0x910b6d4f 0x73837092 0xd666f5da 0x14fd4426
+ 0xd41a8547 0x6f4e928d 0x8096c2f2 0x525ba180
+ 0xc6a28d43 0x960b7cb0 0xb76dacbc 0x024de046
+ 0xc8e3c937 0x0217493b 0x1516dc22 0xe19e70d0
+ 0x655321c8 0xa46a9105 0x61ec2a61 0x1400405b
+ 0xcd0a758d 0xdc792982 0xbd994932 0x6565c8b2
+ 0x187be349 0x0afa44ad 0x714870fc 0xede1b8dc
+ 0x2c4ac6b5 0x7d9793ea 0xe0bc3c0d 0xaa56f23a
+ 0x7fd4e2ec 0x2131ad26 0x2cd34428 0x45e9dec0
+ 0xc15b692a 0xae73e713 0x37c5c3d4 0x70ff213c
+ 0x4d6322fe 0xa29a9b4a 0xca7d3c65 0x1024df74
+ 0x308f4a3f 0x4f48c7d9 0x0c71a17b 0x540441ed
+ 0xbc2f36a8 0x2592d7d4 0xbb643dd3 0xb8fb607b
+ 0x6b2b339b 0x9a40ecc7 0x59226bdc 0x42a5c04c
+ 0x6a1dc320 0x14e3c7c4 0x39cb912c 0xcf5eb477
+ 0xa3a43975 0x79f92cc3 0xe9d4cdfd 0x02dc8fb3
+ 0x240b6842 0xe9ff7bed 0x8f5269b3 0xc4f44baa
+ 0x1f1c74b8 0xb5c39051 0x291cce82 0xfc129a8b
+ 0x0fae02cf 0x31b4d4cc 0x1dfe9722 0x093cd430
+ 0x96c2a838 0x19b3a068 0xa7ead8c3 0xa2b3b92c
+ 0x2e1dc49f 0xe2f84217 0x670e73d3 0xd7c3710e
+ 0x94e4a7c9 0x33e063ab 0x35176206 0x910504bf
+ 0xb04b61d3 0xbed9c702 0x5d6c4cc3 0x63276a86
+ 0x0bfe5143 0x7ed925a1 0xc455934b 0x402a8b04
+ 0x01c03292 0x5de0933c 0xd932d260 0xb5b3b5ce
+ 0xde53664e 0xeaec4fc0 0x506030ac 0x6fbd8304
+ 0x0b0e4881 0x99c16b3a 0x6fc976ad 0xeae57df9
+ 0xc53a953c 0xca681bc7 0x905e49e1 0x405d42c5
+ 0xef39b878 0x57ded0df 0x56b98e32 0x392ce7d0
+ 0xaa7fbfb5 0x6ff550e8 0xf346ae82 0x2b25a8dc
+ 0x3ff980eb 0x302aff14 0x1a43c7ae 0x23f8ec16
+ 0xf774024b 0x1c4e163d 0x6b6f9408 0x0646b4e5
+ 0x2e55bfcb 0x14e3f7bf 0x86fec07a 0xda898470
+ 0xd99a274a 0x8630e98f 0x8c843f0e 0xa840c028
+ 0x950d7fb1 0xeca930fd 0xd281c9e3 0x29b3aed6
+ 0xc419314d 0xa6147b28 0xb504311a 0x91c07531
+ 0xe19ac720 0xfa8cfb5c 0xf8158bcd 0x42202a1d
+ 0xfff43b87 0xdc6fa0d9 0x8a599eeb 0xac3a8df2
+ 0x83ffa50f 0x346a8ff1 0x0947d1ca 0x318a8949
+ 0xe409dd30 0xf73ac9cd 0x9504c972 0xa2392b4c
+ 0x5594ac9f 0x7a45c3e8 0x181d42db 0x085e24a9
+ 0x6cb3e60b 0x3568d771 0xfa96b628 0x945817e8
+ 0xca9d28da 0xcd3a174b 0x7f84ca3d 0x90381d0e
+ 0x09a6f9d7 0x11396376 0x4d158586 0xcc451745
+ 0x9844225c 0xa45b8a9c 0x0c64efde 0x7429ee29
+ 0x308c39b5 0xa3454fb6 0xf949f709 0x09391206
+ 0x0168257e 0x94e10cb6 0x48e49996 0x92928443
+ 0x4a826036 0x9a777b3f 0xf77adfdf 0xc111b354
+ 0xa7ece533 0x050706ac 0x91ed3fd2 0xca15baf6
+ 0xd1714105 0xb564c842 0x886800cc 0xd57309e1
+ 0x38e4fa43 0xb74fe550 0x26f300bc 0x6349cbe6
+ 0x4bc132ae 0x310c1d40 0x3353100c 0x0a308892
+ 0xea6ab62d 0x0a438e7c 0xb000cf51 0xa21aadb3
+ 0xd3628343 0xee7f1a6f 0x3ee28d91 0xa846f25a
+ 0xc898e7c0 0x1198f67e 0x2401caf3 0x78d7acfc
+ 0xbc592220 0x1efd847f 0x1e3e935d 0xdb9025f6
+ 0x41ab6bb6 0x08a10f85 0x160dc5b4 0x4f0ed74e
+ 0x8c3db59d 0x34034397 0xe26017c3 0x03fe3b41
+ 0xc4480582 0x7c0c85de 0x4957c26d 0x9eb32143
+ 0x28676ce2 0xe3627f34 0x71e3afb1 0x7e978fbe
+ 0x3b3ee0f9 0xb5ae1bcf 0x474dc4cc 0x470e2114
+ 0x2490e60c 0xbb534e7c 0x7a8ad252 0x7cc08810
+ 0x9ea23718 0x04ecf4e1 0x732a9f10 0x62c69e22
+ 0x5a94fb4e 0xc1da497b 0x3ab3f2b9 0x09ff7310
+ 0xd7749df9 0x170471dd 0xaa551e91 0x2d605856
+ 0x66a13f75 0x0be4b8a2 0xe64a0c3f 0x288e5671
+ 0x5ee690c8 0x9e1c4b10 0x9f055568 0x8c6ff177
+ 0xa7229231 0x19e678db 0xd90be83f 0x0cf70d67
+ 0x47462463 0x327fdd91 0x51986170 0x3ad883b2
+ 0xa32fa5f2 0x82167691 0x74b6c59e 0x3eae0a3a
+ 0x569386dc 0x6d67fc33 0xa0943958 0x40b2939f
+ 0x334acedf 0x91b6a866 0x5debd880 0xa6f3712d
+ 0xbe8ca5c8 0x4b43fa68 0x72b677d7 0xa42b4d60
+ 0xc719163c 0xa469fbb9 0xb484def6 0x508ddfd1
+ 0x23bf14bd 0x857a13ad 0xf7a47090 0xe6816794
+ 0xbf6d3db3 0xd19fe091 0xb9421e39 0x35b184c2
+ 0xa5c94a6c 0x13b2b25c 0x5c7b45cf 0x648fdd47
+ 0x8832d949 0x0e2380c2 0x2f8e4f88 0xc01022aa
+ 0x4dec89bb 0x0a2c5bff 0xa97e58f8 0x304dddd1
+ 0x468828ac 0x603da881 0x646ddc90 0x1afa151b
+ 0x985bf8ad 0x6e3635d5 0x181268c6 0x420e1647
+ 0x913af569 0x14075a17 0x803aba15 0x2a2562b7
+ 0x2f0627db 0x52785b48 0x36ce7fc3 0x6057349e
+ 0x4affb11c 0x84e82be9 0xa0f60f66 0x1d176256
+ 0x9f1dba85 0x2852129f 0x4592540a 0xae083e7e
+ 0x744edf82 0x75a1e1b7 0x518fbebc 0xf1828d15
+ 0xfa1e31b7 0x88ebf51e 0x0a648385 0x956c002d
+ 0xc8b660cd 0xa82eeb58 0x0754bcf9 0xc4873df1
+ 0xf06c843b 0x7e5ac181 0x59661ea5 0xef2ae542
+ 0x0fea9691 0x9493a352 0xb401f705 0x85573914
+ 0x4e1eefc9 0x45e51c5f 0xd713688c 0x97efca3f
+ 0x292d0e73 0x8db44fd8 0x9f4479e0 0xc049ff9a
+ 0xfac5ddbb 0x4d610fdf 0xa9e01cdf 0x93b4dafd
+ 0x925004b9 0xb0796ea4 0x7e166ac1 0xd030c4ea
+ 0xa9f34c73 0x276cbadb 0xf3b9c282 0xa5bd6a69
+ 0x53df3f11 0xded46173 0x70bff329 0x0ddd0e77
+ 0x52e4a782 0xf01b024c 0xda90618a 0x34a2dd05
+ 0xc144d1fe 0xbaca12a5 0xbbd28cf1 0xc54d84f5
+ 0x0e7cb67b 0xe009e900 0x23657441 0x2214b4fe
+ 0x37693ee7 0x62e093d0 0xf79ca670 0xf1bc6cec
+ 0x1b91f787 0xc9d234c4 0x2a193a4c 0x8c2bfaf4
+ 0x75f4514b 0x03501d9a 0x5554de35 0x5ff35a26
+ 0x670ad976 0xbc8151eb 0x725fb971 0x5768e86f
+ 0x7fdcf5ad 0xe814f3ce 0xe8b9510a 0x55bf074a
+ 0x415fc288 0xa1a360c5 0xf5fef671 0x2d6253fd
+ 0x7fa09b81 0x2bb2e018 0x7159e648 0x10d5d59d
+ 0x462047cd 0x77583e64 0x47f1074c 0xc3c0e0d3
+ 0x023a55b5 0x4ad55057 0xe6d4b9d2 0x9cdd844f
+ 0x87eff8f4 0xd95c1e55 0x7499004e 0x2a43a598
+ 0x0c1472b4 0x33c90a5c 0xc4703c62 0xf293e2d9
+ 0xc3153c7e 0x6eeffef9 0x115e14ec 0x4ad27157
+ 0x888d87c3 0x33edc70f 0x7c38ce66 0x61c10a52
+ 0x5db41c48 0x8e309060 0x7b847b63 0x6b619cd1
+ 0x12855e03 0x52c3281e 0x704f969e 0xf9ab7862
+ 0xb143fc54 0x1ac23fd5 0x89dcd807 0x40a7ffc7
+ 0xc84245b8 0x0248d94d 0x29aca158 0x92d7b241
+ 0x751588ff 0xe8203587 0xc5bd7cdc 0x9de82608
+ 0xb075493c 0x5d43c228 0xff6a5345 0xa64cae5c
+ 0x4a1a9a26 0x08c60b16 0x9399ba46 0x3f535d1c
+ 0x3b9a6ab1 0xa446115c 0xa77bd99c 0x2431dc72
+ 0x729a637f 0x13f960d4 0x230d4e9f 0x0c608153
+ 0x9b9670fc 0x72494838 0x14832ade 0x65aba892
+ 0xd6434455 0x17697982 0x68b9bb34 0x1d700b3f
+ 0x6d0dda39 0x30e0d15e 0x87de41fa 0x9fc55b16
+ 0x0f5730d3 0xc3ea8127 0xeee64f5f 0xa02c5baf
+ 0x64e18d74 0x31de5660 0x5cf8d724 0x6c07ceca
+ 0x409e862a 0xd4ee7999 0x90c22c99 0x59cd395f
+ 0x09c36563 0x1993b09f 0xb0c4e064 0x8d6870a5
+ 0xe2e8e337 0xe8bef0cd 0x708d869e 0xdf808519
+ 0x6fa61e32 0x27161ea8 0x063c783c 0x2aa55c1a
+ 0xa6fcc8a3 0x918b284d 0xbb7870b9 0x788102c3
+ 0x3e49edfa 0x6c5eae4e 0x1c9fc361 0x554ca60b
+ 0xa08364d3 0xa7bd4442 0x204822a5 0x000b71a2
+ 0xd4dff005 0x43265901 0xbdb99200 0xc438e254
+ 0xa4982e58 0x02812101 0xfacbff1d 0xeec56aaa
+ 0xa5525774 0x21ada574 0xffe2f703 0x15d30ea7
+ 0x600696f9 0xc7ff3f59 0xdb57c175 0xa16f78df
+ 0x54a15622 0xe3742dcf 0x06d32994 0xd48463a2
+ 0x44c7c25a 0x41d6ded1 0x3b314de0 0x09992482
+ 0xbeb183c5 0xa0a65c27 0x842075b7 0x9b97e3c6
+ 0xd9545fc7 0x16d00629 0xd85640df 0xe79e694a
+ 0xe818d277 0x1c3d4623 0x23a9a926 0x83ac1b3d
+ 0x39e890c8 0xb3738b84 0x54b772ef 0x74518f0c
+ 0x7190098e 0xe26aff75 0xf6237011 0xbd3400fe
+ 0xda1b8fa6 0xdbf5566b 0x5155cef3 0xddbf1973
+ 0x34e2cb2e 0x535fd6b8 0xbfd337aa 0x6dd1fb0e
+ 0x52b04fbb 0xab5eca05 0xdb740dc1 0x104e6131
+ 0xbf4dcb75 0xaeff3524 0x4257c6b9 0xbf1c8cbb
+ 0x0a69ed82 0x90d991c7 0xea075cba 0x5e3c8330
+ 0x823116f8 0xba8f8a2d 0xcb98a1e9 0x8b2655c6
+ 0xd2f11133 0x3422f3ba 0x3e3a5742 0xdb9714fd
+ 0x91701f60 0xeba19983 0x8bf9f157 0xec87cd03
+ 0xb63260fa 0x207c345c 0x0c838d5a 0x736415ba
+ 0x9638ab07 0xb32c72bc 0x304d191b 0x7775adc8
+ 0x57ece662 0x0467bb66 0xb7cf80e8 0x4c635024
+ 0x176946c3 0x29cba0ae 0xf214b3f2 0x6e727126
+ 0x87b3747c 0x4c19b86b 0xfcc66fce 0x86681713
+ 0x636387f1 0x589e78f3 0x2e8abf1c 0x22c828f7
+ 0x99653c62 0x8e3bd31c 0x79187a73 0xc6d0e5e2
+ 0x8005a045 0x78a38c60 0xe1e8ff4b 0x1102d320
+ 0xaaf4ba7a 0x7223d041 0x45f73e81 0xaf7168af
+ 0x218ab3ae 0x8b1956a7 0x4db00173 0x482c3bc2
+ 0xd982b945 0x4bd7757d 0x0c5ef18e 0x74e66de3
+ 0xcf421ae1 0xf2ddc098 0xcec27e0c 0xe79e711c
+ 0x6f76e136 0xa8d72245 0x196390a6 0xbf56633d
+ 0xd1156298 0x5712cd8b 0xaed801ae 0xa345fab5
+ 0xfde1ba97 0x437a0b29 0xfc5628a4 0x93acf698
+ 0x83ce0bff 0x212f15c3 0x723ef016 0xe793bd50
+ 0x8bc51b39 0x42f17ad2 0x1df73878 0x19af3c24
+ 0xf55b6f93 0x506138d0 0x164c542a 0x8d4e1a26
+ 0x6c606f83 0x6fbebdf5 0x0e4ad76e 0xabd88e6b
+ 0x0e0d74e6 0xd139e08d 0x8b6cf03b 0x04a527b1
+ 0xe619c7a8 0xbf0d57f6 0xb38a5f5f 0x3f328013
+ 0x374c0a9d 0xff36910c 0xe950a494 0xfc477720
+ 0x37bd9390 0x4667497e 0x724eb66b 0x86bda8f7
+ 0x52efc959 0x32d5c2bd 0xddbb49ca 0x9c1eef2c
+ 0x508d8b81 0xc33d7001 0x360ae3c7 0x1197f6c2
+ 0x25efc933 0x4ad234a5 0x9e9c8658 0xc16d4aff
+ 0xbc428573 0x30e8b4c0 0x728c2c48 0xf34e1e70
+ 0xd62187c5 0xca869f89 0x34685a33 0x85d9b877
+ 0x9f77605f 0x93724d34 0x5fc8e8d1 0x70dd81a6
+ 0x643e543b 0xe4ad6c73 0xd6b4e5cd 0x387519c3
+ 0x719d8c6a 0xb2e0565f 0x02235c90 0x230c9b5e
+ 0xe76841a3 0xc2833be0 0x4dab4a72 0x0ae6c0a9
+ 0x0b5e12e2 0x4cda3610 0x954b6ff8 0x6d89a683
+ 0x3583e633 0xdc540da7 0xe2955deb 0x0f290d9d
+ 0xb01e57c4 0x977f4588 0x24b95f0c 0x45529128
+ 0x4528b5ee 0x27511439 0xd088d9bc 0x7c471853
+ 0xf03b8455 0xbda4a828 0xf49736df 0x50eb17c3
+ 0x2affe0e6 0x6727858c 0x6500b8f0 0x0483aa89
+ 0x0e1f6a41 0x72666733 0x85617ce8 0xa0c86838
+ 0xbccd2eed 0x06e8462d 0xc947bf5c 0x4d2d0a53
+ 0x02e70008 0x5039a596 0xb0118cc1 0x690ba325
+ 0x057ca95e 0x032cc1ba 0x3dae2c88 0x4eaa740e
+ 0xf07b09b5 0x6b2c2135 0xeca746b7 0x76019533
+ 0x4cf477b7 0x31848299 0x6b5c7df9 0xc0db5ff1
+ 0x7cd3e08d 0xe25fa562 0x260d66a4 0xda30cf2c
+ 0x14ab6c70 0x029a8dd5 0x7cd5fe2d 0x98ea5852
+ 0x555cf635 0x6c72ccbd 0x64120bef 0xd9e19613
+ 0xf26ac6e8 0xafea03a4 0xc14a11d7 0xb2f8420e
+ 0xe319634a 0x8a8fedd9 0x6ce0da89 0x74269f31
+ 0xd7e0d776 0x86ae9513 0x48bdea80 0xb2e4c581
+ 0xab25566e 0x9ccb71a5 0x7cedb09f 0xd2bdade6
+ 0x39c96ad5 0xe8ebbeec 0xac8a2e2a 0x915be930
+ 0x95e7c98b 0xd00e1d3b 0xdacd08ac 0xd9f515fd
+ 0x45cd3946 0x828a2cc3 0xfbe1bd9a 0xc5e1ebcd
+ 0xac69128c 0xcd6423ba 0xd8653b60 0x48f0614f
+ 0x0c1ebbbe 0x7ab89792 0x9a4b0097 0x2bda854d
+ 0xf17ab2c9 0xcde54eb9 0x4b53a030 0xe2399c4c
+ 0x19454a2f 0x473fe390 0x3a42c16c 0xc4c106a9
+ 0xf5d96e73 0x2ab4078c 0x5d20e7ba 0x47880aab
+ 0xff5e0d78 0xa374bdc2 0xc17109ea 0x39fce648
+ 0x00821cbe 0xc54a60ee 0xd753386e 0x7b28fc16
+ 0xb6309bbe 0xaefd0548 0x41168500 0xee5989a3
+ 0xe0177f09 0xc9fc9eb6 0x09a6e188 0x45776a0d
+ 0xf19a4830 0xc6774893 0x814b2e43 0xf8be5e3c
+ 0x22fa8237 0x75c98f46 0xb1c52edc 0x443d54f8
+ 0x6a1a886e 0xc7f33598 0xaa794644 0x685e5ca2
+ 0x97a735ba 0x3c1a391c 0x13f6f89a 0x660d7041
+ 0x333c3eef 0x40541bb9 0x5c3724d5 0xc348023e
+ 0x89791dd9 0xe72fba89 0x5af98b2c 0xb534fd29
+ 0x64d0e6b1 0xa578e77f 0xf311215e 0x634cc8cb
+ 0xbc534e51 0xdfce3ac7 0x90f88f51 0xb3f7dd48
+ 0x20b3e0ae 0xf4456e85 0xacb3925b 0x2eb3ce78
+ 0x37e61d82 0x724b9cbc 0x1462d9c1 0xd3f49dc4
+ 0xc1ffcc00 0x7c3e3f86 0x6f283bf8 0xf43671ab
+ 0x90cbfb35 0x55390829 0xc8fd0d31 0xc687c45d
+ 0x724ee656 0xfc1eab3c 0x3c8c2f04 0x3caa3af4
+ 0xbe220358 0x4d5b49a2 0x12cf4893 0x867173fb
+ 0xccd4b513 0x7c94a1bb 0x86c42c18 0x2b2070f3
+ 0xd2a70638 0x9d7c07e3 0xd02ed59e 0xd349488f
+ 0x1e85754d 0x333db889 0x0d0defdf 0xef282e45
+ 0xac3f6c29 0xd65a68d1 0x5d0914e4 0x395ec78a
+ 0xb056aa6b 0x4d98d059 0x7ae08f88 0x25c923d2
+ 0x79670f38 0xa881d62f 0x89cd5015 0xfb01da43
+ 0x5861244c 0x05e201eb 0x41d71eda 0xb2babb53
+ 0xc3845fb3 0x1f3b5c56 0xde6c10ac 0x73adb998
+ 0x714aac3f 0x4ad9fc65 0x3acdd014 0xeb319d58
+ 0x48842806 0x47ec1040 0xbfdf0052 0x3c478ec6
+ 0x83b43a0f 0x9e727e69 0x9f4d5925 0x9f45c13e
+ 0x30b8572b 0x26edf8cb 0x577e8b9d 0x9b98d7b3
+ 0xa44a9bbb 0x903e39eb 0x51226dbc 0x933a52b7
+ 0x14c6dc86 0xbc24db59 0x21054454 0x98fc5fa6
+ 0x2c9d8606 0x19178173 0xeda24205 0x90dfaca4
+ 0x21d562ad 0x7e3ad05e 0x2b3a40a4 0x46513f35
+ 0x0d13a598 0x8bf71ca2 0x6a36c430 0xe66f5587
+ 0xc9f13bd6 0xb6534a8b 0x8a3fbfd6 0x38cdfe6c
+ 0x1a1c89f8 0x6d782709 0x7919c451 0x6ccc96fa
+ 0x334029b2 0xa638356e 0x001e709f 0xb2132b06
+ 0x483f1933 0x189ab8f9 0x4ba0ec13 0x490aee0a
+ 0xda63f1fc 0x5679d38a 0xcf1e92f3 0xe7257fbe
+ 0xfeb733d7 0x0704860a 0x34ce2032 0x663b948f
+ 0x544cc928 0x8c23d5aa 0x67986469 0x93f9ac08
+ 0x4fa9a13f 0x9eb311d4 0x41a64161 0x29d1050a
+ 0xa5285c24 0xb53d03a6 0xc5de26f3 0x7876d1c5
+ 0xbdcdcb4b 0x79d1196c 0xe9890732 0x3e58a8c0
+ 0x874f03c7 0xfdfc9cac 0x5d57fa57 0xa3ef01df
+ 0x47bcff48 0x8beb1aae 0xf4bb4f9b 0xa5c83b64
+ 0xd69ab0ce 0x40f6691d 0x2eb8fb7d 0x22640f8d
+ 0xac1ba157 0x3687d705 0x7fac8727 0x4ad75cd8
+ 0x7016d2e9 0x25c36c08 0x7e4248ea 0x292bda19
+ 0x2acf589d 0x0ef7726d 0x835f9e62 0x3f9a1973
+ 0xbb6d2588 0x078ff6b4 0xaec22b5d 0xc740501e
+ 0xa2ab115a 0xea993e64 0xa0cc3ed1 0x934e4e0e
+ 0xd732b66d 0x5fd28c47 0xe4ccb898 0xc6a101c0
+ 0x78274bae 0x625df6a1 0xaf774052 0x3b7c08d2
+ 0x6180ac39 0x3e5aa769 0x6ec74578 0x6b5d27b9
+ 0x98e58a17 0x119dd7d4 0x39429c5a 0xe3d5b391
+ 0xbb8fddb8 0x5929801c 0x68cef71c 0xc36fa301
+ 0xeace4850 0x29f4f97d 0xa58bad79 0x2823998f
+ 0x0fe1352b 0x5960ded0 0x69308816 0x0d7e33c8
+ 0x2fb13bfa 0xff6a326f 0x69cb631a 0x839ea2a1
+ 0x528a8065 0x34cbebfa 0xd4432cc4 0xe13b550b
+ 0xe046569f 0x87b41fb1 0x7751107c 0x0ef6e60b
+ 0x856ffc50 0x11995683 0x77c2ebf1 0x4dec97f9
+ 0x3a28ebc0 0xb7bfa04a 0x40cdceb0 0xd559dd06
+ 0x61c2cd6a 0x8a906fa2 0xd55f43d6 0x7fb3ac35
+ 0x8cea4e81 0x1d359c2e 0xec447c57 0x3414f7f1
+ 0x18243b84 0xdf76849f 0xd753044a 0x7af2d51e
+ 0xaee26ecc 0xae6946b2 0x7478c675 0x88b22f49
+ 0x4de13fc9 0xd35c5956 0xeebb60b6 0xa15b1736
+ 0xa6e78d78 0xfd5e30b3 0xb4fade2d 0x964eb418
+ 0xe9035f51 0x22ab8242 0xfaa64053 0xdfe03834
+ 0x47beb588 0xb82a0887 0x11182e85 0x2f2f9a67
+ 0x4b612f11 0xae04077e 0x7f783c25 0x883a34e1
+ 0x32d43beb 0x6f0536f7 0x85c1537e 0xfb26199a
+ 0x45417e88 0x4af2c8cf 0x0a334486 0x2a3e6838
+ 0x31b8725b 0x63d64541 0x7e516a0e 0x7e42e766
+ 0x4cf30198 0x68abecff 0x7fb49c43 0x8f5b558b
+ 0x32b99abe 0x67337248 0x224c3411 0x4e7c41b7
+ 0xd3aee3a2 0xca19e704 0x2a430b7d 0xe9aee453
+ 0xf4ce492d 0x48fab2a9 0x42ec2076 0x0182cea5
+ 0x8a6373c7 0x18f41b5d 0xdd062fd5 0xb1db44a7
+ 0x285ad917 0xeaaabbd1 0x359b1b23 0xcc123c8e
+ 0x38b70cb9 0xb01ae722 0xa6e72010 0xb647530e
+ 0xf9651d41 0x366d6d0f 0x4b656a6d 0xd36637f0
+ 0x4b5ab8bf 0xc22fdb1e 0xc57c8250 0x799f4e60
+ 0xb55bd50b 0xe8a3432b 0xe752e4e0 0xd0c86482
+ 0x122991f1 0x5bec598e 0xbcb89abd 0x739f61d0
+ 0xd230ae2a 0xd0b99c05 0x2a998a6d 0xab715831
+ 0xb7dd1939 0x57db0ea7 0xed1f4952 0x49274caa
+ 0x35e319b0 0xed2c9cb3 0x601caa20 0xfe782688
+ 0x64b6d30b 0xcd5c325c 0x2c836157 0xa3552f79
+ 0x188094db 0xa42dd7e8 0xc09c2dda 0x02d98d8d
+ 0xed270d28 0xb0f38ada 0x5d7b4261 0xb41df8d8
+ 0x7341b6ae 0x024ce90a 0x0727ae4c 0xa8dd3a0d
+ 0x390f84d5 0x43f5bd12 0xd11fb61f 0x6fc330e1
+ 0x7f2d7fa6 0xf758a4e0 0xceb1f3c3 0x2f341836
+ 0x98fb470f 0x5bf68e58 0x1917a5b2 0x75f33be6
+ 0x16e22316 0x8aa810a0 0x1fc6c9b2 0x22179249
+ 0x3de701e9 0xec48d8b6 0xe85248c1 0x314ce9c1
+ 0xddeb2f47 0x0187909e 0xaa755f62 0xb2019460
+ 0xb2016a9c 0x91f789be 0xe5925997 0xe4864300
+ 0x1fd13759 0x0ad97c1d 0x7cf08c01 0x7eac2dd6
+ 0xcf61a7f3 0xaf9e108f 0x939a2fd9 0x0cb48e78
+ 0xe6ea1a8b 0x0b968273 0xef1c9310 0xf60e82b7
+ 0xe76e9bed 0xb8fa9668 0xf889765b 0x0e51eed6
+ 0x6b6566ea 0xa8f7e2c5 0x9d8c283a 0x879afdcf
+ 0x944873c5 0x58afcfa2 0x2e60600e 0x59666667
+ 0xc812b833 0x5842d0be 0xdbdc0829 0x786bcff9
+ 0x5857ba06 0x6968c729 0xf5447949 0xdb1ceeb0
+ 0xaf04d1f5 0x30614f7f 0x3e80fdc9 0x8a6e1ce0
+ 0xa267d7d5 0x8896143e 0x24e59072 0x68122e1d
+ 0x3ce24add 0xda677bdc 0x8c3f74ef 0xfa60e825
+ 0xf5c136cc 0x2cc5f249 0xa1c6b642 0x47a2305f
+ 0x52cadbc8 0x4d0c32f6 0x07f4d344 0x1f496d59
+ 0x5699b970 0xb8cbe564 0x707f7a2e 0x818bfd45
+ 0x800a8be0 0xd3de4f1f 0x62de0a3a 0x6b342869
+ 0x054daa7c 0xc72b945f 0x1612f126 0xdb4ad492
+ 0xa28c467b 0x78542799 0x61607353 0x39f1c142
+ 0xebf30ad6 0xabe076d0 0x5125cce4 0x5584149c
+ 0x65fa33f4 0x878a918f 0x8c7e5c37 0x334c4284
+ 0xbfd816e1 0x0f0f3460 0xd54519fd 0x03701ca9
+ 0x64885229 0x00e841d0 0x756a9472 0x0c16c5f6
+ 0x65560e81 0x129b6995 0x91c9dd1e 0xe9730dae
+ 0xce47f2a2 0xead8a0ee 0xcd58078f 0x7ca2df31
+ 0x0ebbf13d 0x3c74e061 0xb7f3980a 0x0d354b88
+ 0xfd8db90c 0xec6726d0 0x6bfce0f5 0xea98b7a0
+ 0xac5ddde2 0xb372a14c 0x47b09ed5 0x531bd5c3
+ 0xcfaf5a0a 0x51d6394f 0xe9efdfa8 0x37c79445
+ 0xb13ebf62 0x46715efb 0x31e6a0d7 0xfa48ab48
+ 0xc6552f2c 0x3067b978 0x0afa4ab7 0xc2c17055
+ 0x68dd427d 0xeac01e43 0xe90f12d8 0x6d97c3b1
+ 0xe0d339b0 0x2f3c84cd 0xca3eb3b1 0xbc0d86e1
+ 0x3566f657 0x083374b0 0x199c677f 0xa4a8a4d3
+ 0x224dd5a8 0x8f304abf 0xe1019878 0x9b290d4c
+ 0x5cef7341 0x59ff7e48 0xc91663ac 0xb0b1bede
+ 0xe9d8a9a5 0x8f34cb70 0x588d00d6 0xb7fe69b6
+ 0x29036caa 0xd21d7998 0x4edc3ee9 0xdbd94f37
+ 0x99c63455 0xac94efda 0x545635dc 0xb787b5e1
+ 0x8228666b 0xc7cd8170 0x4f1924a5 0x437884c1
+ 0xfa9236fb 0x1f0f949c 0xd1dc0597 0x56082a24
+ 0x04e51919 0x05dd926f 0x06d264ac 0xaa672d38
+ 0x5a3e396b 0xab48a57c 0x53489bd1 0xb36b3ba2
+ 0x55164db6 0x5b52c5f9 0x68aa8b7f 0x922ce829
+ 0x09e6e5bd 0xbc488a86 0xc0fb6dab 0x98e7754b
+ 0x4c9ad717 0xe3ae7045 0x0b498742 0x80a4384b
+ 0x0dfe0b99 0x70eab3b9 0xbee30b9f 0x4237ca85
+ 0xe67662b1 0xdae3dce5 0x47c84a45 0xf72febf2
+ 0xa58dfdc8 0x77ae88d4 0x038c76b7 0xae699990
+ 0xf5f10de7 0x65d4c59a 0x004a8b4b 0x67c788ec
+ 0x71c918d7 0x0ec70171 0x7041de53 0x43591e1c
+ 0x807242f8 0xa27fe146 0x0055fc7e 0x2f08467e
+ 0x5e04a068 0x54dab094 0x4f6e8c7a 0x20ac2825
+ 0x47949a42 0x9181486c 0x038e3132 0x7c1c51be
+ 0x97544f38 0xe2d27588 0x64889c21 0xdad9a1a9
+ 0xf1d328a4 0x7d47991f 0x2faa1b85 0x2430cab0
+ 0x0e849f91 0x213686c1 0xa2635f37 0xee7983ae
+ 0x87871273 0x6867d60f 0x04cb29ae 0x4e0ee4ee
+ 0xfbd2666a 0xfd7fe017 0x870b26ee 0xc42e104b
+ 0x78919117 0x19590e66 0x9e1a5039 0x9609471b
+ 0x4057fde6 0xc1f27544 0x30af8a8b 0x2ea267a6
+ 0xcfd886b6 0xe632b1f3 0x3f10bc50 0xf38a1bd8
+ 0x7ae1e284 0xe3876d7a 0xb4ce64f8 0xf74b4100
+ 0xa97686da 0x17ebacde 0x2ab068e8 0xcebd1076
+ 0xee8f81d8 0x0d394301 0x6f32c277 0xa926dc1c
+ 0xd5d2ea55 0xdc016b6b 0x6a96022f 0x0143e314
+ 0x23836eed 0xa3e18369 0xd2a155bd 0x8022cef6
+ 0x080b32a8 0x74ba38f0 0xd1ca2089 0x7c80219e
+ 0xf536af16 0xd7a337e3 0xa33600a6 0x39c7754d
+ 0x7d215312 0x1dd65026 0x8cb496c7 0x89dfd508
+ 0x9f945a1c 0x45caec32 0x020a1edc 0x5917baa3
+ 0x296b4b1a 0xcfaa2023 0x63e7a0e5 0xc48b19ae
+ 0x78d98b1e 0xc5d6be01 0xfe4ef13d 0xea6c9915
+ 0xb8190f09 0xf1793822 0x9acf1593 0xc7710fa0
+ 0x6b9a9f3d 0x0220ee2a 0x5d63043d 0x7292a0d5
+ 0xba9a1682 0x6f1e7c19 0xed7cc52e 0x6bb89645
+ 0x4370269c 0x9cb2c1a1 0xa7135973 0xfd1f3bbb
+ 0x50e6eb67 0xf2b9bd22 0xd891f6a7 0x4e0a7449
+ 0xc3dc0005 0x878e3333 0x3b4b8686 0xb215c65c
+ 0x5d8d24c0 0x8d203496 0xff20d243 0x0a6c1253
+ 0x2385c79f 0x52e8d6dc 0xda4bb8b7 0xfab66d97
+ 0x05a4a795 0x6876e856 0x9dabedc2 0x53550c20
+ 0xb3bba16e 0x853bf1cf 0xb85b906d 0x3f374468
+ 0x62e07c2c 0x6903a495 0xdb119586 0x07e91546
+ 0xa8388945 0x5a4e1dda 0xf054cdad 0x4b052880
+ 0xe9bbc9ec 0xe3555e11 0xd4d6479a 0xcad6a986
+ 0x31d9c4ae 0x510ff951 0xcb2f3164 0xbe283401
+ 0x0c390b9e 0x0c9cb487 0xe64e8ffe 0x611a63c0
+ 0xa1d700a5 0x3f864335 0xd1fdf32d 0x7a3aeb09
+ 0xabbc8c4d 0x4d703604 0x6532c8e7 0xccebc529
+ 0xf3c0f514 0x1567f19d 0x591abf6c 0x6c7fc459
+ 0x0858b061 0x092b2489 0x33c1a9cd 0xd6cc8e2e
+ 0x7c1ffeb3 0x3f45cf40 0x1fbcbd39 0xc6f0e628
+ 0xb88bab4d 0xc699de42 0xb62d850c 0xf71a6768
+ 0x2866b891 0x13093fcc 0xc730c502 0x2deaeff4
+ 0xb1bc8535 0x4303997b 0xb31ebd2f 0x82debe94
+ 0x843fa02d 0xba29f80d 0x03cb58c1 0xef1d2017
+ 0x0b5aadf0 0x6c5c3286 0xf084faeb 0x8b96a39b
+ 0x67cb38f8 0xf686ee62 0xbfdc22a1 0xee3f779c
+ 0x8ec73c8c 0xb448536d 0x67bb5d68 0x4369ea8d
+ 0x4b5367cd 0x2dbbc0be 0x8f5986e7 0x798c8392
+ 0xd3aac078 0x0081c0bd 0x94d9d70b 0x40bdeae8
+ 0x6b528e89 0xb0713745 0x063e535f 0x7d696463
+ 0x64f0666b 0x68a82e8c 0xc749dd19 0x875883cc
+ 0x3d35728d 0x4c0e5d8d 0x135f11b3 0xb649b37f
+ 0x8aead5cb 0xdfbd573e 0x563bf917 0xcdb75f08
+ 0x024b93fb 0xc6477eea 0xd88ce51d 0x95f7d77f
+ 0x0b561446 0x2fb6992c 0x4b48c8b1 0x940da60f
+ 0xf1be60b9 0x66d8641b 0x17a0ce15 0x49d22f40
+ 0xb8c494da 0x91930bb1 0xcd317991 0x4c5b4c23
+ 0xafda60eb 0x212c9f04 0xe4732f4e 0xf731ae57
+ 0x19165943 0x2d9288c3 0xc9c45dd3 0x2e05b148
+ 0x225a256a 0xc0249ea2 0xe96733d1 0x56a6803f
+ 0x20458549 0x28210fd6 0x13da740e 0xf0f0be41
+ 0x029c1fa9 0xb1daf3f7 0x1bf0c9aa 0x6f0d5221
+ 0x998b3616 0xa02212a3 0xe76b39b1 0xba0823e6
+ 0x146da6a4 0x858a3e0e 0x58e75b32 0x732f75ed
+ 0x8d88385e 0xe0e7ed55 0xc08ca86d 0x97e2ef67
+ 0xbb048208 0xd384c40b 0x8595bc69 0x65581977
+ 0x7b091c4c 0x60bfbbb5 0x23bcf38f 0x32e4621a
+ 0x7f790d95 0x72c3267c 0x34dd0c12 0x27438915
+ 0x5619893a 0x09d55159 0xdba7eef9 0x7413634f
+ 0xf4883417 0x59a2f28e 0x491f5779 0x0c138f9c
+ 0xc52a03de 0xcb1f92d0 0xb6cfcd21 0xbba95c83
+ 0x5302f12d 0xfc4c030f 0x18722dde 0x131cd3b1
+ 0xa19a1cdb 0x103d9216 0x403e45db 0x5cab72f3
+ 0x17e18f5c 0xbad9d0d9 0xd0d2e010 0x798106fc
+ 0x3abace6c 0x2c3131c6 0xf9529b61 0x27cfa158
+ 0x8890951f 0x87ccf0f3 0xa112b1e8 0x3e0eb033
+ 0xd7469e14 0xb6ccd2ca 0x3d238069 0xb32f057e
+ 0x8d2c939b 0x18d8aa3d 0xdb3cdb2b 0x861ba258
+ 0x46e7b170 0x4830d004 0xeea1b8b2 0x44e29b51
+ 0x0cdd8591 0xf93ad973 0x9383c44d 0x24e323be
+ 0xaaac87a1 0x84eb09d7 0x1f66b641 0x303f92b4
+ 0x81a63a86 0x516321e4 0xe33dfe2e 0x371a4624
+ 0x8f936425 0x596976ca 0x7b1947ef 0x83a9db29
+ 0xc5f337b0 0xe4d51b73 0xb35b56ce 0xb9cac5ba
+ 0x51705ecf 0x93e7d63f 0x5ee7d916 0x479f25b9
+ 0xe90bb406 0xfcd6e78d 0xbd8ed9b7 0xbca7c8b7
+ 0xdf95f4cb 0xc28baeba 0xb4534bbb 0x98b4f840
+ 0xf2218357 0x726e4f81 0x7591ebc4 0xc0523d15
+ 0x6bc82550 0xedfbcfa0 0x57280f50 0xbe7e420c
+ 0xd1152012 0xbf3ee0a2 0x11825710 0x18e728d1
+ 0xb8af00b5 0x2d1e940d 0x1c9ade8f 0x923ed269
+ 0xfd8c2580 0xf6477ff7 0x476a486e 0xd09c18dd
+ 0xaede7959 0x55fb68fc 0xe5692f7f 0x0bf4bd18
+ 0xf5fede2b 0x07bb05e7 0x1bb8ec54 0xa46bba84
+ 0x15051826 0x762ce6ae 0xa0246225 0x35c38cab
+ 0xbbd00a24 0x8205d3f4 0x4cb33ba4 0x293013fd
+ 0xd4f67965 0xe9c1951b 0xff108efa 0xb8e68197
+ 0x36d51e4c 0x2959f7f9 0xf2e4206f 0xc9973e09
+ 0xb61ce3fa 0x9543be90 0x63642668 0xcaaf02be
+ 0x7346a8eb 0x4111f5b5 0xa453cc2b 0xdb524b49
+ 0x4d528cfa 0x71e5fc4d 0x62cbbab2 0x8423f40b
+ 0x1a4db908 0x560c41c2 0x03982d88 0xa49c553a
+ 0x529f6acc 0x82dae294 0x6c5dbaa4 0xfb4ae1f2
+ 0x36e31345 0xb5cba88e 0x3704c623 0xe35245ea
+ 0xa412107c 0x35faf59c 0x08ceb649 0xbd67a6b9
+ 0xe37ddfdf 0x21303abc 0xb7de5e8e 0x88d9366f
+ 0x49bdd73c 0xeca0cd02 0xfe1e01eb 0x30a56c2d
+ 0x0cae1f5b 0xe77521c7 0x5ca59eaf 0x1288aa13
+ 0xc60bc96f 0xf7292504 0x2b037e4d 0xf34757b4
+ 0xedcdc492 0x39044092 0x5d710fbb 0xb8658511
+ 0xe23e4d57 0x595d4d3f 0xc0f80105 0xfe952879
+ 0xe81e2cb6 0x4f5a8fed 0x3bd0d700 0x211887d3
+ 0x6ea6e78a 0xe066640c 0x0d29c725 0xdabbeedd
+ 0xd2aca4d4 0x65c4a06a 0x6645b62f 0xb1de0cd7
+ 0x022e07ea 0xe9f9248b 0x0a2251da 0xdf34159c
+ 0x7894bab3 0x72e465eb 0x37448fca 0xbfbc1911
+ 0xa79e4938 0x48b83ec3 0xb9c6833f 0x19d24abb
+ 0xa434e777 0x77947277 0x2309612e 0x546a6ebb
+ 0x4c96447e 0xab918dce 0x5075ba1d 0x0aa55a7c
+ 0xadcce25b 0x837819d4 0x90d62a9d 0xf116ede5
+ 0xb056cc7f 0xb036353e 0xb7c1af8d 0x014c2cd1
+ 0x356f1593 0x008c2634 0xf7cd0cb0 0x02b0576c
+ 0x5364c954 0x5b40800b 0x60054bd7 0xef31bb60
+ 0x1a85370a 0x458c4348 0x435b8da2 0xd8df0e06
+ 0xde0cf1b8 0xd3c6171c 0x0bc14938 0xdc874128
+ 0x694f96cc 0x7b6687e0 0x9ca59f25 0x617aea60
+ 0x63ebcc8d 0x4bb44d00 0xce46d01c 0x4ab07a75
+ 0x64757638 0xe5903811 0x3562895b 0x760627ce
+ 0x8939cc7f 0x225db9b1 0x730062d9 0x7a5a7a15
+ 0x49678fc3 0x8620cb95 0x9439dee1 0x501f2cae
+ 0x3d08a33c 0x352de5c1 0xe7b24442 0x6ec76b79
+ 0xc575a1e8 0xb7024b20 0xc9dbb9f0 0xfe2303c0
+ 0xba3716ae 0x0cf37bdc 0x1c68a4a7 0x7ba0d609
+ 0x43003a93 0x17dd96c3 0xb884aa37 0x15b2d65f
+ 0xf6016133 0xd1fd7e04 0xc0a22822 0xf8c26247
+ 0x818c35fa 0x4e2b3605 0x83923c44 0x4ddd4397
+ 0x6faf6a11 0x50438703 0x67796dac 0x3443b780
+ 0x484f5bb9 0x8ead98ea 0x472ae543 0x94b0b17b
+ 0x1307833e 0xcb0e8286 0xb02e1ab1 0x36a89f9a
+ 0x372e82f0 0x84741303 0x111ad8ae 0xb1eeacb7
+ 0xd7d8ccd6 0x5f779f32 0x0d65184c 0x0a398467
+ 0xc07c099f 0x0704ffdc 0xa10b2f17 0x4c926dc9
+ 0xd80829ee 0x0821015a 0x512e6d0e 0x57b514dd
+ 0x509cdfd6 0x7e08ef24 0xf536c381 0x65483797
+ 0x439311fd 0xabed0f15 0x51a372c2 0xdd24c506
+ 0x839cdd63 0x0c21c8dd 0x513d9eb4 0x43c6a95e
+ 0x5d543848 0x64843a49 0x687bbf41 0x93d3bce3
+ 0xcf85eea3 0x5f3a6fc4 0xe7b45979 0x4c5848ce
+ 0x924188e3 0xbcbded12 0x0cc18c86 0xf3fd5723
+ 0x148dddb6 0x77cb388f 0x30afd47c 0xa306c453
+ 0x1da0b234 0x0f206f46 0xf25975bb 0x9c75d28f
+ 0xc60ad2fe 0x0067c5b0 0x497a1617 0x81d330e6
+ 0x2c5362ef 0x86a54b1e 0x80ad976e 0x0a86ed37
+ 0x1183b84e 0x2e2ce6e5 0x10b02598 0xd56fb0b7
+ 0xe3e0bca5 0x755d2333 0xe0be1b85 0x6c976f4a
+ 0x555a1465 0x8ab38399 0x51d4a5c8 0xec3d86e1
+ 0x2a85d0dd 0x0d31c16f 0x603f2d48 0x274d5d68
+ 0x292e7df9 0xe444f292 0x329946f1 0x132c3230
+ 0xb2c3ec05 0x88362f92 0x763dc2fa 0x7ee6f3ab
+ 0x7ca649e8 0xafee8a8b 0xeef65517 0x4789c1e3
+ 0x85bd4cb3 0xc87762d3 0xfa528ba7 0xa8e20dde
+ 0xd369c227 0x97e7f300 0x8256f4ce 0xdd5d2901
+ 0x1e37c55e 0xbb6e22fa 0xd9424392 0x8798d9a5
+ 0xc118ddb2 0xc3c91c40 0xe68ead77 0x8cf3655b
+ 0x4381e8fc 0xc94f312a 0x0b372483 0x70b620df
+ 0x53820813 0xb50d6f0c 0x64a53e9e 0x6f7f19f3
+ 0x6315f718 0x9aafff2e 0xf3b5a338 0xf1f3293c
+ 0x750ac26c 0xefe3ddf9 0xdc7369eb 0x024dafe0
+ 0xf56354fe 0xf0afaf86 0x7da1df00 0x7447ffa2
+ 0x4afd091f 0x24f39c82 0x3b3c8aa3 0xd90fc65d
+ 0x10d90b8a 0xf05d49fd 0x281320fe 0x75f62523
+ 0x0537b558 0xf52ae61c 0x77961852 0xbd0db386
+ 0xcb650cb6 0x7387ec69 0x320764c4 0xf5013b3f
+ 0x4f4239c8 0x4983a307 0xf510f405 0x7e355790
+ 0x4f8480d2 0x50dd84ca 0x66947bed 0x56efdfe0
+ 0xa593407d 0xdac216de 0x642a5f74 0x92bb9c2f
+ 0xf37abdd9 0xa24b1b64 0xca1f722c 0xaa5de969
+ 0xb6cb128a 0x697f787b 0x5bd74fb3 0x6de74e39
+ 0x2bc9a4aa 0x634455ab 0xa82aecc4 0x69647f0d
+ 0x4be06592 0x0c220c92 0xb08adf1f 0xd4571d2a
+ 0x0fadece6 0x297c124f 0x2830a499 0x3cc8363f
+ 0x44e34d3a 0x27b4d820 0x98be7f08 0x43417964
+ 0x8a3af8ac 0x89c42336 0xe55d19dd 0x00ee1f6e
+ 0x47d48658 0x55986f58 0x11ccb046 0xf3b97a07
+ 0x7ed364a3 0x106cfcd0 0xc1533857 0x3add2c15
+ 0x143852c7 0x55b38512 0x49a85ce8 0xd61a285d
+ 0x513bd0b9 0x21bde48e 0x4f231482 0x93aa6dde
+ 0x88035659 0xa83e3d2b 0x542513f8 0xe6e74a1c
+ 0x06092343 0xd37c8770 0x41553ead 0x09980a79
+ 0xb0e45895 0x80db4662 0xa6ce0960 0x965cfa7e
+ 0xfea96644 0x2a79157e 0xf020e115 0x61823e96
+ 0xf14f63d7 0xd753d1bd 0xd24a060d 0xfd2691b9
+ 0x18da9d0e 0x9f3c93c4 0x2730e0f2 0xb47e2afa
+ 0x920fda38 0xb5d89646 0xfb4728e5 0x7e78c2cb
+ 0xe46f812c 0xe51cc5c0 0x9d2957fc 0x548798a1
+ 0x240c2103 0xd650ff70 0x15c49ff6 0x99587c0a
+ 0x1bb4a5ca 0xd6db66e7 0xec2d3ac5 0x54164690
+ 0xe61bd6f8 0xc7a45cf8 0xee25f4f4 0xd1eb3ae7
+ 0x90085a1b 0x46a7a74b 0x829717f2 0x7f0769cd
+ 0x3ef72792 0x0c8617a7 0xa86becad 0x9dfe5329
+ 0x1a33c5a6 0x47d4c75b 0x2e10b45f 0xbd11762e
+ 0x15b72a9b 0x015c7f84 0x379c6bd2 0x27525345
+ 0xff3ac5a6 0xac916082 0xf5c24317 0xcc43fc64
+ 0x7f092c8d 0x931d9a0c 0x5a07f13e 0x3e1aa46b
+ 0x717a343f 0xd51221c4 0xc9422fcd 0x63f7af00
+ 0xde81a497 0x0322d271 0x972a4065 0xd75df029
+ 0x343a94a0 0x8c225f7d 0xb4abe87e 0x3cb8ba1b
+ 0x0babab14 0xf29704e7 0xd7134233 0x391f1a35
+ 0x33aca565 0xe6ae586b 0x0470a42c 0x570efddf
+ 0xfea26a3b 0xcee8d934 0x99ece522 0xb8af1375
+ 0xfe4dea4b 0xb96a32c2 0x3469ef9c 0x029fade7
+ 0xc4e77d55 0xc0449b95 0x63336e95 0x8d46c2e0
+ 0xd86d6e23 0xd365b781 0xe73ba0fe 0x10a354c5
+ 0x2d4511a0 0x077206cf 0x1c0dbd55 0x03396771
+ 0x8bce27af 0x70355b4b 0xc2275e58 0x3cfa4df5
+ 0xc8b3b9b8 0xf3fd510f 0x6b055de5 0xb3fef295
+ 0x42b95a20 0x5b5e75e7 0x0aaaa734 0x636d50ae
+ 0x8329283e 0x446e76f3 0x6adc320d 0x69a3e9df
+ 0x1da68939 0x6f071783 0x498dfee5 0xaece51ed
+ 0x4f8a72a8 0x4f2f2f65 0xdac3ba47 0xcbab0287
+ 0xf966cb4d 0xba27861f 0x54c79a21 0x44e2359a
+ 0x6e6b0e7f 0xceae84fb 0xb1530a59 0xecb8cd96
+ 0xff60633e 0xed748fe3 0xf1ab0d95 0x59997216
+ 0x6894cf41 0x948fc7bc 0xfb162ae5 0xeb9951a1
+ 0x99d0a7a3 0x9234587f 0xcd42615b 0x6f9ad0e8
+ 0xeb936dbe 0xbe72b62c 0x44ab5e9f 0xed736b08
+ 0xffaedca9 0x103b89bb 0x7896b40e 0x13a5a924
+ 0x56786357 0x02ab80ec 0x72ef47fd 0x81bf0fd7
+ 0x6661b300 0xaefadc79 0x9968433a 0x16f3718b
+ 0xe997a663 0xbbb55a49 0xf9b9a710 0x5727271f
+ 0x20e9bf55 0x358e3986 0xd1214e1f 0x4d42c46f
+ 0xa6bf8194 0x0c14a853 0x7b51aeb0 0x2f3d4de4
+ 0x3d6ffef6 0x4e94ba19 0x71a9c861 0xcade2398
+ 0xe0b3eb18 0xc9f028b0 0x7d29d2d0 0x372ec60a
+ 0x288a5bfd 0x4fc2bab3 0xc01dd045 0x8222e147
+ 0xe06676de 0x750bbfea 0x586ffb3d 0x2addb655
+ 0x767a6528 0x78abceec 0x1646cb38 0x21e26890
+ 0xd2a7937b 0x2463457c 0x764103fb 0xd540867f
+ 0x3566875f 0x007449ba 0xf9c0c523 0x2c51c86c
+ 0x437e1196 0x69fc0059 0xe0103408 0x19f23997
+ 0x23fdf335 0x7262eef4 0xcbe09390 0x583d0099
+ 0xe862084d 0x19fffbab 0xd2958a5a 0xcb165416
+ 0x32f3a97c 0xe502303a 0x16c4eda5 0xa1bcfd1d
+ 0xc4f35053 0xfd037f66 0xdeac9fee 0xbfb167b1
+ 0x39804db6 0x0bc2011d 0xf56bcd68 0x368cb345
+ 0x52fcb352 0xc306c535 0xf6bff09c 0xa429cbf7
+ 0x7e504be4 0xd2240214 0xf09ee41f 0xcbcf1fe4
+ 0x70f96a85 0x8394bf28 0x3cc19a50 0x49581f96
+ 0x58da5ae0 0x94708c48 0x63febeaa 0x4f656940
+ 0xa7fd6879 0x65524f66 0x5f7ee0df 0x11d487f9
+ 0xb494641e 0x7eb57255 0x5aa208c0 0x5666243a
+ 0x7d5970b5 0x71ea69a1 0x67059c9d 0xd3bde5bc
+ 0xe952b3fe 0x27bbf258 0x197504f4 0x5da6649d
+ 0xecddf4de 0x2d040d3d 0xbc9d3ab6 0xd8cdfb81
+ 0xb36ab627 0x7a548111 0xaaeefa4c 0x0e55b263
+ 0x4f9da6e6 0x26a137dd 0xdea03395 0x23b87267
+ 0x5b3cc98a 0x206de858 0x8d2e5cd2 0xb60f14e6
+ 0xfc10356f 0xeecae1d5 0x39783cbe 0x1a1c9a70
+ 0xb52c6f05 0x64adf10b 0xe12d9f3b 0xb3fb7cf1
+ 0x9051fdea 0xc16ed3bc 0x697199b0 0x08f34342
+ 0x2fb2bab6 0x729ed2b8 0x7691088b 0x82bc9cc1
+ 0xafce7ac3 0xe167bbb9 0x362e5d43 0x945510ec
+ 0xf32dce5e 0x4aec9a82 0xb80520d3 0xd8fcbe40
+ 0xf4877350 0xcfdd487e 0x8c9ff8b5 0x84ce70df
+ 0xffa6abd3 0xf9d2f273 0x342dbff8 0xa72580e3
+ 0x6ffccdc3 0x0c7ccc0f 0x6b24afd4 0x82b71a25
+ 0x1ba361f2 0x6ed8a67d 0x243ce000 0xd16b2e19
+ 0x86d3c3e6 0xca209063 0xaff0b983 0xf411f71f
+ 0x0f2ca724 0xa6fb0fb6 0xfa663640 0xe40fe20e
+ 0xf8e2a5cc 0x1a0e8862 0x11de13a4 0xc811e4a7
+ 0xfe6fa8e6 0xfefce644 0x8f7fcde9 0x94477c62
+ 0xec9b942f 0xfda6b166 0x91330c4d 0xd059d679
+ 0x96b0f7a1 0x22df13ce 0x3f36c3e9 0xc814e342
+ 0x7b7dce7c 0x1000640a 0x8cbe7a56 0x622fa655
+ 0x209d82d7 0x55668514 0x1534f8af 0xc2b7dc1f
+ 0xd89da0dc 0x3ddfe751 0x0532dfe4 0xd39c360c
+ 0x090f91d6 0x48587117 0x8ee383fe 0xf5ffdee4
+ 0xd8bca448 0xd26d6d82 0xe8adcc12 0x8b14b8c1
+ 0x7f872f36 0xb8cb0e16 0x76d60c06 0xf62ddbec
+ 0x3ec7c151 0xe418a789 0x920a3bf8 0xc5b62e09
+ 0x4974ea7e 0x0d8d7962 0x5bbb246a 0x37183d1c
+ 0xf25c63dd 0xb15730a5 0x903e3400 0xdab426eb
+ 0x0323289f 0x9bc16f49 0x2dfd02a1 0x3ab916a1
+ 0xcb6f770a 0x342021b2 0xf9f5c9c0 0x9c8d53a5
+ 0x3d53f39b 0x8e693c58 0xebecc732 0xbf30c538
+ 0x96648d11 0x60f62751 0x29745559 0x8e365fb3
+ 0x7d0b1179 0xea5abbb2 0xe45c4af0 0x53056b1d
+ 0xac7b03dd 0x7015c355 0xf17f8dfd 0xe1ace271
+ 0x9abacdc0 0x5ccedc75 0x478c717d 0xc01dfdad
+ 0x26fb551f 0x73e61f00 0x8bc0b111 0xb6855743
+ 0x28690dc2 0xf13b6766 0xc098861c 0x5c0ffa55
+ 0x271e7d0c 0x66b47b80 0x9921a158 0xd9c560d0
+ 0xb29b6ee7 0x50a9bc97 0xbec4d91e 0xdb2c1fcc
+ 0xdf215786 0x1541e380 0x59cae516 0x2342b2ee
+ 0x8088cd9b 0x7312579d 0xb17be14a 0xa1638c41
+ 0x805c6b18 0xb8a56151 0x56f0a6da 0x96b114d2
+ 0x0845ea7c 0x23e8f7eb 0x4e88e7ce 0x84640f2c
+ 0xacf8eebe 0x4039725a 0x49bf9982 0xfbcfcbd9
+ 0xfbbfb1c1 0x8041659b 0x5b8ee4f3 0x1b6d7a38
+ 0xeb634fc4 0xbf818ab6 0x8076c921 0xc50be762
+ 0x24c43f4b 0x3252acca 0xa7528630 0x9885b151
+ 0x9154b37f 0xfd9d3ab1 0x4f93c117 0x578fba44
+ 0xa56851fc 0x9d8083de 0x769f6fb4 0xd89fec27
+ 0x747c8071 0xe6b2b747 0x8196e2a8 0x3ed6c699
+ 0x8716f1df 0x65325e96 0xfbc715d5 0xb06f9171
+ 0x7aa9cbdd 0x84bda56b 0xdeab06ee 0x80432d8b
+ 0xd76f0a57 0xe0ed5f9a 0x70f991a2 0xf1a9e557
+ 0xcbecbcdd 0xcf0d91fc 0x6751fd67 0x590f206a
+ 0xa26d8130 0x1df02179 0x826303ce 0x6cd58190
+ 0x1219d005 0x4bb2f3b2 0x0dbd8193 0xd8d8f582
+ 0xa5867eed 0x2d6b8ec9 0x5f85ec18 0x7983775a
+ 0x214ca0c1 0x9af3febb 0x213d6568 0x2f8e8c43
+ 0x92add018 0x6e33e00f 0x6fa6834f 0xc3c2cbbc
+ 0x1c65c8c5 0x1827f812 0x868d3a09 0xdac83ade
+ 0x57623da5 0x5ff83257 0x0992e621 0x25cc9ca9
+ 0x10580130 0xff2ae8fe 0x40a58253 0xffdc24d5
+ 0x3e4dbe68 0x291b11f7 0xb3594b9a 0x570c7b6d
+ 0x38d31bd4 0x7155ba24 0x84d56490 0xd98842d5
+ 0xe037d2f6 0xdd2ba821 0xbeb861d5 0x0fda5758
+ 0x5921c665 0x98c7676d 0x8eee487b 0xac0f2411
+ 0xb332d321 0xa0816c65 0x76edde5c 0xab868b36
+ 0x3f8da4fd 0x516af4e7 0xabf748a8 0xbe7820fc
+ 0xbf763827 0xa03a3566 0x8a63e804 0xb4f8f901
+ 0x5d262ee9 0xaf905cf5 0x896d0c94 0x5f992cab
+ 0x81c2faf9 0xda3c686a 0xb01a06dc 0x45ef0c90
+ 0xf2ca525f 0x0e74fe18 0x36ecdb11 0x494125d2
+ 0x226b4aab 0x3e92ae29 0x5bb48774 0xc2c2ef90
+ 0xa9e77d5a 0x409db546 0x7728f003 0x72229503
+ 0x2e8febab 0x8322cfbc 0x5eaf74e9 0x621837f8
+ 0xc70668d1 0xb25c1325 0xd741c010 0xf52e3166
+ 0x71ef7a87 0x74cc93a4 0x7c25ecf4 0xb8b8e20f
+ 0x3658c239 0xbc58fba7 0xf13ec858 0x9271b2a1
+ 0x37084dd5 0x6fc92e82 0x44a6abe6 0x92b9238a
+ 0x9ad3a57e 0xd75daf92 0x8ea573d6 0x69ce1fb6
+ 0xe80df5f2 0xcc1c6ae7 0x6d565a77 0x6981ae63
+ 0x18af1922 0x6e8a7af8 0x10716aa0 0xa7da9970
+ 0x1abbc7cd 0x114f814a 0x4ebb0c07 0xc8fe6a69
+ 0x93d7bc2e 0x0a16181c 0x0379c950 0x4b2e8c18
+ 0x670b83f8 0x82a75eda 0x6eb772dd 0x42cfe197
+ 0xd91ec29c 0x29fb4812 0xab693ead 0xb2f25a1c
+ 0x0b9df6cf 0xb7a1aba2 0x1d7d90bf 0x7de14655
+ 0x649965f6 0x11fbe065 0xa54ac5a3 0x418bd3df
+ 0x4223c00f 0x7bfcf9ae 0xbd979739 0x6a2ee697
+ 0x54e7d9c8 0x73803bdb 0x06654716 0x72225136
+ 0xfaef3873 0x0b4b40dd 0xd3b98b57 0xc56cbab5
+ 0x32174c47 0x4d4d8c32 0xd6f1bf93 0xeefb6950
+ 0xb84ed0da 0x590723d4 0x2d006f09 0xc4bc139c
+ 0x55434982 0x8734189f 0x0e314a50 0x94340d09
+ 0x021c24a4 0x0b0f022d 0xa61f9025 0x71eb72b6
+ 0x744ccea1 0x2030b859 0x78203d74 0x0b8a8389
+ 0xd5211777 0x2609edfc 0x6134eede 0xec74584f
+ 0x0bdb2d06 0xb1768f76 0x56221895 0xfc49bdae
+ 0xbcc6e6ed 0xfeb19c0c 0x18652996 0xaa1a0164
+ 0x3ffdcb94 0x2dc1b090 0xb68bf220 0xc33b967d
+ 0xc907a1aa 0xa3968cb1 0xb3cc65e5 0x33e2b077
+ 0x2bb22904 0xe0fe8fc2 0x4affcc46 0x6b0f0bbc
+ 0x5d1bef41 0x2de11c7f 0xb0d864ee 0x6e96d8dd
+ 0x59c1c108 0xb2544572 0xab3400af 0x604aefcd
+ 0x81be22c3 0x6741e6ca 0x3a93dc1c 0x7b10e639
+ 0x0add7a92 0x39fc1df3 0x884f150b 0xd666a96d
+ 0x87da0c1a 0xf0f73c15 0xc0c00957 0x011ba61d
+ 0xa77e9463 0x96020e4e 0x92416e99 0x881e89c4
+ 0x46981327 0x3bc624f4 0x57f226f5 0xac340cd8
+ 0x3ce239b2 0xec6b33bc 0xa9123e11 0x70640b6b
+ 0xc30f59f0 0x411576fe 0x5ab12c3b 0x3cc20b85
+ 0x924b3be2 0xd1fc7a28 0xa4b0cf7a 0x88098404
+ 0xbbd331e3 0xff2b6047 0x2a1ab042 0xdf220849
+ 0xaf774ae3 0x5a8da79d 0xf18450c8 0x8e6e235f
+ 0x1dd3c039 0x1a867ae2 0xe4ccd1f4 0x50dd3f39
+ 0x8be186ba 0xc7e30fe2 0x17552d4d 0xffac16e4
+ 0x4094bbc4 0xc18a2513 0x650e707f 0x8ecdbba2
+ 0xf53e8e7d 0x047dbce2 0x7fc2a89f 0x07628f94
+ 0x2a8bfc67 0x0d738727 0x7b5c2fd4 0x2c89d27f
+ 0x47f37a64 0xc63debc9 0x15d6c414 0x242c300a
+ 0x645d95ab 0x29e1a49d 0xaf77fab1 0x643b4cd5
+ 0x3e0f63db 0x4f7cc43a 0x33d6797b 0x497d4332
+ 0x7160786f 0xe0c5b75d 0xfb08ecb2 0x26063065
+ 0x9835bf7c 0xf5465591 0x63155d2d 0x14babba1
+ 0x384a0879 0x460db3b1 0xcd37760b 0xad675a77
+ 0xf1dceded 0x69df690a 0x44c6f456 0x87d6a7a4
+ 0x4e0d6504 0xf967f55f 0xca9bb20d 0xd5eb41f6
+ 0xa9aa9b2a 0xa907387b 0x965b6f23 0xdcd47eb5
+ 0x43b5b1a0 0xec876728 0xee7339e8 0x10c5ee16
+ 0x1bd8c0bb 0x7235ae07 0x063e3564 0x388d0bb5
+ 0x80f9a9f6 0xaf96f714 0x6895c899 0x00ad21bd
+ 0xee67961b 0x873781a9 0x22cf435a 0xee90cf3e
+ 0xc9a4fadd 0x9bc1af4c 0x35c0e803 0x211ce71a
+ 0xb9af86bb 0x97828ab5 0x9dbd002a 0x1cc981c7
+ 0xefb36876 0xea739a75 0x5d5abcc1 0xd42260f2
+ 0x95083e0a 0x31fb0b51 0xf243ab8f 0x628b1913
+ 0xe74eb210 0x620b7d9f 0xc81666d2 0xc8fd1ce1
+ 0xf054bd9e 0x78ba7618 0xe1df4e38 0x5e381b3a
+ 0xcc68da1b 0xb3ce70ac 0x7ecda229 0xf8778140
+ 0xae823fa1 0x12af1708 0xc9373879 0x1e687d29
+ 0x96062069 0xf1bfde2b 0x999ff6c0 0x8cbeddf0
+ 0xc825a2bb 0x78106bbb 0x87a964fc 0xb358ec2f
+ 0x4d959300 0x0fe9706a 0xabb1d003 0x72b65294
+ 0x43816b1f 0x6c83b958 0x5549567c 0xb474aa55
+ 0x98851640 0x751a670f 0x25900026 0x2ab174e3
+ 0x1952c3dd 0x38b47c29 0x32c0af52 0x460c8fad
+ 0x85a1004e 0x8cbddcd7 0x66578310 0x4904dcfb
+ 0x04b7a746 0x00c91fb7 0xb1ab2edb 0xd0178ae2
+ 0xc4b8b57e 0x981d4753 0xfdd8939a 0xa8a05055
+ 0x47c8c30e 0x0fab4f6b 0x6ea54079 0x23dc4151
+ 0xc23e83aa 0x2ed2ce8a 0xff95b763 0x08df1d51
+ 0xd16d104e 0x0fa3ee3b 0xdcfe8541 0xa0622490
+ 0x085e5c0f 0xd9bc007b 0x24794e89 0xce341d16
+ 0xf090a98c 0x317150a2 0xcc036257 0x3296722d
+ 0x9c8d4f58 0x7ca5f53b 0xb0e4f9d4 0x1f178bbe
+ 0xc0dcde7c 0x18551596 0x0507b8e2 0x3c40a8ca
+ 0xc632f82b 0x5d1965f9 0x92a00465 0x13a8ca32
+ 0xc0b6756f 0x669d706c 0x58056b22 0xaa25fd37
+ 0x128b731c 0xb141ed31 0x0a8d3ddf 0x48b63bd1
+ 0xd24c5c4e 0x0ccd96b8 0x4b1ff726 0x309be62b
+ 0x26002e68 0x436f2bd0 0xacb62068 0xce098f50
+ 0x330e6160 0x434da66d 0xce14054a 0x0a877e41
+ 0x705eb2fb 0x8433fc7e 0xc1bd475b 0xb550de6d
+ 0xf4faf808 0x9f9b6ebe 0x0ff98ef7 0xace2766f
+ 0x01cc9606 0xd9654327 0x3544cf5b 0xbffbcd80
+ 0xb4a5948f 0xcded4d04 0x69ef5a24 0xf5ae46de
+ 0xe2139499 0x549f82bf 0x2cdfc6b7 0x5fdd2462
+ 0x63c68a37 0x8bce0d04 0x9c66ae30 0x9fd94951
+ 0x5774366d 0xd671675a 0x5582f253 0x436c5b6b
+ 0xfc151e77 0x1974df45 0x5ea9eac2 0x30689b8a
+ 0x9806681a 0xb74d3ec8 0x4f207181 0x668b4951
+ 0xb06514b2 0xeccffed1 0x16188ff2 0x5914d385
+ 0xed4b7023 0xfb0640e8 0x179adcda 0x6e806687
+ 0xb4f0ac07 0x35813615 0x143e66b4 0x1b012a50
+ 0x384f31c5 0x1500dbca 0x06e47afe 0xa8a17374
+ 0x9d0f5c57 0x4574db82 0x91b3680e 0x794683a7
+ 0x30c25d5d 0xf8748c08 0x2e601dfc 0x553152f7
+ 0xec5d489a 0x4bd37616 0xdc04dc7b 0xf0a35ba2
+ 0xb36975db 0xbfe6f98a 0x6d744996 0x5507380b
+ 0x4191e01a 0x0092c384 0xcf3a4388 0x6b0e89c7
+ 0xded7b820 0x1fbd6bba 0x3af210b1 0xfc4a608e
+ 0xa920eb22 0x22db2d65 0x7d6f0447 0x090f3679
+ 0xc4c759cd 0x9758aac6 0xa63251a9 0x47b7a974
+ 0x65421071 0xdca8495e 0x96f879d7 0x1d22ea6f
+ 0x46dd72ba 0xe0c59ccc 0x15737309 0x6d945f11
+ 0xbcb15c8a 0xb11ef0b9 0xe2072633 0xccbd61dc
+ 0xfcb51c44 0xd2315c65 0x3087a6f8 0x5609ee34
+ 0x94c7f951 0x0a057b31 0x6e6f2733 0x179facec
+ 0x36c005b9 0x60184919 0x50b3db1f 0x7a827d7f
+ 0x88755ecc 0x3fb0d6c3 0x63b150d4 0xe2ec3004
+ 0xe0ee30f1 0x118d7040 0x2f4689e7 0xa78be0be
+ 0x3c9bb853 0x75c326cc 0x84097407 0xb0107b5e
+ 0x83a56a91 0x14e60445 0x0fa72553 0x1385e6ce
+ 0x9b8bbdcd 0xe6aa6a9b 0xc2072ccc 0xee916592
+ 0xe44082e1 0x43dbf6d8 0x09f821fc 0xdc84b023
+ 0x0e6a518b 0x945fb180 0x185d0841 0x9ece88f8
+ 0x844558c2 0xed85f422 0xeceb983c 0x6db16826
+ 0x7612b243 0xee3bf226 0xb8eebb7b 0x22e16615
+ 0xc892bb7a 0xdc475a47 0xae390e93 0xe00baa1b
+ 0x725fca23 0xbb868b3a 0x17c62a69 0xeccd3731
+ 0xbe1a4223 0x05c8fd7e 0xa8354afa 0xbbb09f8c
+ 0x31a77e83 0x01f17a68 0x5f37c847 0xa0fdd7db
+ 0x9f8da870 0x98f02167 0x1e966884 0x00e19b81
+ 0x50c91add 0x6aba2a55 0x60be9575 0x3da40b37
+ 0xde13ff4d 0x5b7a79ec 0x4700ffd9 0xfee5ea61
+ 0xaf4d1d1e 0xfccb6f04 0xcf5076d2 0x48c4c98a
+ 0xd6a8915e 0xe4a58522 0x6bf3a6a9 0x4e7c2f15
+ 0xcd7e8d2f 0x843b56b1 0xa35f1a5d 0x1ca226dc
+ 0x917fb163 0x44751f0a 0xd96fa8aa 0x5028dccc
+ 0x7792dd96 0x2a9d749d 0xe48385fb 0xde111e91
+ 0x805e6581 0x3d9b9fad 0x5b750544 0x03785b71
+ 0x9b583214 0x80022658 0xcf1f3730 0xa1be7be7
+ 0x6c1e26f2 0x26de584b 0xb4fc8e35 0x072b520b
+ 0x55db3ac9 0x81e9d490 0x4b5ea53e 0xd5628e00
+ 0x71bfcac3 0x79956bbf 0x275fab80 0x2ad497ed
+ 0x423854b2 0x686451ad 0xfd59d64e 0x9f2049d7
+ 0xcb0f8f32 0x74d7545d 0x4f9c1df8 0x6fbf0afa
+ 0x7ef06915 0xc5117549 0xf20088b4 0x731a5ccf
+ 0xe78bbe74 0xdcb4996e 0x7062a6f1 0xa624b59a
+ 0x7b2d5e41 0xc1065234 0xa7c32078 0x367e7134
+ 0x86f55f58 0x3084ee83 0x0c599d1f 0x69380e2e
+ 0xe59482b3 0x7096432e 0x81124388 0x5be8d01e
+ 0xeb25ec24 0x8b47e9ad 0x432216fd 0xdc496dea
+ 0xcb05fefe 0xe76eb9ab 0x8ed568d2 0xfa963d68
+ 0x70ed6f4e 0xb2b88d58 0x15fc42bb 0xe992ec48
+ 0x359856b3 0x4a0f7741 0x3f0b6eca 0x07c16950
+ 0xcb9dae59 0x209570c2 0xf196555d 0xbf7c0a0f
+ 0x4a814210 0xf8f206c7 0x8bbb0763 0x360fa596
+ 0x13d46195 0x901170e8 0x6dc2e376 0xbfa00989
+ 0xd12cab90 0xf4f4699d 0xbc88b362 0x4827dbd5
+ 0x7cde5cf5 0xe45dff5e 0x2d661b05 0x8902d99e
+ 0x6c9f3584 0x0db3f864 0x1132773f 0x3e944120
+ 0x27058ae1 0xef978864 0xe58eff42 0x020ae503
+ 0x77fe075b 0x9c577e08 0x210b42b9 0xcb8160c0
+ 0x09f99f36 0x6a0b6bee 0x6f18b0ef 0x5452ee3f
+ 0x6c8c4a4d 0x480cb803 0x892f3973 0x066dbb63
+ 0xf7f845c8 0x7ceeee7e 0x7c26c5ce 0xec89119a
+ 0xc64bdc20 0xf46e4324 0xff34c833 0x555b4b3c
+ 0x23ff2701 0x52360759 0xf60acad8 0x241ccb7b
+ 0x29e14901 0xcc068e2b 0xedd0ee02 0xc33a425d
+ 0x7d889b28 0x88577f8d 0xaaf614b1 0x8e8c8eb5
+ 0x81a363f8 0x29f5bcc6 0x08aeb8e9 0x6f9ee222
+ 0x1c50045b 0x792c9434 0x62bc2601 0xc9289175
+ 0x374fc38c 0xbae91a86 0x3268e89b 0x5b008f10
+ 0x0ea6b759 0x9d43ce10 0x09b30dd2 0x643e2b94
+ 0x5c19bafb 0x29515176 0x56a81f95 0x60a80534
+ 0x22fa0a73 0x1259cf8d 0x323fa5b3 0x6322f1d0
+ 0x30581c47 0x50458048 0xd711c1b6 0x4a34236e
+ 0xb60a2e40 0x58df96c9 0x947b90d7 0xd327d664
+ 0x5fe528db 0xf6d9c575 0xb0a251b9 0xed961301
+ 0x2fee3cf9 0xb687e226 0x78fc46c2 0x29e9fef4
+ 0x84bff086 0xd0482ed1 0x018996f1 0xb8b9cdf8
+ 0x20885e68 0xa6f848e2 0xfddabc3e 0x5c9a7f67
+ 0x7cbc3e40 0x5197ebe2 0x41a15775 0x8024fd2a
+ 0x7864106f 0x7cfaf482 0x27798720 0x4956355f
+ 0x30f7195e 0x6ea09dd6 0x6f2b5f3c 0xf38df38e
+ 0xcae7e8cb 0xf8a80b0b 0xbeb227ba 0xbbfa2428
+ 0xbbba3ab6 0xbf83edbc 0x2cdcaa9b 0x2b0841a7
+ 0x79d52e5e 0x40260460 0xb27709be 0x07e3bf6a
+ 0xbdccc2b9 0x369d0069 0x9d745e50 0xff251486
+ 0x1e14957f 0xf7253467 0x9a31eeb9 0x4d77108a
+ 0x44fefc47 0xd02d4082 0x232e3fc1 0xce39396b
+ 0xd7a13714 0x2bd57e7e 0x00876803 0xee73377e
+ 0x78bb6240 0x2ae63c46 0x11e009d2 0x922539cd
+ 0xf3bef05a 0xf0c664c3 0x6e132a0b 0xb0c5bddd
+ 0x40c66494 0xd7d0d02a 0xa73110d0 0x4b409d78
+ 0x6f49bf88 0xcfc9d22e 0x4836da89 0xde5a80be
+ 0xb9c8bdb3 0xe99b2e9d 0xf1b05e68 0x8ab599fc
+ 0x22675035 0x3c8480c0 0xfa3cd457 0xba617098
+ 0x422eca1c 0x0cdc0d01 0x4779b95e 0xccfa0bfa
+ 0xd22674a4 0x76462be6 0x3015ab3b 0x7891688e
+ 0x1c83bf8b 0xaa55839a 0x7a71a83f 0xad451c1b
+ 0xf8b8bf06 0xc75a91be 0xcac50366 0x87e365ae
+ 0x9013ac11 0xe9cec5a5 0xef4d88f5 0x15c27162
+ 0x3dcaf8ae 0xe023891b 0x7b6f1706 0x2f1198e4
+ 0x048e34ba 0xb647b5e8 0xa1826caa 0xed3bc134
+ 0x43b14d28 0xf0c49b54 0x1a6362d4 0xc77fa378
+ 0x3bb12e79 0xcba4cd2b 0x620f2476 0x7729add6
+ 0x9876c439 0x5f7d8795 0x858f7ac8 0x68b94589
+ 0x1321d70b 0x5353a2fc 0x912a5ea4 0x390cf0f5
+ 0x37320473 0x51b3cacf 0xe45046d2 0x9188dcc5
+ 0xb3713b54 0xc9b936e3 0xe9f24574 0x5977a68c
+ 0xc23c56bd 0xcfc39ca9 0xc891b8d0 0x3683ef22
+ 0xc1ce304a 0x3ebf1ce1 0x52cd1cc0 0x3777d973
+ 0xde614072 0xf2efe226 0xbe1f9f9b 0x92a1896b
+ 0x9ca62763 0xcf5703be 0xa6d9c56a 0x185260d6
+ 0xd9e3b86f 0x5c47180b 0x71a7a219 0xe9974375
+ 0xf22af4d3 0xfbc92962 0x968c3fe4 0xc584b60e
+ 0xb9abee26 0x7e9737d8 0x5947da83 0x2f8ccad0
+ 0x7b4ee942 0x51ad62dc 0xf517400c 0xe2bf9e37
+ 0x63057e05 0xe1bfabf8 0xbf118805 0xc038de9c
+ 0x7aa57b7b 0x05584eff 0xb15ea286 0x26c6a6c0
+ 0x8e1392e8 0x7dbf22e1 0x3546f5bd 0x0f84ed9b
+ 0x0b01da4d 0x6dc47417 0xadc6f687 0x4160c045
+ 0xdc26765f 0x63b70c6e 0x8f177107 0x6a5f13cd
+ 0xb56fce56 0x5d1f5ed1 0x62f6a18e 0xf7235691
+ 0x222fa999 0xd48b1435 0xe597d406 0x8dacf828
+ 0x694ecd8c 0xe5283c02 0x60bcdcd3 0xfb9eb384
+ 0x9895492c 0xd38172dd 0xe7b6dff6 0x0ead5894
+ 0x910e2675 0x97d9ee09 0x270b2d8a 0xd03e25e0
+ 0x9e7bbb69 0x57ab1d31 0xf2e7a13d 0x9c8e5baf
+ 0x65fa03f4 0xc66bcbfc 0xf2d8bfe1 0x23059412
+ 0xa3ae7654 0x3a4734a3 0x32c0a8d3 0x4e007b8a
+ 0x5ce30660 0xbd10c57c 0x5365f540 0xeaed3002
+ 0xc377d84d 0x87097a59 0x929edec9 0x5878368b
+ 0xbd450478 0xc3fab275 0x128fdced 0xb706fbb5
+ 0x146f1d41 0x86782651 0xa530ca29 0xa3e1b6be
+ 0x25390048 0x572b4a05 0x8c9b4c90 0xb05428cd
+ 0x33fabab5 0xd16e513e 0x1d6cc812 0x4d80a6ed
+ 0xd6a5a07e 0xc0ee4c19 0x544b75d1 0x3f887360
+ 0xb2f46d1d 0x21609cbd 0xe340211d 0xe9202fb6
+ 0x3023b005 0x3341ead9 0x76c99537 0xc9d76547
+ 0xfb736c3f 0xf6385346 0x93fe2a05 0x92de6df5
+ 0x7793acd1 0x68249b3e 0xc22cae3b 0x668988e0
+ 0xdc1ea28c 0x7ef72b95 0x974098f9 0xb214701c
+ 0xc2de7d98 0xeb1d443e 0x5975f0ec 0x21d67037
+ 0x721e8e99 0x42105562 0x74b1e821 0x20193b2c
+ 0x743a7bb3 0x24643c9c 0x240b331c 0xdf125e2e
+ 0xcb4b0205 0x19edb174 0x505eb85c 0x1830bf22
+ 0x6bf7a528 0x86a7281d 0xfee3488d 0x6c26f4ab
+ 0xbff4ce7a 0xff7cfaf1 0x5df6fd66 0x523f0802
+ 0xf8a87595 0x463b5c19 0x72c564fd 0x2e4797d6
+ 0x1f04a1af 0x0be96baf 0x44552094 0x2a158f50
+ 0x83dac587 0xad4c881d 0x3178e710 0xe938d1be
+ 0xab715a65 0xc34b451e 0x1942832e 0x91557ecb
+ 0xdaf0606d 0xa64623d9 0x84e11fbb 0xa9c9d11b
+ 0x577a15b1 0xd49a2f23 0x6f204e0b 0x0a6e6a2f
+ 0xdaf13637 0x6b4ef557 0xdcaac9a3 0xad97c404
+ 0x8471691a 0x50ca3cf5 0xde57c446 0x70aa02f1
+ 0x84baa6de 0x0232bc79 0xa06427af 0xd2ce56be
+ 0x5da13949 0x254f5f4c 0x3fc3fd02 0x00b5f8eb
+ 0x54a0d4b8 0x5e3ec3b1 0xc6718376 0x5acce6d8
+ 0x614c56e0 0x89a6b00e 0x6cb4e087 0xa9822fe9
+ 0xdea290c6 0xb294582f 0x36f9640e 0x30d0afc4
+ 0xef7d75b9 0xfd9aae2d 0xd6729573 0xac442321
+ 0x158224fc 0xfd6632df 0x10cebf98 0xc3864dd8
+ 0x31577c58 0x49e71f9c 0xb96d876c 0xd867604e
+ 0xba74c3f0 0xad69752f 0x716eb51a 0x469d9d03
+ 0xda4b2e16 0x9e80a908 0x9bcb18e8 0x2f1c595a
+ 0xe823ecfa 0xdfd5badc 0xe460e9e0 0xae418438
+ 0x457811b4 0x29df713a 0xd90b0d29 0x415ba2de
+ 0xa0af6489 0x4922a50e 0x2efa0b0b 0x9394e4cc
+ 0x0ef8f59b 0x0f851711 0xa4670f3b 0xcc6bbfc6
+ 0xae194dfe 0x78e51752 0x4c65a2d2 0x1b0741cd
+ 0xc9f401c0 0x4a678062 0x290d2bc5 0x1a4279c4
+ 0xb5f9160f 0x40ef7c77 0xa9bcfba9 0xaec75f21
+ 0x53d6258e 0x8587eb74 0x0721d492 0x2c6a6e2d
+ 0x8e6cb70e 0xa6bee309 0x6faf5706 0xf8eee239
+ 0x52c85943 0x8c198893 0x3db37858 0x557fbf2e
+ 0x92f1a0e5 0xbd279594 0x46d65132 0x90a2c32a
+ 0xd11db660 0xc73b3922 0x9d1075ff 0xdb80a1cb
+ 0x54158743 0x39694d0a 0x4a0ddc7c 0x721f9dc9
+ 0x04b1b044 0x3bb40aed 0x6be7a88a 0x429a3b09
+ 0xa6e9dfa8 0xba412f0c 0x354f08d2 0xa4569516
+ 0x928cca34 0x398b1a99 0xb7e80291 0xe67d7b71
+ 0xa6582bf0 0x556ebb23 0xdc6d9f6a 0x11b3b753
+ 0xbdf31ae5 0xd3399560 0x6148cec8 0x5188689e
+ 0xde18f46b 0x3da414ad 0x4c44ad29 0x68582541
+ 0x75c8b1e6 0x7ba572de 0xd753ed20 0x4a9c4578
+ 0xf1c9159d 0xcfd9da31 0x46799fbe 0x1aee4426
+ 0xdcdf7b57 0x327db61b 0xa160ea1c 0x84a01fc2
+ 0xbe0aa020 0x5963688b 0x24f32751 0x885b4177
+ 0x26cde88c 0x39e6df90 0x1c7fee90 0x882a5c0c
+ 0x56f1f2e0 0x10bb9f52 0x4f0502aa 0xeae6e5b9
+ 0x65e7ee25 0x8ed230ac 0x38b5e02c 0x5f5311f7
+ 0x929491c0 0xdd923e62 0x5bc6166e 0xa3c89f4e
+ 0x5844fb12 0x0c40f02f 0xdda07582 0x8ca1b803
+ 0x9398b0d0 0x4dba17f9 0xb9879c85 0x26956147
+ 0x3c26a130 0x58cdc52b 0x21fa4801 0x9d965ce6
+ 0xb9942dac 0xd83d1518 0x36e630dc 0x50bb2822
+ 0xcd472a65 0x6feee2f4 0x4853b680 0x7f54945f
+ 0xa522c561 0x28134f6a 0x89b46cb2 0x4fe0047e
+ 0xad602b28 0x4942494f 0x1536ea37 0x40ea6278
+ 0x5020bdb1 0xad3c9f7e 0x1356d0ce 0x411700c8
+ 0x1ba61954 0x65dece8c 0xb788efb9 0x26efcd5e
+ 0x9833fa21 0xea0052b8 0x119a994f 0xa71b168b
+ 0x164a96e0 0x0bd1b4e9 0xaae1e562 0xb550f48c
+ 0x3a3b55e1 0x4d921246 0xcb28af65 0xdd2388ff
+ 0xa63988c3 0x7dfa5a8b 0xc7c44102 0xc75e9f3a
+ 0x5e4305db 0xacb34d1c 0x9b50976b 0xad3f6379
+ 0x6cd20ee3 0xba806f21 0xcd0fcf4a 0x18a55973
+ 0xbafe5266 0x03ee9b8c 0xa35fbfde 0x7f2eb71b
+ 0x23d9aa11 0x0e183c35 0xefb0ae3e 0xc6093786
+ 0x5b380af5 0x64838229 0x3bd69926 0xe9758e1d
+ 0xde439e4a 0x0cbc4bdd 0xda5858e8 0xbe8afc07
+ 0x676379e1 0xccc4c628 0x763e3b38 0xb4823c67
+ 0x9f4aa538 0xd8d33f50 0x41291e48 0xaed28ade
+ 0x6c72eea8 0xa751f4e8 0x3a75dba2 0x5073e3bd
+ 0xf10b4756 0xdf46ab98 0x9ad689f1 0xc2ba74a4
+ 0xf2ce9419 0x4cf9732e 0x75cf58ca 0x249e3c52
+ 0x95d10a93 0x51120008 0x7438d467 0x0a5e7f2d
+ 0xb7a44e46 0xe31e5dee 0x26e2ed14 0x8f16a7d2
+ 0xfcda431c 0xab32ada3 0x3a863c94 0x5fe91346
+ 0x2a92c590 0xb8c17e6b 0xcaf753fe 0x50283647
+ 0x533c8f3c 0x1233e1c1 0x7a5b2eb0 0x79b4ba22
+ 0x3164670c 0x201c500d 0xafeac6bf 0x2fbb0884
+ 0x915de3b0 0xbf733b7f 0xc45d1a42 0xa3b86d4a
+ 0x333ef605 0x6348522a 0xd28d1d19 0xa2cad790
+ 0xf8ad449c 0x05aacdcf 0x64500018 0xb1d8cb18
+ 0x9e4a2ecc 0x091282c7 0xfd64bcf8 0xe1e7c24d
+ 0xfcd0f386 0x0c9faa0e 0xa82f265c 0x83cafc3e
+ 0xcad43563 0xc110837c 0x2a2da74f 0xbd98e00b
+ 0x5c24553d 0x41c75caa 0xe75cb110 0xa004b946
+ 0xd4daa77c 0x88d07273 0x0c75c7eb 0xaf05657a
+ 0xbe1f8336 0x122a7acc 0xe0e5c29d 0xd5896217
+ 0xfb2f909a 0xa74b6458 0xb33a1a38 0x815f7832
+ 0x9584b271 0x9a3bb26e 0x39aa6d36 0x2fba41db
+ 0x133797be 0x9993699e 0xdb50268d 0xccd54ff0
+ 0xb7a33011 0x71db612b 0xef9a4429 0x7217f1d0
+ 0x0ee420ba 0x1f7eb025 0x26572853 0x72712e17
+ 0x5bd7be37 0x74b2288e 0x3ffd1f1f 0xed566562
+ 0x744f4159 0xdbedb36b 0x69e25131 0x604ccb70
+ 0x50d83542 0xe4704ddb 0xdc5144aa 0x33467434
+ 0x1c7c4f2b 0xac774e8e 0xce9c4d1b 0xa0e3c7f7
+ 0xffbecc1c 0xa1c25fb2 0x0e9f6039 0xbe9ed6d0
+ 0xf958fb6a 0xaec3fba8 0x2944e767 0x77dc717e
+ 0x06e9fe1d 0xaf3a4928 0x7d4f3f29 0xead3972b
+ 0x65670bc4 0xd058cc70 0x9fb58c45 0xf5f08926
+ 0x9aed1955 0xb1a5d161 0x14b5aa11 0x66e14cee
+ 0x28d7aae3 0xae45fcec 0x92dc7dc3 0xe9eda97f
+ 0xbee84f22 0xea6f71ac 0x6347c2b8 0xe919afff
+ 0x2c409d7c 0xa9800c52 0xd8033a17 0xc3794565
+ 0xb5311fe8 0x80d8a030 0xf9cf179a 0x508ea242
+ 0x4464cd33 0x91da91a8 0x6c0806cd 0xb5473d09
+ 0x0a0b99b3 0xdaf528eb 0xca1e99e7 0x064055ef
+ 0xc2dce623 0x0b4c15ac 0x23c13327 0x3f9fc266
+ 0x335d9c40 0xaca940c2 0xc18c0797 0xd5027a07
+ 0xb0a4d322 0x2e601275 0x6cc88888 0x658eaf8d
+ 0x509e2247 0xbae254d6 0xf097f138 0xa163751e
+ 0x19558f7c 0xb66f0cd4 0x87b1d966 0x81dd2cad
+ 0xf0c25e6d 0xb8e72dd1 0x00f15f42 0x6d2c1c68
+ 0x43c7e436 0x68eedad4 0xc2686b38 0x6ff30211
+ 0x197c7734 0x905b8602 0x6ab9d204 0x0d16385c
+ 0xb1cb5e16 0x8249a5c4 0x29d1ce0e 0x779f7b63
+ 0x63042725 0x12ce98e3 0x11282058 0xca3a9eb2
+ 0xdb8294e7 0x423e41ac 0xc3ab2774 0xca658d6d
+ 0x519f8896 0xaf6010f0 0xd57a94aa 0xcc17df91
+ 0x7d25cf8b 0x041e6835 0xa056d9e0 0xf90f3964
+ 0x7f99ae59 0xd80125d7 0x9961d6e5 0x41b3da06
+ 0x65c254e4 0x787d2c61 0x16aafb02 0x157ab4a8
+ 0xdee3674a 0x1ed1b601 0x2e36dae9 0xad57ad38
+ 0xaaf25b15 0xd3c37a01 0x68ca9eba 0x2a1bc480
+ 0xba157917 0xc00017c0 0x190bd74a 0xd6c6c1cd
+ 0x4efd4f71 0x388ed702 0xc8812950 0xd0019ca4
+ 0xd44cc835 0xd838fd6a 0x1432ce88 0xce98d932
+ 0xaea21cf4 0x54a44cdf 0xdb4dc5ad 0x1d23a7ae
+ 0x5ae126ad 0x100dcb50 0xa9727413 0xcf1c61cc
+ 0x72f9d2f8 0x4d32d201 0xe27586a8 0x0a1cc932
+ 0x21858469 0xf1cda3f2 0x59703f35 0xbd81f9f4
+ 0xad6ac9cc 0x25665703 0x1212d5cc 0x98a243d3
+ 0x8f47e113 0xd98feef4 0x3c93e832 0xfd67097a
+ 0x0c73fea5 0x6132ec59 0x1dc9bdb7 0x791f79eb
+ 0x84d83574 0xbd5817e6 0x7d5a0f8d 0x18482a08
+ 0x53ac8e4f 0xadd3378f 0xd48540ac 0x4082f5d2
+ 0x3ff5badc 0x24855b3d 0x7bb948f8 0x72637822
+ 0x0687e93b 0x61290b4b 0xd9f20b3f 0xcc0e5beb
+ 0x141ca01f 0xecd1337b 0x8576ec65 0xb6f825a2
+ 0x8b84e8b6 0x5bac53f1 0xd4edd06a 0x76ae712b
+ 0xdc00a887 0x798c2ee1 0xe74a5ab5 0x1539fa68
+ 0xa30817da 0x06f7c53a 0x1930c59d 0xd4232359
+ 0x0dfb1427 0x58d7180b 0x53bf57f9 0x5f001d08
+ 0xd08128ed 0x3208b7be 0x5c2aba8c 0x0abbd0d0
+ 0x424f2041 0x7982f731 0x010ec811 0xa3489c82
+ 0x71ffdfa7 0xda0ed41f 0x8a9e806b 0xfa9bddcb
+ 0x7a9e1a41 0x53c7603f 0x9e3df28d 0xd06dd100
+ 0x2cc64f4a 0x0dfdccf2 0xb4eb9101 0xf56d506d
+ 0xdaeed218 0x45523a16 0x4d6d68ba 0xff9a8f72
+ 0x5358b2f1 0x2511a591 0x9ea2c2fb 0x08cafc7d
+ 0x7ed34bb1 0x0cf2301e 0x62b6c05d 0xc05095ec
+ 0x52128c55 0x030576af 0xef5f37a5 0xdf5ae47a
+ 0x39e55496 0xb2c2129e 0xb2d67d77 0xc5adf049
+ 0x15a1cb4f 0x981948e5 0x7d18acc0 0xec7abb43
+ 0x23f7e366 0xa919a355 0x23872683 0xb7b6d84b
+ 0x4767dab1 0xd133feb1 0x2e5536cd 0x587683d4
+ 0xa181575c 0x4329e640 0x1244ae40 0x5be82f66
+ 0x4b28dc4b 0x4106c9a9 0x517fad7e 0x9e334ca8
+ 0x3c3ba741 0xe902a475 0x91d046a8 0x31361f96
+ 0x911b83bc 0x6607fac7 0xdfbc6390 0x7213aab0
+ 0x8ca8a47a 0x4f3d1f3a 0x3ee76c84 0x22bac3f0
+ 0x475f3cab 0x05d05569 0x92b3f912 0xc632a733
+ 0xd79b7448 0x595b82fa 0x6013b96e 0x6d03b5eb
+ 0xe37045fb 0x6e4add26 0x11f116da 0x4ac8bd3b
+ 0xacb5f8a9 0x8fb943d6 0xa9ac31c7 0xf1ba9752
+ 0x43a6b29a 0xf123766f 0x536fcc32 0xcf8168ad
+ 0xd8fb1e4d 0xb9562fa5 0xfe6d8dea 0xd31ab16c
+ 0xf7dfc381 0xb70f11cb 0x371c6688 0xac3fccee
+ 0xf130a51b 0xc5b8cad7 0x0cb13762 0x64ae00f2
+ 0x45cfad12 0x753d6a4a 0xc6f69472 0x695fba60
+ 0x49d1f754 0x9db947f2 0x2364ae20 0x197492e4
+ 0xc5b9562e 0x34963cec 0xdc26402a 0xa1c88d01
+ 0x58e27195 0x9d60f5c4 0x3e200a43 0x7e9827f2
+ 0x0a4feee5 0xd401e139 0x17352152 0xd509564a
+ 0x4b3142ed 0xef7567fd 0x9a619dbf 0x56ec2cb7
+ 0xc64bb290 0x3d69fd89 0x897325a1 0x74e2cb7c
+ 0xf270fdac 0x2beb6a4f 0x5b60de30 0x49df7517
+ 0x294966cf 0x87f5f667 0x4a9e1f6a 0xabc332c3
+ 0xfaf358aa 0x5baa6cfb 0x36b99bfa 0x40259687
+ 0x584539e2 0x2710ce99 0xec1959aa 0x642c8413
+ 0xfc005d36 0x2b2e6245 0x0012d041 0x09f6b626
+ 0x70fe9e2b 0x3cf30c5c 0x69d0a3ed 0xfe621601
+ 0xb6fa9267 0xe9b507dc 0x49f35866 0x4b97647a
+ 0x9e721adb 0x89e6e8d6 0x407a2f49 0xd977cbaa
+ 0xd9359f5d 0x7b69702d 0x22d6e818 0x57eaa5a3
+ 0xdd5063b0 0x4d7d2312 0x7a865203 0xb7f0905f
+ 0xdd2c2b87 0x7215803c 0x1abe5307 0x2926f38b
+ 0xf6b0cacc 0x96f50647 0xb612feb7 0x6915bfcc
+ 0x058b5cb0 0xc39e47d5 0x7513abdd 0x9e43972a
+ 0x1e55f640 0x896db1c5 0xd9382d2c 0xa52c1f99
+ 0x8afaf5cf 0x36500aa3 0x2e65fa1a 0xbb40d668
+ 0x81188e3f 0x143fba69 0x3f61fc90 0x438d759c
+ 0x893bb96a 0x069f349f 0xffdc43c7 0x6ebfa943
+ 0x671b4751 0x629cec23 0xe717fb9c 0x53fadc0a
+ 0xddc1e212 0xb99788ba 0x78378cf8 0x2ed91106
+ 0xec1de376 0x98d86b3a 0x312a190f 0x0208a0da
+ 0x6dcb469f 0xe6407c6b 0x1c7fea86 0x83841afa
+ 0xa9caaffe 0x86e3fd0a 0x918af9b0 0x0fabdf39
+ 0xdd9fc8f7 0xf9ddd98f 0x3dd0acce 0x2064360b
+ 0x29006620 0x5d7733c2 0x682c4093 0xf038a8b4
+ 0x3a688845 0xf9d0b9d2 0x27f51a57 0xb63b063c
+ 0x533b082b 0x7f0d0dd1 0x7abdb018 0xea6f6176
+ 0x13394ac6 0x825339bb 0x1835fd8d 0xaa46df84
+ 0x0751fe4b 0xbc9fb7c7 0x233873ff 0xca200e1c
+ 0x668fd5a5 0xda059135 0x2baf8828 0x7a2efc0e
+ 0x7c63d98c 0xe71ea373 0x0f218e88 0xa031f88f
+ 0xf32bccf3 0xf15eadad 0x6df44be6 0xb2536e4b
+ 0x2903a9aa 0x42ef8689 0x444432f2 0xd27a6c4c
+ 0x0992a32e 0xaf6e65d2 0xcbefdf23 0xe602151e
+ 0x21beace6 0xd9b992b2 0xe43286cb 0xdb315c09
+ 0x0de7672d 0x9d518ff0 0x75c4e9a0 0x64b2f70a
+ 0x9deb697d 0x5bcf59b8 0x2e4b9a8a 0xd9294b49
+ 0x3fee760e 0xfba8fec6 0x1c140305 0xe400487f
+ 0xc4cd4a38 0x14e6f1c6 0xdf98e7f8 0xfa6c4992
+ 0x62908c82 0x37393196 0xc02464b8 0x4b119742
+ 0x83e5e79d 0x15ddd908 0xf75d1820 0x363025b9
+ 0xd9e1a04b 0x9e110da7 0xd8caf954 0x30f62bc6
+ 0x875fd2b7 0x8b67bc8e 0xd5c77d4c 0x1a8ce00a
+ 0x7cfb14dd 0x3a39fd65 0xaecc2b5f 0xb017dbb5
+ 0x6a57b4f3 0xa27b6509 0xcdb06076 0x000d6366
+ 0x66e4f311 0xf22e25d7 0xf91d9bc5 0x5f9d3a05
+ 0x3b37c96c 0xb0596f50 0x53c24ede 0xb620106a
+ 0x5e675314 0xd98d5b02 0x75261f6e 0x5610c20f
+ 0xedcbe43f 0xbe85b8c2 0x16f7ffb4 0x55eb91fc
+ 0x2605ab1b 0x5ad3b426 0x3658d764 0x639c0560
+ 0x987249ed 0xdc470fa2 0x0d112f6e 0xd8ab77f7
+ 0xaed9455f 0xd9f6a341 0xb9b21249 0x3ff2b69f
+ 0x37ad61d4 0xdd6a089f 0x609233f7 0x46a923f4
+ 0xe5c23e8b 0x6aff8687 0x5e8ece1e 0xc65e1e4f
+ 0xfb96cf51 0x9b697cce 0xb08e02e2 0xf874e0e9
+ 0xbc983fa6 0x870375e3 0xc88bcd2b 0xc6bb19ae
+ 0xaa0c99e3 0xb301ab7f 0x024ba529 0x4449828a
+ 0xd226454a 0x0a610f3a 0xf302a0f4 0x021a3cc2
+ 0xa9e4b6ea 0x0b690b92 0x3379c01c 0x36265ea4
+ 0x29fbc8a3 0xe6279573 0x3cdb8a1e 0x005b5332
+ 0xbab71a8e 0x9677db73 0xa8a6d6ea 0xf0afbd3d
+ 0x576fbee6 0x49a54473 0xfa7c6e95 0xcb914daf
+ 0x58266856 0xa6b53a63 0x7136515a 0x2a3da411
+ 0xb1c994e0 0xbdaecd7b 0x5b436ff8 0x6334ec5f
+ 0x0172b5d2 0x57acd652 0xca4efacd 0x87e7d313
+ 0x78ac87c8 0xaf7602aa 0x3769ff6e 0x86d39747
+ 0xd32a7aa7 0x840cb30c 0x3e7da9b1 0x3c905b44
+ 0x90290dd7 0xebc85f3e 0x32693a53 0xc7140058
+ 0x6ca5cf6c 0xdabfbc3b 0x3d559486 0xe5ce93b9
+ 0x8d3c428a 0x9d18b8ee 0x404f58d3 0x151b4a78
+ 0x2f393e9e 0x69c59344 0x7879e974 0xc32217f5
+ 0xb946562f 0x1d1b8745 0x3666cd1a 0xc6a1e2ef
+ 0xe22d2e5e 0x9e7ed504 0xe6c32118 0xb2919117
+ 0xb2bad34c 0xe7177e87 0x47b68328 0xe579fe7b
+ 0xd0d33f00 0x96923c90 0x5ff2bf45 0xff074961
+ 0x4dce1092 0xe8a89464 0xc0b1ea51 0xd65f0f12
+ 0x6b2389bb 0x48fa0960 0x82722b27 0x62625540
+ 0xd4ff4985 0x768b7c26 0xb36a4ec6 0xf6a66375
+ 0x1c89e246 0xb629fce9 0x6aa72399 0xd783733f
+ 0x6478b123 0xa374412c 0x11b5cfc8 0x73cf2286
+ 0x443f5601 0xd817fca7 0xb2ce2d63 0xf6c63479
+ 0xd16b0550 0xf2a52ac4 0x7843803c 0x1ac3b58b
+ 0x7f96b915 0x732403a1 0x64634349 0xd2ec0bf9
+ 0x10410c08 0xe95d8dfa 0xaaeb33a5 0x57893eaa
+ 0xb59afac2 0xe9fd6dd2 0x50d11a7f 0xde479c58
+ 0x9dac27dc 0xebba7d8b 0x17fa1420 0x74a1678c
+ 0x71ccdaa3 0x5e44b0bb 0x5927a75a 0x7b7580a8
+ 0x33330c9a 0x40192652 0xba6308de 0xecc81fbe
+ 0x41d48824 0x6ce4e0c7 0x145e9225 0xf8484bee
+ 0xc8675611 0x750ec207 0xfa5f5b85 0x618b9f8a
+ 0x007cdb05 0x67f98d4b 0x1035f305 0x8d700e9b
+ 0x9857a0bf 0x4b774ad8 0x8960c81e 0x344a9462
+ 0xee2680d0 0xebb5f6cf 0x7397c9f2 0xcafa01ec
+ 0xaf69f3f4 0x0a1699cb 0x90ed82f8 0xc5c8ac04
+ 0xe50bd06d 0xf75741c6 0xea52365c 0xd0c03f33
+ 0xb5e4e95c 0xebf55379 0x0aae6e4a 0x29f8b91b
+ 0xef8ad2b9 0x7bebf2ca 0xb194b728 0x7df7b083
+ 0x0ea527c4 0x6d55939f 0xb9242c58 0xb3e1f570
+ 0x4fba0507 0x82d7259b 0xb5be7b54 0x0aff6ff9
+ 0x88391023 0xfe352956 0x4a6bfb30 0xa00c9644
+ 0xc478d534 0x0cdb509d 0x9611713c 0xd7c442be
+ 0x8d16889f 0x93abfefe 0x435fa757 0x40d95d3d
+ 0x11b7bdce 0xd074874b 0xdce6add2 0x0b652a4e
+ 0x595a88e6 0x307a223d 0xb624b9bd 0x855ba51f
+ 0xad43c800 0x1fcf6afd 0x4bdd921a 0xd6777384
+ 0x8da9f15f 0x5fb03ee2 0x5e6d04e2 0xb33751cf
+ 0x55d9d38e 0x41589fad 0x6d311b4a 0x43046a7a
+ 0x8d9c7304 0xe25f9788 0x8b459e1b 0xc9a3cfe2
+ 0xe6ab721e 0x4de3c89c 0x5c2d2398 0x085d8d69
+ 0x4e27ce73 0x1cc1f44e 0x05aeaebe 0x8cedb916
+ 0x370b4d46 0x1bc29579 0x33d08b75 0x06b77cff
+ 0x155693d7 0x125d3f0b 0xd8714e15 0x3b7427ba
+ 0x13f6684d 0x834ee449 0xc5a45189 0xb2ad214c
+ 0xa61be586 0x4e4727cd 0x563d1c31 0xd4ba1cc3
+ 0xdb08cd16 0x4940a42c 0x43dfd0cc 0x9d43222c
+ 0x638a0d11 0xc33d3992 0x98bf11f0 0x1aebf6b5
+ 0x1e206582 0x5647f772 0x9255ad74 0x75915665
+ 0x0fe7dd12 0x9def740a 0x9361bdf1 0xc1409fc0
+ 0xd3bac631 0x7492ee87 0xe1e99dde 0x2fbaf552
+ 0xfc24f52c 0xc080882a 0x0a2417c8 0xcea3da70
+ 0x4fe34fad 0xb4e55427 0xd5d54d76 0xf36686ba
+ 0xd6ab1798 0x1868e364 0xa380f948 0x0eaee02a
+ 0xad5a44e8 0xb6d119f4 0x82a43444 0xafad0e68
+ 0x595c3ab7 0x385746b3 0x32df6d2a 0x0b01b2de
+ 0x51d3d6bc 0x107d8620 0x6d215143 0x29d0e901
+ 0xbc57a3ec 0xd584ba34 0x8c244547 0x23d396fa
+ 0xffb03cb4 0x8396c1a7 0x3f251905 0x8bc769b3
+ 0x68f4696c 0xfc297895 0x9ec65e40 0x22deb20b
+ 0x5d1def76 0xa7a095b1 0x3aa6a458 0x6ca11880
+ 0xcde44ece 0x62b59f4c 0x067f272d 0x9a5aae97
+ 0xc60a8d62 0xeb0f40c9 0x83ebae30 0x07dc9cb0
+ 0x05dbdc76 0x0c108eb1 0x314f9247 0x7bfd6072
+ 0xf648e1c0 0xae70bd5e 0x7c27b4d1 0xb0cff1c3
+ 0x8c2dd93c 0x580a4b19 0xfaa1ee8b 0x4173a23f
+ 0x838fa15b 0x2b0fe3c5 0x8059250d 0x659a445d
+ 0x2a1c1968 0xbf13412b 0x1a9f915e 0xaf80263d
+ 0x24508a66 0xe381d252 0x4e0f55a2 0x7ce1f4fb
+ 0xc145da4d 0xbd4b29c3 0x27540ac2 0x23ad4b42
+ 0x8e6bcda5 0x20061c20 0x1d3cb3fd 0x5c5498f3
+ 0xc468681d 0x4c28ef55 0xf0165c1d 0x2dd6d032
+ 0x7e347ccc 0xe04db59c 0x7caa883b 0x1f43df4f
+ 0xc300031c 0x85f19e9b 0x22811fa7 0x2622940e
+ 0x6299f57b 0x5c106568 0xd7da296e 0xccd36b39
+ 0xe349afc0 0xd2c2463e 0xf7f55aef 0x0e0a7e3d
+ 0x6b6fc6d1 0x8854098e 0xc87edace 0x8190c437
+ 0x333b8ec6 0xe49b3a5b 0x4aecd4e3 0x14cc5f22
+ 0xa11faf96 0x3d1cd023 0xae614c70 0x0ab662b4
+ 0x908d8082 0x76316cd0 0x3068ec32 0x829b047d
+ 0xf08d1b94 0x3b2b33f6 0x03df9ae8 0x40f632d0
+ 0x3590085b 0xa33aad24 0x39597da2 0x99415f4e
+ 0x7aed6e11 0x61a920ab 0xca851d8b 0x2606f821
+ 0xeb7c0e8b 0x8bd6edb1 0x725b39f6 0x3afa6248
+ 0x03540044 0xfb118ecf 0x8e18bd5a 0x2a85cc05
+ 0x4ecac12f 0xf53a4d25 0x8e3fc6fe 0x32233799
+ 0xc7ebb5e6 0x058fdcaa 0xe6db17ed 0x2751405c
+ 0xa195a515 0x34410c51 0x4517154e 0xbbb5674f
+ 0x28050e40 0x8fd71724 0xbe78711c 0xc1b18693
+ 0xd202b9d2 0xdf4e0b62 0x460349da 0x71463aef
+ 0xb2fb55d3 0x54a972dd 0x49379f09 0x7a7fdff3
+ 0xbd82d4f8 0xd2894393 0xa82bca57 0xe61ca9b4
+ 0x9e08e6a0 0x53dffe9d 0xe7ae1c5c 0x65bff365
+ 0x7564aef8 0xd94abd3b 0x18d1ba52 0x64a759f0
+ 0x65c5dd4f 0x6f9d433a 0x57cb5a25 0xc1862d25
+ 0xcf50223f 0x90c2724d 0xf5527605 0xb085f18a
+ 0x41e2b17d 0xfb1cabc4 0xd8ab04cc 0x761c2166
+ 0x8365afd4 0xc3276657 0x14f64be6 0x5dd779b7
+ 0x3b3f1faa 0x358d01e8 0x4c821ddd 0x7ada9f95
+ 0x2970bad5 0x3b54a4bd 0x3ca7f039 0xcb67aabc
+ 0x3b264655 0x96401a5e 0xa3990376 0x90834685
+ 0x8ba56352 0xee98c564 0x4a0534ed 0x7d70fad6
+ 0x5d73a1e7 0x23fd8de5 0x39c52296 0xefef1540
+ 0x7bc934dc 0xeed157b4 0x898d8bfa 0x5761e88f
+ 0x73af2674 0x2fb88d9e 0x28de1281 0x9aa76119
+ 0xa3ac21ea 0x28ce635c 0x7596d79a 0xd3295e0b
+ 0x7826630d 0xd815ef01 0x27cf2899 0xf3de6a01
+ 0xcbb32e58 0x6c57be3c 0x292f819f 0xaa4623d6
+ 0xb96ab772 0x90a6f778 0x44b9933b 0xa43e7543
+ 0xb9f417b7 0x7a6537a5 0xf36a6da2 0x0a9bb3fb
+ 0x177c1f28 0x0512c07f 0xdda55932 0x060dda31
+ 0x14465771 0xf3f96780 0xb459e5e3 0x49aaefbd
+ 0xb07db15d 0x2ac82807 0x8404060d 0x417d036b
+ 0x70946fb1 0xe39e68f5 0x5f9b3035 0xf0335e7f
+ 0x2ba457c6 0x2d97ba3a 0xc05156e7 0xbbc9afb2
+ 0xd25981ea 0xe70d060b 0x805c231d 0xae471b34
+ 0x31964d8d 0x3f34e35a 0x8355ee21 0x73822024
+ 0x9ce5f2d6 0xdff19812 0xae55cbaa 0x55f5ecbd
+ 0xfe558210 0x09b95751 0x41ee7cb8 0xd2b9fa15
+ 0x342c07e5 0x7ee50e8e 0xb6154e01 0xdbf4df3a
+ 0xd43e2c77 0xc3ff0498 0xd8106f33 0x9bdb25bd
+ 0x40cb843e 0x106b08a9 0x3227ce7b 0x58bb7cb6
+ 0xb84e3244 0x3f1d0e20 0x76dcbcfd 0xb750bce7
+ 0xa8c11f3f 0x161a8610 0xdc1ef5bd 0x14270b6e
+ 0x285e7898 0x68375db6 0x01d23b44 0x35a17fb0
+ 0x7c9ad882 0x7bda2e0b 0xca67bfcf 0x6e2dd9ab
+ 0x227a6aba 0x5d295397 0x5061f96e 0x47a20c68
+ 0xf5427e3d 0x3a0a3165 0x2438fd9c 0x2dc91147
+ 0xeabab62a 0xdc358e4d 0x7e1fcc9b 0xdc2a328e
+ 0x6e6bf75c 0x68c45517 0x594fe5a7 0x2feac658
+ 0x1f0a4d49 0x97575e83 0xcccbdab8 0xc13f3b64
+ 0x8bfe659f 0xa4ebf545 0x2c3cf874 0x7d78ceba
+ 0x46ac5d6e 0x09309533 0x78ffb6e3 0x7336541e
+ 0x3d270f70 0xd71e72b4 0x9772402a 0x4ed185b7
+ 0x213da698 0x78a54587 0x18054eb4 0x99179a25
+ 0xf758337b 0x94629a30 0xec6bf4e0 0x255ac299
+ 0xe56f52b1 0x1c2a6136 0xfb7cc1f6 0x87b53b53
+ 0x079ca1f7 0x3a8c340f 0xeb70ef48 0xfd1caae4
+ 0x564445e7 0xc1d5c663 0x658fb5fa 0x62d2debe
+ 0xc0907042 0xb5402269 0x16965193 0xc038c21f
+ 0x780f8b76 0x33ffeb3d 0x03ad9602 0x4a7b6432
+ 0x93c2b2f5 0x40720fcd 0xf44c164f 0xcbd43d01
+ 0xcf7098cd 0xc43242fa 0xc530a6b3 0xcc33c1f7
+ 0xde3d648c 0xf1def13d 0x2a22f5d1 0x77704fc6
+ 0x08ed5552 0x3e2295d0 0x00584764 0x6af8585e
+ 0x43f845da 0xa92e38df 0xd98c12b4 0xb4fac901
+ 0x0b05a079 0xa05f215a 0x27d635c6 0x9fc897e5
+ 0x0eb91a30 0x43bdad4c 0x705df05f 0x6b7864b7
+ 0x1b6380ba 0x4a64e8ec 0x517b7b68 0x67336d4b
+ 0xc6d51eab 0xfac40c57 0xb977cbcd 0x0674e5dc
+ 0x74ce2339 0x891cc5f5 0x3230ca78 0xa8a653a0
+ 0xa8d4b370 0x496d2f7f 0x6ca677c5 0x54260ac2
+ 0x630e1143 0xcbf6f819 0x546b2874 0x02267559
+ 0xa2e23914 0x7c9a0393 0x1704bcb3 0x6d680415
+ 0x91da300d 0xe2ce21d2 0xc38faf3e 0xcc8be7cb
+ 0x14496036 0xc98e253a 0x05ca6582 0x8c566616
+ 0xd26204dc 0x3335bd81 0xa94e5af0 0x76fbb455
+ 0x23b27f08 0xc4db6f93 0x5cb5401c 0x7cb2ed29
+ 0x7cbbad8b 0xfc1e8f5e 0x2bc79e28 0xf69228fe
+ 0xbde16357 0xc9ac3b53 0xa6afbc74 0x984bb3f4
+ 0x98a8b9d6 0xdd21c848 0x33e65c3a 0xc53c772c
+ 0x633022f8 0xa324bd5a 0xd260a77a 0x668ca5d3
+ 0x4b79a6b3 0xbfd19bbe 0xca2eb497 0x8e7eb5c9
+ 0x169b2184 0x0503d4f6 0x24f35c00 0x0ac930ab
+ 0xf694120f 0xcee12db4 0x9305757c 0x798a2db2
+ 0xed27ebec 0x2f35829b 0x4294e805 0xa7994ad7
+ 0x49fd229c 0x5d63fe52 0xb7cd7641 0x1a68af3b
+ 0x6f952e97 0x1c02f4de 0xca3a1515 0xed5bf092
+ 0x123c32ea 0x602030aa 0x7811cd1f 0x1b6c38dc
+ 0xeb7712b4 0x4aa767e1 0x6b49d384 0x7ba4ee1a
+ 0x87f02cd2 0xb8e6b0b1 0x090e9f89 0x95f8b90e
+ 0x8d76892c 0x0be06870 0x9ec963c1 0x75d67c9d
+ 0xdde23799 0xf9e3be20 0x549442fc 0x09cb0906
+ 0x95ee6c4b 0x25a2d9b7 0x98154023 0xdda91829
+ 0x0c46879b 0xfbf0e362 0xb7223786 0x7cfbc839
+ 0x3b251e5c 0x8be187a6 0xa24f9da6 0xc3192693
+ 0x7a8ac8b9 0xc493ca03 0xc736b974 0x369db725
+ 0x85a6e92f 0x26dbef75 0xa61a71e9 0x38a08fb9
+ 0x4a214ed6 0x57fc6f4b 0x9cf91617 0x322e13fe
+ 0x5ac816a3 0x748a9728 0xdc777bd6 0x69fb5335
+ 0x258439e8 0xf171a221 0xfa7a07af 0x26447b9f
+ 0xadcf3734 0x5af34b97 0xf8b4b0dd 0x08c79517
+ 0x28861618 0x64692555 0x19fe9897 0xe3bda02c
+ 0x77df51ff 0x93dedf7a 0xc7cb57c4 0x02ee5928
+ 0xd4aeb644 0x01d511e6 0x6512bd02 0x5d8f90f8
+ 0xe77ccfe0 0xe6ee3ecd 0x5403139e 0x6f7075e5
+ 0xb6484511 0x3bd42a35 0x5dcea90c 0x5bb1c6e1
+ 0xb69b5847 0xfe106914 0x74442ce9 0x10997c57
+ 0x1595af7f 0x9f04a8bb 0xa7d2870e 0x19e57681
+ 0x54b276be 0x11c3e3f9 0xc5401783 0x9c413cda
+ 0xa6aa9e8d 0x23ff8569 0xf1797ea7 0x86ce3e8e
+ 0x9ef0a776 0x56a1c30d 0xf5e18916 0xb11464d1
+ 0x7f313c1e 0x49c15cff 0xe2dcfb73 0x637819d8
+ 0x2d6ce0e2 0x2170cd43 0xb750902d 0x5eb02cd2
+ 0x6cadb7d4 0x89b96f3b 0x8d749ca2 0x8ac7abb7
+ 0x31fbdb51 0x7a6df774 0xfb9139f0 0x56f3d9c3
+ 0x0f104f2f 0xfaba3c49 0xe53aefff 0x932237d0
+ 0x8ee10e80 0xadad6e20 0x19883a1a 0xf45a543b
+ 0xd560ff0a 0x8c7b4e03 0xe35696d6 0x9e0ec159
+ 0xfc2cbae5 0x6ce2cddc 0x14a72474 0x89757fe3
+ 0x6b788e7b 0xc16fa200 0xad36bdf7 0x57bdc4d1
+ 0x55146f2b 0xa57db4c5 0x313952e1 0x2c55d0d2
+ 0x32ab0208 0x10f846bc 0xdcba1674 0x436485bb
+ 0x932704de 0xcd7e2e1c 0x59f78879 0x7ca21395
+ 0xbcc07be6 0x2b101e5b 0x38924c37 0xb90928f4
+ 0x8f824214 0x55699b67 0x54cba493 0xe71c27a3
+ 0xdde01c05 0x48d822fd 0x734ed8fe 0x29dbf298
+ 0x9ef3a499 0xfb517934 0x19c8ce8b 0x38b8bf00
+ 0x75da50eb 0x237f3b1d 0xa8940707 0xa98a4149
+ 0x35ec2d39 0xee862d31 0x36659949 0x8f3dffc2
+ 0x70afb227 0x94f443c1 0xb6f9308e 0x0e8ebd54
+ 0x92b8960f 0x56d21560 0x8453d1ca 0x74c680c0
+ 0x2d706dfc 0xd0b81c18 0xbac65445 0x40a34988
+ 0x498145a9 0xf436ae10 0x9b72fec6 0xb4100aed
+ 0xe305983c 0x349fe379 0xbf31cfa7 0xba624703
+ 0x4a491754 0xf973a686 0xa2ba725c 0xd0a23615
+ 0x31903086 0x4ae46e45 0x0f705e05 0x4ea6bbc8
+ 0xbf299e43 0x0689709c 0x9fc93571 0x07cbc14f
+ 0x542ef992 0x80ce91f1 0xf86014aa 0x17d533d1
+ 0xb55e63e2 0xe02e0e4c 0x88a5ed22 0x6302126a
+ 0x56b32e90 0x5fec4381 0xe2e98b3f 0x30693509
+ 0x862e1d75 0x2da30e3c 0xad992d90 0xc62cae4b
+ 0x379c77ba 0x467ea8f1 0x8a820048 0x74cc474e
+ 0x6bca3803 0x18aaa3f3 0x1fafd26a 0x0865f360
+ 0xe3479d10 0x6cefb2b9 0xf6612730 0x2e0f222a
+ 0x749a89e0 0x75b1fa05 0xe2ea0874 0x5d422c20
+ 0x24707d46 0x6d475835 0xed1e556e 0x6aa4543e
+ 0x28b36c16 0x22d83c4a 0x8c3e6d51 0x42a94c9f
+ 0x0c603d0e 0xa8c7f417 0x845997ff 0xdc79494e
+ 0xa130d628 0xc2df082a 0xa3a2c27e 0x3f93b00f
+ 0x1521a7e5 0xca15bae4 0x57e4e836 0xb915a471
+ 0xd9147115 0xad52f80e 0x5fd2a2be 0x15972ed7
+ 0xb69ec21c 0x502f2627 0xfb46a1ca 0xea685d34
+ 0x9226f7f2 0x4b41927d 0x7965eaa0 0xb702e76f
+ 0x79a54721 0x5b8e984a 0x37efcd59 0xfeabf30a
+ 0xd4ad7db5 0xbb2282ab 0x8a5c840b 0x2ba370c5
+ 0xdef5758d 0xa69a9aa1 0x46082250 0x6e8e8477
+ 0xf6280c61 0xf99e4a14 0xcf3c5cbd 0xcce657f0
+ 0xca635eae 0x0be182b5 0x58e8b43a 0x5c717ce5
+ 0xaa7aaff7 0xc329c6b6 0xf1cc91ef 0x8d7cc520
+ 0xda155783 0xd5e2e54c 0xf466f010 0xc5dfac4a
+ 0x606ad5de 0xf4992f1a 0x1344c9ce 0x4aea9020
+ 0xa30447c7 0x0a99ad18 0xd3caa96c 0xfe5b0b4e
+ 0x7b50bbd1 0x33e50575 0xa22d1d06 0x73a1820d
+ 0xce4c4c8c 0x2cde7764 0x511d1c26 0xad0cf826
+ 0x086dc311 0x3060ef7d 0xe6fdc617 0x3050b179
+ 0x1dbb5316 0x4145fcb7 0x2eb62505 0x2e1359e2
+ 0x79cab612 0xaa9282c9 0x7eede562 0xb016f7ed
+ 0x1445fefb 0x809b2e00 0xfafaa754 0x69ac113c
+ 0x548a6e3a 0x6d444c14 0xb3d355d8 0xbbadcd2b
+ 0x3032d634 0x7df39948 0x4c1f9098 0xa9d138ce
+ 0x42823bbe 0x2ef39e3f 0xaaf9ef1d 0x63369afb
+ 0x2bb76c9d 0xb7d38558 0x354160ce 0xc04c6378
+ 0x6c71ab10 0x7914af1a 0x1c1a4694 0x2f9fce8a
+ 0xe28f18d3 0x3acaa573 0x2503b236 0x90ca20e1
+ 0xd2c77ccc 0xc3005311 0x836d9430 0xe91d8463
+ 0xb53e4cb7 0x4e373c67 0xd06ef659 0x27e1a21c
+ 0x285c0391 0x32046fa9 0x8b1b9c92 0x49a22f4e
+ 0x81411430 0x050110e3 0x56144e6a 0x47fb824a
+ 0xdb2e9a6a 0xb5fe97a9 0xabd37259 0x93da3055
+ 0x19fb35e6 0x66661115 0xa27149a2 0xfb7d94b5
+ 0xa315f9af 0xd7d97596 0x134d7d09 0xd5cde0e9
+ 0xbc3f143a 0x1b2061ea 0xd7b15227 0xe8f506e3
+ 0x0aa17e92 0xc8565276 0xc7d90586 0x22a26c8e
+ 0x6d462029 0xe7b1ad73 0xd11fa609 0x67643f2c
+ 0x64f1ef34 0xa0e7e0b6 0x9687611d 0x09c2d32b
+ 0xb494937a 0xcc36510c 0x70555bfd 0xfa25e917
+ 0x7d88b6da 0x30f3b531 0xd19b224a 0x999d0f7a
+ 0x9fe0da18 0x45947b87 0x536dbf3b 0xa6f5182d
+ 0xdf11f95d 0xa5abcdbf 0x7528110b 0xf54fe792
+ 0x71a97619 0x680bd3ff 0x6981ea39 0x683ff854
+ 0x302fbbe4 0x12129f84 0xf63cd448 0x69fe289b
+ 0x568da933 0x2f1e1146 0xe7404e52 0xcd329394
+ 0x02e41762 0x94456d4d 0xe9416a20 0x4e5920e7
+ 0xe8db71fe 0x527a5313 0xe42c7d9e 0x58c8c1fb
+ 0x28949bc1 0x312fdf97 0x3569f41f 0x3ed5f092
+ 0x44baef39 0x5c11d5ad 0xb5d172cf 0xa9e4cfa3
+ 0xbc5ed197 0x2f290ead 0x747f53ed 0xadf1b698
+ 0x1b90440a 0x4cdfe154 0x9b24b832 0xeb97d794
+ 0xc90fe91e 0x4fef1271 0x8bf96025 0xbdb49f79
+ 0x63910640 0x26a05cce 0x3318e422 0xb2fc61de
+ 0xf14cedd1 0x4bd7687a 0x8c4c91dc 0x48a857a2
+ 0xb47aac94 0x787526e2 0x99349c7a 0x0bd6ba75
+ 0xbfbc4b0b 0x040fbec9 0xd00de44b 0xc4c7f0f5
+ 0x74a8653b 0xbd3cc036 0xa601a4f3 0xb82c0da0
+ 0x2709b674 0x73065351 0xaf4cd23f 0x3481ea0f
+ 0x6a1fa77c 0x26a9d280 0x95f4a170 0x393e7590
+ 0x015b3d73 0x36d91e55 0x61a7f3f5 0xf6d39c21
+ 0xd9ee4701 0xe57af451 0x5e141761 0xf6b6e472
+ 0xa6efc965 0x9606aa1b 0xfb8ce005 0x831ab2d1
+ 0xfe7a1af6 0x5e326881 0xa0ad32ae 0x15f86ecc
+ 0xa1a634d2 0x3a40c4a9 0x88e10130 0x2e6c4556
+ 0x8526aa32 0xa81b0d30 0x19c83936 0xdcaa556b
+ 0x6dc8064e 0x5709ad31 0x1b6fba18 0x9ebe34b1
+ 0x28abc3e6 0xd76c3908 0x4374657e 0x6f0fc085
+ 0x4f19a108 0xb774421d 0x405228d5 0x123dbbab
+ 0x18535471 0xfc6bde41 0xd4b2d82e 0x65b85772
+ 0x64731e41 0x29e886f6 0x4c2c7eda 0x91586a5f
+ 0x15b2407b 0x5fa08a72 0x56898e51 0x5424e976
+ 0x19ce4a36 0x0ada4656 0xe634446a 0x478da533
+ 0x36f1c763 0x01ec46c3 0x5e1d1040 0xf6da1918
+ 0x831f8f94 0x43ddb630 0x80b5d4e5 0xfc403ba5
+ 0x40dcdd4e 0xa19d0aa9 0x6c32fad7 0x7cdd6f3d
+ 0x8e9c123a 0x42c4edd0 0xc8247030 0xf0e6cebb
+ 0xf8d1425f 0xcfa8e403 0x67646391 0x9dee9f9b
+ 0x5683c4f6 0xd958ae1c 0xc62eedfa 0xbd67ea10
+ 0x253398d4 0x18b7f92a 0xf101a7de 0x60066732
+ 0x4ca1e3dc 0x6e1eb0a0 0x115aa9e1 0x8370aae0
+ 0xe46756d8 0xa02eb1aa 0x854dbb8a 0x6334873e
+ 0x87613a81 0xb5bd56df 0x491371d1 0x02bbace8
+ 0x2a2e45f9 0x91bdc460 0x2bcf90b6 0x81df2f07
+ 0x34aa2dd5 0x5b54a117 0xb7a5bd42 0x713e2287
+ 0x1ea184d6 0x176bdda0 0xa19c0d86 0x4180fd5c
+ 0xd018a4cc 0x60120a37 0x8f6e094b 0xfebe1b15
+ 0x42866bb7 0x4a9f772e 0x0bcf9cad 0xd936a924
+ 0xec6cf0a1 0x1f9ccf16 0x81f8229f 0xdcef1733
+ 0xb4a31fca 0xefbf0a0a 0x057e0b4b 0x59491c96
+ 0x70ce99bb 0x908ce274 0x637ae09c 0x479fdd52
+ 0x11ea6250 0x7778cdf6 0xd0ffe2ca 0x539b18dc
+ 0xbcdab649 0x3066399b 0xd685edc0 0x79d8d588
+ 0x32942aa1 0xd03531f7 0x5d024d56 0x4dc99729
+ 0xd1efff53 0xdf3ce9a1 0x31462a0e 0xe5427113
+ 0x395e2980 0xcf5c9d4e 0x91e11088 0x7e4d31e2
+ 0x5ff91ae8 0x9340e815 0xfcb89789 0xcb1b2f58
+ 0x655aa934 0x2eb022da 0x419104a9 0x6b648411
+ 0x582048e2 0xa0db392a 0x1e1d6443 0xf3c7a401
+ 0x1e737591 0x452af94c 0xfcb74331 0x2da70f75
+ 0xa8b59eb9 0x736224c8 0x5ba81657 0xfb36eac0
+ 0x4e0336b4 0x8925a32c 0xa4d60fde 0x8a95ff27
+ 0x57a7e536 0x7e6a2f58 0xd9e9751e 0x817cc66a
+ 0xca4bd134 0x627382fe 0x00e56736 0x74844fbc
+ 0xab1f8265 0xa32955e3 0x41cd361a 0xb3ae6366
+ 0x1f77ea37 0x2200c6ef 0x81854e76 0x49ed4e92
+ 0xb57a7fbd 0x7b9de6d2 0x128feedf 0x57bb65fd
+ 0x20ccd650 0xdcde5458 0xd5461b27 0x465147f4
+ 0x70719068 0x2cb48f5d 0x6edc0d43 0x83dbda97
+ 0xf077ea64 0xf61423e2 0x39a55177 0xb23ff07c
+ 0xa02e4ca4 0x9e6250d3 0x77f1df9c 0x238c632e
+ 0xce253a6a 0x096327c5 0x87f1db29 0xd75ac0de
+ 0x456704b5 0x9ee7046e 0xd693dfe0 0xf995c6b9
+ 0xa354d140 0xf16bf090 0xaf511cdd 0xdc56d21e
+ 0xd7cc4d4c 0x5398cc1e 0xe5444b3b 0xe192f473
+ 0xd09ae67d 0x8af2775e 0xc1af44a9 0x57bc4586
+ 0xa6ff5419 0xdd4ba49d 0xec4864fa 0xda9d0357
+ 0x84dfbe33 0xf41ba9c4 0x99e2bda8 0x9fba720b
+ 0xa7dd9e92 0xa0d43386 0x3e0f9ef2 0x6e388282
+ 0x8f47ea95 0xac920523 0xa98ae8a5 0xf6a6a4d4
+ 0xc3fa2e55 0x74a21b36 0x9c0b14b2 0xc6b8a79a
+ 0x367b7036 0x24b9f255 0x0b543b75 0xb630fa41
+ 0x1b260452 0x7daf6714 0xdb8a13d9 0xede8f6bc
+ 0x47a21d0c 0x01d9ca54 0x4a8e5cd4 0x257cd217
+ 0x7504cecc 0x973bbf11 0x992b731e 0xaab55b65
+ 0x77e2f058 0xf580b58e 0xb10419fe 0x679aa4df
+ 0x296c1d64 0x751380f0 0x8f70f0de 0x3f78bdb8
+ 0x1ee68ad6 0x7d5d50e4 0x823710a4 0x18b98d13
+ 0x86bdf798 0x953b8131 0xb5da3d24 0x2eccd3b1
+ 0x828a154c 0xed51b913 0x566e58ef 0xab8ff1b4
+ 0xc744d227 0xe705bbc6 0x6032eb64 0x5495e4a5
+ 0xe83add11 0x08429de8 0xa2e397dc 0x4f00c90b
+ 0xcb7672e8 0xa1d55607 0x0741ca2a 0x323d64f2
+ 0xa700ef1e 0x6ccb2967 0x07c29e41 0x018440a9
+ 0xbb1880cc 0x35502720 0x8a13a96e 0xe2bfcd29
+ 0xa76ad3aa 0xd95be915 0x6dd66033 0x41d655f3
+ 0x02009028 0xb44ec634 0x82e61d87 0x216e624a
+ 0x7fc79105 0xac0307cb 0xd22fa331 0x63746b2f
+ 0xe51ab72d 0x9b550c82 0xb28dbc01 0xd569d017
+ 0xd168d372 0x8d6bfe6b 0x5820751c 0x820a4e23
+ 0x13cfd07a 0x678c8319 0xd1e65476 0x752967ee
+ 0xafb28392 0x390d5488 0x53668098 0xa0c92673
+ 0xaf0549c2 0x644f51c3 0xd59df083 0x7cb37a42
+ 0x12261017 0x038c15b3 0xccc30b03 0x85ee24ce
+ 0x1e029b23 0xb6bb2845 0xb62a305e 0x2d0cf4e9
+ 0x182b887f 0xec423ce7 0x8c1c0b25 0xc83b4737
+ 0x71fb9023 0x63d639f6 0x16c1ce44 0x66ac8331
+ 0xd9aa0975 0xba3d445c 0x5d097729 0xb353a034
+ 0x23811786 0xb81394b5 0x5323f1b3 0x7a3e1576
+ 0x3f2867ad 0x0bc88c8e 0x74b60d63 0xd56335de
+ 0x0d40f71c 0x55ec2524 0xea3a2c78 0x19e5e0ae
+ 0x9bf3d033 0xf57bbc94 0x05b6ac55 0x4c368744
+ 0xae8c68f2 0xf23aad06 0xcf94d185 0x2360ff3d
+ 0x0e8a87f9 0xb97c8d33 0xa7122e6e 0x5ad4dc50
+ 0x6145ff8e 0x617389df 0xe8a0e09b 0x4d40ce6f
+ 0xee2b65fa 0x4104d368 0xf4bc9d85 0x0b67abbc
+ 0x7bbad9ff 0x26b293a2 0x06055372 0xbbb05665
+ 0x0560311d 0x421dc535 0x9c451ac7 0x38c83a74
+ 0xc8921ff8 0x634d52c5 0x6e66dae7 0x1c86fae3
+ 0x5a0645bd 0x6e5fddc9 0x86852d55 0x76207d9a
+ 0x6a4b7990 0x661c00eb 0xb268e55b 0x17daec24
+ 0xa2854da4 0x9b1f3f63 0xdd200bc5 0x0b50aecf
+ 0x8242f913 0xc7ab6eea 0xaa977c22 0x748d0d1b
+ 0x4490aae4 0xaa293e18 0x69aa0720 0x6115eb81
+ 0xa5b187fe 0x828bfe34 0x5fb6d155 0xe764d755
+ 0x08833186 0x8475cce3 0x718bfb48 0x063b287b
+ 0x7ea71b59 0xbedbfd29 0x3736aa07 0xe2dfd533
+ 0xf2ea49a3 0x96b0983a 0xc1f60b14 0x511bed9e
+ 0xac976686 0x9c60ce3d 0xfffd0b07 0x59d7cf79
+ 0x477942b4 0xff2f43cf 0xeb4b899b 0x37a47783
+ 0x8e6602a7 0xb6bfc410 0x7685c6e4 0xb7ec103a
+ 0xd54fdb01 0x3933d261 0x725982d1 0x86ada0a9
+ 0x83788370 0xbafb1498 0x13972979 0x2157be41
+ 0x5e976c80 0x05501107 0xb3b66da9 0xeebcb8fb
+ 0x42ac1fee 0x1dba34a9 0x3f5a7582 0x362e7ed7
+ 0xaa69be91 0x419f4d18 0xb09a9967 0x31aba127
+ 0xaa247bff 0xb31f4958 0xe79562af 0xfb73878c
+ 0x47dc697a 0x5d08fa9b 0x91dcd3c2 0x53e52d33
+ 0xc84ddc84 0xdb5f8e17 0xe51889e2 0xb1aff523
+ 0x4ffa0702 0x2c72b35a 0x9a4246fc 0x62420517
+ 0xaad11acc 0x18190bf9 0x11e140de 0xacc99086
+ 0x39347992 0x191a53d7 0xbe92c4ef 0x9a934b5d
+ 0x64cf7353 0xe30a3e8d 0x0aa6db52 0xb0a7e26d
+ 0xc8fe2f52 0x2e274a07 0x0c94b6ba 0xf80eaf3c
+ 0x1ba3e94e 0x5853ffe3 0x11652833 0xce7b0839
+ 0xd1893c23 0xd06d2078 0xa65f020e 0x281e6a7d
+ 0xdf1da5a2 0xcdf69d20 0x74fa9b92 0xd98d6000
+ 0xb732496c 0xbd12f87e 0x561dc55a 0x651d42ff
+ 0x5736b74a 0x2c48a906 0xfdcbaf15 0xf76606e1
+ 0x80dd0254 0x8105e60b 0x143200b2 0x0f02f524
+ 0x1580d2c6 0x7281c6fc 0xc971cd31 0xd4a57180
+ 0x5051e5ec 0x193c72eb 0x930332c4 0x488d7403
+ 0xa93e425c 0x93e8ca97 0xa0a55070 0xafd8f8fc
+ 0xc424f1bf 0x11050ed2 0x855d0923 0xa0fcef35
+ 0x61f9e84a 0xc2196706 0x7221d5f7 0x96d036a5
+ 0x137ca3fb 0xfd632623 0x30b10850 0xdda390eb
+ 0x270fc9af 0xe6a8d748 0xf55bc288 0x8cc912d1
+ 0xf2d9cd15 0x5ded2f07 0x2de9b076 0xf5088354
+ 0x885becf4 0x959ef88a 0x0d9ea589 0x2ceb0a27
+ 0x8925270e 0xca5ecd99 0x8ba9265c 0x209eb0b7
+ 0x2e8b51d8 0xc598e096 0x23c17aa7 0xf600bcae
+ 0x7b33f831 0x223e1501 0x361c9f12 0xe6aeea94
+ 0xa5c6948f 0xd1daf8cc 0x0b0e0b54 0xb0cea6c7
+ 0xa437fbc8 0xdb4139ab 0xcbbad47a 0x124e2117
+ 0xfb80c5dd 0xef085f4a 0xd24c5fa8 0x2548a1db
+ 0x5e6cdeb2 0x8e4f0290 0x78cd8245 0x1ebb5eb6
+ 0xd9bf1208 0xf20eaf0a 0x544df94d 0xebc9c742
+ 0xbc5b4bbe 0x33f6fcaf 0x32efb07a 0x55d91b59
+ 0x2c0ed1bf 0x39985cb7 0x4cab882f 0x530cdaca
+ 0xccc78cfd 0xdd834c48 0x7ce7898d 0xf7458891
+ 0x933c2ae8 0xa06c5762 0x2eb03e35 0x8e938b71
+ 0x3636f142 0x0026efb8 0x183d71c4 0x7e8ff92a
+ 0x63265ea6 0x0f1352b8 0x73f8a8fa 0x6594e921
+ 0x401f88db 0x64abd8e6 0x994140c7 0xb2258b0c
+ 0x9bd6e6a1 0x92bab589 0x5919a943 0x29ab4d8e
+ 0x33cbb8d4 0x57084d92 0x006c4d50 0x57c49e54
+ 0xec1ecfe6 0xeaa8109a 0x269d94a5 0x4a664f84
+ 0x2bda2944 0xdafb85c7 0x2a7b4b8c 0xd8f124d6
+ 0xbbac0e70 0xeac5a129 0x308d7e39 0x99a023a9
+ 0xf616fc22 0x76fcc40f 0x7f745409 0x83872303
+ 0x0b067846 0xdf90a414 0xb6d9b6e1 0x8d0f93d8
+ 0x6f76a627 0x02f89060 0x392cb9e0 0x6acf19a9
+ 0x7cffe4d1 0x9928b4a0 0x87a031bf 0xecff42d5
+ 0xa376e023 0x69d2e1e3 0x1fb67afd 0x5396049a
+ 0x45538549 0xec0e6f60 0xf1ab27e5 0xc679e764
+ 0xee430c38 0xa6b0c2dc 0x92824db1 0x65d5ffe7
+ 0x448b17d7 0x9c67c8e0 0x14b36e2a 0x283de0a8
+ 0xc59bb35d 0x8faf1ca7 0x4265db7f 0xb0e74749
+ 0x0924d389 0xc22bf3fa 0x017c143d 0x93b4e0d4
+ 0xf8aa8e07 0x07e0293d 0x5b40bba8 0x619c8946
+ 0xc817ee7a 0x82fd526b 0x3e5b0f9a 0x5b352d98
+ 0xc786d63a 0xcbec5c0d 0xd05e9640 0x7cab758e
+ 0xaa9bd61d 0x205ff53f 0x2f093865 0x55ef390d
+ 0x4b008d12 0x0344c52d 0x64820f87 0x8e9c5202
+ 0xdd3f2276 0xf3b46630 0x80e85ea0 0x9aea428f
+ 0xa205b11f 0xa8506b8f 0x2c89f419 0xb0b9694b
+ 0x21029e6a 0x5e05869b 0x3baf3c6f 0xde680ae1
+ 0xd65b5eb0 0x99a6937c 0x52a78fe0 0x6f577b06
+ 0x8dea8d63 0x2417d49c 0x1a0ecb5d 0x91f22002
+ 0xc540298f 0xea9f8f6d 0x01ccfdb5 0x287138c1
+ 0xef206774 0x9d5deed8 0xba844833 0xf612317d
+ 0xe0bd4bb4 0x595d0440 0x73643204 0x2c21370c
+ 0xf9d5df6e 0x05614527 0x73c4edee 0x33f45ded
+ 0xbc47170a 0x24b94b30 0xff304e54 0x4e0c3b53
+ 0x658af390 0x402418bf 0x9db7318c 0x058721ed
+ 0x896bdd56 0xa956c5cd 0x3f928400 0x94c93146
+ 0x56600758 0xf46f4f66 0xa5bf66d5 0x0e8b5870
+ 0x8ba7e755 0x4177fee6 0x32cc8824 0x90b677d8
+ 0x307e9dd3 0x853a7e3b 0xa2f064a4 0xa42dbd46
+ 0x243ed6a9 0x7164eb1f 0x9e97212a 0x9757d142
+ 0xde296a05 0x8699a74a 0xeb02fa7d 0xf80b41fa
+ 0xd9dd2198 0xd7ffbd00 0x21b15853 0x11b78093
+ 0xbb329142 0x5260fb1f 0x22fb24fe 0x7a5e7e71
+ 0x71434197 0xc5ddca32 0x930c8cb9 0x65192958
+ 0xad1a41f1 0xc77442ca 0x72b64ff7 0xa90bcde5
+ 0x184a19de 0x71df036e 0x1b69b0ed 0x023c391f
+ 0xd9847da5 0xca57d383 0x0d21255d 0x2ea68d9b
+ 0x0189eeb5 0x1ea62386 0x4c8d42f0 0xac20dd55
+ 0xacceef1d 0x972f56e3 0x0bc40455 0x3853c5a7
+ 0xcab0d1f5 0x0d2a990b 0x525be1ba 0x5cc6daf5
+ 0x4d564f06 0x834d8f94 0xc0c055e1 0xef34557b
+ 0x354537de 0x7207e6b8 0x659c9298 0xa88ac04e
+ 0x80d8014a 0x7f4f6e7b 0x1136e621 0xb1b62f79
+ 0x8d4613ec 0x673699ee 0xdd6d7741 0xdba1ffa9
+ 0xe219e1b3 0x8bf64c21 0x14aadc3b 0xc4dc4e19
+ 0x47ae1e52 0xc5409e4b 0xce8d29d8 0xe0b1cf25
+ 0xcaf06411 0xd5450dcc 0xf14f29ee 0xf3611dd5
+ 0x52bc02f3 0x886b68aa 0x3b2853ef 0x110aafb0
+ 0x6b6d765a 0x87fbaa12 0xc79f134e 0x88b910fb
+ 0xe04aa148 0x33feeccf 0x3be43d3b 0x067854eb
+ 0xf22561e5 0x56c3abc3 0xcf0ff408 0x6291d940
+ 0xe26819d9 0xcfd04da7 0x94ab2808 0x156dcd0a
+ 0xb6d1c47b 0xdca4aa76 0x877f870d 0x4e06ec17
+ 0xbb560b01 0xbe1b62e7 0xd98b51b2 0x7083e3d5
+ 0x427ab621 0xe5fce36f 0x606dc14a 0xe4b70b49
+ 0x982d2446 0xf2d2e82a 0x60836061 0x681317fe
+ 0x1667e3c8 0xf6eef490 0x1ad768d2 0xbc86ae5c
+ 0xfbb392de 0x868caaaf 0x8429b5ff 0x266b6d5b
+ 0x372e8f2e 0x6e875cce 0x3a972f08 0xabddef20
+ 0xc777c559 0xd8f924a4 0xad39137e 0x4c16a4f0
+ 0x91d51877 0xae645599 0x4d09feb1 0x0cdededf
+ 0x5749b5b8 0x513c9745 0xf4da62f7 0x6583b20d
+ 0xb599bb89 0xaf6bea53 0x7275f6b3 0xdefc5092
+ 0x01a3734f 0xd95f4c5f 0x37bce97c 0x63610b99
+ 0x30555fe4 0x20af2f26 0xf84b2652 0x67ef6d87
+ 0x2119805a 0xcc79747f 0xaa479405 0x63a02857
+ 0x1953fc39 0x4f952879 0x886bfe97 0xf0067752
+ 0xa08b5005 0xcd9a5ebb 0xb04486e6 0x560c79ae
+ 0xe8faf52c 0x64a9a961 0xae9a5f1b 0x74cb5ef7
+ 0xf8d0269d 0x2fb63c57 0xd78a9a90 0x99cc0a42
+ 0x46bb0252 0xe56b026b 0xfb5ff703 0xdc8e0588
+ 0xe5d9e280 0xa73ec2b3 0xe21bccb0 0xe22ee743
+ 0xd1bb3217 0x5d4b3f92 0x0a627d8b 0xf2fd974a
+ 0xad0a57c4 0x261ba12e 0x1670f842 0x996ab25d
+ 0xf6f8043d 0xa6cbb362 0xcac3044e 0x6fe01268
+ 0xa54ab676 0x54d7444a 0xf3be5437 0x6b2b737c
+ 0xbe10300c 0xea505599 0xd60a15f6 0xd971ecc0
+ 0x9c480c46 0x2233038d 0x66d38df9 0xcb566912
+ 0x63cffade 0x75811ca6 0x8dbfa4cc 0xee5fc07b
+ 0x23329e49 0x39ee07e5 0x5de33ff1 0x601f8348
+ 0xb60a8bc3 0x832d3660 0xd1bee11b 0x1a38d12c
+ 0xaf00744f 0x21c2639b 0x0fd34252 0xcd63a9f1
+ 0x60f34993 0xf8728afe 0x75f8bb5c 0x74a250ca
+ 0xb9f51490 0x6ac643a6 0x4011a0e5 0x77288317
+ 0x57f772b9 0x92c0715c 0xd5d0e030 0xde335025
+ 0x669f6b14 0x55c74853 0xf3ac7cd5 0x38284e8c
+ 0xb0fda481 0xf9b7f045 0x839293cc 0xdf91a0a0
+ 0x18d20454 0xf73214fc 0x09577b9d 0xb5febd00
+ 0xd9b96c88 0xb454ea2c 0x6204a932 0x736edf8a
+ 0x9724f56e 0x3092f58d 0xac17cced 0x5ae87e39
+ 0x28dd2a0d 0x3806d96f 0x5e7c8c68 0x72df4471
+ 0x0207de38 0xf026ecac 0x13258e9a 0x34a8e8ce
+ 0xdd7d7286 0x8d7553af 0x11ebac36 0xfb9965ff
+ 0x9beda82d 0x1cd898cf 0x1b791830 0xe96ca8f0
+ 0xa0d274d6 0xdd6fea3a 0x7537177f 0xdd93627c
+ 0x60b64e47 0x10f30724 0x12489cf7 0x4587e1ac
+ 0xe7835522 0x61d48d9d 0x6afd081d 0xafbbcf2c
+ 0xe31d79cd 0x49ae4218 0x7c2c4a33 0x4fdf949d
+ 0x52ccd576 0xef2c3d62 0xfd5b75db 0xe6a5c2e9
+ 0x04fc9c6e 0x47fde414 0x8a87ebfa 0x850904e4
+ 0x2f49b552 0xb5f186fd 0x772a4ba3 0x48d0be3c
+ 0x846c7d78 0xc1c2a1d7 0xb9375f9d 0x302ed828
+ 0xf79208f1 0x8fdc4f71 0xc749ed51 0x1cd0c28c
+ 0xee5a5f7e 0x7f02b7ca 0xdc3b531f 0x99c0119d
+ 0x428e5474 0x10515459 0x8d804d27 0xb7c00220
+ 0x264c2695 0x7aa6e5af 0xef807715 0xa444f446
+ 0xe51c7755 0xcd825b6c 0x39afa440 0x88638e46
+ 0x4ea4366d 0xddfc9854 0x99696f2d 0x210592ea
+ 0xf4763dcf 0x7358acdb 0xedfc8523 0xe46031c8
+ 0xc9762414 0xa71a348b 0x084b6c82 0x9162e0d7
+ 0xda6a5b8a 0x68ca14d5 0x6385741f 0xb103d4c2
+ 0x44299ef8 0x9aba89fa 0x2c87dcfd 0x476865df
+ 0x1189dbb2 0xdcd9d19c 0xac2bbd51 0xa71526f5
+ 0x745222d7 0x4813ca98 0xcfa5802c 0x5d2b3907
+ 0x8a17d1b8 0xea56f907 0x3ea58d71 0x933fa242
+ 0x021f46a7 0xab8d4e86 0xfa4eb33e 0xaecbd5c3
+ 0xb3258e74 0xaac9f193 0x415a5518 0x28b13031
+ 0xbae39e53 0x1072fd5a 0x4e0fbf55 0xb02c5d77
+ 0x5949c780 0xbecf72df 0x15e52c72 0x3ffeb165
+ 0xa8e73d50 0xa52fd918 0x2b3c4d7c 0xa1e9e021
+ 0xd8e91949 0x63bf63ed 0x8f2e150a 0x9cbceca9
+ 0x33b10a97 0x4d2c69f7 0xf26371bf 0x0b5214ec
+ 0x10eb7fca 0x1958b429 0x25f190be 0xafcfb396
+ 0x7aec0c45 0xf9a0f163 0x9c966818 0x28f83619
+ 0xe35c61d4 0x1ad8a656 0x576dba63 0x7aa44804
+ 0xf941b7b8 0xc5faf3cc 0xdf1fd628 0xc009417b
+ 0x366ea78d 0xd3cb7030 0xf3f12e97 0x5298cc89
+ 0xbb43c8ef 0xd0a8ef96 0x564bced6 0xbcbd865c
+ 0x5c80b1d7 0x131ccb04 0x7502d06e 0x465f5cb0
+ 0x93320c4c 0x9df42986 0xbdb1fe26 0x48ae8bdd
+ 0xaf44e912 0x6aa468a5 0x67ecbb05 0x30b7c0a5
+ 0x3ad75711 0xa2d5f63c 0x30150058 0x4d748121
+ 0x70804875 0xf46b6ea6 0xa3fcbb7b 0x1af6b4c4
+ 0x48496de1 0xdb1a2321 0x758eb79a 0xf35f697f
+ 0xb4ff9dfa 0x38ab5b31 0xc918f6f1 0xb3a259fb
+ 0x3610afe7 0xdfcaaa0b 0x00c747dc 0x96c40b4a
+ 0x5c815168 0x29198fee 0xc94eeea9 0x70432b55
+ 0x5de7bbd4 0x0995652d 0x4b3e846c 0x7e4c9ca1
+ 0x7c0e91e6 0x401a820e 0x3ca3429a 0xd3812f44
+ 0x9cb6a5eb 0xf03ce395 0xefca548b 0x8943bc10
+ 0x472b2108 0x82d4a386 0x1d0ef931 0x94cd70ef
+ 0x2d00d619 0x40d36f80 0x238ccc47 0xe0856568
+ 0x9f06ad8b 0x95a4052f 0x287a57fb 0x9e9f9891
+ 0x62bc3a31 0x24c3c1f8 0xbabdc3c4 0xfa40629d
+ 0xd16f1f33 0xa9f7600d 0xbcbdb2d9 0x214f24be
+ 0x623ea3b0 0x8d650418 0xe86635b7 0xb834745f
+ 0x20771340 0x3c69a0b2 0x8b7c84cc 0x740e475c
+ 0xe5a540eb 0x9e216852 0x1383201e 0xfbf1f572
+ 0x9680d736 0x3d7f8d69 0x615ea313 0x87bc1297
+ 0xe552725c 0x9bfee104 0xf2e87d90 0xde9188b4
+ 0x028d268b 0x51c75c60 0xed93377f 0xc380d9d9
+ 0xe858bf8c 0x5d0b4a40 0x05a3171f 0x76ae3ec0
+ 0xf86e3fe6 0xc3d78254 0x7cd640c5 0x6835dacb
+ 0x983bd9a8 0x05d1e564 0xc5d5e9b3 0xf81c6560
+ 0x8ecba474 0x071daa33 0xf5010276 0x5432ba59
+ 0x10f2dbc1 0xbe892680 0x7e92d3d7 0x8d2f0113
+ 0x37fa8034 0xb13058f4 0x44684553 0x2bd0e36a
+ 0x67ea83ef 0x815e7115 0x3cd123af 0xd9aec852
+ 0x67c61c95 0x861d068a 0x60c7797e 0xd9733b31
+ 0x9ed29f37 0x1ccc8e08 0x34bcfa7f 0x1c66914d
+ 0xc64dc834 0xad884c08 0x2b22b8de 0x53d6fd78
+ 0x0355dcc8 0xfd363485 0x62370358 0x0dcb046d
+ 0x22fe7d2f 0x5fdd1117 0xccd6d8d1 0xe97925a4
+ 0x309aca3d 0x56c31fb9 0xe6f81e08 0x24fc0560
+ 0xa78d459b 0x4940b35b 0x9a4a2fdb 0x203eafb8
+ 0x91e5fcab 0xfb9be08e 0x9cb903ac 0x31598d89
+ 0x4f41986c 0x77206f4e 0x61811c9d 0xff51d95b
+ 0x2d7b4c66 0x84ceb768 0xfb135597 0x58087b13
+ 0xa1681cc2 0x14009e31 0x778c3fec 0xe3faf2fb
+ 0x5092b2c9 0x8919c362 0x34e2b174 0x7bb04f44
+ 0x63c39b5e 0x8ef696ff 0x2e4c612d 0x77d390e2
+ 0x5dc958a1 0x528bb31a 0x1cb07e7a 0xe37c9c53
+ 0x002856d7 0x6a10b962 0x423a7b39 0xc6da9227
+ 0x207800e9 0xe200c119 0x0e5af6f3 0xfb580459
+ 0x71dc40a0 0x70434cd9 0x13f7f455 0xdf3fd7ca
+ 0x37cbc698 0xf5a5808d 0xa7bfdf32 0x8a0774c7
+ 0x75b67d50 0x5a6908c9 0x23611a6d 0x8b50c483
+ 0xfe1e2eba 0x7ee1c732 0x2191e47f 0x9e63eb3a
+ 0x379cd875 0x4df7258d 0x166a8aa8 0x1c94586a
+ 0x2456c4d3 0x000185fa 0x7a196b46 0x914e789c
+ 0xf562c939 0xb3bad5db 0xc2c19b89 0x8a621ffd
+ 0x0c807ce0 0x701a938f 0x69234cdd 0x36a00f09
+ 0x964c43f7 0xcf71cd85 0x5f504e16 0x446c6388
+ 0x25742397 0xf1a375c8 0x6bcf822c 0x1b175fd7
+ 0x0fe78e56 0xfe7817d6 0x66da0366 0x904e8327
+ 0x5a0749fa 0xef3ede57 0xd0fa2ac8 0x89791771
+ 0xa5cd616f 0xe9ef2860 0x9b533bc3 0x1d746f03
+ 0xf4bb82b5 0xacae0438 0x840b3e34 0x30371a0d
+ 0x8590acf3 0xeb4ff7e4 0x40437052 0xba847bf6
+ 0x24059538 0x44daca63 0x23b32e28 0x091386e0
+ 0xc480e66a 0xe4a839f5 0x34929bcc 0xb9051207
+ 0xd21252f9 0xc6524769 0x8c422851 0x36280aad
+ 0xbf00b1a1 0x4e36c85d 0x7949e8ef 0xf76be57e
+ 0x373a0ab9 0x1b7555a0 0x0c2caf56 0xc9241f75
+ 0xbe5b0ee8 0x5a486f75 0xfb2c050d 0x6aeda464
+ 0x3fa744ee 0xf6e055a1 0x0a7324ab 0xfab58776
+ 0x09baaf66 0x459ce186 0xc6eb1894 0x56a4ce4a
+ 0x58ce1069 0xf4debf5e 0x04a145b9 0x1a246583
+ 0x9b07fe23 0xd4d37068 0x7321e0bf 0x2dfe17f3
+ 0x426dd8a7 0xc561a2d5 0x7f515a47 0xe57d37fa
+ 0xa85f0aa5 0xffb78cd7 0xf30c4551 0x3572c02b
+ 0x6f4a4cbd 0x7322ecc7 0x170a7b9a 0xa1e80d28
+ 0x5a366af2 0x4f24a3a7 0xfefd29ca 0x0d7b02dc
+ 0x1adde2e1 0x5c426cc5 0xb1e53b76 0x5dba2c5c
+ 0x1458b6ca 0x73cea912 0x39626c25 0x7547e76d
+ 0xfcddbb97 0xf03d59ee 0x3cfdab3d 0x309db86e
+ 0x3de8df47 0x4a570e6d 0x09c9579a 0x19ac033e
+ 0x0a7a9a86 0x3662d261 0x048fa67f 0x4aa4009e
+ 0xc7660654 0x524d81f1 0x3157ec52 0x857d1f10
+ 0x3770162e 0x3d1ff919 0x732d2b13 0x84187da0
+ 0x95722d45 0x362cada5 0x5d67637f 0xdaae8465
+ 0x9f5c0699 0xab9aba98 0x6f97d3fa 0xf9cc4120
+ 0x0ca1872c 0x1a832c9e 0x7b74d6ae 0x98dca967
+ 0x03eb7699 0x5fd02b54 0x962c6224 0xde1ab807
+ 0x800af435 0x2458a4ca 0x717de910 0x31648afc
+ 0x871527de 0x3cb93892 0x45237e37 0x446b1315
+ 0xecd807e8 0x70f38e30 0x140dc60e 0xaef7b7c1
+ 0xadec312e 0x94d45820 0xb8960073 0xe8dd5bac
+ 0x7616ab11 0x0c3cc190 0x516003e3 0x323cdb39
+ 0xd679f9f4 0xd7c179d2 0xdfbc5e24 0xaa1226df
+ 0x3cd41b0e 0x88f436f0 0xbd5b6cb1 0xb78c69aa
+ 0x982e0ca0 0x91f852a3 0xb331636a 0x28df67ee
+ 0x81b029a1 0x9e7375e3 0x56e874c0 0x8b93a735
+ 0xa47eaa4e 0x772ad825 0xfb83ba8b 0xc08db79a
+ 0xcb7a34be 0x14214d72 0x7d6fa82e 0xe75c7002
+ 0xa6290902 0x716d04c1 0xc75f0a97 0xb68e0912
+ 0x08b5ef1b 0x507ecac3 0x2d740b08 0x43b6c7bf
+ 0x3965675a 0xf56dc4fd 0x1ba44239 0x36753f70
+ 0x0b2452fc 0xe36bafe9 0xfc3134c3 0x2ac78286
+ 0x69ba53b8 0x225b9bd9 0xaf426f79 0x99bd2d3e
+ 0x0bcb8e18 0x28c87047 0x2045b3b9 0x730ec870
+ 0xe6558839 0x9ca3de82 0x263a41e7 0x1c8ea255
+ 0x334eb3ad 0xc36d6793 0x66add8ee 0x652c8548
+ 0x79dca1a8 0xc2526972 0xd10f03e2 0xdbae6f42
+ 0xe223bf69 0x10082495 0x74ba4cf9 0xeb71ef5f
+ 0xafae5d4e 0x7b3663e9 0x9339468c 0x31edca72
+ 0x65a07876 0xf336fc1a 0xaa505397 0x011d5253
+ 0x99b88ade 0xa688f0fa 0xedac589d 0xab4d8f45
+ 0x0ff866a1 0x61280e9b 0x65c5a63f 0x8b372073
+ 0x7a4c88df 0xc74f7959 0x19597c51 0x97c8a27f
+ 0x33eb652a 0xffd40c86 0x57a2ca0c 0xaabc6cc8
+ 0x54fd2280 0xd5b59006 0x2e00f009 0x72bd86c4
+ 0x24936e04 0x877188de 0x91b60401 0xb949b337
+ 0xdab93e69 0xdffeab2e 0xb3aa7c79 0xb8612f31
+ 0xf0c53b58 0x8896833f 0xda35944a 0x1867027a
+ 0xef6bfce9 0x8213f320 0xac477eb2 0x92368362
+ 0x606cfdc4 0x27c98907 0x50673ac5 0xec48f5f4
+ 0x39e879f8 0x80d050c8 0x9febddbe 0x5d797725
+ 0x06d8b755 0x0319d93d 0x7eae3ce5 0x8963ed64
+ 0xc91772c9 0x4e031095 0x2fd03d3e 0xe774ea89
+ 0x7dbc97ab 0xe8d8f361 0x6e167fa1 0xd1520c5a
+ 0xb3278325 0x8acaf913 0x6ea81dd4 0x9e3b2a97
+ 0x0a5b8a09 0x84000db1 0x59a30fa9 0xf0b6868d
+ 0xfb62b0ed 0x8953057f 0xdbbca3c0 0xc103b876
+ 0x47420e14 0x1eb22bed 0x58c8f65e 0x3a689da6
+ 0x8ed1a99c 0x869ddc49 0x60015d09 0x2264c797
+ 0xdc10c6ac 0x7275327e 0x8d47d2ab 0x87a75624
+ 0x3dd8fcb6 0x40e67a31 0x98114b1f 0x7e3a5976
+ 0x1d9e62a6 0x988c0398 0x0c7c0d8d 0x0aad4954
+ 0x3c40a234 0x7b752b7b 0x79f94813 0xa0b86dec
+ 0xe3f646ac 0xa993f76a 0x6f9d1f99 0xe883dabf
+ 0xb8ab1b2d 0x6766ac8d 0x6b9a793a 0x02f55fa5
+ 0x351a96ad 0xd190f768 0x35667fe0 0x6a85c938
+ 0x72444e33 0x5140a848 0xd3062250 0xe4ce902a
+ 0x44e7d9d3 0x7c8d48fe 0x4d26a61d 0xbd013c4b
+ 0x540d32bb 0x9152cafd 0x09840a30 0xd7a8663a
+ 0xd5a3ca17 0xfd5dbe65 0x655b226f 0x7cb9debc
+ 0x59d300dd 0x13737132 0xdf0d004f 0xe98bbd9e
+ 0x5626fb54 0xb6d66fbd 0x273087a8 0x032969ea
+ 0xbd69c191 0x010cdfff 0xb2a9cea5 0xb8778e4c
+ 0x8f0dd084 0xc75b4ce6 0x9c027c6f 0x36c58105
+ 0xac424eb8 0xa15d2883 0x9e73b7b8 0x54e9aade
+ 0xb9500a5a 0x97505e35 0x4c59b36c 0xb3ad1302
+ 0x31e21ed1 0x78bcd74e 0x2d9fc122 0x49bae35e
+ 0x5c8f01c0 0x8d29829c 0x0c672566 0x37938db5
+ 0x4959e71f 0x0d2365bf 0xaab666b9 0x52b2cffc
+ 0x200ee1f5 0x5dbb262b 0x9aae28df 0x3223780a
+ 0xb65218cd 0x633b797d 0x93f42423 0x3268b3ae
+ 0x141e506e 0xb1ed94b2 0x497b7973 0x9f2db9f6
+ 0x5260bf9d 0xb30e4310 0x4a3539ec 0x275d2ae2
+ 0xff43e500 0x645e30e5 0xf1527598 0xb76ec4cf
+ 0x88fc44e9 0xde68932c 0xe61aff6b 0x19d042b6
+ 0x11981ff8 0xb0d595d9 0x52764f82 0x7e0ca214
+ 0x8cc51237 0x581f2a1a 0x482420b3 0xd47ff971
+ 0xcff78344 0xc019eca7 0x3146ab02 0x107a3ee4
+ 0x16dc120d 0x33a239ec 0x0ea84236 0xebc7a1f4
+ 0xd1f2fa2a 0x9464c008 0x2b76a4fd 0x9b4acb99
+ 0x00f6a92a 0xd68b8d15 0x25e1e58d 0xe1fe3cd1
+ 0x6fbce2cd 0xf78be2dd 0x09b9c08d 0x6b32d210
+ 0xd06e7c95 0xd62f47f4 0x92c717ca 0x44fe3d2d
+ 0xaa13cc08 0x3d411f94 0xc2eba262 0x7521c9e4
+ 0x77d6cdc7 0x22d76158 0xca2efacf 0x3e51004c
+ 0xef9a82d6 0x1508d20c 0x923f18ff 0x3eaa88e6
+ 0xf2f32bc7 0xe74b8483 0x82529884 0x58b38ad8
+ 0xdd9f2a5f 0xdf54adc3 0xd4497667 0x789c000b
+ 0x935d1743 0xa52d5f1a 0x4e27adf6 0x5c3334af
+ 0x6cf71ba0 0x501f8353 0x031fd6cd 0x4831ec4f
+ 0x08c847db 0x6a6e0657 0x0bd803d4 0xd7c48cfe
+ 0x94b7e25f 0xc6516ebe 0x1001c08a 0x0e165da9
+ 0x4e39605f 0xe3f3637a 0x013daae9 0x217168b0
+ 0x6013ab5f 0xd5b7eb97 0x8ce6b6ef 0xc4259f29
+ 0x470e90a9 0x7a254ff5 0x8dcbf841 0xa2541a7f
+ 0x4880c5ea 0x28c750ea 0x043a0200 0xbeb9653c
+ 0x46e354d1 0x64f7104e 0x05a64bf3 0x7db42752
+ 0xbbd38c7b 0xca7da1d9 0x916c7ebf 0x1df5e3e1
+ 0xef0897f5 0xd0456a5c 0x629b50a3 0x8caefdc3
+ 0xddbf8b94 0xf6e6b341 0xd8ce3e02 0x27c96419
+ 0xb2659ab5 0xe8d576df 0x9f136353 0x6f5230f5
+ 0x68417adc 0x39b65378 0x4b742f21 0x96d071b1
+ 0xeb046da9 0x245ecb46 0xc17eeec3 0xd7c56615
+ 0x07df9b8c 0x647ee4f4 0xf15f7e7b 0x825b87eb
+ 0xdc67dd20 0x43c38867 0x977868ca 0x3a299ef2
+ 0xa75073f7 0x2dcd59e6 0xc6c78c75 0x63a00767
+ 0x74dfba2d 0x7880c7da 0x83f72bc6 0xa9750166
+ 0x716b3abe 0xc949a1ea 0x7e5fc036 0x574ee475
+ 0x39c3cae9 0x8c1dacdb 0x640fcc41 0xc69437e8
+ 0x5d33a950 0xa28e483a 0x4031cf9b 0x0007e3be
+ 0x6e3f277f 0xe25d3025 0xdcbc4a0a 0x7451a537
+ 0xb372169f 0x21ff0e91 0x1978aa74 0x6471624e
+ 0x01a03f20 0xeb391a3c 0x70d18ad5 0x47c9ddcf
+ 0xd9415b2f 0xd9ea29ce 0xffa0677e 0xeff7a04d
+ 0x1d384ff4 0x66195704 0x22736810 0xad754f27
+ 0x782ae9bb 0xffed05b6 0x5ae3f21d 0x5eb2c577
+ 0x0101cf91 0xed0322ad 0x56ac50c8 0xc513b1c6
+ 0x4f62ba8b 0xbaffd6b6 0x6649baa2 0x8702464e
+ 0x78947007 0xd6e97d6e 0xde7c6abf 0x2bdee498
+ 0xcee1db1a 0xb98149de 0x47f32f5c 0xc6c354fc
+ 0x6e148fad 0xb343cf2f 0xeac6a9f0 0x33dd1560
+ 0x923403bb 0x87d6e292 0x0b1cf653 0xe8b76402
+ 0x5f21a955 0x236dec28 0x214663fd 0x1917539e
+ 0x3f11ce80 0x1bb35a2c 0x38a358f1 0x15f67224
+ 0xc65394f9 0x63cd4887 0xe8e73d2b 0x51b6204a
+ 0x8eeae8f5 0x6e071c8f 0x55c23dca 0x4862eaee
+ 0x0afa0037 0xc98446f3 0x09181a1c 0x41e46e02
+ 0xcf13d6b9 0x85907776 0x30116b18 0x27b8c7b1
+ 0xd153a5ce 0xc95c90b2 0x34392718 0x8103dbe4
+ 0xe012a7be 0x6aeb8c6a 0x5bbaddbe 0x221eab21
+ 0xaf769239 0x2621a689 0xe8c41061 0x5890f76b
+ 0x2c4dadd4 0x2ad2e669 0x394209b5 0xb272b2ef
+ 0x560031cb 0x4ab7be9c 0xcc5e92e4 0xc0de0667
+ 0x7a39cf63 0x03482c6e 0xd653de11 0xe14466e1
+ 0xf2dbaf25 0xc34d1c0c 0x03eeb3e3 0x8260874f
+ 0xf6e2ef37 0x13626fba 0x15b7efe4 0x069cd153
+ 0xbf631788 0x797668a9 0x724d831a 0x0ceeb589
+ 0x9559cd31 0xb995d2d2 0x7564c4ef 0xfc45a3dc
+ 0x1cd999e3 0xbe090229 0xab4f9383 0x879156a0
+ 0x06e1d37b 0x3796487a 0xaf1e3884 0x1f9a59ef
+ 0x6c2d8a7b 0x0a8a5ffc 0x4cd60f03 0xa60bfc63
+ 0xf67c6872 0xf19b75cf 0x041cc864 0xc563566f
+ 0x58ae88a0 0x3747b0c1 0x64cd86fa 0xed185c5a
+ 0xb71533c9 0xf15672fa 0x2722d209 0xb71ec7d7
+ 0x3143a8a5 0x61c18934 0x3a899ec5 0x4274f336
+ 0xea7c52a9 0x9193cd11 0x44c471e7 0x57fff360
+ 0x53923783 0x76d57ce6 0xbff32513 0x4dbe0d39
+ 0xb9f80483 0x62ce4d25 0x5941e9fb 0x7dfedfe1
+ 0xa33f9130 0x336e6539 0x1de31e79 0xb6855a41
+ 0x4db2db67 0x02a9f1ed 0x019bcf20 0x53ad0ce3
+ 0x4d049f95 0xa9de2c6f 0xa26f6997 0x28eafacb
+ 0xa5220548 0xb4675e1b 0xe776ee88 0xc93e6c37
+ 0x7868630d 0x1690625e 0x6eba0fd4 0x78f598ff
+ 0x113fa1b7 0xcb025590 0x2ee34123 0x92241df5
+ 0x6edbf0b2 0x3bc2e0a7 0x710ce59f 0x656f0eb7
+ 0xa598424e 0xeca53268 0xb6a44542 0x5bf6674f
+ 0xad483960 0x35290b93 0xfba74c81 0x78141ea2
+ 0xd6baf9e7 0x8e5a08e6 0x4910c5b0 0x7b140d21
+ 0x1958c79e 0x0dbed125 0xcfbe41dc 0x089fc4ab
+ 0xbf014fa7 0xff961610 0x7a2ae6c3 0x560d3a9c
+ 0x2cd77620 0x3a7c15cb 0x9464d8f1 0x249a93ff
+ 0x96fe6c56 0x7231a31c 0x4bcdadd7 0x62edd9f4
+ 0x8ad1916c 0x3a5fbc8d 0x2a2ccd7a 0x558980b1
+ 0xb0137cfa 0x3cae6929 0x587c349c 0xbcfee701
+ 0xbddd49df 0xa0da6dbe 0x4cb03dac 0x5f84ba2d
+ 0x7fb3063c 0x66de2150 0xbf7dbcf2 0x1c0892aa
+ 0x4be8b0ae 0x5d9845ab 0xa21455af 0xc42f2e68
+ 0x9b6f438f 0x5eaf4941 0xabbf9079 0x94984a47
+ 0x542bdea4 0x34cf3d67 0x854010a4 0xf39a9b19
+ 0xd25ffb6a 0x04364e75 0x0af97ef8 0xe10e3620
+ 0x2184d002 0x0c0ca683 0xc19963c6 0x4c428d15
+ 0x47ae4151 0xd11ea57c 0x437a9ed6 0x50a6b8a2
+ 0x141b16e9 0xeb4ae873 0xb51180fa 0xe3dc318d
+ 0x7744a06f 0x64d297d2 0x845fac66 0x5854d172
+ 0xc14dbe9d 0xccba053f 0x4620a715 0x405d728f
+ 0x28b86cec 0xcba09cdc 0x92823f94 0xeae2664c
+ 0x48eda6ae 0x4b60f5f6 0x1772f309 0x8af285bf
+ 0x9c3ae474 0x13149ebf 0x2bc835c2 0xafcaa560
+ 0xc11b6f91 0x94861d9a 0x089c0d82 0x1e04d66d
+ 0xf0e497fb 0x6b2d8b6a 0x9d7f0cae 0x4a93ba71
+ 0x1c006123 0xed4b5f75 0x76e7826d 0x4f884ba9
+ 0xbba28011 0x1e275278 0xfa72461d 0x7e70e215
+ 0x1427ba3c 0x467e4f3c 0x781c5f92 0x357b7951
+ 0x9de2cce4 0x524a0de6 0x12e15f95 0x7b64fae0
+ 0xf27e93cf 0xc6f48158 0x9b71dbd6 0x081dc1b3
+ 0x47c9c2c8 0xf110add7 0x7881b556 0x0404bf1c
+ 0x58e7d936 0x04442173 0xe1e7f0cc 0x128ce897
+ 0x169c0a11 0xf30b5575 0xf2ac0bab 0x91515620
+ 0xe8b809b0 0x2a73d5a0 0x9ed32dae 0xcf943a47
+ 0xfc157bf9 0x1a53054d 0xf0657e2f 0xf39f6ea7
+ 0x92a5834a 0xcdca0c13 0x40a7b40e 0xba0e0cdd
+ 0x72f595c3 0x6b7eeaf3 0x4d0fd8ed 0x9a856082
+ 0xd75402c8 0xe0f8d3b9 0xee57a2a5 0xe1ccf4a7
+ 0xa4fc4fa6 0x9f2407c7 0x75f94c0e 0xbf2361de
+ 0x2d3b4782 0x72c35e50 0xb97f7d4e 0xbc880223
+ 0xb0b24073 0x08931201 0x40e0d18b 0x559db40c
+ 0x6216a921 0x031a379c 0x29bff1ac 0x1c522c12
+ 0x583bfe94 0x2519ba2a 0xd691d08e 0x905dc62f
+ 0x43b421b0 0xd45caaa0 0x5f099da2 0x012fc4a5
+ 0x509712b3 0x67e5d441 0xc843de50 0x7e1c756f
+ 0x91368900 0xc6ec0dd4 0xa41e838f 0x58eabda5
+ 0xd6ad78a9 0xa037b655 0x8af4e767 0xa9b95900
+ 0xdcf1780e 0x64e28d82 0x215ad981 0x292dfcc3
+ 0x708d8557 0x0a507562 0x486022ad 0x8165bc7e
+ 0xabffce1d 0x78fbe480 0x77b916f6 0x88f8167d
+ 0xae8b8edb 0x62698ab6 0xdbc6bbbd 0x001819a6
+ 0x8c096fb3 0x40a121e9 0x7b96a718 0xf6d256ed
+ 0xe5c0a484 0xa09bd764 0x6552b5a2 0x1847ae3f
+ 0x0669a650 0xccabc209 0x85246d20 0x61158f3c
+ 0x379d8086 0x02135988 0x1eccc6db 0xf8f38c67
+ 0x8e1b0f3d 0x0f6e87e5 0x936bbb84 0xe04839eb
+ 0xe26b3e5c 0x3f35ffda 0x4920e752 0x014c876a
+ 0x25189061 0xbe2bc4ec 0xbb2ca0f2 0xe2c1c9b0
+ 0x747df643 0x26da8dbd 0xdacc3c8a 0x7d93b22a
+ 0x922d9a0a 0xf82d65b6 0xd56e5f35 0x7aea7534
+ 0xf1808648 0xdfa7ec9a 0xff00f8c6 0x69091da7
+ 0xbb478c83 0x64e24ae6 0xf2371faf 0xcff5732a
+ 0x4da88e73 0x9c8494df 0x4c0da767 0x3e22bd67
+ 0x059298eb 0x9d7611ce 0x74b4a198 0xbcbe440c
+ 0xe2bb1a9f 0x0ba3e5f7 0x65a5cf9c 0x8b24b6f4
+ 0x7784ca5c 0x24ffc234 0xece71bbd 0x36f8e876
+ 0x1b55d68b 0x2b9163a5 0xaf8be424 0x958eeaef
+ 0x5d711c41 0x66d11cbe 0xfce42868 0x4a3c819c
+ 0xf66d295c 0x629402f7 0x64b2ee3d 0xc0b74538
+ 0xe93a735d 0x3b9e807f 0xd1d0d7c8 0x69588f34
+ 0xae92b6fe 0xf5508d03 0x45b6ccd6 0xf85a18c6
+ 0xe1a28a53 0x438f9a35 0xf4fe84dd 0xe3f95791
+ 0x16860340 0xefe72aee 0xb13575c6 0x3d730481
+ 0x3cf2a43e 0xa6ed239e 0xd7529176 0x8ad63f3f
+ 0x5efe8f4d 0xe9cad7df 0x44fefef4 0xc7198f50
+ 0x85aabf5c 0x15c175c2 0x26f7a0cf 0xf06782f0
+ 0x4dfadfa7 0xbc57a087 0x21406f0b 0x692a8f18
+ 0xd17a358b 0x19d1b2a6 0x6c35022e 0x87d8c987
+ 0xe7f2d06c 0x91c4daa6 0x4a132822 0x1e864671
+ 0x5cbf0c4d 0x6a34f073 0x1c87a8e5 0xb38f1717
+ 0x1cac430b 0xf733ee6e 0xdf73201f 0x71026328
+ 0xee976531 0x661c9d28 0xdeefcd7f 0xdefb4607
+ 0xfca9ef3a 0x3e1b9b38 0xd204c892 0x6b059f5f
+ 0xd5b8665f 0x4eec24fd 0x09b21b40 0x364c708c
+ 0xebe0d543 0xc3d64eed 0x8facb895 0x8f415f31
+ 0x3dd25b0b 0x95f4072e 0x85e6f4c1 0x3345e2a5
+ 0xa56e8dcf 0x3ed8df67 0xa8194a81 0xafe613c7
+ 0x384b25b9 0xe7661836 0x5ad6476d 0xeb0ae982
+ 0x19afdf2f 0x4efb8658 0xff07e358 0x96c469d2
+ 0xf3030add 0xf5bf5b51 0xba03b24c 0xcb77143f
+ 0x134fba20 0xa126558a 0x193cd220 0x48f43727
+ 0x156f2b18 0x4e599917 0xc3ac4eac 0xcc460648
+ 0x67974a2a 0xe2917a7a 0x02998a74 0x470c60d1
+ 0xbacbc868 0xfef38d84 0x3e4597a9 0xa1723ab7
+ 0x8ffed7b2 0xe489b151 0x34b982fa 0xf67bf8ce
+ 0x043cbb33 0xe3927c98 0x3c8fb221 0xbff0644a
+ 0x886d333c 0x1f4cd6b7 0xe9b744f0 0x443ef364
+ 0x04847d65 0xf3c2ba04 0x60a8e656 0xab4dca06
+ 0x620dbf22 0x5b0221e5 0x877973ab 0x128b5a6a
+ 0x4696b5d7 0x8f034e85 0x18796215 0x8579ec7c
+ 0xf8917eae 0xa98bffce 0xfc67e9de 0xa897445e
+ 0x2f115777 0x990bfb90 0x1de53f71 0xfa2e5c1f
+ 0x24a5b882 0x0f871a5b 0xe7fc33a0 0x6927a106
+ 0xb210bc90 0x2ef851de 0x09629147 0x2553882d
+ 0x77393353 0xeacf977e 0x470198f7 0xb7564a05
+ 0x4d575fb4 0x1d980371 0x0feeebba 0x26ba3c12
+ 0x17b21567 0xfb664d1d 0xcee1a603 0xa8881580
+ 0x8a47e853 0x6511027f 0x734f6fd7 0x2977b345
+ 0x7465e47c 0x0e3c4c8c 0x3185ac04 0x2450ea5d
+ 0xa6e97dba 0xf52b2f4b 0x328ac24f 0x5a507ad2
+ 0xac05d4f7 0xca332e1e 0x44b6cdd5 0xe22b049b
+ 0x55b885d1 0x71144ba1 0xf57284d9 0x76cb0900
+ 0x8266cfae 0x82bb0271 0xfe547080 0x53e4dac9
+ 0x0546dcb9 0xa09a8de0 0xd55d15a9 0x7a3a96ad
+ 0xd23c33ed 0x7a8fa769 0xa0542b10 0xdaf92f2c
+ 0xd6433b0e 0xad7cf7b9 0x72c54814 0x38ff5c07
+ 0xddee72d7 0x6c29582d 0xa1574da8 0x418272ea
+ 0x0a9e21f3 0xa34bb5ea 0x1e78630b 0x9238d5d2
+ 0x7cfa682f 0x6e8e841b 0xa4b3d17d 0x70b6d075
+ 0x704db3f8 0x76aa7d19 0x1cd3e85b 0x2ae7fa63
+ 0x5ff0dad0 0xdd92c129 0xce7d884a 0xa7ba03ab
+ 0x3b366560 0xfeaf75c5 0xd08856c3 0x01ffbced
+ 0x089aa8a3 0x2e4b36f1 0x03955648 0x882468ba
+ 0x534abc87 0x28c08402 0xa7512f6a 0x1fab044e
+ 0x6595e159 0x92fdef27 0xa0b6093a 0x5fdb5f3e
+ 0xd0facb7d 0x512a8b83 0xd7f31adc 0x82166318
+ 0xf9ad7f02 0x9120b349 0xab744947 0x2787d6bf
+ 0x489e3546 0x02a7ce3b 0xd3812409 0x819a092d
+ 0x94a48db8 0x49d8dff3 0xdd4e9b5f 0x330d32d0
+ 0x203cad0d 0xace20075 0xfd019f42 0x1cc56871
+ 0xe53e452b 0x51e7c9e6 0x1d6732c7 0x03694ca7
+ 0x900ecdb4 0x3251d119 0x2c4a0669 0x3243bb5e
+ 0xb434326f 0xd6eb26b8 0x8ceb7328 0xff30d7e3
+ 0x861fa43d 0x15386557 0x3fa11d24 0x86590299
+ 0xc3cbd319 0x8d1031a5 0x80db9f63 0x9d957321
+ 0xdec927f4 0x1468a2a1 0xff1b8842 0x4c403eed
+ 0x62140459 0x912ddd25 0x36252404 0x49052d26
+ 0x22205558 0x53773ca0 0x3428d400 0x51002834
+ 0x6b5baa18 0x838bcf14 0x30d09ce0 0xf1c456bd
+ 0xb1fc90c1 0x525dbb0f 0x64a9105e 0xe0a5cc89
+ 0x293f2441 0x335b1c7d 0x55842eff 0x6c7f60dc
+ 0x903fd793 0x868589ef 0x50a596a6 0x337c6988
+ 0xb7a670a9 0xa46b1a8d 0xdf8c013c 0x3dcdfd02
+ 0x01075847 0x06c3a7e6 0xc8f22594 0xfcd94f04
+ 0x8b6ddbbb 0x5a138f6a 0xf43d2cca 0xcf4df232
+ 0x088cddf4 0x9adce26d 0xee803f2c 0xedf042d5
+ 0x7d738c39 0x8f02cc34 0x3f964043 0xbfae17d7
+ 0x5f2dd670 0x177a9f36 0xf0e1dc28 0x07082ed9
+ 0x90534419 0xf03db66a 0xb8ccbbbf 0x739d2ae4
+ 0x3509b32d 0xf0105125 0x2d603572 0xbd1a6b64
+ 0x50959fe9 0x26100668 0x758e250c 0x9b372d1b
+ 0x0f1e1bde 0xd53edd46 0x0187d6e6 0xd0158da6
+ 0x05dd0922 0x3fc0a182 0xd7f70ebd 0xeeda22e1
+ 0x1c7f99ad 0x9b39bee9 0xf101d67c 0x1ffea21d
+ 0x5494b799 0x787a77ca 0xe8908c34 0xdd00d1db
+ 0x25e21bcc 0x30bf0b70 0xd8cd0350 0x96f2d414
+ 0xa9a4cb6d 0xa3f3c207 0x2db5c7bf 0x88e8837b
+ 0xb157189a 0xb9fb869e 0x48c2a7b3 0xf5e0c692
+ 0xf9103c12 0x6c590e9a 0x7e0aac34 0x97392b87
+ 0x8e6c201b 0xc6d68ddb 0xb5fbaf0a 0x1f8e411f
+ 0x6355e9d9 0x05fcca55 0x9b0250dc 0xec9c5d7d
+ 0x668075bd 0xb93078f1 0xcefa1755 0x216c5e0c
+ 0xa83ae6b5 0x748bff79 0xfee9e797 0xc6acb230
+ 0x1243bc06 0xfee350e0 0x3ee5f8e0 0x0508fb60
+ 0x87d9d24d 0x0b54ac94 0xfc37c8fc 0xe9958f2f
+ 0x3a927f73 0x04933b6a 0xa195a6dd 0xda96dca3
+ 0x9c1799c4 0xd055fc63 0x05deebbd 0x2b5400fb
+ 0xf157f110 0x80b1e79a 0xd7f1e4b7 0x5a1fab0d
+ 0xbaaa81c3 0xa42489e8 0x594a791a 0x29f18382
+ 0xe86f0358 0x5aa5f4b0 0xa682993b 0xedbfc5b7
+ 0xf1eac55d 0x9b1716bc 0x907d9d1e 0xb2205254
+ 0x4fbba0f3 0xacea63a4 0xc518d83b 0x8449fef8
+ 0x80b4f69b 0x95dc7429 0x16c22c9b 0x6e116239
+ 0x4c4bfd11 0x56f159fa 0x60cbb0a5 0xa2f4721f
+ 0xa829cf9b 0x5ddbb3af 0x2db824cf 0xe82f3fd1
+ 0xe5dcb2db 0x185fe7af 0x0775003d 0x38669aba
+ 0x7b540eea 0x94ce3d10 0xba77f357 0x63507853
+ 0xb50ebb0c 0xb614739b 0xea3a3c47 0xf2b6176a
+ 0xf805b28d 0xdd0819b7 0x9f4b2799 0x18bdadb8
+ 0x7d58d588 0xc4f0994a 0xef834870 0xef2d6ce4
+ 0x97a36a52 0xb6e581e6 0xddd9aa9b 0x6437d4e8
+ 0x43f74dc5 0x8cbbd744 0xf394a2a0 0x4a1e7f75
+ 0x395bd36f 0x27a8f9e9 0xed62f4a5 0x7c2f0484
+ 0xf394f837 0x5f69d50e 0x86ef57af 0x7af052f0
+ 0x85dee180 0x125f56fa 0x87291494 0x141931ac
+ 0xabca9ae0 0xbc1e4e4d 0x541e2edf 0xa3551bb4
+ 0xed2766fd 0xf6e778c2 0x3a82644f 0x67c47659
+ 0xb81b826c 0xb11603ee 0xba6cc507 0x691fdb74
+ 0x06507f6e 0x64ef2a0f 0xebd9b51d 0xee620487
+ 0x82991d7c 0x1493fed5 0x08af819e 0x7066de45
+ 0xdeee1600 0xde12b903 0xe572ced5 0x81b897be
+ 0x458d0db8 0xc9970232 0x7402dd05 0x44e1c70c
+ 0x1619441f 0x9ea0c392 0x1d13c3dc 0x34737cbb
+ 0xe1d726e1 0xbe7d749d 0x304892a5 0x71c7bb33
+ 0x608bb696 0xd334cfd7 0x862e360e 0x868757ad
+ 0xb7d8aa70 0x81031f5e 0xdb64b80c 0x954ff4c1
+ 0x5c66d432 0x08c77a67 0xd5e298af 0xb6074be1
+ 0xd687a163 0xac2fd525 0x14e6ab5a 0x6ca4232d
+ 0x8a921092 0x0a19e936 0xd4464ee4 0x0da28777
+ 0x6b6d4131 0x975111bc 0x3f26afae 0x5a6faf38
+ 0x867d7956 0x554aa8be 0xf9898211 0x3afcde65
+ 0x493dac6c 0x61d901b2 0xbaf3e9fe 0x2a3758fa
+ 0xc2ad3ee4 0x97d13dad 0xe84b02f9 0xaaf5ca63
+ 0x41a94864 0x6d7b71be 0xd843e866 0x83c3193b
+ 0x972d4bbf 0x55c3a234 0x0d03b540 0x53396a64
+ 0x98b5c0f3 0x36708484 0x38363c7a 0x0076dbf8
+ 0x5edbd01a 0xf6e835d6 0xccb95e4f 0x2bd2907e
+ 0x210f9312 0xf4ec9221 0x343697d6 0x3913cd41
+ 0xb02ced20 0xba991ee5 0x09c7893c 0x749da3c0
+ 0x46e5ad3b 0x871b685d 0x02358659 0xca76706d
+ 0xe61524a2 0xf46ac4a9 0x4f6c9e19 0x68a86d0c
+ 0x9d16bc4f 0xa9157a1f 0x830993b8 0x3738896c
+ 0x7c821db5 0x02de8542 0xb17e3767 0x455a0b40
+ 0x19b707eb 0xed81e63d 0x568e1e36 0xbf5cee00
+ 0xaa12957f 0x67f65ecd 0xb940789c 0x0ab3bab8
+ 0xd7e3a789 0x777b64ba 0x4e00d3be 0x46887a34
+ 0x08f0127f 0xf5027e8f 0x9cdb4671 0xb7a7eac4
+ 0x9be5cfb5 0xb1f57dbd 0xbce97b11 0x41525f56
+ 0x5e847d16 0xf71585b3 0x1ce5047b 0x1bc2fa00
+ 0x860aa4ca 0xf97ee77d 0xe7843ee6 0xf07bd865
+ 0xfa059452 0x58a59ce9 0x24f03b1b 0xd18a52c2
+ 0x180426ab 0x2ced0003 0x399234cd 0xe43f91e9
+ 0xa0516a92 0x8088d598 0xc3a41365 0xd1f044ef
+ 0xfb3808f9 0x1770e594 0xf96c4185 0xc6b67b9f
+ 0x5c01c703 0x65c6ef8d 0xd49310f3 0x0f962bd1
+ 0xfb3c96f1 0x4d501516 0xa09beeb5 0xce9df639
+ 0xf792c71f 0x392b420d 0xc03c9099 0xcab5dc42
+ 0xbdfea308 0x84c80c32 0xcd66ec3f 0x68932191
+ 0x62b69b08 0xcacb4a8b 0x0415feff 0x84673edf
+ 0xe61b5ff3 0x6107a18e 0x6a7a206b 0xed64aa34
+ 0x1bbaef36 0x22a3f0fa 0xb0945c72 0xd1a7f7f8
+ 0x65fd1b29 0xa34d99a9 0xb6f2ea53 0x055ab055
+ 0x433c3eb2 0xe591d68b 0xcabb8a71 0xfb055c2e
+ 0x37e1efec 0x558fd45e 0xa5358766 0xe0c450f3
+ 0x78ed3061 0x8713e084 0x4b0d2ec4 0x24feb10e
+ 0x6689fc4e 0x0c83f1c9 0x7490df57 0x00d618bc
+ 0x2c510caa 0xc5e2838a 0xcfae6669 0xdc2fa4b0
+ 0xa4569e3e 0xcee095c4 0xcb5f42ee 0xdc11393f
+ 0x69f1c5aa 0xa495fae6 0x64c53ea4 0x4477aeb8
+ 0x2ff43cef 0x660aa186 0x5dec9e67 0xa59f6aab
+ 0x51504061 0x28279b5a 0x4e245278 0xdbf53c73
+ 0x01a77ff9 0x7d771730 0xa8d19fc6 0xce3697dd
+ 0xecc405d8 0x22f1872a 0x683afa3f 0x725f7e03
+ 0x14c7acb2 0x845efb20 0xf3e03095 0x8c9a7d04
+ 0xa9f115d3 0xb93fa8ef 0xd2e78a32 0x91e3cc61
+ 0x805d48de 0xc9fcc672 0x225d36f0 0xb32e7627
+ 0x11b7a585 0xa7321798 0x9b40640f 0x0c3a6b7f
+ 0x3337c762 0xbbe54bb3 0xc8316a84 0x0d487a67
+ 0xa6d6b86b 0xd1fb2b92 0x15805dfe 0x5cd49b21
+ 0x9855f2c2 0x74e2a195 0xbdc0729f 0x29f680a9
+ 0x092f47ad 0x0e7091d1 0x6e7d2020 0x0a7b5d47
+ 0xc9c4065b 0xc4cacd97 0xcd7b4071 0x7986cc7a
+ 0xb1c29ef5 0x47ced57d 0xc08a8b40 0x12102685
+ 0x685caae1 0x1ebf3635 0xdfe6af15 0x8a0496f4
+ 0xb9c07f19 0x1f62a68f 0x0133de0a 0x993017d9
+ 0xd0553b5c 0x0c8f1311 0x7d979028 0x6001db26
+ 0x1caf7ffd 0x76ced0cf 0xc33d3f23 0x9fc27423
+ 0x235fc137 0xf85a079b 0x78174474 0x1d15b725
+ 0x20162abf 0x62e0712d 0xa03f9cf0 0x0f4ff140
+ 0xaa389d0d 0xd58e1171 0x8f5d21f4 0x3ad5b3c4
+ 0x03003b51 0x49b29d4f 0xa3d82796 0x9c7f3391
+ 0xe34de3a8 0xab75e6f4 0x3f06b52d 0xb8092f83
+ 0x01f14341 0x929a3b8a 0xa630aa03 0x4b7e055e
+ 0x90b06e58 0xeaf2ad79 0xe8c5b756 0xf46f44e3
+ 0x6693ff09 0x499d2790 0xd0d81c69 0x72d7a2bd
+ 0x794d242b 0x9be19084 0xddd51a72 0xf4f60698
+ 0xd1747d6a 0x24dc87dd 0x78ba7af6 0x548b43d0
+ 0xa2b03ee8 0x100ef53b 0xe836488a 0xf4b9a443
+ 0x41d61bdc 0xee4bedb1 0x8f0ec0b0 0xc0125983
+ 0xaa919a7f 0x6677db37 0x78e7d366 0xc7bef834
+ 0x967a54e7 0x5f78951a 0xc0fddf1f 0xbd5cf29a
+ 0x3fa13be8 0xca67a695 0xc13e8c23 0xaff54342
+ 0x94f4bc22 0x85512c06 0x1439cd71 0x7d13b7b5
+ 0x76f8bd59 0xffe02871 0xbd88ccb1 0x2597d721
+ 0x80a52e2e 0x1f696120 0x689e73aa 0x7d085fa0
+ 0x0e183650 0xe041d3fb 0x5a340dd0 0x26a6c10c
+ 0xe6fef6d0 0xdb18b3b8 0x2fc6df63 0xfa695c57
+ 0xfb3e6a3a 0x64fb412f 0xc1cf1e32 0x6edd945f
+ 0xcee44d66 0xdfb2ec8c 0x5eb84515 0x177f031b
+ 0x56a9db8a 0x0e247577 0x99004862 0xa5805854
+ 0x04b1afc9 0x9c649998 0x908a1424 0xb595099b
+ 0xb91fb0ce 0x8c4bdd8a 0x78de806e 0x65ff3cba
+ 0xb66aeda0 0xe22d3592 0x7c0cdebf 0xc15c0853
+ 0x80f31d27 0x84dfc7ed 0xc96a5992 0x939b3d6c
+ 0xf0ffac53 0xe4be269e 0x4d56d528 0xb0477318
+ 0x40a4b528 0xd938f1bb 0x2b25a6c2 0xc93b3c9f
+ 0x179c9571 0x999c2e91 0xe7280616 0xee6e0481
+ 0xc30eae2a 0x7d6f0458 0x0b7a52ff 0xd44e0a23
+ 0x81d661ee 0x9d0f857b 0xe7fa9d18 0xd499cb85
+ 0x4e27e30a 0xd51d1f9a 0x14195d32 0xccca7d6e
+ 0xc1703a6e 0x15664170 0x7f51c821 0xf1363619
+ 0x37dc27f5 0x6aea6223 0xd574e44c 0x4b683223
+ 0x4135ad1a 0x7694390a 0x0bf4bddf 0x9522f11b
+ 0xc20797be 0x45fb151e 0x96f2a952 0xedfd5f2c
+ 0xdfbcac7f 0x58f5dba6 0x68204d0d 0x52eeb34a
+ 0x8313fd8b 0xda2f1243 0x195a1479 0x19bb2970
+ 0x1c2131e5 0x6841c28c 0x1ec33cfd 0xd3e489de
+ 0xd9b70b18 0x81503d32 0x9642a53e 0x02470015
+ 0xb8d1087f 0x4b629e77 0xd7ec9ee0 0x795ffd91
+ 0xcfa71aeb 0x4bae649a 0x7f768123 0x69f501d5
+ 0x56c19a0c 0x4bfaac57 0x90ea664a 0x4d428e1a
+ 0xaee71c90 0x198fc316 0x549f5572 0x07a22e58
+ 0xe8f444e3 0xedc7fc23 0xe96c1595 0xc4bdad06
+ 0x751a3df5 0x3bc4fba4 0x58cd19b3 0x3665000a
+ 0xe4371d96 0x6c50d4e6 0x5d1d6a57 0xf130eabf
+ 0x48fd82ad 0x42a8bee8 0x71f89c32 0x95fba6dc
+ 0x9150b601 0x72c361b0 0x71a3c317 0x149614f9
+ 0x224e67fa 0xf6a3fea9 0x5461cefa 0x367bc566
+ 0x2226ee83 0xaa13e83f 0x8d7dc705 0x417c7afd
+ 0x8a0f2e17 0xbb4003df 0xd1c27124 0xaaaede8d
+ 0xd4ed5bcd 0xd0102aa8 0x3b519bfa 0xb82d6932
+ 0x50b8f966 0xec685a1d 0xffb18b64 0x538955b2
+ 0xac4b6cf1 0x0a86d32f 0x34e4cc05 0x02adcf17
+ 0x7c80379f 0xcfb5bcb5 0x842190e7 0x8348cd1f
+ 0xabf77742 0x3332866f 0xa56fb2e6 0x6c1fec47
+ 0xf2fbb22c 0x7230d805 0xed17d8f5 0x3426e157
+ 0x1d045cb2 0x6c1e349f 0x3a6116ca 0x4baf0bdb
+ 0xab68daad 0xc4867466 0x7bb15fd9 0x707a6a1a
+ 0x83157678 0x277cffd1 0x8d48e5d2 0xf829bd6d
+ 0x1fd2750e 0xb6bb8854 0x66d0a20a 0x38f47b92
+ 0xa3568b90 0x0d091e16 0x65a8245b 0x238e4299
+ 0xd0bc6bbe 0x8ef67730 0xf976b632 0x326d9d24
+ 0x96833335 0x1d475e95 0x1f8f41b6 0x65c9dabe
+ 0x2133b931 0x43be592d 0xb887160c 0xf21fbfce
+ 0xd83ca306 0xa0fb3fe7 0x7da09bf9 0x3f464aa6
+ 0x37a7e40a 0xbb0c85bc 0xb172ff01 0xee62de6f
+ 0x59d2d646 0x4262e938 0xcd96f5e3 0x0c1862cc
+ 0x438388c7 0x9f45d4b2 0xc65ab0b0 0xd24a381c
+ 0x1d6c6767 0xedaa1ae2 0xa93eaec0 0x662d776b
+ 0x192a88c9 0x6c9d860d 0x61106181 0x30027db0
+ 0xa5ae7b76 0x73fc43da 0xd77472b0 0xf4ceba3d
+ 0x7cd642c6 0x903dd266 0xe33f58e9 0xbd088621
+ 0x8e4c2c12 0xd8c4288e 0x24fdbb22 0xf72ee1f9
+ 0xf291bd7e 0x94e68382 0xbbdd9240 0xb59602de
+ 0x1b59afd0 0xe5417cf5 0x20bbb538 0xe28fdee3
+ 0x0bb16920 0x77d6712a 0x1a0ae5f6 0x0156c43e
+ 0x976b53c4 0xef856d7b 0x5a974cfe 0xec53404b
+ 0xc627c557 0x3318542a 0x8fd883e6 0x508562b3
+ 0xe0ab7501 0x9ae57262 0x95611b5e 0x50c699fd
+ 0x984bb8ab 0x5983ed68 0x9947a7c5 0xc0d2374a
+ 0xe0845ab6 0x9ffec0fe 0x41873bf5 0xc85c1a4c
+ 0x7ef2b12d 0x9e1a3857 0x444da53d 0xb8947919
+ 0x84c8588c 0x268f34e3 0x1974cf3d 0xfa67e03f
+ 0xc4478570 0xc1896f5c 0xf86de14a 0x9d27ddb7
+ 0x5da1c695 0x73c74ab7 0x9123a47b 0x1c9d9563
+ 0x7b96bb9f 0x98d20464 0x1f46fd8d 0x4bc35857
+ 0xc221a75f 0x04b24c86 0xbe1c7271 0x21a7b19a
+ 0x9e050b54 0x8d93d0fb 0x98d7b55b 0xe5fe9502
+ 0x9471bff8 0xb3825934 0x5f22d5b2 0x47f4ae9c
+ 0x62d7623f 0xfdeef9b6 0x38c64ff3 0x9268fd7b
+ 0xa7cfd22e 0x80eeed4c 0xf80a4a3e 0xc9a7e4f4
+ 0x6f334b52 0x48e932a5 0xef8720eb 0xb9e86512
+ 0xc4183682 0x08142405 0x0a32902d 0x34503fb5
+ 0x4c7f132b 0x8db9be38 0x82c20236 0x80a79fa5
+ 0x9a31e682 0xca61dd2c 0x2e354b63 0x8d5a4750
+ 0x7a838960 0x24dffeb5 0xc7d19837 0xebfbc508
+ 0x82e8dbdb 0xe732eaf4 0x109470c1 0xb012af6e
+ 0xe2ce17be 0x79db33be 0x281184f3 0xc813df9d
+ 0x9e6a771f 0x4a81882c 0xda5baf2c 0xfecbbb6b
+ 0x4621a151 0xf4cece92 0xfc230416 0x8d4e758e
+ 0xf69c296c 0x9fa2490a 0xeaa56785 0x3075ed95
+ 0x4c2ffe06 0x817caf32 0x5a72f33a 0xc6d99da3
+ 0x2bbc3dde 0xade463f7 0xb74af1a3 0x738d809d
+ 0xd244aeaa 0x7302a2db 0xcb6e9b1d 0xe297c027
+ 0x15dbaff6 0xce99c273 0x2810eb0e 0xafbe1f09
+ 0xd316d8ba 0x27b8af19 0xb66bdf45 0x3e3b5fbe
+ 0x318a4f05 0x2ea7807b 0xed6d40a0 0x58ba8267
+ 0x1d1c9d15 0x29af51cd 0x04a46683 0x4b759694
+ 0x20ce21e6 0x19ef8036 0x141a8064 0xca36f583
+ 0x6d47da5f 0x3a8f6b9a 0x70a99a79 0x03677150
+ 0x0feb8c70 0xf3509842 0xf33b5dde 0xbef320a3
+ 0x932f9512 0x87497bf0 0xf521a0c8 0xa813483b
+ 0xcd6fae43 0xbb7e4dce 0xc7d039b3 0x2d1e6f8b
+ 0x1b19cb9e 0x8341c193 0xeffde49d 0x4c40621b
+ 0x19d60210 0x8846c540 0xea735ec0 0x0c995dbd
+ 0x9aefe2f3 0xbd46f954 0x9b315f98 0x2819307e
+ 0xebe2c1f5 0x05919533 0xa52921ee 0xa0bd6746
+ 0xd754f5d1 0x39eb2ce6 0x8442d51e 0xb1f75159
+ 0x1b617cd1 0x046fc90a 0x6452daca 0xe8d3e3e1
+ 0x77406387 0xe3ffbfca 0x89387e91 0x7e348a53
+ 0xa5bd3b60 0xc113e95f 0x2ad5a7c4 0x45c1f445
+ 0x2a683930 0x3428246c 0x4b89cf6b 0x05e66b1a
+ 0x571737eb 0x6e55a8e1 0xbc96ce28 0x24d501f3
+ 0x242c8191 0xde8c9472 0xbff946e4 0x551b5759
+ 0x411e3420 0x0f0b9299 0x44aaaf70 0xacf2f3df
+ 0xe9c44a27 0x781ffdce 0xa39651a5 0xdb7b44a5
+ 0xed0ec4d9 0xec17fca2 0xd3ccb15f 0x2b9bd010
+ 0x0446a9ef 0x18df586c 0xe227ae08 0xbbaff527
+ 0x7958fb15 0x03bfc823 0xc09b7b6b 0xce07b0b3
+ 0x0161a359 0x8e21f733 0x8f8168bf 0xc1e2207e
+ 0xf9f65e93 0x831b4ba8 0x4b3677f9 0xf8342d03
+ 0x03c10268 0xd07233c1 0x0df67d97 0x72434732
+ 0x059c7679 0x96526a88 0xb54f9440 0x19e7327f
+ 0x6f7f52c1 0xb4b8d069 0xcc4681eb 0x26ea581b
+ 0xc26fe16e 0x4073cc56 0x6d252a42 0x689fd0fd
+ 0x5d93f1b3 0x070ad283 0xa07cb95b 0x6effe0d1
+ 0xe303ed01 0xb8e9b3f4 0x0721647a 0x31f877c6
+ 0x134518e5 0x08694d5a 0xb0e6ef3b 0xc7fdc67e
+ 0x6111276e 0x45185e0a 0xe13cb5c7 0x7c6ec9e9
+ 0xfdee9721 0xc1fb8bcc 0xe25a2bc1 0x075f717e
+ 0xd37b7698 0xa9cbfeae 0x6b7d0a28 0x1f1c8bdf
+ 0x35d0e6b2 0x8b988b79 0x54f02ea3 0x3426ae01
+ 0x5e402b08 0x840d3b8e 0x221527ff 0x906a86f8
+ 0x411ce6dc 0xe4b3056e 0x26c9ed04 0xf3d8bc97
+ 0x3b02cf67 0x11309c45 0x06ea08bd 0x1c698922
+ 0x04e1e492 0x06e0c39d 0xed2937ab 0x83f1911b
+ 0x25a94599 0x75d365f0 0x98f191e9 0x845f5e0f
+ 0x49547aa4 0x42a0ae2e 0xb7e77fb7 0xe132bfb9
+ 0x1cc087a2 0xb0435a85 0x4818ee36 0x4cd90b16
+ 0xf56d5e22 0xdc49137b 0xb5f16e70 0x8f8ac784
+ 0x84b020c7 0x83c26ace 0x090b3489 0xde14f529
+ 0x6ee716ba 0x9deabba1 0x2c230ded 0xd6a68037
+ 0xe626043f 0x33431885 0xd26423e7 0xcf259f47
+ 0x335dfa6d 0xf052f836 0xcadf2fa5 0x6f2125d9
+ 0xafbb23bf 0x19ec69ba 0x84d10bad 0x8cd3ebd5
+ 0x36f0fbb1 0xbc1cbfbe 0x96c56812 0x0b05c939
+ 0xbd79989d 0xffe74b98 0x6f99405a 0x9f10b14c
+ 0x9d8efef4 0x299d21b5 0x9dd2df5a 0xc7ea511b
+ 0xbdde106f 0xe5dc7d17 0xee136bc7 0xc4521b6b
+ 0x823d31d0 0xcc3c32eb 0xb35ffb33 0x84dd8acd
+ 0xe8ddf3d6 0x4611888c 0xfe469f52 0xf8e18215
+ 0x768747f0 0x86379e46 0xd3cf9eb7 0x86f1e47d
+ 0x30e68652 0x740203fe 0x1031b14e 0x96ce6827
+ 0x45f57455 0xe41b7656 0xaa8496d3 0xb99701d0
+ 0x485f88ed 0x1d064ef7 0xc7e3348e 0x110d938f
+ 0x0c3c9604 0x786b0b35 0x2b2aa6ad 0xdcc45e0b
+ 0xe9b29146 0xdbb00ed2 0x0527d574 0xc8029ff1
+ 0x5699dfd0 0xd627ff70 0x285fb3d8 0xcf2e6b75
+ 0xefad87da 0x4fa21893 0xa391388c 0x5760b28e
+ 0x41a95b55 0x82001638 0x6f0e2d45 0xd30f70aa
+ 0x5eca612f 0x946317f4 0x24c44ef7 0x470d26f2
+ 0xf7e65ef4 0x3a831857 0x53c5699e 0x1af6ff3f
+ 0x675b46c3 0x1bd5cfbb 0x03ab61be 0xa67a2b7b
+ 0xbae16286 0xe1522d53 0x076d8ec2 0x3a603daa
+ 0x0dbacfd9 0xd32acae8 0xe8a23399 0xdf3330bf
+ 0xe990c05d 0xfe56bcc3 0x165f868a 0xdf42a220
+ 0x6587e194 0x0a31eb94 0xa72a98fb 0x5512801d
+ 0xc5fd9c69 0xf7210367 0xcc80f30c 0xc08755bc
+ 0x3afe8202 0xc47d603e 0xd17d2990 0xa4addd73
+ 0xce89fcc5 0x55726cbd 0xeeb77a64 0x628b3d1c
+ 0x2297e332 0x6ecab8e4 0x9739c0d1 0xd53d619c
+ 0xbf1a3371 0xe29ea297 0x140436d5 0xfa4802f8
+ 0x1b277664 0x4f101407 0xde441685 0x1d36bbf4
+ 0x057d9f25 0x7949dbc2 0x57686ffc 0x12984cb7
+ 0x0721d76b 0x81ac7aac 0xeb40577c 0x43aaa8d4
+ 0xb4e06e63 0x7054a526 0x18bced57 0xa37d26a0
+ 0xac039a34 0x156e6d9f 0x07ae4487 0x0e59f4db
+ 0x28aeb416 0xc1c4dafd 0xe0357fef 0x683adca7
+ 0x93f2d62b 0x8f1f6ec6 0xd42fcbd8 0xfc4e3fad
+ 0x082e4bbe 0x578bdbee 0x42dcda04 0x7684e947
+ 0x20853da1 0x207dd044 0x56e372bb 0x5ef4c033
+ 0x83353865 0xb3b42465 0xb80c9c79 0xffedbed0
+ 0x09e45d5b 0x794fe5c7 0x498d4fbd 0xb1cd7a48
+ 0xfc89b057 0xc1d19df8 0x9654d056 0xc94cd085
+ 0xd7cb03b5 0x13a52c5b 0x52471fd3 0x990aaebe
+ 0xe8bed6a7 0xa6960d01 0x68011da1 0x021bf151
+ 0xaaa196f2 0x9e3b6188 0xbb28f2c5 0x559d3dd2
+ 0xc38861b2 0xfd7242b1 0x716c29e2 0x270236a9
+ 0xaaf33479 0x610a7d76 0xc0d564fc 0xf0bb1bd8
+ 0x31fb232b 0xf19ebb3f 0xd62acd99 0x5e45578e
+ 0x467c587f 0x0ac00140 0x9c7c1705 0x61a8a1ea
+ 0x4c5e4e5d 0x0e0d846c 0xd199939c 0xb4c615ae
+ 0x4cfe60cd 0x6b4e5cf4 0xe97ad9ec 0xf325a456
+ 0x6ca45a64 0xb88b4506 0x9f751f49 0x1d66e330
+ 0x59b40444 0x00f530b0 0x9242124d 0xac6de2f9
+ 0x7b7e7a67 0x64962ed3 0xfd0825bc 0xbdbcc113
+ 0x38d8d589 0x3cedb53e 0x17d95495 0x020b8ac2
+ 0xe9aa9bdf 0x0a5a2820 0x64670635 0x91a2a89e
+ 0x91bec6be 0xe9b4f902 0x1ef88ee7 0xec6e1208
+ 0x149e39ca 0xb140ce3b 0x3210a2a7 0x8e489c45
+ 0x59d3ebad 0x30275658 0xc20708d2 0xffdc3e00
+ 0x96c700b8 0x3d03aea6 0xf0ce7ad3 0x232a5585
+ 0xb0dc6620 0x1c1357b3 0xfb4c6d29 0xe5c5b7b7
+ 0xc4bfe2aa 0x37f7ce13 0x433eb884 0x3dde220f
+ 0xc1c34602 0xea700f6f 0x37b79490 0xad5761a3
+ 0xfc5917b1 0x22f7e1be 0xa90566d8 0x89e9db15
+ 0xf91bfa1f 0xdad2260c 0x93eba86f 0x2d94c130
+ 0x777290f1 0x2e656559 0x9be4a490 0x377a6ea0
+ 0x1b4523e4 0xdca0c8a5 0xb00eed31 0x6baeb803
+ 0x9601ee69 0x13d53e86 0xba8d6d8f 0xed6203ce
+ 0xc844f9c7 0x91e8a556 0x39974676 0x3b81329b
+ 0xdd7f10e1 0xbccb6558 0xb20de25c 0x448c44ee
+ 0x8932398a 0x76717b57 0xb20a667a 0x14e2df4a
+ 0xa57107f6 0x701b6c36 0x4b83a1ac 0xb39a1c9e
+ 0x2cc7e9fe 0xf5ae4a62 0x620687b6 0x2d6aef9d
+ 0x6672612c 0x168cdc7e 0x8b09abea 0x522692da
+ 0x6461676d 0x34ab3a9c 0x0d61a2ba 0x0590fef1
+ 0xe9b4b475 0x2dfb6081 0xbcdafb25 0xdae642aa
+ 0x9a9230fd 0xfd67f346 0xdb9d66e1 0x5b307b61
+ 0x9d4f1869 0x21133d6f 0x5157502f 0xcc8ccbc5
+ 0xb6631100 0xa33f48db 0xc0172774 0x5cb276ac
+ 0xe6e5c560 0x07e126dd 0x42bcf23a 0x8064fd70
+ 0x567ece78 0xbbc2fe32 0x9d5ee1bb 0x175b24be
+ 0xf0feac7a 0x57322618 0xfe9e893f 0xa9b2d67b
+ 0x36d03f5a 0xdf178831 0x4da346c5 0x843b1b10
+ 0x0d688dca 0x41a475c6 0x4b7adf33 0x145a00dc
+ 0xcd226a4d 0x4c40cf2c 0xd4972929 0xbad5ea65
+ 0xa96987fa 0xbe247d1c 0x49f2ce89 0xe09bbe72
+ 0xee48486e 0x34b41435 0xb41dbb86 0xe58866c9
+ 0xe848e228 0x18880947 0xd03cd275 0xca285915
+ 0x53dd0097 0xff9069f9 0xaff6a8cd 0xbfe16ac5
+ 0x5e88e076 0xac629a26 0x5a99bee9 0xea892a43
+ 0x8d1d5ce8 0x806a38e3 0xc4d99fcd 0x331a4a01
+ 0x0e586310 0xdd2dfabb 0xe7e6ad37 0x31d67fb1
+ 0xbb985560 0xc969ce24 0x3a424634 0x20a2080e
+ 0xeb1b587c 0x5cf7da4b 0xdaec0133 0xc99abb17
+ 0x63ab9c8f 0xef7e4042 0xca513c8a 0x4e15f5d9
+ 0x7cf8fc96 0x464cea5a 0x2363577d 0xd21bb7db
+ 0x1d977a0f 0xb02f4878 0x4fd1a03b 0x435b9149
+ 0xdfba062e 0xa2f7fc23 0x5ebde93c 0x28e9ed7a
+ 0x4023b147 0x9cac0cf9 0x7c5d5ca1 0xb7453148
+ 0xa52197d9 0xb85dd94b 0x72ee7e51 0xb81f4f5c
+ 0x97a4b485 0x13d8858a 0xa0aabd28 0x9d381125
+ 0x4960d2a7 0xa62787b2 0x865231c2 0xd637cc90
+ 0x6d58f3b7 0xe2759f6e 0xa28af8da 0x5a005f20
+ 0xc11c495b 0x85ecc413 0x657e7b91 0x10b39f7e
+ 0x3fcc394a 0x94b3fc3a 0xb359d60e 0x2e6c1555
+ 0x67d6d21d 0xb0457bc4 0x004f329a 0x2e131d8b
+ 0xfbfbff2a 0x2c1bcbef 0x181f26b6 0x32ebda60
+ 0xa0839e5a 0x241097df 0xb3f070a7 0xefbbd9f0
+ 0x7c3669c7 0x265f2dbc 0x0bd00e42 0x80d6c4c2
+ 0x44874336 0x0b6e7e0a 0xec590889 0xef865c09
+ 0x1a02ac8a 0xfbf78784 0xaaf89d75 0xa86c9caa
+ 0xc626528d 0xfbcec50f 0x2955f18e 0xb5e9a833
+ 0xae60f6bb 0xb3f4c51e 0x21bd6a6e 0x092a6861
+ 0x162d73dd 0xacfa4f0e 0x4efed2bd 0x88980089
+ 0xa2cee6d9 0xdf0953b8 0x6bf5208d 0x4364ed53
+ 0x1a5f19ad 0x2ec7711e 0x7d18832b 0x0f1b28a6
+ 0x0e127845 0x278a6a61 0x9e236436 0xf4646e82
+ 0x07fff0f3 0x34ae92f9 0xec3e71af 0xf7ec7c67
+ 0xdb9ddd62 0xe664e712 0xbb48a158 0x30a14ae6
+ 0x0d93b021 0x83082cc8 0x68952311 0x001b0003
+ 0xf0688e25 0x6c3b5161 0xfff18a53 0xbd1fb0c9
+ 0xe3cc9013 0x1d1e553e 0xa85cdfb0 0x358afc14
+ 0x61749007 0x6fad59bd 0xe85f4500 0x26a5ffa1
+ 0xedd69e21 0x4c1db8ce 0xaf3be18f 0xcd75c259
+ 0xd05f62ee 0x2f0ff1b7 0x717d9bd3 0x62e13392
+ 0x159ce5ce 0xcd9e9bff 0x8964600e 0x57d85abb
+ 0x3f5ead09 0x2d5d4a55 0x87da8369 0xc7944933
+ 0xcde9a717 0x55fa318d 0x112e1607 0x2ca832cb
+ 0xb1181bd5 0x7541a7d4 0xac1a1e20 0x6ad024c8
+ 0x119378ec 0x60b6cbfb 0x068e2f24 0x83acecb1
+ 0x87fd0df3 0x94c9552f 0x08c3d8dc 0x56f1b514
+ 0x717d50e9 0x9680fc39 0xa1bdb28a 0x3dfa1c7c
+ 0x8fc84774 0xb72e06d7 0x42b7ad1e 0x93646393
+ 0xd3632e4a 0x368d78f2 0x36a5ac5b 0x6576a4d8
+ 0x8bc6856c 0xd447936a 0xbec6fb22 0xab285e59
+ 0x3db2c781 0x72eda32a 0x9d654f18 0xdbd78e99
+ 0xbba310ad 0x938ecfc6 0x72d5079a 0x49e2fad4
+ 0x4b44dc75 0x81e82165 0xbe269c9c 0x2558ae80
+ 0xa3bb693e 0x107d10fd 0x8e4fd977 0x22926b4f
+ 0x68c9a7f8 0x6b7439e0 0x5c71c127 0xff5d88b3
+ 0x9d8cce8e 0x02982a71 0xf8fe1ceb 0x3ed3996b
+ 0x1e4f9957 0x63aca642 0xcc9db51b 0xbcb5af80
+ 0x7b2bf393 0x2915079f 0x87f531c5 0xfb06b13a
+ 0x550b261c 0xf01fa342 0xcdf4dd86 0x76718f50
+ 0x717c6bde 0xf460ef23 0x7f912022 0x54fe5b9b
+ 0xc7a5261b 0x073ea6e7 0x71504d55 0x91dd9b8e
+ 0x6d259452 0x2dc96e43 0x289959ca 0x128176a5
+ 0x8d004371 0x835c494e 0x0efa1879 0xddc02e95
+ 0xf0f4618e 0xc67656e2 0xd2bde6b1 0xccaa5e84
+ 0xc6592f19 0x91d01db8 0x2b697d22 0x8adfa55f
+ 0x5a49e4e7 0x897d5c43 0xd326d94f 0xf5ff0c5b
+ 0x57976ca6 0xeff0db4e 0x6d49d466 0x7c054970
+ 0xd3eb0f9f 0x0cbdce79 0x1beaf714 0xfe2df967
+ 0x6a50895e 0x013167bf 0x6139e59c 0x0662ecee
+ 0x9a8d6b53 0xfffb8649 0xce0e685f 0xea5b2a7a
+ 0x8819a629 0x5f96afb4 0x8891acfe 0x545f1097
+ 0x9f314e1b 0x248a5272 0xa40b8424 0xe42af07a
+ 0xa180f331 0x904f3c05 0x98455bc5 0x46198ed7
+ 0x03e208e5 0xcf670099 0x7a85b08c 0xba921ae2
+ 0x1e6947d0 0xddffa6ec 0xea6330d3 0xcda6957e
+ 0x19525cd3 0x311fb407 0x796c1ff4 0x3a2760fb
+ 0xde4bdd71 0xdb289b69 0x9811773c 0xa72cd839
+ 0x03da90de 0xd42912e8 0x8da1fb0a 0x985d4132
+ 0x5890ae40 0x1f7724d0 0xa336824f 0xca19df32
+ 0xf8ac73d1 0x61c370a9 0xe152b073 0xdafc6461
+ 0x23672042 0x9e6982b6 0x1256c6b4 0xe6bf2c9c
+ 0x9dae123e 0x30896b8f 0x99acf3a3 0xaa05d384
+ 0xea3b7bb7 0xe711d473 0xa9053351 0x71a85cb4
+ 0x3a0f5d25 0x2db3cb48 0x86314a6e 0xf7a2265b
+ 0xf7dc1cc3 0x548f56cf 0x4028a1ee 0x7d2e25d5
+ 0x68c87e37 0xbced6b8c 0x536cc252 0x68bab5ca
+ 0x1158c6c5 0xae0e9509 0x66fa6885 0x22bf2b9a
+ 0xa7a60a97 0x18f4f609 0x348623eb 0x773e705f
+ 0xb3d6622f 0x8f348186 0x81cb9856 0x64bf21ba
+ 0x47e1f96d 0xc95a5843 0xeff6cfce 0x08cb092c
+ 0xf214e48d 0xce272fec 0x57bf90df 0x3c425ea8
+ 0x856e1f5e 0x5c21d1b6 0x105488a3 0x553971eb
+ 0xde614ee5 0xdfa3ac81 0xc5eca5b1 0x69d02d23
+ 0x2a0fefb7 0xf9a01854 0xdd99f277 0x75014d7d
+ 0x3830e3dd 0x7dd8f1e7 0xdac5ac92 0xbf57c03a
+ 0xa5e6a6c7 0xb7c1b7a9 0xc8c8405e 0xfd1977da
+ 0x1e6a7ca4 0x299e1025 0x651a0e55 0x53d624a7
+ 0xccc9e861 0x901bce45 0x1de5a1ab 0x6140dcef
+ 0x3e09eafb 0x20c63cd0 0xff642faa 0xbc91a0a7
+ 0xe373e111 0x857236e7 0xe3e61037 0x0b6cc497
+ 0xca1da7e6 0x60e53803 0xb68663db 0x42e9956a
+ 0xbf4a1650 0xb43f25ec 0xc1232a3a 0x283c2ff3
+ 0xcd233183 0x17ccdfc0 0x03ac3e6d 0xa68ced48
+ 0xe38217d5 0x03c6472d 0x6a623afc 0xfce0d117
+ 0x448ee829 0x0909efd4 0x843a3b4a 0x9ad07683
+ 0x2250af2a 0x01ecc053 0x29684919 0x4ee0c62e
+ 0xa326a904 0x3ec83943 0xc42b0663 0x966379b2
+ 0xc672ece4 0x39391ad3 0x689a10f9 0xd3e9cbd6
+ 0x4bfa8446 0xd1ef6375 0xfe01b6a9 0xbda7d01a
+ 0x1e6879bf 0x05bdf46e 0x14ccab04 0xb02ae668
+ 0x58b51752 0x5eb8e83c 0x753d99de 0x87e4235b
+ 0x80b2afe7 0x127439fe 0x127a98a4 0xe5934c92
+ 0x86044bc0 0xa9664abb 0x91365b53 0x35b14bda
+ 0x67755842 0x7239651a 0x49e0b2e6 0xbb1d25fe
+ 0x51ca7213 0xaff2fd82 0xc1223aba 0x02941bcf
+ 0xb6ec2cfe 0xaa817dc0 0xe0475250 0x78098112
+ 0x750ae102 0x0b3135fa 0x23b648d4 0xbc9d78bd
+ 0xc5d7e046 0xe90ef47c 0x7f21eb75 0xdb304b0b
+ 0xa2c12ee2 0xb45e62ed 0x9f50feb6 0xe036ff55
+ 0x422f410b 0x2385de45 0xb37df6a5 0x4c2abf10
+ 0x6a2c7370 0xf35197ac 0x381face9 0x694761c6
+ 0xb2275097 0x208824c7 0x945300a0 0x4ad3f83d
+ 0x38a7aa12 0x00daaf41 0xcd4b2c19 0x25b2e8f7
+ 0x60d3e39b 0xb3dd8220 0x152f86ab 0xd1ec4233
+ 0x1c3df78a 0x5aeac74e 0xdeea2fe3 0xcfcf9b2e
+ 0x6efc8b2a 0x12a8c5c3 0xb56384e4 0x1b1fe549
+ 0xc55acb4d 0x78e7306a 0x733b0f70 0xf4afe6be
+ 0x6d904b03 0x7ddd7862 0x4da02602 0xfce1e904
+ 0x78773a4b 0x9083e908 0xda8a7593 0xafd8776e
+ 0x9e5ae37a 0xd6e7c557 0xad27adaa 0xd0f1a995
+ 0x1c84e046 0x3319b21a 0xd24c0d03 0x1789df77
+ 0x0f02b9ff 0xdb911f76 0xb2df7654 0x2e75a7bd
+ 0x8acc6fd3 0x3c16ec0b 0xe0d7ac22 0x3ddd1ce1
+ 0xfa9ec67a 0x48f2c409 0xf8099606 0xd73a459d
+ 0x9b2b3fa5 0x8e3c3e9c 0x8b99286a 0x006c0e07
+ 0xc299ded3 0x8a2bd400 0x74508dd4 0x609b4afc
+ 0x1a532838 0xb352a629 0xd390d8af 0x440a5798
+ 0xd31f6ad5 0x161aa48e 0x24a4359f 0xf39f49f7
+ 0xff160d2a 0x27a24637 0x84c46d40 0x988d026a
+ 0x5697a68f 0xeae970a0 0x42689e3d 0xc84ee62f
+ 0x764aabd5 0xb6d74ba5 0x8efc05a6 0xf2d0eccb
+ 0x2b4fa41c 0xad24799f 0xf73b8353 0x76bcd448
+ 0x08172d5e 0x5c6be301 0x926ffdd6 0xfa31009f
+ 0x8339c5f9 0x9dde2840 0x00c2d730 0x6402335f
+ 0xf6f84eda 0x5b0e628a 0x140dbafb 0x0533ee67
+ 0xa7523e60 0x20ca14b3 0x1145d280 0xb0c0ba41
+ 0x81f174d1 0xb80fc64e 0xe8321cfe 0x5762e501
+ 0x9e266b75 0x2695a738 0xe3104779 0x1d1ea19e
+ 0x15fd1d53 0xf0fbd4ee 0xc82f4552 0x4ea98e23
+ 0xec892d69 0x66ccadeb 0x2fdf99b4 0xafffec15
+ 0x2de5ee13 0x5e6ead7f 0x20b111cd 0x752254d1
+ 0xc0126f43 0xe2695fd8 0x38651d40 0x15b708ce
+ 0xf2c2ffdc 0xec24c68c 0x04351ddc 0xceac029b
+ 0x0525fc89 0x90e28526 0x0a23a4c2 0xbb33a5c4
+ 0x13f1fc38 0x66d79cd9 0x0acabe80 0x8d4ef5d8
+ 0x4091808e 0x02f7150b 0xf550597e 0x52703c3f
+ 0xfc954b68 0xe9ebaccb 0xd4f35b2a 0x93793446
+ 0xc40799e6 0xa963fc0c 0x92c8d8f1 0xbc8218dc
+ 0x9ec5c30a 0x8a6a2217 0x63d13dfe 0xea664e1e
+ 0x487192a7 0x1c8f8610 0x88e20f93 0xc54a6de3
+ 0x0111ae79 0x1335f02e 0xa2e2d37d 0xc2563697
+ 0x5fffcdec 0x233919ab 0x3bab1329 0x61943e99
+ 0xea7940f7 0x3cc62cf4 0xaedc5bc4 0x41b63f2c
+ 0x6dbf285f 0xb4793534 0x0e1013f2 0xc54d8c2d
+ 0x23c587f7 0x75df0092 0xc055254a 0x55db2c71
+ 0x518eaa5b 0x55c810d6 0x9c44ca37 0x034287ea
+ 0xe06a0567 0x221a0d8c 0x037a9164 0x36693ef9
+ 0xb7d270a6 0xa8d84a63 0xe8862970 0x484077b7
+ 0xab426cb7 0x37db7c9e 0xb34e1752 0x35444958
+ 0x00d48e90 0x8142602d 0x8ca28e2c 0x714598c9
+ 0xb1cce1be 0xbb98db74 0x400e1029 0x330cb2b6
+ 0x1fd3f8ce 0x2abf7516 0xc2d07e5c 0x2b1d2b80
+ 0xf06bd895 0x2fa7bc09 0xbdbdf893 0xd8466f85
+ 0x61e551b0 0x5b99bfb8 0x86ea5ee7 0xfd82ff9a
+ 0xd7c6344a 0x1fa144d8 0x650f0f02 0x71bd73cf
+ 0x2825177d 0x56c76399 0x2e0b873e 0xc3bf939d
+ 0xf8bc3c1b 0x468482e7 0x33cb98a7 0xa679eaf4
+ 0x32ba9b49 0xde86d50c 0x9eeeeee5 0x94a306e5
+ 0x432e1c9c 0x37997d0c 0xa84d981f 0xbe07b56d
+ 0x4ab6d465 0xa3cd92c4 0x5dea82ab 0xf771249d
+ 0x78f87ba5 0x8105df1c 0x3d74e1c1 0xf48cd4c1
+ 0x8ad010e1 0x9e9a2758 0x509c8953 0xeaaed79a
+ 0x97a4ecb7 0x23ffceb0 0xb3e42e61 0x5f41b4eb
+ 0x14d2804c 0x2d635ad3 0xe1314781 0x3921ec18
+ 0x3dbebec3 0x94e0df22 0xb0b4724e 0x0e7f986b
+ 0x83dd7694 0x7041a22e 0x3c942757 0xd6ff5cbb
+ 0x048b0426 0xa5d6c4cb 0x1f4e3bbd 0x78d5924e
+ 0x6a857d77 0x1d115ecc 0x73c6a888 0xefb934ee
+ 0xa7d1702b 0x6794a668 0x03715b90 0xfbab19f9
+ 0xd5a433df 0x12f4d421 0x40519650 0x636a093e
+ 0x1601be15 0xe0fbef6f 0x79d775bc 0x789c3a30
+ 0x4d9fa618 0xedf8fa70 0xb0fa402d 0x692ee91b
+ 0x5a593e5c 0x0fa3667f 0x3f51a636 0x935e28c7
+ 0x230b725a 0x4929bc83 0x76de40ad 0x2d9a5f7f
+ 0x8799e033 0xbf2700b0 0x5220159d 0x1ed71ca5
+ 0xcc66f114 0x15fd868d 0x4236645a 0xded2558e
+ 0xa561cc0d 0x02822e5b 0xd0177f80 0xf09badd9
+ 0xd5380ae3 0xcfc11a46 0x36713416 0x7f3d60cc
+ 0x4018797e 0xc6b23941 0xcb5a4861 0x614ce6df
+ 0xabfc0629 0xa519bcfc 0x911f04f0 0xe509b546
+ 0xbb411eb9 0x9e6b921c 0xbf0b1c70 0x80c2901c
+ 0x85786713 0xad2aafec 0x62711ba7 0x6edb4971
+ 0x214eb137 0x45b1b313 0x6742d5e9 0x7daf37a6
+ 0x21d6a27a 0x059424f7 0x2c8c3dfb 0xe7a06c77
+ 0x10815625 0xb4dc69e8 0x52767f66 0x44d48738
+ 0x84d26c93 0x09008893 0xfc21394a 0x82155a72
+ 0xc4fd7512 0x6d43cd2f 0xcae99e08 0x453175ae
+ 0xc6ee93a3 0x2fed0eac 0xe48fb73d 0x0afe2d2a
+ 0x5966735e 0xdc7e5fb6 0xed1ef13d 0x7e08a106
+ 0xd3ca0e6b 0x4ce5ca02 0xa0beebed 0xe982c609
+ 0x1ee9e5a2 0x24ae26cb 0xfd4c08d4 0x5e85e850
+ 0x11b54b3b 0x87209692 0x4a5b0c35 0xcd25dd6f
+ 0xd9570253 0xaad0b9fe 0xaf984fee 0x6cf7ae2d
+ 0x45d9926c 0x07a66ac6 0x8e7aacdc 0xaf587d66
+ 0x53972a4e 0x8da4a6c9 0x2bc311e5 0x36938ae8
+ 0x179b965d 0x515743f7 0xb5bbbdcd 0xd8602715
+ 0x9e43049f 0x4e78a080 0xba3f1750 0x68635cf0
+ 0x85823047 0xbb03b5fd 0xb0d747c8 0x58d214af
+ 0x94b1ba85 0x6d2cf8ac 0x2bc1faeb 0x6bd7c1e3
+ 0x127658e9 0x8b499020 0xab8f0f62 0xee665a6a
+ 0x89240e4d 0x8a95342b 0x00b38ccc 0xe6b14d9d
+ 0x32a2af71 0x4c9ecb69 0xc8de2685 0xd7385184
+ 0x8e943872 0x809b2c79 0x108511da 0x08b4f54d
+ 0x95f52442 0x26fe296f 0xf7e037c0 0xa1aecdd3
+ 0x89774a91 0xde67c55f 0x1f9816dc 0x1469a4c2
+ 0x28240be2 0x5fd0ad14 0x0949db3a 0x451b94d3
+ 0x637e6d49 0x8a4771c8 0xf65104b7 0xc3058c40
+ 0x592fe4d0 0xe26129f0 0xe66e6ce9 0x26ab39b8
+ 0x308da532 0x205afe77 0x6dc78664 0x84d4890f
+ 0x9d49fcb0 0xcac8f2ed 0xe713d798 0xfed7c75b
+ 0xe441a0d4 0xdf60df37 0xc2eed2f5 0x2d68b20e
+ 0x7827c89a 0x9d4cb9f2 0xb8912cce 0x07516335
+ 0x976ffbb6 0x5cd0de48 0xed716f54 0x6f3c9f7f
+ 0x34cf42d1 0xc1027cbb 0xde67c065 0xe0a229af
+ 0xfc8bd2e8 0xd62ca176 0x8bfb76b2 0x54a1388f
+ 0xe0650bb6 0x6d60682b 0xe16cf130 0xbd7c3ca2
+ 0xea642814 0xa25f4d44 0x27013786 0x7316aa38
+ 0x571511c8 0xf1b6b789 0xb7bfe72b 0x8fd2652c
+ 0xbfc7771a 0x51a2e551 0x3bd738c2 0x2698b495
+ 0xec69a196 0xd5ecb5c4 0x9bd3224c 0x6d9ab4cf
+ 0x326c9942 0x4d711191 0xde9be50a 0xa980ca0b
+ 0xe8e59dd0 0x4439e4ae 0x35de914d 0xee499a84
+ 0xd1ca0c9d 0xfe6ee96d 0x5b1f4fd0 0xabf0621a
+ 0x0c8220c7 0xcb6dbb1e 0xa5116036 0xe858d3c3
+ 0x728e3a56 0x3b33e818 0xbe2643c1 0x497bbcc7
+ 0xeb369828 0x9a4a01be 0x8c7e72a6 0xaf052f25
+ 0x8d3ca85b 0x4703e55e 0x45647d4c 0x86d1e3e8
+ 0x40ab59f9 0x3259b195 0xf979a147 0xb8961870
+ 0x88b024f9 0x366e26bc 0xd6811525 0x252910c2
+ 0x4223a20e 0x7fc971a3 0x4a639bf3 0xb6550c3b
+ 0xfe05e552 0xbdc98897 0x509923ff 0xf51a5abc
+ 0xc6cc0891 0x61cdac05 0x03a68664 0x1b80cc76
+ 0xe18d8ee1 0x798bb4d2 0xd7769bf9 0x9ab4c02d
+ 0x7484774b 0xa9ee2c8b 0x87d34c85 0x15697682
+ 0x9f6a4a55 0x9d7a731c 0x10014d6a 0xb9798070
+ 0xd42f79cb 0x89db59b3 0xd5b0a0b6 0xf60864a5
+ 0x2d6fb084 0x1cb607b2 0x48232701 0x9310cbc6
+ 0x5bc81c98 0x6b25016c 0x2014b99d 0x0836e60b
+ 0x0addbc4c 0x3b8bac7c 0x8d95ac77 0x1d56c3c7
+ 0x58333104 0x3d6eb719 0x676eb951 0xd5c2d1a3
+ 0x239dae86 0x92181ab8 0xbdde9741 0x7995d452
+ 0xe0020661 0x2f80c8b7 0xeedcd4fc 0xe4bde175
+ 0xb98fdf78 0x84b9228f 0x78ecb4f3 0xe99e5d46
+ 0xa33b9b96 0xe2cbc71c 0xc19e2146 0xdc0ee758
+ 0x2d8f8767 0x2036685b 0x149df155 0x2e7ab376
+ 0xb13b4266 0xf5c8a3b0 0x02ca1e19 0x1badd81b
+ 0xb9c1832a 0x73b31f75 0x69979b55 0x567070a2
+ 0x2edeb3dc 0x26b55921 0x461df49f 0xc1aba883
+ 0x25d6faec 0x5260e9bf 0xa8ccdd4c 0x04291961
+ 0xfaf7a1b8 0xbc2d36e3 0xd6c86385 0x2757fbb9
+ 0x62c7107c 0x87dac461 0x0c006454 0x0e971e49
+ 0x4749afca 0x7f1fb389 0xdc0b69d3 0xc69fab09
+ 0x12c372c9 0x78480a51 0x8ab03a94 0xb37022ca
+ 0x1d00e893 0x0989de45 0x8c819503 0x8e0e1c06
+ 0x11cfef86 0x3c2386a6 0x66c0e6c8 0x1befa478
+ 0xd2e7a4a7 0x9a8b5917 0x2cfa1816 0xaf7e6c7a
+ 0xd6c9f0ff 0x1aada3e0 0xbe36a471 0x5a91f3c7
+ 0x6c61ea95 0x5246ef7c 0x20bc86c4 0xcfd87abd
+ 0xdc61f595 0x8310a684 0x0477e35c 0xe59e776f
+ 0xfa403863 0xdaf7bcb1 0xd6084825 0xb90bb047
+ 0xeb9ff684 0x7223fbca 0x6b4af987 0x6b2553f8
+ 0xdaabc6d2 0x82e2ebc3 0xa7c1c054 0x667eb0a7
+ 0x53a0c7d4 0x3fcba743 0x38170187 0x2a2e5830
+ 0xee134608 0xcd6e0112 0xac0831f9 0x9537d532
+ 0x1e176b9c 0xe3fcb69f 0x17a2eee9 0xa9e6467f
+ 0xbf6b0246 0x6a08c0fb 0x7fb943b6 0xb8f67c0e
+ 0x2b3b4ffc 0xb155d20c 0x4eb5de53 0xf078715b
+ >;
diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
new file mode 100644
index 0000000000..8f34369753
--- /dev/null
+++ b/arch/x86/dts/minnowmax.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
+
+/ {
+ model = "Intel Minnowboard Max";
+ compatible = "intel,minnowmax", "intel,baytrail";
+
+ aliases {
+ serial0 = &serial;
+ };
+
+ config {
+ silent_console = <0>;
+ };
+
+ chosen {
+ stdout-path = "/serial";
+ };
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ich";
+ spi-flash@0 {
+ reg = <0>;
+ compatible = "sst,25vf016b", "spi-flash";
+ memory-map = <0xff800000 0x00800000>;
+ };
+ };
+
+ microcode {
+ update@0 {
+#include "microcode/m0130673322.dtsi"
+ };
+ };
+
+};
diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi
index 9b097f4f9b..6865eed9dd 100644
--- a/arch/x86/dts/serial.dtsi
+++ b/arch/x86/dts/serial.dtsi
@@ -1,5 +1,5 @@
/ {
- serial {
+ serial: serial {
compatible = "x86-uart";
reg = <0x3f8 8>;
reg-shift = <0>;
diff --git a/arch/x86/include/asm/arch-baytrail/fsp/azalia.h b/arch/x86/include/asm/arch-baytrail/fsp/azalia.h
new file mode 100644
index 0000000000..d96a20fc8d
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/fsp/azalia.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#ifndef _FSP_AZALIA_H_
+#define _FSP_AZALIA_H_
+
+struct __packed pch_azalia_verb_table_header {
+ uint32_t vendor_device_id;
+ uint16_t sub_system_id;
+ uint8_t revision_id; /* 0xff applies to all steppings */
+ uint8_t front_panel_support;
+ uint16_t number_of_rear_jacks;
+ uint16_t number_of_front_jacks;
+};
+
+struct __packed pch_azalia_verb_table {
+ struct pch_azalia_verb_table_header verb_table_header;
+ const uint32_t *verb_table_data;
+};
+
+struct __packed pch_azalia_config {
+ uint8_t pme_enable:1;
+ uint8_t docking_supported:1;
+ uint8_t docking_attached:1;
+ uint8_t hdmi_codec_enable:1;
+ uint8_t azalia_v_ci_enable:1;
+ uint8_t rsvdbits:3;
+ /* number of verb tables provided by platform */
+ uint8_t azalia_verb_table_num;
+ const struct pch_azalia_verb_table *azalia_verb_table;
+ /* delay timer after azalia reset */
+ uint16_t reset_wait_timer_us;
+};
+
+#endif
diff --git a/arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h
new file mode 100644
index 0000000000..82862f626d
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#ifndef __FSP_VPD_H
+#define __FSP_VPD_H
+
+struct memory_down_data {
+ uint8_t enable_memory_down;
+ uint8_t dram_speed;
+ uint8_t dram_type;
+ uint8_t dimm_0_enable;
+ uint8_t dimm_1_enable;
+ uint8_t dimm_width;
+ uint8_t dimm_density;
+ uint8_t dimm_bus_width;
+ uint8_t dimm_sides; /* Ranks Per dimm_ */
+ uint8_t dimm_tcl; /* tCL */
+ /* tRP and tRCD in DRAM clk - 5:12.5ns, 6:15ns, etc. */
+ uint8_t dimm_trpt_rcd;
+ uint8_t dimm_twr; /* tWR in DRAM clk */
+ uint8_t dimm_twtr; /* tWTR in DRAM clk */
+ uint8_t dimm_trrd; /* tRRD in DRAM clk */
+ uint8_t dimm_trtp; /* tRTP in DRAM clk */
+ uint8_t dimm_tfaw; /* tFAW in DRAM clk */
+};
+
+struct __packed upd_region {
+ uint64_t signature; /* Offset 0x0000 */
+ uint8_t reserved0[24]; /* Offset 0x0008 */
+ uint16_t mrc_init_tseg_size; /* Offset 0x0020 */
+ uint16_t mrc_init_mmio_size; /* Offset 0x0022 */
+ uint8_t mrc_init_spd_addr1; /* Offset 0x0024 */
+ uint8_t mrc_init_spd_addr2; /* Offset 0x0025 */
+ uint8_t emmc_boot_mode; /* Offset 0x0026 */
+ uint8_t enable_sdio; /* Offset 0x0027 */
+ uint8_t enable_sdcard; /* Offset 0x0028 */
+ uint8_t enable_hsuart0; /* Offset 0x0029 */
+ uint8_t enable_hsuart1; /* Offset 0x002a */
+ uint8_t enable_spi; /* Offset 0x002b */
+ uint8_t reserved1; /* Offset 0x002c */
+ uint8_t enable_sata; /* Offset 0x002d */
+ uint8_t sata_mode; /* Offset 0x002e */
+ uint8_t enable_azalia; /* Offset 0x002f */
+ uint32_t azalia_config_ptr; /* Offset 0x0030 */
+ uint8_t enable_xhci; /* Offset 0x0034 */
+ uint8_t enable_lpe; /* Offset 0x0035 */
+ uint8_t lpss_sio_enable_pci_mode; /* Offset 0x0036 */
+ uint8_t enable_dma0; /* Offset 0x0037 */
+ uint8_t enable_dma1; /* Offset 0x0038 */
+ uint8_t enable_i2_c0; /* Offset 0x0039 */
+ uint8_t enable_i2_c1; /* Offset 0x003a */
+ uint8_t enable_i2_c2; /* Offset 0x003b */
+ uint8_t enable_i2_c3; /* Offset 0x003c */
+ uint8_t enable_i2_c4; /* Offset 0x003d */
+ uint8_t enable_i2_c5; /* Offset 0x003e */
+ uint8_t enable_i2_c6; /* Offset 0x003f */
+ uint8_t enable_pwm0; /* Offset 0x0040 */
+ uint8_t enable_pwm1; /* Offset 0x0041 */
+ uint8_t enable_hsi; /* Offset 0x0042 */
+ uint8_t igd_dvmt50_pre_alloc; /* Offset 0x0043 */
+ uint8_t aperture_size; /* Offset 0x0044 */
+ uint8_t gtt_size; /* Offset 0x0045 */
+ uint32_t serial_debug_port_address; /* Offset 0x0046 */
+ uint8_t serial_debug_port_type; /* Offset 0x004a */
+ uint8_t mrc_debug_msg; /* Offset 0x004b */
+ uint8_t isp_enable; /* Offset 0x004c */
+ uint8_t scc_enable_pci_mode; /* Offset 0x004d */
+ uint8_t igd_render_standby; /* Offset 0x004e */
+ uint8_t txe_uma_enable; /* Offset 0x004f */
+ uint8_t os_selection; /* Offset 0x0050 */
+ uint8_t emmc45_ddr50_enabled; /* Offset 0x0051 */
+ uint8_t emmc45_hs200_enabled; /* Offset 0x0052 */
+ uint8_t emmc45_retune_timer_value; /* Offset 0x0053 */
+ uint8_t unused_upd_space1[156]; /* Offset 0x0054 */
+ struct memory_down_data memory_params; /* Offset 0x00f0 */
+ uint16_t terminator; /* Offset 0x0100 */
+};
+
+#define VPD_IMAGE_ID 0x3157454956594C56 /* 'VLYVIEW1' */
+#define VPD_IMAGE_REV 0x00000303
+
+struct __packed vpd_region {
+ uint64_t sign; /* Offset 0x0000 */
+ uint32_t img_rev; /* Offset 0x0008 */
+ uint32_t upd_offset; /* Offset 0x000c */
+ uint8_t unused[16]; /* Offset 0x0010 */
+ uint32_t fsp_res_memlen; /* Offset 0x0020 */
+ uint8_t platform_type; /* Offset 0x0024 */
+ uint8_t enable_secure_boot; /* Offset 0x0025 */
+};
+#endif
diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
new file mode 100644
index 0000000000..ab4e059131
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+/* Where in config space is the register that points to the GPIO registers? */
+#define PCI_CFG_GPIOBASE 0x44
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
index cf7457f42d..c9605258b5 100644
--- a/arch/x86/include/asm/arch-ivybridge/sandybridge.h
+++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
@@ -43,7 +43,7 @@
#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */
#define DEFAULT_RCBABASE 0xfed1c000
/* 4 KB per PCIe device */
-#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS
+#define DEFAULT_PCIEXBAR CONFIG_PCIE_ECAM_BASE
/* Device 0:0.0 PCI configuration space (Host Bridge) */
#define EPBAR 0x40
diff --git a/arch/x86/include/asm/arch-quark/device.h b/arch/x86/include/asm/arch-quark/device.h
new file mode 100644
index 0000000000..4af3dedc95
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/device.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _QUARK_DEVICE_H_
+#define _QUARK_DEVICE_H_
+
+#include <pci.h>
+
+#define QUARK_HOST_BRIDGE PCI_BDF(0, 0, 0)
+#define QUARK_MMC_SDIO PCI_BDF(0, 20, 0)
+#define QUARK_UART0 PCI_BDF(0, 20, 1)
+#define QUARK_USB_DEVICE PCI_BDF(0, 20, 2)
+#define QUARK_USB_EHCI PCI_BDF(0, 20, 3)
+#define QUARK_USB_OHCI PCI_BDF(0, 20, 4)
+#define QUARK_UART1 PCI_BDF(0, 20, 5)
+#define QUARK_EMAC0 PCI_BDF(0, 20, 6)
+#define QUARK_EMAC1 PCI_BDF(0, 20, 7)
+#define QUARK_SPI0 PCI_BDF(0, 21, 0)
+#define QUARK_SPI1 PCI_BDF(0, 21, 1)
+#define QUARK_I2C_GPIO PCI_BDF(0, 21, 2)
+#define QUARK_PCIE0 PCI_BDF(0, 23, 0)
+#define QUARK_PCIE1 PCI_BDF(0, 23, 1)
+#define QUARK_LEGACY_BRIDGE PCI_BDF(0, 31, 0)
+
+#endif /* _QUARK_DEVICE_H_ */
diff --git a/arch/x86/include/asm/arch-quark/gpio.h b/arch/x86/include/asm/arch-quark/gpio.h
new file mode 100644
index 0000000000..ca8cba4f97
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/gpio.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+/* Where in config space is the register that points to the GPIO registers? */
+#define PCI_CFG_GPIOBASE 0x44
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-quark/mrc.h b/arch/x86/include/asm/arch-quark/mrc.h
new file mode 100644
index 0000000000..150fbea0e0
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/mrc.h
@@ -0,0 +1,187 @@
+/*
+ * 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
+ *
+ * SPDX-License-Identifier: Intel
+ */
+
+#ifndef _MRC_H_
+#define _MRC_H_
+
+#define MRC_VERSION 0x0111
+
+/* architectural definitions */
+#define NUM_CHANNELS 1 /* number of channels */
+#define NUM_RANKS 2 /* number of ranks per channel */
+#define NUM_BYTE_LANES 4 /* number of byte lanes per channel */
+
+/* software limitations */
+#define MAX_CHANNELS 1
+#define MAX_RANKS 2
+#define MAX_BYTE_LANES 4
+
+#define MAX_SOCKETS 1
+#define MAX_SIDES 1
+#define MAX_ROWS (MAX_SIDES * MAX_SOCKETS)
+
+/* Specify DRAM and channel width */
+enum {
+ X8, /* DRAM width */
+ X16, /* DRAM width & Channel Width */
+ X32 /* Channel Width */
+};
+
+/* Specify DRAM speed */
+enum {
+ DDRFREQ_800,
+ DDRFREQ_1066
+};
+
+/* Specify DRAM type */
+enum {
+ DDR3,
+ DDR3L
+};
+
+/*
+ * density: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
+ * cl: DRAM CAS Latency in clocks
+ * ras: ACT to PRE command period
+ * wtr: Delay from start of internal write transaction to internal read command
+ * rrd: ACT to ACT command period (JESD79 specific to page size 1K/2K)
+ * faw: Four activate window (JESD79 specific to page size 1K/2K)
+ *
+ * ras/wtr/rrd/faw timings are in picoseconds
+ *
+ * Refer to JEDEC spec (or DRAM datasheet) when changing these values.
+ */
+struct dram_params {
+ uint8_t density;
+ uint8_t cl;
+ uint32_t ras;
+ uint32_t wtr;
+ uint32_t rrd;
+ uint32_t faw;
+};
+
+/*
+ * Delay configuration for individual signals
+ * Vref setting
+ * Scrambler seed
+ */
+struct mrc_timings {
+ uint32_t rcvn[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t rdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t wdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t wdq[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t vref[NUM_CHANNELS][NUM_BYTE_LANES];
+ uint32_t wctl[NUM_CHANNELS][NUM_RANKS];
+ uint32_t wcmd[NUM_CHANNELS];
+ uint32_t scrambler_seed;
+ /* need to save for the case of frequency change */
+ uint8_t ddr_speed;
+};
+
+/* Boot mode defined as bit mask (1<<n) */
+enum {
+ BM_UNKNOWN,
+ BM_COLD = 1, /* full training */
+ BM_FAST = 2, /* restore timing parameters */
+ BM_S3 = 4, /* resume from S3 */
+ BM_WARM = 8
+};
+
+/* MRC execution status */
+#define MRC_SUCCESS 0 /* initialization ok */
+#define MRC_E_MEMTEST 1 /* memtest failed */
+
+/*
+ * Memory Reference Code parameters
+ *
+ * It includes 3 parts:
+ * - input parameters like boot mode and DRAM parameters
+ * - context parameters for MRC internal state
+ * - output parameters like initialization result and memory size
+ */
+struct mrc_params {
+ /* Input parameters */
+ uint32_t boot_mode; /* BM_COLD, BM_FAST, BM_WARM, BM_S3 */
+ /* DRAM parameters */
+ uint8_t dram_width; /* x8, x16 */
+ uint8_t ddr_speed; /* DDRFREQ_800, DDRFREQ_1066 */
+ uint8_t ddr_type; /* DDR3, DDR3L */
+ uint8_t ecc_enables; /* 0, 1 (memory size reduced to 7/8) */
+ uint8_t scrambling_enables; /* 0, 1 */
+ /* 1, 3 (1'st rank has to be populated if 2'nd rank present) */
+ uint32_t rank_enables;
+ uint32_t channel_enables; /* 1 only */
+ uint32_t channel_width; /* x16 only */
+ /* 0, 1, 2 (mode 2 forced if ecc enabled) */
+ uint32_t address_mode;
+ /* REFRESH_RATE: 1=1.95us, 2=3.9us, 3=7.8us, others=RESERVED */
+ uint8_t refresh_rate;
+ /* SR_TEMP_RANGE: 0=normal, 1=extended, others=RESERVED */
+ uint8_t sr_temp_range;
+ /*
+ * RON_VALUE: 0=34ohm, 1=40ohm, others=RESERVED
+ * (select MRS1.DIC driver impedance control)
+ */
+ uint8_t ron_value;
+ /* RTT_NOM_VALUE: 0=40ohm, 1=60ohm, 2=120ohm, others=RESERVED */
+ uint8_t rtt_nom_value;
+ /* RD_ODT_VALUE: 0=off, 1=60ohm, 2=120ohm, 3=180ohm, others=RESERVED */
+ uint8_t rd_odt_value;
+ struct dram_params params;
+ /* Internally used context parameters */
+ uint32_t board_id; /* board layout (use x8 or x16 memory) */
+ uint32_t hte_setup; /* when set hte reconfiguration requested */
+ uint32_t menu_after_mrc;
+ uint32_t power_down_disable;
+ uint32_t tune_rcvn;
+ uint32_t channel_size[NUM_CHANNELS];
+ uint32_t column_bits[NUM_CHANNELS];
+ uint32_t row_bits[NUM_CHANNELS];
+ uint32_t mrs1; /* register content saved during training */
+ uint8_t first_run;
+ /* Output parameters */
+ /* initialization result (non zero specifies error code) */
+ uint32_t status;
+ /* total memory size in bytes (excludes ECC banks) */
+ uint32_t mem_size;
+ /* training results (also used on input) */
+ struct mrc_timings timings;
+};
+
+/*
+ * MRC memory initialization structure
+ *
+ * post_code: a 16-bit post code of a specific initialization routine
+ * boot_path: bitwise or of BM_COLD, BM_FAST, BM_WARM and BM_S3
+ * init_fn: real memory initialization routine
+ */
+struct mem_init {
+ uint16_t post_code;
+ uint16_t boot_path;
+ void (*init_fn)(struct mrc_params *mrc_params);
+};
+
+/* MRC platform data flags */
+#define MRC_FLAG_ECC_EN 0x00000001
+#define MRC_FLAG_SCRAMBLE_EN 0x00000002
+#define MRC_FLAG_MEMTEST_EN 0x00000004
+/* 0b DDR "fly-by" topology else 1b DDR "tree" topology */
+#define MRC_FLAG_TOP_TREE_EN 0x00000008
+/* If set ODR signal is asserted to DRAM devices on writes */
+#define MRC_FLAG_WR_ODT_EN 0x00000010
+
+/**
+ * mrc_init - Memory Reference Code initialization entry routine
+ *
+ * @mrc_params: parameters for MRC
+ */
+void mrc_init(struct mrc_params *mrc_params);
+
+#endif /* _MRC_H_ */
diff --git a/arch/x86/include/asm/arch-quark/msg_port.h b/arch/x86/include/asm/arch-quark/msg_port.h
new file mode 100644
index 0000000000..2e78a66725
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/msg_port.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _QUARK_MSG_PORT_H_
+#define _QUARK_MSG_PORT_H_
+
+/*
+ * In the Quark SoC, some chipset commands are accomplished by utilizing
+ * the internal message network within the host bridge (D0:F0). Accesses
+ * to this network are accomplished by populating the message control
+ * register (MCR), Message Control Register eXtension (MCRX) and the
+ * message data register (MDR).
+ */
+#define MSG_CTRL_REG 0xd0 /* Message Control Register */
+#define MSG_DATA_REG 0xd4 /* Message Data Register */
+#define MSG_CTRL_EXT_REG 0xd8 /* Message Control Register EXT */
+
+/* Normal Read/Write OpCodes */
+#define MSG_OP_READ 0x10
+#define MSG_OP_WRITE 0x11
+
+/* Alternative Read/Write OpCodes */
+#define MSG_OP_ALT_READ 0x06
+#define MSG_OP_ALT_WRITE 0x07
+
+/* IO Read/Write OpCodes */
+#define MSG_OP_IO_READ 0x02
+#define MSG_OP_IO_WRITE 0x03
+
+/* All byte enables */
+#define MSG_BYTE_ENABLE 0xf0
+
+#ifndef __ASSEMBLY__
+
+/**
+ * msg_port_setup - set up the message port control register
+ *
+ * @op: message bus access opcode
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ */
+void msg_port_setup(int op, int port, int reg);
+
+/**
+ * msg_port_read - read a message port register using normal opcode
+ *
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ *
+ * @return: message port register value
+ */
+u32 msg_port_read(u8 port, u32 reg);
+
+/**
+ * msg_port_write - write a message port register using normal opcode
+ *
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ * @value: register value to write
+ */
+void msg_port_write(u8 port, u32 reg, u32 value);
+
+/**
+ * msg_port_alt_read - read a message port register using alternative opcode
+ *
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ *
+ * @return: message port register value
+ */
+u32 msg_port_alt_read(u8 port, u32 reg);
+
+/**
+ * msg_port_alt_write - write a message port register using alternative opcode
+ *
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ * @value: register value to write
+ */
+void msg_port_alt_write(u8 port, u32 reg, u32 value);
+
+/**
+ * msg_port_io_read - read a message port register using I/O opcode
+ *
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ *
+ * @return: message port register value
+ */
+u32 msg_port_io_read(u8 port, u32 reg);
+
+/**
+ * msg_port_io_write - write a message port register using I/O opcode
+ *
+ * @port: port number on the message bus
+ * @reg: register number within a port
+ * @value: register value to write
+ */
+void msg_port_io_write(u8 port, u32 reg, u32 value);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _QUARK_MSG_PORT_H_ */
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h
new file mode 100644
index 0000000000..ceb583e3f0
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/quark.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _QUARK_H_
+#define _QUARK_H_
+
+/* Message Bus Ports */
+#define MSG_PORT_MEM_ARBITER 0x00
+#define MSG_PORT_HOST_BRIDGE 0x03
+#define MSG_PORT_RMU 0x04
+#define MSG_PORT_MEM_MGR 0x05
+#define MSG_PORT_SOC_UNIT 0x31
+
+/* Port 0x00: Memory Arbiter Message Port Registers */
+
+/* Enhanced Configuration Space */
+#define AEC_CTRL 0x00
+
+/* Port 0x03: Host Bridge Message Port Registers */
+
+/* Host Memory I/O Boundary */
+#define HM_BOUND 0x08
+
+/* Extended Configuration Space */
+#define HEC_REG 0x09
+
+/* Port 0x04: Remote Management Unit Message Port Registers */
+
+/* ACPI PBLK Base Address Register */
+#define PBLK_BA 0x70
+
+/* SPI DMA Base Address Register */
+#define SPI_DMA_BA 0x7a
+
+/* Port 0x05: Memory Manager Message Port Registers */
+
+/* eSRAM Block Page Control */
+#define ESRAM_BLK_CTRL 0x82
+#define ESRAM_BLOCK_MODE 0x10000000
+
+/* DRAM */
+#define DRAM_BASE 0x00000000
+#define DRAM_MAX_SIZE 0x80000000
+
+/* eSRAM */
+#define ESRAM_SIZE 0x80000
+
+/* Memory BAR Enable */
+#define MEM_BAR_EN 0x00000001
+
+/* I/O BAR Enable */
+#define IO_BAR_EN 0x80000000
+
+/* 64KiB of RMU binary in flash */
+#define RMU_BINARY_SIZE 0x10000
+
+/* Legacy Bridge PCI Configuration Registers */
+#define LB_GBA 0x44
+#define LB_PM1BLK 0x48
+#define LB_GPE0BLK 0x4c
+#define LB_ACTL 0x58
+#define LB_PABCDRC 0x60
+#define LB_PEFGHRC 0x64
+#define LB_WDTBA 0x84
+#define LB_BCE 0xd4
+#define LB_BC 0xd8
+#define LB_RCBA 0xf0
+
+#endif /* _QUARK_H_ */
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
index bce58b1e69..3c57558d21 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
+++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
@@ -10,8 +10,6 @@
#ifndef __VPDHEADER_H__
#define __VPDHEADER_H__
-#define UPD_TERMINATOR 0x55AA
-
struct __packed upd_region {
u64 sign; /* Offset 0x0000 */
u64 reserved; /* Offset 0x0008 */
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h b/arch/x86/include/asm/fsp/fsp_api.h
index a9d7156109..2d34d138ab 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h
+++ b/arch/x86/include/asm/fsp/fsp_api.h
@@ -8,6 +8,8 @@
#ifndef __FSP_API_H__
#define __FSP_API_H__
+#include <linux/linkage.h>
+
/*
* FspInit continuation function prototype.
* Control will be returned to this callback function after FspInit API call.
@@ -47,9 +49,9 @@ struct fsp_notify_params {
};
/* FspInit API function prototype */
-typedef u32 (*fsp_init_f)(struct fsp_init_params *params);
+typedef asmlinkage u32 (*fsp_init_f)(struct fsp_init_params *params);
/* FspNotify API function prototype */
-typedef u32 (*fsp_notify_f)(struct fsp_notify_params *params);
+typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
#endif
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h b/arch/x86/include/asm/fsp/fsp_bootmode.h
index c3f8b49471..c3f8b49471 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h
+++ b/arch/x86/include/asm/fsp/fsp_bootmode.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h b/arch/x86/include/asm/fsp/fsp_ffs.h
index eaec2b490e..eaec2b490e 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h
+++ b/arch/x86/include/asm/fsp/fsp_ffs.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h b/arch/x86/include/asm/fsp/fsp_fv.h
index a024451a74..a024451a74 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h
+++ b/arch/x86/include/asm/fsp/fsp_fv.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h
index 6cca7f5654..6cca7f5654 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
+++ b/arch/x86/include/asm/fsp/fsp_hob.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h b/arch/x86/include/asm/fsp/fsp_infoheader.h
index 4a4d627b28..4a4d627b28 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h
+++ b/arch/x86/include/asm/fsp/fsp_infoheader.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h b/arch/x86/include/asm/fsp/fsp_platform.h
index 61286ceb46..61286ceb46 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h
+++ b/arch/x86/include/asm/fsp/fsp_platform.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h
index ebdbd03435..c6c7dc0f83 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
+++ b/arch/x86/include/asm/fsp/fsp_support.h
@@ -16,7 +16,7 @@
#include "fsp_platform.h"
#include "fsp_infoheader.h"
#include "fsp_bootmode.h"
-#include "fsp_vpd.h"
+#include <asm/arch/fsp/fsp_vpd.h>
struct shared_data {
struct fsp_header *fsp_hdr;
@@ -26,6 +26,8 @@ struct shared_data {
#define FSP_LOWMEM_BASE 0x100000UL
#define FSP_HIGHMEM_BASE 0x100000000ULL
+#define UPD_TERMINATOR 0x55AA
+
/**
* FSP Continuation assembly helper routine
@@ -61,7 +63,7 @@ void fsp_continue(struct shared_data *shared_data, u32 status,
*
* @retval: the offset of FSP header. If signature is invalid, returns 0.
*/
-u32 find_fsp_header(void);
+struct fsp_header *find_fsp_header(void);
/**
* FSP initialization wrapper function.
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h b/arch/x86/include/asm/fsp/fsp_types.h
index f32d8273a0..f32d8273a0 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h
+++ b/arch/x86/include/asm/fsp/fsp_types.h
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index c30dd4c218..a153dd1622 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -1,4 +1,3 @@
-
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
@@ -9,6 +8,14 @@
#ifndef _PCI_I386_H_
#define _PCI_I386_H_
+/* bus mapping constants (used for PCI core initialization) */
+#define PCI_REG_ADDR 0xcf8
+#define PCI_REG_DATA 0xcfc
+
+#define PCI_CFG_EN 0x80000000
+
+#ifndef __ASSEMBLY__
+
#define DEFINE_PCI_DEVICE_TABLE(_table) \
const struct pci_device_id _table[]
@@ -49,4 +56,6 @@ void pci_write_config8(pci_dev_t dev, unsigned where, unsigned value);
void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value);
void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value);
-#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PCI_I386_H_ */
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index c24846b3ed..c743efd60b 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -39,6 +39,9 @@ ulong board_get_usable_ram_top(ulong total_size);
void dram_init_banksize(void);
int default_print_cpuinfo(void);
+/* Set up a UART which can be used with printch(), printhex8(), etc. */
+int setup_early_uart(void);
+
void setup_pcat_compatibility(void);
void isa_unmap_rom(u32 addr);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 32d7b98fa6..c17f7f088b 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -25,6 +25,7 @@ obj-y += string.o
obj-$(CONFIG_SYS_X86_TSC_TIMER) += tsc_timer.o
obj-$(CONFIG_VIDEO_VGA) += video.o
obj-$(CONFIG_CMD_ZBOOT) += zimage.o
+obj-$(CONFIG_HAVE_FSP) += fsp/
extra-$(CONFIG_USE_PRIVATE_LIBGCC) := lib.a
diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c
index a0ef037da1..915746a4f9 100644
--- a/arch/x86/lib/cmd_hob.c
+++ b/arch/x86/lib/cmd_hob.c
@@ -7,7 +7,7 @@
#include <common.h>
#include <command.h>
#include <linux/compiler.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile
new file mode 100644
index 0000000000..5b12c12d7a
--- /dev/null
+++ b/arch/x86/lib/fsp/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2015 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += fsp_car.o
+obj-y += fsp_common.o
+obj-y += fsp_dram.o
+obj-y += fsp_support.o
diff --git a/arch/x86/cpu/queensbay/tnc_car.S b/arch/x86/lib/fsp/fsp_car.S
index 5e09568b85..5e09568b85 100644
--- a/arch/x86/cpu/queensbay/tnc_car.S
+++ b/arch/x86/lib/fsp/fsp_car.S
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
new file mode 100644
index 0000000000..f668259c0e
--- /dev/null
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/fsp/fsp_support.h>
+
+int print_cpuinfo(void)
+{
+ post_code(POST_CPU_INFO);
+ return default_print_cpuinfo();
+}
+
+void reset_cpu(ulong addr)
+{
+ /* cold reset */
+ outb(0x06, PORT_RESET);
+}
+
+
+int board_pci_post_scan(struct pci_controller *hose)
+{
+ u32 status;
+
+ /* call into FspNotify */
+ debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
+ status = fsp_notify(NULL, INIT_PHASE_PCI);
+ if (status != FSP_SUCCESS)
+ debug("fail, error code %x\n", status);
+ else
+ debug("OK\n");
+
+ return 0;
+}
+
+void board_final_cleanup(void)
+{
+ u32 status;
+
+ /* call into FspNotify */
+ debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
+ status = fsp_notify(NULL, INIT_PHASE_BOOT);
+ if (status != FSP_SUCCESS)
+ debug("fail, error code %x\n", status);
+ else
+ debug("OK\n");
+
+ return;
+}
diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/lib/fsp/fsp_dram.c
index df79a39dd8..4c0a7c82ca 100644
--- a/arch/x86/cpu/queensbay/tnc_dram.c
+++ b/arch/x86/lib/fsp/fsp_dram.c
@@ -5,7 +5,7 @@
*/
#include <common.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
#include <asm/e820.h>
#include <asm/post.h>
diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index aed3e2b300..5f96da120e 100644
--- a/arch/x86/cpu/queensbay/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -6,7 +6,7 @@
*/
#include <common.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
#include <asm/post.h>
/**
@@ -30,7 +30,7 @@ static bool compare_guid(const struct efi_guid *guid1,
return false;
}
-u32 __attribute__((optimize("O0"))) find_fsp_header(void)
+struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
{
/*
* This function may be called before the a stack is established,
@@ -84,7 +84,7 @@ u32 __attribute__((optimize("O0"))) find_fsp_header(void)
fsp = 0;
}
- return (u32)fsp;
+ return (struct fsp_header *)fsp;
}
void fsp_continue(struct shared_data *shared_data, u32 status, void *hob_list)
@@ -124,25 +124,29 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
struct fsp_init_params *params_ptr;
struct upd_region *fsp_upd;
- fsp_hdr = (struct fsp_header *)find_fsp_header();
+#ifdef CONFIG_DEBUG_UART
+ setup_early_uart();
+#endif
+
+ fsp_hdr = find_fsp_header();
if (fsp_hdr == NULL) {
/* No valid FSP info header was found */
panic("Invalid FSP header");
}
- fsp_upd = (struct upd_region *)&shared_data.fsp_upd;
+ fsp_upd = &shared_data.fsp_upd;
memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
/* Reserve a gap in stack top */
rt_buf.common.stack_top = (u32 *)stack_top - 32;
rt_buf.common.boot_mode = boot_mode;
- rt_buf.common.upd_data = (struct upd_region *)fsp_upd;
+ rt_buf.common.upd_data = fsp_upd;
/* Get VPD region start */
fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
fsp_hdr->cfg_region_off);
- /* Verifify the VPD data region is valid */
+ /* Verify the VPD data region is valid */
assert((fsp_vpd->img_rev == VPD_IMAGE_REV) &&
(fsp_vpd->sign == VPD_IMAGE_ID));
@@ -150,7 +154,7 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
sizeof(struct upd_region));
- /* Verifify the UPD data region is valid */
+ /* Verify the UPD data region is valid */
assert(fsp_upd->terminator == UPD_TERMINATOR);
/* Override any UPD setting if required */
diff --git a/arch/x86/lib/pci_type1.c b/arch/x86/lib/pci_type1.c
index 13942a33f7..a251adcacd 100644
--- a/arch/x86/lib/pci_type1.c
+++ b/arch/x86/lib/pci_type1.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <asm/io.h>
#include <pci.h>
+#include <asm/pci.h>
#define cfg_read(val, addr, op) (*val = op((int)(addr)))
#define cfg_write(val, addr, op) op((val), (int)(addr))
@@ -21,7 +22,7 @@ static int \
type1_##rw##_config_##size(struct pci_controller *hose, \
pci_dev_t dev, int offset, type val) \
{ \
- outl(dev | (offset & 0xfc) | 0x80000000, (int)hose->cfg_addr); \
+ outl(dev | (offset & 0xfc) | PCI_CFG_EN, (int)hose->cfg_addr); \
cfg_##rw(val, hose->cfg_data + (offset & mask), op); \
return 0; \
}
@@ -34,10 +35,6 @@ TYPE1_PCI_OP(write, byte, u8, outb, 3)
TYPE1_PCI_OP(write, word, u16, outw, 2)
TYPE1_PCI_OP(write, dword, u32, outl, 0)
-/* bus mapping constants (used for PCI core initialization) */
-#define PCI_REG_ADDR 0x00000cf8
-#define PCI_REG_DATA 0x00000cfc
-
void pci_setup_type1(struct pci_controller *hose)
{
pci_set_ops(hose,
diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig
index 33a31f311f..ea454721c5 100644
--- a/board/google/chromebook_link/Kconfig
+++ b/board/google/chromebook_link/Kconfig
@@ -22,8 +22,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select MARK_GRAPHICS_MEM_WRCOMB
select BOARD_ROMSIZE_KB_8192
-config MMCONF_BASE_ADDRESS
- hex
+config PCIE_ECAM_BASE
default 0xf0000000
config EARLY_POST_CROS_EC
diff --git a/board/intel/galileo/Kconfig b/board/intel/galileo/Kconfig
new file mode 100644
index 0000000000..85afbbc8c5
--- /dev/null
+++ b/board/intel/galileo/Kconfig
@@ -0,0 +1,21 @@
+if TARGET_GALILEO
+
+config SYS_BOARD
+ default "galileo"
+
+config SYS_VENDOR
+ default "intel"
+
+config SYS_SOC
+ default "quark"
+
+config SYS_CONFIG_NAME
+ default "galileo"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select X86_RESET_VECTOR
+ select INTEL_QUARK
+ select BOARD_ROMSIZE_KB_1024
+
+endif
diff --git a/board/intel/galileo/MAINTAINERS b/board/intel/galileo/MAINTAINERS
new file mode 100644
index 0000000000..dbbc82e8a1
--- /dev/null
+++ b/board/intel/galileo/MAINTAINERS
@@ -0,0 +1,6 @@
+INTEL GALILEO BOARD
+M: Bin Meng <bmeng.cn@gmail.com>
+S: Maintained
+F: board/intel/galileo/
+F: include/configs/galileo.h
+F: configs/galileo_defconfig
diff --git a/board/intel/galileo/Makefile b/board/intel/galileo/Makefile
new file mode 100644
index 0000000000..8356df198c
--- /dev/null
+++ b/board/intel/galileo/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += galileo.o start.o
diff --git a/board/intel/galileo/galileo.c b/board/intel/galileo/galileo.c
new file mode 100644
index 0000000000..f2e74687ed
--- /dev/null
+++ b/board/intel/galileo/galileo.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+ return 0;
+}
+
+void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
+{
+ return;
+}
diff --git a/board/intel/galileo/start.S b/board/intel/galileo/start.S
new file mode 100644
index 0000000000..a71db69be9
--- /dev/null
+++ b/board/intel/galileo/start.S
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+ jmp early_board_init_ret
diff --git a/board/intel/minnowmax/Kconfig b/board/intel/minnowmax/Kconfig
new file mode 100644
index 0000000000..43c50a519b
--- /dev/null
+++ b/board/intel/minnowmax/Kconfig
@@ -0,0 +1,24 @@
+if TARGET_MINNOWMAX
+
+config SYS_BOARD
+ default "minnowmax"
+
+config SYS_VENDOR
+ default "intel"
+
+config SYS_SOC
+ default "baytrail"
+
+config SYS_CONFIG_NAME
+ default "minnowmax"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select X86_RESET_VECTOR
+ select INTEL_BAYTRAIL
+ select BOARD_ROMSIZE_KB_8192
+
+config PCIE_ECAM_BASE
+ default 0xe0000000
+
+endif
diff --git a/board/intel/minnowmax/MAINTAINERS b/board/intel/minnowmax/MAINTAINERS
new file mode 100644
index 0000000000..d655761d57
--- /dev/null
+++ b/board/intel/minnowmax/MAINTAINERS
@@ -0,0 +1,6 @@
+CircuitCo Minnowboard Max
+M: Simon Glass <sjg@chromium.org>
+S: Maintained
+F: board/intel/minnowmax
+F: include/configs/minnowmax.h
+F: configs/minnowmax_defconfig
diff --git a/board/intel/minnowmax/Makefile b/board/intel/minnowmax/Makefile
new file mode 100644
index 0000000000..1a614324a2
--- /dev/null
+++ b/board/intel/minnowmax/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015, Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += minnowmax.o start.o
diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
new file mode 100644
index 0000000000..6e82b16335
--- /dev/null
+++ b/board/intel/minnowmax/minnowmax.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/ibmpc.h>
+#include <asm/pnp_def.h>
+#include <netdev.h>
+#include <smsc_lpc47m.h>
+
+#define SERIAL_DEV PNP_DEV(0x2e, 4)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+ lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
+
+ return 0;
+}
+
+void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
+{
+ return;
+}
+
+int board_eth_init(bd_t *bis)
+{
+ return pci_eth_init(bis);
+}
diff --git a/board/intel/minnowmax/start.S b/board/intel/minnowmax/start.S
new file mode 100644
index 0000000000..2c941a4a51
--- /dev/null
+++ b/board/intel/minnowmax/start.S
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+ jmp early_board_init_ret
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c
index cbc107ea50..a0a62ebdca 100644
--- a/common/cmd_scsi.c
+++ b/common/cmd_scsi.c
@@ -217,8 +217,10 @@ void scsi_init(void)
(busdevfunc >> 8) & 0x7);
}
#endif
+ bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
scsi_low_level_init(busdevfunc);
scsi_scan(1);
+ bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
}
#endif
diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig
new file mode 100644
index 0000000000..f2086514be
--- /dev/null
+++ b/configs/galileo_defconfig
@@ -0,0 +1,6 @@
+CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff10000"
+CONFIG_X86=y
+CONFIG_TARGET_GALILEO=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="galileo"
diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig
new file mode 100644
index 0000000000..7bc9085b32
--- /dev/null
+++ b/configs/minnowmax_defconfig
@@ -0,0 +1,13 @@
+CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff00000"
+CONFIG_X86=y
+CONFIG_TARGET_MINNOWMAX=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
+CONFIG_VIDEO_X86=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
+CONFIG_DEBUG_UART_NS16550=y
+CONFIG_DEBUG_UART=y
+CONFIG_MMCONF_BASE_ADDRESS=0xe0000000
+CONFIG_HAVE_INTEL_ME=y
diff --git a/doc/README.x86 b/doc/README.x86
index 7df8cc516a..fb87682e05 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -18,11 +18,11 @@ U-Boot supports running as a coreboot [1] payload on x86. So far only Link
on other x86 boards since coreboot deals with most of the low-level details.
U-Boot also supports booting directly from x86 reset vector without coreboot,
-aka raw support or bare support. Currently Link and Intel Crown Bay board
-support running U-Boot 'bare metal'.
+aka raw support or bare support. Currently Link, Intel Crown Bay, Intel
+Minnowboard Max and Intel Galileo support running U-Boot 'bare metal'.
-As for loading OS, U-Boot supports directly booting a 32-bit or 64-bit Linux
-kernel as part of a FIT image. It also supports a compressed zImage.
+As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit
+Linux kernel as part of a FIT image. It also supports a compressed zImage.
Build Instructions
------------------
@@ -47,13 +47,15 @@ Change the 'Board configuration file' and 'Board Device Tree Source (dts) file'
to point to a new board. You can also change the Cache-As-RAM (CAR) related
settings here if the default values do not fit your new board.
-Building ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
+Building a ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
little bit tricky, as generally it requires several binary blobs which are not
shipped in the U-Boot source tree. Due to this reason, the u-boot.rom build is
not turned on by default in the U-Boot source tree. Firstly, you need turn it
-on by uncommenting the following line in the main U-Boot Makefile:
+on by enabling the ROM build:
-# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+$ export BUILD_ROM=y
+
+This tells the Makefile to build u-boot.rom as a target.
Link-specific instructions:
@@ -108,6 +110,50 @@ Now you can build U-Boot and obtain u-boot.rom
$ make crownbay_defconfig
$ make all
+Intel Minnowboard Max instructions:
+
+This uses as FSP as with Crown Bay, except it is for the Atom E3800 series.
+Download this and get the .fd file (BAYTRAIL_FSP_GOLD_003_16-SEP-2014.fd at
+the time of writing). Put it in the board directory:
+board/intel/minnowmax/fsp.bin
+
+Obtain the VGA RAM (Vga.dat at the time of writing) and put it into the same
+directory: board/intel/minnowmax/vga.bin
+
+You still need two more binary blobs. These come from the sample SPI image
+provided in the FSP (SPI.bin at the time of writing).
+
+Use ifdtool in the U-Boot tools directory to extract the images from that
+file, for example:
+
+ $ ./tools/ifdtool -x BayleyBay/SPI.bin
+ $ cp flashregion_2_intel_me.bin board/intel/minnowmax/me.bin
+ $ cp flashregion_0_flashdescriptor.bin board/intel/minnowmax/descriptor.bin
+
+Now you can build U-Boot and obtain u-boot.rom
+
+$ make minnowmax_defconfig
+$ make all
+
+Intel Galileo instructions:
+
+Only one binary blob is needed for Remote Management Unit (RMU) within Intel
+Quark SoC. Not like FSP, U-Boot does not call into the binary. The binary is
+needed by the Quark SoC itself.
+
+You can get the binary blob from Quark Board Support Package from Intel website:
+
+* ./QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+
+Rename the file and put it to the board directory by:
+
+ $ cp RMU.bin board/intel/galileo/rmu.bin
+
+Now you can build U-Boot and obtain u-boot.rom
+
+$ make galileo_defconfig
+$ make all
+
Test with coreboot
------------------
For testing U-Boot as the coreboot payload, there are things that need be paid
@@ -126,11 +172,21 @@ Make sure 0x1110000 matches CONFIG_SYS_TEXT_BASE and 0x1110015 matches the
symbol address of _start (in arch/x86/cpu/start.S).
If you want to use ELF as the coreboot payload, change U-Boot configuration to
-use CONFIG_OF_EMBED.
+use CONFIG_OF_EMBED instead of CONFIG_OF_SEPARATE.
+
+To enable video you must enable these options in coreboot:
+
+ - Set framebuffer graphics resolution (1280x1024 32k-color (1:5:5))
+ - Keep VESA framebuffer
+
+At present it seems that for Minnowboard Max, coreboot does not pass through
+the video information correctly (it always says the resolution is 0x0). This
+works correctly for link though.
+
CPU Microcode
-------------
-Modern CPU usually requires a special bit stream called microcode [5] to be
+Modern CPUs usually require a special bit stream called microcode [5] to be
loaded on the processor after power up in order to function properly. U-Boot
has already integrated these as hex dumps in the source tree.
@@ -162,6 +218,69 @@ mtrr - List and set the Memory Type Range Registers (MTRR). These are used to
mode to use. U-Boot sets up some reasonable values but you can
adjust then with this command.
+Development Flow
+----------------
+These notes are for those who want to port U-Boot to a new x86 platform.
+
+Since x86 CPUs boot from SPI flash, a SPI flash emulator is a good investment.
+The Dediprog em100 can be used on Linux. The em100 tool is available here:
+
+ http://review.coreboot.org/p/em100.git
+
+On Minnowboard Max the following command line can be used:
+
+ sudo em100 -s -p LOW -d u-boot.rom -c W25Q64DW -r
+
+A suitable clip for connecting over the SPI flash chip is here:
+
+ http://www.dediprog.com/pd/programmer-accessories/EM-TC-8
+
+This allows you to override the SPI flash contents for development purposes.
+Typically you can write to the em100 in around 1200ms, considerably faster
+than programming the real flash device each time. The only important
+limitation of the em100 is that it only supports SPI bus speeds up to 20MHz.
+This means that images must be set to boot with that speed. This is an
+Intel-specific feature - e.g. tools/ifttool has an option to set the SPI
+speed in the SPI descriptor region.
+
+If your chip/board uses an Intel Firmware Support Package (FSP) it is fairly
+easy to fit it in. You can follow the Minnowboard Max implementation, for
+example. Hopefully you will just need to create new files similar to those
+in arch/x86/cpu/baytrail which provide Bay Trail support.
+
+If you are not using an FSP you have more freedom and more responsibility.
+The ivybridge support works this way, although it still uses a ROM for
+graphics and still has binary blobs containing Intel code. You should aim to
+support all important peripherals on your platform including video and storage.
+Use the device tree for configuration where possible.
+
+For the microcode you can create a suitable device tree file using the
+microcode tool:
+
+ ./tools/microcode-tool -d microcode.dat create <model>
+
+or if you only have header files and not the full Intel microcode.dat database:
+
+ ./tools/microcode-tool -H BAY_TRAIL_FSP_KIT/Microcode/M0130673322.h \
+ -H BAY_TRAIL_FSP_KIT/Microcode/M0130679901.h \
+ create all
+
+These are written to arch/x86/dts/microcode/ by default.
+
+Note that it is possible to just add the micrcode for your CPU if you know its
+model. U-Boot prints this information when it starts
+
+ CPU: x86_64, vendor Intel, device 30673h
+
+so here we can use the M0130673322 file.
+
+If you platform can display POST codes on two little 7-segment displays on
+the board, then you can use post_code() calls from C or assembler to monitor
+boot progress. This can be good for debugging.
+
+If not, you can try to get serial working as early as possible. The early
+debug serial port may be useful here. See setup_early_uart() for an example.
+
TODO List
---------
- Audio
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 4ba5878936..ed73687735 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
obj-$(CONFIG_MXC_MMC) += mxcmmc.o
obj-$(CONFIG_MXS_MMC) += mxsmmc.o
obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
+obj-$(CONFIG_X86) += pci_mmc.o
obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
obj-$(CONFIG_S3C_SDI) += s3c_sdi.o
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
new file mode 100644
index 0000000000..37171bfa71
--- /dev/null
+++ b/drivers/mmc/pci_mmc.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <sdhci.h>
+#include <asm/pci.h>
+
+int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
+ int num_ids)
+{
+ struct sdhci_host *mmc_host;
+ pci_dev_t devbusfn;
+ u32 iobase;
+ int ret;
+ int i;
+
+ for (i = 0; i < num_ids; i++) {
+ devbusfn = pci_find_devices(mmc_supported, i);
+ if (devbusfn == -1)
+ return -ENODEV;
+
+ mmc_host = malloc(sizeof(struct sdhci_host));
+ if (!mmc_host)
+ return -ENOMEM;
+
+ mmc_host->name = (char *)name;
+ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
+ mmc_host->ioaddr = (void *)iobase;
+ mmc_host->quirks = 0;
+ ret = add_sdhci(mmc_host, 0, 0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 950a2475c5..e1296cab9e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -15,6 +15,7 @@
#include <common.h>
#include <command.h>
+#include <errno.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <pci.h>
@@ -236,6 +237,48 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
return -1;
}
+pci_dev_t pci_find_class(uint find_class, int index)
+{
+ int bus;
+ int devnum;
+ pci_dev_t bdf;
+ uint32_t class;
+
+ for (bus = 0; bus <= pci_last_busno(); bus++) {
+ for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
+ pci_read_config_dword(PCI_BDF(bus, devnum, 0),
+ PCI_CLASS_REVISION, &class);
+ if (class >> 16 == 0xffff)
+ continue;
+
+ for (bdf = PCI_BDF(bus, devnum, 0);
+ bdf <= PCI_BDF(bus, devnum,
+ PCI_MAX_PCI_FUNCTIONS - 1);
+ bdf += PCI_BDF(0, 0, 1)) {
+ pci_read_config_dword(bdf, PCI_CLASS_REVISION,
+ &class);
+ class >>= 8;
+
+ if (class != find_class)
+ continue;
+ /*
+ * Decrement the index. We want to return the
+ * correct device, so index is 0 for the first
+ * matching device, 1 for the second, etc.
+ */
+ if (index) {
+ index--;
+ continue;
+ }
+ /* Return index'th controller. */
+ return bdf;
+ }
+ }
+ }
+
+ return -ENODEV;
+}
+
pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
{
struct pci_device_id ids[2] = { {}, {0, 0} };
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 5729a152e5..48c0a77fdd 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -228,11 +228,12 @@ int vbe_get_video_info(struct graphic_device *gdev)
#endif
}
-int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
+int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method)
{
struct pci_rom_header *rom, *ram;
int vesa_mode = -1;
uint16_t class;
+ bool emulate;
int ret;
/* Only execute VGA ROMs */
@@ -262,6 +263,29 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
#endif
debug("Selected vesa mode %#x\n", vesa_mode);
+
+ if (exec_method & PCI_ROM_USE_NATIVE) {
+#ifdef CONFIG_X86
+ emulate = false;
+#else
+ if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) {
+ printf("BIOS native execution is only available on x86\n");
+ return -ENOSYS;
+ }
+ emulate = true;
+#endif
+ } else {
+#ifdef CONFIG_BIOSEMU
+ emulate = true;
+#else
+ if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) {
+ printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
+ return -ENOSYS;
+ }
+ emulate = false;
+#endif
+ }
+
if (emulate) {
#ifdef CONFIG_BIOSEMU
BE_VGAInfo *info;
@@ -274,9 +298,6 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
vesa_mode, &mode_info);
if (ret)
return ret;
-#else
- printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
- return -ENOSYS;
#endif
} else {
#ifdef CONFIG_X86
@@ -284,9 +305,6 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
&mode_info);
-#else
- printf("BIOS native execution is only available on x86\n");
- return -ENOSYS;
#endif
}
debug("Final vesa mode %#x\n", mode_info.video_mode);
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index fdff158637..194e882302 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
+#include <errno.h>
#include <malloc.h>
#include <spi.h>
#include <pci.h>
@@ -21,6 +22,7 @@
struct ich_ctlr {
pci_dev_t dev; /* PCI device number */
int ich_version; /* Controller version, 7 or 9 */
+ bool use_sbase; /* Use SBASE instead of RCB */
int ichspi_lock;
int locked;
uint8_t *opmenu;
@@ -145,7 +147,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
* ICH 7 SPI controller only supports array read command
* and byte program command for SST flash
*/
- if (ctlr.ich_version == 7) {
+ if (ctlr.ich_version == 7 || ctlr.use_sbase) {
ich->slave.op_mode_rx = SPI_OPM_RX_AS;
ich->slave.op_mode_tx = SPI_OPM_TX_BP;
}
@@ -175,13 +177,15 @@ void spi_free_slave(struct spi_slave *slave)
static int get_ich_version(uint16_t device_id)
{
if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC ||
- device_id == PCI_DEVICE_ID_INTEL_ITC_LPC)
+ device_id == PCI_DEVICE_ID_INTEL_ITC_LPC ||
+ device_id == PCI_DEVICE_ID_INTEL_QRK_ILB)
return 7;
if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) ||
(device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
- device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX))
+ device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX) ||
+ device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
return 9;
return 0;
@@ -204,14 +208,14 @@ static int ich9_can_do_33mhz(pci_dev_t dev)
return speed == 1;
}
-static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
+static int ich_find_spi_controller(struct ich_ctlr *ich)
{
int last_bus = pci_last_busno();
int bus;
if (last_bus == -1) {
debug("No PCI busses?\n");
- return -1;
+ return -ENODEV;
}
for (bus = 0; bus <= last_bus; bus++) {
@@ -225,24 +229,33 @@ static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
device_id = ids >> 16;
if (vendor_id == PCI_VENDOR_ID_INTEL) {
- *devp = dev;
- *ich_versionp = get_ich_version(device_id);
- return 0;
+ ich->dev = dev;
+ ich->ich_version = get_ich_version(device_id);
+ if (device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
+ ich->use_sbase = true;
+ return ich->ich_version == 0 ? -ENODEV : 0;
}
}
debug("ICH SPI: No ICH found.\n");
- return -1;
+ return -ENODEV;
}
static int ich_init_controller(struct ich_ctlr *ctlr)
{
uint8_t *rcrb; /* Root Complex Register Block */
uint32_t rcba; /* Root Complex Base Address */
+ uint32_t sbase_addr;
+ uint8_t *sbase;
pci_read_config_dword(ctlr->dev, 0xf0, &rcba);
/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
rcrb = (uint8_t *)(rcba & 0xffffc000);
+
+ /* SBASE is similar */
+ pci_read_config_dword(ctlr->dev, 0x54, &sbase_addr);
+ sbase = (uint8_t *)(sbase_addr & 0xfffffe00);
+
if (ctlr->ich_version == 7) {
struct ich7_spi_regs *ich7_spi;
@@ -262,7 +275,10 @@ static int ich_init_controller(struct ich_ctlr *ctlr)
} else if (ctlr->ich_version == 9) {
struct ich9_spi_regs *ich9_spi;
- ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
+ if (ctlr->use_sbase)
+ ich9_spi = (struct ich9_spi_regs *)sbase;
+ else
+ ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
ctlr->ichspi_lock = ich_readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
ctlr->opmenu = ich9_spi->opmenu;
ctlr->menubytes = sizeof(ich9_spi->opmenu);
@@ -282,12 +298,13 @@ static int ich_init_controller(struct ich_ctlr *ctlr)
ctlr->ich_version);
return -1;
}
- debug("ICH SPI: Version %d detected\n", ctlr->ich_version);
/* Work out the maximum speed we can support */
ctlr->max_speed = 20000000;
if (ctlr->ich_version == 9 && ich9_can_do_33mhz(ctlr->dev))
ctlr->max_speed = 33000000;
+ debug("ICH SPI: Version %d detected at %p, speed %ld\n",
+ ctlr->ich_version, ctlr->base, ctlr->max_speed);
ich_set_bbar(ctlr, 0);
@@ -298,7 +315,7 @@ void spi_init(void)
{
uint8_t bios_cntl;
- if (ich_find_spi_controller(&ctlr.dev, &ctlr.ich_version)) {
+ if (ich_find_spi_controller(&ctlr)) {
printf("ICH SPI: Cannot find device\n");
return;
}
@@ -312,10 +329,20 @@ void spi_init(void)
* Disable the BIOS write protect so write commands are allowed. On
* v9, deassert SMM BIOS Write Protect Disable.
*/
- pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
- if (ctlr.ich_version == 9)
- bios_cntl &= ~(1 << 5);
- pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
+ if (ctlr.use_sbase) {
+ struct ich9_spi_regs *ich9_spi;
+
+ ich9_spi = (struct ich9_spi_regs *)ctlr.base;
+ bios_cntl = ich_readb(&ich9_spi->bcr);
+ bios_cntl &= ~(1 << 5); /* clear Enable InSMM_STS (EISS) */
+ bios_cntl |= 1; /* Write Protect Disable (WPD) */
+ ich_writeb(bios_cntl, &ich9_spi->bcr);
+ } else {
+ pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
+ if (ctlr.ich_version == 9)
+ bios_cntl &= ~(1 << 5);
+ pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
+ }
}
int spi_claim_bus(struct spi_slave *slave)
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index d2e4b8523b..1419b23e11 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -37,18 +37,19 @@ struct ich9_spi_regs {
uint8_t opmenu[8]; /* 0x98 */
uint32_t bbar;
uint8_t _reserved3[12];
- uint32_t fdoc;
+ uint32_t fdoc; /* 0xb0 */
uint32_t fdod;
uint8_t _reserved4[8];
- uint32_t afc;
+ uint32_t afc; /* 0xc0 */
uint32_t lvscc;
uint32_t uvscc;
uint8_t _reserved5[4];
- uint32_t fpb;
+ uint32_t fpb; /* 0xd0 */
uint8_t _reserved6[28];
- uint32_t srdl;
+ uint32_t srdl; /* 0xf0 */
uint32_t srdc;
- uint32_t srd;
+ uint32_t scs;
+ uint32_t bcr;
} __packed;
enum {
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c11b551620..66d6e9a6d2 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
+obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
# designware
obj-$(CONFIG_USB_DWC2) += dwc2.o
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 991b19998b..b9eabc5593 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -34,57 +34,6 @@ static struct pci_device_id ehci_pci_ids[] = {
{0, 0}
};
#else
-static pci_dev_t ehci_find_class(int index)
-{
- int bus;
- int devnum;
- pci_dev_t bdf;
- uint32_t class;
-
- for (bus = 0; bus <= pci_last_busno(); bus++) {
- for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
- pci_read_config_dword(PCI_BDF(bus, devnum, 0),
- PCI_CLASS_REVISION, &class);
- if (class >> 16 == 0xffff)
- continue;
-
- for (bdf = PCI_BDF(bus, devnum, 0);
- bdf <= PCI_BDF(bus, devnum,
- PCI_MAX_PCI_FUNCTIONS - 1);
- bdf += PCI_BDF(0, 0, 1)) {
- pci_read_config_dword(bdf, PCI_CLASS_REVISION,
- &class);
- class >>= 8;
- /*
- * Here be dragons! In case we have multiple
- * PCI EHCI controllers, this function will
- * be called multiple times as well. This
- * function will scan the PCI busses, always
- * starting from bus 0, device 0, function 0,
- * until it finds an USB controller. The USB
- * stack gives us an 'index' of a controller
- * that is currently being registered, which
- * is a number, starting from 0 and growing
- * in ascending order as controllers are added.
- * To avoid probing the same controller in tne
- * subsequent runs of this function, we will
- * skip 'index - 1' detected controllers and
- * report the index'th controller.
- */
- if (class != PCI_CLASS_SERIAL_USB_EHCI)
- continue;
- if (index) {
- index--;
- continue;
- }
- /* Return index'th controller. */
- return bdf;
- }
- }
- }
-
- return -ENODEV;
-}
#endif
/*
@@ -102,7 +51,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
#ifdef CONFIG_PCI_EHCI_DEVICE
pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
#else
- pdev = ehci_find_class(index);
+ pdev = pci_find_class(PCI_CLASS_SERIAL_USB_EHCI, index);
#endif
if (pdev < 0) {
printf("EHCI host controller not found\n");
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
new file mode 100644
index 0000000000..361fccebf7
--- /dev/null
+++ b/drivers/usb/host/xhci-pci.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <pci.h>
+#include <usb.h>
+
+#include "xhci.h"
+
+/*
+ * Create the appropriate control structures to manage a new XHCI host
+ * controller.
+ */
+int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr,
+ struct xhci_hcor **ret_hcor)
+{
+ struct xhci_hccr *hccr;
+ struct xhci_hcor *hcor;
+ pci_dev_t pdev;
+ uint32_t cmd;
+ int len;
+
+ pdev = pci_find_class(PCI_CLASS_SERIAL_USB_XHCI, index);
+ if (pdev < 0) {
+ printf("XHCI host controller not found\n");
+ return -1;
+ }
+
+ hccr = (struct xhci_hccr *)pci_map_bar(pdev,
+ PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+ len = HC_LENGTH(xhci_readl(&hccr->cr_capbase));
+ hcor = (struct xhci_hcor *)((uint32_t)hccr + len);
+
+ debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
+ (uint32_t)hccr, (uint32_t)hcor, len);
+
+ *ret_hccr = hccr;
+ *ret_hcor = hcor;
+
+ /* enable busmaster */
+ pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER;
+ pci_write_config_dword(pdev, PCI_COMMAND, cmd);
+
+ return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding * to the XHCI host
+ * controller
+ */
+void xhci_hcd_stop(int index)
+{
+}
diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c
index 3dacafd6bf..47f824a726 100644
--- a/drivers/video/vesa_fb.c
+++ b/drivers/video/vesa_fb.c
@@ -23,6 +23,7 @@ struct pci_device_id vesa_video_ids[] = {
{ .vendor = 0x1002, .device = 0x5159 },
{ .vendor = 0x1002, .device = 0x4752 },
{ .vendor = 0x1002, .device = 0x5452 },
+ { .vendor = 0x8086, .device = 0x0f31 },
{},
};
@@ -41,8 +42,10 @@ void *video_hw_init(void)
printf("no card detected\n");
return NULL;
}
- printf("bdf %x\n", dev);
- ret = pci_run_vga_bios(dev, NULL, true);
+ bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
+ ret = pci_run_vga_bios(dev, NULL, PCI_ROM_USE_NATIVE |
+ PCI_ROM_ALLOW_FALLBACK);
+ bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD);
if (ret) {
printf("failed to run video BIOS: %d\n", ret);
return NULL;
@@ -58,7 +61,7 @@ void *video_hw_init(void)
sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
bits_per_pixel);
printf("%s\n", gdev->modeIdent);
- debug("Framex buffer at %x\n", gdev->pciBase);
+ debug("Frame buffer at %x\n", gdev->pciBase);
return (void *)gdev;
}
diff --git a/include/bootstage.h b/include/bootstage.h
index df13ab2f63..0276cb3f60 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -86,9 +86,9 @@ enum bootstage_id {
BOOTSTAGE_ID_POST_FAIL_R, /* Post failure reported after reloc */
/*
- * This set is reported ony by x86, and the meaning is different. In
+ * This set is reported only by x86, and the meaning is different. In
* this case we are reporting completion of a particular stage.
- * This should probably change in he x86 code (which doesn't report
+ * This should probably change in the x86 code (which doesn't report
* errors in any case), but discussion this can perhaps wait until we
* have a generic board implementation.
*/
@@ -194,6 +194,7 @@ enum bootstage_id {
BOOTSTAGE_ID_MAIN_CPU_READY,
BOOTSTAGE_ID_ACCUM_LCD,
+ BOOTSTAGE_ID_ACCUM_SCSI,
/* a few spare for the user, from here */
BOOTSTAGE_ID_USER,
diff --git a/include/configs/galileo.h b/include/configs/galileo.h
new file mode 100644
index 0000000000..d745f4eb89
--- /dev/null
+++ b/include/configs/galileo.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_MONITOR_LEN (1 << 20)
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_NR_DRAM_BANKS 1
+
+#define CONFIG_X86_SERIAL
+
+/* ns16550 UART is memory-mapped in Quark SoC */
+#undef CONFIG_SYS_NS16550_PORT_MAPPED
+
+#define CONFIG_PCI_MEM_BUS 0x90000000
+#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE 0x20000000
+
+#define CONFIG_PCI_PREF_BUS 0xb0000000
+#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS
+#define CONFIG_PCI_PREF_SIZE 0x20000000
+
+#define CONFIG_PCI_IO_BUS 0x2000
+#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE 0xe000
+
+#define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_PCI_PNP
+
+#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial\0" \
+ "stdout=serial\0" \
+ "stderr=serial\0"
+
+/* SATA is not supported in Quark SoC */
+#undef CONFIG_SCSI_AHCI
+#undef CONFIG_CMD_SCSI
+
+/* Video is not supported in Quark SoC */
+#undef CONFIG_VIDEO
+#undef CONFIG_CFB_CONSOLE
+
+/* SD/MMC support */
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC_SDMA
+#define CONFIG_CMD_MMC
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
new file mode 100644
index 0000000000..823e051eb1
--- /dev/null
+++ b/include/configs/minnowmax.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_MONITOR_LEN (1 << 20)
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_NR_DRAM_BANKS 1
+
+#define CONFIG_X86_SERIAL
+#define CONFIG_SMSC_LPC47M
+
+#define CONFIG_PCI_MEM_BUS 0xd0000000
+#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE 0x10000000
+
+#define CONFIG_PCI_PREF_BUS 0xc0000000
+#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS
+#define CONFIG_PCI_PREF_SIZE 0x10000000
+
+#define CONFIG_PCI_IO_BUS 0x2000
+#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE 0xe000
+
+#define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_PCI_PNP
+#define CONFIG_RTL8169
+#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \
+ "stdout=vga,serial\0" \
+ "stderr=vga,serial\0"
+
+#define CONFIG_SCSI_DEV_LIST \
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}
+#define CONFIG_SPI_FLASH_SST
+
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC_SDMA
+#define CONFIG_CMD_MMC
+
+#undef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+
+#define CONFIG_X86_OPTION_ROM_FILE vga.bin
+#define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000
+
+#ifndef CONFIG_SYS_COREBOOT
+#define CONFIG_VIDEO_VESA
+#endif
+#define VIDEO_IO_OFFSET 0
+#define CONFIG_X86EMU_RAW_IO
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+
+#define CONFIG_FIT_SIGNATURE
+#define CONFIG_RSA
+
+/* Avoid a warning in the Realtek Ethernet driver */
+#define CONFIG_SYS_CACHELINE_SIZE 16
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index ecedfc3ab1..062e6c2219 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -39,7 +39,6 @@
/* SATA AHCI storage */
#define CONFIG_SCSI_AHCI
-#define CONFIG_SATA_INTEL
#ifdef CONFIG_SCSI_AHCI
#define CONFIG_LIBATA
#define CONFIG_SYS_64BIT_LBA
@@ -245,6 +244,9 @@
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME
+#define CONFIG_BOOTSTAGE
+#define CONFIG_CMD_BOOTSTAGE
+
#define CONFIG_CMD_USB
#define CONFIG_EXTRA_ENV_SETTINGS \
diff --git a/include/dt-bindings/mrc/quark.h b/include/dt-bindings/mrc/quark.h
new file mode 100644
index 0000000000..e3ca8a25a3
--- /dev/null
+++ b/include/dt-bindings/mrc/quark.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Intel Quark MRC bindings include several properties
+ * as part of an Intel Quark MRC node. In most cases,
+ * the value of these properties uses the standard values
+ * defined in this header.
+ */
+
+#ifndef _DT_BINDINGS_QRK_MRC_H_
+#define _DT_BINDINGS_QRK_MRC_H_
+
+/* MRC platform data flags */
+#define MRC_FLAG_ECC_EN 0x00000001
+#define MRC_FLAG_SCRAMBLE_EN 0x00000002
+#define MRC_FLAG_MEMTEST_EN 0x00000004
+/* 0b DDR "fly-by" topology else 1b DDR "tree" topology */
+#define MRC_FLAG_TOP_TREE_EN 0x00000008
+/* If set ODR signal is asserted to DRAM devices on writes */
+#define MRC_FLAG_WR_ODT_EN 0x00000010
+
+/* DRAM width */
+#define DRAM_WIDTH_X8 0
+#define DRAM_WIDTH_X16 1
+#define DRAM_WIDTH_X32 2
+
+/* DRAM speed */
+#define DRAM_FREQ_800 0
+#define DRAM_FREQ_1066 1
+
+/* DRAM type */
+#define DRAM_TYPE_DDR3 0
+#define DRAM_TYPE_DDR3L 1
+
+/* DRAM rank mask */
+#define DRAM_RANK(n) (1 << (n))
+
+/* DRAM channel mask */
+#define DRAM_CHANNEL(n) (1 << (n))
+
+/* DRAM channel width */
+#define DRAM_CHANNEL_WIDTH_X8 0
+#define DRAM_CHANNEL_WIDTH_X16 1
+#define DRAM_CHANNEL_WIDTH_X32 2
+
+/* DRAM address mode */
+#define DRAM_ADDR_MODE0 0
+#define DRAM_ADDR_MODE1 1
+#define DRAM_ADDR_MODE2 2
+
+/* DRAM refresh rate */
+#define DRAM_REFRESH_RATE_195US 1
+#define DRAM_REFRESH_RATE_39US 2
+#define DRAM_REFRESH_RATE_785US 3
+
+/* DRAM SR temprature range */
+#define DRAM_SRT_RANGE_NORMAL 0
+#define DRAM_SRT_RANGE_EXTENDED 1
+
+/* DRAM ron value */
+#define DRAM_RON_34OHM 0
+#define DRAM_RON_40OHM 1
+
+/* DRAM rtt nom value */
+#define DRAM_RTT_NOM_40OHM 0
+#define DRAM_RTT_NOM_60OHM 1
+#define DRAM_RTT_NOM_120OHM 2
+
+/* DRAM rd odt value */
+#define DRAM_RD_ODT_OFF 0
+#define DRAM_RD_ODT_60OHM 1
+#define DRAM_RD_ODT_120OHM 2
+#define DRAM_RD_ODT_180OHM 3
+
+/* DRAM density */
+#define DRAM_DENSITY_512M 0
+#define DRAM_DENSITY_1G 1
+#define DRAM_DENSITY_2G 2
+#define DRAM_DENSITY_4G 3
+
+#endif /* _DT_BINDINGS_QRK_MRC_H_ */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 231eed7892..1bc70dba21 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -167,6 +167,7 @@ enum fdt_compat_id {
COMPAT_INTEL_GMA, /* Intel Graphics Media Accelerator */
COMPAT_AMS_AS3722, /* AMS AS3722 PMIC */
COMPAT_INTEL_ICH_SPI, /* Intel ICH7/9 SPI controller */
+ COMPAT_INTEL_QRK_MRC, /* Intel Quark MRC */
COMPAT_COUNT,
};
diff --git a/include/mmc.h b/include/mmc.h
index 09101e2c87..56d97bbdcf 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -438,6 +438,20 @@ int board_mmc_init(bd_t *bis);
int cpu_mmc_init(bd_t *bis);
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
+struct pci_device_id;
+
+/**
+ * pci_mmc_init() - set up PCI MMC devices
+ *
+ * This finds all the matching PCI IDs and sets them up as MMC devices.
+ *
+ * @name: Name to use for devices
+ * @mmc_supported: PCI IDs to search for
+ * @num_ids: Number of elements in @mmc_supported
+ */
+int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
+ int num_ids);
+
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
diff --git a/include/pci.h b/include/pci.h
index 4fbb8f6729..004a048d2f 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -644,8 +644,7 @@ extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int index);
extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index);
-extern pci_dev_t pci_find_class(int wanted_class, int wanted_sub_code,
- int wanted_prog_if, int index);
+pci_dev_t pci_find_class(unsigned int find_class, int index);
extern int pci_hose_config_device(struct pci_controller *hose,
pci_dev_t dev,
diff --git a/include/pci_ids.h b/include/pci_ids.h
index 26f4748685..dc2ca218a6 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -1346,6 +1346,7 @@
#define PCI_VENDOR_ID_REALTEK 0x10ec
#define PCI_DEVICE_ID_REALTEK_8139 0x8139
+#define PCI_DEVICE_ID_REALTEK_8168 0x8168
#define PCI_VENDOR_ID_XILINX 0x10ee
#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0
@@ -2591,9 +2592,17 @@
#define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823
#define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824
#define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F
+#define PCI_DEVICE_ID_INTEL_QRK_SDIO 0x08A7
+#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936
+#define PCI_DEVICE_ID_INTEL_QRK_EMAC 0x0937
+#define PCI_DEVICE_ID_INTEL_QRK_ILB 0x095E
#define PCI_DEVICE_ID_INTEL_I960 0x0960
#define PCI_DEVICE_ID_INTEL_I960RM 0x0962
#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO 0x0f15
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD 0x0f16
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC 0x0f1c
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA 0x0f23
#define PCI_DEVICE_ID_INTEL_82541ER 0x1078
#define PCI_DEVICE_ID_INTEL_82541GI_LF 0x107c
#define PCI_DEVICE_ID_INTEL_82542 0x1000
diff --git a/include/pci_rom.h b/include/pci_rom.h
index 4ba36eb1b7..2f1665d17a 100644
--- a/include/pci_rom.h
+++ b/include/pci_rom.h
@@ -33,14 +33,25 @@ struct pci_rom_data {
uint16_t reserved_2;
};
+/*
+ * Determines which execution method is used and whether we allow falling back
+ * to the other if the requested method is not available.
+ */
+enum pci_rom_emul {
+ PCI_ROM_EMULATE = 0 << 0,
+ PCI_ROM_USE_NATIVE = 1 << 0,
+ PCI_ROM_ALLOW_FALLBACK = 1 << 1,
+};
+
/**
* pci_run_vga_bios() - Run the VGA BIOS in an x86 PC
*
* @dev: Video device containing the BIOS
* @int15_handler: Function to call to handle int 0x15
- * @emulate: true to use the x86 emulator, false to run native
+ * @exec_method: flags from enum pci_rom_emul
*/
-int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate);
+int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void),
+ int exec_method);
/**
* board_map_oprom_vendev() - map several PCI IDs to the one the ROM expects
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 5bf8f29b13..dd58bbb482 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(INTEL_GMA, "intel,gma"),
COMPAT(AMS_AS3722, "ams,as3722"),
COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
+ COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
};
const char *fdtdec_get_compatible(enum fdt_compat_id id)
diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py
index 003716d573..71c2e91566 100755
--- a/tools/microcode-tool.py
+++ b/tools/microcode-tool.py
@@ -76,6 +76,35 @@ def ParseFile(fname):
microcodes[name] = Microcode(name, data)
return date, license_text, microcodes
+def ParseHeaderFiles(fname_list):
+ """Parse a list of header files and return the component parts
+
+ Args:
+ fname_list: List of files to parse
+ Returns:
+ date: String containing date from the file's header
+ license_text: List of text lines for the license file
+ microcodes: List of Microcode objects from the file
+ """
+ microcodes = {}
+ license_text = []
+ date = ''
+ name = None
+ for fname in fname_list:
+ name = os.path.basename(fname).lower()
+ name = os.path.splitext(name)[0]
+ data = []
+ with open(fname) as fd:
+ for line in fd:
+ line = line.rstrip()
+
+ # Omit anything after the last comma
+ words = line.split(',')[:-1]
+ data += [word + ',' for word in words]
+ microcodes[name] = Microcode(name, data)
+ return date, license_text, microcodes
+
+
def List(date, microcodes, model):
"""List the available microcode chunks
@@ -129,13 +158,13 @@ def FindMicrocode(microcodes, model):
break
return found, tried
-def CreateFile(date, license_text, mcode, outfile):
+def CreateFile(date, license_text, mcodes, outfile):
"""Create a microcode file in U-Boot's .dtsi format
Args:
date: String containing date of original microcode file
license: List of text lines for the license file
- mcode: Microcode object to write
+ mcodes: Microcode objects to write (normally only 1)
outfile: Filename to write to ('-' for stdout)
"""
out = '''/*%s
@@ -159,15 +188,22 @@ intel,processor-flags = <%#x>;
data = <%s
\t>;'''
words = ''
- for i in range(len(mcode.words)):
- if not (i & 3):
- words += '\n'
- val = mcode.words[i]
- # Change each word so it will be little-endian in the FDT
- # This data is needed before RAM is available on some platforms so we
- # cannot do an endianness swap on boot.
- val = struct.unpack("<I", struct.pack(">I", val))[0]
- words += '\t%#010x' % val
+ add_comments = len(mcodes) > 1
+ for mcode in mcodes:
+ if add_comments:
+ words += '\n/* %s */' % mcode.name
+ for i in range(len(mcode.words)):
+ if not (i & 3):
+ words += '\n'
+ val = mcode.words[i]
+ # Change each word so it will be little-endian in the FDT
+ # This data is needed before RAM is available on some platforms so
+ # we cannot do an endianness swap on boot.
+ val = struct.unpack("<I", struct.pack(">I", val))[0]
+ words += '\t%#010x' % val
+
+ # Use the first microcode for the headers
+ mcode = mcodes[0]
# Take care to avoid adding a space before a tab
text = ''
@@ -187,8 +223,8 @@ data = <%s
print >> sys.stderr, "Creating directory '%s'" % MICROCODE_DIR
os.makedirs(MICROCODE_DIR)
outfile = os.path.join(MICROCODE_DIR, mcode.name + '.dtsi')
- print >> sys.stderr, "Writing microcode for '%s' to '%s'" % (
- mcode.name, outfile)
+ print >> sys.stderr, "Writing microcode for '%s' to '%s'" % (
+ ', '.join([mcode.name for mcode in mcodes]), outfile)
with open(outfile, 'w') as fd:
print >> fd, out % tuple(args)
@@ -198,8 +234,12 @@ def MicrocodeTool():
parser = OptionParser()
parser.add_option('-d', '--mcfile', type='string', action='store',
help='Name of microcode.dat file')
+ parser.add_option('-H', '--headerfile', type='string', action='append',
+ help='Name of .h file containing microcode')
parser.add_option('-m', '--model', type='string', action='store',
- help='Model name to extract')
+ help="Model name to extract ('all' for all)")
+ parser.add_option('-M', '--multiple', type='string', action='store',
+ help="Allow output of multiple models")
parser.add_option('-o', '--outfile', type='string', action='store',
help='Filename to use for output (- for stdout), default is'
' %s/<name>.dtsi' % MICROCODE_DIR)
@@ -224,9 +264,14 @@ def MicrocodeTool():
if cmd not in commands:
parser.error("Unknown command '%s'" % cmd)
- if not options.mcfile:
- parser.error('You must specify a microcode file')
- date, license_text, microcodes = ParseFile(options.mcfile)
+ if (not not options.mcfile) != (not not options.mcfile):
+ parser.error("You must specify either header files or a microcode file, not both")
+ if options.headerfile:
+ date, license_text, microcodes = ParseHeaderFiles(options.headerfile)
+ elif options.mcfile:
+ date, license_text, microcodes = ParseFile(options.mcfile)
+ else:
+ parser.error('You must specify a microcode file (or header files)')
if cmd == 'list':
List(date, microcodes, options.model)
@@ -236,16 +281,21 @@ def MicrocodeTool():
if not options.model:
parser.error('You must specify a model to create')
model = options.model.lower()
- mcode_list, tried = FindMicrocode(microcodes, model)
+ if options.model == 'all':
+ options.multiple = True
+ mcode_list = microcodes.values()
+ tried = []
+ else:
+ mcode_list, tried = FindMicrocode(microcodes, model)
if not mcode_list:
parser.error("Unknown model '%s' (%s) - try 'list' to list" %
(model, ', '.join(tried)))
- if len(mcode_list) > 1:
+ if not options.multiple and len(mcode_list) > 1:
parser.error("Ambiguous model '%s' (%s) matched %s - try 'list' "
"to list or specify a particular file" %
(model, ', '.join(tried),
', '.join([m.name for m in mcode_list])))
- CreateFile(date, license_text, mcode_list[0], options.outfile)
+ CreateFile(date, license_text, mcode_list, options.outfile)
else:
parser.error("Unknown command '%s'" % cmd)
OpenPOWER on IntegriCloud