@@ -362,6 +362,7 @@ obj-arm-y += strongarm.o
obj-arm-y += collie.o
obj-arm-y += android_arm.o goldfish_device.o goldfish_interrupt.o
goldfish_timer.o
obj-arm-y += goldfish_tty.o goldfish_nand.o goldfish_fb.o goldfish_memlog.o
+obj-arm-y += goldfish_battery.o
obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
@@ -67,6 +67,7 @@ static void android_arm_init_(ram_addr_t ram_size,
goldfish_fb_create(gbus, 0);
goldfish_memlog_create(gbus, 0xff006000);
+ goldfish_battery_create(gbus);
goldfish_nand_create(gbus);
info.ram_size = ram_size;
new file mode 100644
@@ -0,0 +1,247 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "goldfish_device.h"
+#include "power_supply.h"
+
+
+enum {
+ /* status register */
+ BATTERY_INT_STATUS = 0x00,
+ /* set this to enable IRQ */
+ BATTERY_INT_ENABLE = 0x04,
+
+ BATTERY_AC_ONLINE = 0x08,
+ BATTERY_STATUS = 0x0C,
+ BATTERY_HEALTH = 0x10,
+ BATTERY_PRESENT = 0x14,
+ BATTERY_CAPACITY = 0x18,
+
+ BATTERY_STATUS_CHANGED = 1U << 0,
+ AC_STATUS_CHANGED = 1U << 1,
+ BATTERY_INT_MASK = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED,
+};
+
+
+typedef struct GoldfishBatteryDevice {
+ GoldfishDevice dev;
+ // IRQs
+ uint32_t int_status;
+ // irq enable mask for int_status
+ uint32_t int_enable;
+
+ int ac_online;
+ int status;
+ int health;
+ int present;
+ int capacity;
+} GoldfishBatteryDevice;
+
+static uint32_t goldfish_battery_read(void *opaque, target_phys_addr_t
offset)
+{
+ uint32_t ret;
+ GoldfishBatteryDevice *s = (GoldfishBatteryDevice *)opaque;
+
+ switch(offset) {
+ case BATTERY_INT_STATUS:
+ // return current buffer status flags
+ ret = s->int_status & s->int_enable;
+ if (ret) {
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ s->int_status = 0;
+ }
+ return ret;
+
+ case BATTERY_INT_ENABLE:
+ return s->int_enable;
+ case BATTERY_AC_ONLINE:
+ return s->ac_online;
+ case BATTERY_STATUS:
+ return s->status;
+ case BATTERY_HEALTH:
+ return s->health;
+ case BATTERY_PRESENT:
+ return s->present;
+ case BATTERY_CAPACITY:
+ return s->capacity;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_battery_read: Bad offset
%x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_battery_write(void *opaque, target_phys_addr_t offset,
uint32_t val)
+{
+ GoldfishBatteryDevice *s = (GoldfishBatteryDevice *)opaque;
+
+ switch(offset) {
+ case BATTERY_INT_ENABLE:
+ /* enable interrupts */
+ s->int_enable = val;
+// s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY |
AUDIO_INT_WRITE_BUFFER_2_EMPTY);
+// goldfish_device_set_irq(&s->dev, 0, (s->int_status &
s->int_enable));
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset
%x\n", offset);
+ }
+}
+
+static CPUReadMemoryFunc *goldfish_battery_readfn[] = {
+ goldfish_battery_read,
+ goldfish_battery_read,
+ goldfish_battery_read
+};
+
+static CPUWriteMemoryFunc *goldfish_battery_writefn[] = {
+ goldfish_battery_write,
+ goldfish_battery_write,
+ goldfish_battery_write
+};
+
+void goldfish_battery_set_prop(void *opaque, int ac, int property, int
value)
+{
+ int new_status = (ac ? AC_STATUS_CHANGED : BATTERY_STATUS_CHANGED);
+ GoldfishBatteryDevice *s = (GoldfishBatteryDevice *)opaque;
+
+ if (ac) {
+ switch (property) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ s->ac_online = value;
+ break;
+ }
+ } else {
+ switch (property) {
+ case POWER_SUPPLY_PROP_STATUS:
+ s->status = value;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ s->health = value;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ s->present = value;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ s->capacity = value;
+ break;
+ }
+ }
+
+ if (new_status != s->int_status) {
+ s->int_status |= new_status;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status &
s->int_enable));
+ }
+}
+
+void goldfish_battery_display(void *opaque, void (* callback)(void *data,
const char* string), void *data)
+{
+ GoldfishBatteryDevice *s = (GoldfishBatteryDevice *)opaque;
+ char buffer[100];
+ const char* value;
+
+ sprintf(buffer, "AC: %s\r\n", (s->ac_online ? "online" : "offline"));
+ callback(data, buffer);
+
+ switch (s->status) {
+ case POWER_SUPPLY_STATUS_CHARGING:
+ value = "Charging";
+ break;
+ case POWER_SUPPLY_STATUS_DISCHARGING:
+ value = "Discharging";
+ break;
+ case POWER_SUPPLY_STATUS_NOT_CHARGING:
+ value = "Not charging";
+ break;
+ case POWER_SUPPLY_STATUS_FULL:
+ value = "Full";
+ break;
+ default:
+ value = "Unknown";
+ break;
+ }
+ sprintf(buffer, "status: %s\r\n", value);
+ callback(data, buffer);
+
+ switch (s->health) {
+ case POWER_SUPPLY_HEALTH_GOOD:
+ value = "Good";
+ break;
+ case POWER_SUPPLY_HEALTH_OVERHEAT:
+ value = "Overhead";
+ break;
+ case POWER_SUPPLY_HEALTH_DEAD:
+ value = "Dead";
+ break;
+ case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
+ value = "Overvoltage";
+ break;
+ case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
+ value = "Unspecified failure";
+ break;
+ default:
+ value = "Unknown";
+ break;
+ }
+ sprintf(buffer, "health: %s\r\n", value);
+ callback(data, buffer);
+
+ sprintf(buffer, "present: %s\r\n", (s->present ? "true" : "false"));
+ callback(data, buffer);
+
+ sprintf(buffer, "capacity: %d\r\n", s->capacity);
+ callback(data, buffer);
+}
+
+static int goldfish_battery_init(GoldfishDevice *dev)
+{
+ return 0;
+}
+
+DeviceState *goldfish_battery_create(GoldfishBus *gbus)
+{
+ DeviceState *dev;
+ char *name = (char *)"goldfish-battery";
+
+ dev = qdev_create(&gbus->bus, name);
+ qdev_prop_set_string(dev, "name", name);
+ qdev_init_nofail(dev);
+
+ return dev;
+}
+
+static GoldfishDeviceInfo goldfish_battery_info = {
+ .init = goldfish_battery_init,
+ .readfn = goldfish_battery_readfn,
+ .writefn = goldfish_battery_writefn,
+ .qdev.name = "goldfish-battery",
+ .qdev.size = sizeof(GoldfishBatteryDevice),
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("base", GoldfishDevice, base, 0),
+ DEFINE_PROP_UINT32("id", GoldfishDevice, id, 0),
+ DEFINE_PROP_UINT32("size", GoldfishDevice, size, 0x1000),
+ DEFINE_PROP_UINT32("irq", GoldfishDevice, irq, 0),
+ DEFINE_PROP_UINT32("irq_count", GoldfishDevice, irq_count, 1),
+ DEFINE_PROP_INT32("ac_online", GoldfishBatteryDevice, ac_online,
1),
+ DEFINE_PROP_INT32("status", GoldfishBatteryDevice, status,
POWER_SUPPLY_STATUS_CHARGING),
+ DEFINE_PROP_INT32("health", GoldfishBatteryDevice, health,
POWER_SUPPLY_HEALTH_GOOD),
+ DEFINE_PROP_INT32("present", GoldfishBatteryDevice, present, 1),
// battery is present
+ DEFINE_PROP_INT32("capacity", GoldfishBatteryDevice, capacity, 50),
// 50% charged
+ DEFINE_PROP_STRING("name", GoldfishDevice, name),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
+static void goldfish_battery_register(void)
+{
+ goldfish_bus_register_withprop(&goldfish_battery_info);
+}
+device_init(goldfish_battery_register);
@@ -49,12 +49,15 @@ DeviceState *goldfish_tty_create(GoldfishBus *gbus,
CharDriverState *cs, int id,
DeviceState *goldfish_nand_create(GoldfishBus *gbus);
DeviceState *goldfish_fb_create(GoldfishBus *gbus, int id);
DeviceState *goldfish_memlog_create(GoldfishBus *gbus, uint32_t base);
+DeviceState *goldfish_battery_create(GoldfishBus *gbus);
/* Global functions provided by Goldfish devices */
void goldfish_bus_register_withprop(GoldfishDeviceInfo *info);
int goldfish_add_device_no_io(GoldfishDevice *dev);
void goldfish_device_init(DeviceState *dev, uint32_t base, uint32_t irq);
void goldfish_device_set_irq(GoldfishDevice *dev, int irq, int level);
+void goldfish_battery_set_prop(void *opaque, int ac, int property, int
value);
+void goldfish_battery_display(void *opaque, void (* callback)(void *data,
const char* string), void *data);
/** TEMP FILE SUPPORT
**
new file mode 100644
@@ -0,0 +1,109 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifndef __POWER_SUPPLY_H__
+#define __POWER_SUPPLY_H__
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+ POWER_SUPPLY_STATUS_UNKNOWN = 0,
+ POWER_SUPPLY_STATUS_CHARGING,
+ POWER_SUPPLY_STATUS_DISCHARGING,
+ POWER_SUPPLY_STATUS_NOT_CHARGING,
+ POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+ POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+ POWER_SUPPLY_HEALTH_GOOD,
+ POWER_SUPPLY_HEALTH_OVERHEAT,
+ POWER_SUPPLY_HEALTH_DEAD,
+ POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+ POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+enum {
+ POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+ POWER_SUPPLY_TECHNOLOGY_NiMH,
+ POWER_SUPPLY_TECHNOLOGY_LION,
+ POWER_SUPPLY_TECHNOLOGY_LIPO,
+ POWER_SUPPLY_TECHNOLOGY_LiFe,
+ POWER_SUPPLY_TECHNOLOGY_NiCd,
+};
+
+enum {
+ POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+ POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+ POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+ POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum power_supply_property {
+ /* Properties of type `int' */
+ POWER_SUPPLY_PROP_STATUS = 0,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+enum power_supply_type {
+ POWER_SUPPLY_TYPE_BATTERY = 0,
+ POWER_SUPPLY_TYPE_UPS,
+ POWER_SUPPLY_TYPE_MAINS,
+ POWER_SUPPLY_TYPE_USB,
+};
+
+#endif /* __POWER_SUPPLY_H__ */
Signed-off-by: Patrick Jackson <PatrickSJackson@gmail.com> --- Makefile.target | 1 + hw/android_arm.c | 1 + hw/goldfish_battery.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++ hw/goldfish_device.h | 3 + hw/power_supply.h | 109 ++++++++++++++++++++++ 5 files changed, 361 insertions(+), 0 deletions(-) create mode 100644 hw/goldfish_battery.c create mode 100644 hw/power_supply.h