aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/bq20z75.c98
-rw-r--r--include/linux/power_supply.h44
2 files changed, 131 insertions, 11 deletions
diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c
index 492da27e1a47..4141775e5ff6 100644
--- a/drivers/power/bq20z75.c
+++ b/drivers/power/bq20z75.c
@@ -38,11 +38,22 @@ enum {
38 REG_CYCLE_COUNT, 38 REG_CYCLE_COUNT,
39 REG_SERIAL_NUMBER, 39 REG_SERIAL_NUMBER,
40 REG_REMAINING_CAPACITY, 40 REG_REMAINING_CAPACITY,
41 REG_REMAINING_CAPACITY_CHARGE,
41 REG_FULL_CHARGE_CAPACITY, 42 REG_FULL_CHARGE_CAPACITY,
43 REG_FULL_CHARGE_CAPACITY_CHARGE,
42 REG_DESIGN_CAPACITY, 44 REG_DESIGN_CAPACITY,
45 REG_DESIGN_CAPACITY_CHARGE,
43 REG_DESIGN_VOLTAGE, 46 REG_DESIGN_VOLTAGE,
44}; 47};
45 48
49/* Battery Mode defines */
50#define BATTERY_MODE_OFFSET 0x03
51#define BATTERY_MODE_MASK 0x8000
52enum bq20z75_battery_mode {
53 BATTERY_MODE_AMPS,
54 BATTERY_MODE_WATTS
55};
56
46/* manufacturer access defines */ 57/* manufacturer access defines */
47#define MANUFACTURER_ACCESS_STATUS 0x0006 58#define MANUFACTURER_ACCESS_STATUS 0x0006
48#define MANUFACTURER_ACCESS_SLEEP 0x0011 59#define MANUFACTURER_ACCESS_SLEEP 0x0011
@@ -78,8 +89,12 @@ static const struct bq20z75_device_data {
78 BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100), 89 BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
79 [REG_REMAINING_CAPACITY] = 90 [REG_REMAINING_CAPACITY] =
80 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535), 91 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
92 [REG_REMAINING_CAPACITY_CHARGE] =
93 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
81 [REG_FULL_CHARGE_CAPACITY] = 94 [REG_FULL_CHARGE_CAPACITY] =
82 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535), 95 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
96 [REG_FULL_CHARGE_CAPACITY_CHARGE] =
97 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
83 [REG_TIME_TO_EMPTY] = 98 [REG_TIME_TO_EMPTY] =
84 BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 99 BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
85 65535), 100 65535),
@@ -93,6 +108,9 @@ static const struct bq20z75_device_data {
93 [REG_DESIGN_CAPACITY] = 108 [REG_DESIGN_CAPACITY] =
94 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 109 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
95 65535), 110 65535),
111 [REG_DESIGN_CAPACITY_CHARGE] =
112 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0,
113 65535),
96 [REG_DESIGN_VOLTAGE] = 114 [REG_DESIGN_VOLTAGE] =
97 BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 115 BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
98 65535), 116 65535),
@@ -117,6 +135,9 @@ static enum power_supply_property bq20z75_properties[] = {
117 POWER_SUPPLY_PROP_ENERGY_NOW, 135 POWER_SUPPLY_PROP_ENERGY_NOW,
118 POWER_SUPPLY_PROP_ENERGY_FULL, 136 POWER_SUPPLY_PROP_ENERGY_FULL,
119 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 137 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
138 POWER_SUPPLY_PROP_CHARGE_NOW,
139 POWER_SUPPLY_PROP_CHARGE_FULL,
140 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
120}; 141};
121 142
122struct bq20z75_info { 143struct bq20z75_info {
@@ -260,6 +281,9 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
260 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 281 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
261 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 282 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
262 case POWER_SUPPLY_PROP_CURRENT_NOW: 283 case POWER_SUPPLY_PROP_CURRENT_NOW:
284 case POWER_SUPPLY_PROP_CHARGE_NOW:
285 case POWER_SUPPLY_PROP_CHARGE_FULL:
286 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
263 val->intval *= BASE_UNIT_CONVERSION; 287 val->intval *= BASE_UNIT_CONVERSION;
264 break; 288 break;
265 289
@@ -281,11 +305,44 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
281 } 305 }
282} 306}
283 307
308static enum bq20z75_battery_mode
309bq20z75_set_battery_mode(struct i2c_client *client,
310 enum bq20z75_battery_mode mode)
311{
312 int ret, original_val;
313
314 original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET);
315 if (original_val < 0)
316 return original_val;
317
318 if ((original_val & BATTERY_MODE_MASK) == mode)
319 return mode;
320
321 if (mode == BATTERY_MODE_AMPS)
322 ret = original_val & ~BATTERY_MODE_MASK;
323 else
324 ret = original_val | BATTERY_MODE_MASK;
325
326 ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret);
327 if (ret < 0)
328 return ret;
329
330 return original_val & BATTERY_MODE_MASK;
331}
332
284static int bq20z75_get_battery_capacity(struct i2c_client *client, 333static int bq20z75_get_battery_capacity(struct i2c_client *client,
285 int reg_offset, enum power_supply_property psp, 334 int reg_offset, enum power_supply_property psp,
286 union power_supply_propval *val) 335 union power_supply_propval *val)
287{ 336{
288 s32 ret; 337 s32 ret;
338 enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS;
339
340 if (power_supply_is_amp_property(psp))
341 mode = BATTERY_MODE_AMPS;
342
343 mode = bq20z75_set_battery_mode(client, mode);
344 if (mode < 0)
345 return mode;
289 346
290 ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr); 347 ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
291 if (ret < 0) 348 if (ret < 0)
@@ -298,6 +355,10 @@ static int bq20z75_get_battery_capacity(struct i2c_client *client,
298 } else 355 } else
299 val->intval = ret; 356 val->intval = ret;
300 357
358 ret = bq20z75_set_battery_mode(client, mode);
359 if (ret < 0)
360 return ret;
361
301 return 0; 362 return 0;
302} 363}
303 364
@@ -318,11 +379,25 @@ static int bq20z75_get_battery_serial_number(struct i2c_client *client,
318 return 0; 379 return 0;
319} 380}
320 381
382static int bq20z75_get_property_index(struct i2c_client *client,
383 enum power_supply_property psp)
384{
385 int count;
386 for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++)
387 if (psp == bq20z75_data[count].psp)
388 return count;
389
390 dev_warn(&client->dev,
391 "%s: Invalid Property - %d\n", __func__, psp);
392
393 return -EINVAL;
394}
395
321static int bq20z75_get_property(struct power_supply *psy, 396static int bq20z75_get_property(struct power_supply *psy,
322 enum power_supply_property psp, 397 enum power_supply_property psp,
323 union power_supply_propval *val) 398 union power_supply_propval *val)
324{ 399{
325 int count; 400 int ps_index;
326 int ret; 401 int ret;
327 struct bq20z75_info *bq20z75_device = container_of(psy, 402 struct bq20z75_info *bq20z75_device = container_of(psy,
328 struct bq20z75_info, power_supply); 403 struct bq20z75_info, power_supply);
@@ -343,13 +418,15 @@ static int bq20z75_get_property(struct power_supply *psy,
343 case POWER_SUPPLY_PROP_ENERGY_NOW: 418 case POWER_SUPPLY_PROP_ENERGY_NOW:
344 case POWER_SUPPLY_PROP_ENERGY_FULL: 419 case POWER_SUPPLY_PROP_ENERGY_FULL:
345 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 420 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
421 case POWER_SUPPLY_PROP_CHARGE_NOW:
422 case POWER_SUPPLY_PROP_CHARGE_FULL:
423 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
346 case POWER_SUPPLY_PROP_CAPACITY: 424 case POWER_SUPPLY_PROP_CAPACITY:
347 for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) { 425 ps_index = bq20z75_get_property_index(client, psp);
348 if (psp == bq20z75_data[count].psp) 426 if (ps_index < 0)
349 break; 427 return ps_index;
350 }
351 428
352 ret = bq20z75_get_battery_capacity(client, count, psp, val); 429 ret = bq20z75_get_battery_capacity(client, ps_index, psp, val);
353 if (ret) 430 if (ret)
354 return ret; 431 return ret;
355 432
@@ -369,12 +446,11 @@ static int bq20z75_get_property(struct power_supply *psy,
369 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 446 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
370 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 447 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
371 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 448 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
372 for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) { 449 ps_index = bq20z75_get_property_index(client, psp);
373 if (psp == bq20z75_data[count].psp) 450 if (ps_index < 0)
374 break; 451 return ps_index;
375 }
376 452
377 ret = bq20z75_get_battery_property(client, count, psp, val); 453 ret = bq20z75_get_battery_property(client, ps_index, psp, val);
378 if (ret) 454 if (ret)
379 return ret; 455 return ret;
380 456
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 7d7325685c42..e3419fc5541e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -213,4 +213,48 @@ extern void power_supply_unregister(struct power_supply *psy);
213/* For APM emulation, think legacy userspace. */ 213/* For APM emulation, think legacy userspace. */
214extern struct class *power_supply_class; 214extern struct class *power_supply_class;
215 215
216static inline bool power_supply_is_amp_property(enum power_supply_property psp)
217{
218 switch (psp) {
219 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
220 case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
221 case POWER_SUPPLY_PROP_CHARGE_FULL:
222 case POWER_SUPPLY_PROP_CHARGE_EMPTY:
223 case POWER_SUPPLY_PROP_CHARGE_NOW:
224 case POWER_SUPPLY_PROP_CHARGE_AVG:
225 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
226 case POWER_SUPPLY_PROP_CURRENT_MAX:
227 case POWER_SUPPLY_PROP_CURRENT_NOW:
228 case POWER_SUPPLY_PROP_CURRENT_AVG:
229 return 1;
230 default:
231 break;
232 }
233
234 return 0;
235}
236
237static inline bool power_supply_is_watt_property(enum power_supply_property psp)
238{
239 switch (psp) {
240 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
241 case POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN:
242 case POWER_SUPPLY_PROP_ENERGY_FULL:
243 case POWER_SUPPLY_PROP_ENERGY_EMPTY:
244 case POWER_SUPPLY_PROP_ENERGY_NOW:
245 case POWER_SUPPLY_PROP_ENERGY_AVG:
246 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
247 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
248 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
249 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
250 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
251 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
252 return 1;
253 default:
254 break;
255 }
256
257 return 0;
258}
259
216#endif /* __LINUX_POWER_SUPPLY_H__ */ 260#endif /* __LINUX_POWER_SUPPLY_H__ */