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

Commit 3c10c331 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: step-chg-jeita: update JEITA float voltage compensation"

parents 1f886ea2 d7a53157
Loading
Loading
Loading
Loading
+75 −20
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
@@ -79,10 +79,12 @@ struct step_chg_info {

	struct votable		*fcc_votable;
	struct votable		*fv_votable;
	struct votable		*usb_icl_votable;
	struct wakeup_source	*step_chg_ws;
	struct power_supply	*batt_psy;
	struct power_supply	*bms_psy;
	struct power_supply	*main_psy;
	struct power_supply	*usb_psy;
	struct delayed_work	status_change_work;
	struct delayed_work	get_config_work;
	struct notifier_block	nb;
@@ -119,6 +121,17 @@ static bool is_bms_available(struct step_chg_info *chip)
	return true;
}

static bool is_usb_available(struct step_chg_info *chip)
{
	if (!chip->usb_psy)
		chip->usb_psy = power_supply_get_by_name("usb");

	if (!chip->usb_psy)
		return false;

	return true;
}

static int read_range_data_from_node(struct device_node *node,
		const char *prop_str, struct range_data *ranges,
		u32 max_threshold, u32 max_value)
@@ -486,6 +499,7 @@ static int handle_step_chg_config(struct step_chg_info *chip)
	return (STEP_CHG_HYSTERISIS_DELAY_US - elapsed_us + 1000);
}

#define JEITA_SUSPEND_HYST_UV		50000
static int handle_jeita(struct step_chg_info *chip)
{
	union power_supply_propval pval = {0, };
@@ -504,6 +518,8 @@ static int handle_jeita(struct step_chg_info *chip)
			vote(chip->fcc_votable, JEITA_VOTER, false, 0);
		if (chip->fv_votable)
			vote(chip->fv_votable, JEITA_VOTER, false, 0);
		if (chip->usb_icl_votable)
			vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
		return 0;
	}

@@ -525,12 +541,8 @@ static int handle_jeita(struct step_chg_info *chip)
			pval.intval,
			&chip->jeita_fcc_index,
			&fcc_ua);
	if (rc < 0) {
		/* remove the vote if no step-based fcc is found */
		if (chip->fcc_votable)
			vote(chip->fcc_votable, JEITA_VOTER, false, 0);
		goto update_time;
	}
	if (rc < 0)
		fcc_ua = 0;

	if (!chip->fcc_votable)
		chip->fcc_votable = find_votable("FCC");
@@ -538,7 +550,7 @@ static int handle_jeita(struct step_chg_info *chip)
		/* changing FCC is a must */
		return -EINVAL;

	vote(chip->fcc_votable, JEITA_VOTER, true, fcc_ua);
	vote(chip->fcc_votable, JEITA_VOTER, fcc_ua ? true : false, fcc_ua);

	rc = get_val(chip->jeita_fv_config->fv_cfg,
			chip->jeita_fv_config->hysteresis,
@@ -546,21 +558,45 @@ static int handle_jeita(struct step_chg_info *chip)
			pval.intval,
			&chip->jeita_fv_index,
			&fv_uv);
	if (rc < 0) {
		/* remove the vote if no step-based fcc is found */
		if (chip->fv_votable)
			vote(chip->fv_votable, JEITA_VOTER, false, 0);
		goto update_time;
	}
	if (rc < 0)
		fv_uv = 0;

	chip->fv_votable = find_votable("FV");
	if (!chip->fv_votable)
		goto update_time;

	vote(chip->fv_votable, JEITA_VOTER, true, fv_uv);
	if (!chip->usb_icl_votable)
		chip->usb_icl_votable = find_votable("USB_ICL");

	pr_debug("%s = %d FCC = %duA FV = %duV\n",
		chip->jeita_fcc_config->prop_name, pval.intval, fcc_ua, fv_uv);
	if (!chip->usb_icl_votable)
		goto set_jeita_fv;

	/*
	 * If JEITA float voltage is same as max-vfloat of battery then
	 * skip any further VBAT specific checks.
	 */
	rc = power_supply_get_property(chip->batt_psy,
				POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
	if (rc || (pval.intval == fv_uv)) {
		vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
		goto set_jeita_fv;
	}

	/*
	 * Suspend USB input path if battery voltage is above
	 * JEITA VFLOAT threshold.
	 */
	if (fv_uv > 0) {
		rc = power_supply_get_property(chip->batt_psy,
				POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
		if (!rc && (pval.intval > fv_uv))
			vote(chip->usb_icl_votable, JEITA_VOTER, true, 0);
		else if (pval.intval < (fv_uv - JEITA_SUSPEND_HYST_UV))
			vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
	}

set_jeita_fv:
	vote(chip->fv_votable, JEITA_VOTER, fv_uv ? true : false, fv_uv);

update_time:
	chip->jeita_last_update_time = ktime_get();
@@ -618,11 +654,13 @@ static void status_change_work(struct work_struct *work)
	int reschedule_us;
	int reschedule_jeita_work_us = 0;
	int reschedule_step_work_us = 0;
	union power_supply_propval prop = {0, };

	if (!is_batt_available(chip))
		return;
		goto exit_work;

	handle_battery_insertion(chip);

	/* skip elapsed_us debounce for handling battery temperature */
	rc = handle_jeita(chip);
	if (rc > 0)
@@ -636,12 +674,28 @@ static void status_change_work(struct work_struct *work)
	if (rc < 0)
		pr_err("Couldn't handle step rc = %d\n", rc);

	/* Remove stale votes on USB removal */
	if (is_usb_available(chip)) {
		prop.intval = 0;
		power_supply_get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_PRESENT, &prop);
		if (!prop.intval) {
			if (chip->usb_icl_votable)
				vote(chip->usb_icl_votable, JEITA_VOTER,
						false, 0);
		}
	}

	reschedule_us = min(reschedule_jeita_work_us, reschedule_step_work_us);
	if (reschedule_us == 0)
		__pm_relax(chip->step_chg_ws);
		goto exit_work;
	else
		schedule_delayed_work(&chip->status_change_work,
				usecs_to_jiffies(reschedule_us));
	return;

exit_work:
	__pm_relax(chip->step_chg_ws);
}

static int step_chg_notifier_call(struct notifier_block *nb,
@@ -653,7 +707,8 @@ static int step_chg_notifier_call(struct notifier_block *nb,
	if (ev != PSY_EVENT_PROP_CHANGED)
		return NOTIFY_OK;

	if ((strcmp(psy->desc->name, "battery") == 0)) {
	if ((strcmp(psy->desc->name, "battery") == 0)
			|| (strcmp(psy->desc->name, "usb") == 0)) {
		__pm_stay_awake(chip->step_chg_ws);
		schedule_delayed_work(&chip->status_change_work, 0);
	}