4036db60107d5b84a4a8f84b9c2dfcf1a7d811d3
[kugel-rb.git] / firmware / target / arm / as3525 / usb-drv-as3525.c
blob4036db60107d5b84a4a8f84b9c2dfcf1a7d811d3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright © 2010 Tobias Diedrich
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "system.h"
23 #include "usb.h"
24 #include "usb_drv.h"
25 #include "as3525.h"
26 #include "clock-target.h"
27 #include "ascodec.h"
28 #include "as3514.h"
29 #include <stdbool.h>
30 #include "panic.h"
31 /*#define LOGF_ENABLE*/
32 #include "logf.h"
33 #include "usb_ch9.h"
34 #include "usb_core.h"
35 #include "string.h"
37 #if defined(USE_ROCKBOX_USB)
39 #include "usb-drv-as3525.h"
41 static struct usb_endpoint endpoints[USB_NUM_EPS][2];
42 static int got_set_configuration = 0;
43 static int usb_enum_timeout = -1;
46 * dma/setup descriptors and buffers should avoid sharing
47 * a cacheline with other data.
48 * dmadescs may share with each other, since we only access them uncached.
50 static struct usb_dev_dma_desc dmadescs[USB_NUM_EPS][2] __attribute__((aligned(32)));
51 /* reuse unused EP2 OUT descriptor here */
52 static struct usb_dev_setup_buf *setup_desc = (void*)&dmadescs[2][1];
54 #if AS3525_MCLK_SEL != AS3525_CLK_PLLB
55 static inline void usb_enable_pll(void)
57 CGU_COUNTB = CGU_LOCK_CNT;
58 CGU_PLLB = AS3525_PLLB_SETTING;
59 CGU_PLLBSUP = 0; /* enable PLLB */
60 while(!(CGU_INTCTRL & CGU_PLLB_LOCK)); /* wait until PLLB is locked */
63 static inline void usb_disable_pll(void)
65 CGU_PLLBSUP = CGU_PLL_POWERDOWN;
67 #else
68 static inline void usb_enable_pll(void)
72 static inline void usb_disable_pll(void)
75 #endif /* AS3525_MCLK_SEL != AS3525_CLK_PLLB */
77 void usb_attach(void)
79 usb_enable(true);
82 static void usb_tick(void);
84 static void usb_phy_on(void)
86 /* PHY clock */
87 CGU_USB = 1<<5 /* enable */
88 | (CLK_DIV(AS3525_PLLB_FREQ, 48000000) / 2) << 2
89 | 2; /* source = PLLB */
91 /* UVDD on */
92 ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) | (1<<4));
93 mdelay(100);
95 /* reset */
96 CCU_SRC = CCU_SRC_USB_AHB_EN|CCU_SRC_USB_PHY_EN;
97 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
98 mdelay(1);
99 CCU_SRC = CCU_SRC_USB_AHB_EN;
100 mdelay(1);
101 CCU_SRC = CCU_SRL = 0;
103 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
104 | USB_GPIO_TX_BIT_STUFF_EN
105 | USB_GPIO_XO_ON
106 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
109 static void usb_phy_suspend(void)
111 USB_GPIO_CSR |= USB_GPIO_ASESSVLD_EXT |
112 USB_GPIO_BSESSVLD_EXT |
113 USB_GPIO_VBUS_VLD_EXT;
114 mdelay(3);
115 USB_GPIO_CSR |= USB_GPIO_VBUS_VLD_EXT_SEL;
116 mdelay(10);
119 static void usb_phy_resume(void)
121 USB_GPIO_CSR &= ~(USB_GPIO_ASESSVLD_EXT |
122 USB_GPIO_BSESSVLD_EXT |
123 USB_GPIO_VBUS_VLD_EXT);
124 mdelay(3);
125 USB_GPIO_CSR &= ~USB_GPIO_VBUS_VLD_EXT_SEL;
126 mdelay(10);
129 static void setup_desc_init(struct usb_dev_setup_buf *desc)
131 struct usb_dev_setup_buf *uc_desc = AS3525_UNCACHED_ADDR(desc);
133 uc_desc->status = USB_DMA_DESC_BS_HST_RDY;
134 uc_desc->resv = 0xffffffff;
135 uc_desc->data1 = 0xffffffff;
136 uc_desc->data2 = 0xffffffff;
139 static void dma_desc_init(int ep, int dir)
141 struct usb_dev_dma_desc *desc = &dmadescs[ep][dir];
142 struct usb_dev_dma_desc *uc_desc = AS3525_UNCACHED_ADDR(desc);
144 endpoints[ep][dir].uc_desc = uc_desc;
146 uc_desc->status = USB_DMA_DESC_BS_DMA_DONE | \
147 USB_DMA_DESC_LAST | \
148 USB_DMA_DESC_ZERO_LEN;
149 uc_desc->resv = 0xffffffff;
150 uc_desc->data_ptr = 0;
151 uc_desc->next_desc = 0;
154 static void reset_endpoints(int init)
156 int i;
159 * OUT EP 2 is an alias for OUT EP 0 on this HW!
161 * Resonates with "3 bidirectional- plus 1 in-endpoints in device mode"
162 * from the datasheet, but why ep2 and not ep3?
164 * Reserve it here so we will skip over it in request_endpoint().
166 endpoints[2][1].state |= EP_STATE_ALLOCATED;
168 for(i = 0; i < USB_NUM_EPS; i++) {
170 * MPS sizes depending on speed:
171 * LS: 8 (control), no bulk available
172 * FS: 64 (control), 64 (bulk)
173 * HS: 64 (control), 512 (bulk)
175 * We don't need to handle LS since there is no low-speed only
176 * host AFAIK.
178 int mps = i == 0 ? 64 : (usb_drv_port_speed() ? 512 : 64);
180 if (init) {
181 if (endpoints[i][0].state & EP_STATE_BUSY) {
182 if (endpoints[i][0].state & EP_STATE_ASYNC) {
183 endpoints[i][0].rc = -1;
184 wakeup_signal(&endpoints[i][0].complete);
185 } else {
186 usb_core_transfer_complete(i, USB_DIR_IN, -1, 0);
189 endpoints[i][0].state = 0;
190 wakeup_init(&endpoints[i][0].complete);
192 if (i != 2) { /* Skip the OUT EP0 alias */
193 if (endpoints[i][1].state & EP_STATE_BUSY)
194 usb_core_transfer_complete(i, USB_DIR_OUT, -1, 0);
195 endpoints[i][1].state = 0;
196 wakeup_init(&endpoints[i][1].complete);
197 USB_OEP_SUP_PTR(i) = 0;
201 dma_desc_init(i, 0);
202 USB_IEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
203 USB_IEP_MPS (i) = mps; /* in bytes */
204 /* We don't care about the 'IN token received' event */
205 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */
206 USB_IEP_TXFSIZE (i) = mps/2; /* in dwords => mps*2 bytes */
207 USB_IEP_STS (i) = 0xffffffff; /* clear status */
208 USB_IEP_DESC_PTR(i) = 0;
210 if (i != 2) { /* Skip the OUT EP0 alias */
211 dma_desc_init(i, 1);
212 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
213 USB_OEP_MPS (i) = (mps/2 << 16) | mps;
214 USB_OEP_STS_MASK(i) = USB_EP_STAT_BNA; /* OF: 0x1800 */
215 USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */
216 USB_OEP_STS (i) = 0xffffffff; /* clear status */
217 USB_OEP_DESC_PTR(i) = 0;
221 setup_desc_init(setup_desc);
222 USB_OEP_SUP_PTR(0) = (int)setup_desc;
225 void usb_drv_init(void)
227 logf("usb_drv_init() !!!!\n");
229 usb_enable_pll();
231 /* we have external power, so boost cpu */
232 cpu_boost(1);
234 /* length regulator: normal operation */
235 ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2);
237 /* AHB part */
238 CGU_PERI |= CGU_USB_CLOCK_ENABLE;
240 /* reset AHB */
241 CCU_SRC = CCU_SRC_USB_AHB_EN;
242 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
243 mdelay(1);
244 CCU_SRC = CCU_SRL = 0;
246 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
247 | USB_GPIO_TX_BIT_STUFF_EN
248 | USB_GPIO_XO_ON
249 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
251 /* bug workaround according to linux patch */
252 USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */
254 /* enable soft disconnect */
255 USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;
257 usb_phy_on();
258 usb_phy_suspend();
259 USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;
261 /* We don't care about SVC or SOF events */
262 /* Right now we don't handle suspend, so mask those too */
263 USB_DEV_INTR_MASK = USB_DEV_INTR_SVC |
264 USB_DEV_INTR_SOF |
265 USB_DEV_INTR_USB_SUSPEND |
266 USB_DEV_INTR_EARLY_SUSPEND;
268 USB_DEV_CFG = USB_DEV_CFG_STAT_ACK |
269 USB_DEV_CFG_UNI_DIR |
270 USB_DEV_CFG_PI_16BIT |
271 USB_DEV_CFG_HS |
272 USB_DEV_CFG_SELF_POWERED |
273 USB_DEV_CFG_CSR_PRG |
274 USB_DEV_CFG_PHY_ERR_DETECT;
276 USB_DEV_CTRL = USB_DEV_CTRL_DESC_UPDATE |
277 USB_DEV_CTRL_THRES_ENABLE |
278 USB_DEV_CTRL_BURST_ENABLE |
279 USB_DEV_CTRL_BLEN_8DWORDS |
280 USB_DEV_CTRL_TLEN_8THMAXSIZE;
282 USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */
284 reset_endpoints(1);
286 /* clear pending interrupts */
287 USB_DEV_EP_INTR = 0xffffffff;
288 USB_DEV_INTR = 0xffffffff;
290 VIC_INT_ENABLE = INTERRUPT_USB;
292 usb_phy_resume();
293 USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN;
295 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
296 | USB_GPIO_TX_BIT_STUFF_EN
297 | USB_GPIO_XO_ON
298 | USB_GPIO_HS_INTR
299 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
301 tick_add_task(usb_tick);
303 usb_enum_timeout = HZ; /* one second timeout for enumeration */
306 void usb_drv_exit(void)
308 tick_remove_task(usb_tick);
309 USB_DEV_CTRL |= (1<<10); /* soft disconnect */
310 usb_phy_suspend();
312 * mask all interrupts _before_ writing to VIC_INT_EN_CLEAR,
313 * or else the core might latch the interrupt while
314 * the write ot VIC_INT_EN_CLEAR is in the pipeline and
315 * so cause a fake spurious interrupt.
317 USB_DEV_EP_INTR_MASK = 0xffffffff;
318 USB_DEV_INTR_MASK = 0xffffffff;
319 VIC_INT_EN_CLEAR = INTERRUPT_USB;
320 CGU_USB &= ~(1<<5);
321 CGU_PERI &= ~CGU_USB_CLOCK_ENABLE;
322 /* Disable UVDD generating LDO */
323 ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) & ~(1<<4));
324 usb_disable_pll();
325 cpu_boost(0);
326 logf("usb_drv_exit() !!!!\n");
329 int usb_drv_port_speed(void)
331 return (USB_DEV_STS & USB_DEV_STS_MASK_SPD) ? 0 : 1;
334 int usb_drv_request_endpoint(int type, int dir)
336 int d = dir == USB_DIR_IN ? 0 : 1;
337 int i = 1; /* skip the control EP */
339 for(; i < USB_NUM_EPS; i++) {
340 if (endpoints[i][d].state & EP_STATE_ALLOCATED)
341 continue;
343 endpoints[i][d].state |= EP_STATE_ALLOCATED;
345 if (dir == USB_DIR_IN) {
346 USB_IEP_CTRL(i) = USB_EP_CTRL_FLUSH |
347 USB_EP_CTRL_SNAK |
348 USB_EP_CTRL_ACT |
349 (type << 4);
350 USB_DEV_EP_INTR_MASK &= ~(1<<i);
351 } else {
352 USB_OEP_CTRL(i) = USB_EP_CTRL_FLUSH |
353 USB_EP_CTRL_SNAK |
354 USB_EP_CTRL_ACT |
355 (type << 4);
356 USB_DEV_EP_INTR_MASK &= ~(1<<(16+i));
358 /* logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); */
359 return i | dir;
362 logf("usb_drv_request_endpoint(%d, %d): no free endpoint found\n", type, dir);
363 return -1;
366 void usb_drv_release_endpoint(int ep)
368 int i = ep & 0x7f;
369 int d = ep & USB_DIR_IN ? 0 : 1;
371 if (i >= USB_NUM_EPS)
372 return;
374 * Check for control EP and ignore it.
375 * Unfortunately the usb core calls
376 * usb_drv_release_endpoint() for ep=0..(USB_NUM_ENDPOINTS-1),
377 * but doesn't request a new control EP after that...
379 if (i == 0 || /* Don't mask control EP */
380 (i == 2 && d == 1)) /* See reset_endpoints(), EP2_OUT == EP0_OUT */
381 return;
383 if (!(endpoints[i][d].state & EP_STATE_ALLOCATED))
384 return;
386 /* logf("usb_drv_release_endpoint(%d, %d)\n", i, d); */
387 endpoints[i][d].state = 0;
388 USB_DEV_EP_INTR_MASK |= (1<<(16*d+i));
389 USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK;
392 void usb_drv_cancel_all_transfers(void)
394 logf("usb_drv_cancel_all_transfers()\n");
395 return;
397 int flags = disable_irq_save();
398 reset_endpoints(0);
399 restore_irq(flags);
402 int usb_drv_recv(int ep, void *ptr, int len)
404 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
406 ep &= 0x7f;
407 logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len);
409 if (len > USB_DMA_DESC_RXTX_BYTES)
410 panicf("usb_recv: len=%d > %d", len, USB_DMA_DESC_RXTX_BYTES);
412 if ((int)ptr & 31) {
413 logf("addr %08x not aligned!\n", (int)ptr);
416 endpoints[ep][1].state |= EP_STATE_BUSY;
417 endpoints[ep][1].len = len;
418 endpoints[ep][1].rc = -1;
419 endpoints[ep][1].timeout = current_tick + HZ;
421 /* remove data buffer from cache */
422 invalidate_dcache_range(ptr, len);
424 /* DMA setup */
425 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
426 USB_DMA_DESC_LAST |
427 len;
428 if (len == 0) {
429 uc_desc->status |= USB_DMA_DESC_ZERO_LEN;
430 uc_desc->data_ptr = 0;
431 } else {
432 uc_desc->data_ptr = ptr;
434 USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1];
435 USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */
437 /* Make sure receive DMA is on */
438 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
439 logf("enabling receive DMA\n");
440 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
441 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE))
442 logf("failed to enable!\n");
445 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
447 if (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
448 int i = 0;
449 while (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
450 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
451 i++;
453 logf("ep%d CNAK needed %d retries CTRL=%x\n", ep, i, (int)USB_OEP_CTRL(ep));
456 return 0;
459 #if defined(LOGF_ENABLE)
460 static char hexbuf[1025];
461 static char hextab[16] = "0123456789abcdef";
463 char *make_hex(char *data, int len)
465 int i;
466 if (!((int)data & 0x40000000))
467 data = AS3525_UNCACHED_ADDR(data); /* don't pollute the cache */
469 if (len > 512)
470 len = 512;
472 for (i=0; i<len; i++) {
473 hexbuf[2*i ] = hextab[(unsigned char)data[i] >> 4 ];
474 hexbuf[2*i+1] = hextab[(unsigned char)data[i] & 0xf];
476 hexbuf[2*i] = 0;
478 return hexbuf;
480 #endif
482 void ep_send(int ep, void *ptr, int len)
484 struct usb_dev_dma_desc *uc_desc = endpoints[ep][0].uc_desc;
486 endpoints[ep][0].state |= EP_STATE_BUSY;
487 endpoints[ep][0].len = len;
488 endpoints[ep][0].rc = -1;
489 endpoints[ep][0].timeout = current_tick + HZ;
491 /* Make sure data is committed to memory */
492 clean_dcache_range(ptr, len);
494 logf("xx%s\n", make_hex(ptr, len));
496 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
497 USB_DMA_DESC_LAST |
498 len;
499 if (len == 0)
500 uc_desc->status |= USB_DMA_DESC_ZERO_LEN;
502 uc_desc->data_ptr = ptr;
504 USB_IEP_DESC_PTR(ep) = (int)&dmadescs[ep][0];
505 USB_IEP_STS(ep) = 0xffffffff; /* clear status */
506 /* start transfer */
507 USB_IEP_CTRL(ep) |= USB_EP_CTRL_CNAK | USB_EP_CTRL_PD;
508 /* HW automatically sets NAK bit later */
511 int usb_drv_send(int ep, void *ptr, int len)
513 logf("usb_drv_send(%d,%x,%d): ", ep, (int)ptr, len);
515 ep &= 0x7f;
517 if (ep == 0 && got_set_configuration) {
518 got_set_configuration = 0;
519 if (len != 0)
520 panicf("usb_drv_send: GSC, but len!=0");
521 /* Tell the HW we handled the request */
522 USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
523 return 0;
526 ep_send(ep, ptr, len);
527 while (endpoints[ep][0].state & EP_STATE_BUSY)
528 wakeup_wait(&endpoints[ep][0].complete, TIMEOUT_BLOCK);
530 return endpoints[ep][0].rc;
533 int usb_drv_send_nonblocking(int ep, void *ptr, int len)
535 logf("usb_drv_send_nonblocking(%d,%x,%d): ", ep, (int)ptr, len);
536 ep &= 0x7f;
537 endpoints[ep][0].state |= EP_STATE_ASYNC;
538 ep_send(ep, ptr, len);
539 return 0;
542 static void handle_in_ep(int ep)
544 int ep_sts = USB_IEP_STS(ep) & ~USB_IEP_STS_MASK(ep);
546 if (ep > 3)
547 panicf("in_ep > 3?!");
549 USB_IEP_STS(ep) = ep_sts; /* ack */
551 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
552 int ctrl = USB_IEP_CTRL(ep);
553 logf("ep%d IN, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
554 panicf("ep%d IN 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
557 if (ep_sts & USB_EP_STAT_TDC) {
558 endpoints[ep][0].state &= ~EP_STATE_BUSY;
559 endpoints[ep][0].rc = 0;
560 logf("EP%d %x %stx done len %x stat %08x\n",
561 ep, ep_sts, endpoints[ep][0].state & EP_STATE_ASYNC ? "async " :"",
562 endpoints[ep][0].len,
563 endpoints[ep][0].uc_desc->status);
564 if (endpoints[ep][0].state & EP_STATE_ASYNC) {
565 endpoints[ep][0].state &= ~EP_STATE_ASYNC;
566 usb_core_transfer_complete(ep, USB_DIR_IN, 0, endpoints[ep][0].len);
567 } else {
568 wakeup_signal(&endpoints[ep][0].complete);
570 ep_sts &= ~USB_EP_STAT_TDC;
573 if (ep_sts) {
574 logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state);
575 panicf("ep%d IN 0x%x", ep, ep_sts);
579 static void handle_out_ep(int ep)
581 struct usb_ctrlrequest *req = (void*)AS3525_UNCACHED_ADDR(&setup_desc->data1);
582 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep);
584 if (ep > 3)
585 panicf("out_ep > 3!?");
587 USB_OEP_STS(ep) = ep_sts; /* ACK */
589 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
590 int ctrl = USB_OEP_CTRL(ep);
591 logf("ep%d OUT, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
592 panicf("ep%d OUT 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
593 ep_sts &= ~USB_EP_STAT_BNA;
596 if (ep_sts & USB_EP_STAT_OUT_RCVD) {
597 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
598 int dma_sts = uc_desc->status;
599 int dma_len = dma_sts & 0xffff;
601 if (!(dma_sts & USB_DMA_DESC_ZERO_LEN)) {
602 logf("EP%d OUT token, st:%08x len:%d frm:%x data=%s epstate=%d\n",
603 ep, dma_sts & 0xf8000000, dma_len, (dma_sts >> 16) & 0x7ff,
604 make_hex(uc_desc->data_ptr, dma_len), endpoints[ep][1].state);
606 * If parts of the just dmaed range are in cache, dump them now.
608 dump_dcache_range(uc_desc->data_ptr, dma_len);
609 } else{
610 logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep,
611 dma_sts & 0xf8000000, (dma_sts >> 16) & 0x7ff);
614 if (endpoints[ep][1].state & EP_STATE_BUSY) {
615 endpoints[ep][1].state &= ~EP_STATE_BUSY;
616 endpoints[ep][1].rc = 0;
617 usb_core_transfer_complete(ep, USB_DIR_OUT, 0, dma_len);
618 } else {
619 logf("EP%d OUT, but no one was listening?\n", ep);
622 USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */
623 ep_sts &= ~USB_EP_STAT_OUT_RCVD;
626 if (ep_sts & USB_EP_STAT_SETUP_RCVD) {
627 static struct usb_ctrlrequest req_copy;
629 req_copy = *req;
630 logf("t%ld:got SETUP packet: %s type=%d req=%d val=%d ind=%d len=%d\n",
631 current_tick,
632 make_hex((void*)req, 8),
633 req->bRequestType,
634 req->bRequest,
635 req->wValue,
636 req->wIndex,
637 req->wLength);
639 usb_core_control_request(&req_copy);
640 setup_desc_init(setup_desc);
642 ep_sts &= ~USB_EP_STAT_SETUP_RCVD;
645 if (ep_sts) {
646 logf("ep%d OUT, status %x\n", ep, ep_sts);
647 panicf("ep%d OUT 0x%x", ep, ep_sts);
650 #if 0
651 /* HW automatically disables RDE, re-enable it */
652 /* THEORY: Because we only set up one DMA buffer... */
653 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
654 #endif
656 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
657 logf("receive DMA is disabled!\n");
658 //USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
663 * This is a simplified version of the timer based RDE enable from
664 * the Linux amd5536udc.c driver.
665 * We need this because of the following hw issue:
666 * The usb_storage buffer is 63KB, but Linux sends 120KB.
667 * We get the first part, but upon re-enabling receive dma we
668 * get a 'buffer not available' error from the hardware, since
669 * we haven't gotten the next usb_drv_recv() from the stack yet.
670 * It seems the NAK bit is ignored here and the HW tries to dma
671 * the incoming data anyway.
672 * In theory I think the BNA error should be recoverable, but
673 * I haven't figured out how to do that yet and this approach seems
674 * to work for now.
676 static void usb_tick(void)
678 static int rde_timer = 0;
679 static int rde_fails = 0;
680 struct usb_endpoint *eps = &endpoints[0][0];
681 int i;
683 if (usb_enum_timeout != -1) {
685 * If the enum times out it's a charger, drop out of usb mode.
687 if (usb_enum_timeout-- <= 0)
688 usb_remove_int();
691 for (i=0; i<2*USB_NUM_EPS; i++) {
692 if (!(eps[i].state & EP_STATE_BUSY) ||
693 !TIME_AFTER(current_tick, endpoints[i]))
694 continue;
696 /* recv or send timed out */
697 if (eps[i].state & EP_STATE_ASYNC) {
698 eps[i].rc = -1;
699 wakeup_signal(&eps[i].complete);
700 } else {
701 usb_core_transfer_complete(i/2, i&1 ? USB_DIR_OUT : USB_DIR_IN,
702 -1, 0);
704 eps[i].state &= ~(EP_STATE_BUSY|EP_STATE_ASYNC);
707 if (USB_DEV_CTRL & USB_DEV_CTRL_RDE)
708 return;
710 if (!(USB_DEV_STS & USB_DEV_STS_RXF_EMPTY)) {
711 if (rde_timer == 0)
712 logf("usb_tick: fifo got filled\n");
713 rde_timer++;
716 if (rde_timer > 2) {
717 logf("usb_tick: re-enabling RDE\n");
718 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
719 rde_timer = 0;
720 if (USB_DEV_CTRL & USB_DEV_CTRL_RDE) {
721 rde_fails = 0;
722 } else {
723 rde_fails++;
724 if (rde_fails > 3)
725 panicf("usb_tick: failed to set RDE");
730 /* interrupt service routine */
731 void INT_USB(void)
733 int ep = USB_DEV_EP_INTR & ~USB_DEV_EP_INTR_MASK;
734 int intr = USB_DEV_INTR & ~USB_DEV_INTR_MASK;
736 /* ACK interrupt sources */
737 USB_DEV_EP_INTR = ep;
738 USB_DEV_INTR = intr;
740 /* Handle endpoint interrupts */
741 while (ep) {
742 int onebit = 31-__builtin_clz(ep);
744 if (onebit < 16) handle_in_ep(onebit);
745 else handle_out_ep(onebit-16);
747 ep &= ~(1 << onebit);
750 /* Handle general device interrupts */
751 if (intr) {
752 if (intr & USB_DEV_INTR_SET_INTERFACE) {/* SET_INTERFACE received */
753 logf("set interface\n");
754 panicf("set interface");
755 intr &= ~USB_DEV_INTR_SET_INTERFACE;
757 if (intr & USB_DEV_INTR_SET_CONFIG) {/* SET_CONFIGURATION received */
759 * This is handled in HW, we have to fake a request here
760 * for usb_core.
762 static struct usb_ctrlrequest set_config = {
763 bRequestType: USB_TYPE_STANDARD | USB_RECIP_DEVICE,
764 bRequest: USB_REQ_SET_CONFIGURATION,
765 wValue: 0,
766 wIndex: 0,
767 wLength: 0,
770 logf("set config\n");
771 got_set_configuration = 1;
773 set_config.wValue = USB_DEV_STS & USB_DEV_STS_MASK_CFG;
774 usb_core_control_request(&set_config);
775 intr &= ~USB_DEV_INTR_SET_CONFIG;
777 if (intr & USB_DEV_INTR_EARLY_SUSPEND) {/* idle >3ms detected */
778 logf("usb idle\n");
779 intr &= ~USB_DEV_INTR_EARLY_SUSPEND;
781 if (intr & USB_DEV_INTR_USB_RESET) {/* usb reset from host? */
782 logf("usb reset\n");
783 reset_endpoints(1);
784 usb_core_bus_reset();
785 intr &= ~USB_DEV_INTR_USB_RESET;
787 if (intr & USB_DEV_INTR_USB_SUSPEND) {/* suspend req from host? */
788 logf("usb suspend\n");
789 intr &= ~USB_DEV_INTR_USB_SUSPEND;
791 if (intr & USB_DEV_INTR_SOF) {/* sof received */
792 logf("sof\n");
793 intr &= ~USB_DEV_INTR_SOF;
795 if (intr & USB_DEV_INTR_SVC) {/* device status changed */
796 logf("svc: %08x otg: %08x\n", (int)USB_DEV_STS, (int)USB_OTG_CSR);
797 intr &= ~USB_DEV_INTR_SVC;
799 if (intr & USB_DEV_INTR_ENUM_DONE) {/* speed enumeration complete */
800 int spd = USB_DEV_STS & USB_DEV_STS_MASK_SPD; /* Enumerated Speed */
801 usb_enum_timeout = -1;
803 logf("speed enum complete: ");
804 if (spd == USB_DEV_STS_SPD_HS) logf("hs\n");
805 if (spd == USB_DEV_STS_SPD_FS) logf("fs\n");
806 if (spd == USB_DEV_STS_SPD_LS) logf("ls\n");
808 USB_PHY_EP0_INFO = 0x00200000 |
809 USB_CSR_DIR_OUT |
810 USB_CSR_TYPE_CTL;
811 USB_PHY_EP1_INFO = 0x00200000 |
812 USB_CSR_DIR_IN |
813 USB_CSR_TYPE_CTL;
814 USB_PHY_EP2_INFO = 0x00200001 |
815 USB_CSR_DIR_IN |
816 USB_CSR_TYPE_BULK;
817 USB_PHY_EP3_INFO = 0x00200001 |
818 USB_CSR_DIR_IN |
819 USB_CSR_TYPE_BULK;
820 USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
821 USB_IEP_CTRL(0) |= USB_EP_CTRL_ACT;
822 USB_OEP_CTRL(0) |= USB_EP_CTRL_ACT;
823 intr &= ~USB_DEV_INTR_ENUM_DONE;
825 if (intr & USB_DEV_INTR_MYSTERY) {
826 logf("got mystery dev intr\n");
827 USB_DEV_INTR_MASK |= USB_DEV_INTR_MYSTERY;
828 intr &= ~USB_DEV_INTR_MYSTERY;
830 if (intr) {
831 logf("usb devirq 0x%x", intr);
832 panicf("usb devirq 0x%x", intr);
837 /* (not essential? , not implemented in usb-tcc.c) */
838 void usb_drv_set_test_mode(int mode)
840 (void)mode;
843 /* handled internally by controller */
844 void usb_drv_set_address(int address)
846 (void)address;
849 void usb_drv_stall(int ep, bool stall, bool in)
851 if (stall) USB_EP_CTRL(ep, in) |= USB_EP_CTRL_STALL;
852 else USB_EP_CTRL(ep, in) &= ~USB_EP_CTRL_STALL;
855 bool usb_drv_stalled(int ep, bool in)
857 return USB_EP_CTRL(ep, in) & USB_EP_CTRL_STALL;
860 #else
862 void usb_attach(void)
866 void usb_drv_init(void)
870 void usb_drv_exit(void)
874 int usb_drv_port_speed(void)
876 return 0;
879 int usb_drv_request_endpoint(int type, int dir)
881 (void)type;
882 (void)dir;
884 return -1;
887 void usb_drv_release_endpoint(int ep)
889 (void)ep;
892 void usb_drv_cancel_all_transfers(void)
896 void usb_drv_set_test_mode(int mode)
898 (void)mode;
901 void usb_drv_set_address(int address)
903 (void)address;
906 int usb_drv_recv(int ep, void *ptr, int len)
908 (void)ep;
909 (void)ptr;
910 (void)len;
912 return -1;
915 int usb_drv_send(int ep, void *ptr, int len)
917 (void)ep;
918 (void)ptr;
919 (void)len;
921 return -1;
924 int usb_drv_send_nonblocking(int ep, void *ptr, int len)
926 (void)ep;
927 (void)ptr;
928 (void)len;
930 return -1;
933 void usb_drv_stall(int ep, bool stall, bool in)
935 (void)ep;
936 (void)stall;
937 (void)in;
940 bool usb_drv_stalled(int ep, bool in)
942 (void)ep;
943 (void)in;
945 return 0;
948 #endif