Skip to content

Commit

Permalink
max17042: Add support for signalling change in SOC
Browse files Browse the repository at this point in the history
If platform has the alert pin attached to an interrupt source have the
driver signal a change in the SOC every 1 percent.

Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
  • Loading branch information
Ramakrishna Pallala authored and Anton Vorontsov committed Mar 26, 2012
1 parent f3a71a6 commit e5f3872
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions drivers/power/max17042_battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/mod_devicetable.h>
#include <linux/power_supply.h>
#include <linux/power/max17042_battery.h>
Expand All @@ -43,6 +44,11 @@
#define STATUS_SMX_BIT (1 << 14)
#define STATUS_BR_BIT (1 << 15)

/* Interrupt mask bits */
#define CONFIG_ALRT_BIT_ENBL (1 << 2)
#define STATUS_INTR_SOC_BIT (1 << 14)
#define STATUS_INTR_LOW_SOC_BIT (1 << 10)

#define VFSOC0_LOCK 0x0000
#define VFSOC0_UNLOCK 0x0080
#define MODEL_UNLOCK1 0X0059
Expand Down Expand Up @@ -552,6 +558,39 @@ static int max17042_init_chip(struct max17042_chip *chip)
return 0;
}

static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
{
u16 soc, soc_tr;

/* program interrupt thesholds such that we should
* get interrupt for every 'off' perc change in the soc
*/
soc = max17042_read_reg(chip->client, MAX17042_RepSOC) >> 8;
soc_tr = (soc + off) << 8;
soc_tr |= (soc - off);
max17042_write_reg(chip->client, MAX17042_SALRT_Th, soc_tr);
}

static irqreturn_t max17042_intr_handler(int id, void *dev)
{
return IRQ_WAKE_THREAD;
}

static irqreturn_t max17042_thread_handler(int id, void *dev)
{
struct max17042_chip *chip = dev;
u16 val;

val = max17042_read_reg(chip->client, MAX17042_STATUS);
if ((val & STATUS_INTR_SOC_BIT) ||
(val & STATUS_INTR_LOW_SOC_BIT)) {
dev_info(&chip->client->dev, "SOC threshold INTR\n");
max17042_set_soc_threshold(chip, 1);
}

power_supply_changed(&chip->battery);
return IRQ_HANDLED;
}

static void max17042_init_worker(struct work_struct *work)
{
Expand Down Expand Up @@ -613,6 +652,20 @@ static int __devinit max17042_probe(struct i2c_client *client,
max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
}

if (client->irq) {
ret = request_threaded_irq(client->irq, max17042_intr_handler,
max17042_thread_handler,
0, chip->battery.name, chip);
if (!ret) {
reg = max17042_read_reg(client, MAX17042_CONFIG);
reg |= CONFIG_ALRT_BIT_ENBL;
max17042_write_reg(client, MAX17042_CONFIG, reg);
max17042_set_soc_threshold(chip, 1);
} else
dev_err(&client->dev, "%s(): cannot get IRQ\n",
__func__);
}

reg = max17042_read_reg(chip->client, MAX17042_STATUS);

if (reg & STATUS_POR_BIT) {
Expand Down

0 comments on commit e5f3872

Please sign in to comment.