mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
x86: acpi: Generate SPCR table
Microsoft specifies a SPCR (Serial Port Console Redirection Table) [1]. Let's provide it in U-Boot. [1]: https://docs.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
f3275aa4a1
commit
b288cd9600
2 changed files with 120 additions and 0 deletions
|
@ -327,6 +327,8 @@ struct acpi_global_nvs;
|
|||
#define ACPI_DBG2_USB_XHCI 0x0000
|
||||
#define ACPI_DBG2_USB_EHCI 0x0001
|
||||
|
||||
#define ACPI_DBG2_UNKNOWN 0x00FF
|
||||
|
||||
/* SPCR (Serial Port Console Redirection table) */
|
||||
struct __packed acpi_spcr {
|
||||
struct acpi_table_header header;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <serial.h>
|
||||
#include <version.h>
|
||||
#include <asm/acpi/global_nvs.h>
|
||||
#include <asm/acpi_table.h>
|
||||
|
@ -336,6 +337,115 @@ static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
|
|||
header->checksum = table_compute_checksum((void *)mcfg, header->length);
|
||||
}
|
||||
|
||||
static void acpi_create_spcr(struct acpi_spcr *spcr)
|
||||
{
|
||||
struct acpi_table_header *header = &(spcr->header);
|
||||
struct serial_device_info serial_info = {0};
|
||||
ulong serial_address, serial_offset;
|
||||
uint serial_config;
|
||||
uint serial_width;
|
||||
int access_size;
|
||||
int space_id;
|
||||
int ret;
|
||||
|
||||
/* Fill out header fields */
|
||||
acpi_fill_header(header, "SPCR");
|
||||
header->length = sizeof(struct acpi_spcr);
|
||||
header->revision = 2;
|
||||
|
||||
ret = serial_getinfo(&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;
|
||||
}
|
||||
|
||||
ret = serial_getconfig(&serial_config);
|
||||
if (ret)
|
||||
serial_config = SERIAL_DEFAULT_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;
|
||||
|
||||
/* Fix checksum */
|
||||
header->checksum = table_compute_checksum((void *)spcr, header->length);
|
||||
}
|
||||
|
||||
/*
|
||||
* QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
|
||||
*/
|
||||
|
@ -350,6 +460,7 @@ ulong write_acpi_tables(ulong start)
|
|||
struct acpi_fadt *fadt;
|
||||
struct acpi_mcfg *mcfg;
|
||||
struct acpi_madt *madt;
|
||||
struct acpi_spcr *spcr;
|
||||
int i;
|
||||
|
||||
current = start;
|
||||
|
@ -438,6 +549,13 @@ ulong write_acpi_tables(ulong start)
|
|||
acpi_add_table(rsdp, mcfg);
|
||||
current = ALIGN(current, 16);
|
||||
|
||||
debug("ACPI: * SPCR\n");
|
||||
spcr = (struct acpi_spcr *)current;
|
||||
acpi_create_spcr(spcr);
|
||||
current += spcr->header.length;
|
||||
acpi_add_table(rsdp, spcr);
|
||||
current = ALIGN(current, 16);
|
||||
|
||||
debug("current = %x\n", current);
|
||||
|
||||
acpi_rsdp_addr = (unsigned long)rsdp;
|
||||
|
|
Loading…
Reference in a new issue