diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2010-05-03 19:18:10 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2010-05-03 19:18:10 +0000 |
commit | 35f341464b7d9dc2b1bd3f6222da5ec226f34dad (patch) | |
tree | 48bdde1256236849d2f4803bcc52579ad85835ae /firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |
parent | c5abd150889f323ff4c643911d25f34444cbff05 (diff) | |
download | rockbox-35f341464b7d9dc2b1bd3f6222da5ec226f34dad.tar.gz rockbox-35f341464b7d9dc2b1bd3f6222da5ec226f34dad.zip |
Ingenic Jz4740: cleanup USB driver a bit (no externally visible functional changes)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25796 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 237 |
1 files changed, 119 insertions, 118 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index 64428ca2d6..81c6bdb1ed 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |||
@@ -33,12 +33,15 @@ | |||
33 | /* | 33 | /* |
34 | The Jz4740 USB controller is called MUSBHSFC in the datasheet. | 34 | The Jz4740 USB controller is called MUSBHSFC in the datasheet. |
35 | It also seems to be a more generic controller, with support for | 35 | It also seems to be a more generic controller, with support for |
36 | up to 15 endpoints (the Jz4740 only has 3). | 36 | up to 15 endpoints (the Jz4740 only has 5). |
37 | */ | 37 | */ |
38 | 38 | ||
39 | #define USB_EP0_IDLE 0 | 39 | enum |
40 | #define USB_EP0_RX 1 | 40 | { |
41 | #define USB_EP0_TX 2 | 41 | USB_EP0_IDLE, |
42 | USB_EP0_RX, | ||
43 | USB_EP0_TX | ||
44 | }; | ||
42 | 45 | ||
43 | #define EP_BUF_LEFT(ep) ((ep)->length - (ep)->sent) | 46 | #define EP_BUF_LEFT(ep) ((ep)->length - (ep)->sent) |
44 | #define EP_PTR(ep) ((void*)((unsigned int)(ep)->buf + (ep)->sent)) | 47 | #define EP_PTR(ep) ((void*)((unsigned int)(ep)->buf + (ep)->sent)) |
@@ -49,7 +52,10 @@ | |||
49 | 52 | ||
50 | enum ep_type | 53 | enum ep_type |
51 | { | 54 | { |
52 | ep_control, ep_bulk, ep_interrupt | 55 | ep_control, |
56 | ep_bulk, | ||
57 | ep_interrupt, | ||
58 | ep_isochronous | ||
53 | }; | 59 | }; |
54 | 60 | ||
55 | struct usb_endpoint | 61 | struct usb_endpoint |
@@ -69,20 +75,20 @@ struct usb_endpoint | |||
69 | 75 | ||
70 | const unsigned int fifo_addr; | 76 | const unsigned int fifo_addr; |
71 | unsigned short fifo_size; | 77 | unsigned short fifo_size; |
78 | |||
79 | struct wakeup wakeup; | ||
72 | }; | 80 | }; |
73 | 81 | ||
74 | static unsigned char ep0_rx_buf[64]; | 82 | static unsigned char ep0_rx_buf[64]; |
75 | static unsigned char ep0state = USB_EP0_IDLE; | 83 | static unsigned char ep0state = USB_EP0_IDLE; |
76 | static struct usb_endpoint endpoints[] = | 84 | static struct usb_endpoint endpoints[] = |
77 | { | 85 | { |
78 | /* buf length sent busy type use_dma wait fifo_addr fifo_size */ | 86 | { .type = ep_control, .fifo_addr = USB_FIFO_EP0, .fifo_size = 64 }, |
79 | {NULL, 0, {0}, false, ep_control, false, false, USB_FIFO_EP0, 64 }, | 87 | { .type = ep_control, .fifo_addr = USB_FIFO_EP0, .fifo_size = 64, .buf = &ep0_rx_buf }, |
80 | {&ep0_rx_buf, 0, {0}, false, ep_control, false, false, USB_FIFO_EP0, 64 }, | 88 | { .type = ep_bulk, .fifo_addr = USB_FIFO_EP1, .fifo_size = 512 }, |
81 | {NULL, 0, {0}, false, ep_bulk, false, false, USB_FIFO_EP1, 512}, | 89 | { .type = ep_bulk, .fifo_addr = USB_FIFO_EP1, .fifo_size = 512 }, |
82 | {NULL, 0, {0}, false, ep_bulk, false, false, USB_FIFO_EP1, 512}, | 90 | { .type = ep_interrupt, .fifo_addr = USB_FIFO_EP2, .fifo_size = 64 }, |
83 | {NULL, 0, {0}, false, ep_interrupt, false, false, USB_FIFO_EP2, 64 } | ||
84 | }; | 91 | }; |
85 | static struct wakeup ep_wkup[TOTAL_EP()]; | ||
86 | 92 | ||
87 | static inline void select_endpoint(int ep) | 93 | static inline void select_endpoint(int ep) |
88 | { | 94 | { |
@@ -91,7 +97,7 @@ static inline void select_endpoint(int ep) | |||
91 | 97 | ||
92 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) | 98 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) |
93 | { | 99 | { |
94 | logf("readFIFO(EP%d, %d)", EP_NUMBER2(ep), size); | 100 | logf("%s(EP%d, %d)", __func__, EP_NUMBER2(ep), size); |
95 | 101 | ||
96 | register unsigned char *ptr = (unsigned char*)EP_PTR(ep); | 102 | register unsigned char *ptr = (unsigned char*)EP_PTR(ep); |
97 | register unsigned int *ptr32 = (unsigned int*)ptr; | 103 | register unsigned int *ptr32 = (unsigned int*)ptr; |
@@ -112,10 +118,10 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) | |||
112 | while(s--) | 118 | while(s--) |
113 | { | 119 | { |
114 | x = REG32(ep->fifo_addr); | 120 | x = REG32(ep->fifo_addr); |
115 | *ptr++ = (x >> 0) & 0xFF; | 121 | *ptr++ = x & 0xFF; x >>= 8; |
116 | *ptr++ = (x >> 8) & 0xFF; | 122 | *ptr++ = x & 0xFF; x >>= 8; |
117 | *ptr++ = (x >> 16) & 0xFF; | 123 | *ptr++ = x & 0xFF; x >>= 8; |
118 | *ptr++ = (x >> 24) & 0xFF; | 124 | *ptr++ = x; |
119 | } | 125 | } |
120 | } | 126 | } |
121 | 127 | ||
@@ -125,41 +131,30 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) | |||
125 | } | 131 | } |
126 | } | 132 | } |
127 | 133 | ||
128 | static void writeFIFO(struct usb_endpoint *ep, unsigned int size) | 134 | static void writeFIFO(struct usb_endpoint *ep, size_t size) |
129 | { | 135 | { |
130 | logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size); | 136 | logf("%s(EP%d, %d)", __func__, EP_NUMBER2(ep), size); |
131 | 137 | ||
132 | register unsigned int *d32 = (unsigned int *)EP_PTR(ep); | 138 | register unsigned int *d32 = (unsigned int *)EP_PTR(ep); |
133 | register unsigned char *d8 = (unsigned char *)EP_PTR(ep); | 139 | register size_t s = size >> 2; |
134 | register unsigned int s; | ||
135 | 140 | ||
136 | if(size > 0) | 141 | if(size > 0) |
137 | { | 142 | { |
138 | if(UNLIKELY((unsigned int)d8 & 3)) | 143 | while (s--) |
139 | { | 144 | REG32(ep->fifo_addr) = *d32++; |
140 | s = size; | 145 | |
141 | while(s--) | 146 | if( (s = size & 3) ) |
142 | REG8(ep->fifo_addr) = *d8++; | ||
143 | } | ||
144 | else | ||
145 | { | 147 | { |
146 | s = size >> 2; | 148 | register unsigned char *d8 = (unsigned char *)d32; |
147 | while (s--) | 149 | while (s--) |
148 | REG32(ep->fifo_addr) = *d32++; | 150 | REG8(ep->fifo_addr) = *d8++; |
149 | |||
150 | if( (s = size & 3) ) | ||
151 | { | ||
152 | d8 = (unsigned char *)d32; | ||
153 | while (s--) | ||
154 | REG8(ep->fifo_addr) = *d8++; | ||
155 | } | ||
156 | } | 151 | } |
157 | } | 152 | } |
158 | } | 153 | } |
159 | 154 | ||
160 | static void flushFIFO(struct usb_endpoint *ep) | 155 | static void flushFIFO(struct usb_endpoint *ep) |
161 | { | 156 | { |
162 | logf("flushFIFO(%d)", EP_NUMBER(ep)); | 157 | logf("%s(%d)", __func__, EP_NUMBER(ep)); |
163 | 158 | ||
164 | switch (ep->type) | 159 | switch (ep->type) |
165 | { | 160 | { |
@@ -168,6 +163,7 @@ static void flushFIFO(struct usb_endpoint *ep) | |||
168 | 163 | ||
169 | case ep_bulk: | 164 | case ep_bulk: |
170 | case ep_interrupt: | 165 | case ep_interrupt: |
166 | case ep_isochronous: | ||
171 | if(EP_IS_IN(ep)) | 167 | if(EP_IS_IN(ep)) |
172 | REG_USB_REG_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT); | 168 | REG_USB_REG_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT); |
173 | else | 169 | else |
@@ -193,9 +189,9 @@ static void EP0_send(void) | |||
193 | } | 189 | } |
194 | 190 | ||
195 | if(ep->sent == 0) | 191 | if(ep->sent == 0) |
196 | length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); | 192 | length = MIN(ep->length, ep->fifo_size); |
197 | else | 193 | else |
198 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); | 194 | length = MIN(EP_BUF_LEFT(ep), ep->fifo_size); |
199 | 195 | ||
200 | writeFIFO(ep, length); | 196 | writeFIFO(ep, length); |
201 | ep->sent += length; | 197 | ep->sent += length; |
@@ -205,7 +201,7 @@ static void EP0_send(void) | |||
205 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ | 201 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ |
206 | ep0state = USB_EP0_IDLE; | 202 | ep0state = USB_EP0_IDLE; |
207 | if(ep->wait) | 203 | if(ep->wait) |
208 | wakeup_signal(&ep_wkup[0]); | 204 | wakeup_signal(&ep->wakeup); |
209 | } | 205 | } |
210 | else | 206 | else |
211 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY); | 207 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY); |
@@ -213,7 +209,7 @@ static void EP0_send(void) | |||
213 | 209 | ||
214 | static void EP0_handler(void) | 210 | static void EP0_handler(void) |
215 | { | 211 | { |
216 | logf("EP0_handler"); | 212 | logf("%s()", __func__); |
217 | 213 | ||
218 | unsigned char csr0; | 214 | unsigned char csr0; |
219 | 215 | ||
@@ -252,7 +248,7 @@ static void EP0_handler(void) | |||
252 | REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ | 248 | REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ |
253 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[1].buf); | 249 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[1].buf); |
254 | if(endpoints[1].wait) | 250 | if(endpoints[1].wait) |
255 | wakeup_signal(&ep_wkup[1]); | 251 | wakeup_signal(&endpoints[1].wakeup); |
256 | } | 252 | } |
257 | } | 253 | } |
258 | else if(ep0state == USB_EP0_TX) | 254 | else if(ep0state == USB_EP0_TX) |
@@ -266,10 +262,13 @@ static void EPIN_handler(unsigned int endpoint) | |||
266 | 262 | ||
267 | select_endpoint(endpoint); | 263 | select_endpoint(endpoint); |
268 | csr = REG_USB_REG_INCSR; | 264 | csr = REG_USB_REG_INCSR; |
269 | logf("EPIN_handler(%d): 0x%x", endpoint, csr); | 265 | logf("%s(%d): 0x%x", __func__, endpoint, csr); |
270 | 266 | ||
271 | if(!ep->busy) | 267 | if(!ep->busy) |
268 | { | ||
269 | logf("Entered EPIN handler without work!"); | ||
272 | return; | 270 | return; |
271 | } | ||
273 | 272 | ||
274 | if(csr & USB_INCSR_SENTSTALL) | 273 | if(csr & USB_INCSR_SENTSTALL) |
275 | { | 274 | { |
@@ -289,9 +288,9 @@ static void EPIN_handler(unsigned int endpoint) | |||
289 | logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length); | 288 | logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length); |
290 | 289 | ||
291 | if(ep->sent == 0) | 290 | if(ep->sent == 0) |
292 | length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); | 291 | length = MIN(ep->length, ep->fifo_size); |
293 | else | 292 | else |
294 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); | 293 | length = MIN(EP_BUF_LEFT(ep), ep->fifo_size); |
295 | 294 | ||
296 | writeFIFO(ep, length); | 295 | writeFIFO(ep, length); |
297 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; | 296 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; |
@@ -301,7 +300,7 @@ static void EPIN_handler(unsigned int endpoint) | |||
301 | { | 300 | { |
302 | usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); | 301 | usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); |
303 | if(ep->wait) | 302 | if(ep->wait) |
304 | wakeup_signal(&ep_wkup[endpoint*2]); | 303 | wakeup_signal(&ep->wakeup); |
305 | logf("sent complete"); | 304 | logf("sent complete"); |
306 | ep->sent = 0; | 305 | ep->sent = 0; |
307 | ep->length = 0; | 306 | ep->length = 0; |
@@ -316,12 +315,15 @@ static void EPOUT_handler(unsigned int endpoint) | |||
316 | unsigned int size, csr; | 315 | unsigned int size, csr; |
317 | 316 | ||
318 | if(!ep->busy) | 317 | if(!ep->busy) |
318 | { | ||
319 | logf("Entered EPOUT handler without work!"); | ||
319 | return; | 320 | return; |
321 | } | ||
320 | 322 | ||
321 | select_endpoint(endpoint); | 323 | select_endpoint(endpoint); |
322 | while((csr = REG_USB_REG_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY)) | 324 | while((csr = REG_USB_REG_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY)) |
323 | { | 325 | { |
324 | logf("EPOUT_handler(%d): 0x%x", endpoint, csr); | 326 | logf("%s(%d): 0x%x", __func__, endpoint, csr); |
325 | if(csr & USB_OUTCSR_SENTSTALL) | 327 | if(csr & USB_OUTCSR_SENTSTALL) |
326 | { | 328 | { |
327 | logf("stall sent, flushing fifo.."); | 329 | logf("stall sent, flushing fifo.."); |
@@ -351,13 +353,12 @@ static void EPOUT_handler(unsigned int endpoint) | |||
351 | { | 353 | { |
352 | usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); | 354 | usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); |
353 | if(ep->wait) | 355 | if(ep->wait) |
354 | wakeup_signal(&ep_wkup[endpoint*2+1]); | 356 | wakeup_signal(&ep->wakeup); |
355 | logf("receive transfer_complete"); | 357 | logf("receive transfer_complete"); |
356 | ep->received = 0; | 358 | ep->received = 0; |
357 | ep->length = 0; | 359 | ep->length = 0; |
358 | ep->buf = NULL; | 360 | ep->buf = NULL; |
359 | ep->busy = false; | 361 | ep->busy = false; |
360 | return; | ||
361 | } | 362 | } |
362 | } | 363 | } |
363 | } | 364 | } |
@@ -365,8 +366,9 @@ static void EPOUT_handler(unsigned int endpoint) | |||
365 | 366 | ||
366 | static void EPDMA_handler(int number) | 367 | static void EPDMA_handler(int number) |
367 | { | 368 | { |
368 | int endpoint=-1; | 369 | int endpoint = -1; |
369 | unsigned int size=0; | 370 | unsigned int size = 0; |
371 | |||
370 | if(number == USB_INTR_DMA_BULKIN) | 372 | if(number == USB_INTR_DMA_BULKIN) |
371 | endpoint = (REG_USB_REG_CNTL1 >> 4) & 0xF; | 373 | endpoint = (REG_USB_REG_CNTL1 >> 4) & 0xF; |
372 | else if(number == USB_INTR_DMA_BULKOUT) | 374 | else if(number == USB_INTR_DMA_BULKOUT) |
@@ -398,8 +400,10 @@ static void EPDMA_handler(int number) | |||
398 | } | 400 | } |
399 | } | 401 | } |
400 | else if(number == USB_INTR_DMA_BULKIN && size % ep->fifo_size) | 402 | else if(number == USB_INTR_DMA_BULKIN && size % ep->fifo_size) |
403 | { | ||
401 | /* If the last packet is less than MAXP, set INPKTRDY manually */ | 404 | /* If the last packet is less than MAXP, set INPKTRDY manually */ |
402 | REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; | 405 | REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; |
406 | } | ||
403 | 407 | ||
404 | usb_core_transfer_complete(endpoint, EP_IS_IN(ep) ? USB_DIR_IN : USB_DIR_OUT, | 408 | usb_core_transfer_complete(endpoint, EP_IS_IN(ep) ? USB_DIR_IN : USB_DIR_OUT, |
405 | 0, ep->length); | 409 | 0, ep->length); |
@@ -409,7 +413,7 @@ static void EPDMA_handler(int number) | |||
409 | ep->length = 0; | 413 | ep->length = 0; |
410 | ep->buf = NULL; | 414 | ep->buf = NULL; |
411 | if(ep->wait) | 415 | if(ep->wait) |
412 | wakeup_signal(&ep_wkup[EP_NUMBER(ep)]); | 416 | wakeup_signal(&ep->wakeup); |
413 | } | 417 | } |
414 | 418 | ||
415 | static void setup_endpoint(struct usb_endpoint *ep) | 419 | static void setup_endpoint(struct usb_endpoint *ep) |
@@ -435,15 +439,16 @@ static void setup_endpoint(struct usb_endpoint *ep) | |||
435 | { | 439 | { |
436 | csr = (USB_INCSR_FF | USB_INCSR_CDT); | 440 | csr = (USB_INCSR_FF | USB_INCSR_CDT); |
437 | csrh = USB_INCSRH_MODE; | 441 | csrh = USB_INCSRH_MODE; |
442 | |||
438 | if(ep->use_dma) | 443 | if(ep->use_dma) |
439 | csrh |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE); | 444 | csrh |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE); |
440 | 445 | ||
441 | if(ep->type == ep_interrupt) | 446 | if(ep->type == ep_interrupt) |
442 | csrh |= USB_INCSRH_FRCDATATOG; | 447 | csrh |= USB_INCSRH_FRCDATATOG; |
443 | 448 | ||
444 | REG_USB_REG_INMAXP = ep->fifo_size; | 449 | REG_USB_REG_INMAXP = ep->fifo_size; |
445 | REG_USB_REG_INCSR = csr; | 450 | REG_USB_REG_INCSR = csr; |
446 | REG_USB_REG_INCSRH = csrh; | 451 | REG_USB_REG_INCSRH = csrh; |
447 | REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); | 452 | REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); |
448 | } | 453 | } |
449 | else | 454 | else |
@@ -457,9 +462,9 @@ static void setup_endpoint(struct usb_endpoint *ep) | |||
457 | if(ep->use_dma) | 462 | if(ep->use_dma) |
458 | csrh |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); | 463 | csrh |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); |
459 | 464 | ||
460 | REG_USB_REG_OUTMAXP = ep->fifo_size; | 465 | REG_USB_REG_OUTMAXP = ep->fifo_size; |
461 | REG_USB_REG_OUTCSR = csr; | 466 | REG_USB_REG_OUTCSR = csr; |
462 | REG_USB_REG_OUTCSRH = csrh; | 467 | REG_USB_REG_OUTCSRH = csrh; |
463 | REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); | 468 | REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); |
464 | } | 469 | } |
465 | } | 470 | } |
@@ -477,7 +482,7 @@ static void udc_reset(void) | |||
477 | * Generates a Reset interrupt. | 482 | * Generates a Reset interrupt. |
478 | */ | 483 | */ |
479 | 484 | ||
480 | logf("udc_reset()"); | 485 | logf("%s()", __func__); |
481 | 486 | ||
482 | unsigned int i; | 487 | unsigned int i; |
483 | 488 | ||
@@ -493,9 +498,6 @@ static void udc_reset(void) | |||
493 | REG_USB_REG_CNTL1 = 0; | 498 | REG_USB_REG_CNTL1 = 0; |
494 | REG_USB_REG_CNTL2 = 0; | 499 | REG_USB_REG_CNTL2 = 0; |
495 | 500 | ||
496 | /* Reset address */ | ||
497 | REG_USB_REG_FADDR = 0; | ||
498 | |||
499 | /* High speed, softconnect and suspend/resume */ | 501 | /* High speed, softconnect and suspend/resume */ |
500 | REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB | USB_POWER_SUSPENDM); | 502 | REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB | USB_POWER_SUSPENDM); |
501 | 503 | ||
@@ -508,7 +510,7 @@ static void udc_reset(void) | |||
508 | setup_endpoint(&endpoints[i]); | 510 | setup_endpoint(&endpoints[i]); |
509 | 511 | ||
510 | /* Enable interrupts */ | 512 | /* Enable interrupts */ |
511 | REG_USB_REG_INTRINE |= USB_INTR_EP0; | 513 | REG_USB_REG_INTRINE |= USB_INTR_EP0; |
512 | REG_USB_REG_INTRUSBE |= USB_INTR_RESET; | 514 | REG_USB_REG_INTRUSBE |= USB_INTR_RESET; |
513 | 515 | ||
514 | usb_core_bus_reset(); | 516 | usb_core_bus_reset(); |
@@ -523,9 +525,6 @@ void UDC(void) | |||
523 | unsigned short intrOut = REG_USB_REG_INTROUT; | 525 | unsigned short intrOut = REG_USB_REG_INTROUT; |
524 | unsigned char intrDMA = REG_USB_REG_INTR; | 526 | unsigned char intrDMA = REG_USB_REG_INTR; |
525 | 527 | ||
526 | if(UNLIKELY(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0)) | ||
527 | return; | ||
528 | |||
529 | logf("%x %x %x %x", intrUSB, intrIn, intrOut, intrDMA); | 528 | logf("%x %x %x %x", intrUSB, intrIn, intrOut, intrDMA); |
530 | 529 | ||
531 | /* EPIN & EPOUT are all handled in DMA */ | 530 | /* EPIN & EPOUT are all handled in DMA */ |
@@ -559,7 +558,7 @@ bool usb_drv_stalled(int endpoint, bool in) | |||
559 | { | 558 | { |
560 | endpoint &= 0x7F; | 559 | endpoint &= 0x7F; |
561 | 560 | ||
562 | logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); | 561 | logf("%s(%d, %s)", __func__, endpoint, in?"IN":"OUT"); |
563 | 562 | ||
564 | select_endpoint(endpoint); | 563 | select_endpoint(endpoint); |
565 | 564 | ||
@@ -578,7 +577,7 @@ void usb_drv_stall(int endpoint, bool stall, bool in) | |||
578 | { | 577 | { |
579 | endpoint &= 0x7F; | 578 | endpoint &= 0x7F; |
580 | 579 | ||
581 | logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"Y":"N", in?"IN":"OUT"); | 580 | logf("%s(%d,%s,%s)", __func__, endpoint, stall?"Y":"N", in?"IN":"OUT"); |
582 | 581 | ||
583 | select_endpoint(endpoint); | 582 | select_endpoint(endpoint); |
584 | 583 | ||
@@ -629,7 +628,7 @@ void usb_init_device(void) | |||
629 | system_enable_irq(IRQ_UDC); | 628 | system_enable_irq(IRQ_UDC); |
630 | 629 | ||
631 | for(i=0; i<TOTAL_EP(); i++) | 630 | for(i=0; i<TOTAL_EP(); i++) |
632 | wakeup_init(&ep_wkup[i]); | 631 | wakeup_init(&endpoints[i].wakeup); |
633 | } | 632 | } |
634 | 633 | ||
635 | #ifdef USB_GPIO_IRQ | 634 | #ifdef USB_GPIO_IRQ |
@@ -660,7 +659,7 @@ void usb_attach(void) | |||
660 | 659 | ||
661 | void usb_drv_init(void) | 660 | void usb_drv_init(void) |
662 | { | 661 | { |
663 | logf("usb_drv_init()"); | 662 | logf("%s()", __func__); |
664 | 663 | ||
665 | /* Set this bit to allow the UDC entering low-power mode when | 664 | /* Set this bit to allow the UDC entering low-power mode when |
666 | * there are no actions on the USB bus. | 665 | * there are no actions on the USB bus. |
@@ -681,10 +680,10 @@ void usb_drv_init(void) | |||
681 | 680 | ||
682 | void usb_drv_exit(void) | 681 | void usb_drv_exit(void) |
683 | { | 682 | { |
684 | logf("usb_drv_exit()"); | 683 | logf("%s()", __func__); |
685 | 684 | ||
686 | /* Disable interrupts */ | 685 | /* Disable interrupts */ |
687 | REG_USB_REG_INTRINE = 0; | 686 | REG_USB_REG_INTRINE = 0; |
688 | REG_USB_REG_INTROUTE = 0; | 687 | REG_USB_REG_INTROUTE = 0; |
689 | REG_USB_REG_INTRUSBE = 0; | 688 | REG_USB_REG_INTRUSBE = 0; |
690 | 689 | ||
@@ -703,41 +702,33 @@ void usb_drv_exit(void) | |||
703 | 702 | ||
704 | void usb_drv_set_address(int address) | 703 | void usb_drv_set_address(int address) |
705 | { | 704 | { |
706 | logf("set adr: %d", address); | 705 | logf("%s(%d)", __func__, address); |
707 | 706 | ||
708 | REG_USB_REG_FADDR = address; | 707 | REG_USB_REG_FADDR = address; |
709 | } | 708 | } |
710 | 709 | ||
711 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) | 710 | static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length, bool blocking) |
712 | { | 711 | { |
713 | int flags; | 712 | if(ep->type == ep_control && ptr == NULL && length == 0) |
714 | endpoint &= 0x7F; | 713 | return; /* ACK request, handled by the USB controller */ |
715 | 714 | ||
716 | logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); | 715 | int flags = disable_irq_save(); |
717 | 716 | ||
718 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) | 717 | ep->buf = ptr; |
719 | return 0; /* ACK request, handled by the USB controller */ | 718 | ep->sent = 0; |
719 | ep->length = length; | ||
720 | ep->busy = true; | ||
721 | if(blocking) | ||
722 | ep->wait = true; | ||
720 | 723 | ||
721 | if(endpoint == EP_CONTROL) | 724 | if(ep->type == ep_control) |
722 | { | 725 | { |
723 | flags = disable_irq_save(); | ||
724 | endpoints[0].buf = ptr; | ||
725 | endpoints[0].sent = 0; | ||
726 | endpoints[0].length = length; | ||
727 | ep0state = USB_EP0_TX; | 726 | ep0state = USB_EP0_TX; |
728 | EP0_send(); | 727 | EP0_send(); |
729 | restore_irq(flags); | ||
730 | |||
731 | return 0; | ||
732 | } | 728 | } |
733 | else | 729 | else |
734 | { | 730 | { |
735 | flags = disable_irq_save(); | 731 | if(ep->use_dma) |
736 | endpoints[endpoint*2].buf = ptr; | ||
737 | endpoints[endpoint*2].sent = 0; | ||
738 | endpoints[endpoint*2].length = length; | ||
739 | endpoints[endpoint*2].busy = true; | ||
740 | if(endpoints[endpoint*2].use_dma) | ||
741 | { | 732 | { |
742 | //dma_cache_wback_inv((unsigned long)ptr, length); | 733 | //dma_cache_wback_inv((unsigned long)ptr, length); |
743 | __dcache_writeback_all(); | 734 | __dcache_writeback_all(); |
@@ -745,49 +736,59 @@ int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) | |||
745 | REG_USB_REG_COUNT1 = length; | 736 | REG_USB_REG_COUNT1 = length; |
746 | REG_USB_REG_CNTL1 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | | 737 | REG_USB_REG_CNTL1 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | |
747 | USB_CNTL_DIR_IN | USB_CNTL_ENA | | 738 | USB_CNTL_DIR_IN | USB_CNTL_ENA | |
748 | USB_CNTL_EP(endpoint) | USB_CNTL_BURST_16); | 739 | USB_CNTL_EP(EP_NUMBER2(ep)) | USB_CNTL_BURST_16); |
749 | } | 740 | } |
750 | else | 741 | else |
751 | EPIN_handler(endpoint); | 742 | EPIN_handler(EP_NUMBER2(ep)); |
743 | } | ||
752 | 744 | ||
753 | restore_irq(flags); | 745 | restore_irq(flags); |
754 | return 0; | 746 | |
747 | if(blocking) | ||
748 | { | ||
749 | wakeup_wait(&ep->wakeup, TIMEOUT_BLOCK); | ||
750 | ep->wait = false; | ||
755 | } | 751 | } |
756 | } | 752 | } |
757 | 753 | ||
758 | int usb_drv_send(int endpoint, void* ptr, int length) | 754 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) |
759 | { | 755 | { |
760 | int ret; | 756 | logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length); |
761 | endpoint &= 0x7F; | ||
762 | 757 | ||
763 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) | 758 | usb_drv_send_internal(&endpoints[(endpoint & 0x7F)*2], ptr, length, false); |
764 | return 0; /* ACK request, handled by the USB controller */ | ||
765 | 759 | ||
766 | endpoints[endpoint*2].wait = true; | 760 | return 0; |
767 | ret = usb_drv_send_nonblocking(endpoint, ptr, length); | 761 | } |
768 | wakeup_wait(&ep_wkup[endpoint*2], TIMEOUT_BLOCK); | 762 | |
769 | endpoints[endpoint*2].wait = false; | 763 | int usb_drv_send(int endpoint, void* ptr, int length) |
764 | { | ||
765 | logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length); | ||
770 | 766 | ||
771 | return ret; | 767 | usb_drv_send_internal(&endpoints[(endpoint & 0x7F)*2], ptr, length, true); |
768 | |||
769 | return 0; | ||
772 | } | 770 | } |
773 | 771 | ||
774 | int usb_drv_recv(int endpoint, void* ptr, int length) | 772 | int usb_drv_recv(int endpoint, void* ptr, int length) |
775 | { | 773 | { |
776 | int flags; | 774 | int flags; |
775 | struct usb_endpoint *ep; | ||
777 | endpoint &= 0x7F; | 776 | endpoint &= 0x7F; |
778 | 777 | ||
779 | logf("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); | 778 | logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length); |
780 | 779 | ||
781 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) | 780 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) |
782 | return 0; /* ACK request, handled by the USB controller */ | 781 | return 0; /* ACK request, handled by the USB controller */ |
783 | else | 782 | else |
784 | { | 783 | { |
785 | flags = disable_irq_save(); | 784 | flags = disable_irq_save(); |
786 | endpoints[endpoint*2+1].buf = ptr; | 785 | ep = &endpoints[endpoint*2+1]; |
787 | endpoints[endpoint*2+1].received = 0; | 786 | |
788 | endpoints[endpoint*2+1].length = length; | 787 | ep->buf = ptr; |
789 | endpoints[endpoint*2+1].busy = true; | 788 | ep->received = 0; |
790 | if(endpoints[endpoint*2+1].use_dma) | 789 | ep->length = length; |
790 | ep->busy = true; | ||
791 | if(ep->use_dma) | ||
791 | { | 792 | { |
792 | //dma_cache_wback_inv((unsigned long)ptr, length); | 793 | //dma_cache_wback_inv((unsigned long)ptr, length); |
793 | __dcache_writeback_all(); | 794 | __dcache_writeback_all(); |
@@ -807,7 +808,7 @@ int usb_drv_recv(int endpoint, void* ptr, int length) | |||
807 | 808 | ||
808 | void usb_drv_set_test_mode(int mode) | 809 | void usb_drv_set_test_mode(int mode) |
809 | { | 810 | { |
810 | logf("usb_drv_set_test_mode(%d)", mode); | 811 | logf("%s(%d)", __func__, mode); |
811 | 812 | ||
812 | switch(mode) | 813 | switch(mode) |
813 | { | 814 | { |
@@ -836,7 +837,7 @@ int usb_drv_port_speed(void) | |||
836 | 837 | ||
837 | void usb_drv_cancel_all_transfers(void) | 838 | void usb_drv_cancel_all_transfers(void) |
838 | { | 839 | { |
839 | logf("usb_drv_cancel_all_transfers()"); | 840 | logf("%s()", __func__); |
840 | 841 | ||
841 | unsigned int i, flags; | 842 | unsigned int i, flags; |
842 | flags = disable_irq_save(); | 843 | flags = disable_irq_save(); |
@@ -860,12 +861,12 @@ void usb_drv_cancel_all_transfers(void) | |||
860 | void usb_drv_release_endpoint(int ep) | 861 | void usb_drv_release_endpoint(int ep) |
861 | { | 862 | { |
862 | (void)ep; | 863 | (void)ep; |
863 | logf("usb_drv_release_endpoint(%d, %s)", (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); | 864 | logf("%s(%d, %s)", __func__, (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); |
864 | } | 865 | } |
865 | 866 | ||
866 | int usb_drv_request_endpoint(int type, int dir) | 867 | int usb_drv_request_endpoint(int type, int dir) |
867 | { | 868 | { |
868 | logf("usb_drv_request_endpoint(%d, %s)", type, (dir == USB_DIR_IN) ? "IN" : "OUT"); | 869 | logf("%s(%d, %s)", __func__, type, (dir == USB_DIR_IN) ? "IN" : "OUT"); |
869 | 870 | ||
870 | dir &= USB_ENDPOINT_DIR_MASK; | 871 | dir &= USB_ENDPOINT_DIR_MASK; |
871 | type &= USB_ENDPOINT_XFERTYPE_MASK; | 872 | type &= USB_ENDPOINT_XFERTYPE_MASK; |