summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}