From: Maximilian Brune Date: Wed, 23 Oct 2024 13:19:44 +0000 (+0200) Subject: acpi: x86: Move SPCR and DBG2 into common code X-Git-Url: http://git.dujemihanovic.xyz/img/static/%7B%7B%20%24image.RelPermalink%20%7D%7D?a=commitdiff_plain;h=1c03efc01485e2f0ba0a8c7eaa94b1bbbf393251;p=u-boot.git acpi: x86: Move SPCR and DBG2 into common code This moves the SPCR and DBG2 table generation into common code, so that they can be used by architectures other than x86. Signed-off-by: Maximilian Brune Signed-off-by: Patrick Rudolph Reviewed-by: Simon Glass Cc: Simon Glass Cc: Bin Meng --- diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 57e41654ce..e617524617 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -45,17 +45,6 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base, */ int acpi_write_hpet(struct acpi_ctx *ctx); -/** - * acpi_write_dbg2_pci_uart() - Write out a DBG2 table - * - * @ctx: Current ACPI context - * @dev: Debug UART device to describe - * @access_size: Access size for UART (e.g. ACPI_ACCESS_SIZE_DWORD_ACCESS) - * Return: 0 if OK, -ve on error - */ -int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, - uint access_size); - /** * acpi_create_gnvs() - Create a GNVS (Global Non Volatile Storage) table * diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index e38ce19ff7..08fd1e54ce 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -279,140 +279,6 @@ static int acpi_write_tpm2(struct acpi_ctx *ctx, } ACPI_WRITER(5tpm2, "TPM2", acpi_write_tpm2, 0); -int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry) -{ - struct serial_device_info serial_info = {0}; - ulong serial_address, serial_offset; - struct acpi_table_header *header; - struct acpi_spcr *spcr; - struct udevice *dev; - uint serial_config; - uint serial_width; - int access_size; - int space_id; - int ret = -ENODEV; - - spcr = ctx->current; - header = &spcr->header; - - memset(spcr, '\0', sizeof(struct acpi_spcr)); - - /* Fill out header fields */ - acpi_fill_header(header, "SPCR"); - header->length = sizeof(struct acpi_spcr); - header->revision = 2; - - /* Read the device once, here. It is reused below */ - dev = gd->cur_serial_dev; - if (dev) - ret = serial_getinfo(dev, &serial_info); - if (ret) - serial_info.type = SERIAL_CHIP_UNKNOWN; - - /* Encode chip type */ - switch (serial_info.type) { - case SERIAL_CHIP_16550_COMPATIBLE: - spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE; - break; - case SERIAL_CHIP_UNKNOWN: - default: - spcr->interface_type = ACPI_DBG2_UNKNOWN; - break; - } - - /* Encode address space */ - switch (serial_info.addr_space) { - case SERIAL_ADDRESS_SPACE_MEMORY: - space_id = ACPI_ADDRESS_SPACE_MEMORY; - break; - case SERIAL_ADDRESS_SPACE_IO: - default: - space_id = ACPI_ADDRESS_SPACE_IO; - break; - } - - serial_width = serial_info.reg_width * 8; - serial_offset = serial_info.reg_offset << serial_info.reg_shift; - serial_address = serial_info.addr + serial_offset; - - /* Encode register access size */ - switch (serial_info.reg_shift) { - case 0: - access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; - break; - case 1: - access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; - break; - case 2: - access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; - break; - case 3: - access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS; - break; - default: - access_size = ACPI_ACCESS_SIZE_UNDEFINED; - break; - } - - debug("UART type %u @ %lx\n", spcr->interface_type, serial_address); - - /* Fill GAS */ - spcr->serial_port.space_id = space_id; - spcr->serial_port.bit_width = serial_width; - spcr->serial_port.bit_offset = 0; - spcr->serial_port.access_size = access_size; - spcr->serial_port.addrl = lower_32_bits(serial_address); - spcr->serial_port.addrh = upper_32_bits(serial_address); - - /* Encode baud rate */ - switch (serial_info.baudrate) { - case 9600: - spcr->baud_rate = 3; - break; - case 19200: - spcr->baud_rate = 4; - break; - case 57600: - spcr->baud_rate = 6; - break; - case 115200: - spcr->baud_rate = 7; - break; - default: - spcr->baud_rate = 0; - break; - } - - serial_config = SERIAL_DEFAULT_CONFIG; - if (dev) - ret = serial_getconfig(dev, &serial_config); - - spcr->parity = SERIAL_GET_PARITY(serial_config); - spcr->stop_bits = SERIAL_GET_STOP(serial_config); - - /* No PCI devices for now */ - spcr->pci_device_id = 0xffff; - spcr->pci_vendor_id = 0xffff; - - /* - * SPCR has no clue if the UART base clock speed is different - * to the default one. However, the SPCR 1.04 defines baud rate - * 0 as a preconfigured state of UART and OS is supposed not - * to touch the configuration of the serial device. - */ - if (serial_info.clock != SERIAL_DEFAULT_CLOCK) - spcr->baud_rate = 0; - - /* Fix checksum */ - header->checksum = table_compute_checksum((void *)spcr, header->length); - - acpi_add_table(ctx, spcr); - acpi_inc(ctx, spcr->header.length); - - return 0; -} -ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0); - int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry) { ulong addr; @@ -515,46 +381,6 @@ int acpi_write_hpet(struct acpi_ctx *ctx) return 0; } -int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, - uint access_size) -{ - struct acpi_dbg2_header *dbg2 = ctx->current; - char path[ACPI_PATH_MAX]; - struct acpi_gen_regaddr address; - phys_addr_t addr; - int ret; - - if (!device_active(dev)) { - log_info("Device not enabled\n"); - return -EACCES; - } - /* - * PCI devices don't remember their resource allocation information in - * U-Boot at present. We assume that MMIO is used for the UART and that - * the address space is 32 bytes: ns16550 uses 8 registers of up to - * 32-bits each. This is only for debugging so it is not a big deal. - */ - addr = dm_pci_read_bar32(dev, 0); - log_debug("UART addr %lx\n", (ulong)addr); - - memset(&address, '\0', sizeof(address)); - address.space_id = ACPI_ADDRESS_SPACE_MEMORY; - address.addrl = (uint32_t)addr; - address.addrh = (uint32_t)((addr >> 32) & 0xffffffff); - address.access_size = access_size; - - ret = acpi_device_path(dev, path, sizeof(path)); - if (ret) - return log_msg_ret("path", ret); - acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT, - ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path); - - acpi_inc_align(ctx, dbg2->header.length); - acpi_add_table(ctx, dbg2); - - return 0; -} - void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs, void *dsdt) { diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index 15fd61a51d..a372435492 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -913,6 +913,17 @@ static inline int acpi_add_fadt(struct acpi_ctx *ctx, struct acpi_fadt *fadt) return 0; } +/** + * acpi_write_dbg2_pci_uart() - Write out a DBG2 table + * + * @ctx: Current ACPI context + * @dev: Debug UART device to describe + * @access_size: Access size for UART (e.g. ACPI_ACCESS_SIZE_DWORD_ACCESS) + * Return: 0 if OK, -ve on error + */ +int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, + uint access_size); + /** * acpi_write_rsdp() - Write out an RSDP indicating where the ACPI tables are * diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 6dbfdb22de..c9ddcca8cb 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -262,3 +264,185 @@ void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, header->length = current - (uintptr_t)dbg2; header->checksum = table_compute_checksum(dbg2, header->length); } + +int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, + uint access_size) +{ + struct acpi_dbg2_header *dbg2 = ctx->current; + char path[ACPI_PATH_MAX]; + struct acpi_gen_regaddr address; + u64 addr; + int ret; + + if (!device_active(dev)) { + log_info("Device not enabled\n"); + return -EACCES; + } + /* + * PCI devices don't remember their resource allocation information in + * U-Boot at present. We assume that MMIO is used for the UART and that + * the address space is 32 bytes: ns16550 uses 8 registers of up to + * 32-bits each. This is only for debugging so it is not a big deal. + */ + addr = dm_pci_read_bar32(dev, 0); + log_debug("UART addr %lx\n", (ulong)addr); + + ret = acpi_device_path(dev, path, sizeof(path)); + if (ret) + return log_msg_ret("path", ret); + + memset(&address, '\0', sizeof(address)); + address.space_id = ACPI_ADDRESS_SPACE_MEMORY; + address.addrl = (uint32_t)addr; + address.addrh = (uint32_t)((addr >> 32) & 0xffffffff); + address.access_size = access_size; + + ret = acpi_device_path(dev, path, sizeof(path)); + if (ret) + return log_msg_ret("path", ret); + acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT, + ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path); + + acpi_inc_align(ctx, dbg2->header.length); + acpi_add_table(ctx, dbg2); + + return 0; +} + +static int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry) +{ + struct serial_device_info serial_info = {0}; + ulong serial_address, serial_offset; + struct acpi_table_header *header; + struct acpi_spcr *spcr; + struct udevice *dev; + uint serial_config; + uint serial_width; + int access_size; + int space_id; + int ret = -ENODEV; + + spcr = ctx->current; + header = &spcr->header; + + memset(spcr, '\0', sizeof(struct acpi_spcr)); + + /* Fill out header fields */ + acpi_fill_header(header, "SPCR"); + header->length = sizeof(struct acpi_spcr); + header->revision = 2; + + /* Read the device once, here. It is reused below */ + dev = gd->cur_serial_dev; + if (dev) + ret = serial_getinfo(dev, &serial_info); + if (ret) + serial_info.type = SERIAL_CHIP_UNKNOWN; + + /* Encode chip type */ + switch (serial_info.type) { + case SERIAL_CHIP_16550_COMPATIBLE: + spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE; + break; + case SERIAL_CHIP_PL01X: + spcr->interface_type = ACPI_DBG2_ARM_PL011; + break; + case SERIAL_CHIP_UNKNOWN: + default: + spcr->interface_type = ACPI_DBG2_UNKNOWN; + break; + } + + /* Encode address space */ + switch (serial_info.addr_space) { + case SERIAL_ADDRESS_SPACE_MEMORY: + space_id = ACPI_ADDRESS_SPACE_MEMORY; + break; + case SERIAL_ADDRESS_SPACE_IO: + default: + space_id = ACPI_ADDRESS_SPACE_IO; + break; + } + + serial_width = serial_info.reg_width * 8; + serial_offset = serial_info.reg_offset << serial_info.reg_shift; + serial_address = serial_info.addr + serial_offset; + + /* Encode register access size */ + switch (serial_info.reg_shift) { + case 0: + access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; + break; + case 1: + access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; + break; + case 2: + access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + break; + case 3: + access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS; + break; + default: + access_size = ACPI_ACCESS_SIZE_UNDEFINED; + break; + } + + debug("UART type %u @ %lx\n", spcr->interface_type, serial_address); + + /* Fill GAS */ + spcr->serial_port.space_id = space_id; + spcr->serial_port.bit_width = serial_width; + spcr->serial_port.bit_offset = 0; + spcr->serial_port.access_size = access_size; + spcr->serial_port.addrl = lower_32_bits(serial_address); + spcr->serial_port.addrh = upper_32_bits(serial_address); + + /* Encode baud rate */ + switch (serial_info.baudrate) { + case 9600: + spcr->baud_rate = 3; + break; + case 19200: + spcr->baud_rate = 4; + break; + case 57600: + spcr->baud_rate = 6; + break; + case 115200: + spcr->baud_rate = 7; + break; + default: + spcr->baud_rate = 0; + break; + } + + serial_config = SERIAL_DEFAULT_CONFIG; + if (dev) + ret = serial_getconfig(dev, &serial_config); + + spcr->parity = SERIAL_GET_PARITY(serial_config); + spcr->stop_bits = SERIAL_GET_STOP(serial_config); + + /* No PCI devices for now */ + spcr->pci_device_id = 0xffff; + spcr->pci_vendor_id = 0xffff; + + /* + * SPCR has no clue if the UART base clock speed is different + * to the default one. However, the SPCR 1.04 defines baud rate + * 0 as a preconfigured state of UART and OS is supposed not + * to touch the configuration of the serial device. + */ + if (serial_info.clock != SERIAL_DEFAULT_CLOCK) + spcr->baud_rate = 0; + + /* Fix checksum */ + header->checksum = table_compute_checksum((void *)spcr, header->length); + + acpi_add_table(ctx, spcr); + acpi_inc(ctx, spcr->header.length); + + return 0; +} + +ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0);