libreboot-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libreboot-dev] [PATCH] Coreboot update, depthcharge menus improvement


From: Paul Kocialkowski
Subject: [Libreboot-dev] [PATCH] Coreboot update, depthcharge menus improvement
Date: Fri, 30 Oct 2015 17:17:42 +0100

Signed-off-by: Paul Kocialkowski <address@hidden>
---
 ...ay-callbacks-for-developer-and-recovery-m.patch |    35 +-
 .../config/depthcharge/veyron_speedy/config        |     9 +-
 ...sized-half-word-sized-memory-operations-f.patch |    89 -
 ...low-disabling-vboot-firmware-verification.patch |    98 +
 ...low-disabling-vboot-firmware-verification.patch |    84 -
 ...-w83795-Add-full-support-for-fan-control-.patch |   710 -
 ...-amd-sb700-Allow-use-of-auxiliary-SMBUS-c.patch |   142 +-
 ...-w83795-Add-full-support-for-core-functio.patch |   725 +
 ...-w83795-Add-option-to-use-auxiliary-SMBUS.patch |    62 -
 ...eed-Add-native-text-mode-VGA-support-for-.patch |  3675 -----
 ...-w83795-Add-option-to-use-auxiliary-SMBUS.patch |    68 +
 ...pdate-mainboards-using-the-w83795-sensor-.patch |   323 +
 ...-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch |   642 -
 ...eed-Add-native-text-mode-VGA-support-for-.patch |  3675 +++++
 ...-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch |   621 -
 ...-initial-support-for-AMD-Socket-G34-proce.patch |   832 -
 ...-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch |   619 +
 ...-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch |  3463 ----
 ...-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch |   621 +
 ...-initial-support-for-AMD-Socket-G34-proce.patch |   832 +
 ...-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch |    95 -
 ...-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch |   121 -
 ...-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch |  3454 ++++
 ...thbridge-amd-amdfam10-Fix-typo-in-comment.patch |    27 -
 ...-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch |    95 +
 ...ypertransport-Add-additional-debug-output.patch |    35 -
 ...-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch |   121 +
 ...ypertransport-Add-additional-debug-output.patch |    35 +
 ...sus-kgpe-d16-Add-initial-support-for-the-.patch |  3221 ----
 ...sus-kgpe-d16-Add-initial-support-for-the-.patch |  3222 ++++
 ...sus-kgpe-d16-Add-nvram-option-to-enable-d.patch |    72 -
 ...model_10xxx-Clean-up-debugging-statements.patch |   116 -
 ...sus-kgpe-d16-Add-nvram-option-to-enable-d.patch |    72 +
 ...model_10xxx-Clean-up-debugging-statements.patch |   108 +
 ...e-amd-sb700-Add-Suspend-to-RAM-S3-support.patch |   367 -
 ...e-amd-sb700-Add-Suspend-to-RAM-S3-support.patch |   367 +
 ...oton-nct5572d-Enable-power-state-after-po.patch |    82 -
 ...-amd-amdfam10-Add-Suspend-to-RAM-S3-Flash.patch |   135 -
 ...oton-nct5572d-Enable-power-state-after-po.patch |    80 +
 ...srock-e350m1-Update-CMOS-layout-to-match-.patch |    38 +
 ...-amd-amdmct-mct_ddr3-Add-initial-Suspend-.patch |  1007 --
 ...car-Add-initial-Suspend-to-RAM-S3-support.patch |    56 -
 ...-amd-amdfam10-Add-Suspend-to-RAM-S3-Flash.patch |   135 +
 ...sus-kgpe-d16-Add-initial-Suspend-to-RAM-S.patch |   832 -
 ...-amd-amdmct-mct_ddr3-Add-initial-Suspend-.patch |  1017 ++
 ...car-Add-initial-Suspend-to-RAM-S3-support.patch |    56 +
 ...ios-Update-SMBIOS-memory-structures-to-ve.patch |    33 -
 ...sus-kgpe-d16-Add-initial-Suspend-to-RAM-S.patch |   832 +
 ...-amd-amdfam10-Set-DIMM-voltage-based-on-S.patch |   198 -
 ...ios-Update-SMBIOS-memory-structures-to-ve.patch |    33 +
 ...sus-kgpe-d16-Set-DDR3-memory-voltage-base.patch |   166 -
 ...-amd-amdfam10-Set-DIMM-voltage-based-on-S.patch |   198 +
 ...-console-Add-x86-romstage-spinlock-option.patch |   100 -
 ...sus-kgpe-d16-Set-DDR3-memory-voltage-base.patch |   166 +
 ...-amd-amdmct-mct_ddr3-Fix-S3-suspend-overr.patch |    51 -
 ...-amd-amdmct-mct_ddr3-Fix-failing-S3-resum.patch |    53 -
 ...-Add-x86-romstage-spinlock-option-and-pri.patch |   193 +
 ...-amd-amdmct-mct_ddr3-Fix-S3-suspend-overr.patch |    51 +
 ...c-console-Add-x86-printk-spinlock-support.patch |   149 -
 ...029-lib-stack-Add-stack-overrun-detection.patch |     8 +-
 ...cpu-x86-lapic-Add-stack-overrun-detection.patch |     8 +-
 ...-amd-sr5650-Add-AMD-Family-15h-CPU-suppor.patch |     8 +-
 ...Move-model_10xxx-to-family_10h-family_15h.patch |    24 +-
 ...pu-amd-Add-initial-AMD-Family-15h-support.patch | 16206 ------------------
 ...ily_10h-family_15h-Use-correct-label-for-.patch |    28 +
 ...pu-amd-Add-initial-AMD-Family-15h-support.patch | 16249 +++++++++++++++++++
 ...sus-kgpe-d16-Add-initial-Family-15h-CPU-s.patch |   565 -
 ...ily_10h-family_15h-Add-Family-15h-microco.patch |    28 -
 ...sus-kgpe-d16-Add-initial-Family-15h-CPU-s.patch |   556 +
 ...ddr3-Disable-Fam10h-specific-MTRR-setup-o.patch |    38 -
 ...ily_10h-family_15h-Add-Family-15h-microco.patch |    28 +
 ...ddr3-Disable-Fam10h-specific-MTRR-setup-o.patch |    38 +
 ...-Add-romstage-BSP-stack-overrun-detection.patch |    58 -
 ...-Add-romstage-BSP-stack-overrun-detection.patch |    59 +
 ...-Increase-Family-10h-CAR-size-limit-to-12.patch |    31 -
 ...-Increase-Family-10h-CAR-size-limit-to-12.patch |    31 +
 ...-Move-AP-stacks-below-the-BSP-stack-to-fr.patch |    33 -
 ...-Move-AP-stacks-below-the-BSP-stack-to-fr.patch |    33 +
 ...-amd-amdmct-Read-SPD-data-into-cache-to-d.patch |   461 -
 ...-Initialize-entire-CAR-space-instead-of-o.patch |    34 -
 ...-amd-amdmct-Read-SPD-data-into-cache-to-d.patch |   461 +
 ...mct_ddr3-Improve-SPD-DIMM-detect-reliabil.patch |    49 -
 ...-Initialize-entire-CAR-space-instead-of-o.patch |    34 +
 ...mct_ddr3-Improve-SPD-DIMM-detect-reliabil.patch |    49 +
 ...mct_ddr3-Use-training-values-from-previou.patch |   781 -
 ...mct_ddr3-Use-training-values-from-previou.patch |   781 +
 ...-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch |   261 -
 .../0045-mainboard-asus-kgpe-d16-Enable-CC6.patch  |    70 -
 ...-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch |   261 +
 .../kgpe-d16/0046-cpu-amd-Add-CC6-support.patch    |  1307 --
 .../0046-mainboard-asus-kgpe-d16-Enable-CC6.patch  |    70 +
 .../kgpe-d16/0047-cpu-amd-Add-CC6-support.patch    |  1318 ++
 ...-amd-amdmct-Skip-DCT-config-write-to-Flas.patch |   103 -
 ...-amd-amdmct-Skip-DCT-config-write-to-Flas.patch |   103 +
 ...48-southbridge-amd-sb700-Add-AHCI-support.patch |   656 -
 ...sus-kgpe-d16-Properly-initialize-SB700-SA.patch |    49 -
 ...49-southbridge-amd-sb700-Add-AHCI-support.patch |   656 +
 ...sus-kgpe-d16-Properly-initialize-SB700-SA.patch |    49 +
 ...-amd-sb700-Disable-broken-SATA-MSI-functi.patch |    41 -
 ...-amd-sb700-Disable-broken-SATA-MSI-functi.patch |    41 +
 ...-amd-sb700-Indicate-iSATA-eSATA-port-type.patch |    93 -
 ...-amd-amdfam10-Add-ability-to-set-maximum-.patch |    84 -
 ...-amd-sb700-Indicate-iSATA-eSATA-port-type.patch |    94 +
 ...-amd-amdfam10-Add-ability-to-set-maximum-.patch |    84 +
 ...-amd-amdmct-Verify-MCT-NVRAM-options-befo.patch |   149 -
 ...-amd-amdmct-Verify-MCT-NVRAM-options-befo.patch |   149 +
 ...idge-amd-amdmct-Add-option-to-override-ba.patch |   104 -
 ...sus-kgpe-d16-Add-missing-IRQ-routing-for-.patch |   209 -
 ...idge-amd-amdmct-Add-option-to-override-ba.patch |   102 +
 ...sus-kgpe-d16-Add-missing-IRQ-routing-for-.patch |   209 +
 ...-amd-amdmct-Fix-hang-on-boot-due-to-inval.patch |    37 -
 ...-amd-amdmct-Fix-hang-on-boot-due-to-inval.patch |    37 +
 ...-amd-sr5650-Fix-GPP3a-link-training-in-hi.patch |    85 -
 ...-amd-sr5650-Add-optional-delay-after-link.patch |    71 -
 ...-amd-sr5650-Fix-GPP3a-link-training-in-hi.patch |    85 +
 ...sus-kgpe-d16-Properly-configure-SR5690-so.patch |    32 -
 ...-amd-sr5650-Add-optional-delay-after-link.patch |    71 +
 ...sus-kgpe-d16-Properly-configure-SR5690-so.patch |    32 +
 ...-amd-sb700-Add-option-to-disable-SATA-ALP.patch |    86 -
 ...ainboard-asus-kgpe-d16-Set-SP5100-subtype.patch |    26 -
 ...-amd-sb700-Add-option-to-disable-SATA-ALP.patch |    84 +
 ...ainboard-asus-kgpe-d16-Set-SP5100-subtype.patch |    26 +
 ...-amd-amdmct-Fix-crash-on-startup-due-to-N.patch |    33 -
 ...-amd-amdmct-Clear-memory-before-enabling-.patch |   185 -
 ...-amd-amdmct-Fix-crash-on-startup-due-to-N.patch |    33 +
 ...-amd-amdmct-Clear-memory-before-enabling-.patch |   185 +
 ...-amd-sb700-Do-drive-detection-even-in-AHC.patch |   142 -
 ...-amd-sb700-Do-drive-detection-even-in-AHC.patch |   142 +
 ...idge-amd-sb700-Reset-SATA-controller-in-A.patch |    96 -
 ...-amd-sb700-Recover-if-AHCI-disk-detection.patch |   163 -
 ...idge-amd-sb700-Reset-SATA-controller-in-A.patch |    96 +
 ...-amd-sb700-Fix-SATA-port-4-5-drive-detect.patch |    97 -
 ...-amd-sb700-Recover-if-AHCI-disk-detection.patch |   163 +
 ...-amd-sb700-Fix-SATA-port-4-5-drive-detect.patch |    97 +
 ...-amd-sb700-Fix-random-persistent-SATA-AHC.patch |   165 -
 ...-amd-amdmct-mct_ddr3-Fix-lockups-and-wast.patch |   407 -
 ...-amd-sb700-Fix-random-persistent-SATA-AHC.patch |   165 +
 ...-AMD-Family-15h-ECC-initialization-reliab.patch |   474 -
 ...-amd-amdmct-mct_ddr3-Fix-lockups-and-wast.patch |   409 +
 ...-AMD-Family-15h-ECC-initialization-reliab.patch |   474 +
 ...-amd-amdfam10-Properly-indicate-node-and-.patch |   120 -
 ...mct_ddr3-Add-Family-15h-RDIMM-timing-and-.patch |   508 -
 ...-amd-amdfam10-Properly-indicate-node-and-.patch |   120 +
 ...mct_ddr3-Add-Family-15h-RDIMM-timing-and-.patch |   508 +
 ...-amd-amdmct-mct_ddr3-Attempt-to-recover-f.patch |   256 -
 ...-amd-amdmct-mct_ddr3-Attempt-to-recover-f.patch |   256 +
 ...-amd-amdmct-mct_ddr3-Work-around-strange-.patch |    42 -
 ...-amd-amdmct-mct_ddr3-Add-additional-debug.patch |   120 -
 ...-amd-amdmct-mct_ddr3-Work-around-strange-.patch |    42 +
 ...-amd-amdmct-mct_ddr3-Add-additional-debug.patch |   120 +
 ...-amd-amdmct-mct_ddr3-Fix-null-pointer-acc.patch |   240 -
 ...-amd-amdmct-mct_ddr3-Add-missing-Family-1.patch |   268 -
 ...-amd-amdmct-mct_ddr3-Fix-null-pointer-acc.patch |   240 +
 ...-amd-amdmct-mct_ddr3-Add-missing-Family-1.patch |   268 +
 ...-amd-amdmct-mct_ddr3-Set-SkewMemClk-when-.patch |   114 -
 ...-amd-amdmct-mct_ddr3-Properly-indicate-cl.patch |    58 -
 ...-amd-amdmct-mct_ddr3-Set-SkewMemClk-when-.patch |   114 +
 ...-amd-amdmct-mct_ddr3-Fix-Family-10h-boot-.patch |   100 -
 ...-amd-amdmct-mct_ddr3-Properly-indicate-cl.patch |    58 +
 ...-amd-amdmct-mct_ddr3-Fix-Family-10h-boot-.patch |   100 +
 ...idge-amd-sr5650-Always-configure-lane-dir.patch |    51 -
 ...ily_10h-family_15h-Fix-BSP-stack-corrupti.patch |    28 -
 ...idge-amd-sr5650-Always-configure-lane-dir.patch |    51 +
 ...ily_10h-family_15h-Fix-BSP-stack-corrupti.patch |    40 +
 ...-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch |   330 -
 ...mct_ddr3-Partially-fix-up-registered-DIMM.patch |   960 --
 ...-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch |   304 +
 ...mct_ddr3-Partially-fix-up-registered-DIMM.patch |   960 ++
 ...ridge-amd-amdmct-Fix-Family-15h-detection.patch |    49 -
 ...ridge-amd-amdmct-Fix-Family-15h-detection.patch |    49 +
 ...-amd-amdmct-mct_ddr3-Add-registered-and-x.patch |  1887 ---
 ...ily_10h-family_15h-Fix-Family-15h-multipl.patch |  1931 ---
 ...-amd-amdmct-Reduce-maximum-number-of-DDR3.patch |    41 +
 ...dge-amd-amdfam10-Add-probe-filter-support.patch |   214 -
 ...-amd-amdmct-mct_ddr3-Add-registered-and-x.patch |  1887 +++
 ...ily_10h-family_15h-Bring-initial-HT-regis.patch |   248 -
 ...ily_10h-family_15h-Fix-Family-15h-multipl.patch |  1244 ++
 ...dge-amd-amdfam10-Add-probe-filter-support.patch |   282 +
 ...-amd-amdmct-mct_ddr3-Move-K10D-configurat.patch |   338 -
 ...ily_10h-family_15h-Bring-initial-HT-regis.patch |   248 +
 ...oard-asus-kgpe-d16-Fix-I-O-link-detection.patch |    28 -
 ...ily_10h-family_15h-Set-northbridge-thrott.patch |   139 -
 ...-amd-amdmct-mct_ddr3-Move-K10D-configurat.patch |   336 +
 ...ily_10h-family_15h-Fix-incorrect-revision.patch |    64 -
 ...oard-asus-kgpe-d16-Fix-I-O-link-detection.patch |    28 +
 ...ily_10h-family_15h-Set-northbridge-thrott.patch |   110 +
 ...-amd-amdht-Add-support-for-HT3-2.8GHz-and.patch |   561 -
 ...10h-family_15h-Fix-poor-performance-on-Fa.patch |   124 -
 ...ily_10h-family_15h-Fix-incorrect-revision.patch |    64 +
 ...mct_ddr3-Fix-poor-performance-on-Family-1.patch |  1089 --
 ...-amd-amdht-Add-support-for-HT3-2.8GHz-and.patch |   532 +
 ...10h-family_15h-Fix-poor-performance-on-Fa.patch |   124 +
 ...-amd-amdht-Fix-poor-performance-on-Family.patch |    30 -
 ...mct_ddr3-Fix-poor-performance-on-Family-1.patch |  1089 ++
 ...-amd-amdfam10-Fix-poor-performance-on-Fam.patch |    72 -
 ...ily_10h-family_15h-Configure-NB-register-.patch |    34 -
 ...-amd-amdht-Fix-poor-performance-on-Family.patch |    30 +
 ...ily_10h-family_15h-Set-up-link-XCS-token-.patch |   344 -
 ...-amd-amdfam10-Fix-poor-performance-on-Fam.patch |    72 +
 ...ily_10h-family_15h-Configure-NB-register-.patch |    34 +
 ...-amd-amdmct-mct_ddr3-Force-retraining-on-.patch |    36 -
 ...ily_10h-family_15h-Set-up-link-XCS-token-.patch |   344 +
 ...ridge-amd-amdfam10-Fix-invalid-NUMA-table.patch |    28 -
 ...-amd-amdfam10-Add-Family-15h-cache-partit.patch |   123 -
 ...-amd-amdmct-mct_ddr3-Force-retraining-on-.patch |    36 +
 ...mct_ddr3-Set-prefetch-double-stride-to-im.patch |    27 -
 ...ridge-amd-amdfam10-Fix-invalid-NUMA-table.patch |    28 +
 ...ily_10h-family_15h-Set-up-Family-15h-Link.patch |   192 -
 ...-amd-amdfam10-Add-Family-15h-cache-partit.patch |   123 +
 ...mct_ddr3-Set-prefetch-double-stride-to-im.patch |    27 +
 ...ily_10h-family_15h-Set-up-cache-controls-.patch |    43 -
 ...ily_10h-family_15h-Set-up-Family-15h-Link.patch |   192 +
 ...ily_10h-family_15h-Set-up-SRI-to-XCS-Toke.patch |    66 -
 ...0-Control-Family-15h-cache-partitioning-a.patch |   177 -
 ...ily_10h-family_15h-Set-up-cache-controls-.patch |    43 +
 ...ily_10h-family_15h-Set-up-SRI-to-XCS-Toke.patch |    66 +
 ...-amd-amdht-Add-isochronous-setup-support-.patch |   272 -
 ...0-Control-Family-15h-cache-partitioning-a.patch |   190 +
 ...6-acpi-Add-IVRS-table-generation-routines.patch |   121 -
 ...-amd-amdht-Add-isochronous-setup-support-.patch |   279 +
 ...-southbridge-amd-sr5650-Add-IOMMU-support.patch |   711 -
 ...6-acpi-Add-IVRS-table-generation-routines.patch |   121 +
 ...-amd-sr5650-Hide-clock-configuration-devi.patch |    57 -
 ...-amd-amdfam10-Rename-mislabeled-iommu-nvr.patch |    55 -
 ...-southbridge-amd-sr5650-Add-IOMMU-support.patch |   804 +
 ...-amd-amdfam10-Fix-gart-setup-not-working-.patch |    96 -
 ...-amd-sr5650-Hide-clock-configuration-devi.patch |    57 +
 ...sus-kgpe-d16-Add-several-nvram-configurat.patch |   129 -
 ...-amd-amdfam10-Rename-mislabeled-iommu-nvr.patch |    55 +
 ...-amd-amdfam10-Fix-gart-setup-not-working-.patch |    96 +
 ...-amd-sr5650-Use-correct-PCI-configuration.patch |    30 -
 ...sus-kgpe-d16-Add-several-nvram-configurat.patch |    82 +
 ...ge-amd-sr5650-Add-MCFG-ACPI-table-support.patch |   119 -
 ...dge-amd-sb700-Fix-mismatched-FADT-entries.patch |    36 -
 ...-amd-sr5650-Use-correct-PCI-configuration.patch |    30 +
 ...ridge-amd-sb700-Fix-drifting-system-clock.patch |    47 -
 ...ge-amd-sr5650-Add-MCFG-ACPI-table-support.patch |   121 +
 ...-amd-amdmct-mct_ddr3-Add-cc6-setup-inform.patch |    58 -
 ...dge-amd-sb700-Fix-mismatched-FADT-entries.patch |    36 +
 ...-amd-amdfam10-Work-around-sporadic-lockup.patch |    40 -
 ...ridge-amd-sb700-Fix-drifting-system-clock.patch |    47 +
 ...-amd-amdmct-mct_ddr3-Add-cc6-setup-inform.patch |    58 +
 ...-amd-amdmct-mct_ddr3-Ensure-channel-clock.patch |   115 -
 ...-amd-amdfam10-Work-around-sporadic-lockup.patch |    40 +
 ...-amd-amdmct-mct_ddr3-Add-DDR3-termination.patch |    36 -
 ...-amd-amdmct-mct_ddr3-Ensure-channel-clock.patch |   115 +
 ...-amd-amdmct-mct_ddr3-Fix-a-minor-RDIMM-CS.patch |    37 -
 ...-amd-amdmct-mct_ddr3-Add-DDR3-termination.patch |    36 +
 ...-amd-amdmct-mct_ddr3-Fix-odd-rank-data-co.patch |    65 -
 ...-amd-amdmct-mct_ddr3-Fix-a-minor-RDIMM-CS.patch |    37 +
 ...-amd-amdmct-mct_ddr3-Use-antiphase-to-bet.patch |   157 -
 ...-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch |   602 -
 ...-amd-amdmct-mct_ddr3-Fix-odd-rank-data-co.patch |    65 +
 ...0-Add-optional-spinlock-for-nvram-CBFS-ac.patch |   175 -
 ...-amd-amdmct-mct_ddr3-Use-antiphase-to-bet.patch |   157 +
 ...board-asus-kgpe-d16-Enable-CBFS-spinlocks.patch |    68 -
 ...-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch |   602 +
 ...rocode-Introduce-CBFS-access-spinlock-to-.patch |   155 -
 ...0-Add-optional-spinlock-for-nvram-CBFS-ac.patch |   175 +
 ...board-asus-kgpe-d16-Enable-CBFS-spinlocks.patch |    61 +
 ...rd-asus-kgpe-d16-Limit-HT-speed-to-2.6GHz.patch |    41 -
 ...ily_10h-family_15h-Apply-missing-Family-1.patch |    70 -
 ...rocode-Introduce-CBFS-access-spinlock-to-.patch |   155 +
 ...rd-asus-kgpe-d16-Limit-HT-speed-to-2.6GHz.patch |    41 +
 ...-amd-amdmct-mct_ddr3-Use-StopOnError-to-d.patch |   231 -
 ...ily_10h-family_15h-Apply-missing-Family-1.patch |    70 +
 ...oard-asus-kgpe-d16-Enable-GART-by-default.patch |    27 -
 ...-amd-amdfam10-Fix-incorrect-channel-buffe.patch |    42 -
 ...-amd-amdmct-mct_ddr3-Use-StopOnError-to-d.patch |   231 +
 ...ily_10h-family_15h-Force-iolink-detect-to.patch |    37 -
 ...oard-asus-kgpe-d16-Enable-GART-by-default.patch |    27 +
 ...-amd-amdfam10-Fix-incorrect-channel-buffe.patch |    42 +
 ...-amd-amdht-Fix-XCS-buffer-count-setup-on-.patch |   144 -
 ...ily_10h-family_15h-Fix-link-type-detectio.patch |   158 -
 ...ily_10h-family_15h-Force-iolink-detect-to.patch |    37 +
 ...ily_10h-family_15h-Enable-DFE-on-Family-1.patch |    32 -
 ...-amd-amdht-Fix-XCS-buffer-count-setup-on-.patch |   144 +
 ...ily_10h-family_15h-Fix-link-type-detectio.patch |   158 +
 ...ily_10h-family_15h-Enable-DFE-on-Family-1.patch |    32 +
 ...ily_10h-family_15h-Fix-build-when-microco.patch |    28 +
 ...s-Avoid-infinite-loop-if-i2c-device-has-w.patch |    39 +
 ...low-disabling-vboot-firmware-verification.patch |    68 -
 resources/scripts/helpers/download/coreboot        |     5 +-
 283 files changed, 55428 insertions(+), 55778 deletions(-)
 delete mode 100644 
resources/libreboot/patch/chromebook/0001-armv7-Word-sized-half-word-sized-memory-operations-f.patch
 create mode 100644 
resources/libreboot/patch/chromebook/0001-chromeos-Allow-disabling-vboot-firmware-verification.patch
 delete mode 100644 
resources/libreboot/patch/chromebook/0002-chromeos-Allow-disabling-vboot-firmware-verification.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0001-drivers-i2c-w83795-Add-full-support-for-fan-control-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-full-support-for-core-functio.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0004-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0004-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0005-mainboard-Update-mainboards-using-the-w83795-sensor-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0005-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0006-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0006-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0007-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0007-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0008-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0008-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0009-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0009-northbridge-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0011-northbridge-amd-amdfam10-Fix-typo-in-comment.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0011-northbridge-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0012-device-hypertransport-Add-additional-debug-output.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0012-northbridge-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0013-device-hypertransport-Add-additional-debug-output.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0013-mainboard-asus-kgpe-d16-Add-initial-support-for-the-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0014-mainboard-asus-kgpe-d16-Add-initial-support-for-the-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0014-mainboard-asus-kgpe-d16-Add-nvram-option-to-enable-d.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0015-cpu-amd-model_10xxx-Clean-up-debugging-statements.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0015-mainboard-asus-kgpe-d16-Add-nvram-option-to-enable-d.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0016-cpu-amd-model_10xxx-Clean-up-debugging-statements.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0016-southbridge-amd-sb700-Add-Suspend-to-RAM-S3-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0017-southbridge-amd-sb700-Add-Suspend-to-RAM-S3-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0017-superio-nuvoton-nct5572d-Enable-power-state-after-po.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0018-northbridge-amd-amdfam10-Add-Suspend-to-RAM-S3-Flash.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0018-superio-nuvoton-nct5572d-Enable-power-state-after-po.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0019-mainboard-asrock-e350m1-Update-CMOS-layout-to-match-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0019-northbridge-amd-amdmct-mct_ddr3-Add-initial-Suspend-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0020-cpu-amd-car-Add-initial-Suspend-to-RAM-S3-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0020-northbridge-amd-amdfam10-Add-Suspend-to-RAM-S3-Flash.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0021-mainboard-asus-kgpe-d16-Add-initial-Suspend-to-RAM-S.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0021-northbridge-amd-amdmct-mct_ddr3-Add-initial-Suspend-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0022-cpu-amd-car-Add-initial-Suspend-to-RAM-S3-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0022-include-smbios-Update-SMBIOS-memory-structures-to-ve.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0023-mainboard-asus-kgpe-d16-Add-initial-Suspend-to-RAM-S.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0023-northbridge-amd-amdfam10-Set-DIMM-voltage-based-on-S.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0024-include-smbios-Update-SMBIOS-memory-structures-to-ve.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0024-mainboard-asus-kgpe-d16-Set-DDR3-memory-voltage-base.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0025-northbridge-amd-amdfam10-Set-DIMM-voltage-based-on-S.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0025-src-console-Add-x86-romstage-spinlock-option.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0026-mainboard-asus-kgpe-d16-Set-DDR3-memory-voltage-base.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0026-northbridge-amd-amdmct-mct_ddr3-Fix-S3-suspend-overr.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0027-northbridge-amd-amdmct-mct_ddr3-Fix-failing-S3-resum.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0027-src-console-Add-x86-romstage-spinlock-option-and-pri.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0028-northbridge-amd-amdmct-mct_ddr3-Fix-S3-suspend-overr.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0028-src-console-Add-x86-printk-spinlock-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0033-cpu-amd-Add-initial-AMD-Family-15h-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0033-cpu-amd-family_10h-family_15h-Use-correct-label-for-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0034-cpu-amd-Add-initial-AMD-Family-15h-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0034-mainboard-asus-kgpe-d16-Add-initial-Family-15h-CPU-s.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0035-cpu-amd-family_10h-family_15h-Add-Family-15h-microco.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0035-mainboard-asus-kgpe-d16-Add-initial-Family-15h-CPU-s.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0036-amdmct-mct_ddr3-Disable-Fam10h-specific-MTRR-setup-o.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0036-cpu-amd-family_10h-family_15h-Add-Family-15h-microco.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0037-amdmct-mct_ddr3-Disable-Fam10h-specific-MTRR-setup-o.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0037-cpu-amd-car-Add-romstage-BSP-stack-overrun-detection.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0038-cpu-amd-car-Add-romstage-BSP-stack-overrun-detection.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0038-cpu-amd-car-Increase-Family-10h-CAR-size-limit-to-12.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0039-cpu-amd-car-Increase-Family-10h-CAR-size-limit-to-12.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0039-cpu-amd-car-Move-AP-stacks-below-the-BSP-stack-to-fr.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0040-cpu-amd-car-Move-AP-stacks-below-the-BSP-stack-to-fr.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0040-northbridge-amd-amdmct-Read-SPD-data-into-cache-to-d.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0041-cpu-amd-car-Initialize-entire-CAR-space-instead-of-o.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0041-northbridge-amd-amdmct-Read-SPD-data-into-cache-to-d.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0042-amd-amdmct-mct_ddr3-Improve-SPD-DIMM-detect-reliabil.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0042-cpu-amd-car-Initialize-entire-CAR-space-instead-of-o.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0043-amd-amdmct-mct_ddr3-Improve-SPD-DIMM-detect-reliabil.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0043-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0044-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0044-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0045-mainboard-asus-kgpe-d16-Enable-CC6.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0045-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0046-cpu-amd-Add-CC6-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0046-mainboard-asus-kgpe-d16-Enable-CC6.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0047-cpu-amd-Add-CC6-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0047-northbridge-amd-amdmct-Skip-DCT-config-write-to-Flas.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0048-northbridge-amd-amdmct-Skip-DCT-config-write-to-Flas.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0048-southbridge-amd-sb700-Add-AHCI-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0049-mainboard-asus-kgpe-d16-Properly-initialize-SB700-SA.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0050-mainboard-asus-kgpe-d16-Properly-initialize-SB700-SA.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Disable-broken-SATA-MSI-functi.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0051-southbridge-amd-sb700-Disable-broken-SATA-MSI-functi.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0051-southbridge-amd-sb700-Indicate-iSATA-eSATA-port-type.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0052-northbridge-amd-amdfam10-Add-ability-to-set-maximum-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0052-southbridge-amd-sb700-Indicate-iSATA-eSATA-port-type.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0053-northbridge-amd-amdfam10-Add-ability-to-set-maximum-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0053-northbridge-amd-amdmct-Verify-MCT-NVRAM-options-befo.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0054-northbridge-amd-amdmct-Verify-MCT-NVRAM-options-befo.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0054-src-northbridge-amd-amdmct-Add-option-to-override-ba.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0055-mainboard-asus-kgpe-d16-Add-missing-IRQ-routing-for-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0055-src-northbridge-amd-amdmct-Add-option-to-override-ba.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0056-mainboard-asus-kgpe-d16-Add-missing-IRQ-routing-for-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0056-northbridge-amd-amdmct-Fix-hang-on-boot-due-to-inval.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0057-northbridge-amd-amdmct-Fix-hang-on-boot-due-to-inval.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0057-southbridge-amd-sr5650-Fix-GPP3a-link-training-in-hi.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0058-southbridge-amd-sr5650-Add-optional-delay-after-link.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0058-southbridge-amd-sr5650-Fix-GPP3a-link-training-in-hi.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0059-mainboard-asus-kgpe-d16-Properly-configure-SR5690-so.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0059-southbridge-amd-sr5650-Add-optional-delay-after-link.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0060-mainboard-asus-kgpe-d16-Properly-configure-SR5690-so.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0060-southbridge-amd-sb700-Add-option-to-disable-SATA-ALP.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0061-mainboard-asus-kgpe-d16-Set-SP5100-subtype.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0061-southbridge-amd-sb700-Add-option-to-disable-SATA-ALP.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0062-mainboard-asus-kgpe-d16-Set-SP5100-subtype.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0062-northbridge-amd-amdmct-Fix-crash-on-startup-due-to-N.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Fix-crash-on-startup-due-to-N.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0064-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0064-southbridge-amd-sb700-Do-drive-detection-even-in-AHC.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0065-southbridge-amd-sb700-Do-drive-detection-even-in-AHC.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0065-src-southbridge-amd-sb700-Reset-SATA-controller-in-A.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0066-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0066-src-southbridge-amd-sb700-Reset-SATA-controller-in-A.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Fix-SATA-port-4-5-drive-detect.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0068-southbridge-amd-sb700-Fix-SATA-port-4-5-drive-detect.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0068-southbridge-amd-sb700-Fix-random-persistent-SATA-AHC.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0069-northbridge-amd-amdmct-mct_ddr3-Fix-lockups-and-wast.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0069-southbridge-amd-sb700-Fix-random-persistent-SATA-AHC.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0070-cpu-amd-Fix-AMD-Family-15h-ECC-initialization-reliab.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0070-northbridge-amd-amdmct-mct_ddr3-Fix-lockups-and-wast.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0071-cpu-amd-Fix-AMD-Family-15h-ECC-initialization-reliab.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0071-northbridge-amd-amdfam10-Properly-indicate-node-and-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0072-amd-amdmct-mct_ddr3-Add-Family-15h-RDIMM-timing-and-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0072-northbridge-amd-amdfam10-Properly-indicate-node-and-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0073-amd-amdmct-mct_ddr3-Add-Family-15h-RDIMM-timing-and-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0073-northbridge-amd-amdmct-mct_ddr3-Attempt-to-recover-f.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0074-northbridge-amd-amdmct-mct_ddr3-Attempt-to-recover-f.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0074-northbridge-amd-amdmct-mct_ddr3-Work-around-strange-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0075-northbridge-amd-amdmct-mct_ddr3-Add-additional-debug.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0075-northbridge-amd-amdmct-mct_ddr3-Work-around-strange-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0076-northbridge-amd-amdmct-mct_ddr3-Add-additional-debug.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0076-northbridge-amd-amdmct-mct_ddr3-Fix-null-pointer-acc.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0077-northbridge-amd-amdmct-mct_ddr3-Add-missing-Family-1.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0077-northbridge-amd-amdmct-mct_ddr3-Fix-null-pointer-acc.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0078-northbridge-amd-amdmct-mct_ddr3-Add-missing-Family-1.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0078-northbridge-amd-amdmct-mct_ddr3-Set-SkewMemClk-when-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0079-northbridge-amd-amdmct-mct_ddr3-Properly-indicate-cl.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0079-northbridge-amd-amdmct-mct_ddr3-Set-SkewMemClk-when-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0080-northbridge-amd-amdmct-mct_ddr3-Fix-Family-10h-boot-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0080-northbridge-amd-amdmct-mct_ddr3-Properly-indicate-cl.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0081-northbridge-amd-amdmct-mct_ddr3-Fix-Family-10h-boot-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0081-src-southbridge-amd-sr5650-Always-configure-lane-dir.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0082-cpu-amd-family_10h-family_15h-Fix-BSP-stack-corrupti.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0082-src-southbridge-amd-sr5650-Always-configure-lane-dir.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0083-cpu-amd-family_10h-family_15h-Fix-BSP-stack-corrupti.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0083-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0084-amd-amdmct-mct_ddr3-Partially-fix-up-registered-DIMM.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0084-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0085-amd-amdmct-mct_ddr3-Partially-fix-up-registered-DIMM.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-Fix-Family-15h-detection.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0086-northbridge-amd-amdmct-Fix-Family-15h-detection.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0086-northbridge-amd-amdmct-mct_ddr3-Add-registered-and-x.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0087-cpu-amd-family_10h-family_15h-Fix-Family-15h-multipl.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0087-northbridge-amd-amdmct-Reduce-maximum-number-of-DDR3.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0088-northbridge-amd-amdfam10-Add-probe-filter-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0088-northbridge-amd-amdmct-mct_ddr3-Add-registered-and-x.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0089-cpu-amd-family_10h-family_15h-Bring-initial-HT-regis.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0089-cpu-amd-family_10h-family_15h-Fix-Family-15h-multipl.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0090-northbridge-amd-amdfam10-Add-probe-filter-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0090-northbridge-amd-amdmct-mct_ddr3-Move-K10D-configurat.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0091-cpu-amd-family_10h-family_15h-Bring-initial-HT-regis.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0091-mainboard-asus-kgpe-d16-Fix-I-O-link-detection.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0092-cpu-amd-family_10h-family_15h-Set-northbridge-thrott.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0092-northbridge-amd-amdmct-mct_ddr3-Move-K10D-configurat.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0093-cpu-amd-family_10h-family_15h-Fix-incorrect-revision.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0093-mainboard-asus-kgpe-d16-Fix-I-O-link-detection.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0094-cpu-amd-family_10h-family_15h-Set-northbridge-thrott.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0094-northbridge-amd-amdht-Add-support-for-HT3-2.8GHz-and.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0095-amd-family_10h-family_15h-Fix-poor-performance-on-Fa.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0095-cpu-amd-family_10h-family_15h-Fix-incorrect-revision.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0096-amd-amdmct-mct_ddr3-Fix-poor-performance-on-Family-1.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0096-northbridge-amd-amdht-Add-support-for-HT3-2.8GHz-and.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0097-amd-family_10h-family_15h-Fix-poor-performance-on-Fa.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0097-northbridge-amd-amdht-Fix-poor-performance-on-Family.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0098-amd-amdmct-mct_ddr3-Fix-poor-performance-on-Family-1.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0098-northbridge-amd-amdfam10-Fix-poor-performance-on-Fam.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0099-cpu-amd-family_10h-family_15h-Configure-NB-register-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0099-northbridge-amd-amdht-Fix-poor-performance-on-Family.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0100-cpu-amd-family_10h-family_15h-Set-up-link-XCS-token-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0100-northbridge-amd-amdfam10-Fix-poor-performance-on-Fam.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0101-cpu-amd-family_10h-family_15h-Configure-NB-register-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0101-northbridge-amd-amdmct-mct_ddr3-Force-retraining-on-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0102-cpu-amd-family_10h-family_15h-Set-up-link-XCS-token-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0102-northbridge-amd-amdfam10-Fix-invalid-NUMA-table.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0103-northbridge-amd-amdfam10-Add-Family-15h-cache-partit.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0103-northbridge-amd-amdmct-mct_ddr3-Force-retraining-on-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0104-amd-amdmct-mct_ddr3-Set-prefetch-double-stride-to-im.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0104-northbridge-amd-amdfam10-Fix-invalid-NUMA-table.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0105-cpu-amd-family_10h-family_15h-Set-up-Family-15h-Link.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0105-northbridge-amd-amdfam10-Add-Family-15h-cache-partit.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0106-amd-amdmct-mct_ddr3-Set-prefetch-double-stride-to-im.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0106-cpu-amd-family_10h-family_15h-Set-up-cache-controls-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0107-cpu-amd-family_10h-family_15h-Set-up-Family-15h-Link.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0107-cpu-amd-family_10h-family_15h-Set-up-SRI-to-XCS-Toke.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0108-amd-amdfam10-Control-Family-15h-cache-partitioning-a.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0108-cpu-amd-family_10h-family_15h-Set-up-cache-controls-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0109-cpu-amd-family_10h-family_15h-Set-up-SRI-to-XCS-Toke.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0109-northbridge-amd-amdht-Add-isochronous-setup-support-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0110-amd-amdfam10-Control-Family-15h-cache-partitioning-a.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0110-arch-x86-acpi-Add-IVRS-table-generation-routines.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0111-northbridge-amd-amdht-Add-isochronous-setup-support-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0111-southbridge-amd-sr5650-Add-IOMMU-support.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0112-arch-x86-acpi-Add-IVRS-table-generation-routines.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0112-southbridge-amd-sr5650-Hide-clock-configuration-devi.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0113-northbridge-amd-amdfam10-Rename-mislabeled-iommu-nvr.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0113-southbridge-amd-sr5650-Add-IOMMU-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0114-northbridge-amd-amdfam10-Fix-gart-setup-not-working-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0114-southbridge-amd-sr5650-Hide-clock-configuration-devi.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0115-mainboard-asus-kgpe-d16-Add-several-nvram-configurat.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0115-northbridge-amd-amdfam10-Rename-mislabeled-iommu-nvr.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0116-northbridge-amd-amdfam10-Fix-gart-setup-not-working-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0116-southbridge-amd-sr5650-Use-correct-PCI-configuration.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0117-mainboard-asus-kgpe-d16-Add-several-nvram-configurat.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0117-southbridge-amd-sr5650-Add-MCFG-ACPI-table-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0118-southbridge-amd-sb700-Fix-mismatched-FADT-entries.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0118-southbridge-amd-sr5650-Use-correct-PCI-configuration.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0119-southbridge-amd-sb700-Fix-drifting-system-clock.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0119-southbridge-amd-sr5650-Add-MCFG-ACPI-table-support.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0120-northbridge-amd-amdmct-mct_ddr3-Add-cc6-setup-inform.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0120-southbridge-amd-sb700-Fix-mismatched-FADT-entries.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0121-northbridge-amd-amdfam10-Work-around-sporadic-lockup.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0121-southbridge-amd-sb700-Fix-drifting-system-clock.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0122-northbridge-amd-amdmct-mct_ddr3-Add-cc6-setup-inform.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0122-northbridge-amd-amdmct-mct_ddr3-Ensure-channel-clock.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0123-northbridge-amd-amdfam10-Work-around-sporadic-lockup.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0123-northbridge-amd-amdmct-mct_ddr3-Add-DDR3-termination.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0124-northbridge-amd-amdmct-mct_ddr3-Ensure-channel-clock.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0124-northbridge-amd-amdmct-mct_ddr3-Fix-a-minor-RDIMM-CS.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0125-northbridge-amd-amdmct-mct_ddr3-Add-DDR3-termination.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0125-northbridge-amd-amdmct-mct_ddr3-Fix-odd-rank-data-co.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0126-northbridge-amd-amdmct-mct_ddr3-Fix-a-minor-RDIMM-CS.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0126-northbridge-amd-amdmct-mct_ddr3-Use-antiphase-to-bet.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-odd-rank-data-co.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0128-drivers-pc80-Add-optional-spinlock-for-nvram-CBFS-ac.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0128-northbridge-amd-amdmct-mct_ddr3-Use-antiphase-to-bet.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0129-mainboard-asus-kgpe-d16-Enable-CBFS-spinlocks.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0129-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0130-cpu-amd-microcode-Introduce-CBFS-access-spinlock-to-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0130-drivers-pc80-Add-optional-spinlock-for-nvram-CBFS-ac.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0131-mainboard-asus-kgpe-d16-Enable-CBFS-spinlocks.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0131-mainboard-asus-kgpe-d16-Limit-HT-speed-to-2.6GHz.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0132-cpu-amd-family_10h-family_15h-Apply-missing-Family-1.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0132-cpu-amd-microcode-Introduce-CBFS-access-spinlock-to-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0133-mainboard-asus-kgpe-d16-Limit-HT-speed-to-2.6GHz.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0133-northbridge-amd-amdmct-mct_ddr3-Use-StopOnError-to-d.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0134-cpu-amd-family_10h-family_15h-Apply-missing-Family-1.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0134-mainboard-asus-kgpe-d16-Enable-GART-by-default.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0135-northbridge-amd-amdfam10-Fix-incorrect-channel-buffe.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0135-northbridge-amd-amdmct-mct_ddr3-Use-StopOnError-to-d.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0136-cpu-amd-family_10h-family_15h-Force-iolink-detect-to.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0136-mainboard-asus-kgpe-d16-Enable-GART-by-default.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0137-northbridge-amd-amdfam10-Fix-incorrect-channel-buffe.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0137-northbridge-amd-amdht-Fix-XCS-buffer-count-setup-on-.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0138-cpu-amd-family_10h-family_15h-Fix-link-type-detectio.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0138-cpu-amd-family_10h-family_15h-Force-iolink-detect-to.patch
 delete mode 100644 
resources/libreboot/patch/kgpe-d16/0139-cpu-amd-family_10h-family_15h-Enable-DFE-on-Family-1.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0139-northbridge-amd-amdht-Fix-XCS-buffer-count-setup-on-.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0140-cpu-amd-family_10h-family_15h-Fix-link-type-detectio.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0141-cpu-amd-family_10h-family_15h-Enable-DFE-on-Family-1.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0142-cpu-amd-family_10h-family_15h-Fix-build-when-microco.patch
 create mode 100644 
resources/libreboot/patch/kgpe-d16/0143-device-smbus-Avoid-infinite-loop-if-i2c-device-has-w.patch
 delete mode 100644 
resources/libreboot/patch/misc/0009-chromeos-Allow-disabling-vboot-firmware-verification.patch

diff --git 
a/resources/depthcharge/patch/0007-vboot-Display-callbacks-for-developer-and-recovery-m.patch
 
b/resources/depthcharge/patch/0007-vboot-Display-callbacks-for-developer-and-recovery-m.patch
index 4de5a67..ea06121 100644
--- 
a/resources/depthcharge/patch/0007-vboot-Display-callbacks-for-developer-and-recovery-m.patch
+++ 
b/resources/depthcharge/patch/0007-vboot-Display-callbacks-for-developer-and-recovery-m.patch
@@ -1,4 +1,4 @@
-From dc7421b033667ccbad3429e6ed118c849f3b05ca Mon Sep 17 00:00:00 2001
+From 541a3f09ecb062e3f0778eb9846732cfabcbfbba Mon Sep 17 00:00:00 2001
 From: Paul Kocialkowski <address@hidden>
 Date: Tue, 11 Aug 2015 11:22:54 +0200
 Subject: [PATCH 7/7] vboot: Display callbacks for developer and recovery mode
@@ -9,14 +9,14 @@ free software (Chrome OS), so this implements a text-based 
interface instead.
 
 Signed-off-by: Paul Kocialkowski <address@hidden>
 ---
- src/vboot/callbacks/display.c | 157 ++++++++++++++++++++++++++++++++++++++----
- 1 file changed, 145 insertions(+), 12 deletions(-)
+ src/vboot/callbacks/display.c | 168 +++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 156 insertions(+), 12 deletions(-)
 
 diff --git a/src/vboot/callbacks/display.c b/src/vboot/callbacks/display.c
-index efa0691..2341621 100644
+index efa0691..b659f7b 100644
 --- a/src/vboot/callbacks/display.c
 +++ b/src/vboot/callbacks/display.c
-@@ -84,9 +84,16 @@ void print_on_center(const char *msg)
+@@ -84,9 +84,17 @@ void print_on_center(const char *msg)
        print_string(msg);
  }
  
@@ -27,6 +27,7 @@ index efa0691..2341621 100644
 +      unsigned int rows, cols;
 +      uint32_t boot_signed_only = 0;
 +      uint32_t boot_usb = 0;
++      uint32_t boot_legacy = 0;
 +      const char *fw_id;
 +      int fw_index;
 +      void *blob = NULL;
@@ -35,7 +36,7 @@ index efa0691..2341621 100644
  
        /*
         * Show the debug messages for development. It is a backup method
-@@ -98,31 +105,157 @@ VbError_t VbExDisplayScreen(uint32_t screen_type)
+@@ -98,31 +106,167 @@ VbError_t VbExDisplayScreen(uint32_t screen_type)
                video_console_clear();
                break;
        case VB_SCREEN_DEVELOPER_WARNING:
@@ -48,34 +49,44 @@ index efa0691..2341621 100644
 +                              &boot_signed_only);
 +
 +                      VbNvGet(vnc, VBNV_DEV_BOOT_USB, &boot_usb);
++                      VbNvGet(vnc, VBNV_DEV_BOOT_LEGACY, &boot_legacy);
 +              }
 +
 +              print_string(
 +                      "Welcome to developer mode!\n\n"
 +                      "Useful key combinations:\n"
 +                      "- Ctrl + H: Hold developer mode\n"
-+                      "- Ctrl + D: Continue booting\n");
++                      "- Ctrl + D: Boot from internal storage\n");
 +
 +              if (boot_usb)
 +                      print_string("- Ctrl + U: Boot from external media\n");
 +
++              if (boot_legacy)
++                      print_string("- Ctrl + L: Boot from legacy payload\n");
++
 +              print_string(
-+                      "- Ctrl + L: Boot from legacy media\n"
 +                      "- Ctrl + I: Show device information\n"
 +                      "- Space: Disable developer mode\n\n"
-+                      "This screen is shown for 3 seconds (if not 
held).\n\n");
++                      "This screen is shown for 3 seconds (if not held)."
++                      "\n\n");
 +
 +              if (vnc != NULL) {
 +                      if (!boot_signed_only)
 +                              print_string(
-+                                      "Warning: this device will boot "
-+                                      "unsigned kernels!\n");
++                                      "Warning: this device will boot kernels"
++                                      " without verifying their signature!"
++                                      "\n");
 +
 +                      if (boot_usb)
 +                              print_string(
 +                                      "Warning: this device will boot from "
 +                                      "external media!\n");
 +
++                      if (boot_legacy)
++                              print_string(
++                                      "Warning: this device will boot legacy "
++                                      "payloads!\n");
++
 +                      if (!boot_signed_only || boot_usb)
 +                              print_string("\n");
 +              }
@@ -130,7 +141,7 @@ index efa0691..2341621 100644
 +              print_string(
 +                      "Welcome to recovery mode!\n\n"
 +                      "Useful key combinations:\n"
-+                      "- Ctrl + D: Enable developer mode\n\n");
++                      "- Ctrl + D: Enable developer mode (if possible)\n\n");
 +
 +              if (screen_type == VB_SCREEN_RECOVERY_NO_GOOD)
 +                      print_on_center(
diff --git a/resources/libreboot/config/depthcharge/veyron_speedy/config 
b/resources/libreboot/config/depthcharge/veyron_speedy/config
index 9647cff..4abf201 100644
--- a/resources/libreboot/config/depthcharge/veyron_speedy/config
+++ b/resources/libreboot/config/depthcharge/veyron_speedy/config
@@ -206,6 +206,7 @@ CONFIG_HEAP_SIZE=0x4000
 # CONFIG_SOC_NVIDIA_TEGRA210 is not set
 # CONFIG_SOC_QC_IPQ806X is not set
 CONFIG_SOC_ROCKCHIP_RK3288=y
+# CONFIG_VBOOT_VERIFY_FIRMWARE is not set
 # CONFIG_CPU_SAMSUNG_EXYNOS5250 is not set
 # CONFIG_CPU_SAMSUNG_EXYNOS5420 is not set
 # CONFIG_SOC_UCB_RISCV is not set
@@ -285,14 +286,10 @@ CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE=0x00100000
 CONFIG_EC_SOFTWARE_SYNC=y
 # CONFIG_VBOOT_EC_SLOW_UPDATE is not set
 CONFIG_VIRTUAL_DEV_SWITCH=y
-# CONFIG_VBOOT_VERIFY_FIRMWARE is not set
 # CONFIG_NO_TPM_RESUME is not set
 # CONFIG_PHYSICAL_REC_SWITCH is not set
 # CONFIG_LID_SWITCH is not set
 # CONFIG_WIPEOUT_SUPPORTED is not set
-CONFIG_VBOOT_STARTS_IN_BOOTBLOCK=y
-CONFIG_SEPARATE_VERSTAGE=y
-CONFIG_RETURN_FROM_VERSTAGE=y
 # CONFIG_UEFI_2_4_BINDING is not set
 CONFIG_ARCH_ARM=y
 CONFIG_ARCH_BOOTBLOCK_ARM=y
@@ -356,7 +353,6 @@ CONFIG_MAINBOARD_HAS_NATIVE_VGA_INIT=y
 CONFIG_NATIVE_VGA_INIT_USE_EDID=y
 # CONFIG_MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG is not set
 # CONFIG_MULTIPLE_VGA_ADAPTERS is not set
-# CONFIG_SMBUS_HAS_AUX is not set
 # CONFIG_SPD_CACHE is not set
 # CONFIG_PCI is not set
 # CONFIG_PXE_ROM is not set
@@ -457,9 +453,6 @@ CONFIG_POST_DEVICE_NONE=y
 # CONFIG_POST_DEVICE_PCI_PCIE is not set
 # CONFIG_HAVE_ACPI_RESUME is not set
 CONFIG_HAVE_HARD_RESET=y
-# CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK is not set
-# CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK is not set
-# CONFIG_HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK is not set
 CONFIG_HAVE_MONOTONIC_TIMER=y
 CONFIG_GENERIC_UDELAY=y
 # CONFIG_TIMER_QUEUE is not set
diff --git 
a/resources/libreboot/patch/chromebook/0001-armv7-Word-sized-half-word-sized-memory-operations-f.patch
 
b/resources/libreboot/patch/chromebook/0001-armv7-Word-sized-half-word-sized-memory-operations-f.patch
deleted file mode 100644
index f89b160..0000000
--- 
a/resources/libreboot/patch/chromebook/0001-armv7-Word-sized-half-word-sized-memory-operations-f.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-From 9746b7bf27d4a3c7c0de78b26ec9f217887f4e7d Mon Sep 17 00:00:00 2001
-From: Paul Kocialkowski <address@hidden>
-Date: Tue, 22 Sep 2015 22:16:33 +0200
-Subject: [PATCH 1/2] armv7: Word-sized/half-word-sized memory operations for
- 32/16 bit read/write
-
-Some registers only allow word-sized or half-word-sized operations and will
-cause a data fault when accessed with byte-sized operations.
-However, the compiler may or may not break such an operation into smaller
-(byte-sized) chunks. Thus, we need to reliably perform word-sized operations 
for
-32 bit read/write and half-word-sized operations for 16 bit read/write.
-
-This is particularly the case on the rk3288 SRAM registers, where the watchdog
-tombstone is stored. Moving to GCC 5.2.0 introduced a change of strategy in the
-compiler, where a 32 bit read would be broken into byte-sized chunks, which
-caused a data fault when accessing the watchdog tombstone register.
-
-The definitions for byte-sized memory operations are also adapted to stay
-consistent with the rest.
-
-Change-Id: I1fb3fc139e0a813acf9d70f14386a9603c9f9ede
-Signed-off-by: Paul Kocialkowski <address@hidden>
----
- src/arch/arm/include/armv7/arch/io.h | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
-
-diff --git a/src/arch/arm/include/armv7/arch/io.h 
b/src/arch/arm/include/armv7/arch/io.h
-index 9d06003..94cb131 100644
---- a/src/arch/arm/include/armv7/arch/io.h
-+++ b/src/arch/arm/include/armv7/arch/io.h
-@@ -29,40 +29,49 @@
- 
- static inline uint8_t read8(const void *addr)
- {
-+      uint8_t val;
-+
-       dmb();
--      return *(volatile uint8_t *)addr;
-+      asm volatile ("ldrb %0, [%1]" : "=r" (val) : "r" (addr) : "memory");
-+      return val;
- }
- 
- static inline uint16_t read16(const void *addr)
- {
-+      uint16_t val;
-+
-       dmb();
--      return *(volatile uint16_t *)addr;
-+      asm volatile ("ldrh %0, [%1]" : "=r" (val) : "r" (addr) : "memory");
-+      return val;
- }
- 
- static inline uint32_t read32(const void *addr)
- {
-+      uint32_t val;
-+
-       dmb();
--      return *(volatile uint32_t *)addr;
-+      asm volatile ("ldr %0, [%1]" : "=r" (val) : "r" (addr) : "memory");
-+      return val;
- }
- 
- static inline void write8(void *addr, uint8_t val)
- {
-       dmb();
--      *(volatile uint8_t *)addr = val;
-+      asm volatile ("strb %0, [%1]" : : "r" (val), "r" (addr) : "memory");
-       dmb();
- }
- 
- static inline void write16(void *addr, uint16_t val)
- {
-       dmb();
--      *(volatile uint16_t *)addr = val;
-+      asm volatile ("strh %0, [%1]" : : "r" (val), "r" (addr) : "memory");
-       dmb();
- }
- 
- static inline void write32(void *addr, uint32_t val)
- {
-       dmb();
--      *(volatile uint32_t *)addr = val;
-+      asm volatile ("str %0, [%1]" : : "r" (val), "r" (addr) : "memory");
-       dmb();
- }
- 
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/chromebook/0001-chromeos-Allow-disabling-vboot-firmware-verification.patch
 
b/resources/libreboot/patch/chromebook/0001-chromeos-Allow-disabling-vboot-firmware-verification.patch
new file mode 100644
index 0000000..f268922
--- /dev/null
+++ 
b/resources/libreboot/patch/chromebook/0001-chromeos-Allow-disabling-vboot-firmware-verification.patch
@@ -0,0 +1,98 @@
+From 2178bea1fbef28afbb9ffa2d95673407fac1907e Mon Sep 17 00:00:00 2001
+From: Paul Kocialkowski <address@hidden>
+Date: Sun, 9 Aug 2015 10:23:38 +0200
+Subject: [PATCH] chromeos: Allow disabling vboot firmware verification when
+ ChromeOS is enabled
+
+Some ChromeOS bindings might be wanted without using vboot verification, for
+instance to boot up depthcharge from the version of Coreboot installed in the
+write-protected part of the SPI flash (without jumping to a RW firmware).
+
+Vboot firmware verification is still selected by default when ChromeOS is
+enabled, but this allows more flexibility since vboot firmware verification is
+no longer a hard requirement for ChromeOS (that this particular use case still
+allows booting ChromeOS).
+
+In the future, it would make sense to have all the separate components that
+CONFIG_CHROMEOS enables have their own config options, so that they can be
+enabled separately.
+
+Change-Id: Ia4057a56838aa05dcf3cb250ae1a27fd91402ddb
+Signed-off-by: Paul Kocialkowski <address@hidden>
+---
+ src/lib/bootmode.c                            | 2 ++
+ src/soc/rockchip/rk3288/Kconfig               | 2 +-
+ src/vendorcode/google/chromeos/Kconfig        | 2 +-
+ src/vendorcode/google/chromeos/vboot2/Kconfig | 4 ++++
+ 4 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/src/lib/bootmode.c b/src/lib/bootmode.c
+index f2ff72a..13c0130 100644
+--- a/src/lib/bootmode.c
++++ b/src/lib/bootmode.c
+@@ -80,8 +80,10 @@ void gfx_set_init_done(int done)
+ int display_init_required(void)
+ {
+       /* For Chrome OS always honor vboot_skip_display_init(). */
++#if CONFIG_VBOOT_VERIFY_FIRMWARE
+       if (IS_ENABLED(CONFIG_CHROMEOS))
+               return !vboot_skip_display_init();
++#endif
+ 
+       /* By default always initialize display. */
+       return 1;
+diff --git a/src/soc/rockchip/rk3288/Kconfig b/src/soc/rockchip/rk3288/Kconfig
+index bc484e3..74a63e7 100644
+--- a/src/soc/rockchip/rk3288/Kconfig
++++ b/src/soc/rockchip/rk3288/Kconfig
+@@ -35,7 +35,7 @@ config SOC_ROCKCHIP_RK3288
+ 
+ if SOC_ROCKCHIP_RK3288
+ 
+-config CHROMEOS
++config VBOOT_VERIFY_FIRMWARE
+       select VBOOT_STARTS_IN_BOOTBLOCK
+       select SEPARATE_VERSTAGE
+       select RETURN_FROM_VERSTAGE
+diff --git a/src/vendorcode/google/chromeos/Kconfig 
b/src/vendorcode/google/chromeos/Kconfig
+index 8309d19..694e0d7 100644
+--- a/src/vendorcode/google/chromeos/Kconfig
++++ b/src/vendorcode/google/chromeos/Kconfig
+@@ -31,7 +31,6 @@ config CHROMEOS
+       select BOOTMODE_STRAPS
+       select ELOG
+       select COLLECT_TIMESTAMPS
+-      select VBOOT_VERIFY_FIRMWARE
+       help
+         Enable ChromeOS specific features like the GPIO sub table in
+         the coreboot table. NOTE: Enabling this option on an unsupported
+@@ -129,6 +128,7 @@ config VIRTUAL_DEV_SWITCH
+ 
+ config VBOOT_VERIFY_FIRMWARE
+       bool "Verify firmware with vboot."
++      default y if CHROMEOS
+       default n
+       depends on HAVE_HARD_RESET
+       help
+diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig 
b/src/vendorcode/google/chromeos/vboot2/Kconfig
+index 930b009..610a847 100644
+--- a/src/vendorcode/google/chromeos/vboot2/Kconfig
++++ b/src/vendorcode/google/chromeos/vboot2/Kconfig
+@@ -16,6 +16,8 @@
+ ## Foundation, Inc.
+ ##
+ 
++if VBOOT_VERIFY_FIRMWARE
++
+ config VBOOT_STARTS_IN_BOOTBLOCK
+       bool "Vboot starts verifying in bootblock"
+       default n
+@@ -133,3 +135,5 @@ config VBOOT_DYNAMIC_WORK_BUFFER
+         ram to allocate the vboot work buffer. That means vboot verification
+         is after memory init and requires main memory to back the work
+         buffer.
++
++endif # VBOOT_VERIFY_FIRMWARE
+-- 
+1.9.1
+
diff --git 
a/resources/libreboot/patch/chromebook/0002-chromeos-Allow-disabling-vboot-firmware-verification.patch
 
b/resources/libreboot/patch/chromebook/0002-chromeos-Allow-disabling-vboot-firmware-verification.patch
deleted file mode 100644
index bed24b1..0000000
--- 
a/resources/libreboot/patch/chromebook/0002-chromeos-Allow-disabling-vboot-firmware-verification.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From d0e6324693214c51e707928e26571ecc9ab8ee03 Mon Sep 17 00:00:00 2001
-From: Paul Kocialkowski <address@hidden>
-Date: Sun, 9 Aug 2015 10:23:38 +0200
-Subject: [PATCH 2/2] chromeos: Allow disabling vboot firmware verification
- when ChromeOS is enabled
-
-Some ChromeOS bindings might be wanted without using vboot verification, for
-instance to boot up depthcharge from the version of Coreboot installed in the
-write-protected part of the SPI flash (without jumping to a RW firmware).
-
-Vboot firmware verification is still selected by default when ChromeOS is
-enabled, but this allows more flexibility since vboot firmware verification is
-no longer a hard requirement for ChromeOS (that this particular use case still
-allows booting ChromeOS).
-
-In the future, it would make sense to have all the separate components that
-CONFIG_CHROMEOS enables have their own config options, so that they can be
-enabled separately.
-
-Change-Id: Ia4057a56838aa05dcf3cb250ae1a27fd91402ddb
-Signed-off-by: Paul Kocialkowski <address@hidden>
----
- src/lib/bootmode.c                            | 2 ++
- src/vendorcode/google/chromeos/Kconfig        | 2 +-
- src/vendorcode/google/chromeos/vboot2/Kconfig | 4 ++++
- 3 files changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/src/lib/bootmode.c b/src/lib/bootmode.c
-index f2ff72a..13c0130 100644
---- a/src/lib/bootmode.c
-+++ b/src/lib/bootmode.c
-@@ -80,8 +80,10 @@ void gfx_set_init_done(int done)
- int display_init_required(void)
- {
-       /* For Chrome OS always honor vboot_skip_display_init(). */
-+#if CONFIG_VBOOT_VERIFY_FIRMWARE
-       if (IS_ENABLED(CONFIG_CHROMEOS))
-               return !vboot_skip_display_init();
-+#endif
- 
-       /* By default always initialize display. */
-       return 1;
-diff --git a/src/vendorcode/google/chromeos/Kconfig 
b/src/vendorcode/google/chromeos/Kconfig
-index 8309d19..694e0d7 100644
---- a/src/vendorcode/google/chromeos/Kconfig
-+++ b/src/vendorcode/google/chromeos/Kconfig
-@@ -31,7 +31,6 @@ config CHROMEOS
-       select BOOTMODE_STRAPS
-       select ELOG
-       select COLLECT_TIMESTAMPS
--      select VBOOT_VERIFY_FIRMWARE
-       help
-         Enable ChromeOS specific features like the GPIO sub table in
-         the coreboot table. NOTE: Enabling this option on an unsupported
-@@ -129,6 +128,7 @@ config VIRTUAL_DEV_SWITCH
- 
- config VBOOT_VERIFY_FIRMWARE
-       bool "Verify firmware with vboot."
-+      default y if CHROMEOS
-       default n
-       depends on HAVE_HARD_RESET
-       help
-diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig 
b/src/vendorcode/google/chromeos/vboot2/Kconfig
-index 33c33a5..5bd8b54 100644
---- a/src/vendorcode/google/chromeos/vboot2/Kconfig
-+++ b/src/vendorcode/google/chromeos/vboot2/Kconfig
-@@ -16,6 +16,8 @@
- ## Foundation, Inc.
- ##
- 
-+if VBOOT_VERIFY_FIRMWARE
-+
- config VBOOT_STARTS_IN_BOOTBLOCK
-       bool "Vboot starts verifying in bootblock"
-       default n
-@@ -133,3 +135,5 @@ config VBOOT_DYNAMIC_WORK_BUFFER
-         ram to allocate the vboot work buffer. That means vboot verification
-         is after memory init and requires main memory to back the work
-         buffer.
-+
-+endif # VBOOT_VERIFY_FIRMWARE
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0001-drivers-i2c-w83795-Add-full-support-for-fan-control-.patch
 
b/resources/libreboot/patch/kgpe-d16/0001-drivers-i2c-w83795-Add-full-support-for-fan-control-.patch
deleted file mode 100644
index 0dc1606..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0001-drivers-i2c-w83795-Add-full-support-for-fan-control-.patch
+++ /dev/null
@@ -1,710 +0,0 @@
-From f7b8be27ea159845a982c310799a5896865016cd Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 17:53:20 -0500
-Subject: [PATCH 001/139] drivers/i2c/w83795: Add full support for fan control,
- fan monitoring, and voltage monitoring
-
-Change-Id: I3e246af0e398d65ee43ea708060885c67fd7d202
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/drivers/i2c/w83795/chip.h   | 142 +++++++++++++++++
- src/drivers/i2c/w83795/w83795.c | 334 ++++++++++++++++++++++++++--------------
- src/drivers/i2c/w83795/w83795.h |  52 +++++--
- 3 files changed, 399 insertions(+), 129 deletions(-)
- create mode 100644 src/drivers/i2c/w83795/chip.h
-
-diff --git a/src/drivers/i2c/w83795/chip.h b/src/drivers/i2c/w83795/chip.h
-new file mode 100644
-index 0000000..effe119
---- /dev/null
-+++ b/src/drivers/i2c/w83795/chip.h
-@@ -0,0 +1,142 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * 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.
-+ */
-+
-+struct drivers_i2c_w83795_config {
-+      uint8_t fanin_ctl1;
-+      uint8_t fanin_ctl2;
-+
-+      uint8_t temp_ctl1;
-+      uint8_t temp_ctl2;
-+      uint8_t temp_dtse;
-+
-+      uint8_t volt_ctl1;
-+      uint8_t volt_ctl2;
-+
-+      uint8_t temp1_fan_select;
-+      uint8_t temp2_fan_select;
-+      uint8_t temp3_fan_select;
-+      uint8_t temp4_fan_select;
-+      uint8_t temp5_fan_select;
-+      uint8_t temp6_fan_select;
-+
-+      uint8_t temp1_source_select;
-+      uint8_t temp2_source_select;
-+      uint8_t temp3_source_select;
-+      uint8_t temp4_source_select;
-+      uint8_t temp5_source_select;
-+      uint8_t temp6_source_select;
-+
-+      uint32_t vcore1_high_limit_mv;          /* mV */
-+      uint32_t vcore1_low_limit_mv;           /* mV */
-+      uint32_t vcore2_high_limit_mv;          /* mV */
-+      uint32_t vcore2_low_limit_mv;           /* mV */
-+      uint32_t vtt_high_limit_mv;             /* mV */
-+      uint32_t vtt_low_limit_mv;              /* mV */
-+      uint32_t vsen3_high_limit_mv;           /* mV */
-+      uint32_t vsen3_low_limit_mv;            /* mV */
-+      uint32_t vsen4_high_limit_mv;           /* mV */
-+      uint32_t vsen4_low_limit_mv;            /* mV */
-+      uint32_t vsen5_high_limit_mv;           /* mV */
-+      uint32_t vsen5_low_limit_mv;            /* mV */
-+      uint32_t vsen6_high_limit_mv;           /* mV */
-+      uint32_t vsen6_low_limit_mv;            /* mV */
-+      uint32_t vsen7_high_limit_mv;           /* mV */
-+      uint32_t vsen7_low_limit_mv;            /* mV */
-+      uint32_t vsen8_high_limit_mv;           /* mV */
-+      uint32_t vsen8_low_limit_mv;            /* mV */
-+      uint32_t vsen9_high_limit_mv;           /* mV */
-+      uint32_t vsen9_low_limit_mv;            /* mV */
-+      uint32_t vsen10_high_limit_mv;          /* mV */
-+      uint32_t vsen10_low_limit_mv;           /* mV */
-+      uint32_t vsen11_high_limit_mv;          /* mV */
-+      uint32_t vsen11_low_limit_mv;           /* mV */
-+      uint32_t vsen12_high_limit_mv;          /* mV */
-+      uint32_t vsen12_low_limit_mv;           /* mV */
-+      uint32_t vsen13_high_limit_mv;          /* mV */
-+      uint32_t vsen13_low_limit_mv;           /* mV */
-+      uint32_t vdd_high_limit_mv;             /* mV */
-+      uint32_t vdd_low_limit_mv;              /* mV */
-+      uint32_t vsb_high_limit_mv;             /* mV */
-+      uint32_t vsb_low_limit_mv;              /* mV */
-+      uint32_t vbat_high_limit_mv;            /* mV */
-+      uint32_t vbat_low_limit_mv;             /* mV */
-+
-+      int8_t tr1_critical_temperature;        /* °C */
-+      int8_t tr1_critical_hysteresis;         /* °C */
-+      int8_t tr1_warning_temperature;         /* °C */
-+      int8_t tr1_warning_hysteresis;          /* °C */
-+      int8_t tr2_critical_temperature;        /* °C */
-+      int8_t tr2_critical_hysteresis;         /* °C */
-+      int8_t tr2_warning_temperature;         /* °C */
-+      int8_t tr2_warning_hysteresis;          /* °C */
-+      int8_t tr3_critical_temperature;        /* °C */
-+      int8_t tr3_critical_hysteresis;         /* °C */
-+      int8_t tr3_warning_temperature;         /* °C */
-+      int8_t tr3_warning_hysteresis;          /* °C */
-+      int8_t tr4_critical_temperature;        /* °C */
-+      int8_t tr4_critical_hysteresis;         /* °C */
-+      int8_t tr4_warning_temperature;         /* °C */
-+      int8_t tr4_warning_hysteresis;          /* °C */
-+      int8_t tr5_critical_temperature;        /* °C */
-+      int8_t tr5_critical_hysteresis;         /* °C */
-+      int8_t tr5_warning_temperature;         /* °C */
-+      int8_t tr5_warning_hysteresis;          /* °C */
-+      int8_t tr6_critical_temperature;        /* °C */
-+      int8_t tr6_critical_hysteresis;         /* °C */
-+      int8_t tr6_warning_temperature;         /* °C */
-+      int8_t tr6_warning_hysteresis;          /* °C */
-+      int8_t dts_critical_temperature;        /* °C */
-+      int8_t dts_critical_hysteresis;         /* °C */
-+      int8_t dts_warning_temperature;         /* °C */
-+      int8_t dts_warning_hysteresis;          /* °C */
-+
-+      int8_t temp1_critical_temperature;      /* °C */
-+      int8_t temp2_critical_temperature;      /* °C */
-+      int8_t temp3_critical_temperature;      /* °C */
-+      int8_t temp4_critical_temperature;      /* °C */
-+      int8_t temp5_critical_temperature;      /* °C */
-+      int8_t temp6_critical_temperature;      /* °C */
-+
-+      int8_t temp1_target_temperature;        /* °C */
-+      int8_t temp2_target_temperature;        /* °C */
-+      int8_t temp3_target_temperature;        /* °C */
-+      int8_t temp4_target_temperature;        /* °C */
-+      int8_t temp5_target_temperature;        /* °C */
-+      int8_t temp6_target_temperature;        /* °C */
-+
-+      uint8_t fan1_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan2_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan3_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan4_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan5_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan6_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan7_nonstop;                   /* % of full speed (0-100) */
-+      uint8_t fan8_nonstop;                   /* % of full speed (0-100) */
-+
-+      uint8_t default_speed;                  /* % of full speed (0-100) */
-+
-+      uint8_t fan1_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan2_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan3_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan4_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan5_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan6_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan7_duty;                      /* % of full speed (0-100) */
-+      uint8_t fan8_duty;                      /* % of full speed (0-100) */
-+};
-diff --git a/src/drivers/i2c/w83795/w83795.c b/src/drivers/i2c/w83795/w83795.c
-index 2bbe0be..cf0cf2f 100644
---- a/src/drivers/i2c/w83795/w83795.c
-+++ b/src/drivers/i2c/w83795/w83795.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2012 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -21,106 +22,68 @@
- #include <arch/cpu.h>
- #include <console/console.h>
- #include <device/device.h>
--#include "southbridge/amd/cimx/sb700/smbus.h" /*SMBUS_IO_BASE*/
- #include "w83795.h"
-+#include <device/smbus.h>
-+#include "chip.h"
- 
--static int w83795_set_bank(u8 bank)
-+static int w83795_set_bank(struct device *dev, uint8_t bank)
- {
--      return do_smbus_write_byte(SMBUS_IO_BASE, W83795_DEV, 
W83795_REG_BANKSEL, bank);
-+      return smbus_write_byte(dev, W83795_REG_BANKSEL, bank);
- }
- 
--static u8 w83795_read(u16 reg)
-+static uint8_t w83795_read(struct device *dev, uint16_t reg)
- {
-       int ret;
- 
--      ret = w83795_set_bank(reg >> 8);
-+      ret = w83795_set_bank(dev, reg >> 8);
-       if (ret < 0) {
--              printk(BIOS_DEBUG, "read faild to set bank %x\n", reg >> 8);
-+              printk(BIOS_DEBUG, "read failed to set bank %x\n", reg >> 8);
-               return -1;
-       }
- 
--      ret = do_smbus_read_byte(SMBUS_IO_BASE, W83795_DEV, reg & 0xff);
-+      ret = smbus_read_byte(dev, reg & 0xff);
-       return ret;
- }
- 
--static u8 w83795_write(u16 reg, u8 value)
-+static uint8_t w83795_write(struct device *dev, uint16_t reg, uint8_t value)
- {
-       int err;
- 
--      err = w83795_set_bank(reg >> 8);
-+      err = w83795_set_bank(dev, reg >> 8);
-       if (err < 0) {
--              printk(BIOS_DEBUG, "write faild to set bank %x\n", reg >> 8);
-+              printk(BIOS_DEBUG, "write failed to set bank %x\n", reg >> 8);
-               return -1;
-       }
- 
--      err = do_smbus_write_byte(SMBUS_IO_BASE, W83795_DEV, reg & 0xff, value);
-+      err = smbus_write_byte(dev, reg & 0xff, value);
-       return err;
- }
- 
- /*
-- * Enable Digital Temperature Sensor
-+ * Configure Digital Temperature Sensor
-  */
--static void w83795_dts_enable(u8 dts_src)
-+static void w83795_dts_configure(struct device *dev, uint8_t dts_src)
- {
-       u8 val;
- 
-       /* DIS */
--      val = w83795_read(W83795_REG_DTSC);
-+      val = w83795_read(dev, W83795_REG_DTSC);
-       val |= (dts_src & 0x01);
--      w83795_write(W83795_REG_DTSC, val);
--
--      /* DTSE */
--      val = w83795_read(W83795_REG_DTSE);
--      val |= 0xFF;
--      w83795_write(W83795_REG_DTSE, val);
--
--      /* store bank3 regs first before enable DTS */
--
--      /*
--       * TD/TR1-4 thermal diode by default
--       *  0x00 Disable
--       *  0x01 thermistors on motherboard
--       *  0x10 different mode voltage
--       *  0x11 CPU internal thermal diode output
--       *
--       * TR5-6 thermistors by default  TRn
--       */
--      val = 0x55; /* thermal diode */
--      w83795_write(W83795_REG_TEMP_CTRL2, val);
--
--      /* Enable Digital Temperature Sensor */
--      val = w83795_read(W83795_REG_TEMP_CTRL1);
--      val |= W83795_REG_TEMP_CTRL1_EN_DTS; /* EN_DTS */
--      w83795_write(W83795_REG_TEMP_CTRL1, val);
-+      w83795_write(dev, W83795_REG_DTSC, val);
- }
- 
--static void w83795_set_tfmr(w83795_fan_mode_t mode)
--{
--      u8 val;
--      u8 i;
--
--      if ((mode == SMART_FAN_MODE) || (mode == THERMAL_CRUISE_MODE)) {
--              val = 0xFF;
--      } else {
--              val = 0x00;
--      }
--
--      for (i = 0; i < 6; i++)
--              w83795_write(W83795_REG_TFMR(i), val);
--}
--
--static u32 w83795_set_fan_mode(w83795_fan_mode_t mode)
-+static u32 w83795_set_fan_mode(struct device *dev, w83795_fan_mode_t mode)
- {
-       if (mode == SPEED_CRUISE_MODE) {
--              w83795_write(W83795_REG_FCMS1, 0xFF);
-+              w83795_write(dev, W83795_REG_FCMS1, 0xFF);
-               printk(BIOS_INFO, "W83795G/ADG work in Speed Cruise Mode\n");
-       }  else {
--              w83795_write(W83795_REG_FCMS1, 0x00);
-+              w83795_write(dev, W83795_REG_FCMS1, 0x00);
-               if (mode == THERMAL_CRUISE_MODE) {
--                      w83795_write(W83795_REG_FCMS2, 0x00);
-+                      w83795_write(dev, W83795_REG_FCMS2, 0x00);
-                       printk(BIOS_INFO, "W83795G/ADG work in Thermal Cruise 
Mode\n");
-               } else if (mode == SMART_FAN_MODE) {
--                      w83795_write(W83795_REG_FCMS2, 0x3F);
-+                      w83795_write(dev, W83795_REG_FCMS2, 0x3F);
-                       printk(BIOS_INFO, "W83795G/ADG work in Smart Fan 
Mode\n");
-               } else {
-                       printk(BIOS_INFO, "W83795G/ADG work in Manual Mode\n");
-@@ -131,40 +94,12 @@ static u32 w83795_set_fan_mode(w83795_fan_mode_t mode)
-       return 0;
- }
- 
--static void w83795_set_tss(void)
--{
--      u8 val;
--
--      val = 0x00;
--      w83795_write(W83795_REG_TSS(0), val); /* Temp1, 2 */
--      w83795_write(W83795_REG_TSS(1), val); /* Temp3, 4 */
--      w83795_write(W83795_REG_TSS(2), val); /* Temp5, 6 */
--}
--
--static void w83795_set_fan(w83795_fan_mode_t mode)
-+static void w83795_set_fan(struct device *dev, w83795_fan_mode_t mode)
- {
--      u8 i;
--
--      /* select temperature sensor (TSS)*/
--      w83795_set_tss();
--
--      /* select Temperature to Fan mapping Relationships (TFMR)*/
--      w83795_set_tfmr(mode);
--
-       /* set fan output controlled mode (FCMS)*/
--      w83795_set_fan_mode(mode);
-+      w83795_set_fan_mode(dev, mode);
- 
--      /* Set Critical Temperature to Full Speed all fan (CTFS) */
--      for (i = 0; i < 6; i++) {
--              w83795_write(W83795_REG_CTFS(i), 0x50); /* default 80 celsius 
degree */
--      }
--
--      if (mode == THERMAL_CRUISE_MODE) {
--              /* Set Target Temperature of Temperature Inputs (TTTI) */
--              for (i = 0; i < 6; i++) {
--                      w83795_write(W83795_REG_TTTI(i), 0x28); /* default 40 
celsius degree */
--              }
--      } else if (mode == SMART_FAN_MODE) {
-+      if (mode == SMART_FAN_MODE) {
-               /* Set the Relative Register-at SMART FAN IV Control Mode Table 
*/
-               //SFIV TODO
-       }
-@@ -173,16 +108,44 @@ static void w83795_set_fan(w83795_fan_mode_t mode)
-       //TODO
- }
- 
--static void w83795_init(w83795_fan_mode_t mode, u8 dts_src)
-+static uint8_t fan_pct_to_cfg_val(uint8_t percent)
- {
--      u8 i;
--      u8 val;
-+      uint16_t cfg = (((unsigned int)percent * 10000) / 3922);
-+      if (cfg > 0xff)
-+              cfg = 0xff;
-+      return cfg;
-+}
-+
-+static uint8_t millivolts_to_limit_value_type1(int millivolts)
-+{
-+      /* Datasheet v1.41 page 44 (VSEN1 - VSEN13, VTT) */
-+      return ((millivolts / 2) >> 2);
-+}
- 
--      if (do_smbus_read_byte(SMBUS_IO_BASE, W83795_DEV, 0x00) < 0) {
-+static uint8_t millivolts_to_limit_value_type2(int millivolts)
-+{
-+      /* Datasheet v1.41 page 44 (3VSB, 3VDD, VBAT) */
-+      return ((millivolts / 6) >> 2);
-+}
-+
-+static uint16_t millivolts_to_limit_value_type3(int millivolts)
-+{
-+      /* Datasheet v1.41 page 44 (VDSEN14 - VDSEN17) */
-+      return (millivolts / 2);
-+}
-+
-+static void w83795_init(struct device *dev, w83795_fan_mode_t mode, u8 
dts_src)
-+{
-+      struct drivers_i2c_w83795_config *config = dev->chip_info;
-+      uint8_t i;
-+      uint8_t val;
-+      uint16_t limit_value;
-+
-+      if (smbus_read_byte(dev, 0x00) < 0) {
-               printk(BIOS_ERR, "W83795G/ADG Nuvoton H/W Monitor not found\n");
-               return;
-       }
--      val = w83795_read(W83795_REG_CONFIG);
-+      val = w83795_read(dev, W83795_REG_CONFIG);
-       if ((val & W83795_REG_CONFIG_CONFIG48) == 0)
-               printk(BIOS_INFO, "Found 64 pin W83795G Nuvoton H/W Monitor\n");
-       else if ((val & W83795_REG_CONFIG_CONFIG48) == 1)
-@@ -190,35 +153,178 @@ static void w83795_init(w83795_fan_mode_t mode, u8 
dts_src)
- 
-       /* Reset */
-       val |= W83795_REG_CONFIG_INIT;
--      w83795_write(W83795_REG_CONFIG, val);
-+      w83795_write(dev, W83795_REG_CONFIG, val);
-+
-+      /* Fan monitor settings */
-+      w83795_write(dev, W83795_REG_FANIN_CTRL1, config->fanin_ctl1);
-+      w83795_write(dev, W83795_REG_FANIN_CTRL2, config->fanin_ctl2);
-+
-+      /* Temperature thresholds */
-+      w83795_write(dev, W83795_REG_TEMP_CRIT(0), 
config->tr1_critical_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(0), 
config->tr1_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_WARN(0), 
config->tr1_warning_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(0), 
config->tr1_warning_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT(1), 
config->tr2_critical_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(1), 
config->tr2_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_WARN(1), 
config->tr2_warning_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(1), 
config->tr2_warning_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT(2), 
config->tr3_critical_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(2), 
config->tr3_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_WARN(2), 
config->tr3_warning_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(2), 
config->tr3_warning_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT(3), 
config->tr4_critical_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(3), 
config->tr4_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_WARN(3), 
config->tr4_warning_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(3), 
config->tr4_warning_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT(4), 
config->tr5_critical_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(4), 
config->tr5_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_WARN(4), 
config->tr5_warning_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(4), 
config->tr5_warning_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT(5), 
config->tr6_critical_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(5), 
config->tr6_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_TEMP_WARN(5), 
config->tr6_warning_temperature);
-+      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(5), 
config->tr6_warning_hysteresis);
-+
-+      /* DTS enable */
-+      w83795_write(dev, W83795_REG_DTSE, config->temp_dtse);
-+
-+      /* DTS temperature thresholds */
-+      w83795_write(dev, W83795_REG_DTS_CRIT, 
config->dts_critical_temperature);
-+      w83795_write(dev, W83795_REG_DTS_CRIT_HYSTER, 
config->dts_critical_hysteresis);
-+      w83795_write(dev, W83795_REG_DTS_WARN, config->dts_warning_temperature);
-+      w83795_write(dev, W83795_REG_DTS_WARN_HYSTER, 
config->dts_warning_hysteresis);
-+
-+      /* Configure DTS registers in bank3 before enabling DTS */
-+      w83795_dts_configure(dev, dts_src);
-+
-+      /* Temperature monitor settings */
-+      w83795_write(dev, W83795_REG_TEMP_CTRL1, config->temp_ctl1);
-+      w83795_write(dev, W83795_REG_TEMP_CTRL2, config->temp_ctl2);
-+
-+      /* Temperature to fan mappings */
-+      w83795_write(dev, W83795_REG_TFMR(0), config->temp1_fan_select);
-+      w83795_write(dev, W83795_REG_TFMR(1), config->temp2_fan_select);
-+      w83795_write(dev, W83795_REG_TFMR(2), config->temp3_fan_select);
-+      w83795_write(dev, W83795_REG_TFMR(3), config->temp4_fan_select);
-+      w83795_write(dev, W83795_REG_TFMR(4), config->temp5_fan_select);
-+      w83795_write(dev, W83795_REG_TFMR(5), config->temp6_fan_select);
-+
-+      /* Temperature data source to temperature mappings */
-+      w83795_write(dev, W83795_REG_T12TSS, ((config->temp2_source_select & 
0xff) << 8) | (config->temp1_source_select & 0xff));
-+      w83795_write(dev, W83795_REG_T34TSS, ((config->temp4_source_select & 
0xff) << 8) | (config->temp3_source_select & 0xff));
-+      w83795_write(dev, W83795_REG_T56TSS, ((config->temp6_source_select & 
0xff) << 8) | (config->temp5_source_select & 0xff));
- 
--      /* Fan monitoring setting */
--      val = 0xFF; /* FAN1-FAN8 */
--      w83795_write(W83795_REG_FANIN_CTRL1, val);
--      val = 0x3F; /* FAN9-FAN14 */
--      w83795_write(W83795_REG_FANIN_CTRL2, val);
--
--      /* enable monitoring operations */
--      val = w83795_read(W83795_REG_CONFIG);
--      val |= W83795_REG_CONFIG_START;
--      w83795_write(W83795_REG_CONFIG, val);
--
--      w83795_dts_enable(dts_src);
--      w83795_set_fan(mode);
-+      /* Set Critical Temperature to Full Speed all fan (CTFS) */
-+      w83795_write(dev, W83795_REG_CTFS(0), 
config->temp1_critical_temperature);
-+      w83795_write(dev, W83795_REG_CTFS(1), 
config->temp2_critical_temperature);
-+      w83795_write(dev, W83795_REG_CTFS(2), 
config->temp3_critical_temperature);
-+      w83795_write(dev, W83795_REG_CTFS(3), 
config->temp4_critical_temperature);
-+      w83795_write(dev, W83795_REG_CTFS(4), 
config->temp5_critical_temperature);
-+      w83795_write(dev, W83795_REG_CTFS(5), 
config->temp6_critical_temperature);
-+
-+      /* Set fan control target temperatures */
-+      w83795_write(dev, W83795_REG_TTTI(0), config->temp1_target_temperature);
-+      w83795_write(dev, W83795_REG_TTTI(1), config->temp2_target_temperature);
-+      w83795_write(dev, W83795_REG_TTTI(2), config->temp3_target_temperature);
-+      w83795_write(dev, W83795_REG_TTTI(3), config->temp4_target_temperature);
-+      w83795_write(dev, W83795_REG_TTTI(4), config->temp5_target_temperature);
-+      w83795_write(dev, W83795_REG_TTTI(5), config->temp6_target_temperature);
-+
-+      /* Set fan stall prevention parameters */
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(0), config->fan1_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(1), config->fan2_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(2), config->fan3_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(3), config->fan4_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(4), config->fan5_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(5), config->fan6_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(6), config->fan7_nonstop);
-+      w83795_write(dev, W83795_REG_FAN_NONSTOP(7), config->fan8_nonstop);
-+
-+      /* Set fan default speed */
-+      w83795_write(dev, W83795_REG_DFSP, 
fan_pct_to_cfg_val(config->default_speed));
-+
-+      /* Set initial fan speeds */
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(0), 
fan_pct_to_cfg_val(config->fan1_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(1), 
fan_pct_to_cfg_val(config->fan2_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(2), 
fan_pct_to_cfg_val(config->fan3_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(3), 
fan_pct_to_cfg_val(config->fan4_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(4), 
fan_pct_to_cfg_val(config->fan5_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(5), 
fan_pct_to_cfg_val(config->fan6_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(6), 
fan_pct_to_cfg_val(config->fan7_duty));
-+      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(7), 
fan_pct_to_cfg_val(config->fan8_duty));
-+
-+      /* Voltage monitor settings */
-+      w83795_write(dev, W83795_REG_VOLT_CTRL1, config->volt_ctl1);
-+      w83795_write(dev, W83795_REG_VOLT_CTRL2, config->volt_ctl2);
-+
-+      /* Voltage high/low limits */
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(0), 
millivolts_to_limit_value_type1(config->vcore1_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(0), 
millivolts_to_limit_value_type1(config->vcore1_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(1), 
millivolts_to_limit_value_type1(config->vcore2_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(1), 
millivolts_to_limit_value_type1(config->vcore2_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(2), 
millivolts_to_limit_value_type1(config->vsen3_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(2), 
millivolts_to_limit_value_type1(config->vsen3_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(3), 
millivolts_to_limit_value_type1(config->vsen4_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(3), 
millivolts_to_limit_value_type1(config->vsen4_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(4), 
millivolts_to_limit_value_type1(config->vsen5_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(4), 
millivolts_to_limit_value_type1(config->vsen5_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(5), 
millivolts_to_limit_value_type1(config->vsen6_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(5), 
millivolts_to_limit_value_type1(config->vsen6_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(6), 
millivolts_to_limit_value_type1(config->vsen7_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(6), 
millivolts_to_limit_value_type1(config->vsen7_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(7), 
millivolts_to_limit_value_type1(config->vsen8_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(7), 
millivolts_to_limit_value_type1(config->vsen8_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(8), 
millivolts_to_limit_value_type1(config->vsen9_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(8), 
millivolts_to_limit_value_type1(config->vsen9_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(9), 
millivolts_to_limit_value_type1(config->vsen10_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(9), 
millivolts_to_limit_value_type1(config->vsen10_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(10), 
millivolts_to_limit_value_type1(config->vsen11_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(10), 
millivolts_to_limit_value_type1(config->vsen11_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(11), 
millivolts_to_limit_value_type1(config->vtt_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(11), 
millivolts_to_limit_value_type1(config->vtt_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(12), 
millivolts_to_limit_value_type2(config->vdd_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(12), 
millivolts_to_limit_value_type2(config->vdd_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(13), 
millivolts_to_limit_value_type2(config->vsb_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(13), 
millivolts_to_limit_value_type2(config->vsb_low_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(14), 
millivolts_to_limit_value_type2(config->vbat_high_limit_mv));
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(14), 
millivolts_to_limit_value_type2(config->vbat_low_limit_mv));
-+
-+      /* VSEN12 limits */
-+      limit_value = 
millivolts_to_limit_value_type3(config->vsen12_high_limit_mv);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_M(4), limit_value >> 2);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_L(4), limit_value & 0x3);
-+      limit_value = 
millivolts_to_limit_value_type3(config->vsen12_low_limit_mv);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_M(4), limit_value >> 2);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_L(4), limit_value & 0x3);
-+
-+      /* VSEN13 limits */
-+      limit_value = 
millivolts_to_limit_value_type3(config->vsen13_high_limit_mv);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_M(5), limit_value >> 2);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_L(5), limit_value & 0x3);
-+      limit_value = 
millivolts_to_limit_value_type3(config->vsen13_low_limit_mv);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_M(5), limit_value >> 2);
-+      w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_L(5), limit_value & 0x3);
-+
-+      w83795_set_fan(dev, mode);
- 
-       printk(BIOS_INFO, "Fan   CTFS(celsius)  TTTI(celsius)\n");
-       for (i = 0; i < 6; i++) {
--              val = w83795_read(W83795_REG_CTFS(i));
-+              val = w83795_read(dev, W83795_REG_CTFS(i));
-               printk(BIOS_INFO, " %x     %d", i, val);
--              val = w83795_read(W83795_REG_TTTI(i));
-+              val = w83795_read(dev, W83795_REG_TTTI(i));
-               printk(BIOS_INFO, "             %d\n", val);
-       }
- 
-       /* Temperature ReadOut */
-       for (i = 0; i < 9; i++) {
--              val = w83795_read(W83795_REG_DTS(i));
-+              val = w83795_read(dev, W83795_REG_DTS(i));
-               printk(BIOS_DEBUG, "DTS%x ReadOut=%x\n", i, val);
-       }
-+
-+      /* start monitoring operation */
-+      val = w83795_read(dev, W83795_REG_CONFIG);
-+      val |= W83795_REG_CONFIG_START;
-+      w83795_write(dev, W83795_REG_CONFIG, val);
- }
- 
- static void w83795_hwm_init(struct device *dev)
-@@ -232,9 +338,9 @@ static void w83795_hwm_init(struct device *dev)
-               die("CPU: missing cpu device structure");
- 
-       if (cpu->vendor == X86_VENDOR_AMD)
--              w83795_init(THERMAL_CRUISE_MODE, DTS_SRC_AMD_SBTSI);
-+              w83795_init(dev, THERMAL_CRUISE_MODE, DTS_SRC_AMD_SBTSI);
-       else if (cpu->vendor == X86_VENDOR_INTEL)
--              w83795_init(THERMAL_CRUISE_MODE, DTS_SRC_INTEL_PECI);
-+              w83795_init(dev, THERMAL_CRUISE_MODE, DTS_SRC_INTEL_PECI);
-       else
-               printk(BIOS_ERR, "Neither AMD nor INTEL CPU detected\n");
- }
-diff --git a/src/drivers/i2c/w83795/w83795.h b/src/drivers/i2c/w83795/w83795.h
-index cac4d5f..0727dc5 100644
---- a/src/drivers/i2c/w83795/w83795.h
-+++ b/src/drivers/i2c/w83795/w83795.h
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2012 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -20,8 +21,6 @@
- #ifndef _W83795_H_
- #define _W83795_H_
- 
--#define W83795_DEV                    0x2F /* Host I2c Addr (strap to addr1 
addr0 1 1, 0x5E) */
--
- #define W83795_REG_I2C_ADDR           0xFC
- #define W83795_REG_BANKSEL            0x00
- #define W83795_REG_CONFIG             0x01
-@@ -29,6 +28,8 @@
- #define W83795_REG_CONFIG_CONFIG48    0x04
- #define W83795_REG_CONFIG_INIT                0x80
- 
-+#define W83795_REG_VOLT_CTRL1         0x02
-+#define W83795_REG_VOLT_CTRL2         0x03
- #define W83795_REG_TEMP_CTRL1         0x04 /* Temperature Monitoring Control 
Register */
- #define W83795_REG_TEMP_CTRL2         0x05 /* Temperature Monitoring Control 
Register */
- #define W83795_REG_FANIN_CTRL1                0x06
-@@ -37,37 +38,58 @@
- #define DTS_SRC_INTEL_PECI            (0 << 0)
- #define DTS_SRC_AMD_SBTSI             (1 << 0)
- 
--#define W83795_REG_TSS(n)             (0x209 + (n)) /* Temperature Source 
Selection Register */
- #define W83795_REG_TTTI(n)            (0x260 + (n)) /* Target temperature 
W83795G/ADG will try to tune the fan output to keep */
- #define W83795_REG_CTFS(n)            (0x268 + (n)) /* Critical Temperature 
to Full Speed all fan */
--#define W83795_REG_HT(n)              (0x270 + (n)) /* Hysteresis of 
Temperature */
- #define W83795_REG_DTSC                       0x301 /* Digital Temperature 
Sensor Configuration */
- 
- #define W83795_REG_DTSE                       0x302 /* Digital Temperature 
Sensor Enable */
- #define W83795_REG_DTS(n)             (0x26 + (n))
- #define W83795_REG_VRLSB              0x3C
- 
--#define W83795_TEMP_REG_TR1           0x21
--#define W83795_TEMP_REG_TR2           0x22
--#define W83795_TEMP_REG_TR3           0x23
--#define W83795_TEMP_REG_TR4           0x24
--#define W83795_TEMP_REG_TR5           0x1F
--#define W83795_TEMP_REG_TR6           0x20
-+#define W83795_REG_TEMP_TR1           0x21
-+#define W83795_REG_TEMP_TR2           0x22
-+#define W83795_REG_TEMP_TR3           0x23
-+#define W83795_REG_TEMP_TR4           0x24
-+#define W83795_REG_TEMP_TR5           0x1F
-+#define W83795_REG_TEMP_TR6           0x20
-+
-+#define W83795_REG_VOLT_LIM_HIGH(n)   (0x70 + (n * 2))        /* Voltage high 
limit (0 == VSEN1) */
-+#define W83795_REG_VOLT_LIM_LOW(n)    (0x71 + (n * 2))        /* Voltage low 
limit (0 == VSEN1) */
-+#define W83795_REG_VOLT_LIM_HIGH_2_M(n)       (0x96 + (n * 4))        /* 
Voltage high limit MSB (0 == VDSEN14) */
-+#define W83795_REG_VOLT_LIM_LOW_2_M(n)        (0x97 + (n * 4))        /* 
Voltage low limit MSB (0 == VDSEN14)  */
-+#define W83795_REG_VOLT_LIM_HIGH_2_L(n)       (0x98 + (n * 4))        /* 
Voltage high limit LSB (0 == VDSEN14) */
-+#define W83795_REG_VOLT_LIM_LOW_2_L(n)        (0x99 + (n * 4))        /* 
Voltage low limit LSB (0 == VDSEN14)  */
-+
-+#define W83795_REG_TEMP_CRIT(n)               (0x96 + (n * 4))        /* 
Temperature critical limit */
-+#define W83795_REG_TEMP_CRIT_HYSTER(n)        (0x97 + (n * 4))        /* 
Temperature critical limit hysteresis */
-+#define W83795_REG_TEMP_WARN(n)               (0x98 + (n * 4))        /* 
Temperature warning limit */
-+#define W83795_REG_TEMP_WARN_HYSTER(n)        (0x99 + (n * 4))        /* 
Temperature warning limit hysteresis */
-+
-+#define W83795_REG_DTS_CRIT           0xB2                    /* Temperature 
critical limit */
-+#define W83795_REG_DTS_CRIT_HYSTER    0xB3                    /* Temperature 
critical limit hysteresis */
-+#define W83795_REG_DTS_WARN           0xB4                    /* Temperature 
warning limit */
-+#define W83795_REG_DTS_WARN_HYSTER    0xB5                    /* Temperature 
warning limit hysteresis */
- 
- #define W83795_REG_FCMS1              0x201
- #define W83795_REG_FCMS2              0x208
--#define W83795_REG_TFMR(n)            (0x202 + (n)) /*temperature to fam 
mappig*/
-+#define W83795_REG_TFMR(n)            (0x202 + (n))           /* Temperature 
to fan mapping */
-+#define W83795_REG_T12TSS             0x209                   /* Temperature 
Source Selection Register 1 */
-+#define W83795_REG_T34TSS             0x20A                   /* Temperature 
Source Selection Register 2 */
-+#define W83795_REG_T56TSS             0x20B                   /* Temperature 
Source Selection Register 3 */
-+#define W83795_REG_FAN_MANUAL_SPEED(n)        (0x210 + n)
- #define W83795_REG_DFSP                       0x20C
- 
-+#define W83795_REG_FAN_NONSTOP(n)     (0x228 + (n))   /* Fan Nonstop Value */
-+
- #define W83795_REG_FTSH(n)            (0x240 + (n) * 2)
- #define W83795_REG_FTSL(n)            (0x241 + (n) * 2)
- #define W83795_REG_TFTS                       0x250
- 
- typedef enum w83795_fan_mode {
--      SPEED_CRUISE_MODE,      ///< Fan Speed Cruise mode keeps the fan speed 
in a specified range
--      THERMAL_CRUISE_MODE,    ///< Thermal Cruise mode is an algorithm to 
control the fan speed to keep the temperature source around the TTTI
--      SMART_FAN_MODE,         ///< Smart Fan mode offers 6 slopes to control 
the fan speed
--      MANUAL_MODE,            ///< control manually
-+      SPEED_CRUISE_MODE = 0,          ///< Fan Speed Cruise mode keeps the 
fan speed in a specified range
-+      THERMAL_CRUISE_MODE = 1,        ///< Thermal Cruise mode is an 
algorithm to control the fan speed to keep the temperature source around the 
TTTI
-+      SMART_FAN_MODE = 2,             ///< Smart Fan mode offers 6 slopes to 
control the fan speed
-+      MANUAL_MODE = 3,                ///< control manually
- } w83795_fan_mode_t;
- 
- #endif
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0002-southbridge-amd-sb700-Allow-use-of-auxiliary-SMBUS-c.patch
 
b/resources/libreboot/patch/kgpe-d16/0002-southbridge-amd-sb700-Allow-use-of-auxiliary-SMBUS-c.patch
index 651c973..b5f03eb 100644
--- 
a/resources/libreboot/patch/kgpe-d16/0002-southbridge-amd-sb700-Allow-use-of-auxiliary-SMBUS-c.patch
+++ 
b/resources/libreboot/patch/kgpe-d16/0002-southbridge-amd-sb700-Allow-use-of-auxiliary-SMBUS-c.patch
@@ -1,28 +1,29 @@
-From 6ae8695f880a4a15672eda801226b4b1c83aa1a8 Mon Sep 17 00:00:00 2001
+From c3691fe7c155d63baedbb1836e6ccf9c1fcb5846 Mon Sep 17 00:00:00 2001
 From: Timothy Pearson <address@hidden>
 Date: Sat, 17 Oct 2015 04:36:47 -0500
-Subject: [PATCH 002/139] southbridge/amd/sb700: Allow use of auxiliary SMBUS
+Subject: [PATCH 002/143] southbridge/amd/sb700: Allow use of auxiliary SMBUS
  controller
 
 Change-Id: I29ece10eeefc2c75a3829c169f1e1aede7194ec2
 Signed-off-by: Timothy Pearson <address@hidden>
 ---
- src/device/Kconfig                |  4 ++++
- src/include/device/smbus.h        |  5 +++++
- src/southbridge/amd/sb700/Kconfig |  1 +
- src/southbridge/amd/sb700/sm.c    | 36 +++++++++++++++++++++++++++++++-----
- src/southbridge/amd/sb700/smbus.c | 15 +++++++++++++++
- 5 files changed, 56 insertions(+), 5 deletions(-)
+ src/device/Kconfig                |    4 ++++
+ src/include/device/smbus.h        |    5 ++++
+ src/southbridge/amd/sb700/Kconfig |    1 +
+ src/southbridge/amd/sb700/sm.c    |   47 ++++++++++++++++++++++++++++++-------
+ src/southbridge/amd/sb700/smbus.c |   15 ++++++++++++
+ src/southbridge/amd/sb700/smbus.h |    5 ++--
+ 6 files changed, 66 insertions(+), 11 deletions(-)
 
 diff --git a/src/device/Kconfig b/src/device/Kconfig
-index 613461b..3dd2b61 100644
+index 613461b..bcf7dad 100644
 --- a/src/device/Kconfig
 +++ b/src/device/Kconfig
 @@ -192,6 +192,10 @@ config MULTIPLE_VGA_ADAPTERS
        bool
        default n
  
-+config SMBUS_HAS_AUX
++config SMBUS_HAS_AUX_CHANNELS
 +      bool
 +      default n
 +
@@ -30,129 +31,133 @@ index 613461b..3dd2b61 100644
        bool
        default n
 diff --git a/src/include/device/smbus.h b/src/include/device/smbus.h
-index 073d7e2..53e90fb 100644
+index 073d7e2..a838f55 100644
 --- a/src/include/device/smbus.h
 +++ b/src/include/device/smbus.h
 @@ -47,4 +47,9 @@ int smbus_process_call(device_t dev, u8 cmd, u16 data);
  int smbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buffer);
  int smbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buffer);
  
-+#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX)
-+void smbus_switch_to_aux(uint8_t enable_aux);
-+uint8_t smbus_switched_to_aux(void);
++#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS)
++void smbus_switch_to_aux_channel(uint8_t aux_channel_number);
++uint8_t smbus_current_aux_channel(void);
 +#endif
 +
  #endif /* DEVICE_SMBUS_H */
 diff --git a/src/southbridge/amd/sb700/Kconfig 
b/src/southbridge/amd/sb700/Kconfig
-index 42ca2bb..a5dfe07 100644
+index 42ca2bb..0761934 100644
 --- a/src/southbridge/amd/sb700/Kconfig
 +++ b/src/southbridge/amd/sb700/Kconfig
 @@ -27,6 +27,7 @@ config SOUTHBRIDGE_SPECIFIC_OPTIONS # dummy
        select IOAPIC
        select HAVE_USBDEBUG_OPTIONS
        select HAVE_HARD_RESET
-+      select SMBUS_HAS_AUX
++      select SMBUS_HAS_AUX_CHANNELS
  
  # Set for southbridge SP5100 which also uses SB700 driver
  config SOUTHBRIDGE_AMD_SUBTYPE_SP5100
 diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c
-index f544c88..c216e1f 100644
+index f544c88..598ebec 100644
 --- a/src/southbridge/amd/sb700/sm.c
 +++ b/src/southbridge/amd/sb700/sm.c
-@@ -40,6 +40,8 @@
+@@ -40,6 +40,11 @@
  #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
  #endif
  
++#define PRIMARY_SMBUS_RESOURCE_NUMBER 0x90
++#define AUXILIARY_SMBUS_RESOURCE_NUMBER 0x58
++
 +uint8_t smbus_use_aux = 0;
 +
  /*
  * SB700 enables all USB controllers by default in SMBUS Control.
  * SB700 enables SATA by default in SMBUS Control.
-@@ -312,7 +314,10 @@ static int lsmbus_recv_byte(device_t dev)
+@@ -312,7 +317,10 @@ static int lsmbus_recv_byte(device_t dev)
        device = dev->path.i2c.device;
        pbus = get_pbus_smbus(dev);
  
 -      res = find_resource(pbus->dev, 0x90);
 +      if (!smbus_use_aux)
-+              res = find_resource(pbus->dev, 0x90);
++              res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
 +      else
-+              res = find_resource(pbus->dev, 0x58);
++              res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
  
        return do_smbus_recv_byte(res->base, device);
  }
-@@ -326,7 +331,10 @@ static int lsmbus_send_byte(device_t dev, u8 val)
+@@ -326,7 +334,10 @@ static int lsmbus_send_byte(device_t dev, u8 val)
        device = dev->path.i2c.device;
        pbus = get_pbus_smbus(dev);
  
 -      res = find_resource(pbus->dev, 0x90);
 +      if (!smbus_use_aux)
-+              res = find_resource(pbus->dev, 0x90);
++              res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
 +      else
-+              res = find_resource(pbus->dev, 0x58);
++              res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
  
        return do_smbus_send_byte(res->base, device, val);
  }
-@@ -340,7 +348,10 @@ static int lsmbus_read_byte(device_t dev, u8 address)
+@@ -340,7 +351,10 @@ static int lsmbus_read_byte(device_t dev, u8 address)
        device = dev->path.i2c.device;
        pbus = get_pbus_smbus(dev);
  
 -      res = find_resource(pbus->dev, 0x90);
 +      if (!smbus_use_aux)
-+              res = find_resource(pbus->dev, 0x90);
++              res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
 +      else
-+              res = find_resource(pbus->dev, 0x58);
++              res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
  
        return do_smbus_read_byte(res->base, device, address);
  }
-@@ -354,7 +365,10 @@ static int lsmbus_write_byte(device_t dev, u8 address, u8 
val)
+@@ -354,7 +368,10 @@ static int lsmbus_write_byte(device_t dev, u8 address, u8 
val)
        device = dev->path.i2c.device;
        pbus = get_pbus_smbus(dev);
  
 -      res = find_resource(pbus->dev, 0x90);
 +      if (!smbus_use_aux)
-+              res = find_resource(pbus->dev, 0x90);
++              res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
 +      else
-+              res = find_resource(pbus->dev, 0x58);
++              res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
  
        return do_smbus_write_byte(res->base, device, address, val);
  }
-@@ -393,7 +407,7 @@ static void sb700_sm_read_resources(device_t dev)
+@@ -393,9 +410,18 @@ static void sb700_sm_read_resources(device_t dev)
  
        /* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */
  
 -      /* smbus */
+-      res = new_resource(dev, 0x90);
+-      res->base  = 0xB00;
 +      /* primary smbus */
-       res = new_resource(dev, 0x90);
-       res->base  = 0xB00;
-       res->size = 0x10;
-@@ -402,6 +416,15 @@ static void sb700_sm_read_resources(device_t dev)
-       res->gran = 8;
-       res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | 
IORESOURCE_ASSIGNED;
- 
-+      /* auxiliary smbus */
-+      res = new_resource(dev, 0x58);
-+      res->base  = 0xB20;
++      res = new_resource(dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
++      res->base  = SMBUS_IO_BASE;
 +      res->size = 0x10;
 +      res->limit = 0xFFFFUL;  /* res->base + res->size -1; */
 +      res->align = 8;
 +      res->gran = 8;
 +      res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | 
IORESOURCE_ASSIGNED;
 +
-       compact_resources(dev);
- }
- 
-@@ -441,6 +464,9 @@ static void sb700_sm_set_resources(struct device *dev)
- 
-       res = find_resource(dev, 0x90);
-       pci_write_config32(dev, 0x90, res->base | 1);
++      /* auxiliary smbus */
++      res = new_resource(dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
++      res->base  = SMBUS_AUX_IO_BASE;
+       res->size = 0x10;
+       res->limit = 0xFFFFUL;  /* res->base + res->size -1; */
+       res->align = 8;
+@@ -439,8 +465,11 @@ static void sb700_sm_set_resources(struct device *dev)
+       pci_write_config8(dev, 0x65, byte);
+       /* TODO: End of test hpet */
+ 
+-      res = find_resource(dev, 0x90);
+-      pci_write_config32(dev, 0x90, res->base | 1);
++      res = find_resource(dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
++      pci_write_config32(dev, PRIMARY_SMBUS_RESOURCE_NUMBER, res->base | 1);
 +
-+      res = find_resource(dev, 0x58);
-+      pci_write_config32(dev, 0x58, res->base | 1);
++      res = find_resource(dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
++      pci_write_config32(dev, AUXILIARY_SMBUS_RESOURCE_NUMBER, res->base | 1);
  }
  
  static struct pci_operations lops_pci = {
 diff --git a/src/southbridge/amd/sb700/smbus.c 
b/src/southbridge/amd/sb700/smbus.c
-index 94f5e24..a89e830 100644
+index 94f5e24..e1cfe6b 100644
 --- a/src/southbridge/amd/sb700/smbus.c
 +++ b/src/southbridge/amd/sb700/smbus.c
 @@ -22,6 +22,11 @@
@@ -161,8 +166,8 @@ index 94f5e24..a89e830 100644
  
 +extern uint8_t smbus_use_aux;
 +
-+void smbus_switch_to_aux(uint8_t enable_aux);
-+uint8_t smbus_switched_to_aux(void);
++void smbus_switch_to_aux_channel(uint8_t aux_channel_number);
++uint8_t smbus_current_aux_channel(void);
 +
  void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
  {
@@ -171,17 +176,40 @@ index 94f5e24..a89e830 100644
        return 0;
  }
  
-+void smbus_switch_to_aux(uint8_t enable_aux)
++void smbus_switch_to_aux_channel(uint8_t aux_channel_number)
 +{
-+      smbus_use_aux = enable_aux;
++      smbus_use_aux = (aux_channel_number != 0);
 +}
 +
-+uint8_t smbus_switched_to_aux(void)
++uint8_t smbus_current_aux_channel(void)
 +{
 +      return smbus_use_aux;
 +}
 +
  #endif
+diff --git a/src/southbridge/amd/sb700/smbus.h 
b/src/southbridge/amd/sb700/smbus.h
+index d223fe7..34b4098 100644
+--- a/src/southbridge/amd/sb700/smbus.h
++++ b/src/southbridge/amd/sb700/smbus.h
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -24,8 +25,8 @@
+ #include "stddef.h"
+ #include <arch/io.h>
+ 
+-#define SMBUS_IO_BASE 0x6000  /* Is it a temporary SMBus I/O base address? */
+-                              /*SIZE 0x40 */
++#define SMBUS_IO_BASE 0xb00
++#define SMBUS_AUX_IO_BASE 0xb20
+ 
+ #define SMBHSTSTAT 0x0
+ #define SMBSLVSTAT 0x1
 -- 
-1.9.1
+1.7.9.5
 
diff --git 
a/resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-full-support-for-core-functio.patch
 
b/resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-full-support-for-core-functio.patch
new file mode 100644
index 0000000..0cbdaf6
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-full-support-for-core-functio.patch
@@ -0,0 +1,725 @@
+From 72d183bad6db0f2f91b991710d1c0a8113a071f3 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 5 Sep 2015 17:53:20 -0500
+Subject: [PATCH 003/143] drivers/i2c/w83795: Add full support for core
+ functions
+
+Add full support for fan control, fan monitoring, and voltage
+monitoring.  Fan speeds and functions are configurable via
+each mainboard's devicetree.cb file.
+
+NOTE: This patch effectively rewrites large portions of
+the original driver.  You may need to re-verify correct
+operation on your hardware if you were using the old
+driver code.
+
+Change-Id: I3e246af0e398d65ee43ea708060885c67fd7d202
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/drivers/i2c/w83795/chip.h   |  142 ++++++++++++++++
+ src/drivers/i2c/w83795/w83795.c |  339 ++++++++++++++++++++++++++-------------
+ src/drivers/i2c/w83795/w83795.h |   52 ++++--
+ 3 files changed, 405 insertions(+), 128 deletions(-)
+ create mode 100644 src/drivers/i2c/w83795/chip.h
+
+diff --git a/src/drivers/i2c/w83795/chip.h b/src/drivers/i2c/w83795/chip.h
+new file mode 100644
+index 0000000..c8a42ea
+--- /dev/null
++++ b/src/drivers/i2c/w83795/chip.h
+@@ -0,0 +1,142 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2015 Raptor Engineering
++ *
++ * 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.
++ */
++
++struct drivers_i2c_w83795_config {
++      uint8_t fanin_ctl1;
++      uint8_t fanin_ctl2;
++
++      uint8_t temp_ctl1;
++      uint8_t temp_ctl2;
++      uint8_t temp_dtse;
++
++      uint8_t volt_ctl1;
++      uint8_t volt_ctl2;
++
++      uint8_t temp1_fan_select;
++      uint8_t temp2_fan_select;
++      uint8_t temp3_fan_select;
++      uint8_t temp4_fan_select;
++      uint8_t temp5_fan_select;
++      uint8_t temp6_fan_select;
++
++      uint8_t temp1_source_select;
++      uint8_t temp2_source_select;
++      uint8_t temp3_source_select;
++      uint8_t temp4_source_select;
++      uint8_t temp5_source_select;
++      uint8_t temp6_source_select;
++
++      uint32_t vcore1_high_limit_mv;          /* mV */
++      uint32_t vcore1_low_limit_mv;           /* mV */
++      uint32_t vcore2_high_limit_mv;          /* mV */
++      uint32_t vcore2_low_limit_mv;           /* mV */
++      uint32_t vtt_high_limit_mv;             /* mV */
++      uint32_t vtt_low_limit_mv;              /* mV */
++      uint32_t vsen3_high_limit_mv;           /* mV */
++      uint32_t vsen3_low_limit_mv;            /* mV */
++      uint32_t vsen4_high_limit_mv;           /* mV */
++      uint32_t vsen4_low_limit_mv;            /* mV */
++      uint32_t vsen5_high_limit_mv;           /* mV */
++      uint32_t vsen5_low_limit_mv;            /* mV */
++      uint32_t vsen6_high_limit_mv;           /* mV */
++      uint32_t vsen6_low_limit_mv;            /* mV */
++      uint32_t vsen7_high_limit_mv;           /* mV */
++      uint32_t vsen7_low_limit_mv;            /* mV */
++      uint32_t vsen8_high_limit_mv;           /* mV */
++      uint32_t vsen8_low_limit_mv;            /* mV */
++      uint32_t vsen9_high_limit_mv;           /* mV */
++      uint32_t vsen9_low_limit_mv;            /* mV */
++      uint32_t vsen10_high_limit_mv;          /* mV */
++      uint32_t vsen10_low_limit_mv;           /* mV */
++      uint32_t vsen11_high_limit_mv;          /* mV */
++      uint32_t vsen11_low_limit_mv;           /* mV */
++      uint32_t vsen12_high_limit_mv;          /* mV */
++      uint32_t vsen12_low_limit_mv;           /* mV */
++      uint32_t vsen13_high_limit_mv;          /* mV */
++      uint32_t vsen13_low_limit_mv;           /* mV */
++      uint32_t vdd_high_limit_mv;             /* mV */
++      uint32_t vdd_low_limit_mv;              /* mV */
++      uint32_t vsb_high_limit_mv;             /* mV */
++      uint32_t vsb_low_limit_mv;              /* mV */
++      uint32_t vbat_high_limit_mv;            /* mV */
++      uint32_t vbat_low_limit_mv;             /* mV */
++
++      int8_t tr1_critical_temperature;        /* °C */
++      int8_t tr1_critical_hysteresis;         /* °C */
++      int8_t tr1_warning_temperature;         /* °C */
++      int8_t tr1_warning_hysteresis;          /* °C */
++      int8_t tr2_critical_temperature;        /* °C */
++      int8_t tr2_critical_hysteresis;         /* °C */
++      int8_t tr2_warning_temperature;         /* °C */
++      int8_t tr2_warning_hysteresis;          /* °C */
++      int8_t tr3_critical_temperature;        /* °C */
++      int8_t tr3_critical_hysteresis;         /* °C */
++      int8_t tr3_warning_temperature;         /* °C */
++      int8_t tr3_warning_hysteresis;          /* °C */
++      int8_t tr4_critical_temperature;        /* °C */
++      int8_t tr4_critical_hysteresis;         /* °C */
++      int8_t tr4_warning_temperature;         /* °C */
++      int8_t tr4_warning_hysteresis;          /* °C */
++      int8_t tr5_critical_temperature;        /* °C */
++      int8_t tr5_critical_hysteresis;         /* °C */
++      int8_t tr5_warning_temperature;         /* °C */
++      int8_t tr5_warning_hysteresis;          /* °C */
++      int8_t tr6_critical_temperature;        /* °C */
++      int8_t tr6_critical_hysteresis;         /* °C */
++      int8_t tr6_warning_temperature;         /* °C */
++      int8_t tr6_warning_hysteresis;          /* °C */
++      int8_t dts_critical_temperature;        /* °C */
++      int8_t dts_critical_hysteresis;         /* °C */
++      int8_t dts_warning_temperature;         /* °C */
++      int8_t dts_warning_hysteresis;          /* °C */
++
++      int8_t temp1_critical_temperature;      /* °C */
++      int8_t temp2_critical_temperature;      /* °C */
++      int8_t temp3_critical_temperature;      /* °C */
++      int8_t temp4_critical_temperature;      /* °C */
++      int8_t temp5_critical_temperature;      /* °C */
++      int8_t temp6_critical_temperature;      /* °C */
++
++      int8_t temp1_target_temperature;        /* °C */
++      int8_t temp2_target_temperature;        /* °C */
++      int8_t temp3_target_temperature;        /* °C */
++      int8_t temp4_target_temperature;        /* °C */
++      int8_t temp5_target_temperature;        /* °C */
++      int8_t temp6_target_temperature;        /* °C */
++
++      uint8_t fan1_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan2_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan3_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan4_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan5_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan6_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan7_nonstop;                   /* % of full speed (0-100) */
++      uint8_t fan8_nonstop;                   /* % of full speed (0-100) */
++
++      uint8_t default_speed;                  /* % of full speed (0-100) */
++
++      uint8_t fan1_duty;                      /* % of full speed (0-100) */
++      uint8_t fan2_duty;                      /* % of full speed (0-100) */
++      uint8_t fan3_duty;                      /* % of full speed (0-100) */
++      uint8_t fan4_duty;                      /* % of full speed (0-100) */
++      uint8_t fan5_duty;                      /* % of full speed (0-100) */
++      uint8_t fan6_duty;                      /* % of full speed (0-100) */
++      uint8_t fan7_duty;                      /* % of full speed (0-100) */
++      uint8_t fan8_duty;                      /* % of full speed (0-100) */
++};
+diff --git a/src/drivers/i2c/w83795/w83795.c b/src/drivers/i2c/w83795/w83795.c
+index 2bbe0be..0af272f 100644
+--- a/src/drivers/i2c/w83795/w83795.c
++++ b/src/drivers/i2c/w83795/w83795.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2012 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Raptor Engineering
+  *
+  * 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
+@@ -21,106 +22,68 @@
+ #include <arch/cpu.h>
+ #include <console/console.h>
+ #include <device/device.h>
+-#include "southbridge/amd/cimx/sb700/smbus.h" /*SMBUS_IO_BASE*/
+ #include "w83795.h"
++#include <device/smbus.h>
++#include "chip.h"
+ 
+-static int w83795_set_bank(u8 bank)
++static int w83795_set_bank(struct device *dev, uint8_t bank)
+ {
+-      return do_smbus_write_byte(SMBUS_IO_BASE, W83795_DEV, 
W83795_REG_BANKSEL, bank);
++      return smbus_write_byte(dev, W83795_REG_BANKSEL, bank);
+ }
+ 
+-static u8 w83795_read(u16 reg)
++static uint8_t w83795_read(struct device *dev, uint16_t reg)
+ {
+       int ret;
+ 
+-      ret = w83795_set_bank(reg >> 8);
++      ret = w83795_set_bank(dev, reg >> 8);
+       if (ret < 0) {
+-              printk(BIOS_DEBUG, "read faild to set bank %x\n", reg >> 8);
++              printk(BIOS_DEBUG, "read failed to set bank %x\n", reg >> 8);
+               return -1;
+       }
+ 
+-      ret = do_smbus_read_byte(SMBUS_IO_BASE, W83795_DEV, reg & 0xff);
++      ret = smbus_read_byte(dev, reg & 0xff);
+       return ret;
+ }
+ 
+-static u8 w83795_write(u16 reg, u8 value)
++static uint8_t w83795_write(struct device *dev, uint16_t reg, uint8_t value)
+ {
+       int err;
+ 
+-      err = w83795_set_bank(reg >> 8);
++      err = w83795_set_bank(dev, reg >> 8);
+       if (err < 0) {
+-              printk(BIOS_DEBUG, "write faild to set bank %x\n", reg >> 8);
++              printk(BIOS_DEBUG, "write failed to set bank %x\n", reg >> 8);
+               return -1;
+       }
+ 
+-      err = do_smbus_write_byte(SMBUS_IO_BASE, W83795_DEV, reg & 0xff, value);
++      err = smbus_write_byte(dev, reg & 0xff, value);
+       return err;
+ }
+ 
+ /*
+- * Enable Digital Temperature Sensor
++ * Configure Digital Temperature Sensor
+  */
+-static void w83795_dts_enable(u8 dts_src)
++static void w83795_dts_configure(struct device *dev, uint8_t dts_src)
+ {
+       u8 val;
+ 
+       /* DIS */
+-      val = w83795_read(W83795_REG_DTSC);
++      val = w83795_read(dev, W83795_REG_DTSC);
+       val |= (dts_src & 0x01);
+-      w83795_write(W83795_REG_DTSC, val);
+-
+-      /* DTSE */
+-      val = w83795_read(W83795_REG_DTSE);
+-      val |= 0xFF;
+-      w83795_write(W83795_REG_DTSE, val);
+-
+-      /* store bank3 regs first before enable DTS */
+-
+-      /*
+-       * TD/TR1-4 thermal diode by default
+-       *  0x00 Disable
+-       *  0x01 thermistors on motherboard
+-       *  0x10 different mode voltage
+-       *  0x11 CPU internal thermal diode output
+-       *
+-       * TR5-6 thermistors by default  TRn
+-       */
+-      val = 0x55; /* thermal diode */
+-      w83795_write(W83795_REG_TEMP_CTRL2, val);
+-
+-      /* Enable Digital Temperature Sensor */
+-      val = w83795_read(W83795_REG_TEMP_CTRL1);
+-      val |= W83795_REG_TEMP_CTRL1_EN_DTS; /* EN_DTS */
+-      w83795_write(W83795_REG_TEMP_CTRL1, val);
++      w83795_write(dev, W83795_REG_DTSC, val);
+ }
+ 
+-static void w83795_set_tfmr(w83795_fan_mode_t mode)
+-{
+-      u8 val;
+-      u8 i;
+-
+-      if ((mode == SMART_FAN_MODE) || (mode == THERMAL_CRUISE_MODE)) {
+-              val = 0xFF;
+-      } else {
+-              val = 0x00;
+-      }
+-
+-      for (i = 0; i < 6; i++)
+-              w83795_write(W83795_REG_TFMR(i), val);
+-}
+-
+-static u32 w83795_set_fan_mode(w83795_fan_mode_t mode)
++static u32 w83795_set_fan_mode(struct device *dev, w83795_fan_mode_t mode)
+ {
+       if (mode == SPEED_CRUISE_MODE) {
+-              w83795_write(W83795_REG_FCMS1, 0xFF);
++              w83795_write(dev, W83795_REG_FCMS1, 0xFF);
+               printk(BIOS_INFO, "W83795G/ADG work in Speed Cruise Mode\n");
+       }  else {
+-              w83795_write(W83795_REG_FCMS1, 0x00);
++              w83795_write(dev, W83795_REG_FCMS1, 0x00);
+               if (mode == THERMAL_CRUISE_MODE) {
+-                      w83795_write(W83795_REG_FCMS2, 0x00);
++                      w83795_write(dev, W83795_REG_FCMS2, 0x00);
+                       printk(BIOS_INFO, "W83795G/ADG work in Thermal Cruise 
Mode\n");
+               } else if (mode == SMART_FAN_MODE) {
+-                      w83795_write(W83795_REG_FCMS2, 0x3F);
++                      w83795_write(dev, W83795_REG_FCMS2, 0x3F);
+                       printk(BIOS_INFO, "W83795G/ADG work in Smart Fan 
Mode\n");
+               } else {
+                       printk(BIOS_INFO, "W83795G/ADG work in Manual Mode\n");
+@@ -131,40 +94,12 @@ static u32 w83795_set_fan_mode(w83795_fan_mode_t mode)
+       return 0;
+ }
+ 
+-static void w83795_set_tss(void)
++static void w83795_set_fan(struct device *dev, w83795_fan_mode_t mode)
+ {
+-      u8 val;
+-
+-      val = 0x00;
+-      w83795_write(W83795_REG_TSS(0), val); /* Temp1, 2 */
+-      w83795_write(W83795_REG_TSS(1), val); /* Temp3, 4 */
+-      w83795_write(W83795_REG_TSS(2), val); /* Temp5, 6 */
+-}
+-
+-static void w83795_set_fan(w83795_fan_mode_t mode)
+-{
+-      u8 i;
+-
+-      /* select temperature sensor (TSS)*/
+-      w83795_set_tss();
+-
+-      /* select Temperature to Fan mapping Relationships (TFMR)*/
+-      w83795_set_tfmr(mode);
+-
+       /* set fan output controlled mode (FCMS)*/
+-      w83795_set_fan_mode(mode);
++      w83795_set_fan_mode(dev, mode);
+ 
+-      /* Set Critical Temperature to Full Speed all fan (CTFS) */
+-      for (i = 0; i < 6; i++) {
+-              w83795_write(W83795_REG_CTFS(i), 0x50); /* default 80 celsius 
degree */
+-      }
+-
+-      if (mode == THERMAL_CRUISE_MODE) {
+-              /* Set Target Temperature of Temperature Inputs (TTTI) */
+-              for (i = 0; i < 6; i++) {
+-                      w83795_write(W83795_REG_TTTI(i), 0x28); /* default 40 
celsius degree */
+-              }
+-      } else if (mode == SMART_FAN_MODE) {
++      if (mode == SMART_FAN_MODE) {
+               /* Set the Relative Register-at SMART FAN IV Control Mode Table 
*/
+               //SFIV TODO
+       }
+@@ -173,16 +108,44 @@ static void w83795_set_fan(w83795_fan_mode_t mode)
+       //TODO
+ }
+ 
+-static void w83795_init(w83795_fan_mode_t mode, u8 dts_src)
++static uint8_t fan_pct_to_cfg_val(uint8_t percent)
+ {
+-      u8 i;
+-      u8 val;
++      uint16_t cfg = (((unsigned int)percent * 10000) / 3922);
++      if (cfg > 0xff)
++              cfg = 0xff;
++      return cfg;
++}
++
++static uint8_t millivolts_to_limit_value_type1(int millivolts)
++{
++      /* Datasheet v1.41 page 44 (VSEN1 - VSEN13, VTT) */
++      return ((millivolts / 2) >> 2);
++}
++
++static uint8_t millivolts_to_limit_value_type2(int millivolts)
++{
++      /* Datasheet v1.41 page 44 (3VSB, 3VDD, VBAT) */
++      return ((millivolts / 6) >> 2);
++}
++
++static uint16_t millivolts_to_limit_value_type3(int millivolts)
++{
++      /* Datasheet v1.41 page 44 (VDSEN14 - VDSEN17) */
++      return (millivolts / 2);
++}
++
++static void w83795_init(struct device *dev, w83795_fan_mode_t mode, u8 
dts_src)
++{
++      struct drivers_i2c_w83795_config *config = dev->chip_info;
++      uint8_t i;
++      uint8_t val;
++      uint16_t limit_value;
+ 
+-      if (do_smbus_read_byte(SMBUS_IO_BASE, W83795_DEV, 0x00) < 0) {
++      if (smbus_read_byte(dev, 0x00) < 0) {
+               printk(BIOS_ERR, "W83795G/ADG Nuvoton H/W Monitor not found\n");
+               return;
+       }
+-      val = w83795_read(W83795_REG_CONFIG);
++      val = w83795_read(dev, W83795_REG_CONFIG);
+       if ((val & W83795_REG_CONFIG_CONFIG48) == 0)
+               printk(BIOS_INFO, "Found 64 pin W83795G Nuvoton H/W Monitor\n");
+       else if ((val & W83795_REG_CONFIG_CONFIG48) == 1)
+@@ -190,35 +153,185 @@ static void w83795_init(w83795_fan_mode_t mode, u8 
dts_src)
+ 
+       /* Reset */
+       val |= W83795_REG_CONFIG_INIT;
+-      w83795_write(W83795_REG_CONFIG, val);
+-
+-      /* Fan monitoring setting */
+-      val = 0xFF; /* FAN1-FAN8 */
+-      w83795_write(W83795_REG_FANIN_CTRL1, val);
+-      val = 0x3F; /* FAN9-FAN14 */
+-      w83795_write(W83795_REG_FANIN_CTRL2, val);
++      w83795_write(dev, W83795_REG_CONFIG, val);
++
++      /* Fan monitor settings */
++      w83795_write(dev, W83795_REG_FANIN_CTRL1, config->fanin_ctl1);
++      w83795_write(dev, W83795_REG_FANIN_CTRL2, config->fanin_ctl2);
++
++      /* Temperature thresholds */
++      w83795_write(dev, W83795_REG_TEMP_CRIT(0), 
config->tr1_critical_temperature);
++      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(0), 
config->tr1_critical_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_WARN(0), 
config->tr1_warning_temperature);
++      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(0), 
config->tr1_warning_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_CRIT(1), 
config->tr2_critical_temperature);
++      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(1), 
config->tr2_critical_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_WARN(1), 
config->tr2_warning_temperature);
++      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(1), 
config->tr2_warning_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_CRIT(2), 
config->tr3_critical_temperature);
++      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(2), 
config->tr3_critical_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_WARN(2), 
config->tr3_warning_temperature);
++      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(2), 
config->tr3_warning_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_CRIT(3), 
config->tr4_critical_temperature);
++      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(3), 
config->tr4_critical_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_WARN(3), 
config->tr4_warning_temperature);
++      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(3), 
config->tr4_warning_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_CRIT(4), 
config->tr5_critical_temperature);
++      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(4), 
config->tr5_critical_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_WARN(4), 
config->tr5_warning_temperature);
++      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(4), 
config->tr5_warning_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_CRIT(5), 
config->tr6_critical_temperature);
++      w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(5), 
config->tr6_critical_hysteresis);
++      w83795_write(dev, W83795_REG_TEMP_WARN(5), 
config->tr6_warning_temperature);
++      w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(5), 
config->tr6_warning_hysteresis);
++
++      /* DTS enable */
++      w83795_write(dev, W83795_REG_DTSE, config->temp_dtse);
++
++      /* DTS temperature thresholds */
++      w83795_write(dev, W83795_REG_DTS_CRIT, 
config->dts_critical_temperature);
++      w83795_write(dev, W83795_REG_DTS_CRIT_HYSTER, 
config->dts_critical_hysteresis);
++      w83795_write(dev, W83795_REG_DTS_WARN, config->dts_warning_temperature);
++      w83795_write(dev, W83795_REG_DTS_WARN_HYSTER, 
config->dts_warning_hysteresis);
++
++      /* Configure DTS registers in bank3 before enabling DTS */
++      w83795_dts_configure(dev, dts_src);
++
++      /* Temperature monitor settings */
++      w83795_write(dev, W83795_REG_TEMP_CTRL1, config->temp_ctl1);
++      w83795_write(dev, W83795_REG_TEMP_CTRL2, config->temp_ctl2);
++
++      /* Temperature to fan mappings */
++      w83795_write(dev, W83795_REG_TFMR(0), config->temp1_fan_select);
++      w83795_write(dev, W83795_REG_TFMR(1), config->temp2_fan_select);
++      w83795_write(dev, W83795_REG_TFMR(2), config->temp3_fan_select);
++      w83795_write(dev, W83795_REG_TFMR(3), config->temp4_fan_select);
++      w83795_write(dev, W83795_REG_TFMR(4), config->temp5_fan_select);
++      w83795_write(dev, W83795_REG_TFMR(5), config->temp6_fan_select);
++
++      /* Temperature data source to temperature mappings */
++      w83795_write(dev, W83795_REG_T12TSS, ((config->temp2_source_select & 
0xff) << 8) | (config->temp1_source_select & 0xff));
++      w83795_write(dev, W83795_REG_T34TSS, ((config->temp4_source_select & 
0xff) << 8) | (config->temp3_source_select & 0xff));
++      w83795_write(dev, W83795_REG_T56TSS, ((config->temp6_source_select & 
0xff) << 8) | (config->temp5_source_select & 0xff));
++
++      /* Set critical temperatures
++       * If any sensor exceeds the associated critical temperature,
++       * all fans will be forced to full speed.
++       */
++      w83795_write(dev, W83795_REG_CTFS(0), 
config->temp1_critical_temperature);
++      w83795_write(dev, W83795_REG_CTFS(1), 
config->temp2_critical_temperature);
++      w83795_write(dev, W83795_REG_CTFS(2), 
config->temp3_critical_temperature);
++      w83795_write(dev, W83795_REG_CTFS(3), 
config->temp4_critical_temperature);
++      w83795_write(dev, W83795_REG_CTFS(4), 
config->temp5_critical_temperature);
++      w83795_write(dev, W83795_REG_CTFS(5), 
config->temp6_critical_temperature);
++
++      /* Set fan control target temperatures */
++      w83795_write(dev, W83795_REG_TTTI(0), config->temp1_target_temperature);
++      w83795_write(dev, W83795_REG_TTTI(1), config->temp2_target_temperature);
++      w83795_write(dev, W83795_REG_TTTI(2), config->temp3_target_temperature);
++      w83795_write(dev, W83795_REG_TTTI(3), config->temp4_target_temperature);
++      w83795_write(dev, W83795_REG_TTTI(4), config->temp5_target_temperature);
++      w83795_write(dev, W83795_REG_TTTI(5), config->temp6_target_temperature);
++
++      /* Set fan stall prevention parameters */
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(0), config->fan1_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(1), config->fan2_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(2), config->fan3_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(3), config->fan4_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(4), config->fan5_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(5), config->fan6_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(6), config->fan7_nonstop);
++      w83795_write(dev, W83795_REG_FAN_NONSTOP(7), config->fan8_nonstop);
++
++      /* Set fan default speed */
++      w83795_write(dev, W83795_REG_DFSP, 
fan_pct_to_cfg_val(config->default_speed));
++
++      /* Set initial fan speeds */
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(0), 
fan_pct_to_cfg_val(config->fan1_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(1), 
fan_pct_to_cfg_val(config->fan2_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(2), 
fan_pct_to_cfg_val(config->fan3_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(3), 
fan_pct_to_cfg_val(config->fan4_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(4), 
fan_pct_to_cfg_val(config->fan5_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(5), 
fan_pct_to_cfg_val(config->fan6_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(6), 
fan_pct_to_cfg_val(config->fan7_duty));
++      w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(7), 
fan_pct_to_cfg_val(config->fan8_duty));
++
++      /* Voltage monitor settings */
++      w83795_write(dev, W83795_REG_VOLT_CTRL1, config->volt_ctl1);
++      w83795_write(dev, W83795_REG_VOLT_CTRL2, config->volt_ctl2);
++
++      /* Voltage high/low limits */
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(0), 
millivolts_to_limit_value_type1(config->vcore1_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(0), 
millivolts_to_limit_value_type1(config->vcore1_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(1), 
millivolts_to_limit_value_type1(config->vcore2_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(1), 
millivolts_to_limit_value_type1(config->vcore2_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(2), 
millivolts_to_limit_value_type1(config->vsen3_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(2), 
millivolts_to_limit_value_type1(config->vsen3_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(3), 
millivolts_to_limit_value_type1(config->vsen4_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(3), 
millivolts_to_limit_value_type1(config->vsen4_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(4), 
millivolts_to_limit_value_type1(config->vsen5_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(4), 
millivolts_to_limit_value_type1(config->vsen5_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(5), 
millivolts_to_limit_value_type1(config->vsen6_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(5), 
millivolts_to_limit_value_type1(config->vsen6_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(6), 
millivolts_to_limit_value_type1(config->vsen7_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(6), 
millivolts_to_limit_value_type1(config->vsen7_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(7), 
millivolts_to_limit_value_type1(config->vsen8_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(7), 
millivolts_to_limit_value_type1(config->vsen8_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(8), 
millivolts_to_limit_value_type1(config->vsen9_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(8), 
millivolts_to_limit_value_type1(config->vsen9_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(9), 
millivolts_to_limit_value_type1(config->vsen10_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(9), 
millivolts_to_limit_value_type1(config->vsen10_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(10), 
millivolts_to_limit_value_type1(config->vsen11_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(10), 
millivolts_to_limit_value_type1(config->vsen11_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(11), 
millivolts_to_limit_value_type1(config->vtt_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(11), 
millivolts_to_limit_value_type1(config->vtt_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(12), 
millivolts_to_limit_value_type2(config->vdd_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(12), 
millivolts_to_limit_value_type2(config->vdd_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(13), 
millivolts_to_limit_value_type2(config->vsb_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(13), 
millivolts_to_limit_value_type2(config->vsb_low_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(14), 
millivolts_to_limit_value_type2(config->vbat_high_limit_mv));
++      w83795_write(dev, W83795_REG_VOLT_LIM_LOW(14), 
millivolts_to_limit_value_type2(config->vbat_low_limit_mv));
++
++      /* VSEN12 limits */
++      if (config->temp_ctl1 & 0x2) {
++              limit_value = 
millivolts_to_limit_value_type3(config->vsen12_high_limit_mv);
++              w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_M(4), limit_value 
>> 2);
++              w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_L(4), limit_value 
& 0x3);
++              limit_value = 
millivolts_to_limit_value_type3(config->vsen12_low_limit_mv);
++              w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_M(4), limit_value 
>> 2);
++              w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_L(4), limit_value & 
0x3);
++      }
+ 
+-      /* enable monitoring operations */
+-      val = w83795_read(W83795_REG_CONFIG);
+-      val |= W83795_REG_CONFIG_START;
+-      w83795_write(W83795_REG_CONFIG, val);
++      /* VSEN13 limits */
++      if (config->temp_ctl1 & 0x8) {
++              limit_value = 
millivolts_to_limit_value_type3(config->vsen13_high_limit_mv);
++              w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_M(5), limit_value 
>> 2);
++              w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_L(5), limit_value 
& 0x3);
++              limit_value = 
millivolts_to_limit_value_type3(config->vsen13_low_limit_mv);
++              w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_M(5), limit_value 
>> 2);
++              w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_L(5), limit_value & 
0x3);
++      }
+ 
+-      w83795_dts_enable(dts_src);
+-      w83795_set_fan(mode);
++      w83795_set_fan(dev, mode);
+ 
+       printk(BIOS_INFO, "Fan   CTFS(celsius)  TTTI(celsius)\n");
+       for (i = 0; i < 6; i++) {
+-              val = w83795_read(W83795_REG_CTFS(i));
++              val = w83795_read(dev, W83795_REG_CTFS(i));
+               printk(BIOS_INFO, " %x     %d", i, val);
+-              val = w83795_read(W83795_REG_TTTI(i));
++              val = w83795_read(dev, W83795_REG_TTTI(i));
+               printk(BIOS_INFO, "             %d\n", val);
+       }
+ 
+       /* Temperature ReadOut */
+       for (i = 0; i < 9; i++) {
+-              val = w83795_read(W83795_REG_DTS(i));
++              val = w83795_read(dev, W83795_REG_DTS(i));
+               printk(BIOS_DEBUG, "DTS%x ReadOut=%x\n", i, val);
+       }
++
++      /* start monitoring operation */
++      val = w83795_read(dev, W83795_REG_CONFIG);
++      val |= W83795_REG_CONFIG_START;
++      w83795_write(dev, W83795_REG_CONFIG, val);
+ }
+ 
+ static void w83795_hwm_init(struct device *dev)
+@@ -232,9 +345,9 @@ static void w83795_hwm_init(struct device *dev)
+               die("CPU: missing cpu device structure");
+ 
+       if (cpu->vendor == X86_VENDOR_AMD)
+-              w83795_init(THERMAL_CRUISE_MODE, DTS_SRC_AMD_SBTSI);
++              w83795_init(dev, THERMAL_CRUISE_MODE, DTS_SRC_AMD_SBTSI);
+       else if (cpu->vendor == X86_VENDOR_INTEL)
+-              w83795_init(THERMAL_CRUISE_MODE, DTS_SRC_INTEL_PECI);
++              w83795_init(dev, THERMAL_CRUISE_MODE, DTS_SRC_INTEL_PECI);
+       else
+               printk(BIOS_ERR, "Neither AMD nor INTEL CPU detected\n");
+ }
+diff --git a/src/drivers/i2c/w83795/w83795.h b/src/drivers/i2c/w83795/w83795.h
+index cac4d5f..ef603f5 100644
+--- a/src/drivers/i2c/w83795/w83795.h
++++ b/src/drivers/i2c/w83795/w83795.h
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2012 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Raptor Engineering
+  *
+  * 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
+@@ -20,8 +21,6 @@
+ #ifndef _W83795_H_
+ #define _W83795_H_
+ 
+-#define W83795_DEV                    0x2F /* Host I2c Addr (strap to addr1 
addr0 1 1, 0x5E) */
+-
+ #define W83795_REG_I2C_ADDR           0xFC
+ #define W83795_REG_BANKSEL            0x00
+ #define W83795_REG_CONFIG             0x01
+@@ -29,6 +28,8 @@
+ #define W83795_REG_CONFIG_CONFIG48    0x04
+ #define W83795_REG_CONFIG_INIT                0x80
+ 
++#define W83795_REG_VOLT_CTRL1         0x02
++#define W83795_REG_VOLT_CTRL2         0x03
+ #define W83795_REG_TEMP_CTRL1         0x04 /* Temperature Monitoring Control 
Register */
+ #define W83795_REG_TEMP_CTRL2         0x05 /* Temperature Monitoring Control 
Register */
+ #define W83795_REG_FANIN_CTRL1                0x06
+@@ -37,37 +38,58 @@
+ #define DTS_SRC_INTEL_PECI            (0 << 0)
+ #define DTS_SRC_AMD_SBTSI             (1 << 0)
+ 
+-#define W83795_REG_TSS(n)             (0x209 + (n)) /* Temperature Source 
Selection Register */
+ #define W83795_REG_TTTI(n)            (0x260 + (n)) /* Target temperature 
W83795G/ADG will try to tune the fan output to keep */
+ #define W83795_REG_CTFS(n)            (0x268 + (n)) /* Critical Temperature 
to Full Speed all fan */
+-#define W83795_REG_HT(n)              (0x270 + (n)) /* Hysteresis of 
Temperature */
+ #define W83795_REG_DTSC                       0x301 /* Digital Temperature 
Sensor Configuration */
+ 
+ #define W83795_REG_DTSE                       0x302 /* Digital Temperature 
Sensor Enable */
+ #define W83795_REG_DTS(n)             (0x26 + (n))
+ #define W83795_REG_VRLSB              0x3C
+ 
+-#define W83795_TEMP_REG_TR1           0x21
+-#define W83795_TEMP_REG_TR2           0x22
+-#define W83795_TEMP_REG_TR3           0x23
+-#define W83795_TEMP_REG_TR4           0x24
+-#define W83795_TEMP_REG_TR5           0x1F
+-#define W83795_TEMP_REG_TR6           0x20
++#define W83795_REG_TEMP_TR1           0x21
++#define W83795_REG_TEMP_TR2           0x22
++#define W83795_REG_TEMP_TR3           0x23
++#define W83795_REG_TEMP_TR4           0x24
++#define W83795_REG_TEMP_TR5           0x1F
++#define W83795_REG_TEMP_TR6           0x20
++
++#define W83795_REG_VOLT_LIM_HIGH(n)   (0x70 + (n * 2))        /* Voltage high 
limit (0 == VSEN1) */
++#define W83795_REG_VOLT_LIM_LOW(n)    (0x71 + (n * 2))        /* Voltage low 
limit (0 == VSEN1) */
++#define W83795_REG_VOLT_LIM_HIGH_2_M(n)       (0x96 + (n * 4))        /* 
Voltage high limit MSB (0 == VDSEN14) */
++#define W83795_REG_VOLT_LIM_LOW_2_M(n)        (0x97 + (n * 4))        /* 
Voltage low limit MSB (0 == VDSEN14)  */
++#define W83795_REG_VOLT_LIM_HIGH_2_L(n)       (0x98 + (n * 4))        /* 
Voltage high limit LSB (0 == VDSEN14) */
++#define W83795_REG_VOLT_LIM_LOW_2_L(n)        (0x99 + (n * 4))        /* 
Voltage low limit LSB (0 == VDSEN14)  */
++
++#define W83795_REG_TEMP_CRIT(n)               (0x96 + (n * 4))        /* 
Temperature critical limit */
++#define W83795_REG_TEMP_CRIT_HYSTER(n)        (0x97 + (n * 4))        /* 
Temperature critical limit hysteresis */
++#define W83795_REG_TEMP_WARN(n)               (0x98 + (n * 4))        /* 
Temperature warning limit */
++#define W83795_REG_TEMP_WARN_HYSTER(n)        (0x99 + (n * 4))        /* 
Temperature warning limit hysteresis */
++
++#define W83795_REG_DTS_CRIT           0xB2                    /* Temperature 
critical limit */
++#define W83795_REG_DTS_CRIT_HYSTER    0xB3                    /* Temperature 
critical limit hysteresis */
++#define W83795_REG_DTS_WARN           0xB4                    /* Temperature 
warning limit */
++#define W83795_REG_DTS_WARN_HYSTER    0xB5                    /* Temperature 
warning limit hysteresis */
+ 
+ #define W83795_REG_FCMS1              0x201
+ #define W83795_REG_FCMS2              0x208
+-#define W83795_REG_TFMR(n)            (0x202 + (n)) /*temperature to fam 
mappig*/
++#define W83795_REG_TFMR(n)            (0x202 + (n))           /* Temperature 
to fan mapping */
++#define W83795_REG_T12TSS             0x209                   /* Temperature 
Source Selection Register 1 */
++#define W83795_REG_T34TSS             0x20A                   /* Temperature 
Source Selection Register 2 */
++#define W83795_REG_T56TSS             0x20B                   /* Temperature 
Source Selection Register 3 */
++#define W83795_REG_FAN_MANUAL_SPEED(n)        (0x210 + n)
+ #define W83795_REG_DFSP                       0x20C
+ 
++#define W83795_REG_FAN_NONSTOP(n)     (0x228 + (n))   /* Fan Nonstop Value */
++
+ #define W83795_REG_FTSH(n)            (0x240 + (n) * 2)
+ #define W83795_REG_FTSL(n)            (0x241 + (n) * 2)
+ #define W83795_REG_TFTS                       0x250
+ 
+ typedef enum w83795_fan_mode {
+-      SPEED_CRUISE_MODE,      ///< Fan Speed Cruise mode keeps the fan speed 
in a specified range
+-      THERMAL_CRUISE_MODE,    ///< Thermal Cruise mode is an algorithm to 
control the fan speed to keep the temperature source around the TTTI
+-      SMART_FAN_MODE,         ///< Smart Fan mode offers 6 slopes to control 
the fan speed
+-      MANUAL_MODE,            ///< control manually
++      SPEED_CRUISE_MODE = 0,          ///< Fan Speed Cruise mode keeps the 
fan speed in a specified range
++      THERMAL_CRUISE_MODE = 1,        ///< Thermal Cruise mode is an 
algorithm to control the fan speed to keep the temperature source around the 
TTTI
++      SMART_FAN_MODE = 2,             ///< Smart Fan mode offers 6 slopes to 
control the fan speed
++      MANUAL_MODE = 3,                ///< control manually
+ } w83795_fan_mode_t;
+ 
+ #endif
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
 
b/resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
deleted file mode 100644
index b984f28..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0003-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 3e2be2d88101331eedb59c1459630b553c7cb660 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 17 Oct 2015 04:37:10 -0500
-Subject: [PATCH 003/139] drivers/i2c/w83795: Add option to use auxiliary SMBUS
- controller
-
-Change-Id: I5a9b5eba992853b84b0cb6c3a1764edf42ac49b2
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/drivers/i2c/w83795/chip.h   |  4 ++++
- src/drivers/i2c/w83795/w83795.c | 14 ++++++++++++++
- 2 files changed, 18 insertions(+)
-
-diff --git a/src/drivers/i2c/w83795/chip.h b/src/drivers/i2c/w83795/chip.h
-index effe119..413ea87 100644
---- a/src/drivers/i2c/w83795/chip.h
-+++ b/src/drivers/i2c/w83795/chip.h
-@@ -139,4 +139,8 @@ struct drivers_i2c_w83795_config {
-       uint8_t fan6_duty;                      /* % of full speed (0-100) */
-       uint8_t fan7_duty;                      /* % of full speed (0-100) */
-       uint8_t fan8_duty;                      /* % of full speed (0-100) */
-+
-+      uint8_t smbus_aux;                      /* 0 == device located on first 
SMBUS,
-+                                               * 1 == device located on 
auxiliary SMBUS
-+                                               */
- };
-diff --git a/src/drivers/i2c/w83795/w83795.c b/src/drivers/i2c/w83795/w83795.c
-index cf0cf2f..453e0af 100644
---- a/src/drivers/i2c/w83795/w83795.c
-+++ b/src/drivers/i2c/w83795/w83795.c
-@@ -141,7 +141,16 @@ static void w83795_init(struct device *dev, 
w83795_fan_mode_t mode, u8 dts_src)
-       uint8_t val;
-       uint16_t limit_value;
- 
-+#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX)
-+      uint8_t smbus_aux_prev = smbus_switched_to_aux();
-+      smbus_switch_to_aux(config->smbus_aux);
-+#endif
-+
-       if (smbus_read_byte(dev, 0x00) < 0) {
-+#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX)
-+              /* Restore SMBUS channel setting */
-+              smbus_switch_to_aux(smbus_aux_prev);
-+#endif
-               printk(BIOS_ERR, "W83795G/ADG Nuvoton H/W Monitor not found\n");
-               return;
-       }
-@@ -325,6 +334,11 @@ static void w83795_init(struct device *dev, 
w83795_fan_mode_t mode, u8 dts_src)
-       val = w83795_read(dev, W83795_REG_CONFIG);
-       val |= W83795_REG_CONFIG_START;
-       w83795_write(dev, W83795_REG_CONFIG, val);
-+
-+#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX)
-+      /* Restore SMBUS channel setting */
-+      smbus_switch_to_aux(smbus_aux_prev);
-+#endif
- }
- 
- static void w83795_hwm_init(struct device *dev)
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0004-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
 
b/resources/libreboot/patch/kgpe-d16/0004-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
deleted file mode 100644
index 3d9c5c8..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0004-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
+++ /dev/null
@@ -1,3675 +0,0 @@
-From 7075bbddd264958b80ea4831b602b6fbfaf60b0d Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 17:38:09 -0500
-Subject: [PATCH 004/139] drivers/aspeed: Add native text mode VGA support for
- the AST2050
-
-Change-Id: I37763a59d2546cd0c0e57b31fdb7aa77c2c50bee
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/drivers/aspeed/Kconfig                  |    2 +
- src/drivers/aspeed/Makefile.inc             |    1 +
- src/drivers/aspeed/ast2050/Kconfig          |   14 +
- src/drivers/aspeed/ast2050/Makefile.inc     |    1 +
- src/drivers/aspeed/ast2050/ast2050.c        |   83 ++
- src/drivers/aspeed/common/Kconfig           |   10 +
- src/drivers/aspeed/common/Makefile.inc      |    1 +
- src/drivers/aspeed/common/aspeed_coreboot.h |  210 ++++
- src/drivers/aspeed/common/ast_dp501.c       |  443 +++++++
- src/drivers/aspeed/common/ast_dram_tables.h |  165 +++
- src/drivers/aspeed/common/ast_drv.h         |  223 ++++
- src/drivers/aspeed/common/ast_main.c        |  393 +++++++
- src/drivers/aspeed/common/ast_post.c        | 1679 +++++++++++++++++++++++++++
- src/drivers/aspeed/common/ast_tables.h      |  305 +++++
- src/include/device/pci_ids.h                |    3 +
- 15 files changed, 3533 insertions(+)
- create mode 100644 src/drivers/aspeed/Kconfig
- create mode 100644 src/drivers/aspeed/Makefile.inc
- create mode 100644 src/drivers/aspeed/ast2050/Kconfig
- create mode 100644 src/drivers/aspeed/ast2050/Makefile.inc
- create mode 100644 src/drivers/aspeed/ast2050/ast2050.c
- create mode 100644 src/drivers/aspeed/common/Kconfig
- create mode 100644 src/drivers/aspeed/common/Makefile.inc
- create mode 100644 src/drivers/aspeed/common/aspeed_coreboot.h
- create mode 100644 src/drivers/aspeed/common/ast_dp501.c
- create mode 100644 src/drivers/aspeed/common/ast_dram_tables.h
- create mode 100644 src/drivers/aspeed/common/ast_drv.h
- create mode 100644 src/drivers/aspeed/common/ast_main.c
- create mode 100644 src/drivers/aspeed/common/ast_post.c
- create mode 100644 src/drivers/aspeed/common/ast_tables.h
-
-diff --git a/src/drivers/aspeed/Kconfig b/src/drivers/aspeed/Kconfig
-new file mode 100644
-index 0000000..27469b5
---- /dev/null
-+++ b/src/drivers/aspeed/Kconfig
-@@ -0,0 +1,2 @@
-+source src/drivers/aspeed/common/Kconfig
-+source src/drivers/aspeed/ast2050/Kconfig
-\ No newline at end of file
-diff --git a/src/drivers/aspeed/Makefile.inc b/src/drivers/aspeed/Makefile.inc
-new file mode 100644
-index 0000000..955a213
---- /dev/null
-+++ b/src/drivers/aspeed/Makefile.inc
-@@ -0,0 +1 @@
-+subdirs-y += common ast2050
-\ No newline at end of file
-diff --git a/src/drivers/aspeed/ast2050/Kconfig 
b/src/drivers/aspeed/ast2050/Kconfig
-new file mode 100644
-index 0000000..f110d58
---- /dev/null
-+++ b/src/drivers/aspeed/ast2050/Kconfig
-@@ -0,0 +1,14 @@
-+config DRIVERS_ASPEED_AST2050
-+      bool
-+
-+if DRIVERS_ASPEED_AST2050
-+
-+config DEVICE_SPECIFIC_OPTIONS # dummy
-+      def_bool y
-+      select DRIVERS_ASPEED_AST_COMMON
-+
-+config NATIVE_VGA_INIT_USE_EDID
-+      bool
-+      default n
-+
-+endif # DRIVERS_ASPEED_AST2050
-diff --git a/src/drivers/aspeed/ast2050/Makefile.inc 
b/src/drivers/aspeed/ast2050/Makefile.inc
-new file mode 100644
-index 0000000..3ba9dde
---- /dev/null
-+++ b/src/drivers/aspeed/ast2050/Makefile.inc
-@@ -0,0 +1 @@
-+ramstage-$(CONFIG_DRIVERS_ASPEED_AST2050) += ast2050.c
-\ No newline at end of file
-diff --git a/src/drivers/aspeed/ast2050/ast2050.c 
b/src/drivers/aspeed/ast2050/ast2050.c
-new file mode 100644
-index 0000000..809e9de
---- /dev/null
-+++ b/src/drivers/aspeed/ast2050/ast2050.c
-@@ -0,0 +1,83 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * 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
-+ */
-+#include <delay.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <arch/io.h>
-+#include <edid.h>
-+
-+#include <console/console.h>
-+#include <device/device.h>
-+#include <device/pci.h>
-+#include <device/pci_ids.h>
-+#include <device/pci_ops.h>
-+
-+#include <pc80/vga.h>
-+
-+#include "../common/aspeed_coreboot.h"
-+#include "../common/ast_drv.h"
-+
-+static void aspeed_ast2050_set_resources(device_t dev)
-+{
-+      /* Reserve VGA regions */
-+      mmio_resource(dev, 3, 0xa0000 >> 10, 0x1ffff >> 10);
-+
-+      /* Run standard resource set routine */
-+      pci_dev_set_resources(dev);
-+}
-+
-+static void aspeed_ast2050_init(struct device *dev)
-+{
-+      u8 ret;
-+      struct drm_device drm_dev;
-+
-+      drm_dev.pdev = dev;
-+
-+      printk(BIOS_INFO, "ASpeed AST2050: initializing video device\n");
-+      ret = ast_driver_load(&drm_dev, 0);
-+
-+      /* Unlock extended configuration registers */
-+      outb(0x80, 0x3d4); outb(0xa8, 0x3d5);
-+
-+      /* Set CRT Request Threshold */
-+      outb(0xa6, 0x3d4); outb(0x2f, 0x3d5);
-+      outb(0xa7, 0x3d4); outb(0x3f, 0x3d5);
-+
-+      /* Initialize standard VGA text mode */
-+      vga_io_init();
-+      vga_textmode_init();
-+      printk(BIOS_INFO, "ASpeed VGA text mode initialized\n");
-+
-+      /* if we don't have console, at least print something... */
-+      vga_line_write(0, "ASpeed VGA text mode initialized");
-+}
-+
-+static struct device_operations aspeed_ast2050_ops  = {
-+      .read_resources   = pci_dev_read_resources,
-+      .set_resources    = aspeed_ast2050_set_resources,
-+      .enable_resources = pci_dev_enable_resources,
-+      .init             = aspeed_ast2050_init,
-+      .scan_bus         = 0,
-+};
-+
-+static const struct pci_driver aspeed_ast2050_driver __pci_driver = {
-+        .ops    = &aspeed_ast2050_ops,
-+        .vendor = PCI_VENDOR_ID_ASPEED,
-+        .device = PCI_DEVICE_ID_ASPEED_AST2050_VGA,
-+};
-diff --git a/src/drivers/aspeed/common/Kconfig 
b/src/drivers/aspeed/common/Kconfig
-new file mode 100644
-index 0000000..0f7056b
---- /dev/null
-+++ b/src/drivers/aspeed/common/Kconfig
-@@ -0,0 +1,10 @@
-+config DRIVERS_ASPEED_AST_COMMON
-+      bool
-+
-+if !MAINBOARD_DO_NATIVE_VGA_INIT
-+
-+config DEVICE_SPECIFIC_OPTIONS # dummy
-+      def_bool y
-+      select VGA
-+
-+endif # MAINBOARD_DO_NATIVE_VGA_INIT
-diff --git a/src/drivers/aspeed/common/Makefile.inc 
b/src/drivers/aspeed/common/Makefile.inc
-new file mode 100644
-index 0000000..75f8b48
---- /dev/null
-+++ b/src/drivers/aspeed/common/Makefile.inc
-@@ -0,0 +1 @@
-+ramstage-$(CONFIG_DRIVERS_ASPEED_AST_COMMON) += ast_dp501.c ast_main.c 
ast_post.c
-diff --git a/src/drivers/aspeed/common/aspeed_coreboot.h 
b/src/drivers/aspeed/common/aspeed_coreboot.h
-new file mode 100644
-index 0000000..237c23f
---- /dev/null
-+++ b/src/drivers/aspeed/common/aspeed_coreboot.h
-@@ -0,0 +1,210 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * 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, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#ifndef _ASPEED_COREBOOT_
-+#define _ASPEED_COREBOOT_
-+
-+#include <delay.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <string.h>
-+#include <arch/io.h>
-+
-+#include <console/console.h>
-+#include <device/device.h>
-+#include <device/pci.h>
-+#include <device/pci_ids.h>
-+#include <device/pci_ops.h>
-+
-+/* coreboot <--> kernel code interface */
-+#define __iomem
-+typedef u64 phys_addr_t;
-+#define pci_dev device
-+
-+#define SZ_16M 0x01000000
-+
-+#define min_t(type, x, y) ({                  \
-+      type __min1 = (x);                      \
-+      type __min2 = (y);                      \
-+      __min1 < __min2 ? __min1 : __min2; })
-+
-+#define dev_info(dev, format, arg...) printk(BIOS_INFO, "ASpeed VGA: " 
format, ##arg)
-+#define dev_dbg(dev, format, arg...) printk(BIOS_DEBUG, "ASpeed VGA: " 
format, ##arg)
-+#define dev_err(dev, format, arg...) printk(BIOS_ERR, "ASpeed VGA: " format, 
##arg)
-+
-+#define pr_info(format, arg...) printk(BIOS_INFO, "ASpeed VGA: " format, 
##arg)
-+#define pr_debug(format, arg...) printk(BIOS_INFO, "ASpeed VGA: " format, 
##arg)
-+#define pr_err(format, arg...) printk(BIOS_ERR, "ASpeed VGA: " format, ##arg)
-+
-+#define DRM_INFO pr_info
-+
-+#define GFP_KERNEL 0
-+#define GFP_ATOMIC 1
-+#define kfree(address) free(address)
-+
-+#define EIO 5
-+#define ENOMEM 12
-+
-+struct firmware {
-+      size_t size;
-+      const u8 *data;
-+      struct page **pages;
-+
-+      /* firmware loader private fields */
-+      void *priv;
-+};
-+
-+struct drm_device {
-+      struct pci_dev *pdev;
-+      void *dev_private;
-+};
-+
-+static inline void *kzalloc(size_t size, int flags) {
-+      void* ptr = malloc(size);
-+      memset(ptr, 0, size);
-+      return ptr;
-+}
-+
-+static inline void writel(u32 val, volatile void *addr) {
-+      *(u32*)addr = val;
-+}
-+
-+static inline u32 readl(const volatile void *addr) {
-+      return *(u32*)addr;
-+}
-+
-+static inline void writew(u16 val, volatile void *addr) {
-+      *(u16*)addr = val;
-+}
-+
-+static inline u16 readw(const volatile void *addr) {
-+      return *(u16*)addr;
-+}
-+
-+static inline void writeb(u8 val, volatile void *addr) {
-+      *(u8*)addr = val;
-+}
-+
-+static inline u8 readb(const volatile void *addr) {
-+      return *(u8*)addr;
-+}
-+
-+static inline int pci_read_config_dword(struct pci_dev *dev, int where,
-+      u32 *val)
-+{
-+      *val = pci_read_config32(dev, where);
-+      return 0;
-+}
-+
-+static inline int pci_write_config_dword(struct pci_dev *dev, int where,
-+      u32 val)
-+{
-+      pci_write_config32(dev, where, val);
-+      return 0;
-+}
-+
-+static inline int pci_read_config_byte(struct pci_dev *dev, int where,
-+      u8 *val)
-+{
-+      *val = pci_read_config8(dev, where);
-+      return 0;
-+}
-+
-+static inline struct resource* resource_at_bar(struct pci_dev *dev, u8 bar) {
-+      struct resource *res = dev->resource_list;
-+      int i;
-+      for (i = 0; i < bar; i++) {
-+              res = res->next;
-+              if (res == NULL)
-+                      return NULL;
-+      }
-+
-+      return res;
-+}
-+
-+static inline resource_t pci_resource_len(struct pci_dev *dev, u8 bar) {
-+      struct resource *res = resource_at_bar(dev, bar);
-+      if (res)
-+              return res->size;
-+      else
-+              return 0;
-+}
-+
-+static inline resource_t pci_resource_start(struct pci_dev *dev, u8 bar) {
-+      struct resource *res = resource_at_bar(dev, bar);
-+      if (res)
-+              return res->base;
-+      else
-+              return 0;
-+}
-+
-+static inline unsigned int ioread32(void __iomem *p) {
-+      return readl(p);
-+}
-+
-+static inline void iowrite32(u32 val, void __iomem *p) {
-+      writel(val, p);
-+}
-+
-+static inline unsigned int ioread16(void __iomem *p) {
-+      return readw(p);
-+}
-+
-+static inline void iowrite16(u16 val, void __iomem *p) {
-+      writew(val, p);
-+}
-+
-+static inline unsigned int ioread8(void __iomem *p) {
-+      return readb(p);
-+}
-+
-+static inline void iowrite8(u8 val, void __iomem *p) {
-+      writeb(val, p);
-+}
-+
-+static inline unsigned int ioread_cbio32(void __iomem *p) {
-+      return inl((uint16_t)((intptr_t)p));
-+}
-+
-+static inline void iowrite_cbio32(u32 val, void __iomem *p) {
-+      outl(val, (uint16_t)((intptr_t)p));
-+}
-+
-+static inline unsigned int ioread_cbio16(void __iomem *p) {
-+      return inw((uint16_t)((intptr_t)p));
-+}
-+
-+static inline void iowrite_cbio16(u16 val, void __iomem *p) {
-+      outw(val, (uint16_t)((intptr_t)p));
-+}
-+
-+static inline unsigned int ioread_cbio8(void __iomem *p) {
-+      return inb((uint16_t)((intptr_t)p));
-+}
-+
-+static inline void iowrite_cbio8(u8 val, void __iomem *p) {
-+      outb(val, (uint16_t)((intptr_t)p));
-+}
-+
-+static inline void msleep(unsigned int msecs) {
-+      udelay(msecs * 1000);
-+}
-+
-+#endif
-\ No newline at end of file
-diff --git a/src/drivers/aspeed/common/ast_dp501.c 
b/src/drivers/aspeed/common/ast_dp501.c
-new file mode 100644
-index 0000000..5be8ec3
---- /dev/null
-+++ b/src/drivers/aspeed/common/ast_dp501.c
-@@ -0,0 +1,443 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * File taken from the Linux ast driver (v3.18.5)
-+ * Coreboot-specific includes added at top and/or contents modified
-+ * as needed to function within the coreboot environment.
-+ *
-+ * 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.
-+ */
-+
-+#include "ast_drv.h"
-+
-+static void send_ack(struct ast_private *ast)
-+{
-+      u8 sendack;
-+      sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
-+      sendack |= 0x80;
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
-+}
-+
-+static void send_nack(struct ast_private *ast)
-+{
-+      u8 sendack;
-+      sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
-+      sendack &= ~0x80;
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
-+}
-+
-+static bool wait_ack(struct ast_private *ast)
-+{
-+      u8 waitack;
-+      u32 retry = 0;
-+      do {
-+              waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 
0xff);
-+              waitack &= 0x80;
-+              udelay(100);
-+      } while ((!waitack) && (retry++ < 1000));
-+
-+      if (retry < 1000)
-+              return true;
-+      else
-+              return false;
-+}
-+
-+static bool wait_nack(struct ast_private *ast)
-+{
-+      u8 waitack;
-+      u32 retry = 0;
-+      do {
-+              waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 
0xff);
-+              waitack &= 0x80;
-+              udelay(100);
-+      } while ((waitack) && (retry++ < 1000));
-+
-+      if (retry < 1000)
-+              return true;
-+      else
-+              return false;
-+}
-+
-+static void set_cmd_trigger(struct ast_private *ast)
-+{
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40);
-+}
-+
-+static void clear_cmd_trigger(struct ast_private *ast)
-+{
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00);
-+}
-+
-+#if 0
-+static bool wait_fw_ready(struct ast_private *ast)
-+{
-+      u8 waitready;
-+      u32 retry = 0;
-+      do {
-+              waitready = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 
0xff);
-+              waitready &= 0x40;
-+              udelay(100);
-+      } while ((!waitready) && (retry++ < 1000));
-+
-+      if (retry < 1000)
-+              return true;
-+      else
-+              return false;
-+}
-+#endif
-+
-+static bool ast_write_cmd(struct drm_device *dev, u8 data)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      int retry = 0;
-+      if (wait_nack(ast)) {
-+              send_nack(ast);
-+              ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
-+              send_ack(ast);
-+              set_cmd_trigger(ast);
-+              do {
-+                      if (wait_ack(ast)) {
-+                              clear_cmd_trigger(ast);
-+                              send_nack(ast);
-+                              return true;
-+                      }
-+              } while (retry++ < 100);
-+      }
-+      clear_cmd_trigger(ast);
-+      send_nack(ast);
-+      return false;
-+}
-+
-+static bool ast_write_data(struct drm_device *dev, u8 data)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+
-+      if (wait_nack(ast)) {
-+              send_nack(ast);
-+              ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
-+              send_ack(ast);
-+              if (wait_ack(ast)) {
-+                      send_nack(ast);
-+                      return true;
-+              }
-+      }
-+      send_nack(ast);
-+      return false;
-+}
-+
-+#if 0
-+static bool ast_read_data(struct drm_device *dev, u8 *data)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 tmp;
-+
-+      *data = 0;
-+
-+      if (wait_ack(ast) == false)
-+              return false;
-+      tmp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd3, 0xff);
-+      *data = tmp;
-+      if (wait_nack(ast) == false) {
-+              send_nack(ast);
-+              return false;
-+      }
-+      send_nack(ast);
-+      return true;
-+}
-+
-+static void clear_cmd(struct ast_private *ast)
-+{
-+      send_nack(ast);
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00);
-+}
-+#endif
-+
-+void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
-+{
-+      ast_write_cmd(dev, 0x40);
-+      ast_write_data(dev, mode);
-+
-+      msleep(10);
-+}
-+
-+static u32 get_fw_base(struct ast_private *ast)
-+{
-+      return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
-+}
-+
-+bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u32 i, data;
-+      u32 boot_address;
-+
-+      data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
-+      if (data) {
-+              boot_address = get_fw_base(ast);
-+              for (i = 0; i < size; i += 4)
-+                      *(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);
-+              return true;
-+      }
-+      return false;
-+}
-+
-+bool ast_launch_m68k(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u32 i, data, len = 0;
-+      u32 boot_address;
-+      u8 *fw_addr = NULL;
-+      u8 jreg;
-+
-+      data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
-+      if (!data) {
-+
-+              if (ast->dp501_fw_addr) {
-+                      fw_addr = ast->dp501_fw_addr;
-+                      len = 32*1024;
-+              } else if (ast->dp501_fw) {
-+                      fw_addr = (u8 *)ast->dp501_fw->data;
-+                      len = ast->dp501_fw->size;
-+              }
-+              /* Get BootAddress */
-+              ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
-+              data = ast_mindwm(ast, 0x1e6e0004);
-+              switch (data & 0x03) {
-+              case 0:
-+                      boot_address = 0x44000000;
-+                      break;
-+              default:
-+              case 1:
-+                      boot_address = 0x48000000;
-+                      break;
-+              case 2:
-+                      boot_address = 0x50000000;
-+                      break;
-+              case 3:
-+                      boot_address = 0x60000000;
-+                      break;
-+              }
-+              boot_address -= 0x200000; /* -2MB */
-+
-+              /* copy image to buffer */
-+              for (i = 0; i < len; i += 4) {
-+                      data = *(u32 *)(fw_addr + i);
-+                      ast_moutdwm(ast, boot_address + i, data);
-+              }
-+
-+              /* Init SCU */
-+              ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
-+
-+              /* Launch FW */
-+              ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
-+              ast_moutdwm(ast, 0x1e6e2100, 1);
-+
-+              /* Update Scratch */
-+              data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff;                
/* D[11:9] = 100b: UEFI handling */
-+              data |= 0x800;
-+              ast_moutdwm(ast, 0x1e6e2040, data);
-+
-+              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 
0xfc); /* D[1:0]: Reserved Video Buffer */
-+              jreg |= 0x02;
-+              ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg);
-+      }
-+      return true;
-+}
-+
-+u8 ast_get_dp501_max_clk(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u32 boot_address, offset, data;
-+      u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
-+
-+      boot_address = get_fw_base(ast);
-+
-+      /* validate FW version */
-+      offset = 0xf000;
-+      data = ast_mindwm(ast, boot_address + offset);
-+      if ((data & 0xf0) != 0x10) /* version: 1x */
-+              return maxclk;
-+
-+      /* Read Link Capability */
-+      offset  = 0xf014;
-+      data = ast_mindwm(ast, boot_address + offset);
-+      linkcap[0] = (data & 0xff000000) >> 24;
-+      linkcap[1] = (data & 0x00ff0000) >> 16;
-+      linkcap[2] = (data & 0x0000ff00) >> 8;
-+      linkcap[3] = (data & 0x000000ff);
-+      if (linkcap[2] == 0) {
-+              linkrate = linkcap[0];
-+              linklanes = linkcap[1];
-+              data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-+              if (data > 0xff)
-+                      data = 0xff;
-+              maxclk = (u8)data;
-+      }
-+      return maxclk;
-+}
-+
-+bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u32 i, boot_address, offset, data;
-+
-+      boot_address = get_fw_base(ast);
-+
-+      /* validate FW version */
-+      offset = 0xf000;
-+      data = ast_mindwm(ast, boot_address + offset);
-+      if ((data & 0xf0) != 0x10)
-+              return false;
-+
-+      /* validate PnP Monitor */
-+      offset = 0xf010;
-+      data = ast_mindwm(ast, boot_address + offset);
-+      if (!(data & 0x01))
-+              return false;
-+
-+      /* Read EDID */
-+      offset = 0xf020;
-+      for (i = 0; i < 128; i += 4) {
-+              data = ast_mindwm(ast, boot_address + offset + i);
-+              *(u32 *)(ediddata + i) = data;
-+      }
-+
-+      return true;
-+}
-+
-+static bool ast_init_dvo(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 jreg;
-+      u32 data;
-+      ast_write32(ast, 0xf004, 0x1e6e0000);
-+      ast_write32(ast, 0xf000, 0x1);
-+      ast_write32(ast, 0x12000, 0x1688a8a8);
-+
-+      jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-+      if (!(jreg & 0x80)) {
-+              /* Init SCU DVO Settings */
-+              data = ast_read32(ast, 0x12008);
-+              /* delay phase */
-+              data &= 0xfffff8ff;
-+              data |= 0x00000500;
-+              ast_write32(ast, 0x12008, data);
-+
-+              if (ast->chip == AST2300) {
-+                      data = ast_read32(ast, 0x12084);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0xfffe0000;
-+                      ast_write32(ast, 0x12084, data);
-+
-+                      data = ast_read32(ast, 0x12088);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0x000fffff;
-+                      ast_write32(ast, 0x12088, data);
-+
-+                      data = ast_read32(ast, 0x12090);
-+                      /* multi-pins for DVO single-edge */
-+                      data &= 0xffffffcf;
-+                      data |= 0x00000020;
-+                      ast_write32(ast, 0x12090, data);
-+              } else { /* AST2400 */
-+                      data = ast_read32(ast, 0x12088);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0x30000000;
-+                      ast_write32(ast, 0x12088, data);
-+
-+                      data = ast_read32(ast, 0x1208c);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0x000000cf;
-+                      ast_write32(ast, 0x1208c, data);
-+
-+                      data = ast_read32(ast, 0x120a4);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0xffff0000;
-+                      ast_write32(ast, 0x120a4, data);
-+
-+                      data = ast_read32(ast, 0x120a8);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0x0000000f;
-+                      ast_write32(ast, 0x120a8, data);
-+
-+                      data = ast_read32(ast, 0x12094);
-+                      /* multi-pins for DVO single-edge */
-+                      data |= 0x00000002;
-+                      ast_write32(ast, 0x12094, data);
-+              }
-+      }
-+
-+      /* Force to DVO */
-+      data = ast_read32(ast, 0x1202c);
-+      data &= 0xfffbffff;
-+      ast_write32(ast, 0x1202c, data);
-+
-+      /* Init VGA DVO Settings */
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);
-+      return true;
-+}
-+
-+
-+static void ast_init_analog(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u32 data;
-+
-+      /*
-+       * Set DAC source to VGA mode in SCU2C via the P2A
-+       * bridge. First configure the P2U to target the SCU
-+       * in case it isn't at this stage.
-+       */
-+      ast_write32(ast, 0xf004, 0x1e6e0000);
-+      ast_write32(ast, 0xf000, 0x1);
-+
-+      /* Then unlock the SCU with the magic password */
-+      ast_write32(ast, 0x12000, 0x1688a8a8);
-+      ast_write32(ast, 0x12000, 0x1688a8a8);
-+      ast_write32(ast, 0x12000, 0x1688a8a8);
-+
-+      /* Finally, clear bits [17:16] of SCU2c */
-+      data = ast_read32(ast, 0x1202c);
-+      data &= 0xfffcffff;
-+      ast_write32(ast, 0, data);
-+
-+      /* Disable DVO */
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00);
-+}
-+
-+void ast_init_3rdtx(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 jreg;
-+
-+      if (ast->chip == AST2300 || ast->chip == AST2400) {
-+              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 
0xff);
-+              switch (jreg & 0x0e) {
-+              case 0x04:
-+                      ast_init_dvo(dev);
-+                      break;
-+              case 0x08:
-+                      ast_launch_m68k(dev);
-+                      break;
-+              case 0x0c:
-+                      ast_init_dvo(dev);
-+                      break;
-+              default:
-+                      if (ast->tx_chip_type == AST_TX_SIL164)
-+                              ast_init_dvo(dev);
-+                      else
-+                              ast_init_analog(dev);
-+              }
-+      }
-+}
-diff --git a/src/drivers/aspeed/common/ast_dram_tables.h 
b/src/drivers/aspeed/common/ast_dram_tables.h
-new file mode 100644
-index 0000000..4884cba
---- /dev/null
-+++ b/src/drivers/aspeed/common/ast_dram_tables.h
-@@ -0,0 +1,165 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * File taken from the Linux ast driver (v3.18.5)
-+ * Coreboot-specific includes added at top and/or contents modified
-+ * as needed to function within the coreboot environment.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef AST_DRAM_TABLES_H
-+#define AST_DRAM_TABLES_H
-+
-+/* DRAM timing tables */
-+struct ast_dramstruct {
-+      u16 index;
-+      u32 data;
-+};
-+
-+static const struct ast_dramstruct ast2000_dram_table_data[] = {
-+      { 0x0108, 0x00000000 },
-+      { 0x0120, 0x00004a21 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x0000, 0xFFFFFFFF },
-+      { 0x0004, 0x00000089 },
-+      { 0x0008, 0x22331353 },
-+      { 0x000C, 0x0d07000b },
-+      { 0x0010, 0x11113333 },
-+      { 0x0020, 0x00110350 },
-+      { 0x0028, 0x1e0828f0 },
-+      { 0x0024, 0x00000001 },
-+      { 0x001C, 0x00000000 },
-+      { 0x0014, 0x00000003 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x0018, 0x00000131 },
-+      { 0x0014, 0x00000001 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x0018, 0x00000031 },
-+      { 0x0014, 0x00000001 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x0028, 0x1e0828f1 },
-+      { 0x0024, 0x00000003 },
-+      { 0x002C, 0x1f0f28fb },
-+      { 0x0030, 0xFFFFFE01 },
-+      { 0xFFFF, 0xFFFFFFFF }
-+};
-+
-+static const struct ast_dramstruct ast1100_dram_table_data[] = {
-+      { 0x2000, 0x1688a8a8 },
-+      { 0x2020, 0x000041f0 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x0000, 0xfc600309 },
-+      { 0x006C, 0x00909090 },
-+      { 0x0064, 0x00050000 },
-+      { 0x0004, 0x00000585 },
-+      { 0x0008, 0x0011030f },
-+      { 0x0010, 0x22201724 },
-+      { 0x0018, 0x1e29011a },
-+      { 0x0020, 0x00c82222 },
-+      { 0x0014, 0x01001523 },
-+      { 0x001C, 0x1024010d },
-+      { 0x0024, 0x00cb2522 },
-+      { 0x0038, 0xffffff82 },
-+      { 0x003C, 0x00000000 },
-+      { 0x0040, 0x00000000 },
-+      { 0x0044, 0x00000000 },
-+      { 0x0048, 0x00000000 },
-+      { 0x004C, 0x00000000 },
-+      { 0x0050, 0x00000000 },
-+      { 0x0054, 0x00000000 },
-+      { 0x0058, 0x00000000 },
-+      { 0x005C, 0x00000000 },
-+      { 0x0060, 0x032aa02a },
-+      { 0x0064, 0x002d3000 },
-+      { 0x0068, 0x00000000 },
-+      { 0x0070, 0x00000000 },
-+      { 0x0074, 0x00000000 },
-+      { 0x0078, 0x00000000 },
-+      { 0x007C, 0x00000000 },
-+      { 0x0034, 0x00000001 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x002C, 0x00000732 },
-+      { 0x0030, 0x00000040 },
-+      { 0x0028, 0x00000005 },
-+      { 0x0028, 0x00000007 },
-+      { 0x0028, 0x00000003 },
-+      { 0x0028, 0x00000001 },
-+      { 0x000C, 0x00005a08 },
-+      { 0x002C, 0x00000632 },
-+      { 0x0028, 0x00000001 },
-+      { 0x0030, 0x000003c0 },
-+      { 0x0028, 0x00000003 },
-+      { 0x0030, 0x00000040 },
-+      { 0x0028, 0x00000003 },
-+      { 0x000C, 0x00005a21 },
-+      { 0x0034, 0x00007c03 },
-+      { 0x0120, 0x00004c41 },
-+      { 0xffff, 0xffffffff },
-+};
-+
-+static const struct ast_dramstruct ast2100_dram_table_data[] = {
-+      { 0x2000, 0x1688a8a8 },
-+      { 0x2020, 0x00004120 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x0000, 0xfc600309 },
-+      { 0x006C, 0x00909090 },
-+      { 0x0064, 0x00070000 },
-+      { 0x0004, 0x00000489 },
-+      { 0x0008, 0x0011030f },
-+      { 0x0010, 0x32302926 },
-+      { 0x0018, 0x274c0122 },
-+      { 0x0020, 0x00ce2222 },
-+      { 0x0014, 0x01001523 },
-+      { 0x001C, 0x1024010d },
-+      { 0x0024, 0x00cb2522 },
-+      { 0x0038, 0xffffff82 },
-+      { 0x003C, 0x00000000 },
-+      { 0x0040, 0x00000000 },
-+      { 0x0044, 0x00000000 },
-+      { 0x0048, 0x00000000 },
-+      { 0x004C, 0x00000000 },
-+      { 0x0050, 0x00000000 },
-+      { 0x0054, 0x00000000 },
-+      { 0x0058, 0x00000000 },
-+      { 0x005C, 0x00000000 },
-+      { 0x0060, 0x0f2aa02a },
-+      { 0x0064, 0x003f3005 },
-+      { 0x0068, 0x02020202 },
-+      { 0x0070, 0x00000000 },
-+      { 0x0074, 0x00000000 },
-+      { 0x0078, 0x00000000 },
-+      { 0x007C, 0x00000000 },
-+      { 0x0034, 0x00000001 },
-+      { 0xFF00, 0x00000043 },
-+      { 0x002C, 0x00000942 },
-+      { 0x0030, 0x00000040 },
-+      { 0x0028, 0x00000005 },
-+      { 0x0028, 0x00000007 },
-+      { 0x0028, 0x00000003 },
-+      { 0x0028, 0x00000001 },
-+      { 0x000C, 0x00005a08 },
-+      { 0x002C, 0x00000842 },
-+      { 0x0028, 0x00000001 },
-+      { 0x0030, 0x000003c0 },
-+      { 0x0028, 0x00000003 },
-+      { 0x0030, 0x00000040 },
-+      { 0x0028, 0x00000003 },
-+      { 0x000C, 0x00005a21 },
-+      { 0x0034, 0x00007c03 },
-+      { 0x0120, 0x00005061 },
-+      { 0xffff, 0xffffffff },
-+};
-+
-+#endif
-diff --git a/src/drivers/aspeed/common/ast_drv.h 
b/src/drivers/aspeed/common/ast_drv.h
-new file mode 100644
-index 0000000..53640f1
---- /dev/null
-+++ b/src/drivers/aspeed/common/ast_drv.h
-@@ -0,0 +1,223 @@
-+/*
-+ * Copyright 2012 Red Hat Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 
CLAIM,
-+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ */
-+/*
-+ * Authors: Dave Airlie <address@hidden>
-+ */
-+#ifndef __AST_DRV_H__
-+#define __AST_DRV_H__
-+
-+#include "aspeed_coreboot.h"
-+
-+#define PCI_CHIP_AST2000 0x2000
-+#define PCI_CHIP_AST2100 0x2010
-+#define PCI_CHIP_AST1180 0x1180
-+
-+
-+enum ast_chip {
-+      AST2000,
-+      AST2100,
-+      AST1100,
-+      AST2200,
-+      AST2150,
-+      AST2300,
-+      AST2400,
-+      AST1180,
-+};
-+
-+enum ast_tx_chip {
-+      AST_TX_NONE,
-+      AST_TX_SIL164,
-+      AST_TX_ITE66121,
-+      AST_TX_DP501,
-+};
-+
-+#define AST_DRAM_512Mx16 0
-+#define AST_DRAM_1Gx16   1
-+#define AST_DRAM_512Mx32 2
-+#define AST_DRAM_1Gx32   3
-+#define AST_DRAM_2Gx16   6
-+#define AST_DRAM_4Gx16   7
-+
-+struct ast_fbdev;
-+
-+struct ast_private {
-+      struct drm_device *dev;
-+
-+      void __iomem *regs;
-+      void __iomem *ioregs;
-+      bool io_space_uses_mmap;
-+
-+      enum ast_chip chip;
-+      bool vga2_clone;
-+      uint32_t dram_bus_width;
-+      uint32_t dram_type;
-+      uint32_t mclk;
-+      uint32_t vram_size;
-+
-+      struct ast_fbdev *fbdev;
-+
-+      int fb_mtrr;
-+
-+      struct drm_gem_object *cursor_cache;
-+      uint64_t cursor_cache_gpu_addr;
-+
-+      int next_cursor;
-+      bool support_wide_screen;
-+
-+      enum ast_tx_chip tx_chip_type;
-+      u8 dp501_maxclk;
-+      u8 *dp501_fw_addr;
-+      const struct firmware *dp501_fw;        /* dp501 fw */
-+};
-+
-+int ast_driver_load(struct drm_device *dev, unsigned long flags);
-+int ast_driver_unload(struct drm_device *dev);
-+
-+#define AST_IO_AR_PORT_WRITE          (0x40)
-+#define AST_IO_MISC_PORT_WRITE                (0x42)
-+#define AST_IO_VGA_ENABLE_PORT                (0x43)
-+#define AST_IO_SEQ_PORT                       (0x44)
-+#define AST_IO_DAC_INDEX_READ         (0x47)
-+#define AST_IO_DAC_INDEX_WRITE                (0x48)
-+#define AST_IO_DAC_DATA                       (0x49)
-+#define AST_IO_GR_PORT                        (0x4E)
-+#define AST_IO_CRTC_PORT              (0x54)
-+#define AST_IO_INPUT_STATUS1_READ     (0x5A)
-+#define AST_IO_MISC_PORT_READ         (0x4C)
-+
-+#define AST_IO_MM_OFFSET              (0x380)
-+
-+#define __ast_read(x) \
-+static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \
-+u##x val = 0;\
-+val = ioread##x(ast->regs + reg); \
-+return val;\
-+}
-+
-+__ast_read(8);
-+__ast_read(16);
-+__ast_read(32)
-+
-+#define __ast_io_read(x) \
-+static inline u##x ast_io_read##x(struct ast_private *ast, u32 reg) { \
-+u##x val = 0;\
-+if (ast->io_space_uses_mmap) \
-+val = ioread##x(ast->regs + reg); \
-+else \
-+val = ioread_cbio##x(ast->ioregs + reg); \
-+return val;\
-+}
-+
-+__ast_io_read(8);
-+__ast_io_read(16);
-+__ast_io_read(32);
-+
-+#define __ast_write(x) \
-+static inline void ast_write##x(struct ast_private *ast, u32 reg, u##x val) {\
-+      iowrite##x(val, ast->regs + reg);\
-+      }
-+
-+__ast_write(8);
-+__ast_write(16);
-+__ast_write(32);
-+
-+#define __ast_io_write(x) \
-+static inline void ast_io_write##x(struct ast_private *ast, u32 reg, u##x 
val) {\
-+      if (ast->io_space_uses_mmap) \
-+      iowrite##x(val, ast->regs + reg);\
-+      else \
-+      iowrite_cbio##x(val, ast->ioregs + reg);\
-+      }
-+
-+__ast_io_write(8);
-+__ast_io_write(16);
-+#undef __ast_io_write
-+
-+static inline void ast_set_index_reg(struct ast_private *ast,
-+                                   uint32_t base, uint8_t index,
-+                                   uint8_t val)
-+{
-+      ast_io_write16(ast, base, ((u16)val << 8) | index);
-+}
-+
-+void ast_set_index_reg_mask(struct ast_private *ast,
-+                          uint32_t base, uint8_t index,
-+                          uint8_t mask, uint8_t val);
-+uint8_t ast_get_index_reg(struct ast_private *ast,
-+                        uint32_t base, uint8_t index);
-+uint8_t ast_get_index_reg_mask(struct ast_private *ast,
-+                             uint32_t base, uint8_t index, uint8_t mask);
-+
-+static inline void ast_open_key(struct ast_private *ast)
-+{
-+      ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8);
-+}
-+
-+#define AST_VIDMEM_SIZE_8M    0x00800000
-+#define AST_VIDMEM_SIZE_16M   0x01000000
-+#define AST_VIDMEM_SIZE_32M   0x02000000
-+#define AST_VIDMEM_SIZE_64M   0x04000000
-+#define AST_VIDMEM_SIZE_128M  0x08000000
-+
-+#define AST_VIDMEM_DEFAULT_SIZE AST_VIDMEM_SIZE_8M
-+
-+#define AST_MAX_HWC_WIDTH 64
-+#define AST_MAX_HWC_HEIGHT 64
-+
-+#define AST_HWC_SIZE                (AST_MAX_HWC_WIDTH*AST_MAX_HWC_HEIGHT*2)
-+#define AST_HWC_SIGNATURE_SIZE      32
-+
-+#define AST_DEFAULT_HWC_NUM 2
-+/* define for signature structure */
-+#define AST_HWC_SIGNATURE_CHECKSUM  0x00
-+#define AST_HWC_SIGNATURE_SizeX     0x04
-+#define AST_HWC_SIGNATURE_SizeY     0x08
-+#define AST_HWC_SIGNATURE_X         0x0C
-+#define AST_HWC_SIGNATURE_Y         0x10
-+#define AST_HWC_SIGNATURE_HOTSPOTX  0x14
-+#define AST_HWC_SIGNATURE_HOTSPOTY  0x18
-+
-+#define AST_MM_ALIGN_SHIFT 4
-+#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
-+
-+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-+
-+/* ast post */
-+void ast_enable_vga(struct drm_device *dev);
-+void ast_enable_mmio(struct drm_device *dev);
-+bool ast_is_vga_enabled(struct drm_device *dev);
-+void ast_post_gpu(struct drm_device *dev);
-+u32 ast_mindwm(struct ast_private *ast, u32 r);
-+void ast_moutdwm(struct ast_private *ast, u32 r, u32 v);
-+/* ast dp501 */
-+int ast_load_dp501_microcode(struct drm_device *dev);
-+void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
-+bool ast_launch_m68k(struct drm_device *dev);
-+bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
-+bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
-+u8 ast_get_dp501_max_clk(struct drm_device *dev);
-+void ast_init_3rdtx(struct drm_device *dev);
-+#endif
-diff --git a/src/drivers/aspeed/common/ast_main.c 
b/src/drivers/aspeed/common/ast_main.c
-new file mode 100644
-index 0000000..2939442
---- /dev/null
-+++ b/src/drivers/aspeed/common/ast_main.c
-@@ -0,0 +1,393 @@
-+/*
-+ * Copyright 2012 Red Hat Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 
CLAIM,
-+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ */
-+/*
-+ * Authors: Dave Airlie <address@hidden>
-+ */
-+#include "ast_drv.h"
-+
-+#include "ast_dram_tables.h"
-+
-+void ast_set_index_reg_mask(struct ast_private *ast,
-+                          uint32_t base, uint8_t index,
-+                          uint8_t mask, uint8_t val)
-+{
-+      u8 tmp;
-+      ast_io_write8(ast, base, index);
-+      tmp = (ast_io_read8(ast, base + 1) & mask) | val;
-+      ast_set_index_reg(ast, base, index, tmp);
-+}
-+
-+uint8_t ast_get_index_reg(struct ast_private *ast,
-+                        uint32_t base, uint8_t index)
-+{
-+      uint8_t ret;
-+      ast_io_write8(ast, base, index);
-+      ret = ast_io_read8(ast, base + 1);
-+      return ret;
-+}
-+
-+uint8_t ast_get_index_reg_mask(struct ast_private *ast,
-+                             uint32_t base, uint8_t index, uint8_t mask)
-+{
-+      uint8_t ret;
-+      ast_io_write8(ast, base, index);
-+      ret = ast_io_read8(ast, base + 1) & mask;
-+      return ret;
-+}
-+
-+
-+static int ast_detect_chip(struct drm_device *dev, bool *need_post)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      uint32_t data, jreg;
-+      ast_open_key(ast);
-+
-+      if (dev->pdev->device == PCI_CHIP_AST1180) {
-+              ast->chip = AST1100;
-+              DRM_INFO("AST 1180 detected\n");
-+      } else {
-+              pci_read_config_dword(ast->dev->pdev, 0x08, &data);
-+              uint8_t revision = data & 0xff;
-+
-+              if (revision >= 0x30) {
-+                      ast->chip = AST2400;
-+                      DRM_INFO("AST 2400 detected\n");
-+              } else if (revision >= 0x20) {
-+                      ast->chip = AST2300;
-+                      DRM_INFO("AST 2300 detected\n");
-+              } else if (revision >= 0x10) {
-+                      ast_write32(ast, 0xf004, 0x1e6e0000);
-+                      ast_write32(ast, 0xf000, 0x1);
-+
-+                      data = ast_read32(ast, 0x1207c);
-+                      switch (data & 0x0300) {
-+                      case 0x0200:
-+                              ast->chip = AST1100;
-+                              DRM_INFO("AST 1100 detected\n");
-+                              break;
-+                      case 0x0100:
-+                              ast->chip = AST2200;
-+                              DRM_INFO("AST 2200 detected\n");
-+                              break;
-+                      case 0x0000:
-+                              ast->chip = AST2150;
-+                              DRM_INFO("AST 2150 detected\n");
-+                              break;
-+                      default:
-+                              ast->chip = AST2100;
-+                              DRM_INFO("AST 2100 detected\n");
-+                              break;
-+                      }
-+                      ast->vga2_clone = false;
-+              } else {
-+                      ast->chip = AST2000;
-+                      DRM_INFO("AST 2000 detected\n");
-+              }
-+      }
-+
-+      /*
-+       * If VGA isn't enabled, we need to enable now or subsequent
-+       * access to the scratch registers will fail. We also inform
-+       * our caller that it needs to POST the chip
-+       * (Assumption: VGA not enabled -> need to POST)
-+       */
-+      if (!ast_is_vga_enabled(dev)) {
-+              ast_enable_vga(dev);
-+              ast_enable_mmio(dev);
-+              DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
-+              *need_post = true;
-+      } else
-+              *need_post = false;
-+
-+      /* Check if we support wide screen */
-+      switch (ast->chip) {
-+      case AST1180:
-+              ast->support_wide_screen = true;
-+              break;
-+      case AST2000:
-+              ast->support_wide_screen = false;
-+              break;
-+      default:
-+              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 
0xff);
-+              if (!(jreg & 0x80))
-+                      ast->support_wide_screen = true;
-+              else if (jreg & 0x01)
-+                      ast->support_wide_screen = true;
-+              else {
-+                      ast->support_wide_screen = false;
-+                      /* Read SCU7c (silicon revision register) */
-+                      ast_write32(ast, 0xf004, 0x1e6e0000);
-+                      ast_write32(ast, 0xf000, 0x1);
-+                      data = ast_read32(ast, 0x1207c);
-+                      data &= 0x300;
-+                      if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
-+                              ast->support_wide_screen = true;
-+                      if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
-+                              ast->support_wide_screen = true;
-+              }
-+              break;
-+      }
-+
-+      /* Check 3rd Tx option (digital output afaik) */
-+      ast->tx_chip_type = AST_TX_NONE;
-+
-+      /*
-+       * VGACRA3 Enhanced Color Mode Register, check if DVO is already
-+       * enabled, in that case, assume we have a SIL164 TMDS transmitter
-+       *
-+       * Don't make that assumption if we the chip wasn't enabled and
-+       * is at power-on reset, otherwise we'll incorrectly "detect" a
-+       * SIL164 when there is none.
-+       */
-+      if (!*need_post) {
-+              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 
0xff);
-+              if (jreg & 0x80)
-+                      ast->tx_chip_type = AST_TX_SIL164;
-+      }
-+
-+      if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
-+              /*
-+               * On AST2300 and 2400, look the configuration set by the SoC in
-+               * the SOC scratch register #1 bits 11:8 (interestingly marked
-+               * as "reserved" in the spec)
-+               */
-+              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 
0xff);
-+              switch (jreg) {
-+              case 0x04:
-+                      ast->tx_chip_type = AST_TX_SIL164;
-+                      break;
-+              case 0x08:
-+                      ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL);
-+                      if (ast->dp501_fw_addr) {
-+                              /* backup firmware */
-+                              if (ast_backup_fw(dev, ast->dp501_fw_addr, 
32*1024)) {
-+                                      kfree(ast->dp501_fw_addr);
-+                                      ast->dp501_fw_addr = NULL;
-+                              }
-+                      }
-+                      /* fallthrough */
-+              case 0x0c:
-+                      ast->tx_chip_type = AST_TX_DP501;
-+              }
-+      }
-+
-+      /* Print stuff for diagnostic purposes */
-+      switch(ast->tx_chip_type) {
-+      case AST_TX_SIL164:
-+              DRM_INFO("Using Sil164 TMDS transmitter\n");
-+              break;
-+      case AST_TX_DP501:
-+              DRM_INFO("Using DP501 DisplayPort transmitter\n");
-+              break;
-+      default:
-+              DRM_INFO("Analog VGA only\n");
-+      }
-+      return 0;
-+}
-+
-+static int ast_get_dram_info(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      uint8_t i;
-+      uint32_t data, data2;
-+      uint32_t denum, num, div, ref_pll;
-+
-+      ast_write32(ast, 0xf004, 0x1e6e0000);
-+      ast_write32(ast, 0xf000, 0x1);
-+
-+
-+      ast_write32(ast, 0x10000, 0xfc600309);
-+
-+      /* Wait up to 2.5 seconds for device initialization / register unlock */
-+      for (i = 0; i < 250; i++) {
-+              if (ast_read32(ast, 0x10000) == 0x01)
-+                      break;
-+              mdelay(10);
-+      }
-+      if (ast_read32(ast, 0x10000) != 0x01)
-+              dev_err(dev->pdev, "Unable to unlock SDRAM control 
registers\n");
-+
-+      data = ast_read32(ast, 0x10004);
-+
-+      if (data & 0x400)
-+              ast->dram_bus_width = 16;
-+      else
-+              ast->dram_bus_width = 32;
-+
-+      if (ast->chip == AST2300 || ast->chip == AST2400) {
-+              switch (data & 0x03) {
-+              case 0:
-+                      ast->dram_type = AST_DRAM_512Mx16;
-+                      break;
-+              default:
-+              case 1:
-+                      ast->dram_type = AST_DRAM_1Gx16;
-+                      break;
-+              case 2:
-+                      ast->dram_type = AST_DRAM_2Gx16;
-+                      break;
-+              case 3:
-+                      ast->dram_type = AST_DRAM_4Gx16;
-+                      break;
-+              }
-+      } else {
-+              switch (data & 0x0c) {
-+              case 0:
-+              case 4:
-+                      ast->dram_type = AST_DRAM_512Mx16;
-+                      break;
-+              case 8:
-+                      if (data & 0x40)
-+                              ast->dram_type = AST_DRAM_1Gx16;
-+                      else
-+                              ast->dram_type = AST_DRAM_512Mx32;
-+                      break;
-+              case 0xc:
-+                      ast->dram_type = AST_DRAM_1Gx32;
-+                      break;
-+              }
-+      }
-+
-+      data = ast_read32(ast, 0x10120);
-+      data2 = ast_read32(ast, 0x10170);
-+      if (data2 & 0x2000)
-+              ref_pll = 14318;
-+      else
-+              ref_pll = 12000;
-+
-+      denum = data & 0x1f;
-+      num = (data & 0x3fe0) >> 5;
-+      data = (data & 0xc000) >> 14;
-+      switch (data) {
-+      case 3:
-+              div = 0x4;
-+              break;
-+      case 2:
-+      case 1:
-+              div = 0x2;
-+              break;
-+      default:
-+              div = 0x1;
-+              break;
-+      }
-+      ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
-+      return 0;
-+}
-+
-+static u32 ast_get_vram_info(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 jreg;
-+      u32 vram_size;
-+      ast_open_key(ast);
-+
-+      vram_size = AST_VIDMEM_DEFAULT_SIZE;
-+      jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);
-+      switch (jreg & 3) {
-+      case 0: vram_size = AST_VIDMEM_SIZE_8M; break;
-+      case 1: vram_size = AST_VIDMEM_SIZE_16M; break;
-+      case 2: vram_size = AST_VIDMEM_SIZE_32M; break;
-+      case 3: vram_size = AST_VIDMEM_SIZE_64M; break;
-+      }
-+
-+      return vram_size;
-+}
-+
-+int ast_driver_load(struct drm_device *dev, unsigned long flags)
-+{
-+      struct ast_private *ast;
-+      bool need_post;
-+      int ret = 0;
-+      struct resource *res;
-+
-+      ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL);
-+      if (!ast)
-+              return -ENOMEM;
-+
-+      dev->dev_private = ast;
-+      ast->dev = dev;
-+
-+      /* PCI BAR 1 */
-+        res = find_resource(dev->pdev, 0x14);
-+      if (!res) {
-+              dev_err(dev->pdev, "BAR1 resource not found.\n");
-+              ret = -EIO;
-+              goto out_free;
-+      }
-+      ast->regs = res2mmio(res, 0, 0);
-+      if (!ast->regs) {
-+              ret = -EIO;
-+              goto out_free;
-+      }
-+
-+      /* PCI BAR 2 */
-+      ast->io_space_uses_mmap = false;
-+      res = find_resource(dev->pdev, 0x18);
-+      if (!res) {
-+              dev_err(dev->pdev, "BAR2 resource not found.\n");
-+              ret = -EIO;
-+              goto out_free;
-+      }
-+
-+      /*
-+       * If we don't have IO space at all, use MMIO now and
-+       * assume the chip has MMIO enabled by default (rev 0x20
-+       * and higher).
-+       */
-+      if (!(res->flags & IORESOURCE_IO)) {
-+              DRM_INFO("platform has no IO space, trying MMIO\n");
-+              ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
-+              ast->io_space_uses_mmap = true;
-+      }
-+
-+      /* "map" IO regs if the above hasn't done so already */
-+      if (!ast->ioregs) {
-+              ast->ioregs = res2mmio(res, 0, 0);
-+              if (!ast->ioregs) {
-+                      ret = -EIO;
-+                      goto out_free;
-+              }
-+              /* Adjust the I/O space location to match expectations (the 
code expects offset 0x0 to be I/O location 0x380) */
-+              ast->ioregs = (void *)AST_IO_MM_OFFSET;
-+      }
-+
-+      ast_detect_chip(dev, &need_post);
-+
-+      if (ast->chip != AST1180) {
-+              ast_get_dram_info(dev);
-+              ast->vram_size = ast_get_vram_info(dev);
-+              DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, 
ast->dram_bus_width, ast->vram_size);
-+      }
-+
-+      if (need_post)
-+              ast_post_gpu(dev);
-+
-+      return 0;
-+out_free:
-+      kfree(ast);
-+      dev->dev_private = NULL;
-+      return ret;
-+}
-diff --git a/src/drivers/aspeed/common/ast_post.c 
b/src/drivers/aspeed/common/ast_post.c
-new file mode 100644
-index 0000000..7d31845
---- /dev/null
-+++ b/src/drivers/aspeed/common/ast_post.c
-@@ -0,0 +1,1679 @@
-+/*
-+ * Copyright 2012 Red Hat Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 
CLAIM,
-+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ */
-+/*
-+ * Authors: Dave Airlie <address@hidden>
-+ */
-+
-+#include "ast_drv.h"
-+
-+#include "ast_dram_tables.h"
-+
-+static void ast_init_dram_2300(struct drm_device *dev);
-+
-+void ast_enable_vga(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+
-+      ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01);
-+      ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);
-+}
-+
-+void ast_enable_mmio(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
-+}
-+
-+
-+bool ast_is_vga_enabled(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 ch;
-+
-+      if (ast->chip == AST1180) {
-+              /* TODO 1180 */
-+      } else {
-+              ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
-+              if (ch) {
-+                      ast_open_key(ast);
-+                      ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xb6, 0xff);
-+                      return ch & 0x04;
-+              }
-+      }
-+      return 0;
-+}
-+
-+static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
-+static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff };
-+static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };
-+
-+static void
-+ast_set_def_ext_reg(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 i, index, reg;
-+      uint32_t data;
-+      const u8 *ext_reg_info;
-+
-+      pci_read_config_dword(ast->dev->pdev, 0x08, &data);
-+      uint8_t revision = data & 0xff;
-+
-+      /* reset scratch */
-+      for (i = 0x81; i <= 0x8f; i++)
-+              ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
-+
-+      if (ast->chip == AST2300 || ast->chip == AST2400) {
-+              if (revision >= 0x20)
-+                      ext_reg_info = extreginfo_ast2300;
-+              else
-+                      ext_reg_info = extreginfo_ast2300a0;
-+      } else
-+              ext_reg_info = extreginfo;
-+
-+      index = 0xa0;
-+      while (*ext_reg_info != 0xff) {
-+              ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, 
*ext_reg_info);
-+              index++;
-+              ext_reg_info++;
-+      }
-+
-+      /* disable standard IO/MEM decode if secondary */
-+      /* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */
-+
-+      /* Set Ext. Default */
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01);
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00);
-+
-+      /* Enable RAMDAC for A1 */
-+      reg = 0x04;
-+      if (ast->chip == AST2300 || ast->chip == AST2400)
-+              reg |= 0x20;
-+      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
-+}
-+
-+u32 ast_mindwm(struct ast_private *ast, u32 r)
-+{
-+      uint32_t data;
-+
-+      ast_write32(ast, 0xf004, r & 0xffff0000);
-+      ast_write32(ast, 0xf000, 0x1);
-+
-+      do {
-+              data = ast_read32(ast, 0xf004) & 0xffff0000;
-+      } while (data != (r & 0xffff0000));
-+      return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
-+}
-+
-+void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)
-+{
-+      uint32_t data;
-+      ast_write32(ast, 0xf004, r & 0xffff0000);
-+      ast_write32(ast, 0xf000, 0x1);
-+      do {
-+              data = ast_read32(ast, 0xf004) & 0xffff0000;
-+      } while (data != (r & 0xffff0000));
-+      ast_write32(ast, 0x10000 + (r & 0x0000ffff), v);
-+}
-+
-+/*
-+ * AST2100/2150 DLL CBR Setting
-+ */
-+#define CBR_SIZE_AST2150           ((16 << 10) - 1)
-+#define CBR_PASSNUM_AST2150          5
-+#define CBR_THRESHOLD_AST2150        10
-+#define CBR_THRESHOLD2_AST2150       10
-+#define TIMEOUT_AST2150              5000000
-+
-+#define CBR_PATNUM_AST2150           8
-+
-+static const u32 pattern_AST2150[14] = {
-+      0xFF00FF00,
-+      0xCC33CC33,
-+      0xAA55AA55,
-+      0xFFFE0001,
-+      0x683501FE,
-+      0x0F1929B0,
-+      0x2D0B4346,
-+      0x60767F02,
-+      0x6FBE36A6,
-+      0x3A253035,
-+      0x3019686D,
-+      0x41C6167E,
-+      0x620152BF,
-+      0x20F050E0
-+};
-+
-+static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen)
-+{
-+      u32 data, timeout;
-+
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
-+              if (++timeout > TIMEOUT_AST2150) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+                      return 0xffffffff;
-+              }
-+      } while (!data);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
-+              if (++timeout > TIMEOUT_AST2150) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+                      return 0xffffffff;
-+              }
-+      } while (!data);
-+      data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      return data;
-+}
-+
-+#if 0 /* unused in DDX driver - here for completeness */
-+static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen)
-+{
-+      u32 data, timeout;
-+
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
-+              if (++timeout > TIMEOUT_AST2150) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+                      return 0xffffffff;
-+              }
-+      } while (!data);
-+      data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      return data;
-+}
-+#endif
-+
-+static int cbrtest_ast2150(struct ast_private *ast)
-+{
-+      int i;
-+
-+      for (i = 0; i < 8; i++)
-+              if (mmctestburst2_ast2150(ast, i))
-+                      return 0;
-+      return 1;
-+}
-+
-+static int cbrscan_ast2150(struct ast_private *ast, int busw)
-+{
-+      u32 patcnt, loop;
-+
-+      for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
-+              ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]);
-+              for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
-+                      if (cbrtest_ast2150(ast))
-+                              break;
-+              }
-+              if (loop == CBR_PASSNUM_AST2150)
-+                      return 0;
-+      }
-+      return 1;
-+}
-+
-+
-+static void cbrdlli_ast2150(struct ast_private *ast, int busw)
-+{
-+      u32 dll_min[4], dll_max[4], dlli, data, passcnt;
-+
-+cbr_start:
-+      dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff;
-+      dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0;
-+      passcnt = 0;
-+
-+      for (dlli = 0; dlli < 100; dlli++) {
-+              ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) 
| (dlli << 24));
-+              data = cbrscan_ast2150(ast, busw);
-+              if (data != 0) {
-+                      if (data & 0x1) {
-+                              if (dll_min[0] > dlli)
-+                                      dll_min[0] = dlli;
-+                              if (dll_max[0] < dlli)
-+                                      dll_max[0] = dlli;
-+                      }
-+                      passcnt++;
-+              } else if (passcnt >= CBR_THRESHOLD_AST2150)
-+                      goto cbr_start;
-+      }
-+      if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150)
-+              goto cbr_start;
-+
-+      dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
-+      ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli 
<< 24));
-+}
-+
-+
-+
-+static void ast_init_dram_reg(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      u8 j;
-+      u32 data, temp, i;
-+      const struct ast_dramstruct *dram_reg_info;
-+
-+      j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-+
-+      if ((j & 0x80) == 0) { /* VGA only */
-+              if (ast->chip == AST2000) {
-+                      dram_reg_info = ast2000_dram_table_data;
-+                      ast_write32(ast, 0xf004, 0x1e6e0000);
-+                      ast_write32(ast, 0xf000, 0x1);
-+                      ast_write32(ast, 0x10100, 0xa8);
-+
-+                      do {
-+                              ;
-+                      } while (ast_read32(ast, 0x10100) != 0xa8);
-+              } else {/* AST2100/1100 */
-+                      if (ast->chip == AST2100 || ast->chip == 2200)
-+                              dram_reg_info = ast2100_dram_table_data;
-+                      else
-+                              dram_reg_info = ast1100_dram_table_data;
-+
-+                      ast_write32(ast, 0xf004, 0x1e6e0000);
-+                      ast_write32(ast, 0xf000, 0x1);
-+                      ast_write32(ast, 0x12000, 0x1688A8A8);
-+
-+                      /* Wait up to 2.5 seconds for device initialization / 
register unlock */
-+                      for (i = 0; i < 250; i++) {
-+                              if (ast_read32(ast, 0x12000) == 0x01)
-+                                      break;
-+                              mdelay(10);
-+                      }
-+                      if (ast_read32(ast, 0x12000) != 0x01)
-+                              dev_err(dev->pdev, "Unable to unlock SCU 
registers\n");
-+
-+                      ast_write32(ast, 0x10000, 0xfc600309);
-+
-+                      /* Wait up to 2.5 seconds for device initialization / 
register unlock */
-+                      for (i = 0; i < 250; i++) {
-+                              if (ast_read32(ast, 0x10000) == 0x01)
-+                                      break;
-+                              mdelay(10);
-+                      }
-+                      if (ast_read32(ast, 0x10000) != 0x01)
-+                              dev_err(dev->pdev, "Unable to unlock SDRAM 
control registers\n");
-+              }
-+
-+              while (dram_reg_info->index != 0xffff) {
-+                      if (dram_reg_info->index == 0xff00) {/* delay fn */
-+                              for (i = 0; i < 15; i++)
-+                                      udelay(dram_reg_info->data);
-+                      } else if (dram_reg_info->index == 0x4 && ast->chip != 
AST2000) {
-+                              data = dram_reg_info->data;
-+                              if (ast->dram_type == AST_DRAM_1Gx16)
-+                                      data = 0x00000d89;
-+                              else if (ast->dram_type == AST_DRAM_1Gx32)
-+                                      data = 0x00000c8d;
-+
-+                              temp = ast_read32(ast, 0x12070);
-+                              temp &= 0xc;
-+                              temp <<= 2;
-+                              ast_write32(ast, 0x10000 + 
dram_reg_info->index, data | temp);
-+                      } else
-+                              ast_write32(ast, 0x10000 + 
dram_reg_info->index, dram_reg_info->data);
-+                      dram_reg_info++;
-+              }
-+
-+              /* AST 2100/2150 DRAM calibration */
-+              data = ast_read32(ast, 0x10120);
-+              if (data == 0x5061) { /* 266Mhz */
-+                      data = ast_read32(ast, 0x10004);
-+                      if (data & 0x40)
-+                              cbrdlli_ast2150(ast, 16); /* 16 bits */
-+                      else
-+                              cbrdlli_ast2150(ast, 32); /* 32 bits */
-+              }
-+
-+              switch (ast->chip) {
-+              case AST2000:
-+                      temp = ast_read32(ast, 0x10140);
-+                      ast_write32(ast, 0x10140, temp | 0x40);
-+                      break;
-+              case AST1100:
-+              case AST2100:
-+              case AST2200:
-+              case AST2150:
-+                      temp = ast_read32(ast, 0x1200c);
-+                      ast_write32(ast, 0x1200c, temp & 0xfffffffd);
-+                      temp = ast_read32(ast, 0x12040);
-+                      ast_write32(ast, 0x12040, temp | 0x40);
-+                      break;
-+              default:
-+                      break;
-+              }
-+      }
-+
-+      /* wait ready */
-+      /* Wait up to 2.5 seconds for device to become ready */
-+      for (i = 0; i < 250; i++) {
-+              j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-+              mdelay(10);
-+              if ((j & 0x40) != 0)
-+                      break;
-+      }
-+      if ((j & 0x40) == 0)
-+              dev_err(dev->pdev, "Timeout while waiting for device to signal 
ready\n");
-+}
-+
-+void ast_post_gpu(struct drm_device *dev)
-+{
-+      u32 reg;
-+      struct ast_private *ast = dev->dev_private;
-+
-+      pci_read_config_dword(ast->dev->pdev, 0x04, &reg);
-+      reg |= 0x3;
-+      pci_write_config_dword(ast->dev->pdev, 0x04, reg);
-+
-+      ast_enable_vga(dev);
-+      ast_enable_mmio(dev);
-+      ast_open_key(ast);
-+      ast_set_def_ext_reg(dev);
-+
-+      if (ast->chip == AST2300 || ast->chip == AST2400)
-+              ast_init_dram_2300(dev);
-+      else
-+              ast_init_dram_reg(dev);
-+
-+      ast_init_3rdtx(dev);
-+}
-+
-+/* AST 2300 DRAM settings */
-+#define AST_DDR3 0
-+#define AST_DDR2 1
-+
-+struct ast2300_dram_param {
-+      u32 dram_type;
-+      u32 dram_chipid;
-+      u32 dram_freq;
-+      u32 vram_size;
-+      u32 odt;
-+      u32 wodt;
-+      u32 rodt;
-+      u32 dram_config;
-+      u32 reg_PERIOD;
-+      u32 reg_MADJ;
-+      u32 reg_SADJ;
-+      u32 reg_MRS;
-+      u32 reg_EMRS;
-+      u32 reg_AC1;
-+      u32 reg_AC2;
-+      u32 reg_DQSIC;
-+      u32 reg_DRV;
-+      u32 reg_IOZ;
-+      u32 reg_DQIDLY;
-+      u32 reg_FREQ;
-+      u32 madj_max;
-+      u32 dll2_finetune_step;
-+};
-+
-+/*
-+ * DQSI DLL CBR Setting
-+ */
-+#define CBR_SIZE0            ((1  << 10) - 1)
-+#define CBR_SIZE1            ((4  << 10) - 1)
-+#define CBR_SIZE2            ((64 << 10) - 1)
-+#define CBR_PASSNUM          5
-+#define CBR_PASSNUM2         5
-+#define CBR_THRESHOLD        10
-+#define CBR_THRESHOLD2       10
-+#define TIMEOUT              5000000
-+#define CBR_PATNUM           8
-+
-+static const u32 pattern[8] = {
-+      0xFF00FF00,
-+      0xCC33CC33,
-+      0xAA55AA55,
-+      0x88778877,
-+      0x92CC4D6E,
-+      0x543D3CDE,
-+      0xF1E843C7,
-+      0x7C61D253
-+};
-+
-+static int mmc_test_burst(struct ast_private *ast, u32 datagen)
-+{
-+      u32 data, timeout;
-+
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
-+              if (data & 0x2000) {
-+                      return 0;
-+              }
-+              if (++timeout > TIMEOUT) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+                      return 0;
-+              }
-+      } while (!data);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      return 1;
-+}
-+
-+static int mmc_test_burst2(struct ast_private *ast, u32 datagen)
-+{
-+      u32 data, timeout;
-+
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
-+              if (++timeout > TIMEOUT) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x0);
-+                      return -1;
-+              }
-+      } while (!data);
-+      data = ast_mindwm(ast, 0x1e6e0078);
-+      data = (data | (data >> 16)) & 0xffff;
-+      ast_moutdwm(ast, 0x1e6e0070, 0x0);
-+      return data;
-+}
-+
-+static int mmc_test_single(struct ast_private *ast, u32 datagen)
-+{
-+      u32 data, timeout;
-+
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
-+              if (data & 0x2000)
-+                      return 0;
-+              if (++timeout > TIMEOUT) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x0);
-+                      return 0;
-+              }
-+      } while (!data);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x0);
-+      return 1;
-+}
-+
-+static int mmc_test_single2(struct ast_private *ast, u32 datagen)
-+{
-+      u32 data, timeout;
-+
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
-+      timeout = 0;
-+      do {
-+              data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
-+              if (++timeout > TIMEOUT) {
-+                      ast_moutdwm(ast, 0x1e6e0070, 0x0);
-+                      return -1;
-+              }
-+      } while (!data);
-+      data = ast_mindwm(ast, 0x1e6e0078);
-+      data = (data | (data >> 16)) & 0xffff;
-+      ast_moutdwm(ast, 0x1e6e0070, 0x0);
-+      return data;
-+}
-+
-+static int cbr_test(struct ast_private *ast)
-+{
-+      u32 data;
-+      int i;
-+      data = mmc_test_single2(ast, 0);
-+      if ((data & 0xff) && (data & 0xff00))
-+              return 0;
-+      for (i = 0; i < 8; i++) {
-+              data = mmc_test_burst2(ast, i);
-+              if ((data & 0xff) && (data & 0xff00))
-+                      return 0;
-+      }
-+      if (!data)
-+              return 3;
-+      else if (data & 0xff)
-+              return 2;
-+      return 1;
-+}
-+
-+static int cbr_scan(struct ast_private *ast)
-+{
-+      u32 data, data2, patcnt, loop;
-+
-+      data2 = 3;
-+      for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
-+              ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
-+              for (loop = 0; loop < CBR_PASSNUM2; loop++) {
-+                      if ((data = cbr_test(ast)) != 0) {
-+                              data2 &= data;
-+                              if (!data2)
-+                                      return 0;
-+                              break;
-+                      }
-+              }
-+              if (loop == CBR_PASSNUM2)
-+                      return 0;
-+      }
-+      return data2;
-+}
-+
-+static u32 cbr_test2(struct ast_private *ast)
-+{
-+      u32 data;
-+
-+      data = mmc_test_burst2(ast, 0);
-+      if (data == 0xffff)
-+              return 0;
-+      data |= mmc_test_single2(ast, 0);
-+      if (data == 0xffff)
-+              return 0;
-+
-+      return ~data & 0xffff;
-+}
-+
-+static u32 cbr_scan2(struct ast_private *ast)
-+{
-+      u32 data, data2, patcnt, loop;
-+
-+      data2 = 0xffff;
-+      for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
-+              ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
-+              for (loop = 0; loop < CBR_PASSNUM2; loop++) {
-+                      if ((data = cbr_test2(ast)) != 0) {
-+                              data2 &= data;
-+                              if (!data2)
-+                                      return 0;
-+                              break;
-+                      }
-+              }
-+              if (loop == CBR_PASSNUM2)
-+                      return 0;
-+      }
-+      return data2;
-+}
-+
-+static u32 cbr_test3(struct ast_private *ast)
-+{
-+      if (!mmc_test_burst(ast, 0))
-+              return 0;
-+      if (!mmc_test_single(ast, 0))
-+              return 0;
-+      return 1;
-+}
-+
-+static u32 cbr_scan3(struct ast_private *ast)
-+{
-+      u32 patcnt, loop;
-+
-+      for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
-+              ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
-+              for (loop = 0; loop < 2; loop++) {
-+                      if (cbr_test3(ast))
-+                              break;
-+              }
-+              if (loop == 2)
-+                      return 0;
-+      }
-+      return 1;
-+}
-+
-+static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param 
*param)
-+{
-+      u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, 
passcnt, retry = 0;
-+      bool status = false;
-+FINETUNE_START:
-+      for (cnt = 0; cnt < 16; cnt++) {
-+              dllmin[cnt] = 0xff;
-+              dllmax[cnt] = 0x0;
-+      }
-+      passcnt = 0;
-+      for (dlli = 0; dlli < 76; dlli++) {
-+              ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli 
<< 24));
-+              ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
-+              data = cbr_scan2(ast);
-+              if (data != 0) {
-+                      mask = 0x00010001;
-+                      for (cnt = 0; cnt < 16; cnt++) {
-+                              if (data & mask) {
-+                                      if (dllmin[cnt] > dlli) {
-+                                              dllmin[cnt] = dlli;
-+                                      }
-+                                      if (dllmax[cnt] < dlli) {
-+                                              dllmax[cnt] = dlli;
-+                                      }
-+                              }
-+                              mask <<= 1;
-+                      }
-+                      passcnt++;
-+              } else if (passcnt >= CBR_THRESHOLD2) {
-+                      break;
-+              }
-+      }
-+      gold_sadj[0] = 0x0;
-+      passcnt = 0;
-+      for (cnt = 0; cnt < 16; cnt++) {
-+              if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) 
>= CBR_THRESHOLD2)) {
-+                      gold_sadj[0] += dllmin[cnt];
-+                      passcnt++;
-+              }
-+      }
-+      if (retry++ > 10)
-+              goto FINETUNE_DONE;
-+      if (passcnt != 16) {
-+              goto FINETUNE_START;
-+      }
-+      status = true;
-+FINETUNE_DONE:
-+      gold_sadj[0] = gold_sadj[0] >> 4;
-+      gold_sadj[1] = gold_sadj[0];
-+
-+      data = 0;
-+      for (cnt = 0; cnt < 8; cnt++) {
-+              data >>= 3;
-+              if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) 
>= CBR_THRESHOLD2)) {
-+                      dlli = dllmin[cnt];
-+                      if (gold_sadj[0] >= dlli) {
-+                              dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
-+                              if (dlli > 3) {
-+                                      dlli = 3;
-+                              }
-+                      } else {
-+                              dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
-+                              if (dlli > 4) {
-+                                      dlli = 4;
-+                              }
-+                              dlli = (8 - dlli) & 0x7;
-+                      }
-+                      data |= dlli << 21;
-+              }
-+      }
-+      ast_moutdwm(ast, 0x1E6E0080, data);
-+
-+      data = 0;
-+      for (cnt = 8; cnt < 16; cnt++) {
-+              data >>= 3;
-+              if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) 
>= CBR_THRESHOLD2)) {
-+                      dlli = dllmin[cnt];
-+                      if (gold_sadj[1] >= dlli) {
-+                              dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
-+                              if (dlli > 3) {
-+                                      dlli = 3;
-+                              } else {
-+                                      dlli = (dlli - 1) & 0x7;
-+                              }
-+                      } else {
-+                              dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
-+                              dlli += 1;
-+                              if (dlli > 4) {
-+                                      dlli = 4;
-+                              }
-+                              dlli = (8 - dlli) & 0x7;
-+                      }
-+                      data |= dlli << 21;
-+              }
-+      }
-+      ast_moutdwm(ast, 0x1E6E0084, data);
-+      return status;
-+} /* finetuneDQI_L */
-+
-+static void finetuneDQSI(struct ast_private *ast)
-+{
-+      u32 dlli, dqsip, dqidly;
-+      u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
-+      u32 g_dqidly, g_dqsip, g_margin, g_side;
-+      u16 pass[32][2][2];
-+      char tag[2][76];
-+
-+      /* Disable DQI CBR */
-+      reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
-+      reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
-+      reg_mcr18 &= 0x0000ffff;
-+      ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
-+
-+      for (dlli = 0; dlli < 76; dlli++) {
-+              tag[0][dlli] = 0x0;
-+              tag[1][dlli] = 0x0;
-+      }
-+      for (dqidly = 0; dqidly < 32; dqidly++) {
-+              pass[dqidly][0][0] = 0xff;
-+              pass[dqidly][0][1] = 0x0;
-+              pass[dqidly][1][0] = 0xff;
-+              pass[dqidly][1][1] = 0x0;
-+      }
-+      for (dqidly = 0; dqidly < 32; dqidly++) {
-+              passcnt[0] = passcnt[1] = 0;
-+              for (dqsip = 0; dqsip < 2; dqsip++) {
-+                      ast_moutdwm(ast, 0x1E6E000C, 0);
-+                      ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) 
| (dqsip << 23));
-+                      ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
-+                      for (dlli = 0; dlli < 76; dlli++) {
-+                              ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli 
<< 16) | (dlli << 24));
-+                              ast_moutdwm(ast, 0x1E6E0070, 0);
-+                              ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
-+                              if (cbr_scan3(ast)) {
-+                                      if (dlli == 0)
-+                                              break;
-+                                      passcnt[dqsip]++;
-+                                      tag[dqsip][dlli] = 'P';
-+                                      if (dlli < pass[dqidly][dqsip][0])
-+                                              pass[dqidly][dqsip][0] = (u16) 
dlli;
-+                                      if (dlli > pass[dqidly][dqsip][1])
-+                                              pass[dqidly][dqsip][1] = (u16) 
dlli;
-+                              } else if (passcnt[dqsip] >= 5)
-+                                      break;
-+                              else {
-+                                      pass[dqidly][dqsip][0] = 0xff;
-+                                      pass[dqidly][dqsip][1] = 0x0;
-+                              }
-+                      }
-+              }
-+              if (passcnt[0] == 0 && passcnt[1] == 0)
-+                      dqidly++;
-+      }
-+      /* Search margin */
-+      g_dqidly = g_dqsip = g_margin = g_side = 0;
-+
-+      for (dqidly = 0; dqidly < 32; dqidly++) {
-+              for (dqsip = 0; dqsip < 2; dqsip++) {
-+                      if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
-+                              continue;
-+                      diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
-+                      if ((diff+2) < g_margin)
-+                              continue;
-+                      passcnt[0] = passcnt[1] = 0;
-+                      for (dlli = pass[dqidly][dqsip][0]; dlli > 0  && 
tag[dqsip][dlli] != 0; dlli--, passcnt[0]++);
-+                      for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && 
tag[dqsip][dlli] != 0; dlli++, passcnt[1]++);
-+                      if (passcnt[0] > passcnt[1])
-+                              passcnt[0] = passcnt[1];
-+                      passcnt[1] = 0;
-+                      if (passcnt[0] > g_side)
-+                              passcnt[1] = passcnt[0] - g_side;
-+                      if (diff > (g_margin+1) && (passcnt[1] > 0 || 
passcnt[0] > 8)) {
-+                              g_margin = diff;
-+                              g_dqidly = dqidly;
-+                              g_dqsip  = dqsip;
-+                              g_side   = passcnt[0];
-+                      } else if (passcnt[1] > 1 && g_side < 8) {
-+                              if (diff > g_margin)
-+                                      g_margin = diff;
-+                              g_dqidly = dqidly;
-+                              g_dqsip  = dqsip;
-+                              g_side   = passcnt[0];
-+                      }
-+              }
-+      }
-+      reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
-+      ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
-+
-+}
-+static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param 
*param)
-+{
-+      u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
-+      bool status = false;
-+
-+      finetuneDQSI(ast);
-+      if (finetuneDQI_L(ast, param) == false)
-+              return status;
-+
-+CBR_START2:
-+      dllmin[0] = dllmin[1] = 0xff;
-+      dllmax[0] = dllmax[1] = 0x0;
-+      passcnt = 0;
-+      for (dlli = 0; dlli < 76; dlli++) {
-+              ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli 
<< 24));
-+              ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
-+              data = cbr_scan(ast);
-+              if (data != 0) {
-+                      if (data & 0x1) {
-+                              if (dllmin[0] > dlli) {
-+                                      dllmin[0] = dlli;
-+                              }
-+                              if (dllmax[0] < dlli) {
-+                                      dllmax[0] = dlli;
-+                              }
-+                      }
-+                      if (data & 0x2) {
-+                              if (dllmin[1] > dlli) {
-+                                      dllmin[1] = dlli;
-+                              }
-+                              if (dllmax[1] < dlli) {
-+                                      dllmax[1] = dlli;
-+                              }
-+                      }
-+                      passcnt++;
-+              } else if (passcnt >= CBR_THRESHOLD) {
-+                      break;
-+              }
-+      }
-+      if (retry++ > 10)
-+              goto CBR_DONE2;
-+      if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) {
-+              goto CBR_START2;
-+      }
-+      if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) {
-+              goto CBR_START2;
-+      }
-+      status = true;
-+CBR_DONE2:
-+      dlli  = (dllmin[1] + dllmax[1]) >> 1;
-+      dlli <<= 8;
-+      dlli += (dllmin[0] + dllmax[0]) >> 1;
-+      ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 
16));
-+      return status;
-+} /* CBRDLL2 */
-+
-+static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param 
*param)
-+{
-+      u32 trap, trap_AC2, trap_MRS;
-+
-+      ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
-+
-+      /* Ger trap info */
-+      trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
-+      trap_AC2  = 0x00020000 + (trap << 16);
-+      trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
-+      trap_MRS  = 0x00000010 + (trap << 4);
-+      trap_MRS |= ((trap & 0x2) << 18);
-+
-+      param->reg_MADJ       = 0x00034C4C;
-+      param->reg_SADJ       = 0x00001800;
-+      param->reg_DRV        = 0x000000F0;
-+      param->reg_PERIOD     = param->dram_freq;
-+      param->rodt           = 0;
-+
-+      switch (param->dram_freq) {
-+      case 336:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0190);
-+              param->wodt          = 0;
-+              param->reg_AC1       = 0x22202725;
-+              param->reg_AC2       = 0xAA007613 | trap_AC2;
-+              param->reg_DQSIC     = 0x000000BA;
-+              param->reg_MRS       = 0x04001400 | trap_MRS;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_IOZ       = 0x00000023;
-+              param->reg_DQIDLY    = 0x00000074;
-+              param->reg_FREQ      = 0x00004DC0;
-+              param->madj_max      = 96;
-+              param->dll2_finetune_step = 3;
-+              switch (param->dram_chipid) {
-+              default:
-+              case AST_DRAM_512Mx16:
-+              case AST_DRAM_1Gx16:
-+                      param->reg_AC2   = 0xAA007613 | trap_AC2;
-+                      break;
-+              case AST_DRAM_2Gx16:
-+                      param->reg_AC2   = 0xAA00761C | trap_AC2;
-+                      break;
-+              case AST_DRAM_4Gx16:
-+                      param->reg_AC2   = 0xAA007636 | trap_AC2;
-+                      break;
-+              }
-+              break;
-+      default:
-+      case 396:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
-+              param->wodt          = 1;
-+              param->reg_AC1       = 0x33302825;
-+              param->reg_AC2       = 0xCC009617 | trap_AC2;
-+              param->reg_DQSIC     = 0x000000E2;
-+              param->reg_MRS       = 0x04001600 | trap_MRS;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DRV       = 0x000000FA;
-+              param->reg_DQIDLY    = 0x00000089;
-+              param->reg_FREQ      = 0x00005040;
-+              param->madj_max      = 96;
-+              param->dll2_finetune_step = 4;
-+
-+              switch (param->dram_chipid) {
-+              default:
-+              case AST_DRAM_512Mx16:
-+              case AST_DRAM_1Gx16:
-+                      param->reg_AC2   = 0xCC009617 | trap_AC2;
-+                      break;
-+              case AST_DRAM_2Gx16:
-+                      param->reg_AC2   = 0xCC009622 | trap_AC2;
-+                      break;
-+              case AST_DRAM_4Gx16:
-+                      param->reg_AC2   = 0xCC00963F | trap_AC2;
-+                      break;
-+              }
-+              break;
-+
-+      case 408:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
-+              param->wodt          = 1;
-+              param->reg_AC1       = 0x33302825;
-+              param->reg_AC2       = 0xCC009617 | trap_AC2;
-+              param->reg_DQSIC     = 0x000000E2;
-+              param->reg_MRS       = 0x04001600 | trap_MRS;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_IOZ       = 0x00000023;
-+              param->reg_DRV       = 0x000000FA;
-+              param->reg_DQIDLY    = 0x00000089;
-+              param->reg_FREQ      = 0x000050C0;
-+              param->madj_max      = 96;
-+              param->dll2_finetune_step = 4;
-+
-+              switch (param->dram_chipid) {
-+              default:
-+              case AST_DRAM_512Mx16:
-+              case AST_DRAM_1Gx16:
-+                      param->reg_AC2   = 0xCC009617 | trap_AC2;
-+                      break;
-+              case AST_DRAM_2Gx16:
-+                      param->reg_AC2   = 0xCC009622 | trap_AC2;
-+                      break;
-+              case AST_DRAM_4Gx16:
-+                      param->reg_AC2   = 0xCC00963F | trap_AC2;
-+                      break;
-+              }
-+
-+              break;
-+      case 456:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0230);
-+              param->wodt          = 0;
-+              param->reg_AC1       = 0x33302926;
-+              param->reg_AC2       = 0xCD44961A;
-+              param->reg_DQSIC     = 0x000000FC;
-+              param->reg_MRS       = 0x00081830;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_IOZ       = 0x00000045;
-+              param->reg_DQIDLY    = 0x00000097;
-+              param->reg_FREQ      = 0x000052C0;
-+              param->madj_max      = 88;
-+              param->dll2_finetune_step = 4;
-+              break;
-+      case 504:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0270);
-+              param->wodt          = 1;
-+              param->reg_AC1       = 0x33302926;
-+              param->reg_AC2       = 0xDE44A61D;
-+              param->reg_DQSIC     = 0x00000117;
-+              param->reg_MRS       = 0x00081A30;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_IOZ       = 0x070000BB;
-+              param->reg_DQIDLY    = 0x000000A0;
-+              param->reg_FREQ      = 0x000054C0;
-+              param->madj_max      = 79;
-+              param->dll2_finetune_step = 4;
-+              break;
-+      case 528:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0290);
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x33302926;
-+              param->reg_AC2       = 0xEF44B61E;
-+              param->reg_DQSIC     = 0x00000125;
-+              param->reg_MRS       = 0x00081A30;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x000000F5;
-+              param->reg_IOZ       = 0x00000023;
-+              param->reg_DQIDLY    = 0x00000088;
-+              param->reg_FREQ      = 0x000055C0;
-+              param->madj_max      = 76;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 576:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0140);
-+              param->reg_MADJ      = 0x00136868;
-+              param->reg_SADJ      = 0x00004534;
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x33302A37;
-+              param->reg_AC2       = 0xEF56B61E;
-+              param->reg_DQSIC     = 0x0000013F;
-+              param->reg_MRS       = 0x00101A50;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x000000FA;
-+              param->reg_IOZ       = 0x00000023;
-+              param->reg_DQIDLY    = 0x00000078;
-+              param->reg_FREQ      = 0x000057C0;
-+              param->madj_max      = 136;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 600:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
-+              param->reg_MADJ      = 0x00136868;
-+              param->reg_SADJ      = 0x00004534;
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x32302A37;
-+              param->reg_AC2       = 0xDF56B61F;
-+              param->reg_DQSIC     = 0x0000014D;
-+              param->reg_MRS       = 0x00101A50;
-+              param->reg_EMRS      = 0x00000004;
-+              param->reg_DRV       = 0x000000F5;
-+              param->reg_IOZ       = 0x00000023;
-+              param->reg_DQIDLY    = 0x00000078;
-+              param->reg_FREQ      = 0x000058C0;
-+              param->madj_max      = 132;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 624:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0160);
-+              param->reg_MADJ      = 0x00136868;
-+              param->reg_SADJ      = 0x00004534;
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x32302A37;
-+              param->reg_AC2       = 0xEF56B621;
-+              param->reg_DQSIC     = 0x0000015A;
-+              param->reg_MRS       = 0x02101A50;
-+              param->reg_EMRS      = 0x00000004;
-+              param->reg_DRV       = 0x000000F5;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DQIDLY    = 0x00000078;
-+              param->reg_FREQ      = 0x000059C0;
-+              param->madj_max      = 128;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      } /* switch freq */
-+
-+      switch (param->dram_chipid) {
-+      case AST_DRAM_512Mx16:
-+              param->dram_config = 0x130;
-+              break;
-+      default:
-+      case AST_DRAM_1Gx16:
-+              param->dram_config = 0x131;
-+              break;
-+      case AST_DRAM_2Gx16:
-+              param->dram_config = 0x132;
-+              break;
-+      case AST_DRAM_4Gx16:
-+              param->dram_config = 0x133;
-+              break;
-+      } /* switch size */
-+
-+      switch (param->vram_size) {
-+      default:
-+      case AST_VIDMEM_SIZE_8M:
-+              param->dram_config |= 0x00;
-+              break;
-+      case AST_VIDMEM_SIZE_16M:
-+              param->dram_config |= 0x04;
-+              break;
-+      case AST_VIDMEM_SIZE_32M:
-+              param->dram_config |= 0x08;
-+              break;
-+      case AST_VIDMEM_SIZE_64M:
-+              param->dram_config |= 0x0c;
-+              break;
-+      }
-+
-+}
-+
-+static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param 
*param)
-+{
-+      u32 data, data2, retry = 0;
-+
-+ddr3_init_start:
-+      ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
-+      ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
-+      ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
-+      udelay(10);
-+      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
-+      ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
-+      udelay(10);
-+      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
-+      udelay(10);
-+
-+      ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
-+      ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
-+      ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
-+      ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
-+      ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
-+      ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
-+      ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
-+      ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
-+      ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
-+      ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
-+      ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
-+      ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0054, 0);
-+      ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
-+      ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
-+      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
-+      /* Wait MCLK2X lock to MCLK */
-+      do {
-+              data = ast_mindwm(ast, 0x1E6E001C);
-+      } while (!(data & 0x08000000));
-+      data = ast_mindwm(ast, 0x1E6E001C);
-+      data = (data >> 8) & 0xff;
-+      while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
-+              data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
-+              if ((data2 & 0xff) > param->madj_max) {
-+                      break;
-+              }
-+              ast_moutdwm(ast, 0x1E6E0064, data2);
-+              if (data2 & 0x00100000) {
-+                      data2 = ((data2 & 0xff) >> 3) + 3;
-+              } else {
-+                      data2 = ((data2 & 0xff) >> 2) + 5;
-+              }
-+              data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
-+              data2 += data & 0xff;
-+              data = data | (data2 << 8);
-+              ast_moutdwm(ast, 0x1E6E0068, data);
-+              udelay(10);
-+              ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 
0xC0000);
-+              udelay(10);
-+              data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
-+              ast_moutdwm(ast, 0x1E6E0018, data);
-+              data = data | 0x200;
-+              ast_moutdwm(ast, 0x1E6E0018, data);
-+              do {
-+                      data = ast_mindwm(ast, 0x1E6E001C);
-+              } while (!(data & 0x08000000));
-+
-+              data = ast_mindwm(ast, 0x1E6E001C);
-+              data = (data >> 8) & 0xff;
-+      }
-+      ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
-+      data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
-+      ast_moutdwm(ast, 0x1E6E0018, data);
-+
-+      ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
-+      ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
-+      udelay(50);
-+      /* Mode Register Setting */
-+      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
-+      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
-+      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
-+      ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
-+
-+      ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
-+      data = 0;
-+      if (param->wodt) {
-+              data = 0x300;
-+      }
-+      if (param->rodt) {
-+              data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
-+      }
-+      ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
-+
-+      /* Calibrate the DQSI delay */
-+      if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
-+              goto ddr3_init_start;
-+
-+      ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
-+      /* ECC Memory Initialization */
-+#ifdef ECC
-+      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0070, 0x221);
-+      do {
-+              data = ast_mindwm(ast, 0x1E6E0070);
-+      } while (!(data & 0x00001000));
-+      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
-+#endif
-+
-+
-+}
-+
-+static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param 
*param)
-+{
-+      u32 trap, trap_AC2, trap_MRS;
-+
-+      ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
-+
-+      /* Ger trap info */
-+      trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
-+      trap_AC2  = (trap << 20) | (trap << 16);
-+      trap_AC2 += 0x00110000;
-+      trap_MRS  = 0x00000040 | (trap << 4);
-+
-+
-+      param->reg_MADJ       = 0x00034C4C;
-+      param->reg_SADJ       = 0x00001800;
-+      param->reg_DRV        = 0x000000F0;
-+      param->reg_PERIOD     = param->dram_freq;
-+      param->rodt           = 0;
-+
-+      switch (param->dram_freq) {
-+      case 264:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0130);
-+              param->wodt          = 0;
-+              param->reg_AC1       = 0x11101513;
-+              param->reg_AC2       = 0x78117011;
-+              param->reg_DQSIC     = 0x00000092;
-+              param->reg_MRS       = 0x00000842;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_DRV       = 0x000000F0;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DQIDLY    = 0x0000005A;
-+              param->reg_FREQ      = 0x00004AC0;
-+              param->madj_max      = 138;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 336:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0190);
-+              param->wodt          = 1;
-+              param->reg_AC1       = 0x22202613;
-+              param->reg_AC2       = 0xAA009016 | trap_AC2;
-+              param->reg_DQSIC     = 0x000000BA;
-+              param->reg_MRS       = 0x00000A02 | trap_MRS;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x000000FA;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DQIDLY    = 0x00000074;
-+              param->reg_FREQ      = 0x00004DC0;
-+              param->madj_max      = 96;
-+              param->dll2_finetune_step = 3;
-+              switch (param->dram_chipid) {
-+              default:
-+              case AST_DRAM_512Mx16:
-+                      param->reg_AC2   = 0xAA009012 | trap_AC2;
-+                      break;
-+              case AST_DRAM_1Gx16:
-+                      param->reg_AC2   = 0xAA009016 | trap_AC2;
-+                      break;
-+              case AST_DRAM_2Gx16:
-+                      param->reg_AC2   = 0xAA009023 | trap_AC2;
-+                      break;
-+              case AST_DRAM_4Gx16:
-+                      param->reg_AC2   = 0xAA00903B | trap_AC2;
-+                      break;
-+              }
-+              break;
-+      default:
-+      case 396:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
-+              param->wodt          = 1;
-+              param->rodt          = 0;
-+              param->reg_AC1       = 0x33302714;
-+              param->reg_AC2       = 0xCC00B01B | trap_AC2;
-+              param->reg_DQSIC     = 0x000000E2;
-+              param->reg_MRS       = 0x00000C02 | trap_MRS;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x000000FA;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DQIDLY    = 0x00000089;
-+              param->reg_FREQ      = 0x00005040;
-+              param->madj_max      = 96;
-+              param->dll2_finetune_step = 4;
-+
-+              switch (param->dram_chipid) {
-+              case AST_DRAM_512Mx16:
-+                      param->reg_AC2   = 0xCC00B016 | trap_AC2;
-+                      break;
-+              default:
-+              case AST_DRAM_1Gx16:
-+                      param->reg_AC2   = 0xCC00B01B | trap_AC2;
-+                      break;
-+              case AST_DRAM_2Gx16:
-+                      param->reg_AC2   = 0xCC00B02B | trap_AC2;
-+                      break;
-+              case AST_DRAM_4Gx16:
-+                      param->reg_AC2   = 0xCC00B03F | trap_AC2;
-+                      break;
-+              }
-+
-+              break;
-+
-+      case 408:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
-+              param->wodt          = 1;
-+              param->rodt          = 0;
-+              param->reg_AC1       = 0x33302714;
-+              param->reg_AC2       = 0xCC00B01B | trap_AC2;
-+              param->reg_DQSIC     = 0x000000E2;
-+              param->reg_MRS       = 0x00000C02 | trap_MRS;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x000000FA;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DQIDLY    = 0x00000089;
-+              param->reg_FREQ      = 0x000050C0;
-+              param->madj_max      = 96;
-+              param->dll2_finetune_step = 4;
-+
-+              switch (param->dram_chipid) {
-+              case AST_DRAM_512Mx16:
-+                      param->reg_AC2   = 0xCC00B016 | trap_AC2;
-+                      break;
-+              default:
-+              case AST_DRAM_1Gx16:
-+                      param->reg_AC2   = 0xCC00B01B | trap_AC2;
-+                      break;
-+              case AST_DRAM_2Gx16:
-+                      param->reg_AC2   = 0xCC00B02B | trap_AC2;
-+                      break;
-+              case AST_DRAM_4Gx16:
-+                      param->reg_AC2   = 0xCC00B03F | trap_AC2;
-+                      break;
-+              }
-+
-+              break;
-+      case 456:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0230);
-+              param->wodt          = 0;
-+              param->reg_AC1       = 0x33302815;
-+              param->reg_AC2       = 0xCD44B01E;
-+              param->reg_DQSIC     = 0x000000FC;
-+              param->reg_MRS       = 0x00000E72;
-+              param->reg_EMRS      = 0x00000000;
-+              param->reg_DRV       = 0x00000000;
-+              param->reg_IOZ       = 0x00000034;
-+              param->reg_DQIDLY    = 0x00000097;
-+              param->reg_FREQ      = 0x000052C0;
-+              param->madj_max      = 88;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 504:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0261);
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x33302815;
-+              param->reg_AC2       = 0xDE44C022;
-+              param->reg_DQSIC     = 0x00000117;
-+              param->reg_MRS       = 0x00000E72;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x0000000A;
-+              param->reg_IOZ       = 0x00000045;
-+              param->reg_DQIDLY    = 0x000000A0;
-+              param->reg_FREQ      = 0x000054C0;
-+              param->madj_max      = 79;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 528:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0120);
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x33302815;
-+              param->reg_AC2       = 0xEF44D024;
-+              param->reg_DQSIC     = 0x00000125;
-+              param->reg_MRS       = 0x00000E72;
-+              param->reg_EMRS      = 0x00000004;
-+              param->reg_DRV       = 0x000000F9;
-+              param->reg_IOZ       = 0x00000045;
-+              param->reg_DQIDLY    = 0x000000A7;
-+              param->reg_FREQ      = 0x000055C0;
-+              param->madj_max      = 76;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 552:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x43402915;
-+              param->reg_AC2       = 0xFF44E025;
-+              param->reg_DQSIC     = 0x00000132;
-+              param->reg_MRS       = 0x00000E72;
-+              param->reg_EMRS      = 0x00000040;
-+              param->reg_DRV       = 0x0000000A;
-+              param->reg_IOZ       = 0x00000045;
-+              param->reg_DQIDLY    = 0x000000AD;
-+              param->reg_FREQ      = 0x000056C0;
-+              param->madj_max      = 76;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      case 576:
-+              ast_moutdwm(ast, 0x1E6E2020, 0x0140);
-+              param->wodt          = 1;
-+              param->rodt          = 1;
-+              param->reg_AC1       = 0x43402915;
-+              param->reg_AC2       = 0xFF44E027;
-+              param->reg_DQSIC     = 0x0000013F;
-+              param->reg_MRS       = 0x00000E72;
-+              param->reg_EMRS      = 0x00000004;
-+              param->reg_DRV       = 0x000000F5;
-+              param->reg_IOZ       = 0x00000045;
-+              param->reg_DQIDLY    = 0x000000B3;
-+              param->reg_FREQ      = 0x000057C0;
-+              param->madj_max      = 76;
-+              param->dll2_finetune_step = 3;
-+              break;
-+      }
-+
-+      switch (param->dram_chipid) {
-+      case AST_DRAM_512Mx16:
-+              param->dram_config = 0x100;
-+              break;
-+      default:
-+      case AST_DRAM_1Gx16:
-+              param->dram_config = 0x121;
-+              break;
-+      case AST_DRAM_2Gx16:
-+              param->dram_config = 0x122;
-+              break;
-+      case AST_DRAM_4Gx16:
-+              param->dram_config = 0x123;
-+              break;
-+      } /* switch size */
-+
-+      switch (param->vram_size) {
-+      default:
-+      case AST_VIDMEM_SIZE_8M:
-+              param->dram_config |= 0x00;
-+              break;
-+      case AST_VIDMEM_SIZE_16M:
-+              param->dram_config |= 0x04;
-+              break;
-+      case AST_VIDMEM_SIZE_32M:
-+              param->dram_config |= 0x08;
-+              break;
-+      case AST_VIDMEM_SIZE_64M:
-+              param->dram_config |= 0x0c;
-+              break;
-+      }
-+}
-+
-+static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param 
*param)
-+{
-+      u32 data, data2, retry = 0;
-+
-+ddr2_init_start:
-+      ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
-+      ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
-+      ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
-+      ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
-+      udelay(10);
-+      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
-+      udelay(10);
-+
-+      ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
-+      ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
-+      ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
-+      ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
-+      ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
-+      ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
-+      ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
-+      ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
-+      ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
-+      ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
-+      ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
-+      ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0054, 0);
-+      ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
-+      ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
-+      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
-+
-+      /* Wait MCLK2X lock to MCLK */
-+      do {
-+              data = ast_mindwm(ast, 0x1E6E001C);
-+      } while (!(data & 0x08000000));
-+      data = ast_mindwm(ast, 0x1E6E001C);
-+      data = (data >> 8) & 0xff;
-+      while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
-+              data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
-+              if ((data2 & 0xff) > param->madj_max) {
-+                      break;
-+              }
-+              ast_moutdwm(ast, 0x1E6E0064, data2);
-+              if (data2 & 0x00100000) {
-+                      data2 = ((data2 & 0xff) >> 3) + 3;
-+              } else {
-+                      data2 = ((data2 & 0xff) >> 2) + 5;
-+              }
-+              data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
-+              data2 += data & 0xff;
-+              data = data | (data2 << 8);
-+              ast_moutdwm(ast, 0x1E6E0068, data);
-+              udelay(10);
-+              ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 
0xC0000);
-+              udelay(10);
-+              data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
-+              ast_moutdwm(ast, 0x1E6E0018, data);
-+              data = data | 0x200;
-+              ast_moutdwm(ast, 0x1E6E0018, data);
-+              do {
-+                      data = ast_mindwm(ast, 0x1E6E001C);
-+              } while (!(data & 0x08000000));
-+
-+              data = ast_mindwm(ast, 0x1E6E001C);
-+              data = (data >> 8) & 0xff;
-+      }
-+      ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
-+      data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
-+      ast_moutdwm(ast, 0x1E6E0018, data);
-+
-+      ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
-+      ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
-+      udelay(50);
-+      /* Mode Register Setting */
-+      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
-+      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
-+
-+      ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
-+      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
-+      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
-+      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
-+      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
-+
-+      ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
-+      data = 0;
-+      if (param->wodt) {
-+              data = 0x500;
-+      }
-+      if (param->rodt) {
-+              data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
-+      }
-+      ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
-+      ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
-+
-+      /* Calibrate the DQSI delay */
-+      if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
-+              goto ddr2_init_start;
-+
-+      /* ECC Memory Initialization */
-+#ifdef ECC
-+      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0070, 0x221);
-+      do {
-+              data = ast_mindwm(ast, 0x1E6E0070);
-+      } while (!(data & 0x00001000));
-+      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
-+      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
-+#endif
-+
-+}
-+
-+static void ast_init_dram_2300(struct drm_device *dev)
-+{
-+      struct ast_private *ast = dev->dev_private;
-+      struct ast2300_dram_param param;
-+      u32 temp;
-+      u8 reg;
-+
-+      reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-+      if ((reg & 0x80) == 0) {/* vga only */
-+              ast_write32(ast, 0xf004, 0x1e6e0000);
-+              ast_write32(ast, 0xf000, 0x1);
-+              ast_write32(ast, 0x12000, 0x1688a8a8);
-+              do {
-+                      ;
-+              } while (ast_read32(ast, 0x12000) != 0x1);
-+
-+              ast_write32(ast, 0x10000, 0xfc600309);
-+              do {
-+                      ;
-+              } while (ast_read32(ast, 0x10000) != 0x1);
-+
-+              /* Slow down CPU/AHB CLK in VGA only mode */
-+              temp = ast_read32(ast, 0x12008);
-+              temp |= 0x73;
-+              ast_write32(ast, 0x12008, temp);
-+
-+              param.dram_type = AST_DDR3;
-+              if (temp & 0x01000000)
-+                      param.dram_type = AST_DDR2;
-+              param.dram_chipid = ast->dram_type;
-+              param.dram_freq = ast->mclk;
-+              param.vram_size = ast->vram_size;
-+
-+              if (param.dram_type == AST_DDR3) {
-+                      get_ddr3_info(ast, &param);
-+                      ddr3_init(ast, &param);
-+              } else {
-+                      get_ddr2_info(ast, &param);
-+                      ddr2_init(ast, &param);
-+              }
-+
-+              temp = ast_mindwm(ast, 0x1e6e2040);
-+              ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
-+      }
-+
-+      /* wait ready */
-+      do {
-+              reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-+      } while ((reg & 0x40) == 0);
-+}
-+
-diff --git a/src/drivers/aspeed/common/ast_tables.h 
b/src/drivers/aspeed/common/ast_tables.h
-new file mode 100644
-index 0000000..3608d5a
---- /dev/null
-+++ b/src/drivers/aspeed/common/ast_tables.h
-@@ -0,0 +1,305 @@
-+/*
-+ * Copyright (c) 2005 ASPEED Technology Inc.
-+ *
-+ * Permission to use, copy, modify, distribute, and sell this software and its
-+ * documentation for any purpose is hereby granted without fee, provided that
-+ * the above copyright notice appear in all copies and that both that
-+ * copyright notice and this permission notice appear in supporting
-+ * documentation, and that the name of the authors not be used in
-+ * advertising or publicity pertaining to distribution of the software without
-+ * specific, written prior permission.  The authors makes no representations
-+ * about the suitability of this software for any purpose.  It is provided
-+ * "as is" without express or implied warranty.
-+ *
-+ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-+ * PERFORMANCE OF THIS SOFTWARE.
-+ */
-+/* Ported from xf86-video-ast driver */
-+
-+#ifndef AST_TABLES_H
-+#define AST_TABLES_H
-+
-+/* Std. Table Index Definition */
-+#define TextModeIndex         0
-+#define EGAModeIndex          1
-+#define VGAModeIndex          2
-+#define HiCModeIndex          3
-+#define TrueCModeIndex                4
-+
-+#define Charx8Dot               0x00000001
-+#define HalfDCLK                0x00000002
-+#define DoubleScanMode          0x00000004
-+#define LineCompareOff          0x00000008
-+#define HBorder                 0x00000020
-+#define VBorder                 0x00000010
-+#define WideScreenMode                0x00000100
-+#define NewModeInfo           0x00000200
-+#define NHSync                        0x00000400
-+#define PHSync                        0x00000800
-+#define NVSync                        0x00001000
-+#define PVSync                        0x00002000
-+#define SyncPP                        (PVSync | PHSync)
-+#define SyncPN                        (PVSync | NHSync)
-+#define SyncNP                        (NVSync | PHSync)
-+#define SyncNN                        (NVSync | NHSync)
-+
-+/* DCLK Index */
-+#define VCLK25_175                    0x00
-+#define VCLK28_322                    0x01
-+#define VCLK31_5                      0x02
-+#define VCLK36                        0x03
-+#define VCLK40                        0x04
-+#define VCLK49_5                      0x05
-+#define VCLK50                        0x06
-+#define VCLK56_25                     0x07
-+#define VCLK65                        0x08
-+#define VCLK75                        0x09
-+#define VCLK78_75                     0x0A
-+#define VCLK94_5                      0x0B
-+#define VCLK108                       0x0C
-+#define VCLK135                       0x0D
-+#define VCLK157_5                     0x0E
-+#define VCLK162                       0x0F
-+/* #define VCLK193_25                 0x10 */
-+#define VCLK154               0x10
-+#define VCLK83_5              0x11
-+#define VCLK106_5             0x12
-+#define VCLK146_25            0x13
-+#define VCLK148_5             0x14
-+#define VCLK71                0x15
-+#define VCLK88_75             0x16
-+#define VCLK119               0x17
-+#define VCLK85_5              0x18
-+#define VCLK97_75                     0x19
-+#define VCLK118_25                    0x1A
-+
-+static struct ast_vbios_dclk_info dclk_table[] = {
-+      {0x2C, 0xE7, 0x03},                                     /* 00: 
VCLK25_175       */
-+      {0x95, 0x62, 0x03},                                     /* 01: 
VCLK28_322       */
-+      {0x67, 0x63, 0x01},                                     /* 02: VCLK31_5 
        */
-+      {0x76, 0x63, 0x01},                                     /* 03: VCLK36   
        */
-+      {0xEE, 0x67, 0x01},                                     /* 04: VCLK40   
        */
-+      {0x82, 0x62, 0x01},                             /* 05: VCLK49_5         
*/
-+      {0xC6, 0x64, 0x01},                                     /* 06: VCLK50   
        */
-+      {0x94, 0x62, 0x01},                                     /* 07: 
VCLK56_25        */
-+      {0x80, 0x64, 0x00},                                     /* 08: VCLK65   
        */
-+      {0x7B, 0x63, 0x00},                                     /* 09: VCLK75   
        */
-+      {0x67, 0x62, 0x00},                                     /* 0A: 
VCLK78_75        */
-+      {0x7C, 0x62, 0x00},                                     /* 0B: VCLK94_5 
        */
-+      {0x8E, 0x62, 0x00},                                     /* 0C: VCLK108  
        */
-+      {0x85, 0x24, 0x00},                                     /* 0D: VCLK135  
        */
-+      {0x67, 0x22, 0x00},                                     /* 0E: 
VCLK157_5        */
-+      {0x6A, 0x22, 0x00},                                     /* 0F: VCLK162  
        */
-+      {0x4d, 0x4c, 0x80},                                     /* 10: VCLK154  
        */
-+      {0xa7, 0x78, 0x80},                                     /* 11: VCLK83.5 
        */
-+      {0x28, 0x49, 0x80},                                     /* 12: 
VCLK106.5        */
-+      {0x37, 0x49, 0x80},                                     /* 13: 
VCLK146.25       */
-+      {0x1f, 0x45, 0x80},                                     /* 14: 
VCLK148.5        */
-+      {0x47, 0x6c, 0x80},                                     /* 15: VCLK71   
    */
-+      {0x25, 0x65, 0x80},                                     /* 16: 
VCLK88.75    */
-+      {0x77, 0x58, 0x80},                                     /* 17: VCLK119  
    */
-+      {0x32, 0x67, 0x80},                                 /* 18: VCLK85_5     
*/
-+      {0x6a, 0x6d, 0x80},                                     /* 19: 
VCLK97_75        */
-+      {0x3b, 0x2c, 0x81},                                     /* 1A: 
VCLK118_25       */
-+};
-+
-+static struct ast_vbios_stdtable vbios_stdtable[] = {
-+      /* MD_2_3_400 */
-+      {
-+              0x67,
-+              {0x00,0x03,0x00,0x02},
-+              {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-+               0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
-+               0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
-+               0xff},
-+              {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-+               0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-+               0x0c,0x00,0x0f,0x08},
-+              {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-+               0xff}
-+      },
-+      /* Mode12/ExtEGATable */
-+      {
-+              0xe3,
-+              {0x01,0x0f,0x00,0x06},
-+              {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
-+               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-+               0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,
-+               0xff},
-+              {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-+               0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-+               0x01,0x00,0x0f,0x00},
-+              {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-+               0xff}
-+      },
-+      /* ExtVGATable */
-+      {
-+              0x2f,
-+              {0x01,0x0f,0x00,0x0e},
-+              {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
-+               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-+               0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
-+               0xff},
-+              {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-+               0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-+               0x01,0x00,0x00,0x00},
-+              {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
-+               0xff}
-+      },
-+      /* ExtHiCTable */
-+      {
-+              0x2f,
-+              {0x01,0x0f,0x00,0x0e},
-+              {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
-+               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-+               0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
-+               0xff},
-+              {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-+               0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-+               0x01,0x00,0x00,0x00},
-+              {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-+               0xff}
-+      },
-+      /* ExtTrueCTable */
-+      {
-+              0x2f,
-+              {0x01,0x0f,0x00,0x0e},
-+              {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
-+               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-+               0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
-+               0xff},
-+              {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-+               0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-+               0x01,0x00,0x00,0x00},
-+              {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-+               0xff}
-+      },
-+};
-+
-+static struct ast_vbios_enhtable res_640x480[] = {
-+      { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175,  /* 60Hz */
-+        (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E },
-+      { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5,   /* 72Hz */
-+        (SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2E  },
-+      { 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5,   /* 75Hz */
-+        (SyncNN | Charx8Dot) , 75, 3, 0x2E },
-+      { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36,             /* 85Hz */
-+        (SyncNN | Charx8Dot) , 85, 4, 0x2E },
-+      { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36,             /* end */
-+        (SyncNN | Charx8Dot) , 0xFF, 4, 0x2E },
-+};
-+
-+static struct ast_vbios_enhtable res_800x600[] = {
-+      {1024, 800, 24, 72, 625, 600, 1, 2, VCLK36,             /* 56Hz */
-+       (SyncPP | Charx8Dot), 56, 1, 0x30 },
-+      {1056, 800, 40, 128, 628, 600, 1, 4, VCLK40,    /* 60Hz */
-+       (SyncPP | Charx8Dot), 60, 2, 0x30 },
-+      {1040, 800, 56, 120, 666, 600, 37, 6, VCLK50,   /* 72Hz */
-+       (SyncPP | Charx8Dot), 72, 3, 0x30 },
-+      {1056, 800, 16, 80, 625, 600, 1, 3, VCLK49_5,   /* 75Hz */
-+       (SyncPP | Charx8Dot), 75, 4, 0x30 },
-+      {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25,  /* 85Hz */
-+       (SyncPP | Charx8Dot), 84, 5, 0x30 },
-+      {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25,  /* end */
-+       (SyncPP | Charx8Dot), 0xFF, 5, 0x30 },
-+};
-+
-+
-+static struct ast_vbios_enhtable res_1024x768[] = {
-+      {1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65,   /* 60Hz */
-+       (SyncNN | Charx8Dot), 60, 1, 0x31 },
-+      {1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75,   /* 70Hz */
-+       (SyncNN | Charx8Dot), 70, 2, 0x31 },
-+      {1312, 1024, 16, 96, 800, 768, 1, 3, VCLK78_75, /* 75Hz */
-+       (SyncPP | Charx8Dot), 75, 3, 0x31 },
-+      {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5,  /* 85Hz */
-+       (SyncPP | Charx8Dot), 84, 4, 0x31 },
-+      {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5,  /* end */
-+       (SyncPP | Charx8Dot), 0xFF, 4, 0x31 },
-+};
-+
-+static struct ast_vbios_enhtable res_1280x1024[] = {
-+      {1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108,        /* 60Hz */
-+       (SyncPP | Charx8Dot), 60, 1, 0x32 },
-+      {1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135,        /* 75Hz */
-+       (SyncPP | Charx8Dot), 75, 2, 0x32 },
-+      {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5,      /* 85Hz */
-+       (SyncPP | Charx8Dot), 85, 3, 0x32 },
-+      {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5,      /* end */
-+       (SyncPP | Charx8Dot), 0xFF, 3, 0x32 },
-+};
-+
-+static struct ast_vbios_enhtable res_1600x1200[] = {
-+      {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162,        /* 60Hz */
-+       (SyncPP | Charx8Dot), 60, 1, 0x33 },
-+      {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162,        /* end */
-+       (SyncPP | Charx8Dot), 0xFF, 1, 0x33 },
-+};
-+
-+/* 16:9 */
-+static struct ast_vbios_enhtable res_1360x768[] = {
-+      {1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,          /* 60Hz */
-+       (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x39 },
-+      {1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,          /* end */
-+       (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 1, 0x39 },
-+};
-+
-+static struct ast_vbios_enhtable res_1600x900[] = {
-+      {1760, 1600, 48, 32, 926,  900, 3, 5, VCLK97_75,        /* 60Hz CVT RB 
*/
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x3A },
-+      {2112, 1600, 88,168, 934,  900, 3, 5, VCLK118_25,       /* 60Hz CVT */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x3A },
-+      {2112, 1600, 88,168, 934,  900, 3, 5, VCLK118_25,       /* 60Hz CVT */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x3A },
-+};
-+
-+static struct ast_vbios_enhtable res_1920x1080[] = {
-+      {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x38 },
-+      {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 1, 0x38 },
-+};
-+
-+
-+/* 16:10 */
-+static struct ast_vbios_enhtable res_1280x800[] = {
-+      {1440, 1280, 48, 32,  823,  800, 3, 6, VCLK71,  /* 60Hz RB */
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x35 },
-+      {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x35 },
-+      {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x35 },
-+
-+};
-+
-+static struct ast_vbios_enhtable res_1440x900[] = {
-+      {1600, 1440, 48, 32,  926,  900, 3, 6, VCLK88_75,       /* 60Hz RB */
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x36 },
-+      {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x36 },
-+      {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x36 },
-+};
-+
-+static struct ast_vbios_enhtable res_1680x1050[] = {
-+      {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x37 },
-+      {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25,      /* 60Hz */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x37 },
-+      {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25,      /* 60Hz */
-+       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x37 },
-+};
-+
-+static struct ast_vbios_enhtable res_1920x1200[] = {
-+      {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x34 },
-+      {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */
-+       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 1, 0x34 },
-+};
-+
-+#endif
-diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
-index dcb8a42..fcaf4aa 100644
---- a/src/include/device/pci_ids.h
-+++ b/src/include/device/pci_ids.h
-@@ -1991,6 +1991,9 @@
- #define PCI_DEVICE_ID_XGI_20          0x0020
- #define PCI_DEVICE_ID_XGI_40          0x0040
- 
-+#define PCI_VENDOR_ID_ASPEED          0x1a03
-+#define PCI_DEVICE_ID_ASPEED_AST2050_VGA      0x2000
-+
- #define PCI_VENDOR_ID_SYMPHONY                0x1c1c
- #define PCI_DEVICE_ID_SYMPHONY_101    0x0001
- 
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0004-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
 
b/resources/libreboot/patch/kgpe-d16/0004-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
new file mode 100644
index 0000000..ccb52ae
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0004-drivers-i2c-w83795-Add-option-to-use-auxiliary-SMBUS.patch
@@ -0,0 +1,68 @@
+From 8996dda2293b74ec84251cc2eefb7722acd6bd6b Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 17 Oct 2015 04:37:10 -0500
+Subject: [PATCH 004/143] drivers/i2c/w83795: Add option to use auxiliary
+ SMBUS controller
+
+Change-Id: I5a9b5eba992853b84b0cb6c3a1764edf42ac49b2
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/drivers/i2c/w83795/chip.h   |    7 +++++++
+ src/drivers/i2c/w83795/w83795.c |   17 +++++++++++++++++
+ 2 files changed, 24 insertions(+)
+
+diff --git a/src/drivers/i2c/w83795/chip.h b/src/drivers/i2c/w83795/chip.h
+index c8a42ea..9a3f847 100644
+--- a/src/drivers/i2c/w83795/chip.h
++++ b/src/drivers/i2c/w83795/chip.h
+@@ -139,4 +139,11 @@ struct drivers_i2c_w83795_config {
+       uint8_t fan6_duty;                      /* % of full speed (0-100) */
+       uint8_t fan7_duty;                      /* % of full speed (0-100) */
+       uint8_t fan8_duty;                      /* % of full speed (0-100) */
++
++      uint8_t smbus_aux;                      /* 0   == device located on 
primary SMBUS,
++                                               * 1   == device located on 
first auxiliary
++                                               *        SMBUS channel,
++                                               * <n> == device located on <n> 
auxiliary
++                                               *        SMBUS channel
++                                               */
+ };
+diff --git a/src/drivers/i2c/w83795/w83795.c b/src/drivers/i2c/w83795/w83795.c
+index 0af272f..0f82e1c 100644
+--- a/src/drivers/i2c/w83795/w83795.c
++++ b/src/drivers/i2c/w83795/w83795.c
+@@ -141,7 +141,18 @@ static void w83795_init(struct device *dev, 
w83795_fan_mode_t mode, u8 dts_src)
+       uint8_t val;
+       uint16_t limit_value;
+ 
++#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS)
++      uint8_t smbus_aux_channel_prev = smbus_current_aux_channel();
++      smbus_switch_to_aux_channel(config->smbus_aux);
++      printk(BIOS_DEBUG, "Set SMBUS controller to channel %d\n", 
config->smbus_aux);
++#endif
++
+       if (smbus_read_byte(dev, 0x00) < 0) {
++#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS)
++              /* Restore SMBUS channel setting */
++              smbus_switch_to_aux_channel(smbus_aux_channel_prev);
++              printk(BIOS_DEBUG, "Set SMBUS controller to channel %d\n", 
smbus_aux_channel_prev);
++#endif
+               printk(BIOS_ERR, "W83795G/ADG Nuvoton H/W Monitor not found\n");
+               return;
+       }
+@@ -332,6 +343,12 @@ static void w83795_init(struct device *dev, 
w83795_fan_mode_t mode, u8 dts_src)
+       val = w83795_read(dev, W83795_REG_CONFIG);
+       val |= W83795_REG_CONFIG_START;
+       w83795_write(dev, W83795_REG_CONFIG, val);
++
++#if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS)
++      /* Restore SMBUS channel setting */
++      smbus_switch_to_aux_channel(smbus_aux_channel_prev);
++      printk(BIOS_DEBUG, "Set SMBUS controller to channel %d\n", 
smbus_aux_channel_prev);
++#endif
+ }
+ 
+ static void w83795_hwm_init(struct device *dev)
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0005-mainboard-Update-mainboards-using-the-w83795-sensor-.patch
 
b/resources/libreboot/patch/kgpe-d16/0005-mainboard-Update-mainboards-using-the-w83795-sensor-.patch
new file mode 100644
index 0000000..e848f49
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0005-mainboard-Update-mainboards-using-the-w83795-sensor-.patch
@@ -0,0 +1,323 @@
+From 2b9d5ca0b29cbe6e1600879b5cc731c2c4cb106d Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Thu, 22 Oct 2015 02:53:39 -0500
+Subject: [PATCH 005/143] mainboard: Update mainboards using the w83795 sensor
+ device
+
+Update mainboards using the w83795 sensor device with sane default
+values.  Note that in some cases the defaults may vary from the
+defaults provided by the old driver, for example the default fan
+speeds and control modes have changed as I do not have any information
+on the correct sensor to fan mappings for these boards.
+
+Change-Id: Id2ad6222d7a0f29483b022fa097d7d098c6b4122
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/mainboard/supermicro/h8qgi/devicetree.cb |   89 ++++++++++++++++++++++++++
+ src/mainboard/supermicro/h8scm/devicetree.cb |   89 ++++++++++++++++++++++++++
+ src/mainboard/tyan/s8226/devicetree.cb       |   89 ++++++++++++++++++++++++++
+ 3 files changed, 267 insertions(+)
+
+diff --git a/src/mainboard/supermicro/h8qgi/devicetree.cb 
b/src/mainboard/supermicro/h8qgi/devicetree.cb
+index 59740c9..6c3ee90 100644
+--- a/src/mainboard/supermicro/h8qgi/devicetree.cb
++++ b/src/mainboard/supermicro/h8qgi/devicetree.cb
+@@ -107,6 +107,95 @@ chip northbridge/amd/agesa/family15/root_complex
+                                                       end
+                                               end #superio/winbond/w83627dhg
+                                               chip drivers/i2c/w83795
++                                                      register "fanin_ctl1" = 
"0xff"                  # Enable monitoring of FANIN1 - FANIN8
++                                                      register "fanin_ctl2" = 
"0x00"                  # Connect FANIN11 - FANIN14 to alternate functions
++                                                      register "temp_ctl1" = 
"0x2a"                   # Enable monitoring of DTS, VSEN12, and VSEN13
++                                                      register "temp_ctl2" = 
"0x01"                   # Enable monitoring of TD1/TR1
++                                                      register "temp_dtse" = 
"0x03"                   # Enable DTS1 and DTS2
++                                                      register "volt_ctl1" = 
"0xff"                   # Enable monitoring of VSEN1 - VSEN8
++                                                      register "volt_ctl2" = 
"0xf7"                   # Enable monitoring of VSEN9 - VSEN11, 3VDD, 3VSB, and 
VBAT
++                                                      register 
"temp1_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp1)
++                                                      register 
"temp2_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp2)
++                                                      register 
"temp3_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp3)
++                                                      register 
"temp4_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp4)
++                                                      register 
"temp5_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp5)
++                                                      register 
"temp6_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp6)
++                                                      register 
"temp1_source_select" = "0x00"         # Use TD1/TR1 as data source for Temp1
++                                                      register 
"temp2_source_select" = "0x00"         # Use TD2/TR2 as data source for Temp2
++                                                      register 
"temp3_source_select" = "0x00"         # Use TD3/TR3 as data source for Temp3
++                                                      register 
"temp4_source_select" = "0x00"         # Use TD4/TR4 as data source for Temp4
++                                                      register 
"temp5_source_select" = "0x00"         # Use TR5 as data source for Temp5
++                                                      register 
"temp6_source_select" = "0x00"         # Use TR6 as data source for Temp6
++                                                      register 
"tr1_critical_temperature" = "85"      # Set TD1/TR1 critical temperature to 
85°C
++                                                      register 
"tr1_critical_hysteresis" = "80"       # Set TD1/TR1 critical hysteresis 
temperature to 80°C
++                                                      register 
"tr1_warning_temperature" = "70"       # Set TD1/TR1 warning temperature to 70°C
++                                                      register 
"tr1_warning_hysteresis" = "65"        # Set TD1/TR1 warning hysteresis 
temperature to 65°C
++                                                      register 
"dts_critical_temperature" = "85"      # Set DTS (CPU) critical temperature to 
85°C
++                                                      register 
"dts_critical_hysteresis" = "80"       # Set DTS (CPU) critical hysteresis 
temperature to 80°C
++                                                      register 
"dts_warning_temperature" = "70"       # Set DTS (CPU) warning temperature to 
70°C
++                                                      register 
"dts_warning_hysteresis" = "65"        # Set DTS (CPU) warning hysteresis 
temperature to 65°C
++                                                      register 
"temp1_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp2_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp3_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp4_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp5_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp6_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp1_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp2_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp3_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp4_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp5_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp6_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register "fan1_nonstop" 
= "7"                   # Set Fan 1 minimum speed
++                                                      register "fan2_nonstop" 
= "7"                   # Set Fan 2 minimum speed
++                                                      register "fan3_nonstop" 
= "7"                   # Set Fan 3 minimum speed
++                                                      register "fan4_nonstop" 
= "7"                   # Set Fan 4 minimum speed
++                                                      register "fan5_nonstop" 
= "7"                   # Set Fan 5 minimum speed
++                                                      register "fan6_nonstop" 
= "7"                   # Set Fan 6 minimum speed
++                                                      register "fan7_nonstop" 
= "7"                   # Set Fan 7 minimum speed
++                                                      register "fan8_nonstop" 
= "7"                   # Set Fan 8 minimum speed
++                                                      register 
"default_speed" = "100"                # All fans to full speed on power up
++                                                      register "fan1_duty" = 
"100"                    # Fan 1 to full speed
++                                                      register "fan2_duty" = 
"100"                    # Fan 2 to full speed
++                                                      register "fan3_duty" = 
"100"                    # Fan 3 to full speed
++                                                      register "fan4_duty" = 
"100"                    # Fan 4 to full speed
++                                                      register "fan5_duty" = 
"100"                    # Fan 5 to full speed
++                                                      register "fan6_duty" = 
"100"                    # Fan 6 to full speed
++                                                      register "fan7_duty" = 
"100"                    # Fan 7 to full speed
++                                                      register "fan8_duty" = 
"100"                    # Fan 8 to full speed
++                                                      register 
"vcore1_high_limit_mv" = "1500"        # VCORE1 (Node 0) high limit to 1.5V
++                                                      register 
"vcore1_low_limit_mv" = "900"          # VCORE1 (Node 0) low limit to 0.9V
++                                                      register 
"vcore2_high_limit_mv" = "1500"        # VCORE2 (Node 1) high limit to 1.5V
++                                                      register 
"vcore2_low_limit_mv" = "900"          # VCORE2 (Node 1) low limit to 0.9V
++                                                      register 
"vsen3_high_limit_mv" = "1600"         # VSEN1 (Node 0 RAM voltage) high limit 
to 1.6V
++                                                      register 
"vsen3_low_limit_mv" = "1100"          # VSEN1 (Node 0 RAM voltage) low limit 
to 1.1V
++                                                      register 
"vsen4_high_limit_mv" = "1600"         # VSEN2 (Node 1 RAM voltage) high limit 
to 1.6V
++                                                      register 
"vsen4_low_limit_mv" = "1100"          # VSEN2 (Node 1 RAM voltage) low limit 
to 1.1V
++                                                      register 
"vsen5_high_limit_mv" = "1250"         # VSEN5 (Node 0 HT link voltage) high 
limit to 1.25V
++                                                      register 
"vsen5_low_limit_mv" = "1150"          # VSEN5 (Node 0 HT link voltage) low 
limit to 1.15V
++                                                      register 
"vsen6_high_limit_mv" = "1250"         # VSEN6 (Node 1 HT link voltage) high 
limit to 1.25V
++                                                      register 
"vsen6_low_limit_mv" = "1150"          # VSEN6 (Node 1 HT link voltage) low 
limit to 1.15V
++                                                      register 
"vsen7_high_limit_mv" = "1150"         # VSEN7 (Northbridge core voltage) high 
limit to 1.15V
++                                                      register 
"vsen7_low_limit_mv" = "1050"          # VSEN7 (Northbridge core voltage) low 
limit to 1.05V
++                                                      register 
"vsen8_high_limit_mv" = "1900"         # VSEN8 (+1.8V) high limit to 1.9V
++                                                      register 
"vsen8_low_limit_mv" = "1700"          # VSEN8 (+1.8V) low limit to 1.7V
++                                                      register 
"vsen9_high_limit_mv" = "1250"         # VSEN9 (+1.2V) high limit to 1.25V
++                                                      register 
"vsen9_low_limit_mv" = "1150"          # VSEN9 (+1.2V) low limit to 1.15V
++                                                      register 
"vsen10_high_limit_mv" = "1150"        # VSEN10 (+1.1V) high limit to 1.15V
++                                                      register 
"vsen10_low_limit_mv" = "1050"         # VSEN10 (+1.1V) low limit to 1.05V
++                                                      register 
"vsen11_high_limit_mv" = "1625"        # VSEN11 (5VSB, scaling factor ~3.2) 
high limit to 5.2V
++                                                      register 
"vsen11_low_limit_mv" = "1500"         # VSEN11 (5VSB, scaling factor ~3.2) low 
limit to 4.8V
++                                                      register 
"vsen12_high_limit_mv" = "1083"        # VSEN12 (+12V, scaling factor ~12) high 
limit to 13V
++                                                      register 
"vsen12_low_limit_mv" = "917"          # VSEN12 (+12V, scaling factor ~12) low 
limit to 11V
++                                                      register 
"vsen13_high_limit_mv" = "1625"        # VSEN13 (+5V, scaling factor ~3.2) high 
limit to 5.2V
++                                                      register 
"vsen13_low_limit_mv" = "1500"         # VSEN13 (+5V, scaling factor ~3.2) low 
limit to 4.8V
++                                                      register 
"vdd_high_limit_mv" = "3500"           # 3VDD high limit to 3.5V
++                                                      register 
"vdd_low_limit_mv" = "3100"            # 3VDD low limit to 3.1V
++                                                      register 
"vsb_high_limit_mv" = "3500"           # 3VSB high limit to 3.5V
++                                                      register 
"vsb_low_limit_mv" = "3100"            # 3VSB low limit to 3.1V
++                                                      register 
"vbat_high_limit_mv" = "3500"          # VBAT (+3V) high limit to 3.5V
++                                                      register 
"vbat_low_limit_mv" = "2500"           # VBAT (+3V) low limit to 2.5V
++                                                      register "smbus_aux" = 
"0"                      # Device located on primary SMBUS
+                                                       device pnp 5e on #hwm
+                                                       end
+                                               end #drivers/i2c/w83795
+diff --git a/src/mainboard/supermicro/h8scm/devicetree.cb 
b/src/mainboard/supermicro/h8scm/devicetree.cb
+index b8fb823..a280e62 100644
+--- a/src/mainboard/supermicro/h8scm/devicetree.cb
++++ b/src/mainboard/supermicro/h8scm/devicetree.cb
+@@ -106,6 +106,95 @@ chip northbridge/amd/agesa/family15/root_complex
+                                                       end
+                                               end #superio/winbond/w83627dhg
+                                               chip drivers/i2c/w83795
++                                                      register "fanin_ctl1" = 
"0xff"                  # Enable monitoring of FANIN1 - FANIN8
++                                                      register "fanin_ctl2" = 
"0x00"                  # Connect FANIN11 - FANIN14 to alternate functions
++                                                      register "temp_ctl1" = 
"0x2a"                   # Enable monitoring of DTS, VSEN12, and VSEN13
++                                                      register "temp_ctl2" = 
"0x01"                   # Enable monitoring of TD1/TR1
++                                                      register "temp_dtse" = 
"0x03"                   # Enable DTS1 and DTS2
++                                                      register "volt_ctl1" = 
"0xff"                   # Enable monitoring of VSEN1 - VSEN8
++                                                      register "volt_ctl2" = 
"0xf7"                   # Enable monitoring of VSEN9 - VSEN11, 3VDD, 3VSB, and 
VBAT
++                                                      register 
"temp1_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp1)
++                                                      register 
"temp2_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp2)
++                                                      register 
"temp3_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp3)
++                                                      register 
"temp4_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp4)
++                                                      register 
"temp5_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp5)
++                                                      register 
"temp6_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp6)
++                                                      register 
"temp1_source_select" = "0x00"         # Use TD1/TR1 as data source for Temp1
++                                                      register 
"temp2_source_select" = "0x00"         # Use TD2/TR2 as data source for Temp2
++                                                      register 
"temp3_source_select" = "0x00"         # Use TD3/TR3 as data source for Temp3
++                                                      register 
"temp4_source_select" = "0x00"         # Use TD4/TR4 as data source for Temp4
++                                                      register 
"temp5_source_select" = "0x00"         # Use TR5 as data source for Temp5
++                                                      register 
"temp6_source_select" = "0x00"         # Use TR6 as data source for Temp6
++                                                      register 
"tr1_critical_temperature" = "85"      # Set TD1/TR1 critical temperature to 
85°C
++                                                      register 
"tr1_critical_hysteresis" = "80"       # Set TD1/TR1 critical hysteresis 
temperature to 80°C
++                                                      register 
"tr1_warning_temperature" = "70"       # Set TD1/TR1 warning temperature to 70°C
++                                                      register 
"tr1_warning_hysteresis" = "65"        # Set TD1/TR1 warning hysteresis 
temperature to 65°C
++                                                      register 
"dts_critical_temperature" = "85"      # Set DTS (CPU) critical temperature to 
85°C
++                                                      register 
"dts_critical_hysteresis" = "80"       # Set DTS (CPU) critical hysteresis 
temperature to 80°C
++                                                      register 
"dts_warning_temperature" = "70"       # Set DTS (CPU) warning temperature to 
70°C
++                                                      register 
"dts_warning_hysteresis" = "65"        # Set DTS (CPU) warning hysteresis 
temperature to 65°C
++                                                      register 
"temp1_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp2_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp3_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp4_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp5_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp6_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp1_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp2_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp3_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp4_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp5_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp6_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register "fan1_nonstop" 
= "7"                   # Set Fan 1 minimum speed
++                                                      register "fan2_nonstop" 
= "7"                   # Set Fan 2 minimum speed
++                                                      register "fan3_nonstop" 
= "7"                   # Set Fan 3 minimum speed
++                                                      register "fan4_nonstop" 
= "7"                   # Set Fan 4 minimum speed
++                                                      register "fan5_nonstop" 
= "7"                   # Set Fan 5 minimum speed
++                                                      register "fan6_nonstop" 
= "7"                   # Set Fan 6 minimum speed
++                                                      register "fan7_nonstop" 
= "7"                   # Set Fan 7 minimum speed
++                                                      register "fan8_nonstop" 
= "7"                   # Set Fan 8 minimum speed
++                                                      register 
"default_speed" = "100"                # All fans to full speed on power up
++                                                      register "fan1_duty" = 
"100"                    # Fan 1 to full speed
++                                                      register "fan2_duty" = 
"100"                    # Fan 2 to full speed
++                                                      register "fan3_duty" = 
"100"                    # Fan 3 to full speed
++                                                      register "fan4_duty" = 
"100"                    # Fan 4 to full speed
++                                                      register "fan5_duty" = 
"100"                    # Fan 5 to full speed
++                                                      register "fan6_duty" = 
"100"                    # Fan 6 to full speed
++                                                      register "fan7_duty" = 
"100"                    # Fan 7 to full speed
++                                                      register "fan8_duty" = 
"100"                    # Fan 8 to full speed
++                                                      register 
"vcore1_high_limit_mv" = "1500"        # VCORE1 (Node 0) high limit to 1.5V
++                                                      register 
"vcore1_low_limit_mv" = "900"          # VCORE1 (Node 0) low limit to 0.9V
++                                                      register 
"vcore2_high_limit_mv" = "1500"        # VCORE2 (Node 1) high limit to 1.5V
++                                                      register 
"vcore2_low_limit_mv" = "900"          # VCORE2 (Node 1) low limit to 0.9V
++                                                      register 
"vsen3_high_limit_mv" = "1600"         # VSEN1 (Node 0 RAM voltage) high limit 
to 1.6V
++                                                      register 
"vsen3_low_limit_mv" = "1100"          # VSEN1 (Node 0 RAM voltage) low limit 
to 1.1V
++                                                      register 
"vsen4_high_limit_mv" = "1600"         # VSEN2 (Node 1 RAM voltage) high limit 
to 1.6V
++                                                      register 
"vsen4_low_limit_mv" = "1100"          # VSEN2 (Node 1 RAM voltage) low limit 
to 1.1V
++                                                      register 
"vsen5_high_limit_mv" = "1250"         # VSEN5 (Node 0 HT link voltage) high 
limit to 1.25V
++                                                      register 
"vsen5_low_limit_mv" = "1150"          # VSEN5 (Node 0 HT link voltage) low 
limit to 1.15V
++                                                      register 
"vsen6_high_limit_mv" = "1250"         # VSEN6 (Node 1 HT link voltage) high 
limit to 1.25V
++                                                      register 
"vsen6_low_limit_mv" = "1150"          # VSEN6 (Node 1 HT link voltage) low 
limit to 1.15V
++                                                      register 
"vsen7_high_limit_mv" = "1150"         # VSEN7 (Northbridge core voltage) high 
limit to 1.15V
++                                                      register 
"vsen7_low_limit_mv" = "1050"          # VSEN7 (Northbridge core voltage) low 
limit to 1.05V
++                                                      register 
"vsen8_high_limit_mv" = "1900"         # VSEN8 (+1.8V) high limit to 1.9V
++                                                      register 
"vsen8_low_limit_mv" = "1700"          # VSEN8 (+1.8V) low limit to 1.7V
++                                                      register 
"vsen9_high_limit_mv" = "1250"         # VSEN9 (+1.2V) high limit to 1.25V
++                                                      register 
"vsen9_low_limit_mv" = "1150"          # VSEN9 (+1.2V) low limit to 1.15V
++                                                      register 
"vsen10_high_limit_mv" = "1150"        # VSEN10 (+1.1V) high limit to 1.15V
++                                                      register 
"vsen10_low_limit_mv" = "1050"         # VSEN10 (+1.1V) low limit to 1.05V
++                                                      register 
"vsen11_high_limit_mv" = "1625"        # VSEN11 (5VSB, scaling factor ~3.2) 
high limit to 5.2V
++                                                      register 
"vsen11_low_limit_mv" = "1500"         # VSEN11 (5VSB, scaling factor ~3.2) low 
limit to 4.8V
++                                                      register 
"vsen12_high_limit_mv" = "1083"        # VSEN12 (+12V, scaling factor ~12) high 
limit to 13V
++                                                      register 
"vsen12_low_limit_mv" = "917"          # VSEN12 (+12V, scaling factor ~12) low 
limit to 11V
++                                                      register 
"vsen13_high_limit_mv" = "1625"        # VSEN13 (+5V, scaling factor ~3.2) high 
limit to 5.2V
++                                                      register 
"vsen13_low_limit_mv" = "1500"         # VSEN13 (+5V, scaling factor ~3.2) low 
limit to 4.8V
++                                                      register 
"vdd_high_limit_mv" = "3500"           # 3VDD high limit to 3.5V
++                                                      register 
"vdd_low_limit_mv" = "3100"            # 3VDD low limit to 3.1V
++                                                      register 
"vsb_high_limit_mv" = "3500"           # 3VSB high limit to 3.5V
++                                                      register 
"vsb_low_limit_mv" = "3100"            # 3VSB low limit to 3.1V
++                                                      register 
"vbat_high_limit_mv" = "3500"          # VBAT (+3V) high limit to 3.5V
++                                                      register 
"vbat_low_limit_mv" = "2500"           # VBAT (+3V) low limit to 2.5V
++                                                      register "smbus_aux" = 
"0"                      # Device located on primary SMBUS
+                                                       device pnp 5e on #hwm
+                                                       end
+                                               end #drivers/i2c/w83795
+diff --git a/src/mainboard/tyan/s8226/devicetree.cb 
b/src/mainboard/tyan/s8226/devicetree.cb
+index 64701a5..9f5e584 100644
+--- a/src/mainboard/tyan/s8226/devicetree.cb
++++ b/src/mainboard/tyan/s8226/devicetree.cb
+@@ -106,6 +106,95 @@ chip northbridge/amd/agesa/family15/root_complex
+                                                       end
+                                               end #superio/winbond/w83627dhg
+                                               chip drivers/i2c/w83795
++                                                      register "fanin_ctl1" = 
"0xff"                  # Enable monitoring of FANIN1 - FANIN8
++                                                      register "fanin_ctl2" = 
"0x00"                  # Connect FANIN11 - FANIN14 to alternate functions
++                                                      register "temp_ctl1" = 
"0x2a"                   # Enable monitoring of DTS, VSEN12, and VSEN13
++                                                      register "temp_ctl2" = 
"0x01"                   # Enable monitoring of TD1/TR1
++                                                      register "temp_dtse" = 
"0x03"                   # Enable DTS1 and DTS2
++                                                      register "volt_ctl1" = 
"0xff"                   # Enable monitoring of VSEN1 - VSEN8
++                                                      register "volt_ctl2" = 
"0xf7"                   # Enable monitoring of VSEN9 - VSEN11, 3VDD, 3VSB, and 
VBAT
++                                                      register 
"temp1_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp1)
++                                                      register 
"temp2_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp2)
++                                                      register 
"temp3_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp3)
++                                                      register 
"temp4_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp4)
++                                                      register 
"temp5_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp5)
++                                                      register 
"temp6_fan_select" = "0x00"            # All fans to manual mode (no dependence 
on Temp6)
++                                                      register 
"temp1_source_select" = "0x00"         # Use TD1/TR1 as data source for Temp1
++                                                      register 
"temp2_source_select" = "0x00"         # Use TD2/TR2 as data source for Temp2
++                                                      register 
"temp3_source_select" = "0x00"         # Use TD3/TR3 as data source for Temp3
++                                                      register 
"temp4_source_select" = "0x00"         # Use TD4/TR4 as data source for Temp4
++                                                      register 
"temp5_source_select" = "0x00"         # Use TR5 as data source for Temp5
++                                                      register 
"temp6_source_select" = "0x00"         # Use TR6 as data source for Temp6
++                                                      register 
"tr1_critical_temperature" = "85"      # Set TD1/TR1 critical temperature to 
85°C
++                                                      register 
"tr1_critical_hysteresis" = "80"       # Set TD1/TR1 critical hysteresis 
temperature to 80°C
++                                                      register 
"tr1_warning_temperature" = "70"       # Set TD1/TR1 warning temperature to 70°C
++                                                      register 
"tr1_warning_hysteresis" = "65"        # Set TD1/TR1 warning hysteresis 
temperature to 65°C
++                                                      register 
"dts_critical_temperature" = "85"      # Set DTS (CPU) critical temperature to 
85°C
++                                                      register 
"dts_critical_hysteresis" = "80"       # Set DTS (CPU) critical hysteresis 
temperature to 80°C
++                                                      register 
"dts_warning_temperature" = "70"       # Set DTS (CPU) warning temperature to 
70°C
++                                                      register 
"dts_warning_hysteresis" = "65"        # Set DTS (CPU) warning hysteresis 
temperature to 65°C
++                                                      register 
"temp1_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp2_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp3_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp4_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp5_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp6_critical_temperature" = "80"    # Set Temp1 critical temperature to 80°C
++                                                      register 
"temp1_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp2_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp3_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp4_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp5_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register 
"temp6_target_temperature" = "80"      # Set Temp1 target temperature to 80°C
++                                                      register "fan1_nonstop" 
= "7"                   # Set Fan 1 minimum speed
++                                                      register "fan2_nonstop" 
= "7"                   # Set Fan 2 minimum speed
++                                                      register "fan3_nonstop" 
= "7"                   # Set Fan 3 minimum speed
++                                                      register "fan4_nonstop" 
= "7"                   # Set Fan 4 minimum speed
++                                                      register "fan5_nonstop" 
= "7"                   # Set Fan 5 minimum speed
++                                                      register "fan6_nonstop" 
= "7"                   # Set Fan 6 minimum speed
++                                                      register "fan7_nonstop" 
= "7"                   # Set Fan 7 minimum speed
++                                                      register "fan8_nonstop" 
= "7"                   # Set Fan 8 minimum speed
++                                                      register 
"default_speed" = "100"                # All fans to full speed on power up
++                                                      register "fan1_duty" = 
"100"                    # Fan 1 to full speed
++                                                      register "fan2_duty" = 
"100"                    # Fan 2 to full speed
++                                                      register "fan3_duty" = 
"100"                    # Fan 3 to full speed
++                                                      register "fan4_duty" = 
"100"                    # Fan 4 to full speed
++                                                      register "fan5_duty" = 
"100"                    # Fan 5 to full speed
++                                                      register "fan6_duty" = 
"100"                    # Fan 6 to full speed
++                                                      register "fan7_duty" = 
"100"                    # Fan 7 to full speed
++                                                      register "fan8_duty" = 
"100"                    # Fan 8 to full speed
++                                                      register 
"vcore1_high_limit_mv" = "1500"        # VCORE1 (Node 0) high limit to 1.5V
++                                                      register 
"vcore1_low_limit_mv" = "900"          # VCORE1 (Node 0) low limit to 0.9V
++                                                      register 
"vcore2_high_limit_mv" = "1500"        # VCORE2 (Node 1) high limit to 1.5V
++                                                      register 
"vcore2_low_limit_mv" = "900"          # VCORE2 (Node 1) low limit to 0.9V
++                                                      register 
"vsen3_high_limit_mv" = "1600"         # VSEN1 (Node 0 RAM voltage) high limit 
to 1.6V
++                                                      register 
"vsen3_low_limit_mv" = "1100"          # VSEN1 (Node 0 RAM voltage) low limit 
to 1.1V
++                                                      register 
"vsen4_high_limit_mv" = "1600"         # VSEN2 (Node 1 RAM voltage) high limit 
to 1.6V
++                                                      register 
"vsen4_low_limit_mv" = "1100"          # VSEN2 (Node 1 RAM voltage) low limit 
to 1.1V
++                                                      register 
"vsen5_high_limit_mv" = "1250"         # VSEN5 (Node 0 HT link voltage) high 
limit to 1.25V
++                                                      register 
"vsen5_low_limit_mv" = "1150"          # VSEN5 (Node 0 HT link voltage) low 
limit to 1.15V
++                                                      register 
"vsen6_high_limit_mv" = "1250"         # VSEN6 (Node 1 HT link voltage) high 
limit to 1.25V
++                                                      register 
"vsen6_low_limit_mv" = "1150"          # VSEN6 (Node 1 HT link voltage) low 
limit to 1.15V
++                                                      register 
"vsen7_high_limit_mv" = "1150"         # VSEN7 (Northbridge core voltage) high 
limit to 1.15V
++                                                      register 
"vsen7_low_limit_mv" = "1050"          # VSEN7 (Northbridge core voltage) low 
limit to 1.05V
++                                                      register 
"vsen8_high_limit_mv" = "1900"         # VSEN8 (+1.8V) high limit to 1.9V
++                                                      register 
"vsen8_low_limit_mv" = "1700"          # VSEN8 (+1.8V) low limit to 1.7V
++                                                      register 
"vsen9_high_limit_mv" = "1250"         # VSEN9 (+1.2V) high limit to 1.25V
++                                                      register 
"vsen9_low_limit_mv" = "1150"          # VSEN9 (+1.2V) low limit to 1.15V
++                                                      register 
"vsen10_high_limit_mv" = "1150"        # VSEN10 (+1.1V) high limit to 1.15V
++                                                      register 
"vsen10_low_limit_mv" = "1050"         # VSEN10 (+1.1V) low limit to 1.05V
++                                                      register 
"vsen11_high_limit_mv" = "1625"        # VSEN11 (5VSB, scaling factor ~3.2) 
high limit to 5.2V
++                                                      register 
"vsen11_low_limit_mv" = "1500"         # VSEN11 (5VSB, scaling factor ~3.2) low 
limit to 4.8V
++                                                      register 
"vsen12_high_limit_mv" = "1083"        # VSEN12 (+12V, scaling factor ~12) high 
limit to 13V
++                                                      register 
"vsen12_low_limit_mv" = "917"          # VSEN12 (+12V, scaling factor ~12) low 
limit to 11V
++                                                      register 
"vsen13_high_limit_mv" = "1625"        # VSEN13 (+5V, scaling factor ~3.2) high 
limit to 5.2V
++                                                      register 
"vsen13_low_limit_mv" = "1500"         # VSEN13 (+5V, scaling factor ~3.2) low 
limit to 4.8V
++                                                      register 
"vdd_high_limit_mv" = "3500"           # 3VDD high limit to 3.5V
++                                                      register 
"vdd_low_limit_mv" = "3100"            # 3VDD low limit to 3.1V
++                                                      register 
"vsb_high_limit_mv" = "3500"           # 3VSB high limit to 3.5V
++                                                      register 
"vsb_low_limit_mv" = "3100"            # 3VSB low limit to 3.1V
++                                                      register 
"vbat_high_limit_mv" = "3500"          # VBAT (+3V) high limit to 3.5V
++                                                      register 
"vbat_low_limit_mv" = "2500"           # VBAT (+3V) low limit to 2.5V
++                                                      register "smbus_aux" = 
"0"                      # Device located on primary SMBUS
+                                                       device pnp 5e on #hwm
+                                                       end
+                                               end #drivers/i2c/w83795
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0005-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
 
b/resources/libreboot/patch/kgpe-d16/0005-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
deleted file mode 100644
index a895479..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0005-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
+++ /dev/null
@@ -1,642 +0,0 @@
-From e897086a84f3b7c1af321e2a8a303cc49367b390 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 17:46:15 -0500
-Subject: [PATCH 005/139] southbridge/amd/sb700: Fix boot hang on ASUS KGPE-D16
-
-Change-Id: I1d7d6715663a13ab94fd6d71808e35f0f7384d00
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/southbridge/amd/sb700/Kconfig       |   4 +
- src/southbridge/amd/sb700/acpi/ide.asl  | 234 ++++++++++++++++++++++++++++++++
- src/southbridge/amd/sb700/acpi/sata.asl | 133 ++++++++++++++++++
- src/southbridge/amd/sb700/bootblock.c   |  46 ++++++-
- src/southbridge/amd/sb700/early_setup.c |  18 +++
- src/southbridge/amd/sb700/lpc.c         |   3 +
- src/southbridge/amd/sb700/sm.c          |  21 +--
- src/southbridge/amd/sb700/smbus.h       |   5 +-
- 8 files changed, 447 insertions(+), 17 deletions(-)
- create mode 100644 src/southbridge/amd/sb700/acpi/ide.asl
- create mode 100644 src/southbridge/amd/sb700/acpi/sata.asl
-
-diff --git a/src/southbridge/amd/sb700/Kconfig 
b/src/southbridge/amd/sb700/Kconfig
-index a5dfe07..f56f84a 100644
---- a/src/southbridge/amd/sb700/Kconfig
-+++ b/src/southbridge/amd/sb700/Kconfig
-@@ -42,6 +42,10 @@ config SOUTHBRIDGE_AMD_SB700_SKIP_ISA_DMA_INIT
-       bool
-       default n
- 
-+config SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA
-+      bool
-+      default n
-+
- config EHCI_BAR
-       hex
-       default 0xfef00000
-diff --git a/src/southbridge/amd/sb700/acpi/ide.asl 
b/src/southbridge/amd/sb700/acpi/ide.asl
-new file mode 100644
-index 0000000..9b5e3ea
---- /dev/null
-+++ b/src/southbridge/amd/sb700/acpi/ide.asl
-@@ -0,0 +1,234 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ *
-+ * 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
-+ */
-+
-+/* Some timing tables */
-+Name(UDTT, Package(){ /* Udma timing table */
-+      120, 90, 60, 45, 30, 20, 15, 0  /* UDMA modes 0 -> 6 */
-+})
-+
-+Name(MDTT, Package(){ /* MWDma timing table */
-+      480, 150, 120, 0        /* Legacy DMA modes 0 -> 2 */
-+})
-+
-+Name(POTT, Package(){ /* Pio timing table */
-+      600, 390, 270, 180, 120, 0      /* PIO modes 0 -> 4 */
-+})
-+
-+/* Some timing register value tables */
-+Name(MDRT, Package(){ /* MWDma timing register table */
-+      0x77, 0x21, 0x20, 0xFF  /* Legacy DMA modes 0 -> 2 */
-+})
-+
-+Name(PORT, Package(){
-+      0x99, 0x47, 0x34, 0x22, 0x20, 0x99      /* PIO modes 0 -> 4 */
-+})
-+
-+OperationRegion(ICRG, PCI_Config, 0x40, 0x20) /* ide control registers */
-+      Field(ICRG, AnyAcc, NoLock, Preserve)
-+{
-+      PPTS, 8,        /* Primary PIO Slave Timing */
-+      PPTM, 8,        /* Primary PIO Master Timing */
-+      OFFSET(0x04), PMTS, 8,  /* Primary MWDMA Slave Timing */
-+      PMTM, 8,        /* Primary MWDMA Master Timing */
-+      OFFSET(0x08), PPCR, 8,  /* Primary PIO Control */
-+      OFFSET(0x0A), PPMM, 4,  /* Primary PIO master Mode */
-+      PPSM, 4,        /* Primary PIO slave Mode */
-+      OFFSET(0x14), PDCR, 2,  /* Primary UDMA Control */
-+      OFFSET(0x16), PDMM, 4,  /* Primary UltraDMA Mode */
-+      PDSM, 4,        /* Primary UltraDMA Mode */
-+}
-+
-+Method(GTTM, 1) /* get total time*/
-+{
-+      Store(And(Arg0, 0x0F), Local0)  /* Recovery Width */
-+      Increment(Local0)
-+      Store(ShiftRight(Arg0, 4), Local1)      /* Command Width */
-+      Increment(Local1)
-+      Return(Multiply(30, Add(Local0, Local1)))
-+}
-+
-+Device(PRID)
-+{
-+      Name (_ADR, Zero)
-+      Method(_GTM, 0, Serialized)
-+      {
-+              NAME(OTBF, Buffer(20) { /* out buffer */
-+                      0xFF, 0xFF, 0xFF, 0xFF,
-+                      0xFF, 0xFF, 0xFF, 0xFF,
-+                      0xFF, 0xFF, 0xFF, 0xFF,
-+                      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
-+              })
-+
-+              CreateDwordField(OTBF, 0, PSD0)   /* PIO spd0 */
-+              CreateDwordField(OTBF, 4, DSD0)   /* DMA spd0 */
-+              CreateDwordField(OTBF, 8, PSD1)   /* PIO spd1 */
-+              CreateDwordField(OTBF, 12, DSD1) /* DMA spd1 */
-+              CreateDwordField(OTBF, 16, BFFG) /* buffer flags */
-+
-+              /* Just return if the channel is disabled */
-+              If(And(PPCR, 0x01)) { /* primary PIO control */
-+                      Return(OTBF)
-+              }
-+
-+              /* Always tell them independent timing available and 
IOChannelReady used on both drives */
-+              Or(BFFG, 0x1A, BFFG)
-+
-+              Store(GTTM(PPTM), PSD0) /* save total time of primary PIO 
master timming  to PIO spd0 */
-+              Store(GTTM(PPTS), PSD1) /* save total time of primary PIO slave 
Timing  to PIO spd1 */
-+
-+              If(And(PDCR, 0x01)) {   /* It's under UDMA mode */
-+                      Or(BFFG, 0x01, BFFG)
-+                      Store(DerefOf(Index(UDTT, PDMM)), DSD0)
-+              }
-+              Else {
-+                      Store(GTTM(PMTM), DSD0) /* Primary MWDMA Master Timing, 
 DmaSpd0 */
-+              }
-+
-+              If(And(PDCR, 0x02)) {   /* It's under UDMA mode */
-+                      Or(BFFG, 0x04, BFFG)
-+                      Store(DerefOf(Index(UDTT, PDSM)), DSD1)
-+              }
-+              Else {
-+                      Store(GTTM(PMTS), DSD1) /* Primary MWDMA Slave Timing,  
DmaSpd0 */
-+              }
-+
-+              Return(OTBF) /* out buffer */
-+      }                               /* End Method(_GTM) */
-+
-+      Method(_STM, 3, Serialized)
-+      {
-+              NAME(INBF, Buffer(20) { /* in buffer */
-+                      0xFF, 0xFF, 0xFF, 0xFF,
-+                      0xFF, 0xFF, 0xFF, 0xFF,
-+                      0xFF, 0xFF, 0xFF, 0xFF,
-+                      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
-+              })
-+
-+              CreateDwordField(INBF, 0, PSD0)    /* PIO spd0 */
-+              CreateDwordField(INBF, 4, DSD0)   /* PIO spd0 */
-+              CreateDwordField(INBF, 8, PSD1)   /* PIO spd1 */
-+              CreateDwordField(INBF, 12, DSD1) /* DMA spd1 */
-+              CreateDwordField(INBF, 16, BFFG) /*buffer flag */
-+
-+              Store(Match(POTT, MLE, PSD0, MTR, 0, 0), Local0)
-+              Divide(Local0, 5, PPMM,) /* Primary PIO master Mode */
-+              Store(Match(POTT, MLE, PSD1, MTR, 0, 0), Local1)
-+              Divide(Local1, 5, PPSM,) /* Primary PIO slave Mode */
-+
-+              Store(DerefOf(Index(PORT, Local0)), PPTM) /* Primary PIO Master 
Timing */
-+              Store(DerefOf(Index(PORT, Local1)), PPTS) /* Primary PIO Slave 
Timing */
-+
-+              If(And(BFFG, 0x01)) {   /* Drive 0 is under UDMA mode */
-+                      Store(Match(UDTT, MLE, DSD0, MTR, 0, 0), Local0)
-+                      Divide(Local0, 7, PDMM,)
-+                      Or(PDCR, 0x01, PDCR)
-+              }
-+              Else {
-+                      If(LNotEqual(DSD0, 0xFFFFFFFF)) {
-+                              Store(Match(MDTT, MLE, DSD0, MTR, 0, 0), Local0)
-+                              Store(DerefOf(Index(MDRT, Local0)), PMTM)
-+                      }
-+              }
-+
-+              If(And(BFFG, 0x04)) {   /* Drive 1 is under UDMA mode */
-+                      Store(Match(UDTT, MLE, DSD1, MTR, 0, 0), Local0)
-+                      Divide(Local0, 7, PDSM,)
-+                      Or(PDCR, 0x02, PDCR)
-+              }
-+              Else {
-+                      If(LNotEqual(DSD1, 0xFFFFFFFF)) {
-+                              Store(Match(MDTT, MLE, DSD1, MTR, 0, 0), Local0)
-+                              Store(DerefOf(Index(MDRT, Local0)), PMTS)
-+                      }
-+              }
-+              /* Return(INBF) */
-+      }               /*End Method(_STM) */
-+      Device(MST)
-+      {
-+              Name(_ADR, 0)
-+              Method(_GTF, 0, Serialized) {
-+                      Name(CMBF, Buffer(21) {
-+                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
-+                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
-+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5
-+                      })
-+                      CreateByteField(CMBF, 1, POMD)
-+                      CreateByteField(CMBF, 8, DMMD)
-+                      CreateByteField(CMBF, 5, CMDA)
-+                      CreateByteField(CMBF, 12, CMDB)
-+                      CreateByteField(CMBF, 19, CMDC)
-+
-+                      Store(0xA0, CMDA)
-+                      Store(0xA0, CMDB)
-+                      Store(0xA0, CMDC)
-+
-+                      Or(PPMM, 0x08, POMD)
-+
-+                      If(And(PDCR, 0x01)) {
-+                              Or(PDMM, 0x40, DMMD)
-+                      }
-+                      Else {
-+                              Store(Match
-+                                    (MDTT, MLE, GTTM(PMTM),
-+                                     MTR, 0, 0), Local0)
-+                              If(LLess(Local0, 3)) {
-+                                      Or(0x20, Local0, DMMD)
-+                              }
-+                      }
-+                      Return(CMBF)
-+              }
-+      }               /* End Device(MST) */
-+
-+      Device(SLAV)
-+      {
-+              Name(_ADR, 1)
-+              Method(_GTF, 0, Serialized) {
-+                      Name(CMBF, Buffer(21) {
-+                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
-+                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
-+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5
-+                      })
-+                      CreateByteField(CMBF, 1, POMD)
-+                      CreateByteField(CMBF, 8, DMMD)
-+                      CreateByteField(CMBF, 5, CMDA)
-+                      CreateByteField(CMBF, 12, CMDB)
-+                      CreateByteField(CMBF, 19, CMDC)
-+
-+                      Store(0xB0, CMDA)
-+                      Store(0xB0, CMDB)
-+                      Store(0xB0, CMDC)
-+
-+                      Or(PPSM, 0x08, POMD)
-+
-+                      If(And(PDCR, 0x02)) {
-+                              Or(PDSM, 0x40, DMMD)
-+                      }
-+                      Else {
-+                              Store(Match
-+                                    (MDTT, MLE, GTTM(PMTS),
-+                                     MTR, 0, 0), Local0)
-+                              If(LLess(Local0, 3)) {
-+                                      Or(0x20, Local0, DMMD)
-+                              }
-+                      }
-+                      Return(CMBF)
-+              }
-+      }                       /* End Device(SLAV) */
-+}
-diff --git a/src/southbridge/amd/sb700/acpi/sata.asl 
b/src/southbridge/amd/sb700/acpi/sata.asl
-new file mode 100644
-index 0000000..46a82b7
---- /dev/null
-+++ b/src/southbridge/amd/sb700/acpi/sata.asl
-@@ -0,0 +1,133 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * 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
-+ */
-+
-+Name(STTM, Buffer(20) {
-+      0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
-+      0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
-+      0x1f, 0x00, 0x00, 0x00
-+})
-+
-+/* Start by clearing the PhyRdyChg bits */
-+Method(_INI) {
-+      \_GPE._L1F()
-+}
-+
-+Device(PMRY)
-+{
-+      Name(_ADR, 0)
-+      Method(_GTM, 0x0, NotSerialized) {
-+              Return(STTM)
-+      }
-+      Method(_STM, 0x3, NotSerialized) {}
-+
-+      Device(PMST) {
-+              Name(_ADR, 0)
-+              Method(_STA,0) {
-+                      if (LGreater(P0IS,0)) {
-+                              return (0x0F) /* sata is visible */
-+                      } else {
-+                              return  (0x00) /* sata is missing */
-+                      }
-+              }
-+      }/* end of PMST */
-+
-+      Device(PSLA)
-+      {
-+              Name(_ADR, 1)
-+              Method(_STA,0) {
-+                      if (LGreater(P1IS,0)) {
-+                              return (0x0F) /* sata is visible */
-+                      } else {
-+                              return (0x00) /* sata is missing */
-+                      }
-+              }
-+      }       /* end of PSLA */
-+}   /* end of PMRY */
-+
-+
-+Device(SEDY)
-+{
-+      Name(_ADR, 1)           /* IDE Scondary Channel */
-+      Method(_GTM, 0x0, NotSerialized) {
-+              Return(STTM)
-+      }
-+      Method(_STM, 0x3, NotSerialized) {}
-+
-+      Device(SMST)
-+      {
-+              Name(_ADR, 0)
-+              Method(_STA,0) {
-+                      if (LGreater(P2IS,0)) {
-+                              return (0x0F) /* sata is visible */
-+                      } else {
-+                              return (0x00) /* sata is missing */
-+                      }
-+              }
-+      } /* end of SMST */
-+
-+      Device(SSLA)
-+      {
-+              Name(_ADR, 1)
-+              Method(_STA,0) {
-+                      if (LGreater(P3IS,0)) {
-+                              return (0x0F) /* sata is visible */
-+                      } else {
-+                              return (0x00) /* sata is missing */
-+                      }
-+              }
-+      } /* end of SSLA */
-+}   /* end of SEDY */
-+
-+/* SATA Hot Plug Support */
-+Scope(\_GPE) {
-+      Method(_L1F,0x0,NotSerialized) {
-+              if (\_SB.P0PR) {
-+                      if (LGreater(\_SB.P0IS,0)) {
-+                              sleep(32)
-+                      }
-+                      Notify(\_SB.PCI0.SAT0.PMRY.PMST, 0x01) /* 
NOTIFY_DEVICE_CHECK */
-+                      store(one, \_SB.P0PR)
-+              }
-+
-+              if (\_SB.P1PR) {
-+                      if (LGreater(\_SB.P1IS,0)) {
-+                              sleep(32)
-+                      }
-+                      Notify(\_SB.PCI0.SAT0.PMRY.PSLA, 0x01) /* 
NOTIFY_DEVICE_CHECK */
-+                      store(one, \_SB.P1PR)
-+              }
-+
-+              if (\_SB.P2PR) {
-+                      if (LGreater(\_SB.P2IS,0)) {
-+                              sleep(32)
-+                      }
-+                      Notify(\_SB.PCI0.SAT0.SEDY.SMST, 0x01) /* 
NOTIFY_DEVICE_CHECK */
-+                      store(one, \_SB.P2PR)
-+              }
-+
-+              if (\_SB.P3PR) {
-+                      if (LGreater(\_SB.P3IS,0)) {
-+                              sleep(32)
-+                      }
-+                      Notify(\_SB.PCI0.SAT0.SEDY.SSLA, 0x01) /* 
NOTIFY_DEVICE_CHECK */
-+                      store(one, \_SB.P3PR)
-+              }
-+      }
-+}
-diff --git a/src/southbridge/amd/sb700/bootblock.c 
b/src/southbridge/amd/sb700/bootblock.c
-index 67e6434..8f722a8 100644
---- a/src/southbridge/amd/sb700/bootblock.c
-+++ b/src/southbridge/amd/sb700/bootblock.c
-@@ -1,6 +1,7 @@
- /*
-  * This file is part of the coreboot project.
-  *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-  *
-  * This program is free software; you can redistribute it and/or modify
-@@ -35,10 +36,17 @@
- static void sb700_enable_rom(void)
- {
-       u8 reg8;
-+      u32 dword;
-       pci_devfn_t dev;
- 
-       dev = PCI_DEV(0, 0x14, 3);
- 
-+      /* The LPC settings below work for SPI flash as well;
-+       * the hardware does not distinguish between LPC and SPI flash ROM
-+       * aside from offering additional side-channel access to SPI flash
-+       * via a separate register-based interface.
-+       */
-+
-       /* Decode variable LPC ROM address ranges 1 and 2. */
-       reg8 = pci_io_read_config8(dev, 0x48);
-       reg8 |= (1 << 3) | (1 << 4);
-@@ -52,15 +60,41 @@ static void sb700_enable_rom(void)
- 
-       /* LPC ROM address range 2: */
-       /*
--       * Enable LPC ROM range start at:
--       * 0xfff8(0000): 512KB
--       * 0xfff0(0000): 1MB
--       * 0xffe0(0000): 2MB
--       * 0xffc0(0000): 4MB
--       */
-+      * Enable LPC ROM range start at:
-+      * 0xfff8(0000): 512KB
-+      * 0xfff0(0000): 1MB
-+      * 0xffe0(0000): 2MB
-+      * 0xffc0(0000): 4MB
-+      * 0xff80(0000): 8MB
-+      */
-       pci_io_write_config16(dev, 0x6c, 0x10000 - (CONFIG_COREBOOT_ROMSIZE_KB 
>> 6));
-       /* Enable LPC ROM range end at 0xffff(ffff). */
-       pci_io_write_config16(dev, 0x6e, 0xffff);
-+
-+      /* SB700 LPC Bridge 0x48h.
-+       * Turn on all LPC IO Port decode enables
-+       */
-+      dword = pci_io_read_config32(dev, 0x44);
-+      dword = 0xffffffff;
-+      pci_io_write_config32(dev, 0x44, dword);
-+
-+      /* SB700 LPC Bridge 0x48h.
-+       * BIT0: Port Enable for SuperIO 0x2E-0x2F
-+       * BIT1: Port Enable for SuperIO 0x4E-0x4F
-+       * BIT4: Port Enable for LPC ROM Address Arrage2 (0x68-0x6C)
-+       * BIT6: Port Enable for RTC IO 0x70-0x73
-+       * BIT21: Port Enable for Port 0x80
-+       */
-+      reg8 = pci_io_read_config8(dev, 0x48);
-+      reg8 |= (1<<0) | (1<<1) | (1<<4) | (1<<6);
-+      pci_io_write_config8(dev, 0x48, reg8);
-+
-+      /* SB700 LPC Bridge 0x4ah.
-+       * BIT4: Port Enable for Port 0x80
-+       */
-+      reg8 = pci_io_read_config8(dev, 0x4a);
-+      reg8 |= (1<<4);
-+      pci_io_write_config8(dev, 0x4a, reg8);
- }
- 
- static void bootblock_southbridge_init(void)
-diff --git a/src/southbridge/amd/sb700/early_setup.c 
b/src/southbridge/amd/sb700/early_setup.c
-index d25599e..de3fa97 100644
---- a/src/southbridge/amd/sb700/early_setup.c
-+++ b/src/southbridge/amd/sb700/early_setup.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -395,6 +396,15 @@ static void sb700_devices_por_init(void)
-       byte |= (1 << 0);
-       pci_write_config8(dev, 0xd2, byte);
- 
-+      /* set auxiliary smbus iobase and enable controller */
-+      pci_write_config32(dev, 0x58, SMBUS_AUX_IO_BASE | 1);
-+
-+      if (inw(SMBUS_IO_BASE) == 0xFF)
-+              printk(BIOS_INFO, "sb700_devices_por_init(): Primary SMBUS 
controller I/O not found\n");
-+
-+      if (inw(SMBUS_AUX_IO_BASE) == 0xFF)
-+              printk(BIOS_INFO, "sb700_devices_por_init(): Secondary SMBUS 
controller I/O not found\n");
-+
-       /* KB2RstEnable */
-       pci_write_config8(dev, 0x40, 0x44);
- 
-@@ -439,6 +449,14 @@ static void sb700_devices_por_init(void)
-       /*pci_write_config8(dev, 0x79, 0x4F); */
-       pci_write_config8(dev, 0x78, 0xFF);
- 
-+      if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
-+              printk(BIOS_DEBUG, "sb700_devices_por_init(): Disabling ISA DMA 
support\n");
-+              /* Disable LPC ISA DMA Capability */
-+              byte = pci_read_config8(dev, 0x78);
-+              byte &= ~(1 << 0);
-+              pci_write_config8(dev, 0x78, byte);
-+      }
-+
-       /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that 
is reserved */
-       pci_write_config16(dev, 0x4, 0x0407);
- 
-diff --git a/src/southbridge/amd/sb700/lpc.c b/src/southbridge/amd/sb700/lpc.c
-index a39ec18..0cc1e8b 100644
---- a/src/southbridge/amd/sb700/lpc.c
-+++ b/src/southbridge/amd/sb700/lpc.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -45,6 +46,8 @@ static void lpc_init(device_t dev)
-       u32 dword;
-       device_t sm_dev;
- 
-+      printk(BIOS_SPEW, "%s\n", __func__);
-+
-       /* Enable the LPC Controller */
-       sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
-       dword = pci_read_config32(sm_dev, 0x64);
-diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c
-index c216e1f..a4b78d0 100644
---- a/src/southbridge/amd/sb700/sm.c
-+++ b/src/southbridge/amd/sb700/sm.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -59,11 +60,8 @@ static void sm_init(device_t dev)
-       printk(BIOS_INFO, "sm_init().\n");
- 
-       rev = get_sb700_revision(dev);
--      ioapic_base = (void *)(pci_read_config32(dev, 0x74) & (0xffffffe0));    
/* some like mem resource, but does not have  enable bit */
--      /* Don't rename APIC ID */
--      /* TODO: We should call setup_ioapic() here. But kernel hangs if cpu is 
K8.
--       * We need to check out why and change back. */
--      clear_ioapic(ioapic_base);
-+      ioapic_base = (void *)(pci_read_config32(dev, 0x74) & (0xffffffe0));    
/* some like mem resource, but does not have enable bit */
-+      setup_ioapic(ioapic_base, 0); /* Don't rename IOAPIC ID. */
- 
-       /* 2.10 Interrupt Routing/Filtering */
-       dword = pci_read_config8(dev, 0x62);
-@@ -129,9 +127,10 @@ static void sm_init(device_t dev)
-       get_option(&on, "power_on_after_fail");
-       byte = pm_ioread(0x74);
-       byte &= ~0x03;
--      if (on) {
--              byte |= 2;
--      }
-+      if (on == 1)
-+              byte |= 0x1;    /* Force power on */
-+      else if (on == 2)
-+              byte |= 0x2;    /* Use last power state */
-       byte |= 1 << 2;
-       pm_iowrite(0x74, byte);
-       printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off");
-@@ -295,6 +294,10 @@ static void sm_init(device_t dev)
-       byte &= ~(1 << 1);
-       pm_iowrite(0x59, byte);
- 
-+      /* Enable SCI as irq9. */
-+      outb(0x4, 0xC00);
-+      outb(0x9, 0xC01);
-+
-       printk(BIOS_INFO, "sm_init() end\n");
- 
-       /* Enable NbSb virtual channel */
-@@ -385,7 +388,7 @@ static void sb700_sm_read_resources(device_t dev)
-       struct resource *res;
- 
-       /* Get the normal pci resources of this device */
--      /* pci_dev_read_resources(dev); */
-+      pci_dev_read_resources(dev);
- 
-       /* apic */
-       res = new_resource(dev, 0x74);
-diff --git a/src/southbridge/amd/sb700/smbus.h 
b/src/southbridge/amd/sb700/smbus.h
-index d223fe7..34b4098 100644
---- a/src/southbridge/amd/sb700/smbus.h
-+++ b/src/southbridge/amd/sb700/smbus.h
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -24,8 +25,8 @@
- #include "stddef.h"
- #include <arch/io.h>
- 
--#define SMBUS_IO_BASE 0x6000  /* Is it a temporary SMBus I/O base address? */
--                              /*SIZE 0x40 */
-+#define SMBUS_IO_BASE 0xb00
-+#define SMBUS_AUX_IO_BASE 0xb20
- 
- #define SMBHSTSTAT 0x0
- #define SMBSLVSTAT 0x1
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0006-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
 
b/resources/libreboot/patch/kgpe-d16/0006-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
new file mode 100644
index 0000000..b243026
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0006-drivers-aspeed-Add-native-text-mode-VGA-support-for-.patch
@@ -0,0 +1,3675 @@
+From 913f5fe9e0107c27e0029fe76f62b37f88ccb221 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 5 Sep 2015 17:38:09 -0500
+Subject: [PATCH 006/143] drivers/aspeed: Add native text mode VGA support for
+ the AST2050
+
+Change-Id: I37763a59d2546cd0c0e57b31fdb7aa77c2c50bee
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/drivers/aspeed/Kconfig                  |    2 +
+ src/drivers/aspeed/Makefile.inc             |    1 +
+ src/drivers/aspeed/ast2050/Kconfig          |   14 +
+ src/drivers/aspeed/ast2050/Makefile.inc     |    1 +
+ src/drivers/aspeed/ast2050/ast2050.c        |   83 ++
+ src/drivers/aspeed/common/Kconfig           |   10 +
+ src/drivers/aspeed/common/Makefile.inc      |    1 +
+ src/drivers/aspeed/common/aspeed_coreboot.h |  210 ++++
+ src/drivers/aspeed/common/ast_dp501.c       |  443 +++++++
+ src/drivers/aspeed/common/ast_dram_tables.h |  165 +++
+ src/drivers/aspeed/common/ast_drv.h         |  223 ++++
+ src/drivers/aspeed/common/ast_main.c        |  393 +++++++
+ src/drivers/aspeed/common/ast_post.c        | 1679 +++++++++++++++++++++++++++
+ src/drivers/aspeed/common/ast_tables.h      |  305 +++++
+ src/include/device/pci_ids.h                |    3 +
+ 15 files changed, 3533 insertions(+)
+ create mode 100644 src/drivers/aspeed/Kconfig
+ create mode 100644 src/drivers/aspeed/Makefile.inc
+ create mode 100644 src/drivers/aspeed/ast2050/Kconfig
+ create mode 100644 src/drivers/aspeed/ast2050/Makefile.inc
+ create mode 100644 src/drivers/aspeed/ast2050/ast2050.c
+ create mode 100644 src/drivers/aspeed/common/Kconfig
+ create mode 100644 src/drivers/aspeed/common/Makefile.inc
+ create mode 100644 src/drivers/aspeed/common/aspeed_coreboot.h
+ create mode 100644 src/drivers/aspeed/common/ast_dp501.c
+ create mode 100644 src/drivers/aspeed/common/ast_dram_tables.h
+ create mode 100644 src/drivers/aspeed/common/ast_drv.h
+ create mode 100644 src/drivers/aspeed/common/ast_main.c
+ create mode 100644 src/drivers/aspeed/common/ast_post.c
+ create mode 100644 src/drivers/aspeed/common/ast_tables.h
+
+diff --git a/src/drivers/aspeed/Kconfig b/src/drivers/aspeed/Kconfig
+new file mode 100644
+index 0000000..27469b5
+--- /dev/null
++++ b/src/drivers/aspeed/Kconfig
+@@ -0,0 +1,2 @@
++source src/drivers/aspeed/common/Kconfig
++source src/drivers/aspeed/ast2050/Kconfig
+\ No newline at end of file
+diff --git a/src/drivers/aspeed/Makefile.inc b/src/drivers/aspeed/Makefile.inc
+new file mode 100644
+index 0000000..955a213
+--- /dev/null
++++ b/src/drivers/aspeed/Makefile.inc
+@@ -0,0 +1 @@
++subdirs-y += common ast2050
+\ No newline at end of file
+diff --git a/src/drivers/aspeed/ast2050/Kconfig 
b/src/drivers/aspeed/ast2050/Kconfig
+new file mode 100644
+index 0000000..f110d58
+--- /dev/null
++++ b/src/drivers/aspeed/ast2050/Kconfig
+@@ -0,0 +1,14 @@
++config DRIVERS_ASPEED_AST2050
++      bool
++
++if DRIVERS_ASPEED_AST2050
++
++config DEVICE_SPECIFIC_OPTIONS # dummy
++      def_bool y
++      select DRIVERS_ASPEED_AST_COMMON
++
++config NATIVE_VGA_INIT_USE_EDID
++      bool
++      default n
++
++endif # DRIVERS_ASPEED_AST2050
+diff --git a/src/drivers/aspeed/ast2050/Makefile.inc 
b/src/drivers/aspeed/ast2050/Makefile.inc
+new file mode 100644
+index 0000000..3ba9dde
+--- /dev/null
++++ b/src/drivers/aspeed/ast2050/Makefile.inc
+@@ -0,0 +1 @@
++ramstage-$(CONFIG_DRIVERS_ASPEED_AST2050) += ast2050.c
+\ No newline at end of file
+diff --git a/src/drivers/aspeed/ast2050/ast2050.c 
b/src/drivers/aspeed/ast2050/ast2050.c
+new file mode 100644
+index 0000000..809e9de
+--- /dev/null
++++ b/src/drivers/aspeed/ast2050/ast2050.c
+@@ -0,0 +1,83 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * 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
++ */
++#include <delay.h>
++#include <stdlib.h>
++#include <string.h>
++#include <arch/io.h>
++#include <edid.h>
++
++#include <console/console.h>
++#include <device/device.h>
++#include <device/pci.h>
++#include <device/pci_ids.h>
++#include <device/pci_ops.h>
++
++#include <pc80/vga.h>
++
++#include "../common/aspeed_coreboot.h"
++#include "../common/ast_drv.h"
++
++static void aspeed_ast2050_set_resources(device_t dev)
++{
++      /* Reserve VGA regions */
++      mmio_resource(dev, 3, 0xa0000 >> 10, 0x1ffff >> 10);
++
++      /* Run standard resource set routine */
++      pci_dev_set_resources(dev);
++}
++
++static void aspeed_ast2050_init(struct device *dev)
++{
++      u8 ret;
++      struct drm_device drm_dev;
++
++      drm_dev.pdev = dev;
++
++      printk(BIOS_INFO, "ASpeed AST2050: initializing video device\n");
++      ret = ast_driver_load(&drm_dev, 0);
++
++      /* Unlock extended configuration registers */
++      outb(0x80, 0x3d4); outb(0xa8, 0x3d5);
++
++      /* Set CRT Request Threshold */
++      outb(0xa6, 0x3d4); outb(0x2f, 0x3d5);
++      outb(0xa7, 0x3d4); outb(0x3f, 0x3d5);
++
++      /* Initialize standard VGA text mode */
++      vga_io_init();
++      vga_textmode_init();
++      printk(BIOS_INFO, "ASpeed VGA text mode initialized\n");
++
++      /* if we don't have console, at least print something... */
++      vga_line_write(0, "ASpeed VGA text mode initialized");
++}
++
++static struct device_operations aspeed_ast2050_ops  = {
++      .read_resources   = pci_dev_read_resources,
++      .set_resources    = aspeed_ast2050_set_resources,
++      .enable_resources = pci_dev_enable_resources,
++      .init             = aspeed_ast2050_init,
++      .scan_bus         = 0,
++};
++
++static const struct pci_driver aspeed_ast2050_driver __pci_driver = {
++        .ops    = &aspeed_ast2050_ops,
++        .vendor = PCI_VENDOR_ID_ASPEED,
++        .device = PCI_DEVICE_ID_ASPEED_AST2050_VGA,
++};
+diff --git a/src/drivers/aspeed/common/Kconfig 
b/src/drivers/aspeed/common/Kconfig
+new file mode 100644
+index 0000000..0f7056b
+--- /dev/null
++++ b/src/drivers/aspeed/common/Kconfig
+@@ -0,0 +1,10 @@
++config DRIVERS_ASPEED_AST_COMMON
++      bool
++
++if !MAINBOARD_DO_NATIVE_VGA_INIT
++
++config DEVICE_SPECIFIC_OPTIONS # dummy
++      def_bool y
++      select VGA
++
++endif # MAINBOARD_DO_NATIVE_VGA_INIT
+diff --git a/src/drivers/aspeed/common/Makefile.inc 
b/src/drivers/aspeed/common/Makefile.inc
+new file mode 100644
+index 0000000..75f8b48
+--- /dev/null
++++ b/src/drivers/aspeed/common/Makefile.inc
+@@ -0,0 +1 @@
++ramstage-$(CONFIG_DRIVERS_ASPEED_AST_COMMON) += ast_dp501.c ast_main.c 
ast_post.c
+diff --git a/src/drivers/aspeed/common/aspeed_coreboot.h 
b/src/drivers/aspeed/common/aspeed_coreboot.h
+new file mode 100644
+index 0000000..237c23f
+--- /dev/null
++++ b/src/drivers/aspeed/common/aspeed_coreboot.h
+@@ -0,0 +1,210 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * 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, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef _ASPEED_COREBOOT_
++#define _ASPEED_COREBOOT_
++
++#include <delay.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <arch/io.h>
++
++#include <console/console.h>
++#include <device/device.h>
++#include <device/pci.h>
++#include <device/pci_ids.h>
++#include <device/pci_ops.h>
++
++/* coreboot <--> kernel code interface */
++#define __iomem
++typedef u64 phys_addr_t;
++#define pci_dev device
++
++#define SZ_16M 0x01000000
++
++#define min_t(type, x, y) ({                  \
++      type __min1 = (x);                      \
++      type __min2 = (y);                      \
++      __min1 < __min2 ? __min1 : __min2; })
++
++#define dev_info(dev, format, arg...) printk(BIOS_INFO, "ASpeed VGA: " 
format, ##arg)
++#define dev_dbg(dev, format, arg...) printk(BIOS_DEBUG, "ASpeed VGA: " 
format, ##arg)
++#define dev_err(dev, format, arg...) printk(BIOS_ERR, "ASpeed VGA: " format, 
##arg)
++
++#define pr_info(format, arg...) printk(BIOS_INFO, "ASpeed VGA: " format, 
##arg)
++#define pr_debug(format, arg...) printk(BIOS_INFO, "ASpeed VGA: " format, 
##arg)
++#define pr_err(format, arg...) printk(BIOS_ERR, "ASpeed VGA: " format, ##arg)
++
++#define DRM_INFO pr_info
++
++#define GFP_KERNEL 0
++#define GFP_ATOMIC 1
++#define kfree(address) free(address)
++
++#define EIO 5
++#define ENOMEM 12
++
++struct firmware {
++      size_t size;
++      const u8 *data;
++      struct page **pages;
++
++      /* firmware loader private fields */
++      void *priv;
++};
++
++struct drm_device {
++      struct pci_dev *pdev;
++      void *dev_private;
++};
++
++static inline void *kzalloc(size_t size, int flags) {
++      void* ptr = malloc(size);
++      memset(ptr, 0, size);
++      return ptr;
++}
++
++static inline void writel(u32 val, volatile void *addr) {
++      *(u32*)addr = val;
++}
++
++static inline u32 readl(const volatile void *addr) {
++      return *(u32*)addr;
++}
++
++static inline void writew(u16 val, volatile void *addr) {
++      *(u16*)addr = val;
++}
++
++static inline u16 readw(const volatile void *addr) {
++      return *(u16*)addr;
++}
++
++static inline void writeb(u8 val, volatile void *addr) {
++      *(u8*)addr = val;
++}
++
++static inline u8 readb(const volatile void *addr) {
++      return *(u8*)addr;
++}
++
++static inline int pci_read_config_dword(struct pci_dev *dev, int where,
++      u32 *val)
++{
++      *val = pci_read_config32(dev, where);
++      return 0;
++}
++
++static inline int pci_write_config_dword(struct pci_dev *dev, int where,
++      u32 val)
++{
++      pci_write_config32(dev, where, val);
++      return 0;
++}
++
++static inline int pci_read_config_byte(struct pci_dev *dev, int where,
++      u8 *val)
++{
++      *val = pci_read_config8(dev, where);
++      return 0;
++}
++
++static inline struct resource* resource_at_bar(struct pci_dev *dev, u8 bar) {
++      struct resource *res = dev->resource_list;
++      int i;
++      for (i = 0; i < bar; i++) {
++              res = res->next;
++              if (res == NULL)
++                      return NULL;
++      }
++
++      return res;
++}
++
++static inline resource_t pci_resource_len(struct pci_dev *dev, u8 bar) {
++      struct resource *res = resource_at_bar(dev, bar);
++      if (res)
++              return res->size;
++      else
++              return 0;
++}
++
++static inline resource_t pci_resource_start(struct pci_dev *dev, u8 bar) {
++      struct resource *res = resource_at_bar(dev, bar);
++      if (res)
++              return res->base;
++      else
++              return 0;
++}
++
++static inline unsigned int ioread32(void __iomem *p) {
++      return readl(p);
++}
++
++static inline void iowrite32(u32 val, void __iomem *p) {
++      writel(val, p);
++}
++
++static inline unsigned int ioread16(void __iomem *p) {
++      return readw(p);
++}
++
++static inline void iowrite16(u16 val, void __iomem *p) {
++      writew(val, p);
++}
++
++static inline unsigned int ioread8(void __iomem *p) {
++      return readb(p);
++}
++
++static inline void iowrite8(u8 val, void __iomem *p) {
++      writeb(val, p);
++}
++
++static inline unsigned int ioread_cbio32(void __iomem *p) {
++      return inl((uint16_t)((intptr_t)p));
++}
++
++static inline void iowrite_cbio32(u32 val, void __iomem *p) {
++      outl(val, (uint16_t)((intptr_t)p));
++}
++
++static inline unsigned int ioread_cbio16(void __iomem *p) {
++      return inw((uint16_t)((intptr_t)p));
++}
++
++static inline void iowrite_cbio16(u16 val, void __iomem *p) {
++      outw(val, (uint16_t)((intptr_t)p));
++}
++
++static inline unsigned int ioread_cbio8(void __iomem *p) {
++      return inb((uint16_t)((intptr_t)p));
++}
++
++static inline void iowrite_cbio8(u8 val, void __iomem *p) {
++      outb(val, (uint16_t)((intptr_t)p));
++}
++
++static inline void msleep(unsigned int msecs) {
++      udelay(msecs * 1000);
++}
++
++#endif
+\ No newline at end of file
+diff --git a/src/drivers/aspeed/common/ast_dp501.c 
b/src/drivers/aspeed/common/ast_dp501.c
+new file mode 100644
+index 0000000..5be8ec3
+--- /dev/null
++++ b/src/drivers/aspeed/common/ast_dp501.c
+@@ -0,0 +1,443 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * File taken from the Linux ast driver (v3.18.5)
++ * Coreboot-specific includes added at top and/or contents modified
++ * as needed to function within the coreboot environment.
++ *
++ * 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.
++ */
++
++#include "ast_drv.h"
++
++static void send_ack(struct ast_private *ast)
++{
++      u8 sendack;
++      sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
++      sendack |= 0x80;
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
++}
++
++static void send_nack(struct ast_private *ast)
++{
++      u8 sendack;
++      sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
++      sendack &= ~0x80;
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
++}
++
++static bool wait_ack(struct ast_private *ast)
++{
++      u8 waitack;
++      u32 retry = 0;
++      do {
++              waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 
0xff);
++              waitack &= 0x80;
++              udelay(100);
++      } while ((!waitack) && (retry++ < 1000));
++
++      if (retry < 1000)
++              return true;
++      else
++              return false;
++}
++
++static bool wait_nack(struct ast_private *ast)
++{
++      u8 waitack;
++      u32 retry = 0;
++      do {
++              waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 
0xff);
++              waitack &= 0x80;
++              udelay(100);
++      } while ((waitack) && (retry++ < 1000));
++
++      if (retry < 1000)
++              return true;
++      else
++              return false;
++}
++
++static void set_cmd_trigger(struct ast_private *ast)
++{
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40);
++}
++
++static void clear_cmd_trigger(struct ast_private *ast)
++{
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00);
++}
++
++#if 0
++static bool wait_fw_ready(struct ast_private *ast)
++{
++      u8 waitready;
++      u32 retry = 0;
++      do {
++              waitready = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 
0xff);
++              waitready &= 0x40;
++              udelay(100);
++      } while ((!waitready) && (retry++ < 1000));
++
++      if (retry < 1000)
++              return true;
++      else
++              return false;
++}
++#endif
++
++static bool ast_write_cmd(struct drm_device *dev, u8 data)
++{
++      struct ast_private *ast = dev->dev_private;
++      int retry = 0;
++      if (wait_nack(ast)) {
++              send_nack(ast);
++              ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
++              send_ack(ast);
++              set_cmd_trigger(ast);
++              do {
++                      if (wait_ack(ast)) {
++                              clear_cmd_trigger(ast);
++                              send_nack(ast);
++                              return true;
++                      }
++              } while (retry++ < 100);
++      }
++      clear_cmd_trigger(ast);
++      send_nack(ast);
++      return false;
++}
++
++static bool ast_write_data(struct drm_device *dev, u8 data)
++{
++      struct ast_private *ast = dev->dev_private;
++
++      if (wait_nack(ast)) {
++              send_nack(ast);
++              ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
++              send_ack(ast);
++              if (wait_ack(ast)) {
++                      send_nack(ast);
++                      return true;
++              }
++      }
++      send_nack(ast);
++      return false;
++}
++
++#if 0
++static bool ast_read_data(struct drm_device *dev, u8 *data)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 tmp;
++
++      *data = 0;
++
++      if (wait_ack(ast) == false)
++              return false;
++      tmp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd3, 0xff);
++      *data = tmp;
++      if (wait_nack(ast) == false) {
++              send_nack(ast);
++              return false;
++      }
++      send_nack(ast);
++      return true;
++}
++
++static void clear_cmd(struct ast_private *ast)
++{
++      send_nack(ast);
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00);
++}
++#endif
++
++void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
++{
++      ast_write_cmd(dev, 0x40);
++      ast_write_data(dev, mode);
++
++      msleep(10);
++}
++
++static u32 get_fw_base(struct ast_private *ast)
++{
++      return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
++}
++
++bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
++{
++      struct ast_private *ast = dev->dev_private;
++      u32 i, data;
++      u32 boot_address;
++
++      data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
++      if (data) {
++              boot_address = get_fw_base(ast);
++              for (i = 0; i < size; i += 4)
++                      *(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);
++              return true;
++      }
++      return false;
++}
++
++bool ast_launch_m68k(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u32 i, data, len = 0;
++      u32 boot_address;
++      u8 *fw_addr = NULL;
++      u8 jreg;
++
++      data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
++      if (!data) {
++
++              if (ast->dp501_fw_addr) {
++                      fw_addr = ast->dp501_fw_addr;
++                      len = 32*1024;
++              } else if (ast->dp501_fw) {
++                      fw_addr = (u8 *)ast->dp501_fw->data;
++                      len = ast->dp501_fw->size;
++              }
++              /* Get BootAddress */
++              ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
++              data = ast_mindwm(ast, 0x1e6e0004);
++              switch (data & 0x03) {
++              case 0:
++                      boot_address = 0x44000000;
++                      break;
++              default:
++              case 1:
++                      boot_address = 0x48000000;
++                      break;
++              case 2:
++                      boot_address = 0x50000000;
++                      break;
++              case 3:
++                      boot_address = 0x60000000;
++                      break;
++              }
++              boot_address -= 0x200000; /* -2MB */
++
++              /* copy image to buffer */
++              for (i = 0; i < len; i += 4) {
++                      data = *(u32 *)(fw_addr + i);
++                      ast_moutdwm(ast, boot_address + i, data);
++              }
++
++              /* Init SCU */
++              ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
++
++              /* Launch FW */
++              ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
++              ast_moutdwm(ast, 0x1e6e2100, 1);
++
++              /* Update Scratch */
++              data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff;                
/* D[11:9] = 100b: UEFI handling */
++              data |= 0x800;
++              ast_moutdwm(ast, 0x1e6e2040, data);
++
++              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 
0xfc); /* D[1:0]: Reserved Video Buffer */
++              jreg |= 0x02;
++              ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg);
++      }
++      return true;
++}
++
++u8 ast_get_dp501_max_clk(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u32 boot_address, offset, data;
++      u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
++
++      boot_address = get_fw_base(ast);
++
++      /* validate FW version */
++      offset = 0xf000;
++      data = ast_mindwm(ast, boot_address + offset);
++      if ((data & 0xf0) != 0x10) /* version: 1x */
++              return maxclk;
++
++      /* Read Link Capability */
++      offset  = 0xf014;
++      data = ast_mindwm(ast, boot_address + offset);
++      linkcap[0] = (data & 0xff000000) >> 24;
++      linkcap[1] = (data & 0x00ff0000) >> 16;
++      linkcap[2] = (data & 0x0000ff00) >> 8;
++      linkcap[3] = (data & 0x000000ff);
++      if (linkcap[2] == 0) {
++              linkrate = linkcap[0];
++              linklanes = linkcap[1];
++              data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
++              if (data > 0xff)
++                      data = 0xff;
++              maxclk = (u8)data;
++      }
++      return maxclk;
++}
++
++bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
++{
++      struct ast_private *ast = dev->dev_private;
++      u32 i, boot_address, offset, data;
++
++      boot_address = get_fw_base(ast);
++
++      /* validate FW version */
++      offset = 0xf000;
++      data = ast_mindwm(ast, boot_address + offset);
++      if ((data & 0xf0) != 0x10)
++              return false;
++
++      /* validate PnP Monitor */
++      offset = 0xf010;
++      data = ast_mindwm(ast, boot_address + offset);
++      if (!(data & 0x01))
++              return false;
++
++      /* Read EDID */
++      offset = 0xf020;
++      for (i = 0; i < 128; i += 4) {
++              data = ast_mindwm(ast, boot_address + offset + i);
++              *(u32 *)(ediddata + i) = data;
++      }
++
++      return true;
++}
++
++static bool ast_init_dvo(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 jreg;
++      u32 data;
++      ast_write32(ast, 0xf004, 0x1e6e0000);
++      ast_write32(ast, 0xf000, 0x1);
++      ast_write32(ast, 0x12000, 0x1688a8a8);
++
++      jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
++      if (!(jreg & 0x80)) {
++              /* Init SCU DVO Settings */
++              data = ast_read32(ast, 0x12008);
++              /* delay phase */
++              data &= 0xfffff8ff;
++              data |= 0x00000500;
++              ast_write32(ast, 0x12008, data);
++
++              if (ast->chip == AST2300) {
++                      data = ast_read32(ast, 0x12084);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0xfffe0000;
++                      ast_write32(ast, 0x12084, data);
++
++                      data = ast_read32(ast, 0x12088);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0x000fffff;
++                      ast_write32(ast, 0x12088, data);
++
++                      data = ast_read32(ast, 0x12090);
++                      /* multi-pins for DVO single-edge */
++                      data &= 0xffffffcf;
++                      data |= 0x00000020;
++                      ast_write32(ast, 0x12090, data);
++              } else { /* AST2400 */
++                      data = ast_read32(ast, 0x12088);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0x30000000;
++                      ast_write32(ast, 0x12088, data);
++
++                      data = ast_read32(ast, 0x1208c);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0x000000cf;
++                      ast_write32(ast, 0x1208c, data);
++
++                      data = ast_read32(ast, 0x120a4);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0xffff0000;
++                      ast_write32(ast, 0x120a4, data);
++
++                      data = ast_read32(ast, 0x120a8);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0x0000000f;
++                      ast_write32(ast, 0x120a8, data);
++
++                      data = ast_read32(ast, 0x12094);
++                      /* multi-pins for DVO single-edge */
++                      data |= 0x00000002;
++                      ast_write32(ast, 0x12094, data);
++              }
++      }
++
++      /* Force to DVO */
++      data = ast_read32(ast, 0x1202c);
++      data &= 0xfffbffff;
++      ast_write32(ast, 0x1202c, data);
++
++      /* Init VGA DVO Settings */
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);
++      return true;
++}
++
++
++static void ast_init_analog(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u32 data;
++
++      /*
++       * Set DAC source to VGA mode in SCU2C via the P2A
++       * bridge. First configure the P2U to target the SCU
++       * in case it isn't at this stage.
++       */
++      ast_write32(ast, 0xf004, 0x1e6e0000);
++      ast_write32(ast, 0xf000, 0x1);
++
++      /* Then unlock the SCU with the magic password */
++      ast_write32(ast, 0x12000, 0x1688a8a8);
++      ast_write32(ast, 0x12000, 0x1688a8a8);
++      ast_write32(ast, 0x12000, 0x1688a8a8);
++
++      /* Finally, clear bits [17:16] of SCU2c */
++      data = ast_read32(ast, 0x1202c);
++      data &= 0xfffcffff;
++      ast_write32(ast, 0, data);
++
++      /* Disable DVO */
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00);
++}
++
++void ast_init_3rdtx(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 jreg;
++
++      if (ast->chip == AST2300 || ast->chip == AST2400) {
++              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 
0xff);
++              switch (jreg & 0x0e) {
++              case 0x04:
++                      ast_init_dvo(dev);
++                      break;
++              case 0x08:
++                      ast_launch_m68k(dev);
++                      break;
++              case 0x0c:
++                      ast_init_dvo(dev);
++                      break;
++              default:
++                      if (ast->tx_chip_type == AST_TX_SIL164)
++                              ast_init_dvo(dev);
++                      else
++                              ast_init_analog(dev);
++              }
++      }
++}
+diff --git a/src/drivers/aspeed/common/ast_dram_tables.h 
b/src/drivers/aspeed/common/ast_dram_tables.h
+new file mode 100644
+index 0000000..4884cba
+--- /dev/null
++++ b/src/drivers/aspeed/common/ast_dram_tables.h
+@@ -0,0 +1,165 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * File taken from the Linux ast driver (v3.18.5)
++ * Coreboot-specific includes added at top and/or contents modified
++ * as needed to function within the coreboot environment.
++ *
++ * 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.
++ */
++
++#ifndef AST_DRAM_TABLES_H
++#define AST_DRAM_TABLES_H
++
++/* DRAM timing tables */
++struct ast_dramstruct {
++      u16 index;
++      u32 data;
++};
++
++static const struct ast_dramstruct ast2000_dram_table_data[] = {
++      { 0x0108, 0x00000000 },
++      { 0x0120, 0x00004a21 },
++      { 0xFF00, 0x00000043 },
++      { 0x0000, 0xFFFFFFFF },
++      { 0x0004, 0x00000089 },
++      { 0x0008, 0x22331353 },
++      { 0x000C, 0x0d07000b },
++      { 0x0010, 0x11113333 },
++      { 0x0020, 0x00110350 },
++      { 0x0028, 0x1e0828f0 },
++      { 0x0024, 0x00000001 },
++      { 0x001C, 0x00000000 },
++      { 0x0014, 0x00000003 },
++      { 0xFF00, 0x00000043 },
++      { 0x0018, 0x00000131 },
++      { 0x0014, 0x00000001 },
++      { 0xFF00, 0x00000043 },
++      { 0x0018, 0x00000031 },
++      { 0x0014, 0x00000001 },
++      { 0xFF00, 0x00000043 },
++      { 0x0028, 0x1e0828f1 },
++      { 0x0024, 0x00000003 },
++      { 0x002C, 0x1f0f28fb },
++      { 0x0030, 0xFFFFFE01 },
++      { 0xFFFF, 0xFFFFFFFF }
++};
++
++static const struct ast_dramstruct ast1100_dram_table_data[] = {
++      { 0x2000, 0x1688a8a8 },
++      { 0x2020, 0x000041f0 },
++      { 0xFF00, 0x00000043 },
++      { 0x0000, 0xfc600309 },
++      { 0x006C, 0x00909090 },
++      { 0x0064, 0x00050000 },
++      { 0x0004, 0x00000585 },
++      { 0x0008, 0x0011030f },
++      { 0x0010, 0x22201724 },
++      { 0x0018, 0x1e29011a },
++      { 0x0020, 0x00c82222 },
++      { 0x0014, 0x01001523 },
++      { 0x001C, 0x1024010d },
++      { 0x0024, 0x00cb2522 },
++      { 0x0038, 0xffffff82 },
++      { 0x003C, 0x00000000 },
++      { 0x0040, 0x00000000 },
++      { 0x0044, 0x00000000 },
++      { 0x0048, 0x00000000 },
++      { 0x004C, 0x00000000 },
++      { 0x0050, 0x00000000 },
++      { 0x0054, 0x00000000 },
++      { 0x0058, 0x00000000 },
++      { 0x005C, 0x00000000 },
++      { 0x0060, 0x032aa02a },
++      { 0x0064, 0x002d3000 },
++      { 0x0068, 0x00000000 },
++      { 0x0070, 0x00000000 },
++      { 0x0074, 0x00000000 },
++      { 0x0078, 0x00000000 },
++      { 0x007C, 0x00000000 },
++      { 0x0034, 0x00000001 },
++      { 0xFF00, 0x00000043 },
++      { 0x002C, 0x00000732 },
++      { 0x0030, 0x00000040 },
++      { 0x0028, 0x00000005 },
++      { 0x0028, 0x00000007 },
++      { 0x0028, 0x00000003 },
++      { 0x0028, 0x00000001 },
++      { 0x000C, 0x00005a08 },
++      { 0x002C, 0x00000632 },
++      { 0x0028, 0x00000001 },
++      { 0x0030, 0x000003c0 },
++      { 0x0028, 0x00000003 },
++      { 0x0030, 0x00000040 },
++      { 0x0028, 0x00000003 },
++      { 0x000C, 0x00005a21 },
++      { 0x0034, 0x00007c03 },
++      { 0x0120, 0x00004c41 },
++      { 0xffff, 0xffffffff },
++};
++
++static const struct ast_dramstruct ast2100_dram_table_data[] = {
++      { 0x2000, 0x1688a8a8 },
++      { 0x2020, 0x00004120 },
++      { 0xFF00, 0x00000043 },
++      { 0x0000, 0xfc600309 },
++      { 0x006C, 0x00909090 },
++      { 0x0064, 0x00070000 },
++      { 0x0004, 0x00000489 },
++      { 0x0008, 0x0011030f },
++      { 0x0010, 0x32302926 },
++      { 0x0018, 0x274c0122 },
++      { 0x0020, 0x00ce2222 },
++      { 0x0014, 0x01001523 },
++      { 0x001C, 0x1024010d },
++      { 0x0024, 0x00cb2522 },
++      { 0x0038, 0xffffff82 },
++      { 0x003C, 0x00000000 },
++      { 0x0040, 0x00000000 },
++      { 0x0044, 0x00000000 },
++      { 0x0048, 0x00000000 },
++      { 0x004C, 0x00000000 },
++      { 0x0050, 0x00000000 },
++      { 0x0054, 0x00000000 },
++      { 0x0058, 0x00000000 },
++      { 0x005C, 0x00000000 },
++      { 0x0060, 0x0f2aa02a },
++      { 0x0064, 0x003f3005 },
++      { 0x0068, 0x02020202 },
++      { 0x0070, 0x00000000 },
++      { 0x0074, 0x00000000 },
++      { 0x0078, 0x00000000 },
++      { 0x007C, 0x00000000 },
++      { 0x0034, 0x00000001 },
++      { 0xFF00, 0x00000043 },
++      { 0x002C, 0x00000942 },
++      { 0x0030, 0x00000040 },
++      { 0x0028, 0x00000005 },
++      { 0x0028, 0x00000007 },
++      { 0x0028, 0x00000003 },
++      { 0x0028, 0x00000001 },
++      { 0x000C, 0x00005a08 },
++      { 0x002C, 0x00000842 },
++      { 0x0028, 0x00000001 },
++      { 0x0030, 0x000003c0 },
++      { 0x0028, 0x00000003 },
++      { 0x0030, 0x00000040 },
++      { 0x0028, 0x00000003 },
++      { 0x000C, 0x00005a21 },
++      { 0x0034, 0x00007c03 },
++      { 0x0120, 0x00005061 },
++      { 0xffff, 0xffffffff },
++};
++
++#endif
+diff --git a/src/drivers/aspeed/common/ast_drv.h 
b/src/drivers/aspeed/common/ast_drv.h
+new file mode 100644
+index 0000000..53640f1
+--- /dev/null
++++ b/src/drivers/aspeed/common/ast_drv.h
+@@ -0,0 +1,223 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 
CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
++ * USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ */
++/*
++ * Authors: Dave Airlie <address@hidden>
++ */
++#ifndef __AST_DRV_H__
++#define __AST_DRV_H__
++
++#include "aspeed_coreboot.h"
++
++#define PCI_CHIP_AST2000 0x2000
++#define PCI_CHIP_AST2100 0x2010
++#define PCI_CHIP_AST1180 0x1180
++
++
++enum ast_chip {
++      AST2000,
++      AST2100,
++      AST1100,
++      AST2200,
++      AST2150,
++      AST2300,
++      AST2400,
++      AST1180,
++};
++
++enum ast_tx_chip {
++      AST_TX_NONE,
++      AST_TX_SIL164,
++      AST_TX_ITE66121,
++      AST_TX_DP501,
++};
++
++#define AST_DRAM_512Mx16 0
++#define AST_DRAM_1Gx16   1
++#define AST_DRAM_512Mx32 2
++#define AST_DRAM_1Gx32   3
++#define AST_DRAM_2Gx16   6
++#define AST_DRAM_4Gx16   7
++
++struct ast_fbdev;
++
++struct ast_private {
++      struct drm_device *dev;
++
++      void __iomem *regs;
++      void __iomem *ioregs;
++      bool io_space_uses_mmap;
++
++      enum ast_chip chip;
++      bool vga2_clone;
++      uint32_t dram_bus_width;
++      uint32_t dram_type;
++      uint32_t mclk;
++      uint32_t vram_size;
++
++      struct ast_fbdev *fbdev;
++
++      int fb_mtrr;
++
++      struct drm_gem_object *cursor_cache;
++      uint64_t cursor_cache_gpu_addr;
++
++      int next_cursor;
++      bool support_wide_screen;
++
++      enum ast_tx_chip tx_chip_type;
++      u8 dp501_maxclk;
++      u8 *dp501_fw_addr;
++      const struct firmware *dp501_fw;        /* dp501 fw */
++};
++
++int ast_driver_load(struct drm_device *dev, unsigned long flags);
++int ast_driver_unload(struct drm_device *dev);
++
++#define AST_IO_AR_PORT_WRITE          (0x40)
++#define AST_IO_MISC_PORT_WRITE                (0x42)
++#define AST_IO_VGA_ENABLE_PORT                (0x43)
++#define AST_IO_SEQ_PORT                       (0x44)
++#define AST_IO_DAC_INDEX_READ         (0x47)
++#define AST_IO_DAC_INDEX_WRITE                (0x48)
++#define AST_IO_DAC_DATA                       (0x49)
++#define AST_IO_GR_PORT                        (0x4E)
++#define AST_IO_CRTC_PORT              (0x54)
++#define AST_IO_INPUT_STATUS1_READ     (0x5A)
++#define AST_IO_MISC_PORT_READ         (0x4C)
++
++#define AST_IO_MM_OFFSET              (0x380)
++
++#define __ast_read(x) \
++static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \
++u##x val = 0;\
++val = ioread##x(ast->regs + reg); \
++return val;\
++}
++
++__ast_read(8);
++__ast_read(16);
++__ast_read(32)
++
++#define __ast_io_read(x) \
++static inline u##x ast_io_read##x(struct ast_private *ast, u32 reg) { \
++u##x val = 0;\
++if (ast->io_space_uses_mmap) \
++val = ioread##x(ast->regs + reg); \
++else \
++val = ioread_cbio##x(ast->ioregs + reg); \
++return val;\
++}
++
++__ast_io_read(8);
++__ast_io_read(16);
++__ast_io_read(32);
++
++#define __ast_write(x) \
++static inline void ast_write##x(struct ast_private *ast, u32 reg, u##x val) {\
++      iowrite##x(val, ast->regs + reg);\
++      }
++
++__ast_write(8);
++__ast_write(16);
++__ast_write(32);
++
++#define __ast_io_write(x) \
++static inline void ast_io_write##x(struct ast_private *ast, u32 reg, u##x 
val) {\
++      if (ast->io_space_uses_mmap) \
++      iowrite##x(val, ast->regs + reg);\
++      else \
++      iowrite_cbio##x(val, ast->ioregs + reg);\
++      }
++
++__ast_io_write(8);
++__ast_io_write(16);
++#undef __ast_io_write
++
++static inline void ast_set_index_reg(struct ast_private *ast,
++                                   uint32_t base, uint8_t index,
++                                   uint8_t val)
++{
++      ast_io_write16(ast, base, ((u16)val << 8) | index);
++}
++
++void ast_set_index_reg_mask(struct ast_private *ast,
++                          uint32_t base, uint8_t index,
++                          uint8_t mask, uint8_t val);
++uint8_t ast_get_index_reg(struct ast_private *ast,
++                        uint32_t base, uint8_t index);
++uint8_t ast_get_index_reg_mask(struct ast_private *ast,
++                             uint32_t base, uint8_t index, uint8_t mask);
++
++static inline void ast_open_key(struct ast_private *ast)
++{
++      ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8);
++}
++
++#define AST_VIDMEM_SIZE_8M    0x00800000
++#define AST_VIDMEM_SIZE_16M   0x01000000
++#define AST_VIDMEM_SIZE_32M   0x02000000
++#define AST_VIDMEM_SIZE_64M   0x04000000
++#define AST_VIDMEM_SIZE_128M  0x08000000
++
++#define AST_VIDMEM_DEFAULT_SIZE AST_VIDMEM_SIZE_8M
++
++#define AST_MAX_HWC_WIDTH 64
++#define AST_MAX_HWC_HEIGHT 64
++
++#define AST_HWC_SIZE                (AST_MAX_HWC_WIDTH*AST_MAX_HWC_HEIGHT*2)
++#define AST_HWC_SIGNATURE_SIZE      32
++
++#define AST_DEFAULT_HWC_NUM 2
++/* define for signature structure */
++#define AST_HWC_SIGNATURE_CHECKSUM  0x00
++#define AST_HWC_SIGNATURE_SizeX     0x04
++#define AST_HWC_SIGNATURE_SizeY     0x08
++#define AST_HWC_SIGNATURE_X         0x0C
++#define AST_HWC_SIGNATURE_Y         0x10
++#define AST_HWC_SIGNATURE_HOTSPOTX  0x14
++#define AST_HWC_SIGNATURE_HOTSPOTY  0x18
++
++#define AST_MM_ALIGN_SHIFT 4
++#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
++
++#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
++
++/* ast post */
++void ast_enable_vga(struct drm_device *dev);
++void ast_enable_mmio(struct drm_device *dev);
++bool ast_is_vga_enabled(struct drm_device *dev);
++void ast_post_gpu(struct drm_device *dev);
++u32 ast_mindwm(struct ast_private *ast, u32 r);
++void ast_moutdwm(struct ast_private *ast, u32 r, u32 v);
++/* ast dp501 */
++int ast_load_dp501_microcode(struct drm_device *dev);
++void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
++bool ast_launch_m68k(struct drm_device *dev);
++bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
++bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
++u8 ast_get_dp501_max_clk(struct drm_device *dev);
++void ast_init_3rdtx(struct drm_device *dev);
++#endif
+diff --git a/src/drivers/aspeed/common/ast_main.c 
b/src/drivers/aspeed/common/ast_main.c
+new file mode 100644
+index 0000000..2939442
+--- /dev/null
++++ b/src/drivers/aspeed/common/ast_main.c
+@@ -0,0 +1,393 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 
CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
++ * USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ */
++/*
++ * Authors: Dave Airlie <address@hidden>
++ */
++#include "ast_drv.h"
++
++#include "ast_dram_tables.h"
++
++void ast_set_index_reg_mask(struct ast_private *ast,
++                          uint32_t base, uint8_t index,
++                          uint8_t mask, uint8_t val)
++{
++      u8 tmp;
++      ast_io_write8(ast, base, index);
++      tmp = (ast_io_read8(ast, base + 1) & mask) | val;
++      ast_set_index_reg(ast, base, index, tmp);
++}
++
++uint8_t ast_get_index_reg(struct ast_private *ast,
++                        uint32_t base, uint8_t index)
++{
++      uint8_t ret;
++      ast_io_write8(ast, base, index);
++      ret = ast_io_read8(ast, base + 1);
++      return ret;
++}
++
++uint8_t ast_get_index_reg_mask(struct ast_private *ast,
++                             uint32_t base, uint8_t index, uint8_t mask)
++{
++      uint8_t ret;
++      ast_io_write8(ast, base, index);
++      ret = ast_io_read8(ast, base + 1) & mask;
++      return ret;
++}
++
++
++static int ast_detect_chip(struct drm_device *dev, bool *need_post)
++{
++      struct ast_private *ast = dev->dev_private;
++      uint32_t data, jreg;
++      ast_open_key(ast);
++
++      if (dev->pdev->device == PCI_CHIP_AST1180) {
++              ast->chip = AST1100;
++              DRM_INFO("AST 1180 detected\n");
++      } else {
++              pci_read_config_dword(ast->dev->pdev, 0x08, &data);
++              uint8_t revision = data & 0xff;
++
++              if (revision >= 0x30) {
++                      ast->chip = AST2400;
++                      DRM_INFO("AST 2400 detected\n");
++              } else if (revision >= 0x20) {
++                      ast->chip = AST2300;
++                      DRM_INFO("AST 2300 detected\n");
++              } else if (revision >= 0x10) {
++                      ast_write32(ast, 0xf004, 0x1e6e0000);
++                      ast_write32(ast, 0xf000, 0x1);
++
++                      data = ast_read32(ast, 0x1207c);
++                      switch (data & 0x0300) {
++                      case 0x0200:
++                              ast->chip = AST1100;
++                              DRM_INFO("AST 1100 detected\n");
++                              break;
++                      case 0x0100:
++                              ast->chip = AST2200;
++                              DRM_INFO("AST 2200 detected\n");
++                              break;
++                      case 0x0000:
++                              ast->chip = AST2150;
++                              DRM_INFO("AST 2150 detected\n");
++                              break;
++                      default:
++                              ast->chip = AST2100;
++                              DRM_INFO("AST 2100 detected\n");
++                              break;
++                      }
++                      ast->vga2_clone = false;
++              } else {
++                      ast->chip = AST2000;
++                      DRM_INFO("AST 2000 detected\n");
++              }
++      }
++
++      /*
++       * If VGA isn't enabled, we need to enable now or subsequent
++       * access to the scratch registers will fail. We also inform
++       * our caller that it needs to POST the chip
++       * (Assumption: VGA not enabled -> need to POST)
++       */
++      if (!ast_is_vga_enabled(dev)) {
++              ast_enable_vga(dev);
++              ast_enable_mmio(dev);
++              DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
++              *need_post = true;
++      } else
++              *need_post = false;
++
++      /* Check if we support wide screen */
++      switch (ast->chip) {
++      case AST1180:
++              ast->support_wide_screen = true;
++              break;
++      case AST2000:
++              ast->support_wide_screen = false;
++              break;
++      default:
++              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 
0xff);
++              if (!(jreg & 0x80))
++                      ast->support_wide_screen = true;
++              else if (jreg & 0x01)
++                      ast->support_wide_screen = true;
++              else {
++                      ast->support_wide_screen = false;
++                      /* Read SCU7c (silicon revision register) */
++                      ast_write32(ast, 0xf004, 0x1e6e0000);
++                      ast_write32(ast, 0xf000, 0x1);
++                      data = ast_read32(ast, 0x1207c);
++                      data &= 0x300;
++                      if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
++                              ast->support_wide_screen = true;
++                      if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
++                              ast->support_wide_screen = true;
++              }
++              break;
++      }
++
++      /* Check 3rd Tx option (digital output afaik) */
++      ast->tx_chip_type = AST_TX_NONE;
++
++      /*
++       * VGACRA3 Enhanced Color Mode Register, check if DVO is already
++       * enabled, in that case, assume we have a SIL164 TMDS transmitter
++       *
++       * Don't make that assumption if we the chip wasn't enabled and
++       * is at power-on reset, otherwise we'll incorrectly "detect" a
++       * SIL164 when there is none.
++       */
++      if (!*need_post) {
++              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 
0xff);
++              if (jreg & 0x80)
++                      ast->tx_chip_type = AST_TX_SIL164;
++      }
++
++      if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
++              /*
++               * On AST2300 and 2400, look the configuration set by the SoC in
++               * the SOC scratch register #1 bits 11:8 (interestingly marked
++               * as "reserved" in the spec)
++               */
++              jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 
0xff);
++              switch (jreg) {
++              case 0x04:
++                      ast->tx_chip_type = AST_TX_SIL164;
++                      break;
++              case 0x08:
++                      ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL);
++                      if (ast->dp501_fw_addr) {
++                              /* backup firmware */
++                              if (ast_backup_fw(dev, ast->dp501_fw_addr, 
32*1024)) {
++                                      kfree(ast->dp501_fw_addr);
++                                      ast->dp501_fw_addr = NULL;
++                              }
++                      }
++                      /* fallthrough */
++              case 0x0c:
++                      ast->tx_chip_type = AST_TX_DP501;
++              }
++      }
++
++      /* Print stuff for diagnostic purposes */
++      switch(ast->tx_chip_type) {
++      case AST_TX_SIL164:
++              DRM_INFO("Using Sil164 TMDS transmitter\n");
++              break;
++      case AST_TX_DP501:
++              DRM_INFO("Using DP501 DisplayPort transmitter\n");
++              break;
++      default:
++              DRM_INFO("Analog VGA only\n");
++      }
++      return 0;
++}
++
++static int ast_get_dram_info(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      uint8_t i;
++      uint32_t data, data2;
++      uint32_t denum, num, div, ref_pll;
++
++      ast_write32(ast, 0xf004, 0x1e6e0000);
++      ast_write32(ast, 0xf000, 0x1);
++
++
++      ast_write32(ast, 0x10000, 0xfc600309);
++
++      /* Wait up to 2.5 seconds for device initialization / register unlock */
++      for (i = 0; i < 250; i++) {
++              if (ast_read32(ast, 0x10000) == 0x01)
++                      break;
++              mdelay(10);
++      }
++      if (ast_read32(ast, 0x10000) != 0x01)
++              dev_err(dev->pdev, "Unable to unlock SDRAM control 
registers\n");
++
++      data = ast_read32(ast, 0x10004);
++
++      if (data & 0x400)
++              ast->dram_bus_width = 16;
++      else
++              ast->dram_bus_width = 32;
++
++      if (ast->chip == AST2300 || ast->chip == AST2400) {
++              switch (data & 0x03) {
++              case 0:
++                      ast->dram_type = AST_DRAM_512Mx16;
++                      break;
++              default:
++              case 1:
++                      ast->dram_type = AST_DRAM_1Gx16;
++                      break;
++              case 2:
++                      ast->dram_type = AST_DRAM_2Gx16;
++                      break;
++              case 3:
++                      ast->dram_type = AST_DRAM_4Gx16;
++                      break;
++              }
++      } else {
++              switch (data & 0x0c) {
++              case 0:
++              case 4:
++                      ast->dram_type = AST_DRAM_512Mx16;
++                      break;
++              case 8:
++                      if (data & 0x40)
++                              ast->dram_type = AST_DRAM_1Gx16;
++                      else
++                              ast->dram_type = AST_DRAM_512Mx32;
++                      break;
++              case 0xc:
++                      ast->dram_type = AST_DRAM_1Gx32;
++                      break;
++              }
++      }
++
++      data = ast_read32(ast, 0x10120);
++      data2 = ast_read32(ast, 0x10170);
++      if (data2 & 0x2000)
++              ref_pll = 14318;
++      else
++              ref_pll = 12000;
++
++      denum = data & 0x1f;
++      num = (data & 0x3fe0) >> 5;
++      data = (data & 0xc000) >> 14;
++      switch (data) {
++      case 3:
++              div = 0x4;
++              break;
++      case 2:
++      case 1:
++              div = 0x2;
++              break;
++      default:
++              div = 0x1;
++              break;
++      }
++      ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
++      return 0;
++}
++
++static u32 ast_get_vram_info(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 jreg;
++      u32 vram_size;
++      ast_open_key(ast);
++
++      vram_size = AST_VIDMEM_DEFAULT_SIZE;
++      jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);
++      switch (jreg & 3) {
++      case 0: vram_size = AST_VIDMEM_SIZE_8M; break;
++      case 1: vram_size = AST_VIDMEM_SIZE_16M; break;
++      case 2: vram_size = AST_VIDMEM_SIZE_32M; break;
++      case 3: vram_size = AST_VIDMEM_SIZE_64M; break;
++      }
++
++      return vram_size;
++}
++
++int ast_driver_load(struct drm_device *dev, unsigned long flags)
++{
++      struct ast_private *ast;
++      bool need_post;
++      int ret = 0;
++      struct resource *res;
++
++      ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL);
++      if (!ast)
++              return -ENOMEM;
++
++      dev->dev_private = ast;
++      ast->dev = dev;
++
++      /* PCI BAR 1 */
++        res = find_resource(dev->pdev, 0x14);
++      if (!res) {
++              dev_err(dev->pdev, "BAR1 resource not found.\n");
++              ret = -EIO;
++              goto out_free;
++      }
++      ast->regs = res2mmio(res, 0, 0);
++      if (!ast->regs) {
++              ret = -EIO;
++              goto out_free;
++      }
++
++      /* PCI BAR 2 */
++      ast->io_space_uses_mmap = false;
++      res = find_resource(dev->pdev, 0x18);
++      if (!res) {
++              dev_err(dev->pdev, "BAR2 resource not found.\n");
++              ret = -EIO;
++              goto out_free;
++      }
++
++      /*
++       * If we don't have IO space at all, use MMIO now and
++       * assume the chip has MMIO enabled by default (rev 0x20
++       * and higher).
++       */
++      if (!(res->flags & IORESOURCE_IO)) {
++              DRM_INFO("platform has no IO space, trying MMIO\n");
++              ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
++              ast->io_space_uses_mmap = true;
++      }
++
++      /* "map" IO regs if the above hasn't done so already */
++      if (!ast->ioregs) {
++              ast->ioregs = res2mmio(res, 0, 0);
++              if (!ast->ioregs) {
++                      ret = -EIO;
++                      goto out_free;
++              }
++              /* Adjust the I/O space location to match expectations (the 
code expects offset 0x0 to be I/O location 0x380) */
++              ast->ioregs = (void *)AST_IO_MM_OFFSET;
++      }
++
++      ast_detect_chip(dev, &need_post);
++
++      if (ast->chip != AST1180) {
++              ast_get_dram_info(dev);
++              ast->vram_size = ast_get_vram_info(dev);
++              DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, 
ast->dram_bus_width, ast->vram_size);
++      }
++
++      if (need_post)
++              ast_post_gpu(dev);
++
++      return 0;
++out_free:
++      kfree(ast);
++      dev->dev_private = NULL;
++      return ret;
++}
+diff --git a/src/drivers/aspeed/common/ast_post.c 
b/src/drivers/aspeed/common/ast_post.c
+new file mode 100644
+index 0000000..7d31845
+--- /dev/null
++++ b/src/drivers/aspeed/common/ast_post.c
+@@ -0,0 +1,1679 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 
CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
++ * USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ */
++/*
++ * Authors: Dave Airlie <address@hidden>
++ */
++
++#include "ast_drv.h"
++
++#include "ast_dram_tables.h"
++
++static void ast_init_dram_2300(struct drm_device *dev);
++
++void ast_enable_vga(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++
++      ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01);
++      ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);
++}
++
++void ast_enable_mmio(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
++}
++
++
++bool ast_is_vga_enabled(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 ch;
++
++      if (ast->chip == AST1180) {
++              /* TODO 1180 */
++      } else {
++              ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
++              if (ch) {
++                      ast_open_key(ast);
++                      ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xb6, 0xff);
++                      return ch & 0x04;
++              }
++      }
++      return 0;
++}
++
++static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
++static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff };
++static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };
++
++static void
++ast_set_def_ext_reg(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 i, index, reg;
++      uint32_t data;
++      const u8 *ext_reg_info;
++
++      pci_read_config_dword(ast->dev->pdev, 0x08, &data);
++      uint8_t revision = data & 0xff;
++
++      /* reset scratch */
++      for (i = 0x81; i <= 0x8f; i++)
++              ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
++
++      if (ast->chip == AST2300 || ast->chip == AST2400) {
++              if (revision >= 0x20)
++                      ext_reg_info = extreginfo_ast2300;
++              else
++                      ext_reg_info = extreginfo_ast2300a0;
++      } else
++              ext_reg_info = extreginfo;
++
++      index = 0xa0;
++      while (*ext_reg_info != 0xff) {
++              ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, 
*ext_reg_info);
++              index++;
++              ext_reg_info++;
++      }
++
++      /* disable standard IO/MEM decode if secondary */
++      /* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */
++
++      /* Set Ext. Default */
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01);
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00);
++
++      /* Enable RAMDAC for A1 */
++      reg = 0x04;
++      if (ast->chip == AST2300 || ast->chip == AST2400)
++              reg |= 0x20;
++      ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
++}
++
++u32 ast_mindwm(struct ast_private *ast, u32 r)
++{
++      uint32_t data;
++
++      ast_write32(ast, 0xf004, r & 0xffff0000);
++      ast_write32(ast, 0xf000, 0x1);
++
++      do {
++              data = ast_read32(ast, 0xf004) & 0xffff0000;
++      } while (data != (r & 0xffff0000));
++      return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
++}
++
++void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)
++{
++      uint32_t data;
++      ast_write32(ast, 0xf004, r & 0xffff0000);
++      ast_write32(ast, 0xf000, 0x1);
++      do {
++              data = ast_read32(ast, 0xf004) & 0xffff0000;
++      } while (data != (r & 0xffff0000));
++      ast_write32(ast, 0x10000 + (r & 0x0000ffff), v);
++}
++
++/*
++ * AST2100/2150 DLL CBR Setting
++ */
++#define CBR_SIZE_AST2150           ((16 << 10) - 1)
++#define CBR_PASSNUM_AST2150          5
++#define CBR_THRESHOLD_AST2150        10
++#define CBR_THRESHOLD2_AST2150       10
++#define TIMEOUT_AST2150              5000000
++
++#define CBR_PATNUM_AST2150           8
++
++static const u32 pattern_AST2150[14] = {
++      0xFF00FF00,
++      0xCC33CC33,
++      0xAA55AA55,
++      0xFFFE0001,
++      0x683501FE,
++      0x0F1929B0,
++      0x2D0B4346,
++      0x60767F02,
++      0x6FBE36A6,
++      0x3A253035,
++      0x3019686D,
++      0x41C6167E,
++      0x620152BF,
++      0x20F050E0
++};
++
++static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen)
++{
++      u32 data, timeout;
++
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
++              if (++timeout > TIMEOUT_AST2150) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++                      return 0xffffffff;
++              }
++      } while (!data);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
++              if (++timeout > TIMEOUT_AST2150) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++                      return 0xffffffff;
++              }
++      } while (!data);
++      data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      return data;
++}
++
++#if 0 /* unused in DDX driver - here for completeness */
++static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen)
++{
++      u32 data, timeout;
++
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
++              if (++timeout > TIMEOUT_AST2150) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++                      return 0xffffffff;
++              }
++      } while (!data);
++      data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      return data;
++}
++#endif
++
++static int cbrtest_ast2150(struct ast_private *ast)
++{
++      int i;
++
++      for (i = 0; i < 8; i++)
++              if (mmctestburst2_ast2150(ast, i))
++                      return 0;
++      return 1;
++}
++
++static int cbrscan_ast2150(struct ast_private *ast, int busw)
++{
++      u32 patcnt, loop;
++
++      for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
++              ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]);
++              for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
++                      if (cbrtest_ast2150(ast))
++                              break;
++              }
++              if (loop == CBR_PASSNUM_AST2150)
++                      return 0;
++      }
++      return 1;
++}
++
++
++static void cbrdlli_ast2150(struct ast_private *ast, int busw)
++{
++      u32 dll_min[4], dll_max[4], dlli, data, passcnt;
++
++cbr_start:
++      dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff;
++      dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0;
++      passcnt = 0;
++
++      for (dlli = 0; dlli < 100; dlli++) {
++              ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) 
| (dlli << 24));
++              data = cbrscan_ast2150(ast, busw);
++              if (data != 0) {
++                      if (data & 0x1) {
++                              if (dll_min[0] > dlli)
++                                      dll_min[0] = dlli;
++                              if (dll_max[0] < dlli)
++                                      dll_max[0] = dlli;
++                      }
++                      passcnt++;
++              } else if (passcnt >= CBR_THRESHOLD_AST2150)
++                      goto cbr_start;
++      }
++      if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150)
++              goto cbr_start;
++
++      dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
++      ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli 
<< 24));
++}
++
++
++
++static void ast_init_dram_reg(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      u8 j;
++      u32 data, temp, i;
++      const struct ast_dramstruct *dram_reg_info;
++
++      j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
++
++      if ((j & 0x80) == 0) { /* VGA only */
++              if (ast->chip == AST2000) {
++                      dram_reg_info = ast2000_dram_table_data;
++                      ast_write32(ast, 0xf004, 0x1e6e0000);
++                      ast_write32(ast, 0xf000, 0x1);
++                      ast_write32(ast, 0x10100, 0xa8);
++
++                      do {
++                              ;
++                      } while (ast_read32(ast, 0x10100) != 0xa8);
++              } else {/* AST2100/1100 */
++                      if (ast->chip == AST2100 || ast->chip == 2200)
++                              dram_reg_info = ast2100_dram_table_data;
++                      else
++                              dram_reg_info = ast1100_dram_table_data;
++
++                      ast_write32(ast, 0xf004, 0x1e6e0000);
++                      ast_write32(ast, 0xf000, 0x1);
++                      ast_write32(ast, 0x12000, 0x1688A8A8);
++
++                      /* Wait up to 2.5 seconds for device initialization / 
register unlock */
++                      for (i = 0; i < 250; i++) {
++                              if (ast_read32(ast, 0x12000) == 0x01)
++                                      break;
++                              mdelay(10);
++                      }
++                      if (ast_read32(ast, 0x12000) != 0x01)
++                              dev_err(dev->pdev, "Unable to unlock SCU 
registers\n");
++
++                      ast_write32(ast, 0x10000, 0xfc600309);
++
++                      /* Wait up to 2.5 seconds for device initialization / 
register unlock */
++                      for (i = 0; i < 250; i++) {
++                              if (ast_read32(ast, 0x10000) == 0x01)
++                                      break;
++                              mdelay(10);
++                      }
++                      if (ast_read32(ast, 0x10000) != 0x01)
++                              dev_err(dev->pdev, "Unable to unlock SDRAM 
control registers\n");
++              }
++
++              while (dram_reg_info->index != 0xffff) {
++                      if (dram_reg_info->index == 0xff00) {/* delay fn */
++                              for (i = 0; i < 15; i++)
++                                      udelay(dram_reg_info->data);
++                      } else if (dram_reg_info->index == 0x4 && ast->chip != 
AST2000) {
++                              data = dram_reg_info->data;
++                              if (ast->dram_type == AST_DRAM_1Gx16)
++                                      data = 0x00000d89;
++                              else if (ast->dram_type == AST_DRAM_1Gx32)
++                                      data = 0x00000c8d;
++
++                              temp = ast_read32(ast, 0x12070);
++                              temp &= 0xc;
++                              temp <<= 2;
++                              ast_write32(ast, 0x10000 + 
dram_reg_info->index, data | temp);
++                      } else
++                              ast_write32(ast, 0x10000 + 
dram_reg_info->index, dram_reg_info->data);
++                      dram_reg_info++;
++              }
++
++              /* AST 2100/2150 DRAM calibration */
++              data = ast_read32(ast, 0x10120);
++              if (data == 0x5061) { /* 266Mhz */
++                      data = ast_read32(ast, 0x10004);
++                      if (data & 0x40)
++                              cbrdlli_ast2150(ast, 16); /* 16 bits */
++                      else
++                              cbrdlli_ast2150(ast, 32); /* 32 bits */
++              }
++
++              switch (ast->chip) {
++              case AST2000:
++                      temp = ast_read32(ast, 0x10140);
++                      ast_write32(ast, 0x10140, temp | 0x40);
++                      break;
++              case AST1100:
++              case AST2100:
++              case AST2200:
++              case AST2150:
++                      temp = ast_read32(ast, 0x1200c);
++                      ast_write32(ast, 0x1200c, temp & 0xfffffffd);
++                      temp = ast_read32(ast, 0x12040);
++                      ast_write32(ast, 0x12040, temp | 0x40);
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      /* wait ready */
++      /* Wait up to 2.5 seconds for device to become ready */
++      for (i = 0; i < 250; i++) {
++              j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
++              mdelay(10);
++              if ((j & 0x40) != 0)
++                      break;
++      }
++      if ((j & 0x40) == 0)
++              dev_err(dev->pdev, "Timeout while waiting for device to signal 
ready\n");
++}
++
++void ast_post_gpu(struct drm_device *dev)
++{
++      u32 reg;
++      struct ast_private *ast = dev->dev_private;
++
++      pci_read_config_dword(ast->dev->pdev, 0x04, &reg);
++      reg |= 0x3;
++      pci_write_config_dword(ast->dev->pdev, 0x04, reg);
++
++      ast_enable_vga(dev);
++      ast_enable_mmio(dev);
++      ast_open_key(ast);
++      ast_set_def_ext_reg(dev);
++
++      if (ast->chip == AST2300 || ast->chip == AST2400)
++              ast_init_dram_2300(dev);
++      else
++              ast_init_dram_reg(dev);
++
++      ast_init_3rdtx(dev);
++}
++
++/* AST 2300 DRAM settings */
++#define AST_DDR3 0
++#define AST_DDR2 1
++
++struct ast2300_dram_param {
++      u32 dram_type;
++      u32 dram_chipid;
++      u32 dram_freq;
++      u32 vram_size;
++      u32 odt;
++      u32 wodt;
++      u32 rodt;
++      u32 dram_config;
++      u32 reg_PERIOD;
++      u32 reg_MADJ;
++      u32 reg_SADJ;
++      u32 reg_MRS;
++      u32 reg_EMRS;
++      u32 reg_AC1;
++      u32 reg_AC2;
++      u32 reg_DQSIC;
++      u32 reg_DRV;
++      u32 reg_IOZ;
++      u32 reg_DQIDLY;
++      u32 reg_FREQ;
++      u32 madj_max;
++      u32 dll2_finetune_step;
++};
++
++/*
++ * DQSI DLL CBR Setting
++ */
++#define CBR_SIZE0            ((1  << 10) - 1)
++#define CBR_SIZE1            ((4  << 10) - 1)
++#define CBR_SIZE2            ((64 << 10) - 1)
++#define CBR_PASSNUM          5
++#define CBR_PASSNUM2         5
++#define CBR_THRESHOLD        10
++#define CBR_THRESHOLD2       10
++#define TIMEOUT              5000000
++#define CBR_PATNUM           8
++
++static const u32 pattern[8] = {
++      0xFF00FF00,
++      0xCC33CC33,
++      0xAA55AA55,
++      0x88778877,
++      0x92CC4D6E,
++      0x543D3CDE,
++      0xF1E843C7,
++      0x7C61D253
++};
++
++static int mmc_test_burst(struct ast_private *ast, u32 datagen)
++{
++      u32 data, timeout;
++
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
++              if (data & 0x2000) {
++                      return 0;
++              }
++              if (++timeout > TIMEOUT) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++                      return 0;
++              }
++      } while (!data);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      return 1;
++}
++
++static int mmc_test_burst2(struct ast_private *ast, u32 datagen)
++{
++      u32 data, timeout;
++
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
++              if (++timeout > TIMEOUT) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x0);
++                      return -1;
++              }
++      } while (!data);
++      data = ast_mindwm(ast, 0x1e6e0078);
++      data = (data | (data >> 16)) & 0xffff;
++      ast_moutdwm(ast, 0x1e6e0070, 0x0);
++      return data;
++}
++
++static int mmc_test_single(struct ast_private *ast, u32 datagen)
++{
++      u32 data, timeout;
++
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
++              if (data & 0x2000)
++                      return 0;
++              if (++timeout > TIMEOUT) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x0);
++                      return 0;
++              }
++      } while (!data);
++      ast_moutdwm(ast, 0x1e6e0070, 0x0);
++      return 1;
++}
++
++static int mmc_test_single2(struct ast_private *ast, u32 datagen)
++{
++      u32 data, timeout;
++
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
++      ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
++      timeout = 0;
++      do {
++              data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
++              if (++timeout > TIMEOUT) {
++                      ast_moutdwm(ast, 0x1e6e0070, 0x0);
++                      return -1;
++              }
++      } while (!data);
++      data = ast_mindwm(ast, 0x1e6e0078);
++      data = (data | (data >> 16)) & 0xffff;
++      ast_moutdwm(ast, 0x1e6e0070, 0x0);
++      return data;
++}
++
++static int cbr_test(struct ast_private *ast)
++{
++      u32 data;
++      int i;
++      data = mmc_test_single2(ast, 0);
++      if ((data & 0xff) && (data & 0xff00))
++              return 0;
++      for (i = 0; i < 8; i++) {
++              data = mmc_test_burst2(ast, i);
++              if ((data & 0xff) && (data & 0xff00))
++                      return 0;
++      }
++      if (!data)
++              return 3;
++      else if (data & 0xff)
++              return 2;
++      return 1;
++}
++
++static int cbr_scan(struct ast_private *ast)
++{
++      u32 data, data2, patcnt, loop;
++
++      data2 = 3;
++      for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
++              ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
++              for (loop = 0; loop < CBR_PASSNUM2; loop++) {
++                      if ((data = cbr_test(ast)) != 0) {
++                              data2 &= data;
++                              if (!data2)
++                                      return 0;
++                              break;
++                      }
++              }
++              if (loop == CBR_PASSNUM2)
++                      return 0;
++      }
++      return data2;
++}
++
++static u32 cbr_test2(struct ast_private *ast)
++{
++      u32 data;
++
++      data = mmc_test_burst2(ast, 0);
++      if (data == 0xffff)
++              return 0;
++      data |= mmc_test_single2(ast, 0);
++      if (data == 0xffff)
++              return 0;
++
++      return ~data & 0xffff;
++}
++
++static u32 cbr_scan2(struct ast_private *ast)
++{
++      u32 data, data2, patcnt, loop;
++
++      data2 = 0xffff;
++      for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
++              ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
++              for (loop = 0; loop < CBR_PASSNUM2; loop++) {
++                      if ((data = cbr_test2(ast)) != 0) {
++                              data2 &= data;
++                              if (!data2)
++                                      return 0;
++                              break;
++                      }
++              }
++              if (loop == CBR_PASSNUM2)
++                      return 0;
++      }
++      return data2;
++}
++
++static u32 cbr_test3(struct ast_private *ast)
++{
++      if (!mmc_test_burst(ast, 0))
++              return 0;
++      if (!mmc_test_single(ast, 0))
++              return 0;
++      return 1;
++}
++
++static u32 cbr_scan3(struct ast_private *ast)
++{
++      u32 patcnt, loop;
++
++      for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
++              ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
++              for (loop = 0; loop < 2; loop++) {
++                      if (cbr_test3(ast))
++                              break;
++              }
++              if (loop == 2)
++                      return 0;
++      }
++      return 1;
++}
++
++static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param 
*param)
++{
++      u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, 
passcnt, retry = 0;
++      bool status = false;
++FINETUNE_START:
++      for (cnt = 0; cnt < 16; cnt++) {
++              dllmin[cnt] = 0xff;
++              dllmax[cnt] = 0x0;
++      }
++      passcnt = 0;
++      for (dlli = 0; dlli < 76; dlli++) {
++              ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli 
<< 24));
++              ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
++              data = cbr_scan2(ast);
++              if (data != 0) {
++                      mask = 0x00010001;
++                      for (cnt = 0; cnt < 16; cnt++) {
++                              if (data & mask) {
++                                      if (dllmin[cnt] > dlli) {
++                                              dllmin[cnt] = dlli;
++                                      }
++                                      if (dllmax[cnt] < dlli) {
++                                              dllmax[cnt] = dlli;
++                                      }
++                              }
++                              mask <<= 1;
++                      }
++                      passcnt++;
++              } else if (passcnt >= CBR_THRESHOLD2) {
++                      break;
++              }
++      }
++      gold_sadj[0] = 0x0;
++      passcnt = 0;
++      for (cnt = 0; cnt < 16; cnt++) {
++              if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) 
>= CBR_THRESHOLD2)) {
++                      gold_sadj[0] += dllmin[cnt];
++                      passcnt++;
++              }
++      }
++      if (retry++ > 10)
++              goto FINETUNE_DONE;
++      if (passcnt != 16) {
++              goto FINETUNE_START;
++      }
++      status = true;
++FINETUNE_DONE:
++      gold_sadj[0] = gold_sadj[0] >> 4;
++      gold_sadj[1] = gold_sadj[0];
++
++      data = 0;
++      for (cnt = 0; cnt < 8; cnt++) {
++              data >>= 3;
++              if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) 
>= CBR_THRESHOLD2)) {
++                      dlli = dllmin[cnt];
++                      if (gold_sadj[0] >= dlli) {
++                              dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
++                              if (dlli > 3) {
++                                      dlli = 3;
++                              }
++                      } else {
++                              dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
++                              if (dlli > 4) {
++                                      dlli = 4;
++                              }
++                              dlli = (8 - dlli) & 0x7;
++                      }
++                      data |= dlli << 21;
++              }
++      }
++      ast_moutdwm(ast, 0x1E6E0080, data);
++
++      data = 0;
++      for (cnt = 8; cnt < 16; cnt++) {
++              data >>= 3;
++              if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) 
>= CBR_THRESHOLD2)) {
++                      dlli = dllmin[cnt];
++                      if (gold_sadj[1] >= dlli) {
++                              dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
++                              if (dlli > 3) {
++                                      dlli = 3;
++                              } else {
++                                      dlli = (dlli - 1) & 0x7;
++                              }
++                      } else {
++                              dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
++                              dlli += 1;
++                              if (dlli > 4) {
++                                      dlli = 4;
++                              }
++                              dlli = (8 - dlli) & 0x7;
++                      }
++                      data |= dlli << 21;
++              }
++      }
++      ast_moutdwm(ast, 0x1E6E0084, data);
++      return status;
++} /* finetuneDQI_L */
++
++static void finetuneDQSI(struct ast_private *ast)
++{
++      u32 dlli, dqsip, dqidly;
++      u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
++      u32 g_dqidly, g_dqsip, g_margin, g_side;
++      u16 pass[32][2][2];
++      char tag[2][76];
++
++      /* Disable DQI CBR */
++      reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
++      reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
++      reg_mcr18 &= 0x0000ffff;
++      ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
++
++      for (dlli = 0; dlli < 76; dlli++) {
++              tag[0][dlli] = 0x0;
++              tag[1][dlli] = 0x0;
++      }
++      for (dqidly = 0; dqidly < 32; dqidly++) {
++              pass[dqidly][0][0] = 0xff;
++              pass[dqidly][0][1] = 0x0;
++              pass[dqidly][1][0] = 0xff;
++              pass[dqidly][1][1] = 0x0;
++      }
++      for (dqidly = 0; dqidly < 32; dqidly++) {
++              passcnt[0] = passcnt[1] = 0;
++              for (dqsip = 0; dqsip < 2; dqsip++) {
++                      ast_moutdwm(ast, 0x1E6E000C, 0);
++                      ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) 
| (dqsip << 23));
++                      ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
++                      for (dlli = 0; dlli < 76; dlli++) {
++                              ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli 
<< 16) | (dlli << 24));
++                              ast_moutdwm(ast, 0x1E6E0070, 0);
++                              ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
++                              if (cbr_scan3(ast)) {
++                                      if (dlli == 0)
++                                              break;
++                                      passcnt[dqsip]++;
++                                      tag[dqsip][dlli] = 'P';
++                                      if (dlli < pass[dqidly][dqsip][0])
++                                              pass[dqidly][dqsip][0] = (u16) 
dlli;
++                                      if (dlli > pass[dqidly][dqsip][1])
++                                              pass[dqidly][dqsip][1] = (u16) 
dlli;
++                              } else if (passcnt[dqsip] >= 5)
++                                      break;
++                              else {
++                                      pass[dqidly][dqsip][0] = 0xff;
++                                      pass[dqidly][dqsip][1] = 0x0;
++                              }
++                      }
++              }
++              if (passcnt[0] == 0 && passcnt[1] == 0)
++                      dqidly++;
++      }
++      /* Search margin */
++      g_dqidly = g_dqsip = g_margin = g_side = 0;
++
++      for (dqidly = 0; dqidly < 32; dqidly++) {
++              for (dqsip = 0; dqsip < 2; dqsip++) {
++                      if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
++                              continue;
++                      diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
++                      if ((diff+2) < g_margin)
++                              continue;
++                      passcnt[0] = passcnt[1] = 0;
++                      for (dlli = pass[dqidly][dqsip][0]; dlli > 0  && 
tag[dqsip][dlli] != 0; dlli--, passcnt[0]++);
++                      for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && 
tag[dqsip][dlli] != 0; dlli++, passcnt[1]++);
++                      if (passcnt[0] > passcnt[1])
++                              passcnt[0] = passcnt[1];
++                      passcnt[1] = 0;
++                      if (passcnt[0] > g_side)
++                              passcnt[1] = passcnt[0] - g_side;
++                      if (diff > (g_margin+1) && (passcnt[1] > 0 || 
passcnt[0] > 8)) {
++                              g_margin = diff;
++                              g_dqidly = dqidly;
++                              g_dqsip  = dqsip;
++                              g_side   = passcnt[0];
++                      } else if (passcnt[1] > 1 && g_side < 8) {
++                              if (diff > g_margin)
++                                      g_margin = diff;
++                              g_dqidly = dqidly;
++                              g_dqsip  = dqsip;
++                              g_side   = passcnt[0];
++                      }
++              }
++      }
++      reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
++      ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
++
++}
++static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param 
*param)
++{
++      u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
++      bool status = false;
++
++      finetuneDQSI(ast);
++      if (finetuneDQI_L(ast, param) == false)
++              return status;
++
++CBR_START2:
++      dllmin[0] = dllmin[1] = 0xff;
++      dllmax[0] = dllmax[1] = 0x0;
++      passcnt = 0;
++      for (dlli = 0; dlli < 76; dlli++) {
++              ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli 
<< 24));
++              ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
++              data = cbr_scan(ast);
++              if (data != 0) {
++                      if (data & 0x1) {
++                              if (dllmin[0] > dlli) {
++                                      dllmin[0] = dlli;
++                              }
++                              if (dllmax[0] < dlli) {
++                                      dllmax[0] = dlli;
++                              }
++                      }
++                      if (data & 0x2) {
++                              if (dllmin[1] > dlli) {
++                                      dllmin[1] = dlli;
++                              }
++                              if (dllmax[1] < dlli) {
++                                      dllmax[1] = dlli;
++                              }
++                      }
++                      passcnt++;
++              } else if (passcnt >= CBR_THRESHOLD) {
++                      break;
++              }
++      }
++      if (retry++ > 10)
++              goto CBR_DONE2;
++      if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) {
++              goto CBR_START2;
++      }
++      if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) {
++              goto CBR_START2;
++      }
++      status = true;
++CBR_DONE2:
++      dlli  = (dllmin[1] + dllmax[1]) >> 1;
++      dlli <<= 8;
++      dlli += (dllmin[0] + dllmax[0]) >> 1;
++      ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 
16));
++      return status;
++} /* CBRDLL2 */
++
++static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param 
*param)
++{
++      u32 trap, trap_AC2, trap_MRS;
++
++      ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
++
++      /* Ger trap info */
++      trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
++      trap_AC2  = 0x00020000 + (trap << 16);
++      trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
++      trap_MRS  = 0x00000010 + (trap << 4);
++      trap_MRS |= ((trap & 0x2) << 18);
++
++      param->reg_MADJ       = 0x00034C4C;
++      param->reg_SADJ       = 0x00001800;
++      param->reg_DRV        = 0x000000F0;
++      param->reg_PERIOD     = param->dram_freq;
++      param->rodt           = 0;
++
++      switch (param->dram_freq) {
++      case 336:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0190);
++              param->wodt          = 0;
++              param->reg_AC1       = 0x22202725;
++              param->reg_AC2       = 0xAA007613 | trap_AC2;
++              param->reg_DQSIC     = 0x000000BA;
++              param->reg_MRS       = 0x04001400 | trap_MRS;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_IOZ       = 0x00000023;
++              param->reg_DQIDLY    = 0x00000074;
++              param->reg_FREQ      = 0x00004DC0;
++              param->madj_max      = 96;
++              param->dll2_finetune_step = 3;
++              switch (param->dram_chipid) {
++              default:
++              case AST_DRAM_512Mx16:
++              case AST_DRAM_1Gx16:
++                      param->reg_AC2   = 0xAA007613 | trap_AC2;
++                      break;
++              case AST_DRAM_2Gx16:
++                      param->reg_AC2   = 0xAA00761C | trap_AC2;
++                      break;
++              case AST_DRAM_4Gx16:
++                      param->reg_AC2   = 0xAA007636 | trap_AC2;
++                      break;
++              }
++              break;
++      default:
++      case 396:
++              ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
++              param->wodt          = 1;
++              param->reg_AC1       = 0x33302825;
++              param->reg_AC2       = 0xCC009617 | trap_AC2;
++              param->reg_DQSIC     = 0x000000E2;
++              param->reg_MRS       = 0x04001600 | trap_MRS;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DRV       = 0x000000FA;
++              param->reg_DQIDLY    = 0x00000089;
++              param->reg_FREQ      = 0x00005040;
++              param->madj_max      = 96;
++              param->dll2_finetune_step = 4;
++
++              switch (param->dram_chipid) {
++              default:
++              case AST_DRAM_512Mx16:
++              case AST_DRAM_1Gx16:
++                      param->reg_AC2   = 0xCC009617 | trap_AC2;
++                      break;
++              case AST_DRAM_2Gx16:
++                      param->reg_AC2   = 0xCC009622 | trap_AC2;
++                      break;
++              case AST_DRAM_4Gx16:
++                      param->reg_AC2   = 0xCC00963F | trap_AC2;
++                      break;
++              }
++              break;
++
++      case 408:
++              ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
++              param->wodt          = 1;
++              param->reg_AC1       = 0x33302825;
++              param->reg_AC2       = 0xCC009617 | trap_AC2;
++              param->reg_DQSIC     = 0x000000E2;
++              param->reg_MRS       = 0x04001600 | trap_MRS;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_IOZ       = 0x00000023;
++              param->reg_DRV       = 0x000000FA;
++              param->reg_DQIDLY    = 0x00000089;
++              param->reg_FREQ      = 0x000050C0;
++              param->madj_max      = 96;
++              param->dll2_finetune_step = 4;
++
++              switch (param->dram_chipid) {
++              default:
++              case AST_DRAM_512Mx16:
++              case AST_DRAM_1Gx16:
++                      param->reg_AC2   = 0xCC009617 | trap_AC2;
++                      break;
++              case AST_DRAM_2Gx16:
++                      param->reg_AC2   = 0xCC009622 | trap_AC2;
++                      break;
++              case AST_DRAM_4Gx16:
++                      param->reg_AC2   = 0xCC00963F | trap_AC2;
++                      break;
++              }
++
++              break;
++      case 456:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0230);
++              param->wodt          = 0;
++              param->reg_AC1       = 0x33302926;
++              param->reg_AC2       = 0xCD44961A;
++              param->reg_DQSIC     = 0x000000FC;
++              param->reg_MRS       = 0x00081830;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_IOZ       = 0x00000045;
++              param->reg_DQIDLY    = 0x00000097;
++              param->reg_FREQ      = 0x000052C0;
++              param->madj_max      = 88;
++              param->dll2_finetune_step = 4;
++              break;
++      case 504:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0270);
++              param->wodt          = 1;
++              param->reg_AC1       = 0x33302926;
++              param->reg_AC2       = 0xDE44A61D;
++              param->reg_DQSIC     = 0x00000117;
++              param->reg_MRS       = 0x00081A30;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_IOZ       = 0x070000BB;
++              param->reg_DQIDLY    = 0x000000A0;
++              param->reg_FREQ      = 0x000054C0;
++              param->madj_max      = 79;
++              param->dll2_finetune_step = 4;
++              break;
++      case 528:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0290);
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x33302926;
++              param->reg_AC2       = 0xEF44B61E;
++              param->reg_DQSIC     = 0x00000125;
++              param->reg_MRS       = 0x00081A30;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x000000F5;
++              param->reg_IOZ       = 0x00000023;
++              param->reg_DQIDLY    = 0x00000088;
++              param->reg_FREQ      = 0x000055C0;
++              param->madj_max      = 76;
++              param->dll2_finetune_step = 3;
++              break;
++      case 576:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0140);
++              param->reg_MADJ      = 0x00136868;
++              param->reg_SADJ      = 0x00004534;
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x33302A37;
++              param->reg_AC2       = 0xEF56B61E;
++              param->reg_DQSIC     = 0x0000013F;
++              param->reg_MRS       = 0x00101A50;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x000000FA;
++              param->reg_IOZ       = 0x00000023;
++              param->reg_DQIDLY    = 0x00000078;
++              param->reg_FREQ      = 0x000057C0;
++              param->madj_max      = 136;
++              param->dll2_finetune_step = 3;
++              break;
++      case 600:
++              ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
++              param->reg_MADJ      = 0x00136868;
++              param->reg_SADJ      = 0x00004534;
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x32302A37;
++              param->reg_AC2       = 0xDF56B61F;
++              param->reg_DQSIC     = 0x0000014D;
++              param->reg_MRS       = 0x00101A50;
++              param->reg_EMRS      = 0x00000004;
++              param->reg_DRV       = 0x000000F5;
++              param->reg_IOZ       = 0x00000023;
++              param->reg_DQIDLY    = 0x00000078;
++              param->reg_FREQ      = 0x000058C0;
++              param->madj_max      = 132;
++              param->dll2_finetune_step = 3;
++              break;
++      case 624:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0160);
++              param->reg_MADJ      = 0x00136868;
++              param->reg_SADJ      = 0x00004534;
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x32302A37;
++              param->reg_AC2       = 0xEF56B621;
++              param->reg_DQSIC     = 0x0000015A;
++              param->reg_MRS       = 0x02101A50;
++              param->reg_EMRS      = 0x00000004;
++              param->reg_DRV       = 0x000000F5;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DQIDLY    = 0x00000078;
++              param->reg_FREQ      = 0x000059C0;
++              param->madj_max      = 128;
++              param->dll2_finetune_step = 3;
++              break;
++      } /* switch freq */
++
++      switch (param->dram_chipid) {
++      case AST_DRAM_512Mx16:
++              param->dram_config = 0x130;
++              break;
++      default:
++      case AST_DRAM_1Gx16:
++              param->dram_config = 0x131;
++              break;
++      case AST_DRAM_2Gx16:
++              param->dram_config = 0x132;
++              break;
++      case AST_DRAM_4Gx16:
++              param->dram_config = 0x133;
++              break;
++      } /* switch size */
++
++      switch (param->vram_size) {
++      default:
++      case AST_VIDMEM_SIZE_8M:
++              param->dram_config |= 0x00;
++              break;
++      case AST_VIDMEM_SIZE_16M:
++              param->dram_config |= 0x04;
++              break;
++      case AST_VIDMEM_SIZE_32M:
++              param->dram_config |= 0x08;
++              break;
++      case AST_VIDMEM_SIZE_64M:
++              param->dram_config |= 0x0c;
++              break;
++      }
++
++}
++
++static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param 
*param)
++{
++      u32 data, data2, retry = 0;
++
++ddr3_init_start:
++      ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
++      ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
++      ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
++      udelay(10);
++      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
++      ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
++      udelay(10);
++      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
++      udelay(10);
++
++      ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
++      ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
++      ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
++      ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
++      ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
++      ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
++      ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
++      ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
++      ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
++      ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
++      ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
++      ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
++      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0054, 0);
++      ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
++      ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
++      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
++      /* Wait MCLK2X lock to MCLK */
++      do {
++              data = ast_mindwm(ast, 0x1E6E001C);
++      } while (!(data & 0x08000000));
++      data = ast_mindwm(ast, 0x1E6E001C);
++      data = (data >> 8) & 0xff;
++      while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
++              data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
++              if ((data2 & 0xff) > param->madj_max) {
++                      break;
++              }
++              ast_moutdwm(ast, 0x1E6E0064, data2);
++              if (data2 & 0x00100000) {
++                      data2 = ((data2 & 0xff) >> 3) + 3;
++              } else {
++                      data2 = ((data2 & 0xff) >> 2) + 5;
++              }
++              data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
++              data2 += data & 0xff;
++              data = data | (data2 << 8);
++              ast_moutdwm(ast, 0x1E6E0068, data);
++              udelay(10);
++              ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 
0xC0000);
++              udelay(10);
++              data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
++              ast_moutdwm(ast, 0x1E6E0018, data);
++              data = data | 0x200;
++              ast_moutdwm(ast, 0x1E6E0018, data);
++              do {
++                      data = ast_mindwm(ast, 0x1E6E001C);
++              } while (!(data & 0x08000000));
++
++              data = ast_mindwm(ast, 0x1E6E001C);
++              data = (data >> 8) & 0xff;
++      }
++      ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
++      data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
++      ast_moutdwm(ast, 0x1E6E0018, data);
++
++      ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
++      ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
++      udelay(50);
++      /* Mode Register Setting */
++      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
++      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
++      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
++      ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
++
++      ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
++      data = 0;
++      if (param->wodt) {
++              data = 0x300;
++      }
++      if (param->rodt) {
++              data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
++      }
++      ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
++
++      /* Calibrate the DQSI delay */
++      if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
++              goto ddr3_init_start;
++
++      ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
++      /* ECC Memory Initialization */
++#ifdef ECC
++      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0070, 0x221);
++      do {
++              data = ast_mindwm(ast, 0x1E6E0070);
++      } while (!(data & 0x00001000));
++      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
++#endif
++
++
++}
++
++static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param 
*param)
++{
++      u32 trap, trap_AC2, trap_MRS;
++
++      ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
++
++      /* Ger trap info */
++      trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
++      trap_AC2  = (trap << 20) | (trap << 16);
++      trap_AC2 += 0x00110000;
++      trap_MRS  = 0x00000040 | (trap << 4);
++
++
++      param->reg_MADJ       = 0x00034C4C;
++      param->reg_SADJ       = 0x00001800;
++      param->reg_DRV        = 0x000000F0;
++      param->reg_PERIOD     = param->dram_freq;
++      param->rodt           = 0;
++
++      switch (param->dram_freq) {
++      case 264:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0130);
++              param->wodt          = 0;
++              param->reg_AC1       = 0x11101513;
++              param->reg_AC2       = 0x78117011;
++              param->reg_DQSIC     = 0x00000092;
++              param->reg_MRS       = 0x00000842;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_DRV       = 0x000000F0;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DQIDLY    = 0x0000005A;
++              param->reg_FREQ      = 0x00004AC0;
++              param->madj_max      = 138;
++              param->dll2_finetune_step = 3;
++              break;
++      case 336:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0190);
++              param->wodt          = 1;
++              param->reg_AC1       = 0x22202613;
++              param->reg_AC2       = 0xAA009016 | trap_AC2;
++              param->reg_DQSIC     = 0x000000BA;
++              param->reg_MRS       = 0x00000A02 | trap_MRS;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x000000FA;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DQIDLY    = 0x00000074;
++              param->reg_FREQ      = 0x00004DC0;
++              param->madj_max      = 96;
++              param->dll2_finetune_step = 3;
++              switch (param->dram_chipid) {
++              default:
++              case AST_DRAM_512Mx16:
++                      param->reg_AC2   = 0xAA009012 | trap_AC2;
++                      break;
++              case AST_DRAM_1Gx16:
++                      param->reg_AC2   = 0xAA009016 | trap_AC2;
++                      break;
++              case AST_DRAM_2Gx16:
++                      param->reg_AC2   = 0xAA009023 | trap_AC2;
++                      break;
++              case AST_DRAM_4Gx16:
++                      param->reg_AC2   = 0xAA00903B | trap_AC2;
++                      break;
++              }
++              break;
++      default:
++      case 396:
++              ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
++              param->wodt          = 1;
++              param->rodt          = 0;
++              param->reg_AC1       = 0x33302714;
++              param->reg_AC2       = 0xCC00B01B | trap_AC2;
++              param->reg_DQSIC     = 0x000000E2;
++              param->reg_MRS       = 0x00000C02 | trap_MRS;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x000000FA;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DQIDLY    = 0x00000089;
++              param->reg_FREQ      = 0x00005040;
++              param->madj_max      = 96;
++              param->dll2_finetune_step = 4;
++
++              switch (param->dram_chipid) {
++              case AST_DRAM_512Mx16:
++                      param->reg_AC2   = 0xCC00B016 | trap_AC2;
++                      break;
++              default:
++              case AST_DRAM_1Gx16:
++                      param->reg_AC2   = 0xCC00B01B | trap_AC2;
++                      break;
++              case AST_DRAM_2Gx16:
++                      param->reg_AC2   = 0xCC00B02B | trap_AC2;
++                      break;
++              case AST_DRAM_4Gx16:
++                      param->reg_AC2   = 0xCC00B03F | trap_AC2;
++                      break;
++              }
++
++              break;
++
++      case 408:
++              ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
++              param->wodt          = 1;
++              param->rodt          = 0;
++              param->reg_AC1       = 0x33302714;
++              param->reg_AC2       = 0xCC00B01B | trap_AC2;
++              param->reg_DQSIC     = 0x000000E2;
++              param->reg_MRS       = 0x00000C02 | trap_MRS;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x000000FA;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DQIDLY    = 0x00000089;
++              param->reg_FREQ      = 0x000050C0;
++              param->madj_max      = 96;
++              param->dll2_finetune_step = 4;
++
++              switch (param->dram_chipid) {
++              case AST_DRAM_512Mx16:
++                      param->reg_AC2   = 0xCC00B016 | trap_AC2;
++                      break;
++              default:
++              case AST_DRAM_1Gx16:
++                      param->reg_AC2   = 0xCC00B01B | trap_AC2;
++                      break;
++              case AST_DRAM_2Gx16:
++                      param->reg_AC2   = 0xCC00B02B | trap_AC2;
++                      break;
++              case AST_DRAM_4Gx16:
++                      param->reg_AC2   = 0xCC00B03F | trap_AC2;
++                      break;
++              }
++
++              break;
++      case 456:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0230);
++              param->wodt          = 0;
++              param->reg_AC1       = 0x33302815;
++              param->reg_AC2       = 0xCD44B01E;
++              param->reg_DQSIC     = 0x000000FC;
++              param->reg_MRS       = 0x00000E72;
++              param->reg_EMRS      = 0x00000000;
++              param->reg_DRV       = 0x00000000;
++              param->reg_IOZ       = 0x00000034;
++              param->reg_DQIDLY    = 0x00000097;
++              param->reg_FREQ      = 0x000052C0;
++              param->madj_max      = 88;
++              param->dll2_finetune_step = 3;
++              break;
++      case 504:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0261);
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x33302815;
++              param->reg_AC2       = 0xDE44C022;
++              param->reg_DQSIC     = 0x00000117;
++              param->reg_MRS       = 0x00000E72;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x0000000A;
++              param->reg_IOZ       = 0x00000045;
++              param->reg_DQIDLY    = 0x000000A0;
++              param->reg_FREQ      = 0x000054C0;
++              param->madj_max      = 79;
++              param->dll2_finetune_step = 3;
++              break;
++      case 528:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0120);
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x33302815;
++              param->reg_AC2       = 0xEF44D024;
++              param->reg_DQSIC     = 0x00000125;
++              param->reg_MRS       = 0x00000E72;
++              param->reg_EMRS      = 0x00000004;
++              param->reg_DRV       = 0x000000F9;
++              param->reg_IOZ       = 0x00000045;
++              param->reg_DQIDLY    = 0x000000A7;
++              param->reg_FREQ      = 0x000055C0;
++              param->madj_max      = 76;
++              param->dll2_finetune_step = 3;
++              break;
++      case 552:
++              ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x43402915;
++              param->reg_AC2       = 0xFF44E025;
++              param->reg_DQSIC     = 0x00000132;
++              param->reg_MRS       = 0x00000E72;
++              param->reg_EMRS      = 0x00000040;
++              param->reg_DRV       = 0x0000000A;
++              param->reg_IOZ       = 0x00000045;
++              param->reg_DQIDLY    = 0x000000AD;
++              param->reg_FREQ      = 0x000056C0;
++              param->madj_max      = 76;
++              param->dll2_finetune_step = 3;
++              break;
++      case 576:
++              ast_moutdwm(ast, 0x1E6E2020, 0x0140);
++              param->wodt          = 1;
++              param->rodt          = 1;
++              param->reg_AC1       = 0x43402915;
++              param->reg_AC2       = 0xFF44E027;
++              param->reg_DQSIC     = 0x0000013F;
++              param->reg_MRS       = 0x00000E72;
++              param->reg_EMRS      = 0x00000004;
++              param->reg_DRV       = 0x000000F5;
++              param->reg_IOZ       = 0x00000045;
++              param->reg_DQIDLY    = 0x000000B3;
++              param->reg_FREQ      = 0x000057C0;
++              param->madj_max      = 76;
++              param->dll2_finetune_step = 3;
++              break;
++      }
++
++      switch (param->dram_chipid) {
++      case AST_DRAM_512Mx16:
++              param->dram_config = 0x100;
++              break;
++      default:
++      case AST_DRAM_1Gx16:
++              param->dram_config = 0x121;
++              break;
++      case AST_DRAM_2Gx16:
++              param->dram_config = 0x122;
++              break;
++      case AST_DRAM_4Gx16:
++              param->dram_config = 0x123;
++              break;
++      } /* switch size */
++
++      switch (param->vram_size) {
++      default:
++      case AST_VIDMEM_SIZE_8M:
++              param->dram_config |= 0x00;
++              break;
++      case AST_VIDMEM_SIZE_16M:
++              param->dram_config |= 0x04;
++              break;
++      case AST_VIDMEM_SIZE_32M:
++              param->dram_config |= 0x08;
++              break;
++      case AST_VIDMEM_SIZE_64M:
++              param->dram_config |= 0x0c;
++              break;
++      }
++}
++
++static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param 
*param)
++{
++      u32 data, data2, retry = 0;
++
++ddr2_init_start:
++      ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
++      ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
++      ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
++      ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
++      udelay(10);
++      ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
++      udelay(10);
++
++      ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
++      ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
++      ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
++      ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
++      ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
++      ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
++      ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
++      ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
++      ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
++      ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
++      ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
++      ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0054, 0);
++      ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
++      ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
++      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
++
++      /* Wait MCLK2X lock to MCLK */
++      do {
++              data = ast_mindwm(ast, 0x1E6E001C);
++      } while (!(data & 0x08000000));
++      data = ast_mindwm(ast, 0x1E6E001C);
++      data = (data >> 8) & 0xff;
++      while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
++              data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
++              if ((data2 & 0xff) > param->madj_max) {
++                      break;
++              }
++              ast_moutdwm(ast, 0x1E6E0064, data2);
++              if (data2 & 0x00100000) {
++                      data2 = ((data2 & 0xff) >> 3) + 3;
++              } else {
++                      data2 = ((data2 & 0xff) >> 2) + 5;
++              }
++              data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
++              data2 += data & 0xff;
++              data = data | (data2 << 8);
++              ast_moutdwm(ast, 0x1E6E0068, data);
++              udelay(10);
++              ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 
0xC0000);
++              udelay(10);
++              data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
++              ast_moutdwm(ast, 0x1E6E0018, data);
++              data = data | 0x200;
++              ast_moutdwm(ast, 0x1E6E0018, data);
++              do {
++                      data = ast_mindwm(ast, 0x1E6E001C);
++              } while (!(data & 0x08000000));
++
++              data = ast_mindwm(ast, 0x1E6E001C);
++              data = (data >> 8) & 0xff;
++      }
++      ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
++      data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
++      ast_moutdwm(ast, 0x1E6E0018, data);
++
++      ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
++      ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
++      udelay(50);
++      /* Mode Register Setting */
++      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
++      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
++
++      ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
++      ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
++      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
++      ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
++      ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
++
++      ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
++      data = 0;
++      if (param->wodt) {
++              data = 0x500;
++      }
++      if (param->rodt) {
++              data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
++      }
++      ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
++      ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
++
++      /* Calibrate the DQSI delay */
++      if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
++              goto ddr2_init_start;
++
++      /* ECC Memory Initialization */
++#ifdef ECC
++      ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0070, 0x221);
++      do {
++              data = ast_mindwm(ast, 0x1E6E0070);
++      } while (!(data & 0x00001000));
++      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
++      ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
++#endif
++
++}
++
++static void ast_init_dram_2300(struct drm_device *dev)
++{
++      struct ast_private *ast = dev->dev_private;
++      struct ast2300_dram_param param;
++      u32 temp;
++      u8 reg;
++
++      reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
++      if ((reg & 0x80) == 0) {/* vga only */
++              ast_write32(ast, 0xf004, 0x1e6e0000);
++              ast_write32(ast, 0xf000, 0x1);
++              ast_write32(ast, 0x12000, 0x1688a8a8);
++              do {
++                      ;
++              } while (ast_read32(ast, 0x12000) != 0x1);
++
++              ast_write32(ast, 0x10000, 0xfc600309);
++              do {
++                      ;
++              } while (ast_read32(ast, 0x10000) != 0x1);
++
++              /* Slow down CPU/AHB CLK in VGA only mode */
++              temp = ast_read32(ast, 0x12008);
++              temp |= 0x73;
++              ast_write32(ast, 0x12008, temp);
++
++              param.dram_type = AST_DDR3;
++              if (temp & 0x01000000)
++                      param.dram_type = AST_DDR2;
++              param.dram_chipid = ast->dram_type;
++              param.dram_freq = ast->mclk;
++              param.vram_size = ast->vram_size;
++
++              if (param.dram_type == AST_DDR3) {
++                      get_ddr3_info(ast, &param);
++                      ddr3_init(ast, &param);
++              } else {
++                      get_ddr2_info(ast, &param);
++                      ddr2_init(ast, &param);
++              }
++
++              temp = ast_mindwm(ast, 0x1e6e2040);
++              ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
++      }
++
++      /* wait ready */
++      do {
++              reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
++      } while ((reg & 0x40) == 0);
++}
++
+diff --git a/src/drivers/aspeed/common/ast_tables.h 
b/src/drivers/aspeed/common/ast_tables.h
+new file mode 100644
+index 0000000..3608d5a
+--- /dev/null
++++ b/src/drivers/aspeed/common/ast_tables.h
+@@ -0,0 +1,305 @@
++/*
++ * Copyright (c) 2005 ASPEED Technology Inc.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the authors not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission.  The authors makes no representations
++ * about the suitability of this software for any purpose.  It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++/* Ported from xf86-video-ast driver */
++
++#ifndef AST_TABLES_H
++#define AST_TABLES_H
++
++/* Std. Table Index Definition */
++#define TextModeIndex         0
++#define EGAModeIndex          1
++#define VGAModeIndex          2
++#define HiCModeIndex          3
++#define TrueCModeIndex                4
++
++#define Charx8Dot               0x00000001
++#define HalfDCLK                0x00000002
++#define DoubleScanMode          0x00000004
++#define LineCompareOff          0x00000008
++#define HBorder                 0x00000020
++#define VBorder                 0x00000010
++#define WideScreenMode                0x00000100
++#define NewModeInfo           0x00000200
++#define NHSync                        0x00000400
++#define PHSync                        0x00000800
++#define NVSync                        0x00001000
++#define PVSync                        0x00002000
++#define SyncPP                        (PVSync | PHSync)
++#define SyncPN                        (PVSync | NHSync)
++#define SyncNP                        (NVSync | PHSync)
++#define SyncNN                        (NVSync | NHSync)
++
++/* DCLK Index */
++#define VCLK25_175                    0x00
++#define VCLK28_322                    0x01
++#define VCLK31_5                      0x02
++#define VCLK36                        0x03
++#define VCLK40                        0x04
++#define VCLK49_5                      0x05
++#define VCLK50                        0x06
++#define VCLK56_25                     0x07
++#define VCLK65                        0x08
++#define VCLK75                        0x09
++#define VCLK78_75                     0x0A
++#define VCLK94_5                      0x0B
++#define VCLK108                       0x0C
++#define VCLK135                       0x0D
++#define VCLK157_5                     0x0E
++#define VCLK162                       0x0F
++/* #define VCLK193_25                 0x10 */
++#define VCLK154               0x10
++#define VCLK83_5              0x11
++#define VCLK106_5             0x12
++#define VCLK146_25            0x13
++#define VCLK148_5             0x14
++#define VCLK71                0x15
++#define VCLK88_75             0x16
++#define VCLK119               0x17
++#define VCLK85_5              0x18
++#define VCLK97_75                     0x19
++#define VCLK118_25                    0x1A
++
++static struct ast_vbios_dclk_info dclk_table[] = {
++      {0x2C, 0xE7, 0x03},                                     /* 00: 
VCLK25_175       */
++      {0x95, 0x62, 0x03},                                     /* 01: 
VCLK28_322       */
++      {0x67, 0x63, 0x01},                                     /* 02: VCLK31_5 
        */
++      {0x76, 0x63, 0x01},                                     /* 03: VCLK36   
        */
++      {0xEE, 0x67, 0x01},                                     /* 04: VCLK40   
        */
++      {0x82, 0x62, 0x01},                             /* 05: VCLK49_5         
*/
++      {0xC6, 0x64, 0x01},                                     /* 06: VCLK50   
        */
++      {0x94, 0x62, 0x01},                                     /* 07: 
VCLK56_25        */
++      {0x80, 0x64, 0x00},                                     /* 08: VCLK65   
        */
++      {0x7B, 0x63, 0x00},                                     /* 09: VCLK75   
        */
++      {0x67, 0x62, 0x00},                                     /* 0A: 
VCLK78_75        */
++      {0x7C, 0x62, 0x00},                                     /* 0B: VCLK94_5 
        */
++      {0x8E, 0x62, 0x00},                                     /* 0C: VCLK108  
        */
++      {0x85, 0x24, 0x00},                                     /* 0D: VCLK135  
        */
++      {0x67, 0x22, 0x00},                                     /* 0E: 
VCLK157_5        */
++      {0x6A, 0x22, 0x00},                                     /* 0F: VCLK162  
        */
++      {0x4d, 0x4c, 0x80},                                     /* 10: VCLK154  
        */
++      {0xa7, 0x78, 0x80},                                     /* 11: VCLK83.5 
        */
++      {0x28, 0x49, 0x80},                                     /* 12: 
VCLK106.5        */
++      {0x37, 0x49, 0x80},                                     /* 13: 
VCLK146.25       */
++      {0x1f, 0x45, 0x80},                                     /* 14: 
VCLK148.5        */
++      {0x47, 0x6c, 0x80},                                     /* 15: VCLK71   
    */
++      {0x25, 0x65, 0x80},                                     /* 16: 
VCLK88.75    */
++      {0x77, 0x58, 0x80},                                     /* 17: VCLK119  
    */
++      {0x32, 0x67, 0x80},                                 /* 18: VCLK85_5     
*/
++      {0x6a, 0x6d, 0x80},                                     /* 19: 
VCLK97_75        */
++      {0x3b, 0x2c, 0x81},                                     /* 1A: 
VCLK118_25       */
++};
++
++static struct ast_vbios_stdtable vbios_stdtable[] = {
++      /* MD_2_3_400 */
++      {
++              0x67,
++              {0x00,0x03,0x00,0x02},
++              {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++               0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
++               0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
++               0xff},
++              {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++               0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++               0x0c,0x00,0x0f,0x08},
++              {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++               0xff}
++      },
++      /* Mode12/ExtEGATable */
++      {
++              0xe3,
++              {0x01,0x0f,0x00,0x06},
++              {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
++               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++               0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,
++               0xff},
++              {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++               0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++               0x01,0x00,0x0f,0x00},
++              {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++               0xff}
++      },
++      /* ExtVGATable */
++      {
++              0x2f,
++              {0x01,0x0f,0x00,0x0e},
++              {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
++               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++               0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
++               0xff},
++              {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++               0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
++               0x01,0x00,0x00,0x00},
++              {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
++               0xff}
++      },
++      /* ExtHiCTable */
++      {
++              0x2f,
++              {0x01,0x0f,0x00,0x0e},
++              {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
++               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++               0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
++               0xff},
++              {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++               0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
++               0x01,0x00,0x00,0x00},
++              {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++               0xff}
++      },
++      /* ExtTrueCTable */
++      {
++              0x2f,
++              {0x01,0x0f,0x00,0x0e},
++              {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
++               0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++               0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
++               0xff},
++              {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++               0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
++               0x01,0x00,0x00,0x00},
++              {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++               0xff}
++      },
++};
++
++static struct ast_vbios_enhtable res_640x480[] = {
++      { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175,  /* 60Hz */
++        (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E },
++      { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5,   /* 72Hz */
++        (SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2E  },
++      { 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5,   /* 75Hz */
++        (SyncNN | Charx8Dot) , 75, 3, 0x2E },
++      { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36,             /* 85Hz */
++        (SyncNN | Charx8Dot) , 85, 4, 0x2E },
++      { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36,             /* end */
++        (SyncNN | Charx8Dot) , 0xFF, 4, 0x2E },
++};
++
++static struct ast_vbios_enhtable res_800x600[] = {
++      {1024, 800, 24, 72, 625, 600, 1, 2, VCLK36,             /* 56Hz */
++       (SyncPP | Charx8Dot), 56, 1, 0x30 },
++      {1056, 800, 40, 128, 628, 600, 1, 4, VCLK40,    /* 60Hz */
++       (SyncPP | Charx8Dot), 60, 2, 0x30 },
++      {1040, 800, 56, 120, 666, 600, 37, 6, VCLK50,   /* 72Hz */
++       (SyncPP | Charx8Dot), 72, 3, 0x30 },
++      {1056, 800, 16, 80, 625, 600, 1, 3, VCLK49_5,   /* 75Hz */
++       (SyncPP | Charx8Dot), 75, 4, 0x30 },
++      {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25,  /* 85Hz */
++       (SyncPP | Charx8Dot), 84, 5, 0x30 },
++      {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25,  /* end */
++       (SyncPP | Charx8Dot), 0xFF, 5, 0x30 },
++};
++
++
++static struct ast_vbios_enhtable res_1024x768[] = {
++      {1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65,   /* 60Hz */
++       (SyncNN | Charx8Dot), 60, 1, 0x31 },
++      {1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75,   /* 70Hz */
++       (SyncNN | Charx8Dot), 70, 2, 0x31 },
++      {1312, 1024, 16, 96, 800, 768, 1, 3, VCLK78_75, /* 75Hz */
++       (SyncPP | Charx8Dot), 75, 3, 0x31 },
++      {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5,  /* 85Hz */
++       (SyncPP | Charx8Dot), 84, 4, 0x31 },
++      {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5,  /* end */
++       (SyncPP | Charx8Dot), 0xFF, 4, 0x31 },
++};
++
++static struct ast_vbios_enhtable res_1280x1024[] = {
++      {1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108,        /* 60Hz */
++       (SyncPP | Charx8Dot), 60, 1, 0x32 },
++      {1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135,        /* 75Hz */
++       (SyncPP | Charx8Dot), 75, 2, 0x32 },
++      {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5,      /* 85Hz */
++       (SyncPP | Charx8Dot), 85, 3, 0x32 },
++      {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5,      /* end */
++       (SyncPP | Charx8Dot), 0xFF, 3, 0x32 },
++};
++
++static struct ast_vbios_enhtable res_1600x1200[] = {
++      {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162,        /* 60Hz */
++       (SyncPP | Charx8Dot), 60, 1, 0x33 },
++      {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162,        /* end */
++       (SyncPP | Charx8Dot), 0xFF, 1, 0x33 },
++};
++
++/* 16:9 */
++static struct ast_vbios_enhtable res_1360x768[] = {
++      {1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,          /* 60Hz */
++       (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x39 },
++      {1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,          /* end */
++       (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 1, 0x39 },
++};
++
++static struct ast_vbios_enhtable res_1600x900[] = {
++      {1760, 1600, 48, 32, 926,  900, 3, 5, VCLK97_75,        /* 60Hz CVT RB 
*/
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x3A },
++      {2112, 1600, 88,168, 934,  900, 3, 5, VCLK118_25,       /* 60Hz CVT */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x3A },
++      {2112, 1600, 88,168, 934,  900, 3, 5, VCLK118_25,       /* 60Hz CVT */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x3A },
++};
++
++static struct ast_vbios_enhtable res_1920x1080[] = {
++      {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x38 },
++      {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 1, 0x38 },
++};
++
++
++/* 16:10 */
++static struct ast_vbios_enhtable res_1280x800[] = {
++      {1440, 1280, 48, 32,  823,  800, 3, 6, VCLK71,  /* 60Hz RB */
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x35 },
++      {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x35 },
++      {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x35 },
++
++};
++
++static struct ast_vbios_enhtable res_1440x900[] = {
++      {1600, 1440, 48, 32,  926,  900, 3, 6, VCLK88_75,       /* 60Hz RB */
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x36 },
++      {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x36 },
++      {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x36 },
++};
++
++static struct ast_vbios_enhtable res_1680x1050[] = {
++      {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x37 },
++      {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25,      /* 60Hz */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 2, 0x37 },
++      {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25,      /* 60Hz */
++       (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 2, 0x37 },
++};
++
++static struct ast_vbios_enhtable res_1920x1200[] = {
++      {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 1, 0x34 },
++      {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */
++       (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
0xFF, 1, 0x34 },
++};
++
++#endif
+diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
+index dcb8a42..fcaf4aa 100644
+--- a/src/include/device/pci_ids.h
++++ b/src/include/device/pci_ids.h
+@@ -1991,6 +1991,9 @@
+ #define PCI_DEVICE_ID_XGI_20          0x0020
+ #define PCI_DEVICE_ID_XGI_40          0x0040
+ 
++#define PCI_VENDOR_ID_ASPEED          0x1a03
++#define PCI_DEVICE_ID_ASPEED_AST2050_VGA      0x2000
++
+ #define PCI_VENDOR_ID_SYMPHONY                0x1c1c
+ #define PCI_DEVICE_ID_SYMPHONY_101    0x0001
+ 
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0006-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
 
b/resources/libreboot/patch/kgpe-d16/0006-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
deleted file mode 100644
index a0273e2..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0006-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
+++ /dev/null
@@ -1,621 +0,0 @@
-From 03ff36542c8f8260b2ff7db5f41a16e9299a1bd0 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 17:46:38 -0500
-Subject: [PATCH 006/139] southbridge/amd/sr5650: Fix boot failure on ASUS
- KGPE-D16
-
-Change-Id: Ia13ba58118a826e830a4dc6e2378b76110fcabad
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/southbridge/amd/sr5650/acpi/sr5650.asl | 388 +++++++++++++++++++++++++++++
- src/southbridge/amd/sr5650/early_setup.c   |   7 +-
- src/southbridge/amd/sr5650/ht.c            |   3 +-
- src/southbridge/amd/sr5650/pcie.c          |  37 ++-
- src/southbridge/amd/sr5650/sr5650.c        |  51 ++--
- 5 files changed, 456 insertions(+), 30 deletions(-)
- create mode 100644 src/southbridge/amd/sr5650/acpi/sr5650.asl
-
-diff --git a/src/southbridge/amd/sr5650/acpi/sr5650.asl 
b/src/southbridge/amd/sr5650/acpi/sr5650.asl
-new file mode 100644
-index 0000000..a6ab114
---- /dev/null
-+++ b/src/southbridge/amd/sr5650/acpi/sr5650.asl
-@@ -0,0 +1,388 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ * Copyright (C) 2009 Advanced Micro Devices, Inc.
-+ *
-+ * 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
-+ */
-+
-+Scope(\) {
-+      Name(PCBA, 0xE0000000)  /* Base address of PCIe config space */
-+      Name(HPBA, 0xFED00000)  /* Base address of HPET table */
-+
-+      /* PIC IRQ mapping registers, C00h-C01h */
-+      OperationRegion(PRQM, SystemIO, 0x00000C00, 0x00000002)
-+              Field(PRQM, ByteAcc, NoLock, Preserve) {
-+              PRQI, 0x00000008,
-+              PRQD, 0x00000008,  /* Offset: 1h */
-+      }
-+      IndexField(PRQI, PRQD, ByteAcc, NoLock, Preserve) {
-+              PINA, 0x00000008,       /* Index 0 */
-+              PINB, 0x00000008,       /* Index 1 */
-+              PINC, 0x00000008,       /* Index 2 */
-+              PIND, 0x00000008,       /* Index 3 */
-+              AINT, 0x00000008,       /* Index 4 */
-+              SINT, 0x00000008,       /* Index 5 */
-+                  , 0x00000008,       /* Index 6 */
-+              AAUD, 0x00000008,       /* Index 7 */
-+              AMOD, 0x00000008,       /* Index 8 */
-+              PINE, 0x00000008,       /* Index 9 */
-+              PINF, 0x00000008,       /* Index A */
-+              PING, 0x00000008,       /* Index B */
-+              PINH, 0x00000008,       /* Index C */
-+      }
-+
-+      /* PCI Error control register */
-+      OperationRegion(PERC, SystemIO, 0x00000C14, 0x00000001)
-+              Field(PERC, ByteAcc, NoLock, Preserve) {
-+              SENS, 0x00000001,
-+              PENS, 0x00000001,
-+              SENE, 0x00000001,
-+              PENE, 0x00000001,
-+      }
-+
-+      Scope(\_SB) {
-+              /* PCIe Configuration Space for 16 busses */
-+              OperationRegion(PCFG, SystemMemory, PCBA, 0x01000000) /* Each 
bus consumes 1MB */
-+                      Field(PCFG, ByteAcc, NoLock, Preserve) {
-+                      /* Byte offsets are computed using the following 
technique:
-+                       * ((bus number + 1) * ((device number * 8) * 4096)) + 
register offset
-+                       * The 8 comes from 8 functions per device, and 4096 
bytes per function config space
-+                      */
-+                      Offset(0x00088024),     /* Byte offset to SATA register 
24h - Bus 0, Device 17, Function 0 */
-+                      STB5, 32,
-+                      Offset(0x00098042),     /* Byte offset to OHCI0 
register 42h - Bus 0, Device 19, Function 0 */
-+                      PT0D, 1,
-+                      PT1D, 1,
-+                      PT2D, 1,
-+                      PT3D, 1,
-+                      PT4D, 1,
-+                      PT5D, 1,
-+                      PT6D, 1,
-+                      PT7D, 1,
-+                      PT8D, 1,
-+                      PT9D, 1,
-+                      Offset(0x000A0004),     /* Byte offset to SMBUS 
register 4h - Bus 0, Device 20, Function 0 */
-+                      SBIE, 1,
-+                      SBME, 1,
-+                      Offset(0x000A0008),     /* Byte offset to SMBUS 
register 8h - Bus 0, Device 20, Function 0 */
-+                      SBRI, 8,
-+                      Offset(0x000A0014),     /* Byte offset to SMBUS 
register 14h - Bus 0, Device 20, Function 0 */
-+                      SBB1, 32,
-+                      Offset(0x000A0078),     /* Byte offset to SMBUS 
register 78h - Bus 0, Device 20, Function 0 */
-+                      ,14,
-+                      P92E, 1,                /* Port92 decode enable */
-+              }
-+
-+              OperationRegion(SB5, SystemMemory, STB5, 0x1000)
-+                      Field(SB5, AnyAcc, NoLock, Preserve){
-+                      /* Port 0 */
-+                      Offset(0x120),          /* Port 0 Task file status */
-+                      P0ER, 1,
-+                      , 2,
-+                      P0DQ, 1,
-+                      , 3,
-+                      P0BY, 1,
-+                      Offset(0x128),          /* Port 0 Serial ATA status */
-+                      P0DD, 4,
-+                      , 4,
-+                      P0IS, 4,
-+                      Offset(0x12C),          /* Port 0 Serial ATA control */
-+                      P0DI, 4,
-+                      Offset(0x130),          /* Port 0 Serial ATA error */
-+                      , 16,
-+                      P0PR, 1,
-+
-+                      /* Port 1 */
-+                      offset(0x1A0),          /* Port 1 Task file status */
-+                      P1ER, 1,
-+                      , 2,
-+                      P1DQ, 1,
-+                      , 3,
-+                      P1BY, 1,
-+                      Offset(0x1A8),          /* Port 1 Serial ATA status */
-+                      P1DD, 4,
-+                      , 4,
-+                      P1IS, 4,
-+                      Offset(0x1AC),          /* Port 1 Serial ATA control */
-+                      P1DI, 4,
-+                      Offset(0x1B0),          /* Port 1 Serial ATA error */
-+                      , 16,
-+                      P1PR, 1,
-+
-+                      /* Port 2 */
-+                      Offset(0x220),          /* Port 2 Task file status */
-+                      P2ER, 1,
-+                      , 2,
-+                      P2DQ, 1,
-+                      , 3,
-+                      P2BY, 1,
-+                      Offset(0x228),          /* Port 2 Serial ATA status */
-+                      P2DD, 4,
-+                      , 4,
-+                      P2IS, 4,
-+                      Offset(0x22C),          /* Port 2 Serial ATA control */
-+                      P2DI, 4,
-+                      Offset(0x230),          /* Port 2 Serial ATA error */
-+                      , 16,
-+                      P2PR, 1,
-+
-+                      /* Port 3 */
-+                      Offset(0x2A0),          /* Port 3 Task file status */
-+                      P3ER, 1,
-+                      , 2,
-+                      P3DQ, 1,
-+                      , 3,
-+                      P3BY, 1,
-+                      Offset(0x2A8),          /* Port 3 Serial ATA status */
-+                      P3DD, 4,
-+                      , 4,
-+                      P3IS, 4,
-+                      Offset(0x2AC),          /* Port 3 Serial ATA control */
-+                      P3DI, 4,
-+                      Offset(0x2B0),          /* Port 3 Serial ATA error */
-+                      , 16,
-+                      P3PR, 1,
-+              }
-+
-+              Method(CIRQ, 0x00, NotSerialized){
-+                      Store(0, PINA)
-+                      Store(0, PINB)
-+                      Store(0, PINC)
-+                      Store(0, PIND)
-+                      Store(0, PINE)
-+                      Store(0, PINF)
-+                      Store(0, PING)
-+                      Store(0, PINH)
-+              }
-+
-+              /* set "A", 8259 interrupts */
-+              Name (PRSA, ResourceTemplate () {
-+                      IRQ(Level, ActiveLow, Exclusive) {4, 7, 10, 11, 12, 14, 
15}
-+              })
-+
-+              Method (CRSA, 1, Serialized) {
-+                      Name (LRTL, ResourceTemplate() {
-+                              IRQ(Level, ActiveLow, Shared) {15}
-+                      })
-+                      CreateWordField(LRTL, 1, LIRQ)
-+                      ShiftLeft(1, Arg0, LIRQ)
-+                      Return (LRTL)
-+              }
-+
-+              Method (SRSA, 1, Serialized) {
-+                      CreateWordField(Arg0, 1, LIRQ)
-+                      FindSetRightBit(LIRQ, Local0)
-+                      if (Local0) {
-+                              Decrement(Local0)
-+                      }
-+                      Return (Local0)
-+              }
-+
-+              Device(LNKA) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 1)
-+                      Method(_STA, 0) {
-+                              if (PINA) {
-+                                      Return(0x0B) /* LNKA is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKA is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PINA)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PINA))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PINA)
-+                      }
-+              }
-+
-+              Device(LNKB) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 2)
-+                      Method(_STA, 0) {
-+                              if (PINB) {
-+                                      Return(0x0B) /* LNKB is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKB is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PINB)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PINB))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PINB)
-+                      }
-+              }
-+
-+              Device(LNKC) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 3)
-+                      Method(_STA, 0) {
-+                              if (PINC) {
-+                                      Return(0x0B) /* LNKC is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKC is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PINC)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PINC))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PINC)
-+                      }
-+              }
-+
-+              Device(LNKD) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 4)
-+                      Method(_STA, 0) {
-+                              if (PIND) {
-+                                      Return(0x0B) /* LNKD is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKD is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PIND)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PIND))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PIND)
-+                      }
-+              }
-+
-+              Device(LNKE) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 5)
-+                      Method(_STA, 0) {
-+                              if (PINE) {
-+                                      Return(0x0B) /* LNKE is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKE is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PINE)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PINE))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PINE)
-+                      }
-+              }
-+
-+              Device(LNKF) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 6)
-+                      Method(_STA, 0) {
-+                              if (PINF) {
-+                                      Return(0x0B) /* LNKF is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKF is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PINF)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PINF))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PINF)
-+                      }
-+              }
-+
-+              Device(LNKG) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 7)
-+                      Method(_STA, 0) {
-+                              if (PING) {
-+                                      Return(0x0B) /* LNKG is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKG is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PING)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PING))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PING)
-+                      }
-+              }
-+
-+              Device(LNKH) {
-+                      Name(_HID, EISAID("PNP0C0F"))
-+                      Name(_UID, 8)
-+                      Method(_STA, 0) {
-+                              if (PINH) {
-+                                      Return(0x0B) /* LNKH is invisible */
-+                              } else {
-+                                      Return(0x09) /* LNKH is disabled */
-+                              }
-+                      }
-+                      Method(_DIS, 0) {
-+                              Store(0, PINH)
-+                      }
-+                      Method(_PRS, 0) {
-+                              Return (PRSA)
-+                      }
-+                      Method (_CRS, 0, Serialized) {
-+                              Return (CRSA(PINH))
-+                      }
-+                      Method (_SRS, 1, Serialized) {
-+                              Store (SRSA(Arg0), PINH)
-+                      }
-+              }
-+
-+      }   /* End Scope(_SB)  */
-+
-+}  /* End Scope(/)  */
-diff --git a/src/southbridge/amd/sr5650/early_setup.c 
b/src/southbridge/amd/sr5650/early_setup.c
-index ec555f8..664f60a 100644
---- a/src/southbridge/amd/sr5650/early_setup.c
-+++ b/src/southbridge/amd/sr5650/early_setup.c
-@@ -3,6 +3,7 @@
-  *
-  * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -504,7 +505,8 @@ void sr5650_early_setup(void)
-       /*ATINB_PrepareInit */
-       get_cpu_rev();
- 
--      switch (get_nb_rev(nb_dev)) {   /* PCIEMiscInit */
-+      uint8_t revno = get_nb_rev(nb_dev);
-+      switch (revno) {        /* PCIEMiscInit */
-       case REV_SR5650_A11:
-               printk(BIOS_INFO, "NB Revision is A11.\n");
-               break;
-@@ -514,6 +516,9 @@ void sr5650_early_setup(void)
-       case REV_SR5650_A21:
-               printk(BIOS_INFO, "NB Revision is A21.\n");
-               break;
-+      default:
-+              printk(BIOS_INFO, "NB Revision is %02x (Unrecognized).\n", 
revno);
-+              break;
-       }
- 
-       fam10_optimization();
-diff --git a/src/southbridge/amd/sr5650/ht.c b/src/southbridge/amd/sr5650/ht.c
-index c497107..02f4f7f 100644
---- a/src/southbridge/amd/sr5650/ht.c
-+++ b/src/southbridge/amd/sr5650/ht.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -55,7 +56,7 @@ static const apic_device_info default_apic_device_info_t [] 
= {
-       [13] = {4,     ABCD,       30}    /* Dev13 Grp4 [Int - 16..19] */
- };
- 
--/* Their name are quite regular. So I undefine them. */
-+/* These define names are common, so undefine them to avoid potential issues 
in other code */
- #undef ABCD
- #undef BCDA
- #undef CDAB
-diff --git a/src/southbridge/amd/sr5650/pcie.c 
b/src/southbridge/amd/sr5650/pcie.c
-index 3720a61..d306b5a 100644
---- a/src/southbridge/amd/sr5650/pcie.c
-+++ b/src/southbridge/amd/sr5650/pcie.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -61,8 +62,10 @@ static void ValidatePortEn(device_t nb_dev)
- *****************************************************************/
- static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port)
- {
-+      printk(BIOS_DEBUG, "PciePowerOffGppPorts() port %d\n", port);
-       u32 reg;
-       u16 state_save;
-+      uint8_t i;
-       struct southbridge_amd_sr5650_config *cfg =
-               (struct southbridge_amd_sr5650_config *)nb_dev->chip_info;
-       u16 state = cfg->port_enable;
-@@ -72,6 +75,28 @@ static void PciePowerOffGppPorts(device_t nb_dev, device_t 
dev, u32 port)
-       state = ~state;
-       state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7);
-       state_save = state << 17;
-+      /* Disable ports any that failed training */
-+      for (i = 9; i <= 13; i++) {
-+              if (!(AtiPcieCfg.PortDetect & 1 << i)) {
-+                      if ((port >= 9) && (port <= 13)) {
-+                              state |= (1 << (port + 7));
-+                      }
-+                      if (port == 9)
-+                              state_save |= 1 << 25;
-+                      if (port == 10)
-+                              state_save |= 1 << 26;
-+                      if (port == 11)
-+                              state_save |= 1 << 6;
-+                      if (port == 12)
-+                              state_save |= 1 << 7;
-+
-+                      if (port == 13) {
-+                              reg = nbmisc_read_index(nb_dev, 0x2a);
-+                              reg |= 1 << 4;
-+                              nbmisc_write_index(nb_dev, 0x2a, reg);
-+                      }
-+              }
-+      }
-       state &= !(AtiPcieCfg.PortHp);
-       reg = nbmisc_read_index(nb_dev, 0x0c);
-       reg |= state;
-@@ -483,6 +508,8 @@ static void EnableLclkGating(device_t dev)
- *****************************************/
- void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
- {
-+      uint8_t training_ok = 1;
-+
-       u32 gpp_sb_sel = 0;
-       struct southbridge_amd_sr5650_config *cfg =
-           (struct southbridge_amd_sr5650_config *)nb_dev->chip_info;
-@@ -701,6 +728,12 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, 
u32 port)
-                               printk(BIOS_DEBUG, "PcieTrainPort port=0x%x 
result=%d\n", port, res);
-                               if (res) {
-                                       AtiPcieCfg.PortDetect |= 1 << port;
-+                              } else {
-+                                      /* If the training failed the disable 
the bridge to prevent subsequent
-+                                       * lockup on bridge configuration 
register read during the PCI bus scan
-+                                       */
-+                                      training_ok = 0;
-+                                      dev->enabled = 0;
-                               }
-                       }
-               }
-@@ -747,8 +780,8 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 
port)
-        * wait dev 0x6B bit3 clear
-        */
- 
--      if (port == 8){
--              PciePowerOffGppPorts(nb_dev, dev, port); /* , This should be 
run for all ports that are not hotplug and don't detect devices */
-+      if ((port == 8) || (!training_ok)) {
-+              PciePowerOffGppPorts(nb_dev, dev, port);        /* This is run 
for all ports that are not hotplug and don't detect devices */
-       }
- }
- 
-diff --git a/src/southbridge/amd/sr5650/sr5650.c 
b/src/southbridge/amd/sr5650/sr5650.c
-index 441be66..75383de 100644
---- a/src/southbridge/amd/sr5650/sr5650.c
-+++ b/src/southbridge/amd/sr5650/sr5650.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -95,32 +96,30 @@ void nbpcie_ind_write_index(device_t nb_dev, u32 index, 
u32 data)
- void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add)
- {
-       /* K8 Function1 is address map */
--      device_t k8_f1;
--      device_t np = dev_find_slot(0, PCI_DEVFN(0x19, 1));
--      u16 node;
--
--      for (node = 0; node < CONFIG_MAX_PHYSICAL_CPUS; node++) {
--              k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1));
--              if (!k8_f1) {
--                      break;
--              }
--
--              if (in_out) {
--                      /* Fill MMIO limit/base pair. */
--                      pci_write_config32(k8_f1, 0xbc,
--                                         (((pcie_base_add + 0x10000000 -
--                                            1) >> 8) & 0xffffff00) | 0x8 | 
(np ? 2 << 4 : 0 << 4));
--                      pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 
0x3);
--                      pci_write_config32(k8_f1, 0xb4,
--                                         ((mmio_base_add + 0x10000000 -
--                                           1) >> 8) | (np ? 2 << 4 : 0 << 4));
--                      pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 
0x3);
--              } else {
--                      pci_write_config32(k8_f1, 0xb8, 0);
--                      pci_write_config32(k8_f1, 0xbc, 0);
--                      pci_write_config32(k8_f1, 0xb0, 0);
--                      pci_write_config32(k8_f1, 0xb4, 0);
--              }
-+      device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
-+      device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
-+
-+      if (in_out) {
-+              u32 dword, sblk;
-+
-+              /* Get SBLink value (HyperTransport I/O Hub Link ID). */
-+              dword = pci_read_config32(k8_f0, 0x64);
-+              sblk = (dword >> 8) & 0x3;
-+
-+              /* Fill MMIO limit/base pair. */
-+              pci_write_config32(k8_f1, 0xbc,
-+                                 (((pcie_base_add + 0x10000000 -
-+                                   1) >> 8) & 0xffffff00) | 0x80 | (sblk << 
4));
-+              pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3);
-+              pci_write_config32(k8_f1, 0xb4,
-+                                 (((mmio_base_add + 0x10000000 -
-+                                   1) >> 8) & 0xffffff00) | (sblk << 4));
-+              pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3);
-+      } else {
-+              pci_write_config32(k8_f1, 0xb8, 0);
-+              pci_write_config32(k8_f1, 0xbc, 0);
-+              pci_write_config32(k8_f1, 0xb0, 0);
-+              pci_write_config32(k8_f1, 0xb4, 0);
-       }
- }
- 
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0007-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
 
b/resources/libreboot/patch/kgpe-d16/0007-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
deleted file mode 100644
index 017295e..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0007-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
+++ /dev/null
@@ -1,832 +0,0 @@
-From 1c4603c0b0003dc41519ed8e03782ff6e1f9222f Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 17:50:29 -0500
-Subject: [PATCH 007/139] cpu/amd: Add initial support for AMD Socket G34
- processors
-
-Change-Id: Iccd034f32c26513edd52ca3a11a30f61c362682d
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/cpu/amd/Kconfig                        |   1 +
- src/cpu/amd/Makefile.inc                   |   1 +
- src/cpu/amd/car/post_cache_as_ram.c        |  19 ++++-
- src/cpu/amd/model_10xxx/init_cpus.c        |  34 ++++++++-
- src/cpu/amd/model_10xxx/model_10xxx_init.c |   2 +
- src/cpu/amd/model_10xxx/processor_name.c   |  23 +++++++
- src/cpu/amd/model_10xxx/ram_calc.c         |   2 +
- src/cpu/amd/quadcore/quadcore_id.c         |  77 ++++++++++++++++-----
- src/cpu/amd/socket_G34/Kconfig             |  29 ++++++++
- src/cpu/amd/socket_G34/Makefile.inc        |  14 ++++
- src/cpu/amd/socket_G34/socket_G34.c        |  25 +++++++
- src/northbridge/amd/amdfam10/northbridge.c | 102 ++++++++++++++++++++++-----
- src/northbridge/amd/amdht/ht_wrapper.c     | 107 ++++++++++++++++++++++++++++-
- src/northbridge/amd/amdht/ht_wrapper.h     |  25 +++++++
- 14 files changed, 417 insertions(+), 44 deletions(-)
- create mode 100644 src/cpu/amd/socket_G34/Kconfig
- create mode 100644 src/cpu/amd/socket_G34/Makefile.inc
- create mode 100644 src/cpu/amd/socket_G34/socket_G34.c
- create mode 100644 src/northbridge/amd/amdht/ht_wrapper.h
-
-diff --git a/src/cpu/amd/Kconfig b/src/cpu/amd/Kconfig
-index 8286b2a..3a02043 100644
---- a/src/cpu/amd/Kconfig
-+++ b/src/cpu/amd/Kconfig
-@@ -5,6 +5,7 @@ source src/cpu/amd/socket_AM2/Kconfig
- source src/cpu/amd/socket_AM2r2/Kconfig
- source src/cpu/amd/socket_AM3/Kconfig
- source src/cpu/amd/socket_C32/Kconfig
-+source src/cpu/amd/socket_G34/Kconfig
- source src/cpu/amd/socket_ASB2/Kconfig
- source src/cpu/amd/socket_F/Kconfig
- source src/cpu/amd/socket_F_1207/Kconfig
-diff --git a/src/cpu/amd/Makefile.inc b/src/cpu/amd/Makefile.inc
-index a73e25f..e532aba 100644
---- a/src/cpu/amd/Makefile.inc
-+++ b/src/cpu/amd/Makefile.inc
-@@ -8,6 +8,7 @@ subdirs-$(CONFIG_CPU_AMD_SOCKET_AM2R2) += socket_AM2r2
- subdirs-$(CONFIG_CPU_AMD_SOCKET_AM3) += socket_AM3
- subdirs-$(CONFIG_CPU_AMD_SOCKET_ASB2) += socket_ASB2
- subdirs-$(CONFIG_CPU_AMD_SOCKET_C32_NON_AGESA) += socket_C32
-+subdirs-$(CONFIG_CPU_AMD_SOCKET_G34_NON_AGESA) += socket_G34
- subdirs-$(CONFIG_CPU_AMD_GEODE_GX2) += geode_gx2
- subdirs-$(CONFIG_CPU_AMD_GEODE_LX) += geode_lx
- subdirs-$(CONFIG_CPU_AMD_SOCKET_S1G1) += socket_S1G1
-diff --git a/src/cpu/amd/car/post_cache_as_ram.c 
b/src/cpu/amd/car/post_cache_as_ram.c
-index 96df3e7..230d1aa 100644
---- a/src/cpu/amd/car/post_cache_as_ram.c
-+++ b/src/cpu/amd/car/post_cache_as_ram.c
-@@ -1,4 +1,5 @@
--/* 2005.6 by yhlu
-+/* Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ * 2005.6 by yhlu
-  * 2006.3 yhlu add copy data from CAR to ram
-  */
- #include <string.h>
-@@ -46,6 +47,15 @@ static void memset_(void *d, int val, size_t len)
-       memset(d, val, len);
- }
- 
-+static int memcmp_(void *d, const void *s, size_t len)
-+{
-+#if PRINTK_IN_CAR
-+      printk(BIOS_SPEW, " Compare [%08x-%08x] with [%08x - %08x] ... ",
-+              (u32) s, (u32) (s + len - 1), (u32) d, (u32) (d + len - 1));
-+#endif
-+      return memcmp(d, s, len);
-+}
-+
- static void prepare_romstage_ramstack(void *resume_backup_memory)
- {
-       size_t backup_top = backup_size();
-@@ -110,6 +120,12 @@ void post_cache_as_ram(void)
-       memcpy_(migrated_car, &_car_data_start[0], car_size);
-       print_car_debug("Done\n");
- 
-+      print_car_debug("Verifying data integrity in RAM... ");
-+      if (memcmp_(migrated_car, &_car_data_start[0], car_size) == 0)
-+              print_car_debug("Done\n");
-+      else
-+              print_car_debug("FAILED\n");
-+
-       /* New stack grows right below migrated_car. */
-       print_car_debug("Switching to use RAM as stack... ");
-       cache_as_ram_switch_stack(migrated_car);
-@@ -128,6 +144,7 @@ void cache_as_ram_new_stack (void)
-       disable_cache_as_ram_bsp();
- 
-       disable_cache();
-+      /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */
-       set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
-       enable_cache();
- 
-diff --git a/src/cpu/amd/model_10xxx/init_cpus.c 
b/src/cpu/amd/model_10xxx/init_cpus.c
-index 4c72848..8de6d25 100644
---- a/src/cpu/amd/model_10xxx/init_cpus.c
-+++ b/src/cpu/amd/model_10xxx/init_cpus.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -67,6 +68,9 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
-       u32 nb_cfg_54;
-       int i, j;
-       u32 ApicIdCoreIdSize;
-+      uint8_t rev_gte_d = 0;
-+      uint8_t dual_node = 0;
-+      uint32_t f3xe8;
- 
-       /* get_nodes define in ht_wrapper.c */
-       nodes = get_nodes();
-@@ -81,6 +85,16 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
-       /* Assume that all node are same stepping, otherwise we can use use
-          nb_cfg_54 from bsp for all nodes */
-       nb_cfg_54 = read_nb_cfg_54();
-+      f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
-+
-+      if (cpuid_eax(0x80000001) >= 0x8)
-+              /* Revision D or later */
-+              rev_gte_d = 1;
-+
-+      if (rev_gte_d)
-+               /* Check for dual node capability */
-+              if (f3xe8 & 0x20000000)
-+                      dual_node = 1;
- 
-       ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
-       if (ApicIdCoreIdSize) {
-@@ -91,6 +105,8 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
- 
-       for (i = 0; i < nodes; i++) {
-               cores_found = get_core_num_in_bsp(i);
-+              if (siblings > cores_found)
-+                      siblings = cores_found;
- 
-               u32 jstart, jend;
- 
-@@ -107,9 +123,21 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
-               }
- 
-               for (j = jstart; j <= jend; j++) {
--                      ap_apicid =
--                          i * (nb_cfg_54 ? (siblings + 1) : 1) +
--                          j * (nb_cfg_54 ? 1 : 64);
-+                      if (dual_node) {
-+                              ap_apicid = 0;
-+                              if (nb_cfg_54) {
-+                                      ap_apicid |= ((i >> 1) & 0x3) << 4;     
                /* Node ID */
-+                                      ap_apicid |= ((i & 0x1) * (siblings + 
1)) + j;          /* Core ID */
-+                              } else {
-+                                      ap_apicid |= i & 0x3;                   
                /* Node ID */
-+                                      ap_apicid |= (((i & 0x1) * (siblings + 
1)) + j) << 4;   /* Core ID */
-+                              }
-+                      } else {
-+                              ap_apicid =
-+                              i * (nb_cfg_54 ? (siblings + 1) : 1) +
-+                              j * (nb_cfg_54 ? 1 : 64);
-+                      }
-+
- 
- #if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET > 0)
- #if !CONFIG_LIFT_BSP_APIC_ID
-diff --git a/src/cpu/amd/model_10xxx/model_10xxx_init.c 
b/src/cpu/amd/model_10xxx/model_10xxx_init.c
-index 590b89d..b942c1a 100644
---- a/src/cpu/amd/model_10xxx/model_10xxx_init.c
-+++ b/src/cpu/amd/model_10xxx/model_10xxx_init.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2007 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -153,6 +154,7 @@ static struct cpu_device_id cpu_table[] = {
-       { X86_VENDOR_AMD, 0x100F63 },           /* DA-C3 */
-       { X86_VENDOR_AMD, 0x100F80 },           /* HY-D0 */
-       { X86_VENDOR_AMD, 0x100F81 },           /* HY-D1 */
-+      { X86_VENDOR_AMD, 0x100F91 },           /* HY-D1 */
-       { X86_VENDOR_AMD, 0x100FA0 },           /* PH-E0 */
-       { 0, 0 },
- };
-diff --git a/src/cpu/amd/model_10xxx/processor_name.c 
b/src/cpu/amd/model_10xxx/processor_name.c
-index a25e3a9..12c45c9 100644
---- a/src/cpu/amd/model_10xxx/processor_name.c
-+++ b/src/cpu/amd/model_10xxx/processor_name.c
-@@ -157,6 +157,24 @@ static const struct str_s String2_socket_AM2[] = {
-       {0, 0, 0, NULL}
- };
- 
-+static const struct str_s String1_socket_G34[] = {
-+      {0x00, 0x07, 0x00, "AMD Opteron(tm) Processor 61"},
-+      {0x00, 0x0B, 0x00, "AMD Opteron(tm) Processor 61"},
-+      {0x01, 0x07, 0x01, "Embedded AMD Opteron(tm) Processor "},
-+      {0, 0, 0, NULL}
-+};
-+
-+static const struct str_s String2_socket_G34[] = {
-+      {0x00, 0x07, 0x00, " HE"},
-+      {0x00, 0x07, 0x01, " SE"},
-+      {0x00, 0x0B, 0x00, " HE"},
-+      {0x00, 0x0B, 0x01, " SE"},
-+      {0x00, 0x0B, 0x0F, ""},
-+      {0x01, 0x07, 0x01, " QS"},
-+      {0x01, 0x07, 0x02, " KS"},
-+      {0, 0, 0, NULL}
-+};
-+
- static const struct str_s String1_socket_C32[] = {
-       {0x00, 0x03, 0x00, "AMD Opteron(tm) Processor 41"},
-       {0x00, 0x05, 0x00, "AMD Opteron(tm) Processor 41"},
-@@ -240,6 +258,11 @@ int init_processor_name(void)
-               str = String1_socket_AM2;
-               str2 = String2_socket_AM2;
-               break;
-+      case 3:         /* G34 */
-+              str = String1_socket_G34;
-+              str2 = String2_socket_G34;
-+              str2_checkNC = 0;
-+              break;
-       case 5:         /* C32 */
-               str = String1_socket_C32;
-               str2 = String2_socket_C32;
-diff --git a/src/cpu/amd/model_10xxx/ram_calc.c 
b/src/cpu/amd/model_10xxx/ram_calc.c
-index c8637c9..46ccdbd 100644
---- a/src/cpu/amd/model_10xxx/ram_calc.c
-+++ b/src/cpu/amd/model_10xxx/ram_calc.c
-@@ -26,6 +26,7 @@
- 
- #include "ram_calc.h"
- 
-+#if !IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
- uint64_t get_uma_memory_size(uint64_t topmem)
- {
-       uint64_t uma_size = 0;
-@@ -50,3 +51,4 @@ void *cbmem_top(void)
- 
-       return (void *) topmem - get_uma_memory_size(topmem);
- }
-+#endif
-diff --git a/src/cpu/amd/quadcore/quadcore_id.c 
b/src/cpu/amd/quadcore/quadcore_id.c
-index cf45196..c5921de 100644
---- a/src/cpu/amd/quadcore/quadcore_id.c
-+++ b/src/cpu/amd/quadcore/quadcore_id.c
-@@ -1,6 +1,7 @@
- /*
-  * This file is part of the coreboot project.
-  *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  * Copyright (C) 2007 Advanced Micro Devices, Inc.
-  *
-  * This program is free software; you can redistribute it and/or modify
-@@ -37,33 +38,71 @@ u32 get_initial_apicid(void)
-       return ((cpuid_ebx(1) >> 24) & 0xff);
- }
- 
--//called by amd_siblings too
--#define CORE_ID_BIT 2
--#define NODE_ID_BIT 6
-+/* Called by amd_siblings (ramstage) as well */
- struct node_core_id get_node_core_id(u32 nb_cfg_54)
- {
-       struct node_core_id id;
--      u32 core_id_bits;
-+      uint8_t apicid;
-+      uint8_t rev_gte_d = 0;
-+      uint8_t dual_node = 0;
-+      uint32_t f3xe8;
- 
--      u32 ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf);
--      if(ApicIdCoreIdSize) {
--              core_id_bits = ApicIdCoreIdSize;
--      } else {
--              core_id_bits = CORE_ID_BIT; //quad core
--      }
-+#ifdef __PRE_RAM__
-+      f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
-+#else
-+      f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-+#endif
-+
-+      if (cpuid_eax(0x80000001) >= 0x8)
-+              /* Revision D or later */
-+              rev_gte_d = 1;
- 
--      // get the apicid via cpuid(1) ebx[31:24]
-+      if (rev_gte_d)
-+               /* Check for dual node capability */
-+              if (f3xe8 & 0x20000000)
-+                      dual_node = 1;
-+
-+      /* Get the apicid via cpuid(1) ebx[31:24]
-+       * The apicid format varies based on processor revision
-+       */
-+      apicid = (cpuid_ebx(1) >> 24) & 0xff;
-       if( nb_cfg_54) {
--              // when NB_CFG[54] is set, nodeid = ebx[31:26], coreid = 
ebx[25:24]
--              id.coreid = (cpuid_ebx(1) >> 24) & 0xff;
--              id.nodeid = (id.coreid>>core_id_bits);
--              id.coreid &= ((1<<core_id_bits)-1);
-+              if (rev_gte_d && dual_node) {
-+                      id.coreid = apicid & 0xf;
-+                      id.nodeid = (apicid & 0x30) >> 4;
-+              } else if (rev_gte_d && !dual_node) {
-+                      id.coreid = apicid & 0x7;
-+                      id.nodeid = (apicid & 0x38) >> 3;
-+              } else {
-+                      id.coreid = apicid & 0x3;
-+                      id.nodeid = (apicid & 0x1c) >> 2;
-+              }
-       } else {
--              // when NB_CFG[54] is clear, nodeid = ebx[29:24], coreid = 
ebx[31:30]
--              id.nodeid = (cpuid_ebx(1) >> 24) & 0xff;
--              id.coreid = (id.nodeid>>NODE_ID_BIT);
--              id.nodeid &= ((1<<NODE_ID_BIT)-1);
-+              if (rev_gte_d && dual_node) {
-+                      id.coreid = (apicid & 0xf0) >> 4;
-+                      id.nodeid = apicid & 0x3;
-+              } else if (rev_gte_d && !dual_node) {
-+                      id.coreid = (apicid & 0xe0) >> 5;
-+                      id.nodeid = apicid & 0x7;
-+              } else {
-+                      id.coreid = (apicid & 0x60) >> 5;
-+                      id.nodeid = apicid & 0x7;
-+              }
-       }
-+
-+      if (rev_gte_d && dual_node) {
-+              /* Coreboot expects each separate processor die to be on a 
different nodeid.
-+               * Since the code above returns nodeid 0 even on internal node 
1 some fixup is needed...
-+               */
-+              uint8_t core_count = (((f3xe8 & 0x00008000) >> 13) | ((f3xe8 & 
0x00003000) >> 12)) + 1;
-+
-+              id.nodeid = id.nodeid * 2;
-+              if (id.coreid >= core_count) {
-+                      id.nodeid += 1;
-+                      id.coreid = id.coreid - core_count;
-+              }
-+      }
-+
-       return id;
- }
- 
-diff --git a/src/cpu/amd/socket_G34/Kconfig b/src/cpu/amd/socket_G34/Kconfig
-new file mode 100644
-index 0000000..abc9726
---- /dev/null
-+++ b/src/cpu/amd/socket_G34/Kconfig
-@@ -0,0 +1,29 @@
-+config CPU_AMD_SOCKET_G34_NON_AGESA
-+      bool
-+      select CPU_AMD_MODEL_10XXX
-+      select PCI_IO_CFG_EXT
-+      select X86_AMD_FIXED_MTRRS
-+
-+if CPU_AMD_SOCKET_G34_NON_AGESA
-+
-+config CPU_SOCKET_TYPE
-+      hex
-+      default 0x15
-+
-+config EXT_RT_TBL_SUPPORT
-+      bool
-+      default n
-+
-+config CBB
-+      hex
-+      default 0x0
-+
-+config CDB
-+      hex
-+      default 0x18
-+
-+config XIP_ROM_SIZE
-+      hex
-+      default 0x80000
-+
-+endif
-diff --git a/src/cpu/amd/socket_G34/Makefile.inc 
b/src/cpu/amd/socket_G34/Makefile.inc
-new file mode 100644
-index 0000000..a8e1333
---- /dev/null
-+++ b/src/cpu/amd/socket_G34/Makefile.inc
-@@ -0,0 +1,14 @@
-+ramstage-y += socket_G34.c
-+subdirs-y += ../model_10xxx
-+subdirs-y += ../quadcore
-+subdirs-y += ../mtrr
-+subdirs-y += ../microcode
-+subdirs-y += ../../x86/tsc
-+subdirs-y += ../../x86/lapic
-+subdirs-y += ../../x86/cache
-+subdirs-y += ../../x86/pae
-+subdirs-y += ../../x86/mtrr
-+subdirs-y += ../../x86/smm
-+subdirs-y += ../smm
-+
-+cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc
-diff --git a/src/cpu/amd/socket_G34/socket_G34.c 
b/src/cpu/amd/socket_G34/socket_G34.c
-new file mode 100644
-index 0000000..90f7b8c
---- /dev/null
-+++ b/src/cpu/amd/socket_G34/socket_G34.c
-@@ -0,0 +1,25 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * 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
-+ */
-+
-+#include <device/device.h>
-+
-+struct chip_operations cpu_amd_socket_G34_ops = {
-+      CHIP_NAME("socket G34")
-+};
-diff --git a/src/northbridge/amd/amdfam10/northbridge.c 
b/src/northbridge/amd/amdfam10/northbridge.c
-index 6d91cbd..74cecc8 100644
---- a/src/northbridge/amd/amdfam10/northbridge.c
-+++ b/src/northbridge/amd/amdfam10/northbridge.c
-@@ -187,6 +187,43 @@ static void ht_route_link(struct bus *link, scan_state 
mode)
-       }
- }
- 
-+static void amd_g34_fixup(struct bus *link, device_t dev)
-+{
-+      uint32_t nodeid = amdfam10_nodeid(dev);
-+      uint8_t rev_gte_d = 0;
-+      uint8_t dual_node = 0;
-+      uint32_t f3xe8;
-+
-+      if (cpuid_eax(0x80000001) >= 0x8)
-+              /* Revision D or later */
-+              rev_gte_d = 1;
-+
-+      if (rev_gte_d) {
-+              f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-+
-+              /* Check for dual node capability */
-+              if (f3xe8 & 0x20000000)
-+                      dual_node = 1;
-+
-+              if (dual_node) {
-+                      /* Each G34 processor contains a defective HT link.
-+                      * See the BKDG Rev 3.62 section 2.7.1.5 for details.
-+                      */
-+                      f3xe8 = pci_read_config32(get_node_pci(nodeid, 3), 
0xe8);
-+                      uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 
30);
-+                      if (internal_node_number == 0) {
-+                              /* Node 0 */
-+                              if (link->link_num == 6)        /* Link 2 
Sublink 1 */
-+                                      printk(BIOS_DEBUG, 
"amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT 
link\n", nodeid, internal_node_number);
-+                      } else {
-+                              /* Node 1 */
-+                              if (link->link_num == 5)        /* Link 1 
Sublink 1 */
-+                                      printk(BIOS_DEBUG, 
"amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT 
link\n", nodeid, internal_node_number);
-+                      }
-+              }
-+      }
-+}
-+
- static void amdfam10_scan_chain(struct bus *link)
- {
-               unsigned int next_unitid;
-@@ -277,8 +314,11 @@ static void amdfam10_scan_chains(device_t dev)
-       trim_ht_chain(dev);
- 
-       for (link = dev->link_list; link; link = link->next) {
--              if (link->ht_link_up)
-+              if (link->ht_link_up) {
-+                      if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX))
-+                              amd_g34_fixup(link, dev);
-                       amdfam10_scan_chain(link);
-+              }
-       }
- }
- 
-@@ -323,8 +363,7 @@ static struct resource *amdfam10_find_iopair(device_t dev, 
unsigned nodeid, unsi
-               if (result == 1) {
-                       /* I have been allocated this one */
-                       break;
--              }
--              else if (result > 1) {
-+              } else if (result > 1) {
-                       /* I have a free register pair */
-                       free_reg = reg;
-               }
-@@ -357,8 +396,7 @@ static struct resource *amdfam10_find_mempair(device_t 
dev, u32 nodeid, u32 link
-               if (result == 1) {
-                       /* I have been allocated this one */
-                       break;
--              }
--              else if (result > 1) {
-+              } else if (result > 1) {
-                       /* I have a free register pair */
-                       free_reg = reg;
-               }
-@@ -473,8 +511,7 @@ static void amdfam10_set_resource(device_t dev, struct 
resource *resource,
- 
-               set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
-               store_conf_io_addr(nodeid, link_num, reg, (resource->index >> 
24), rbase>>8, rend>>8);
--      }
--      else if (resource->flags & IORESOURCE_MEM) {
-+      } else if (resource->flags & IORESOURCE_MEM) {
-               set_mmio_addr_reg(nodeid, link_num, reg, (resource->index 
>>24), rbase>>8, rend>>8, sysconf.nodes) ;// [39:8]
-               store_conf_mmio_addr(nodeid, link_num, reg, (resource->index 
>>24), rbase>>8, rend>>8);
-       }
-@@ -799,8 +836,7 @@ static void amdfam10_domain_set_resources(device_t dev)
-                       }
-                       if ((basek + sizek) <= 4*1024*1024) {
-                               sizek = 0;
--                      }
--                      else {
-+                      } else {
-                               basek = 4*1024*1024;
-                               sizek -= (4*1024*1024 - mmio_basek);
-                       }
-@@ -977,8 +1013,7 @@ static int amdfam10_get_smbios_data17(int* count, int 
handle, int parent_handle,
-                               if (dimm_size_bytes > 0x800000000) {
-                                       t->size = 0x7FFF;
-                                       t->extended_size = dimm_size_bytes;
--                              }
--                              else {
-+                              } else {
-                                       t->size = dimm_size_bytes / (1024*1024);
-                                       t->size &= (~0x8000);   /* size 
specified in megabytes */
-                               }
-@@ -1005,8 +1040,7 @@ static int amdfam10_get_smbios_data17(int* count, int 
handle, int parent_handle,
-                               t->part_number = smbios_add_string(t->eos, 
mem_info->dct_stat[node].DimmPartNumber[slot]);
-                               if 
(mem_info->dct_stat[node].DimmSerialNumber[slot] == 0) {
-                                       t->serial_number = 
smbios_add_string(t->eos, "None");
--                              }
--                              else {
-+                              } else {
-                                       snprintf(string_buffer, sizeof 
(string_buffer), "%08X", mem_info->dct_stat[node].DimmSerialNumber[slot]);
-                                       t->serial_number = 
smbios_add_string(t->eos, string_buffer);
-                               }
-@@ -1108,8 +1142,7 @@ static void add_more_links(device_t dev, unsigned 
total_links)
-                       memset(link, 0, links*sizeof(*link));
-                       last->next = link;
-               }
--      }
--      else {
-+      } else {
-               link = malloc(total_links*sizeof(*link));
-               memset(link, 0, total_links*sizeof(*link));
-               dev->link_list = link;
-@@ -1244,6 +1277,10 @@ static void cpu_bus_scan(device_t dev)
-               unsigned busn, devn;
-               struct bus *pbus;
- 
-+              uint8_t rev_gte_d = 0;
-+              uint8_t dual_node = 0;
-+              uint32_t f3xe8;
-+
-               busn = CONFIG_CBB;
-               devn = CONFIG_CDB+i;
-               pbus = dev_mc->bus;
-@@ -1268,6 +1305,7 @@ static void cpu_bus_scan(device_t dev)
-                       }
-               }
- 
-+
-               /* Ok, We need to set the links for that device.
-                * otherwise the device under it will not be scanned
-                */
-@@ -1279,6 +1317,17 @@ static void cpu_bus_scan(device_t dev)
-               if (cdb_dev)
-                       add_more_links(cdb_dev, 4);
- 
-+              f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-+
-+              if (cpuid_eax(0x80000001) >= 0x8)
-+                      /* Revision D or later */
-+                      rev_gte_d = 1;
-+
-+              if (rev_gte_d)
-+                      /* Check for dual node capability */
-+                      if (f3xe8 & 0x20000000)
-+                              dual_node = 1;
-+
-               cores_found = 0; // one core
-               cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
-               int enable_node = cdb_dev && cdb_dev->enabled;
-@@ -1290,6 +1339,9 @@ static void cpu_bus_scan(device_t dev)
-                       printk(BIOS_DEBUG, "  %s siblings=%d\n", 
dev_path(cdb_dev), cores_found);
-               }
- 
-+              if (siblings > cores_found)
-+                      siblings = cores_found;
-+
-               u32 jj;
-               if(disable_siblings) {
-                       jj = 0;
-@@ -1299,7 +1351,20 @@ static void cpu_bus_scan(device_t dev)
-               }
- 
-               for (j = 0; j <=jj; j++ ) {
--                      u32 apic_id = i * (nb_cfg_54?(siblings+1):1) + j * 
(nb_cfg_54?1:64); // ?
-+                      u32 apic_id;
-+
-+                      if (dual_node) {
-+                              apic_id = 0;
-+                              if (nb_cfg_54) {
-+                                      apic_id |= ((i >> 1) & 0x3) << 4;       
                /* Node ID */
-+                                      apic_id |= ((i & 0x1) * (siblings + 1)) 
+ j;            /* Core ID */
-+                              } else {
-+                                      apic_id |= i & 0x3;                     
                /* Node ID */
-+                                      apic_id |= (((i & 0x1) * (siblings + 
1)) + j) << 4;     /* Core ID */
-+                              }
-+                      } else {
-+                              apic_id = i * (nb_cfg_54?(siblings+1):1) + j * 
(nb_cfg_54?1:64); // ?
-+                      }
- 
- #if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET>0)
-                       if(sysconf.enabled_apic_ext_id) {
-@@ -1311,7 +1376,7 @@ static void cpu_bus_scan(device_t dev)
-                       device_t cpu = add_cpu_device(cpu_bus, apic_id, 
enable_node);
-                       if (cpu)
-                               amd_cpu_topology(cpu, i, j);
--              } //j
-+              }
-       }
- }
- 
-@@ -1356,8 +1421,7 @@ static void root_complex_enable_dev(struct device *dev)
-       /* Set the operations if it is a special bus type */
-       if (dev->path.type == DEVICE_PATH_DOMAIN) {
-               dev->ops = &pci_domain_ops;
--      }
--      else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
-+      } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
-               dev->ops = &cpu_bus_ops;
-       }
- }
-diff --git a/src/northbridge/amd/amdht/ht_wrapper.c 
b/src/northbridge/amd/amdht/ht_wrapper.c
-index 36fe60b..389b1b1 100644
---- a/src/northbridge/amd/amdht/ht_wrapper.c
-+++ b/src/northbridge/amd/amdht/ht_wrapper.c
-@@ -22,6 +22,8 @@
- #include <console/console.h>
- #include <northbridge/amd/amdfam10/amdfam10.h>
- 
-+#include "ht_wrapper.h"
-+
- /*----------------------------------------------------------------------------
-  *                    TYPEDEFS, DEFINITIONS AND MACROS
-  *
-@@ -113,6 +115,20 @@ void getAmdTopolist(u8 ***p)
-       *p = (u8 **)amd_topo_list;
- }
- 
-+/**
-+ * BOOL AMD_CB_IgnoreLink(u8 Node, u8 Link)
-+ * Description:
-+ *    This routine is used to ignore connected yet faulty HT links,
-+ *    such as those present in a G34 processor package.
-+ *
-+ * Parameters:
-+ *    @param[in]  node   = The node on which this chain is located
-+ *    @param[in]  link   = The link on the host for this chain
-+ */
-+static BOOL AMD_CB_IgnoreLink (u8 node, u8 link)
-+{
-+      return 0;
-+}
- 
- /**
-  * void amd_ht_init(struct sys_info *sysinfo)
-@@ -128,7 +144,7 @@ static void amd_ht_init(struct sys_info *sysinfo)
-               0,      // u8 AutoBusStart;
-               32,     // u8 AutoBusMax;
-               6,      // u8 AutoBusIncrement;
--              NULL,   // BOOL (*AMD_CB_IgnoreLink)();
-+              AMD_CB_IgnoreLink,              // BOOL (*AMD_CB_IgnoreLink)();
-               NULL,   // BOOL (*AMD_CB_OverrideBusNumbers)();
-               AMD_CB_ManualBUIDSwapList,      // BOOL 
(*AMD_CB_ManualBUIDSwapList)();
-               NULL,   // void (*AMD_CB_DeviceCapOverride)();
-@@ -146,6 +162,93 @@ static void amd_ht_init(struct sys_info *sysinfo)
-       printk(BIOS_DEBUG, "Enter amd_ht_init()\n");
-       amdHtInitialize(&ht_wrapper);
-       printk(BIOS_DEBUG, "Exit amd_ht_init()\n");
-+}
- 
--
-+/**
-+ * void amd_ht_fixup(struct sys_info *sysinfo)
-+ *
-+ *  AMD HT fixup
-+ *
-+ */
-+void amd_ht_fixup(struct sys_info *sysinfo) {
-+      printk(BIOS_DEBUG, "amd_ht_fixup()\n");
-+      if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) {
-+              uint8_t rev_gte_d = 0;
-+              uint8_t dual_node = 0;
-+              uint32_t f3xe8;
-+              uint32_t family;
-+              uint32_t model;
-+
-+              family = model = cpuid_eax(0x80000001);
-+              model = ((model & 0xf0000) >> 16) | ((model & 0xf0) >> 4);
-+
-+              if (model >= 0x8)
-+                      /* Revision D or later */
-+                      rev_gte_d = 1;
-+
-+              if (rev_gte_d) {
-+                      f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
-+
-+                      /* Check for dual node capability */
-+                      if (f3xe8 & 0x20000000)
-+                              dual_node = 1;
-+
-+                      if (dual_node) {
-+                              /* Each G34 processor contains a defective HT 
link.
-+                              * See the BKDG Rev 3.62 section 2.7.1.5 for 
details.
-+                              */
-+                              uint8_t node;
-+                              uint8_t node_count = get_nodes();
-+                              uint32_t dword;
-+                              for (node = 0; node < node_count; node++) {
-+                                      f3xe8 = 
pci_read_config32(NODE_PCI(node, 3), 0xe8);
-+                                      uint8_t internal_node_number = ((f3xe8 
& 0xc0000000) >> 30);
-+                                      printk(BIOS_DEBUG, "amd_ht_fixup(): 
node %d (internal node ID %d): disabling defective HT link\n", node, 
internal_node_number);
-+                                      if (internal_node_number == 0) {
-+                                              uint8_t 
package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xd8) & 0x1;
-+                                              if (package_link_3_connected) {
-+                                                      /* Set WidthIn and 
WidthOut to 0 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0xc4);
-+                                                      dword &= ~0x77000000;
-+                                                      
pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
-+                                                      /* Set Ganged to 1 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x178);
-+                                                      dword |= 0x00000001;
-+                                                      
pci_write_config32(NODE_PCI(node, 0), 0x178, dword);
-+                                              } else {
-+                                                      /* Set ConnDly to 1 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x16c);
-+                                                      dword |= 0x00000100;
-+                                                      
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
-+                                                      /* Set TransOff and 
EndOfChain to 1 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 4), 0xc4);
-+                                                      dword |= 0x000000c0;
-+                                                      
pci_write_config32(NODE_PCI(node, 4), 0xc4, dword);
-+                                              }
-+                                      } else if (internal_node_number == 1) {
-+                                              uint8_t 
package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xb8) & 0x1;
-+                                              if (package_link_3_connected) {
-+                                                      /* Set WidthIn and 
WidthOut to 0 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0xa4);
-+                                                      dword &= ~0x77000000;
-+                                                      
pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
-+                                                      /* Set Ganged to 1 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x174);
-+                                                      dword |= 0x00000001;
-+                                                      
pci_write_config32(NODE_PCI(node, 0), 0x174, dword);
-+                                              } else {
-+                                                      /* Set ConnDly to 1 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x16c);
-+                                                      dword |= 0x00000100;
-+                                                      
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
-+                                                      /* Set TransOff and 
EndOfChain to 1 */
-+                                                      dword = 
pci_read_config32(NODE_PCI(node, 4), 0xa4);
-+                                                      dword |= 0x000000c0;
-+                                                      
pci_write_config32(NODE_PCI(node, 4), 0xa4, dword);
-+                                              }
-+                                      }
-+                              }
-+                      }
-+              }
-+      }
- }
-diff --git a/src/northbridge/amd/amdht/ht_wrapper.h 
b/src/northbridge/amd/amdht/ht_wrapper.h
-new file mode 100644
-index 0000000..3e9d957
---- /dev/null
-+++ b/src/northbridge/amd/amdht/ht_wrapper.h
-@@ -0,0 +1,25 @@
-+/*
-+ * This file is part of the coreboot project.
-+ *
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-+ *
-+ * 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.
-+ */
-+
-+#ifndef AMD_HT_WRAPPER_H
-+#define AMD_HT_WRAPPER_H
-+
-+void amd_ht_fixup(struct sys_info *sysinfo);
-+
-+#endif
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0007-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
 
b/resources/libreboot/patch/kgpe-d16/0007-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
new file mode 100644
index 0000000..0cac522
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0007-southbridge-amd-sb700-Fix-boot-hang-on-ASUS-KGPE-D16.patch
@@ -0,0 +1,619 @@
+From c95c41fbedceda4de85a076f8fc600c82106727c Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 5 Sep 2015 17:46:15 -0500
+Subject: [PATCH 007/143] southbridge/amd/sb700: Fix boot hang on ASUS
+ KGPE-D16
+
+Change-Id: I1d7d6715663a13ab94fd6d71808e35f0f7384d00
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/southbridge/amd/sb700/Kconfig       |    4 +
+ src/southbridge/amd/sb700/acpi/ide.asl  |  234 +++++++++++++++++++++++++++++++
+ src/southbridge/amd/sb700/acpi/sata.asl |  133 ++++++++++++++++++
+ src/southbridge/amd/sb700/bootblock.c   |   46 +++++-
+ src/southbridge/amd/sb700/early_setup.c |   18 +++
+ src/southbridge/amd/sb700/lpc.c         |    3 +
+ src/southbridge/amd/sb700/sm.c          |   21 +--
+ 7 files changed, 444 insertions(+), 15 deletions(-)
+ create mode 100644 src/southbridge/amd/sb700/acpi/ide.asl
+ create mode 100644 src/southbridge/amd/sb700/acpi/sata.asl
+
+diff --git a/src/southbridge/amd/sb700/Kconfig 
b/src/southbridge/amd/sb700/Kconfig
+index 0761934..bca74fb 100644
+--- a/src/southbridge/amd/sb700/Kconfig
++++ b/src/southbridge/amd/sb700/Kconfig
+@@ -42,6 +42,10 @@ config SOUTHBRIDGE_AMD_SB700_SKIP_ISA_DMA_INIT
+       bool
+       default n
+ 
++config SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA
++      bool
++      default n
++
+ config EHCI_BAR
+       hex
+       default 0xfef00000
+diff --git a/src/southbridge/amd/sb700/acpi/ide.asl 
b/src/southbridge/amd/sb700/acpi/ide.asl
+new file mode 100644
+index 0000000..9b5e3ea
+--- /dev/null
++++ b/src/southbridge/amd/sb700/acpi/ide.asl
+@@ -0,0 +1,234 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ *
++ * 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
++ */
++
++/* Some timing tables */
++Name(UDTT, Package(){ /* Udma timing table */
++      120, 90, 60, 45, 30, 20, 15, 0  /* UDMA modes 0 -> 6 */
++})
++
++Name(MDTT, Package(){ /* MWDma timing table */
++      480, 150, 120, 0        /* Legacy DMA modes 0 -> 2 */
++})
++
++Name(POTT, Package(){ /* Pio timing table */
++      600, 390, 270, 180, 120, 0      /* PIO modes 0 -> 4 */
++})
++
++/* Some timing register value tables */
++Name(MDRT, Package(){ /* MWDma timing register table */
++      0x77, 0x21, 0x20, 0xFF  /* Legacy DMA modes 0 -> 2 */
++})
++
++Name(PORT, Package(){
++      0x99, 0x47, 0x34, 0x22, 0x20, 0x99      /* PIO modes 0 -> 4 */
++})
++
++OperationRegion(ICRG, PCI_Config, 0x40, 0x20) /* ide control registers */
++      Field(ICRG, AnyAcc, NoLock, Preserve)
++{
++      PPTS, 8,        /* Primary PIO Slave Timing */
++      PPTM, 8,        /* Primary PIO Master Timing */
++      OFFSET(0x04), PMTS, 8,  /* Primary MWDMA Slave Timing */
++      PMTM, 8,        /* Primary MWDMA Master Timing */
++      OFFSET(0x08), PPCR, 8,  /* Primary PIO Control */
++      OFFSET(0x0A), PPMM, 4,  /* Primary PIO master Mode */
++      PPSM, 4,        /* Primary PIO slave Mode */
++      OFFSET(0x14), PDCR, 2,  /* Primary UDMA Control */
++      OFFSET(0x16), PDMM, 4,  /* Primary UltraDMA Mode */
++      PDSM, 4,        /* Primary UltraDMA Mode */
++}
++
++Method(GTTM, 1) /* get total time*/
++{
++      Store(And(Arg0, 0x0F), Local0)  /* Recovery Width */
++      Increment(Local0)
++      Store(ShiftRight(Arg0, 4), Local1)      /* Command Width */
++      Increment(Local1)
++      Return(Multiply(30, Add(Local0, Local1)))
++}
++
++Device(PRID)
++{
++      Name (_ADR, Zero)
++      Method(_GTM, 0, Serialized)
++      {
++              NAME(OTBF, Buffer(20) { /* out buffer */
++                      0xFF, 0xFF, 0xFF, 0xFF,
++                      0xFF, 0xFF, 0xFF, 0xFF,
++                      0xFF, 0xFF, 0xFF, 0xFF,
++                      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
++              })
++
++              CreateDwordField(OTBF, 0, PSD0)   /* PIO spd0 */
++              CreateDwordField(OTBF, 4, DSD0)   /* DMA spd0 */
++              CreateDwordField(OTBF, 8, PSD1)   /* PIO spd1 */
++              CreateDwordField(OTBF, 12, DSD1) /* DMA spd1 */
++              CreateDwordField(OTBF, 16, BFFG) /* buffer flags */
++
++              /* Just return if the channel is disabled */
++              If(And(PPCR, 0x01)) { /* primary PIO control */
++                      Return(OTBF)
++              }
++
++              /* Always tell them independent timing available and 
IOChannelReady used on both drives */
++              Or(BFFG, 0x1A, BFFG)
++
++              Store(GTTM(PPTM), PSD0) /* save total time of primary PIO 
master timming  to PIO spd0 */
++              Store(GTTM(PPTS), PSD1) /* save total time of primary PIO slave 
Timing  to PIO spd1 */
++
++              If(And(PDCR, 0x01)) {   /* It's under UDMA mode */
++                      Or(BFFG, 0x01, BFFG)
++                      Store(DerefOf(Index(UDTT, PDMM)), DSD0)
++              }
++              Else {
++                      Store(GTTM(PMTM), DSD0) /* Primary MWDMA Master Timing, 
 DmaSpd0 */
++              }
++
++              If(And(PDCR, 0x02)) {   /* It's under UDMA mode */
++                      Or(BFFG, 0x04, BFFG)
++                      Store(DerefOf(Index(UDTT, PDSM)), DSD1)
++              }
++              Else {
++                      Store(GTTM(PMTS), DSD1) /* Primary MWDMA Slave Timing,  
DmaSpd0 */
++              }
++
++              Return(OTBF) /* out buffer */
++      }                               /* End Method(_GTM) */
++
++      Method(_STM, 3, Serialized)
++      {
++              NAME(INBF, Buffer(20) { /* in buffer */
++                      0xFF, 0xFF, 0xFF, 0xFF,
++                      0xFF, 0xFF, 0xFF, 0xFF,
++                      0xFF, 0xFF, 0xFF, 0xFF,
++                      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
++              })
++
++              CreateDwordField(INBF, 0, PSD0)    /* PIO spd0 */
++              CreateDwordField(INBF, 4, DSD0)   /* PIO spd0 */
++              CreateDwordField(INBF, 8, PSD1)   /* PIO spd1 */
++              CreateDwordField(INBF, 12, DSD1) /* DMA spd1 */
++              CreateDwordField(INBF, 16, BFFG) /*buffer flag */
++
++              Store(Match(POTT, MLE, PSD0, MTR, 0, 0), Local0)
++              Divide(Local0, 5, PPMM,) /* Primary PIO master Mode */
++              Store(Match(POTT, MLE, PSD1, MTR, 0, 0), Local1)
++              Divide(Local1, 5, PPSM,) /* Primary PIO slave Mode */
++
++              Store(DerefOf(Index(PORT, Local0)), PPTM) /* Primary PIO Master 
Timing */
++              Store(DerefOf(Index(PORT, Local1)), PPTS) /* Primary PIO Slave 
Timing */
++
++              If(And(BFFG, 0x01)) {   /* Drive 0 is under UDMA mode */
++                      Store(Match(UDTT, MLE, DSD0, MTR, 0, 0), Local0)
++                      Divide(Local0, 7, PDMM,)
++                      Or(PDCR, 0x01, PDCR)
++              }
++              Else {
++                      If(LNotEqual(DSD0, 0xFFFFFFFF)) {
++                              Store(Match(MDTT, MLE, DSD0, MTR, 0, 0), Local0)
++                              Store(DerefOf(Index(MDRT, Local0)), PMTM)
++                      }
++              }
++
++              If(And(BFFG, 0x04)) {   /* Drive 1 is under UDMA mode */
++                      Store(Match(UDTT, MLE, DSD1, MTR, 0, 0), Local0)
++                      Divide(Local0, 7, PDSM,)
++                      Or(PDCR, 0x02, PDCR)
++              }
++              Else {
++                      If(LNotEqual(DSD1, 0xFFFFFFFF)) {
++                              Store(Match(MDTT, MLE, DSD1, MTR, 0, 0), Local0)
++                              Store(DerefOf(Index(MDRT, Local0)), PMTS)
++                      }
++              }
++              /* Return(INBF) */
++      }               /*End Method(_STM) */
++      Device(MST)
++      {
++              Name(_ADR, 0)
++              Method(_GTF, 0, Serialized) {
++                      Name(CMBF, Buffer(21) {
++                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
++                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
++                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5
++                      })
++                      CreateByteField(CMBF, 1, POMD)
++                      CreateByteField(CMBF, 8, DMMD)
++                      CreateByteField(CMBF, 5, CMDA)
++                      CreateByteField(CMBF, 12, CMDB)
++                      CreateByteField(CMBF, 19, CMDC)
++
++                      Store(0xA0, CMDA)
++                      Store(0xA0, CMDB)
++                      Store(0xA0, CMDC)
++
++                      Or(PPMM, 0x08, POMD)
++
++                      If(And(PDCR, 0x01)) {
++                              Or(PDMM, 0x40, DMMD)
++                      }
++                      Else {
++                              Store(Match
++                                    (MDTT, MLE, GTTM(PMTM),
++                                     MTR, 0, 0), Local0)
++                              If(LLess(Local0, 3)) {
++                                      Or(0x20, Local0, DMMD)
++                              }
++                      }
++                      Return(CMBF)
++              }
++      }               /* End Device(MST) */
++
++      Device(SLAV)
++      {
++              Name(_ADR, 1)
++              Method(_GTF, 0, Serialized) {
++                      Name(CMBF, Buffer(21) {
++                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
++                              0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
++                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5
++                      })
++                      CreateByteField(CMBF, 1, POMD)
++                      CreateByteField(CMBF, 8, DMMD)
++                      CreateByteField(CMBF, 5, CMDA)
++                      CreateByteField(CMBF, 12, CMDB)
++                      CreateByteField(CMBF, 19, CMDC)
++
++                      Store(0xB0, CMDA)
++                      Store(0xB0, CMDB)
++                      Store(0xB0, CMDC)
++
++                      Or(PPSM, 0x08, POMD)
++
++                      If(And(PDCR, 0x02)) {
++                              Or(PDSM, 0x40, DMMD)
++                      }
++                      Else {
++                              Store(Match
++                                    (MDTT, MLE, GTTM(PMTS),
++                                     MTR, 0, 0), Local0)
++                              If(LLess(Local0, 3)) {
++                                      Or(0x20, Local0, DMMD)
++                              }
++                      }
++                      Return(CMBF)
++              }
++      }                       /* End Device(SLAV) */
++}
+diff --git a/src/southbridge/amd/sb700/acpi/sata.asl 
b/src/southbridge/amd/sb700/acpi/sata.asl
+new file mode 100644
+index 0000000..46a82b7
+--- /dev/null
++++ b/src/southbridge/amd/sb700/acpi/sata.asl
+@@ -0,0 +1,133 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * 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
++ */
++
++Name(STTM, Buffer(20) {
++      0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
++      0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
++      0x1f, 0x00, 0x00, 0x00
++})
++
++/* Start by clearing the PhyRdyChg bits */
++Method(_INI) {
++      \_GPE._L1F()
++}
++
++Device(PMRY)
++{
++      Name(_ADR, 0)
++      Method(_GTM, 0x0, NotSerialized) {
++              Return(STTM)
++      }
++      Method(_STM, 0x3, NotSerialized) {}
++
++      Device(PMST) {
++              Name(_ADR, 0)
++              Method(_STA,0) {
++                      if (LGreater(P0IS,0)) {
++                              return (0x0F) /* sata is visible */
++                      } else {
++                              return  (0x00) /* sata is missing */
++                      }
++              }
++      }/* end of PMST */
++
++      Device(PSLA)
++      {
++              Name(_ADR, 1)
++              Method(_STA,0) {
++                      if (LGreater(P1IS,0)) {
++                              return (0x0F) /* sata is visible */
++                      } else {
++                              return (0x00) /* sata is missing */
++                      }
++              }
++      }       /* end of PSLA */
++}   /* end of PMRY */
++
++
++Device(SEDY)
++{
++      Name(_ADR, 1)           /* IDE Scondary Channel */
++      Method(_GTM, 0x0, NotSerialized) {
++              Return(STTM)
++      }
++      Method(_STM, 0x3, NotSerialized) {}
++
++      Device(SMST)
++      {
++              Name(_ADR, 0)
++              Method(_STA,0) {
++                      if (LGreater(P2IS,0)) {
++                              return (0x0F) /* sata is visible */
++                      } else {
++                              return (0x00) /* sata is missing */
++                      }
++              }
++      } /* end of SMST */
++
++      Device(SSLA)
++      {
++              Name(_ADR, 1)
++              Method(_STA,0) {
++                      if (LGreater(P3IS,0)) {
++                              return (0x0F) /* sata is visible */
++                      } else {
++                              return (0x00) /* sata is missing */
++                      }
++              }
++      } /* end of SSLA */
++}   /* end of SEDY */
++
++/* SATA Hot Plug Support */
++Scope(\_GPE) {
++      Method(_L1F,0x0,NotSerialized) {
++              if (\_SB.P0PR) {
++                      if (LGreater(\_SB.P0IS,0)) {
++                              sleep(32)
++                      }
++                      Notify(\_SB.PCI0.SAT0.PMRY.PMST, 0x01) /* 
NOTIFY_DEVICE_CHECK */
++                      store(one, \_SB.P0PR)
++              }
++
++              if (\_SB.P1PR) {
++                      if (LGreater(\_SB.P1IS,0)) {
++                              sleep(32)
++                      }
++                      Notify(\_SB.PCI0.SAT0.PMRY.PSLA, 0x01) /* 
NOTIFY_DEVICE_CHECK */
++                      store(one, \_SB.P1PR)
++              }
++
++              if (\_SB.P2PR) {
++                      if (LGreater(\_SB.P2IS,0)) {
++                              sleep(32)
++                      }
++                      Notify(\_SB.PCI0.SAT0.SEDY.SMST, 0x01) /* 
NOTIFY_DEVICE_CHECK */
++                      store(one, \_SB.P2PR)
++              }
++
++              if (\_SB.P3PR) {
++                      if (LGreater(\_SB.P3IS,0)) {
++                              sleep(32)
++                      }
++                      Notify(\_SB.PCI0.SAT0.SEDY.SSLA, 0x01) /* 
NOTIFY_DEVICE_CHECK */
++                      store(one, \_SB.P3PR)
++              }
++      }
++}
+diff --git a/src/southbridge/amd/sb700/bootblock.c 
b/src/southbridge/amd/sb700/bootblock.c
+index 67e6434..8f722a8 100644
+--- a/src/southbridge/amd/sb700/bootblock.c
++++ b/src/southbridge/amd/sb700/bootblock.c
+@@ -1,6 +1,7 @@
+ /*
+  * This file is part of the coreboot project.
+  *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -35,10 +36,17 @@
+ static void sb700_enable_rom(void)
+ {
+       u8 reg8;
++      u32 dword;
+       pci_devfn_t dev;
+ 
+       dev = PCI_DEV(0, 0x14, 3);
+ 
++      /* The LPC settings below work for SPI flash as well;
++       * the hardware does not distinguish between LPC and SPI flash ROM
++       * aside from offering additional side-channel access to SPI flash
++       * via a separate register-based interface.
++       */
++
+       /* Decode variable LPC ROM address ranges 1 and 2. */
+       reg8 = pci_io_read_config8(dev, 0x48);
+       reg8 |= (1 << 3) | (1 << 4);
+@@ -52,15 +60,41 @@ static void sb700_enable_rom(void)
+ 
+       /* LPC ROM address range 2: */
+       /*
+-       * Enable LPC ROM range start at:
+-       * 0xfff8(0000): 512KB
+-       * 0xfff0(0000): 1MB
+-       * 0xffe0(0000): 2MB
+-       * 0xffc0(0000): 4MB
+-       */
++      * Enable LPC ROM range start at:
++      * 0xfff8(0000): 512KB
++      * 0xfff0(0000): 1MB
++      * 0xffe0(0000): 2MB
++      * 0xffc0(0000): 4MB
++      * 0xff80(0000): 8MB
++      */
+       pci_io_write_config16(dev, 0x6c, 0x10000 - (CONFIG_COREBOOT_ROMSIZE_KB 
>> 6));
+       /* Enable LPC ROM range end at 0xffff(ffff). */
+       pci_io_write_config16(dev, 0x6e, 0xffff);
++
++      /* SB700 LPC Bridge 0x48h.
++       * Turn on all LPC IO Port decode enables
++       */
++      dword = pci_io_read_config32(dev, 0x44);
++      dword = 0xffffffff;
++      pci_io_write_config32(dev, 0x44, dword);
++
++      /* SB700 LPC Bridge 0x48h.
++       * BIT0: Port Enable for SuperIO 0x2E-0x2F
++       * BIT1: Port Enable for SuperIO 0x4E-0x4F
++       * BIT4: Port Enable for LPC ROM Address Arrage2 (0x68-0x6C)
++       * BIT6: Port Enable for RTC IO 0x70-0x73
++       * BIT21: Port Enable for Port 0x80
++       */
++      reg8 = pci_io_read_config8(dev, 0x48);
++      reg8 |= (1<<0) | (1<<1) | (1<<4) | (1<<6);
++      pci_io_write_config8(dev, 0x48, reg8);
++
++      /* SB700 LPC Bridge 0x4ah.
++       * BIT4: Port Enable for Port 0x80
++       */
++      reg8 = pci_io_read_config8(dev, 0x4a);
++      reg8 |= (1<<4);
++      pci_io_write_config8(dev, 0x4a, reg8);
+ }
+ 
+ static void bootblock_southbridge_init(void)
+diff --git a/src/southbridge/amd/sb700/early_setup.c 
b/src/southbridge/amd/sb700/early_setup.c
+index d25599e..de3fa97 100644
+--- a/src/southbridge/amd/sb700/early_setup.c
++++ b/src/southbridge/amd/sb700/early_setup.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -395,6 +396,15 @@ static void sb700_devices_por_init(void)
+       byte |= (1 << 0);
+       pci_write_config8(dev, 0xd2, byte);
+ 
++      /* set auxiliary smbus iobase and enable controller */
++      pci_write_config32(dev, 0x58, SMBUS_AUX_IO_BASE | 1);
++
++      if (inw(SMBUS_IO_BASE) == 0xFF)
++              printk(BIOS_INFO, "sb700_devices_por_init(): Primary SMBUS 
controller I/O not found\n");
++
++      if (inw(SMBUS_AUX_IO_BASE) == 0xFF)
++              printk(BIOS_INFO, "sb700_devices_por_init(): Secondary SMBUS 
controller I/O not found\n");
++
+       /* KB2RstEnable */
+       pci_write_config8(dev, 0x40, 0x44);
+ 
+@@ -439,6 +449,14 @@ static void sb700_devices_por_init(void)
+       /*pci_write_config8(dev, 0x79, 0x4F); */
+       pci_write_config8(dev, 0x78, 0xFF);
+ 
++      if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
++              printk(BIOS_DEBUG, "sb700_devices_por_init(): Disabling ISA DMA 
support\n");
++              /* Disable LPC ISA DMA Capability */
++              byte = pci_read_config8(dev, 0x78);
++              byte &= ~(1 << 0);
++              pci_write_config8(dev, 0x78, byte);
++      }
++
+       /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that 
is reserved */
+       pci_write_config16(dev, 0x4, 0x0407);
+ 
+diff --git a/src/southbridge/amd/sb700/lpc.c b/src/southbridge/amd/sb700/lpc.c
+index a39ec18..0cc1e8b 100644
+--- a/src/southbridge/amd/sb700/lpc.c
++++ b/src/southbridge/amd/sb700/lpc.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -45,6 +46,8 @@ static void lpc_init(device_t dev)
+       u32 dword;
+       device_t sm_dev;
+ 
++      printk(BIOS_SPEW, "%s\n", __func__);
++
+       /* Enable the LPC Controller */
+       sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
+       dword = pci_read_config32(sm_dev, 0x64);
+diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c
+index 598ebec..71253b5 100644
+--- a/src/southbridge/amd/sb700/sm.c
++++ b/src/southbridge/amd/sb700/sm.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -62,11 +63,8 @@ static void sm_init(device_t dev)
+       printk(BIOS_INFO, "sm_init().\n");
+ 
+       rev = get_sb700_revision(dev);
+-      ioapic_base = (void *)(pci_read_config32(dev, 0x74) & (0xffffffe0));    
/* some like mem resource, but does not have  enable bit */
+-      /* Don't rename APIC ID */
+-      /* TODO: We should call setup_ioapic() here. But kernel hangs if cpu is 
K8.
+-       * We need to check out why and change back. */
+-      clear_ioapic(ioapic_base);
++      ioapic_base = (void *)(pci_read_config32(dev, 0x74) & (0xffffffe0));    
/* some like mem resource, but does not have enable bit */
++      setup_ioapic(ioapic_base, 0); /* Don't rename IOAPIC ID. */
+ 
+       /* 2.10 Interrupt Routing/Filtering */
+       dword = pci_read_config8(dev, 0x62);
+@@ -132,9 +130,10 @@ static void sm_init(device_t dev)
+       get_option(&on, "power_on_after_fail");
+       byte = pm_ioread(0x74);
+       byte &= ~0x03;
+-      if (on) {
+-              byte |= 2;
+-      }
++      if (on == 1)
++              byte |= 0x1;    /* Force power on */
++      else if (on == 2)
++              byte |= 0x2;    /* Use last power state */
+       byte |= 1 << 2;
+       pm_iowrite(0x74, byte);
+       printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off");
+@@ -298,6 +297,10 @@ static void sm_init(device_t dev)
+       byte &= ~(1 << 1);
+       pm_iowrite(0x59, byte);
+ 
++      /* Enable SCI as irq9. */
++      outb(0x4, 0xC00);
++      outb(0x9, 0xC01);
++
+       printk(BIOS_INFO, "sm_init() end\n");
+ 
+       /* Enable NbSb virtual channel */
+@@ -388,7 +391,7 @@ static void sb700_sm_read_resources(device_t dev)
+       struct resource *res;
+ 
+       /* Get the normal pci resources of this device */
+-      /* pci_dev_read_resources(dev); */
++      pci_dev_read_resources(dev);
+ 
+       /* apic */
+       res = new_resource(dev, 0x74);
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0008-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
 
b/resources/libreboot/patch/kgpe-d16/0008-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
deleted file mode 100644
index 75367b6..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0008-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
+++ /dev/null
@@ -1,3463 +0,0 @@
-From 2f8bf745a7ffc2e031efa0f60f993b88baf5a714 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 17:55:58 -0500
-Subject: [PATCH 008/139] northbridge/amd/amdmct: Fix broken AMD K10 DDR3
- memory initalization
-
-Change-Id: Iab690db769e820600693ad1170085623b177b94e
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/northbridge/amd/amdfam10/raminit_amdmct.c   |   2 +
- src/northbridge/amd/amdmct/mct/mct_d.c          |   1 -
- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c     | 177 +++++-
- src/northbridge/amd/amdmct/mct_ddr3/mct_d.h     |   8 +-
- src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h |  87 +--
- src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c  |   6 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c  | 806 +++++++++++++-----------
- src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c    |   6 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c  |  14 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c  |   3 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctproc.c   |  19 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c    |   5 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c    | 800 ++++++++++++-----------
- src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c  |  18 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c  |  13 +-
- src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c   |   7 +-
- src/northbridge/amd/amdmct/mct_ddr3/mctwl.c     |  42 +-
- src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c   | 267 ++++----
- src/northbridge/amd/amdmct/wrappers/mcti_d.c    | 112 +---
- 19 files changed, 1253 insertions(+), 1140 deletions(-)
-
-diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c 
b/src/northbridge/amd/amdfam10/raminit_amdmct.c
-index a0d47f4..a585fae 100644
---- a/src/northbridge/amd/amdfam10/raminit_amdmct.c
-+++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c
-@@ -28,12 +28,14 @@ static  void print_tx(const char *strval, u32 val)
- }
- #endif
- 
-+#if (CONFIG_DIMM_SUPPORT & 0x000F)!=0x0005 /* not needed for AMD_FAM10_DDR3 */
- static  void print_t(const char *strval)
- {
- #if CONFIG_DEBUG_RAM_SETUP
-       printk(BIOS_DEBUG, "%s", strval);
- #endif
- }
-+#endif
- 
- static  void print_tf(const char *func, const char *strval)
- {
-diff --git a/src/northbridge/amd/amdmct/mct/mct_d.c 
b/src/northbridge/amd/amdmct/mct/mct_d.c
-index 3dec934..88910e2 100644
---- a/src/northbridge/amd/amdmct/mct/mct_d.c
-+++ b/src/northbridge/amd/amdmct/mct/mct_d.c
-@@ -542,7 +542,6 @@ static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
-               pDCTstat = pDCTstatA + Node;
-               devx = pDCTstat->dev_map;
-               DramSelBaseAddr = 0;
--              pDCTstat = pDCTstatA + Node;
-               if (!pDCTstat->GangedMode) {
-                       DramSelBaseAddr = pDCTstat->NodeSysLimit - 
pDCTstat->DCTSysLimit;
-                       /*In unganged mode, we must add DCT0 and DCT1 to 
DCTSysLimit */
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-index 71a6be8..fa59d71 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-@@ -214,6 +214,8 @@ static const u8 Table_DQSRcvEn_Offset[] = 
{0x00,0x01,0x10,0x11,0x2};
- static const u8 Tab_L1CLKDis[]  = {0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 
0x04};
- static const u8 Tab_AM3CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
0x00};
- static const u8 Tab_S1CLKDis[]  = {0xA2, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00};
-+static const u8 Tab_C32CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
0x00};   /* Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */
-+static const u8 Tab_G34CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
0x00};   /* Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */
- static const u8 Tab_ManualCLKDis[]= {0x10, 0x04, 0x08, 0x20, 0x00, 0x00, 
0x00, 0x00};
- 
- static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF};
-@@ -277,6 +279,11 @@ restartinit:
-       for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-               struct DCTStatStruc *pDCTstat;
-               pDCTstat = pDCTstatA + Node;
-+
-+              /* Zero out data structures to avoid false detection of DIMMs */
-+              memset(pDCTstat, 0, sizeof(struct DCTStatStruc));
-+
-+              /* Initialize data structures */
-               pDCTstat->Node_ID = Node;
-               pDCTstat->dev_host = PA_HOST(Node);
-               pDCTstat->dev_map = PA_MAP(Node);
-@@ -284,17 +291,22 @@ restartinit:
-               pDCTstat->dev_nbmisc = PA_NBMISC(Node);
-               pDCTstat->NodeSysBase = node_sys_base;
- 
-+              printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_init Node %d\n", 
Node);
-               mct_init(pMCTstat, pDCTstat);
-               mctNodeIDDebugPort_D();
-               pDCTstat->NodePresent = NodePresent_D(Node);
-               if (pDCTstat->NodePresent) {            /* See if Node is 
there*/
-+                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: 
clear_legacy_Mode\n");
-                       clear_legacy_Mode(pMCTstat, pDCTstat);
-                       pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);
- 
-+                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: 
mct_InitialMCT_D\n");
-                       mct_InitialMCT_D(pMCTstat, pDCTstat);
- 
-+                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: 
mctSMBhub_Init\n");
-                       mctSMBhub_Init(Node);           /* Switch SMBUS 
crossbar to proper node*/
- 
-+                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_initDCT\n");
-                       mct_initDCT(pMCTstat, pDCTstat);
-                       if (pDCTstat->ErrCode == SC_FatalErr) {
-                               goto fatalexit;         /* any fatal errors?*/
-@@ -345,6 +357,7 @@ restartinit:
- 
-       mct_FinalMCT_D(pMCTstat, pDCTstatA);
-       printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", 
pMCTstat->GStatus);
-+
-       return;
- 
- fatalexit:
-@@ -560,7 +573,6 @@ static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
-               pDCTstat = pDCTstatA + Node;
-               devx = pDCTstat->dev_map;
-               DramSelBaseAddr = 0;
--              pDCTstat = pDCTstatA + Node; /* ??? */
-               if (!pDCTstat->GangedMode) {
-                       DramSelBaseAddr = pDCTstat->NodeSysLimit - 
pDCTstat->DCTSysLimit;
-                       /*In unganged mode, we must add DCT0 and DCT1 to 
DCTSysLimit */
-@@ -645,6 +657,7 @@ static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
-               devx = pDCTstat->dev_map;
- 
-               if (pDCTstat->NodePresent) {
-+                      printk(BIOS_DEBUG, " Copy dram map from Node 0 to Node 
%02x \n", Node);
-                       reg = 0x40;             /*Dram Base 0*/
-                       do {
-                               val = Get_NB32(dev, reg);
-@@ -1162,7 +1175,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
- 
-       /* Program DRAM Timing values */
-       DramTimingLo = 0;       /* Dram Timing Low init */
--      val = pDCTstat->CASL - 2; /* pDCTstat.CASL to reg. definition */
-+      val = pDCTstat->CASL - 4; /* pDCTstat.CASL to reg. definition */
-       DramTimingLo |= val;
- 
-       val = pDCTstat->Trcd - Bias_TrcdT;
-@@ -1406,18 +1419,16 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
-       else if (tCKproposed16x <= 24) {
-               pDCTstat->TargetFreq = 6;
-               tCKproposed16x = 24;
--      }
--      else if (tCKproposed16x <= 30) {
-+      } else if (tCKproposed16x <= 30) {
-               pDCTstat->TargetFreq = 5;
-               tCKproposed16x = 30;
--      }
--      else {
-+      } else {
-               pDCTstat->TargetFreq = 4;
-               tCKproposed16x = 40;
-       }
-       /* Running through this loop twice:
-          - First time find tCL at target frequency
--         - Second tim find tCL at 400MHz */
-+         - Second time find tCL at 400MHz */
- 
-       for (;;) {
-               CLT_Fail = 0;
-@@ -1451,7 +1462,7 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
-                       CLT_Fail = 1;
-               /* get CL and T */
-               if (!CLT_Fail) {
--                      bytex = CLactual - 2;
-+                      bytex = CLactual;
-                       if (tCKproposed16x == 20)
-                               byte = 7;
-                       else if (tCKproposed16x == 24)
-@@ -1632,7 +1643,7 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
-               val = 0x0f; /* recommended setting (default) */
-       DramConfigHi |= val << 24;
- 
--      if (pDCTstat->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Bx))
-+      if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx | AMD_DR_Bx))
-               DramConfigHi |= 1 << DcqArbBypassEn;
- 
-       /* Build MemClkDis Value from Dram Timing Lo and
-@@ -1657,6 +1668,10 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
-                               p = Tab_L1CLKDis;
-                       else if (byte == PT_M2 || byte == PT_AS)
-                               p = Tab_AM3CLKDis;
-+                      else if (byte == PT_C3)
-+                              p = Tab_C32CLKDis;
-+                      else if (byte == PT_GR)
-+                              p = Tab_G34CLKDis;
-                       else
-                               p = Tab_S1CLKDis;
- 
-@@ -2102,8 +2117,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
-                               if (byte == JED_RDIMM || byte == JED_MiniRDIMM) 
{
-                                       RegDIMMPresent |= 1 << i;
-                                       pDCTstat->DimmRegistered[i] = 1;
--                              }
--                              else {
-+                              } else {
-                                       pDCTstat->DimmRegistered[i] = 0;
-                               }
-                               /* Check ECC capable */
-@@ -2977,9 +2991,9 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
-               } else {        /* For Dx CPU */
-                       val = 0x0CE00F00 | 1 << 29/* FlushWrOnStpGnt */;
-                       if (!(pDCTstat->GangedMode))
--                              val |= 0x20; /* MctWrLimit =  8 for Unganed 
mode */
-+                              val |= 0x20; /* MctWrLimit =  8 for Unganged 
mode */
-                       else
--                              val |= 0x40; /* MctWrLimit =  16 for ganed mode 
*/
-+                              val |= 0x40; /* MctWrLimit =  16 for ganged 
mode */
-                       Set_NB32(pDCTstat->dev_dct, 0x11C, val);
- 
-                       val = Get_NB32(pDCTstat->dev_dct, 0x1B0);
-@@ -3414,6 +3428,138 @@ static void mct_BeforeDramInit_Prod_D(struct 
MCTStatStruc *pMCTstat,
-                       Set_NB32(dev,  0x98 + reg_off, 0x0D000030);
-                       Set_NB32(dev,  0x9C + reg_off, dword);
-                       Set_NB32(dev,  0x98 + reg_off, 0x4D040F30);
-+
-+                      /* FIXME
-+                       * Mainboards need to be able to specify the maximum 
number of DIMMs installable per channel
-+                       * For now assume a maximum of 2 DIMMs per channel can 
be installed
-+                       */
-+                      uint8_t MaxDimmsInstallable = 2;
-+
-+                      /* Obtain number of DIMMs on channel */
-+                      uint8_t dimm_count = pDCTstat->MAdimms[i];
-+                      uint8_t rank_count_dimm0;
-+                      uint8_t rank_count_dimm1;
-+                      uint32_t odt_pattern_0;
-+                      uint32_t odt_pattern_1;
-+                      uint32_t odt_pattern_2;
-+                      uint32_t odt_pattern_3;
-+
-+                      /* Select appropriate ODT pattern for installed DIMMs
-+                       * Refer to the BKDG Rev. 3.62, page 120 onwards
-+                       */
-+                      if 
(pDCTstat->C_DCTPtr[i]->Status[DCT_STATUS_REGISTERED]) {
-+                              if (MaxDimmsInstallable == 2) {
-+                                      if (dimm_count == 1) {
-+                                              /* 1 DIMM detected */
-+                                              rank_count_dimm1 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[1];
-+                                              if (rank_count_dimm1 == 1) {
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x00020000;
-+                                              } else if (rank_count_dimm1 == 
2) {
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x02080000;
-+                                              } else if (rank_count_dimm1 == 
4) {
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x020a0000;
-+                                                      odt_pattern_3 = 
0x080a0000;
-+                                              } else {
-+                                                      /* Fallback */
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x00000000;
-+                                              }
-+                                      } else {
-+                                              /* 2 DIMMs detected */
-+                                              rank_count_dimm0 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[0];
-+                                              rank_count_dimm1 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[1];
-+                                              if ((rank_count_dimm0 < 4) && 
(rank_count_dimm1 < 4)) {
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x01010202;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x09030603;
-+                                              } else if ((rank_count_dimm0 < 
4) && (rank_count_dimm1 == 4)) {
-+                                                      odt_pattern_0 = 
0x01010000;
-+                                                      odt_pattern_1 = 
0x01010a0a;
-+                                                      odt_pattern_2 = 
0x01090000;
-+                                                      odt_pattern_3 = 
0x01030e0b;
-+                                              } else if ((rank_count_dimm0 == 
4) && (rank_count_dimm1 < 4)) {
-+                                                      odt_pattern_0 = 
0x00000202;
-+                                                      odt_pattern_1 = 
0x05050202;
-+                                                      odt_pattern_2 = 
0x00000206;
-+                                                      odt_pattern_3 = 
0x0d070203;
-+                                              } else if ((rank_count_dimm0 == 
4) && (rank_count_dimm1 == 4)) {
-+                                                      odt_pattern_0 = 
0x05050a0a;
-+                                                      odt_pattern_1 = 
0x05050a0a;
-+                                                      odt_pattern_2 = 
0x050d0a0e;
-+                                                      odt_pattern_3 = 
0x05070a0b;
-+                                              } else {
-+                                                      /* Fallback */
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x00000000;
-+                                              }
-+                                      }
-+                              } else {
-+                                      /* FIXME
-+                                       * 3 DIMMs per channel UNIMPLEMENTED
-+                                       */
-+                                      odt_pattern_0 = 0x00000000;
-+                                      odt_pattern_1 = 0x00000000;
-+                                      odt_pattern_2 = 0x00000000;
-+                                      odt_pattern_3 = 0x00000000;
-+                              }
-+                      } else {
-+                              if (MaxDimmsInstallable == 2) {
-+                                      if (dimm_count == 1) {
-+                                              /* 1 DIMM detected */
-+                                              rank_count_dimm1 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[1];
-+                                              if (rank_count_dimm1 == 1) {
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x00020000;
-+                                              } else if (rank_count_dimm1 == 
2) {
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x02080000;
-+                                              } else {
-+                                                      /* Fallback */
-+                                                      odt_pattern_0 = 
0x00000000;
-+                                                      odt_pattern_1 = 
0x00000000;
-+                                                      odt_pattern_2 = 
0x00000000;
-+                                                      odt_pattern_3 = 
0x00000000;
-+                                              }
-+                                      } else {
-+                                              /* 2 DIMMs detected */
-+                                              odt_pattern_0 = 0x00000000;
-+                                              odt_pattern_1 = 0x01010202;
-+                                              odt_pattern_2 = 0x00000000;
-+                                              odt_pattern_3 = 0x09030603;
-+                                      }
-+                              } else {
-+                                      /* FIXME
-+                                       * 3 DIMMs per channel UNIMPLEMENTED
-+                                       */
-+                                      odt_pattern_0 = 0x00000000;
-+                                      odt_pattern_1 = 0x00000000;
-+                                      odt_pattern_2 = 0x00000000;
-+                                      odt_pattern_3 = 0x00000000;
-+                              }
-+                      }
-+
-+                      /* Program ODT pattern */
-+                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x180, 
odt_pattern_1);
-+                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x181, 
odt_pattern_0);
-+                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x182, 
odt_pattern_3);
-+                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x183, 
odt_pattern_2);
-               }
-       }
- }
-@@ -3657,6 +3803,7 @@ static void mct_BeforeDQSTrain_D(struct MCTStatStruc 
*pMCTstat,
-       }
- }
- 
-+/* Erratum 350 */
- static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
-                                       struct DCTStatStruc *pDCTstat, u8 dct)
- {
-@@ -3692,11 +3839,11 @@ static void mct_ResetDLL_D(struct MCTStatStruc 
*pMCTstat,
-                               mct_Read1LTestPattern_D(pMCTstat, pDCTstat, 
addr);      /* cache fills */
- 
-                               /* Write 0000_8000h to register 
F2x[1,0]9C_xD080F0C */
--                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0x4D080F0C, 0x00008000);
-+                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0xD080F0C, 0x00008000);
-                               mct_Wait(80); /* wait >= 300ns */
- 
-                               /* Write 0000_0000h to register 
F2x[1,0]9C_xD080F0C */
--                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0x4D080F0C, 0x00000000);
-+                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0xD080F0C, 0x00000000);
-                               mct_Wait(800); /* wait >= 2us */
-                               break;
-                       }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h 
b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-index e2d7aa8..219aa42 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-@@ -499,7 +499,7 @@ struct DCTStatStruc {              /* A per Node 
structure*/
-               /* CHB DIMM0 Byte 0 - 7  TxDqs */
-               /* CHB DIMM1 Byte 0 - 7  TxDqs */
-               /* CHB DIMM1 Byte 0 - 7  TxDqs */
--      u8 CH_D_B_RCVRDLY[2][4][8];     /* [A/B] [DIMM0-3] [DQS] */
-+      u16 CH_D_B_RCVRDLY[2][4][8];    /* [A/B] [DIMM0-3] [DQS] */
-               /* CHA DIMM 0 Receiver Enable Delay*/
-               /* CHA DIMM 1 Receiver Enable Delay*/
-               /* CHA DIMM 2 Receiver Enable Delay*/
-@@ -509,7 +509,7 @@ struct DCTStatStruc {              /* A per Node 
structure*/
-               /* CHB DIMM 1 Receiver Enable Delay*/
-               /* CHB DIMM 2 Receiver Enable Delay*/
-               /* CHB DIMM 3 Receiver Enable Delay*/
--      u8 CH_D_BC_RCVRDLY[2][4];
-+      u16 CH_D_BC_RCVRDLY[2][4];
-               /* CHA DIMM 0 - 4 Check Byte Receiver Enable Delay*/
-               /* CHB DIMM 0 - 4 Check Byte Receiver Enable Delay*/
-       u8 DIMMValidDCT[2];     /* DIMM# in DCT0*/
-@@ -769,7 +769,7 @@ u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass);
- u32 SetupDqsPattern_1PassA(u8 Pass);
- u32 SetupDqsPattern_1PassB(u8 Pass);
- u8 mct_Get_Start_RcvrEnDly_1Pass(u8 Pass);
--u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 
RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass);
-+u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, 
u16 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass);
- void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
- void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
- u32 mctGetLogicalCPUID(u32 Node);
-@@ -779,7 +779,7 @@ void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, 
struct DCTStatStruc *pDCTs
- void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
- void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
- void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,struct DCTStatStruc 
*pDCTstatA);
--void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 
FinalValue, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 
Pass);
-+void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u8 
FinalValue, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 
Pass);
- void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel);
- void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u32 dct);
- void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u8 dct);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h 
b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
-index 60f98bc..c40ea1a 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -103,10 +104,10 @@ static void proc_CLFLUSH(u32 addr_hi)
- 
-       __asm__ volatile (
-               /* clflush fs:[eax] */
--              "outb %%al, $0xed\n\t"  /* _EXECFENCE */
--               "clflush %%fs:(%0)\n\t"
-+              "outb %%al, $0xed\n\t"  /* _EXECFENCE */
-+              "clflush %%fs:(%0)\n\t"
-               "mfence\n\t"
--               ::"a" (addr_hi<<8)
-+              ::"a" (addr_hi<<8)
-       );
- }
- 
-@@ -141,6 +142,24 @@ static u32 read32_fs(u32 addr_lo)
-       return value;
- }
- 
-+static uint64_t read64_fs(uint32_t addr_lo)
-+{
-+      uint64_t value = 0;
-+      uint32_t value_lo;
-+      uint32_t value_hi;
-+
-+      __asm__ volatile (
-+              "outb %%al, $0xed\n\t"  /* _EXECFENCE */
-+              "mfence\n\t"
-+              "movl %%fs:(%2), %0\n\t"
-+              "movl %%fs:(%3), %1\n\t"
-+              :"=c"(value_lo), "=d"(value_hi): "a" (addr_lo), "b" (addr_lo + 
4) : "memory"
-+      );
-+      value |= value_lo;
-+      value |= ((uint64_t)value_hi) << 32;
-+      return value;
-+}
-+
- #ifdef UNUSED_CODE
- static u8 read8_fs(u32 addr_lo)
- {
-@@ -210,68 +229,6 @@ static __attribute__((noinline)) void 
FlushDQSTestPattern_L18(u32 addr_lo)
-       );
- }
- 
--static void ReadL18TestPattern(u32 addr_lo)
--{
--      /* set fs and use fs prefix to access the mem */
--      __asm__ volatile (
--              "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
--              "movl %%fs:-128(%%esi), %%eax\n\t"      /* TestAddr cache line 
*/
--              "movl %%fs:-64(%%esi), %%eax\n\t"       /* +1 */
--              "movl %%fs:(%%esi), %%eax\n\t"          /* +2 */
--              "movl %%fs:64(%%esi), %%eax\n\t"        /* +3 */
--
--              "movl %%fs:-128(%%edi), %%eax\n\t"      /* +4 */
--              "movl %%fs:-64(%%edi), %%eax\n\t"       /* +5 */
--              "movl %%fs:(%%edi), %%eax\n\t"          /* +6 */
--              "movl %%fs:64(%%edi), %%eax\n\t"        /* +7 */
--
--              "movl %%fs:-128(%%ebx), %%eax\n\t"      /* +8 */
--              "movl %%fs:-64(%%ebx), %%eax\n\t"       /* +9 */
--              "movl %%fs:(%%ebx), %%eax\n\t"          /* +10 */
--              "movl %%fs:64(%%ebx), %%eax\n\t"        /* +11 */
--
--              "movl %%fs:-128(%%ecx), %%eax\n\t"      /* +12 */
--              "movl %%fs:-64(%%ecx), %%eax\n\t"       /* +13 */
--              "movl %%fs:(%%ecx), %%eax\n\t"          /* +14 */
--              "movl %%fs:64(%%ecx), %%eax\n\t"        /* +15 */
--
--              "movl %%fs:-128(%%edx), %%eax\n\t"      /* +16 */
--              "movl %%fs:-64(%%edx), %%eax\n\t"       /* +17 */
--              "mfence\n\t"
--
--               :: "a"(0), "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
--                  "d" (addr_lo +128+16*64), "S"(addr_lo+128),
--                  "D"(addr_lo+128+4*64)
--      );
--
--}
--
--static void ReadL9TestPattern(u32 addr_lo)
--{
--
--      /* set fs and use fs prefix to access the mem */
--      __asm__ volatile (
--              "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
--
--              "movl %%fs:-128(%%ecx), %%eax\n\t"      /* TestAddr cache line 
*/
--              "movl %%fs:-64(%%ecx), %%eax\n\t"       /* +1 */
--              "movl %%fs:(%%ecx), %%eax\n\t"          /* +2 */
--              "movl %%fs:64(%%ecx), %%eax\n\t"        /* +3 */
--
--              "movl %%fs:-128(%%edx), %%eax\n\t"      /* +4 */
--              "movl %%fs:-64(%%edx), %%eax\n\t"       /* +5 */
--              "movl %%fs:(%%edx), %%eax\n\t"          /* +6 */
--              "movl %%fs:64(%%edx), %%eax\n\t"        /* +7 */
--
--              "movl %%fs:-128(%%ebx), %%eax\n\t"      /* +8 */
--              "mfence\n\t"
--
--               :: "a"(0), "b" (addr_lo+128+8*64), "c"(addr_lo+128),
--                  "d"(addr_lo+128+4*64)
--      );
--
--}
--
- static void ReadMaxRdLat1CLTestPattern_D(u32 addr)
- {
-       SetUpperFSbase(addr);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c
-index ae1654c..99a2628 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -17,7 +18,7 @@
-  * Foundation, Inc.
-  */
- 
--/* The socket type F (1207), Fr2, G (1207) are not tested.
-+/* The socket type Fr2, G (1207) are not tested.
-  */
- 
- static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
-@@ -79,8 +80,7 @@ static void Get_ChannelPS_Cfg0_D( u8 MAAdimms, u8 Speed, u8 
MAAload,
-                       else
-                               *AddrTmgCTL = 0x00353935;
-               }
--      }
--      else {
-+      } else {
-               if(Speed == 4) {
-                       *AddrTmgCTL = 0x00000000;
-                       if (MAAdimms == 3)
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
-index 404727b..cc2f43a 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -22,13 +23,6 @@ static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat,
-                               u8 scale, u8 ChipSel);
- static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 ChipSel);
--static u8 MiddleDQS_D(u8 min, u8 max);
--static void TrainReadDQS_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u8 cs_start);
--static void TrainWriteDQS_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u8 cs_start);
- static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat,
-                                       struct DCTStatStruc *pDCTstat,
-                                       u32 TestAddr_lo);
-@@ -43,31 +37,19 @@ static void FlushDQSTestPattern_D(struct DCTStatStruc 
*pDCTstat,
-                                       u32 addr_lo);
- static void SetTargetWTIO_D(u32 TestAddr);
- static void ResetTargetWTIO_D(void);
--static void ReadDQSTestPattern_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat,
--                                      u32 TestAddr_lo);
--static void mctEngDQSwindow_Save_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
--                                      u8 RnkDlyFilterMin, u8 RnkDlyFilterMax);
- void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index);
- u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat);
- static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat,
-                                       struct DCTStatStruc *pDCTstat,
-                                       u8 ChipSel);
--static void mct_SetDQSDelayAllCSR_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat,
--                                      u8 cs_start);
- u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 Channel,
-                               u8 receiver, u8 *valid);
- static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat,
-                               u32 *buffer);
--
--static void StoreWrRdDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
--                                    u8 RnkDlyFilterMin, u8 RnkDlyFilterMax);
-+static void proc_IOCLFLUSH_D(u32 addr_hi);
- 
- static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat, u8 ChipSel);
- 
-@@ -286,20 +268,99 @@ static void CalcEccDQSPos_D(struct MCTStatStruc 
*pMCTstat,
-       pDCTstat->DQSDelay = (u8)DQSDelay;
- }
- 
-+static void write_dqs_write_data_timing_registers(uint16_t* delay, uint32_t 
dev, uint8_t dimm, uint32_t index_reg)
-+{
-+      uint32_t dword;
-+
-+      /* Lanes 0 - 3 */
-+      dword = Get_NB32_index_wait(dev, index_reg, 0x1 | (dimm << 8));
-+      dword &= ~0x7f7f7f7f;
-+      dword |= (delay[3] & 0x7f) << 24;
-+      dword |= (delay[2] & 0x7f) << 16;
-+      dword |= (delay[1] & 0x7f) << 8;
-+      dword |= delay[0] & 0x7f;
-+      Set_NB32_index_wait(dev, index_reg, 0x1 | (dimm << 8), dword);
-+
-+      /* Lanes 4 - 7 */
-+      dword = Get_NB32_index_wait(dev, index_reg, 0x2 | (dimm << 8));
-+      dword &= ~0x7f7f7f7f;
-+      dword |= (delay[7] & 0x7f) << 24;
-+      dword |= (delay[6] & 0x7f) << 16;
-+      dword |= (delay[5] & 0x7f) << 8;
-+      dword |= delay[4] & 0x7f;
-+      Set_NB32_index_wait(dev, index_reg, 0x2 | (dimm << 8), dword);
-+
-+      /* Lane 8 (ECC) */
-+      dword = Get_NB32_index_wait(dev, index_reg, 0x3 | (dimm << 8));
-+      dword &= ~0x0000007f;
-+      dword |= delay[8] & 0x7f;
-+      Set_NB32_index_wait(dev, index_reg, 0x3 | (dimm << 8), dword);
-+}
-+
-+static void write_dqs_read_data_timing_registers(uint16_t* delay, uint32_t 
dev, uint8_t dimm, uint32_t index_reg)
-+{
-+      uint32_t dword;
-+
-+      /* Lanes 0 - 3 */
-+      dword = Get_NB32_index_wait(dev, index_reg, 0x5 | (dimm << 8));
-+      dword &= ~0x3f3f3f3f;
-+      dword |= (delay[3] & 0x3f) << 24;
-+      dword |= (delay[2] & 0x3f) << 16;
-+      dword |= (delay[1] & 0x3f) << 8;
-+      dword |= delay[0] & 0x3f;
-+      Set_NB32_index_wait(dev, index_reg, 0x5 | (dimm << 8), dword);
-+
-+      /* Lanes 4 - 7 */
-+      dword = Get_NB32_index_wait(dev, index_reg, 0x6 | (dimm << 8));
-+      dword &= ~0x3f3f3f3f;
-+      dword |= (delay[7] & 0x3f) << 24;
-+      dword |= (delay[6] & 0x3f) << 16;
-+      dword |= (delay[5] & 0x3f) << 8;
-+      dword |= delay[4] & 0x3f;
-+      Set_NB32_index_wait(dev, index_reg, 0x6 | (dimm << 8), dword);
-+
-+      /* Lane 8 (ECC) */
-+      dword = Get_NB32_index_wait(dev, index_reg, 0x7 | (dimm << 8));
-+      dword &= ~0x0000003f;
-+      dword |= delay[8] & 0x3f;
-+      Set_NB32_index_wait(dev, index_reg, 0x7 | (dimm << 8), dword);
-+}
-+
-+/* DQS Position Training
-+ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.3
-+ */
- static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u8 cs_start)
-+                              struct DCTStatStruc *pDCTstat)
- {
-       u32 Errors;
--      u8 Channel, DQSWrDelay;
-+      u8 Channel;
-+      u8 Receiver;
-       u8 _DisableDramECC = 0;
--      u32 PatternBuffer[292];
-+      u32 PatternBuffer[304]; /* 288 + 16 */
-       u8 _Wrap32Dis = 0, _SSE2 = 0;
--      u8 dqsWrDelay_end;
- 
-+      u32 dev;
-       u32 addr;
-+      u8 valid;
-       u32 cr4;
-       u32 lo, hi;
-+      u32 index_reg;
-+      uint32_t TestAddr;
-+
-+      uint8_t dual_rank;
-+      uint8_t iter;
-+      uint8_t lane;
-+      uint16_t bytelane_test_results;
-+      uint16_t current_write_dqs_delay[MAX_BYTE_LANES];
-+      uint16_t current_read_dqs_delay[MAX_BYTE_LANES];
-+      uint16_t write_dqs_delay_stepping_done[MAX_BYTE_LANES];
-+      uint8_t dqs_read_results_array[2][MAX_BYTE_LANES][64];          /* 
[rank][lane][step] */
-+      uint8_t dqs_write_results_array[2][MAX_BYTE_LANES][128];        /* 
[rank][lane][step] */
-+
-+      uint8_t last_pos = 0;
-+      uint8_t cur_count = 0;
-+      uint8_t best_pos = 0;
-+      uint8_t best_count = 0;
- 
-       print_debug_dqs("\nTrainDQSRdWrPos: Node_ID ", pDCTstat->Node_ID, 0);
-       cr4 = read_cr4();
-@@ -323,50 +384,363 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc 
*pMCTstat,
-       SetupDqsPattern_D(pMCTstat, pDCTstat, PatternBuffer);
- 
-       /* mct_BeforeTrainDQSRdWrPos_D */
--      dqsWrDelay_end = 0x20;
-+
-+      dev = pDCTstat->dev_dct;
-+      pDCTstat->Direction = DQS_READDIR;
-+
-+      /* 2.8.9.9.3 (2)
-+       * Loop over each channel, lane, and rank
-+       */
-+
-+      /* NOTE
-+       * The BKDG originally stated to iterate over lane, then rank, however 
this process is quite slow
-+       * compared to an equivalent loop over rank, then lane as the latter 
allows multiple lanes to be
-+       * tested simultaneously, thus improving performance by around 8x.
-+       */
- 
-       Errors = 0;
-       for (Channel = 0; Channel < 2; Channel++) {
--              print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ",Channel, 1);
-+              print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ", Channel, 1);
-               pDCTstat->Channel = Channel;
- 
-               if (pDCTstat->DIMMValidDCT[Channel] == 0)       /* 
mct_BeforeTrainDQSRdWrPos_D */
-                       continue;
--              pDCTstat->DqsRdWrPos_Saved = 0;
--              for ( DQSWrDelay = 0; DQSWrDelay < dqsWrDelay_end; 
DQSWrDelay++) {
--                      pDCTstat->DQSDelay = DQSWrDelay;
--                      pDCTstat->Direction = DQS_WRITEDIR;
--                      mct_SetDQSDelayAllCSR_D(pMCTstat, pDCTstat, cs_start);
--
--                      print_debug_dqs("\t\tTrainDQSRdWrPos: 21 DQSWrDelay ", 
DQSWrDelay, 2);
--                      TrainReadDQS_D(pMCTstat, pDCTstat, cs_start);
--                      print_debug_dqs("\t\tTrainDQSRdWrPos: 21 
DqsRdWrPos_Saved ", pDCTstat->DqsRdWrPos_Saved, 2);
--                      if (pDCTstat->DqsRdWrPos_Saved == 0xFF)
--                              break;
--
--                      print_debug_dqs("\t\tTrainDQSRdWrPos: 22 TrainErrors 
",pDCTstat->TrainErrors, 2);
--                      if (pDCTstat->TrainErrors == 0) {
-+
-+              index_reg = 0x98 + 0x100 * Channel;
-+
-+              dual_rank = 0;
-+              Receiver = mct_InitReceiver_D(pDCTstat, Channel);
-+              /* There are four receiver pairs, loosely associated with 
chipselects.
-+              * This is essentially looping over each rank of each DIMM.
-+              */
-+              for (; Receiver < 8; Receiver++) {
-+                      if ((Receiver & 0x1) == 0) {
-+                              /* Even rank of DIMM */
-+                              if(mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, 
Channel, Receiver+1))
-+                                      dual_rank = 1;
-+                              else
-+                                      dual_rank = 0;
-+                      }
-+
-+                      if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, 
Receiver)) {
-+                              continue;
-+                      }
-+
-+                      /* Select the base test address for the current rank */
-+                      TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, 
Channel, Receiver, &valid);
-+                      if (!valid) {   /* Address not supported on current CS 
*/
-+                              continue;
-+                      }
-+
-+                      print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 14 TestAddr 
", TestAddr, 4);
-+                      SetUpperFSbase(TestAddr);       /* fs:eax=far ptr to 
target */
-+
-+                      print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 12 Receiver 
", Receiver, 2);
-+
-+                      /* 2.8.9.9.3 (DRAM Write Data Timing Loop)
-+                       * Iterate over all possible DQS delay values (0x0 - 
0x7f)
-+                       */
-+                      uint8_t test_write_dqs_delay = 0;
-+                      uint8_t test_read_dqs_delay = 0;
-+                      uint8_t passing_dqs_delay_found[MAX_BYTE_LANES];
-+
-+                      /* Initialize variables */
-+                      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+                              current_write_dqs_delay[lane] = 0;
-+                              passing_dqs_delay_found[lane] = 0;
-+                              write_dqs_delay_stepping_done[lane] = 0;
-+                      }
-+
-+                      for (test_write_dqs_delay = 0; test_write_dqs_delay < 
128; test_write_dqs_delay++) {
-+                              print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 16 
test_write_dqs_delay ", test_write_dqs_delay, 6);
-+
-+                              /* Break out of loop if passing window already 
found, */
-+                              if (write_dqs_delay_stepping_done[0] && 
write_dqs_delay_stepping_done[1]
-+                                      && write_dqs_delay_stepping_done[2] && 
write_dqs_delay_stepping_done[3]
-+                                      && write_dqs_delay_stepping_done[4] && 
write_dqs_delay_stepping_done[5]
-+                                      && write_dqs_delay_stepping_done[6] && 
write_dqs_delay_stepping_done[7])
-                                       break;
-+
-+                              /* Commit the current Write Data Timing 
settings to the hardware registers */
-+                              
write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver 
>> 1), index_reg);
-+
-+                              /* Write the DRAM training pattern to the base 
test address */
-+                              WriteDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8);
-+
-+                              /* 2.8.9.9.3 (DRAM Read DQS Timing Control Loop)
-+                               * Iterate over all possible DQS delay values 
(0x0 - 0x3f)
-+                               */
-+                              for (test_read_dqs_delay = 0; 
test_read_dqs_delay < 64; test_read_dqs_delay++) {
-+                                      
print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 test_read_dqs_delay ", 
test_read_dqs_delay, 6);
-+
-+                                      /* Initialize Read DQS Timing Control 
settings for this iteration */
-+                                      for (lane = 0; lane < MAX_BYTE_LANES; 
lane++)
-+                                              if 
(!write_dqs_delay_stepping_done[lane])
-+                                                      
current_read_dqs_delay[lane] = test_read_dqs_delay;
-+
-+                                      /* Commit the current Read DQS Timing 
Control settings to the hardware registers */
-+                                      
write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 
1), index_reg);
-+
-+                                      /* Initialize test result variable */
-+                                      bytelane_test_results = 0xff;
-+
-+                                      /* Read the DRAM training pattern from 
the base test address three times
-+                                       * NOTE
-+                                       * While the BKDG states to read three 
times this is probably excessive!
-+                                       * Decrease training time by only 
reading the test pattern once per iteration
-+                                       */
-+                                      for (iter = 0; iter < 1; iter++) {
-+                                              /* Flush caches */
-+                                              SetTargetWTIO_D(TestAddr);
-+                                              FlushDQSTestPattern_D(pDCTstat, 
TestAddr << 8);
-+                                              ResetTargetWTIO_D();
-+
-+                                              /* Read and compare pattern */
-+                                              bytelane_test_results &= 
(CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 
:: Lane 0] 0=fail, 1=pass */
-+
-+                                              /* If all lanes have already 
failed testing bypass remaining re-read attempt(s) */
-+                                              if (bytelane_test_results == 
0x0)
-+                                                      break;
-+                                      }
-+
-+                                      /* Store any lanes that passed testing 
for later use */
-+                                      for (lane = 0; lane < 8; lane++)
-+                                              if 
(!write_dqs_delay_stepping_done[lane])
-+                                                      
dqs_read_results_array[Receiver & 0x1][lane][test_read_dqs_delay] = 
(!!(bytelane_test_results & (1 << lane)));
-+
-+                                      
print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 162 bytelane_test_results ", 
bytelane_test_results, 6);
-+                              }
-+
-+                              for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+                                      if (write_dqs_delay_stepping_done[lane])
-+                                              continue;
-+
-+                                      /* Determine location and length of 
longest consecutive string of passing values
-+                                       * Output is stored in best_pos and 
best_count
-+                                       */
-+                                      last_pos = 0;
-+                                      cur_count = 0;
-+                                      best_pos = 0;
-+                                      best_count = 0;
-+                                      for (iter = 0; iter < 64; iter++) {
-+                                              if 
((dqs_read_results_array[Receiver & 0x1][lane][iter]) && (iter < 63)) {
-+                                                      /* Pass */
-+                                                      cur_count++;
-+                                              } else {
-+                                                      /* Failure or end of 
loop */
-+                                                      if (cur_count > 
best_count) {
-+                                                              best_count = 
cur_count;
-+                                                              best_pos = 
last_pos;
-+                                                      }
-+                                                      cur_count = 0;
-+                                                      last_pos = iter;
-+                                              }
-+                                      }
-+
-+                                      if (best_count > 2) {
-+                                              /* Exit the DRAM Write Data 
Timing Loop after programming the Read DQS Timing Control
-+                                               * register with the center of 
the passing window
-+                                               */
-+                                              current_read_dqs_delay[lane] = 
(best_pos + (best_count / 2));
-+                                              passing_dqs_delay_found[lane] = 
1;
-+
-+                                              /* Commit the current Read DQS 
Timing Control settings to the hardware registers */
-+                                              
write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 
1), index_reg);
-+
-+                                              /* Exit the DRAM Write Data 
Timing Loop */
-+                                              
write_dqs_delay_stepping_done[lane] = 1;
-+
-+                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest passing region ", 
best_count, 4);
-+                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest passing region start ", 
best_pos, 4);
-+                                      }
-+
-+                                      /* Increment the DQS Write Delay value 
if needed for the next DRAM Write Data Timing Loop iteration */
-+                                      if 
(!write_dqs_delay_stepping_done[lane])
-+                                              current_write_dqs_delay[lane]++;
-+                              }
-                       }
--                      Errors |= pDCTstat->TrainErrors;
--              }
- 
--              pDCTstat->DqsRdWrPos_Saved = 0;
--              if (DQSWrDelay < dqsWrDelay_end) {
--                      Errors = 0;
-+                      /* Flag failure(s) if present */
-+                      for (lane = 0; lane < 8; lane++) {
-+                              if (!passing_dqs_delay_found[lane]) {
-+                                      
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 121 Unable to find passing region for 
lane ", lane, 2);
-+
-+                                      /* Flag absence of passing window */
-+                                      Errors |= 1 << SB_NODQSPOS;
-+                              }
-+                      }
-+
-+                      /* Iterate over all possible Write Data Timing values 
(0x0 - 0x7f)
-+                       * Note that the Read DQS Timing Control was calibrated 
/ centered in the prior nested loop
-+                       */
-+                      for (test_write_dqs_delay = 0; test_write_dqs_delay < 
128; test_write_dqs_delay++) {
-+                              /* Initialize Write Data Timing settings for 
this iteration */
-+                              for (lane = 0; lane < MAX_BYTE_LANES; lane++)
-+                                      current_write_dqs_delay[lane] = 
test_write_dqs_delay;
-+
-+                              /* Commit the current Write Data Timing 
settings to the hardware registers */
-+                              
write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver 
>> 1), index_reg);
-+
-+                              /* Write the DRAM training pattern to the base 
test address */
-+                              WriteDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8);
-+
-+                              /* Flush caches */
-+                              SetTargetWTIO_D(TestAddr);
-+                              FlushDQSTestPattern_D(pDCTstat, TestAddr << 8);
-+                              ResetTargetWTIO_D();
-+
-+                              /* Read and compare pattern from the base test 
address */
-+                              bytelane_test_results = 
(CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 
:: Lane 0] 0=fail, 1=pass */
-+
-+                              /* Store any lanes that passed testing for 
later use */
-+                              for (lane = 0; lane < 8; lane++)
-+                                      dqs_write_results_array[Receiver & 
0x1][lane][test_write_dqs_delay] = (!!(bytelane_test_results & (1 << lane)));
-+                      }
-+
-+                      for (lane = 0; lane < 8; lane++) {
-+                              if ((!dual_rank) || (dual_rank && (Receiver & 
0x1))) {
-+
-+#ifdef PRINT_PASS_FAIL_BITMAPS
-+                                      for (iter = 0; iter < 64; iter++) {
-+                                              if 
(dqs_read_results_array[0][lane][iter])
-+                                                      printk(BIOS_DEBUG, "+");
-+                                              else
-+                                                      printk(BIOS_DEBUG, ".");
-+                                      }
-+                                      printk(BIOS_DEBUG, "\n");
-+                                      for (iter = 0; iter < 64; iter++) {
-+                                              if 
(dqs_read_results_array[1][lane][iter])
-+                                                      printk(BIOS_DEBUG, "+");
-+                                              else
-+                                                      printk(BIOS_DEBUG, ".");
-+                                      }
-+                                      printk(BIOS_DEBUG, "\n\n");
-+                                      for (iter = 0; iter < 128; iter++) {
-+                                              if 
(dqs_write_results_array[0][lane][iter])
-+                                                      printk(BIOS_DEBUG, "+");
-+                                              else
-+                                                      printk(BIOS_DEBUG, ".");
-+                                      }
-+                                      printk(BIOS_DEBUG, "\n");
-+                                      for (iter = 0; iter < 128; iter++) {
-+                                              if 
(dqs_write_results_array[1][lane][iter])
-+                                                      printk(BIOS_DEBUG, "+");
-+                                              else
-+                                                      printk(BIOS_DEBUG, ".");
-+                                      }
-+                                      printk(BIOS_DEBUG, "\n\n");
-+#endif
-+
-+                                      /* Base rank of single-rank DIMM, or 
odd rank of dual-rank DIMM */
-+                                      if (dual_rank) {
-+                                              /* Intersect the passing 
windows of both ranks */
-+                                              for (iter = 0; iter < 64; 
iter++)
-+                                                      if 
(!dqs_read_results_array[1][lane][iter])
-+                                                              
dqs_read_results_array[0][lane][iter] = 0;
-+                                              for (iter = 0; iter < 128; 
iter++)
-+                                                      if 
(!dqs_write_results_array[1][lane][iter])
-+                                                              
dqs_write_results_array[0][lane][iter] = 0;
-+                                      }
-+
-+                                      /* Determine location and length of 
longest consecutive string of passing values for read DQS timing
-+                                       * Output is stored in best_pos and 
best_count
-+                                       */
-+                                      last_pos = 0;
-+                                      cur_count = 0;
-+                                      best_pos = 0;
-+                                      best_count = 0;
-+                                      for (iter = 0; iter < 64; iter++) {
-+                                              if 
((dqs_read_results_array[0][lane][iter]) && (iter < 63)) {
-+                                                      /* Pass */
-+                                                      cur_count++;
-+                                              } else {
-+                                                      /* Failure or end of 
loop */
-+                                                      if (cur_count > 
best_count) {
-+                                                              best_count = 
cur_count;
-+                                                              best_pos = 
last_pos;
-+                                                      }
-+                                                      cur_count = 0;
-+                                                      last_pos = iter;
-+                                              }
-+                                      }
-+                                      
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region ", 
best_count, 4);
-+                                      if (best_count > 0) {
-+                                              if (best_count < MIN_DQS_WNDW) {
-+                                                      /* Flag excessively 
small passing window */
-+                                                      Errors |= 1 << 
SB_SMALLDQS;
-+                                              }
-+
-+                                              /* Find the center of the 
passing window */
-+                                              current_read_dqs_delay[lane] = 
(best_pos + (best_count / 2));
-+
-+                                              /* Commit the current Read DQS 
Timing Control settings to the hardware registers */
-+                                              
write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 
1), index_reg);
-+
-+                                              /* Save the final Read DQS 
Timing Control settings for later use */
-+                                              
pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_READDIR][lane] = 
current_read_dqs_delay[lane];
-+                                      } else {
-+                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 122 Unable to find read passing 
region for lane ", lane, 2);
-+
-+                                              /* Flag absence of passing 
window */
-+                                              Errors |= 1 << SB_NODQSPOS;
-+                                      }
-+
-+                                      /* Determine location and length of 
longest consecutive string of passing values for write DQS timing
-+                                       * Output is stored in best_pos and 
best_count
-+                                       */
-+                                      last_pos = 0;
-+                                      cur_count = 0;
-+                                      best_pos = 0;
-+                                      best_count = 0;
-+                                      for (iter = 0; iter < 128; iter++) {
-+                                              if 
((dqs_write_results_array[0][lane][iter]) && (iter < 127)) {
-+                                                      /* Pass */
-+                                                      cur_count++;
-+                                              } else {
-+                                                      /* Failure or end of 
loop */
-+                                                      if (cur_count > 
best_count) {
-+                                                              best_count = 
cur_count;
-+                                                              best_pos = 
last_pos;
-+                                                      }
-+                                                      cur_count = 0;
-+                                                      last_pos = iter;
-+                                              }
-+                                      }
-+                                      
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region ", 
best_count, 4);
-+                                      if (best_count > 0) {
-+                                              if (best_count < MIN_DQS_WNDW) {
-+                                                      /* Flag excessively 
small passing window */
-+                                                      Errors |= 1 << 
SB_SMALLDQS;
-+                                              }
-+
-+                                              /* Find the center of the 
passing window */
-+                                              current_write_dqs_delay[lane] = 
(best_pos + (best_count / 2));
-+
-+                                              /* Commit the current Write 
Data Timing settings to the hardware registers */
-+                                              
write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver 
>> 1), index_reg);
-+
-+                                              /* Save the final Write Data 
Timing settings for later use */
-+                                              
pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_WRITEDIR][lane] = 
current_write_dqs_delay[lane];
-+                                      } else {
-+                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 123 Unable to find write passing 
region for lane ", lane, 2);
-+
-+                                              /* Flag absence of passing 
window */
-+                                              Errors |= 1 << SB_NODQSPOS;
-+                                      }
-+                              }
-+                      }
- 
--                      print_debug_dqs("\tTrainDQSRdWrPos: 231 DQSWrDelay ", 
DQSWrDelay, 1);
--                      TrainWriteDQS_D(pMCTstat, pDCTstat, cs_start);
-               }
--              print_debug_dqs("\tTrainDQSRdWrPos: 232 Errors ", Errors, 1);
--              pDCTstat->ErrStatus |= Errors;
-       }
- 
-+      pDCTstat->TrainErrors |= Errors;
-+      pDCTstat->ErrStatus |= Errors;
-+
- #if DQS_TRAIN_DEBUG > 0
-       {
-               u8 val;
-               u8 i;
--              u8 Channel, Receiver, Dir;
-+              u8 ChannelDTD, ReceiverDTD, Dir;
-               u8 *p;
- 
-               for (Dir = 0; Dir < 2; Dir++) {
-@@ -375,14 +749,14 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc 
*pMCTstat,
-                       } else {
-                               printk(BIOS_DEBUG, "TrainDQSRdWrPos: 
CH_D_DIR_B_DQS RD:\n");
-                       }
--                      for (Channel = 0; Channel < 2; Channel++) {
--                              printk(BIOS_DEBUG, "Channel: %02x\n", Channel);
--                              for (Receiver = cs_start; Receiver < (cs_start 
+ 2); Receiver += 2) {
--                                      printk(BIOS_DEBUG, "\t\tReceiver: %02x: 
", Receiver);
--                                      p = 
pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][Dir];
-+                      for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
-+                              printk(BIOS_DEBUG, "Channel: %02x\n", 
ChannelDTD);
-+                              for (ReceiverDTD = 0; ReceiverDTD < 
MAX_CS_SUPPORTED; ReceiverDTD += 2) {
-+                                      printk(BIOS_DEBUG, "\t\tReceiver: 
%02x:", ReceiverDTD);
-+                                      p = 
pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir];
-                                       for (i=0;i<8; i++) {
-                                               val  = p[i];
--                                              printk(BIOS_DEBUG, "%02x ", 
val);
-+                                              printk(BIOS_DEBUG, " %02x", 
val);
-                                       }
-                                       printk(BIOS_DEBUG, "\n");
-                               }
-@@ -437,225 +811,6 @@ static void SetupDqsPattern_D(struct MCTStatStruc 
*pMCTstat,
-       pDCTstat->PtrPatternBufA = (u32)buf;
- }
- 
--static void TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u8 cs_start)
--{
--      u32 Errors;
--      u8 ChipSel, DQSDelay;
--      u8 RnkDlySeqPassMin=0, RnkDlySeqPassMax=0xFF, RnkDlyFilterMin=0, 
RnkDlyFilterMax=0xFF;
--      u8 RnkDlySeqPassMinTot=0, RnkDlySeqPassMaxTot=0xFF, 
RnkDlyFilterMinTot=0, RnkDlyFilterMaxTot=0xFF;
--      u8 LastTest ,LastTestTot;
--      u32 TestAddr;
--      u8 ByteLane;
--      u8 MutualCSPassW[128];
--      u8 BanksPresent;
--      u8 dqsDelay_end;
--      u8 tmp, valid, tmp1;
--      u16 word;
--
--      /* MutualCSPassW: each byte represents a bitmap of pass/fail per
--       * ByteLane.  The indext within MutualCSPassW is the delay value
--       * given the results.
--       */
--      print_debug_dqs("\t\t\tTrainDQSPos begin ", 0, 3);
--
--      Errors = 0;
--      BanksPresent = 0;
--
--      dqsDelay_end = 32;
--      /* Bitmapped status per delay setting, 0xff=All positions
--       * passing (1= PASS). Set the entire array.
--       */
--      for (DQSDelay=0; DQSDelay<128; DQSDelay++) {
--              MutualCSPassW[DQSDelay] = 0xFF;
--      }
--
--      for (ChipSel = cs_start; ChipSel < (cs_start + 2); ChipSel++) { /* 
logical register chipselects 0..7 */
--              print_debug_dqs("\t\t\t\tTrainDQSPos: 11 ChipSel ", ChipSel, 4);
--
--              if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, 
pDCTstat->Channel, ChipSel)) {
--                      print_debug_dqs("\t\t\t\tmct_RcvrRankEnabled_D CS not 
enabled ", ChipSel, 4);
--                      continue;
--              }
--
--              BanksPresent = 1;       /* flag for at least one bank is 
present */
--              TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, 
pDCTstat->Channel, ChipSel, &valid);
--              if (!valid) {
--                      print_debug_dqs("\t\t\t\tAddress not supported on 
current CS ", TestAddr, 4);
--                      continue;
--              }
--
--              print_debug_dqs("\t\t\t\tTrainDQSPos: 12 TestAddr ", TestAddr, 
4);
--              SetUpperFSbase(TestAddr);       /* fs:eax=far ptr to target */
--
--              if (pDCTstat->Direction == DQS_READDIR) {
--                      print_debug_dqs("\t\t\t\tTrainDQSPos: 13 for read ", 0, 
4);
--                      WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 
8);
--              }
--
--              for (DQSDelay = 0; DQSDelay < dqsDelay_end; DQSDelay++) {
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 141 DQSDelay ", 
DQSDelay, 5);
--
--                      tmp = 0xFF;
--                      tmp1 = DQSDelay;
--                      if (pDCTstat->Direction == DQS_READDIR) {
--                              tmp &= MutualCSPassW[DQSDelay];
--                              tmp1 += dqsDelay_end;
--                      }
--                      tmp &= MutualCSPassW[tmp1];
--
--                      if (tmp == 0) {
--                              continue;/* skip current delay value if other 
chipselects have failed all 8 bytelanes */
--                      }
--
--                      pDCTstat->DQSDelay = DQSDelay;
--                      mct_SetDQSDelayAllCSR_D(pMCTstat, pDCTstat, cs_start);
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 142 
MutualCSPassW ", MutualCSPassW[DQSDelay], 5);
--
--                      if (pDCTstat->Direction == DQS_WRITEDIR) {
--                              print_debug_dqs("\t\t\t\t\tTrainDQSPos: 143 for 
write", 0, 5);
--                              WriteDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8);
--                      }
--
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 Pattern ", 
pDCTstat->Pattern, 5);
--                      ReadDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8);
--                      /* print_debug_dqs("\t\t\t\t\tTrainDQSPos: 145 
MutualCSPassW ", MutualCSPassW[DQSDelay], 5); */
--                      word = CompareDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8); /* 0=fail, 1=pass */
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 compare 1 
", word, 3);
--
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 
DqsRdWrPos_Saved ", pDCTstat->DqsRdWrPos_Saved, 3);
--                      word &= ~(pDCTstat->DqsRdWrPos_Saved); /* mask out 
bytelanes that already passed */
--                      word &= ~(pDCTstat->DqsRdWrPos_Saved << 8);
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 compare 2 
", word, 3);
--
--                      tmp = DQSDelay;
--                      if (pDCTstat->Direction == DQS_READDIR) {
--                              MutualCSPassW[tmp] &= word >> 8;
--                              tmp += dqsDelay_end;
--                      }
--                      MutualCSPassW[tmp] &= word & 0xFF;
--
--                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 146 
\tMutualCSPassW ", MutualCSPassW[DQSDelay], 5);
--
--                      SetTargetWTIO_D(TestAddr);
--                      FlushDQSTestPattern_D(pDCTstat, TestAddr << 8);
--                      ResetTargetWTIO_D();
--              }
--
--      }
--
--      if (pDCTstat->Direction == DQS_READDIR) {
--              dqsDelay_end <<= 1;
--      }
--
--      if (BanksPresent) {
--              #if 0           /* show the bitmap */
--              for (ByteLane = 0; ByteLane < 8; ByteLane++) { /* just print 
ByteLane 0 */
--                      for (DQSDelay = 0; DQSDelay < dqsDelay_end; DQSDelay++) 
{
--                              if (!(MutualCSPassW[DQSDelay] &(1 << 
ByteLane))) {
--                                      printk(BIOS_DEBUG, ".");
--                              } else {
--                                      printk(BIOS_DEBUG, "*");
--                              }
--                      }
--                      printk(BIOS_DEBUG, "\n");
--              }
--              #endif
--              for (ByteLane = 0; ByteLane < 8; ByteLane++) {
--                      print_debug_dqs("\t\t\t\tTrainDQSPos: 31 ByteLane 
",ByteLane, 4);
--                      if (!(pDCTstat->DqsRdWrPos_Saved &(1 << ByteLane))) {
--                              pDCTstat->ByteLane = ByteLane;
--                              LastTest = DQS_FAIL;            /* Analyze the 
results */
--                              LastTestTot = DQS_FAIL;
--                              /* RnkDlySeqPassMin = 0; */
--                              /* RnkDlySeqPassMax = 0; */
--                              RnkDlyFilterMax = 0;
--                              RnkDlyFilterMin = 0;
--                              RnkDlyFilterMaxTot = 0;
--                              RnkDlyFilterMinTot = 0;
--                              for (DQSDelay = 0; DQSDelay < dqsDelay_end; 
DQSDelay++) {
--                                      if (MutualCSPassW[DQSDelay] & (1 << 
ByteLane)) {
--                                              
print_debug_dqs("\t\t\t\t\tTrainDQSPos: 321 DQSDelay ", DQSDelay, 5);
--                                              
print_debug_dqs("\t\t\t\t\tTrainDQSPos: 322 MutualCSPassW ", 
MutualCSPassW[DQSDelay], 5);
--                                              if (pDCTstat->Direction == 
DQS_READDIR)
--                                                      tmp = 0x20;
--                                              else
--                                                      tmp = 0;
--                                              if (DQSDelay >= tmp) {
--                                                      RnkDlySeqPassMax = 
DQSDelay;
--                                                      if (LastTest == 
DQS_FAIL) {
--                                                              
RnkDlySeqPassMin = DQSDelay; /* start sequential run */
--                                                      }
--                                                      if ((RnkDlySeqPassMax - 
RnkDlySeqPassMin)>(RnkDlyFilterMax-RnkDlyFilterMin)){
--                                                              RnkDlyFilterMin 
= RnkDlySeqPassMin;
--                                                              RnkDlyFilterMax 
= RnkDlySeqPassMax;
--                                                      }
--                                                      LastTest = DQS_PASS;
--                                              }
--
--                                              if (pDCTstat->Direction == 
DQS_READDIR) {
--                                                      RnkDlySeqPassMaxTot = 
DQSDelay;
--                                                      if (LastTestTot == 
DQS_FAIL)
--                                                              
RnkDlySeqPassMinTot = DQSDelay;
--                                                      if 
((RnkDlySeqPassMaxTot - 
RnkDlySeqPassMinTot)>(RnkDlyFilterMaxTot-RnkDlyFilterMinTot)){
--                                                              
RnkDlyFilterMinTot = RnkDlySeqPassMinTot;
--                                                              
RnkDlyFilterMaxTot = RnkDlySeqPassMaxTot;
--                                                      }
--                                                      LastTestTot = DQS_PASS;
--                                              }
--                                      } else {
--                                              LastTest = DQS_FAIL;
--                                              LastTestTot = DQS_FAIL;
--                                      }
--                              }
--                              print_debug_dqs("\t\t\t\tTrainDQSPos: 33 
RnkDlySeqPassMax ", RnkDlySeqPassMax, 4);
--                              if (RnkDlySeqPassMax == 0) {
--                                      Errors |= 1 << SB_NODQSPOS; /* no 
passing window */
--                              } else {
--                                      
print_debug_dqs_pair("\t\t\t\tTrainDQSPos: 34 RnkDlyFilter: ", RnkDlyFilterMin, 
" ",  RnkDlyFilterMax, 4);
--                                      if (((RnkDlyFilterMax - 
RnkDlyFilterMin) < MIN_DQS_WNDW)){
--                                              Errors |= 1 << SB_SMALLDQS;
--                                      } else {
--                                              u8 middle_dqs;
--                                              /* mctEngDQSwindow_Save_D Not 
required for arrays */
--                                              if (pDCTstat->Direction == 
DQS_READDIR)
--                                                      middle_dqs = 
MiddleDQS_D(RnkDlyFilterMinTot, RnkDlyFilterMaxTot);
--                                              else
--                                                      middle_dqs = 
MiddleDQS_D(RnkDlyFilterMin, RnkDlyFilterMax);
--                                              pDCTstat->DQSDelay = middle_dqs;
--                                              mct_SetDQSDelayCSR_D(pMCTstat, 
pDCTstat, cs_start);  /* load the register with the value */
--                                              if (pDCTstat->Direction == 
DQS_READDIR)
--                                                      
StoreWrRdDQSDatStrucVal_D(pMCTstat, pDCTstat, cs_start, RnkDlyFilterMinTot, 
RnkDlyFilterMaxTot); /* store the value into the data structure */
--                                              else
--                                                      
StoreWrRdDQSDatStrucVal_D(pMCTstat, pDCTstat, cs_start, RnkDlyFilterMin, 
RnkDlyFilterMax); /* store the value into the data structure */
--                                              
print_debug_dqs("\t\t\t\tTrainDQSPos: 42 middle_dqs : ",middle_dqs, 4);
--                                              pDCTstat->DqsRdWrPos_Saved |= 1 
<< ByteLane;
--                                      }
--                              }
--                      }
--              } /* if (pDCTstat->DqsRdWrPos_Saved &(1 << ByteLane)) */
--      }
--/* skipLocMiddle: */
--      pDCTstat->TrainErrors = Errors;
--
--      print_debug_dqs("\t\t\tTrainDQSPos: Errors ", Errors, 3);
--}
--
--static void mctEngDQSwindow_Save_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
--                                      u8 RnkDlyFilterMin, u8 RnkDlyFilterMax)
--{
--      pDCTstat->CH_D_DIR_MaxMin_B_Dly[pDCTstat->Channel]
--              [pDCTstat->Direction]
--              [0]
--              [pDCTstat->ByteLane] = RnkDlyFilterMin;
--      pDCTstat->CH_D_DIR_MaxMin_B_Dly[pDCTstat->Channel]
--              [pDCTstat->Direction]
--              [1]
--              [pDCTstat->ByteLane] = RnkDlyFilterMax;
--}
--
- static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
-                                       struct DCTStatStruc *pDCTstat, u8 
ChipSel)
- {
-@@ -679,26 +834,6 @@ static void StoreDQSDatStrucVal_D(struct MCTStatStruc 
*pMCTstat,
-                                       pDCTstat->DQSDelay;
- }
- 
--static void StoreWrRdDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
--                                      u8 RnkDlyFilterMin, u8 RnkDlyFilterMax)
--{
--      u8 dn;
--
--      if (pDCTstat->Direction == DQS_WRITEDIR) {
--              dn = ChipSel >> 1;
--              RnkDlyFilterMin += 
pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][dn][pDCTstat->ByteLane];
--              RnkDlyFilterMax += 
pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][dn][pDCTstat->ByteLane];
--              pDCTstat->DQSDelay += 
pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][dn][pDCTstat->ByteLane];
--      } else {
--              RnkDlyFilterMin <<= 1;
--              RnkDlyFilterMax <<= 1;
--              pDCTstat->DQSDelay <<= 1;
--      }
--      mctEngDQSwindow_Save_D(pMCTstat, pDCTstat, ChipSel, RnkDlyFilterMin, 
RnkDlyFilterMax);
--      StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel);
--}
--
- static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 ChipSel)
- {
-@@ -720,33 +855,6 @@ static void GetDQSDatStrucVal_D(struct MCTStatStruc 
*pMCTstat,
- 
- /* FindDQSDatDimmVal_D is not required since we use an array */
- 
--static u8 MiddleDQS_D(u8 min, u8 max)
--{
--      u8 size;
--      size = max-min;
--      if (size % 2)
--              size++;         /* round up if the size isn't even. */
--      return ( min + (size >> 1));
--}
--
--static void TrainReadDQS_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u8 cs_start)
--{
--      print_debug_dqs("\t\tTrainReadPos ", 0, 2);
--      pDCTstat->Direction = DQS_READDIR;
--      TrainDQSPos_D(pMCTstat, pDCTstat, cs_start);
--}
--
--static void TrainWriteDQS_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u8 cs_start)
--{
--      pDCTstat->Direction = DQS_WRITEDIR;
--      print_debug_dqs("\t\tTrainWritePos", 0, 2);
--      TrainDQSPos_D(pMCTstat, pDCTstat, cs_start);
--}
--
- static void proc_IOCLFLUSH_D(u32 addr_hi)
- {
-       SetTargetWTIO_D(addr_hi);
-@@ -963,30 +1071,6 @@ static void ResetTargetWTIO_D(void)
-       _WRMSR(0xc0010017, lo, hi); /* IORR0 Mask */
- }
- 
--static void ReadDQSTestPattern_D(struct MCTStatStruc *pMCTstat,
--                              struct DCTStatStruc *pDCTstat,
--                              u32 TestAddr_lo)
--{
--      /* Read a pattern of 72 bit times (per DQ), to test dram functionality.
--       * The pattern is a stress pattern which exercises both ISI and
--       * crosstalk.  The number of cache lines to fill is dependent on DCT
--       * width mode and burstlength.
--       * Mode BL  Lines Pattern no.
--       * ----+---+-------------------
--       * 64   4         9     0
--       * 64   8         9     0
--       * 64M  4         9     0
--       * 64M  8         9     0
--       * 128  4         18    1
--       * 128  8         N/A   -
--       */
--      if (pDCTstat->Pattern == 0)
--              ReadL9TestPattern(TestAddr_lo);
--      else
--              ReadL18TestPattern(TestAddr_lo);
--      _MFENCE;
--}
--
- u32 SetUpperFSbase(u32 addr_hi)
- {
-       /* Set the upper 32-bits of the Base address, 4GB aligned) for the
-@@ -1009,8 +1093,6 @@ void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index)
-       Set_NB32_index_wait(dev, index_reg, index, val);
- }
- 
--/* mctEngDQSwindow_Save_D not required with arrays */
--
- void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
-                       struct DCTStatStruc *pDCTstatA)
- {
-@@ -1021,8 +1103,8 @@ void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
-       for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-               pDCTstat = pDCTstatA + Node;
-               if (pDCTstat->DCTSysLimit) {
-+                      TrainDQSRdWrPos_D(pMCTstat, pDCTstat);
-                       for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel 
+= 2) {
--                              TrainDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel);
-                               SetEccDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel);
-                       }
-               }
-@@ -1137,27 +1219,6 @@ static void mct_SetDQSDelayCSR_D(struct MCTStatStruc 
*pMCTstat,
-       }
- }
- 
--/*
-- * mct_SetDQSDelayAllCSR_D:
-- * Write the Delay value to all eight byte lanes.
-- */
--static void mct_SetDQSDelayAllCSR_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat,
--                                      u8 cs_start)
--{
--      u8 ByteLane;
--      u8 ChipSel = cs_start;
--
--      for (ChipSel = cs_start; ChipSel < (cs_start + 2); ChipSel++) {
--              if ( mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, 
pDCTstat->Channel, ChipSel)) {
--                      for (ByteLane = 0; ByteLane < 8; ByteLane++) {
--                              pDCTstat->ByteLane = ByteLane;
--                              mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, 
ChipSel);
--                      }
--              }
--      }
--}
--
- u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat,
-                               u8 Channel, u8 ChipSel)
-@@ -1196,7 +1257,7 @@ u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
-       reg = 0x40 + (receiver << 2) + reg_off;
-       val = Get_NB32(dev, reg);
- 
--      val &= ~0x0F;
-+      val &= ~0xe007c01f;
- 
-       /* unganged mode DCT0+DCT1, sys addr of DCT1=node
-        * base+DctSelBaseAddr+local ca base*/
-@@ -1277,6 +1338,7 @@ exitGetAddrWNoError:
-       print_debug_dqs("mct_GetMCTSysAddr_D: base_addr ", val, 2);
-       print_debug_dqs("mct_GetMCTSysAddr_D: valid ", *valid, 2);
-       print_debug_dqs("mct_GetMCTSysAddr_D: status ", pDCTstat->Status, 2);
-+      print_debug_dqs("mct_GetMCTSysAddr_D: SysBase ", pDCTstat->DCTSysBase, 
2);
-       print_debug_dqs("mct_GetMCTSysAddr_D: HoleBase ", 
pDCTstat->DCTHoleBase, 2);
-       print_debug_dqs("mct_GetMCTSysAddr_D: Cachetop ", 
pMCTstat->Sub4GCacheTop, 2);
- 
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
-index 528c782..60bc01d 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -25,7 +26,6 @@ static void EnableZQcalibration(struct MCTStatStruc 
*pMCTstat, struct DCTStatStr
- static void DisableZQcalibration(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat);
- static void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat);
- static void PrepareC_DCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u8 dct);
--static void MultiplyDelay(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u8 dct);
- static void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat);
- static void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat);
- 
-@@ -154,7 +154,6 @@ static void PhyWLPass2(struct MCTStatStruc *pMCTstat,
-               Clear_OnDimmMirror(pMCTstat, pDCTstat);
-               SetDllSpeedUp_D(pMCTstat, pDCTstat, dct);
-               DisableAutoRefresh_D(pMCTstat, pDCTstat);
--              MultiplyDelay(pMCTstat, pDCTstat, dct);
-               for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
-                       if (DIMMValid & (1 << (dimm << 1)))
-                               AgesaHwWlPhase1(pDCTstat->C_MCTPtr, 
pDCTstat->C_DCTPtr[dct], dimm, SecondPass);
-@@ -162,6 +161,9 @@ static void PhyWLPass2(struct MCTStatStruc *pMCTstat,
-       }
- }
- 
-+/* Write Levelization Training
-+ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.1
-+ */
- static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
-                                       struct DCTStatStruc *pDCTstat)
- {
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c
-index 3d625de..596fb23 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -201,12 +202,13 @@ static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 
*pMtrrAddr, u16 MtrrType)
- 
- void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA)
- {
--/* UMA memory size may need splitting the MTRR configuration into two
--  Before training use NB_BottomIO or the physical memory size to set the 
MTRRs.
--  After training, add UMAMemTyping function to reconfigure the MTRRs based on
--  NV_BottomUMA (for UMA systems only).
--  This two-step process allows all memory to be cached for training
--*/
-+      /* UMA memory size may need splitting the MTRR configuration into two
-+       * Before training use NB_BottomIO or the physical memory size to set 
the MTRRs.
-+       * After training, add UMAMemTyping function to reconfigure the MTRRs 
based on
-+       * NV_BottomUMA (for UMA systems only).
-+       * This two-step process allows all memory to be cached for training
-+      */
-+
-       u32 Bottom32bIO, Cache32bTOP;
-       u32 val;
-       u32 addr;
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c
-index 013a1b9..6f97061 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -140,7 +141,7 @@ void InterleaveNodes_D(struct MCTStatStruc *pMCTstat,
-       }
- 
-       if (DoIntlv) {
--              MCTMemClr_D(pMCTstat,pDCTstatA);
-+              MCTMemClr_D(pMCTstat, pDCTstatA);
-               /* Program Interleaving enabled on Node 0 map only.*/
-               MemSize0 <<= bsf(Nodes);        /* MemSize=MemSize*2 (or 4, or 
8) */
-               Dct0MemSize <<= bsf(Nodes);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
-index da2f372..cda9c6b 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -36,10 +37,10 @@ u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, 
u8 dct, u32 misc2)
-               val = Get_NB32(pDCTstat->dev_dct, dct * 0x100 + 0x78);
- 
-               val &= 7;
--              val = ((~val) & 0xFF) + 1;
-+              val = ((~val) & 0xff) + 1;
-               val += 6;
--              val &= 0xFF;
--              misc2 &= 0xFFF8FFFF;
-+              val &= 0x7;
-+              misc2 &= 0xfff8ffff;
-               misc2 |= val << 16;     /* DataTxFifoWrDly */
-               if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
-                       misc2 |= 1 << 7; /* ProgOdtEn */
-@@ -52,11 +53,15 @@ void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat)
-       u32 val;
- 
-       if (pDCTstat->LogicalCPUID & (AMD_DR_Cx)) {
--              Set_NB32(pDCTstat->dev_dct, 0x11C, 0x0CE00FC0 | 1 << 29/* 
FlushWrOnStpGnt */);
-+              /* Revision C */
-+              Set_NB32(pDCTstat->dev_dct, 0x11c, 0x0ce00fc0 | 1 << 29/* 
FlushWrOnStpGnt */);
-+      }
- 
--              val = Get_NB32(pDCTstat->dev_dct, 0x1B0);
--              val &= 0xFFFFF8C0;
-+      if (pDCTstat->LogicalCPUID & (AMD_DR_Cx)) {
-+              val = Get_NB32(pDCTstat->dev_dct, 0x1b0);
-+              val &= ~0x73f;
-               val |= 0x101;   /* BKDG recommended settings */
--              Set_NB32(pDCTstat->dev_dct, 0x1B0, val);
-+
-+              Set_NB32(pDCTstat->dev_dct, 0x1b0, val);
-       }
- }
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
-index 6de2f4e..b21b96a 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -172,6 +173,7 @@ static u32 mct_MR1(struct MCTStatStruc *pMCTstat,
-                       ret |= 1 << 11;
-       }
- 
-+      /* program MrsAddress[12]=QOFF: based on F2x[1,0]84[Qoff] */
-       if (dword & (1 << 13))
-               ret |= 1 << 12;
- 
-@@ -199,7 +201,8 @@ static u32 mct_MR0(struct MCTStatStruc *pMCTstat,
-       /* program MrsAddress[6:4,2]=read CAS latency
-          (CL):based on F2x[1,0]88[Tcl] */
-       dword2 = Get_NB32(dev, reg_off + 0x88);
--      ret |= (dword2 & 0xF) << 4; /* F2x88[3:0] to MrsAddress[6:4,2]=xxx0b */
-+      ret |= (dword2 & 0x7) << 4;             /* F2x88[2:0] to 
MrsAddress[6:4] */
-+      ret |= ((dword2 & 0x8) >> 3) << 2;      /* F2x88[3] to MrsAddress[2] */
- 
-       /* program MrsAddress[12]=0 (PPD):slow exit */
-       if (dword & (1 << 23))
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
-index 8e5c268..91e8f77 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -24,25 +25,13 @@
- 
- static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 Pass);
--static u8 mct_SavePassRcvEnDly_D(struct DCTStatStruc *pDCTstat,
--                                      u8 rcvrEnDly, u8 Channel,
--                                      u8 receiver, u8 Pass);
--static u8 mct_CompareTestPatternQW0_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat,
--                                      u32 addr, u8 channel,
--                                      u8 pattern, u8 Pass);
- static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
-                                        struct DCTStatStruc *pDCTstat);
- static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 Channel);
- static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 Channel);
--static void mct_SetFinalRcvrEnDly_D(struct DCTStatStruc *pDCTstat,
--                              u8 RcvrEnDly, u8 where,
--                              u8 Channel, u8 Receiver,
--                              u32 dev, u32 index_reg,
--                              u8 Addl_Index, u8 Pass);
--static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u8 
DQSRcvEnDly);
-+static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, 
u16 DQSRcvEnDly);
- static void fenceDynTraining_D(struct MCTStatStruc *pMCTstat,
-                       struct DCTStatStruc *pDCTstat, u8 dct);
- static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat);
-@@ -50,17 +39,17 @@ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc 
*pDCTstat);
- /* Warning:  These must be located so they do not cross a logical 16-bit
-    segment boundary! */
- static const u32 TestPattern0_D[] = {
--      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
--      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
--      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
--      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
--};
--static const u32 TestPattern1_D[] = {
-       0x55555555, 0x55555555, 0x55555555, 0x55555555,
-       0x55555555, 0x55555555, 0x55555555, 0x55555555,
-       0x55555555, 0x55555555, 0x55555555, 0x55555555,
-       0x55555555, 0x55555555, 0x55555555, 0x55555555,
- };
-+static const u32 TestPattern1_D[] = {
-+      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
-+      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
-+      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
-+      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
-+};
- static const u32 TestPattern2_D[] = {
-       0x12345678, 0x87654321, 0x23456789, 0x98765432,
-       0x59385824, 0x30496724, 0x24490795, 0x99938733,
-@@ -104,16 +93,87 @@ void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat,
-               dqsTrainRcvrEn_SW(pMCTstat, pDCTstat, Pass);
- }
- 
-+static void read_dqs_write_timing_control_registers(uint16_t* 
current_total_delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
-+{
-+      uint8_t lane;
-+      uint32_t dword;
-+
-+      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+              uint32_t wdt_reg;
-+              if ((lane == 0) || (lane == 1))
-+                      wdt_reg = 0x30;
-+              if ((lane == 2) || (lane == 3))
-+                      wdt_reg = 0x31;
-+              if ((lane == 4) || (lane == 5))
-+                      wdt_reg = 0x40;
-+              if ((lane == 6) || (lane == 7))
-+                      wdt_reg = 0x41;
-+              if (lane == 8)
-+                      wdt_reg = 0x32;
-+              wdt_reg += dimm * 3;
-+              dword = Get_NB32_index_wait(dev, index_reg, wdt_reg);
-+              if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1))
-+                      current_total_delay[lane] = (dword & 0x00ff0000) >> 16;
-+              if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || 
(lane == 0))
-+                      current_total_delay[lane] = dword & 0x000000ff;
-+      }
-+}
-+
-+static void write_dqs_receiver_enable_control_registers(uint16_t* 
current_total_delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
-+{
-+      uint8_t lane;
-+      uint32_t dword;
-+
-+      for (lane = 0; lane < 8; lane++) {
-+              uint32_t ret_reg;
-+              if ((lane == 0) || (lane == 1))
-+                      ret_reg = 0x10;
-+              if ((lane == 2) || (lane == 3))
-+                      ret_reg = 0x11;
-+              if ((lane == 4) || (lane == 5))
-+                      ret_reg = 0x20;
-+              if ((lane == 6) || (lane == 7))
-+                      ret_reg = 0x21;
-+              ret_reg += dimm * 3;
-+              dword = Get_NB32_index_wait(dev, index_reg, ret_reg);
-+              if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) {
-+                      dword &= ~(0x1ff << 16);
-+                      dword |= (current_total_delay[lane] & 0x1ff) << 16;
-+              }
-+              if ((lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) {
-+                      dword &= ~0x1ff;
-+                      dword |= current_total_delay[lane] & 0x1ff;
-+              }
-+              Set_NB32_index_wait(dev, index_reg, ret_reg, dword);
-+      }
-+}
-+
-+static uint32_t convert_testaddr_and_channel_to_address(struct DCTStatStruc 
*pDCTstat, uint32_t testaddr, uint8_t channel)
-+{
-+      SetUpperFSbase(testaddr);
-+      testaddr <<= 8;
-+
-+      if((pDCTstat->Status & (1<<SB_128bitmode)) && channel ) {
-+              testaddr += 8;  /* second channel */
-+      }
-+
-+      return testaddr;
-+}
-+
-+/* DQS Receiver Enable Training
-+ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.2
-+ */
- static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat, u8 Pass)
- {
--      u8 Channel, RcvrEnDly, RcvrEnDlyRmin;
--      u8 Test0, Test1, CurrTest, CurrTestSide0, CurrTestSide1;
--      u8 CTLRMaxDelay, _2Ranks, PatternA, PatternB;
-+      u8 Channel;
-+      u8 _2Ranks;
-       u8 Addl_Index = 0;
-       u8 Receiver;
-       u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0;
--      u8 RcvrEnDlyLimit, Final_Value, MaxDelay_CH[2];
-+      u8 Final_Value;
-+      u16 CTLRMaxDelay;
-+      u16 MaxDelay_CH[2];
-       u32 TestAddr0, TestAddr1, TestAddr0B, TestAddr1B;
-       u32 PatternBuffer[64+4]; /* FIXME: need increase 8? */
-       u32 Errors;
-@@ -127,9 +187,20 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
-       u32 cr4;
-       u32 lo, hi;
- 
-+      uint32_t dword;
-+      uint8_t rank;
-+      uint8_t lane;
-+      uint16_t current_total_delay[MAX_BYTE_LANES];
-+      uint16_t candidate_total_delay[8];
-+      uint8_t data_test_pass_sr[2][8];        /* [rank][lane] */
-+      uint8_t data_test_pass[8];              /* [lane] */
-+      uint8_t data_test_pass_prev[8];         /* [lane] */
-+      uint8_t window_det_toggle[8];
-+      uint8_t trained[8];
-+      uint64_t result_qword1;
-+      uint64_t result_qword2;
-+
-       u8 valid;
--      u32 tmp;
--      u8 LastTest;
- 
-       print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0);
-       print_debug_dqs("TrainRcvEn: Pass", Pass, 0);
-@@ -181,33 +252,103 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
- 
-       Errors = 0;
-       dev = pDCTstat->dev_dct;
--      CTLRMaxDelay = 0;
- 
-       for (Channel = 0; Channel < 2; Channel++) {
-               print_debug_dqs("\tTrainRcvEn51: Node ", pDCTstat->Node_ID, 1);
-               print_debug_dqs("\tTrainRcvEn51: Channel ", Channel, 1);
-               pDCTstat->Channel = Channel;
- 
-+              CTLRMaxDelay = 0;
-               MaxDelay_CH[Channel] = 0;
-               index_reg = 0x98 + 0x100 * Channel;
- 
-               Receiver = mct_InitReceiver_D(pDCTstat, Channel);
--              /* There are four receiver pairs, loosely associated with 
chipselects. */
-+              /* There are four receiver pairs, loosely associated with 
chipselects.
-+               * This is essentially looping over each DIMM.
-+               */
-               for (; Receiver < 8; Receiver += 2) {
-                       Addl_Index = (Receiver >> 1) * 3 + 0x10;
--                      LastTest = DQS_FAIL;
--
--                      /* mct_ModifyIndex_D */
--                      RcvrEnDlyRmin = RcvrEnDlyLimit = 0xff;
- 
-                       print_debug_dqs("\t\tTrainRcvEnd52: index ", 
Addl_Index, 2);
- 
--                      if(!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, 
Receiver)) {
-+                      if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, 
Receiver)) {
-                               continue;
-                       }
- 
-+                      /* Clear data structures */
-+                      for (lane = 0; lane < 8; lane++) {
-+                              data_test_pass_prev[lane] = 0;
-+                              trained[lane] = 0;
-+                      }
-+
-+                      /* 2.8.9.9.2 (1, 6)
-+                       * Retrieve gross and fine timing fields from write DQS 
registers
-+                       */
-+                      
read_dqs_write_timing_control_registers(current_total_delay, dev, (Receiver >> 
1), index_reg);
-+
-+                      /* 2.8.9.9.2 (1)
-+                       * Program the Write Data Timing and Write ECC Timing 
register to
-+                       * the values stored in the DQS Write Timing Control 
register
-+                       * for each lane
-+                       */
-+                      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+                              uint32_t wdt_reg;
-+
-+                              /* Calculate Write Data Timing register 
location */
-+                              if ((lane == 0) || (lane == 1) || (lane == 2) 
|| (lane == 3))
-+                                      wdt_reg = 0x1;
-+                              if ((lane == 4) || (lane == 5) || (lane == 6) 
|| (lane == 7))
-+                                      wdt_reg = 0x2;
-+                              if (lane == 8)
-+                                      wdt_reg = 0x3;
-+                              wdt_reg |= ((Receiver / 2) << 8);
-+
-+                              /* Set Write Data Timing register values */
-+                              dword = Get_NB32_index_wait(dev, index_reg, 
wdt_reg);
-+                              if ((lane == 7) || (lane == 3)) {
-+                                      dword &= ~(0x7f << 24);
-+                                      dword |= (current_total_delay[lane] & 
0x7f) << 24;
-+                              }
-+                              if ((lane == 6) || (lane == 2)) {
-+                                      dword &= ~(0x7f << 16);
-+                                      dword |= (current_total_delay[lane] & 
0x7f) << 16;
-+                              }
-+                              if ((lane == 5) || (lane == 1)) {
-+                                      dword &= ~(0x7f << 8);
-+                                      dword |= (current_total_delay[lane] & 
0x7f) << 8;
-+                              }
-+                              if ((lane == 8) || (lane == 4) || (lane == 0)) {
-+                                      dword &= ~0x7f;
-+                                      dword |= current_total_delay[lane] & 
0x7f;
-+                              }
-+                              Set_NB32_index_wait(dev, index_reg, wdt_reg, 
dword);
-+                      }
-+
-+                      /* 2.8.9.9.2 (2)
-+                       * Program the Read DQS Timing Control and the Read DQS 
ECC Timing Control registers
-+                       * to 1/2 MEMCLK for all lanes
-+                       */
-+                      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
-+                              uint32_t rdt_reg;
-+                              if ((lane == 0) || (lane == 1) || (lane == 2) 
|| (lane == 3))
-+                                      rdt_reg = 0x5;
-+                              if ((lane == 4) || (lane == 5) || (lane == 6) 
|| (lane == 7))
-+                                      rdt_reg = 0x6;
-+                              if (lane == 8)
-+                                      rdt_reg = 0x7;
-+                              rdt_reg |= ((Receiver / 2) << 8);
-+                              if (lane == 8)
-+                                      dword = 0x0000003f;
-+                              else
-+                                      dword = 0x3f3f3f3f;
-+                              Set_NB32_index_wait(dev, index_reg, rdt_reg, 
dword);
-+                      }
-+
-+                      /* 2.8.9.9.2 (3)
-+                       * Select two test addresses for each rank present
-+                       */
-                       TestAddr0 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, 
Channel, Receiver, &valid);
--                      if(!valid) {    /* Address not supported on current CS 
*/
-+                      if (!valid) {   /* Address not supported on current CS 
*/
-                               continue;
-                       }
- 
-@@ -229,171 +370,214 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
-                       print_debug_dqs("\t\tTrainRcvEn53: TestAddr1 ", 
TestAddr1, 2);
-                       print_debug_dqs("\t\tTrainRcvEn53: TestAddr1B ", 
TestAddr1B, 2);
- 
--                      /*
--                       * Get starting RcvrEnDly value
-+                      /* 2.8.9.9.2 (4, 5)
-+                       * Write 1 cache line of the appropriate test pattern 
to each test addresse
-                        */
--                      RcvrEnDly = mct_Get_Start_RcvrEnDly_1Pass(Pass);
-+                      mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0, 
0); /* rank 0 of DIMM, testpattern 0 */
-+                      mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0B, 1); /* rank 0 of DIMM, testpattern 1 */
-+                      if (_2Ranks) {
-+                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr1, 0); /*rank 1 of DIMM, testpattern 0 */
-+                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr1B, 1); /*rank 1 of DIMM, testpattern 1 */
-+                      }
- 
--                      /* mct_GetInitFlag_D*/
--                      if (Pass == FirstPass) {
--                              pDCTstat->DqsRcvEn_Pass = 0;
--                      } else {
--                              pDCTstat->DqsRcvEn_Pass=0xFF;
-+#if DQS_TRAIN_DEBUG > 0
-+                      for (lane = 0; lane < 8; lane++) {
-+                              print_debug_dqs("\t\tTrainRcvEn54: lane: ", 
lane, 2);
-+                              print_debug_dqs("\t\tTrainRcvEn54: 
current_total_delay ", current_total_delay[lane], 2);
-                       }
--                      pDCTstat->DqsRcvEn_Saved = 0;
-+#endif
- 
-+                      /* 2.8.9.9.2 (6)
-+                       * Write gross and fine timing fields to read DQS 
registers
-+                       */
-+                      
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
-+
-+                      /* 2.8.9.9.2 (7)
-+                       * Loop over all delay values up to 1 MEMCLK (0x40 
delay steps) from the initial delay values
-+                       *
-+                       * FIXME
-+                       * It is not clear if training should be discontinued 
if any test failures occur in the first
-+                       * 1 MEMCLK window, or if it should be discontinued if 
no successes occur in the first 1 MEMCLK
-+                       * window.  Therefore, loop over up to 2 MEMCLK (0x80 
delay steps) to be on the safe side.
-+                       */
-+                      uint16_t current_delay_step;
- 
--                      while(RcvrEnDly < RcvrEnDlyLimit) {     /* sweep Delay 
value here */
--                              print_debug_dqs("\t\t\tTrainRcvEn541: RcvrEnDly 
", RcvrEnDly, 3);
-+                      for (current_delay_step = 0; current_delay_step < 0x80; 
current_delay_step++) {
-+                              print_debug_dqs("\t\t\tTrainRcvEn541: 
current_delay_step ", current_delay_step, 3);
- 
--                              /* callback not required
--                              if(mct_AdjustDelay_D(pDCTstat, RcvrEnDly))
--                                      goto skipDly;
-+                              /* 2.8.9.9.2 (7 D)
-+                              * Terminate if all lanes are trained
-                               */
-+                              uint8_t all_lanes_trained = 1;
-+                              for (lane = 0; lane < 8; lane++)
-+                                      if (!trained[lane])
-+                                              all_lanes_trained = 0;
- 
--                              /* Odd steps get another pattern such that even
--                               and odd steps alternate. The pointers to the
--                               patterns will be swaped at the end of the loop
--                               so that they correspond. */
--                              if(RcvrEnDly & 1) {
--                                      PatternA = 1;
--                                      PatternB = 0;
--                              } else {
--                                      /* Even step */
--                                      PatternA = 0;
--                                      PatternB = 1;
--                              }
--
--                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0, PatternA); /* rank 0 of DIMM, testpattern 0 */
--                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0B, PatternB); /* rank 0 of DIMM, testpattern 1 */
--                              if(_2Ranks) {
--                                      mct_Write1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr1, PatternA); /*rank 1 of DIMM, testpattern 0 */
--                                      mct_Write1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr1B, PatternB); /*rank 1 of DIMM, testpattern 1 */
--                              }
--
--                              mct_SetRcvrEnDly_D(pDCTstat, RcvrEnDly, 0, 
Channel, Receiver, dev, index_reg, Addl_Index, Pass);
--
--                              CurrTest = DQS_FAIL;
--                              CurrTestSide0 = DQS_FAIL;
--                              CurrTestSide1 = DQS_FAIL;
--
--                              mct_Read1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0); /*cache fills */
--                              Test0 = mct_CompareTestPatternQW0_D(pMCTstat, 
pDCTstat, TestAddr0, Channel, PatternA, Pass);/* ROM vs cache compare */
--                              proc_IOCLFLUSH_D(TestAddr0);
--                              ResetDCTWrPtr_D(dev, index_reg, Addl_Index);
--
--                              print_debug_dqs("\t\t\tTrainRcvEn542: Test0 
result ", Test0, 3);
--
--                              /* != 0x00 mean pass */
--
--                              if(Test0 == DQS_PASS) {
--                                      mct_Read1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr0B);        /*cache fills */
--                                      /* ROM vs cache compare */
--                                      Test1 = 
mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr0B, Channel, PatternB, 
Pass);
--                                      proc_IOCLFLUSH_D(TestAddr0B);
--                                      ResetDCTWrPtr_D(dev, index_reg, 
Addl_Index);
--
--                                      print_debug_dqs("\t\t\tTrainRcvEn543: 
Test1 result ", Test1, 3);
-+                              if (all_lanes_trained)
-+                                      break;
- 
--                                      if(Test1 == DQS_PASS) {
--                                              CurrTestSide0 = DQS_PASS;
-+                              /* 2.8.9.9.2 (7 A)
-+                              * Loop over all ranks
-+                              */
-+                              for (rank = 0; rank < (_2Ranks + 1); rank++) {
-+                                      /* 2.8.9.9.2 (7 A a-d)
-+                                       * Read the first test address of the 
current rank
-+                                       * Store the first data beat for 
analysis
-+                                       * Reset read pointer in the DRAM 
controller FIFO
-+                                       * Read the second test address of the 
current rank
-+                                       * Store the first data beat for 
analysis
-+                                       * Reset read pointer in the DRAM 
controller FIFO
-+                                       */
-+                                      if (rank & 1) {
-+                                              /* 2.8.9.9.2 (7 D)
-+                                               * Invert read instructions to 
alternate data read order on the bus
-+                                               */
-+                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0B:TestAddr1B);
-+                                              result_qword2 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0B:TestAddr1B, Channel));
-+                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
-+                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0:TestAddr1);
-+                                              result_qword1 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0:TestAddr1, Channel));
-+                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
-+                                      } else {
-+                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0:TestAddr1);
-+                                              result_qword1 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0:TestAddr1, Channel));
-+                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
-+                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0B:TestAddr1B);
-+                                              result_qword2 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0B:TestAddr1B, Channel));
-+                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
-                                       }
--                              }
--                              if(_2Ranks) {
--                                      mct_Read1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr1); /*cache fills */
--                                      /* ROM vs cache compare */
--                                      Test0 = 
mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr1, Channel, PatternA, 
Pass);
--                                      proc_IOCLFLUSH_D(TestAddr1);
--                                      ResetDCTWrPtr_D(dev, index_reg, 
Addl_Index);
--
--                                      print_debug_dqs("\t\t\tTrainRcvEn544: 
Test0 result ", Test0, 3);
--
--                                      if(Test0 == DQS_PASS) {
--                                              
mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1B);        /*cache fills */
--                                              /* ROM vs cache compare */
--                                              Test1 = 
mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr1B, Channel, PatternB, 
Pass);
--                                              proc_IOCLFLUSH_D(TestAddr1B);
--                                              ResetDCTWrPtr_D(dev, index_reg, 
Addl_Index);
--
--                                              
print_debug_dqs("\t\t\tTrainRcvEn545: Test1 result ", Test1, 3);
--                                              if(Test1 == DQS_PASS) {
--                                                      CurrTestSide1 = 
DQS_PASS;
-+                                      /* 2.8.9.9.2 (7 A e)
-+                                       * Compare both read patterns and flag 
passing ranks/lanes
-+                                       */
-+                                      uint8_t result_lane_byte1;
-+                                      uint8_t result_lane_byte2;
-+                                      for (lane = 0; lane < 8; lane++) {
-+                                              if (trained[lane] == 1) {
-+#if DQS_TRAIN_DEBUG > 0
-+                                                      
print_debug_dqs("\t\t\t\t\t\t\t\t lane already trained: ", lane, 4);
-+#endif
-+                                                      continue;
-                                               }
-+
-+                                              result_lane_byte1 = 
(result_qword1 >> (lane * 8)) & 0xff;
-+                                              result_lane_byte2 = 
(result_qword2 >> (lane * 8)) & 0xff;
-+                                              if ((result_lane_byte1 == 0x55) 
&& (result_lane_byte2 == 0xaa))
-+                                                      
data_test_pass_sr[rank][lane] = 1;
-+                                              else
-+                                                      
data_test_pass_sr[rank][lane] = 0;
-+#if DQS_TRAIN_DEBUG > 0
-+                                              
print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0x55, "  |  ", result_lane_byte1, 4);
-+                                              
print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0xaa, "  |  ", result_lane_byte2, 4);
-+#endif
-                                       }
-                               }
- 
--                              if(_2Ranks) {
--                                      if ((CurrTestSide0 == DQS_PASS) && 
(CurrTestSide1 == DQS_PASS)) {
--                                              CurrTest = DQS_PASS;
-+                              /* 2.8.9.9.2 (7 B)
-+                               * If DIMM is dual rank, only use delays that 
pass testing for both ranks
-+                               */
-+                              for (lane = 0; lane < 8; lane++) {
-+                                      if (_2Ranks) {
-+                                              if 
((data_test_pass_sr[0][lane]) && (data_test_pass_sr[1][lane]))
-+                                                      data_test_pass[lane] = 
1;
-+                                              else
-+                                                      data_test_pass[lane] = 
0;
-+                                      } else {
-+                                              data_test_pass[lane] = 
data_test_pass_sr[0][lane];
-                                       }
--                              } else if (CurrTestSide0 == DQS_PASS) {
--                                      CurrTest = DQS_PASS;
-                               }
- 
--                              /* record first pass DqsRcvEn to stack */
--                              valid = mct_SavePassRcvEnDly_D(pDCTstat, 
RcvrEnDly, Channel, Receiver, Pass);
-+                              /* 2.8.9.9.2 (7 E)
-+                               * For each lane, update the DQS receiver delay 
setting in support of next iteration
-+                               */
-+                              for (lane = 0; lane < 8; lane++) {
-+                                      if (trained[lane] == 1)
-+                                              continue;
-+
-+                                      /* 2.8.9.9.2 (7 C a)
-+                                       * Save the total delay of the first 
success after a failure for later use
-+                                       */
-+                                      if ((data_test_pass[lane] == 1) && 
(data_test_pass_prev[lane] == 0)) {
-+                                              candidate_total_delay[lane] = 
current_total_delay[lane];
-+                                              window_det_toggle[lane] = 0;
-+                                      }
- 
--                              /* Break(1:RevF,2:DR) or not(0) FIXME: This 
comment deosn't make sense */
--                              if(valid == 2 || (LastTest == DQS_FAIL && valid 
== 1)) {
--                                      RcvrEnDlyRmin = RcvrEnDly;
--                                      break;
-+                                      /* 2.8.9.9.2 (7 C b)
-+                                       * If the current delay failed testing 
add 1/8 UI to the current delay
-+                                       */
-+                                      if (data_test_pass[lane] == 0)
-+                                              current_total_delay[lane] += 
0x4;
-+
-+                                      /* 2.8.9.9.2 (7 C c)
-+                                       * If the current delay passed testing 
alternately add either 1/32 UI or 1/4 UI to the current delay
-+                                       * If 1.25 UI of delay have been added 
with no failures the lane is considered trained
-+                                       */
-+                                      if (data_test_pass[lane] == 1) {
-+                                              /* See if lane is trained */
-+                                              if ((current_total_delay[lane] 
- candidate_total_delay[lane]) >= 0x28) {
-+                                                      trained[lane] = 1;
-+
-+                                                      /* Calculate and set 
final lane delay value
-+                                                       * The final delay is 
the candidate delay + 7/8 UI
-+                                                       */
-+                                                      
current_total_delay[lane] = candidate_total_delay[lane] + 0x1c;
-+                                              } else {
-+                                                      if 
(window_det_toggle[lane] == 0) {
-+                                                              
current_total_delay[lane] += 0x1;
-+                                                              
window_det_toggle[lane] = 1;
-+                                                      } else {
-+                                                              
current_total_delay[lane] += 0x8;
-+                                                              
window_det_toggle[lane] = 0;
-+                                                      }
-+                                              }
-+                                      }
-                               }
- 
--                              LastTest = CurrTest;
--
--                              /* swap the rank 0 pointers */
--                              tmp = TestAddr0;
--                              TestAddr0 = TestAddr0B;
--                              TestAddr0B = tmp;
--
--                              /* swap the rank 1 pointers */
--                              tmp = TestAddr1;
--                              TestAddr1 = TestAddr1B;
--                              TestAddr1B = tmp;
--
--                              print_debug_dqs("\t\t\tTrainRcvEn56: RcvrEnDly 
", RcvrEnDly, 3);
-+                              /* Update delays in hardware */
-+                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
- 
--                              RcvrEnDly++;
--
--                      }       /* while RcvrEnDly */
--
--                      print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDly ", 
RcvrEnDly, 2);
--                      print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDlyRmin ", 
RcvrEnDlyRmin, 3);
--                      print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDlyLimit ", 
RcvrEnDlyLimit, 3);
--                      if(RcvrEnDlyRmin == RcvrEnDlyLimit) {
--                              /* no passing window */
--                              pDCTstat->ErrStatus |= 1 << SB_NORCVREN;
--                              Errors |= 1 << SB_NORCVREN;
--                              pDCTstat->ErrCode = SC_FatalErr;
-+                              /* Save previous results for comparison in the 
next iteration */
-+                              for (lane = 0; lane < 8; lane++)
-+                                      data_test_pass_prev[lane] = 
data_test_pass[lane];
-                       }
- 
--                      if(RcvrEnDly > (RcvrEnDlyLimit - 1)) {
--                              /* passing window too narrow, too far delayed*/
--                              pDCTstat->ErrStatus |= 1 << SB_SmallRCVR;
--                              Errors |= 1 << SB_SmallRCVR;
--                              pDCTstat->ErrCode = SC_FatalErr;
--                              RcvrEnDly = RcvrEnDlyLimit - 1;
--                              pDCTstat->CSTrainFail |= 1 << Receiver;
--                              pDCTstat->DimmTrainFail |= 1 << (Receiver + 
Channel);
--                      }
--
--                      /* CHB_D0_B0_RCVRDLY set in mct_Average_RcvrEnDly_Pass 
*/
--                      mct_Average_RcvrEnDly_Pass(pDCTstat, RcvrEnDly, 
RcvrEnDlyLimit, Channel, Receiver, Pass);
-+#if DQS_TRAIN_DEBUG > 0
-+                      for (lane = 0; lane < 8; lane++)
-+                              print_debug_dqs_pair("\t\tTrainRcvEn55: Lane ", 
lane, " current_total_delay ", current_total_delay[lane], 2);
-+#endif
- 
--                      mct_SetFinalRcvrEnDly_D(pDCTstat, RcvrEnDly, 
Final_Value, Channel, Receiver, dev, index_reg, Addl_Index, Pass);
-+                      /* Find highest delay value and save for later use */
-+                      for (lane = 0; lane < 8; lane++)
-+                              if (current_total_delay[lane] > CTLRMaxDelay)
-+                                      CTLRMaxDelay = 
current_total_delay[lane];
- 
--                      if(pDCTstat->ErrStatus & (1 << SB_SmallRCVR)) {
--                              Errors |= 1 << SB_SmallRCVR;
-+                      /* See if any lanes failed training, and set error 
flags appropriately
-+                       * For all trained lanes, save delay values for later 
use
-+                       */
-+                      for (lane = 0; lane < 8; lane++) {
-+                              if (trained[lane]) {
-+                                      
pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1][lane] = 
current_total_delay[lane];
-+                              } else {
-+                                      printk(BIOS_WARNING, "TrainRcvrEn: 
WARNING: Lane %d of receiver %d on channel %d failed training!\n", lane, 
Receiver, Channel);
-+
-+                                      /* Set error flags */
-+                                      pDCTstat->ErrStatus |= 1 << SB_NORCVREN;
-+                                      Errors |= 1 << SB_NORCVREN;
-+                                      pDCTstat->ErrCode = SC_FatalErr;
-+                                      pDCTstat->CSTrainFail |= 1 << Receiver;
-+                                      pDCTstat->DimmTrainFail |= 1 << 
(Receiver + Channel);
-+                              }
-                       }
- 
--                      RcvrEnDly += Pass1MemClkDly;
--                      if(RcvrEnDly > CTLRMaxDelay) {
--                              CTLRMaxDelay = RcvrEnDly;
--                      }
-+                      /* 2.8.9.9.2 (8)
-+                       * Flush the receiver FIFO
-+                       * Write one full cache line of non-0x55/0xaa data to 
one of the test addresses, then read it back to flush the FIFO
-+                       */
- 
--              }       /* while Receiver */
-+                      WriteLNTestPattern(TestAddr0 << 8, (uint8_t 
*)TestPattern2_D, 1);
-+                      mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0);
-+              }
-               MaxDelay_CH[Channel] = CTLRMaxDelay;
--      }       /* for Channel */
-+      }
- 
-       CTLRMaxDelay = MaxDelay_CH[0];
-       if (MaxDelay_CH[1] > CTLRMaxDelay)
-@@ -428,31 +612,31 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
- 
- #if DQS_TRAIN_DEBUG > 0
-       {
--              u8 Channel;
-+              u8 ChannelDTD;
-               printk(BIOS_DEBUG, "TrainRcvrEn: CH_MaxRdLat:\n");
--              for(Channel = 0; Channel<2; Channel++) {
-+              for(ChannelDTD = 0; ChannelDTD<2; ChannelDTD++) {
-                       printk(BIOS_DEBUG, "Channel:%x: %x\n",
--                             Channel, pDCTstat->CH_MaxRdLat[Channel]);
-+                             ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD]);
-               }
-       }
- #endif
- 
- #if DQS_TRAIN_DEBUG > 0
-       {
--              u8 val;
--              u8 Channel, Receiver;
-+              u16 valDTD;
-+              u8 ChannelDTD, ReceiverDTD;
-               u8 i;
--              u8 *p;
-+              u16 *p;
- 
-               printk(BIOS_DEBUG, "TrainRcvrEn: CH_D_B_RCVRDLY:\n");
--              for(Channel = 0; Channel < 2; Channel++) {
--                      printk(BIOS_DEBUG, "Channel:%x\n", Channel);
--                      for(Receiver = 0; Receiver<8; Receiver+=2) {
--                              printk(BIOS_DEBUG, "\t\tReceiver:%x:", 
Receiver);
--                              p = 
pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver>>1];
-+              for(ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
-+                      printk(BIOS_DEBUG, "Channel:%x\n", ChannelDTD);
-+                      for(ReceiverDTD = 0; ReceiverDTD<8; ReceiverDTD+=2) {
-+                              printk(BIOS_DEBUG, "\t\tReceiver:%x:", 
ReceiverDTD);
-+                              p = 
pDCTstat->CH_D_B_RCVRDLY[ChannelDTD][ReceiverDTD>>1];
-                               for (i=0;i<8; i++) {
--                                      val  = p[i];
--                                      printk(BIOS_DEBUG, "%x ", val);
-+                                      valDTD = p[i];
-+                                      printk(BIOS_DEBUG, " %03x", valDTD);
-                               }
-                               printk(BIOS_DEBUG, "\n");
-                       }
-@@ -475,15 +659,6 @@ u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 
dct)
-       }
- }
- 
--static void mct_SetFinalRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 
RcvrEnDly, u8 where, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 
Addl_Index, u8 Pass/*, u8 *p*/)
--{
--      /*
--       * Program final DqsRcvEnDly to additional index for DQS receiver
--       *  enabled delay
--       */
--      mct_SetRcvrEnDly_D(pDCTstat, RcvrEnDly, where, Channel, Receiver, dev, 
index_reg, Addl_Index, Pass);
--}
--
- static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat)
- {
-       u8 ch_end, ch;
-@@ -514,17 +689,20 @@ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc 
*pDCTstat)
-  * Function only used once so it was inlined.
-  */
- 
--void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly,
-+/* Set F2x[1, 0]9C_x[2B:10] DRAM DQS Receiver Enable Timing Control Registers
-+ * See BKDG Rev. 3.62 page 268 for more information
-+ */
-+void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly,
-                       u8 FinalValue, u8 Channel, u8 Receiver, u32 dev,
-                       u32 index_reg, u8 Addl_Index, u8 Pass)
- {
-       u32 index;
-       u8 i;
--      u8 *p;
-+      u16 *p;
-       u32 val;
- 
--      if(RcvrEnDly == 0xFE) {
--              /*set the boudary flag */
-+      if(RcvrEnDly == 0x1fe) {
-+              /*set the boundary flag */
-               pDCTstat->Status |= 1 << SB_DQSRcvLimit;
-       }
- 
-@@ -543,27 +721,57 @@ void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, 
u8 RcvrEnDly,
-               val = Get_NB32_index_wait(dev, index_reg, index);
-               if(i & 1) {
-                       /* odd byte lane */
--                      val &= ~(0xFF << 16);
--                      val |= (RcvrEnDly << 16);
-+                      val &= ~(0x1ff << 16);
-+                      val |= ((RcvrEnDly & 0x1ff) << 16);
-               } else {
-                       /* even byte lane */
--                      val &= ~0xFF;
--                      val |= RcvrEnDly;
-+                      val &= ~0x1ff;
-+                      val |= (RcvrEnDly & 0x1ff);
-               }
-               Set_NB32_index_wait(dev, index_reg, index, val);
-       }
- 
- }
- 
--static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u8 
DQSRcvEnDly)
-+/* Calculate MaxRdLatency
-+ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.5
-+ */
-+static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, 
u16 DQSRcvEnDly)
- {
-       u32 dev;
-       u32 reg;
--      u16 SubTotal;
-+      u32 SubTotal;
-       u32 index_reg;
-       u32 reg_off;
-       u32 val;
--      u32 valx;
-+
-+      uint8_t cpu_val_n;
-+      uint8_t cpu_val_p;
-+
-+      u16 freq_tab[] = {400, 533, 667, 800};
-+
-+      /* Set up processor-dependent values */
-+      if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
-+              /* Revision D and above */
-+              cpu_val_n = 4;
-+              cpu_val_p = 29;
-+      } else if (pDCTstat->LogicalCPUID & AMD_DR_Cx) {
-+              /* Revision C */
-+              uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
-+              if ((package_type == PT_L1)             /* Socket F (1207) */
-+                      || (package_type == PT_M2)      /* Socket AM3 */
-+                      || (package_type == PT_S1)) {   /* Socket S1g<x> */
-+                      cpu_val_n = 10;
-+                      cpu_val_p = 11;
-+              } else {
-+                      cpu_val_n = 4;
-+                      cpu_val_p = 29;
-+              }
-+      } else {
-+              /* Revision B and below */
-+              cpu_val_n = 10;
-+              cpu_val_p = 11;
-+      }
- 
-       if(pDCTstat->GangedMode)
-               Channel = 0;
-@@ -598,49 +806,32 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc 
*pDCTstat, u8 Channel, u8 DQ
-       val = Get_NB32(dev, 0x78 + reg_off);
-       SubTotal += 8 - (val & 0x0f);
- 
--      /* Convert bits 7-5 (also referred to as the course delay) of
-+      /* Convert bits 7-5 (also referred to as the coarse delay) of
-        * the current (or worst case) DQS receiver enable delay to
-        * 1/2 MEMCLKs units, rounding up, and add this to the sub-total.
-        */
--      SubTotal += DQSRcvEnDly >> 5;   /*BOZO-no rounding up */
-+      SubTotal += DQSRcvEnDly >> 5;   /* Retrieve gross delay portion of 
value */
- 
--      /* Add 5.5 to the sub-total. 5.5 represents part of the
-+      /* Add "P" to the sub-total. "P" represents part of the
-        * processor specific constant delay value in the DRAM
-        * clock domain.
-        */
-       SubTotal <<= 1;         /*scale 1/2 MemClk to 1/4 MemClk */
--      SubTotal += 11;         /*add 5.5 1/2MemClk */
-+      SubTotal += cpu_val_p;  /*add "P" 1/2MemClk */
-+      SubTotal >>= 1;         /*scale 1/4 MemClk back to 1/2 MemClk */
- 
-       /* Convert the sub-total (in 1/2 MEMCLKs) to northbridge
--       * clocks (NCLKs) as follows (assuming DDR400 and assuming
--       * that no P-state or link speed changes have occurred).
-+       * clocks (NCLKs)
-        */
-+      SubTotal *= 200 * ((Get_NB32(pDCTstat->dev_nbmisc, 0xd4) & 0x1f) + 4);
-+      SubTotal /= freq_tab[((Get_NB32(pDCTstat->dev_dct, 0x94 + reg_off) & 
0x7) - 3)];
-+      SubTotal = (SubTotal + (2 - 1)) / 2;    /* Round up */
- 
--      /* New formula:
--       * SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */
--      val = Get_NB32(dev, 0x94 + reg_off);
--
--      /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
--      val &= 7;
--      if (val >= 3) {
--              val <<= 1;
--      } else
--              val += 3;
--      valx = val << 2;
--
--      val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4);
--      SubTotal *= ((val & 0x1f) + 4 ) * 3;
--
--      SubTotal /= valx;
--      if (SubTotal % valx) {  /* round up */
--              SubTotal++;
--      }
--
--      /* Add 5 NCLKs to the sub-total. 5 represents part of the
-+      /* Add "N" NCLKs to the sub-total. "N" represents part of the
-        * processor specific constant value in the northbridge
-        * clock domain.
-        */
--      SubTotal += 5;
-+      SubTotal += (cpu_val_n) / 2;
- 
-       pDCTstat->CH_MaxRdLat[Channel] = SubTotal;
-       if(pDCTstat->GangedMode) {
-@@ -659,143 +850,6 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc 
*pDCTstat, u8 Channel, u8 DQ
-       Set_NB32(dev, reg, val);
- }
- 
--static u8 mct_SavePassRcvEnDly_D(struct DCTStatStruc *pDCTstat,
--                      u8 rcvrEnDly, u8 Channel,
--                      u8 receiver, u8 Pass)
--{
--      u8 i;
--      u8 mask_Saved, mask_Pass;
--      u8 *p;
--
--      /* calculate dimm offset
--       * not needed for CH_D_B_RCVRDLY array
--       */
--
--      /* cmp if there has new DqsRcvEnDly to be recorded */
--      mask_Pass = pDCTstat->DqsRcvEn_Pass;
--
--      if(Pass == SecondPass) {
--              mask_Pass = ~mask_Pass;
--      }
--
--      mask_Saved = pDCTstat->DqsRcvEn_Saved;
--      if(mask_Pass != mask_Saved) {
--
--              /* find desired stack offset according to channel/dimm/byte */
--              if(Pass == SecondPass) {
--                      /* FIXME: SecondPass is never used for Barcelona p = 
pDCTstat->CH_D_B_RCVRDLY_1[Channel][receiver>>1]; */
--                      p = 0; /* Keep the compiler happy. */
--              } else {
--                      mask_Saved &= mask_Pass;
--                      p = pDCTstat->CH_D_B_RCVRDLY[Channel][receiver>>1];
--              }
--              for(i=0; i < 8; i++) {
--                      /* cmp per byte lane */
--                      if(mask_Pass & (1 << i)) {
--                              if(!(mask_Saved & (1 << i))) {
--                                      /* save RcvEnDly to stack, according to
--                                      the related Dimm/byte lane */
--                                      p[i] = (u8)rcvrEnDly;
--                                      mask_Saved |= 1 << i;
--                              }
--                      }
--              }
--              pDCTstat->DqsRcvEn_Saved = mask_Saved;
--      }
--      return mct_SaveRcvEnDly_D_1Pass(pDCTstat, Pass);
--}
--
--static u8 mct_CompareTestPatternQW0_D(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat,
--                                      u32 addr, u8 channel,
--                                      u8 pattern, u8 Pass)
--{
--      /* Compare only the first beat of data.  Since target addrs are cache
--       * line aligned, the Channel parameter is used to determine which
--       * cache QW to compare.
--       */
--
--      u8 *test_buf;
--      u8 i;
--      u8 result;
--      u8 value;
--
--      if(Pass == FirstPass) {
--              if(pattern==1) {
--                      test_buf = (u8 *)TestPattern1_D;
--              } else {
--                      test_buf = (u8 *)TestPattern0_D;
--              }
--      } else {                /* Second Pass */
--              test_buf = (u8 *)TestPattern2_D;
--      }
--
--      SetUpperFSbase(addr);
--      addr <<= 8;
--
--      if((pDCTstat->Status & (1<<SB_128bitmode)) && channel ) {
--              addr += 8;      /* second channel */
--              test_buf += 8;
--      }
--
--      print_debug_dqs_pair("\t\t\t\t\t\t  test_buf = ", (u32)test_buf, "  |  
addr_lo = ", addr,  4);
--      for (i=0; i<8; i++, addr ++) {
--              value = read32_fs(addr);
--              print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", test_buf[i], "  |  ", 
value, 4);
--
--              if (value == test_buf[i]) {
--                      pDCTstat->DqsRcvEn_Pass |= (1<<i);
--              } else {
--                      pDCTstat->DqsRcvEn_Pass &= ~(1<<i);
--              }
--      }
--
--      result = DQS_FAIL;
--
--      if (Pass == FirstPass) {
--              /* if first pass, at least one byte lane pass
--               * ,then DQS_PASS=1 and will set to related reg.
--               */
--              if(pDCTstat->DqsRcvEn_Pass != 0) {
--                      result = DQS_PASS;
--              } else {
--                      result = DQS_FAIL;
--              }
--
--      } else {
--              /* if second pass, at least one byte lane fail
--               * ,then DQS_FAIL=1 and will set to related reg.
--               */
--              if(pDCTstat->DqsRcvEn_Pass != 0xFF) {
--                      result = DQS_FAIL;
--              } else {
--                      result = DQS_PASS;
--              }
--      }
--
--      /* if second pass, we can't find the fail until FFh,
--       * then let it fail to save the final delay
--       */
--      if((Pass == SecondPass) && (pDCTstat->Status & (1 << SB_DQSRcvLimit))) {
--              result = DQS_FAIL;
--              pDCTstat->DqsRcvEn_Pass = 0;
--      }
--
--      /* second pass needs to be inverted
--       * FIXME? this could be inverted in the above code to start with...
--       */
--      if(Pass == SecondPass) {
--              if (result == DQS_PASS) {
--                      result = DQS_FAIL;
--              } else if (result == DQS_FAIL) { /* FIXME: doesn't need to be 
else if */
--                      result = DQS_PASS;
--              }
--      }
--
--
--      return result;
--}
--
- static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
-                               struct DCTStatStruc *pDCTstat)
- {
-@@ -854,7 +908,7 @@ void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 
Channel)
-       u32 index_reg;
-       u32 index;
-       u8 ChipSel;
--      u8 *p;
-+      u16 *p;
-       u32 val;
- 
-       dev = pDCTstat->dev_dct;
-@@ -884,7 +938,7 @@ static void CalcEccDQSRcvrEn_D(struct MCTStatStruc 
*pMCTstat,
- 
-       for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) {
-               if(mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, ChipSel)) 
{
--                      u8 *p;
-+                      u16 *p;
-                       p = pDCTstat->CH_D_B_RCVRDLY[Channel][ChipSel>>1];
- 
-                       /* DQS Delay Value of Data Bytelane
-@@ -920,6 +974,10 @@ static void CalcEccDQSRcvrEn_D(struct MCTStatStruc 
*pMCTstat,
-       SetEccDQSRcvrEn_D(pDCTstat, Channel);
- }
- 
-+/* 2.8.9.9.4
-+ * ECC Byte Lane Training
-+ * DQS Receiver Enable Delay
-+ */
- void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat,
-                       struct DCTStatStruc *pDCTstatA)
- {
-@@ -1017,7 +1075,9 @@ static void fenceDynTraining_D(struct MCTStatStruc 
*pMCTstat,
-               avRecValue -= 3;
-       else
-       */
--      if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
-+      if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
-+              avRecValue -= 8;
-+      else if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
-               avRecValue -= 8;
-       else if (pDCTstat->LogicalCPUID & AMD_DR_Bx)
-               avRecValue -= 8;
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
-index c009756..f01e011 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -36,17 +37,12 @@ u32 SetupDqsPattern_1PassB(u8 pass)
-       return (u32) TestPattern0_D;
- }
- 
--u8  mct_Get_Start_RcvrEnDly_1Pass(u8 pass)
--{
--      return 0;
--}
--
--static u8 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 
Channel, u8 Receiver,
-+static u16 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 
Channel, u8 Receiver,
-                                       u8 Pass)
- {
--      u8 i, MaxValue;
--      u8 *p;
--      u8 val;
-+      u16 i, MaxValue;
-+      u16 *p;
-+      u16 val;
- 
-       MaxValue = 0;
-       p = pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1];
-@@ -76,8 +72,8 @@ u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, 
u8 pass)
-       return ret;
- }
- 
--u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
--                              u8 RcvrEnDly, u8 RcvrEnDlyLimit,
-+u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
-+                              u16 RcvrEnDly, u16 RcvrEnDlyLimit,
-                               u8 Channel, u8 Receiver, u8 Pass)
- 
- {
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c
-index b01889d..796febc 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -74,15 +75,15 @@ u8 mct_Get_Start_RcvrEnDly_Pass(struct DCTStatStruc 
*pDCTstat,
-       return RcvrEnDly;
- }
- 
--u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
--                              u8 RcvrEnDly, u8 RcvrEnDlyLimit,
-+u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
-+                              u16 RcvrEnDly, u16 RcvrEnDlyLimit,
-                               u8 Channel, u8 Receiver, u8 Pass)
- {
-       u8 i;
--      u8 *p;
--      u8 *p_1;
--      u8 val;
--      u8 val_1;
-+      u16 *p;
-+      u16 *p_1;
-+      u16 val;
-+      u16 val_1;
-       u8 valid = 1;
-       u8 bn;
- 
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
-index ea5c8c7..920f514 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -191,10 +192,10 @@ static void maxRdLatencyTrain_D(struct MCTStatStruc 
*pMCTstat,
- 
- #if DQS_TRAIN_DEBUG > 0
-       {
--              u8 Channel;
-+              u8 ChannelDTD;
-               printk(BIOS_DEBUG, "maxRdLatencyTrain: CH_MaxRdLat:\n");
--              for(Channel = 0; Channel<2; Channel++) {
--                      printk(BIOS_DEBUG, "Channel: %02x: %02x\n", Channel, 
pDCTstat->CH_MaxRdLat[Channel]);
-+              for(ChannelDTD = 0; ChannelDTD<2; ChannelDTD++) {
-+                      printk(BIOS_DEBUG, "Channel: %02x: %02x\n", ChannelDTD, 
pDCTstat->CH_MaxRdLat[ChannelDTD]);
-               }
-       }
- #endif
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
-index cdeae49..1c3e322 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -58,9 +59,9 @@ void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
-       pDCTstat->C_DCTPtr[dct]->LogicalCPUID = pDCTstat->LogicalCPUID;
- 
-       for (dimm = 0; dimm < MAX_DIMMS; dimm++) {
--              if (DimmValid & (1 << dimm))
-+              if (DimmValid & (1 << (dimm << 1)))
-                       pDCTstat->C_DCTPtr[dct]->DimmPresent[dimm] = 1;
--              if (Dimmx8Present & (1 << dimm))
-+              if (Dimmx8Present & (1 << (dimm << 1)))
-                       pDCTstat->C_DCTPtr[dct]->DimmX8Present[dimm] = 1;
-       }
- 
-@@ -88,9 +89,9 @@ void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
-               u8  DimmRanks;
-               if (DimmValid & (1 << (dimm << 1))) {
-                       DimmRanks = 1;
--                      if (pDCTstat->DimmDRPresent & (1 << (dimm+dct)))
-+                      if (pDCTstat->DimmDRPresent & (1 << ((dimm << 1) + 
dct)))
-                               DimmRanks = 2;
--                      else if (pDCTstat->DimmQRPresent & (1 << (dimm+dct)))
-+                      else if (pDCTstat->DimmQRPresent & (1 << ((dimm << 1) + 
dct)))
-                               DimmRanks = 4;
-               } else
-                       DimmRanks = 0;
-@@ -249,35 +250,6 @@ static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
-       }
- }
- 
--/* Multiply the previously saved delay values in Pass 1, step #5 by
--   (target frequency)/400 to find the gross and fine delay initialization
--   values at the target frequency.
-- */
--void MultiplyDelay(struct MCTStatStruc *pMCTstat,
--                                      struct DCTStatStruc *pDCTstat, u8 dct)
--{
--      u16 index;
--      u8 Multiplier;
--      u8 gross, fine;
--      u16 total;
--
--      Multiplier = pDCTstat->TargetFreq;
--
--      for (index=0; index < MAX_BYTE_LANES*MAX_LDIMMS; index ++) {
--              gross = pDCTstat->C_DCTPtr[dct]->WLGrossDelay[index];
--              fine = pDCTstat->C_DCTPtr[dct]->WLFineDelay[index];
--
--              total = gross << 5 | fine;
--              total *= Multiplier;
--              if (total % 3)
--                      total = total / 3 + 1;
--              else
--                      total = total / 3;
--              pDCTstat->C_DCTPtr[dct]->WLGrossDelay[index] = (total & 0xFF) 
>> 5;
--              pDCTstat->C_DCTPtr[dct]->WLFineDelay[index] = total & 0x1F;
--      }
--}
--
- /*
-  * the DRAM controller to bring the DRAMs out of self refresh mode.
-  */
-@@ -352,9 +324,9 @@ void SetTargetFreq(struct MCTStatStruc *pMCTstat,
- 
-               if (!DCT1Present)
-                       pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
--              else if (pDCTstat->GangedMode) {
-+              else if (pDCTstat->GangedMode)
-                       pDCTstat->CSPresent = 0;
--              } else
-+              else
-                       pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1];
- 
-               FreqChgCtrlWrd(pMCTstat, pDCTstat);
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-index 212a348..c76476b 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-@@ -2,6 +2,7 @@
-  * This file is part of the coreboot project.
-  *
-  * Copyright (C) 2010 Advanced Micro Devices, Inc.
-+ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
-  *
-  * 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
-@@ -235,6 +236,65 @@ u32 swapBankBits(sDCTStruct *pDCTData, u32 MRSValue)
-       return MRSValue;
- }
- 
-+static uint16_t unbuffered_dimm_nominal_termination_emrs(uint8_t 
number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank)
-+{
-+      uint16_t term;
-+
-+      /* FIXME
-+       * Mainboards need to be able to specify the maximum number of DIMMs 
installable per channel
-+       * For now assume a maximum of 2 DIMMs per channel can be installed
-+       */
-+      uint8_t MaxDimmsInstallable = 2;
-+
-+      if (number_of_dimms == 1) {
-+              if (MaxDimmsInstallable < 3) {
-+                      term = 0x04;    /* Rtt_Nom=RZQ/4=60 Ohm */
-+              } else {
-+                      if (rank_count == 1) {
-+                              term = 0x04;    /* Rtt_Nom=RZQ/4=60 Ohm */
-+                      } else {
-+                              if (rank == 0)
-+                                      term = 0x04;    /* Rtt_Nom=RZQ/4=60 Ohm 
*/
-+                              else
-+                                      term = 0x00;    /* Rtt_Nom=OFF */
-+                      }
-+              }
-+      } else {
-+              if (frequency_index < 5)
-+                      term = 0x0044;  /* Rtt_Nom=RZQ/6=40 Ohm */
-+              else
-+                      term = 0x0204;  /* Rtt_Nom=RZQ/8=30 Ohm */
-+      }
-+
-+      return term;
-+}
-+
-+static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t 
number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank)
-+{
-+      uint16_t term;
-+
-+      /* FIXME
-+       * Mainboards need to be able to specify the maximum number of DIMMs 
installable per channel
-+       * For now assume a maximum of 2 DIMMs per channel can be installed
-+       */
-+      uint8_t MaxDimmsInstallable = 2;
-+
-+      if (number_of_dimms == 1) {
-+              if (MaxDimmsInstallable < 3) {
-+                      term = 0x00;    /* Rtt_WR=off */
-+              } else {
-+                      if (rank_count == 1)
-+                              term = 0x00;    /* Rtt_WR=off */
-+                      else
-+                              term = 0x200;   /* Rtt_WR=RZQ/4=60 Ohm */
-+              }
-+      } else {
-+              term = 0x400;   /* Rtt_WR=RZQ/2=120 Ohm */
-+      }
-+
-+      return term;
-+}
-+
- 
/*-----------------------------------------------------------------------------
-  *  void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *DCTData, u8 Dimm, 
BOOL WL)
-  *
-@@ -295,48 +355,23 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
-               if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-                       tempW1 = RttNomTargetRegDimm(pMCTData, pDCTData, dimm, 
wl, MemClkFreq, rank);
-               } else {
--                      if (wl)
--                      {
--                              if (pDCTData->MaxDimmsInstalled == 1)
--                              {
--                                      if ((pDCTData->DimmRanks[dimm] == 2) && 
(rank == 0))
--                                      {
--                                              tempW1 = 0x00;  /* Rtt_Nom=OFF 
*/
--                                      }
-+                      if (wl) {
-+                              if (rank == 0) {
-+                                      /* Get Rtt_WR for the current DIMM and 
rank */
-+                                      uint16_t dynamic_term = 
unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-+
-+                                      /* Convert dynamic termination code to 
corresponding nominal termination code */
-+                                      if (dynamic_term == 0x200)
-+                                              tempW1 = 0x04;
-+                                      else if (dynamic_term == 0x400)
-+                                              tempW1 = 0x40;
-                                       else
--                                      {
--                                              tempW1 = 0x04;  /* 
Rtt_Nom=RZQ/4=60 Ohm */
--                                      }
--                              }
--                              else    /* 2 Dimms or more per channel */
--                              {
--                                      if ((pDCTData->DimmRanks[dimm] == 2) && 
(rank == 1))
--                                      {
--                                              tempW1 = 0x00;  /* Rtt_Nom=OFF 
*/
--                                      }
--                                      else
--                                      {
--                                              if (MemClkFreq == 6) {
--                                                      tempW1 = 0x04;  /* 
Rtt_Nom=RZQ/4=60 Ohm */
--                                              } else {
--                                                      tempW1 = 0x40;/* 
Rtt_Nom=RZQ/2=120 Ohm */
--                                              }
--                                      }
--                              }
--                      }
--                      else {  /* 1 or 4 Dimms per channel */
--                              if ((pDCTData->MaxDimmsInstalled == 1) || 
(pDCTData->MaxDimmsInstalled == 4))
--                              {
--                                      tempW1 = 0x04;  /* Rtt_Nom=RZQ/4=60 Ohm 
*/
--                              }
--                              else    /* 2 or 3 Dimms per channel */
--                              {
--                                      if (MemClkFreq < 5) {
--                                              tempW1 = 0x0044;        /* 
Rtt_Nom=RZQ/6=40 Ohm */
--                                      } else {
--                                              tempW1 = 0x0204;        /* 
Rtt_Nom=RZQ/8=30 Ohm */
--                                      }
-+                                              tempW1 = 0x0;
-+                              } else {
-+                                      tempW1 = 
unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-                               }
-+                      } else {
-+                              tempW1 = 
unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-                       }
-               }
-               tempW=tempW|tempW1;
-@@ -353,20 +388,22 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
-                       else
-                       {
-                               /* Disable the output drivers of all other 
ranks for
--                               * the target DIMM. */
-+                               * the target DIMM.
-+                               */
-                               tempW = bitTestSet(tempW1, Qoff);
-                       }
-               }
--              /* program MrsAddress[5,1]=output driver impedance control 
(DIC):
--               * based on F2x[1,0]84[DrvImpCtrl] */
-+              /* Program MrsAddress[5,1]=output driver impedance control 
(DIC):
-+               * based on F2x[1,0]84[DrvImpCtrl]
-+               */
-               tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-                               FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, 
DrvImpCtrlEnd);
--              if (bitTest(tempW1,1))
--              {tempW = bitTestSet(tempW, 5);}
--              if (bitTest(tempW1,0))
--              {tempW = bitTestSet(tempW, 1);}
-+              if (bitTest(tempW1, 1))
-+                      tempW = bitTestSet(tempW, 5);
-+              if (bitTest(tempW1, 0))
-+                      tempW = bitTestSet(tempW, 1);
- 
--              tempW = swapAddrBits_wl(pDCTData,tempW);
-+              tempW = swapAddrBits_wl(pDCTData, tempW);
- 
-               set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-                       DRAM_INIT, MrsAddressStart, MrsAddressEnd, tempW);
-@@ -404,29 +441,10 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
-               if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && 
(pDCTData->Status[DCT_STATUS_REGISTERED]))
-                       tempW+=0x8;
-               /* determine Rtt_WR for WL & Normal mode */
--              if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+              if (pDCTData->Status[DCT_STATUS_REGISTERED])
-                       tempW1 = RttWrRegDimm(pMCTData, pDCTData, dimm, wl, 
MemClkFreq, rank);
--              } else {
--                      if (wl)
--                      {
--                              tempW1 = 0x00;  /* Rtt_WR=off */
--                      }
--                      else
--                      {
--                              if (pDCTData->MaxDimmsInstalled == 1)
--                              {
--                                      tempW1 = 0x00;  /* Rtt_WR=off */
--                              }
--                              else
--                              {
--                                      if (MemClkFreq == 6) {
--                                              tempW1 = 0x200; /* 
Rtt_WR=RZQ/4=60 Ohm */
--                                      } else {
--                                              tempW1 = 0x400; /* Rtt_WR=RZQ/2 
*/
--                                      }
--                              }
--                      }
--              }
-+              else
-+                      tempW1 = 
unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[dimm], rank);
-               tempW=tempW|tempW1;
-               tempW = swapAddrBits_wl(pDCTData,tempW);
-               set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
-@@ -483,38 +501,10 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
-                                       }
- 
-                                       /* determine Rtt_Nom for WL & Normal 
mode */
--                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED])
-                                               tempW1 = 
RttNomNonTargetRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank);
--                                      } else {
--                                              if (wl)
--                                              {
--                                                      if 
((pDCTData->DimmRanks[currDimm] == 2) && (rank == 1))
--                                                      {
--                                                              tempW1 = 0x00;  
/* Rtt_Nom=OFF */
--                                                      }
--                                                      else
--                                                      {
--                                                              if (MemClkFreq 
< 5) {
--                                                                      tempW1 
= 0x0044;/* Rtt_Nom=RZQ/6=40 Ohm */
--                                                              } else {
--                                                                      tempW1 
= 0x0204;/* Rtt_Nom=RZQ/8=30 Ohm */
--                                                              }
--                                                      }
--                                              }
--                                              else {  /* 1 or 4 Dimms per 
channel */
--                                                      if 
(pDCTData->MaxDimmsInstalled == 4)
--                                                      {
--                                                              tempW1 = 0x04;  
/* Rtt_Nom=RZQ/4=60 Ohm */
--                                                      }
--                                                      else {  /* 2 or 3 Dimms 
per channel */
--                                                              if (MemClkFreq 
< 5) {
--                                                                      tempW1 
= 0x0044;        /* Rtt_Nom=RZQ/6=40 Ohm */
--                                                              } else {
--                                                                      tempW1 
= 0x0204;        /* Rtt_Nom=RZQ/8=30 Ohm */
--                                                              }
--                                                      }
--                                              }
--                                      }
-+                                      else
-+                                              tempW1 = 
unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-                                       tempW=tempW|tempW1;
-                                       /* program MrsAddress[5,1]=output 
driver impedance control (DIC):
-                                        * based on F2x[1,0]84[DrvImpCtrl] */
-@@ -560,22 +550,10 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
-                                       if ((pDCTData->LogicalCPUID & 
AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED]))
-                                               tempW+=0x8;
-                                       /* determine Rtt_WR for WL & Normal 
mode */
--                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED]) {
-+                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED])
-                                               tempW1 = RttWrRegDimm(pMCTData, 
pDCTData, currDimm, wl, MemClkFreq, rank);
--                                      } else {
--                                              if (wl)
--                                              {
--                                                      tempW1 = 0x00;  /* 
Rtt_WR=off */
--                                              }
--                                              else
--                                              {
--                                                      if (MemClkFreq == 6) {
--                                                              tempW1 = 0x200; 
/* Rtt_WR=RZQ/4=60 Ohm */
--                                                      } else {
--                                                              tempW1 = 0x400; 
/* Rtt_WR=RZQ/2 */
--                                                      }
--                                              }
--                                      }
-+                                      else
-+                                              tempW1 = 
unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
-                                       tempW=tempW|tempW1;
-                                       tempW = swapAddrBits_wl(pDCTData,tempW);
-                                       set_Bits(pDCTData, pDCTData->CurrDct, 
pDCTData->NodeId, FUN_DCT,
-@@ -646,9 +624,14 @@ void programODT(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm)
-  */
- void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
- {
--      u8 ByteLane, Seed_Gross, Seed_Fine;
-+      u8 ByteLane, Seed_Gross, Seed_Fine, MemClkFreq;
-       u32 Value, Addr;
-       u16 Addl_Data_Offset, Addl_Data_Port;
-+      u16 freq_tab[] = {400, 533, 667, 800};
-+
-+      /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 800MHz */
-+      MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
-+                              FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
- 
-       /* Program F2x[1, 0]9C_x08[WrLvOdt[3:0]] to the proper ODT settings for 
the
-        * current memory subsystem configuration.
-@@ -656,12 +639,13 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct 
*pDCTData, u8 dimm, u8 pass)
-       programODT(pMCTData, pDCTData, dimm);
- 
-       /* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */
--      if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
-+      if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx)) {
-               set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, 
pDCTData->NodeId, FUN_DCT,
-                               DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, 
WrLvOdtEn, (u32)1);
-+      }
-       else
-       {
--              /* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 
0 for Rev.B*/
-+              /* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 
0 for Rev.B */
-               if (pDCTData->DctTrain)
-               {
-                       Addl_Data_Offset=0x198;
-@@ -687,7 +671,6 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, 
u8 dimm, u8 pass)
- 
-       /* Wait 10 MEMCLKs to allow for ODT signal settling. */
-       pMCTData->AgesaDelay(10);
--      ByteLane = 0;
-       if (pass == 1)
-       {
-               if (pDCTData->Status[DCT_STATUS_REGISTERED])
-@@ -705,10 +688,17 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct 
*pDCTData, u8 dimm, u8 pass)
-               }
-               else
-               {
--                      Seed_Gross = 0x00;
--                      Seed_Fine = 0x1A;
-+                      if (MemClkFreq == 6) {
-+                              /* DDR-800 */
-+                              Seed_Gross = 0x00;
-+                              Seed_Fine = 0x1a;
-+                      } else {
-+                              /* Use settings for DDR-400 (interpolated from 
BKDG) */
-+                              Seed_Gross = 0x00;
-+                              Seed_Fine = 0x0d;
-+                      }
-               }
--              while(ByteLane < MAX_BYTE_LANES)
-+              for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
-               {
-                       /* Program an initialization value to registers F2x[1, 
0]9C_x[51:50] and
-                        * F2x[1, 0]9C_x52 to set the gross and fine delay for 
all the byte lane fields
-@@ -720,35 +710,32 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct 
*pDCTData, u8 dimm, u8 pass)
-                        */
-                       pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Gross;
-                       pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Fine;
--                      ByteLane++;
-               }
--      } else if (pDCTData->Status[DCT_STATUS_REGISTERED]) {           /* For 
Pass 2 */
-+      } else {                /* Pass 2 */
-               /* From BKDG, Write Leveling Seed Value. */
--              /* TODO: The unbuffered DIMMs are unstable on the code below. 
So temporarily it is
--               * only for registered DIMMs. */
-               u32 RegisterDelay, SeedTotal;
--              u8 MemClkFreq;
--              u16 freq_tab[] = {400, 533, 667, 800};
--              while(ByteLane < MAX_BYTE_LANES)
-+              for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
-               {
--                      MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, 
pDCTData->NodeId,
--                                            FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
-                       if (pDCTData->Status[DCT_STATUS_REGISTERED])
-                               RegisterDelay = 0x20; /* TODO: ((RCW2 & BIT0) 
== 0) ? 0x20 : 0x30; */
-                       else
-                               RegisterDelay = 0;
--                      SeedTotal = 
(pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1F) |
--                              
pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5;
-+                      SeedTotal = 
(pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) |
-+                              
(pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5);
-                       /* SeedTotalPreScaling = (the total delay value in 
F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization
-                          training) - RegisterDelay. */
--                      /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 
800MHz */
--                      SeedTotal = (u16) (RegisterDelay + ((((u32) SeedTotal - 
RegisterDelay) *
--                                                           
freq_tab[MemClkFreq-3]) / 400));
--                      Seed_Gross = (SeedTotal & 0x20) != 0 ? 1 : 2;
--                      Seed_Fine = SeedTotal & 0x1F;
-+                      SeedTotal = (uint16_t) (RegisterDelay + ((((uint64_t) 
SeedTotal - RegisterDelay) *
-+                                                              
freq_tab[MemClkFreq-3] * 100) / (freq_tab[0] * 100)));
-+                      Seed_Gross = SeedTotal / 32;
-+                      Seed_Fine = SeedTotal & 0x1f;
-+                      if (Seed_Gross == 0)
-+                              Seed_Gross = 0;
-+                      else if (Seed_Gross & 0x1)
-+                              Seed_Gross = 1;
-+                      else
-+                              Seed_Gross = 2;
-                       pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Gross;
-                       pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Fine;
--                      ByteLane ++;
-               }
-       }
- 
-diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c 
b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-index ea32893..6465e13 100644
---- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-+++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-@@ -49,7 +49,7 @@ static const uint16_t ddr3_limits[4] = {800, 666, 533, 400};
- static u16 mctGet_NVbits(u8 index)
- {
-       u16 val = 0;
--      int nvram;
-+      int nvram = 0;
- 
-       switch (index) {
-       case NV_PACK_TYPE:
-@@ -59,6 +59,10 @@ static u16 mctGet_NVbits(u8 index)
-               val = 1;
- #elif CONFIG_CPU_SOCKET_TYPE == 0x13  /* ASB2 */
-               val = 4;
-+#elif CONFIG_CPU_SOCKET_TYPE == 0x14  /* C32 */
-+              val = 5;
-+#elif CONFIG_CPU_SOCKET_TYPE == 0x15  /* G34 */
-+              val = 3;
- //#elif SYSTEM_TYPE == MOBILE
- //            val = 2;
- #endif
-@@ -297,6 +301,8 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc 
*pDCTstat)
-       /* Determine the number of installed DIMMs */
-       int ch1_count = 0;
-       int ch2_count = 0;
-+      uint8_t ch1_registered = 0;
-+      uint8_t ch2_registered = 0;
-       int i;
-       for (i = 0; i < 15; i = i + 2) {
-               if (pDCTstat->DIMMValid & (1 << i))
-@@ -304,6 +310,12 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc 
*pDCTstat)
-               if (pDCTstat->DIMMValid & (1 << (i + 1)))
-                       ch2_count++;
-       }
-+      for (i = 0; i < MAX_DIMMS_SUPPORTED; i = i + 2) {
-+              if (pDCTstat->DimmRegistered[i])
-+                      ch1_registered = 1;
-+              if (pDCTstat->DimmRegistered[i + 1])
-+                      ch2_registered = 1;
-+      }
-       if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) {
-               printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 1: %d DIMM(s) 
detected\n", ch1_count);
-               printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) 
detected\n", ch2_count);
-@@ -413,101 +425,6 @@ static void mctHookAfterDramInit(void)
- }
- 
- #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
--static void coreDelay(u32 microseconds)
--{
--      msr_t now;
--      msr_t end;
--      u32 cycles;
--
--      /* delay ~40us
--         This seems like a hack to me...
--         It would be nice to have a central delay function. */
--
--      cycles = (microseconds * 100) << 3;  /* x8 (number of 1.25ns ticks) */
--
--        if (!(rdmsr(HWCR).lo & TSC_FREQ_SEL_MASK)) {
--            msr_t pstate_msr = rdmsr(CUR_PSTATE_MSR);
--            if (!(rdmsr(0xC0010064+pstate_msr.lo).lo & NB_DID_M_ON)) {
--            cycles = cycles <<1; // half freq, double cycles
--          }
--      } // else should we keep p0 freq at the time of setting 
TSC_FREQ_SEL_MASK somewhere and check it here ?
--
--      now = rdmsr(TSC_MSR);
--        // avoid overflow when called near 2^32 ticks ~ 5.3 s boundaries
--      if (0xffffffff - cycles >= now.lo ) {
--        end.hi =  now.hi;
--          end.lo = now.lo + cycles;
--      } else {
--          end.hi = now.hi +1; //
--          end.lo = cycles - (1+(0xffffffff - now.lo));
--      }
--      do {
--          now = rdmsr(TSC_MSR);
--        } while ((now.hi < end.hi) || ((now.hi == end.hi) && (now.lo < 
end.lo)));
--}
--
--/* Erratum 350 */
--static void vErrata350(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat)
--{
--      u8 u8Channel;
--      u8 u8Receiver;
--      u32 u32Addr;
--      u8 u8Valid;
--      u32 u32DctDev;
--
--      // 1. dummy read for each installed DIMM */
--      for (u8Channel = 0; u8Channel < 2; u8Channel++) {
--              // This will be 0 for vaild DIMMS, eles 8
--              u8Receiver = mct_InitReceiver_D(pDCTstat, u8Channel);
--
--              for (; u8Receiver < 8; u8Receiver += 2) {
--                      u32Addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, 
u8Channel, u8Receiver, &u8Valid);
--
--                      if(!u8Valid) {  /* Address not supported on current CS 
*/
--                              print_t("vErrata350: Address not supported on 
current CS\n");
--                              continue;
--                      }
--                      print_t("vErrata350: dummy read \n");
--                      read32_fs(u32Addr);
--              }
--      }
--
--      print_t("vErrata350: step 2a\n");
--
--      /* 2. Write 0000_8000h to register F2x[1, 0]9C_xD080F0C. */
--      u32DctDev = pDCTstat->dev_dct;
--      Set_NB32_index_wait(u32DctDev, 0x098, 0xD080F0C, 0x00008000);
--      /*                                                ^--- value
--                                              ^---F2x[1, 0]9C_x0D080F0C, No 
description in BKDG.
--                                       ^----F2x[1, 0]98 DRAM Controller 
Additional Data Offset Register */
--
--      if(!pDCTstat->GangedMode) {
--              print_t("vErrata350: step 2b\n");
--              Set_NB32_index_wait(u32DctDev, 0x198, 0xD080F0C, 0x00008000);
--              /*                                                ^--- value
--                                                      ^---F2x[1, 
0]9C_x0D080F0C, No description in BKDG
--                                              ^----F2x[1, 0]98 DRAM 
Controller Additional Data Offset Register */
--      }
--
--      print_t("vErrata350: step 3\n");
--      /* 3. Wait at least 300 nanoseconds. */
--      coreDelay(1);
--
--      print_t("vErrata350: step 4\n");
--      /* 4. Write 0000_0000h to register F2x[1, 0]9C_xD080F0C. */
--      Set_NB32_index_wait(u32DctDev, 0x098, 0xD080F0C, 0x00000000);
--
--      if(!pDCTstat->GangedMode) {
--              print_t("vErrata350: step 4b\n");
--              Set_NB32_index_wait(u32DctDev, 0x198, 0xD080F0C, 0x00000000);
--      }
--
--      print_t("vErrata350: step 5\n");
--      /* 5. Wait at least 2 microseconds. */
--      coreDelay(2);
--
--}
--
- static void vErratum372(struct DCTStatStruc *pDCTstat)
- {
-         msr_t msr = rdmsr(NB_CFG_MSR);
-@@ -546,8 +463,7 @@ static void mctHookBeforeAnyTraining(struct MCTStatStruc 
*pMCTstat, struct DCTSt
- {
- #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
-   /* FIXME :  as of 25.6.2010 errata 350 and 372 should apply to  
((RB|BL|DA)-C[23])|(HY-D[01])|(PH-E0) but I don't find constants for all of 
them */
--      if (pDCTstatA->LogicalCPUID & AMD_DRBH_Cx) {
--              vErrata350(pMCTstat, pDCTstatA);
-+      if (pDCTstatA->LogicalCPUID & (AMD_DRBH_Cx | AMD_DR_Dx)) {
-               vErratum372(pDCTstatA);
-               vErratum414(pDCTstatA);
-       }
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0008-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
 
b/resources/libreboot/patch/kgpe-d16/0008-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
new file mode 100644
index 0000000..3b3da91
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0008-southbridge-amd-sr5650-Fix-boot-failure-on-ASUS-KGPE.patch
@@ -0,0 +1,621 @@
+From ccebca23a1e58cc82d9e2d48642ee604ebbcd3b9 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 5 Sep 2015 17:46:38 -0500
+Subject: [PATCH 008/143] southbridge/amd/sr5650: Fix boot failure on ASUS
+ KGPE-D16
+
+Change-Id: Ia13ba58118a826e830a4dc6e2378b76110fcabad
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/southbridge/amd/sr5650/acpi/sr5650.asl |  388 ++++++++++++++++++++++++++++
+ src/southbridge/amd/sr5650/early_setup.c   |    7 +-
+ src/southbridge/amd/sr5650/ht.c            |    3 +-
+ src/southbridge/amd/sr5650/pcie.c          |   37 ++-
+ src/southbridge/amd/sr5650/sr5650.c        |   51 ++--
+ 5 files changed, 456 insertions(+), 30 deletions(-)
+ create mode 100644 src/southbridge/amd/sr5650/acpi/sr5650.asl
+
+diff --git a/src/southbridge/amd/sr5650/acpi/sr5650.asl 
b/src/southbridge/amd/sr5650/acpi/sr5650.asl
+new file mode 100644
+index 0000000..a6ab114
+--- /dev/null
++++ b/src/southbridge/amd/sr5650/acpi/sr5650.asl
+@@ -0,0 +1,388 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ * Copyright (C) 2009 Advanced Micro Devices, Inc.
++ *
++ * 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
++ */
++
++Scope(\) {
++      Name(PCBA, 0xE0000000)  /* Base address of PCIe config space */
++      Name(HPBA, 0xFED00000)  /* Base address of HPET table */
++
++      /* PIC IRQ mapping registers, C00h-C01h */
++      OperationRegion(PRQM, SystemIO, 0x00000C00, 0x00000002)
++              Field(PRQM, ByteAcc, NoLock, Preserve) {
++              PRQI, 0x00000008,
++              PRQD, 0x00000008,  /* Offset: 1h */
++      }
++      IndexField(PRQI, PRQD, ByteAcc, NoLock, Preserve) {
++              PINA, 0x00000008,       /* Index 0 */
++              PINB, 0x00000008,       /* Index 1 */
++              PINC, 0x00000008,       /* Index 2 */
++              PIND, 0x00000008,       /* Index 3 */
++              AINT, 0x00000008,       /* Index 4 */
++              SINT, 0x00000008,       /* Index 5 */
++                  , 0x00000008,       /* Index 6 */
++              AAUD, 0x00000008,       /* Index 7 */
++              AMOD, 0x00000008,       /* Index 8 */
++              PINE, 0x00000008,       /* Index 9 */
++              PINF, 0x00000008,       /* Index A */
++              PING, 0x00000008,       /* Index B */
++              PINH, 0x00000008,       /* Index C */
++      }
++
++      /* PCI Error control register */
++      OperationRegion(PERC, SystemIO, 0x00000C14, 0x00000001)
++              Field(PERC, ByteAcc, NoLock, Preserve) {
++              SENS, 0x00000001,
++              PENS, 0x00000001,
++              SENE, 0x00000001,
++              PENE, 0x00000001,
++      }
++
++      Scope(\_SB) {
++              /* PCIe Configuration Space for 16 busses */
++              OperationRegion(PCFG, SystemMemory, PCBA, 0x01000000) /* Each 
bus consumes 1MB */
++                      Field(PCFG, ByteAcc, NoLock, Preserve) {
++                      /* Byte offsets are computed using the following 
technique:
++                       * ((bus number + 1) * ((device number * 8) * 4096)) + 
register offset
++                       * The 8 comes from 8 functions per device, and 4096 
bytes per function config space
++                      */
++                      Offset(0x00088024),     /* Byte offset to SATA register 
24h - Bus 0, Device 17, Function 0 */
++                      STB5, 32,
++                      Offset(0x00098042),     /* Byte offset to OHCI0 
register 42h - Bus 0, Device 19, Function 0 */
++                      PT0D, 1,
++                      PT1D, 1,
++                      PT2D, 1,
++                      PT3D, 1,
++                      PT4D, 1,
++                      PT5D, 1,
++                      PT6D, 1,
++                      PT7D, 1,
++                      PT8D, 1,
++                      PT9D, 1,
++                      Offset(0x000A0004),     /* Byte offset to SMBUS 
register 4h - Bus 0, Device 20, Function 0 */
++                      SBIE, 1,
++                      SBME, 1,
++                      Offset(0x000A0008),     /* Byte offset to SMBUS 
register 8h - Bus 0, Device 20, Function 0 */
++                      SBRI, 8,
++                      Offset(0x000A0014),     /* Byte offset to SMBUS 
register 14h - Bus 0, Device 20, Function 0 */
++                      SBB1, 32,
++                      Offset(0x000A0078),     /* Byte offset to SMBUS 
register 78h - Bus 0, Device 20, Function 0 */
++                      ,14,
++                      P92E, 1,                /* Port92 decode enable */
++              }
++
++              OperationRegion(SB5, SystemMemory, STB5, 0x1000)
++                      Field(SB5, AnyAcc, NoLock, Preserve){
++                      /* Port 0 */
++                      Offset(0x120),          /* Port 0 Task file status */
++                      P0ER, 1,
++                      , 2,
++                      P0DQ, 1,
++                      , 3,
++                      P0BY, 1,
++                      Offset(0x128),          /* Port 0 Serial ATA status */
++                      P0DD, 4,
++                      , 4,
++                      P0IS, 4,
++                      Offset(0x12C),          /* Port 0 Serial ATA control */
++                      P0DI, 4,
++                      Offset(0x130),          /* Port 0 Serial ATA error */
++                      , 16,
++                      P0PR, 1,
++
++                      /* Port 1 */
++                      offset(0x1A0),          /* Port 1 Task file status */
++                      P1ER, 1,
++                      , 2,
++                      P1DQ, 1,
++                      , 3,
++                      P1BY, 1,
++                      Offset(0x1A8),          /* Port 1 Serial ATA status */
++                      P1DD, 4,
++                      , 4,
++                      P1IS, 4,
++                      Offset(0x1AC),          /* Port 1 Serial ATA control */
++                      P1DI, 4,
++                      Offset(0x1B0),          /* Port 1 Serial ATA error */
++                      , 16,
++                      P1PR, 1,
++
++                      /* Port 2 */
++                      Offset(0x220),          /* Port 2 Task file status */
++                      P2ER, 1,
++                      , 2,
++                      P2DQ, 1,
++                      , 3,
++                      P2BY, 1,
++                      Offset(0x228),          /* Port 2 Serial ATA status */
++                      P2DD, 4,
++                      , 4,
++                      P2IS, 4,
++                      Offset(0x22C),          /* Port 2 Serial ATA control */
++                      P2DI, 4,
++                      Offset(0x230),          /* Port 2 Serial ATA error */
++                      , 16,
++                      P2PR, 1,
++
++                      /* Port 3 */
++                      Offset(0x2A0),          /* Port 3 Task file status */
++                      P3ER, 1,
++                      , 2,
++                      P3DQ, 1,
++                      , 3,
++                      P3BY, 1,
++                      Offset(0x2A8),          /* Port 3 Serial ATA status */
++                      P3DD, 4,
++                      , 4,
++                      P3IS, 4,
++                      Offset(0x2AC),          /* Port 3 Serial ATA control */
++                      P3DI, 4,
++                      Offset(0x2B0),          /* Port 3 Serial ATA error */
++                      , 16,
++                      P3PR, 1,
++              }
++
++              Method(CIRQ, 0x00, NotSerialized){
++                      Store(0, PINA)
++                      Store(0, PINB)
++                      Store(0, PINC)
++                      Store(0, PIND)
++                      Store(0, PINE)
++                      Store(0, PINF)
++                      Store(0, PING)
++                      Store(0, PINH)
++              }
++
++              /* set "A", 8259 interrupts */
++              Name (PRSA, ResourceTemplate () {
++                      IRQ(Level, ActiveLow, Exclusive) {4, 7, 10, 11, 12, 14, 
15}
++              })
++
++              Method (CRSA, 1, Serialized) {
++                      Name (LRTL, ResourceTemplate() {
++                              IRQ(Level, ActiveLow, Shared) {15}
++                      })
++                      CreateWordField(LRTL, 1, LIRQ)
++                      ShiftLeft(1, Arg0, LIRQ)
++                      Return (LRTL)
++              }
++
++              Method (SRSA, 1, Serialized) {
++                      CreateWordField(Arg0, 1, LIRQ)
++                      FindSetRightBit(LIRQ, Local0)
++                      if (Local0) {
++                              Decrement(Local0)
++                      }
++                      Return (Local0)
++              }
++
++              Device(LNKA) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 1)
++                      Method(_STA, 0) {
++                              if (PINA) {
++                                      Return(0x0B) /* LNKA is invisible */
++                              } else {
++                                      Return(0x09) /* LNKA is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PINA)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PINA))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PINA)
++                      }
++              }
++
++              Device(LNKB) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 2)
++                      Method(_STA, 0) {
++                              if (PINB) {
++                                      Return(0x0B) /* LNKB is invisible */
++                              } else {
++                                      Return(0x09) /* LNKB is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PINB)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PINB))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PINB)
++                      }
++              }
++
++              Device(LNKC) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 3)
++                      Method(_STA, 0) {
++                              if (PINC) {
++                                      Return(0x0B) /* LNKC is invisible */
++                              } else {
++                                      Return(0x09) /* LNKC is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PINC)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PINC))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PINC)
++                      }
++              }
++
++              Device(LNKD) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 4)
++                      Method(_STA, 0) {
++                              if (PIND) {
++                                      Return(0x0B) /* LNKD is invisible */
++                              } else {
++                                      Return(0x09) /* LNKD is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PIND)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PIND))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PIND)
++                      }
++              }
++
++              Device(LNKE) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 5)
++                      Method(_STA, 0) {
++                              if (PINE) {
++                                      Return(0x0B) /* LNKE is invisible */
++                              } else {
++                                      Return(0x09) /* LNKE is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PINE)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PINE))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PINE)
++                      }
++              }
++
++              Device(LNKF) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 6)
++                      Method(_STA, 0) {
++                              if (PINF) {
++                                      Return(0x0B) /* LNKF is invisible */
++                              } else {
++                                      Return(0x09) /* LNKF is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PINF)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PINF))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PINF)
++                      }
++              }
++
++              Device(LNKG) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 7)
++                      Method(_STA, 0) {
++                              if (PING) {
++                                      Return(0x0B) /* LNKG is invisible */
++                              } else {
++                                      Return(0x09) /* LNKG is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PING)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PING))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PING)
++                      }
++              }
++
++              Device(LNKH) {
++                      Name(_HID, EISAID("PNP0C0F"))
++                      Name(_UID, 8)
++                      Method(_STA, 0) {
++                              if (PINH) {
++                                      Return(0x0B) /* LNKH is invisible */
++                              } else {
++                                      Return(0x09) /* LNKH is disabled */
++                              }
++                      }
++                      Method(_DIS, 0) {
++                              Store(0, PINH)
++                      }
++                      Method(_PRS, 0) {
++                              Return (PRSA)
++                      }
++                      Method (_CRS, 0, Serialized) {
++                              Return (CRSA(PINH))
++                      }
++                      Method (_SRS, 1, Serialized) {
++                              Store (SRSA(Arg0), PINH)
++                      }
++              }
++
++      }   /* End Scope(_SB)  */
++
++}  /* End Scope(/)  */
+diff --git a/src/southbridge/amd/sr5650/early_setup.c 
b/src/southbridge/amd/sr5650/early_setup.c
+index ec555f8..664f60a 100644
+--- a/src/southbridge/amd/sr5650/early_setup.c
++++ b/src/southbridge/amd/sr5650/early_setup.c
+@@ -3,6 +3,7 @@
+  *
+  * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -504,7 +505,8 @@ void sr5650_early_setup(void)
+       /*ATINB_PrepareInit */
+       get_cpu_rev();
+ 
+-      switch (get_nb_rev(nb_dev)) {   /* PCIEMiscInit */
++      uint8_t revno = get_nb_rev(nb_dev);
++      switch (revno) {        /* PCIEMiscInit */
+       case REV_SR5650_A11:
+               printk(BIOS_INFO, "NB Revision is A11.\n");
+               break;
+@@ -514,6 +516,9 @@ void sr5650_early_setup(void)
+       case REV_SR5650_A21:
+               printk(BIOS_INFO, "NB Revision is A21.\n");
+               break;
++      default:
++              printk(BIOS_INFO, "NB Revision is %02x (Unrecognized).\n", 
revno);
++              break;
+       }
+ 
+       fam10_optimization();
+diff --git a/src/southbridge/amd/sr5650/ht.c b/src/southbridge/amd/sr5650/ht.c
+index c497107..02f4f7f 100644
+--- a/src/southbridge/amd/sr5650/ht.c
++++ b/src/southbridge/amd/sr5650/ht.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -55,7 +56,7 @@ static const apic_device_info default_apic_device_info_t [] 
= {
+       [13] = {4,     ABCD,       30}    /* Dev13 Grp4 [Int - 16..19] */
+ };
+ 
+-/* Their name are quite regular. So I undefine them. */
++/* These define names are common, so undefine them to avoid potential issues 
in other code */
+ #undef ABCD
+ #undef BCDA
+ #undef CDAB
+diff --git a/src/southbridge/amd/sr5650/pcie.c 
b/src/southbridge/amd/sr5650/pcie.c
+index 3720a61..d306b5a 100644
+--- a/src/southbridge/amd/sr5650/pcie.c
++++ b/src/southbridge/amd/sr5650/pcie.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -61,8 +62,10 @@ static void ValidatePortEn(device_t nb_dev)
+ *****************************************************************/
+ static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port)
+ {
++      printk(BIOS_DEBUG, "PciePowerOffGppPorts() port %d\n", port);
+       u32 reg;
+       u16 state_save;
++      uint8_t i;
+       struct southbridge_amd_sr5650_config *cfg =
+               (struct southbridge_amd_sr5650_config *)nb_dev->chip_info;
+       u16 state = cfg->port_enable;
+@@ -72,6 +75,28 @@ static void PciePowerOffGppPorts(device_t nb_dev, device_t 
dev, u32 port)
+       state = ~state;
+       state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7);
+       state_save = state << 17;
++      /* Disable ports any that failed training */
++      for (i = 9; i <= 13; i++) {
++              if (!(AtiPcieCfg.PortDetect & 1 << i)) {
++                      if ((port >= 9) && (port <= 13)) {
++                              state |= (1 << (port + 7));
++                      }
++                      if (port == 9)
++                              state_save |= 1 << 25;
++                      if (port == 10)
++                              state_save |= 1 << 26;
++                      if (port == 11)
++                              state_save |= 1 << 6;
++                      if (port == 12)
++                              state_save |= 1 << 7;
++
++                      if (port == 13) {
++                              reg = nbmisc_read_index(nb_dev, 0x2a);
++                              reg |= 1 << 4;
++                              nbmisc_write_index(nb_dev, 0x2a, reg);
++                      }
++              }
++      }
+       state &= !(AtiPcieCfg.PortHp);
+       reg = nbmisc_read_index(nb_dev, 0x0c);
+       reg |= state;
+@@ -483,6 +508,8 @@ static void EnableLclkGating(device_t dev)
+ *****************************************/
+ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
+ {
++      uint8_t training_ok = 1;
++
+       u32 gpp_sb_sel = 0;
+       struct southbridge_amd_sr5650_config *cfg =
+           (struct southbridge_amd_sr5650_config *)nb_dev->chip_info;
+@@ -701,6 +728,12 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, 
u32 port)
+                               printk(BIOS_DEBUG, "PcieTrainPort port=0x%x 
result=%d\n", port, res);
+                               if (res) {
+                                       AtiPcieCfg.PortDetect |= 1 << port;
++                              } else {
++                                      /* If the training failed the disable 
the bridge to prevent subsequent
++                                       * lockup on bridge configuration 
register read during the PCI bus scan
++                                       */
++                                      training_ok = 0;
++                                      dev->enabled = 0;
+                               }
+                       }
+               }
+@@ -747,8 +780,8 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 
port)
+        * wait dev 0x6B bit3 clear
+        */
+ 
+-      if (port == 8){
+-              PciePowerOffGppPorts(nb_dev, dev, port); /* , This should be 
run for all ports that are not hotplug and don't detect devices */
++      if ((port == 8) || (!training_ok)) {
++              PciePowerOffGppPorts(nb_dev, dev, port);        /* This is run 
for all ports that are not hotplug and don't detect devices */
+       }
+ }
+ 
+diff --git a/src/southbridge/amd/sr5650/sr5650.c 
b/src/southbridge/amd/sr5650/sr5650.c
+index 441be66..75383de 100644
+--- a/src/southbridge/amd/sr5650/sr5650.c
++++ b/src/southbridge/amd/sr5650/sr5650.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -95,32 +96,30 @@ void nbpcie_ind_write_index(device_t nb_dev, u32 index, 
u32 data)
+ void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add)
+ {
+       /* K8 Function1 is address map */
+-      device_t k8_f1;
+-      device_t np = dev_find_slot(0, PCI_DEVFN(0x19, 1));
+-      u16 node;
+-
+-      for (node = 0; node < CONFIG_MAX_PHYSICAL_CPUS; node++) {
+-              k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1));
+-              if (!k8_f1) {
+-                      break;
+-              }
+-
+-              if (in_out) {
+-                      /* Fill MMIO limit/base pair. */
+-                      pci_write_config32(k8_f1, 0xbc,
+-                                         (((pcie_base_add + 0x10000000 -
+-                                            1) >> 8) & 0xffffff00) | 0x8 | 
(np ? 2 << 4 : 0 << 4));
+-                      pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 
0x3);
+-                      pci_write_config32(k8_f1, 0xb4,
+-                                         ((mmio_base_add + 0x10000000 -
+-                                           1) >> 8) | (np ? 2 << 4 : 0 << 4));
+-                      pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 
0x3);
+-              } else {
+-                      pci_write_config32(k8_f1, 0xb8, 0);
+-                      pci_write_config32(k8_f1, 0xbc, 0);
+-                      pci_write_config32(k8_f1, 0xb0, 0);
+-                      pci_write_config32(k8_f1, 0xb4, 0);
+-              }
++      device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
++      device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
++
++      if (in_out) {
++              u32 dword, sblk;
++
++              /* Get SBLink value (HyperTransport I/O Hub Link ID). */
++              dword = pci_read_config32(k8_f0, 0x64);
++              sblk = (dword >> 8) & 0x3;
++
++              /* Fill MMIO limit/base pair. */
++              pci_write_config32(k8_f1, 0xbc,
++                                 (((pcie_base_add + 0x10000000 -
++                                   1) >> 8) & 0xffffff00) | 0x80 | (sblk << 
4));
++              pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3);
++              pci_write_config32(k8_f1, 0xb4,
++                                 (((mmio_base_add + 0x10000000 -
++                                   1) >> 8) & 0xffffff00) | (sblk << 4));
++              pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3);
++      } else {
++              pci_write_config32(k8_f1, 0xb8, 0);
++              pci_write_config32(k8_f1, 0xbc, 0);
++              pci_write_config32(k8_f1, 0xb0, 0);
++              pci_write_config32(k8_f1, 0xb4, 0);
+       }
+ }
+ 
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0009-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
 
b/resources/libreboot/patch/kgpe-d16/0009-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
new file mode 100644
index 0000000..b66fdf3
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0009-cpu-amd-Add-initial-support-for-AMD-Socket-G34-proce.patch
@@ -0,0 +1,832 @@
+From 9c3c40d0b53a338e7ed153b933155db1bc0cae08 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 5 Sep 2015 17:50:29 -0500
+Subject: [PATCH 009/143] cpu/amd: Add initial support for AMD Socket G34
+ processors
+
+Change-Id: Iccd034f32c26513edd52ca3a11a30f61c362682d
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/cpu/amd/Kconfig                        |    1 +
+ src/cpu/amd/Makefile.inc                   |    1 +
+ src/cpu/amd/car/post_cache_as_ram.c        |   19 ++++-
+ src/cpu/amd/model_10xxx/init_cpus.c        |   34 ++++++++-
+ src/cpu/amd/model_10xxx/model_10xxx_init.c |    2 +
+ src/cpu/amd/model_10xxx/processor_name.c   |   23 ++++++
+ src/cpu/amd/model_10xxx/ram_calc.c         |    2 +
+ src/cpu/amd/quadcore/quadcore_id.c         |   77 +++++++++++++++-----
+ src/cpu/amd/socket_G34/Kconfig             |   29 ++++++++
+ src/cpu/amd/socket_G34/Makefile.inc        |   14 ++++
+ src/cpu/amd/socket_G34/socket_G34.c        |   25 +++++++
+ src/northbridge/amd/amdfam10/northbridge.c |  102 +++++++++++++++++++++-----
+ src/northbridge/amd/amdht/ht_wrapper.c     |  107 +++++++++++++++++++++++++++-
+ src/northbridge/amd/amdht/ht_wrapper.h     |   25 +++++++
+ 14 files changed, 417 insertions(+), 44 deletions(-)
+ create mode 100644 src/cpu/amd/socket_G34/Kconfig
+ create mode 100644 src/cpu/amd/socket_G34/Makefile.inc
+ create mode 100644 src/cpu/amd/socket_G34/socket_G34.c
+ create mode 100644 src/northbridge/amd/amdht/ht_wrapper.h
+
+diff --git a/src/cpu/amd/Kconfig b/src/cpu/amd/Kconfig
+index 8286b2a..3a02043 100644
+--- a/src/cpu/amd/Kconfig
++++ b/src/cpu/amd/Kconfig
+@@ -5,6 +5,7 @@ source src/cpu/amd/socket_AM2/Kconfig
+ source src/cpu/amd/socket_AM2r2/Kconfig
+ source src/cpu/amd/socket_AM3/Kconfig
+ source src/cpu/amd/socket_C32/Kconfig
++source src/cpu/amd/socket_G34/Kconfig
+ source src/cpu/amd/socket_ASB2/Kconfig
+ source src/cpu/amd/socket_F/Kconfig
+ source src/cpu/amd/socket_F_1207/Kconfig
+diff --git a/src/cpu/amd/Makefile.inc b/src/cpu/amd/Makefile.inc
+index a73e25f..e532aba 100644
+--- a/src/cpu/amd/Makefile.inc
++++ b/src/cpu/amd/Makefile.inc
+@@ -8,6 +8,7 @@ subdirs-$(CONFIG_CPU_AMD_SOCKET_AM2R2) += socket_AM2r2
+ subdirs-$(CONFIG_CPU_AMD_SOCKET_AM3) += socket_AM3
+ subdirs-$(CONFIG_CPU_AMD_SOCKET_ASB2) += socket_ASB2
+ subdirs-$(CONFIG_CPU_AMD_SOCKET_C32_NON_AGESA) += socket_C32
++subdirs-$(CONFIG_CPU_AMD_SOCKET_G34_NON_AGESA) += socket_G34
+ subdirs-$(CONFIG_CPU_AMD_GEODE_GX2) += geode_gx2
+ subdirs-$(CONFIG_CPU_AMD_GEODE_LX) += geode_lx
+ subdirs-$(CONFIG_CPU_AMD_SOCKET_S1G1) += socket_S1G1
+diff --git a/src/cpu/amd/car/post_cache_as_ram.c 
b/src/cpu/amd/car/post_cache_as_ram.c
+index 96df3e7..230d1aa 100644
+--- a/src/cpu/amd/car/post_cache_as_ram.c
++++ b/src/cpu/amd/car/post_cache_as_ram.c
+@@ -1,4 +1,5 @@
+-/* 2005.6 by yhlu
++/* Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ * 2005.6 by yhlu
+  * 2006.3 yhlu add copy data from CAR to ram
+  */
+ #include <string.h>
+@@ -46,6 +47,15 @@ static void memset_(void *d, int val, size_t len)
+       memset(d, val, len);
+ }
+ 
++static int memcmp_(void *d, const void *s, size_t len)
++{
++#if PRINTK_IN_CAR
++      printk(BIOS_SPEW, " Compare [%08x-%08x] with [%08x - %08x] ... ",
++              (u32) s, (u32) (s + len - 1), (u32) d, (u32) (d + len - 1));
++#endif
++      return memcmp(d, s, len);
++}
++
+ static void prepare_romstage_ramstack(void *resume_backup_memory)
+ {
+       size_t backup_top = backup_size();
+@@ -110,6 +120,12 @@ void post_cache_as_ram(void)
+       memcpy_(migrated_car, &_car_data_start[0], car_size);
+       print_car_debug("Done\n");
+ 
++      print_car_debug("Verifying data integrity in RAM... ");
++      if (memcmp_(migrated_car, &_car_data_start[0], car_size) == 0)
++              print_car_debug("Done\n");
++      else
++              print_car_debug("FAILED\n");
++
+       /* New stack grows right below migrated_car. */
+       print_car_debug("Switching to use RAM as stack... ");
+       cache_as_ram_switch_stack(migrated_car);
+@@ -128,6 +144,7 @@ void cache_as_ram_new_stack (void)
+       disable_cache_as_ram_bsp();
+ 
+       disable_cache();
++      /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */
+       set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
+       enable_cache();
+ 
+diff --git a/src/cpu/amd/model_10xxx/init_cpus.c 
b/src/cpu/amd/model_10xxx/init_cpus.c
+index 4c72848..8de6d25 100644
+--- a/src/cpu/amd/model_10xxx/init_cpus.c
++++ b/src/cpu/amd/model_10xxx/init_cpus.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -67,6 +68,9 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
+       u32 nb_cfg_54;
+       int i, j;
+       u32 ApicIdCoreIdSize;
++      uint8_t rev_gte_d = 0;
++      uint8_t dual_node = 0;
++      uint32_t f3xe8;
+ 
+       /* get_nodes define in ht_wrapper.c */
+       nodes = get_nodes();
+@@ -81,6 +85,16 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
+       /* Assume that all node are same stepping, otherwise we can use use
+          nb_cfg_54 from bsp for all nodes */
+       nb_cfg_54 = read_nb_cfg_54();
++      f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
++
++      if (cpuid_eax(0x80000001) >= 0x8)
++              /* Revision D or later */
++              rev_gte_d = 1;
++
++      if (rev_gte_d)
++               /* Check for dual node capability */
++              if (f3xe8 & 0x20000000)
++                      dual_node = 1;
+ 
+       ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
+       if (ApicIdCoreIdSize) {
+@@ -91,6 +105,8 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
+ 
+       for (i = 0; i < nodes; i++) {
+               cores_found = get_core_num_in_bsp(i);
++              if (siblings > cores_found)
++                      siblings = cores_found;
+ 
+               u32 jstart, jend;
+ 
+@@ -107,9 +123,21 @@ static void for_each_ap(u32 bsp_apicid, u32 core_range, 
process_ap_t process_ap,
+               }
+ 
+               for (j = jstart; j <= jend; j++) {
+-                      ap_apicid =
+-                          i * (nb_cfg_54 ? (siblings + 1) : 1) +
+-                          j * (nb_cfg_54 ? 1 : 64);
++                      if (dual_node) {
++                              ap_apicid = 0;
++                              if (nb_cfg_54) {
++                                      ap_apicid |= ((i >> 1) & 0x3) << 4;     
                /* Node ID */
++                                      ap_apicid |= ((i & 0x1) * (siblings + 
1)) + j;          /* Core ID */
++                              } else {
++                                      ap_apicid |= i & 0x3;                   
                /* Node ID */
++                                      ap_apicid |= (((i & 0x1) * (siblings + 
1)) + j) << 4;   /* Core ID */
++                              }
++                      } else {
++                              ap_apicid =
++                              i * (nb_cfg_54 ? (siblings + 1) : 1) +
++                              j * (nb_cfg_54 ? 1 : 64);
++                      }
++
+ 
+ #if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET > 0)
+ #if !CONFIG_LIFT_BSP_APIC_ID
+diff --git a/src/cpu/amd/model_10xxx/model_10xxx_init.c 
b/src/cpu/amd/model_10xxx/model_10xxx_init.c
+index 590b89d..b942c1a 100644
+--- a/src/cpu/amd/model_10xxx/model_10xxx_init.c
++++ b/src/cpu/amd/model_10xxx/model_10xxx_init.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2007 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -153,6 +154,7 @@ static struct cpu_device_id cpu_table[] = {
+       { X86_VENDOR_AMD, 0x100F63 },           /* DA-C3 */
+       { X86_VENDOR_AMD, 0x100F80 },           /* HY-D0 */
+       { X86_VENDOR_AMD, 0x100F81 },           /* HY-D1 */
++      { X86_VENDOR_AMD, 0x100F91 },           /* HY-D1 */
+       { X86_VENDOR_AMD, 0x100FA0 },           /* PH-E0 */
+       { 0, 0 },
+ };
+diff --git a/src/cpu/amd/model_10xxx/processor_name.c 
b/src/cpu/amd/model_10xxx/processor_name.c
+index a25e3a9..12c45c9 100644
+--- a/src/cpu/amd/model_10xxx/processor_name.c
++++ b/src/cpu/amd/model_10xxx/processor_name.c
+@@ -157,6 +157,24 @@ static const struct str_s String2_socket_AM2[] = {
+       {0, 0, 0, NULL}
+ };
+ 
++static const struct str_s String1_socket_G34[] = {
++      {0x00, 0x07, 0x00, "AMD Opteron(tm) Processor 61"},
++      {0x00, 0x0B, 0x00, "AMD Opteron(tm) Processor 61"},
++      {0x01, 0x07, 0x01, "Embedded AMD Opteron(tm) Processor "},
++      {0, 0, 0, NULL}
++};
++
++static const struct str_s String2_socket_G34[] = {
++      {0x00, 0x07, 0x00, " HE"},
++      {0x00, 0x07, 0x01, " SE"},
++      {0x00, 0x0B, 0x00, " HE"},
++      {0x00, 0x0B, 0x01, " SE"},
++      {0x00, 0x0B, 0x0F, ""},
++      {0x01, 0x07, 0x01, " QS"},
++      {0x01, 0x07, 0x02, " KS"},
++      {0, 0, 0, NULL}
++};
++
+ static const struct str_s String1_socket_C32[] = {
+       {0x00, 0x03, 0x00, "AMD Opteron(tm) Processor 41"},
+       {0x00, 0x05, 0x00, "AMD Opteron(tm) Processor 41"},
+@@ -240,6 +258,11 @@ int init_processor_name(void)
+               str = String1_socket_AM2;
+               str2 = String2_socket_AM2;
+               break;
++      case 3:         /* G34 */
++              str = String1_socket_G34;
++              str2 = String2_socket_G34;
++              str2_checkNC = 0;
++              break;
+       case 5:         /* C32 */
+               str = String1_socket_C32;
+               str2 = String2_socket_C32;
+diff --git a/src/cpu/amd/model_10xxx/ram_calc.c 
b/src/cpu/amd/model_10xxx/ram_calc.c
+index c8637c9..46ccdbd 100644
+--- a/src/cpu/amd/model_10xxx/ram_calc.c
++++ b/src/cpu/amd/model_10xxx/ram_calc.c
+@@ -26,6 +26,7 @@
+ 
+ #include "ram_calc.h"
+ 
++#if !IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
+ uint64_t get_uma_memory_size(uint64_t topmem)
+ {
+       uint64_t uma_size = 0;
+@@ -50,3 +51,4 @@ void *cbmem_top(void)
+ 
+       return (void *) topmem - get_uma_memory_size(topmem);
+ }
++#endif
+diff --git a/src/cpu/amd/quadcore/quadcore_id.c 
b/src/cpu/amd/quadcore/quadcore_id.c
+index cf45196..c5921de 100644
+--- a/src/cpu/amd/quadcore/quadcore_id.c
++++ b/src/cpu/amd/quadcore/quadcore_id.c
+@@ -1,6 +1,7 @@
+ /*
+  * This file is part of the coreboot project.
+  *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  * Copyright (C) 2007 Advanced Micro Devices, Inc.
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -37,33 +38,71 @@ u32 get_initial_apicid(void)
+       return ((cpuid_ebx(1) >> 24) & 0xff);
+ }
+ 
+-//called by amd_siblings too
+-#define CORE_ID_BIT 2
+-#define NODE_ID_BIT 6
++/* Called by amd_siblings (ramstage) as well */
+ struct node_core_id get_node_core_id(u32 nb_cfg_54)
+ {
+       struct node_core_id id;
+-      u32 core_id_bits;
++      uint8_t apicid;
++      uint8_t rev_gte_d = 0;
++      uint8_t dual_node = 0;
++      uint32_t f3xe8;
+ 
+-      u32 ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf);
+-      if(ApicIdCoreIdSize) {
+-              core_id_bits = ApicIdCoreIdSize;
+-      } else {
+-              core_id_bits = CORE_ID_BIT; //quad core
+-      }
++#ifdef __PRE_RAM__
++      f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
++#else
++      f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
++#endif
++
++      if (cpuid_eax(0x80000001) >= 0x8)
++              /* Revision D or later */
++              rev_gte_d = 1;
+ 
+-      // get the apicid via cpuid(1) ebx[31:24]
++      if (rev_gte_d)
++               /* Check for dual node capability */
++              if (f3xe8 & 0x20000000)
++                      dual_node = 1;
++
++      /* Get the apicid via cpuid(1) ebx[31:24]
++       * The apicid format varies based on processor revision
++       */
++      apicid = (cpuid_ebx(1) >> 24) & 0xff;
+       if( nb_cfg_54) {
+-              // when NB_CFG[54] is set, nodeid = ebx[31:26], coreid = 
ebx[25:24]
+-              id.coreid = (cpuid_ebx(1) >> 24) & 0xff;
+-              id.nodeid = (id.coreid>>core_id_bits);
+-              id.coreid &= ((1<<core_id_bits)-1);
++              if (rev_gte_d && dual_node) {
++                      id.coreid = apicid & 0xf;
++                      id.nodeid = (apicid & 0x30) >> 4;
++              } else if (rev_gte_d && !dual_node) {
++                      id.coreid = apicid & 0x7;
++                      id.nodeid = (apicid & 0x38) >> 3;
++              } else {
++                      id.coreid = apicid & 0x3;
++                      id.nodeid = (apicid & 0x1c) >> 2;
++              }
+       } else {
+-              // when NB_CFG[54] is clear, nodeid = ebx[29:24], coreid = 
ebx[31:30]
+-              id.nodeid = (cpuid_ebx(1) >> 24) & 0xff;
+-              id.coreid = (id.nodeid>>NODE_ID_BIT);
+-              id.nodeid &= ((1<<NODE_ID_BIT)-1);
++              if (rev_gte_d && dual_node) {
++                      id.coreid = (apicid & 0xf0) >> 4;
++                      id.nodeid = apicid & 0x3;
++              } else if (rev_gte_d && !dual_node) {
++                      id.coreid = (apicid & 0xe0) >> 5;
++                      id.nodeid = apicid & 0x7;
++              } else {
++                      id.coreid = (apicid & 0x60) >> 5;
++                      id.nodeid = apicid & 0x7;
++              }
+       }
++
++      if (rev_gte_d && dual_node) {
++              /* Coreboot expects each separate processor die to be on a 
different nodeid.
++               * Since the code above returns nodeid 0 even on internal node 
1 some fixup is needed...
++               */
++              uint8_t core_count = (((f3xe8 & 0x00008000) >> 13) | ((f3xe8 & 
0x00003000) >> 12)) + 1;
++
++              id.nodeid = id.nodeid * 2;
++              if (id.coreid >= core_count) {
++                      id.nodeid += 1;
++                      id.coreid = id.coreid - core_count;
++              }
++      }
++
+       return id;
+ }
+ 
+diff --git a/src/cpu/amd/socket_G34/Kconfig b/src/cpu/amd/socket_G34/Kconfig
+new file mode 100644
+index 0000000..abc9726
+--- /dev/null
++++ b/src/cpu/amd/socket_G34/Kconfig
+@@ -0,0 +1,29 @@
++config CPU_AMD_SOCKET_G34_NON_AGESA
++      bool
++      select CPU_AMD_MODEL_10XXX
++      select PCI_IO_CFG_EXT
++      select X86_AMD_FIXED_MTRRS
++
++if CPU_AMD_SOCKET_G34_NON_AGESA
++
++config CPU_SOCKET_TYPE
++      hex
++      default 0x15
++
++config EXT_RT_TBL_SUPPORT
++      bool
++      default n
++
++config CBB
++      hex
++      default 0x0
++
++config CDB
++      hex
++      default 0x18
++
++config XIP_ROM_SIZE
++      hex
++      default 0x80000
++
++endif
+diff --git a/src/cpu/amd/socket_G34/Makefile.inc 
b/src/cpu/amd/socket_G34/Makefile.inc
+new file mode 100644
+index 0000000..a8e1333
+--- /dev/null
++++ b/src/cpu/amd/socket_G34/Makefile.inc
+@@ -0,0 +1,14 @@
++ramstage-y += socket_G34.c
++subdirs-y += ../model_10xxx
++subdirs-y += ../quadcore
++subdirs-y += ../mtrr
++subdirs-y += ../microcode
++subdirs-y += ../../x86/tsc
++subdirs-y += ../../x86/lapic
++subdirs-y += ../../x86/cache
++subdirs-y += ../../x86/pae
++subdirs-y += ../../x86/mtrr
++subdirs-y += ../../x86/smm
++subdirs-y += ../smm
++
++cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc
+diff --git a/src/cpu/amd/socket_G34/socket_G34.c 
b/src/cpu/amd/socket_G34/socket_G34.c
+new file mode 100644
+index 0000000..90f7b8c
+--- /dev/null
++++ b/src/cpu/amd/socket_G34/socket_G34.c
+@@ -0,0 +1,25 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * 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
++ */
++
++#include <device/device.h>
++
++struct chip_operations cpu_amd_socket_G34_ops = {
++      CHIP_NAME("socket G34")
++};
+diff --git a/src/northbridge/amd/amdfam10/northbridge.c 
b/src/northbridge/amd/amdfam10/northbridge.c
+index 6d91cbd..74cecc8 100644
+--- a/src/northbridge/amd/amdfam10/northbridge.c
++++ b/src/northbridge/amd/amdfam10/northbridge.c
+@@ -187,6 +187,43 @@ static void ht_route_link(struct bus *link, scan_state 
mode)
+       }
+ }
+ 
++static void amd_g34_fixup(struct bus *link, device_t dev)
++{
++      uint32_t nodeid = amdfam10_nodeid(dev);
++      uint8_t rev_gte_d = 0;
++      uint8_t dual_node = 0;
++      uint32_t f3xe8;
++
++      if (cpuid_eax(0x80000001) >= 0x8)
++              /* Revision D or later */
++              rev_gte_d = 1;
++
++      if (rev_gte_d) {
++              f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
++
++              /* Check for dual node capability */
++              if (f3xe8 & 0x20000000)
++                      dual_node = 1;
++
++              if (dual_node) {
++                      /* Each G34 processor contains a defective HT link.
++                      * See the BKDG Rev 3.62 section 2.7.1.5 for details.
++                      */
++                      f3xe8 = pci_read_config32(get_node_pci(nodeid, 3), 
0xe8);
++                      uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 
30);
++                      if (internal_node_number == 0) {
++                              /* Node 0 */
++                              if (link->link_num == 6)        /* Link 2 
Sublink 1 */
++                                      printk(BIOS_DEBUG, 
"amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT 
link\n", nodeid, internal_node_number);
++                      } else {
++                              /* Node 1 */
++                              if (link->link_num == 5)        /* Link 1 
Sublink 1 */
++                                      printk(BIOS_DEBUG, 
"amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT 
link\n", nodeid, internal_node_number);
++                      }
++              }
++      }
++}
++
+ static void amdfam10_scan_chain(struct bus *link)
+ {
+               unsigned int next_unitid;
+@@ -277,8 +314,11 @@ static void amdfam10_scan_chains(device_t dev)
+       trim_ht_chain(dev);
+ 
+       for (link = dev->link_list; link; link = link->next) {
+-              if (link->ht_link_up)
++              if (link->ht_link_up) {
++                      if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX))
++                              amd_g34_fixup(link, dev);
+                       amdfam10_scan_chain(link);
++              }
+       }
+ }
+ 
+@@ -323,8 +363,7 @@ static struct resource *amdfam10_find_iopair(device_t dev, 
unsigned nodeid, unsi
+               if (result == 1) {
+                       /* I have been allocated this one */
+                       break;
+-              }
+-              else if (result > 1) {
++              } else if (result > 1) {
+                       /* I have a free register pair */
+                       free_reg = reg;
+               }
+@@ -357,8 +396,7 @@ static struct resource *amdfam10_find_mempair(device_t 
dev, u32 nodeid, u32 link
+               if (result == 1) {
+                       /* I have been allocated this one */
+                       break;
+-              }
+-              else if (result > 1) {
++              } else if (result > 1) {
+                       /* I have a free register pair */
+                       free_reg = reg;
+               }
+@@ -473,8 +511,7 @@ static void amdfam10_set_resource(device_t dev, struct 
resource *resource,
+ 
+               set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
+               store_conf_io_addr(nodeid, link_num, reg, (resource->index >> 
24), rbase>>8, rend>>8);
+-      }
+-      else if (resource->flags & IORESOURCE_MEM) {
++      } else if (resource->flags & IORESOURCE_MEM) {
+               set_mmio_addr_reg(nodeid, link_num, reg, (resource->index 
>>24), rbase>>8, rend>>8, sysconf.nodes) ;// [39:8]
+               store_conf_mmio_addr(nodeid, link_num, reg, (resource->index 
>>24), rbase>>8, rend>>8);
+       }
+@@ -799,8 +836,7 @@ static void amdfam10_domain_set_resources(device_t dev)
+                       }
+                       if ((basek + sizek) <= 4*1024*1024) {
+                               sizek = 0;
+-                      }
+-                      else {
++                      } else {
+                               basek = 4*1024*1024;
+                               sizek -= (4*1024*1024 - mmio_basek);
+                       }
+@@ -977,8 +1013,7 @@ static int amdfam10_get_smbios_data17(int* count, int 
handle, int parent_handle,
+                               if (dimm_size_bytes > 0x800000000) {
+                                       t->size = 0x7FFF;
+                                       t->extended_size = dimm_size_bytes;
+-                              }
+-                              else {
++                              } else {
+                                       t->size = dimm_size_bytes / (1024*1024);
+                                       t->size &= (~0x8000);   /* size 
specified in megabytes */
+                               }
+@@ -1005,8 +1040,7 @@ static int amdfam10_get_smbios_data17(int* count, int 
handle, int parent_handle,
+                               t->part_number = smbios_add_string(t->eos, 
mem_info->dct_stat[node].DimmPartNumber[slot]);
+                               if 
(mem_info->dct_stat[node].DimmSerialNumber[slot] == 0) {
+                                       t->serial_number = 
smbios_add_string(t->eos, "None");
+-                              }
+-                              else {
++                              } else {
+                                       snprintf(string_buffer, sizeof 
(string_buffer), "%08X", mem_info->dct_stat[node].DimmSerialNumber[slot]);
+                                       t->serial_number = 
smbios_add_string(t->eos, string_buffer);
+                               }
+@@ -1108,8 +1142,7 @@ static void add_more_links(device_t dev, unsigned 
total_links)
+                       memset(link, 0, links*sizeof(*link));
+                       last->next = link;
+               }
+-      }
+-      else {
++      } else {
+               link = malloc(total_links*sizeof(*link));
+               memset(link, 0, total_links*sizeof(*link));
+               dev->link_list = link;
+@@ -1244,6 +1277,10 @@ static void cpu_bus_scan(device_t dev)
+               unsigned busn, devn;
+               struct bus *pbus;
+ 
++              uint8_t rev_gte_d = 0;
++              uint8_t dual_node = 0;
++              uint32_t f3xe8;
++
+               busn = CONFIG_CBB;
+               devn = CONFIG_CDB+i;
+               pbus = dev_mc->bus;
+@@ -1268,6 +1305,7 @@ static void cpu_bus_scan(device_t dev)
+                       }
+               }
+ 
++
+               /* Ok, We need to set the links for that device.
+                * otherwise the device under it will not be scanned
+                */
+@@ -1279,6 +1317,17 @@ static void cpu_bus_scan(device_t dev)
+               if (cdb_dev)
+                       add_more_links(cdb_dev, 4);
+ 
++              f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
++
++              if (cpuid_eax(0x80000001) >= 0x8)
++                      /* Revision D or later */
++                      rev_gte_d = 1;
++
++              if (rev_gte_d)
++                      /* Check for dual node capability */
++                      if (f3xe8 & 0x20000000)
++                              dual_node = 1;
++
+               cores_found = 0; // one core
+               cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
+               int enable_node = cdb_dev && cdb_dev->enabled;
+@@ -1290,6 +1339,9 @@ static void cpu_bus_scan(device_t dev)
+                       printk(BIOS_DEBUG, "  %s siblings=%d\n", 
dev_path(cdb_dev), cores_found);
+               }
+ 
++              if (siblings > cores_found)
++                      siblings = cores_found;
++
+               u32 jj;
+               if(disable_siblings) {
+                       jj = 0;
+@@ -1299,7 +1351,20 @@ static void cpu_bus_scan(device_t dev)
+               }
+ 
+               for (j = 0; j <=jj; j++ ) {
+-                      u32 apic_id = i * (nb_cfg_54?(siblings+1):1) + j * 
(nb_cfg_54?1:64); // ?
++                      u32 apic_id;
++
++                      if (dual_node) {
++                              apic_id = 0;
++                              if (nb_cfg_54) {
++                                      apic_id |= ((i >> 1) & 0x3) << 4;       
                /* Node ID */
++                                      apic_id |= ((i & 0x1) * (siblings + 1)) 
+ j;            /* Core ID */
++                              } else {
++                                      apic_id |= i & 0x3;                     
                /* Node ID */
++                                      apic_id |= (((i & 0x1) * (siblings + 
1)) + j) << 4;     /* Core ID */
++                              }
++                      } else {
++                              apic_id = i * (nb_cfg_54?(siblings+1):1) + j * 
(nb_cfg_54?1:64); // ?
++                      }
+ 
+ #if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET>0)
+                       if(sysconf.enabled_apic_ext_id) {
+@@ -1311,7 +1376,7 @@ static void cpu_bus_scan(device_t dev)
+                       device_t cpu = add_cpu_device(cpu_bus, apic_id, 
enable_node);
+                       if (cpu)
+                               amd_cpu_topology(cpu, i, j);
+-              } //j
++              }
+       }
+ }
+ 
+@@ -1356,8 +1421,7 @@ static void root_complex_enable_dev(struct device *dev)
+       /* Set the operations if it is a special bus type */
+       if (dev->path.type == DEVICE_PATH_DOMAIN) {
+               dev->ops = &pci_domain_ops;
+-      }
+-      else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
++      } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+               dev->ops = &cpu_bus_ops;
+       }
+ }
+diff --git a/src/northbridge/amd/amdht/ht_wrapper.c 
b/src/northbridge/amd/amdht/ht_wrapper.c
+index 36fe60b..389b1b1 100644
+--- a/src/northbridge/amd/amdht/ht_wrapper.c
++++ b/src/northbridge/amd/amdht/ht_wrapper.c
+@@ -22,6 +22,8 @@
+ #include <console/console.h>
+ #include <northbridge/amd/amdfam10/amdfam10.h>
+ 
++#include "ht_wrapper.h"
++
+ /*----------------------------------------------------------------------------
+  *                    TYPEDEFS, DEFINITIONS AND MACROS
+  *
+@@ -113,6 +115,20 @@ void getAmdTopolist(u8 ***p)
+       *p = (u8 **)amd_topo_list;
+ }
+ 
++/**
++ * BOOL AMD_CB_IgnoreLink(u8 Node, u8 Link)
++ * Description:
++ *    This routine is used to ignore connected yet faulty HT links,
++ *    such as those present in a G34 processor package.
++ *
++ * Parameters:
++ *    @param[in]  node   = The node on which this chain is located
++ *    @param[in]  link   = The link on the host for this chain
++ */
++static BOOL AMD_CB_IgnoreLink (u8 node, u8 link)
++{
++      return 0;
++}
+ 
+ /**
+  * void amd_ht_init(struct sys_info *sysinfo)
+@@ -128,7 +144,7 @@ static void amd_ht_init(struct sys_info *sysinfo)
+               0,      // u8 AutoBusStart;
+               32,     // u8 AutoBusMax;
+               6,      // u8 AutoBusIncrement;
+-              NULL,   // BOOL (*AMD_CB_IgnoreLink)();
++              AMD_CB_IgnoreLink,              // BOOL (*AMD_CB_IgnoreLink)();
+               NULL,   // BOOL (*AMD_CB_OverrideBusNumbers)();
+               AMD_CB_ManualBUIDSwapList,      // BOOL 
(*AMD_CB_ManualBUIDSwapList)();
+               NULL,   // void (*AMD_CB_DeviceCapOverride)();
+@@ -146,6 +162,93 @@ static void amd_ht_init(struct sys_info *sysinfo)
+       printk(BIOS_DEBUG, "Enter amd_ht_init()\n");
+       amdHtInitialize(&ht_wrapper);
+       printk(BIOS_DEBUG, "Exit amd_ht_init()\n");
++}
+ 
+-
++/**
++ * void amd_ht_fixup(struct sys_info *sysinfo)
++ *
++ *  AMD HT fixup
++ *
++ */
++void amd_ht_fixup(struct sys_info *sysinfo) {
++      printk(BIOS_DEBUG, "amd_ht_fixup()\n");
++      if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) {
++              uint8_t rev_gte_d = 0;
++              uint8_t dual_node = 0;
++              uint32_t f3xe8;
++              uint32_t family;
++              uint32_t model;
++
++              family = model = cpuid_eax(0x80000001);
++              model = ((model & 0xf0000) >> 16) | ((model & 0xf0) >> 4);
++
++              if (model >= 0x8)
++                      /* Revision D or later */
++                      rev_gte_d = 1;
++
++              if (rev_gte_d) {
++                      f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
++
++                      /* Check for dual node capability */
++                      if (f3xe8 & 0x20000000)
++                              dual_node = 1;
++
++                      if (dual_node) {
++                              /* Each G34 processor contains a defective HT 
link.
++                              * See the BKDG Rev 3.62 section 2.7.1.5 for 
details.
++                              */
++                              uint8_t node;
++                              uint8_t node_count = get_nodes();
++                              uint32_t dword;
++                              for (node = 0; node < node_count; node++) {
++                                      f3xe8 = 
pci_read_config32(NODE_PCI(node, 3), 0xe8);
++                                      uint8_t internal_node_number = ((f3xe8 
& 0xc0000000) >> 30);
++                                      printk(BIOS_DEBUG, "amd_ht_fixup(): 
node %d (internal node ID %d): disabling defective HT link\n", node, 
internal_node_number);
++                                      if (internal_node_number == 0) {
++                                              uint8_t 
package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xd8) & 0x1;
++                                              if (package_link_3_connected) {
++                                                      /* Set WidthIn and 
WidthOut to 0 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0xc4);
++                                                      dword &= ~0x77000000;
++                                                      
pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
++                                                      /* Set Ganged to 1 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x178);
++                                                      dword |= 0x00000001;
++                                                      
pci_write_config32(NODE_PCI(node, 0), 0x178, dword);
++                                              } else {
++                                                      /* Set ConnDly to 1 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x16c);
++                                                      dword |= 0x00000100;
++                                                      
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
++                                                      /* Set TransOff and 
EndOfChain to 1 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 4), 0xc4);
++                                                      dword |= 0x000000c0;
++                                                      
pci_write_config32(NODE_PCI(node, 4), 0xc4, dword);
++                                              }
++                                      } else if (internal_node_number == 1) {
++                                              uint8_t 
package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xb8) & 0x1;
++                                              if (package_link_3_connected) {
++                                                      /* Set WidthIn and 
WidthOut to 0 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0xa4);
++                                                      dword &= ~0x77000000;
++                                                      
pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
++                                                      /* Set Ganged to 1 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x174);
++                                                      dword |= 0x00000001;
++                                                      
pci_write_config32(NODE_PCI(node, 0), 0x174, dword);
++                                              } else {
++                                                      /* Set ConnDly to 1 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 0), 0x16c);
++                                                      dword |= 0x00000100;
++                                                      
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
++                                                      /* Set TransOff and 
EndOfChain to 1 */
++                                                      dword = 
pci_read_config32(NODE_PCI(node, 4), 0xa4);
++                                                      dword |= 0x000000c0;
++                                                      
pci_write_config32(NODE_PCI(node, 4), 0xa4, dword);
++                                              }
++                                      }
++                              }
++                      }
++              }
++      }
+ }
+diff --git a/src/northbridge/amd/amdht/ht_wrapper.h 
b/src/northbridge/amd/amdht/ht_wrapper.h
+new file mode 100644
+index 0000000..3e9d957
+--- /dev/null
++++ b/src/northbridge/amd/amdht/ht_wrapper.h
+@@ -0,0 +1,25 @@
++/*
++ * This file is part of the coreboot project.
++ *
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
++ *
++ * 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.
++ */
++
++#ifndef AMD_HT_WRAPPER_H
++#define AMD_HT_WRAPPER_H
++
++void amd_ht_fixup(struct sys_info *sysinfo);
++
++#endif
+-- 
+1.7.9.5
+
diff --git 
a/resources/libreboot/patch/kgpe-d16/0009-northbridge-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch
 
b/resources/libreboot/patch/kgpe-d16/0009-northbridge-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch
deleted file mode 100644
index 877d6b0..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0009-northbridge-amd-amdmct-mct_ddr3-Fix-curly-brace-styl.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 008cfb1a5e464a79af252b34086b1eb28d8b3420 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Tue, 8 Sep 2015 16:08:45 -0500
-Subject: [PATCH 009/139] northbridge/amd/amdmct/mct_ddr3: Fix curly brace
- style violations
-
-Change-Id: Ic27d404a7ed76b58043037e8b66097db6d664501
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c | 37 ++++++++-------------------
- 1 file changed, 10 insertions(+), 27 deletions(-)
-
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-index c76476b..9f42d54 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
-@@ -818,28 +818,19 @@ void setWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, 
u8 dimm, u8 targetAddr)
- 
-               tempB = 0;
-               offsetAddr = (u8)(3 * dimm);
--              if (ByteLane < 2)
--              {
-+              if (ByteLane < 2) {
-                       tempB = (u8)(16 * ByteLane);
-                       addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01;
--              }
--              else if (ByteLane <4)
--              {
-+              } else if (ByteLane <4) {
-                       tempB = (u8)(16 * ByteLane);
-                       addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 + 1;
--              }
--              else if (ByteLane <6)
--              {
-+              } else if (ByteLane <6) {
-                       tempB = (u8)(16 * ByteLane);
-                       addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45;
--              }
--              else if (ByteLane <8)
--              {
-+              } else if (ByteLane <8) {
-                       tempB = (u8)(16 * ByteLane);
-                       addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45 + 1;
--              }
--              else
--              {
-+              } else {
-                       tempB = 0;
-                       addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 + 2;
-               }
-@@ -883,19 +874,14 @@ void getWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, 
u8 dimm)
-       u32 addr, fine, gross;
-       tempB = 0;
-       index = (u8)(MAX_BYTE_LANES*dimm);
--      if (ByteLane < 4)
--      {
-+      if (ByteLane < 4) {
-               tempB = (u8)(8 * ByteLane);
-               addr = DRAM_CONT_ADD_PHASE_REC_CTRL_LOW;
--      }
--      else if (ByteLane < 8)
--      {
-+      } else if (ByteLane < 8) {
-               tempB1 = (u8)(ByteLane - 4);
-               tempB = (u8)(8 * tempB1);
-               addr = DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH;
--      }
--      else
--      {
-+      } else {
-               tempB = 0;
-               addr = DRAM_CONT_ADD_ECC_PHASE_REC_CTRL;
-       }
-@@ -911,16 +897,13 @@ void getWLByteDelay(sDCTStruct *pDCTData, u8 ByteLane, 
u8 dimm)
-       /* Adjust seed gross delay overflow (greater than 3):
-        * - Adjust the trained gross delay to the original seed gross delay.
-        */
--      if(pDCTData->WLGrossDelay[index+ByteLane] >= 3)
--      {
-+      if (pDCTData->WLGrossDelay[index+ByteLane] >= 3) {
-               gross += pDCTData->WLGrossDelay[index+ByteLane];
-               if(pDCTData->WLGrossDelay[index+ByteLane] & 1)
-                       gross -= 1;
-               else
-                       gross -= 2;
--      }
--      else if((pDCTData->WLGrossDelay[index+ByteLane] == 0) && (gross == 3))
--      {
-+      } else if ((pDCTData->WLGrossDelay[index+ByteLane] == 0) && (gross == 
3)) {
-               /* If seed gross delay is 0 but PRE result gross delay is 3, it 
is negative.
-                * We will then round the negative number to 0.
-                */
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch
 
b/resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch
deleted file mode 100644
index d5a8941..0000000
--- 
a/resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdfam10-Limit-maximum-RAM-clock-to-.patch
+++ /dev/null
@@ -1,121 +0,0 @@
-From 5e830015eefae9024835e76c81715821a55b0853 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <address@hidden>
-Date: Sat, 5 Sep 2015 18:00:27 -0500
-Subject: [PATCH 010/139] northbridge/amd/amdfam10: Limit maximum RAM clock to
- BKDG recommendations
-
-Change-Id: I45eb03a4b351e458e8448245896743bd6fa57637
-Signed-off-by: Timothy Pearson <address@hidden>
----
- src/northbridge/amd/amdfam10/raminit_amdmct.c | 46 +++++++++++++++++++++++----
- src/northbridge/amd/amdmct/wrappers/mcti_d.c  |  2 +-
- 2 files changed, 41 insertions(+), 7 deletions(-)
-
-diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c 
b/src/northbridge/amd/amdfam10/raminit_amdmct.c
-index a585fae..3f33eba 100644
---- a/src/northbridge/amd/amdfam10/raminit_amdmct.c
-+++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c
-@@ -44,29 +44,58 @@ static  void print_tf(const char *func, const char *strval)
- #endif
- }
- 
--static uint16_t mct_MaxLoadFreq(uint8_t count, uint16_t freq)
-+static uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t registered, uint16_t 
freq)
- {
-       /* Return limited maximum RAM frequency */
-       if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
--              if (IS_ENABLED(CONFIG_DIMM_REGISTERED)) {
-+              if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
-                       /* K10 BKDG Rev. 3.62 Table 53 */
-                       if (count > 2) {
-                               /* Limit to DDR2-533 */
-                               if (freq > 266) {
-                                       freq = 266;
--                                      print_tf(__func__, ": More than 2 DIMMs 
on channel; limiting to DDR2-533\n");
-+                                      print_tf(__func__, ": More than 2 
registered DIMMs on channel; limiting to DDR2-533\n");
-                               }
-                       }
--              }
--              else {
-+              } else {
-                       /* K10 BKDG Rev. 3.62 Table 52 */
-                       if (count > 1) {
-                               /* Limit to DDR2-800 */
-                               if (freq > 400) {
-                                       freq = 400;
--                                      print_tf(__func__, ": More than 1 DIMM 
on channel; limiting to DDR2-800\n");
-+                                      print_tf(__func__, ": More than 1 
unbuffered DIMM on channel; limiting to DDR2-800\n");
-+                              }
-+                      }
-+              }
-+      } else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
-+              if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
-+                      /* K10 BKDG Rev. 3.62 Table 34 */
-+                      if (count > 2) {
-+                              /* Limit to DDR3-800 */
-+                              if (freq > 400) {
-+                                      freq = 400;
-+                                      print_tf(__func__, ": More than 2 
registered DIMMs on channel; limiting to DDR3-800\n");
-+                              }
-+                      } else if (count == 2) {
-+                              /* Limit to DDR3-1066 */
-+                              if (freq > 533) {
-+                                      freq = 533;
-+                                      print_tf(__func__, ": 2 registered 
DIMMs on channel; limiting to DDR3-1066\n");
-+                              }
-+                      } else {
-+                              /* Limit to DDR3-1333 */
-+                              if (freq > 666) {
-+                                      freq = 666;
-+                                      print_tf(__func__, ": 1 registered DIMM 
on channel; limiting to DDR3-1333\n");
-                               }
-                       }
-+              } else {
-+                      /* K10 BKDG Rev. 3.62 Table 33 */
-+                      /* Limit to DDR3-1333 */
-+                      if (freq > 666) {
-+                              freq = 666;
-+                              print_tf(__func__, ": unbuffered DIMMs on 
channel; limiting to DDR3-1333\n");
-+                      }
-               }
-       }
- 
-@@ -120,6 +149,9 @@ static uint16_t mct_MaxLoadFreq(uint8_t count, uint16_t 
freq)
- //C32
- #elif CONFIG_CPU_SOCKET_TYPE == 0x14
- #include "../amdmct/mct_ddr3/mctardk5.c"
-+//G34
-+#elif CONFIG_CPU_SOCKET_TYPE == 0x15
-+#include "../amdmct/mct_ddr3/mctardk5.c"
- #endif
- 
- #else  /* DDR2 */
-@@ -207,6 +239,7 @@ static void raminit_amdmct(struct sys_info *sysinfo)
-       printk(BIOS_DEBUG, "raminit_amdmct end:\n");
- }
- 
-+#if !IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
- static void amdmct_cbmem_store_info(struct sys_info *sysinfo)
- {
-       if (!sysinfo)
-@@ -245,3 +278,4 @@ static void amdmct_cbmem_store_info(struct sys_info 
*sysinfo)
-       }
- #endif
- }
-+#endif
-diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c 
b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-index 6465e13..47260f2 100644
---- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-+++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-@@ -322,7 +322,7 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc 
*pDCTstat)
-       }
- 
-       /* Set limits if needed */
--      pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), 
pDCTstat->PresetmaxFreq);
-+      pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), 
(ch1_registered || ch2_registered), pDCTstat->PresetmaxFreq);
- }
- 
- #ifdef UNUSED_CODE
--- 
-1.9.1
-
diff --git 
a/resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
 
b/resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
new file mode 100644
index 0000000..c3abdee
--- /dev/null
+++ 
b/resources/libreboot/patch/kgpe-d16/0010-northbridge-amd-amdmct-Fix-broken-AMD-K10-DDR3-memor.patch
@@ -0,0 +1,3454 @@
+From b79a652d746bc186b0de559aa237462e7ba09109 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <address@hidden>
+Date: Sat, 5 Sep 2015 17:55:58 -0500
+Subject: [PATCH 010/143] northbridge/amd/amdmct: Fix broken AMD K10 DDR3
+ memory initalization
+
+Change-Id: Iab690db769e820600693ad1170085623b177b94e
+Signed-off-by: Timothy Pearson <address@hidden>
+---
+ src/northbridge/amd/amdfam10/raminit_amdmct.c   |    2 +
+ src/northbridge/amd/amdmct/mct/mct_d.c          |    1 -
+ src/northbridge/amd/amdmct/mct_ddr3/mct_d.c     |  177 ++++-
+ src/northbridge/amd/amdmct/mct_ddr3/mct_d.h     |    8 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h |   87 +--
+ src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c  |    6 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c  |  806 ++++++++++++-----------
+ src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c    |    6 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c  |   14 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c  |    3 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctproc.c   |   19 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c    |    5 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c    |  800 +++++++++++-----------
+ src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c  |   18 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c  |   13 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c   |    7 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mctwl.c     |   42 +-
+ src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c   |  267 ++++----
+ src/northbridge/amd/amdmct/wrappers/mcti_d.c    |  110 +---
+ 19 files changed, 1252 insertions(+), 1139 deletions(-)
+
+diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c 
b/src/northbridge/amd/amdfam10/raminit_amdmct.c
+index a0d47f4..a585fae 100644
+--- a/src/northbridge/amd/amdfam10/raminit_amdmct.c
++++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c
+@@ -28,12 +28,14 @@ static  void print_tx(const char *strval, u32 val)
+ }
+ #endif
+ 
++#if (CONFIG_DIMM_SUPPORT & 0x000F)!=0x0005 /* not needed for AMD_FAM10_DDR3 */
+ static  void print_t(const char *strval)
+ {
+ #if CONFIG_DEBUG_RAM_SETUP
+       printk(BIOS_DEBUG, "%s", strval);
+ #endif
+ }
++#endif
+ 
+ static  void print_tf(const char *func, const char *strval)
+ {
+diff --git a/src/northbridge/amd/amdmct/mct/mct_d.c 
b/src/northbridge/amd/amdmct/mct/mct_d.c
+index 3dec934..88910e2 100644
+--- a/src/northbridge/amd/amdmct/mct/mct_d.c
++++ b/src/northbridge/amd/amdmct/mct/mct_d.c
+@@ -542,7 +542,6 @@ static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
+               pDCTstat = pDCTstatA + Node;
+               devx = pDCTstat->dev_map;
+               DramSelBaseAddr = 0;
+-              pDCTstat = pDCTstatA + Node;
+               if (!pDCTstat->GangedMode) {
+                       DramSelBaseAddr = pDCTstat->NodeSysLimit - 
pDCTstat->DCTSysLimit;
+                       /*In unganged mode, we must add DCT0 and DCT1 to 
DCTSysLimit */
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+index 71a6be8..fa59d71 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+@@ -214,6 +214,8 @@ static const u8 Table_DQSRcvEn_Offset[] = 
{0x00,0x01,0x10,0x11,0x2};
+ static const u8 Tab_L1CLKDis[]  = {0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 
0x04};
+ static const u8 Tab_AM3CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
0x00};
+ static const u8 Tab_S1CLKDis[]  = {0xA2, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00};
++static const u8 Tab_C32CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
0x00};   /* Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */
++static const u8 Tab_G34CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
0x00};   /* Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */
+ static const u8 Tab_ManualCLKDis[]= {0x10, 0x04, 0x08, 0x20, 0x00, 0x00, 
0x00, 0x00};
+ 
+ static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF};
+@@ -277,6 +279,11 @@ restartinit:
+       for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
+               struct DCTStatStruc *pDCTstat;
+               pDCTstat = pDCTstatA + Node;
++
++              /* Zero out data structures to avoid false detection of DIMMs */
++              memset(pDCTstat, 0, sizeof(struct DCTStatStruc));
++
++              /* Initialize data structures */
+               pDCTstat->Node_ID = Node;
+               pDCTstat->dev_host = PA_HOST(Node);
+               pDCTstat->dev_map = PA_MAP(Node);
+@@ -284,17 +291,22 @@ restartinit:
+               pDCTstat->dev_nbmisc = PA_NBMISC(Node);
+               pDCTstat->NodeSysBase = node_sys_base;
+ 
++              printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_init Node %d\n", 
Node);
+               mct_init(pMCTstat, pDCTstat);
+               mctNodeIDDebugPort_D();
+               pDCTstat->NodePresent = NodePresent_D(Node);
+               if (pDCTstat->NodePresent) {            /* See if Node is 
there*/
++                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: 
clear_legacy_Mode\n");
+                       clear_legacy_Mode(pMCTstat, pDCTstat);
+                       pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);
+ 
++                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: 
mct_InitialMCT_D\n");
+                       mct_InitialMCT_D(pMCTstat, pDCTstat);
+ 
++                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: 
mctSMBhub_Init\n");
+                       mctSMBhub_Init(Node);           /* Switch SMBUS 
crossbar to proper node*/
+ 
++                      printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_initDCT\n");
+                       mct_initDCT(pMCTstat, pDCTstat);
+                       if (pDCTstat->ErrCode == SC_FatalErr) {
+                               goto fatalexit;         /* any fatal errors?*/
+@@ -345,6 +357,7 @@ restartinit:
+ 
+       mct_FinalMCT_D(pMCTstat, pDCTstatA);
+       printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", 
pMCTstat->GStatus);
++
+       return;
+ 
+ fatalexit:
+@@ -560,7 +573,6 @@ static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
+               pDCTstat = pDCTstatA + Node;
+               devx = pDCTstat->dev_map;
+               DramSelBaseAddr = 0;
+-              pDCTstat = pDCTstatA + Node; /* ??? */
+               if (!pDCTstat->GangedMode) {
+                       DramSelBaseAddr = pDCTstat->NodeSysLimit - 
pDCTstat->DCTSysLimit;
+                       /*In unganged mode, we must add DCT0 and DCT1 to 
DCTSysLimit */
+@@ -645,6 +657,7 @@ static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
+               devx = pDCTstat->dev_map;
+ 
+               if (pDCTstat->NodePresent) {
++                      printk(BIOS_DEBUG, " Copy dram map from Node 0 to Node 
%02x \n", Node);
+                       reg = 0x40;             /*Dram Base 0*/
+                       do {
+                               val = Get_NB32(dev, reg);
+@@ -1162,7 +1175,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
+ 
+       /* Program DRAM Timing values */
+       DramTimingLo = 0;       /* Dram Timing Low init */
+-      val = pDCTstat->CASL - 2; /* pDCTstat.CASL to reg. definition */
++      val = pDCTstat->CASL - 4; /* pDCTstat.CASL to reg. definition */
+       DramTimingLo |= val;
+ 
+       val = pDCTstat->Trcd - Bias_TrcdT;
+@@ -1406,18 +1419,16 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
+       else if (tCKproposed16x <= 24) {
+               pDCTstat->TargetFreq = 6;
+               tCKproposed16x = 24;
+-      }
+-      else if (tCKproposed16x <= 30) {
++      } else if (tCKproposed16x <= 30) {
+               pDCTstat->TargetFreq = 5;
+               tCKproposed16x = 30;
+-      }
+-      else {
++      } else {
+               pDCTstat->TargetFreq = 4;
+               tCKproposed16x = 40;
+       }
+       /* Running through this loop twice:
+          - First time find tCL at target frequency
+-         - Second tim find tCL at 400MHz */
++         - Second time find tCL at 400MHz */
+ 
+       for (;;) {
+               CLT_Fail = 0;
+@@ -1451,7 +1462,7 @@ static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
+                       CLT_Fail = 1;
+               /* get CL and T */
+               if (!CLT_Fail) {
+-                      bytex = CLactual - 2;
++                      bytex = CLactual;
+                       if (tCKproposed16x == 20)
+                               byte = 7;
+                       else if (tCKproposed16x == 24)
+@@ -1632,7 +1643,7 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
+               val = 0x0f; /* recommended setting (default) */
+       DramConfigHi |= val << 24;
+ 
+-      if (pDCTstat->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Bx))
++      if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx | AMD_DR_Bx))
+               DramConfigHi |= 1 << DcqArbBypassEn;
+ 
+       /* Build MemClkDis Value from Dram Timing Lo and
+@@ -1657,6 +1668,10 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
+                               p = Tab_L1CLKDis;
+                       else if (byte == PT_M2 || byte == PT_AS)
+                               p = Tab_AM3CLKDis;
++                      else if (byte == PT_C3)
++                              p = Tab_C32CLKDis;
++                      else if (byte == PT_GR)
++                              p = Tab_G34CLKDis;
+                       else
+                               p = Tab_S1CLKDis;
+ 
+@@ -2102,8 +2117,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
+                               if (byte == JED_RDIMM || byte == JED_MiniRDIMM) 
{
+                                       RegDIMMPresent |= 1 << i;
+                                       pDCTstat->DimmRegistered[i] = 1;
+-                              }
+-                              else {
++                              } else {
+                                       pDCTstat->DimmRegistered[i] = 0;
+                               }
+                               /* Check ECC capable */
+@@ -2977,9 +2991,9 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat,
+               } else {        /* For Dx CPU */
+                       val = 0x0CE00F00 | 1 << 29/* FlushWrOnStpGnt */;
+                       if (!(pDCTstat->GangedMode))
+-                              val |= 0x20; /* MctWrLimit =  8 for Unganed 
mode */
++                              val |= 0x20; /* MctWrLimit =  8 for Unganged 
mode */
+                       else
+-                              val |= 0x40; /* MctWrLimit =  16 for ganed mode 
*/
++                              val |= 0x40; /* MctWrLimit =  16 for ganged 
mode */
+                       Set_NB32(pDCTstat->dev_dct, 0x11C, val);
+ 
+                       val = Get_NB32(pDCTstat->dev_dct, 0x1B0);
+@@ -3414,6 +3428,138 @@ static void mct_BeforeDramInit_Prod_D(struct 
MCTStatStruc *pMCTstat,
+                       Set_NB32(dev,  0x98 + reg_off, 0x0D000030);
+                       Set_NB32(dev,  0x9C + reg_off, dword);
+                       Set_NB32(dev,  0x98 + reg_off, 0x4D040F30);
++
++                      /* FIXME
++                       * Mainboards need to be able to specify the maximum 
number of DIMMs installable per channel
++                       * For now assume a maximum of 2 DIMMs per channel can 
be installed
++                       */
++                      uint8_t MaxDimmsInstallable = 2;
++
++                      /* Obtain number of DIMMs on channel */
++                      uint8_t dimm_count = pDCTstat->MAdimms[i];
++                      uint8_t rank_count_dimm0;
++                      uint8_t rank_count_dimm1;
++                      uint32_t odt_pattern_0;
++                      uint32_t odt_pattern_1;
++                      uint32_t odt_pattern_2;
++                      uint32_t odt_pattern_3;
++
++                      /* Select appropriate ODT pattern for installed DIMMs
++                       * Refer to the BKDG Rev. 3.62, page 120 onwards
++                       */
++                      if 
(pDCTstat->C_DCTPtr[i]->Status[DCT_STATUS_REGISTERED]) {
++                              if (MaxDimmsInstallable == 2) {
++                                      if (dimm_count == 1) {
++                                              /* 1 DIMM detected */
++                                              rank_count_dimm1 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[1];
++                                              if (rank_count_dimm1 == 1) {
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x00020000;
++                                              } else if (rank_count_dimm1 == 
2) {
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x02080000;
++                                              } else if (rank_count_dimm1 == 
4) {
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x020a0000;
++                                                      odt_pattern_3 = 
0x080a0000;
++                                              } else {
++                                                      /* Fallback */
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x00000000;
++                                              }
++                                      } else {
++                                              /* 2 DIMMs detected */
++                                              rank_count_dimm0 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[0];
++                                              rank_count_dimm1 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[1];
++                                              if ((rank_count_dimm0 < 4) && 
(rank_count_dimm1 < 4)) {
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x01010202;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x09030603;
++                                              } else if ((rank_count_dimm0 < 
4) && (rank_count_dimm1 == 4)) {
++                                                      odt_pattern_0 = 
0x01010000;
++                                                      odt_pattern_1 = 
0x01010a0a;
++                                                      odt_pattern_2 = 
0x01090000;
++                                                      odt_pattern_3 = 
0x01030e0b;
++                                              } else if ((rank_count_dimm0 == 
4) && (rank_count_dimm1 < 4)) {
++                                                      odt_pattern_0 = 
0x00000202;
++                                                      odt_pattern_1 = 
0x05050202;
++                                                      odt_pattern_2 = 
0x00000206;
++                                                      odt_pattern_3 = 
0x0d070203;
++                                              } else if ((rank_count_dimm0 == 
4) && (rank_count_dimm1 == 4)) {
++                                                      odt_pattern_0 = 
0x05050a0a;
++                                                      odt_pattern_1 = 
0x05050a0a;
++                                                      odt_pattern_2 = 
0x050d0a0e;
++                                                      odt_pattern_3 = 
0x05070a0b;
++                                              } else {
++                                                      /* Fallback */
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x00000000;
++                                              }
++                                      }
++                              } else {
++                                      /* FIXME
++                                       * 3 DIMMs per channel UNIMPLEMENTED
++                                       */
++                                      odt_pattern_0 = 0x00000000;
++                                      odt_pattern_1 = 0x00000000;
++                                      odt_pattern_2 = 0x00000000;
++                                      odt_pattern_3 = 0x00000000;
++                              }
++                      } else {
++                              if (MaxDimmsInstallable == 2) {
++                                      if (dimm_count == 1) {
++                                              /* 1 DIMM detected */
++                                              rank_count_dimm1 = 
pDCTstat->C_DCTPtr[i]->DimmRanks[1];
++                                              if (rank_count_dimm1 == 1) {
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x00020000;
++                                              } else if (rank_count_dimm1 == 
2) {
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x02080000;
++                                              } else {
++                                                      /* Fallback */
++                                                      odt_pattern_0 = 
0x00000000;
++                                                      odt_pattern_1 = 
0x00000000;
++                                                      odt_pattern_2 = 
0x00000000;
++                                                      odt_pattern_3 = 
0x00000000;
++                                              }
++                                      } else {
++                                              /* 2 DIMMs detected */
++                                              odt_pattern_0 = 0x00000000;
++                                              odt_pattern_1 = 0x01010202;
++                                              odt_pattern_2 = 0x00000000;
++                                              odt_pattern_3 = 0x09030603;
++                                      }
++                              } else {
++                                      /* FIXME
++                                       * 3 DIMMs per channel UNIMPLEMENTED
++                                       */
++                                      odt_pattern_0 = 0x00000000;
++                                      odt_pattern_1 = 0x00000000;
++                                      odt_pattern_2 = 0x00000000;
++                                      odt_pattern_3 = 0x00000000;
++                              }
++                      }
++
++                      /* Program ODT pattern */
++                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x180, 
odt_pattern_1);
++                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x181, 
odt_pattern_0);
++                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x182, 
odt_pattern_3);
++                      Set_NB32_index_wait(dev, 0xf0 + reg_off, 0x183, 
odt_pattern_2);
+               }
+       }
+ }
+@@ -3657,6 +3803,7 @@ static void mct_BeforeDQSTrain_D(struct MCTStatStruc 
*pMCTstat,
+       }
+ }
+ 
++/* Erratum 350 */
+ static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
+                                       struct DCTStatStruc *pDCTstat, u8 dct)
+ {
+@@ -3692,11 +3839,11 @@ static void mct_ResetDLL_D(struct MCTStatStruc 
*pMCTstat,
+                               mct_Read1LTestPattern_D(pMCTstat, pDCTstat, 
addr);      /* cache fills */
+ 
+                               /* Write 0000_8000h to register 
F2x[1,0]9C_xD080F0C */
+-                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0x4D080F0C, 0x00008000);
++                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0xD080F0C, 0x00008000);
+                               mct_Wait(80); /* wait >= 300ns */
+ 
+                               /* Write 0000_0000h to register 
F2x[1,0]9C_xD080F0C */
+-                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0x4D080F0C, 0x00000000);
++                              Set_NB32_index_wait(dev, 0x98 + reg_off, 
0xD080F0C, 0x00000000);
+                               mct_Wait(800); /* wait >= 2us */
+                               break;
+                       }
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h 
b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
+index e2d7aa8..219aa42 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
+@@ -499,7 +499,7 @@ struct DCTStatStruc {              /* A per Node 
structure*/
+               /* CHB DIMM0 Byte 0 - 7  TxDqs */
+               /* CHB DIMM1 Byte 0 - 7  TxDqs */
+               /* CHB DIMM1 Byte 0 - 7  TxDqs */
+-      u8 CH_D_B_RCVRDLY[2][4][8];     /* [A/B] [DIMM0-3] [DQS] */
++      u16 CH_D_B_RCVRDLY[2][4][8];    /* [A/B] [DIMM0-3] [DQS] */
+               /* CHA DIMM 0 Receiver Enable Delay*/
+               /* CHA DIMM 1 Receiver Enable Delay*/
+               /* CHA DIMM 2 Receiver Enable Delay*/
+@@ -509,7 +509,7 @@ struct DCTStatStruc {              /* A per Node 
structure*/
+               /* CHB DIMM 1 Receiver Enable Delay*/
+               /* CHB DIMM 2 Receiver Enable Delay*/
+               /* CHB DIMM 3 Receiver Enable Delay*/
+-      u8 CH_D_BC_RCVRDLY[2][4];
++      u16 CH_D_BC_RCVRDLY[2][4];
+               /* CHA DIMM 0 - 4 Check Byte Receiver Enable Delay*/
+               /* CHB DIMM 0 - 4 Check Byte Receiver Enable Delay*/
+       u8 DIMMValidDCT[2];     /* DIMM# in DCT0*/
+@@ -769,7 +769,7 @@ u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass);
+ u32 SetupDqsPattern_1PassA(u8 Pass);
+ u32 SetupDqsPattern_1PassB(u8 Pass);
+ u8 mct_Get_Start_RcvrEnDly_1Pass(u8 Pass);
+-u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 
RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass);
++u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, 
u16 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass);
+ void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
+ void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
+ u32 mctGetLogicalCPUID(u32 Node);
+@@ -779,7 +779,7 @@ void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, 
struct DCTStatStruc *pDCTs
+ void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
+ void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA);
+ void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,struct DCTStatStruc 
*pDCTstatA);
+-void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 
FinalValue, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 
Pass);
++void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u8 
FinalValue, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 
Pass);
+ void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel);
+ void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u32 dct);
+ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u8 dct);
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h 
b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
+index 60f98bc..c40ea1a 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -103,10 +104,10 @@ static void proc_CLFLUSH(u32 addr_hi)
+ 
+       __asm__ volatile (
+               /* clflush fs:[eax] */
+-              "outb %%al, $0xed\n\t"  /* _EXECFENCE */
+-               "clflush %%fs:(%0)\n\t"
++              "outb %%al, $0xed\n\t"  /* _EXECFENCE */
++              "clflush %%fs:(%0)\n\t"
+               "mfence\n\t"
+-               ::"a" (addr_hi<<8)
++              ::"a" (addr_hi<<8)
+       );
+ }
+ 
+@@ -141,6 +142,24 @@ static u32 read32_fs(u32 addr_lo)
+       return value;
+ }
+ 
++static uint64_t read64_fs(uint32_t addr_lo)
++{
++      uint64_t value = 0;
++      uint32_t value_lo;
++      uint32_t value_hi;
++
++      __asm__ volatile (
++              "outb %%al, $0xed\n\t"  /* _EXECFENCE */
++              "mfence\n\t"
++              "movl %%fs:(%2), %0\n\t"
++              "movl %%fs:(%3), %1\n\t"
++              :"=c"(value_lo), "=d"(value_hi): "a" (addr_lo), "b" (addr_lo + 
4) : "memory"
++      );
++      value |= value_lo;
++      value |= ((uint64_t)value_hi) << 32;
++      return value;
++}
++
+ #ifdef UNUSED_CODE
+ static u8 read8_fs(u32 addr_lo)
+ {
+@@ -210,68 +229,6 @@ static __attribute__((noinline)) void 
FlushDQSTestPattern_L18(u32 addr_lo)
+       );
+ }
+ 
+-static void ReadL18TestPattern(u32 addr_lo)
+-{
+-      /* set fs and use fs prefix to access the mem */
+-      __asm__ volatile (
+-              "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
+-              "movl %%fs:-128(%%esi), %%eax\n\t"      /* TestAddr cache line 
*/
+-              "movl %%fs:-64(%%esi), %%eax\n\t"       /* +1 */
+-              "movl %%fs:(%%esi), %%eax\n\t"          /* +2 */
+-              "movl %%fs:64(%%esi), %%eax\n\t"        /* +3 */
+-
+-              "movl %%fs:-128(%%edi), %%eax\n\t"      /* +4 */
+-              "movl %%fs:-64(%%edi), %%eax\n\t"       /* +5 */
+-              "movl %%fs:(%%edi), %%eax\n\t"          /* +6 */
+-              "movl %%fs:64(%%edi), %%eax\n\t"        /* +7 */
+-
+-              "movl %%fs:-128(%%ebx), %%eax\n\t"      /* +8 */
+-              "movl %%fs:-64(%%ebx), %%eax\n\t"       /* +9 */
+-              "movl %%fs:(%%ebx), %%eax\n\t"          /* +10 */
+-              "movl %%fs:64(%%ebx), %%eax\n\t"        /* +11 */
+-
+-              "movl %%fs:-128(%%ecx), %%eax\n\t"      /* +12 */
+-              "movl %%fs:-64(%%ecx), %%eax\n\t"       /* +13 */
+-              "movl %%fs:(%%ecx), %%eax\n\t"          /* +14 */
+-              "movl %%fs:64(%%ecx), %%eax\n\t"        /* +15 */
+-
+-              "movl %%fs:-128(%%edx), %%eax\n\t"      /* +16 */
+-              "movl %%fs:-64(%%edx), %%eax\n\t"       /* +17 */
+-              "mfence\n\t"
+-
+-               :: "a"(0), "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
+-                  "d" (addr_lo +128+16*64), "S"(addr_lo+128),
+-                  "D"(addr_lo+128+4*64)
+-      );
+-
+-}
+-
+-static void ReadL9TestPattern(u32 addr_lo)
+-{
+-
+-      /* set fs and use fs prefix to access the mem */
+-      __asm__ volatile (
+-              "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
+-
+-              "movl %%fs:-128(%%ecx), %%eax\n\t"      /* TestAddr cache line 
*/
+-              "movl %%fs:-64(%%ecx), %%eax\n\t"       /* +1 */
+-              "movl %%fs:(%%ecx), %%eax\n\t"          /* +2 */
+-              "movl %%fs:64(%%ecx), %%eax\n\t"        /* +3 */
+-
+-              "movl %%fs:-128(%%edx), %%eax\n\t"      /* +4 */
+-              "movl %%fs:-64(%%edx), %%eax\n\t"       /* +5 */
+-              "movl %%fs:(%%edx), %%eax\n\t"          /* +6 */
+-              "movl %%fs:64(%%edx), %%eax\n\t"        /* +7 */
+-
+-              "movl %%fs:-128(%%ebx), %%eax\n\t"      /* +8 */
+-              "mfence\n\t"
+-
+-               :: "a"(0), "b" (addr_lo+128+8*64), "c"(addr_lo+128),
+-                  "d"(addr_lo+128+4*64)
+-      );
+-
+-}
+-
+ static void ReadMaxRdLat1CLTestPattern_D(u32 addr)
+ {
+       SetUpperFSbase(addr);
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c
+index ae1654c..99a2628 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -17,7 +18,7 @@
+  * Foundation, Inc.
+  */
+ 
+-/* The socket type F (1207), Fr2, G (1207) are not tested.
++/* The socket type Fr2, G (1207) are not tested.
+  */
+ 
+ static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
+@@ -79,8 +80,7 @@ static void Get_ChannelPS_Cfg0_D( u8 MAAdimms, u8 Speed, u8 
MAAload,
+                       else
+                               *AddrTmgCTL = 0x00353935;
+               }
+-      }
+-      else {
++      } else {
+               if(Speed == 4) {
+                       *AddrTmgCTL = 0x00000000;
+                       if (MAAdimms == 3)
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+index 404727b..cc2f43a 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -22,13 +23,6 @@ static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat,
+                               u8 scale, u8 ChipSel);
+ static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 ChipSel);
+-static u8 MiddleDQS_D(u8 min, u8 max);
+-static void TrainReadDQS_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u8 cs_start);
+-static void TrainWriteDQS_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u8 cs_start);
+ static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat,
+                                       struct DCTStatStruc *pDCTstat,
+                                       u32 TestAddr_lo);
+@@ -43,31 +37,19 @@ static void FlushDQSTestPattern_D(struct DCTStatStruc 
*pDCTstat,
+                                       u32 addr_lo);
+ static void SetTargetWTIO_D(u32 TestAddr);
+ static void ResetTargetWTIO_D(void);
+-static void ReadDQSTestPattern_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat,
+-                                      u32 TestAddr_lo);
+-static void mctEngDQSwindow_Save_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
+-                                      u8 RnkDlyFilterMin, u8 RnkDlyFilterMax);
+ void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index);
+ u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat);
+ static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat,
+                                       struct DCTStatStruc *pDCTstat,
+                                       u8 ChipSel);
+-static void mct_SetDQSDelayAllCSR_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat,
+-                                      u8 cs_start);
+ u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 Channel,
+                               u8 receiver, u8 *valid);
+ static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat,
+                               u32 *buffer);
+-
+-static void StoreWrRdDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
+-                                    u8 RnkDlyFilterMin, u8 RnkDlyFilterMax);
++static void proc_IOCLFLUSH_D(u32 addr_hi);
+ 
+ static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat, u8 ChipSel);
+ 
+@@ -286,20 +268,99 @@ static void CalcEccDQSPos_D(struct MCTStatStruc 
*pMCTstat,
+       pDCTstat->DQSDelay = (u8)DQSDelay;
+ }
+ 
++static void write_dqs_write_data_timing_registers(uint16_t* delay, uint32_t 
dev, uint8_t dimm, uint32_t index_reg)
++{
++      uint32_t dword;
++
++      /* Lanes 0 - 3 */
++      dword = Get_NB32_index_wait(dev, index_reg, 0x1 | (dimm << 8));
++      dword &= ~0x7f7f7f7f;
++      dword |= (delay[3] & 0x7f) << 24;
++      dword |= (delay[2] & 0x7f) << 16;
++      dword |= (delay[1] & 0x7f) << 8;
++      dword |= delay[0] & 0x7f;
++      Set_NB32_index_wait(dev, index_reg, 0x1 | (dimm << 8), dword);
++
++      /* Lanes 4 - 7 */
++      dword = Get_NB32_index_wait(dev, index_reg, 0x2 | (dimm << 8));
++      dword &= ~0x7f7f7f7f;
++      dword |= (delay[7] & 0x7f) << 24;
++      dword |= (delay[6] & 0x7f) << 16;
++      dword |= (delay[5] & 0x7f) << 8;
++      dword |= delay[4] & 0x7f;
++      Set_NB32_index_wait(dev, index_reg, 0x2 | (dimm << 8), dword);
++
++      /* Lane 8 (ECC) */
++      dword = Get_NB32_index_wait(dev, index_reg, 0x3 | (dimm << 8));
++      dword &= ~0x0000007f;
++      dword |= delay[8] & 0x7f;
++      Set_NB32_index_wait(dev, index_reg, 0x3 | (dimm << 8), dword);
++}
++
++static void write_dqs_read_data_timing_registers(uint16_t* delay, uint32_t 
dev, uint8_t dimm, uint32_t index_reg)
++{
++      uint32_t dword;
++
++      /* Lanes 0 - 3 */
++      dword = Get_NB32_index_wait(dev, index_reg, 0x5 | (dimm << 8));
++      dword &= ~0x3f3f3f3f;
++      dword |= (delay[3] & 0x3f) << 24;
++      dword |= (delay[2] & 0x3f) << 16;
++      dword |= (delay[1] & 0x3f) << 8;
++      dword |= delay[0] & 0x3f;
++      Set_NB32_index_wait(dev, index_reg, 0x5 | (dimm << 8), dword);
++
++      /* Lanes 4 - 7 */
++      dword = Get_NB32_index_wait(dev, index_reg, 0x6 | (dimm << 8));
++      dword &= ~0x3f3f3f3f;
++      dword |= (delay[7] & 0x3f) << 24;
++      dword |= (delay[6] & 0x3f) << 16;
++      dword |= (delay[5] & 0x3f) << 8;
++      dword |= delay[4] & 0x3f;
++      Set_NB32_index_wait(dev, index_reg, 0x6 | (dimm << 8), dword);
++
++      /* Lane 8 (ECC) */
++      dword = Get_NB32_index_wait(dev, index_reg, 0x7 | (dimm << 8));
++      dword &= ~0x0000003f;
++      dword |= delay[8] & 0x3f;
++      Set_NB32_index_wait(dev, index_reg, 0x7 | (dimm << 8), dword);
++}
++
++/* DQS Position Training
++ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.3
++ */
+ static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u8 cs_start)
++                              struct DCTStatStruc *pDCTstat)
+ {
+       u32 Errors;
+-      u8 Channel, DQSWrDelay;
++      u8 Channel;
++      u8 Receiver;
+       u8 _DisableDramECC = 0;
+-      u32 PatternBuffer[292];
++      u32 PatternBuffer[304]; /* 288 + 16 */
+       u8 _Wrap32Dis = 0, _SSE2 = 0;
+-      u8 dqsWrDelay_end;
+ 
++      u32 dev;
+       u32 addr;
++      u8 valid;
+       u32 cr4;
+       u32 lo, hi;
++      u32 index_reg;
++      uint32_t TestAddr;
++
++      uint8_t dual_rank;
++      uint8_t iter;
++      uint8_t lane;
++      uint16_t bytelane_test_results;
++      uint16_t current_write_dqs_delay[MAX_BYTE_LANES];
++      uint16_t current_read_dqs_delay[MAX_BYTE_LANES];
++      uint16_t write_dqs_delay_stepping_done[MAX_BYTE_LANES];
++      uint8_t dqs_read_results_array[2][MAX_BYTE_LANES][64];          /* 
[rank][lane][step] */
++      uint8_t dqs_write_results_array[2][MAX_BYTE_LANES][128];        /* 
[rank][lane][step] */
++
++      uint8_t last_pos = 0;
++      uint8_t cur_count = 0;
++      uint8_t best_pos = 0;
++      uint8_t best_count = 0;
+ 
+       print_debug_dqs("\nTrainDQSRdWrPos: Node_ID ", pDCTstat->Node_ID, 0);
+       cr4 = read_cr4();
+@@ -323,50 +384,363 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc 
*pMCTstat,
+       SetupDqsPattern_D(pMCTstat, pDCTstat, PatternBuffer);
+ 
+       /* mct_BeforeTrainDQSRdWrPos_D */
+-      dqsWrDelay_end = 0x20;
++
++      dev = pDCTstat->dev_dct;
++      pDCTstat->Direction = DQS_READDIR;
++
++      /* 2.8.9.9.3 (2)
++       * Loop over each channel, lane, and rank
++       */
++
++      /* NOTE
++       * The BKDG originally stated to iterate over lane, then rank, however 
this process is quite slow
++       * compared to an equivalent loop over rank, then lane as the latter 
allows multiple lanes to be
++       * tested simultaneously, thus improving performance by around 8x.
++       */
+ 
+       Errors = 0;
+       for (Channel = 0; Channel < 2; Channel++) {
+-              print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ",Channel, 1);
++              print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ", Channel, 1);
+               pDCTstat->Channel = Channel;
+ 
+               if (pDCTstat->DIMMValidDCT[Channel] == 0)       /* 
mct_BeforeTrainDQSRdWrPos_D */
+                       continue;
+-              pDCTstat->DqsRdWrPos_Saved = 0;
+-              for ( DQSWrDelay = 0; DQSWrDelay < dqsWrDelay_end; 
DQSWrDelay++) {
+-                      pDCTstat->DQSDelay = DQSWrDelay;
+-                      pDCTstat->Direction = DQS_WRITEDIR;
+-                      mct_SetDQSDelayAllCSR_D(pMCTstat, pDCTstat, cs_start);
+-
+-                      print_debug_dqs("\t\tTrainDQSRdWrPos: 21 DQSWrDelay ", 
DQSWrDelay, 2);
+-                      TrainReadDQS_D(pMCTstat, pDCTstat, cs_start);
+-                      print_debug_dqs("\t\tTrainDQSRdWrPos: 21 
DqsRdWrPos_Saved ", pDCTstat->DqsRdWrPos_Saved, 2);
+-                      if (pDCTstat->DqsRdWrPos_Saved == 0xFF)
+-                              break;
+-
+-                      print_debug_dqs("\t\tTrainDQSRdWrPos: 22 TrainErrors 
",pDCTstat->TrainErrors, 2);
+-                      if (pDCTstat->TrainErrors == 0) {
++
++              index_reg = 0x98 + 0x100 * Channel;
++
++              dual_rank = 0;
++              Receiver = mct_InitReceiver_D(pDCTstat, Channel);
++              /* There are four receiver pairs, loosely associated with 
chipselects.
++              * This is essentially looping over each rank of each DIMM.
++              */
++              for (; Receiver < 8; Receiver++) {
++                      if ((Receiver & 0x1) == 0) {
++                              /* Even rank of DIMM */
++                              if(mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, 
Channel, Receiver+1))
++                                      dual_rank = 1;
++                              else
++                                      dual_rank = 0;
++                      }
++
++                      if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, 
Receiver)) {
++                              continue;
++                      }
++
++                      /* Select the base test address for the current rank */
++                      TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, 
Channel, Receiver, &valid);
++                      if (!valid) {   /* Address not supported on current CS 
*/
++                              continue;
++                      }
++
++                      print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 14 TestAddr 
", TestAddr, 4);
++                      SetUpperFSbase(TestAddr);       /* fs:eax=far ptr to 
target */
++
++                      print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 12 Receiver 
", Receiver, 2);
++
++                      /* 2.8.9.9.3 (DRAM Write Data Timing Loop)
++                       * Iterate over all possible DQS delay values (0x0 - 
0x7f)
++                       */
++                      uint8_t test_write_dqs_delay = 0;
++                      uint8_t test_read_dqs_delay = 0;
++                      uint8_t passing_dqs_delay_found[MAX_BYTE_LANES];
++
++                      /* Initialize variables */
++                      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
++                              current_write_dqs_delay[lane] = 0;
++                              passing_dqs_delay_found[lane] = 0;
++                              write_dqs_delay_stepping_done[lane] = 0;
++                      }
++
++                      for (test_write_dqs_delay = 0; test_write_dqs_delay < 
128; test_write_dqs_delay++) {
++                              print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 16 
test_write_dqs_delay ", test_write_dqs_delay, 6);
++
++                              /* Break out of loop if passing window already 
found, */
++                              if (write_dqs_delay_stepping_done[0] && 
write_dqs_delay_stepping_done[1]
++                                      && write_dqs_delay_stepping_done[2] && 
write_dqs_delay_stepping_done[3]
++                                      && write_dqs_delay_stepping_done[4] && 
write_dqs_delay_stepping_done[5]
++                                      && write_dqs_delay_stepping_done[6] && 
write_dqs_delay_stepping_done[7])
+                                       break;
++
++                              /* Commit the current Write Data Timing 
settings to the hardware registers */
++                              
write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver 
>> 1), index_reg);
++
++                              /* Write the DRAM training pattern to the base 
test address */
++                              WriteDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8);
++
++                              /* 2.8.9.9.3 (DRAM Read DQS Timing Control Loop)
++                               * Iterate over all possible DQS delay values 
(0x0 - 0x3f)
++                               */
++                              for (test_read_dqs_delay = 0; 
test_read_dqs_delay < 64; test_read_dqs_delay++) {
++                                      
print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 test_read_dqs_delay ", 
test_read_dqs_delay, 6);
++
++                                      /* Initialize Read DQS Timing Control 
settings for this iteration */
++                                      for (lane = 0; lane < MAX_BYTE_LANES; 
lane++)
++                                              if 
(!write_dqs_delay_stepping_done[lane])
++                                                      
current_read_dqs_delay[lane] = test_read_dqs_delay;
++
++                                      /* Commit the current Read DQS Timing 
Control settings to the hardware registers */
++                                      
write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 
1), index_reg);
++
++                                      /* Initialize test result variable */
++                                      bytelane_test_results = 0xff;
++
++                                      /* Read the DRAM training pattern from 
the base test address three times
++                                       * NOTE
++                                       * While the BKDG states to read three 
times this is probably excessive!
++                                       * Decrease training time by only 
reading the test pattern once per iteration
++                                       */
++                                      for (iter = 0; iter < 1; iter++) {
++                                              /* Flush caches */
++                                              SetTargetWTIO_D(TestAddr);
++                                              FlushDQSTestPattern_D(pDCTstat, 
TestAddr << 8);
++                                              ResetTargetWTIO_D();
++
++                                              /* Read and compare pattern */
++                                              bytelane_test_results &= 
(CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 
:: Lane 0] 0=fail, 1=pass */
++
++                                              /* If all lanes have already 
failed testing bypass remaining re-read attempt(s) */
++                                              if (bytelane_test_results == 
0x0)
++                                                      break;
++                                      }
++
++                                      /* Store any lanes that passed testing 
for later use */
++                                      for (lane = 0; lane < 8; lane++)
++                                              if 
(!write_dqs_delay_stepping_done[lane])
++                                                      
dqs_read_results_array[Receiver & 0x1][lane][test_read_dqs_delay] = 
(!!(bytelane_test_results & (1 << lane)));
++
++                                      
print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 162 bytelane_test_results ", 
bytelane_test_results, 6);
++                              }
++
++                              for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
++                                      if (write_dqs_delay_stepping_done[lane])
++                                              continue;
++
++                                      /* Determine location and length of 
longest consecutive string of passing values
++                                       * Output is stored in best_pos and 
best_count
++                                       */
++                                      last_pos = 0;
++                                      cur_count = 0;
++                                      best_pos = 0;
++                                      best_count = 0;
++                                      for (iter = 0; iter < 64; iter++) {
++                                              if 
((dqs_read_results_array[Receiver & 0x1][lane][iter]) && (iter < 63)) {
++                                                      /* Pass */
++                                                      cur_count++;
++                                              } else {
++                                                      /* Failure or end of 
loop */
++                                                      if (cur_count > 
best_count) {
++                                                              best_count = 
cur_count;
++                                                              best_pos = 
last_pos;
++                                                      }
++                                                      cur_count = 0;
++                                                      last_pos = iter;
++                                              }
++                                      }
++
++                                      if (best_count > 2) {
++                                              /* Exit the DRAM Write Data 
Timing Loop after programming the Read DQS Timing Control
++                                               * register with the center of 
the passing window
++                                               */
++                                              current_read_dqs_delay[lane] = 
(best_pos + (best_count / 2));
++                                              passing_dqs_delay_found[lane] = 
1;
++
++                                              /* Commit the current Read DQS 
Timing Control settings to the hardware registers */
++                                              
write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 
1), index_reg);
++
++                                              /* Exit the DRAM Write Data 
Timing Loop */
++                                              
write_dqs_delay_stepping_done[lane] = 1;
++
++                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest passing region ", 
best_count, 4);
++                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest passing region start ", 
best_pos, 4);
++                                      }
++
++                                      /* Increment the DQS Write Delay value 
if needed for the next DRAM Write Data Timing Loop iteration */
++                                      if 
(!write_dqs_delay_stepping_done[lane])
++                                              current_write_dqs_delay[lane]++;
++                              }
+                       }
+-                      Errors |= pDCTstat->TrainErrors;
+-              }
+ 
+-              pDCTstat->DqsRdWrPos_Saved = 0;
+-              if (DQSWrDelay < dqsWrDelay_end) {
+-                      Errors = 0;
++                      /* Flag failure(s) if present */
++                      for (lane = 0; lane < 8; lane++) {
++                              if (!passing_dqs_delay_found[lane]) {
++                                      
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 121 Unable to find passing region for 
lane ", lane, 2);
++
++                                      /* Flag absence of passing window */
++                                      Errors |= 1 << SB_NODQSPOS;
++                              }
++                      }
++
++                      /* Iterate over all possible Write Data Timing values 
(0x0 - 0x7f)
++                       * Note that the Read DQS Timing Control was calibrated 
/ centered in the prior nested loop
++                       */
++                      for (test_write_dqs_delay = 0; test_write_dqs_delay < 
128; test_write_dqs_delay++) {
++                              /* Initialize Write Data Timing settings for 
this iteration */
++                              for (lane = 0; lane < MAX_BYTE_LANES; lane++)
++                                      current_write_dqs_delay[lane] = 
test_write_dqs_delay;
++
++                              /* Commit the current Write Data Timing 
settings to the hardware registers */
++                              
write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver 
>> 1), index_reg);
++
++                              /* Write the DRAM training pattern to the base 
test address */
++                              WriteDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8);
++
++                              /* Flush caches */
++                              SetTargetWTIO_D(TestAddr);
++                              FlushDQSTestPattern_D(pDCTstat, TestAddr << 8);
++                              ResetTargetWTIO_D();
++
++                              /* Read and compare pattern from the base test 
address */
++                              bytelane_test_results = 
(CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 
:: Lane 0] 0=fail, 1=pass */
++
++                              /* Store any lanes that passed testing for 
later use */
++                              for (lane = 0; lane < 8; lane++)
++                                      dqs_write_results_array[Receiver & 
0x1][lane][test_write_dqs_delay] = (!!(bytelane_test_results & (1 << lane)));
++                      }
++
++                      for (lane = 0; lane < 8; lane++) {
++                              if ((!dual_rank) || (dual_rank && (Receiver & 
0x1))) {
++
++#ifdef PRINT_PASS_FAIL_BITMAPS
++                                      for (iter = 0; iter < 64; iter++) {
++                                              if 
(dqs_read_results_array[0][lane][iter])
++                                                      printk(BIOS_DEBUG, "+");
++                                              else
++                                                      printk(BIOS_DEBUG, ".");
++                                      }
++                                      printk(BIOS_DEBUG, "\n");
++                                      for (iter = 0; iter < 64; iter++) {
++                                              if 
(dqs_read_results_array[1][lane][iter])
++                                                      printk(BIOS_DEBUG, "+");
++                                              else
++                                                      printk(BIOS_DEBUG, ".");
++                                      }
++                                      printk(BIOS_DEBUG, "\n\n");
++                                      for (iter = 0; iter < 128; iter++) {
++                                              if 
(dqs_write_results_array[0][lane][iter])
++                                                      printk(BIOS_DEBUG, "+");
++                                              else
++                                                      printk(BIOS_DEBUG, ".");
++                                      }
++                                      printk(BIOS_DEBUG, "\n");
++                                      for (iter = 0; iter < 128; iter++) {
++                                              if 
(dqs_write_results_array[1][lane][iter])
++                                                      printk(BIOS_DEBUG, "+");
++                                              else
++                                                      printk(BIOS_DEBUG, ".");
++                                      }
++                                      printk(BIOS_DEBUG, "\n\n");
++#endif
++
++                                      /* Base rank of single-rank DIMM, or 
odd rank of dual-rank DIMM */
++                                      if (dual_rank) {
++                                              /* Intersect the passing 
windows of both ranks */
++                                              for (iter = 0; iter < 64; 
iter++)
++                                                      if 
(!dqs_read_results_array[1][lane][iter])
++                                                              
dqs_read_results_array[0][lane][iter] = 0;
++                                              for (iter = 0; iter < 128; 
iter++)
++                                                      if 
(!dqs_write_results_array[1][lane][iter])
++                                                              
dqs_write_results_array[0][lane][iter] = 0;
++                                      }
++
++                                      /* Determine location and length of 
longest consecutive string of passing values for read DQS timing
++                                       * Output is stored in best_pos and 
best_count
++                                       */
++                                      last_pos = 0;
++                                      cur_count = 0;
++                                      best_pos = 0;
++                                      best_count = 0;
++                                      for (iter = 0; iter < 64; iter++) {
++                                              if 
((dqs_read_results_array[0][lane][iter]) && (iter < 63)) {
++                                                      /* Pass */
++                                                      cur_count++;
++                                              } else {
++                                                      /* Failure or end of 
loop */
++                                                      if (cur_count > 
best_count) {
++                                                              best_count = 
cur_count;
++                                                              best_pos = 
last_pos;
++                                                      }
++                                                      cur_count = 0;
++                                                      last_pos = iter;
++                                              }
++                                      }
++                                      
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region ", 
best_count, 4);
++                                      if (best_count > 0) {
++                                              if (best_count < MIN_DQS_WNDW) {
++                                                      /* Flag excessively 
small passing window */
++                                                      Errors |= 1 << 
SB_SMALLDQS;
++                                              }
++
++                                              /* Find the center of the 
passing window */
++                                              current_read_dqs_delay[lane] = 
(best_pos + (best_count / 2));
++
++                                              /* Commit the current Read DQS 
Timing Control settings to the hardware registers */
++                                              
write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, (Receiver >> 
1), index_reg);
++
++                                              /* Save the final Read DQS 
Timing Control settings for later use */
++                                              
pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_READDIR][lane] = 
current_read_dqs_delay[lane];
++                                      } else {
++                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 122 Unable to find read passing 
region for lane ", lane, 2);
++
++                                              /* Flag absence of passing 
window */
++                                              Errors |= 1 << SB_NODQSPOS;
++                                      }
++
++                                      /* Determine location and length of 
longest consecutive string of passing values for write DQS timing
++                                       * Output is stored in best_pos and 
best_count
++                                       */
++                                      last_pos = 0;
++                                      cur_count = 0;
++                                      best_pos = 0;
++                                      best_count = 0;
++                                      for (iter = 0; iter < 128; iter++) {
++                                              if 
((dqs_write_results_array[0][lane][iter]) && (iter < 127)) {
++                                                      /* Pass */
++                                                      cur_count++;
++                                              } else {
++                                                      /* Failure or end of 
loop */
++                                                      if (cur_count > 
best_count) {
++                                                              best_count = 
cur_count;
++                                                              best_pos = 
last_pos;
++                                                      }
++                                                      cur_count = 0;
++                                                      last_pos = iter;
++                                              }
++                                      }
++                                      
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region ", 
best_count, 4);
++                                      if (best_count > 0) {
++                                              if (best_count < MIN_DQS_WNDW) {
++                                                      /* Flag excessively 
small passing window */
++                                                      Errors |= 1 << 
SB_SMALLDQS;
++                                              }
++
++                                              /* Find the center of the 
passing window */
++                                              current_write_dqs_delay[lane] = 
(best_pos + (best_count / 2));
++
++                                              /* Commit the current Write 
Data Timing settings to the hardware registers */
++                                              
write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, (Receiver 
>> 1), index_reg);
++
++                                              /* Save the final Write Data 
Timing settings for later use */
++                                              
pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_WRITEDIR][lane] = 
current_write_dqs_delay[lane];
++                                      } else {
++                                              
print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 123 Unable to find write passing 
region for lane ", lane, 2);
++
++                                              /* Flag absence of passing 
window */
++                                              Errors |= 1 << SB_NODQSPOS;
++                                      }
++                              }
++                      }
+ 
+-                      print_debug_dqs("\tTrainDQSRdWrPos: 231 DQSWrDelay ", 
DQSWrDelay, 1);
+-                      TrainWriteDQS_D(pMCTstat, pDCTstat, cs_start);
+               }
+-              print_debug_dqs("\tTrainDQSRdWrPos: 232 Errors ", Errors, 1);
+-              pDCTstat->ErrStatus |= Errors;
+       }
+ 
++      pDCTstat->TrainErrors |= Errors;
++      pDCTstat->ErrStatus |= Errors;
++
+ #if DQS_TRAIN_DEBUG > 0
+       {
+               u8 val;
+               u8 i;
+-              u8 Channel, Receiver, Dir;
++              u8 ChannelDTD, ReceiverDTD, Dir;
+               u8 *p;
+ 
+               for (Dir = 0; Dir < 2; Dir++) {
+@@ -375,14 +749,14 @@ static void TrainDQSRdWrPos_D(struct MCTStatStruc 
*pMCTstat,
+                       } else {
+                               printk(BIOS_DEBUG, "TrainDQSRdWrPos: 
CH_D_DIR_B_DQS RD:\n");
+                       }
+-                      for (Channel = 0; Channel < 2; Channel++) {
+-                              printk(BIOS_DEBUG, "Channel: %02x\n", Channel);
+-                              for (Receiver = cs_start; Receiver < (cs_start 
+ 2); Receiver += 2) {
+-                                      printk(BIOS_DEBUG, "\t\tReceiver: %02x: 
", Receiver);
+-                                      p = 
pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][Dir];
++                      for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
++                              printk(BIOS_DEBUG, "Channel: %02x\n", 
ChannelDTD);
++                              for (ReceiverDTD = 0; ReceiverDTD < 
MAX_CS_SUPPORTED; ReceiverDTD += 2) {
++                                      printk(BIOS_DEBUG, "\t\tReceiver: 
%02x:", ReceiverDTD);
++                                      p = 
pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir];
+                                       for (i=0;i<8; i++) {
+                                               val  = p[i];
+-                                              printk(BIOS_DEBUG, "%02x ", 
val);
++                                              printk(BIOS_DEBUG, " %02x", 
val);
+                                       }
+                                       printk(BIOS_DEBUG, "\n");
+                               }
+@@ -437,225 +811,6 @@ static void SetupDqsPattern_D(struct MCTStatStruc 
*pMCTstat,
+       pDCTstat->PtrPatternBufA = (u32)buf;
+ }
+ 
+-static void TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u8 cs_start)
+-{
+-      u32 Errors;
+-      u8 ChipSel, DQSDelay;
+-      u8 RnkDlySeqPassMin=0, RnkDlySeqPassMax=0xFF, RnkDlyFilterMin=0, 
RnkDlyFilterMax=0xFF;
+-      u8 RnkDlySeqPassMinTot=0, RnkDlySeqPassMaxTot=0xFF, 
RnkDlyFilterMinTot=0, RnkDlyFilterMaxTot=0xFF;
+-      u8 LastTest ,LastTestTot;
+-      u32 TestAddr;
+-      u8 ByteLane;
+-      u8 MutualCSPassW[128];
+-      u8 BanksPresent;
+-      u8 dqsDelay_end;
+-      u8 tmp, valid, tmp1;
+-      u16 word;
+-
+-      /* MutualCSPassW: each byte represents a bitmap of pass/fail per
+-       * ByteLane.  The indext within MutualCSPassW is the delay value
+-       * given the results.
+-       */
+-      print_debug_dqs("\t\t\tTrainDQSPos begin ", 0, 3);
+-
+-      Errors = 0;
+-      BanksPresent = 0;
+-
+-      dqsDelay_end = 32;
+-      /* Bitmapped status per delay setting, 0xff=All positions
+-       * passing (1= PASS). Set the entire array.
+-       */
+-      for (DQSDelay=0; DQSDelay<128; DQSDelay++) {
+-              MutualCSPassW[DQSDelay] = 0xFF;
+-      }
+-
+-      for (ChipSel = cs_start; ChipSel < (cs_start + 2); ChipSel++) { /* 
logical register chipselects 0..7 */
+-              print_debug_dqs("\t\t\t\tTrainDQSPos: 11 ChipSel ", ChipSel, 4);
+-
+-              if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, 
pDCTstat->Channel, ChipSel)) {
+-                      print_debug_dqs("\t\t\t\tmct_RcvrRankEnabled_D CS not 
enabled ", ChipSel, 4);
+-                      continue;
+-              }
+-
+-              BanksPresent = 1;       /* flag for at least one bank is 
present */
+-              TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, 
pDCTstat->Channel, ChipSel, &valid);
+-              if (!valid) {
+-                      print_debug_dqs("\t\t\t\tAddress not supported on 
current CS ", TestAddr, 4);
+-                      continue;
+-              }
+-
+-              print_debug_dqs("\t\t\t\tTrainDQSPos: 12 TestAddr ", TestAddr, 
4);
+-              SetUpperFSbase(TestAddr);       /* fs:eax=far ptr to target */
+-
+-              if (pDCTstat->Direction == DQS_READDIR) {
+-                      print_debug_dqs("\t\t\t\tTrainDQSPos: 13 for read ", 0, 
4);
+-                      WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 
8);
+-              }
+-
+-              for (DQSDelay = 0; DQSDelay < dqsDelay_end; DQSDelay++) {
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 141 DQSDelay ", 
DQSDelay, 5);
+-
+-                      tmp = 0xFF;
+-                      tmp1 = DQSDelay;
+-                      if (pDCTstat->Direction == DQS_READDIR) {
+-                              tmp &= MutualCSPassW[DQSDelay];
+-                              tmp1 += dqsDelay_end;
+-                      }
+-                      tmp &= MutualCSPassW[tmp1];
+-
+-                      if (tmp == 0) {
+-                              continue;/* skip current delay value if other 
chipselects have failed all 8 bytelanes */
+-                      }
+-
+-                      pDCTstat->DQSDelay = DQSDelay;
+-                      mct_SetDQSDelayAllCSR_D(pMCTstat, pDCTstat, cs_start);
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 142 
MutualCSPassW ", MutualCSPassW[DQSDelay], 5);
+-
+-                      if (pDCTstat->Direction == DQS_WRITEDIR) {
+-                              print_debug_dqs("\t\t\t\t\tTrainDQSPos: 143 for 
write", 0, 5);
+-                              WriteDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8);
+-                      }
+-
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 Pattern ", 
pDCTstat->Pattern, 5);
+-                      ReadDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8);
+-                      /* print_debug_dqs("\t\t\t\t\tTrainDQSPos: 145 
MutualCSPassW ", MutualCSPassW[DQSDelay], 5); */
+-                      word = CompareDQSTestPattern_D(pMCTstat, pDCTstat, 
TestAddr << 8); /* 0=fail, 1=pass */
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 compare 1 
", word, 3);
+-
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 
DqsRdWrPos_Saved ", pDCTstat->DqsRdWrPos_Saved, 3);
+-                      word &= ~(pDCTstat->DqsRdWrPos_Saved); /* mask out 
bytelanes that already passed */
+-                      word &= ~(pDCTstat->DqsRdWrPos_Saved << 8);
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 compare 2 
", word, 3);
+-
+-                      tmp = DQSDelay;
+-                      if (pDCTstat->Direction == DQS_READDIR) {
+-                              MutualCSPassW[tmp] &= word >> 8;
+-                              tmp += dqsDelay_end;
+-                      }
+-                      MutualCSPassW[tmp] &= word & 0xFF;
+-
+-                      print_debug_dqs("\t\t\t\t\tTrainDQSPos: 146 
\tMutualCSPassW ", MutualCSPassW[DQSDelay], 5);
+-
+-                      SetTargetWTIO_D(TestAddr);
+-                      FlushDQSTestPattern_D(pDCTstat, TestAddr << 8);
+-                      ResetTargetWTIO_D();
+-              }
+-
+-      }
+-
+-      if (pDCTstat->Direction == DQS_READDIR) {
+-              dqsDelay_end <<= 1;
+-      }
+-
+-      if (BanksPresent) {
+-              #if 0           /* show the bitmap */
+-              for (ByteLane = 0; ByteLane < 8; ByteLane++) { /* just print 
ByteLane 0 */
+-                      for (DQSDelay = 0; DQSDelay < dqsDelay_end; DQSDelay++) 
{
+-                              if (!(MutualCSPassW[DQSDelay] &(1 << 
ByteLane))) {
+-                                      printk(BIOS_DEBUG, ".");
+-                              } else {
+-                                      printk(BIOS_DEBUG, "*");
+-                              }
+-                      }
+-                      printk(BIOS_DEBUG, "\n");
+-              }
+-              #endif
+-              for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+-                      print_debug_dqs("\t\t\t\tTrainDQSPos: 31 ByteLane 
",ByteLane, 4);
+-                      if (!(pDCTstat->DqsRdWrPos_Saved &(1 << ByteLane))) {
+-                              pDCTstat->ByteLane = ByteLane;
+-                              LastTest = DQS_FAIL;            /* Analyze the 
results */
+-                              LastTestTot = DQS_FAIL;
+-                              /* RnkDlySeqPassMin = 0; */
+-                              /* RnkDlySeqPassMax = 0; */
+-                              RnkDlyFilterMax = 0;
+-                              RnkDlyFilterMin = 0;
+-                              RnkDlyFilterMaxTot = 0;
+-                              RnkDlyFilterMinTot = 0;
+-                              for (DQSDelay = 0; DQSDelay < dqsDelay_end; 
DQSDelay++) {
+-                                      if (MutualCSPassW[DQSDelay] & (1 << 
ByteLane)) {
+-                                              
print_debug_dqs("\t\t\t\t\tTrainDQSPos: 321 DQSDelay ", DQSDelay, 5);
+-                                              
print_debug_dqs("\t\t\t\t\tTrainDQSPos: 322 MutualCSPassW ", 
MutualCSPassW[DQSDelay], 5);
+-                                              if (pDCTstat->Direction == 
DQS_READDIR)
+-                                                      tmp = 0x20;
+-                                              else
+-                                                      tmp = 0;
+-                                              if (DQSDelay >= tmp) {
+-                                                      RnkDlySeqPassMax = 
DQSDelay;
+-                                                      if (LastTest == 
DQS_FAIL) {
+-                                                              
RnkDlySeqPassMin = DQSDelay; /* start sequential run */
+-                                                      }
+-                                                      if ((RnkDlySeqPassMax - 
RnkDlySeqPassMin)>(RnkDlyFilterMax-RnkDlyFilterMin)){
+-                                                              RnkDlyFilterMin 
= RnkDlySeqPassMin;
+-                                                              RnkDlyFilterMax 
= RnkDlySeqPassMax;
+-                                                      }
+-                                                      LastTest = DQS_PASS;
+-                                              }
+-
+-                                              if (pDCTstat->Direction == 
DQS_READDIR) {
+-                                                      RnkDlySeqPassMaxTot = 
DQSDelay;
+-                                                      if (LastTestTot == 
DQS_FAIL)
+-                                                              
RnkDlySeqPassMinTot = DQSDelay;
+-                                                      if 
((RnkDlySeqPassMaxTot - 
RnkDlySeqPassMinTot)>(RnkDlyFilterMaxTot-RnkDlyFilterMinTot)){
+-                                                              
RnkDlyFilterMinTot = RnkDlySeqPassMinTot;
+-                                                              
RnkDlyFilterMaxTot = RnkDlySeqPassMaxTot;
+-                                                      }
+-                                                      LastTestTot = DQS_PASS;
+-                                              }
+-                                      } else {
+-                                              LastTest = DQS_FAIL;
+-                                              LastTestTot = DQS_FAIL;
+-                                      }
+-                              }
+-                              print_debug_dqs("\t\t\t\tTrainDQSPos: 33 
RnkDlySeqPassMax ", RnkDlySeqPassMax, 4);
+-                              if (RnkDlySeqPassMax == 0) {
+-                                      Errors |= 1 << SB_NODQSPOS; /* no 
passing window */
+-                              } else {
+-                                      
print_debug_dqs_pair("\t\t\t\tTrainDQSPos: 34 RnkDlyFilter: ", RnkDlyFilterMin, 
" ",  RnkDlyFilterMax, 4);
+-                                      if (((RnkDlyFilterMax - 
RnkDlyFilterMin) < MIN_DQS_WNDW)){
+-                                              Errors |= 1 << SB_SMALLDQS;
+-                                      } else {
+-                                              u8 middle_dqs;
+-                                              /* mctEngDQSwindow_Save_D Not 
required for arrays */
+-                                              if (pDCTstat->Direction == 
DQS_READDIR)
+-                                                      middle_dqs = 
MiddleDQS_D(RnkDlyFilterMinTot, RnkDlyFilterMaxTot);
+-                                              else
+-                                                      middle_dqs = 
MiddleDQS_D(RnkDlyFilterMin, RnkDlyFilterMax);
+-                                              pDCTstat->DQSDelay = middle_dqs;
+-                                              mct_SetDQSDelayCSR_D(pMCTstat, 
pDCTstat, cs_start);  /* load the register with the value */
+-                                              if (pDCTstat->Direction == 
DQS_READDIR)
+-                                                      
StoreWrRdDQSDatStrucVal_D(pMCTstat, pDCTstat, cs_start, RnkDlyFilterMinTot, 
RnkDlyFilterMaxTot); /* store the value into the data structure */
+-                                              else
+-                                                      
StoreWrRdDQSDatStrucVal_D(pMCTstat, pDCTstat, cs_start, RnkDlyFilterMin, 
RnkDlyFilterMax); /* store the value into the data structure */
+-                                              
print_debug_dqs("\t\t\t\tTrainDQSPos: 42 middle_dqs : ",middle_dqs, 4);
+-                                              pDCTstat->DqsRdWrPos_Saved |= 1 
<< ByteLane;
+-                                      }
+-                              }
+-                      }
+-              } /* if (pDCTstat->DqsRdWrPos_Saved &(1 << ByteLane)) */
+-      }
+-/* skipLocMiddle: */
+-      pDCTstat->TrainErrors = Errors;
+-
+-      print_debug_dqs("\t\t\tTrainDQSPos: Errors ", Errors, 3);
+-}
+-
+-static void mctEngDQSwindow_Save_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
+-                                      u8 RnkDlyFilterMin, u8 RnkDlyFilterMax)
+-{
+-      pDCTstat->CH_D_DIR_MaxMin_B_Dly[pDCTstat->Channel]
+-              [pDCTstat->Direction]
+-              [0]
+-              [pDCTstat->ByteLane] = RnkDlyFilterMin;
+-      pDCTstat->CH_D_DIR_MaxMin_B_Dly[pDCTstat->Channel]
+-              [pDCTstat->Direction]
+-              [1]
+-              [pDCTstat->ByteLane] = RnkDlyFilterMax;
+-}
+-
+ static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
+                                       struct DCTStatStruc *pDCTstat, u8 
ChipSel)
+ {
+@@ -679,26 +834,6 @@ static void StoreDQSDatStrucVal_D(struct MCTStatStruc 
*pMCTstat,
+                                       pDCTstat->DQSDelay;
+ }
+ 
+-static void StoreWrRdDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat, u8 
ChipSel,
+-                                      u8 RnkDlyFilterMin, u8 RnkDlyFilterMax)
+-{
+-      u8 dn;
+-
+-      if (pDCTstat->Direction == DQS_WRITEDIR) {
+-              dn = ChipSel >> 1;
+-              RnkDlyFilterMin += 
pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][dn][pDCTstat->ByteLane];
+-              RnkDlyFilterMax += 
pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][dn][pDCTstat->ByteLane];
+-              pDCTstat->DQSDelay += 
pDCTstat->CH_D_B_TxDqs[pDCTstat->Channel][dn][pDCTstat->ByteLane];
+-      } else {
+-              RnkDlyFilterMin <<= 1;
+-              RnkDlyFilterMax <<= 1;
+-              pDCTstat->DQSDelay <<= 1;
+-      }
+-      mctEngDQSwindow_Save_D(pMCTstat, pDCTstat, ChipSel, RnkDlyFilterMin, 
RnkDlyFilterMax);
+-      StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel);
+-}
+-
+ static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 ChipSel)
+ {
+@@ -720,33 +855,6 @@ static void GetDQSDatStrucVal_D(struct MCTStatStruc 
*pMCTstat,
+ 
+ /* FindDQSDatDimmVal_D is not required since we use an array */
+ 
+-static u8 MiddleDQS_D(u8 min, u8 max)
+-{
+-      u8 size;
+-      size = max-min;
+-      if (size % 2)
+-              size++;         /* round up if the size isn't even. */
+-      return ( min + (size >> 1));
+-}
+-
+-static void TrainReadDQS_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u8 cs_start)
+-{
+-      print_debug_dqs("\t\tTrainReadPos ", 0, 2);
+-      pDCTstat->Direction = DQS_READDIR;
+-      TrainDQSPos_D(pMCTstat, pDCTstat, cs_start);
+-}
+-
+-static void TrainWriteDQS_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u8 cs_start)
+-{
+-      pDCTstat->Direction = DQS_WRITEDIR;
+-      print_debug_dqs("\t\tTrainWritePos", 0, 2);
+-      TrainDQSPos_D(pMCTstat, pDCTstat, cs_start);
+-}
+-
+ static void proc_IOCLFLUSH_D(u32 addr_hi)
+ {
+       SetTargetWTIO_D(addr_hi);
+@@ -963,30 +1071,6 @@ static void ResetTargetWTIO_D(void)
+       _WRMSR(0xc0010017, lo, hi); /* IORR0 Mask */
+ }
+ 
+-static void ReadDQSTestPattern_D(struct MCTStatStruc *pMCTstat,
+-                              struct DCTStatStruc *pDCTstat,
+-                              u32 TestAddr_lo)
+-{
+-      /* Read a pattern of 72 bit times (per DQ), to test dram functionality.
+-       * The pattern is a stress pattern which exercises both ISI and
+-       * crosstalk.  The number of cache lines to fill is dependent on DCT
+-       * width mode and burstlength.
+-       * Mode BL  Lines Pattern no.
+-       * ----+---+-------------------
+-       * 64   4         9     0
+-       * 64   8         9     0
+-       * 64M  4         9     0
+-       * 64M  8         9     0
+-       * 128  4         18    1
+-       * 128  8         N/A   -
+-       */
+-      if (pDCTstat->Pattern == 0)
+-              ReadL9TestPattern(TestAddr_lo);
+-      else
+-              ReadL18TestPattern(TestAddr_lo);
+-      _MFENCE;
+-}
+-
+ u32 SetUpperFSbase(u32 addr_hi)
+ {
+       /* Set the upper 32-bits of the Base address, 4GB aligned) for the
+@@ -1009,8 +1093,6 @@ void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index)
+       Set_NB32_index_wait(dev, index_reg, index, val);
+ }
+ 
+-/* mctEngDQSwindow_Save_D not required with arrays */
+-
+ void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
+                       struct DCTStatStruc *pDCTstatA)
+ {
+@@ -1021,8 +1103,8 @@ void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat,
+       for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
+               pDCTstat = pDCTstatA + Node;
+               if (pDCTstat->DCTSysLimit) {
++                      TrainDQSRdWrPos_D(pMCTstat, pDCTstat);
+                       for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel 
+= 2) {
+-                              TrainDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel);
+                               SetEccDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel);
+                       }
+               }
+@@ -1137,27 +1219,6 @@ static void mct_SetDQSDelayCSR_D(struct MCTStatStruc 
*pMCTstat,
+       }
+ }
+ 
+-/*
+- * mct_SetDQSDelayAllCSR_D:
+- * Write the Delay value to all eight byte lanes.
+- */
+-static void mct_SetDQSDelayAllCSR_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat,
+-                                      u8 cs_start)
+-{
+-      u8 ByteLane;
+-      u8 ChipSel = cs_start;
+-
+-      for (ChipSel = cs_start; ChipSel < (cs_start + 2); ChipSel++) {
+-              if ( mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, 
pDCTstat->Channel, ChipSel)) {
+-                      for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+-                              pDCTstat->ByteLane = ByteLane;
+-                              mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, 
ChipSel);
+-                      }
+-              }
+-      }
+-}
+-
+ u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat,
+                               u8 Channel, u8 ChipSel)
+@@ -1196,7 +1257,7 @@ u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
+       reg = 0x40 + (receiver << 2) + reg_off;
+       val = Get_NB32(dev, reg);
+ 
+-      val &= ~0x0F;
++      val &= ~0xe007c01f;
+ 
+       /* unganged mode DCT0+DCT1, sys addr of DCT1=node
+        * base+DctSelBaseAddr+local ca base*/
+@@ -1277,6 +1338,7 @@ exitGetAddrWNoError:
+       print_debug_dqs("mct_GetMCTSysAddr_D: base_addr ", val, 2);
+       print_debug_dqs("mct_GetMCTSysAddr_D: valid ", *valid, 2);
+       print_debug_dqs("mct_GetMCTSysAddr_D: status ", pDCTstat->Status, 2);
++      print_debug_dqs("mct_GetMCTSysAddr_D: SysBase ", pDCTstat->DCTSysBase, 
2);
+       print_debug_dqs("mct_GetMCTSysAddr_D: HoleBase ", 
pDCTstat->DCTHoleBase, 2);
+       print_debug_dqs("mct_GetMCTSysAddr_D: Cachetop ", 
pMCTstat->Sub4GCacheTop, 2);
+ 
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
+index 528c782..60bc01d 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -25,7 +26,6 @@ static void EnableZQcalibration(struct MCTStatStruc 
*pMCTstat, struct DCTStatStr
+ static void DisableZQcalibration(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat);
+ static void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat);
+ static void PrepareC_DCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u8 dct);
+-static void MultiplyDelay(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstat, u8 dct);
+ static void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat);
+ static void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct 
DCTStatStruc *pDCTstat);
+ 
+@@ -154,7 +154,6 @@ static void PhyWLPass2(struct MCTStatStruc *pMCTstat,
+               Clear_OnDimmMirror(pMCTstat, pDCTstat);
+               SetDllSpeedUp_D(pMCTstat, pDCTstat, dct);
+               DisableAutoRefresh_D(pMCTstat, pDCTstat);
+-              MultiplyDelay(pMCTstat, pDCTstat, dct);
+               for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
+                       if (DIMMValid & (1 << (dimm << 1)))
+                               AgesaHwWlPhase1(pDCTstat->C_MCTPtr, 
pDCTstat->C_DCTPtr[dct], dimm, SecondPass);
+@@ -162,6 +161,9 @@ static void PhyWLPass2(struct MCTStatStruc *pMCTstat,
+       }
+ }
+ 
++/* Write Levelization Training
++ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.1
++ */
+ static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
+                                       struct DCTStatStruc *pDCTstat)
+ {
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c
+index 3d625de..596fb23 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -201,12 +202,13 @@ static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 
*pMtrrAddr, u16 MtrrType)
+ 
+ void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc 
*pDCTstatA)
+ {
+-/* UMA memory size may need splitting the MTRR configuration into two
+-  Before training use NB_BottomIO or the physical memory size to set the 
MTRRs.
+-  After training, add UMAMemTyping function to reconfigure the MTRRs based on
+-  NV_BottomUMA (for UMA systems only).
+-  This two-step process allows all memory to be cached for training
+-*/
++      /* UMA memory size may need splitting the MTRR configuration into two
++       * Before training use NB_BottomIO or the physical memory size to set 
the MTRRs.
++       * After training, add UMAMemTyping function to reconfigure the MTRRs 
based on
++       * NV_BottomUMA (for UMA systems only).
++       * This two-step process allows all memory to be cached for training
++      */
++
+       u32 Bottom32bIO, Cache32bTOP;
+       u32 val;
+       u32 addr;
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c
+index 013a1b9..6f97061 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -140,7 +141,7 @@ void InterleaveNodes_D(struct MCTStatStruc *pMCTstat,
+       }
+ 
+       if (DoIntlv) {
+-              MCTMemClr_D(pMCTstat,pDCTstatA);
++              MCTMemClr_D(pMCTstat, pDCTstatA);
+               /* Program Interleaving enabled on Node 0 map only.*/
+               MemSize0 <<= bsf(Nodes);        /* MemSize=MemSize*2 (or 4, or 
8) */
+               Dct0MemSize <<= bsf(Nodes);
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
+index da2f372..cda9c6b 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -36,10 +37,10 @@ u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, 
u8 dct, u32 misc2)
+               val = Get_NB32(pDCTstat->dev_dct, dct * 0x100 + 0x78);
+ 
+               val &= 7;
+-              val = ((~val) & 0xFF) + 1;
++              val = ((~val) & 0xff) + 1;
+               val += 6;
+-              val &= 0xFF;
+-              misc2 &= 0xFFF8FFFF;
++              val &= 0x7;
++              misc2 &= 0xfff8ffff;
+               misc2 |= val << 16;     /* DataTxFifoWrDly */
+               if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
+                       misc2 |= 1 << 7; /* ProgOdtEn */
+@@ -52,11 +53,15 @@ void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat)
+       u32 val;
+ 
+       if (pDCTstat->LogicalCPUID & (AMD_DR_Cx)) {
+-              Set_NB32(pDCTstat->dev_dct, 0x11C, 0x0CE00FC0 | 1 << 29/* 
FlushWrOnStpGnt */);
++              /* Revision C */
++              Set_NB32(pDCTstat->dev_dct, 0x11c, 0x0ce00fc0 | 1 << 29/* 
FlushWrOnStpGnt */);
++      }
+ 
+-              val = Get_NB32(pDCTstat->dev_dct, 0x1B0);
+-              val &= 0xFFFFF8C0;
++      if (pDCTstat->LogicalCPUID & (AMD_DR_Cx)) {
++              val = Get_NB32(pDCTstat->dev_dct, 0x1b0);
++              val &= ~0x73f;
+               val |= 0x101;   /* BKDG recommended settings */
+-              Set_NB32(pDCTstat->dev_dct, 0x1B0, val);
++
++              Set_NB32(pDCTstat->dev_dct, 0x1b0, val);
+       }
+ }
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
+index 6de2f4e..b21b96a 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -172,6 +173,7 @@ static u32 mct_MR1(struct MCTStatStruc *pMCTstat,
+                       ret |= 1 << 11;
+       }
+ 
++      /* program MrsAddress[12]=QOFF: based on F2x[1,0]84[Qoff] */
+       if (dword & (1 << 13))
+               ret |= 1 << 12;
+ 
+@@ -199,7 +201,8 @@ static u32 mct_MR0(struct MCTStatStruc *pMCTstat,
+       /* program MrsAddress[6:4,2]=read CAS latency
+          (CL):based on F2x[1,0]88[Tcl] */
+       dword2 = Get_NB32(dev, reg_off + 0x88);
+-      ret |= (dword2 & 0xF) << 4; /* F2x88[3:0] to MrsAddress[6:4,2]=xxx0b */
++      ret |= (dword2 & 0x7) << 4;             /* F2x88[2:0] to 
MrsAddress[6:4] */
++      ret |= ((dword2 & 0x8) >> 3) << 2;      /* F2x88[3] to MrsAddress[2] */
+ 
+       /* program MrsAddress[12]=0 (PPD):slow exit */
+       if (dword & (1 << 23))
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
+index 8e5c268..91e8f77 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -24,25 +25,13 @@
+ 
+ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 Pass);
+-static u8 mct_SavePassRcvEnDly_D(struct DCTStatStruc *pDCTstat,
+-                                      u8 rcvrEnDly, u8 Channel,
+-                                      u8 receiver, u8 Pass);
+-static u8 mct_CompareTestPatternQW0_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat,
+-                                      u32 addr, u8 channel,
+-                                      u8 pattern, u8 Pass);
+ static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
+                                        struct DCTStatStruc *pDCTstat);
+ static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 Channel);
+ static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 Channel);
+-static void mct_SetFinalRcvrEnDly_D(struct DCTStatStruc *pDCTstat,
+-                              u8 RcvrEnDly, u8 where,
+-                              u8 Channel, u8 Receiver,
+-                              u32 dev, u32 index_reg,
+-                              u8 Addl_Index, u8 Pass);
+-static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u8 
DQSRcvEnDly);
++static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, 
u16 DQSRcvEnDly);
+ static void fenceDynTraining_D(struct MCTStatStruc *pMCTstat,
+                       struct DCTStatStruc *pDCTstat, u8 dct);
+ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat);
+@@ -50,17 +39,17 @@ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc 
*pDCTstat);
+ /* Warning:  These must be located so they do not cross a logical 16-bit
+    segment boundary! */
+ static const u32 TestPattern0_D[] = {
+-      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
+-      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
+-      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
+-      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
+-};
+-static const u32 TestPattern1_D[] = {
+       0x55555555, 0x55555555, 0x55555555, 0x55555555,
+       0x55555555, 0x55555555, 0x55555555, 0x55555555,
+       0x55555555, 0x55555555, 0x55555555, 0x55555555,
+       0x55555555, 0x55555555, 0x55555555, 0x55555555,
+ };
++static const u32 TestPattern1_D[] = {
++      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
++      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
++      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
++      0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
++};
+ static const u32 TestPattern2_D[] = {
+       0x12345678, 0x87654321, 0x23456789, 0x98765432,
+       0x59385824, 0x30496724, 0x24490795, 0x99938733,
+@@ -104,16 +93,87 @@ void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat,
+               dqsTrainRcvrEn_SW(pMCTstat, pDCTstat, Pass);
+ }
+ 
++static void read_dqs_write_timing_control_registers(uint16_t* 
current_total_delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
++{
++      uint8_t lane;
++      uint32_t dword;
++
++      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
++              uint32_t wdt_reg;
++              if ((lane == 0) || (lane == 1))
++                      wdt_reg = 0x30;
++              if ((lane == 2) || (lane == 3))
++                      wdt_reg = 0x31;
++              if ((lane == 4) || (lane == 5))
++                      wdt_reg = 0x40;
++              if ((lane == 6) || (lane == 7))
++                      wdt_reg = 0x41;
++              if (lane == 8)
++                      wdt_reg = 0x32;
++              wdt_reg += dimm * 3;
++              dword = Get_NB32_index_wait(dev, index_reg, wdt_reg);
++              if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1))
++                      current_total_delay[lane] = (dword & 0x00ff0000) >> 16;
++              if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || 
(lane == 0))
++                      current_total_delay[lane] = dword & 0x000000ff;
++      }
++}
++
++static void write_dqs_receiver_enable_control_registers(uint16_t* 
current_total_delay, uint32_t dev, uint8_t dimm, uint32_t index_reg)
++{
++      uint8_t lane;
++      uint32_t dword;
++
++      for (lane = 0; lane < 8; lane++) {
++              uint32_t ret_reg;
++              if ((lane == 0) || (lane == 1))
++                      ret_reg = 0x10;
++              if ((lane == 2) || (lane == 3))
++                      ret_reg = 0x11;
++              if ((lane == 4) || (lane == 5))
++                      ret_reg = 0x20;
++              if ((lane == 6) || (lane == 7))
++                      ret_reg = 0x21;
++              ret_reg += dimm * 3;
++              dword = Get_NB32_index_wait(dev, index_reg, ret_reg);
++              if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) {
++                      dword &= ~(0x1ff << 16);
++                      dword |= (current_total_delay[lane] & 0x1ff) << 16;
++              }
++              if ((lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) {
++                      dword &= ~0x1ff;
++                      dword |= current_total_delay[lane] & 0x1ff;
++              }
++              Set_NB32_index_wait(dev, index_reg, ret_reg, dword);
++      }
++}
++
++static uint32_t convert_testaddr_and_channel_to_address(struct DCTStatStruc 
*pDCTstat, uint32_t testaddr, uint8_t channel)
++{
++      SetUpperFSbase(testaddr);
++      testaddr <<= 8;
++
++      if((pDCTstat->Status & (1<<SB_128bitmode)) && channel ) {
++              testaddr += 8;  /* second channel */
++      }
++
++      return testaddr;
++}
++
++/* DQS Receiver Enable Training
++ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.2
++ */
+ static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat, u8 Pass)
+ {
+-      u8 Channel, RcvrEnDly, RcvrEnDlyRmin;
+-      u8 Test0, Test1, CurrTest, CurrTestSide0, CurrTestSide1;
+-      u8 CTLRMaxDelay, _2Ranks, PatternA, PatternB;
++      u8 Channel;
++      u8 _2Ranks;
+       u8 Addl_Index = 0;
+       u8 Receiver;
+       u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0;
+-      u8 RcvrEnDlyLimit, Final_Value, MaxDelay_CH[2];
++      u8 Final_Value;
++      u16 CTLRMaxDelay;
++      u16 MaxDelay_CH[2];
+       u32 TestAddr0, TestAddr1, TestAddr0B, TestAddr1B;
+       u32 PatternBuffer[64+4]; /* FIXME: need increase 8? */
+       u32 Errors;
+@@ -127,9 +187,20 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
+       u32 cr4;
+       u32 lo, hi;
+ 
++      uint32_t dword;
++      uint8_t rank;
++      uint8_t lane;
++      uint16_t current_total_delay[MAX_BYTE_LANES];
++      uint16_t candidate_total_delay[8];
++      uint8_t data_test_pass_sr[2][8];        /* [rank][lane] */
++      uint8_t data_test_pass[8];              /* [lane] */
++      uint8_t data_test_pass_prev[8];         /* [lane] */
++      uint8_t window_det_toggle[8];
++      uint8_t trained[8];
++      uint64_t result_qword1;
++      uint64_t result_qword2;
++
+       u8 valid;
+-      u32 tmp;
+-      u8 LastTest;
+ 
+       print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0);
+       print_debug_dqs("TrainRcvEn: Pass", Pass, 0);
+@@ -181,33 +252,103 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
+ 
+       Errors = 0;
+       dev = pDCTstat->dev_dct;
+-      CTLRMaxDelay = 0;
+ 
+       for (Channel = 0; Channel < 2; Channel++) {
+               print_debug_dqs("\tTrainRcvEn51: Node ", pDCTstat->Node_ID, 1);
+               print_debug_dqs("\tTrainRcvEn51: Channel ", Channel, 1);
+               pDCTstat->Channel = Channel;
+ 
++              CTLRMaxDelay = 0;
+               MaxDelay_CH[Channel] = 0;
+               index_reg = 0x98 + 0x100 * Channel;
+ 
+               Receiver = mct_InitReceiver_D(pDCTstat, Channel);
+-              /* There are four receiver pairs, loosely associated with 
chipselects. */
++              /* There are four receiver pairs, loosely associated with 
chipselects.
++               * This is essentially looping over each DIMM.
++               */
+               for (; Receiver < 8; Receiver += 2) {
+                       Addl_Index = (Receiver >> 1) * 3 + 0x10;
+-                      LastTest = DQS_FAIL;
+-
+-                      /* mct_ModifyIndex_D */
+-                      RcvrEnDlyRmin = RcvrEnDlyLimit = 0xff;
+ 
+                       print_debug_dqs("\t\tTrainRcvEnd52: index ", 
Addl_Index, 2);
+ 
+-                      if(!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, 
Receiver)) {
++                      if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, 
Receiver)) {
+                               continue;
+                       }
+ 
++                      /* Clear data structures */
++                      for (lane = 0; lane < 8; lane++) {
++                              data_test_pass_prev[lane] = 0;
++                              trained[lane] = 0;
++                      }
++
++                      /* 2.8.9.9.2 (1, 6)
++                       * Retrieve gross and fine timing fields from write DQS 
registers
++                       */
++                      
read_dqs_write_timing_control_registers(current_total_delay, dev, (Receiver >> 
1), index_reg);
++
++                      /* 2.8.9.9.2 (1)
++                       * Program the Write Data Timing and Write ECC Timing 
register to
++                       * the values stored in the DQS Write Timing Control 
register
++                       * for each lane
++                       */
++                      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
++                              uint32_t wdt_reg;
++
++                              /* Calculate Write Data Timing register 
location */
++                              if ((lane == 0) || (lane == 1) || (lane == 2) 
|| (lane == 3))
++                                      wdt_reg = 0x1;
++                              if ((lane == 4) || (lane == 5) || (lane == 6) 
|| (lane == 7))
++                                      wdt_reg = 0x2;
++                              if (lane == 8)
++                                      wdt_reg = 0x3;
++                              wdt_reg |= ((Receiver / 2) << 8);
++
++                              /* Set Write Data Timing register values */
++                              dword = Get_NB32_index_wait(dev, index_reg, 
wdt_reg);
++                              if ((lane == 7) || (lane == 3)) {
++                                      dword &= ~(0x7f << 24);
++                                      dword |= (current_total_delay[lane] & 
0x7f) << 24;
++                              }
++                              if ((lane == 6) || (lane == 2)) {
++                                      dword &= ~(0x7f << 16);
++                                      dword |= (current_total_delay[lane] & 
0x7f) << 16;
++                              }
++                              if ((lane == 5) || (lane == 1)) {
++                                      dword &= ~(0x7f << 8);
++                                      dword |= (current_total_delay[lane] & 
0x7f) << 8;
++                              }
++                              if ((lane == 8) || (lane == 4) || (lane == 0)) {
++                                      dword &= ~0x7f;
++                                      dword |= current_total_delay[lane] & 
0x7f;
++                              }
++                              Set_NB32_index_wait(dev, index_reg, wdt_reg, 
dword);
++                      }
++
++                      /* 2.8.9.9.2 (2)
++                       * Program the Read DQS Timing Control and the Read DQS 
ECC Timing Control registers
++                       * to 1/2 MEMCLK for all lanes
++                       */
++                      for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
++                              uint32_t rdt_reg;
++                              if ((lane == 0) || (lane == 1) || (lane == 2) 
|| (lane == 3))
++                                      rdt_reg = 0x5;
++                              if ((lane == 4) || (lane == 5) || (lane == 6) 
|| (lane == 7))
++                                      rdt_reg = 0x6;
++                              if (lane == 8)
++                                      rdt_reg = 0x7;
++                              rdt_reg |= ((Receiver / 2) << 8);
++                              if (lane == 8)
++                                      dword = 0x0000003f;
++                              else
++                                      dword = 0x3f3f3f3f;
++                              Set_NB32_index_wait(dev, index_reg, rdt_reg, 
dword);
++                      }
++
++                      /* 2.8.9.9.2 (3)
++                       * Select two test addresses for each rank present
++                       */
+                       TestAddr0 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, 
Channel, Receiver, &valid);
+-                      if(!valid) {    /* Address not supported on current CS 
*/
++                      if (!valid) {   /* Address not supported on current CS 
*/
+                               continue;
+                       }
+ 
+@@ -229,171 +370,214 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
+                       print_debug_dqs("\t\tTrainRcvEn53: TestAddr1 ", 
TestAddr1, 2);
+                       print_debug_dqs("\t\tTrainRcvEn53: TestAddr1B ", 
TestAddr1B, 2);
+ 
+-                      /*
+-                       * Get starting RcvrEnDly value
++                      /* 2.8.9.9.2 (4, 5)
++                       * Write 1 cache line of the appropriate test pattern 
to each test addresse
+                        */
+-                      RcvrEnDly = mct_Get_Start_RcvrEnDly_1Pass(Pass);
++                      mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0, 
0); /* rank 0 of DIMM, testpattern 0 */
++                      mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0B, 1); /* rank 0 of DIMM, testpattern 1 */
++                      if (_2Ranks) {
++                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr1, 0); /*rank 1 of DIMM, testpattern 0 */
++                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr1B, 1); /*rank 1 of DIMM, testpattern 1 */
++                      }
+ 
+-                      /* mct_GetInitFlag_D*/
+-                      if (Pass == FirstPass) {
+-                              pDCTstat->DqsRcvEn_Pass = 0;
+-                      } else {
+-                              pDCTstat->DqsRcvEn_Pass=0xFF;
++#if DQS_TRAIN_DEBUG > 0
++                      for (lane = 0; lane < 8; lane++) {
++                              print_debug_dqs("\t\tTrainRcvEn54: lane: ", 
lane, 2);
++                              print_debug_dqs("\t\tTrainRcvEn54: 
current_total_delay ", current_total_delay[lane], 2);
+                       }
+-                      pDCTstat->DqsRcvEn_Saved = 0;
++#endif
+ 
++                      /* 2.8.9.9.2 (6)
++                       * Write gross and fine timing fields to read DQS 
registers
++                       */
++                      
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
++
++                      /* 2.8.9.9.2 (7)
++                       * Loop over all delay values up to 1 MEMCLK (0x40 
delay steps) from the initial delay values
++                       *
++                       * FIXME
++                       * It is not clear if training should be discontinued 
if any test failures occur in the first
++                       * 1 MEMCLK window, or if it should be discontinued if 
no successes occur in the first 1 MEMCLK
++                       * window.  Therefore, loop over up to 2 MEMCLK (0x80 
delay steps) to be on the safe side.
++                       */
++                      uint16_t current_delay_step;
+ 
+-                      while(RcvrEnDly < RcvrEnDlyLimit) {     /* sweep Delay 
value here */
+-                              print_debug_dqs("\t\t\tTrainRcvEn541: RcvrEnDly 
", RcvrEnDly, 3);
++                      for (current_delay_step = 0; current_delay_step < 0x80; 
current_delay_step++) {
++                              print_debug_dqs("\t\t\tTrainRcvEn541: 
current_delay_step ", current_delay_step, 3);
+ 
+-                              /* callback not required
+-                              if(mct_AdjustDelay_D(pDCTstat, RcvrEnDly))
+-                                      goto skipDly;
++                              /* 2.8.9.9.2 (7 D)
++                              * Terminate if all lanes are trained
+                               */
++                              uint8_t all_lanes_trained = 1;
++                              for (lane = 0; lane < 8; lane++)
++                                      if (!trained[lane])
++                                              all_lanes_trained = 0;
+ 
+-                              /* Odd steps get another pattern such that even
+-                               and odd steps alternate. The pointers to the
+-                               patterns will be swaped at the end of the loop
+-                               so that they correspond. */
+-                              if(RcvrEnDly & 1) {
+-                                      PatternA = 1;
+-                                      PatternB = 0;
+-                              } else {
+-                                      /* Even step */
+-                                      PatternA = 0;
+-                                      PatternB = 1;
+-                              }
+-
+-                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0, PatternA); /* rank 0 of DIMM, testpattern 0 */
+-                              mct_Write1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0B, PatternB); /* rank 0 of DIMM, testpattern 1 */
+-                              if(_2Ranks) {
+-                                      mct_Write1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr1, PatternA); /*rank 1 of DIMM, testpattern 0 */
+-                                      mct_Write1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr1B, PatternB); /*rank 1 of DIMM, testpattern 1 */
+-                              }
+-
+-                              mct_SetRcvrEnDly_D(pDCTstat, RcvrEnDly, 0, 
Channel, Receiver, dev, index_reg, Addl_Index, Pass);
+-
+-                              CurrTest = DQS_FAIL;
+-                              CurrTestSide0 = DQS_FAIL;
+-                              CurrTestSide1 = DQS_FAIL;
+-
+-                              mct_Read1LTestPattern_D(pMCTstat, pDCTstat, 
TestAddr0); /*cache fills */
+-                              Test0 = mct_CompareTestPatternQW0_D(pMCTstat, 
pDCTstat, TestAddr0, Channel, PatternA, Pass);/* ROM vs cache compare */
+-                              proc_IOCLFLUSH_D(TestAddr0);
+-                              ResetDCTWrPtr_D(dev, index_reg, Addl_Index);
+-
+-                              print_debug_dqs("\t\t\tTrainRcvEn542: Test0 
result ", Test0, 3);
+-
+-                              /* != 0x00 mean pass */
+-
+-                              if(Test0 == DQS_PASS) {
+-                                      mct_Read1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr0B);        /*cache fills */
+-                                      /* ROM vs cache compare */
+-                                      Test1 = 
mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr0B, Channel, PatternB, 
Pass);
+-                                      proc_IOCLFLUSH_D(TestAddr0B);
+-                                      ResetDCTWrPtr_D(dev, index_reg, 
Addl_Index);
+-
+-                                      print_debug_dqs("\t\t\tTrainRcvEn543: 
Test1 result ", Test1, 3);
++                              if (all_lanes_trained)
++                                      break;
+ 
+-                                      if(Test1 == DQS_PASS) {
+-                                              CurrTestSide0 = DQS_PASS;
++                              /* 2.8.9.9.2 (7 A)
++                              * Loop over all ranks
++                              */
++                              for (rank = 0; rank < (_2Ranks + 1); rank++) {
++                                      /* 2.8.9.9.2 (7 A a-d)
++                                       * Read the first test address of the 
current rank
++                                       * Store the first data beat for 
analysis
++                                       * Reset read pointer in the DRAM 
controller FIFO
++                                       * Read the second test address of the 
current rank
++                                       * Store the first data beat for 
analysis
++                                       * Reset read pointer in the DRAM 
controller FIFO
++                                       */
++                                      if (rank & 1) {
++                                              /* 2.8.9.9.2 (7 D)
++                                               * Invert read instructions to 
alternate data read order on the bus
++                                               */
++                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0B:TestAddr1B);
++                                              result_qword2 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0B:TestAddr1B, Channel));
++                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
++                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0:TestAddr1);
++                                              result_qword1 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0:TestAddr1, Channel));
++                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
++                                      } else {
++                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0:TestAddr1);
++                                              result_qword1 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0:TestAddr1, Channel));
++                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
++                                              proc_IOCLFLUSH_D((rank == 
0)?TestAddr0B:TestAddr1B);
++                                              result_qword2 = 
read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 
0)?TestAddr0B:TestAddr1B, Channel));
++                                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
+                                       }
+-                              }
+-                              if(_2Ranks) {
+-                                      mct_Read1LTestPattern_D(pMCTstat, 
pDCTstat, TestAddr1); /*cache fills */
+-                                      /* ROM vs cache compare */
+-                                      Test0 = 
mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr1, Channel, PatternA, 
Pass);
+-                                      proc_IOCLFLUSH_D(TestAddr1);
+-                                      ResetDCTWrPtr_D(dev, index_reg, 
Addl_Index);
+-
+-                                      print_debug_dqs("\t\t\tTrainRcvEn544: 
Test0 result ", Test0, 3);
+-
+-                                      if(Test0 == DQS_PASS) {
+-                                              
mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1B);        /*cache fills */
+-                                              /* ROM vs cache compare */
+-                                              Test1 = 
mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr1B, Channel, PatternB, 
Pass);
+-                                              proc_IOCLFLUSH_D(TestAddr1B);
+-                                              ResetDCTWrPtr_D(dev, index_reg, 
Addl_Index);
+-
+-                                              
print_debug_dqs("\t\t\tTrainRcvEn545: Test1 result ", Test1, 3);
+-                                              if(Test1 == DQS_PASS) {
+-                                                      CurrTestSide1 = 
DQS_PASS;
++                                      /* 2.8.9.9.2 (7 A e)
++                                       * Compare both read patterns and flag 
passing ranks/lanes
++                                       */
++                                      uint8_t result_lane_byte1;
++                                      uint8_t result_lane_byte2;
++                                      for (lane = 0; lane < 8; lane++) {
++                                              if (trained[lane] == 1) {
++#if DQS_TRAIN_DEBUG > 0
++                                                      
print_debug_dqs("\t\t\t\t\t\t\t\t lane already trained: ", lane, 4);
++#endif
++                                                      continue;
+                                               }
++
++                                              result_lane_byte1 = 
(result_qword1 >> (lane * 8)) & 0xff;
++                                              result_lane_byte2 = 
(result_qword2 >> (lane * 8)) & 0xff;
++                                              if ((result_lane_byte1 == 0x55) 
&& (result_lane_byte2 == 0xaa))
++                                                      
data_test_pass_sr[rank][lane] = 1;
++                                              else
++                                                      
data_test_pass_sr[rank][lane] = 0;
++#if DQS_TRAIN_DEBUG > 0
++                                              
print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0x55, "  |  ", result_lane_byte1, 4);
++                                              
print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0xaa, "  |  ", result_lane_byte2, 4);
++#endif
+                                       }
+                               }
+ 
+-                              if(_2Ranks) {
+-                                      if ((CurrTestSide0 == DQS_PASS) && 
(CurrTestSide1 == DQS_PASS)) {
+-                                              CurrTest = DQS_PASS;
++                              /* 2.8.9.9.2 (7 B)
++                               * If DIMM is dual rank, only use delays that 
pass testing for both ranks
++                               */
++                              for (lane = 0; lane < 8; lane++) {
++                                      if (_2Ranks) {
++                                              if 
((data_test_pass_sr[0][lane]) && (data_test_pass_sr[1][lane]))
++                                                      data_test_pass[lane] = 
1;
++                                              else
++                                                      data_test_pass[lane] = 
0;
++                                      } else {
++                                              data_test_pass[lane] = 
data_test_pass_sr[0][lane];
+                                       }
+-                              } else if (CurrTestSide0 == DQS_PASS) {
+-                                      CurrTest = DQS_PASS;
+                               }
+ 
+-                              /* record first pass DqsRcvEn to stack */
+-                              valid = mct_SavePassRcvEnDly_D(pDCTstat, 
RcvrEnDly, Channel, Receiver, Pass);
++                              /* 2.8.9.9.2 (7 E)
++                               * For each lane, update the DQS receiver delay 
setting in support of next iteration
++                               */
++                              for (lane = 0; lane < 8; lane++) {
++                                      if (trained[lane] == 1)
++                                              continue;
++
++                                      /* 2.8.9.9.2 (7 C a)
++                                       * Save the total delay of the first 
success after a failure for later use
++                                       */
++                                      if ((data_test_pass[lane] == 1) && 
(data_test_pass_prev[lane] == 0)) {
++                                              candidate_total_delay[lane] = 
current_total_delay[lane];
++                                              window_det_toggle[lane] = 0;
++                                      }
+ 
+-                              /* Break(1:RevF,2:DR) or not(0) FIXME: This 
comment deosn't make sense */
+-                              if(valid == 2 || (LastTest == DQS_FAIL && valid 
== 1)) {
+-                                      RcvrEnDlyRmin = RcvrEnDly;
+-                                      break;
++                                      /* 2.8.9.9.2 (7 C b)
++                                       * If the current delay failed testing 
add 1/8 UI to the current delay
++                                       */
++                                      if (data_test_pass[lane] == 0)
++                                              current_total_delay[lane] += 
0x4;
++
++                                      /* 2.8.9.9.2 (7 C c)
++                                       * If the current delay passed testing 
alternately add either 1/32 UI or 1/4 UI to the current delay
++                                       * If 1.25 UI of delay have been added 
with no failures the lane is considered trained
++                                       */
++                                      if (data_test_pass[lane] == 1) {
++                                              /* See if lane is trained */
++                                              if ((current_total_delay[lane] 
- candidate_total_delay[lane]) >= 0x28) {
++                                                      trained[lane] = 1;
++
++                                                      /* Calculate and set 
final lane delay value
++                                                       * The final delay is 
the candidate delay + 7/8 UI
++                                                       */
++                                                      
current_total_delay[lane] = candidate_total_delay[lane] + 0x1c;
++                                              } else {
++                                                      if 
(window_det_toggle[lane] == 0) {
++                                                              
current_total_delay[lane] += 0x1;
++                                                              
window_det_toggle[lane] = 1;
++                                                      } else {
++                                                              
current_total_delay[lane] += 0x8;
++                                                              
window_det_toggle[lane] = 0;
++                                                      }
++                                              }
++                                      }
+                               }
+ 
+-                              LastTest = CurrTest;
+-
+-                              /* swap the rank 0 pointers */
+-                              tmp = TestAddr0;
+-                              TestAddr0 = TestAddr0B;
+-                              TestAddr0B = tmp;
+-
+-                              /* swap the rank 1 pointers */
+-                              tmp = TestAddr1;
+-                              TestAddr1 = TestAddr1B;
+-                              TestAddr1B = tmp;
+-
+-                              print_debug_dqs("\t\t\tTrainRcvEn56: RcvrEnDly 
", RcvrEnDly, 3);
++                              /* Update delays in hardware */
++                              
write_dqs_receiver_enable_control_registers(current_total_delay, dev, (Receiver 
>> 1), index_reg);
+ 
+-                              RcvrEnDly++;
+-
+-                      }       /* while RcvrEnDly */
+-
+-                      print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDly ", 
RcvrEnDly, 2);
+-                      print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDlyRmin ", 
RcvrEnDlyRmin, 3);
+-                      print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDlyLimit ", 
RcvrEnDlyLimit, 3);
+-                      if(RcvrEnDlyRmin == RcvrEnDlyLimit) {
+-                              /* no passing window */
+-                              pDCTstat->ErrStatus |= 1 << SB_NORCVREN;
+-                              Errors |= 1 << SB_NORCVREN;
+-                              pDCTstat->ErrCode = SC_FatalErr;
++                              /* Save previous results for comparison in the 
next iteration */
++                              for (lane = 0; lane < 8; lane++)
++                                      data_test_pass_prev[lane] = 
data_test_pass[lane];
+                       }
+ 
+-                      if(RcvrEnDly > (RcvrEnDlyLimit - 1)) {
+-                              /* passing window too narrow, too far delayed*/
+-                              pDCTstat->ErrStatus |= 1 << SB_SmallRCVR;
+-                              Errors |= 1 << SB_SmallRCVR;
+-                              pDCTstat->ErrCode = SC_FatalErr;
+-                              RcvrEnDly = RcvrEnDlyLimit - 1;
+-                              pDCTstat->CSTrainFail |= 1 << Receiver;
+-                              pDCTstat->DimmTrainFail |= 1 << (Receiver + 
Channel);
+-                      }
+-
+-                      /* CHB_D0_B0_RCVRDLY set in mct_Average_RcvrEnDly_Pass 
*/
+-                      mct_Average_RcvrEnDly_Pass(pDCTstat, RcvrEnDly, 
RcvrEnDlyLimit, Channel, Receiver, Pass);
++#if DQS_TRAIN_DEBUG > 0
++                      for (lane = 0; lane < 8; lane++)
++                              print_debug_dqs_pair("\t\tTrainRcvEn55: Lane ", 
lane, " current_total_delay ", current_total_delay[lane], 2);
++#endif
+ 
+-                      mct_SetFinalRcvrEnDly_D(pDCTstat, RcvrEnDly, 
Final_Value, Channel, Receiver, dev, index_reg, Addl_Index, Pass);
++                      /* Find highest delay value and save for later use */
++                      for (lane = 0; lane < 8; lane++)
++                              if (current_total_delay[lane] > CTLRMaxDelay)
++                                      CTLRMaxDelay = 
current_total_delay[lane];
+ 
+-                      if(pDCTstat->ErrStatus & (1 << SB_SmallRCVR)) {
+-                              Errors |= 1 << SB_SmallRCVR;
++                      /* See if any lanes failed training, and set error 
flags appropriately
++                       * For all trained lanes, save delay values for later 
use
++                       */
++                      for (lane = 0; lane < 8; lane++) {
++                              if (trained[lane]) {
++                                      
pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1][lane] = 
current_total_delay[lane];
++                              } else {
++                                      printk(BIOS_WARNING, "TrainRcvrEn: 
WARNING: Lane %d of receiver %d on channel %d failed training!\n", lane, 
Receiver, Channel);
++
++                                      /* Set error flags */
++                                      pDCTstat->ErrStatus |= 1 << SB_NORCVREN;
++                                      Errors |= 1 << SB_NORCVREN;
++                                      pDCTstat->ErrCode = SC_FatalErr;
++                                      pDCTstat->CSTrainFail |= 1 << Receiver;
++                                      pDCTstat->DimmTrainFail |= 1 << 
(Receiver + Channel);
++                              }
+                       }
+ 
+-                      RcvrEnDly += Pass1MemClkDly;
+-                      if(RcvrEnDly > CTLRMaxDelay) {
+-                              CTLRMaxDelay = RcvrEnDly;
+-                      }
++                      /* 2.8.9.9.2 (8)
++                       * Flush the receiver FIFO
++                       * Write one full cache line of non-0x55/0xaa data to 
one of the test addresses, then read it back to flush the FIFO
++                       */
+ 
+-              }       /* while Receiver */
++                      WriteLNTestPattern(TestAddr0 << 8, (uint8_t 
*)TestPattern2_D, 1);
++                      mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0);
++              }
+               MaxDelay_CH[Channel] = CTLRMaxDelay;
+-      }       /* for Channel */
++      }
+ 
+       CTLRMaxDelay = MaxDelay_CH[0];
+       if (MaxDelay_CH[1] > CTLRMaxDelay)
+@@ -428,31 +612,31 @@ static void dqsTrainRcvrEn_SW(struct MCTStatStruc 
*pMCTstat,
+ 
+ #if DQS_TRAIN_DEBUG > 0
+       {
+-              u8 Channel;
++              u8 ChannelDTD;
+               printk(BIOS_DEBUG, "TrainRcvrEn: CH_MaxRdLat:\n");
+-              for(Channel = 0; Channel<2; Channel++) {
++              for(ChannelDTD = 0; ChannelDTD<2; ChannelDTD++) {
+                       printk(BIOS_DEBUG, "Channel:%x: %x\n",
+-                             Channel, pDCTstat->CH_MaxRdLat[Channel]);
++                             ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD]);
+               }
+       }
+ #endif
+ 
+ #if DQS_TRAIN_DEBUG > 0
+       {
+-              u8 val;
+-              u8 Channel, Receiver;
++              u16 valDTD;
++              u8 ChannelDTD, ReceiverDTD;
+               u8 i;
+-              u8 *p;
++              u16 *p;
+ 
+               printk(BIOS_DEBUG, "TrainRcvrEn: CH_D_B_RCVRDLY:\n");
+-              for(Channel = 0; Channel < 2; Channel++) {
+-                      printk(BIOS_DEBUG, "Channel:%x\n", Channel);
+-                      for(Receiver = 0; Receiver<8; Receiver+=2) {
+-                              printk(BIOS_DEBUG, "\t\tReceiver:%x:", 
Receiver);
+-                              p = 
pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver>>1];
++              for(ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
++                      printk(BIOS_DEBUG, "Channel:%x\n", ChannelDTD);
++                      for(ReceiverDTD = 0; ReceiverDTD<8; ReceiverDTD+=2) {
++                              printk(BIOS_DEBUG, "\t\tReceiver:%x:", 
ReceiverDTD);
++                              p = 
pDCTstat->CH_D_B_RCVRDLY[ChannelDTD][ReceiverDTD>>1];
+                               for (i=0;i<8; i++) {
+-                                      val  = p[i];
+-                                      printk(BIOS_DEBUG, "%x ", val);
++                                      valDTD = p[i];
++                                      printk(BIOS_DEBUG, " %03x", valDTD);
+                               }
+                               printk(BIOS_DEBUG, "\n");
+                       }
+@@ -475,15 +659,6 @@ u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 
dct)
+       }
+ }
+ 
+-static void mct_SetFinalRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 
RcvrEnDly, u8 where, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 
Addl_Index, u8 Pass/*, u8 *p*/)
+-{
+-      /*
+-       * Program final DqsRcvEnDly to additional index for DQS receiver
+-       *  enabled delay
+-       */
+-      mct_SetRcvrEnDly_D(pDCTstat, RcvrEnDly, where, Channel, Receiver, dev, 
index_reg, Addl_Index, Pass);
+-}
+-
+ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat)
+ {
+       u8 ch_end, ch;
+@@ -514,17 +689,20 @@ static void mct_DisableDQSRcvEn_D(struct DCTStatStruc 
*pDCTstat)
+  * Function only used once so it was inlined.
+  */
+ 
+-void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly,
++/* Set F2x[1, 0]9C_x[2B:10] DRAM DQS Receiver Enable Timing Control Registers
++ * See BKDG Rev. 3.62 page 268 for more information
++ */
++void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly,
+                       u8 FinalValue, u8 Channel, u8 Receiver, u32 dev,
+                       u32 index_reg, u8 Addl_Index, u8 Pass)
+ {
+       u32 index;
+       u8 i;
+-      u8 *p;
++      u16 *p;
+       u32 val;
+ 
+-      if(RcvrEnDly == 0xFE) {
+-              /*set the boudary flag */
++      if(RcvrEnDly == 0x1fe) {
++              /*set the boundary flag */
+               pDCTstat->Status |= 1 << SB_DQSRcvLimit;
+       }
+ 
+@@ -543,27 +721,57 @@ void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, 
u8 RcvrEnDly,
+               val = Get_NB32_index_wait(dev, index_reg, index);
+               if(i & 1) {
+                       /* odd byte lane */
+-                      val &= ~(0xFF << 16);
+-                      val |= (RcvrEnDly << 16);
++                      val &= ~(0x1ff << 16);
++                      val |= ((RcvrEnDly & 0x1ff) << 16);
+               } else {
+                       /* even byte lane */
+-                      val &= ~0xFF;
+-                      val |= RcvrEnDly;
++                      val &= ~0x1ff;
++                      val |= (RcvrEnDly & 0x1ff);
+               }
+               Set_NB32_index_wait(dev, index_reg, index, val);
+       }
+ 
+ }
+ 
+-static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u8 
DQSRcvEnDly)
++/* Calculate MaxRdLatency
++ * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.5
++ */
++static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, 
u16 DQSRcvEnDly)
+ {
+       u32 dev;
+       u32 reg;
+-      u16 SubTotal;
++      u32 SubTotal;
+       u32 index_reg;
+       u32 reg_off;
+       u32 val;
+-      u32 valx;
++
++      uint8_t cpu_val_n;
++      uint8_t cpu_val_p;
++
++      u16 freq_tab[] = {400, 533, 667, 800};
++
++      /* Set up processor-dependent values */
++      if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
++              /* Revision D and above */
++              cpu_val_n = 4;
++              cpu_val_p = 29;
++      } else if (pDCTstat->LogicalCPUID & AMD_DR_Cx) {
++              /* Revision C */
++              uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
++              if ((package_type == PT_L1)             /* Socket F (1207) */
++                      || (package_type == PT_M2)      /* Socket AM3 */
++                      || (package_type == PT_S1)) {   /* Socket S1g<x> */
++                      cpu_val_n = 10;
++                      cpu_val_p = 11;
++              } else {
++                      cpu_val_n = 4;
++                      cpu_val_p = 29;
++              }
++      } else {
++              /* Revision B and below */
++              cpu_val_n = 10;
++              cpu_val_p = 11;
++      }
+ 
+       if(pDCTstat->GangedMode)
+               Channel = 0;
+@@ -598,49 +806,32 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc 
*pDCTstat, u8 Channel, u8 DQ
+       val = Get_NB32(dev, 0x78 + reg_off);
+       SubTotal += 8 - (val & 0x0f);
+ 
+-      /* Convert bits 7-5 (also referred to as the course delay) of
++      /* Convert bits 7-5 (also referred to as the coarse delay) of
+        * the current (or worst case) DQS receiver enable delay to
+        * 1/2 MEMCLKs units, rounding up, and add this to the sub-total.
+        */
+-      SubTotal += DQSRcvEnDly >> 5;   /*BOZO-no rounding up */
++      SubTotal += DQSRcvEnDly >> 5;   /* Retrieve gross delay portion of 
value */
+ 
+-      /* Add 5.5 to the sub-total. 5.5 represents part of the
++      /* Add "P" to the sub-total. "P" represents part of the
+        * processor specific constant delay value in the DRAM
+        * clock domain.
+        */
+       SubTotal <<= 1;         /*scale 1/2 MemClk to 1/4 MemClk */
+-      SubTotal += 11;         /*add 5.5 1/2MemClk */
++      SubTotal += cpu_val_p;  /*add "P" 1/2MemClk */
++      SubTotal >>= 1;         /*scale 1/4 MemClk back to 1/2 MemClk */
+ 
+       /* Convert the sub-total (in 1/2 MEMCLKs) to northbridge
+-       * clocks (NCLKs) as follows (assuming DDR400 and assuming
+-       * that no P-state or link speed changes have occurred).
++       * clocks (NCLKs)
+        */
++      SubTotal *= 200 * ((Get_NB32(pDCTstat->dev_nbmisc, 0xd4) & 0x1f) + 4);
++      SubTotal /= freq_tab[((Get_NB32(pDCTstat->dev_dct, 0x94 + reg_off) & 
0x7) - 3)];
++      SubTotal = (SubTotal + (2 - 1)) / 2;    /* Round up */
+ 
+-      /* New formula:
+-       * SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */
+-      val = Get_NB32(dev, 0x94 + reg_off);
+-
+-      /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
+-      val &= 7;
+-      if (val >= 3) {
+-              val <<= 1;
+-      } else
+-              val += 3;
+-      valx = val << 2;
+-
+-      val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4);
+-      SubTotal *= ((val & 0x1f) + 4 ) * 3;
+-
+-      SubTotal /= valx;
+-      if (SubTotal % valx) {  /* round up */
+-              SubTotal++;
+-      }
+-
+-      /* Add 5 NCLKs to the sub-total. 5 represents part of the
++      /* Add "N" NCLKs to the sub-total. "N" represents part of the
+        * processor specific constant value in the northbridge
+        * clock domain.
+        */
+-      SubTotal += 5;
++      SubTotal += (cpu_val_n) / 2;
+ 
+       pDCTstat->CH_MaxRdLat[Channel] = SubTotal;
+       if(pDCTstat->GangedMode) {
+@@ -659,143 +850,6 @@ static void mct_SetMaxLatency_D(struct DCTStatStruc 
*pDCTstat, u8 Channel, u8 DQ
+       Set_NB32(dev, reg, val);
+ }
+ 
+-static u8 mct_SavePassRcvEnDly_D(struct DCTStatStruc *pDCTstat,
+-                      u8 rcvrEnDly, u8 Channel,
+-                      u8 receiver, u8 Pass)
+-{
+-      u8 i;
+-      u8 mask_Saved, mask_Pass;
+-      u8 *p;
+-
+-      /* calculate dimm offset
+-       * not needed for CH_D_B_RCVRDLY array
+-       */
+-
+-      /* cmp if there has new DqsRcvEnDly to be recorded */
+-      mask_Pass = pDCTstat->DqsRcvEn_Pass;
+-
+-      if(Pass == SecondPass) {
+-              mask_Pass = ~mask_Pass;
+-      }
+-
+-      mask_Saved = pDCTstat->DqsRcvEn_Saved;
+-      if(mask_Pass != mask_Saved) {
+-
+-              /* find desired stack offset according to channel/dimm/byte */
+-              if(Pass == SecondPass) {
+-                      /* FIXME: SecondPass is never used for Barcelona p = 
pDCTstat->CH_D_B_RCVRDLY_1[Channel][receiver>>1]; */
+-                      p = 0; /* Keep the compiler happy. */
+-              } else {
+-                      mask_Saved &= mask_Pass;
+-                      p = pDCTstat->CH_D_B_RCVRDLY[Channel][receiver>>1];
+-              }
+-              for(i=0; i < 8; i++) {
+-                      /* cmp per byte lane */
+-                      if(mask_Pass & (1 << i)) {
+-                              if(!(mask_Saved & (1 << i))) {
+-                                      /* save RcvEnDly to stack, according to
+-                                      the related Dimm/byte lane */
+-                                      p[i] = (u8)rcvrEnDly;
+-                                      mask_Saved |= 1 << i;
+-                              }
+-                      }
+-              }
+-              pDCTstat->DqsRcvEn_Saved = mask_Saved;
+-      }
+-      return mct_SaveRcvEnDly_D_1Pass(pDCTstat, Pass);
+-}
+-
+-static u8 mct_CompareTestPatternQW0_D(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat,
+-                                      u32 addr, u8 channel,
+-                                      u8 pattern, u8 Pass)
+-{
+-      /* Compare only the first beat of data.  Since target addrs are cache
+-       * line aligned, the Channel parameter is used to determine which
+-       * cache QW to compare.
+-       */
+-
+-      u8 *test_buf;
+-      u8 i;
+-      u8 result;
+-      u8 value;
+-
+-      if(Pass == FirstPass) {
+-              if(pattern==1) {
+-                      test_buf = (u8 *)TestPattern1_D;
+-              } else {
+-                      test_buf = (u8 *)TestPattern0_D;
+-              }
+-      } else {                /* Second Pass */
+-              test_buf = (u8 *)TestPattern2_D;
+-      }
+-
+-      SetUpperFSbase(addr);
+-      addr <<= 8;
+-
+-      if((pDCTstat->Status & (1<<SB_128bitmode)) && channel ) {
+-              addr += 8;      /* second channel */
+-              test_buf += 8;
+-      }
+-
+-      print_debug_dqs_pair("\t\t\t\t\t\t  test_buf = ", (u32)test_buf, "  |  
addr_lo = ", addr,  4);
+-      for (i=0; i<8; i++, addr ++) {
+-              value = read32_fs(addr);
+-              print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", test_buf[i], "  |  ", 
value, 4);
+-
+-              if (value == test_buf[i]) {
+-                      pDCTstat->DqsRcvEn_Pass |= (1<<i);
+-              } else {
+-                      pDCTstat->DqsRcvEn_Pass &= ~(1<<i);
+-              }
+-      }
+-
+-      result = DQS_FAIL;
+-
+-      if (Pass == FirstPass) {
+-              /* if first pass, at least one byte lane pass
+-               * ,then DQS_PASS=1 and will set to related reg.
+-               */
+-              if(pDCTstat->DqsRcvEn_Pass != 0) {
+-                      result = DQS_PASS;
+-              } else {
+-                      result = DQS_FAIL;
+-              }
+-
+-      } else {
+-              /* if second pass, at least one byte lane fail
+-               * ,then DQS_FAIL=1 and will set to related reg.
+-               */
+-              if(pDCTstat->DqsRcvEn_Pass != 0xFF) {
+-                      result = DQS_FAIL;
+-              } else {
+-                      result = DQS_PASS;
+-              }
+-      }
+-
+-      /* if second pass, we can't find the fail until FFh,
+-       * then let it fail to save the final delay
+-       */
+-      if((Pass == SecondPass) && (pDCTstat->Status & (1 << SB_DQSRcvLimit))) {
+-              result = DQS_FAIL;
+-              pDCTstat->DqsRcvEn_Pass = 0;
+-      }
+-
+-      /* second pass needs to be inverted
+-       * FIXME? this could be inverted in the above code to start with...
+-       */
+-      if(Pass == SecondPass) {
+-              if (result == DQS_PASS) {
+-                      result = DQS_FAIL;
+-              } else if (result == DQS_FAIL) { /* FIXME: doesn't need to be 
else if */
+-                      result = DQS_PASS;
+-              }
+-      }
+-
+-
+-      return result;
+-}
+-
+ static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat,
+                               struct DCTStatStruc *pDCTstat)
+ {
+@@ -854,7 +908,7 @@ void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 
Channel)
+       u32 index_reg;
+       u32 index;
+       u8 ChipSel;
+-      u8 *p;
++      u16 *p;
+       u32 val;
+ 
+       dev = pDCTstat->dev_dct;
+@@ -884,7 +938,7 @@ static void CalcEccDQSRcvrEn_D(struct MCTStatStruc 
*pMCTstat,
+ 
+       for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) {
+               if(mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, ChipSel)) 
{
+-                      u8 *p;
++                      u16 *p;
+                       p = pDCTstat->CH_D_B_RCVRDLY[Channel][ChipSel>>1];
+ 
+                       /* DQS Delay Value of Data Bytelane
+@@ -920,6 +974,10 @@ static void CalcEccDQSRcvrEn_D(struct MCTStatStruc 
*pMCTstat,
+       SetEccDQSRcvrEn_D(pDCTstat, Channel);
+ }
+ 
++/* 2.8.9.9.4
++ * ECC Byte Lane Training
++ * DQS Receiver Enable Delay
++ */
+ void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat,
+                       struct DCTStatStruc *pDCTstatA)
+ {
+@@ -1017,7 +1075,9 @@ static void fenceDynTraining_D(struct MCTStatStruc 
*pMCTstat,
+               avRecValue -= 3;
+       else
+       */
+-      if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
++      if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
++              avRecValue -= 8;
++      else if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
+               avRecValue -= 8;
+       else if (pDCTstat->LogicalCPUID & AMD_DR_Bx)
+               avRecValue -= 8;
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
+index c009756..f01e011 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -36,17 +37,12 @@ u32 SetupDqsPattern_1PassB(u8 pass)
+       return (u32) TestPattern0_D;
+ }
+ 
+-u8  mct_Get_Start_RcvrEnDly_1Pass(u8 pass)
+-{
+-      return 0;
+-}
+-
+-static u8 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 
Channel, u8 Receiver,
++static u16 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 
Channel, u8 Receiver,
+                                       u8 Pass)
+ {
+-      u8 i, MaxValue;
+-      u8 *p;
+-      u8 val;
++      u16 i, MaxValue;
++      u16 *p;
++      u16 val;
+ 
+       MaxValue = 0;
+       p = pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1];
+@@ -76,8 +72,8 @@ u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, 
u8 pass)
+       return ret;
+ }
+ 
+-u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
+-                              u8 RcvrEnDly, u8 RcvrEnDlyLimit,
++u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
++                              u16 RcvrEnDly, u16 RcvrEnDlyLimit,
+                               u8 Channel, u8 Receiver, u8 Pass)
+ 
+ {
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c
+index b01889d..796febc 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -74,15 +75,15 @@ u8 mct_Get_Start_RcvrEnDly_Pass(struct DCTStatStruc 
*pDCTstat,
+       return RcvrEnDly;
+ }
+ 
+-u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
+-                              u8 RcvrEnDly, u8 RcvrEnDlyLimit,
++u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
++                              u16 RcvrEnDly, u16 RcvrEnDlyLimit,
+                               u8 Channel, u8 Receiver, u8 Pass)
+ {
+       u8 i;
+-      u8 *p;
+-      u8 *p_1;
+-      u8 val;
+-      u8 val_1;
++      u16 *p;
++      u16 *p_1;
++      u16 val;
++      u16 val_1;
+       u8 valid = 1;
+       u8 bn;
+ 
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
+index ea5c8c7..920f514 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -191,10 +192,10 @@ static void maxRdLatencyTrain_D(struct MCTStatStruc 
*pMCTstat,
+ 
+ #if DQS_TRAIN_DEBUG > 0
+       {
+-              u8 Channel;
++              u8 ChannelDTD;
+               printk(BIOS_DEBUG, "maxRdLatencyTrain: CH_MaxRdLat:\n");
+-              for(Channel = 0; Channel<2; Channel++) {
+-                      printk(BIOS_DEBUG, "Channel: %02x: %02x\n", Channel, 
pDCTstat->CH_MaxRdLat[Channel]);
++              for(ChannelDTD = 0; ChannelDTD<2; ChannelDTD++) {
++                      printk(BIOS_DEBUG, "Channel: %02x: %02x\n", ChannelDTD, 
pDCTstat->CH_MaxRdLat[ChannelDTD]);
+               }
+       }
+ #endif
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
+index cdeae49..1c3e322 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -58,9 +59,9 @@ void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
+       pDCTstat->C_DCTPtr[dct]->LogicalCPUID = pDCTstat->LogicalCPUID;
+ 
+       for (dimm = 0; dimm < MAX_DIMMS; dimm++) {
+-              if (DimmValid & (1 << dimm))
++              if (DimmValid & (1 << (dimm << 1)))
+                       pDCTstat->C_DCTPtr[dct]->DimmPresent[dimm] = 1;
+-              if (Dimmx8Present & (1 << dimm))
++              if (Dimmx8Present & (1 << (dimm << 1)))
+                       pDCTstat->C_DCTPtr[dct]->DimmX8Present[dimm] = 1;
+       }
+ 
+@@ -88,9 +89,9 @@ void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
+               u8  DimmRanks;
+               if (DimmValid & (1 << (dimm << 1))) {
+                       DimmRanks = 1;
+-                      if (pDCTstat->DimmDRPresent & (1 << (dimm+dct)))
++                      if (pDCTstat->DimmDRPresent & (1 << ((dimm << 1) + 
dct)))
+                               DimmRanks = 2;
+-                      else if (pDCTstat->DimmQRPresent & (1 << (dimm+dct)))
++                      else if (pDCTstat->DimmQRPresent & (1 << ((dimm << 1) + 
dct)))
+                               DimmRanks = 4;
+               } else
+                       DimmRanks = 0;
+@@ -249,35 +250,6 @@ static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
+       }
+ }
+ 
+-/* Multiply the previously saved delay values in Pass 1, step #5 by
+-   (target frequency)/400 to find the gross and fine delay initialization
+-   values at the target frequency.
+- */
+-void MultiplyDelay(struct MCTStatStruc *pMCTstat,
+-                                      struct DCTStatStruc *pDCTstat, u8 dct)
+-{
+-      u16 index;
+-      u8 Multiplier;
+-      u8 gross, fine;
+-      u16 total;
+-
+-      Multiplier = pDCTstat->TargetFreq;
+-
+-      for (index=0; index < MAX_BYTE_LANES*MAX_LDIMMS; index ++) {
+-              gross = pDCTstat->C_DCTPtr[dct]->WLGrossDelay[index];
+-              fine = pDCTstat->C_DCTPtr[dct]->WLFineDelay[index];
+-
+-              total = gross << 5 | fine;
+-              total *= Multiplier;
+-              if (total % 3)
+-                      total = total / 3 + 1;
+-              else
+-                      total = total / 3;
+-              pDCTstat->C_DCTPtr[dct]->WLGrossDelay[index] = (total & 0xFF) 
>> 5;
+-              pDCTstat->C_DCTPtr[dct]->WLFineDelay[index] = total & 0x1F;
+-      }
+-}
+-
+ /*
+  * the DRAM controller to bring the DRAMs out of self refresh mode.
+  */
+@@ -352,9 +324,9 @@ void SetTargetFreq(struct MCTStatStruc *pMCTstat,
+ 
+               if (!DCT1Present)
+                       pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
+-              else if (pDCTstat->GangedMode) {
++              else if (pDCTstat->GangedMode)
+                       pDCTstat->CSPresent = 0;
+-              } else
++              else
+                       pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1];
+ 
+               FreqChgCtrlWrd(pMCTstat, pDCTstat);
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c 
b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+index 212a348..67d705c 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+@@ -2,6 +2,7 @@
+  * This file is part of the coreboot project.
+  *
+  * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <address@hidden>, Raptor Engineering
+  *
+  * 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
+@@ -235,6 +236,65 @@ u32 swapBankBits(sDCTStruct *pDCTData, u32 MRSValue)
+       return MRSValue;
+ }
+ 
++static uint16_t unbuffered_dimm_nominal_termination_emrs(uint8_t 
number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank)
++{
++      uint16_t term;
++
++      /* FIXME
++       * Mainboards need to be able to specify the maximum number of DIMMs 
installable per channel
++       * For now assume a maximum of 2 DIMMs per channel can be installed
++       */
++      uint8_t MaxDimmsInstallable = 2;
++
++      if (number_of_dimms == 1) {
++              if (MaxDimmsInstallable < 3) {
++                      term = 0x04;    /* Rtt_Nom=RZQ/4=60 Ohm */
++              } else {
++                      if (rank_count == 1) {
++                              term = 0x04;    /* Rtt_Nom=RZQ/4=60 Ohm */
++                      } else {
++                              if (rank == 0)
++                                      term = 0x04;    /* Rtt_Nom=RZQ/4=60 Ohm 
*/
++                              else
++                                      term = 0x00;    /* Rtt_Nom=OFF */
++                      }
++              }
++      } else {
++              if (frequency_index < 5)
++                      term = 0x0044;  /* Rtt_Nom=RZQ/6=40 Ohm */
++              else
++                      term = 0x0204;  /* Rtt_Nom=RZQ/8=30 Ohm */
++      }
++
++      return term;
++}
++
++static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t 
number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank)
++{
++      uint16_t term;
++
++      /* FIXME
++       * Mainboards need to be able to specify the maximum number of DIMMs 
installable per channel
++       * For now assume a maximum of 2 DIMMs per channel can be installed
++       */
++      uint8_t MaxDimmsInstallable = 2;
++
++      if (number_of_dimms == 1) {
++              if (MaxDimmsInstallable < 3) {
++                      term = 0x00;    /* Rtt_WR=off */
++              } else {
++                      if (rank_count == 1)
++                              term = 0x00;    /* Rtt_WR=off */
++                      else
++                              term = 0x200;   /* Rtt_WR=RZQ/4=60 Ohm */
++              }
++      } else {
++              term = 0x400;   /* Rtt_WR=RZQ/2=120 Ohm */
++      }
++
++      return term;
++}
++
+ 
/*-----------------------------------------------------------------------------
+  *  void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *DCTData, u8 Dimm, 
BOOL WL)
+  *
+@@ -295,48 +355,23 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
+               if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
+                       tempW1 = RttNomTargetRegDimm(pMCTData, pDCTData, dimm, 
wl, MemClkFreq, rank);
+               } else {
+-                      if (wl)
+-                      {
+-                              if (pDCTData->MaxDimmsInstalled == 1)
+-                              {
+-                                      if ((pDCTData->DimmRanks[dimm] == 2) && 
(rank == 0))
+-                                      {
+-                                              tempW1 = 0x00;  /* Rtt_Nom=OFF 
*/
+-                                      }
++                      if (wl) {
++                              if (rank == 0) {
++                                      /* Get Rtt_WR for the current DIMM and 
rank */
++                                      uint16_t dynamic_term = 
unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[dimm], rank);
++
++                                      /* Convert dynamic termination code to 
corresponding nominal termination code */
++                                      if (dynamic_term == 0x200)
++                                              tempW1 = 0x04;
++                                      else if (dynamic_term == 0x400)
++                                              tempW1 = 0x40;
+                                       else
+-                                      {
+-                                              tempW1 = 0x04;  /* 
Rtt_Nom=RZQ/4=60 Ohm */
+-                                      }
+-                              }
+-                              else    /* 2 Dimms or more per channel */
+-                              {
+-                                      if ((pDCTData->DimmRanks[dimm] == 2) && 
(rank == 1))
+-                                      {
+-                                              tempW1 = 0x00;  /* Rtt_Nom=OFF 
*/
+-                                      }
+-                                      else
+-                                      {
+-                                              if (MemClkFreq == 6) {
+-                                                      tempW1 = 0x04;  /* 
Rtt_Nom=RZQ/4=60 Ohm */
+-                                              } else {
+-                                                      tempW1 = 0x40;/* 
Rtt_Nom=RZQ/2=120 Ohm */
+-                                              }
+-                                      }
+-                              }
+-                      }
+-                      else {  /* 1 or 4 Dimms per channel */
+-                              if ((pDCTData->MaxDimmsInstalled == 1) || 
(pDCTData->MaxDimmsInstalled == 4))
+-                              {
+-                                      tempW1 = 0x04;  /* Rtt_Nom=RZQ/4=60 Ohm 
*/
+-                              }
+-                              else    /* 2 or 3 Dimms per channel */
+-                              {
+-                                      if (MemClkFreq < 5) {
+-                                              tempW1 = 0x0044;        /* 
Rtt_Nom=RZQ/6=40 Ohm */
+-                                      } else {
+-                                              tempW1 = 0x0204;        /* 
Rtt_Nom=RZQ/8=30 Ohm */
+-                                      }
++                                              tempW1 = 0x0;
++                              } else {
++                                      tempW1 = 
unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[dimm], rank);
+                               }
++                      } else {
++                              tempW1 = 
unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[dimm], rank);
+                       }
+               }
+               tempW=tempW|tempW1;
+@@ -353,20 +388,22 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
+                       else
+                       {
+                               /* Disable the output drivers of all other 
ranks for
+-                               * the target DIMM. */
++                               * the target DIMM.
++                               */
+                               tempW = bitTestSet(tempW1, Qoff);
+                       }
+               }
+-              /* program MrsAddress[5,1]=output driver impedance control 
(DIC):
+-               * based on F2x[1,0]84[DrvImpCtrl] */
++              /* Program MrsAddress[5,1]=output driver impedance control 
(DIC):
++               * based on F2x[1,0]84[DrvImpCtrl]
++               */
+               tempW1 = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
+                               FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, 
DrvImpCtrlEnd);
+-              if (bitTest(tempW1,1))
+-              {tempW = bitTestSet(tempW, 5);}
+-              if (bitTest(tempW1,0))
+-              {tempW = bitTestSet(tempW, 1);}
++              if (bitTest(tempW1, 1))
++                      tempW = bitTestSet(tempW, 5);
++              if (bitTest(tempW1, 0))
++                      tempW = bitTestSet(tempW, 1);
+ 
+-              tempW = swapAddrBits_wl(pDCTData,tempW);
++              tempW = swapAddrBits_wl(pDCTData, tempW);
+ 
+               set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
+                       DRAM_INIT, MrsAddressStart, MrsAddressEnd, tempW);
+@@ -404,29 +441,10 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
+               if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && 
(pDCTData->Status[DCT_STATUS_REGISTERED]))
+                       tempW+=0x8;
+               /* determine Rtt_WR for WL & Normal mode */
+-              if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
++              if (pDCTData->Status[DCT_STATUS_REGISTERED])
+                       tempW1 = RttWrRegDimm(pMCTData, pDCTData, dimm, wl, 
MemClkFreq, rank);
+-              } else {
+-                      if (wl)
+-                      {
+-                              tempW1 = 0x00;  /* Rtt_WR=off */
+-                      }
+-                      else
+-                      {
+-                              if (pDCTData->MaxDimmsInstalled == 1)
+-                              {
+-                                      tempW1 = 0x00;  /* Rtt_WR=off */
+-                              }
+-                              else
+-                              {
+-                                      if (MemClkFreq == 6) {
+-                                              tempW1 = 0x200; /* 
Rtt_WR=RZQ/4=60 Ohm */
+-                                      } else {
+-                                              tempW1 = 0x400; /* Rtt_WR=RZQ/2 
*/
+-                                      }
+-                              }
+-                      }
+-              }
++              else
++                      tempW1 = 
unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[dimm], rank);
+               tempW=tempW|tempW1;
+               tempW = swapAddrBits_wl(pDCTData,tempW);
+               set_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId, FUN_DCT,
+@@ -483,38 +501,10 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
+                                       }
+ 
+                                       /* determine Rtt_Nom for WL & Normal 
mode */
+-                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED]) {
++                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED])
+                                               tempW1 = 
RttNomNonTargetRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank);
+-                                      } else {
+-                                              if (wl)
+-                                              {
+-                                                      if 
((pDCTData->DimmRanks[currDimm] == 2) && (rank == 1))
+-                                                      {
+-                                                              tempW1 = 0x00;  
/* Rtt_Nom=OFF */
+-                                                      }
+-                                                      else
+-                                                      {
+-                                                              if (MemClkFreq 
< 5) {
+-                                                                      tempW1 
= 0x0044;/* Rtt_Nom=RZQ/6=40 Ohm */
+-                                                              } else {
+-                                                                      tempW1 
= 0x0204;/* Rtt_Nom=RZQ/8=30 Ohm */
+-                                                              }
+-                                                      }
+-                                              }
+-                                              else {  /* 1 or 4 Dimms per 
channel */
+-                                                      if 
(pDCTData->MaxDimmsInstalled == 4)
+-                                                      {
+-                                                              tempW1 = 0x04;  
/* Rtt_Nom=RZQ/4=60 Ohm */
+-                                                      }
+-                                                      else {  /* 2 or 3 Dimms 
per channel */
+-                                                              if (MemClkFreq 
< 5) {
+-                                                                      tempW1 
= 0x0044;        /* Rtt_Nom=RZQ/6=40 Ohm */
+-                                                              } else {
+-                                                                      tempW1 
= 0x0204;        /* Rtt_Nom=RZQ/8=30 Ohm */
+-                                                              }
+-                                                      }
+-                                              }
+-                                      }
++                                      else
++                                              tempW1 = 
unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
+                                       tempW=tempW|tempW1;
+                                       /* program MrsAddress[5,1]=output 
driver impedance control (DIC):
+                                        * based on F2x[1,0]84[DrvImpCtrl] */
+@@ -560,22 +550,10 @@ void prepareDimms(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm, BOOL wl)
+                                       if ((pDCTData->LogicalCPUID & 
AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED]))
+                                               tempW+=0x8;
+                                       /* determine Rtt_WR for WL & Normal 
mode */
+-                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED]) {
++                                      if 
(pDCTData->Status[DCT_STATUS_REGISTERED])
+                                               tempW1 = RttWrRegDimm(pMCTData, 
pDCTData, currDimm, wl, MemClkFreq, rank);
+-                                      } else {
+-                                              if (wl)
+-                                              {
+-                                                      tempW1 = 0x00;  /* 
Rtt_WR=off */
+-                                              }
+-                                              else
+-                                              {
+-                                                      if (MemClkFreq == 6) {
+-                                                              tempW1 = 0x200; 
/* Rtt_WR=RZQ/4=60 Ohm */
+-                                                      } else {
+-                                                              tempW1 = 0x400; 
/* Rtt_WR=RZQ/2 */
+-                                                      }
+-                                              }
+-                                      }
++                                      else
++                                              tempW1 = 
unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, 
MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
+                                       tempW=tempW|tempW1;
+                                       tempW = swapAddrBits_wl(pDCTData,tempW);
+                                       set_Bits(pDCTData, pDCTData->CurrDct, 
pDCTData->NodeId, FUN_DCT,
+@@ -646,9 +624,14 @@ void programODT(sMCTStruct *pMCTData, sDCTStruct 
*pDCTData, u8 dimm)
+  */
+ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
+ {
+-      u8 ByteLane, Seed_Gross, Seed_Fine;
++      u8 ByteLane, Seed_Gross, Seed_Fine, MemClkFreq;
+       u32 Value, Addr;
+       u16 Addl_Data_Offset, Addl_Data_Port;
++      u16 freq_tab[] = {400, 533, 667, 800};
++
++      /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 800MHz */
++      MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
++                              FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
+ 
+       /* Program F2x[1, 0]9C_x08[WrLvOdt[3:0]] to the proper ODT settings for 
the
+        * current memory subsystem configuration.
+@@ -656,12 +639,13 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct 
*pDCTData, u8 dimm, u8 pass)
+       programODT(pMCTData, pDCTData, dimm);
+ 
+       /* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */
+-      if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
++      if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx)) {
+               set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, 
pDCTData->NodeId, FUN_DCT,
+                               DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, 
WrLvOdtEn, (u32)1);
++      }
+       else
+       {
+-              /* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 
0 for Rev.B*/
++              /* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 
0 for Rev.B */
+               if (pDCTData->DctTrain)
+               {
+                       Addl_Data_Offset=0x198;
+@@ -687,7 +671,6 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, 
u8 dimm, u8 pass)
+ 
+       /* Wait 10 MEMCLKs to allow for ODT signal settling. */
+       pMCTData->AgesaDelay(10);
+-      ByteLane = 0;
+       if (pass == 1)
+       {
+               if (pDCTData->Status[DCT_STATUS_REGISTERED])
+@@ -705,10 +688,17 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct 
*pDCTData, u8 dimm, u8 pass)
+               }
+               else
+               {
+-                      Seed_Gross = 0x00;
+-                      Seed_Fine = 0x1A;
++                      if (MemClkFreq == 6) {
++                              /* DDR-800 */
++                              Seed_Gross = 0x00;
++                              Seed_Fine = 0x1a;
++                      } else {
++                              /* Use settings for DDR-400 (interpolated from 
BKDG) */
++                              Seed_Gross = 0x00;
++                              Seed_Fine = 0x0d;
++                      }
+               }
+-              while(ByteLane < MAX_BYTE_LANES)
++              for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
+               {
+                       /* Program an initialization value to registers F2x[1, 
0]9C_x[51:50] and
+                        * F2x[1, 0]9C_x52 to set the gross and fine delay for 
all the byte lane fields
+@@ -720,35 +710,32 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct 
*pDCTData, u8 dimm, u8 pass)
+                        */
+                       pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Gross;
+                       pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Fine;
+-                      ByteLane++;
+               }
+-      } else if (pDCTData->Status[DCT_STATUS_REGISTERED]) {           /* For 
Pass 2 */
++      } else {                /* Pass 2 */
+               /* From BKDG, Write Leveling Seed Value. */
+-              /* TODO: The unbuffered DIMMs are unstable on the code below. 
So temporarily it is
+-               * only for registered DIMMs. */
+               u32 RegisterDelay, SeedTotal;
+-              u8 MemClkFreq;
+-              u16 freq_tab[] = {400, 533, 667, 800};
+-              while(ByteLane < MAX_BYTE_LANES)
++              for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
+               {
+-                      MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, 
pDCTData->NodeId,
+-                                            FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
+                       if (pDCTData->Status[DCT_STATUS_REGISTERED])
+                               RegisterDelay = 0x20; /* TODO: ((RCW2 & BIT0) 
== 0) ? 0x20 : 0x30; */
+                       else
+                               RegisterDelay = 0;
+-                      SeedTotal = 
(pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1F) |
+-                              
pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5;
++                      SeedTotal = 
(pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) |
++                              
(pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5);
+                       /* SeedTotalPreScaling = (the total delay value in 
F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization
+                          training) - RegisterDelay. */
+-                      /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 
800MHz */
+-                      SeedTotal = (u16) (RegisterDelay + ((((u32) SeedTotal - 
RegisterDelay) *
+-                                                           
freq_tab[MemClkFreq-3]) / 400));
+-                      Seed_Gross = (SeedTotal & 0x20) != 0 ? 1 : 2;
+-                      Seed_Fine = SeedTotal & 0x1F;
++                      SeedTotal = (uint16_t) (RegisterDelay + ((((uint64_t) 
SeedTotal - RegisterDelay) *
++                                                              
freq_tab[MemClkFreq-3] * 100) / (freq_tab[0] * 100)));
++                      Seed_Gross = SeedTotal / 32;
++                      Seed_Fine = SeedTotal & 0x1f;
++                      if (Seed_Gross == 0)
++                              Seed_Gross = 0;
++                      else if (Seed_Gross & 0x1)
++                              Seed_Gross = 1;
++                      else
++                              Seed_Gross = 2;
+                       pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Gross;
+                       pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = 
Seed_Fine;
+-                      ByteLane ++;
+               }
+       }
+ 
+diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c 
b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
+index ea32893..c00cf24 100644
+--- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
++++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
+@@ -59,6 +59,10 @@ static u16 mctGet_NVbits(u8 index)
+               val = 1;
+ #elif CONFIG_CPU_SOCKET_TYPE == 0x13  /* ASB2 */
+               val = 4;
++#elif CONFIG_CPU_SOCKET_TYPE == 0x14  /* C32 */
++              val = 5;
++#elif CONFIG_CPU_SOCKET_TYPE == 0x15  /* G34 */
++              val = 3;
+ //#elif SYSTEM_TYPE == MOBILE
+ //            val = 2;
+ #endif
+@@ -297,6 +301,8 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc 
*pDCTstat)
+       /* Determine the number of installed DIMMs */
+       int ch1_count = 0;
+       int ch2_count = 0;
++      uint8_t ch1_registered = 0;
++      uint8_t ch2_registered = 0;
+       int i;
+       for (i = 0; i < 15; i = i + 2) {
+               if (pDCTstat->DIMMValid & (1 << i))
+@@ -304,6 +310,12 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc 
*pDCTstat)
+               if (pDCTstat->DIMMValid & (1 << (i + 1)))
+                       ch2_count++;
+       }
++      for (i = 0; i < MAX_DIMMS_SUPPORTED; i = i + 2) {
++              if (pDCTstat->DimmRegistered[i])
++                      ch1_registered = 1;
++              if (pDCTstat->DimmRegistered[i + 1])
++                      ch2_registered = 1;
++      }
+       if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) {
+               printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 1: %d DIMM(s) 
detected\n", ch1_count);
+               printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) 
detected\n", ch2_count);
+@@ -413,101 +425,6 @@ static void mctHookAfterDramInit(void)
+ }
+ 
+ #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
+-static void coreDelay(u32 microseconds)
+-{
+-      msr_t now;
+