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

Commit d2ae2dfd authored by Ashay Jaiswal's avatar Ashay Jaiswal Committed by Harry Yang
Browse files

power: smb1390/battery: update ILIM configuration logic



Current design configures SMB1390's ILIM as minimum of settled
AICL or FCC/2, update this logic to configure ILIM as minimum of
ICL or 3.2A(max. ILIM) for parallel configuration where SMB1390 is
directly connected to VPH node. Configuring ILIM to higher current
will keep SMB1390 out of ILIM condition.

Change-Id: Icbfb8eee950e5cd80410a10e43e765ffd286f729
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
parent dc6d3a31
Loading
Loading
Loading
Loading
+57 −14
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ struct pl_data {
	struct votable		*usb_icl_votable;
	struct votable		*usb_icl_votable;
	struct votable		*pl_enable_votable_indirect;
	struct votable		*pl_enable_votable_indirect;
	struct votable		*cp_ilim_votable;
	struct votable		*cp_ilim_votable;
	struct votable		*cp_disable_votable;
	struct delayed_work	status_change_work;
	struct delayed_work	status_change_work;
	struct work_struct	pl_disable_forever_work;
	struct work_struct	pl_disable_forever_work;
	struct work_struct	pl_taper_work;
	struct work_struct	pl_taper_work;
@@ -126,6 +127,37 @@ enum {
	RESTRICT_CHG_CURRENT,
	RESTRICT_CHG_CURRENT,
	FCC_STEPPING_IN_PROGRESS,
	FCC_STEPPING_IN_PROGRESS,
};
};
/*********
 * HELPER*
 *********/
static bool is_cp_available(struct pl_data *chip)
{
	if (!chip->cp_master_psy)
		chip->cp_master_psy =
			power_supply_get_by_name("charge_pump_master");

	return !!chip->cp_master_psy;
}

static bool cp_ilim_boost_enabled(struct pl_data *chip)
{
	union power_supply_propval pval = {-1, };

	if (is_cp_available(chip))
		power_supply_get_property(chip->cp_master_psy,
				POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE, &pval);

	return pval.intval == POWER_SUPPLY_PL_OUTPUT_VPH;
}

static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim)
{
	if (!chip->cp_ilim_votable)
		chip->cp_ilim_votable = find_votable("CP_ILIM");

	if (!cp_ilim_boost_enabled(chip) && chip->cp_ilim_votable)
		vote(chip->cp_ilim_votable, voter, true, ilim);
}


/*******
/*******
 * ICL *
 * ICL *
@@ -487,10 +519,7 @@ static void get_main_fcc_config(struct pl_data *chip, int *total_fcc)
	union power_supply_propval pval = {0, };
	union power_supply_propval pval = {0, };
	int rc;
	int rc;


	if (!chip->cp_master_psy)
	if (!is_cp_available(chip))
		chip->cp_master_psy =
			power_supply_get_by_name("charge_pump_master");
	if (!chip->cp_master_psy)
		goto out;
		goto out;


	rc = power_supply_get_property(chip->cp_master_psy,
	rc = power_supply_get_property(chip->cp_master_psy,
@@ -661,6 +690,7 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
{
{
	struct pl_data *chip = data;
	struct pl_data *chip = data;
	int master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0;
	int master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0;
	union power_supply_propval pval = {0, };


	if (total_fcc_ua < 0)
	if (total_fcc_ua < 0)
		return 0;
		return 0;
@@ -668,8 +698,26 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
	if (!chip->main_psy)
	if (!chip->main_psy)
		return 0;
		return 0;


	if (!chip->cp_ilim_votable)
	if (!chip->cp_disable_votable)
		chip->cp_ilim_votable = find_votable("CP_ILIM");
		chip->cp_disable_votable = find_votable("CP_DISABLE");

	if (chip->cp_disable_votable) {
		if (cp_ilim_boost_enabled(chip)) {
			power_supply_get_property(chip->cp_master_psy,
					POWER_SUPPLY_PROP_MIN_ICL, &pval);
			/*
			 * With ILIM boost feature ILIM configuration is
			 * independent of battery FCC, disable CP if FCC/2
			 * falls below MIN_ICL supported by CP.
			 */
			if ((total_fcc_ua / 2) < pval.intval)
				vote(chip->cp_disable_votable, FCC_VOTER,
						true, 0);
			else
				vote(chip->cp_disable_votable, FCC_VOTER,
						false, 0);
		}
	}


	if (chip->pl_mode != POWER_SUPPLY_PL_NONE) {
	if (chip->pl_mode != POWER_SUPPLY_PL_NONE) {
		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
@@ -867,9 +915,7 @@ static void fcc_stepper_work(struct work_struct *work)
	chip->main_fcc_ua = main_fcc;
	chip->main_fcc_ua = main_fcc;
	chip->slave_fcc_ua = parallel_fcc;
	chip->slave_fcc_ua = parallel_fcc;


	if (chip->cp_ilim_votable)
	cp_configure_ilim(chip, FCC_VOTER, chip->main_fcc_ua / 2);
		vote(chip->cp_ilim_votable, FCC_VOTER, true,
					chip->main_fcc_ua / 2);


	if (reschedule_ms) {
	if (reschedule_ms) {
		schedule_delayed_work(&chip->fcc_stepper_work,
		schedule_delayed_work(&chip->fcc_stepper_work,
@@ -986,8 +1032,7 @@ static int usb_icl_vote_callback(struct votable *votable, void *data,


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


	if (chip->cp_ilim_votable)
	cp_configure_ilim(chip, ICL_CHANGE_VOTER, icl_ua);
		vote(chip->cp_ilim_votable, ICL_CHANGE_VOTER, true, icl_ua);


	return 0;
	return 0;
}
}
@@ -1247,9 +1292,7 @@ static int pl_disable_vote_callback(struct votable *votable,
				return rc;
				return rc;
			}
			}


			if (chip->cp_ilim_votable)
			cp_configure_ilim(chip, FCC_VOTER, total_fcc_ua / 2);
				vote(chip->cp_ilim_votable, FCC_VOTER, true,
						total_fcc_ua / 2);


			/* reset parallel FCC */
			/* reset parallel FCC */
			chip->slave_fcc_ua = 0;
			chip->slave_fcc_ua = 0;
+66 −16
Original line number Original line Diff line number Diff line
@@ -75,6 +75,9 @@
#define WINDOW_DETECTION_DELTA_X1P0	0
#define WINDOW_DETECTION_DELTA_X1P0	0
#define WINDOW_DETECTION_DELTA_X1P5	1
#define WINDOW_DETECTION_DELTA_X1P5	1


#define CORE_FTRIM_DIS_REG		0x1035
#define TR_DIS_ILIM_DET_BIT		BIT(4)

#define CORE_ATEST1_SEL_REG		0x10E2
#define CORE_ATEST1_SEL_REG		0x10E2
#define ATEST1_OUTPUT_ENABLE_BIT	BIT(7)
#define ATEST1_OUTPUT_ENABLE_BIT	BIT(7)
#define ATEST1_SEL_MASK			GENMASK(6, 0)
#define ATEST1_SEL_MASK			GENMASK(6, 0)
@@ -92,6 +95,7 @@
#define SOC_LEVEL_VOTER		"SOC_LEVEL_VOTER"
#define SOC_LEVEL_VOTER		"SOC_LEVEL_VOTER"


#define THERMAL_SUSPEND_DECIDEGC	1400
#define THERMAL_SUSPEND_DECIDEGC	1400
#define MAX_ILIM_UA			3200000


#define smb1390_dbg(chip, reason, fmt, ...)				\
#define smb1390_dbg(chip, reason, fmt, ...)				\
	do {								\
	do {								\
@@ -174,6 +178,7 @@ struct smb1390 {
	u32			min_ilim_ua;
	u32			min_ilim_ua;
	u32			max_temp_alarm_degc;
	u32			max_temp_alarm_degc;
	u32			max_cutoff_soc;
	u32			max_cutoff_soc;
	u32			pl_output_mode;
};
};


struct smb_irq {
struct smb_irq {
@@ -262,12 +267,29 @@ static bool is_psy_voter_available(struct smb1390 *chip)


static void cp_toggle_switcher(struct smb1390 *chip)
static void cp_toggle_switcher(struct smb1390 *chip)
{
{
	int rc;

	/*
	 * Disable ILIM detection before toggling the switcher
	 * to prevent any ILIM interrupt storm while toggling
	 * the switcher.
	 */
	rc = regmap_update_bits(chip->regmap, CORE_FTRIM_DIS_REG,
			TR_DIS_ILIM_DET_BIT, TR_DIS_ILIM_DET_BIT);
	if (rc < 0)
		pr_err("Couldn't disable ILIM rc=%d\n", rc);

	vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, true, 0);
	vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, true, 0);


	/* Delay for toggling switcher */
	/* Delay for toggling switcher */
	usleep_range(20, 30);
	usleep_range(20, 30);


	vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, false, 0);
	vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, false, 0);

	rc = regmap_update_bits(chip->regmap, CORE_FTRIM_DIS_REG,
			TR_DIS_ILIM_DET_BIT, 0);
	if (rc < 0)
		pr_err("Couldn't enable ILIM rc=%d\n", rc);
}
}


static int smb1390_get_cp_en_status(struct smb1390 *chip, int id, bool *enable)
static int smb1390_get_cp_en_status(struct smb1390 *chip, int id, bool *enable)
@@ -522,6 +544,7 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data,
		return -EINVAL;
		return -EINVAL;
	}
	}


	ilim_uA = min(ilim_uA, MAX_ILIM_UA);
	rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG,
	rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG,
		CFG_ILIM_MASK,
		CFG_ILIM_MASK,
		DIV_ROUND_CLOSEST(max(ilim_uA, 500000) - 500000, 100000));
		DIV_ROUND_CLOSEST(max(ilim_uA, 500000) - 500000, 100000));
@@ -568,6 +591,9 @@ static int smb1390_notifier_cb(struct notifier_block *nb,
	return NOTIFY_OK;
	return NOTIFY_OK;
}
}


#define ILIM_NR			10
#define ILIM_DR			8
#define ILIM_FACTOR(ilim)	((ilim * ILIM_NR) / ILIM_DR)
static void smb1390_status_change_work(struct work_struct *work)
static void smb1390_status_change_work(struct work_struct *work)
{
{
	struct smb1390 *chip = container_of(work, struct smb1390,
	struct smb1390 *chip = container_of(work, struct smb1390,
@@ -598,11 +624,6 @@ static void smb1390_status_change_work(struct work_struct *work)


		vote(chip->disable_votable, SRC_VOTER, false, 0);
		vote(chip->disable_votable, SRC_VOTER, false, 0);


		/*
		 * ILIM is set based on the primary chargers AICL result. This
		 * ensures VBUS does not collapse due to the current drawn via
		 * MID.
		 */
		if (pval.intval == POWER_SUPPLY_CP_WIRELESS) {
		if (pval.intval == POWER_SUPPLY_CP_WIRELESS) {
			vote(chip->ilim_votable, ICL_VOTER, false, 0);
			vote(chip->ilim_votable, ICL_VOTER, false, 0);
			rc = power_supply_get_property(chip->dc_psy,
			rc = power_supply_get_property(chip->dc_psy,
@@ -612,15 +633,30 @@ static void smb1390_status_change_work(struct work_struct *work)
			else
			else
				vote(chip->ilim_votable, WIRELESS_VOTER, true,
				vote(chip->ilim_votable, WIRELESS_VOTER, true,
						pval.intval);
						pval.intval);
		} else { /* QC3 or PPS */
		} else {
			vote(chip->ilim_votable, WIRELESS_VOTER, false, 0);
			vote(chip->ilim_votable, WIRELESS_VOTER, false, 0);
			if ((chip->pl_output_mode == POWER_SUPPLY_PL_OUTPUT_VPH)
				&& (pval.intval == POWER_SUPPLY_CP_PPS)) {
				rc = power_supply_get_property(chip->usb_psy,
				rc = power_supply_get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval);
					POWER_SUPPLY_PROP_PD_CURRENT_MAX,
					&pval);
				if (rc < 0)
				if (rc < 0)
				pr_err("Couldn't get usb icl rc=%d\n", rc);
					pr_err("Couldn't get PD CURRENT MAX rc=%d\n",
							rc);
				else
				else
				vote(chip->ilim_votable, ICL_VOTER, true,
					vote(chip->ilim_votable, ICL_VOTER,
								pval.intval);
						true, ILIM_FACTOR(pval.intval));
			} else {
				rc = power_supply_get_property(chip->usb_psy,
					POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
					&pval);
				if (rc < 0)
					pr_err("Couldn't get usb aicl rc=%d\n",
							rc);
				else
					vote(chip->ilim_votable, ICL_VOTER,
							true, pval.intval);
			}
		}
		}


		/*
		/*
@@ -729,6 +765,8 @@ static enum power_supply_property smb1390_charge_pump_props[] = {
	POWER_SUPPLY_PROP_CP_IRQ_STATUS,
	POWER_SUPPLY_PROP_CP_IRQ_STATUS,
	POWER_SUPPLY_PROP_CP_ILIM,
	POWER_SUPPLY_PROP_CP_ILIM,
	POWER_SUPPLY_PROP_CHIP_VERSION,
	POWER_SUPPLY_PROP_CHIP_VERSION,
	POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE,
	POWER_SUPPLY_PROP_MIN_ICL,
};
};


static int smb1390_get_prop(struct power_supply *psy,
static int smb1390_get_prop(struct power_supply *psy,
@@ -818,6 +856,12 @@ static int smb1390_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CHIP_VERSION:
	case POWER_SUPPLY_PROP_CHIP_VERSION:
		val->intval = chip->pmic_rev_id->rev4;
		val->intval = chip->pmic_rev_id->rev4;
		break;
		break;
	case POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE:
		val->intval = chip->pl_output_mode;
		break;
	case POWER_SUPPLY_PROP_MIN_ICL:
		val->intval = chip->min_ilim_ua;
		break;
	default:
	default:
		smb1390_dbg(chip, PR_MISC, "charge pump power supply get prop %d not supported\n",
		smb1390_dbg(chip, PR_MISC, "charge pump power supply get prop %d not supported\n",
			prop);
			prop);
@@ -931,6 +975,10 @@ static int smb1390_parse_dt(struct smb1390 *chip)
	of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc",
	of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc",
			&chip->max_cutoff_soc);
			&chip->max_cutoff_soc);


	/* Default parallel output configuration is VPH connection */
	chip->pl_output_mode = POWER_SUPPLY_PL_OUTPUT_VPH;
	of_property_read_u32(chip->dev->of_node, "qcom,parallel-output-mode",
			&chip->pl_output_mode);
	return 0;
	return 0;
}
}


@@ -963,9 +1011,11 @@ static int smb1390_create_votables(struct smb1390 *chip)


	/*
	/*
	 * In case SMB1390 probe happens after FCC value has been configured,
	 * In case SMB1390 probe happens after FCC value has been configured,
	 * update ilim vote to reflect FCC / 2 value.
	 * update ilim vote to reflect FCC / 2 value, this is only applicable
	 * when SMB1390 is directly connected to VBAT.
	 */
	 */
	if (chip->fcc_votable)
	if ((chip->pl_output_mode != POWER_SUPPLY_PL_OUTPUT_VPH)
			&& chip->fcc_votable)
		vote(chip->ilim_votable, FCC_VOTER, true,
		vote(chip->ilim_votable, FCC_VOTER, true,
			get_effective_result(chip->fcc_votable) / 2);
			get_effective_result(chip->fcc_votable) / 2);