Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-qnovo.txt +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ Required properties: Optional Properties: - qcom,external-rsense: To indicate whether the platform uses external or internal rsense for measuring battery current. - qcom,enable-for-dc: To enable qnovo for dc charging path. Example: Loading drivers/power/supply/qcom/pmic-voter.c +5 −6 Original line number Diff line number Diff line Loading @@ -521,11 +521,10 @@ static int show_votable_clients(struct seq_file *m, void *data) lock_votable(votable); seq_printf(m, "Votable %s:\n", votable->name); seq_puts(m, "clients:\n"); for (i = 0; i < votable->num_clients; i++) { if (votable->client_strs[i]) { seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n", seq_printf(m, "%s: %s:\t\t\ten=%d v=%d\n", votable->name, votable->client_strs[i], votable->votes[i].enabled, votable->votes[i].value); Loading @@ -544,11 +543,11 @@ static int show_votable_clients(struct seq_file *m, void *data) break; } seq_printf(m, "type: %s\n", type_str); seq_puts(m, "Effective:\n"); effective_client_str = get_effective_client_locked(votable); seq_printf(m, "%-15s:\t\tv=%d\n", seq_printf(m, "%s: effective=%s type=%s v=%d\n", votable->name, effective_client_str ? effective_client_str : "none", type_str, get_effective_result_locked(votable)); unlock_votable(votable); Loading drivers/power/supply/qcom/qpnp-qnovo.c +43 −12 Original line number Diff line number Diff line Loading @@ -112,6 +112,7 @@ #define GAIN_LSB_FACTOR 976560 #define USER_VOTER "user_voter" #define SHUTDOWN_VOTER "user_voter" #define OK_TO_QNOVO_VOTER "ok_to_qnovo_voter" #define QNOVO_VOTER "qnovo_voter" Loading @@ -130,6 +131,7 @@ struct qnovo_dt_props { bool external_rsense; struct device_node *revid_dev_node; bool enable_for_dc; }; struct qnovo { Loading Loading @@ -442,6 +444,8 @@ static int qnovo_parse_dt(struct qnovo *chip) pr_err("Missing qcom,pmic-revid property - driver failed\n"); return -EINVAL; } chip->dt.enable_for_dc = of_property_read_bool(node, "qcom,enable-for-dc"); return 0; } Loading Loading @@ -1310,6 +1314,10 @@ static void status_change_work(struct work_struct *work) if (usb_present) dc_present = 0; /* disable qnovo for dc path by forcing dc_present = 0 always */ if (!chip->dt.enable_for_dc) dc_present = 0; if (chip->dc_present && !dc_present) { /* removal */ chip->dc_present = 0; Loading @@ -1333,6 +1341,26 @@ static void ptrain_restart_work(struct work_struct *work) struct qnovo, ptrain_restart_work.work); u8 pt_t1, pt_t2; int rc; u8 pt_en; rc = qnovo_read(chip, QNOVO_PTRAIN_EN, &pt_en, 1); if (rc < 0) { dev_err(chip->dev, "Couldn't read QNOVO_PTRAIN_EN rc = %d\n", rc); goto clean_up; } if (!pt_en) { rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT, QNOVO_PTRAIN_EN_BIT); if (rc < 0) { dev_err(chip->dev, "Couldn't enable pulse train rc=%d\n", rc); goto clean_up; } /* sleep 20ms for the pulse trains to restart and settle */ msleep(20); } rc = qnovo_read(chip, QNOVO_PTTIME_STS, &pt_t1, 1); if (rc < 0) { Loading Loading @@ -1395,16 +1423,7 @@ static irqreturn_t handle_ptrain_done(int irq, void *data) struct qnovo *chip = data; union power_supply_propval pval = {0}; /* * In some cases (esp shutting down) the userspace would disable by * setting qnovo_enable=0. Also charger could be removed or there is * an error (i.e. its not okay to run qnovo)- * skip taking ESR measurement in such situations */ if (get_client_vote(chip->disable_votable, USER_VOTER) || get_effective_result(chip->not_ok_to_qnovo_votable) > 0) return IRQ_HANDLED; qnovo_update_status(chip); /* * hw resets pt_en bit once ptrain_done triggers. Loading @@ -1415,13 +1434,14 @@ static irqreturn_t handle_ptrain_done(int irq, void *data) vote(chip->pt_dis_votable, QNI_PT_VOTER, true, 0); vote(chip->pt_dis_votable, ESR_VOTER, true, 0); if (is_fg_available(chip)) if (is_fg_available(chip) && !get_client_vote(chip->disable_votable, USER_VOTER) && !get_effective_result(chip->not_ok_to_qnovo_votable)) power_supply_set_property(chip->bms_psy, POWER_SUPPLY_PROP_RESISTANCE, &pval); vote(chip->pt_dis_votable, ESR_VOTER, false, 0); qnovo_update_status(chip); kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE); return IRQ_HANDLED; } Loading @@ -1434,6 +1454,9 @@ static int qnovo_hw_init(struct qnovo *chip) u8 vadc_offset, vadc_gain; u8 val; vote(chip->chg_ready_votable, USB_READY_VOTER, false, 0); vote(chip->chg_ready_votable, DC_READY_VOTER, false, 0); vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, FG_AVAILABLE_VOTER, true, 0); Loading Loading @@ -1706,6 +1729,13 @@ static int qnovo_remove(struct platform_device *pdev) return 0; } static void qnovo_shutdown(struct platform_device *pdev) { struct qnovo *chip = platform_get_drvdata(pdev); vote(chip->not_ok_to_qnovo_votable, SHUTDOWN_VOTER, true, 0); } static const struct of_device_id match_table[] = { { .compatible = "qcom,qpnp-qnovo", }, { }, Loading @@ -1719,6 +1749,7 @@ static struct platform_driver qnovo_driver = { }, .probe = qnovo_probe, .remove = qnovo_remove, .shutdown = qnovo_shutdown, }; module_platform_driver(qnovo_driver); Loading drivers/power/supply/qcom/smb-lib.c +40 −0 Original line number Diff line number Diff line Loading @@ -3616,6 +3616,32 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst) } } static void smblib_notify_extcon_props(struct smb_charger *chg) { union power_supply_propval val; smblib_get_prop_typec_cc_orientation(chg, &val); extcon_set_cable_state_(chg->extcon, EXTCON_USB_CC, (val.intval == 2) ? 1 : 0); extcon_set_cable_state_(chg->extcon, EXTCON_USB_SPEED, true); } static void smblib_notify_device_mode(struct smb_charger *chg, bool enable) { if (enable) smblib_notify_extcon_props(chg); extcon_set_cable_state_(chg->extcon, EXTCON_USB, enable); } static void smblib_notify_usb_host(struct smb_charger *chg, bool enable) { if (enable) smblib_notify_extcon_props(chg); extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST, enable); } #define HVDCP_DET_MS 2500 static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) { Loading @@ -3635,6 +3661,8 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) if (chg->micro_usb_mode) extcon_set_cable_state_(chg->extcon, EXTCON_USB, true); if (chg->use_extcon) smblib_notify_device_mode(chg, true); case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: /* if not DCP then no hvdcp timeout happens, Enable pd here. */ Loading Loading @@ -3719,6 +3747,10 @@ static void typec_sink_insertion(struct smb_charger *chg) */ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, false, 0); if (chg->use_extcon) { smblib_notify_usb_host(chg, true); chg->otg_present = true; } } static void typec_sink_removal(struct smb_charger *chg) Loading Loading @@ -3867,6 +3899,14 @@ unlock: typec_sink_removal(chg); smblib_update_usb_type(chg); if (chg->use_extcon) { if (chg->otg_present) smblib_notify_usb_host(chg, false); else smblib_notify_device_mode(chg, false); } chg->otg_present = false; } static void smblib_handle_typec_insertion(struct smb_charger *chg) Loading drivers/power/supply/qcom/smb-lib.h +7 −0 Original line number Diff line number Diff line Loading @@ -139,9 +139,14 @@ struct smb_irq_info { static const unsigned int smblib_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, EXTCON_USB_CC, EXTCON_USB_SPEED, EXTCON_NONE, }; /* EXTCON_USB and EXTCON_USB_HOST are mutually exclusive */ static const u32 smblib_extcon_exclusive[] = {0x3, 0}; struct smb_regulator { struct regulator_dev *rdev; struct regulator_desc rdesc; Loading Loading @@ -328,6 +333,8 @@ struct smb_charger { int usb_icl_change_irq_enabled; u32 jeita_status; u8 float_cfg; bool use_extcon; bool otg_present; /* workaround flag */ u32 wa_flags; Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-qnovo.txt +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ Required properties: Optional Properties: - qcom,external-rsense: To indicate whether the platform uses external or internal rsense for measuring battery current. - qcom,enable-for-dc: To enable qnovo for dc charging path. Example: Loading
drivers/power/supply/qcom/pmic-voter.c +5 −6 Original line number Diff line number Diff line Loading @@ -521,11 +521,10 @@ static int show_votable_clients(struct seq_file *m, void *data) lock_votable(votable); seq_printf(m, "Votable %s:\n", votable->name); seq_puts(m, "clients:\n"); for (i = 0; i < votable->num_clients; i++) { if (votable->client_strs[i]) { seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n", seq_printf(m, "%s: %s:\t\t\ten=%d v=%d\n", votable->name, votable->client_strs[i], votable->votes[i].enabled, votable->votes[i].value); Loading @@ -544,11 +543,11 @@ static int show_votable_clients(struct seq_file *m, void *data) break; } seq_printf(m, "type: %s\n", type_str); seq_puts(m, "Effective:\n"); effective_client_str = get_effective_client_locked(votable); seq_printf(m, "%-15s:\t\tv=%d\n", seq_printf(m, "%s: effective=%s type=%s v=%d\n", votable->name, effective_client_str ? effective_client_str : "none", type_str, get_effective_result_locked(votable)); unlock_votable(votable); Loading
drivers/power/supply/qcom/qpnp-qnovo.c +43 −12 Original line number Diff line number Diff line Loading @@ -112,6 +112,7 @@ #define GAIN_LSB_FACTOR 976560 #define USER_VOTER "user_voter" #define SHUTDOWN_VOTER "user_voter" #define OK_TO_QNOVO_VOTER "ok_to_qnovo_voter" #define QNOVO_VOTER "qnovo_voter" Loading @@ -130,6 +131,7 @@ struct qnovo_dt_props { bool external_rsense; struct device_node *revid_dev_node; bool enable_for_dc; }; struct qnovo { Loading Loading @@ -442,6 +444,8 @@ static int qnovo_parse_dt(struct qnovo *chip) pr_err("Missing qcom,pmic-revid property - driver failed\n"); return -EINVAL; } chip->dt.enable_for_dc = of_property_read_bool(node, "qcom,enable-for-dc"); return 0; } Loading Loading @@ -1310,6 +1314,10 @@ static void status_change_work(struct work_struct *work) if (usb_present) dc_present = 0; /* disable qnovo for dc path by forcing dc_present = 0 always */ if (!chip->dt.enable_for_dc) dc_present = 0; if (chip->dc_present && !dc_present) { /* removal */ chip->dc_present = 0; Loading @@ -1333,6 +1341,26 @@ static void ptrain_restart_work(struct work_struct *work) struct qnovo, ptrain_restart_work.work); u8 pt_t1, pt_t2; int rc; u8 pt_en; rc = qnovo_read(chip, QNOVO_PTRAIN_EN, &pt_en, 1); if (rc < 0) { dev_err(chip->dev, "Couldn't read QNOVO_PTRAIN_EN rc = %d\n", rc); goto clean_up; } if (!pt_en) { rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT, QNOVO_PTRAIN_EN_BIT); if (rc < 0) { dev_err(chip->dev, "Couldn't enable pulse train rc=%d\n", rc); goto clean_up; } /* sleep 20ms for the pulse trains to restart and settle */ msleep(20); } rc = qnovo_read(chip, QNOVO_PTTIME_STS, &pt_t1, 1); if (rc < 0) { Loading Loading @@ -1395,16 +1423,7 @@ static irqreturn_t handle_ptrain_done(int irq, void *data) struct qnovo *chip = data; union power_supply_propval pval = {0}; /* * In some cases (esp shutting down) the userspace would disable by * setting qnovo_enable=0. Also charger could be removed or there is * an error (i.e. its not okay to run qnovo)- * skip taking ESR measurement in such situations */ if (get_client_vote(chip->disable_votable, USER_VOTER) || get_effective_result(chip->not_ok_to_qnovo_votable) > 0) return IRQ_HANDLED; qnovo_update_status(chip); /* * hw resets pt_en bit once ptrain_done triggers. Loading @@ -1415,13 +1434,14 @@ static irqreturn_t handle_ptrain_done(int irq, void *data) vote(chip->pt_dis_votable, QNI_PT_VOTER, true, 0); vote(chip->pt_dis_votable, ESR_VOTER, true, 0); if (is_fg_available(chip)) if (is_fg_available(chip) && !get_client_vote(chip->disable_votable, USER_VOTER) && !get_effective_result(chip->not_ok_to_qnovo_votable)) power_supply_set_property(chip->bms_psy, POWER_SUPPLY_PROP_RESISTANCE, &pval); vote(chip->pt_dis_votable, ESR_VOTER, false, 0); qnovo_update_status(chip); kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE); return IRQ_HANDLED; } Loading @@ -1434,6 +1454,9 @@ static int qnovo_hw_init(struct qnovo *chip) u8 vadc_offset, vadc_gain; u8 val; vote(chip->chg_ready_votable, USB_READY_VOTER, false, 0); vote(chip->chg_ready_votable, DC_READY_VOTER, false, 0); vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, FG_AVAILABLE_VOTER, true, 0); Loading Loading @@ -1706,6 +1729,13 @@ static int qnovo_remove(struct platform_device *pdev) return 0; } static void qnovo_shutdown(struct platform_device *pdev) { struct qnovo *chip = platform_get_drvdata(pdev); vote(chip->not_ok_to_qnovo_votable, SHUTDOWN_VOTER, true, 0); } static const struct of_device_id match_table[] = { { .compatible = "qcom,qpnp-qnovo", }, { }, Loading @@ -1719,6 +1749,7 @@ static struct platform_driver qnovo_driver = { }, .probe = qnovo_probe, .remove = qnovo_remove, .shutdown = qnovo_shutdown, }; module_platform_driver(qnovo_driver); Loading
drivers/power/supply/qcom/smb-lib.c +40 −0 Original line number Diff line number Diff line Loading @@ -3616,6 +3616,32 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst) } } static void smblib_notify_extcon_props(struct smb_charger *chg) { union power_supply_propval val; smblib_get_prop_typec_cc_orientation(chg, &val); extcon_set_cable_state_(chg->extcon, EXTCON_USB_CC, (val.intval == 2) ? 1 : 0); extcon_set_cable_state_(chg->extcon, EXTCON_USB_SPEED, true); } static void smblib_notify_device_mode(struct smb_charger *chg, bool enable) { if (enable) smblib_notify_extcon_props(chg); extcon_set_cable_state_(chg->extcon, EXTCON_USB, enable); } static void smblib_notify_usb_host(struct smb_charger *chg, bool enable) { if (enable) smblib_notify_extcon_props(chg); extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST, enable); } #define HVDCP_DET_MS 2500 static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) { Loading @@ -3635,6 +3661,8 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) if (chg->micro_usb_mode) extcon_set_cable_state_(chg->extcon, EXTCON_USB, true); if (chg->use_extcon) smblib_notify_device_mode(chg, true); case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: /* if not DCP then no hvdcp timeout happens, Enable pd here. */ Loading Loading @@ -3719,6 +3747,10 @@ static void typec_sink_insertion(struct smb_charger *chg) */ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, false, 0); if (chg->use_extcon) { smblib_notify_usb_host(chg, true); chg->otg_present = true; } } static void typec_sink_removal(struct smb_charger *chg) Loading Loading @@ -3867,6 +3899,14 @@ unlock: typec_sink_removal(chg); smblib_update_usb_type(chg); if (chg->use_extcon) { if (chg->otg_present) smblib_notify_usb_host(chg, false); else smblib_notify_device_mode(chg, false); } chg->otg_present = false; } static void smblib_handle_typec_insertion(struct smb_charger *chg) Loading
drivers/power/supply/qcom/smb-lib.h +7 −0 Original line number Diff line number Diff line Loading @@ -139,9 +139,14 @@ struct smb_irq_info { static const unsigned int smblib_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, EXTCON_USB_CC, EXTCON_USB_SPEED, EXTCON_NONE, }; /* EXTCON_USB and EXTCON_USB_HOST are mutually exclusive */ static const u32 smblib_extcon_exclusive[] = {0x3, 0}; struct smb_regulator { struct regulator_dev *rdev; struct regulator_desc rdesc; Loading Loading @@ -328,6 +333,8 @@ struct smb_charger { int usb_icl_change_irq_enabled; u32 jeita_status; u8 float_cfg; bool use_extcon; bool otg_present; /* workaround flag */ u32 wa_flags; Loading