Commit 4e924a81 authored by Grazvydas Ignotas's avatar Grazvydas Ignotas Committed by Anton Vorontsov

power_supply: bq27x00: add status and time properties

The BQ27x00 series of chips can report time-to-empty and
time-to-full, so let's add corresponding properties.
Also report charge status based on status flag register.
Signed-off-by: default avatarGrazvydas Ignotas <notasas@gmail.com>
Signed-off-by: default avatarAnton Vorontsov <cbouatmailru@gmail.com>
parent e20908d9
......@@ -32,10 +32,16 @@
#define BQ27x00_REG_VOLT 0x08
#define BQ27x00_REG_AI 0x14
#define BQ27x00_REG_FLAGS 0x0A
#define BQ27x00_REG_TTE 0x16
#define BQ27x00_REG_TTF 0x18
#define BQ27x00_REG_TTECP 0x26
#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
#define BQ27000_FLAG_CHGS BIT(7)
#define BQ27500_REG_SOC 0x2c
#define BQ27500_FLAG_DSC BIT(0)
#define BQ27500_FLAG_FC BIT(9)
/* If the system has several batteries we need a different name for each
* of them...
......@@ -62,11 +68,15 @@ struct bq27x00_device_info {
};
static enum power_supply_property bq27x00_battery_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
};
/*
......@@ -144,7 +154,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di)
dev_err(di->dev, "error reading flags\n");
return 0;
}
if ((flags & (1 << 7)) != 0) {
if (flags & BQ27000_FLAG_CHGS) {
dev_dbg(di->dev, "negative current!\n");
return -curr;
}
......@@ -174,6 +184,60 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
return rsoc;
}
static int bq27x00_battery_status(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
int flags = 0;
int status;
int ret;
ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
if (ret < 0) {
dev_err(di->dev, "error reading flags\n");
return ret;
}
if (di->chip == BQ27500) {
if (flags & BQ27500_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
else if (flags & BQ27500_FLAG_DSC)
status = POWER_SUPPLY_STATUS_DISCHARGING;
else
status = POWER_SUPPLY_STATUS_CHARGING;
} else {
if (flags & BQ27000_FLAG_CHGS)
status = POWER_SUPPLY_STATUS_CHARGING;
else
status = POWER_SUPPLY_STATUS_DISCHARGING;
}
val->intval = status;
return 0;
}
/*
* Read a time register.
* Return < 0 if something fails.
*/
static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg,
union power_supply_propval *val)
{
int tval = 0;
int ret;
ret = bq27x00_read(reg, &tval, 0, di);
if (ret) {
dev_err(di->dev, "error reading register %02x\n", reg);
return ret;
}
if (tval == 65535)
return -ENODATA;
val->intval = tval * 60;
return 0;
}
#define to_bq27x00_device_info(x) container_of((x), \
struct bq27x00_device_info, bat);
......@@ -181,9 +245,13 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
int ret = 0;
struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
ret = bq27x00_battery_status(di, val);
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
case POWER_SUPPLY_PROP_PRESENT:
val->intval = bq27x00_battery_voltage(di);
......@@ -199,11 +267,20 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_TEMP:
val->intval = bq27x00_battery_temperature(di);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val);
break;
case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val);
break;
default:
return -EINVAL;
}
return 0;
return ret;
}
static void bq27x00_powersupply_init(struct bq27x00_device_info *di)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment