summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/acpi.c53
-rw-r--r--src/arch/x86/include/arch/acpi.h48
2 files changed, 100 insertions, 1 deletions
diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c
index bf9813cbfe..1b8aaae64b 100644
--- a/src/arch/x86/acpi.c
+++ b/src/arch/x86/acpi.c
@@ -772,6 +772,57 @@ void acpi_create_vfct(struct device *device,
header->checksum = acpi_checksum((void *)vfct, header->length);
}
+void acpi_create_ipmi(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)
+{
+ acpi_header_t *header = &(spmi->header);
+ memset((void *)spmi, 0, sizeof(struct acpi_spmi));
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "SPMI", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->asl_compiler_revision = asl_revision;
+ header->length = sizeof(struct acpi_spmi);
+ header->revision = get_acpi_table_revision(SPMI);
+
+ spmi->reserved = 1;
+
+ if (device->path.type == DEVICE_PATH_PCI) {
+ spmi->pci_device_flag = ACPI_IPMI_PCI_DEVICE_FLAG;
+ spmi->pci_bus = device->bus->secondary;
+ spmi->pci_device = device->path.pci.devfn >> 3;
+ spmi->pci_function = device->path.pci.devfn & 0x7;
+ } else if (type != IPMI_INTERFACE_SSIF) {
+ memcpy(spmi->uid, &uid, sizeof(spmi->uid));
+ }
+
+ spmi->base_address = *addr;
+ spmi->specification_revision = ipmi_revision;
+
+ spmi->interface_type = type;
+
+ if (gpe_interrupt >= 0 && gpe_interrupt < 32) {
+ spmi->gpe = gpe_interrupt;
+ spmi->interrupt_type |= ACPI_IPMI_INT_TYPE_SCI;
+ }
+ if (apic_interrupt > 0) {
+ spmi->global_system_interrupt = apic_interrupt;
+ spmi->interrupt_type |= ACPI_IPMI_INT_TYPE_APIC;
+ }
+
+ /* Calculate checksum. */
+ header->checksum = acpi_checksum((void *)spmi, header->length);
+}
+
void acpi_create_ivrs(acpi_ivrs_t *ivrs,
unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t *ivrs_struct,
unsigned long current))
@@ -1490,6 +1541,8 @@ int get_acpi_table_revision(enum acpi_tables table)
return 1;
case SLIT: /* ACPI 2.0 upto 6.3: 1 */
return 1;
+ case SPMI: /* IMPI 2.0 */
+ return 5;
case HPET: /* Currently 1. Table added in ACPI 2.0. */
return 1;
case VFCT: /* ACPI 2.0/3.0/4.0: 1 */
diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h
index dbf46a9b1b..e48b2da567 100644
--- a/src/arch/x86/include/arch/acpi.h
+++ b/src/arch/x86/include/arch/acpi.h
@@ -82,7 +82,7 @@ enum acpi_tables {
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
+ VFCT, NHLT, SPMI
};
/* RSDP (Root System Description Pointer) */
@@ -782,6 +782,43 @@ enum acpi_upc_type {
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 {
+ struct acpi_table_header 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. */
@@ -834,6 +871,15 @@ void acpi_create_vfct(struct device *device,
struct acpi_vfct *vfct_struct,
unsigned long current));
+void acpi_create_ipmi(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));