From 0e6344e1cfe0bad409a4a0bfacbaa92a57440aa7 Mon Sep 17 00:00:00 2001 From: Kerry Sheh Date: Wed, 12 Oct 2011 11:42:59 +0800 Subject: [PATCH] SB800: Sata Enable bus master and enable ahci for AHCI/RAID mode In order to make sure AHCI/RAID ROM works correctly For SB800_SATA_AHCI or SB800_SATA_RAID mode, SATA should enable bus master and the ahci also should be enabled. Change-Id: I9d9c557816d364d8373fe343860ad5fe45988200 Signed-off-by: Kerry She Signed-off-by: Kerry She Reviewed-on: http://review.coreboot.org/248 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones --- src/include/device/pci_ids.h | 1 + src/southbridge/amd/cimx/sb800/late.c | 55 ++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h index 390a42a66c..d16f85e4d7 100644 --- a/src/include/device/pci_ids.h +++ b/src/include/device/pci_ids.h @@ -15,6 +15,7 @@ #define PCI_CLASS_STORAGE_FLOPPY 0x0102 #define PCI_CLASS_STORAGE_IPI 0x0103 #define PCI_CLASS_STORAGE_RAID 0x0104 +#define PCI_CLASS_STORAGE_SATA 0x0106 #define PCI_CLASS_STORAGE_OTHER 0x0180 #define PCI_BASE_CLASS_NETWORK 0x02 diff --git a/src/southbridge/amd/cimx/sb800/late.c b/src/southbridge/amd/cimx/sb800/late.c index b78f1ce726..8c7abdba16 100644 --- a/src/southbridge/amd/cimx/sb800/late.c +++ b/src/southbridge/amd/cimx/sb800/late.c @@ -74,6 +74,46 @@ u32 sb800_callout_entry(u32 func, u32 data, void* config) return ret; } +#define HOST_CAP 0x00 /* host capabilities */ +#define HOST_CTL 0x04 /* global host control */ +#define HOST_IRQ_STAT 0x08 /* interrupt status */ +#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ + +#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ +static void ahci_raid_init(struct device *dev) +{ + u8 irq = 0; + u32 bar5, caps, ports, val; + + val = pci_read_config16(dev, PCI_CLASS_DEVICE); + if (val == PCI_CLASS_STORAGE_SATA) { + printk(BIOS_DEBUG, "AHCI controller "); + } else if (val == PCI_CLASS_STORAGE_RAID) { + printk(BIOS_DEBUG, "RAID controller "); + } else { + printk(BIOS_WARNING, "device class:%x, neither in ahci or raid mode\n", val); + return; + } + + irq = pci_read_config8(dev, PCI_INTERRUPT_LINE); + bar5 = pci_read_config32(dev, PCI_BASE_ADDRESS_5); + printk(BIOS_DEBUG, "IOMEM base: 0x%X, IRQ: 0x%X\n", bar5, irq); + + caps = *(volatile u32 *)(bar5 + HOST_CAP); + caps = (caps & 0x1F) + 1; + ports= *(volatile u32 *)(bar5 + HOST_PORTS_IMPL); + printk(BIOS_DEBUG, "Number of Ports: 0x%x, Port implemented(bit map): 0x%x\n", caps, ports); + + /* make sure ahci is enabled */ + val = *(volatile u32 *)(bar5 + HOST_CTL); + if (!(val & HOST_CTL_AHCI_EN)) { + *(volatile u32 *)(bar5 + HOST_CTL) = val | HOST_CTL_AHCI_EN; + } + + dev->command |= PCI_COMMAND_MASTER; + pci_write_config8(dev, PCI_COMMAND, dev->command); + printk(BIOS_DEBUG, "AHCI/RAID controller initialized\n"); +} static struct pci_operations lops_pci = { .set_subsystem = pci_dev_set_subsystem, @@ -98,17 +138,28 @@ static struct device_operations sata_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = 0, + .init = ahci_raid_init, .scan_bus = 0, .ops_pci = &lops_pci, }; -static const struct pci_driver sata_driver __pci_driver = { +static const struct pci_driver ahci_driver __pci_driver = { .ops = &sata_ops, .vendor = PCI_VENDOR_ID_ATI, .device = PCI_DEVICE_ID_ATI_SB800_SATA_AHCI, }; +static const struct pci_driver raid_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB800_SATA_RAID, +}; +static const struct pci_driver raid5_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB800_SATA_RAID5, +}; + #if CONFIG_USBDEBUG == 1 static void usb_set_resources(struct device *dev) {