From: Grazvydas Ignotas Date: Fri, 3 Feb 2012 16:00:28 +0000 (+0200) Subject: usb: musb: wake the device before ulpi transfers X-Git-Tag: sz_beta2~38 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=521cc76b1f10445b067bf5b6f469e5d32f60c09c;hp=7bcf018345a6ed7bb6ebdb495a91e0befc0e9847;p=pandora-kernel.git usb: musb: wake the device before ulpi transfers 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 Signed-off-by: Grazvydas Ignotas --- diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 191c9ca6498b..98c37d869a2f 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -137,6 +137,9 @@ static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset) 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); @@ -154,15 +157,22 @@ static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset) 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); - 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, @@ -172,6 +182,9 @@ static int musb_ulpi_write(struct otg_transceiver *otg, 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); @@ -185,15 +198,20 @@ static int musb_ulpi_write(struct otg_transceiver *otg, 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); - return 0; +out: + pm_runtime_put(otg->io_dev); + + return ret; } #else #define musb_ulpi_read NULL @@ -1955,6 +1973,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) } if (!musb->xceiv->io_ops) { + musb->xceiv->io_dev = musb->controller; musb->xceiv->io_priv = musb->mregs; musb->xceiv->io_ops = &musb_ulpi_access; } diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index d87f44f5b04e..308b6990fd4a 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -71,6 +71,7 @@ struct otg_transceiver { struct usb_bus *host; struct usb_gadget *gadget; + struct device *io_dev; struct otg_io_access_ops *io_ops; void __iomem *io_priv;