diff options
author | Ramakrishna Pallala <ramakrishna.pallala@intel.com> | 2012-01-24 12:26:06 -0500 |
---|---|---|
committer | Anton Vorontsov <anton.vorontsov@linaro.org> | 2012-03-26 12:38:41 -0400 |
commit | e5f3872d20448706d3bb8083ee82a9226d3f8b5c (patch) | |
tree | e6631f09e2465a3770e5c6d2a9eeeb3c33b3b6f0 /drivers/power | |
parent | f3a71a6eb13b71cc8a3dc5b6e5692e3db66b92f0 (diff) |
max17042: Add support for signalling change in SOC
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>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/max17042_battery.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index fde7ccd62953..3a30a27b094c 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/interrupt.h> | ||
30 | #include <linux/mod_devicetable.h> | 31 | #include <linux/mod_devicetable.h> |
31 | #include <linux/power_supply.h> | 32 | #include <linux/power_supply.h> |
32 | #include <linux/power/max17042_battery.h> | 33 | #include <linux/power/max17042_battery.h> |
@@ -43,6 +44,11 @@ | |||
43 | #define STATUS_SMX_BIT (1 << 14) | 44 | #define STATUS_SMX_BIT (1 << 14) |
44 | #define STATUS_BR_BIT (1 << 15) | 45 | #define STATUS_BR_BIT (1 << 15) |
45 | 46 | ||
47 | /* Interrupt mask bits */ | ||
48 | #define CONFIG_ALRT_BIT_ENBL (1 << 2) | ||
49 | #define STATUS_INTR_SOC_BIT (1 << 14) | ||
50 | #define STATUS_INTR_LOW_SOC_BIT (1 << 10) | ||
51 | |||
46 | #define VFSOC0_LOCK 0x0000 | 52 | #define VFSOC0_LOCK 0x0000 |
47 | #define VFSOC0_UNLOCK 0x0080 | 53 | #define VFSOC0_UNLOCK 0x0080 |
48 | #define MODEL_UNLOCK1 0X0059 | 54 | #define MODEL_UNLOCK1 0X0059 |
@@ -552,6 +558,39 @@ static int max17042_init_chip(struct max17042_chip *chip) | |||
552 | return 0; | 558 | return 0; |
553 | } | 559 | } |
554 | 560 | ||
561 | static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) | ||
562 | { | ||
563 | u16 soc, soc_tr; | ||
564 | |||
565 | /* program interrupt thesholds such that we should | ||
566 | * get interrupt for every 'off' perc change in the soc | ||
567 | */ | ||
568 | soc = max17042_read_reg(chip->client, MAX17042_RepSOC) >> 8; | ||
569 | soc_tr = (soc + off) << 8; | ||
570 | soc_tr |= (soc - off); | ||
571 | max17042_write_reg(chip->client, MAX17042_SALRT_Th, soc_tr); | ||
572 | } | ||
573 | |||
574 | static irqreturn_t max17042_intr_handler(int id, void *dev) | ||
575 | { | ||
576 | return IRQ_WAKE_THREAD; | ||
577 | } | ||
578 | |||
579 | static irqreturn_t max17042_thread_handler(int id, void *dev) | ||
580 | { | ||
581 | struct max17042_chip *chip = dev; | ||
582 | u16 val; | ||
583 | |||
584 | val = max17042_read_reg(chip->client, MAX17042_STATUS); | ||
585 | if ((val & STATUS_INTR_SOC_BIT) || | ||
586 | (val & STATUS_INTR_LOW_SOC_BIT)) { | ||
587 | dev_info(&chip->client->dev, "SOC threshold INTR\n"); | ||
588 | max17042_set_soc_threshold(chip, 1); | ||
589 | } | ||
590 | |||
591 | power_supply_changed(&chip->battery); | ||
592 | return IRQ_HANDLED; | ||
593 | } | ||
555 | 594 | ||
556 | static void max17042_init_worker(struct work_struct *work) | 595 | static void max17042_init_worker(struct work_struct *work) |
557 | { | 596 | { |
@@ -613,6 +652,20 @@ static int __devinit max17042_probe(struct i2c_client *client, | |||
613 | max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); | 652 | max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); |
614 | } | 653 | } |
615 | 654 | ||
655 | if (client->irq) { | ||
656 | ret = request_threaded_irq(client->irq, max17042_intr_handler, | ||
657 | max17042_thread_handler, | ||
658 | 0, chip->battery.name, chip); | ||
659 | if (!ret) { | ||
660 | reg = max17042_read_reg(client, MAX17042_CONFIG); | ||
661 | reg |= CONFIG_ALRT_BIT_ENBL; | ||
662 | max17042_write_reg(client, MAX17042_CONFIG, reg); | ||
663 | max17042_set_soc_threshold(chip, 1); | ||
664 | } else | ||
665 | dev_err(&client->dev, "%s(): cannot get IRQ\n", | ||
666 | __func__); | ||
667 | } | ||
668 | |||
616 | reg = max17042_read_reg(chip->client, MAX17042_STATUS); | 669 | reg = max17042_read_reg(chip->client, MAX17042_STATUS); |
617 | 670 | ||
618 | if (reg & STATUS_POR_BIT) { | 671 | if (reg & STATUS_POR_BIT) { |