Attention is currently required from: Patrick Rudolph.

Tim Wawrzynczak has uploaded this change for review.

View Change

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


To view, visit change 56005. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I542290bd5490aa6580a5ae2b266da3d78bc17e6b
Gerrit-Change-Number: 56005
Gerrit-PatchSet: 1
Gerrit-Owner: Tim Wawrzynczak <twawrzynczak@chromium.org>
Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org>
Gerrit-Attention: Patrick Rudolph <siro@das-labor.org>
Gerrit-MessageType: newchange