Loading drivers/power/qpnp-smb2.c +2 −0 Original line number Diff line number Diff line Loading @@ -1423,6 +1423,7 @@ static int smb2_determine_initial_status(struct smb2 *chip) smblib_handle_usb_source_change(0, &irq_data); smblib_handle_chg_state_change(0, &irq_data); smblib_handle_icl_change(0, &irq_data); smblib_handle_batt_temp_changed(0, &irq_data); return 0; } Loading Loading @@ -1485,6 +1486,7 @@ static struct smb_irq_info smb2_irqs[] = { .name = "bat-temp", .handler = smblib_handle_batt_temp_changed, .flags = IRQ_TYPE_EDGE_RISING, .wake = true, }, [BATT_OCP_IRQ] = { .name = "bat-ocp", Loading drivers/power/smb-lib.c +130 −38 Original line number Diff line number Diff line Loading @@ -1293,37 +1293,35 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) #define MAX_RETRY 15 #define MIN_DELAY_US 2000 #define MAX_DELAY_US 9000 static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) static int otg_current[] = {250000, 500000, 1000000, 1500000}; static int smblib_enable_otg_wa(struct smb_charger *chg) { struct smb_charger *chg = rdev_get_drvdata(rdev); int rc, retry_count = 0, min_delay = MIN_DELAY_US; u8 stat; int rc, i, retry_count = 0, min_delay = MIN_DELAY_US; smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, ENG_BUCKBOOST_HALT1_8_MODE_BIT); for (i = 0; i < ARRAY_SIZE(otg_current); i++) { smblib_dbg(chg, PR_OTG, "enabling OTG with %duA\n", otg_current[i]); rc = smblib_set_charge_param(chg, &chg->param.otg_cl, otg_current[i]); if (rc < 0) { smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", rc); smblib_err(chg, "Couldn't set otg limit rc=%d\n", rc); return rc; } smblib_dbg(chg, PR_OTG, "enabling OTG\n"); rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); if (rc < 0) { smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc); smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); return rc; } if (chg->wa_flags & OTG_WA) { /* check for softstart */ retry_count = 0; min_delay = MIN_DELAY_US; do { usleep_range(min_delay, min_delay + 100); rc = smblib_read(chg, OTG_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read OTG status rc=%d\n", smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc); goto out; } Loading @@ -1331,30 +1329,74 @@ static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) if (stat & BOOST_SOFTSTART_DONE_BIT) { rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua); if (rc < 0) smblib_err(chg, "Couldn't set otg limit\n"); if (rc < 0) { smblib_err(chg, "Couldn't set otg limit rc=%d\n", rc); goto out; } break; } /* increase the delay for following iterations */ if (retry_count > 5) min_delay = MAX_DELAY_US; } while (retry_count++ < MAX_RETRY); if (retry_count >= MAX_RETRY) { smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n"); smblib_dbg(chg, PR_OTG, "OTG enable failed with %duA\n", otg_current[i]); rc = smblib_write(chg, CMD_OTG_REG, 0); if (rc < 0) { smblib_err(chg, "disable OTG rc=%d\n", rc); goto out; } } else { smblib_dbg(chg, PR_OTG, "OTG enabled\n"); return 0; } } if (i == ARRAY_SIZE(otg_current)) { rc = -EINVAL; goto out; } return 0; out: /* disable OTG if softstart failed */ smblib_write(chg, CMD_OTG_REG, 0); return rc; } static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); int rc; smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, ENG_BUCKBOOST_HALT1_8_MODE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", rc); return rc; } smblib_dbg(chg, PR_OTG, "enabling OTG\n"); if (chg->wa_flags & OTG_WA) { rc = smblib_enable_otg_wa(chg); if (rc < 0) smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); } else { rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); if (rc < 0) smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); } return rc; } int smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); Loading Loading @@ -2299,16 +2341,9 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg, int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, union power_supply_propval *val) { const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); int rc, pulses; val->intval = MICRO_5V; if (apsd_result == NULL) { smblib_err(chg, "APSD result is NULL\n"); return 0; } switch (apsd_result->pst) { switch (chg->real_charger_type) { case POWER_SUPPLY_TYPE_USB_HVDCP_3: rc = smblib_get_pulse_cnt(chg, &pulses); if (rc < 0) { Loading @@ -2318,6 +2353,9 @@ int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, } val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses; break; case POWER_SUPPLY_TYPE_USB_PD: val->intval = chg->voltage_min_uv; break; default: val->intval = MICRO_5V; break; Loading Loading @@ -2564,6 +2602,7 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg, } chg->voltage_min_uv = min_uv; power_supply_changed(&chg->usb_main_psy); return rc; } Loading Loading @@ -2848,6 +2887,51 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, return rc; } static int smblib_recover_from_soft_jeita(struct smb_charger *chg) { u8 stat_1 = 0, stat_2 = 0; int rc; rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat_1); if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", rc); return rc; } rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat_2); if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n", rc); return rc; } if ((chg->jeita_status && !(stat_2 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK) && ((stat_1 & BATTERY_CHARGER_STATUS_MASK) == TERMINATE_CHARGE))) { /* * We are moving from JEITA soft -> Normal and charging * is terminated */ rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, 0); if (rc < 0) { smblib_err(chg, "Couldn't disable charging rc=%d\n", rc); return rc; } rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, CHARGING_ENABLE_CMD_BIT); if (rc < 0) { smblib_err(chg, "Couldn't enable charging rc=%d\n", rc); return rc; } } chg->jeita_status = stat_2 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK; return 0; } /*********************** * USB MAIN PSY GETTERS * *************************/ Loading Loading @@ -3040,6 +3124,14 @@ irqreturn_t smblib_handle_batt_temp_changed(int irq, void *data) { struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; int rc; rc = smblib_recover_from_soft_jeita(chg); if (rc < 0) { smblib_err(chg, "Couldn't recover chg from soft jeita rc=%d\n", rc); return IRQ_HANDLED; } rerun_election(chg->fcc_votable); power_supply_changed(&chg->batt_psy); Loading drivers/power/smb-lib.h +1 −0 Original line number Diff line number Diff line Loading @@ -317,6 +317,7 @@ struct smb_charger { int typec_mode; int usb_icl_change_irq_enabled; bool skip_usb_notification; u32 jeita_status; /* workaround flag */ u32 wa_flags; Loading Loading
drivers/power/qpnp-smb2.c +2 −0 Original line number Diff line number Diff line Loading @@ -1423,6 +1423,7 @@ static int smb2_determine_initial_status(struct smb2 *chip) smblib_handle_usb_source_change(0, &irq_data); smblib_handle_chg_state_change(0, &irq_data); smblib_handle_icl_change(0, &irq_data); smblib_handle_batt_temp_changed(0, &irq_data); return 0; } Loading Loading @@ -1485,6 +1486,7 @@ static struct smb_irq_info smb2_irqs[] = { .name = "bat-temp", .handler = smblib_handle_batt_temp_changed, .flags = IRQ_TYPE_EDGE_RISING, .wake = true, }, [BATT_OCP_IRQ] = { .name = "bat-ocp", Loading
drivers/power/smb-lib.c +130 −38 Original line number Diff line number Diff line Loading @@ -1293,37 +1293,35 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) #define MAX_RETRY 15 #define MIN_DELAY_US 2000 #define MAX_DELAY_US 9000 static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) static int otg_current[] = {250000, 500000, 1000000, 1500000}; static int smblib_enable_otg_wa(struct smb_charger *chg) { struct smb_charger *chg = rdev_get_drvdata(rdev); int rc, retry_count = 0, min_delay = MIN_DELAY_US; u8 stat; int rc, i, retry_count = 0, min_delay = MIN_DELAY_US; smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, ENG_BUCKBOOST_HALT1_8_MODE_BIT); for (i = 0; i < ARRAY_SIZE(otg_current); i++) { smblib_dbg(chg, PR_OTG, "enabling OTG with %duA\n", otg_current[i]); rc = smblib_set_charge_param(chg, &chg->param.otg_cl, otg_current[i]); if (rc < 0) { smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", rc); smblib_err(chg, "Couldn't set otg limit rc=%d\n", rc); return rc; } smblib_dbg(chg, PR_OTG, "enabling OTG\n"); rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); if (rc < 0) { smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc); smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); return rc; } if (chg->wa_flags & OTG_WA) { /* check for softstart */ retry_count = 0; min_delay = MIN_DELAY_US; do { usleep_range(min_delay, min_delay + 100); rc = smblib_read(chg, OTG_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read OTG status rc=%d\n", smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc); goto out; } Loading @@ -1331,30 +1329,74 @@ static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) if (stat & BOOST_SOFTSTART_DONE_BIT) { rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua); if (rc < 0) smblib_err(chg, "Couldn't set otg limit\n"); if (rc < 0) { smblib_err(chg, "Couldn't set otg limit rc=%d\n", rc); goto out; } break; } /* increase the delay for following iterations */ if (retry_count > 5) min_delay = MAX_DELAY_US; } while (retry_count++ < MAX_RETRY); if (retry_count >= MAX_RETRY) { smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n"); smblib_dbg(chg, PR_OTG, "OTG enable failed with %duA\n", otg_current[i]); rc = smblib_write(chg, CMD_OTG_REG, 0); if (rc < 0) { smblib_err(chg, "disable OTG rc=%d\n", rc); goto out; } } else { smblib_dbg(chg, PR_OTG, "OTG enabled\n"); return 0; } } if (i == ARRAY_SIZE(otg_current)) { rc = -EINVAL; goto out; } return 0; out: /* disable OTG if softstart failed */ smblib_write(chg, CMD_OTG_REG, 0); return rc; } static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); int rc; smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, ENG_BUCKBOOST_HALT1_8_MODE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", rc); return rc; } smblib_dbg(chg, PR_OTG, "enabling OTG\n"); if (chg->wa_flags & OTG_WA) { rc = smblib_enable_otg_wa(chg); if (rc < 0) smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); } else { rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); if (rc < 0) smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); } return rc; } int smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); Loading Loading @@ -2299,16 +2341,9 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg, int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, union power_supply_propval *val) { const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); int rc, pulses; val->intval = MICRO_5V; if (apsd_result == NULL) { smblib_err(chg, "APSD result is NULL\n"); return 0; } switch (apsd_result->pst) { switch (chg->real_charger_type) { case POWER_SUPPLY_TYPE_USB_HVDCP_3: rc = smblib_get_pulse_cnt(chg, &pulses); if (rc < 0) { Loading @@ -2318,6 +2353,9 @@ int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, } val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses; break; case POWER_SUPPLY_TYPE_USB_PD: val->intval = chg->voltage_min_uv; break; default: val->intval = MICRO_5V; break; Loading Loading @@ -2564,6 +2602,7 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg, } chg->voltage_min_uv = min_uv; power_supply_changed(&chg->usb_main_psy); return rc; } Loading Loading @@ -2848,6 +2887,51 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, return rc; } static int smblib_recover_from_soft_jeita(struct smb_charger *chg) { u8 stat_1 = 0, stat_2 = 0; int rc; rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat_1); if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", rc); return rc; } rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat_2); if (rc < 0) { smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n", rc); return rc; } if ((chg->jeita_status && !(stat_2 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK) && ((stat_1 & BATTERY_CHARGER_STATUS_MASK) == TERMINATE_CHARGE))) { /* * We are moving from JEITA soft -> Normal and charging * is terminated */ rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, 0); if (rc < 0) { smblib_err(chg, "Couldn't disable charging rc=%d\n", rc); return rc; } rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, CHARGING_ENABLE_CMD_BIT); if (rc < 0) { smblib_err(chg, "Couldn't enable charging rc=%d\n", rc); return rc; } } chg->jeita_status = stat_2 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK; return 0; } /*********************** * USB MAIN PSY GETTERS * *************************/ Loading Loading @@ -3040,6 +3124,14 @@ irqreturn_t smblib_handle_batt_temp_changed(int irq, void *data) { struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; int rc; rc = smblib_recover_from_soft_jeita(chg); if (rc < 0) { smblib_err(chg, "Couldn't recover chg from soft jeita rc=%d\n", rc); return IRQ_HANDLED; } rerun_election(chg->fcc_votable); power_supply_changed(&chg->batt_psy); Loading
drivers/power/smb-lib.h +1 −0 Original line number Diff line number Diff line Loading @@ -317,6 +317,7 @@ struct smb_charger { int typec_mode; int usb_icl_change_irq_enabled; bool skip_usb_notification; u32 jeita_status; /* workaround flag */ u32 wa_flags; Loading