aboutsummaryrefslogtreecommitdiff
path: root/resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch')
-rw-r--r--resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch163
1 files changed, 163 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch b/resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch
new file mode 100644
index 00000000..407952e3
--- /dev/null
+++ b/resources/libreboot/patch/kgpe-d16/0067-southbridge-amd-sb700-Recover-if-AHCI-disk-detection.patch
@@ -0,0 +1,163 @@
+From e80d2ec15e83fe1e6bb1ee4c8b3d4dad196e023f Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <tpearson@raptorengineeringinc.com>
+Date: Mon, 22 Jun 2015 02:21:29 -0500
+Subject: [PATCH 067/143] southbridge/amd/sb700: Recover if AHCI disk
+ detection fails
+
+Change-Id: I29051af5eca5d31b6aecc261e9a48028380eccb3
+Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
+---
+ src/southbridge/amd/sb700/sata.c | 83 ++++++++++++++++++++++++++++++++++----
+ 1 file changed, 75 insertions(+), 8 deletions(-)
+
+diff --git a/src/southbridge/amd/sb700/sata.c b/src/southbridge/amd/sb700/sata.c
+index d51baa1..ce242c1 100644
+--- a/src/southbridge/amd/sb700/sata.c
++++ b/src/southbridge/amd/sb700/sata.c
+@@ -31,12 +31,15 @@
+ static int sata_drive_detect(int portnum, uint16_t iobar)
+ {
+ u8 byte, byte2;
++ u8 byte_prev, byte2_prev;
+ int i = 0;
++ byte_prev = byte2_prev = 0;
+ outb(0xa0 + 0x10 * (portnum % 2), iobar + 0x6);
+ while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7),
+ (byte != (0xa0 + 0x10 * (portnum % 2))) ||
+ ((byte2 & 0x88) != 0)) {
+- printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2);
++ if ((byte != byte_prev) || (byte2 != byte2_prev))
++ printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2);
+ 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
+@@ -45,11 +48,22 @@ static int sata_drive_detect(int portnum, uint16_t iobar)
+ printk(BIOS_DEBUG, "drive no longer selected after %i ms, "
+ "retrying init\n", i * 10);
+ return 1;
+- } else
+- printk(BIOS_SPEW, "drive detection not yet completed, "
+- "waiting...\n");
++ } else {
++ if (i == 0)
++ printk(BIOS_SPEW, "drive detection not yet completed, "
++ "waiting...\n");
++ }
+ mdelay(10);
+ i++;
++ byte_prev = byte;
++ byte2_prev = byte2;
++
++ /* Detect stuck SATA controller and attempt reset */
++ if (i > 1024) {
++ printk(BIOS_DEBUG, "drive detection not done after %i ms, "
++ "resetting HBA and retrying init\n", i * 10);
++ return 2;
++ }
+ }
+ printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10);
+ return 0;
+@@ -105,12 +119,13 @@ static void sata_init(struct device *dev)
+ 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;
++ int i, j, ret;
+ uint8_t nvram;
+ uint8_t sata_ahci_mode;
+ uint8_t sata_alpm_enable;
+ uint8_t port_count;
+ uint8_t max_port_count;
++ uint8_t hba_reset_count;
+
+ sata_ahci_mode = 0;
+ if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
+@@ -124,14 +139,23 @@ static void sata_init(struct device *dev)
+ /* SATA SMBus Disable */
+ sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
+
++ hba_reset_count = 0;
++
++retry_init:
+ byte = pci_read_config8(sm_dev, 0xad);
+ /* Disable SATA SMBUS */
+- byte |= (1 << 0);
+- /* Enable SATA and power saving */
+ byte |= (1 << 1);
++ /* Enable SATA and power saving */
++ byte |= (1 << 0);
+ byte |= (1 << 5);
+ pci_write_config8(sm_dev, 0xad, byte);
+
++ /* Take the PHY logic out of reset */
++ word = pci_read_config16(dev, 0x84);
++ word |= 0x1 << 2;
++ word &= ~0x1f8;
++ pci_write_config16(dev, 0x84, word);
++
+ /* get rev_id */
+ rev_id = pci_read_config8(sm_dev, 0x08) - 0x28;
+
+@@ -324,6 +348,26 @@ static void sata_init(struct device *dev)
+ if (port_count > max_port_count)
+ port_count = max_port_count;
+
++ /* Send COMRESET to all ports */
++ for (i = 0; i < port_count; i++) {
++ /* Read in Port-N Serial ATA Control Register */
++ byte = read8(sata_bar5 + 0x12C + 0x80 * i);
++
++ /* Set Reset Bit */
++ byte |= 0x1;
++ 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);
++ }
++
+ /* RPR7.7 SATA drive detection. */
+ /* Use BAR5+0x128,BAR0 for Primary Slave */
+ /* Use BAR5+0x1A8,BAR0 for Primary Slave */
+@@ -369,8 +413,31 @@ static void sata_init(struct device *dev)
+ current_bar = ((i / 2) == 0) ? sata_bar0 : sata_bar2;
+ else
+ current_bar = ide_bar0;
+- if (!sata_drive_detect(i, current_bar))
++ ret = sata_drive_detect(i, current_bar);
++ if (ret == 0) {
+ break;
++ } else if (ret == 2) {
++ /* Reset PHY logic */
++ word = pci_read_config16(dev, 0x84);
++ word &= ~(0x1 << 2);
++ word |= 0x1f8;
++ pci_write_config16(dev, 0x84, word);
++
++ /* Disable SATA controller */
++ byte = pci_read_config8(sm_dev, 0xad);
++ byte &= ~(0x1);
++ pci_write_config8(sm_dev, 0xad, byte);
++
++ mdelay(100);
++
++ /* Retry initialization */
++ hba_reset_count++;
++ if (hba_reset_count < 16)
++ goto retry_init;
++ else
++ printk(BIOS_WARNING, "HBA reset count exceeded, "
++ "continuing but AHCI drives may not function\n");
++ }
+ }
+ if (sata_ahci_mode)
+ printk(BIOS_DEBUG, "AHCI device %d is %sready after %i tries\n",
+--
+1.7.9.5
+