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

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

Merge "ARM: dts: msm: Enable fcc stepping for sm6150"

parents 0f724066 ca5b8130
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -245,6 +245,12 @@ Charger specific properties:
		This is only applicable to certain PMICs like PMI632 which
		has SCHGM_FLASH peripheral.

- qcom,fcc-stepping-enable
  Usage:      optional
  Value type: bool
  Definition: Boolean flag which when present enables stepwise change in FCC.
		The default stepping rate is 100mA/sec.

=============================================
Second Level Nodes - SMB5 Charger Peripherals
=============================================
+1 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@
	qcom,battery-data = <&mtp_batterydata>;
	qcom,step-charging-enable;
	qcom,sw-jeita-enable;
	qcom,fcc-stepping-enable;
	qcom,sec-charger-config = <3>;
};

+1 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@
	qcom,battery-data = <&mtp_batterydata>;
	qcom,step-charging-enable;
	qcom,sw-jeita-enable;
	qcom,fcc-stepping-enable;
	qcom,sec-charger-config = <1>;
};

+395 −86
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define USBIN_I_VOTER			"USBIN_I_VOTER"
#define PL_FCC_LOW_VOTER		"PL_FCC_LOW_VOTER"
#define ICL_LIMIT_VOTER			"ICL_LIMIT_VOTER"
#define FCC_STEPPER_VOTER		"FCC_STEPPER_VOTER"

struct pl_data {
	int			pl_mode;
@@ -52,6 +53,7 @@ struct pl_data {
	int			pl_min_icl_ua;
	int			slave_pct;
	int			slave_fcc_ua;
	int			main_fcc_ua;
	int			restricted_current;
	bool			restricted_charging_enabled;
	struct votable		*fcc_votable;
@@ -65,15 +67,25 @@ struct pl_data {
	struct work_struct	pl_disable_forever_work;
	struct work_struct	pl_taper_work;
	struct delayed_work	pl_awake_work;
	struct delayed_work	fcc_stepper_work;
	bool			taper_work_running;
	struct power_supply	*main_psy;
	struct power_supply	*pl_psy;
	struct power_supply	*batt_psy;
	struct power_supply	*usb_psy;
	struct power_supply	*dc_psy;
	int			charge_type;
	int			total_settled_ua;
	int			pl_settled_ua;
	int			pl_fcc_max;
	int			fcc_stepper_enable;
	int			main_step_fcc_dir;
	int			main_step_fcc_count;
	int			main_step_fcc_residual;
	int			parallel_step_fcc_dir;
	int			parallel_step_fcc_count;
	int			parallel_step_fcc_residual;
	int			step_fcc;
	u32			wa_flags;
	struct class		qcom_batt_class;
	struct wakeup_source	*pl_ws;
@@ -111,6 +123,7 @@ enum {
	SLAVE_PCT,
	RESTRICT_CHG_ENABLE,
	RESTRICT_CHG_CURRENT,
	FCC_STEPPING_IN_PROGRESS,
};

/*******
@@ -258,7 +271,6 @@ static void split_settled(struct pl_data *chip)

	chip->total_settled_ua = total_settled_ua;
	chip->pl_settled_ua = slave_ua;

}

static ssize_t version_show(struct class *c, struct class_attribute *attr,
@@ -378,11 +390,26 @@ static ssize_t restrict_cur_store(struct class *c, struct class_attribute *attr,
}
static CLASS_ATTR_RW(restrict_cur);

/****************************
 * FCC STEPPING IN PROGRESS *
 ****************************/
static ssize_t fcc_stepping_in_progress_show(struct class *c,
				struct class_attribute *attr, char *ubuf)
{
	struct pl_data *chip = container_of(c, struct pl_data,
			qcom_batt_class);

	return snprintf(ubuf, PAGE_SIZE, "%d\n", chip->step_fcc);
}
static CLASS_ATTR_RO(fcc_stepping_in_progress);

static struct attribute *batt_class_attrs[] = {
	[VER]			= &class_attr_version.attr,
	[SLAVE_PCT]		= &class_attr_slave_pct.attr,
	[RESTRICT_CHG_ENABLE]	= &class_attr_restrict_chg.attr,
	[RESTRICT_CHG_CURRENT]	= &class_attr_restrict_cur.attr,
	[FCC_STEPPING_IN_PROGRESS]
				= &class_attr_fcc_stepping_in_progress.attr,
	NULL,
};
ATTRIBUTE_GROUPS(batt_class);
@@ -391,6 +418,10 @@ ATTRIBUTE_GROUPS(batt_class);
 *  FCC  *
 **********/
#define EFFICIENCY_PCT	80
#define FCC_STEP_SIZE_UA 100000
#define FCC_STEP_UPDATE_DELAY_MS 1000
#define STEP_UP 1
#define STEP_DOWN -1
static void get_fcc_split(struct pl_data *chip, int total_ua,
			int *master_ua, int *slave_ua)
{
@@ -443,6 +474,47 @@ static void get_fcc_split(struct pl_data *chip, int total_ua,
		*master_ua = max(0, total_ua - *slave_ua);
}

static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua,
			int parallel_fcc_ua)
{
	union power_supply_propval pval = {0, };
	int rc;

	/* Read current FCC of main charger */
	rc = power_supply_get_property(chip->main_psy,
		POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
	if (rc < 0) {
		pr_err("Couldn't get main charger current fcc, rc=%d\n", rc);
		return;
	}
	chip->main_fcc_ua = pval.intval;

	chip->main_step_fcc_dir = (main_fcc_ua > pval.intval) ?
				STEP_UP : STEP_DOWN;
	chip->main_step_fcc_count = abs((main_fcc_ua - pval.intval) /
				FCC_STEP_SIZE_UA);
	chip->main_step_fcc_residual = (main_fcc_ua - pval.intval) %
				FCC_STEP_SIZE_UA;

	chip->parallel_step_fcc_dir = (parallel_fcc_ua > chip->slave_fcc_ua) ?
				STEP_UP : STEP_DOWN;
	chip->parallel_step_fcc_count = abs((parallel_fcc_ua -
				chip->slave_fcc_ua) / FCC_STEP_SIZE_UA);
	chip->parallel_step_fcc_residual = (parallel_fcc_ua -
				chip->slave_fcc_ua) % FCC_STEP_SIZE_UA;

	if (chip->parallel_step_fcc_count || chip->parallel_step_fcc_residual
		|| chip->main_step_fcc_count || chip->main_step_fcc_residual)
		chip->step_fcc = 1;

	pr_debug("Main FCC Stepper parameters: main_step_direction: %d, main_step_count: %d, main_residual_fcc: %d\n",
		chip->main_step_fcc_dir, chip->main_step_fcc_count,
		chip->main_step_fcc_residual);
	pr_debug("Parallel FCC Stepper parameters: parallel_step_direction: %d, parallel_step_count: %d, parallel_residual_fcc: %d\n",
		chip->parallel_step_fcc_dir, chip->parallel_step_fcc_count,
		chip->parallel_step_fcc_residual);
}

#define MINIMUM_PARALLEL_FCC_UA		500000
#define PL_TAPER_WORK_DELAY_MS		500
#define TAPER_RESIDUAL_PCT		90
@@ -562,6 +634,195 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
	return 0;
}

static void fcc_stepper_work(struct work_struct *work)
{
	struct pl_data *chip = container_of(work, struct pl_data,
			fcc_stepper_work.work);
	union power_supply_propval pval = {0, };
	int reschedule_ms = 0, rc = 0, charger_present = 0;
	int main_fcc = chip->main_fcc_ua;
	int parallel_fcc = chip->slave_fcc_ua;

	/* Check whether USB is present or not */
	rc = power_supply_get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_PRESENT, &pval);
	if (rc < 0)
		pr_err("Couldn't get USB Present status, rc=%d\n", rc);

	charger_present = pval.intval;

	/*Check whether DC charger is present or not */
	if (!chip->dc_psy)
		chip->dc_psy = power_supply_get_by_name("dc");
	if (chip->dc_psy) {
		rc = power_supply_get_property(chip->dc_psy,
				POWER_SUPPLY_PROP_PRESENT, &pval);
		if (rc < 0)
			pr_err("Couldn't get DC Present status, rc=%d\n", rc);

		charger_present |= pval.intval;
	}

	/*
	 * If USB is not present, then set parallel FCC to min value and
	 * main FCC to the effective value of FCC votable and exit.
	 */
	if (!charger_present) {
		/* Disable parallel */
		parallel_fcc = 0;

		if (chip->pl_psy) {
			pval.intval = 1;
			rc = power_supply_set_property(chip->pl_psy,
				POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
			if (rc < 0) {
				pr_err("Couldn't change slave suspend state rc=%d\n",
					rc);
				goto out;
			}

			chip->pl_disable = true;
			power_supply_changed(chip->pl_psy);
		}

		main_fcc = get_effective_result_locked(chip->fcc_votable);
		pval.intval = main_fcc;
		rc = power_supply_set_property(chip->main_psy,
			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
		if (rc < 0) {
			pr_err("Couldn't set main charger fcc, rc=%d\n", rc);
			goto out;
		}

		goto stepper_exit;
	}

	if (chip->main_step_fcc_count) {
		main_fcc += (FCC_STEP_SIZE_UA * chip->main_step_fcc_dir);
		chip->main_step_fcc_count--;
		reschedule_ms = FCC_STEP_UPDATE_DELAY_MS;
	} else if (chip->main_step_fcc_residual) {
		main_fcc += chip->main_step_fcc_residual;
		chip->main_step_fcc_residual = 0;
	}

	if (chip->parallel_step_fcc_count) {
		parallel_fcc += (FCC_STEP_SIZE_UA *
			chip->parallel_step_fcc_dir);
		chip->parallel_step_fcc_count--;
		reschedule_ms = FCC_STEP_UPDATE_DELAY_MS;
	} else if (chip->parallel_step_fcc_residual) {
		parallel_fcc += chip->parallel_step_fcc_residual;
		chip->parallel_step_fcc_residual = 0;
	}

	if (parallel_fcc < chip->slave_fcc_ua) {
		/* Set parallel FCC */
		if (chip->pl_psy && !chip->pl_disable) {
			if (parallel_fcc < MINIMUM_PARALLEL_FCC_UA) {
				pval.intval = 1;
				rc = power_supply_set_property(chip->pl_psy,
					POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
				if (rc < 0) {
					pr_err("Couldn't change slave suspend state rc=%d\n",
						rc);
					goto out;
				}

				if (IS_USBIN(chip->pl_mode))
					split_settled(chip);

				parallel_fcc = 0;
				chip->parallel_step_fcc_count = 0;
				chip->parallel_step_fcc_residual = 0;
				chip->total_settled_ua = 0;
				chip->pl_settled_ua = 0;
				chip->pl_disable = true;
				power_supply_changed(chip->pl_psy);
			} else {
				/* Set Parallel FCC */
				pval.intval = parallel_fcc;
				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 charger fcc, rc=%d\n",
						rc);
					goto out;
				}
			}
		}

		/* Set main FCC */
		pval.intval = main_fcc;
		rc = power_supply_set_property(chip->main_psy,
			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
		if (rc < 0) {
			pr_err("Couldn't set main charger fcc, rc=%d\n", rc);
			goto out;
		}
	} else {
		/* Set main FCC */
		pval.intval = main_fcc;
		rc = power_supply_set_property(chip->main_psy,
			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
		if (rc < 0) {
			pr_err("Couldn't set main charger fcc, rc=%d\n", rc);
			goto out;
		}

		/* Set parallel FCC */
		if (chip->pl_psy) {
			pval.intval = parallel_fcc;
			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 charger fcc, rc=%d\n",
					rc);
				goto out;
			}

			/*
			 * Enable parallel charger only if it was disabled
			 * earlier and configured slave fcc is greater than or
			 * equal to minimum parallel FCC value.
			 */
			if (chip->pl_disable && parallel_fcc
					>= MINIMUM_PARALLEL_FCC_UA) {
				pval.intval = 0;
				rc = power_supply_set_property(chip->pl_psy,
					POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
				if (rc < 0) {
					pr_err("Couldn't change slave suspend state rc=%d\n",
						rc);
					goto out;
				}

				if (IS_USBIN(chip->pl_mode))
					split_settled(chip);

				chip->pl_disable = false;
				power_supply_changed(chip->pl_psy);
			}
		}
	}

stepper_exit:
	chip->main_fcc_ua = main_fcc;
	chip->slave_fcc_ua = parallel_fcc;

	if (reschedule_ms) {
		schedule_delayed_work(&chip->fcc_stepper_work,
				msecs_to_jiffies(reschedule_ms));
		pr_debug("Rescheduling FCC_STEPPER work\n");
		return;
	}
out:
	chip->step_fcc = 0;
	vote(chip->pl_awake_votable, FCC_STEPPER_VOTER, false, 0);
}

#define PARALLEL_FLOAT_VOLTAGE_DELTA_UV 50000
static int pl_fv_vote_callback(struct votable *votable, void *data,
			int fv_uv, const char *client)
@@ -700,6 +961,17 @@ static bool is_main_available(struct pl_data *chip)
	return !!chip->main_psy;
}

static bool is_batt_available(struct pl_data *chip)
{
	if (!chip->batt_psy)
		chip->batt_psy = power_supply_get_by_name("battery");

	if (!chip->batt_psy)
		return false;

	return true;
}

static int pl_disable_vote_callback(struct votable *votable,
		void *data, int pl_disable, const char *client)
{
@@ -712,6 +984,28 @@ static int pl_disable_vote_callback(struct votable *votable,
	if (!is_main_available(chip))
		return -ENODEV;

	if (!is_batt_available(chip))
		return -ENODEV;

	if (!chip->usb_psy)
		chip->usb_psy = power_supply_get_by_name("usb");
	if (!chip->usb_psy) {
		pr_err("Couldn't get usb psy\n");
		return -ENODEV;
	}

	rc = power_supply_get_property(chip->batt_psy,
			POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE, &pval);
	if (rc < 0) {
		pr_err("Couldn't read FCC step update status, rc=%d\n", rc);
		return rc;
	}
	chip->fcc_stepper_enable = pval.intval;
	pr_debug("FCC Stepper %s\n", pval.intval ? "enabled" : "disabled");

	if (chip->fcc_stepper_enable)
		cancel_delayed_work_sync(&chip->fcc_stepper_work);

	total_fcc_ua = get_effective_result_locked(chip->fcc_votable);

	if (chip->pl_mode != POWER_SUPPLY_PL_NONE && !pl_disable) {
@@ -747,6 +1041,15 @@ static int pl_disable_vote_callback(struct votable *votable,
		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
				&slave_fcc_ua);

		if (chip->fcc_stepper_enable) {
			vote(chip->pl_awake_votable, FCC_STEPPER_VOTER,
					true, 0);
			get_fcc_stepper_params(chip, master_fcc_ua,
					slave_fcc_ua);
			if (chip->step_fcc)
				schedule_delayed_work(&chip->fcc_stepper_work,
					0);
		} else {
			/*
			 * If there is an increase in slave share
			 * (Also handles parallel enable case)
@@ -761,7 +1064,8 @@ static int pl_disable_vote_callback(struct votable *votable,
				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
					&pval);
				if (rc < 0) {
				pr_err("Could not set main fcc, rc=%d\n", rc);
					pr_err("Could not set main fcc, rc=%d\n",
						rc);
					return rc;
				}

@@ -794,7 +1098,8 @@ static int pl_disable_vote_callback(struct votable *votable,
				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
					&pval);
				if (rc < 0) {
				pr_err("Could not set main fcc, rc=%d\n", rc);
					pr_err("Could not set main fcc, rc=%d\n",
						rc);
					return rc;
				}
			}
@@ -813,6 +1118,8 @@ static int pl_disable_vote_callback(struct votable *votable,

			if (IS_USBIN(chip->pl_mode))
				split_settled(chip);
		}

		/*
		 * we could have been enabled while in taper mode,
		 *  start the taper work if so
@@ -838,6 +1145,7 @@ static int pl_disable_vote_callback(struct votable *votable,
			(master_fcc_ua * 100) / total_fcc_ua,
			(slave_fcc_ua * 100) / total_fcc_ua);
	} else {
		if (!chip->fcc_stepper_enable) {
			if (IS_USBIN(chip->pl_mode))
				split_settled(chip);

@@ -863,18 +1171,27 @@ static int pl_disable_vote_callback(struct votable *votable,

			/* reset parallel FCC */
			chip->slave_fcc_ua = 0;
			chip->total_settled_ua = 0;
			chip->pl_settled_ua = 0;
		} else {
			vote(chip->pl_awake_votable, FCC_STEPPER_VOTER,
					true, 0);
			get_fcc_stepper_params(chip, total_fcc_ua, 0);
			if (chip->step_fcc)
				schedule_delayed_work(&chip->fcc_stepper_work,
					0);
		}

		rerun_election(chip->fv_votable);

		cancel_delayed_work_sync(&chip->pl_awake_work);
		schedule_delayed_work(&chip->pl_awake_work,
						msecs_to_jiffies(5000));

		chip->total_settled_ua = 0;
		chip->pl_settled_ua = 0;
	}

	/* notify parallel state change */
	if (chip->pl_psy && (chip->pl_disable != pl_disable)) {
	if (chip->pl_psy && (chip->pl_disable != pl_disable)
				&& !chip->fcc_stepper_enable) {
		power_supply_changed(chip->pl_psy);
		chip->pl_disable = (bool)pl_disable;
	}
@@ -909,17 +1226,6 @@ static int pl_awake_vote_callback(struct votable *votable,
	return 0;
}

static bool is_batt_available(struct pl_data *chip)
{
	if (!chip->batt_psy)
		chip->batt_psy = power_supply_get_by_name("battery");

	if (!chip->batt_psy)
		return false;

	return true;
}

static bool is_parallel_available(struct pl_data *chip)
{
	union power_supply_propval pval = {0, };
@@ -1083,6 +1389,7 @@ static void handle_settled_icl_change(struct pl_data *chip)
	else
		vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0);

	rerun_election(chip->fcc_votable);

	if (IS_USBIN(chip->pl_mode)) {
		/*
@@ -1331,6 +1638,7 @@ int qcom_batt_init(int smb_version)
	INIT_WORK(&chip->pl_taper_work, pl_taper_work);
	INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work);
	INIT_DELAYED_WORK(&chip->pl_awake_work, pl_awake_work);
	INIT_DELAYED_WORK(&chip->fcc_stepper_work, fcc_stepper_work);

	rc = pl_register_notifier(chip);
	if (rc < 0) {
@@ -1386,6 +1694,7 @@ void qcom_batt_deinit(void)
	cancel_work_sync(&chip->pl_taper_work);
	cancel_work_sync(&chip->pl_disable_forever_work);
	cancel_delayed_work_sync(&chip->pl_awake_work);
	cancel_delayed_work_sync(&chip->fcc_stepper_work);

	power_supply_unreg_notifier(&chip->nb);
	destroy_votable(chip->pl_enable_votable_indirect);
+6 −0
Original line number Diff line number Diff line
@@ -440,6 +440,9 @@ static int smb5_parse_dt(struct smb5 *chip)
	if (rc < 0)
		chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;

	chg->fcc_stepper_enable = of_property_read_bool(node,
					"qcom,fcc-stepping-enable");

	rc = of_property_match_string(node, "io-channel-names",
			"usb_in_voltage");
	if (rc >= 0) {
@@ -1176,6 +1179,7 @@ static enum power_supply_property smb5_batt_props[] = {
	POWER_SUPPLY_PROP_RECHARGE_SOC,
	POWER_SUPPLY_PROP_CHARGE_FULL,
	POWER_SUPPLY_PROP_FORCE_RECHARGE,
	POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
};

static int smb5_batt_get_prop(struct power_supply *psy,
@@ -1293,6 +1297,8 @@ static int smb5_batt_get_prop(struct power_supply *psy,
		break;
	case POWER_SUPPLY_PROP_FORCE_RECHARGE:
		val->intval = 0;
	case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE:
		val->intval = chg->fcc_stepper_enable;
		break;
	default:
		pr_err("batt power supply prop %d not supported\n", psp);
Loading