in supply/smb347-charger.c [531:671]
static int smb347_set_temp_limits(struct smb347_charger *smb)
{
unsigned int id = smb->id;
bool enable_therm_monitor = false;
int ret = 0;
int val;
if (smb->chip_temp_threshold) {
val = smb->chip_temp_threshold;
/* degree C */
val = clamp_val(val, 100, 130) - 100;
val /= 10;
ret = regmap_update_bits(smb->regmap, CFG_OTG,
CFG_OTG_TEMP_THRESHOLD_MASK,
val << CFG_OTG_TEMP_THRESHOLD_SHIFT);
if (ret < 0)
return ret;
}
if (smb->soft_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {
val = smb->soft_cold_temp_limit;
val = clamp_val(val, 0, 15);
val /= 5;
/* this goes from higher to lower so invert the value */
val = ~val & 0x3;
ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,
CFG_TEMP_LIMIT_SOFT_COLD_MASK,
val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT);
if (ret < 0)
return ret;
enable_therm_monitor = true;
}
if (smb->soft_hot_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {
val = smb->soft_hot_temp_limit;
val = clamp_val(val, 40, 55) - 40;
val /= 5;
ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,
CFG_TEMP_LIMIT_SOFT_HOT_MASK,
val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT);
if (ret < 0)
return ret;
enable_therm_monitor = true;
}
if (smb->hard_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {
val = smb->hard_cold_temp_limit;
val = clamp_val(val, -5, 10) + 5;
val /= 5;
/* this goes from higher to lower so invert the value */
val = ~val & 0x3;
ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,
CFG_TEMP_LIMIT_HARD_COLD_MASK,
val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT);
if (ret < 0)
return ret;
enable_therm_monitor = true;
}
if (smb->hard_hot_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {
val = smb->hard_hot_temp_limit;
val = clamp_val(val, 50, 65) - 50;
val /= 5;
ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,
CFG_TEMP_LIMIT_HARD_HOT_MASK,
val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT);
if (ret < 0)
return ret;
enable_therm_monitor = true;
}
/*
* If any of the temperature limits are set, we also enable the
* thermistor monitoring.
*
* When soft limits are hit, the device will start to compensate
* current and/or voltage depending on the configuration.
*
* When hard limit is hit, the device will suspend charging
* depending on the configuration.
*/
if (enable_therm_monitor) {
ret = regmap_update_bits(smb->regmap, CFG_THERM,
CFG_THERM_MONITOR_DISABLED, 0);
if (ret < 0)
return ret;
}
if (smb->suspend_on_hard_temp_limit) {
ret = regmap_update_bits(smb->regmap, CFG_SYSOK,
CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED, 0);
if (ret < 0)
return ret;
}
if (smb->soft_temp_limit_compensation !=
SMB3XX_SOFT_TEMP_COMPENSATE_DEFAULT) {
val = smb->soft_temp_limit_compensation & 0x3;
ret = regmap_update_bits(smb->regmap, CFG_THERM,
CFG_THERM_SOFT_HOT_COMPENSATION_MASK,
val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT);
if (ret < 0)
return ret;
ret = regmap_update_bits(smb->regmap, CFG_THERM,
CFG_THERM_SOFT_COLD_COMPENSATION_MASK,
val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT);
if (ret < 0)
return ret;
}
if (smb->charge_current_compensation) {
val = current_to_hw(ccc_tbl[id], ARRAY_SIZE(ccc_tbl[id]),
smb->charge_current_compensation);
if (val < 0)
return val;
ret = regmap_update_bits(smb->regmap, CFG_OTG,
CFG_OTG_CC_COMPENSATION_MASK,
(val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT);
if (ret < 0)
return ret;
}
return ret;
}