summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
7bcf018)
musb can be suspended at the time some other driver wants to do ulpi
transfers using otg_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 otg_transceiver so that pm_runtime can be used.
Cc: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
int i = 0;
u8 r;
u8 power;
int i = 0;
u8 r;
u8 power;
+ int ret;
+
+ pm_runtime_get_sync(otg->io_dev);
/* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER);
/* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER);
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) {
i++;
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) {
i++;
- if (i == 10000)
- return -ETIMEDOUT;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
}
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
}
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT;
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(otg->io_dev);
+
+ return ret;
}
static int musb_ulpi_write(struct otg_transceiver *otg,
}
static int musb_ulpi_write(struct otg_transceiver *otg,
int i = 0;
u8 r = 0;
u8 power;
int i = 0;
u8 r = 0;
u8 power;
+ int ret = 0;
+
+ pm_runtime_get_sync(otg->io_dev);
/* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER);
/* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER);
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) {
i++;
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) {
i++;
- if (i == 10000)
- return -ETIMEDOUT;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
}
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
}
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
+out:
+ pm_runtime_put(otg->io_dev);
+
+ return ret;
}
#else
#define musb_ulpi_read NULL
}
#else
#define musb_ulpi_read NULL
}
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_ops = &musb_ulpi_access;
}
musb->xceiv->io_priv = musb->mregs;
musb->xceiv->io_ops = &musb_ulpi_access;
}
struct usb_bus *host;
struct usb_gadget *gadget;
struct usb_bus *host;
struct usb_gadget *gadget;
struct otg_io_access_ops *io_ops;
void __iomem *io_priv;
struct otg_io_access_ops *io_ops;
void __iomem *io_priv;