ACPI: Difference between revisions

From coreboot
Jump to navigation Jump to search
m (microsoft 0xa5 stop info)
(More APIC info)
Line 145: Line 145:
==== acpi_fill_madt ====
==== acpi_fill_madt ====


This describes the ACPI IRQ information, as well as IRQ override. The gsi_base used in the code
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
is base for second APIC. Provide APIC bases and IDs. 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. 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.
and also deal with so called IRQ overrides.
 
Lets look at the figure bellow which explains how the interrupt are routed:[[Image:ApicSystem.svg|thumb|left|A system with 8259s and APICs]]
 
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 the 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 ====
==== write_acpi_tables ====

Revision as of 22:14, 13 February 2009

ACPI setup HOWTO

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

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 IO port values plus IRQ:

fadt->sci_int = 9;
fadt->pm1a_evt_blk = VT8237R_ACPI_IO_BASE;
fadt->pm1b_evt_blk = 0x0;
fadt->pm1a_cnt_blk = VT8237R_ACPI_IO_BASE + 0x4;
fadt->pm1b_cnt_blk = 0x0;
fadt->pm2_cnt_blk = 0x0;
fadt->pm_tmr_blk = VT8237R_ACPI_IO_BASE + 0x8;
fadt->gpe0_blk = VT8237R_ACPI_IO_BASE + 0x20;
fadt->gpe1_blk = 0x0;

In this example the ACPI IRQ is 9, and the PM1A event block start 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 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

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

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).

        Scope (\_PR)
        {
                Processor (\_PR.CPU0, 0x00, 0x000000, 0x00) {}
                Processor (\_PR.CPU1, 0x01, 0x000000, 0x00) {}
        }

This is here for compatibility. More interesting is:


        /* For now only define 2 power states:
         *  - S0 which is fully on
         *  - S5 which is soft off
         * any others would involve declaring the wake up methods
         */
        Name (\_S0, Package () {0x00, 0x00, 0x00, 0x00 })
        Name (\_S5, Package () {0x02, 0x02, 0x00, 0x00 })

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.

Interrupt routing in DSDT

The _PRT methods define the routing, similar to PIR and MP Table.

     Package (0x04) { 0x000BFFFF, 0x00, 0x00, 0x10 }, //slot 0xB
     Package (0x04) { 0x000BFFFF, 0x01, 0x00, 0x11 },
     Package (0x04) { 0x000BFFFF, 0x02, 0x00, 0x12 },
     Package (0x04) { 0x000BFFFF, 0x03, 0x00, 0x13 },

This defines the slot 0xB (all functions FFFF) routing as follows :

INTA -> IRQ16
INTB -> IRQ17
INTC -> IRQ18
INTD -> IRQ19

Note: you cannot indicate the special functions like:

Package (0x04) { 0x000F0001, 0x00, 0x00, 0x14 }, //0xf NAtive IDE IRQ 20

It means 0:0f.1 INTA is routed to IRQ20. Linux likes it. Windows not (code 12). 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... 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.

Rest of the file contains just some legacy devices to make certain OS instatallers happy. Don't forget to install iasl compiler and also adjust the coreboot buildsystem to build 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 describes 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 DSDT table must be patched runtime during the POST. The only board which is doing is this is the AMD/Pistachio/DBM690T.

The actual content for family 0fh revF and later can be generated by complex algorithm implemented in the acpi files of DBM690T. Up to revE, all P state info must be hardcoded in tables.

Proposed change: The generic post revE algorithm must be moved to the amd-acpi.c as well we can put this info to SSDT table instead, which can be generated runtime. The AML bytecode generator as well as a P state table generator were submitted to mailing list.

For now, you must include your Pstate info yourself using the generator and including that file in DSDT code.

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.

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

DSDT debugging

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:

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

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.

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

Other tables

Rest of the ACPI tables is located at acpi_tables.c. I will describe briefly all methods:

acpi_fill_mcfg

If your platform supports MMCONFIG (memory mapped PCI configuration registers) just modify the function with correct base address.

acpi_fill_madt

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.

Lets look at the figure bellow which explains how the interrupt are routed:

A system with 8259s and APICs

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 the 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 ommit the HPET and MCFG tables.

FACS table

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

More to Read

Some good FAQ: http://www.acpi.info/acpi_faq.htm