[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH][RFC 05/14] power: add power chip emulation
From: |
liguang |
Subject: |
[Qemu-devel] [PATCH][RFC 05/14] power: add power chip emulation |
Date: |
Mon, 18 Mar 2013 16:39:21 +0800 |
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 <address@hidden>
---
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
diff --git a/Makefile.objs b/Makefile.objs
index a68cdac..a895e7d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -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/
diff --git a/power.c b/power.c
new file mode 100644
index 0000000..ce9cdab
--- /dev/null
+++ b/power.c
@@ -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);
+
diff --git a/power.h b/power.h
new file mode 100644
index 0000000..e36fd31
--- /dev/null
+++ b/power.h
@@ -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
--
1.7.2.5
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH][RFC 05/14] power: add power chip emulation,
liguang <=