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

Merge tag 'for-v3.6' of git://git.infradead.org/battery-2.6

Pull battery updates from Anton Vorontsov:
"The tag contains just a few battery-related changes for v3.6. It's is
all pretty straightforward, except one thing.

One of our patches added thermal support for power supply class, but
thermal/ subsystem changed under our feet. We (well, Stephen, that
is) caught the issue and it was decided[1] that I'd just delay the
battery pull request, and then will fix it up by merging upstream back
into battery tree at the specific commit.

That's not all though: another[2] small fixup for thermal subsystem
was needed to get rid of a warning in power supply subsystem (the
warning was not drivers/power's "fault", the thermal registration
function just needed a proper const annotation, which is also done by
a small commit on top of the merge.

So, to sum this up:
- The 'master' branch of the battery tree was in the -next tree for
weeks, was never rebased, altered etc. It should be all OK;
- Although, for-v3.6 tag contains the 'master' branch + merge + the
warning fix.

[1] http://lkml.org/lkml/2012/6/19/23
[2] http://lkml.org/lkml/2012/6/18/28"

* tag 'for-v3.6' of git://git.infradead.org/battery-2.6: (23 commits)
thermal: Constify 'type' argument for the registration routine
olpc-battery: update CHARGE_FULL_DESIGN property for BYD LiFe batteries
olpc-battery: Add VOLTAGE_MAX_DESIGN property
charger-manager: Fix build break related to EXTCON
lp8727_charger: Move header file into platform_data directory
power_supply: Add min/max alert properties for CAPACITY, TEMP, TEMP_AMBIENT
bq27x00_battery: Add support for BQ27425 chip
charger-manager: Set current limit of regulator for over current protection
charger-manager: Use EXTCON Subsystem to detect charger cables for charging
test_power: Add VOLTAGE_NOW and BATTERY_TEMP properties
test_power: Add support for USB AC source
gpio-charger: Use cansleep version of gpio_set_value
bq27x00_battery: Add support for power average and health properties
sbs-battery: Don't trigger false supply_changed event
twl4030_charger: Allow charger to control the regulator that feeds it
twl4030_charger: Add backup-battery charging
twl4030_charger: Fix some typos
max17042_battery: Support CHARGE_COUNTER power supply attribute
smb347-charger: Add constant charge and current properties
power_supply: Add constant charge_current and charge_voltage properties
...

+789 -57
+10
Documentation/power/power_supply_class.txt
··· 112 112 be negative; there is no empty or full value. It is only useful for 113 113 relative, time-based measurements. 114 114 115 + CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger. 116 + 117 + CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. 118 + 115 119 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. 116 120 117 121 CAPACITY - capacity in percents. 122 + CAPACITY_ALERT_MIN - minimum capacity alert value in percents. 123 + CAPACITY_ALERT_MAX - maximum capacity alert value in percents. 118 124 CAPACITY_LEVEL - capacity level. This corresponds to 119 125 POWER_SUPPLY_CAPACITY_LEVEL_*. 120 126 121 127 TEMP - temperature of the power supply. 128 + TEMP_ALERT_MIN - minimum battery temperature alert value in milli centigrade. 129 + TEMP_ALERT_MAX - maximum battery temperature alert value in milli centigrade. 122 130 TEMP_AMBIENT - ambient temperature. 131 + TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert value in milli centigrade. 132 + TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert value in milli centigrade. 123 133 124 134 TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e. 125 135 while battery powers a load)
+5 -4
drivers/mfd/twl-core.c
··· 717 717 static struct regulator_consumer_supply usb1v8 = { 718 718 .supply = "usb1v8", 719 719 }; 720 - static struct regulator_consumer_supply usb3v1 = { 721 - .supply = "usb3v1", 720 + static struct regulator_consumer_supply usb3v1[] = { 721 + { .supply = "usb3v1" }, 722 + { .supply = "bci3v1" }, 722 723 }; 723 724 724 725 /* First add the regulators so that they can be used by transceiver */ ··· 747 746 return PTR_ERR(child); 748 747 749 748 child = add_regulator_linked(TWL4030_REG_VUSB3V1, 750 - &usb_fixed, &usb3v1, 1, 749 + &usb_fixed, usb3v1, 2, 751 750 features); 752 751 if (IS_ERR(child)) 753 752 return PTR_ERR(child); ··· 768 767 if (twl_has_regulator() && child) { 769 768 usb1v5.dev_name = dev_name(child); 770 769 usb1v8.dev_name = dev_name(child); 771 - usb3v1.dev_name = dev_name(child); 770 + usb3v1[0].dev_name = dev_name(child); 772 771 } 773 772 } 774 773 if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
+1
drivers/power/Kconfig
··· 268 268 config CHARGER_MANAGER 269 269 bool "Battery charger manager for multiple chargers" 270 270 depends on REGULATOR && RTC_CLASS 271 + select EXTCON 271 272 help 272 273 Say Y to enable charger-manager support, which allows multiple 273 274 chargers attached to a battery and multiple batteries attached to a
+140 -15
drivers/power/bq27x00_battery.c
··· 22 22 * Datasheets: 23 23 * http://focus.ti.com/docs/prod/folders/print/bq27000.html 24 24 * http://focus.ti.com/docs/prod/folders/print/bq27500.html 25 + * http://www.ti.com/product/bq27425-g1 25 26 */ 26 27 27 28 #include <linux/module.h> ··· 52 51 #define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ 53 52 #define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ 54 53 #define BQ27x00_REG_AE 0x22 /* Available energy */ 54 + #define BQ27x00_POWER_AVG 0x24 55 55 56 56 #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ 57 57 #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ ··· 68 66 #define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ 69 67 #define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ 70 68 #define BQ27500_FLAG_FC BIT(9) 69 + #define BQ27500_FLAG_OTC BIT(15) 70 + 71 + /* bq27425 register addresses are same as bq27x00 addresses minus 4 */ 72 + #define BQ27425_REG_OFFSET 0x04 73 + #define BQ27425_REG_SOC 0x18 /* Register address plus offset */ 71 74 72 75 #define BQ27000_RS 20 /* Resistor sense */ 76 + #define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000) 73 77 74 78 struct bq27x00_device_info; 75 79 struct bq27x00_access_methods { 76 80 int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); 77 81 }; 78 82 79 - enum bq27x00_chip { BQ27000, BQ27500 }; 83 + enum bq27x00_chip { BQ27000, BQ27500, BQ27425}; 80 84 81 85 struct bq27x00_reg_cache { 82 86 int temperature; ··· 94 86 int capacity; 95 87 int energy; 96 88 int flags; 89 + int power_avg; 90 + int health; 97 91 }; 98 92 99 93 struct bq27x00_device_info { ··· 133 123 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 134 124 POWER_SUPPLY_PROP_CYCLE_COUNT, 135 125 POWER_SUPPLY_PROP_ENERGY_NOW, 126 + POWER_SUPPLY_PROP_POWER_AVG, 127 + POWER_SUPPLY_PROP_HEALTH, 128 + }; 129 + 130 + static enum power_supply_property bq27425_battery_props[] = { 131 + POWER_SUPPLY_PROP_STATUS, 132 + POWER_SUPPLY_PROP_PRESENT, 133 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 134 + POWER_SUPPLY_PROP_CURRENT_NOW, 135 + POWER_SUPPLY_PROP_CAPACITY, 136 + POWER_SUPPLY_PROP_CAPACITY_LEVEL, 137 + POWER_SUPPLY_PROP_TEMP, 138 + POWER_SUPPLY_PROP_TECHNOLOGY, 139 + POWER_SUPPLY_PROP_CHARGE_FULL, 140 + POWER_SUPPLY_PROP_CHARGE_NOW, 141 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 136 142 }; 137 143 138 144 static unsigned int poll_interval = 360; ··· 163 137 static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, 164 138 bool single) 165 139 { 140 + if (di->chip == BQ27425) 141 + return di->bus.read(di, reg - BQ27425_REG_OFFSET, single); 166 142 return di->bus.read(di, reg, single); 143 + } 144 + 145 + /* 146 + * Higher versions of the chip like BQ27425 and BQ27500 147 + * differ from BQ27000 and BQ27200 in calculation of certain 148 + * parameters. Hence we need to check for the chip type. 149 + */ 150 + static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) 151 + { 152 + if (di->chip == BQ27425 || di->chip == BQ27500) 153 + return true; 154 + return false; 167 155 } 168 156 169 157 /* ··· 190 150 191 151 if (di->chip == BQ27500) 192 152 rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); 153 + else if (di->chip == BQ27425) 154 + rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); 193 155 else 194 156 rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); 195 157 ··· 216 174 return charge; 217 175 } 218 176 219 - if (di->chip == BQ27500) 177 + if (bq27xxx_is_chip_version_higher(di)) 220 178 charge *= 1000; 221 179 else 222 180 charge = charge * 3570 / BQ27000_RS; ··· 250 208 { 251 209 int ilmd; 252 210 253 - if (di->chip == BQ27500) 211 + if (bq27xxx_is_chip_version_higher(di)) 254 212 ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); 255 213 else 256 214 ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); ··· 260 218 return ilmd; 261 219 } 262 220 263 - if (di->chip == BQ27500) 221 + if (bq27xxx_is_chip_version_higher(di)) 264 222 ilmd *= 1000; 265 223 else 266 224 ilmd = ilmd * 256 * 3570 / BQ27000_RS; ··· 304 262 return temp; 305 263 } 306 264 307 - if (di->chip == BQ27500) 265 + if (bq27xxx_is_chip_version_higher(di)) 308 266 temp -= 2731; 309 267 else 310 268 temp = ((temp * 5) - 5463) / 2; ··· 348 306 return tval * 60; 349 307 } 350 308 309 + /* 310 + * Read a power avg register. 311 + * Return < 0 if something fails. 312 + */ 313 + static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg) 314 + { 315 + int tval; 316 + 317 + tval = bq27x00_read(di, reg, false); 318 + if (tval < 0) { 319 + dev_err(di->dev, "error reading power avg rgister %02x: %d\n", 320 + reg, tval); 321 + return tval; 322 + } 323 + 324 + if (di->chip == BQ27500) 325 + return tval; 326 + else 327 + return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS; 328 + } 329 + 330 + /* 331 + * Read flag register. 332 + * Return < 0 if something fails. 333 + */ 334 + static int bq27x00_battery_read_health(struct bq27x00_device_info *di) 335 + { 336 + int tval; 337 + 338 + tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false); 339 + if (tval < 0) { 340 + dev_err(di->dev, "error reading flag register:%d\n", tval); 341 + return tval; 342 + } 343 + 344 + if ((di->chip == BQ27500)) { 345 + if (tval & BQ27500_FLAG_SOCF) 346 + tval = POWER_SUPPLY_HEALTH_DEAD; 347 + else if (tval & BQ27500_FLAG_OTC) 348 + tval = POWER_SUPPLY_HEALTH_OVERHEAT; 349 + else 350 + tval = POWER_SUPPLY_HEALTH_GOOD; 351 + return tval; 352 + } else { 353 + if (tval & BQ27000_FLAG_EDV1) 354 + tval = POWER_SUPPLY_HEALTH_DEAD; 355 + else 356 + tval = POWER_SUPPLY_HEALTH_GOOD; 357 + return tval; 358 + } 359 + 360 + return -1; 361 + } 362 + 351 363 static void bq27x00_update(struct bq27x00_device_info *di) 352 364 { 353 365 struct bq27x00_reg_cache cache = {0, }; 354 366 bool is_bq27500 = di->chip == BQ27500; 367 + bool is_bq27425 = di->chip == BQ27425; 355 368 356 369 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); 357 370 if (cache.flags >= 0) { 358 - if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) { 371 + if (!is_bq27500 && !is_bq27425 372 + && (cache.flags & BQ27000_FLAG_CI)) { 359 373 dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); 360 374 cache.capacity = -ENODATA; 361 375 cache.energy = -ENODATA; ··· 419 321 cache.time_to_empty_avg = -ENODATA; 420 322 cache.time_to_full = -ENODATA; 421 323 cache.charge_full = -ENODATA; 324 + cache.health = -ENODATA; 422 325 } else { 423 326 cache.capacity = bq27x00_battery_read_rsoc(di); 424 - cache.energy = bq27x00_battery_read_energy(di); 425 - cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); 426 - cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); 427 - cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); 327 + if (!is_bq27425) { 328 + cache.energy = bq27x00_battery_read_energy(di); 329 + cache.time_to_empty = 330 + bq27x00_battery_read_time(di, 331 + BQ27x00_REG_TTE); 332 + cache.time_to_empty_avg = 333 + bq27x00_battery_read_time(di, 334 + BQ27x00_REG_TTECP); 335 + cache.time_to_full = 336 + bq27x00_battery_read_time(di, 337 + BQ27x00_REG_TTF); 338 + } 428 339 cache.charge_full = bq27x00_battery_read_lmd(di); 340 + cache.health = bq27x00_battery_read_health(di); 429 341 } 430 342 cache.temperature = bq27x00_battery_read_temperature(di); 343 + if (!is_bq27425) 344 + cache.cycle_count = bq27x00_battery_read_cyct(di); 431 345 cache.cycle_count = bq27x00_battery_read_cyct(di); 346 + cache.power_avg = 347 + bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); 432 348 433 349 /* We only have to read charge design full once */ 434 350 if (di->charge_design_full <= 0) ··· 488 376 return curr; 489 377 } 490 378 491 - if (di->chip == BQ27500) { 379 + if (bq27xxx_is_chip_version_higher(di)) { 492 380 /* bq27500 returns signed value */ 493 381 val->intval = (int)((s16)curr) * 1000; 494 382 } else { ··· 509 397 { 510 398 int status; 511 399 512 - if (di->chip == BQ27500) { 400 + if (bq27xxx_is_chip_version_higher(di)) { 513 401 if (di->cache.flags & BQ27500_FLAG_FC) 514 402 status = POWER_SUPPLY_STATUS_FULL; 515 403 else if (di->cache.flags & BQ27500_FLAG_DSC) ··· 537 425 { 538 426 int level; 539 427 540 - if (di->chip == BQ27500) { 428 + if (bq27xxx_is_chip_version_higher(di)) { 541 429 if (di->cache.flags & BQ27500_FLAG_FC) 542 430 level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 543 431 else if (di->cache.flags & BQ27500_FLAG_SOC1) ··· 662 550 case POWER_SUPPLY_PROP_ENERGY_NOW: 663 551 ret = bq27x00_simple_value(di->cache.energy, val); 664 552 break; 553 + case POWER_SUPPLY_PROP_POWER_AVG: 554 + ret = bq27x00_simple_value(di->cache.power_avg, val); 555 + break; 556 + case POWER_SUPPLY_PROP_HEALTH: 557 + ret = bq27x00_simple_value(di->cache.health, val); 558 + break; 665 559 default: 666 560 return -EINVAL; 667 561 } ··· 688 570 int ret; 689 571 690 572 di->bat.type = POWER_SUPPLY_TYPE_BATTERY; 691 - di->bat.properties = bq27x00_battery_props; 692 - di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); 573 + di->chip = BQ27425; 574 + if (di->chip == BQ27425) { 575 + di->bat.properties = bq27425_battery_props; 576 + di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props); 577 + } else { 578 + di->bat.properties = bq27x00_battery_props; 579 + di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); 580 + } 693 581 di->bat.get_property = bq27x00_battery_get_property; 694 582 di->bat.external_power_changed = bq27x00_external_power_changed; 695 583 ··· 853 729 static const struct i2c_device_id bq27x00_id[] = { 854 730 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ 855 731 { "bq27500", BQ27500 }, 732 + { "bq27425", BQ27425 }, 856 733 {}, 857 734 }; 858 735 MODULE_DEVICE_TABLE(i2c, bq27x00_id);
+136 -16
drivers/power/charger-manager.c
··· 271 271 if (enable) { 272 272 if (cm->emergency_stop) 273 273 return -EAGAIN; 274 - err = regulator_bulk_enable(desc->num_charger_regulators, 275 - desc->charger_regulators); 274 + for (i = 0 ; i < desc->num_charger_regulators ; i++) 275 + regulator_enable(desc->charger_regulators[i].consumer); 276 276 } else { 277 277 /* 278 278 * Abnormal battery state - Stop charging forcibly, 279 279 * even if charger was enabled at the other places 280 280 */ 281 - err = regulator_bulk_disable(desc->num_charger_regulators, 282 - desc->charger_regulators); 283 - 284 281 for (i = 0; i < desc->num_charger_regulators; i++) { 285 282 if (regulator_is_enabled( 286 283 desc->charger_regulators[i].consumer)) { ··· 285 288 desc->charger_regulators[i].consumer); 286 289 dev_warn(cm->dev, 287 290 "Disable regulator(%s) forcibly.\n", 288 - desc->charger_regulators[i].supply); 291 + desc->charger_regulators[i].regulator_name); 289 292 } 290 293 } 291 294 } ··· 991 994 } 992 995 EXPORT_SYMBOL_GPL(setup_charger_manager); 993 996 997 + /** 998 + * charger_extcon_work - enable/diable charger according to the state 999 + * of charger cable 1000 + * 1001 + * @work: work_struct of the function charger_extcon_work. 1002 + */ 1003 + static void charger_extcon_work(struct work_struct *work) 1004 + { 1005 + struct charger_cable *cable = 1006 + container_of(work, struct charger_cable, wq); 1007 + int ret; 1008 + 1009 + if (cable->attached && cable->min_uA != 0 && cable->max_uA != 0) { 1010 + ret = regulator_set_current_limit(cable->charger->consumer, 1011 + cable->min_uA, cable->max_uA); 1012 + if (ret < 0) { 1013 + pr_err("Cannot set current limit of %s (%s)\n", 1014 + cable->charger->regulator_name, cable->name); 1015 + return; 1016 + } 1017 + 1018 + pr_info("Set current limit of %s : %duA ~ %duA\n", 1019 + cable->charger->regulator_name, 1020 + cable->min_uA, cable->max_uA); 1021 + } 1022 + 1023 + try_charger_enable(cable->cm, cable->attached); 1024 + } 1025 + 1026 + /** 1027 + * charger_extcon_notifier - receive the state of charger cable 1028 + * when registered cable is attached or detached. 1029 + * 1030 + * @self: the notifier block of the charger_extcon_notifier. 1031 + * @event: the cable state. 1032 + * @ptr: the data pointer of notifier block. 1033 + */ 1034 + static int charger_extcon_notifier(struct notifier_block *self, 1035 + unsigned long event, void *ptr) 1036 + { 1037 + struct charger_cable *cable = 1038 + container_of(self, struct charger_cable, nb); 1039 + 1040 + cable->attached = event; 1041 + schedule_work(&cable->wq); 1042 + 1043 + return NOTIFY_DONE; 1044 + } 1045 + 1046 + /** 1047 + * charger_extcon_init - register external connector to use it 1048 + * as the charger cable 1049 + * 1050 + * @cm: the Charger Manager representing the battery. 1051 + * @cable: the Charger cable representing the external connector. 1052 + */ 1053 + static int charger_extcon_init(struct charger_manager *cm, 1054 + struct charger_cable *cable) 1055 + { 1056 + int ret = 0; 1057 + 1058 + /* 1059 + * Charger manager use Extcon framework to identify 1060 + * the charger cable among various external connector 1061 + * cable (e.g., TA, USB, MHL, Dock). 1062 + */ 1063 + INIT_WORK(&cable->wq, charger_extcon_work); 1064 + cable->nb.notifier_call = charger_extcon_notifier; 1065 + ret = extcon_register_interest(&cable->extcon_dev, 1066 + cable->extcon_name, cable->name, &cable->nb); 1067 + if (ret < 0) { 1068 + pr_info("Cannot register extcon_dev for %s(cable: %s).\n", 1069 + cable->extcon_name, 1070 + cable->name); 1071 + ret = -EINVAL; 1072 + } 1073 + 1074 + return ret; 1075 + } 1076 + 994 1077 static int charger_manager_probe(struct platform_device *pdev) 995 1078 { 996 1079 struct charger_desc *desc = dev_get_platdata(&pdev->dev); 997 1080 struct charger_manager *cm; 998 1081 int ret = 0, i = 0; 1082 + int j = 0; 999 1083 union power_supply_propval val; 1000 1084 1001 1085 if (g_desc && !rtc_dev && g_desc->rtc_name) { ··· 1245 1167 goto err_register; 1246 1168 } 1247 1169 1248 - ret = regulator_bulk_get(&pdev->dev, desc->num_charger_regulators, 1249 - desc->charger_regulators); 1250 - if (ret) { 1251 - dev_err(&pdev->dev, "Cannot get charger regulators.\n"); 1252 - goto err_bulk_get; 1170 + for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1171 + struct charger_regulator *charger 1172 + = &desc->charger_regulators[i]; 1173 + 1174 + charger->consumer = regulator_get(&pdev->dev, 1175 + charger->regulator_name); 1176 + if (charger->consumer == NULL) { 1177 + dev_err(&pdev->dev, "Cannot find charger(%s)n", 1178 + charger->regulator_name); 1179 + ret = -EINVAL; 1180 + goto err_chg_get; 1181 + } 1182 + 1183 + for (j = 0 ; j < charger->num_cables ; j++) { 1184 + struct charger_cable *cable = &charger->cables[j]; 1185 + 1186 + ret = charger_extcon_init(cm, cable); 1187 + if (ret < 0) { 1188 + dev_err(&pdev->dev, "Cannot find charger(%s)n", 1189 + charger->regulator_name); 1190 + goto err_extcon; 1191 + } 1192 + cable->charger = charger; 1193 + cable->cm = cm; 1194 + } 1253 1195 } 1254 1196 1255 1197 ret = try_charger_enable(cm, true); ··· 1295 1197 return 0; 1296 1198 1297 1199 err_chg_enable: 1298 - regulator_bulk_free(desc->num_charger_regulators, 1299 - desc->charger_regulators); 1300 - err_bulk_get: 1200 + err_extcon: 1201 + for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1202 + struct charger_regulator *charger 1203 + = &desc->charger_regulators[i]; 1204 + for (j = 0 ; j < charger->num_cables ; j++) { 1205 + struct charger_cable *cable = &charger->cables[j]; 1206 + extcon_unregister_interest(&cable->extcon_dev); 1207 + } 1208 + } 1209 + err_chg_get: 1210 + for (i = 0 ; i < desc->num_charger_regulators ; i++) 1211 + regulator_put(desc->charger_regulators[i].consumer); 1212 + 1301 1213 power_supply_unregister(&cm->charger_psy); 1302 1214 err_register: 1303 1215 kfree(cm->charger_psy.properties); ··· 1326 1218 { 1327 1219 struct charger_manager *cm = platform_get_drvdata(pdev); 1328 1220 struct charger_desc *desc = cm->desc; 1221 + int i = 0; 1222 + int j = 0; 1329 1223 1330 1224 /* Remove from the list */ 1331 1225 mutex_lock(&cm_list_mtx); ··· 1339 1229 if (delayed_work_pending(&cm_monitor_work)) 1340 1230 cancel_delayed_work_sync(&cm_monitor_work); 1341 1231 1342 - regulator_bulk_free(desc->num_charger_regulators, 1343 - desc->charger_regulators); 1232 + for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1233 + struct charger_regulator *charger 1234 + = &desc->charger_regulators[i]; 1235 + for (j = 0 ; j < charger->num_cables ; j++) { 1236 + struct charger_cable *cable = &charger->cables[j]; 1237 + extcon_unregister_interest(&cable->extcon_dev); 1238 + } 1239 + } 1240 + 1241 + for (i = 0 ; i < desc->num_charger_regulators ; i++) 1242 + regulator_put(desc->charger_regulators[i].consumer); 1243 + 1344 1244 power_supply_unregister(&cm->charger_psy); 1345 1245 1346 1246 try_charger_enable(cm, false);
+1 -1
drivers/power/ds2781_battery.c
··· 64 64 return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); 65 65 } 66 66 67 - int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, 67 + static int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, 68 68 int addr, size_t count) 69 69 { 70 70 return ds2781_battery_io(dev_info, buf, addr, count, 0);
+1 -1
drivers/power/gpio-charger.c
··· 54 54 55 55 switch (psp) { 56 56 case POWER_SUPPLY_PROP_ONLINE: 57 - val->intval = gpio_get_value(pdata->gpio); 57 + val->intval = gpio_get_value_cansleep(pdata->gpio); 58 58 val->intval ^= pdata->gpio_active_low; 59 59 break; 60 60 default:
+1 -1
drivers/power/lp8727_charger.c
··· 15 15 #include <linux/interrupt.h> 16 16 #include <linux/i2c.h> 17 17 #include <linux/power_supply.h> 18 - #include <linux/lp8727.h> 18 + #include <linux/platform_data/lp8727.h> 19 19 20 20 #define DEBOUNCE_MSEC 270 21 21
+8
drivers/power/max17042_battery.c
··· 113 113 POWER_SUPPLY_PROP_VOLTAGE_OCV, 114 114 POWER_SUPPLY_PROP_CAPACITY, 115 115 POWER_SUPPLY_PROP_CHARGE_FULL, 116 + POWER_SUPPLY_PROP_CHARGE_COUNTER, 116 117 POWER_SUPPLY_PROP_TEMP, 117 118 POWER_SUPPLY_PROP_CURRENT_NOW, 118 119 POWER_SUPPLY_PROP_CURRENT_AVG, ··· 197 196 break; 198 197 case POWER_SUPPLY_PROP_CHARGE_FULL: 199 198 ret = max17042_read_reg(chip->client, MAX17042_FullCAP); 199 + if (ret < 0) 200 + return ret; 201 + 202 + val->intval = ret * 1000 / 2; 203 + break; 204 + case POWER_SUPPLY_PROP_CHARGE_COUNTER: 205 + ret = max17042_read_reg(chip->client, MAX17042_QH); 200 206 if (ret < 0) 201 207 return ret; 202 208
+58 -4
drivers/power/olpc_battery.c
··· 231 231 232 232 case POWER_SUPPLY_TECHNOLOGY_LiFe: 233 233 switch (mfr) { 234 - case 1: /* Gold Peak */ 235 - val->intval = 2800000; 236 - break; 234 + case 1: /* Gold Peak, fall through */ 237 235 case 2: /* BYD */ 238 - val->intval = 3100000; 236 + val->intval = 2800000; 239 237 break; 240 238 default: 241 239 return -EIO; ··· 263 265 264 266 val->intval = soc * (full.intval / 100); 265 267 return 0; 268 + } 269 + 270 + static int olpc_bat_get_voltage_max_design(union power_supply_propval *val) 271 + { 272 + uint8_t ec_byte; 273 + union power_supply_propval tech; 274 + int mfr; 275 + int ret; 276 + 277 + ret = olpc_bat_get_tech(&tech); 278 + if (ret) 279 + return ret; 280 + 281 + ec_byte = BAT_ADDR_MFR_TYPE; 282 + ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); 283 + if (ret) 284 + return ret; 285 + 286 + mfr = ec_byte >> 4; 287 + 288 + switch (tech.intval) { 289 + case POWER_SUPPLY_TECHNOLOGY_NiMH: 290 + switch (mfr) { 291 + case 1: /* Gold Peak */ 292 + val->intval = 6000000; 293 + break; 294 + default: 295 + return -EIO; 296 + } 297 + break; 298 + 299 + case POWER_SUPPLY_TECHNOLOGY_LiFe: 300 + switch (mfr) { 301 + case 1: /* Gold Peak */ 302 + val->intval = 6400000; 303 + break; 304 + case 2: /* BYD */ 305 + val->intval = 6500000; 306 + break; 307 + default: 308 + return -EIO; 309 + } 310 + break; 311 + 312 + default: 313 + return -EIO; 314 + } 315 + 316 + return ret; 266 317 } 267 318 268 319 /********************************************************************* ··· 448 401 sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf)); 449 402 val->strval = bat_serial; 450 403 break; 404 + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 405 + ret = olpc_bat_get_voltage_max_design(val); 406 + if (ret) 407 + return ret; 408 + break; 451 409 default: 452 410 ret = -EINVAL; 453 411 break; ··· 480 428 POWER_SUPPLY_PROP_MANUFACTURER, 481 429 POWER_SUPPLY_PROP_SERIAL_NUMBER, 482 430 POWER_SUPPLY_PROP_CHARGE_COUNTER, 431 + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 483 432 }; 484 433 485 434 /* XO-1.5 does not have ambient temperature property */ ··· 502 449 POWER_SUPPLY_PROP_MANUFACTURER, 503 450 POWER_SUPPLY_PROP_SERIAL_NUMBER, 504 451 POWER_SUPPLY_PROP_CHARGE_COUNTER, 452 + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 505 453 }; 506 454 507 455 /* EEPROM reading goes completely around the power_supply API, sadly */
+2 -2
drivers/power/pda_power.c
··· 134 134 regulator_set_current_limit(ac_draw, max_uA, max_uA); 135 135 if (!regulator_enabled) { 136 136 dev_dbg(dev, "charger on (AC)\n"); 137 - regulator_enable(ac_draw); 137 + WARN_ON(regulator_enable(ac_draw)); 138 138 regulator_enabled = 1; 139 139 } 140 140 } else { 141 141 if (regulator_enabled) { 142 142 dev_dbg(dev, "charger off\n"); 143 - regulator_disable(ac_draw); 143 + WARN_ON(regulator_disable(ac_draw)); 144 144 regulator_enabled = 0; 145 145 } 146 146 }
+65
drivers/power/power_supply_core.c
··· 17 17 #include <linux/device.h> 18 18 #include <linux/err.h> 19 19 #include <linux/power_supply.h> 20 + #include <linux/thermal.h> 20 21 #include "power_supply.h" 21 22 22 23 /* exported for the APM Power driver, APM emulation */ ··· 170 169 kfree(dev); 171 170 } 172 171 172 + #ifdef CONFIG_THERMAL 173 + static int power_supply_read_temp(struct thermal_zone_device *tzd, 174 + unsigned long *temp) 175 + { 176 + struct power_supply *psy; 177 + union power_supply_propval val; 178 + int ret; 179 + 180 + WARN_ON(tzd == NULL); 181 + psy = tzd->devdata; 182 + ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val); 183 + 184 + /* Convert tenths of degree Celsius to milli degree Celsius. */ 185 + if (!ret) 186 + *temp = val.intval * 100; 187 + 188 + return ret; 189 + } 190 + 191 + static struct thermal_zone_device_ops psy_tzd_ops = { 192 + .get_temp = power_supply_read_temp, 193 + }; 194 + 195 + static int psy_register_thermal(struct power_supply *psy) 196 + { 197 + int i; 198 + 199 + /* Register battery zone device psy reports temperature */ 200 + for (i = 0; i < psy->num_properties; i++) { 201 + if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { 202 + psy->tzd = thermal_zone_device_register(psy->name, 0, 0, 203 + psy, &psy_tzd_ops, 0, 0, 0, 0); 204 + if (IS_ERR(psy->tzd)) 205 + return PTR_ERR(psy->tzd); 206 + break; 207 + } 208 + } 209 + return 0; 210 + } 211 + 212 + static void psy_unregister_thermal(struct power_supply *psy) 213 + { 214 + if (IS_ERR_OR_NULL(psy->tzd)) 215 + return; 216 + thermal_zone_device_unregister(psy->tzd); 217 + } 218 + #else 219 + static int psy_register_thermal(struct power_supply *psy) 220 + { 221 + return 0; 222 + } 223 + 224 + static void psy_unregister_thermal(struct power_supply *psy) 225 + { 226 + } 227 + #endif 228 + 173 229 int power_supply_register(struct device *parent, struct power_supply *psy) 174 230 { 175 231 struct device *dev; ··· 255 197 if (rc) 256 198 goto device_add_failed; 257 199 200 + rc = psy_register_thermal(psy); 201 + if (rc) 202 + goto register_thermal_failed; 203 + 258 204 rc = power_supply_create_triggers(psy); 259 205 if (rc) 260 206 goto create_triggers_failed; ··· 268 206 goto success; 269 207 270 208 create_triggers_failed: 209 + psy_unregister_thermal(psy); 210 + register_thermal_failed: 271 211 device_del(dev); 272 212 kobject_set_name_failed: 273 213 device_add_failed: ··· 284 220 cancel_work_sync(&psy->changed_work); 285 221 sysfs_remove_link(&psy->dev->kobj, "powers"); 286 222 power_supply_remove_triggers(psy); 223 + psy_unregister_thermal(psy); 287 224 device_unregister(psy->dev); 288 225 } 289 226 EXPORT_SYMBOL_GPL(power_supply_unregister);
+8
drivers/power/power_supply_sysfs.c
··· 159 159 POWER_SUPPLY_ATTR(charge_now), 160 160 POWER_SUPPLY_ATTR(charge_avg), 161 161 POWER_SUPPLY_ATTR(charge_counter), 162 + POWER_SUPPLY_ATTR(constant_charge_current), 163 + POWER_SUPPLY_ATTR(constant_charge_voltage), 162 164 POWER_SUPPLY_ATTR(energy_full_design), 163 165 POWER_SUPPLY_ATTR(energy_empty_design), 164 166 POWER_SUPPLY_ATTR(energy_full), ··· 168 166 POWER_SUPPLY_ATTR(energy_now), 169 167 POWER_SUPPLY_ATTR(energy_avg), 170 168 POWER_SUPPLY_ATTR(capacity), 169 + POWER_SUPPLY_ATTR(capacity_alert_min), 170 + POWER_SUPPLY_ATTR(capacity_alert_max), 171 171 POWER_SUPPLY_ATTR(capacity_level), 172 172 POWER_SUPPLY_ATTR(temp), 173 + POWER_SUPPLY_ATTR(temp_alert_min), 174 + POWER_SUPPLY_ATTR(temp_alert_max), 173 175 POWER_SUPPLY_ATTR(temp_ambient), 176 + POWER_SUPPLY_ATTR(temp_ambient_alert_min), 177 + POWER_SUPPLY_ATTR(temp_ambient_alert_max), 174 178 POWER_SUPPLY_ATTR(time_to_empty_now), 175 179 POWER_SUPPLY_ATTR(time_to_empty_avg), 176 180 POWER_SUPPLY_ATTR(time_to_full_now),
+1 -1
drivers/power/sbs-battery.c
··· 469 469 470 470 case POWER_SUPPLY_PROP_TECHNOLOGY: 471 471 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 472 - break; 472 + goto done; /* don't trigger power_supply_changed()! */ 473 473 474 474 case POWER_SUPPLY_PROP_ENERGY_NOW: 475 475 case POWER_SUPPLY_PROP_ENERGY_FULL:
+117 -6
drivers/power/smb347-charger.c
··· 196 196 1200000, 197 197 }; 198 198 199 + /* Convert register value to current using lookup table */ 200 + static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val) 201 + { 202 + if (val >= size) 203 + return -EINVAL; 204 + return tbl[val]; 205 + } 206 + 199 207 /* Convert current to register value using lookup table */ 200 208 static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) 201 209 { ··· 849 841 return ret; 850 842 } 851 843 844 + /* 845 + * Returns the constant charge current programmed 846 + * into the charger in uA. 847 + */ 848 + static int get_const_charge_current(struct smb347_charger *smb) 849 + { 850 + int ret, intval; 851 + unsigned int v; 852 + 853 + if (!smb347_is_ps_online(smb)) 854 + return -ENODATA; 855 + 856 + ret = regmap_read(smb->regmap, STAT_B, &v); 857 + if (ret < 0) 858 + return ret; 859 + 860 + /* 861 + * The current value is composition of FCC and PCC values 862 + * and we can detect which table to use from bit 5. 863 + */ 864 + if (v & 0x20) { 865 + intval = hw_to_current(fcc_tbl, ARRAY_SIZE(fcc_tbl), v & 7); 866 + } else { 867 + v >>= 3; 868 + intval = hw_to_current(pcc_tbl, ARRAY_SIZE(pcc_tbl), v & 7); 869 + } 870 + 871 + return intval; 872 + } 873 + 874 + /* 875 + * Returns the constant charge voltage programmed 876 + * into the charger in uV. 877 + */ 878 + static int get_const_charge_voltage(struct smb347_charger *smb) 879 + { 880 + int ret, intval; 881 + unsigned int v; 882 + 883 + if (!smb347_is_ps_online(smb)) 884 + return -ENODATA; 885 + 886 + ret = regmap_read(smb->regmap, STAT_A, &v); 887 + if (ret < 0) 888 + return ret; 889 + 890 + v &= STAT_A_FLOAT_VOLTAGE_MASK; 891 + if (v > 0x3d) 892 + v = 0x3d; 893 + 894 + intval = 3500000 + v * 20000; 895 + 896 + return intval; 897 + } 898 + 852 899 static int smb347_mains_get_property(struct power_supply *psy, 853 900 enum power_supply_property prop, 854 901 union power_supply_propval *val) 855 902 { 856 903 struct smb347_charger *smb = 857 904 container_of(psy, struct smb347_charger, mains); 905 + int ret; 858 906 859 - if (prop == POWER_SUPPLY_PROP_ONLINE) { 907 + switch (prop) { 908 + case POWER_SUPPLY_PROP_ONLINE: 860 909 val->intval = smb->mains_online; 861 - return 0; 910 + break; 911 + 912 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 913 + ret = get_const_charge_voltage(smb); 914 + if (ret < 0) 915 + return ret; 916 + else 917 + val->intval = ret; 918 + break; 919 + 920 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 921 + ret = get_const_charge_current(smb); 922 + if (ret < 0) 923 + return ret; 924 + else 925 + val->intval = ret; 926 + break; 927 + 928 + default: 929 + return -EINVAL; 862 930 } 863 - return -EINVAL; 931 + 932 + return 0; 864 933 } 865 934 866 935 static enum power_supply_property smb347_mains_properties[] = { 867 936 POWER_SUPPLY_PROP_ONLINE, 937 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 938 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 868 939 }; 869 940 870 941 static int smb347_usb_get_property(struct power_supply *psy, ··· 952 865 { 953 866 struct smb347_charger *smb = 954 867 container_of(psy, struct smb347_charger, usb); 868 + int ret; 955 869 956 - if (prop == POWER_SUPPLY_PROP_ONLINE) { 870 + switch (prop) { 871 + case POWER_SUPPLY_PROP_ONLINE: 957 872 val->intval = smb->usb_online; 958 - return 0; 873 + break; 874 + 875 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 876 + ret = get_const_charge_voltage(smb); 877 + if (ret < 0) 878 + return ret; 879 + else 880 + val->intval = ret; 881 + break; 882 + 883 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 884 + ret = get_const_charge_current(smb); 885 + if (ret < 0) 886 + return ret; 887 + else 888 + val->intval = ret; 889 + break; 890 + 891 + default: 892 + return -EINVAL; 959 893 } 960 - return -EINVAL; 894 + 895 + return 0; 961 896 } 962 897 963 898 static enum power_supply_property smb347_usb_properties[] = { 964 899 POWER_SUPPLY_PROP_ONLINE, 900 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 901 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 965 902 }; 966 903 967 904 static int smb347_battery_get_property(struct power_supply *psy,
+75
drivers/power/test_power.c
··· 22 22 #include <linux/vermagic.h> 23 23 24 24 static int ac_online = 1; 25 + static int usb_online = 1; 25 26 static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 26 27 static int battery_health = POWER_SUPPLY_HEALTH_GOOD; 27 28 static int battery_present = 1; /* true */ 28 29 static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; 29 30 static int battery_capacity = 50; 31 + static int battery_voltage = 3300; 30 32 31 33 static int test_power_get_ac_property(struct power_supply *psy, 32 34 enum power_supply_property psp, ··· 37 35 switch (psp) { 38 36 case POWER_SUPPLY_PROP_ONLINE: 39 37 val->intval = ac_online; 38 + break; 39 + default: 40 + return -EINVAL; 41 + } 42 + return 0; 43 + } 44 + 45 + static int test_power_get_usb_property(struct power_supply *psy, 46 + enum power_supply_property psp, 47 + union power_supply_propval *val) 48 + { 49 + switch (psp) { 50 + case POWER_SUPPLY_PROP_ONLINE: 51 + val->intval = usb_online; 40 52 break; 41 53 default: 42 54 return -EINVAL; ··· 102 86 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: 103 87 val->intval = 3600; 104 88 break; 89 + case POWER_SUPPLY_PROP_TEMP: 90 + val->intval = 26; 91 + break; 92 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 93 + val->intval = battery_voltage; 94 + break; 105 95 default: 106 96 pr_info("%s: some properties deliberately report errors.\n", 107 97 __func__); ··· 136 114 POWER_SUPPLY_PROP_MODEL_NAME, 137 115 POWER_SUPPLY_PROP_MANUFACTURER, 138 116 POWER_SUPPLY_PROP_SERIAL_NUMBER, 117 + POWER_SUPPLY_PROP_TEMP, 118 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 139 119 }; 140 120 141 121 static char *test_power_ac_supplied_to[] = { ··· 159 135 .properties = test_power_battery_props, 160 136 .num_properties = ARRAY_SIZE(test_power_battery_props), 161 137 .get_property = test_power_get_battery_property, 138 + }, { 139 + .name = "test_usb", 140 + .type = POWER_SUPPLY_TYPE_USB, 141 + .supplied_to = test_power_ac_supplied_to, 142 + .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to), 143 + .properties = test_power_ac_props, 144 + .num_properties = ARRAY_SIZE(test_power_ac_props), 145 + .get_property = test_power_get_usb_property, 162 146 }, 163 147 }; 164 148 ··· 199 167 200 168 /* Let's see how we handle changes... */ 201 169 ac_online = 0; 170 + usb_online = 0; 202 171 battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 203 172 for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) 204 173 power_supply_changed(&test_power_supplies[i]); ··· 308 275 return strlen(buffer); 309 276 } 310 277 278 + static int param_set_usb_online(const char *key, const struct kernel_param *kp) 279 + { 280 + usb_online = map_get_value(map_ac_online, key, usb_online); 281 + power_supply_changed(&test_power_supplies[2]); 282 + return 0; 283 + } 284 + 285 + static int param_get_usb_online(char *buffer, const struct kernel_param *kp) 286 + { 287 + strcpy(buffer, map_get_key(map_ac_online, usb_online, "unknown")); 288 + return strlen(buffer); 289 + } 290 + 311 291 static int param_set_battery_status(const char *key, 312 292 const struct kernel_param *kp) 313 293 { ··· 396 350 397 351 #define param_get_battery_capacity param_get_int 398 352 353 + static int param_set_battery_voltage(const char *key, 354 + const struct kernel_param *kp) 355 + { 356 + int tmp; 399 357 358 + if (1 != sscanf(key, "%d", &tmp)) 359 + return -EINVAL; 360 + 361 + battery_voltage = tmp; 362 + power_supply_changed(&test_power_supplies[1]); 363 + return 0; 364 + } 365 + 366 + #define param_get_battery_voltage param_get_int 400 367 401 368 static struct kernel_param_ops param_ops_ac_online = { 402 369 .set = param_set_ac_online, 403 370 .get = param_get_ac_online, 371 + }; 372 + 373 + static struct kernel_param_ops param_ops_usb_online = { 374 + .set = param_set_usb_online, 375 + .get = param_get_usb_online, 404 376 }; 405 377 406 378 static struct kernel_param_ops param_ops_battery_status = { ··· 446 382 .get = param_get_battery_capacity, 447 383 }; 448 384 385 + static struct kernel_param_ops param_ops_battery_voltage = { 386 + .set = param_set_battery_voltage, 387 + .get = param_get_battery_voltage, 388 + }; 449 389 450 390 #define param_check_ac_online(name, p) __param_check(name, p, void); 391 + #define param_check_usb_online(name, p) __param_check(name, p, void); 451 392 #define param_check_battery_status(name, p) __param_check(name, p, void); 452 393 #define param_check_battery_present(name, p) __param_check(name, p, void); 453 394 #define param_check_battery_technology(name, p) __param_check(name, p, void); 454 395 #define param_check_battery_health(name, p) __param_check(name, p, void); 455 396 #define param_check_battery_capacity(name, p) __param_check(name, p, void); 397 + #define param_check_battery_voltage(name, p) __param_check(name, p, void); 456 398 457 399 458 400 module_param(ac_online, ac_online, 0644); 459 401 MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); 402 + 403 + module_param(usb_online, usb_online, 0644); 404 + MODULE_PARM_DESC(usb_online, "USB charging state <on|off>"); 460 405 461 406 module_param(battery_status, battery_status, 0644); 462 407 MODULE_PARM_DESC(battery_status, ··· 486 413 module_param(battery_capacity, battery_capacity, 0644); 487 414 MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); 488 415 416 + module_param(battery_voltage, battery_voltage, 0644); 417 + MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)"); 489 418 490 419 MODULE_DESCRIPTION("Power supply driver for testing"); 491 420 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
+77 -3
drivers/power/twl4030_charger.c
··· 22 22 #include <linux/power_supply.h> 23 23 #include <linux/notifier.h> 24 24 #include <linux/usb/otg.h> 25 + #include <linux/regulator/machine.h> 25 26 26 27 #define TWL4030_BCIMSTATEC 0x02 27 28 #define TWL4030_BCIICHG 0x08 ··· 30 29 #define TWL4030_BCIVBUS 0x0c 31 30 #define TWL4030_BCIMFSTS4 0x10 32 31 #define TWL4030_BCICTL1 0x23 32 + #define TWL4030_BB_CFG 0x12 33 33 34 34 #define TWL4030_BCIAUTOWEN BIT(5) 35 35 #define TWL4030_CONFIG_DONE BIT(4) ··· 40 38 #define TWL4030_USBFASTMCHG BIT(2) 41 39 #define TWL4030_STS_VBUS BIT(7) 42 40 #define TWL4030_STS_USB_ID BIT(2) 41 + #define TWL4030_BBCHEN BIT(4) 42 + #define TWL4030_BBSEL_MASK 0b1100 43 + #define TWL4030_BBSEL_2V5 0b0000 44 + #define TWL4030_BBSEL_3V0 0b0100 45 + #define TWL4030_BBSEL_3V1 0b1000 46 + #define TWL4030_BBSEL_3V2 0b1100 47 + #define TWL4030_BBISEL_MASK 0b11 48 + #define TWL4030_BBISEL_25uA 0b00 49 + #define TWL4030_BBISEL_150uA 0b01 50 + #define TWL4030_BBISEL_500uA 0b10 51 + #define TWL4030_BBISEL_1000uA 0b11 43 52 44 53 /* BCI interrupts */ 45 54 #define TWL4030_WOVF BIT(0) /* Watchdog overflow */ ··· 88 75 struct work_struct work; 89 76 int irq_chg; 90 77 int irq_bci; 78 + struct regulator *usb_reg; 79 + int usb_enabled; 91 80 92 81 unsigned long event; 93 82 }; ··· 119 104 120 105 static int twl4030_clear_set_boot_bci(u8 clear, u8 set) 121 106 { 122 - return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0, 107 + return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear, 123 108 TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, 124 109 TWL4030_PM_MASTER_BOOT_BCI); 125 110 } ··· 167 152 } 168 153 169 154 /* 170 - * Enable/Disable USB Charge funtionality. 155 + * Enable/Disable USB Charge functionality. 171 156 */ 172 157 static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) 173 158 { 174 159 int ret; 175 160 176 161 if (enable) { 177 - /* Check for USB charger conneted */ 162 + /* Check for USB charger connected */ 178 163 if (!twl4030_bci_have_vbus(bci)) 179 164 return -ENODEV; 180 165 ··· 187 172 return -EACCES; 188 173 } 189 174 175 + /* Need to keep regulator on */ 176 + if (!bci->usb_enabled) { 177 + regulator_enable(bci->usb_reg); 178 + bci->usb_enabled = 1; 179 + } 180 + 190 181 /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ 191 182 ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); 192 183 if (ret < 0) ··· 203 182 TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); 204 183 } else { 205 184 ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); 185 + if (bci->usb_enabled) { 186 + regulator_disable(bci->usb_reg); 187 + bci->usb_enabled = 0; 188 + } 206 189 } 207 190 208 191 return ret; ··· 223 198 ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC); 224 199 else 225 200 ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC, 0); 201 + 202 + return ret; 203 + } 204 + 205 + /* 206 + * Enable/Disable charging of Backup Battery. 207 + */ 208 + static int twl4030_charger_enable_backup(int uvolt, int uamp) 209 + { 210 + int ret; 211 + u8 flags; 212 + 213 + if (uvolt < 2500000 || 214 + uamp < 25) { 215 + /* disable charging of backup battery */ 216 + ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, 217 + TWL4030_BBCHEN, 0, TWL4030_BB_CFG); 218 + return ret; 219 + } 220 + 221 + flags = TWL4030_BBCHEN; 222 + if (uvolt >= 3200000) 223 + flags |= TWL4030_BBSEL_3V2; 224 + else if (uvolt >= 3100000) 225 + flags |= TWL4030_BBSEL_3V1; 226 + else if (uvolt >= 3000000) 227 + flags |= TWL4030_BBSEL_3V0; 228 + else 229 + flags |= TWL4030_BBSEL_2V5; 230 + 231 + if (uamp >= 1000) 232 + flags |= TWL4030_BBISEL_1000uA; 233 + else if (uamp >= 500) 234 + flags |= TWL4030_BBISEL_500uA; 235 + else if (uamp >= 150) 236 + flags |= TWL4030_BBISEL_150uA; 237 + else 238 + flags |= TWL4030_BBISEL_25uA; 239 + 240 + ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, 241 + TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK, 242 + flags, 243 + TWL4030_BB_CFG); 226 244 227 245 return ret; 228 246 } ··· 493 425 static int __init twl4030_bci_probe(struct platform_device *pdev) 494 426 { 495 427 struct twl4030_bci *bci; 428 + struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; 496 429 int ret; 497 430 u32 reg; 498 431 ··· 524 455 bci->usb.properties = twl4030_charger_props; 525 456 bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props); 526 457 bci->usb.get_property = twl4030_bci_get_property; 458 + 459 + bci->usb_reg = regulator_get(bci->dev, "bci3v1"); 527 460 528 461 ret = power_supply_register(&pdev->dev, &bci->usb); 529 462 if (ret) { ··· 575 504 576 505 twl4030_charger_enable_ac(true); 577 506 twl4030_charger_enable_usb(bci, true); 507 + twl4030_charger_enable_backup(pdata->bb_uvolt, 508 + pdata->bb_uamp); 578 509 579 510 return 0; 580 511 ··· 605 532 606 533 twl4030_charger_enable_ac(false); 607 534 twl4030_charger_enable_usb(bci, false); 535 + twl4030_charger_enable_backup(0, 0); 608 536 609 537 /* mask interrupts */ 610 538 twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
+1 -1
drivers/thermal/thermal_sys.c
··· 1251 1251 * longer needed. The passive cooling formula uses tc1 and tc2 as described in 1252 1252 * section 11.1.5.1 of the ACPI specification 3.0. 1253 1253 */ 1254 - struct thermal_zone_device *thermal_zone_device_register(char *type, 1254 + struct thermal_zone_device *thermal_zone_device_register(const char *type, 1255 1255 int trips, int mask, void *devdata, 1256 1256 const struct thermal_zone_device_ops *ops, 1257 1257 int tc1, int tc2, int passive_delay, int polling_delay)
+2
include/linux/i2c/twl.h
··· 555 555 struct twl4030_bci_platform_data { 556 556 int *battery_tmp_tbl; 557 557 unsigned int tblsize; 558 + int bb_uvolt; /* voltage to charge backup battery */ 559 + int bb_uamp; /* current for backup battery charging */ 558 560 }; 559 561 560 562 /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
include/linux/lp8727.h include/linux/platform_data/lp8727.h
+66 -1
include/linux/power/charger-manager.h
··· 16 16 #define _CHARGER_MANAGER_H 17 17 18 18 #include <linux/power_supply.h> 19 + #include <linux/extcon.h> 19 20 20 21 enum data_source { 21 22 CM_BATTERY_PRESENT, ··· 66 65 }; 67 66 68 67 /** 68 + * struct charger_cable 69 + * @extcon_name: the name of extcon device. 70 + * @name: the name of charger cable(external connector). 71 + * @extcon_dev: the extcon device. 72 + * @wq: the workqueue to control charger according to the state of 73 + * charger cable. If charger cable is attached, enable charger. 74 + * But if charger cable is detached, disable charger. 75 + * @nb: the notifier block to receive changed state from EXTCON 76 + * (External Connector) when charger cable is attached/detached. 77 + * @attached: the state of charger cable. 78 + * true: the charger cable is attached 79 + * false: the charger cable is detached 80 + * @charger: the instance of struct charger_regulator. 81 + * @cm: the Charger Manager representing the battery. 82 + */ 83 + struct charger_cable { 84 + const char *extcon_name; 85 + const char *name; 86 + 87 + /* The charger-manager use Exton framework*/ 88 + struct extcon_specific_cable_nb extcon_dev; 89 + struct work_struct wq; 90 + struct notifier_block nb; 91 + 92 + /* The state of charger cable */ 93 + bool attached; 94 + 95 + struct charger_regulator *charger; 96 + 97 + /* 98 + * Set min/max current of regulator to protect over-current issue 99 + * according to a kind of charger cable when cable is attached. 100 + */ 101 + int min_uA; 102 + int max_uA; 103 + 104 + struct charger_manager *cm; 105 + }; 106 + 107 + /** 108 + * struct charger_regulator 109 + * @regulator_name: the name of regulator for using charger. 110 + * @consumer: the regulator consumer for the charger. 111 + * @cables: 112 + * the array of charger cables to enable/disable charger 113 + * and set current limit according to constratint data of 114 + * struct charger_cable if only charger cable included 115 + * in the array of charger cables is attached/detached. 116 + * @num_cables: the number of charger cables. 117 + */ 118 + struct charger_regulator { 119 + /* The name of regulator for charging */ 120 + const char *regulator_name; 121 + struct regulator *consumer; 122 + 123 + /* 124 + * Store constraint information related to current limit, 125 + * each cable have different condition for charging. 126 + */ 127 + struct charger_cable *cables; 128 + int num_cables; 129 + }; 130 + 131 + /** 69 132 * struct charger_desc 70 133 * @psy_name: the name of power-supply-class for charger manager 71 134 * @polling_mode: ··· 174 109 char **psy_charger_stat; 175 110 176 111 int num_charger_regulators; 177 - struct regulator_bulk_data *charger_regulators; 112 + struct charger_regulator *charger_regulators; 178 113 179 114 char *psy_fuel_gauge; 180 115
+13
include/linux/power_supply.h
··· 109 109 POWER_SUPPLY_PROP_CHARGE_NOW, 110 110 POWER_SUPPLY_PROP_CHARGE_AVG, 111 111 POWER_SUPPLY_PROP_CHARGE_COUNTER, 112 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 113 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 112 114 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 113 115 POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, 114 116 POWER_SUPPLY_PROP_ENERGY_FULL, ··· 118 116 POWER_SUPPLY_PROP_ENERGY_NOW, 119 117 POWER_SUPPLY_PROP_ENERGY_AVG, 120 118 POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ 119 + POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, /* in percents! */ 120 + POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX, /* in percents! */ 121 121 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 122 122 POWER_SUPPLY_PROP_TEMP, 123 + POWER_SUPPLY_PROP_TEMP_ALERT_MIN, 124 + POWER_SUPPLY_PROP_TEMP_ALERT_MAX, 123 125 POWER_SUPPLY_PROP_TEMP_AMBIENT, 126 + POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN, 127 + POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX, 124 128 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 125 129 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 126 130 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, ··· 181 173 /* private */ 182 174 struct device *dev; 183 175 struct work_struct changed_work; 176 + #ifdef CONFIG_THERMAL 177 + struct thermal_zone_device *tzd; 178 + #endif 184 179 185 180 #ifdef CONFIG_LEDS_TRIGGERS 186 181 struct led_trigger *charging_full_trig; ··· 247 236 case POWER_SUPPLY_PROP_CHARGE_NOW: 248 237 case POWER_SUPPLY_PROP_CHARGE_AVG: 249 238 case POWER_SUPPLY_PROP_CHARGE_COUNTER: 239 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 250 240 case POWER_SUPPLY_PROP_CURRENT_MAX: 251 241 case POWER_SUPPLY_PROP_CURRENT_NOW: 252 242 case POWER_SUPPLY_PROP_CURRENT_AVG: ··· 275 263 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 276 264 case POWER_SUPPLY_PROP_VOLTAGE_AVG: 277 265 case POWER_SUPPLY_PROP_VOLTAGE_OCV: 266 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 278 267 case POWER_SUPPLY_PROP_POWER_NOW: 279 268 return 1; 280 269 default:
+1 -1
include/linux/thermal.h
··· 151 151 }; 152 152 #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) 153 153 154 - struct thermal_zone_device *thermal_zone_device_register(char *, int, int, 154 + struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, 155 155 void *, const struct thermal_zone_device_ops *, int tc1, 156 156 int tc2, int passive_freq, int polling_freq); 157 157 void thermal_zone_device_unregister(struct thermal_zone_device *);