diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 108 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 10 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 40 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 2 |
4 files changed, 50 insertions, 110 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a2473a9141..c2f48ce428 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -120,63 +120,6 @@ static struct descriptor { #define ehci_is_TDI() (ehci->flags & EHCI_HAS_TT) -#ifdef CONFIG_MMU -/* - * Routines to handle (flush/invalidate) the dcache for the QH and qTD - * structures and data buffers. This is needed on platforms using this - * EHCI support with dcache enabled. - */ -static void flush_invalidate(void *addr, int size, int flush) -{ - if (flush) { - dma_flush_range((unsigned long)addr, (unsigned long)(addr + size)); - } else { - dma_inv_range((unsigned long)addr, (unsigned long)(addr + size)); - } -} - -static void cache_qtd(struct qTD *qtd, int flush) -{ - u32 *ptr = (u32 *)qtd->qt_buffer[0]; - int len = (qtd->qt_token & 0x7fff0000) >> 16; - - if (ptr && len) - flush_invalidate(ptr, len, flush); -} - -static void cache_qh(struct ehci_priv *ehci, int flush) -{ - int i; - - flush_invalidate(ehci->qh_list, sizeof(struct QH) * NUM_QH, flush); - flush_invalidate(ehci->td, sizeof(struct qTD) * NUM_TD, flush); - - for (i = 0; i < NUM_TD; i ++) - cache_qtd(&ehci->td[i], flush); -} - -static inline void ehci_flush_dcache(struct ehci_priv *ehci) -{ - cache_qh(ehci, 1); -} - -static inline void ehci_invalidate_dcache(struct ehci_priv *ehci) -{ - cache_qh(ehci, 0); -} -#else /* CONFIG_MMU */ -/* - * - */ -static inline void ehci_flush_dcache(struct ehci_priv *ehci) -{ -} - -static inline void ehci_invalidate_dcache(struct ehci_priv *ehci) -{ -} -#endif /* CONFIG_MMU */ - static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) { uint32_t result; @@ -231,6 +174,9 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) int idx; addr = (uint32_t) buf; + td->qtd_dma = addr; + td->length = sz; + idx = 0; while (idx < 5) { td->qt_buffer[idx] = cpu_to_hc32(addr); @@ -264,7 +210,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t endpt, token, usbsts; uint32_t c, toggle; uint32_t cmd; - int ret = 0; + int ret = 0, i; uint64_t start, timeout_val; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, @@ -296,11 +242,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); qh->qh_endpt2 = cpu_to_hc32(endpt); - qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + qh->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); + qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); td = NULL; - tdp = &qh->qh_overlay.qt_next; + tdp = &qh->qt_next; toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); @@ -363,7 +309,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci->qh_list->qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); /* Flush dcache */ - ehci_flush_dcache(ehci); + if (IS_ENABLED(CONFIG_MMU)) { + for (i = 0; i < NUM_TD; i ++) { + struct qTD *qtd = &ehci->td[i]; + if (!qtd->qtd_dma) + continue; + dma_flush_range(qtd->qtd_dma, qtd->qtd_dma + qtd->length); + } + } usbsts = ehci_readl(&ehci->hcor->or_usbsts); ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f)); @@ -384,8 +337,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, start = get_time_ns(); vtd = td; do { - /* Invalidate dcache */ - ehci_invalidate_dcache(ehci); token = hc32_to_cpu(vtd->qt_token); if (is_timeout(start, timeout_val)) { /* Disable async schedule. */ @@ -394,11 +345,20 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci_writel(&ehci->hcor->or_usbcmd, cmd); ret = handshake(&ehci->hcor->or_usbsts, STD_ASS, 0, 100 * 1000); - ehci_writel(&qh->qh_overlay.qt_token, 0); + ehci_writel(&qh->qt_token, 0); return -ETIMEDOUT; } } while (token & 0x80); + if (IS_ENABLED(CONFIG_MMU)) { + for (i = 0; i < NUM_TD; i ++) { + struct qTD *qtd = &ehci->td[i]; + if (!qtd->qtd_dma) + continue; + dma_inv_range(qtd->qtd_dma, qtd->qtd_dma + qtd->length); + } + } + /* Disable async schedule. */ cmd = ehci_readl(&ehci->hcor->or_usbcmd); cmd &= ~CMD_ASE; @@ -413,7 +373,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH); - token = hc32_to_cpu(qh->qh_overlay.qt_token); + token = hc32_to_cpu(qh->qt_token); if (!(token & 0x80)) { debug("TOKEN=0x%08x\n", token); switch (token & 0xfc) { @@ -451,10 +411,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, fail: printf("fail1\n"); - td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); + td = (void *)hc32_to_cpu(qh->qt_next); while (td != (void *)QT_NEXT_TERMINATE) { - qh->qh_overlay.qt_next = td->qt_next; - td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); + qh->qt_next = td->qt_next; + td = (void *)hc32_to_cpu(qh->qt_next); } return -1; } @@ -770,9 +730,9 @@ static int ehci_init(struct usb_host *host) ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH); ehci->qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12)); ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); - ehci->qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - ehci->qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - ehci->qh_list->qh_overlay.qt_token = cpu_to_hc32(0x40); + ehci->qh_list->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); + ehci->qh_list->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + ehci->qh_list->qt_token = cpu_to_hc32(0x40); /* Set async. queue head pointer. */ ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list); @@ -878,8 +838,8 @@ static int ehci_probe(struct device_d *dev) ehci->hccr = dev_request_mem_region(dev, 0); ehci->hcor = dev_request_mem_region(dev, 1); - ehci->qh_list = xmemalign(32, sizeof(struct QH) * NUM_QH); - ehci->td = xmemalign(32, sizeof(struct qTD) * NUM_TD); + ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD); + ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD); host->init = ehci_init; host->submit_int_msg = submit_int_msg; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index eac93db01c..b127b95bbe 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -166,7 +166,9 @@ struct qTD { uint32_t qt_altnext; uint32_t qt_token; uint32_t qt_buffer[5]; -}; + unsigned long qtd_dma; + size_t length; +} __attribute__ ((aligned (32))); /* Queue Head (QH). */ struct QH { @@ -179,7 +181,11 @@ struct QH { uint32_t qh_endpt1; uint32_t qh_endpt2; uint32_t qh_curtd; - struct qTD qh_overlay; + /* qtd overlay (hardware parts of a struct qTD) */ + uint32_t qt_next; + uint32_t qt_altnext; + uint32_t qt_token; + uint32_t qt_buffer[5]; /* * Add dummy fill value to make the size of this struct * aligned to 32 bytes diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 05e4094386..f10d827615 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -415,7 +415,7 @@ static void ohci_dump(struct ohci *controller, int verbose) /* get a transfer request */ -int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) +static int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) { struct ed *ed; int i, size = 0; @@ -498,7 +498,7 @@ int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) static inline int sohci_return_job(struct ohci *hc, struct urb_priv *urb) { #ifdef ENBALE_PIPE_INTERRUPT - struct ohci_regs *regs = hc->regs; + struct ohci_regs __iomem *regs = hc->regs; #endif switch (usb_pipetype(urb->pipe)) { @@ -848,7 +848,7 @@ static void td_fill(struct ohci *ohci, unsigned int info, } #endif if (!len) - data = 0; + data = NULL; td->hwINFO = m32_swap(info); td->hwCBP = virt_to_phys((void *)m32_swap((unsigned long)data)); @@ -894,7 +894,7 @@ static void td_submit_job(struct usb_device *dev, unsigned long pipe, if (data_len) data = buffer; else - data = 0; + data = NULL; switch (usb_pipetype(pipe)) { case PIPE_BULK: @@ -1214,32 +1214,6 @@ static inline void wr_rh_portstat(struct ohci *ohci, int wIndex, __u32 value) writel(value, &ohci->regs->roothub.portstatus[wIndex-1]); } -/* request to virtual root hub */ - -int rh_check_port_status(struct ohci *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); -#ifdef CONFIG_AT91C_PQFP_UHPBUG - ndp = (ndp == 2) ? 1 : 0; -#endif - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && - ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd) { @@ -1502,7 +1476,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, /* common code for handling submit messages - used for all but root hub */ /* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +static int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *setup, int interval, int timeout) { @@ -1721,7 +1695,7 @@ static int hc_start(struct ohci *ohci) static int hc_interrupt(struct ohci *ohci) { - struct ohci_regs *regs = ohci->regs; + struct ohci_regs __iomem *regs = ohci->regs; int ints; int stat = 0; @@ -1840,7 +1814,7 @@ static int ohci_probe(struct device_d *dev) usb_register_host(host); - ohci->regs = (void *)dev->resource[0].start; + ohci->regs = dev_request_mem_region(dev, 0); return 0; } diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 913296319e..9c9b8375ce 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -408,7 +408,7 @@ struct ohci { int disabled; /* e.g. got a UE, we're hung */ unsigned long flags; /* for HC bugs */ - struct ohci_regs *regs; /* OHCI controller's memory */ + struct ohci_regs __iomem *regs; /* OHCI controller's memory */ int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ struct ed *ed_rm_list[2]; /* lists of all endpoints to be removed */ |