Merge "power: qpnp-smb2: Force power-role to UFP by default"

tirimbino
qctecmdr 5 years ago committed by Gerrit - the friendly Code Review server
commit 35285f0517
  1. 5
      Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
  2. 46
      drivers/power/supply/qcom/qpnp-smb2.c
  3. 46
      drivers/power/supply/qcom/smb-lib.c
  4. 2
      drivers/power/supply/qcom/smb-lib.h

@ -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

@ -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;
}
@ -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
@ -1898,13 +1902,36 @@ static int smb2_post_init(struct smb2 *chip)
*/
rerun_election(chg->usb_icl_votable);
/* configure power role for dual-role */
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);
return rc;
/* 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,
TYPEC_POWER_ROLE_CMD_MASK, 0);
if (rc < 0) {
dev_err(chg->dev,
"Couldn't configure power role for DRP rc=%d\n",
rc);
return rc;
}
}
rerun_election(chg->usb_irq_enable_votable);
@ -2568,8 +2595,9 @@ static void smb2_shutdown(struct platform_device *pdev)
/* disable all interrupts */
smb2_disable_interrupts(chg);
/* configure power role for UFP */
smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
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);
/* force HVDCP to 5V */

@ -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;
@ -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 */
@ -1096,7 +1138,7 @@ static int __smblib_set_prop_typec_power_role(struct smb_charger *chg,
}
rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
TYPEC_POWER_ROLE_CMD_MASK, power_role);
TYPEC_POWER_ROLE_CMD_MASK, power_role);
if (rc < 0) {
smblib_err(chg, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
power_role, rc);
@ -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;
}

@ -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;
@ -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…
Cancel
Save