Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / hw / acpi / ich9_timer.c
blob5b1c9101566047783ea09faf1ac2c13f119dd902
1 /*
2 * QEMU ICH9 Timer emulation
4 * Copyright (c) 2024 Dominic Prinz <git@dprinz.de>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
10 #include "qemu/osdep.h"
11 #include "hw/core/cpu.h"
12 #include "hw/pci/pci.h"
13 #include "hw/southbridge/ich9.h"
14 #include "qemu/timer.h"
16 #include "hw/acpi/ich9_timer.h"
18 void ich9_pm_update_swsmi_timer(ICH9LPCPMRegs *pm, bool enable)
20 uint16_t swsmi_rate_sel;
21 int64_t expire_time;
22 ICH9LPCState *lpc;
24 if (enable) {
25 lpc = container_of(pm, ICH9LPCState, pm);
26 swsmi_rate_sel =
27 (pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_3) & 0xc0) >> 6;
29 if (swsmi_rate_sel == 0) {
30 expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1500000LL;
31 } else {
32 expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
33 8 * (1 << swsmi_rate_sel) * 1000000LL;
36 timer_mod(pm->swsmi_timer, expire_time);
37 } else {
38 timer_del(pm->swsmi_timer);
42 static void ich9_pm_swsmi_timer_expired(void *opaque)
44 ICH9LPCPMRegs *pm = opaque;
46 pm->smi_sts |= ICH9_PMIO_SMI_STS_SWSMI_STS;
47 ich9_generate_smi();
49 ich9_pm_update_swsmi_timer(pm, pm->smi_en & ICH9_PMIO_SMI_EN_SWSMI_EN);
52 void ich9_pm_swsmi_timer_init(ICH9LPCPMRegs *pm)
54 pm->smi_sts_wmask |= ICH9_PMIO_SMI_STS_SWSMI_STS;
55 pm->swsmi_timer =
56 timer_new_ns(QEMU_CLOCK_VIRTUAL, ich9_pm_swsmi_timer_expired, pm);
59 void ich9_pm_update_periodic_timer(ICH9LPCPMRegs *pm, bool enable)
61 uint16_t per_smi_sel;
62 int64_t expire_time;
63 ICH9LPCState *lpc;
65 if (enable) {
66 lpc = container_of(pm, ICH9LPCState, pm);
67 per_smi_sel = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1) & 3;
68 expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
69 8 * (1 << (3 - per_smi_sel)) * NANOSECONDS_PER_SECOND;
71 timer_mod(pm->periodic_timer, expire_time);
72 } else {
73 timer_del(pm->periodic_timer);
77 static void ich9_pm_periodic_timer_expired(void *opaque)
79 ICH9LPCPMRegs *pm = opaque;
81 pm->smi_sts = ICH9_PMIO_SMI_STS_PERIODIC_STS;
82 ich9_generate_smi();
84 ich9_pm_update_periodic_timer(pm,
85 pm->smi_en & ICH9_PMIO_SMI_EN_PERIODIC_EN);
88 void ich9_pm_periodic_timer_init(ICH9LPCPMRegs *pm)
90 pm->smi_sts_wmask |= ICH9_PMIO_SMI_STS_PERIODIC_STS;
91 pm->periodic_timer =
92 timer_new_ns(QEMU_CLOCK_VIRTUAL, ich9_pm_periodic_timer_expired, pm);