From c3fcdccb816f9c5df5a3c158d167a20c1ae088ee Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 5 Sep 2015 17:46:38 -0500 Subject: southbridge/amd/sr5650: Fix boot failure on ASUS KGPE-D16 Change-Id: Ia13ba58118a826e830a4dc6e2378b76110fcabad Signed-off-by: Timothy Pearson Reviewed-on: http://review.coreboot.org/11939 Tested-by: Raptor Engineering Automated Test Stand Reviewed-by: Edward O'Callaghan Tested-by: build bot (Jenkins) Reviewed-by: Peter Stuge --- src/southbridge/amd/sr5650/acpi/sr5650.asl | 388 +++++++++++++++++++++++++++++ src/southbridge/amd/sr5650/early_setup.c | 7 +- src/southbridge/amd/sr5650/ht.c | 3 +- src/southbridge/amd/sr5650/pcie.c | 37 ++- src/southbridge/amd/sr5650/sr5650.c | 51 ++-- 5 files changed, 456 insertions(+), 30 deletions(-) create mode 100644 src/southbridge/amd/sr5650/acpi/sr5650.asl diff --git a/src/southbridge/amd/sr5650/acpi/sr5650.asl b/src/southbridge/amd/sr5650/acpi/sr5650.asl new file mode 100644 index 0000000000..a6ab1144d6 --- /dev/null +++ b/src/southbridge/amd/sr5650/acpi/sr5650.asl @@ -0,0 +1,388 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Timothy Pearson , Raptor Engineering + * Copyright (C) 2009 Advanced Micro Devices, Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Scope(\) { + Name(PCBA, 0xE0000000) /* Base address of PCIe config space */ + Name(HPBA, 0xFED00000) /* Base address of HPET table */ + + /* PIC IRQ mapping registers, C00h-C01h */ + OperationRegion(PRQM, SystemIO, 0x00000C00, 0x00000002) + Field(PRQM, ByteAcc, NoLock, Preserve) { + PRQI, 0x00000008, + PRQD, 0x00000008, /* Offset: 1h */ + } + IndexField(PRQI, PRQD, ByteAcc, NoLock, Preserve) { + PINA, 0x00000008, /* Index 0 */ + PINB, 0x00000008, /* Index 1 */ + PINC, 0x00000008, /* Index 2 */ + PIND, 0x00000008, /* Index 3 */ + AINT, 0x00000008, /* Index 4 */ + SINT, 0x00000008, /* Index 5 */ + , 0x00000008, /* Index 6 */ + AAUD, 0x00000008, /* Index 7 */ + AMOD, 0x00000008, /* Index 8 */ + PINE, 0x00000008, /* Index 9 */ + PINF, 0x00000008, /* Index A */ + PING, 0x00000008, /* Index B */ + PINH, 0x00000008, /* Index C */ + } + + /* PCI Error control register */ + OperationRegion(PERC, SystemIO, 0x00000C14, 0x00000001) + Field(PERC, ByteAcc, NoLock, Preserve) { + SENS, 0x00000001, + PENS, 0x00000001, + SENE, 0x00000001, + PENE, 0x00000001, + } + + Scope(\_SB) { + /* PCIe Configuration Space for 16 busses */ + OperationRegion(PCFG, SystemMemory, PCBA, 0x01000000) /* Each bus consumes 1MB */ + Field(PCFG, ByteAcc, NoLock, Preserve) { + /* Byte offsets are computed using the following technique: + * ((bus number + 1) * ((device number * 8) * 4096)) + register offset + * The 8 comes from 8 functions per device, and 4096 bytes per function config space + */ + Offset(0x00088024), /* Byte offset to SATA register 24h - Bus 0, Device 17, Function 0 */ + STB5, 32, + Offset(0x00098042), /* Byte offset to OHCI0 register 42h - Bus 0, Device 19, Function 0 */ + PT0D, 1, + PT1D, 1, + PT2D, 1, + PT3D, 1, + PT4D, 1, + PT5D, 1, + PT6D, 1, + PT7D, 1, + PT8D, 1, + PT9D, 1, + Offset(0x000A0004), /* Byte offset to SMBUS register 4h - Bus 0, Device 20, Function 0 */ + SBIE, 1, + SBME, 1, + Offset(0x000A0008), /* Byte offset to SMBUS register 8h - Bus 0, Device 20, Function 0 */ + SBRI, 8, + Offset(0x000A0014), /* Byte offset to SMBUS register 14h - Bus 0, Device 20, Function 0 */ + SBB1, 32, + Offset(0x000A0078), /* Byte offset to SMBUS register 78h - Bus 0, Device 20, Function 0 */ + ,14, + P92E, 1, /* Port92 decode enable */ + } + + OperationRegion(SB5, SystemMemory, STB5, 0x1000) + Field(SB5, AnyAcc, NoLock, Preserve){ + /* Port 0 */ + Offset(0x120), /* Port 0 Task file status */ + P0ER, 1, + , 2, + P0DQ, 1, + , 3, + P0BY, 1, + Offset(0x128), /* Port 0 Serial ATA status */ + P0DD, 4, + , 4, + P0IS, 4, + Offset(0x12C), /* Port 0 Serial ATA control */ + P0DI, 4, + Offset(0x130), /* Port 0 Serial ATA error */ + , 16, + P0PR, 1, + + /* Port 1 */ + offset(0x1A0), /* Port 1 Task file status */ + P1ER, 1, + , 2, + P1DQ, 1, + , 3, + P1BY, 1, + Offset(0x1A8), /* Port 1 Serial ATA status */ + P1DD, 4, + , 4, + P1IS, 4, + Offset(0x1AC), /* Port 1 Serial ATA control */ + P1DI, 4, + Offset(0x1B0), /* Port 1 Serial ATA error */ + , 16, + P1PR, 1, + + /* Port 2 */ + Offset(0x220), /* Port 2 Task file status */ + P2ER, 1, + , 2, + P2DQ, 1, + , 3, + P2BY, 1, + Offset(0x228), /* Port 2 Serial ATA status */ + P2DD, 4, + , 4, + P2IS, 4, + Offset(0x22C), /* Port 2 Serial ATA control */ + P2DI, 4, + Offset(0x230), /* Port 2 Serial ATA error */ + , 16, + P2PR, 1, + + /* Port 3 */ + Offset(0x2A0), /* Port 3 Task file status */ + P3ER, 1, + , 2, + P3DQ, 1, + , 3, + P3BY, 1, + Offset(0x2A8), /* Port 3 Serial ATA status */ + P3DD, 4, + , 4, + P3IS, 4, + Offset(0x2AC), /* Port 3 Serial ATA control */ + P3DI, 4, + Offset(0x2B0), /* Port 3 Serial ATA error */ + , 16, + P3PR, 1, + } + + Method(CIRQ, 0x00, NotSerialized){ + Store(0, PINA) + Store(0, PINB) + Store(0, PINC) + Store(0, PIND) + Store(0, PINE) + Store(0, PINF) + Store(0, PING) + Store(0, PINH) + } + + /* set "A", 8259 interrupts */ + Name (PRSA, ResourceTemplate () { + IRQ(Level, ActiveLow, Exclusive) {4, 7, 10, 11, 12, 14, 15} + }) + + Method (CRSA, 1, Serialized) { + Name (LRTL, ResourceTemplate() { + IRQ(Level, ActiveLow, Shared) {15} + }) + CreateWordField(LRTL, 1, LIRQ) + ShiftLeft(1, Arg0, LIRQ) + Return (LRTL) + } + + Method (SRSA, 1, Serialized) { + CreateWordField(Arg0, 1, LIRQ) + FindSetRightBit(LIRQ, Local0) + if (Local0) { + Decrement(Local0) + } + Return (Local0) + } + + Device(LNKA) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 1) + Method(_STA, 0) { + if (PINA) { + Return(0x0B) /* LNKA is invisible */ + } else { + Return(0x09) /* LNKA is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PINA) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PINA)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PINA) + } + } + + Device(LNKB) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 2) + Method(_STA, 0) { + if (PINB) { + Return(0x0B) /* LNKB is invisible */ + } else { + Return(0x09) /* LNKB is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PINB) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PINB)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PINB) + } + } + + Device(LNKC) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 3) + Method(_STA, 0) { + if (PINC) { + Return(0x0B) /* LNKC is invisible */ + } else { + Return(0x09) /* LNKC is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PINC) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PINC)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PINC) + } + } + + Device(LNKD) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 4) + Method(_STA, 0) { + if (PIND) { + Return(0x0B) /* LNKD is invisible */ + } else { + Return(0x09) /* LNKD is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PIND) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PIND)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PIND) + } + } + + Device(LNKE) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 5) + Method(_STA, 0) { + if (PINE) { + Return(0x0B) /* LNKE is invisible */ + } else { + Return(0x09) /* LNKE is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PINE) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PINE)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PINE) + } + } + + Device(LNKF) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 6) + Method(_STA, 0) { + if (PINF) { + Return(0x0B) /* LNKF is invisible */ + } else { + Return(0x09) /* LNKF is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PINF) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PINF)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PINF) + } + } + + Device(LNKG) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 7) + Method(_STA, 0) { + if (PING) { + Return(0x0B) /* LNKG is invisible */ + } else { + Return(0x09) /* LNKG is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PING) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PING)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PING) + } + } + + Device(LNKH) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 8) + Method(_STA, 0) { + if (PINH) { + Return(0x0B) /* LNKH is invisible */ + } else { + Return(0x09) /* LNKH is disabled */ + } + } + Method(_DIS, 0) { + Store(0, PINH) + } + Method(_PRS, 0) { + Return (PRSA) + } + Method (_CRS, 0, Serialized) { + Return (CRSA(PINH)) + } + Method (_SRS, 1, Serialized) { + Store (SRSA(Arg0), PINH) + } + } + + } /* End Scope(_SB) */ + +} /* End Scope(/) */ diff --git a/src/southbridge/amd/sr5650/early_setup.c b/src/southbridge/amd/sr5650/early_setup.c index ec555f81b2..664f60af10 100644 --- a/src/southbridge/amd/sr5650/early_setup.c +++ b/src/southbridge/amd/sr5650/early_setup.c @@ -3,6 +3,7 @@ * * Copyright (C) 2015 Timothy Pearson , Raptor Engineering * Copyright (C) 2010 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Timothy Pearson , 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 @@ -504,7 +505,8 @@ void sr5650_early_setup(void) /*ATINB_PrepareInit */ get_cpu_rev(); - switch (get_nb_rev(nb_dev)) { /* PCIEMiscInit */ + uint8_t revno = get_nb_rev(nb_dev); + switch (revno) { /* PCIEMiscInit */ case REV_SR5650_A11: printk(BIOS_INFO, "NB Revision is A11.\n"); break; @@ -514,6 +516,9 @@ void sr5650_early_setup(void) case REV_SR5650_A21: printk(BIOS_INFO, "NB Revision is A21.\n"); break; + default: + printk(BIOS_INFO, "NB Revision is %02x (Unrecognized).\n", revno); + break; } fam10_optimization(); diff --git a/src/southbridge/amd/sr5650/ht.c b/src/southbridge/amd/sr5650/ht.c index c497107fdc..02f4f7ff19 100644 --- a/src/southbridge/amd/sr5650/ht.c +++ b/src/southbridge/amd/sr5650/ht.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 , 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 @@ -55,7 +56,7 @@ static const apic_device_info default_apic_device_info_t [] = { [13] = {4, ABCD, 30} /* Dev13 Grp4 [Int - 16..19] */ }; -/* Their name are quite regular. So I undefine them. */ +/* These define names are common, so undefine them to avoid potential issues in other code */ #undef ABCD #undef BCDA #undef CDAB diff --git a/src/southbridge/amd/sr5650/pcie.c b/src/southbridge/amd/sr5650/pcie.c index a2cc54ee86..79f2a5fa4c 100644 --- a/src/southbridge/amd/sr5650/pcie.c +++ b/src/southbridge/amd/sr5650/pcie.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 , 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 @@ -61,8 +62,10 @@ static void ValidatePortEn(device_t nb_dev) *****************************************************************/ static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) { + printk(BIOS_DEBUG, "PciePowerOffGppPorts() port %d\n", port); u32 reg; u16 state_save; + uint8_t i; struct southbridge_amd_sr5650_config *cfg = (struct southbridge_amd_sr5650_config *)nb_dev->chip_info; u16 state = cfg->port_enable; @@ -72,6 +75,28 @@ static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) state = ~state; state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); state_save = state << 17; + /* Disable ports any that failed training */ + for (i = 9; i <= 13; i++) { + if (!(AtiPcieCfg.PortDetect & 1 << i)) { + if ((port >= 9) && (port <= 13)) { + state |= (1 << (port + 7)); + } + if (port == 9) + state_save |= 1 << 25; + if (port == 10) + state_save |= 1 << 26; + if (port == 11) + state_save |= 1 << 6; + if (port == 12) + state_save |= 1 << 7; + + if (port == 13) { + reg = nbmisc_read_index(nb_dev, 0x2a); + reg |= 1 << 4; + nbmisc_write_index(nb_dev, 0x2a, reg); + } + } + } state &= !(AtiPcieCfg.PortHp); reg = nbmisc_read_index(nb_dev, 0x0c); reg |= state; @@ -483,6 +508,8 @@ static void EnableLclkGating(device_t dev) *****************************************/ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) { + uint8_t training_ok = 1; + u32 gpp_sb_sel = 0; struct southbridge_amd_sr5650_config *cfg = (struct southbridge_amd_sr5650_config *)nb_dev->chip_info; @@ -744,6 +771,12 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) port, hw_port, res); if (res) { AtiPcieCfg.PortDetect |= 1 << port; + } else { + /* If the training failed the disable the bridge to prevent subsequent + * lockup on bridge configuration register read during the PCI bus scan + */ + training_ok = 0; + dev->enabled = 0; } } } @@ -790,8 +823,8 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) * wait dev 0x6B bit3 clear */ - if (port == 8){ - PciePowerOffGppPorts(nb_dev, dev, port); /* , This should be run for all ports that are not hotplug and don't detect devices */ + if ((port == 8) || (!training_ok)) { + PciePowerOffGppPorts(nb_dev, dev, port); /* This is run for all ports that are not hotplug and don't detect devices */ } } diff --git a/src/southbridge/amd/sr5650/sr5650.c b/src/southbridge/amd/sr5650/sr5650.c index 07d5e20e8a..6db1eb1f2f 100644 --- a/src/southbridge/amd/sr5650/sr5650.c +++ b/src/southbridge/amd/sr5650/sr5650.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 , 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 @@ -95,32 +96,30 @@ void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) { /* K8 Function1 is address map */ - device_t k8_f1; - device_t np = dev_find_slot(0, PCI_DEVFN(0x19, 1)); - u16 node; - - for (node = 0; node < CONFIG_MAX_PHYSICAL_CPUS; node++) { - k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18 + node, 1)); - if (!k8_f1) { - break; - } - - if (in_out) { - /* Fill MMIO limit/base pair. */ - pci_write_config32(k8_f1, 0xbc, - (((pcie_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | 0x8 | (np ? 2 << 4 : 0 << 4)); - pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); - pci_write_config32(k8_f1, 0xb4, - ((mmio_base_add + 0x10000000 - - 1) >> 8) | (np ? 2 << 4 : 0 << 4)); - pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); - } else { - pci_write_config32(k8_f1, 0xb8, 0); - pci_write_config32(k8_f1, 0xbc, 0); - pci_write_config32(k8_f1, 0xb0, 0); - pci_write_config32(k8_f1, 0xb4, 0); - } + device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + + if (in_out) { + u32 dword, sblk; + + /* Get SBLink value (HyperTransport I/O Hub Link ID). */ + dword = pci_read_config32(k8_f0, 0x64); + sblk = (dword >> 8) & 0x3; + + /* Fill MMIO limit/base pair. */ + pci_write_config32(k8_f1, 0xbc, + (((pcie_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); + pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); + pci_write_config32(k8_f1, 0xb4, + (((mmio_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | (sblk << 4)); + pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); + } else { + pci_write_config32(k8_f1, 0xb8, 0); + pci_write_config32(k8_f1, 0xbc, 0); + pci_write_config32(k8_f1, 0xb0, 0); + pci_write_config32(k8_f1, 0xb4, 0); } } -- cgit v1.2.3