148 lines
3.3 KiB
C
Executable File
148 lines
3.3 KiB
C
Executable File
#include "usb3_drv.h"
|
|
#include "usb3_pcd.h"
|
|
|
|
static void handle_usb_reset_intr(usb3_pcd_t *pcd)
|
|
{
|
|
usb3_pcd_ep_t *ep;
|
|
|
|
/* Clear stall on each EP */
|
|
ep = &pcd->in_ep;
|
|
if (ep->stopped)
|
|
usb3_ep_clear_stall(pcd, ep);
|
|
|
|
ep = &pcd->out_ep;
|
|
if (ep->stopped)
|
|
usb3_ep_clear_stall(pcd, ep);
|
|
|
|
/* Set Device Address to 0 */
|
|
usb3_set_address(pcd, 0);
|
|
|
|
pcd->ltm_enable = 0;
|
|
}
|
|
|
|
static void handle_connect_done_intr(usb3_pcd_t *pcd)
|
|
{
|
|
usb3_pcd_ep_t *ep0 = &pcd->ep0;
|
|
uint32_t diepcfg0, doepcfg0, diepcfg1, doepcfg1;
|
|
usb3_dev_ep_regs_t *ep_reg;
|
|
int speed;
|
|
|
|
ep0->stopped = 0;
|
|
speed = usb3_get_device_speed(pcd);
|
|
pcd->speed = speed;
|
|
|
|
usb3_pcd_set_speed(pcd, speed);
|
|
|
|
/*
|
|
* Set the MPS of EP0 based on the connection speed
|
|
*/
|
|
diepcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
|
diepcfg0 |= USB3_CFG_ACTION_MODIFY << USB3_EPCFG0_CFG_ACTION_SHIFT;
|
|
diepcfg1 = USB3_EPCFG1_XFER_CMPL_BIT | USB3_EPCFG1_XFER_IN_PROG_BIT | USB3_EPCFG1_XFER_NRDY_BIT |
|
|
USB3_EPCFG1_EP_DIR_BIT;
|
|
|
|
doepcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
|
doepcfg0 |= USB3_CFG_ACTION_MODIFY << USB3_EPCFG0_CFG_ACTION_SHIFT;
|
|
doepcfg1 = USB3_EPCFG1_XFER_CMPL_BIT | USB3_EPCFG1_XFER_IN_PROG_BIT | USB3_EPCFG1_XFER_NRDY_BIT;
|
|
|
|
switch (speed) {
|
|
case USB_SPEED_SUPER:
|
|
diepcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT;
|
|
doepcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT;
|
|
break;
|
|
|
|
case USB_SPEED_HIGH:
|
|
case USB_SPEED_FULL:
|
|
diepcfg0 |= 64 << USB3_EPCFG0_MPS_SHIFT;
|
|
doepcfg0 |= 64 << USB3_EPCFG0_MPS_SHIFT;
|
|
break;
|
|
|
|
case USB_SPEED_LOW:
|
|
diepcfg0 |= 8 << USB3_EPCFG0_MPS_SHIFT;
|
|
doepcfg0 |= 8 << USB3_EPCFG0_MPS_SHIFT;
|
|
break;
|
|
}
|
|
|
|
diepcfg0 |= ep0->tx_fifo_num << USB3_EPCFG0_TXFNUM_SHIFT;
|
|
|
|
/* Issue "DEPCFG" command to EP0-OUT */
|
|
ep_reg = &pcd->out_ep_regs[0];
|
|
usb3_dep_cfg(pcd, ep_reg, doepcfg0, doepcfg1, 0);
|
|
|
|
/* Issue "DEPCFG" command to EP0-IN */
|
|
ep_reg = &pcd->in_ep_regs[0];
|
|
usb3_dep_cfg(pcd, ep_reg, diepcfg0, diepcfg1, 0);
|
|
|
|
pcd->state = USB3_STATE_DEFAULT;
|
|
}
|
|
|
|
int usb3_handle_ep_intr(usb3_pcd_t *pcd, uint32_t physep, uint32_t event)
|
|
{
|
|
usb3_pcd_ep_t *ep;
|
|
int epnum, is_in;
|
|
int error = USB_NO_ERR;
|
|
|
|
/* Physical Out EPs are even, physical In EPs are odd */
|
|
is_in = physep & 1;
|
|
epnum = (physep >> 1) & 0xf;
|
|
|
|
/* Get EP pointer */
|
|
if (is_in) {
|
|
ep = usb3_get_in_ep(pcd, epnum);
|
|
} else {
|
|
ep = usb3_get_out_ep(pcd, epnum);
|
|
}
|
|
//printf("\n##########%s,%d,event=0x%x\n",__func__,__LINE__,event);
|
|
switch (event & USB3_DEPEVT_INTTYPE_BITS) {
|
|
case USB3_DEPEVT_XFER_CMPL << USB3_DEPEVT_INTTYPE_SHIFT:
|
|
ep->xfer_started = 0;
|
|
|
|
/* Complete the transfer */
|
|
if (0 == epnum) {
|
|
usb3_os_handle_ep0(pcd, event);
|
|
} else {
|
|
//printf("\n##########%s,%d,event=0x%x\n",__func__,__LINE__,event);
|
|
error = usb3_ep_complete_request(pcd, ep, event);
|
|
}
|
|
break;
|
|
|
|
case USB3_DEPEVT_XFER_NRDY << USB3_DEPEVT_INTTYPE_SHIFT:
|
|
if (0 == epnum) {
|
|
switch (pcd->ep0state) {
|
|
case EP0_IN_WAIT_NRDY:
|
|
if (is_in) {
|
|
usb3_os_handle_ep0(pcd, event);
|
|
}
|
|
break;
|
|
case EP0_OUT_WAIT_NRDY:
|
|
if (!is_in) {
|
|
usb3_os_handle_ep0(pcd, event);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
void usb3_handle_dev_intr(usb3_pcd_t *pcd, uint32_t event)
|
|
{
|
|
uint32_t dint = (event >> USB3_DEVT_SHIFT) &
|
|
(USB3_DEVT_BITS >> USB3_DEVT_SHIFT);
|
|
|
|
switch (dint) {
|
|
case USB3_DEVT_USBRESET:
|
|
handle_usb_reset_intr(pcd);
|
|
break;
|
|
|
|
case USB3_DEVT_CONNDONE:
|
|
handle_connect_done_intr(pcd);
|
|
break;
|
|
}
|
|
}
|
|
|