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

Commit a0e406a6 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "phy: msm: usb: Check VBUS state before accessing registers in suspend"

parents 1e05ffb3 af15029b
Loading
Loading
Loading
Loading
+58 −32
Original line number Diff line number Diff line
@@ -1420,6 +1420,7 @@ static irqreturn_t msm_otg_phy_irq_handler(int irq, void *data)

static void msm_otg_set_vbus_state(int online);
static void msm_otg_perf_vote_update(struct msm_otg *motg, bool perf_mode);
static int get_psy_type(struct msm_otg *motg);

#ifdef CONFIG_PM_SLEEP
static int msm_otg_suspend(struct msm_otg *motg)
@@ -1458,7 +1459,11 @@ static int msm_otg_suspend(struct msm_otg *motg)
		msm_otg_perf_vote_update(motg, false);

	host_pc_charger = (motg->chg_type == USB_SDP_CHARGER) ||
				(motg->chg_type == USB_CDP_CHARGER);
			(motg->chg_type == USB_CDP_CHARGER) ||
			(get_psy_type(motg) == POWER_SUPPLY_TYPE_USB) ||
			(get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP);
	msm_otg_dbg_log_event(phy, "CHARGER CONNECTED",
			host_pc_charger, motg->inputs);

	/* !BSV, but its handling is in progress by otg sm_work */
	sm_work_busy = !test_bit(B_SESS_VLD, &motg->inputs) &&
@@ -1468,17 +1473,6 @@ static int msm_otg_suspend(struct msm_otg *motg)
	if (motg->err_event_seen)
		msm_otg_reset(phy);

	/* Enable line state difference wakeup fix for only device and host
	 * bus suspend scenarios.  Otherwise PHY can not be suspended when
	 * a charger that pulls DP/DM high is connected.
	 */
	config2 = readl_relaxed(USB_GENCONFIG_2);
	if (device_bus_suspend)
		config2 |= GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
	else
		config2 &= ~GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
	writel_relaxed(config2, USB_GENCONFIG_2);

	/*
	 * Abort suspend when,
	 * 1. host mode activation in progress due to Micro-A cable insertion
@@ -1496,6 +1490,17 @@ static int msm_otg_suspend(struct msm_otg *motg)
		return -EBUSY;
	}

	/* Enable line state difference wakeup fix for only device and host
	 * bus suspend scenarios.  Otherwise PHY can not be suspended when
	 * a charger that pulls DP/DM high is connected.
	 */
	config2 = readl_relaxed(USB_GENCONFIG_2);
	if (device_bus_suspend)
		config2 |= GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
	else
		config2 &= ~GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
	writel_relaxed(config2, USB_GENCONFIG_2);

	if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED) {
		/* put the controller in non-driving mode */
		func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
@@ -2862,6 +2867,10 @@ static void check_for_sdp_connection(struct work_struct *w)
	msm_otg_set_vbus_state(motg->vbus_state);
}

#define DP_PULSE_WIDTH_MSEC 200
static int
msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width);

static void msm_otg_sm_work(struct work_struct *w)
{
	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
@@ -2905,6 +2914,9 @@ static void msm_otg_sm_work(struct work_struct *w)
				get_pm_runtime_counter(dev), 0);
			pm_runtime_put_sync(dev);
			break;
		} else if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP) {
			pr_debug("Connected to CDP, pull DP up from sm_work\n");
			msm_otg_phy_drive_dp_pulse(motg, DP_PULSE_WIDTH_MSEC);
		}
		pm_runtime_put(dev);
		/* FALL THROUGH */
@@ -3073,9 +3085,14 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
{
	int ret = 0;
	u32 val;
	bool in_lpm = false;

	msm_otg_dbg_log_event(&motg->phy, "DRIVE DP PULSE",
				motg->inputs, 0);
	if (atomic_read(&motg->in_lpm))
		in_lpm = true;

	if (in_lpm) {
		ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
		if (ret)
			return ret;
@@ -3086,6 +3103,7 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
		clk_prepare_enable(motg->phy_csr_clk);
		clk_prepare_enable(motg->core_clk);
		clk_prepare_enable(motg->pclk);
	}

	msm_otg_exit_phy_retention(motg);

@@ -3131,6 +3149,7 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)

	/* Make sure above writes are completed before clks off */
	mb();
	if (in_lpm) {
		clk_disable_unprepare(motg->pclk);
		clk_disable_unprepare(motg->core_clk);
		clk_disable_unprepare(motg->phy_csr_clk);
@@ -3138,17 +3157,19 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
		regulator_disable(hsusb_vdd);
		msm_hsusb_config_vddcx(0);
		msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
	} else {
		msm_otg_reset(&motg->phy);
	}

	msm_otg_dbg_log_event(&motg->phy, "DP PULSE DRIVEN",
				motg->inputs, 0);
	return 0;
}

#define DP_PULSE_WIDTH_MSEC 200

static void msm_otg_set_vbus_state(int online)
{
	struct msm_otg *motg = the_msm_otg;
	struct usb_otg *otg = motg->phy.otg;

	motg->vbus_state = online;

@@ -3161,7 +3182,12 @@ static void msm_otg_set_vbus_state(int online)
				motg->inputs, 0);
		if (test_and_set_bit(B_SESS_VLD, &motg->inputs))
			return;
		if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP) {
		/*
		 * It might race with block reset happening in sm_work, while
		 * state machine is in undefined state. Add check to avoid it.
		 */
		if ((get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP) &&
		    (otg->state != OTG_STATE_UNDEFINED)) {
			pr_debug("Connected to CDP, pull DP up\n");
			msm_otg_phy_drive_dp_pulse(motg, DP_PULSE_WIDTH_MSEC);
		}