Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt +25 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,31 @@ Charger specific properties: Value type: bool Definition: Boolean flag which when present disables USB-PD operation. - qcom,hw-die-temp-mitigation Usage: optional Value type: bool Definition: Boolean flag which when present enables h/w based thermal mitigation. - qcom,hw-connector-mitigation Usage: optional Value type: bool Definition: Boolean flag which when present enables h/w based connector temperature mitigation. - qcom,hw-skin-temp-mitigation Usage: optional Value type: bool Definition: Boolean flag which when present enables h/w based skin temperature mitigation. - qcom,connector-internal-pull-kohm Usage: optional Value type: <u32> Definition: Specifies internal pull-up configuration to be applied to connector THERM. The only valid values are (0/30/100/400). If not specified 100K is used as default pull-up. ============================================= Second Level Nodes - SMB5 Charger Peripherals ============================================= Loading drivers/power/supply/qcom/qpnp-smb5.c +227 −19 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ static struct smb_params smb5_pmi632_params = { }, .icl_stat = { .name = "input current limit status", .reg = AICL_ICL_STATUS_REG, .reg = ICL_STATUS_REG, .min_u = 0, .max_u = 3000000, .step_u = 50000, Loading Loading @@ -88,6 +88,22 @@ static struct smb_params smb5_pmi632_params = { .step_u = 400, .set_proc = smblib_set_chg_freq, }, .aicl_5v_threshold = { .name = "AICL 5V threshold", .reg = USBIN_5V_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 4700, .step_u = 100, }, .aicl_cont_threshold = { .name = "AICL CONT threshold", .reg = USBIN_CONT_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 8800, .step_u = 100, .get_proc = smblib_get_aicl_cont_threshold, .set_proc = smblib_set_aicl_cont_threshold, }, }; static struct smb_params smb5_pm8150b_params = { Loading Loading @@ -164,6 +180,22 @@ static struct smb_params smb5_pm8150b_params = { .step_u = 400, .set_proc = smblib_set_chg_freq, }, .aicl_5v_threshold = { .name = "AICL 5V threshold", .reg = USBIN_5V_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 4700, .step_u = 100, }, .aicl_cont_threshold = { .name = "AICL CONT threshold", .reg = USBIN_CONT_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 11800, .step_u = 100, .get_proc = smblib_get_aicl_cont_threshold, .set_proc = smblib_set_aicl_cont_threshold, }, }; struct smb_dt_props { Loading Loading @@ -251,6 +283,13 @@ static struct attribute *smb5_attrs[] = { }; ATTRIBUTE_GROUPS(smb5); enum { BAT_THERM = 0, MISC_THERM, CONN_THERM, SMB_THERM, }; #define PMI632_MAX_ICL_UA 3000000 #define PM6150_MAX_FCC_UA 3000000 static int smb5_chg_config_init(struct smb5 *chip) Loading Loading @@ -295,6 +334,7 @@ static int smb5_chg_config_init(struct smb5 *chip) break; case PMI632_SUBTYPE: chip->chg.smb_version = PMI632_SUBTYPE; chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA; chg->param = smb5_pmi632_params; chg->use_extcon = true; chg->name = "pmi632_charger"; Loading Loading @@ -324,6 +364,45 @@ static int smb5_chg_config_init(struct smb5 *chip) return rc; } #define PULL_NO_PULL 0 #define PULL_30K 30 #define PULL_100K 100 #define PULL_400K 400 static int get_valid_pullup(int pull_up) { /* pull up can only be 0/30K/100K/400K) */ switch (pull_up) { case PULL_NO_PULL: return INTERNAL_PULL_NO_PULL; case PULL_30K: return INTERNAL_PULL_30K_PULL; case PULL_100K: return INTERNAL_PULL_100K_PULL; case PULL_400K: return INTERNAL_PULL_400K_PULL; default: return INTERNAL_PULL_100K_PULL; } } #define INTERNAL_PULL_UP_MASK 0x3 static int smb5_configure_internal_pull(struct smb_charger *chg, int type, int pull) { int rc; int shift = type * 2; u8 mask = INTERNAL_PULL_UP_MASK << shift; u8 val = pull << shift; rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG, mask, val); if (rc < 0) dev_err(chg->dev, "Couldn't configure ADC pull-up reg rc=%d\n", rc); return rc; } #define MICRO_1P5A 1500000 #define MICRO_P1A 100000 #define MICRO_1PA 1000000 Loading Loading @@ -434,6 +513,19 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) of_property_read_bool(node, "qcom,uusb-moisture-protection-enable"); chg->hw_die_temp_mitigation = of_property_read_bool(node, "qcom,hw-die-temp-mitigation"); chg->hw_connector_mitigation = of_property_read_bool(node, "qcom,hw-connector-mitigation"); chg->hw_skin_temp_mitigation = of_property_read_bool(node, "qcom,hw-skin-temp-mitigation"); chg->connector_pull_up = -EINVAL; of_property_read_u32(node, "qcom,connector-internal-pull-kohm", &chg->connector_pull_up); chip->dt.disable_suspend_on_collapse = of_property_read_bool(node, "qcom,disable-suspend-on-collapse"); Loading Loading @@ -623,6 +715,8 @@ static enum power_supply_property smb5_usb_props[] = { POWER_SUPPLY_PROP_SMB_EN_REASON, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_MOISTURE_DETECTED, POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED, POWER_SUPPLY_PROP_QC_OPTI_DISABLE, }; static int smb5_usb_get_prop(struct power_supply *psy, Loading @@ -632,6 +726,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, struct smb5 *chip = power_supply_get_drvdata(psy); struct smb_charger *chg = &chip->chg; int rc = 0; val->intval = 0; switch (psp) { case POWER_SUPPLY_PROP_PRESENT: Loading Loading @@ -733,6 +828,16 @@ static int smb5_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_MOISTURE_DETECTED: val->intval = chg->moisture_present; break; case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED: val->intval = !chg->flash_active; break; case POWER_SUPPLY_PROP_QC_OPTI_DISABLE: if (chg->hw_die_temp_mitigation) val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE; if (chg->hw_connector_mitigation) val->intval |= POWER_SUPPLY_QC_CTM_DISABLE; break; default: pr_err("get prop %d is not supported in usb\n", psp); rc = -EINVAL; Loading Loading @@ -1026,6 +1131,7 @@ static int smb5_usb_main_set_prop(struct power_supply *psy, { struct smb5 *chip = power_supply_get_drvdata(psy); struct smb_charger *chg = &chip->chg; union power_supply_propval pval = {0, }; int rc = 0; switch (psp) { Loading @@ -1039,7 +1145,35 @@ static int smb5_usb_main_set_prop(struct power_supply *psy, rc = smblib_set_icl_current(chg, val->intval); break; case POWER_SUPPLY_PROP_FLASH_ACTIVE: if ((chg->smb_version == PMI632_SUBTYPE) && (chg->flash_active != val->intval)) { chg->flash_active = val->intval; rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) pr_err("Failed to get USB preset status rc=%d\n", rc); if (pval.intval) { rc = smblib_force_vbus_voltage(chg, chg->flash_active ? FORCE_5V_BIT : IDLE_BIT); if (rc < 0) pr_err("Failed to force 5V\n"); else chg->pulse_cnt = 0; } else { /* USB absent & flash not-active - vote 100mA */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); } pr_debug("flash active VBUS 5V restriction %s\n", chg->flash_active ? "applied" : "removed"); /* Update userspace */ if (chg->batt_psy) power_supply_changed(chg->batt_psy); } break; case POWER_SUPPLY_PROP_TOGGLE_STAT: rc = smblib_toggle_smb_en(chg, val->intval); Loading Loading @@ -1462,9 +1596,10 @@ static int smb5_batt_set_prop(struct power_supply *psy, rc = smblib_set_prop_ship_mode(chg, val); break; case POWER_SUPPLY_PROP_RERUN_AICL: rc = smblib_rerun_aicl(chg); rc = smblib_run_aicl(chg, RERUN_AICL); break; case POWER_SUPPLY_PROP_DP_DM: if (!chg->flash_active) rc = smblib_dp_dm(chg, val->intval); break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: Loading Loading @@ -1802,30 +1937,37 @@ static int smb5_configure_micro_usb(struct smb_charger *chg) return rc; } #define RAW_ITERM(iterm_ma, max_range) \ div_s64((int64_t)iterm_ma * ADC_CHG_ITERM_MASK, max_range) static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) { u8 *buf; int rc = 0; s16 raw_hi_thresh, raw_lo_thresh; s16 raw_hi_thresh, raw_lo_thresh, max_limit_ma; struct smb_charger *chg = &chip->chg; if (chip->dt.term_current_thresh_hi_ma < -10000 || chip->dt.term_current_thresh_hi_ma > 10000 || chip->dt.term_current_thresh_lo_ma < -10000 || chip->dt.term_current_thresh_lo_ma > 10000) { if (chip->chg.smb_version == PMI632_SUBTYPE) max_limit_ma = ITERM_LIMITS_PMI632_MA; else max_limit_ma = ITERM_LIMITS_PM8150B_MA; if (chip->dt.term_current_thresh_hi_ma < (-1 * max_limit_ma) || chip->dt.term_current_thresh_hi_ma > max_limit_ma || chip->dt.term_current_thresh_lo_ma < (-1 * max_limit_ma) || chip->dt.term_current_thresh_lo_ma > max_limit_ma) { dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc); return -EINVAL; } /* * Conversion: * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000) * raw (A) = (term_current * ADC_CHG_ITERM_MASK) / max_limit_ma * Note: raw needs to be converted to big-endian format. */ if (chip->dt.term_current_thresh_hi_ma) { raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma * ADC_CHG_TERM_MASK) / 10000); raw_hi_thresh = RAW_ITERM(chip->dt.term_current_thresh_hi_ma, max_limit_ma); raw_hi_thresh = sign_extend32(raw_hi_thresh, 15); buf = (u8 *)&raw_hi_thresh; raw_hi_thresh = buf[1] | (buf[0] << 8); Loading @@ -1840,8 +1982,8 @@ static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) } if (chip->dt.term_current_thresh_lo_ma) { raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma * ADC_CHG_TERM_MASK) / 10000); raw_lo_thresh = RAW_ITERM(chip->dt.term_current_thresh_lo_ma, max_limit_ma); raw_lo_thresh = sign_extend32(raw_lo_thresh, 15); buf = (u8 *)&raw_lo_thresh; raw_lo_thresh = buf[1] | (buf[0] << 8); Loading Loading @@ -1873,6 +2015,54 @@ static int smb5_configure_iterm_thresholds(struct smb5 *chip) return rc; } static int smb5_configure_mitigation(struct smb_charger *chg) { int rc; u8 chan = 0, src_cfg = 0; if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation && !chg->hw_skin_temp_mitigation) { src_cfg = THERMREG_SW_ICL_ADJUST_BIT; } else { if (chg->hw_die_temp_mitigation) { chan = DIE_TEMP_CHANNEL_EN_BIT; src_cfg = THERMREG_DIE_ADC_SRC_EN_BIT | THERMREG_DIE_CMP_SRC_EN_BIT; } if (chg->hw_connector_mitigation) { chan |= CONN_THM_CHANNEL_EN_BIT; src_cfg |= THERMREG_CONNECTOR_ADC_SRC_EN_BIT; } if (chg->hw_skin_temp_mitigation) { chan |= MISC_THM_CHANNEL_EN_BIT; src_cfg |= THERMREG_SKIN_ADC_SRC_EN_BIT; } rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG, CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT | MISC_THM_CHANNEL_EN_BIT, chan); if (rc < 0) { dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc); return rc; } } rc = smblib_masked_write(chg, MISC_THERMREG_SRC_CFG_REG, THERMREG_SW_ICL_ADJUST_BIT | THERMREG_DIE_ADC_SRC_EN_BIT | THERMREG_DIE_CMP_SRC_EN_BIT | THERMREG_SKIN_ADC_SRC_EN_BIT | SKIN_ADC_CFG_BIT | THERMREG_CONNECTOR_ADC_SRC_EN_BIT, src_cfg); if (rc < 0) { dev_err(chg->dev, "Couldn't configure THERM_SRC reg rc=%d\n", rc); return rc; } return 0; } static int smb5_init_dc_peripheral(struct smb_charger *chg) { int rc = 0; Loading Loading @@ -1920,6 +2110,12 @@ static int smb5_init_hw(struct smb5 *chip) smblib_get_charge_param(chg, &chg->param.usb_icl, &chg->default_icl_ua); smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold, &chg->default_aicl_5v_threshold_mv); chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv; smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold, &chg->default_aicl_cont_threshold_mv); chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv; if (chg->charger_temp_max == -EINVAL) { rc = smblib_get_thermal_threshold(chg, Loading @@ -1946,11 +2142,10 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } } else { /* Allows software thermal regulation only */ rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG, THERMREG_SW_ICL_ADJUST_BIT); /* configure temperature mitigation */ rc = smb5_configure_mitigation(chg); if (rc < 0) { dev_err(chg->dev, "Couldn't configure SMB thermal regulation rc=%d\n", dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc); return rc; } Loading Loading @@ -2295,6 +2490,17 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } if (chg->connector_pull_up != -EINVAL) { rc = smb5_configure_internal_pull(chg, CONN_THERM, get_valid_pullup(chg->connector_pull_up)); if (rc < 0) { dev_err(chg->dev, "Couldn't configure CONN_THERM pull-up rc=%d\n", rc); return rc; } } return rc; } Loading Loading @@ -2466,10 +2672,12 @@ static struct smb_irq_info smb5_irqs[] = { [USBIN_UV_IRQ] = { .name = "usbin-uv", .handler = usbin_uv_irq_handler, .wake = true, .storm_data = {true, 3000, 5}, }, [USBIN_OV_IRQ] = { .name = "usbin-ov", .handler = default_irq_handler, .handler = usbin_ov_irq_handler, }, [USBIN_PLUGIN_IRQ] = { .name = "usbin-plugin", Loading drivers/power/supply/qcom/schgm-flash.c +31 −1 Original line number Diff line number Diff line Loading @@ -94,6 +94,11 @@ static void schgm_flash_parse_dt(struct smb_charger *chg) } } bool is_flash_active(struct smb_charger *chg) { return chg->flash_active ? true : false; } int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val) { int rc, vreg_state; Loading Loading @@ -140,6 +145,31 @@ int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val) return 0; } void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode) { int rc; u8 reg; /* * If torch is configured in default BOOST mode, skip any update in the * mode configuration. */ if (chg->headroom_mode == FIXED_MODE) return; if ((mode != TORCH_BOOST_MODE) && (mode != TORCH_BUCK_MODE)) return; reg = mode; rc = smblib_masked_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, TORCH_PRIORITY_CONTROL_BIT, reg); if (rc < 0) pr_err("Couldn't configure Torch priority control rc=%d\n", rc); pr_debug("Torch priority changed to: %d\n", mode); } int schgm_flash_init(struct smb_charger *chg) { int rc; Loading Loading @@ -183,7 +213,7 @@ int schgm_flash_init(struct smb_charger *chg) reg = (chg->headroom_mode == FIXED_MODE) ? TORCH_PRIORITY_CONTROL_BIT : 0; rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL, reg); rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, reg); if (rc < 0) { pr_err("Couldn't force 5V boost in torch mode rc=%d\n", rc); Loading drivers/power/supply/qcom/schgm-flash.h +8 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #define SCHGM_FLASH_CONTROL_REG (SCHGM_FLASH_BASE + 0x60) #define SOC_LOW_FOR_FLASH_EN_BIT BIT(7) #define SCHGM_TORCH_PRIORITY_CONTROL (SCHGM_FLASH_BASE + 0x63) #define SCHGM_TORCH_PRIORITY_CONTROL_REG (SCHGM_FLASH_BASE + 0x63) #define TORCH_PRIORITY_CONTROL_BIT BIT(0) #define SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG (SCHGM_FLASH_BASE + 0x67) Loading @@ -38,8 +38,15 @@ #define SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG \ (SCHGM_FLASH_BASE + 0x68) enum torch_mode { TORCH_BUCK_MODE = 0, TORCH_BOOST_MODE, }; int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val); void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode); int schgm_flash_init(struct smb_charger *chg); bool is_flash_active(struct smb_charger *chg); irqreturn_t schgm_flash_default_irq_handler(int irq, void *data); irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data); Loading drivers/power/supply/qcom/smb5-lib.c +297 −28 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt +25 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,31 @@ Charger specific properties: Value type: bool Definition: Boolean flag which when present disables USB-PD operation. - qcom,hw-die-temp-mitigation Usage: optional Value type: bool Definition: Boolean flag which when present enables h/w based thermal mitigation. - qcom,hw-connector-mitigation Usage: optional Value type: bool Definition: Boolean flag which when present enables h/w based connector temperature mitigation. - qcom,hw-skin-temp-mitigation Usage: optional Value type: bool Definition: Boolean flag which when present enables h/w based skin temperature mitigation. - qcom,connector-internal-pull-kohm Usage: optional Value type: <u32> Definition: Specifies internal pull-up configuration to be applied to connector THERM. The only valid values are (0/30/100/400). If not specified 100K is used as default pull-up. ============================================= Second Level Nodes - SMB5 Charger Peripherals ============================================= Loading
drivers/power/supply/qcom/qpnp-smb5.c +227 −19 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ static struct smb_params smb5_pmi632_params = { }, .icl_stat = { .name = "input current limit status", .reg = AICL_ICL_STATUS_REG, .reg = ICL_STATUS_REG, .min_u = 0, .max_u = 3000000, .step_u = 50000, Loading Loading @@ -88,6 +88,22 @@ static struct smb_params smb5_pmi632_params = { .step_u = 400, .set_proc = smblib_set_chg_freq, }, .aicl_5v_threshold = { .name = "AICL 5V threshold", .reg = USBIN_5V_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 4700, .step_u = 100, }, .aicl_cont_threshold = { .name = "AICL CONT threshold", .reg = USBIN_CONT_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 8800, .step_u = 100, .get_proc = smblib_get_aicl_cont_threshold, .set_proc = smblib_set_aicl_cont_threshold, }, }; static struct smb_params smb5_pm8150b_params = { Loading Loading @@ -164,6 +180,22 @@ static struct smb_params smb5_pm8150b_params = { .step_u = 400, .set_proc = smblib_set_chg_freq, }, .aicl_5v_threshold = { .name = "AICL 5V threshold", .reg = USBIN_5V_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 4700, .step_u = 100, }, .aicl_cont_threshold = { .name = "AICL CONT threshold", .reg = USBIN_CONT_AICL_THRESHOLD_REG, .min_u = 4000, .max_u = 11800, .step_u = 100, .get_proc = smblib_get_aicl_cont_threshold, .set_proc = smblib_set_aicl_cont_threshold, }, }; struct smb_dt_props { Loading Loading @@ -251,6 +283,13 @@ static struct attribute *smb5_attrs[] = { }; ATTRIBUTE_GROUPS(smb5); enum { BAT_THERM = 0, MISC_THERM, CONN_THERM, SMB_THERM, }; #define PMI632_MAX_ICL_UA 3000000 #define PM6150_MAX_FCC_UA 3000000 static int smb5_chg_config_init(struct smb5 *chip) Loading Loading @@ -295,6 +334,7 @@ static int smb5_chg_config_init(struct smb5 *chip) break; case PMI632_SUBTYPE: chip->chg.smb_version = PMI632_SUBTYPE; chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA; chg->param = smb5_pmi632_params; chg->use_extcon = true; chg->name = "pmi632_charger"; Loading Loading @@ -324,6 +364,45 @@ static int smb5_chg_config_init(struct smb5 *chip) return rc; } #define PULL_NO_PULL 0 #define PULL_30K 30 #define PULL_100K 100 #define PULL_400K 400 static int get_valid_pullup(int pull_up) { /* pull up can only be 0/30K/100K/400K) */ switch (pull_up) { case PULL_NO_PULL: return INTERNAL_PULL_NO_PULL; case PULL_30K: return INTERNAL_PULL_30K_PULL; case PULL_100K: return INTERNAL_PULL_100K_PULL; case PULL_400K: return INTERNAL_PULL_400K_PULL; default: return INTERNAL_PULL_100K_PULL; } } #define INTERNAL_PULL_UP_MASK 0x3 static int smb5_configure_internal_pull(struct smb_charger *chg, int type, int pull) { int rc; int shift = type * 2; u8 mask = INTERNAL_PULL_UP_MASK << shift; u8 val = pull << shift; rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG, mask, val); if (rc < 0) dev_err(chg->dev, "Couldn't configure ADC pull-up reg rc=%d\n", rc); return rc; } #define MICRO_1P5A 1500000 #define MICRO_P1A 100000 #define MICRO_1PA 1000000 Loading Loading @@ -434,6 +513,19 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) of_property_read_bool(node, "qcom,uusb-moisture-protection-enable"); chg->hw_die_temp_mitigation = of_property_read_bool(node, "qcom,hw-die-temp-mitigation"); chg->hw_connector_mitigation = of_property_read_bool(node, "qcom,hw-connector-mitigation"); chg->hw_skin_temp_mitigation = of_property_read_bool(node, "qcom,hw-skin-temp-mitigation"); chg->connector_pull_up = -EINVAL; of_property_read_u32(node, "qcom,connector-internal-pull-kohm", &chg->connector_pull_up); chip->dt.disable_suspend_on_collapse = of_property_read_bool(node, "qcom,disable-suspend-on-collapse"); Loading Loading @@ -623,6 +715,8 @@ static enum power_supply_property smb5_usb_props[] = { POWER_SUPPLY_PROP_SMB_EN_REASON, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_MOISTURE_DETECTED, POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED, POWER_SUPPLY_PROP_QC_OPTI_DISABLE, }; static int smb5_usb_get_prop(struct power_supply *psy, Loading @@ -632,6 +726,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, struct smb5 *chip = power_supply_get_drvdata(psy); struct smb_charger *chg = &chip->chg; int rc = 0; val->intval = 0; switch (psp) { case POWER_SUPPLY_PROP_PRESENT: Loading Loading @@ -733,6 +828,16 @@ static int smb5_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_MOISTURE_DETECTED: val->intval = chg->moisture_present; break; case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED: val->intval = !chg->flash_active; break; case POWER_SUPPLY_PROP_QC_OPTI_DISABLE: if (chg->hw_die_temp_mitigation) val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE; if (chg->hw_connector_mitigation) val->intval |= POWER_SUPPLY_QC_CTM_DISABLE; break; default: pr_err("get prop %d is not supported in usb\n", psp); rc = -EINVAL; Loading Loading @@ -1026,6 +1131,7 @@ static int smb5_usb_main_set_prop(struct power_supply *psy, { struct smb5 *chip = power_supply_get_drvdata(psy); struct smb_charger *chg = &chip->chg; union power_supply_propval pval = {0, }; int rc = 0; switch (psp) { Loading @@ -1039,7 +1145,35 @@ static int smb5_usb_main_set_prop(struct power_supply *psy, rc = smblib_set_icl_current(chg, val->intval); break; case POWER_SUPPLY_PROP_FLASH_ACTIVE: if ((chg->smb_version == PMI632_SUBTYPE) && (chg->flash_active != val->intval)) { chg->flash_active = val->intval; rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) pr_err("Failed to get USB preset status rc=%d\n", rc); if (pval.intval) { rc = smblib_force_vbus_voltage(chg, chg->flash_active ? FORCE_5V_BIT : IDLE_BIT); if (rc < 0) pr_err("Failed to force 5V\n"); else chg->pulse_cnt = 0; } else { /* USB absent & flash not-active - vote 100mA */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); } pr_debug("flash active VBUS 5V restriction %s\n", chg->flash_active ? "applied" : "removed"); /* Update userspace */ if (chg->batt_psy) power_supply_changed(chg->batt_psy); } break; case POWER_SUPPLY_PROP_TOGGLE_STAT: rc = smblib_toggle_smb_en(chg, val->intval); Loading Loading @@ -1462,9 +1596,10 @@ static int smb5_batt_set_prop(struct power_supply *psy, rc = smblib_set_prop_ship_mode(chg, val); break; case POWER_SUPPLY_PROP_RERUN_AICL: rc = smblib_rerun_aicl(chg); rc = smblib_run_aicl(chg, RERUN_AICL); break; case POWER_SUPPLY_PROP_DP_DM: if (!chg->flash_active) rc = smblib_dp_dm(chg, val->intval); break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: Loading Loading @@ -1802,30 +1937,37 @@ static int smb5_configure_micro_usb(struct smb_charger *chg) return rc; } #define RAW_ITERM(iterm_ma, max_range) \ div_s64((int64_t)iterm_ma * ADC_CHG_ITERM_MASK, max_range) static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) { u8 *buf; int rc = 0; s16 raw_hi_thresh, raw_lo_thresh; s16 raw_hi_thresh, raw_lo_thresh, max_limit_ma; struct smb_charger *chg = &chip->chg; if (chip->dt.term_current_thresh_hi_ma < -10000 || chip->dt.term_current_thresh_hi_ma > 10000 || chip->dt.term_current_thresh_lo_ma < -10000 || chip->dt.term_current_thresh_lo_ma > 10000) { if (chip->chg.smb_version == PMI632_SUBTYPE) max_limit_ma = ITERM_LIMITS_PMI632_MA; else max_limit_ma = ITERM_LIMITS_PM8150B_MA; if (chip->dt.term_current_thresh_hi_ma < (-1 * max_limit_ma) || chip->dt.term_current_thresh_hi_ma > max_limit_ma || chip->dt.term_current_thresh_lo_ma < (-1 * max_limit_ma) || chip->dt.term_current_thresh_lo_ma > max_limit_ma) { dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc); return -EINVAL; } /* * Conversion: * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000) * raw (A) = (term_current * ADC_CHG_ITERM_MASK) / max_limit_ma * Note: raw needs to be converted to big-endian format. */ if (chip->dt.term_current_thresh_hi_ma) { raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma * ADC_CHG_TERM_MASK) / 10000); raw_hi_thresh = RAW_ITERM(chip->dt.term_current_thresh_hi_ma, max_limit_ma); raw_hi_thresh = sign_extend32(raw_hi_thresh, 15); buf = (u8 *)&raw_hi_thresh; raw_hi_thresh = buf[1] | (buf[0] << 8); Loading @@ -1840,8 +1982,8 @@ static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) } if (chip->dt.term_current_thresh_lo_ma) { raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma * ADC_CHG_TERM_MASK) / 10000); raw_lo_thresh = RAW_ITERM(chip->dt.term_current_thresh_lo_ma, max_limit_ma); raw_lo_thresh = sign_extend32(raw_lo_thresh, 15); buf = (u8 *)&raw_lo_thresh; raw_lo_thresh = buf[1] | (buf[0] << 8); Loading Loading @@ -1873,6 +2015,54 @@ static int smb5_configure_iterm_thresholds(struct smb5 *chip) return rc; } static int smb5_configure_mitigation(struct smb_charger *chg) { int rc; u8 chan = 0, src_cfg = 0; if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation && !chg->hw_skin_temp_mitigation) { src_cfg = THERMREG_SW_ICL_ADJUST_BIT; } else { if (chg->hw_die_temp_mitigation) { chan = DIE_TEMP_CHANNEL_EN_BIT; src_cfg = THERMREG_DIE_ADC_SRC_EN_BIT | THERMREG_DIE_CMP_SRC_EN_BIT; } if (chg->hw_connector_mitigation) { chan |= CONN_THM_CHANNEL_EN_BIT; src_cfg |= THERMREG_CONNECTOR_ADC_SRC_EN_BIT; } if (chg->hw_skin_temp_mitigation) { chan |= MISC_THM_CHANNEL_EN_BIT; src_cfg |= THERMREG_SKIN_ADC_SRC_EN_BIT; } rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG, CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT | MISC_THM_CHANNEL_EN_BIT, chan); if (rc < 0) { dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc); return rc; } } rc = smblib_masked_write(chg, MISC_THERMREG_SRC_CFG_REG, THERMREG_SW_ICL_ADJUST_BIT | THERMREG_DIE_ADC_SRC_EN_BIT | THERMREG_DIE_CMP_SRC_EN_BIT | THERMREG_SKIN_ADC_SRC_EN_BIT | SKIN_ADC_CFG_BIT | THERMREG_CONNECTOR_ADC_SRC_EN_BIT, src_cfg); if (rc < 0) { dev_err(chg->dev, "Couldn't configure THERM_SRC reg rc=%d\n", rc); return rc; } return 0; } static int smb5_init_dc_peripheral(struct smb_charger *chg) { int rc = 0; Loading Loading @@ -1920,6 +2110,12 @@ static int smb5_init_hw(struct smb5 *chip) smblib_get_charge_param(chg, &chg->param.usb_icl, &chg->default_icl_ua); smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold, &chg->default_aicl_5v_threshold_mv); chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv; smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold, &chg->default_aicl_cont_threshold_mv); chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv; if (chg->charger_temp_max == -EINVAL) { rc = smblib_get_thermal_threshold(chg, Loading @@ -1946,11 +2142,10 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } } else { /* Allows software thermal regulation only */ rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG, THERMREG_SW_ICL_ADJUST_BIT); /* configure temperature mitigation */ rc = smb5_configure_mitigation(chg); if (rc < 0) { dev_err(chg->dev, "Couldn't configure SMB thermal regulation rc=%d\n", dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc); return rc; } Loading Loading @@ -2295,6 +2490,17 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } if (chg->connector_pull_up != -EINVAL) { rc = smb5_configure_internal_pull(chg, CONN_THERM, get_valid_pullup(chg->connector_pull_up)); if (rc < 0) { dev_err(chg->dev, "Couldn't configure CONN_THERM pull-up rc=%d\n", rc); return rc; } } return rc; } Loading Loading @@ -2466,10 +2672,12 @@ static struct smb_irq_info smb5_irqs[] = { [USBIN_UV_IRQ] = { .name = "usbin-uv", .handler = usbin_uv_irq_handler, .wake = true, .storm_data = {true, 3000, 5}, }, [USBIN_OV_IRQ] = { .name = "usbin-ov", .handler = default_irq_handler, .handler = usbin_ov_irq_handler, }, [USBIN_PLUGIN_IRQ] = { .name = "usbin-plugin", Loading
drivers/power/supply/qcom/schgm-flash.c +31 −1 Original line number Diff line number Diff line Loading @@ -94,6 +94,11 @@ static void schgm_flash_parse_dt(struct smb_charger *chg) } } bool is_flash_active(struct smb_charger *chg) { return chg->flash_active ? true : false; } int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val) { int rc, vreg_state; Loading Loading @@ -140,6 +145,31 @@ int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val) return 0; } void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode) { int rc; u8 reg; /* * If torch is configured in default BOOST mode, skip any update in the * mode configuration. */ if (chg->headroom_mode == FIXED_MODE) return; if ((mode != TORCH_BOOST_MODE) && (mode != TORCH_BUCK_MODE)) return; reg = mode; rc = smblib_masked_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, TORCH_PRIORITY_CONTROL_BIT, reg); if (rc < 0) pr_err("Couldn't configure Torch priority control rc=%d\n", rc); pr_debug("Torch priority changed to: %d\n", mode); } int schgm_flash_init(struct smb_charger *chg) { int rc; Loading Loading @@ -183,7 +213,7 @@ int schgm_flash_init(struct smb_charger *chg) reg = (chg->headroom_mode == FIXED_MODE) ? TORCH_PRIORITY_CONTROL_BIT : 0; rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL, reg); rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, reg); if (rc < 0) { pr_err("Couldn't force 5V boost in torch mode rc=%d\n", rc); Loading
drivers/power/supply/qcom/schgm-flash.h +8 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #define SCHGM_FLASH_CONTROL_REG (SCHGM_FLASH_BASE + 0x60) #define SOC_LOW_FOR_FLASH_EN_BIT BIT(7) #define SCHGM_TORCH_PRIORITY_CONTROL (SCHGM_FLASH_BASE + 0x63) #define SCHGM_TORCH_PRIORITY_CONTROL_REG (SCHGM_FLASH_BASE + 0x63) #define TORCH_PRIORITY_CONTROL_BIT BIT(0) #define SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG (SCHGM_FLASH_BASE + 0x67) Loading @@ -38,8 +38,15 @@ #define SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG \ (SCHGM_FLASH_BASE + 0x68) enum torch_mode { TORCH_BUCK_MODE = 0, TORCH_BOOST_MODE, }; int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val); void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode); int schgm_flash_init(struct smb_charger *chg); bool is_flash_active(struct smb_charger *chg); irqreturn_t schgm_flash_default_irq_handler(int irq, void *data); irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data); Loading
drivers/power/supply/qcom/smb5-lib.c +297 −28 File changed.Preview size limit exceeded, changes collapsed. Show changes