Attention is currently required from: Patrick Rudolph. Tim Wawrzynczak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/56005 )
Change subject: soc/intel/common/block/acpi: Add LPM requirements support to PEPD _DSM ......................................................................
soc/intel/common/block/acpi: Add LPM requirements support to PEPD _DSM
This patch adds support for the S0ix UUID in the Intel Power Engine _DSM method. This allows the ACPI tables to expose device/IP power states requirements for different system low power states
BUG=b:185437326 TEST=cat /sys/kernel/debug/pmc_core/substate_requirements Element | S0i2.0 | S0i3.0 | Status | USB2PLL_OFF_STS | Required | Required | Yes | PCIe/USB3.1_Gen2PLL_OFF_STS | Required | Required | | PCIe_Gen3PLL_OFF_STS | Required | Required | Yes | OPIOPLL_OFF_STS | Required | Required | | OCPLL_OFF_STS | Required | Required | Yes | MainPLL_OFF_STS | | Required | | MIPIPLL_OFF_STS | Required | Required | Yes | Fast_XTAL_Osc_OFF_STS | | Required | | AC_Ring_Osc_OFF_STS | Required | Required | Yes | SATAPLL_OFF_STS | Required | Required | Yes | XTAL_USB2PLL_OFF_STS | | Required | Yes | CSME_PG_STS | Required | Required | Yes | SATA_PG_STS | Required | Required | Yes | xHCI_PG_STS | Required | Required | | UFSX2_PG_STS | Required | Required | Yes | OTG_PG_STS | Required | Required | Yes | SPA_PG_STS | Required | Required | Yes | SPB_PG_STS | Required | Required | Yes | SPC_PG_STS | Required | Required | Yes | THC0_PG_STS | Required | Required | Yes | THC1_PG_STS | Required | Required | Yes | GBETSN_PG_STS | Required | Required | Yes | GBE_PG_STS | Required | Required | Yes | LPSS_PG_STS | Required | Required | | ADSP_D3_STS | | Required | Yes | xHCI0_D3_STS | Required | Required | | xDCI1_D3_STS | Required | Required | Yes | IS_D3_STS | Required | Required | | GBE_TSN_D3_STS | Required | Required | Yes | CPU_C10_REQ_STS_0 | Required | Required | Yes | CNVI_REQ_STS_6 | | Required | | ISH_REQ_STS_7 | | Required | Yes | MPHY_Core_DL_REQ_STS_16 | Required | Required | | Break-even_En_REQ_STS_17 | Required | Required | Yes | Auto-demo_En_REQ_STS_18 | Required | Required | Yes | Int_Timer_SS_Wake0_Pol_STS | Required | Required | | Int_Timer_SS_Wake1_Pol_STS | Required | Required | | Int_Timer_SS_Wake2_Pol_STS | Required | Required | | Int_Timer_SS_Wake3_Pol_STS | Required | Required | | Int_Timer_SS_Wake4_Pol_STS | Required | Required | | Int_Timer_SS_Wake5_Pol_STS | Required | Required | |
Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org Change-Id: I542290bd5490aa6580a5ae2b266da3d78bc17e6b --- M src/soc/intel/common/block/acpi/Kconfig M src/soc/intel/common/block/acpi/pep.c M src/soc/intel/common/block/include/intelblocks/pmc_ipc.h 3 files changed, 75 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/05/56005/1
diff --git a/src/soc/intel/common/block/acpi/Kconfig b/src/soc/intel/common/block/acpi/Kconfig index 12c0d45..8d6ede2 100644 --- a/src/soc/intel/common/block/acpi/Kconfig +++ b/src/soc/intel/common/block/acpi/Kconfig @@ -21,6 +21,15 @@ Generate an Intel Power Engine device object in the SSDT. This is usually used for providing ACPI hooks for S0ix exit/entry.
+config SOC_INTEL_COMMON_BLOCK_ACPI_PEP_LPM_REQ + bool + depends on SOC_INTEL_COMMON_BLOCK_ACPI_PEP + help + Generate a 2nd set of _DSM functions for the Power Engine device that + will return a buffer that contains the contents of the PMC's LPM + requirements registers. A kernel can use this to display the + requirements for different LPM substates. + config SOC_INTEL_COMMON_BLOCK_CRASHLOG bool depends on SOC_INTEL_CRASHLOG diff --git a/src/soc/intel/common/block/acpi/pep.c b/src/soc/intel/common/block/acpi/pep.c index 9723d28..1dcbb0a 100644 --- a/src/soc/intel/common/block/acpi/pep.c +++ b/src/soc/intel/common/block/acpi/pep.c @@ -3,17 +3,24 @@ #include <acpi/acpigen.h> #include <console/console.h> #include <intelblocks/acpi.h> +#include <intelblocks/pmc_ipc.h> #include <soc/pci_devs.h> #include <stdlib.h> #include <types.h>
#define LPI_S0_HELPER_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66" +#define PEP_S0IX_UUID "57a6512e-3979-4e9d-9708-ff13b2508972" #define SYSTEM_POWER_MANAGEMENT_HID "INT33A1" #define SYSTEM_POWER_MANAGEMENT_CID "PNP0D80" #define EC_S0IX_HOOK "\_SB.PCI0.LPCB.EC0.S0IX" #define MAINBOARD_HOOK "\_SB.MS0X" #define ENABLE_PM_BITS_HOOK "\_SB.PCI0.EGPM" #define RESTORE_PM_BITS_HOOK "\_SB.PCI0.RGPM" +#define LPM_STATES 8 +#define LPM_REQ_PER_STATE 6 +#define LPM_REGISTERS_COUNT (LPM_STATES * LPM_REQ_PER_STATE) +#define PMC_LPM_REQ_BASE 0x1000 +#define LPM_REQ_REG_STRIDE 48
/* * Supported functions bitmask @@ -105,10 +112,65 @@ lpi_s0ix_exit, /* s0ix exit */ };
+/* + * Supported functions bitmask + * bit 0: other functions than 0 are supported + * bits 1-6: function x supported + */ +static void pep_s0ix_enum_functions(void *unused) +{ + if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_PEP_LPM_REQ)) + acpigen_write_return_singleton_buffer(0x03); + else + acpigen_write_return_singleton_buffer(0x00); +} + +static void pep_s0ix_collect_lpm_requirements(void *unused) +{ + if (!CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_PEP_LPM_REQ)) + return; + + uint32_t *reg = calloc(LPM_REGISTERS_COUNT, sizeof(uint32_t)); + enum cb_err result = CB_SUCCESS; + uint32_t *ptr = reg; + + /* Read the various LPM state requirement registers from the PMC */ + for (size_t i = 0; i < LPM_STATES && result == CB_SUCCESS; i++) { + for (size_t j = 0; j < LPM_REQ_PER_STATE; j++) { + const uint32_t offset = PMC_LPM_REQ_BASE + i * LPM_REQ_REG_STRIDE + + j * sizeof(uint32_t); + const uint32_t cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_GENERAL_COMM, + PMC_IPC_SUBCMD_GEN_COMM_READ, + 0); + struct pmc_ipc_buffer req = {.buf[0] = offset}; + struct pmc_ipc_buffer res = {}; + + result = pmc_send_ipc_cmd(cmd_reg, &req, &res); + if (result != CB_SUCCESS) + break; + + *ptr++ = res.buf[0]; + } + } + + if (result == CB_SUCCESS) + acpigen_write_return_byte_buffer((uint8_t *)reg, LPM_REGISTERS_COUNT * sizeof(uint32_t)); + else + printk(BIOS_ERR, "ERROR: Failed to retrieve PMC LPM requirements registers\n"); + + free(reg); +} + +static void (*pep_s0ix[])(void *) = { + pep_s0ix_enum_functions, /* enumerate functions */ + pep_s0ix_collect_lpm_requirements, /* Return LPM requirements */ +}; + void generate_acpi_power_engine(const struct device *dev) { struct dsm_uuid ids[] = { DSM_UUID(LPI_S0_HELPER_UUID, lpi_s0_helpers, ARRAY_SIZE(lpi_s0_helpers), NULL), + DSM_UUID(PEP_S0IX_UUID, pep_s0ix, ARRAY_SIZE(pep_s0ix), NULL), };
const char *scope = acpi_device_scope(dev); diff --git a/src/soc/intel/common/block/include/intelblocks/pmc_ipc.h b/src/soc/intel/common/block/include/intelblocks/pmc_ipc.h index b67abc0..de21027 100644 --- a/src/soc/intel/common/block/include/intelblocks/pmc_ipc.h +++ b/src/soc/intel/common/block/include/intelblocks/pmc_ipc.h @@ -21,6 +21,10 @@
#define PMC_IPC_CMD_NO_MSI 0
+/* IPC command for general communication */ +#define PMC_IPC_CMD_GENERAL_COMM 0xA0 +#define PMC_IPC_SUBCMD_GEN_COMM_READ 0x02 + /* IPC command to enable/disable PCIe SRCCLK */ #define PMC_IPC_CMD_ID_SET_PCIE_CLOCK 0xAC