Loading drivers/power/supply/qcom/qg-core.h +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ struct qg_dt { int esr_disable_soc; int esr_min_ibat_ua; int shutdown_soc_threshold; int min_sleep_time_secs; int sys_min_volt_mv; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; Loading Loading @@ -137,6 +139,7 @@ struct qpnp_qg { ktime_t last_user_update_time; ktime_t last_fifo_update_time; unsigned long last_maint_soc_update_time; unsigned long suspend_time; struct iio_channel *batt_therm_chan; struct iio_channel *batt_id_chan; Loading drivers/power/supply/qcom/qpnp-qg.c +86 −6 Original line number Diff line number Diff line Loading @@ -1612,6 +1612,54 @@ static int qg_get_charge_counter(struct qpnp_qg *chip, int *charge_counter) return 0; } static int qg_get_power(struct qpnp_qg *chip, int *val, bool average) { int rc, v_min, v_ocv, rbatt = 0, esr = 0; s64 power; if (is_debug_batt_id(chip)) { *val = -EINVAL; return 0; } v_min = chip->dt.sys_min_volt_mv * 1000; rc = qg_sdam_read(SDAM_OCV_UV, &v_ocv); if (rc < 0) { pr_err("Failed to read OCV rc=%d\n", rc); return rc; } rc = qg_sdam_read(SDAM_RBAT_MOHM, &rbatt); if (rc < 0) { pr_err("Failed to read T_RBAT rc=%d\n", rc); return rc; } rbatt *= 1000; /* uohms */ esr = chip->esr_last * 1000; if (rbatt <= 0 || esr <= 0) { pr_debug("Invalid rbatt/esr rbatt=%d esr=%d\n", rbatt, esr); *val = -EINVAL; return 0; } power = (s64)v_min * (v_ocv - v_min); if (average) power = div_s64(power, rbatt); else power = div_s64(power, esr); *val = power; qg_dbg(chip, QG_DEBUG_STATUS, "v_min=%d v_ocv=%d rbatt=%d esr=%d power=%lld\n", v_min, v_ocv, rbatt, esr, power); return 0; } static int qg_get_ttf_param(void *data, enum ttf_param param, int *val) { union power_supply_propval prop = {0, }; Loading Loading @@ -1942,6 +1990,12 @@ static int qg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_AVG: rc = qg_get_vbat_avg(chip, &pval->intval); break; case POWER_SUPPLY_PROP_POWER_NOW: rc = qg_get_power(chip, &pval->intval, false); break; case POWER_SUPPLY_PROP_POWER_AVG: rc = qg_get_power(chip, &pval->intval, true); break; default: pr_debug("Unsupported property %d\n", psp); break; Loading Loading @@ -1997,6 +2051,8 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_CC_SOC, POWER_SUPPLY_PROP_FG_RESET, POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_NOW, }; static const struct power_supply_desc qg_psy_desc = { Loading Loading @@ -3419,6 +3475,8 @@ static void qg_create_debugfs(struct qpnp_qg *chip) #define DEFAULT_ESR_QUAL_VBAT_UV 7000 #define DEFAULT_ESR_DISABLE_SOC 1000 #define ESR_CHG_MIN_IBAT_UA (-450000) #define DEFAULT_SLEEP_TIME_SECS 1800 /* 30 mins */ #define DEFAULT_SYS_MIN_VOLT_MV 2800 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; Loading Loading @@ -3655,10 +3713,22 @@ static int qg_parse_dt(struct qpnp_qg *chip) else chip->dt.shutdown_soc_threshold = temp; rc = of_property_read_u32(node, "qcom,qg-sys-min-voltage", &temp); if (rc < 0) chip->dt.sys_min_volt_mv = DEFAULT_SYS_MIN_VOLT_MV; else chip->dt.sys_min_volt_mv = temp; chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns"); chip->dt.use_s7_ocv = of_property_read_bool(node, "qcom,qg-use-s7-ocv"); rc = of_property_read_u32(node, "qcom,min-sleep-time-secs", &temp); if (rc < 0) chip->dt.min_sleep_time_secs = DEFAULT_SLEEP_TIME_SECS; else chip->dt.min_sleep_time_secs = temp; /* Capacity learning params*/ if (!chip->dt.cl_disable) { chip->dt.cl_feedback_on = of_property_read_bool(node, Loading Loading @@ -3799,9 +3869,12 @@ static int process_suspend(struct qpnp_qg *chip) chip->suspend_data = true; } qg_dbg(chip, QG_DEBUG_PM, "FIFO rt_length=%d sleep_fifo_length=%d default_s2_count=%d suspend_data=%d\n", get_rtc_time(&chip->suspend_time); qg_dbg(chip, QG_DEBUG_PM, "FIFO rt_length=%d sleep_fifo_length=%d default_s2_count=%d suspend_data=%d time=%d\n", fifo_rt_length, sleep_fifo_length, chip->dt.s2_fifo_length, chip->suspend_data); chip->dt.s2_fifo_length, chip->suspend_data, chip->suspend_time); return rc; } Loading @@ -3811,12 +3884,15 @@ static int process_resume(struct qpnp_qg *chip) u8 status2 = 0, rt_status = 0; u32 ocv_uv = 0, ocv_raw = 0; int rc; unsigned long rtc_sec = 0; unsigned long rtc_sec = 0, sleep_time_secs = 0; /* skip if profile is not loaded */ if (!chip->profile_loaded) return 0; get_rtc_time(&rtc_sec); sleep_time_secs = rtc_sec - chip->suspend_time; rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1); if (rc < 0) { pr_err("Failed to read status2 register, rc=%d\n", rc); Loading @@ -3832,12 +3908,15 @@ static int process_resume(struct qpnp_qg *chip) /* Clear suspend data as there has been a GOOD OCV */ memset(&chip->kdata, 0, sizeof(chip->kdata)); get_rtc_time(&rtc_sec); chip->kdata.fifo_time = (u32)rtc_sec; chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; chip->kdata.param[QG_GOOD_OCV_UV].valid = true; chip->suspend_data = false; /* allow SOC jump if we have slept longer */ if (sleep_time_secs >= chip->dt.min_sleep_time_secs) chip->force_soc = true; qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n", ocv_uv); } Loading @@ -3850,9 +3929,10 @@ static int process_resume(struct qpnp_qg *chip) } rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT; qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n", qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d sleep_time=%d secs\n", !!rt_status, chip->suspend_data, chip->kdata.param[QG_GOOD_OCV_UV].valid); chip->kdata.param[QG_GOOD_OCV_UV].valid, sleep_time_secs); /* * If this is not a wakeup from FIFO-done, * process the data immediately if - we have data from Loading Loading
drivers/power/supply/qcom/qg-core.h +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ struct qg_dt { int esr_disable_soc; int esr_min_ibat_ua; int shutdown_soc_threshold; int min_sleep_time_secs; int sys_min_volt_mv; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; Loading Loading @@ -137,6 +139,7 @@ struct qpnp_qg { ktime_t last_user_update_time; ktime_t last_fifo_update_time; unsigned long last_maint_soc_update_time; unsigned long suspend_time; struct iio_channel *batt_therm_chan; struct iio_channel *batt_id_chan; Loading
drivers/power/supply/qcom/qpnp-qg.c +86 −6 Original line number Diff line number Diff line Loading @@ -1612,6 +1612,54 @@ static int qg_get_charge_counter(struct qpnp_qg *chip, int *charge_counter) return 0; } static int qg_get_power(struct qpnp_qg *chip, int *val, bool average) { int rc, v_min, v_ocv, rbatt = 0, esr = 0; s64 power; if (is_debug_batt_id(chip)) { *val = -EINVAL; return 0; } v_min = chip->dt.sys_min_volt_mv * 1000; rc = qg_sdam_read(SDAM_OCV_UV, &v_ocv); if (rc < 0) { pr_err("Failed to read OCV rc=%d\n", rc); return rc; } rc = qg_sdam_read(SDAM_RBAT_MOHM, &rbatt); if (rc < 0) { pr_err("Failed to read T_RBAT rc=%d\n", rc); return rc; } rbatt *= 1000; /* uohms */ esr = chip->esr_last * 1000; if (rbatt <= 0 || esr <= 0) { pr_debug("Invalid rbatt/esr rbatt=%d esr=%d\n", rbatt, esr); *val = -EINVAL; return 0; } power = (s64)v_min * (v_ocv - v_min); if (average) power = div_s64(power, rbatt); else power = div_s64(power, esr); *val = power; qg_dbg(chip, QG_DEBUG_STATUS, "v_min=%d v_ocv=%d rbatt=%d esr=%d power=%lld\n", v_min, v_ocv, rbatt, esr, power); return 0; } static int qg_get_ttf_param(void *data, enum ttf_param param, int *val) { union power_supply_propval prop = {0, }; Loading Loading @@ -1942,6 +1990,12 @@ static int qg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_AVG: rc = qg_get_vbat_avg(chip, &pval->intval); break; case POWER_SUPPLY_PROP_POWER_NOW: rc = qg_get_power(chip, &pval->intval, false); break; case POWER_SUPPLY_PROP_POWER_AVG: rc = qg_get_power(chip, &pval->intval, true); break; default: pr_debug("Unsupported property %d\n", psp); break; Loading Loading @@ -1997,6 +2051,8 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_CC_SOC, POWER_SUPPLY_PROP_FG_RESET, POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_NOW, }; static const struct power_supply_desc qg_psy_desc = { Loading Loading @@ -3419,6 +3475,8 @@ static void qg_create_debugfs(struct qpnp_qg *chip) #define DEFAULT_ESR_QUAL_VBAT_UV 7000 #define DEFAULT_ESR_DISABLE_SOC 1000 #define ESR_CHG_MIN_IBAT_UA (-450000) #define DEFAULT_SLEEP_TIME_SECS 1800 /* 30 mins */ #define DEFAULT_SYS_MIN_VOLT_MV 2800 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; Loading Loading @@ -3655,10 +3713,22 @@ static int qg_parse_dt(struct qpnp_qg *chip) else chip->dt.shutdown_soc_threshold = temp; rc = of_property_read_u32(node, "qcom,qg-sys-min-voltage", &temp); if (rc < 0) chip->dt.sys_min_volt_mv = DEFAULT_SYS_MIN_VOLT_MV; else chip->dt.sys_min_volt_mv = temp; chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns"); chip->dt.use_s7_ocv = of_property_read_bool(node, "qcom,qg-use-s7-ocv"); rc = of_property_read_u32(node, "qcom,min-sleep-time-secs", &temp); if (rc < 0) chip->dt.min_sleep_time_secs = DEFAULT_SLEEP_TIME_SECS; else chip->dt.min_sleep_time_secs = temp; /* Capacity learning params*/ if (!chip->dt.cl_disable) { chip->dt.cl_feedback_on = of_property_read_bool(node, Loading Loading @@ -3799,9 +3869,12 @@ static int process_suspend(struct qpnp_qg *chip) chip->suspend_data = true; } qg_dbg(chip, QG_DEBUG_PM, "FIFO rt_length=%d sleep_fifo_length=%d default_s2_count=%d suspend_data=%d\n", get_rtc_time(&chip->suspend_time); qg_dbg(chip, QG_DEBUG_PM, "FIFO rt_length=%d sleep_fifo_length=%d default_s2_count=%d suspend_data=%d time=%d\n", fifo_rt_length, sleep_fifo_length, chip->dt.s2_fifo_length, chip->suspend_data); chip->dt.s2_fifo_length, chip->suspend_data, chip->suspend_time); return rc; } Loading @@ -3811,12 +3884,15 @@ static int process_resume(struct qpnp_qg *chip) u8 status2 = 0, rt_status = 0; u32 ocv_uv = 0, ocv_raw = 0; int rc; unsigned long rtc_sec = 0; unsigned long rtc_sec = 0, sleep_time_secs = 0; /* skip if profile is not loaded */ if (!chip->profile_loaded) return 0; get_rtc_time(&rtc_sec); sleep_time_secs = rtc_sec - chip->suspend_time; rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1); if (rc < 0) { pr_err("Failed to read status2 register, rc=%d\n", rc); Loading @@ -3832,12 +3908,15 @@ static int process_resume(struct qpnp_qg *chip) /* Clear suspend data as there has been a GOOD OCV */ memset(&chip->kdata, 0, sizeof(chip->kdata)); get_rtc_time(&rtc_sec); chip->kdata.fifo_time = (u32)rtc_sec; chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; chip->kdata.param[QG_GOOD_OCV_UV].valid = true; chip->suspend_data = false; /* allow SOC jump if we have slept longer */ if (sleep_time_secs >= chip->dt.min_sleep_time_secs) chip->force_soc = true; qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n", ocv_uv); } Loading @@ -3850,9 +3929,10 @@ static int process_resume(struct qpnp_qg *chip) } rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT; qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n", qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d sleep_time=%d secs\n", !!rt_status, chip->suspend_data, chip->kdata.param[QG_GOOD_OCV_UV].valid); chip->kdata.param[QG_GOOD_OCV_UV].valid, sleep_time_secs); /* * If this is not a wakeup from FIFO-done, * process the data immediately if - we have data from Loading