Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt +5 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,11 @@ Charger specific properties: Definition: Boolean flag which when present enables stepwise change in FCC. The default stepping rate is 100mA/sec. - qcom,ufp-only-mode Usage: optional Value type: bool Definition: Boolean flag which when present configure charger in SINK only mode. ============================================= Second Level Nodes - SMB2 Charger Peripherals Loading drivers/power/supply/qcom/qpnp-smb2.c +37 −9 Original line number Diff line number Diff line Loading @@ -339,6 +339,9 @@ static int smb2_parse_dt(struct smb2 *chip) chg->fcc_stepper_enable = of_property_read_bool(node, "qcom,fcc-stepping-enable"); chg->ufp_only_mode = of_property_read_bool(node, "qcom,ufp-only-mode"); return 0; } Loading Loading @@ -1891,6 +1894,7 @@ static int smb2_post_init(struct smb2 *chip) { struct smb_charger *chg = &chip->chg; int rc; u8 stat; /* In case the usb path is suspended, we would have missed disabling * the icl change interrupt because the interrupt could have been Loading @@ -1898,14 +1902,37 @@ static int smb2_post_init(struct smb2 *chip) */ rerun_election(chg->usb_icl_votable); /* Force charger in Sink Only mode */ if (chg->ufp_only_mode) { rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &stat); if (rc < 0) { dev_err(chg->dev, "Couldn't read SOFTWARE_CTRL_REG rc=%d\n", rc); return rc; } if (!(stat & UFP_EN_CMD_BIT)) { /* configure charger in UFP only mode */ rc = smblib_force_ufp(chg); if (rc < 0) { dev_err(chg->dev, "Couldn't force UFP mode rc=%d\n", rc); return rc; } } } else { /* configure power role for dual-role */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't configure power role for DRP rc=%d\n", rc); "Couldn't configure power role for DRP rc=%d\n", rc); return rc; } } rerun_election(chg->usb_irq_enable_votable); Loading Loading @@ -2568,6 +2595,7 @@ static void smb2_shutdown(struct platform_device *pdev) /* disable all interrupts */ smb2_disable_interrupts(chg); if (!chg->ufp_only_mode) /* configure power role for UFP */ smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, UFP_EN_CMD_BIT); Loading drivers/power/supply/qcom/smb-lib.c +45 −1 Original line number Diff line number Diff line Loading @@ -506,6 +506,43 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, /******************** * HELPER FUNCTIONS * ********************/ int smblib_force_ufp(struct smb_charger *chg) { int rc; /* force FSM in IDLE state */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT); if (rc < 0) { smblib_err(chg, "Couldn't put FSM in idle rc=%d\n", rc); return rc; } /* wait for FSM to enter idle state */ msleep(200); rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT | UFP_EN_CMD_BIT, UFP_EN_CMD_BIT); if (rc < 0) { smblib_err(chg, "Couldn't force UFP mode rc=%d\n", rc); return rc; } /* wait for mode change before enabling FSM */ usleep_range(10000, 11000); /* release FSM from idle state */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_DISABLE_CMD_BIT, 0); if (rc < 0) { smblib_err(chg, "Couldn't release FSM from idle rc=%d\n", rc); return rc; } return 0; } static int smblib_request_dpdm(struct smb_charger *chg, bool enable) { int rc = 0; Loading Loading @@ -1077,6 +1114,11 @@ static int __smblib_set_prop_typec_power_role(struct smb_charger *chg, return -EINVAL; } if (power_role != TYPEC_DISABLE_CMD_BIT) { if (chg->ufp_only_mode) power_role = UFP_EN_CMD_BIT; } if (chg->wa_flags & TYPEC_PBS_WA_BIT) { if (power_role == UFP_EN_CMD_BIT) { /* disable PBS workaround when forcing sink mode */ Loading Loading @@ -5227,6 +5269,8 @@ static int smblib_create_votables(struct smb_charger *chg) rc = PTR_ERR(chg->disable_power_role_switch); return rc; } vote(chg->disable_power_role_switch, DEFAULT_VOTER, chg->ufp_only_mode, 0); return rc; } Loading drivers/power/supply/qcom/smb-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -356,6 +356,7 @@ struct smb_charger { bool otg_present; bool disable_stat_sw_override; bool fcc_stepper_enable; bool ufp_only_mode; /* workaround flag */ u32 wa_flags; Loading Loading @@ -548,6 +549,7 @@ int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override); void smblib_usb_typec_change(struct smb_charger *chg); int smblib_toggle_stat(struct smb_charger *chg, int reset); int smblib_force_ufp(struct smb_charger *chg); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt +5 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,11 @@ Charger specific properties: Definition: Boolean flag which when present enables stepwise change in FCC. The default stepping rate is 100mA/sec. - qcom,ufp-only-mode Usage: optional Value type: bool Definition: Boolean flag which when present configure charger in SINK only mode. ============================================= Second Level Nodes - SMB2 Charger Peripherals Loading
drivers/power/supply/qcom/qpnp-smb2.c +37 −9 Original line number Diff line number Diff line Loading @@ -339,6 +339,9 @@ static int smb2_parse_dt(struct smb2 *chip) chg->fcc_stepper_enable = of_property_read_bool(node, "qcom,fcc-stepping-enable"); chg->ufp_only_mode = of_property_read_bool(node, "qcom,ufp-only-mode"); return 0; } Loading Loading @@ -1891,6 +1894,7 @@ static int smb2_post_init(struct smb2 *chip) { struct smb_charger *chg = &chip->chg; int rc; u8 stat; /* In case the usb path is suspended, we would have missed disabling * the icl change interrupt because the interrupt could have been Loading @@ -1898,14 +1902,37 @@ static int smb2_post_init(struct smb2 *chip) */ rerun_election(chg->usb_icl_votable); /* Force charger in Sink Only mode */ if (chg->ufp_only_mode) { rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &stat); if (rc < 0) { dev_err(chg->dev, "Couldn't read SOFTWARE_CTRL_REG rc=%d\n", rc); return rc; } if (!(stat & UFP_EN_CMD_BIT)) { /* configure charger in UFP only mode */ rc = smblib_force_ufp(chg); if (rc < 0) { dev_err(chg->dev, "Couldn't force UFP mode rc=%d\n", rc); return rc; } } } else { /* configure power role for dual-role */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't configure power role for DRP rc=%d\n", rc); "Couldn't configure power role for DRP rc=%d\n", rc); return rc; } } rerun_election(chg->usb_irq_enable_votable); Loading Loading @@ -2568,6 +2595,7 @@ static void smb2_shutdown(struct platform_device *pdev) /* disable all interrupts */ smb2_disable_interrupts(chg); if (!chg->ufp_only_mode) /* configure power role for UFP */ smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, UFP_EN_CMD_BIT); Loading
drivers/power/supply/qcom/smb-lib.c +45 −1 Original line number Diff line number Diff line Loading @@ -506,6 +506,43 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, /******************** * HELPER FUNCTIONS * ********************/ int smblib_force_ufp(struct smb_charger *chg) { int rc; /* force FSM in IDLE state */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT); if (rc < 0) { smblib_err(chg, "Couldn't put FSM in idle rc=%d\n", rc); return rc; } /* wait for FSM to enter idle state */ msleep(200); rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT | UFP_EN_CMD_BIT, UFP_EN_CMD_BIT); if (rc < 0) { smblib_err(chg, "Couldn't force UFP mode rc=%d\n", rc); return rc; } /* wait for mode change before enabling FSM */ usleep_range(10000, 11000); /* release FSM from idle state */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_DISABLE_CMD_BIT, 0); if (rc < 0) { smblib_err(chg, "Couldn't release FSM from idle rc=%d\n", rc); return rc; } return 0; } static int smblib_request_dpdm(struct smb_charger *chg, bool enable) { int rc = 0; Loading Loading @@ -1077,6 +1114,11 @@ static int __smblib_set_prop_typec_power_role(struct smb_charger *chg, return -EINVAL; } if (power_role != TYPEC_DISABLE_CMD_BIT) { if (chg->ufp_only_mode) power_role = UFP_EN_CMD_BIT; } if (chg->wa_flags & TYPEC_PBS_WA_BIT) { if (power_role == UFP_EN_CMD_BIT) { /* disable PBS workaround when forcing sink mode */ Loading Loading @@ -5227,6 +5269,8 @@ static int smblib_create_votables(struct smb_charger *chg) rc = PTR_ERR(chg->disable_power_role_switch); return rc; } vote(chg->disable_power_role_switch, DEFAULT_VOTER, chg->ufp_only_mode, 0); return rc; } Loading
drivers/power/supply/qcom/smb-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -356,6 +356,7 @@ struct smb_charger { bool otg_present; bool disable_stat_sw_override; bool fcc_stepper_enable; bool ufp_only_mode; /* workaround flag */ u32 wa_flags; Loading Loading @@ -548,6 +549,7 @@ int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override); void smblib_usb_typec_change(struct smb_charger *chg); int smblib_toggle_stat(struct smb_charger *chg, int reset); int smblib_force_ufp(struct smb_charger *chg); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading