diff options
| author | Evan Wilson <evan@oliodevices.com> | 2016-01-20 21:35:37 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit2@ip-172-31-25-77.us-west-1.compute.internal> | 2015-04-16 10:08:13 +0000 |
| commit | 7bdf9fd7e2337b3d75bfa1d1d7a5b1372d50fc04 (patch) | |
| tree | 0137b4403f3f0565c26f1b0fcfa5856bca75714c | |
| parent | 058e418668659a82ae277b05dc1fc1a546aa3bc8 (diff) | |
| parent | 42bdc122eed6e3748d55574e8f57ca3907b81767 (diff) | |
| download | olio-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.c | 144 |
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); |