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>
20 #include <linux/usb/ch9.h>
25 #define usb_debug(fmt, arg...) printf(fmt, ## arg)
27 #define usb_debug(fmt, arg...)
32 USB_HIGH, USB_FULL, USB_LOW
35 #define USB_DEVICE_QUALIFIER_TYPE 0x06
36 #define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE 0x07
45 int check_usb_reconnected = 0;
47 extern void usb_power_on(void);
48 extern void usb_power_off(void);
49 extern unsigned char *thor_get_device_desc(unsigned int speed);
50 extern unsigned char *thor_get_config_desc(unsigned int speed);
51 extern unsigned char *thor_get_string_desc(unsigned char index);
52 extern unsigned char *thor_get_qualifer_desc(void);
53 extern unsigned char *thor_get_other_speed_config_desc(void);
55 extern void Dcache_InvalRegion(unsigned int addr, unsigned int length);
56 extern void Dcache_CleanRegion(unsigned int addr, unsigned int length);
57 extern int panic_display(void);
59 static __inline void usb_handler (void);
61 //static int booting_mode = BOOT_MODE_NORMAL;
63 /**---------------------------------------------------------------------------*
65 **---------------------------------------------------------------------------*/
66 #define BULK_MPS USB_PACKET_512
67 #define EP_OUT USB_EP2
69 #define EP_INTERRUPT USB_EP3
70 #define MAX_RECV_LENGTH (BULK_MPS)
71 #define MAX_PACKET_SIZE (BULK_MPS)
72 #define USB_TIMEOUT (1000)
74 #define USB_SUSPEND_AFTER_USB_MODE_START 0 // step 2. if (usb suspend occurred) after usb mode started
75 #define USB_STARTED 1 // step 1. after usb mode start this value will set
76 #define USB_DETACHED_AFTER_USB_MODE_START 2 // step 3. if (usb suspend occurred) and (musb cable detached) -> goto usb restart
77 #define USB_BEFORE_USB_MODE 4 // step 0. default value before usb mode start
79 /**---------------------------------------------------------------------------*
81 **---------------------------------------------------------------------------*/
82 __align(32) uint8 line_coding_config[7] = {0x00,0xc2,0x01,0x00,0x00,0x00,0x08};
83 __align (32) LOCAL uint32 s_setup_packet[8] = {0};
84 __align (32) LOCAL unsigned char usb_out_endpoint_buf[2] [MAX_RECV_LENGTH];
85 /*lint -e551 for "enum_speed" */
86 uint32 enum_speed = 0;
87 LOCAL uint32 recv_length = 0;
88 static unsigned int g_cdc_status = 0;
89 LOCAL uint32 s_comm_feature = 0;
91 uint32 g_cdc_state = 0;
92 LOCAL uint32 g_cdc_configuration = 1;
93 LOCAL uint32 g_cdc_interface = 1;
95 LOCAL uint32 g_usb_status = USB_BEFORE_USB_MODE;
96 /*****************************************************************************/
97 // Description: configure out endpoint0 to receive setup message.
98 // Global resource dependence:
99 // Author: jiayong.yang
101 /*****************************************************************************/
102 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
104 // Programs DOEPTSIZ0 register with Packet Count and Transfer Size
105 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_29|BIT_30); //setup packet count , 3 packet
106 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_3|BIT_4); //set Transfer Size ,24 bytes
110 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
113 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26; // set clear NAK
114 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
117 /*****************************************************************************/
118 // Description: configure in endpoint0 to send message.
119 // Global resource dependence:
120 // Author: jiayong.yang
122 /*****************************************************************************/
123 LOCAL void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
125 volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
127 diep0tsiz_ptr->mBits.transfer_size = transfer_size;
128 diep0tsiz_ptr->mBits.packet_count = packet_count;
132 Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
133 * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
136 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
138 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26; // clear NAK
140 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
144 diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
145 if(diep0tsiz_ptr->dwValue==0)
150 diep0tsiz_ptr->dwValue=0;
152 /*****************************************************************************/
153 // Description: usb reset interrupt handler.
154 // Global resource dependence:
155 // Author: jiayong.yang
157 /*****************************************************************************/
158 LOCAL void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
160 if (dir) // out endpoint
162 *(volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
163 * (volatile uint32 *) USB_DOEPMSK = (unsigned int) (BIT_13|BIT_12|BIT_3|BIT_0);
167 *(volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
168 *(volatile uint32 *) USB_DIEPMSK = 0xffffffff;
171 /*****************************************************************************/
172 // Description: configure specified endpoint to send/receive message.
173 // Global resource dependence:
174 // Author: jiayong.yang
176 /*****************************************************************************/
177 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
182 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
184 doepctl_ptr->mBits.ep_type = ep_type;
185 doepctl_ptr->mBits.mps =mps;
186 doepctl_ptr->mBits.set_nak = 0x1;
190 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
192 diepctl_ptr->mBits.ep_type = ep_type;
193 diepctl_ptr->mBits.mps = mps;
194 diepctl_ptr->mBits.set_nak = 0x1;
198 /*****************************************************************************/
199 // Description: start endpoint transfer.
200 // Global resource dependence:
201 // Author: jiayong.yang
203 /*****************************************************************************/
204 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
206 uint16 packet_count = 0;
210 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
214 * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
217 doeptsiz_ptr->mBits.transfer_size = MAX_RECV_LENGTH; // transfer size
218 doeptsiz_ptr->mBits.packet_count = MAX_RECV_LENGTH/BULK_MPS;
219 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) (BIT_26|BIT_31); // clear nak
223 volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U *) USB_DIEPTSIZ (ep_num);
224 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
228 Dcache_CleanRegion((unsigned int)buffer, transfer_size);//0511
229 * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
232 dieptsiz_ptr->mBits.transfer_size = transfer_size; // transfer size
233 packet_count = (transfer_size+diepctl_ptr->mBits.mps-1) /diepctl_ptr->mBits.mps;/*lint !e564*/
234 dieptsiz_ptr->mBits.packet_count = packet_count; // packet count
235 diepctl_ptr->mBits.tx_fifo_number = ep_num; // tx fifo number
237 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
238 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
243 /*****************************************************************************/
244 // Description: process desecriptor request.
245 // Global resource dependence:
246 // Author: jiayong.yang
248 /*****************************************************************************/
249 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
252 uint8 *send_data=NULL;
254 uint32 config_des_size=0;
256 length = (uint32) (request2->mBits.length_m<<8 |request2->mBits.length_l);
258 switch (request1->mBits.value_m)
260 case USB_DEVICE_DESCRIPTOR_TYPE:
261 send_data = (uint8 *) thor_get_device_desc(enum_speed);
264 * only send less or equal than requested length.
265 * no need to care about larger reqeust than possible
266 * descriptor length because of zero-length packet
267 * generated by usb controller
269 EPI0_config (min(USB_DT_DEVICE_SIZE, length), 0x1, TRUE, (uint32 *) send_data);
272 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
273 send_data = (uint8 *) thor_get_config_desc(enum_speed);
274 config_des_size = send_data[3]<<8 |send_data[2];
276 if (length > config_des_size)
278 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
279 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
283 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
284 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
288 case USB_STRING_DESCRIPTOR_TYPE:
290 uint8 str_index = request1->mBits.value_l;
291 send_data = thor_get_string_desc(str_index);
293 if(length > send_data[0])
295 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
299 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
304 case USB_DEVICE_QUALIFIER_TYPE:
305 send_data = (uint8 *) thor_get_qualifer_desc();
306 if(length > send_data[0])
308 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
312 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
316 case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
318 send_data = (uint8 *) thor_get_other_speed_config_desc();
319 config_des_size = send_data[3]<<8 |send_data[2];
320 if (length > config_des_size)
322 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
323 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
327 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
328 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
336 /*****************************************************************************/
337 // Description: process setup transaction.
338 // Global resource dependence:
339 // Author: jiayong.yang
341 /*****************************************************************************/
342 LOCAL int USB_EP0RecvEmptyPacket (void)
345 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
347 if(doepint_ptr->mBits.transfer_com == 1)
348 doepint_ptr->mBits.transfer_com=1;
350 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) ; //setup packet count , 3 packet
352 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
353 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
354 while(doepint_ptr->mBits.transfer_com==0)
356 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
360 LOCAL int USB_EP0RecvData (uint32 *pBuf,int transfer_size)
364 if (transfer_size == 0)
369 packet_count = (transfer_size+63) /64;
370 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) | (transfer_size&0x7f); //setup packet count , 3 packet
371 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) pBuf;
372 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
373 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
376 LOCAL void usb_reset_pipe(uint8 epno)
378 uint8 ep_num = epno & 0x7F;
383 if((epno & 0x80) == 0)
385 *(volatile uint32 *)USB_DOEPCTL(ep_num) |= BIT_28;
389 *(volatile uint32 *)USB_DIEPCTL(ep_num) |= BIT_28;
392 /*****************************************************************************/
393 // Description: process setup transaction.
394 // Global resource dependence:
395 // Author: jiayong.yang
397 /*****************************************************************************/
398 PUBLIC void usb_set_feature (void)
400 volatile USB_DCTL_U *dctl_ptr = (volatile USB_DCTL_U *) USB_DCTL;
401 USB_REQUEST_2_U *request2;
402 USB_REQUEST_2_U request2_u;
403 request2_u.dwValue = s_setup_packet[1];
404 request2= &request2_u;
406 EPI0_config (0x0, 0x1, FALSE, NULL);
408 while (* (volatile uint32 *) USB_DIEP0TSIZ) {}; // wait packet count is zero
410 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // clear ep out nak
412 switch (request2->mBits.index_m)
415 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
418 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
420 case 3://Test_SE0_NAK
421 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
424 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
426 case 5://Test_Force_Enable
427 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
433 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
436 LOCAL void usb_setup_handle (void)
438 usb_debug("%s : enter \n", __func__);
439 uint32 vendor_ack = 0;
440 USB_REQUEST_1_U *request1;
441 USB_REQUEST_2_U *request2;
442 USB_REQUEST_1_U request1_u;
443 USB_REQUEST_2_U request2_u;
444 request1_u.dwValue = s_setup_packet[0];
445 request2_u.dwValue = s_setup_packet[1];
446 request1= &request1_u;
447 request2= &request2_u;
449 switch (request1->mBits.type)
451 case USB_REQ_STANDARD://standard
453 switch (request1->mBits.recipient) //Recipient
457 switch (request1->mBits.brequest)
459 case USB_REQUEST_SET_FEATURE:
462 case USB_REQUEST_SET_ADDRESS:
464 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
466 dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
467 EPI0_config (0, 1, FALSE, NULL);
470 case USB_REQUEST_GET_DESCRIPTOR:
471 usb_get_descriptor (request1, request2);
473 case USB_REQUEST_SET_CONFIGURATION: //0x00 0x09
474 g_cdc_configuration = request1->mBits.value_l;
475 EPI0_config (0, 1, FALSE, NULL);
479 usb_EPActive (EP_IN, USB_EP_DIR_IN);
480 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
484 case USB_REQUEST_GET_CONFIGURATION:
485 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_configuration);
487 case USB_REQUEST_SET_INTERFACE:
488 EPI0_config (0, 1, FALSE, NULL);
490 case USB_REQUEST_CLEAR_FEATURE:
491 if(request1->mBits.recipient == 2)
493 usb_reset_pipe(request2->mBits.index_l);
495 EPI0_config (0, 1, FALSE, NULL);
498 EPI0_config (0, 1, TRUE, &vendor_ack);
503 case USB_REC_INTERFACE:
505 switch(request1->mBits.brequest)
507 case USB_REQUEST_SET_INTERFACE://0x01 0x0b
508 g_cdc_interface = request1->mBits.value_l;
509 EPI0_config (0, 1, FALSE, NULL);
511 case USB_REQUEST_GET_INTERFACE://0x81 0x0a
512 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_interface);
517 case USB_REC_ENDPOINT:
519 switch(request1->mBits.brequest)
521 case USB_REQUEST_GET_STATUS://0x82 0x00
522 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_state);
524 case USB_REQUEST_SET_FEATURE://0x02 0x03
528 case USB_REQUEST_CLEAR_FEATURE://0x02 0x01
529 if(request1->mBits.recipient == 2)
531 usb_reset_pipe(request2->mBits.index_l);
533 EPI0_config (0, 1, FALSE, NULL);
543 case USB_REQ_CLASS://class
544 switch (request1->mBits.recipient)
546 case USB_REC_INTERFACE:
547 switch (request1->mBits.brequest)
550 if (request1->mBits.value_l)
552 if (g_cdc_status == 0)
554 usb_EPActive (EP_IN, USB_EP_DIR_IN);
555 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
557 usb_debug("g_cdc_status = 1 \n");
560 EPI0_config (0, 1, FALSE, NULL);
563 if (request2->mBits.length_l)
565 USB_EP0RecvData((uint32 *)line_coding_config,request2->mBits.length_l);
567 EPI0_config (0, 1, FALSE, NULL);
570 EPI0_config(7, 1, TRUE,(uint32 *)line_coding_config);
571 USB_EP0RecvEmptyPacket();
573 case USB_CLEAR_COMM_FEATURE :
575 EPI0_config (0, 1, FALSE, NULL);
577 case USB_GET_COMM_FEATURE :
578 if (request2->mBits.length_l)
580 EPI0_config (2, 1, TRUE, &s_comm_feature);
583 case USB_SET_COMM_FEATURE :
584 if (request2->mBits.length_l)
586 USB_EP0RecvData((uint32 *)&s_comm_feature,2);
588 EPI0_config (0, 1, FALSE, NULL);
593 EPI0_config (0, 1, TRUE, NULL);
598 EPI0_config (4, 1, TRUE, &vendor_ack);
601 EPI0_config (0, 1, TRUE, NULL);
605 /*****************************************************************************/
606 // Description: usb reset interrupt handler.
607 // Global resource dependence:
608 // Author: jiayong.yang
610 /*****************************************************************************/
612 LOCAL void usb_reset_handler (void)
615 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
617 dcfg_ptr->mBits.devaddr = 0;
618 *(volatile uint32 *) USB_GAHBCFG |= BIT_5;
619 *(volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_12); // disable reset interrupt
621 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27; // set NAK for all OUT endpoint
623 *(volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
625 *(volatile uint32 *) USB_DAINTMSK |= (unsigned int) (BIT_0|BIT_16);
626 *(volatile uint32 *) USB_DOEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_2|BIT_1);
627 *(volatile uint32 *) USB_DIEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_1|BIT_2|BIT_5);//lint !e718
629 *(volatile uint32 *) USB_GRXFSIZ = (unsigned int) (BIT_2 | BIT_4 | BIT_8);
630 *(volatile uint32 *) USB_GNPTXFSIZ = (unsigned int) ((BIT_2 | BIT_4 | BIT_8) | BIT_20);
631 *(volatile uint32 *) USB_DIEPTXF (1) = (unsigned int) ((BIT_2 | BIT_5 | BIT_8) | BIT_24);
632 *(volatile uint32 *) USB_DIEPTXF (2) = (unsigned int) ((BIT_2 | BIT_5 | BIT_9) | BIT_18);
633 *(volatile uint32 *) USB_DIEPTXF (3) = (unsigned int) ((BIT_3 | BIT_5 | BIT_9) | BIT_24);
634 *(volatile uint32 *) USB_DIEPTXF (4) = (unsigned int) ((BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_18);
635 *(volatile uint32 *) USB_DIEPTXF (5) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_24);
636 *(volatile uint32 *) USB_DIEPTXF (6) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_10) | BIT_18);
638 *(volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5; //reflush tx fifo
640 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
644 if (timeout >= USB_TIMEOUT)
652 * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4; //reflush rx fifo
654 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
658 if (timeout >= USB_TIMEOUT)
664 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));//////////for test
665 EPO0_config (TRUE, s_setup_packet);
667 *(volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12; // enable reset interrupt
668 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12; //clear reset interrupt
671 /*****************************************************************************/
672 // Description: usb enumeration done handler.
673 // Global resource dependence:
674 // Author: jiayong.yang
676 /*****************************************************************************/
678 LOCAL void usb_enumeration_done (void)
680 volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
682 enum_speed = dsts_ptr->mBits.enumspd; //read enumration speed
683 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
685 if ( enum_speed == USB_HIGH )
687 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, BULK_MPS);
688 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, BULK_MPS);
689 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
693 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, USB_PACKET_64);
694 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, USB_PACKET_64);
695 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
697 usb_EPActive (EP_INTERRUPT, USB_EP_DIR_IN);
698 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
699 EPO0_config (TRUE, s_setup_packet);
701 *(volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
702 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
705 /*****************************************************************************/
706 // Description: out endpoint0 handler.
707 // Global resource dependence:
708 // Author: jiayong.yang
710 /*****************************************************************************/
712 LOCAL void usb_EP0_out_handle (void)
714 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
715 USB_DOEPINT_U doepint;
717 doepint.dwValue = doepint_ptr->dwValue;
718 doepint_ptr->dwValue = doepint.dwValue;
720 if (doepint.mBits.timeout_condi)
725 if (doepint.mBits.transfer_com)
729 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
733 size = (*(volatile uint32 *)USB_DOEP0TSIZ) & 0x18;
740 Dcache_InvalRegion ((unsigned int) s_setup_packet, sizeof (s_setup_packet)); //0511
741 EPO0_config (TRUE, s_setup_packet); //renable ep0 nd set packet count
745 /*****************************************************************************/
746 // Description: out endpoint handler.
747 // Global resource dependence:
748 // Author: jiayong.yang
750 /*****************************************************************************/
751 LOCAL void usb_EP_out_handle (void)
753 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
756 daint.dwValue = daint_ptr->dwValue; // disable EP out interrupt
758 if (daint.mBits.outepint_0)
760 usb_EP0_out_handle();
763 //* (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
765 /*****************************************************************************/
766 // Description: in endpoint handler.
767 // Global resource dependence:
768 // Author: jiayong.yang
770 /*****************************************************************************/
771 LOCAL void usb_EP_in_handle (void)
773 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
776 daint.dwValue = daint_ptr->dwValue;
778 if (daint.mBits.inepint_0)
780 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (0);
781 USB_DIEPINT_U diepint;
782 diepint.dwValue = diepint_ptr->dwValue;
783 diepint_ptr->dwValue = diepint.dwValue;
787 /*****************************************************************************/
788 // Description: usb interrupt handler.
789 // Global resource dependence:
790 // Author: jiayong.yang
792 /*****************************************************************************/
793 static void usb_handler (void)
795 volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
796 volatile USB_INTSTS_U usb_int;
797 usb_int.dwValue = usb_int_ptr->dwValue;
799 // in endpoint interrupt
800 if (usb_int.mBits.iepint)
803 // out endpoint interrupt
804 if (usb_int.mBits.oepint)
807 // enumeration done interrupt
808 if (usb_int.mBits.enumdone)
809 usb_enumeration_done();
812 if (usb_int.mBits.usbrst)
816 check_usb_reconnected = 1;
822 if (usb_int.mBits.usbsusp)
824 if(g_usb_status == USB_STARTED)
826 g_usb_status = USB_SUSPEND_AFTER_USB_MODE_START;
831 /*****************************************************************************/
832 // Description: configure in endpoint ep_id to send message.
833 // Global resource dependence:
834 // Author: jiayong.yang
836 /*****************************************************************************/
837 //extern int microusb_charger_connected(void);
838 extern u32 is_usb_cable(void);
839 static int32 USB_ReadEx_Internal(uint8 *pBuf,uint32 len)
841 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
842 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (EP_OUT);
846 if(doepint_ptr->mBits.transfer_com == 1)
848 doepint_ptr->mBits.transfer_com = 1;
851 Dcache_CleanRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);
852 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
853 while(doepint_ptr->mBits.transfer_com==0)
855 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
857 if(check_usb_reconnected == 1 && g_cdc_status == 1)
859 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
860 check_usb_reconnected = 0;
863 doepint_ptr->mBits.transfer_com = 1;
864 Dcache_InvalRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);//0511
865 recv_length = MAX_RECV_LENGTH - doeptsiz_ptr->mBits.transfer_size;
868 if(recv_length > len)
881 int USB_ReadEx(unsigned char *pBuf, int len)
888 read_len = USB_ReadEx_Internal(pBuf,len);
891 /* RDX exception handling when PC(intenet explorer) control RDX tool */
895 if( g_usb_status == USB_DETACHED_AFTER_USB_MODE_START )
905 /*****************************************************************************/
906 // Description: configure in endpoint ep_id to send message.
907 // Global resource dependence:
908 // Author: jiayong.yang
910 /*****************************************************************************/
911 PUBLIC int32 USB_WriteEx(uint8 *pBuf,uint32 len)
913 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
916 int transfer_size = 0;
917 int transfered_size = 0;
921 if(len > MAX_RECV_LENGTH)
923 transfer_size = MAX_RECV_LENGTH;
925 else if((len % MAX_PACKET_SIZE)==0)
927 transfer_size = len - 32;
934 len = len - transfer_size;
936 for(i=0;i<transfer_size;i++)
938 usb_out_endpoint_buf[1][i] = pBuf[i+transfered_size];
941 if(diepint_ptr->mBits.transfer_com == 1)
943 diepint_ptr->mBits.transfer_com = 1;
946 usb_start_transfer ( (USB_EP_NUM_E) EP_IN, USB_EP_DIR_IN, transfer_size, TRUE, (uint32 *) usb_out_endpoint_buf[1]);
949 diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
951 }while(diepint_ptr->mBits.transfer_com==0);
952 diepint_ptr->mBits.transfer_com = 1;
953 transfered_size += transfer_size;
955 return transfered_size;
958 /*****************************************************************************/
959 // Description: initialize the usb core.
960 // Global resource dependence:
961 // Author: jiayong.yang
963 /*****************************************************************************/
964 LOCAL void usb_core_init (void)
966 usb_debug("%s : enter \n", __func__);
969 //Core soft reset, include hclk and phy clock
970 * (volatile uint32 *) USB_GRSTCTL |= BIT_0;
971 usb_debug("Inside usb_core_init \n");
975 reg_val = * (volatile uint32 *) USB_GRSTCTL;
977 if (reg_val & BIT_31)
981 } while (time_out<10);
983 * (volatile uint32 *) USB_DCTL &= ~ (BIT_1); //soft disconnect
984 * (volatile uint32 *) USB_GOTGCTL |= BIT_6|BIT_7;//Bvalid en
986 // program global ahb configuration
988 * (volatile uint32 *) USB_GAHBCFG |= BIT_1|BIT_2|BIT_3; // burst length INCR16
989 * (volatile uint32 *) USB_GAHBCFG |= BIT_0; // global interrupt mask , 0:mask 1:unmask
991 // program global usb configuration
992 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_6); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
993 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_17); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
994 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_4); // ULPI or UTMI+ selection bit, UTMI+ interface
995 * (volatile uint32 *) USB_GUSBCFG |= BIT_3; // PHY Interface bit, 16 bit
996 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_0|BIT_1|BIT_2); // HS/FS time out calibration,
997 * (volatile uint32 *) USB_GUSBCFG |= BIT_10|BIT_12; // USB turnaround time, 16bit UTMI+
998 * (volatile uint32 *) USB_GUSBCFG |= BIT_30; // force device mode
1000 * (volatile uint32 *) USB_GINTSTS = 0xffffffff;
1002 * (volatile uint32 *) USB_GINTMSK = 0; // mask all first
1005 * (volatile uint32 *) USB_DCFG &= ~BIT_2; // out handshake
1006 * (volatile uint32 *) USB_DCFG &= ~ (BIT_11 | BIT_12);
1008 * (volatile uint32 *) USB_GINTMSK |= BIT_12; // usb reset int mask, 0:mask 1:unmask
1009 * (volatile uint32 *) USB_GINTMSK |= BIT_13; // enumeration done int mask, 0:mask 1:unmask
1010 * (volatile uint32 *) USB_GINTMSK |= BIT_18;
1011 * (volatile uint32 *) USB_GINTMSK |= BIT_19;
1013 * (volatile uint32 *) USB_GINTMSK &= ~BIT_4; // DMA mode, must mask rx fifo level interrupt
1015 * (volatile uint32 *) USB_DCFG &= ~BIT_0; //configure HS mode.
1016 usb_debug("After USBC_CORE_INIT \n");
1018 /*****************************************************************************/
1019 // Description: configure in endpoint ep_id to send message.
1020 // Global resource dependence:
1021 // Author: jiayong.yang
1023 /*****************************************************************************/
1025 __align(64) unsigned char sprd_thor_setup_buf[512] = {0,};
1027 static int s_usb_connected = 0;
1029 extern int thor_handle(void);
1031 void sprd_usb_thor_start(void)
1033 g_usb_status = USB_STARTED;
1036 if (s_usb_connected == 0) {
1037 USB_ReadEx_Internal(sprd_thor_setup_buf, sizeof(sprd_thor_setup_buf));
1039 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START)
1042 if (!strncmp((char *)sprd_thor_setup_buf, "THOR", strlen("THOR")))
1044 usb_debug("- thor is connected!\n");
1045 USB_WriteEx((uint8 *)"ROHT", strlen("ROHT"));
1046 usb_debug("thor Setup Complete\n");
1047 s_usb_connected = 1;
1050 usb_debug("thor_seup error - Not receiving THOR\n");
1051 s_usb_connected = 0;
1058 usb_debug("%s : exit \n", __func__);
1063 void thor_USB_Init(void)
1065 usb_debug("%s : enter\n", __func__);
1069 usb_debug("usb_Core_init() is called\n");
1072 while (!g_cdc_status)
1075 sprd_usb_thor_start();
1077 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START) {
1078 g_usb_status = USB_BEFORE_USB_MODE;
1084 void USB_DeInit (void)
1089 /************************************************
1091 * Register call back function for v3_protocol.
1093 ************************************************/
1095 //extern int usb_cb_register(u32 (*up)(void *, u32), u32 (*down)(void *, u32));
1097 void sprd_usb_cb_register(void)
1099 usb_debug("%s : start \n", __func__);
1100 usb_cb_register(USB_WriteEx, USB_ReadEx);
1104 void disconnect_usb(void)
1106 s_usb_connected = 0;
1109 int thor_usb_is_connected(void)
1111 return s_usb_connected;