u-boot/arch/x86/cpu/baytrail/acpi.c
Heinrich Schuchardt a083ae71e0 acpi: use 64-bit addresses in FADT table
Fields X_FIRMWAE_CTRL and X_DSDT must be 64bit wide. Convert pointers to
to uintptr_t to fill these.

If field X_FIRMWARE_CTRL is filled, field FIRMWARE must be ignored. If
field X_DSDT is filled, field DSDT must be ignored. We should not fill
unused fields.

See the field definitions in chapter "5.2.9 Fixed ACPI Description Table
(FADT)" of the ACPI Specification 6.5.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
2024-01-07 13:45:07 -07:00

211 lines
6.2 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <log.h>
#include <mapmem.h>
#include <acpi/acpi_s3.h>
#include <acpi/acpi_table.h>
#include <asm/io.h>
#include <asm/tables.h>
#include <asm/arch/global_nvs.h>
#include <asm/arch/iomap.h>
#include <dm/uclass-internal.h>
static int baytrail_write_fadt(struct acpi_ctx *ctx,
const struct acpi_writer *entry)
{
struct acpi_table_header *header;
struct acpi_fadt *fadt;
fadt = ctx->current;
header = &fadt->header;
u16 pmbase = ACPI_BASE_ADDRESS;
memset(fadt, '\0', sizeof(struct acpi_fadt));
acpi_fill_header(header, "FACP");
header->length = sizeof(struct acpi_fadt);
header->revision = 4;
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
fadt->sci_int = 9;
fadt->smi_cmd = 0;
fadt->acpi_enable = 0;
fadt->acpi_disable = 0;
fadt->s4bios_req = 0;
fadt->pstate_cnt = 0;
fadt->pm1a_evt_blk = pmbase;
fadt->pm1b_evt_blk = 0x0;
fadt->pm1a_cnt_blk = pmbase + 0x4;
fadt->pm1b_cnt_blk = 0x0;
fadt->pm2_cnt_blk = pmbase + 0x50;
fadt->pm_tmr_blk = pmbase + 0x8;
fadt->gpe0_blk = pmbase + 0x20;
fadt->gpe1_blk = 0;
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm2_cnt_len = 1;
fadt->pm_tmr_len = 4;
fadt->gpe0_blk_len = 8;
fadt->gpe1_blk_len = 0;
fadt->gpe1_base = 0;
fadt->cst_cnt = 0;
fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
fadt->flush_size = 0;
fadt->flush_stride = 0;
fadt->duty_offset = 1;
fadt->duty_width = 0;
fadt->day_alrm = 0x0d;
fadt->mon_alrm = 0x00;
fadt->century = 0x00;
fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_RESET_REGISTER |
ACPI_FADT_PLATFORM_CLOCK;
fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->reset_reg.bit_width = 8;
fadt->reset_reg.bit_offset = 0;
fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
fadt->reset_reg.addrl = IO_PORT_RESET;
fadt->reset_reg.addrh = 0;
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
fadt->x_pm1a_evt_blk.bit_offset = 0;
fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
fadt->x_pm1a_evt_blk.addrh = 0x0;
fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1b_evt_blk.bit_width = 0;
fadt->x_pm1b_evt_blk.bit_offset = 0;
fadt->x_pm1b_evt_blk.access_size = 0;
fadt->x_pm1b_evt_blk.addrl = 0x0;
fadt->x_pm1b_evt_blk.addrh = 0x0;
fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
fadt->x_pm1a_cnt_blk.bit_offset = 0;
fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
fadt->x_pm1a_cnt_blk.addrh = 0x0;
fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1b_cnt_blk.bit_width = 0;
fadt->x_pm1b_cnt_blk.bit_offset = 0;
fadt->x_pm1b_cnt_blk.access_size = 0;
fadt->x_pm1b_cnt_blk.addrl = 0x0;
fadt->x_pm1b_cnt_blk.addrh = 0x0;
fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
fadt->x_pm2_cnt_blk.bit_offset = 0;
fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
fadt->x_pm2_cnt_blk.addrh = 0x0;
fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.bit_offset = 0;
fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
fadt->x_pm_tmr_blk.addrh = 0x0;
fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
fadt->x_gpe0_blk.bit_offset = 0;
fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
fadt->x_gpe0_blk.addrh = 0x0;
fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_gpe1_blk.bit_width = 0;
fadt->x_gpe1_blk.bit_offset = 0;
fadt->x_gpe1_blk.access_size = 0;
fadt->x_gpe1_blk.addrl = 0x0;
fadt->x_gpe1_blk.addrh = 0x0;
header->checksum = table_compute_checksum(fadt, header->length);
return acpi_add_fadt(ctx, fadt);
}
ACPI_WRITER(5fadt, "FADT", baytrail_write_fadt, 0);
int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
{
struct udevice *dev;
int ret;
/* at least we have one processor */
gnvs->pcnt = 1;
/* override the processor count with actual number */
ret = uclass_find_first_device(UCLASS_CPU, &dev);
if (ret == 0 && dev != NULL) {
ret = cpu_get_count(dev);
if (ret > 0)
gnvs->pcnt = ret;
}
/* determine whether internal uart is on */
if (IS_ENABLED(CONFIG_INTERNAL_UART))
gnvs->iuart_en = 1;
else
gnvs->iuart_en = 0;
return 0;
}
/*
* The following two routines are called at a very early stage, even before
* FSP 2nd phase API fsp_init() is called. Registers off ACPI_BASE_ADDRESS
* and PMC_BASE_ADDRESS are accessed, so we need make sure the base addresses
* of these two blocks are programmed by either U-Boot or FSP.
*
* It has been verified that 1st phase API (see arch/x86/lib/fsp1/fsp_car.S)
* on Intel BayTrail SoC already initializes these two base addresses so
* we are safe to access these registers here.
*/
enum acpi_sleep_state chipset_prev_sleep_state(void)
{
u32 pm1_sts;
u32 pm1_cnt;
u32 gen_pmcon1;
enum acpi_sleep_state prev_sleep_state = ACPI_S0;
/* Read Power State */
pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
gen_pmcon1 = readl(PMC_BASE_ADDRESS + GEN_PMCON1);
debug("PM1_STS = 0x%x PM1_CNT = 0x%x GEN_PMCON1 = 0x%x\n",
pm1_sts, pm1_cnt, gen_pmcon1);
if (pm1_sts & WAK_STS)
prev_sleep_state = acpi_sleep_from_pm1(pm1_cnt);
if (gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR))
prev_sleep_state = ACPI_S5;
return prev_sleep_state;
}
void chipset_clear_sleep_state(void)
{
u32 pm1_cnt;
pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
}