[coreboot] [patch] asus a8v-e (se|deluxe): Add _CRS method to a8v board dsdt PCI0 device definition

Tobias Diedrich ranma+coreboot at tdiedrich.de
Mon Nov 15 19:34:55 CET 2010


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 at 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)
+			}
 		}
 	}
 }




More information about the coreboot mailing list