change source file mode to 0644 instead of 0755
[profile/mobile/platform/kernel/u-boot-tm1.git] / property / usb / drv_cdc.c
1 /******************************************************************************
2  ** File Name:      DRV_usb.c                                                 *
3  ** Author:         JiaYong.Yang                                              *
4  ** DATE:           09/01/2010                                                *
5  ** Copyright:      2010 Spreatrum, Incoporated. All Rights Reserved.         *
6  ** Description:                                                              *
7  ******************************************************************************/
8 /**---------------------------------------------------------------------------*
9  **                         Dependencies                                      *
10  **---------------------------------------------------------------------------*/
11 #include <config.h>
12 #include <common.h>
13
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
21 #define USB_DEBUG
22
23 #ifdef USB_DEBUG
24 #define usb_debug(fmt, arg...)          printf(fmt, ## arg)
25 #else
26 #define usb_debug(fmt, arg...)
27 #endif
28
29 typedef enum
30 {
31         USB_HIGH, USB_FULL, USB_LOW
32 } USB_SPEED;
33
34 #define USB_DEVICE_QUALIFIER_TYPE                 0x06
35 #define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE                 0x07
36
37
38 #define PUBLIC
39 #define LOCAL static
40 int rdx=0;
41 int x=0;
42 int error=0;
43 int length;
44 int check_usb_reconnected = 0;
45
46 extern void usb_power_on(void);
47
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);
51
52 static __inline void usb_handler (void);
53
54 //static int booting_mode = BOOT_MODE_NORMAL;
55
56 /**---------------------------------------------------------------------------*
57  **                         Compiler Flag                                     *
58  **---------------------------------------------------------------------------*/
59 #define BULK_MPS                USB_PACKET_512
60 #define EP_OUT                  USB_EP2
61 #define EP_IN                   USB_EP1
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)
66
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
71
72 /**---------------------------------------------------------------------------*
73  **                         Data Structures                                   *
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;
83 /*++for ch9 test*/
84 uint32  g_cdc_state = 0;
85 LOCAL uint32 g_cdc_configuration = 1;
86 LOCAL uint32 g_cdc_interface = 1;
87 /*--for ch9 test*/
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
93 //  Note:
94 /*****************************************************************************/
95 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
96 {
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
100
101         if (is_dma)
102         {
103                 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
104         }
105
106         * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26;    // set clear NAK
107         * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31;    // set endpoint enable
108         return 0;
109 }
110 /*****************************************************************************/
111 //  Description:   configure in endpoint0 to send message.
112 //  Global resource dependence:
113 //  Author:        jiayong.yang
114 //  Note:
115 /*****************************************************************************/
116 LOCAL void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
117 {
118         volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
119
120         diep0tsiz_ptr->mBits.transfer_size = transfer_size;
121         diep0tsiz_ptr->mBits.packet_count = packet_count;
122
123         if (is_dma)
124         {
125                 Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
126                 * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
127         }
128
129         * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
130
131         * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26;                    // clear NAK
132
133         * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31;                    // set endpoint enable
134
135         while(1)
136         {
137                 diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
138                 if(diep0tsiz_ptr->dwValue==0)
139                 {
140                         break;
141                 }
142         }
143         diep0tsiz_ptr->dwValue=0;
144 }
145 /*****************************************************************************/
146 //  Description:   usb reset interrupt handler.
147 //  Global resource dependence:
148 //  Author:        jiayong.yang
149 //  Note:
150 /*****************************************************************************/
151 LOCAL void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
152 {
153         if (dir)        // out endpoint
154         {
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);
157         }
158         else
159         {
160                 *(volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_15;     //lint !e718// endpoint active
161                 *(volatile uint32 *) USB_DIEPMSK = 0xffffffff;
162         }
163 }
164 /*****************************************************************************/
165 //  Description:   configure specified endpoint to send/receive message.
166 //  Global resource dependence:
167 //  Author:        jiayong.yang
168 //  Note:
169 /*****************************************************************************/
170 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
171 {
172         // out endpoint
173         if (dir)
174         {
175                 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
176
177                 doepctl_ptr->mBits.ep_type = ep_type;
178                 doepctl_ptr->mBits.mps =mps;
179                 doepctl_ptr->mBits.set_nak = 0x1;
180         }
181         else
182         {
183                 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
184
185                 diepctl_ptr->mBits.ep_type = ep_type;
186                 diepctl_ptr->mBits.mps = mps;
187                 diepctl_ptr->mBits.set_nak = 0x1;
188         }
189 }
190
191 /*****************************************************************************/
192 //  Description:   start endpoint transfer.
193 //  Global resource dependence:
194 //  Author:        jiayong.yang
195 //  Note:
196 /*****************************************************************************/
197 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
198 {
199         uint16 packet_count = 0;
200
201         if (dir)
202         {
203                 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
204
205                 if (is_dma)
206                 {
207                         * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
208                 }
209
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
213         }
214         else
215         {
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);
218
219                 if (is_dma)
220                 {
221                         Dcache_CleanRegion((unsigned int)buffer,  transfer_size);//0511
222                         * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
223                 }
224
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
229
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
232         }
233
234 }
235
236 /*****************************************************************************/
237 //  Description:   process desecriptor request.
238 //  Global resource dependence:
239 //  Author:        jiayong.yang
240 //  Note:
241 /*****************************************************************************/
242 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
243 {
244         uint32 length = 0;
245         uint8 *send_data=NULL;
246         uint8 pkt_cnt=0;
247         uint32 config_des_size=0;
248
249         length = (uint32) (request2->mBits.length_m<<8 |request2->mBits.length_l);
250
251         switch (request1->mBits.value_m)
252         {
253                 case USB_DEVICE_DESCRIPTOR_TYPE:
254                         send_data = (uint8 *) thor_get_device_desc(enum_speed);
255
256                         EPI0_config (0x12, 0x1, TRUE, (uint32 *) send_data);
257                         break;
258
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];
262
263                         if (length > config_des_size)
264                         {
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);
267                         }
268                         else
269                         {
270                                 pkt_cnt =  (length % 64) ? length/64 + 1 : length/64;
271                                 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
272                         }
273                         break;
274
275                 case USB_STRING_DESCRIPTOR_TYPE:
276                 {
277                         uint8 str_index = request1->mBits.value_l;
278                         send_data = thor_get_string_desc(str_index);
279
280                         if(length > send_data[0])
281                         {
282                                 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
283                         }
284                         else
285                         {
286                                 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
287                         }
288                 }
289                         break;
290
291                 case USB_DEVICE_QUALIFIER_TYPE:
292                         send_data = (uint8 *) thor_get_qualifer_desc();
293                         if(length > send_data[0])
294                         {
295                                 EPI0_config (send_data[0], 0x1, TRUE, (uint32 *) send_data);
296                         }
297                         else
298                         {
299                                 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
300                         }
301                         break;
302
303                 case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
304
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)
308                         {
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);
311                         }
312                         else
313                         {
314                                 pkt_cnt =  (length % 64) ? length/64 + 1 : length/64;
315                                 EPI0_config (length, pkt_cnt, TRUE, (uint32 *) send_data);
316                         }
317                         break;
318
319                 default:
320                         break;
321         }
322 }
323 /*****************************************************************************/
324 //  Description:   process setup transaction.
325 //  Global resource dependence:
326 //  Author:        jiayong.yang
327 //  Note:
328 /*****************************************************************************/
329 LOCAL int USB_EP0RecvEmptyPacket (void)
330 {
331         uint32 packet_count;
332         volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
333
334         if(doepint_ptr->mBits.transfer_com == 1)
335                 doepint_ptr->mBits.transfer_com=1;
336         packet_count = 1;
337         * (volatile uint32 *) USB_DOEP0TSIZ = (packet_count<<19) ; //setup packet count , 3 packet
338
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)
342         {
343                 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
344         }
345         return 0;
346 }
347 LOCAL int USB_EP0RecvData (uint32 *pBuf,int transfer_size)
348 {
349         uint32 packet_count;
350
351         if (transfer_size == 0)
352         {
353                 return 0;
354         }
355
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
361         return 0;
362 }
363 LOCAL void usb_reset_pipe(uint8 epno)
364 {
365         uint8 ep_num = epno & 0x7F;
366         if(ep_num == 0)
367         {
368                 return;
369         }
370         if((epno & 0x80) == 0)
371         {
372                 *(volatile uint32 *)USB_DOEPCTL(ep_num) |= BIT_28;
373         }
374         else
375         {
376                 *(volatile uint32 *)USB_DIEPCTL(ep_num) |= BIT_28;
377         }
378 }
379 /*****************************************************************************/
380 //  Description:   process setup transaction.
381 //  Global resource dependence:
382 //  Author:        jiayong.yang
383 //  Note:
384 /*****************************************************************************/
385 PUBLIC void usb_set_feature (void)
386 {
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;
397
398         EPI0_config (0x0, 0x1, FALSE, NULL);
399
400         while (* (volatile uint32 *) USB_DIEP0TSIZ) {}; // wait packet count is zero
401
402         * (volatile uint32 *) USB_DOEP0CTL |= BIT_26; // clear ep out nak
403
404         switch (request2->mBits.index_m)
405         {
406                 case    1://Test_J
407                         dctl_ptr->mBits.tstctl = request2->mBits.index_m;
408                         break;
409                 case    2://Test_K
410                         dctl_ptr->mBits.tstctl = request2->mBits.index_m;
411                         break;
412                 case    3://Test_SE0_NAK
413                         dctl_ptr->mBits.tstctl = request2->mBits.index_m;
414                         break;
415                 case    4://Test_Packet
416                         dctl_ptr->mBits.tstctl = request2->mBits.index_m;
417                         break;
418                 case    5://Test_Force_Enable
419                         dctl_ptr->mBits.tstctl = request2->mBits.index_m;
420                         break;
421                 default:
422                         break;
423         }
424
425         dctl_ptr->mBits.tstctl = request2->mBits.index_m;
426 }
427
428 LOCAL void usb_setup_handle (void)
429 {
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;
440
441         switch (request1->mBits.type)
442         {
443                 case USB_REQ_STANDARD://standard
444
445                         switch (request1->mBits.recipient)                                              //Recipient
446                         {
447                                 case USB_REC_DEVICE:
448
449                                         switch (request1->mBits.brequest)
450                                         {
451                                                 case USB_REQUEST_SET_FEATURE:
452                                                         usb_set_feature ();
453                                                         break;
454                                                 case USB_REQUEST_SET_ADDRESS:
455                                                 {
456                                                         volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
457
458                                                         dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
459                                                         EPI0_config (0, 1, FALSE, NULL);
460                                                 }
461                                                         break;
462                                                 case USB_REQUEST_GET_DESCRIPTOR:
463                                                         usb_get_descriptor (request1, request2);
464                                                         break;
465                                                 case USB_REQUEST_SET_CONFIGURATION: //0x00 0x09
466                                                         g_cdc_configuration = request1->mBits.value_l;
467                                                         EPI0_config (0, 1, FALSE, NULL);
468
469                                                         if(g_cdc_status ==0)
470                                                         {
471                                                                 usb_EPActive (EP_IN, USB_EP_DIR_IN);
472                                                                 usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
473                                                                 g_cdc_status = 1;
474                                                         }
475                                                         break;
476                                                 case USB_REQUEST_GET_CONFIGURATION:
477                                                         EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_configuration);
478                                                         break;
479                                                 case USB_REQUEST_SET_INTERFACE:
480                                                         EPI0_config (0, 1, FALSE, NULL);
481                                                         break;
482                                                 case USB_REQUEST_CLEAR_FEATURE:
483                                                         if(request1->mBits.recipient == 2)
484                                                         {
485                                                                 usb_reset_pipe(request2->mBits.index_l);
486                                                         }
487                                                         EPI0_config (0, 1, FALSE, NULL);
488                                                         break;
489                                                 default:
490                                                         EPI0_config (0, 1, TRUE, &vendor_ack);
491                                                         break;
492                                         }
493                                         break;
494
495                                 case USB_REC_INTERFACE:
496
497                                         switch(request1->mBits.brequest)
498                                         {
499                                                 case USB_REQUEST_SET_INTERFACE://0x01 0x0b
500                                                         g_cdc_interface = request1->mBits.value_l;
501                                                         EPI0_config (0, 1, FALSE, NULL);
502                                                         break;
503                                                 case USB_REQUEST_GET_INTERFACE://0x81 0x0a
504                                                         EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_interface);
505                                                         break;
506                                         }
507                                         break;
508
509                                 case USB_REC_ENDPOINT:
510
511                                         switch(request1->mBits.brequest)
512                                         {
513                                                 case USB_REQUEST_GET_STATUS://0x82 0x00
514                                                         EPI0_config (request2->mBits.length_l, 1, TRUE, &g_cdc_state);
515                                                         break;
516                                                 case USB_REQUEST_SET_FEATURE://0x02 0x03
517                                                         g_cdc_state = 1;
518                                                         usb_set_feature ();
519                                                         break;
520                                                 case USB_REQUEST_CLEAR_FEATURE://0x02 0x01
521                                                         if(request1->mBits.recipient == 2)
522                                                         {
523                                                                 usb_reset_pipe(request2->mBits.index_l);
524                                                         }
525                                                         EPI0_config (0, 1, FALSE, NULL);
526                                                         g_cdc_state = 0;
527                                                         break;
528                                                 default:
529                                                         break;
530                                         }
531                                         break;
532                         }
533                         break;
534
535                 case USB_REQ_CLASS://class
536                         switch (request1->mBits.recipient)
537                         {
538                                 case USB_REC_INTERFACE:
539                                         switch (request1->mBits.brequest)
540                                         {
541                                                 case 0x22:
542                                                         if (request1->mBits.value_l)
543                                                         {
544                                                                 if (g_cdc_status == 0)
545                                                                 {
546                                                                         usb_EPActive (EP_IN, USB_EP_DIR_IN);
547                                                                         usb_EPActive (EP_OUT, USB_EP_DIR_OUT);
548                                                                         g_cdc_status = 1;
549                                                                         usb_debug("g_cdc_status = 1 \n");
550                                                                 }
551                                                         }
552                                                         EPI0_config (0, 1, FALSE, NULL);
553                                                         break;
554                                                 case 0x20:
555                                                         if (request2->mBits.length_l)
556                                                         {
557                                                                 USB_EP0RecvData((uint32 *)line_coding_config,request2->mBits.length_l);
558                                                         }
559                                                                 EPI0_config (0, 1, FALSE, NULL);
560                                                         break;
561                                                 case 0x21:
562                                                         EPI0_config(7, 1, TRUE,(uint32 *)line_coding_config);
563                                                         USB_EP0RecvEmptyPacket();
564                                                         break;
565                                                 case USB_CLEAR_COMM_FEATURE :
566                                                         s_comm_feature = 0;
567                                                         EPI0_config (0, 1, FALSE, NULL);
568                                                         break;
569                                                 case USB_GET_COMM_FEATURE :
570                                                         if (request2->mBits.length_l)
571                                                         {
572                                                                 EPI0_config (2, 1, TRUE, &s_comm_feature);
573                                                         }
574                                                         break;
575                                                 case USB_SET_COMM_FEATURE :
576                                                         if (request2->mBits.length_l)
577                                                         {
578                                                                 USB_EP0RecvData((uint32 *)&s_comm_feature,2);
579                                                         }
580                                                         EPI0_config (0, 1, FALSE, NULL);
581                                                         break;
582                                         }
583                                         break;
584                                 default:
585                                         EPI0_config (0, 1, TRUE, NULL);
586                                         break;
587                         }
588                         break;
589                 case USB_REQ_VENDOR:
590                         EPI0_config (4, 1, TRUE, &vendor_ack);
591                         break;
592                 default:
593                         EPI0_config (0, 1, TRUE, NULL);
594                         break;
595         }
596 }
597 /*****************************************************************************/
598 //  Description:   usb reset interrupt handler.
599 //  Global resource dependence:
600 //  Author:        jiayong.yang
601 //  Note:
602 /*****************************************************************************/
603
604 LOCAL void usb_reset_handler (void)
605 {
606         uint32  timeout = 0;
607         volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
608
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
612
613     *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;                            // set NAK for all OUT endpoint
614
615     *(volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
616
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
620
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);
629
630     *(volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5;                          //reflush tx fifo
631
632         while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
633         {
634                 timeout++;
635
636                 if (timeout >= USB_TIMEOUT)
637                 {
638                         break;
639                 }
640         }
641
642         timeout = 0;
643
644         * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4;                          //reflush rx fifo
645
646         while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
647         {
648                 timeout++;
649
650                 if (timeout >= USB_TIMEOUT)
651                 {
652                         break;
653                 }
654         }
655
656         Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));//////////for test
657         EPO0_config (TRUE, s_setup_packet);
658
659         *(volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12;                             // enable reset interrupt
660         *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12;                             //clear reset interrupt
661 }
662
663 /*****************************************************************************/
664 //  Description:   usb enumeration done handler.
665 //  Global resource dependence:
666 //  Author:        jiayong.yang
667 //  Note:
668 /*****************************************************************************/
669
670 LOCAL void usb_enumeration_done (void)
671 {
672         volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
673
674         enum_speed = dsts_ptr->mBits.enumspd;                                   //read enumration speed
675         * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
676
677         if ( enum_speed == USB_HIGH )
678         {
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);
682         }
683         else
684         {
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);
688         }
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);
692
693         *(volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
694         *(volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
695 }
696
697 /*****************************************************************************/
698 //  Description:   out endpoint0 handler.
699 //  Global resource dependence:
700 //  Author:        jiayong.yang
701 //  Note:
702 /*****************************************************************************/
703
704 LOCAL void usb_EP0_out_handle (void)
705 {
706         volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
707         USB_DOEPINT_U doepint;
708
709         doepint.dwValue = doepint_ptr->dwValue;
710         doepint_ptr->dwValue = doepint.dwValue;
711
712         if (doepint.mBits.timeout_condi)
713         {
714                 usb_setup_handle ();
715         }
716
717         if (doepint.mBits.transfer_com)
718         {
719                 uint8 size = 0;
720                 uint32 i;
721                 *(volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
722
723                 for(i=0;i<50;i++);
724
725                 size = (*(volatile uint32 *)USB_DOEP0TSIZ) & 0x18;
726                 if(size != 0x18)
727                 {
728                         usb_setup_handle();
729                 }
730         }
731
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
734 }
735
736
737 /*****************************************************************************/
738 //  Description:   out endpoint handler.
739 //  Global resource dependence:
740 //  Author:        jiayong.yang
741 //  Note:
742 /*****************************************************************************/
743 LOCAL void usb_EP_out_handle (void)
744 {
745         volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
746         USB_DAINT_U daint;
747
748         daint.dwValue = daint_ptr->dwValue;         // disable EP out interrupt
749
750         if (daint.mBits.outepint_0)
751         {
752                 usb_EP0_out_handle();
753         }
754
755         //* (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
756 }
757 /*****************************************************************************/
758 //  Description:   in endpoint handler.
759 //  Global resource dependence:
760 //  Author:        jiayong.yang
761 //  Note:
762 /*****************************************************************************/
763 LOCAL void usb_EP_in_handle (void)
764 {
765         volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
766         USB_DAINT_U daint;
767
768         daint.dwValue = daint_ptr->dwValue;
769
770         if (daint.mBits.inepint_0)
771         {
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;
776         }
777 }
778
779 /*****************************************************************************/
780 //  Description:   usb interrupt handler.
781 //  Global resource dependence:
782 //  Author:        jiayong.yang
783 //  Note:
784 /*****************************************************************************/
785 static  void usb_handler (void)
786 {
787         volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
788         volatile USB_INTSTS_U  usb_int;
789         uint32 i=0;
790          char string[64] ={0,};
791         usb_int.dwValue = usb_int_ptr->dwValue;
792
793         // in endpoint interrupt
794         if (usb_int.mBits.iepint)
795                 usb_EP_in_handle();
796
797         // out endpoint interrupt
798         if (usb_int.mBits.oepint)
799                 usb_EP_out_handle();
800
801         // enumeration done interrupt
802         if (usb_int.mBits.enumdone)
803                 usb_enumeration_done();
804
805         // reset interrupt
806         if (usb_int.mBits.usbrst)
807         {
808                 if (g_cdc_status)
809                 {
810                         check_usb_reconnected = 1;
811                         g_cdc_status = 0;
812                 }
813                 usb_reset_handler();
814         }
815
816         if (usb_int.mBits.usbsusp)
817         {
818                 if(g_usb_status == USB_STARTED)
819                 {
820                         g_usb_status = USB_SUSPEND_AFTER_USB_MODE_START;
821                 }
822         }
823 }
824
825 /*****************************************************************************/
826 //  Description:   configure in endpoint ep_id to send message.
827 //  Global resource dependence:
828 //  Author:        jiayong.yang
829 //  Note:
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)
834 {
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);
837     int i;
838
839     if(recv_length == 0)
840     {
841         if(doepint_ptr->mBits.transfer_com == 1)
842         {
843             doepint_ptr->mBits.transfer_com = 1;
844         }
845
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)
849         {
850                 doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (EP_OUT);
851                 usb_handler();
852                 if(check_usb_reconnected == 1 && g_cdc_status == 1)
853                 {
854                         usb_start_transfer (EP_OUT, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) pBuf);
855                         check_usb_reconnected = 0;
856                 }
857         }
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;
861     }
862
863     if(recv_length > len)
864     {
865         recv_length -= len;
866     }
867     else
868     {
869         len = recv_length;
870         recv_length = 0;
871     }
872
873     return len;
874 }
875
876 int USB_ReadEx(unsigned char *pBuf, int len)
877 {
878     int32 ret = len;
879     int32 read_len = 0;
880     if (len == 0)
881                 return 0;
882     do {
883         read_len = USB_ReadEx_Internal(pBuf,len);
884         if( read_len == 6 )
885         {
886             /* RDX exception handling when PC(intenet explorer) control RDX tool */
887             return 6;
888         }
889
890         if( g_usb_status == USB_DETACHED_AFTER_USB_MODE_START )
891         {
892             return 0;
893         }
894         pBuf += read_len;
895         len -= read_len;
896     } while (len > 0);
897
898     return ret;
899 }
900 /*****************************************************************************/
901 //  Description:   configure in endpoint ep_id to send message.
902 //  Global resource dependence:
903 //  Author:        jiayong.yang
904 //  Note:
905 /*****************************************************************************/
906 PUBLIC int32 USB_WriteEx(uint8 *pBuf,uint32 len)
907 {
908         volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
909         int i;
910
911         int transfer_size = 0;
912         int transfered_size = 0;
913
914
915         do{
916                 if(len > MAX_RECV_LENGTH)
917                 {
918                         transfer_size = MAX_RECV_LENGTH;
919                 }
920                 else if((len % MAX_PACKET_SIZE)==0)
921                 {
922                         transfer_size = len - 32;
923                 }
924                 else
925                 {
926                         transfer_size = len;
927                 }
928
929                 len = len - transfer_size;
930
931                 for(i=0;i<transfer_size;i++)
932                 {
933                         usb_out_endpoint_buf[1][i] = pBuf[i+transfered_size];
934                 }
935
936                 if(diepint_ptr->mBits.transfer_com == 1)
937                 {
938                         diepint_ptr->mBits.transfer_com = 1;
939                 }
940                 usb_handler();
941                 usb_start_transfer ( (USB_EP_NUM_E) EP_IN, USB_EP_DIR_IN, transfer_size, TRUE, (uint32 *) usb_out_endpoint_buf[1]);
942
943                 do{
944                         diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (EP_IN);
945                         usb_handler();
946                 }while(diepint_ptr->mBits.transfer_com==0);
947                 diepint_ptr->mBits.transfer_com = 1;
948                 transfered_size += transfer_size;
949         }while(len >0);
950         return transfered_size;
951 }
952
953 /*****************************************************************************/
954 //  Description:   initialize the usb core.
955 //  Global resource dependence:
956 //  Author:        jiayong.yang
957 //  Note:
958 /*****************************************************************************/
959 LOCAL void usb_core_init (void)
960 {
961         usb_debug("%s : enter \n", __func__);
962         uint32 time_out=0;
963
964         //Core soft reset, include hclk and phy clock
965         * (volatile uint32 *) USB_GRSTCTL |= BIT_0;
966         usb_debug("Inside usb_core_init \n");
967         do {
968                 uint32 reg_val = 0;
969                 time_out++;
970                 reg_val = * (volatile uint32 *) USB_GRSTCTL;
971
972                 if (reg_val & BIT_31)
973                 {
974                         break;
975                 }
976         } while (time_out<10);
977
978         * (volatile uint32 *) USB_DCTL &= ~ (BIT_1);  //soft disconnect
979         * (volatile uint32 *) USB_GOTGCTL |= BIT_6|BIT_7;//Bvalid en
980
981         // program global ahb configuration
982
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
985
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
994
995         * (volatile uint32 *) USB_GINTSTS = 0xffffffff;
996
997         * (volatile uint32 *) USB_GINTMSK =  0;                     // mask all first
998
999         // device init
1000         * (volatile uint32 *) USB_DCFG &= ~BIT_2;                   // out handshake
1001         * (volatile uint32 *) USB_DCFG &= ~ (BIT_11 | BIT_12);
1002
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;
1007
1008         * (volatile uint32 *) USB_GINTMSK &= ~BIT_4;                // DMA mode, must mask rx fifo level interrupt
1009
1010         * (volatile uint32 *) USB_DCFG &= ~BIT_0;  //configure HS mode.
1011         usb_debug("After USBC_CORE_INIT \n");
1012 }
1013 /*****************************************************************************/
1014 //  Description:   configure in endpoint ep_id to send message.
1015 //  Global resource dependence:
1016 //  Author:        jiayong.yang
1017 //  Note:
1018 /*****************************************************************************/
1019
1020 /* Enter point */
1021 void thor_USB_Init(void)
1022 {
1023         usb_debug("%s : enter\n", __func__);
1024         unsigned int len = 0;
1025
1026         usb_power_on();
1027         usb_core_init();
1028         usb_debug("usb_Core_init() is called\n");
1029
1030 USB_RESTART:
1031         while (!g_cdc_status)
1032                 usb_handler();
1033
1034         sprd_usb_thor_start();
1035
1036         if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START) {
1037                 g_usb_status = USB_BEFORE_USB_MODE;
1038                 g_cdc_status = 0;
1039                 goto USB_RESTART;
1040         }
1041 }
1042
1043 void USB_DeInit (void)
1044 {
1045         usb_power_off();
1046 }
1047
1048 __align(64) unsigned char sprd_thor_setup_buf[512] = {0,};
1049
1050 static int s_usb_connected = 0;
1051
1052 /************************************************
1053  *
1054  * Register call back function for v3_protocol.
1055  *
1056  ************************************************/
1057 /* FIXME */
1058 //extern int usb_cb_register(u32 (*up)(void *, u32), u32 (*down)(void *, u32));
1059 #if 0
1060 void sprd_usb_cb_register(void)
1061 {
1062         usb_debug("%s : start \n", __func__);
1063         usb_cb_register(USB_WriteEx, USB_ReadEx);
1064 }
1065 #endif
1066
1067 extern int thor_handle(void);
1068
1069 void sprd_usb_thor_start()
1070 {
1071     g_usb_status = USB_STARTED;
1072
1073         do {
1074                 if (s_usb_connected == 0) {
1075                         USB_ReadEx_Internal(sprd_thor_setup_buf, sizeof(sprd_thor_setup_buf));
1076
1077                         if (g_usb_status == USB_DETACHED_AFTER_USB_MODE_START)
1078                                 return -1;
1079
1080                         if (!strncmp(sprd_thor_setup_buf, "THOR", strlen("THOR")))
1081                         {
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;
1086                                 break;
1087                         } else{
1088                                 usb_debug("thor_seup error - Not receiving THOR\n");
1089                                 s_usb_connected = 0;
1090                         }
1091                 }
1092         } while(1);
1093
1094         thor_handle();
1095
1096         usb_debug("%s : exit \n", __func__);
1097         return 0;
1098 }
1099
1100 void disconnect_usb(void)
1101 {
1102         s_usb_connected = 0;
1103 }
1104
1105 int thor_usb_is_connected(void)
1106 {
1107         return s_usb_connected;
1108 }