Loading drivers/power/supply/qcom/qg-battery-profile.c +18 −4 Original line number Diff line number Diff line Loading @@ -393,19 +393,33 @@ static int qg_parse_battery_profile(struct qg_battery_data *battery) return rc; } int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging) int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup) { u8 table_index = charging ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2; u8 table_index = 0; int soc_avg = 0, soc_charge = 0, soc_discharge = 0; if (!the_battery || !the_battery->profile) { pr_err("Battery profile not loaded\n"); return -ENODEV; } *soc = interpolate_soc(&the_battery->profile[table_index], if (lookup == SOC_AVERAGE) { soc_charge = interpolate_soc( &the_battery->profile[TABLE_SOC_OCV1], batt_temp, UV_TO_DECIUV(ocv_uv)); soc_discharge = interpolate_soc( &the_battery->profile[TABLE_SOC_OCV2], batt_temp, UV_TO_DECIUV(ocv_uv)); soc_avg = (soc_charge + soc_discharge) / 2; } else { table_index = (lookup == SOC_CHARGE) ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2; soc_avg = interpolate_soc( &the_battery->profile[table_index], batt_temp, UV_TO_DECIUV(ocv_uv)); } *soc = CAP(0, 100, DIV_ROUND_CLOSEST(*soc, 100)); *soc = CAP(0, 100, DIV_ROUND_CLOSEST(soc_avg, 100)); return 0; } Loading drivers/power/supply/qcom/qg-battery-profile.h +1 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,6 @@ int qg_batterydata_init(struct device_node *node); void qg_batterydata_exit(void); int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging); int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup); #endif /* __QG_BATTERY_PROFILE_H__ */ drivers/power/supply/qcom/qg-defs.h +6 −0 Original line number Diff line number Diff line Loading @@ -45,4 +45,10 @@ #define CAP(min, max, value) \ ((min > value) ? min : ((value > max) ? max : value)) enum soc_lookup { SOC_CHARGE, SOC_DISCHARGE, SOC_AVERAGE, }; #endif /* __QG_DEFS_H__ */ drivers/power/supply/qcom/qg-util.c +1 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,7 @@ int get_fifo_length(struct qpnp_qg *chip, u32 *fifo_length, bool rt) } if (rt) { *fifo_length &= COUNT_FIFO_RT_MASK; *fifo_length = reg & COUNT_FIFO_RT_MASK; } else { *fifo_length = (reg & FIFO_LENGTH_MASK) >> FIFO_LENGTH_SHIFT; *fifo_length += 1; Loading drivers/power/supply/qcom/qpnp-qg.c +37 −26 Original line number Diff line number Diff line Loading @@ -247,6 +247,20 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length) return rc; } /* * If there is pending data from suspend, append the new FIFO * data to it. */ if (chip->suspend_data) { j = chip->kdata.fifo_length; /* append the data */ chip->suspend_data = false; qg_dbg(chip, QG_DEBUG_FIFO, "Pending suspend-data FIFO length=%d\n", j); } else { /* clear any old pending data */ chip->kdata.fifo_length = 0; } for (i = 0; i < fifo_length * 2; i = i + 2, j++) { rc = qg_read(chip, chip->qg_base + QG_V_FIFO0_DATA0_REG + i, &v_fifo[i], 2); Loading Loading @@ -280,7 +294,7 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length) chip->kdata.fifo[j].count); } chip->kdata.fifo_length = fifo_length; chip->kdata.fifo_length += fifo_length; chip->kdata.seq_no = chip->seq_no++ % U32_MAX; return rc; Loading Loading @@ -1481,7 +1495,8 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) pr_err("Failed to read good_ocv rc=%d\n", rc); use_pon_ocv = true; } else { rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, SOC_AVERAGE); if (rc < 0) { pr_err("Failed to lookup SOC (GOOD_OCV) @ PON rc=%d\n", rc); Loading Loading @@ -1534,7 +1549,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) pr_err("Failed to read HW PON ocv rc=%d\n", rc); return rc; } rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, SOC_AVERAGE); if (rc < 0) { pr_err("Failed to lookup SOC @ PON rc=%d\n", rc); soc = 50; Loading Loading @@ -2046,6 +2061,8 @@ static int process_suspend(struct qpnp_qg *chip) int rc; u32 fifo_rt_length = 0, sleep_fifo_length = 0; chip->suspend_data = false; /* ignore any suspend processing if we are charging */ if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) { qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n"); Loading Loading @@ -2104,9 +2121,9 @@ static int process_suspend(struct qpnp_qg *chip) static int process_resume(struct qpnp_qg *chip) { int rc, batt_temp = 0; u8 status2 = 0, rt_status = 0; u32 ocv_uv = 0, soc = 0; u32 ocv_uv = 0; int rc, batt_temp = 0; rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1); if (rc < 0) { Loading @@ -2128,23 +2145,12 @@ static int process_resume(struct qpnp_qg *chip) chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; chip->kdata.param[QG_GOOD_OCV_UV].valid = true; /* Clear suspend data as there has been a GOOD OCV */ chip->suspend_data = false; rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); if (rc < 0) { pr_err("Failed to lookup OCV, rc=%d\n", rc); return rc; qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n", ocv_uv); } chip->catch_up_soc = soc; /* update the SOC immediately */ qg_scale_soc(chip, true); qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV soc=%d\n", ocv_uv, soc); } /* * If the wakeup was not because of FIFO_DONE * send the pending data collected during suspend. */ rc = qg_read(chip, chip->qg_base + QG_INT_LATCHED_STS_REG, &rt_status, 1); if (rc < 0) { Loading @@ -2153,17 +2159,22 @@ static int process_resume(struct qpnp_qg *chip) } rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT; if (!rt_status && chip->suspend_data) { qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n", !!rt_status, chip->suspend_data, chip->kdata.param[QG_GOOD_OCV_UV].valid); /* * If this is not a wakeup from FIFO-done, * process the data immediately if - we have data from * suspend or there is a good OCV. */ if (!rt_status && (chip->suspend_data || chip->kdata.param[QG_GOOD_OCV_UV].valid)) { vote(chip->awake_votable, SUSPEND_DATA_VOTER, true, 0); /* signal the read thread */ chip->data_ready = true; wake_up_interruptible(&chip->qg_wait_q); } qg_dbg(chip, QG_DEBUG_PM, "fifo_done rt_status=%d suspend_data=%d data_ready=%d\n", !!rt_status, chip->suspend_data, chip->data_ready); chip->suspend_data = false; } return rc; } Loading Loading
drivers/power/supply/qcom/qg-battery-profile.c +18 −4 Original line number Diff line number Diff line Loading @@ -393,19 +393,33 @@ static int qg_parse_battery_profile(struct qg_battery_data *battery) return rc; } int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging) int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup) { u8 table_index = charging ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2; u8 table_index = 0; int soc_avg = 0, soc_charge = 0, soc_discharge = 0; if (!the_battery || !the_battery->profile) { pr_err("Battery profile not loaded\n"); return -ENODEV; } *soc = interpolate_soc(&the_battery->profile[table_index], if (lookup == SOC_AVERAGE) { soc_charge = interpolate_soc( &the_battery->profile[TABLE_SOC_OCV1], batt_temp, UV_TO_DECIUV(ocv_uv)); soc_discharge = interpolate_soc( &the_battery->profile[TABLE_SOC_OCV2], batt_temp, UV_TO_DECIUV(ocv_uv)); soc_avg = (soc_charge + soc_discharge) / 2; } else { table_index = (lookup == SOC_CHARGE) ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2; soc_avg = interpolate_soc( &the_battery->profile[table_index], batt_temp, UV_TO_DECIUV(ocv_uv)); } *soc = CAP(0, 100, DIV_ROUND_CLOSEST(*soc, 100)); *soc = CAP(0, 100, DIV_ROUND_CLOSEST(soc_avg, 100)); return 0; } Loading
drivers/power/supply/qcom/qg-battery-profile.h +1 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,6 @@ int qg_batterydata_init(struct device_node *node); void qg_batterydata_exit(void); int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging); int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup); #endif /* __QG_BATTERY_PROFILE_H__ */
drivers/power/supply/qcom/qg-defs.h +6 −0 Original line number Diff line number Diff line Loading @@ -45,4 +45,10 @@ #define CAP(min, max, value) \ ((min > value) ? min : ((value > max) ? max : value)) enum soc_lookup { SOC_CHARGE, SOC_DISCHARGE, SOC_AVERAGE, }; #endif /* __QG_DEFS_H__ */
drivers/power/supply/qcom/qg-util.c +1 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,7 @@ int get_fifo_length(struct qpnp_qg *chip, u32 *fifo_length, bool rt) } if (rt) { *fifo_length &= COUNT_FIFO_RT_MASK; *fifo_length = reg & COUNT_FIFO_RT_MASK; } else { *fifo_length = (reg & FIFO_LENGTH_MASK) >> FIFO_LENGTH_SHIFT; *fifo_length += 1; Loading
drivers/power/supply/qcom/qpnp-qg.c +37 −26 Original line number Diff line number Diff line Loading @@ -247,6 +247,20 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length) return rc; } /* * If there is pending data from suspend, append the new FIFO * data to it. */ if (chip->suspend_data) { j = chip->kdata.fifo_length; /* append the data */ chip->suspend_data = false; qg_dbg(chip, QG_DEBUG_FIFO, "Pending suspend-data FIFO length=%d\n", j); } else { /* clear any old pending data */ chip->kdata.fifo_length = 0; } for (i = 0; i < fifo_length * 2; i = i + 2, j++) { rc = qg_read(chip, chip->qg_base + QG_V_FIFO0_DATA0_REG + i, &v_fifo[i], 2); Loading Loading @@ -280,7 +294,7 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length) chip->kdata.fifo[j].count); } chip->kdata.fifo_length = fifo_length; chip->kdata.fifo_length += fifo_length; chip->kdata.seq_no = chip->seq_no++ % U32_MAX; return rc; Loading Loading @@ -1481,7 +1495,8 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) pr_err("Failed to read good_ocv rc=%d\n", rc); use_pon_ocv = true; } else { rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, SOC_AVERAGE); if (rc < 0) { pr_err("Failed to lookup SOC (GOOD_OCV) @ PON rc=%d\n", rc); Loading Loading @@ -1534,7 +1549,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) pr_err("Failed to read HW PON ocv rc=%d\n", rc); return rc; } rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, SOC_AVERAGE); if (rc < 0) { pr_err("Failed to lookup SOC @ PON rc=%d\n", rc); soc = 50; Loading Loading @@ -2046,6 +2061,8 @@ static int process_suspend(struct qpnp_qg *chip) int rc; u32 fifo_rt_length = 0, sleep_fifo_length = 0; chip->suspend_data = false; /* ignore any suspend processing if we are charging */ if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) { qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n"); Loading Loading @@ -2104,9 +2121,9 @@ static int process_suspend(struct qpnp_qg *chip) static int process_resume(struct qpnp_qg *chip) { int rc, batt_temp = 0; u8 status2 = 0, rt_status = 0; u32 ocv_uv = 0, soc = 0; u32 ocv_uv = 0; int rc, batt_temp = 0; rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1); if (rc < 0) { Loading @@ -2128,23 +2145,12 @@ static int process_resume(struct qpnp_qg *chip) chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; chip->kdata.param[QG_GOOD_OCV_UV].valid = true; /* Clear suspend data as there has been a GOOD OCV */ chip->suspend_data = false; rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); if (rc < 0) { pr_err("Failed to lookup OCV, rc=%d\n", rc); return rc; qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n", ocv_uv); } chip->catch_up_soc = soc; /* update the SOC immediately */ qg_scale_soc(chip, true); qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV soc=%d\n", ocv_uv, soc); } /* * If the wakeup was not because of FIFO_DONE * send the pending data collected during suspend. */ rc = qg_read(chip, chip->qg_base + QG_INT_LATCHED_STS_REG, &rt_status, 1); if (rc < 0) { Loading @@ -2153,17 +2159,22 @@ static int process_resume(struct qpnp_qg *chip) } rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT; if (!rt_status && chip->suspend_data) { qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n", !!rt_status, chip->suspend_data, chip->kdata.param[QG_GOOD_OCV_UV].valid); /* * If this is not a wakeup from FIFO-done, * process the data immediately if - we have data from * suspend or there is a good OCV. */ if (!rt_status && (chip->suspend_data || chip->kdata.param[QG_GOOD_OCV_UV].valid)) { vote(chip->awake_votable, SUSPEND_DATA_VOTER, true, 0); /* signal the read thread */ chip->data_ready = true; wake_up_interruptible(&chip->qg_wait_q); } qg_dbg(chip, QG_DEBUG_PM, "fifo_done rt_status=%d suspend_data=%d data_ready=%d\n", !!rt_status, chip->suspend_data, chip->data_ready); chip->suspend_data = false; } return rc; } Loading