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