
Hi Andy,
On Sat, Sep 22, 2018 at 9:05 PM Andy Shevchenko andriy.shevchenko@linux.intel.com wrote:
TBD
Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com
arch/x86/include/asm/acpi_table.h | 25 ++++++++++ arch/x86/lib/acpi_table.c | 82 +++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+)
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 95fae036f6..27435871b9 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -303,6 +303,31 @@ struct acpi_mcfg_mmconfig { /* ACPI global NVS structure */ struct acpi_global_nvs;
+/* SPCR (Serial Port Console Redirection table) */ +struct __packed acpi_spcr {
struct acpi_table_header header; /* Common ACPI table header */
u8 interface_type; /* 0=full 16550, 1=subset of 16550 */
u8 reserved[3];
struct acpi_gen_regaddr serial_port; /* The base address of the Serial Port register set */
u8 interrupt_type;
u8 pc_interrupt;
u32 interrupt; /* Global system interrupt */
u8 baud_rate;
u8 parity;
u8 stop_bits;
u8 flow_control;
u8 terminal_type;
u8 reserved1;
u16 pci_device_id; /* Must be 0xffff if not PCI device */
u16 pci_vendor_id; /* Must be 0xffff if not PCI device */
u8 pci_bus;
u8 pci_device;
u8 pci_function;
u32 pci_flags;
u8 pci_segment;
u32 reserved2;
+};
/* These can be used by the target port */
void acpi_fill_header(struct acpi_table_header *header, char *signature); diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index c6b2026613..551a78b11a 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -12,6 +12,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> @@ -338,6 +339,79 @@ 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 info = {0};
int access_size;
int ret;
/* Fill out header fields */
acpi_fill_header(header, "SPCR");
header->length = sizeof(struct acpi_spcr);
header->revision = 2;
ret = serial_getinfo(&info);
if (ret)
debug("Can't get information of serial device: %d\n", ret);
/* Encode baud rate */
switch (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;
}
/* Encode register access size */
switch (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;
}
spcr->serial_port.space_id = ACPI_ADDRESS_SPACE_MEMORY;
spcr->serial_port.bit_width = info.reg_width;
spcr->serial_port.bit_offset = info.reg_offset;
spcr->serial_port.access_size = access_size;
spcr->serial_port.addrl = info.addr >> 0;
spcr->serial_port.addrh = info.addr >> 32;
/* Hard coded values for now */
spcr->parity = 0;
spcr->stop_bits = 1;
/* No PCI devices for now */
spcr->pci_device_id = 0xffff;
spcr->pci_vendor_id = 0xffff;
I see not every member of 'struct __packed acpi_spcr' is populated. Are they not used by kernel? If kernel does not use it, it is used by Windows?
/* 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
*/ @@ -352,6 +426,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;
@@ -440,6 +515,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;
--
Regards, Bin