Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cd8ac49 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qcom: battery: update FCC split policy"

parents 42e05c9a b4d32925
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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
================================================
+103 −31
Original line number Diff line number Diff line
/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -47,6 +47,7 @@

struct pl_data {
	int			pl_mode;
	int			pl_batfet_mode;
	int			slave_pct;
	int			slave_fcc_ua;
	int			restricted_current;
@@ -155,12 +156,22 @@ static void split_settled(struct pl_data *chip)
		total_current_ua = pval.intval;
	}

	/*
	 * If there is an increase in slave share
	 * (Also handles parallel enable case)
	 *	Set Main ICL then slave ICL
	 * else
	 * (Also handles parallel disable case)
	 *	Set slave ICL then main ICL.
	 */
	if (slave_ua > chip->pl_settled_ua) {
		pval.intval = total_current_ua - slave_ua;
		/* Set ICL on main charger */
		rc = power_supply_set_property(chip->main_psy,
				POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
		if (rc < 0) {
		pr_err("Couldn't change slave suspend state rc=%d\n", rc);
			pr_err("Couldn't change slave suspend state rc=%d\n",
					rc);
			return;
		}

@@ -172,6 +183,26 @@ static void split_settled(struct pl_data *chip)
			pr_err("Couldn't set parallel icl, rc=%d\n", rc);
			return;
		}
	} else {
		/* set parallel's ICL  could be 0mA when pl is disabled */
		pval.intval = slave_ua;
		rc = power_supply_set_property(chip->pl_psy,
				POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
		if (rc < 0) {
			pr_err("Couldn't set parallel icl, rc=%d\n", rc);
			return;
		}

		pval.intval = total_current_ua - slave_ua;
		/* Set ICL on main charger */
		rc = power_supply_set_property(chip->main_psy,
				POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
		if (rc < 0) {
			pr_err("Couldn't change slave suspend state rc=%d\n",
					rc);
			return;
		}
	}

	chip->total_settled_ua = total_settled_ua;
	chip->pl_settled_ua = slave_ua;
@@ -345,11 +376,11 @@ static void get_fcc_split(struct pl_data *chip, int total_ua,
	*slave_ua = (slave_limited_ua * chip->slave_pct) / 100;

	/*
	 * In USBIN_USBIN configuration with internal rsense parallel
	 * charger's current goes through main charger's BATFET, keep
	 * the main charger's FCC to the votable result.
	 * In stacked BATFET configuration charger's current goes
	 * through main charger's BATFET, keep the main charger's FCC
	 * to the votable result.
	 */
	if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
	if (chip->pl_batfet_mode == POWER_SUPPLY_PL_STACKED_BATFET)
		*master_ua = max(0, total_ua);
	else
		*master_ua = max(0, total_ua - *slave_ua);
@@ -634,8 +665,15 @@ static int pl_disable_vote_callback(struct votable *votable,
		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
				&slave_fcc_ua);

		chip->slave_fcc_ua = slave_fcc_ua;

		/*
		 * If there is an increase in slave share
		 * (Also handles parallel enable case)
		 *	Set Main ICL then slave FCC
		 * else
		 * (Also handles parallel disable case)
		 *	Set slave ICL then main FCC.
		 */
		if (slave_fcc_ua > chip->slave_fcc_ua) {
			pval.intval = master_fcc_ua;
			rc = power_supply_set_property(chip->main_psy,
				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
@@ -650,9 +688,34 @@ static int pl_disable_vote_callback(struct votable *votable,
				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
				&pval);
			if (rc < 0) {
			pr_err("Couldn't set parallel fcc, rc=%d\n", rc);
				pr_err("Couldn't set parallel fcc, rc=%d\n",
						rc);
				return rc;
			}

			chip->slave_fcc_ua = slave_fcc_ua;
		} else {
			pval.intval = slave_fcc_ua;
			rc = power_supply_set_property(chip->pl_psy,
				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
				&pval);
			if (rc < 0) {
				pr_err("Couldn't set parallel fcc, rc=%d\n",
						rc);
				return rc;
			}

			chip->slave_fcc_ua = slave_fcc_ua;

			pval.intval = master_fcc_ua;
			rc = power_supply_set_property(chip->main_psy,
				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
				&pval);
			if (rc < 0) {
				pr_err("Could not set main fcc, rc=%d\n", rc);
				return rc;
			}
		}

		/*
		 * Enable will be called with a valid pl_psy always. The
@@ -806,6 +869,15 @@ static bool is_parallel_available(struct pl_data *chip)
			return false;
	}

	rc = power_supply_get_property(chip->pl_psy,
		       POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE, &pval);
	if (rc < 0) {
		pr_err("Couldn't get parallel batfet mode rc=%d\n",
				rc);
		return false;
	}
	chip->pl_batfet_mode = pval.intval;

	vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0);

	return true;
+274 −30
Original line number Diff line number Diff line
@@ -28,16 +28,21 @@
#include <linux/power_supply.h>
#include <linux/workqueue.h>
#include <linux/pmic-voter.h>
#include <linux/string.h>

/* SMB1355 registers, different than mentioned in smb-reg.h */

#define REVID_BASE	0x0100
#define I2C_SS_DIG_BASE 0x0E00
#define CHGR_BASE	0x1000
#define ANA2_BASE	0x1100
#define BATIF_BASE	0x1200
#define USBIN_BASE	0x1300
#define ANA1_BASE	0x1400
#define MISC_BASE	0x1600

#define REVID_MFG_ID_SPARE_REG                  (REVID_BASE + 0xFF)

#define I2C_SS_DIG_PMIC_SID_REG			(I2C_SS_DIG_BASE + 0x45)
#define PMIC_SID_MASK				GENMASK(3, 0)
#define PMIC_SID0_BIT				BIT(0)
@@ -80,28 +85,38 @@
#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)
#define DIE_TEMP_COMP_HYST_BIT			BIT(1)

#define ANA1_ENG_SREFGEN_CFG2_REG		(ANA1_BASE + 0xC1)
#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)

#define BANDGAP_ENABLE_REG			(MISC_BASE + 0x42)
#define BANDGAP_ENABLE_CMD_BIT			BIT(0)

#define BARK_BITE_WDOG_PET_REG			(MISC_BASE + 0x43)
#define BARK_BITE_WDOG_PET_BIT			BIT(0)

#define CLOCK_REQUEST_REG			(MISC_BASE + 0x44)
#define CLOCK_REQUEST_CMD_BIT			BIT(0)

#define WD_CFG_REG				(MISC_BASE + 0x51)
#define WATCHDOG_TRIGGER_AFP_EN_BIT		BIT(7)
#define BARK_WDOG_INT_EN_BIT			BIT(6)
@@ -113,6 +128,10 @@
#define MISC_CUST_SDCDC_CLK_CFG_REG		(MISC_BASE + 0xA0)
#define SWITCHER_CLK_FREQ_MASK			GENMASK(3, 0)

#define MISC_CUST_SDCDC_ILIMIT_CFG_REG		(MISC_BASE + 0xA1)
#define LS_VALLEY_THRESH_PCT_BIT		BIT(3)
#define PCL_LIMIT_MASK				GENMASK(1, 0)

#define SNARL_BARK_BITE_WD_CFG_REG		(MISC_BASE + 0x53)
#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT	BIT(7)
#define SNARL_WDOG_TIMEOUT_MASK			GENMASK(6, 4)
@@ -155,6 +174,8 @@
	((mode == POWER_SUPPLY_PL_USBIN_USBIN) \
	 || (mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))

#define PARALLEL_ENABLE_VOTER			"PARALLEL_ENABLE_VOTER"

struct smb_chg_param {
	const char	*name;
	u16		reg;
@@ -204,6 +225,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 {
@@ -211,6 +234,8 @@ struct smb1355 {
	char			*name;
	struct regmap		*regmap;

	int			max_fcc;

	struct smb_dt_props	dt;
	struct smb_params	param;

@@ -225,10 +250,20 @@ struct smb1355 {
	bool			exit_die_temp;
	struct delayed_work	die_temp_work;
	bool			disabled;

	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)
		return true;

	/* assume everything above 0xA0 is secure */
	return (addr & 0xFF) >= 0xA0;
}
@@ -245,6 +280,25 @@ static int smb1355_read(struct smb1355 *chip, u16 addr, u8 *val)
	return rc;
}

static int smb1355_masked_force_write(struct smb1355 *chip, u16 addr, u8 mask,
					u8 val)
{
	int rc;

	mutex_lock(&chip->write_lock);
	if (is_secure(chip, addr)) {
		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
		if (rc < 0)
			goto unlock;
	}

	rc = regmap_write_bits(chip->regmap, addr, mask, val);

unlock:
	mutex_unlock(&chip->write_lock);
	return rc;
}

static int smb1355_masked_write(struct smb1355 *chip, u16 addr, u8 mask, u8 val)
{
	int rc;
@@ -334,8 +388,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);
@@ -354,7 +407,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;
		}
@@ -420,6 +473,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;
@@ -450,6 +504,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;
}

@@ -470,9 +533,12 @@ static enum power_supply_property smb1355_parallel_props[] = {
	POWER_SUPPLY_PROP_PARALLEL_MODE,
	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
	POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE,
	POWER_SUPPLY_PROP_PARALLEL_FCC_MAX,
	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
	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,
@@ -499,10 +565,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) {
@@ -510,13 +579,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;
@@ -549,6 +618,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
			val->intval = chip->c_charger_temp_max;
		break;
	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
@@ -570,10 +649,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;
@@ -593,6 +676,13 @@ static int smb1355_parallel_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_MIN_ICL:
		val->intval = MIN_PARALLEL_ICL_UA;
		break;
	case POWER_SUPPLY_PROP_PARALLEL_FCC_MAX:
		val->intval = chip->max_fcc;
		break;
	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
		/* Not in ship mode as long as device is active */
		val->intval = 0;
		break;
	default:
		pr_err_ratelimited("parallel psy get prop %d not supported\n",
			prop);
@@ -636,6 +726,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);
@@ -644,6 +736,19 @@ 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,
				disable, 0);

	rc = smb1355_masked_write(chip, BANDGAP_ENABLE_REG,
				BANDGAP_ENABLE_CMD_BIT,
				disable ? 0 : BANDGAP_ENABLE_CMD_BIT);
	if (rc < 0) {
		pr_err("Couldn't configure bandgap enable rc=%d\n", rc);
		return rc;
	}

	chip->disabled = disable;

@@ -672,6 +777,20 @@ static int smb1355_set_current_max(struct smb1355 *chip, int curr)
	return rc;
}

static int smb1355_clk_request(struct smb1355 *chip, bool enable)
{
	int rc;

	rc = smb1355_masked_force_write(chip, CLOCK_REQUEST_REG,
				CLOCK_REQUEST_CMD_BIT,
				enable ? CLOCK_REQUEST_CMD_BIT : 0);
	if (rc < 0)
		pr_err("Couldn't %s clock rc=%d\n",
			       enable ? "enable" : "disable", rc);

	return rc;
}

static int smb1355_parallel_set_prop(struct power_supply *psy,
				     enum power_supply_property prop,
				     const union power_supply_propval *val)
@@ -700,6 +819,10 @@ static int smb1355_parallel_set_prop(struct power_supply *psy,
		break;
	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
		chip->c_charger_temp_max = val->intval;
	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
		if (!val->intval)
			break;
		rc = smb1355_clk_request(chip, false);
		break;
	default:
		pr_debug("parallel power supply set prop %d not supported\n",
@@ -758,6 +881,38 @@ static int smb1355_init_parallel_psy(struct smb1355 *chip)
 * HARDWARE INITIALIZATION *
 ***************************/

#define MFG_ID_SMB1354			0x01
#define MFG_ID_SMB1355			0xFF
#define SMB1354_MAX_PARALLEL_FCC_UA	2500000
#define SMB1355_MAX_PARALLEL_FCC_UA	6000000
static int smb1355_detect_version(struct smb1355 *chip)
{
	int rc;
	u8 val;

	rc = smb1355_read(chip, REVID_MFG_ID_SPARE_REG, &val);
	if (rc < 0) {
		pr_err("Unable to read REVID rc=%d\n", rc);
		return rc;
	}

	switch (val) {
	case MFG_ID_SMB1354:
		chip->name = "smb1354";
		chip->max_fcc = SMB1354_MAX_PARALLEL_FCC_UA;
		break;
	case MFG_ID_SMB1355:
		chip->name = "smb1355";
		chip->max_fcc = SMB1355_MAX_PARALLEL_FCC_UA;
		break;
	default:
		pr_err("Invalid value of REVID val=%d", val);
		return -EINVAL;
	}

	return rc;
}

static int smb1355_tskin_sensor_config(struct smb1355 *chip)
{
	int rc;
@@ -847,6 +1002,12 @@ 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);
	if (rc < 0)
		return rc;

	/* Change to let SMB1355 only respond to address 0x0C  */
	rc = smb1355_masked_write(chip, I2C_SS_DIG_PMIC_SID_REG,
@@ -918,13 +1079,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);
@@ -935,13 +1118,40 @@ 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;
	}

	/* Enable valley current comparator all the time */
	rc = smb1355_masked_write(chip, ANA1_ENG_SREFGEN_CFG2_REG,
		VALLEY_COMPARATOR_EN_BIT, VALLEY_COMPARATOR_EN_BIT);
	if (rc < 0) {
		pr_err("Couldn't enable valley current comparator rc=%d\n", rc);
		return rc;
	}

	/* Set LS_VALLEY threshold to 85% */
	rc = smb1355_masked_write(chip, MISC_CUST_SDCDC_ILIMIT_CFG_REG,
		LS_VALLEY_THRESH_PCT_BIT, LS_VALLEY_THRESH_PCT_BIT);
	if (rc < 0) {
		pr_err("Couldn't set LS valley threshold to 85pc rc=%d\n", rc);
		return rc;
	}

	/* For SMB1354, set PCL to 8.6 A */
	if (!strcmp(chip->name, "smb1354")) {
		rc = smb1355_masked_write(chip, MISC_CUST_SDCDC_ILIMIT_CFG_REG,
				PCL_LIMIT_MASK, PCL_LIMIT_MASK);
		if (rc < 0) {
			pr_err("Couldn't set PCL limit to 8.6A rc=%d\n", rc);
			return rc;
		}
	}

	rc = smb1355_tskin_sensor_config(chip);
	if (rc < 0) {
		pr_err("Couldn't configure tskin regs rc=%d\n", rc);
@@ -1079,6 +1289,7 @@ static int smb1355_request_interrupt(struct smb1355 *chip,
		return rc;
	}

	smb1355_irqs[irq_index].irq = irq;
	if (smb1355_irqs[irq_index].wake)
		enable_irq_wake(irq);

@@ -1107,6 +1318,23 @@ static int smb1355_request_interrupts(struct smb1355 *chip)

	return rc;
}
static int smb1355_irq_disable_callback(struct votable *votable, void *data,
			int disable, const char *client)

{
	int i;

	for (i = 0; i < ARRAY_SIZE(smb1355_irqs); i++) {
		if (smb1355_irqs[i].irq) {
			if (disable)
				disable_irq(smb1355_irqs[i].irq);
			else
				enable_irq(smb1355_irqs[i].irq);
		}
	}

	return 0;
}

/*********
 * PROBE *
@@ -1132,7 +1360,6 @@ static int smb1355_probe(struct platform_device *pdev)
	chip->param = v1_params;
	chip->c_health = -EINVAL;
	chip->c_charger_temp_max = -EINVAL;
	chip->name = "smb1355";
	mutex_init(&chip->write_lock);
	INIT_DELAYED_WORK(&chip->die_temp_work, die_temp_work);
	chip->disabled = true;
@@ -1150,6 +1377,12 @@ static int smb1355_probe(struct platform_device *pdev)
		return -ENODEV;
	}

	rc = smb1355_detect_version(chip);
	if (rc < 0) {
		pr_err("Couldn't detect SMB1355/1354 chip type rc=%d\n", rc);
		goto cleanup;
	}

	platform_set_drvdata(pdev, chip);

	rc = smb1355_parse_dt(chip);
@@ -1183,6 +1416,15 @@ static int smb1355_probe(struct platform_device *pdev)
		goto cleanup;
	}

	chip->irq_disable_votable = create_votable("SMB1355_IRQ_DISABLE",
			VOTE_SET_ANY, smb1355_irq_disable_callback, chip);
	if (IS_ERR(chip->irq_disable_votable)) {
		rc = PTR_ERR(chip->irq_disable_votable);
		goto cleanup;
	}
	/* keep IRQ's disabled until parallel is enabled */
	vote(chip->irq_disable_votable, PARALLEL_ENABLE_VOTER, true, 0);

	pr_info("%s probed successfully pl_mode=%s batfet_mode=%s\n",
		chip->name,
		IS_USBIN(chip->dt.pl_mode) ? "USBIN-USBIN" : "USBMID-USBMID",
@@ -1210,6 +1452,8 @@ static void smb1355_shutdown(struct platform_device *pdev)
	rc = smb1355_set_parallel_charging(chip, true);
	if (rc < 0)
		pr_err("Couldn't disable parallel path rc=%d\n", rc);

	smb1355_clk_request(chip, false);
}

static struct platform_driver smb1355_driver = {