Loading drivers/power/supply/qcom/pmic-voter.c +2 −2 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * Copyright (c) 2015-2017, 2019 The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> Loading @@ -13,7 +13,7 @@ #include <linux/pmic-voter.h> #define NUM_MAX_CLIENTS 16 #define NUM_MAX_CLIENTS 32 #define DEBUG_FORCE_CLIENT "DEBUG_FORCE_CLIENT" static DEFINE_SPINLOCK(votable_list_slock); Loading drivers/power/supply/qcom/qpnp-smb5.c +49 −51 Original line number Diff line number Diff line Loading @@ -206,6 +206,7 @@ struct smb_dt_props { bool no_battery; bool hvdcp_disable; bool hvdcp_autonomous; bool adc_based_aicl; int sec_charger_config; int auto_recharge_soc; int auto_recharge_vbat_mv; Loading Loading @@ -549,6 +550,9 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) chip->dt.disable_suspend_on_collapse = of_property_read_bool(node, "qcom,disable-suspend-on-collapse"); chip->dt.adc_based_aicl = of_property_read_bool(node, "qcom,adc-based-aicl"); return 0; } Loading @@ -560,18 +564,11 @@ static int smb5_parse_dt_adc_channels(struct smb_charger *chg) if (rc < 0) return rc; if (!chg->iio.mid_chan) { rc = smblib_get_iio_channel(chg, "usb_in_voltage", &chg->iio.usbin_v_chan); if (rc < 0) return rc; if (!chg->iio.usbin_v_chan) { dev_err(chg->dev, "No voltage channel defined\n"); return -EINVAL; } } rc = smblib_get_iio_channel(chg, "chg_temp", &chg->iio.temp_chan); if (rc < 0) return rc; Loading Loading @@ -1288,6 +1285,7 @@ static enum power_supply_property smb5_dc_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION, POWER_SUPPLY_PROP_REAL_TYPE, POWER_SUPPLY_PROP_DC_RESET, }; static int smb5_dc_get_prop(struct power_supply *psy, Loading Loading @@ -1322,6 +1320,8 @@ static int smb5_dc_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION: rc = smblib_get_prop_voltage_wls_output(chg, val); case POWER_SUPPLY_PROP_DC_RESET: val->intval = 0; break; default: return -EINVAL; Loading Loading @@ -1352,6 +1352,9 @@ static int smb5_dc_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION: rc = smblib_set_prop_voltage_wls_output(chg, val); break; case POWER_SUPPLY_PROP_DC_RESET: rc = smblib_set_prop_dc_reset(chg); break; default: return -EINVAL; } Loading Loading @@ -1917,14 +1920,17 @@ static int smb5_configure_typec(struct smb_charger *chg) return rc; } if (chg->smb_version != PMI632_SUBTYPE) { rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG, USBIN_IN_COLLAPSE_GF_SEL_MASK | USBIN_AICL_STEP_TIMING_SEL_MASK, USBIN_IN_COLLAPSE_GF_SEL_MASK | USBIN_AICL_STEP_TIMING_SEL_MASK, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't set USBIN_LOAD_CFG_REG rc=%d\n", rc); return rc; } } /* Set CC threshold to 1.6 V in source mode */ rc = smblib_masked_write(chg, TYPE_C_EXIT_STATE_CFG_REG, Loading Loading @@ -2215,40 +2221,32 @@ static int smb5_configure_recharging(struct smb5 *chip) static int smb5_configure_float_charger(struct smb5 *chip) { int rc = 0; u8 val = 0; struct smb_charger *chg = &chip->chg; /* configure float charger options */ switch (chip->dt.float_option) { case FLOAT_DCP: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, 0); break; case FLOAT_SDP: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT); val = FORCE_FLOAT_SDP_CFG_BIT; break; case DISABLE_CHARGING: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT); val = FLOAT_DIS_CHGING_CFG_BIT; break; case SUSPEND_INPUT: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT); val = SUSPEND_FLOAT_CFG_BIT; break; case FLOAT_DCP: default: rc = 0; val = 0; break; } chg->float_cfg = val; /* Update float charger setting and set DCD timeout 300ms */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK | DCD_TIMEOUT_SEL_BIT, val); if (rc < 0) { dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n", rc); return rc; } rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg); if (rc < 0) { dev_err(chg->dev, "Couldn't read float charger options rc=%d\n", dev_err(chg->dev, "Couldn't change float charger setting rc=%d\n", rc); return rc; } Loading Loading @@ -2434,15 +2432,16 @@ static int smb5_init_hw(struct smb5 *chip) return rc; /* * AICL configuration: * start from min and AICL ADC disable, and enable aicl rerun * AICL configuration: enable aicl and aicl rerun and based on DT * configuration enable/disable ADB based AICL and Suspend on collapse. */ if (chg->smb_version != PMI632_SUBTYPE) { mask = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_ADC_EN_BIT | USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT; val = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_EN_BIT; if (!chip->dt.disable_suspend_on_collapse) val |= SUSPEND_ON_COLLAPSE_USBIN_BIT; if (chip->dt.adc_based_aicl) val |= USBIN_AICL_ADC_EN_BIT; rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, mask, val); Loading @@ -2450,7 +2449,6 @@ static int smb5_init_hw(struct smb5 *chip) dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc); return rc; } } rc = smblib_write(chg, AICL_RERUN_TIME_CFG_REG, AICL_RERUN_TIME_12S_VAL); Loading drivers/power/supply/qcom/smb5-lib.c +130 −8 Original line number Diff line number Diff line Loading @@ -322,11 +322,14 @@ static void smblib_notify_extcon_props(struct smb_charger *chg, int id) val.intval = ((prop_val.intval == 2) ? 1 : 0); extcon_set_property(chg->extcon, id, EXTCON_PROP_USB_TYPEC_POLARITY, val); } val.intval = true; extcon_set_property(chg->extcon, id, EXTCON_PROP_USB_SS, val); } else if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) { val.intval = false; extcon_set_property(chg->extcon, id, EXTCON_PROP_USB_SS, val); } } static void smblib_notify_device_mode(struct smb_charger *chg, bool enable) Loading Loading @@ -2923,6 +2926,57 @@ int smblib_set_prop_voltage_wls_output(struct smb_charger *chg, return rc; } int smblib_set_prop_dc_reset(struct smb_charger *chg) { int rc; rc = vote(chg->dc_suspend_votable, VOUT_VOTER, true, 0); if (rc < 0) { smblib_err(chg, "Couldn't suspend DC rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_EN_MASK, DCIN_EN_OVERRIDE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't set DCIN_EN_OVERRIDE_BIT rc=%d\n", rc); return rc; } rc = smblib_write(chg, DCIN_CMD_PON_REG, DCIN_PON_BIT | MID_CHG_BIT); if (rc < 0) { smblib_err(chg, "Couldn't write %d to DCIN_CMD_PON_REG rc=%d\n", DCIN_PON_BIT | MID_CHG_BIT, rc); return rc; } /* Wait for 10ms to allow the charge to get drained */ usleep_range(10000, 10010); rc = smblib_write(chg, DCIN_CMD_PON_REG, 0); if (rc < 0) { smblib_err(chg, "Couldn't clear DCIN_CMD_PON_REG rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_EN_MASK, 0); if (rc < 0) { smblib_err(chg, "Couldn't clear DCIN_EN_OVERRIDE_BIT rc=%d\n", rc); return rc; } rc = vote(chg->dc_suspend_votable, VOUT_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't unsuspend DC rc=%d\n", rc); return rc; } smblib_dbg(chg, PR_MISC, "Wireless charger removal detection successful\n"); return rc; } /******************* * USB PSY GETTERS * *******************/ Loading Loading @@ -3643,7 +3697,7 @@ int smblib_get_prop_scope(struct smb_charger *chg, return 0; } int smblib_get_prop_connector_health(struct smb_charger *chg) static int smblib_get_typec_connector_temp_status(struct smb_charger *chg) { int rc; u8 stat; Loading Loading @@ -3686,6 +3740,56 @@ int smblib_get_prop_connector_health(struct smb_charger *chg) return POWER_SUPPLY_HEALTH_COOL; } static int smblib_get_skin_temp_status(struct smb_charger *chg) { int rc; u8 stat; rc = smblib_read(chg, SKIN_TEMP_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read SKIN_TEMP_STATUS_REG, rc=%d\n", rc); return POWER_SUPPLY_HEALTH_UNKNOWN; } if (stat & SKIN_TEMP_RST_BIT) return POWER_SUPPLY_HEALTH_OVERHEAT; if (stat & SKIN_TEMP_UB_BIT) return POWER_SUPPLY_HEALTH_HOT; if (stat & SKIN_TEMP_LB_BIT) return POWER_SUPPLY_HEALTH_WARM; return POWER_SUPPLY_HEALTH_COOL; } int smblib_get_prop_connector_health(struct smb_charger *chg) { bool dc_present, usb_present; int input_present; int rc; rc = smblib_is_input_present(chg, &input_present); if (rc < 0) return POWER_SUPPLY_HEALTH_UNKNOWN; dc_present = input_present & INPUT_PRESENT_DC; usb_present = input_present & INPUT_PRESENT_USB; if (usb_present) return smblib_get_typec_connector_temp_status(chg); /* * In PM8150B, SKIN channel measures Wireless charger receiver * temp, used to regulate DC ICL. */ if (chg->smb_version == PM8150B_SUBTYPE && dc_present) return smblib_get_skin_temp_status(chg); return POWER_SUPPLY_HEALTH_COOL; } static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) { int rp_ua; Loading Loading @@ -3735,12 +3839,12 @@ static int smblib_handle_usb_current(struct smb_charger *chg, * Confiugure USB500 mode if Float charger is * configured for SDP mode. */ rc = set_sdp_current(chg, USBIN_500MA); rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, USBIN_500MA); if (rc < 0) smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc); return rc; } Loading Loading @@ -4854,6 +4958,11 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) if (chg->pd_active) return; if (chg->typec_mode == POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, 500000); return; } /* * HVDCP 2/3, handled separately */ Loading Loading @@ -5138,6 +5247,14 @@ static void typec_src_insertion(struct smb_charger *chg) smblib_hvdcp_detect_try_enable(chg, true); } static void typec_ra_ra_insertion(struct smb_charger *chg) { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, 500000); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); chg->ok_to_pd = false; smblib_hvdcp_detect_enable(chg, true); } static void typec_sink_removal(struct smb_charger *chg) { int rc; Loading Loading @@ -5437,7 +5554,11 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) return IRQ_HANDLED; } if (stat & SNK_SRC_MODE_BIT) { if (smblib_get_prop_dfp_mode(chg) == POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) { chg->sink_src_mode = AUDIO_ACCESS_MODE; typec_ra_ra_insertion(chg); } else if (stat & SNK_SRC_MODE_BIT) { if (smblib_src_lpd(chg)) return IRQ_HANDLED; chg->sink_src_mode = SRC_MODE; Loading @@ -5453,6 +5574,7 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) typec_sink_removal(chg); break; case SINK_MODE: case AUDIO_ACCESS_MODE: typec_src_removal(chg); break; case UNATTACHED_MODE: Loading drivers/power/supply/qcom/smb5-lib.h +3 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ enum print_reason { #define USBOV_DBC_VOTER "USBOV_DBC_VOTER" #define CHG_TERMINATION_VOTER "CHG_TERMINATION_VOTER" #define THERMAL_THROTTLE_VOTER "THERMAL_THROTTLE_VOTER" #define VOUT_VOTER "VOUT_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -94,6 +95,7 @@ enum smb_mode { enum sink_src_mode { SINK_MODE, SRC_MODE, AUDIO_ACCESS_MODE, UNATTACHED_MODE, }; Loading Loading @@ -632,6 +634,7 @@ int smblib_get_prop_voltage_wls_output(struct smb_charger *chg, union power_supply_propval *val); int smblib_set_prop_voltage_wls_output(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_dc_reset(struct smb_charger *chg); int smblib_get_prop_usb_present(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_usb_online(struct smb_charger *chg, Loading drivers/power/supply/qcom/smb5-reg.h +13 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,7 @@ enum { #define HVDCP_EN_BIT BIT(2) #define USBIN_OPTIONS_2_CFG_REG (USBIN_BASE + 0x63) #define DCD_TIMEOUT_SEL_BIT BIT(5) #define FLOAT_OPTIONS_MASK GENMASK(2, 0) #define FLOAT_DIS_CHGING_CFG_BIT BIT(2) #define SUSPEND_FLOAT_CFG_BIT BIT(1) Loading Loading @@ -317,6 +318,12 @@ enum { #define DCIN_CMD_IL_REG (DCIN_BASE + 0x40) #define DCIN_SUSPEND_BIT BIT(0) #define DCIN_EN_OVERRIDE_BIT BIT(1) #define DCIN_EN_MASK GENMASK(2, 1) #define DCIN_CMD_PON_REG (DCIN_BASE + 0x45) #define DCIN_PON_BIT BIT(0) #define MID_CHG_BIT BIT(1) #define DCIN_LOAD_CFG_REG (DCIN_BASE + 0x65) #define INPUT_MISS_POLL_EN_BIT BIT(5) Loading Loading @@ -461,6 +468,12 @@ enum { #define DIE_TEMP_UB_BIT BIT(1) #define DIE_TEMP_LB_BIT BIT(0) #define SKIN_TEMP_STATUS_REG (MISC_BASE + 0x08) #define SKIN_TEMP_SHDN_BIT BIT(3) #define SKIN_TEMP_RST_BIT BIT(2) #define SKIN_TEMP_UB_BIT BIT(1) #define SKIN_TEMP_LB_BIT BIT(0) #define CONNECTOR_TEMP_STATUS_REG (MISC_BASE + 0x09) #define CONNECTOR_TEMP_SHDN_BIT BIT(3) #define CONNECTOR_TEMP_RST_BIT BIT(2) Loading Loading
drivers/power/supply/qcom/pmic-voter.c +2 −2 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * Copyright (c) 2015-2017, 2019 The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> Loading @@ -13,7 +13,7 @@ #include <linux/pmic-voter.h> #define NUM_MAX_CLIENTS 16 #define NUM_MAX_CLIENTS 32 #define DEBUG_FORCE_CLIENT "DEBUG_FORCE_CLIENT" static DEFINE_SPINLOCK(votable_list_slock); Loading
drivers/power/supply/qcom/qpnp-smb5.c +49 −51 Original line number Diff line number Diff line Loading @@ -206,6 +206,7 @@ struct smb_dt_props { bool no_battery; bool hvdcp_disable; bool hvdcp_autonomous; bool adc_based_aicl; int sec_charger_config; int auto_recharge_soc; int auto_recharge_vbat_mv; Loading Loading @@ -549,6 +550,9 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) chip->dt.disable_suspend_on_collapse = of_property_read_bool(node, "qcom,disable-suspend-on-collapse"); chip->dt.adc_based_aicl = of_property_read_bool(node, "qcom,adc-based-aicl"); return 0; } Loading @@ -560,18 +564,11 @@ static int smb5_parse_dt_adc_channels(struct smb_charger *chg) if (rc < 0) return rc; if (!chg->iio.mid_chan) { rc = smblib_get_iio_channel(chg, "usb_in_voltage", &chg->iio.usbin_v_chan); if (rc < 0) return rc; if (!chg->iio.usbin_v_chan) { dev_err(chg->dev, "No voltage channel defined\n"); return -EINVAL; } } rc = smblib_get_iio_channel(chg, "chg_temp", &chg->iio.temp_chan); if (rc < 0) return rc; Loading Loading @@ -1288,6 +1285,7 @@ static enum power_supply_property smb5_dc_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION, POWER_SUPPLY_PROP_REAL_TYPE, POWER_SUPPLY_PROP_DC_RESET, }; static int smb5_dc_get_prop(struct power_supply *psy, Loading Loading @@ -1322,6 +1320,8 @@ static int smb5_dc_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION: rc = smblib_get_prop_voltage_wls_output(chg, val); case POWER_SUPPLY_PROP_DC_RESET: val->intval = 0; break; default: return -EINVAL; Loading Loading @@ -1352,6 +1352,9 @@ static int smb5_dc_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION: rc = smblib_set_prop_voltage_wls_output(chg, val); break; case POWER_SUPPLY_PROP_DC_RESET: rc = smblib_set_prop_dc_reset(chg); break; default: return -EINVAL; } Loading Loading @@ -1917,14 +1920,17 @@ static int smb5_configure_typec(struct smb_charger *chg) return rc; } if (chg->smb_version != PMI632_SUBTYPE) { rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG, USBIN_IN_COLLAPSE_GF_SEL_MASK | USBIN_AICL_STEP_TIMING_SEL_MASK, USBIN_IN_COLLAPSE_GF_SEL_MASK | USBIN_AICL_STEP_TIMING_SEL_MASK, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't set USBIN_LOAD_CFG_REG rc=%d\n", rc); return rc; } } /* Set CC threshold to 1.6 V in source mode */ rc = smblib_masked_write(chg, TYPE_C_EXIT_STATE_CFG_REG, Loading Loading @@ -2215,40 +2221,32 @@ static int smb5_configure_recharging(struct smb5 *chip) static int smb5_configure_float_charger(struct smb5 *chip) { int rc = 0; u8 val = 0; struct smb_charger *chg = &chip->chg; /* configure float charger options */ switch (chip->dt.float_option) { case FLOAT_DCP: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, 0); break; case FLOAT_SDP: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT); val = FORCE_FLOAT_SDP_CFG_BIT; break; case DISABLE_CHARGING: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT); val = FLOAT_DIS_CHGING_CFG_BIT; break; case SUSPEND_INPUT: rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT); val = SUSPEND_FLOAT_CFG_BIT; break; case FLOAT_DCP: default: rc = 0; val = 0; break; } chg->float_cfg = val; /* Update float charger setting and set DCD timeout 300ms */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, FLOAT_OPTIONS_MASK | DCD_TIMEOUT_SEL_BIT, val); if (rc < 0) { dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n", rc); return rc; } rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg); if (rc < 0) { dev_err(chg->dev, "Couldn't read float charger options rc=%d\n", dev_err(chg->dev, "Couldn't change float charger setting rc=%d\n", rc); return rc; } Loading Loading @@ -2434,15 +2432,16 @@ static int smb5_init_hw(struct smb5 *chip) return rc; /* * AICL configuration: * start from min and AICL ADC disable, and enable aicl rerun * AICL configuration: enable aicl and aicl rerun and based on DT * configuration enable/disable ADB based AICL and Suspend on collapse. */ if (chg->smb_version != PMI632_SUBTYPE) { mask = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_ADC_EN_BIT | USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT; val = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_EN_BIT; if (!chip->dt.disable_suspend_on_collapse) val |= SUSPEND_ON_COLLAPSE_USBIN_BIT; if (chip->dt.adc_based_aicl) val |= USBIN_AICL_ADC_EN_BIT; rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, mask, val); Loading @@ -2450,7 +2449,6 @@ static int smb5_init_hw(struct smb5 *chip) dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc); return rc; } } rc = smblib_write(chg, AICL_RERUN_TIME_CFG_REG, AICL_RERUN_TIME_12S_VAL); Loading
drivers/power/supply/qcom/smb5-lib.c +130 −8 Original line number Diff line number Diff line Loading @@ -322,11 +322,14 @@ static void smblib_notify_extcon_props(struct smb_charger *chg, int id) val.intval = ((prop_val.intval == 2) ? 1 : 0); extcon_set_property(chg->extcon, id, EXTCON_PROP_USB_TYPEC_POLARITY, val); } val.intval = true; extcon_set_property(chg->extcon, id, EXTCON_PROP_USB_SS, val); } else if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) { val.intval = false; extcon_set_property(chg->extcon, id, EXTCON_PROP_USB_SS, val); } } static void smblib_notify_device_mode(struct smb_charger *chg, bool enable) Loading Loading @@ -2923,6 +2926,57 @@ int smblib_set_prop_voltage_wls_output(struct smb_charger *chg, return rc; } int smblib_set_prop_dc_reset(struct smb_charger *chg) { int rc; rc = vote(chg->dc_suspend_votable, VOUT_VOTER, true, 0); if (rc < 0) { smblib_err(chg, "Couldn't suspend DC rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_EN_MASK, DCIN_EN_OVERRIDE_BIT); if (rc < 0) { smblib_err(chg, "Couldn't set DCIN_EN_OVERRIDE_BIT rc=%d\n", rc); return rc; } rc = smblib_write(chg, DCIN_CMD_PON_REG, DCIN_PON_BIT | MID_CHG_BIT); if (rc < 0) { smblib_err(chg, "Couldn't write %d to DCIN_CMD_PON_REG rc=%d\n", DCIN_PON_BIT | MID_CHG_BIT, rc); return rc; } /* Wait for 10ms to allow the charge to get drained */ usleep_range(10000, 10010); rc = smblib_write(chg, DCIN_CMD_PON_REG, 0); if (rc < 0) { smblib_err(chg, "Couldn't clear DCIN_CMD_PON_REG rc=%d\n", rc); return rc; } rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_EN_MASK, 0); if (rc < 0) { smblib_err(chg, "Couldn't clear DCIN_EN_OVERRIDE_BIT rc=%d\n", rc); return rc; } rc = vote(chg->dc_suspend_votable, VOUT_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't unsuspend DC rc=%d\n", rc); return rc; } smblib_dbg(chg, PR_MISC, "Wireless charger removal detection successful\n"); return rc; } /******************* * USB PSY GETTERS * *******************/ Loading Loading @@ -3643,7 +3697,7 @@ int smblib_get_prop_scope(struct smb_charger *chg, return 0; } int smblib_get_prop_connector_health(struct smb_charger *chg) static int smblib_get_typec_connector_temp_status(struct smb_charger *chg) { int rc; u8 stat; Loading Loading @@ -3686,6 +3740,56 @@ int smblib_get_prop_connector_health(struct smb_charger *chg) return POWER_SUPPLY_HEALTH_COOL; } static int smblib_get_skin_temp_status(struct smb_charger *chg) { int rc; u8 stat; rc = smblib_read(chg, SKIN_TEMP_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read SKIN_TEMP_STATUS_REG, rc=%d\n", rc); return POWER_SUPPLY_HEALTH_UNKNOWN; } if (stat & SKIN_TEMP_RST_BIT) return POWER_SUPPLY_HEALTH_OVERHEAT; if (stat & SKIN_TEMP_UB_BIT) return POWER_SUPPLY_HEALTH_HOT; if (stat & SKIN_TEMP_LB_BIT) return POWER_SUPPLY_HEALTH_WARM; return POWER_SUPPLY_HEALTH_COOL; } int smblib_get_prop_connector_health(struct smb_charger *chg) { bool dc_present, usb_present; int input_present; int rc; rc = smblib_is_input_present(chg, &input_present); if (rc < 0) return POWER_SUPPLY_HEALTH_UNKNOWN; dc_present = input_present & INPUT_PRESENT_DC; usb_present = input_present & INPUT_PRESENT_USB; if (usb_present) return smblib_get_typec_connector_temp_status(chg); /* * In PM8150B, SKIN channel measures Wireless charger receiver * temp, used to regulate DC ICL. */ if (chg->smb_version == PM8150B_SUBTYPE && dc_present) return smblib_get_skin_temp_status(chg); return POWER_SUPPLY_HEALTH_COOL; } static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) { int rp_ua; Loading Loading @@ -3735,12 +3839,12 @@ static int smblib_handle_usb_current(struct smb_charger *chg, * Confiugure USB500 mode if Float charger is * configured for SDP mode. */ rc = set_sdp_current(chg, USBIN_500MA); rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, USBIN_500MA); if (rc < 0) smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc); return rc; } Loading Loading @@ -4854,6 +4958,11 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) if (chg->pd_active) return; if (chg->typec_mode == POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, 500000); return; } /* * HVDCP 2/3, handled separately */ Loading Loading @@ -5138,6 +5247,14 @@ static void typec_src_insertion(struct smb_charger *chg) smblib_hvdcp_detect_try_enable(chg, true); } static void typec_ra_ra_insertion(struct smb_charger *chg) { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, 500000); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); chg->ok_to_pd = false; smblib_hvdcp_detect_enable(chg, true); } static void typec_sink_removal(struct smb_charger *chg) { int rc; Loading Loading @@ -5437,7 +5554,11 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) return IRQ_HANDLED; } if (stat & SNK_SRC_MODE_BIT) { if (smblib_get_prop_dfp_mode(chg) == POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) { chg->sink_src_mode = AUDIO_ACCESS_MODE; typec_ra_ra_insertion(chg); } else if (stat & SNK_SRC_MODE_BIT) { if (smblib_src_lpd(chg)) return IRQ_HANDLED; chg->sink_src_mode = SRC_MODE; Loading @@ -5453,6 +5574,7 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data) typec_sink_removal(chg); break; case SINK_MODE: case AUDIO_ACCESS_MODE: typec_src_removal(chg); break; case UNATTACHED_MODE: Loading
drivers/power/supply/qcom/smb5-lib.h +3 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ enum print_reason { #define USBOV_DBC_VOTER "USBOV_DBC_VOTER" #define CHG_TERMINATION_VOTER "CHG_TERMINATION_VOTER" #define THERMAL_THROTTLE_VOTER "THERMAL_THROTTLE_VOTER" #define VOUT_VOTER "VOUT_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -94,6 +95,7 @@ enum smb_mode { enum sink_src_mode { SINK_MODE, SRC_MODE, AUDIO_ACCESS_MODE, UNATTACHED_MODE, }; Loading Loading @@ -632,6 +634,7 @@ int smblib_get_prop_voltage_wls_output(struct smb_charger *chg, union power_supply_propval *val); int smblib_set_prop_voltage_wls_output(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_dc_reset(struct smb_charger *chg); int smblib_get_prop_usb_present(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_usb_online(struct smb_charger *chg, Loading
drivers/power/supply/qcom/smb5-reg.h +13 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,7 @@ enum { #define HVDCP_EN_BIT BIT(2) #define USBIN_OPTIONS_2_CFG_REG (USBIN_BASE + 0x63) #define DCD_TIMEOUT_SEL_BIT BIT(5) #define FLOAT_OPTIONS_MASK GENMASK(2, 0) #define FLOAT_DIS_CHGING_CFG_BIT BIT(2) #define SUSPEND_FLOAT_CFG_BIT BIT(1) Loading Loading @@ -317,6 +318,12 @@ enum { #define DCIN_CMD_IL_REG (DCIN_BASE + 0x40) #define DCIN_SUSPEND_BIT BIT(0) #define DCIN_EN_OVERRIDE_BIT BIT(1) #define DCIN_EN_MASK GENMASK(2, 1) #define DCIN_CMD_PON_REG (DCIN_BASE + 0x45) #define DCIN_PON_BIT BIT(0) #define MID_CHG_BIT BIT(1) #define DCIN_LOAD_CFG_REG (DCIN_BASE + 0x65) #define INPUT_MISS_POLL_EN_BIT BIT(5) Loading Loading @@ -461,6 +468,12 @@ enum { #define DIE_TEMP_UB_BIT BIT(1) #define DIE_TEMP_LB_BIT BIT(0) #define SKIN_TEMP_STATUS_REG (MISC_BASE + 0x08) #define SKIN_TEMP_SHDN_BIT BIT(3) #define SKIN_TEMP_RST_BIT BIT(2) #define SKIN_TEMP_UB_BIT BIT(1) #define SKIN_TEMP_LB_BIT BIT(0) #define CONNECTOR_TEMP_STATUS_REG (MISC_BASE + 0x09) #define CONNECTOR_TEMP_SHDN_BIT BIT(3) #define CONNECTOR_TEMP_RST_BIT BIT(2) Loading