summaryrefslogtreecommitdiffstats
path: root/drivers/usb/imx/imx-usb-phy.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-09-29 14:30:44 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-09-29 14:30:48 +0200
commite21ddc6ec059f59153dbc42d1281768d32bc6150 (patch)
tree57d3f9c351b5dc92aa15dc827d82b015cd3326f3 /drivers/usb/imx/imx-usb-phy.c
parenta44f222e09193ec3df7e3e9a000ff37b9c0fa72f (diff)
downloadbarebox-e21ddc6ec059f59153dbc42d1281768d32bc6150.tar.gz
barebox-e21ddc6ec059f59153dbc42d1281768d32bc6150.tar.xz
usb: imx-us-phy: implement notify_(dis)concect
The i.MX6 USB phy does not recognize disconnects of high speed devices when the USBPHY_CTRL_ENHOSTDISCONDETECT is not set. The phy does not work properly though when this bit is always set, so implement the notify_(dis)concect() callbacks to set this bit whenever a high speed device is connected and to clear it again when the device is disconnected. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/usb/imx/imx-usb-phy.c')
-rw-r--r--drivers/usb/imx/imx-usb-phy.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
index 2829ffce38..9f46f8de6d 100644
--- a/drivers/usb/imx/imx-usb-phy.c
+++ b/drivers/usb/imx/imx-usb-phy.c
@@ -33,6 +33,7 @@
#define USBPHY_CTRL_CLKGATE (1 << 30)
#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15)
#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14)
+#define USBPHY_CTRL_ENHOSTDISCONDETECT (1 << 1)
struct imx_usbphy {
struct usb_phy usb_phy;
@@ -67,6 +68,30 @@ static int imx_usbphy_phy_init(struct phy *phy)
return 0;
}
+static int imx_usbphy_notify_connect(struct usb_phy *phy,
+ enum usb_device_speed speed)
+{
+ struct imx_usbphy *imxphy = container_of(phy, struct imx_usbphy, usb_phy);
+
+ if (speed == USB_SPEED_HIGH) {
+ writel(USBPHY_CTRL_ENHOSTDISCONDETECT,
+ imxphy->base + USBPHY_CTRL + SET);
+ }
+
+ return 0;
+}
+
+static int imx_usbphy_notify_disconnect(struct usb_phy *phy,
+ enum usb_device_speed speed)
+{
+ struct imx_usbphy *imxphy = container_of(phy, struct imx_usbphy, usb_phy);
+
+ writel(USBPHY_CTRL_ENHOSTDISCONDETECT,
+ imxphy->base + USBPHY_CTRL + CLR);
+
+ return 0;
+}
+
static struct phy *imx_usbphy_xlate(struct device_d *dev,
struct of_phandle_args *args)
{
@@ -112,6 +137,8 @@ static int imx_usbphy_probe(struct device_d *dev)
dev->priv = imxphy;
imxphy->usb_phy.dev = dev;
+ imxphy->usb_phy.notify_connect = imx_usbphy_notify_connect;
+ imxphy->usb_phy.notify_disconnect = imx_usbphy_notify_disconnect;
imxphy->phy = phy_create(dev, NULL, &imx_phy_ops, NULL);
if (IS_ERR(imxphy->phy)) {
ret = PTR_ERR(imxphy->phy);