[coreboot] Patch set updated for coreboot: c372138 NOTFORMERGE: VX900 early init, and EPIA M850 board

Alexandru Gagniuc (mr.nuke.me@gmail.com) gerrit at coreboot.org
Wed Aug 15 13:49:50 CEST 2012


Alexandru Gagniuc (mr.nuke.me at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1228

-gerrit

commit c372138245d18ad60bf7b639cff4c404be5ccb0e
Author: Alexandru Gagniuc <mr.nuke.me at gmail.com>
Date:   Wed Jul 25 13:16:39 2012 -0500

    NOTFORMERGE: VX900 early init, and EPIA M850 board
    
    Early initialization for VIA VX900:
    
    MMCONF:
    Works from very early ramstage. I am curently keeping MMCONF disabled
    during development, because I want to timestamp romstage, and compare
    the with and without MMCONF results.
    
    SMBUS is functional.
    
    RAMINIT:
    Raminit works with 1 rank, but untested with several ranks.
    DRAM calibration when more than one DIMM is present is not fully
    implemented. Correct MRS command mapping not implemented for DIMMS
    which swap address pins.
    
    The delay calibration strategy is to put some predefined delays for
    the DQ input delays, and run hardware calibration on the other
    three delays (DQS input, DQ/DQS output).
    For the future, we could change this strategy to one that uses the
    hardware calibration of DQ input. Unfortunately, according to my
    testing, the DQ input delay calibration does not work reliably.
    
    Memtest runs through the serial console, and does not whine about
    any memory errors (longest test was about 6 hours).
    
    RAMINIT TODO: Check burst timing and burst settings
    
    VX900 in ramstage:
    
    LPC:
    Added LPC driver struct in VX800 code. The LPCs seem to be similar
    enough that the VX800 LPC code works on the VX900 (not fully tested)
    
    VGA still displays garbage.
    The VGA driver for VX800 could work with the VX900, provided UMA memory
    is initialized during romstage. I have decided to initialize the VGA in
    ramstage for two reasons: 1. bugs in the initializing of the VGA can
    make the memory checks fail, and 2. ramstage is compressed, so we save
    a bit of ROM space. The VX800 VGA code can thus not be used for the
    VX900.
    
    SATA:
    SeaBIOS is (ocasionally) able to detect the attached SATA devices, but
    actually booting is a whole different story.
    
    VIA EPIA M850 board:
    
    Minimum infrastructure to compile a coreboot image for this board is
    added; most PCI devices are switched off in devicetree.cb.
    
    Unhandled exceptions pop up more often than not. Appear to be memory
    errors. Suspect errors related to A20.
    Payload loads. SeaBIOS detects disks (sometimes), and jumps to bootsector,
    but grub2 defecates its pantaloons very early on.
    
    Change-Id: I7624944dbc05fbf3019897a116954d71dfda0031
    Signed-off-by: Alexandru Gagniuc <mr.nuke.me at gmail.com>
---
 .gitignore                                |    7 +
 src/arch/x86/include/arch/romcc_io.h      |   28 +
 src/cpu/via/nano/nano_ucode_blob.c        |  900 +++++++++++++++++++++++++
 src/devices/dram/dram.h                   |  154 +++++
 src/devices/dram/dram_util.c              |  297 +++++++++
 src/devices/smbus/early_smbus.c           |  141 ++++
 src/devices/smbus/smbus.h                 |   99 +++
 src/include/device/pci_ids.h              |   23 +
 src/include/lib.h                         |    1 +
 src/lib/ramtest.c                         |   35 +
 src/mainboard/via/Kconfig                 |    3 +
 src/mainboard/via/epia-m850/Kconfig       |   47 ++
 src/mainboard/via/epia-m850/Makefile.inc  |   21 +
 src/mainboard/via/epia-m850/devicetree.cb |   90 +++
 src/mainboard/via/epia-m850/mainboard.c   |   24 +
 src/mainboard/via/epia-m850/romstage.c    |  122 ++++
 src/northbridge/via/Kconfig               |    1 +
 src/northbridge/via/Makefile.inc          |    1 +
 src/northbridge/via/vx800/lpc.c           |    6 +
 src/northbridge/via/vx800/vga.c           |   48 +-
 src/northbridge/via/vx900/Kconfig         |   39 ++
 src/northbridge/via/vx900/Makefile.inc    |   43 ++
 src/northbridge/via/vx900/chip.h          |   23 +
 src/northbridge/via/vx900/chrome9hd.c     |  385 +++++++++++
 src/northbridge/via/vx900/early_smbus.c   |  191 ++++++
 src/northbridge/via/vx900/early_uma_ram.c |  135 ++++
 src/northbridge/via/vx900/early_vx900.c   |  167 +++++
 src/northbridge/via/vx900/early_vx900.h   |   78 +++
 src/northbridge/via/vx900/forgotten.c     |   32 +
 src/northbridge/via/vx900/forgotten.h     |   78 +++
 src/northbridge/via/vx900/lpc.c           |  145 ++++
 src/northbridge/via/vx900/northbridge.c   |  159 +++++
 src/northbridge/via/vx900/raminit.h       |   72 ++
 src/northbridge/via/vx900/raminit_ddr3.c  | 1036 +++++++++++++++++++++++++++++
 src/northbridge/via/vx900/romstrap.inc    |   60 ++
 src/northbridge/via/vx900/romstrap.lds    |   27 +
 src/northbridge/via/vx900/sata.c          |  296 +++++++++
 src/northbridge/via/vx900/traf_ctrl.c     |   35 +
 src/northbridge/via/vx900/vx900.h         |   74 +++
 39 files changed, 5084 insertions(+), 39 deletions(-)

diff --git a/.gitignore b/.gitignore
index ea10be7..429982f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.gitignore
 .config
 .config.old
 .xcompile
@@ -56,3 +57,9 @@ util/superiotool/superiotool
 util/romcc/romcc
 util/romcc/tests/*.S-O2-mmmx
 util/romcc/tests/fail_test*.S
+*~
+*.patch
+*.rom
+ util/
+coreboot.kdev4
+memtest
diff --git a/src/arch/x86/include/arch/romcc_io.h b/src/arch/x86/include/arch/romcc_io.h
index 37fb7ab..8876b28 100644
--- a/src/arch/x86/include/arch/romcc_io.h
+++ b/src/arch/x86/include/arch/romcc_io.h
@@ -244,6 +244,34 @@ static inline __attribute__((always_inline)) void pci_write_config32(device_t de
 #endif
 }
 
+static inline __attribute__((always_inline))
+void pci_mod_config8(device_t dev, unsigned int where,
+		     uint8_t clr_mask, uint8_t set_mask)
+{
+	uint8_t reg8 = pci_read_config8(dev, where);
+	reg8 &= ~clr_mask;
+	reg8 |= set_mask;
+	pci_write_config8(dev, where, reg8);
+}
+static inline __attribute__((always_inline))
+void pci_mod_config16(device_t dev, unsigned int where,
+		      uint16_t clr_mask, uint16_t set_mask)
+{
+	uint16_t reg16 = pci_read_config16(dev, where);
+	reg16 &= ~clr_mask;
+	reg16 |= set_mask;
+	pci_write_config16(dev, where, reg16);
+}
+static inline __attribute__((always_inline))
+void pci_mod_config32(device_t dev, unsigned int where,
+		      uint32_t clr_mask, uint32_t set_mask)
+{
+	uint32_t reg32 = pci_read_config32(dev, where);
+	reg32 &= ~clr_mask;
+	reg32 |= set_mask;
+	pci_write_config32(dev, where, reg32);
+}
+
 #define PCI_DEV_INVALID (0xffffffffU)
 static inline device_t pci_io_locate_device(unsigned pci_id, device_t dev)
 {
diff --git a/src/cpu/via/nano/nano_ucode_blob.c b/src/cpu/via/nano/nano_ucode_blob.c
new file mode 100644
index 0000000..6fc04db
--- /dev/null
+++ b/src/cpu/via/nano/nano_ucode_blob.c
@@ -0,0 +1,900 @@
+unsigned array[3588] =
+{
+    0x53415252, 0x00000000, 0x010f07d9, 0x000006f2,
+    0x04bb1af1, 0x00000001, 0xffffffff, 0x00000ca0,
+    0x00000cd0, 0x46363030, 0x45325032, 0x00000000,
+    0xcb93e3bb, 0x191b8d4a, 0x1863851e, 0x5073b90e,
+    0x637e23a3, 0xfb2b5429, 0x04714c6c, 0xc15656b7,
+    0x1a338d28, 0x1b182ec1, 0x3c52af0a, 0x6d370976,
+    0x969bc177, 0x64487a31, 0xcc081129, 0x5e1eab09,
+    0x60510c3c, 0x8a8056df, 0xd63b03a9, 0xa44b1274,
+    0x0debc269, 0x8b0345ed, 0x4970a2f6, 0x207d49ea,
+    0x204d200f, 0x382f15c8, 0xa036eb02, 0xb4a7bc00,
+    0xdb71ba56, 0x94b7c995, 0x9a62daf2, 0x1121f430,
+    0x3e4a5be0, 0x3c7161fc, 0x871cf176, 0x401b4152,
+    0x7666d9e6, 0xa7d0a300, 0xba2badc0, 0xb76c09d7,
+    0x20188e4c, 0x790a4683, 0xc9e67da8, 0x0e06ac83,
+    0x61a20460, 0xff613e2b, 0x75987149, 0x1f377798,
+    0x0d2d0a03, 0x80770351, 0xfdd1521a, 0x9e0c3559,
+    0x615cff3f, 0x4b52bf4f, 0x7f147ef1, 0x8710413d,
+    0xa1f56c83, 0x82b4e353, 0x41059fd8, 0x0ba3cee2,
+    0xec086b55, 0x30884385, 0x8de9db16, 0x5b43fe34,
+    0x181d9769, 0xaf85ba70, 0xc1e0339d, 0x57543307,
+    0x6a9f4dae, 0xc311f618, 0xb517af2e, 0xf1dee71b,
+    0x055b82d4, 0x2c87f018, 0x855e566e, 0x62902b91,
+    0x81add936, 0x369c1e10, 0x580b5188, 0x72884066,
+    0x60451175, 0x33f8c435, 0xeb7a0000, 0x403bb343,
+    0xa7af4cee, 0x52dc1a70, 0x0f14769b, 0xc3322154,
+    0xbe2d133c, 0x18631717, 0x4dd84315, 0x004885c0,
+    0xeb301a26, 0xff84832c, 0xcba0da4a, 0xa62d6358,
+    0x63f014e7, 0xfd11a7cd, 0xe4caac35, 0xee8eac91,
+    0xf46f29e6, 0x98b09104, 0xf3e95a8d, 0x66b0a414,
+    0xd8fc6cd4, 0x5ffd91e9, 0x59df2432, 0x5a76aba5,
+    0x39564d85, 0x05743921, 0x0f8c6cc2, 0xc75205b0,
+    0x69ebf3a1, 0xbd742cf5, 0x75b4904f, 0xb6757441,
+    0x0019eb84, 0x65186919, 0x5cda5257, 0x9abec161,
+    0x2703a74d, 0xb8e17040, 0xcee1b384, 0x13e81aed,
+    0x5f1accea, 0x61593e03, 0x1e3a816e, 0xddd02632,
+    0x489c55c3, 0x999ee852, 0x6f1fc127, 0xb8a3dda1,
+    0x88218af7, 0xafd4a7c1, 0x8a9cd570, 0x525b63d8,
+    0x39ca4752, 0x18cda626, 0xc6871457, 0x53606f5f,
+    0x57e6bc19, 0xe7fca134, 0x5b554854, 0xa92ca963,
+    0x9fefd3ff, 0x208c2169, 0x585520fa, 0x1661b36e,
+    0x47ab65ee, 0xdfebfbf9, 0x9c66a187, 0x17dad804,
+    0x2c78cadc, 0xd5e76482, 0xc5325e9f, 0x75f4e6a3,
+    0x5bf89d31, 0xe3b8343b, 0x66ae81c0, 0xb08e79bd,
+    0x7c14f7d3, 0x77c55a1c, 0xb9564471, 0x7fbf729a,
+    0x80b59bd8, 0xa11c09fd, 0x07e3ca4c, 0xbab01bcd,
+    0x3789f6bc, 0x9818d37d, 0xe6d32289, 0x0f6a4bf6,
+    0xcd25812f, 0xb77d2cdb, 0xfc2d2824, 0xb86998dd,
+    0x66de552c, 0x063f6eba, 0xd65591a3, 0x59ade6b7,
+    0x5dfa16eb, 0x8c5b0b17, 0xc5b92112, 0x2f5a48b8,
+    0x81ad574a, 0x42259f3e, 0x79403f4b, 0x0924fc75,
+    0x108fe221, 0xa251e85f, 0x4e8c16ec, 0x365c9527,
+    0x2abbb52f, 0x118c79a7, 0xb05ba6c0, 0x0eb2b3ed,
+    0x8b011c88, 0x79175adb, 0xcbafe02c, 0x9307c24f,
+    0xd15209ca, 0x23e569fd, 0x26815346, 0x425bd748,
+    0x504217c2, 0x64e9d2c0, 0x400ba29a, 0x632e3858,
+    0x7ab4e2d5, 0x6e868452, 0x85bd8005, 0x189cd3c0,
+    0xd3cbe3f7, 0x820a90aa, 0x4f68b900, 0x65c53860,
+    0x9a86de7f, 0x4c836b6b, 0x73841092, 0x78590b4a,
+    0xcd4afc02, 0x73e79113, 0xafefe0f9, 0x30bec385,
+    0x1fc9252f, 0x6ee8ce4d, 0x3cfa91bb, 0xf493ad13,
+    0xf02593e0, 0xa63b96da, 0xa7a9c5cb, 0xdcf34661,
+    0xdabcc8c9, 0x1f330aa8, 0x288df4de, 0xffc2462a,
+    0xba825a78, 0x6a12478b, 0xda32e0a9, 0xb832887e,
+    0x5fe63cc3, 0x26cc1f1b, 0x4c7015be, 0x52b54080,
+    0xb025f5f1, 0x8f8d5ede, 0xbfd6ce2f, 0x924891c3,
+    0xbe57187d, 0x46e5774f, 0x60a835a3, 0x55a976d3,
+    0xe30f0595, 0xca07e54a, 0x8231e320, 0x8f977146,
+    0x475d7c82, 0x10d413c6, 0xc052b913, 0x4c837bc3,
+    0xbb18ba72, 0x504e64d8, 0x6981f723, 0xda361a85,
+    0x93443179, 0x74ee16a6, 0xe69a40a5, 0xc117916c,
+    0xef2f94ac, 0xa06b1e43, 0xdc6e01f9, 0x738e45d0,
+    0x6b691cca, 0xd3aee7a7, 0x4fe6ee6c, 0xaf2c3419,
+    0x936e5354, 0xaa757d6d, 0xd01d94fc, 0x47472d81,
+    0x59489f6d, 0x05cc8f75, 0xeaf2c914, 0xde038603,
+    0x421e1d5d, 0x45130e4f, 0x8567c50a, 0x240a6fe6,
+    0x2d270151, 0xeebc219e, 0x0c144950, 0x7d720b18,
+    0xe6fcf50f, 0x0cda08b2, 0x9241fad6, 0x93152f2d,
+    0x168b85b9, 0x6eeaeacd, 0xd260c66e, 0x98722b57,
+    0xe7fcce71, 0x8cf65088, 0x7c218a64, 0x9e957b44,
+    0xb2f65850, 0x077e049f, 0x2e53ea65, 0x7bf3cb90,
+    0xca9a4364, 0xddacedc2, 0x1d14f350, 0x3bde8346,
+    0xf7e5d1ee, 0x7328349d, 0xd665e46f, 0xeffc771b,
+    0xb8e40217, 0xaf1ffddb, 0xacef49f0, 0x7a4767e1,
+    0x29659ac1, 0x8fdfee86, 0x2652e871, 0x32ef6440,
+    0x23981fef, 0xd6956341, 0x44996531, 0xc6dac529,
+    0xdb49a5c1, 0xb49e0268, 0x03b9a628, 0x859a9cb5,
+    0x2324f6de, 0x8e09a640, 0x73111b32, 0x209d2265,
+    0xf8ce7adf, 0x1fee2336, 0x91be0cc2, 0xa6231b34,
+    0x2ee23a48, 0x1f9f0f02, 0xcef888d5, 0x54928d45,
+    0x84a864f8, 0xdffdc2ac, 0xedead650, 0x895781ca,
+    0x2c1ae5c7, 0x7cd560f0, 0xf346ad96, 0x2a919ca3,
+    0xe845fb6a, 0x5d571861, 0xa28f98f7, 0x0625128f,
+    0xb3032eea, 0x5e737938, 0xab4e2758, 0x30da5a1a,
+    0x0700091c, 0x49e24af7, 0xb8739db8, 0x7071cb8d,
+    0xe8b664cf, 0x5fd996ac, 0x69949200, 0x7e8e89ed,
+    0xb534a7bc, 0x79fcab56, 0xf7c922c0, 0x260db9df,
+    0x044a7415, 0x771bf7c6, 0x43c80438, 0xa68f9d6e,
+    0x26866efd, 0x069dbef7, 0x5ec95f89, 0x118a6f4e,
+    0x04f307c8, 0xd2442831, 0xc3a4055d, 0x38dd57bb,
+    0x5a2bf99e, 0x943c8216, 0x8a8a8d67, 0x06d8933d,
+    0x36d8c238, 0x52892351, 0x233fca34, 0x8f37f14a,
+    0x03da33bb, 0x5403344c, 0x89abc6db, 0x0c615ee4,
+    0x841c70f6, 0x2eb7465a, 0xbe04d7f2, 0x58d30b98,
+    0x684f579c, 0x04968042, 0xa1288066, 0xa02d7561,
+    0xef31130a, 0x7af7c497, 0xd06ac0f2, 0xd7d213f3,
+    0xc7151981, 0x6f62d944, 0xfa29cd6e, 0xcc39d1c6,
+    0x1ac2747b, 0x3c15dd86, 0x9c0c31eb, 0x81297dc2,
+    0x1da797fc, 0x7eede51d, 0xb7acaba4, 0x3fe2d1af,
+    0x72255af0, 0x99649635, 0x993f7868, 0x400d58f5,
+    0x6d606432, 0xb3a02790, 0xbc8b9346, 0x001c3213,
+    0xf0521676, 0x8fed58a2, 0x91a13447, 0x2a2e3fe3,
+    0x3d961ac1, 0xee9f3e1a, 0xdb1e5cc0, 0x91170710,
+    0x3bb17cd9, 0xa87cc42a, 0x29fb31dd, 0x540fa9c9,
+    0xe74c97ef, 0x08e2ac05, 0xee5255cb, 0x8ccb8dad,
+    0x14508794, 0x75702112, 0x05ecb30b, 0x5b68f36f,
+    0xdd90f0f0, 0x4c60e9fe, 0x1152b8b2, 0x1598fe5e,
+    0x10f1a26d, 0x95b63950, 0x4360fd96, 0x65c82329,
+    0x2a4b6080, 0x9ff2d6aa, 0x8ff3c3af, 0x2ebdbdec,
+    0xc42c46d9, 0x1af653ee, 0x5fbf4d3a, 0xa9936322,
+    0xdc317ab0, 0x7671bdbd, 0xc971f3aa, 0x07978288,
+    0x7c47615b, 0x0db52c1b, 0x3d0eda0b, 0xe63c6102,
+    0xd56ef998, 0xaa755081, 0x0a749833, 0xcf4ec8ed,
+    0x34a92cff, 0xee1bf9a1, 0xb59b0b64, 0x96354086,
+    0x9d7d5a3c, 0x8144a9ad, 0x96830ca9, 0x90703b77,
+    0x44db18c2, 0x0932960c, 0xc89dbf7b, 0x3ca76c1c,
+    0xe6cc836b, 0x368eede3, 0x55c18caf, 0x00cbafd5,
+    0xc3078024, 0x7d15441c, 0xd23ad62c, 0xf7661a68,
+    0x98847057, 0xd6767a16, 0x196501b6, 0x68396b86,
+    0xef4af71b, 0xa81367c2, 0xa4d13e7d, 0xbb8eebeb,
+    0x4db5f47a, 0x731be642, 0xc2a15f27, 0x3324a7ea,
+    0x0db10f7b, 0xaba8fe35, 0x225eb533, 0x9f188e3d,
+    0xa5da4ad3, 0x3464c397, 0xc7572bc2, 0x43bc38e5,
+    0x3a79ff7f, 0x3021c8f4, 0x822d257e, 0x295f9ee3,
+    0xa62aa886, 0xeedfdbd0, 0x10ba9b9b, 0x6304cbca,
+    0x03bbb766, 0x5fccc253, 0x6434c05e, 0xabd80cac,
+    0x036ea64a, 0xc7babe5a, 0xde7b2fbe, 0xbcd2d22a,
+    0x5f8219a6, 0xfc75fedf, 0x4f17ce1c, 0x6e670ca9,
+    0x625b6ae6, 0xee8e9f95, 0x3b3eaae1, 0x9b3ca894,
+    0x0b0ba78b, 0xfad8065d, 0xa1006779, 0xad9dc956,
+    0x9f1d8e3d, 0x92f57a18, 0x9bc9e111, 0xc318ae8f,
+    0xb6862269, 0x3d06fb0d, 0x861c740b, 0xb95e8053,
+    0x419e7fd2, 0xc360dc82, 0x26d99c21, 0x4336524b,
+    0x8a9414e5, 0xef9e020e, 0x57e81247, 0xa32a3cab,
+    0x568e0a11, 0x4daf23bd, 0x1b5d7277, 0x212b7332,
+    0xdb34afb5, 0xf3d0c01d, 0x5ca627df, 0xaa39c230,
+    0x4192aa29, 0xed166fa9, 0x071922a6, 0x61074f39,
+    0xfa700b5a, 0x4a60ed83, 0x1d1d9850, 0x5fe6c671,
+    0x17730867, 0x6b2c5bfc, 0x0e0dd897, 0xa5c82db3,
+    0xffcd57cb, 0x962ec9fb, 0x1ac2bdfc, 0x8b85b190,
+    0x7a4b5a35, 0xd1224522, 0x900462c7, 0x32805daa,
+    0xa1a8b29b, 0x4720559b, 0x1d846a68, 0x08edd510,
+    0x02ca010f, 0xeadce4c4, 0x038cde06, 0xbdbfadac,
+    0x9144d599, 0x670e6072, 0xc14d3857, 0x61f2de60,
+    0x003d684f, 0xc1ddece7, 0x66c453b6, 0xaf66d81a,
+    0xe15a2f94, 0xbb3c1f59, 0xab6f1f7d, 0x3b24d812,
+    0xd629cd94, 0x09d51c81, 0x45cc0259, 0x8eaa8b98,
+    0xbd945c62, 0x4e74d9ba, 0x449372d0, 0x59bbc106,
+    0xaa2e4bda, 0xeb24fd0b, 0xc461db59, 0x89fb5031,
+    0xd51d68bd, 0xe43f615f, 0x0cda1656, 0xe5d77e7a,
+    0x8136b5c1, 0x13b0c9fd, 0x424adc1c, 0x62797556,
+    0x450ac473, 0x7f1a6b9d, 0xf678b474, 0x56bd0f0e,
+    0xe0d75f60, 0x29fc1192, 0xed79a7de, 0x331ffd62,
+    0xacdac9e9, 0x59de2860, 0x81765718, 0x288c9049,
+    0x5aa21365, 0x1d8c1119, 0x1f69f6aa, 0x9d5fecc7,
+    0xccab7d03, 0x611dd66d, 0x88cff2c3, 0xa32df329,
+    0xfb79f49c, 0xa5673b94, 0x01ca3e4a, 0x4a3c4a3a,
+    0x79e381ee, 0xfdccd33a, 0xdfffe03c, 0x71785391,
+    0xd35dc0a3, 0x90c514d7, 0x7f272154, 0x2fbade0b,
+    0x7e7a40f7, 0x81225389, 0xbc7959fe, 0xfc11b819,
+    0xb35a6494, 0xf2536a6f, 0x08797aa8, 0x448cd990,
+    0x9444e16e, 0x03e145ae, 0xd5df6c1b, 0xbf11e6bf,
+    0xa4cfa985, 0xa22bfbfe, 0x0a51c5c8, 0xdc037e99,
+    0x22433d50, 0x734d2ba1, 0x8462dcd9, 0x93c0eaca,
+    0xef87a4bd, 0x7ddfcd1e, 0x73e7d2c6, 0x55c6a86c,
+    0xc1d99aae, 0xe88fa687, 0xbeadd303, 0x91af28c0,
+    0x38e178a0, 0x903911b9, 0x804982e8, 0x4e28b42c,
+    0x50d16e74, 0x5cf89c55, 0xa5e4a723, 0x69647877,
+    0xb9e426a6, 0x5f0b5419, 0x4c810a84, 0x99c0bc0b,
+    0x1c66db66, 0x9d664e5c, 0x97c517f4, 0xcd7bf742,
+    0x284a6299, 0x29a414f6, 0x266b30bf, 0x341a3c0f,
+    0x03649f3c, 0x3baaff4f, 0x150626e4, 0xcc705cac,
+    0x97f93343, 0x5c667935, 0x796e0213, 0x87339a47,
+    0xb67e7c0b, 0x19d36387, 0xfdebd50f, 0x2ccbb93a,
+    0x53418f96, 0xb9913750, 0x474e557d, 0x39066bfe,
+    0xc132ed2f, 0x969eef68, 0xeea46a2b, 0xf38d3ac8,
+    0x94fa4b4a, 0x0f3d5a39, 0x663681bb, 0x052d913d,
+    0x0ed760d8, 0x6a86a5e6, 0x3b4f8215, 0x45e1703e,
+    0x7b6da797, 0x2f417ce8, 0x370805fb, 0x10d71f7d,
+    0x939e57b1, 0x660658bf, 0xb0578eff, 0x83c92004,
+    0x82d2e830, 0x6a069ede, 0x37bff328, 0xcfc11964,
+    0xc1551e3b, 0x43f5f81d, 0x993a4c70, 0xb5368f5c,
+    0xcdfd6ab1, 0x33fb820b, 0x8982c211, 0x658c9d3d,
+    0x03d94fea, 0x9d14461e, 0xf6054c0b, 0x23505ea9,
+    0x767bc220, 0x2ae3ca31, 0xf3994369, 0x60c3f27e,
+    0x4b9b0489, 0x44cc2326, 0x8c6f6753, 0x92905384,
+    0x4aa90362, 0x5fb075a6, 0x2e61e8bb, 0x46cd1270,
+    0xe72c6c9d, 0x83111ee4, 0xccd8f5c5, 0x5103ec2f,
+    0x6e851815, 0x947f246e, 0xde86ad18, 0x9760a987,
+    0x059e48e2, 0x58a79e93, 0x6aa5b31a, 0x35aabcd5,
+    0x71f4d3e7, 0x1ae1f425, 0xecce2950, 0x6253dc95,
+    0xd91f8ddc, 0x214a4a07, 0xb4d299ad, 0x13ef8d8e,
+    0xbed7b47f, 0x4a12a7eb, 0xeb0963ab, 0xdf0f3b8f,
+    0x2aa6845d, 0x80881430, 0xd615c63d, 0x4d244696,
+    0xf627cc27, 0xe03210af, 0x2bc55248, 0xf16867e9,
+    0x1e065d75, 0xc2b362cd, 0xd9751d64, 0xc2949adf,
+    0x53415252, 0x00000000, 0x061a07d9, 0x000006f3,
+    0x08074e5a, 0x00000001, 0xffffffff, 0x00000390,
+    0x000003c0, 0x46363030, 0x32315033, 0x00000000,
+    0xb07f7392, 0x535a690e, 0xb60295df, 0xfaff25b9,
+    0x4f4609e6, 0x9fe6ac72, 0x879663b0, 0xab25c96a,
+    0x65e5e671, 0x5cd611f8, 0xf39e82bd, 0x931d23de,
+    0x4504a04c, 0x2ba455fb, 0x2fc1034c, 0xbd47d87e,
+    0xdeb4d91c, 0x33e88111, 0xf1521b6d, 0xa0f8cb0f,
+    0x013166c3, 0xa784e786, 0xb564c335, 0x826dca49,
+    0xda84b5e5, 0x63b0da88, 0xd15fd3b3, 0x501590bf,
+    0x9efa91a7, 0x5f8b7591, 0x97710227, 0xf162ab61,
+    0x76ec62b9, 0xa8bbba48, 0x5be51483, 0xb84fdb38,
+    0x933f9758, 0x8616b6b7, 0xc0b405c4, 0xcdbd4e00,
+    0x254c6488, 0x907dc541, 0x90edf61d, 0x5beef31e,
+    0x782de3cf, 0x158500d4, 0x9cee8612, 0xdebe1f64,
+    0xce9d7aa3, 0x0b968a79, 0x520ae716, 0x3dc74a69,
+    0xb2393da8, 0x6a9f4ec0, 0x7e609890, 0x07121f6b,
+    0xb318c3f8, 0x52db78bd, 0x2530e9fe, 0xae1a1b72,
+    0xef55426d, 0x462b9823, 0x9b5fcc9f, 0x46b525ee,
+    0x5284a388, 0xc1ce0d78, 0xf9e86226, 0xaad31a00,
+    0xb183aeb0, 0xa75f6593, 0xffa6705a, 0x1d43b713,
+    0x644424eb, 0x1f9cc20e, 0xa096550f, 0x3497cebd,
+    0x1941af1f, 0xcf205da8, 0xb3996a90, 0xa08cd793,
+    0xe1021d21, 0xaa80086e, 0x30e29788, 0xd35458e5,
+    0x6d5b50cf, 0xc5aaa0f0, 0xd8dceac7, 0x096d6e2a,
+    0x10b245dc, 0xba5c77c1, 0x2970e03b, 0x4b742ff2,
+    0x6a2ffbf5, 0x42d4cdbc, 0xeb2744c1, 0xf49eb6f5,
+    0x806e288c, 0x608e6ad8, 0x9fa0d47f, 0xb40e1ae4,
+    0x0e63b495, 0x6b1b1fbd, 0x8f1dcda5, 0xff0f7888,
+    0xeb425a16, 0x1eee7e0a, 0x69c202bc, 0x04020726,
+    0xbbc62de3, 0x6ebbd54b, 0x22be95c7, 0xe37298e9,
+    0x309bd861, 0xb04b8d33, 0x63b1e9dd, 0xa27459a1,
+    0x1f7f69eb, 0xb4cfda0b, 0x226d81a3, 0xaef54cc2,
+    0xfdb2af55, 0x8f40bd55, 0x7c75fc1b, 0x1ea27f79,
+    0x7d4775a3, 0x49b65d08, 0xbd9afb11, 0x9c54c786,
+    0x01fe71ea, 0x9bfc7e9a, 0xe8dca094, 0x416dd13c,
+    0xc160dfe5, 0x737538f7, 0x6e4a1a3b, 0x3e6dafc7,
+    0x6d72e2ce, 0x12e54b8a, 0x7035f549, 0xb072e1d4,
+    0x3b38588f, 0xe026e230, 0xeb224bf0, 0xe37f21c9,
+    0x9a36fef9, 0x5d82682d, 0x11e5edc2, 0x3442a202,
+    0x5072abc3, 0xe544eb7e, 0x578bde22, 0x295f8584,
+    0x02c23076, 0x35476376, 0x9f135eb8, 0x0613fe0f,
+    0x5ff04afc, 0xd3e1053f, 0x23b58392, 0xc4a0f77a,
+    0xb87814d6, 0x3a8c17f4, 0xb5efab44, 0x3fe2c21e,
+    0xcbe0efb6, 0x12997b25, 0x5b18b44e, 0x6b849d21,
+    0x580f84e4, 0x99a964d0, 0x3fa892a9, 0xd4b01144,
+    0x6d54c83b, 0x31659593, 0xd7596e21, 0x642c0e11,
+    0x7403ea9c, 0x47719512, 0x33a86634, 0x8ae60597,
+    0xb94e5df6, 0x5cf4e917, 0xe438f361, 0x8f5d4d13,
+    0x00f3d7b7, 0xb9b15305, 0x8e9e1537, 0x350c32f9,
+    0x31d5f77f, 0xdb7ae793, 0x70094efd, 0xca83ff65,
+    0xa7f487dc, 0xb15ddccc, 0x99609635, 0xf06787f3,
+    0x8bc4b4e1, 0x6ebc77e2, 0xf55f780b, 0x4a3b9c96,
+    0x91860f8a, 0x75827196, 0xb5948530, 0xc7152cb7,
+    0xec776fea, 0x55c73d21, 0xc4b036c5, 0x69af8697,
+    0x1d80bc77, 0x91eea8a8, 0xd1ba9808, 0x5a0a812f,
+    0xc2a14b33, 0x351a2801, 0xc0b41870, 0x3241a4f9,
+    0xa09fe4b5, 0x407aae2b, 0x394b6e00, 0x323a0b88,
+    0xa01681d5, 0xda56a382, 0x216d8f3d, 0x7b8e0b61,
+    0xfb4aa26e, 0x6e5c4623, 0xdc082e4c, 0xe9ea397c,
+    0x53415252, 0x00000000, 0x061907da, 0x000006f8,
+    0xd4f1b587, 0x00000001, 0xffffffff, 0x00000220,
+    0x00000250, 0x46363030, 0x46325438, 0x00000000,
+    0x3299b452, 0x689711fa, 0xee4c84d4, 0xba1598f3,
+    0x1b403653, 0x2798a70b, 0x224e13ad, 0xc328665d,
+    0x19f33bc3, 0x54e1be26, 0xe8128c3f, 0x06f9f27f,
+    0x6fb344ff, 0x36bd410e, 0x229793f2, 0x4d5bc18d,
+    0xc4f03970, 0xfc7234d0, 0x1856eb5d, 0xcb3a0ed7,
+    0x524e9de9, 0x1f6cde76, 0x1affdd49, 0xadd2bab5,
+    0x9c472670, 0x84553d4e, 0x7c8124e1, 0xaddd4ac0,
+    0xf3588d7c, 0x4642a4be, 0xb1eaa4e5, 0x9069602a,
+    0x44118af3, 0x3c4c0dbc, 0xacfafeca, 0xa6c708be,
+    0x4610f501, 0x91f4aabe, 0x0fa3cddf, 0xc64761a7,
+    0x22022ece, 0xa4d589bc, 0x237de460, 0x60067a6c,
+    0xf4cff750, 0xd7f5f8c5, 0x9ce2a52a, 0x5653e820,
+    0x139344a8, 0xc1203a30, 0x4e7f9226, 0xf562836d,
+    0x0280a4f9, 0x6f23eb5e, 0x3a0e7684, 0x23281e3e,
+    0xb3c7c258, 0x216d2392, 0xba5f0c35, 0x4e82b0fc,
+    0xf4e4b3ab, 0x1cd124b7, 0xe1a3261c, 0x5972c999,
+    0x9575d310, 0x58c81253, 0xc24d1f17, 0xd224c5f7,
+    0x1205ac8a, 0x2a0fccee, 0x3017b59b, 0x8caf9c22,
+    0x9e2a470c, 0x3a217bfb, 0xafc9c401, 0x8f278be9,
+    0xedcc7fce, 0x293cfb52, 0x2fbcf8f5, 0x2470a1df,
+    0xc8fa046e, 0x58315fcb, 0xfc7c7834, 0xcab53bdd,
+    0xf3615edf, 0x65f5df91, 0xb145ec86, 0x246bb495,
+    0x6a71f1e8, 0xc01d50cf, 0x6768cb06, 0x835912be,
+    0x884a8f0b, 0xafa8c8c0, 0xfa37d361, 0x8026f64e,
+    0x8c755c89, 0x4c412800, 0x94f8c215, 0xcee50ecd,
+    0xe4098f72, 0xe932bccd, 0xf0d2a3b0, 0xe3cbfd25,
+    0xecc7ce41, 0x501b9db9, 0x160ef756, 0x35e97342,
+    0xc1de34a6, 0xb9f30ca2, 0x1e5018a7, 0xcc6ed6c3,
+    0x84698919, 0x8e1337e2, 0x299b3d65, 0x401339a2,
+    0x437d0911, 0xa0baf2cc, 0xe23713b1, 0x814cde1a,
+    0x18977d01, 0x22a6a5fd, 0x75eba689, 0x586ecb90,
+    0x9a5b37e3, 0x3d3da0f1, 0xed63599a, 0x40dba6cc,
+    0xa8a920a7, 0x9b548faf, 0x7562d2ca, 0xd69ac4e0,
+    0x59ef1bfc, 0x08787853, 0x82844a28, 0x2cd823e5,
+    0x53415252, 0x00000000, 0x051a07da, 0x000006f8,
+    0x5d1a2de5, 0x00000001, 0xffffffff, 0x00000c20,
+    0x00000c50, 0x46363030, 0x64325038, 0x00000000,
+    0x1239d07e, 0x691e32e0, 0xd205e5c0, 0xdfc570de,
+    0x278e4479, 0x4bca3390, 0x6e7e9b71, 0xd4a85a32,
+    0x99af2c5e, 0xb452d0a5, 0x4bec4f39, 0x045a8308,
+    0x09639159, 0xe5ee7bd3, 0x1f49d8ef, 0x3a72c6ce,
+    0x9a299074, 0xf7a294c2, 0xf88ad4e9, 0x99a46faf,
+    0xd106a8e9, 0x1c1c978b, 0x22c43cc1, 0x4af01738,
+    0x1f0d51e1, 0x43976497, 0xd59b7f7c, 0x77879a05,
+    0xe8e89fed, 0x93e1b538, 0x9d3855ef, 0x7ea23c17,
+    0xe550e1f6, 0x17613f73, 0x0783fc18, 0x81980e9d,
+    0x107dc8df, 0xe620b143, 0x48236b44, 0xabf1efb9,
+    0x7100c5c7, 0xd2245ace, 0x8c859d0b, 0x563a71b7,
+    0x697dc982, 0xc34a7399, 0x84fea92f, 0xfe6fae64,
+    0x5e053930, 0xf3de4ab5, 0xc9924782, 0xa4509166,
+    0x96780cbb, 0xf9008bb1, 0x4d9f7e1b, 0x0e117f75,
+    0x01c28c4a, 0xe4321ae6, 0xfb340eab, 0x666247a1,
+    0xa8a5a4a8, 0xe47a3486, 0x94b71bff, 0xeb6d4841,
+    0x51b7dbbf, 0xcf6bdc3e, 0xae0c68a0, 0xd28c8e55,
+    0x170435d7, 0x9ee8dcb5, 0xcd2de33e, 0xd13ac2de,
+    0xa15478d6, 0x226485e7, 0xff7ab105, 0xa0c4ae78,
+    0x4a8c6cd6, 0xbe4008ab, 0x1037e1e5, 0x5eeb7789,
+    0x9811fe9c, 0xde44c9ed, 0xa2ffd6d1, 0xecc9f0da,
+    0x00a460e2, 0x44767b1a, 0xe854e585, 0xc70d0131,
+    0x3f519a63, 0x468d4386, 0xbbd9c826, 0xa8de428a,
+    0x0015b96d, 0x17221e10, 0x514e719e, 0x62398cee,
+    0xb67bb642, 0x0b552de8, 0xe2b2d2f6, 0x22be5083,
+    0x5ab773ae, 0x46cf2603, 0x86d62320, 0xa0748945,
+    0x5493221a, 0xa783c1ba, 0x622660e8, 0xb6dc2449,
+    0xc1897743, 0xfd20c8b4, 0xe14c135f, 0x4e811706,
+    0xdfdd2b7d, 0x3c16ffa5, 0xd0905f28, 0xc823bef5,
+    0xd862aa3b, 0x31365fb9, 0x7bd9c7ab, 0xbcf2d6c4,
+    0xbfc18909, 0xe26312ca, 0x5a68d937, 0x6d250f9b,
+    0x0781914d, 0xabe54ba9, 0x85d894e6, 0x8c825963,
+    0xc6e50f72, 0x538ea5a1, 0x861a4623, 0x2bffc2de,
+    0xe28ae4a2, 0x397d6007, 0xa861f13d, 0xdba785be,
+    0xc11c37e5, 0xc41a74d7, 0x0f1485c5, 0x1e477a67,
+    0x8c3d8f46, 0xf7ed4dc8, 0xe99bc25a, 0x1900b0b0,
+    0xe5cb1b0e, 0x86d18bbf, 0x06ce255c, 0xa762a311,
+    0x721137c7, 0x26770edd, 0x41839b2c, 0x4bd33366,
+    0x53836b63, 0xfdc9ed92, 0x5a5145cd, 0xb389fb44,
+    0x2314ff6d, 0x3b6f0c95, 0x3b201e62, 0xbc5c0994,
+    0xc620809b, 0x2d9cfacb, 0xe7ed2028, 0x43ecd1c1,
+    0x13586475, 0x4a720fd7, 0x402f351d, 0xb9781bf9,
+    0x730e46b4, 0x6810e052, 0xf1dd1b73, 0x8c93e152,
+    0xb668f9a8, 0x387ee173, 0x41b84b1a, 0xfccfcd68,
+    0x6047f011, 0xaec6155a, 0x29e0273b, 0x3c9d935e,
+    0xcb98f03e, 0x4fb51e6f, 0x3ad9b929, 0x6569a278,
+    0x09b3f6a5, 0x722e9d27, 0x3d4e7da7, 0x11eb3728,
+    0x076d703d, 0xdca1cf88, 0x2bfad541, 0xcb82293b,
+    0x99c39f16, 0x6bcb6cbb, 0x1ed41582, 0xcc9be6f0,
+    0x11f00eb4, 0x1ba055d1, 0xe9a43853, 0x5c055bbe,
+    0x1ba8500c, 0x70430fd4, 0x45583d82, 0xfc41ef87,
+    0x3e513205, 0xfd65386c, 0x8a814402, 0x14117437,
+    0x8a486978, 0xb49cc14d, 0x9c22a9e9, 0x746c15ae,
+    0xcab3486f, 0x3989de53, 0xd7e237cb, 0x5feb4d98,
+    0x5c56cbc2, 0x841b5e44, 0x09c9a118, 0xf1f2d529,
+    0x4fb098fc, 0x1cb3e1ea, 0x9f25bb78, 0xd56f9469,
+    0x38b08d7a, 0x19b0e914, 0x86311f65, 0x7069459d,
+    0x711daf17, 0x09738673, 0x53e9bedb, 0x043032e5,
+    0x32058bd4, 0x22b1a50f, 0xc66b2642, 0x2a7c553c,
+    0xe7da476d, 0xdfbcc19a, 0x538b5822, 0x3bca007f,
+    0x082d45fc, 0x78bfcdcb, 0x98e554c4, 0x9ec8e392,
+    0xebf5ed7c, 0x3b154db7, 0xacf59ef8, 0x8443d4a5,
+    0xd90a6e4d, 0x486d9807, 0xfd4bab17, 0x76628450,
+    0xc73b007e, 0x9397abc5, 0x63f035c8, 0x92c4603b,
+    0xe5807fd2, 0xd305a2ae, 0x65d2c231, 0xdf35bd23,
+    0xaae754fe, 0x46b9de20, 0x699fd249, 0xa38ddaf0,
+    0xb3dbf2df, 0x151c7094, 0x7bf864b9, 0x65aff002,
+    0x7d8d621b, 0xce073aa8, 0x6086f5b5, 0xfd4d8243,
+    0x791482c3, 0x0df0d01d, 0x6ad8e4ba, 0x6ad0d3f7,
+    0x2b77d92b, 0x6d68d02d, 0x4a43d822, 0xfef3b1a1,
+    0x54e96282, 0xdb7ab5b3, 0x72aac1d9, 0xfb4f83ad,
+    0x1e51747c, 0x36fea058, 0x1e715a12, 0xf3aa6639,
+    0xfd1a3a64, 0xf173bee2, 0x6a382ad0, 0x48435821,
+    0x31b90284, 0x3b9ba0c1, 0xf2329444, 0x323f7d8d,
+    0x8c72dc74, 0xce9301e1, 0x8cb5cd91, 0x124f7dcd,
+    0xcac6a0f6, 0xe487f261, 0x88e05297, 0x49074df2,
+    0x1c4c72ea, 0xbf37e900, 0x09103656, 0x723f13f7,
+    0x454b06c2, 0xe35eaf5f, 0x8879aaa4, 0x78c5ef10,
+    0xe5895238, 0x749df405, 0x0ce57fec, 0x6da90247,
+    0xea013e94, 0x6c907d03, 0x1b2f69b5, 0xb2744c73,
+    0xad1fa97c, 0xca641bb7, 0x10af012e, 0x0c922243,
+    0xa35519c2, 0xcc3067e7, 0x1064d47d, 0x087e9aa6,
+    0x803b5642, 0x9936d3c1, 0x3336db24, 0x2c3ccdec,
+    0xe5b6be8a, 0xe69dea99, 0x4a6f9632, 0xa9a945ca,
+    0xe7ba26df, 0xb2dae8a0, 0xde770e47, 0x91138e00,
+    0x3895be22, 0xd0b5f9b5, 0x834c3f69, 0xf75d5f75,
+    0x90468761, 0x009f6475, 0x73fe55e6, 0x73a00e1c,
+    0xddaaa0c5, 0xeb3ab712, 0x15d4c070, 0x1cdafd9f,
+    0x67831b13, 0xef666e8c, 0xc28c36a6, 0x42e5e1f4,
+    0xd5eb66b7, 0x388f50b3, 0x048c56ed, 0x2f4f9415,
+    0x435785a6, 0x9d42dc6f, 0x4273b34e, 0x3c3595e8,
+    0x15f938b4, 0xe2dd91ca, 0x83336b59, 0x4fd6fb7c,
+    0xbb696bdf, 0x27ce9bd3, 0xdbb85616, 0xf9d9fb6a,
+    0xb2f0eff5, 0x9216697f, 0x8f51ff6c, 0x99aa370b,
+    0x2acda31f, 0xd6a36d34, 0xd8475f8d, 0x00c6db0e,
+    0xfb5db914, 0xeccd35a5, 0x9de84e78, 0x11c242a3,
+    0xae3788e1, 0xc3f11ed6, 0xdb7da54d, 0xf9c24298,
+    0x2d1ddec5, 0x180df86c, 0x32fd5b37, 0x82e762ba,
+    0x19c464f9, 0x0b746141, 0x7069dd69, 0xd509970c,
+    0xdd325119, 0xe6195b0d, 0xf56796e7, 0xa0d7b2c9,
+    0xe392698d, 0x3d72adeb, 0x40e9eff3, 0xdf27aa62,
+    0xfbe9b1bb, 0x3eaf1333, 0x32d9cba9, 0xa90704aa,
+    0x2de9b422, 0x50f4c07c, 0xb63b4b7e, 0xa34313ca,
+    0x981dedfd, 0xeab79e01, 0x8900d971, 0x54ecd36d,
+    0x09146d31, 0x232c3d8b, 0x724b0f3f, 0x27beaf1b,
+    0x6380dce1, 0xf345f0c1, 0xa6cd4fb7, 0x5412699f,
+    0x0ebceac3, 0x92a5d843, 0x6c47d876, 0x34db9582,
+    0xf0159db3, 0x1e08b349, 0x8858102d, 0x24109519,
+    0xbcb7cae4, 0x84cf5852, 0x9e052e13, 0xb81c27bf,
+    0xd2750406, 0x5a35b818, 0xfb2c4908, 0xa4972bf0,
+    0x89296d16, 0xa7d13b99, 0xd74fa892, 0x1a9de940,
+    0xf2f439d9, 0x81eae6cd, 0x964f0918, 0x20c1f8bc,
+    0x415977f4, 0x85a775dd, 0xac52244e, 0x8fcc423c,
+    0x2d29104d, 0xbc61c01a, 0xf9675ac5, 0x90b773d2,
+    0x54d53eea, 0x1a9f081c, 0xa052d353, 0x9813df28,
+    0x3b2f5310, 0x0e771c09, 0xf4fedb01, 0x3e8efd60,
+    0x278d845d, 0xde7f42ba, 0x2345f3ac, 0xbebef98c,
+    0xe8adcba5, 0xdcd1e4ad, 0xf83bc609, 0x9a2fa38f,
+    0x2ac6482f, 0xa20cf438, 0x1a56ccc9, 0x79f1ed26,
+    0xd16c090c, 0x3c4d43ba, 0x3b2face9, 0x8f2a121a,
+    0x23bff2f3, 0xc05f634e, 0x7abcaff3, 0x8f640674,
+    0x91c1718a, 0xafed69e8, 0x5045ac4a, 0x1305672c,
+    0x50d9e2e3, 0xcc009820, 0xcf623411, 0x383811a7,
+    0xc1803f0f, 0x20cee852, 0xa5954ac9, 0x930e486f,
+    0xb6381088, 0x8c5f599b, 0x7c36f62d, 0x603132d6,
+    0xe79e0289, 0x23e6bbcb, 0xf36d61c5, 0xa188ccb4,
+    0x8138aea8, 0xa93c9f62, 0x68450a57, 0xedf82eca,
+    0x7e930a05, 0xc368bf51, 0xb92feb10, 0x17f95ccf,
+    0x6f15cfea, 0x0c6734c4, 0x7c86850d, 0x01ed6dbd,
+    0x1db961a7, 0x50d369c2, 0x81fe1af0, 0x598b6b2a,
+    0x42a3a9cf, 0x6e05e662, 0xf5b6a456, 0x2748aeb0,
+    0xc4645796, 0x5d9c489b, 0xbd6c830e, 0x1c161f9c,
+    0x476deedd, 0x269b3eec, 0xc602402d, 0x4b6fc409,
+    0x9f068add, 0xda7e60b9, 0xd8348fcb, 0x73d2b0d1,
+    0xa5959497, 0xeef9eca7, 0x4e32cb40, 0xec36b3ec,
+    0x4f1b132a, 0x662d5a69, 0xa6a019d6, 0x5c463ceb,
+    0x7d41e303, 0x59014126, 0x00fa882c, 0x4b1364b2,
+    0xcf0fabda, 0x2b1c9268, 0xb43c1b3f, 0xa684737b,
+    0x47f06aac, 0xcb04b166, 0x2af950ee, 0x216d324e,
+    0x9a9fbbbe, 0x33a47d17, 0x76f86457, 0xd93c3cd2,
+    0x20db26d9, 0xd49946dc, 0x6d95f662, 0x937c535a,
+    0x096e0a00, 0x62c05258, 0xe21c3f63, 0xbd267ef9,
+    0xc8c98b92, 0xb3e7880a, 0x528d53d3, 0x1d33fd8a,
+    0xf94c986f, 0xa8e57165, 0xac413d88, 0x34f19e3b,
+    0x50a3d8b7, 0x58fb8676, 0x54769514, 0xbde066cb,
+    0x2f764378, 0xea725550, 0x0a8da2f2, 0xca2eb43e,
+    0xdb390910, 0x99912ba4, 0x684a13a0, 0xf9dfce0c,
+    0x892a9f9a, 0xae224458, 0x18711cf0, 0x65c356ec,
+    0x381439ef, 0xd464bd27, 0x35de3dff, 0xaaa4df24,
+    0x10d24190, 0x3928a9cc, 0x0c825daa, 0x478c90a3,
+    0x5e6e78ca, 0x74f376d9, 0xd956af27, 0x063de8ca,
+    0x2f01ee2a, 0x6bc4cf28, 0x3e34901c, 0xd32a57ee,
+    0x213685b6, 0x75d5440a, 0x10695179, 0xded4b2b0,
+    0x7061436d, 0xbf4ea54e, 0xbd2ddcd5, 0xcfcc7995,
+    0xbc811e36, 0xcf6b17a3, 0x2bb295b6, 0xd3c0e8f2,
+    0xf8d0f7d6, 0x185a221b, 0x25006d43, 0xffbb6a42,
+    0x519c1a07, 0xe1e1024e, 0x5061c863, 0x4b0ba1ea,
+    0x5f86a8cb, 0x9a141d40, 0x65ed1bbb, 0x59aaccdc,
+    0xc301f198, 0xfc80d362, 0x5a837e5a, 0xe0cfb2e5,
+    0xc260a4dd, 0x31eff844, 0xfa7a0250, 0xff916b6a,
+    0x532e7112, 0xec3d9fb3, 0x67eadd71, 0x5d035008,
+    0x1031f03e, 0x10bc1eb0, 0xa4ffda78, 0x3fc90618,
+    0x069d00fd, 0x55e1a1a2, 0x0a989734, 0x5e710bde,
+    0x014971ee, 0x4da810b6, 0x81bc117d, 0x4c1ef7ce,
+    0x3b1700d3, 0x71384ebd, 0xdd61e7e8, 0x289950f1,
+    0xd07180c8, 0xb2e515cc, 0x997acc95, 0x5be0c088,
+    0x1d8158dc, 0xf0a69511, 0xb956f917, 0x9b5d5862,
+    0x0d6465b6, 0xce06697f, 0xfe1c0e62, 0xa4580f33,
+    0x2eeb88b5, 0x681dac6a, 0x9cfc3e9b, 0xa6ac8962,
+    0xf3881c23, 0x20e2f490, 0xc2537859, 0xed893623,
+    0xf425531f, 0x318333b7, 0x3256ae11, 0xd7a21e7a,
+    0x878f5dea, 0x863f99d8, 0x6a0aff4b, 0xad9ef05f,
+    0x2e0b2622, 0x328ee279, 0x9d78deba, 0x098fb6b4,
+    0xfd55c005, 0x09f38311, 0xaf043a10, 0x5beef91b,
+    0x49003cd2, 0x9131085f, 0x6fa720d9, 0x478eba08,
+    0x1ebd8a6c, 0x70a5de24, 0xf3381bd1, 0x0cd7e36e,
+    0xb8a700a0, 0x2e9c5742, 0x9b09100e, 0x57c7e936,
+    0xf9505650, 0x3e0aeb75, 0x48bb9648, 0xdafe191a,
+    0x0dcfc0eb, 0x99959593, 0x23215288, 0xd094cb50,
+    0xd5e7fbb2, 0xc891856d, 0x9e5939fd, 0xd394ea44,
+    0xf9657de6, 0xa2a2775b, 0x9926805d, 0xd8ac5f16,
+    0x5c86f714, 0x00d46245, 0x1303e8ea, 0xc98bb0e2,
+    0x3417f3ee, 0xe75bfce0, 0xeadd8c71, 0xc17a4930,
+    0x5f29da29, 0xe807c6d0, 0xbed5247f, 0xbf731759,
+    0xf9787556, 0x3a476c20, 0xd85972b5, 0x1ec03708,
+    0xa0690f12, 0x2fc6ed76, 0x014aa07c, 0x3725e608,
+    0x31adaeb9, 0x2d1a12bf, 0xc97eed8c, 0xe55bb6f0,
+    0xc6e2c259, 0xa09811a2, 0x8dae432c, 0x969602b5,
+    0xf389d691, 0x32d9dc61, 0x43758e7b, 0x7c4b2cf6,
+    0x97945f6c, 0x59c54e8a, 0x6262fbb0, 0x677b4c79,
+    0x7a1f6899, 0x17298ee9, 0x6b0cd48f, 0xe38037cc,
+    0x3c210d43, 0xe5239986, 0x15140d7f, 0x6be997b4,
+    0x34e54608, 0x896736ef, 0x6f719086, 0x1c946889,
+    0x8c02a0a5, 0x530d2d15, 0x76afe26b, 0xbec240c8,
+    0x53415252, 0x00000000, 0x0a0507da, 0x000006fa,
+    0xc28eb1c2, 0x00000001, 0xffffffff, 0x00000300,
+    0x00000330, 0x46363030, 0x37335441, 0x00000000,
+    0x0d31346a, 0xeb2ca8ec, 0xc65a3981, 0x28ddcdcc,
+    0xf3a8fae5, 0x19d731f5, 0xdf863966, 0x7635b5f2,
+    0x36d4f0b2, 0xbe24024e, 0x51f57cda, 0x9241c870,
+    0x68895578, 0x74f59766, 0x5fbda11c, 0xb818f7d7,
+    0xf35d31b8, 0xe4e576ee, 0xbe1a8a54, 0xe6c59c9c,
+    0x54d5b539, 0xdca35f5b, 0x19eba0ec, 0x4fba2f04,
+    0x0df76dfc, 0x05d5b057, 0x36784885, 0x5b43e337,
+    0x14285276, 0x4561194e, 0x103a82ae, 0x9c7b625a,
+    0x9d96b6f3, 0xa4fd5883, 0x20585c48, 0x94c67d0d,
+    0x9ce050d2, 0xd0b5165e, 0x63a0bd8e, 0xf9cd1ece,
+    0x1584115a, 0x5a662320, 0x63e96e07, 0x7818aac2,
+    0x6e71233d, 0x1fd178d4, 0x79f16ec9, 0x82f84202,
+    0x39d8be98, 0x15723245, 0x48ce0075, 0x801ead46,
+    0x69e8dd35, 0xe5d94c2a, 0x6abb1b97, 0x20762ad6,
+    0x5e0df657, 0xf7f9a887, 0x20ffb759, 0xbb52002c,
+    0xa488ebeb, 0xac4eb608, 0x2dd6fc64, 0x67763775,
+    0x31961884, 0xcd2edeb2, 0x275aed6f, 0x90d87287,
+    0x2e0f651a, 0xf14b5cac, 0x6bc86e79, 0xcd5ea86c,
+    0x322ae237, 0x7ece1ef2, 0x45abb79e, 0x5a1b6a68,
+    0xe3aa633f, 0x9f471388, 0x73ac0258, 0x32ef97ee,
+    0xe7a98b7a, 0x3feb205f, 0x5466aca4, 0xbf65921c,
+    0x977da54a, 0xeb27e06f, 0x44bd2376, 0x78e9dd9b,
+    0x0c426ef0, 0x6ba253ff, 0x1ea0144d, 0x6099a85b,
+    0x1f0de3db, 0x15e925f7, 0x1e172b91, 0x8a9d83ab,
+    0x0948df11, 0xc4338ceb, 0x3d13d77b, 0xc4ba859e,
+    0x601c45a4, 0x2b7a4cfd, 0xd6f42cb0, 0x03827c56,
+    0xcbe180ef, 0x8ac33028, 0xdd3a5aea, 0x772c2d5d,
+    0x44884fa7, 0xb37de9c0, 0x9e7fba9d, 0x761f99f1,
+    0x118f7fcc, 0x7bd6346d, 0xa5c85359, 0xe09d8dae,
+    0x6034a867, 0x4af20a35, 0xe213d5b5, 0x83678e65,
+    0x7fa12f26, 0x881bf834, 0xd7a898f9, 0x2e00d34d,
+    0xadfd0f9f, 0x64f62e57, 0xeb94a4e6, 0x2741735d,
+    0xfdd7bf3d, 0x0bb5d428, 0x04c6cf8e, 0x7c91f2e2,
+    0x862dafe0, 0xe2bc5ef5, 0x1cf8983f, 0x48fb28fb,
+    0xf3725287, 0xfceacf3c, 0x9c97d1b6, 0x244aa0f2,
+    0x74cd0c3d, 0x62def4c1, 0x5389a927, 0x9213a193,
+    0xfbccaf62, 0xe0c52a28, 0x2f960d1e, 0x261fdc3a,
+    0xa4011e50, 0x8cba98a3, 0xc1ee67fd, 0x8bdc9bd1,
+    0xd2ba1d9a, 0x2ff19168, 0x2c893f34, 0x465b9763,
+    0xac4a2241, 0xdabab40a, 0x848d8ed7, 0x32e0c7db,
+    0xe037749b, 0xa806fe6d, 0xfd392283, 0x54c23f8b,
+    0xddff2a30, 0xbc3cf4b2, 0xfa60ba33, 0xa9bba869,
+    0x0ab138e4, 0xd0a75765, 0x83a03739, 0xed1e0b96,
+    0x7b2a9c07, 0x21d68bd2, 0x1c74b719, 0x63eaac88,
+    0xea824a44, 0x3f1e946d, 0xaa660153, 0x30d73746,
+    0x25019ec8, 0x93a60137, 0xebd12222, 0x2a97f7a8,
+    0xca0d18f0, 0x60a7b913, 0xe208502f, 0xf7f99b2e,
+    0xa111ffab, 0x17977781, 0xa1d5ac7b, 0xdeb44610,
+    0x53415252, 0x00000000, 0x091807da, 0x000006fa,
+    0x0bd03d37, 0x00000001, 0xffffffff, 0x00000c10,
+    0x00000c40, 0x46363030, 0x36335041, 0x00000000,
+    0xa8502cf0, 0x6b8ae36f, 0xcc201a00, 0xf99bd698,
+    0xbaa54ce5, 0xd26c6c64, 0x6586a335, 0xdf114ce6,
+    0x65768732, 0x0c9fff59, 0xf0c87c99, 0x3cb93d44,
+    0x776f6f6a, 0x4cd46553, 0x3b5548de, 0xba94bd6d,
+    0xacfdae04, 0x01d0ed9a, 0x2b51dcbb, 0x0e88b2c0,
+    0x0a87b9bd, 0x7fdafd01, 0x2b2114a4, 0x094f0a66,
+    0xa19ef4ff, 0xf00fc22f, 0x0a791589, 0x14b0605b,
+    0x65c880ce, 0x98a25bd3, 0xc46bcf0f, 0x23b28754,
+    0x9d5b0d0a, 0xc7b95ff1, 0x4b559af5, 0x2c972fb7,
+    0x24c7393a, 0x50953092, 0xcdfbb400, 0xd8b74e66,
+    0x167c8540, 0xe5f33cf3, 0x6f06bece, 0x67853c91,
+    0xec256024, 0x4321a8d7, 0xdf8db159, 0xb3c4ea19,
+    0x49c55dbb, 0x6cd0893f, 0x24926b88, 0x8b6d8c1e,
+    0xcbc1ca74, 0x0d97abf7, 0xbd0683e5, 0xfbd070ae,
+    0x2d86f2ba, 0xdf2d5df1, 0x1c94ac1d, 0xce105cc6,
+    0x707d966a, 0x425adf11, 0xd5437db4, 0x9439e46c,
+    0xf491c327, 0xa264301e, 0x74f59c4c, 0x4fd8cd7d,
+    0x4d2ee13b, 0xeedc9b07, 0xb48c496e, 0x0a9a158b,
+    0xe2aa1f80, 0xe56e1be4, 0x601147a5, 0x9e8e1a67,
+    0xe311dea5, 0x0e787f57, 0xe6d48d91, 0xfc5efa36,
+    0x8d740ced, 0x626aa6ec, 0xfa47f6c6, 0x78236dbc,
+    0xac414eda, 0xbe9b7c3f, 0x922aa24c, 0xe824c36b,
+    0x4bf0a6ea, 0x4650f510, 0xe14ea433, 0x8a863587,
+    0x99f2e00c, 0xace2241e, 0x673a6a21, 0xeacd0611,
+    0x1d5d9f26, 0x63542bdc, 0x19769443, 0x83fb04f6,
+    0xd2dba174, 0x41fc8e8e, 0xb753a248, 0xbe7f5d53,
+    0x97bd16c8, 0xb6e3ea74, 0x10a04714, 0x678ba0fe,
+    0x41903bb6, 0xdc3f69f5, 0x69c0e20e, 0xa3857a0e,
+    0xa66aec62, 0x4f1129d4, 0x39bf5e5c, 0x6566814d,
+    0x6ebc5d8d, 0x74fab02e, 0x6ce9ff42, 0x20dd4b0d,
+    0x89a915bc, 0xdb86b288, 0xe6a2f5c0, 0xd26fa8d8,
+    0x8ce2b6ef, 0xb38cb16c, 0x7e187321, 0xe9057cf7,
+    0xfeff6963, 0xafcbd93d, 0x1ac7600e, 0xf953ad97,
+    0xdd8daaa5, 0x24ffd3a3, 0x6a87f2e0, 0xa5a876ae,
+    0xbe7ec94d, 0x630e9bdd, 0x14cf97ff, 0x0ad023f8,
+    0xafc7d6b6, 0x01d9c914, 0xcaa89ce8, 0xb87471ee,
+    0xf7a6722f, 0x37e1c449, 0x16efc69c, 0x6b5fd873,
+    0x0cb4dbf5, 0xd7e3e2fc, 0x1b980086, 0x3fcc2b9b,
+    0xef724017, 0x6ab5078a, 0x9c469135, 0xda49a6d8,
+    0x94bd4cd4, 0x5ee98e66, 0x4bb9cd31, 0x96bb17de,
+    0x3796eef6, 0x0a0cdc6f, 0x5855dd79, 0x21f4df2a,
+    0x70fcf480, 0x1e408673, 0x2c9a1e7c, 0xd8281ab2,
+    0xd2251523, 0xc207118f, 0xb520e691, 0xf7be5cd0,
+    0xae7af3ad, 0xd8bd2853, 0xed06f5e7, 0x70e4318d,
+    0xd949fff5, 0x84a7dca6, 0x54116bcb, 0xe38fab7c,
+    0x41f88f1a, 0x148f2a61, 0x6598203c, 0xf3df679c,
+    0xa47d2d48, 0x6ebd84aa, 0xca409338, 0x5ea735c7,
+    0x8f5902a3, 0x486b9a72, 0x2a6c9f7a, 0x4f58af16,
+    0x8e589cbd, 0x847b026e, 0xeb883553, 0x9bd04361,
+    0xdf75294b, 0x5701b848, 0x8e4c290e, 0x84ae09a2,
+    0x7c2e5310, 0x1f1e3351, 0x57464eba, 0x2f2bd882,
+    0x55312151, 0xd699d4a8, 0x86c0cb2a, 0xc18625d5,
+    0x01e34f5f, 0xdd71a9b5, 0x00d1404c, 0x478a8fdd,
+    0xaca315cd, 0x08c2bb61, 0xe1e95f74, 0x5c0f2e74,
+    0xc5b86ecd, 0x5efba52e, 0x27162c32, 0x2cd364e0,
+    0x7c2ff4dd, 0x20afee39, 0x01f06c32, 0x5705321c,
+    0x721e9a19, 0x0406919f, 0x793ddfdb, 0x34ad2684,
+    0xb870a1c0, 0x12723655, 0x8f3a0553, 0x1eb77d55,
+    0x31777ded, 0x80d06c75, 0x9e0f8431, 0x289bd541,
+    0x742e6c03, 0xd9d32028, 0xb7891977, 0xaddc8f96,
+    0x1815c705, 0x7c50fb3f, 0x72e1a6d5, 0x58a49102,
+    0x94734a5a, 0xf1431853, 0xcb403be0, 0x80ff034c,
+    0x1cca1d4c, 0xa451b20a, 0xcfff97a1, 0x6897d11a,
+    0x153fe0f9, 0x6747b5df, 0x3a88bcef, 0x6648176b,
+    0x7986c1d7, 0x3f2d7a08, 0x8ea0db0e, 0xf0f57877,
+    0x0ed1edbf, 0x95158803, 0x0425f867, 0x79237bc3,
+    0x28ce7bcc, 0x60f311a5, 0xc7ba09fb, 0x55596285,
+    0xc724ebe4, 0xeac78d31, 0x3e6c778e, 0x05252503,
+    0x3dcdcb51, 0x78c59d5c, 0xa3dee354, 0x52b19d1a,
+    0xfca398b0, 0x63f65f9d, 0xc9fc4fa4, 0xd35ebec9,
+    0xa3698241, 0x05d0e962, 0xf7526d10, 0x7777b4e4,
+    0x72482300, 0x96d42113, 0xce18adb9, 0x0f6fae9b,
+    0xbd737b23, 0x2f327586, 0x456e2db2, 0xe8bacf5c,
+    0xa3333916, 0xb1045776, 0xe831b66b, 0x28c002f1,
+    0x6907e87b, 0xd44c8009, 0xb8bfbd22, 0x5f11a712,
+    0xb99ed38c, 0xf14ef1bf, 0xa50cffec, 0x3ac7cc61,
+    0x967864d6, 0x0f4dd3f2, 0x9a52c6e0, 0x4622af4c,
+    0x8c5fe79d, 0x1f5aaf51, 0xb379d3fc, 0x06f5485c,
+    0xb46f53fc, 0xfb7b867e, 0x4fd79268, 0xb426ba21,
+    0x3bd32579, 0xeccf15e1, 0xdbf2585f, 0x38dc054a,
+    0xf66e29ce, 0x93d218ef, 0x38a61bee, 0x5d764b3b,
+    0x698c1bee, 0xd1f1dcca, 0xcb4d774f, 0x7ae6113e,
+    0xbc46ab5d, 0x7cea59f7, 0xef726f3c, 0x86e552c8,
+    0x54b5c263, 0xbb9f213c, 0xb0ec7aee, 0xae412550,
+    0x7d672e4c, 0x479482d1, 0xbe984fd4, 0xbb40b4e9,
+    0xce460f5b, 0xc25d2d8e, 0x14d43871, 0xc622459e,
+    0xd25cdf24, 0x4cfc08fe, 0x6e66c76d, 0x6163f5e5,
+    0x590ef352, 0x38dd5eee, 0x5b56b3c0, 0xbf7a708f,
+    0xd11ce5b9, 0x46fe1639, 0x87e53fae, 0x52b6d358,
+    0x32d6eb0b, 0x2c8d0693, 0x7b823fba, 0x1743a83d,
+    0x89ec17f7, 0x74679c91, 0x14768344, 0xf27ab26f,
+    0xcafbebd7, 0xb996128f, 0xef5940d8, 0xf3d2817c,
+    0xbfa77515, 0x223a22a1, 0xc301ff17, 0xfb63edb7,
+    0x4d0b235a, 0x9dbd7318, 0xf165ef57, 0x872805e4,
+    0x78fbcb1b, 0x8715e546, 0x909b519b, 0x073ebe68,
+    0x520c18f5, 0x75d543ef, 0xfffd247f, 0xc51faa72,
+    0xc3ff9c28, 0x05d95767, 0xf8a8ce29, 0x6c3100df,
+    0x9602b7b5, 0xf1df9514, 0xdfbde49a, 0x63f347c3,
+    0xa3fedee4, 0x5ab74220, 0x9e3ab0fb, 0x6024aa18,
+    0x941b54f2, 0xaf740c6b, 0x07278738, 0xdc9f9f70,
+    0x528d7eb4, 0xb78b4da4, 0x7e0859ca, 0x4d7f2f34,
+    0x4cce084c, 0x1e1eaa38, 0xe237324d, 0x096f11bc,
+    0x8b040823, 0x2a1c921a, 0x13df560f, 0x8d6f9621,
+    0x34ed0c9c, 0x8f52c968, 0x8c079396, 0x5c2d78c5,
+    0xba61f0ba, 0x0d6737a7, 0xc7ac90b5, 0x40711497,
+    0xc610777e, 0x1baf3ab6, 0x2a509778, 0xb64267ae,
+    0xf0292472, 0x316c99d9, 0x2773d52f, 0x31de412b,
+    0x7d7c33d9, 0x5418cbd7, 0x779a60f5, 0x2b6635a1,
+    0x4a7480ad, 0xa91700ed, 0xdd719d72, 0xf4ef7bfa,
+    0xf292f4a7, 0xe20a154c, 0x6980673e, 0xd087d272,
+    0x3f62947c, 0xcf82e629, 0x998f72d1, 0x181537ec,
+    0xec99111e, 0x9ff94a7e, 0x5838ed56, 0x652e00ad,
+    0x63d2e127, 0x291b39ed, 0xe8874f1f, 0x9fcea857,
+    0x4b44e4d7, 0x79facf6b, 0xfa97248d, 0xabf1b436,
+    0x44bf8ca3, 0xa2342483, 0x27b39aae, 0x54ad61e8,
+    0x62aaf9c8, 0xcf1f0e5f, 0x57727cb9, 0x2bbe1a27,
+    0xad813e18, 0xade7e54a, 0x6d9ae354, 0x7dda6e41,
+    0x6b503615, 0xe539a489, 0xacd4cf0c, 0x50b5ee9b,
+    0xe12cd634, 0xdaa2358a, 0xf3ed5c3c, 0xd7bf1749,
+    0xc8953072, 0x8e5cebe6, 0xa89070ea, 0xb8978ab1,
+    0x9bb10556, 0x14552e00, 0x5e3254e6, 0x3749eeca,
+    0xdafe140d, 0xe7ed3e04, 0x5bed7ee9, 0xf9f2b6d0,
+    0x78958f75, 0xe5e5677a, 0x6bd77819, 0x802ca29a,
+    0x90bbda35, 0x1ed94bcc, 0x04d5fd91, 0xb23898df,
+    0xef508485, 0xc2db56db, 0x335a3555, 0xafd667b7,
+    0x2e41b466, 0xd17eb896, 0x98ba5a85, 0x7205a0cd,
+    0xa89f5fe5, 0xbc8082bf, 0x0ea9336d, 0xd5f7695f,
+    0x3df7ae79, 0x0c16a95b, 0x872eca3f, 0x6565c3c6,
+    0xa7c70d84, 0x5a9cfc9d, 0xf9d365e1, 0x83b41c41,
+    0xa361972f, 0xcedd50d9, 0x0dd0ffaf, 0x33beb660,
+    0x6e5f8aae, 0x39d89272, 0x59a2dd37, 0x46b32dd6,
+    0x23d1b438, 0xaed8f126, 0xf56c2494, 0x1be3e72a,
+    0x49559bde, 0x651f3b68, 0xa77ee774, 0xf6ee86d2,
+    0xd6958a8b, 0x12ba080f, 0xce76bd3b, 0xafad53b0,
+    0xe5fb067a, 0x4f4b6149, 0x54215017, 0xad0378e2,
+    0x482d9f3f, 0xfb953d72, 0xd078f21d, 0x8b91bcd0,
+    0xd5eff898, 0x2d47c13a, 0xfc918304, 0x6569bbdd,
+    0xdfccdc07, 0x3f6c1171, 0x0aa3e691, 0x22b945c6,
+    0x123c08b9, 0x3c61ad47, 0xf3684a46, 0x6ddf05df,
+    0x45587657, 0x65d93c69, 0x3028c52a, 0x0f0bc6f9,
+    0x9686fdc6, 0x50c758fe, 0x4fb30ed1, 0xfbc1e704,
+    0xfdb31f63, 0x593a7512, 0x316393b2, 0xc9f4832b,
+    0x4f1a5a37, 0xb1b47d4d, 0x5fcc8ccd, 0xe8069867,
+    0x0e3709c9, 0x09e4cb6d, 0x7a5db9a9, 0x64a714d4,
+    0xbec5c79a, 0x16bea0a5, 0x81666c3d, 0x35f96dea,
+    0x9b6405f0, 0x3ad8a387, 0x8672e95e, 0xf6b43b37,
+    0x8c2a03e8, 0x454073e1, 0x2dcec42d, 0xf78c7e73,
+    0x082676e2, 0x0350e3fb, 0xd8221bde, 0x825a4d19,
+    0xb9fa4b07, 0xb107ffac, 0x2a4b6eea, 0x3e642e4b,
+    0xa7585a91, 0x84610e89, 0x63238347, 0xbbc51fd3,
+    0xfe022393, 0x5ca78d29, 0x817b9406, 0x4e56ceb6,
+    0x41675640, 0x2e7ce351, 0x97409f25, 0xf723c6ec,
+    0x0392c2de, 0xd6a28f3a, 0x78de0130, 0xae0a3790,
+    0xee61980d, 0x7f1bb7b8, 0x1e09abde, 0x978c8936,
+    0x3f389b96, 0xec790b39, 0xf822a35b, 0x8a1d3592,
+    0xdebdb41d, 0x133b9d1a, 0x5883447b, 0xbcf8bb09,
+    0x8fe79675, 0xaa8f1d7b, 0xd017c7b7, 0xcd06e94f,
+    0x8755fc1a, 0xffaa89fa, 0x29be8e81, 0x6fcf52a5,
+    0x55725694, 0x02573e0b, 0x233e87cc, 0x4ef6c107,
+    0x6f903aec, 0xe71d60d1, 0xa043f83c, 0xe5899344,
+    0x40d5ea27, 0xde3a6bd4, 0x22cffa9b, 0xb70a3a9d,
+    0xee1e1fc1, 0x9f304bcf, 0x9a00125e, 0x4fdce973,
+    0x81cfc376, 0xba14685c, 0x1307212d, 0x9d3cb67c,
+    0xcf5174a2, 0xce2df038, 0x3d98a9bb, 0x1e4e0289,
+    0x70370e7a, 0xab7f5a12, 0xd9a73509, 0x84073ecd,
+    0x1640aed1, 0xb129a7e9, 0xfd8d50b7, 0xaa97ef05,
+    0xa398d289, 0x3d0445b0, 0x2a063516, 0x0ac49d0e,
+    0x273b8e5e, 0xad1c3b0a, 0x59c61b56, 0xdf16f4b2,
+    0x55710d7c, 0x4f8a9a78, 0xe9a3e9cc, 0x96c33642,
+    0xc1711c0b, 0x453e85a7, 0x36cb0791, 0xd052b65f,
+    0xd9745f46, 0x720f96c6, 0x112e753a, 0x8e487589,
+    0x040c3d65, 0x1c642c49, 0x59cebaef, 0x3c44c71d,
+    0x416fe930, 0xa2092f52, 0x8b89f343, 0xf44f9656,
+    0x2fe20f9e, 0xbc5acf24, 0x43238ee6, 0x247a5997,
+    0x2f0e3771, 0xc03e76d9, 0xdef328ee, 0xed802543,
+    0x2a32c194, 0x4cd92940, 0x3d9eccbc, 0x9fb7ac0e,
+    0x23e4acff, 0x0f6ef7cd, 0xdfb588d0, 0x2aa0b794,
+    0x7a5d022a, 0x4356c9b3, 0x97281179, 0x41337e53,
+    0x76790819, 0xb9a5ca77, 0xaf1a9b2a, 0x1a655dfb,
+    0x6b106bc8, 0xee6fcab5, 0xe16c7aac, 0x45cb5be6,
+    0x280d9a95, 0xf2ddc81b, 0x9e1f01e0, 0x1148cf1d,
+    0xf483fc39, 0x3a66021c, 0x1057a22c, 0xa0685244,
+    0x1e8a55bc, 0x0390fe02, 0x76c29392, 0x53c53e08,
+    0xa733d7a2, 0xcb877f82, 0x4fd82ea5, 0x53cb96f3,
+    0x4547075d, 0x41c477e8, 0xb0912c69, 0x57ed6e48,
+    0x3e743d6c, 0x882451c7, 0xc868cedd, 0xb3fae605,
+    0xd81848cb, 0xf3b16ab0, 0x5f3c7494, 0x4fca84d3,
+    0x621cafcb, 0xa7225d72, 0x83596120, 0xc8f57258,
+    0x5b443741, 0x0858ebb9, 0xa7392619, 0x26c71263,
+    0xdfac85c7, 0x95929d75, 0x2a082fe4, 0xb91c4054,
+    0x2b1a13b2, 0x717e3a2c, 0xfe2165ed, 0x1c5b1653,
+    0x9ab498cd, 0x3b3d437a, 0xe9c737d3, 0xfd071595,
+    0x638c4625, 0x997ec96b, 0xa4b0d070, 0xe459568c,
+    0x53415252, 0x00000000, 0x091807da, 0x000006fa,
+    0xd43a9824, 0x00000001, 0xffffffff, 0x00000940,
+    0x00000970, 0x46363030, 0x36335041, 0x00000000,
+    0x302b7fb9, 0x51c322f3, 0x1481e6b5, 0x9950f1a5,
+    0x27048310, 0xb3895c51, 0x5a93c4a9, 0xeb6c4601,
+    0x95b0f2ff, 0x99ff6dc9, 0x83843695, 0xb687e255,
+    0xa3efa9f1, 0x23d98810, 0x846ac2d3, 0x1c9d6010,
+    0x6715bfdc, 0xa789fab9, 0xe56a1d09, 0x0eeb0427,
+    0x9ed0a3a7, 0x45ec7559, 0x0c2eb033, 0x17f146dc,
+    0x30c35795, 0x37a56765, 0x66b11205, 0x5471a208,
+    0x5a0049b8, 0xc008aca5, 0x29ee84fb, 0x66e3303d,
+    0x101656d6, 0x2e7de920, 0x673cabfd, 0xf05d1c06,
+    0x64c507f6, 0xd823cbe0, 0x7e7f4183, 0x04cad122,
+    0x747e3ba9, 0x3226c602, 0x7dc01760, 0xce634320,
+    0x84f55355, 0x1c411f23, 0x6972e335, 0x06f74042,
+    0xa8006f71, 0xfeed7d7e, 0x3f09abbf, 0x6a1a8c7f,
+    0x0d1b730c, 0x5c73a586, 0x9d73ed26, 0xe43c786a,
+    0x1da597e3, 0x34c8f323, 0x447d5fb3, 0x9976957d,
+    0x2c5df47b, 0xf19a1bc3, 0xe53b3cbe, 0xf0a8e170,
+    0x11f0f112, 0x60e00900, 0xc4014477, 0xcbbda9cf,
+    0x478c7d43, 0x0c76da66, 0x54f59535, 0x3a310af5,
+    0x81a2e87b, 0xae577790, 0xc610b904, 0xaa7afec7,
+    0x0ba491df, 0xc44ac7ea, 0x055551b0, 0x967834ff,
+    0x46075ceb, 0x3f0d8a90, 0x6336f1f4, 0x638e85be,
+    0xdbc8df61, 0x0112c46c, 0x94aa12ed, 0xe1814406,
+    0xcb48defa, 0x4c5543ca, 0x756f2306, 0xd7a66dd7,
+    0x48262543, 0xece84d6d, 0x6addde77, 0x8e5045a5,
+    0x94761706, 0x2a8f98ff, 0x14898b09, 0xc5111544,
+    0x60c93fc7, 0x6bea5ad2, 0x81282ca0, 0xe34f2730,
+    0x9013ce09, 0xebe061d9, 0x975eb536, 0xadcd9034,
+    0x257fc5a9, 0xffc3bd52, 0x1eadf9ba, 0x0bd81a5c,
+    0xea0c52f9, 0x8347a620, 0x78663976, 0xccaa6aec,
+    0x2bd641d4, 0xc3dcc4dc, 0x55e5296d, 0x9e94bfe1,
+    0x746c3a01, 0x99f0dcea, 0xf52657aa, 0x3622ceb3,
+    0xa95f8c65, 0x8eaaee04, 0xd71aea04, 0xfcfd6e78,
+    0x7984686c, 0xe40a8dbf, 0xf50ee2e9, 0x93eb96c1,
+    0xe834ee5b, 0x5d05b60b, 0x20c10cea, 0x0a8c2645,
+    0x155a6187, 0xde1aedae, 0x7204cf15, 0xe85373e4,
+    0xe9f93d4a, 0xc7531d3a, 0x5c535875, 0x46ec1ae6,
+    0x6aeea9bd, 0x871bb354, 0x1ab2be63, 0xf8dad26c,
+    0x7b04e772, 0x48564a81, 0x742d28ba, 0x6e698de4,
+    0xa0779db3, 0x1ce0c3d7, 0x237cb6b0, 0xf286fe37,
+    0x781af9aa, 0xf4d61b0b, 0xe26b7572, 0x51f38cb3,
+    0x604873cb, 0x693a158f, 0xb2a0b427, 0xa6cf762b,
+    0xe91831d4, 0x0376bf4b, 0x0ea5b667, 0x830b103e,
+    0x25a8dd84, 0x21e82db9, 0x6d4c0e5e, 0xfb767d16,
+    0x4b883e4b, 0x3de33b14, 0xc9490454, 0x33d61eb4,
+    0xd0197448, 0x940e34a4, 0x8c48a3b1, 0x3456c76f,
+    0x92535ef7, 0x95328e66, 0x8882cce2, 0xce2b761b,
+    0x729cf0e7, 0xa892dd65, 0x804de33d, 0x1549715e,
+    0x8c819f7a, 0x982d9d26, 0x05314c31, 0x2ea19906,
+    0xf48db2da, 0xd1b20b93, 0x2bbaea99, 0x4289b538,
+    0x1352afb3, 0x15aa3a0a, 0x3b80f3f5, 0xc1a1719c,
+    0x132c9711, 0x46fd6ca8, 0x771b91c5, 0x09414702,
+    0x9a9fb8d6, 0xff2bc606, 0xb6214f8a, 0x74dacacf,
+    0x513c4dd5, 0x137fa66c, 0x503d5d37, 0xe024c0da,
+    0x793e186f, 0x31c2bf95, 0x320c616a, 0x83719c1d,
+    0xde0d6e00, 0x9409b2a0, 0xe213fae2, 0x21731821,
+    0x83f51eb3, 0x3cb2eab5, 0xd9c401d3, 0x8d5379ac,
+    0x624189bb, 0x5233e883, 0x1f3d0c02, 0x3b46edc3,
+    0xb47d4661, 0xff867384, 0xf4daa252, 0xfc55fa25,
+    0xb465352e, 0xe1ff2a20, 0x438427df, 0x8cd561f1,
+    0x8c2debb1, 0xf89d5e68, 0x74015f75, 0xa5ea69fa,
+    0x0197a406, 0xbc60439a, 0x32244a3c, 0x4c0b5007,
+    0x61d1138d, 0x024a59f1, 0x305fe9cc, 0x724833dc,
+    0xcbae0bea, 0x8de58519, 0x62968adc, 0xadd0011c,
+    0xc5b23595, 0x5b3990c9, 0xd3c64ecc, 0xb5d33759,
+    0x054c797b, 0xc172220c, 0xda29fe07, 0x7f450ebf,
+    0xec12a33e, 0x86d9bbb3, 0x78bffba7, 0x6a183c16,
+    0x3cdb717b, 0x601e0c7f, 0xcf945c26, 0x073e7331,
+    0xdebd7ad0, 0x62879d5c, 0xe0273347, 0xa2ff18e4,
+    0x78a14f44, 0x20728f07, 0x25cfa3d5, 0xd699e2a7,
+    0xc729bf4e, 0x9250bd92, 0xbabf3a88, 0xf69d91ac,
+    0x0de005b2, 0xee6c6551, 0xf3ec51af, 0x0d4ab84f,
+    0x85b7f548, 0xa0dcf7ae, 0x55efb6a5, 0xbcc9fdb5,
+    0xe789546e, 0x8a209948, 0xb49fc3dd, 0x945fd8f7,
+    0x9c2ab04e, 0x17625832, 0x18253aab, 0x26e3b5fe,
+    0xd03ebf0d, 0xe5f8b8e4, 0xcdf3ef2f, 0x4024ca62,
+    0xd3436616, 0xd19b1010, 0x7e53746c, 0xbaea2597,
+    0xdd72726c, 0xb5a6a4c4, 0x348efd94, 0xba4d3a94,
+    0x3d736b7c, 0xd32fd9e8, 0x98624886, 0xeaab1e7d,
+    0xeec8edc6, 0x51dacdff, 0xf7359960, 0x221caa31,
+    0x34fb3350, 0x794d034c, 0x6aef3d76, 0xc925c505,
+    0xf752c1ad, 0x04b61fde, 0x7b42ef68, 0x1a119091,
+    0xe21077a2, 0xc0c21dfb, 0x480cee09, 0x70144e31,
+    0x49d345b9, 0xb3fe6f47, 0x11d12867, 0xe99898c6,
+    0x6e54b4fd, 0x5f8d169c, 0x93e707b9, 0x1a90974c,
+    0xd6a685e4, 0x6c20c321, 0x29f12f73, 0x12e54190,
+    0x04de2470, 0x6dbb24bb, 0x7f0fd71c, 0xd5e2c954,
+    0x7d93c73a, 0xd2a2c48d, 0x61e2db8d, 0x1a192d47,
+    0xc2d8d438, 0x5e779066, 0xc4bcc619, 0x06f872ef,
+    0xf3401439, 0x573ebd1b, 0x61896e22, 0xde431aef,
+    0xbad386d8, 0xf54ca23b, 0x57d8016f, 0xd98e33ac,
+    0xc5f29f61, 0x85217cb1, 0x250a23ef, 0x16c2d7ce,
+    0x8b8b0207, 0xaeaf1661, 0x8c645ab3, 0x10692f9a,
+    0x84845cb2, 0x3809ed87, 0x958b72cf, 0xfdc465f9,
+    0x167924f4, 0x79b72fd3, 0xd53e01b8, 0x878c0bc7,
+    0x444d821d, 0xb2329171, 0x68dae31b, 0x6dd25eb0,
+    0x876262cc, 0x600fcaf3, 0xa26397e5, 0xab3b5cd5,
+    0x11f6df26, 0x3b503f54, 0xfd28517b, 0xac2c6723,
+    0xf189feec, 0x6c0eabe7, 0xc3b57dd3, 0x9383ffbc,
+    0xaff39d18, 0x4dae936e, 0x8806e540, 0xd956dfe9,
+    0x7726c523, 0xe20d141f, 0x75249f0c, 0x641c7ecf,
+    0x4d75cad2, 0x5e2097c6, 0xffdba551, 0xf97adab1,
+    0x8d86a099, 0x4ce7dafa, 0xc4bf244c, 0xbd5ab78b,
+    0x9060c834, 0x4f0533da, 0xeee0c724, 0x39963d31,
+    0xcde4a77c, 0xf2222170, 0x00675c98, 0x72b6807a,
+    0xfceec299, 0xb4bfd75f, 0x82385beb, 0x8a4fa5e6,
+    0x1f4d790b, 0x8cb998f6, 0x5e41077c, 0xbdb77edc,
+    0x5b885781, 0xdcd539a0, 0x50f70de2, 0xf72c206e,
+    0xd47a8c39, 0xc8c84742, 0x4f5e1cde, 0x8ec26342,
+    0x45add698, 0xc0bd2b6d, 0x10096f65, 0xc7e30310,
+    0x1c951782, 0x37b5edea, 0xe10aea7f, 0xf40d763c,
+    0x01a93a40, 0x197d0a4b, 0x3d41eed5, 0xe9beb9d6,
+    0x1d9247a4, 0xeafe224c, 0x2f2578d5, 0x45eb10a4,
+    0xb6b22e2b, 0xef55f252, 0xb4e224e4, 0x067dcb26,
+    0xb6d0b2a3, 0xfd8a0221, 0x049bbf33, 0x70752994,
+    0xf75fd79b, 0x34fcb9d9, 0x90ca2832, 0xf1c767ca,
+    0x387d06cd, 0x9d5bfdfc, 0x45fb1391, 0xffbf1a8f,
+    0xa7713b73, 0x04b45260, 0x41f7aadf, 0x4e9ab87d,
+    0x26cfd8fc, 0x4ae2842a, 0x00b21491, 0x8e41fff9,
+    0x931d987b, 0x1780ad94, 0x74d9d450, 0x6b4e7b86,
+    0xd290203b, 0x2677caa9, 0x962f8e81, 0x2ed26089,
+    0x14e26f42, 0xeb70b144, 0xa095d8c1, 0x6b572c29,
+    0x78fbacf2, 0x5cdc5cfb, 0xfae86706, 0xddda5706,
+    0xaa767744, 0x7493a4a2, 0x0e9f6b3f, 0x9806a4df,
+    0x10e4c5d5, 0x9b49682a, 0xcb1d045c, 0x0b93aa0f,
+    0x9204696b, 0x82d18f87, 0x1551957c, 0x5410f2ed,
+    0xb937ab2e, 0xaaf40b54, 0x2b9d4857, 0x50231070,
+    0x49ee3994, 0xceaa9dbb, 0x9bd8c899, 0xe9605a77,
+    0xfd88758b, 0x6464201d, 0xa0605f2c, 0xc54d1473,
+    0x30f678bd, 0xe07ade92, 0x315e83b4, 0x9f0e9866,
+    0x6861b81f, 0xe3dbc8c2, 0xd67d8c2d, 0x27ffa228,
+    0x25727f2b, 0xc6637d9b, 0x455637b4, 0x5aabdb00,
+    0xb74a792c, 0x5bc1a7a8, 0xcbb106d8, 0xd7088b31,
+    0xefec63ed, 0x5fcb7619, 0x79b5006e, 0x46de8644,
+    0xdc61db98, 0x7701dca1, 0x1a9622f6, 0x6d192615,
+    0xc380d47a, 0x10685fa3, 0x1f7fc304, 0x06d3796a,
+    0x345013f3, 0x4c2db462, 0xddab6807, 0xf2525b65,
+    0x086d312b, 0x62df52a6, 0x0903ce35, 0xf526c030,
+    0x58ad7ac0, 0xf188c61f, 0x09869aa0, 0x76ae266b,
+    0xe352afc2, 0xa5f2f582, 0x5ec4d829, 0x78fbae90,
+    0xfb64e6ea, 0x96f43d96, 0x735098d0, 0x45006937,
+    0xb8c64d9d, 0xdc1eacc8, 0x48674e13, 0x809f1e57,
+    0x3481a112, 0xe97aa223, 0xd9609801, 0x120265b2,
+    0x12211b6f, 0x7a930f99, 0x10d1fa9b, 0x69413983,
+    0x72c88496, 0xf6bd37de, 0x397c05bf, 0x69cf3d17,
+    0x2472b3e5, 0x6534bde0, 0x175c0e03, 0xfd31a289,
+    0xe4d5d467, 0x933c0637, 0x14547ff0, 0x63dddc17,
+    0x734f0426, 0x1b7d4414, 0x1d61e181, 0xa9bb645b,
+    0xe33daddd, 0x0f3fd487, 0xb36f4aef, 0x042e3609
+};
diff --git a/src/devices/dram/dram.h b/src/devices/dram/dram.h
new file mode 100644
index 0000000..d79cc52
--- /dev/null
+++ b/src/devices/dram/dram.h
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRAM_H
+#define DRAM_H
+
+#include <stdint.h>
+
+/* DRAM type, byte 2 of spd */
+#define DRAM_TYPE_UNDEFINED             0x00
+#define DRAM_TYPE_FPM_DRAM              0x01
+#define DRAM_TYPE_EDO                   0x02
+#define DRAM_TYPE_PIPELINED_NIBBLE      0x03
+#define DRAM_TYPE_SDRAM                 0x04
+#define DRAM_TYPE_ROM                   0x05
+#define DRAM_TYPE_DDR_SGRAM             0x06
+#define DRAM_TYPE_DDR                   0x07
+#define DRAM_TYPE_DDR2                  0x08
+#define DRAM_TYPE_DDR2_FBDIMM           0x09
+#define DRAM_TYPE_DDR2_FB_PROBE         0x0a
+#define DRAM_TYPE_DDR3                  0x0b
+
+/* Module type (byte 3, bits 3:0) of SPD */
+#define DIMM_TYPE_UNDEFINED     0
+#define DIMM_TYPE_RDIMM         1
+#define DIMM_TYPE_UDIMM         2
+#define DIMM_TYPE_SO_DIMM       3
+#define DIMM_TYPE_MICRO_DIMM    4
+#define DIMM_TYPE_MINI_RDIMM    5
+#define DIMM_TYPE_MINI_UDIMM    6
+#define DIMM_TYPE_MINI_CDIMM    7
+#define DIMM_TYPE_72B_SO_UDIMM  8
+#define DIMM_TYPE_72B_SO_RDIMM  9
+#define DIMM_TYPE_72B_SO_CDIMM  10
+
+#if defined(CONFIG_DEBUG_RAM_SETUP) && (CONFIG_DEBUG_RAM_SETUP)
+#define printram(x, ...) printk(BIOS_DEBUG, x, ##__VA_ARGS__)
+#else
+#define printram(x, ...)
+#endif
+
+/* Different values for tCK, representing standard DDR3 frequencies
+ * As always, these values are in 1/256 ns units */
+#define TCK_1066MHZ     240
+#define TCK_800MHZ      320
+#define TCK_666MHZ      384
+#define TCK_533MHZ      480
+#define TCK_400MHZ      640
+#define TCK_333MHZ      768
+#define TCK_266MHZ      960
+#define TCK_200MHZ      1280
+
+#define RAM_UNIT (1<<24)
+
+#include <stdint.h>
+
+/**
+ *\brief DIMM characteristics
+ *
+ * The characteristics of each DIMM, as presented by the SPD
+ */
+typedef struct dimm_attr_st {
+	u8 dram_type;
+	u16 cas_supported;
+	/* Number of ranks */
+	u8 ranks;
+	/* Number or row address bits */
+	u8 row_bits;
+	/* Number or column address bits */
+	u8 col_bits;
+	/* Size of module in (1 << 24) bytes (16MB) */
+	u16 size;
+	/* Latencies are in units of ns, scaled by x256 */
+	u32 tCK;
+	u32 tAA;
+	u32 tWR;
+	u32 tRCD;
+	u32 tRRD;
+	u32 tRP;
+	u32 tRAS;
+	u32 tRC;
+	u32 tRFC;
+	u32 tWTR;
+	u32 tRTP;
+	u32 tFAW;
+
+} dimm_attr;
+
+typedef struct ramctr_timing_st {
+	u8 dram_type;
+	u16 cas_supported;
+	/* tLatencies are in units of ns, scaled by x256 */
+	u32 tCK;
+	u32 tAA;
+	u32 tWR;
+	u32 tRCD;
+	u32 tRRD;
+	u32 tRP;
+	u32 tRAS;
+	u32 tRC;
+	u32 tRFC;
+	u32 tWTR;
+	u32 tRTP;
+	u32 tFAW;
+	/* Latencies in terms of clock cycles
+	 * They are saved separately as they are needed for DRAM MRS commands*/
+	u8 CAS; /* CAS read latency */
+	u8 CWL; /* CAS write latency */
+	u8 WR;  /* write recovery time */
+	
+} ramctr_timing;
+
+
+typedef u8 spd_raw_data[256];
+
+/**
+ * \brief Decode the raw spd data
+ */
+void spd_decode_ddr3(dimm_attr *dimm, spd_raw_data spd_data);
+
+/**
+ * \brief Checks if the DIMM is Registered based on byte[3] of the spd
+ */
+int dimm_is_registered(u8 spd_byte3);
+
+/**
+ * \brief Print the info in dimm
+ */
+void dram_print_spd_ddr3(const dimm_attr *dimm);
+
+/**
+ * \brief Read double word from specified address
+ *
+ * Should be useful when doing an MRS to the DIMM
+ */
+u32 volatile_read(u32 addr);
+
+#endif /* DRAM_H */
diff --git a/src/devices/dram/dram_util.c b/src/devices/dram/dram_util.c
new file mode 100644
index 0000000..75913e4
--- /dev/null
+++ b/src/devices/dram/dram_util.c
@@ -0,0 +1,297 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dram.h"
+#include <console/console.h>
+#include <device/device.h>
+
+u32 volatile_read(volatile u32 addr)
+{
+	volatile u32 result;
+	result = *(volatile u32*)addr;
+	return result;
+}
+
+int dimm_is_registered(u8 spd_byte3)
+{
+	spd_byte3 &= 0x0f;
+	if( (spd_byte3 == DIMM_TYPE_RDIMM)
+		| (spd_byte3 == DIMM_TYPE_MINI_RDIMM)
+		| (spd_byte3 == DIMM_TYPE_72B_SO_RDIMM) )
+		return 1;
+	
+	return 0;
+}
+
+void spd_decode_ddr3(dimm_attr *dimm, spd_raw_data spd)
+{
+	int nCRC, i;
+	u16 crc, spd_crc;
+	u8 * ptr = spd;
+	u8 ftb_divisor;
+	u8 ftb_dividend;
+	u8 capacity_shift, bus_width, sdram_width;
+	u32 mtb; /* medium time base */
+	/* Make sure that the spd dump is indeed from a DDR3 module */
+	if(spd[2] != DRAM_TYPE_DDR3)
+	{
+		printram("Not a DDR3 SPD!\n");
+		dimm->dram_type = DRAM_TYPE_UNDEFINED;
+		return;
+	}
+	dimm->dram_type = DRAM_TYPE_DDR3;
+
+	/* Find the number of bytes covered by CRC */
+	if(spd[0] & 0x80) {
+		nCRC = 117;
+	} else {
+		nCRC =126;
+	}
+
+	/* Compute the CRC */
+	crc = 0;
+	while (--nCRC >= 0) {
+		crc = crc ^ (int)*ptr++ << 8;
+		for (i = 0; i < 8; ++i)
+			if (crc & 0x8000) {
+				crc = crc << 1 ^ 0x1021;
+			} else {
+				crc = crc << 1;
+			}
+	}
+	/* Compare with the CRC in the SPD */
+	spd_crc = (spd[127] << 8) + spd[126];
+	/* Verify the CRC is correct */
+	if(crc != spd_crc)
+		printram("SPD CRC failed!!!");
+
+	
+	unsigned int reg, val, param;
+	printram("  Revision: %x \n", spd[1] );
+	printram("  Type    : %x \n", spd[2] );
+	printram("  Key     : %x \n", spd[3] );
+	
+	reg = spd[4];
+	/* Number of memory banks */
+	val = (reg >> 4) & 0x07;
+	if (val > 0x03) printram("  Invalid number of memory banks\n");
+	param = 1 << (val + 3);
+	printram("  Banks   : %u \n", param );
+	/* SDRAM capacity */
+	capacity_shift = reg & 0x0f;
+	if (capacity_shift > 0x06) printram("  Invalid module capacity\n");
+	if (capacity_shift < 0x02) {
+		printram("  Capacity: %u Mb\n", 256 << capacity_shift);
+	} else {
+		printram("  Capacity: %u Gb\n", 1 << (capacity_shift - 2));
+	}
+	
+	reg = spd[5];
+	/* Row address bits */
+	val = (reg >> 4) & 0x07;
+	if(val > 0x04) printram("  Invalid row address bits\n");
+	dimm->row_bits = val + 12;
+	/* Column address bits */
+	val = reg & 0x07;
+	if(val > 0x03) printram("  Invalid column address bits\n");
+	dimm->col_bits = val + 9;
+	
+	/* Module nominal voltage */
+	reg = spd[6];
+	print_debug("  Supported voltages: ");
+	if(reg & (1<<2) ) print_debug("1.2V ");
+	if(reg & (1<<1) ) print_debug("1.35V ");
+	if( !(reg & (1<<0)) ) print_debug("1.5V ");
+	print_debug("\n");
+
+	/* Module organization */
+	reg = spd[7];
+	/* Number of ranks*/
+	val = (reg >> 3) & 0x07;
+	if(val > 3) printram("  Invalid number of ranks\n");
+	dimm->ranks = val + 1;
+	/* SDRAM device width */
+	val = (reg & 0x07);
+	if(val > 3) printram("  Invalid SDRAM width\n");
+	sdram_width = (4 << val);
+	printram("  SDRAM width       : %u \n", sdram_width);
+
+	/* Memory bus width */
+	reg = spd[8];
+	/* Bus extension */
+	val = (reg >> 3) & 0x03;
+	if(val > 1) printram("  Invalid bus extension\n");
+	printram("  Bus extension     : %u bits\n", val?8:0);
+	/* Bus width */
+	val = reg & 0x07;
+	if(val > 3) printram("  Invalid bus width\n");
+	bus_width = 8 << val;
+	printram("  Bus width         : %u \n", bus_width);
+
+	/* We have all the info we need to compute the dimm size */
+	/* Capacity is 256Mbit multiplied by the power of 2 specified in
+	 * capacity_shift
+	 * The rest is the JEDEC formula */
+	/* I am certain it will fit in 16 bits
+	 * Remember, It's in units of 2^24 bytes*/
+	dimm->size =  ( (1 << (capacity_shift + (25-24)) ) * bus_width
+			* dimm->ranks ) / sdram_width;
+
+	/* Fine Timebase (FTB) Dividend/Divisor */
+	/* Dividend */
+	ftb_dividend = (spd[9] >> 4) & 0x0f;
+	/* Divisor */
+	ftb_divisor = spd[9] & 0x0f;
+
+	/* Medium Timebase =
+	 *   Medium Timebase (MTB) Dividend /
+	 *   Medium Timebase (MTB) Divisor */
+	mtb = (((u32)spd[10]) << 8) / spd [11];
+
+	/* SDRAM Minimum Cycle Time (tCKmin) */
+	dimm->tCK = spd[12] * mtb;
+
+	/* CAS Latencies Supported */
+	dimm->cas_supported = (spd[15] << 8) + spd[14];
+
+	/* Minimum CAS Latency Time (tAAmin) */
+	dimm->tAA = spd[16] * mtb;
+
+	/* Minimum Write Recovery Time (tWRmin) */
+	dimm->tWR = spd[17] * mtb;
+
+	/* Minimum RAS# to CAS# Delay Time (tRCDmin) */
+	dimm->tRCD = spd[18] * mtb;
+
+	/* Minimum Row Active to Row Active Delay Time (tRRDmin) */
+	dimm->tRRD = spd[19] * mtb;
+
+	/* Minimum Row Precharge Delay Time (tRPmin)*/
+	dimm->tRP = spd[20] * mtb;
+
+	/* Minimum Active to Precharge Delay Time (tRASmin) */
+	dimm->tRAS = (((spd[21] & 0x0f) << 8) + spd[22]) * mtb;
+	
+	/* Minimum Active to Active/Refresh Delay Time (tRCmin) */
+	dimm->tRC = (((spd[21] & 0xf0) << 4) + spd[23]) * mtb;
+
+	/* Minimum Refresh Recovery Delay Time (tRFCmin) */
+	dimm->tRFC = ((spd[25] << 8) + spd[24]) * mtb;
+
+	/* Minimum Internal Write to Read Command Delay Time (tWTRmin) */
+	dimm->tWTR = spd[26] * mtb;
+
+	/* Minimum Internal Read to Precharge Command Delay Time (tRTPmin) */
+	dimm->tRTP = spd[27] * mtb;
+
+	/* Minimum Four Activate Window Delay Time (tFAWmin) */
+	dimm->tFAW = (((spd[28] & 0x0f) << 8) + spd[29]) * mtb;
+
+	/* SDRAM Optional Features */
+	reg = spd[30];
+	print_debug("  Optional features :");
+	if(reg & 0x80) print_debug(" DLL-Off_mode");
+	if(reg & 0x02) print_debug(" RZQ/7");
+	if(reg & 0x01) print_debug(" RZQ/6");
+	print_debug("\n");
+
+	/* SDRAM Thermal and Refresh Options */
+	reg = spd[31];
+	print_debug("  Thermal features  :");
+	if(reg & 0x80) print_debug(" PASR");
+	if(reg & 0x08) print_debug(" ODTS");
+	if(reg & 0x04) print_debug(" ASR");
+	if(reg & 0x02) print_debug(" ext_temp_refresh");
+	if(reg & 0x01) print_debug(" ext_temp_range");
+	print_debug("\n");
+
+	/*  Module Thermal Sensor */
+	reg = spd[32];
+	print_debug("  Thermal sensor    : ");
+	if(reg & 0x80) print_debug("yes");
+	else print_debug("no");
+	print_debug("\n");
+
+	/*  SDRAM Device Type */
+	reg = spd[33];
+	print_debug("  Standard SDRAM    : ");
+	if(reg & 0x80) print_debug("no");
+	else print_debug("yes");
+	print_debug("\n");
+
+	/* Fine Offset for SDRAM Minimum Cycle Time (tCKmin) */
+	//printram("  tCKmin FTB        : %i \n", spd[34]);
+	/* Fine Offset for Minimum CAS Latency Time (tAAmin) */
+	//printram("  tAAmin FTB        : %i \n", spd[35]);
+	/* Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin) */
+	//printram("  tRCDmin FTB       : %i \n", spd[36]);
+	/* Fine Offset for Minimum Row Precharge Delay Time (tRPmin) */
+	//printram("  tRPmin FTB        : %i \n", spd[37]);
+	/* Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin) */
+	//printram("  tRCmin FTB        : %i \n", spd[38]);
+
+	if(spd[60] & 0x01)
+		printram("  DIMM Address bits mirrorred!!!\n");
+
+}
+
+static void print_ns(const char * msg, u32 val)
+{
+	u32 mant, fp;
+	mant = val/256;
+	fp = (val % 256) * 1000/256;
+
+	printram("%s%3u.%.3u ns\n", msg, mant, fp);
+}
+
+void dram_print_spd_ddr3(const dimm_attr *dimm)
+{
+	u16 val16;
+	int i;
+
+	printram("  Row    addr bits  : %u \n", dimm->row_bits);
+	printram("  Column addr bits  : %u \n", dimm->col_bits);
+	printram("  Number of ranks   : %u \n", dimm->ranks);
+	printram("  DIMM Capacity     : %u MB\n", dimm->size << 4);
+
+	/* CAS Latencies Supported */
+	val16 = dimm->cas_supported;
+	print_debug("  CAS latencies     :");
+	i = 0;
+	do{
+		if(val16 & 1) printram(" %u", i + 4);
+		i++;
+		val16 >>= 1;
+	} while(val16);
+	print_debug("\n");
+
+	print_ns("  tCKmin            : ", dimm->tCK);
+	print_ns("  tAAmin            : ", dimm->tAA);
+	print_ns("  tWRmin            : ", dimm->tWR);
+	print_ns("  tRCDmin           : ", dimm->tRCD);
+	print_ns("  tRRDmin           : ", dimm->tRRD);
+	print_ns("  tRPmin            : ", dimm->tRP);
+	print_ns("  tRASmin           : ", dimm->tRAS);
+	print_ns("  tRCmin            : ", dimm->tRC);
+	print_ns("  tRFCmin           : ", dimm->tRFC);
+	print_ns("  tWTRmin           : ", dimm->tWTR);
+	print_ns("  tRTPmin           : ", dimm->tRTP);
+	print_ns("  tFAWmin           : ", dimm->tFAW);
+
+}
diff --git a/src/devices/smbus/early_smbus.c b/src/devices/smbus/early_smbus.c
new file mode 100644
index 0000000..4583aca
--- /dev/null
+++ b/src/devices/smbus/early_smbus.c
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * @file post_codes.h
+ *
+ * This file defines the implementations for the functions defined in smbus.h
+ * These are a generic SMBUS implementation, which should work with a majority
+ * of chipsets.
+ * They are marked weak so that they can be overridden by the chipset code if
+ * necessary.
+ */
+
+#include "smbus.h"
+
+/**
+ * \brief Brief delay for SMBUS transactions
+ */
+__attribute__((weak))
+void __smbus_delay(void)
+{
+	inb(0x80);
+}
+
+/**
+ * \brief Clear the SMBUS host status register
+ */
+__attribute__((weak))
+void __smbus_reset(u16 __smbus_io_base)
+{
+	outb(0xdf, SMBHSTSTAT);
+}
+
+/**
+ * \brief Print an error, should it occur. If no error, just exit.
+ *
+ * @param host_status The data returned on the host status register after
+ *		      a transaction is processed.
+ * @param loops The number of times a transaction was attempted.
+ * @return	0 if no error occurred
+ * 		1 if an error was detected
+ */
+__attribute__((weak))
+int __smbus_print_error(u8 host_status, int loops, u16 __smbus_io_base)
+{
+	/* Check if there actually was an error. */
+	if ((host_status == 0x00 || host_status == 0x40 ||
+		host_status == 0x42) && (loops < SMBUS_TIMEOUT))
+		return 0;
+	
+	if (loops >= SMBUS_TIMEOUT)
+		printsmbus("SMBus timeout\n");
+	if (host_status & (1 << 4))
+		printsmbus("Interrupt/SMI# was Failed Bus Transaction\n");
+	if (host_status & (1 << 3))
+		printsmbus("Bus error\n");
+	if (host_status & (1 << 2))
+		printsmbus("Device error\n");
+	if (host_status & (1 << 1))
+		printsmbus("Interrupt/SMI# completed successfully\n");
+	if (host_status & (1 << 0))
+		printsmbus("Host busy\n");
+	return 1;
+}
+
+/**
+ * \brief Checks if the SMBUS is currently busy with a transaction
+ */
+__attribute__((weak))
+int __smbus_is_busy(u16 __smbus_io_base)
+{
+	/* Check if bit 0 of the status register is 1 (busy) or 0 (ready) */
+	return ( (inb(SMBHSTSTAT) & (1 << 0)) == 1);
+}
+
+/**
+ * \brief Wait for the SMBUS to become ready to process a new transaction.
+ */
+__attribute__((weak))
+int __smbus_wait_until_ready(u16 __smbus_io_base)
+{
+	int loops;
+	
+	printsmbus("Waiting until SMBus ready\n");
+	
+	/* Loop up to SMBUS_TIMEOUT times, waiting for bit 0 of the
+	 * SMBus Host Status register to go to 0, indicating the operation
+	 * was completed successfully. I don't remember why I did it this way,
+	 * but I think it was because ROMCC was running low on registers */
+	loops = 0;
+	while (__smbus_is_busy(__smbus_io_base) && loops < SMBUS_TIMEOUT)
+		++loops;
+	
+	return __smbus_print_error(inb(SMBHSTSTAT), loops, __smbus_io_base);
+}
+
+/**
+ * \brief Read a byte from the SMBUS.
+ *
+ * @param dimm The address location of the DIMM on the SMBus.
+ * @param offset The offset the data is located at.
+ */
+__attribute__((weak))
+u8 __smbus_read_byte(u8 dimm, u8 offset, u16 __smbus_io_base)
+{
+	u8 val;
+	
+	/* Initialize SMBUS sequence */
+	__smbus_reset(__smbus_io_base);
+	/* Clear host data port. */
+	outb(0x00, SMBHSTDAT0);
+	
+	__smbus_wait_until_ready(__smbus_io_base);
+	
+	/* Actual addr to reg format. */
+	dimm = (dimm << 1);
+	dimm |= 1; /* read command */
+	outb(dimm, SMBXMITADD);
+	outb(offset, SMBHSTCMD);
+	/* Start transaction, byte data read. */
+	outb(0x48, SMBHSTCTL);
+	__smbus_wait_until_ready(__smbus_io_base);
+	
+	val = inb(SMBHSTDAT0);
+	return val;
+}
\ No newline at end of file
diff --git a/src/devices/smbus/smbus.h b/src/devices/smbus/smbus.h
new file mode 100644
index 0000000..820a0dd
--- /dev/null
+++ b/src/devices/smbus/smbus.h
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file post_codes.h
+ *
+ * This file defines the prototypes for several common SMBUS functions
+ * These functions are prefixed with __smbus_ so that they do not conflict with
+ * the dozens of similar (duplicated) implementations in many southbridges.
+ *
+ * As a last parameter, the SMBUS functions take a u16 value __smbus_io_base,
+ * which represents the base IO port for smbus transactions
+ */
+
+#include <arch/io.h>
+
+/**
+ * \brief SMBUS IO ports in relation to the base IO port
+ */
+#define SMBHSTSTAT		__smbus_io_base + 0x0
+#define SMBSLVSTAT		__smbus_io_base + 0x1
+#define SMBHSTCTL		__smbus_io_base + 0x2
+#define SMBHSTCMD		__smbus_io_base + 0x3
+#define SMBXMITADD		__smbus_io_base + 0x4
+#define SMBHSTDAT0		__smbus_io_base + 0x5
+#define SMBHSTDAT1		__smbus_io_base + 0x6
+#define SMBBLKDAT		__smbus_io_base + 0x7
+#define SMBSLVCTL		__smbus_io_base + 0x8
+#define SMBTRNSADD		__smbus_io_base + 0x9
+#define SMBSLVDATA 		__smbus_io_base + 0xa
+
+#define SMBUS_TIMEOUT		(100*1000*10)
+
+/**
+ * \brief printk macro for SMBUS debugging
+ */
+#if defined(CONFIG_DEBUG_SMBUS_SETUP) && (CONFIG_DEBUG_SMBUS_SETUP)
+#define printsmbus(x, ...) printk(BIOS_DEBUG, x, ##__VA_ARGS__)
+#else
+#define printsmbus(x, ...)
+#endif
+
+void __smbus_reset(u16 __smbus_io_base);
+int __smbus_print_error(u8 host_status, int loops, u16 __smbus_io_base);
+int __smbus_is_busy(u16 __smbus_io_base);
+int __smbus_wait_until_ready(u16 __smbus_io_base);
+u8 __smbus_read_byte(u8 dimm, u8 offset, u16 __smbus_io_base);
+
+void __smbus_delay(void);
+
+#if defined(SMBUS_IO_BASE) && (SMBUS_IO_BASE != 0)
+
+__attribute__((always_inline, unused))
+static void smbus_reset(void)
+{
+	__smbus_reset(SMBUS_IO_BASE);
+}
+
+__attribute__((always_inline, unused))
+static int smbus_is_busy(void)
+{
+	return __smbus_is_busy(SMBUS_IO_BASE);
+}
+
+__attribute__((always_inline, unused))
+static int smbus_wait_until_ready(void)
+{
+	return __smbus_wait_until_ready(SMBUS_IO_BASE);
+}
+
+__attribute__((always_inline, unused))
+static int smbus_print_error(u8 host_status, int loops)
+{
+	return __smbus_print_error(host_status, loops, SMBUS_IO_BASE);
+}
+
+__attribute__((always_inline, unused))
+static u8 smbus_read_byte(u8 dimm, u8 offset)
+{
+	return __smbus_read_byte(dimm, offset, SMBUS_IO_BASE);
+}
+
+#endif
\ No newline at end of file
diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
index 7aac1f7..5c23bd0 100644
--- a/src/include/device/pci_ids.h
+++ b/src/include/device/pci_ids.h
@@ -1337,6 +1337,29 @@
 #define PCI_DEVICE_ID_VIA_VX855_VGA	0x5122
 #define PCI_DEVICE_ID_VIA_VX855_VLINK	0x7409
 #define PCI_DEVICE_ID_VIA_VX855_MEMCTRL	0x3409
+/* VIA VX900 PCI IDs */
+#define PCI_DEVICE_ID_VIA_VX900_HOST_BR	0x0410
+#define PCI_DEVICE_ID_VIA_VX900_ERR	0x1410
+#define PCI_DEVICE_ID_VIA_VX900_CPU_CTR	0x2410
+#define PCI_DEVICE_ID_VIA_VX900_MEMCTRL	0x3410
+#define PCI_DEVICE_ID_VIA_VX900_PM	0x4410
+#define PCI_DEVICE_ID_VIA_VX900_TRAF	0x5410
+#define PCI_DEVICE_ID_VIA_VX900_SCRATCH	0x6410
+#define PCI_DEVICE_ID_VIA_VX900_NBRIDGE	0x7410
+#define PCI_DEVICE_ID_VIA_VX900_LPC	0x8410
+#define PCI_DEVICE_ID_VIA_VX900_PEX1	0xa410
+#define PCI_DEVICE_ID_VIA_VX900_PEX2	0xb410
+#define PCI_DEVICE_ID_VIA_VX900_PEX3	0xc410
+#define PCI_DEVICE_ID_VIA_VX900_PEX4	0xd410
+#define PCI_DEVICE_ID_VIA_VX900_PEX_CTR	0xe410
+#define PCI_DEVICE_ID_VIA_VX900_SNMIC	0xa353
+#define PCI_DEVICE_ID_VIA_VX900_PCI_BR	0xb353
+#define PCI_DEVICE_ID_VIA_VX900_VGA	0x7122
+#define PCI_DEVICE_ID_VIA_VX900_VID_DEC	0x9170
+#define PCI_DEVICE_ID_VIA_VX900_HDAC	0x3288
+#define PCI_DEVICE_ID_VIA_VX900_ETH	0x3119
+#define PCI_DEVICE_ID_VIA_VX900_SATA	0x9001
+/* VIA CN700 */
 #define PCI_DEVICE_ID_VIA_CN700_AGP	0x0314
 #define PCI_DEVICE_ID_VIA_CN700_ERR	0x1314
 #define PCI_DEVICE_ID_VIA_CN700_HOST	0x2314
diff --git a/src/include/lib.h b/src/include/lib.h
index b2f38a8..b51911a 100644
--- a/src/include/lib.h
+++ b/src/include/lib.h
@@ -38,6 +38,7 @@ void move_gdt(void);
 /* Defined in src/lib/ramtest.c */
 void ram_check(unsigned long start, unsigned long stop);
 int ram_check_nodie(unsigned long start, unsigned long stop);
+int ram_check_noprint_nodie(unsigned long start, unsigned long stop);
 void quick_ram_check(void);
 
 /* Defined in src/lib/stack.c */
diff --git a/src/lib/ramtest.c b/src/lib/ramtest.c
index 3457210..192d573 100644
--- a/src/lib/ramtest.c
+++ b/src/lib/ramtest.c
@@ -223,6 +223,41 @@ int ram_check_nodie(unsigned long start, unsigned long stop)
 	return ret;
 }
 
+int ram_check_noprint_nodie(unsigned long start, unsigned long stop)
+{
+		unsigned long addr, value, value2;
+	unsigned short int idx;
+	unsigned char failed, failures;
+	uint8_t verbose = 0;
+
+	for (idx=0; idx<0x400; idx+=4) {
+		test_pattern(idx, &addr, &value);
+		write_phys(start + addr, value);
+	}
+
+	/* Make sure we don't read before we wrote */
+	phys_memory_barrier();
+
+	failures = 0;
+	for (idx=0; idx<0x400; idx+=4) {
+		test_pattern(idx, &addr, &value);
+		value2 = read_phys(start + addr);
+
+		failed = (value2 != value);
+		failures |= failed;
+		if  (failed && !verbose) {
+		}
+		if (verbose) {
+		}
+	}
+	if (failures) {
+		return 1;
+	}
+	else {
+	}
+	return 0;
+}
+
 void quick_ram_check(void)
 {
 	int fail = 0;
diff --git a/src/mainboard/via/Kconfig b/src/mainboard/via/Kconfig
index 6980548..48f4055 100644
--- a/src/mainboard/via/Kconfig
+++ b/src/mainboard/via/Kconfig
@@ -9,6 +9,8 @@ config BOARD_VIA_EPIA_CN
 	bool "EPIA-CN"
 config BOARD_VIA_EPIA_M700
 	bool "EPIA-M700"
+config BOARD_VIA_EPIA_M850
+	bool "EPIA-M850"
 config BOARD_VIA_EPIA_M
 	bool "EPIA-M"
 config BOARD_VIA_EPIA_N
@@ -23,6 +25,7 @@ endchoice
 source "src/mainboard/via/epia/Kconfig"
 source "src/mainboard/via/epia-cn/Kconfig"
 source "src/mainboard/via/epia-m700/Kconfig"
+source "src/mainboard/via/epia-m850/Kconfig"
 source "src/mainboard/via/epia-m/Kconfig"
 source "src/mainboard/via/epia-n/Kconfig"
 source "src/mainboard/via/pc2500e/Kconfig"
diff --git a/src/mainboard/via/epia-m850/Kconfig b/src/mainboard/via/epia-m850/Kconfig
new file mode 100644
index 0000000..c0db0a2
--- /dev/null
+++ b/src/mainboard/via/epia-m850/Kconfig
@@ -0,0 +1,47 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011-2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+if BOARD_VIA_EPIA_M850
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select ARCH_X86
+	select CPU_VIA_NANO
+	select NORTHBRIDGE_VIA_VX900
+	select SUPERIO_FINTEK_F81865F
+	#select BOARD_HAS_FADT
+	#select HAVE_PIRQ_TABLE
+	#select HAVE_ACPI_TABLES
+	#select HAVE_ACPI_RESUME
+	#select HAVE_OPTION_TABLE
+	select BOARD_ROMSIZE_KB_512
+
+config MAINBOARD_DIR
+	string
+	default via/epia-m850
+
+config MAINBOARD_PART_NUMBER
+	string
+	default "EPIA-M850"
+
+config IRQ_SLOT_COUNT
+	int
+	default 13
+
+endif # BOARD_VIA_EPIA_M850
diff --git a/src/mainboard/via/epia-m850/Makefile.inc b/src/mainboard/via/epia-m850/Makefile.inc
new file mode 100644
index 0000000..9c6d31f
--- /dev/null
+++ b/src/mainboard/via/epia-m850/Makefile.inc
@@ -0,0 +1,21 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+#romstage-y += ./../../../superio/fintek/f81865f/f81865f_early_serial.c
+
diff --git a/src/mainboard/via/epia-m850/devicetree.cb b/src/mainboard/via/epia-m850/devicetree.cb
new file mode 100644
index 0000000..38ed6c3
--- /dev/null
+++ b/src/mainboard/via/epia-m850/devicetree.cb
@@ -0,0 +1,90 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+chip northbridge/via/vx900		# Northbridge
+	device lapic_cluster 0 on		# APIC cluster
+		chip cpu/via/nano		# VIA NANO
+			device lapic 0 on end	# APIC
+		end
+	end
+	device pci_domain 0 on
+		device pci 0.0  on end		# [0410] Host controller
+		device pci 0.1  on end		# [1410] Error Reporting
+		device pci 0.2  on end		# [2410] CPU Bus Control
+		device pci 0.3  on end		# [3410] DRAM Bus Control
+		device pci 0.4  on end		# [4410] Power Management
+		device pci 0.5  on end		# [5410] APIC+Traffic Control
+		device pci 0.6  off end		# [6410] Scratch Registers
+		device pci 0.7  on end		# [7410] V4 Link Control
+		device pci 1.0  off end		# [7122] VGA Chrome9 HD
+		device pci 1.1  off end		# [9170] Audio Device
+		device pci 3.0  off end		# [a410] PEX1
+		device pci 3.1  off end		# [b410] PEX2
+		device pci 3.2  off end		# [c410] PEX3
+		device pci 3.3  off end		# [d410] PEX4
+		device pci 3.4  off end		# [e410] PCIE bridge
+		device pci b.0  off end		# [a409] USB Device
+		device pci c.0  off end		# [95d0] SDIO Host Controller
+		device pci d.0  off end		# [9530] Memory Card controller
+		device pci f.0  on end		# [9001] SATA Controller
+		device pci 10.0 off end		# [3038] USB 1.1
+		device pci 10.1 off end		# [3038] USB 1.1
+		device pci 10.2 off end		# [3038] USB 1.1
+		device pci 10.3 off end		# [3038] USB 1.1
+		device pci 10.4 off end		# [3104] USB 2.0
+		device pci 11.0 on		# [8410] LPC Bus Control
+			#chip drivers/generic/generic	# DIMM 0 channel 1
+			#	device i2c 50 on end
+			#end
+			#chip drivers/generic/generic	# DIMM 1 channel 1
+			#	device i2c 51 on end
+			#end
+			chip superio/fintek/f81865f	# Super duper IO
+				device pnp 4e.0 off end	# Floppy
+				device pnp 4e.3 off end	# Parallel Port
+				device pnp 4e.4 off end	# Hardware Monitor
+				device pnp 4e.5 on 	# Keyboard
+					io 0x60 = 0x60
+					io 0x62 = 0x64
+					irq 0x70 = 1
+				end
+				device pnp 4e.6 off end	# GPIO
+				device pnp 4e.a off end	# PME
+				device pnp 4e.10 on	# COM1
+					io 0x60 = 0x3f8
+					irq 0x70 = 4
+				end
+				device pnp 4e.11 off	# COM2
+					io 0x60 = 0x2f8
+					irq 0x70 = 3
+				end
+				device pnp 4e.12 off	# COM3
+					io 0x60 = 0x3e8
+					irq 0x70 = 10
+				end
+				device pnp 4e.13 off	# COM4
+					io 0x60 = 0x2e8
+					irq 0x70 = 11
+				end
+			end # superio/fintek/f81865f
+		end # LPC
+		device pci 11.7 on end		# [a353] North-South control
+		device pci 14.0 off end		# [3288] Azalia HDAC
+	end
+end
diff --git a/src/mainboard/via/epia-m850/mainboard.c b/src/mainboard/via/epia-m850/mainboard.c
new file mode 100644
index 0000000..57b12e1
--- /dev/null
+++ b/src/mainboard/via/epia-m850/mainboard.c
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <device/device.h>
+
+struct chip_operations mainboard_ops = {
+	CHIP_NAME("VIA EPIA-M850 Mainboard")
+};
diff --git a/src/mainboard/via/epia-m850/romstage.c b/src/mainboard/via/epia-m850/romstage.c
new file mode 100644
index 0000000..c05f4a2
--- /dev/null
+++ b/src/mainboard/via/epia-m850/romstage.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+  * Copyright (C) 2011-2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Inspired from the EPIA-M700
+ */
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/romcc_io.h>
+#include <arch/hlt.h>
+#include <console/console.h>
+#include <lib.h>
+#include <cpu/x86/bist.h>
+#include <string.h>
+#include <timestamp.h>
+
+#include <console/cbmem_console.h>
+
+#include "northbridge/via/vx900/early_vx900.h"
+#include "northbridge/via/vx900/raminit.h"
+#include "superio/fintek/f81865f/f81865f_early_serial.c"
+
+#define SERIAL_DEV PNP_DEV(0x4e, 0x10)
+
+static inline u64 tsc2u64(tsc_t tsc)
+{
+	return ((u64)tsc.hi << 32) | tsc.lo;
+}
+#define TSC_PER_USEC 1297
+static inline u32 tsc2ms(u64 end, u64 start)
+{
+	return ((u32)(end-start)/TSC_PER_USEC)/1000;
+}
+/* cache_as_ram.inc jumps to here. */
+void main(unsigned long bist);
+void main(unsigned long bist)
+{
+	tsc_t tsc_at_romstage_start = rdtsc();;
+
+	/* First thing we need to do on the VX900, before anything else */
+	vx900_enable_pci_config_space();
+
+	f81865f_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
+	console_init();
+	print_debug("Console initialized. \n");
+
+	vx900_cpu_to_dram_interface_setup();
+
+	/* Keyboard off */
+	//pci_mod_config8(LPC, 0x51, (1<<2)|(1<<0), 0);
+	/* NOT HERE FIXME */
+	pci_write_config8(SNMIC, 0x60, 1 << (30-24));
+
+	/* Be smart. Get this info */
+	vx900_print_strapping_info();
+	/* DEVEL helper */
+	vx900_disable_auto_reboot();
+	/* Halt if there was a built-in self test failure. */
+	report_bist_failure(bist);
+
+	/* Oh, almighty, give us the SMBUS */
+	enable_smbus();
+
+	/* If this works, then SMBUS is up and running */
+	/* dump_spd_data(); */
+
+	tsc_t tsc_before_raminit = rdtsc();
+	/* Now we can worry about raminit.
+	 * This board only has DDR3, so no need to worry about which DRAM type
+	 * to use */
+	dimm_layout dimms = {{0x50, 0x51, SPD_END_LIST}};
+	vx900_init_dram_ddr3(&dimms);
+	tsc_t tsc_after_raminit = rdtsc();
+
+	ram_check(0, 0x80);
+	ram_check(512<<10, 0x80);
+	ram_check(1024<<10, 0x80);
+	ram_check((1<<20) - (1<<10), 0x80);
+	ram_check((1<<24), 0x80);
+	ram_check((512 + 256 -1)<<20, 0x80);
+	//ram_check(988*1024*1024, 0x80);
+
+	print_debug("We passed RAM verify\n");
+	/* We got RAM working, now we can write the timestamps to RAM */
+	cbmem_initialize();
+	timestamp_init(tsc_at_romstage_start);
+	timestamp_add(TS_START_ROMSTAGE, tsc_at_romstage_start );
+	timestamp_add(TS_BEFORE_INITRAM, tsc_before_raminit );
+	timestamp_add(TS_AFTER_INITRAM, tsc_after_raminit );
+	timestamp_add_now(TS_END_ROMSTAGE);
+
+
+	/* FIXME: They no es belong here */
+	u64 start, end;
+	start = tsc2u64(tsc_at_romstage_start);
+	end = tsc2u64(tsc_before_raminit);
+	printk(BIOS_DEBUG, "Before raminit %ums\n", tsc2ms(end, start));
+
+	start = end;
+	end = tsc2u64(tsc_after_raminit);
+	printk(BIOS_DEBUG, "Actual Raminit %ums\n", tsc2ms(end, start));
+}
diff --git a/src/northbridge/via/Kconfig b/src/northbridge/via/Kconfig
index 2c38acf..8a747b9 100644
--- a/src/northbridge/via/Kconfig
+++ b/src/northbridge/via/Kconfig
@@ -4,3 +4,4 @@ source src/northbridge/via/cn400/Kconfig
 source src/northbridge/via/vt8601/Kconfig
 source src/northbridge/via/vt8623/Kconfig
 source src/northbridge/via/vx800/Kconfig
+source src/northbridge/via/vx900/Kconfig
diff --git a/src/northbridge/via/Makefile.inc b/src/northbridge/via/Makefile.inc
index 75cb15b..2e74b61 100644
--- a/src/northbridge/via/Makefile.inc
+++ b/src/northbridge/via/Makefile.inc
@@ -4,4 +4,5 @@ subdirs-$(CONFIG_NORTHBRIDGE_VIA_CN700) += cn700
 subdirs-$(CONFIG_NORTHBRIDGE_VIA_CX700) += cx700
 subdirs-$(CONFIG_NORTHBRIDGE_VIA_CN400) += cn400
 subdirs-$(CONFIG_NORTHBRIDGE_VIA_VX800) += vx800
+subdirs-$(CONFIG_NORTHBRIDGE_VIA_VX900) += vx900
 
diff --git a/src/northbridge/via/vx800/lpc.c b/src/northbridge/via/vx800/lpc.c
index b9941d1..144ede0 100644
--- a/src/northbridge/via/vx800/lpc.c
+++ b/src/northbridge/via/vx800/lpc.c
@@ -375,3 +375,9 @@ static const struct pci_driver lpc_driver __pci_driver = {
 	.vendor = PCI_VENDOR_ID_VIA,
 	.device = PCI_DEVICE_ID_VIA_VX855_LPC,
 };
+
+static const struct pci_driver lpc_driver_900 __pci_driver = {
+	.ops = &vx800_lpc_ops,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_VX900_LPC,
+};
\ No newline at end of file
diff --git a/src/northbridge/via/vx800/vga.c b/src/northbridge/via/vx800/vga.c
index e438012..0bedde0 100644
--- a/src/northbridge/via/vx800/vga.c
+++ b/src/northbridge/via/vx800/vga.c
@@ -126,24 +126,6 @@ static int via_vx800_int15_handler(struct eregs *regs)
 	return res;
 }
 
-#ifdef UNUSED_CODE
-static void write_protect_vgabios(void)
-{
-	device_t dev;
-
-	printk(BIOS_INFO, "write_protect_vgabios\n");
-	/* there are two possible devices. Just do both. */
-	dev = dev_find_device(PCI_VENDOR_ID_VIA,
-			      PCI_DEVICE_ID_VIA_VX855_MEMCTRL, 0);
-	if (dev)
-		pci_write_config8(dev, 0x80, 0xff);
-	/*vx855 no th 0x61 reg */
-	/*dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_VLINK, 0);
-	   //if(dev)
-	   //   pci_write_config8(dev, 0x61, 0xff); */
-}
-#endif
-
 static void vga_enable_console(void)
 {
 	/* Call VGA BIOS int10 function 0x4f14 to enable main console
@@ -152,7 +134,7 @@ static void vga_enable_console(void)
 	 */
 
 	/*                 int#,    EAX,    EBX,    ECX,    EDX,    ESI,    EDI */
-	realmode_interrupt(0x10, 0x4f14, 0x8003, 0x0001, 0x0000, 0x0000, 0x0000);
+	//realmode_interrupt(0x10, 0x4f14, 0x8003, 0x0001, 0x0000, 0x0000, 0x0000);
 }
 
 extern u8 acpi_sleep_type;
@@ -173,7 +155,7 @@ static void vga_init(device_t dev)
 	//pci_write_config32(dev,0x14, 0xdd000000);
 	pci_write_config32(dev, 0x10, VIACONFIG_VGA_PCI_10);
 	pci_write_config32(dev, 0x14, VIACONFIG_VGA_PCI_14);
-	pci_write_config8(dev, 0x3c, 0x0a);	//same with vx855_lpc.c
+	pci_write_config8(dev, PCI_INTERRUPT_LINE, 0x0a);//same with vx855_lpc.c
 	//*/
 
 	printk(BIOS_DEBUG, "Initializing VGA...\n");
@@ -182,27 +164,9 @@ static void vga_init(device_t dev)
 
 	printk(BIOS_DEBUG, "Enable VGA console\n");
 	vga_enable_console();
-
-	if ((acpi_sleep_type == 3)/* || (PAYLOAD_IS_SEABIOS == 0)*/) {
-		/* It's not clear if these need to be programmed before or after
-		 * the VGA bios runs. Try both, clean up later */
-		/* Set memory rate to 200MHz */
-		outb(0x3d, CRTM_INDEX);
-		reg8 = inb(CRTM_DATA);
-		reg8 &= 0x0f;
-		reg8 |= (0x3 << 4);
-		outb(0x3d, CRTM_INDEX);
-		outb(reg8, CRTM_DATA);
-
-#if 0
-		/* Set framebuffer size to CONFIG_VIDEO_MB mb */
-		reg8 = (CONFIG_VIDEO_MB/4);
-		outb(0x39, SR_INDEX);
-		outb(reg8, SR_DATA);
-#endif
-	}
 }
 
+
 static struct device_operations vga_operations = {
 	.read_resources = pci_dev_read_resources,
 	.set_resources = pci_dev_set_resources,
@@ -216,3 +180,9 @@ static const struct pci_driver vga_driver __pci_driver = {
 	.vendor = PCI_VENDOR_ID_VIA,
 	.device = PCI_DEVICE_ID_VIA_VX855_VGA,
 };
+
+static const struct pci_driver vga_driver_900 __pci_driver = {
+	.ops = &vga_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_VX900_VGA,
+};
diff --git a/src/northbridge/via/vx900/Kconfig b/src/northbridge/via/vx900/Kconfig
new file mode 100644
index 0000000..7a45887
--- /dev/null
+++ b/src/northbridge/via/vx900/Kconfig
@@ -0,0 +1,39 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+config NORTHBRIDGE_VIA_VX900
+	bool
+	select IOAPIC
+	select HAVE_DEBUG_RAM_SETUP
+	select HAVE_DEBUG_SMBUS
+	select HAVE_HARD_RESET
+	# Don't do MMCONF until we have at least some usable hardware working
+	# Yes, MMCONF works, and it works nicely, but it also adds some
+	# complications that are better dealt once the code is running well
+	# select MMCONF_SUPPORT
+	# select MMCONF_SUPPORT_DEFAULT
+	select GFXUMA
+
+config MMCONF_BASE_ADDRESS
+	hex
+	default 0xc0000000
+
+config VGA_BIOS_ID
+	string
+	default "1106,7122"
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/Makefile.inc b/src/northbridge/via/vx900/Makefile.inc
new file mode 100644
index 0000000..c714779
--- /dev/null
+++ b/src/northbridge/via/vx900/Makefile.inc
@@ -0,0 +1,43 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011-2012 Alexandru Gagniuc <mr.nuke.me at gmail.com>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+romstage-y += early_smbus.c
+romstage-y += early_vx900.c
+romstage-y += early_uma_ram.c
+romstage-y += raminit_ddr3.c
+romstage-y += ./../../../devices/dram/dram_util.c
+romstage-y += ./../../../devices/smbus/early_smbus.c
+#romstage-y += $(src)/drivers/pc80/udelay_io.c
+romstage-y += ./../../../drivers/pc80/udelay_io.c
+romstage-$(CONFIG_COLLECT_TIMESTAMPS) += ./../../../lib/cbmem.c
+
+driver-y += northbridge.c
+driver-y += chrome9hd.c
+driver-y += traf_ctrl.c
+driver-y += sata.c
+driver-y += lpc.c
+#driver-y += ./../vx800/lpc.c
+
+# The buildsystem only includes this file if CONFIG_VGA is selected.
+# We need to do some VGA I/O before the VGA can be initialized. We can make good
+# use of some of the functions there, so include them unconditionally
+ramstage-y += ./../../../drivers/pc80/vga/vga_io.c
+
+chipset_bootblock_inc += $(src)/northbridge/via/vx900/romstrap.inc
+chipset_bootblock_lds += $(src)/northbridge/via/vx900/romstrap.lds
diff --git a/src/northbridge/via/vx900/chip.h b/src/northbridge/via/vx900/chip.h
new file mode 100644
index 0000000..15c9744
--- /dev/null
+++ b/src/northbridge/via/vx900/chip.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+struct northbridge_via_vx900_config {
+};
+
+extern struct chip_operations northbridge_via_vx900_ops;
diff --git a/src/northbridge/via/vx900/chrome9hd.c b/src/northbridge/via/vx900/chrome9hd.c
new file mode 100644
index 0000000..4188201
--- /dev/null
+++ b/src/northbridge/via/vx900/chrome9hd.c
@@ -0,0 +1,385 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <pc80/vga_io.h>
+
+#include "vx900.h"
+
+#define CHROME_9_HD_MIN_FB_SIZE   8
+#define CHROME_9_HD_MAX_FB_SIZE 512
+
+/* Helper to determine the framebuffer size */
+u32 chrome9hd_fb_size(void)
+{
+	static u32 fb_size = 0;
+	/* We do some PCI and CMOS IO to find our value, so if we've already
+	 * found it, save some time */
+	if(fb_size != 0)
+		return fb_size;
+	/* FIXME: read fb_size from CMOS, but until that is implemented, start
+	 * from 512MB */
+	u32 sizem = 512;
+
+	/* The minimum framebuffer size is 8MB. */
+	sizem = max(sizem, CHROME_9_HD_MIN_FB_SIZE);
+
+	const device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
+		PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
+	/* We have two limitations on the maximum framebuffer size:
+	 * 1) (Sanity) No more that 1/4 of system RAM
+	 * 2) (Hardware limitation) No larger than DRAM in last rank
+	 * Check both of these limitations and apply them to our framebuffer */
+	u32 tomm = (pci_read_config16(mcu, 0x88) & 0x07ff) << (24-20);
+	u32 max_sizem = tomm >> 2;
+	if(sizem > max_sizem) {
+		printk(BIOS_ALERT, "The framebuffer size of of %dMB is larger"
+			" than 1/4 of available memory.\n"
+			" Limiting framebuffer to %dMB\n", sizem, max_sizem);
+		sizem = max_sizem;
+	}
+
+	/* Now handle limitation #2
+	 * Look at the ending address of the memory ranks, from last to first,
+	 * until we find one that is not zero. That is our last rank, and its
+	 * size is the limit of our framebuffer. */
+	int i;
+	for(i = VX900_MAX_MEM_RANKS - 1; i > -1; i--) {
+		u8 reg8 = pci_read_config8(mcu, 0x40 + 1);
+		if(reg8 == 0)
+			continue;
+		/* We've reached the last populated rank */
+		u8 ranksize = reg8 - pci_read_config8(mcu, 0x48 + i);
+		max_sizem = ranksize >> 6;
+	};
+	if(sizem > max_sizem) {
+		printk(BIOS_ALERT, "The framebuffer size of of %dMB is larger"
+		" than size of the last DRAM rank.\n"
+		" Limiting framebuffer to %dMB\n", sizem, max_sizem);
+		sizem = max_sizem;
+	}
+
+	/* Now round the framebuffer size to the closest power of 2 */
+	u8 fb_pow = 0;
+	while(sizem >> fb_pow) fb_pow ++;
+	fb_pow --;
+	sizem = (1 << fb_pow);
+	/* We store the framebuffer size in bytes, for simplicity */
+	fb_size = sizem << 20;
+	return fb_size;
+}
+
+#if 0 && CONFIG_OPTION_ROM_RUN_YABEL
+#include <x86emu/x86emu.h>
+static int vx900_int15_handler_yabel(void)
+{
+	int res=-1;
+	printk(BIOS_DEBUG, "%s %0x\n", __func__, M.x86.R_AX & 0xffff);
+	switch(M.x86.R_AX & 0xffff) {
+		case 0x5f19:
+			M.x86.R_AX=0x5f;
+			M.x86.R_CX=0x03;
+			res=0;
+			break;
+		case 0x5f18:
+		{
+			/*
+			 * BL Bit[7:4]
+			 * Memory Data Rate
+			 * 0000: 66MHz
+			 * 0001: 100MHz
+			 * 0010: 133MHz
+			 * 0011: 200MHz ( DDR200 )
+			 * 0100: 266MHz ( DDR266 )
+			 * 0101: 333MHz ( DDR333 )
+			 * 0110: 400MHz ( DDR400 )
+			 * 0111: 533MHz ( DDR I/II 533
+			 * 1000: 667MHz ( DDR I/II 667)
+			 * Bit[3:0]
+			 * N:  Frame Buffer Size 2^N  MB
+			 */
+			u8 i;
+			device_t dev;
+			dev = dev_find_slot(0, PCI_DEVFN(0, 3));
+			i = pci_read_config8(dev, 0xa1);
+			i = (i & 0x70);
+			i = i >> 4;
+			if (i == 0) {
+				M.x86.R_AX = 0x00;	//not support 5f18
+				break;
+			}
+			i = i + 2;
+			M.x86.R_BX = (u32) i;
+			i = pci_read_config8(dev, 0x90);
+			i = (i & 0x07);
+			i = i + 3;
+			i = i << 4;
+			M.x86.R_BX = M.x86.R_BX + ((u32) i);
+			M.x86.R_AX = 0x5f;
+			res = 0;
+			break;
+		}
+		case 0x5f00:
+			M.x86.R_AX = 0x005f;
+			res = 0;
+			break;
+		case 0x5f01:
+			M.x86.R_AX = 0x5f;
+			M.x86.R_CX = (M.x86.R_CX & 0xffffff00 ) | 2; // panel type =  2 = 1024 * 768
+			res = 0;
+			break;
+		case 0x5f02:
+			M.x86.R_AX=0x5f;
+			M.x86.R_BX= (M.x86.R_BX & 0xffff0000) | 2;
+			M.x86.R_CX= (M.x86.R_CX & 0xffff0000) | 0x401;  // PAL + crt only
+			M.x86.R_DX= (M.x86.R_DX & 0xffff0000) | 0;  // TV Layout - default
+			res=0;
+			break;
+		case 0x5f0f:
+			M.x86.R_AX = 0x005f;
+			res = 0;
+			break;
+		default:
+			printk(BIOS_DEBUG, "Unsupported INT15 call %04x!\n",
+			       M.x86.R_AX & 0xffff);
+			M.x86.R_AX = 0;
+			break;
+	}
+	return res;
+}
+
+static void vx900_vga_set_int15_handler(void)
+{
+	printk(BIOS_DEBUG, "Our int15 handler is at %p\n",
+	       &vx900_int15_handler_yabel);
+	typedef int (* yabel_handleIntFunc)(void);
+	extern yabel_handleIntFunc yabel_intFuncArray[256];
+	yabel_intFuncArray[0x15] = vx900_int15_handler_yabel;
+}
+#endif
+
+static void chrome9hd_set_sid_vid(u16 vendor, u16 device)
+{
+	vga_sr_write(0x36, vendor >> 8);   /* SVID high byte */
+	vga_sr_write(0x35, vendor & 0xff); /* SVID low  byte */
+	vga_sr_write(0x38, device >> 8);   /*  SID high byte */
+	vga_sr_write(0x37, device & 0xff); /*  SID low  byte */
+}
+
+static void chrome9hd_biosguide_init_seq(device_t dev)
+{
+	device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
+	device_t host = dev_find_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_VX900_HOST_BR, 0);
+	print_debug("1\n");
+	/* Step 1 - Enable VGA controller */
+	/* FIXME: This is the VGA hole @ 640k-768k, and the vga port io
+	 * We need the port IO, but can we disable the memory hole? */
+	print_debug("1.a\n");
+	pci_mod_config8(mcu, 0xa4, 0, 0x80); /* VGA memory hole */
+
+	print_debug("2\n");
+	/* Step 2 - Forward MDA cycles to GFX */
+	pci_mod_config8(host, 0x4e, 1<<1, 0); /* FIXME */
+
+	print_debug("3\n");
+	/* Step 3 - Enable GFX I/O space */
+	pci_mod_config8(dev, PCI_COMMAND, 0, PCI_COMMAND_IO);
+
+	print_debug("4\n");
+	/* Step 4 - Enable video subsystem */
+	vga_enable_mask(1<<0, 1<<0);
+
+	print_debug("5\n");
+	/* Step 5 - Unlock accessing of IO space */
+	vga_sr_write(0x10, 0x01);
+
+	/* Step 8 - Enable memory base register on the GFX */
+	if(uma_memory_base == 0)
+		die("uma_memory_base not set. Abandon ship!\n");
+	printk(BIOS_DEBUG, "UMA base @0x%.10llx\n", uma_memory_base);
+	vga_sr_write(0x6d, (uma_memory_base >> 21) & 0xff); /* base 28:21 */
+	vga_sr_write(0x6e, (uma_memory_base >> 29) & 0xff); /* base 36:29 */
+	vga_sr_write(0x6f, 0x00); /* base what what in the butt ?? */
+
+	/* Step 9 - Set SID/VID */
+	chrome9hd_set_sid_vid(0x1106, 0x7122);
+
+	/* Prime PLL FIXME: bad comment */
+	//vga_sr_mask(0x3c, 1<<2, 1<<2);
+
+	//VGA IO Address Select. 3B5 or 3D5?
+	//vga_misc_mask(1<<0, 1<<0);
+
+	//enable Base VGA 16 Bits Decode
+	//pci_mod_config8(host, 0x4e, 0, 1<<4);
+}
+
+static void dump_pci_device(device_t dev)
+{
+	int i;
+	for (i = 0; i <= 255; i++) {
+		unsigned char val;
+		if ((i & 0x0f) == 0) {
+			print_debug_hex8(i);
+			print_debug_char(':');
+		}
+		val = pci_read_config8(dev, i);
+		if((i & 7) == 0) print_debug(" |");
+		print_debug_char(' ');
+		print_debug_hex8(val);
+		if ((i & 0x0f) == 0x0f) {
+			print_debug("\n");
+		}
+	}
+}
+
+static void chrome9hd_init(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== Chrome9 HD INIT\n");
+	print_debug("======================================================\n");
+
+	chrome9hd_biosguide_init_seq(dev);
+
+	//vx900_vga_set_int15_handler();
+
+	u32 fb_address = pci_read_config32(dev, PCI_BASE_ADDRESS_2);
+	fb_address &= ~0x0F;
+	if (!fb_address) {
+		printk(BIOS_WARNING, "Chrome: No FB BAR assigned!\n");
+		return;
+	}
+
+	printk(BIOS_INFO, "Chrome: Using %dMB Framebuffer at 0x%08X.\n",
+	       256, fb_address);
+
+	/* Poison the framebuffer */
+//	size_t i, j;
+//	for(i = 0; i < 256; i++) {
+//		u32 * fb = (u32*) (u32)(fb_address + i * (1<<20));
+//		for(j = 0; j < (1<<20)>>2; j++) {
+//			fb[j] = 0xdeadbeef;
+//		}
+//	}
+
+	printk(BIOS_DEBUG, "Initializing VGA...\n");
+
+	pci_dev_init(dev);
+
+	printk(BIOS_DEBUG, "Enable VGA console\n");
+	//vga_enable_console();
+
+	dump_pci_device(dev);
+}
+
+static void chrome9hd_enable(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== Chrome9 HD ENABLE\n");
+	print_debug("======================================================\n");
+
+	device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
+	/* FIXME: here? -=- ACLK 250Mhz */
+	pci_mod_config8(mcu, 0xbb, 0, 0x01);
+}
+
+static void chrome9hd_disable(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== Chrome9 HD DISABLE\n");
+	print_debug("======================================================\n");
+
+	device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
+	/* Disable GFX - This step effectively renders the GFX inert
+	 * It won't even show up as a PCI device during enumeration */
+	pci_mod_config8(mcu, 0xa1, 1<<7, 0);
+}
+
+static void chrome9hd_read_resources(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== Chrome9 HD READ RESOURCES\n");
+	print_debug("======================================================\n");
+
+	/* Mirror mirror, shiny glass, tell me that is not my ass */
+	u32 fb_size = chrome9hd_fb_size() >> 20;
+
+	uma_resource(dev, 0x18, uma_memory_base>>10, uma_memory_size>>10);
+
+	u8 fb_pow = 0;
+	while(fb_size >> fb_pow) fb_pow ++;
+	fb_pow --;
+
+	/* Step 6 - Let MCU know the framebuffer size */
+	device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
+	pci_mod_config8(mcu, 0xa1, 7<<4, (fb_pow - 2) <<4);
+
+	/* Step 7 - Let GFX know the framebuffer size (through PCI and IOCTL)
+	 * The size we set here affects the behavior of BAR2, and the amount of
+	 * MMIO space it requests. The default is 512MB, so if we don't set this
+	 * before reading the resources, we could waste space below 4G */
+	pci_write_config8(dev, 0xb2, ((0xff << (fb_pow - 2)) & ~(1<<7)) );
+	vga_sr_write(0x68, (0xff << (fb_pow - 1)) );
+	/* And also that the framebuffer is in the syste, RAM */
+	pci_mod_config8(dev, 0xb0, 0, 1<<0);
+
+	pci_dev_read_resources(dev);
+}
+
+static void chrome9hd_set_resources(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== Chrome9 HD SET RESOURCES\n");
+	print_debug("======================================================\n");
+
+	pci_dev_set_resources(dev);
+}
+
+static void chrome9hd_enable_resources(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== Chrome9 HD ENABLE RESOURCES\n");
+	print_debug("======================================================\n");
+
+	pci_dev_enable_resources(dev);
+}
+
+static struct device_operations chrome9hd_operations = {
+	.read_resources = chrome9hd_read_resources,
+	.set_resources = chrome9hd_set_resources,
+	.enable_resources = chrome9hd_enable_resources,
+	.init = chrome9hd_init,
+	.disable = chrome9hd_disable,
+	.enable = chrome9hd_enable,
+	.ops_pci = 0,
+};
+
+static const struct pci_driver chrome9hd_driver __pci_driver = {
+	.ops = &chrome9hd_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_VX900_VGA,
+};
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/early_smbus.c b/src/northbridge/via/vx900/early_smbus.c
new file mode 100644
index 0000000..aa6cec0
--- /dev/null
+++ b/src/northbridge/via/vx900/early_smbus.c
@@ -0,0 +1,191 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <device/pci_ids.h>
+#include "early_vx900.h"
+
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <devices/dram/dram.h>
+
+__attribute__((unused))
+static void smbus_delays(int delays)
+{
+	while(delays--) __smbus_delay();
+}
+
+
+/**
+ * Read a byte from the SMBus.
+ *
+ * @param dimm The address location of the DIMM on the SMBus.
+ * @param offset The offset the data is located at.
+ */
+u8 __smbus_read_byte(u8 dimm, u8 offset, u16 __smbus_io_base)
+{
+	u8 val;
+	
+	/* Initialize SMBUS sequence */
+	smbus_reset();
+	/* Clear host data port. */
+	outb(0x00, SMBHSTDAT0);
+	
+	smbus_wait_until_ready();
+	smbus_delays(50);
+	
+	/* Actual addr to reg format. */
+	dimm = (dimm << 1);
+	dimm |= 1; /* read command */
+	outb(dimm, SMBXMITADD);
+	outb(offset, SMBHSTCMD);
+	/* Start transaction, byte data read. */
+	outb(0x48, SMBHSTCTL);
+	smbus_wait_until_ready();
+	
+	val = inb(SMBHSTDAT0);
+	return val;
+}
+
+void enable_smbus(void)
+{
+	device_t dev;
+	u8 reg8;
+	u16 __smbus_io_base = SMBUS_IO_BASE;
+
+	/* Locate the Power Management control */
+	dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VX900_LPC), 0);
+	
+	if (dev == PCI_DEV_INVALID) {
+		die("Power Managment Controller not found\n");
+	}
+
+	/*
+	 * To use SMBus to manage devices on the system board, it is a must to
+	 * enable SMBus function by setting
+	 * PMU_RXD2[0] (SMBus Controller Enable) to 1.
+	 * And set PMU_RXD0 and PMU_RXD1 (SMBus I/O Base) to an appropriate
+	 * I/O port address, so that all registers in SMBus I/O port can be
+	 * accessed.
+	 */
+
+	reg8 = pci_read_config8(dev, 0xd2);
+	/* Enable SMBus controller */
+	reg8 |= 1;
+	/* Set SMBUS clock from 128k source */
+	reg8 |= 1<<2;
+	pci_write_config8(dev, 0xd2, reg8);
+
+	reg8 = pci_read_config8(dev, 0x94);
+	/* SMBUS clock from divider of 14.318 MHz */
+	reg8 &= ~(1<<7);
+	pci_write_config8(dev, 0x94, reg8);
+
+	/* Set SMBus IO base */
+	pci_write_config16(dev, 0xd0, SMBUS_IO_BASE);
+
+	/*
+	 * Initialize the SMBus sequence:
+	 */
+	/* Clear SMBus host status register */
+	smbus_reset();
+	/* Clear SMBus host data 0 register */
+	outb(0x00, SMBHSTDAT0);
+
+	/* Wait for SMBUS */
+	smbus_wait_until_ready();
+
+}
+
+void spd_read(u8 addr, spd_raw_data spd)
+{
+	u8 reg;
+	int i, regs;
+	reg = smbus_read_byte(addr, 2);
+	if(reg != 0x0b)
+	{
+		printk(BIOS_DEBUG, "SMBUS device %x not a DDR3 module\n", addr);
+		spd[2] = 0;
+		return;
+	}
+
+	reg = smbus_read_byte(addr, 0);
+	reg &= 0xf;
+	if (reg == 0x3) {
+		regs = 256;
+	} else if (reg == 0x2) {
+		regs = 176;
+	} else if (reg == 0x1) {
+		regs = 128;
+	} else {
+		printk(BIOS_INFO, "No DIMM present at %x\n", addr);
+		spd[2] = 0;
+		return;
+	}
+	printk(BIOS_DEBUG, "SPD Data for DIMM %x \n", addr);
+	for (i = 0; i < regs; i++) {
+		reg = smbus_read_byte(addr, i);
+		//printk(BIOS_DEBUG, "  Offset %u  = 0x%x \n", i, reg );
+		spd[i] = reg;
+	}
+}
+
+void dump_spd_data(void)
+{
+	int dimm, offset, regs;
+	unsigned int reg;
+	spd_raw_data spd;
+	dimm_attr dimmx;
+	
+	for (dimm = 0x50; dimm < 0x52; dimm++) {
+		reg = smbus_read_byte(dimm, 2);
+		if(reg != 0x0b)
+		{
+			printk(BIOS_DEBUG,
+			       "SMBUS device %x not a DDR3 module\n", dimm);
+			continue;
+		}
+
+		reg = smbus_read_byte(dimm, 0);
+		reg &= 0xf;
+		if (reg == 0x3) {
+			regs = 256;
+		} else if (reg == 0x2) {
+			regs = 176;
+		} else if (reg == 0x1) {
+			regs = 128;
+		} else {
+			printk(BIOS_INFO, "No DIMM present at %x\n", dimm);
+			regs = 0;
+			continue;
+		}
+		printk(BIOS_DEBUG, "SPD Data for DIMM %x \n", dimm);
+		for (offset = 0; offset < regs; offset++) {
+			reg = smbus_read_byte(dimm, offset);
+			//printk(BIOS_DEBUG, "  Offset %u  = 0x%x \n", offset, reg );
+			spd[offset] = reg;
+		}
+
+		spd_decode_ddr3(&dimmx, spd);
+		dram_print_spd_ddr3(&dimmx);
+
+	}
+}
+
diff --git a/src/northbridge/via/vx900/early_uma_ram.c b/src/northbridge/via/vx900/early_uma_ram.c
new file mode 100644
index 0000000..d19d062
--- /dev/null
+++ b/src/northbridge/via/vx900/early_uma_ram.c
@@ -0,0 +1,135 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011-2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+# include "early_vx900.h"
+
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cbfs.h>
+#include <device/pci_def.h>
+#include <stddef.h>
+
+/* These are mainly arbitration values for the MCU to arbitrate bandwidth
+ * between CPU requests and GFX requests. They are set such that the GFX will
+ * get more bandwidth when needed (i.e. 3D graphics)
+ * If the GFX is idle, the CPU will still be able to use all available memory
+ * bandwidth. */
+static pci_reg8 mcu_vga_arbiter_config[] = {
+	{0xa2, 0xb4}, /* Arbitration - GFX */
+	{0xa6, 0x01}, /* Enable 8QW request merging from GFX*/
+	{0xb0, 0xb8}, /* Arbitration - Video decoder */
+	{0xb1, 0x22}, /* Enable 8QW request merging from Video decoder */
+	{0xb8, 0x11}, /* Priority adjustemnt for Video Decoder */
+	{0xb9, 0x11}, /* Arbitration - Video Decoder Queue -  I */
+	{0xba, 0x11}, /* Arbitration - Video Decoder Queue - II */
+};
+
+static void vx900_gfx_dram_arbitration(void)
+{
+	size_t i;
+	for(i = 0; i < (sizeof(mcu_vga_arbiter_config)/sizeof(pci_reg8)); i++)
+	{
+		pci_write_config8(MCU, mcu_vga_arbiter_config[i].addr,
+				  mcu_vga_arbiter_config[i].val);
+	}
+}
+
+void vx900_dram_set_gfx_resources(void)
+{
+	printk(BIOS_SPEW, "Setting up GFX mem area \n");
+	/* FIXME: enable VGA or not? */
+	/* u32 fbuff_size = vga_decide_framebuffer_size();
+	 * if(fbuff_size == 0) {
+	 *	Do not initialize the IGP
+	 * 	return;
+	 * } */
+
+
+	/* Step 1 - Enable VGA controller */
+//	pci_mod_config8(MCU, 0xa1, 0, 0x80);
+	/* FIXME: This is the VGA hole @ 640k-768k, and the vga port io
+	 * We need the port IO, but can we disable the memory hole? */
+//	pci_mod_config8(MCU, 0xa4, 0, 0x80); /* VGA memory hole */
+
+	//device_t d0f0 = PCI_DEV(0,0,0);
+	/* Step 2 - Forward MDA to GFX */
+//	pci_mod_config8(d0f0, 0x4e, 1<<1, 0); /* FIXME */
+
+	/* Step 3 - Enable GFX I/O space */
+//	pci_mod_config8(GFX, PCI_COMMAND, 0, PCI_COMMAND_IO);
+
+	/* Step 4 - Enable video subsystem */
+//	u8 io8 = inb(0x3c3);
+//	io8 |= 1<<0;
+//	outb(io8, 0x3c3);
+	//3410-20-KKL-04 +S
+
+	/* Step 5 - Unlock accessing of IO space */
+//	vx900_gfx_write8(0x10, 0x01);
+
+	/* Prime PLL FIXME: bad comment */
+	//vx900_gfx_mod8(0x3c, 0, 1<<2);
+	//vx900_gfx_mod8(0x3c, 0, 0);
+
+	//VGA IO Address Select. 3B5 or 3D5?
+	u8 io8 = inb(0x03cc);
+	io8 |= 0x01;
+	outb(io8, 0x3c2);
+	//3410-20-KKL-04 +E
+
+	/* Bandwidth, bandwidth, bandwidth */
+	vx900_gfx_dram_arbitration();
+
+	/* FIXME: here? -=- ACLK 250Mhz */
+	pci_mod_config8(MCU, 0xbb, 0, 0x01);
+
+	/* Step 6 - Let MCU know the framebuffer size */
+//	pci_mod_config8(MCU, 0xa1, 7<<4, (fb_pow - 2) <<4);
+	/* Step 7 - Let GFX know the framebuffer size (through PCI and IOCTL) */
+//	pci_write_config8(GFX, 0xb2, ((0xff << (fb_pow - 2)) & ~(1<<7)) );
+//	vx900_gfx_write8(0x68, (0xff << (fb_pow - 1)) );
+
+	/* Step 8 - Enable memory base register on the GFX */
+//	const u64 tom = ( pci_read_config16(MCU, 0x88) & 0x07ff ) << 24;
+//	const u64 fb_base = tom - (fb_size << 20);
+//	vx900_gfx_write8(0x6d, (fb_base >> 21) & 0xff); /* base 28:21 */
+//	vx900_gfx_write8(0x6e, (fb_base >> 29) & 0xff); /* base 36:29 */
+//	vx900_gfx_write8(0x6f, 0x00); /* base what what in the butt ?? */
+
+	/* Step 9 - Set SID/VID */
+//	vx900_gfx_set_sid_vid(0x1106, 0x7122);
+
+	/* VGA framebuffer is system-local (in system RAM) */
+//	pci_write_config8(GFX, 0xb0, 0x01);
+
+	//enable Base VGA 16 Bits Decode
+	//pci_mod_config8(HOST_CTR, 0x4e, 0, 1<<4);
+
+	/* That was it for the BIOS guide steps */
+	/* FIXME: Do we need these canucking IO bars? */
+	//pci_write_config32(GFX, PCI_BASE_ADDRESS_0, 0xf8000008);
+	//pci_write_config32(GFX, PCI_BASE_ADDRESS_1, 0xfc000000);
+	//pci_write_config32(GFX, PCI_BASE_ADDRESS_2, fb_base | 0x08);
+
+	/* Direct framebuffer access
+	 * FIXME: framebuffer base should be decided based on TOM and size */
+	/* Let the MCU know of the frambuffer base, for direct access by CPU */
+	//(MCU, 0xa0, 0x0ffe, 0x0200);
+}
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/early_vx900.c b/src/northbridge/via/vx900/early_vx900.c
new file mode 100644
index 0000000..14e4ee3
--- /dev/null
+++ b/src/northbridge/via/vx900/early_vx900.c
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "early_vx900.h"
+#include <arch/romcc_io.h>
+#include <console/console.h>
+
+unsigned long get_top_of_ram(void)
+{
+	u16 reg_tom = pci_read_config8(MCU, 0x88);
+	return (((unsigned long) reg_tom) << 24) - (256<<20);
+}
+
+struct cbmem_entry *get_cbmem_toc(void)
+{
+	return (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
+}
+
+void vx900_enable_pci_config_space(void)
+{
+	/* MMCONF is not yet enabled, so we'll need to specify we want to do
+	 * pci_io. We don't want to do pci_mmio until we enable it */
+	/* Enable multifunction bit for northbridge.
+	 * This enables the PCI configuration spaces of D0F1 to D0F7 to be
+	 * accessed */
+	pci_io_write_config8(HOST_CTR, 0x4f, 0x01);
+
+#if CONFIG_MMCONF_SUPPORT
+	/* COOL, now enable MMCONF */
+	u8 reg8 = pci_io_read_config8(TRAF_CTR, 0x60);
+	reg8 |= 3;
+	pci_io_write_config8(TRAF_CTR, 0x60, reg8);
+	reg8 = CONFIG_MMCONF_BASE_ADDRESS >> 28;
+	pci_io_write_config8(TRAF_CTR, 0x61, reg8);
+#endif
+}
+
+/**
+ *\brief Prints information regarding the hardware strapping on VX900
+ *
+ * Certain features on the VX900 are controlled by strapping pins which are
+ * hardwired on the mainboard. These values determine whether the ROM is on the
+ * SPI or LPC bus, or whether auto-reset is enabled.
+ * \n
+ * Having a feel for these values is important when trying to fix obscure
+ * problems found when porting a mainboard based on the VX900.
+ * \n
+ * These values are decoded and printed to the terminal.
+ */
+void vx900_print_strapping_info(void)
+{
+	u8 strap = pci_read_config8(SNMIC, 0x56);
+
+	print_debug("VX900 strapping pins indicate that:\n");
+	printk(BIOS_DEBUG, " ROM is on %s bus\n",
+	       (strap & (1<<0)) ? "SPI" : "LPC" );
+	printk(BIOS_DEBUG, " Auto reset is %s\n",
+	       (strap & (1<<1)) ? "disabled" : "enabled" );
+	printk(BIOS_DEBUG, " LPC FWH command is %s\n",
+	       (strap & (1<<2)) ? "enabled"  : "disabled" );
+	printk(BIOS_DEBUG, " Debug link is is %s\n",
+	       (strap & (1<<4)) ? "enabled"  : "disabled" );
+	printk(BIOS_DEBUG, " PCI master mode is %s\n",
+	       (strap & (1<<5)) ? "enabled"  : "disabled" );
+}
+
+/**
+ *\brief Disables the auto-reboot mechanism on VX900
+ *
+ * The VX900 has an auto-reboot mechanism that can be enabled by a hardware
+ * strap. This mechanism can make development annoying, since we don't know if
+ * the reset was caused by a bug in coreboot, or by this mechanism.
+ */
+void vx900_disable_auto_reboot(void)
+{
+	if( pci_read_config8(SNMIC, 0x56) & (1<<1) ) {
+		print_debug("Auto-reboot is disabled in hardware\n");
+		return;
+	}
+	/* Disable the GP3 timer, which is the root of all evil */
+	pci_write_config8(LPC, 0x98, 0);
+	/* Yep, that's all it takes */
+	print_debug("GP3 timer disabled."
+		    " Auto-reboot should not give you any more trouble.\n");
+}
+
+static void dump_pci_device(device_t dev)
+{
+	int i;
+	printram("PCI: %.2x:%.2x.%.2x",
+		 (dev >> 20) & 0xff, (dev >> 15) & 0x1f, (dev >> 12) & 7 );
+	printram("\n");
+
+	for (i = 0; i <= 0xff; i++) {
+		unsigned char val;
+		if ((i & 0x0f) == 0) {
+			printram("%.2x:", i);
+		}
+
+		if ((i & 0x0f) == 0x08) {
+			printram(" |");
+		}
+
+		val = pci_read_config8(dev, i);
+		printram(" %.2x", val);
+
+		if ((i & 0x0f) == 0x0f) {
+			printram("\n");
+		}
+	}
+}
+
+void vx900_cpu_to_dram_interface_setup(void)
+{
+	/* Enable 4QW request merging */
+	pci_mod_config8(HOST_BUS, 0x54, 0, (1<<4)|(1<<3)|(1<<2) );
+
+	dump_pci_device(HOST_BUS);
+}
+
+void vx900_disable_legacy_rom_shadow(void)
+{
+	/* Disable shitty 8086 legacy shadows
+	 * This frees the entire 640k-1M range for DRAM
+	 * VGA may still use 640k-768k if enabled later
+	 * Unfortunately, we need to disable these shadows in more than one
+	 * device, and that's why some ranges are disabled more than once */
+	pci_write_config8(MCU, 0x80, 0xff); /* ROM 768k - 832k */
+	pci_write_config8(MCU, 0x81, 0xff); /* ROM 832k - 896k */
+	pci_write_config8(MCU, 0x82, 0xff); /* ROM 896k - 960k */
+	/* ROM 960k - 1M * SMRAM: 640k - 768k */
+	pci_write_config8(MCU, 0x83, 0x31);
+
+	/* Bits 6:0 are the ROM shadow on top of 4G, so leave those untouched */
+	pci_mod_config8(LPC, 0x41, 1<<7, 0);/* 896k - 960k */
+
+	pci_write_config8(SNMIC, 0x61, 0); /* 768k - 832k */
+	pci_write_config8(SNMIC, 0x62, 0); /* 832k - 896k */
+	pci_write_config8(SNMIC, 0x63, 0); /* 896k - 1M   */
+	pci_write_config8(SNMIC, 0x64, 0); /* 896k - 960k */
+
+	/* Doesn't really belong here, but it is "shitty legacy"
+	 * Enable A20 line */
+	outb( inb(0x92)|(1<<1), 0x92);
+}
+
+void vx900_disable_gfx(void)
+{
+	/* Disable GFX */
+	pci_mod_config8(MCU, 0xa1, 1<<7, 0);
+}
diff --git a/src/northbridge/via/vx900/early_vx900.h b/src/northbridge/via/vx900/early_vx900.h
new file mode 100644
index 0000000..8cd7d25
--- /dev/null
+++ b/src/northbridge/via/vx900/early_vx900.h
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011-2012 Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EARLY_VX900_H
+#define EARLY_VX900_H
+
+#include "raminit.h"
+#include "vx900.h"
+
+#include <arch/io.h>
+#include <cbmem.h>
+#include <devices/smbus/smbus.h>
+#include <stdint.h>
+
+/* North Module devices */
+#define HOST_CTR PCI_DEV(0, 0, 0)
+#define ERR_REP  PCI_DEV(0, 0, 1)
+#define HOST_BUS PCI_DEV(0, 0, 2)
+#define MCU      PCI_DEV(0, 0, 3)
+#define POWERMAN PCI_DEV(0, 0, 4)
+#define TRAF_CTR PCI_DEV(0, 0, 5)
+#define NSBIC    PCI_DEV(0, 0, 7)
+
+#define GFX      PCI_DEV(0, 1, 0)
+#define HDMI     PCI_DEV(0, 1, 0)
+
+#define PEXx     PCI_DEV(0, 3, x)
+#define PEX_CTR  PCI_DEV(0, 3, 4)
+
+/* South Module devices */
+#define UARTx    PCI_DEV(0, 0x0a, x)
+#define USB_MASS PCI_DEV(0, 0x0b, 0)
+#define SDIO     PCI_DEV(0, 0x0c, 0)
+#define CARD_RD  PCI_DEV(0, 0x0d, 0)
+#define SATA     PCI_DEV(0, 0x0d, 0)
+#define USBx     PCI_DEV(0, 0x10, x)
+#define USB_EHCI PCI_DEV(0, 0x10, 4)
+#define LPC      PCI_DEV(0, 0x11, 0)
+#define PMU      LPC
+#define SNMIC    PCI_DEV(0, 0x11, 7)
+#define P2P      PCI_DEV(0, 0x13, 0)
+#define HDAC     PCI_DEV(0, 0x14, 0)
+
+
+unsigned long get_top_of_ram(void);
+
+void enable_smbus(void);
+void dump_spd_data(void);
+void spd_read(u8 addr, spd_raw_data spd);
+
+void vx900_enable_pci_config_space(void);
+void vx900_disable_legacy_rom_shadow(void);
+
+void vx900_print_strapping_info(void);
+void vx900_disable_auto_reboot(void);
+
+void vx900_cpu_to_dram_interface_setup(void);
+
+void vx900_dram_set_gfx_resources(void);
+void vx900_disable_gfx(void);
+
+#endif /* EARLY_VX900_H */
diff --git a/src/northbridge/via/vx900/forgotten.c b/src/northbridge/via/vx900/forgotten.c
new file mode 100644
index 0000000..1b79e4e
--- /dev/null
+++ b/src/northbridge/via/vx900/forgotten.c
@@ -0,0 +1,32 @@
+#include "forgotten.h"
+#include <../../dram/dram.h>
+
+u16 ddr3_get_mr3(char dataflow_from_mpr)
+{
+	u32 cmd = 0;
+	if(dataflow_from_mpr) cmd |= (1<<2);
+	return cmd;
+}
+
+/*
+ * Translate the MRS command into the memory address corresponding to the
+ * command. This is based on the CPU address to memory address mapping described
+ * by the initial values of registers  0x52 and 0x53, so do not fuck with them
+ * until after the MRS commands have been sent to all ranks
+ */
+
+u32 vx900_get_mrs_addr(u8 mrs_type, u16 cmd);
+
+u32 vx900_get_mrs_addr(u8 mrs_type, u16 cmd)
+{
+	u32 addr = 0;
+	/* A3 <-> MA0, A4 <-> MA1, ... A12 <-> MA9 */
+	addr |= ((cmd &0x3ff)<< 3);
+	/* A20 <-> MA10 */
+	addr |= (((cmd >> 10) & 0x1) << 20);
+	/* A13 <-> MA11, A14 <-> MA12 */
+	addr |= (((cmd >> 11) & 0x3) << 13);
+	/* A17 <-> BA0, A18 <-> BA1, A19 <-> BA2 */
+	addr |= ((mrs_type & 0x7) << 17);
+	return addr;
+}
diff --git a/src/northbridge/via/vx900/forgotten.h b/src/northbridge/via/vx900/forgotten.h
new file mode 100644
index 0000000..43641f7
--- /dev/null
+++ b/src/northbridge/via/vx900/forgotten.h
@@ -0,0 +1,78 @@
+#ifndef REDUNDANT_H
+#define REDUNDANT_H
+
+#define DDR3_MR0_PRECHARGE_SLOW    0
+#define DDR3_MR0_PRECHARGE_FAST    1
+#define DDR3_MR0_MODE_NORMAL       0
+#define DDR3_MR0_MODE_TEST         1
+#define DDR3_MR0_DLL_RESET_NO      0
+#define DDR3_MR0_DLL_RESET_YES     1
+#define DDR3_MR0_BURST_TYPE_SEQUENTIAL   0
+#define DDR3_MR0_BURST_TYPE_INTERLEAVED  1
+#define DDR3_MR0_BURST_LENGTH_FIXED_8    0
+#define DDR3_MR0_BURST_LENGTH_CHOP       1
+#define DDR3_MR0_BURST_LENGTH_FIXED_4    2
+/**
+ * \brief Get command address for a DDR3 MR0 command
+ */
+u16 ddr3_get_mr0(
+	char precharge_pd,
+	u8 write_recovery,
+	char dll_reset,
+	char mode,
+	u8 cas,
+	char interleaved_burst,
+	u8 burst_lenght
+);
+
+#define DDR3_MR1_TQDS_DISABLE            0
+#define DDR3_MR1_TQDS_ENABLE             1
+#define DDR3_MR1_QOFF_ENABLE             0
+#define DDR3_MR1_QOFF_DISABLE            1
+#define DDR3_MR1_WRITE_LEVELING_DISABLE  0
+#define DDR3_MR1_WRITE_LEVELING_ENABLE   1
+#define DDR3_MR1_RTT_NOM_OFF             0
+#define DDR3_MR1_RTT_NOM_RZQ4            1
+#define DDR3_MR1_RTT_NOM_RZQ2            2
+#define DDR3_MR1_RTT_NOM_RZQ6            3
+#define DDR3_MR1_RTT_NOM_RZQ12           4
+#define DDR3_MR1_RTT_NOM_RZQ8            5
+#define DDR3_MR1_AL_DISABLE              0
+#define DDR3_MR1_AL_CL_MINUS_1           1
+#define DDR3_MR1_AL_CL_MINUS_2           2
+#define DDR3_MR1_ODS_RZQ6                0
+#define DDR3_MR1_ODS_RZQ7                1
+#define DDR3_MR1_DLL_ENABLE              0
+#define DDR3_MR1_DLL_DISABLE             1
+/**
+ * \brief Get command address for a DDR3 MR1 command
+ */
+u16 ddr3_get_mr1(
+	char q_off,
+	char tdqs,
+	u8 rtt_nom,
+	char write_leveling,
+	u8 output_drive_strenght,
+	u8 additive_latency,
+	u8 dll_disable
+);
+
+#define DDR3_MR2_RTT_WR_OFF              0
+#define DDR3_MR2_RTT_WR_RZQ4             1
+#define DDR3_MR2_RTT_WR_RZQ2             2
+/**
+ * \brief Get command address for a DDR3 MR2 command
+ */
+u16 ddr3_get_mr2(
+	u8 rtt_wr,
+	char extended_temp,
+	char auto_self_refresh,
+	u8 cas_write
+);
+
+/**
+ * \brief Get command address for a DDR3 MR3 command
+ */
+u16 ddr3_get_mr3(char dataflow_from_mpr);
+
+#endif /* REDUNDANT_H */
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/lpc.c b/src/northbridge/via/vx900/lpc.c
new file mode 100644
index 0000000..c8e052b
--- /dev/null
+++ b/src/northbridge/via/vx900/lpc.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <pc80/i8259.h>
+#include <pc80/mc146818rtc.h>
+
+#include "vx900.h"
+
+#define INTA 7
+#define INTB 6
+#define INTC 15
+#define INTD 5
+
+/* Restricted to IRQ 10, 11, 14, or 15 */
+#define INTSATA 14
+
+typedef struct {
+	u8 bus;
+	u8 slot;
+	u8 irq[4];
+} irq_entry;
+
+const static irq_entry irq_table[] = {
+	{0, 0x1, {INTA, INTB, INTC, INTD} },             /* VGA */
+	{0, 0xf, {INTSATA, INTSATA, INTSATA, INTSATA} }, /* SATA controller */
+	{0xff} /* End list */
+};
+
+static void assign_irqs_from_table(void)
+{
+	const irq_entry * irqs = irq_table;
+	while(irqs->bus != 0xff) {
+		pci_assign_irqs(irqs->bus, irqs->slot, irqs->irq);
+		irqs++;
+	}
+}
+
+static void vx900_lpc_read_resources(device_t dev)
+{
+	pci_dev_read_resources(dev);
+	/* In case we need to do some more stuff */
+}
+
+static void vx900_lpc_set_resources(device_t dev)
+{
+	/* In case we need to do some more stuff */
+
+	pci_dev_set_resources(dev);
+}
+
+static void vx900_lpc_misc_stuff(device_t dev)
+{
+	/* GPIO 11,10 to SATALED [1,0] */
+	pci_mod_config8(dev, 0xe4, 0 , 1<<0);
+}
+
+static void vx900_lpc_interrupt_stuff(device_t dev)
+{
+	/* Enable setting trigger mode through 0x4d0, and 0x4d1 ports
+	 * And enable I/O recovery time */
+	pci_mod_config8(dev, 0x40, 0, (1<<2)|(1<<6));
+	/* Set serial IRQ frame width to 6 PCI cycles (recommended by VIA)
+	 * And enable serial IRQ */
+	pci_mod_config8(dev, 0x52, 3<<0, (1<<3)|(1<<0) );
+
+	/* Disable IRQ12 storm FIXME: bad comment */
+	pci_mod_config8(dev, 0x51, (1<<2), 0);
+
+	/* Enable APIC */
+	pci_mod_config8(dev, 0x58, 0, 1<<6);
+
+	/* Route INTA -> INTD to the proper interrupts */
+	pci_write_config8(dev, 0x55, INTA<<4);
+	pci_write_config8(dev, 0x56, INTB | (INTC<<4) );
+	pci_write_config8(dev, 0x57, INTD<<4);
+	/* The SATA controller interrupt is more special */
+	pci_write_config8(dev, 0x4c, (INTSATA - 14) | (1<<6) );
+
+	/* Get the IRQs up and running. SeaBIOS might need these to boot */
+	setup_i8259();
+	assign_irqs_from_table();
+
+	/* DMA Enable */
+	//pci_write_config8(dev, 0x53, 0xff);
+}
+
+static void dump_pci_device(device_t dev)
+{
+	int i;
+	for (i = 0; i <= 255; i++) {
+		unsigned char val;
+		if ((i & 0x0f) == 0) {
+			print_debug_hex8(i);
+			print_debug_char(':');
+		}
+		val = pci_read_config8(dev, i);
+		if((i & 7) == 0) print_debug(" |");
+		print_debug_char(' ');
+		print_debug_hex8(val);
+		if ((i & 0x0f) == 0x0f) {
+			print_debug("\n");
+		}
+	}
+}
+
+static void vx900_lpc_init(device_t dev)
+{
+	vx900_lpc_interrupt_stuff(dev);
+	vx900_lpc_misc_stuff(dev);
+	dump_pci_device(dev);
+}
+
+static struct device_operations vx900_lpc_ops = {
+	.read_resources = vx900_lpc_read_resources,
+	.set_resources = vx900_lpc_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init = vx900_lpc_init,
+	.scan_bus = scan_static_bus,
+};
+
+static const struct pci_driver lpc_driver __pci_driver = {
+	.ops = &vx900_lpc_ops,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_VX900_LPC,
+};
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/northbridge.c b/src/northbridge/via/vx900/northbridge.c
new file mode 100644
index 0000000..e71807d
--- /dev/null
+++ b/src/northbridge/via/vx900/northbridge.c
@@ -0,0 +1,159 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "vx900.h"
+#include "chip.h"
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <cpu/cpu.h>
+#include <cbmem.h>
+#include <lib.h>
+#include <string.h>
+
+static void vx900_set_resources(device_t dev)
+{
+	print_debug("========================================"
+		    "========================================\n" );
+	print_debug("============= VX900 memory sizing & Co. "
+		    "========================================\n" );
+	print_debug("========================================"
+		    "========================================\n" );
+
+
+	int idx = 0;
+	const device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
+		PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
+	if(!mcu) {
+		die("Something is terribly wrong.\n"
+		    " We tried locating the MCU on the PCI bus, "
+		    "but couldn't find it. Halting.\n");
+	}
+
+	u32 pci_tolm = find_pci_tolm(dev->link_list);
+	printk(BIOS_SPEW, "Found PCI tolm at           %.8x\n", pci_tolm);
+	printk(BIOS_SPEW, "Found PCI tolm at           %dMB\n", pci_tolm>>20);
+
+	/* The last valid DRAM address is computed by the MCU
+	 * One issue might be if we have a hole in the rank mappings, so that
+	 * virtual ranks are not mapped successively in the linear address space
+	 * (Ex: rank 0 mapped 0-1G, rank 1 mapped 2G-3G)
+	 * We don't do this awkward mapping in RAM init, so we don't worry about
+	 * it here, but it is something to keep in mind if having RAM issues */
+	u32 vx900_tom = pci_read_config16(mcu, 0x88) & 0x07ff;
+	const u32 tomk = vx900_tom << (24-10);
+	printk(BIOS_SPEW, "Found top of memory at      %dMB\n", tomk>>10);
+
+	/* Do the same for top of low RAM */
+	u32 vx900_tolm = (pci_read_config16(mcu, 0x84) & 0xfff0) >> 4;
+	const u32 full_tolmk = vx900_tolm << (20-10);
+	printk(BIOS_SPEW, "Found top of low memory at  %dMB\n", full_tolmk>>10);
+
+	/* What about the framebuffer for the integrated GPU? */
+	u32 fbufk = chrome9hd_fb_size() >> 10;
+	printk(BIOS_SPEW, "Integrated graphics buffer: %dMB\n", fbufk>>10);
+
+	/* Can't use the framebuffer as system RAM, sorry */
+	u32 tolmk = full_tolmk - fbufk;
+	ram_resource(dev, idx++, 0, 640);
+	printk(BIOS_SPEW, "System ram left:            %dMB\n", tolmk>>10);
+	/* FIXME: how can we avoid leaving this hole?
+	 * Leave a hole for VGA, 0xa0000 - 0xc0000  ?? */
+	/* TODO: VGA Memory hole can be disabled in SNMIC. Upper 64k of ROM seem
+	 * to be always mapped to the top of 1M, but this can be overcome with
+	 * some smart positive/subtractive resource decoding */
+	ram_resource(dev, idx++, 768, (tolmk - 768));
+	uma_memory_size = fbufk << 10;
+	uma_memory_base = tolmk << 10;
+
+	struct resource *res;
+	res = new_resource(dev, idx++);
+	res->size = 512<<10;
+	res->base = 0xffffffff - (res->size -1);
+	//res->align = log2(res->size);
+	//res->gran = log2(res->size);
+	//res->limit = 0xffffffff;
+	res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_ASSIGNED |
+		     IORESOURCE_STORED;
+
+	#if CONFIG_WRITE_HIGH_TABLES
+	/* Leave some space for ACPI, PIRQ and MP tables */
+	high_tables_base = (tolmk<<10) - HIGH_MEMORY_SIZE;
+	high_tables_size = HIGH_MEMORY_SIZE;
+	printk(BIOS_DEBUG, "high_tables_base: %08llx, size %lld\n",
+	       high_tables_base, high_tables_size);
+	/* Because of the video framebuffer, the high tables may be in a
+	 * different location than in romstage, so we need to copy them over */
+/*	void* old_tables = (void*)((full_tolmk<<10) - HIGH_MEMORY_SIZE);
+	void* new_tables = (void*)((u32)high_tables_base);
+	printk(BIOS_DEBUG, "Moving CBMEM from %p to %p\n",
+			   old_tables, new_tables);
+	memcpy(new_tables, old_tables, HIGH_MEMORY_SIZE);
+	cbmem_reinit(high_tables_base);
+*/	#endif
+	print_debug("======================================================\n");
+	assign_resources(dev->link_list);
+}
+
+static struct device_operations pci_domain_ops = {
+	.read_resources   = pci_domain_read_resources,
+	.set_resources    = vx900_set_resources,
+	.enable_resources = NULL,
+	.init             = NULL,
+	.scan_bus         = pci_domain_scan_bus,
+#if CONFIG_MMCONF_SUPPORT_DEFAULT
+	.ops_pci_bus	  = &pci_ops_mmconf,
+#else
+	.ops_pci_bus	  = &pci_cf8_conf1,
+#endif
+};
+
+static void cpu_bus_init(device_t dev)
+{
+	initialize_cpus(dev->link_list);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+static struct device_operations cpu_bus_ops = {
+	.read_resources   = cpu_bus_noop,
+	.set_resources    = cpu_bus_noop,
+	.enable_resources = cpu_bus_noop,
+	.init             = cpu_bus_init,
+	.scan_bus         = 0,
+};
+
+static void enable_dev(device_t dev)
+{
+	/* Set the operations if it is a special bus type */
+	if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
+		dev->ops = &pci_domain_ops;
+	} else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
+		dev->ops = &cpu_bus_ops;
+	}
+}
+
+struct chip_operations northbridge_via_vx900_ops = {
+	CHIP_NAME("VIA VX900 Chipset")
+	.enable_dev = enable_dev,
+};
+
diff --git a/src/northbridge/via/vx900/raminit.h b/src/northbridge/via/vx900/raminit.h
new file mode 100644
index 0000000..a1b8710
--- /dev/null
+++ b/src/northbridge/via/vx900/raminit.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RAMINIT_VX900_H
+#define RAMINIT_VX900_H
+
+#include <devices/dram/dram.h>
+#include "vx900.h"
+
+#define SPD_END_LIST 0xff
+
+typedef struct dimm_layout_st
+{
+	/* The address of the DIMM on the SMBUS *
+	 * 0xFF to terminate the array*/
+	u8 spd_addr[VX900_MAX_DIMM_SLOTS + 1];
+} dimm_layout;
+
+typedef struct dimm_info_st
+{
+	dimm_attr dimm[VX900_MAX_DIMM_SLOTS];
+} dimm_info;
+
+typedef struct mem_rank_st {
+	u16 start_addr;
+	u16 end_addr;
+}mem_rank;
+
+typedef struct rank_layout_st {
+	u32 phys_rank_size[VX900_MAX_MEM_RANKS];
+	mem_rank virt[VX900_MAX_MEM_RANKS];
+} rank_layout;
+
+typedef struct pci_reg8_st {
+	u8 addr;
+	u8 val;
+} pci_reg8;
+
+typedef u8 timing_dly[8];
+
+typedef struct delay_range_st {
+	timing_dly low;
+	timing_dly avg;
+	timing_dly high;
+} delay_range;
+
+typedef struct vx900_delay_calib_st {
+	delay_range rx_dq_cr;
+	delay_range rx_dqs;
+	delay_range tx_dq;
+	delay_range tx_dqs;
+} vx900_delay_calib;
+
+void vx900_init_dram_ddr3(const dimm_layout *dimms);
+
+#endif /* RAMINIT_VX900_H */
diff --git a/src/northbridge/via/vx900/raminit_ddr3.c b/src/northbridge/via/vx900/raminit_ddr3.c
new file mode 100644
index 0000000..165d539
--- /dev/null
+++ b/src/northbridge/via/vx900/raminit_ddr3.c
@@ -0,0 +1,1036 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011-2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "early_vx900.h"
+#include "raminit.h"
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <delay.h>
+#include <lib.h>
+#include <string.h>
+
+/* Map BA0 to A17, BA1 to A18 */
+/* Map BA2 to A19, RA0/RA1 must not overlap BA[0:2] */
+#define VX900_MRS_MA_MAP   0x4b33       /* MA Pin Mapping for MRS commands */
+#define VX900_CALIB_MA_MAP 0x5911       /* MA Pin mapping for calibrations */
+
+/* Registers 0x78 -> 0x7f contain calibration the settings for DRAM IO timing
+ * The dataset in these registers is selected from 0x70.
+ * Once the correct dataset is selected the delays can be altered.
+ *   delay_type refers to TxDQS, TxDQ, RxDQS, or RxCR
+ *   bound refers to either manual, average, upper bound, or lower bound
+ */
+#define VX900_CALIB_TxDQS		0
+#define VX900_CALIB_TxDQ		1
+#define VX900_CALIB_RxDQS		2
+#define VX900_CALIB_RxDQ_CR		3
+
+#define VX900_CALIB_AVERAGE		0
+#define VX900_CALIB_LOWER		1
+#define VX900_CALIB_UPPER		2
+#define VX900_CALIB_MANUAL		4
+
+static void vx900_delay_calib_mode_select(u8 delay_type, u8 bound)
+{
+	/* Which calibration setting */
+	u8 reg8 = (delay_type & 0x03) << 2;
+	/* Upper, lower, average, or manual setting */
+	reg8 |= (bound & 0x03);
+	pci_write_config8(MCU, 0x70, reg8);
+}
+
+static void vx900_read_0x78_0x7f(timing_dly dly)
+{
+	*((u32*) (&(dly[0]))) = pci_read_config32(MCU, 0x78);
+	*((u32*) (&(dly[4]))) = pci_read_config32(MCU, 0x7c);
+}
+
+static void vx900_write_0x78_0x7f(const timing_dly dly)
+{
+	pci_write_config32(MCU, 0x78, *((u32*) (&(dly[0]))) );
+	pci_write_config32(MCU, 0x7c, *((u32*) (&(dly[4]))) );
+}
+
+static void vx900_read_delay_range(delay_range *d_range, u8 mode)
+{
+	vx900_delay_calib_mode_select(mode, VX900_CALIB_LOWER);
+	vx900_read_0x78_0x7f(d_range->low);
+	vx900_delay_calib_mode_select(mode, VX900_CALIB_AVERAGE);
+	vx900_read_0x78_0x7f(d_range->avg);
+	vx900_delay_calib_mode_select(mode, VX900_CALIB_UPPER);
+	vx900_read_0x78_0x7f(d_range->high);
+}
+
+static void dump_delay(const timing_dly dly)
+{
+	u8 i;
+	for(i = 0; i < 8; i ++)
+	{
+		printram(" %.2x", dly[i]);
+	}
+	printram("\n");
+}
+
+static void dump_delay_range(const delay_range d_range)
+{
+	printram("Lower limit: ");
+	dump_delay(d_range.low);
+	printram("Average:     ");
+	dump_delay(d_range.avg);
+	printram("Upper limit: ");
+	dump_delay(d_range.high);
+}
+
+/* These are some "safe" values that can be used for memory initialization.
+ * Some will stay untouched, and others will be overwritten later on
+ * YOU REALLY NEED THE DATASHEET TO UNDERSTAND THESE !!! */
+static pci_reg8 mcu_init_config[] = {
+	{0x40, 0x01}, /* Virtual rank 0 ending address = 64M - 1 */
+	{0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00}, /* Virtual Ranks ending */
+	{0x48, 0x00}, /* Virtual rank 0 starting address = 0 */
+	{0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00}, /* Virtual Ranks beginning */
+	{0x50, 0xd8}, /* Set ranks 0-3 to 11 col bits, 16 row bits */
+	/* Disable all virtual ranks */
+	{0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+	/* Disable rank interleaving in ranks 0-3 */
+	{0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+	{0x6c, 0xA0}, /* Memory type: DDR3, VDIMM: 1.5V, 64-bit DRAM */
+	{0xc4, 0x80}, /* Enable 8 memory banks */
+	{0xc6, 0x80}, /* Minimum latency from self-refresh. Bit [7] must be 1 */
+	/* FIXME: do it here or in Final config? */
+	{0xc8, 0x80}, /* Enable automatic triggering of short ZQ calibration */
+	{0x99, 0xf0}, /* Power Management and Bypass Reorder Queue */
+	/* Enable differential DQS; MODT assertion values suggested in DS */
+	{0x9e, 0xa1}, {0x9f, 0x51},
+	/* DQ/DQM Duty Control - Do not put any extra delays*/
+	{0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00}, {0xec, 0x00},
+	{0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+	{0xfc, 0x00}, {0xfd, 0x00}, {0xfe, 0x00}, {0xff, 0x00},
+	/* The following parameters we may or may not change */
+	{0x61, 0x2e}, /* DRAMC Pipeline Control */
+	{0x77, 0x10}, /* MDQS Output Control */
+
+	/* The following are parameters we'll most likely never change again */
+	{0x60, 0xf4}, /* DRAM Pipeline Turn-Around Setting */
+	{0x65, 0x49}, /* DRAM Arbitration Bandwidth Timer - I */
+	{0x66, 0x80}, /* DRAM Queue / Arbitration */
+	{0x69, 0xc6}, /* Bank Control: 8 banks, high priority refresh */
+	{0x6a, 0xfc}, /* DRAMC Request Reorder Control */
+	{0x6e, 0x38}, /* Burst lenght: 8, burst-chop: enable */
+	{0x73, 0x04}, /* Close All Pages Threshold */
+
+	/* The following need to be dynamically asserted */
+	/* See: check_special_registers.c */
+	{0x74, 0xa0}, /* Yes, same 0x74; add one more T */
+	{0x76, 0x60}, /* Write Data Phase Control */
+
+};
+
+/* This table keeps the driving strength control setting that we can safely use
+ * doring initialization. */
+static pci_reg8 mcu_drv_ctrl_config[] = {
+	{0xd3, 0x03}, /* Enable auto-compensation circuit for ODT strength */
+	{0xd4, 0x80}, /* Set internal ODT to dynamically turn on or off */
+	{0xd6, 0x20}, /* Enable strong driving for MA and DRAM commands*/
+	{0xd0, 0x88}, /* (ODT) Strength ?has effect? */
+	{0xe0, 0x88}, /* DRAM Driving – Group DQS (MDQS) */
+	{0xe1, 0x00}, /* Disable offset mode for driving strength control */
+	{0xe2, 0x88}, /* DRAM Driving – Group DQ (MD, MDQM) */
+	{0xe4, 0xcc}, /* DRAM Driving – Group CSA (MCS, MCKE, MODT) */
+	{0xe8, 0x88}, /* DRAM Driving – Group MA (MA, MBA, MSRAS, MSCAS, MSWE)*/
+	{0xe6, 0xff}, /* DRAM Driving – Group DCLK0 (DCLK[2:0] for DIMM0) */
+	{0xe7, 0xff}, /* DRAM Driving – Group DCLK1 (DCLK[5:3] for DIMM1) */
+	{0xe4, 0xcc}, /* DRAM Driving – Group CSA (MCS, MCKE, MODT)*/
+	{0x91, 0x08}, /* MCLKO Output Phase Delay - I */
+	{0x92, 0x08}, /* MCLKO Output Phase Delay - II */
+	{0x93, 0x16}, /* CS/CKE Output Phase Delay */
+	{0x95, 0x16}, /* SCMD/MA Output Phase Delay */
+	{0x9b, 0x3f}, /* Memory Clock Output Enable */
+};
+
+static void vx900_dram_set_ma_map(u16 map)
+{
+	pci_write_config16(MCU, 0x52, map);
+}
+
+static void vx900_dram_write_init_config(void)
+{
+	/* Keep our RAM space free of legacy stuff */
+	vx900_disable_legacy_rom_shadow();
+
+	/* Now worry about the real RAM init */
+	size_t i;
+	for(i = 0; i < (sizeof(mcu_init_config)/sizeof(pci_reg8)); i++)
+	{
+		pci_write_config8(MCU, mcu_init_config[i].addr,
+				  mcu_init_config[i].val);
+	}
+	vx900_dram_set_ma_map(VX900_CALIB_MA_MAP);
+}
+
+static void dram_find_spds_ddr3(const dimm_layout *addr, dimm_info *dimm)
+{
+	size_t i = 0;
+	int dimms = 0;
+	do {
+		spd_raw_data spd;
+		spd_read(addr->spd_addr[i], spd);
+		spd_decode_ddr3(&dimm->dimm[i], spd);
+		if(dimm->dimm[i].dram_type != DRAM_TYPE_DDR3) continue;
+		dimms++;
+		dram_print_spd_ddr3(&dimm->dimm[i]);
+	} while(addr->spd_addr[++i] != SPD_END_LIST
+		&& i < VX900_MAX_DIMM_SLOTS);
+
+	if(!dimms)
+		die("No DIMMs were found");
+}
+
+static void dram_find_common_params(const dimm_info *dimms, ramctr_timing *ctrl)
+{
+	size_t  i, valid_dimms;
+	memset(ctrl, 0, sizeof(ramctr_timing));
+	ctrl->cas_supported = 0xff;
+	valid_dimms = 0;
+	for(i = 0; i < VX900_MAX_DIMM_SLOTS; i++)
+	{
+		const dimm_attr *dimm = &dimms->dimm[i];
+		if(dimm->dram_type == DRAM_TYPE_UNDEFINED) continue;
+		valid_dimms++;
+
+		if(valid_dimms == 1) {
+			/* First DIMM defines the type of DIMM */
+			ctrl->dram_type = dimm->dram_type;
+		} else {
+			/* Check if we have mismatched DIMMs */
+			if(ctrl->dram_type != dimm->dram_type)
+				die("Mismatched DIMM Types");
+		}
+		/* Find all possible CAS combinations */
+		ctrl->cas_supported &= dimm->cas_supported;
+
+		/* Find the smallest common latencies supported by all DIMMs */
+		ctrl->tCK  = max(ctrl->tCK,  dimm->tCK );
+		ctrl->tAA  = max(ctrl->tAA,  dimm->tAA );
+		ctrl->tWR  = max(ctrl->tWR,  dimm->tWR );
+		ctrl->tRCD = max(ctrl->tRCD, dimm->tRCD);
+		ctrl->tRRD = max(ctrl->tRRD, dimm->tRRD);
+		ctrl->tRP  = max(ctrl->tRP,  dimm->tRP );
+		ctrl->tRAS = max(ctrl->tRAS, dimm->tRAS);
+		ctrl->tRC  = max(ctrl->tRC,  dimm->tRC );
+		ctrl->tRFC = max(ctrl->tRFC, dimm->tRFC);
+		ctrl->tWTR = max(ctrl->tWTR, dimm->tWTR);
+		ctrl->tRTP = max(ctrl->tRTP, dimm->tRTP);
+		ctrl->tFAW = max(ctrl->tFAW, dimm->tFAW);
+
+	}
+
+	if(!ctrl->cas_supported) die("Unsupported DIMM combination. "
+		"DIMMS do not support common CAS latency");
+	if(!valid_dimms) die("No valid DIMMs found");
+}
+
+static void vx900_dram_phys_bank_range(const dimm_info *dimms,
+				       rank_layout *ranks)
+{
+	size_t i;
+	for(i = 0; i < VX900_MAX_DIMM_SLOTS; i ++)
+	{
+		if(dimms->dimm[i].dram_type == DRAM_TYPE_UNDEFINED)
+			continue;
+		u8 nranks = dimms->dimm[i].ranks;
+		if(nranks > 2)
+			die("Found DIMM with more than two ranks, which is not "
+			"supported by this chipset");
+		u32 size = dimms->dimm[i].size;
+		if(nranks == 2) {
+			/* Each rank holds half the capacity of the DIMM */
+			size >>= 1;
+			ranks->phys_rank_size[i<<1] = size;
+			ranks->phys_rank_size[(i<<1) | 1] = size;
+		} else {
+			/* Otherwise, everything is held in the first bank */
+			ranks->phys_rank_size[i<<1] = size;
+			ranks->phys_rank_size[(i<<1) | 1] = 0;;
+		}
+	}
+}
+
+static void vx900_dram_driving_ctrl(const dimm_info *dimm)
+{
+	size_t i, ndimms;
+	u8 val;
+
+	/* For ODT range selection, datasheet recommends
+	 * when 1 DIMM  present:  60 Ohm
+	 * when 2 DIMMs present: 120 Ohm  */
+	ndimms = 0;
+	for(i = 0; i < VX900_MAX_DIMM_SLOTS; i++) {
+		if(dimm->dimm[i].dram_type == DRAM_TYPE_DDR3) ndimms++;
+	}
+	val = (ndimms > 1) ? 0x0 : 0x1;
+	pci_write_config8(MCU, 0xd5, val << 2);
+
+
+	/* FIXME: Assert dynamically based on dimm config */
+	/* DRAM ODT Lookup Table*/
+	pci_write_config8(MCU, 0x9c, 0xe4);
+
+	for(i = 0; i < (sizeof(mcu_drv_ctrl_config)/sizeof(pci_reg8)); i++)
+	{
+		pci_write_config8(MCU, mcu_drv_ctrl_config[i].addr,
+				  mcu_drv_ctrl_config[i].val);
+	}
+}
+
+static void vx900_pr_map_all_vr3(void)
+{
+	/* Enable all ranks and set them to VR3 */
+	pci_write_config16(MCU, 0x54, 0xbbbb);
+}
+/* Map physical rank pr to virtual rank vr */
+static void vx900_map_pr_vr(u8 pr, u8 vr)
+{
+	pr &= 0x3; vr &= 0x3;
+	/* Enable rank (bit [3], and set the VR number bits [1:0] */
+	u16 val = 0x8 | vr;
+	/* Now move the value to the appropriate PR */
+	val <<= (pr * 4);
+	pci_mod_config16(MCU, 0x54, 0xf << (pr * 4), val);
+	printram("Mapping PR %u to VR %u\n", pr, vr);
+}
+
+static u8 vx900_get_CWL(u8 CAS)
+{
+	/* Get CWL based on CAS using the following rule:
+	 *       _________________________________________
+	 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
+	 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T |  7T |  8T |
+	 */
+	static const u8 cas_cwl_map[] = {5, 5, 5, 6, 6, 7, 7, 8};
+	if(CAS > 11) return 8;
+	return cas_cwl_map[CAS - 4];
+}
+
+static void vx900_dram_timing(ramctr_timing *ctrl)
+{
+	/* Here we are calculating latencies, and writing them to the appropiate
+	 * registers. Some registers do not take latencies from 0T, for example:
+	 * CAS: 000 = 4T, 001 = 5T, 010 = 6T, etc
+	 * In this example we subtract 4T from the result for CAS: (val - 4)
+	 * The & 0x07 after (val - T0) just makes sure that, no matter what
+	 * crazy thing may happen, we do not write outside the bits allocated
+	 * in the register */
+	u8 reg8, val, tFAW, tRRD;
+	u32 val32;
+
+	/* Maximum supported DDR3 frequency is 533MHz (DDR3 1066)
+	 * so make sure we cap it if we have faster DIMMs */
+	if(ctrl->tCK < TCK_533MHZ) ctrl->tCK = TCK_533MHZ;
+	val32 = (1000 << 8) / ctrl->tCK;
+	printram("Selected DRAM frequency: %u MHz\n", val32);
+
+	/* Now find the right DRAM frequency setting,
+	 * and align it to the closest JEDEC standard frequency */
+	if(ctrl->tCK <= TCK_533MHZ)      {val = 0x07; ctrl->tCK = TCK_533MHZ;}
+	else if(ctrl->tCK <= TCK_400MHZ) {val = 0x06; ctrl->tCK = TCK_400MHZ;}
+	else if(ctrl->tCK <= TCK_333MHZ) {val = 0x05; ctrl->tCK = TCK_333MHZ;}
+	else if(ctrl->tCK <= TCK_266MHZ) {val = 0x04; ctrl->tCK = TCK_266MHZ;}
+
+	/* Find CAS and CWL latencies */
+	val = (ctrl->tAA + ctrl->tCK -1) / ctrl->tCK;
+	printram("Minimum  CAS latency   : %uT\n", val);
+	/* Find lowest supported CAS latency that satisfies the minimum value */
+	while( !((ctrl->cas_supported >> (val-4))&1)
+		&& (ctrl->cas_supported >> (val-4))) {
+		val++;
+	}
+	/* Is CAS supported */
+	if(!(ctrl->cas_supported & (1 << (val-4))) )
+		printram("CAS not supported\n");
+	printram("Selected CAS latency   : %uT\n", val);
+	ctrl->CAS = val;
+	ctrl->CWL = vx900_get_CWL(ctrl->CAS);
+	printram("Selected CWL latency   : %uT\n", ctrl->CWL);
+	/* Write CAS and CWL */
+	reg8 = ( ((ctrl->CWL - 4) &0x07) << 4 ) | ((ctrl->CAS - 4) & 0x07);
+	pci_write_config8(MCU, 0xc0, reg8);
+
+	/* Find tRCD */
+	val = (ctrl->tRCD + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tRCD          : %uT\n", val);
+	reg8 = ((val-4) & 0x7) << 4;
+	/* Find tRP */
+	val = (ctrl->tRP + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tRP           : %uT\n", val);
+	reg8 |= ((val-4) & 0x7);
+	pci_write_config8(MCU, 0xc1, reg8);
+
+	/* Find tRAS */
+	val = (ctrl->tRAS + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tRAS          : %uT\n", val);
+	reg8 = ((val-15) & 0x7) << 4;
+	/* Find tWR */
+	ctrl->WR = (ctrl->tWR + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tWR           : %uT\n", ctrl->WR);
+	reg8 |= ((ctrl->WR-4) & 0x7);
+	pci_write_config8(MCU, 0xc2, reg8);
+
+	/* Find tFAW */
+	tFAW = (ctrl->tFAW + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tFAW          : %uT\n", tFAW);
+	/* Find tRRD */
+	tRRD = (ctrl->tRRD + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tRRD          : %uT\n", tRRD);
+	val = tFAW - 4*tRRD;	/* number of cycles above 4*tRRD */
+	reg8 = ((val-0) & 0x7) << 4;
+	reg8 |= ((tRRD-2) & 0x7);
+	pci_write_config8(MCU, 0xc3, reg8);
+
+	/* Find tRTP */
+	val = (ctrl->tRTP + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tRTP          : %uT\n", val);
+	reg8 = ((val & 0x3) << 4);
+	/* Find tWTR */
+	val = (ctrl->tWTR + ctrl->tCK -1) / ctrl->tCK;
+	printram("Selected tWTR          : %uT\n", val);
+	reg8 |= ((val - 2) & 0x7);
+	pci_mod_config8(MCU, 0xc4, 0x3f, reg8);
+
+	/* DRAM Timing for All Ranks - VI
+	 * [7:6] CKE Assertion Minimum Pulse Width
+	 *     We probably don't want to mess with this just yet.
+	 * [5:0] Refresh-to-Active or Refresh-to-Refresh (tRFC)
+	 *     tRFC = (30 + 2 * [5:0])T
+	 *     Since we previously set RxC4[7]
+	 */
+	reg8 = pci_read_config8(MCU, 0xc5);
+	val = (ctrl->tRFC + ctrl->tCK -1) / ctrl->tCK;
+	printram("Minimum  tRFC          : %uT\n", val);
+	if(val < 30) {
+		val = 0;
+	} else {
+		val = (val -30 + 1 ) / 2;
+	}
+	;
+	printram("Selected tRFC          : %uT\n", 30 + 2 * val);
+	reg8 |= (val & 0x3f);
+	pci_write_config8(MCU, 0xc5, reg8);
+
+	/* Where does this go??? */
+	val = (ctrl->tRC + ctrl->tCK -1) / ctrl->tCK;
+	printram("Required tRC           : %uT\n", val);
+}
+
+static void vx900_dram_freq(ramctr_timing *ctrl)
+{
+	u8 val;
+
+	/* Program the DRAM frequency */
+
+	/* Step 1 - Reset the PLL */
+	pci_mod_config8(MCU, 0x90, 0x00, 0x0f);
+	/* Wait at least 10 ns; VIA code delays by 640us */
+	udelay(640);
+
+	/* Step 2 - Set target frequency */
+	if(ctrl->tCK <= TCK_533MHZ)      {val = 0x07; ctrl->tCK = TCK_533MHZ;}
+	else if(ctrl->tCK <= TCK_400MHZ) {val = 0x06; ctrl->tCK = TCK_400MHZ;}
+	else if(ctrl->tCK <= TCK_333MHZ) {val = 0x05; ctrl->tCK = TCK_333MHZ;}
+	else /*ctrl->tCK <= TCK_266MHZ*/ {val = 0x04; ctrl->tCK = TCK_266MHZ;}
+	/* Restart the PLL with the desired frequency */
+	pci_mod_config8(MCU, 0x90, 0x0f, val);
+
+	/* Step 3 - Wait for PLL to stabilize */
+	udelay(2000);
+
+	/* Step 4 - Reset the DLL - Clear [7,4]*/
+	pci_mod_config8(MCU, 0x6b, 0x90, 0x00);
+	udelay(2000);
+
+	/* Step 5 - Enable the DLL - Set bits [7,4] to 01b*/
+	pci_mod_config8(MCU, 0x6b, 0x00, 0x10);
+	udelay(2000);
+
+	/* Step 6 - Start DLL Calibration - Set bit [7] */
+	pci_mod_config8(MCU, 0x6b, 0x00, 0x80);
+	udelay(5);
+
+	/* Step 7 - Finish DLL Calibration - Clear bit [7]*/
+	pci_mod_config8(MCU, 0x6b, 0x80, 0x00);
+
+	/* Step 8 - If we have registered DIMMs, we need to set bit[0] */
+	if(dimm_is_registered(ctrl->dram_type)){
+		printram("Enabling RDIMM support in memory controller\n");
+		pci_mod_config8(MCU, 0x6c, 0x00, 0x01);
+	}
+}
+
+
+void vx900_dram_ddr3_do_hw_mrs(u8 ma_swap, u8 rtt_nom,
+				      u8 ods, u8 rtt_wr, u8 srt, u8 asr);
+/*static*/ void vx900_dram_ddr3_do_hw_mrs(u8 ma_swap, u8 rtt_nom,
+				      u8 ods, u8 rtt_wr, u8 srt, u8 asr)
+{
+	/* The VX900 can send the MRS commands directly through hardware
+	 * It does the MR2->MR3->MR1->MR0->LongZQ dance*/
+	u16 reg16 = 0;
+	if(asr) reg16 |= (1 << 8);
+	if(srt) reg16 |= (1 << 9);
+	reg16 |= ((rtt_wr & 0x03) << 12);
+	if(ma_swap) reg16 |= (1 << 1);
+	reg16 |= ((ods & 0x03) << 2);
+	reg16 |= ((rtt_nom & 0x7) << 4);
+	reg16 |= 1; /* This is the trigger bit */
+	pci_write_config16(MCU, 0xcc, reg16);
+	/* Wait for MRS commands to be sent */
+	while(pci_read_config8(MCU, 0xcc) & 1);
+}
+#include "forgotten.h"
+#include "forgotten.c"
+
+static void vx900_dram_send_soft_mrs(u8 type, u16 cmd)
+{
+	u32 addr;
+	/* Set Fun3_RX6B[2:0] to 011b (MSR Enable). */
+	pci_mod_config8(MCU, 0x6b, 0x07, (3<<0));
+	/* Find the address corresponding to the MRS */
+	addr = vx900_get_mrs_addr(type, cmd);
+	/* Execute the MRS */
+	volatile_read(addr);
+	/* Set Fun3_Rx6B[2:0] to 000b (Normal SDRAM Mode). */
+	pci_mod_config8(MCU, 0x6b, 0x07, 0x00);
+}
+
+static void vx900_dram_ddr3_dimm_init(const ramctr_timing *ctrl,
+				      const rank_layout *ranks)
+{
+	size_t i;
+
+	/* Set BA[0/1/2] to [A17/18/19] */
+	vx900_dram_set_ma_map(VX900_MRS_MA_MAP);
+
+	/* Step 01 - Set Fun3_Rx6E[5] to 1b to support burst length. */
+	pci_mod_config8(MCU, 0x6e, 0, 1<<5);
+	/* Step 02 - Set Fun3_RX69[0] to 0b (Disable Multiple Page Mode). */
+	pci_mod_config8(MCU, 0x69, (1<<0), 0x00);
+	/* And set [7:6] to 10b ?*/
+	pci_write_config8(MCU, 0x69, 0x87);
+
+	/* Step 03 - Set the target physical rank to virtual rank0 and other
+	 * ranks to virtual rank3. */
+	vx900_pr_map_all_vr3();
+
+	/* Step 04 - Set Fun3_Rx50 to D8h. */
+	pci_write_config8(MCU, 0x50, 0xd8);
+	/* Step 05 - Set Fun3_RX6B[5] to 1b to de-assert RESET# and wait for at
+	 * least 500 us. */
+	pci_mod_config8(MCU, 0x6b, 0x00, (1<<5) );
+	udelay(500);
+
+	/* Step 6 -> 15 - Set the target physical rank to virtual rank 0 and
+	 * other ranks to virtual rank 3.
+	 * Repeat Step 6 to 14 for every rank present, then jump to Step 16. */
+	for(i = 0; i < VX900_MAX_MEM_RANKS; i++)
+	{
+		if(ranks->phys_rank_size[i] == 0) continue;
+		printram("Initializing rank %lu\n", i);
+
+		/* Set target physical rank to virtual rank 0
+		 * other ranks to virtual rank 3*/
+		vx900_map_pr_vr(i, 0);
+
+		/* FIXME: Is this needed on HW init? */
+		pci_mod_config8(MCU, 0x6b, 0x07, 0x01);	/* Enable NOP */
+		volatile_read(0x0);			/* Do NOP */
+		pci_mod_config8(MCU, 0x6b, 0x07, 0x03);	/* MSR Enable */
+
+		/* FIXME: Values dependent on DIMM setup
+		 * This works for 1 DIMM
+		 * See init_dram_by_rank.c and get_basic_information.c
+		 * in the VIA provided code */
+		const u8 rtt_nom = DDR3_MR1_RTT_NOM_RZQ2;
+		const u8 ods = DDR3_MR1_ODS_RZQ6;
+		const u8 rtt_wr = DDR3_MR2_RTT_WR_OFF;
+
+		printram("Using Hardware method\n");
+		/* FIXME: MA swap dependent on module */
+		vx900_dram_ddr3_do_hw_mrs(0, rtt_nom, ods, rtt_wr, 0, 0);
+
+		/* Normal SDRAM Mode */
+		pci_mod_config8(MCU, 0x6b, 0x07, 0x00);
+
+		/* Step 15, set the rank to virtual rank 3*/
+		vx900_map_pr_vr(i, 3);
+	}
+
+	/* Step 16 – Set Fun3_Rx6B[2:0] to 000b (Normal SDRAM Mode). */
+	pci_mod_config8(MCU, 0x6b, 0x07, 0x00);
+
+	/* Set BA[0/1/2] to [A13/14/15] */
+	vx900_dram_set_ma_map(VX900_CALIB_MA_MAP);
+
+	/* Step 17 – Set Fun3_Rx69[0] to 1b (Enable Multiple Page Mode). */
+	pci_mod_config8(MCU, 0x69, 0x00, (1<<0) );
+
+	printram("DIMM initialization sequence complete\n");
+}
+
+static void vx900_dram_enter_read_leveling(void)
+{
+	/* Precharge all before issuing read leveling MRS to DRAM */
+	pci_mod_config8(MCU, 0x06b, 0x07, 0x02);
+	volatile_read(0x0);
+	udelay(1000);
+
+	/* Enable read leveling: Set D0F3Rx71[7]=1 */
+	pci_mod_config8(MCU, 0x71, 0x40, 0x80);
+
+	/* Put DRAM in read leveling mode */
+	u16 cmd = ddr3_get_mr3(1);
+	vx900_dram_send_soft_mrs(3, cmd);
+}
+
+static void vx900_dram_exit_read_leveling(void)
+{
+	/* Disable read leveling, and put dram in normal operation mode */
+	u16 cmd = ddr3_get_mr3(0);
+	vx900_dram_send_soft_mrs(3, cmd);
+
+	/* Disable read leveling: Set D0F3Rx71[7]=0 */
+	pci_mod_config8(MCU, 0x71, 1<<7, 0);
+}
+
+static void vx900_rx_capture_range_calib(void)
+{
+	u8 reg8;
+	const u32 cal_addr = 0x20;
+
+	/* Set IO calibration address */
+	pci_mod_config16(MCU, 0x8c , 0xfff0, cal_addr&(0xfff0));
+	/* Data pattern must be 0x00 for this calibration
+	 * See paragraph describing Rx8e */
+	pci_write_config8(MCU, 0x8e, 0x00);
+
+	/* Need to put DRAM and MCU in read leveling */
+	vx900_dram_enter_read_leveling();
+
+	/* Data pattern must be 0x00 for this calibration
+	 * See paragraph describing Rx8e */
+	pci_write_config8(MCU, 0x8e, 0x00);
+	/* Trigger calibration */
+	reg8 = 0xa0;
+	pci_write_config8(MCU, 0x71, reg8);
+
+	/* Wait for it */
+	while(pci_read_config8(MCU, 0x71) & 0x10);
+	vx900_dram_exit_read_leveling();
+}
+
+static void vx900_rx_dqs_delay_calib(void)
+{
+	const u32 cal_addr = 0x30;
+
+	/* We need to disable refresh commands so that they don't interfere */
+	const u8 ref_cnt = pci_read_config8(MCU, 0xc7);
+	pci_write_config8(MCU, 0xc7, 0);
+	/* Set IO calibration address */
+	pci_mod_config16(MCU, 0x8c , 0xfff0, cal_addr&(0xfff0));
+	/* Data pattern must be 0x00 for this calibration
+	 * See paragraph describing Rx8e */
+	pci_write_config8(MCU, 0x8e, 0x00);
+
+	/* Need to put DRAM and MCU in read leveling */
+	vx900_dram_enter_read_leveling();
+
+	/* From VIA code; Undocumented
+	 * In theory this enables MODT[3:0] to be asserted */
+	pci_mod_config8(MCU, 0x9e, 0, 0x80);
+
+	/* Trigger calibration: Set D0F3Rx71[1:0]=10b */
+	pci_mod_config8(MCU, 0x71, 0x03, 0x02);
+
+	/* Wait for calibration to complete */
+	while( pci_read_config8(MCU, 0x71) & 0x02 );
+	vx900_dram_exit_read_leveling();
+
+	/* Restore the refresh counter*/
+	pci_write_config8(MCU, 0xc7, ref_cnt);
+
+	/* FIXME: should we save it before, or should we just set it as is */
+	vx900_dram_set_ma_map(VX900_CALIB_MA_MAP);
+}
+
+static void vx900_tx_dqs_trigger_calib(u8 pattern)
+{
+	u32 i;
+	/* Data pattern for calibration */
+	pci_write_config8(MCU, 0x8e, pattern);
+	/* Trigger calibration */
+	pci_mod_config8(MCU, 0x75, 0, 0x20);
+	/* Wait for calibration */
+	i = 0;
+	while(pci_read_config8(MCU, 0x75) & 0x20) i++;
+	printram(" Tx DQS calib took %u PCI cycles\n", i);
+}
+static void vx900_tx_dqs_delay_calib(void)
+{
+	const u32 cal_addr = 0x00;
+	/* Set IO calibration address */
+	pci_mod_config16(MCU, 0x8c , 0xfff0, cal_addr&(0xfff0));
+	/* Set circuit to use calibration results - Clear Rx75[0]*/
+	pci_mod_config8(MCU, 0x75, 0x01, 0);
+	/* Run calibration with first data pattern*/
+	vx900_tx_dqs_trigger_calib(0x5a);
+	/* Run again with different pattern */
+	vx900_tx_dqs_trigger_calib(0xa5);
+}
+
+static void vx900_tx_dq_delay_calib(void)
+{
+	int i = 0;
+	/* Data pattern for calibration */
+	pci_write_config8(MCU, 0x8e, 0x5a);
+	/* Trigger calibration */
+	pci_mod_config8(MCU, 0x75, 0, 0x02);
+	/* Wait for calibration */
+	while(pci_read_config8(MCU, 0x75) & 0x02) i++;
+	printram("TX DQ calibration took %u PCI cycles\n", i);
+}
+
+static void vx900_rxdqs_adjust(delay_range *dly)
+{
+	/* Adjust Rx DQS delay after calibration has been run. This is
+	 * recommended by VIA, but no explanation was provided as to why */
+	size_t i;
+	for(i = 0; i < 8; i++)
+	{
+		if(dly->low[i] < 3)
+		{
+			if(i == 2 || i== 4) dly->low[i] += 4;
+			else dly->avg[i] += 3;
+
+		}
+
+		if(dly->high[i] > 0x38) dly->avg[i] -= 6;
+		else if(dly->high[i] > 0x30) dly->avg[i] -= 4;
+
+		if(dly->avg[i] > 0x20) dly->avg[i] = 0x20;
+	}
+
+	/* Put Rx DQS delay into manual mode (Set Rx[2,0] to 01) */
+	pci_mod_config8(MCU, 0x71, 0x05, 0x01);
+	/* Now write the new settings */
+	vx900_delay_calib_mode_select(VX900_CALIB_RxDQS, VX900_CALIB_MANUAL);
+	vx900_write_0x78_0x7f(dly->avg);
+}
+
+static void vx900_dram_calibrate_delays(const ramctr_timing *ctrl,
+				   const rank_layout *ranks)
+{
+	timing_dly dly;
+	size_t i;
+	u8 val;
+	vx900_delay_calib delay_cal;
+	memset(&delay_cal, 0, sizeof(delay_cal));
+	printram("Starting delay calibration\n");
+
+	/**** Read delay control ****/
+	/* MD Input Data Push Timing Control;
+	 *     use values recommended in datasheet
+	 * Setting this too low causes the Rx window to move below the range we
+	 * need it so we can capture it with Rx_78_7f
+	 * This causes Rx calibrations to be too close to 0, and Tx
+	 * calibrations will fail.
+	 * Setting this too high causes the window to move above the range.
+	 */
+	if      (ctrl->tCK <= TCK_533MHZ) val = 2;
+	else if (ctrl->tCK <= TCK_333MHZ) val = 1;
+	else	 val = 0;
+	val ++; /* FIXME: vendor BIOS sets this to 3 */
+	pci_mod_config8(MCU, 0x74, (0x03 << 1), ((val & 0x03) << 1) );
+
+	/* FIXME: The vendor BIOS increases the MD input delay - WHY ? */
+	pci_mod_config8(MCU, 0xef, (3<<4), 3<<4);
+
+
+	/**** Write delay control ****/
+	/* FIXME: The vendor BIOS does this, but WHY?
+	 * Early DQ/DQS for write cycles */
+	pci_mod_config8(MCU, 0x76, (3<<2), 2<<2);
+	/* FIXME: The vendor BIOS does this - Output preamble ?*/
+	pci_write_config8(MCU, 0x77, 0x10);
+
+	/* FIXME: Vendor BIOS goes in with
+	 * 8 page registers
+	 * multiple page mode
+	 * High Priority Refresh request
+	 * -- WHY?*/
+	pci_write_config8(MCU, 0x69, 0xc7);
+
+	/* Set BA[0/1/2] to [A17/18/19] */
+	vx900_dram_set_ma_map(VX900_MRS_MA_MAP);
+	/* Disable Multiple Page Mode - Set Rx69[0] to 0 */
+	pci_mod_config8(MCU, 0x69, (1<<0), 0x00);
+
+	/* It's very important that we keep all ranks which are not calibrated
+	 * mapped to VR3. Even if we disable them, if they are mapped to VR0
+	 * (the rank we use for calibrations), the calibrations may fail in
+	 * unexpected ways. */
+	vx900_pr_map_all_vr3();
+
+	for(i = 0; i < VX900_MAX_DIMM_SLOTS; i++)
+	{
+		/* Do we have a valid DIMM? */
+		if(ranks->phys_rank_size[i] + ranks->phys_rank_size[i+1] == 0 )
+			continue;
+
+		/* Map the first rank of the DIMM to VR0 */
+		vx900_map_pr_vr(2*i, 0);
+
+		/* Run calibrations */
+		if(0){
+		/* If we run this if(0) block, everything else may fail
+		 * putting a huge delay after this block sometimes fixes the
+		 * issue. */
+		vx900_rx_capture_range_calib();
+		vx900_read_delay_range(&(delay_cal.rx_dq_cr),
+				       VX900_CALIB_RxDQ_CR);
+		dump_delay_range(delay_cal.rx_dq_cr);}
+
+		/*FIXME: Cheating with Rx CR setting
+		 * We need to either use Rx CR calibration
+		 * or set up a table for the calibration */
+		dly[0] = 0x28; dly[1] = 0x1c; dly[2] = 0x28; dly[3] = 0x28;
+		dly[4] = 0x2c; dly[5] = 0x30; dly[6] = 0x30; dly[7] = 0x34;
+		printram("Bypassing RxCR 78-7f calibration with:\n");
+		dump_delay(dly);
+		/* We need to put the setting on manual mode */
+		pci_mod_config8(MCU, 0x71, 0, 0x10);
+		vx900_delay_calib_mode_select(VX900_CALIB_RxDQ_CR, VX900_CALIB_MANUAL);
+		vx900_write_0x78_0x7f(dly);
+
+		/************* RxDQS *************/
+		vx900_rx_dqs_delay_calib();
+		vx900_read_delay_range(&(delay_cal.rx_dqs), VX900_CALIB_RxDQS);
+		printram("RX DQS calibration results\n");
+		dump_delay_range(delay_cal.rx_dqs);
+
+		vx900_rxdqs_adjust(&(delay_cal.rx_dqs));
+
+		vx900_read_delay_range(&(delay_cal.rx_dqs), VX900_CALIB_RxDQS);
+		printram("RX DQS calibration results after adjustment\n");
+		dump_delay_range(delay_cal.rx_dqs);
+
+		/* Enable multiple page mode */
+		pci_mod_config8(MCU, 0x69, 0, 1<<1);
+
+		/* FIXME: this is done by vendor BIOS, and recommended by VIA
+		 * However, datasheet says that bit[7] is reserved, and
+		 * calibration works just as well if we don't set this to 1b .
+		 * Should we really do this, or can we drop it ? */
+		if(ctrl->tCK <= TCK_533MHZ){
+		for( i = 0; i< 8; i++) dly[i] = 0x80;
+		pci_mod_config8(MCU, 0x75, 0x00, 0x01); /* manual Tx DQ DQS */
+		vx900_delay_calib_mode_select(VX900_CALIB_TxDQ, VX900_CALIB_MANUAL);
+		vx900_write_0x78_0x7f(dly);
+		vx900_delay_calib_mode_select(VX900_CALIB_TxDQS, VX900_CALIB_MANUAL);
+		vx900_write_0x78_0x7f(dly);
+		}
+
+		/************* TxDQS *************/
+		vx900_tx_dqs_delay_calib();
+
+		vx900_read_delay_range(&(delay_cal.tx_dqs), VX900_CALIB_TxDQS);
+		printram("Tx DQS calibration results\n");
+		dump_delay_range(delay_cal.tx_dqs);
+		/************* TxDQ  *************/
+		/* FIXME: not sure if multiple page mode should be enabled here
+		 * Vendor BIOS does it */
+		pci_mod_config8(MCU, 0x69, 0 , 0x01);
+
+		vx900_tx_dq_delay_calib();
+		vx900_read_delay_range(&(delay_cal.tx_dq), VX900_CALIB_TxDQ);
+		printram("TX DQ delay calibration results:\n");
+		dump_delay_range(delay_cal.tx_dq);
+
+		/* write manual settings */
+		pci_mod_config8(MCU, 0x75, 0, 0x01);
+		vx900_delay_calib_mode_select(VX900_CALIB_TxDQS, VX900_CALIB_MANUAL);
+		vx900_write_0x78_0x7f(delay_cal.tx_dqs.avg);
+		vx900_delay_calib_mode_select(VX900_CALIB_TxDQ, VX900_CALIB_MANUAL);
+		vx900_write_0x78_0x7f(delay_cal.tx_dq.avg);
+	}
+}
+
+static void vx900_dram_set_refresh_counter(ramctr_timing *ctrl)
+{
+	u8 reg8;
+	/* Set DRAM refresh counter
+	 * Based on a refresh counter of 0x61 at 400MHz */
+	reg8 = (TCK_400MHZ * 0x61) / ctrl->tCK;
+	pci_write_config8(MCU, 0xc7, reg8);
+}
+
+static void vx900_dram_range(ramctr_timing *ctrl, rank_layout *ranks)
+{
+	size_t i, vrank = 0;
+	u8 reg8;
+	u32 ramsize = 0;
+	/* All unused physical ranks go to VR3. Otherwise, the MCU might be
+	 * trying to read or write from unused ranks, or even worse, write some
+	 * bits to the rank we want, and some to the unused ranks, even though
+	 * they are disabled. Since VR3 is the last virtual rank to be used, we
+	 * eliminate any ambiguities that the MCU may face. */
+	vx900_pr_map_all_vr3();
+	for(i = 0; i < VX900_MAX_MEM_RANKS; i++)
+	{
+		u32 rank_size = ranks->phys_rank_size[i];
+		if(!rank_size) continue;
+		ranks->virt[vrank].start_addr = ramsize;
+		ramsize += rank_size;
+		ranks->virt[vrank].end_addr = ramsize;
+
+		/* Rank memory range */
+		reg8 = (ranks->virt[vrank].start_addr >> 2);
+		pci_write_config8(MCU, 0x48 + vrank, reg8);
+		reg8 = (ranks->virt[vrank].end_addr >> 2);
+		pci_write_config8(MCU, 0x40 + vrank, reg8);
+
+		vx900_map_pr_vr(i, vrank);
+
+		printram("Mapped Physical rank %u, to virtual rank %u\n"
+			 "    Start address: 0x%.8x000000\n"
+			 "    End   address: 0x%.8x000000\n",
+			 (int) i, (int) vrank,
+			 ranks->virt[vrank].start_addr,
+			 ranks->virt[vrank].end_addr);
+		/* Move on to next virtual rank */
+		vrank++;
+	}
+
+	/* FIXME: What if our RAM overlaps the PCI config space? */
+	/* We need to write the top low address to the MCU */
+	u32 tolmk = ramsize * (RAM_UNIT >> 10);
+	u16 chip_tolm = (tolmk >> 6) & 0xfff0;
+	pci_mod_config16(MCU, 0x84, 0xfff0, chip_tolm);
+
+	printram("Initialized %u virtual ranks, with a total size of %u MB\n",
+		 (int) vrank, ramsize << 4);
+}
+
+static void vx900_dram_write_final_config(ramctr_timing *ctrl)
+{
+
+	/* FIXME: These are quick cheats */
+	pci_write_config8(MCU, 0x50, 0xa0); /* DRAM MA map */
+	vx900_dram_set_ma_map(VX900_CALIB_MA_MAP); /* Rank interleave */
+
+	pci_write_config8(MCU, 0x69, 0xe7);
+	//pci_write_config8(MCU, 0x72, 0x0f);
+
+	//pci_write_config8(MCU, 0x97, 0xa4); /* self-refresh */
+	//pci_write_config8(MCU, 0x98, 0xba); /* self-refresh II */
+	//pci_write_config8(MCU, 0x9a, 0x80); /* self-refresh III */
+
+	/* Enable automatic triggering of short ZQ calibration */
+	pci_write_config8(MCU, 0xc8, 0x80);
+}
+
+static void print_debug_pci_dev(device_t dev)
+{
+	printram("PCI: %.2x:%.2x.%.2x",
+		 (dev >> 20) & 0xff, (dev >> 15) & 0x1f, (dev >> 12) & 7 );
+}
+
+static void dump_pci_device(device_t dev)
+{
+	int i;
+	print_debug_pci_dev(dev);
+	printram("\n");
+
+	for (i = 0; i <= 0xff; i++) {
+		unsigned char val;
+		if ((i & 0x0f) == 0) {
+			printram("%.2x:", i);
+		}
+
+		if ((i & 0x0f) == 0x08) {
+			printram(" |");
+		}
+
+		val = pci_read_config8(dev, i);
+		printram(" %.2x", val);
+
+		if ((i & 0x0f) == 0x0f) {
+			printram("\n");
+		}
+	}
+}
+
+void vx900_init_dram_ddr3(const dimm_layout *dimm_addr)
+{
+	dimm_info dimm_prop;
+	ramctr_timing ctrl_prop;
+	rank_layout ranks;
+	device_t mcu;
+
+	if(!ram_check_noprint_nodie(1<<20, 1<<20)) {
+		printram("RAM is already initialized. Skipping init\n");
+		return;
+	}
+	/* Locate the Memory controller */
+	mcu = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VX900_MEMCTRL), 0);
+
+	if (mcu == PCI_DEV_INVALID) {
+		die("Memory Controller not found\n");
+	}
+	memset(&dimm_prop, 0, sizeof(dimm_prop));
+	memset(&ctrl_prop, 0, sizeof(ctrl_prop));
+	memset(&ranks, 0, sizeof(ranks));
+	/* 1) Write some initial "safe" parameters */
+	vx900_dram_write_init_config();
+	/* 2) Get timing information from SPDs */
+	dram_find_spds_ddr3(dimm_addr, &dimm_prop);
+	/* 3) Find lowest common denominator for all modules */
+	dram_find_common_params(&dimm_prop, &ctrl_prop);
+	/* 4) Find the size of each memory rank */
+	vx900_dram_phys_bank_range(&dimm_prop, &ranks);
+	/* 5) Set DRAM driving strength */
+	vx900_dram_driving_ctrl(&dimm_prop);
+	/* 6) Set DRAM frequency and latencies */
+	vx900_dram_timing(&ctrl_prop);
+	vx900_dram_freq(&ctrl_prop);
+	/* 7) Initialize the modules themselves */
+	vx900_dram_ddr3_dimm_init(&ctrl_prop, &ranks);
+	/* 8) Set refresh counter based on DRAM frequency */
+	vx900_dram_set_refresh_counter(&ctrl_prop);
+	/* 9) Calibrate receive and transmit delays */
+	vx900_dram_calibrate_delays(&ctrl_prop, &ranks);
+	/* 10) Enable Physical to Virtual Rank mapping */
+	vx900_dram_range(&ctrl_prop, &ranks);
+	/* 99) Some final adjustments */
+	vx900_dram_write_final_config(&ctrl_prop);
+	/* Take a dump */
+	dump_pci_device(mcu);
+
+}
diff --git a/src/northbridge/via/vx900/romstrap.inc b/src/northbridge/via/vx900/romstrap.inc
new file mode 100644
index 0000000..e4ce677
--- /dev/null
+++ b/src/northbridge/via/vx900/romstrap.inc
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Tyan Computer
+ * (Written by Yinghai Lu <yhlu at tyan.com> for Tyan Computer)
+ * Copyright (C) 2007 Rudolf Marek <r.marek at assembler.cz>
+ * Copyright (C) 2009 One Laptop per Child, Association, Inc.
+ * Copyright (C) 2011-2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/* As extracted from the manufacturer's ROM, the romstrap table looks like:
+ * .long 0x77886047 .long 0x00777777
+ * .long 0x00000000 .long 0x00000000
+ * .long 0x00888888 .long 0x00AA1111
+ * .long 0x00000000 .long 0x00000000
+ *
+ * The vendor BIOS then adjusts some of these settings very early on. Instead of
+ * adjusting those settings in code, we work them in the romstrap table.
+ *
+ */
+/* This file constructs the ROM strap table for VX900 */
+
+	.section ".romstrap", "a", @progbits
+
+	.globl __romstrap_start
+__romstrap_start:
+tblpointer:
+	.long 0x77886047
+	.long 0x00777777
+	.long 0x00000000
+	.long 0x00000000
+	.long 0x00888888
+	.long 0x00AA1111
+	.long 0x00000000
+	.long 0x00000000
+
+/*
+ * The pointer to above table should be at 0xffffffd0,
+ * the table itself MUST be aligned to 128B it seems!
+ */
+rspointers:
+	.long tblpointer				// It will be 0xffffffd0
+
+	.globl __romstrap_end
+
+__romstrap_end:
+.previous
diff --git a/src/northbridge/via/vx900/romstrap.lds b/src/northbridge/via/vx900/romstrap.lds
new file mode 100644
index 0000000..fc63c05
--- /dev/null
+++ b/src/northbridge/via/vx900/romstrap.lds
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 AMD
+ * (Written by Yinghai Lu <yinghai.lu at amd.com> for AMD)
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+SECTIONS {
+	. = (0x100000000 - 0x2c) - (__romstrap_end - __romstrap_start);
+	.romstrap (.): {
+		*(.romstrap)
+	}
+}
diff --git a/src/northbridge/via/vx900/sata.c b/src/northbridge/via/vx900/sata.c
new file mode 100644
index 0000000..09b8ca5
--- /dev/null
+++ b/src/northbridge/via/vx900/sata.c
@@ -0,0 +1,296 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reset.h>
+
+#include "vx900.h"
+
+void hard_reset(void)
+{
+	outb((1 << 2) | (1 << 1), 0xcf9);
+}
+
+static void dump_pci_device(device_t dev)
+{
+	int i;
+	for (i = 0; i <= 255; i++) {
+		unsigned char val;
+		if ((i & 0x0f) == 0) {
+			print_debug_hex8(i);
+			print_debug_char(':');
+		}
+		val = pci_read_config8(dev, i);
+		if((i & 7) == 0) print_debug(" |");
+		print_debug_char(' ');
+		print_debug_hex8(val);
+		if ((i & 0x0f) == 0x0f) {
+			print_debug("\n");
+		}
+	}
+}
+
+static void vx900_print_sata_errors(u32 flags)
+{
+	/* Status flags */
+	printk(BIOS_DEBUG, "\tPhyRdy %s\n",
+			   (flags&(1<<16)) ? "changed" : "not changed");
+	printk(BIOS_DEBUG, "\tCOMWAKE %s\n",
+			   (flags&(1<<16)) ? "detected" : "not detected");
+	printk(BIOS_DEBUG, "\tExchange as determined by COMINIT %s\n",
+			   (flags&(1<<26)) ? "occured" : "not occured");
+	printk(BIOS_DEBUG, "\tPort selector presence %s\n",
+			   (flags&(1<<27)) ? "detected" : "not detected");
+	/* Errors */
+	if(flags&(1<<0))
+		print_debug("\tRecovered data integrity ERROR\n");
+	if(flags&(1<<1))
+		print_debug("\tRecovered data communication ERROR\n");
+	if(flags&(1<<8))
+		print_debug("\tNon-recovered Transient Data Integrity ERROR\n");
+	if(flags&(1<<9))
+		print_debug("\tNon-recovered Persistent Communication or"
+			    "\tData Integrity ERROR\n");
+	if(flags&(1<<10))
+		print_debug("\tProtocol ERROR\n");
+	if(flags&(1<<11))
+		print_debug("\tInternal ERROR\n");
+	if(flags&(1<<17))
+		print_debug("\tPHY Internal ERROR\n");
+	if(flags&(1<<19))
+		print_debug("\t10B to 8B Decode ERROR\n");
+	if(flags&(1<<20))
+		print_debug("\tDisparity ERROR\n");
+	if(flags&(1<<21))
+		print_debug("\tCRC ERROR\n");
+	if(flags&(1<<22))
+		print_debug("\tHandshake ERROR\n");
+	if(flags&(1<<23))
+		print_debug("\tLink Sequence ERROR\n");
+	if(flags&(1<<24))
+		print_debug("\tTransport State Transition ERROR\n");
+	if(flags&(1<<25))
+		print_debug("\tUNRECOGNIZED FIS type\n");
+}
+
+static void vx900_dbg_sata_errors(device_t dev)
+{
+	/* Port 0 */
+	if (pci_read_config8(dev, 0xa0) & (1<<0) ) {
+		print_debug("Device detected in SATA port 0.\n");
+		u32 flags = pci_read_config32(dev, 0xa8);
+		vx900_print_sata_errors(flags);
+	};
+	/* Port 1 */
+	if (pci_read_config8(dev, 0xa1) & (1<<0) ) {
+		print_debug("Device detected in SATA port 1.\n");
+		u32 flags = pci_read_config32(dev, 0xac);
+		vx900_print_sata_errors(flags);
+	};
+}
+
+typedef u8 sata_phy_config[64];
+
+static sata_phy_config reference_ephy = {
+	0x80, 0xb8, 0xf0, 0xfe, 0x40, 0x7e, 0xf6, 0xdd,
+	0x1a, 0x22, 0xa0, 0x10, 0x02, 0xa9, 0x7c, 0x7e,
+	0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0x84, 0x8c,
+	0x75, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x40, 0xd0, 0x41, 0x40, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x40, 0x50, 0x41, 0x40, 0x00, 0x00, 0x00,
+	0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static u32 sata_phy_read32(device_t dev, u8 index)
+{
+	/* The SATA PHY control registers are accessed by a funny index/value
+	 * scheme. Each byte (0,1,2,3) has its own 4-bit index */
+	index = (index >> 2) & 0xf;
+	u16 i16 = index | (index<<4) | (index<<8)| (index<<12);
+	/* The index */
+	pci_write_config16(dev, 0x68, i16);
+	/* The value */
+	return pci_read_config32(dev, 0x64);
+}
+
+static void sata_phy_write32(device_t dev, u8 index, u32 val)
+{
+	/* The SATA PHY control registers are accessed by a funny index/value
+	 * scheme. Each byte (0,1,2,3) has its own 4-bit index */
+	index = (index >> 2) & 0xf;
+	u16 i16 = index | (index<<4) | (index<<8)| (index<<12);
+	/* The index */
+	pci_write_config16(dev, 0x68, i16);
+	/* The value */
+	pci_write_config32(dev, 0x64, val);
+}
+
+static void vx900_sata_read_phy_config(device_t dev, sata_phy_config cfg)
+{
+	size_t i;
+	u32* data = (u32*)cfg;
+	for(i = 0; i < (sizeof(sata_phy_config) ) >> 2; i++) {
+		data[i] = sata_phy_read32(dev, i<<2);
+	}
+}
+
+static void vx900_sata_write_phy_config(device_t dev, sata_phy_config cfg)
+{
+	size_t i;
+	u32* data = (u32*)cfg;
+	for(i = 0; i < (sizeof(sata_phy_config) ) >> 2; i++) {
+		sata_phy_write32(dev, i<<2, data[i]);
+	}
+}
+
+static void vx900_sata_dump_phy_config(sata_phy_config cfg)
+{
+	print_debug("SATA PHY config:\n");
+	int i;
+	for (i = 0; i < sizeof(sata_phy_config); i++) {
+		unsigned char val;
+		if ((i & 0x0f) == 0) {
+			print_debug_hex8(i);
+			print_debug_char(':');
+		}
+		val = cfg[i];
+		if((i & 7) == 0) print_debug(" |");
+		print_debug_char(' ');
+		print_debug_hex8(val);
+		if ((i & 0x0f) == 0x0f) {
+			print_debug("\n");
+		}
+	}
+}
+
+static void vx900_native_ide_mode(device_t dev)
+{
+	/* AHCI mode requires a sub-class of 0x06, and Interface of 0x01
+	 * SATA mode requires a sub-class of 0x06, and Interface of 0x00
+	 * Unfortunately, setting the class to SATA, will prevent us from
+	 * modyfing the interface register to an AHCI/SATA compliant value.
+	 * Thus, payloads or OS may not properly identify this as a SATA
+	 * controller. We could set the class code to 0x04, which would cause
+	 * the interface register to become 0x00, which represents a RAID
+	 * controller. Unfortunately, when we do this, SeaBIOS will skip this
+	 * as a storage device, and we will not be able to boot.
+	 * Our only option is to operate in IDE mode */
+	/* Disable subclass write protect */
+	pci_mod_config8(dev, 0x45, 1<<7, 0);
+	/* Change the device class to SATA */
+	pci_write_config8(dev, PCI_CLASS_DEVICE, 0x01);
+	/* Re-enable subclass write protect */
+	pci_mod_config8(dev, 0x45, 0, 1<<7);
+	/* Put it in native IDE mode */
+	pci_mod_config8(dev, PCI_CLASS_PROG, 0, 1<<0);
+}
+
+static void vx900_sata_init(device_t dev)
+{
+	print_debug("======================================================\n");
+	print_debug("== SATA init \n");
+	print_debug("======================================================\n");
+
+	/* Enable SATA primary channel IO access */
+	pci_mod_config8(dev, 0x40, 0, 1<<1);
+	/* Just SATA, so it makes sense to be in native SATA mode */
+	vx900_native_ide_mode(dev);
+
+	/* TP Layer Idle at least 20us before the Following Command */
+	pci_mod_config8(dev, 0x53, 0, 1<<7);
+	/* Resend COMRESET When Recovering SATA Gen2 Device Error */
+	pci_mod_config8(dev, 0x62, 1<<1, 1<<7);
+
+	/* Fix "PMP Device Can’t Detect HDD Normally" (VIA Porting Guide)
+	 * SATA device detection will not work unless we clear these bits.
+	 * Without doing this, SeaBIOS (and potentially other payloads) will
+	 * timeout when detecting SATA devices */
+	pci_mod_config8(dev, 0x89, (1<<3) | (1<<6), 0);
+
+	/* 12.7 Two Software Resets May Affect the System
+	 * When the software does the second reset before the first reset
+	 * finishes, it may cause the system hang. It would do one software
+	 * reset and check the BSY bit of one port only, and the BSY bit of
+	 * other port would be 1, then it does another software reset
+	 * immediately and causes the system hang.
+	 * This is because the first software reset doesn’t finish, and the
+	 * state machine of the host controller conflicts, it can’t finish the
+	 * second one anymore. The BSY bit of slave port would be always 1 after
+	 * the second software reset issues. BIOS should set the following
+	 * bit to avoid this issue. */
+	pci_mod_config8(dev, 0x80, 0, 1<<6);
+
+	/* We need to set the EPHY values before doing anything with the link */
+	sata_phy_config ephy;
+	vx900_sata_read_phy_config(dev, ephy);
+	if(1) {
+		vx900_sata_dump_phy_config(ephy);
+		vx900_sata_write_phy_config(dev, reference_ephy);
+	} else {
+		/* Enable TX and RX driving resistance */
+		/* TX - 50 Ohm */
+		ephy[1] &= ~(0x1f<<3);
+		ephy[1] |= (1<<7) | (8<<3);
+		/* RX - 50 Ohm */
+		ephy[2] &= ~(0x1f<<3);
+		ephy[2] |= (1<<7) | (8<<3);
+		vx900_sata_write_phy_config(dev, ephy);
+	}
+
+	vx900_sata_read_phy_config(dev, ephy);
+	vx900_sata_dump_phy_config(ephy);
+
+	/* Clear error flags */
+	pci_write_config32(dev, 0xa8, 0xffffffff);
+	pci_write_config32(dev, 0xac, 0xffffffff);
+
+	/* Start OOB link negotiation sequence */
+	pci_mod_config8(dev, 0xb9, 0, 3<<4);
+
+	/* FIXME: From now on, we are just doing DEBUG stuff
+	 * Wait until PHY communication is enabled */
+	u32 wloops = 0;
+	while(! (pci_read_config8(dev, 0xa0) & (1<<1)) ) wloops ++;
+	printk(BIOS_SPEW, "wloops: %u\n", wloops);
+
+	print_debug("And finally, the dump you've all been waiting for\n");
+	dump_pci_device(dev);
+	vx900_dbg_sata_errors(dev);
+}
+
+static void vx900_sata_read_resources(device_t dev)
+{
+	pci_dev_read_resources(dev);
+}
+
+static struct device_operations vga_operations = {
+	.read_resources = vx900_sata_read_resources,
+	.set_resources = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init = vx900_sata_init,
+};
+
+static const struct pci_driver chrome9hd_driver __pci_driver = {
+	.ops = &vga_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_VX900_SATA,
+};
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/traf_ctrl.c b/src/northbridge/via/vx900/traf_ctrl.c
new file mode 100644
index 0000000..cc620cc
--- /dev/null
+++ b/src/northbridge/via/vx900/traf_ctrl.c
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static struct device_operations vga_operations = {
+	.read_resources = pci_dev_read_resources,
+	.set_resources = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init = pci_dev_init,
+	.ops_pci = 0,
+};
+
+static const struct pci_driver vga_driver_900 __pci_driver = {
+	.ops = &vga_operations,
+	.vendor = PCI_VENDOR_ID_VIA,
+	.device = PCI_DEVICE_ID_VIA_VX900_TRAF,
+};
\ No newline at end of file
diff --git a/src/northbridge/via/vx900/vx900.h b/src/northbridge/via/vx900/vx900.h
new file mode 100644
index 0000000..21a24b2
--- /dev/null
+++ b/src/northbridge/via/vx900/vx900.h
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define VX900_ACPI_IO_BASE		0x0400
+
+#define VX900_NB_IOAPIC_ID		0x2
+#define VX900_NB_IOAPIC_BASE		0xfecc000
+
+#define VX900_SB_IOAPIC_ID		0x1
+#define VX900_SB_IOAPIC_BASE		0xfec0000
+
+#define SMBUS_IO_BASE	0x500
+
+/* The maximum number of DIMM slots that the VX900 supports */
+#define VX900_MAX_DIMM_SLOTS 2
+#define VX900_MAX_MEM_RANKS 4
+
+#define min(a,b) a<b?a:b
+#define max(a,b) a>b?a:b
+
+#ifndef __PRE_RAM__
+
+#include <arch/io.h>
+#include <device/pci.h>
+
+/* We use these throughout the code. They really belong in a generic part of
+ * coreboot, but until beuraucracy gets them there, we still need them  */
+static inline __attribute__((always_inline))
+void pci_mod_config8(device_t dev, unsigned int where,
+		     uint8_t clr_mask, uint8_t set_mask)
+{
+	uint8_t reg8 = pci_read_config8(dev, where);
+	reg8 &= ~clr_mask;
+	reg8 |= set_mask;
+	pci_write_config8(dev, where, reg8);
+}
+static inline __attribute__((always_inline))
+void pci_mod_config16(device_t dev, unsigned int where,
+		      uint16_t clr_mask, uint16_t set_mask)
+{
+	uint16_t reg16 = pci_read_config16(dev, where);
+	reg16 &= ~clr_mask;
+	reg16 |= set_mask;
+	pci_write_config16(dev, where, reg16);
+}
+static inline __attribute__((always_inline))
+void pci_mod_config32(device_t dev, unsigned int where,
+		      uint32_t clr_mask, uint32_t set_mask)
+{
+	uint32_t reg32 = pci_read_config32(dev, where);
+	reg32 &= ~clr_mask;
+	reg32 |= set_mask;
+	pci_write_config32(dev, where, reg32);
+}
+
+u32 chrome9hd_fb_size(void);
+
+#endif /* __PRE_RAM__ */
\ No newline at end of file




More information about the coreboot mailing list