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

Commit 9d87447b authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy Committed by Gerrit - the friendly Code Review server
Browse files

power: qpnp-smbcharger: improve handling USB insertion/removal



Currently, we handle the USB insertion through source detect
(SRC_DET) interrupt and USB removal through undervolt (UV)
interrupt.

In certain cases where the VBUS drops less than 5V (say 4.4 V)
and VBAT is at 4.3 V, PHY disconnects. It will never get
reasserted since the VBUS doesn't drop below 1V and goes
back to 5V.

To handle such corner cases, handle the USB removal for
DCP/HVDCP on the falling edge of UV interrupt and on the
falling edge of SRC_DET interrupt for CDP/SDP. Handle
the USB insertion on the rising edge of SRC_DET interrupt.

CRs-Fixed: 794058
Change-Id: Ied5f1016d1dfe040902224fca2b30a580a4dad88
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent adb479c0
Loading
Loading
Loading
Loading
+55 −10
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ static enum pwr_path_type smbchg_get_pwr_path(struct smbchg_chip *chip)
#define USBID_MSB			0xE
#define USBIN_UV_BIT			BIT(0)
#define USBIN_OV_BIT			BIT(1)
#define USBIN_SRC_DET_BIT		BIT(2)
#define FMB_STS_MASK			SMB_MASK(3, 0)
#define USBID_GND_THRESHOLD		0x495
static bool is_otg_present(struct smbchg_chip *chip)
@@ -3727,40 +3728,84 @@ out:
 */
static irqreturn_t usbin_uv_handler(int irq, void *_chip)
{
	int rc;
	u8 reg;
	union power_supply_propval prop = {0, };
	struct smbchg_chip *chip = _chip;
	bool usb_present = is_usb_present(chip);

	pr_smb(PR_STATUS, "chip->usb_present = %d usb_present = %d\n",
			chip->usb_present, usb_present);

	rc = smbchg_read(chip, &reg, chip->usb_chgpth_base + RT_STS, 1);
	if (rc < 0) {
		dev_err(chip->dev, "Couldn't read usb rt status rc = %d\n", rc);
		goto out;
	}
	reg &= USBIN_UV_BIT;

	if (reg && chip->usb_psy && !chip->usb_psy->get_property(chip->usb_psy,
							POWER_SUPPLY_PROP_TYPE,
							&prop)) {
		if ((prop.intval == POWER_SUPPLY_TYPE_USB_HVDCP) ||
			(prop.intval == POWER_SUPPLY_TYPE_USB_DCP)) {
			if (chip->usb_present && !usb_present) {
		/* USB removed */
				/* DCP or HVDCP removed */
				chip->usb_present = usb_present;
				handle_usb_removal(chip);
			}
		}
	}
	smbchg_wipower_check(chip);
out:
	return IRQ_HANDLED;
}

/**
 * src_detect_handler() - this is called when USB charger type is detected, use
 *			it for handling USB charger insertion
 * src_detect_handler() - this is called on rising edge when USB charger type
 *			is detected and on falling edge when USB voltage falls
 *			below the coarse detect voltage(1V), use it for
 *			handling USB charger insertion and CDP or SDP removal
 * @chip: pointer to smbchg_chip
 * @rt_stat: the status bit indicating chg insertion/removal
 */
static irqreturn_t src_detect_handler(int irq, void *_chip)
{
	int rc;
	u8 reg;
	union power_supply_propval prop = {0, };
	struct smbchg_chip *chip = _chip;
	bool usb_present = is_usb_present(chip);

	pr_smb(PR_STATUS, "chip->usb_present = %d usb_present = %d\n",
			chip->usb_present, usb_present);

	rc = smbchg_read(chip, &reg, chip->usb_chgpth_base + RT_STS, 1);
	if (rc < 0) {
		dev_err(chip->dev, "Couldn't read usb rt status rc = %d\n", rc);
		goto out;
	}
	reg &= USBIN_SRC_DET_BIT;

	if (reg) {
		if (!chip->usb_present && usb_present) {
			/* USB inserted */
			chip->usb_present = usb_present;
			handle_usb_insertion(chip);
		}
	} else if (chip->usb_psy && !chip->usb_psy->get_property(chip->usb_psy,
							POWER_SUPPLY_PROP_TYPE,
							&prop)) {
		if (((prop.intval == POWER_SUPPLY_TYPE_USB_CDP) ||
			(prop.intval == POWER_SUPPLY_TYPE_USB)) &&
			chip->usb_present) {
				/* CDP or SDP removed */
				chip->usb_present = !chip->usb_present;
				handle_usb_removal(chip);
		}
	}

out:
	return IRQ_HANDLED;
}