summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch
diff options
context:
space:
mode:
authorFrancis Rowe <info@gluglug.org.uk>2016-01-02 17:10:32 (EST)
committer Francis Rowe <info@gluglug.org.uk>2016-01-04 15:28:39 (EST)
commitd1f408f3725aa02bc1d76c4c6aadb4697bd073c0 (patch)
tree7eed036543ae1f8c57b56825880a722a8efbedf1 /resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch
parent91aec7e72005dcda72d19f2d024a02d8c0f86590 (diff)
downloadlibreboot-d1f408f3725aa02bc1d76c4c6aadb4697bd073c0.zip
libreboot-d1f408f3725aa02bc1d76c4c6aadb4697bd073c0.tar.gz
libreboot-d1f408f3725aa02bc1d76c4c6aadb4697bd073c0.tar.bz2
Use different coreboot revisions and patches per board
The release archives will be bigger, but this is a necessary change that makes libreboot development easier. At present, there are boards maintained in libreboot by different people. By doing it this way, that becomes much easier. This is in contrast to the present situation, where a change to one board potentially affects all other boards, especially when updating to a new version of coreboot. Coreboot-libre scripts, download scripts, build scripts - everything. The entire build system has been modified to reflect this change of development. For reasons of consistency, cbfstool and nvramtool are no longer included in the util archives.
Diffstat (limited to 'resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch')
-rw-r--r--resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch656
1 files changed, 656 insertions, 0 deletions
diff --git a/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch b/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch
new file mode 100644
index 0000000..7f5d402
--- /dev/null
+++ b/resources/libreboot/patch/coreboot/33fb4cf0ffb01be8bcb6b488872c87eb50e7d77f/grub/kgpe-d16/0049-southbridge-amd-sb700-Add-AHCI-support.patch
@@ -0,0 +1,656 @@
+From 2ddaf32b63d12d630da6726ba6fa46caa0e5940f Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <tpearson@raptorengineeringinc.com>
+Date: Tue, 9 Jun 2015 18:09:50 -0500
+Subject: [PATCH 049/143] southbridge/amd/sb700: Add AHCI support
+
+Change-Id: I147284e6a435f4b96d6821a122c1f4f9ddc2ea33
+Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
+---
+ 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 | 256 ++++++++++++++++++++----------
+ src/southbridge/amd/sb800/fadt.c | 1 +
+ 9 files changed, 267 insertions(+), 119 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 8906dee..75bf0ee 100644
+--- a/src/mainboard/asus/kgpe-d16/Kconfig
++++ b/src/mainboard/asus/kgpe-d16/Kconfig
+@@ -89,6 +89,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 bca74fb..05eac5f 100644
+--- a/src/southbridge/amd/sb700/Kconfig
++++ b/src/southbridge/amd/sb700/Kconfig
+@@ -46,6 +46,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..a06a72f 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..d97288a 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");
++ /* 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 == 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);
++ /* 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);
++ /* Set Reset Bit and 1.5g bit */
++ byte |= 0x11;
++ write8((sata_bar5 + 0x12C + 0x80 * i), byte);
+
+- /* Wait 1ms */
+- mdelay(1);
++ /* Wait 1ms */
++ mdelay(1);
+
+- /* Clear Reset Bit */
+- byte &= ~0x01;
+- write8((sata_bar5 + 0x12C + 0x80 * i), byte);
++ /* Clear Reset Bit */
++ byte &= ~0x01;
++ write8((sata_bar5 + 0x12C + 0x80 * i), byte);
+
+- /* Wait 1ms */
+- mdelay(1);
++ /* 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;
+- }
++ /* 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 (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2))
+- break;
++ 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 30b4496..5eb83d7 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
+