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);
48 extern void Dcache_InvalRegion(unsigned int addr, unsigned int length);
49 extern void Dcache_CleanRegion(unsigned int addr, unsigned int length);
50 extern int panic_display(void);
52 static __inline void usb_handler (void);
54 //static int booting_mode = BOOT_MODE_NORMAL;
56 /**---------------------------------------------------------------------------*
58 **---------------------------------------------------------------------------*/
59 #define BULK_MPS USB_PACKET_512
60 #define EP_OUT USB_EP2
62 #define EP_INTERRUPT USB_EP3
63 #define MAX_RECV_LENGTH (BULK_MPS)
64 #define MAX_PACKET_SIZE (BULK_MPS)
65 #define USB_TIMEOUT (1000)
67 #define USB_SUSPEND_AFTER_USB_MODE_START 0 // step 2. if (usb suspend occurred) after usb mode started
68 #define USB_STARTED 1 // step 1. after usb mode start this value will set
69 #define USB_DETACHED_AFTER_USB_MODE_START 2 // step 3. if (usb suspend occurred) and (musb cable detached) -> goto usb restart
70 #define USB_BEFORE_USB_MODE 4 // step 0. default value before usb mode start
72 /**---------------------------------------------------------------------------*
74 **---------------------------------------------------------------------------*/
75 __align(32) uint8 line_coding_config[7] = {0x00,0xc2,0x01,0x00,0x00,0x00,0x08};
76 __align (32) LOCAL uint32 s_setup_packet[8] = {0};
77 __align (32) LOCAL unsigned char usb_out_endpoint_buf[2] [MAX_RECV_LENGTH];
78 /*lint -e551 for "enum_speed" */
79 uint32 enum_speed = 0;
80 LOCAL uint32 recv_length = 0;
81 static unsigned int g_cdc_status = 0;
82 LOCAL uint32 s_comm_feature = 0;
84 uint32 g_cdc_state = 0;
85 LOCAL uint32 g_cdc_configuration = 1;
86 LOCAL uint32 g_cdc_interface = 1;
88 LOCAL uint32 g_usb_status = USB_BEFORE_USB_MODE;
89 /*****************************************************************************/
90 // Description: configure out endpoint0 to receive setup message.
91 // Global resource dependence:
92 // Author: jiayong.yang
94 /*****************************************************************************/
95 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
97 // Programs DOEPTSIZ0 register with Packet Count and Transfer Size
98 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_29|BIT_30); //setup packet count , 3 packet
99 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_3|BIT_4); //set Transfer Size ,24 bytes
103 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
106 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26; // set clear NAK
107 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
110 /*****************************************************************************/
111 // Description: configure in endpoint0 to send message.
112 // Global resource dependence:
113 // Author: jiayong.yang
115 /*****************************************************************************/
116 LOCAL void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
118 volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
120 diep0tsiz_ptr->mBits.transfer_size = transfer_size;
121 diep0tsiz_ptr->mBits.packet_count = packet_count;
125 Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
126 * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
129 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
131 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26; // clear NAK
133 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
137 diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
138 if(diep0tsiz_ptr->dwValue==0)
143 diep0tsiz_ptr->dwValue=0;
145 /*****************************************************************************/
146 // Description: usb reset interrupt handler.
147 // Global resource dependence:
148 // Author: jiayong.yang
150 /*****************************************************************************/
151 LOCAL void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
153 if (dir) // out endpoint
155 *(volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
156 * (volatile uint32 *) USB_DOEPMSK = (unsigned int) (BIT_13|BIT_12|BIT_3|BIT_0);
160 *(volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
161 *(volatile uint32 *) USB_DIEPMSK = 0xffffffff;
164 /*****************************************************************************/
165 // Description: configure specified endpoint to send/receive message.
166 // Global resource dependence:
167 // Author: jiayong.yang
169 /*****************************************************************************/
170 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
175 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
177 doepctl_ptr->mBits.ep_type = ep_type;
178 doepctl_ptr->mBits.mps =mps;
179 doepctl_ptr->mBits.set_nak = 0x1;
183 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
185 diepctl_ptr->mBits.ep_type = ep_type;
186 diepctl_ptr->mBits.mps = mps;
187 diepctl_ptr->mBits.set_nak = 0x1;
191 /*****************************************************************************/
192 // Description: start endpoint transfer.
193 // Global resource dependence:
194 // Author: jiayong.yang
196 /*****************************************************************************/
197 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
199 uint16 packet_count = 0;
203 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
207 * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
210 doeptsiz_ptr->mBits.transfer_size = MAX_RECV_LENGTH; // transfer size
211 doeptsiz_ptr->mBits.packet_count = MAX_RECV_LENGTH/BULK_MPS;
212 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) (BIT_26|BIT_31); // clear nak
216 volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U *) USB_DIEPTSIZ (ep_num);
217 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
221 Dcache_CleanRegion((unsigned int)buffer, transfer_size);//0511
222 * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
225 dieptsiz_ptr->mBits.transfer_size = transfer_size; // transfer size
226 packet_count = (transfer_size+diepctl_ptr->mBits.mps-1) /diepctl_ptr->mBits.mps;/*lint !e564*/
227 dieptsiz_ptr->mBits.packet_count = packet_count; // packet count
228 diepctl_ptr->mBits.tx_fifo_number = ep_num; // tx fifo number
230 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
231 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
236 /*****************************************************************************/
237 // Description: process desecriptor request.
238 // Global resource dependence:
239 // Author: jiayong.yang
241 /*****************************************************************************/
242 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
245 uint8 *send_data=NULL;
247 uint32 config_des_size=0;
249 length = (uint32) (request2->mBits.length_m<<8 |request2->mBits.length_l);
251 switch (request1->mBits.value_m)
253 case USB_DEVICE_DESCRIPTOR_TYPE:
254 send_data = (uint8 *) thor_get_device_desc(enum_speed);
256 EPI0_config (0x12, 0x1, TRUE, (uint32 *) send_data);
259 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
260 send_data = (uint8 *) thor_get_config_desc(enum_speed);
261 config_des_size = send_data[3]<<8 |send_data[2];
263 if (length > config_des_size)
265 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
266 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
270 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
271 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
275 case USB_STRING_DESCRIPTOR_TYPE:
277 uint8 str_index = request1->mBits.value_l;
278 send_data = thor_get_string_desc(str_index);
280 if(length > send_data[0])
282 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
286 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
291 case USB_DEVICE_QUALIFIER_TYPE:
292 send_data = (uint8 *) thor_get_qualifer_desc();
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);
303 case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
305 send_data = (uint8 *) thor_get_other_speed_config_desc();
306 config_des_size = send_data[3]<<8 |send_data[2];
307 if (length > config_des_size)
309 pkt_cnt = (config_des_size % 64) ? config_des_size/64 + 1 : config_des_size/64;
310 EPI0_config (config_des_size, pkt_cnt, TRUE, (uint32 *) send_data);
314 pkt_cnt = (length % 64) ? length/64 + 1 : length/64;
315 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
323 /*****************************************************************************/
324 // Description: process setup transaction.
325 // Global resource dependence:
326 // Author: jiayong.yang
328 /*****************************************************************************/
329 LOCAL int USB_EP0RecvEmptyPacket (void)
332 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
334 if(doepint_ptr->mBits.transfer_com == 1)
335 doepint_ptr->mBits.transfer_com=1;
337 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) ; //setup packet count , 3 packet
339 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
340 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
341 while(doepint_ptr->mBits.transfer_com==0)
343 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
347 LOCAL int USB_EP0RecvData (uint32 *pBuf,int transfer_size)
351 if (transfer_size == 0)
356 packet_count = (transfer_size+63) /64;
357 * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) | (transfer_size&0x7f); //setup packet count , 3 packet
358 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) pBuf;
359 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // set clear NAK
360 * (volatile uint32 *) USB_DOEP0CTL |= BIT_31; // set endpoint enable
363 LOCAL void usb_reset_pipe(uint8 epno)
365 uint8 ep_num = epno & 0x7F;
370 if((epno & 0x80) == 0)
372 *(volatile uint32 *)USB_DOEPCTL(ep_num) |= BIT_28;
376 *(volatile uint32 *)USB_DIEPCTL(ep_num) |= BIT_28;
379 /*****************************************************************************/
380 // Description: process setup transaction.
381 // Global resource dependence:
382 // Author: jiayong.yang
384 /*****************************************************************************/
385 PUBLIC void usb_set_feature (void)
387 volatile USB_DCFG_U *dcfg_ptr = (volatile USB_DCFG_U *) USB_DCFG;
388 volatile USB_DCTL_U *dctl_ptr = (volatile USB_DCTL_U *) USB_DCTL;
389 USB_REQUEST_1_U *request1;
390 USB_REQUEST_2_U *request2;
391 USB_REQUEST_1_U request1_u;
392 USB_REQUEST_2_U request2_u;
393 request1_u.dwValue = s_setup_packet[0];
394 request2_u.dwValue = s_setup_packet[1];
395 request1= &request1_u;
396 request2= &request2_u;
398 EPI0_config (0x0, 0x1, FALSE, NULL);
400 while (* (volatile uint32 *) USB_DIEP0TSIZ) {}; // wait packet count is zero
402 * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // clear ep out nak
404 switch (request2->mBits.index_m)
407 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
410 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
412 case 3://Test_SE0_NAK
413 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
416 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
418 case 5://Test_Force_Enable
419 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
425 dctl_ptr->mBits.tstctl = request2->mBits.index_m;
428 LOCAL void usb_setup_handle (void)
430 usb_debug("%s : enter \n", __func__);
431 uint32 vendor_ack = 0;
432 USB_REQUEST_1_U *request1;
433 USB_REQUEST_2_U *request2;
434 USB_REQUEST_1_U request1_u;
435 USB_REQUEST_2_U request2_u;
436 request1_u.dwValue = s_setup_packet[0];
437 request2_u.dwValue = s_setup_packet[1];
438 request1= &request1_u;
439 request2= &request2_u;
441 switch (request1->mBits.type)
443 case USB_REQ_STANDARD://standard
445 switch (request1->mBits.recipient) //Recipient
449 switch (request1->mBits.brequest)
451 case USB_REQUEST_SET_FEATURE:
454 case USB_REQUEST_SET_ADDRESS:
456 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
458 dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
459 EPI0_config (0, 1, FALSE, NULL);
462 case USB_REQUEST_GET_DESCRIPTOR:
463 usb_get_descriptor (request1, request2);
465 case USB_REQUEST_SET_CONFIGURATION: //0x00 0x09
466 g_cdc_configuration = request1->mBits.value_l;
467 EPI0_config (0, 1, FALSE, NULL);
471 usb_EPActive (EP_IN, USB_EP_DIR_IN);
472 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
476 case USB_REQUEST_GET_CONFIGURATION:
477 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_configuration);
479 case USB_REQUEST_SET_INTERFACE:
480 EPI0_config (0, 1, FALSE, NULL);
482 case USB_REQUEST_CLEAR_FEATURE:
483 if(request1->mBits.recipient == 2)
485 usb_reset_pipe(request2->mBits.index_l);
487 EPI0_config (0, 1, FALSE, NULL);
490 EPI0_config (0, 1, TRUE, &vendor_ack);
495 case USB_REC_INTERFACE:
497 switch(request1->mBits.brequest)
499 case USB_REQUEST_SET_INTERFACE://0x01 0x0b
500 g_cdc_interface = request1->mBits.value_l;
501 EPI0_config (0, 1, FALSE, NULL);
503 case USB_REQUEST_GET_INTERFACE://0x81 0x0a
504 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_interface);
509 case USB_REC_ENDPOINT:
511 switch(request1->mBits.brequest)
513 case USB_REQUEST_GET_STATUS://0x82 0x00
514 EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_state);
516 case USB_REQUEST_SET_FEATURE://0x02 0x03
520 case USB_REQUEST_CLEAR_FEATURE://0x02 0x01
521 if(request1->mBits.recipient == 2)
523 usb_reset_pipe(request2->mBits.index_l);
525 EPI0_config (0, 1, FALSE, NULL);
535 case USB_REQ_CLASS://class
536 switch (request1->mBits.recipient)
538 case USB_REC_INTERFACE:
539 switch (request1->mBits.brequest)
542 if (request1->mBits.value_l)
544 if (g_cdc_status == 0)
546 usb_EPActive (EP_IN, USB_EP_DIR_IN);
547 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
549 usb_debug("g_cdc_status = 1 \n");
552 EPI0_config (0, 1, FALSE, NULL);
555 if (request2->mBits.length_l)
557 USB_EP0RecvData((uint32 *)line_coding_config,request2->mBits.length_l);
559 EPI0_config (0, 1, FALSE, NULL);
562 EPI0_config(7, 1, TRUE,(uint32 *)line_coding_config);
563 USB_EP0RecvEmptyPacket();
565 case USB_CLEAR_COMM_FEATURE :
567 EPI0_config (0, 1, FALSE, NULL);
569 case USB_GET_COMM_FEATURE :
570 if (request2->mBits.length_l)
572 EPI0_config (2, 1, TRUE, &s_comm_feature);
575 case USB_SET_COMM_FEATURE :
576 if (request2->mBits.length_l)
578 USB_EP0RecvData((uint32 *)&s_comm_feature,2);
580 EPI0_config (0, 1, FALSE, NULL);
585 EPI0_config (0, 1, TRUE, NULL);
590 EPI0_config (4, 1, TRUE, &vendor_ack);
593 EPI0_config (0, 1, TRUE, NULL);
597 /*****************************************************************************/
598 // Description: usb reset interrupt handler.
599 // Global resource dependence:
600 // Author: jiayong.yang
602 /*****************************************************************************/
604 LOCAL void usb_reset_handler (void)
607 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
609 dcfg_ptr->mBits.devaddr = 0;
610 *(volatile uint32 *) USB_GAHBCFG |= BIT_5;
611 *(volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_12); // disable reset interrupt
613 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27; // set NAK for all OUT endpoint
615 *(volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
617 *(volatile uint32 *) USB_DAINTMSK |= (unsigned int) (BIT_0|BIT_16);
618 *(volatile uint32 *) USB_DOEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_2|BIT_1);
619 *(volatile uint32 *) USB_DIEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_1|BIT_2|BIT_5);//lint !e718
621 *(volatile uint32 *) USB_GRXFSIZ = (unsigned int) (BIT_2 | BIT_4 | BIT_8);
622 *(volatile uint32 *) USB_GNPTXFSIZ = (unsigned int) ((BIT_2 | BIT_4 | BIT_8) | BIT_20);
623 *(volatile uint32 *) USB_DIEPTXF (1) = (unsigned int) ((BIT_2 | BIT_5 | BIT_8) | BIT_24);
624 *(volatile uint32 *) USB_DIEPTXF (2) = (unsigned int) ((BIT_2 | BIT_5 | BIT_9) | BIT_18);
625 *(volatile uint32 *) USB_DIEPTXF (3) = (unsigned int) ((BIT_3 | BIT_5 | BIT_9) | BIT_24);
626 *(volatile uint32 *) USB_DIEPTXF (4) = (unsigned int) ((BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_18);
627 *(volatile uint32 *) USB_DIEPTXF (5) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_8 | BIT_9) | BIT_24);
628 *(volatile uint32 *) USB_DIEPTXF (6) = (unsigned int) ((BIT_2 | BIT_3 | BIT_5 | BIT_10) | BIT_18);
630 *(volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5; //reflush tx fifo
632 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
636 if (timeout >= USB_TIMEOUT)
644 * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4; //reflush rx fifo
646 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
650 if (timeout >= USB_TIMEOUT)
656 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));//////////for test
657 EPO0_config (TRUE, s_setup_packet);
659 *(volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12; // enable reset interrupt
660 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12; //clear reset interrupt
663 /*****************************************************************************/
664 // Description: usb enumeration done handler.
665 // Global resource dependence:
666 // Author: jiayong.yang
668 /*****************************************************************************/
670 LOCAL void usb_enumeration_done (void)
672 volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
674 enum_speed = dsts_ptr->mBits.enumspd; //read enumration speed
675 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
677 if ( enum_speed == USB_HIGH )
679 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, BULK_MPS);
680 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, BULK_MPS);
681 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
685 EPn_config (EP_IN, USB_EP_TYPE_BULK, USB_EP_DIR_IN, USB_PACKET_64);
686 EPn_config (EP_OUT, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, USB_PACKET_64);
687 EPn_config (EP_INTERRUPT, USB_EP_TYPE_INTERRUPT, USB_EP_DIR_IN, USB_PACKET_16);
689 usb_EPActive (EP_INTERRUPT, USB_EP_DIR_IN);
690 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
691 EPO0_config (TRUE, s_setup_packet);
693 *(volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
694 *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
697 /*****************************************************************************/
698 // Description: out endpoint0 handler.
699 // Global resource dependence:
700 // Author: jiayong.yang
702 /*****************************************************************************/
704 LOCAL void usb_EP0_out_handle (void)
706 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
707 USB_DOEPINT_U doepint;
709 doepint.dwValue = doepint_ptr->dwValue;
710 doepint_ptr->dwValue = doepint.dwValue;
712 if (doepint.mBits.timeout_condi)
717 if (doepint.mBits.transfer_com)
721 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
725 size = (*(volatile uint32 *)USB_DOEP0TSIZ) & 0x18;
732 Dcache_InvalRegion ((unsigned int) s_setup_packet, sizeof (s_setup_packet)); //0511
733 EPO0_config (TRUE, s_setup_packet); //renable ep0 nd set packet count
737 /*****************************************************************************/
738 // Description: out endpoint handler.
739 // Global resource dependence:
740 // Author: jiayong.yang
742 /*****************************************************************************/
743 LOCAL void usb_EP_out_handle (void)
745 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
748 daint.dwValue = daint_ptr->dwValue; // disable EP out interrupt
750 if (daint.mBits.outepint_0)
752 usb_EP0_out_handle();
755 //* (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
757 /*****************************************************************************/
758 // Description: in endpoint handler.
759 // Global resource dependence:
760 // Author: jiayong.yang
762 /*****************************************************************************/
763 LOCAL void usb_EP_in_handle (void)
765 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
768 daint.dwValue = daint_ptr->dwValue;
770 if (daint.mBits.inepint_0)
772 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (0);
773 USB_DIEPINT_U diepint;
774 diepint.dwValue = diepint_ptr->dwValue;
775 diepint_ptr->dwValue = diepint.dwValue;
779 /*****************************************************************************/
780 // Description: usb interrupt handler.
781 // Global resource dependence:
782 // Author: jiayong.yang
784 /*****************************************************************************/
785 static void usb_handler (void)
787 volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
788 volatile USB_INTSTS_U usb_int;
790 char string[64] ={0,};
791 usb_int.dwValue = usb_int_ptr->dwValue;
793 // in endpoint interrupt
794 if (usb_int.mBits.iepint)
797 // out endpoint interrupt
798 if (usb_int.mBits.oepint)
801 // enumeration done interrupt
802 if (usb_int.mBits.enumdone)
803 usb_enumeration_done();
806 if (usb_int.mBits.usbrst)
810 check_usb_reconnected = 1;
816 if (usb_int.mBits.usbsusp)
818 if(g_usb_status == USB_STARTED)
820 g_usb_status = USB_SUSPEND_AFTER_USB_MODE_START;
825 /*****************************************************************************/
826 // Description: configure in endpoint ep_id to send message.
827 // Global resource dependence:
828 // Author: jiayong.yang
830 /*****************************************************************************/
831 //extern int microusb_charger_connected(void);
832 extern u32 is_usb_cable(void);
833 static int32 USB_ReadEx_Internal(uint8 *pBuf,uint32 len)
835 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
836 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (EP_OUT);
841 if(doepint_ptr->mBits.transfer_com == 1)
843 doepint_ptr->mBits.transfer_com = 1;
846 Dcache_CleanRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);
847 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
848 while(doepint_ptr->mBits.transfer_com==0)
850 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
852 if(check_usb_reconnected == 1 && g_cdc_status == 1)
854 usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
855 check_usb_reconnected = 0;
858 doepint_ptr->mBits.transfer_com = 1;
859 Dcache_InvalRegion((unsigned int)(&pBuf[0]), MAX_RECV_LENGTH);//0511
860 recv_length = MAX_RECV_LENGTH - doeptsiz_ptr->mBits.transfer_size;
863 if(recv_length > len)
876 int USB_ReadEx(unsigned char *pBuf, int len)
883 read_len = USB_ReadEx_Internal(pBuf,len);
886 /* RDX exception handling when PC(intenet explorer) control RDX tool */
890 if( g_usb_status == USB_DETACHED_AFTER_USB_MODE_START )
900 /*****************************************************************************/
901 // Description: configure in endpoint ep_id to send message.
902 // Global resource dependence:
903 // Author: jiayong.yang
905 /*****************************************************************************/
906 PUBLIC int32 USB_WriteEx(uint8 *pBuf,uint32 len)
908 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
911 int transfer_size = 0;
912 int transfered_size = 0;
916 if(len > MAX_RECV_LENGTH)
918 transfer_size = MAX_RECV_LENGTH;
920 else if((len % MAX_PACKET_SIZE)==0)
922 transfer_size = len - 32;
929 len = len - transfer_size;
931 for(i=0;i<transfer_size;i++)
933 usb_out_endpoint_buf[1][i] = pBuf[i+transfered_size];
936 if(diepint_ptr->mBits.transfer_com == 1)
938 diepint_ptr->mBits.transfer_com = 1;
941 usb_start_transfer ( (USB_EP_NUM_E) EP_IN, USB_EP_DIR_IN, transfer_size, TRUE, (uint32 *) usb_out_endpoint_buf[1]);
944 diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
946 }while(diepint_ptr->mBits.transfer_com==0);
947 diepint_ptr->mBits.transfer_com = 1;
948 transfered_size += transfer_size;
950 return transfered_size;
953 /*****************************************************************************/
954 // Description: initialize the usb core.
955 // Global resource dependence:
956 // Author: jiayong.yang
958 /*****************************************************************************/
959 LOCAL void usb_core_init (void)
961 usb_debug("%s : enter \n", __func__);
964 //Core soft reset, include hclk and phy clock
965 * (volatile uint32 *) USB_GRSTCTL |= BIT_0;
966 usb_debug("Inside usb_core_init \n");
970 reg_val = * (volatile uint32 *) USB_GRSTCTL;
972 if (reg_val & BIT_31)
976 } while (time_out<10);
978 * (volatile uint32 *) USB_DCTL &= ~ (BIT_1); //soft disconnect
979 * (volatile uint32 *) USB_GOTGCTL |= BIT_6|BIT_7;//Bvalid en
981 // program global ahb configuration
983 * (volatile uint32 *) USB_GAHBCFG |= BIT_1|BIT_2|BIT_3; // burst length INCR16
984 * (volatile uint32 *) USB_GAHBCFG |= BIT_0; // global interrupt mask , 0:mask 1:unmask
986 // program global usb configuration
987 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_6); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
988 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_17); // External FS PAY or Interal FS Serial PHY Selection, UTMI+ or ULPI PHY
989 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_4); // ULPI or UTMI+ selection bit, UTMI+ interface
990 * (volatile uint32 *) USB_GUSBCFG |= BIT_3; // PHY Interface bit, 16 bit
991 * (volatile uint32 *) USB_GUSBCFG &= ~ (BIT_0|BIT_1|BIT_2); // HS/FS time out calibration,
992 * (volatile uint32 *) USB_GUSBCFG |= BIT_10|BIT_12; // USB turnaround time, 16bit UTMI+
993 * (volatile uint32 *) USB_GUSBCFG |= BIT_30; // force device mode
995 * (volatile uint32 *) USB_GINTSTS = 0xffffffff;
997 * (volatile uint32 *) USB_GINTMSK = 0; // mask all first
1000 * (volatile uint32 *) USB_DCFG &= ~BIT_2; // out handshake
1001 * (volatile uint32 *) USB_DCFG &= ~ (BIT_11 | BIT_12);
1003 * (volatile uint32 *) USB_GINTMSK |= BIT_12; // usb reset int mask, 0:mask 1:unmask
1004 * (volatile uint32 *) USB_GINTMSK |= BIT_13; // enumeration done int mask, 0:mask 1:unmask
1005 * (volatile uint32 *) USB_GINTMSK |= BIT_18;
1006 * (volatile uint32 *) USB_GINTMSK |= BIT_19;
1008 * (volatile uint32 *) USB_GINTMSK &= ~BIT_4; // DMA mode, must mask rx fifo level interrupt
1010 * (volatile uint32 *) USB_DCFG &= ~BIT_0; //configure HS mode.
1011 usb_debug("After USBC_CORE_INIT \n");
1013 /*****************************************************************************/
1014 // Description: configure in endpoint ep_id to send message.
1015 // Global resource dependence:
1016 // Author: jiayong.yang
1018 /*****************************************************************************/
1021 void thor_USB_Init(void)
1023 usb_debug("%s : enter\n", __func__);
1024 unsigned int len = 0;
1028 usb_debug("usb_Core_init() is called\n");
1031 while (!g_cdc_status)
1034 sprd_usb_thor_start();
1036 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START) {
1037 g_usb_status = USB_BEFORE_USB_MODE;
1043 void USB_DeInit (void)
1048 __align(64) unsigned char sprd_thor_setup_buf[512] = {0,};
1050 static int s_usb_connected = 0;
1052 /************************************************
1054 * Register call back function for v3_protocol.
1056 ************************************************/
1058 //extern int usb_cb_register(u32 (*up)(void *, u32), u32 (*down)(void *, u32));
1060 void sprd_usb_cb_register(void)
1062 usb_debug("%s : start \n", __func__);
1063 usb_cb_register(USB_WriteEx, USB_ReadEx);
1067 extern int thor_handle(void);
1069 void sprd_usb_thor_start()
1071 g_usb_status = USB_STARTED;
1074 if (s_usb_connected == 0) {
1075 USB_ReadEx_Internal(sprd_thor_setup_buf, sizeof(sprd_thor_setup_buf));
1077 if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START)
1080 if (!strncmp(sprd_thor_setup_buf, "THOR", strlen("THOR")))
1082 usb_debug("- thor is connected!\n");
1083 USB_WriteEx("ROHT", strlen("ROHT"));
1084 usb_debug("thor Setup Complete\n");
1085 s_usb_connected = 1;
1088 usb_debug("thor_seup error - Not receiving THOR\n");
1089 s_usb_connected = 0;
1096 usb_debug("%s : exit \n", __func__);
1100 void disconnect_usb(void)
1102 s_usb_connected = 0;
1105 int thor_usb_is_connected(void)
1107 return s_usb_connected;