Add _CRS method to a8v board dsdt PCI0 device definition
swiftgeek noted on irc that his A8V-E Deluxe has trouble booting Linux using filo:
16:42 < SwiftGeek> filo managed to load kernel img + initramfs img from pata device 16:42 < SwiftGeek> but there is no pata device in linux
|pci 0000:00:0b.0: no compatible bridge window for [mem 0xd2100000-0xd210ffff pref] |pci 0000:05:00.0: no compatible bridge window for [mem 0xd2000000-0xd201ffff pref] |[...]
This is because the _CRS method for the PCI0 device is missing in the dsdt. It happens to work anyway with seabios, because seabios dmi data reports the bios production year as 2007 and Linux automatically disables the use of crs in the pci code then:
arch/x86/pci/acpi.c:pci_acpi_crs_quirks(): | if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) | pci_use_crs = false;
But with filo there is no BIOS so it tries to use the non-existing crs data:
|PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug |[Firmware Bug]: ACPI: no secondary bus range in _CRS
In the end leading to a failed pata_via probe:
|pata_via 0000:00:0f.1: device not available (can't reserve [io 0x0000-0x0007]) |pata_via: probe of 0000:00:0f.1 failed with error -22
Booting with the pci=nocrs kernel option works as a workaround, but the right thing to do is adding a _crs method.
The simplistic _crs method below should work fine for both Linux and Windows XP. However, for correctness it is needed to exclude some reserved ranges:
http://permalink.gmane.org/gmane.linux.bios/63267 (However, contrary to what I stated in that message, APIC space is already accounted for by both Linux and XP and doesn't have to be included in the PNP0C02 device resources, but it doesn't hurt to include it and makes the patch as simple as possible)
Signed-off-by: Tobias Diedrich ranma+coreboot@tdiedrich.de
---
Index: src/mainboard/asus/a8v-e_se/acpi_tables.c =================================================================== --- src/mainboard/asus/a8v-e_se/acpi_tables.c.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_se/acpi_tables.c 2010-11-15 19:11:03.000000000 +0100 @@ -31,6 +31,7 @@ #include <device/pci_ids.h> #include "southbridge/via/vt8237r/vt8237r.h" #include "southbridge/via/k8t890/k8t890.h" +#include "northbridge/amd/amdk8/amdk8_acpi.h"
extern const unsigned char AmlCode[];
@@ -81,6 +82,12 @@ return current; }
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) +{ + k8acpi_write_vars(); + return (unsigned long) (acpigen_get_current()); +} + unsigned long write_acpi_tables(unsigned long start) { unsigned long current; @@ -91,6 +98,7 @@ acpi_mcfg_t *mcfg; acpi_fadt_t *fadt; acpi_facs_t *facs; + acpi_header_t *ssdt; acpi_header_t *dsdt;
/* Align ACPI tables to 16 byte. */ @@ -151,6 +159,14 @@ current += srat->header.length; acpi_add_table(rsdp, srat);
+ /* SSDT */ + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + + acpi_create_ssdt_generator(ssdt, "DYNADATA"); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + printk(BIOS_INFO, "ACPI: done.\n"); return current; } Index: src/mainboard/asus/a8v-e_se/dsdt.asl =================================================================== --- src/mainboard/asus/a8v-e_se/dsdt.asl.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_se/dsdt.asl 2010-11-15 19:09:57.000000000 +0100 @@ -206,6 +206,58 @@ } } } + + External(TOM1) /* top of memory below 4GB */ + + Method(_CRS, 0) { + Name(TMP, ResourceTemplate() { + WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Granularity + 0x0000, // Range Minimum + 0x00FF, // Range Maximum + 0x0000, // Translation Offset + 0x0100, // Length + ,, + ) + IO(Decode16, 0x0CF8, 0x0CF8, 1, 8) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0000, /* range minimum */ + 0x0CF7, /* range maximum */ + 0x0000, /* translation */ + 0x0CF8 /* length */ + ) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0D00, /* range minimum */ + 0xFFFF, /* range maximum */ + 0x0000, /* translation */ + 0xF300 /* length */ + ) + + /* memory space for PCI BARs below 4GB */ + Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO) + }) + CreateDWordField(TMP, MMIO._BAS, MM1B) + CreateDWordField(TMP, MMIO._LEN, MM1L) + /* + * Declare memory between TOM1 and 4GB as available + * for PCI MMIO. + * + * Use ShiftLeft to avoid 64bit constant (for XP). + * This will work even if the OS does 32bit arithmetic, as + * 32bit (0x00000000 - TOM1) will wrap and give the same + * result as 64bit (0x100000000 - TOM1). + */ + Store(TOM1, MM1B) + ShiftLeft(0x10000000, 4, Local0) + Subtract(Local0, TOM1, Local0) + Store(Local0, MM1L) + + Return(TMP) + } } } } Index: src/mainboard/asus/a8v-e_deluxe/acpi_tables.c =================================================================== --- src/mainboard/asus/a8v-e_deluxe/acpi_tables.c.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_deluxe/acpi_tables.c 2010-11-15 19:11:03.000000000 +0100 @@ -31,6 +31,7 @@ #include <device/pci_ids.h> #include "southbridge/via/vt8237r/vt8237r.h" #include "southbridge/via/k8t890/k8t890.h" +#include "northbridge/amd/amdk8/amdk8_acpi.h"
extern const unsigned char AmlCode[];
@@ -81,6 +82,12 @@ return current; }
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) +{ + k8acpi_write_vars(); + return (unsigned long) (acpigen_get_current()); +} + unsigned long write_acpi_tables(unsigned long start) { unsigned long current; @@ -91,6 +98,7 @@ acpi_mcfg_t *mcfg; acpi_fadt_t *fadt; acpi_facs_t *facs; + acpi_header_t *ssdt; acpi_header_t *dsdt;
/* Align ACPI tables to 16 byte. */ @@ -151,6 +159,14 @@ current += srat->header.length; acpi_add_table(rsdp, srat);
+ /* SSDT */ + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + + acpi_create_ssdt_generator(ssdt, "DYNADATA"); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + printk(BIOS_INFO, "ACPI: done.\n"); return current; } Index: src/mainboard/asus/a8v-e_deluxe/dsdt.asl =================================================================== --- src/mainboard/asus/a8v-e_deluxe/dsdt.asl.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_deluxe/dsdt.asl 2010-11-15 19:09:57.000000000 +0100 @@ -206,6 +206,58 @@ } } } + + External(TOM1) /* top of memory below 4GB */ + + Method(_CRS, 0) { + Name(TMP, ResourceTemplate() { + WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Granularity + 0x0000, // Range Minimum + 0x00FF, // Range Maximum + 0x0000, // Translation Offset + 0x0100, // Length + ,, + ) + IO(Decode16, 0x0CF8, 0x0CF8, 1, 8) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0000, /* range minimum */ + 0x0CF7, /* range maximum */ + 0x0000, /* translation */ + 0x0CF8 /* length */ + ) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0D00, /* range minimum */ + 0xFFFF, /* range maximum */ + 0x0000, /* translation */ + 0xF300 /* length */ + ) + + /* memory space for PCI BARs below 4GB */ + Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO) + }) + CreateDWordField(TMP, MMIO._BAS, MM1B) + CreateDWordField(TMP, MMIO._LEN, MM1L) + /* + * Declare memory between TOM1 and 4GB as available + * for PCI MMIO. + * + * Use ShiftLeft to avoid 64bit constant (for XP). + * This will work even if the OS does 32bit arithmetic, as + * 32bit (0x00000000 - TOM1) will wrap and give the same + * result as 64bit (0x100000000 - TOM1). + */ + Store(TOM1, MM1B) + ShiftLeft(0x10000000, 4, Local0) + Subtract(Local0, TOM1, Local0) + Store(Local0, MM1L) + + Return(TMP) + } } } }
Hi,
I think we should use for _CRS what M2V-MX uses. It reads the real decodes from the MMIO regions of K8. It is in the northbridge/amd/amdk8/amdk8_util.asl
If you look with k8resdump from utils
ruiktest:~/coreboot/util/k8resdump# make
Checking for pciutils and zlib... found. ruiktest:~/coreboot/util/k8resdump# ./k8resdump DRAM map: #0 0x0000000000 - 0x001fffffff Access: R/W IntlvEN:0x0 IntlvSEL:0x0 Dstnode:0 DRAM map: #1 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:1 DRAM map: #2 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:2 DRAM map: #3 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:3 DRAM map: #4 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:4 DRAM map: #5 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:5 DRAM map: #6 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:6 DRAM map: #7 0x0000000000 - 0x0000ffffff Access: / IntlvEN:0x0 IntlvSEL:0x0 Dstnode:7 MMIO map: #0 0x0000000000 - 0x000000ffff Access: / Dstnode:0 DstLink 0 MMIO map: #1 0x0000000000 - 0x000000ffff Access: / Dstnode:0 DstLink 0 MMIO map: #2 0x0000000000 - 0x000000ffff Access: / Dstnode:0 DstLink 0 MMIO map: #3 0x0000000000 - 0x000000ffff Access: / Dstnode:0 DstLink 0 MMIO map: #4 0x0000000000 - 0x000000ffff Access: / Dstnode:0 DstLink 0 MMIO map: #5 0x00000a0000 - 0x00000bffff Access: R/W Dstnode:0 DstLink 0 MMIO map: #6 0x00e0000000 - 0x00f12fffff Access: R/W Dstnode:0 DstLink 0 MMIO map: #7 0x00c0000000 - 0x00dfffffff Access: R/W Dstnode:0 DstLink 0 IO map: #0 0x001000 - 0x001fff Access: R/W VGA Dstnode:0 DstLink 0 IO map: #1 0x000000 - 0x000fff Access: / Dstnode:0 DstLink 0 IO map: #2 0x000000 - 0x000fff Access: / Dstnode:0 DstLink 0 IO map: #3 0x000000 - 0x000fff Access: / Dstnode:0 DstLink 0 ruiktest:~/coreboot/util/k8resdump#
You see that in fact only parts of that space is decoded.
Rudolf
On 15.11.2010 19:34, Tobias Diedrich wrote:
Add _CRS method to a8v board dsdt PCI0 device definition
swiftgeek noted on irc that his A8V-E Deluxe has trouble booting Linux using filo:
16:42< SwiftGeek> filo managed to load kernel img + initramfs img from pata device 16:42< SwiftGeek> but there is no pata device in linux
|pci 0000:00:0b.0: no compatible bridge window for [mem 0xd2100000-0xd210ffff pref] |pci 0000:05:00.0: no compatible bridge window for [mem 0xd2000000-0xd201ffff pref] |[...]
This is because the _CRS method for the PCI0 device is missing in the dsdt. It happens to work anyway with seabios, because seabios dmi data reports the bios production year as 2007 and Linux automatically disables the use of crs in the pci code then:
arch/x86/pci/acpi.c:pci_acpi_crs_quirks(): | if (dmi_get_date(DMI_BIOS_DATE,&year, NULL, NULL)&& year< 2008) | pci_use_crs = false;
But with filo there is no BIOS so it tries to use the non-existing crs data:
|PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug |[Firmware Bug]: ACPI: no secondary bus range in _CRS
In the end leading to a failed pata_via probe:
|pata_via 0000:00:0f.1: device not available (can't reserve [io 0x0000-0x0007]) |pata_via: probe of 0000:00:0f.1 failed with error -22
Booting with the pci=nocrs kernel option works as a workaround, but the right thing to do is adding a _crs method.
The simplistic _crs method below should work fine for both Linux and Windows XP. However, for correctness it is needed to exclude some reserved ranges:
http://permalink.gmane.org/gmane.linux.bios/63267 (However, contrary to what I stated in that message, APIC space is already accounted for by both Linux and XP and doesn't have to be included in the PNP0C02 device resources, but it doesn't hurt to include it and makes the patch as simple as possible)
Signed-off-by: Tobias Diedrichranma+coreboot@tdiedrich.de
Index: src/mainboard/asus/a8v-e_se/acpi_tables.c
--- src/mainboard/asus/a8v-e_se/acpi_tables.c.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_se/acpi_tables.c 2010-11-15 19:11:03.000000000 +0100 @@ -31,6 +31,7 @@ #include<device/pci_ids.h> #include "southbridge/via/vt8237r/vt8237r.h" #include "southbridge/via/k8t890/k8t890.h" +#include "northbridge/amd/amdk8/amdk8_acpi.h"
extern const unsigned char AmlCode[];
@@ -81,6 +82,12 @@ return current; }
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) +{
- k8acpi_write_vars();
- return (unsigned long) (acpigen_get_current());
+}
- unsigned long write_acpi_tables(unsigned long start) { unsigned long current;
@@ -91,6 +98,7 @@ acpi_mcfg_t *mcfg; acpi_fadt_t *fadt; acpi_facs_t *facs;
acpi_header_t *ssdt; acpi_header_t *dsdt;
/* Align ACPI tables to 16 byte. */
@@ -151,6 +159,14 @@ current += srat->header.length; acpi_add_table(rsdp, srat);
- /* SSDT */
- printk(BIOS_DEBUG, "ACPI: * SSDT\n");
- ssdt = (acpi_header_t *)current;
- acpi_create_ssdt_generator(ssdt, "DYNADATA");
- current += ssdt->length;
- acpi_add_table(rsdp, ssdt);
- printk(BIOS_INFO, "ACPI: done.\n"); return current; }
Index: src/mainboard/asus/a8v-e_se/dsdt.asl
--- src/mainboard/asus/a8v-e_se/dsdt.asl.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_se/dsdt.asl 2010-11-15 19:09:57.000000000 +0100 @@ -206,6 +206,58 @@ } } }
External(TOM1) /* top of memory below 4GB */
Method(_CRS, 0) {
Name(TMP, ResourceTemplate() {
WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Granularity
0x0000, // Range Minimum
0x00FF, // Range Maximum
0x0000, // Translation Offset
0x0100, // Length
,,
)
IO(Decode16, 0x0CF8, 0x0CF8, 1, 8)
WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, /* address granularity */
0x0000, /* range minimum */
0x0CF7, /* range maximum */
0x0000, /* translation */
0x0CF8 /* length */
)
WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, /* address granularity */
0x0D00, /* range minimum */
0xFFFF, /* range maximum */
0x0000, /* translation */
0xF300 /* length */
)
/* memory space for PCI BARs below 4GB */
Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO)
})
CreateDWordField(TMP, MMIO._BAS, MM1B)
CreateDWordField(TMP, MMIO._LEN, MM1L)
/*
* Declare memory between TOM1 and 4GB as available
* for PCI MMIO.
*
* Use ShiftLeft to avoid 64bit constant (for XP).
* This will work even if the OS does 32bit arithmetic, as
* 32bit (0x00000000 - TOM1) will wrap and give the same
* result as 64bit (0x100000000 - TOM1).
*/
Store(TOM1, MM1B)
ShiftLeft(0x10000000, 4, Local0)
Subtract(Local0, TOM1, Local0)
Store(Local0, MM1L)
Return(TMP)
} } }}
Index: src/mainboard/asus/a8v-e_deluxe/acpi_tables.c
--- src/mainboard/asus/a8v-e_deluxe/acpi_tables.c.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_deluxe/acpi_tables.c 2010-11-15 19:11:03.000000000 +0100 @@ -31,6 +31,7 @@ #include<device/pci_ids.h> #include "southbridge/via/vt8237r/vt8237r.h" #include "southbridge/via/k8t890/k8t890.h" +#include "northbridge/amd/amdk8/amdk8_acpi.h"
extern const unsigned char AmlCode[];
@@ -81,6 +82,12 @@ return current; }
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) +{
- k8acpi_write_vars();
- return (unsigned long) (acpigen_get_current());
+}
- unsigned long write_acpi_tables(unsigned long start) { unsigned long current;
@@ -91,6 +98,7 @@ acpi_mcfg_t *mcfg; acpi_fadt_t *fadt; acpi_facs_t *facs;
acpi_header_t *ssdt; acpi_header_t *dsdt;
/* Align ACPI tables to 16 byte. */
@@ -151,6 +159,14 @@ current += srat->header.length; acpi_add_table(rsdp, srat);
- /* SSDT */
- printk(BIOS_DEBUG, "ACPI: * SSDT\n");
- ssdt = (acpi_header_t *)current;
- acpi_create_ssdt_generator(ssdt, "DYNADATA");
- current += ssdt->length;
- acpi_add_table(rsdp, ssdt);
- printk(BIOS_INFO, "ACPI: done.\n"); return current; }
Index: src/mainboard/asus/a8v-e_deluxe/dsdt.asl
--- src/mainboard/asus/a8v-e_deluxe/dsdt.asl.orig 2010-11-15 19:09:56.000000000 +0100 +++ src/mainboard/asus/a8v-e_deluxe/dsdt.asl 2010-11-15 19:09:57.000000000 +0100 @@ -206,6 +206,58 @@ } } }
External(TOM1) /* top of memory below 4GB */
Method(_CRS, 0) {
Name(TMP, ResourceTemplate() {
WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Granularity
0x0000, // Range Minimum
0x00FF, // Range Maximum
0x0000, // Translation Offset
0x0100, // Length
,,
)
IO(Decode16, 0x0CF8, 0x0CF8, 1, 8)
WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, /* address granularity */
0x0000, /* range minimum */
0x0CF7, /* range maximum */
0x0000, /* translation */
0x0CF8 /* length */
)
WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, /* address granularity */
0x0D00, /* range minimum */
0xFFFF, /* range maximum */
0x0000, /* translation */
0xF300 /* length */
)
/* memory space for PCI BARs below 4GB */
Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO)
})
CreateDWordField(TMP, MMIO._BAS, MM1B)
CreateDWordField(TMP, MMIO._LEN, MM1L)
/*
* Declare memory between TOM1 and 4GB as available
* for PCI MMIO.
*
* Use ShiftLeft to avoid 64bit constant (for XP).
* This will work even if the OS does 32bit arithmetic, as
* 32bit (0x00000000 - TOM1) will wrap and give the same
* result as 64bit (0x100000000 - TOM1).
*/
Store(TOM1, MM1B)
ShiftLeft(0x10000000, 4, Local0)
Subtract(Local0, TOM1, Local0)
Store(Local0, MM1L)
Return(TMP)
} } }}