diff options
| -rw-r--r-- | Documentation/power/charger-manager.txt | 25 | ||||
| -rw-r--r-- | drivers/power/charger-manager.c | 229 | ||||
| -rw-r--r-- | include/linux/power/charger-manager.h | 25 |
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 | |||
| 47 | 2. Global Charger-Manager Data related with suspend_again | 53 | 2. Global Charger-Manager Data related with suspend_again |
| 48 | ======================================================== | 54 | ======================================================== |
| 49 | In order to setup Charger Manager with suspend-again feature | 55 | In order to setup Charger Manager with suspend-again feature |
| @@ -55,7 +61,7 @@ if there are multiple batteries. If there are multiple batteries, the | |||
| 55 | multiple instances of Charger Manager share the same charger_global_desc | 61 | multiple instances of Charger Manager share the same charger_global_desc |
| 56 | and it will manage in-suspend monitoring for all instances of Charger Manager. | 62 | and it will manage in-suspend monitoring for all instances of Charger Manager. |
| 57 | 63 | ||
| 58 | The user needs to provide all the two entries properly in order to activate | 64 | The user needs to provide all the three entries properly in order to activate |
| 59 | in-suspend monitoring: | 65 | in-suspend monitoring: |
| 60 | 66 | ||
| 61 | struct charger_global_desc { | 67 | struct 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 | |||
| 84 | bool 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 | ||
| 79 | 3. How to setup suspend_again | 90 | 3. 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 | ||
| 125 | unsigned int fullbatt_vchkdrop_ms; | ||
| 126 | unsigned 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 | |||
| 114 | unsigned int fullbatt_uV; | 135 | unsigned 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 | ||
| 124 | enum data_source battery_present; | 145 | enum 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; | |||
| 57 | static bool cm_rtc_set; | 57 | static bool cm_rtc_set; |
| 58 | static unsigned long cm_suspend_duration_ms; | 58 | static unsigned long cm_suspend_duration_ms; |
| 59 | 59 | ||
| 60 | /* About normal (not suspended) monitoring */ | ||
| 61 | static unsigned long polling_jiffy = ULONG_MAX; /* ULONG_MAX: no polling */ | ||
| 62 | static unsigned long next_polling; /* Next appointed polling time */ | ||
| 63 | static struct workqueue_struct *cm_wq; /* init at driver add */ | ||
| 64 | static struct delayed_work cm_monitor_work; /* init at driver add */ | ||
| 65 | |||
| 60 | /* Global charger-manager description */ | 66 | /* Global charger-manager description */ |
| 61 | static struct charger_global_desc *g_desc; /* init with setup_charger_manager */ | 67 | static 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 | */ | ||
| 298 | static 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 | */ | ||
| 376 | static 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 | } |
