Loading drivers/power/supply/qcom/smb-lib.c +75 −2 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -3291,6 +3291,9 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data) struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; struct storm_watch *wdata; const struct apsd_result *apsd = smblib_get_apsd_result(chg); int rc; u8 stat = 0, max_pulses = 0; smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); if (!chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data) Loading @@ -3298,6 +3301,54 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data) wdata = &chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data->storm_data; reset_storm_count(wdata); if (!chg->non_compliant_chg_detected && apsd->pst == POWER_SUPPLY_TYPE_USB_HVDCP) { rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat); if (rc < 0) smblib_err(chg, "Couldn't read CHANGE_STATUS_REG rc=%d\n", rc); if (stat & QC_5V_BIT) return IRQ_HANDLED; rc = smblib_read(chg, HVDCP_PULSE_COUNT_MAX_REG, &max_pulses); if (rc < 0) smblib_err(chg, "Couldn't read QC2 max pulses rc=%d\n", rc); chg->non_compliant_chg_detected = true; chg->qc2_max_pulses = (max_pulses & HVDCP_PULSE_COUNT_MAX_QC2_MASK); if (stat & QC_12V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_9V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 9V rc=%d\n", rc); } else if (stat & QC_9V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_5V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 5V rc=%d\n", rc); } rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, 0); if (rc < 0) smblib_err(chg, "Couldn't turn off SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); smblib_rerun_apsd(chg); } return IRQ_HANDLED; } Loading Loading @@ -4068,6 +4119,28 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) if (rc < 0) smblib_err(chg, "Couldn't set 120mS tCC debounce rc=%d\n", rc); /* * if non-compliant charger caused UV, restore original max pulses * and turn SUSPEND_ON_COLLAPSE_USBIN_BIT back on. */ if (chg->non_compliant_chg_detected) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, chg->qc2_max_pulses); if (rc < 0) smblib_err(chg, "Couldn't restore max pulses rc=%d\n", rc); rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, SUSPEND_ON_COLLAPSE_USBIN_BIT); if (rc < 0) smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); chg->non_compliant_chg_detected = false; } /* enable APSD CC trigger for next insertion */ rc = smblib_masked_write(chg, TYPE_C_CFG_REG, APSD_START_ON_CC_BIT, APSD_START_ON_CC_BIT); Loading drivers/power/supply/qcom/smb-lib.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -352,6 +352,8 @@ struct smb_charger { bool try_sink_active; int boost_current_ua; int temp_speed_reading_count; int qc2_max_pulses; bool non_compliant_chg_detected; /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; Loading drivers/power/supply/qcom/smb-reg.h +10 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -587,6 +587,15 @@ enum { #define EN_LEGACY_CABLE_DETECTION_BIT BIT(1) #define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0) #define HVDCP_PULSE_COUNT_MAX_REG (USBIN_BASE + 0x5B) #define HVDCP_PULSE_COUNT_MAX_QC2_MASK GENMASK(7, 6) enum { HVDCP_PULSE_COUNT_MAX_QC2_5V, HVDCP_PULSE_COUNT_MAX_QC2_9V, HVDCP_PULSE_COUNT_MAX_QC2_12V, HVDCP_PULSE_COUNT_MAX_QC2_INVALID }; #define USBIN_ADAPTER_ALLOW_CFG_REG (USBIN_BASE + 0x60) #define USBIN_ADAPTER_ALLOW_MASK GENMASK(3, 0) enum { Loading drivers/power/supply/qcom/smb5-lib.c +73 −0 Original line number Diff line number Diff line Loading @@ -2934,6 +2934,9 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data) struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; struct storm_watch *wdata; const struct apsd_result *apsd = smblib_get_apsd_result(chg); int rc; u8 stat = 0, max_pulses = 0; smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); if (!chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data) Loading @@ -2941,6 +2944,54 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data) wdata = &chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data->storm_data; reset_storm_count(wdata); if (!chg->non_compliant_chg_detected && apsd->pst == POWER_SUPPLY_TYPE_USB_HVDCP) { rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat); if (rc < 0) smblib_err(chg, "Couldn't read CHANGE_STATUS_REG rc=%d\n", rc); if (stat & QC_5V_BIT) return IRQ_HANDLED; rc = smblib_read(chg, HVDCP_PULSE_COUNT_MAX_REG, &max_pulses); if (rc < 0) smblib_err(chg, "Couldn't read QC2 max pulses rc=%d\n", rc); chg->non_compliant_chg_detected = true; chg->qc2_max_pulses = (max_pulses & HVDCP_PULSE_COUNT_MAX_QC2_MASK); if (stat & QC_12V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_9V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 9V rc=%d\n", rc); } else if (stat & QC_9V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_5V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 5V rc=%d\n", rc); } rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, 0); if (rc < 0) smblib_err(chg, "Couldn't turn off SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); smblib_rerun_apsd(chg); } return IRQ_HANDLED; } Loading Loading @@ -3514,6 +3565,28 @@ static void typec_src_removal(struct smb_charger *chg) smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n", rc); /* * if non-compliant charger caused UV, restore original max pulses * and turn SUSPEND_ON_COLLAPSE_USBIN_BIT back on. */ if (chg->non_compliant_chg_detected) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, chg->qc2_max_pulses); if (rc < 0) smblib_err(chg, "Couldn't restore max pulses rc=%d\n", rc); rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, SUSPEND_ON_COLLAPSE_USBIN_BIT); if (rc < 0) smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); chg->non_compliant_chg_detected = false; } if (chg->use_extcon) smblib_notify_device_mode(chg, false); Loading drivers/power/supply/qcom/smb5-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -367,6 +367,8 @@ struct smb_charger { /* workaround flag */ u32 wa_flags; int boost_current_ua; int qc2_max_pulses; bool non_compliant_chg_detected; /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; Loading Loading
drivers/power/supply/qcom/smb-lib.c +75 −2 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -3291,6 +3291,9 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data) struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; struct storm_watch *wdata; const struct apsd_result *apsd = smblib_get_apsd_result(chg); int rc; u8 stat = 0, max_pulses = 0; smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); if (!chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data) Loading @@ -3298,6 +3301,54 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data) wdata = &chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data->storm_data; reset_storm_count(wdata); if (!chg->non_compliant_chg_detected && apsd->pst == POWER_SUPPLY_TYPE_USB_HVDCP) { rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat); if (rc < 0) smblib_err(chg, "Couldn't read CHANGE_STATUS_REG rc=%d\n", rc); if (stat & QC_5V_BIT) return IRQ_HANDLED; rc = smblib_read(chg, HVDCP_PULSE_COUNT_MAX_REG, &max_pulses); if (rc < 0) smblib_err(chg, "Couldn't read QC2 max pulses rc=%d\n", rc); chg->non_compliant_chg_detected = true; chg->qc2_max_pulses = (max_pulses & HVDCP_PULSE_COUNT_MAX_QC2_MASK); if (stat & QC_12V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_9V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 9V rc=%d\n", rc); } else if (stat & QC_9V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_5V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 5V rc=%d\n", rc); } rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, 0); if (rc < 0) smblib_err(chg, "Couldn't turn off SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); smblib_rerun_apsd(chg); } return IRQ_HANDLED; } Loading Loading @@ -4068,6 +4119,28 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) if (rc < 0) smblib_err(chg, "Couldn't set 120mS tCC debounce rc=%d\n", rc); /* * if non-compliant charger caused UV, restore original max pulses * and turn SUSPEND_ON_COLLAPSE_USBIN_BIT back on. */ if (chg->non_compliant_chg_detected) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, chg->qc2_max_pulses); if (rc < 0) smblib_err(chg, "Couldn't restore max pulses rc=%d\n", rc); rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, SUSPEND_ON_COLLAPSE_USBIN_BIT); if (rc < 0) smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); chg->non_compliant_chg_detected = false; } /* enable APSD CC trigger for next insertion */ rc = smblib_masked_write(chg, TYPE_C_CFG_REG, APSD_START_ON_CC_BIT, APSD_START_ON_CC_BIT); Loading
drivers/power/supply/qcom/smb-lib.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -352,6 +352,8 @@ struct smb_charger { bool try_sink_active; int boost_current_ua; int temp_speed_reading_count; int qc2_max_pulses; bool non_compliant_chg_detected; /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; Loading
drivers/power/supply/qcom/smb-reg.h +10 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -587,6 +587,15 @@ enum { #define EN_LEGACY_CABLE_DETECTION_BIT BIT(1) #define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0) #define HVDCP_PULSE_COUNT_MAX_REG (USBIN_BASE + 0x5B) #define HVDCP_PULSE_COUNT_MAX_QC2_MASK GENMASK(7, 6) enum { HVDCP_PULSE_COUNT_MAX_QC2_5V, HVDCP_PULSE_COUNT_MAX_QC2_9V, HVDCP_PULSE_COUNT_MAX_QC2_12V, HVDCP_PULSE_COUNT_MAX_QC2_INVALID }; #define USBIN_ADAPTER_ALLOW_CFG_REG (USBIN_BASE + 0x60) #define USBIN_ADAPTER_ALLOW_MASK GENMASK(3, 0) enum { Loading
drivers/power/supply/qcom/smb5-lib.c +73 −0 Original line number Diff line number Diff line Loading @@ -2934,6 +2934,9 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data) struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; struct storm_watch *wdata; const struct apsd_result *apsd = smblib_get_apsd_result(chg); int rc; u8 stat = 0, max_pulses = 0; smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); if (!chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data) Loading @@ -2941,6 +2944,54 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data) wdata = &chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data->storm_data; reset_storm_count(wdata); if (!chg->non_compliant_chg_detected && apsd->pst == POWER_SUPPLY_TYPE_USB_HVDCP) { rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat); if (rc < 0) smblib_err(chg, "Couldn't read CHANGE_STATUS_REG rc=%d\n", rc); if (stat & QC_5V_BIT) return IRQ_HANDLED; rc = smblib_read(chg, HVDCP_PULSE_COUNT_MAX_REG, &max_pulses); if (rc < 0) smblib_err(chg, "Couldn't read QC2 max pulses rc=%d\n", rc); chg->non_compliant_chg_detected = true; chg->qc2_max_pulses = (max_pulses & HVDCP_PULSE_COUNT_MAX_QC2_MASK); if (stat & QC_12V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_9V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 9V rc=%d\n", rc); } else if (stat & QC_9V_BIT) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, HVDCP_PULSE_COUNT_MAX_QC2_5V); if (rc < 0) smblib_err(chg, "Couldn't force max pulses to 5V rc=%d\n", rc); } rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, 0); if (rc < 0) smblib_err(chg, "Couldn't turn off SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); smblib_rerun_apsd(chg); } return IRQ_HANDLED; } Loading Loading @@ -3514,6 +3565,28 @@ static void typec_src_removal(struct smb_charger *chg) smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n", rc); /* * if non-compliant charger caused UV, restore original max pulses * and turn SUSPEND_ON_COLLAPSE_USBIN_BIT back on. */ if (chg->non_compliant_chg_detected) { rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, HVDCP_PULSE_COUNT_MAX_QC2_MASK, chg->qc2_max_pulses); if (rc < 0) smblib_err(chg, "Couldn't restore max pulses rc=%d\n", rc); rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, SUSPEND_ON_COLLAPSE_USBIN_BIT, SUSPEND_ON_COLLAPSE_USBIN_BIT); if (rc < 0) smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", rc); chg->non_compliant_chg_detected = false; } if (chg->use_extcon) smblib_notify_device_mode(chg, false); Loading
drivers/power/supply/qcom/smb5-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -367,6 +367,8 @@ struct smb_charger { /* workaround flag */ u32 wa_flags; int boost_current_ua; int qc2_max_pulses; bool non_compliant_chg_detected; /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; Loading