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

Commit 725a596a authored by Anirudh Ghayal's avatar Anirudh Ghayal
Browse files

power: smb135x-charger: Handle delay in src_detect state change



The SMB hardware does not generate an interrupt on the falling
edge of src_detect, there is only a change in its real-time
status which is detected by the driver while handling the usbin_uv
irq.  This can be a problem when the USB input voltage
drops slowly and software is unable to detect the falling-edge of
src_detect, thus failing to detect a USB removal.

Handle this by periodically checking for the src_detect falling
event after receiving the usbin_uv irq.

CRs-Fixed: 1077297
Change-Id: I6ec27cbf5efd07181df2f7a4c5af84f0e96724f2
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent f762adc5
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -403,6 +403,8 @@ struct smb135x_chg {
	bool				resume_completed;
	bool				irq_waiting;
	bool				device_suspended;
	bool				usbin_uv;
	u32				src_detect_low_tries;
	u32				usb_suspended;
	u32				dc_suspended;
	struct mutex			path_suspend_lock;
@@ -418,6 +420,7 @@ struct smb135x_chg {
	struct regulator		*therm_bias_vreg;
	struct regulator		*usb_pullup_vreg;
	struct delayed_work		wireless_insertion_work;
	struct delayed_work		src_detect_low_work;

	unsigned int			thermal_levels;
	unsigned int			therm_lvl_sel;
@@ -439,6 +442,8 @@ int retry_sleep_ms[RETRY_COUNT] = {
	10, 20, 30, 40, 50
};

static irqreturn_t smb135x_chg_stat_handler(int irq, void *dev_id);

static void smb135x_stay_awake(struct smb135x_chg *chip)
{
	if (chip->device_suspended)
@@ -2854,6 +2859,39 @@ static int handle_usb_insertion(struct smb135x_chg *chip)
	return 0;
}

#define SRC_DETECT_LOW_DELAY_MS		msecs_to_jiffies(200)
#define SRC_DETECT_LOW_TRIES		20
static void src_detect_check_work(struct work_struct *work)
{
	struct smb135x_chg *chip = container_of(work,
			struct smb135x_chg, src_detect_low_work.work);

	pr_debug("usb_present=%d usbin_uv=%d src_det_tries=%d\n",
			chip->usb_present, chip->usbin_uv,
			chip->src_detect_low_tries);

	if (!chip->usb_present || !chip->usbin_uv) {
		/*
		 * either src_detect was detected or USB voltage
		 * recovered after a UV.
		 */
		smb135x_relax(chip);
		return;
	}

	smb135x_chg_stat_handler(chip->client->irq, chip);

	/* reschedule the work if usb is still present */
	if (chip->usb_present &&
			chip->src_detect_low_tries < SRC_DETECT_LOW_TRIES) {
		chip->src_detect_low_tries++;
		schedule_delayed_work(&chip->src_detect_low_work,
					SRC_DETECT_LOW_DELAY_MS);
	} else {
		smb135x_relax(chip);
	}
}

/**
 * usbin_uv_handler()
 * @chip: pointer to smb135x_chg chip
@@ -2867,9 +2905,16 @@ static int usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat)
	bool usb_present = !rt_stat;

	if (usb_present) {
		chip->usbin_uv = false;
		pr_debug("Set usb psy dp=f dm=f\n");
		power_supply_set_dp_dm(chip->usb_psy,
				POWER_SUPPLY_DP_DM_DPF_DMF);
	} else {
		chip->usbin_uv = true;
		chip->src_detect_low_tries = 0;
		smb135x_stay_awake(chip);
		schedule_delayed_work(&chip->src_detect_low_work,
					SRC_DETECT_LOW_DELAY_MS);
	}

	pr_debug("chip->usb_present = %d usb_present = %d\n",
@@ -4230,6 +4275,7 @@ static int smb135x_main_charger_probe(struct i2c_client *client,
	INIT_DELAYED_WORK(&chip->reset_otg_oc_count_work,
					reset_otg_oc_count_work);
	INIT_DELAYED_WORK(&chip->hvdcp_det_work, smb135x_hvdcp_det_work);
	INIT_DELAYED_WORK(&chip->src_detect_low_work, src_detect_check_work);
	mutex_init(&chip->path_suspend_lock);
	mutex_init(&chip->current_change_lock);
	mutex_init(&chip->read_write_lock);