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);
49 extern void Dcache_InvalRegion(unsigned int addr, unsigned int length);
50 extern void Dcache_CleanRegion(unsigned int addr, unsigned int length);
51 extern int panic_display(void);
53 static __inline void usb_handler (void);
55 //static int booting_mode = BOOT_MODE_NORMAL;
57 /**---------------------------------------------------------------------------*
59 **---------------------------------------------------------------------------*/
60 #define BULK_MPS USB_PACKET_512
61 #define EP_OUT USB_EP2
63 #define EP_INTERRUPT USB_EP3
64 #define MAX_RECV_LENGTH (BULK_MPS)
65 #define MAX_PACKET_SIZE (BULK_MPS)
66 #define USB_TIMEOUT (1000)
68 #define USB_SUSPEND_AFTER_USB_MODE_START 0 // step 2. if (usb suspend occurred) after usb mode started
69 #define USB_STARTED 1 // step 1. after usb mode start this value will set
70 #define USB_DETACHED_AFTER_USB_MODE_START 2 // step 3. if (usb suspend occurred) and (musb cable detached) -> goto usb restart
71 #define USB_BEFORE_USB_MODE 4 // step 0. default value before usb mode start
73 /**---------------------------------------------------------------------------*
75 **---------------------------------------------------------------------------*/
76 __align(32) uint8 line_coding_config[7] = {0x00,0xc2,0x01,0x00,0x00,0x00,0x08};
77 __align (32) LOCAL uint32 s_setup_packet[8] = {0};
78 __align (32) LOCAL unsigned char usb_out_endpoint_buf[2] [MAX_RECV_LENGTH];
79 /*lint -e551 for "enum_speed" */
80 uint32 enum_speed = 0;
81 LOCAL uint32 recv_length = 0;
82 static unsigned int g_cdc_status = 0;
83 LOCAL uint32 s_comm_feature = 0;
85 uint32 g_cdc_state = 0;
86 LOCAL uint32 g_cdc_configuration = 1;
87 LOCAL uint32 g_cdc_interface = 1;
89 LOCAL uint32 g_usb_status = USB_BEFORE_USB_MODE;
90 /*****************************************************************************/
91 // Description: configure out endpoint0 to receive setup message.
92 // Global resource dependence:
93 // Author: jiayong.yang
95 /*****************************************************************************/
96 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
98 // Programs DOEPTSIZ0 register with Packet Count and Transfer Size
99 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_29|BIT_30); //setup packet count , 3 packet
100 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_3|BIT_4); //set Transfer Size ,24 bytes
104 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
107 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26; // set clear NAK
108 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
111 /*****************************************************************************/
112 // Description: configure in endpoint0 to send message.
113 // Global resource dependence:
114 // Author: jiayong.yang
116 /*****************************************************************************/
117 LOCAL void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
119 volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
121 diep0tsiz_ptr->mBits.transfer_size = transfer_size;
122 diep0tsiz_ptr->mBits.packet_count = packet_count;
126 Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
127 * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
130 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
132 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26; // clear NAK
134 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
138 diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
139 if(diep0tsiz_ptr->dwValue==0)
144 diep0tsiz_ptr->dwValue=0;
146 /*****************************************************************************/
147 // Description: usb reset interrupt handler.
148 // Global resource dependence:
149 // Author: jiayong.yang
151 /*****************************************************************************/
152 LOCAL void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
154 if (dir) // out endpoint
156 *(volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
157 * (volatile uint32 *) USB_DOEPMSK = (unsigned int) (BIT_13|BIT_12|BIT_3|BIT_0);
161 *(volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
162 *(volatile uint32 *) USB_DIEPMSK = 0xffffffff;
165 /*****************************************************************************/
166 // Description: configure specified endpoint to send/receive message.
167 // Global resource dependence:
168 // Author: jiayong.yang
170 /*****************************************************************************/
171 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
176 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
178 doepctl_ptr->mBits.ep_type = ep_type;
179 doepctl_ptr->mBits.mps =mps;
180 doepctl_ptr->mBits.set_nak = 0x1;
184 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
186 diepctl_ptr->mBits.ep_type = ep_type;
187 diepctl_ptr->mBits.mps = mps;
188 diepctl_ptr->mBits.set_nak = 0x1;
192 /*****************************************************************************/
193 // Description: start endpoint transfer.
194 // Global resource dependence:
195 // Author: jiayong.yang
197 /*****************************************************************************/
198 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
200 uint16 packet_count = 0;
204 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
208 * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
211 doeptsiz_ptr->mBits.transfer_size = MAX_RECV_LENGTH; // transfer size
212 doeptsiz_ptr->mBits.packet_count = MAX_RECV_LENGTH/BULK_MPS;
213 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) (BIT_26|BIT_31); // clear nak
217 volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U *) USB_DIEPTSIZ (ep_num);
218 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
222 Dcache_CleanRegion((unsigned int)buffer, transfer_size);//0511
223 * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
226 dieptsiz_ptr->mBits.transfer_size = transfer_size; // transfer size
227 packet_count = (transfer_size+diepctl_ptr->mBits.mps-1) /diepctl_ptr->mBits.mps;/*lint !e564*/
228 dieptsiz_ptr->mBits.packet_count = packet_count; // packet count
229 diepctl_ptr->mBits.tx_fifo_number = ep_num; // tx fifo number
231 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
232 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
237 /*****************************************************************************/
238 // Description: process desecriptor request.
239 // Global resource dependence:
240 // Author: jiayong.yang
242 /*****************************************************************************/
243 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
246 uint8 *send_data=NULL;
248 uint32 config_des_size=0;
250 length = (uint32) (request2->mBits.length_m<<8 |request2->mBits.length_l);
252 switch (request1->mBits.value_m)
254 case USB_DEVICE_DESCRIPTOR_TYPE:
255 send_data = (uint8 *) thor_get_device_desc(enum_speed);
258 * only send less or equal than requested length.
259 * no need to care about larger reqeust than possible
260 * descriptor length because of zero-length packet
261 * generated by usb controller
263 EPI0_config (min(USB_DT_DEVICE_SIZE, length), 0x1, TRUE, (uint32 *) send_data);
266 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
267 send_data = (uint8 *) thor_get_config_desc(enum_speed);
268 config_des_size = send_data[3]<<8 |send_data[2];
270 if (length > config_des_size)
272 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
273 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
277 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
278 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
282 case USB_STRING_DESCRIPTOR_TYPE:
284 uint8 str_index = request1->mBits.value_l;
285 send_data = thor_get_string_desc(str_index);
287 if(length > send_data[0])
289 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
293 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
298 case USB_DEVICE_QUALIFIER_TYPE:
299 send_data = (uint8 *) thor_get_qualifer_desc();
300 if(length > send_data[0])
302 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
306 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
310 case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
312 send_data = (uint8 *) thor_get_other_speed_config_desc();
313 config_des_size = send_data[3]<<8 |send_data[2];
314 if (length > config_des_size)
316 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
317 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
321 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
322 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
330 /*****************************************************************************/
331 // Description: process setup transaction.
332 // Global resource dependence:
333 // Author: jiayong.yang
335 /*****************************************************************************/
336 LOCAL int USB_EP0RecvEmptyPacket (void)
339 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
341 if(doepint_ptr->mBits.transfer_com == 1)
342 doepint_ptr->mBits.transfer_com=1;
344 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) ; //setup packet count , 3 packet
346 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
347 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
348 while(doepint_ptr->mBits.transfer_com==0)
350 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
354 LOCAL int USB_EP0RecvData (uint32 *pBuf,int transfer_size)
358 if (transfer_size == 0)
363 packet_count = (transfer_size+63) /64;
364 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) | (transfer_size&0x7f); //setup packet count , 3 packet
365 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) pBuf;
366 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
367 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
370 LOCAL void usb_reset_pipe(uint8 epno)
372 uint8 ep_num = epno & 0x7F;
377 if((epno & 0x80) == 0)
379 *(volatile uint32 *)USB_DOEPCTL(ep_num) |= BIT_28;
383 *(volatile uint32 *)USB_DIEPCTL(ep_num) |= BIT_28;
386 /*****************************************************************************/
387 // Description: process setup transaction.
388 // Global resource dependence:
389 // Author: jiayong.yang
391 /*****************************************************************************/
392 PUBLIC void usb_set_feature (void)
394 volatile USB_DCFG_U *dcfg_ptr = (volatile USB_DCFG_U *) USB_DCFG;
395 volatile USB_DCTL_U *dctl_ptr = (volatile USB_DCTL_U *) USB_DCTL;
396 USB_REQUEST_1_U *request1;
397 USB_REQUEST_2_U *request2;
398 USB_REQUEST_1_U request1_u;
399 USB_REQUEST_2_U request2_u;
400 request1_u.dwValue = s_setup_packet[0];
401 request2_u.dwValue = s_setup_packet[1];
402 request1= &request1_u;
403 request2= &request2_u;
405 EPI0_config (0x0, 0x1, FALSE, NULL);
407 while (* (volatile uint32 *) USB_DIEP0TSIZ) {}; // wait packet count is zero
409 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // clear ep out nak
411 switch (request2->mBits.index_m)
414 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
417 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
419 case 3://Test_SE0_NAK
420 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
423 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
425 case 5://Test_Force_Enable
426 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
432 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
435 LOCAL void usb_setup_handle (void)
437 usb_debug("%s : enter \n", __func__);
438 uint32 vendor_ack = 0;
439 USB_REQUEST_1_U *request1;
440 USB_REQUEST_2_U *request2;
441 USB_REQUEST_1_U request1_u;
442 USB_REQUEST_2_U request2_u;
443 request1_u.dwValue = s_setup_packet[0];
444 request2_u.dwValue = s_setup_packet[1];
445 request1= &request1_u;
446 request2= &request2_u;
448 switch (request1->mBits.type)
450 case USB_REQ_STANDARD://standard
452 switch (request1->mBits.recipient) //Recipient
456 switch (request1->mBits.brequest)
458 case USB_REQUEST_SET_FEATURE:
461 case USB_REQUEST_SET_ADDRESS:
463 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
465 dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
466 EPI0_config (0, 1, FALSE, NULL);
469 case USB_REQUEST_GET_DESCRIPTOR:
470 usb_get_descriptor (request1, request2);
472 case USB_REQUEST_SET_CONFIGURATION: //0x00 0x09
473 g_cdc_configuration = request1->mBits.value_l;
474 EPI0_config (0, 1, FALSE, NULL);
478 usb_EPActive (EP_IN, USB_EP_DIR_IN);
479 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
483 case USB_REQUEST_GET_CONFIGURATION:
484 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_configuration);
486 case USB_REQUEST_SET_INTERFACE:
487 EPI0_config (0, 1, FALSE, NULL);
489 case USB_REQUEST_CLEAR_FEATURE:
490 if(request1->mBits.recipient == 2)
492 usb_reset_pipe(request2->mBits.index_l);
494 EPI0_config (0, 1, FALSE, NULL);
497 EPI0_config (0, 1, TRUE, &vendor_ack);
502 case USB_REC_INTERFACE:
504 switch(request1->mBits.brequest)
506 case USB_REQUEST_SET_INTERFACE://0x01 0x0b
507 g_cdc_interface = request1->mBits.value_l;
508 EPI0_config (0, 1, FALSE, NULL);
510 case USB_REQUEST_GET_INTERFACE://0x81 0x0a
511 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_interface);
516 case USB_REC_ENDPOINT:
518 switch(request1->mBits.brequest)
520 case USB_REQUEST_GET_STATUS://0x82 0x00
521 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_state);
523 case USB_REQUEST_SET_FEATURE://0x02 0x03
527 case USB_REQUEST_CLEAR_FEATURE://0x02 0x01
528 if(request1->mBits.recipient == 2)
530 usb_reset_pipe(request2->mBits.index_l);
532 EPI0_config (0, 1, FALSE, NULL);
542 case USB_REQ_CLASS://class
543 switch (request1->mBits.recipient)
545 case USB_REC_INTERFACE:
546 switch (request1->mBits.brequest)
549 if (request1->mBits.value_l)
551 if (g_cdc_status == 0)
553 usb_EPActive (EP_IN, USB_EP_DIR_IN);
554 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
556 usb_debug("g_cdc_status = 1 \n");
559 EPI0_config (0, 1, FALSE, NULL);
562 if (request2->mBits.length_l)
564 USB_EP0RecvData((uint32 *)line_coding_config,request2->mBits.length_l);
566 EPI0_config (0, 1, FALSE, NULL);
569 EPI0_config(7, 1, TRUE,(uint32 *)line_coding_config);
570 USB_EP0RecvEmptyPacket();
572 case USB_CLEAR_COMM_FEATURE :
574 EPI0_config (0, 1, FALSE, NULL);
576 case USB_GET_COMM_FEATURE :
577 if (request2->mBits.length_l)
579 EPI0_config (2, 1, TRUE, &s_comm_feature);
582 case USB_SET_COMM_FEATURE :
583 if (request2->mBits.length_l)
585 USB_EP0RecvData((uint32 *)&s_comm_feature,2);
587 EPI0_config (0, 1, FALSE, NULL);
592 EPI0_config (0, 1, TRUE, NULL);
597 EPI0_config (4, 1, TRUE, &vendor_ack);
600 EPI0_config (0, 1, TRUE, NULL);
604 /*****************************************************************************/
605 // Description: usb reset interrupt handler.
606 // Global resource dependence:
607 // Author: jiayong.yang
609 /*****************************************************************************/
611 LOCAL void usb_reset_handler (void)
614 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
616 dcfg_ptr->mBits.devaddr = 0;
617 *(volatile uint32 *) USB_GAHBCFG |= BIT_5;
618 *(volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_12); // disable reset interrupt
620 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27; // set NAK for all OUT endpoint
622 *(volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
624 *(volatile uint32 *) USB_DAINTMSK |= (unsigned int) (BIT_0|BIT_16);
625 *(volatile uint32 *) USB_DOEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_2|BIT_1);
626 *(volatile uint32 *) USB_DIEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_1|BIT_2|BIT_5);//lint !e718
628 *(volatile uint32 *) USB_GRXFSIZ = (unsigned int) (BIT_2 | BIT_4 | BIT_8);
629 *(volatile uint32 *) USB_GNPTXFSIZ = (unsigned int) ((BIT_2 | BIT_4 | BIT_8) | BIT_20);
630 *(volatile uint32 *) USB_DIEPTXF (1) = (unsigned int) ((BIT_2 | BIT_5 | BIT_8) | BIT_24);
631 *(volatile uint32 *) USB_DIEPTXF (2) = (unsigned int) ((BIT_2 | BIT_5 | BIT_9) | BIT_18);
632 *(volatile uint32 *) USB_DIEPTXF (3) = (unsigned int) ((BIT_3 | BIT_5 | BIT_9) | BIT_24);
633 *(volatile uint32 *) USB_DIEPTXF (4) = (unsigned int) ((BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_18);
634 *(volatile uint32 *) USB_DIEPTXF (5) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_24);
635 *(volatile uint32 *) USB_DIEPTXF (6) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_10) | BIT_18);
637 *(volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5; //reflush tx fifo
639 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
643 if (timeout >= USB_TIMEOUT)
651 * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4; //reflush rx fifo
653 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
657 if (timeout >= USB_TIMEOUT)
663 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));//////////for test
664 EPO0_config (TRUE, s_setup_packet);
666 *(volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12; // enable reset interrupt
667 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12; //clear reset interrupt
670 /*****************************************************************************/
671 // Description: usb enumeration done handler.
672 // Global resource dependence:
673 // Author: jiayong.yang
675 /*****************************************************************************/
677 LOCAL void usb_enumeration_done (void)
679 volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
681 enum_speed = dsts_ptr->mBits.enumspd; //read enumration speed
682 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
684 if ( enum_speed == USB_HIGH )
686 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, BULK_MPS);
687 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, BULK_MPS);
688 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
692 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, USB_PACKET_64);
693 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, USB_PACKET_64);
694 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
696 usb_EPActive (EP_INTERRUPT, USB_EP_DIR_IN);
697 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
698 EPO0_config (TRUE, s_setup_packet);
700 *(volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
701 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
704 /*****************************************************************************/
705 // Description: out endpoint0 handler.
706 // Global resource dependence:
707 // Author: jiayong.yang
709 /*****************************************************************************/
711 LOCAL void usb_EP0_out_handle (void)
713 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
714 USB_DOEPINT_U doepint;
716 doepint.dwValue = doepint_ptr->dwValue;
717 doepint_ptr->dwValue = doepint.dwValue;
719 if (doepint.mBits.timeout_condi)
724 if (doepint.mBits.transfer_com)
728 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
732 size = (*(volatile uint32 *)USB_DOEP0TSIZ) & 0x18;
739 Dcache_InvalRegion ((unsigned int) s_setup_packet, sizeof (s_setup_packet)); //0511
740 EPO0_config (TRUE, s_setup_packet); //renable ep0 nd set packet count
744 /*****************************************************************************/
745 // Description: out endpoint handler.
746 // Global resource dependence:
747 // Author: jiayong.yang
749 /*****************************************************************************/
750 LOCAL void usb_EP_out_handle (void)
752 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
755 daint.dwValue = daint_ptr->dwValue; // disable EP out interrupt
757 if (daint.mBits.outepint_0)
759 usb_EP0_out_handle();
762 //* (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
764 /*****************************************************************************/
765 // Description: in endpoint handler.
766 // Global resource dependence:
767 // Author: jiayong.yang
769 /*****************************************************************************/
770 LOCAL void usb_EP_in_handle (void)
772 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
775 daint.dwValue = daint_ptr->dwValue;
777 if (daint.mBits.inepint_0)
779 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (0);
780 USB_DIEPINT_U diepint;
781 diepint.dwValue = diepint_ptr->dwValue;
782 diepint_ptr->dwValue = diepint.dwValue;
786 /*****************************************************************************/
787 // Description: usb interrupt handler.
788 // Global resource dependence:
789 // Author: jiayong.yang
791 /*****************************************************************************/
792 static void usb_handler (void)
794 volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
795 volatile USB_INTSTS_U usb_int;
797 char string[64] ={0,};
798 usb_int.dwValue = usb_int_ptr->dwValue;
800 // in endpoint interrupt
801 if (usb_int.mBits.iepint)
804 // out endpoint interrupt
805 if (usb_int.mBits.oepint)
808 // enumeration done interrupt
809 if (usb_int.mBits.enumdone)
810 usb_enumeration_done();
813 if (usb_int.mBits.usbrst)
817 check_usb_reconnected = 1;
823 if (usb_int.mBits.usbsusp)
825 if(g_usb_status == USB_STARTED)
827 g_usb_status = USB_SUSPEND_AFTER_USB_MODE_START;
832 /*****************************************************************************/
833 // Description: configure in endpoint ep_id to send message.
834 // Global resource dependence:
835 // Author: jiayong.yang
837 /*****************************************************************************/
838 //extern int microusb_charger_connected(void);
839 extern u32 is_usb_cable(void);
840 static int32 USB_ReadEx_Internal(uint8 *pBuf,uint32 len)
842 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
843 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (EP_OUT);
848 if(doepint_ptr->mBits.transfer_com == 1)
850 doepint_ptr->mBits.transfer_com = 1;
853 Dcache_CleanRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);
854 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
855 while(doepint_ptr->mBits.transfer_com==0)
857 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
859 if(check_usb_reconnected == 1 && g_cdc_status == 1)
861 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
862 check_usb_reconnected = 0;
865 doepint_ptr->mBits.transfer_com = 1;
866 Dcache_InvalRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);//0511
867 recv_length = MAX_RECV_LENGTH - doeptsiz_ptr->mBits.transfer_size;
870 if(recv_length > len)
883 int USB_ReadEx(unsigned char *pBuf, int len)
890 read_len = USB_ReadEx_Internal(pBuf,len);
893 /* RDX exception handling when PC(intenet explorer) control RDX tool */
897 if( g_usb_status == USB_DETACHED_AFTER_USB_MODE_START )
907 /*****************************************************************************/
908 // Description: configure in endpoint ep_id to send message.
909 // Global resource dependence:
910 // Author: jiayong.yang
912 /*****************************************************************************/
913 PUBLIC int32 USB_WriteEx(uint8 *pBuf,uint32 len)
915 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
918 int transfer_size = 0;
919 int transfered_size = 0;
923 if(len > MAX_RECV_LENGTH)
925 transfer_size = MAX_RECV_LENGTH;
927 else if((len % MAX_PACKET_SIZE)==0)
929 transfer_size = len - 32;
936 len = len - transfer_size;
938 for(i=0;i<transfer_size;i++)
940 usb_out_endpoint_buf[1][i] = pBuf[i+transfered_size];
943 if(diepint_ptr->mBits.transfer_com == 1)
945 diepint_ptr->mBits.transfer_com = 1;
948 usb_start_transfer ( (USB_EP_NUM_E) EP_IN, USB_EP_DIR_IN, transfer_size, TRUE, (uint32 *) usb_out_endpoint_buf[1]);
951 diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
953 }while(diepint_ptr->mBits.transfer_com==0);
954 diepint_ptr->mBits.transfer_com = 1;
955 transfered_size += transfer_size;
957 return transfered_size;
960 /*****************************************************************************/
961 // Description: initialize the usb core.
962 // Global resource dependence:
963 // Author: jiayong.yang
965 /*****************************************************************************/
966 LOCAL void usb_core_init (void)
968 usb_debug("%s : enter \n", __func__);
971 //Core soft reset, include hclk and phy clock
972 * (volatile uint32 *) USB_GRSTCTL |= BIT_0;
973 usb_debug("Inside usb_core_init \n");
977 reg_val = * (volatile uint32 *) USB_GRSTCTL;
979 if (reg_val & BIT_31)
983 } while (time_out<10);
985 * (volatile uint32 *) USB_DCTL &= ~ (BIT_1); //soft disconnect
986 * (volatile uint32 *) USB_GOTGCTL |= BIT_6|BIT_7;//Bvalid en
988 // program global ahb configuration
990 * (volatile uint32 *) USB_GAHBCFG |= BIT_1|BIT_2|BIT_3; // burst length INCR16
991 * (volatile uint32 *) USB_GAHBCFG |= BIT_0; // global interrupt mask , 0:mask 1:unmask
993 // program global usb configuration
994 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_6); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
995 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_17); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
996 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_4); // ULPI or UTMI+ selection bit, UTMI+ interface
997 * (volatile uint32 *) USB_GUSBCFG |= BIT_3; // PHY Interface bit, 16 bit
998 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_0|BIT_1|BIT_2); // HS/FS time out calibration,
999 * (volatile uint32 *) USB_GUSBCFG |= BIT_10|BIT_12; // USB turnaround time, 16bit UTMI+
1000 * (volatile uint32 *) USB_GUSBCFG |= BIT_30; // force device mode
1002 * (volatile uint32 *) USB_GINTSTS = 0xffffffff;
1004 * (volatile uint32 *) USB_GINTMSK = 0; // mask all first
1007 * (volatile uint32 *) USB_DCFG &= ~BIT_2; // out handshake
1008 * (volatile uint32 *) USB_DCFG &= ~ (BIT_11 | BIT_12);
1010 * (volatile uint32 *) USB_GINTMSK |= BIT_12; // usb reset int mask, 0:mask 1:unmask
1011 * (volatile uint32 *) USB_GINTMSK |= BIT_13; // enumeration done int mask, 0:mask 1:unmask
1012 * (volatile uint32 *) USB_GINTMSK |= BIT_18;
1013 * (volatile uint32 *) USB_GINTMSK |= BIT_19;
1015 * (volatile uint32 *) USB_GINTMSK &= ~BIT_4; // DMA mode, must mask rx fifo level interrupt
1017 * (volatile uint32 *) USB_DCFG &= ~BIT_0; //configure HS mode.
1018 usb_debug("After USBC_CORE_INIT \n");
1020 /*****************************************************************************/
1021 // Description: configure in endpoint ep_id to send message.
1022 // Global resource dependence:
1023 // Author: jiayong.yang
1025 /*****************************************************************************/
1028 void thor_USB_Init(void)
1030 usb_debug("%s : enter\n", __func__);
1031 unsigned int len = 0;
1035 usb_debug("usb_Core_init() is called\n");
1038 while (!g_cdc_status)
1041 sprd_usb_thor_start();
1043 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START) {
1044 g_usb_status = USB_BEFORE_USB_MODE;
1050 void USB_DeInit (void)
1055 __align(64) unsigned char sprd_thor_setup_buf[512] = {0,};
1057 static int s_usb_connected = 0;
1059 /************************************************
1061 * Register call back function for v3_protocol.
1063 ************************************************/
1065 //extern int usb_cb_register(u32 (*up)(void *, u32), u32 (*down)(void *, u32));
1067 void sprd_usb_cb_register(void)
1069 usb_debug("%s : start \n", __func__);
1070 usb_cb_register(USB_WriteEx, USB_ReadEx);
1074 extern int thor_handle(void);
1076 void sprd_usb_thor_start()
1078 g_usb_status = USB_STARTED;
1081 if (s_usb_connected == 0) {
1082 USB_ReadEx_Internal(sprd_thor_setup_buf, sizeof(sprd_thor_setup_buf));
1084 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START)
1087 if (!strncmp(sprd_thor_setup_buf, "THOR", strlen("THOR")))
1089 usb_debug("- thor is connected!\n");
1090 USB_WriteEx("ROHT", strlen("ROHT"));
1091 usb_debug("thor Setup Complete\n");
1092 s_usb_connected = 1;
1095 usb_debug("thor_seup error - Not receiving THOR\n");
1096 s_usb_connected = 0;
1103 usb_debug("%s : exit \n", __func__);
1107 void disconnect_usb(void)
1109 s_usb_connected = 0;
1112 int thor_usb_is_connected(void)
1114 return s_usb_connected;