summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525v2.c134
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525v2.h18
2 files changed, 108 insertions, 44 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c
index fc6b858755..0149cac653 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525v2.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c
@@ -137,8 +137,7 @@ static void usb_enable_device_interrupts(void)
137 | USB_GINTMSK_inepintr 137 | USB_GINTMSK_inepintr
138 | USB_GINTMSK_outepintr 138 | USB_GINTMSK_outepintr
139 | USB_GINTMSK_otgintr 139 | USB_GINTMSK_otgintr
140 | USB_GINTMSK_usbsuspend 140 | USB_GINTMSK_disconnect;
141 | USB_GINTMSK_wkupintr;
142} 141}
143 142
144static void usb_flush_tx_fifos(int nums) 143static void usb_flush_tx_fifos(int nums)
@@ -209,24 +208,24 @@ static void reset_endpoints(void)
209 * transfer size = 64 208 * transfer size = 64
210 * Setup EP0 IN/OUT with 64 byte maximum packet size and activate both. Enable transfer on EP0 OUT 209 * Setup EP0 IN/OUT with 64 byte maximum packet size and activate both. Enable transfer on EP0 OUT
211 */ 210 */
212
213 /* 64 bytes packet size, active endpoint */
214 USB_DOEPCTL(0) = USB_DEPCTL_usbactep | (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos);
215 211
216 USB_DOEPTSIZ(0) = (1 << USB_DEPTSIZ0_supcnt_bit_pos) 212 USB_DOEPTSIZ(0) = (1 << USB_DEPTSIZ0_supcnt_bit_pos)
217 | (1 << USB_DEPTSIZ0_pkcnt_bit_pos) 213 | (1 << USB_DEPTSIZ0_pkcnt_bit_pos)
218 | 64; 214 | 8;
219 215
220 /* setup DMA */ 216 /* setup DMA */
221 clean_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */ 217 clean_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */
222 USB_DOEPDMA(0) = (unsigned long)&ep0_setup_pkt; /* virtual address=physical address */ 218 USB_DOEPDMA(0) = (unsigned long)&ep0_setup_pkt; /* virtual address=physical address */
223 219
224 /* Enable endpoint, clear nak */ 220 /* Enable endpoint, clear nak */
225 USB_DOEPCTL(0) |= USB_DEPCTL_epena | USB_DEPCTL_cnak; 221 USB_DOEPCTL(0) = USB_DEPCTL_epena | USB_DEPCTL_cnak | USB_DEPCTL_usbactep
222 | (USB_DEPCTL_MPS_8 << USB_DEPCTL_mps_bit_pos);
226 223
227 /* 64 bytes packet size, active endpoint */ 224 /* 64 bytes packet size, active endpoint */
228 USB_DIEPCTL(0) = (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos) 225 USB_DIEPCTL(0) = (USB_DEPCTL_MPS_8 << USB_DEPCTL_mps_bit_pos)
229 | USB_DEPCTL_usbactep; 226 | USB_DEPCTL_usbactep;
227
228 USB_DCTL = USB_DCTL_cgnpinnak | USB_DCTL_cgoutnak;
230} 229}
231 230
232static void core_dev_init(void) 231static void core_dev_init(void)
@@ -251,6 +250,13 @@ static void core_dev_init(void)
251 if(USB_GHWCFG4_DED_FIFO_EN != 1) /* it seems to be multiple tx fifo support */ 250 if(USB_GHWCFG4_DED_FIFO_EN != 1) /* it seems to be multiple tx fifo support */
252 panicf("usb: no multiple tx fifo"); 251 panicf("usb: no multiple tx fifo");
253 252
253 #ifdef USB_USE_CUSTOM_FIFO_LAYOUT
254 if(USB_GHWCFG2_DYN_FIFO != 1)
255 panicf("usb: no dynamic fifo");
256 if(USB_GRXFSIZ != USB_DATA_FIFO_DEPTH)
257 panicf("usb: wrong data fifo size");
258 #endif /* USB_USE_CUSTOM_FIFO_LAYOUT */
259
254 /* do some logging */ 260 /* do some logging */
255 logf("hwcfg1: %08lx", USB_GHWCFG1); 261 logf("hwcfg1: %08lx", USB_GHWCFG1);
256 logf("hwcfg2: %08lx", USB_GHWCFG2); 262 logf("hwcfg2: %08lx", USB_GHWCFG2);
@@ -277,13 +283,42 @@ static void core_dev_init(void)
277 panicf("usb: num out ep static mismatch(%u,%u)", usb_num_out_ep, USB_NUM_OUT_EP); 283 panicf("usb: num out ep static mismatch(%u,%u)", usb_num_out_ep, USB_NUM_OUT_EP);
278 284
279 logf("%d in ep, %d out ep", usb_num_in_ep, usb_num_out_ep); 285 logf("%d in ep, %d out ep", usb_num_in_ep, usb_num_out_ep);
280 /* 286
281 logf("initial:"); 287 logf("initial:");
282 logf(" tot fifo sz: %lx", USB_GHWCFG3_DFIFO_LEN); 288 logf(" tot fifo sz: %lx", USB_GHWCFG3_DFIFO_LEN);
283 logf(" rx fifo: [%04x,+%4lx]", 0, USB_GRXFSIZ); 289 logf(" rx fifo: [%04x,+%4lx]", 0, USB_GRXFSIZ);
284 logf(" nptx fifo: [%04lx,+%4lx]", USB_GET_FIFOSIZE_START_ADR(USB_GNPTXFSIZ), 290 logf(" nptx fifo: [%04lx,+%4lx]", USB_GET_FIFOSIZE_START_ADR(USB_GNPTXFSIZ),
285 USB_GET_FIFOSIZE_DEPTH(USB_GNPTXFSIZ)); 291 USB_GET_FIFOSIZE_DEPTH(USB_GNPTXFSIZ));
286 */ 292
293 #ifdef USB_USE_CUSTOM_FIFO_LAYOUT
294 /* Setup FIFOs */
295 /* Organize FIFO as follow:
296 * 0 -> rxfsize : RX fifo
297 * rxfsize -> rxfsize + nptxfsize : TX fifo for first IN ep
298 * rxfsize + nptxfsize -> rxfsize + 2 * nptxfsize : TX fifo for second IN ep
299 * rxfsize + 2 * nptxfsize -> rxfsize + 3 * nptxfsize : TX fifo for third IN ep
300 * ...
301 */
302
303 unsigned short adr = 0;
304 unsigned short depth = USB_RX_FIFO_SIZE;
305 USB_GRXFSIZ = depth;
306 adr += depth;
307 depth = USB_NPTX_FIFO_SIZE;
308 USB_GNPTXFSIZ = USB_MAKE_FIFOSIZE_DATA(adr, depth);
309 adr += depth;
310
311 for(i = 1; i <= USB_NUM_IN_EP; i++)
312 {
313 depth = USB_EPTX_FIFO_SIZE;
314 USB_DIEPTXFSIZ(i) = USB_MAKE_FIFOSIZE_DATA(adr, depth);
315 adr += depth;
316 }
317
318 if(adr > USB_DATA_FIFO_DEPTH)
319 panicf("usb: total data fifo size exceeded");
320 #endif /* USB_USE_CUSTOM_FIFO_LAYOUT */
321
287 for(i = 1; i <= USB_NUM_IN_EP; i++) 322 for(i = 1; i <= USB_NUM_IN_EP; i++)
288 { 323 {
289 logf(" dieptx fifo(%2u): [%04lx,+%4lx]", i, 324 logf(" dieptx fifo(%2u): [%04lx,+%4lx]", i,
@@ -291,22 +326,12 @@ static void core_dev_init(void)
291 USB_GET_FIFOSIZE_DEPTH(USB_DIEPTXFSIZ(i))); 326 USB_GET_FIFOSIZE_DEPTH(USB_DIEPTXFSIZ(i)));
292 } 327 }
293 328
294 /* flush the fifos */ 329 /* Setup interrupt masks for endpoints */
295 usb_flush_tx_fifos(0x10); /* flush all */
296 usb_flush_rx_fifo();
297
298 /* flush learning queue */
299 USB_GRSTCTL = USB_GRSTCTL_intknqflsh;
300
301 /* Clear all pending device interrupts */
302 USB_DAINT = 0xffffffff;
303 /* Setup interrupt masks for enpoints */
304 /* Setup interrupt masks */ 330 /* Setup interrupt masks */
305 USB_DOEPMSK = USB_DOEPINT_setup | USB_DOEPINT_xfercompl | USB_DOEPINT_ahberr 331 USB_DOEPMSK = USB_DOEPINT_setup | USB_DOEPINT_xfercompl | USB_DOEPINT_ahberr
306 | USB_DOEPINT_epdisabled; 332 | USB_DOEPINT_epdisabled;
307 USB_DIEPMSK = USB_DIEPINT_xfercompl | USB_DIEPINT_timeout 333 USB_DIEPMSK = USB_DIEPINT_xfercompl | USB_DIEPINT_timeout
308 | USB_DIEPINT_epdisabled | USB_DIEPINT_ahberr 334 | USB_DIEPINT_epdisabled | USB_DIEPINT_ahberr;
309 | USB_DIEPINT_intknepmis;
310 USB_DAINTMSK = 0xffffffff; 335 USB_DAINTMSK = 0xffffffff;
311 336
312 reset_endpoints(); 337 reset_endpoints();
@@ -322,27 +347,32 @@ static void core_dev_init(void)
322 logf(" rx_thr_len: %lu", (USB_DTHRCTL & USB_DTHRCTL_rx_thr_len_bits) >> USB_DTHRCTL_rx_thr_len_bit_pos); 347 logf(" rx_thr_len: %lu", (USB_DTHRCTL & USB_DTHRCTL_rx_thr_len_bits) >> USB_DTHRCTL_rx_thr_len_bit_pos);
323 */ 348 */
324 349
350 USB_DTHRCTL = 0;
351
325 /* enable USB interrupts */ 352 /* enable USB interrupts */
326 usb_enable_device_interrupts(); 353 usb_enable_device_interrupts();
327} 354}
328 355
329static void core_init(void) 356static void core_init(void)
330{ 357{
358 /* Disconnect */
359 USB_DCTL |= USB_DCTL_sftdiscon;
331 /* Select UTMI+ 16 */ 360 /* Select UTMI+ 16 */
332 USB_GUSBCFG |= USB_GUSBCFG_phy_if; 361 USB_GUSBCFG |= USB_GUSBCFG_phy_if;
333 /* core reset */ 362
334 core_reset();
335
336 /* fixme: the current code is for internal DMA only, the clip+ architecture 363 /* fixme: the current code is for internal DMA only, the clip+ architecture
337 * define the internal DMA model */ 364 * define the internal DMA model */
338 /* Set burstlen and enable DMA*/ 365 /* Set burstlen and enable DMA*/
339 USB_GAHBCFG = (USB_GAHBCFG_INT_DMA_BURST_INCR << USB_GAHBCFG_hburstlen_bit_pos) 366 USB_GAHBCFG = (USB_GAHBCFG_INT_DMA_BURST_INCR4 << USB_GAHBCFG_hburstlen_bit_pos)
340 | USB_GAHBCFG_dma_enable; 367 | USB_GAHBCFG_dma_enable;
341 /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */ 368 /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */
342 USB_GUSBCFG &= ~(USB_GUSBCFG_srpcap | USB_GUSBCFG_hnpcapp); 369 USB_GUSBCFG &= ~(USB_GUSBCFG_srpcap | USB_GUSBCFG_hnpcapp);
343 370
344 /* perform device model specific init */ 371 /* perform device model specific init */
345 core_dev_init(); 372 core_dev_init();
373
374 /* Reconnect */
375 USB_DCTL &= ~USB_DCTL_sftdiscon;
346} 376}
347 377
348static void usb_enable_global_interrupts(void) 378static void usb_enable_global_interrupts(void)
@@ -381,8 +411,8 @@ static bool handle_usb_reset(void)
381 /* Clear the Remote Wakeup Signalling */ 411 /* Clear the Remote Wakeup Signalling */
382 USB_DCTL &= ~USB_DCTL_rmtwkupsig; 412 USB_DCTL &= ~USB_DCTL_rmtwkupsig;
383 413
384 /* Flush the NP Tx FIFO */ 414 /* Flush FIFOs */
385 usb_flush_tx_fifos(0); 415 usb_flush_tx_fifos(0x10);
386 416
387 /* Flush the Learning Queue */ 417 /* Flush the Learning Queue */
388 USB_GRSTCTL = USB_GRSTCTL_intknqflsh; 418 USB_GRSTCTL = USB_GRSTCTL_intknqflsh;
@@ -397,20 +427,6 @@ static bool handle_usb_reset(void)
397 return true; 427 return true;
398} 428}
399 429
400static bool handle_usb_suspend(void)
401{
402 logf("usb: suspend");
403
404 return true;
405}
406
407static bool handle_wake_up(void)
408{
409 logf("usb: wake up");
410
411 return true;
412}
413
414static bool handle_enum_done(void) 430static bool handle_enum_done(void)
415{ 431{
416 logf("usb: enum done"); 432 logf("usb: enum done");
@@ -430,6 +446,38 @@ static bool handle_enum_done(void)
430 logf("GAHBCFG=%lx", USB_GAHBCFG); 446 logf("GAHBCFG=%lx", USB_GAHBCFG);
431 logf("GUSBCFG=%lx", USB_GUSBCFG); 447 logf("GUSBCFG=%lx", USB_GUSBCFG);
432 logf("DCFG=%lx", USB_DCFG); 448 logf("DCFG=%lx", USB_DCFG);
449 logf("DTHRCTL=%lx", USB_DTHRCTL);
450
451 switch((USB_DSTS & USB_DSTS_enumspd_bits) >> USB_DSTS_enumspd_bit_pos)
452 {
453 case USB_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
454 logf("usb: HS");
455 break;
456 case USB_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
457 case USB_DSTS_ENUMSPD_FS_PHY_48MHZ:
458 logf("usb: FS");
459 break;
460 case USB_DSTS_ENUMSPD_LS_PHY_6MHZ:
461 panicf("usb: LS is not supported");
462 }
463
464 USB_DOEPCTL(0) = (USB_DOEPCTL(0) & ~USB_DEPCTL_mps_bits)
465 | (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos);
466 USB_DIEPCTL(0) = (USB_DIEPCTL(0) & ~USB_DEPCTL_mps_bits)
467 | (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos);
468
469 unsigned i, ep;
470 FOR_EACH_IN_EP(i, ep)
471 USB_DIEPCTL(ep) = (USB_DIEPCTL(ep) & ~USB_DEPCTL_mps_bits)
472 | (512 << USB_DEPCTL_mps_bit_pos);
473
474 FOR_EACH_OUT_EP(i, ep)
475 USB_DOEPCTL(ep) = (USB_DOEPCTL(ep) & ~USB_DEPCTL_mps_bits)
476 | (512 << USB_DEPCTL_mps_bit_pos);
477
478 USB_DOEPTSIZ(0) = (1 << USB_DEPTSIZ0_supcnt_bit_pos)
479 | (1 << USB_DEPTSIZ0_pkcnt_bit_pos)
480 | 64;
433 481
434 return true; 482 return true;
435} 483}
@@ -507,8 +555,6 @@ void INT_USB(void)
507 /* device part */ 555 /* device part */
508 HANDLED_CASE(USB_GINTMSK_usbreset, handle_usb_reset) 556 HANDLED_CASE(USB_GINTMSK_usbreset, handle_usb_reset)
509 HANDLED_CASE(USB_GINTMSK_enumdone, handle_enum_done) 557 HANDLED_CASE(USB_GINTMSK_enumdone, handle_enum_done)
510 HANDLED_CASE(USB_GINTMSK_usbsuspend, handle_usb_suspend)
511 HANDLED_CASE(USB_GINTMSK_wkupintr, handle_wake_up)
512 /* 558 /*
513 HANDLED_CASE(USB_GINTMSK_inepintr, handle_in_ep_int) 559 HANDLED_CASE(USB_GINTMSK_inepintr, handle_in_ep_int)
514 HANDLED_CASE(USB_GINTMSK_outepintr, handle_out_ep_int) 560 HANDLED_CASE(USB_GINTMSK_outepintr, handle_out_ep_int)
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.h b/firmware/target/arm/as3525/usb-drv-as3525v2.h
index 37e8aee1e9..72dd8a0b5a 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525v2.h
+++ b/firmware/target/arm/as3525/usb-drv-as3525v2.h
@@ -121,7 +121,11 @@
121 121
122#define USB_GAHBCFG_glblintrmsk (1 << 0) /** Global interrupt mask */ 122#define USB_GAHBCFG_glblintrmsk (1 << 0) /** Global interrupt mask */
123#define USB_GAHBCFG_hburstlen_bit_pos 1 123#define USB_GAHBCFG_hburstlen_bit_pos 1
124#define USB_GAHBCFG_INT_DMA_BURST_SINGLE 0
124#define USB_GAHBCFG_INT_DMA_BURST_INCR 1 /** note: the linux patch has several other value, this is one picked for internal dma */ 125#define USB_GAHBCFG_INT_DMA_BURST_INCR 1 /** note: the linux patch has several other value, this is one picked for internal dma */
126#define USB_GAHBCFG_INT_DMA_BURST_INCR4 3
127#define USB_GAHBCFG_INT_DMA_BURST_INCR8 5
128#define USB_GAHBCFG_INT_DMA_BURST_INCR16 7
125#define USB_GAHBCFG_dma_enable (1 << 5) /** Enable DMA */ 129#define USB_GAHBCFG_dma_enable (1 << 5) /** Enable DMA */
126 130
127/* NOTE: USB_GINTSTS bits are the same as in USB_GINTMSK plus the following one */ 131/* NOTE: USB_GINTSTS bits are the same as in USB_GINTMSK plus the following one */
@@ -362,6 +366,20 @@
362/** 366/**
363 * Parameters 367 * Parameters
364 */ 368 */
369#define USB_USE_CUSTOM_FIFO_LAYOUT
370
371#ifdef USB_USE_CUSTOM_FIFO_LAYOUT
372/* Data fifo: includes RX fifo, non period TX fifo and periodic fifos
373 * NOTE: this is a hardware parameter, it cannot be changed ! */
374#define USB_DATA_FIFO_DEPTH 0x535
375/* size of the FX fifo */
376#define USB_RX_FIFO_SIZE 0x100
377/* size of the non periodic TX fifo */
378#define USB_NPTX_FIFO_SIZE 0x100
379/* size of each TX ep fifo size */
380#define USB_EPTX_FIFO_SIZE 0x100
381#endif /* USB_USE_CUSTOM_FIFO_LAYOUT */
382
365/* Number of IN/OUT endpoints */ 383/* Number of IN/OUT endpoints */
366#define USB_NUM_IN_EP 3 384#define USB_NUM_IN_EP 3
367#define USB_NUM_OUT_EP 2 385#define USB_NUM_OUT_EP 2