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

Commit e6e4152a authored by Xiaozhe Shi's avatar Xiaozhe Shi Committed by Abhijeet Dharmapurikar
Browse files

power: qpnp-smbcharger: limit enabling parallel charger frequently



Currently, whenever the charger driver receives an AICL done interrupt,
it will go and attempt to enable parallel charging if it's available.
However, this can create a loop where a charger cannot support parallel
charging with load, but upon disabling parallel charging, the AICL done
interrupt from the AICL tries to re-enable parallel charging.

Fix this by not allowing parallel charging to be re-enabled more than
once every 30 seconds.

CRs-Fixed: 815311
Change-Id: Id8f9aea3f3eefda4b50d3807f666bb11377b229e
Signed-off-by: default avatarXiaozhe Shi <xiaozhes@codeaurora.org>
parent dcc3b524
Loading
Loading
Loading
Loading
+17 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/batterydata-lib.h>
#include <linux/batterydata-lib.h>
#include <linux/of_batterydata.h>
#include <linux/of_batterydata.h>
#include <linux/msm_bcl.h>
#include <linux/msm_bcl.h>
#include <linux/ktime.h>


/* Mask/Bit helpers */
/* Mask/Bit helpers */
#define _SMB_MASK(BITS, POS) \
#define _SMB_MASK(BITS, POS) \
@@ -59,6 +60,8 @@ struct parallel_usb_cfg {
	bool				avail;
	bool				avail;
	struct mutex			lock;
	struct mutex			lock;
	int				initial_aicl_ma;
	int				initial_aicl_ma;
	ktime_t				last_disabled;
	bool				enabled_once;
};
};


struct ilim_entry {
struct ilim_entry {
@@ -1498,9 +1501,11 @@ static int smbchg_get_min_parallel_current_ma(struct smbchg_chip *chip)
#define USBIN_SUSPEND_STS_BIT		BIT(3)
#define USBIN_SUSPEND_STS_BIT		BIT(3)
#define USBIN_ACTIVE_PWR_SRC_BIT	BIT(1)
#define USBIN_ACTIVE_PWR_SRC_BIT	BIT(1)
#define DCIN_ACTIVE_PWR_SRC_BIT		BIT(0)
#define DCIN_ACTIVE_PWR_SRC_BIT		BIT(0)
#define PARALLEL_REENABLE_TIMER_MS	30000
static bool smbchg_is_parallel_usb_ok(struct smbchg_chip *chip)
static bool smbchg_is_parallel_usb_ok(struct smbchg_chip *chip)
{
{
	int min_current_thr_ma, rc, type;
	int min_current_thr_ma, rc, type;
	ktime_t kt_since_last_disable;
	u8 reg;
	u8 reg;


	if (!smbchg_parallel_en) {
	if (!smbchg_parallel_en) {
@@ -1508,6 +1513,15 @@ static bool smbchg_is_parallel_usb_ok(struct smbchg_chip *chip)
		return false;
		return false;
	}
	}


	kt_since_last_disable = ktime_sub(ktime_get_boottime(),
					chip->parallel.last_disabled);
	if (chip->parallel.enabled_once && ktime_to_ms(kt_since_last_disable)
					< PARALLEL_REENABLE_TIMER_MS) {
		pr_smb(PR_STATUS, "Only been %lld since disable, skipping\n",
				ktime_to_ms(kt_since_last_disable));
		return false;
	}

	if (get_prop_charge_type(chip) != POWER_SUPPLY_CHARGE_TYPE_FAST) {
	if (get_prop_charge_type(chip) != POWER_SUPPLY_CHARGE_TYPE_FAST) {
		pr_smb(PR_STATUS, "Not in fast charge, skipping\n");
		pr_smb(PR_STATUS, "Not in fast charge, skipping\n");
		return false;
		return false;
@@ -1692,6 +1706,7 @@ static void smbchg_parallel_usb_disable(struct smbchg_chip *chip)
	if (!parallel_psy)
	if (!parallel_psy)
		return;
		return;
	pr_smb(PR_STATUS, "disabling parallel charger\n");
	pr_smb(PR_STATUS, "disabling parallel charger\n");
	chip->parallel.last_disabled = ktime_get_boottime();
	taper_irq_en(chip, false);
	taper_irq_en(chip, false);
	chip->parallel.initial_aicl_ma = 0;
	chip->parallel.initial_aicl_ma = 0;
	chip->parallel.current_max_ma = 0;
	chip->parallel.current_max_ma = 0;
@@ -1880,6 +1895,7 @@ static void smbchg_parallel_usb_enable(struct smbchg_chip *chip)
	parallel_psy->set_property(parallel_psy,
	parallel_psy->set_property(parallel_psy,
			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);


	chip->parallel.enabled_once = true;
	new_parallel_cl_ma = total_current_ma / 2;
	new_parallel_cl_ma = total_current_ma / 2;


	if (new_parallel_cl_ma == parallel_cl_ma) {
	if (new_parallel_cl_ma == parallel_cl_ma) {
@@ -4216,6 +4232,7 @@ static void handle_usb_removal(struct smbchg_chip *chip)
		disable_irq_wake(chip->aicl_done_irq);
		disable_irq_wake(chip->aicl_done_irq);
		chip->enable_aicl_wake = false;
		chip->enable_aicl_wake = false;
	}
	}
	chip->parallel.enabled_once = false;
	chip->vbat_above_headroom = false;
	chip->vbat_above_headroom = false;
}
}