aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/power/charger-manager.txt25
-rw-r--r--drivers/power/charger-manager.c229
-rw-r--r--include/linux/power/charger-manager.h25
3 files changed, 278 insertions, 1 deletions
diff --git a/Documentation/power/charger-manager.txt b/Documentation/power/charger-manager.txt
index fdcca991df30..9b3863386e54 100644
--- a/Documentation/power/charger-manager.txt
+++ b/Documentation/power/charger-manager.txt
@@ -44,6 +44,12 @@ Charger Manager supports the following:
44 Normally, the platform will need to resume and suspend some devices 44 Normally, the platform will need to resume and suspend some devices
45 that are used by Charger Manager. 45 that are used by Charger Manager.
46 46
47* Support for premature full-battery event handling
48 If the battery voltage drops by "fullbatt_vchkdrop_uV" after
49 "fullbatt_vchkdrop_ms" from the full-battery event, the framework
50 restarts charging. This check is also performed while suspended by
51 setting wakeup time accordingly and using suspend_again.
52
472. Global Charger-Manager Data related with suspend_again 532. Global Charger-Manager Data related with suspend_again
48======================================================== 54========================================================
49In order to setup Charger Manager with suspend-again feature 55In order to setup Charger Manager with suspend-again feature
@@ -55,7 +61,7 @@ if there are multiple batteries. If there are multiple batteries, the
55multiple instances of Charger Manager share the same charger_global_desc 61multiple instances of Charger Manager share the same charger_global_desc
56and it will manage in-suspend monitoring for all instances of Charger Manager. 62and it will manage in-suspend monitoring for all instances of Charger Manager.
57 63
58The user needs to provide all the two entries properly in order to activate 64The user needs to provide all the three entries properly in order to activate
59in-suspend monitoring: 65in-suspend monitoring:
60 66
61struct charger_global_desc { 67struct charger_global_desc {
@@ -74,6 +80,11 @@ bool (*rtc_only_wakeup)(void);
74 same struct. If there is any other wakeup source triggered the 80 same struct. If there is any other wakeup source triggered the
75 wakeup, it should return false. If the "rtc" is the only wakeup 81 wakeup, it should return false. If the "rtc" is the only wakeup
76 reason, it should return true. 82 reason, it should return true.
83
84bool assume_timer_stops_in_suspend;
85 : if true, Charger Manager assumes that
86 the timer (CM uses jiffies as timer) stops during suspend. Then, CM
87 assumes that the suspend-duration is same as the alarm length.
77}; 88};
78 89
793. How to setup suspend_again 903. How to setup suspend_again
@@ -111,6 +122,16 @@ enum polling_modes polling_mode;
111 CM_POLL_CHARGING_ONLY: poll this battery if and only if the 122 CM_POLL_CHARGING_ONLY: poll this battery if and only if the
112 battery is being charged. 123 battery is being charged.
113 124
125unsigned int fullbatt_vchkdrop_ms;
126unsigned int fullbatt_vchkdrop_uV;
127 : If both have non-zero values, Charger Manager will check the
128 battery voltage drop fullbatt_vchkdrop_ms after the battery is fully
129 charged. If the voltage drop is over fullbatt_vchkdrop_uV, Charger
130 Manager will try to recharge the battery by disabling and enabling
131 chargers. Recharge with voltage drop condition only (without delay
132 condition) is needed to be implemented with hardware interrupts from
133 fuel gauges or charger devices/chips.
134
114unsigned int fullbatt_uV; 135unsigned int fullbatt_uV;
115 : If specified with a non-zero value, Charger Manager assumes 136 : If specified with a non-zero value, Charger Manager assumes
116 that the battery is full (capacity = 100) if the battery is not being 137 that the battery is full (capacity = 100) if the battery is not being
@@ -122,6 +143,8 @@ unsigned int polling_interval_ms;
122 this battery every polling_interval_ms or more frequently. 143 this battery every polling_interval_ms or more frequently.
123 144
124enum data_source battery_present; 145enum data_source battery_present;
146 : CM_BATTERY_PRESENT: assume that the battery exists.
147 CM_NO_BATTERY: assume that the battery does not exists.
125 CM_FUEL_GAUGE: get battery presence information from fuel gauge. 148 CM_FUEL_GAUGE: get battery presence information from fuel gauge.
126 CM_CHARGER_STAT: get battery presence from chargers. 149 CM_CHARGER_STAT: get battery presence from chargers.
127 150
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 9eca9f1ff0ea..959062d16bac 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -57,6 +57,12 @@ static bool cm_suspended;
57static bool cm_rtc_set; 57static bool cm_rtc_set;
58static unsigned long cm_suspend_duration_ms; 58static unsigned long cm_suspend_duration_ms;
59 59
60/* About normal (not suspended) monitoring */
61static unsigned long polling_jiffy = ULONG_MAX; /* ULONG_MAX: no polling */
62static unsigned long next_polling; /* Next appointed polling time */
63static struct workqueue_struct *cm_wq; /* init at driver add */
64static struct delayed_work cm_monitor_work; /* init at driver add */
65
60/* Global charger-manager description */ 66/* Global charger-manager description */
61static struct charger_global_desc *g_desc; /* init with setup_charger_manager */ 67static struct charger_global_desc *g_desc; /* init with setup_charger_manager */
62 68
@@ -71,6 +77,11 @@ static bool is_batt_present(struct charger_manager *cm)
71 int i, ret; 77 int i, ret;
72 78
73 switch (cm->desc->battery_present) { 79 switch (cm->desc->battery_present) {
80 case CM_BATTERY_PRESENT:
81 present = true;
82 break;
83 case CM_NO_BATTERY:
84 break;
74 case CM_FUEL_GAUGE: 85 case CM_FUEL_GAUGE:
75 ret = cm->fuel_gauge->get_property(cm->fuel_gauge, 86 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
76 POWER_SUPPLY_PROP_PRESENT, &val); 87 POWER_SUPPLY_PROP_PRESENT, &val);
@@ -279,6 +290,26 @@ static int try_charger_enable(struct charger_manager *cm, bool enable)
279} 290}
280 291
281/** 292/**
293 * try_charger_restart - Restart charging.
294 * @cm: the Charger Manager representing the battery.
295 *
296 * Restart charging by turning off and on the charger.
297 */
298static int try_charger_restart(struct charger_manager *cm)
299{
300 int err;
301
302 if (cm->emergency_stop)
303 return -EAGAIN;
304
305 err = try_charger_enable(cm, false);
306 if (err)
307 return err;
308
309 return try_charger_enable(cm, true);
310}
311
312/**
282 * uevent_notify - Let users know something has changed. 313 * uevent_notify - Let users know something has changed.
283 * @cm: the Charger Manager representing the battery. 314 * @cm: the Charger Manager representing the battery.
284 * @event: the event string. 315 * @event: the event string.
@@ -334,6 +365,46 @@ static void uevent_notify(struct charger_manager *cm, const char *event)
334} 365}
335 366
336/** 367/**
368 * fullbatt_vchk - Check voltage drop some times after "FULL" event.
369 * @work: the work_struct appointing the function
370 *
371 * If a user has designated "fullbatt_vchkdrop_ms/uV" values with
372 * charger_desc, Charger Manager checks voltage drop after the battery
373 * "FULL" event. It checks whether the voltage has dropped more than
374 * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
375 */
376static void fullbatt_vchk(struct work_struct *work)
377{
378 struct delayed_work *dwork = to_delayed_work(work);
379 struct charger_manager *cm = container_of(dwork,
380 struct charger_manager, fullbatt_vchk_work);
381 struct charger_desc *desc = cm->desc;
382 int batt_uV, err, diff;
383
384 /* remove the appointment for fullbatt_vchk */
385 cm->fullbatt_vchk_jiffies_at = 0;
386
387 if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
388 return;
389
390 err = get_batt_uV(cm, &batt_uV);
391 if (err) {
392 dev_err(cm->dev, "%s: get_batt_uV error(%d).\n", __func__, err);
393 return;
394 }
395
396 diff = cm->fullbatt_vchk_uV;
397 diff -= batt_uV;
398
399 dev_dbg(cm->dev, "VBATT dropped %duV after full-batt.\n", diff);
400
401 if (diff > desc->fullbatt_vchkdrop_uV) {
402 try_charger_restart(cm);
403 uevent_notify(cm, "Recharge");
404 }
405}
406
407/**
337 * _cm_monitor - Monitor the temperature and return true for exceptions. 408 * _cm_monitor - Monitor the temperature and return true for exceptions.
338 * @cm: the Charger Manager representing the battery. 409 * @cm: the Charger Manager representing the battery.
339 * 410 *
@@ -392,6 +463,68 @@ static bool cm_monitor(void)
392 return stop; 463 return stop;
393} 464}