| /* |
| * |
| * 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_GENERIC_EVENT_DEVICE_H |
| #define HW_ACPI_GENERIC_EVENT_DEVICE_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" |
| OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) |
| |
| #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 |