|
@@ -696,12 +696,31 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
|
|
kfree(req);
|
|
kfree(req);
|
|
}
|
|
}
|
|
|
|
|
|
-/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
+/* Actually add a dTD chain to an empty dQH and let go */
|
|
|
|
+static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td)
|
|
|
|
+{
|
|
|
|
+ struct ep_queue_head *qh = get_qh_by_ep(ep);
|
|
|
|
+
|
|
|
|
+ /* Write dQH next pointer and terminate bit to 0 */
|
|
|
|
+ qh->next_dtd_ptr = cpu_to_hc32(td->td_dma
|
|
|
|
+ & EP_QUEUE_HEAD_NEXT_POINTER_MASK);
|
|
|
|
+
|
|
|
|
+ /* Clear active and halt bit */
|
|
|
|
+ qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
|
|
|
|
+ | EP_QUEUE_HEAD_STATUS_HALT));
|
|
|
|
+
|
|
|
|
+ /* Ensure that updates to the QH will occur before priming. */
|
|
|
|
+ wmb();
|
|
|
|
+
|
|
|
|
+ /* Prime endpoint by writing correct bit to ENDPTPRIME */
|
|
|
|
+ fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16))
|
|
|
|
+ : (1 << (ep_index(ep))), &dr_regs->endpointprime);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Add dTD chain to the dQH of an EP */
|
|
static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
|
|
static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
|
|
{
|
|
{
|
|
- int i = ep_index(ep) * 2 + ep_is_in(ep);
|
|
|
|
u32 temp, bitmask, tmp_stat;
|
|
u32 temp, bitmask, tmp_stat;
|
|
- struct ep_queue_head *dQH = &ep->udc->ep_qh[i];
|
|
|
|
|
|
|
|
/* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);
|
|
/* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);
|
|
VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */
|
|
VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */
|
|
@@ -719,7 +738,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
|
|
cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
|
|
cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
|
|
/* Read prime bit, if 1 goto done */
|
|
/* Read prime bit, if 1 goto done */
|
|
if (fsl_readl(&dr_regs->endpointprime) & bitmask)
|
|
if (fsl_readl(&dr_regs->endpointprime) & bitmask)
|
|
- goto out;
|
|
|
|
|
|
+ return;
|
|
|
|
|
|
do {
|
|
do {
|
|
/* Set ATDTW bit in USBCMD */
|
|
/* Set ATDTW bit in USBCMD */
|
|
@@ -736,28 +755,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
|
|
fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);
|
|
fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);
|
|
|
|
|
|
if (tmp_stat)
|
|
if (tmp_stat)
|
|
- goto out;
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Write dQH next pointer and terminate bit to 0 */
|
|
|
|
- temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
|
|
|
|
- dQH->next_dtd_ptr = cpu_to_hc32(temp);
|
|
|
|
-
|
|
|
|
- /* Clear active and halt bit */
|
|
|
|
- temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
|
|
|
|
- | EP_QUEUE_HEAD_STATUS_HALT));
|
|
|
|
- dQH->size_ioc_int_sts &= temp;
|
|
|
|
-
|
|
|
|
- /* Ensure that updates to the QH will occur before priming. */
|
|
|
|
- wmb();
|
|
|
|
-
|
|
|
|
- /* Prime endpoint by writing 1 to ENDPTPRIME */
|
|
|
|
- temp = ep_is_in(ep)
|
|
|
|
- ? (1 << (ep_index(ep) + 16))
|
|
|
|
- : (1 << (ep_index(ep)));
|
|
|
|
- fsl_writel(temp, &dr_regs->endpointprime);
|
|
|
|
-out:
|
|
|
|
- return;
|
|
|
|
|
|
+ fsl_prime_ep(ep, req->head);
|
|
}
|
|
}
|
|
|
|
|
|
/* Fill in the dTD structure
|
|
/* Fill in the dTD structure
|
|
@@ -877,7 +878,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|
|
VDBG("%s, bad ep", __func__);
|
|
VDBG("%s, bad ep", __func__);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
- if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
|
|
|
|
|
|
+ if (usb_endpoint_xfer_isoc(ep->desc)) {
|
|
if (req->req.length > ep->ep.maxpacket)
|
|
if (req->req.length > ep->ep.maxpacket)
|
|
return -EMSGSIZE;
|
|
return -EMSGSIZE;
|
|
}
|
|
}
|
|
@@ -973,25 +974,20 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
|
|
|
|
|
|
/* The request isn't the last request in this ep queue */
|
|
/* The request isn't the last request in this ep queue */
|
|
if (req->queue.next != &ep->queue) {
|
|
if (req->queue.next != &ep->queue) {
|
|
- struct ep_queue_head *qh;
|
|
|
|
struct fsl_req *next_req;
|
|
struct fsl_req *next_req;
|
|
|
|
|
|
- qh = ep->qh;
|
|
|
|
next_req = list_entry(req->queue.next, struct fsl_req,
|
|
next_req = list_entry(req->queue.next, struct fsl_req,
|
|
queue);
|
|
queue);
|
|
|
|
|
|
- /* Point the QH to the first TD of next request */
|
|
|
|
- fsl_writel((u32) next_req->head, &qh->curr_dtd_ptr);
|
|
|
|
|
|
+ /* prime with dTD of next request */
|
|
|
|
+ fsl_prime_ep(ep, next_req->head);
|
|
}
|
|
}
|
|
-
|
|
|
|
- /* The request hasn't been processed, patch up the TD chain */
|
|
|
|
|
|
+ /* The request hasn't been processed, patch up the TD chain */
|
|
} else {
|
|
} else {
|
|
struct fsl_req *prev_req;
|
|
struct fsl_req *prev_req;
|
|
|
|
|
|
prev_req = list_entry(req->queue.prev, struct fsl_req, queue);
|
|
prev_req = list_entry(req->queue.prev, struct fsl_req, queue);
|
|
- fsl_writel(fsl_readl(&req->tail->next_td_ptr),
|
|
|
|
- &prev_req->tail->next_td_ptr);
|
|
|
|
-
|
|
|
|
|
|
+ prev_req->tail->next_td_ptr = req->tail->next_td_ptr;
|
|
}
|
|
}
|
|
|
|
|
|
done(ep, req, -ECONNRESET);
|
|
done(ep, req, -ECONNRESET);
|
|
@@ -1032,7 +1028,7 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
|
|
|
|
|
|
+ if (usb_endpoint_xfer_isoc(ep->desc)) {
|
|
status = -EOPNOTSUPP;
|
|
status = -EOPNOTSUPP;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -1068,7 +1064,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)
|
|
struct fsl_udc *udc;
|
|
struct fsl_udc *udc;
|
|
int size = 0;
|
|
int size = 0;
|
|
u32 bitmask;
|
|
u32 bitmask;
|
|
- struct ep_queue_head *d_qh;
|
|
|
|
|
|
+ struct ep_queue_head *qh;
|
|
|
|
|
|
ep = container_of(_ep, struct fsl_ep, ep);
|
|
ep = container_of(_ep, struct fsl_ep, ep);
|
|
if (!_ep || (!ep->desc && ep_index(ep) != 0))
|
|
if (!_ep || (!ep->desc && ep_index(ep) != 0))
|
|
@@ -1079,13 +1075,13 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)
|
|
if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
|
|
if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
|
|
return -ESHUTDOWN;
|
|
return -ESHUTDOWN;
|
|
|
|
|
|
- d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)];
|
|
|
|
|
|
+ qh = get_qh_by_ep(ep);
|
|
|
|
|
|
bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) :
|
|
bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) :
|
|
(1 << (ep_index(ep)));
|
|
(1 << (ep_index(ep)));
|
|
|
|
|
|
if (fsl_readl(&dr_regs->endptstatus) & bitmask)
|
|
if (fsl_readl(&dr_regs->endptstatus) & bitmask)
|
|
- size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE)
|
|
|
|
|
|
+ size = (qh->size_ioc_int_sts & DTD_PACKET_SIZE)
|
|
>> DTD_LENGTH_BIT_POS;
|
|
>> DTD_LENGTH_BIT_POS;
|
|
|
|
|
|
pr_debug("%s %u\n", __func__, size);
|
|
pr_debug("%s %u\n", __func__, size);
|
|
@@ -1938,8 +1934,7 @@ static int fsl_start(struct usb_gadget_driver *driver,
|
|
if (!udc_controller)
|
|
if (!udc_controller)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
- if (!driver || (driver->speed != USB_SPEED_FULL
|
|
|
|
- && driver->speed != USB_SPEED_HIGH)
|
|
|
|
|
|
+ if (!driver || driver->speed < USB_SPEED_FULL
|
|
|| !bind || !driver->disconnect || !driver->setup)
|
|
|| !bind || !driver->disconnect || !driver->setup)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|