soc/intel: deduplicate ACPI timer emulation
The code for enabling ACPI timer emulation is the same for the SoCs
SKL, CNL, ICL, TGL, JSL and EHL. Deduplicate it by moving it to
common code.
APL differs in not having the delay settings. However, the bits are
marked as "spare" and BWG mentions there are no "reserved bit checks
done". Thus, we can write them unconditionally without any effect.
Note: The ACPI timer emulation can only be used by SoCs with microcode
supporting CTC (Common Timer Copy) / ACPI timer emulation.
Change-Id: Ied4b312b6d53e80e71c55f4d1ca78a8cb2799793
Signed-off-by: Michael Niewöhner <foss@mniewoehner.de>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45951
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/src/soc/intel/alderlake/cpu.c b/src/soc/intel/alderlake/cpu.c
index 39a4265..9fab277 100644
--- a/src/soc/intel/alderlake/cpu.c
+++ b/src/soc/intel/alderlake/cpu.c
@@ -23,7 +23,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/soc_chip.h>
static void soc_fsp_load(void)
@@ -62,25 +61,6 @@
wrmsr(MSR_POWER_CTL, msr);
}
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
@@ -97,7 +77,6 @@
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
- /* Enable PM timer emulation */
enable_pm_timer_emulation();
/* Enable Direct Cache Access */
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index 79fab1a..64889e5 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -10,6 +10,7 @@
subdirs-y += ../../../cpu/x86/cache
bootblock-y += bootblock/bootblock.c
+bootblock-y += ../common/block/cpu/pm_timer_emulation.c
bootblock-$(CONFIG_FSP_CAR) += fspcar.c
bootblock-y += car.c
bootblock-y += heci.c
diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h
index aaf6258..748f76a 100644
--- a/src/soc/intel/apollolake/include/soc/pm.h
+++ b/src/soc/intel/apollolake/include/soc/pm.h
@@ -234,8 +234,6 @@
void pch_log_state(void);
-void enable_pm_timer_emulation(void);
-
/* STM Support */
uint16_t get_pmbase(void);
diff --git a/src/soc/intel/apollolake/pmutil.c b/src/soc/intel/apollolake/pmutil.c
index e0de93e..6e96b57 100644
--- a/src/soc/intel/apollolake/pmutil.c
+++ b/src/soc/intel/apollolake/pmutil.c
@@ -178,24 +178,6 @@
return prev_sleep_state;
}
-void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + R_ACPI_PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
static int rtc_failed(uint32_t gen_pmcon1)
{
return !!(gen_pmcon1 & RPS);
diff --git a/src/soc/intel/cannonlake/cpu.c b/src/soc/intel/cannonlake/cpu.c
index 20da942..61b1989 100644
--- a/src/soc/intel/cannonlake/cpu.c
+++ b/src/soc/intel/cannonlake/cpu.c
@@ -14,7 +14,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/systemagent.h>
#include <cpu/x86/mtrr.h>
#include <cpu/intel/microcode.h>
@@ -58,29 +57,6 @@
wrmsr(MSR_POWER_CTL, msr);
}
-/*
- * The emulated ACPI timer allows replacing of the ACPI timer
- * (PM1_TMR) to have no impart on the system.
- */
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
static void configure_c_states(void)
{
msr_t msr;
@@ -135,7 +111,6 @@
set_aesni_lock();
- /* Enable ACPI Timer Emulation via MSR 0x121 */
enable_pm_timer_emulation();
/* Enable Direct Cache Access */
diff --git a/src/soc/intel/common/block/cpu/Makefile.inc b/src/soc/intel/common/block/cpu/Makefile.inc
index deddb67..7692076 100644
--- a/src/soc/intel/common/block/cpu/Makefile.inc
+++ b/src/soc/intel/common/block/cpu/Makefile.inc
@@ -11,3 +11,4 @@
romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CPU) += cpulib.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CPU) += cpulib.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CPU_MPINIT) += mp_init.c
+ramstage-$(CONFIG_CPU_SUPPORTS_PM_TIMER_EMULATION) += pm_timer_emulation.c
diff --git a/src/soc/intel/common/block/cpu/pm_timer_emulation.c b/src/soc/intel/common/block/cpu/pm_timer_emulation.c
new file mode 100644
index 0000000..8f56da5
--- /dev/null
+++ b/src/soc/intel/common/block/cpu/pm_timer_emulation.c
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cpu/x86/msr.h>
+#include <intelblocks/cpulib.h>
+#include <intelblocks/msr.h>
+#include <soc/iomap.h>
+#include <soc/pm.h>
+
+void enable_pm_timer_emulation(void)
+{
+ msr_t msr;
+
+ if (!CONFIG_CPU_XTAL_HZ)
+ return;
+
+ /*
+ * The derived frequency is calculated as follows:
+ * (clock * msr[63:32]) >> 32 = target frequency.
+ * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
+ */
+ msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
+ /* Set PM1 timer IO port and enable */
+ msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
+ EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
+ wrmsr(MSR_EMULATE_PM_TIMER, msr);
+}
diff --git a/src/soc/intel/common/block/include/intelblocks/cpulib.h b/src/soc/intel/common/block/include/intelblocks/cpulib.h
index d2b00ef..4dfbef4 100644
--- a/src/soc/intel/common/block/include/intelblocks/cpulib.h
+++ b/src/soc/intel/common/block/include/intelblocks/cpulib.h
@@ -156,4 +156,10 @@
/* Get a supported PRMRR size in bytes with respect to users choice */
int get_valid_prmrr_size(void);
+/*
+ * Enable the emulated ACPI timer in case it's not available or to allow
+ * disabling the PM ACPI timer (PM1_TMR) for power saving.
+ */
+void enable_pm_timer_emulation(void);
+
#endif /* SOC_INTEL_COMMON_BLOCK_CPULIB_H */
diff --git a/src/soc/intel/elkhartlake/cpu.c b/src/soc/intel/elkhartlake/cpu.c
index 720a295..d0fa019 100644
--- a/src/soc/intel/elkhartlake/cpu.c
+++ b/src/soc/intel/elkhartlake/cpu.c
@@ -17,7 +17,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/soc_chip.h>
static void soc_fsp_load(void)
@@ -56,25 +55,6 @@
wrmsr(MSR_POWER_CTL, msr);
}
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
@@ -91,7 +71,6 @@
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
- /* Enable PM timer emulation */
enable_pm_timer_emulation();
/* Enable Direct Cache Access */
diff --git a/src/soc/intel/icelake/cpu.c b/src/soc/intel/icelake/cpu.c
index ea2b357..1734ba6 100644
--- a/src/soc/intel/icelake/cpu.c
+++ b/src/soc/intel/icelake/cpu.c
@@ -17,7 +17,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/soc_chip.h>
static void soc_fsp_load(void)
@@ -56,25 +55,6 @@
wrmsr(MSR_POWER_CTL, msr);
}
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
static void configure_c_states(void)
{
msr_t msr;
@@ -127,7 +107,6 @@
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
- /* Enable PM timer emulation */
enable_pm_timer_emulation();
/* Enable Direct Cache Access */
diff --git a/src/soc/intel/jasperlake/cpu.c b/src/soc/intel/jasperlake/cpu.c
index 312fc7d..6518945 100644
--- a/src/soc/intel/jasperlake/cpu.c
+++ b/src/soc/intel/jasperlake/cpu.c
@@ -17,7 +17,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/soc_chip.h>
static void soc_fsp_load(void)
@@ -56,25 +55,6 @@
wrmsr(MSR_POWER_CTL, msr);
}
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
@@ -91,7 +71,6 @@
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
- /* Enable PM timer emulation */
enable_pm_timer_emulation();
/* Enable Direct Cache Access */
diff --git a/src/soc/intel/skylake/cpu.c b/src/soc/intel/skylake/cpu.c
index 1682503..6872c12 100644
--- a/src/soc/intel/skylake/cpu.c
+++ b/src/soc/intel/skylake/cpu.c
@@ -21,7 +21,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/ramstage.h>
#include <soc/systemagent.h>
@@ -96,29 +95,6 @@
wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr);
}
-/*
- * The emulated ACPI timer allows disabling of the ACPI timer
- * (PM1_TMR) to have no impart on the system.
- */
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
diff --git a/src/soc/intel/tigerlake/cpu.c b/src/soc/intel/tigerlake/cpu.c
index d7234e7..36dfa1b 100644
--- a/src/soc/intel/tigerlake/cpu.c
+++ b/src/soc/intel/tigerlake/cpu.c
@@ -23,7 +23,6 @@
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
-#include <soc/pm.h>
#include <soc/soc_chip.h>
static void soc_fsp_load(void)
@@ -62,25 +61,6 @@
wrmsr(MSR_POWER_CTL, msr);
}
-static void enable_pm_timer_emulation(void)
-{
- msr_t msr;
-
- if (!CONFIG_CPU_XTAL_HZ)
- return;
-
- /*
- * The derived frequency is calculated as follows:
- * (clock * msr[63:32]) >> 32 = target frequency.
- * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
- */
- msr.hi = (3579545ULL << 32) / CONFIG_CPU_XTAL_HZ;
- /* Set PM1 timer IO port and enable */
- msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
- EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
- wrmsr(MSR_EMULATE_PM_TIMER, msr);
-}
-
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
@@ -97,7 +77,6 @@
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
- /* Enable PM timer emulation */
enable_pm_timer_emulation();
/* Enable Direct Cache Access */