Attention is currently required from: Lance Zhao, Tim Wawrzynczak.
Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/75685?usp=email )
Change subject: WIP acpi: Add SPCR table ......................................................................
WIP acpi: Add SPCR table
Signed-off-by: Arthur Heymans arthur@aheymans.xyz Change-Id: I64e624c17a27b9215a8ba83bd6cbb2c0a7aa1dfc --- M src/acpi/acpi.c M src/include/acpi/acpi.h 2 files changed, 73 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/85/75685/1
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c index 4fdbd6f..5cd8e54 100644 --- a/src/acpi/acpi.c +++ b/src/acpi/acpi.c @@ -1822,6 +1822,60 @@ return coreboot_rsdp; }
+static void acpi_create_spcr(acpi_spcr_t *spcr) +{ + acpi_header_t *header = &(spcr->header); + struct lb_serial serial; + if (fill_lb_serial(&serial) != CB_SUCCESS) + return; + + memset((void *)spcr, 0, sizeof(acpi_spcr_t)); + + memcpy(header->signature, "SPCR", 4); + header->length = sizeof(acpi_spcr_t); + header->revision = get_acpi_table_revision(SPCR); + 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; + + /* 16550 compatible, TODO do we need others? */ + spcr->interface_type = 0; + assert(serial.type == LB_SERIAL_TYPE_IO_MAPPED + || serial.type == LB_SERIAL_TYPE_MEMORY_MAPPED); + spcr->base_address.space_id = serial.type == LB_SERIAL_TYPE_IO_MAPPED ? ACPI_ADDRESS_SPACE_IO : ACPI_ADDRESS_SPACE_MEMORY; + spcr->base_address.bit_width = serial.regwidth * 8; + spcr->base_address.bit_offset = 0; + spcr->base_address.access_size = serial.regwidth; + spcr->base_address.addrl = serial.baseaddr; + spcr->base_address.addrh = 0; + if (ENV_X86) + spcr->interrupt_type = IO_APIC_COMPATIBLE_INTERRUPT; + if (serial.type == LB_SERIAL_TYPE_IO_MAPPED) + spcr->interrupt_type |= PC_AT_COMPATIBLE_INTERRUPT; + /* TODO: provide callback for IRQ on non standard ports*/ + if (serial.type == LB_SERIAL_TYPE_IO_MAPPED) { + switch (serial.baseaddr) { + case 0x3f8: + spcr->irq = 4; + spcr->global_system_interrupt = 4; + break; + case 0x2f8: + spcr->irq = 3; + spcr->global_system_interrupt = 3; + break; + } + } + spcr->configured_baudrate = 0; /* Have the OS use whatever is currently set */ + spcr->parity = 0; + spcr->stop_bits = 1; + spcr->flow_control = 0; + spcr->terminal_type = 2; /* 2 = VT-UTF8 */ + spcr->language = 0; + spcr->pci_did = 0xffff; + spcr->pci_vid = 0xffff; +} + unsigned long write_acpi_tables(unsigned long start) { unsigned long current; @@ -1839,6 +1893,7 @@ acpi_madt_t *madt; acpi_lpit_t *lpit; acpi_bert_t *bert; + acpi_spcr_t *spcr; struct device *dev; unsigned long fw; size_t slic_size, dsdt_size; @@ -2090,6 +2145,15 @@ } }
+ printk(BIOS_DEBUG, "ACPI: * SPCR\n"); + spcr = (acpi_spcr_t *)current; + acpi_create_spcr(spcr); + if (spcr->header.length > sizeof(acpi_spcr_t)) { + current += spcr->header.length; + acpi_add_table(rsdp, spcr); + } + current = acpi_align_current(current); + printk(BIOS_DEBUG, "current = %lx\n", current);
for (dev = all_devices; dev; dev = dev->next) { @@ -2251,6 +2315,8 @@ return 1; case LPIT: /* ACPI 5.1 up to 6.3: 0 */ return 0; + case SPCR: + return 4; default: return -1; } diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h index 548b4c3..3676a23 100644 --- a/src/include/acpi/acpi.h +++ b/src/include/acpi/acpi.h @@ -75,6 +75,7 @@ /* Tables defined by ACPI and used by coreboot */ BERT, CEDT, DBG2, DMAR, DSDT, EINJ, FACS, FADT, HEST, HMAT, HPET, IVRS, MADT, MCFG, RSDP, RSDT, SLIT, SRAT, SSDT, TCPA, TPM2, XSDT, ECDT, LPIT, + SPCR, /* Additional proprietary tables used by coreboot */ VFCT, NHLT, SPMI, CRAT }; @@ -1328,6 +1329,12 @@ } __packed acpi_spcr_t; _Static_assert(sizeof(acpi_spcr_t) == 88, "acpi_spcr_t must have an 88 byte size\n");
+#define PC_AT_COMPATIBLE_INTERRUPT (1 << 0) +#define IO_APIC_COMPATIBLE_INTERRUPT (1 << 1) +#define IO_SAPIC_COMPATIBLE_INTERRUPT (1 << 2) +#define ARMH_GIC_COMPATIBLE_INTERRUPT (1 << 3) +#define RISCV_PLIC_COMPATIBLE_INTERRUPT (1 << 4) + uintptr_t get_coreboot_rsdp(void); void acpi_create_einj(acpi_einj_t *einj, uintptr_t addr, u8 actions);