From fe183ea9c0378e62bd566be613b1b86e4b1017e8 Mon Sep 17 00:00:00 2001 From: chailu1 Date: Thu, 30 Jul 2020 13:44:20 +0800 Subject: [PATCH] charge: Handle QC2.0 charger vbus rise 12V some non-standard QC2.0 charger (e.g. Tronsmart) will rise vbus to 12V when phone do HVDCP3 detect protocol. So when vbus reach 12V, we disable HVDCP to workaround it. refer to (CR) Change-Id: I1a1fbf1715ac6fbd12a9cd550207b210f16a951d Signed-off-by: chailu1 Reviewed-on: https://gerrit.mot.com/1709435 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 4 +++ drivers/power/supply/qcom/smb5-lib.c | 42 +++++++++++++++++++++++++-- drivers/power/supply/qcom/smb5-lib.h | 5 +++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index d86f81f0160a..53a8c9316f1b 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -648,6 +648,9 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) if (chg->chg_param.qc4_max_icl_ua <= 0) chg->chg_param.qc4_max_icl_ua = MICRO_4PA; + chg->ext_ovp_greater_12v = of_property_read_bool(node, + "mmi,ext-ovp-greater-12v"); + return 0; } @@ -4260,6 +4263,7 @@ static int smb5_probe(struct platform_device *pdev) chg->connector_health = -EINVAL; chg->otg_present = false; chg->main_fcc_max = -EINVAL; + chg->qc_usbov = false; mutex_init(&chg->adc_lock); chg->regmap = dev_get_regmap(chg->dev->parent, NULL); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 8403bfa4dfa0..5a6f8cffef96 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -574,12 +574,12 @@ static const struct apsd_result smblib_apsd_results[] = { [HVDCP2] = { .name = "HVDCP2", .bit = DCP_CHARGER_BIT | QC_2P0_BIT, - .pst = POWER_SUPPLY_TYPE_USB_DCP + .pst = POWER_SUPPLY_TYPE_USB_HVDCP }, [HVDCP3] = { .name = "HVDCP3", .bit = DCP_CHARGER_BIT | QC_3P0_BIT, - .pst = POWER_SUPPLY_TYPE_USB_DCP, + .pst = POWER_SUPPLY_TYPE_USB_HVDCP_3, }, }; @@ -1156,6 +1156,26 @@ void smblib_hvdcp_hw_inov_enable(struct smb_charger *chg, bool enable) rc); } +void smblib_hvdcp_enable_mmi(struct smb_charger *chg, bool enable) +{ + int rc; + u8 mask; + + if (chg->hvdcp_disable) + return; + + mask = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT; + rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, mask, + enable ? mask : 0); + if (rc < 0) + smblib_err(chg, "MMI failed to write USBIN_OPTIONS_1_CFG rc=%d\n", + rc); + else + chg->hvdcp_is_disable = enable ? false : true; + + return; +} + void smblib_hvdcp_exit_config(struct smb_charger *chg) { u8 stat; @@ -6875,6 +6895,14 @@ static void typec_src_removal(struct smb_charger *chg) chg->qc2_unsupported_voltage = QC2_COMPLIANT; } + if (chg->hvdcp_is_disable && + ((!chg->ext_ovp_greater_12v && !chg->qc_usbov) || + (chg->ext_ovp_greater_12v && chg->qc_usbov))) { + smblib_err(chg, "Re-enable HVDCP as type-c removal\n"); + smblib_hvdcp_enable_mmi(chg, true); + } + chg->qc_usbov = false; + if (chg->use_extcon) smblib_notify_device_mode(chg, false); @@ -7684,6 +7712,16 @@ irqreturn_t usbin_ov_irq_handler(int irq, void *data) smblib_dbg(chg, PR_MISC, "USBOV debounce status %d\n", chg->dbc_usbov); + + if ((!chg->qc_usbov) && + (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP || + chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3)) { + smblib_err(chg, "QC vbus OV disable HVDCP\n"); + chg->qc_usbov = true; + smblib_hvdcp_enable_mmi(chg, false); + smblib_rerun_apsd(chg); + } + return IRQ_HANDLED; } diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 02e3dce199d6..49bb1bfeebc1 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -738,7 +738,10 @@ struct smb_charger { int qc2_max_pulses; enum qc2_non_comp_voltage qc2_unsupported_voltage; bool dbc_usbov; - + bool qc_usbov; + bool hvdcp_is_disable; + /*if external ovp threshold greater than 12V*/ + bool ext_ovp_greater_12v; /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon;