summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-09-26 11:27:24 -0700
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-10-10 09:44:09 -0700
commit21005fbb17c0b223beaa71ec5b171246299ffdcf (patch)
tree68b31418bb011e294dbd8b8e42421faf92dbfc7c
parent03451c889216fe99c241cb092589a486c2b07e8c (diff)
qpnp-fg-gen3: add support to configure and handle delta battery temperature
Battery temperature delta configuration can be used to know the battery temperature change. There is an interrupt associated with this configuration which can be used to update the battery health of the device. Change-Id: Ic55b9bb34ac9912f88dab6a11ec365814b525ca2 Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt6
-rw-r--r--drivers/power/qcom-charger/fg-core.h3
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c63
3 files changed, 72 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
index 2736da585e0b..7841251c67fe 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
@@ -210,6 +210,12 @@ First Level Node - FG Gen3 device
0 - No hysteresis
1,2,3 - Value in Celsius.
+- qcom,fg-batt-temp-delta
+ Usage: optional
+ Value type: <u32>
+ Definition: Battery temperature delta interrupt threshold. Possible
+ values are: 2, 4, 6 and 10. Unit is in Kelvin.
+
==========================================================
Second Level Nodes - Peripherals managed by FG Gen3 driver
==========================================================
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h
index beb7ab287823..7e08b71e3b6a 100644
--- a/drivers/power/qcom-charger/fg-core.h
+++ b/drivers/power/qcom-charger/fg-core.h
@@ -194,6 +194,7 @@ struct fg_dt_props {
int cl_max_cap_limit;
int cl_min_cap_limit;
int jeita_hyst_temp;
+ int batt_temp_delta;
};
/* parameters from battery profile */
@@ -261,6 +262,8 @@ struct fg_chip {
int status;
int charge_done;
int last_soc;
+ int last_batt_temp;
+ int health;
bool profile_available;
bool profile_loaded;
bool battery_missing;
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index cef24ddcd106..f8c1ad5963af 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -771,6 +771,27 @@ static inline void get_temp_setpoint(int threshold, u8 *val)
*val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5);
}
+static inline void get_batt_temp_delta(int delta, u8 *val)
+{
+ switch (delta) {
+ case 2:
+ *val = BTEMP_DELTA_2K;
+ break;
+ case 4:
+ *val = BTEMP_DELTA_4K;
+ break;
+ case 6:
+ *val = BTEMP_DELTA_6K;
+ break;
+ case 10:
+ *val = BTEMP_DELTA_10K;
+ break;
+ default:
+ *val = BTEMP_DELTA_2K;
+ break;
+ };
+}
+
static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
int flags)
{
@@ -1849,6 +1870,14 @@ static int fg_hw_init(struct fg_chip *chip)
}
}
+ get_batt_temp_delta(chip->dt.batt_temp_delta, &val);
+ rc = fg_masked_write(chip, BATT_INFO_BATT_TMPR_INTR(chip),
+ CHANGE_THOLD_MASK, val);
+ if (rc < 0) {
+ pr_err("Error in writing batt_temp_delta, rc=%d\n", rc);
+ return rc;
+ }
+
return 0;
}
@@ -1902,8 +1931,33 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
{
struct fg_chip *chip = data;
+ union power_supply_propval prop = {0, };
+ int rc, batt_temp;
fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
+ rc = fg_get_battery_temp(chip, &batt_temp);
+ if (rc < 0) {
+ pr_err("Error in getting batt_temp\n");
+ return IRQ_HANDLED;
+ }
+
+ if (!is_charger_available(chip)) {
+ chip->last_batt_temp = batt_temp;
+ return IRQ_HANDLED;
+ }
+
+ power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
+ &prop);
+ chip->health = prop.intval;
+
+ if (chip->last_batt_temp != batt_temp) {
+ chip->last_batt_temp = batt_temp;
+ power_supply_changed(chip->batt_psy);
+ }
+
+ if (abs(chip->last_batt_temp - batt_temp) > 30)
+ pr_warn("Battery temperature last:%d current: %d\n",
+ chip->last_batt_temp, batt_temp);
return IRQ_HANDLED;
}
@@ -2013,6 +2067,7 @@ static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
[BATT_TEMP_DELTA_IRQ] = {
.name = "batt-temp-delta",
.handler = fg_delta_batt_temp_irq_handler,
+ .wakeable = true,
},
[BATT_MISSING_IRQ] = {
.name = "batt-missing",
@@ -2116,6 +2171,8 @@ static int fg_register_interrupts(struct fg_chip *chip)
#define DEFAULT_CL_MAX_DEC_DECIPERC 100
#define DEFAULT_CL_MIN_LIM_DECIPERC 0
#define DEFAULT_CL_MAX_LIM_DECIPERC 0
+#define BTEMP_DELTA_LOW 2
+#define BTEMP_DELTA_HIGH 10
static int fg_parse_dt(struct fg_chip *chip)
{
struct device_node *child, *revid_node, *node = chip->dev->of_node;
@@ -2353,6 +2410,12 @@ static int fg_parse_dt(struct fg_chip *chip)
else
chip->dt.jeita_hyst_temp = temp;
+ rc = of_property_read_u32(node, "qcom,fg-batt-temp-delta", &temp);
+ if (rc < 0)
+ chip->dt.batt_temp_delta = -EINVAL;
+ else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
+ chip->dt.batt_temp_delta = temp;
+
return 0;
}