Loading drivers/power/supply/qcom/battery.c +24 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #define TAPER_END_VOTER "TAPER_END_VOTER" #define PL_TAPER_EARLY_BAD_VOTER "PL_TAPER_EARLY_BAD_VOTER" #define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER" #define PL_HW_ABSENT_VOTER "PL_HW_ABSENT_VOTER" struct pl_data { int pl_mode; Loading @@ -44,6 +45,7 @@ struct pl_data { struct votable *pl_disable_votable; struct votable *pl_awake_votable; struct work_struct status_change_work; struct work_struct pl_disable_forever_work; struct delayed_work pl_taper_work; struct power_supply *main_psy; struct power_supply *pl_psy; Loading Loading @@ -361,6 +363,15 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, return 0; } static void pl_disable_forever_work(struct work_struct *work) { struct pl_data *chip = container_of(work, struct pl_data, pl_disable_forever_work); /* Disable Parallel charger forever */ vote(chip->pl_disable_votable, PL_HW_ABSENT_VOTER, true, 0); } static int pl_disable_vote_callback(struct votable *votable, void *data, int pl_disable, const char *client) { Loading @@ -372,6 +383,18 @@ static int pl_disable_vote_callback(struct votable *votable, chip->taper_pct = 100; if (!pl_disable) { /* enable */ rc = power_supply_get_property(chip->pl_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); if (rc == -ENODEV) { /* * -ENODEV is returned only if parallel chip * is not present in the system. * Disable parallel charger forever. */ schedule_work(&chip->pl_disable_forever_work); return rc; } rerun_election(chip->fv_votable); rerun_election(chip->fcc_votable); /* Loading Loading @@ -697,6 +720,7 @@ static int pl_init(void) INIT_WORK(&chip->status_change_work, status_change_work); INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work); INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work); rc = pl_register_notifier(chip); if (rc < 0) { Loading drivers/power/supply/qcom/qpnp-smb2.c +5 −9 Original line number Diff line number Diff line Loading @@ -385,6 +385,8 @@ static int smb2_parse_dt(struct smb2 *chip) chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb"); chg->dcp_icl_ua = chip->dt.usb_icl_ua; return 0; } Loading Loading @@ -1338,7 +1340,6 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } chg->dcp_icl_ua = chip->dt.usb_icl_ua; chg->boost_threshold_ua = chip->dt.boost_threshold_ua; rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); Loading @@ -1350,13 +1351,10 @@ static int smb2_init_hw(struct smb2 *chip) smblib_rerun_apsd_if_required(chg); /* clear the ICL override if it is set */ if (stat & ICL_OVERRIDE_LATCH_BIT) { rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT); if (rc < 0) { if (smblib_icl_override(chg, false) < 0) { pr_err("Couldn't disable ICL override rc=%d\n", rc); return rc; } } /* votes must be cast before configuring software control */ vote(chg->usb_suspend_votable, Loading @@ -1367,8 +1365,6 @@ static int smb2_init_hw(struct smb2 *chip) DEFAULT_VOTER, true, chip->dt.fcc_ua); vote(chg->fv_votable, DEFAULT_VOTER, true, chip->dt.fv_uv); vote(chg->usb_icl_votable, DCP_VOTER, true, chip->dt.usb_icl_ua); vote(chg->dc_icl_votable, DEFAULT_VOTER, true, chip->dt.dc_icl_ua); vote(chg->hvdcp_disable_votable_indirect, DEFAULT_VOTER, Loading drivers/power/supply/qcom/smb-lib.c +106 −53 Original line number Diff line number Diff line Loading @@ -151,6 +151,31 @@ static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua) return 0; } int smblib_icl_override(struct smb_charger *chg, bool override) { int rc; bool override_status; u8 stat; rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read APSD_RESULT_STATUS_REG rc=%d\n", rc); return rc; } override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT); if (override != override_status) { rc = smblib_masked_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't override ICL rc=%d\n", rc); return rc; } } return 0; } /******************** * REGISTER GETTERS * ********************/ Loading Loading @@ -591,6 +616,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) /* reset both usbin current and voltage votes */ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0); cancel_delayed_work_sync(&chg->hvdcp_detect_work); Loading Loading @@ -728,19 +754,33 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, { struct smb_charger *chg = data; int rc = 0; bool suspend = (icl_ua < USBIN_25MA); bool suspend, override; u8 icl_options = 0; override = true; /* remove override if no voters or type = SDP or CDP */ if (client == NULL || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP) override = false; suspend = false; if (client && (icl_ua < USBIN_25MA)) suspend = true; if (suspend) goto out; if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) { rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua); if (client) { rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc); smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc); return rc; } } goto out; } Loading Loading @@ -769,10 +809,14 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, } out: if (override) icl_options |= USBIN_MODE_CHG_BIT; rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT, icl_options); if (rc < 0) { smblib_err(chg, "Couldn't set ICL opetions rc=%d\n", rc); smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc); return rc; } Loading @@ -783,6 +827,12 @@ out: return rc; } rc = smblib_icl_override(chg, override); if (rc < 0) { smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc); return rc; } return rc; } Loading Loading @@ -1996,11 +2046,11 @@ int smblib_set_prop_usb_current_max(struct smb_charger *chg, true, val->intval); } else if (chg->system_suspend_supported) { if (val->intval <= USBIN_25MA) rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, val->intval); rc = vote(chg->usb_icl_votable, PD_SUSPEND_SUPPORTED_VOTER, true, val->intval); else rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); rc = vote(chg->usb_icl_votable, PD_SUSPEND_SUPPORTED_VOTER, false, 0); } return rc; } Loading Loading @@ -2137,7 +2187,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, "Couldn't enable vconn on CC line rc=%d\n", rc); return rc; } /* * Enforce 500mA for PD until the real vote comes in later. * It is guaranteed that pd_active is set prior to * pd_current_max */ rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); if (rc < 0) { smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", Loading @@ -2145,50 +2199,17 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, return rc; } /* remove DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT); if (rc < 0) { smblib_err(chg, "Couldn't change USB mode rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't override APSD rc=%d\n", rc); return rc; } } else { rc = vote(chg->usb_icl_votable, DCP_VOTER, true, chg->dcp_icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT, 0); if (rc < 0) { smblib_err(chg, "Couldn't override APSD rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, USBIN_MODE_CHG_BIT, 0); /* remove USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't change USB mode rc=%d\n", rc); smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc); return rc; } } Loading Loading @@ -2782,6 +2803,9 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, if (chg->mode == PARALLEL_MASTER) vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0); /* QC authentication done, parallel charger can be enabled now */ vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, false, 0); /* the APSD done handler will set the USB supply type */ apsd_result = smblib_get_apsd_result(chg); smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n", Loading @@ -2791,6 +2815,8 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, bool rising, bool qc_charger) { const struct apsd_result *apsd_result = smblib_update_usb_type(chg); /* Hold off PD only until hvdcp 2.0 detection timeout */ if (rising) { vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, Loading @@ -2798,6 +2824,24 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, if (get_effective_result(chg->pd_disallowed_votable_indirect)) /* could be a legacy cable, try doing hvdcp */ try_rerun_apsd_for_hvdcp(chg); /* * HVDCP detection timeout done * If adapter is not QC2.0/QC3.0 - it is a plain old DCP. */ if (!qc_charger && (apsd_result->bit & DCP_CHARGER_BIT)) /* enforce DCP ICL if specified */ vote(chg->usb_icl_votable, DCP_VOTER, chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua); /* * If adapter is not QC2.0/QC3.0 remove vote for parallel * disable. * Otherwise if adapter is QC2.0/QC3.0 wait for authentication * to complete. */ if (!qc_charger) vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, false, 0); } smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n", Loading Loading @@ -2923,12 +2967,19 @@ static void typec_source_removal(struct smb_charger *chg) /* clear USB ICL vote for PD_VOTER */ rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't un-vote PD from USB ICL rc=%d\n", rc); /* clear USB ICL vote for USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't un-vote USB_PSY from USB ICL rc=%d\n", rc); /* clear USB ICL vote for DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); } static void typec_source_insertion(struct smb_charger *chg) Loading Loading @@ -2957,6 +3008,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0); vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0); vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0); vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0); /* reset votes from vbus_cc_short */ vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, Loading Loading @@ -3514,6 +3566,7 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0); chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY, smblib_usb_suspend_vote_callback, Loading drivers/power/supply/qcom/smb-lib.h +3 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ enum print_reason { #define HVDCP_INDIRECT_VOTER "HVDCP_INDIRECT_VOTER" #define MICRO_USB_VOTER "MICRO_USB_VOTER" #define DEBUG_BOARD_VOTER "DEBUG_BOARD_VOTER" #define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER" #define PL_DISABLE_HVDCP_VOTER "PL_DISABLE_HVDCP_VOTER" #define VCONN_MAX_ATTEMPTS 3 #define OTG_MAX_ATTEMPTS 3 Loading Loading @@ -405,6 +407,7 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg); int smblib_rerun_apsd_if_required(struct smb_charger *chg); int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val); int smblib_icl_override(struct smb_charger *chg, bool override); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading drivers/power/supply/qcom/smb1351-charger.c +93 −65 Original line number Diff line number Diff line Loading @@ -461,7 +461,7 @@ struct smb1351_charger { int parallel_pin_polarity_setting; bool parallel_charger; bool parallel_charger_present; bool parallel_charger_suspended; bool bms_controlled_charging; bool apsd_rerun; bool usbin_ov; Loading Loading @@ -1409,34 +1409,27 @@ static int smb1351_battery_get_property(struct power_supply *psy, static enum power_supply_property smb1351_parallel_properties[] = { POWER_SUPPLY_PROP_CHARGING_ENABLED, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_PARALLEL_MODE, }; static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, int present) static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip, int suspend) { int rc; u8 reg, mask = 0; if (present == chip->parallel_charger_present) { pr_debug("present %d -> %d, skipping\n", chip->parallel_charger_present, present); if (chip->parallel_charger_suspended == suspend) { pr_debug("Skip same state request suspended = %d suspend=%d\n", chip->parallel_charger_suspended, !suspend); return 0; } if (present) { /* Check if SMB1351 is present */ rc = smb1351_read_reg(chip, CHG_REVISION_REG, ®); if (rc) { pr_debug("Failed to detect smb1351-parallel-charger, may be absent\n"); return -ENODEV; } if (!suspend) { rc = smb_chip_get_version(chip); if (rc) { pr_err("Couldn't get version rc = %d\n", rc); Loading Loading @@ -1476,6 +1469,26 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, } } /* control USB suspend via command bits */ rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG, APSD_EN_BIT | SUSPEND_MODE_CTRL_BIT, SUSPEND_MODE_CTRL_BY_I2C); if (rc) { pr_err("Couldn't set USB suspend rc=%d\n", rc); return rc; } /* * When present is being set force USB suspend, start charging * only when POWER_SUPPLY_PROP_CURRENT_MAX is set. */ rc = smb1351_usb_suspend(chip, CURRENT, true); if (rc) { pr_err("failed to suspend rc=%d\n", rc); return rc; } chip->usb_psy_ma = SUSPEND_CURRENT_MA; /* set chg en by pin active low */ reg = chip->parallel_pin_polarity_setting | USBCS_CTRL_BY_I2C; rc = smb1351_masked_write(chip, CHG_PIN_EN_CTRL_REG, Loading @@ -1485,15 +1498,6 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, return rc; } /* control USB suspend via command bits */ rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG, SUSPEND_MODE_CTRL_BIT, SUSPEND_MODE_CTRL_BY_I2C); if (rc) { pr_err("Couldn't set USB suspend rc=%d\n", rc); return rc; } /* * setup USB 2.0/3.0 detection and USB 500/100 * command polarity Loading @@ -1508,23 +1512,21 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, return rc; } /* set fast charging current limit */ chip->target_fastchg_current_max_ma = SMB1351_CHG_FAST_MIN_MA; rc = smb1351_fastchg_current_set(chip, chip->target_fastchg_current_max_ma); if (rc) { pr_err("Couldn't set fastchg current rc=%d\n", rc); return rc; } } chip->parallel_charger_suspended = false; } else { rc = smb1351_usb_suspend(chip, CURRENT, true); if (rc) pr_debug("failed to suspend rc=%d\n", rc); chip->parallel_charger_present = present; /* * When present is being set force USB suspend, start charging * only when POWER_SUPPLY_PROP_CURRENT_MAX is set. */ chip->usb_psy_ma = SUSPEND_CURRENT_MA; smb1351_usb_suspend(chip, CURRENT, true); chip->parallel_charger_suspended = true; } return 0; } Loading Loading @@ -1564,6 +1566,31 @@ static bool smb1351_is_input_current_limited(struct smb1351_charger *chip) return !!(reg & IRQ_IC_LIMIT_STATUS_BIT); } static bool smb1351_is_usb_present(struct smb1351_charger *chip) { int rc; union power_supply_propval val = {0, }; if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (!chip->usb_psy) { pr_err("USB psy not found\n"); return false; } rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_ONLINE, &val); if (rc < 0) { pr_err("Failed to get present property rc=%d\n", rc); return false; } if (val.intval) return true; return false; } static int smb1351_parallel_set_property(struct power_supply *psy, enum power_supply_property prop, const union power_supply_propval *val) Loading @@ -1577,38 +1604,30 @@ static int smb1351_parallel_set_property(struct power_supply *psy, *CHG EN is controlled by pin in the parallel charging. *Use suspend if disable charging by command. */ if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) rc = smb1351_usb_suspend(chip, USER, !val->intval); break; case POWER_SUPPLY_PROP_PRESENT: rc = smb1351_parallel_set_chg_present(chip, val->intval); case POWER_SUPPLY_PROP_INPUT_SUSPEND: rc = smb1351_parallel_set_chg_suspend(chip, val->intval); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: if (chip->parallel_charger_present) { chip->target_fastchg_current_max_ma = val->intval / 1000; if (!chip->parallel_charger_suspended) rc = smb1351_fastchg_current_set(chip, chip->target_fastchg_current_max_ma); } break; case POWER_SUPPLY_PROP_CURRENT_MAX: if (chip->parallel_charger_present) { index = smb1351_get_closest_usb_setpoint( val->intval / 1000); index = smb1351_get_closest_usb_setpoint(val->intval / 1000); chip->usb_psy_ma = usb_chg_current[index]; if (!chip->parallel_charger_suspended) rc = smb1351_set_usb_chg_current(chip, chip->usb_psy_ma); } break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: if (chip->parallel_charger_present && (chip->vfloat_mv != val->intval)) { chip->vfloat_mv = val->intval / 1000; if (!chip->parallel_charger_suspended) rc = smb1351_float_voltage_set(chip, val->intval); if (!rc) chip->vfloat_mv = val->intval; } else { chip->vfloat_mv = val->intval; } break; default: return -EINVAL; Loading Loading @@ -1638,41 +1657,49 @@ static int smb1351_parallel_get_property(struct power_supply *psy, val->intval = !chip->usb_suspended_status; break; case POWER_SUPPLY_PROP_CURRENT_MAX: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = chip->usb_psy_ma * 1000; else val->intval = 0; break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: if (!chip->parallel_charger_suspended) val->intval = chip->vfloat_mv; else val->intval = 0; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = chip->parallel_charger_present; case POWER_SUPPLY_PROP_CHARGE_TYPE: val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; /* Check if SMB1351 is present */ if (smb1351_is_usb_present(chip)) { val->intval = smb1351_get_prop_charge_type(chip); if (val->intval == POWER_SUPPLY_CHARGE_TYPE_UNKNOWN) { pr_debug("Failed to charge type, charger may be absent\n"); return -ENODEV; } } break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = chip->fastchg_current_max_ma * 1000; else val->intval = 0; break; case POWER_SUPPLY_PROP_STATUS: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = smb1351_get_prop_batt_status(chip); else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = smb1351_is_input_current_limited(chip) ? 1 : 0; else val->intval = 0; break; case POWER_SUPPLY_PROP_PARALLEL_MODE: if (chip->parallel_charger_present) val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN; else val->intval = POWER_SUPPLY_PARALLEL_NONE; break; default: return -EINVAL; Loading Loading @@ -3142,6 +3169,7 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client, chip->client = client; chip->dev = &client->dev; chip->parallel_charger = true; chip->parallel_charger_suspended = true; chip->usb_suspended_status = of_property_read_bool(node, "qcom,charging-disabled"); Loading Loading
drivers/power/supply/qcom/battery.c +24 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #define TAPER_END_VOTER "TAPER_END_VOTER" #define PL_TAPER_EARLY_BAD_VOTER "PL_TAPER_EARLY_BAD_VOTER" #define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER" #define PL_HW_ABSENT_VOTER "PL_HW_ABSENT_VOTER" struct pl_data { int pl_mode; Loading @@ -44,6 +45,7 @@ struct pl_data { struct votable *pl_disable_votable; struct votable *pl_awake_votable; struct work_struct status_change_work; struct work_struct pl_disable_forever_work; struct delayed_work pl_taper_work; struct power_supply *main_psy; struct power_supply *pl_psy; Loading Loading @@ -361,6 +363,15 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, return 0; } static void pl_disable_forever_work(struct work_struct *work) { struct pl_data *chip = container_of(work, struct pl_data, pl_disable_forever_work); /* Disable Parallel charger forever */ vote(chip->pl_disable_votable, PL_HW_ABSENT_VOTER, true, 0); } static int pl_disable_vote_callback(struct votable *votable, void *data, int pl_disable, const char *client) { Loading @@ -372,6 +383,18 @@ static int pl_disable_vote_callback(struct votable *votable, chip->taper_pct = 100; if (!pl_disable) { /* enable */ rc = power_supply_get_property(chip->pl_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); if (rc == -ENODEV) { /* * -ENODEV is returned only if parallel chip * is not present in the system. * Disable parallel charger forever. */ schedule_work(&chip->pl_disable_forever_work); return rc; } rerun_election(chip->fv_votable); rerun_election(chip->fcc_votable); /* Loading Loading @@ -697,6 +720,7 @@ static int pl_init(void) INIT_WORK(&chip->status_change_work, status_change_work); INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work); INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work); rc = pl_register_notifier(chip); if (rc < 0) { Loading
drivers/power/supply/qcom/qpnp-smb2.c +5 −9 Original line number Diff line number Diff line Loading @@ -385,6 +385,8 @@ static int smb2_parse_dt(struct smb2 *chip) chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb"); chg->dcp_icl_ua = chip->dt.usb_icl_ua; return 0; } Loading Loading @@ -1338,7 +1340,6 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } chg->dcp_icl_ua = chip->dt.usb_icl_ua; chg->boost_threshold_ua = chip->dt.boost_threshold_ua; rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); Loading @@ -1350,13 +1351,10 @@ static int smb2_init_hw(struct smb2 *chip) smblib_rerun_apsd_if_required(chg); /* clear the ICL override if it is set */ if (stat & ICL_OVERRIDE_LATCH_BIT) { rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT); if (rc < 0) { if (smblib_icl_override(chg, false) < 0) { pr_err("Couldn't disable ICL override rc=%d\n", rc); return rc; } } /* votes must be cast before configuring software control */ vote(chg->usb_suspend_votable, Loading @@ -1367,8 +1365,6 @@ static int smb2_init_hw(struct smb2 *chip) DEFAULT_VOTER, true, chip->dt.fcc_ua); vote(chg->fv_votable, DEFAULT_VOTER, true, chip->dt.fv_uv); vote(chg->usb_icl_votable, DCP_VOTER, true, chip->dt.usb_icl_ua); vote(chg->dc_icl_votable, DEFAULT_VOTER, true, chip->dt.dc_icl_ua); vote(chg->hvdcp_disable_votable_indirect, DEFAULT_VOTER, Loading
drivers/power/supply/qcom/smb-lib.c +106 −53 Original line number Diff line number Diff line Loading @@ -151,6 +151,31 @@ static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua) return 0; } int smblib_icl_override(struct smb_charger *chg, bool override) { int rc; bool override_status; u8 stat; rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read APSD_RESULT_STATUS_REG rc=%d\n", rc); return rc; } override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT); if (override != override_status) { rc = smblib_masked_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't override ICL rc=%d\n", rc); return rc; } } return 0; } /******************** * REGISTER GETTERS * ********************/ Loading Loading @@ -591,6 +616,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) /* reset both usbin current and voltage votes */ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0); cancel_delayed_work_sync(&chg->hvdcp_detect_work); Loading Loading @@ -728,19 +754,33 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, { struct smb_charger *chg = data; int rc = 0; bool suspend = (icl_ua < USBIN_25MA); bool suspend, override; u8 icl_options = 0; override = true; /* remove override if no voters or type = SDP or CDP */ if (client == NULL || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP) override = false; suspend = false; if (client && (icl_ua < USBIN_25MA)) suspend = true; if (suspend) goto out; if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) { rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua); if (client) { rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc); smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc); return rc; } } goto out; } Loading Loading @@ -769,10 +809,14 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, } out: if (override) icl_options |= USBIN_MODE_CHG_BIT; rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT, icl_options); if (rc < 0) { smblib_err(chg, "Couldn't set ICL opetions rc=%d\n", rc); smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc); return rc; } Loading @@ -783,6 +827,12 @@ out: return rc; } rc = smblib_icl_override(chg, override); if (rc < 0) { smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc); return rc; } return rc; } Loading Loading @@ -1996,11 +2046,11 @@ int smblib_set_prop_usb_current_max(struct smb_charger *chg, true, val->intval); } else if (chg->system_suspend_supported) { if (val->intval <= USBIN_25MA) rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, val->intval); rc = vote(chg->usb_icl_votable, PD_SUSPEND_SUPPORTED_VOTER, true, val->intval); else rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); rc = vote(chg->usb_icl_votable, PD_SUSPEND_SUPPORTED_VOTER, false, 0); } return rc; } Loading Loading @@ -2137,7 +2187,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, "Couldn't enable vconn on CC line rc=%d\n", rc); return rc; } /* * Enforce 500mA for PD until the real vote comes in later. * It is guaranteed that pd_active is set prior to * pd_current_max */ rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); if (rc < 0) { smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", Loading @@ -2145,50 +2199,17 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, return rc; } /* remove DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT); if (rc < 0) { smblib_err(chg, "Couldn't change USB mode rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't override APSD rc=%d\n", rc); return rc; } } else { rc = vote(chg->usb_icl_votable, DCP_VOTER, true, chg->dcp_icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT, 0); if (rc < 0) { smblib_err(chg, "Couldn't override APSD rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, USBIN_MODE_CHG_BIT, 0); /* remove USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't change USB mode rc=%d\n", rc); smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc); return rc; } } Loading Loading @@ -2782,6 +2803,9 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, if (chg->mode == PARALLEL_MASTER) vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0); /* QC authentication done, parallel charger can be enabled now */ vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, false, 0); /* the APSD done handler will set the USB supply type */ apsd_result = smblib_get_apsd_result(chg); smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n", Loading @@ -2791,6 +2815,8 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, bool rising, bool qc_charger) { const struct apsd_result *apsd_result = smblib_update_usb_type(chg); /* Hold off PD only until hvdcp 2.0 detection timeout */ if (rising) { vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, Loading @@ -2798,6 +2824,24 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, if (get_effective_result(chg->pd_disallowed_votable_indirect)) /* could be a legacy cable, try doing hvdcp */ try_rerun_apsd_for_hvdcp(chg); /* * HVDCP detection timeout done * If adapter is not QC2.0/QC3.0 - it is a plain old DCP. */ if (!qc_charger && (apsd_result->bit & DCP_CHARGER_BIT)) /* enforce DCP ICL if specified */ vote(chg->usb_icl_votable, DCP_VOTER, chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua); /* * If adapter is not QC2.0/QC3.0 remove vote for parallel * disable. * Otherwise if adapter is QC2.0/QC3.0 wait for authentication * to complete. */ if (!qc_charger) vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, false, 0); } smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n", Loading Loading @@ -2923,12 +2967,19 @@ static void typec_source_removal(struct smb_charger *chg) /* clear USB ICL vote for PD_VOTER */ rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't un-vote PD from USB ICL rc=%d\n", rc); /* clear USB ICL vote for USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't un-vote USB_PSY from USB ICL rc=%d\n", rc); /* clear USB ICL vote for DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); } static void typec_source_insertion(struct smb_charger *chg) Loading Loading @@ -2957,6 +3008,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0); vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0); vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0); vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0); /* reset votes from vbus_cc_short */ vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, Loading Loading @@ -3514,6 +3566,7 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0); chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY, smblib_usb_suspend_vote_callback, Loading
drivers/power/supply/qcom/smb-lib.h +3 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ enum print_reason { #define HVDCP_INDIRECT_VOTER "HVDCP_INDIRECT_VOTER" #define MICRO_USB_VOTER "MICRO_USB_VOTER" #define DEBUG_BOARD_VOTER "DEBUG_BOARD_VOTER" #define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER" #define PL_DISABLE_HVDCP_VOTER "PL_DISABLE_HVDCP_VOTER" #define VCONN_MAX_ATTEMPTS 3 #define OTG_MAX_ATTEMPTS 3 Loading Loading @@ -405,6 +407,7 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg); int smblib_rerun_apsd_if_required(struct smb_charger *chg); int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val); int smblib_icl_override(struct smb_charger *chg, bool override); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading
drivers/power/supply/qcom/smb1351-charger.c +93 −65 Original line number Diff line number Diff line Loading @@ -461,7 +461,7 @@ struct smb1351_charger { int parallel_pin_polarity_setting; bool parallel_charger; bool parallel_charger_present; bool parallel_charger_suspended; bool bms_controlled_charging; bool apsd_rerun; bool usbin_ov; Loading Loading @@ -1409,34 +1409,27 @@ static int smb1351_battery_get_property(struct power_supply *psy, static enum power_supply_property smb1351_parallel_properties[] = { POWER_SUPPLY_PROP_CHARGING_ENABLED, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_PARALLEL_MODE, }; static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, int present) static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip, int suspend) { int rc; u8 reg, mask = 0; if (present == chip->parallel_charger_present) { pr_debug("present %d -> %d, skipping\n", chip->parallel_charger_present, present); if (chip->parallel_charger_suspended == suspend) { pr_debug("Skip same state request suspended = %d suspend=%d\n", chip->parallel_charger_suspended, !suspend); return 0; } if (present) { /* Check if SMB1351 is present */ rc = smb1351_read_reg(chip, CHG_REVISION_REG, ®); if (rc) { pr_debug("Failed to detect smb1351-parallel-charger, may be absent\n"); return -ENODEV; } if (!suspend) { rc = smb_chip_get_version(chip); if (rc) { pr_err("Couldn't get version rc = %d\n", rc); Loading Loading @@ -1476,6 +1469,26 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, } } /* control USB suspend via command bits */ rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG, APSD_EN_BIT | SUSPEND_MODE_CTRL_BIT, SUSPEND_MODE_CTRL_BY_I2C); if (rc) { pr_err("Couldn't set USB suspend rc=%d\n", rc); return rc; } /* * When present is being set force USB suspend, start charging * only when POWER_SUPPLY_PROP_CURRENT_MAX is set. */ rc = smb1351_usb_suspend(chip, CURRENT, true); if (rc) { pr_err("failed to suspend rc=%d\n", rc); return rc; } chip->usb_psy_ma = SUSPEND_CURRENT_MA; /* set chg en by pin active low */ reg = chip->parallel_pin_polarity_setting | USBCS_CTRL_BY_I2C; rc = smb1351_masked_write(chip, CHG_PIN_EN_CTRL_REG, Loading @@ -1485,15 +1498,6 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, return rc; } /* control USB suspend via command bits */ rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG, SUSPEND_MODE_CTRL_BIT, SUSPEND_MODE_CTRL_BY_I2C); if (rc) { pr_err("Couldn't set USB suspend rc=%d\n", rc); return rc; } /* * setup USB 2.0/3.0 detection and USB 500/100 * command polarity Loading @@ -1508,23 +1512,21 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, return rc; } /* set fast charging current limit */ chip->target_fastchg_current_max_ma = SMB1351_CHG_FAST_MIN_MA; rc = smb1351_fastchg_current_set(chip, chip->target_fastchg_current_max_ma); if (rc) { pr_err("Couldn't set fastchg current rc=%d\n", rc); return rc; } } chip->parallel_charger_suspended = false; } else { rc = smb1351_usb_suspend(chip, CURRENT, true); if (rc) pr_debug("failed to suspend rc=%d\n", rc); chip->parallel_charger_present = present; /* * When present is being set force USB suspend, start charging * only when POWER_SUPPLY_PROP_CURRENT_MAX is set. */ chip->usb_psy_ma = SUSPEND_CURRENT_MA; smb1351_usb_suspend(chip, CURRENT, true); chip->parallel_charger_suspended = true; } return 0; } Loading Loading @@ -1564,6 +1566,31 @@ static bool smb1351_is_input_current_limited(struct smb1351_charger *chip) return !!(reg & IRQ_IC_LIMIT_STATUS_BIT); } static bool smb1351_is_usb_present(struct smb1351_charger *chip) { int rc; union power_supply_propval val = {0, }; if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (!chip->usb_psy) { pr_err("USB psy not found\n"); return false; } rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_ONLINE, &val); if (rc < 0) { pr_err("Failed to get present property rc=%d\n", rc); return false; } if (val.intval) return true; return false; } static int smb1351_parallel_set_property(struct power_supply *psy, enum power_supply_property prop, const union power_supply_propval *val) Loading @@ -1577,38 +1604,30 @@ static int smb1351_parallel_set_property(struct power_supply *psy, *CHG EN is controlled by pin in the parallel charging. *Use suspend if disable charging by command. */ if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) rc = smb1351_usb_suspend(chip, USER, !val->intval); break; case POWER_SUPPLY_PROP_PRESENT: rc = smb1351_parallel_set_chg_present(chip, val->intval); case POWER_SUPPLY_PROP_INPUT_SUSPEND: rc = smb1351_parallel_set_chg_suspend(chip, val->intval); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: if (chip->parallel_charger_present) { chip->target_fastchg_current_max_ma = val->intval / 1000; if (!chip->parallel_charger_suspended) rc = smb1351_fastchg_current_set(chip, chip->target_fastchg_current_max_ma); } break; case POWER_SUPPLY_PROP_CURRENT_MAX: if (chip->parallel_charger_present) { index = smb1351_get_closest_usb_setpoint( val->intval / 1000); index = smb1351_get_closest_usb_setpoint(val->intval / 1000); chip->usb_psy_ma = usb_chg_current[index]; if (!chip->parallel_charger_suspended) rc = smb1351_set_usb_chg_current(chip, chip->usb_psy_ma); } break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: if (chip->parallel_charger_present && (chip->vfloat_mv != val->intval)) { chip->vfloat_mv = val->intval / 1000; if (!chip->parallel_charger_suspended) rc = smb1351_float_voltage_set(chip, val->intval); if (!rc) chip->vfloat_mv = val->intval; } else { chip->vfloat_mv = val->intval; } break; default: return -EINVAL; Loading Loading @@ -1638,41 +1657,49 @@ static int smb1351_parallel_get_property(struct power_supply *psy, val->intval = !chip->usb_suspended_status; break; case POWER_SUPPLY_PROP_CURRENT_MAX: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = chip->usb_psy_ma * 1000; else val->intval = 0; break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: if (!chip->parallel_charger_suspended) val->intval = chip->vfloat_mv; else val->intval = 0; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = chip->parallel_charger_present; case POWER_SUPPLY_PROP_CHARGE_TYPE: val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; /* Check if SMB1351 is present */ if (smb1351_is_usb_present(chip)) { val->intval = smb1351_get_prop_charge_type(chip); if (val->intval == POWER_SUPPLY_CHARGE_TYPE_UNKNOWN) { pr_debug("Failed to charge type, charger may be absent\n"); return -ENODEV; } } break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = chip->fastchg_current_max_ma * 1000; else val->intval = 0; break; case POWER_SUPPLY_PROP_STATUS: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = smb1351_get_prop_batt_status(chip); else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended) val->intval = smb1351_is_input_current_limited(chip) ? 1 : 0; else val->intval = 0; break; case POWER_SUPPLY_PROP_PARALLEL_MODE: if (chip->parallel_charger_present) val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN; else val->intval = POWER_SUPPLY_PARALLEL_NONE; break; default: return -EINVAL; Loading Loading @@ -3142,6 +3169,7 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client, chip->client = client; chip->dev = &client->dev; chip->parallel_charger = true; chip->parallel_charger_suspended = true; chip->usb_suspended_status = of_property_read_bool(node, "qcom,charging-disabled"); Loading