Merge branch 'master' of git://git.denx.de/u-boot-x86
authorTom Rini <trini@ti.com>
Tue, 10 Feb 2015 15:42:56 +0000 (10:42 -0500)
committerTom Rini <trini@ti.com>
Tue, 10 Feb 2015 15:42:56 +0000 (10:42 -0500)
102 files changed:
Makefile
arch/x86/Kconfig
arch/x86/cpu/Makefile
arch/x86/cpu/baytrail/Kconfig [new file with mode: 0644]
arch/x86/cpu/baytrail/Makefile [new file with mode: 0644]
arch/x86/cpu/baytrail/early_uart.c [new file with mode: 0644]
arch/x86/cpu/baytrail/fsp_configs.c [new file with mode: 0644]
arch/x86/cpu/baytrail/pci.c [new file with mode: 0644]
arch/x86/cpu/baytrail/valleyview.c [new file with mode: 0644]
arch/x86/cpu/ivybridge/gma.c
arch/x86/cpu/ivybridge/sdram.c
arch/x86/cpu/quark/Kconfig [new file with mode: 0644]
arch/x86/cpu/quark/Makefile [new file with mode: 0644]
arch/x86/cpu/quark/car.S [new file with mode: 0644]
arch/x86/cpu/quark/dram.c [new file with mode: 0644]
arch/x86/cpu/quark/hte.c [new file with mode: 0644]
arch/x86/cpu/quark/hte.h [new file with mode: 0644]
arch/x86/cpu/quark/mrc.c [new file with mode: 0644]
arch/x86/cpu/quark/mrc_util.c [new file with mode: 0644]
arch/x86/cpu/quark/mrc_util.h [new file with mode: 0644]
arch/x86/cpu/quark/msg_port.c [new file with mode: 0644]
arch/x86/cpu/quark/pci.c [new file with mode: 0644]
arch/x86/cpu/quark/quark.c [new file with mode: 0644]
arch/x86/cpu/quark/smc.c [new file with mode: 0644]
arch/x86/cpu/quark/smc.h [new file with mode: 0644]
arch/x86/cpu/queensbay/Kconfig
arch/x86/cpu/queensbay/Makefile
arch/x86/cpu/queensbay/fsp_configs.c
arch/x86/cpu/queensbay/tnc.c
arch/x86/cpu/queensbay/tnc_pci.c
arch/x86/cpu/queensbay/topcliff.c
arch/x86/dts/Makefile
arch/x86/dts/galileo.dts [new file with mode: 0644]
arch/x86/dts/microcode/m0130673322.dtsi [new file with mode: 0644]
arch/x86/dts/minnowmax.dts [new file with mode: 0644]
arch/x86/dts/serial.dtsi
arch/x86/include/asm/arch-baytrail/fsp/azalia.h [new file with mode: 0644]
arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h [new file with mode: 0644]
arch/x86/include/asm/arch-baytrail/gpio.h [new file with mode: 0644]
arch/x86/include/asm/arch-ivybridge/sandybridge.h
arch/x86/include/asm/arch-quark/device.h [new file with mode: 0644]
arch/x86/include/asm/arch-quark/gpio.h [new file with mode: 0644]
arch/x86/include/asm/arch-quark/mrc.h [new file with mode: 0644]
arch/x86/include/asm/arch-quark/msg_port.h [new file with mode: 0644]
arch/x86/include/asm/arch-quark/quark.h [new file with mode: 0644]
arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
arch/x86/include/asm/fsp/fsp_api.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h with 88% similarity]
arch/x86/include/asm/fsp/fsp_bootmode.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h with 100% similarity]
arch/x86/include/asm/fsp/fsp_ffs.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h with 100% similarity]
arch/x86/include/asm/fsp/fsp_fv.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h with 100% similarity]
arch/x86/include/asm/fsp/fsp_hob.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h with 100% similarity]
arch/x86/include/asm/fsp/fsp_infoheader.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h with 100% similarity]
arch/x86/include/asm/fsp/fsp_platform.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h with 100% similarity]
arch/x86/include/asm/fsp/fsp_support.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h with 98% similarity]
arch/x86/include/asm/fsp/fsp_types.h [moved from arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h with 100% similarity]
arch/x86/include/asm/pci.h
arch/x86/include/asm/u-boot-x86.h
arch/x86/lib/Makefile
arch/x86/lib/cmd_hob.c
arch/x86/lib/fsp/Makefile [new file with mode: 0644]
arch/x86/lib/fsp/fsp_car.S [moved from arch/x86/cpu/queensbay/tnc_car.S with 100% similarity]
arch/x86/lib/fsp/fsp_common.c [new file with mode: 0644]
arch/x86/lib/fsp/fsp_dram.c [moved from arch/x86/cpu/queensbay/tnc_dram.c with 98% similarity]
arch/x86/lib/fsp/fsp_support.c [moved from arch/x86/cpu/queensbay/fsp_support.c with 96% similarity]
arch/x86/lib/pci_type1.c
board/google/chromebook_link/Kconfig
board/intel/galileo/Kconfig [new file with mode: 0644]
board/intel/galileo/MAINTAINERS [new file with mode: 0644]
board/intel/galileo/Makefile [new file with mode: 0644]
board/intel/galileo/galileo.c [new file with mode: 0644]
board/intel/galileo/start.S [new file with mode: 0644]
board/intel/minnowmax/Kconfig [new file with mode: 0644]
board/intel/minnowmax/MAINTAINERS [new file with mode: 0644]
board/intel/minnowmax/Makefile [new file with mode: 0644]
board/intel/minnowmax/minnowmax.c [new file with mode: 0644]
board/intel/minnowmax/start.S [new file with mode: 0644]
common/cmd_scsi.c
configs/galileo_defconfig [new file with mode: 0644]
configs/minnowmax_defconfig [new file with mode: 0644]
doc/README.x86
drivers/mmc/Makefile
drivers/mmc/pci_mmc.c [new file with mode: 0644]
drivers/pci/pci.c
drivers/pci/pci_rom.c
drivers/spi/ich.c
drivers/spi/ich.h
drivers/usb/host/Makefile
drivers/usb/host/ehci-pci.c
drivers/usb/host/xhci-pci.c [new file with mode: 0644]
drivers/video/vesa_fb.c
include/bootstage.h
include/configs/galileo.h [new file with mode: 0644]
include/configs/minnowmax.h [new file with mode: 0644]
include/configs/x86-common.h
include/dt-bindings/mrc/quark.h [new file with mode: 0644]
include/fdtdec.h
include/mmc.h
include/pci.h
include/pci_ids.h
include/pci_rom.h
lib/fdtdec.c
tools/microcode-tool.py

index 76bae8b..6da4215 100644 (file)
--- 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),)
index 90e828a..fef11f3 100644 (file)
@@ -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
index 62e43c0..6ded0a7 100644 (file)
@@ -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 (file)
index 0000000..e86cc01
--- /dev/null
@@ -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 (file)
index 0000000..8914e8b
--- /dev/null
@@ -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 (file)
index 0000000..4199210
--- /dev/null
@@ -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 (file)
index 0000000..86b6926
--- /dev/null
@@ -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 (file)
index 0000000..6c291f9
--- /dev/null
@@ -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 (file)
index 0000000..a3e837d
--- /dev/null
@@ -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;
+}
index 6cf9654..821ea25 100644 (file)
@@ -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 */
index 4963448..766b385 100644 (file)
@@ -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 (file)
index 0000000..bc961ef
--- /dev/null
@@ -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 (file)
index 0000000..e87b424
--- /dev/null
@@ -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 (file)
index 0000000..3432ffa
--- /dev/null
@@ -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 (file)
index 0000000..9cac846
--- /dev/null
@@ -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 (file)
index 0000000..372815d
--- /dev/null
@@ -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 (file)
index 0000000..6577796
--- /dev/null
@@ -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 (file)
index 0000000..7eb34c5
--- /dev/null
@@ -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 (file)
index 0000000..3a79ae5
--- /dev/null
@@ -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 (file)
index 0000000..f0ddbce
--- /dev/null
@@ -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 (file)
index 0000000..31713e3
--- /dev/null
@@ -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 (file)
index 0000000..354e15a
--- /dev/null
@@ -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 (file)
index 0000000..dccf7ac
--- /dev/null
@@ -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 (file)
index 0000000..e34bec4
--- /dev/null
@@ -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 (file)
index 0000000..46017a1
--- /dev/null
@@ -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_ */
index f6b5201..397e599 100644 (file)
@@ -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
index 2c2ec01..d8761fd 100644 (file)
@@ -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
index af28e45..78bc966 100644 (file)
@@ -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)
 {
index 8637cdc..30ab725 100644 (file)
@@ -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;
-}
index 39bff49..6c291f9 100644 (file)
@@ -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;
-}
index b01422a..9faf1b9 100644 (file)
@@ -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));
 }
index 97ed884..7a66133 100644 (file)
@@ -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 (file)
index 0000000..66af64a
--- /dev/null
@@ -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 (file)
index 0000000..90bf2fb
--- /dev/null
@@ -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 (file)
index 0000000..8f34369
--- /dev/null
@@ -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"
+               };
+       };
+
+};
index 9b097f4..6865eed 100644 (file)
@@ -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 (file)
index 0000000..d96a20f
--- /dev/null
@@ -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 (file)
index 0000000..82862f6
--- /dev/null
@@ -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 (file)
index 0000000..ab4e059
--- /dev/null
@@ -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_ */
index cf7457f..c960525 100644 (file)
@@ -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 (file)
index 0000000..4af3ded
--- /dev/null
@@ -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 (file)
index 0000000..ca8cba4
--- /dev/null
@@ -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 (file)
index 0000000..150fbea
--- /dev/null
@@ -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 (file)
index 0000000..2e78a66
--- /dev/null
@@ -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 (file)
index 0000000..ceb583e
--- /dev/null
@@ -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_ */
index bce58b1..3c57558 100644 (file)
@@ -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 */
similarity index 88%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h
rename to arch/x86/include/asm/fsp/fsp_api.h
index a9d7156..2d34d13 100644 (file)
@@ -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
@@ -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.
index c30dd4c..a153dd1 100644 (file)
@@ -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_ */
index c24846b..c743efd 100644 (file)
@@ -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);
index 32d7b98..c17f7f0 100644 (file)
@@ -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
 
index a0ef037..915746a 100644 (file)
@@ -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 (file)
index 0000000..5b12c12
--- /dev/null
@@ -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/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
new file mode 100644 (file)
index 0000000..f668259
--- /dev/null
@@ -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;
+}
similarity index 98%
rename from arch/x86/cpu/queensbay/tnc_dram.c
rename to arch/x86/lib/fsp/fsp_dram.c
index df79a39..4c0a7c8 100644 (file)
@@ -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>
 
similarity index 96%
rename from arch/x86/cpu/queensbay/fsp_support.c
rename to arch/x86/lib/fsp/fsp_support.c
index aed3e2b..5f96da1 100644 (file)
@@ -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 */
index 13942a3..a251adc 100644 (file)
@@ -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,
index 33a31f3..ea45472 100644 (file)
@@ -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 (file)
index 0000000..85afbbc
--- /dev/null
@@ -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 (file)
index 0000000..dbbc82e
--- /dev/null
@@ -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 (file)
index 0000000..8356df1
--- /dev/null
@@ -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 (file)
index 0000000..f2e7468
--- /dev/null
@@ -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 (file)
index 0000000..a71db69
--- /dev/null
@@ -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 (file)
index 0000000..43c50a5
--- /dev/null
@@ -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 (file)
index 0000000..d655761
--- /dev/null
@@ -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 (file)
index 0000000..1a61432
--- /dev/null
@@ -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 (file)
index 0000000..6e82b16
--- /dev/null
@@ -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 (file)
index 0000000..2c941a4
--- /dev/null
@@ -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
index cbc107e..a0a62eb 100644 (file)
@@ -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 (file)
index 0000000..f208651
--- /dev/null
@@ -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 (file)
index 0000000..7bc9085
--- /dev/null
@@ -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
index 7df8cc5..fb87682 100644 (file)
@@ -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 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
index 4ba5878..ed73687 100644 (file)
@@ -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 (file)
index 0000000..37171bf
--- /dev/null
@@ -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;
+}
index 950a247..e1296ca 100644 (file)
@@ -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} };
index 5729a15..48c0a77 100644 (file)
@@ -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);
index fdff158..194e882 100644 (file)
@@ -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)
index d2e4b85..1419b23 100644 (file)
@@ -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 {
index c11b551..66d6e9a 100644 (file)
@@ -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
index 991b199..b9eabc5 100644 (file)
@@ -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 (file)
index 0000000..361fcce
--- /dev/null
@@ -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)
+{
+}
index 3dacafd..47f824a 100644 (file)
@@ -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;
 }
index df13ab2..0276cb3 100644 (file)
@@ -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 (file)
index 0000000..d745f4e
--- /dev/null
@@ -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 (file)
index 0000000..823e051
--- /dev/null
@@ -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 */
index ecedfc3..062e6c2 100644 (file)
@@ -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
 #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 (file)
index 0000000..e3ca8a2
--- /dev/null
@@ -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_ */
index 231eed7..1bc70db 100644 (file)
@@ -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,
 };
index 09101e2..56d97bb 100644 (file)
@@ -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
index 4fbb8f6..004a048 100644 (file)
@@ -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,
index 26f4748..dc2ca21 100644 (file)
 
 #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
 #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
index 4ba36eb..2f1665d 100644 (file)
@@ -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
index 5bf8f29..dd58bbb 100644 (file)
@@ -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)
index 003716d..71c2e91 100755 (executable)
@@ -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)