blob: 3c619985156ea2858cd016813183e483562990b4 [file] [log] [blame]
Michael Niewöhner310c7632020-10-01 22:28:03 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
Michael Niewöhner880acbe2021-09-26 14:09:59 +02003#include <commonlib/helpers.h>
Michael Niewöhner310c7632020-10-01 22:28:03 +02004#include <cpu/x86/msr.h>
5#include <intelblocks/cpulib.h>
6#include <intelblocks/msr.h>
7#include <soc/iomap.h>
8#include <soc/pm.h>
9
10void enable_pm_timer_emulation(void)
11{
12 msr_t msr;
13
Michael Niewöhner413810e2021-09-24 23:42:14 +020014 if (CONFIG(USE_PM_ACPI_TIMER) || !CONFIG_CPU_XTAL_HZ)
Michael Niewöhner310c7632020-10-01 22:28:03 +020015 return;
16
17 /*
18 * The derived frequency is calculated as follows:
19 * (clock * msr[63:32]) >> 32 = target frequency.
20 * Back solve the multiplier so the 3.579545MHz ACPI timer frequency is used.
21 */
Michael Niewöhner880acbe2021-09-26 14:09:59 +020022 msr.hi = DIV_ROUND_CLOSEST((3579545ULL << 32), CONFIG_CPU_XTAL_HZ);
Michael Niewöhner310c7632020-10-01 22:28:03 +020023 /* Set PM1 timer IO port and enable */
24 msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
25 EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
26 wrmsr(MSR_EMULATE_PM_TIMER, msr);
27}