aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/sunxi.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2016-11-21 08:59:23 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-11-21 17:35:36 +0100
commit454f83d5e60110a18f24ffc0d58d2252d09c9a92 (patch)
tree7a2bf961047f1666872fc7f9ce718fb99802f19b /drivers/usb/musb/sunxi.c
parentmusb: sunxi: Remove custom babble handling (diff)
downloadlinux-dev-454f83d5e60110a18f24ffc0d58d2252d09c9a92.tar.xz
linux-dev-454f83d5e60110a18f24ffc0d58d2252d09c9a92.zip
musb: sunxi: Force session end on babble errors in host-mode
The sunxi musb has a bug where sometimes it will generate a babble error on device disconnect instead of a disconnect irq. When this happens the musb-controller switches from host mode to device mode (it clears MUSB_DEVCTL_SESSION and sets MUSB_DEVCTL_BDEVICE) and gets stuck in this state. Clearing this requires reporting Vbus low for 200 or more ms, but on some devices Vbus is simply always high (host-only mode, no Vbus control). This commit adds a sunxi_musb_recover() callback which makes sunxi_musb_work call phy_set_mode with the current mode, which will force end the current session. This fixes the musb controller getting stuck in this state on systems without Vbus control; and also fixes the need to unplug the usb-b -> usb-a cable to get out of this state on systems with Vbus control. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/musb/sunxi.c')
-rw-r--r--drivers/usb/musb/sunxi.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 82eba92284c0..d0be0eadd0d9 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -380,6 +380,20 @@ static int sunxi_musb_set_mode(struct musb *musb, u8 mode)
return 0;
}
+static int sunxi_musb_recover(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ /*
+ * Schedule a phy_set_mode with the current glue->phy_mode value,
+ * this will force end the current session.
+ */
+ set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
+ schedule_work(&glue->work);
+
+ return 0;
+}
+
/*
* sunxi musb register layout
* 0x00 - 0x17 fifo regs, 1 long per fifo
@@ -608,6 +622,7 @@ static const struct musb_platform_ops sunxi_musb_ops = {
.dma_init = sunxi_musb_dma_controller_create,
.dma_exit = sunxi_musb_dma_controller_destroy,
.set_mode = sunxi_musb_set_mode,
+ .recover = sunxi_musb_recover,
.set_vbus = sunxi_musb_set_vbus,
.pre_root_reset_end = sunxi_musb_pre_root_reset_end,
.post_root_reset_end = sunxi_musb_post_root_reset_end,