Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27-rc6 213 lines 5.3 kB view raw
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 18static 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 31static 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 47static enum power_supply_property pmu_ac_props[] = { 48 POWER_SUPPLY_PROP_ONLINE, 49}; 50 51static 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 63static char *pmu_batt_types[] = { 64 "Smart", "Comet", "Hooper", "Unknown" 65}; 66 67static 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 81static 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 123static 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 138static struct platform_device *bat_pdev; 139 140static 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 179battery_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); 187ac_register_failed: 188 platform_device_unregister(bat_pdev); 189pdev_register_failed: 190success: 191 return ret; 192} 193 194static 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 208module_init(pmu_bat_init); 209module_exit(pmu_bat_exit); 210 211MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 212MODULE_LICENSE("GPL"); 213MODULE_DESCRIPTION("PMU battery driver");