Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt +21 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,27 @@ Charger specific properties: then charge inhibit will be disabled by default. Allowed values are: 50, 100, 200, 300. - qcom,chg-term-src Usage: optional Value type: <u32> Definition: Specify either the ADC or analog comparators to be used in order to set threshold values for charge termination current. 0 - Unspecified 1 - Select ADC comparator 2 - Select ANALOG comparator - qcom,chg-term-current-ma Usage: optional Value type: <u32> Definition: When ADC comparator is selected as qcom,chg-term-src, this parameter should be set to the desired upper threshold. - qcom,chg-term-base-current-ma Usage: optional Value type: <u32> Definition: When ADC comparator is selected as qcom,chg-term-src, this parameter should be set to the desired lower threshold. - qcom,auto-recharge-soc Usage: optional Value type: <u32> Loading drivers/power/supply/qcom/qpnp-smb5.c +94 −2 Original line number Diff line number Diff line Loading @@ -179,6 +179,9 @@ struct smb_dt_props { int wd_bark_time; int batt_profile_fcc_ua; int batt_profile_fv_uv; int term_current_src; int term_current_thresh_hi_ma; int term_current_thresh_lo_ma; }; struct smb5 { Loading Loading @@ -328,6 +331,18 @@ static int smb5_parse_dt(struct smb5 *chip) if (rc < 0) chg->otg_cl_ua = MICRO_1P5A; rc = of_property_read_u32(node, "qcom,chg-term-src", &chip->dt.term_current_src); if (rc < 0) chip->dt.term_current_src = ITERM_SRC_UNSPECIFIED; rc = of_property_read_u32(node, "qcom,chg-term-current-ma", &chip->dt.term_current_thresh_hi_ma); if (chip->dt.term_current_src == ITERM_SRC_ADC) rc = of_property_read_u32(node, "qcom,chg-term-base-current-ma", &chip->dt.term_current_thresh_lo_ma); if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) { chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len, GFP_KERNEL); Loading Loading @@ -1039,6 +1054,7 @@ static enum power_supply_property smb5_batt_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, Loading Loading @@ -1122,6 +1138,9 @@ static int smb5_batt_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->fcc_votable, BATT_PROFILE_VOTER); break; case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: rc = smblib_get_prop_batt_iterm(chg, val); break; case POWER_SUPPLY_PROP_TEMP: rc = smblib_get_prop_batt_temp(chg, val); break; Loading Loading @@ -1456,6 +1475,71 @@ static int smb5_configure_micro_usb(struct smb_charger *chg) return rc; } static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) { int rc = 0; int raw_hi_thresh, raw_lo_thresh; 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) { 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) */ 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 = sign_extend32(raw_hi_thresh, 15); rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, (u8 *)&raw_hi_thresh, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n", rc); return rc; } } 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 = sign_extend32(raw_lo_thresh, 15); rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG, (u8 *)&raw_lo_thresh, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n", rc); return rc; } } return rc; } static int smb5_configure_iterm_thresholds(struct smb5 *chip) { int rc = 0; switch (chip->dt.term_current_src) { case ITERM_SRC_ADC: rc = smb5_configure_iterm_thresholds_adc(chip); break; default: break; } return rc; } static int smb5_init_hw(struct smb5 *chip) { struct smb_charger *chg = &chip->chg; Loading Loading @@ -1622,6 +1706,14 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } /* set termination current threshold values */ rc = smb5_configure_iterm_thresholds(chip); if (rc < 0) { pr_err("Couldn't configure ITERM thresholds rc=%d\n", rc); return rc; } /* configure float charger options */ switch (chip->dt.float_option) { case FLOAT_DCP: Loading drivers/power/supply/qcom/smb5-lib.c +39 −0 Original line number Diff line number Diff line Loading @@ -1471,6 +1471,45 @@ int smblib_get_prop_batt_current_now(struct smb_charger *chg, return rc; } int smblib_get_prop_batt_iterm(struct smb_charger *chg, union power_supply_propval *val) { int rc, temp; u8 stat; /* * Currently, only ADC comparator-based termination is supported, * hence read only the threshold corresponding to ADC source. * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0. */ rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n", rc); return rc; } if (stat & CHGR_ITERM_USE_ANALOG_BIT) { val->intval = -EINVAL; return 0; } rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, (u8 *)&temp, 2); if (rc < 0) { smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n", rc); return rc; } temp = sign_extend32(temp, 15); temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK); val->intval = temp; return rc; } int smblib_get_prop_batt_temp(struct smb_charger *chg, union power_supply_propval *val) { Loading drivers/power/supply/qcom/smb5-lib.h +10 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ enum print_reason { #define VBAT_TO_VRAW_ADC(v) div_u64((u64)v * 1000000UL, 194637UL) #define ADC_CHG_TERM_MASK 32767 enum smb_mode { PARALLEL_MASTER = 0, PARALLEL_SLAVE, Loading Loading @@ -171,6 +173,12 @@ enum float_options { SUSPEND_INPUT = 4, }; enum chg_term_config_src { ITERM_SRC_UNSPECIFIED, ITERM_SRC_ADC, ITERM_SRC_ANALOG }; struct smb_irq_info { const char *name; const irq_handler_t handler; Loading Loading @@ -459,6 +467,8 @@ int smblib_get_prop_batt_voltage_now(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_current_now(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_iterm(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_temp(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_charge_counter(struct smb_charger *chg, Loading drivers/power/supply/qcom/smb5-reg.h +9 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,11 @@ enum { #define CHGR_FAST_CHARGE_CURRENT_CFG_REG (CHGR_BASE + 0x61) #define CHGR_ADC_ITERM_UP_THD_MSB_REG (CHGR_BASE + 0x67) #define CHGR_ADC_ITERM_UP_THD_LSB_REG (CHGR_BASE + 0x68) #define CHGR_ADC_ITERM_LO_THD_MSB_REG (CHGR_BASE + 0x69) #define CHGR_ADC_ITERM_LO_THD_LSB_REG (CHGR_BASE + 0x6A) #define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG (CHGR_BASE + 0x6B) #define NO_OF_SAMPLE_FOR_RCHG_SHIFT 2 #define NO_OF_SAMPLE_FOR_RCHG GENMASK(3, 2) Loading Loading @@ -102,6 +107,10 @@ enum { #define JEITA_CCCOMP_CFG_COLD_REG (CHGR_BASE + 0x93) #define CHGR_JEITA_THRESHOLD_BASE_REG(i) (CHGR_BASE + 0x94 + (i * 4)) #define CHGR_ENG_CHARGING_CFG_REG (CHGR_BASE + 0xC0) #define CHGR_ITERM_USE_ANALOG_BIT BIT(3) /******************************** * DCDC Peripheral Registers * ********************************/ Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt +21 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,27 @@ Charger specific properties: then charge inhibit will be disabled by default. Allowed values are: 50, 100, 200, 300. - qcom,chg-term-src Usage: optional Value type: <u32> Definition: Specify either the ADC or analog comparators to be used in order to set threshold values for charge termination current. 0 - Unspecified 1 - Select ADC comparator 2 - Select ANALOG comparator - qcom,chg-term-current-ma Usage: optional Value type: <u32> Definition: When ADC comparator is selected as qcom,chg-term-src, this parameter should be set to the desired upper threshold. - qcom,chg-term-base-current-ma Usage: optional Value type: <u32> Definition: When ADC comparator is selected as qcom,chg-term-src, this parameter should be set to the desired lower threshold. - qcom,auto-recharge-soc Usage: optional Value type: <u32> Loading
drivers/power/supply/qcom/qpnp-smb5.c +94 −2 Original line number Diff line number Diff line Loading @@ -179,6 +179,9 @@ struct smb_dt_props { int wd_bark_time; int batt_profile_fcc_ua; int batt_profile_fv_uv; int term_current_src; int term_current_thresh_hi_ma; int term_current_thresh_lo_ma; }; struct smb5 { Loading Loading @@ -328,6 +331,18 @@ static int smb5_parse_dt(struct smb5 *chip) if (rc < 0) chg->otg_cl_ua = MICRO_1P5A; rc = of_property_read_u32(node, "qcom,chg-term-src", &chip->dt.term_current_src); if (rc < 0) chip->dt.term_current_src = ITERM_SRC_UNSPECIFIED; rc = of_property_read_u32(node, "qcom,chg-term-current-ma", &chip->dt.term_current_thresh_hi_ma); if (chip->dt.term_current_src == ITERM_SRC_ADC) rc = of_property_read_u32(node, "qcom,chg-term-base-current-ma", &chip->dt.term_current_thresh_lo_ma); if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) { chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len, GFP_KERNEL); Loading Loading @@ -1039,6 +1054,7 @@ static enum power_supply_property smb5_batt_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, Loading Loading @@ -1122,6 +1138,9 @@ static int smb5_batt_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->fcc_votable, BATT_PROFILE_VOTER); break; case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: rc = smblib_get_prop_batt_iterm(chg, val); break; case POWER_SUPPLY_PROP_TEMP: rc = smblib_get_prop_batt_temp(chg, val); break; Loading Loading @@ -1456,6 +1475,71 @@ static int smb5_configure_micro_usb(struct smb_charger *chg) return rc; } static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) { int rc = 0; int raw_hi_thresh, raw_lo_thresh; 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) { 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) */ 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 = sign_extend32(raw_hi_thresh, 15); rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, (u8 *)&raw_hi_thresh, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n", rc); return rc; } } 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 = sign_extend32(raw_lo_thresh, 15); rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG, (u8 *)&raw_lo_thresh, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n", rc); return rc; } } return rc; } static int smb5_configure_iterm_thresholds(struct smb5 *chip) { int rc = 0; switch (chip->dt.term_current_src) { case ITERM_SRC_ADC: rc = smb5_configure_iterm_thresholds_adc(chip); break; default: break; } return rc; } static int smb5_init_hw(struct smb5 *chip) { struct smb_charger *chg = &chip->chg; Loading Loading @@ -1622,6 +1706,14 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } /* set termination current threshold values */ rc = smb5_configure_iterm_thresholds(chip); if (rc < 0) { pr_err("Couldn't configure ITERM thresholds rc=%d\n", rc); return rc; } /* configure float charger options */ switch (chip->dt.float_option) { case FLOAT_DCP: Loading
drivers/power/supply/qcom/smb5-lib.c +39 −0 Original line number Diff line number Diff line Loading @@ -1471,6 +1471,45 @@ int smblib_get_prop_batt_current_now(struct smb_charger *chg, return rc; } int smblib_get_prop_batt_iterm(struct smb_charger *chg, union power_supply_propval *val) { int rc, temp; u8 stat; /* * Currently, only ADC comparator-based termination is supported, * hence read only the threshold corresponding to ADC source. * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0. */ rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n", rc); return rc; } if (stat & CHGR_ITERM_USE_ANALOG_BIT) { val->intval = -EINVAL; return 0; } rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, (u8 *)&temp, 2); if (rc < 0) { smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n", rc); return rc; } temp = sign_extend32(temp, 15); temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK); val->intval = temp; return rc; } int smblib_get_prop_batt_temp(struct smb_charger *chg, union power_supply_propval *val) { Loading
drivers/power/supply/qcom/smb5-lib.h +10 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ enum print_reason { #define VBAT_TO_VRAW_ADC(v) div_u64((u64)v * 1000000UL, 194637UL) #define ADC_CHG_TERM_MASK 32767 enum smb_mode { PARALLEL_MASTER = 0, PARALLEL_SLAVE, Loading Loading @@ -171,6 +173,12 @@ enum float_options { SUSPEND_INPUT = 4, }; enum chg_term_config_src { ITERM_SRC_UNSPECIFIED, ITERM_SRC_ADC, ITERM_SRC_ANALOG }; struct smb_irq_info { const char *name; const irq_handler_t handler; Loading Loading @@ -459,6 +467,8 @@ int smblib_get_prop_batt_voltage_now(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_current_now(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_iterm(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_temp(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_batt_charge_counter(struct smb_charger *chg, Loading
drivers/power/supply/qcom/smb5-reg.h +9 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,11 @@ enum { #define CHGR_FAST_CHARGE_CURRENT_CFG_REG (CHGR_BASE + 0x61) #define CHGR_ADC_ITERM_UP_THD_MSB_REG (CHGR_BASE + 0x67) #define CHGR_ADC_ITERM_UP_THD_LSB_REG (CHGR_BASE + 0x68) #define CHGR_ADC_ITERM_LO_THD_MSB_REG (CHGR_BASE + 0x69) #define CHGR_ADC_ITERM_LO_THD_LSB_REG (CHGR_BASE + 0x6A) #define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG (CHGR_BASE + 0x6B) #define NO_OF_SAMPLE_FOR_RCHG_SHIFT 2 #define NO_OF_SAMPLE_FOR_RCHG GENMASK(3, 2) Loading Loading @@ -102,6 +107,10 @@ enum { #define JEITA_CCCOMP_CFG_COLD_REG (CHGR_BASE + 0x93) #define CHGR_JEITA_THRESHOLD_BASE_REG(i) (CHGR_BASE + 0x94 + (i * 4)) #define CHGR_ENG_CHARGING_CFG_REG (CHGR_BASE + 0xC0) #define CHGR_ITERM_USE_ANALOG_BIT BIT(3) /******************************** * DCDC Peripheral Registers * ********************************/ Loading