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.

Merge git://git.infradead.org/users/cbou/battery-2.6.31

* git://git.infradead.org/users/cbou/battery-2.6.31:
Add ds2782 battery gas gauge driver
olpc_battery: Ensure that the TRICKLE bit is checked
olpc_battery: Fix up eeprom read function

+353 -11
+7
drivers/power/Kconfig
··· 43 43 help 44 44 Say Y here to enable support for batteries with ds2760 chip. 45 45 46 + config BATTERY_DS2782 47 + tristate "DS2782 standalone gas-gauge" 48 + depends on I2C 49 + help 50 + Say Y here to enable support for the DS2782 standalone battery 51 + gas-gauge. 52 + 46 53 config BATTERY_PMU 47 54 tristate "Apple PMU battery" 48 55 depends on PPC32 && ADB_PMU
+1
drivers/power/Makefile
··· 19 19 obj-$(CONFIG_WM8350_POWER) += wm8350_power.o 20 20 21 21 obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o 22 + obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o 22 23 obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o 23 24 obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 24 25 obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
+330
drivers/power/ds2782_battery.c
··· 1 + /* 2 + * I2C client/driver for the Maxim/Dallas DS2782 Stand-Alone Fuel Gauge IC 3 + * 4 + * Copyright (C) 2009 Bluewater Systems Ltd 5 + * 6 + * Author: Ryan Mallon <ryan@bluewatersys.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/module.h> 16 + #include <linux/types.h> 17 + #include <linux/errno.h> 18 + #include <linux/swab.h> 19 + #include <linux/i2c.h> 20 + #include <linux/idr.h> 21 + #include <linux/power_supply.h> 22 + 23 + #define DS2782_REG_RARC 0x06 /* Remaining active relative capacity */ 24 + 25 + #define DS2782_REG_VOLT_MSB 0x0c 26 + #define DS2782_REG_TEMP_MSB 0x0a 27 + #define DS2782_REG_CURRENT_MSB 0x0e 28 + 29 + /* EEPROM Block */ 30 + #define DS2782_REG_RSNSP 0x69 /* Sense resistor value */ 31 + 32 + /* Current unit measurement in uA for a 1 milli-ohm sense resistor */ 33 + #define DS2782_CURRENT_UNITS 1563 34 + 35 + #define to_ds2782_info(x) container_of(x, struct ds2782_info, battery) 36 + 37 + struct ds2782_info { 38 + struct i2c_client *client; 39 + struct power_supply battery; 40 + int id; 41 + }; 42 + 43 + static DEFINE_IDR(battery_id); 44 + static DEFINE_MUTEX(battery_lock); 45 + 46 + static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val) 47 + { 48 + int ret; 49 + 50 + ret = i2c_smbus_read_byte_data(info->client, reg); 51 + if (ret < 0) { 52 + dev_err(&info->client->dev, "register read failed\n"); 53 + return ret; 54 + } 55 + 56 + *val = ret; 57 + return 0; 58 + } 59 + 60 + static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb, 61 + s16 *val) 62 + { 63 + int ret; 64 + 65 + ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb)); 66 + if (ret < 0) { 67 + dev_err(&info->client->dev, "register read failed\n"); 68 + return ret; 69 + } 70 + 71 + *val = ret; 72 + return 0; 73 + } 74 + 75 + static int ds2782_get_temp(struct ds2782_info *info, int *temp) 76 + { 77 + s16 raw; 78 + int err; 79 + 80 + /* 81 + * Temperature is measured in units of 0.125 degrees celcius, the 82 + * power_supply class measures temperature in tenths of degrees 83 + * celsius. The temperature value is stored as a 10 bit number, plus 84 + * sign in the upper bits of a 16 bit register. 85 + */ 86 + err = ds2782_read_reg16(info, DS2782_REG_TEMP_MSB, &raw); 87 + if (err) 88 + return err; 89 + *temp = ((raw / 32) * 125) / 100; 90 + return 0; 91 + } 92 + 93 + static int ds2782_get_current(struct ds2782_info *info, int *current_uA) 94 + { 95 + int sense_res; 96 + int err; 97 + u8 sense_res_raw; 98 + s16 raw; 99 + 100 + /* 101 + * The units of measurement for current are dependent on the value of 102 + * the sense resistor. 103 + */ 104 + err = ds2782_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw); 105 + if (err) 106 + return err; 107 + if (sense_res_raw == 0) { 108 + dev_err(&info->client->dev, "sense resistor value is 0\n"); 109 + return -ENXIO; 110 + } 111 + sense_res = 1000 / sense_res_raw; 112 + 113 + dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n", 114 + sense_res); 115 + err = ds2782_read_reg16(info, DS2782_REG_CURRENT_MSB, &raw); 116 + if (err) 117 + return err; 118 + *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res); 119 + return 0; 120 + } 121 + 122 + static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA) 123 + { 124 + s16 raw; 125 + int err; 126 + 127 + /* 128 + * Voltage is measured in units of 4.88mV. The voltage is stored as 129 + * a 10-bit number plus sign, in the upper bits of a 16-bit register 130 + */ 131 + err = ds2782_read_reg16(info, DS2782_REG_VOLT_MSB, &raw); 132 + if (err) 133 + return err; 134 + *voltage_uA = (raw / 32) * 4800; 135 + return 0; 136 + } 137 + 138 + static int ds2782_get_capacity(struct ds2782_info *info, int *capacity) 139 + { 140 + int err; 141 + u8 raw; 142 + 143 + err = ds2782_read_reg(info, DS2782_REG_RARC, &raw); 144 + if (err) 145 + return err; 146 + *capacity = raw; 147 + return raw; 148 + } 149 + 150 + static int ds2782_get_status(struct ds2782_info *info, int *status) 151 + { 152 + int err; 153 + int current_uA; 154 + int capacity; 155 + 156 + err = ds2782_get_current(info, &current_uA); 157 + if (err) 158 + return err; 159 + 160 + err = ds2782_get_capacity(info, &capacity); 161 + if (err) 162 + return err; 163 + 164 + if (capacity == 100) 165 + *status = POWER_SUPPLY_STATUS_FULL; 166 + else if (current_uA == 0) 167 + *status = POWER_SUPPLY_STATUS_NOT_CHARGING; 168 + else if (current_uA < 0) 169 + *status = POWER_SUPPLY_STATUS_DISCHARGING; 170 + else 171 + *status = POWER_SUPPLY_STATUS_CHARGING; 172 + 173 + return 0; 174 + } 175 + 176 + static int ds2782_battery_get_property(struct power_supply *psy, 177 + enum power_supply_property prop, 178 + union power_supply_propval *val) 179 + { 180 + struct ds2782_info *info = to_ds2782_info(psy); 181 + int ret; 182 + 183 + switch (prop) { 184 + case POWER_SUPPLY_PROP_STATUS: 185 + ret = ds2782_get_status(info, &val->intval); 186 + break; 187 + 188 + case POWER_SUPPLY_PROP_CAPACITY: 189 + ret = ds2782_get_capacity(info, &val->intval); 190 + break; 191 + 192 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 193 + ret = ds2782_get_voltage(info, &val->intval); 194 + break; 195 + 196 + case POWER_SUPPLY_PROP_CURRENT_NOW: 197 + ret = ds2782_get_current(info, &val->intval); 198 + break; 199 + 200 + case POWER_SUPPLY_PROP_TEMP: 201 + ret = ds2782_get_temp(info, &val->intval); 202 + break; 203 + 204 + default: 205 + ret = -EINVAL; 206 + } 207 + 208 + return ret; 209 + } 210 + 211 + static enum power_supply_property ds2782_battery_props[] = { 212 + POWER_SUPPLY_PROP_STATUS, 213 + POWER_SUPPLY_PROP_CAPACITY, 214 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 215 + POWER_SUPPLY_PROP_CURRENT_NOW, 216 + POWER_SUPPLY_PROP_TEMP, 217 + }; 218 + 219 + static void ds2782_power_supply_init(struct power_supply *battery) 220 + { 221 + battery->type = POWER_SUPPLY_TYPE_BATTERY; 222 + battery->properties = ds2782_battery_props; 223 + battery->num_properties = ARRAY_SIZE(ds2782_battery_props); 224 + battery->get_property = ds2782_battery_get_property; 225 + battery->external_power_changed = NULL; 226 + } 227 + 228 + static int ds2782_battery_remove(struct i2c_client *client) 229 + { 230 + struct ds2782_info *info = i2c_get_clientdata(client); 231 + 232 + power_supply_unregister(&info->battery); 233 + kfree(info->battery.name); 234 + 235 + mutex_lock(&battery_lock); 236 + idr_remove(&battery_id, info->id); 237 + mutex_unlock(&battery_lock); 238 + 239 + i2c_set_clientdata(client, info); 240 + 241 + kfree(info); 242 + return 0; 243 + } 244 + 245 + static int ds2782_battery_probe(struct i2c_client *client, 246 + const struct i2c_device_id *id) 247 + { 248 + struct ds2782_info *info; 249 + int ret; 250 + int num; 251 + 252 + /* Get an ID for this battery */ 253 + ret = idr_pre_get(&battery_id, GFP_KERNEL); 254 + if (ret == 0) { 255 + ret = -ENOMEM; 256 + goto fail_id; 257 + } 258 + 259 + mutex_lock(&battery_lock); 260 + ret = idr_get_new(&battery_id, client, &num); 261 + mutex_unlock(&battery_lock); 262 + if (ret < 0) 263 + goto fail_id; 264 + 265 + info = kzalloc(sizeof(*info), GFP_KERNEL); 266 + if (!info) { 267 + ret = -ENOMEM; 268 + goto fail_info; 269 + } 270 + 271 + info->battery.name = kasprintf(GFP_KERNEL, "ds2782-%d", num); 272 + if (!info->battery.name) { 273 + ret = -ENOMEM; 274 + goto fail_name; 275 + } 276 + 277 + i2c_set_clientdata(client, info); 278 + info->client = client; 279 + ds2782_power_supply_init(&info->battery); 280 + 281 + ret = power_supply_register(&client->dev, &info->battery); 282 + if (ret) { 283 + dev_err(&client->dev, "failed to register battery\n"); 284 + goto fail_register; 285 + } 286 + 287 + return 0; 288 + 289 + fail_register: 290 + kfree(info->battery.name); 291 + fail_name: 292 + i2c_set_clientdata(client, info); 293 + kfree(info); 294 + fail_info: 295 + mutex_lock(&battery_lock); 296 + idr_remove(&battery_id, num); 297 + mutex_unlock(&battery_lock); 298 + fail_id: 299 + return ret; 300 + } 301 + 302 + static const struct i2c_device_id ds2782_id[] = { 303 + {"ds2782", 0}, 304 + {}, 305 + }; 306 + 307 + static struct i2c_driver ds2782_battery_driver = { 308 + .driver = { 309 + .name = "ds2782-battery", 310 + }, 311 + .probe = ds2782_battery_probe, 312 + .remove = ds2782_battery_remove, 313 + .id_table = ds2782_id, 314 + }; 315 + 316 + static int __init ds2782_init(void) 317 + { 318 + return i2c_add_driver(&ds2782_battery_driver); 319 + } 320 + module_init(ds2782_init); 321 + 322 + static void __exit ds2782_exit(void) 323 + { 324 + i2c_del_driver(&ds2782_battery_driver); 325 + } 326 + module_exit(ds2782_exit); 327 + 328 + MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); 329 + MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver"); 330 + MODULE_LICENSE("GPL");
+15 -11
drivers/power/olpc_battery.c
··· 8 8 * published by the Free Software Foundation. 9 9 */ 10 10 11 + #include <linux/kernel.h> 11 12 #include <linux/module.h> 12 13 #include <linux/err.h> 13 14 #include <linux/platform_device.h> ··· 36 35 #define BAT_STAT_AC 0x10 37 36 #define BAT_STAT_CHARGING 0x20 38 37 #define BAT_STAT_DISCHARGING 0x40 38 + #define BAT_STAT_TRICKLE 0x80 39 39 40 40 #define BAT_ERR_INFOFAIL 0x02 41 41 #define BAT_ERR_OVERVOLTAGE 0x04 ··· 91 89 static int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte) 92 90 { 93 91 if (olpc_platform_info.ecver > 0x44) { 94 - if (ec_byte & BAT_STAT_CHARGING) 92 + if (ec_byte & (BAT_STAT_CHARGING | BAT_STAT_TRICKLE)) 95 93 val->intval = POWER_SUPPLY_STATUS_CHARGING; 96 94 else if (ec_byte & BAT_STAT_DISCHARGING) 97 95 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; ··· 221 219 It doesn't matter though -- the EC will return the last-known 222 220 information, and it's as if we just ran that _little_ bit faster 223 221 and managed to read it out before the battery went away. */ 224 - if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT) 222 + if (!(ec_byte & (BAT_STAT_PRESENT | BAT_STAT_TRICKLE)) && 223 + psp != POWER_SUPPLY_PROP_PRESENT) 225 224 return -ENODEV; 226 225 227 226 switch (psp) { ··· 232 229 return ret; 233 230 break; 234 231 case POWER_SUPPLY_PROP_PRESENT: 235 - val->intval = !!(ec_byte & BAT_STAT_PRESENT); 232 + val->intval = !!(ec_byte & (BAT_STAT_PRESENT | 233 + BAT_STAT_TRICKLE)); 236 234 break; 237 235 238 236 case POWER_SUPPLY_PROP_HEALTH: ··· 338 334 struct bin_attribute *attr, char *buf, loff_t off, size_t count) 339 335 { 340 336 uint8_t ec_byte; 341 - int ret, end; 337 + int ret; 338 + int i; 342 339 343 340 if (off >= EEPROM_SIZE) 344 341 return 0; 345 342 if (off + count > EEPROM_SIZE) 346 343 count = EEPROM_SIZE - off; 347 344 348 - end = EEPROM_START + off + count; 349 - for (ec_byte = EEPROM_START + off; ec_byte < end; ec_byte++) { 350 - ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, 351 - &buf[ec_byte - EEPROM_START], 1); 345 + for (i = 0; i < count; i++) { 346 + ec_byte = EEPROM_START + off + i; 347 + ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1); 352 348 if (ret) { 353 - printk(KERN_ERR "olpc-battery: EC command " 354 - "EC_BAT_EEPROM @ 0x%x failed -" 355 - " %d!\n", ec_byte, ret); 349 + pr_err("olpc-battery: " 350 + "EC_BAT_EEPROM cmd @ 0x%x failed - %d!\n", 351 + ec_byte, ret); 356 352 return -EIO; 357 353 } 358 354 }