summaryrefslogtreecommitdiff
path: root/src/soc/intel/common/block
diff options
context:
space:
mode:
authorMichael Niewöhner <foss@mniewoehner.de>2021-01-01 21:04:09 +0100
committerMichael Niewöhner <foss@mniewoehner.de>2021-01-11 20:49:23 +0000
commitf0a44ae0eb329ba4c6f77f1635675ea042492be1 (patch)
tree5c762b9cf8125eb86065c79a51abb764fa59f739 /src/soc/intel/common/block
parentd456f65056530faccca31b392ffaff7bcc0953b3 (diff)
acpi,soc/intel/common: add support for Intel Low Power Idle Table
Add support for the Intel LPIT table to support reading Low Power Idle Residency counters by the OS. On platforms supporting S0ix sleep states there can be two types of residencies: * CPU package PC10 residency counter (read from MSR via FFH interface) * PCH SLP_S0 assertion residency counter (read via memory mapped interface) With presence of one or both of these counters in the LPIT table, Linux dynamically adds the corresponding attributes to the cpuidle sysfs interface, that can be used to read the residency timers: * /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us * /sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us The code in src/acpi implements generic LPIT support. Each SoC or platform has to implement `acpi_fill_lpit` to fill the table with platform-specific LPI state entries. This is done in this change for soc/intel/common, while being added as its own compilation unit, so SoCs not yet using common acpi code (like Skylake) can use it, too. Reference: https://uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf Test: Linux adds the cpuidle sysfs interface; Windows with s0ix_enable=1 boots without crashing with an INTERNAL_POWER_ERROR. - Windows and Linux tested on google/akemi together with CB:49046 - Linux tested on clevo/cml-u, supermicro/x11ssmf together with CB:49046 Change-Id: I816888e8788e2f04c89f20d6ea1654d2f35cf18e Tested-by: Matt DeVillier <matt.devillier@gmail.com> Tested-by: Michael Niewöhner <foss@mniewoehner.de> Signed-off-by: Shaunak Saha <shaunak.saha@intel.com> Signed-off-by: Michael Niewöhner <foss@mniewoehner.de> Reviewed-on: https://review.coreboot.org/c/coreboot/+/49045 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Diffstat (limited to 'src/soc/intel/common/block')
-rw-r--r--src/soc/intel/common/block/acpi/Kconfig7
-rw-r--r--src/soc/intel/common/block/acpi/Makefile.inc1
-rw-r--r--src/soc/intel/common/block/acpi/acpi.c1
-rw-r--r--src/soc/intel/common/block/acpi/lpit.c65
4 files changed, 74 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/acpi/Kconfig b/src/soc/intel/common/block/acpi/Kconfig
index d9a7a87859..a4f9844c70 100644
--- a/src/soc/intel/common/block/acpi/Kconfig
+++ b/src/soc/intel/common/block/acpi/Kconfig
@@ -5,6 +5,13 @@ config SOC_INTEL_COMMON_BLOCK_ACPI
help
Intel Processor common code for ACPI
+config SOC_INTEL_COMMON_BLOCK_ACPI_LPIT
+ bool
+ depends on HAVE_ACPI_TABLES
+ select ACPI_LPIT
+ help
+ Generate LPIT table with LPI state entries.
+
if SOC_INTEL_COMMON_BLOCK_ACPI
config SOC_INTEL_COMMON_BLOCK_ACPI_CPPC
diff --git a/src/soc/intel/common/block/acpi/Makefile.inc b/src/soc/intel/common/block/acpi/Makefile.inc
index c6bdac5d3e..4e3a323625 100644
--- a/src/soc/intel/common/block/acpi/Makefile.inc
+++ b/src/soc/intel/common/block/acpi/Makefile.inc
@@ -1 +1,2 @@
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI) += acpi.c
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_LPIT) += lpit.c
diff --git a/src/soc/intel/common/block/acpi/acpi.c b/src/soc/intel/common/block/acpi/acpi.c
index f4560bd585..1a18cfc23e 100644
--- a/src/soc/intel/common/block/acpi/acpi.c
+++ b/src/soc/intel/common/block/acpi/acpi.c
@@ -10,6 +10,7 @@
#include <cf9_reset.h>
#include <console/console.h>
#include <cpu/intel/turbo.h>
+#include <cpu/intel/msr.h>
#include <cpu/intel/common/common.h>
#include <cpu/x86/smm.h>
#include <intelblocks/acpi.h>
diff --git a/src/soc/intel/common/block/acpi/lpit.c b/src/soc/intel/common/block/acpi/lpit.c
new file mode 100644
index 0000000000..5b9689cead
--- /dev/null
+++ b/src/soc/intel/common/block/acpi/lpit.c
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpi.h>
+#include <cpu/intel/msr.h>
+#include <soc/iomap.h>
+#include <soc/pmc.h>
+
+unsigned long acpi_fill_lpit(unsigned long current)
+{
+ uint16_t uid = 0;
+ acpi_lpi_desc_ncst_t *pkg_counter;
+ acpi_lpi_desc_ncst_t *sys_counter;
+
+ /*
+ * Package C10 (PC10) residency counter
+ */
+ pkg_counter = (void *)current;
+ current += acpi_create_lpi_desc_ncst((void *)current, uid++);
+
+ /* MWAIT LPI state entry trigger */
+ pkg_counter->entry_trigger.addrl = 0x60; /* MWAIT(6,0) / HW C10 */
+ pkg_counter->entry_trigger.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT;
+ pkg_counter->entry_trigger.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL;
+ pkg_counter->entry_trigger.space_id = ACPI_ADDRESS_SPACE_FIXED;
+ pkg_counter->entry_trigger.access_size = ACPI_ACCESS_SIZE_UNDEFINED;
+
+ /* PC10 residency counter */
+ pkg_counter->residency_counter.addrl = MSR_PKG_C10_RESIDENCY;
+ pkg_counter->residency_counter.bit_offset = 0;
+ pkg_counter->residency_counter.bit_width = 64;
+ pkg_counter->residency_counter.space_id = ACPI_ADDRESS_SPACE_FIXED;
+ pkg_counter->residency_counter.access_size = ACPI_ACCESS_SIZE_UNDEFINED;
+ pkg_counter->counter_frequency = ACPI_LPIT_CTR_FREQ_TSC;
+
+ /* Min. residency and worst-case latency (from FSP and vendor dumps) */
+ pkg_counter->min_residency = 30000; /* break-even: 30 ms */
+ pkg_counter->max_latency = 3000; /* worst-case latency: 3 ms */
+
+ /*
+ * System (Slp_S0) residency counter
+ */
+ sys_counter = (void *)current;
+ current += acpi_create_lpi_desc_ncst((void *)current, uid++);
+
+ /* MWAIT LPI state entry trigger */
+ sys_counter->entry_trigger.addrl = 0x60; /* MWAIT(6,0) / HW C10 */
+ sys_counter->entry_trigger.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT;
+ sys_counter->entry_trigger.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL;
+ sys_counter->entry_trigger.space_id = ACPI_ADDRESS_SPACE_FIXED;
+ sys_counter->entry_trigger.access_size = ACPI_ACCESS_SIZE_UNDEFINED;
+
+ /* Slp_S0 residency counter */
+ sys_counter->residency_counter.addrl = PCH_PWRM_BASE_ADDRESS + SLP_S0_RES;
+ sys_counter->residency_counter.bit_offset = 0;
+ sys_counter->residency_counter.bit_width = 32;
+ sys_counter->residency_counter.space_id = ACPI_ADDRESS_SPACE_MEMORY;
+ sys_counter->residency_counter.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ sys_counter->counter_frequency = ACPI_LPIT_CTR_FREQ_TSC;
+
+ /* Min. residency and worst-case latency (from FSP and vendor dumps) */
+ sys_counter->min_residency = 30000; /* break-even: 30 ms */
+ sys_counter->max_latency = 3000; /* worst-case latency: 3 ms */
+
+ return current;
+}