Loading Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt +12 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,18 @@ Charger specific properties: stacked one after the other and thus all the charge current (FCC) flows through main. In a non-stacked configuration each charger controls the charge current (FCC) separately. - qcom,die-temp-threshold-degc Usage: optional Value type: <u32> Definition: Specifies DIE temp threshold beyond which h/w starts mitigation. If not sepcified, 90 degrees centigrade is used. - qcom,hw-die-temp-mitigation Usage: optional Value type: bool Definition: Boolean property to enable h/w controlled die temp mitigation. ================================================ Second Level Nodes - SMB1355 Charger Peripherals ================================================ Loading drivers/power/supply/qcom/smb1355-charger.c +91 −29 Original line number Diff line number Diff line Loading @@ -80,8 +80,12 @@ #define BATIF_CFG_SMISC_BATID_REG (BATIF_BASE + 0x73) #define CFG_SMISC_RBIAS_EXT_CTRL_BIT BIT(2) #define SMB2CHGS_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0) #define SMB2CHG_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0) #define TDIE_COMPARATOR_THRESHOLD GENMASK(5, 0) #define DIE_LOW_RANGE_BASE_DEGC 34 #define DIE_LOW_RANGE_DELTA 16 #define DIE_LOW_RANGE_MAX_DEGC 97 #define DIE_LOW_RANGE_SHIFT 4 #define BATIF_ENG_SCMISC_SPARE1_REG (BATIF_BASE + 0xC2) #define EXT_BIAS_PIN_BIT BIT(2) Loading @@ -91,13 +95,10 @@ #define VALLEY_COMPARATOR_EN_BIT BIT(0) #define TEMP_COMP_STATUS_REG (MISC_BASE + 0x07) #define SKIN_TEMP_RST_HOT_BIT BIT(6) #define SKIN_TEMP_UB_HOT_BIT BIT(5) #define SKIN_TEMP_LB_HOT_BIT BIT(4) #define DIE_TEMP_TSD_HOT_BIT BIT(3) #define DIE_TEMP_RST_HOT_BIT BIT(2) #define DIE_TEMP_UB_HOT_BIT BIT(1) #define DIE_TEMP_LB_HOT_BIT BIT(0) #define TEMP_RST_HOT_BIT BIT(2) #define TEMP_UB_HOT_BIT BIT(1) #define TEMP_LB_HOT_BIT BIT(0) #define SKIN_TEMP_SHIFT 4 #define MISC_RT_STS_REG (MISC_BASE + 0x10) #define HARD_ILIMIT_RT_STS_BIT BIT(5) Loading Loading @@ -223,6 +224,8 @@ struct smb_dt_props { bool disable_ctm; int pl_mode; int pl_batfet_mode; bool hw_die_temp_mitigation; u32 die_temp_threshold; }; struct smb1355 { Loading Loading @@ -250,6 +253,11 @@ struct smb1355 { struct votable *irq_disable_votable; }; enum { CONNECTOR_TEMP = 0, DIE_TEMP, }; static bool is_secure(struct smb1355 *chip, int addr) { if (addr == CLOCK_REQUEST_REG) Loading Loading @@ -379,8 +387,7 @@ static void die_temp_work(struct work_struct *work) u8 temp_stat; for (i = 0; i < BIT(5); i++) { rc = smb1355_masked_write(chip, SMB2CHGS_BATIF_ENG_SMISC_DIETEMP, rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP, TDIE_COMPARATOR_THRESHOLD, i); if (rc < 0) { pr_err("Couldn't set temp comp threshold rc=%d\n", rc); Loading @@ -399,7 +406,7 @@ static void die_temp_work(struct work_struct *work) continue; } if (!(temp_stat & DIE_TEMP_UB_HOT_BIT)) { if (!(temp_stat & TEMP_UB_HOT_BIT)) { /* found the temp */ break; } Loading Loading @@ -465,6 +472,7 @@ static int smb1355_determine_initial_status(struct smb1355 *chip) return 0; } #define DEFAULT_DIE_TEMP_LOW_THRESHOLD 90 static int smb1355_parse_dt(struct smb1355 *chip) { struct device_node *node = chip->dev->of_node; Loading Loading @@ -495,6 +503,15 @@ static int smb1355_parse_dt(struct smb1355 *chip) if (of_property_read_bool(node, "qcom,stacked-batfet")) chip->dt.pl_batfet_mode = POWER_SUPPLY_PL_STACKED_BATFET; chip->dt.hw_die_temp_mitigation = of_property_read_bool(node, "qcom,hw-die-temp-mitigation"); chip->dt.die_temp_threshold = DEFAULT_DIE_TEMP_LOW_THRESHOLD; of_property_read_u32(node, "qcom,die-temp-threshold-degc", &chip->dt.die_temp_threshold); if (chip->dt.die_temp_threshold > DIE_LOW_RANGE_MAX_DEGC) chip->dt.die_temp_threshold = DIE_LOW_RANGE_MAX_DEGC; return 0; } Loading @@ -520,6 +537,7 @@ static enum power_supply_property smb1355_parallel_props[] = { POWER_SUPPLY_PROP_MIN_ICL, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_SET_SHIP_MODE, POWER_SUPPLY_PROP_DIE_HEALTH, }; static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip, Loading @@ -546,10 +564,13 @@ static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip, return rc; } static int smb1355_get_prop_connector_health(struct smb1355 *chip) static int smb1355_get_prop_health(struct smb1355 *chip, int type) { u8 temp; int rc; int rc, shift; /* Connector-temp uses skin-temp configuration */ shift = (type == CONNECTOR_TEMP) ? SKIN_TEMP_SHIFT : 0; rc = smb1355_read(chip, TEMP_COMP_STATUS_REG, &temp); if (rc < 0) { Loading @@ -557,13 +578,13 @@ static int smb1355_get_prop_connector_health(struct smb1355 *chip) return POWER_SUPPLY_HEALTH_UNKNOWN; } if (temp & SKIN_TEMP_RST_HOT_BIT) if (temp & (TEMP_RST_HOT_BIT << shift)) return POWER_SUPPLY_HEALTH_OVERHEAT; if (temp & SKIN_TEMP_UB_HOT_BIT) if (temp & (TEMP_UB_HOT_BIT << shift)) return POWER_SUPPLY_HEALTH_HOT; if (temp & SKIN_TEMP_LB_HOT_BIT) if (temp & (TEMP_LB_HOT_BIT << shift)) return POWER_SUPPLY_HEALTH_WARM; return POWER_SUPPLY_HEALTH_COOL; Loading Loading @@ -614,6 +635,16 @@ static int smb1355_parallel_get_prop(struct power_supply *psy, val->intval = chip->die_temp_deciDegC; break; case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: /* * In case of h/w controlled die_temp mitigation, * die_temp/die_temp_max can not be reported as this * requires run time manipulation of DIE_TEMP low * threshold which will interfere with h/w mitigation * scheme. */ if (chip->dt.hw_die_temp_mitigation) val->intval = -EINVAL; else rc = smb1355_get_prop_charger_temp_max(chip, val); break; case POWER_SUPPLY_PROP_INPUT_SUSPEND: Loading @@ -635,10 +666,14 @@ static int smb1355_parallel_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: if (chip->c_health == -EINVAL) val->intval = smb1355_get_prop_connector_health(chip); val->intval = smb1355_get_prop_health(chip, CONNECTOR_TEMP); else val->intval = chip->c_health; break; case POWER_SUPPLY_PROP_DIE_HEALTH: val->intval = smb1355_get_prop_health(chip, DIE_TEMP); break; case POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE: val->intval = chip->dt.pl_batfet_mode; break; Loading Loading @@ -708,6 +743,8 @@ static int smb1355_set_parallel_charging(struct smb1355 *chip, bool disable) } chip->die_temp_deciDegC = -EINVAL; /* Only enable temperature measurement for s/w based mitigation */ if (!chip->dt.hw_die_temp_mitigation) { if (disable) { chip->exit_die_temp = true; cancel_delayed_work_sync(&chip->die_temp_work); Loading @@ -716,6 +753,7 @@ static int smb1355_set_parallel_charging(struct smb1355 *chip, bool disable) chip->exit_die_temp = false; schedule_delayed_work(&chip->die_temp_work, 0); } } if (chip->irq_disable_votable) vote(chip->irq_disable_votable, PARALLEL_ENABLE_VOTER, Loading Loading @@ -978,6 +1016,7 @@ static int smb1355_tskin_sensor_config(struct smb1355 *chip) static int smb1355_init_hw(struct smb1355 *chip) { int rc; u8 val, range; /* request clock always on */ rc = smb1355_clk_request(chip, true); Loading Loading @@ -1045,13 +1084,35 @@ static int smb1355_init_hw(struct smb1355 *chip) return rc; } /* Configure DIE temp Low threshold */ if (chip->dt.hw_die_temp_mitigation) { range = (chip->dt.die_temp_threshold - DIE_LOW_RANGE_BASE_DEGC) / (DIE_LOW_RANGE_DELTA); val = (chip->dt.die_temp_threshold - ((range * DIE_LOW_RANGE_DELTA) + DIE_LOW_RANGE_BASE_DEGC)) % DIE_LOW_RANGE_DELTA; rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP, TDIE_COMPARATOR_THRESHOLD, (range << DIE_LOW_RANGE_SHIFT) | val); if (rc < 0) { pr_err("Couldn't set temp comp threshold rc=%d\n", rc); return rc; } } /* * Enable thermal Die temperature comparator source and disable hw * mitigation for skin/die * Enable thermal Die temperature comparator source and * enable hardware controlled current adjustment for die temp * if charger is configured in h/w controlled die temp mitigation. */ val = THERMREG_DIE_CMP_SRC_EN_BIT; if (!chip->dt.hw_die_temp_mitigation) val |= BYP_THERM_CHG_CURR_ADJUST_BIT; rc = smb1355_masked_write(chip, MISC_THERMREG_SRC_CFG_REG, THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT, THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT); val); if (rc < 0) { pr_err("Couldn't set Skin temperature comparator src rc=%d\n", rc); Loading @@ -1062,8 +1123,9 @@ static int smb1355_init_hw(struct smb1355 *chip) * Disable hysterisis for die temperature. This is so that sw can run * stepping scheme quickly */ val = chip->dt.hw_die_temp_mitigation ? DIE_TEMP_COMP_HYST_BIT : 0; rc = smb1355_masked_write(chip, BATIF_ENG_SCMISC_SPARE1_REG, DIE_TEMP_COMP_HYST_BIT, 0); DIE_TEMP_COMP_HYST_BIT, val); if (rc < 0) { pr_err("Couldn't disable hyst. for die rc=%d\n", rc); return rc; Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt +12 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,18 @@ Charger specific properties: stacked one after the other and thus all the charge current (FCC) flows through main. In a non-stacked configuration each charger controls the charge current (FCC) separately. - qcom,die-temp-threshold-degc Usage: optional Value type: <u32> Definition: Specifies DIE temp threshold beyond which h/w starts mitigation. If not sepcified, 90 degrees centigrade is used. - qcom,hw-die-temp-mitigation Usage: optional Value type: bool Definition: Boolean property to enable h/w controlled die temp mitigation. ================================================ Second Level Nodes - SMB1355 Charger Peripherals ================================================ Loading
drivers/power/supply/qcom/smb1355-charger.c +91 −29 Original line number Diff line number Diff line Loading @@ -80,8 +80,12 @@ #define BATIF_CFG_SMISC_BATID_REG (BATIF_BASE + 0x73) #define CFG_SMISC_RBIAS_EXT_CTRL_BIT BIT(2) #define SMB2CHGS_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0) #define SMB2CHG_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0) #define TDIE_COMPARATOR_THRESHOLD GENMASK(5, 0) #define DIE_LOW_RANGE_BASE_DEGC 34 #define DIE_LOW_RANGE_DELTA 16 #define DIE_LOW_RANGE_MAX_DEGC 97 #define DIE_LOW_RANGE_SHIFT 4 #define BATIF_ENG_SCMISC_SPARE1_REG (BATIF_BASE + 0xC2) #define EXT_BIAS_PIN_BIT BIT(2) Loading @@ -91,13 +95,10 @@ #define VALLEY_COMPARATOR_EN_BIT BIT(0) #define TEMP_COMP_STATUS_REG (MISC_BASE + 0x07) #define SKIN_TEMP_RST_HOT_BIT BIT(6) #define SKIN_TEMP_UB_HOT_BIT BIT(5) #define SKIN_TEMP_LB_HOT_BIT BIT(4) #define DIE_TEMP_TSD_HOT_BIT BIT(3) #define DIE_TEMP_RST_HOT_BIT BIT(2) #define DIE_TEMP_UB_HOT_BIT BIT(1) #define DIE_TEMP_LB_HOT_BIT BIT(0) #define TEMP_RST_HOT_BIT BIT(2) #define TEMP_UB_HOT_BIT BIT(1) #define TEMP_LB_HOT_BIT BIT(0) #define SKIN_TEMP_SHIFT 4 #define MISC_RT_STS_REG (MISC_BASE + 0x10) #define HARD_ILIMIT_RT_STS_BIT BIT(5) Loading Loading @@ -223,6 +224,8 @@ struct smb_dt_props { bool disable_ctm; int pl_mode; int pl_batfet_mode; bool hw_die_temp_mitigation; u32 die_temp_threshold; }; struct smb1355 { Loading Loading @@ -250,6 +253,11 @@ struct smb1355 { struct votable *irq_disable_votable; }; enum { CONNECTOR_TEMP = 0, DIE_TEMP, }; static bool is_secure(struct smb1355 *chip, int addr) { if (addr == CLOCK_REQUEST_REG) Loading Loading @@ -379,8 +387,7 @@ static void die_temp_work(struct work_struct *work) u8 temp_stat; for (i = 0; i < BIT(5); i++) { rc = smb1355_masked_write(chip, SMB2CHGS_BATIF_ENG_SMISC_DIETEMP, rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP, TDIE_COMPARATOR_THRESHOLD, i); if (rc < 0) { pr_err("Couldn't set temp comp threshold rc=%d\n", rc); Loading @@ -399,7 +406,7 @@ static void die_temp_work(struct work_struct *work) continue; } if (!(temp_stat & DIE_TEMP_UB_HOT_BIT)) { if (!(temp_stat & TEMP_UB_HOT_BIT)) { /* found the temp */ break; } Loading Loading @@ -465,6 +472,7 @@ static int smb1355_determine_initial_status(struct smb1355 *chip) return 0; } #define DEFAULT_DIE_TEMP_LOW_THRESHOLD 90 static int smb1355_parse_dt(struct smb1355 *chip) { struct device_node *node = chip->dev->of_node; Loading Loading @@ -495,6 +503,15 @@ static int smb1355_parse_dt(struct smb1355 *chip) if (of_property_read_bool(node, "qcom,stacked-batfet")) chip->dt.pl_batfet_mode = POWER_SUPPLY_PL_STACKED_BATFET; chip->dt.hw_die_temp_mitigation = of_property_read_bool(node, "qcom,hw-die-temp-mitigation"); chip->dt.die_temp_threshold = DEFAULT_DIE_TEMP_LOW_THRESHOLD; of_property_read_u32(node, "qcom,die-temp-threshold-degc", &chip->dt.die_temp_threshold); if (chip->dt.die_temp_threshold > DIE_LOW_RANGE_MAX_DEGC) chip->dt.die_temp_threshold = DIE_LOW_RANGE_MAX_DEGC; return 0; } Loading @@ -520,6 +537,7 @@ static enum power_supply_property smb1355_parallel_props[] = { POWER_SUPPLY_PROP_MIN_ICL, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_SET_SHIP_MODE, POWER_SUPPLY_PROP_DIE_HEALTH, }; static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip, Loading @@ -546,10 +564,13 @@ static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip, return rc; } static int smb1355_get_prop_connector_health(struct smb1355 *chip) static int smb1355_get_prop_health(struct smb1355 *chip, int type) { u8 temp; int rc; int rc, shift; /* Connector-temp uses skin-temp configuration */ shift = (type == CONNECTOR_TEMP) ? SKIN_TEMP_SHIFT : 0; rc = smb1355_read(chip, TEMP_COMP_STATUS_REG, &temp); if (rc < 0) { Loading @@ -557,13 +578,13 @@ static int smb1355_get_prop_connector_health(struct smb1355 *chip) return POWER_SUPPLY_HEALTH_UNKNOWN; } if (temp & SKIN_TEMP_RST_HOT_BIT) if (temp & (TEMP_RST_HOT_BIT << shift)) return POWER_SUPPLY_HEALTH_OVERHEAT; if (temp & SKIN_TEMP_UB_HOT_BIT) if (temp & (TEMP_UB_HOT_BIT << shift)) return POWER_SUPPLY_HEALTH_HOT; if (temp & SKIN_TEMP_LB_HOT_BIT) if (temp & (TEMP_LB_HOT_BIT << shift)) return POWER_SUPPLY_HEALTH_WARM; return POWER_SUPPLY_HEALTH_COOL; Loading Loading @@ -614,6 +635,16 @@ static int smb1355_parallel_get_prop(struct power_supply *psy, val->intval = chip->die_temp_deciDegC; break; case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: /* * In case of h/w controlled die_temp mitigation, * die_temp/die_temp_max can not be reported as this * requires run time manipulation of DIE_TEMP low * threshold which will interfere with h/w mitigation * scheme. */ if (chip->dt.hw_die_temp_mitigation) val->intval = -EINVAL; else rc = smb1355_get_prop_charger_temp_max(chip, val); break; case POWER_SUPPLY_PROP_INPUT_SUSPEND: Loading @@ -635,10 +666,14 @@ static int smb1355_parallel_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: if (chip->c_health == -EINVAL) val->intval = smb1355_get_prop_connector_health(chip); val->intval = smb1355_get_prop_health(chip, CONNECTOR_TEMP); else val->intval = chip->c_health; break; case POWER_SUPPLY_PROP_DIE_HEALTH: val->intval = smb1355_get_prop_health(chip, DIE_TEMP); break; case POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE: val->intval = chip->dt.pl_batfet_mode; break; Loading Loading @@ -708,6 +743,8 @@ static int smb1355_set_parallel_charging(struct smb1355 *chip, bool disable) } chip->die_temp_deciDegC = -EINVAL; /* Only enable temperature measurement for s/w based mitigation */ if (!chip->dt.hw_die_temp_mitigation) { if (disable) { chip->exit_die_temp = true; cancel_delayed_work_sync(&chip->die_temp_work); Loading @@ -716,6 +753,7 @@ static int smb1355_set_parallel_charging(struct smb1355 *chip, bool disable) chip->exit_die_temp = false; schedule_delayed_work(&chip->die_temp_work, 0); } } if (chip->irq_disable_votable) vote(chip->irq_disable_votable, PARALLEL_ENABLE_VOTER, Loading Loading @@ -978,6 +1016,7 @@ static int smb1355_tskin_sensor_config(struct smb1355 *chip) static int smb1355_init_hw(struct smb1355 *chip) { int rc; u8 val, range; /* request clock always on */ rc = smb1355_clk_request(chip, true); Loading Loading @@ -1045,13 +1084,35 @@ static int smb1355_init_hw(struct smb1355 *chip) return rc; } /* Configure DIE temp Low threshold */ if (chip->dt.hw_die_temp_mitigation) { range = (chip->dt.die_temp_threshold - DIE_LOW_RANGE_BASE_DEGC) / (DIE_LOW_RANGE_DELTA); val = (chip->dt.die_temp_threshold - ((range * DIE_LOW_RANGE_DELTA) + DIE_LOW_RANGE_BASE_DEGC)) % DIE_LOW_RANGE_DELTA; rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP, TDIE_COMPARATOR_THRESHOLD, (range << DIE_LOW_RANGE_SHIFT) | val); if (rc < 0) { pr_err("Couldn't set temp comp threshold rc=%d\n", rc); return rc; } } /* * Enable thermal Die temperature comparator source and disable hw * mitigation for skin/die * Enable thermal Die temperature comparator source and * enable hardware controlled current adjustment for die temp * if charger is configured in h/w controlled die temp mitigation. */ val = THERMREG_DIE_CMP_SRC_EN_BIT; if (!chip->dt.hw_die_temp_mitigation) val |= BYP_THERM_CHG_CURR_ADJUST_BIT; rc = smb1355_masked_write(chip, MISC_THERMREG_SRC_CFG_REG, THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT, THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT); val); if (rc < 0) { pr_err("Couldn't set Skin temperature comparator src rc=%d\n", rc); Loading @@ -1062,8 +1123,9 @@ static int smb1355_init_hw(struct smb1355 *chip) * Disable hysterisis for die temperature. This is so that sw can run * stepping scheme quickly */ val = chip->dt.hw_die_temp_mitigation ? DIE_TEMP_COMP_HYST_BIT : 0; rc = smb1355_masked_write(chip, BATIF_ENG_SCMISC_SPARE1_REG, DIE_TEMP_COMP_HYST_BIT, 0); DIE_TEMP_COMP_HYST_BIT, val); if (rc < 0) { pr_err("Couldn't disable hyst. for die rc=%d\n", rc); return rc; Loading