aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_core.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2014-04-02 07:58:28 -0400
committerFelipe Balbi <balbi@ti.com>2014-04-21 15:07:28 -0400
commitca88fc2ef0d790a1da37804219102336f7622b97 (patch)
tree6fba0f43345cda2e2a4463ec6cc3f3a38c8e8125 /drivers/usb/musb/musb_core.c
parent1e42d20c88f2f56c0d81363d7b0f1d3762037f53 (diff)
usb: musb: add a work_struct to recover from babble errors
Handle BABBLE interrupt error conditions from a work struct handler. This indirection is necessary as we can't be certain that the phy functions don't sleep. Platform layer implementation may pass a babble error down to the core in order to handle it. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb/musb_core.c')
-rw-r--r--drivers/usb/musb/musb_core.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 07576907e2c6..61da471b7aed 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -848,6 +848,10 @@ b_host:
848 } 848 }
849 } 849 }
850 850
851 /* handle babble condition */
852 if (int_usb & MUSB_INTR_BABBLE)
853 schedule_work(&musb->recover_work);
854
851#if 0 855#if 0
852/* REVISIT ... this would be for multiplexing periodic endpoints, or 856/* REVISIT ... this would be for multiplexing periodic endpoints, or
853 * supporting transfer phasing to prevent exceeding ISO bandwidth 857 * supporting transfer phasing to prevent exceeding ISO bandwidth
@@ -1746,6 +1750,34 @@ static void musb_irq_work(struct work_struct *data)
1746 } 1750 }
1747} 1751}
1748 1752
1753/* Recover from babble interrupt conditions */
1754static void musb_recover_work(struct work_struct *data)
1755{
1756 struct musb *musb = container_of(data, struct musb, recover_work);
1757 int status;
1758
1759 musb_platform_reset(musb);
1760
1761 usb_phy_vbus_off(musb->xceiv);
1762 udelay(100);
1763
1764 usb_phy_vbus_on(musb->xceiv);
1765 udelay(100);
1766
1767 /*
1768 * When a babble condition occurs, the musb controller removes the
1769 * session bit and the endpoint config is lost.
1770 */
1771 if (musb->dyn_fifo)
1772 status = ep_config_from_table(musb);
1773 else
1774 status = ep_config_from_hw(musb);
1775
1776 /* start the session again */
1777 if (status == 0)
1778 musb_start(musb);
1779}
1780
1749/* -------------------------------------------------------------------------- 1781/* --------------------------------------------------------------------------
1750 * Init support 1782 * Init support
1751 */ 1783 */
@@ -1913,6 +1945,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
1913 1945
1914 /* Init IRQ workqueue before request_irq */ 1946 /* Init IRQ workqueue before request_irq */
1915 INIT_WORK(&musb->irq_work, musb_irq_work); 1947 INIT_WORK(&musb->irq_work, musb_irq_work);
1948 INIT_WORK(&musb->recover_work, musb_recover_work);
1916 INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); 1949 INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
1917 INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); 1950 INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
1918 1951
@@ -2008,6 +2041,7 @@ fail4:
2008 2041
2009fail3: 2042fail3:
2010 cancel_work_sync(&musb->irq_work); 2043 cancel_work_sync(&musb->irq_work);
2044 cancel_work_sync(&musb->recover_work);
2011 cancel_delayed_work_sync(&musb->finish_resume_work); 2045 cancel_delayed_work_sync(&musb->finish_resume_work);
2012 cancel_delayed_work_sync(&musb->deassert_reset_work); 2046 cancel_delayed_work_sync(&musb->deassert_reset_work);
2013 if (musb->dma_controller) 2047 if (musb->dma_controller)
@@ -2073,6 +2107,7 @@ static int musb_remove(struct platform_device *pdev)
2073 dma_controller_destroy(musb->dma_controller); 2107 dma_controller_destroy(musb->dma_controller);
2074 2108
2075 cancel_work_sync(&musb->irq_work); 2109 cancel_work_sync(&musb->irq_work);
2110 cancel_work_sync(&musb->recover_work);
2076 cancel_delayed_work_sync(&musb->finish_resume_work); 2111 cancel_delayed_work_sync(&musb->finish_resume_work);
2077 cancel_delayed_work_sync(&musb->deassert_reset_work); 2112 cancel_delayed_work_sync(&musb->deassert_reset_work);
2078 musb_free(musb); 2113 musb_free(musb);