Furquan Shaikh has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
cpu: Add a helper function cpu_get_lapic_addr
This change adds a helper function cpu_get_lapic_addr() that returns LOCAL_APIC_ADDR for x86 whereas 0 for non-x86 platforms. This is being done in preparation to move all ACPI table support in coreboot out of arch/x86.
BUG=b:155428745
Change-Id: I4d9c50ee46804164712aaa22be1b434f800871ec Signed-off-by: Furquan Shaikh furquan@google.com --- M src/arch/x86/acpi.c M src/arch/x86/cpu.c A src/include/acpi/acpi.h A src/include/acpi/acpi_device.h A src/include/acpi/acpi_ivrs.h A src/include/acpi/acpi_pld.h A src/include/acpi/acpigen.h A src/include/acpi/acpigen_dsm.h A src/include/acpi/acpigen_ps2_keybd.h M src/include/cpu/cpu.h 10 files changed, 2,387 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/40929/1
diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index 5c15a5e..a2175f5 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -16,9 +16,9 @@
#include <console/console.h> #include <string.h> -#include <arch/acpi.h> -#include <arch/acpi_ivrs.h> -#include <arch/acpigen.h> +#include <acpi/acpi.h> +#include <acpi/acpi_ivrs.h> +#include <acpi/acpigen.h> #include <device/pci.h> #include <cbmem.h> #include <commonlib/helpers.h> @@ -242,7 +242,7 @@ header->length = sizeof(acpi_madt_t); header->revision = get_acpi_table_revision(MADT);
- madt->lapic_addr = LOCAL_APIC_ADDR; + madt->lapic_addr = cpu_get_lapic_addr(); if (CONFIG(ACPI_HAVE_PCAT_8259)) madt->flags |= 1;
diff --git a/src/arch/x86/cpu.c b/src/arch/x86/cpu.c index 1ee8fb3..b523768 100644 --- a/src/arch/x86/cpu.c +++ b/src/arch/x86/cpu.c @@ -354,3 +354,8 @@ } return -1; } + +uintptr_t cpu_get_lapic_addr(void) +{ + return LOCAL_APIC_ADDR; +} diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h new file mode 100644 index 0000000..86b3932 --- /dev/null +++ b/src/include/acpi/acpi.h @@ -0,0 +1,1051 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +/* + * coreboot ACPI support - headers and defines. + */ + +#ifndef __ASM_ACPI_H +#define __ASM_ACPI_H + +/* + * The type and enable fields are common in ACPI, but the + * values themselves are hardware implementation defined. + */ +#if CONFIG(ACPI_INTEL_HARDWARE_SLEEP_VALUES) + #define SLP_EN (1 << 13) + #define SLP_TYP_SHIFT 10 + #define SLP_TYP (7 << SLP_TYP_SHIFT) + #define SLP_TYP_S0 0 + #define SLP_TYP_S1 1 + #define SLP_TYP_S3 5 + #define SLP_TYP_S4 6 + #define SLP_TYP_S5 7 +#elif CONFIG(ACPI_AMD_HARDWARE_SLEEP_VALUES) + #define SLP_EN (1 << 13) + #define SLP_TYP_SHIFT 10 + #define SLP_TYP (7 << SLP_TYP_SHIFT) + #define SLP_TYP_S0 0 + #define SLP_TYP_S1 1 + #define SLP_TYP_S3 3 + #define SLP_TYP_S4 4 + #define SLP_TYP_S5 5 +#endif + +#define ACPI_TABLE_CREATOR "COREBOOT" /* Must be exactly 8 bytes long! */ +#define OEM_ID "COREv4" /* Must be exactly 6 bytes long! */ + +#if !defined(__ASSEMBLER__) && !defined(__ACPI__) +#include <commonlib/helpers.h> +#include <device/device.h> +#include <uuid.h> +#include <cper.h> +#include <types.h> + +#define RSDP_SIG "RSD PTR " /* RSDT pointer signature */ +#define ASLC "CORE" /* Must be exactly 4 bytes long! */ + +/* + * The assigned ACPI ID for the coreboot project is 'BOOT' + * http://www.uefi.org/acpi_id_list + */ +#define COREBOOT_ACPI_ID "BOOT" /* ACPI ID for coreboot HIDs */ + +/* List of ACPI HID that use the coreboot ACPI ID */ +enum coreboot_acpi_ids { + COREBOOT_ACPI_ID_CBTABLE = 0x0000, /* BOOT0000 */ + COREBOOT_ACPI_ID_MAX = 0xFFFF, /* BOOTFFFF */ +}; + +enum acpi_tables { + /* Tables defined by ACPI and used by coreboot */ + BERT, DBG2, DMAR, DSDT, FACS, FADT, HEST, HPET, IVRS, MADT, MCFG, + RSDP, RSDT, SLIT, SRAT, SSDT, TCPA, TPM2, XSDT, ECDT, + /* Additional proprietary tables used by coreboot */ + VFCT, NHLT, SPMI +}; + +/* RSDP (Root System Description Pointer) */ +typedef struct acpi_rsdp { + char signature[8]; /* RSDP signature */ + u8 checksum; /* Checksum of the first 20 bytes */ + char oem_id[6]; /* OEM ID */ + u8 revision; /* RSDP revision */ + 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]; +} __packed acpi_rsdp_t; + +/* GAS (Generic Address Structure) */ +typedef struct acpi_gen_regaddr { + u8 space_id; /* Address space ID */ + u8 bit_width; /* Register size in bits */ + u8 bit_offset; /* Register bit offset */ + u8 access_size; /* Access size since ACPI 2.0c */ + u32 addrl; /* Register address, low 32 bits */ + u32 addrh; /* Register address, high 32 bits */ +} __packed acpi_addr_t; + +#define ACPI_ADDRESS_SPACE_MEMORY 0 /* System memory */ +#define ACPI_ADDRESS_SPACE_IO 1 /* System I/O */ +#define ACPI_ADDRESS_SPACE_PCI 2 /* PCI config space */ +#define ACPI_ADDRESS_SPACE_EC 3 /* Embedded controller */ +#define ACPI_ADDRESS_SPACE_SMBUS 4 /* SMBus */ +#define ACPI_ADDRESS_SPACE_PCC 0x0A /* Platform Comm. Channel */ +#define 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 */ +#define ACPI_ACCESS_SIZE_UNDEFINED 0 /* Undefined (legacy reasons) */ +#define ACPI_ACCESS_SIZE_BYTE_ACCESS 1 +#define ACPI_ACCESS_SIZE_WORD_ACCESS 2 +#define ACPI_ACCESS_SIZE_DWORD_ACCESS 3 +#define ACPI_ACCESS_SIZE_QWORD_ACCESS 4 + +/* Common ACPI HIDs */ +#define ACPI_HID_FDC "PNP0700" +#define ACPI_HID_KEYBOARD "PNP0303" +#define ACPI_HID_MOUSE "PNP0F03" +#define ACPI_HID_COM "PNP0501" +#define ACPI_HID_LPT "PNP0400" +#define ACPI_HID_PNP "PNP0C02" + +/* 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 */ +} __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) */ +typedef struct acpi_rsdt { + acpi_header_t header; + u32 entry[MAX_ACPI_TABLES]; +} __packed acpi_rsdt_t; + +/* XSDT (Extended System Description Table) */ +typedef struct acpi_xsdt { + acpi_header_t header; + u64 entry[MAX_ACPI_TABLES]; +} __packed acpi_xsdt_t; + +/* HPET timers */ +typedef struct acpi_hpet { + acpi_header_t header; + u32 id; + acpi_addr_t addr; + u8 number; + u16 min_tick; + u8 attributes; +} __packed acpi_hpet_t; + +/* MCFG (PCI Express MMIO config space BAR description table) */ +typedef struct acpi_mcfg { + acpi_header_t header; + u8 reserved[8]; +} __packed acpi_mcfg_t; + +typedef struct acpi_tcpa { + acpi_header_t header; + u16 platform_class; + u32 laml; + u64 lasa; +} __packed acpi_tcpa_t; + +typedef struct acpi_tpm2 { + acpi_header_t header; + u16 platform_class; + u8 reserved[2]; + u64 control_area; + u32 start_method; + u8 msp[12]; + u32 laml; + u64 lasa; +} __packed acpi_tpm2_t; + +typedef struct 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]; +} __packed acpi_mcfg_mmconfig_t; + +/* SRAT (System Resource Affinity Table) */ +typedef struct acpi_srat { + acpi_header_t header; + u32 resv; + u64 resv1; + /* Followed by static resource allocation structure[n] */ +} __packed acpi_srat_t; + +/* SRAT: Processor Local APIC/SAPIC Affinity Structure */ +typedef struct acpi_srat_lapic { + u8 type; /* Type (0) */ + u8 length; /* Length in bytes (16) */ + u8 proximity_domain_7_0; /* Proximity domain bits[7:0] */ + u8 apic_id; /* Local APIC ID */ + u32 flags; /* Enable bit 0 = 1, other bits reserved to 0 */ + u8 local_sapic_eid; /* Local SAPIC EID */ + u8 proximity_domain_31_8[3]; /* Proximity domain bits[31:8] */ + u32 clock_domain; /* _CDM Clock Domain */ +} __packed acpi_srat_lapic_t; + +/* SRAT: Memory Affinity Structure */ +typedef struct acpi_srat_mem { + u8 type; /* Type (1) */ + u8 length; /* Length in bytes (40) */ + u32 proximity_domain; /* Proximity domain */ + u16 resv; + u32 base_address_low; /* Mem range base address, low */ + u32 base_address_high; /* Mem range base address, high */ + u32 length_low; /* Mem range length, low */ + u32 length_high; /* Mem range length, high */ + u32 resv1; + u32 flags; /* Enable bit 0, hot pluggable bit 1; Non Volatile bit 2, + * other bits reserved to 0 + */ + u32 resv2[2]; +} __packed acpi_srat_mem_t; + +/* SLIT (System Locality Distance Information Table) */ +typedef struct acpi_slit { + acpi_header_t header; + /* Followed by static resource allocation 8+byte[num*num] */ +} __packed acpi_slit_t; + +/* MADT (Multiple APIC Description Table) */ +typedef struct acpi_madt { + acpi_header_t header; + u32 lapic_addr; /* Local APIC address */ + u32 flags; /* Multiple APIC flags */ +} __packed acpi_madt_t; + +/* VFCT image header */ +typedef struct acpi_vfct_image_hdr { + u32 PCIBus; + u32 PCIDevice; + u32 PCIFunction; + u16 VendorID; + u16 DeviceID; + u16 SSVID; + u16 SSID; + u32 Revision; + u32 ImageLength; + u8 VbiosContent; // dummy - copy VBIOS here +} __packed acpi_vfct_image_hdr_t; + +/* VFCT (VBIOS Fetch Table) */ +typedef struct acpi_vfct { + acpi_header_t header; + u8 TableUUID[16]; + u32 VBIOSImageOffset; + u32 Lib1ImageOffset; + u32 Reserved[4]; + acpi_vfct_image_hdr_t image_hdr; +} __packed acpi_vfct_t; + +typedef struct acpi_ivrs_info { +} __packed acpi_ivrs_info_t; + +/* IVRS IVHD (I/O Virtualization Hardware Definition Block) Type 10h */ +typedef struct acpi_ivrs_ivhd { + uint8_t type; + uint8_t flags; + uint16_t length; + uint16_t device_id; + uint16_t capability_offset; + uint32_t iommu_base_low; + uint32_t iommu_base_high; + uint16_t pci_segment_group; + uint16_t iommu_info; + uint32_t iommu_feature_info; + uint8_t entry[0]; +} __packed acpi_ivrs_ivhd_t; + +/* IVRS (I/O Virtualization Reporting Structure) Type 10h */ +typedef struct acpi_ivrs { + acpi_header_t header; + uint32_t iv_info; + uint32_t reserved[2]; + struct acpi_ivrs_ivhd ivhd; +} __packed acpi_ivrs_t; + +/* IVHD Type 11h IOMMU Attributes */ +typedef struct ivhd11_iommu_attr { + uint32_t reserved1 : 13; + uint32_t perf_counters : 4; + uint32_t perf_counter_banks : 6; + uint32_t msi_num_ppr : 5; + uint32_t reserved2 : 4; +} __packed ivhd11_iommu_attr_t; + +/* IVRS IVHD (I/O Virtualization Hardware Definition Block) Type 11h */ +typedef struct acpi_ivrs_ivhd_11 { + uint8_t type; + uint8_t flags; + uint16_t length; + uint16_t device_id; + uint16_t capability_offset; + uint32_t iommu_base_low; + uint32_t iommu_base_high; + uint16_t pci_segment_group; + uint16_t iommu_info; + struct ivhd11_iommu_attr iommu_attributes; + uint32_t efr_reg_image_low; + uint32_t efr_reg_image_high; + uint32_t reserved[2]; + uint8_t entry[0]; +} __packed acpi_ivrs_ivhd11_t; + +enum dev_scope_type { + SCOPE_PCI_ENDPOINT = 1, + SCOPE_PCI_SUB = 2, + SCOPE_IOAPIC = 3, + SCOPE_MSI_HPET = 4, + SCOPE_ACPI_NAMESPACE_DEVICE = 5 +}; + +typedef struct dev_scope { + u8 type; + u8 length; + u8 reserved[2]; + u8 enumeration; + u8 start_bus; + struct { + u8 dev; + u8 fn; + } __packed path[0]; +} __packed dev_scope_t; + +enum dmar_type { + DMAR_DRHD = 0, + DMAR_RMRR = 1, + DMAR_ATSR = 2, + DMAR_RHSA = 3, + DMAR_ANDD = 4 +}; + +enum { + DRHD_INCLUDE_PCI_ALL = 1 +}; + +enum dmar_flags { + DMAR_INTR_REMAP = 1 << 0, + DMAR_X2APIC_OPT_OUT = 1 << 1, + DMA_CTRL_PLATFORM_OPT_IN_FLAG = 1 << 2, +}; + +typedef struct dmar_entry { + u16 type; + u16 length; + u8 flags; + u8 reserved; + u16 segment; + u64 bar; +} __packed dmar_entry_t; + +typedef struct dmar_rmrr_entry { + u16 type; + u16 length; + u16 reserved; + u16 segment; + u64 bar; + u64 limit; +} __packed dmar_rmrr_entry_t; + +typedef struct dmar_atsr_entry { + u16 type; + u16 length; + u8 flags; + u8 reserved; + u16 segment; +} __packed dmar_atsr_entry_t; + +typedef struct dmar_rhsa_entry { + u16 type; + u16 length; + u32 reserved; + u64 base_address; + u32 proximity_domain; +} __packed dmar_rhsa_entry_t; + +typedef struct dmar_andd_entry { + u16 type; + u16 length; + u8 reserved[3]; + u8 device_number; + u8 device_name[]; +} __packed dmar_andd_entry_t; + +/* DMAR (DMA Remapping Reporting Structure) */ +typedef struct acpi_dmar { + acpi_header_t header; + u8 host_address_width; + u8 flags; + u8 reserved[10]; + dmar_entry_t structure[0]; +} __packed acpi_dmar_t; + +/* MADT: APIC Structure Types */ +enum acpi_apic_types { + LOCAL_APIC, /* Processor local APIC */ + IO_APIC, /* I/O APIC */ + IRQ_SOURCE_OVERRIDE, /* Interrupt source override */ + NMI_TYPE, /* NMI source */ + LOCAL_APIC_NMI, /* Local APIC NMI */ + LAPIC_ADDRESS_OVERRIDE, /* Local APIC address override */ + IO_SAPIC, /* I/O SAPIC */ + LOCAL_SAPIC, /* Local SAPIC */ + PLATFORM_IRQ_SOURCES, /* Platform interrupt sources */ + LOCAL_X2APIC, /* Processor local x2APIC */ + LOCAL_X2APIC_NMI, /* Local x2APIC NMI */ + GICC, /* GIC CPU Interface */ + GICD, /* GIC Distributor */ + GIC_MSI_FRAME, /* GIC MSI Frame */ + GICR, /* GIC Redistributor */ + GIC_ITS, /* Interrupt Translation Service */ + /* 0x10-0x7f: Reserved */ + /* 0x80-0xff: Reserved for OEM use */ +}; + +/* MADT: Processor Local APIC Structure */ +typedef struct 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 */ +} __packed acpi_madt_lapic_t; + +/* MADT: Local APIC NMI Structure */ +typedef struct 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# */ +} __packed acpi_madt_lapic_nmi_t; + +/* MADT: I/O APIC Structure */ +typedef struct 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 */ +} __packed acpi_madt_ioapic_t; + +/* MADT: Interrupt Source Override Structure */ +typedef struct 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 */ +} __packed acpi_madt_irqoverride_t; + +/* MADT: Processor Local x2APIC Structure */ +typedef struct acpi_madt_lx2apic { + u8 type; /* Type (9) */ + u8 length; /* Length in bytes (16) */ + u16 reserved; + u32 x2apic_id; /* Local x2APIC ID */ + u32 flags; /* Same as Local APIC flags */ + u32 processor_id; /* ACPI processor ID */ +} __packed acpi_madt_lx2apic_t; + +/* MADT: Processor Local x2APIC NMI Structure */ +typedef struct acpi_madt_lx2apic_nmi { + u8 type; /* Type (10) */ + u8 length; /* Length in bytes (12) */ + u16 flags; /* Same as MPS INTI flags */ + u32 processor_id; /* ACPI processor ID */ + u8 lint; /* Local APIC LINT# */ + u8 reserved[3]; +} __packed acpi_madt_lx2apic_nmi_t; + +#define ACPI_DBG2_PORT_SERIAL 0x8000 +#define ACPI_DBG2_PORT_SERIAL_16550 0x0000 +#define ACPI_DBG2_PORT_SERIAL_16550_DBGP 0x0001 +#define ACPI_DBG2_PORT_SERIAL_ARM_PL011 0x0003 +#define ACPI_DBG2_PORT_SERIAL_ARM_SBSA 0x000e +#define ACPI_DBG2_PORT_SERIAL_ARM_DDC 0x000f +#define ACPI_DBG2_PORT_SERIAL_BCM2835 0x0010 +#define ACPI_DBG2_PORT_IEEE1394 0x8001 +#define ACPI_DBG2_PORT_IEEE1394_STANDARD 0x0000 +#define ACPI_DBG2_PORT_USB 0x8002 +#define ACPI_DBG2_PORT_USB_XHCI 0x0000 +#define ACPI_DBG2_PORT_USB_EHCI 0x0001 +#define ACPI_DBG2_PORT_NET 0x8003 + +/* DBG2: Microsoft Debug Port Table 2 header */ +typedef struct acpi_dbg2_header { + acpi_header_t header; + uint32_t devices_offset; + uint32_t devices_count; +} __attribute__((packed)) acpi_dbg2_header_t; + +/* DBG2: Microsoft Debug Port Table 2 device entry */ +typedef struct acpi_dbg2_device { + uint8_t revision; + uint16_t length; + uint8_t address_count; + uint16_t namespace_string_length; + uint16_t namespace_string_offset; + uint16_t oem_data_length; + uint16_t oem_data_offset; + uint16_t port_type; + uint16_t port_subtype; + uint8_t reserved[2]; + uint16_t base_address_offset; + uint16_t address_size_offset; +} __attribute__((packed)) acpi_dbg2_device_t; + +/* FADT (Fixed ACPI Description Table) */ +typedef struct acpi_fadt { + acpi_header_t header; + u32 firmware_ctrl; + u32 dsdt; + u8 reserved; /* Should be 0 */ + 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; + acpi_addr_t reset_reg; + u8 reset_value; + u16 ARM_boot_arch; /* Revision 6 only, Revision 5: Must be zero */ + u8 FADT_MinorVersion; /* Revision 6 only, Revision 5: Must be zero */ + u32 x_firmware_ctl_l; + u32 x_firmware_ctl_h; + u32 x_dsdt_l; + u32 x_dsdt_h; + acpi_addr_t x_pm1a_evt_blk; + acpi_addr_t x_pm1b_evt_blk; + acpi_addr_t x_pm1a_cnt_blk; + acpi_addr_t x_pm1b_cnt_blk; + acpi_addr_t x_pm2_cnt_blk; + acpi_addr_t x_pm_tmr_blk; + acpi_addr_t x_gpe0_blk; + acpi_addr_t x_gpe1_blk; + /* Revision 5 */ + acpi_addr_t sleep_control_reg; + acpi_addr_t sleep_status_reg; + /* Revision 6 */ + u64 hypervisor_vendor_identity; +} __packed acpi_fadt_t; + +/* 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 +#define ACPI_FADT_REV_ACPI_6_0 6 + +/* 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 since ACPI 5.0 */ + +/* FADT Boot Architecture Flags */ +#define ACPI_FADT_LEGACY_DEVICES (1 << 0) +#define ACPI_FADT_8042 (1 << 1) +#define ACPI_FADT_VGA_NOT_PRESENT (1 << 2) +#define ACPI_FADT_MSI_NOT_SUPPORTED (1 << 3) +#define ACPI_FADT_NO_PCIE_ASPM_CONTROL (1 << 4) +#define ACPI_FADT_NO_CMOS_RTC (1 << 5) +#define ACPI_FADT_LEGACY_FREE 0x00 /* No legacy devices (including 8042) */ + +/* FADT ARM Boot Architecture Flags */ +#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0) +#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1) +/* bits 2-16: reserved since ACPI 5.1 */ + +/* 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 & greater */ +}; + +/* FACS (Firmware ACPI Control Structure) */ +typedef struct 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; /* FACS version */ + u8 resv1[3]; /* This value is 0 */ + u32 ospm_flags; /* 64BIT_WAKE_F */ + u8 resv2[24]; /* This value is 0 */ +} __packed acpi_facs_t; + +/* FACS flags */ +#define ACPI_FACS_S4BIOS_F (1 << 0) +#define ACPI_FACS_64BIT_WAKE_F (1 << 1) +/* Bits 31..2: reserved */ + +/* ECDT (Embedded Controller Boot Resources Table) */ +typedef struct acpi_ecdt { + acpi_header_t header; + acpi_addr_t ec_control; /* EC control register */ + acpi_addr_t ec_data; /* EC data register */ + u32 uid; /* UID */ + u8 gpe_bit; /* GPE bit */ + u8 ec_id[]; /* EC ID */ +} __packed acpi_ecdt_t; + +/* HEST (Hardware Error Source Table) */ +typedef struct acpi_hest { + acpi_header_t header; + u32 error_source_count; + /* error_source_struct(s) */ +} __packed acpi_hest_t; + +/* Error Source Descriptors */ +typedef struct acpi_hest_esd { + u16 type; + u16 source_id; + u16 resv; + u8 flags; + u8 enabled; + u32 prealloc_erecords; /* The number of error records to + * pre-allocate for this error source. + */ + u32 max_section_per_record; +} __packed acpi_hest_esd_t; + +/* Hardware Error Notification */ +typedef struct acpi_hest_hen { + u8 type; + u8 length; + u16 conf_we; /* Configuration Write Enable */ + u32 poll_interval; + u32 vector; + u32 sw2poll_threshold_val; + u32 sw2poll_threshold_win; + u32 error_threshold_val; + u32 error_threshold_win; +} __packed acpi_hest_hen_t; + +/* BERT (Boot Error Record Table) */ +typedef struct acpi_bert { + acpi_header_t header; + u32 region_length; + u64 error_region; +} __packed acpi_bert_t; + +/* Generic Error Data Entry */ +typedef struct acpi_hest_generic_data { + guid_t section_type; + u32 error_severity; + u16 revision; + u8 validation_bits; + u8 flags; + u32 data_length; + guid_t fru_id; + u8 fru_text[20]; + /* error data */ +} __packed acpi_hest_generic_data_t; + +/* Generic Error Data Entry v300 */ +typedef struct acpi_hest_generic_data_v300 { + guid_t section_type; + u32 error_severity; + u16 revision; + u8 validation_bits; + u8 flags; /* see CPER Section Descriptor, Flags field */ + u32 data_length; + guid_t fru_id; + u8 fru_text[20]; + cper_timestamp_t timestamp; + /* error data */ +} __packed acpi_hest_generic_data_v300_t; +#define HEST_GENERIC_ENTRY_V300 0x300 + +/* Both Generic Error Status & Generic Error Data Entry, Error Severity field */ +#define ACPI_GENERROR_SEV_RECOVERABLE 0 +#define ACPI_GENERROR_SEV_FATAL 1 +#define ACPI_GENERROR_SEV_CORRECTED 2 +#define ACPI_GENERROR_SEV_NONE 3 + +/* Generic Error Data Entry, Validation Bits field */ +#define ACPI_GENERROR_VALID_FRUID BIT(0) +#define ACPI_GENERROR_VALID_FRUID_TEXT BIT(1) +#define ACPI_GENERROR_VALID_TIMESTAMP BIT(2) + +/* Generic Error Status Block */ +typedef struct acpi_generic_error_status { + u32 block_status; + u32 raw_data_offset; /* must follow any generic entries */ + u32 raw_data_length; + u32 data_length; /* generic data */ + u32 error_severity; + /* Generic Error Data structures, zero or more entries */ +} __packed acpi_generic_error_status_t; + +/* Generic Status Block, Block Status values */ +#define GENERIC_ERR_STS_UNCORRECTABLE_VALID BIT(0) +#define GENERIC_ERR_STS_CORRECTABLE_VALID BIT(1) +#define GENERIC_ERR_STS_MULT_UNCORRECTABLE BIT(2) +#define GENERIC_ERR_STS_MULT_CORRECTABLE BIT(3) +#define GENERIC_ERR_STS_ENTRY_COUNT_SHIFT 4 +#define GENERIC_ERR_STS_ENTRY_COUNT_MAX 0x3ff +#define GENERIC_ERR_STS_ENTRY_COUNT_MASK \ + (GENERIC_ERR_STS_ENTRY_COUNT_MAX \ + << GENERIC_ERR_STS_ENTRY_COUNT_SHIFT) + +typedef struct acpi_cstate { + u8 ctype; + u16 latency; + u32 power; + acpi_addr_t resource; +} __packed acpi_cstate_t; + +typedef struct acpi_tstate { + u32 percent; + u32 power; + u32 latency; + u32 control; + u32 status; +} __packed acpi_tstate_t; + +/* Port types for ACPI _UPC object */ +enum acpi_upc_type { + UPC_TYPE_A, + UPC_TYPE_MINI_AB, + UPC_TYPE_EXPRESSCARD, + UPC_TYPE_USB3_A, + UPC_TYPE_USB3_B, + UPC_TYPE_USB3_MICRO_B, + UPC_TYPE_USB3_MICRO_AB, + UPC_TYPE_USB3_POWER_B, + UPC_TYPE_C_USB2_ONLY, + UPC_TYPE_C_USB2_SS_SWITCH, + UPC_TYPE_C_USB2_SS, + UPC_TYPE_PROPRIETARY = 0xff, + /* + * The following types are not directly defined in the ACPI + * spec but are used by coreboot to identify a USB device type. + */ + UPC_TYPE_INTERNAL = 0xff, + UPC_TYPE_UNUSED, + UPC_TYPE_HUB +}; + +enum acpi_ipmi_interface_type { + IPMI_INTERFACE_RESERVED = 0, + IPMI_INTERFACE_KCS, + IPMI_INTERFACE_SMIC, + IPMI_INTERFACE_BT, + IPMI_INTERFACE_SSIF, +}; + +#define ACPI_IPMI_PCI_DEVICE_FLAG (1 << 0) +#define ACPI_IPMI_INT_TYPE_SCI (1 << 0) +#define ACPI_IPMI_INT_TYPE_APIC (1 << 1) + +/* ACPI IPMI 2.0 */ +struct acpi_spmi { + acpi_header_t header; + u8 interface_type; + u8 reserved; + u16 specification_revision; + u8 interrupt_type; + u8 gpe; + u8 reserved2; + u8 pci_device_flag; + + u32 global_system_interrupt; + acpi_addr_t base_address; + union { + struct { + u8 pci_segment_group; + u8 pci_bus; + u8 pci_device; + u8 pci_function; + }; + u8 uid[4]; + }; + u8 reserved3; +} __packed; + +unsigned long fw_cfg_acpi_tables(unsigned long start); + +/* These are implemented by the target port or north/southbridge. */ +unsigned long write_acpi_tables(unsigned long addr); +unsigned long acpi_fill_madt(unsigned long current); +unsigned long acpi_fill_mcfg(unsigned long current); +unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t *ivrs, unsigned long current); +void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id); +void acpi_write_bert(acpi_bert_t *bert, uintptr_t region, size_t length); +void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt); +#if CONFIG(COMMON_FADT) +void acpi_fill_fadt(acpi_fadt_t *fadt); +#endif + +void update_ssdt(void *ssdt); +void update_ssdtx(void *ssdtx, int i); + +/* These can be used by the target port. */ +u8 acpi_checksum(u8 *table, u32 length); + +void acpi_add_table(acpi_rsdp_t *rsdp, void *table); + +int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic); +int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr, + u32 gsi_base); +int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride, + u8 bus, u8 source, u32 gsirq, u16 flags); +int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu, + u16 flags, u8 lint); +void acpi_create_madt(acpi_madt_t *madt); +unsigned long acpi_create_madt_lapics(unsigned long current); +unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, + u8 lint); +int acpi_create_madt_lx2apic(acpi_madt_lx2apic_t *lapic, u32 cpu, u32 apic); +int acpi_create_madt_lx2apic_nmi(acpi_madt_lx2apic_nmi_t *lapic_nmi, u32 cpu, + u16 flags, u8 lint); +int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic); +int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek, u32 sizek, + u32 flags); +int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base, + u16 seg_nr, u8 start, u8 end); +unsigned long acpi_create_srat_lapics(unsigned long current); +void acpi_create_srat(acpi_srat_t *srat, + unsigned long (*acpi_fill_srat)(unsigned long current)); + +void acpi_create_slit(acpi_slit_t *slit, + unsigned long (*acpi_fill_slit)(unsigned long current)); + +void acpi_create_vfct(const struct device *device, + acpi_vfct_t *vfct, + unsigned long (*acpi_fill_vfct)(const struct device *device, + acpi_vfct_t *vfct_struct, + unsigned long current)); + +void acpi_create_ipmi(const struct device *device, + struct acpi_spmi *spmi, + const u16 ipmi_revision, + const acpi_addr_t *addr, + const enum acpi_ipmi_interface_type type, + const s8 gpe_interrupt, + const u32 apic_interrupt, + const u32 uid); + +void acpi_create_ivrs(acpi_ivrs_t *ivrs, + unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t *ivrs_struct, + unsigned long current)); + +void acpi_create_hpet(acpi_hpet_t *hpet); +unsigned long acpi_write_hpet(const struct device *device, unsigned long start, + acpi_rsdp_t *rsdp); + +/* cpu/intel/speedstep/acpi.c */ +void generate_cpu_entries(const struct device *device); + +void acpi_create_mcfg(acpi_mcfg_t *mcfg); + +void acpi_create_facs(acpi_facs_t *facs); + +void acpi_create_dbg2(acpi_dbg2_header_t *dbg2_header, + int port_type, int port_subtype, + acpi_addr_t *address, uint32_t address_size, + const char *device_path); + +unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current, + const struct device *dev, uint8_t access_size); +void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags, + unsigned long (*acpi_fill_dmar)(unsigned long)); +unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, + u16 segment, u64 bar); +unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment, + u64 bar, u64 limit); +unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags, + u16 segment); +unsigned long acpi_create_dmar_rhsa(unsigned long current, u64 base_addr, + u32 proximity_domain); +unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number, + const char *device_name); +void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current); +void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current); +void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current); +unsigned long acpi_create_dmar_ds_pci_br(unsigned long current, + u8 bus, u8 dev, u8 fn); +unsigned long acpi_create_dmar_ds_pci(unsigned long current, + u8 bus, u8 dev, u8 fn); +unsigned long acpi_create_dmar_ds_ioapic(unsigned long current, + u8 enumeration_id, + u8 bus, u8 dev, u8 fn); +unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current, + u8 enumeration_id, + u8 bus, u8 dev, u8 fn); +void acpi_write_hest(acpi_hest_t *hest, + unsigned long (*acpi_fill_hest)(acpi_hest_t *hest)); + +unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, + acpi_hest_esd_t *esd, u16 type, void *data, u16 len); + +/* For ACPI S3 support. */ +void acpi_resume(void *wake_vec); +void mainboard_suspend_resume(void); +void *acpi_find_wakeup_vector(void); + +/* ACPI_Sn assignments are defined to always equal the sleep state numbers */ +enum { + ACPI_S0 = 0, + ACPI_S1 = 1, + ACPI_S2 = 2, + ACPI_S3 = 3, + ACPI_S4 = 4, + ACPI_S5 = 5, +}; + +#if CONFIG(ACPI_INTEL_HARDWARE_SLEEP_VALUES) \ + || CONFIG(ACPI_AMD_HARDWARE_SLEEP_VALUES) +/* Given the provided PM1 control register return the ACPI sleep type. */ +static inline int acpi_sleep_from_pm1(uint32_t pm1_cnt) +{ + switch (((pm1_cnt) & SLP_TYP) >> SLP_TYP_SHIFT) { + case SLP_TYP_S0: return ACPI_S0; + case SLP_TYP_S1: return ACPI_S1; + case SLP_TYP_S3: return ACPI_S3; + case SLP_TYP_S4: return ACPI_S4; + case SLP_TYP_S5: return ACPI_S5; + } + return -1; +} +#endif + +/* Returns ACPI_Sx values. */ +int acpi_get_sleep_type(void); + +/* Read and clear GPE status */ +int acpi_get_gpe(int gpe); + +static inline int acpi_s3_resume_allowed(void) +{ + return CONFIG(HAVE_ACPI_RESUME); +} + +#if CONFIG(HAVE_ACPI_RESUME) + +#if ENV_ROMSTAGE_OR_BEFORE +static inline int acpi_is_wakeup_s3(void) +{ + return (acpi_get_sleep_type() == ACPI_S3); +} +#else +int acpi_is_wakeup(void); +int acpi_is_wakeup_s3(void); +int acpi_is_wakeup_s4(void); +#endif + +#else +static inline int acpi_is_wakeup(void) { return 0; } +static inline int acpi_is_wakeup_s3(void) { return 0; } +static inline int acpi_is_wakeup_s4(void) { return 0; } +#endif + +static inline uintptr_t acpi_align_current(uintptr_t current) +{ + return ALIGN_UP(current, 16); +} + +/* ACPI table revisions should match the revision of the ACPI spec + * supported. This function keeps the table versions synced. This could + * be made into a weak function if there is ever a need to override the + * coreboot default ACPI spec version supported. */ +int get_acpi_table_revision(enum acpi_tables table); + +#endif // !defined(__ASSEMBLER__) && !defined(__ACPI__) && !defined(__ROMC__) + +#endif /* __ASM_ACPI_H */ diff --git a/src/include/acpi/acpi_device.h b/src/include/acpi/acpi_device.h new file mode 100644 index 0000000..ed64cd8 --- /dev/null +++ b/src/include/acpi/acpi_device.h @@ -0,0 +1,513 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#ifndef __ACPI_DEVICE_H +#define __ACPI_DEVICE_H + +#include <device/i2c.h> +#include <stdint.h> +#include <spi-generic.h> + +enum acpi_dp_type { + ACPI_DP_TYPE_UNKNOWN, + ACPI_DP_TYPE_INTEGER, + ACPI_DP_TYPE_STRING, + ACPI_DP_TYPE_REFERENCE, + ACPI_DP_TYPE_TABLE, + ACPI_DP_TYPE_ARRAY, + ACPI_DP_TYPE_CHILD, +}; + +struct acpi_dp { + enum acpi_dp_type type; + const char *name; + struct acpi_dp *next; + union { + struct acpi_dp *child; + struct acpi_dp *array; + }; + union { + uint64_t integer; + const char *string; + }; +}; + +#define ACPI_DESCRIPTOR_LARGE (1 << 7) +#define ACPI_DESCRIPTOR_INTERRUPT (ACPI_DESCRIPTOR_LARGE | 9) +#define ACPI_DESCRIPTOR_GPIO (ACPI_DESCRIPTOR_LARGE | 12) +#define ACPI_DESCRIPTOR_SERIAL_BUS (ACPI_DESCRIPTOR_LARGE | 14) + +/* + * PRP0001 is a special DT namespace link device ID. It provides a means to use + * existing DT-compatible device identification in ACPI. When this _HID is used + * by an ACPI device, the ACPI subsystem in OS looks up "compatible" property in + * device object's _DSD and will use the value of that property to identify the + * corresponding device in analogy with the original DT device identification + * algorithm. + * More details can be found in Linux kernel documentation: + * Documentation/acpi/enumeration.txt + */ +#define ACPI_DT_NAMESPACE_HID "PRP0001" + +struct device; +const char *acpi_device_name(const struct device *dev); +const char *acpi_device_hid(const struct device *dev); +uint32_t acpi_device_uid(const struct device *dev); +const char *acpi_device_path(const struct device *dev); +const char *acpi_device_scope(const struct device *dev); +const char *acpi_device_path_join(const struct device *dev, const char *name); +int acpi_device_status(const struct device *dev); +void acpi_device_write_uid(const struct device *dev); + +/* + * ACPI Descriptor for extended Interrupt() + */ + +enum acpi_irq_mode { + ACPI_IRQ_EDGE_TRIGGERED, + ACPI_IRQ_LEVEL_TRIGGERED +}; + +enum acpi_irq_polarity { + ACPI_IRQ_ACTIVE_LOW, + ACPI_IRQ_ACTIVE_HIGH, + ACPI_IRQ_ACTIVE_BOTH +}; + +enum acpi_irq_shared { + ACPI_IRQ_EXCLUSIVE, + ACPI_IRQ_SHARED +}; + +enum acpi_irq_wake { + ACPI_IRQ_NO_WAKE, + ACPI_IRQ_WAKE +}; + +struct acpi_irq { + unsigned int pin; + enum acpi_irq_mode mode; + enum acpi_irq_polarity polarity; + enum acpi_irq_shared shared; + enum acpi_irq_wake wake; +}; + +#define ACPI_IRQ_CFG(_pin, _mode, _pol, _shared, _wake) { \ + .pin = (_pin), \ + .mode = (_mode), \ + .polarity = (_pol), \ + .shared = (_shared), \ + .wake = (_wake) } + +#define ACPI_IRQ_EDGE_LOW(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \ + ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_NO_WAKE) + +#define ACPI_IRQ_EDGE_HIGH(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \ + ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_NO_WAKE) + +#define ACPI_IRQ_LEVEL_LOW(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \ + ACPI_IRQ_SHARED, ACPI_IRQ_NO_WAKE) + +#define ACPI_IRQ_LEVEL_HIGH(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \ + ACPI_IRQ_SHARED, ACPI_IRQ_NO_WAKE) + +#define ACPI_IRQ_WAKE_EDGE_LOW(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \ + ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_WAKE) + +#define ACPI_IRQ_WAKE_EDGE_HIGH(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \ + ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_WAKE) + +#define ACPI_IRQ_WAKE_LEVEL_LOW(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \ + ACPI_IRQ_SHARED, ACPI_IRQ_WAKE) + +#define ACPI_IRQ_WAKE_LEVEL_HIGH(x) \ + ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \ + ACPI_IRQ_SHARED, ACPI_IRQ_WAKE) + +/* Write extended Interrupt() descriptor to SSDT AML output */ +void acpi_device_write_interrupt(const struct acpi_irq *irq); + +/* + * ACPI Descriptors for GpioIo() and GpioInterrupt() + */ + +enum acpi_gpio_type { + ACPI_GPIO_TYPE_INTERRUPT, + ACPI_GPIO_TYPE_IO +}; + +enum acpi_gpio_pull { + ACPI_GPIO_PULL_DEFAULT, + ACPI_GPIO_PULL_UP, + ACPI_GPIO_PULL_DOWN, + ACPI_GPIO_PULL_NONE +}; + +enum acpi_gpio_io_restrict { + ACPI_GPIO_IO_RESTRICT_NONE, + ACPI_GPIO_IO_RESTRICT_INPUT, + ACPI_GPIO_IO_RESTRICT_OUTPUT, + ACPI_GPIO_IO_RESTRICT_PRESERVE +}; + +enum acpi_gpio_polarity { + ACPI_GPIO_ACTIVE_HIGH = 0, + ACPI_GPIO_ACTIVE_LOW = 1, +}; + +#define ACPI_GPIO_REVISION_ID 1 +#define ACPI_GPIO_MAX_PINS 8 + +struct acpi_gpio { + int pin_count; + uint16_t pins[ACPI_GPIO_MAX_PINS]; + + enum acpi_gpio_type type; + enum acpi_gpio_pull pull; + const char *resource; + + /* GpioInt */ + uint16_t interrupt_debounce_timeout; /* 1/100 ms */ + struct acpi_irq irq; + + /* GpioIo */ + uint16_t output_drive_strength; /* 1/100 mA */ + int io_shared; + enum acpi_gpio_io_restrict io_restrict; + enum acpi_gpio_polarity polarity; +}; + +/* Basic output GPIO with default pull settings */ +#define ACPI_GPIO_OUTPUT_ACTIVE_HIGH(gpio) { \ + .type = ACPI_GPIO_TYPE_IO, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .io_restrict = ACPI_GPIO_IO_RESTRICT_OUTPUT, \ + .polarity = ACPI_GPIO_ACTIVE_HIGH, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +#define ACPI_GPIO_OUTPUT_ACTIVE_LOW(gpio) { \ + .type = ACPI_GPIO_TYPE_IO, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .io_restrict = ACPI_GPIO_IO_RESTRICT_OUTPUT, \ + .polarity = ACPI_GPIO_ACTIVE_LOW, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Basic input GPIO with default pull settings */ +#define ACPI_GPIO_INPUT_ACTIVE_HIGH(gpio) { \ + .type = ACPI_GPIO_TYPE_IO, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .io_restrict = ACPI_GPIO_IO_RESTRICT_INPUT, \ + .polarity = ACPI_GPIO_ACTIVE_HIGH, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +#define ACPI_GPIO_INPUT_ACTIVE_LOW(gpio) { \ + .type = ACPI_GPIO_TYPE_IO, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .io_restrict = ACPI_GPIO_IO_RESTRICT_INPUT, \ + .polarity = ACPI_GPIO_ACTIVE_LOW, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Edge Triggered Active High GPIO interrupt */ +#define ACPI_GPIO_IRQ_EDGE_HIGH(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_HIGH, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Edge Triggered Active Low GPIO interrupt */ +#define ACPI_GPIO_IRQ_EDGE_LOW(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_LOW, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Edge Triggered Active Both GPIO interrupt */ +#define ACPI_GPIO_IRQ_EDGE_BOTH(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_BOTH, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Edge Triggered Active High GPIO interrupt with wake */ +#define ACPI_GPIO_IRQ_EDGE_HIGH_WAKE(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_HIGH, \ + .irq.wake = ACPI_IRQ_WAKE, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Edge Triggered Active Low GPIO interrupt with wake */ +#define ACPI_GPIO_IRQ_EDGE_LOW_WAKE(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_LOW, \ + .irq.wake = ACPI_IRQ_WAKE, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Edge Triggered Active Both GPIO interrupt with wake */ +#define ACPI_GPIO_IRQ_EDGE_BOTH_WAKE(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_BOTH, \ + .irq.wake = ACPI_IRQ_WAKE, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Level Triggered Active High GPIO interrupt */ +#define ACPI_GPIO_IRQ_LEVEL_HIGH(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_LEVEL_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_HIGH, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Level Triggered Active Low GPIO interrupt */ +#define ACPI_GPIO_IRQ_LEVEL_LOW(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_LEVEL_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_LOW, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Level Triggered Active High GPIO interrupt with wake */ +#define ACPI_GPIO_IRQ_LEVEL_HIGH_WAKE(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_LEVEL_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_HIGH, \ + .irq.wake = ACPI_IRQ_WAKE, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Level Triggered Active Low GPIO interrupt with wake */ +#define ACPI_GPIO_IRQ_LEVEL_LOW_WAKE(gpio) { \ + .type = ACPI_GPIO_TYPE_INTERRUPT, \ + .pull = ACPI_GPIO_PULL_DEFAULT, \ + .irq.mode = ACPI_IRQ_LEVEL_TRIGGERED, \ + .irq.polarity = ACPI_IRQ_ACTIVE_LOW, \ + .irq.wake = ACPI_IRQ_WAKE, \ + .pin_count = 1, \ + .pins = { (gpio) } } + +/* Write GpioIo() or GpioInt() descriptor to SSDT AML output */ +void acpi_device_write_gpio(const struct acpi_gpio *gpio); + +/* + * ACPI Descriptors for Serial Bus interfaces + */ + +#define ACPI_SERIAL_BUS_TYPE_I2C 1 +#define ACPI_SERIAL_BUS_TYPE_SPI 2 +#define ACPI_I2C_SERIAL_BUS_REVISION_ID 1 /* TODO: upgrade to 2 */ +#define ACPI_I2C_TYPE_SPECIFIC_REVISION_ID 1 +#define ACPI_SPI_SERIAL_BUS_REVISION_ID 1 +#define ACPI_SPI_TYPE_SPECIFIC_REVISION_ID 1 + +/* + * ACPI I2C Bus + */ + +struct acpi_i2c { + /* I2C Address */ + uint16_t address; + /* 7 or 10 bit Address Mode */ + enum i2c_address_mode mode_10bit; + /* I2C Bus Speed in Hz */ + enum i2c_speed speed; + /* Reference to I2C controller */ + const char *resource; +}; + +/* Write I2cSerialBus() descriptor to SSDT AML output */ +void acpi_device_write_i2c(const struct acpi_i2c *i2c); + +/* + * ACPI SPI Bus + */ + +struct acpi_spi { + /* Device selection */ + uint16_t device_select; + /* Device selection line is active high or low */ + enum spi_polarity device_select_polarity; + /* 3 or 4 wire SPI connection */ + enum spi_wire_mode wire_mode; + /* Connection speed in HZ */ + unsigned int speed; + /* Size in bits of smallest transfer unit */ + u8 data_bit_length; + /* Phase of clock pulse on which to capture data */ + enum spi_clock_phase clock_phase; + /* Indicate if clock is high or low during first phase */ + enum spi_polarity clock_polarity; + /* Reference to SPI controller */ + const char *resource; +}; + +/* Write SPI Bus descriptor to SSDT AML output */ +void acpi_device_write_spi(const struct acpi_spi *spi); + +/* GPIO/timing information for the power on/off sequences */ +struct acpi_power_res_params { + /* GPIO used to take device out of reset or to put it into reset. */ + struct acpi_gpio *reset_gpio; + /* Delay to be inserted after device is taken out of reset. + * (_ON method delay) + */ + unsigned int reset_delay_ms; + /* Delay to be inserted after device is put into reset. + * (_OFF method delay) + */ + unsigned int reset_off_delay_ms; + /* GPIO used to enable device. */ + struct acpi_gpio *enable_gpio; + /* Delay to be inserted after device is enabled. + * (_ON method delay) + */ + unsigned int enable_delay_ms; + /* Delay to be inserted after device is disabled. + * (_OFF method delay) + */ + unsigned int enable_off_delay_ms; + /* GPIO used to stop operation of device. */ + struct acpi_gpio *stop_gpio; + /* Delay to be inserted after disabling stop. + * (_ON method delay) + */ + unsigned int stop_delay_ms; + /* Delay to be inserted after enabling stop. + * (_OFF method delay) + */ + unsigned int stop_off_delay_ms; +}; + +/* + * Add a basic PowerResource block for a device that includes + * GPIOs to control enable, reset and stop operation of the device. Each + * GPIO is optional, but at least one must be provided. + * + * Reset - Put the device into / take the device out of reset. + * Enable - Enable / disable power to device. + * Stop - Stop / start operation of device. + */ +void acpi_device_add_power_res(const struct acpi_power_res_params *params); + +/* + * Writing Device Properties objects via _DSD + * + * http://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pd... + * http://uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extensi... + * + * The Device Property Hierarchy can be multiple levels deep with multiple + * children possible in each level. In order to support this flexibility + * the device property hierarchy must be built up before being written out. + * + * For example: + * + * // Child table with string and integer + * struct acpi_dp *child = acpi_dp_new_table("CHLD"); + * acpi_dp_add_string(child, "childstring", "CHILD"); + * acpi_dp_add_integer(child, "childint", 100); + * + * // _DSD table with integer and gpio and child pointer + * struct acpi_dp *dsd = acpi_dp_new_table("_DSD"); + * acpi_dp_add_integer(dsd, "number1", 1); + * acpi_dp_add_gpio(dsd, "gpio", "_SB.PCI0.GPIO", 0, 0, 1); + * acpi_dp_add_child(dsd, "child", child); + * + * // Write entries into SSDT and clean up resources + * acpi_dp_write(dsd); + * + * Name(_DSD, Package() { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") + * Package() { + * Package() { "gpio", Package() { _SB.PCI0.GPIO, 0, 0, 0 } } + * Package() { "number1", 1 } + * } + * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b") + * Package() { + * Package() { "child", CHLD } + * } + * } + * Name(CHLD, Package() { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") + * Package() { + * Package() { "childstring", "CHILD" } + * Package() { "childint", 100 } + * } + * } + */ + +/* Start a new Device Property table with provided ACPI reference */ +struct acpi_dp *acpi_dp_new_table(const char *ref); + +/* Add integer Device Property */ +struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name, + uint64_t value); + +/* Add string Device Property */ +struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name, + const char *string); + +/* Add ACPI reference Device Property */ +struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name, + const char *reference); + +/* Add an array of Device Properties */ +struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array); + +/* Add an array of integers Device Property */ +struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name, + uint64_t *array, int len); + +/* Add a GPIO binding Device Property */ +struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name, + const char *ref, int index, int pin, + int active_low); + +/* Add a child table of Device Properties */ +struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name, + struct acpi_dp *child); + +/* Add a list of Device Properties, returns the number of properties added */ +size_t acpi_dp_add_property_list(struct acpi_dp *dp, + const struct acpi_dp *property_list, + size_t property_count); + +/* Write Device Property hierarchy and clean up resources */ +void acpi_dp_write(struct acpi_dp *table); + +/* + * Helper function to write a PCI device with _ADR object defined. + * + * IMPORTANT: Scope of a device created in SSDT cannot be used to add ACPI nodes under that + * scope in DSDT. So, if there are any references to this PCI device scope required from static + * asl files, do not use this function and instead add the device to DSDT as well. + */ +void acpi_device_write_pci_dev(const struct device *dev); + +#endif diff --git a/src/include/acpi/acpi_ivrs.h b/src/include/acpi/acpi_ivrs.h new file mode 100644 index 0000000..83abfb6 --- /dev/null +++ b/src/include/acpi/acpi_ivrs.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +/* + * AMD I/O Virtualization Technology (IOMMU) + * Specification 48882-Rev 2.62-February 2015 + * + * from http://www.uefi.org/acpi + * I/O Virtualization Reporting Structure (IVRS) + */ + +#ifndef __ARCH_ACPI_IVRS_H +#define __ARCH_ACPI_IVRS_H + +/* I/O Virtualization Reporting Structure (IVRS) */ +#define IVHD_BLOCK_TYPE_LEGACY__FIXED 0x10 +#define IVHD_BLOCK_TYPE_FULL__FIXED 0x11 +#define IVHD_BLOCK_TYPE_FULL__ACPI_HID 0x40 + +/* IVRS Revision Field */ +#define IVRS_FORMAT_FIXED 0x01 /* Type 10h & 11h only */ +#define IVRS_FORMAT_MIXED 0x02 /* Type 10h, 11h, & 40h */ + +/* IVRS IVinfo Field */ +/* ATS response address range reserved */ +#define IVINFO_HT_ATS_RESERVED (1 << 22) + +/* Virtual Address size - All other values are reserved */ +#define IVINFO_VA_SIZE_32_BITS (0x20 << 15) +#define IVINFO_VA_SIZE_40_BITS (0x28 << 15) +#define IVINFO_VA_SIZE_48_BITS (0x30 << 15) +#define IVINFO_VA_SIZE_64_BITS (0x40 << 15) + +/* Physical Address size - All other values are reserved */ +#define IVINFO_PA_SIZE_40_BITS (0x28 << 8) +#define IVINFO_PA_SIZE_48_BITS (0x30 << 8) +#define IVINFO_PA_SIZE_52_BITS (0x34 << 8) + +/* Guest Virtual Address size - All other values are reserved */ +#define IVINFO_GVA_SIZE_48_BITS (0x02 << 5) + +/* Extended Feature Support */ +#define IVINFO_EFR_SUPPORTED 0x01 + +/* IVHD Flags Field */ +#define IVHD_FLAG_PPE_SUP (1 << 7) /* Type 10h only */ +#define IVHD_FLAG_PREF_SUP (1 << 6) /* Type 10h only */ +#define IVHD_FLAG_COHERENT (1 << 5) +#define IVHD_FLAG_IOTLB_SUP (1 << 4) +#define IVHD_FLAG_ISOC (1 << 3) +#define IVHD_FLAG_RES_PASS_PW (1 << 2) +#define IVHD_FLAG_PASS_PW (1 << 1) +#define IVHD_FLAG_HT_TUN_EN (1 << 0) + +/* IVHD IOMMU Info Field */ +#define IOMMU_INFO_UNIT_ID_SHIFT 8 + +/* IVHD IOMMU Feature Reporting Field */ +#define IOMMU_FEATURE_HATS_SHIFT 30 /* Type 10h only */ +#define IOMMU_FEATURE_GATS_SHIFT 28 /* Type 10h only */ +#define IOMMU_FEATURE_MSI_NUM_PPR_SHIFT 23 +#define IOMMU_FEATURE_PN_BANKS_SHIFT 17 +#define IOMMU_FEATURE_PN_COUNTERS_SHIFT 13 +#define IOMMU_FEATURE_PA_SMAX_SHIFT 8 /* Type 10h only */ + +#define IOMMU_FEATURE_HE_SUP (1 << 7) /* Type 10h only */ +#define IOMMU_FEATURE_GA_SUP (1 << 6) /* Type 10h only */ +#define IOMMU_FEATURE_IA_SUP (1 << 5) /* Type 10h only */ +#define IOMMU_FEATURE_GLX_SINGLE_LEVEL (0 << 3) /* Type 10h only */ +#define IOMMU_FEATURE_GLX_TWO_LEVEL (1 << 3) /* Type 10h only */ +#define IOMMU_FEATURE_GLX_THREE_LEVEL (2 << 3) /* Type 10h only */ +#define IOMMU_FEATURE_GT_SUP (1 << 1) /* Type 10h only */ +#define IOMMU_FEATURE_NX_SUP (1 << 0) /* Type 10h only */ + +/* IVHD Device Entry Type Codes */ +#define IVHD_DEV_4_BYTE_ALL 0x01 +#define IVHD_DEV_4_BYTE_SELECT 0x02 +#define IVHD_DEV_4_BYTE_START_RANGE 0x03 +#define IVHD_DEV_4_BYTE_END_RANGE 0x04 +#define IVHD_DEV_8_BYTE_ALIAS_SELECT 0x42 +#define IVHD_DEV_8_BYTE_ALIAS_START_RANGE 0x43 +#define IVHD_DEV_8_BYTE_EXT_SELECT 0x46 +#define IVHD_DEV_8_BYTE_EXT_START_RANGE 0x47 +#define IVHD_DEV_8_BYTE_EXT_SPECIAL_DEV 0x48 +#define IVHD_DEV_VARIABLE 0xF0 + +/* IVHD Device Table Entry (DTE) Settings */ +#define IVHD_DTE_LINT_1_PASS (1 << 7) +#define IVHD_DTE_LINT_0_PASS (1 << 6) +#define IVHD_DTE_SYS_MGT_TGT_ABT (0 << 4) +#define IVHD_DTE_SYS_MGT_NO_TRANS (1 << 4) +#define IVHD_DTE_SYS_MGT_INTX_NO_TRANS (2 << 4) +#define IVHD_DTE_SYS_MGT_TRANS (3 << 4) +#define IVHD_DTE_NMI_PASS (1 << 2) +#define IVHD_DTE_EXT_INT_PASS (1 << 1) +#define IVHD_DTE_INIT_PASS (1 << 0) + +/* IVHD Device Entry Extended DTE Setting Field */ +#define IVHD_DEV_EXT_ATS_DISABLE (1 << 31) + +/* IVHD Special Device Entry Variety Field */ +#define IVHD_SPECIAL_DEV_IOAPIC 0x01 +#define IVHD_SPECIAL_DEV_HPET 0x02 + +/* Device EntryType F0h UID Format */ +#define IVHD_UID_NOT_PRESENT 0x00 +#define IVHD_UID_INT 0x01 +#define IVHD_UID_STRING 0x02 + +/* IVHD (I/O Virtualization Hardware Definition Block) 4-byte entry */ +typedef struct ivrs_ivhd_generic { + uint8_t type; + uint16_t dev_id; + uint8_t dte_setting; +} __packed ivrs_ivhd_generic_t; + +/* IVHD (I/O Virtualization Hardware Definition Block) 8-byte entries */ +typedef struct ivrs_ivhd_alias { + uint8_t type; + uint16_t dev_id; + uint8_t dte_setting; + uint8_t reserved1; + uint16_t source_dev_id; + uint8_t reserved2; +} __packed ivrs_ivhd_alias_t; + +typedef struct ivrs_ivhd_extended { + uint8_t type; + uint16_t dev_id; + uint8_t dte_setting; + uint32_t extended_dte_setting; +} __packed ivrs_ivhd_extended_t; + +typedef struct ivrs_ivhd_special { + uint8_t type; + uint16_t reserved; + uint8_t dte_setting; + uint8_t handle; + uint16_t source_dev_id; + uint8_t variety; +} __packed ivrs_ivhd_special_t; + +#endif diff --git a/src/include/acpi/acpi_pld.h b/src/include/acpi/acpi_pld.h new file mode 100644 index 0000000..944eb31 --- /dev/null +++ b/src/include/acpi/acpi_pld.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#ifndef __ACPI_PLD_H +#define __ACPI_PLD_H + +#include <arch/acpi.h> +#include <stdint.h> + +enum acpi_pld_panel { + PLD_PANEL_TOP, + PLD_PANEL_BOTTOM, + PLD_PANEL_LEFT, + PLD_PANEL_RIGHT, + PLD_PANEL_FRONT, + PLD_PANEL_BACK, + PLD_PANEL_UNKNOWN +}; + +enum acpi_pld_vertical_position { + PLD_VERTICAL_POSITION_UPPER, + PLD_VERTICAL_POSITION_CENTER, + PLD_VERTICAL_POSITION_LOWER +}; + +/* + * The ACPI spec 6.2A does not define the horizontal position field. + * These values are taken from the IASL compiler: + * https://github.com/acpica/acpica/blob/master/source/components/utilities/utg... + */ + +enum acpi_pld_horizontal_position { + PLD_HORIZONTAL_POSITION_LEFT, + PLD_HORIZONTAL_POSITION_CENTER, + PLD_HORIZONTAL_POSITION_RIGHT +}; + +enum acpi_pld_shape { + PLD_SHAPE_ROUND, + PLD_SHAPE_OVAL, + PLD_SHAPE_SQUARE, + PLD_SHAPE_VERTICAL_RECTANGLE, + PLD_SHAPE_HORIZONTAL_RECTANGLE, + PLD_SHAPE_VERTICAL_TRAPEZOID, + PLD_SHAPE_HORIZONTAL_TRAPEZOID, + PLD_SHAPE_UNKNOWN, + PLD_SHAPE_CHAMFERED +}; + +enum acpi_pld_orientation { + PLD_ORIENTATION_HORIZONTAL, + PLD_ORIENTATION_VERTICAL, +}; + +enum acpi_pld_rotate { + PLD_ROTATE_0, + PLD_ROTATE_45, + PLD_ROTATE_90, + PLD_ROTATE_135, + PLD_ROTATE_180, + PLD_ROTATE_225, + PLD_ROTATE_270, + PLD_ROTATE_315 +}; + +#define ACPI_PLD_GROUP(__token, __position) \ + { \ + .token = __token, \ + .position = __position, \ + } + +struct acpi_pld_group { + uint8_t token; + uint8_t position; +}; + +struct acpi_pld { + /* Color field can be explicitly ignored */ + bool ignore_color; + uint8_t color_red; + uint8_t color_blue; + uint8_t color_green; + + /* Port characteristics */ + bool visible; /* Can be seen by the user */ + bool lid; /* Port is on lid of device */ + bool dock; /* Port is in a docking station */ + bool bay; /* Port is in a bay */ + bool ejectable; /* Device is ejectable, has _EJx objects */ + bool ejectable_ospm; /* Device needs OSPM to eject */ + uint16_t width; /* Width in mm */ + uint16_t height; /* Height in mm */ + uint16_t vertical_offset; + uint16_t horizontal_offset; + enum acpi_pld_panel panel; + enum acpi_pld_horizontal_position horizontal_position; + enum acpi_pld_vertical_position vertical_position; + enum acpi_pld_shape shape; + enum acpi_pld_rotate rotation; + + /* Port grouping */ + enum acpi_pld_orientation orientation; + struct acpi_pld_group group; + uint8_t draw_order; + uint8_t cabinet_number; + uint8_t card_cage_number; + + /* Set if this PLD defines a reference shape */ + bool reference_shape; +}; + +/* Fill out PLD structure with defaults based on USB port type */ +int acpi_pld_fill_usb(struct acpi_pld *pld, enum acpi_upc_type type, + struct acpi_pld_group *group); + +/* Turn PLD structure into a 20 byte ACPI buffer */ +int acpi_pld_to_buffer(const struct acpi_pld *pld, uint8_t *buf, int buf_len); + +#endif diff --git a/src/include/acpi/acpigen.h b/src/include/acpi/acpigen.h new file mode 100644 index 0000000..3339ce4 --- /dev/null +++ b/src/include/acpi/acpigen.h @@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#ifndef LIBACPI_H +#define LIBACPI_H + +#include <stdint.h> +#include <arch/acpi.h> +#include <arch/acpi_device.h> +#include <arch/acpi_pld.h> +#include <device/pci_type.h> + +/* Values that can be returned for ACPI Device _STA method */ +#define ACPI_STATUS_DEVICE_PRESENT (1 << 0) +#define ACPI_STATUS_DEVICE_ENABLED (1 << 1) +#define ACPI_STATUS_DEVICE_SHOW_IN_UI (1 << 2) +#define ACPI_STATUS_DEVICE_STATE_OK (1 << 3) + +#define ACPI_STATUS_DEVICE_ALL_OFF 0 +#define ACPI_STATUS_DEVICE_ALL_ON (ACPI_STATUS_DEVICE_PRESENT |\ + ACPI_STATUS_DEVICE_ENABLED |\ + ACPI_STATUS_DEVICE_SHOW_IN_UI |\ + ACPI_STATUS_DEVICE_STATE_OK) +#define ACPI_STATUS_DEVICE_HIDDEN_ON (ACPI_STATUS_DEVICE_PRESENT |\ + ACPI_STATUS_DEVICE_ENABLED |\ + ACPI_STATUS_DEVICE_STATE_OK) + +/* ACPI Op/Prefix Codes */ +enum { + ZERO_OP = 0x00, + ONE_OP = 0x01, + ALIAS_OP = 0x06, + NAME_OP = 0x08, + BYTE_PREFIX = 0x0A, + WORD_PREFIX = 0x0B, + DWORD_PREFIX = 0x0C, + STRING_PREFIX = 0x0D, + QWORD_PREFIX = 0x0E, + SCOPE_OP = 0x10, + BUFFER_OP = 0x11, + PACKAGE_OP = 0x12, + VARIABLE_PACKAGE_OP = 0x13, + METHOD_OP = 0x14, + EXTERNAL_OP = 0x15, + DUAL_NAME_PREFIX = 0x2E, + MULTI_NAME_PREFIX = 0x2F, + EXT_OP_PREFIX = 0x5B, + MUTEX_OP = 0x01, + EVENT_OP = 0x01, + SF_RIGHT_OP = 0x10, + SF_LEFT_OP = 0x11, + COND_REFOF_OP = 0x12, + CREATEFIELD_OP = 0x13, + LOAD_TABLE_OP = 0x1f, + LOAD_OP = 0x20, + STALL_OP = 0x21, + SLEEP_OP = 0x22, + ACQUIRE_OP = 0x23, + SIGNAL_OP = 0x24, + WAIT_OP = 0x25, + RST_OP = 0x26, + RELEASE_OP = 0x27, + FROM_BCD_OP = 0x28, + TO_BCD_OP = 0x29, + UNLOAD_OP = 0x2A, + REVISON_OP = 0x30, + DEBUG_OP = 0x31, + FATAL_OP = 0x32, + TIMER_OP = 0x33, + OPREGION_OP = 0x80, + FIELD_OP = 0x81, + DEVICE_OP = 0x82, + PROCESSOR_OP = 0x83, + POWER_RES_OP = 0x84, + THERMAL_ZONE_OP = 0x85, + INDEX_FIELD_OP = 0x86, + BANK_FIELD_OP = 0x87, + DATA_REGION_OP = 0x88, + ROOT_PREFIX = 0x5C, + PARENT_PREFIX = 0x5E, + LOCAL0_OP = 0x60, + LOCAL1_OP = 0x61, + LOCAL2_OP = 0x62, + LOCAL3_OP = 0x63, + LOCAL4_OP = 0x64, + LOCAL5_OP = 0x65, + LOCAL6_OP = 0x66, + LOCAL7_OP = 0x67, + ARG0_OP = 0x68, + ARG1_OP = 0x69, + ARG2_OP = 0x6A, + ARG3_OP = 0x6B, + ARG4_OP = 0x6C, + ARG5_OP = 0x6D, + ARG6_OP = 0x6E, + STORE_OP = 0x70, + REF_OF_OP = 0x71, + ADD_OP = 0x72, + CONCATENATE_OP = 0x73, + SUBTRACT_OP = 0x74, + INCREMENT_OP = 0x75, + DECREMENT_OP = 0x76, + MULTIPLY_OP = 0x77, + DIVIDE_OP = 0x78, + SHIFT_LEFT_OP = 0x79, + SHIFT_RIGHT_OP = 0x7A, + AND_OP = 0x7B, + NAND_OP = 0x7C, + OR_OP = 0x7D, + NOR_OP = 0x7E, + XOR_OP = 0x7F, + NOT_OP = 0x80, + FD_SHIFT_LEFT_BIT_OR = 0x81, + FD_SHIFT_RIGHT_BIT_OR = 0x82, + DEREF_OP = 0x83, + CONCATENATE_TEMP_OP = 0x84, + MOD_OP = 0x85, + NOTIFY_OP = 0x86, + SIZEOF_OP = 0x87, + INDEX_OP = 0x88, + MATCH_OP = 0x89, + CREATE_DWORD_OP = 0x8A, + CREATE_WORD_OP = 0x8B, + CREATE_BYTE_OP = 0x8C, + CREATE_BIT_OP = 0x8D, + OBJ_TYPE_OP = 0x8E, + CREATE_QWORD_OP = 0x8F, + LAND_OP = 0x90, + LOR_OP = 0x91, + LNOT_OP = 0x92, + LEQUAL_OP = 0x93, + LGREATER_OP = 0x94, + LLESS_OP = 0x95, + TO_BUFFER_OP = 0x96, + TO_DEC_STRING_OP = 0x97, + TO_HEX_STRING_OP = 0x98, + TO_INTEGER_OP = 0x99, + TO_STRING_OP = 0x9C, + CP_OBJ_OP = 0x9D, + MID_OP = 0x9E, + CONTINUE_OP = 0x9F, + IF_OP = 0xA0, + ELSE_OP = 0xA1, + WHILE_OP = 0xA2, + NOOP_OP = 0xA3, + RETURN_OP = 0xA4, + BREAK_OP = 0xA5, + COMMENT_OP = 0xA9, + BREAKPIONT_OP = 0xCC, + ONES_OP = 0xFF, +}; + +#define FIELDLIST_OFFSET(X) { .type = OFFSET, \ + .name = "",\ + .bits = X * 8, \ + } +#define FIELDLIST_NAMESTR(X, Y) { .type = NAME_STRING, \ + .name = X, \ + .bits = Y, \ + } + +#define FIELD_ANYACC 0 +#define FIELD_BYTEACC 1 +#define FIELD_WORDACC 2 +#define FIELD_DWORDACC 3 +#define FIELD_QWORDACC 4 +#define FIELD_BUFFERACC 5 +#define FIELD_NOLOCK (0<<4) +#define FIELD_LOCK (1<<4) +#define FIELD_PRESERVE (0<<5) +#define FIELD_WRITEASONES (1<<5) +#define FIELD_WRITEASZEROS (2<<5) + +enum field_type { + OFFSET, + NAME_STRING, + FIELD_TYPE_MAX, +}; + +struct fieldlist { + enum field_type type; + const char *name; + u32 bits; +}; + +#define OPREGION(rname, space, offset, len) {.name = rname, \ + .regionspace = space, \ + .regionoffset = offset, \ + .regionlen = len, \ + } + +enum region_space { + SYSTEMMEMORY, + SYSTEMIO, + PCI_CONFIG, + EMBEDDEDCONTROL, + SMBUS, + CMOS, + PCIBARTARGET, + IPMI, + GPIO_REGION, + GPSERIALBUS, + PCC, + FIXED_HARDWARE = 0x7F, + REGION_SPACE_MAX, +}; + +struct opregion { + const char *name; + enum region_space regionspace; + unsigned long regionoffset; + unsigned long regionlen; +}; + +#define DSM_UUID(DSM_UUID, DSM_CALLBACKS, DSM_COUNT, DSM_ARG) \ + { .uuid = DSM_UUID, \ + .callbacks = DSM_CALLBACKS, \ + .count = DSM_COUNT, \ + .arg = DSM_ARG, \ + } + +struct dsm_uuid { + const char *uuid; + void (**callbacks)(void *); + size_t count; + void *arg; +}; + +/*version 1 has 15 fields, version 2 has 19, and version 3 has 21 */ +enum cppc_fields { + CPPC_HIGHEST_PERF, /* can be DWORD */ + CPPC_NOMINAL_PERF, /* can be DWORD */ + CPPC_LOWEST_NONL_PERF, /* can be DWORD */ + CPPC_LOWEST_PERF, /* can be DWORD */ + CPPC_GUARANTEED_PERF, + CPPC_DESIRED_PERF, + CPPC_MIN_PERF, + CPPC_MAX_PERF, + CPPC_PERF_REDUCE_TOLERANCE, + CPPC_TIME_WINDOW, + CPPC_COUNTER_WRAP, /* can be DWORD */ + CPPC_REF_PERF_COUNTER, + CPPC_DELIVERED_PERF_COUNTER, + CPPC_PERF_LIMITED, + CPPC_ENABLE, /* can be System I/O */ + CPPC_MAX_FIELDS_VER_1, + CPPC_AUTO_SELECT = /* can be DWORD */ + CPPC_MAX_FIELDS_VER_1, + CPPC_AUTO_ACTIVITY_WINDOW, + CPPC_PERF_PREF, + CPPC_REF_PERF, /* can be DWORD */ + CPPC_MAX_FIELDS_VER_2, + CPPC_LOWEST_FREQ = /* can be DWORD */ + CPPC_MAX_FIELDS_VER_2, + CPPC_NOMINAL_FREQ, /* can be DWORD */ + CPPC_MAX_FIELDS_VER_3, +}; + +struct cppc_config { + u32 version; /* must be 1, 2, or 3 */ + /* + * The generic acpi_addr_t structure is being used, though + * anything besides PPC or FFIXED generally requires checking + * if the OS has advertised support for it (via _OSC). + * + * NOTE: some fields permit DWORDs to be used. If you + * provide a System Memory register with all zeros (which + * represents unsupported) then this will be used as-is. + * Otherwise, a System Memory register with a 32-bit + * width will be converted into a DWORD field (the value + * of which will be the value of 'addrl'. Any other use + * of System Memory register is currently undefined. + * (i.e., if you have an actual need for System Memory + * then you'll need to adjust this kludge). + */ + acpi_addr_t regs[CPPC_MAX_FIELDS_VER_3]; +}; + +void acpigen_write_return_integer(uint64_t arg); +void acpigen_write_return_string(const char *arg); +void acpigen_write_len_f(void); +void acpigen_pop_len(void); +void acpigen_set_current(char *curr); +char *acpigen_get_current(void); +char *acpigen_write_package(int nr_el); +void acpigen_write_zero(void); +void acpigen_write_one(void); +void acpigen_write_ones(void); +void acpigen_write_byte(unsigned int data); +void acpigen_emit_byte(unsigned char data); +void acpigen_emit_ext_op(uint8_t op); +void acpigen_emit_word(unsigned int data); +void acpigen_emit_dword(unsigned int data); +void acpigen_emit_stream(const char *data, int size); +void acpigen_emit_string(const char *string); +void acpigen_emit_namestring(const char *namepath); +void acpigen_emit_eisaid(const char *eisaid); +void acpigen_write_word(unsigned int data); +void acpigen_write_dword(unsigned int data); +void acpigen_write_qword(uint64_t data); +void acpigen_write_integer(uint64_t data); +void acpigen_write_string(const char *string); +void acpigen_write_name_unicode(const char *name, const char *string); +void acpigen_write_name(const char *name); +void acpigen_write_name_zero(const char *name); +void acpigen_write_name_one(const char *name); +void acpigen_write_name_string(const char *name, const char *string); +void acpigen_write_name_dword(const char *name, uint32_t val); +void acpigen_write_name_qword(const char *name, uint64_t val); +void acpigen_write_name_byte(const char *name, uint8_t val); +void acpigen_write_name_integer(const char *name, uint64_t val); +void acpigen_write_coreboot_hid(enum coreboot_acpi_ids id); +void acpigen_write_scope(const char *name); +void acpigen_write_method(const char *name, int nargs); +void acpigen_write_method_serialized(const char *name, int nargs); +void acpigen_write_device(const char *name); +void acpigen_write_PPC(u8 nr); +void acpigen_write_PPC_NVS(void); +void acpigen_write_empty_PCT(void); +void acpigen_write_empty_PTC(void); +void acpigen_write_PRW(u32 wake, u32 level); +void acpigen_write_STA(uint8_t status); +void acpigen_write_TPC(const char *gnvs_tpc_limit); +void acpigen_write_PSS_package(u32 coreFreq, u32 power, u32 transLat, + u32 busmLat, u32 control, u32 status); +typedef enum { SW_ALL = 0xfc, SW_ANY = 0xfd, HW_ALL = 0xfe } PSD_coord; +void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype); +void acpigen_write_CST_package_entry(acpi_cstate_t *cstate); +void acpigen_write_CST_package(acpi_cstate_t *entry, int nentries); +typedef enum { CSD_HW_ALL = 0xfe } CSD_coord; +void acpigen_write_CSD_package(u32 domain, u32 numprocs, CSD_coord coordtype, + u32 index); +void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len); +void acpigen_write_processor_package(const char *name, + unsigned int first_core, + unsigned int core_count); +void acpigen_write_processor_cnot(const unsigned int number_of_cores); +void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list); +void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype); +void acpigen_write_mem32fixed(int readwrite, u32 base, u32 size); +void acpigen_write_io16(u16 min, u16 max, u8 align, u8 len, u8 decode16); +void acpigen_write_register_resource(const acpi_addr_t *addr); +void acpigen_write_resourcetemplate_header(void); +void acpigen_write_resourcetemplate_footer(void); +void acpigen_write_mainboard_resource_template(void); +void acpigen_write_mainboard_resources(const char *scope, const char *name); +void acpigen_write_irq(u16 mask); +void acpigen_write_uuid(const char *uuid); +void acpigen_write_power_res(const char *name, uint8_t level, uint16_t order, + const char *dev_states[], size_t dev_states_count); +void acpigen_write_sleep(uint64_t sleep_ms); +void acpigen_write_store(void); +void acpigen_write_store_ops(uint8_t src, uint8_t dst); +void acpigen_write_store_op_to_namestr(uint8_t src, const char *dst); +void acpigen_write_or(uint8_t arg1, uint8_t arg2, uint8_t res); +void acpigen_write_xor(uint8_t arg1, uint8_t arg2, uint8_t res); +void acpigen_write_and(uint8_t arg1, uint8_t arg2, uint8_t res); +void acpigen_write_not(uint8_t arg, uint8_t res); +void acpigen_write_debug_string(const char *str); +void acpigen_write_debug_integer(uint64_t val); +void acpigen_write_debug_op(uint8_t op); +void acpigen_write_if(void); +void acpigen_write_if_and(uint8_t arg1, uint8_t arg2); +void acpigen_write_if_lequal_op_int(uint8_t op, uint64_t val); +void acpigen_write_if_lequal_namestr_int(const char *namestr, uint64_t val); +void acpigen_write_else(void); +void acpigen_write_to_buffer(uint8_t src, uint8_t dst); +void acpigen_write_to_integer(uint8_t src, uint8_t dst); +void acpigen_write_byte_buffer(uint8_t *arr, size_t size); +void acpigen_write_return_byte_buffer(uint8_t *arr, size_t size); +void acpigen_write_return_singleton_buffer(uint8_t arg); +void acpigen_write_return_byte(uint8_t arg); +void acpigen_write_upc(enum acpi_upc_type type); +void acpigen_write_pld(const struct acpi_pld *pld); +void acpigen_write_ADR(uint64_t adr); +void acpigen_write_ADR_pci_devfn(pci_devfn_t devfn); +void acpigen_write_ADR_pci_device(const struct device *dev); +/* + * Generate ACPI AML code for _DSM method. + * This function takes as input uuid for the device, set of callbacks and + * argument to pass into the callbacks. Callbacks should ensure that Local0 and + * Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks. + */ +void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *), + size_t count, void *arg); +void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count); + +/* + * Generate ACPI AML code for _CPC (Continuous Performance Control). + * Execute the package function once to create a global table, then + * execute the method function within each processor object to + * create a method that points to the global table. + */ +void acpigen_write_CPPC_package(const struct cppc_config *config); +void acpigen_write_CPPC_method(void); + +/* + * Generate ACPI AML code for _ROM method. + * This function takes as input ROM data and ROM length. + * The ROM length has to be multiple of 4096 and has to be less + * than the current implementation limit of 0x40000. + */ +void acpigen_write_rom(void *bios, const size_t length); +/* + * Generate ACPI AML code for OperationRegion + * This function takes input region name, region space, region offset & region + * length. + */ +void acpigen_write_opregion(struct opregion *opreg); +/* + * Generate ACPI AML code for Mutex + * This function takes mutex name and initial value. + */ +void acpigen_write_mutex(const char *name, const uint8_t flags); +/* + * Generate ACPI AML code for Acquire + * This function takes mutex name and privilege value. + */ +void acpigen_write_acquire(const char *name, const uint16_t val); +/* + * Generate ACPI AML code for Release + * This function takes mutex name. + */ +void acpigen_write_release(const char *name); +/* + * Generate ACPI AML code for Field + * This function takes input region name, fieldlist, count & flags. + */ +void acpigen_write_field(const char *name, const struct fieldlist *l, size_t count, + uint8_t flags); +/* + * Generate ACPI AML code for IndexField + * This function takes input index name, data name, fieldlist, count & flags. + */ +void acpigen_write_indexfield(const char *idx, const char *data, + struct fieldlist *l, size_t count, uint8_t flags); + +int get_cst_entries(acpi_cstate_t **); + +/* + * Soc-implemented functions for generating ACPI AML code for GPIO handling. All + * these functions are expected to use only Local5, Local6 and Local7 + * variables. If the functions call into another ACPI method, then there is no + * restriction on the use of Local variables. In case of get/read functions, + * return value is expected to be stored in Local0 variable. + * + * All functions return 0 on success and -1 on error. + */ + +/* Generate ACPI AML code to return Rx value of GPIO in Local0. */ +int acpigen_soc_read_rx_gpio(unsigned int gpio_num); + +/* Generate ACPI AML code to return Tx value of GPIO in Local0. */ +int acpigen_soc_get_tx_gpio(unsigned int gpio_num); + +/* Generate ACPI AML code to set Tx value of GPIO to 1. */ +int acpigen_soc_set_tx_gpio(unsigned int gpio_num); + +/* Generate ACPI AML code to set Tx value of GPIO to 0. */ +int acpigen_soc_clear_tx_gpio(unsigned int gpio_num); + +/* + * Helper functions for enabling/disabling Tx GPIOs based on the GPIO + * polarity. These functions end up calling acpigen_soc_{set,clear}_tx_gpio to + * make callbacks into SoC acpigen code. + * + * Returns 0 on success and -1 on error. + */ +int acpigen_enable_tx_gpio(struct acpi_gpio *gpio); +int acpigen_disable_tx_gpio(struct acpi_gpio *gpio); + +/* + * Helper function for getting a RX GPIO value based on the GPIO polarity. + * The return value is stored in Local0 variable. + * This function ends up calling acpigen_soc_get_rx_gpio to make callbacks + * into SoC acpigen code + */ +void acpigen_get_rx_gpio(struct acpi_gpio *gpio); + +/* refer to ACPI 6.4.3.5.3 Word Address Space Descriptor section for details */ +void acpigen_resource_word(u16 res_type, u16 gen_flags, u16 type_flags, u16 gran, + u16 range_min, u16 range_max, u16 translation, u16 length); +/* refer to ACPI 6.4.3.5.2 DWord Address Space Descriptor section for details */ +void acpigen_resource_dword(u16 res_type, u16 gen_flags, u16 type_flags, + u32 gran, u32 range_min, u32 range_max, u32 translation, u32 length); +/* refer to ACPI 6.4.3.5.1 QWord Address Space Descriptor section for details */ +void acpigen_resource_qword(u16 res_type, u16 gen_flags, u16 type_flags, + u64 gran, u64 range_min, u64 range_max, u64 translation, u64 length); + +#endif diff --git a/src/include/acpi/acpigen_dsm.h b/src/include/acpi/acpigen_dsm.h new file mode 100644 index 0000000..c51c12b --- /dev/null +++ b/src/include/acpi/acpigen_dsm.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#ifndef __ARCH_ACPIGEN_DSM_H__ +#define __ARCH_ACPIGEN_DSM_H__ + +#include <stdint.h> + +struct dsm_i2c_hid_config { + uint8_t hid_desc_reg_offset; +}; + +void acpigen_write_dsm_i2c_hid(struct dsm_i2c_hid_config *config); + +#endif /* __ARCH_ACPIGEN_DSM_H__ */ diff --git a/src/include/acpi/acpigen_ps2_keybd.h b/src/include/acpi/acpigen_ps2_keybd.h new file mode 100644 index 0000000..c0228bc --- /dev/null +++ b/src/include/acpi/acpigen_ps2_keybd.h @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __ACPIGEN_PS2_KEYBD_H__ +#define __ACPIGEN_PS2_KEYBD_H__ + +#include <types.h> + +enum ps2_action_key { + PS2_KEY_ABSENT = 0, + PS2_KEY_BACK, + PS2_KEY_FORWARD, + PS2_KEY_REFRESH, + PS2_KEY_FULLSCREEN, + PS2_KEY_OVERVIEW, + PS2_KEY_BRIGHTNESS_DOWN, + PS2_KEY_BRIGHTNESS_UP, + PS2_KEY_VOL_MUTE, + PS2_KEY_VOL_DOWN, + PS2_KEY_VOL_UP, + PS2_KEY_SNAPSHOT, + PS2_KEY_PRIVACY_SCRN_TOGGLE, + PS2_KEY_KBD_BKLIGHT_DOWN, + PS2_KEY_KBD_BKLIGHT_UP, + PS2_KEY_PLAY_PAUSE, + PS2_KEY_NEXT_TRACK, + PS2_KEY_PREV_TRACK, +}; + +#define PS2_MIN_TOP_ROW_KEYS 10 +#define PS2_MAX_TOP_ROW_KEYS 15 + +void acpigen_ps2_keyboard_dsd(const char *scope, uint8_t num_top_row_keys, + enum ps2_action_key action_keys[], + bool can_send_function_keys, + bool has_numeric_keypad, bool has_scrnlock_key); + +#endif /* __ACPIGEN_PS2_KEYBD_H__ */ diff --git a/src/include/cpu/cpu.h b/src/include/cpu/cpu.h index cdb6817..486059b 100644 --- a/src/include/cpu/cpu.h +++ b/src/include/cpu/cpu.h @@ -13,6 +13,12 @@ asmlinkage void secondary_cpu_init(unsigned int cpu_index); int cpu_phys_address_size(void);
+#if CONFIG(ARCH_X86) +uintptr_t cpu_get_lapic_addr(void); +#else +static uintptr_t cpu_get_lapic_addr(void) { return 0; } +#endif + #if ENV_RAMSTAGE #define __cpu_driver __attribute__((used, __section__(".rodata.cpu_driver"))) #else
build bot (Jenkins) has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 1:
(3 comments)
https://review.coreboot.org/c/coreboot/+/40929/1/src/include/acpi/acpigen.h File src/include/acpi/acpigen.h:
https://review.coreboot.org/c/coreboot/+/40929/1/src/include/acpi/acpigen.h@... PS1, Line 384: void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *), function definition argument 'void' should also have an identifier name
https://review.coreboot.org/c/coreboot/+/40929/1/src/include/acpi/acpigen.h@... PS1, Line 384: void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *), function definition argument 'void *' should also have an identifier name
https://review.coreboot.org/c/coreboot/+/40929/1/src/include/acpi/acpigen.h@... PS1, Line 438: int get_cst_entries(acpi_cstate_t **); function definition argument 'acpi_cstate_t **' should also have an identifier name
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 1: Code-Review-2
Incorrect push.
Furquan Shaikh has uploaded a new patch set (#2). ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
cpu: Add a helper function cpu_get_lapic_addr
This change adds a helper function cpu_get_lapic_addr() that returns LOCAL_APIC_ADDR for x86 whereas 0 for non-x86 platforms. This is being done in preparation to move all ACPI table support in coreboot out of arch/x86.
BUG=b:155428745
Change-Id: I4d9c50ee46804164712aaa22be1b434f800871ec Signed-off-by: Furquan Shaikh furquan@google.com --- M src/arch/x86/acpi.c M src/arch/x86/cpu.c M src/include/cpu/cpu.h 3 files changed, 12 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/40929/2
Furquan Shaikh has removed a vote from this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Removed Code-Review-2 by Furquan Shaikh furquan@google.com
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 4:
I guess lapic is very x86 specific, but rather than a lot of #ifdefs in arch-independent code you could define these in the arch-dependent cpu headers.
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 4:
Patch Set 4:
I guess lapic is very x86 specific, but rather than a lot of #ifdefs in arch-independent code you could define these in the arch-dependent cpu headers.
Yeah, I thought about that but I was wondering if things would look really confusing having a "#define LOCAL_APIC_ADDR 0" in every cpu.h. I am fine either ways. Not having #ifdefs in arch-independent code is definitely nice.
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 4:
Patch Set 4:
Patch Set 4:
I guess lapic is very x86 specific, but rather than a lot of #ifdefs in arch-independent code you could define these in the arch-dependent cpu headers.
Yeah, I thought about that but I was wondering if things would look really confusing having a "#define LOCAL_APIC_ADDR 0" in every cpu.h. I am fine either ways. Not having #ifdefs in arch-independent code is definitely nice.
I also thought about this: #ifndef LOCAL_APIC_ADDR #define LOCAL_APIC_ADDR 0 #endif
But, there is always risk of silently breaking this on x86 platforms in some refactoring.
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 4:
Patch Set 4:
Patch Set 4:
Patch Set 4:
I guess lapic is very x86 specific, but rather than a lot of #ifdefs in arch-independent code you could define these in the arch-dependent cpu headers.
Yeah, I thought about that but I was wondering if things would look really confusing having a "#define LOCAL_APIC_ADDR 0" in every cpu.h. I am fine either ways. Not having #ifdefs in arch-independent code is definitely nice.
I also thought about this: #ifndef LOCAL_APIC_ADDR #define LOCAL_APIC_ADDR 0 #endif
But, there is always risk of silently breaking this on x86 platforms in some refactoring.
Weak function to the rescue.
Aaron Durbin has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 4: Code-Review+2
no one really moves apic addresses around. This should just work,and I'd argue we could just make this an inline.
Hello build bot (Jenkins), Duncan Laurie, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/40929
to look at the new patch set (#5).
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
cpu: Add a helper function cpu_get_lapic_addr
This change adds a helper function cpu_get_lapic_addr() that returns LOCAL_APIC_ADDR for x86. It also adds a weak default implementation which returns 0 if platform does not support LAPIC. This is being done in preparation to move all ACPI table support in coreboot out of arch/x86.
BUG=b:155428745
Change-Id: I4d9c50ee46804164712aaa22be1b434f800871ec Signed-off-by: Furquan Shaikh furquan@google.com --- M src/arch/x86/acpi.c M src/arch/x86/cpu.c M src/include/cpu/cpu.h 3 files changed, 16 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/40929/5
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 5:
Patch Set 4: Code-Review+2
no one really moves apic addresses around. This should just work,and I'd argue we could just make this an inline.
Are you saying just get rid of LOCAL_APIC_ADDR altogether from coreboot?
Aaron Durbin has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 6: Code-Review+2
Patch Set 5:
Patch Set 4: Code-Review+2
no one really moves apic addresses around. This should just work,and I'd argue we could just make this an inline.
Are you saying just get rid of LOCAL_APIC_ADDR altogether from coreboot?
No. I was just noting we probably could get away with just putting the decision in the header. It's not a big deal, though.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
Patch Set 6: Code-Review+2
Felix Held has submitted this change. ( https://review.coreboot.org/c/coreboot/+/40929 )
Change subject: cpu: Add a helper function cpu_get_lapic_addr ......................................................................
cpu: Add a helper function cpu_get_lapic_addr
This change adds a helper function cpu_get_lapic_addr() that returns LOCAL_APIC_ADDR for x86. It also adds a weak default implementation which returns 0 if platform does not support LAPIC. This is being done in preparation to move all ACPI table support in coreboot out of arch/x86.
BUG=b:155428745
Change-Id: I4d9c50ee46804164712aaa22be1b434f800871ec Signed-off-by: Furquan Shaikh furquan@google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/40929 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Aaron Durbin adurbin@chromium.org Reviewed-by: Duncan Laurie dlaurie@chromium.org --- M src/arch/x86/acpi.c M src/arch/x86/cpu.c M src/include/cpu/cpu.h 3 files changed, 16 insertions(+), 2 deletions(-)
Approvals: build bot (Jenkins): Verified Duncan Laurie: Looks good to me, approved Aaron Durbin: Looks good to me, approved
diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index 5c15a5e..8e7b51d 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -22,7 +22,6 @@ #include <device/pci.h> #include <cbmem.h> #include <commonlib/helpers.h> -#include <cpu/x86/lapic_def.h> #include <cpu/cpu.h> #include <cbfs.h> #include <version.h> @@ -222,6 +221,15 @@ return lapic_nmi->length; }
+__weak uintptr_t cpu_get_lapic_addr(void) +{ + /* + * If an architecture does not support LAPIC, this weak implementation returns LAPIC + * addr as 0. + */ + return 0; +} + void acpi_create_madt(acpi_madt_t *madt) { acpi_header_t *header = &(madt->header); @@ -242,7 +250,7 @@ header->length = sizeof(acpi_madt_t); header->revision = get_acpi_table_revision(MADT);
- madt->lapic_addr = LOCAL_APIC_ADDR; + madt->lapic_addr = cpu_get_lapic_addr(); if (CONFIG(ACPI_HAVE_PCAT_8259)) madt->flags |= 1;
diff --git a/src/arch/x86/cpu.c b/src/arch/x86/cpu.c index 1ee8fb3..b523768 100644 --- a/src/arch/x86/cpu.c +++ b/src/arch/x86/cpu.c @@ -354,3 +354,8 @@ } return -1; } + +uintptr_t cpu_get_lapic_addr(void) +{ + return LOCAL_APIC_ADDR; +} diff --git a/src/include/cpu/cpu.h b/src/include/cpu/cpu.h index cdb6817..db324b6 100644 --- a/src/include/cpu/cpu.h +++ b/src/include/cpu/cpu.h @@ -6,6 +6,7 @@ void cpu_initialize(unsigned int cpu_index); /* Returns default APIC id based on logical_cpu number or < 0 on failure. */ int cpu_get_apic_id(int logical_cpu); +uintptr_t cpu_get_lapic_addr(void); /* Function to keep track of cpu default apic_id */ void cpu_add_map_entry(unsigned int index); struct bus;