diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-10-29 15:44:47 +0530 |
---|---|---|
committer | Laxman Dewangan <ldewangan@nvidia.com> | 2013-10-30 02:15:46 -0700 |
commit | 36216bbbe04c9ee655ebc42fdc6b327c56853091 (patch) | |
tree | ff9463bd3b2e9f90a47a45852627787a9b482d83 /drivers | |
parent | 428aaa378d086a7906bd69468e2023ac66da092c (diff) |
power: batter-gauge: enhance helper APIs
Add following APIs:
- Add helper function to configure RTC.
- Add the APIs to cancel the auto restart.
- Avoud multiple locking and unlocking of wake_lock
- Register thermal zone only if it is required.
Change-Id: Ic473c25968e87786c948366316527b471ab16d35
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/304806
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/power/battery-charger-gauge-comm.c | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/drivers/power/battery-charger-gauge-comm.c b/drivers/power/battery-charger-gauge-comm.c index c9aed6ff82bc..458390625ae2 100644 --- a/drivers/power/battery-charger-gauge-comm.c +++ b/drivers/power/battery-charger-gauge-comm.c @@ -21,6 +21,7 @@ * 02111-1307, USA */ +#include <linux/alarmtimer.h> #include <linux/module.h> #include <linux/err.h> #include <linux/export.h> @@ -31,7 +32,11 @@ #include <linux/mutex.h> #include <linux/thermal.h> #include <linux/list.h> +#include <linux/rtc.h> +#include <linux/time.h> +#include <linux/timer.h> #include <linux/power/battery-charger-gauge-comm.h> +#include <linux/power/reset/system-pmic.h> #include <linux/wakelock.h> #define JETI_TEMP_COLD 0 @@ -56,6 +61,8 @@ struct battery_charger_dev { struct thermal_zone_device *battery_tz; bool start_monitoring; struct wake_lock charger_wake_lock; + bool locked; + struct rtc_device *rtc; }; struct battery_gauge_dev { @@ -166,14 +173,20 @@ EXPORT_SYMBOL_GPL(battery_charger_thermal_stop_monitoring); int battery_charger_acquire_wake_lock(struct battery_charger_dev *bc_dev) { - wake_lock(&bc_dev->charger_wake_lock); + if (!bc_dev->locked) { + wake_lock(&bc_dev->charger_wake_lock); + bc_dev->locked = true; + } return 0; } EXPORT_SYMBOL_GPL(battery_charger_acquire_wake_lock); int battery_charger_release_wake_lock(struct battery_charger_dev *bc_dev) { - wake_unlock(&bc_dev->charger_wake_lock); + if (bc_dev->locked) { + wake_unlock(&bc_dev->charger_wake_lock); + bc_dev->locked = false; + } return 0; } EXPORT_SYMBOL_GPL(battery_charger_release_wake_lock); @@ -191,6 +204,72 @@ int battery_charging_restart(struct battery_charger_dev *bc_dev, int after_sec) } EXPORT_SYMBOL_GPL(battery_charging_restart); +void battery_charging_restart_cancel(struct battery_charger_dev *bc_dev) +{ + if (!bc_dev->ops->restart_charging) { + dev_err(bc_dev->parent_dev, + "No callback for restart charging\n"); + return; + } + cancel_delayed_work(&bc_dev->restart_charging_wq); +} +EXPORT_SYMBOL_GPL(battery_charging_restart_cancel); + +int battery_charging_wakeup(struct battery_charger_dev *bc_dev, int after_sec) +{ + int ret; + unsigned long now; + struct rtc_wkalrm alm; + int alarm_time = after_sec; + + if (!alarm_time) + return 0; + + bc_dev->rtc = alarmtimer_get_rtcdev(); + if (!bc_dev->rtc) { + dev_err(bc_dev->parent_dev, "No RTC device found\n"); + return -ENODEV; + } + + alm.enabled = true; + ret = rtc_read_time(bc_dev->rtc, &alm.time); + if (ret < 0) { + dev_err(bc_dev->parent_dev, "RTC read time failed %d\n", ret); + return ret; + } + rtc_tm_to_time(&alm.time, &now); + + rtc_time_to_tm(now + alarm_time, &alm.time); + ret = rtc_set_alarm(bc_dev->rtc, &alm); + if (ret < 0) { + dev_err(bc_dev->parent_dev, "RTC set alarm failed %d\n", ret); + alm.enabled = false; + return ret; + } + alm.enabled = false; + return 0; +} +EXPORT_SYMBOL_GPL(battery_charging_wakeup); + +int battery_charging_system_reset_after(struct battery_charger_dev *bc_dev, + int after_sec) +{ + struct system_pmic_rtc_data rtc_data; + int ret; + + dev_info(bc_dev->parent_dev, "Setting system on after %d sec\n", + after_sec); + battery_charging_wakeup(bc_dev, after_sec); + rtc_data.power_on_after_sec = after_sec; + + ret = system_pmic_set_power_on_event(SYSTEM_PMIC_RTC_ALARM, &rtc_data); + if (ret < 0) + dev_err(bc_dev->parent_dev, + "Setting power on event failed: %d\n", ret); + return ret; +} +EXPORT_SYMBOL_GPL(battery_charging_system_reset_after); + struct battery_charger_dev *battery_charger_register(struct device *dev, struct battery_charger_info *bci, void *drv_data) { @@ -218,14 +297,18 @@ struct battery_charger_dev *battery_charger_register(struct device *dev, bc_dev->drv_data = drv_data; /* Thermal monitoring */ - bc_dev->polling_time_sec = bci->polling_time_sec; - strcpy(bc_dev->tz_name, bci->tz_name ? : ""); - bc_dev->battery_tz = thermal_zone_device_find_by_name(bc_dev->tz_name); - if (!bc_dev->battery_tz) - dev_info(dev, "Battery thermal zone %s is not registered yet\n", - bc_dev->tz_name); - INIT_DELAYED_WORK(&bc_dev->poll_temp_monitor_wq, - battery_charger_thermal_monitor_wq); + if (!bc_dev->tz_name) { + bc_dev->polling_time_sec = bci->polling_time_sec; + strcpy(bc_dev->tz_name, bci->tz_name ? : ""); + bc_dev->battery_tz = thermal_zone_device_find_by_name( + bc_dev->tz_name); + if (!bc_dev->battery_tz) + dev_info(dev, + "Battery thermal zone %s is not registered yet\n", + bc_dev->tz_name); + INIT_DELAYED_WORK(&bc_dev->poll_temp_monitor_wq, + battery_charger_thermal_monitor_wq); + } INIT_DELAYED_WORK(&bc_dev->restart_charging_wq, battery_charger_restart_charging_wq); @@ -242,7 +325,8 @@ void battery_charger_unregister(struct battery_charger_dev *bc_dev) { mutex_lock(&charger_gauge_list_mutex); list_del(&bc_dev->list); - cancel_delayed_work(&bc_dev->poll_temp_monitor_wq); + if (bc_dev->polling_time_sec) + cancel_delayed_work(&bc_dev->poll_temp_monitor_wq); cancel_delayed_work(&bc_dev->restart_charging_wq); wake_lock_destroy(&bc_dev->charger_wake_lock); mutex_unlock(&charger_gauge_list_mutex); |