/* * * Copyright (c) 2018 Intel Corporation * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd * Written by Samuel Ortiz, Shameer Kolothum * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2 or later, as published by the Free Software Foundation. * * The ACPI Generic Event Device (GED) is a hardware-reduced specific * device[ACPI v6.1 Section 5.6.9] that handles all platform events, * including the hotplug ones. Generic Event Device allows platforms * to handle interrupts in ACPI ASL statements. It follows a very * similar approach like the _EVT method from GPIO events. All * interrupts are listed in _CRS and the handler is written in _EVT * method. Here, we use a single interrupt for the GED device, relying * on IO memory region to communicate the type of device affected by * the interrupt. This way, we can support up to 32 events with a * unique interrupt. * * Here is an example. * * Device (\_SB.GED) * { * Name (_HID, "ACPI0013") * Name (_UID, Zero) * Name (_CRS, ResourceTemplate () * { * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) * { * 0x00000029, * } * }) * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) * Field (EREG, DWordAcc, NoLock, WriteAsZeros) * { * ESEL, 32 * } * * Method (_EVT, 1, Serialized) // _EVT: Event * { * Local0 = ESEL // ESEL = IO memory region which specifies the * // device type. * If (((Local0 & One) == One)) * { * MethodEvent1() * } * If ((Local0 & 0x2) == 0x2) * { * MethodEvent2() * } * ... * } * } * */ #ifndef HW_ACPI_GED_H #define HW_ACPI_GED_H #include "hw/sysbus.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/ghes.h" #include "qom/object.h" #define ACPI_POWER_BUTTON_DEVICE "PWRB" #define TYPE_ACPI_GED "acpi-ged" typedef struct AcpiGedState AcpiGedState; DECLARE_INSTANCE_CHECKER(AcpiGedState, ACPI_GED, TYPE_ACPI_GED) #define TYPE_ACPI_GED_X86 "acpi-ged-x86" #define ACPI_GED_X86(obj) \ OBJECT_CHECK(AcpiGedX86State, (obj), TYPE_ACPI_GED_X86) #define ACPI_GED_EVT_SEL_OFFSET 0x0 #define ACPI_GED_EVT_SEL_LEN 0x4 #define ACPI_GED_REG_SLEEP_CTL 0x00 #define ACPI_GED_REG_SLEEP_STS 0x01 #define ACPI_GED_REG_RESET 0x02 #define ACPI_GED_REG_COUNT 0x03 /* ACPI_GED_REG_RESET value for reset*/ #define ACPI_GED_RESET_VALUE 0x42 /* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */ #define ACPI_GED_SLP_TYP_S5 0x05 #define GED_DEVICE "GED" #define AML_GED_EVT_REG "EREG" #define AML_GED_EVT_SEL "ESEL" /* * Platforms need to specify the GED event bitmap * to describe what kind of events they want to support * through GED. */ #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 #define ACPI_GED_PWR_DOWN_EVT 0x2 #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 typedef struct GEDState { MemoryRegion evt; MemoryRegion regs; uint32_t sel; } GEDState; struct AcpiGedState { SysBusDevice parent_obj; MemHotplugState memhp_state; MemoryRegion container_memhp; GEDState ged_state; uint32_t ged_event_bitmap; qemu_irq irq; AcpiGhesState ghes_state; }; void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); void acpi_dsdt_add_power_button(Aml *scope); #endif