@@ -73,6 +73,7 @@ common-obj-y += bt-host.o bt-vhci.o
common-obj-y += dma-helpers.o
common-obj-y += vl.o
+common-obj-y += power.o
common-obj-$(CONFIG_SLIRP) += slirp/
new file mode 100644
@@ -0,0 +1,133 @@
+#include "power.h"
+#include "qemu/main-loop.h"
+
+
+PowerChip pmc;
+
+void power_management_set(PowerState ps)
+{
+ switch (ps) {
+ case POWER_OFF:
+ case POWER_ON:
+ case POWER_SUSPEND:
+ case POWER_WAKEUP:
+ pmc.power_state = ps;
+ break;
+ case POWER_RESET:
+ pmc.power_state = ps | POWER_OFF;
+ break;
+ default:
+ pmc.power_state = POWER_IDLE;
+ break;
+ }
+}
+
+static void power_management_on(DeviceState *dev)
+{
+ qbus_reset_all_fn(sysbus_get_default());
+}
+
+static void power_management_off(DeviceState *dev)
+{
+ qbus_power_off(sysbus_get_default());
+}
+
+static void power_management_suspend(DeviceState *dev)
+{
+ qbus_power_suspend(sysbus_get_default());
+}
+
+static void power_management_wakeup(DeviceState *dev)
+{
+ qbus_power_wakeup(sysbus_get_default());
+}
+
+WakeupReason power_management_wakeup_reason(void)
+{
+ return pmc.wakeup_reason;
+}
+
+void power_management_wakeup_reason_set(WakeupReason wr)
+{
+ pmc.wakeup_reason = wr;
+}
+
+void power_management_wakeup_capability(WakeupReason wr, bool ok)
+{
+ switch (wr) {
+ case QEMU_WAKEUP_REASON_RTC:
+ case QEMU_WAKEUP_REASON_PMTIMER:
+ if (ok) {
+ pmc.wakeup_capability |= 1 << wr;
+ } else {
+ pmc.wakeup_capability &= ~(1 << wr);
+ }
+ default:
+ break;
+ }
+}
+
+PowerState power_management(void)
+{
+ int reset = pmc.power_state & 0x80;
+
+ switch (pmc.power_state & 0xf) {
+ case POWER_ON:
+ power_management_on(NULL);
+ break;
+ case POWER_OFF:
+ power_management_off(NULL);
+ if (reset) {
+ pmc.power_state = POWER_ON;
+ }
+ break;
+ case POWER_SUSPEND:
+ power_management_suspend(NULL);
+ break;
+ case POWER_WAKEUP:
+ if (1 << pmc.wakeup_reason & pmc.wakeup_capability) {
+ power_management_wakeup(NULL);
+ }
+ default:
+ break;
+ }
+
+ if (reset == 0) {
+ pmc.power_state = POWER_IDLE;
+ }
+
+ return pmc.power_state;
+}
+
+static void power_chip_init(Object *obj)
+{
+ pmc.power_state = POWER_IDLE;
+ pmc.wakeup_reason = QEMU_WAKEUP_REASON_UNKNOWN;
+ pmc.wakeup_capability = QEMU_WAKEUP_REASON_RTC | QEMU_WAKEUP_REASON_PMTIMER;
+}
+
+static void power_chip_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->on = power_management_on;
+ dc->off = power_management_off;
+ dc->wakeup = power_management_wakeup;
+ dc->suspend = power_management_suspend;
+}
+
+static const TypeInfo power_chip_info = {
+ .name = TYPE_POWER_CHIP,
+ .parent = NULL,
+ .instance_size = sizeof(PowerChip),
+ .instance_init = power_chip_init,
+ .class_init = power_chip_class_init,
+};
+
+static void power_chip_types(void)
+{
+ type_register_static(&power_chip_info);
+}
+
+type_init(power_chip_types);
+
new file mode 100644
@@ -0,0 +1,41 @@
+#ifndef ____POWER_H_
+#define ____POWER_H_
+
+#include "hw/qdev.h"
+#include "hw/qdev-core.h"
+
+
+typedef enum PowerState {
+ POWER_IDLE = 0,
+ POWER_OFF = 0x1,
+ POWER_ON = 0x2,
+ POWER_RESET = 0x80,
+ POWER_SUSPEND = 0x4,
+ POWER_WAKEUP = 0x8,
+} PowerState;
+
+typedef enum WakeupReason {
+ QEMU_WAKEUP_REASON_UNKNOWN = -1,
+ QEMU_WAKEUP_REASON_OTHER = 0,
+ QEMU_WAKEUP_REASON_RTC,
+ QEMU_WAKEUP_REASON_PMTIMER,
+} WakeupReason;
+
+typedef struct PowerChip {
+ DeviceState dev;
+ PowerState power_state;
+ WakeupReason wakeup_reason;
+ int wakeup_capability;
+} PowerChip;
+
+#define TYPE_POWER_CHIP "power-chip"
+
+#define PMC(obj) OBJECT_CHECK(PowerChip, (obj), TYPE_CPU)
+
+void power_management_set(PowerState ps);
+PowerState power_management(void);
+WakeupReason power_management_wakeup_reason(void);
+void power_management_wakeup_reason_set(WakeupReason wr);
+void power_management_wakeup_capability(WakeupReason wr, bool ok);
+
+#endif
this power chip manage on/off/wakeup/suspend power state transition, when state changed, it will trigger all callbacks embedded in all device object. This just like power action in real world. Signed-off-by: liguang <lig.fnst@cn.fujitsu.com> --- Makefile.objs | 1 + power.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ power.h | 41 +++++++++++++++++ 3 files changed, 175 insertions(+), 0 deletions(-) create mode 100644 power.c create mode 100644 power.h