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

Commit 1bf41339 authored by Ashay Jaiswal's avatar Ashay Jaiswal Committed by Harry Yang
Browse files

qpnp-smb2: Add software based glitch filter for OTG detection



When the USB_ID line is pulled low for a very short time there is a
possibility that the SW misses rising edge(removal) event. This may
lead to the state where charger is stuck in the boost-mode forever.

Fix this my adding a SW based glitch logic which checks for the
USB_ID after a SW debounce time and then notifies its presence/removal to
the USB driver.

CRs-Fixed: 2044958
Change-Id: I31974f7d68b435bbef329278cedbd726ada02e3f
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
parent 85d3a5a0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -176,6 +176,12 @@ Charger specific properties:
  Definition: Specifies the maximum charger buck/boost switching frequency in
		 KHz. It overrides the max frequency defined for the charger.

- qcom,otg-deglitch-time-ms
  Usage:      optional
  Value type: <u32>
  Definition: Specifies the deglitch interval for OTG detection.
		If the value is not present, 50 msec is used as default.

=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
+9 −2
Original line number Diff line number Diff line
@@ -268,6 +268,7 @@ module_param_named(

#define MICRO_1P5A		1500000
#define MICRO_P1A		100000
#define OTG_DEFAULT_DEGLITCH_TIME_MS	50
static int smb2_parse_dt(struct smb2 *chip)
{
	struct smb_charger *chg = &chip->chg;
@@ -397,6 +398,12 @@ static int smb2_parse_dt(struct smb2 *chip)

	chg->suspend_input_on_debug_batt = of_property_read_bool(node,
					"qcom,suspend-input-on-debug-batt");

	rc = of_property_read_u32(node, "qcom,otg-deglitch-time-ms",
					&chg->otg_delay_ms);
	if (rc < 0)
		chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;

	return 0;
}

+31 −21
Original line number Diff line number Diff line
@@ -3730,26 +3730,6 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
		   smblib_typec_mode_name[pval.intval]);
}

irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg)
{
	int rc;
	u8 stat;

	rc = smblib_read(chg, TYPE_C_STATUS_3_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
		return IRQ_HANDLED;
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
		stat, !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));

	extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST,
			!!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
	power_supply_changed(chg->usb_psy);

	return IRQ_HANDLED;
}

static void smblib_usb_typec_change(struct smb_charger *chg)
{
	int rc;
@@ -3784,7 +3764,11 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
	struct smb_charger *chg = irq_data->parent_data;

	if (chg->micro_usb_mode) {
		smblib_handle_usb_typec_change_for_uusb(chg);
		cancel_delayed_work_sync(&chg->uusb_otg_work);
		vote(chg->awake_votable, OTG_DELAY_VOTER, true, 0);
		smblib_dbg(chg, PR_INTERRUPT, "Scheduling OTG work\n");
		schedule_delayed_work(&chg->uusb_otg_work,
				msecs_to_jiffies(chg->otg_delay_ms));
		return IRQ_HANDLED;
	}

@@ -3869,6 +3853,30 @@ irqreturn_t smblib_handle_wdog_bark(int irq, void *data)
/***************
 * Work Queues *
 ***************/
static void smblib_uusb_otg_work(struct work_struct *work)
{
	struct smb_charger *chg = container_of(work, struct smb_charger,
						uusb_otg_work.work);
	int rc;
	u8 stat;
	bool otg;

	rc = smblib_read(chg, TYPE_C_STATUS_3_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
		goto out;
	}

	otg = !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT));
	extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST, otg);
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
			stat, otg);
	power_supply_changed(chg->usb_psy);

out:
	vote(chg->awake_votable, OTG_DELAY_VOTER, false, 0);
}


static void smblib_hvdcp_detect_work(struct work_struct *work)
{
@@ -4450,6 +4458,7 @@ int smblib_init(struct smb_charger *chg)
	INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
	INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
	INIT_WORK(&chg->legacy_detection_work, smblib_legacy_detection_work);
	INIT_DELAYED_WORK(&chg->uusb_otg_work, smblib_uusb_otg_work);
	chg->fake_capacity = -EINVAL;
	chg->fake_input_current_limited = -EINVAL;

@@ -4504,6 +4513,7 @@ int smblib_deinit(struct smb_charger *chg)
		cancel_delayed_work_sync(&chg->icl_change_work);
		cancel_delayed_work_sync(&chg->pl_enable_work);
		cancel_work_sync(&chg->legacy_detection_work);
		cancel_delayed_work_sync(&chg->uusb_otg_work);
		power_supply_unreg_notifier(&chg->nb);
		smblib_destroy_votables(chg);
		qcom_batt_deinit();
+3 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ enum print_reason {
#define CC2_WA_VOTER			"CC2_WA_VOTER"
#define QNOVO_VOTER			"QNOVO_VOTER"
#define BATT_PROFILE_VOTER		"BATT_PROFILE_VOTER"
#define OTG_DELAY_VOTER			"OTG_DELAY_VOTER"

#define VCONN_MAX_ATTEMPTS	3
#define OTG_MAX_ATTEMPTS	3
@@ -229,6 +230,7 @@ struct smb_charger {
	enum smb_mode		mode;
	struct smb_chg_freq	chg_freq;
	int			smb_version;
	int			otg_delay_ms;

	/* locks */
	struct mutex		lock;
@@ -290,6 +292,7 @@ struct smb_charger {
	struct delayed_work	icl_change_work;
	struct delayed_work	pl_enable_work;
	struct work_struct	legacy_detection_work;
	struct delayed_work	uusb_otg_work;

	/* cached status */
	int			voltage_min_uv;