usb_storage seems to be working now, enable USE_ROCKBOX_USB on C200v2, other AMSv1 untested.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27039 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
831707d991
commit
072c0a15cb
4 changed files with 121 additions and 30 deletions
|
@ -173,8 +173,9 @@
|
|||
|
||||
/* enable these for the experimental usb stack */
|
||||
#define HAVE_USBSTACK
|
||||
#define USB_HANDLED_BY_OF
|
||||
//#define USE_ROCKBOX_USB
|
||||
//#define USB_HANDLED_BY_OF
|
||||
#define USE_ROCKBOX_USB
|
||||
//#define USB_ENABLE_SERIAL
|
||||
#define USB_VENDOR_ID 0x0781
|
||||
#define USB_PRODUCT_ID 0x7452
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ void usb_attach(void)
|
|||
usb_enable(true);
|
||||
}
|
||||
|
||||
static void usb_tick(void);
|
||||
|
||||
static void usb_phy_on(void)
|
||||
{
|
||||
/* PHY clock */
|
||||
|
@ -174,10 +176,20 @@ static void reset_endpoints(int init)
|
|||
int mps = i == 0 ? 64 : (usb_drv_port_speed() ? 512 : 64);
|
||||
|
||||
if (init) {
|
||||
if (endpoints[i][0].state & EP_STATE_BUSY) {
|
||||
if (endpoints[i][0].state & EP_STATE_ASYNC) {
|
||||
endpoints[i][0].rc = -1;
|
||||
wakeup_signal(&endpoints[i][0].complete);
|
||||
} else {
|
||||
usb_core_transfer_complete(i, USB_DIR_IN, -1, 0);
|
||||
}
|
||||
}
|
||||
endpoints[i][0].state = 0;
|
||||
wakeup_init(&endpoints[i][0].complete);
|
||||
|
||||
if (i != 2) { /* Skip the OUT EP0 alias */
|
||||
if (endpoints[i][1].state & EP_STATE_BUSY)
|
||||
usb_core_transfer_complete(i, USB_DIR_OUT, -1, 0);
|
||||
endpoints[i][1].state = 0;
|
||||
wakeup_init(&endpoints[i][1].complete);
|
||||
USB_OEP_SUP_PTR(i) = 0;
|
||||
|
@ -189,15 +201,15 @@ static void reset_endpoints(int init)
|
|||
USB_IEP_MPS (i) = mps; /* in bytes */
|
||||
/* We don't care about the 'IN token received' event */
|
||||
USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */
|
||||
USB_IEP_TXFSIZE (i) = mps/2; /* in dwords => mps*2 bytes */
|
||||
USB_IEP_TXFSIZE (i) = mps/4; /* in dwords => mps*2 bytes */
|
||||
USB_IEP_STS (i) = 0xffffffff; /* clear status */
|
||||
USB_IEP_DESC_PTR(i) = 0;
|
||||
|
||||
if (i != 2) { /* Skip the OUT EP0 alias */
|
||||
dma_desc_init(i, 1);
|
||||
USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
|
||||
USB_OEP_MPS (i) = (mps/2 << 23) | mps;
|
||||
USB_OEP_STS_MASK(i) = 0x0000; /* OF: 0x1800 */
|
||||
USB_OEP_MPS (i) = (mps/4 << 16) | mps;
|
||||
USB_OEP_STS_MASK(i) = USB_EP_STAT_BNA; /* OF: 0x1800 */
|
||||
USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */
|
||||
USB_OEP_STS (i) = 0xffffffff; /* clear status */
|
||||
USB_OEP_DESC_PTR(i) = 0;
|
||||
|
@ -281,10 +293,12 @@ void usb_drv_init(void)
|
|||
| USB_GPIO_HS_INTR
|
||||
| USB_GPIO_CLK_SEL10; /* 0x06180000; */
|
||||
|
||||
tick_add_task(usb_tick);
|
||||
}
|
||||
|
||||
void usb_drv_exit(void)
|
||||
{
|
||||
tick_remove_task(usb_tick);
|
||||
USB_DEV_CTRL |= (1<<10); /* soft disconnect */
|
||||
/*
|
||||
* mask all interrupts _before_ writing to VIC_INT_EN_CLEAR,
|
||||
|
@ -383,16 +397,20 @@ int usb_drv_recv(int ep, void *ptr, int len)
|
|||
ep &= 0x7f;
|
||||
logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len);
|
||||
|
||||
if (len > USB_DMA_DESC_RXTX_BYTES)
|
||||
panicf("usb_recv: len=%d > %d", len, USB_DMA_DESC_RXTX_BYTES);
|
||||
|
||||
if ((int)ptr & 31) {
|
||||
logf("addr %08x not aligned!\n", (int)ptr);
|
||||
}
|
||||
|
||||
endpoints[ep][1].state |= EP_STATE_BUSY;
|
||||
endpoints[ep][1].len = len;
|
||||
endpoints[ep][1].rc = -1;
|
||||
endpoints[ep][1].rc = -1;
|
||||
endpoints[ep][1].buf = ptr;
|
||||
|
||||
/* remove data buffer from cache */
|
||||
dump_dcache_range(ptr, len);
|
||||
invalidate_dcache();
|
||||
|
||||
/* DMA setup */
|
||||
uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
|
||||
|
@ -406,7 +424,27 @@ int usb_drv_recv(int ep, void *ptr, int len)
|
|||
}
|
||||
USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1];
|
||||
USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */
|
||||
USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK;
|
||||
|
||||
/* Make sure receive DMA is on */
|
||||
if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
|
||||
logf("enabling receive DMA\n");
|
||||
USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
|
||||
if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE))
|
||||
logf("failed to enable!\n");
|
||||
}
|
||||
|
||||
USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
|
||||
|
||||
if (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
|
||||
int i = 0;
|
||||
logf("CNAK fail? CTRL=%x\n", (int)USB_OEP_CTRL(ep));
|
||||
while (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
|
||||
USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
|
||||
i++;
|
||||
}
|
||||
if (i>2)
|
||||
panicf("CNAK needed %d retries\n", i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -443,7 +481,7 @@ void ep_send(int ep, void *ptr, int len)
|
|||
endpoints[ep][0].rc = -1;
|
||||
|
||||
/* Make sure data is committed to memory */
|
||||
clean_dcache_range(ptr, len);
|
||||
clean_dcache();
|
||||
|
||||
logf("xx%s\n", make_hex(ptr, len));
|
||||
|
||||
|
@ -493,8 +531,9 @@ static void handle_in_ep(int ep)
|
|||
USB_IEP_STS(ep) = ep_sts; /* ack */
|
||||
|
||||
if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
|
||||
logf("ep%d IN, status %x (BNA)\n", ep, ep_sts);
|
||||
panicf("ep%d IN 0x%x (BNA)", ep, ep_sts);
|
||||
int ctrl = USB_IEP_CTRL(ep);
|
||||
logf("ep%d IN, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
|
||||
panicf("ep%d IN 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
|
||||
}
|
||||
|
||||
if (ep_sts & USB_EP_STAT_TDC) {
|
||||
|
@ -517,17 +556,12 @@ static void handle_in_ep(int ep)
|
|||
logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state);
|
||||
panicf("ep%d IN 0x%x", ep, ep_sts);
|
||||
}
|
||||
|
||||
/* HW automatically disables RDE, re-enable it */
|
||||
/* But this an IN ep, I wonder... */
|
||||
USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
|
||||
}
|
||||
|
||||
static void handle_out_ep(int ep)
|
||||
{
|
||||
struct usb_ctrlrequest *req = (void*)AS3525_UNCACHED_ADDR(&setup_desc->data1);
|
||||
int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep);
|
||||
struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
|
||||
|
||||
if (ep > 3)
|
||||
panicf("out_ep > 3!?");
|
||||
|
@ -535,11 +569,14 @@ static void handle_out_ep(int ep)
|
|||
USB_OEP_STS(ep) = ep_sts; /* ACK */
|
||||
|
||||
if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
|
||||
logf("ep%d OUT, status %x (BNA)\n", ep, ep_sts);
|
||||
panicf("ep%d OUT 0x%x (BNA)", ep, ep_sts);
|
||||
int ctrl = USB_OEP_CTRL(ep);
|
||||
logf("ep%d OUT, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
|
||||
panicf("ep%d OUT 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
|
||||
ep_sts &= ~USB_EP_STAT_BNA;
|
||||
}
|
||||
|
||||
if (ep_sts & USB_EP_STAT_OUT_RCVD) {
|
||||
struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
|
||||
int dma_sts = uc_desc->status;
|
||||
int dma_len = dma_sts & 0xffff;
|
||||
|
||||
|
@ -553,7 +590,7 @@ static void handle_out_ep(int ep)
|
|||
dump_dcache_range(uc_desc->data_ptr, dma_len);
|
||||
} else{
|
||||
logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep,
|
||||
dma_mst, dma_frm);
|
||||
dma_sts & 0xf8000000, (dma_sts >> 16) & 0x7ff);
|
||||
}
|
||||
|
||||
if (endpoints[ep][1].state & EP_STATE_BUSY) {
|
||||
|
@ -565,7 +602,6 @@ static void handle_out_ep(int ep)
|
|||
}
|
||||
|
||||
USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */
|
||||
|
||||
ep_sts &= ~USB_EP_STAT_OUT_RCVD;
|
||||
}
|
||||
|
||||
|
@ -592,9 +628,58 @@ static void handle_out_ep(int ep)
|
|||
panicf("ep%d OUT 0x%x", ep, ep_sts);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* HW automatically disables RDE, re-enable it */
|
||||
/* THEORY: Because we only set up one DMA buffer... */
|
||||
USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
|
||||
#endif
|
||||
|
||||
if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
|
||||
logf("receive DMA is disabled!\n");
|
||||
//USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a simplified version of the timer based RDE enable from
|
||||
* the Linux amd5536udc.c driver.
|
||||
* We need this because of the following hw issue:
|
||||
* The usb_storage buffer is 63KB, but Linux sends 120KB.
|
||||
* We get the first part, but upon re-enabling receive dma we
|
||||
* get a 'buffer not available' error from the hardware, since
|
||||
* we haven't gotten the next usb_drv_recv() from the stack yet.
|
||||
* It seems the NAK bit is ignored here and the HW tries to dma
|
||||
* the incoming data anyway.
|
||||
* In theory I think the BNA error should be recoverable, but
|
||||
* I haven't figured out how to do that yet and this approach seems
|
||||
* to work for now.
|
||||
*/
|
||||
static void usb_tick(void)
|
||||
{
|
||||
static int rde_timer = 0;
|
||||
static int rde_fails = 0;
|
||||
|
||||
if (USB_DEV_CTRL & USB_DEV_CTRL_RDE)
|
||||
return;
|
||||
|
||||
if (!(USB_DEV_STS & USB_DEV_STS_RXF_EMPTY)) {
|
||||
if (rde_timer == 0)
|
||||
logf("usb_tick: fifo got filled\n");
|
||||
rde_timer++;
|
||||
}
|
||||
|
||||
if (rde_timer > 2) {
|
||||
logf("usb_tick: re-enabling RDE\n");
|
||||
USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
|
||||
rde_timer = 0;
|
||||
if (USB_DEV_CTRL & USB_DEV_CTRL_RDE) {
|
||||
rde_fails = 0;
|
||||
} else {
|
||||
rde_fails++;
|
||||
if (rde_fails > 3)
|
||||
panicf("usb_tick: failed to set RDE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* interrupt service routine */
|
||||
|
@ -696,12 +781,6 @@ void INT_USB(void)
|
|||
if (intr)
|
||||
panicf("usb devirq 0x%x", intr);
|
||||
}
|
||||
|
||||
if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
|
||||
logf("re-enabling receive DMA\n");
|
||||
USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* (not essential? , not implemented in usb-tcc.c) */
|
||||
|
|
|
@ -237,6 +237,7 @@ typedef struct {
|
|||
#define USB_DEV_INTR_SOF 0x00000020 /* SOF seen on bus */
|
||||
#define USB_DEV_INTR_ENUM_DONE 0x00000040 /* usb speed enum done */
|
||||
#define USB_DEV_INTR_SVC 0x00000080 /* USB_DEV_STS changed */
|
||||
#define USB_DEV_INTR_MYSTERY 0x00000200 /* Unknown, maybe Host Error */
|
||||
|
||||
/* EP Control Register Fields */
|
||||
#define USB_EP_CTRL_STALL 0x00000001
|
||||
|
|
|
@ -59,8 +59,13 @@
|
|||
#ifdef USB_READ_BUFFER_SIZE
|
||||
#define READ_BUFFER_SIZE USB_READ_BUFFER_SIZE
|
||||
#else
|
||||
#if CONFIG_CPU == AS3525
|
||||
/* We'd need to implement multidescriptor dma for sizes >65535 */
|
||||
#define READ_BUFFER_SIZE (1024*63)
|
||||
#else
|
||||
#define READ_BUFFER_SIZE (1024*64)
|
||||
#endif
|
||||
#endif /* CONFIG_CPU == AS3525 */
|
||||
#endif /* USB_READ_BUFFER_SIZE */
|
||||
|
||||
#define MAX_CBW_SIZE 1024
|
||||
|
||||
|
@ -68,11 +73,16 @@
|
|||
#define WRITE_BUFFER_SIZE USB_WRITE_BUFFER_SIZE
|
||||
#else
|
||||
#if (CONFIG_STORAGE & STORAGE_SD)
|
||||
#if CONFIG_CPU == AS3525
|
||||
/* We'd need to implement multidescriptor dma for sizes >65535 */
|
||||
#define WRITE_BUFFER_SIZE (1024*63)
|
||||
#else
|
||||
#define WRITE_BUFFER_SIZE (1024*64)
|
||||
#endif /* CONFIG_CPU == AS3525 */
|
||||
#else
|
||||
#define WRITE_BUFFER_SIZE (1024*24)
|
||||
#endif
|
||||
#endif
|
||||
#endif /* (CONFIG_STORAGE & STORAGE_SD) */
|
||||
#endif /* USB_WRITE_BUFFER_SIZE */
|
||||
|
||||
#define ALLOCATE_BUFFER_SIZE (2*MAX(READ_BUFFER_SIZE,WRITE_BUFFER_SIZE))
|
||||
|
||||
|
@ -466,7 +476,7 @@ void usb_storage_init_connection(void)
|
|||
unsigned char * audio_buffer;
|
||||
|
||||
audio_buffer = audio_get_buffer(false,&bufsize);
|
||||
#ifdef UNCACHED_ADDR
|
||||
#if defined(UNCACHED_ADDR) && CONFIG_CPU != AS3525
|
||||
cbw_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer+31) & 0xffffffe0);
|
||||
#else
|
||||
cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0);
|
||||
|
|
Loading…
Reference in a new issue