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

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

* git://git.infradead.org/battery-2.6:
bq27x00_battery: use unaligned access helper
power_supply: fix dependency of tosa_battery
power_supply: Support for Texas Instruments BQ27200 battery managers
power_supply: Add function to return system-wide power state
pda_power: Check and handle return value of set_irq_wake

+427 -5
+7 -1
drivers/power/Kconfig
··· 51 51 52 52 config BATTERY_TOSA 53 53 tristate "Sharp SL-6000 (tosa) battery" 54 - depends on MACH_TOSA && MFD_TC6393XB 54 + depends on MACH_TOSA && MFD_TC6393XB && TOUCHSCREEN_WM97XX 55 55 help 56 56 Say Y to enable support for the battery on the Sharp Zaurus 57 57 SL-6000 (tosa) models. ··· 61 61 depends on TOUCHSCREEN_WM97XX=y 62 62 help 63 63 Say Y to enable support for battery measured by WM97xx aux port. 64 + 65 + config BATTERY_BQ27x00 66 + tristate "BQ27200 battery driver" 67 + depends on I2C 68 + help 69 + Say Y here to enable support for batteries with BQ27200(I2C) chip. 64 70 65 71 endif # POWER_SUPPLY
+1
drivers/power/Makefile
··· 22 22 obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 23 23 obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o 24 24 obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o 25 + obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
+381
drivers/power/bq27x00_battery.c
··· 1 + /* 2 + * BQ27x00 battery driver 3 + * 4 + * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> 5 + * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> 6 + * 7 + * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. 8 + * 9 + * This package is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + * 13 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 + * 17 + */ 18 + #include <linux/module.h> 19 + #include <linux/param.h> 20 + #include <linux/jiffies.h> 21 + #include <linux/workqueue.h> 22 + #include <linux/delay.h> 23 + #include <linux/platform_device.h> 24 + #include <linux/power_supply.h> 25 + #include <linux/idr.h> 26 + #include <linux/i2c.h> 27 + #include <asm/unaligned.h> 28 + 29 + #define DRIVER_VERSION "1.0.0" 30 + 31 + #define BQ27x00_REG_TEMP 0x06 32 + #define BQ27x00_REG_VOLT 0x08 33 + #define BQ27x00_REG_RSOC 0x0B /* Relative State-of-Charge */ 34 + #define BQ27x00_REG_AI 0x14 35 + #define BQ27x00_REG_FLAGS 0x0A 36 + 37 + /* If the system has several batteries we need a different name for each 38 + * of them... 39 + */ 40 + static DEFINE_IDR(battery_id); 41 + static DEFINE_MUTEX(battery_mutex); 42 + 43 + struct bq27x00_device_info; 44 + struct bq27x00_access_methods { 45 + int (*read)(u8 reg, int *rt_value, int b_single, 46 + struct bq27x00_device_info *di); 47 + }; 48 + 49 + struct bq27x00_device_info { 50 + struct device *dev; 51 + int id; 52 + int voltage_uV; 53 + int current_uA; 54 + int temp_C; 55 + int charge_rsoc; 56 + struct bq27x00_access_methods *bus; 57 + struct power_supply bat; 58 + 59 + struct i2c_client *client; 60 + }; 61 + 62 + static enum power_supply_property bq27x00_battery_props[] = { 63 + POWER_SUPPLY_PROP_PRESENT, 64 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 65 + POWER_SUPPLY_PROP_CURRENT_NOW, 66 + POWER_SUPPLY_PROP_CAPACITY, 67 + POWER_SUPPLY_PROP_TEMP, 68 + }; 69 + 70 + /* 71 + * Common code for BQ27x00 devices 72 + */ 73 + 74 + static int bq27x00_read(u8 reg, int *rt_value, int b_single, 75 + struct bq27x00_device_info *di) 76 + { 77 + int ret; 78 + 79 + ret = di->bus->read(reg, rt_value, b_single, di); 80 + *rt_value = be16_to_cpu(*rt_value); 81 + 82 + return ret; 83 + } 84 + 85 + /* 86 + * Return the battery temperature in Celcius degrees 87 + * Or < 0 if something fails. 88 + */ 89 + static int bq27x00_battery_temperature(struct bq27x00_device_info *di) 90 + { 91 + int ret; 92 + int temp = 0; 93 + 94 + ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di); 95 + if (ret) { 96 + dev_err(di->dev, "error reading temperature\n"); 97 + return ret; 98 + } 99 + 100 + return (temp >> 2) - 273; 101 + } 102 + 103 + /* 104 + * Return the battery Voltage in milivolts 105 + * Or < 0 if something fails. 106 + */ 107 + static int bq27x00_battery_voltage(struct bq27x00_device_info *di) 108 + { 109 + int ret; 110 + int volt = 0; 111 + 112 + ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di); 113 + if (ret) { 114 + dev_err(di->dev, "error reading voltage\n"); 115 + return ret; 116 + } 117 + 118 + return volt; 119 + } 120 + 121 + /* 122 + * Return the battery average current 123 + * Note that current can be negative signed as well 124 + * Or 0 if something fails. 125 + */ 126 + static int bq27x00_battery_current(struct bq27x00_device_info *di) 127 + { 128 + int ret; 129 + int curr = 0; 130 + int flags = 0; 131 + 132 + ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di); 133 + if (ret) { 134 + dev_err(di->dev, "error reading current\n"); 135 + return 0; 136 + } 137 + ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di); 138 + if (ret < 0) { 139 + dev_err(di->dev, "error reading flags\n"); 140 + return 0; 141 + } 142 + if ((flags & (1 << 7)) != 0) { 143 + dev_dbg(di->dev, "negative current!\n"); 144 + return -curr; 145 + } 146 + return curr; 147 + } 148 + 149 + /* 150 + * Return the battery Relative State-of-Charge 151 + * Or < 0 if something fails. 152 + */ 153 + static int bq27x00_battery_rsoc(struct bq27x00_device_info *di) 154 + { 155 + int ret; 156 + int rsoc = 0; 157 + 158 + ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di); 159 + if (ret) { 160 + dev_err(di->dev, "error reading relative State-of-Charge\n"); 161 + return ret; 162 + } 163 + 164 + return rsoc >> 8; 165 + } 166 + 167 + #define to_bq27x00_device_info(x) container_of((x), \ 168 + struct bq27x00_device_info, bat); 169 + 170 + static int bq27x00_battery_get_property(struct power_supply *psy, 171 + enum power_supply_property psp, 172 + union power_supply_propval *val) 173 + { 174 + struct bq27x00_device_info *di = to_bq27x00_device_info(psy); 175 + 176 + switch (psp) { 177 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 178 + case POWER_SUPPLY_PROP_PRESENT: 179 + val->intval = bq27x00_battery_voltage(di); 180 + if (psp == POWER_SUPPLY_PROP_PRESENT) 181 + val->intval = val->intval <= 0 ? 0 : 1; 182 + break; 183 + case POWER_SUPPLY_PROP_CURRENT_NOW: 184 + val->intval = bq27x00_battery_current(di); 185 + break; 186 + case POWER_SUPPLY_PROP_CAPACITY: 187 + val->intval = bq27x00_battery_rsoc(di); 188 + break; 189 + case POWER_SUPPLY_PROP_TEMP: 190 + val->intval = bq27x00_battery_temperature(di); 191 + break; 192 + default: 193 + return -EINVAL; 194 + } 195 + 196 + return 0; 197 + } 198 + 199 + static void bq27x00_powersupply_init(struct bq27x00_device_info *di) 200 + { 201 + di->bat.type = POWER_SUPPLY_TYPE_BATTERY; 202 + di->bat.properties = bq27x00_battery_props; 203 + di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); 204 + di->bat.get_property = bq27x00_battery_get_property; 205 + di->bat.external_power_changed = NULL; 206 + } 207 + 208 + /* 209 + * BQ27200 specific code 210 + */ 211 + 212 + static int bq27200_read(u8 reg, int *rt_value, int b_single, 213 + struct bq27x00_device_info *di) 214 + { 215 + struct i2c_client *client = di->client; 216 + struct i2c_msg msg[1]; 217 + unsigned char data[2]; 218 + int err; 219 + 220 + if (!client->adapter) 221 + return -ENODEV; 222 + 223 + msg->addr = client->addr; 224 + msg->flags = 0; 225 + msg->len = 1; 226 + msg->buf = data; 227 + 228 + data[0] = reg; 229 + err = i2c_transfer(client->adapter, msg, 1); 230 + 231 + if (err >= 0) { 232 + if (!b_single) 233 + msg->len = 2; 234 + else 235 + msg->len = 1; 236 + 237 + msg->flags = I2C_M_RD; 238 + err = i2c_transfer(client->adapter, msg, 1); 239 + if (err >= 0) { 240 + if (!b_single) 241 + *rt_value = get_unaligned_be16(data); 242 + else 243 + *rt_value = data[0]; 244 + 245 + return 0; 246 + } 247 + } 248 + return err; 249 + } 250 + 251 + static int bq27200_battery_probe(struct i2c_client *client, 252 + const struct i2c_device_id *id) 253 + { 254 + char *name; 255 + struct bq27x00_device_info *di; 256 + struct bq27x00_access_methods *bus; 257 + int num; 258 + int retval = 0; 259 + 260 + /* Get new ID for the new battery device */ 261 + retval = idr_pre_get(&battery_id, GFP_KERNEL); 262 + if (retval == 0) 263 + return -ENOMEM; 264 + mutex_lock(&battery_mutex); 265 + retval = idr_get_new(&battery_id, client, &num); 266 + mutex_unlock(&battery_mutex); 267 + if (retval < 0) 268 + return retval; 269 + 270 + name = kasprintf(GFP_KERNEL, "bq27200-%d", num); 271 + if (!name) { 272 + dev_err(&client->dev, "failed to allocate device name\n"); 273 + retval = -ENOMEM; 274 + goto batt_failed_1; 275 + } 276 + 277 + di = kzalloc(sizeof(*di), GFP_KERNEL); 278 + if (!di) { 279 + dev_err(&client->dev, "failed to allocate device info data\n"); 280 + retval = -ENOMEM; 281 + goto batt_failed_2; 282 + } 283 + di->id = num; 284 + 285 + bus = kzalloc(sizeof(*bus), GFP_KERNEL); 286 + if (!bus) { 287 + dev_err(&client->dev, "failed to allocate access method " 288 + "data\n"); 289 + retval = -ENOMEM; 290 + goto batt_failed_3; 291 + } 292 + 293 + i2c_set_clientdata(client, di); 294 + di->dev = &client->dev; 295 + di->bat.name = name; 296 + bus->read = &bq27200_read; 297 + di->bus = bus; 298 + di->client = client; 299 + 300 + bq27x00_powersupply_init(di); 301 + 302 + retval = power_supply_register(&client->dev, &di->bat); 303 + if (retval) { 304 + dev_err(&client->dev, "failed to register battery\n"); 305 + goto batt_failed_4; 306 + } 307 + 308 + dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION); 309 + 310 + return 0; 311 + 312 + batt_failed_4: 313 + kfree(bus); 314 + batt_failed_3: 315 + kfree(di); 316 + batt_failed_2: 317 + kfree(name); 318 + batt_failed_1: 319 + mutex_lock(&battery_mutex); 320 + idr_remove(&battery_id, num); 321 + mutex_unlock(&battery_mutex); 322 + 323 + return retval; 324 + } 325 + 326 + static int bq27200_battery_remove(struct i2c_client *client) 327 + { 328 + struct bq27x00_device_info *di = i2c_get_clientdata(client); 329 + 330 + power_supply_unregister(&di->bat); 331 + 332 + kfree(di->bat.name); 333 + 334 + mutex_lock(&battery_mutex); 335 + idr_remove(&battery_id, di->id); 336 + mutex_unlock(&battery_mutex); 337 + 338 + kfree(di); 339 + 340 + return 0; 341 + } 342 + 343 + /* 344 + * Module stuff 345 + */ 346 + 347 + static const struct i2c_device_id bq27200_id[] = { 348 + { "bq27200", 0 }, 349 + {}, 350 + }; 351 + 352 + static struct i2c_driver bq27200_battery_driver = { 353 + .driver = { 354 + .name = "bq27200-battery", 355 + }, 356 + .probe = bq27200_battery_probe, 357 + .remove = bq27200_battery_remove, 358 + .id_table = bq27200_id, 359 + }; 360 + 361 + static int __init bq27x00_battery_init(void) 362 + { 363 + int ret; 364 + 365 + ret = i2c_add_driver(&bq27200_battery_driver); 366 + if (ret) 367 + printk(KERN_ERR "Unable to register BQ27200 driver\n"); 368 + 369 + return ret; 370 + } 371 + module_init(bq27x00_battery_init); 372 + 373 + static void __exit bq27x00_battery_exit(void) 374 + { 375 + i2c_del_driver(&bq27200_battery_driver); 376 + } 377 + module_exit(bq27x00_battery_exit); 378 + 379 + MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); 380 + MODULE_DESCRIPTION("BQ27x00 battery monitor driver"); 381 + MODULE_LICENSE("GPL");
+7 -4
drivers/power/pda_power.c
··· 334 334 } 335 335 336 336 #ifdef CONFIG_PM 337 + static int ac_wakeup_enabled; 338 + static int usb_wakeup_enabled; 339 + 337 340 static int pda_power_suspend(struct platform_device *pdev, pm_message_t state) 338 341 { 339 342 if (device_may_wakeup(&pdev->dev)) { 340 343 if (ac_irq) 341 - enable_irq_wake(ac_irq->start); 344 + ac_wakeup_enabled = !enable_irq_wake(ac_irq->start); 342 345 if (usb_irq) 343 - enable_irq_wake(usb_irq->start); 346 + usb_wakeup_enabled = !enable_irq_wake(usb_irq->start); 344 347 } 345 348 346 349 return 0; ··· 352 349 static int pda_power_resume(struct platform_device *pdev) 353 350 { 354 351 if (device_may_wakeup(&pdev->dev)) { 355 - if (usb_irq) 352 + if (usb_irq && usb_wakeup_enabled) 356 353 disable_irq_wake(usb_irq->start); 357 - if (ac_irq) 354 + if (ac_irq && ac_wakeup_enabled) 358 355 disable_irq_wake(ac_irq->start); 359 356 } 360 357
+25
drivers/power/power_supply_core.c
··· 87 87 return error; 88 88 } 89 89 90 + static int __power_supply_is_system_supplied(struct device *dev, void *data) 91 + { 92 + union power_supply_propval ret = {0,}; 93 + struct power_supply *psy = dev_get_drvdata(dev); 94 + 95 + if (psy->type != POWER_SUPPLY_TYPE_BATTERY) { 96 + if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) 97 + return 0; 98 + if (ret.intval) 99 + return ret.intval; 100 + } 101 + return 0; 102 + } 103 + 104 + int power_supply_is_system_supplied(void) 105 + { 106 + int error; 107 + 108 + error = class_for_each_device(power_supply_class, NULL, NULL, 109 + __power_supply_is_system_supplied); 110 + 111 + return error; 112 + } 113 + 90 114 int power_supply_register(struct device *parent, struct power_supply *psy) 91 115 { 92 116 int rc = 0; ··· 172 148 173 149 EXPORT_SYMBOL_GPL(power_supply_changed); 174 150 EXPORT_SYMBOL_GPL(power_supply_am_i_supplied); 151 + EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); 175 152 EXPORT_SYMBOL_GPL(power_supply_register); 176 153 EXPORT_SYMBOL_GPL(power_supply_unregister); 177 154
+6
include/linux/power_supply.h
··· 165 165 extern void power_supply_changed(struct power_supply *psy); 166 166 extern int power_supply_am_i_supplied(struct power_supply *psy); 167 167 168 + #if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE) 169 + extern int power_supply_is_system_supplied(void); 170 + #else 171 + static inline int power_supply_is_system_supplied(void) { return -ENOSYS; } 172 + #endif 173 + 168 174 extern int power_supply_register(struct device *parent, 169 175 struct power_supply *psy); 170 176 extern void power_supply_unregister(struct power_supply *psy);