as3525v2-usb: major code renaming
[kugel-rb.git] / firmware / target / arm / as3525 / usb-drv-as3525.c
blob2f6fa20af8f76a3f9c49f57f81ca9e27ca6b7bd6
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];
44 * dma/setup descriptors and buffers should avoid sharing
45 * a cacheline with other data.
46 * dmadescs may share with each other, since we only access them uncached.
48 static struct usb_dev_dma_desc dmadescs[USB_NUM_EPS][2] __attribute__((aligned(32)));
49 /* reuse unused EP2 OUT descriptor here */
50 static struct usb_dev_setup_buf *setup_desc = (void*)&dmadescs[2][1];
52 #if AS3525_MCLK_SEL != AS3525_CLK_PLLB
53 static inline void usb_enable_pll(void)
55 CGU_COUNTB = CGU_LOCK_CNT;
56 CGU_PLLB = AS3525_PLLB_SETTING;
57 CGU_PLLBSUP = 0; /* enable PLLB */
58 while(!(CGU_INTCTRL & CGU_PLLB_LOCK)); /* wait until PLLB is locked */
61 static inline void usb_disable_pll(void)
63 CGU_PLLBSUP = CGU_PLL_POWERDOWN;
65 #else
66 static inline void usb_enable_pll(void)
70 static inline void usb_disable_pll(void)
73 #endif /* AS3525_MCLK_SEL != AS3525_CLK_PLLB */
75 void usb_attach(void)
77 usb_enable(true);
80 static void usb_phy_on(void)
82 /* PHY clock */
83 CGU_USB = 1<<5 /* enable */
84 | (CLK_DIV(AS3525_PLLB_FREQ, 48000000) / 2) << 2
85 | 2; /* source = PLLB */
87 /* UVDD on */
88 ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) | (1<<4));
89 mdelay(100);
91 /* reset */
92 CCU_SRC = CCU_SRC_USB_AHB_EN|CCU_SRC_USB_PHY_EN;
93 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
94 mdelay(1);
95 CCU_SRC = CCU_SRC_USB_AHB_EN;
96 mdelay(1);
97 CCU_SRC = CCU_SRL = 0;
99 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
100 | USB_GPIO_TX_BIT_STUFF_EN
101 | USB_GPIO_XO_ON
102 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
105 static void usb_phy_suspend(void)
107 USB_GPIO_CSR |= USB_GPIO_ASESSVLD_EXT |
108 USB_GPIO_BSESSVLD_EXT |
109 USB_GPIO_VBUS_VLD_EXT;
110 mdelay(3);
111 USB_GPIO_CSR |= USB_GPIO_VBUS_VLD_EXT_SEL;
112 mdelay(10);
115 static void usb_phy_resume(void)
117 USB_GPIO_CSR &= ~(USB_GPIO_ASESSVLD_EXT |
118 USB_GPIO_BSESSVLD_EXT |
119 USB_GPIO_VBUS_VLD_EXT);
120 mdelay(3);
121 USB_GPIO_CSR &= ~USB_GPIO_VBUS_VLD_EXT_SEL;
122 mdelay(10);
125 static void setup_desc_init(struct usb_dev_setup_buf *desc)
127 struct usb_dev_setup_buf *uc_desc = AS3525_UNCACHED_ADDR(desc);
129 uc_desc->status = USB_DMA_DESC_BS_HST_RDY;
130 uc_desc->resv = 0xffffffff;
131 uc_desc->data1 = 0xffffffff;
132 uc_desc->data2 = 0xffffffff;
135 static void dma_desc_init(int ep, int dir)
137 struct usb_dev_dma_desc *desc = &dmadescs[ep][dir];
138 struct usb_dev_dma_desc *uc_desc = AS3525_UNCACHED_ADDR(desc);
140 endpoints[ep][dir].uc_desc = uc_desc;
142 uc_desc->status = USB_DMA_DESC_BS_DMA_DONE | \
143 USB_DMA_DESC_LAST | \
144 USB_DMA_DESC_ZERO_LEN;
145 uc_desc->resv = 0xffffffff;
146 uc_desc->data_ptr = 0;
147 uc_desc->next_desc = 0;
150 static void reset_endpoints(int init)
152 int i;
154 * MPS sizes depending on speed:
155 * LS: 8 (control), no bulk available
156 * FS: 64 (control), 64 (bulk)
157 * HS: 64 (control), 512 (bulk)
159 * We don't need to handle LS since there is no low-speed only host AFAIK.
161 int mps = i == 0 ? 64 : (usb_drv_port_speed() ? 512 : 64);
164 * OUT EP 2 is an alias for OUT EP 0 on this HW!
166 * Resonates with "3 bidirectional- plus 1 in-endpoints in device mode"
167 * from the datasheet, but why ep2 and not ep3?
169 * Reserve it here so we will skip over it in request_endpoint().
171 endpoints[2][1].state |= EP_STATE_ALLOCATED;
173 for(i = 0; i < USB_NUM_EPS; i++) {
174 if (init) {
175 endpoints[i][0].state = 0;
176 wakeup_init(&endpoints[i][0].complete);
178 if (i != 2) { /* Skip the OUT EP0 alias */
179 endpoints[i][1].state = 0;
180 wakeup_init(&endpoints[i][1].complete);
181 USB_OEP_SUP_PTR(i) = 0;
185 dma_desc_init(i, 0);
186 USB_IEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
187 USB_IEP_MPS (i) = mps; /* in bytes */
188 /* We don't care about the 'IN token received' event */
189 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */
190 USB_IEP_TXFSIZE (i) = mps/2; /* in dwords => mps*2 bytes */
191 USB_IEP_STS (i) = 0xffffffff; /* clear status */
192 USB_IEP_DESC_PTR(i) = 0;
194 if (i != 2) { /* Skip the OUT EP0 alias */
195 dma_desc_init(i, 1);
196 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
197 USB_OEP_MPS (i) = (mps/2 << 23) | mps;
198 USB_OEP_STS_MASK(i) = 0x0000; /* OF: 0x1800 */
199 USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */
200 USB_OEP_STS (i) = 0xffffffff; /* clear status */
201 USB_OEP_DESC_PTR(i) = 0;
205 setup_desc_init(setup_desc);
206 USB_OEP_SUP_PTR(0) = (int)setup_desc;
209 void usb_drv_init(void)
211 logf("usb_drv_init() !!!!\n");
213 usb_enable_pll();
215 /* length regulator: normal operation */
216 ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2);
218 /* AHB part */
219 CGU_PERI |= CGU_USB_CLOCK_ENABLE;
221 /* reset AHB */
222 CCU_SRC = CCU_SRC_USB_AHB_EN;
223 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
224 mdelay(1);
225 CCU_SRC = CCU_SRL = 0;
227 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
228 | USB_GPIO_TX_BIT_STUFF_EN
229 | USB_GPIO_XO_ON
230 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
232 /* bug workaround according to linux patch */
233 USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */
235 /* enable soft disconnect */
236 USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;
238 usb_phy_on();
239 usb_phy_suspend();
240 USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;
242 /* We don't care about SVC or SOF events */
243 /* Right now we don't handle suspend, so mask those too */
244 USB_DEV_INTR_MASK = USB_DEV_INTR_SVC |
245 USB_DEV_INTR_SOF |
246 USB_DEV_INTR_USB_SUSPEND |
247 USB_DEV_INTR_EARLY_SUSPEND;
249 USB_DEV_CFG = USB_DEV_CFG_STAT_ACK |
250 USB_DEV_CFG_UNI_DIR |
251 USB_DEV_CFG_PI_16BIT |
252 USB_DEV_CFG_HS |
253 USB_DEV_CFG_SELF_POWERED |
254 USB_DEV_CFG_CSR_PRG |
255 USB_DEV_CFG_PHY_ERR_DETECT;
257 USB_DEV_CTRL = USB_DEV_CTRL_BLEN_1DWORD |
258 USB_DEV_CTRL_DESC_UPDATE |
259 USB_DEV_CTRL_THRES_ENABLE |
260 USB_DEV_CTRL_RDE |
261 0x04000000;
263 USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */
265 reset_endpoints(1);
267 /* clear pending interrupts */
268 USB_DEV_EP_INTR = 0xffffffff;
269 USB_DEV_INTR = 0xffffffff;
271 VIC_INT_ENABLE = INTERRUPT_USB;
273 usb_phy_resume();
274 USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN;
276 USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
277 | USB_GPIO_TX_BIT_STUFF_EN
278 | USB_GPIO_XO_ON
279 | USB_GPIO_HS_INTR
280 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
284 void usb_drv_exit(void)
286 USB_DEV_CTRL |= (1<<10); /* soft disconnect */
288 * mask all interrupts _before_ writing to VIC_INT_EN_CLEAR,
289 * or else the core might latch the interrupt while
290 * the write ot VIC_INT_EN_CLEAR is in the pipeline and
291 * so cause a fake spurious interrupt.
293 USB_DEV_EP_INTR_MASK = 0xffffffff;
294 USB_DEV_INTR_MASK = 0xffffffff;
295 VIC_INT_EN_CLEAR = INTERRUPT_USB;
296 CGU_USB &= ~(1<<5);
297 CGU_PERI &= ~CGU_USB_CLOCK_ENABLE;
298 /* Disable UVDD generating LDO */
299 ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) & ~(1<<4));
300 usb_disable_pll();
301 logf("usb_drv_exit() !!!!\n");
304 int usb_drv_port_speed(void)
306 return (USB_DEV_STS & USB_DEV_STS_MASK_SPD) ? 0 : 1;
309 int usb_drv_request_endpoint(int type, int dir)
311 int d = dir == USB_DIR_IN ? 0 : 1;
312 int i = 1; /* skip the control EP */
314 for(; i < USB_NUM_EPS; i++) {
315 if (endpoints[i][d].state & EP_STATE_ALLOCATED)
316 continue;
318 endpoints[i][d].state |= EP_STATE_ALLOCATED;
320 if (dir == USB_DIR_IN) {
321 USB_IEP_CTRL(i) = USB_EP_CTRL_FLUSH |
322 USB_EP_CTRL_SNAK |
323 USB_EP_CTRL_ACT |
324 (type << 4);
325 USB_DEV_EP_INTR_MASK &= ~(1<<i);
326 } else {
327 USB_OEP_CTRL(i) = USB_EP_CTRL_FLUSH |
328 USB_EP_CTRL_SNAK |
329 USB_EP_CTRL_ACT |
330 (type << 4);
331 USB_DEV_EP_INTR_MASK &= ~(1<<(16+i));
333 /* logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); */
334 return i | dir;
337 logf("usb_drv_request_endpoint(%d, %d): no free endpoint found\n", type, dir);
338 return -1;
341 void usb_drv_release_endpoint(int ep)
343 int i = ep & 0x7f;
344 int d = ep & USB_DIR_IN ? 0 : 1;
346 if (i >= USB_NUM_EPS)
347 return;
349 * Check for control EP and ignore it.
350 * Unfortunately the usb core calls
351 * usb_drv_release_endpoint() for ep=0..(USB_NUM_ENDPOINTS-1),
352 * but doesn't request a new control EP after that...
354 if (i == 0 || /* Don't mask control EP */
355 (i == 2 && d == 1)) /* See reset_endpoints(), EP2_OUT == EP0_OUT */
356 return;
358 if (!(endpoints[i][d].state & EP_STATE_ALLOCATED))
359 return;
361 /* logf("usb_drv_release_endpoint(%d, %d)\n", i, d); */
362 endpoints[i][d].state = 0;
363 USB_DEV_EP_INTR_MASK |= (1<<(16*d+i));
364 USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK;
367 void usb_drv_cancel_all_transfers(void)
369 logf("usb_drv_cancel_all_transfers()\n");
370 return;
372 int flags = disable_irq_save();
373 reset_endpoints(0);
374 restore_irq(flags);
377 int usb_drv_recv(int ep, void *ptr, int len)
379 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
381 ep &= 0x7f;
382 logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len);
384 if ((int)ptr & 31) {
385 logf("addr %08x not aligned!\n", (int)ptr);
388 endpoints[ep][1].state |= EP_STATE_BUSY;
389 endpoints[ep][1].len = len;
390 endpoints[ep][1].rc = -1;
392 /* remove data buffer from cache */
393 dump_dcache_range(ptr, len);
395 /* DMA setup */
396 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
397 USB_DMA_DESC_LAST |
398 len;
399 if (len == 0) {
400 uc_desc->status |= USB_DMA_DESC_ZERO_LEN;
401 uc_desc->data_ptr = 0;
402 } else {
403 uc_desc->data_ptr = ptr;
405 USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1];
406 USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */
407 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK;
409 return 0;
412 #if defined(LOGF_ENABLE)
413 static char hexbuf[1025];
414 static char hextab[16] = "0123456789abcdef";
416 char *make_hex(char *data, int len)
418 int i;
419 if (!((int)data & 0x40000000))
420 data = AS3525_UNCACHED_ADDR(data); /* don't pollute the cache */
422 if (len > 512)
423 len = 512;
425 for (i=0; i<len; i++) {
426 hexbuf[2*i ] = hextab[(unsigned char)data[i] >> 4 ];
427 hexbuf[2*i+1] = hextab[(unsigned char)data[i] & 0xf];
429 hexbuf[2*i] = 0;
431 return hexbuf;
433 #endif
435 void ep_send(int ep, void *ptr, int len)
437 struct usb_dev_dma_desc *uc_desc = endpoints[ep][0].uc_desc;
439 endpoints[ep][0].state |= EP_STATE_BUSY;
440 endpoints[ep][0].len = len;
441 endpoints[ep][0].rc = -1;
443 /* Make sure data is committed to memory */
444 clean_dcache_range(ptr, len);
446 logf("xx%s\n", make_hex(ptr, len));
448 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
449 USB_DMA_DESC_LAST |
450 len;
451 if (len == 0)
452 uc_desc->status |= USB_DMA_DESC_ZERO_LEN;
454 uc_desc->data_ptr = ptr;
456 USB_IEP_DESC_PTR(ep) = (int)&dmadescs[ep][0];
457 USB_IEP_STS(ep) = 0xffffffff; /* clear status */
458 /* start transfer */
459 USB_IEP_CTRL(ep) |= USB_EP_CTRL_CNAK | USB_EP_CTRL_PD;
460 /* HW automatically sets NAK bit later */
463 int usb_drv_send(int ep, void *ptr, int len)
465 logf("usb_drv_send(%d,%x,%d): ", ep, (int)ptr, len);
467 ep &= 0x7f;
468 ep_send(ep, ptr, len);
469 while (endpoints[ep][0].state & EP_STATE_BUSY)
470 wakeup_wait(&endpoints[ep][0].complete, TIMEOUT_BLOCK);
472 return endpoints[ep][0].rc;
475 int usb_drv_send_nonblocking(int ep, void *ptr, int len)
477 logf("usb_drv_send_nonblocking(%d,%x,%d): ", ep, (int)ptr, len);
478 ep &= 0x7f;
479 endpoints[ep][0].state |= EP_STATE_ASYNC;
480 ep_send(ep, ptr, len);
481 return 0;
484 static void handle_in_ep(int ep)
486 int ep_sts = USB_IEP_STS(ep) & ~USB_IEP_STS_MASK(ep);
488 if (ep > 3)
489 panicf("in_ep > 3?!");
491 USB_IEP_STS(ep) = ep_sts; /* ack */
493 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
494 logf("ep%d IN, status %x (BNA)\n", ep, ep_sts);
495 panicf("ep%d IN 0x%x (BNA)", ep, ep_sts);
498 if (ep_sts & USB_EP_STAT_TDC) {
499 endpoints[ep][0].state &= ~EP_STATE_BUSY;
500 endpoints[ep][0].rc = 0;
501 logf("EP%d %x %stx done len %x stat %08x\n",
502 ep, ep_sts, endpoints[ep][0].state & EP_STATE_ASYNC ? "async " :"",
503 endpoints[ep][0].len,
504 endpoints[ep][0].uc_desc->status);
505 if (endpoints[ep][0].state & EP_STATE_ASYNC) {
506 endpoints[ep][0].state &= ~EP_STATE_ASYNC;
507 usb_core_transfer_complete(ep, USB_DIR_IN, 0, endpoints[ep][0].len);
508 } else {
509 wakeup_signal(&endpoints[ep][0].complete);
511 ep_sts &= ~USB_EP_STAT_TDC;
514 if (ep_sts) {
515 logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state);
516 panicf("ep%d IN 0x%x", ep, ep_sts);
519 /* HW automatically disables RDE, re-enable it */
520 /* But this an IN ep, I wonder... */
521 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
524 static void handle_out_ep(int ep)
526 struct usb_ctrlrequest *req = (void*)AS3525_UNCACHED_ADDR(&setup_desc->data1);
527 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep);
528 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
530 if (ep > 3)
531 panicf("out_ep > 3!?");
533 USB_OEP_STS(ep) = ep_sts; /* ACK */
535 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
536 logf("ep%d OUT, status %x (BNA)\n", ep, ep_sts);
537 panicf("ep%d OUT 0x%x (BNA)", ep, ep_sts);
540 if (ep_sts & USB_EP_STAT_OUT_RCVD) {
541 int dma_sts = uc_desc->status;
542 int dma_len = dma_sts & 0xffff;
544 if (!(dma_sts & USB_DMA_DESC_ZERO_LEN)) {
545 logf("EP%d OUT token, st:%08x len:%d frm:%x data=%s epstate=%d\n",
546 ep, dma_sts & 0xf8000000, dma_len, (dma_sts >> 16) & 0x7ff,
547 make_hex(uc_desc->data_ptr, dma_len), endpoints[ep][1].state);
549 * If parts of the just dmaed range are in cache, dump them now.
551 dump_dcache_range(uc_desc->data_ptr, dma_len);
552 } else{
553 logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep,
554 dma_mst, dma_frm);
557 if (endpoints[ep][1].state & EP_STATE_BUSY) {
558 endpoints[ep][1].state &= ~EP_STATE_BUSY;
559 endpoints[ep][1].rc = 0;
560 usb_core_transfer_complete(ep, USB_DIR_OUT, 0, dma_len);
561 } else {
562 logf("EP%d OUT, but no one was listening?\n", ep);
565 USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */
567 ep_sts &= ~USB_EP_STAT_OUT_RCVD;
570 if (ep_sts & USB_EP_STAT_SETUP_RCVD) {
571 static struct usb_ctrlrequest req_copy;
573 req_copy = *req;
574 logf("t%ld:got SETUP packet: type=%d req=%d val=%d ind=%d len=%d\n",
575 current_tick,
576 req->bRequestType,
577 req->bRequest,
578 req->wValue,
579 req->wIndex,
580 req->wLength);
582 usb_core_control_request(&req_copy);
583 setup_desc_init(setup_desc);
585 ep_sts &= ~USB_EP_STAT_SETUP_RCVD;
588 if (ep_sts) {
589 logf("ep%d OUT, status %x\n", ep, ep_sts);
590 panicf("ep%d OUT 0x%x", ep, ep_sts);
593 /* HW automatically disables RDE, re-enable it */
594 /* THEORY: Because we only set up one DMA buffer... */
595 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
598 /* interrupt service routine */
599 void INT_USB(void)
601 int ep = USB_DEV_EP_INTR & ~USB_DEV_EP_INTR_MASK;
602 int intr = USB_DEV_INTR & ~USB_DEV_INTR_MASK;
604 /* ACK interrupt sources */
605 USB_DEV_EP_INTR = ep;
606 USB_DEV_INTR = intr;
608 /* Handle endpoint interrupts */
609 while (ep) {
610 int onebit = 31-__builtin_clz(ep);
612 if (onebit < 16) handle_in_ep(onebit);
613 else handle_out_ep(onebit-16);
615 ep &= ~(1 << onebit);
618 /* Handle general device interrupts */
619 if (intr) {
620 if (intr & USB_DEV_INTR_SET_INTERFACE) {/* SET_INTERFACE received */
621 logf("set interface\n");
622 panicf("set interface");
623 intr &= ~USB_DEV_INTR_SET_INTERFACE;
625 if (intr & USB_DEV_INTR_SET_CONFIG) {/* SET_CONFIGURATION received */
627 * This is handled in HW, we have to fake a request here
628 * for usb_core.
630 static struct usb_ctrlrequest set_config = {
631 bRequestType: USB_TYPE_STANDARD | USB_RECIP_DEVICE,
632 bRequest: USB_REQ_SET_CONFIGURATION,
633 wValue: 0,
634 wIndex: 0,
635 wLength: 0,
638 logf("set config\n");
640 set_config.wValue = USB_DEV_STS & USB_DEV_STS_MASK_CFG;
641 usb_core_control_request(&set_config);
643 /* Tell the HW we handled the request */
644 USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
645 intr &= ~USB_DEV_INTR_SET_CONFIG;
647 if (intr & USB_DEV_INTR_EARLY_SUSPEND) {/* idle >3ms detected */
648 logf("usb idle\n");
649 intr &= ~USB_DEV_INTR_EARLY_SUSPEND;
651 if (intr & USB_DEV_INTR_USB_RESET) {/* usb reset from host? */
652 logf("usb reset\n");
653 reset_endpoints(1);
654 usb_core_bus_reset();
655 intr &= ~USB_DEV_INTR_USB_RESET;
657 if (intr & USB_DEV_INTR_USB_SUSPEND) {/* suspend req from host? */
658 logf("usb suspend\n");
659 intr &= ~USB_DEV_INTR_USB_SUSPEND;
661 if (intr & USB_DEV_INTR_SOF) {/* sof received */
662 logf("sof\n");
663 intr &= ~USB_DEV_INTR_SOF;
665 if (intr & USB_DEV_INTR_SVC) {/* device status changed */
666 logf("svc: %08x otg: %08x\n", (int)USB_DEV_STS, (int)USB_OTG_CSR);
667 intr &= ~USB_DEV_INTR_SVC;
669 if (intr & USB_DEV_INTR_ENUM_DONE) {/* speed enumeration complete */
670 int spd = USB_DEV_STS & USB_DEV_STS_MASK_SPD; /* Enumerated Speed */
672 logf("speed enum complete: ");
673 if (spd == USB_DEV_STS_SPD_HS) logf("hs\n");
674 if (spd == USB_DEV_STS_SPD_FS) logf("fs\n");
675 if (spd == USB_DEV_STS_SPD_LS) logf("ls\n");
677 USB_PHY_EP0_INFO = 0x00200000 |
678 USB_CSR_DIR_OUT |
679 USB_CSR_TYPE_CTL;
680 USB_PHY_EP1_INFO = 0x00200000 |
681 USB_CSR_DIR_IN |
682 USB_CSR_TYPE_CTL;
683 USB_PHY_EP2_INFO = 0x00200001 |
684 USB_CSR_DIR_IN |
685 USB_CSR_TYPE_BULK;
686 USB_PHY_EP3_INFO = 0x00200001 |
687 USB_CSR_DIR_IN |
688 USB_CSR_TYPE_BULK;
689 USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
690 USB_IEP_CTRL(0) |= USB_EP_CTRL_ACT;
691 USB_OEP_CTRL(0) |= USB_EP_CTRL_ACT;
692 intr &= ~USB_DEV_INTR_ENUM_DONE;
694 if (intr)
695 panicf("usb devirq 0x%x", intr);
698 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
699 logf("re-enabling receive DMA\n");
700 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
705 /* (not essential? , not implemented in usb-tcc.c) */
706 void usb_drv_set_test_mode(int mode)
708 (void)mode;
711 /* handled internally by controller */
712 void usb_drv_set_address(int address)
714 (void)address;
717 void usb_drv_stall(int ep, bool stall, bool in)
719 if (stall) USB_EP_CTRL(ep, in) |= USB_EP_CTRL_STALL;
720 else USB_EP_CTRL(ep, in) &= ~USB_EP_CTRL_STALL;
723 bool usb_drv_stalled(int ep, bool in)
725 return USB_EP_CTRL(ep, in) & USB_EP_CTRL_STALL;
728 #else
730 void usb_attach(void)
734 void usb_drv_init(void)
738 void usb_drv_exit(void)
742 int usb_drv_port_speed(void)
744 return 0;
747 int usb_drv_request_endpoint(int type, int dir)
749 (void)type;
750 (void)dir;
752 return -1;
755 void usb_drv_release_endpoint(int ep)
757 (void)ep;
760 void usb_drv_cancel_all_transfers(void)
764 void usb_drv_set_test_mode(int mode)
766 (void)mode;
769 void usb_drv_set_address(int address)
771 (void)address;
774 int usb_drv_recv(int ep, void *ptr, int len)
776 (void)ep;
777 (void)ptr;
778 (void)len;
780 return -1;
783 int usb_drv_send(int ep, void *ptr, int len)
785 (void)ep;
786 (void)ptr;
787 (void)len;
789 return -1;
792 int usb_drv_send_nonblocking(int ep, void *ptr, int len)
794 (void)ep;
795 (void)ptr;
796 (void)len;
798 return -1;
801 void usb_drv_stall(int ep, bool stall, bool in)
803 (void)ep;
804 (void)stall;
805 (void)in;
808 bool usb_drv_stalled(int ep, bool in)
810 (void)ep;
811 (void)in;
813 return 0;
816 #endif