risc-v/mpfs: usb: fix ep0 stall/resume and rx reads
Fix EP0 stall and resume properly. EP0 wasn't clearly addressed on stall / resume operations. Also fix data reads that provide garbage for the first request. It has always random data as it's completed prior to any read operation. Signed-off-by: Eero Nurkkala <eero.nurkkala@offcode.fi>
This commit is contained in:
parent
e843c441de
commit
c38d547900
@ -755,7 +755,14 @@ static int mpfs_ep_stall(struct mpfs_ep_s *privep)
|
||||
privep->stalled = true;
|
||||
privep->pending = false;
|
||||
|
||||
if (USB_ISEPIN(privep->ep.eplog))
|
||||
if (epno == EP0)
|
||||
{
|
||||
mpfs_modifyreg16(MPFS_USB_INDEXED_CSR_EP0_CSR0,
|
||||
0,
|
||||
CSR0L_DEV_SEND_STALL_MASK |
|
||||
CSR0L_DEV_SERVICED_RX_PKT_RDY_MASK);
|
||||
}
|
||||
else if (USB_ISEPIN(privep->ep.eplog))
|
||||
{
|
||||
mpfs_modifyreg16(MPFS_USB_ENDPOINT(epno) +
|
||||
MPFS_USB_ENDPOINT_TX_CSR_OFFSET,
|
||||
@ -972,6 +979,7 @@ static int mpfs_req_read(struct mpfs_usbdev_s *priv,
|
||||
struct mpfs_ep_s *privep, uint16_t recvsize)
|
||||
{
|
||||
struct mpfs_req_s *privreq;
|
||||
bool earlyread = false;
|
||||
int epno;
|
||||
|
||||
DEBUGASSERT(priv && privep && privep->epstate == USB_EPSTATE_IDLE);
|
||||
@ -1016,7 +1024,14 @@ static int mpfs_req_read(struct mpfs_usbdev_s *priv,
|
||||
{
|
||||
/* Update the total number of bytes transferred */
|
||||
|
||||
privreq->req.xfrd += recvsize;
|
||||
privep->rxactive = true;
|
||||
privreq->req.xfrd += mpfs_read_rx_fifo(privreq->req.buf,
|
||||
privreq->req.len,
|
||||
epno);
|
||||
|
||||
/* Early read indicates a request that was already in place */
|
||||
|
||||
earlyread = true;
|
||||
privreq->inflight = 0;
|
||||
|
||||
usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
|
||||
@ -1036,15 +1051,24 @@ static int mpfs_req_read(struct mpfs_usbdev_s *priv,
|
||||
|
||||
DEBUGASSERT(recvsize == 0);
|
||||
|
||||
/* activate new read request from queue */
|
||||
/* Activate new read request from queue */
|
||||
|
||||
privep->rxactive = true;
|
||||
privreq->req.xfrd = 0;
|
||||
privreq->inflight = privreq->req.len;
|
||||
priv->eplist[epno].descb[0]->addr = (uintptr_t)privreq->req.buf;
|
||||
|
||||
privreq->req.xfrd += mpfs_read_rx_fifo(privreq->req.buf, privreq->req.len,
|
||||
epno);
|
||||
/* It's possible the request has been completed already. If so, don't
|
||||
* repeat the read as the buffer is empty.
|
||||
*/
|
||||
|
||||
if (!earlyread)
|
||||
{
|
||||
privep->rxactive = true;
|
||||
privreq->req.xfrd = 0;
|
||||
priv->eplist[epno].descb[0]->addr = (uintptr_t)privreq->req.buf;
|
||||
|
||||
privreq->req.xfrd += mpfs_read_rx_fifo(privreq->req.buf,
|
||||
privreq->req.len,
|
||||
epno);
|
||||
}
|
||||
|
||||
if (epno == EP0)
|
||||
{
|
||||
@ -1736,9 +1760,15 @@ static int mpfs_ep_resume(struct mpfs_ep_s *privep)
|
||||
privep->pending = false;
|
||||
privep->epstate = USB_EPSTATE_IDLE;
|
||||
|
||||
/* Clear STALLRQx request and reset data toggle */
|
||||
/* Clear STALLRQx request and reset data toggle if needed */
|
||||
|
||||
if (USB_ISEPIN(privep->ep.eplog))
|
||||
if (epno == EP0)
|
||||
{
|
||||
mpfs_modifyreg16(MPFS_USB_INDEXED_CSR_EP0_CSR0,
|
||||
CSR0L_DEV_STALL_SENT_MASK,
|
||||
0);
|
||||
}
|
||||
else if (USB_ISEPIN(privep->ep.eplog))
|
||||
{
|
||||
mpfs_modifyreg16(MPFS_USB_ENDPOINT(epno) +
|
||||
MPFS_USB_ENDPOINT_TX_CSR_OFFSET,
|
||||
@ -3573,6 +3603,8 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
|
||||
struct mpfs_usbdev_s *priv = &g_usbd;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(driver != NULL);
|
||||
|
||||
/* First hook up the driver */
|
||||
|
||||
priv->driver = driver;
|
||||
|
Loading…
Reference in New Issue
Block a user