summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2019-01-10 23:13:11 +0100
committerPatrick Georgi <pgeorgi@google.com>2019-06-06 10:38:22 +0000
commit5eb81bed2ea503aaf910430da492ed75d27ef94f (patch)
tree562c5611149b81c7b81d96c242feff2fe3dede78 /src/southbridge
parentfefe7afeb0abb9d779f1e3b025dde6e1164dac9d (diff)
sb/intel/i82801gx: Detect if the southbridge supports AHCI
This automatically detects whether the southbridge supports AHCI. If AHCI support is selected it will be used unless "sata_no_ahci" is set in the devicetree to override the behavior. Change-Id: I8d9f4e63ae8b2862c422938f3103c44e761bcda4 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/30822 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/intel/i82801gx/chip.h8
-rw-r--r--src/southbridge/intel/i82801gx/i82801gx.h1
-rw-r--r--src/southbridge/intel/i82801gx/sata.c47
3 files changed, 46 insertions, 10 deletions
diff --git a/src/southbridge/intel/i82801gx/chip.h b/src/southbridge/intel/i82801gx/chip.h
index db27ef7097..8909f50bc1 100644
--- a/src/southbridge/intel/i82801gx/chip.h
+++ b/src/southbridge/intel/i82801gx/chip.h
@@ -18,6 +18,12 @@
#include <stdint.h>
+enum sata_mode {
+ SATA_MODE_AHCI = 0,
+ SATA_MODE_IDE_LEGACY_COMBINED,
+ SATA_MODE_IDE_PLAIN,
+};
+
struct southbridge_intel_i82801gx_config {
/**
* Interrupt Routing configuration
@@ -65,7 +71,7 @@ struct southbridge_intel_i82801gx_config {
uint32_t ide_legacy_combined;
uint32_t ide_enable_primary;
uint32_t ide_enable_secondary;
- uint32_t sata_ahci;
+ enum sata_mode sata_mode;
uint32_t sata_ports_implemented;
/* Enable linear PCIe Root Port function numbers starting at zero */
diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h
index e44fcf5123..76420b4e17 100644
--- a/src/southbridge/intel/i82801gx/i82801gx.h
+++ b/src/southbridge/intel/i82801gx/i82801gx.h
@@ -82,6 +82,7 @@ int smbus_block_write(unsigned int device, unsigned int cmd, u8 bytes,
#define FDVCT 0xe4
#define PCIE_4_PORTS_MAX (1 << 7)
+#define AHCI_UNSUPPORTED (1 << 3)
/* GEN_PMCON_3 bits */
#define RTC_BATTERY_DEAD (1 << 2)
diff --git a/src/southbridge/intel/i82801gx/sata.c b/src/southbridge/intel/i82801gx/sata.c
index b657513dcf..24dbf7cf27 100644
--- a/src/southbridge/intel/i82801gx/sata.c
+++ b/src/southbridge/intel/i82801gx/sata.c
@@ -51,18 +51,42 @@ static u8 get_ich7_sata_ports(void)
void sata_enable(struct device *dev)
{
/* Get the chip configuration */
- config_t *config = dev->chip_info;
+ struct southbridge_intel_i82801gx_config *config = dev->chip_info;
+
+ if (config->sata_mode == SATA_MODE_AHCI) {
+ /* Check if the southbridge supports AHCI */
+ struct device *lpc_dev = pcidev_on_root(31, 0);
+ if (!lpc_dev) {
+ /* According to the PCI spec function 0 on a bus:device
+ needs to be active for other functions to be enabled.
+ Since SATA is on the same bus:device as the LPC
+ bridge, it makes little sense to continue. */
+ die("Couldn't find the LPC device!\n");
+ }
+
+ const bool ahci_supported = !(pci_read_config32(lpc_dev, FDVCT)
+ & AHCI_UNSUPPORTED);
+
+ if (!ahci_supported) {
+ /* Fallback to IDE PLAIN for sata for the rest of the
+ initialization */
+ config->sata_mode = SATA_MODE_IDE_PLAIN;
+ printk(BIOS_DEBUG,
+ "AHCI not supported, falling back to plain mode.\n");
+ }
+
+ }
- if (config->sata_ahci) {
+ if (config->sata_mode == SATA_MODE_AHCI) {
/* Set map to ahci */
pci_write_config8(dev, SATA_MAP,
- (pci_read_config8(dev, SATA_MAP) & ~0xc3) | 0x40);
+ (pci_read_config8(dev, SATA_MAP)
+ & ~0xc3) | 0x40);
} else {
- /* Set map to ide */
+ /* Set map to ide */
pci_write_config8(dev, SATA_MAP,
- pci_read_config8(dev, SATA_MAP) & ~0xc3);
+ pci_read_config8(dev, SATA_MAP) & ~0xc3);
}
-
/* At this point, the new pci id will appear on the bus */
}
@@ -89,7 +113,8 @@ static void sata_init(struct device *dev)
/* Enable BARs */
pci_write_config16(dev, PCI_COMMAND, 0x0007);
- if (config->ide_legacy_combined) {
+ switch (config->sata_mode) {
+ case SATA_MODE_IDE_LEGACY_COMBINED:
printk(BIOS_DEBUG, "SATA controller in combined mode.\n");
/* No AHCI: clear AHCI base */
pci_write_config32(dev, 0x24, 0x00000000);
@@ -120,7 +145,8 @@ static void sata_init(struct device *dev)
/* Restrict ports - 0 and 2 only available */
ports &= 0x5;
- } else if (config->sata_ahci) {
+ break;
+ case SATA_MODE_AHCI:
printk(BIOS_DEBUG, "SATA controller in AHCI mode.\n");
/* Allow both Legacy and Native mode */
pci_write_config8(dev, 0x09, 0x8f);
@@ -131,7 +157,9 @@ static void sata_init(struct device *dev)
ahci_bar = (u32 *)(pci_read_config32(dev, 0x27) & ~0x3ff);
ahci_bar[3] = config->sata_ports_implemented;
- } else {
+ break;
+ default:
+ case SATA_MODE_IDE_PLAIN:
printk(BIOS_DEBUG, "SATA controller in plain mode.\n");
/* Set Sata Controller Mode. No Mapping(?) */
pci_write_config8(dev, SATA_MAP, 0x00);
@@ -168,6 +196,7 @@ static void sata_init(struct device *dev)
/* Set IDE I/O Configuration */
reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
pci_write_config32(dev, IDE_CONFIG, reg32);
+ break;
}
/* Set port control */