Merge git://git.infradead.org/battery-2.6

* git://git.infradead.org/battery-2.6:
apm_power: check I.intval for zero value, we use it as the divisor
MAINTAINERS: remove kernel-discuss@handhelds.org list
pda_power: implement polling
pda_power: various cleanups
apm_power: support using VOLTAGE_* properties for apm calculations
pda_power: add suspend/resume support
power_supply: add few more values and props
pda_power: only register available psu
power: fix incorrect unregistration in power_supply_create_attrs error path
power: remove POWER_SUPPLY_PROP_CAPACITY_LEVEL
[BATTERY] power_supply_leds: use kasprintf
[BATTERY] Every file should include the headers containing the prototypes for its global functions.

+301 -153
+4 -2
Documentation/power_supply_class.txt
··· 87 Battery driver also can use this attribute just to inform userspace 88 about maximal and minimal voltage thresholds of a given battery. 89 90 CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when 91 battery considered full/empty. 92 ··· 104 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. 105 106 CAPACITY - capacity in percents. 107 - CAPACITY_LEVEL - capacity level. This corresponds to 108 - POWER_SUPPLY_CAPACITY_LEVEL_*. 109 110 TEMP - temperature of the power supply. 111 TEMP_AMBIENT - ambient temperature.
··· 87 Battery driver also can use this attribute just to inform userspace 88 about maximal and minimal voltage thresholds of a given battery. 89 90 + VOLTAGE_MAX, VOLTAGE_MIN - same as _DESIGN voltage values except that 91 + these ones should be used if hardware could only guess (measure and 92 + retain) the thresholds of a given power supply. 93 + 94 CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when 95 battery considered full/empty. 96 ··· 100 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. 101 102 CAPACITY - capacity in percents. 103 104 TEMP - temperature of the power supply. 105 TEMP_AMBIENT - ambient temperature.
-1
MAINTAINERS
··· 3053 P: David Woodhouse 3054 M: dwmw2@infradead.org 3055 L: linux-kernel@vger.kernel.org 3056 - L: kernel-discuss@handhelds.org 3057 T: git git.infradead.org/battery-2.6.git 3058 S: Maintained 3059
··· 3053 P: David Woodhouse 3054 M: dwmw2@infradead.org 3055 L: linux-kernel@vger.kernel.org 3056 T: git git.infradead.org/battery-2.6.git 3057 S: Maintained 3058
+73 -21
drivers/power/apm_power.c
··· 13 #include <linux/power_supply.h> 14 #include <linux/apm-emulation.h> 15 16 - static DEFINE_MUTEX(apm_mutex); 17 #define PSY_PROP(psy, prop, val) psy->get_property(psy, \ 18 POWER_SUPPLY_PROP_##prop, val) 19 ··· 22 23 #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val) 24 25 static struct power_supply *main_battery; 26 27 struct find_bat_param { 28 struct power_supply *main; ··· 114 } 115 } 116 117 - static int calculate_time(int status, int using_charge) 118 { 119 union power_supply_propval full; 120 union power_supply_propval empty; ··· 133 return -1; 134 } 135 136 - if (using_charge) { 137 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; 138 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; 139 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 140 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 141 cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; 142 cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; 143 - } else { 144 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; 145 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 146 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; 147 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 148 cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; 149 cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; 150 } 151 152 if (_MPSY_PROP(full_prop, &full)) { ··· 190 return -((cur.intval - empty.intval) * 60L) / I.intval; 191 } 192 193 - static int calculate_capacity(int using_charge) 194 { 195 enum power_supply_property full_prop, empty_prop; 196 enum power_supply_property full_design_prop, empty_design_prop; ··· 217 union power_supply_propval empty, full, cur; 218 int ret; 219 220 - if (using_charge) { 221 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; 222 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 223 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; 224 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; 225 now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; 226 avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; 227 - } else { 228 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; 229 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; 230 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 231 empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; 232 now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; 233 avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; 234 } 235 236 if (_MPSY_PROP(full_prop, &full)) { ··· 310 info->battery_life = capacity.intval; 311 } else { 312 /* try calculate using energy */ 313 - info->battery_life = calculate_capacity(0); 314 /* if failed try calculate using charge instead */ 315 if (info->battery_life == -1) 316 - info->battery_life = calculate_capacity(1); 317 } 318 319 /* charging status */ ··· 338 339 if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { 340 if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) || 341 - !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) { 342 info->time = time_to_full.intval / 60; 343 - } else { 344 - info->time = calculate_time(status.intval, 0); 345 - if (info->time == -1) 346 - info->time = calculate_time(status.intval, 1); 347 - } 348 } else { 349 if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) || 350 - !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) { 351 info->time = time_to_empty.intval / 60; 352 - } else { 353 - info->time = calculate_time(status.intval, 0); 354 - if (info->time == -1) 355 - info->time = calculate_time(status.intval, 1); 356 - } 357 } 358 359 mutex_unlock(&apm_mutex);
··· 13 #include <linux/power_supply.h> 14 #include <linux/apm-emulation.h> 15 16 + 17 #define PSY_PROP(psy, prop, val) psy->get_property(psy, \ 18 POWER_SUPPLY_PROP_##prop, val) 19 ··· 22 23 #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val) 24 25 + static DEFINE_MUTEX(apm_mutex); 26 static struct power_supply *main_battery; 27 + 28 + enum apm_source { 29 + SOURCE_ENERGY, 30 + SOURCE_CHARGE, 31 + SOURCE_VOLTAGE, 32 + }; 33 34 struct find_bat_param { 35 struct power_supply *main; ··· 107 } 108 } 109 110 + static int do_calculate_time(int status, enum apm_source source) 111 { 112 union power_supply_propval full; 113 union power_supply_propval empty; ··· 126 return -1; 127 } 128 129 + if (!I.intval) 130 + return 0; 131 + 132 + switch (source) { 133 + case SOURCE_CHARGE: 134 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; 135 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; 136 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 137 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 138 cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; 139 cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; 140 + break; 141 + case SOURCE_ENERGY: 142 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; 143 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 144 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; 145 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 146 cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; 147 cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; 148 + break; 149 + case SOURCE_VOLTAGE: 150 + full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; 151 + full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; 152 + empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; 153 + empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; 154 + cur_avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; 155 + cur_now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; 156 + break; 157 + default: 158 + printk(KERN_ERR "Unsupported source: %d\n", source); 159 + return -1; 160 } 161 162 if (_MPSY_PROP(full_prop, &full)) { ··· 166 return -((cur.intval - empty.intval) * 60L) / I.intval; 167 } 168 169 + static int calculate_time(int status) 170 + { 171 + int time; 172 + 173 + time = do_calculate_time(status, SOURCE_ENERGY); 174 + if (time != -1) 175 + return time; 176 + 177 + time = do_calculate_time(status, SOURCE_CHARGE); 178 + if (time != -1) 179 + return time; 180 + 181 + time = do_calculate_time(status, SOURCE_VOLTAGE); 182 + if (time != -1) 183 + return time; 184 + 185 + return -1; 186 + } 187 + 188 + static int calculate_capacity(enum apm_source source) 189 { 190 enum power_supply_property full_prop, empty_prop; 191 enum power_supply_property full_design_prop, empty_design_prop; ··· 174 union power_supply_propval empty, full, cur; 175 int ret; 176 177 + switch (source) { 178 + case SOURCE_CHARGE: 179 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; 180 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 181 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; 182 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; 183 now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; 184 avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; 185 + break; 186 + case SOURCE_ENERGY: 187 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; 188 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; 189 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 190 empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; 191 now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; 192 avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; 193 + case SOURCE_VOLTAGE: 194 + full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; 195 + empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; 196 + full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; 197 + empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; 198 + now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; 199 + avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; 200 + break; 201 + default: 202 + printk(KERN_ERR "Unsupported source: %d\n", source); 203 + return -1; 204 } 205 206 if (_MPSY_PROP(full_prop, &full)) { ··· 254 info->battery_life = capacity.intval; 255 } else { 256 /* try calculate using energy */ 257 + info->battery_life = calculate_capacity(SOURCE_ENERGY); 258 /* if failed try calculate using charge instead */ 259 if (info->battery_life == -1) 260 + info->battery_life = calculate_capacity(SOURCE_CHARGE); 261 + if (info->battery_life == -1) 262 + info->battery_life = calculate_capacity(SOURCE_VOLTAGE); 263 } 264 265 /* charging status */ ··· 280 281 if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { 282 if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) || 283 + !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) 284 info->time = time_to_full.intval / 60; 285 + else 286 + info->time = calculate_time(status.intval); 287 } else { 288 if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) || 289 + !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) 290 info->time = time_to_empty.intval / 60; 291 + else 292 + info->time = calculate_time(status.intval); 293 } 294 295 mutex_unlock(&apm_mutex);
-9
drivers/power/olpc_battery.c
··· 226 return ret; 227 val->intval = ec_byte; 228 break; 229 - case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 230 - if (ec_byte & BAT_STAT_FULL) 231 - val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 232 - else if (ec_byte & BAT_STAT_LOW) 233 - val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 234 - else 235 - val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 236 - break; 237 case POWER_SUPPLY_PROP_TEMP: 238 ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); 239 if (ret) ··· 257 POWER_SUPPLY_PROP_VOLTAGE_AVG, 258 POWER_SUPPLY_PROP_CURRENT_AVG, 259 POWER_SUPPLY_PROP_CAPACITY, 260 - POWER_SUPPLY_PROP_CAPACITY_LEVEL, 261 POWER_SUPPLY_PROP_TEMP, 262 POWER_SUPPLY_PROP_TEMP_AMBIENT, 263 POWER_SUPPLY_PROP_MANUFACTURER,
··· 226 return ret; 227 val->intval = ec_byte; 228 break; 229 case POWER_SUPPLY_PROP_TEMP: 230 ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); 231 if (ret) ··· 265 POWER_SUPPLY_PROP_VOLTAGE_AVG, 266 POWER_SUPPLY_PROP_CURRENT_AVG, 267 POWER_SUPPLY_PROP_CAPACITY, 268 POWER_SUPPLY_PROP_TEMP, 269 POWER_SUPPLY_PROP_TEMP_AMBIENT, 270 POWER_SUPPLY_PROP_MANUFACTURER,
+203 -81
drivers/power/pda_power.c
··· 32 static struct resource *ac_irq, *usb_irq; 33 static struct timer_list charger_timer; 34 static struct timer_list supply_timer; 35 36 static int pda_power_get_property(struct power_supply *psy, 37 enum power_supply_property psp, ··· 73 "backup-battery", 74 }; 75 76 - static struct power_supply pda_power_supplies[] = { 77 - { 78 - .name = "ac", 79 - .type = POWER_SUPPLY_TYPE_MAINS, 80 - .supplied_to = pda_power_supplied_to, 81 - .num_supplicants = ARRAY_SIZE(pda_power_supplied_to), 82 - .properties = pda_power_props, 83 - .num_properties = ARRAY_SIZE(pda_power_props), 84 - .get_property = pda_power_get_property, 85 - }, 86 - { 87 - .name = "usb", 88 - .type = POWER_SUPPLY_TYPE_USB, 89 - .supplied_to = pda_power_supplied_to, 90 - .num_supplicants = ARRAY_SIZE(pda_power_supplied_to), 91 - .properties = pda_power_props, 92 - .num_properties = ARRAY_SIZE(pda_power_props), 93 - .get_property = pda_power_get_property, 94 - }, 95 }; 96 97 static void update_charger(void) 98 { 99 if (!pdata->set_charge) 100 return; 101 102 - if (pdata->is_ac_online && pdata->is_ac_online()) { 103 dev_dbg(dev, "charger on (AC)\n"); 104 pdata->set_charge(PDA_POWER_CHARGE_AC); 105 - } else if (pdata->is_usb_online && pdata->is_usb_online()) { 106 dev_dbg(dev, "charger on (USB)\n"); 107 pdata->set_charge(PDA_POWER_CHARGE_USB); 108 } else { ··· 119 } 120 } 121 122 - static void supply_timer_func(unsigned long power_supply_ptr) 123 { 124 - void *power_supply = (void *)power_supply_ptr; 125 126 - power_supply_changed(power_supply); 127 } 128 129 - static void charger_timer_func(unsigned long power_supply_ptr) 130 { 131 update_charger(); 132 133 - /* Okay, charger set. Now wait a bit before notifying supplicants, 134 - * charge power should stabilize. */ 135 - supply_timer.data = power_supply_ptr; 136 mod_timer(&supply_timer, 137 jiffies + msecs_to_jiffies(pdata->wait_for_charger)); 138 } 139 140 static irqreturn_t power_changed_isr(int irq, void *power_supply) 141 { 142 - /* Wait a bit before reading ac/usb line status and setting charger, 143 - * because ac/usb status readings may lag from irq. */ 144 - charger_timer.data = (unsigned long)power_supply; 145 mod_timer(&charger_timer, 146 jiffies + msecs_to_jiffies(pdata->wait_for_status)); 147 return IRQ_HANDLED; 148 } 149 150 static int pda_power_probe(struct platform_device *pdev) ··· 209 210 pdata = pdev->dev.platform_data; 211 212 update_charger(); 213 214 if (!pdata->wait_for_status) ··· 218 if (!pdata->wait_for_charger) 219 pdata->wait_for_charger = 500; 220 221 setup_timer(&charger_timer, charger_timer_func, 0); 222 setup_timer(&supply_timer, supply_timer_func, 0); 223 224 ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac"); 225 usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb"); 226 - if (!ac_irq && !usb_irq) { 227 - dev_err(dev, "no ac/usb irq specified\n"); 228 - ret = -ENODEV; 229 - goto noirqs; 230 - } 231 232 if (pdata->supplied_to) { 233 - pda_power_supplies[0].supplied_to = pdata->supplied_to; 234 - pda_power_supplies[1].supplied_to = pdata->supplied_to; 235 - pda_power_supplies[0].num_supplicants = pdata->num_supplicants; 236 - pda_power_supplies[1].num_supplicants = pdata->num_supplicants; 237 } 238 239 - ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]); 240 - if (ret) { 241 - dev_err(dev, "failed to register %s power supply\n", 242 - pda_power_supplies[0].name); 243 - goto supply0_failed; 244 - } 245 - 246 - ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]); 247 - if (ret) { 248 - dev_err(dev, "failed to register %s power supply\n", 249 - pda_power_supplies[1].name); 250 - goto supply1_failed; 251 - } 252 - 253 - if (ac_irq) { 254 - ret = request_irq(ac_irq->start, power_changed_isr, 255 - get_irq_flags(ac_irq), ac_irq->name, 256 - &pda_power_supplies[0]); 257 if (ret) { 258 - dev_err(dev, "request ac irq failed\n"); 259 - goto ac_irq_failed; 260 } 261 } 262 263 - if (usb_irq) { 264 - ret = request_irq(usb_irq->start, power_changed_isr, 265 - get_irq_flags(usb_irq), usb_irq->name, 266 - &pda_power_supplies[1]); 267 if (ret) { 268 - dev_err(dev, "request usb irq failed\n"); 269 - goto usb_irq_failed; 270 } 271 } 272 273 - goto success; 274 275 usb_irq_failed: 276 - if (ac_irq) 277 - free_irq(ac_irq->start, &pda_power_supplies[0]); 278 ac_irq_failed: 279 - power_supply_unregister(&pda_power_supplies[1]); 280 - supply1_failed: 281 - power_supply_unregister(&pda_power_supplies[0]); 282 - supply0_failed: 283 - noirqs: 284 wrongid: 285 - success: 286 return ret; 287 } 288 289 static int pda_power_remove(struct platform_device *pdev) 290 { 291 - if (usb_irq) 292 - free_irq(usb_irq->start, &pda_power_supplies[1]); 293 - if (ac_irq) 294 - free_irq(ac_irq->start, &pda_power_supplies[0]); 295 del_timer_sync(&charger_timer); 296 del_timer_sync(&supply_timer); 297 - power_supply_unregister(&pda_power_supplies[1]); 298 - power_supply_unregister(&pda_power_supplies[0]); 299 return 0; 300 } 301 302 static struct platform_driver pda_power_pdrv = { 303 .driver = { ··· 357 }, 358 .probe = pda_power_probe, 359 .remove = pda_power_remove, 360 }; 361 362 static int __init pda_power_init(void)
··· 32 static struct resource *ac_irq, *usb_irq; 33 static struct timer_list charger_timer; 34 static struct timer_list supply_timer; 35 + static struct timer_list polling_timer; 36 + static int polling; 37 + 38 + enum { 39 + PDA_PSY_OFFLINE = 0, 40 + PDA_PSY_ONLINE = 1, 41 + PDA_PSY_TO_CHANGE, 42 + }; 43 + static int new_ac_status = -1; 44 + static int new_usb_status = -1; 45 + static int ac_status = -1; 46 + static int usb_status = -1; 47 48 static int pda_power_get_property(struct power_supply *psy, 49 enum power_supply_property psp, ··· 61 "backup-battery", 62 }; 63 64 + static struct power_supply pda_psy_ac = { 65 + .name = "ac", 66 + .type = POWER_SUPPLY_TYPE_MAINS, 67 + .supplied_to = pda_power_supplied_to, 68 + .num_supplicants = ARRAY_SIZE(pda_power_supplied_to), 69 + .properties = pda_power_props, 70 + .num_properties = ARRAY_SIZE(pda_power_props), 71 + .get_property = pda_power_get_property, 72 }; 73 + 74 + static struct power_supply pda_psy_usb = { 75 + .name = "usb", 76 + .type = POWER_SUPPLY_TYPE_USB, 77 + .supplied_to = pda_power_supplied_to, 78 + .num_supplicants = ARRAY_SIZE(pda_power_supplied_to), 79 + .properties = pda_power_props, 80 + .num_properties = ARRAY_SIZE(pda_power_props), 81 + .get_property = pda_power_get_property, 82 + }; 83 + 84 + static void update_status(void) 85 + { 86 + if (pdata->is_ac_online) 87 + new_ac_status = !!pdata->is_ac_online(); 88 + 89 + if (pdata->is_usb_online) 90 + new_usb_status = !!pdata->is_usb_online(); 91 + } 92 93 static void update_charger(void) 94 { 95 if (!pdata->set_charge) 96 return; 97 98 + if (new_ac_status > 0) { 99 dev_dbg(dev, "charger on (AC)\n"); 100 pdata->set_charge(PDA_POWER_CHARGE_AC); 101 + } else if (new_usb_status > 0) { 102 dev_dbg(dev, "charger on (USB)\n"); 103 pdata->set_charge(PDA_POWER_CHARGE_USB); 104 } else { ··· 99 } 100 } 101 102 + static void supply_timer_func(unsigned long unused) 103 { 104 + if (ac_status == PDA_PSY_TO_CHANGE) { 105 + ac_status = new_ac_status; 106 + power_supply_changed(&pda_psy_ac); 107 + } 108 109 + if (usb_status == PDA_PSY_TO_CHANGE) { 110 + usb_status = new_usb_status; 111 + power_supply_changed(&pda_psy_usb); 112 + } 113 } 114 115 + static void psy_changed(void) 116 { 117 update_charger(); 118 119 + /* 120 + * Okay, charger set. Now wait a bit before notifying supplicants, 121 + * charge power should stabilize. 122 + */ 123 mod_timer(&supply_timer, 124 jiffies + msecs_to_jiffies(pdata->wait_for_charger)); 125 } 126 127 + static void charger_timer_func(unsigned long unused) 128 + { 129 + update_status(); 130 + psy_changed(); 131 + } 132 + 133 static irqreturn_t power_changed_isr(int irq, void *power_supply) 134 { 135 + if (power_supply == &pda_psy_ac) 136 + ac_status = PDA_PSY_TO_CHANGE; 137 + else if (power_supply == &pda_psy_usb) 138 + usb_status = PDA_PSY_TO_CHANGE; 139 + else 140 + return IRQ_NONE; 141 + 142 + /* 143 + * Wait a bit before reading ac/usb line status and setting charger, 144 + * because ac/usb status readings may lag from irq. 145 + */ 146 mod_timer(&charger_timer, 147 jiffies + msecs_to_jiffies(pdata->wait_for_status)); 148 + 149 return IRQ_HANDLED; 150 + } 151 + 152 + static void polling_timer_func(unsigned long unused) 153 + { 154 + int changed = 0; 155 + 156 + dev_dbg(dev, "polling...\n"); 157 + 158 + update_status(); 159 + 160 + if (!ac_irq && new_ac_status != ac_status) { 161 + ac_status = PDA_PSY_TO_CHANGE; 162 + changed = 1; 163 + } 164 + 165 + if (!usb_irq && new_usb_status != usb_status) { 166 + usb_status = PDA_PSY_TO_CHANGE; 167 + changed = 1; 168 + } 169 + 170 + if (changed) 171 + psy_changed(); 172 + 173 + mod_timer(&polling_timer, 174 + jiffies + msecs_to_jiffies(pdata->polling_interval)); 175 } 176 177 static int pda_power_probe(struct platform_device *pdev) ··· 142 143 pdata = pdev->dev.platform_data; 144 145 + update_status(); 146 update_charger(); 147 148 if (!pdata->wait_for_status) ··· 150 if (!pdata->wait_for_charger) 151 pdata->wait_for_charger = 500; 152 153 + if (!pdata->polling_interval) 154 + pdata->polling_interval = 2000; 155 + 156 setup_timer(&charger_timer, charger_timer_func, 0); 157 setup_timer(&supply_timer, supply_timer_func, 0); 158 159 ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac"); 160 usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb"); 161 162 if (pdata->supplied_to) { 163 + pda_psy_ac.supplied_to = pdata->supplied_to; 164 + pda_psy_ac.num_supplicants = pdata->num_supplicants; 165 + pda_psy_usb.supplied_to = pdata->supplied_to; 166 + pda_psy_usb.num_supplicants = pdata->num_supplicants; 167 } 168 169 + if (pdata->is_ac_online) { 170 + ret = power_supply_register(&pdev->dev, &pda_psy_ac); 171 if (ret) { 172 + dev_err(dev, "failed to register %s power supply\n", 173 + pda_psy_ac.name); 174 + goto ac_supply_failed; 175 + } 176 + 177 + if (ac_irq) { 178 + ret = request_irq(ac_irq->start, power_changed_isr, 179 + get_irq_flags(ac_irq), ac_irq->name, 180 + &pda_psy_ac); 181 + if (ret) { 182 + dev_err(dev, "request ac irq failed\n"); 183 + goto ac_irq_failed; 184 + } 185 + } else { 186 + polling = 1; 187 } 188 } 189 190 + if (pdata->is_usb_online) { 191 + ret = power_supply_register(&pdev->dev, &pda_psy_usb); 192 if (ret) { 193 + dev_err(dev, "failed to register %s power supply\n", 194 + pda_psy_usb.name); 195 + goto usb_supply_failed; 196 + } 197 + 198 + if (usb_irq) { 199 + ret = request_irq(usb_irq->start, power_changed_isr, 200 + get_irq_flags(usb_irq), 201 + usb_irq->name, &pda_psy_usb); 202 + if (ret) { 203 + dev_err(dev, "request usb irq failed\n"); 204 + goto usb_irq_failed; 205 + } 206 + } else { 207 + polling = 1; 208 } 209 } 210 211 + if (polling) { 212 + dev_dbg(dev, "will poll for status\n"); 213 + setup_timer(&polling_timer, polling_timer_func, 0); 214 + mod_timer(&polling_timer, 215 + jiffies + msecs_to_jiffies(pdata->polling_interval)); 216 + } 217 + 218 + if (ac_irq || usb_irq) 219 + device_init_wakeup(&pdev->dev, 1); 220 + 221 + return 0; 222 223 usb_irq_failed: 224 + if (pdata->is_usb_online) 225 + power_supply_unregister(&pda_psy_usb); 226 + usb_supply_failed: 227 + if (pdata->is_ac_online && ac_irq) 228 + free_irq(ac_irq->start, &pda_psy_ac); 229 ac_irq_failed: 230 + if (pdata->is_ac_online) 231 + power_supply_unregister(&pda_psy_ac); 232 + ac_supply_failed: 233 wrongid: 234 return ret; 235 } 236 237 static int pda_power_remove(struct platform_device *pdev) 238 { 239 + if (pdata->is_usb_online && usb_irq) 240 + free_irq(usb_irq->start, &pda_psy_usb); 241 + if (pdata->is_ac_online && ac_irq) 242 + free_irq(ac_irq->start, &pda_psy_ac); 243 + 244 + if (polling) 245 + del_timer_sync(&polling_timer); 246 del_timer_sync(&charger_timer); 247 del_timer_sync(&supply_timer); 248 + 249 + if (pdata->is_usb_online) 250 + power_supply_unregister(&pda_psy_usb); 251 + if (pdata->is_ac_online) 252 + power_supply_unregister(&pda_psy_ac); 253 + 254 return 0; 255 } 256 + 257 + #ifdef CONFIG_PM 258 + static int pda_power_suspend(struct platform_device *pdev, pm_message_t state) 259 + { 260 + if (device_may_wakeup(&pdev->dev)) { 261 + if (ac_irq) 262 + enable_irq_wake(ac_irq->start); 263 + if (usb_irq) 264 + enable_irq_wake(usb_irq->start); 265 + } 266 + 267 + return 0; 268 + } 269 + 270 + static int pda_power_resume(struct platform_device *pdev) 271 + { 272 + if (device_may_wakeup(&pdev->dev)) { 273 + if (usb_irq) 274 + disable_irq_wake(usb_irq->start); 275 + if (ac_irq) 276 + disable_irq_wake(ac_irq->start); 277 + } 278 + 279 + return 0; 280 + } 281 + #else 282 + #define pda_power_suspend NULL 283 + #define pda_power_resume NULL 284 + #endif /* CONFIG_PM */ 285 286 static struct platform_driver pda_power_pdrv = { 287 .driver = { ··· 237 }, 238 .probe = pda_power_probe, 239 .remove = pda_power_remove, 240 + .suspend = pda_power_suspend, 241 + .resume = pda_power_resume, 242 }; 243 244 static int __init pda_power_init(void)
+9 -18
drivers/power/power_supply_leds.c
··· 10 * You may use this code as per GPL version 2 11 */ 12 13 #include <linux/power_supply.h> 14 15 /* Battery specific LEDs triggers. */ 16 ··· 49 { 50 int rc = 0; 51 52 - psy->charging_full_trig_name = kmalloc(strlen(psy->name) + 53 - sizeof("-charging-or-full"), GFP_KERNEL); 54 if (!psy->charging_full_trig_name) 55 goto charging_full_failed; 56 57 - psy->charging_trig_name = kmalloc(strlen(psy->name) + 58 - sizeof("-charging"), GFP_KERNEL); 59 if (!psy->charging_trig_name) 60 goto charging_failed; 61 62 - psy->full_trig_name = kmalloc(strlen(psy->name) + 63 - sizeof("-full"), GFP_KERNEL); 64 if (!psy->full_trig_name) 65 goto full_failed; 66 - 67 - strcpy(psy->charging_full_trig_name, psy->name); 68 - strcat(psy->charging_full_trig_name, "-charging-or-full"); 69 - strcpy(psy->charging_trig_name, psy->name); 70 - strcat(psy->charging_trig_name, "-charging"); 71 - strcpy(psy->full_trig_name, psy->name); 72 - strcat(psy->full_trig_name, "-full"); 73 74 led_trigger_register_simple(psy->charging_full_trig_name, 75 &psy->charging_full_trig); ··· 113 { 114 int rc = 0; 115 116 - psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"), 117 - GFP_KERNEL); 118 if (!psy->online_trig_name) 119 goto online_failed; 120 - 121 - strcpy(psy->online_trig_name, psy->name); 122 - strcat(psy->online_trig_name, "-online"); 123 124 led_trigger_register_simple(psy->online_trig_name, &psy->online_trig); 125
··· 10 * You may use this code as per GPL version 2 11 */ 12 13 + #include <linux/kernel.h> 14 #include <linux/power_supply.h> 15 + 16 + #include "power_supply.h" 17 18 /* Battery specific LEDs triggers. */ 19 ··· 46 { 47 int rc = 0; 48 49 + psy->charging_full_trig_name = kasprintf(GFP_KERNEL, 50 + "%s-charging-or-full", psy->name); 51 if (!psy->charging_full_trig_name) 52 goto charging_full_failed; 53 54 + psy->charging_trig_name = kasprintf(GFP_KERNEL, 55 + "%s-charging", psy->name); 56 if (!psy->charging_trig_name) 57 goto charging_failed; 58 59 + psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->name); 60 if (!psy->full_trig_name) 61 goto full_failed; 62 63 led_trigger_register_simple(psy->charging_full_trig_name, 64 &psy->charging_full_trig); ··· 118 { 119 int rc = 0; 120 121 + psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online", psy->name); 122 if (!psy->online_trig_name) 123 goto online_failed; 124 125 led_trigger_register_simple(psy->online_trig_name, &psy->online_trig); 126
+8 -11
drivers/power/power_supply_sysfs.c
··· 14 #include <linux/ctype.h> 15 #include <linux/power_supply.h> 16 17 /* 18 * This is because the name "current" breaks the device attr macro. 19 * The "current" word resolves to "(get_current())" so instead of ··· 48 "Unspecified failure" 49 }; 50 static char *technology_text[] = { 51 - "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd" 52 - }; 53 - static char *capacity_level_text[] = { 54 - "Unknown", "Critical", "Low", "Normal", "High", "Full" 55 }; 56 ssize_t ret; 57 struct power_supply *psy = dev_get_drvdata(dev); ··· 71 return sprintf(buf, "%s\n", health_text[value.intval]); 72 else if (off == POWER_SUPPLY_PROP_TECHNOLOGY) 73 return sprintf(buf, "%s\n", technology_text[value.intval]); 74 - else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL) 75 - return sprintf(buf, "%s\n", 76 - capacity_level_text[value.intval]); 77 else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) 78 return sprintf(buf, "%s\n", value.strval); 79 ··· 85 POWER_SUPPLY_ATTR(present), 86 POWER_SUPPLY_ATTR(online), 87 POWER_SUPPLY_ATTR(technology), 88 POWER_SUPPLY_ATTR(voltage_max_design), 89 POWER_SUPPLY_ATTR(voltage_min_design), 90 POWER_SUPPLY_ATTR(voltage_now), ··· 158 &power_supply_attrs[psy->properties[j]]); 159 statics_failed: 160 while (i--) 161 - device_remove_file(psy->dev, 162 - &power_supply_static_attrs[psy->properties[i]]); 163 succeed: 164 return rc; 165 } ··· 168 int i; 169 170 for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) 171 - device_remove_file(psy->dev, 172 - &power_supply_static_attrs[i]); 173 174 for (i = 0; i < psy->num_properties; i++) 175 device_remove_file(psy->dev,
··· 14 #include <linux/ctype.h> 15 #include <linux/power_supply.h> 16 17 + #include "power_supply.h" 18 + 19 /* 20 * This is because the name "current" breaks the device attr macro. 21 * The "current" word resolves to "(get_current())" so instead of ··· 46 "Unspecified failure" 47 }; 48 static char *technology_text[] = { 49 + "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", 50 + "LiMn" 51 }; 52 ssize_t ret; 53 struct power_supply *psy = dev_get_drvdata(dev); ··· 71 return sprintf(buf, "%s\n", health_text[value.intval]); 72 else if (off == POWER_SUPPLY_PROP_TECHNOLOGY) 73 return sprintf(buf, "%s\n", technology_text[value.intval]); 74 else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) 75 return sprintf(buf, "%s\n", value.strval); 76 ··· 88 POWER_SUPPLY_ATTR(present), 89 POWER_SUPPLY_ATTR(online), 90 POWER_SUPPLY_ATTR(technology), 91 + POWER_SUPPLY_ATTR(voltage_max), 92 + POWER_SUPPLY_ATTR(voltage_min), 93 POWER_SUPPLY_ATTR(voltage_max_design), 94 POWER_SUPPLY_ATTR(voltage_min_design), 95 POWER_SUPPLY_ATTR(voltage_now), ··· 159 &power_supply_attrs[psy->properties[j]]); 160 statics_failed: 161 while (i--) 162 + device_remove_file(psy->dev, &power_supply_static_attrs[i]); 163 succeed: 164 return rc; 165 } ··· 170 int i; 171 172 for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) 173 + device_remove_file(psy->dev, &power_supply_static_attrs[i]); 174 175 for (i = 0; i < psy->num_properties; i++) 176 device_remove_file(psy->dev,
+1
include/linux/pda_power.h
··· 26 27 unsigned int wait_for_status; /* msecs, default is 500 */ 28 unsigned int wait_for_charger; /* msecs, default is 500 */ 29 }; 30 31 #endif /* __PDA_POWER_H__ */
··· 26 27 unsigned int wait_for_status; /* msecs, default is 500 */ 28 unsigned int wait_for_charger; /* msecs, default is 500 */ 29 + unsigned int polling_interval; /* msecs, default is 2000 */ 30 }; 31 32 #endif /* __PDA_POWER_H__ */
+3 -10
include/linux/power_supply.h
··· 54 POWER_SUPPLY_TECHNOLOGY_LIPO, 55 POWER_SUPPLY_TECHNOLOGY_LiFe, 56 POWER_SUPPLY_TECHNOLOGY_NiCd, 57 - }; 58 - 59 - enum { 60 - POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0, 61 - POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL, 62 - POWER_SUPPLY_CAPACITY_LEVEL_LOW, 63 - POWER_SUPPLY_CAPACITY_LEVEL_NORMAL, 64 - POWER_SUPPLY_CAPACITY_LEVEL_HIGH, 65 - POWER_SUPPLY_CAPACITY_LEVEL_FULL, 66 }; 67 68 enum power_supply_property { ··· 64 POWER_SUPPLY_PROP_PRESENT, 65 POWER_SUPPLY_PROP_ONLINE, 66 POWER_SUPPLY_PROP_TECHNOLOGY, 67 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 68 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 69 POWER_SUPPLY_PROP_VOLTAGE_NOW, ··· 85 POWER_SUPPLY_PROP_ENERGY_NOW, 86 POWER_SUPPLY_PROP_ENERGY_AVG, 87 POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ 88 - POWER_SUPPLY_PROP_CAPACITY_LEVEL, 89 POWER_SUPPLY_PROP_TEMP, 90 POWER_SUPPLY_PROP_TEMP_AMBIENT, 91 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
··· 54 POWER_SUPPLY_TECHNOLOGY_LIPO, 55 POWER_SUPPLY_TECHNOLOGY_LiFe, 56 POWER_SUPPLY_TECHNOLOGY_NiCd, 57 + POWER_SUPPLY_TECHNOLOGY_LiMn, 58 }; 59 60 enum power_supply_property { ··· 72 POWER_SUPPLY_PROP_PRESENT, 73 POWER_SUPPLY_PROP_ONLINE, 74 POWER_SUPPLY_PROP_TECHNOLOGY, 75 + POWER_SUPPLY_PROP_VOLTAGE_MAX, 76 + POWER_SUPPLY_PROP_VOLTAGE_MIN, 77 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 78 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 79 POWER_SUPPLY_PROP_VOLTAGE_NOW, ··· 91 POWER_SUPPLY_PROP_ENERGY_NOW, 92 POWER_SUPPLY_PROP_ENERGY_AVG, 93 POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ 94 POWER_SUPPLY_PROP_TEMP, 95 POWER_SUPPLY_PROP_TEMP_AMBIENT, 96 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,