summaryrefslogtreecommitdiff
path: root/firmware/target/mips
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c87
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
163static void EP0_send(void) 169static 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
193static void EP0_handler(void) 201static void EP0_handler(void)
194{ 202{
195logf("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
238static void EPIN_handler(unsigned int endpoint) 247static void EPIN_handler(unsigned int endpoint)
239{ 248{
240logf("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
272static void EPOUT_handler(unsigned int endpoint) 287static void EPOUT_handler(unsigned int endpoint)
273{ 288{
274logf("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
306static void setup_endpoint(struct usb_endpoint *ep) 327static void setup_endpoint(struct usb_endpoint *ep)
@@ -351,6 +372,17 @@ static void setup_endpoint(struct usb_endpoint *ep)
351 372
352static void udc_reset(void) 373static 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