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

Commit cd39d246 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Drive a pulse on DP on CDP detection"

parents 66b37f32 5276006f
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -3104,6 +3104,7 @@ static int dwc3_cpu_notifier_cb(struct notifier_block *nfb,
}

static void dwc3_otg_sm_work(struct work_struct *w);
static int get_psy_type(struct dwc3_msm *mdwc);

static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
{
@@ -3258,6 +3259,8 @@ static void check_for_sdp_connection(struct work_struct *w)
	}
}

#define DP_PULSE_WIDTH_MSEC 200

static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
	unsigned long event, void *ptr)
{
@@ -3270,6 +3273,14 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
		return NOTIFY_DONE;

	mdwc->vbus_active = event;

	if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP &&
			mdwc->vbus_active) {
		dev_dbg(mdwc->dev, "Connected to CDP, pull DP up\n");
		usb_phy_drive_dp_pulse(mdwc->hs_phy, DP_PULSE_WIDTH_MSEC);
	}


	if (dwc->is_drd && !mdwc->in_restart)
		queue_work(mdwc->dwc3_wq, &mdwc->resume_work);

+69 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2018, 2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@

/* QUSB2PHY_PWR_CTRL1 register related bits */
#define PWR_CTRL1_POWR_DOWN		BIT(0)
#define CLAMP_N_EN			BIT(1)

/* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */
#define CORE_READY_STATUS		BIT(0)
@@ -82,6 +83,10 @@
/* STAT5 register bits */
#define VSTATUS_PLL_LOCK_STATUS_MASK	BIT(0)

/* DEBUG_CTRL4 register bits  */
#define FORCED_UTMI_DPPULLDOWN	BIT(2)
#define FORCED_UTMI_DMPULLDOWN	BIT(3)

enum qusb_phy_reg {
	PORT_TUNE1,
	PLL_COMMON_STATUS_ONE,
@@ -94,6 +99,8 @@ enum qusb_phy_reg {
	SQ_CTRL2,
	DEBUG_CTRL1,
	DEBUG_CTRL2,
	DEBUG_CTRL3,
	DEBUG_CTRL4,
	STAT5,
	USB2_PHY_REG_MAX,
};
@@ -452,6 +459,24 @@ static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt,
			usleep_range(delay, (delay + 2000));
	}
}
static void msm_usb_write_readback(void __iomem *base, u32 offset,
					const u32 mask, u32 val)
{
	u32 write_val, tmp = readl_relaxed(base + offset);

	tmp &= ~mask;		/* retain other bits */
	write_val = tmp | val;

	writel_relaxed(write_val, base + offset);

	/* Read back to see if val was written */
	tmp = readl_relaxed(base + offset);
	tmp &= mask;		/* clear other bits */

	if (tmp != val)
		pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
			__func__, val, offset);
}

static void qusb_phy_reset(struct qusb_phy *qphy)
{
@@ -889,6 +914,48 @@ static int qusb_phy_disable_chirp(struct usb_phy *phy, bool disable)
	mutex_unlock(&qphy->lock);
	return ret;
}
static int msm_qusb_phy_drive_dp_pulse(struct usb_phy *phy,
					unsigned int interval_ms)
{
	struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);

	qusb_phy_enable_clocks(qphy, true);

	msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1],
				PWR_CTRL1_POWR_DOWN, 0x00);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4],
				FORCED_UTMI_DPPULLDOWN, 0x00);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4],
				FORCED_UTMI_DMPULLDOWN,
				FORCED_UTMI_DMPULLDOWN);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL3],
				0xd1, 0xd1);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1],
				CLAMP_N_EN, CLAMP_N_EN);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL],
				DPSE_INTR_HIGH_SEL, 0x00);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL],
				DPSE_INTR_EN, DPSE_INTR_EN);

	msleep(interval_ms);

	msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL],
				DPSE_INTR_HIGH_SEL |
				DPSE_INTR_EN, 0x00);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL3],
				0xd1, 0x00);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4],
				FORCED_UTMI_DPPULLDOWN |
				FORCED_UTMI_DMPULLDOWN, 0x00);
	msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1],
				PWR_CTRL1_POWR_DOWN |
				CLAMP_N_EN, 0x00);

	msleep(20);

	qusb_phy_enable_clocks(qphy, false);
	return 0;
}

static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev)
{
@@ -1332,6 +1399,7 @@ static int qusb_phy_probe(struct platform_device *pdev)
	qphy->phy.type			= USB_PHY_TYPE_USB2;
	qphy->phy.notify_connect        = qusb_phy_notify_connect;
	qphy->phy.notify_disconnect     = qusb_phy_notify_disconnect;
	qphy->phy.drive_dp_pulse	= msm_qusb_phy_drive_dp_pulse;

	/*
	 * qusb_phy_disable_chirp is not required if soc version is
+10 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ struct usb_phy {

	/* reset the PHY clocks */
	int     (*reset)(struct usb_phy *x);
	int	(*drive_dp_pulse)(struct usb_phy *x, unsigned int pulse_width);

	/* for notification of usb_phy_dbg_events */
	void    (*dbg_event)(struct usb_phy *x,
@@ -241,6 +242,15 @@ usb_phy_reset(struct usb_phy *x)
	return 0;
}

static inline int
usb_phy_drive_dp_pulse(struct usb_phy *x, unsigned int pulse_width)
{
	if (x && x->drive_dp_pulse)
		return x->drive_dp_pulse(x, pulse_width);

	return 0;
}

/* for usb host and peripheral controller drivers */
#if IS_ENABLED(CONFIG_USB_PHY)
extern struct usb_phy *usb_get_phy(enum usb_phy_type type);