mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-15 17:34:43 +00:00
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 <maximilian.brune@9elements.com> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-by: Simon Glass <sjg@chromium.org> Cc: Simon Glass <sjg@chromium.org> Cc: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
0d28900dd1
commit
1c03efc014
4 changed files with 195 additions and 185 deletions
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
#include <log.h>
|
||||
#include <mapmem.h>
|
||||
#include <tables_csum.h>
|
||||
#include <serial.h>
|
||||
#include <version_string.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <dm/acpi.h>
|
||||
|
||||
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue