Commit bf070bc1 authored by Grazvydas Ignotas's avatar Grazvydas Ignotas Committed by Felipe Balbi

usb: musb: wake the device before ulpi transfers

musb can be suspended at the time some other driver wants to do ulpi
transfers using usb_phy_io_* functions, and that can cause data abort,
as it happened with isp1704_charger:
http://article.gmane.org/gmane.linux.kernel/1226122

Add pm_runtime to ulpi functions to rectify this. This also adds io_dev
to usb_phy so that pm_runtime_* functions can be used.

Cc: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: default avatarGrazvydas Ignotas <notasas@gmail.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 692933b2
...@@ -137,6 +137,9 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) ...@@ -137,6 +137,9 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
int i = 0; int i = 0;
u8 r; u8 r;
u8 power; u8 power;
int ret;
pm_runtime_get_sync(phy->io_dev);
/* Make sure the transceiver is not in low power mode */ /* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER); power = musb_readb(addr, MUSB_POWER);
...@@ -154,15 +157,22 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) ...@@ -154,15 +157,22 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) { & MUSB_ULPI_REG_CMPLT)) {
i++; i++;
if (i == 10000) if (i == 10000) {
return -ETIMEDOUT; ret = -ETIMEDOUT;
goto out;
}
} }
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT; r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
return musb_readb(addr, MUSB_ULPI_REG_DATA); ret = musb_readb(addr, MUSB_ULPI_REG_DATA);
out:
pm_runtime_put(phy->io_dev);
return ret;
} }
static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
...@@ -171,6 +181,9 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) ...@@ -171,6 +181,9 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
int i = 0; int i = 0;
u8 r = 0; u8 r = 0;
u8 power; u8 power;
int ret = 0;
pm_runtime_get_sync(phy->io_dev);
/* Make sure the transceiver is not in low power mode */ /* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER); power = musb_readb(addr, MUSB_POWER);
...@@ -184,15 +197,20 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) ...@@ -184,15 +197,20 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) { & MUSB_ULPI_REG_CMPLT)) {
i++; i++;
if (i == 10000) if (i == 10000) {
return -ETIMEDOUT; ret = -ETIMEDOUT;
goto out;
}
} }
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT; r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
return 0; out:
pm_runtime_put(phy->io_dev);
return ret;
} }
#else #else
#define musb_ulpi_read NULL #define musb_ulpi_read NULL
...@@ -1908,6 +1926,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -1908,6 +1926,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
} }
if (!musb->xceiv->io_ops) { if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs; musb->xceiv->io_priv = musb->mregs;
musb->xceiv->io_ops = &musb_ulpi_access; musb->xceiv->io_ops = &musb_ulpi_access;
} }
......
...@@ -94,6 +94,7 @@ struct usb_phy { ...@@ -94,6 +94,7 @@ struct usb_phy {
struct usb_otg *otg; struct usb_otg *otg;
struct device *io_dev;
struct usb_phy_io_ops *io_ops; struct usb_phy_io_ops *io_ops;
void __iomem *io_priv; void __iomem *io_priv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment