This page contains some (developer) documentation about how ACPI can be used in coreboot.

+

= ACPI setup HOWTO =

= ACPI setup HOWTO =

−

Please have a look to files in the src/mainboard/asus/a8v-e_se. Check also the [ http://acpi.info ]

+

Please have a look to files in the [http://tracker.coreboot.org/trac/coreboot/browser/trunk/coreboot-v2/src/mainboard/asus/a8v-e_se src/mainboard/asus/a8v-e_se]. Please also checkout http://acpi.info, which contains the ACPI specification.

−

which contains the specification.

+

== Setup hardware ==

== Setup hardware ==

−

Setup the PMIO base address to some known address, and setup the desired ACPI IRQ (usually IRQ9).

+

Setup the '''PMIO base address''' to some known address, and setup the desired ACPI IRQ (usually IRQ9). Sometimes it is called SCI interrupt.

−

Sometimes it is called SCI interrupt.

+

== Fill FADT ==

== Fill FADT ==

−

Now you will need to create an ACPI table which describes the I/O port location for kernel ACPI implementation. This is the FACP table. You will need to create the fadt.c file and fill in

+

Now you will need to create an ACPI table which describes the I/O port location for kernel ACPI implementation. This is the '''FACP''' table. You will need to create the '''fadt.c''' file and fill in the I/O port values plus IRQ:

−

the IO port values plus IRQ:

+

<pre>

<pre>

Line 26:

Line 25:

</pre>

</pre>

−

In this example the ACPI IRQ is 9, and the PM1A event block start at VT8237R_ACPI_IO_BASE. You

+

In this example the ACPI IRQ is 9, and the '''PM1A event block''' starts at VT8237R_ACPI_IO_BASE. You may obtain some values from '''cat /proc/ioport''' if running with proprietary BIOS. Not all blocks are necessary usually only PM1A PMTMR and GPE0 are used. Please note that this table has the I/O port information stored twice using different formats. Please consult the ACPI specification for details, mostly could be used what are the defaults in the '''fadt.c'''.

−

may obtain some values from cat /proc/ioport if running with proprietary BIOS. Not all blocks

+

−

are necessary usually only PM1A PMTMR and GPE0 are used. Please note that this table has the IO port

+

−

information stored twice using different formats. Please consult the ACPI specification for details,

+

−

mostly could be used what are the defaults in the fadt.c

+

== Fill DSDT ==

== Fill DSDT ==

−

The DSDT table contains a bytecode that is executed by driver in the kernel. This table stores also

+

The '''DSDT table''' contains a bytecode that is executed by a driver in the kernel. This table stores also '''ACPI routing information''' in '''_PRT''' methods. You may add those _PRT methods later.

−

ACPI routing information in _PRT methods. You may add those _PRT methods later.

+

==== Generic part of DSDT ====

==== Generic part of DSDT ====

−

Very generic DSDT table would look like in similar way how it is ASUS A8V-E/ASUS M2V-MX SE (dsdt.asl).

+

A very generic DSDT table would look similar to the ASUS A8V-E/ASUS M2V-MX SE [http://tracker.coreboot.org/trac/coreboot/browser/trunk/coreboot-v2/src/mainboard/asus/a8v-e_se src/mainboard/asus/a8v-e_se/dsdt.asl dsdt.asl] file.

<pre>

<pre>

Line 50:

Line 44:

This is here for compatibility. More interesting is:

This is here for compatibility. More interesting is:

−

<pre>

+

<pre>

/* For now only define 2 power states:

/* For now only define 2 power states:

* - S0 which is fully on

* - S0 which is fully on

Line 61:

Line 55:

</pre>

</pre>

−

This defines the SLP_TYP fields in PM1A register. In my case I need to store 010 to perform soft off.

+

This defines the SLP_TYP fields in PM1A register. In my case I need to store 010 to perform soft off, and 000 to wakeup. Modify it to fit your chipset needs.

It means 0:0f.1 INTA is routed to IRQ20. Linux likes it. Windows does not (code 12). The ACPI standard requires that function is always 0xffff.

−

Please note that the 0x10, 0x11 are called GSI (global system interrupt). All your interrupts routed through first APIC will start with 0x00, second APIC will perhaps start at IRQ24 etc etc...

+

Please note that the 0x10, 0x11 are called '''GSI (global system interrupt)'''. All your interrupts routed through first APIC will start with 0x00, second APIC will perhaps start at IRQ24 etc. This example has no support for legacy PIC routing. For PIC routing you would need to alter the rest of the fields in the _PRT package and also crete PIRQA-PIRQD special devices.

−

This example has no support for legacy PIC routing. For PIC routing you would need to alter rest of the fields in the _PRT package and also crete PIRQA-PIRQD special devices.

+

−

The described above uses static IRQ assignments. Some chipsets like MPC55/CK804 have a configuration register

+

The described above uses static IRQ assignments. Some chipsets like MPC55/CK804 have a configuration register which indicates what APIC pins are routed to what interrupt. Those typically use dynamic IRQ routing which provides a '''_CRS''' and '''_SRS''' methods to set such registers. For now, those registers are filled in MP-Table setup of each MCP55/CK804 board. All you need is to have static wiring like the MP-Table has.

−

which indicates what APIC pin are routed to what interrupt. Those typically use dynamic IRQ routing which provides

+

−

a _CRS and _SRS methods to set such registers. For now, those registers are filled in MP-Table setup of each MCP55/CK804 board. All you need is to have static wiring like the MP-Table has.

+

−

Rest of the file contains just some legacy devices to make certain OS installers happy.

+

The rest of the file contains just some legacy devices to make certain OS installers happy. Don't forget to install the '''iasl''' compiler and also adjust the coreboot buildsystem to build the binary DSDT for you.

−

Don't forget to install iasl compiler and also adjust the coreboot buildsystem to build binary DSDT

+

−

for you.

+

=== CPU Power Management ===

=== CPU Power Management ===

−

The CPU power management is hardware specific. It is described in APCI specs and also in AMD BIOS and Kernel Developer guide. The rest of this section describes the AMD specific part. AMD needs ACPI objects which describes the similar info as the legacy PowerNow table. Check the BKDG for details.

+

The CPU power management is hardware specific. It is described in APCI specs and also in AMD BIOS and Kernel Developer guide. The rest of this section describes the AMD specific part. AMD needs ACPI objects which describe the similar info as the legacy PowerNow table. Check the BKDG for details.

−

The content of the tables must be generated runtime, which is a bit problem, because the AML code must be generated or DSDT patched. There is an acpigen infrastructure to generate the AML code.

+

The content of the tables must be generated at runtime, which is a bit of a problem, because the AML code must be generated or DSDT patched. There is an '''acpigen''' infrastructure to generate the AML code.

−

The actual content for family 0fh revF and later P-States can be generated by complex algorithm implemented in amd_model_fxx_generate_powernow(). This function should be called in acpi_fill_ssdt_generator() callback.

+

The actual content for family 0fh revF and later P-States can be generated by complex algorithm implemented in amd_model_fxx_generate_powernow(). This function should be called in acpi_fill_ssdt_generator() callback. Up to revE, all P state info must be hardcoded in tables (not supported).

−

Up to revE, all P state info must be hardcoded in tables (not supported).

+

=== C States ===

=== C States ===

+

C states are processor power states. C1 is mandantory and reached on IA32 compatible processors using the HLT instruction, C2 and C3 are optional and must be configured.

C states are processor power states. C1 is mandantory and reached on IA32 compatible processors using the HLT instruction, C2 and C3 are optional and must be configured.

−

C States can be configured in ACPI using two methods:

+

C states can be configured in ACPI using two methods:

# by defining the P_BLK base address in the Processor() Definition, and P_LVLx_LAT values in the FADT

# by defining the P_BLK base address in the Processor() Definition, and P_LVLx_LAT values in the FADT

−

# using the _CST Object

+

# using the _CST object

P_BLK is easier to configure, if the hardware supports that method. ACPI defines that there must be two registers at P_BLK+4 and P_BLK+5 that initiate a transition to C2 or C3 when the register is read. After sleep, the read returns 0. P_LVLx_LAT define the worst case latency of the state transition.

P_BLK is easier to configure, if the hardware supports that method. ACPI defines that there must be two registers at P_BLK+4 and P_BLK+5 that initiate a transition to C2 or C3 when the register is read. After sleep, the read returns 0. P_LVLx_LAT define the worst case latency of the state transition.

−

_CST is necessary if you want to support more than 3 C states, or if the transition procedure doesn't follow the ACPI requirement

+

_CST is necessary if you want to support more than 3 C states, or if the transition procedure doesn't follow the ACPI requirement.

=== PCI root bus _CRS method ===

=== PCI root bus _CRS method ===

−

The Windows needs to know the actual decode ranges for PCI root bus (and any other). Windows needs to know platform independent way, how is I/O routed on PCI0 bus (and other busses). For K8 it means to read the I/O and MMIO routing registers (same as k8resdump provides) and make it ACPI object. This was perhaps done previously on Aruma board. The actual PCI regs are read in acpi-k8 in modelf and stored as SSDT table. The k8-util.asl code will construct the resources from that SSDT table.

+

Windows needs to know the actual decode ranges for PCI root bus (and any other). Windows needs to know platform independent way, how is I/O routed on PCI0 bus (and other busses). For K8 it means to read the I/O and MMIO routing registers (same as '''k8resdump''' provides) and make it ACPI object. This was perhaps done previously on Aruma board. The actual PCI regs are read in acpi-k8 in modelf and stored as SSDT table. The k8-util.asl code will construct the resources from that SSDT table.

One can use the k8-util.asl code which will construct the resource objects. Check the ASUS M2V-MX mainboard ACPI code.

One can use the k8-util.asl code which will construct the resource objects. Check the ASUS M2V-MX mainboard ACPI code.

Line 129:

Line 119:

=== DSDT debugging ===

=== DSDT debugging ===

−

There are two ways. You can store values in "debug" object, which will print it in dmesg.

+

There are two ways. You can store values in "debug" object, which will print it in dmesg. Check http://www.linuxhq.com/kernel/v2.6/28-rc6/Documentation/acpi/debug.txt how to turn that on. In DSDT use store method to write to Debug object. You can write buffers, ints etc:

−

Check http://www.linuxhq.com/kernel/v2.6/28-rc6/Documentation/acpi/debug.txt how to turn that on. In DSDT use

+

−

store method to write to Debug object. You can write buffers, ints etc:

+

* Store ("The answer to the question of live universe and everything is:", Debug)

* Store ("The answer to the question of live universe and everything is:", Debug)

* Store (42, Debug)

* Store (42, Debug)

−

Second method is userspace interpretation of dsdt table. This can be achieved with APCI CA unix package.

+

Second method is userspace interpretation of DSDT table. This can be achieved with APCI CA Unix package. It is located in '''acpica-unix-20081204/tools/acpiexec'''. You can eval the objects and run the methods, like _CRS for example.

−

It is located in acpica-unix-20081204/tools/acpiexec. You can eval the objects and run the methods, like _CRS

+

−

for example.

+

−

If you receive BSOD with STOP code 0xa5 check this:

+

If you receive a BSOD with '''STOP code 0xa5''', check this: http://support.microsoft.com/kb/314830.

This table describes the ACPI IRQ information, as well as IRQ override. For code example check the M2V-MX SE acpi_tables. You will need to create the sub-table for LAPIC (the APIC counterpart in CPU) and describe the APICs

+

[[Image:ApicSystem.svg|thumb|right|A system with 8259s and APICs]]

−

and also deal with so called IRQ overrides.

+

−

Let’s look at the figure below which explains how the interrupts are routed:[[Image:ApicSystem.svg|thumb|left|A system with 8259s and APICs]]

+

This table describes the ACPI IRQ information, as well as IRQ override. For code example check the M2V-MX SE acpi_tables. You will need to create the sub-table for LAPIC (the APIC counterpart in CPU) and describe the APICs and also deal with so called IRQ overrides.

+

+

Let’s look at the figure below which explains how the interrupts are routed.

The interrupt sources are on the right side. The legacy IRQs and the PCI IRQs are connected to both APIC and 8259.

The interrupt sources are on the right side. The legacy IRQs and the PCI IRQs are connected to both APIC and 8259.

Line 168:

Line 153:

Last thing in this table are IRQ overrides. Usually there are two IRQ overrides. IRQ0 override means that IRQ0 is not connected to pin 0 on APIC but to another, most likely pin 2. Check the figure above why. Second IRQ override is for ACPI IRQ. This overrides the 'level' of the interrupt to 'active low'. The rest of the table is filled with NMI entries for the processor.

Last thing in this table are IRQ overrides. Usually there are two IRQ overrides. IRQ0 override means that IRQ0 is not connected to pin 0 on APIC but to another, most likely pin 2. Check the figure above why. Second IRQ override is for ACPI IRQ. This overrides the 'level' of the interrupt to 'active low'. The rest of the table is filled with NMI entries for the processor.

+

+

<br clear="all" />

=== write_acpi_tables ===

=== write_acpi_tables ===

−

This is the main function which constructs the tables. Functions described above are callbacks from the

+

This is the main function which constructs the tables. Functions described above are callbacks from the "construct" functions called here. You may omit the HPET and MCFG tables.

−

"construct" functions called here. You may ommit the HPET and MCFG tables.

+

=== FACS table ===

=== FACS table ===

−

This table must be aligned to 64B boundary (Windows check this).

+

+

This table must be aligned to 64B boundary (Windows checks this).

= Suspend to RAM =

= Suspend to RAM =

−

There are patches on ML which add support for suspend to RAM in coreboot. The resume start of the computer does not differ until OS waking vector is executed instead of payload.

+

There are patches on the mailing list which add support for suspend to RAM in coreboot. The resume start of the computer does not differ until OS waking vector is executed instead of payload.

Checklist of things which needs to be setup correctly:

Checklist of things which needs to be setup correctly:

* Supend clocks, SUSA/B/C plane pins

* Supend clocks, SUSA/B/C plane pins

−

* Often the SuperIO has some pin to toggle the power for RAM

+

* Often the Super I/O has some pin to toggle the power for RAM

* SLP_TYPE with S3 definition to your DSDT

* SLP_TYPE with S3 definition to your DSDT

−

* support for exit-self-refresh in your RAM controller

+

* Support for exit-self-refresh in your RAM controller

−

* an NVRAM which store the memory configuration, which is known runtime (DQS)

+

* An NVRAM which stores the memory configuration, which is known runtime (DQS)

* Chipset tweaks for S3 (like various signal delays)

* Chipset tweaks for S3 (like various signal delays)

* CPU tweaks (for AMD the PM1 and PM2 registers and SMAF codes)

* CPU tweaks (for AMD the PM1 and PM2 registers and SMAF codes)

* _RAMBASE of coreboot setup to 31MB and set LB_MEM_TOPK to 32MB

* _RAMBASE of coreboot setup to 31MB and set LB_MEM_TOPK to 32MB

−

* make sure new code does not corrupt any memory

+

* Make sure new code does not corrupt any memory

−

* make sure that you reserve _RAMBASE - LB_MEM_TOPK

+

* Make sure that you reserve _RAMBASE - LB_MEM_TOPK

* SMP might need some fixes

* SMP might need some fixes

= ACPI bytecode generator =

= ACPI bytecode generator =

−

Some ACPI stuff is generated runtime. To achieve this goal we have a AML code generator which generates binary

+

Some ACPI stuff is generated runtime. To achieve this goal we have a AML code generator which generates binary ACPI bytecode. Such code then resides typically in SSDT table. There is a helper function which creates such a table - acpi_create_ssdt_generator(). The content of the table is created through the callback function acpi_fill_ssdt_generator(). So far we have two big users of the generator k8acpi_write_vars() and amd_model_fxx_generate_powernow(). The first function will generate some runtime configuration of HT bus and PCI decode ranges. Second function generates the P-States.

−

ACPI bytecode. Such code then resides typically in SSDT table. There is a helper function which creates such

+

−

table - acpi_create_ssdt_generator(). The content of the table is created through callback function acpi_fill_ssdt_generator(). So far we have two big users of the generator k8acpi_write_vars() and amd_model_fxx_generate_powernow(). The first function will generate some runtime configuration of HT bus and PCI decode ranges. Second function generates the P-States.

+

−

The available functions are in acpigen.h. Mostly there are functions generating some primitive named data structures. However sometime is necessary to put more data to a package. ACPI AML code needs to know the block

+

The available functions are in acpigen.h. Mostly there are functions generating some primitive named data structures. However sometimes it's necessary to put more data to a package. ACPI AML code needs to know the block lengths. The len is unknown until we have filled the payload of such package. Therefore when we are done, we need

−

lengths. The len is unknown until we have filled the payload of such package. Therefore when we are done, we need

+

to call function acpigen_patch_len(int len) which will patch last object (package) which need patching. It uses stack internally so more structures can be nested. Look to acpigen.c and learn what functions call acpigen_write_len_f() - those needs patching.

−

to call function acpigen_patch_len(int len) which will patch last object (package) which need patching. It uses

+

−

stack internally so more structures can be nested. Look to acpigen.c and learn what functions call acpigen_write_len_f() - those needs patching.

ACPI setup HOWTO

Setup hardware

Setup the PMIO base address to some known address, and setup the desired ACPI IRQ (usually IRQ9). Sometimes it is called SCI interrupt.

Fill FADT

Now you will need to create an ACPI table which describes the I/O port location for kernel ACPI implementation. This is the FACP table. You will need to create the fadt.c file and fill in the I/O port values plus IRQ:

In this example the ACPI IRQ is 9, and the PM1A event block starts at VT8237R_ACPI_IO_BASE. You may obtain some values from cat /proc/ioport if running with proprietary BIOS. Not all blocks are necessary usually only PM1A PMTMR and GPE0 are used. Please note that this table has the I/O port information stored twice using different formats. Please consult the ACPI specification for details, mostly could be used what are the defaults in the fadt.c.

Fill DSDT

The DSDT table contains a bytecode that is executed by a driver in the kernel. This table stores also ACPI routing information in _PRT methods. You may add those _PRT methods later.

It means 0:0f.1 INTA is routed to IRQ20. Linux likes it. Windows does not (code 12). The ACPI standard requires that function is always 0xffff.

Please note that the 0x10, 0x11 are called GSI (global system interrupt). All your interrupts routed through first APIC will start with 0x00, second APIC will perhaps start at IRQ24 etc. This example has no support for legacy PIC routing. For PIC routing you would need to alter the rest of the fields in the _PRT package and also crete PIRQA-PIRQD special devices.

The described above uses static IRQ assignments. Some chipsets like MPC55/CK804 have a configuration register which indicates what APIC pins are routed to what interrupt. Those typically use dynamic IRQ routing which provides a _CRS and _SRS methods to set such registers. For now, those registers are filled in MP-Table setup of each MCP55/CK804 board. All you need is to have static wiring like the MP-Table has.

The rest of the file contains just some legacy devices to make certain OS installers happy. Don't forget to install the iasl compiler and also adjust the coreboot buildsystem to build the binary DSDT for you.

CPU Power Management

The CPU power management is hardware specific. It is described in APCI specs and also in AMD BIOS and Kernel Developer guide. The rest of this section describes the AMD specific part. AMD needs ACPI objects which describe the similar info as the legacy PowerNow table. Check the BKDG for details.

The content of the tables must be generated at runtime, which is a bit of a problem, because the AML code must be generated or DSDT patched. There is an acpigen infrastructure to generate the AML code.

The actual content for family 0fh revF and later P-States can be generated by complex algorithm implemented in amd_model_fxx_generate_powernow(). This function should be called in acpi_fill_ssdt_generator() callback. Up to revE, all P state info must be hardcoded in tables (not supported).

C States

C states are processor power states. C1 is mandantory and reached on IA32 compatible processors using the HLT instruction, C2 and C3 are optional and must be configured.

C states can be configured in ACPI using two methods:

by defining the P_BLK base address in the Processor() Definition, and P_LVLx_LAT values in the FADT

using the _CST object

P_BLK is easier to configure, if the hardware supports that method. ACPI defines that there must be two registers at P_BLK+4 and P_BLK+5 that initiate a transition to C2 or C3 when the register is read. After sleep, the read returns 0. P_LVLx_LAT define the worst case latency of the state transition.

_CST is necessary if you want to support more than 3 C states, or if the transition procedure doesn't follow the ACPI requirement.

PCI root bus _CRS method

Windows needs to know the actual decode ranges for PCI root bus (and any other). Windows needs to know platform independent way, how is I/O routed on PCI0 bus (and other busses). For K8 it means to read the I/O and MMIO routing registers (same as k8resdump provides) and make it ACPI object. This was perhaps done previously on Aruma board. The actual PCI regs are read in acpi-k8 in modelf and stored as SSDT table. The k8-util.asl code will construct the resources from that SSDT table.

One can use the k8-util.asl code which will construct the resource objects. Check the ASUS M2V-MX mainboard ACPI code.

Second method is userspace interpretation of DSDT table. This can be achieved with APCI CA Unix package. It is located in acpica-unix-20081204/tools/acpiexec. You can eval the objects and run the methods, like _CRS for example.

acpi_fill_mcfg

acpi_fill_madt

A system with 8259s and APICs

This table describes the ACPI IRQ information, as well as IRQ override. For code example check the M2V-MX SE acpi_tables. You will need to create the sub-table for LAPIC (the APIC counterpart in CPU) and describe the APICs and also deal with so called IRQ overrides.

Let’s look at the figure below which explains how the interrupts are routed.

The interrupt sources are on the right side. The legacy IRQs and the PCI IRQs are connected to both APIC and 8259.

In the legacy case, the APIC is programmed in virtual wire mode. It will just interconnect pin0 of APIC with its output, bypassing APIC completely. OS uses 8259s, and ignores APICs at all.

The APIC should be in this mode in BIOS, to do that for your SB, check the setup_ioapic in vt8237r_lpc.c. Please note that there is some bit which also says if APIC is delivering through wires, or through FSB messages.

But back to the table. You need to provide some kind of description of the APICs. Each APIC is identified with its own ID and with the offset where its IRQ starts. It is called GSI base – Global System Interrupt base. This is just the value which is used in the _PRT entries as offset for IRQ nr. Typically the first SB APIC has offset 0, second APIC starts where the first has finished, so at IRQ 24 if the first has 24 interrupt sources.

Last thing in this table are IRQ overrides. Usually there are two IRQ overrides. IRQ0 override means that IRQ0 is not connected to pin 0 on APIC but to another, most likely pin 2. Check the figure above why. Second IRQ override is for ACPI IRQ. This overrides the 'level' of the interrupt to 'active low'. The rest of the table is filled with NMI entries for the processor.

write_acpi_tables

This is the main function which constructs the tables. Functions described above are callbacks from the "construct" functions called here. You may omit the HPET and MCFG tables.

FACS table

This table must be aligned to 64B boundary (Windows checks this).

Suspend to RAM

There are patches on the mailing list which add support for suspend to RAM in coreboot. The resume start of the computer does not differ until OS waking vector is executed instead of payload.

Checklist of things which needs to be setup correctly:

Supend clocks, SUSA/B/C plane pins

Often the Super I/O has some pin to toggle the power for RAM

SLP_TYPE with S3 definition to your DSDT

Support for exit-self-refresh in your RAM controller

An NVRAM which stores the memory configuration, which is known runtime (DQS)

Chipset tweaks for S3 (like various signal delays)

CPU tweaks (for AMD the PM1 and PM2 registers and SMAF codes)

_RAMBASE of coreboot setup to 31MB and set LB_MEM_TOPK to 32MB

Make sure new code does not corrupt any memory

Make sure that you reserve _RAMBASE - LB_MEM_TOPK

SMP might need some fixes

ACPI bytecode generator

Some ACPI stuff is generated runtime. To achieve this goal we have a AML code generator which generates binary ACPI bytecode. Such code then resides typically in SSDT table. There is a helper function which creates such a table - acpi_create_ssdt_generator(). The content of the table is created through the callback function acpi_fill_ssdt_generator(). So far we have two big users of the generator k8acpi_write_vars() and amd_model_fxx_generate_powernow(). The first function will generate some runtime configuration of HT bus and PCI decode ranges. Second function generates the P-States.

The available functions are in acpigen.h. Mostly there are functions generating some primitive named data structures. However sometimes it's necessary to put more data to a package. ACPI AML code needs to know the block lengths. The len is unknown until we have filled the payload of such package. Therefore when we are done, we need
to call function acpigen_patch_len(int len) which will patch last object (package) which need patching. It uses stack internally so more structures can be nested. Look to acpigen.c and learn what functions call acpigen_write_len_f() - those needs patching.

Debugging ACPI

When CONFIG_ACPI_DEBUG is compiled into the kernel, the ACPI debug level can be specified on the kernel command line: