optimise musb dcd and hcd driver

This commit is contained in:
sakumisu
2022-06-04 21:11:16 +08:00
parent 38db93fc7e
commit 8866d9aab4
2 changed files with 61 additions and 51 deletions

View File

@@ -15,9 +15,7 @@
#endif #endif
#ifndef USBD_IRQHandler #ifndef USBD_IRQHandler
#define USBD_IRQHandler USB_INT_Handler //use actual usb irq name instead #define USBD_IRQHandler USBD_IRQHandler //use actual usb irq name instead
void USBD_IRQHandler(int, void *);
#endif #endif
#define MUSB_FADDR_OFFSET 0x98 #define MUSB_FADDR_OFFSET 0x98
@@ -652,11 +650,7 @@ static void handle_ep0(void)
} }
} }
#ifdef CONFIG_USB_MUSB_SUNXI
void USBD_IRQHandler(int irq, void *args)
#else
void USBD_IRQHandler(void) void USBD_IRQHandler(void)
#endif
{ {
uint32_t is; uint32_t is;
uint32_t txis; uint32_t txis;

View File

@@ -15,8 +15,7 @@
#endif #endif
#ifndef USBH_IRQHandler #ifndef USBH_IRQHandler
#define USBH_IRQHandler USB_INT_Handler //use actual usb irq name instead #define USBH_IRQHandler USBH_IRQHandler //use actual usb irq name instead
void USBH_IRQHandler(int, void *);
#endif #endif
#define MUSB_FADDR_OFFSET 0x98 #define MUSB_FADDR_OFFSET 0x98
@@ -165,7 +164,6 @@ struct usb_musb_chan {
}; };
struct usb_musb_priv { struct usb_musb_priv {
volatile bool connected; /* Connected to device */
struct usb_musb_chan chan[CONIFG_USB_MUSB_EP_NUM][CONFIG_USBHOST_PIPE_NUM]; struct usb_musb_chan chan[CONIFG_USB_MUSB_EP_NUM][CONFIG_USBHOST_PIPE_NUM];
volatile struct usb_musb_chan *active_chan[CONIFG_USB_MUSB_EP_NUM]; volatile struct usb_musb_chan *active_chan[CONIFG_USB_MUSB_EP_NUM];
usb_osal_mutex_t exclsem[CONIFG_USB_MUSB_EP_NUM]; /* Support mutually exclusive access */ usb_osal_mutex_t exclsem[CONIFG_USB_MUSB_EP_NUM]; /* Support mutually exclusive access */
@@ -330,7 +328,7 @@ static int usb_musb_chan_waitsetup(struct usb_musb_chan *chan)
/* Is the device still connected? */ /* Is the device still connected? */
if (g_usbhost.connected) { if (usbh_get_port_connect_status(0)) {
/* Yes.. then set waiter to indicate that we expect to be informed /* Yes.. then set waiter to indicate that we expect to be informed
* when either (1) the device is disconnected, or (2) the transfer * when either (1) the device is disconnected, or (2) the transfer
* completed. * completed.
@@ -373,7 +371,7 @@ static int usb_musb_chan_asynchsetup(struct usb_musb_chan *chan, usbh_asynch_cal
flags = usb_osal_enter_critical_section(); flags = usb_osal_enter_critical_section();
/* Is the device still connected? */ /* Is the device still connected? */
if (g_usbhost.connected) { if (usbh_get_port_connect_status(0)) {
/* Yes.. then set waiter to indicate that we expect to be informed /* Yes.. then set waiter to indicate that we expect to be informed
* when either (1) the device is disconnected, or (2) the transfer * when either (1) the device is disconnected, or (2) the transfer
* completed. * completed.
@@ -484,11 +482,11 @@ int usb_hc_init(void)
{ {
uint8_t regval; uint8_t regval;
uint32_t fifo_offset = 0; uint32_t fifo_offset = 0;
g_usbhost.connected = 0;
usb_hc_low_level_init(); usb_hc_low_level_init();
USBC_SelectActiveEp(0); USBC_SelectActiveEp(0);
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64; HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64;
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = 0; HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = 0;
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64; HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64;
@@ -530,7 +528,12 @@ int usb_hc_init(void)
bool usbh_get_port_connect_status(const uint8_t port) bool usbh_get_port_connect_status(const uint8_t port)
{ {
return g_usbhost.connected; if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_FSDEV)
return true;
if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_LSDEV)
return true;
return false;
} }
int usbh_reset_port(const uint8_t port) int usbh_reset_port(const uint8_t port)
@@ -607,8 +610,6 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
chan->waitsem = usb_osal_sem_create(0); chan->waitsem = usb_osal_sem_create(0);
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
*ep = (usbh_epinfo_t)chan; *ep = (usbh_epinfo_t)chan;
} else { } else {
chidx = usb_musb_chan_alloc(ep_idx); chidx = usb_musb_chan_alloc(ep_idx);
@@ -1045,24 +1046,37 @@ int usb_ep_cancel(usbh_epinfo_t ep)
void handle_ep0(void) void handle_ep0(void)
{ {
uint8_t ep0_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET); uint8_t ep0_status;
struct usb_musb_chan *chan; struct usb_musb_chan *chan;
int result = 0;
chan = (struct usb_musb_chan *)g_usbhost.active_chan[0]; chan = (struct usb_musb_chan *)g_usbhost.active_chan[0];
USBC_SelectActiveEp(0);
ep0_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET);
if (ep0_status & USB_CSRL0_STALLED) {
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALLED;
usb_ep0_state = USB_EP0_STATE_SETUP;
result = -EPERM;
goto chan_wait;
}
if (ep0_status & USB_CSRL0_ERROR) { if (ep0_status & USB_CSRL0_ERROR) {
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_ERROR; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_ERROR;
usb_musb_fifo_flush(0); usb_musb_fifo_flush(0);
usb_ep0_state = USB_EP0_STATE_SETUP; usb_ep0_state = USB_EP0_STATE_SETUP;
chan->result = -EIO; result = -EIO;
goto chan_wait; goto chan_wait;
} }
if (ep0_status & USB_CSRL0_STALL) { if (ep0_status & USB_CSRL0_STALL) {
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALL; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALL;
usb_ep0_state = USB_EP0_STATE_SETUP; usb_ep0_state = USB_EP0_STATE_SETUP;
chan->result = -EPERM; result = -EPERM;
goto chan_wait; goto chan_wait;
} }
switch (usb_ep0_state) { switch (usb_ep0_state) {
case USB_EP0_STATE_SETUP: case USB_EP0_STATE_SETUP:
break; break;
@@ -1097,7 +1111,7 @@ void handle_ep0(void)
break; break;
case USB_EP0_STATE_OUT_STATUS: case USB_EP0_STATE_OUT_STATUS:
usb_ep0_state = USB_EP0_STATE_SETUP; usb_ep0_state = USB_EP0_STATE_SETUP;
chan->result = 0; result = 0;
goto chan_wait; goto chan_wait;
case USB_EP0_STATE_IN_STATUS_C: case USB_EP0_STATE_IN_STATUS_C:
if (ep0_status & (USB_CSRL0_RXRDY | USB_CSRL0_STATUS)) { if (ep0_status & (USB_CSRL0_RXRDY | USB_CSRL0_STATUS)) {
@@ -1105,7 +1119,7 @@ void handle_ep0(void)
} }
usb_ep0_state = USB_EP0_STATE_SETUP; usb_ep0_state = USB_EP0_STATE_SETUP;
chan->result = 0; result = 0;
goto chan_wait; goto chan_wait;
break; break;
@@ -1139,23 +1153,23 @@ void handle_ep0(void)
} }
return; return;
chan_wait: chan_wait:
usb_musb_chan_wakeup(chan); if (chan) {
chan->result = result;
usb_musb_chan_wakeup(chan);
}
} }
#ifdef CONFIG_USB_MUSB_SUNXI
void USBH_IRQHandler(int irq, void *arg)
#else
void USBH_IRQHandler(void) void USBH_IRQHandler(void)
#endif
{ {
uint32_t is; uint32_t is;
uint32_t txis; uint32_t txis;
uint32_t rxis; uint32_t rxis;
uint8_t ep_csrl_status; uint8_t ep_csrl_status;
uint8_t ep_csrh_status; // uint8_t ep_csrh_status;
struct usb_musb_chan *chan; struct usb_musb_chan *chan;
uint8_t ep_idx; uint8_t ep_idx;
uint8_t old_ep_idx; uint8_t old_ep_idx;
int result = 0;
is = HWREGB(USB_BASE + MUSB_IS_OFFSET); is = HWREGB(USB_BASE + MUSB_IS_OFFSET);
txis = HWREGH(USB_BASE + MUSB_TXIS_OFFSET); txis = HWREGH(USB_BASE + MUSB_TXIS_OFFSET);
@@ -1166,16 +1180,13 @@ void USBH_IRQHandler(void)
old_ep_idx = USBC_GetActiveEp(); old_ep_idx = USBC_GetActiveEp();
if (is & USB_IS_CONN) { if (is & USB_IS_CONN) {
if (!g_usbhost.connected) { if (usbh_get_port_connect_status(0)) {
g_usbhost.connected = true;
usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1);
} }
} }
if (is & USB_IS_DISCON) { if (is & USB_IS_DISCON) {
if (g_usbhost.connected) { if (usbh_get_port_connect_status(0) == false) {
g_usbhost.connected = false;
for (uint8_t ep_index = 0; ep_index < CONIFG_USB_MUSB_EP_NUM; ep_index++) { for (uint8_t ep_index = 0; ep_index < CONIFG_USB_MUSB_EP_NUM; ep_index++) {
if (g_usbhost.active_chan[ep_index]) { if (g_usbhost.active_chan[ep_index]) {
chan = (struct usb_musb_chan *)g_usbhost.active_chan[ep_index]; chan = (struct usb_musb_chan *)g_usbhost.active_chan[ep_index];
@@ -1211,7 +1222,6 @@ void USBH_IRQHandler(void)
if (txis & USB_TXIE_EP0) { if (txis & USB_TXIE_EP0) {
txis &= ~USB_TXIE_EP0; txis &= ~USB_TXIE_EP0;
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = USB_TXIE_EP0; HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = USB_TXIE_EP0;
USBC_SelectActiveEp(0);
handle_ep0(); handle_ep0();
} }
@@ -1225,20 +1235,19 @@ void USBH_IRQHandler(void)
USBC_SelectActiveEp(ep_idx); USBC_SelectActiveEp(ep_idx);
ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET); ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET);
ep_csrh_status = HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET);
if (ep_csrl_status & USB_TXCSRL1_ERROR) { if (ep_csrl_status & USB_TXCSRL1_ERROR) {
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_ERROR; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_ERROR;
chan->result = -EIO; result = -EIO;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else if (ep_csrl_status & USB_TXCSRL1_NAKTO) { } else if (ep_csrl_status & USB_TXCSRL1_NAKTO) {
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_NAKTO; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_NAKTO;
chan->result = -EBUSY; result = -EBUSY;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else if (ep_csrl_status & USB_TXCSRL1_STALL) { } else if (ep_csrl_status & USB_TXCSRL1_STALL) {
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_STALL; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_STALL;
chan->result = -EPERM; result = -EPERM;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else { } else {
uint32_t size = chan->buflen; uint32_t size = chan->buflen;
@@ -1251,8 +1260,8 @@ void USBH_IRQHandler(void)
chan->xfrd += size; chan->xfrd += size;
if (chan->buflen == 0) { if (chan->buflen == 0) {
chan->result = 0; result = 0;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else { } else {
usb_musb_write_packet(ep_idx, chan->buffer, size); usb_musb_write_packet(ep_idx, chan->buffer, size);
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
@@ -1271,20 +1280,20 @@ void USBH_IRQHandler(void)
USBC_SelectActiveEp(ep_idx); USBC_SelectActiveEp(ep_idx);
ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET); ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET);
ep_csrh_status = HWREGB(USB_BASE + MUSB_IND_RXCSRH_OFFSET); //ep_csrh_status = HWREGB(USB_BASE + MUSB_IND_RXCSRH_OFFSET); // todo:for iso transfer
if (ep_csrl_status & USB_RXCSRL1_ERROR) { if (ep_csrl_status & USB_RXCSRL1_ERROR) {
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_ERROR; HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_ERROR;
chan->result = -EIO; result = -EIO;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else if (ep_csrl_status & USB_RXCSRL1_NAKTO) { } else if (ep_csrl_status & USB_RXCSRL1_NAKTO) {
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_NAKTO; HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_NAKTO;
chan->result = -EBUSY; result = -EBUSY;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else if (ep_csrl_status & USB_RXCSRL1_STALL) { } else if (ep_csrl_status & USB_RXCSRL1_STALL) {
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_STALL; HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_STALL;
chan->result = -EPERM; result = -EPERM;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else if (ep_csrl_status & USB_RXCSRL1_RXRDY) { } else if (ep_csrl_status & USB_RXCSRL1_RXRDY) {
uint32_t size = chan->buflen; uint32_t size = chan->buflen;
if (size > chan->mps) { if (size > chan->mps) {
@@ -1300,12 +1309,19 @@ void USBH_IRQHandler(void)
chan->buflen -= size; chan->buflen -= size;
chan->xfrd += size; chan->xfrd += size;
if ((size < chan->mps) || (chan->buflen == 0)) { if ((size < chan->mps) || (chan->buflen == 0)) {
chan->result = 0; result = 0;
usb_musb_chan_wakeup(chan); goto chan_wait;
} else { } else {
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT;
} }
} }
} }
USBC_SelectActiveEp(old_ep_idx); USBC_SelectActiveEp(old_ep_idx);
return;
chan_wait:
USBC_SelectActiveEp(old_ep_idx);
if (chan) {
chan->result = result;
usb_musb_chan_wakeup(chan);
}
} }