1 /******************************************************************************
2 ** File Name: DRV_usb.c *
3 ** Author: JiaYong.Yang *
5 ** Copyright: 2010 Spreatrum, Incoporated. All Rights Reserved. *
7 ******************************************************************************/
8 /**---------------------------------------------------------------------------*
10 **---------------------------------------------------------------------------*/
14 #include <asm/arch/common.h>
15 #include <asm/arch/usb200_fdl.h>
16 #include <asm/arch/drv_usb20.h>
17 #include <asm/arch/virtual_com.h>
18 #include <asm/arch/packet.h>
19 #include <asm/arch/usb20_reg_v3.h>
24 #define usb_debug(fmt, arg...) printf(fmt, ## arg)
26 #define usb_debug(fmt, arg...)
31 USB_HIGH, USB_FULL, USB_LOW
34 #define USB_DEVICE_QUALIFIER_TYPE 0x06
35 #define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE 0x07
44 int check_usb_reconnected = 0;
46 extern void usb_power_on(void);
47 extern void usb_power_off(void);
48 extern unsigned char *thor_get_device_desc(unsigned int speed);
49 extern unsigned char *thor_get_config_desc(unsigned int speed);
50 extern unsigned char *thor_get_string_desc(unsigned char index);
51 extern unsigned char *thor_get_qualifer_desc(void);
52 extern unsigned char *thor_get_other_speed_config_desc(void);
54 extern void Dcache_InvalRegion(unsigned int addr, unsigned int length);
55 extern void Dcache_CleanRegion(unsigned int addr, unsigned int length);
56 extern int panic_display(void);
58 static __inline void usb_handler (void);
60 //static int booting_mode = BOOT_MODE_NORMAL;
62 /**---------------------------------------------------------------------------*
64 **---------------------------------------------------------------------------*/
65 #define BULK_MPS USB_PACKET_512
66 #define EP_OUT USB_EP2
68 #define EP_INTERRUPT USB_EP3
69 #define MAX_RECV_LENGTH (BULK_MPS)
70 #define MAX_PACKET_SIZE (BULK_MPS)
71 #define USB_TIMEOUT (1000)
73 #define USB_SUSPEND_AFTER_USB_MODE_START 0 // step 2. if (usb suspend occurred) after usb mode started
74 #define USB_STARTED 1 // step 1. after usb mode start this value will set
75 #define USB_DETACHED_AFTER_USB_MODE_START 2 // step 3. if (usb suspend occurred) and (musb cable detached) -> goto usb restart
76 #define USB_BEFORE_USB_MODE 4 // step 0. default value before usb mode start
78 /**---------------------------------------------------------------------------*
80 **---------------------------------------------------------------------------*/
81 __align(32) uint8 line_coding_config[7] = {0x00,0xc2,0x01,0x00,0x00,0x00,0x08};
82 __align (32) LOCAL uint32 s_setup_packet[8] = {0};
83 __align (32) LOCAL unsigned char usb_out_endpoint_buf[2] [MAX_RECV_LENGTH];
84 /*lint -e551 for "enum_speed" */
85 uint32 enum_speed = 0;
86 LOCAL uint32 recv_length = 0;
87 static unsigned int g_cdc_status = 0;
88 LOCAL uint32 s_comm_feature = 0;
90 uint32 g_cdc_state = 0;
91 LOCAL uint32 g_cdc_configuration = 1;
92 LOCAL uint32 g_cdc_interface = 1;
94 LOCAL uint32 g_usb_status = USB_BEFORE_USB_MODE;
95 /*****************************************************************************/
96 // Description: configure out endpoint0 to receive setup message.
97 // Global resource dependence:
98 // Author: jiayong.yang
100 /*****************************************************************************/
101 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
103 // Programs DOEPTSIZ0 register with Packet Count and Transfer Size
104 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_29|BIT_30); //setup packet count , 3 packet
105 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_3|BIT_4); //set Transfer Size ,24 bytes
109 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
112 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26; // set clear NAK
113 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
116 /*****************************************************************************/
117 // Description: configure in endpoint0 to send message.
118 // Global resource dependence:
119 // Author: jiayong.yang
121 /*****************************************************************************/
122 LOCAL void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
124 volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
126 diep0tsiz_ptr->mBits.transfer_size = transfer_size;
127 diep0tsiz_ptr->mBits.packet_count = packet_count;
131 Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
132 * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
135 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
137 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26; // clear NAK
139 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
143 diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
144 if(diep0tsiz_ptr->dwValue==0)
149 diep0tsiz_ptr->dwValue=0;
151 /*****************************************************************************/
152 // Description: usb reset interrupt handler.
153 // Global resource dependence:
154 // Author: jiayong.yang
156 /*****************************************************************************/
157 LOCAL void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
159 if (dir) // out endpoint
161 *(volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
162 * (volatile uint32 *) USB_DOEPMSK = (unsigned int) (BIT_13|BIT_12|BIT_3|BIT_0);
166 *(volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
167 *(volatile uint32 *) USB_DIEPMSK = 0xffffffff;
170 /*****************************************************************************/
171 // Description: configure specified endpoint to send/receive message.
172 // Global resource dependence:
173 // Author: jiayong.yang
175 /*****************************************************************************/
176 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
181 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
183 doepctl_ptr->mBits.ep_type = ep_type;
184 doepctl_ptr->mBits.mps =mps;
185 doepctl_ptr->mBits.set_nak = 0x1;
189 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
191 diepctl_ptr->mBits.ep_type = ep_type;
192 diepctl_ptr->mBits.mps = mps;
193 diepctl_ptr->mBits.set_nak = 0x1;
197 /*****************************************************************************/
198 // Description: start endpoint transfer.
199 // Global resource dependence:
200 // Author: jiayong.yang
202 /*****************************************************************************/
203 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
205 uint16 packet_count = 0;
209 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
213 * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
216 doeptsiz_ptr->mBits.transfer_size = MAX_RECV_LENGTH; // transfer size
217 doeptsiz_ptr->mBits.packet_count = MAX_RECV_LENGTH/BULK_MPS;
218 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) (BIT_26|BIT_31); // clear nak
222 volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U *) USB_DIEPTSIZ (ep_num);
223 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
227 Dcache_CleanRegion((unsigned int)buffer, transfer_size);//0511
228 * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
231 dieptsiz_ptr->mBits.transfer_size = transfer_size; // transfer size
232 packet_count = (transfer_size+diepctl_ptr->mBits.mps-1) /diepctl_ptr->mBits.mps;/*lint !e564*/
233 dieptsiz_ptr->mBits.packet_count = packet_count; // packet count
234 diepctl_ptr->mBits.tx_fifo_number = ep_num; // tx fifo number
236 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
237 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
242 /*****************************************************************************/
243 // Description: process desecriptor request.
244 // Global resource dependence:
245 // Author: jiayong.yang
247 /*****************************************************************************/
248 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
251 uint8 *send_data=NULL;
253 uint32 config_des_size=0;
255 length = (uint32) (request2->mBits.length_m<<8 |request2->mBits.length_l);
257 switch (request1->mBits.value_m)
259 case USB_DEVICE_DESCRIPTOR_TYPE:
260 send_data = (uint8 *) thor_get_device_desc(enum_speed);
262 EPI0_config (0x12, 0x1, TRUE, (uint32 *) send_data);
265 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
266 send_data = (uint8 *) thor_get_config_desc(enum_speed);
267 config_des_size = send_data[3]<<8 |send_data[2];
269 if (length > config_des_size)
271 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
272 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
276 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
277 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
281 case USB_STRING_DESCRIPTOR_TYPE:
283 uint8 str_index = request1->mBits.value_l;
284 send_data = thor_get_string_desc(str_index);
286 if(length > send_data[0])
288 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
292 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
297 case USB_DEVICE_QUALIFIER_TYPE:
298 send_data = (uint8 *) thor_get_qualifer_desc();
299 if(length > send_data[0])
301 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
305 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
309 case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
311 send_data = (uint8 *) thor_get_other_speed_config_desc();
312 config_des_size = send_data[3]<<8 |send_data[2];
313 if (length > config_des_size)
315 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
316 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
320 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
321 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
329 /*****************************************************************************/
330 // Description: process setup transaction.
331 // Global resource dependence:
332 // Author: jiayong.yang
334 /*****************************************************************************/
335 LOCAL int USB_EP0RecvEmptyPacket (void)
338 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
340 if(doepint_ptr->mBits.transfer_com == 1)
341 doepint_ptr->mBits.transfer_com=1;
343 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) ; //setup packet count , 3 packet
345 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
346 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
347 while(doepint_ptr->mBits.transfer_com==0)
349 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
353 LOCAL int USB_EP0RecvData (uint32 *pBuf,int transfer_size)
357 if (transfer_size == 0)
362 packet_count = (transfer_size+63) /64;
363 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) | (transfer_size&0x7f); //setup packet count , 3 packet
364 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) pBuf;
365 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
366 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
369 LOCAL void usb_reset_pipe(uint8 epno)
371 uint8 ep_num = epno & 0x7F;
376 if((epno & 0x80) == 0)
378 *(volatile uint32 *)USB_DOEPCTL(ep_num) |= BIT_28;
382 *(volatile uint32 *)USB_DIEPCTL(ep_num) |= BIT_28;
385 /*****************************************************************************/
386 // Description: process setup transaction.
387 // Global resource dependence:
388 // Author: jiayong.yang
390 /*****************************************************************************/
391 PUBLIC void usb_set_feature (void)
393 volatile USB_DCTL_U *dctl_ptr = (volatile USB_DCTL_U *) USB_DCTL;
394 USB_REQUEST_2_U *request2;
395 USB_REQUEST_2_U request2_u;
396 request2_u.dwValue = s_setup_packet[1];
397 request2= &request2_u;
399 EPI0_config (0x0, 0x1, FALSE, NULL);
401 while (* (volatile uint32 *) USB_DIEP0TSIZ) {}; // wait packet count is zero
403 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // clear ep out nak
405 switch (request2->mBits.index_m)
408 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
411 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
413 case 3://Test_SE0_NAK
414 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
417 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
419 case 5://Test_Force_Enable
420 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
426 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
429 LOCAL void usb_setup_handle (void)
431 usb_debug("%s : enter \n", __func__);
432 uint32 vendor_ack = 0;
433 USB_REQUEST_1_U *request1;
434 USB_REQUEST_2_U *request2;
435 USB_REQUEST_1_U request1_u;
436 USB_REQUEST_2_U request2_u;
437 request1_u.dwValue = s_setup_packet[0];
438 request2_u.dwValue = s_setup_packet[1];
439 request1= &request1_u;
440 request2= &request2_u;
442 switch (request1->mBits.type)
444 case USB_REQ_STANDARD://standard
446 switch (request1->mBits.recipient) //Recipient
450 switch (request1->mBits.brequest)
452 case USB_REQUEST_SET_FEATURE:
455 case USB_REQUEST_SET_ADDRESS:
457 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
459 dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
460 EPI0_config (0, 1, FALSE, NULL);
463 case USB_REQUEST_GET_DESCRIPTOR:
464 usb_get_descriptor (request1, request2);
466 case USB_REQUEST_SET_CONFIGURATION: //0x00 0x09
467 g_cdc_configuration = request1->mBits.value_l;
468 EPI0_config (0, 1, FALSE, NULL);
472 usb_EPActive (EP_IN, USB_EP_DIR_IN);
473 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
477 case USB_REQUEST_GET_CONFIGURATION:
478 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_configuration);
480 case USB_REQUEST_SET_INTERFACE:
481 EPI0_config (0, 1, FALSE, NULL);
483 case USB_REQUEST_CLEAR_FEATURE:
484 if(request1->mBits.recipient == 2)
486 usb_reset_pipe(request2->mBits.index_l);
488 EPI0_config (0, 1, FALSE, NULL);
491 EPI0_config (0, 1, TRUE, &vendor_ack);
496 case USB_REC_INTERFACE:
498 switch(request1->mBits.brequest)
500 case USB_REQUEST_SET_INTERFACE://0x01 0x0b
501 g_cdc_interface = request1->mBits.value_l;
502 EPI0_config (0, 1, FALSE, NULL);
504 case USB_REQUEST_GET_INTERFACE://0x81 0x0a
505 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_interface);
510 case USB_REC_ENDPOINT:
512 switch(request1->mBits.brequest)
514 case USB_REQUEST_GET_STATUS://0x82 0x00
515 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_state);
517 case USB_REQUEST_SET_FEATURE://0x02 0x03
521 case USB_REQUEST_CLEAR_FEATURE://0x02 0x01
522 if(request1->mBits.recipient == 2)
524 usb_reset_pipe(request2->mBits.index_l);
526 EPI0_config (0, 1, FALSE, NULL);
536 case USB_REQ_CLASS://class
537 switch (request1->mBits.recipient)
539 case USB_REC_INTERFACE:
540 switch (request1->mBits.brequest)
543 if (request1->mBits.value_l)
545 if (g_cdc_status == 0)
547 usb_EPActive (EP_IN, USB_EP_DIR_IN);
548 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
550 usb_debug("g_cdc_status = 1 \n");
553 EPI0_config (0, 1, FALSE, NULL);
556 if (request2->mBits.length_l)
558 USB_EP0RecvData((uint32 *)line_coding_config,request2->mBits.length_l);
560 EPI0_config (0, 1, FALSE, NULL);
563 EPI0_config(7, 1, TRUE,(uint32 *)line_coding_config);
564 USB_EP0RecvEmptyPacket();
566 case USB_CLEAR_COMM_FEATURE :
568 EPI0_config (0, 1, FALSE, NULL);
570 case USB_GET_COMM_FEATURE :
571 if (request2->mBits.length_l)
573 EPI0_config (2, 1, TRUE, &s_comm_feature);
576 case USB_SET_COMM_FEATURE :
577 if (request2->mBits.length_l)
579 USB_EP0RecvData((uint32 *)&s_comm_feature,2);
581 EPI0_config (0, 1, FALSE, NULL);
586 EPI0_config (0, 1, TRUE, NULL);
591 EPI0_config (4, 1, TRUE, &vendor_ack);
594 EPI0_config (0, 1, TRUE, NULL);
598 /*****************************************************************************/
599 // Description: usb reset interrupt handler.
600 // Global resource dependence:
601 // Author: jiayong.yang
603 /*****************************************************************************/
605 LOCAL void usb_reset_handler (void)
608 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
610 dcfg_ptr->mBits.devaddr = 0;
611 *(volatile uint32 *) USB_GAHBCFG |= BIT_5;
612 *(volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_12); // disable reset interrupt
614 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27; // set NAK for all OUT endpoint
616 *(volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
618 *(volatile uint32 *) USB_DAINTMSK |= (unsigned int) (BIT_0|BIT_16);
619 *(volatile uint32 *) USB_DOEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_2|BIT_1);
620 *(volatile uint32 *) USB_DIEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_1|BIT_2|BIT_5);//lint !e718
622 *(volatile uint32 *) USB_GRXFSIZ = (unsigned int) (BIT_2 | BIT_4 | BIT_8);
623 *(volatile uint32 *) USB_GNPTXFSIZ = (unsigned int) ((BIT_2 | BIT_4 | BIT_8) | BIT_20);
624 *(volatile uint32 *) USB_DIEPTXF (1) = (unsigned int) ((BIT_2 | BIT_5 | BIT_8) | BIT_24);
625 *(volatile uint32 *) USB_DIEPTXF (2) = (unsigned int) ((BIT_2 | BIT_5 | BIT_9) | BIT_18);
626 *(volatile uint32 *) USB_DIEPTXF (3) = (unsigned int) ((BIT_3 | BIT_5 | BIT_9) | BIT_24);
627 *(volatile uint32 *) USB_DIEPTXF (4) = (unsigned int) ((BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_18);
628 *(volatile uint32 *) USB_DIEPTXF (5) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_24);
629 *(volatile uint32 *) USB_DIEPTXF (6) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_10) | BIT_18);
631 *(volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5; //reflush tx fifo
633 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
637 if (timeout >= USB_TIMEOUT)
645 * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4; //reflush rx fifo
647 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
651 if (timeout >= USB_TIMEOUT)
657 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));//////////for test
658 EPO0_config (TRUE, s_setup_packet);
660 *(volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12; // enable reset interrupt
661 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12; //clear reset interrupt
664 /*****************************************************************************/
665 // Description: usb enumeration done handler.
666 // Global resource dependence:
667 // Author: jiayong.yang
669 /*****************************************************************************/
671 LOCAL void usb_enumeration_done (void)
673 volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
675 enum_speed = dsts_ptr->mBits.enumspd; //read enumration speed
676 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
678 if ( enum_speed == USB_HIGH )
680 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, BULK_MPS);
681 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, BULK_MPS);
682 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
686 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, USB_PACKET_64);
687 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, USB_PACKET_64);
688 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
690 usb_EPActive (EP_INTERRUPT, USB_EP_DIR_IN);
691 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
692 EPO0_config (TRUE, s_setup_packet);
694 *(volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
695 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
698 /*****************************************************************************/
699 // Description: out endpoint0 handler.
700 // Global resource dependence:
701 // Author: jiayong.yang
703 /*****************************************************************************/
705 LOCAL void usb_EP0_out_handle (void)
707 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
708 USB_DOEPINT_U doepint;
710 doepint.dwValue = doepint_ptr->dwValue;
711 doepint_ptr->dwValue = doepint.dwValue;
713 if (doepint.mBits.timeout_condi)
718 if (doepint.mBits.transfer_com)
722 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
726 size = (*(volatile uint32 *)USB_DOEP0TSIZ) & 0x18;
733 Dcache_InvalRegion ((unsigned int) s_setup_packet, sizeof (s_setup_packet)); //0511
734 EPO0_config (TRUE, s_setup_packet); //renable ep0 nd set packet count
738 /*****************************************************************************/
739 // Description: out endpoint handler.
740 // Global resource dependence:
741 // Author: jiayong.yang
743 /*****************************************************************************/
744 LOCAL void usb_EP_out_handle (void)
746 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
749 daint.dwValue = daint_ptr->dwValue; // disable EP out interrupt
751 if (daint.mBits.outepint_0)
753 usb_EP0_out_handle();
756 //* (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
758 /*****************************************************************************/
759 // Description: in endpoint handler.
760 // Global resource dependence:
761 // Author: jiayong.yang
763 /*****************************************************************************/
764 LOCAL void usb_EP_in_handle (void)
766 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
769 daint.dwValue = daint_ptr->dwValue;
771 if (daint.mBits.inepint_0)
773 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (0);
774 USB_DIEPINT_U diepint;
775 diepint.dwValue = diepint_ptr->dwValue;
776 diepint_ptr->dwValue = diepint.dwValue;
780 /*****************************************************************************/
781 // Description: usb interrupt handler.
782 // Global resource dependence:
783 // Author: jiayong.yang
785 /*****************************************************************************/
786 static void usb_handler (void)
788 volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
789 volatile USB_INTSTS_U usb_int;
790 usb_int.dwValue = usb_int_ptr->dwValue;
792 // in endpoint interrupt
793 if (usb_int.mBits.iepint)
796 // out endpoint interrupt
797 if (usb_int.mBits.oepint)
800 // enumeration done interrupt
801 if (usb_int.mBits.enumdone)
802 usb_enumeration_done();
805 if (usb_int.mBits.usbrst)
809 check_usb_reconnected = 1;
815 if (usb_int.mBits.usbsusp)
817 if(g_usb_status == USB_STARTED)
819 g_usb_status = USB_SUSPEND_AFTER_USB_MODE_START;
824 /*****************************************************************************/
825 // Description: configure in endpoint ep_id to send message.
826 // Global resource dependence:
827 // Author: jiayong.yang
829 /*****************************************************************************/
830 //extern int microusb_charger_connected(void);
831 extern u32 is_usb_cable(void);
832 static int32 USB_ReadEx_Internal(uint8 *pBuf,uint32 len)
834 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
835 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (EP_OUT);
839 if(doepint_ptr->mBits.transfer_com == 1)
841 doepint_ptr->mBits.transfer_com = 1;
844 Dcache_CleanRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);
845 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
846 while(doepint_ptr->mBits.transfer_com==0)
848 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
850 if(check_usb_reconnected == 1 && g_cdc_status == 1)
852 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
853 check_usb_reconnected = 0;
856 doepint_ptr->mBits.transfer_com = 1;
857 Dcache_InvalRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);//0511
858 recv_length = MAX_RECV_LENGTH - doeptsiz_ptr->mBits.transfer_size;
861 if(recv_length > len)
874 int USB_ReadEx(unsigned char *pBuf, int len)
881 read_len = USB_ReadEx_Internal(pBuf,len);
884 /* RDX exception handling when PC(intenet explorer) control RDX tool */
888 if( g_usb_status == USB_DETACHED_AFTER_USB_MODE_START )
898 /*****************************************************************************/
899 // Description: configure in endpoint ep_id to send message.
900 // Global resource dependence:
901 // Author: jiayong.yang
903 /*****************************************************************************/
904 PUBLIC int32 USB_WriteEx(uint8 *pBuf,uint32 len)
906 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
909 int transfer_size = 0;
910 int transfered_size = 0;
914 if(len > MAX_RECV_LENGTH)
916 transfer_size = MAX_RECV_LENGTH;
918 else if((len % MAX_PACKET_SIZE)==0)
920 transfer_size = len - 32;
927 len = len - transfer_size;
929 for(i=0;i<transfer_size;i++)
931 usb_out_endpoint_buf[1][i] = pBuf[i+transfered_size];
934 if(diepint_ptr->mBits.transfer_com == 1)
936 diepint_ptr->mBits.transfer_com = 1;
939 usb_start_transfer ( (USB_EP_NUM_E) EP_IN, USB_EP_DIR_IN, transfer_size, TRUE, (uint32 *) usb_out_endpoint_buf[1]);
942 diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
944 }while(diepint_ptr->mBits.transfer_com==0);
945 diepint_ptr->mBits.transfer_com = 1;
946 transfered_size += transfer_size;
948 return transfered_size;
951 /*****************************************************************************/
952 // Description: initialize the usb core.
953 // Global resource dependence:
954 // Author: jiayong.yang
956 /*****************************************************************************/
957 LOCAL void usb_core_init (void)
959 usb_debug("%s : enter \n", __func__);
962 //Core soft reset, include hclk and phy clock
963 * (volatile uint32 *) USB_GRSTCTL |= BIT_0;
964 usb_debug("Inside usb_core_init \n");
968 reg_val = * (volatile uint32 *) USB_GRSTCTL;
970 if (reg_val & BIT_31)
974 } while (time_out<10);
976 * (volatile uint32 *) USB_DCTL &= ~ (BIT_1); //soft disconnect
977 * (volatile uint32 *) USB_GOTGCTL |= BIT_6|BIT_7;//Bvalid en
979 // program global ahb configuration
981 * (volatile uint32 *) USB_GAHBCFG |= BIT_1|BIT_2|BIT_3; // burst length INCR16
982 * (volatile uint32 *) USB_GAHBCFG |= BIT_0; // global interrupt mask , 0:mask 1:unmask
984 // program global usb configuration
985 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_6); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
986 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_17); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
987 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_4); // ULPI or UTMI+ selection bit, UTMI+ interface
988 * (volatile uint32 *) USB_GUSBCFG |= BIT_3; // PHY Interface bit, 16 bit
989 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_0|BIT_1|BIT_2); // HS/FS time out calibration,
990 * (volatile uint32 *) USB_GUSBCFG |= BIT_10|BIT_12; // USB turnaround time, 16bit UTMI+
991 * (volatile uint32 *) USB_GUSBCFG |= BIT_30; // force device mode
993 * (volatile uint32 *) USB_GINTSTS = 0xffffffff;
995 * (volatile uint32 *) USB_GINTMSK = 0; // mask all first
998 * (volatile uint32 *) USB_DCFG &= ~BIT_2; // out handshake
999 * (volatile uint32 *) USB_DCFG &= ~ (BIT_11 | BIT_12);
1001 * (volatile uint32 *) USB_GINTMSK |= BIT_12; // usb reset int mask, 0:mask 1:unmask
1002 * (volatile uint32 *) USB_GINTMSK |= BIT_13; // enumeration done int mask, 0:mask 1:unmask
1003 * (volatile uint32 *) USB_GINTMSK |= BIT_18;
1004 * (volatile uint32 *) USB_GINTMSK |= BIT_19;
1006 * (volatile uint32 *) USB_GINTMSK &= ~BIT_4; // DMA mode, must mask rx fifo level interrupt
1008 * (volatile uint32 *) USB_DCFG &= ~BIT_0; //configure HS mode.
1009 usb_debug("After USBC_CORE_INIT \n");
1011 /*****************************************************************************/
1012 // Description: configure in endpoint ep_id to send message.
1013 // Global resource dependence:
1014 // Author: jiayong.yang
1016 /*****************************************************************************/
1018 __align(64) unsigned char sprd_thor_setup_buf[512] = {0,};
1020 static int s_usb_connected = 0;
1022 extern int thor_handle(void);
1024 void sprd_usb_thor_start(void)
1026 g_usb_status = USB_STARTED;
1029 if (s_usb_connected == 0) {
1030 USB_ReadEx_Internal(sprd_thor_setup_buf, sizeof(sprd_thor_setup_buf));
1032 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START)
1035 if (!strncmp((char *)sprd_thor_setup_buf, "THOR", strlen("THOR")))
1037 usb_debug("- thor is connected!\n");
1038 USB_WriteEx((uint8 *)"ROHT", strlen("ROHT"));
1039 usb_debug("thor Setup Complete\n");
1040 s_usb_connected = 1;
1043 usb_debug("thor_seup error - Not receiving THOR\n");
1044 s_usb_connected = 0;
1051 usb_debug("%s : exit \n", __func__);
1056 void thor_USB_Init(void)
1058 usb_debug("%s : enter\n", __func__);
1062 usb_debug("usb_Core_init() is called\n");
1065 while (!g_cdc_status)
1068 sprd_usb_thor_start();
1070 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START) {
1071 g_usb_status = USB_BEFORE_USB_MODE;
1077 void USB_DeInit (void)
1082 /************************************************
1084 * Register call back function for v3_protocol.
1086 ************************************************/
1088 //extern int usb_cb_register(u32 (*up)(void *, u32), u32 (*down)(void *, u32));
1090 void sprd_usb_cb_register(void)
1092 usb_debug("%s : start \n", __func__);
1093 usb_cb_register(USB_WriteEx, USB_ReadEx);
1097 void disconnect_usb(void)
1099 s_usb_connected = 0;
1102 int thor_usb_is_connected(void)
1104 return s_usb_connected;