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

Commit 2d9bc442 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: smb1390/battery: update ILIM configuration logic"

parents 7b67fb80 d2ae2dfd
Loading
Loading
Loading
Loading
+57 −14
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ struct pl_data {
	struct votable		*usb_icl_votable;
	struct votable		*pl_enable_votable_indirect;
	struct votable		*cp_ilim_votable;
	struct votable		*cp_disable_votable;
	struct delayed_work	status_change_work;
	struct work_struct	pl_disable_forever_work;
	struct work_struct	pl_taper_work;
@@ -128,6 +129,37 @@ enum {
	RESTRICT_CHG_CURRENT,
	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 *
@@ -489,10 +521,7 @@ static void get_main_fcc_config(struct pl_data *chip, int *total_fcc)
	union power_supply_propval pval = {0, };
	int rc;

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

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

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

	if (!chip->cp_ilim_votable)
		chip->cp_ilim_votable = find_votable("CP_ILIM");
	if (!chip->cp_disable_votable)
		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) {
		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
@@ -874,9 +922,7 @@ static void fcc_stepper_work(struct work_struct *work)
	chip->main_fcc_ua = main_fcc;
	chip->slave_fcc_ua = parallel_fcc;

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

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

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

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

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

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

			/* reset parallel FCC */
			chip->slave_fcc_ua = 0;
+66 −16
Original line number Diff line number Diff line
@@ -75,6 +75,9 @@
#define WINDOW_DETECTION_DELTA_X1P0	0
#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 ATEST1_OUTPUT_ENABLE_BIT	BIT(7)
#define ATEST1_SEL_MASK			GENMASK(6, 0)
@@ -92,6 +95,7 @@
#define SOC_LEVEL_VOTER		"SOC_LEVEL_VOTER"

#define THERMAL_SUSPEND_DECIDEGC	1400
#define MAX_ILIM_UA			3200000

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

struct smb_irq {
@@ -262,12 +267,29 @@ static bool is_psy_voter_available(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);

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

	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)
@@ -522,6 +544,7 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data,
		return -EINVAL;
	}

	ilim_uA = min(ilim_uA, MAX_ILIM_UA);
	rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG,
		CFG_ILIM_MASK,
		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;
}

#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)
{
	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);

		/*
		 * 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) {
			vote(chip->ilim_votable, ICL_VOTER, false, 0);
			rc = power_supply_get_property(chip->dc_psy,
@@ -612,15 +633,30 @@ static void smb1390_status_change_work(struct work_struct *work)
			else
				vote(chip->ilim_votable, WIRELESS_VOTER, true,
						pval.intval);
		} else { /* QC3 or PPS */
		} else {
			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,
				POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval);
					POWER_SUPPLY_PROP_PD_CURRENT_MAX,
					&pval);
				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
				vote(chip->ilim_votable, ICL_VOTER, true,
								pval.intval);
					vote(chip->ilim_votable, ICL_VOTER,
						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_ILIM,
	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,
@@ -818,6 +856,12 @@ static int smb1390_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CHIP_VERSION:
		val->intval = chip->pmic_rev_id->rev4;
		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:
		smb1390_dbg(chip, PR_MISC, "charge pump power supply get prop %d not supported\n",
			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",
			&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;
}

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

	/*
	 * 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,
			get_effective_result(chip->fcc_votable) / 2);