risc-v/mpfs: usb: provide more endpoints
The underlying hardware supports 9 endpoints: - EP0 - 4x IN EPs - 4x OUT EPs Currently the driver assumes every EP number is unique. This limits the amount of EPs to 1 + 4 = 5. Utilize the EPs in such a manner that all may be used. Also fix a few error handling related bugs. Update the composite driver to match the current situation as well. Signed-off-by: Eero Nurkkala <eero.nurkkala@offcode.fi>
This commit is contained in:
parent
e0bb281e7a
commit
4df8b16060
@ -27,7 +27,7 @@
|
||||
|
||||
#define SOFT_RESET_REG_MASK 0x03u
|
||||
|
||||
#define MPFS_USB_NENDPOINTS 8 /* 4 IN and 4 OUT endpoints */
|
||||
#define MPFS_USB_NENDPOINTS 9 /* EP0 + 4x IN and 4x OUT EPs */
|
||||
#define MPFS_USB_MAXPACKETSIZE(ep) 64
|
||||
#define MPFS_USB_MAXPACKETSIZE_HS(ep) 512
|
||||
#define MPFS_EP0_MAXPACKET 64
|
||||
|
@ -138,10 +138,11 @@
|
||||
#define mpfs_rqempty(q) ((q)->head == NULL)
|
||||
#define mpfs_rqpeek(q) ((q)->head)
|
||||
|
||||
#define MPFS_EPSET_ALL (0xff) /* All endpoints */
|
||||
#define MPFS_EPSET_NOTEP0 (0xfe) /* All endpoints except EP0 */
|
||||
#define MPFS_EPSET_ALL (0x1ff) /* All endpoints */
|
||||
#define MPFS_EPSET_NOTEP0 (0x1fe) /* All endpoints except EP0 */
|
||||
#define MPFS_EP_BIT(ep) (1 << (ep))
|
||||
#define MPFS_MAX_MULTIPACKET_SIZE (0x3fff)
|
||||
#define MPFS_EPIN_START (MPFS_USB_NENDPOINTS / 2)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
@ -652,9 +653,19 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv,
|
||||
uint8_t epno;
|
||||
int nbytes;
|
||||
int ret;
|
||||
int idx;
|
||||
|
||||
epno = USB_EPNO(privep->ep.eplog);
|
||||
|
||||
if (USB_ISEPIN(privep->ep.eplog))
|
||||
{
|
||||
idx = epno + MPFS_EPIN_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = epno;
|
||||
}
|
||||
|
||||
mpfs_putreg8(epno, MPFS_USB_INDEX);
|
||||
|
||||
/* Get the number of bytes remaining to be sent. */
|
||||
@ -686,8 +697,8 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv,
|
||||
|
||||
/* Setup TX transfer using ep configured maxpacket size */
|
||||
|
||||
priv->eplist[epno].descb[1]->addr = (uintptr_t)buf;
|
||||
packetsize = priv->eplist[epno].descb[1]->pktsize;
|
||||
priv->eplist[idx].descb[1]->addr = (uintptr_t)buf;
|
||||
packetsize = priv->eplist[idx].descb[1]->pktsize;
|
||||
|
||||
/* Set automatic ZLP sending if requested on req */
|
||||
|
||||
@ -696,7 +707,7 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv,
|
||||
/* Handle this properly when DMA supported */
|
||||
}
|
||||
|
||||
priv->eplist[epno].descb[1]->pktsize = packetsize;
|
||||
priv->eplist[idx].descb[1]->pktsize = packetsize;
|
||||
|
||||
/* Indicate that we are in the sending state */
|
||||
|
||||
@ -707,6 +718,7 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv,
|
||||
ret = mpfs_write_tx_fifo(buf, packetsize, epno);
|
||||
if (ret != OK)
|
||||
{
|
||||
privep->epstate = USB_EPSTATE_IDLE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -731,6 +743,7 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv,
|
||||
ret = mpfs_write_tx_fifo(buf, nbytes, epno);
|
||||
if (ret != OK)
|
||||
{
|
||||
privep->epstate = USB_EPSTATE_IDLE;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -906,6 +919,7 @@ static int mpfs_req_write(struct mpfs_usbdev_s *priv,
|
||||
ret = mpfs_req_wrsetup(priv, privep, privreq);
|
||||
if (ret != OK)
|
||||
{
|
||||
mpfs_req_complete(privep, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1711,6 +1725,7 @@ static int mpfs_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
||||
req->result = -EINPROGRESS;
|
||||
req->xfrd = 0;
|
||||
privreq->inflight = 0;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Handle IN (device-to-host) requests. NOTE: If the class device is
|
||||
@ -1993,6 +2008,7 @@ static int mpfs_ep_stallresume(struct usbdev_ep_s *ep, bool resume)
|
||||
* Input Parameters:
|
||||
* priv - USB device abstraction
|
||||
* epset - Set of bits, one bit reflects one endpoint
|
||||
* in - If the EP is direction IN
|
||||
*
|
||||
* Returned Value:
|
||||
* Endpoint structure or NULL in case of error
|
||||
@ -2000,7 +2016,7 @@ static int mpfs_ep_stallresume(struct usbdev_ep_s *ep, bool resume)
|
||||
****************************************************************************/
|
||||
|
||||
static inline struct mpfs_ep_s *
|
||||
mpfs_ep_reserve(struct mpfs_usbdev_s *priv, uint8_t epset)
|
||||
mpfs_ep_reserve(struct mpfs_usbdev_s *priv, uint16_t epset, bool in)
|
||||
{
|
||||
struct mpfs_ep_s *privep = NULL;
|
||||
irqstate_t flags;
|
||||
@ -2008,15 +2024,34 @@ mpfs_ep_reserve(struct mpfs_usbdev_s *priv, uint8_t epset)
|
||||
|
||||
flags = enter_critical_section();
|
||||
epset &= priv->epavail;
|
||||
|
||||
if (epset != 0)
|
||||
{
|
||||
/* Select the lowest bit in the set of matching, available endpoints
|
||||
* (skipping EP0)
|
||||
*/
|
||||
|
||||
for (epndx = 1; epndx < MPFS_USB_NENDPOINTS; epndx++)
|
||||
int max;
|
||||
|
||||
if (in)
|
||||
{
|
||||
uint8_t bit = MPFS_EP_BIT(epndx);
|
||||
/* 5, 6, 7 and 8 */
|
||||
|
||||
max = MPFS_USB_NENDPOINTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 1, 2, 3 and 4 */
|
||||
|
||||
max = MPFS_EPIN_START + 1;
|
||||
}
|
||||
|
||||
for (epndx = 1 + (MPFS_USB_NENDPOINTS / 2) * in;
|
||||
epndx < max;
|
||||
epndx++)
|
||||
{
|
||||
uint16_t bit = MPFS_EP_BIT(epndx);
|
||||
|
||||
if ((epset & bit) != 0)
|
||||
{
|
||||
/* Mark the endpoint no longer available */
|
||||
@ -2033,6 +2068,8 @@ mpfs_ep_reserve(struct mpfs_usbdev_s *priv, uint8_t epset)
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGASSERT(privep != NULL);
|
||||
|
||||
leave_critical_section(flags);
|
||||
return privep;
|
||||
}
|
||||
@ -2088,9 +2125,14 @@ static struct usbdev_ep_s *mpfs_allocep(struct usbdev_s *dev, uint8_t epno,
|
||||
epset = MPFS_EP_BIT(epno);
|
||||
}
|
||||
|
||||
if (in)
|
||||
{
|
||||
epset <<= MPFS_EPIN_START;
|
||||
}
|
||||
|
||||
/* Check if the selected endpoint number is available */
|
||||
|
||||
privep = mpfs_ep_reserve(priv, epset);
|
||||
privep = mpfs_ep_reserve(priv, epset, in);
|
||||
if (privep == NULL)
|
||||
{
|
||||
return NULL;
|
||||
@ -2509,6 +2551,7 @@ static void mpfs_ep0_setup(struct mpfs_usbdev_s *priv)
|
||||
uint8_t epno;
|
||||
int nbytes = 0; /* Assume zero-length packet */
|
||||
int ret;
|
||||
int idx;
|
||||
|
||||
/* Terminate any pending requests */
|
||||
|
||||
@ -2570,6 +2613,15 @@ static void mpfs_ep0_setup(struct mpfs_usbdev_s *priv)
|
||||
case USB_REQ_RECIPIENT_ENDPOINT:
|
||||
{
|
||||
epno = USB_EPNO(index.b[LSB]);
|
||||
if (USB_ISEPIN(index.b[LSB]))
|
||||
{
|
||||
idx = epno + MPFS_EPIN_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = epno;
|
||||
}
|
||||
|
||||
usbtrace(TRACE_INTDECODE(MPFS_TRACEINTID_GETSTATUS), epno);
|
||||
if (epno >= MPFS_USB_NENDPOINTS)
|
||||
{
|
||||
@ -2579,7 +2631,7 @@ static void mpfs_ep0_setup(struct mpfs_usbdev_s *priv)
|
||||
}
|
||||
else
|
||||
{
|
||||
privep = &priv->eplist[epno];
|
||||
privep = &priv->eplist[idx];
|
||||
response.w = 0; /* Not stalled */
|
||||
nbytes = 2; /* Response size: 2 bytes */
|
||||
|
||||
@ -2665,7 +2717,16 @@ static void mpfs_ep0_setup(struct mpfs_usbdev_s *priv)
|
||||
if (epno < MPFS_USB_NENDPOINTS && index.b[MSB] == 0 &&
|
||||
value.w == USB_FEATURE_ENDPOINTHALT && len.w == 0)
|
||||
{
|
||||
privep = &priv->eplist[epno];
|
||||
if (USB_ISEPIN(index.b[LSB]))
|
||||
{
|
||||
idx = epno + MPFS_EPIN_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = epno;
|
||||
}
|
||||
|
||||
privep = &priv->eplist[idx];
|
||||
privep->halted = false;
|
||||
|
||||
ret = mpfs_ep_resume(privep);
|
||||
@ -2719,7 +2780,16 @@ static void mpfs_ep0_setup(struct mpfs_usbdev_s *priv)
|
||||
if (epno < MPFS_USB_NENDPOINTS && index.b[MSB] == 0 &&
|
||||
value.w == USB_FEATURE_ENDPOINTHALT && len.w == 0)
|
||||
{
|
||||
privep = &priv->eplist[epno];
|
||||
if (USB_ISEPIN(index.b[LSB]))
|
||||
{
|
||||
idx = epno + MPFS_EPIN_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = epno;
|
||||
}
|
||||
|
||||
privep = &priv->eplist[idx];
|
||||
privep->halted = true;
|
||||
|
||||
ret = mpfs_ep_stall(privep);
|
||||
@ -3035,7 +3105,10 @@ static void mpfs_ep_rx_interrupt(struct mpfs_usbdev_s *priv, int epno)
|
||||
static void mpfs_ep_tx_interrupt(struct mpfs_usbdev_s *priv, int epno)
|
||||
{
|
||||
struct mpfs_ep_s *privep;
|
||||
privep = &priv->eplist[epno];
|
||||
|
||||
privep = &priv->eplist[epno + MPFS_EPIN_START];
|
||||
|
||||
DEBUGASSERT((epno + MPFS_EPIN_START) < MPFS_USB_NENDPOINTS);
|
||||
|
||||
mpfs_putreg8(epno, MPFS_USB_INDEX);
|
||||
|
||||
@ -3080,14 +3153,13 @@ static void mpfs_ep_tx_interrupt(struct mpfs_usbdev_s *priv, int epno)
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - USB device abstraction
|
||||
* epno - The endpoint number
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void mpfs_ctrl_ep_interrupt(struct mpfs_usbdev_s *priv, int epno)
|
||||
static void mpfs_ctrl_ep_interrupt(struct mpfs_usbdev_s *priv)
|
||||
{
|
||||
struct mpfs_ep_s *privep;
|
||||
uint16_t count0;
|
||||
@ -3096,9 +3168,9 @@ static void mpfs_ctrl_ep_interrupt(struct mpfs_usbdev_s *priv, int epno)
|
||||
|
||||
/* Get the endpoint structure */
|
||||
|
||||
privep = &priv->eplist[epno];
|
||||
privep = &priv->eplist[EP0];
|
||||
|
||||
mpfs_putreg8(epno, MPFS_USB_INDEX);
|
||||
mpfs_putreg8(EP0, MPFS_USB_INDEX);
|
||||
|
||||
/* Make sure we're in device mode */
|
||||
|
||||
@ -3198,8 +3270,6 @@ static void mpfs_ctrl_ep_interrupt(struct mpfs_usbdev_s *priv, int epno)
|
||||
{
|
||||
uint16_t rlen;
|
||||
|
||||
DEBUGASSERT(epno == EP0);
|
||||
|
||||
/* Yes.. back to the IDLE state */
|
||||
|
||||
privep->epstate = USB_EPSTATE_IDLE;
|
||||
@ -3311,7 +3381,7 @@ static int mpfs_usb_interrupt(int irq, void *context, void *arg)
|
||||
|
||||
if ((pending_tx_ep & 0x01) != 0)
|
||||
{
|
||||
mpfs_ctrl_ep_interrupt(priv, 0);
|
||||
mpfs_ctrl_ep_interrupt(priv);
|
||||
}
|
||||
|
||||
if (pending_tx_ep != 0)
|
||||
@ -3667,7 +3737,14 @@ static void mpfs_sw_setup(struct mpfs_usbdev_s *priv)
|
||||
|
||||
priv->eplist[epno].ep.ops = &g_epops;
|
||||
priv->eplist[epno].dev = priv;
|
||||
priv->eplist[epno].ep.eplog = epno;
|
||||
if (epno < (MPFS_EPIN_START + 1))
|
||||
{
|
||||
priv->eplist[epno].ep.eplog = epno;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->eplist[epno].ep.eplog = epno - MPFS_EPIN_START;
|
||||
}
|
||||
|
||||
/* We will use a maxpacket size for supported for each endpoint */
|
||||
|
||||
|
@ -252,8 +252,8 @@ void *board_composite_connect(int port, int configid)
|
||||
/* Endpoints */
|
||||
|
||||
dev[0].devinfo.epno[CDCACM_EP_BULKIN_IDX] = 3;
|
||||
dev[0].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 4;
|
||||
dev[0].devinfo.epno[CDCACM_EP_INTIN_IDX] = 5;
|
||||
dev[0].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 3;
|
||||
dev[0].devinfo.epno[CDCACM_EP_INTIN_IDX] = 4;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user