Skip to content

Commit 433c24e

Browse files
committed
Merge git://git.infradead.org/battery-2.6
* git://git.infradead.org/battery-2.6: power_supply: Add driver for the PMU on WM831x PMICs ds2760_battery: Fix integer overflow for time_to_empty_now wm97xx_battery: Convert to dev_pm_ops wm97xx_battery: Use irq to detect charger state wm97xx_battery: Use platform_data wm97xx-core: Pass platform_data to battery ds2760_battery: implement set_charged() feature power_supply: get_by_name and set_charged functionality power_supply: EXPORT_SYMBOL cleanups ds2760_battery: add current_accum module parameter ds2760_battery: handle full_active_uAh == 0 case correctly ds2760_battery: add rated_capacity module parameter ds2760_battery: export more features ds2760_battery: delay power supply registration wm8350_power: Implement charge type property power_supply: Add a charge_type property, and use it for olpc driver olpc_battery: Add an 'error' sysfs device that displays raw errors Revert "power: remove POWER_SUPPLY_PROP_CAPACITY_LEVEL"
2 parents 85afd82 + f056878 commit 433c24e

File tree

15 files changed

+1331
-66
lines changed

15 files changed

+1331
-66
lines changed

Documentation/power/power_supply_class.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ STATUS - this attribute represents operating status (charging, full,
7676
discharging (i.e. powering a load), etc.). This corresponds to
7777
BATTERY_STATUS_* values, as defined in battery.h.
7878

79+
CHARGE_TYPE - batteries can typically charge at different rates.
80+
This defines trickle and fast charges. For batteries that
81+
are already charged or discharging, 'n/a' can be displayed (or
82+
'unknown', if the status is not known).
83+
7984
HEALTH - represents health of the battery, values corresponds to
8085
POWER_SUPPLY_HEALTH_*, defined in battery.h.
8186

@@ -108,6 +113,8 @@ relative, time-based measurements.
108113
ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
109114

110115
CAPACITY - capacity in percents.
116+
CAPACITY_LEVEL - capacity level. This corresponds to
117+
POWER_SUPPLY_CAPACITY_LEVEL_*.
111118

112119
TEMP - temperature of the power supply.
113120
TEMP_AMBIENT - ambient temperature.

drivers/input/touchscreen/wm97xx-core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev)
561561
static int wm97xx_probe(struct device *dev)
562562
{
563563
struct wm97xx *wm;
564+
struct wm97xx_pdata *pdata = dev->platform_data;
564565
int ret = 0, id = 0;
565566

566567
wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL);
@@ -658,6 +659,7 @@ static int wm97xx_probe(struct device *dev)
658659
}
659660
platform_set_drvdata(wm->battery_dev, wm);
660661
wm->battery_dev->dev.parent = dev;
662+
wm->battery_dev->dev.platform_data = pdata;
661663
ret = platform_device_add(wm->battery_dev);
662664
if (ret < 0)
663665
goto batt_reg_err;
@@ -671,6 +673,7 @@ static int wm97xx_probe(struct device *dev)
671673
}
672674
platform_set_drvdata(wm->touch_dev, wm);
673675
wm->touch_dev->dev.parent = dev;
676+
wm->touch_dev->dev.platform_data = pdata;
674677
ret = platform_device_add(wm->touch_dev);
675678
if (ret < 0)
676679
goto touch_reg_err;

drivers/power/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ config APM_POWER
2929
Say Y here to enable support APM status emulation using
3030
battery class devices.
3131

32+
config WM831X_POWER
33+
tristate "WM831X PMU support"
34+
depends on MFD_WM831X
35+
help
36+
Say Y here to enable support for the power management unit
37+
provided by Wolfson Microelectronics WM831x PMICs.
38+
3239
config WM8350_POWER
3340
tristate "WM8350 PMU support"
3441
depends on MFD_WM8350

drivers/power/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
1616

1717
obj-$(CONFIG_PDA_POWER) += pda_power.o
1818
obj-$(CONFIG_APM_POWER) += apm_power.o
19+
obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
1920
obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
2021

2122
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o

drivers/power/ds2760_battery.c

Lines changed: 122 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct ds2760_device_info {
5656
struct device *w1_dev;
5757
struct workqueue_struct *monitor_wqueue;
5858
struct delayed_work monitor_work;
59+
struct delayed_work set_charged_work;
5960
};
6061

6162
static unsigned int cache_time = 1000;
@@ -66,6 +67,14 @@ static unsigned int pmod_enabled;
6667
module_param(pmod_enabled, bool, 0644);
6768
MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");
6869

70+
static unsigned int rated_capacity;
71+
module_param(rated_capacity, uint, 0644);
72+
MODULE_PARM_DESC(rated_capacity, "rated battery capacity, 10*mAh or index");
73+
74+
static unsigned int current_accum;
75+
module_param(current_accum, uint, 0644);
76+
MODULE_PARM_DESC(current_accum, "current accumulator value");
77+
6978
/* Some batteries have their rated capacity stored a N * 10 mAh, while
7079
* others use an index into this table. */
7180
static int rated_capacities[] = {
@@ -168,8 +177,13 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
168177
di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
169178
di->raw[DS2760_ACTIVE_FULL + 1];
170179

171-
scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
172-
di->raw[DS2760_ACTIVE_FULL + 1];
180+
/* If the full_active_uAh value is not given, fall back to the rated
181+
* capacity. This is likely to happen when chips are not part of the
182+
* battery pack and is therefore not bootstrapped. */
183+
if (di->full_active_uAh == 0)
184+
di->full_active_uAh = di->rated_capacity / 1000L;
185+
186+
scale[0] = di->full_active_uAh;
173187
for (i = 1; i < 5; i++)
174188
scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
175189

@@ -197,15 +211,31 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
197211
if (di->rem_capacity > 100)
198212
di->rem_capacity = 100;
199213

200-
if (di->current_uA)
201-
di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
202-
3600L) / di->current_uA;
214+
if (di->current_uA >= 100L)
215+
di->life_sec = -((di->accum_current_uAh - di->empty_uAh) * 36L)
216+
/ (di->current_uA / 100L);
203217
else
204218
di->life_sec = 0;
205219

206220
return 0;
207221
}
208222

223+
static void ds2760_battery_set_current_accum(struct ds2760_device_info *di,
224+
unsigned int acr_val)
225+
{
226+
unsigned char acr[2];
227+
228+
/* acr is in units of 0.25 mAh */
229+
acr_val *= 4L;
230+
acr_val /= 1000;
231+
232+
acr[0] = acr_val >> 8;
233+
acr[1] = acr_val & 0xff;
234+
235+
if (w1_ds2760_write(di->w1_dev, acr, DS2760_CURRENT_ACCUM_MSB, 2) < 2)
236+
dev_warn(di->dev, "ACR write failed\n");
237+
}
238+
209239
static void ds2760_battery_update_status(struct ds2760_device_info *di)
210240
{
211241
int old_charge_status = di->charge_status;
@@ -237,21 +267,9 @@ static void ds2760_battery_update_status(struct ds2760_device_info *di)
237267
if (di->full_counter < 2) {
238268
di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
239269
} else {
240-
unsigned char acr[2];
241-
int acr_val;
242-
243-
/* acr is in units of 0.25 mAh */
244-
acr_val = di->full_active_uAh * 4L / 1000;
245-
246-
acr[0] = acr_val >> 8;
247-
acr[1] = acr_val & 0xff;
248-
249-
if (w1_ds2760_write(di->w1_dev, acr,
250-
DS2760_CURRENT_ACCUM_MSB, 2) < 2)
251-
dev_warn(di->dev,
252-
"ACR reset failed\n");
253-
254270
di->charge_status = POWER_SUPPLY_STATUS_FULL;
271+
ds2760_battery_set_current_accum(di,
272+
di->full_active_uAh);
255273
}
256274
}
257275
} else {
@@ -274,6 +292,17 @@ static void ds2760_battery_write_status(struct ds2760_device_info *di,
274292
w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
275293
}
276294

295+
static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,
296+
unsigned char rated_capacity)
297+
{
298+
if (rated_capacity == di->raw[DS2760_RATED_CAPACITY])
299+
return;
300+
301+
w1_ds2760_write(di->w1_dev, &rated_capacity, DS2760_RATED_CAPACITY, 1);
302+
w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
303+
w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
304+
}
305+
277306
static void ds2760_battery_work(struct work_struct *work)
278307
{
279308
struct ds2760_device_info *di = container_of(work,
@@ -299,6 +328,52 @@ static void ds2760_battery_external_power_changed(struct power_supply *psy)
299328
queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
300329
}
301330

331+
332+
static void ds2760_battery_set_charged_work(struct work_struct *work)
333+
{
334+
char bias;
335+
struct ds2760_device_info *di = container_of(work,
336+
struct ds2760_device_info, set_charged_work.work);
337+
338+
dev_dbg(di->dev, "%s\n", __func__);
339+
340+
ds2760_battery_read_status(di);
341+
342+
/* When we get notified by external circuitry that the battery is
343+
* considered fully charged now, we know that there is no current
344+
* flow any more. However, the ds2760's internal current meter is
345+
* too inaccurate to rely on - spec say something ~15% failure.
346+
* Hence, we use the current offset bias register to compensate
347+
* that error.
348+
*/
349+
350+
if (!power_supply_am_i_supplied(&di->bat))
351+
return;
352+
353+
bias = (signed char) di->current_raw +
354+
(signed char) di->raw[DS2760_CURRENT_OFFSET_BIAS];
355+
356+
dev_dbg(di->dev, "%s: bias = %d\n", __func__, bias);
357+
358+
w1_ds2760_write(di->w1_dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);
359+
w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
360+
w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
361+
362+
/* Write to the di->raw[] buffer directly - the CURRENT_OFFSET_BIAS
363+
* value won't be read back by ds2760_battery_read_status() */
364+
di->raw[DS2760_CURRENT_OFFSET_BIAS] = bias;
365+
}
366+
367+
static void ds2760_battery_set_charged(struct power_supply *psy)
368+
{
369+
struct ds2760_device_info *di = to_ds2760_device_info(psy);
370+
371+
/* postpone the actual work by 20 secs. This is for debouncing GPIO
372+
* signals and to let the current value settle. See AN4188. */
373+
cancel_delayed_work(&di->set_charged_work);
374+
queue_delayed_work(di->monitor_wqueue, &di->set_charged_work, HZ * 20);
375+
}
376+
302377
static int ds2760_battery_get_property(struct power_supply *psy,
303378
enum power_supply_property psp,
304379
union power_supply_propval *val)
@@ -337,6 +412,12 @@ static int ds2760_battery_get_property(struct power_supply *psy,
337412
case POWER_SUPPLY_PROP_TEMP:
338413
val->intval = di->temp_C;
339414
break;
415+
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
416+
val->intval = di->life_sec;
417+
break;
418+
case POWER_SUPPLY_PROP_CAPACITY:
419+
val->intval = di->rem_capacity;
420+
break;
340421
default:
341422
return -EINVAL;
342423
}
@@ -353,6 +434,8 @@ static enum power_supply_property ds2760_battery_props[] = {
353434
POWER_SUPPLY_PROP_CHARGE_EMPTY,
354435
POWER_SUPPLY_PROP_CHARGE_NOW,
355436
POWER_SUPPLY_PROP_TEMP,
437+
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
438+
POWER_SUPPLY_PROP_CAPACITY,
356439
};
357440

358441
static int ds2760_battery_probe(struct platform_device *pdev)
@@ -376,17 +459,12 @@ static int ds2760_battery_probe(struct platform_device *pdev)
376459
di->bat.properties = ds2760_battery_props;
377460
di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
378461
di->bat.get_property = ds2760_battery_get_property;
462+
di->bat.set_charged = ds2760_battery_set_charged;
379463
di->bat.external_power_changed =
380464
ds2760_battery_external_power_changed;
381465

382466
di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
383467

384-
retval = power_supply_register(&pdev->dev, &di->bat);
385-
if (retval) {
386-
dev_err(di->dev, "failed to register battery\n");
387-
goto batt_failed;
388-
}
389-
390468
/* enable sleep mode feature */
391469
ds2760_battery_read_status(di);
392470
status = di->raw[DS2760_STATUS_REG];
@@ -397,7 +475,24 @@ static int ds2760_battery_probe(struct platform_device *pdev)
397475

398476
ds2760_battery_write_status(di, status);
399477

478+
/* set rated capacity from module param */
479+
if (rated_capacity)
480+
ds2760_battery_write_rated_capacity(di, rated_capacity);
481+
482+
/* set current accumulator if given as parameter.
483+
* this should only be done for bootstrapping the value */
484+
if (current_accum)
485+
ds2760_battery_set_current_accum(di, current_accum);
486+
487+
retval = power_supply_register(&pdev->dev, &di->bat);
488+
if (retval) {
489+
dev_err(di->dev, "failed to register battery\n");
490+
goto batt_failed;
491+
}
492+
400493
INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
494+
INIT_DELAYED_WORK(&di->set_charged_work,
495+
ds2760_battery_set_charged_work);
401496
di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
402497
if (!di->monitor_wqueue) {
403498
retval = -ESRCH;
@@ -422,6 +517,8 @@ static int ds2760_battery_remove(struct platform_device *pdev)
422517

423518
cancel_rearming_delayed_workqueue(di->monitor_wqueue,
424519
&di->monitor_work);
520+
cancel_rearming_delayed_workqueue(di->monitor_wqueue,
521+
&di->set_charged_work);
425522
destroy_workqueue(di->monitor_wqueue);
426523
power_supply_unregister(&di->bat);
427524

0 commit comments

Comments
 (0)