Loading drivers/power/supply/qcom/qpnp-smblite.c +55 −3 Original line number Diff line number Diff line Loading @@ -183,11 +183,12 @@ ATTRIBUTE_GROUPS(smblite); static int smblite_chg_config_init(struct smblite *chip) { struct smb_charger *chg = &chip->chg; int subtype = (u8)of_device_get_match_data(chg->dev); u8 val; int rc = 0; switch (subtype) { chg->subtype = (u8)of_device_get_match_data(chg->dev); switch (chg->subtype) { case PM2250: chg->wa_flags |= WEAK_ADAPTER_WA; chg->base = smb_base[PM2250]; Loading @@ -209,7 +210,7 @@ static int smblite_chg_config_init(struct smblite *chip) chg->name = "PM5100_charger"; break; default: pr_err("Unsupported PMIC subtype=%d\n", subtype); pr_err("Unsupported PMIC subtype=%d\n", chg->subtype); return -EINVAL; } Loading Loading @@ -302,6 +303,9 @@ static int smblite_parse_dt_misc(struct smblite *chip, struct device_node *node) if (chg->chg_param.fcc_step_size_ua <= 0) chg->chg_param.fcc_step_size_ua = DEFAULT_FCC_STEP_SIZE_UA; chg->concurrent_mode_supported = of_property_read_bool(node, "qcom,concurrency-mode-supported"); return 0; } Loading Loading @@ -771,6 +775,41 @@ static int smblite_init_batt_psy(struct smblite *chip) return rc; } /******************* * QCOM SMB Class * *******************/ static ssize_t boost_concurrent_mode_store(struct class *c, struct class_attribute *attr, const char *buf, size_t count) { struct smb_charger *chg = container_of(c, struct smb_charger, qcom_class); int rc; bool val; if (kstrtobool(buf, &val)) return -EINVAL; rc = smblite_lib_set_concurrent_config(chg, val); if (rc < 0) return rc; return count; } static ssize_t boost_concurrent_mode_show(struct class *c, struct class_attribute *attr, char *buf) { struct smb_charger *chg = container_of(c, struct smb_charger, qcom_class); return scnprintf(buf, PAGE_SIZE, "%d\n", chg->concurrent_mode_status); } static CLASS_ATTR_RW(boost_concurrent_mode); static struct attribute *qcom_class_attrs[] = { &class_attr_boost_concurrent_mode.attr, NULL, }; ATTRIBUTE_GROUPS(qcom_class); /*************************** * HARDWARE INITIALIZATION * ***************************/ Loading Loading @@ -1964,6 +2003,18 @@ static int smblite_probe(struct platform_device *pdev) goto disable_irq; } /* Register QCOM SMB class */ if (is_concurrent_mode_supported(chg)) { chg->qcom_class.name = "qcom-smb"; chg->qcom_class.owner = THIS_MODULE; chg->qcom_class.class_groups = qcom_class_groups; rc = class_register(&chg->qcom_class); if (rc < 0) { pr_err("Failed to create qcom_class rc=%d\n", rc); goto disable_irq; } } device_init_wakeup(chg->dev, true); rc = smblite_lib_get_prop_usb_present(chg, &pval); Loading Loading @@ -1991,6 +2042,7 @@ static int smblite_remove(struct platform_device *pdev) struct smb_charger *chg = &chip->chg; smblite_disable_interrupts(chg); class_destroy(&chg->qcom_class); smblite_lib_deinit(chg); sysfs_remove_groups(&chg->dev->kobj, smblite_groups); platform_set_drvdata(pdev, NULL); Loading drivers/power/supply/qcom/smblite-lib.c +212 −40 Original line number Diff line number Diff line Loading @@ -523,6 +523,40 @@ static int smblite_lib_register_notifier(struct smb_charger *chg) return 0; } bool is_concurrent_mode_supported(struct smb_charger *chg) { return (chg->concurrent_mode_supported && chg->subtype == PM5100); } static int smblite_lib_concurrent_mode_config(struct smb_charger *chg, bool enable) { int rc; if (!is_concurrent_mode_supported(chg)) return 0; rc = smblite_lib_write(chg, CONCURRENT_MODE_CFG_REG(chg->base), (enable ? CONCURRENT_MODE_EN_BIT : 0)); if (rc < 0) smblite_lib_err(chg, "Failed to write CONCURRENT_MODE_CFG_REG rc=%d\n", rc); if (!enable) { /* Remove usb_icl_vote when concurrency mode is disabled */ rc = vote(chg->usb_icl_votable, CONCURRENT_MODE_VOTER, false, 0); if (rc < 0) smblite_lib_err(chg, "Failed to vote on ICL rc=%d\n", rc); /* Remove chg_disable_vote when concurrency mode is disabled */ rc = vote(chg->chg_disable_votable, CONCURRENT_MODE_VOTER, false, 0); if (rc < 0) smblite_lib_err(chg, "Failed to vote on ICL rc=%d\n", rc); } return rc; } static void smblite_lib_uusb_removal(struct smb_charger *chg) { int rc; Loading Loading @@ -563,6 +597,8 @@ static void smblite_lib_uusb_removal(struct smb_charger *chg) chg->uusb_apsd_rerun_done = false; chg->hvdcp3_detected = false; /* Disable concurrent mode on USB removal. */ smblite_lib_concurrent_mode_config(chg, false); } void smblite_lib_suspend_on_debug_battery(struct smb_charger *chg) Loading Loading @@ -1299,7 +1335,52 @@ static int smblite_lib_dp_pulse(struct smb_charger *chg) return rc; } int smblite_lib_force_vbus_voltage(struct smb_charger *chg, u8 val) #define HVDCP3_QUALIFICATION_UV (PM5100_MAX_HVDCP3_PULSES * \ (HVDCP3_STEP_SIZE_UV / 2)) static int smblite_lib_hvdcp3_force_max_vbus(struct smb_charger *chg) { union power_supply_propval pval = {0, }; int cnt = 0, rc, prev_vbus; bool qc3_detected = false; rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); return rc; } prev_vbus = pval.intval; /* * Statically increase voltage till 6V. * ( i.e : 1V / 200mV = 5 pulses ). */ while (cnt++ < PM5100_MAX_HVDCP3_PULSES) { smblite_lib_dp_pulse(chg); /* wait for 100ms for vbus to settle. */ msleep(100); } rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); return rc; } /* Check if voltage incremented. (i.e if QC3 ) */ if (pval.intval >= (prev_vbus + HVDCP3_QUALIFICATION_UV)) qc3_detected = true; smblite_lib_dbg(chg, PR_MISC, "HVDCP3 : detected=%s, prev_vbus=%d, vbus_now=%d\n", (qc3_detected ? "True" : "False"), prev_vbus, pval.intval); return qc3_detected; } static int smblite_lib_force_vbus_voltage(struct smb_charger *chg, u8 val) { int rc; Loading Loading @@ -1356,6 +1437,111 @@ int smblite_lib_run_aicl(struct smb_charger *chg, int type) return 0; } #define CONCURRENCY_REDUCED_ICL_UA 300000 int smblite_lib_set_concurrent_config(struct smb_charger *chg, bool enable) { int rc = 0, icl_ua = 0, settled_icl_ua = 0, usb_present = 0; union power_supply_propval pval = {0, }; if (!is_concurrent_mode_supported(chg)) { smblite_lib_dbg(chg, PR_MISC, "Concurrent Mode supported disabled\n"); return 0; } /* Exit if there is no change in state */ if (chg->concurrent_mode_status == enable) goto out; rc = smblite_lib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblite_lib_dbg(chg, PR_MISC, "Couldn't get USB preset status rc=%d\n", rc); goto failure; } usb_present = pval.intval; if (enable) { /* Check if USB is connected */ if (!usb_present) { smblite_lib_dbg(chg, PR_MISC, "Failed to enable concurrent mode USB disconnected\n", rc); goto failure; } /* Get AICL Result */ rc = smblite_lib_get_prop_input_current_settled(chg, &settled_icl_ua); if (rc) { smblite_lib_err(chg, "Failed read AICL Result rc=%d\n", rc); goto failure; } /* Return if AICL result is less than 300mA. */ if (settled_icl_ua <= CONCURRENCY_REDUCED_ICL_UA) { smblite_lib_dbg(chg, PR_MISC, "AICL Result too less to enable concurreny mode\n"); goto failure; } icl_ua = settled_icl_ua - CONCURRENCY_REDUCED_ICL_UA; rc = vote(chg->usb_icl_votable, CONCURRENT_MODE_VOTER, true, icl_ua); if (rc < 0) { smblite_lib_err(chg, "Failed to vote on ICL rc=%d\n", rc); goto failure; } if (chg->hvdcp3_detected) { /* Force Vbus to 5V. */ rc = smblite_lib_force_vbus_voltage(chg, FORCE_5V_BIT); if (rc < 0) smblite_lib_err(chg, "Failed to force vbus to 5V rc=%d\n", rc); } /* Enable charger if already disabled */ rc = vote(chg->chg_disable_votable, CONCURRENT_MODE_VOTER, false, 0); if (rc < 0) { smblite_lib_err(chg, "Failed to Enable charger rc=%d\n", rc); goto failure; } /* Enable concurrent mode */ rc = smblite_lib_concurrent_mode_config(chg, true); if (rc < 0) goto failure; chg->concurrent_mode_status = true; smblite_lib_dbg(chg, PR_MISC, "Concurrent Mode enabled successfully: settled_icl_ua=%duA, icl_ua=%duA, is_hvdcp3=%d\n", settled_icl_ua, icl_ua, chg->hvdcp3_detected); goto out; } else { /* Disable concurrent mode */ rc = smblite_lib_concurrent_mode_config(chg, false); if (rc < 0) goto failure; /* Restore vbus to MAX(6V) if QC3P5 is connected */ if (chg->hvdcp3_detected && usb_present) smblite_lib_hvdcp3_force_max_vbus(chg); chg->concurrent_mode_status = false; smblite_lib_dbg(chg, PR_MISC, "Concurrent Mode disabled successfully: is_hvdcp3=%d\n", chg->hvdcp3_detected); goto out; } failure: rc = -EINVAL; smblite_lib_dbg(chg, PR_MISC, "Failed to %s concurrent mode\n", (enable ? "Enable" : "Disable")); out: return rc; } /******************* * USB PSY GETTERS * *******************/ Loading Loading @@ -2397,12 +2583,30 @@ static void smblite_lib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising) { int rc = 0; u8 stat; if (vbus_rising) { rc = typec_partner_register(chg); if (rc < 0) smblite_lib_err(chg, "Couldn't register partner rc =%d\n", rc); /* * For PM5100 check if concurrent mode support is enabled and * charging is paused in hardware due to boost being enabled, * force charging to be disabled in SW. */ if (is_concurrent_mode_supported(chg)) { rc = smblite_lib_read(chg, CHGR_CHG_EN_STATUS_REG(chg->base), &stat); if (rc < 0) smblite_lib_err(chg, "Couldn't read CHGR_EN_STATUS_REG rc=%d\n", rc); vote(chg->chg_disable_votable, CONCURRENT_MODE_VOTER, (stat & CHARGING_DISABLED_FROM_BOOST_BIT), 0); smblite_lib_dbg(chg, PR_MISC, "charger_en_status=%x, Charging disable by boost\n", stat); } } else { smblite_lib_notify_device_mode(chg, false); smblite_lib_uusb_removal(chg); Loading Loading @@ -2695,54 +2899,22 @@ static void smblite_lib_handle_apsd_done(struct smb_charger *chg, bool rising) apsd_result->name); } #define HVDCP3_QUALIFICATION_UV (PM5100_MAX_HVDCP3_PULSES * \ (HVDCP3_STEP_SIZE_UV / 2)) static void smblite_lib_handle_hvdcp_check_timeout(struct smb_charger *chg, bool rising, bool qc_charger) { union power_supply_propval pval = {0, }; int rc = 0, cnt = 0, prev_vbus; int rc = 0; if (rising) { if (qc_charger) { rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); goto failure; } prev_vbus = pval.intval; /* * Statically increase voltage till 6V. * ( i.e : 1V / 200mV = 5 pulses ). */ while (cnt++ < PM5100_MAX_HVDCP3_PULSES) { smblite_lib_dp_pulse(chg); /* wait for 100ms for vbus to settle. */ msleep(100); } rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); goto failure; } /* Check if voltage incremented. (i.e if QC3 )*/ if (pval.intval >= (prev_vbus + HVDCP3_QUALIFICATION_UV)) /* Increase vbus to MAX(6V), if incremented HVDCP_3 is detected */ rc = smblite_lib_hvdcp3_force_max_vbus(chg); if (rc < 0) smblite_lib_err(chg, "HVDCP3 detection failure\n"); if (rc > 0) chg->hvdcp3_detected = true; smblite_lib_dbg(chg, PR_MISC, "HVDCP3 : detected=%s, prev_vbus=%d, vbus_now=%d\n", (chg->hvdcp3_detected ? "True" : "False"), prev_vbus, pval.intval); } } failure: smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", __func__, rising ? "rising" : "falling"); } Loading drivers/power/supply/qcom/smblite-lib.h +7 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ enum print_reason { #define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER" #define TYPEC_SWAP_VOTER "TYPEC_SWAP_VOTER" #define FLASH_ACTIVE_VOTER "FLASH_ACTIVE_VOTER" #define CONCURRENT_MODE_VOTER "CONCURRENT_MODE_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -264,8 +265,10 @@ struct smb_charger { struct iio_channel *iio_chans; struct iio_channel **iio_chan_list_qg; struct iio_channel **iio_chan_list_smb_parallel; struct class qcom_class; int *debug_mask; enum smb_mode mode; u8 subtype; int weak_chg_icl_ua; /* locks */ Loading Loading @@ -359,6 +362,8 @@ struct smb_charger { bool uusb_apsd_rerun_done; bool dpdm_enabled; bool hvdcp3_detected; bool concurrent_mode_supported; bool concurrent_mode_status; /* workaround flag */ u32 wa_flags; Loading Loading @@ -503,5 +508,7 @@ int smblite_iio_get_prop(struct smb_charger *chg, int channel, int *val); int smblite_iio_set_prop(struct smb_charger *chg, int channel, int val); int smblite_lib_get_fcc(struct smb_chg_param *param, u8 val_raw); int smblite_lib_set_fcc(struct smb_chg_param *param, int val_u, u8 *val_raw); int smblite_lib_set_concurrent_config(struct smb_charger *chg, bool enable); bool is_concurrent_mode_supported(struct smb_charger *chg); #endif /* __SMBLITE_LIB_H */ drivers/power/supply/qcom/smblite-reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ enum { DISABLE_CHARGE, }; #define CHGR_CHG_EN_STATUS_REG(base) (base.chg_base + 0x07) #define CHARGING_DISABLED_FROM_BOOST_BIT BIT(6) #define CHARGER_VBAT_STATUS_REG(base) (base.chg_base + 0x08) #define BAT_OV_BIT BIT(7) Loading Loading @@ -103,6 +106,9 @@ enum { #define DCDC_LDO_CFG_REG(base) (base.dcdc_base + 0x70) #define LDO_MODE_BIT BIT(0) #define CONCURRENT_MODE_CFG_REG(base) (base.dcdc_base + 0x50) #define CONCURRENT_MODE_EN_BIT BIT(0) /******************************** * BATIF Peripheral Registers * ********************************/ Loading Loading
drivers/power/supply/qcom/qpnp-smblite.c +55 −3 Original line number Diff line number Diff line Loading @@ -183,11 +183,12 @@ ATTRIBUTE_GROUPS(smblite); static int smblite_chg_config_init(struct smblite *chip) { struct smb_charger *chg = &chip->chg; int subtype = (u8)of_device_get_match_data(chg->dev); u8 val; int rc = 0; switch (subtype) { chg->subtype = (u8)of_device_get_match_data(chg->dev); switch (chg->subtype) { case PM2250: chg->wa_flags |= WEAK_ADAPTER_WA; chg->base = smb_base[PM2250]; Loading @@ -209,7 +210,7 @@ static int smblite_chg_config_init(struct smblite *chip) chg->name = "PM5100_charger"; break; default: pr_err("Unsupported PMIC subtype=%d\n", subtype); pr_err("Unsupported PMIC subtype=%d\n", chg->subtype); return -EINVAL; } Loading Loading @@ -302,6 +303,9 @@ static int smblite_parse_dt_misc(struct smblite *chip, struct device_node *node) if (chg->chg_param.fcc_step_size_ua <= 0) chg->chg_param.fcc_step_size_ua = DEFAULT_FCC_STEP_SIZE_UA; chg->concurrent_mode_supported = of_property_read_bool(node, "qcom,concurrency-mode-supported"); return 0; } Loading Loading @@ -771,6 +775,41 @@ static int smblite_init_batt_psy(struct smblite *chip) return rc; } /******************* * QCOM SMB Class * *******************/ static ssize_t boost_concurrent_mode_store(struct class *c, struct class_attribute *attr, const char *buf, size_t count) { struct smb_charger *chg = container_of(c, struct smb_charger, qcom_class); int rc; bool val; if (kstrtobool(buf, &val)) return -EINVAL; rc = smblite_lib_set_concurrent_config(chg, val); if (rc < 0) return rc; return count; } static ssize_t boost_concurrent_mode_show(struct class *c, struct class_attribute *attr, char *buf) { struct smb_charger *chg = container_of(c, struct smb_charger, qcom_class); return scnprintf(buf, PAGE_SIZE, "%d\n", chg->concurrent_mode_status); } static CLASS_ATTR_RW(boost_concurrent_mode); static struct attribute *qcom_class_attrs[] = { &class_attr_boost_concurrent_mode.attr, NULL, }; ATTRIBUTE_GROUPS(qcom_class); /*************************** * HARDWARE INITIALIZATION * ***************************/ Loading Loading @@ -1964,6 +2003,18 @@ static int smblite_probe(struct platform_device *pdev) goto disable_irq; } /* Register QCOM SMB class */ if (is_concurrent_mode_supported(chg)) { chg->qcom_class.name = "qcom-smb"; chg->qcom_class.owner = THIS_MODULE; chg->qcom_class.class_groups = qcom_class_groups; rc = class_register(&chg->qcom_class); if (rc < 0) { pr_err("Failed to create qcom_class rc=%d\n", rc); goto disable_irq; } } device_init_wakeup(chg->dev, true); rc = smblite_lib_get_prop_usb_present(chg, &pval); Loading Loading @@ -1991,6 +2042,7 @@ static int smblite_remove(struct platform_device *pdev) struct smb_charger *chg = &chip->chg; smblite_disable_interrupts(chg); class_destroy(&chg->qcom_class); smblite_lib_deinit(chg); sysfs_remove_groups(&chg->dev->kobj, smblite_groups); platform_set_drvdata(pdev, NULL); Loading
drivers/power/supply/qcom/smblite-lib.c +212 −40 Original line number Diff line number Diff line Loading @@ -523,6 +523,40 @@ static int smblite_lib_register_notifier(struct smb_charger *chg) return 0; } bool is_concurrent_mode_supported(struct smb_charger *chg) { return (chg->concurrent_mode_supported && chg->subtype == PM5100); } static int smblite_lib_concurrent_mode_config(struct smb_charger *chg, bool enable) { int rc; if (!is_concurrent_mode_supported(chg)) return 0; rc = smblite_lib_write(chg, CONCURRENT_MODE_CFG_REG(chg->base), (enable ? CONCURRENT_MODE_EN_BIT : 0)); if (rc < 0) smblite_lib_err(chg, "Failed to write CONCURRENT_MODE_CFG_REG rc=%d\n", rc); if (!enable) { /* Remove usb_icl_vote when concurrency mode is disabled */ rc = vote(chg->usb_icl_votable, CONCURRENT_MODE_VOTER, false, 0); if (rc < 0) smblite_lib_err(chg, "Failed to vote on ICL rc=%d\n", rc); /* Remove chg_disable_vote when concurrency mode is disabled */ rc = vote(chg->chg_disable_votable, CONCURRENT_MODE_VOTER, false, 0); if (rc < 0) smblite_lib_err(chg, "Failed to vote on ICL rc=%d\n", rc); } return rc; } static void smblite_lib_uusb_removal(struct smb_charger *chg) { int rc; Loading Loading @@ -563,6 +597,8 @@ static void smblite_lib_uusb_removal(struct smb_charger *chg) chg->uusb_apsd_rerun_done = false; chg->hvdcp3_detected = false; /* Disable concurrent mode on USB removal. */ smblite_lib_concurrent_mode_config(chg, false); } void smblite_lib_suspend_on_debug_battery(struct smb_charger *chg) Loading Loading @@ -1299,7 +1335,52 @@ static int smblite_lib_dp_pulse(struct smb_charger *chg) return rc; } int smblite_lib_force_vbus_voltage(struct smb_charger *chg, u8 val) #define HVDCP3_QUALIFICATION_UV (PM5100_MAX_HVDCP3_PULSES * \ (HVDCP3_STEP_SIZE_UV / 2)) static int smblite_lib_hvdcp3_force_max_vbus(struct smb_charger *chg) { union power_supply_propval pval = {0, }; int cnt = 0, rc, prev_vbus; bool qc3_detected = false; rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); return rc; } prev_vbus = pval.intval; /* * Statically increase voltage till 6V. * ( i.e : 1V / 200mV = 5 pulses ). */ while (cnt++ < PM5100_MAX_HVDCP3_PULSES) { smblite_lib_dp_pulse(chg); /* wait for 100ms for vbus to settle. */ msleep(100); } rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); return rc; } /* Check if voltage incremented. (i.e if QC3 ) */ if (pval.intval >= (prev_vbus + HVDCP3_QUALIFICATION_UV)) qc3_detected = true; smblite_lib_dbg(chg, PR_MISC, "HVDCP3 : detected=%s, prev_vbus=%d, vbus_now=%d\n", (qc3_detected ? "True" : "False"), prev_vbus, pval.intval); return qc3_detected; } static int smblite_lib_force_vbus_voltage(struct smb_charger *chg, u8 val) { int rc; Loading Loading @@ -1356,6 +1437,111 @@ int smblite_lib_run_aicl(struct smb_charger *chg, int type) return 0; } #define CONCURRENCY_REDUCED_ICL_UA 300000 int smblite_lib_set_concurrent_config(struct smb_charger *chg, bool enable) { int rc = 0, icl_ua = 0, settled_icl_ua = 0, usb_present = 0; union power_supply_propval pval = {0, }; if (!is_concurrent_mode_supported(chg)) { smblite_lib_dbg(chg, PR_MISC, "Concurrent Mode supported disabled\n"); return 0; } /* Exit if there is no change in state */ if (chg->concurrent_mode_status == enable) goto out; rc = smblite_lib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblite_lib_dbg(chg, PR_MISC, "Couldn't get USB preset status rc=%d\n", rc); goto failure; } usb_present = pval.intval; if (enable) { /* Check if USB is connected */ if (!usb_present) { smblite_lib_dbg(chg, PR_MISC, "Failed to enable concurrent mode USB disconnected\n", rc); goto failure; } /* Get AICL Result */ rc = smblite_lib_get_prop_input_current_settled(chg, &settled_icl_ua); if (rc) { smblite_lib_err(chg, "Failed read AICL Result rc=%d\n", rc); goto failure; } /* Return if AICL result is less than 300mA. */ if (settled_icl_ua <= CONCURRENCY_REDUCED_ICL_UA) { smblite_lib_dbg(chg, PR_MISC, "AICL Result too less to enable concurreny mode\n"); goto failure; } icl_ua = settled_icl_ua - CONCURRENCY_REDUCED_ICL_UA; rc = vote(chg->usb_icl_votable, CONCURRENT_MODE_VOTER, true, icl_ua); if (rc < 0) { smblite_lib_err(chg, "Failed to vote on ICL rc=%d\n", rc); goto failure; } if (chg->hvdcp3_detected) { /* Force Vbus to 5V. */ rc = smblite_lib_force_vbus_voltage(chg, FORCE_5V_BIT); if (rc < 0) smblite_lib_err(chg, "Failed to force vbus to 5V rc=%d\n", rc); } /* Enable charger if already disabled */ rc = vote(chg->chg_disable_votable, CONCURRENT_MODE_VOTER, false, 0); if (rc < 0) { smblite_lib_err(chg, "Failed to Enable charger rc=%d\n", rc); goto failure; } /* Enable concurrent mode */ rc = smblite_lib_concurrent_mode_config(chg, true); if (rc < 0) goto failure; chg->concurrent_mode_status = true; smblite_lib_dbg(chg, PR_MISC, "Concurrent Mode enabled successfully: settled_icl_ua=%duA, icl_ua=%duA, is_hvdcp3=%d\n", settled_icl_ua, icl_ua, chg->hvdcp3_detected); goto out; } else { /* Disable concurrent mode */ rc = smblite_lib_concurrent_mode_config(chg, false); if (rc < 0) goto failure; /* Restore vbus to MAX(6V) if QC3P5 is connected */ if (chg->hvdcp3_detected && usb_present) smblite_lib_hvdcp3_force_max_vbus(chg); chg->concurrent_mode_status = false; smblite_lib_dbg(chg, PR_MISC, "Concurrent Mode disabled successfully: is_hvdcp3=%d\n", chg->hvdcp3_detected); goto out; } failure: rc = -EINVAL; smblite_lib_dbg(chg, PR_MISC, "Failed to %s concurrent mode\n", (enable ? "Enable" : "Disable")); out: return rc; } /******************* * USB PSY GETTERS * *******************/ Loading Loading @@ -2397,12 +2583,30 @@ static void smblite_lib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising) { int rc = 0; u8 stat; if (vbus_rising) { rc = typec_partner_register(chg); if (rc < 0) smblite_lib_err(chg, "Couldn't register partner rc =%d\n", rc); /* * For PM5100 check if concurrent mode support is enabled and * charging is paused in hardware due to boost being enabled, * force charging to be disabled in SW. */ if (is_concurrent_mode_supported(chg)) { rc = smblite_lib_read(chg, CHGR_CHG_EN_STATUS_REG(chg->base), &stat); if (rc < 0) smblite_lib_err(chg, "Couldn't read CHGR_EN_STATUS_REG rc=%d\n", rc); vote(chg->chg_disable_votable, CONCURRENT_MODE_VOTER, (stat & CHARGING_DISABLED_FROM_BOOST_BIT), 0); smblite_lib_dbg(chg, PR_MISC, "charger_en_status=%x, Charging disable by boost\n", stat); } } else { smblite_lib_notify_device_mode(chg, false); smblite_lib_uusb_removal(chg); Loading Loading @@ -2695,54 +2899,22 @@ static void smblite_lib_handle_apsd_done(struct smb_charger *chg, bool rising) apsd_result->name); } #define HVDCP3_QUALIFICATION_UV (PM5100_MAX_HVDCP3_PULSES * \ (HVDCP3_STEP_SIZE_UV / 2)) static void smblite_lib_handle_hvdcp_check_timeout(struct smb_charger *chg, bool rising, bool qc_charger) { union power_supply_propval pval = {0, }; int rc = 0, cnt = 0, prev_vbus; int rc = 0; if (rising) { if (qc_charger) { rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); goto failure; } prev_vbus = pval.intval; /* * Statically increase voltage till 6V. * ( i.e : 1V / 200mV = 5 pulses ). */ while (cnt++ < PM5100_MAX_HVDCP3_PULSES) { smblite_lib_dp_pulse(chg); /* wait for 100ms for vbus to settle. */ msleep(100); } rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", rc); goto failure; } /* Check if voltage incremented. (i.e if QC3 )*/ if (pval.intval >= (prev_vbus + HVDCP3_QUALIFICATION_UV)) /* Increase vbus to MAX(6V), if incremented HVDCP_3 is detected */ rc = smblite_lib_hvdcp3_force_max_vbus(chg); if (rc < 0) smblite_lib_err(chg, "HVDCP3 detection failure\n"); if (rc > 0) chg->hvdcp3_detected = true; smblite_lib_dbg(chg, PR_MISC, "HVDCP3 : detected=%s, prev_vbus=%d, vbus_now=%d\n", (chg->hvdcp3_detected ? "True" : "False"), prev_vbus, pval.intval); } } failure: smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", __func__, rising ? "rising" : "falling"); } Loading
drivers/power/supply/qcom/smblite-lib.h +7 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ enum print_reason { #define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER" #define TYPEC_SWAP_VOTER "TYPEC_SWAP_VOTER" #define FLASH_ACTIVE_VOTER "FLASH_ACTIVE_VOTER" #define CONCURRENT_MODE_VOTER "CONCURRENT_MODE_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -264,8 +265,10 @@ struct smb_charger { struct iio_channel *iio_chans; struct iio_channel **iio_chan_list_qg; struct iio_channel **iio_chan_list_smb_parallel; struct class qcom_class; int *debug_mask; enum smb_mode mode; u8 subtype; int weak_chg_icl_ua; /* locks */ Loading Loading @@ -359,6 +362,8 @@ struct smb_charger { bool uusb_apsd_rerun_done; bool dpdm_enabled; bool hvdcp3_detected; bool concurrent_mode_supported; bool concurrent_mode_status; /* workaround flag */ u32 wa_flags; Loading Loading @@ -503,5 +508,7 @@ int smblite_iio_get_prop(struct smb_charger *chg, int channel, int *val); int smblite_iio_set_prop(struct smb_charger *chg, int channel, int val); int smblite_lib_get_fcc(struct smb_chg_param *param, u8 val_raw); int smblite_lib_set_fcc(struct smb_chg_param *param, int val_u, u8 *val_raw); int smblite_lib_set_concurrent_config(struct smb_charger *chg, bool enable); bool is_concurrent_mode_supported(struct smb_charger *chg); #endif /* __SMBLITE_LIB_H */
drivers/power/supply/qcom/smblite-reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ enum { DISABLE_CHARGE, }; #define CHGR_CHG_EN_STATUS_REG(base) (base.chg_base + 0x07) #define CHARGING_DISABLED_FROM_BOOST_BIT BIT(6) #define CHARGER_VBAT_STATUS_REG(base) (base.chg_base + 0x08) #define BAT_OV_BIT BIT(7) Loading Loading @@ -103,6 +106,9 @@ enum { #define DCDC_LDO_CFG_REG(base) (base.dcdc_base + 0x70) #define LDO_MODE_BIT BIT(0) #define CONCURRENT_MODE_CFG_REG(base) (base.dcdc_base + 0x50) #define CONCURRENT_MODE_EN_BIT BIT(0) /******************************** * BATIF Peripheral Registers * ********************************/ Loading