1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/*
*
* 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"
OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
#define TYPE_ACPI_GED_X86 "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
|