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