diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-12-31 18:15:24 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-12-31 18:15:24 +0000 |
commit | 5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a (patch) | |
tree | 410a1436005800874a2ff3939e2671b972901f97 /firmware/target | |
parent | a2e80d573ca83a66b3aacdf9fe966c9528918c15 (diff) | |
download | rockbox-5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a.tar.gz rockbox-5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a.zip |
Ingenic Jz4740:
* Fix compiling
* More USB work
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19628 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 87 |
1 files changed, 62 insertions, 25 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index eda3fb3b88..cc8d5afa20 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |||
@@ -30,6 +30,12 @@ | |||
30 | #include "jz4740.h" | 30 | #include "jz4740.h" |
31 | #include "thread.h" | 31 | #include "thread.h" |
32 | 32 | ||
33 | /* | ||
34 | The Jz4740 USB controller is called MUSBHSFC in the datasheet. | ||
35 | It also seems to be a more generic controller, with support for | ||
36 | up to 15 endpoints (the Jz4740 only has 3). | ||
37 | */ | ||
38 | |||
33 | #define USB_EP0_IDLE 0 | 39 | #define USB_EP0_IDLE 0 |
34 | #define USB_EP0_RX 1 | 40 | #define USB_EP0_RX 1 |
35 | #define USB_EP0_TX 2 | 41 | #define USB_EP0_TX 2 |
@@ -162,13 +168,16 @@ static void flushFIFO(struct usb_endpoint *ep) | |||
162 | 168 | ||
163 | static void EP0_send(void) | 169 | static void EP0_send(void) |
164 | { | 170 | { |
165 | register struct usb_endpoint* ep = &endpoints[1]; | 171 | struct usb_endpoint* ep = &endpoints[1]; |
166 | register unsigned int length; | 172 | unsigned int length; |
173 | unsigned char csr0; | ||
174 | |||
175 | select_endpoint(0); | ||
176 | csr0 = REG_USB_REG_CSR0; | ||
167 | 177 | ||
168 | if(ep->length == 0) | 178 | if(ep->length == 0) |
169 | { | 179 | { |
170 | select_endpoint(0); | 180 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND); |
171 | REG_USB_REG_CSR0 |= (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND); | ||
172 | return; | 181 | return; |
173 | } | 182 | } |
174 | 183 | ||
@@ -177,22 +186,22 @@ static void EP0_send(void) | |||
177 | else | 186 | else |
178 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); | 187 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); |
179 | 188 | ||
180 | select_endpoint(0); | ||
181 | writeFIFO(ep, length); | 189 | writeFIFO(ep, length); |
182 | ep->sent += length; | 190 | ep->sent += length; |
183 | 191 | ||
184 | if(ep->sent >= ep->length) | 192 | if(ep->sent >= ep->length) |
185 | { | 193 | { |
186 | REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ | 194 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ |
187 | ep0state = USB_EP0_IDLE; | 195 | ep0state = USB_EP0_IDLE; |
188 | } | 196 | } |
189 | else | 197 | else |
190 | REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; | 198 | REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY); |
191 | } | 199 | } |
192 | 200 | ||
193 | static void EP0_handler(void) | 201 | static void EP0_handler(void) |
194 | { | 202 | { |
195 | logf("EP0_handler"); | 203 | logf("EP0_handler"); |
204 | |||
196 | register unsigned char csr0; | 205 | register unsigned char csr0; |
197 | 206 | ||
198 | /* Read CSR0 */ | 207 | /* Read CSR0 */ |
@@ -204,7 +213,7 @@ logf("EP0_handler"); | |||
204 | */ | 213 | */ |
205 | if (csr0 & USB_CSR0_SENTSTALL) | 214 | if (csr0 & USB_CSR0_SENTSTALL) |
206 | { | 215 | { |
207 | REG_USB_REG_CSR0 &= ~USB_CSR0_SENTSTALL; | 216 | REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL; |
208 | ep0state = USB_EP0_IDLE; | 217 | ep0state = USB_EP0_IDLE; |
209 | return; | 218 | return; |
210 | } | 219 | } |
@@ -214,20 +223,20 @@ logf("EP0_handler"); | |||
214 | An interrupt will be generated and the FIFO flushed at this time. | 223 | An interrupt will be generated and the FIFO flushed at this time. |
215 | The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. | 224 | The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. |
216 | */ | 225 | */ |
217 | if (csr0 & USB_CSR0_SETUPEND) | 226 | if (csr0 & USB_CSR0_SETUPEND) |
218 | { | 227 | { |
219 | REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; | 228 | REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDSETUPEND; |
220 | ep0state = USB_EP0_IDLE; | 229 | ep0state = USB_EP0_IDLE; |
221 | return; | 230 | return; |
222 | } | 231 | } |
223 | 232 | ||
224 | /* Call relevant routines for endpoint 0 state */ | 233 | /* Call relevant routines for endpoint 0 state */ |
225 | if (ep0state == USB_EP0_IDLE) | 234 | if (ep0state == USB_EP0_IDLE) |
226 | { | 235 | { |
227 | if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ | 236 | if(csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ |
228 | { | 237 | { |
229 | readFIFO(&endpoints[0], REG_USB_REG_COUNT0); | 238 | readFIFO(&endpoints[0], REG_USB_REG_COUNT0); |
230 | REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ | 239 | REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ |
231 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); | 240 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); |
232 | } | 241 | } |
233 | } | 242 | } |
@@ -237,14 +246,15 @@ logf("EP0_handler"); | |||
237 | 246 | ||
238 | static void EPIN_handler(unsigned int endpoint) | 247 | static void EPIN_handler(unsigned int endpoint) |
239 | { | 248 | { |
240 | logf("EPIN_handler(%d)", endpoint); | 249 | logf("EPIN_handler(%d)", endpoint); |
250 | |||
241 | struct usb_endpoint* ep = &endpoints[endpoint*2+1]; | 251 | struct usb_endpoint* ep = &endpoints[endpoint*2+1]; |
242 | unsigned int length, csr; | 252 | unsigned int length, csr; |
243 | 253 | ||
244 | select_endpoint(endpoint); | 254 | select_endpoint(endpoint); |
245 | csr = REG_USB_REG_INCSR; | 255 | csr = REG_USB_REG_INCSR; |
246 | 256 | ||
247 | if(ep->length == 0) | 257 | if(ep->buf == NULL || ep->length == 0) |
248 | { | 258 | { |
249 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; | 259 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; |
250 | return; | 260 | return; |
@@ -266,19 +276,25 @@ logf("EPIN_handler(%d)", endpoint); | |||
266 | 276 | ||
267 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; | 277 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; |
268 | if(ep->sent >= ep->length) | 278 | if(ep->sent >= ep->length) |
269 | usb_core_transfer_complete(endpoint|USB_DIR_IN, USB_DIR_IN, 0, ep->sent); | 279 | { |
280 | usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); | ||
281 | ep->sent = 0; | ||
282 | ep->length = 0; | ||
283 | ep->buf = NULL; | ||
284 | } | ||
270 | } | 285 | } |
271 | 286 | ||
272 | static void EPOUT_handler(unsigned int endpoint) | 287 | static void EPOUT_handler(unsigned int endpoint) |
273 | { | 288 | { |
274 | logf("EPOUT_handler(%d)", endpoint); | 289 | logf("EPOUT_handler(%d)", endpoint); |
290 | |||
275 | struct usb_endpoint* ep = &endpoints[endpoint*2]; | 291 | struct usb_endpoint* ep = &endpoints[endpoint*2]; |
276 | unsigned int size, csr; | 292 | unsigned int size, csr; |
277 | 293 | ||
278 | select_endpoint(endpoint); | 294 | select_endpoint(endpoint); |
279 | csr = REG_USB_REG_OUTCSR; | 295 | csr = REG_USB_REG_OUTCSR; |
280 | 296 | ||
281 | if(ep->buf == NULL && ep->length == 0) | 297 | if(ep->buf == NULL || ep->length == 0) |
282 | { | 298 | { |
283 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; | 299 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; |
284 | return; | 300 | return; |
@@ -291,16 +307,21 @@ logf("EPOUT_handler(%d)", endpoint); | |||
291 | } | 307 | } |
292 | 308 | ||
293 | size = REG_USB_REG_OUTCOUNT; | 309 | size = REG_USB_REG_OUTCOUNT; |
294 | ep->received += size; | ||
295 | 310 | ||
296 | readFIFO(ep, size); | 311 | readFIFO(ep, size); |
312 | ep->received += size; | ||
297 | 313 | ||
298 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; | 314 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; |
299 | 315 | ||
300 | logf("received: %d length: %d", ep->received, ep->length); | 316 | logf("received: %d length: %d", ep->received, ep->length); |
301 | 317 | ||
302 | //if(ep->received >= ep->length) | 318 | if(size < ep->fifo_size || ep->received >= ep->length) |
303 | usb_core_transfer_complete(endpoint|USB_DIR_OUT, USB_DIR_OUT, 0, ep->received); | 319 | { |
320 | usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); | ||
321 | ep->received = 0; | ||
322 | ep->length = 0; | ||
323 | ep->buf = NULL; | ||
324 | } | ||
304 | } | 325 | } |
305 | 326 | ||
306 | static void setup_endpoint(struct usb_endpoint *ep) | 327 | static void setup_endpoint(struct usb_endpoint *ep) |
@@ -351,6 +372,17 @@ static void setup_endpoint(struct usb_endpoint *ep) | |||
351 | 372 | ||
352 | static void udc_reset(void) | 373 | static void udc_reset(void) |
353 | { | 374 | { |
375 | /* From the datasheet: | ||
376 | |||
377 | When a reset condition is detected on the USB, the controller performs the following actions: | ||
378 | * Sets FAddr to 0. | ||
379 | * Sets Index to 0. | ||
380 | * Flushes all endpoint FIFOs. | ||
381 | * Clears all control/status registers. | ||
382 | * Enables all endpoint interrupts. | ||
383 | * Generates a Reset interrupt. | ||
384 | */ | ||
385 | |||
354 | logf("udc_reset()"); | 386 | logf("udc_reset()"); |
355 | 387 | ||
356 | register unsigned int i; | 388 | register unsigned int i; |
@@ -371,8 +403,7 @@ static void udc_reset(void) | |||
371 | REG_USB_REG_FADDR = 0; | 403 | REG_USB_REG_FADDR = 0; |
372 | 404 | ||
373 | /* High speed and softconnect */ | 405 | /* High speed and softconnect */ |
374 | //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); | 406 | REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); |
375 | REG_USB_REG_POWER = USB_POWER_SOFTCONN; | ||
376 | 407 | ||
377 | /* Enable SUSPEND */ | 408 | /* Enable SUSPEND */ |
378 | /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ | 409 | /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ |
@@ -560,6 +591,9 @@ int usb_drv_send(int endpoint, void* ptr, int length) | |||
560 | 591 | ||
561 | logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); | 592 | logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); |
562 | 593 | ||
594 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) | ||
595 | return 0; /* ACK request, handled by the USB controller */ | ||
596 | |||
563 | if(endpoint == EP_CONTROL) | 597 | if(endpoint == EP_CONTROL) |
564 | { | 598 | { |
565 | flags = disable_irq_save(); | 599 | flags = disable_irq_save(); |
@@ -657,9 +691,12 @@ void usb_drv_cancel_all_transfers(void) | |||
657 | 691 | ||
658 | unsigned int i, flags; | 692 | unsigned int i, flags; |
659 | flags = disable_irq_save(); | 693 | flags = disable_irq_save(); |
660 | 694 | ||
661 | for(i=0; i<TOTAL_EP(); i++) | 695 | for(i=0; i<TOTAL_EP(); i++) |
662 | { | 696 | { |
697 | if(i > 2) | ||
698 | endpoints[i].buf = NULL; | ||
699 | |||
663 | endpoints[i].sent = 0; | 700 | endpoints[i].sent = 0; |
664 | endpoints[i].length = 0; | 701 | endpoints[i].length = 0; |
665 | 702 | ||