aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/charger-manager.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 04:29:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 04:29:24 -0400
commite665faa424a4a782aa986274920c1fc5b76f5560 (patch)
tree2cf64abadecbbeadcffc02cb7671cb593fc45488 /drivers/power/charger-manager.c
parentca4da6948bc6a7010ecf916dad528c177dcb9a81 (diff)
parent18766f0936d444fd7ff2e0064bd6e69a89d5c6fc (diff)
Merge tag 'for-v3.7' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov: "1. New drivers: - Marvell 88pm860x charger and battery drivers; - Texas Instruments LP8788 charger driver; 2. Two new power supply properties: whether a battery is authentic, and chargers' maximal currents and voltages; 3. A lot of TI LP8727 Charger cleanups; 4. New features for Charger Manager, mainly now we can disable specific regulators; 5. Random fixes and cleanups for other drivers." Fix up trivial conflicts in <linux/mfd/88pm860x.h> * tag 'for-v3.7' of git://git.infradead.org/battery-2.6: (52 commits) pda_power: Remove ac_draw_failed goto and label charger-manager: Add support sysfs entry for charger charger-manager: Support limit of maximum possible charger-manager: Check fully charged state of battery periodically lp8727_charger: More pure cosmetic improvements lp8727_charger: Fix checkpatch warning lp8727_charger: Add description in the private data lp8727_charger: Fix a typo - chg_parm to chg_param lp8727_charger: Make some cosmetic changes in lp8727_delayed_func() lp8727_charger: Clean up lp8727_charger_changed() lp8727_charger: Return if the battery is discharging lp8727_charger: Make lp8727_charger_get_propery() simpler lp8727_charger: Make lp8727_ctrl_switch() inline lp8727_charger: Make lp8727_init_device() shorter lp8727_charger: Clean up lp8727_is_charger_attached() lp8727_charger: Use specific definition lp8727_charger: Clean up lp8727 definitions lp8727_charger: Use the definition rather than enum lp8727_charger: Fix code for getting battery temp lp8727_charger: Clear interrrupts at inital time ...
Diffstat (limited to 'drivers/power/charger-manager.c')
-rw-r--r--drivers/power/charger-manager.c434
1 files changed, 385 insertions, 49 deletions
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 7ff83cf43c8c..8a0aca6364c7 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -22,6 +22,7 @@
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/power/charger-manager.h> 23#include <linux/power/charger-manager.h>
24#include <linux/regulator/consumer.h> 24#include <linux/regulator/consumer.h>
25#include <linux/sysfs.h>
25 26
26static const char * const default_event_names[] = { 27static const char * const default_event_names[] = {
27 [CM_EVENT_UNKNOWN] = "Unknown", 28 [CM_EVENT_UNKNOWN] = "Unknown",
@@ -227,6 +228,58 @@ static bool is_charging(struct charger_manager *cm)
227} 228}
228 229
229/** 230/**
231 * is_full_charged - Returns true if the battery is fully charged.
232 * @cm: the Charger Manager representing the battery.
233 */
234static bool is_full_charged(struct charger_manager *cm)
235{
236 struct charger_desc *desc = cm->desc;
237 union power_supply_propval val;
238 int ret = 0;
239 int uV;
240
241 /* If there is no battery, it cannot be charged */
242 if (!is_batt_present(cm)) {
243 val.intval = 0;
244 goto out;
245 }
246
247 if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) {
248 /* Not full if capacity of fuel gauge isn't full */
249 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
250 POWER_SUPPLY_PROP_CHARGE_FULL, &val);
251 if (!ret && val.intval > desc->fullbatt_full_capacity) {
252 val.intval = 1;
253 goto out;
254 }
255 }
256
257 /* Full, if it's over the fullbatt voltage */
258 if (desc->fullbatt_uV > 0) {
259 ret = get_batt_uV(cm, &uV);
260 if (!ret && uV >= desc->fullbatt_uV) {
261 val.intval = 1;
262 goto out;
263 }
264 }
265
266 /* Full, if the capacity is more than fullbatt_soc */
267 if (cm->fuel_gauge && desc->fullbatt_soc > 0) {
268 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
269 POWER_SUPPLY_PROP_CAPACITY, &val);
270 if (!ret && val.intval >= desc->fullbatt_soc) {
271 val.intval = 1;
272 goto out;
273 }
274 }
275
276 val.intval = 0;
277
278out:
279 return val.intval ? true : false;
280}
281
282/**
230 * is_polling_required - Return true if need to continue polling for this CM. 283 * is_polling_required - Return true if need to continue polling for this CM.
231 * @cm: the Charger Manager representing the battery. 284 * @cm: the Charger Manager representing the battery.
232 */ 285 */
@@ -271,10 +324,46 @@ static int try_charger_enable(struct charger_manager *cm, bool enable)
271 if (enable) { 324 if (enable) {
272 if (cm->emergency_stop) 325 if (cm->emergency_stop)
273 return -EAGAIN; 326 return -EAGAIN;
274 for (i = 0 ; i < desc->num_charger_regulators ; i++) 327
275 regulator_enable(desc->charger_regulators[i].consumer); 328 /*
329 * Save start time of charging to limit
330 * maximum possible charging time.
331 */
332 cm->charging_start_time = ktime_to_ms(ktime_get());
333 cm->charging_end_time = 0;
334
335 for (i = 0 ; i < desc->num_charger_regulators ; i++) {
336 if (desc->charger_regulators[i].externally_control)
337 continue;
338
339 err = regulator_enable(desc->charger_regulators[i].consumer);
340 if (err < 0) {
341 dev_warn(cm->dev,
342 "Cannot enable %s regulator\n",
343 desc->charger_regulators[i].regulator_name);
344 }
345 }
276 } else { 346 } else {
277 /* 347 /*
348 * Save end time of charging to maintain fully charged state
349 * of battery after full-batt.
350 */
351 cm->charging_start_time = 0;
352 cm->charging_end_time = ktime_to_ms(ktime_get());
353
354 for (i = 0 ; i < desc->num_charger_regulators ; i++) {
355 if (desc->charger_regulators[i].externally_control)
356 continue;
357
358 err = regulator_disable(desc->charger_regulators[i].consumer);
359 if (err < 0) {
360 dev_warn(cm->dev,
361 "Cannot disable %s regulator\n",
362 desc->charger_regulators[i].regulator_name);
363 }
364 }
365
366 /*
278 * Abnormal battery state - Stop charging forcibly, 367 * Abnormal battery state - Stop charging forcibly,
279 * even if charger was enabled at the other places 368 * even if charger was enabled at the other places
280 */ 369 */
@@ -400,15 +489,62 @@ static void fullbatt_vchk(struct work_struct *work)
400 return; 489 return;
401 } 490 }
402 491
403 diff = cm->fullbatt_vchk_uV; 492 diff = desc->fullbatt_uV;
404 diff -= batt_uV; 493 diff -= batt_uV;
405 494
406 dev_dbg(cm->dev, "VBATT dropped %duV after full-batt.\n", diff); 495 dev_info(cm->dev, "VBATT dropped %duV after full-batt.\n", diff);
407 496
408 if (diff > desc->fullbatt_vchkdrop_uV) { 497 if (diff > desc->fullbatt_vchkdrop_uV) {
409 try_charger_restart(cm); 498 try_charger_restart(cm);
410 uevent_notify(cm, "Recharge"); 499 uevent_notify(cm, "Recharging");
500 }
501}
502
503/**
504 * check_charging_duration - Monitor charging/discharging duration
505 * @cm: the Charger Manager representing the battery.
506 *
507 * If whole charging duration exceed 'charging_max_duration_ms',
508 * cm stop charging to prevent overcharge/overheat. If discharging
509 * duration exceed 'discharging _max_duration_ms', charger cable is
510 * attached, after full-batt, cm start charging to maintain fully
511 * charged state for battery.
512 */
513static int check_charging_duration(struct charger_manager *cm)
514{
515 struct charger_desc *desc = cm->desc;
516 u64 curr = ktime_to_ms(ktime_get());
517 u64 duration;
518 int ret = false;
519
520 if (!desc->charging_max_duration_ms &&
521 !desc->discharging_max_duration_ms)
522 return ret;
523
524 if (cm->charger_enabled) {
525 duration = curr - cm->charging_start_time;
526
527 if (duration > desc->charging_max_duration_ms) {
528 dev_info(cm->dev, "Charging duration exceed %lldms",
529 desc->charging_max_duration_ms);
530 uevent_notify(cm, "Discharging");
531 try_charger_enable(cm, false);
532 ret = true;
533 }
534 } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
535 duration = curr - cm->charging_end_time;
536
537 if (duration > desc->charging_max_duration_ms &&
538 is_ext_pwr_online(cm)) {
539 dev_info(cm->dev, "DisCharging duration exceed %lldms",
540 desc->discharging_max_duration_ms);
541 uevent_notify(cm, "Recharing");
542 try_charger_enable(cm, true);
543 ret = true;
544 }
411 } 545 }
546
547 return ret;
412} 548}
413 549
414/** 550/**
@@ -426,10 +562,14 @@ static bool _cm_monitor(struct charger_manager *cm)
426 dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n", 562 dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n",
427 cm->last_temp_mC / 1000, cm->last_temp_mC % 1000); 563 cm->last_temp_mC / 1000, cm->last_temp_mC % 1000);
428 564
429 /* It has been stopped or charging already */ 565 /* It has been stopped already */
430 if (!!temp == !!cm->emergency_stop) 566 if (temp && cm->emergency_stop)
431 return false; 567 return false;
432 568
569 /*
570 * Check temperature whether overheat or cold.
571 * If temperature is out of range normal state, stop charging.
572 */
433 if (temp) { 573 if (temp) {
434 cm->emergency_stop = temp; 574 cm->emergency_stop = temp;
435 if (!try_charger_enable(cm, false)) { 575 if (!try_charger_enable(cm, false)) {
@@ -438,10 +578,41 @@ static bool _cm_monitor(struct charger_manager *cm)
438 else 578 else
439 uevent_notify(cm, "COLD"); 579 uevent_notify(cm, "COLD");
440 } 580 }
581
582 /*
583 * Check whole charging duration and discharing duration
584 * after full-batt.
585 */
586 } else if (!cm->emergency_stop && check_charging_duration(cm)) {
587 dev_dbg(cm->dev,
588 "Charging/Discharging duration is out of range");
589 /*
590 * Check dropped voltage of battery. If battery voltage is more
591 * dropped than fullbatt_vchkdrop_uV after fully charged state,
592 * charger-manager have to recharge battery.
593 */
594 } else if (!cm->emergency_stop && is_ext_pwr_online(cm) &&
595 !cm->charger_enabled) {
596 fullbatt_vchk(&cm->fullbatt_vchk_work.work);
597
598 /*
599 * Check whether fully charged state to protect overcharge
600 * if charger-manager is charging for battery.
601 */
602 } else if (!cm->emergency_stop && is_full_charged(cm) &&
603 cm->charger_enabled) {
604 dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n");
605 uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]);
606
607 try_charger_enable(cm, false);
608
609 fullbatt_vchk(&cm->fullbatt_vchk_work.work);
441 } else { 610 } else {
442 cm->emergency_stop = 0; 611 cm->emergency_stop = 0;
443 if (!try_charger_enable(cm, true)) 612 if (is_ext_pwr_online(cm)) {
444 uevent_notify(cm, "CHARGING"); 613 if (!try_charger_enable(cm, true))
614 uevent_notify(cm, "CHARGING");
615 }
445 } 616 }
446 617
447 return true; 618 return true;
@@ -701,47 +872,10 @@ static int charger_get_property(struct power_supply *psy,
701 val->intval = 0; 872 val->intval = 0;
702 break; 873 break;
703 case POWER_SUPPLY_PROP_CHARGE_FULL: 874 case POWER_SUPPLY_PROP_CHARGE_FULL:
704 if (cm->fuel_gauge) { 875 if (is_full_charged(cm))
705 if (cm->fuel_gauge->get_property(cm->fuel_gauge,
706 POWER_SUPPLY_PROP_CHARGE_FULL, val) == 0)
707 break;
708 }
709
710 if (is_ext_pwr_online(cm)) {
711 /* Not full if it's charging. */
712 if (is_charging(cm)) {
713 val->intval = 0;
714 break;
715 }
716 /*
717 * Full if it's powered but not charging andi
718 * not forced stop by emergency
719 */
720 if (!cm->emergency_stop) {
721 val->intval = 1;
722 break;
723 }
724 }
725
726 /* Full if it's over the fullbatt voltage */
727 ret = get_batt_uV(cm, &uV);
728 if (!ret && desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
729 !is_charging(cm)) {
730 val->intval = 1; 876 val->intval = 1;
731 break; 877 else
732 } 878 val->intval = 0;
733
734 /* Full if the cap is 100 */
735 if (cm->fuel_gauge) {
736 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
737 POWER_SUPPLY_PROP_CAPACITY, val);
738 if (!ret && val->intval >= 100 && !is_charging(cm)) {
739 val->intval = 1;
740 break;
741 }
742 }
743
744 val->intval = 0;
745 ret = 0; 879 ret = 0;
746 break; 880 break;
747 case POWER_SUPPLY_PROP_CHARGE_NOW: 881 case POWER_SUPPLY_PROP_CHARGE_NOW:
@@ -1031,7 +1165,26 @@ static int charger_extcon_notifier(struct notifier_block *self,
1031 struct charger_cable *cable = 1165 struct charger_cable *cable =
1032 container_of(self, struct charger_cable, nb); 1166 container_of(self, struct charger_cable, nb);
1033 1167
1168 /*
1169 * The newly state of charger cable.
1170 * If cable is attached, cable->attached is true.
1171 */
1034 cable->attached = event; 1172 cable->attached = event;
1173
1174 /*
1175 * Setup monitoring to check battery state
1176 * when charger cable is attached.
1177 */
1178 if (cable->attached && is_polling_required(cable->cm)) {
1179 if (work_pending(&setup_polling))
1180 cancel_work_sync(&setup_polling);
1181 schedule_work(&setup_polling);
1182 }
1183
1184 /*
1185 * Setup work for controlling charger(regulator)
1186 * according to charger cable.
1187 */
1035 schedule_work(&cable->wq); 1188 schedule_work(&cable->wq);
1036 1189
1037 return NOTIFY_DONE; 1190 return NOTIFY_DONE;
@@ -1068,12 +1221,101 @@ static int charger_extcon_init(struct charger_manager *cm,
1068 return ret; 1221 return ret;
1069} 1222}
1070 1223
1224/* help function of sysfs node to control charger(regulator) */
1225static ssize_t charger_name_show(struct device *dev,
1226 struct device_attribute *attr, char *buf)
1227{
1228 struct charger_regulator *charger
1229 = container_of(attr, struct charger_regulator, attr_name);
1230
1231 return sprintf(buf, "%s\n", charger->regulator_name);
1232}
1233
1234static ssize_t charger_state_show(struct device *dev,
1235 struct device_attribute *attr, char *buf)
1236{
1237 struct charger_regulator *charger
1238 = container_of(attr, struct charger_regulator, attr_state);
1239 int state = 0;
1240
1241 if (!charger->externally_control)
1242 state = regulator_is_enabled(charger->consumer);
1243
1244 return sprintf(buf, "%s\n", state ? "enabled" : "disabled");
1245}
1246
1247static ssize_t charger_externally_control_show(struct device *dev,
1248 struct device_attribute *attr, char *buf)
1249{
1250 struct charger_regulator *charger = container_of(attr,
1251 struct charger_regulator, attr_externally_control);
1252
1253 return sprintf(buf, "%d\n", charger->externally_control);
1254}
1255
1256static ssize_t charger_externally_control_store(struct device *dev,
1257 struct device_attribute *attr, const char *buf,
1258 size_t count)
1259{
1260 struct charger_regulator *charger
1261 = container_of(attr, struct charger_regulator,
1262 attr_externally_control);
1263 struct charger_manager *cm = charger->cm;
1264 struct charger_desc *desc = cm->desc;
1265 int i;
1266 int ret;
1267 int externally_control;
1268 int chargers_externally_control = 1;
1269
1270 ret = sscanf(buf, "%d", &externally_control);
1271 if (ret == 0) {
1272 ret = -EINVAL;
1273 return ret;
1274 }
1275
1276 if (!externally_control) {
1277 charger->externally_control = 0;
1278 return count;
1279 }
1280
1281 for (i = 0; i < desc->num_charger_regulators; i++) {
1282 if (&desc->charger_regulators[i] != charger &&
1283 !desc->charger_regulators[i].externally_control) {
1284 /*
1285 * At least, one charger is controlled by
1286 * charger-manager
1287 */
1288 chargers_externally_control = 0;
1289 break;
1290 }
1291 }
1292
1293 if (!chargers_externally_control) {
1294 if (cm->charger_enabled) {
1295 try_charger_enable(charger->cm, false);
1296 charger->externally_control = externally_control;
1297 try_charger_enable(charger->cm, true);
1298 } else {
1299 charger->externally_control = externally_control;
1300 }
1301 } else {
1302 dev_warn(cm->dev,
1303 "'%s' regulator should be controlled "
1304 "in charger-manager because charger-manager "
1305 "must need at least one charger for charging\n",
1306 charger->regulator_name);
1307 }
1308
1309 return count;
1310}
1311
1071static int charger_manager_probe(struct platform_device *pdev) 1312static int charger_manager_probe(struct platform_device *pdev)
1072{ 1313{
1073 struct charger_desc *desc = dev_get_platdata(&pdev->dev); 1314 struct charger_desc *desc = dev_get_platdata(&pdev->dev);
1074 struct charger_manager *cm; 1315 struct charger_manager *cm;
1075 int ret = 0, i = 0; 1316 int ret = 0, i = 0;
1076 int j = 0; 1317 int j = 0;
1318 int chargers_externally_control = 1;
1077 union power_supply_propval val; 1319 union power_supply_propval val;
1078 1320
1079 if (g_desc && !rtc_dev && g_desc->rtc_name) { 1321 if (g_desc && !rtc_dev && g_desc->rtc_name) {
@@ -1125,6 +1367,15 @@ static int charger_manager_probe(struct platform_device *pdev)
1125 desc->fullbatt_vchkdrop_ms = 0; 1367 desc->fullbatt_vchkdrop_ms = 0;
1126 desc->fullbatt_vchkdrop_uV = 0; 1368 desc->fullbatt_vchkdrop_uV = 0;
1127 } 1369 }
1370 if (desc->fullbatt_soc == 0) {
1371 dev_info(&pdev->dev, "Ignoring full-battery soc(state of"
1372 " charge) threshold as it is not"
1373 " supplied.");
1374 }
1375 if (desc->fullbatt_full_capacity == 0) {
1376 dev_info(&pdev->dev, "Ignoring full-battery full capacity"
1377 " threshold as it is not supplied.");
1378 }
1128 1379
1129 if (!desc->charger_regulators || desc->num_charger_regulators < 1) { 1380 if (!desc->charger_regulators || desc->num_charger_regulators < 1) {
1130 ret = -EINVAL; 1381 ret = -EINVAL;
@@ -1182,6 +1433,15 @@ static int charger_manager_probe(struct platform_device *pdev)
1182 goto err_chg_stat; 1433 goto err_chg_stat;
1183 } 1434 }
1184 1435
1436 if (!desc->charging_max_duration_ms ||
1437 !desc->discharging_max_duration_ms) {
1438 dev_info(&pdev->dev, "Cannot limit charging duration "
1439 "checking mechanism to prevent overcharge/overheat "
1440 "and control discharging duration");
1441 desc->charging_max_duration_ms = 0;
1442 desc->discharging_max_duration_ms = 0;
1443 }
1444
1185 platform_set_drvdata(pdev, cm); 1445 platform_set_drvdata(pdev, cm);
1186 1446
1187 memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); 1447 memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
@@ -1245,6 +1505,8 @@ static int charger_manager_probe(struct platform_device *pdev)
1245 for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1505 for (i = 0 ; i < desc->num_charger_regulators ; i++) {
1246 struct charger_regulator *charger 1506 struct charger_regulator *charger
1247 = &desc->charger_regulators[i]; 1507 = &desc->charger_regulators[i];
1508 char buf[11];
1509 char *str;
1248 1510
1249 charger->consumer = regulator_get(&pdev->dev, 1511 charger->consumer = regulator_get(&pdev->dev,
1250 charger->regulator_name); 1512 charger->regulator_name);
@@ -1254,6 +1516,7 @@ static int charger_manager_probe(struct platform_device *pdev)
1254 ret = -EINVAL; 1516 ret = -EINVAL;
1255 goto err_chg_get; 1517 goto err_chg_get;
1256 } 1518 }
1519 charger->cm = cm;
1257 1520
1258 for (j = 0 ; j < charger->num_cables ; j++) { 1521 for (j = 0 ; j < charger->num_cables ; j++) {
1259 struct charger_cable *cable = &charger->cables[j]; 1522 struct charger_cable *cable = &charger->cables[j];
@@ -1267,6 +1530,71 @@ static int charger_manager_probe(struct platform_device *pdev)
1267 cable->charger = charger; 1530 cable->charger = charger;
1268 cable->cm = cm; 1531 cable->cm = cm;
1269 } 1532 }
1533
1534 /* Create sysfs entry to control charger(regulator) */
1535 snprintf(buf, 10, "charger.%d", i);
1536 str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL);
1537 if (!str) {
1538 for (i--; i >= 0; i--) {
1539 charger = &desc->charger_regulators[i];
1540 kfree(charger->attr_g.name);
1541 }
1542 ret = -ENOMEM;
1543
1544 goto err_extcon;
1545 }
1546 strcpy(str, buf);
1547
1548 charger->attrs[0] = &charger->attr_name.attr;
1549 charger->attrs[1] = &charger->attr_state.attr;
1550 charger->attrs[2] = &charger->attr_externally_control.attr;
1551 charger->attrs[3] = NULL;
1552 charger->attr_g.name = str;
1553 charger->attr_g.attrs = charger->attrs;
1554
1555 sysfs_attr_init(&charger->attr_name.attr);
1556 charger->attr_name.attr.name = "name";
1557 charger->attr_name.attr.mode = 0444;
1558 charger->attr_name.show = charger_name_show;
1559
1560 sysfs_attr_init(&charger->attr_state.attr);
1561 charger->attr_state.attr.name = "state";
1562 charger->attr_state.attr.mode = 0444;
1563 charger->attr_state.show = charger_state_show;
1564
1565 sysfs_attr_init(&charger->attr_externally_control.attr);
1566 charger->attr_externally_control.attr.name
1567 = "externally_control";
1568 charger->attr_externally_control.attr.mode = 0644;
1569 charger->attr_externally_control.show
1570 = charger_externally_control_show;
1571 charger->attr_externally_control.store
1572 = charger_externally_control_store;
1573
1574 if (!desc->charger_regulators[i].externally_control ||
1575 !chargers_externally_control) {
1576 chargers_externally_control = 0;
1577 }
1578 dev_info(&pdev->dev, "'%s' regulator's externally_control"
1579 "is %d\n", charger->regulator_name,
1580 charger->externally_control);
1581
1582 ret = sysfs_create_group(&cm->charger_psy.dev->kobj,
1583 &charger->attr_g);
1584 if (ret < 0) {
1585 dev_info(&pdev->dev, "Cannot create sysfs entry"
1586 "of %s regulator\n",
1587 charger->regulator_name);
1588 }
1589 }
1590
1591 if (chargers_externally_control) {
1592 dev_err(&pdev->dev, "Cannot register regulator because "
1593 "charger-manager must need at least "
1594 "one charger for charging battery\n");
1595
1596 ret = -EINVAL;
1597 goto err_chg_enable;
1270 } 1598 }
1271 1599
1272 ret = try_charger_enable(cm, true); 1600 ret = try_charger_enable(cm, true);
@@ -1292,6 +1620,14 @@ static int charger_manager_probe(struct platform_device *pdev)
1292 return 0; 1620 return 0;
1293 1621
1294err_chg_enable: 1622err_chg_enable:
1623 for (i = 0; i < desc->num_charger_regulators; i++) {
1624 struct charger_regulator *charger;
1625
1626 charger = &desc->charger_regulators[i];
1627 sysfs_remove_group(&cm->charger_psy.dev->kobj,
1628 &charger->attr_g);
1629 kfree(charger->attr_g.name);
1630 }
1295err_extcon: 1631err_extcon:
1296 for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1632 for (i = 0 ; i < desc->num_charger_regulators ; i++) {
1297 struct charger_regulator *charger 1633 struct charger_regulator *charger