]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/usb/host/ehci-hcd.c
usb: ehci: fully align interrupt QHs/QTDs
[karo-tx-uboot.git] / drivers / usb / host / ehci-hcd.c
index 3ae04c0253b694c32e310824627301b395e9ffe0..6017090ebeec93092953cc53266cd6de4a745dc7 100644 (file)
@@ -201,6 +201,9 @@ static int ehci_shutdown(struct ehci_ctrl *ctrl)
        int i, ret = 0;
        uint32_t cmd, reg;
 
+       if (!ctrl || !ctrl->hcor)
+               return -EINVAL;
+
        cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
        cmd &= ~(CMD_PSE | CMD_ASE);
        ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
@@ -392,6 +395,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
                QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(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);
 
        tdp = &qh->qh_overlay.qt_next;
 
@@ -919,28 +923,33 @@ int usb_lowlevel_stop(int index)
        return ehci_hcd_stop(index);
 }
 
-int usb_lowlevel_init(int index, void **controller)
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 {
        uint32_t reg;
        uint32_t cmd;
        struct QH *qh_list;
        struct QH *periodic;
        int i;
+       int rc;
 
-       if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
-               return -1;
+       rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor);
+       if (rc)
+               return rc;
+       if (init == USB_INIT_DEVICE)
+               goto done;
 
        /* EHCI spec section 4.1 */
        if (ehci_reset(index))
                return -1;
 
 #if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
-       if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
-               return -1;
+       rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor);
+       if (rc)
+               return rc;
 #endif
        /* Set the high address word (aka segment) for 64-bit controller */
        if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1)
-               ehci_writel(ehcic[index].hcor->or_ctrldssegment, 0);
+               ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0);
 
        qh_list = &ehcic[index].qh_list;
 
@@ -1037,7 +1046,7 @@ int usb_lowlevel_init(int index, void **controller)
        printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
 
        ehcic[index].rootdev = 0;
-
+done:
        *controller = &ehcic[index];
        return 0;
 }
@@ -1153,14 +1162,16 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
                debug("ehci intr queue: out of memory\n");
                goto fail1;
        }
-       result->first = memalign(32, sizeof(struct QH) * queuesize);
+       result->first = memalign(USB_DMA_MINALIGN,
+                                sizeof(struct QH) * queuesize);
        if (!result->first) {
                debug("ehci intr queue: out of memory\n");
                goto fail2;
        }
        result->current = result->first;
        result->last = result->first + queuesize - 1;
-       result->tds = memalign(32, sizeof(struct qTD) * queuesize);
+       result->tds = memalign(USB_DMA_MINALIGN,
+                              sizeof(struct qTD) * queuesize);
        if (!result->tds) {
                debug("ehci intr queue: out of memory\n");
                goto fail3;
@@ -1178,6 +1189,7 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
                        qh->qh_link = QH_LINK_TERMINATE;
 
                qh->qh_overlay.qt_next = (uint32_t)td;
+               qh->qh_overlay.qt_altnext = QT_NEXT_TERMINATE;
                qh->qh_endpt1 = (0 << 28) | /* No NAK reload (ehci 4.9) */
                        (usb_maxpacket(dev, pipe) << 16) | /* MPS */
                        (1 << 14) |