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

Pull power supply updates from Sebastian Reichel:
"Power supply and reset changes for the v3.18-rc:

- misc. charger-manager fixes
- year 2038 fix in ab8500_fg
- fix error handling of bq2415x_charger"

* tag 'for-v3.18-rc' of git://git.infradead.org/battery-2.6:
power: charger-manager: Fix accessing invalidated power supply after charger unbind
power: charger-manager: Fix accessing invalidated power supply after fuel gauge unbind
power: charger-manager: Avoid recursive thermal get_temp call
power_supply: Add no_thermal property to prevent recursive get_temp calls
power: bq2415x_charger: Fix memory leak on DTS parsing error
power: bq2415x_charger: Properly handle ENODEV from power_supply_get_by_phandle
power: ab8500_fg.c: use 64-bit time types

+144 -72
+9 -8
drivers/power/ab8500_fg.c
··· 25 25 #include <linux/slab.h> 26 26 #include <linux/delay.h> 27 27 #include <linux/time.h> 28 + #include <linux/time64.h> 28 29 #include <linux/of.h> 29 30 #include <linux/completion.h> 30 31 #include <linux/mfd/core.h> ··· 109 108 struct ab8500_fg_avg_cap { 110 109 int avg; 111 110 int samples[NBR_AVG_SAMPLES]; 112 - __kernel_time_t time_stamps[NBR_AVG_SAMPLES]; 111 + time64_t time_stamps[NBR_AVG_SAMPLES]; 113 112 int pos; 114 113 int nbr_samples; 115 114 int sum; ··· 387 386 */ 388 387 static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample) 389 388 { 390 - struct timespec ts; 389 + struct timespec64 ts64; 391 390 struct ab8500_fg_avg_cap *avg = &di->avg_cap; 392 391 393 - getnstimeofday(&ts); 392 + getnstimeofday64(&ts64); 394 393 395 394 do { 396 395 avg->sum += sample - avg->samples[avg->pos]; 397 396 avg->samples[avg->pos] = sample; 398 - avg->time_stamps[avg->pos] = ts.tv_sec; 397 + avg->time_stamps[avg->pos] = ts64.tv_sec; 399 398 avg->pos++; 400 399 401 400 if (avg->pos == NBR_AVG_SAMPLES) ··· 408 407 * Check the time stamp for each sample. If too old, 409 408 * replace with latest sample 410 409 */ 411 - } while (ts.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]); 410 + } while (ts64.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]); 412 411 413 412 avg->avg = avg->sum / avg->nbr_samples; 414 413 ··· 447 446 static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample) 448 447 { 449 448 int i; 450 - struct timespec ts; 449 + struct timespec64 ts64; 451 450 struct ab8500_fg_avg_cap *avg = &di->avg_cap; 452 451 453 - getnstimeofday(&ts); 452 + getnstimeofday64(&ts64); 454 453 455 454 for (i = 0; i < NBR_AVG_SAMPLES; i++) { 456 455 avg->samples[i] = sample; 457 - avg->time_stamps[i] = ts.tv_sec; 456 + avg->time_stamps[i] = ts64.tv_sec; 458 457 } 459 458 460 459 avg->pos = 0;
+15 -8
drivers/power/bq2415x_charger.c
··· 1579 1579 if (np) { 1580 1580 bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection"); 1581 1581 1582 - if (!bq->notify_psy) 1583 - return -EPROBE_DEFER; 1582 + if (IS_ERR(bq->notify_psy)) { 1583 + dev_info(&client->dev, 1584 + "no 'ti,usb-charger-detection' property (err=%ld)\n", 1585 + PTR_ERR(bq->notify_psy)); 1586 + bq->notify_psy = NULL; 1587 + } else if (!bq->notify_psy) { 1588 + ret = -EPROBE_DEFER; 1589 + goto error_2; 1590 + } 1584 1591 } 1585 1592 else if (pdata->notify_device) 1586 1593 bq->notify_psy = power_supply_get_by_name(pdata->notify_device); ··· 1609 1602 ret = of_property_read_u32(np, "ti,current-limit", 1610 1603 &bq->init_data.current_limit); 1611 1604 if (ret) 1612 - return ret; 1605 + goto error_2; 1613 1606 ret = of_property_read_u32(np, "ti,weak-battery-voltage", 1614 1607 &bq->init_data.weak_battery_voltage); 1615 1608 if (ret) 1616 - return ret; 1609 + goto error_2; 1617 1610 ret = of_property_read_u32(np, "ti,battery-regulation-voltage", 1618 1611 &bq->init_data.battery_regulation_voltage); 1619 1612 if (ret) 1620 - return ret; 1613 + goto error_2; 1621 1614 ret = of_property_read_u32(np, "ti,charge-current", 1622 1615 &bq->init_data.charge_current); 1623 1616 if (ret) 1624 - return ret; 1617 + goto error_2; 1625 1618 ret = of_property_read_u32(np, "ti,termination-current", 1626 1619 &bq->init_data.termination_current); 1627 1620 if (ret) 1628 - return ret; 1621 + goto error_2; 1629 1622 ret = of_property_read_u32(np, "ti,resistor-sense", 1630 1623 &bq->init_data.resistor_sense); 1631 1624 if (ret) 1632 - return ret; 1625 + goto error_2; 1633 1626 } else { 1634 1627 memcpy(&bq->init_data, pdata, sizeof(bq->init_data)); 1635 1628 }
+111 -53
drivers/power/charger-manager.c
··· 97 97 static bool is_batt_present(struct charger_manager *cm) 98 98 { 99 99 union power_supply_propval val; 100 + struct power_supply *psy; 100 101 bool present = false; 101 102 int i, ret; 102 103 ··· 108 107 case CM_NO_BATTERY: 109 108 break; 110 109 case CM_FUEL_GAUGE: 111 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 110 + psy = power_supply_get_by_name(cm->desc->psy_fuel_gauge); 111 + if (!psy) 112 + break; 113 + 114 + ret = psy->get_property(psy, 112 115 POWER_SUPPLY_PROP_PRESENT, &val); 113 116 if (ret == 0 && val.intval) 114 117 present = true; 115 118 break; 116 119 case CM_CHARGER_STAT: 117 - for (i = 0; cm->charger_stat[i]; i++) { 118 - ret = cm->charger_stat[i]->get_property( 119 - cm->charger_stat[i], 120 - POWER_SUPPLY_PROP_PRESENT, &val); 120 + for (i = 0; cm->desc->psy_charger_stat[i]; i++) { 121 + psy = power_supply_get_by_name( 122 + cm->desc->psy_charger_stat[i]); 123 + if (!psy) { 124 + dev_err(cm->dev, "Cannot find power supply \"%s\"\n", 125 + cm->desc->psy_charger_stat[i]); 126 + continue; 127 + } 128 + 129 + ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, 130 + &val); 121 131 if (ret == 0 && val.intval) { 122 132 present = true; 123 133 break; ··· 151 139 static bool is_ext_pwr_online(struct charger_manager *cm) 152 140 { 153 141 union power_supply_propval val; 142 + struct power_supply *psy; 154 143 bool online = false; 155 144 int i, ret; 156 145 157 146 /* If at least one of them has one, it's yes. */ 158 - for (i = 0; cm->charger_stat[i]; i++) { 159 - ret = cm->charger_stat[i]->get_property( 160 - cm->charger_stat[i], 161 - POWER_SUPPLY_PROP_ONLINE, &val); 147 + for (i = 0; cm->desc->psy_charger_stat[i]; i++) { 148 + psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); 149 + if (!psy) { 150 + dev_err(cm->dev, "Cannot find power supply \"%s\"\n", 151 + cm->desc->psy_charger_stat[i]); 152 + continue; 153 + } 154 + 155 + ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); 162 156 if (ret == 0 && val.intval) { 163 157 online = true; 164 158 break; ··· 185 167 static int get_batt_uV(struct charger_manager *cm, int *uV) 186 168 { 187 169 union power_supply_propval val; 170 + struct power_supply *fuel_gauge; 188 171 int ret; 189 172 190 - if (!cm->fuel_gauge) 173 + fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); 174 + if (!fuel_gauge) 191 175 return -ENODEV; 192 176 193 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 177 + ret = fuel_gauge->get_property(fuel_gauge, 194 178 POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); 195 179 if (ret) 196 180 return ret; ··· 209 189 { 210 190 int i, ret; 211 191 bool charging = false; 192 + struct power_supply *psy; 212 193 union power_supply_propval val; 213 194 214 195 /* If there is no battery, it cannot be charged */ ··· 217 196 return false; 218 197 219 198 /* If at least one of the charger is charging, return yes */ 220 - for (i = 0; cm->charger_stat[i]; i++) { 199 + for (i = 0; cm->desc->psy_charger_stat[i]; i++) { 221 200 /* 1. The charger sholuld not be DISABLED */ 222 201 if (cm->emergency_stop) 223 202 continue; 224 203 if (!cm->charger_enabled) 225 204 continue; 226 205 206 + psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); 207 + if (!psy) { 208 + dev_err(cm->dev, "Cannot find power supply \"%s\"\n", 209 + cm->desc->psy_charger_stat[i]); 210 + continue; 211 + } 212 + 227 213 /* 2. The charger should be online (ext-power) */ 228 - ret = cm->charger_stat[i]->get_property( 229 - cm->charger_stat[i], 230 - POWER_SUPPLY_PROP_ONLINE, &val); 214 + ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); 231 215 if (ret) { 232 216 dev_warn(cm->dev, "Cannot read ONLINE value from %s\n", 233 217 cm->desc->psy_charger_stat[i]); ··· 245 219 * 3. The charger should not be FULL, DISCHARGING, 246 220 * or NOT_CHARGING. 247 221 */ 248 - ret = cm->charger_stat[i]->get_property( 249 - cm->charger_stat[i], 250 - POWER_SUPPLY_PROP_STATUS, &val); 222 + ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val); 251 223 if (ret) { 252 224 dev_warn(cm->dev, "Cannot read STATUS value from %s\n", 253 225 cm->desc->psy_charger_stat[i]); ··· 272 248 { 273 249 struct charger_desc *desc = cm->desc; 274 250 union power_supply_propval val; 251 + struct power_supply *fuel_gauge; 275 252 int ret = 0; 276 253 int uV; 277 254 ··· 280 255 if (!is_batt_present(cm)) 281 256 return false; 282 257 283 - if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { 258 + fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); 259 + if (!fuel_gauge) 260 + return false; 261 + 262 + if (desc->fullbatt_full_capacity > 0) { 284 263 val.intval = 0; 285 264 286 265 /* Not full if capacity of fuel gauge isn't full */ 287 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 266 + ret = fuel_gauge->get_property(fuel_gauge, 288 267 POWER_SUPPLY_PROP_CHARGE_FULL, &val); 289 268 if (!ret && val.intval > desc->fullbatt_full_capacity) 290 269 return true; ··· 302 273 } 303 274 304 275 /* Full, if the capacity is more than fullbatt_soc */ 305 - if (cm->fuel_gauge && desc->fullbatt_soc > 0) { 276 + if (desc->fullbatt_soc > 0) { 306 277 val.intval = 0; 307 278 308 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 279 + ret = fuel_gauge->get_property(fuel_gauge, 309 280 POWER_SUPPLY_PROP_CAPACITY, &val); 310 281 if (!ret && val.intval >= desc->fullbatt_soc) 311 282 return true; ··· 580 551 return ret; 581 552 } 582 553 554 + static int cm_get_battery_temperature_by_psy(struct charger_manager *cm, 555 + int *temp) 556 + { 557 + struct power_supply *fuel_gauge; 558 + 559 + fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); 560 + if (!fuel_gauge) 561 + return -ENODEV; 562 + 563 + return fuel_gauge->get_property(fuel_gauge, 564 + POWER_SUPPLY_PROP_TEMP, 565 + (union power_supply_propval *)temp); 566 + } 567 + 583 568 static int cm_get_battery_temperature(struct charger_manager *cm, 584 569 int *temp) 585 570 { ··· 603 560 return -ENODEV; 604 561 605 562 #ifdef CONFIG_THERMAL 606 - ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); 607 - if (!ret) 608 - /* Calibrate temperature unit */ 609 - *temp /= 100; 610 - #else 611 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 612 - POWER_SUPPLY_PROP_TEMP, 613 - (union power_supply_propval *)temp); 563 + if (cm->tzd_batt) { 564 + ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); 565 + if (!ret) 566 + /* Calibrate temperature unit */ 567 + *temp /= 100; 568 + } else 614 569 #endif 570 + { 571 + /* if-else continued from CONFIG_THERMAL */ 572 + ret = cm_get_battery_temperature_by_psy(cm, temp); 573 + } 574 + 615 575 return ret; 616 576 } 617 577 ··· 873 827 struct charger_manager *cm = container_of(psy, 874 828 struct charger_manager, charger_psy); 875 829 struct charger_desc *desc = cm->desc; 830 + struct power_supply *fuel_gauge; 876 831 int ret = 0; 877 832 int uV; 878 833 ··· 904 857 ret = get_batt_uV(cm, &val->intval); 905 858 break; 906 859 case POWER_SUPPLY_PROP_CURRENT_NOW: 907 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 860 + fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); 861 + if (!fuel_gauge) { 862 + ret = -ENODEV; 863 + break; 864 + } 865 + ret = fuel_gauge->get_property(fuel_gauge, 908 866 POWER_SUPPLY_PROP_CURRENT_NOW, val); 909 867 break; 910 868 case POWER_SUPPLY_PROP_TEMP: 911 869 case POWER_SUPPLY_PROP_TEMP_AMBIENT: 912 870 return cm_get_battery_temperature(cm, &val->intval); 913 871 case POWER_SUPPLY_PROP_CAPACITY: 914 - if (!cm->fuel_gauge) { 872 + fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); 873 + if (!fuel_gauge) { 915 874 ret = -ENODEV; 916 875 break; 917 876 } ··· 928 875 break; 929 876 } 930 877 931 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 878 + ret = fuel_gauge->get_property(fuel_gauge, 932 879 POWER_SUPPLY_PROP_CAPACITY, val); 933 880 if (ret) 934 881 break; ··· 977 924 break; 978 925 case POWER_SUPPLY_PROP_CHARGE_NOW: 979 926 if (is_charging(cm)) { 980 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 927 + fuel_gauge = power_supply_get_by_name( 928 + cm->desc->psy_fuel_gauge); 929 + if (!fuel_gauge) { 930 + ret = -ENODEV; 931 + break; 932 + } 933 + 934 + ret = fuel_gauge->get_property(fuel_gauge, 981 935 POWER_SUPPLY_PROP_CHARGE_NOW, 982 936 val); 983 937 if (ret) { ··· 1030 970 .properties = default_charger_props, 1031 971 .num_properties = ARRAY_SIZE(default_charger_props), 1032 972 .get_property = charger_get_property, 973 + .no_thermal = true, 1033 974 }; 1034 975 1035 976 /** ··· 1546 1485 return ret; 1547 1486 } 1548 1487 1549 - static int cm_init_thermal_data(struct charger_manager *cm) 1488 + static int cm_init_thermal_data(struct charger_manager *cm, 1489 + struct power_supply *fuel_gauge) 1550 1490 { 1551 1491 struct charger_desc *desc = cm->desc; 1552 1492 union power_supply_propval val; 1553 1493 int ret; 1554 1494 1555 1495 /* Verify whether fuel gauge provides battery temperature */ 1556 - ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 1496 + ret = fuel_gauge->get_property(fuel_gauge, 1557 1497 POWER_SUPPLY_PROP_TEMP, &val); 1558 1498 1559 1499 if (!ret) { ··· 1564 1502 cm->desc->measure_battery_temp = true; 1565 1503 } 1566 1504 #ifdef CONFIG_THERMAL 1567 - cm->tzd_batt = cm->fuel_gauge->tzd; 1568 - 1569 1505 if (ret && desc->thermal_zone) { 1570 1506 cm->tzd_batt = 1571 1507 thermal_zone_get_zone_by_name(desc->thermal_zone); ··· 1726 1666 int ret = 0, i = 0; 1727 1667 int j = 0; 1728 1668 union power_supply_propval val; 1669 + struct power_supply *fuel_gauge; 1729 1670 1730 1671 if (g_desc && !rtc_dev && g_desc->rtc_name) { 1731 1672 rtc_dev = rtc_class_open(g_desc->rtc_name); ··· 1790 1729 while (desc->psy_charger_stat[i]) 1791 1730 i++; 1792 1731 1793 - cm->charger_stat = devm_kzalloc(&pdev->dev, 1794 - sizeof(struct power_supply *) * i, GFP_KERNEL); 1795 - if (!cm->charger_stat) 1796 - return -ENOMEM; 1797 - 1732 + /* Check if charger's supplies are present at probe */ 1798 1733 for (i = 0; desc->psy_charger_stat[i]; i++) { 1799 - cm->charger_stat[i] = power_supply_get_by_name( 1800 - desc->psy_charger_stat[i]); 1801 - if (!cm->charger_stat[i]) { 1734 + struct power_supply *psy; 1735 + 1736 + psy = power_supply_get_by_name(desc->psy_charger_stat[i]); 1737 + if (!psy) { 1802 1738 dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", 1803 1739 desc->psy_charger_stat[i]); 1804 1740 return -ENODEV; 1805 1741 } 1806 1742 } 1807 1743 1808 - cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); 1809 - if (!cm->fuel_gauge) { 1744 + fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); 1745 + if (!fuel_gauge) { 1810 1746 dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", 1811 1747 desc->psy_fuel_gauge); 1812 1748 return -ENODEV; ··· 1846 1788 cm->charger_psy.num_properties = psy_default.num_properties; 1847 1789 1848 1790 /* Find which optional psy-properties are available */ 1849 - if (!cm->fuel_gauge->get_property(cm->fuel_gauge, 1791 + if (!fuel_gauge->get_property(fuel_gauge, 1850 1792 POWER_SUPPLY_PROP_CHARGE_NOW, &val)) { 1851 1793 cm->charger_psy.properties[cm->charger_psy.num_properties] = 1852 1794 POWER_SUPPLY_PROP_CHARGE_NOW; 1853 1795 cm->charger_psy.num_properties++; 1854 1796 } 1855 - if (!cm->fuel_gauge->get_property(cm->fuel_gauge, 1797 + if (!fuel_gauge->get_property(fuel_gauge, 1856 1798 POWER_SUPPLY_PROP_CURRENT_NOW, 1857 1799 &val)) { 1858 1800 cm->charger_psy.properties[cm->charger_psy.num_properties] = ··· 1860 1802 cm->charger_psy.num_properties++; 1861 1803 } 1862 1804 1863 - ret = cm_init_thermal_data(cm); 1805 + ret = cm_init_thermal_data(cm, fuel_gauge); 1864 1806 if (ret) { 1865 1807 dev_err(&pdev->dev, "Failed to initialize thermal data\n"); 1866 1808 cm->desc->measure_battery_temp = false; ··· 2124 2066 int i; 2125 2067 bool found = false; 2126 2068 2127 - for (i = 0; cm->charger_stat[i]; i++) { 2128 - if (psy == cm->charger_stat[i]) { 2069 + for (i = 0; cm->desc->psy_charger_stat[i]; i++) { 2070 + if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) { 2129 2071 found = true; 2130 2072 break; 2131 2073 }
+3
drivers/power/power_supply_core.c
··· 417 417 { 418 418 int i; 419 419 420 + if (psy->no_thermal) 421 + return 0; 422 + 420 423 /* Register battery zone device psy reports temperature */ 421 424 for (i = 0; i < psy->num_properties; i++) { 422 425 if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
-3
include/linux/power/charger-manager.h
··· 253 253 struct device *dev; 254 254 struct charger_desc *desc; 255 255 256 - struct power_supply *fuel_gauge; 257 - struct power_supply **charger_stat; 258 - 259 256 #ifdef CONFIG_THERMAL 260 257 struct thermal_zone_device *tzd_batt; 261 258 #endif
+6
include/linux/power_supply.h
··· 200 200 void (*external_power_changed)(struct power_supply *psy); 201 201 void (*set_charged)(struct power_supply *psy); 202 202 203 + /* 204 + * Set if thermal zone should not be created for this power supply. 205 + * For example for virtual supplies forwarding calls to actual 206 + * sensors or other supplies. 207 + */ 208 + bool no_thermal; 203 209 /* For APM emulation, think legacy userspace. */ 204 210 int use_for_apm; 205 211