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