xref: /openbmc/qemu/hw/acpi/ich9.c (revision f7d3e29d)
149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini  * ACPI implementation
349ab747fSPaolo Bonzini  *
449ab747fSPaolo Bonzini  * Copyright (c) 2006 Fabrice Bellard
549ab747fSPaolo Bonzini  * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
649ab747fSPaolo Bonzini  *                    VA Linux Systems Japan K.K.
749ab747fSPaolo Bonzini  * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
849ab747fSPaolo Bonzini  *
949ab747fSPaolo Bonzini  * This is based on acpi.c.
1049ab747fSPaolo Bonzini  *
1149ab747fSPaolo Bonzini  * This library is free software; you can redistribute it and/or
1249ab747fSPaolo Bonzini  * modify it under the terms of the GNU Lesser General Public
1349ab747fSPaolo Bonzini  * License version 2 as published by the Free Software Foundation.
1449ab747fSPaolo Bonzini  *
1549ab747fSPaolo Bonzini  * This library is distributed in the hope that it will be useful,
1649ab747fSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1749ab747fSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1849ab747fSPaolo Bonzini  * Lesser General Public License for more details.
1949ab747fSPaolo Bonzini  *
2049ab747fSPaolo Bonzini  * You should have received a copy of the GNU Lesser General Public
2149ab747fSPaolo Bonzini  * License along with this library; if not, see <http://www.gnu.org/licenses/>
2249ab747fSPaolo Bonzini  *
2349ab747fSPaolo Bonzini  * Contributions after 2012-01-13 are licensed under the terms of the
2449ab747fSPaolo Bonzini  * GNU GPL, version 2 or (at your option) any later version.
2549ab747fSPaolo Bonzini  */
2649ab747fSPaolo Bonzini #include "hw/hw.h"
276f1426abSMichael S. Tsirkin #include "qapi/visitor.h"
2849ab747fSPaolo Bonzini #include "hw/i386/pc.h"
2949ab747fSPaolo Bonzini #include "hw/pci/pci.h"
3049ab747fSPaolo Bonzini #include "qemu/timer.h"
3149ab747fSPaolo Bonzini #include "sysemu/sysemu.h"
3249ab747fSPaolo Bonzini #include "hw/acpi/acpi.h"
3349ab747fSPaolo Bonzini #include "sysemu/kvm.h"
3449ab747fSPaolo Bonzini #include "exec/address-spaces.h"
3549ab747fSPaolo Bonzini 
3649ab747fSPaolo Bonzini #include "hw/i386/ich9.h"
371f862184SIgor Mammedov #include "hw/mem/pc-dimm.h"
3849ab747fSPaolo Bonzini 
3949ab747fSPaolo Bonzini //#define DEBUG
4049ab747fSPaolo Bonzini 
4149ab747fSPaolo Bonzini #ifdef DEBUG
4249ab747fSPaolo Bonzini #define ICH9_DEBUG(fmt, ...) \
4349ab747fSPaolo Bonzini do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
4449ab747fSPaolo Bonzini #else
4549ab747fSPaolo Bonzini #define ICH9_DEBUG(fmt, ...)    do { } while (0)
4649ab747fSPaolo Bonzini #endif
4749ab747fSPaolo Bonzini 
4849ab747fSPaolo Bonzini static void ich9_pm_update_sci_fn(ACPIREGS *regs)
4949ab747fSPaolo Bonzini {
5049ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = container_of(regs, ICH9LPCPMRegs, acpi_regs);
5106313503SIgor Mammedov     acpi_update_sci(&pm->acpi_regs, pm->irq);
5249ab747fSPaolo Bonzini }
5349ab747fSPaolo Bonzini 
5449ab747fSPaolo Bonzini static uint64_t ich9_gpe_readb(void *opaque, hwaddr addr, unsigned width)
5549ab747fSPaolo Bonzini {
5649ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = opaque;
5749ab747fSPaolo Bonzini     return acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
5849ab747fSPaolo Bonzini }
5949ab747fSPaolo Bonzini 
6049ab747fSPaolo Bonzini static void ich9_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
6149ab747fSPaolo Bonzini                             unsigned width)
6249ab747fSPaolo Bonzini {
6349ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = opaque;
6449ab747fSPaolo Bonzini     acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
652c047956SIgor Mammedov     acpi_update_sci(&pm->acpi_regs, pm->irq);
6649ab747fSPaolo Bonzini }
6749ab747fSPaolo Bonzini 
6849ab747fSPaolo Bonzini static const MemoryRegionOps ich9_gpe_ops = {
6949ab747fSPaolo Bonzini     .read = ich9_gpe_readb,
7049ab747fSPaolo Bonzini     .write = ich9_gpe_writeb,
7149ab747fSPaolo Bonzini     .valid.min_access_size = 1,
7249ab747fSPaolo Bonzini     .valid.max_access_size = 4,
7349ab747fSPaolo Bonzini     .impl.min_access_size = 1,
7449ab747fSPaolo Bonzini     .impl.max_access_size = 1,
7549ab747fSPaolo Bonzini     .endianness = DEVICE_LITTLE_ENDIAN,
7649ab747fSPaolo Bonzini };
7749ab747fSPaolo Bonzini 
7849ab747fSPaolo Bonzini static uint64_t ich9_smi_readl(void *opaque, hwaddr addr, unsigned width)
7949ab747fSPaolo Bonzini {
8049ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = opaque;
8149ab747fSPaolo Bonzini     switch (addr) {
8249ab747fSPaolo Bonzini     case 0:
8349ab747fSPaolo Bonzini         return pm->smi_en;
8449ab747fSPaolo Bonzini     case 4:
8549ab747fSPaolo Bonzini         return pm->smi_sts;
8649ab747fSPaolo Bonzini     default:
8749ab747fSPaolo Bonzini         return 0;
8849ab747fSPaolo Bonzini     }
8949ab747fSPaolo Bonzini }
9049ab747fSPaolo Bonzini 
9149ab747fSPaolo Bonzini static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
9249ab747fSPaolo Bonzini                             unsigned width)
9349ab747fSPaolo Bonzini {
9449ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = opaque;
9549ab747fSPaolo Bonzini     switch (addr) {
9649ab747fSPaolo Bonzini     case 0:
9749ab747fSPaolo Bonzini         pm->smi_en = val;
9849ab747fSPaolo Bonzini         break;
9949ab747fSPaolo Bonzini     }
10049ab747fSPaolo Bonzini }
10149ab747fSPaolo Bonzini 
10249ab747fSPaolo Bonzini static const MemoryRegionOps ich9_smi_ops = {
10349ab747fSPaolo Bonzini     .read = ich9_smi_readl,
10449ab747fSPaolo Bonzini     .write = ich9_smi_writel,
10549ab747fSPaolo Bonzini     .valid.min_access_size = 4,
10649ab747fSPaolo Bonzini     .valid.max_access_size = 4,
10749ab747fSPaolo Bonzini     .endianness = DEVICE_LITTLE_ENDIAN,
10849ab747fSPaolo Bonzini };
10949ab747fSPaolo Bonzini 
11049ab747fSPaolo Bonzini void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
11149ab747fSPaolo Bonzini {
11249ab747fSPaolo Bonzini     ICH9_DEBUG("to 0x%x\n", pm_io_base);
11349ab747fSPaolo Bonzini 
11449ab747fSPaolo Bonzini     assert((pm_io_base & ICH9_PMIO_MASK) == 0);
11549ab747fSPaolo Bonzini 
11649ab747fSPaolo Bonzini     pm->pm_io_base = pm_io_base;
11749ab747fSPaolo Bonzini     memory_region_transaction_begin();
11849ab747fSPaolo Bonzini     memory_region_set_enabled(&pm->io, pm->pm_io_base != 0);
11949ab747fSPaolo Bonzini     memory_region_set_address(&pm->io, pm->pm_io_base);
12049ab747fSPaolo Bonzini     memory_region_transaction_commit();
12149ab747fSPaolo Bonzini }
12249ab747fSPaolo Bonzini 
12349ab747fSPaolo Bonzini static int ich9_pm_post_load(void *opaque, int version_id)
12449ab747fSPaolo Bonzini {
12549ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = opaque;
12649ab747fSPaolo Bonzini     uint32_t pm_io_base = pm->pm_io_base;
12749ab747fSPaolo Bonzini     pm->pm_io_base = 0;
12849ab747fSPaolo Bonzini     ich9_pm_iospace_update(pm, pm_io_base);
12949ab747fSPaolo Bonzini     return 0;
13049ab747fSPaolo Bonzini }
13149ab747fSPaolo Bonzini 
13249ab747fSPaolo Bonzini #define VMSTATE_GPE_ARRAY(_field, _state)                            \
13349ab747fSPaolo Bonzini  {                                                                   \
13449ab747fSPaolo Bonzini      .name       = (stringify(_field)),                              \
13549ab747fSPaolo Bonzini      .version_id = 0,                                                \
13649ab747fSPaolo Bonzini      .num        = ICH9_PMIO_GPE0_LEN,                               \
13749ab747fSPaolo Bonzini      .info       = &vmstate_info_uint8,                              \
13849ab747fSPaolo Bonzini      .size       = sizeof(uint8_t),                                  \
13949ab747fSPaolo Bonzini      .flags      = VMS_ARRAY | VMS_POINTER,                          \
14049ab747fSPaolo Bonzini      .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
14149ab747fSPaolo Bonzini  }
14249ab747fSPaolo Bonzini 
143f816a62dSIgor Mammedov static bool vmstate_test_use_memhp(void *opaque)
144f816a62dSIgor Mammedov {
145f816a62dSIgor Mammedov     ICH9LPCPMRegs *s = opaque;
146f816a62dSIgor Mammedov     return s->acpi_memory_hotplug.is_enabled;
147f816a62dSIgor Mammedov }
148f816a62dSIgor Mammedov 
149f816a62dSIgor Mammedov static const VMStateDescription vmstate_memhp_state = {
150f816a62dSIgor Mammedov     .name = "ich9_pm/memhp",
151f816a62dSIgor Mammedov     .version_id = 1,
152f816a62dSIgor Mammedov     .minimum_version_id = 1,
153f816a62dSIgor Mammedov     .minimum_version_id_old = 1,
154f816a62dSIgor Mammedov     .fields      = (VMStateField[]) {
155f816a62dSIgor Mammedov         VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, ICH9LPCPMRegs),
156f816a62dSIgor Mammedov         VMSTATE_END_OF_LIST()
157f816a62dSIgor Mammedov     }
158f816a62dSIgor Mammedov };
159f816a62dSIgor Mammedov 
16049ab747fSPaolo Bonzini const VMStateDescription vmstate_ich9_pm = {
16149ab747fSPaolo Bonzini     .name = "ich9_pm",
16249ab747fSPaolo Bonzini     .version_id = 1,
16349ab747fSPaolo Bonzini     .minimum_version_id = 1,
16449ab747fSPaolo Bonzini     .post_load = ich9_pm_post_load,
16549ab747fSPaolo Bonzini     .fields = (VMStateField[]) {
16649ab747fSPaolo Bonzini         VMSTATE_UINT16(acpi_regs.pm1.evt.sts, ICH9LPCPMRegs),
16749ab747fSPaolo Bonzini         VMSTATE_UINT16(acpi_regs.pm1.evt.en, ICH9LPCPMRegs),
16849ab747fSPaolo Bonzini         VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, ICH9LPCPMRegs),
169e720677eSPaolo Bonzini         VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, ICH9LPCPMRegs),
17049ab747fSPaolo Bonzini         VMSTATE_INT64(acpi_regs.tmr.overflow_time, ICH9LPCPMRegs),
17149ab747fSPaolo Bonzini         VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, ICH9LPCPMRegs),
17249ab747fSPaolo Bonzini         VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, ICH9LPCPMRegs),
17349ab747fSPaolo Bonzini         VMSTATE_UINT32(smi_en, ICH9LPCPMRegs),
17449ab747fSPaolo Bonzini         VMSTATE_UINT32(smi_sts, ICH9LPCPMRegs),
17549ab747fSPaolo Bonzini         VMSTATE_END_OF_LIST()
176f816a62dSIgor Mammedov     },
177f816a62dSIgor Mammedov     .subsections = (VMStateSubsection[]) {
178f816a62dSIgor Mammedov         {
179f816a62dSIgor Mammedov             .vmsd = &vmstate_memhp_state,
180f816a62dSIgor Mammedov             .needed = vmstate_test_use_memhp,
181f816a62dSIgor Mammedov         },
182f816a62dSIgor Mammedov         VMSTATE_END_OF_LIST()
18349ab747fSPaolo Bonzini     }
18449ab747fSPaolo Bonzini };
18549ab747fSPaolo Bonzini 
18649ab747fSPaolo Bonzini static void pm_reset(void *opaque)
18749ab747fSPaolo Bonzini {
18849ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = opaque;
18949ab747fSPaolo Bonzini     ich9_pm_iospace_update(pm, 0);
19049ab747fSPaolo Bonzini 
19149ab747fSPaolo Bonzini     acpi_pm1_evt_reset(&pm->acpi_regs);
19249ab747fSPaolo Bonzini     acpi_pm1_cnt_reset(&pm->acpi_regs);
19349ab747fSPaolo Bonzini     acpi_pm_tmr_reset(&pm->acpi_regs);
19449ab747fSPaolo Bonzini     acpi_gpe_reset(&pm->acpi_regs);
19549ab747fSPaolo Bonzini 
19649ab747fSPaolo Bonzini     if (kvm_enabled()) {
19749ab747fSPaolo Bonzini         /* Mark SMM as already inited to prevent SMM from running. KVM does not
19849ab747fSPaolo Bonzini          * support SMM mode. */
19949ab747fSPaolo Bonzini         pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
20049ab747fSPaolo Bonzini     }
20149ab747fSPaolo Bonzini 
20206313503SIgor Mammedov     acpi_update_sci(&pm->acpi_regs, pm->irq);
20349ab747fSPaolo Bonzini }
20449ab747fSPaolo Bonzini 
20549ab747fSPaolo Bonzini static void pm_powerdown_req(Notifier *n, void *opaque)
20649ab747fSPaolo Bonzini {
20749ab747fSPaolo Bonzini     ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, powerdown_notifier);
20849ab747fSPaolo Bonzini 
20949ab747fSPaolo Bonzini     acpi_pm1_evt_power_down(&pm->acpi_regs);
21049ab747fSPaolo Bonzini }
21149ab747fSPaolo Bonzini 
21249ab747fSPaolo Bonzini void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
213a3ac6b53SHu Tao                   qemu_irq sci_irq)
21449ab747fSPaolo Bonzini {
21564bde0f3SPaolo Bonzini     memory_region_init(&pm->io, OBJECT(lpc_pci), "ich9-pm", ICH9_PMIO_SIZE);
21649ab747fSPaolo Bonzini     memory_region_set_enabled(&pm->io, false);
21749ab747fSPaolo Bonzini     memory_region_add_subregion(pci_address_space_io(lpc_pci),
21849ab747fSPaolo Bonzini                                 0, &pm->io);
21949ab747fSPaolo Bonzini 
22049ab747fSPaolo Bonzini     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
22149ab747fSPaolo Bonzini     acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
2226ac0d8d4SAmit Shah     acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->s4_val);
22349ab747fSPaolo Bonzini 
22449ab747fSPaolo Bonzini     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
22564bde0f3SPaolo Bonzini     memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm,
22675902802SHu Tao                           "acpi-gpe0", ICH9_PMIO_GPE0_LEN);
22749ab747fSPaolo Bonzini     memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
22849ab747fSPaolo Bonzini 
22964bde0f3SPaolo Bonzini     memory_region_init_io(&pm->io_smi, OBJECT(lpc_pci), &ich9_smi_ops, pm,
23075902802SHu Tao                           "acpi-smi", 8);
23149ab747fSPaolo Bonzini     memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
23249ab747fSPaolo Bonzini 
23349ab747fSPaolo Bonzini     pm->irq = sci_irq;
23449ab747fSPaolo Bonzini     qemu_register_reset(pm_reset, pm);
23549ab747fSPaolo Bonzini     pm->powerdown_notifier.notify = pm_powerdown_req;
23649ab747fSPaolo Bonzini     qemu_register_powerdown_notifier(&pm->powerdown_notifier);
237d6610bc2SIgor Mammedov 
238411b5db8SGu Zheng     acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
239d6610bc2SIgor Mammedov                           &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
2401f862184SIgor Mammedov 
2411f862184SIgor Mammedov     if (pm->acpi_memory_hotplug.is_enabled) {
2421f862184SIgor Mammedov         acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
2431f862184SIgor Mammedov                                  &pm->acpi_memory_hotplug);
2441f862184SIgor Mammedov     }
24549ab747fSPaolo Bonzini }
2466f1426abSMichael S. Tsirkin 
2476f1426abSMichael S. Tsirkin static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
2486f1426abSMichael S. Tsirkin                                  void *opaque, const char *name,
2496f1426abSMichael S. Tsirkin                                  Error **errp)
2506f1426abSMichael S. Tsirkin {
2516f1426abSMichael S. Tsirkin     ICH9LPCPMRegs *pm = opaque;
2526f1426abSMichael S. Tsirkin     uint32_t value = pm->pm_io_base + ICH9_PMIO_GPE0_STS;
2536f1426abSMichael S. Tsirkin 
2546f1426abSMichael S. Tsirkin     visit_type_uint32(v, &value, name, errp);
2556f1426abSMichael S. Tsirkin }
2566f1426abSMichael S. Tsirkin 
2571f862184SIgor Mammedov static bool ich9_pm_get_memory_hotplug_support(Object *obj, Error **errp)
2581f862184SIgor Mammedov {
2591f862184SIgor Mammedov     ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
2601f862184SIgor Mammedov 
2611f862184SIgor Mammedov     return s->pm.acpi_memory_hotplug.is_enabled;
2621f862184SIgor Mammedov }
2631f862184SIgor Mammedov 
2641f862184SIgor Mammedov static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
2651f862184SIgor Mammedov                                                Error **errp)
2661f862184SIgor Mammedov {
2671f862184SIgor Mammedov     ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
2681f862184SIgor Mammedov 
2691f862184SIgor Mammedov     s->pm.acpi_memory_hotplug.is_enabled = value;
2701f862184SIgor Mammedov }
2711f862184SIgor Mammedov 
2726ac0d8d4SAmit Shah static void ich9_pm_get_disable_s3(Object *obj, Visitor *v,
2736ac0d8d4SAmit Shah                                    void *opaque, const char *name,
2746ac0d8d4SAmit Shah                                    Error **errp)
2756ac0d8d4SAmit Shah {
2766ac0d8d4SAmit Shah     ICH9LPCPMRegs *pm = opaque;
2776ac0d8d4SAmit Shah     uint8_t value = pm->disable_s3;
2786ac0d8d4SAmit Shah 
2796ac0d8d4SAmit Shah     visit_type_uint8(v, &value, name, errp);
2806ac0d8d4SAmit Shah }
2816ac0d8d4SAmit Shah 
2826ac0d8d4SAmit Shah static void ich9_pm_set_disable_s3(Object *obj, Visitor *v,
2836ac0d8d4SAmit Shah                                    void *opaque, const char *name,
2846ac0d8d4SAmit Shah                                    Error **errp)
2856ac0d8d4SAmit Shah {
2866ac0d8d4SAmit Shah     ICH9LPCPMRegs *pm = opaque;
2876ac0d8d4SAmit Shah     Error *local_err = NULL;
2886ac0d8d4SAmit Shah     uint8_t value;
2896ac0d8d4SAmit Shah 
2906ac0d8d4SAmit Shah     visit_type_uint8(v, &value, name, &local_err);
2916ac0d8d4SAmit Shah     if (local_err) {
2926ac0d8d4SAmit Shah         goto out;
2936ac0d8d4SAmit Shah     }
2946ac0d8d4SAmit Shah     pm->disable_s3 = value;
2956ac0d8d4SAmit Shah out:
2966ac0d8d4SAmit Shah     error_propagate(errp, local_err);
2976ac0d8d4SAmit Shah }
2986ac0d8d4SAmit Shah 
2996ac0d8d4SAmit Shah static void ich9_pm_get_disable_s4(Object *obj, Visitor *v,
3006ac0d8d4SAmit Shah                                    void *opaque, const char *name,
3016ac0d8d4SAmit Shah                                    Error **errp)
3026ac0d8d4SAmit Shah {
3036ac0d8d4SAmit Shah     ICH9LPCPMRegs *pm = opaque;
3046ac0d8d4SAmit Shah     uint8_t value = pm->disable_s4;
3056ac0d8d4SAmit Shah 
3066ac0d8d4SAmit Shah     visit_type_uint8(v, &value, name, errp);
3076ac0d8d4SAmit Shah }
3086ac0d8d4SAmit Shah 
3096ac0d8d4SAmit Shah static void ich9_pm_set_disable_s4(Object *obj, Visitor *v,
3106ac0d8d4SAmit Shah                                    void *opaque, const char *name,
3116ac0d8d4SAmit Shah                                    Error **errp)
3126ac0d8d4SAmit Shah {
3136ac0d8d4SAmit Shah     ICH9LPCPMRegs *pm = opaque;
3146ac0d8d4SAmit Shah     Error *local_err = NULL;
3156ac0d8d4SAmit Shah     uint8_t value;
3166ac0d8d4SAmit Shah 
3176ac0d8d4SAmit Shah     visit_type_uint8(v, &value, name, &local_err);
3186ac0d8d4SAmit Shah     if (local_err) {
3196ac0d8d4SAmit Shah         goto out;
3206ac0d8d4SAmit Shah     }
3216ac0d8d4SAmit Shah     pm->disable_s4 = value;
3226ac0d8d4SAmit Shah out:
3236ac0d8d4SAmit Shah     error_propagate(errp, local_err);
3246ac0d8d4SAmit Shah }
3256ac0d8d4SAmit Shah 
3266ac0d8d4SAmit Shah static void ich9_pm_get_s4_val(Object *obj, Visitor *v,
3276ac0d8d4SAmit Shah                                void *opaque, const char *name,
3286ac0d8d4SAmit Shah                                Error **errp)
3296ac0d8d4SAmit Shah {
3306ac0d8d4SAmit Shah     ICH9LPCPMRegs *pm = opaque;
3316ac0d8d4SAmit Shah     uint8_t value = pm->s4_val;
3326ac0d8d4SAmit Shah 
3336ac0d8d4SAmit Shah     visit_type_uint8(v, &value, name, errp);
3346ac0d8d4SAmit Shah }
3356ac0d8d4SAmit Shah 
3366ac0d8d4SAmit Shah static void ich9_pm_set_s4_val(Object *obj, Visitor *v,
3376ac0d8d4SAmit Shah                                void *opaque, const char *name,
3386ac0d8d4SAmit Shah                                Error **errp)
3396ac0d8d4SAmit Shah {
3406ac0d8d4SAmit Shah     ICH9LPCPMRegs *pm = opaque;
3416ac0d8d4SAmit Shah     Error *local_err = NULL;
3426ac0d8d4SAmit Shah     uint8_t value;
3436ac0d8d4SAmit Shah 
3446ac0d8d4SAmit Shah     visit_type_uint8(v, &value, name, &local_err);
3456ac0d8d4SAmit Shah     if (local_err) {
3466ac0d8d4SAmit Shah         goto out;
3476ac0d8d4SAmit Shah     }
3486ac0d8d4SAmit Shah     pm->s4_val = value;
3496ac0d8d4SAmit Shah out:
3506ac0d8d4SAmit Shah     error_propagate(errp, local_err);
3516ac0d8d4SAmit Shah }
3526ac0d8d4SAmit Shah 
3536f1426abSMichael S. Tsirkin void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
3546f1426abSMichael S. Tsirkin {
3556f1426abSMichael S. Tsirkin     static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
3561f862184SIgor Mammedov     pm->acpi_memory_hotplug.is_enabled = true;
3576ac0d8d4SAmit Shah     pm->disable_s3 = 0;
3586ac0d8d4SAmit Shah     pm->disable_s4 = 0;
3596ac0d8d4SAmit Shah     pm->s4_val = 2;
3606f1426abSMichael S. Tsirkin 
3616f1426abSMichael S. Tsirkin     object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
3626f1426abSMichael S. Tsirkin                                    &pm->pm_io_base, errp);
3636f1426abSMichael S. Tsirkin     object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
3646f1426abSMichael S. Tsirkin                         ich9_pm_get_gpe0_blk,
3656f1426abSMichael S. Tsirkin                         NULL, NULL, pm, NULL);
3666f1426abSMichael S. Tsirkin     object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
3676f1426abSMichael S. Tsirkin                                    &gpe0_len, errp);
3681f862184SIgor Mammedov     object_property_add_bool(obj, "memory-hotplug-support",
3691f862184SIgor Mammedov                              ich9_pm_get_memory_hotplug_support,
3701f862184SIgor Mammedov                              ich9_pm_set_memory_hotplug_support,
3711f862184SIgor Mammedov                              NULL);
3726ac0d8d4SAmit Shah     object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
3736ac0d8d4SAmit Shah                         ich9_pm_get_disable_s3,
3746ac0d8d4SAmit Shah                         ich9_pm_set_disable_s3,
3756ac0d8d4SAmit Shah                         NULL, pm, NULL);
3766ac0d8d4SAmit Shah     object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8",
3776ac0d8d4SAmit Shah                         ich9_pm_get_disable_s4,
3786ac0d8d4SAmit Shah                         ich9_pm_set_disable_s4,
3796ac0d8d4SAmit Shah                         NULL, pm, NULL);
3806ac0d8d4SAmit Shah     object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8",
3816ac0d8d4SAmit Shah                         ich9_pm_get_s4_val,
3826ac0d8d4SAmit Shah                         ich9_pm_set_s4_val,
3836ac0d8d4SAmit Shah                         NULL, pm, NULL);
3841f862184SIgor Mammedov }
3851f862184SIgor Mammedov 
3861f862184SIgor Mammedov void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
3871f862184SIgor Mammedov {
3881f862184SIgor Mammedov     if (pm->acpi_memory_hotplug.is_enabled &&
3891f862184SIgor Mammedov         object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
3901f862184SIgor Mammedov         acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
3911f862184SIgor Mammedov                             dev, errp);
392c5171ed0SGu Zheng     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
393c5171ed0SGu Zheng         acpi_cpu_plug_cb(&pm->acpi_regs, pm->irq, &pm->gpe_cpu, dev, errp);
3941f862184SIgor Mammedov     } else {
3951f862184SIgor Mammedov         error_setg(errp, "acpi: device plug request for not supported device"
3961f862184SIgor Mammedov                    " type: %s", object_get_typename(OBJECT(dev)));
3971f862184SIgor Mammedov     }
3986f1426abSMichael S. Tsirkin }
39943f50410SIgor Mammedov 
400469b8ad2STang Chen void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
401469b8ad2STang Chen                                       Error **errp)
402469b8ad2STang Chen {
40364fec58eSTang Chen     if (pm->acpi_memory_hotplug.is_enabled &&
40464fec58eSTang Chen         object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
40564fec58eSTang Chen         acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
40664fec58eSTang Chen                                       &pm->acpi_memory_hotplug, dev, errp);
40764fec58eSTang Chen     } else {
408469b8ad2STang Chen         error_setg(errp, "acpi: device unplug request for not supported device"
409469b8ad2STang Chen                    " type: %s", object_get_typename(OBJECT(dev)));
410469b8ad2STang Chen     }
41164fec58eSTang Chen }
412469b8ad2STang Chen 
41391a734a6STang Chen void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
41491a734a6STang Chen                               Error **errp)
41591a734a6STang Chen {
416*f7d3e29dSTang Chen     if (pm->acpi_memory_hotplug.is_enabled &&
417*f7d3e29dSTang Chen         object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
418*f7d3e29dSTang Chen         acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
419*f7d3e29dSTang Chen     } else {
42091a734a6STang Chen         error_setg(errp, "acpi: device unplug for not supported device"
42191a734a6STang Chen                    " type: %s", object_get_typename(OBJECT(dev)));
42291a734a6STang Chen     }
423*f7d3e29dSTang Chen }
42491a734a6STang Chen 
42543f50410SIgor Mammedov void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
42643f50410SIgor Mammedov {
42743f50410SIgor Mammedov     ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
42843f50410SIgor Mammedov 
42943f50410SIgor Mammedov     acpi_memory_ospm_status(&s->pm.acpi_memory_hotplug, list);
43043f50410SIgor Mammedov }
431