Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 325952
b: refs/heads/master
c: 363366c
h: refs/heads/master
v: v3
  • Loading branch information
Mike Thompson authored and Felipe Balbi committed Sep 10, 2012
1 parent 02fd559 commit 6fc5be5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 51e1e7bcef53e6a91cfffff0145ab315def61f61
refs/heads/master: 363366cf61c544ea476f3d220f43a95cb03014f5
38 changes: 35 additions & 3 deletions trunk/drivers/usb/otg/mxs-phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/workqueue.h>

#define DRIVER_NAME "mxs_phy"

Expand All @@ -34,9 +35,16 @@
#define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14)
#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)

/*
* Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit
* so that connection and reset processing can be completed for the root hub.
*/
#define MXY_PHY_ENHOSTDISCONDETECT_DELAY 250

struct mxs_phy {
struct usb_phy phy;
struct clk *clk;
struct delayed_work enhostdiscondetect_work;
};

#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
Expand All @@ -62,6 +70,7 @@ static int mxs_phy_init(struct usb_phy *phy)

clk_prepare_enable(mxs_phy->clk);
mxs_phy_hw_init(mxs_phy);
INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);

return 0;
}
Expand All @@ -76,13 +85,34 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
clk_disable_unprepare(mxs_phy->clk);
}

static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws)
{
struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy,
enhostdiscondetect_work.work);

/* Enable HOSTDISCONDETECT after delay. */
dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n");
writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET);
}

static int mxs_phy_on_connect(struct usb_phy *phy, int port)
{
struct mxs_phy *mxs_phy = to_mxs_phy(phy);

dev_dbg(phy->dev, "Connect on port %d\n", port);

mxs_phy_hw_init(to_mxs_phy(phy));
writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
phy->io_priv + HW_USBPHY_CTRL_SET);
mxs_phy_hw_init(mxs_phy);

/*
* Delay enabling ENHOSTDISCONDETECT so that connection and
* reset processing can be completed for the root hub.
*/
dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n");
PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work,
mxs_phy_enhostdiscondetect_delay);
schedule_delayed_work(&mxs_phy->enhostdiscondetect_work,
msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY));

return 0;
}
Expand All @@ -91,6 +121,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy, int port)
{
dev_dbg(phy->dev, "Disconnect on port %d\n", port);

/* No need to delay before clearing ENHOSTDISCONDETECT. */
dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n");
writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
phy->io_priv + HW_USBPHY_CTRL_CLR);

Expand Down

0 comments on commit 6fc5be5

Please sign in to comment.