Message ID | 20180922130505.77474-3-andriy.shevchenko@linux.intel.com |
---|---|
State | Superseded |
Delegated to: | Bin Meng |
Headers | show |
Series | ACPI: Generate SPCR table | expand |
On 09/22/2018 03:05 PM, Andy Shevchenko wrote: > TBD Same remark as Patch 1 > > 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; > + > + /* 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; >
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
On Tue, Sep 25, 2018 at 10:27:33AM +0800, Bin Meng wrote: > On Sat, Sep 22, 2018 at 9:05 PM Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: > > +/* 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; > > +}; > 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? No idea about Windows, but there are two statements: - *not all* should be filled, otherwise it would be contradictory (PCI vs. non-PCI device, for example) - Linux doesn't use all of them, indeed
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; + + /* 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;
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(+)