Loading drivers/power/supply/power_supply_sysfs.c +1 −0 Original line number Diff line number Diff line Loading @@ -387,6 +387,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(fcc_stepper_enable), POWER_SUPPLY_ATTR(toggle_stat), POWER_SUPPLY_ATTR(main_fcc_max), POWER_SUPPLY_ATTR(fg_reset), /* Charge pump properties */ POWER_SUPPLY_ATTR(cp_status1), POWER_SUPPLY_ATTR(cp_status2), Loading drivers/power/supply/qcom/qg-core.h +1 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,7 @@ struct qpnp_qg { bool parallel_enabled; bool usb_present; bool charge_full; bool force_soc; int charge_status; int charge_type; int chg_iterm_ma; Loading drivers/power/supply/qcom/qg-reg.h +3 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,9 @@ #define QG_INT_LATCHED_STS_REG 0x18 #define FIFO_UPDATE_DONE_INT_LAT_STS_BIT BIT(3) #define QG_STATE_TRIG_CMD_REG 0x40 #define S7_PON_OCV_START BIT(3) #define QG_DATA_CTL1_REG 0x41 #define MASTER_HOLD_OR_CLR_BIT BIT(0) Loading drivers/power/supply/qcom/qpnp-qg.c +95 −2 Original line number Diff line number Diff line Loading @@ -1048,7 +1048,8 @@ static void process_udata_work(struct work_struct *work) chip->catch_up_soc = chip->udata.param[QG_SOC].data; } qg_scale_soc(chip, false); qg_scale_soc(chip, chip->force_soc); chip->force_soc = false; /* update parameters to SDAM */ chip->sdam_data[SDAM_SOC] = chip->msoc; Loading Loading @@ -1631,6 +1632,94 @@ static int qg_ttf_awake_voter(void *data, bool val) return 0; } #define MAX_QG_OK_RETRIES 20 static int qg_reset(struct qpnp_qg *chip) { int rc = 0, count = 0, soc = 0; u32 ocv_uv = 0, ocv_raw = 0; u8 reg = 0; qg_dbg(chip, QG_DEBUG_STATUS, "QG RESET triggered\n"); mutex_lock(&chip->data_lock); /* hold and release master to clear FIFO's */ rc = qg_master_hold(chip, true); if (rc < 0) { pr_err("Failed to hold master, rc=%d\n", rc); goto done; } /* delay for the master-hold */ msleep(20); rc = qg_master_hold(chip, false); if (rc < 0) { pr_err("Failed to release master, rc=%d\n", rc); goto done; } /* delay for master to settle */ msleep(20); qg_get_battery_voltage(chip, &rc); qg_get_battery_capacity(chip, &soc); qg_dbg(chip, QG_DEBUG_STATUS, "VBAT=%duV SOC=%d\n", rc, soc); /* Trigger S7 */ rc = qg_masked_write(chip, chip->qg_base + QG_STATE_TRIG_CMD_REG, S7_PON_OCV_START, S7_PON_OCV_START); if (rc < 0) { pr_err("Failed to trigger S7, rc=%d\n", rc); goto done; } /* poll for QG OK */ do { rc = qg_read(chip, chip->qg_base + QG_STATUS1_REG, ®, 1); if (rc < 0) { pr_err("Failed to read STATUS1_REG rc=%d\n", rc); goto done; } if (reg & QG_OK_BIT) break; msleep(200); count++; } while (count < MAX_QG_OK_RETRIES); if (count == MAX_QG_OK_RETRIES) { qg_dbg(chip, QG_DEBUG_STATUS, "QG_OK not set\n"); goto done; } /* read S7 PON OCV */ rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S7_PON_OCV); if (rc < 0) { pr_err("Failed to read PON OCV rc=%d\n", rc); goto done; } qg_dbg(chip, QG_DEBUG_STATUS, "S7_OCV = %duV\n", ocv_uv); chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; chip->kdata.param[QG_GOOD_OCV_UV].valid = true; /* clear all the userspace data */ chip->kdata.param[QG_CLEAR_LEARNT_DATA].data = 1; chip->kdata.param[QG_CLEAR_LEARNT_DATA].valid = true; vote(chip->awake_votable, GOOD_OCV_VOTER, true, 0); /* signal the read thread */ chip->data_ready = true; chip->force_soc = true; wake_up_interruptible(&chip->qg_wait_q); done: mutex_unlock(&chip->data_lock); return rc; } static int qg_psy_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *pval) Loading Loading @@ -1669,6 +1758,9 @@ static int qg_psy_set_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ESR_NOMINAL: chip->esr_nominal = pval->intval; break; case POWER_SUPPLY_PROP_FG_RESET: qg_reset(chip); break; default: break; } Loading Loading @@ -1793,6 +1885,7 @@ static int qg_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_ESR_ACTUAL: case POWER_SUPPLY_PROP_ESR_NOMINAL: case POWER_SUPPLY_PROP_SOH: case POWER_SUPPLY_PROP_FG_RESET: return 1; default: break; Loading Loading @@ -1827,6 +1920,7 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_ESR_ACTUAL, POWER_SUPPLY_PROP_ESR_NOMINAL, POWER_SUPPLY_PROP_SOH, POWER_SUPPLY_PROP_FG_RESET, }; static const struct power_supply_desc qg_psy_desc = { Loading Loading @@ -1993,7 +2087,6 @@ static int qg_handle_battery_removal(struct qpnp_qg *chip) return rc; } #define MAX_QG_OK_RETRIES 20 static int qg_handle_battery_insertion(struct qpnp_qg *chip) { int rc, count = 0; Loading include/linux/power_supply.h +1 −0 Original line number Diff line number Diff line Loading @@ -312,6 +312,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE, POWER_SUPPLY_PROP_TOGGLE_STAT, POWER_SUPPLY_PROP_MAIN_FCC_MAX, POWER_SUPPLY_PROP_FG_RESET, /* Charge pump properties */ POWER_SUPPLY_PROP_CP_STATUS1, POWER_SUPPLY_PROP_CP_STATUS2, Loading Loading
drivers/power/supply/power_supply_sysfs.c +1 −0 Original line number Diff line number Diff line Loading @@ -387,6 +387,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(fcc_stepper_enable), POWER_SUPPLY_ATTR(toggle_stat), POWER_SUPPLY_ATTR(main_fcc_max), POWER_SUPPLY_ATTR(fg_reset), /* Charge pump properties */ POWER_SUPPLY_ATTR(cp_status1), POWER_SUPPLY_ATTR(cp_status2), Loading
drivers/power/supply/qcom/qg-core.h +1 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,7 @@ struct qpnp_qg { bool parallel_enabled; bool usb_present; bool charge_full; bool force_soc; int charge_status; int charge_type; int chg_iterm_ma; Loading
drivers/power/supply/qcom/qg-reg.h +3 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,9 @@ #define QG_INT_LATCHED_STS_REG 0x18 #define FIFO_UPDATE_DONE_INT_LAT_STS_BIT BIT(3) #define QG_STATE_TRIG_CMD_REG 0x40 #define S7_PON_OCV_START BIT(3) #define QG_DATA_CTL1_REG 0x41 #define MASTER_HOLD_OR_CLR_BIT BIT(0) Loading
drivers/power/supply/qcom/qpnp-qg.c +95 −2 Original line number Diff line number Diff line Loading @@ -1048,7 +1048,8 @@ static void process_udata_work(struct work_struct *work) chip->catch_up_soc = chip->udata.param[QG_SOC].data; } qg_scale_soc(chip, false); qg_scale_soc(chip, chip->force_soc); chip->force_soc = false; /* update parameters to SDAM */ chip->sdam_data[SDAM_SOC] = chip->msoc; Loading Loading @@ -1631,6 +1632,94 @@ static int qg_ttf_awake_voter(void *data, bool val) return 0; } #define MAX_QG_OK_RETRIES 20 static int qg_reset(struct qpnp_qg *chip) { int rc = 0, count = 0, soc = 0; u32 ocv_uv = 0, ocv_raw = 0; u8 reg = 0; qg_dbg(chip, QG_DEBUG_STATUS, "QG RESET triggered\n"); mutex_lock(&chip->data_lock); /* hold and release master to clear FIFO's */ rc = qg_master_hold(chip, true); if (rc < 0) { pr_err("Failed to hold master, rc=%d\n", rc); goto done; } /* delay for the master-hold */ msleep(20); rc = qg_master_hold(chip, false); if (rc < 0) { pr_err("Failed to release master, rc=%d\n", rc); goto done; } /* delay for master to settle */ msleep(20); qg_get_battery_voltage(chip, &rc); qg_get_battery_capacity(chip, &soc); qg_dbg(chip, QG_DEBUG_STATUS, "VBAT=%duV SOC=%d\n", rc, soc); /* Trigger S7 */ rc = qg_masked_write(chip, chip->qg_base + QG_STATE_TRIG_CMD_REG, S7_PON_OCV_START, S7_PON_OCV_START); if (rc < 0) { pr_err("Failed to trigger S7, rc=%d\n", rc); goto done; } /* poll for QG OK */ do { rc = qg_read(chip, chip->qg_base + QG_STATUS1_REG, ®, 1); if (rc < 0) { pr_err("Failed to read STATUS1_REG rc=%d\n", rc); goto done; } if (reg & QG_OK_BIT) break; msleep(200); count++; } while (count < MAX_QG_OK_RETRIES); if (count == MAX_QG_OK_RETRIES) { qg_dbg(chip, QG_DEBUG_STATUS, "QG_OK not set\n"); goto done; } /* read S7 PON OCV */ rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S7_PON_OCV); if (rc < 0) { pr_err("Failed to read PON OCV rc=%d\n", rc); goto done; } qg_dbg(chip, QG_DEBUG_STATUS, "S7_OCV = %duV\n", ocv_uv); chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; chip->kdata.param[QG_GOOD_OCV_UV].valid = true; /* clear all the userspace data */ chip->kdata.param[QG_CLEAR_LEARNT_DATA].data = 1; chip->kdata.param[QG_CLEAR_LEARNT_DATA].valid = true; vote(chip->awake_votable, GOOD_OCV_VOTER, true, 0); /* signal the read thread */ chip->data_ready = true; chip->force_soc = true; wake_up_interruptible(&chip->qg_wait_q); done: mutex_unlock(&chip->data_lock); return rc; } static int qg_psy_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *pval) Loading Loading @@ -1669,6 +1758,9 @@ static int qg_psy_set_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ESR_NOMINAL: chip->esr_nominal = pval->intval; break; case POWER_SUPPLY_PROP_FG_RESET: qg_reset(chip); break; default: break; } Loading Loading @@ -1793,6 +1885,7 @@ static int qg_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_ESR_ACTUAL: case POWER_SUPPLY_PROP_ESR_NOMINAL: case POWER_SUPPLY_PROP_SOH: case POWER_SUPPLY_PROP_FG_RESET: return 1; default: break; Loading Loading @@ -1827,6 +1920,7 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_ESR_ACTUAL, POWER_SUPPLY_PROP_ESR_NOMINAL, POWER_SUPPLY_PROP_SOH, POWER_SUPPLY_PROP_FG_RESET, }; static const struct power_supply_desc qg_psy_desc = { Loading Loading @@ -1993,7 +2087,6 @@ static int qg_handle_battery_removal(struct qpnp_qg *chip) return rc; } #define MAX_QG_OK_RETRIES 20 static int qg_handle_battery_insertion(struct qpnp_qg *chip) { int rc, count = 0; Loading
include/linux/power_supply.h +1 −0 Original line number Diff line number Diff line Loading @@ -312,6 +312,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE, POWER_SUPPLY_PROP_TOGGLE_STAT, POWER_SUPPLY_PROP_MAIN_FCC_MAX, POWER_SUPPLY_PROP_FG_RESET, /* Charge pump properties */ POWER_SUPPLY_PROP_CP_STATUS1, POWER_SUPPLY_PROP_CP_STATUS2, Loading