diff options
| -rw-r--r-- | drivers/power/bq27x00_battery.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 1526d020cbc6..5d940fad8d43 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
| @@ -32,10 +32,16 @@ | |||
| 32 | #define BQ27x00_REG_VOLT 0x08 | 32 | #define BQ27x00_REG_VOLT 0x08 |
| 33 | #define BQ27x00_REG_AI 0x14 | 33 | #define BQ27x00_REG_AI 0x14 |
| 34 | #define BQ27x00_REG_FLAGS 0x0A | 34 | #define BQ27x00_REG_FLAGS 0x0A |
| 35 | #define BQ27x00_REG_TTE 0x16 | ||
| 36 | #define BQ27x00_REG_TTF 0x18 | ||
| 37 | #define BQ27x00_REG_TTECP 0x26 | ||
| 35 | 38 | ||
| 36 | #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ | 39 | #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ |
| 40 | #define BQ27000_FLAG_CHGS BIT(7) | ||
| 37 | 41 | ||
| 38 | #define BQ27500_REG_SOC 0x2c | 42 | #define BQ27500_REG_SOC 0x2c |
| 43 | #define BQ27500_FLAG_DSC BIT(0) | ||
| 44 | #define BQ27500_FLAG_FC BIT(9) | ||
| 39 | 45 | ||
| 40 | /* If the system has several batteries we need a different name for each | 46 | /* If the system has several batteries we need a different name for each |
| 41 | * of them... | 47 | * of them... |
| @@ -62,11 +68,15 @@ struct bq27x00_device_info { | |||
| 62 | }; | 68 | }; |
| 63 | 69 | ||
| 64 | static enum power_supply_property bq27x00_battery_props[] = { | 70 | static enum power_supply_property bq27x00_battery_props[] = { |
| 71 | POWER_SUPPLY_PROP_STATUS, | ||
| 65 | POWER_SUPPLY_PROP_PRESENT, | 72 | POWER_SUPPLY_PROP_PRESENT, |
| 66 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 73 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
| 67 | POWER_SUPPLY_PROP_CURRENT_NOW, | 74 | POWER_SUPPLY_PROP_CURRENT_NOW, |
| 68 | POWER_SUPPLY_PROP_CAPACITY, | 75 | POWER_SUPPLY_PROP_CAPACITY, |
| 69 | POWER_SUPPLY_PROP_TEMP, | 76 | POWER_SUPPLY_PROP_TEMP, |
| 77 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
| 78 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | ||
| 79 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, | ||
| 70 | }; | 80 | }; |
| 71 | 81 | ||
| 72 | /* | 82 | /* |
| @@ -144,7 +154,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di) | |||
| 144 | dev_err(di->dev, "error reading flags\n"); | 154 | dev_err(di->dev, "error reading flags\n"); |
| 145 | return 0; | 155 | return 0; |
| 146 | } | 156 | } |
| 147 | if ((flags & (1 << 7)) != 0) { | 157 | if (flags & BQ27000_FLAG_CHGS) { |
| 148 | dev_dbg(di->dev, "negative current!\n"); | 158 | dev_dbg(di->dev, "negative current!\n"); |
| 149 | return -curr; | 159 | return -curr; |
| 150 | } | 160 | } |
| @@ -174,6 +184,60 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di) | |||
| 174 | return rsoc; | 184 | return rsoc; |
| 175 | } | 185 | } |
| 176 | 186 | ||
| 187 | static int bq27x00_battery_status(struct bq27x00_device_info *di, | ||
| 188 | union power_supply_propval *val) | ||
| 189 | { | ||
| 190 | int flags = 0; | ||
| 191 | int status; | ||
| 192 | int ret; | ||
| 193 | |||
| 194 | ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di); | ||
| 195 | if (ret < 0) { | ||
| 196 | dev_err(di->dev, "error reading flags\n"); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (di->chip == BQ27500) { | ||
| 201 | if (flags & BQ27500_FLAG_FC) | ||
| 202 | status = POWER_SUPPLY_STATUS_FULL; | ||
| 203 | else if (flags & BQ27500_FLAG_DSC) | ||
| 204 | status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
| 205 | else | ||
| 206 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
| 207 | } else { | ||
| 208 | if (flags & BQ27000_FLAG_CHGS) | ||
| 209 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
| 210 | else | ||
| 211 | status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
| 212 | } | ||
| 213 | |||
| 214 | val->intval = status; | ||
| 215 | return 0; | ||
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * Read a time register. | ||
| 220 | * Return < 0 if something fails. | ||
| 221 | */ | ||
| 222 | static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg, | ||
| 223 | union power_supply_propval *val) | ||
| 224 | { | ||
| 225 | int tval = 0; | ||
| 226 | int ret; | ||
| 227 | |||
| 228 | ret = bq27x00_read(reg, &tval, 0, di); | ||
| 229 | if (ret) { | ||
| 230 | dev_err(di->dev, "error reading register %02x\n", reg); | ||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (tval == 65535) | ||
| 235 | return -ENODATA; | ||
| 236 | |||
| 237 | val->intval = tval * 60; | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 177 | #define to_bq27x00_device_info(x) container_of((x), \ | 241 | #define to_bq27x00_device_info(x) container_of((x), \ |
| 178 | struct bq27x00_device_info, bat); | 242 | struct bq27x00_device_info, bat); |
| 179 | 243 | ||
| @@ -181,9 +245,13 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
| 181 | enum power_supply_property psp, | 245 | enum power_supply_property psp, |
| 182 | union power_supply_propval *val) | 246 | union power_supply_propval *val) |
| 183 | { | 247 | { |
| 248 | int ret = 0; | ||
| 184 | struct bq27x00_device_info *di = to_bq27x00_device_info(psy); | 249 | struct bq27x00_device_info *di = to_bq27x00_device_info(psy); |
| 185 | 250 | ||
| 186 | switch (psp) { | 251 | switch (psp) { |
| 252 | case POWER_SUPPLY_PROP_STATUS: | ||
| 253 | ret = bq27x00_battery_status(di, val); | ||
| 254 | break; | ||
| 187 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 255 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
| 188 | case POWER_SUPPLY_PROP_PRESENT: | 256 | case POWER_SUPPLY_PROP_PRESENT: |
| 189 | val->intval = bq27x00_battery_voltage(di); | 257 | val->intval = bq27x00_battery_voltage(di); |
| @@ -199,11 +267,20 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
| 199 | case POWER_SUPPLY_PROP_TEMP: | 267 | case POWER_SUPPLY_PROP_TEMP: |
| 200 | val->intval = bq27x00_battery_temperature(di); | 268 | val->intval = bq27x00_battery_temperature(di); |
| 201 | break; | 269 | break; |
| 270 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: | ||
| 271 | ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val); | ||
| 272 | break; | ||
| 273 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | ||
| 274 | ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val); | ||
| 275 | break; | ||
| 276 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: | ||
| 277 | ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val); | ||
| 278 | break; | ||
| 202 | default: | 279 | default: |
| 203 | return -EINVAL; | 280 | return -EINVAL; |
| 204 | } | 281 | } |
| 205 | 282 | ||
| 206 | return 0; | 283 | return ret; |
| 207 | } | 284 | } |
| 208 | 285 | ||
| 209 | static void bq27x00_powersupply_init(struct bq27x00_device_info *di) | 286 | static void bq27x00_powersupply_init(struct bq27x00_device_info *di) |
