diff options
Diffstat (limited to 'drivers')
| -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); |