1 /*
2 *
3 * Copyright (c) 2018 Intel Corporation
4 * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd
5 * Written by Samuel Ortiz, Shameer Kolothum
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2 or later, as published by the Free Software Foundation.
10 */
11
12 #include "qemu/osdep.h"
13 #include "qapi/error.h"
14 #include "hw/acpi/acpi.h"
15 #include "hw/acpi/pcihp.h"
16 #include "hw/acpi/generic_event_device.h"
17 #include "hw/pci/pci.h"
18 #include "hw/irq.h"
19 #include "hw/mem/pc-dimm.h"
20 #include "hw/mem/nvdimm.h"
21 #include "hw/pci/pci_device.h"
22 #include "hw/qdev-properties.h"
23 #include "migration/vmstate.h"
24 #include "qemu/error-report.h"
25 #include "system/runstate.h"
26
27 static const uint32_t ged_supported_events[] = {
28 ACPI_GED_MEM_HOTPLUG_EVT,
29 ACPI_GED_PWR_DOWN_EVT,
30 ACPI_GED_NVDIMM_HOTPLUG_EVT,
31 ACPI_GED_CPU_HOTPLUG_EVT,
32 ACPI_GED_PCI_HOTPLUG_EVT,
33 };
34
35 /*
36 * The ACPI Generic Event Device (GED) is a hardware-reduced specific
37 * device[ACPI v6.1 Section 5.6.9] that handles all platform events,
38 * including the hotplug ones. Platforms need to specify their own
39 * GED Event bitmap to describe what kind of events they want to support
40 * through GED. This routine uses a single interrupt for the GED device,
41 * relying on IO memory region to communicate the type of device
42 * affected by the interrupt. This way, we can support up to 32 events
43 * with a unique interrupt.
44 */
build_ged_aml(Aml * table,const char * name,HotplugHandler * hotplug_dev,uint32_t ged_irq,AmlRegionSpace rs,hwaddr ged_base)45 void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
46 uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base)
47 {
48 AcpiGedState *s = ACPI_GED(hotplug_dev);
49 Aml *crs = aml_resource_template();
50 Aml *evt, *field;
51 Aml *dev = aml_device("%s", name);
52 Aml *evt_sel = aml_local(0);
53 Aml *esel = aml_name(AML_GED_EVT_SEL);
54
55 /* _CRS interrupt */
56 aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
57 AML_EXCLUSIVE, &ged_irq, 1));
58
59 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0013")));
60 aml_append(dev, aml_name_decl("_UID", aml_string(GED_DEVICE)));
61 aml_append(dev, aml_name_decl("_CRS", crs));
62
63 /* Append IO region */
64 aml_append(dev, aml_operation_region(AML_GED_EVT_REG, rs,
65 aml_int(ged_base + ACPI_GED_EVT_SEL_OFFSET),
66 ACPI_GED_EVT_SEL_LEN));
67 field = aml_field(AML_GED_EVT_REG, AML_DWORD_ACC, AML_NOLOCK,
68 AML_WRITE_AS_ZEROS);
69 aml_append(field, aml_named_field(AML_GED_EVT_SEL,
70 ACPI_GED_EVT_SEL_LEN * BITS_PER_BYTE));
71 aml_append(dev, field);
72
73 /*
74 * For each GED event we:
75 * - Add a conditional block for each event, inside a loop.
76 * - Call a method for each supported GED event type.
77 *
78 * The resulting ASL code looks like:
79 *
80 * Local0 = ESEL
81 * If ((Local0 & One) == One)
82 * {
83 * MethodEvent0()
84 * }
85 *
86 * If ((Local0 & 0x2) == 0x2)
87 * {
88 * MethodEvent1()
89 * }
90 * ...
91 */
92 evt = aml_method("_EVT", 1, AML_SERIALIZED);
93 {
94 Aml *if_ctx;
95 uint32_t i;
96 uint32_t ged_events = ctpop32(s->ged_event_bitmap);
97
98 /* Local0 = ESEL */
99 aml_append(evt, aml_store(esel, evt_sel));
100
101 for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) {
102 uint32_t event = s->ged_event_bitmap & ged_supported_events[i];
103
104 if (!event) {
105 continue;
106 }
107
108 if_ctx = aml_if(aml_equal(aml_and(evt_sel, aml_int(event), NULL),
109 aml_int(event)));
110 switch (event) {
111 case ACPI_GED_MEM_HOTPLUG_EVT:
112 aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "."
113 MEMORY_SLOT_SCAN_METHOD));
114 break;
115 case ACPI_GED_CPU_HOTPLUG_EVT:
116 aml_append(if_ctx, aml_call0(AML_GED_EVT_CPU_SCAN_METHOD));
117 break;
118 case ACPI_GED_PWR_DOWN_EVT:
119 aml_append(if_ctx,
120 aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
121 aml_int(0x80)));
122 break;
123 case ACPI_GED_NVDIMM_HOTPLUG_EVT:
124 aml_append(if_ctx,
125 aml_notify(aml_name("\\_SB.NVDR"),
126 aml_int(0x80)));
127 break;
128 case ACPI_GED_PCI_HOTPLUG_EVT:
129 aml_append(if_ctx,
130 aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0xFFFF));
131 aml_append(if_ctx, aml_call0("\\_SB.PCI0.PCNT"));
132 aml_append(if_ctx, aml_release(aml_name("\\_SB.PCI0.BLCK")));
133 break;
134 default:
135 /*
136 * Please make sure all the events in ged_supported_events[]
137 * are handled above.
138 */
139 g_assert_not_reached();
140 }
141
142 aml_append(evt, if_ctx);
143 ged_events--;
144 }
145
146 if (ged_events) {
147 error_report("Unsupported events specified");
148 abort();
149 }
150 }
151
152 /* Append _EVT method */
153 aml_append(dev, evt);
154
155 aml_append(table, dev);
156 }
157
acpi_dsdt_add_power_button(Aml * scope)158 void acpi_dsdt_add_power_button(Aml *scope)
159 {
160 Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE);
161 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C")));
162 aml_append(dev, aml_name_decl("_UID", aml_int(0)));
163 aml_append(scope, dev);
164 }
165
166 /* Memory read by the GED _EVT AML dynamic method */
ged_evt_read(void * opaque,hwaddr addr,unsigned size)167 static uint64_t ged_evt_read(void *opaque, hwaddr addr, unsigned size)
168 {
169 uint64_t val = 0;
170 GEDState *ged_st = opaque;
171
172 switch (addr) {
173 case ACPI_GED_EVT_SEL_OFFSET:
174 /* Read the selector value and reset it */
175 val = ged_st->sel;
176 ged_st->sel = 0;
177 break;
178 default:
179 break;
180 }
181
182 return val;
183 }
184
185 /* Nothing is expected to be written to the GED memory region */
ged_evt_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)186 static void ged_evt_write(void *opaque, hwaddr addr, uint64_t data,
187 unsigned int size)
188 {
189 }
190
191 static const MemoryRegionOps ged_evt_ops = {
192 .read = ged_evt_read,
193 .write = ged_evt_write,
194 .endianness = DEVICE_LITTLE_ENDIAN,
195 .valid = {
196 .min_access_size = 4,
197 .max_access_size = 4,
198 },
199 };
200
ged_regs_read(void * opaque,hwaddr addr,unsigned size)201 static uint64_t ged_regs_read(void *opaque, hwaddr addr, unsigned size)
202 {
203 return 0;
204 }
205
ged_regs_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)206 static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data,
207 unsigned int size)
208 {
209 bool slp_en;
210 int slp_typ;
211
212 switch (addr) {
213 case ACPI_GED_REG_SLEEP_CTL:
214 slp_typ = (data >> ACPI_GED_SLP_TYP_POS) & ACPI_GED_SLP_TYP_MASK;
215 slp_en = !!(data & ACPI_GED_SLP_EN);
216 if (slp_en && slp_typ == ACPI_GED_SLP_TYP_S5) {
217 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
218 }
219 return;
220 case ACPI_GED_REG_SLEEP_STS:
221 return;
222 case ACPI_GED_REG_RESET:
223 if (data == ACPI_GED_RESET_VALUE) {
224 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
225 }
226 return;
227 }
228 }
229
230 static const MemoryRegionOps ged_regs_ops = {
231 .read = ged_regs_read,
232 .write = ged_regs_write,
233 .endianness = DEVICE_LITTLE_ENDIAN,
234 .valid = {
235 .min_access_size = 1,
236 .max_access_size = 1,
237 },
238 };
239
acpi_ged_device_pre_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)240 static void acpi_ged_device_pre_plug_cb(HotplugHandler *hotplug_dev,
241 DeviceState *dev, Error **errp)
242 {
243 if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
244 acpi_pcihp_device_pre_plug_cb(hotplug_dev, dev, errp);
245 }
246 }
247
acpi_ged_device_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)248 static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
249 DeviceState *dev, Error **errp)
250 {
251 AcpiGedState *s = ACPI_GED(hotplug_dev);
252
253 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
254 if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
255 nvdimm_acpi_plug_cb(hotplug_dev, dev);
256 } else {
257 acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp);
258 }
259 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
260 acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
261 } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
262 acpi_pcihp_device_plug_cb(hotplug_dev, &s->pcihp_state, dev, errp);
263 } else {
264 error_setg(errp, "virt: device plug request for unsupported device"
265 " type: %s", object_get_typename(OBJECT(dev)));
266 }
267 }
268
acpi_ged_unplug_request_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)269 static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
270 DeviceState *dev, Error **errp)
271 {
272 AcpiGedState *s = ACPI_GED(hotplug_dev);
273
274 if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
275 !(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
276 acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
277 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
278 acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
279 } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
280 acpi_pcihp_device_unplug_request_cb(hotplug_dev, &s->pcihp_state,
281 dev, errp);
282 } else {
283 error_setg(errp, "acpi: device unplug request for unsupported device"
284 " type: %s", object_get_typename(OBJECT(dev)));
285 }
286 }
287
acpi_ged_unplug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)288 static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
289 DeviceState *dev, Error **errp)
290 {
291 AcpiGedState *s = ACPI_GED(hotplug_dev);
292
293 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
294 acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
295 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
296 acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp);
297 } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
298 acpi_pcihp_device_unplug_cb(hotplug_dev, &s->pcihp_state, dev, errp);
299 } else {
300 error_setg(errp, "acpi: device unplug for unsupported device"
301 " type: %s", object_get_typename(OBJECT(dev)));
302 }
303 }
304
acpi_ged_ospm_status(AcpiDeviceIf * adev,ACPIOSTInfoList *** list)305 static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
306 {
307 AcpiGedState *s = ACPI_GED(adev);
308
309 acpi_memory_ospm_status(&s->memhp_state, list);
310 acpi_cpu_ospm_status(&s->cpuhp_state, list);
311 }
312
acpi_ged_send_event(AcpiDeviceIf * adev,AcpiEventStatusBits ev)313 static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
314 {
315 AcpiGedState *s = ACPI_GED(adev);
316 GEDState *ged_st = &s->ged_state;
317 uint32_t sel;
318
319 if (ev & ACPI_MEMORY_HOTPLUG_STATUS) {
320 sel = ACPI_GED_MEM_HOTPLUG_EVT;
321 } else if (ev & ACPI_POWER_DOWN_STATUS) {
322 sel = ACPI_GED_PWR_DOWN_EVT;
323 } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
324 sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
325 } else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
326 sel = ACPI_GED_CPU_HOTPLUG_EVT;
327 } else if (ev & ACPI_PCI_HOTPLUG_STATUS) {
328 sel = ACPI_GED_PCI_HOTPLUG_EVT;
329 } else {
330 /* Unknown event. Return without generating interrupt. */
331 warn_report("GED: Unsupported event %d. No irq injected", ev);
332 return;
333 }
334
335 /*
336 * Set the GED selector field to communicate the event type.
337 * This will be read by GED aml code to select the appropriate
338 * event method.
339 */
340 ged_st->sel |= sel;
341
342 /* Trigger the event by sending an interrupt to the guest. */
343 qemu_irq_pulse(s->irq);
344 }
345
346 static const Property acpi_ged_properties[] = {
347 DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0),
348 DEFINE_PROP_BOOL(ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, AcpiGedState,
349 pcihp_state.use_acpi_hotplug_bridge, 0),
350 DEFINE_PROP_LINK("bus", AcpiGedState, pcihp_state.root,
351 TYPE_PCI_BUS, PCIBus *),
352 };
353
354 static const VMStateDescription vmstate_memhp_state = {
355 .name = "acpi-ged/memhp",
356 .version_id = 1,
357 .minimum_version_id = 1,
358 .fields = (const VMStateField[]) {
359 VMSTATE_MEMORY_HOTPLUG(memhp_state, AcpiGedState),
360 VMSTATE_END_OF_LIST()
361 }
362 };
363
cpuhp_needed(void * opaque)364 static bool cpuhp_needed(void *opaque)
365 {
366 MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
367
368 return mc->has_hotpluggable_cpus;
369 }
370
371 static const VMStateDescription vmstate_cpuhp_state = {
372 .name = "acpi-ged/cpuhp",
373 .version_id = 1,
374 .minimum_version_id = 1,
375 .needed = cpuhp_needed,
376 .fields = (VMStateField[]) {
377 VMSTATE_CPU_HOTPLUG(cpuhp_state, AcpiGedState),
378 VMSTATE_END_OF_LIST()
379 }
380 };
381
382 static const VMStateDescription vmstate_ged_state = {
383 .name = "acpi-ged-state",
384 .version_id = 1,
385 .minimum_version_id = 1,
386 .fields = (const VMStateField[]) {
387 VMSTATE_UINT32(sel, GEDState),
388 VMSTATE_END_OF_LIST()
389 }
390 };
391
392 static const VMStateDescription vmstate_ghes = {
393 .name = "acpi-ghes",
394 .version_id = 1,
395 .minimum_version_id = 1,
396 .fields = (const VMStateField[]) {
397 VMSTATE_UINT64(hw_error_le, AcpiGhesState),
398 VMSTATE_END_OF_LIST()
399 },
400 };
401
ghes_needed(void * opaque)402 static bool ghes_needed(void *opaque)
403 {
404 AcpiGedState *s = opaque;
405 return s->ghes_state.hw_error_le;
406 }
407
408 static const VMStateDescription vmstate_ghes_state = {
409 .name = "acpi-ged/ghes",
410 .version_id = 1,
411 .minimum_version_id = 1,
412 .needed = ghes_needed,
413 .fields = (const VMStateField[]) {
414 VMSTATE_STRUCT(ghes_state, AcpiGedState, 1,
415 vmstate_ghes, AcpiGhesState),
416 VMSTATE_END_OF_LIST()
417 }
418 };
419
pcihp_needed(void * opaque)420 static bool pcihp_needed(void *opaque)
421 {
422 AcpiGedState *s = opaque;
423 return s->pcihp_state.use_acpi_hotplug_bridge;
424 }
425
426 static const VMStateDescription vmstate_pcihp_state = {
427 .name = "acpi-ged/pcihp",
428 .version_id = 1,
429 .minimum_version_id = 1,
430 .needed = pcihp_needed,
431 .fields = (const VMStateField[]) {
432 VMSTATE_PCI_HOTPLUG(pcihp_state,
433 AcpiGedState,
434 NULL, NULL),
435 VMSTATE_END_OF_LIST()
436 }
437 };
438
439 static const VMStateDescription vmstate_acpi_ged = {
440 .name = "acpi-ged",
441 .version_id = 1,
442 .minimum_version_id = 1,
443 .fields = (const VMStateField[]) {
444 VMSTATE_STRUCT(ged_state, AcpiGedState, 1, vmstate_ged_state, GEDState),
445 VMSTATE_END_OF_LIST(),
446 },
447 .subsections = (const VMStateDescription * const []) {
448 &vmstate_memhp_state,
449 &vmstate_cpuhp_state,
450 &vmstate_ghes_state,
451 &vmstate_pcihp_state,
452 NULL
453 }
454 };
455
acpi_ged_realize(DeviceState * dev,Error ** errp)456 static void acpi_ged_realize(DeviceState *dev, Error **errp)
457 {
458 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
459 AcpiGedState *s = ACPI_GED(dev);
460 AcpiPciHpState *pcihp_state = &s->pcihp_state;
461 uint32_t ged_events;
462 int i;
463
464 if (pcihp_state->use_acpi_hotplug_bridge) {
465 s->ged_event_bitmap |= ACPI_GED_PCI_HOTPLUG_EVT;
466 }
467 ged_events = ctpop32(s->ged_event_bitmap);
468
469 for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) {
470 uint32_t event = s->ged_event_bitmap & ged_supported_events[i];
471
472 if (!event) {
473 continue;
474 }
475
476 switch (event) {
477 case ACPI_GED_CPU_HOTPLUG_EVT:
478 /* initialize CPU Hotplug related regions */
479 memory_region_init(&s->container_cpuhp, OBJECT(dev),
480 "cpuhp container",
481 ACPI_CPU_HOTPLUG_REG_LEN);
482 sysbus_init_mmio(sbd, &s->container_cpuhp);
483 cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev),
484 &s->cpuhp_state, 0);
485 break;
486 case ACPI_GED_PCI_HOTPLUG_EVT:
487 memory_region_init(&s->container_pcihp, OBJECT(dev),
488 ACPI_PCIHP_REGION_NAME, ACPI_PCIHP_SIZE);
489 sysbus_init_mmio(sbd, &s->container_pcihp);
490 acpi_pcihp_init(OBJECT(s), &s->pcihp_state,
491 &s->container_pcihp, 0);
492 qbus_set_hotplug_handler(BUS(s->pcihp_state.root), OBJECT(dev));
493 }
494 ged_events--;
495 }
496
497 if (ged_events) {
498 error_report("Unsupported events specified");
499 abort();
500 }
501 }
502
acpi_ged_initfn(Object * obj)503 static void acpi_ged_initfn(Object *obj)
504 {
505 DeviceState *dev = DEVICE(obj);
506 AcpiGedState *s = ACPI_GED(dev);
507 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
508 GEDState *ged_st = &s->ged_state;
509
510 memory_region_init_io(&ged_st->evt, obj, &ged_evt_ops, ged_st,
511 TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN);
512 sysbus_init_mmio(sbd, &ged_st->evt);
513
514 sysbus_init_irq(sbd, &s->irq);
515
516 s->memhp_state.is_enabled = true;
517 /*
518 * GED handles memory hotplug event and acpi-mem-hotplug
519 * memory region gets initialized here. Create an exclusive
520 * container for memory hotplug IO and expose it as GED sysbus
521 * MMIO so that boards can map it separately.
522 */
523 memory_region_init(&s->container_memhp, OBJECT(dev), "memhp container",
524 MEMORY_HOTPLUG_IO_LEN);
525 sysbus_init_mmio(sbd, &s->container_memhp);
526 acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev),
527 &s->memhp_state, 0);
528
529 memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st,
530 TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT);
531 sysbus_init_mmio(sbd, &ged_st->regs);
532 }
533
ged_reset_hold(Object * obj,ResetType type)534 static void ged_reset_hold(Object *obj, ResetType type)
535 {
536 AcpiGedState *s = ACPI_GED(obj);
537
538 if (s->pcihp_state.use_acpi_hotplug_bridge) {
539 acpi_pcihp_reset(&s->pcihp_state);
540 }
541 }
542
acpi_ged_class_init(ObjectClass * class,const void * data)543 static void acpi_ged_class_init(ObjectClass *class, const void *data)
544 {
545 DeviceClass *dc = DEVICE_CLASS(class);
546 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class);
547 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class);
548 ResettableClass *rc = RESETTABLE_CLASS(class);
549 AcpiGedClass *gedc = ACPI_GED_CLASS(class);
550
551 dc->desc = "ACPI Generic Event Device";
552 device_class_set_props(dc, acpi_ged_properties);
553 dc->vmsd = &vmstate_acpi_ged;
554 dc->realize = acpi_ged_realize;
555
556 hc->pre_plug = acpi_ged_device_pre_plug_cb;
557 hc->plug = acpi_ged_device_plug_cb;
558 hc->unplug_request = acpi_ged_unplug_request_cb;
559 hc->unplug = acpi_ged_unplug_cb;
560 resettable_class_set_parent_phases(rc, NULL, ged_reset_hold, NULL,
561 &gedc->parent_phases);
562
563 adevc->ospm_status = acpi_ged_ospm_status;
564 adevc->send_event = acpi_ged_send_event;
565 }
566
567 static const TypeInfo acpi_ged_info = {
568 .name = TYPE_ACPI_GED,
569 .parent = TYPE_SYS_BUS_DEVICE,
570 .instance_size = sizeof(AcpiGedState),
571 .instance_init = acpi_ged_initfn,
572 .class_init = acpi_ged_class_init,
573 .class_size = sizeof(AcpiGedClass),
574 .interfaces = (const InterfaceInfo[]) {
575 { TYPE_HOTPLUG_HANDLER },
576 { TYPE_ACPI_DEVICE_IF },
577 { }
578 }
579 };
580
acpi_ged_register_types(void)581 static void acpi_ged_register_types(void)
582 {
583 type_register_static(&acpi_ged_info);
584 }
585
586 type_init(acpi_ged_register_types)
587