aboutsummaryrefslogtreecommitdiff
path: root/resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Add-AHCI-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Add-AHCI-support.patch')
-rw-r--r--resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Add-AHCI-support.patch658
1 files changed, 658 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Add-AHCI-support.patch b/resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Add-AHCI-support.patch
new file mode 100644
index 00000000..8fde17cb
--- /dev/null
+++ b/resources/libreboot/patch/kgpe-d16/0050-southbridge-amd-sb700-Add-AHCI-support.patch
@@ -0,0 +1,658 @@
+From 2b426e29b8a34e7ce3ae479d6472d52687903165 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <kb9vqf@pearsoncomputing.net>
+Date: Tue, 9 Jun 2015 18:09:50 -0500
+Subject: [PATCH 050/146] southbridge/amd/sb700: Add AHCI support
+
+---
+ src/include/device/pci_ids.h | 2 +
+ src/mainboard/asus/kgpe-d16/Kconfig | 4 +
+ src/mainboard/asus/kgpe-d16/cmos.default | 1 +
+ src/mainboard/asus/kgpe-d16/cmos.layout | 3 +-
+ src/southbridge/amd/sb700/Kconfig | 4 +
+ src/southbridge/amd/sb700/early_setup.c | 73 ++++++---
+ src/southbridge/amd/sb700/ide.c | 42 +++--
+ src/southbridge/amd/sb700/sata.c | 264 ++++++++++++++++++++----------
+ src/southbridge/amd/sb800/fadt.c | 1 +
+ 9 files changed, 271 insertions(+), 123 deletions(-)
+
+diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
+index fcaf4aa..664ac49 100644
+--- a/src/include/device/pci_ids.h
++++ b/src/include/device/pci_ids.h
+@@ -311,6 +311,8 @@
+
+ #define PCI_DEVICE_ID_ATI_SB700_LPC 0x439D
+ #define PCI_DEVICE_ID_ATI_SB700_SATA 0x4390
++#define PCI_DEVICE_ID_ATI_SB700_SATA_AHCI 0x4391
++#define PCI_DEVICE_ID_ATI_SB700_SATA_AHCI_AMD 0x4394
+ #define PCI_DEVICE_ID_ATI_SB700_IDE 0x439C
+ #define PCI_DEVICE_ID_ATI_SB700_HDA 0x4383
+ #define PCI_DEVICE_ID_ATI_SB700_PCI 0x4384
+diff --git a/src/mainboard/asus/kgpe-d16/Kconfig b/src/mainboard/asus/kgpe-d16/Kconfig
+index d0af47f..9c359da 100644
+--- a/src/mainboard/asus/kgpe-d16/Kconfig
++++ b/src/mainboard/asus/kgpe-d16/Kconfig
+@@ -88,6 +88,10 @@ config IRQ_SLOT_COUNT
+ int
+ default 13
+
++config SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD
++ hex
++ default 0x3f
++
+ config ONBOARD_VGA_IS_PRIMARY
+ bool
+ default y
+diff --git a/src/mainboard/asus/kgpe-d16/cmos.default b/src/mainboard/asus/kgpe-d16/cmos.default
+index e3eb4fe..5bfaadd 100644
+--- a/src/mainboard/asus/kgpe-d16/cmos.default
++++ b/src/mainboard/asus/kgpe-d16/cmos.default
+@@ -16,6 +16,7 @@ interleave_nodes = Disable
+ interleave_memory_channels = Enable
+ cpu_c_states = Enable
+ cpu_cc6_state = Enable
++sata_ahci_mode = Enable
+ ieee1394 = Enable
+ power_on_after_fail = On
+ boot_option = Fallback
+diff --git a/src/mainboard/asus/kgpe-d16/cmos.layout b/src/mainboard/asus/kgpe-d16/cmos.layout
+index 7f9f661..247fd7b 100644
+--- a/src/mainboard/asus/kgpe-d16/cmos.layout
++++ b/src/mainboard/asus/kgpe-d16/cmos.layout
+@@ -45,7 +45,8 @@ entries
+ 464 1 e 2 compute_unit_siblings
+ 465 1 e 1 cpu_c_states
+ 466 1 e 1 cpu_cc6_state
+-467 1 r 0 allow_spd_nvram_cache_restore
++467 1 e 1 sata_ahci_mode
++468 1 r 0 allow_spd_nvram_cache_restore
+ 477 1 e 1 ieee1394
+ 728 256 h 0 user_data
+ 984 16 h 0 check_sum
+diff --git a/src/southbridge/amd/sb700/Kconfig b/src/southbridge/amd/sb700/Kconfig
+index 064f32e..246b645 100644
+--- a/src/southbridge/amd/sb700/Kconfig
++++ b/src/southbridge/amd/sb700/Kconfig
+@@ -45,6 +45,10 @@ config SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA
+ bool
+ default n
+
++config SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD
++ hex
++ default 0xf
++
+ config EHCI_BAR
+ hex
+ default 0xfef00000
+diff --git a/src/southbridge/amd/sb700/early_setup.c b/src/southbridge/amd/sb700/early_setup.c
+index fd3b099..70a2aee 100644
+--- a/src/southbridge/amd/sb700/early_setup.c
++++ b/src/southbridge/amd/sb700/early_setup.c
+@@ -354,9 +354,13 @@ static void sb700_devices_por_init(void)
+ {
+ device_t dev;
+ u8 byte;
+-#if CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100
+- u32 dword;
+-#endif
++ uint32_t dword;
++ uint8_t nvram;
++ uint8_t sata_ahci_mode;
++
++ sata_ahci_mode = 0;
++ if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
++ sata_ahci_mode = !!nvram;
+
+ printk(BIOS_INFO, "sb700_devices_por_init()\n");
+ /* SMBus Device, BDF:0-20-0 */
+@@ -517,34 +521,56 @@ static void sb700_devices_por_init(void)
+ /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */
+ pci_write_config8(dev, 0x50, 0x01);
+
++ if (!sata_ahci_mode){
+ #if CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100
+- /* SP5100 default SATA mode is RAID5 MODE */
+- dev = pci_locate_device(PCI_ID(0x1002, 0x4393), 0);
+- /* Set SATA Operation Mode, Set to IDE mode */
+- byte = pci_read_config8(dev, 0x40);
+- byte |= (1 << 0);
+- pci_write_config8(dev, 0x40, byte);
++ /* SP5100 default SATA mode is RAID5 MODE */
++ dev = pci_locate_device(PCI_ID(0x1002, 0x4393), 0);
++
++ /* Set SATA Operation Mode, Set to IDE mode */
++ byte = pci_read_config8(dev, 0x40);
++ byte |= (1 << 0);
++ pci_write_config8(dev, 0x40, byte);
+
+- dword = 0x01018f00;
+- pci_write_config32(dev, 0x8, dword);
++ dword = 0x01018f00;
++ pci_write_config32(dev, 0x8, dword);
+
+- /* set SATA Device ID writable */
+- dword = pci_read_config32(dev, 0x40);
+- dword &= ~(1 << 24);
+- pci_write_config32(dev, 0x40, dword);
++ /* set SATA Device ID writable */
++ dword = pci_read_config32(dev, 0x40);
++ dword &= ~(1 << 24);
++ pci_write_config32(dev, 0x40, dword);
+
+- /* set Device ID accommodate with IDE emulation mode configuration*/
+- pci_write_config32(dev, 0x0, 0x43901002);
++ /* set Device ID consistent with IDE emulation mode configuration */
++ pci_write_config32(dev, 0x0, 0x43901002);
+
+- /* rpr v2.13 4.17 Reset CPU on Sync Flood */
+- abcfg_reg(0x10050, 1 << 2, 1 << 2);
++ /* rpr v2.13 4.17 Reset CPU on Sync Flood */
++ abcfg_reg(0x10050, 1 << 2, 1 << 2);
+ #endif
++ }
+
+ /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */
+- printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-18-0\n");
++ printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-17-0\n");
+ dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0);
+
+- /*PHY Global Control*/
++ if (sata_ahci_mode) {
++ /* Switch to AHCI mode (AMD inbox) */
++ dword = pci_read_config32(dev, 0x40);
++ dword |= (0x1 << 24); /* Lock Flash Device ID = 1 */
++ pci_write_config32(dev, 0x40, dword);
++
++ /* Deactivate Sub-Class Code write protection */
++ byte = pci_read_config8(dev, 0x40);
++ byte |= (1 << 0);
++ pci_write_config8(dev, 0x40, byte);
++
++ dword = pci_read_config32(dev, 0x08);
++ dword &= ~(0xff << 16); /* Sub-Class Code = 0x6 */
++ dword |= (0x6 << 16);
++ dword &= ~(0xff << 8); /* Operating Mode Selection = 0x1 */
++ dword |= (0x1 << 8);
++ pci_write_config32(dev, 0x08, dword);
++ }
++
++ /* PHY Global Control */
+ pci_write_config16(dev, 0x86, 0x2C00);
+ }
+
+@@ -695,6 +721,11 @@ static void sb700_pci_cfg(void)
+
+ /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */
+ dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0);
++ if (dev == PCI_DEV_INVALID)
++ dev = pci_locate_device(PCI_ID(0x1002, 0x4391), 0);
++ if (dev == PCI_DEV_INVALID)
++ dev = pci_locate_device(PCI_ID(0x1002, 0x4394), 0);
++
+ /* rpr7.12 SATA MSI and D3 Power State Capability. */
+ byte = pci_read_config8(dev, 0x40);
+ byte |= 1 << 0;
+diff --git a/src/southbridge/amd/sb700/ide.c b/src/southbridge/amd/sb700/ide.c
+index 8803d7f..4e07717 100644
+--- a/src/southbridge/amd/sb700/ide.c
++++ b/src/southbridge/amd/sb700/ide.c
+@@ -1,6 +1,7 @@
+ /*
+ * This file is part of the coreboot project.
+ *
++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -22,6 +23,7 @@
+ #include <device/pci.h>
+ #include <device/pci_ids.h>
+ #include <device/pci_ops.h>
++#include <option.h>
+ #include "sb700.h"
+
+ static void ide_init(struct device *dev)
+@@ -30,6 +32,12 @@ static void ide_init(struct device *dev)
+ /* Enable ide devices so the linux ide driver will work */
+ u32 dword;
+ u8 byte;
++ uint8_t nvram;
++ uint8_t sata_ahci_mode;
++
++ sata_ahci_mode = 0;
++ if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
++ sata_ahci_mode = !!nvram;
+
+ conf = dev->chip_info;
+
+@@ -39,25 +47,25 @@ static void ide_init(struct device *dev)
+ dword &= ~(1 << 16);
+ pci_write_config32(dev, 0x70, dword);
+
+- /* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */
+- byte = pci_read_config8(dev, 0x54);
+- byte |= 0xf;
+- pci_write_config8(dev, 0x54, byte);
+-
+- /* Enable I/O Access&& Bus Master */
+- dword = pci_read_config16(dev, 0x4);
+- dword |= 1 << 2;
+- pci_write_config16(dev, 0x4, dword);
+-
+- /* set ide as primary, if you want to boot from IDE, you'd better set it
+- * in $vendor/$mainboard/devicetree.cb */
++ if (!sata_ahci_mode) {
++ /* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */
++ byte = pci_read_config8(dev, 0x54);
++ byte |= 0xf;
++ pci_write_config8(dev, 0x54, byte);
+
++ /* Enable I/O Access&& Bus Master */
++ dword = pci_read_config16(dev, 0x4);
++ dword |= 1 << 2;
++ pci_write_config16(dev, 0x4, dword);
+
+- if (conf->boot_switch_sata_ide == 1) {
+- struct device *sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
+- byte = pci_read_config8(sm_dev, 0xAD);
+- byte |= 1 << 4;
+- pci_write_config8(sm_dev, 0xAD, byte);
++ /* set ide as primary, if you want to boot from IDE, you'd better set it
++ * in $vendor/$mainboard/devicetree.cb */
++ if (conf->boot_switch_sata_ide == 1) {
++ struct device *sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
++ byte = pci_read_config8(sm_dev, 0xad);
++ byte |= 1 << 4;
++ pci_write_config8(sm_dev, 0xad, byte);
++ }
+ }
+ }
+
+diff --git a/src/southbridge/amd/sb700/sata.c b/src/southbridge/amd/sb700/sata.c
+index 172ad36..c0b3cd5 100644
+--- a/src/southbridge/amd/sb700/sata.c
++++ b/src/southbridge/amd/sb700/sata.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 <tpearson@raptorengineeringinc.com>, 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,18 +25,19 @@
+ #include <device/pci_ids.h>
+ #include <device/pci_ops.h>
+ #include <arch/io.h>
++#include <option.h>
+ #include "sb700.h"
+
+-static int sata_drive_detect(int portnum, u16 iobar)
++static int sata_drive_detect(int portnum, uint16_t iobar)
+ {
+ u8 byte, byte2;
+ int i = 0;
+- outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6);
++ outb(0xa0 + 0x10 * (portnum % 2), iobar + 0x6);
+ while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7),
+- (byte != (0xA0 + 0x10 * (portnum % 2))) ||
++ (byte != (0xa0 + 0x10 * (portnum % 2))) ||
+ ((byte2 & 0x88) != 0)) {
+ printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2);
+- if (byte != (0xA0 + 0x10 * (portnum % 2))) {
++ if (byte != (0xa0 + 0x10 * (portnum % 2))) {
+ /* This will happen at the first iteration of this loop
+ * if the first SATA port is unpopulated and the
+ * second SATA port is populated.
+@@ -65,15 +67,15 @@ void __attribute__((weak)) sb7xx_51xx_setup_sata_phys(struct device *dev)
+ pci_write_config32(dev, 0x90, 0x01B48016);
+ pci_write_config32(dev, 0x94, 0x01B48016);
+ pci_write_config32(dev, 0x98, 0x01B48016);
+- pci_write_config32(dev, 0x9C, 0x01B48016);
++ pci_write_config32(dev, 0x9c, 0x01B48016);
+
+ /* RPR7.6.3 SATA GEN II PHY port setting for port [0~5]. */
+- pci_write_config16(dev, 0xA0, 0xA09A);
+- pci_write_config16(dev, 0xA2, 0xA09F);
+- pci_write_config16(dev, 0xA4, 0xA07A);
+- pci_write_config16(dev, 0xA6, 0xA07A);
+- pci_write_config16(dev, 0xA8, 0xA07A);
+- pci_write_config16(dev, 0xAA, 0xA07A);
++ pci_write_config16(dev, 0xa0, 0xA09A);
++ pci_write_config16(dev, 0xa2, 0xA09F);
++ pci_write_config16(dev, 0xa4, 0xA07A);
++ pci_write_config16(dev, 0xa6, 0xA07A);
++ pci_write_config16(dev, 0xa8, 0xA07A);
++ pci_write_config16(dev, 0xaa, 0xA07A);
+ }
+
+ static void sata_init(struct device *dev)
+@@ -83,8 +85,18 @@ static void sata_init(struct device *dev)
+ u32 dword;
+ u8 rev_id;
+ void *sata_bar5;
+- u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4;
++ uint16_t sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4;
++ uint16_t ide_bar0, ide_bar1, ide_bar2, ide_bar3;
++ uint16_t current_bar;
+ int i, j;
++ uint8_t nvram;
++ uint8_t sata_ahci_mode;
++ uint8_t port_count;
++ uint8_t max_port_count;
++
++ sata_ahci_mode = 0;
++ if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
++ sata_ahci_mode = !!nvram;
+
+ device_t sm_dev;
+ /* SATA SMBus Disable */
+@@ -98,21 +110,39 @@ static void sata_init(struct device *dev)
+ byte |= (1 << 5);
+ pci_write_config8(sm_dev, 0xad, byte);
+
++ /* get rev_id */
++ rev_id = pci_read_config8(sm_dev, 0x08) - 0x28;
++
++ if (sata_ahci_mode) {
++ /* Enable link latency enhancement on A14 and above */
++ if (rev_id >= 0x14) {
++ byte = pci_read_config8(sm_dev, 0xad);
++ byte &= ~(1 << 5);
++ pci_write_config8(sm_dev, 0xad, byte);
++ }
++ }
++
++ /* Disable combined mode */
++ byte = pci_read_config8(sm_dev, 0xad);
++ byte &= ~(1 << 3);
++ pci_write_config8(sm_dev, 0xad, byte);
++
++ device_t ide_dev;
++ /* IDE Device */
++ ide_dev = dev_find_slot(0, PCI_DEVFN(0x14, 1));
++
+ /* RPR 7.2 SATA Initialization */
+ /* Set the interrupt Mapping to INTG# */
+ byte = pci_read_config8(sm_dev, 0xaf);
+ byte = 0x6 << 2;
+ pci_write_config8(sm_dev, 0xaf, byte);
+
+- /* get rev_id */
+- rev_id = pci_read_config8(sm_dev, 0x08) - 0x28;
+-
+ /* get base address */
+ sata_bar5 = (void *)(pci_read_config32(dev, 0x24) & ~0x3FF);
+ sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7;
+ sata_bar1 = pci_read_config16(dev, 0x14) & ~0x3;
+ sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7;
+- sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x3;
++ sata_bar3 = pci_read_config16(dev, 0x1c) & ~0x3;
+ sata_bar4 = pci_read_config16(dev, 0x20) & ~0xf;
+
+ printk(BIOS_SPEW, "sata_bar0=%x\n", sata_bar0); /* 3030 */
+@@ -122,11 +152,16 @@ static void sata_init(struct device *dev)
+ printk(BIOS_SPEW, "sata_bar4=%x\n", sata_bar4); /* 3000 */
+ printk(BIOS_SPEW, "sata_bar5=%p\n", sata_bar5); /* e0309000 */
+
+- /* disable combined mode */
+- byte = pci_read_config8(sm_dev, 0xAD);
+- byte &= ~(1 << 3);
+- pci_write_config8(sm_dev, 0xAD, byte);
+- /* Program the 2C to 0x43801002 */
++ ide_bar0 = pci_read_config16(ide_dev, 0x10) & ~0x7;
++ ide_bar1 = pci_read_config16(ide_dev, 0x14) & ~0x3;
++ ide_bar2 = pci_read_config16(ide_dev, 0x18) & ~0x7;
++ ide_bar3 = pci_read_config16(ide_dev, 0x1c) & ~0x3;
++ printk(BIOS_SPEW, "ide_bar0=%x\n", ide_bar0);
++ printk(BIOS_SPEW, "ide_bar1=%x\n", ide_bar1);
++ printk(BIOS_SPEW, "ide_bar2=%x\n", ide_bar2);
++ printk(BIOS_SPEW, "ide_bar3=%x\n", ide_bar3);
++
++ /* Program the Subsystem ID/VID to 0x43801002 */
+ dword = 0x43801002;
+ pci_write_config32(dev, 0x2c, dword);
+
+@@ -140,15 +175,48 @@ static void sata_init(struct device *dev)
+ byte |= (1 << 2);
+ pci_write_config8(dev, 0x40, byte);
+
+- /* Set SATA Operation Mode, Set to IDE mode */
++ /* Unlock subclass and certain BAR R/O registers */
+ byte = pci_read_config8(dev, 0x40);
+ byte |= (1 << 0);
+- byte |= (1 << 4);
+ pci_write_config8(dev, 0x40, byte);
+
+- dword = 0x01018f00;
+- pci_write_config32(dev, 0x8, dword);
++ /* Disable AHCI enhancement (AMD SP5100 RPR page 54) */
++ dword = pci_read_config32(dev, 0x40);
++ dword |= (1 << 23);
++ pci_write_config32(dev, 0x40, dword);
++
++ if (sata_ahci_mode) {
++ /* Force number of ports to 6
++ * NOTE: This is not documented in the register
++ * reference guide, but CIMX needs to do this
++ * to activate all 6 ports when IDE is disabled.
++ */
++ dword = read32(sata_bar5 + 0x00);
++ dword &= ~0x7;
++ dword |= 0x5;
++ write32(sata_bar5 + 0x00, dword);
++ } else {
++ /* Set SATA Operation Mode, Set to IDE mode */
++ byte = pci_read_config8(dev, 0x40);
++ byte |= (1 << 4);
++ pci_write_config8(dev, 0x40, byte);
++
++ dword = 0x01018f00;
++ pci_write_config32(dev, 0x8, dword);
++ }
++
++ /* Get maximum number of ports */
++ max_port_count = read32(sata_bar5 + 0x00) & 0x1f;
++ max_port_count++;
++ printk(BIOS_SPEW, "Maximum SATA port count supported by silicon: %d\n", max_port_count);
++
++ /* Set number of ports */
++ dword = CONFIG_SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD;
++ for (i = max_port_count; i < 32; i++)
++ dword &= ~(0x1 << i);
++ write32(sata_bar5 + 0x0c, dword);
+
++ /* Write protect Sub-Class Code */
+ byte = pci_read_config8(dev, 0x40);
+ byte &= ~(1 << 0);
+ pci_write_config8(dev, 0x40, byte);
+@@ -181,6 +249,7 @@ static void sata_init(struct device *dev)
+ byte = 0x10;
+ pci_write_config8(dev, 0x46, byte);
+ sb7xx_51xx_setup_sata_phys(dev);
++
+ /* Enable the I/O, MM, BusMaster access for SATA */
+ byte = pci_read_config8(dev, 0x4);
+ byte |= 7 << 0;
+@@ -191,62 +260,75 @@ static void sata_init(struct device *dev)
+ pci_write_config32(dev, 0xC, 0x00004000);
+ #endif
+
+- /* RPR7.7 SATA drive detection. */
+- /* Use BAR5+0x128,BAR0 for Primary Slave */
+- /* Use BAR5+0x1A8,BAR0 for Primary Slave */
+- /* Use BAR5+0x228,BAR2 for Secondary Master */
+- /* Use BAR5+0x2A8,BAR2 for Secondary Slave */
+- /* Use BAR5+0x328,PATA_BAR0/2 for Primary/Secondary master emulation */
+- /* Use BAR5+0x3A8,PATA_BAR0/2 for Primary/Secondary Slave emulation */
+-
+- /* TODO: port 4,5, which are PATA emulations. What are PATA_BARs? */
+-
+- for (i = 0; i < 4; i++) {
+- byte = read8(sata_bar5 + 0x128 + 0x80 * i);
+- printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte);
+- byte &= 0xF;
+- if( byte == 0x1 ) {
+- /* If the drive status is 0x1 then we see it but we aren't talking to it. */
+- /* Try to do something about it. */
+- printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n");
+-
+- /* Read in Port-N Serial ATA Control Register */
+- byte = read8(sata_bar5 + 0x12C + 0x80 * i);
+-
+- /* Set Reset Bit and 1.5g bit */
+- byte |= 0x11;
+- write8((sata_bar5 + 0x12C + 0x80 * i), byte);
+-
+- /* Wait 1ms */
+- mdelay(1);
+-
+- /* Clear Reset Bit */
+- byte &= ~0x01;
+- write8((sata_bar5 + 0x12C + 0x80 * i), byte);
+-
+- /* Wait 1ms */
+- mdelay(1);
+-
+- /* Reread status */
++ /* Determine port count */
++ port_count = 0;
++ for (i = 0; i < 32; i++) {
++ if (CONFIG_SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD & (0x1 << i))
++ port_count = i;
++ }
++ port_count++;
++ if (port_count > max_port_count)
++ port_count = max_port_count;
++
++ if (!sata_ahci_mode) {
++ /* RPR7.7 SATA drive detection. */
++ /* Use BAR5+0x128,BAR0 for Primary Slave */
++ /* Use BAR5+0x1A8,BAR0 for Primary Slave */
++ /* Use BAR5+0x228,BAR2 for Secondary Master */
++ /* Use BAR5+0x2A8,BAR2 for Secondary Slave */
++ /* Use BAR5+0x328,PATA_BAR0/2 for Primary/Secondary Master emulation */
++ /* Use BAR5+0x3A8,PATA_BAR0/2 for Primary/Secondary Slave emulation */
++ for (i = 0; i < port_count; i++) {
+ byte = read8(sata_bar5 + 0x128 + 0x80 * i);
+ printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte);
+ byte &= 0xF;
+- }
+-
+- if (byte == 0x3) {
+- for (j = 0; j < 10; j++) {
+- if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2))
+- break;
++ if (byte == 0x1) {
++ /* If the drive status is 0x1 then we see it but we aren't talking to it. */
++ /* Try to do something about it. */
++ printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n");
++
++ /* Read in Port-N Serial ATA Control Register */
++ byte = read8(sata_bar5 + 0x12C + 0x80 * i);
++
++ /* Set Reset Bit and 1.5g bit */
++ byte |= 0x11;
++ write8((sata_bar5 + 0x12C + 0x80 * i), byte);
++
++ /* Wait 1ms */
++ mdelay(1);
++
++ /* Clear Reset Bit */
++ byte &= ~0x01;
++ write8((sata_bar5 + 0x12C + 0x80 * i), byte);
++
++ /* Wait 1ms */
++ mdelay(1);
++
++ /* Reread status */
++ byte = read8(sata_bar5 + 0x128 + 0x80 * i);
++ printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte);
++ byte &= 0xF;
++ }
++
++ if (byte == 0x3) {
++ for (j = 0; j < 10; j++) {
++ if (i < 4)
++ current_bar = ((i / 2) == 0) ? sata_bar0 : sata_bar2;
++ else
++ current_bar = ide_bar0;
++ if (!sata_drive_detect(i, current_bar))
++ break;
++ }
++ printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n",
++ (i / 2) ? "Secondary" : "Primary",
++ (i % 2 ) ? "Slave" : "Master",
++ (j == 10) ? "not " : "",
++ (j == 10) ? j : j + 1);
++ } else {
++ printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n",
++ (i / 2) ? "Secondary" : "Primary",
++ (i % 2 ) ? "Slave" : "Master", i);
+ }
+- printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n",
+- (i / 2) ? "Secondary" : "Primary",
+- (i % 2 ) ? "Slave" : "Master",
+- (j == 10) ? "not " : "",
+- (j == 10) ? j : j + 1);
+- } else {
+- printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n",
+- (i / 2) ? "Secondary" : "Primary",
+- (i % 2 ) ? "Slave" : "Master", i);
+ }
+ }
+
+@@ -256,13 +338,15 @@ static void sata_init(struct device *dev)
+ byte |= 1 << 1;
+ write8((sata_bar5 + 0x4), byte);
+
+- /* Clear error status */
+- write32((sata_bar5 + 0x130), 0xFFFFFFFF);
+- write32((sata_bar5 + 0x1b0), 0xFFFFFFFF);
+- write32((sata_bar5 + 0x230), 0xFFFFFFFF);
+- write32((sata_bar5 + 0x2b0), 0xFFFFFFFF);
+- write32((sata_bar5 + 0x330), 0xFFFFFFFF);
+- write32((sata_bar5 + 0x3b0), 0xFFFFFFFF);
++ if (!sata_ahci_mode) {
++ /* Clear error status */
++ write32((sata_bar5 + 0x130), 0xFFFFFFFF);
++ write32((sata_bar5 + 0x1b0), 0xFFFFFFFF);
++ write32((sata_bar5 + 0x230), 0xFFFFFFFF);
++ write32((sata_bar5 + 0x2b0), 0xFFFFFFFF);
++ write32((sata_bar5 + 0x330), 0xFFFFFFFF);
++ write32((sata_bar5 + 0x3b0), 0xFFFFFFFF);
++ }
+
+ /* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */
+ /* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */
+@@ -293,3 +377,15 @@ static const struct pci_driver sata0_driver __pci_driver = {
+ .vendor = PCI_VENDOR_ID_ATI,
+ .device = PCI_DEVICE_ID_ATI_SB700_SATA,
+ };
++
++static const struct pci_driver sata1_driver __pci_driver = {
++ .ops = &sata_ops,
++ .vendor = PCI_VENDOR_ID_ATI,
++ .device = PCI_DEVICE_ID_ATI_SB700_SATA_AHCI,
++};
++
++static const struct pci_driver sata2_driver __pci_driver = {
++ .ops = &sata_ops,
++ .vendor = PCI_VENDOR_ID_ATI,
++ .device = PCI_DEVICE_ID_ATI_SB700_SATA_AHCI_AMD,
++};
+diff --git a/src/southbridge/amd/sb800/fadt.c b/src/southbridge/amd/sb800/fadt.c
+index 5250e20..95e3354 100644
+--- a/src/southbridge/amd/sb800/fadt.c
++++ b/src/southbridge/amd/sb800/fadt.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 <tpearson@raptorengineeringinc.com>, 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
+--
+1.7.9.5
+