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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCgAGBQJUZp/xAAoJENju1/PIO/qa77IQAIiHwwQXMLiJxY2j/0lVayPl Cr5PH6hshRs2+GflwF6GcpiiooIYi1wy+GCLRqGwWltwnwldJWU9Z1ILLcXqzxuG 6UNP4akrXY9Yo66lCQgDrPzoTTXx/bzwScN3sFS70c6ExEbC3RCnPfZEwin6g3CP W+ucwEbVLQ6sl/8t9NbJ3GJ37/TiY0CcRyhU4PLllOwrjUiPgyuM8ZvrS3F/7TQC ww16OOsT3c9tXlizRQM21j91/jN5+ZtCn9eAXfCk5Z/zJbWb57EL8b1iMn0UGUJs pVi+vxdTkPztJm8E0ihjaVCkBlJQlxPNdQn0FqpbgEL5RjY4O6MkBrS4VIvUlAbu +Q91/a83A74sr3Fq1J9hc0KB+jxZxFSJEqFWsGEuqkHYQhxfVZWzKLRNCrX0DNQl rlCQO1cl8CrKQqSsj6Ox/YurjedZv5/eTBRzKpCoc9F7Iof6MY2O2YSGQZkWkstQ DmUSL3eEVVkASfDie1ajMJl9OzrtrsdTeM1zcko7k+p2gHyEx8KXHOuxHFS6OX+I 0Z0EALRKKT5w03t9yyqGhYesvEZpcmP5kEMWSDMO/FsatacZzYGGpk67wvEwmL6K ty1C+m9Tqj76JqkqsEudc3pbSLj6M3r+qPc4WX2MPgzIADAPdeKKuADVG+5gGJFQ QFC8DjKLu/BLNM98kLzq =JVQ6 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
ec7de6567f
6 changed files with 144 additions and 72 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
|
#include <linux/time64.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
|
@ -108,7 +109,7 @@ enum ab8500_fg_calibration_state {
|
||||||
struct ab8500_fg_avg_cap {
|
struct ab8500_fg_avg_cap {
|
||||||
int avg;
|
int avg;
|
||||||
int samples[NBR_AVG_SAMPLES];
|
int samples[NBR_AVG_SAMPLES];
|
||||||
__kernel_time_t time_stamps[NBR_AVG_SAMPLES];
|
time64_t time_stamps[NBR_AVG_SAMPLES];
|
||||||
int pos;
|
int pos;
|
||||||
int nbr_samples;
|
int nbr_samples;
|
||||||
int sum;
|
int sum;
|
||||||
|
@ -386,15 +387,15 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
|
||||||
*/
|
*/
|
||||||
static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
|
static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec64 ts64;
|
||||||
struct ab8500_fg_avg_cap *avg = &di->avg_cap;
|
struct ab8500_fg_avg_cap *avg = &di->avg_cap;
|
||||||
|
|
||||||
getnstimeofday(&ts);
|
getnstimeofday64(&ts64);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
avg->sum += sample - avg->samples[avg->pos];
|
avg->sum += sample - avg->samples[avg->pos];
|
||||||
avg->samples[avg->pos] = sample;
|
avg->samples[avg->pos] = sample;
|
||||||
avg->time_stamps[avg->pos] = ts.tv_sec;
|
avg->time_stamps[avg->pos] = ts64.tv_sec;
|
||||||
avg->pos++;
|
avg->pos++;
|
||||||
|
|
||||||
if (avg->pos == NBR_AVG_SAMPLES)
|
if (avg->pos == NBR_AVG_SAMPLES)
|
||||||
|
@ -407,7 +408,7 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
|
||||||
* Check the time stamp for each sample. If too old,
|
* Check the time stamp for each sample. If too old,
|
||||||
* replace with latest sample
|
* replace with latest sample
|
||||||
*/
|
*/
|
||||||
} while (ts.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
|
} while (ts64.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
|
||||||
|
|
||||||
avg->avg = avg->sum / avg->nbr_samples;
|
avg->avg = avg->sum / avg->nbr_samples;
|
||||||
|
|
||||||
|
@ -446,14 +447,14 @@ static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
|
||||||
static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
|
static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct timespec ts;
|
struct timespec64 ts64;
|
||||||
struct ab8500_fg_avg_cap *avg = &di->avg_cap;
|
struct ab8500_fg_avg_cap *avg = &di->avg_cap;
|
||||||
|
|
||||||
getnstimeofday(&ts);
|
getnstimeofday64(&ts64);
|
||||||
|
|
||||||
for (i = 0; i < NBR_AVG_SAMPLES; i++) {
|
for (i = 0; i < NBR_AVG_SAMPLES; i++) {
|
||||||
avg->samples[i] = sample;
|
avg->samples[i] = sample;
|
||||||
avg->time_stamps[i] = ts.tv_sec;
|
avg->time_stamps[i] = ts64.tv_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
avg->pos = 0;
|
avg->pos = 0;
|
||||||
|
|
|
@ -1579,8 +1579,15 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
if (np) {
|
if (np) {
|
||||||
bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection");
|
bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection");
|
||||||
|
|
||||||
if (!bq->notify_psy)
|
if (IS_ERR(bq->notify_psy)) {
|
||||||
return -EPROBE_DEFER;
|
dev_info(&client->dev,
|
||||||
|
"no 'ti,usb-charger-detection' property (err=%ld)\n",
|
||||||
|
PTR_ERR(bq->notify_psy));
|
||||||
|
bq->notify_psy = NULL;
|
||||||
|
} else if (!bq->notify_psy) {
|
||||||
|
ret = -EPROBE_DEFER;
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (pdata->notify_device)
|
else if (pdata->notify_device)
|
||||||
bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
|
bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
|
||||||
|
@ -1602,27 +1609,27 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
ret = of_property_read_u32(np, "ti,current-limit",
|
ret = of_property_read_u32(np, "ti,current-limit",
|
||||||
&bq->init_data.current_limit);
|
&bq->init_data.current_limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error_2;
|
||||||
ret = of_property_read_u32(np, "ti,weak-battery-voltage",
|
ret = of_property_read_u32(np, "ti,weak-battery-voltage",
|
||||||
&bq->init_data.weak_battery_voltage);
|
&bq->init_data.weak_battery_voltage);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error_2;
|
||||||
ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
|
ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
|
||||||
&bq->init_data.battery_regulation_voltage);
|
&bq->init_data.battery_regulation_voltage);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error_2;
|
||||||
ret = of_property_read_u32(np, "ti,charge-current",
|
ret = of_property_read_u32(np, "ti,charge-current",
|
||||||
&bq->init_data.charge_current);
|
&bq->init_data.charge_current);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error_2;
|
||||||
ret = of_property_read_u32(np, "ti,termination-current",
|
ret = of_property_read_u32(np, "ti,termination-current",
|
||||||
&bq->init_data.termination_current);
|
&bq->init_data.termination_current);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error_2;
|
||||||
ret = of_property_read_u32(np, "ti,resistor-sense",
|
ret = of_property_read_u32(np, "ti,resistor-sense",
|
||||||
&bq->init_data.resistor_sense);
|
&bq->init_data.resistor_sense);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error_2;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
|
memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ static struct charger_global_desc *g_desc; /* init with setup_charger_manager */
|
||||||
static bool is_batt_present(struct charger_manager *cm)
|
static bool is_batt_present(struct charger_manager *cm)
|
||||||
{
|
{
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
|
struct power_supply *psy;
|
||||||
bool present = false;
|
bool present = false;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
|
@ -107,16 +108,27 @@ static bool is_batt_present(struct charger_manager *cm)
|
||||||
case CM_NO_BATTERY:
|
case CM_NO_BATTERY:
|
||||||
break;
|
break;
|
||||||
case CM_FUEL_GAUGE:
|
case CM_FUEL_GAUGE:
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
psy = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
|
||||||
|
if (!psy)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = psy->get_property(psy,
|
||||||
POWER_SUPPLY_PROP_PRESENT, &val);
|
POWER_SUPPLY_PROP_PRESENT, &val);
|
||||||
if (ret == 0 && val.intval)
|
if (ret == 0 && val.intval)
|
||||||
present = true;
|
present = true;
|
||||||
break;
|
break;
|
||||||
case CM_CHARGER_STAT:
|
case CM_CHARGER_STAT:
|
||||||
for (i = 0; cm->charger_stat[i]; i++) {
|
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
|
||||||
ret = cm->charger_stat[i]->get_property(
|
psy = power_supply_get_by_name(
|
||||||
cm->charger_stat[i],
|
cm->desc->psy_charger_stat[i]);
|
||||||
POWER_SUPPLY_PROP_PRESENT, &val);
|
if (!psy) {
|
||||||
|
dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
|
||||||
|
cm->desc->psy_charger_stat[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT,
|
||||||
|
&val);
|
||||||
if (ret == 0 && val.intval) {
|
if (ret == 0 && val.intval) {
|
||||||
present = true;
|
present = true;
|
||||||
break;
|
break;
|
||||||
|
@ -139,14 +151,20 @@ static bool is_batt_present(struct charger_manager *cm)
|
||||||
static bool is_ext_pwr_online(struct charger_manager *cm)
|
static bool is_ext_pwr_online(struct charger_manager *cm)
|
||||||
{
|
{
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
|
struct power_supply *psy;
|
||||||
bool online = false;
|
bool online = false;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
/* If at least one of them has one, it's yes. */
|
/* If at least one of them has one, it's yes. */
|
||||||
for (i = 0; cm->charger_stat[i]; i++) {
|
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
|
||||||
ret = cm->charger_stat[i]->get_property(
|
psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
|
||||||
cm->charger_stat[i],
|
if (!psy) {
|
||||||
POWER_SUPPLY_PROP_ONLINE, &val);
|
dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
|
||||||
|
cm->desc->psy_charger_stat[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
|
||||||
if (ret == 0 && val.intval) {
|
if (ret == 0 && val.intval) {
|
||||||
online = true;
|
online = true;
|
||||||
break;
|
break;
|
||||||
|
@ -167,12 +185,14 @@ static bool is_ext_pwr_online(struct charger_manager *cm)
|
||||||
static int get_batt_uV(struct charger_manager *cm, int *uV)
|
static int get_batt_uV(struct charger_manager *cm, int *uV)
|
||||||
{
|
{
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
|
struct power_supply *fuel_gauge;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!cm->fuel_gauge)
|
fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
|
||||||
|
if (!fuel_gauge)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
|
POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -189,6 +209,7 @@ static bool is_charging(struct charger_manager *cm)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
bool charging = false;
|
bool charging = false;
|
||||||
|
struct power_supply *psy;
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
|
|
||||||
/* If there is no battery, it cannot be charged */
|
/* If there is no battery, it cannot be charged */
|
||||||
|
@ -196,17 +217,22 @@ static bool is_charging(struct charger_manager *cm)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* If at least one of the charger is charging, return yes */
|
/* If at least one of the charger is charging, return yes */
|
||||||
for (i = 0; cm->charger_stat[i]; i++) {
|
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
|
||||||
/* 1. The charger sholuld not be DISABLED */
|
/* 1. The charger sholuld not be DISABLED */
|
||||||
if (cm->emergency_stop)
|
if (cm->emergency_stop)
|
||||||
continue;
|
continue;
|
||||||
if (!cm->charger_enabled)
|
if (!cm->charger_enabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
|
||||||
|
if (!psy) {
|
||||||
|
dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
|
||||||
|
cm->desc->psy_charger_stat[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* 2. The charger should be online (ext-power) */
|
/* 2. The charger should be online (ext-power) */
|
||||||
ret = cm->charger_stat[i]->get_property(
|
ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
|
||||||
cm->charger_stat[i],
|
|
||||||
POWER_SUPPLY_PROP_ONLINE, &val);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(cm->dev, "Cannot read ONLINE value from %s\n",
|
dev_warn(cm->dev, "Cannot read ONLINE value from %s\n",
|
||||||
cm->desc->psy_charger_stat[i]);
|
cm->desc->psy_charger_stat[i]);
|
||||||
|
@ -219,9 +245,7 @@ static bool is_charging(struct charger_manager *cm)
|
||||||
* 3. The charger should not be FULL, DISCHARGING,
|
* 3. The charger should not be FULL, DISCHARGING,
|
||||||
* or NOT_CHARGING.
|
* or NOT_CHARGING.
|
||||||
*/
|
*/
|
||||||
ret = cm->charger_stat[i]->get_property(
|
ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
|
||||||
cm->charger_stat[i],
|
|
||||||
POWER_SUPPLY_PROP_STATUS, &val);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(cm->dev, "Cannot read STATUS value from %s\n",
|
dev_warn(cm->dev, "Cannot read STATUS value from %s\n",
|
||||||
cm->desc->psy_charger_stat[i]);
|
cm->desc->psy_charger_stat[i]);
|
||||||
|
@ -248,6 +272,7 @@ static bool is_full_charged(struct charger_manager *cm)
|
||||||
{
|
{
|
||||||
struct charger_desc *desc = cm->desc;
|
struct charger_desc *desc = cm->desc;
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
|
struct power_supply *fuel_gauge;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int uV;
|
int uV;
|
||||||
|
|
||||||
|
@ -255,11 +280,15 @@ static bool is_full_charged(struct charger_manager *cm)
|
||||||
if (!is_batt_present(cm))
|
if (!is_batt_present(cm))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) {
|
fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
|
||||||
|
if (!fuel_gauge)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (desc->fullbatt_full_capacity > 0) {
|
||||||
val.intval = 0;
|
val.intval = 0;
|
||||||
|
|
||||||
/* Not full if capacity of fuel gauge isn't full */
|
/* Not full if capacity of fuel gauge isn't full */
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CHARGE_FULL, &val);
|
POWER_SUPPLY_PROP_CHARGE_FULL, &val);
|
||||||
if (!ret && val.intval > desc->fullbatt_full_capacity)
|
if (!ret && val.intval > desc->fullbatt_full_capacity)
|
||||||
return true;
|
return true;
|
||||||
|
@ -273,10 +302,10 @@ static bool is_full_charged(struct charger_manager *cm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Full, if the capacity is more than fullbatt_soc */
|
/* Full, if the capacity is more than fullbatt_soc */
|
||||||
if (cm->fuel_gauge && desc->fullbatt_soc > 0) {
|
if (desc->fullbatt_soc > 0) {
|
||||||
val.intval = 0;
|
val.intval = 0;
|
||||||
|
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CAPACITY, &val);
|
POWER_SUPPLY_PROP_CAPACITY, &val);
|
||||||
if (!ret && val.intval >= desc->fullbatt_soc)
|
if (!ret && val.intval >= desc->fullbatt_soc)
|
||||||
return true;
|
return true;
|
||||||
|
@ -551,6 +580,20 @@ static int check_charging_duration(struct charger_manager *cm)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
|
||||||
|
int *temp)
|
||||||
|
{
|
||||||
|
struct power_supply *fuel_gauge;
|
||||||
|
|
||||||
|
fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
|
||||||
|
if (!fuel_gauge)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return fuel_gauge->get_property(fuel_gauge,
|
||||||
|
POWER_SUPPLY_PROP_TEMP,
|
||||||
|
(union power_supply_propval *)temp);
|
||||||
|
}
|
||||||
|
|
||||||
static int cm_get_battery_temperature(struct charger_manager *cm,
|
static int cm_get_battery_temperature(struct charger_manager *cm,
|
||||||
int *temp)
|
int *temp)
|
||||||
{
|
{
|
||||||
|
@ -560,15 +603,18 @@ static int cm_get_battery_temperature(struct charger_manager *cm,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
#ifdef CONFIG_THERMAL
|
#ifdef CONFIG_THERMAL
|
||||||
ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
|
if (cm->tzd_batt) {
|
||||||
if (!ret)
|
ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
|
||||||
/* Calibrate temperature unit */
|
if (!ret)
|
||||||
*temp /= 100;
|
/* Calibrate temperature unit */
|
||||||
#else
|
*temp /= 100;
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
} else
|
||||||
POWER_SUPPLY_PROP_TEMP,
|
|
||||||
(union power_supply_propval *)temp);
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
/* if-else continued from CONFIG_THERMAL */
|
||||||
|
ret = cm_get_battery_temperature_by_psy(cm, temp);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,6 +873,7 @@ static int charger_get_property(struct power_supply *psy,
|
||||||
struct charger_manager *cm = container_of(psy,
|
struct charger_manager *cm = container_of(psy,
|
||||||
struct charger_manager, charger_psy);
|
struct charger_manager, charger_psy);
|
||||||
struct charger_desc *desc = cm->desc;
|
struct charger_desc *desc = cm->desc;
|
||||||
|
struct power_supply *fuel_gauge;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int uV;
|
int uV;
|
||||||
|
|
||||||
|
@ -857,14 +904,20 @@ static int charger_get_property(struct power_supply *psy,
|
||||||
ret = get_batt_uV(cm, &val->intval);
|
ret = get_batt_uV(cm, &val->intval);
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
|
||||||
|
if (!fuel_gauge) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CURRENT_NOW, val);
|
POWER_SUPPLY_PROP_CURRENT_NOW, val);
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_TEMP:
|
case POWER_SUPPLY_PROP_TEMP:
|
||||||
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
|
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
|
||||||
return cm_get_battery_temperature(cm, &val->intval);
|
return cm_get_battery_temperature(cm, &val->intval);
|
||||||
case POWER_SUPPLY_PROP_CAPACITY:
|
case POWER_SUPPLY_PROP_CAPACITY:
|
||||||
if (!cm->fuel_gauge) {
|
fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
|
||||||
|
if (!fuel_gauge) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -875,7 +928,7 @@ static int charger_get_property(struct power_supply *psy,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CAPACITY, val);
|
POWER_SUPPLY_PROP_CAPACITY, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
@ -924,7 +977,14 @@ static int charger_get_property(struct power_supply *psy,
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_NOW:
|
case POWER_SUPPLY_PROP_CHARGE_NOW:
|
||||||
if (is_charging(cm)) {
|
if (is_charging(cm)) {
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
fuel_gauge = power_supply_get_by_name(
|
||||||
|
cm->desc->psy_fuel_gauge);
|
||||||
|
if (!fuel_gauge) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CHARGE_NOW,
|
POWER_SUPPLY_PROP_CHARGE_NOW,
|
||||||
val);
|
val);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -970,6 +1030,7 @@ static struct power_supply psy_default = {
|
||||||
.properties = default_charger_props,
|
.properties = default_charger_props,
|
||||||
.num_properties = ARRAY_SIZE(default_charger_props),
|
.num_properties = ARRAY_SIZE(default_charger_props),
|
||||||
.get_property = charger_get_property,
|
.get_property = charger_get_property,
|
||||||
|
.no_thermal = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1485,14 +1546,15 @@ static int charger_manager_register_sysfs(struct charger_manager *cm)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cm_init_thermal_data(struct charger_manager *cm)
|
static int cm_init_thermal_data(struct charger_manager *cm,
|
||||||
|
struct power_supply *fuel_gauge)
|
||||||
{
|
{
|
||||||
struct charger_desc *desc = cm->desc;
|
struct charger_desc *desc = cm->desc;
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Verify whether fuel gauge provides battery temperature */
|
/* Verify whether fuel gauge provides battery temperature */
|
||||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
ret = fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_TEMP, &val);
|
POWER_SUPPLY_PROP_TEMP, &val);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
@ -1502,8 +1564,6 @@ static int cm_init_thermal_data(struct charger_manager *cm)
|
||||||
cm->desc->measure_battery_temp = true;
|
cm->desc->measure_battery_temp = true;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_THERMAL
|
#ifdef CONFIG_THERMAL
|
||||||
cm->tzd_batt = cm->fuel_gauge->tzd;
|
|
||||||
|
|
||||||
if (ret && desc->thermal_zone) {
|
if (ret && desc->thermal_zone) {
|
||||||
cm->tzd_batt =
|
cm->tzd_batt =
|
||||||
thermal_zone_get_zone_by_name(desc->thermal_zone);
|
thermal_zone_get_zone_by_name(desc->thermal_zone);
|
||||||
|
@ -1666,6 +1726,7 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
int ret = 0, i = 0;
|
int ret = 0, i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
|
struct power_supply *fuel_gauge;
|
||||||
|
|
||||||
if (g_desc && !rtc_dev && g_desc->rtc_name) {
|
if (g_desc && !rtc_dev && g_desc->rtc_name) {
|
||||||
rtc_dev = rtc_class_open(g_desc->rtc_name);
|
rtc_dev = rtc_class_open(g_desc->rtc_name);
|
||||||
|
@ -1729,23 +1790,20 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
while (desc->psy_charger_stat[i])
|
while (desc->psy_charger_stat[i])
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
cm->charger_stat = devm_kzalloc(&pdev->dev,
|
/* Check if charger's supplies are present at probe */
|
||||||
sizeof(struct power_supply *) * i, GFP_KERNEL);
|
|
||||||
if (!cm->charger_stat)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
for (i = 0; desc->psy_charger_stat[i]; i++) {
|
for (i = 0; desc->psy_charger_stat[i]; i++) {
|
||||||
cm->charger_stat[i] = power_supply_get_by_name(
|
struct power_supply *psy;
|
||||||
desc->psy_charger_stat[i]);
|
|
||||||
if (!cm->charger_stat[i]) {
|
psy = power_supply_get_by_name(desc->psy_charger_stat[i]);
|
||||||
|
if (!psy) {
|
||||||
dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
|
dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
|
||||||
desc->psy_charger_stat[i]);
|
desc->psy_charger_stat[i]);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
|
fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
|
||||||
if (!cm->fuel_gauge) {
|
if (!fuel_gauge) {
|
||||||
dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
|
dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
|
||||||
desc->psy_fuel_gauge);
|
desc->psy_fuel_gauge);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1788,13 +1846,13 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
cm->charger_psy.num_properties = psy_default.num_properties;
|
cm->charger_psy.num_properties = psy_default.num_properties;
|
||||||
|
|
||||||
/* Find which optional psy-properties are available */
|
/* Find which optional psy-properties are available */
|
||||||
if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
|
if (!fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
|
POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
|
||||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||||
POWER_SUPPLY_PROP_CHARGE_NOW;
|
POWER_SUPPLY_PROP_CHARGE_NOW;
|
||||||
cm->charger_psy.num_properties++;
|
cm->charger_psy.num_properties++;
|
||||||
}
|
}
|
||||||
if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
|
if (!fuel_gauge->get_property(fuel_gauge,
|
||||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||||
&val)) {
|
&val)) {
|
||||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||||
|
@ -1802,7 +1860,7 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
cm->charger_psy.num_properties++;
|
cm->charger_psy.num_properties++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cm_init_thermal_data(cm);
|
ret = cm_init_thermal_data(cm, fuel_gauge);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to initialize thermal data\n");
|
dev_err(&pdev->dev, "Failed to initialize thermal data\n");
|
||||||
cm->desc->measure_battery_temp = false;
|
cm->desc->measure_battery_temp = false;
|
||||||
|
@ -2066,8 +2124,8 @@ static bool find_power_supply(struct charger_manager *cm,
|
||||||
int i;
|
int i;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
for (i = 0; cm->charger_stat[i]; i++) {
|
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
|
||||||
if (psy == cm->charger_stat[i]) {
|
if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,6 +417,9 @@ static int psy_register_thermal(struct power_supply *psy)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (psy->no_thermal)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Register battery zone device psy reports temperature */
|
/* Register battery zone device psy reports temperature */
|
||||||
for (i = 0; i < psy->num_properties; i++) {
|
for (i = 0; i < psy->num_properties; i++) {
|
||||||
if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
|
if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
|
||||||
|
|
|
@ -253,9 +253,6 @@ struct charger_manager {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct charger_desc *desc;
|
struct charger_desc *desc;
|
||||||
|
|
||||||
struct power_supply *fuel_gauge;
|
|
||||||
struct power_supply **charger_stat;
|
|
||||||
|
|
||||||
#ifdef CONFIG_THERMAL
|
#ifdef CONFIG_THERMAL
|
||||||
struct thermal_zone_device *tzd_batt;
|
struct thermal_zone_device *tzd_batt;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -200,6 +200,12 @@ struct power_supply {
|
||||||
void (*external_power_changed)(struct power_supply *psy);
|
void (*external_power_changed)(struct power_supply *psy);
|
||||||
void (*set_charged)(struct power_supply *psy);
|
void (*set_charged)(struct power_supply *psy);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set if thermal zone should not be created for this power supply.
|
||||||
|
* For example for virtual supplies forwarding calls to actual
|
||||||
|
* sensors or other supplies.
|
||||||
|
*/
|
||||||
|
bool no_thermal;
|
||||||
/* For APM emulation, think legacy userspace. */
|
/* For APM emulation, think legacy userspace. */
|
||||||
int use_for_apm;
|
int use_for_apm;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue