usb-s3c6400: store endpoint status per direction
Just as like all other drivers do Confirmed to work on Nano2g
This commit is contained in:
parent
d9f1f86a65
commit
7b28711f6c
1 changed files with 36 additions and 33 deletions
|
@ -515,7 +515,7 @@ int usb_drv_send(int ep, void *ptr, int len)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static struct ep_type endpoints[USB_NUM_ENDPOINTS];
|
static struct ep_type endpoints[USB_NUM_ENDPOINTS][2];
|
||||||
|
|
||||||
/* USB control requests may be up to 64 bytes in size.
|
/* USB control requests may be up to 64 bytes in size.
|
||||||
Even though we never use anything more than the 8 header bytes,
|
Even though we never use anything more than the 8 header bytes,
|
||||||
|
@ -535,15 +535,15 @@ static volatile bool plugged = false;
|
||||||
|
|
||||||
static void reset_endpoints(int reinit)
|
static void reset_endpoints(int reinit)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
for (unsigned i = 0; i < sizeof(endpoints)/(2*sizeof(struct ep_type)); i++)
|
||||||
for (i = 0; i < sizeof(endpoints)/sizeof(struct ep_type); i++)
|
for (unsigned dir = 0; dir < 2; dir++)
|
||||||
{
|
{
|
||||||
if (reinit) endpoints[i].active = false;
|
if (reinit) endpoints[i][dir].active = false;
|
||||||
endpoints[i].busy = false;
|
endpoints[i][dir].busy = false;
|
||||||
endpoints[i].status = -1;
|
endpoints[i][dir].status = -1;
|
||||||
endpoints[i].done = true;
|
endpoints[i][dir].done = true;
|
||||||
semaphore_release(&endpoints[i].complete);
|
semaphore_release(&endpoints[i][dir].complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEPCTL(0, false) = DEPCTL_usbactep | (1 << DEPCTL_nextep_bitp);
|
DEPCTL(0, false) = DEPCTL_usbactep | (1 << DEPCTL_nextep_bitp);
|
||||||
DEPCTL(0, true) = DEPCTL_usbactep;
|
DEPCTL(0, true) = DEPCTL_usbactep;
|
||||||
|
@ -575,26 +575,28 @@ static void reset_endpoints(int reinit)
|
||||||
int usb_drv_request_endpoint(int type, int dir)
|
int usb_drv_request_endpoint(int type, int dir)
|
||||||
{
|
{
|
||||||
bool out = dir == USB_DIR_OUT;
|
bool out = dir == USB_DIR_OUT;
|
||||||
for(size_t ep = out ? 2 : 1; ep < USB_NUM_ENDPOINTS; ep += 2)
|
for(size_t ep = out ? 2 : 1; ep < USB_NUM_ENDPOINTS; ep += 2) {
|
||||||
if (!endpoints[ep].active)
|
if (!endpoints[ep][out ? DIR_OUT : DIR_IN].active)
|
||||||
{
|
{
|
||||||
endpoints[ep].active = true;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].active = true;
|
||||||
DEPCTL(ep, out) = (DEPCTL(ep, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp)) |
|
DEPCTL(ep, out) = (DEPCTL(ep, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp)) |
|
||||||
(type << DEPCTL_eptype_bitp);
|
(type << DEPCTL_eptype_bitp);
|
||||||
return ep | dir;
|
return ep | dir;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_drv_release_endpoint(int ep)
|
void usb_drv_release_endpoint(int ep)
|
||||||
{
|
{
|
||||||
|
bool out = !(ep & USB_DIR_IN);
|
||||||
ep = ep & 0x7f;
|
ep = ep & 0x7f;
|
||||||
|
|
||||||
if (ep < 1 || ep > USB_NUM_ENDPOINTS)
|
if (ep < 1 || ep > USB_NUM_ENDPOINTS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
endpoints[ep].active = false;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_reset(void)
|
static void usb_reset(void)
|
||||||
|
@ -646,14 +648,14 @@ static void handle_ep_int(bool out)
|
||||||
{
|
{
|
||||||
if (!out) inflight = false;
|
if (!out) inflight = false;
|
||||||
commit_discard_dcache();
|
commit_discard_dcache();
|
||||||
int bytes = endpoints[ep].size - (DEPTSIZ(ep, out) & (DEPTSIZ_xfersize_bits < DEPTSIZ_xfersize_bitp));
|
int bytes = endpoints[ep][out ? DIR_OUT : DIR_IN].size - (DEPTSIZ(ep, out) & (DEPTSIZ_xfersize_bits < DEPTSIZ_xfersize_bitp));
|
||||||
if (endpoints[ep].busy)
|
if (endpoints[ep][out ? DIR_OUT : DIR_IN].busy)
|
||||||
{
|
{
|
||||||
endpoints[ep].busy = false;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].busy = false;
|
||||||
endpoints[ep].status = 0;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].status = 0;
|
||||||
endpoints[ep].done = true;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].done = true;
|
||||||
usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, bytes);
|
usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, bytes);
|
||||||
semaphore_release(&endpoints[ep].complete);
|
semaphore_release(&endpoints[ep][out ? DIR_OUT : DIR_IN].complete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,12 +664,12 @@ static void handle_ep_int(bool out)
|
||||||
|
|
||||||
if (!out && (epints & DIEPINT_timeout))
|
if (!out && (epints & DIEPINT_timeout))
|
||||||
{
|
{
|
||||||
if (endpoints[ep].busy)
|
if (endpoints[ep][out ? DIR_OUT : DIR_IN].busy)
|
||||||
{
|
{
|
||||||
endpoints[ep].busy = false;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].busy = false;
|
||||||
endpoints[ep].status = 1;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].status = 1;
|
||||||
endpoints[ep].done = true;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].done = true;
|
||||||
semaphore_release(&endpoints[ep].complete);
|
semaphore_release(&endpoints[ep][out ? DIR_OUT : DIR_IN].complete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,8 +737,8 @@ static void ep_transfer(int ep, void *ptr, int len, bool out)
|
||||||
/* disable interrupts to avoid any race */
|
/* disable interrupts to avoid any race */
|
||||||
int oldlevel = disable_irq_save();
|
int oldlevel = disable_irq_save();
|
||||||
if (!out) inflight = true;
|
if (!out) inflight = true;
|
||||||
endpoints[ep].busy = true;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].busy = true;
|
||||||
endpoints[ep].size = len;
|
endpoints[ep][out ? DIR_OUT : DIR_IN].size = len;
|
||||||
|
|
||||||
if (out) DEPCTL(ep, out) &= ~DEPCTL_stall;
|
if (out) DEPCTL(ep, out) &= ~DEPCTL_stall;
|
||||||
|
|
||||||
|
@ -762,11 +764,11 @@ static void ep_transfer(int ep, void *ptr, int len, bool out)
|
||||||
int usb_drv_send(int endpoint, void *ptr, int length)
|
int usb_drv_send(int endpoint, void *ptr, int length)
|
||||||
{
|
{
|
||||||
endpoint = EP_NUM(endpoint);
|
endpoint = EP_NUM(endpoint);
|
||||||
endpoints[endpoint].done = false;
|
endpoints[endpoint][1].done = false;
|
||||||
ep_transfer(endpoint, ptr, length, false);
|
ep_transfer(endpoint, ptr, length, false);
|
||||||
while (!endpoints[endpoint].done && endpoints[endpoint].busy)
|
while (!endpoints[endpoint][1].done && endpoints[endpoint][1].busy)
|
||||||
semaphore_wait(&endpoints[endpoint].complete, TIMEOUT_BLOCK);
|
semaphore_wait(&endpoints[endpoint][1].complete, TIMEOUT_BLOCK);
|
||||||
return endpoints[endpoint].status;
|
return endpoints[endpoint][1].status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_drv_cancel_all_transfers(void)
|
void usb_drv_cancel_all_transfers(void)
|
||||||
|
@ -778,8 +780,9 @@ void usb_drv_cancel_all_transfers(void)
|
||||||
|
|
||||||
void usb_drv_init(void)
|
void usb_drv_init(void)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(endpoints)/sizeof(struct ep_type); i++)
|
for (unsigned i = 0; i < sizeof(endpoints)/(2*sizeof(struct ep_type)); i++)
|
||||||
semaphore_init(&endpoints[i].complete, 1, 0);
|
for (unsigned dir = 0; dir < 2; dir++)
|
||||||
|
semaphore_init(&endpoints[i][dir].complete, 1, 0);
|
||||||
|
|
||||||
/* Enable USB clock */
|
/* Enable USB clock */
|
||||||
#if CONFIG_CPU==S5L8701
|
#if CONFIG_CPU==S5L8701
|
||||||
|
|
Loading…
Reference in a new issue