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

Commit 8fcfe088 authored by Chanwoo Choi's avatar Chanwoo Choi Committed by Anton Vorontsov
Browse files

charger-manager: Support limit of maximum possible



This patch check maximum possible duration of charging/discharging.

If whole charging duration exceed 'desc->charging_max_duration_ms', cm
stop charging to prevent overcharge/overheat. And if discharging duration
exceed, charger cable is attached, after full-batt, cm start charging to
maintain fully charged state for battery.

Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: default avatarMyungjoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarAnton Vorontsov <anton.vorontsov@linaro.org>
parent 2ed9e9b6
Loading
Loading
Loading
Loading
+79 −1
Original line number Diff line number Diff line
@@ -323,6 +323,14 @@ static int try_charger_enable(struct charger_manager *cm, bool enable)
	if (enable) {
		if (cm->emergency_stop)
			return -EAGAIN;

		/*
		 * Save start time of charging to limit
		 * maximum possible charging time.
		 */
		cm->charging_start_time = ktime_to_ms(ktime_get());
		cm->charging_end_time = 0;

		for (i = 0 ; i < desc->num_charger_regulators ; i++) {
			err = regulator_enable(desc->charger_regulators[i].consumer);
			if (err < 0) {
@@ -332,6 +340,13 @@ static int try_charger_enable(struct charger_manager *cm, bool enable)
			}
		}
	} else {
		/*
		 * Save end time of charging to maintain fully charged state
		 * of battery after full-batt.
		 */
		cm->charging_start_time = 0;
		cm->charging_end_time = ktime_to_ms(ktime_get());

		for (i = 0 ; i < desc->num_charger_regulators ; i++) {
			err = regulator_disable(desc->charger_regulators[i].consumer);
			if (err < 0) {
@@ -474,8 +489,55 @@ static void fullbatt_vchk(struct work_struct *work)

	if (diff > desc->fullbatt_vchkdrop_uV) {
		try_charger_restart(cm);
		uevent_notify(cm, "Recharge");
		uevent_notify(cm, "Recharging");
	}
}

/**
 * check_charging_duration - Monitor charging/discharging duration
 * @cm: the Charger Manager representing the battery.
 *
 * If whole charging duration exceed 'charging_max_duration_ms',
 * cm stop charging to prevent overcharge/overheat. If discharging
 * duration exceed 'discharging _max_duration_ms', charger cable is
 * attached, after full-batt, cm start charging to maintain fully
 * charged state for battery.
 */
static int check_charging_duration(struct charger_manager *cm)
{
	struct charger_desc *desc = cm->desc;
	u64 curr = ktime_to_ms(ktime_get());
	u64 duration;
	int ret = false;

	if (!desc->charging_max_duration_ms &&
			!desc->discharging_max_duration_ms)
		return ret;

	if (cm->charger_enabled) {
		duration = curr - cm->charging_start_time;

		if (duration > desc->charging_max_duration_ms) {
			dev_info(cm->dev, "Charging duration exceed %lldms",
				 desc->charging_max_duration_ms);
			uevent_notify(cm, "Discharging");
			try_charger_enable(cm, false);
			ret = true;
		}
	} else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
		duration = curr - cm->charging_end_time;

		if (duration > desc->charging_max_duration_ms &&
				is_ext_pwr_online(cm)) {
			dev_info(cm->dev, "DisCharging duration exceed %lldms",
				 desc->discharging_max_duration_ms);
			uevent_notify(cm, "Recharing");
			try_charger_enable(cm, true);
			ret = true;
		}
	}

	return ret;
}

/**
@@ -510,6 +572,13 @@ static bool _cm_monitor(struct charger_manager *cm)
				uevent_notify(cm, "COLD");
		}

	/*
	 * Check whole charging duration and discharing duration
	 * after full-batt.
	 */
	} else if (!cm->emergency_stop && check_charging_duration(cm)) {
		dev_dbg(cm->dev,
			"Charging/Discharging duration is out of range");
	/*
	 * Check dropped voltage of battery. If battery voltage is more
	 * dropped than fullbatt_vchkdrop_uV after fully charged state,
@@ -1271,6 +1340,15 @@ static int charger_manager_probe(struct platform_device *pdev)
		goto err_chg_stat;
	}

	if (!desc->charging_max_duration_ms ||
			!desc->discharging_max_duration_ms) {
		dev_info(&pdev->dev, "Cannot limit charging duration "
			 "checking mechanism to prevent overcharge/overheat "
			 "and control discharging duration");
		desc->charging_max_duration_ms = 0;
		desc->discharging_max_duration_ms = 0;
	}

	platform_set_drvdata(pdev, cm);

	memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
+15 −0
Original line number Diff line number Diff line
@@ -162,6 +162,13 @@ struct charger_regulator {
 * @measure_battery_temp:
 *	true: measure battery temperature
 *	false: measure ambient temperature
 * @charging_max_duration_ms: Maximum possible duration for charging
 *	If whole charging duration exceed 'charging_max_duration_ms',
 *	cm stop charging.
 * @discharging_max_duration_ms:
 *	Maximum possible duration for discharging with charger cable
 *	after full-batt. If discharging duration exceed 'discharging
 *	max_duration_ms', cm start charging.
 */
struct charger_desc {
	char *psy_name;
@@ -186,6 +193,9 @@ struct charger_desc {

	int (*temperature_out_of_range)(int *mC);
	bool measure_battery_temp;

	u64 charging_max_duration_ms;
	u64 discharging_max_duration_ms;
};

#define PSY_NAME_MAX	30
@@ -210,6 +220,8 @@ struct charger_desc {
 *	saved status of external power before entering suspend-to-RAM
 * @status_save_batt:
 *	saved status of battery before entering suspend-to-RAM
 * @charging_start_time: saved start time of enabling charging
 * @charging_end_time: saved end time of disabling charging
 */
struct charger_manager {
	struct list_head entry;
@@ -232,6 +244,9 @@ struct charger_manager {

	bool status_save_ext_pwr_inserted;
	bool status_save_batt;

	u64 charging_start_time;
	u64 charging_end_time;
};

#ifdef CONFIG_CHARGER_MANAGER