southbridge/amd/sb700: Fix random persistent SATA AHCI drive detection failure
Change-Id: I4202a62217a7aaeaba07e4b994a350e83e064c9c Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/12001 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
0d0375b3c6
commit
876bdd4ab3
1 changed files with 39 additions and 36 deletions
|
@ -121,7 +121,6 @@ static void sata_init(struct device *dev)
|
|||
uint8_t sata_alpm_enable;
|
||||
uint8_t port_count;
|
||||
uint8_t max_port_count;
|
||||
uint8_t hba_reset_count;
|
||||
uint8_t ide_io_enabled;
|
||||
uint8_t ide_legacy_io_enabled;
|
||||
|
||||
|
@ -137,14 +136,20 @@ 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:
|
||||
/* WARNING
|
||||
* Enabling the SATA link latency enhancement (SMBUS 0xAD bit 5)
|
||||
* causes random persistent drive detection failures until it is cleared,
|
||||
* with the probabability of detection failure rising exponentially with
|
||||
* the number of drives attached to the controller!
|
||||
* This happens on Rev15 H/W.
|
||||
* Do NOT follow the RPR advice; leave this bit set at all times...
|
||||
*/
|
||||
byte = pci_read_config8(sm_dev, 0xad);
|
||||
/* Disable SATA SMBUS */
|
||||
byte |= (1 << 1);
|
||||
/* Enable SATA and power saving */
|
||||
byte |= (1 << 0);
|
||||
/* Disable link latency enhancement */
|
||||
byte |= (1 << 5);
|
||||
pci_write_config8(sm_dev, 0xad, byte);
|
||||
|
||||
|
@ -159,15 +164,6 @@ retry_init:
|
|||
|
||||
printk(BIOS_SPEW, "rev_id=%x\n", rev_id);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable combined mode */
|
||||
byte = pci_read_config8(sm_dev, 0xad);
|
||||
byte |= (1 << 3);
|
||||
|
@ -281,6 +277,17 @@ retry_init:
|
|||
write32(sata_bar5 + 0xfc, dword);
|
||||
}
|
||||
|
||||
/* Enable SATA ports */
|
||||
byte = pci_read_config8(dev, 0x42);
|
||||
if (max_port_count <= 6) {
|
||||
byte |= 0x3f;
|
||||
for (i = 0; i < max_port_count; i++)
|
||||
byte &= ~(0x1 << i);
|
||||
} else {
|
||||
byte &= ~0x3f;
|
||||
}
|
||||
pci_write_config8(dev, 0x42, byte);
|
||||
|
||||
if (sata_ahci_mode) {
|
||||
/* FIXME
|
||||
* SeaBIOS does not know how to spin
|
||||
|
@ -302,6 +309,9 @@ retry_init:
|
|||
write32(sata_bar5 + 0x04, dword);
|
||||
}
|
||||
|
||||
sb7xx_51xx_setup_sata_phys(dev);
|
||||
sb7xx_51xx_setup_sata_port_indication(sata_bar5);
|
||||
|
||||
/* Write protect Sub-Class Code */
|
||||
byte = pci_read_config8(dev, 0x40);
|
||||
byte &= ~(1 << 0);
|
||||
|
@ -327,7 +337,7 @@ retry_init:
|
|||
else {
|
||||
dword &= ~(1 << 24 | 1 << 21); /* A14 and above */
|
||||
dword &= ~0xFF80; /* 15:7 */
|
||||
dword |= 1 << 15 | 0x7F << 7;
|
||||
dword |= 1 << 15 | 0x7F << 7 | 1 << 6;
|
||||
}
|
||||
pci_write_config32(dev, 0x48, dword);
|
||||
|
||||
|
@ -335,9 +345,6 @@ retry_init:
|
|||
byte = 0x10;
|
||||
pci_write_config8(dev, 0x46, byte);
|
||||
|
||||
sb7xx_51xx_setup_sata_phys(dev);
|
||||
sb7xx_51xx_setup_sata_port_indication(sata_bar5);
|
||||
|
||||
/* Enable the I/O, MM, BusMaster access for SATA */
|
||||
byte = pci_read_config8(dev, 0x4);
|
||||
byte |= 7 << 0;
|
||||
|
@ -422,32 +429,28 @@ retry_init:
|
|||
if (i < 4)
|
||||
current_bar = ((i / 2) == 0) ? sata_bar0 : sata_bar2;
|
||||
else
|
||||
current_bar = ide_bar0;
|
||||
current_bar = (pci_read_config8(sm_dev, 0xad) & (0x1 << 4))
|
||||
? ide_bar2 : ide_bar0;
|
||||
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);
|
||||
/* Read in Port-N Serial ATA Control Register */
|
||||
byte = read8(sata_bar5 + 0x12C + 0x80 * i);
|
||||
|
||||
/* Disable SATA controller */
|
||||
byte = pci_read_config8(sm_dev, 0xad);
|
||||
byte &= ~(1 << 0);
|
||||
byte &= ~(1 << 3);
|
||||
pci_write_config8(sm_dev, 0xad, byte);
|
||||
/* Set Reset Bit */
|
||||
byte |= 0x1;
|
||||
write8((sata_bar5 + 0x12C + 0x80 * i), byte);
|
||||
|
||||
mdelay(100);
|
||||
/* Wait 1000ms */
|
||||
mdelay(1000);
|
||||
|
||||
/* 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");
|
||||
/* Clear Reset Bit */
|
||||
byte &= ~0x01;
|
||||
write8((sata_bar5 + 0x12C + 0x80 * i), byte);
|
||||
|
||||
/* Wait 1ms */
|
||||
mdelay(1);
|
||||
}
|
||||
}
|
||||
if (sata_ahci_mode)
|
||||
|
|
Loading…
Reference in a new issue