Commit 07a8cdd2 authored by Anand Gadiyar's avatar Anand Gadiyar Committed by Felipe Balbi

usb: musb: do not use dma for control transfers

The Inventra DMA engine used with the MUSB controller in many
SoCs cannot use DMA for control transfers on EP0, but can use
DMA for all other transfers.

The USB core maps urbs for DMA if hcd->self.uses_dma is true.
(hcd->self.uses_dma is true for MUSB as well).

Split the uses_dma flag into two - one that says if the
controller needs to use PIO for control transfers, and
another which says if the controller uses DMA (for all
other transfers).

Also, populate this flag for all MUSB by default.

(Tested on OMAP3 and OMAP4 boards, with EHCI and MUSB HCDs
simultaneously in use).
Signed-off-by: default avatarMaulik Mankad <x0082077@ti.com>
Signed-off-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: default avatarAnand Gadiyar <gadiyar@ti.com>
Cc: Oliver Neukum <oliver@neukum.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Praveena NADAHALLY <praveen.nadahally@stericsson.com>
Cc: Ajay Kumar Gupta <ajay.gupta@ti.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent bb324b08
...@@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, ...@@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
*/ */
if (usb_endpoint_xfer_control(&urb->ep->desc)) { if (usb_endpoint_xfer_control(&urb->ep->desc)) {
if (hcd->self.uses_pio_for_control)
return ret;
if (hcd->self.uses_dma) { if (hcd->self.uses_dma) {
urb->setup_dma = dma_map_single( urb->setup_dma = dma_map_single(
hcd->self.controller, hcd->self.controller,
......
...@@ -2116,12 +2116,15 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -2116,12 +2116,15 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
* Otherwise, wait till the gadget driver hooks up. * Otherwise, wait till the gadget driver hooks up.
*/ */
if (!is_otg_enabled(musb) && is_host_enabled(musb)) { if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
musb->xceiv->default_a = 1; musb->xceiv->default_a = 1;
musb->xceiv->state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
status = usb_add_hcd(musb_to_hcd(musb), -1, 0); status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
hcd->self.uses_pio_for_control = 1;
DBG(1, "%s mode, status %d, devctl %02x %c\n", DBG(1, "%s mode, status %d, devctl %02x %c\n",
"HOST", status, "HOST", status,
musb_readb(musb->mregs, MUSB_DEVCTL), musb_readb(musb->mregs, MUSB_DEVCTL),
......
...@@ -1833,6 +1833,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -1833,6 +1833,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) { if (is_otg_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
DBG(3, "OTG startup...\n"); DBG(3, "OTG startup...\n");
/* REVISIT: funcall to other code, which also /* REVISIT: funcall to other code, which also
...@@ -1847,6 +1849,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -1847,6 +1849,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
musb->gadget_driver = NULL; musb->gadget_driver = NULL;
musb->g.dev.driver = NULL; musb->g.dev.driver = NULL;
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
} else {
hcd->self.uses_pio_for_control = 1;
} }
} }
} }
......
...@@ -313,6 +313,10 @@ struct usb_bus { ...@@ -313,6 +313,10 @@ struct usb_bus {
int busnum; /* Bus number (in order of reg) */ int busnum; /* Bus number (in order of reg) */
const char *bus_name; /* stable id (PCI slot_name etc) */ const char *bus_name; /* stable id (PCI slot_name etc) */
u8 uses_dma; /* Does the host controller use DMA? */ u8 uses_dma; /* Does the host controller use DMA? */
u8 uses_pio_for_control; /*
* Does the host controller use PIO
* for control transfers?
*/
u8 otg_port; /* 0, or number of OTG/HNP port */ u8 otg_port; /* 0, or number of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */ unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */ unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
......
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