Move AMSv1 USB to the USB_DETECT_BY_DRV model, so connecting to a dumb charger works...
[maemo-rb.git] / firmware / target / arm / as3525 / usb-drv-as3525.c
blob2e5330ec1b48e0914999f001ec2d81d2d6ee3901
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 "usb-target.h"
26 #include "as3525.h"
27 #include "clock-target.h"
28 #include "ascodec.h"
29 #include "as3514.h"
30 #include <stdbool.h>
31 #include "panic.h"
32 /*#define LOGF_ENABLE*/
33 #include "logf.h"
34 #include "usb_ch9.h"
35 #include "usb_core.h"
36 #include "string.h"
38 #include "usb-drv-as3525.h"
40 static struct usb_endpoint endpoints[USB_NUM_EPS][2];
41 static int got_set_configuration = 0;
42 static int usb_enum_timeout = -1;
45 * dma/setup descriptors and buffers should avoid sharing
46 * a cacheline with other data.
47 * dmadescs may share with each other, since we only access them uncached.
49 static struct usb_dev_dma_desc dmadescs[USB_NUM_EPS][2] __attribute__((aligned(32)));
50 /* reuse unused EP2 OUT descriptor here */
51 static struct usb_dev_setup_buf *setup_desc = (void*)&dmadescs[2][1];
53 #if AS3525_MCLK_SEL != AS3525_CLK_PLLB
54 static inline void usb_enable_pll(void)
56 CGU_COUNTB = CGU_LOCK_CNT;
57 CGU_PLLB = AS3525_PLLB_SETTING;
58 CGU_PLLBSUP = 0; /* enable PLLB */
59 while(!(CGU_INTCTRL & CGU_PLLB_LOCK)); /* wait until PLLB is locked */
62 static inline void usb_disable_pll(void)
64 CGU_PLLBSUP = CGU_PLL_POWERDOWN;
66 #else
67 static inline void usb_enable_pll(void)
71 static inline void usb_disable_pll(void)
74 #endif /* AS3525_MCLK_SEL != AS3525_CLK_PLLB */
76 void usb_attach(void)
78 usb_enable(true);
81 static void usb_tick(void);
83 static void usb_phy_on(void)
85 /* PHY clock */
86 CGU_USB = 1<<5 /* enable */
87 | (CLK_DIV(AS3525_PLLB_FREQ, 48000000) / 2) << 2
88 | 2; /* source = PLLB */
90 /* UVDD on */
91 ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) | (1<<4));
92 mdelay(100);
94 /* reset */
95 CCU_SRC = CCU_SRC_USB_AHB_EN|CCU_SRC_USB_PHY_EN;
96 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
97 mdelay(1);
98 CCU_SRC = CCU_SRC_USB_AHB_EN;
99 mdelay(1);
100 CCU_SRC = CCU_SRL = 0;
102 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
103 | USB_GPIO_TX_BIT_STUFF_EN
104 | USB_GPIO_XO_ON
105 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
108 static void usb_phy_suspend(void)
110 USB_GPIO_CSR |= USB_GPIO_ASESSVLD_EXT |
111 USB_GPIO_BSESSVLD_EXT |
112 USB_GPIO_VBUS_VLD_EXT;
113 mdelay(3);
114 USB_GPIO_CSR |= USB_GPIO_VBUS_VLD_EXT_SEL;
115 mdelay(10);
118 static void usb_phy_resume(void)
120 USB_GPIO_CSR &= ~(USB_GPIO_ASESSVLD_EXT |
121 USB_GPIO_BSESSVLD_EXT |
122 USB_GPIO_VBUS_VLD_EXT);
123 mdelay(3);
124 USB_GPIO_CSR &= ~USB_GPIO_VBUS_VLD_EXT_SEL;
125 mdelay(10);
128 static void setup_desc_init(struct usb_dev_setup_buf *desc)
130 struct usb_dev_setup_buf *uc_desc = AS3525_UNCACHED_ADDR(desc);
132 uc_desc->status = USB_DMA_DESC_BS_HST_RDY;
133 uc_desc->resv = 0xffffffff;
134 uc_desc->data1 = 0xffffffff;
135 uc_desc->data2 = 0xffffffff;
138 static void dma_desc_init(int ep, int dir)
140 struct usb_dev_dma_desc *desc = &dmadescs[ep][dir];
141 struct usb_dev_dma_desc *uc_desc = AS3525_UNCACHED_ADDR(desc);
143 endpoints[ep][dir].uc_desc = uc_desc;
145 uc_desc->status = USB_DMA_DESC_BS_DMA_DONE | \
146 USB_DMA_DESC_LAST | \
147 USB_DMA_DESC_ZERO_LEN;
148 uc_desc->resv = 0xffffffff;
149 uc_desc->data_ptr = 0;
150 uc_desc->next_desc = 0;
153 static void reset_endpoints(int init)
155 int i;
158 * OUT EP 2 is an alias for OUT EP 0 on this HW!
160 * Resonates with "3 bidirectional- plus 1 in-endpoints in device mode"
161 * from the datasheet, but why ep2 and not ep3?
163 * Reserve it here so we will skip over it in request_endpoint().
165 endpoints[2][1].state |= EP_STATE_ALLOCATED;
167 for(i = 0; i < USB_NUM_EPS; i++) {
169 * MPS sizes depending on speed:
170 * LS: 8 (control), no bulk available
171 * FS: 64 (control), 64 (bulk)
172 * HS: 64 (control), 512 (bulk)
174 * We don't need to handle LS since there is no low-speed only
175 * host AFAIK.
177 int mps = i == 0 ? 64 : (usb_drv_port_speed() ? 512 : 64);
179 if (init) {
180 if (endpoints[i][0].state & EP_STATE_BUSY) {
181 if (endpoints[i][0].state & EP_STATE_ASYNC) {
182 endpoints[i][0].rc = -1;
183 wakeup_signal(&endpoints[i][0].complete);
184 } else {
185 usb_core_transfer_complete(i, USB_DIR_IN, -1, 0);
188 endpoints[i][0].state = 0;
189 wakeup_init(&endpoints[i][0].complete);
191 if (i != 2) { /* Skip the OUT EP0 alias */
192 if (endpoints[i][1].state & EP_STATE_BUSY)
193 usb_core_transfer_complete(i, USB_DIR_OUT, -1, 0);
194 endpoints[i][1].state = 0;
195 wakeup_init(&endpoints[i][1].complete);
196 USB_OEP_SUP_PTR(i) = 0;
200 dma_desc_init(i, 0);
201 USB_IEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
202 USB_IEP_MPS (i) = mps; /* in bytes */
203 /* We don't care about the 'IN token received' event */
204 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */
205 USB_IEP_TXFSIZE (i) = mps/2; /* in dwords => mps*2 bytes */
206 USB_IEP_STS (i) = 0xffffffff; /* clear status */
207 USB_IEP_DESC_PTR(i) = 0;
209 if (i != 2) { /* Skip the OUT EP0 alias */
210 dma_desc_init(i, 1);
211 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
212 USB_OEP_MPS (i) = (mps/2 << 16) | mps;
213 USB_OEP_STS_MASK(i) = USB_EP_STAT_BNA; /* OF: 0x1800 */
214 USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */
215 USB_OEP_STS (i) = 0xffffffff; /* clear status */
216 USB_OEP_DESC_PTR(i) = 0;
220 setup_desc_init(setup_desc);
221 USB_OEP_SUP_PTR(0) = AS3525_PHYSICAL_ADDR((int)setup_desc);
224 void usb_drv_init(void)
226 logf("usb_drv_init() !!!!\n");
228 usb_enable_pll();
230 /* we have external power, so boost cpu */
231 cpu_boost(1);
233 /* length regulator: normal operation */
234 ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2);
236 /* AHB part */
237 bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE);
239 /* reset AHB */
240 CCU_SRC = CCU_SRC_USB_AHB_EN;
241 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
242 mdelay(1);
243 CCU_SRC = CCU_SRL = 0;
245 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
246 | USB_GPIO_TX_BIT_STUFF_EN
247 | USB_GPIO_XO_ON
248 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
250 /* bug workaround according to linux patch */
251 USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */
253 /* enable soft disconnect */
254 USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;
256 usb_phy_on();
257 usb_phy_suspend();
258 USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;
260 /* We don't care about SVC or SOF events */
261 /* Right now we don't handle suspend, so mask those too */
262 USB_DEV_INTR_MASK = USB_DEV_INTR_SVC |
263 USB_DEV_INTR_SOF |
264 USB_DEV_INTR_USB_SUSPEND |
265 USB_DEV_INTR_EARLY_SUSPEND;
267 USB_DEV_CFG = USB_DEV_CFG_STAT_ACK |
268 USB_DEV_CFG_UNI_DIR |
269 USB_DEV_CFG_PI_16BIT |
270 USB_DEV_CFG_HS |
271 USB_DEV_CFG_SELF_POWERED |
272 USB_DEV_CFG_CSR_PRG |
273 USB_DEV_CFG_PHY_ERR_DETECT;
275 USB_DEV_CTRL = USB_DEV_CTRL_DESC_UPDATE |
276 USB_DEV_CTRL_THRES_ENABLE |
277 USB_DEV_CTRL_BURST_ENABLE |
278 USB_DEV_CTRL_BLEN_8DWORDS |
279 USB_DEV_CTRL_TLEN_8THMAXSIZE;
281 USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */
283 reset_endpoints(1);
285 /* clear pending interrupts */
286 USB_DEV_EP_INTR = 0xffffffff;
287 USB_DEV_INTR = 0xffffffff;
289 VIC_INT_ENABLE = INTERRUPT_USB;
291 usb_phy_resume();
292 USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN;
294 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
295 | USB_GPIO_TX_BIT_STUFF_EN
296 | USB_GPIO_XO_ON
297 | USB_GPIO_HS_INTR
298 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
300 tick_add_task(usb_tick);
302 usb_enum_timeout = HZ; /* one second timeout for enumeration */
305 void usb_drv_exit(void)
307 tick_remove_task(usb_tick);
308 USB_DEV_CTRL |= (1<<10); /* soft disconnect */
309 usb_phy_suspend();
311 * mask all interrupts _before_ writing to VIC_INT_EN_CLEAR,
312 * or else the core might latch the interrupt while
313 * the write ot VIC_INT_EN_CLEAR is in the pipeline and
314 * so cause a fake spurious interrupt.
316 USB_DEV_EP_INTR_MASK = 0xffffffff;
317 USB_DEV_INTR_MASK = 0xffffffff;
318 VIC_INT_EN_CLEAR = INTERRUPT_USB;
319 CGU_USB &= ~(1<<5);
320 bitclr32(&CGU_PERI, CGU_USB_CLOCK_ENABLE);
321 /* Disable UVDD generating LDO */
322 ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) & ~(1<<4));
323 usb_disable_pll();
324 cpu_boost(0);
325 logf("usb_drv_exit() !!!!\n");
328 int usb_drv_port_speed(void)
330 return (USB_DEV_STS & USB_DEV_STS_MASK_SPD) ? 0 : 1;
333 int usb_drv_request_endpoint(int type, int dir)
335 int d = dir == USB_DIR_IN ? 0 : 1;
336 int i = 1; /* skip the control EP */
338 for(; i < USB_NUM_EPS; i++) {
339 if (endpoints[i][d].state & EP_STATE_ALLOCATED)
340 continue;
342 endpoints[i][d].state |= EP_STATE_ALLOCATED;
344 if (dir == USB_DIR_IN) {
345 USB_IEP_CTRL(i) = USB_EP_CTRL_FLUSH |
346 USB_EP_CTRL_SNAK |
347 USB_EP_CTRL_ACT |
348 (type << 4);
349 USB_DEV_EP_INTR_MASK &= ~(1<<i);
350 } else {
351 USB_OEP_CTRL(i) = USB_EP_CTRL_FLUSH |
352 USB_EP_CTRL_SNAK |
353 USB_EP_CTRL_ACT |
354 (type << 4);
355 USB_DEV_EP_INTR_MASK &= ~(1<<(16+i));
357 /* logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); */
358 return i | dir;
361 logf("usb_drv_request_endpoint(%d, %d): no free endpoint found\n", type, dir);
362 return -1;
365 void usb_drv_release_endpoint(int ep)
367 int i = ep & 0x7f;
368 int d = ep & USB_DIR_IN ? 0 : 1;
370 if (i >= USB_NUM_EPS)
371 return;
373 * Check for control EP and ignore it.
374 * Unfortunately the usb core calls
375 * usb_drv_release_endpoint() for ep=0..(USB_NUM_ENDPOINTS-1),
376 * but doesn't request a new control EP after that...
378 if (i == 0 || /* Don't mask control EP */
379 (i == 2 && d == 1)) /* See reset_endpoints(), EP2_OUT == EP0_OUT */
380 return;
382 if (!(endpoints[i][d].state & EP_STATE_ALLOCATED))
383 return;
385 /* logf("usb_drv_release_endpoint(%d, %d)\n", i, d); */
386 endpoints[i][d].state = 0;
387 USB_DEV_EP_INTR_MASK |= (1<<(16*d+i));
388 USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK;
391 void usb_drv_cancel_all_transfers(void)
393 logf("usb_drv_cancel_all_transfers()\n");
394 return;
396 int flags = disable_irq_save();
397 reset_endpoints(0);
398 restore_irq(flags);
401 int usb_drv_recv(int ep, void *ptr, int len)
403 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
405 ep &= 0x7f;
406 logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len);
408 if (len > USB_DMA_DESC_RXTX_BYTES)
409 panicf("usb_recv: len=%d > %d", len, USB_DMA_DESC_RXTX_BYTES);
411 if ((int)ptr & 31) {
412 logf("addr %08x not aligned!\n", (int)ptr);
415 endpoints[ep][1].state |= EP_STATE_BUSY;
416 endpoints[ep][1].len = len;
417 endpoints[ep][1].rc = -1;
419 /* remove data buffer from cache */
420 invalidate_dcache_range(ptr, len);
422 /* DMA setup */
423 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
424 USB_DMA_DESC_LAST |
425 len;
426 if (len == 0) {
427 uc_desc->status |= USB_DMA_DESC_ZERO_LEN;
428 uc_desc->data_ptr = 0;
429 } else {
430 uc_desc->data_ptr = AS3525_PHYSICAL_ADDR(ptr);
432 USB_OEP_DESC_PTR(ep) = AS3525_PHYSICAL_ADDR((int)&dmadescs[ep][1]);
433 USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */
435 /* Make sure receive DMA is on */
436 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
437 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
438 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE))
439 logf("failed to enable RDE!\n");
442 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
444 if (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
445 int i = 0;
446 while (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
447 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
448 i++;
450 logf("ep%d CNAK needed %d retries CTRL=%x\n", ep, i, (int)USB_OEP_CTRL(ep));
453 return 0;
456 #if defined(LOGF_ENABLE)
457 static char hexbuf[1025];
458 static char hextab[16] = "0123456789abcdef";
460 char *make_hex(char *data, int len)
462 int i;
463 if (!((int)data & 0x40000000))
464 data = AS3525_UNCACHED_ADDR(data); /* don't pollute the cache */
466 if (len > 512)
467 len = 512;
469 for (i=0; i<len; i++) {
470 hexbuf[2*i ] = hextab[(unsigned char)data[i] >> 4 ];
471 hexbuf[2*i+1] = hextab[(unsigned char)data[i] & 0xf];
473 hexbuf[2*i] = 0;
475 return hexbuf;
477 #endif
479 static void ep_send(int ep, void *ptr, int len)
481 struct usb_dev_dma_desc *uc_desc = endpoints[ep][0].uc_desc;
483 endpoints[ep][0].state |= EP_STATE_BUSY;
484 endpoints[ep][0].len = len;
485 endpoints[ep][0].rc = -1;
488 * I'm seeing a problem where Linux sends two SETUP requests,
489 * but fails to read the response from the first one.
490 * We then have the response we wanted to send still in our fifo,
491 * so flush the fifo before sending on the control endpoint.
493 if (ep == 0)
494 USB_IEP_CTRL(ep) |= USB_EP_CTRL_FLUSH;
496 /* Make sure data is committed to memory */
497 clean_dcache_range(ptr, len);
499 logf("xx%s\n", make_hex(ptr, len));
501 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
502 USB_DMA_DESC_LAST |
503 len;
504 if (len == 0)
505 uc_desc->status |= USB_DMA_DESC_ZERO_LEN;
507 uc_desc->data_ptr = AS3525_PHYSICAL_ADDR(ptr);
509 USB_IEP_DESC_PTR(ep) = AS3525_PHYSICAL_ADDR((int)&dmadescs[ep][0]);
510 USB_IEP_STS(ep) = 0xffffffff; /* clear status */
511 /* start transfer */
512 USB_IEP_CTRL(ep) |= USB_EP_CTRL_CNAK | USB_EP_CTRL_PD;
513 /* HW automatically sets NAK bit later */
516 int usb_drv_send(int ep, void *ptr, int len)
518 logf("usb_drv_send(%d,%x,%d): ", ep, (int)ptr, len);
520 ep &= 0x7f;
522 if (ep == 0 && got_set_configuration) {
523 got_set_configuration = 0;
524 if (len != 0)
525 panicf("usb_drv_send: GSC, but len!=0");
526 /* Tell the HW we handled the request */
527 USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
528 return 0;
531 ep_send(ep, ptr, len);
532 if (wakeup_wait(&endpoints[ep][0].complete, HZ) == OBJ_WAIT_TIMEDOUT)
533 logf("send timed out!\n");
535 return endpoints[ep][0].rc;
538 int usb_drv_send_nonblocking(int ep, void *ptr, int len)
540 logf("usb_drv_send_nonblocking(%d,%x,%d): ", ep, (int)ptr, len);
541 ep &= 0x7f;
542 endpoints[ep][0].state |= EP_STATE_ASYNC;
543 ep_send(ep, ptr, len);
544 return 0;
547 static void handle_in_ep(int ep)
549 int ep_sts = USB_IEP_STS(ep) & ~USB_IEP_STS_MASK(ep);
551 if (ep > 3)
552 panicf("in_ep > 3?!");
554 USB_IEP_STS(ep) = ep_sts; /* ack */
556 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
557 int ctrl = USB_IEP_CTRL(ep);
558 logf("ep%d IN, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
559 panicf("ep%d IN 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
562 if (ep_sts & USB_EP_STAT_TDC) {
563 endpoints[ep][0].state &= ~EP_STATE_BUSY;
564 endpoints[ep][0].rc = 0;
565 logf("EP%d %x %stx done len %x stat %08x\n",
566 ep, ep_sts, endpoints[ep][0].state & EP_STATE_ASYNC ? "async " :"",
567 endpoints[ep][0].len,
568 endpoints[ep][0].uc_desc->status);
569 if (endpoints[ep][0].state & EP_STATE_ASYNC) {
570 endpoints[ep][0].state &= ~EP_STATE_ASYNC;
571 usb_core_transfer_complete(ep, USB_DIR_IN, 0, endpoints[ep][0].len);
572 } else {
573 wakeup_signal(&endpoints[ep][0].complete);
575 ep_sts &= ~USB_EP_STAT_TDC;
578 if (ep_sts) {
579 logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state);
580 panicf("ep%d IN 0x%x", ep, ep_sts);
584 static void handle_out_ep(int ep)
586 struct usb_ctrlrequest *req = (void*)AS3525_UNCACHED_ADDR(&setup_desc->data1);
587 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep);
589 if (ep > 3)
590 panicf("out_ep > 3!?");
592 USB_OEP_STS(ep) = ep_sts; /* ACK */
594 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
595 int ctrl = USB_OEP_CTRL(ep);
596 logf("ep%d OUT, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
597 panicf("ep%d OUT 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
598 ep_sts &= ~USB_EP_STAT_BNA;
601 if (ep_sts & USB_EP_STAT_OUT_RCVD) {
602 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
603 int dma_sts = uc_desc->status;
604 int dma_len = dma_sts & 0xffff;
606 if (!(dma_sts & USB_DMA_DESC_ZERO_LEN)) {
607 logf("EP%d OUT token, st:%08x len:%d frm:%x data=%s epstate=%d\n",
608 ep, dma_sts & 0xf8000000, dma_len, (dma_sts >> 16) & 0x7ff,
609 make_hex(uc_desc->data_ptr, dma_len), endpoints[ep][1].state);
611 * If parts of the just dmaed range are in cache, dump them now.
613 dump_dcache_range(uc_desc->data_ptr, dma_len);
614 } else{
615 logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep,
616 dma_sts & 0xf8000000, (dma_sts >> 16) & 0x7ff);
619 if (endpoints[ep][1].state & EP_STATE_BUSY) {
620 endpoints[ep][1].state &= ~EP_STATE_BUSY;
621 endpoints[ep][1].rc = 0;
622 usb_core_transfer_complete(ep, USB_DIR_OUT, 0, dma_len);
623 } else {
624 logf("EP%d OUT, but no one was listening?\n", ep);
627 USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */
628 ep_sts &= ~USB_EP_STAT_OUT_RCVD;
631 if (ep_sts & USB_EP_STAT_SETUP_RCVD) {
632 static struct usb_ctrlrequest req_copy;
634 req_copy = *req;
635 logf("t%ld:got SETUP packet: %s type=%d req=%d val=%d ind=%d len=%d\n",
636 current_tick,
637 make_hex((void*)req, 8),
638 req->bRequestType,
639 req->bRequest,
640 req->wValue,
641 req->wIndex,
642 req->wLength);
644 usb_core_control_request(&req_copy);
645 setup_desc_init(setup_desc);
647 ep_sts &= ~USB_EP_STAT_SETUP_RCVD;
650 if (ep_sts) {
651 logf("ep%d OUT, status %x\n", ep, ep_sts);
652 panicf("ep%d OUT 0x%x", ep, ep_sts);
657 * This is a simplified version of the timer based RDE enable from
658 * the Linux amd5536udc.c driver.
659 * We need this because of the following hw issue:
660 * The usb_storage buffer is 63KB, but Linux sends 120KB.
661 * We get the first part, but upon re-enabling receive dma we
662 * get a 'buffer not available' error from the hardware, since
663 * we haven't gotten the next usb_drv_recv() from the stack yet.
664 * It seems the NAK bit is ignored here and the HW tries to dma
665 * the incoming data anyway.
666 * In theory I think the BNA error should be recoverable, but
667 * I haven't figured out how to do that yet and this approach seems
668 * to work for now.
670 static void usb_tick(void)
672 static int rde_timer = 0;
673 static int rde_fails = 0;
675 if (usb_enum_timeout != -1) {
677 * If the enum times out it's a charger, drop out of usb mode.
679 if (usb_enum_timeout-- <= 0)
680 usb_remove_int();
683 if (USB_DEV_CTRL & USB_DEV_CTRL_RDE)
684 return;
686 if (!(USB_DEV_STS & USB_DEV_STS_RXF_EMPTY))
687 rde_timer++;
689 if (rde_timer < 2)
690 return;
692 logf("usb_tick: re-enabling RDE\n");
693 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
694 rde_timer = 0;
695 if (USB_DEV_CTRL & USB_DEV_CTRL_RDE) {
696 rde_fails = 0;
697 } else {
698 rde_fails++;
699 if (rde_fails > 3)
700 panicf("usb_tick: failed to set RDE");
704 /* interrupt service routine */
705 void INT_USB(void)
707 int ep = USB_DEV_EP_INTR & ~USB_DEV_EP_INTR_MASK;
708 int intr = USB_DEV_INTR & ~USB_DEV_INTR_MASK;
710 /* ACK interrupt sources */
711 USB_DEV_EP_INTR = ep;
712 USB_DEV_INTR = intr;
714 /* Handle endpoint interrupts */
715 while (ep) {
716 int onebit = 31-__builtin_clz(ep);
718 if (onebit < 16) handle_in_ep(onebit);
719 else handle_out_ep(onebit-16);
721 ep &= ~(1 << onebit);
724 /* Handle general device interrupts */
725 if (intr) {
726 if (intr & USB_DEV_INTR_SET_INTERFACE) {/* SET_INTERFACE received */
727 logf("set interface\n");
728 panicf("set interface");
729 intr &= ~USB_DEV_INTR_SET_INTERFACE;
731 if (intr & USB_DEV_INTR_SET_CONFIG) {/* SET_CONFIGURATION received */
733 * This is handled in HW, we have to fake a request here
734 * for usb_core.
736 static struct usb_ctrlrequest set_config = {
737 bRequestType: USB_TYPE_STANDARD | USB_RECIP_DEVICE,
738 bRequest: USB_REQ_SET_CONFIGURATION,
739 wValue: 0,
740 wIndex: 0,
741 wLength: 0,
744 logf("set config\n");
745 got_set_configuration = 1;
747 set_config.wValue = USB_DEV_STS & USB_DEV_STS_MASK_CFG;
748 usb_core_control_request(&set_config);
749 intr &= ~USB_DEV_INTR_SET_CONFIG;
751 if (intr & USB_DEV_INTR_EARLY_SUSPEND) {/* idle >3ms detected */
752 logf("usb idle\n");
753 intr &= ~USB_DEV_INTR_EARLY_SUSPEND;
755 if (intr & USB_DEV_INTR_USB_RESET) {/* usb reset from host? */
756 logf("usb reset\n");
757 usb_drv_usb_detect_event();
758 reset_endpoints(1);
759 usb_core_bus_reset();
760 intr &= ~USB_DEV_INTR_USB_RESET;
762 if (intr & USB_DEV_INTR_USB_SUSPEND) {/* suspend req from host? */
763 logf("usb suspend\n");
764 intr &= ~USB_DEV_INTR_USB_SUSPEND;
766 if (intr & USB_DEV_INTR_SOF) {/* sof received */
767 logf("sof\n");
768 intr &= ~USB_DEV_INTR_SOF;
770 if (intr & USB_DEV_INTR_SVC) {/* device status changed */
771 logf("svc: %08x otg: %08x\n", (int)USB_DEV_STS, (int)USB_OTG_CSR);
772 intr &= ~USB_DEV_INTR_SVC;
774 if (intr & USB_DEV_INTR_ENUM_DONE) {/* speed enumeration complete */
775 int spd = USB_DEV_STS & USB_DEV_STS_MASK_SPD; /* Enumerated Speed */
776 usb_enum_timeout = -1;
778 logf("speed enum complete: ");
779 if (spd == USB_DEV_STS_SPD_HS) logf("hs\n");
780 if (spd == USB_DEV_STS_SPD_FS) logf("fs\n");
781 if (spd == USB_DEV_STS_SPD_LS) logf("ls\n");
783 USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
784 USB_IEP_CTRL(0) |= USB_EP_CTRL_ACT;
785 USB_OEP_CTRL(0) |= USB_EP_CTRL_ACT;
786 intr &= ~USB_DEV_INTR_ENUM_DONE;
788 if (intr & USB_DEV_INTR_MYSTERY) {
789 logf("got mystery dev intr\n");
790 USB_DEV_INTR_MASK |= USB_DEV_INTR_MYSTERY;
791 intr &= ~USB_DEV_INTR_MYSTERY;
793 if (intr) {
794 logf("usb devirq 0x%x", intr);
795 panicf("usb devirq 0x%x", intr);
800 /* (not essential? , not implemented in usb-tcc.c) */
801 void usb_drv_set_test_mode(int mode)
803 (void)mode;
806 /* handled internally by controller */
807 void usb_drv_set_address(int address)
809 (void)address;
812 void usb_drv_stall(int ep, bool stall, bool in)
814 if (stall) USB_EP_CTRL(ep, in) |= USB_EP_CTRL_STALL;
815 else USB_EP_CTRL(ep, in) &= ~USB_EP_CTRL_STALL;
818 bool usb_drv_stalled(int ep, bool in)
820 return USB_EP_CTRL(ep, in) & USB_EP_CTRL_STALL;