[U-Boot] [PATCH] x86: Initial ACPI support for minnowmax and qemu.

Saket Sinha saket.sinha89 at gmail.com
Fri Jul 10 02:28:21 CEST 2015


Signed-off-by: Saket Sinha <saket.sinha89 at gmail.com>
---
 arch/x86/Kconfig                           |   7 +
 arch/x86/cpu/qemu/Makefile                 |   3 +-
 arch/x86/cpu/qemu/acpi.c                   | 176 +++++++++++
 arch/x86/cpu/qemu/acpi/cpu-hotplug.asl     |  78 +++++
 arch/x86/cpu/qemu/acpi/dbug.asl            |  26 ++
 arch/x86/cpu/qemu/acpi/hpet.asl            |  36 +++
 arch/x86/cpu/qemu/acpi/isa.asl             | 102 +++++++
 arch/x86/cpu/qemu/acpi/pci-crs.asl         |  94 ++++++
 arch/x86/cpu/qemu/dsdt.asl                 | 454 +++++++++++++++++++++++++++++
 arch/x86/include/asm/acpi_table.h          | 387 ++++++++++++++++++++++++
 arch/x86/lib/Makefile                      |   1 +
 arch/x86/lib/acpi_table.c                  | 395 +++++++++++++++++++++++++
 arch/x86/lib/tables.c                      |   5 +
 board/intel/minnowmax/Makefile             |   3 +-
 board/intel/minnowmax/acpi.c               | 251 ++++++++++++++++
 board/intel/minnowmax/acpi/cpu.asl         |  56 ++++
 board/intel/minnowmax/acpi/device_nvs.asl  |  66 +++++
 board/intel/minnowmax/acpi/ec.asl          |   0
 board/intel/minnowmax/acpi/globalnvs.asl   |  83 ++++++
 board/intel/minnowmax/acpi/mainboard.asl   |   4 +
 board/intel/minnowmax/acpi/platform.asl    |  52 ++++
 board/intel/minnowmax/acpi/sleepstates.asl |   5 +
 board/intel/minnowmax/acpi/superio.asl     |   0
 board/intel/minnowmax/dsdt.asl             |  29 ++
 scripts/Makefile.lib                       |  11 +
 25 files changed, 2322 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/cpu/qemu/acpi.c
 create mode 100644 arch/x86/cpu/qemu/acpi/cpu-hotplug.asl
 create mode 100644 arch/x86/cpu/qemu/acpi/dbug.asl
 create mode 100644 arch/x86/cpu/qemu/acpi/hpet.asl
 create mode 100644 arch/x86/cpu/qemu/acpi/isa.asl
 create mode 100644 arch/x86/cpu/qemu/acpi/pci-crs.asl
 create mode 100644 arch/x86/cpu/qemu/dsdt.asl
 create mode 100644 arch/x86/include/asm/acpi_table.h
 create mode 100644 arch/x86/lib/acpi_table.c
 create mode 100644 board/intel/minnowmax/acpi.c
 create mode 100644 board/intel/minnowmax/acpi/cpu.asl
 create mode 100644 board/intel/minnowmax/acpi/device_nvs.asl
 create mode 100644 board/intel/minnowmax/acpi/ec.asl
 create mode 100644 board/intel/minnowmax/acpi/globalnvs.asl
 create mode 100644 board/intel/minnowmax/acpi/mainboard.asl
 create mode 100644 board/intel/minnowmax/acpi/platform.asl
 create mode 100644 board/intel/minnowmax/acpi/sleepstates.asl
 create mode 100644 board/intel/minnowmax/acpi/superio.asl
 create mode 100644 board/intel/minnowmax/dsdt.asl

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cbbaa4f..7beda01 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -338,6 +338,13 @@ config GENERATE_MP_TABLE
 
 endmenu
 
+config GENERATE_ACPI_TABLE 
+       bool "Generate ACPI(Advanced Configuration and Power Interface) table"   
+       default y
+       help	
+       The Advanced Configuration and Power Interface (ACPI) specification provides an open standard for device configuration and management           by the operating system. It defines platform-independent interfaces for hardware discovery, configuration, power management & monitoring.
+
+
 config MAX_PIRQ_LINKS
 	int
 	default 8
diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile
index be79723..1fbfbc5 100644
--- a/arch/x86/cpu/qemu/Makefile
+++ b/arch/x86/cpu/qemu/Makefile
@@ -4,5 +4,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += car.o dram.o qemu.o
+obj-y += car.o dram.o qemu.o 
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o
 obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/x86/cpu/qemu/acpi.c b/arch/x86/cpu/qemu/acpi.c
new file mode 100644
index 0000000..aab374a
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi.c
@@ -0,0 +1,176 @@
+#include <asm/acpi_table.h>
+#include <asm/cpu.h>
+#include <asm/ioapic.h>
+#include <asm/lapic.h>
+#include <asm/tables.h>
+#include <asm/pci.h>
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+
+void acpi_create_fadt(struct acpi_fadt * fadt, struct acpi_facs * facs, void *dsdt)
+{
+	acpi_header_t *header = &(fadt->header);
+	u16 pmbase;
+
+	pci_dev_t bdf = PCI_BDF(0, 0x1f, 0);
+	pci_read_config_word(bdf, 0x40, &pmbase);
+
+	memset((void *) fadt, 0, sizeof(struct acpi_fadt));
+	memcpy(header->signature, "FACP", 4);
+	header->length = sizeof(struct acpi_fadt);
+	header->revision = 3;
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+	header->asl_compiler_revision = 0;
+
+	fadt->firmware_ctrl = (unsigned long) facs;
+	fadt->dsdt = (unsigned long) dsdt;
+	fadt->model = 0x00;
+	fadt->preferred_pm_profile = PM_MOBILE;
+	fadt->sci_int = 0x9;
+	fadt->smi_cmd = 0;
+	fadt->acpi_enable = 0;
+	fadt->acpi_disable = 0;
+	fadt->s4bios_req = 0x0;
+	fadt->pstate_cnt = 0;
+	fadt->pm1a_evt_blk = pmbase;
+	fadt->pm1b_evt_blk = 0x0;
+	fadt->pm1a_cnt_blk = pmbase + 0x4;
+	fadt->pm1b_cnt_blk = 0x0;
+	fadt->pm2_cnt_blk = pmbase + 0x50;
+	fadt->pm_tmr_blk = pmbase + 0x8;
+	fadt->gpe0_blk = pmbase + 0x20;
+	fadt->gpe1_blk = 0;
+	fadt->pm1_evt_len = 4;
+	fadt->pm1_cnt_len = 2; /* Upper word is reserved and
+				  Linux complains about 32 bit. */
+	fadt->pm2_cnt_len = 1;
+	fadt->pm_tmr_len = 4;
+	fadt->gpe0_blk_len = 16;
+	fadt->gpe1_blk_len = 0;
+	fadt->gpe1_base = 0;
+	fadt->cst_cnt = 0;
+	fadt->p_lvl2_lat = 1;
+	fadt->p_lvl3_lat = 0x39;
+	fadt->flush_size = 0;
+	fadt->flush_stride = 0;
+	fadt->duty_offset = 1;
+	fadt->duty_width = 3;
+	fadt->day_alrm = 0xd;
+	fadt->mon_alrm = 0x00;
+	fadt->century = 0x32;
+	fadt->iapc_boot_arch = 0x00;
+	fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+			ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE |
+			ACPI_FADT_DOCKING_SUPPORTED | ACPI_FADT_RESET_REGISTER |
+			ACPI_FADT_PLATFORM_CLOCK;
+	fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
+	fadt->reset_reg.bit_width = 8;
+	fadt->reset_reg.bit_offset = 0;
+	fadt->reset_reg.resv = 0;
+	fadt->reset_reg.addrl = 0xcf9;
+	fadt->reset_reg.addrh = 0;
+	fadt->reset_value = 0x06;
+	fadt->x_firmware_ctl_l = 0; /* Set X_FIRMWARE_CTRL only if FACS is */
+	fadt->x_firmware_ctl_h = 0; /* above 4GB. If X_FIRMWARE_CTRL is set, */
+				    /* then FIRMWARE_CTRL must be zero. */
+
+	fadt->x_dsdt_l = (unsigned long)dsdt;
+	fadt->x_dsdt_h = 0;
+	fadt->x_pm1a_evt_blk.space_id = 1;
+	fadt->x_pm1a_evt_blk.bit_width = 32;
+	fadt->x_pm1a_evt_blk.bit_offset = 0;
+	fadt->x_pm1a_evt_blk.resv = 0;
+	fadt->x_pm1a_evt_blk.addrl = pmbase;
+	fadt->x_pm1a_evt_blk.addrh = 0x0;
+	fadt->x_pm1b_evt_blk.space_id = 0;
+	fadt->x_pm1b_evt_blk.bit_width = 0;
+	fadt->x_pm1b_evt_blk.bit_offset = 0;
+	fadt->x_pm1b_evt_blk.resv = 0;
+	fadt->x_pm1b_evt_blk.addrl = 0x0;
+	fadt->x_pm1b_evt_blk.addrh = 0x0;
+	fadt->x_pm1a_cnt_blk.space_id = 1;
+	fadt->x_pm1a_cnt_blk.bit_width = 16; /* Upper word is reserved and
+						Linux complains about 32 bit. */
+	fadt->x_pm1a_cnt_blk.bit_offset = 0;
+	fadt->x_pm1a_cnt_blk.resv = 0;
+	fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
+	fadt->x_pm1a_cnt_blk.addrh = 0x0;
+	fadt->x_pm1b_cnt_blk.space_id = 0;
+	fadt->x_pm1b_cnt_blk.bit_width = 0;
+	fadt->x_pm1b_cnt_blk.bit_offset = 0;
+	fadt->x_pm1b_cnt_blk.resv = 0;
+	fadt->x_pm1b_cnt_blk.addrl = 0x0;
+	fadt->x_pm1b_cnt_blk.addrh = 0x0;
+	fadt->x_pm2_cnt_blk.space_id = 1;
+	fadt->x_pm2_cnt_blk.bit_width = 8;
+	fadt->x_pm2_cnt_blk.bit_offset = 0;
+	fadt->x_pm2_cnt_blk.resv = 0;
+	fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
+	fadt->x_pm2_cnt_blk.addrh = 0x0;
+	fadt->x_pm_tmr_blk.space_id = 1;
+	fadt->x_pm_tmr_blk.bit_width = 32;
+	fadt->x_pm_tmr_blk.bit_offset = 0;
+	fadt->x_pm_tmr_blk.resv = 0;
+	fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
+	fadt->x_pm_tmr_blk.addrh = 0x0;
+	fadt->x_gpe0_blk.space_id = 1;
+	fadt->x_gpe0_blk.bit_width = 128;
+	fadt->x_gpe0_blk.bit_offset = 0;
+	fadt->x_gpe0_blk.resv = 0;
+	fadt->x_gpe0_blk.addrl = pmbase + 0x20;
+	fadt->x_gpe0_blk.addrh = 0x0;
+	fadt->x_gpe1_blk.space_id = 0;
+	fadt->x_gpe1_blk.bit_width = 0;
+	fadt->x_gpe1_blk.bit_offset = 0;
+	fadt->x_gpe1_blk.resv = 0;
+	fadt->x_gpe1_blk.addrl = 0x0;
+	fadt->x_gpe1_blk.addrh = 0x0;
+
+	header->checksum =
+	    table_compute_checksum((void *) fadt, header->length);
+
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+        /* create all subtables for processors */
+        current = acpi_create_madt_lapics(current);
+
+        /* Write SB800 IOAPIC, only one */
+        current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *) current, 2,
+                                           IO_APIC_ADDR, 0);
+
+        current += acpi_create_madt_irqoverride((struct acpi_madt_irqoverride *)
+                                                current, 0, 0, 2, 0);
+        current += acpi_create_madt_irqoverride((struct acpi_madt_irqoverride *)
+                                                current, 0, 9, 9, 0xF);
+        /* 0: mean bus 0--->ISA */
+        /* 0: PIC 0 */
+        /* 2: APIC 2 */
+        /* 5 mean: 0101 --> Edge-triggered, Active high */
+
+}
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+	pci_dev_t dev;
+	struct pci_device_id id[] = { { 0x8086, 0x29c0 } };
+        u32 reg;
+
+        dev = pci_find_devices(id, 0);
+        if (!dev) 
+                return current;
+
+        reg = pci_read_config_dword(dev, 0x60, &reg);
+        if ((reg & 0x07) != 0x01)  // require enabled + 256MB size
+                return current;
+
+	 current += acpi_create_mcfg_mmconfig((struct acpi_mcfg_mmconfig *) current,
+                                             reg & 0xf0000000, 0x0, 0x0, 255);
+
+        return current;
+}
diff --git a/arch/x86/cpu/qemu/acpi/cpu-hotplug.asl b/arch/x86/cpu/qemu/acpi/cpu-hotplug.asl
new file mode 100644
index 0000000..0f3e83b
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/cpu-hotplug.asl
@@ -0,0 +1,78 @@
+/****************************************************************
+ * CPU hotplug
+ ****************************************************************/
+
+Scope(\_SB) {
+    /* Objects filled in by run-time generated SSDT */
+    External(NTFY, MethodObj)
+    External(CPON, PkgObj)
+
+    /* Methods called by run-time generated SSDT Processor objects */
+    Method(CPMA, 1, NotSerialized) {
+        // _MAT method - create an madt apic buffer
+        // Arg0 = Processor ID = Local APIC ID
+        // Local0 = CPON flag for this cpu
+        Store(DerefOf(Index(CPON, Arg0)), Local0)
+        // Local1 = Buffer (in madt apic form) to return
+        Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
+        // Update the processor id, lapic id, and enable/disable status
+        Store(Arg0, Index(Local1, 2))
+        Store(Arg0, Index(Local1, 3))
+        Store(Local0, Index(Local1, 4))
+        Return (Local1)
+    }
+    Method(CPST, 1, NotSerialized) {
+        // _STA method - return ON status of cpu
+        // Arg0 = Processor ID = Local APIC ID
+        // Local0 = CPON flag for this cpu
+        Store(DerefOf(Index(CPON, Arg0)), Local0)
+        If (Local0) {
+            Return (0xF)
+        } Else {
+            Return (0x0)
+        }
+    }
+    Method(CPEJ, 2, NotSerialized) {
+        // _EJ0 method - eject callback
+        Sleep(200)
+    }
+
+    /* CPU hotplug notify method */
+    OperationRegion(PRST, SystemIO, 0xaf00, 32)
+    Field(PRST, ByteAcc, NoLock, Preserve) {
+        PRS, 256
+    }
+    Method(PRSC, 0) {
+        // Local5 = active cpu bitmap
+        Store(PRS, Local5)
+        // Local2 = last read byte from bitmap
+        Store(Zero, Local2)
+        // Local0 = Processor ID / APIC ID iterator
+        Store(Zero, Local0)
+        While (LLess(Local0, SizeOf(CPON))) {
+            // Local1 = CPON flag for this cpu
+            Store(DerefOf(Index(CPON, Local0)), Local1)
+            If (And(Local0, 0x07)) {
+                // Shift down previously read bitmap byte
+                ShiftRight(Local2, 1, Local2)
+            } Else {
+                // Read next byte from cpu bitmap
+                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+            }
+            // Local3 = active state for this cpu
+            Store(And(Local2, 1), Local3)
+
+            If (LNotEqual(Local1, Local3)) {
+                // State change - update CPON with new state
+                Store(Local3, Index(CPON, Local0))
+                // Do CPU notify
+                If (LEqual(Local3, 1)) {
+                    NTFY(Local0, 1)
+                } Else {
+                    NTFY(Local0, 3)
+                }
+            }
+            Increment(Local0)
+        }
+    }
+}
diff --git a/arch/x86/cpu/qemu/acpi/dbug.asl b/arch/x86/cpu/qemu/acpi/dbug.asl
new file mode 100644
index 0000000..276321f
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/dbug.asl
@@ -0,0 +1,26 @@
+/****************************************************************
+ * Debugging
+ ****************************************************************/
+
+Scope(\) {
+    /* Debug Output */
+    OperationRegion(DBG, SystemIO, 0x0402, 0x01)
+    Field(DBG, ByteAcc, NoLock, Preserve) {
+        DBGB,   8,
+    }
+
+    /* Debug method - use this method to send output to the QEMU
+     * BIOS debug port.  This method handles strings, integers,
+     * and buffers.  For example: DBUG("abc") DBUG(0x123) */
+    Method(DBUG, 1) {
+        ToHexString(Arg0, Local0)
+        ToBuffer(Local0, Local0)
+        Subtract(SizeOf(Local0), 1, Local1)
+        Store(Zero, Local2)
+        While (LLess(Local2, Local1)) {
+            Store(DerefOf(Index(Local0, Local2)), DBGB)
+            Increment(Local2)
+        }
+        Store(0x0A, DBGB)
+    }
+}
diff --git a/arch/x86/cpu/qemu/acpi/hpet.asl b/arch/x86/cpu/qemu/acpi/hpet.asl
new file mode 100644
index 0000000..f33e527
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/hpet.asl
@@ -0,0 +1,36 @@
+/****************************************************************
+ * HPET
+ ****************************************************************/
+
+Scope(\_SB) {
+    Device(HPET) {
+        Name(_HID, EISAID("PNP0103"))
+        Name(_UID, 0)
+        OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
+        Field(HPTM, DWordAcc, Lock, Preserve) {
+            VEND, 32,
+            PRD, 32,
+        }
+        Method(_STA, 0, NotSerialized) {
+            Store(VEND, Local0)
+            Store(PRD, Local1)
+            ShiftRight(Local0, 16, Local0)
+            If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
+                Return (0x0)
+            }
+            If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
+                Return (0x0)
+            }
+            Return (0x0F)
+        }
+        Name(_CRS, ResourceTemplate() {
+#if 0       /* This makes WinXP BSOD for not yet figured reasons. */
+            IRQNoFlags() {2, 8}
+#endif
+            Memory32Fixed(ReadOnly,
+                0xFED00000,         // Address Base
+                0x00000400,         // Address Length
+                )
+        })
+    }
+}
diff --git a/arch/x86/cpu/qemu/acpi/isa.asl b/arch/x86/cpu/qemu/acpi/isa.asl
new file mode 100644
index 0000000..23761db
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/isa.asl
@@ -0,0 +1,102 @@
+/* Common legacy ISA style devices. */
+Scope(\_SB.PCI0.ISA) {
+
+    Device(RTC) {
+        Name(_HID, EisaId("PNP0B00"))
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
+            IRQNoFlags() { 8 }
+            IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
+        })
+    }
+
+    Device(KBD) {
+        Name(_HID, EisaId("PNP0303"))
+        Method(_STA, 0, NotSerialized) {
+            Return (0x0f)
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
+            IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
+            IRQNoFlags() { 1 }
+        })
+    }
+
+    Device(MOU) {
+        Name(_HID, EisaId("PNP0F13"))
+        Method(_STA, 0, NotSerialized) {
+            Return (0x0f)
+        }
+        Name(_CRS, ResourceTemplate() {
+            IRQNoFlags() { 12 }
+        })
+    }
+
+    Device(FDC0) {
+        Name(_HID, EisaId("PNP0700"))
+        Method(_STA, 0, NotSerialized) {
+            Store(FDEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
+            IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
+            IRQNoFlags() { 6 }
+            DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
+        })
+    }
+
+    Device(LPT) {
+        Name(_HID, EisaId("PNP0400"))
+        Method(_STA, 0, NotSerialized) {
+            Store(LPEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
+            IRQNoFlags() { 7 }
+        })
+    }
+
+    Device(COM1) {
+        Name(_HID, EisaId("PNP0501"))
+        Name(_UID, 0x01)
+        Method(_STA, 0, NotSerialized) {
+            Store(CAEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
+            IRQNoFlags() { 4 }
+        })
+    }
+
+    Device(COM2) {
+        Name(_HID, EisaId("PNP0501"))
+        Name(_UID, 0x02)
+        Method(_STA, 0, NotSerialized) {
+            Store(CBEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
+            IRQNoFlags() { 3 }
+        })
+    }
+}
diff --git a/arch/x86/cpu/qemu/acpi/pci-crs.asl b/arch/x86/cpu/qemu/acpi/pci-crs.asl
new file mode 100644
index 0000000..63d1fd5
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/pci-crs.asl
@@ -0,0 +1,94 @@
+/* PCI CRS (current resources) definition. */
+Scope(\_SB.PCI0) {
+
+    Name(CRES, ResourceTemplate() {
+        WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+            0x0000,             // Address Space Granularity
+            0x0000,             // Address Range Minimum
+            0x00FF,             // Address Range Maximum
+            0x0000,             // Address Translation Offset
+            0x0100,             // Address Length
+            ,, )
+        IO(Decode16,
+            0x0CF8,             // Address Range Minimum
+            0x0CF8,             // Address Range Maximum
+            0x01,               // Address Alignment
+            0x08,               // Address Length
+            )
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+            0x0000,             // Address Space Granularity
+            0x0000,             // Address Range Minimum
+            0x0CF7,             // Address Range Maximum
+            0x0000,             // Address Translation Offset
+            0x0CF8,             // Address Length
+            ,, , TypeStatic)
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+            0x0000,             // Address Space Granularity
+            0x0D00,             // Address Range Minimum
+            0xFFFF,             // Address Range Maximum
+            0x0000,             // Address Translation Offset
+            0xF300,             // Address Length
+            ,, , TypeStatic)
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+            0x00000000,         // Address Space Granularity
+            0x000A0000,         // Address Range Minimum
+            0x000BFFFF,         // Address Range Maximum
+            0x00000000,         // Address Translation Offset
+            0x00020000,         // Address Length
+            ,, , AddressRangeMemory, TypeStatic)
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+            0x00000000,         // Address Space Granularity
+            0xE0000000,         // Address Range Minimum
+            0xFEBFFFFF,         // Address Range Maximum
+            0x00000000,         // Address Translation Offset
+            0x1EC00000,         // Address Length
+            ,, PW32, AddressRangeMemory, TypeStatic)
+    })
+
+    Name(CR64, ResourceTemplate() {
+        QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+            0x00000000,          // Address Space Granularity
+            0x8000000000,        // Address Range Minimum
+            0xFFFFFFFFFF,        // Address Range Maximum
+            0x00000000,          // Address Translation Offset
+            0x8000000000,        // Address Length
+            ,, PW64, AddressRangeMemory, TypeStatic)
+    })
+
+    Method(_CRS, 0) {
+#if 0
+        /* Fields provided by dynamically created ssdt */
+        External(P0S, IntObj)
+        External(P0E, IntObj)
+        External(P1V, IntObj)
+        External(P1S, BuffObj)
+        External(P1E, BuffObj)
+        External(P1L, BuffObj)
+
+        /* fixup 32bit pci io window */
+        CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
+        CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
+        CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
+        Store(P0S, PS32)
+        Store(P0E, PE32)
+        Store(Add(Subtract(P0E, P0S), 1), PL32)
+
+        If (LEqual(P1V, Zero)) {
+            Return (CRES)
+        }
+
+        /* fixup 64bit pci io window */
+        CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
+        CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
+        CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
+        Store(P1S, PS64)
+        Store(P1E, PE64)
+        Store(P1L, PL64)
+        /* add window and return result */
+        ConcatenateResTemplate(CRES, CR64, Local0)
+        Return (Local0)
+#else
+        Return (CRES)
+#endif
+    }
+}
diff --git a/arch/x86/cpu/qemu/dsdt.asl b/arch/x86/cpu/qemu/dsdt.asl
new file mode 100644
index 0000000..01aed6f
--- /dev/null
+++ b/arch/x86/cpu/qemu/dsdt.asl
@@ -0,0 +1,454 @@
+/*
+ * Bochs/QEMU ACPI DSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+/*
+ * Copyright (c) 2010 Isaku Yamahata
+ *                    yamahata at valinux co jp
+ * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
+ */
+
+DefinitionBlock (
+    "dsdt.aml",         // Output Filename
+    "DSDT",             // Signature
+    0x01,               // DSDT Compliance Revision
+    "UBOO",             // OEMID
+    "UBOOT   ",         // TABLE ID
+    0x2                 // OEM Revision
+    )
+{
+
+#include "acpi/dbug.asl"
+
+    Scope(\_SB) {
+        OperationRegion(PCST, SystemIO, 0xae00, 0x0c)
+        OperationRegion(PCSB, SystemIO, 0xae0c, 0x01)
+        Field(PCSB, AnyAcc, NoLock, WriteAsZeros) {
+            PCIB, 8,
+        }
+    }
+
+
+/****************************************************************
+ * PCI Bus definition
+ ****************************************************************/
+
+    Scope(\_SB) {
+        Device(PCI0) {
+            Name(_HID, EisaId("PNP0A08"))
+            Name(_CID, EisaId("PNP0A03"))
+            Name(_ADR, 0x00)
+            Name(_UID, 1)
+
+            // _OSC: based on sample of ACPI3.0b spec
+            Name(SUPP, 0) // PCI _OSC Support Field value
+            Name(CTRL, 0) // PCI _OSC Control Field value
+            Method(_OSC, 4) {
+                // Create DWORD-addressable fields from the Capabilities Buffer
+                CreateDWordField(Arg3, 0, CDW1)
+
+                // Check for proper UUID
+                If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
+                    // Create DWORD-addressable fields from the Capabilities Buffer
+                    CreateDWordField(Arg3, 4, CDW2)
+                    CreateDWordField(Arg3, 8, CDW3)
+
+                    // Save Capabilities DWORD2 & 3
+                    Store(CDW2, SUPP)
+                    Store(CDW3, CTRL)
+
+                    // Always allow native PME, AER (no dependencies)
+                    // Never allow SHPC (no SHPC controller in this system)
+                    And(CTRL, 0x1D, CTRL)
+
+#if 0 // For now, nothing to do
+                    If (Not(And(CDW1, 1))) { // Query flag clear?
+                        // Disable GPEs for features granted native control.
+                        If (And(CTRL, 0x01)) { // Hot plug control granted?
+                            Store(0, HPCE) // clear the hot plug SCI enable bit
+                            Store(1, HPCS) // clear the hot plug SCI status bit
+                        }
+                        If (And(CTRL, 0x04)) { // PME control granted?
+                            Store(0, PMCE) // clear the PME SCI enable bit
+                            Store(1, PMCS) // clear the PME SCI status bit
+                        }
+                        If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure?
+                            // Set status to not restore PCI Express cap structure
+                            // upon resume from S3
+                            Store(1, S3CR)
+                        }
+                    }
+#endif
+                    If (LNotEqual(Arg1, One)) {
+                        // Unknown revision
+                        Or(CDW1, 0x08, CDW1)
+                    }
+                    If (LNotEqual(CDW3, CTRL)) {
+                        // Capabilities bits were masked
+                        Or(CDW1, 0x10, CDW1)
+                    }
+                    // Update DWORD3 in the buffer
+                    Store(CTRL, CDW3)
+                } Else {
+                    Or(CDW1, 4, CDW1) // Unrecognized UUID
+                }
+                Return (Arg3)
+            }
+        }
+    }
+
+#include "acpi/pci-crs.asl"
+#include "acpi/hpet.asl"
+
+
+/****************************************************************
+ * VGA
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        Device(VGA) {
+            Name(_ADR, 0x00010000)
+            Method(_S1D, 0, NotSerialized) {
+                Return (0x00)
+            }
+            Method(_S2D, 0, NotSerialized) {
+                Return (0x00)
+            }
+            Method(_S3D, 0, NotSerialized) {
+                Return (0x00)
+            }
+        }
+    }
+
+
+/****************************************************************
+ * LPC ISA bridge
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        /* PCI D31:f0 LPC ISA bridge */
+        Device(ISA) {
+            /* PCI D31:f0 */
+            Name(_ADR, 0x001f0000)
+
+            /* ICH9 PCI to ISA irq remapping */
+            OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
+
+            OperationRegion(LPCD, PCI_Config, 0x80, 0x2)
+            Field(LPCD, AnyAcc, NoLock, Preserve) {
+                COMA,   3,
+                    ,   1,
+                COMB,   3,
+
+                Offset(0x01),
+                LPTD,   2,
+                    ,   2,
+                FDCD,   2
+            }
+            OperationRegion(LPCE, PCI_Config, 0x82, 0x2)
+            Field(LPCE, AnyAcc, NoLock, Preserve) {
+                CAEN,   1,
+                CBEN,   1,
+                LPEN,   1,
+                FDEN,   1
+            }
+        }
+    }
+
+#include "acpi/isa.asl"
+
+
+/****************************************************************
+ * PCI IRQs
+ ****************************************************************/
+
+    /* Zero => PIC mode, One => APIC Mode */
+    Name(\PICF, Zero)
+    Method(\_PIC, 1, NotSerialized) {
+        Store(Arg0, \PICF)
+    }
+
+    Scope(\_SB) {
+        Scope(PCI0) {
+#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3)  \
+    Package() { nr##ffff, 0, lnk0, 0 },           \
+    Package() { nr##ffff, 1, lnk1, 0 },           \
+    Package() { nr##ffff, 2, lnk2, 0 },           \
+    Package() { nr##ffff, 3, lnk3, 0 }
+
+#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD)
+#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA)
+#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB)
+#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC)
+
+#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH)
+#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE)
+#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF)
+#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG)
+
+            Name(PRTP, Package() {
+                prt_slot_lnkE(0x0000),
+                prt_slot_lnkF(0x0001),
+                prt_slot_lnkG(0x0002),
+                prt_slot_lnkH(0x0003),
+                prt_slot_lnkE(0x0004),
+                prt_slot_lnkF(0x0005),
+                prt_slot_lnkG(0x0006),
+                prt_slot_lnkH(0x0007),
+                prt_slot_lnkE(0x0008),
+                prt_slot_lnkF(0x0009),
+                prt_slot_lnkG(0x000a),
+                prt_slot_lnkH(0x000b),
+                prt_slot_lnkE(0x000c),
+                prt_slot_lnkF(0x000d),
+                prt_slot_lnkG(0x000e),
+                prt_slot_lnkH(0x000f),
+                prt_slot_lnkE(0x0010),
+                prt_slot_lnkF(0x0011),
+                prt_slot_lnkG(0x0012),
+                prt_slot_lnkH(0x0013),
+                prt_slot_lnkE(0x0014),
+                prt_slot_lnkF(0x0015),
+                prt_slot_lnkG(0x0016),
+                prt_slot_lnkH(0x0017),
+                prt_slot_lnkE(0x0018),
+
+                /* INTA -> PIRQA for slot 25 - 31
+                   see the default value of D<N>IR */
+                prt_slot_lnkA(0x0019),
+                prt_slot_lnkA(0x001a),
+                prt_slot_lnkA(0x001b),
+                prt_slot_lnkA(0x001c),
+                prt_slot_lnkA(0x001d),
+
+                /* PCIe->PCI bridge. use PIRQ[E-H] */
+                prt_slot_lnkE(0x001e),
+
+                prt_slot_lnkA(0x001f)
+            })
+
+#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3)  \
+    Package() { nr##ffff, 0, gsi0, 0 },           \
+    Package() { nr##ffff, 1, gsi1, 0 },           \
+    Package() { nr##ffff, 2, gsi2, 0 },           \
+    Package() { nr##ffff, 3, gsi3, 0 }
+
+#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID)
+#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA)
+#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB)
+#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC)
+
+#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH)
+#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE)
+#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF)
+#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG)
+
+            Name(PRTA, Package() {
+                prt_slot_gsiE(0x0000),
+                prt_slot_gsiF(0x0001),
+                prt_slot_gsiG(0x0002),
+                prt_slot_gsiH(0x0003),
+                prt_slot_gsiE(0x0004),
+                prt_slot_gsiF(0x0005),
+                prt_slot_gsiG(0x0006),
+                prt_slot_gsiH(0x0007),
+                prt_slot_gsiE(0x0008),
+                prt_slot_gsiF(0x0009),
+                prt_slot_gsiG(0x000a),
+                prt_slot_gsiH(0x000b),
+                prt_slot_gsiE(0x000c),
+                prt_slot_gsiF(0x000d),
+                prt_slot_gsiG(0x000e),
+                prt_slot_gsiH(0x000f),
+                prt_slot_gsiE(0x0010),
+                prt_slot_gsiF(0x0011),
+                prt_slot_gsiG(0x0012),
+                prt_slot_gsiH(0x0013),
+                prt_slot_gsiE(0x0014),
+                prt_slot_gsiF(0x0015),
+                prt_slot_gsiG(0x0016),
+                prt_slot_gsiH(0x0017),
+                prt_slot_gsiE(0x0018),
+
+                /* INTA -> PIRQA for slot 25 - 31, but 30
+                   see the default value of D<N>IR */
+                prt_slot_gsiA(0x0019),
+                prt_slot_gsiA(0x001a),
+                prt_slot_gsiA(0x001b),
+                prt_slot_gsiA(0x001c),
+                prt_slot_gsiA(0x001d),
+
+                /* PCIe->PCI bridge. use PIRQ[E-H] */
+                prt_slot_gsiE(0x001e),
+
+                prt_slot_gsiA(0x001f)
+            })
+
+            Method(_PRT, 0, NotSerialized) {
+                /* PCI IRQ routing table, example from ACPI 2.0a specification,
+                   section 6.2.8.1 */
+                /* Note: we provide the same info as the PCI routing
+                   table of the Bochs BIOS */
+                If (LEqual(\PICF, Zero)) {
+                    Return (PRTP)
+                } Else {
+                    Return (PRTA)
+                }
+            }
+        }
+
+        Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
+            PRQA,   8,
+            PRQB,   8,
+            PRQC,   8,
+            PRQD,   8,
+
+            Offset(0x08),
+            PRQE,   8,
+            PRQF,   8,
+            PRQG,   8,
+            PRQH,   8
+        }
+
+        Method(IQST, 1, NotSerialized) {
+            // _STA method - get status
+            If (And(0x80, Arg0)) {
+                Return (0x09)
+            }
+            Return (0x0B)
+        }
+        Method(IQCR, 1, NotSerialized) {
+            // _CRS method - get current settings
+            Name(PRR0, ResourceTemplate() {
+                Interrupt(, Level, ActiveHigh, Shared) { 0 }
+            })
+            CreateDWordField(PRR0, 0x05, PRRI)
+            Store(And(Arg0, 0x0F), PRRI)
+            Return (PRR0)
+        }
+
+#define define_link(link, uid, reg)                             \
+        Device(link) {                                          \
+            Name(_HID, EISAID("PNP0C0F"))                       \
+            Name(_UID, uid)                                     \
+            Name(_PRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    5, 10, 11                                   \
+                }                                               \
+            })                                                  \
+            Method(_STA, 0, NotSerialized) {                    \
+                Return (IQST(reg))                              \
+            }                                                   \
+            Method(_DIS, 0, NotSerialized) {                    \
+                Or(reg, 0x80, reg)                              \
+            }                                                   \
+            Method(_CRS, 0, NotSerialized) {                    \
+                Return (IQCR(reg))                              \
+            }                                                   \
+            Method(_SRS, 1, NotSerialized) {                    \
+                CreateDWordField(Arg0, 0x05, PRRI)              \
+                Store(PRRI, reg)                                \
+            }                                                   \
+        }
+
+        define_link(LNKA, 0, PRQA)
+        define_link(LNKB, 1, PRQB)
+        define_link(LNKC, 2, PRQC)
+        define_link(LNKD, 3, PRQD)
+        define_link(LNKE, 4, PRQE)
+        define_link(LNKF, 5, PRQF)
+        define_link(LNKG, 6, PRQG)
+        define_link(LNKH, 7, PRQH)
+
+#define define_gsi_link(link, uid, gsi)                         \
+        Device(link) {                                          \
+            Name(_HID, EISAID("PNP0C0F"))                       \
+            Name(_UID, uid)                                     \
+            Name(_PRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    gsi                                         \
+                }                                               \
+            })                                                  \
+            Name(_CRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    gsi                                         \
+                }                                               \
+            })                                                  \
+            Method(_SRS, 1, NotSerialized) {                    \
+            }                                                   \
+        }
+
+        define_gsi_link(GSIA, 0, 0x10)
+        define_gsi_link(GSIB, 0, 0x11)
+        define_gsi_link(GSIC, 0, 0x12)
+        define_gsi_link(GSID, 0, 0x13)
+        define_gsi_link(GSIE, 0, 0x14)
+        define_gsi_link(GSIF, 0, 0x15)
+        define_gsi_link(GSIG, 0, 0x16)
+        define_gsi_link(GSIH, 0, 0x17)
+    }
+
+#if 0
+#include "cpu-hotplug.asl"
+#endif
+
+
+/****************************************************************
+ * General purpose events
+ ****************************************************************/
+
+    Scope(\_GPE) {
+        Name(_HID, "ACPI0006")
+
+        Method(_L00) {
+        }
+        Method(_L01) {
+#if 0
+            // CPU hotplug event
+            \_SB.PRSC()
+#endif
+        }
+        Method(_L02) {
+        }
+        Method(_L03) {
+        }
+        Method(_L04) {
+        }
+        Method(_L05) {
+        }
+        Method(_L06) {
+        }
+        Method(_L07) {
+        }
+        Method(_L08) {
+        }
+        Method(_L09) {
+        }
+        Method(_L0A) {
+        }
+        Method(_L0B) {
+        }
+        Method(_L0C) {
+        }
+        Method(_L0D) {
+        }
+        Method(_L0E) {
+        }
+        Method(_L0F) {
+        }
+    }
+}
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
new file mode 100644
index 0000000..52992db
--- /dev/null
+++ b/arch/x86/include/asm/acpi_table.h
@@ -0,0 +1,387 @@
+#include <linux/string.h>
+#include <malloc.h>
+#include <common.h>
+#include <asm/post.h>
+
+#define RSDP_SIG		"RSD PTR "  /* RSDT pointer signature */
+#define ACPI_TABLE_CREATOR	"UBOOT   "  /* Must be exactly 8 bytes long! */
+#define OEM_ID			"UBOOT "    /* Must be exactly 6 bytes long! */
+#define ASLC			"UBOO"      /* Must be exactly 4 bytes long! */
+
+#define APM_CNT         0xb2
+#define APM_CNT_CST_CONTROL     0x85
+#define APM_CNT_PST_CONTROL     0x80
+#define APM_CNT_ACPI_DISABLE    0x1e
+#define APM_CNT_ACPI_ENABLE     0xe1
+#define APM_CNT_MBI_UPDATE      0xeb
+#define APM_CNT_GNVS_UPDATE     0xea
+#define APM_CNT_FINALIZE        0xcb
+#define APM_CNT_LEGACY          0xcc
+#define APM_STS         0xb3 
+
+
+#define MP_IRQ_POLARITY_DEFAULT 0x0
+#define MP_IRQ_POLARITY_HIGH    0x1
+#define MP_IRQ_POLARITY_LOW     0x3
+#define MP_IRQ_POLARITY_MASK    0x3
+#define MP_IRQ_TRIGGER_DEFAULT  0x0
+#define MP_IRQ_TRIGGER_EDGE     0x4
+#define MP_IRQ_TRIGGER_LEVEL    0xc
+#define MP_IRQ_TRIGGER_MASK     0xc
+
+#define ACTL                            0x00
+# define SCIS_MASK                              0x07
+# define SCIS_IRQ9                              0x00
+# define SCIS_IRQ10                             0x01
+# define SCIS_IRQ11                             0x02
+# define SCIS_IRQ20                             0x04
+# define SCIS_IRQ21                             0x05
+# define SCIS_IRQ22                             0x06
+# define SCIS_IRQ23                             0x07
+
+#define ILB_BASE_ADDRESS                0xfed08000
+#define ILB_BASE_SIZE                   0x400
+
+enum bus_type {
+        PIC =  0,
+        APIC = 2,
+        ETHIGH = 5
+};
+
+
+typedef struct acpi_gen_regaddr {
+        u8  space_id;           /* Address space ID */
+        u8  bit_width;          /* Register size in bits */
+        u8  bit_offset;         /* Register bit offset */
+        union {
+                u8  resv;                       /* Reserved in ACPI 2.0 - 2.0b */
+                u8  access_size;        /* Access size in ACPI 2.0c/3.0/4.0/5.0 */
+        };
+        u32 addrl;              /* Register address, low 32 bits */
+        u32 addrh;              /* Register address, high 32 bits */
+} __attribute__ ((packed)) acpi_addr_t;
+
+
+/* RSDP (Root System Description Pointer) */
+struct __packed acpi_rsdp {
+	char  signature[8];	/* RSDP signature */
+	u8    checksum;		/* Checksum of the first 20 bytes */
+	char  oem_id[6];	/* OEM ID */
+	u8    revision;		/* 0 for ACPI 1.0, 2 for ACPI 2.0/3.0/4.0 */
+	u32   rsdt_address;	/* Physical address of RSDT (32 bits) */
+	u32   length;		/* Total RSDP length (incl. extended part) */
+	u64   xsdt_address;	/* Physical address of XSDT (64 bits) */
+	u8    ext_checksum;	/* Checksum of the whole table */
+	u8    reserved[3];
+};
+/* Note: ACPI 1.0 didn't have length, xsdt_address, and ext_checksum. */
+
+enum acpi_address_space_type {
+	ACPI_ADDRESS_SPACE_MEMORY = 0,	/* System memory */
+	ACPI_ADDRESS_SPACE_IO = 1,	/* System I/O */
+	ACPI_ADDRESS_SPACE_PCI = 2,	/* PCI config space */
+	ACPI_ADDRESS_SPACE_EC = 3,	/* Embedded controller */
+	ACPI_ADDRESS_SPACE_SMBUS = 4,	/* SMBus */
+	ACPI_ADDRESS_SPACE_PCC = 0x0A,	/* Platform Comm. Channel */
+	ACPI_ADDRESS_SPACE_FIXED = 0x7f	/* Functional fixed hardware */
+};
+
+#define  ACPI_FFIXEDHW_VENDOR_INTEL	   1	/* Intel */
+#define  ACPI_FFIXEDHW_CLASS_HLT	   0	/* C1 Halt */
+#define  ACPI_FFIXEDHW_CLASS_IO_HLT	   1	/* C1 I/O then Halt */
+#define  ACPI_FFIXEDHW_CLASS_MWAIT	   2	/* MWAIT Native C-state */
+#define  ACPI_FFIXEDHW_FLAG_HW_COORD	   1	/* Hardware Coordination bit */
+#define  ACPI_FFIXEDHW_FLAG_BM_STS	   2	/* BM_STS avoidance bit */
+/* 0x80-0xbf: Reserved */
+/* 0xc0-0xff: OEM defined */
+
+/* Access size definitions for Generic address structure */
+enum acpi_address_space_size {
+	ACPI_ACCESS_SIZE_UNDEFINED = 0,	/* Undefined (legacy reasons) */
+	ACPI_ACCESS_SIZE_BYTE_ACCESS = 1,
+	ACPI_ACCESS_SIZE_WORD_ACCESS = 2,
+	ACPI_ACCESS_SIZE_DWORD_ACCESS = 3,
+	ACPI_ACCESS_SIZE_QWORD_ACCESS = 4
+};
+
+/* Generic ACPI header, provided by (almost) all tables */
+typedef struct acpi_table_header {
+	char signature[4];           /* ACPI signature (4 ASCII characters) */
+	u32  length;                 /* Table length in bytes (incl. header) */
+	u8   revision;               /* Table version (not ACPI version!) */
+	u8   checksum;               /* To make sum of entire table == 0 */
+	char oem_id[6];              /* OEM identification */
+	char oem_table_id[8];        /* OEM table identification */
+	u32  oem_revision;           /* OEM revision number */
+	char asl_compiler_id[4];     /* ASL compiler vendor ID */
+	u32  asl_compiler_revision;  /* ASL compiler revision number */
+} __attribute__ ((packed)) acpi_header_t;
+
+/* A maximum number of 32 ACPI tables ought to be enough for now. */
+#define MAX_ACPI_TABLES 32
+
+/* RSDT (Root System Description Table) */
+struct __packed acpi_rsdt {
+	struct acpi_table_header header;
+	u32 entry[MAX_ACPI_TABLES];
+};
+
+/* XSDT (Extended System Description Table) */
+struct __packed acpi_xsdt {
+	struct acpi_table_header header;
+	u64 entry[MAX_ACPI_TABLES];
+};
+
+/* MCFG (PCI Express MMIO config space BAR description table) */
+struct __packed acpi_mcfg {
+	struct acpi_table_header header;
+	u8 reserved[8];
+};
+
+struct __packed acpi_mcfg_mmconfig {
+	u32 base_address;
+	u32 base_reserved;
+	u16 pci_segment_group_number;
+	u8 start_bus_number;
+	u8 end_bus_number;
+	u8 reserved[4];
+};
+
+/* MADT (Multiple APIC Description Table) */
+struct __packed acpi_madt {
+	struct acpi_table_header header;
+	u32 lapic_addr;			/* Local APIC address */
+	u32 flags;			/* Multiple APIC flags */
+} __attribute__ ((packed)) acpi_madt_t;
+
+enum dev_scope_type {
+	SCOPE_PCI_ENDPOINT = 1,
+	SCOPE_PCI_SUB = 2,
+	SCOPE_IOAPIC = 3,
+	SCOPE_MSI_HPET = 4
+};
+
+typedef struct dev_scope {
+	u8 type;
+	u8 length;
+	u8 reserved[2];
+	u8 enumeration;
+	u8 start_bus;
+	struct {
+		u8 dev;
+		u8 fn;
+	} __attribute__((packed)) path[0];
+} __attribute__ ((packed)) dev_scope_t;
+
+/* MADT: APIC Structure Types */
+/* TODO: Convert to ALLCAPS. */
+enum acpi_apic_types {
+	LocalApic		= 0,	/* Processor local APIC */
+	IOApic			= 1,	/* I/O APIC */
+	IRQSourceOverride	= 2,	/* Interrupt source override */
+	NMIType			= 3,	/* NMI source */
+	LocalApicNMI		= 4,	/* Local APIC NMI */
+	LApicAddressOverride	= 5,	/* Local APIC address override */
+	IOSApic			= 6,	/* I/O SAPIC */
+	LocalSApic		= 7,	/* Local SAPIC */
+	PlatformIRQSources	= 8,	/* Platform interrupt sources */
+	Localx2Apic		= 9,	/* Processor local x2APIC */
+	Localx2ApicNMI		= 10,	/* Local x2APIC NMI */
+	/* 0x0b-0x7f: Reserved */
+	/* 0x80-0xff: Reserved for OEM use */
+};
+
+/* MADT: Processor Local APIC Structure */
+struct __packed acpi_madt_lapic {
+	u8 type;			/* Type (0) */
+	u8 length;			/* Length in bytes (8) */
+	u8 processor_id;		/* ACPI processor ID */
+	u8 apic_id;			/* Local APIC ID */
+	u32 flags;			/* Local APIC flags */
+};
+
+/* MADT: Local APIC NMI Structure */
+struct __packed acpi_madt_lapic_nmi {
+	u8 type;			/* Type (4) */
+	u8 length;			/* Length in bytes (6) */
+	u8 processor_id;		/* ACPI processor ID */
+	u16 flags;			/* MPS INTI flags */
+	u8 lint;			/* Local APIC LINT# */
+};
+
+/* MADT: I/O APIC Structure */
+struct __packed acpi_madt_ioapic {
+	u8 type;			/* Type (1) */
+	u8 length;			/* Length in bytes (12) */
+	u8 ioapic_id;			/* I/O APIC ID */
+	u8 reserved;
+	u32 ioapic_addr;		/* I/O APIC address */
+	u32 gsi_base;			/* Global system interrupt base */
+};
+
+/* MADT: Interrupt Source Override Structure */
+struct __packed acpi_madt_irqoverride {
+	u8 type;			/* Type (2) */
+	u8 length;			/* Length in bytes (10) */
+	u8 bus;				/* ISA (0) */
+	u8 source;			/* Bus-relative int. source (IRQ) */
+	u32 gsirq;			/* Global system interrupt */
+	u16 flags;			/* MPS INTI flags */
+};
+
+/* FADT (Fixed ACPI Description Table) */
+struct __packed acpi_fadt {
+	struct acpi_table_header header;
+	u32 firmware_ctrl;
+	u32 dsdt;
+	u8 model;
+	u8 preferred_pm_profile;
+	u16 sci_int;
+	u32 smi_cmd;
+	u8 acpi_enable;
+	u8 acpi_disable;
+	u8 s4bios_req;
+	u8 pstate_cnt;
+	u32 pm1a_evt_blk;
+	u32 pm1b_evt_blk;
+	u32 pm1a_cnt_blk;
+	u32 pm1b_cnt_blk;
+	u32 pm2_cnt_blk;
+	u32 pm_tmr_blk;
+	u32 gpe0_blk;
+	u32 gpe1_blk;
+	u8 pm1_evt_len;
+	u8 pm1_cnt_len;
+	u8 pm2_cnt_len;
+	u8 pm_tmr_len;
+	u8 gpe0_blk_len;
+	u8 gpe1_blk_len;
+	u8 gpe1_base;
+	u8 cst_cnt;
+	u16 p_lvl2_lat;
+	u16 p_lvl3_lat;
+	u16 flush_size;
+	u16 flush_stride;
+	u8 duty_offset;
+	u8 duty_width;
+	u8 day_alrm;
+	u8 mon_alrm;
+	u8 century;
+	u16 iapc_boot_arch;
+	u8 res2;
+	u32 flags;
+	struct acpi_gen_regaddr reset_reg;
+	u8 reset_value;
+	u8 res3;
+	u8 res4;
+	u8 res5;
+	u32 x_firmware_ctl_l;
+	u32 x_firmware_ctl_h;
+	u32 x_dsdt_l;
+	u32 x_dsdt_h;
+	struct acpi_gen_regaddr x_pm1a_evt_blk;
+	struct acpi_gen_regaddr x_pm1b_evt_blk;
+	struct acpi_gen_regaddr x_pm1a_cnt_blk;
+	struct acpi_gen_regaddr x_pm1b_cnt_blk;
+	struct acpi_gen_regaddr x_pm2_cnt_blk;
+	struct acpi_gen_regaddr x_pm_tmr_blk;
+	struct acpi_gen_regaddr x_gpe0_blk;
+	struct acpi_gen_regaddr x_gpe1_blk;
+};
+
+/* FADT TABLE Revision values */
+#define ACPI_FADT_REV_ACPI_1_0		1
+#define ACPI_FADT_REV_ACPI_2_0		3
+#define ACPI_FADT_REV_ACPI_3_0		4
+#define ACPI_FADT_REV_ACPI_4_0		4
+#define ACPI_FADT_REV_ACPI_5_0		5
+
+/* Flags for p_lvl2_lat and p_lvl3_lat */
+#define ACPI_FADT_C2_NOT_SUPPORTED	101
+#define ACPI_FADT_C3_NOT_SUPPORTED	1001
+
+/* FADT Feature Flags */
+#define ACPI_FADT_WBINVD		(1 << 0)
+#define ACPI_FADT_WBINVD_FLUSH		(1 << 1)
+#define ACPI_FADT_C1_SUPPORTED		(1 << 2)
+#define ACPI_FADT_C2_MP_SUPPORTED	(1 << 3)
+#define ACPI_FADT_POWER_BUTTON		(1 << 4)
+#define ACPI_FADT_SLEEP_BUTTON		(1 << 5)
+#define ACPI_FADT_FIXED_RTC		(1 << 6)
+#define ACPI_FADT_S4_RTC_WAKE		(1 << 7)
+#define ACPI_FADT_32BIT_TIMER		(1 << 8)
+#define ACPI_FADT_DOCKING_SUPPORTED	(1 << 9)
+#define ACPI_FADT_RESET_REGISTER	(1 << 10)
+#define ACPI_FADT_SEALED_CASE		(1 << 11)
+#define ACPI_FADT_HEADLESS		(1 << 12)
+#define ACPI_FADT_SLEEP_TYPE		(1 << 13)
+#define ACPI_FADT_PCI_EXPRESS_WAKE	(1 << 14)
+#define ACPI_FADT_PLATFORM_CLOCK	(1 << 15)
+#define ACPI_FADT_S4_RTC_VALID		(1 << 16)
+#define ACPI_FADT_REMOTE_POWER_ON	(1 << 17)
+#define ACPI_FADT_APIC_CLUSTER		(1 << 18)
+#define ACPI_FADT_APIC_PHYSICAL		(1 << 19)
+/* Bits 20-31: reserved ACPI 3.0 & 4.0 */
+#define ACPI_FADT_HW_REDUCED_ACPI	(1 << 20)
+#define ACPI_FADT_LOW_PWR_IDLE_S0	(1 << 21)
+/* bits 22-31: reserved ACPI 5.0 */
+
+/* FADT Boot Architecture Flags */
+enum acpi_fadt_boot_flags {
+	ACPI_FADT_LEGACY_DEVICES = (1 << 0),
+	ACPI_FADT_8042 = (1 << 1),
+	ACPI_FADT_VGA_NOT_PRESENT = (1 << 2),
+	ACPI_FADT_MSI_NOT_SUPPORTED = (1 << 3),
+	ACPI_FADT_NO_PCIE_ASPM_CONTROL = (1 << 4),
+	ACPI_FADT_LEGACY_FREE = 0x00	/* No legacy devices (including 8042) */
+};
+/* FADT Preferred Power Management Profile */
+enum acpi_preferred_pm_profiles {
+	PM_UNSPECIFIED		= 0,
+	PM_DESKTOP		= 1,
+	PM_MOBILE		= 2,
+	PM_WORKSTATION		= 3,
+	PM_ENTERPRISE_SERVER	= 4,
+	PM_SOHO_SERVER  	= 5,
+	PM_APPLIANCE_PC		= 6,
+	PM_PERFORMANCE_SERVER	= 7,
+	PM_TABLET		= 8,	/* ACPI 5.0 */
+};
+
+/* FACS (Firmware ACPI Control Structure) */
+struct __packed acpi_facs {
+	char signature[4];			/* "FACS" */
+	u32 length;				/* Length in bytes (>= 64) */
+	u32 hardware_signature;			/* Hardware signature */
+	u32 firmware_waking_vector;		/* Firmware waking vector */
+	u32 global_lock;			/* Global lock */
+	u32 flags;				/* FACS flags */
+	u32 x_firmware_waking_vector_l;		/* X FW waking vector, low */
+	u32 x_firmware_waking_vector_h;		/* X FW waking vector, high */
+	u8 version;				/* ACPI 4.0: 2 */
+	u8 resv[31];				/* FIXME: 4.0: ospm_flags */
+};
+
+/* FACS flags */
+#define ACPI_FACS_S4BIOS_F	(1 << 0)
+#define ACPI_FACS_64BIT_WAKE_F	(1 << 1)
+/* Bits 31..2: reserved */
+
+/* These can be used by the target port. */
+
+void acpi_add_table(struct acpi_rsdp *rsdp, void *table);
+unsigned long write_acpi_tables(unsigned long start);
+int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic, u8 cpu, u8 apic);
+unsigned long acpi_create_madt_lapics(unsigned long current);
+int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id, u32 addr, u32 gsi_base);
+int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride, u8 bus, u8 source, u32 gsirq, u16 flags);
+unsigned long acpi_fill_mcfg(unsigned long current);
+unsigned long acpi_fill_madt(unsigned long current);
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs, void *dsdt);
+int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end);
+
+static inline uint32_t read32(const void *addr)
+{
+        return *(volatile uint32_t *)addr;
+}
+
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 43489fd..ce23af3 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -29,6 +29,7 @@ obj-y += physmem.o
 obj-$(CONFIG_X86_RAMTEST) += ramtest.o
 obj-y += sfi.o
 obj-y	+= string.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
 obj-y	+= tables.o
 obj-$(CONFIG_SYS_X86_TSC_TIMER)	+= tsc_timer.o
 obj-$(CONFIG_CMD_ZBOOT)	+= zimage.o
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
new file mode 100644
index 0000000..eb4bf14
--- /dev/null
+++ b/arch/x86/lib/acpi_table.c
@@ -0,0 +1,395 @@
+#include <asm/acpi_table.h>
+#include <asm/cpu.h>
+#include <asm/ioapic.h>
+#include <asm/lapic.h>
+#include <asm/tables.h>
+#include <asm/pci.h>
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+ 
+extern const unsigned char AmlCode[];
+
+/**
+ * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length
+ * and checksum.
+ */
+void acpi_add_table(struct acpi_rsdp *rsdp, void *table)
+{
+	int i, entries_num;
+	struct acpi_rsdt *rsdt;
+	struct acpi_xsdt *xsdt = NULL;
+
+	/* The RSDT is mandatory... */
+	rsdt = (struct acpi_rsdt *)rsdp->rsdt_address;
+
+	/* ...while the XSDT is not. */
+	if (rsdp->xsdt_address)
+		xsdt = (struct acpi_xsdt *)((u32)rsdp->xsdt_address);
+
+	/* This should always be MAX_ACPI_TABLES. */
+	entries_num = ARRAY_SIZE(rsdt->entry);
+
+	for (i = 0; i < entries_num; i++) {
+		if (rsdt->entry[i] == 0)
+			break;
+	}
+
+	if (i >= entries_num) {
+		debug("ACPI: Error: Could not add ACPI table, "
+			"too many tables.\n");
+		return;
+	}
+
+	/* Add table to the RSDT. */
+	rsdt->entry[i] = (u32)table;
+
+	/* Fix RSDT length or the kernel will assume invalid entries. */
+	rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i + 1));
+
+	/* Re-calculate checksum. */
+	rsdt->header.checksum = 0; /* Hope this won't get optimized away */
+	rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, rsdt->header.length);
+
+	/*
+	 * And now the same thing for the XSDT. We use the same index as for
+	 * now we want the XSDT and RSDT to always be in sync in coreboot.
+	 */
+	if (xsdt) {
+		/* Add table to the XSDT. */
+		xsdt->entry[i] = (u64)(u32)table;
+
+		/* Fix XSDT length. */
+		xsdt->header.length = sizeof(acpi_header_t) +
+					(sizeof(u64) * (i + 1));
+
+		/* Re-calculate checksum. */
+		xsdt->header.checksum = 0;
+		xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
+							xsdt->header.length);
+	}
+
+}
+
+int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic, u8 cpu, u8 apic)
+{
+        lapic->type = 0; /* Local APIC structure */
+        lapic->length = sizeof(struct acpi_madt_lapic);
+        lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
+        lapic->processor_id = cpu;
+        lapic->apic_id = apic;
+
+        return lapic->length;
+}
+
+unsigned long acpi_create_madt_lapics(unsigned long current)
+{
+	struct udevice *dev;
+
+        for (uclass_find_first_device(UCLASS_CPU, &dev);
+             dev;
+             uclass_find_next_device(&dev)) {
+                struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+     		current += acpi_create_madt_lapic((struct acpi_madt_lapic *)current, plat->cpu_id, plat->cpu_id);
+	}
+        return current;
+}
+
+int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id, u32 addr,
+                                u32 gsi_base)
+{
+        ioapic->type = 1; /* I/O APIC structure */
+        ioapic->length = sizeof(struct acpi_madt_ioapic);
+        ioapic->reserved = 0x00;
+        ioapic->gsi_base = gsi_base;
+        ioapic->ioapic_id = id;
+        ioapic->ioapic_addr = addr;
+
+        return ioapic->length;
+}
+
+int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
+                u8 bus, u8 source, u32 gsirq, u16 flags)
+{
+        irqoverride->type = 2; /* Interrupt source override */
+        irqoverride->length = sizeof(struct acpi_madt_irqoverride);
+        irqoverride->bus = bus;
+        irqoverride->source = source;
+        irqoverride->gsirq = gsirq;
+        irqoverride->flags = flags;
+
+        return irqoverride->length;
+}
+
+static void acpi_create_madt(struct acpi_madt *madt)
+{
+	acpi_header_t *header = &(madt->header);
+	unsigned long current = (unsigned long)madt + sizeof(struct acpi_madt);
+
+	memset((void *)madt, 0, sizeof(struct acpi_madt));
+
+	/* Fill out header fields. */
+	memcpy(header->signature, "APIC", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(struct acpi_madt);
+	header->revision = 1; /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
+
+	madt->lapic_addr = LAPIC_DEFAULT_BASE;
+	madt->flags = 0x1; /* PCAT_COMPAT */
+
+	current = acpi_fill_madt(current);
+
+	/* (Re)calculate length and checksum. */
+	header->length = current - (unsigned long)madt;
+
+	header->checksum = table_compute_checksum((void *)madt, header->length);
+}
+
+int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
+                                u16 seg_nr, u8 start, u8 end)
+{
+        memset(mmconfig, 0, sizeof(*mmconfig));
+        mmconfig->base_address = base;
+        mmconfig->base_reserved = 0;
+        mmconfig->pci_segment_group_number = seg_nr;
+        mmconfig->start_bus_number = start;
+        mmconfig->end_bus_number = end;
+
+        return sizeof(struct acpi_mcfg_mmconfig);
+}
+
+/* MCFG is defined in the PCI Firmware Specification 3.0. */
+static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
+{
+	acpi_header_t *header = &(mcfg->header);
+	unsigned long current = (unsigned long)mcfg + sizeof(struct acpi_mcfg);
+
+	memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
+
+	/* Fill out header fields. */
+	memcpy(header->signature, "MCFG", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(struct acpi_mcfg);
+	header->revision = 1;
+
+	current = acpi_fill_mcfg(current);
+
+	/* (Re)calculate length and checksum. */
+	header->length = current - (unsigned long)mcfg;
+	header->checksum = table_compute_checksum((void *)mcfg, header->length);
+}
+
+static void acpi_create_facs(struct acpi_facs *facs)
+{
+	memset((void *)facs, 0, sizeof(struct acpi_facs));
+
+	memcpy(facs->signature, "FACS", 4);
+	facs->length = sizeof(struct acpi_facs);
+	facs->hardware_signature = 0;
+	facs->firmware_waking_vector = 0;
+	facs->global_lock = 0;
+	facs->flags = 0;
+	facs->x_firmware_waking_vector_l = 0;
+	facs->x_firmware_waking_vector_h = 0;
+	facs->version = 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
+}
+
+static void acpi_write_rsdt(struct acpi_rsdt *rsdt)
+{
+	acpi_header_t *header = &(rsdt->header);
+
+	/* Fill out header fields. */
+	memcpy(header->signature, "RSDT", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(struct acpi_rsdt);
+	header->revision = 1; /* ACPI 1.0/2.0/3.0/4.0: 1 */
+
+	/* Entries are filled in later, we come with an empty set. */
+
+	/* Fix checksum. */
+	header->checksum = table_compute_checksum((void *)rsdt, sizeof(struct acpi_rsdt));
+}
+
+static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
+{
+	acpi_header_t *header = &(xsdt->header);
+
+	/* Fill out header fields. */
+	memcpy(header->signature, "XSDT", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(struct acpi_xsdt);
+	header->revision = 1; /* ACPI 1.0: N/A, 2.0/3.0/4.0: 1 */
+
+	/* Entries are filled in later, we come with an empty set. */
+
+	/* Fix checksum. */
+	header->checksum = table_compute_checksum((void *)xsdt, sizeof(struct acpi_xsdt));
+}
+
+static void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt)
+{
+	memset(rsdp, 0, sizeof(struct acpi_rsdp));
+
+	memcpy(rsdp->signature, RSDP_SIG, 8);
+	memcpy(rsdp->oem_id, OEM_ID, 6);
+
+	rsdp->length = sizeof(struct acpi_rsdp);
+	rsdp->rsdt_address = (u32)rsdt;
+
+	/*
+	 * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2.
+	 *
+	 * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2.
+	 * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR
+	 * revision 0).
+	 */
+	if (xsdt == NULL) {
+		rsdp->revision = 0;
+	} else {
+		rsdp->xsdt_address = (u64)(u32)xsdt;
+		rsdp->revision = 2;
+	}
+
+	/* Calculate checksums. */
+	rsdp->checksum = table_compute_checksum((void *)rsdp, 20);
+	rsdp->ext_checksum = table_compute_checksum((void *)rsdp, sizeof(struct acpi_rsdp));
+}
+
+static void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id)
+{
+        unsigned long current = (unsigned long)ssdt + sizeof(acpi_header_t);
+
+        memset((void *)ssdt, 0, sizeof(acpi_header_t));
+
+        memcpy(&ssdt->signature, "SSDT", 4);
+        ssdt->revision = 2; /* ACPI 1.0/2.0: ?, ACPI 3.0/4.0: 2 */
+        memcpy(&ssdt->oem_id, OEM_ID, 6);
+        memcpy(&ssdt->oem_table_id, oem_table_id, 8);
+        ssdt->oem_revision = 42;
+        memcpy(&ssdt->asl_compiler_id, ASLC, 4);
+        ssdt->asl_compiler_revision = 42;
+        ssdt->length = sizeof(acpi_header_t);
+
+        /* (Re)calculate length and checksum. */
+        ssdt->length = current - (unsigned long)ssdt;
+        ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
+}
+
+
+#define ALIGN_CURRENT current = (ALIGN(current, 16))
+unsigned long write_acpi_tables(unsigned long start)
+{
+	unsigned long current;
+	struct acpi_rsdp *rsdp;
+	struct acpi_rsdt *rsdt;
+	struct acpi_xsdt *xsdt;
+	struct acpi_facs *facs;
+	acpi_header_t *dsdt;
+	struct acpi_fadt *fadt;
+	struct acpi_mcfg *mcfg;
+	struct acpi_madt *madt;
+	acpi_header_t *ssdt;
+
+	current = start;
+
+	/* Align ACPI tables to 16byte */
+	ALIGN_CURRENT;
+
+	debug("ACPI: Writing ACPI tables at %lx.\n", start);
+
+	/* We need at least an RSDP and an RSDT Table */
+	rsdp = (struct acpi_rsdp *) current;
+	current += sizeof(struct acpi_rsdp);
+	ALIGN_CURRENT;
+	rsdt = (struct acpi_rsdt *) current;
+	current += sizeof(struct acpi_rsdt);
+	ALIGN_CURRENT;
+	xsdt = (struct acpi_xsdt *) current;
+	current += sizeof(struct acpi_xsdt);
+	ALIGN_CURRENT;
+
+	/* clear all table memory */
+	memset((void *) start, 0, current - start);
+
+	acpi_write_rsdp(rsdp, rsdt, xsdt);
+	acpi_write_rsdt(rsdt);
+	acpi_write_xsdt(xsdt);
+	
+	debug("ACPI:    * FACS\n");
+	facs = (struct acpi_facs *) current;
+	current += sizeof(struct acpi_facs);
+	ALIGN_CURRENT;
+
+	acpi_create_facs(facs);
+
+	debug("ACPI:    * DSDT\n");
+        dsdt = (acpi_header_t *) current;
+        memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
+        if (dsdt->length >= sizeof(acpi_header_t)) {
+               current += sizeof(acpi_header_t);
+               memcpy((char *)current,
+                      (char *)&AmlCode + sizeof(acpi_header_t),
+                      dsdt->length - sizeof(acpi_header_t));
+               current += dsdt->length - sizeof(acpi_header_t);
+
+               /* (Re)calculate length and checksum. */
+               dsdt->length = current - (unsigned long)dsdt;
+               dsdt->checksum = 0;
+               dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
+        }
+        ALIGN_CURRENT;
+
+        debug("ACPI:    * FADT\n");
+        fadt = (struct acpi_fadt *) current;
+        current += sizeof(struct acpi_fadt);
+        ALIGN_CURRENT;
+        acpi_create_fadt(fadt, facs, dsdt);
+        acpi_add_table(rsdp, fadt);
+
+	debug("ACPI:    * MCFG\n");
+	mcfg = (struct acpi_mcfg *) current;
+	acpi_create_mcfg(mcfg);
+	if (mcfg->header.length > sizeof(struct acpi_mcfg)) {
+		current += mcfg->header.length;
+		ALIGN_CURRENT;
+		acpi_add_table(rsdp, mcfg);
+	}
+
+	debug("ACPI:    * MADT\n");
+	madt = (struct acpi_madt *) current;
+	acpi_create_madt(madt);
+	if (madt->header.length > sizeof(struct acpi_madt)) {
+		current+=madt->header.length;
+		acpi_add_table(rsdp,madt);
+	}
+	ALIGN_CURRENT;
+
+        debug("ACPI:    * SSDT\n");
+	ssdt = (acpi_header_t *)current;
+        acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
+        if (ssdt->length > sizeof(acpi_header_t)) {
+                current += ssdt->length;
+                acpi_add_table(rsdp, ssdt);
+                ALIGN_CURRENT;
+        }
+	
+
+	debug("current = %lx\n", current);
+
+	debug("ACPI: done.\n");
+	return current;
+}
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c
index 75ffbc1..5ed1c7e 100644
--- a/arch/x86/lib/tables.c
+++ b/arch/x86/lib/tables.c
@@ -8,6 +8,7 @@
 #include <asm/sfi.h>
 #include <asm/mpspec.h>
 #include <asm/tables.h>
+#include <asm/acpi_table.h>
 
 u8 table_compute_checksum(void *v, int len)
 {
@@ -51,4 +52,8 @@ void write_tables(void)
 	rom_table_end = write_mp_table(rom_table_end);
 	rom_table_end = ALIGN(rom_table_end, 1024);
 #endif
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+        rom_table_end = write_acpi_tables(rom_table_end);
+        rom_table_end = ALIGN(rom_table_end, 1024);
+#endif
 }
diff --git a/board/intel/minnowmax/Makefile b/board/intel/minnowmax/Makefile
index 1a61432..ec3776f 100644
--- a/board/intel/minnowmax/Makefile
+++ b/board/intel/minnowmax/Makefile
@@ -4,4 +4,5 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y	+= minnowmax.o start.o
+obj-y	+= minnowmax.o start.o 
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o
diff --git a/board/intel/minnowmax/acpi.c b/board/intel/minnowmax/acpi.c
new file mode 100644
index 0000000..a41e67d
--- /dev/null
+++ b/board/intel/minnowmax/acpi.c
@@ -0,0 +1,251 @@
+#include <asm/acpi_table.h>
+#include <asm/cpu.h>
+#include <asm/ioapic.h>
+#include <asm/lapic.h>
+#include <asm/tables.h>
+#include <asm/pci.h>
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+
+static inline uint32_t read32(const void *addr)
+{
+        dmb();
+        return *(volatile uint32_t *)addr;
+}
+
+static int acpi_sci_irq(void)
+{
+        u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
+        int scis;
+        static int sci_irq;
+
+        if (sci_irq)
+                return sci_irq;
+
+        /* Determine how SCI is routed. */
+        scis = read32(actl) & SCIS_MASK;
+        switch (scis) {
+        case SCIS_IRQ9:
+        case SCIS_IRQ10:
+        case SCIS_IRQ11:
+                sci_irq = scis - SCIS_IRQ9 + 9;
+                break;
+        case SCIS_IRQ20:
+        case SCIS_IRQ21:
+        case SCIS_IRQ22:
+        case SCIS_IRQ23:
+                sci_irq = scis - SCIS_IRQ20 + 20;
+                break;
+        default:
+                printf("Invalid SCI route! Defaulting to IRQ9.\n");
+                sci_irq = 9;
+                break;
+        }
+
+        printf("SCI is IRQ%d\n", sci_irq);
+        return sci_irq;
+
+}
+
+unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+	 int sci_irq = acpi_sci_irq();
+        struct acpi_madt_irqoverride *irqovr;
+        uint16_t sci_flags = MP_IRQ_TRIGGER_LEVEL;
+
+        /* INT_SRC_OVR */
+        irqovr = (void *)current;
+        current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
+
+        if (sci_irq >= 20)
+                sci_flags |= MP_IRQ_POLARITY_LOW;
+        else
+                sci_flags |= MP_IRQ_POLARITY_HIGH;
+
+        irqovr = (void *)current;
+        current += acpi_create_madt_irqoverride(irqovr, 0, sci_irq, sci_irq,
+                                                sci_flags);
+
+        return current;
+
+}
+
+void acpi_fill_fadt(struct acpi_fadt *fadt)
+{
+	u16 pm;
+	u16 pmbase;
+
+        pci_dev_t bdf = PCI_BDF(0, 0x1f, 0);
+        pci_read_config_word(bdf, 0x40, &pm);
+
+        pmbase = pm & 0xfffe;
+
+        fadt->model = 1;
+
+        fadt->sci_int = 0x9;
+        fadt->smi_cmd = APM_CNT;
+        fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+        fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+        fadt->s4bios_req = 0x0;
+        fadt->pstate_cnt = 0;
+
+        fadt->pm1a_evt_blk = pmbase;
+        fadt->pm1b_evt_blk = 0x0;
+        fadt->pm1a_cnt_blk = pmbase + 0x4;
+        fadt->pm1b_cnt_blk = 0x0;
+        fadt->pm2_cnt_blk = pmbase + 0x50;
+        fadt->pm_tmr_blk = pmbase + 0x8;
+        fadt->gpe0_blk = pmbase + 0x20;
+        fadt->gpe1_blk = 0;
+
+        fadt->pm1_evt_len = 4;
+        fadt->pm1_cnt_len = 2;
+        fadt->pm2_cnt_len = 1;
+        fadt->pm_tmr_len = 4;
+        fadt->gpe0_blk_len = 16;
+        fadt->gpe1_blk_len = 0;
+        fadt->gpe1_base = 0;
+        fadt->cst_cnt = 0;
+
+        fadt->p_lvl3_lat = 87;
+        fadt->flush_size = 1024;
+        fadt->flush_stride = 16;
+        fadt->duty_offset = 1;
+        fadt->day_alrm = 0xd;
+        fadt->mon_alrm = 0x00;
+        fadt->century = 0x00;
+        fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+
+        fadt->flags = ACPI_FADT_WBINVD |
+                        ACPI_FADT_C1_SUPPORTED |
+                        ACPI_FADT_SLEEP_BUTTON |
+                        ACPI_FADT_RESET_REGISTER |
+                        ACPI_FADT_SEALED_CASE |
+                        ACPI_FADT_S4_RTC_WAKE |
+                        ACPI_FADT_PLATFORM_CLOCK;
+
+        fadt->reset_reg.space_id = 1;
+        fadt->reset_reg.bit_width = 8;
+        fadt->reset_reg.bit_offset = 0;
+        fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+        fadt->reset_reg.addrl = 0xcf9;
+        fadt->reset_reg.addrh = 0;
+
+        fadt->reset_value = 6;
+
+
+        fadt->x_pm1a_evt_blk.space_id = 1;
+        fadt->x_pm1a_evt_blk.bit_width = 32;
+        fadt->x_pm1a_evt_blk.bit_offset = 0;
+        fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+        fadt->x_pm1a_evt_blk.addrl = pmbase;
+        fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+        fadt->x_pm1b_evt_blk.space_id = 1;
+        fadt->x_pm1b_evt_blk.bit_width = 0;
+        fadt->x_pm1b_evt_blk.bit_offset = 0;
+        fadt->x_pm1b_evt_blk.access_size = 0;
+        fadt->x_pm1b_evt_blk.addrl = 0x0;
+        fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+        fadt->x_pm1a_cnt_blk.space_id = 1;
+        fadt->x_pm1a_cnt_blk.bit_width = 16;
+        fadt->x_pm1a_cnt_blk.bit_offset = 0;
+        fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+        fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
+        fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+        fadt->x_pm1b_cnt_blk.space_id = 1;
+        fadt->x_pm1b_cnt_blk.bit_width = 0;
+        fadt->x_pm1b_cnt_blk.bit_offset = 0;
+        fadt->x_pm1b_cnt_blk.access_size = 0;
+        fadt->x_pm1b_cnt_blk.addrl = 0x0;
+        fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+        fadt->x_pm2_cnt_blk.space_id = 1;
+        fadt->x_pm2_cnt_blk.bit_width = 8;
+        fadt->x_pm2_cnt_blk.bit_offset = 0;
+        fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+        fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
+        fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+
+        fadt->x_pm_tmr_blk.space_id = 1;
+        fadt->x_pm_tmr_blk.bit_width = 32;
+        fadt->x_pm_tmr_blk.bit_offset = 0;
+        fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+        fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
+        fadt->x_pm_tmr_blk.addrh = 0x0;
+
+        fadt->x_gpe0_blk.space_id = 1;
+        fadt->x_gpe0_blk.bit_width = 128;
+        fadt->x_gpe0_blk.bit_offset = 0;
+        fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+        fadt->x_gpe0_blk.addrl = pmbase + 0x20;
+        fadt->x_gpe0_blk.addrh = 0x0;
+
+        fadt->x_gpe1_blk.space_id = 1;
+        fadt->x_gpe1_blk.bit_width = 0;
+        fadt->x_gpe1_blk.bit_offset = 0;
+        fadt->x_gpe1_blk.access_size = 0;
+        fadt->x_gpe1_blk.addrl = 0x0;
+        fadt->x_gpe1_blk.addrh = 0x0;
+
+
+}
+
+
+void acpi_create_fadt(struct acpi_fadt * fadt, struct acpi_facs * facs, void *dsdt)
+{
+        acpi_header_t *header = &(fadt->header);
+
+        memset((void *) fadt, 0, sizeof(struct acpi_fadt));
+        memcpy(header->signature, "FACP", 4);
+        header->length = sizeof(struct acpi_fadt);
+        header->revision = 4;
+        memcpy(header->oem_id, OEM_ID, 6);
+        memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+        memcpy(header->asl_compiler_id, ASLC, 4);
+        header->asl_compiler_revision = 0;
+
+        fadt->firmware_ctrl = (unsigned long) facs;
+        fadt->dsdt = (unsigned long) dsdt;
+
+        fadt->x_firmware_ctl_l = (unsigned long)facs;
+        fadt->x_firmware_ctl_h = 0;
+        fadt->x_dsdt_l = (unsigned long)dsdt;
+        fadt->x_dsdt_h = 0;
+
+        if(IS_ENABLED(CONFIG_SYSTEM_TYPE_LAPTOP)) {
+                fadt->preferred_pm_profile = PM_MOBILE;
+        } else {
+                fadt->preferred_pm_profile = PM_DESKTOP;
+        }
+
+        acpi_fill_fadt(fadt);
+
+        header->checksum =
+            table_compute_checksum((void *) fadt, header->length);
+
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+        current = acpi_create_madt_lapics(current);
+
+        /* IOAPIC */
+        current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *) current,
+                                2, IO_APIC_ADDR, 0);
+
+        current = acpi_madt_irq_overrides(current);
+
+        return current;
+
+}
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+        return current;
+}
diff --git a/board/intel/minnowmax/acpi/cpu.asl b/board/intel/minnowmax/acpi/cpu.asl
new file mode 100644
index 0000000..67c34e5
--- /dev/null
+++ b/board/intel/minnowmax/acpi/cpu.asl
@@ -0,0 +1,56 @@
+/* These devices are created at runtime */
+External (\_PR.CP00, DeviceObj)
+External (\_PR.CP01, DeviceObj)
+External (\_PR.CP02, DeviceObj)
+External (\_PR.CP03, DeviceObj)
+
+/* Notify OS to re-read CPU tables, assuming ^2 CPU count */
+Method (PNOT)
+{
+	If (LGreaterEqual (\PCNT, 2)) {
+		Notify (\_PR.CP00, 0x81)  // _CST
+		Notify (\_PR.CP01, 0x81)  // _CST
+	}
+	If (LGreaterEqual (\PCNT, 4)) {
+		Notify (\_PR.CP02, 0x81)  // _CST
+		Notify (\_PR.CP03, 0x81)  // _CST
+	}
+}
+
+/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */
+Method (PPCN)
+{
+	If (LGreaterEqual (\PCNT, 2)) {
+		Notify (\_PR.CP00, 0x80)  // _PPC
+		Notify (\_PR.CP01, 0x80)  // _PPC
+	}
+	If (LGreaterEqual (\PCNT, 4)) {
+		Notify (\_PR.CP02, 0x80)  // _PPC
+		Notify (\_PR.CP03, 0x80)  // _PPC
+	}
+}
+
+/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */
+Method (TNOT)
+{
+	If (LGreaterEqual (\PCNT, 2)) {
+		Notify (\_PR.CP00, 0x82)  // _TPC
+		Notify (\_PR.CP01, 0x82)  // _TPC
+	}
+	If (LGreaterEqual (\PCNT, 4)) {
+		Notify (\_PR.CP02, 0x82)  // _TPC
+		Notify (\_PR.CP03, 0x82)  // _TPC
+	}
+}
+
+/* Return a package containing enabled processor entries */
+Method (PPKG)
+{
+	If (LGreaterEqual (\PCNT, 4)) {
+		Return (Package() {\_PR.CP00, \_PR.CP01, \_PR.CP02, \_PR.CP03})
+	} ElseIf (LGreaterEqual (\PCNT, 2)) {
+		Return (Package() {\_PR.CP00, \_PR.CP01})
+	} Else {
+		Return (Package() {\_PR.CP00})
+	}
+}
diff --git a/board/intel/minnowmax/acpi/device_nvs.asl b/board/intel/minnowmax/acpi/device_nvs.asl
new file mode 100644
index 0000000..4aedb03
--- /dev/null
+++ b/board/intel/minnowmax/acpi/device_nvs.asl
@@ -0,0 +1,66 @@
+/* Device Enabled in ACPI Mode */
+
+S0EN,	8,	// SDMA Enable
+S1EN,	8,	// I2C1 Enable
+S2EN,	8,	// I2C2 Enable
+S3EN,	8,	// I2C3 Enable
+S4EN,	8,	// I2C4 Enable
+S5EN,	8,	// I2C5 Enable
+S6EN,	8,	// I2C6 Enable
+S7EN,	8,	// I2C7 Enable
+S8EN,	8,	// SDMA2 Enable
+S9EN,	8,	// SPI Enable
+SAEN,	8,	// PWM1 Enable
+SBEN,	8,	// PWM2 Enable
+SCEN,	8,	// UART2 Enable
+SDEN,	8,	// UART2 Enable
+C0EN,	8,	// MMC Enable
+C1EN,	8,	// SDIO Enable
+C2EN,	8,	// SD Card Enable
+LPEN,	8,	// LPE Enable
+
+/* BAR 0 */
+
+S0B0,	32,	// SDMA BAR0
+S1B0,	32,	// I2C1 BAR0
+S2B0,	32,	// I2C2 BAR0
+S3B0,	32,	// I2C3 BAR0
+S4B0,	32,	// I2C4 BAR0
+S5B0,	32,	// I2C5 BAR0
+S6B0,	32,	// I2C6 BAR0
+S7B0,	32,	// I2C7 BAR0
+S8B0,	32,	// SDMA2 BAR0
+S9B0,	32,	// SPI BAR0
+SAB0,	32,	// PWM1 BAR0
+SBB0,	32,	// PWM2 BAR0
+SCB0,	32,	// UART1 BAR0
+SDB0,	32,	// UART2 BAR0
+C0B0,	32,	// MMC BAR0
+C1B0,	32,	// SDIO BAR0
+C2B0,	32,	// SD Card BAR0
+LPB0,	32,	// LPE BAR0
+
+/* BAR 1 */
+
+S0B1,	32,	// SDMA BAR1
+S1B1,	32,	// I2C1 BAR1
+S2B1,	32,	// I2C2 BAR1
+S3B1,	32,	// I2C3 BAR1
+S4B1,	32,	// I2C4 BAR1
+S5B1,	32,	// I2C5 BAR1
+S6B1,	32,	// I2C6 BAR1
+S7B1,	32,	// I2C7 BAR1
+S8B1,	32,	// SDMA2 BAR1
+S9B1,	32,	// SPI BAR1
+SAB1,	32,	// PWM1 BAR1
+SBB1,	32,	// PWM2 BAR1
+SCB1,	32,	// UART1 BAR1
+SDB1,	32,	// UART2 BAR1
+C0B1,	32,	// MMC BAR1
+C1B1,	32,	// SDIO BAR1
+C2B1,	32,	// SD Card BAR1
+LPB1,	32,	// LPE BAR1
+
+/* Extra */
+
+LPFW,	32,	// LPE BAR2 Firmware
diff --git a/board/intel/minnowmax/acpi/ec.asl b/board/intel/minnowmax/acpi/ec.asl
new file mode 100644
index 0000000..e69de29
diff --git a/board/intel/minnowmax/acpi/globalnvs.asl b/board/intel/minnowmax/acpi/globalnvs.asl
new file mode 100644
index 0000000..c8d6165
--- /dev/null
+++ b/board/intel/minnowmax/acpi/globalnvs.asl
@@ -0,0 +1,83 @@
+/* Global Variables */
+
+Name(\PICM, 0)		// IOAPIC/8259
+
+/* Global ACPI memory region. This region is used for passing information
+ * between coreboot (aka "the system bios"), ACPI, and the SMI handler.
+ * Since we don't know where this will end up in memory at ACPI compile time,
+ * we have to fix it up in coreboot's ACPI creation phase.
+ */
+
+
+External(NVSA)
+OperationRegion (GNVS, SystemMemory, NVSA, 0x2000)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+	/* Miscellaneous */
+	Offset (0x00),
+	OSYS,	16,	// 0x00 - Operating System
+	SMIF,	 8,	// 0x02 - SMI function
+	PRM0,	 8,	// 0x03 - SMI function parameter
+	PRM1,	 8,	// 0x04 - SMI function parameter
+	SCIF,	 8,	// 0x05 - SCI function
+	PRM2,	 8,	// 0x06 - SCI function parameter
+	PRM3,	 8,	// 0x07 - SCI function parameter
+	LCKF,	 8,	// 0x08 - Global Lock function for EC
+	PRM4,	 8,	// 0x09 - Lock function parameter
+	PRM5,	 8,	// 0x0a - Lock function parameter
+	P80D,	32,	// 0x0b - Debug port (IO 0x80) value
+	LIDS,	 8,	// 0x0f - LID state (open = 1)
+	PWRS,	 8,	// 0x10 - Power State (AC = 1)
+	PCNT,	 8,	// 0x11 - Processor count
+	TPMP,	 8,	// 0x12 - TPM Present and Enabled
+	TLVL,	 8,	// 0x13 - Throttle Level
+	PPCM,	 8,	// 0x14 - Maximum P-state usable by OS
+
+	/* Device Config */
+	Offset (0x20),
+	S5U0,	 8,	// 0x20 - Enable USB0 in S5
+	S5U1,	 8,	// 0x21 - Enable USB1 in S5
+	S3U0,	 8,	// 0x22 - Enable USB0 in S3
+	S3U1,	 8,	// 0x23 - Enable USB1 in S3
+	TACT,	 8,	// 0x24 - Thermal Active trip point
+	TPSV,	 8,	// 0x25 - Thermal Passive trip point
+	TCRT,	 8,	// 0x26 - Thermal Critical trip point
+	DPTE,	 8,	// 0x27 - Enable DPTF
+
+	/* Base addresses */
+	Offset (0x30),
+	CMEM,	 32,	// 0x30 - CBMEM TOC
+	TOLM,	 32,	// 0x34 - Top of Low Memory
+	CBMC,	 32,	// 0x38 - coreboot mem console pointer
+
+	Offset (0x1000),
+	#include "device_nvs.asl"
+}
+
+/* Set flag to enable USB charging in S3 */
+Method (S3UE)
+{
+	Store (One, \S3U0)
+	Store (One, \S3U1)
+}
+
+/* Set flag to disable USB charging in S3 */
+Method (S3UD)
+{
+	Store (Zero, \S3U0)
+	Store (Zero, \S3U1)
+}
+
+/* Set flag to enable USB charging in S5 */
+Method (S5UE)
+{
+	Store (One, \S5U0)
+	Store (One, \S5U1)
+}
+
+/* Set flag to disable USB charging in S5 */
+Method (S5UD)
+{
+	Store (Zero, \S5U0)
+	Store (Zero, \S5U1)
+}
diff --git a/board/intel/minnowmax/acpi/mainboard.asl b/board/intel/minnowmax/acpi/mainboard.asl
new file mode 100644
index 0000000..711d054
--- /dev/null
+++ b/board/intel/minnowmax/acpi/mainboard.asl
@@ -0,0 +1,4 @@
+Device (PWRB)
+{
+	Name(_HID, EisaId("PNP0C0C"))
+}
diff --git a/board/intel/minnowmax/acpi/platform.asl b/board/intel/minnowmax/acpi/platform.asl
new file mode 100644
index 0000000..9ad887c
--- /dev/null
+++ b/board/intel/minnowmax/acpi/platform.asl
@@ -0,0 +1,52 @@
+/* The APM port can be used for generating software SMIs */
+
+OperationRegion (APMP, SystemIO, 0xb2, 2)
+Field (APMP, ByteAcc, NoLock, Preserve)
+{
+	APMC, 8,	// APM command
+	APMS, 8		// APM status
+}
+
+/* Port 80 POST */
+
+OperationRegion (POST, SystemIO, 0x80, 1)
+Field (POST, ByteAcc, Lock, Preserve)
+{
+	DBG0, 8
+}
+
+/* SMI I/O Trap */
+Method(TRAP, 1, Serialized)
+{
+	Store (Arg0, SMIF)	// SMI Function
+	Store (0, TRP0)		// Generate trap
+	Return (SMIF)		// Return value of SMI handler
+}
+
+/* The _PIC method is called by the OS to choose between interrupt
+ * routing via the i8259 interrupt controller or the APIC.
+ *
+ * _PIC is called with a parameter of 0 for i8259 configuration and
+ * with a parameter of 1 for Local Apic/IOAPIC configuration.
+ */
+
+Method(_PIC, 1)
+{
+	// Remember the OS' IRQ routing choice.
+	Store(Arg0, PICM)
+}
+
+/* The _PTS method (Prepare To Sleep) is called before the OS is
+ * entering a sleep state. The sleep state number is passed in Arg0
+ */
+
+Method(_PTS,1)
+{
+}
+
+/* The _WAK method is called on system wakeup */
+
+Method(_WAK,1)
+{
+	Return(Package(){0,0})
+}
diff --git a/board/intel/minnowmax/acpi/sleepstates.asl b/board/intel/minnowmax/acpi/sleepstates.asl
new file mode 100644
index 0000000..92619df
--- /dev/null
+++ b/board/intel/minnowmax/acpi/sleepstates.asl
@@ -0,0 +1,5 @@
+Name(\_S0, Package(){0x0,0x0,0x0,0x0})
+// Name(\_S1, Package(){0x1,0x1,0x0,0x0})
+Name(\_S3, Package(){0x5,0x5,0x0,0x0})
+Name(\_S4, Package(){0x6,0x6,0x0,0x0})
+Name(\_S5, Package(){0x7,0x7,0x0,0x0})
diff --git a/board/intel/minnowmax/acpi/superio.asl b/board/intel/minnowmax/acpi/superio.asl
new file mode 100644
index 0000000..e69de29
diff --git a/board/intel/minnowmax/dsdt.asl b/board/intel/minnowmax/dsdt.asl
new file mode 100644
index 0000000..187d68c
--- /dev/null
+++ b/board/intel/minnowmax/dsdt.asl
@@ -0,0 +1,29 @@
+#define INCLUDE_LPE  1
+#define INCLUDE_SCC  1
+#define INCLUDE_EHCI 1
+#define INCLUDE_XHCI 1
+#define INCLUDE_LPSS 1
+
+
+DefinitionBlock(
+	"dsdt.aml",
+	"DSDT",
+	0x02,		// DSDT revision: ACPI v2.0
+	"COREv4",	// OEM id
+	"UBOOT",	// OEM table id
+	0x20110725	// OEM revision
+)
+{
+	// Some generic macros
+	#include "acpi/platform.asl"
+
+	// global NVS and variables
+	#include "acpi/globalnvs.asl"
+
+	#include "acpi/cpu.asl"
+
+	/* Chipset specific sleep states */
+	#include "acpi/sleepstates.asl"
+
+	#include "acpi/mainboard.asl"
+}
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 8731fc6..b642930 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -297,6 +297,17 @@ _dtbinst_pre_:
 %.dtb_dtbinst_: $(obj)/%.dtb _dtbinst_pre_
 	$(call cmd,dtb_install,$(INSTALL_DTBS_PATH))
 
+# ACPI
+# ---------------------------------------------------------------------------
+quiet_cmd_acpi_c_asl= ASL     $@
+cmd_acpi_c_asl=	 \
+	$(CPP) -x assembler-with-cpp -P -o $<.tmp $<; \
+	iasl -tc -p $< -tc $<.tmp; \
+	mv $(patsubst %.asl,%.hex,$<) $@
+
+$(obj)/%.c:	$(src)/%.asl
+	$(call cmd,acpi_c_asl)
+
 # Bzip2
 # ---------------------------------------------------------------------------
 
-- 
2.1.4



More information about the U-Boot mailing list