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