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

Commit 59f042f6 authored by Bin Liu's avatar Bin Liu Committed by Felipe Balbi
Browse files

usb: phy: phy-am335x: bypass first VBUS sensing for host-only mode



To prevent VBUS contention, the am335x MUSB phy senses VBUS first before
transitioning to host mode. However, for host-only mode, VBUS could be
directly tied to 5V power rail which could prevent MUSB transitions to
host mode.

This change receives dr_mode of the controller then bypass the first
VBUS sensing for host-only mode, so that MUSB can work in host mode
event if VBUS is tied to 5V.

Signed-off-by: default avatarBin Liu <b-liu@ti.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 5306661e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ config AM335X_PHY_USB
	select USB_PHY
	select AM335X_CONTROL_USB
	select NOP_USB_XCEIV
	select USB_COMMON
	help
	  This driver provides PHY support for that phy which part for the
	  AM335x SoC.
+11 −3
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <linux/of.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
#include "phy-am335x-control.h"

struct am335x_control_usb {
@@ -58,7 +59,8 @@ static void am335x_phy_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
	spin_unlock(&usb_ctrl->lock);
}

static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id,
				enum usb_dr_mode dr_mode, bool on)
{
	struct am335x_control_usb *usb_ctrl;
	u32 val;
@@ -80,8 +82,14 @@ static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)

	val = readl(usb_ctrl->phy_reg + reg);
	if (on) {
		if (dr_mode == USB_DR_MODE_HOST) {
			val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN |
					USBPHY_OTGVDET_EN);
			val |= USBPHY_OTGSESSEND_EN;
		} else {
			val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
			val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
		}
	} else {
		val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
	}
+5 −3
Original line number Diff line number Diff line
@@ -2,13 +2,15 @@
#define _AM335x_PHY_CONTROL_H_

struct phy_control {
	void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
	void (*phy_power)(struct phy_control *phy_ctrl, u32 id,
			enum usb_dr_mode dr_mode, bool on);
	void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
};

static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id, bool on)
static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id,
				enum usb_dr_mode dr_mode, bool on)
{
	phy_ctrl->phy_power(phy_ctrl, id, on);
	phy_ctrl->phy_power(phy_ctrl, id, dr_mode, on);
}

static inline void phy_ctrl_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
+10 −5
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/usb/of.h>

#include "phy-am335x-control.h"
#include "phy-generic.h"
@@ -16,13 +17,14 @@ struct am335x_phy {
	struct usb_phy_generic usb_phy_gen;
	struct phy_control *phy_ctrl;
	int id;
	enum usb_dr_mode dr_mode;
};

static int am335x_init(struct usb_phy *phy)
{
	struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);

	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, true);
	return 0;
}

@@ -30,7 +32,7 @@ static void am335x_shutdown(struct usb_phy *phy)
{
	struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);

	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);
}

static int am335x_phy_probe(struct platform_device *pdev)
@@ -46,12 +48,15 @@ static int am335x_phy_probe(struct platform_device *pdev)
	am_phy->phy_ctrl = am335x_get_phy_control(dev);
	if (!am_phy->phy_ctrl)
		return -EPROBE_DEFER;

	am_phy->id = of_alias_get_id(pdev->dev.of_node, "phy");
	if (am_phy->id < 0) {
		dev_err(&pdev->dev, "Missing PHY id: %d\n", am_phy->id);
		return am_phy->id;
	}

	am_phy->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node);

	ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL);
	if (ret)
		return ret;
@@ -75,7 +80,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
	 */

	device_set_wakeup_enable(dev, false);
	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);

	return 0;
}
@@ -105,7 +110,7 @@ static int am335x_phy_suspend(struct device *dev)
	if (device_may_wakeup(dev))
		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, true);

	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);

	return 0;
}
@@ -115,7 +120,7 @@ static int am335x_phy_resume(struct device *dev)
	struct platform_device	*pdev = to_platform_device(dev);
	struct am335x_phy	*am_phy = platform_get_drvdata(pdev);

	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, true);

	if (device_may_wakeup(dev))
		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, false);