diff options
| author | David Woodhouse <dwmw2@infradead.org> | 2007-05-03 16:47:40 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@infradead.org> | 2007-07-10 06:28:12 -0400 |
| commit | efea58e397dec84e37209c98619d39a46872db4d (patch) | |
| tree | 45159f261783eab6a0df2d2e2999f46cb41eb6d6 | |
| parent | fe0e3153acfef4864b69932cf116eb5f38f7500c (diff) | |
[BATTERY] Apple PMU driver
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Anton Vorontsov <cbou@mail.ru>
| -rw-r--r-- | drivers/power/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/power/Makefile | 1 | ||||
| -rw-r--r-- | drivers/power/pmu_battery.c | 215 |
3 files changed, 223 insertions, 0 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 921456243e4b..051724f62fa3 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
| @@ -35,4 +35,11 @@ config BATTERY_DS2760 | |||
| 35 | help | 35 | help |
| 36 | Say Y here to enable support for batteries with ds2760 chip. | 36 | Say Y here to enable support for batteries with ds2760 chip. |
| 37 | 37 | ||
| 38 | config BATTERY_PMU | ||
| 39 | tristate "Apple PMU battery" | ||
| 40 | depends on ADB_PMU | ||
| 41 | help | ||
| 42 | Say Y here to expose battery information on Apple machines | ||
| 43 | through the generic battery class. | ||
| 44 | |||
| 38 | endif # POWER_SUPPLY | 45 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index a978ba15f6c5..a072b0400cda 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
| @@ -18,3 +18,4 @@ obj-$(CONFIG_PDA_POWER) += pda_power.o | |||
| 18 | obj-$(CONFIG_APM_POWER) += apm_power.o | 18 | obj-$(CONFIG_APM_POWER) += apm_power.o |
| 19 | 19 | ||
| 20 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o | 20 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o |
| 21 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o | ||
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c new file mode 100644 index 000000000000..2fea4af0e40a --- /dev/null +++ b/drivers/power/pmu_battery.c | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | /* | ||
| 2 | * Battery class driver for Apple PMU | ||
| 3 | * | ||
| 4 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/power_supply.h> | ||
| 15 | #include <linux/adb.h> | ||
| 16 | #include <linux/pmu.h> | ||
| 17 | |||
| 18 | static struct pmu_battery_dev { | ||
| 19 | struct power_supply bat; | ||
| 20 | struct pmu_battery_info *pbi; | ||
| 21 | char name[16]; | ||
| 22 | int propval; | ||
| 23 | } *pbats[PMU_MAX_BATTERIES]; | ||
| 24 | |||
| 25 | #define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat) | ||
| 26 | |||
| 27 | /********************************************************************* | ||
| 28 | * Power | ||
| 29 | *********************************************************************/ | ||
| 30 | |||
| 31 | static int pmu_get_ac_prop(struct power_supply *psy, | ||
| 32 | enum power_supply_property psp, | ||
| 33 | union power_supply_propval *val) | ||
| 34 | { | ||
| 35 | switch (psp) { | ||
| 36 | case POWER_SUPPLY_PROP_ONLINE: | ||
| 37 | val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) || | ||
| 38 | (pmu_battery_count == 0); | ||
| 39 | break; | ||
| 40 | default: | ||
| 41 | return -EINVAL; | ||
| 42 | } | ||
| 43 | |||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | static enum power_supply_property pmu_ac_props[] = { | ||
| 48 | POWER_SUPPLY_PROP_ONLINE, | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct power_supply pmu_ac = { | ||
| 52 | .name = "pmu-ac", | ||
| 53 | .type = POWER_SUPPLY_TYPE_MAINS, | ||
| 54 | .properties = pmu_ac_props, | ||
| 55 | .num_properties = ARRAY_SIZE(pmu_ac_props), | ||
| 56 | .get_property = pmu_get_ac_prop, | ||
| 57 | }; | ||
| 58 | |||
| 59 | /********************************************************************* | ||
| 60 | * Battery properties | ||
| 61 | *********************************************************************/ | ||
| 62 | |||
| 63 | static char *pmu_batt_types[] = { | ||
| 64 | "Smart", "Comet", "Hooper", "Unknown" | ||
| 65 | }; | ||
| 66 | |||
| 67 | static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi) | ||
| 68 | { | ||
| 69 | switch (pbi->flags & PMU_BATT_TYPE_MASK) { | ||
| 70 | case PMU_BATT_TYPE_SMART: | ||
| 71 | return pmu_batt_types[0]; | ||
| 72 | case PMU_BATT_TYPE_COMET: | ||
| 73 | return pmu_batt_types[1]; | ||
| 74 | case PMU_BATT_TYPE_HOOPER: | ||
| 75 | return pmu_batt_types[2]; | ||
| 76 | default: break; | ||
| 77 | } | ||
| 78 | return pmu_batt_types[3]; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int pmu_bat_get_property(struct power_supply *psy, | ||
| 82 | enum power_supply_property psp, | ||
| 83 | union power_supply_propval *val) | ||
| 84 | { | ||
| 85 | struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy); | ||
| 86 | struct pmu_battery_info *pbi = pbat->pbi; | ||
| 87 | |||
| 88 | switch (psp) { | ||
| 89 | case POWER_SUPPLY_PROP_STATUS: | ||
| 90 | if (pbi->flags & PMU_BATT_CHARGING) | ||
| 91 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
| 92 | else | ||
| 93 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
| 94 | break; | ||
| 95 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 96 | val->intval = !!(pbi->flags & PMU_BATT_PRESENT); | ||
| 97 | break; | ||
| 98 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
| 99 | val->strval = pmu_bat_get_model_name(pbi); | ||
| 100 | break; | ||
| 101 | case POWER_SUPPLY_PROP_ENERGY_AVG: | ||
| 102 | val->intval = pbi->charge * 1000; /* mWh -> µWh */ | ||
| 103 | break; | ||
| 104 | case POWER_SUPPLY_PROP_ENERGY_FULL: | ||
| 105 | val->intval = pbi->max_charge * 1000; /* mWh -> µWh */ | ||
| 106 | break; | ||
| 107 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
| 108 | val->intval = pbi->amperage * 1000; /* mA -> µA */ | ||
| 109 | break; | ||
| 110 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
| 111 | val->intval = pbi->voltage * 1000; /* mV -> µV */ | ||
| 112 | break; | ||
| 113 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | ||
| 114 | val->intval = pbi->time_remaining; | ||
| 115 | break; | ||
| 116 | default: | ||
| 117 | return -EINVAL; | ||
| 118 | } | ||
| 119 | |||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static enum power_supply_property pmu_bat_props[] = { | ||
| 124 | POWER_SUPPLY_PROP_STATUS, | ||
| 125 | POWER_SUPPLY_PROP_PRESENT, | ||
| 126 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
| 127 | POWER_SUPPLY_PROP_ENERGY_AVG, | ||
| 128 | POWER_SUPPLY_PROP_ENERGY_FULL, | ||
| 129 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
| 130 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
| 131 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | ||
| 132 | }; | ||
| 133 | |||
| 134 | /********************************************************************* | ||
| 135 | * Initialisation | ||
| 136 | *********************************************************************/ | ||
| 137 | |||
| 138 | static struct platform_device *bat_pdev; | ||
| 139 | |||
| 140 | static int __init pmu_bat_init(void) | ||
| 141 | { | ||
| 142 | int ret; | ||
| 143 | int i; | ||
| 144 | |||
| 145 | bat_pdev = platform_device_register_simple("pmu-battery", | ||
| 146 | 0, NULL, 0); | ||
| 147 | if (IS_ERR(bat_pdev)) { | ||
| 148 | ret = PTR_ERR(bat_pdev); | ||
| 149 | goto pdev_register_failed; | ||
| 150 | } | ||
| 151 | |||
| 152 | ret = power_supply_register(&bat_pdev->dev, &pmu_ac); | ||
| 153 | if (ret) | ||
| 154 | goto ac_register_failed; | ||
| 155 | |||
| 156 | for (i = 0; i < pmu_battery_count; i++) { | ||
| 157 | struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat), | ||
| 158 | GFP_KERNEL); | ||
| 159 | if (!pbat) | ||
| 160 | break; | ||
| 161 | |||
| 162 | sprintf(pbat->name, "PMU battery %d", i); | ||
| 163 | pbat->bat.name = pbat->name; | ||
| 164 | pbat->bat.properties = pmu_bat_props; | ||
| 165 | pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props); | ||
| 166 | pbat->bat.get_property = pmu_bat_get_property; | ||
| 167 | pbat->pbi = &pmu_batteries[i]; | ||
| 168 | |||
| 169 | ret = power_supply_register(&bat_pdev->dev, &pbat->bat); | ||
| 170 | if (ret) { | ||
| 171 | kfree(pbat); | ||
| 172 | goto battery_register_failed; | ||
| 173 | } | ||
| 174 | pbats[i] = pbat; | ||
| 175 | } | ||
| 176 | |||
| 177 | goto success; | ||
| 178 | |||
| 179 | battery_register_failed: | ||
| 180 | while (i--) { | ||
| 181 | if (!pbats[i]) | ||
| 182 | continue; | ||
| 183 | power_supply_unregister(&pbats[i]->bat); | ||
| 184 | kfree(pbats[i]); | ||
| 185 | } | ||
| 186 | power_supply_unregister(&pmu_ac); | ||
| 187 | ac_register_failed: | ||
| 188 | platform_device_unregister(bat_pdev); | ||
| 189 | pdev_register_failed: | ||
| 190 | success: | ||
| 191 | return ret; | ||
| 192 | } | ||
| 193 | |||
| 194 | static void __exit pmu_bat_exit(void) | ||
| 195 | { | ||
| 196 | int i; | ||
| 197 | |||
| 198 | for (i = 0; i < PMU_MAX_BATTERIES; i++) { | ||
| 199 | if (!pbats[i]) | ||
| 200 | continue; | ||
| 201 | power_supply_unregister(&pbats[i]->bat); | ||
| 202 | kfree(pbats[i]); | ||
| 203 | } | ||
| 204 | power_supply_unregister(&pmu_ac); | ||
| 205 | platform_device_unregister(bat_pdev); | ||
| 206 | |||
| 207 | return; | ||
| 208 | } | ||
| 209 | |||
| 210 | module_init(pmu_bat_init); | ||
| 211 | module_exit(pmu_bat_exit); | ||
| 212 | |||
| 213 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | ||
| 214 | MODULE_LICENSE("GPL"); | ||
| 215 | MODULE_DESCRIPTION("PMU battery driver"); | ||
