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: Grazvydas Ignotas <notasas@gmail.com> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
This commit is contained in:
parent
e20908d95e
commit
4e924a814a
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue