Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +15 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,21 @@ First Level Node - QGAUGE device Value type: <bool> Definition: Boolean property to use S7 for PON OCV. - qcom,min-sleep-time-secs Usage: optional Value type: <u32> Definition: The minimum sleep time in secs to allow a SOC jump if there has been a GOOD_OCV. - qcom,qg-sys-min-voltage Usage: optional Value type: <u32> Definition: The voltage threshold (in mV) which describes the system minimum voltage as per the hardware recommendation. This is not used for any configuration but only for calculating the available power. If this property is not specified, then the default value used is 2800 mV. ========================================================== Second Level Nodes - Peripherals managed by QGAUGE driver ========================================================== Loading drivers/power/supply/qcom/qg-core.h +3 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,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 @@ -142,6 +144,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 @@ -1579,6 +1579,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 @@ -1909,6 +1957,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 @@ -1964,6 +2018,8 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_FG_RESET, POWER_SUPPLY_PROP_CC_SOC, 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 @@ -3360,6 +3416,8 @@ static int qg_alg_init(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 @@ -3596,10 +3654,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 @@ -3740,9 +3810,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 @@ -3752,12 +3825,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 @@ -3773,12 +3849,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 @@ -3791,9 +3870,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
Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +15 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,21 @@ First Level Node - QGAUGE device Value type: <bool> Definition: Boolean property to use S7 for PON OCV. - qcom,min-sleep-time-secs Usage: optional Value type: <u32> Definition: The minimum sleep time in secs to allow a SOC jump if there has been a GOOD_OCV. - qcom,qg-sys-min-voltage Usage: optional Value type: <u32> Definition: The voltage threshold (in mV) which describes the system minimum voltage as per the hardware recommendation. This is not used for any configuration but only for calculating the available power. If this property is not specified, then the default value used is 2800 mV. ========================================================== Second Level Nodes - Peripherals managed by QGAUGE driver ========================================================== Loading
drivers/power/supply/qcom/qg-core.h +3 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,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 @@ -142,6 +144,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 @@ -1579,6 +1579,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 @@ -1909,6 +1957,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 @@ -1964,6 +2018,8 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_FG_RESET, POWER_SUPPLY_PROP_CC_SOC, 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 @@ -3360,6 +3416,8 @@ static int qg_alg_init(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 @@ -3596,10 +3654,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 @@ -3740,9 +3810,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 @@ -3752,12 +3825,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 @@ -3773,12 +3849,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 @@ -3791,9 +3870,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