X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fehci-hcd.c;h=fdad739724eacb545817ebaf8128bdba96a82c91;hb=31043e20ae748635f142483e8b7b645948687055;hp=443cc2313465fcc872f21fbca52914a9bf50c2f2;hpb=9c6a9d7c8be40f58cf3faf0a4b8d9d33a21ca4f5;p=oweals%2Fu-boot.git diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 443cc23134..fdad739724 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -36,16 +36,7 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif -static struct ehci_ctrl { - struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ - struct ehci_hcor *hcor; - int rootdev; - uint16_t portreset; - struct QH qh_list __aligned(USB_DMA_MINALIGN); - struct QH periodic_queue __aligned(USB_DMA_MINALIGN); - uint32_t *periodic_list; - int ntds; -} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; +static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; #define ALIGN_END_ADDR(type, ptr, size) \ ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) @@ -589,10 +580,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); } else { dev->act_len = 0; +#ifndef CONFIG_USB_EHCI_FARADAY debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), ehci_readl(&ctrl->hcor->or_portsc[0]), ehci_readl(&ctrl->hcor->or_portsc[1])); +#endif } free(qtd); @@ -603,6 +596,17 @@ fail: return -1; } +__weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) +{ + if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { + /* Printing the message would cause a scan failure! */ + debug("The request port(%u) is not configured\n", port); + return NULL; + } + + return (uint32_t *)&hcor->or_portsc[port]; +} + int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) @@ -629,11 +633,9 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - if (!port || port > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", port - 1); + status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); + if (!status_reg) return -1; - } - status_reg = (uint32_t *)&ctrl->hcor->or_portsc[port - 1]; break; default: status_reg = NULL; @@ -915,6 +917,9 @@ int usb_lowlevel_init(int index, void **controller) qh_list->qh_overlay.qt_token = cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); + flush_dcache_range((uint32_t)qh_list, + ALIGN_END_ADDR(struct QH, qh_list, 1)); + /* Set async. queue head pointer. */ ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); @@ -928,6 +933,9 @@ int usb_lowlevel_init(int index, void **controller) periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + flush_dcache_range((uint32_t)periodic, + ALIGN_END_ADDR(struct QH, periodic, 1)); + /* * Step 2: Setup frame-list: Every microframe, USB tries the same list. * In particular, device specifications on polling frequency @@ -937,7 +945,9 @@ int usb_lowlevel_init(int index, void **controller) * Split Transactions will be spread across microframes using * S-mask and C-mask. */ - ehcic[index].periodic_list = memalign(4096, 1024*4); + if (ehcic[index].periodic_list == NULL) + ehcic[index].periodic_list = memalign(4096, 1024 * 4); + if (!ehcic[index].periodic_list) return -ENOMEM; for (i = 0; i < 1024; i++) { @@ -945,6 +955,10 @@ int usb_lowlevel_init(int index, void **controller) | QH_LINK_TYPE_QH; } + flush_dcache_range((uint32_t)ehcic[index].periodic_list, + ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list, + 1024)); + /* Set periodic list base address */ ehci_writel(&ehcic[index].hcor->or_periodiclistbase, (uint32_t)ehcic[index].periodic_list); @@ -971,10 +985,13 @@ int usb_lowlevel_init(int index, void **controller) cmd |= CMD_RUN; ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); +#ifndef CONFIG_USB_EHCI_FARADAY /* take control over the ports */ cmd = ehci_readl(&ehcic[index].hcor->or_configflag); cmd |= FLAG_CF; ehci_writel(&ehcic[index].hcor->or_configflag, cmd); +#endif + /* unblock posted write */ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); mdelay(5); @@ -1156,6 +1173,16 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, *buf = buffer + i * elementsize; } + flush_dcache_range((uint32_t)buffer, + ALIGN_END_ADDR(char, buffer, + queuesize * elementsize)); + flush_dcache_range((uint32_t)result->first, + ALIGN_END_ADDR(struct QH, result->first, + queuesize)); + flush_dcache_range((uint32_t)result->tds, + ALIGN_END_ADDR(struct qTD, result->tds, + queuesize)); + if (disable_periodic(ctrl) < 0) { debug("FATAL: periodic should never fail, but did"); goto fail3; @@ -1166,6 +1193,11 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, result->last->qh_link = list->qh_link; list->qh_link = (uint32_t)result->first | QH_LINK_TYPE_QH; + flush_dcache_range((uint32_t)result->last, + ALIGN_END_ADDR(struct QH, result->last, 1)); + flush_dcache_range((uint32_t)list, + ALIGN_END_ADDR(struct QH, list, 1)); + if (enable_periodic(ctrl) < 0) { debug("FATAL: periodic should never fail, but did"); goto fail3; @@ -1196,6 +1228,8 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) return NULL; } /* still active */ + invalidate_dcache_range((uint32_t)cur, + ALIGN_END_ADDR(struct QH, cur, 1)); if (cur->qh_overlay.qt_token & 0x80) { debug("Exit poll_int_queue with no completed intr transfer. " "token is %x\n", cur->qh_overlay.qt_token); @@ -1302,6 +1336,9 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return -EINVAL; } + invalidate_dcache_range((uint32_t)buffer, + ALIGN_END_ADDR(char, buffer, length)); + ret = destroy_int_queue(dev, queue); if (ret < 0) return ret;