summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Wilson <evan@oliodevices.com>2016-01-20 21:35:37 +0000
committerGerrit Code Review <gerrit2@ip-172-31-25-77.us-west-1.compute.internal>2015-04-16 10:08:13 +0000
commit7bdf9fd7e2337b3d75bfa1d1d7a5b1372d50fc04 (patch)
tree0137b4403f3f0565c26f1b0fcfa5856bca75714c
parent058e418668659a82ae277b05dc1fc1a546aa3bc8 (diff)
parent42bdc122eed6e3748d55574e8f57ca3907b81767 (diff)
downloadolio-linux-3.10-7bdf9fd7e2337b3d75bfa1d1d7a5b1372d50fc04.tar.xz
olio-linux-3.10-7bdf9fd7e2337b3d75bfa1d1d7a5b1372d50fc04.zip
Merge "Adding alarm timer based polling while on the charger. Basically, when the charger interrupts are off, the rtc polling is on." into android-3.10-bringup
-rw-r--r--drivers/power/bq27x00_battery.c144
1 files changed, 53 insertions, 91 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 5835bc881cd..8002531960e 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -56,7 +56,7 @@
* In hindsight, a lot of this can probably be moved to the charger
* manager.
*/
-
+#include <linux/alarmtimer.h>
#include "asm/io.h"
#include "../../arch/arm/mach-omap2/mux.h"
#include "../../arch/arm/mach-omap2/iomap.h"
@@ -279,6 +279,8 @@ static __initdata u8 bq276xx_regs[NUM_REGS] = {
#define BQ276XX_OP_CFG_B_OFFSET 2
#define BQ276XX_OP_CFG_B_DEF_SEAL_BIT (1 << 5)
+#define BQ27X00_ALARM_TIMER_INTERVAL 300 /* 5 minutes */
+
struct bq27x00_device_info;
struct bq27x00_access_methods {
int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
@@ -337,6 +339,9 @@ struct bq27x00_device_info {
u8 regs[NUM_REGS];
struct dm_reg *dm_regs;
u16 dm_regs_count;
+
+ struct alarm poll_alarm;
+ ktime_t alarm_time;
};
static __initdata enum power_supply_property bq27x00_battery_props[] = {
@@ -431,8 +436,7 @@ static __initdata enum power_supply_property bq276xx_battery_props[] = {
* Customize these values and, if necessary, add more based on system needs.
To be added, maybe (for bq274xx):
- {81, 9, 1, 3}, /* Quit Relax Time (3s) */
-
+ {81, 9, 1, 3}, Quit Relax Time (3s)
*/
static struct dm_reg bq274xx_dm_regs[] = {
{36, 6, 1, 90}, /* FC Clear % */
@@ -1142,7 +1146,7 @@ static void rom_mode_gauge_dm_init(struct bq27x00_device_info *di)
subclass = dm_reg->subclass;
offset = dm_reg->offset;
- printk ("%s OLIO updating reg %d, offset %d\n", __FUNCTION__,
+ olio_debug ("updating reg %d, offset %d\n",
subclass, offset);
/*
@@ -1178,76 +1182,6 @@ static void rom_mode_gauge_dm_init(struct bq27x00_device_info *di)
exit_cfg_update_mode(di);
}
-/***************************************************************************
- * bq27x00_should_wakeup - decide whether to sleep or wake
- *
- * All I need is the power level last time we had an interrupt. If it isn't
- * at least 2% from last time, go back to sleep.
- *
- * OK, that's not good enough. It needs to detect whether we're on or off
- * the charger as well - use the status inquiry for that.
- *
- * I need to make a wrapper function around battery_poll that can be
- * invoked when we're coming from an interrupt. That, or a global variable.
- * Some way to only do this test when it's actually relevant.
- */
-
-
-static bool bq27x00_should_wakeup(struct bq27x00_device_info *di) {
-
- static int previous_charge = 0; /* initial value */
- static int status_previous = 0;
- int charge_diff;
- int soc;
- union power_supply_propval val;
-
- int status;
-
- printk ("%s OLIO entered\n", __FUNCTION__);
-
- /* check if power change is big enough for us to
- * wake up to.
- */
-
- if ((soc = bq27x00_battery_read_soc(di)) < 0)
- return false; /* error */
-
- charge_diff = abs (soc - previous_charge);
-
- printk ("%s OLIO found diff %d\n", __FUNCTION__, charge_diff);
-
- if (charge_diff >= 5) {
- previous_charge = soc;
- printk ("exiting, true\n");
- return true;
- }
-
- /* else check the status. This should turn off interrupts if
- * it wasn't done before.
- */
-
- status = bq27x00_battery_status(di, &val);
-
- /* we ignore unknown statuses - it's probably just the ts81001
- * that hasn't woken up yet
- */
-
- if (status != POWER_SUPPLY_STATUS_UNKNOWN &&
- status != status_previous) { /* something has changed! */
- printk ("%s OLIO state changed (old = %d, new = %d, "
- "wake up!\n", __FUNCTION__, status_previous,
- status);
- status_previous = status;
- return true;
- } else {
- printk ("%s OLIO old state = %d, new state = %d, sleep\n",
- __FUNCTION__, status_previous, status);
- }
-
- printk ("exiting, false\n");
-
- return false;
-}
/***************************************************************************
* bq27x00_battery_interrupt - work to do from interrupt
@@ -1263,17 +1197,13 @@ static void bq27x00_battery_interrupt (struct work_struct *i_work)
struct bq27x00_device_info *di =
container_of(i_work, struct bq27x00_device_info, interrupt_work.work);
- printk ("%s OLIO taking charge wake lock\n", __FUNCTION__);
+ olio_debug ("taking charge wake lock\n");
wake_lock_timeout(&chg_wake_lock, msecs_to_jiffies(500));
bq27x00_update (di);
status = bq27x00_battery_status(di, &val);
-#if 0
- if (bq27x00_should_wakeup(di)) {
- }
-#endif
- printk ("%s OLIO battery status = %d\n", __FUNCTION__, status);
+ olio_debug ("battery status = %d\n", status);
/* release the low-level wake lock (taken in isr handler) */
wake_unlock (&isr_wake_lock);
@@ -1285,6 +1215,8 @@ static void bq27x00_battery_poll(struct work_struct *p_work)
struct bq27x00_device_info *di =
container_of(p_work, struct bq27x00_device_info, work.work);
+ olio_debug ("entered\n");
+
if (((di->chip == BQ274XX) || (di->chip == BQ276XX)) &&
!rom_mode_gauge_dm_initialized(di)) {
rom_mode_gauge_dm_init(di);
@@ -1299,6 +1231,26 @@ static void bq27x00_battery_poll(struct work_struct *p_work)
}
}
+static enum alarmtimer_restart
+bq27x00_run_poll_alarm(struct alarm * p_alarm, ktime_t now)
+{
+ struct bq27x00_device_info *di =
+ container_of(p_alarm, struct bq27x00_device_info, poll_alarm);
+
+ olio_debug ("entered\n");
+
+ wake_lock_timeout(&chg_wake_lock, msecs_to_jiffies(500));
+
+ cancel_delayed_work(&di->work);
+ schedule_delayed_work(&di->work, 5);
+
+ /* reschedule manually, since restart doesn't seem to do what we want. */
+
+ alarm_start_relative (&di->poll_alarm, di->alarm_time);
+
+ return ALARMTIMER_NORESTART;
+}
+
/*
* Return the battery average current in µA
* Note that current can be negative signed as well
@@ -1338,6 +1290,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
/* We need to turn off the wakeup capability of the pins when we don't
* want the interrupts, or all heck breaks loose.
+ */
static void olio_interrupt_enabled (int irq) {
__raw_writew ((u16) (4 << 12 | 1 << 8 | 0 << 4 | 4),
@@ -1388,7 +1341,7 @@ static int bq27x00_charger_status (struct bq27x00_device_info *di,
}
/* Test 2 */
- printk ("OLIO %s mA_now == %d \n", __FUNCTION__, mA_now);
+ olio_debug ("mA_now == %d \n", mA_now);
if (mA_now < 0) {
ts81001->ops->request_charge(ts81001, 100);
@@ -1404,12 +1357,11 @@ static int bq27x00_charger_status (struct bq27x00_device_info *di,
case NOT_CHARGING:
olio_debug("exiting, DISCHARGING\n");
mutex_lock(&di->lock);
- if (!irq_enabled) {
- printk ("%s OLIO off charger, enabling chg interrupts\n",
- __FUNCTION__);
+ if (!irq_enabled) { /* set up for off charger behavior */
+ olio_debug ("off charger, enabling chg interrupts\n");
irq_enabled = 1;
olio_interrupt_enabled (di->irq);
- /* enable_irq_wake (di->irq); */ /* enable interrupts */
+ alarm_cancel (&di->poll_alarm);
}
mutex_unlock(&di->lock);
return POWER_SUPPLY_STATUS_DISCHARGING;
@@ -1418,12 +1370,11 @@ static int bq27x00_charger_status (struct bq27x00_device_info *di,
case TOPOFF:
olio_debug("exiting, CHARGING\n");
mutex_lock(&di->lock);
- if (irq_enabled) {
- printk ("%s OLIO on charger, disabling chg interrupts\n",
- __FUNCTION__);
+ if (irq_enabled) { /* set up for on charger behavior */
+ olio_debug ("on charger, disabling chg interrupts\n");
irq_enabled = 0;
olio_interrupt_disabled (di->irq);
- /* disable_irq_wake (di->irq); */ /* disable interrupts */
+ alarm_start_relative (&di->poll_alarm, di->alarm_time);
}
mutex_unlock(&di->lock);
return POWER_SUPPLY_STATUS_CHARGING;
@@ -1632,7 +1583,7 @@ static irqreturn_t bq27x00_chg_isr(int irq, void *dev) {
struct power_supply *ps = (struct power_supply*) dev;
struct bq27x00_device_info *di = to_bq27x00_device_info(ps);
- printk ("%s OLIO ISR triggered!\n", __FUNCTION__);
+ olio_debug ("ISR triggered!\n");
wake_lock(&isr_wake_lock);
@@ -1681,8 +1632,19 @@ static int __init bq27x00_powersupply_init(struct bq27x00_device_info *di)
di->bat.get_property = bq27x00_battery_get_property;
di->bat.external_power_changed = bq27x00_external_power_changed;
- INIT_DELAYED_WORK(&di->interrupt_work, bq27x00_battery_interrupt);
INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
+ INIT_DELAYED_WORK(&di->interrupt_work, bq27x00_battery_interrupt);
+
+#ifdef CONFIG_OLIO_TS81001
+ /* Set up alarm timer which wakes the device up if suspended. */
+
+ alarm_init (&di->poll_alarm, ALARM_BOOTTIME,
+ bq27x00_run_poll_alarm);
+
+ di->alarm_time = ktime_set(BQ27X00_ALARM_TIMER_INTERVAL,0);
+
+ alarm_start_relative (&di->poll_alarm, di->alarm_time);
+#endif
mutex_init(&di->lock);
ret = power_supply_register(di->dev, &di->bat);