Root/usbboot/xburst_stage2/udc.c

1/*
2 * Copyright (C) 2009 Qi Hardware Inc.,
3 * Author: Xiangfu Liu <xiangfu@sharism.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 3 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA
18 */
19#include "usb/usb.h"
20#include "usb/udc.h"
21#include "target/usb_boot.h"
22#include "target/xburst_types.h"
23#include "ingenic_request.h"
24
25#if defined(NANONOTE)
26#include "target/jz4740.h"
27#elif defined(LEPUS)
28#include "target/jz4760.h"
29#else
30    #error "Please Define [NANONOTE] or [LEPUS]"
31#endif
32
33#define dprintf(x...) /* serial_puts(x) */
34#define TXFIFOEP0 USB_FIFO_EP0
35
36extern void serial_put_hex(int );
37
38u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
39u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
40u32 Bulk_in_size, Bulk_in_finish, Bulk_out_size;
41u16 handshake_PKT[4] = {0, 0, 0, 0};
42u8 udc_state;
43
44static u32 rx_buf[32];
45static u32 tx_buf[32];
46static u32 tx_size, rx_size, finished, fifo;
47static u8 ep0state, USB_Version;
48
49static u32 fifoaddr[] =
50{
51    TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8
52};
53
54static u32 fifosize[] = {
55    MAX_EP0_SIZE, MAX_EP1_SIZE
56};
57
58void *memset(void *s, int c, size_t count)
59{
60    char *xs = s;
61
62    while (count--)
63        *xs++ = c;
64    return s;
65}
66
67void *memcpy(void *dest, const void *src, size_t count)
68{
69    char *tmp = dest;
70    const char *s = src;
71
72    while (count--)
73        *tmp++ = *s++;
74
75    return dest;
76}
77
78static void udcReadFifo(u8 *ptr, int size)
79{
80    u32 *d = (u32 *)ptr;
81    int s;
82    s = (size + 3) >> 2;
83    while (s--)
84        *d++ = REG32(fifo);
85}
86
87static void udcWriteFifo(u8 *ptr, int size)
88{
89    u32 *d = (u32 *)ptr;
90    u8 *c;
91    int s, q;
92
93    if (size > 0) {
94        s = size >> 2;
95        while (s--)
96            REG32(fifo) = *d++;
97        q = size & 3;
98        if (q) {
99            c = (u8 *)d;
100            while (q--)
101                REG8(fifo) = *c++;
102        }
103    }
104}
105
106void HW_SendPKT(int ep, const u8 *buf, int size)
107{
108    fifo = fifoaddr[ep];
109
110    if (ep!=0) {
111        Bulk_in_size = size;
112        Bulk_in_finish = 0;
113        jz_writeb(USB_REG_INDEX, ep);
114        if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) {
115            udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
116                     Bulk_in_size - Bulk_in_finish);
117            usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
118            Bulk_in_finish = Bulk_in_size;
119        } else {
120            udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
121                     fifosize[ep]);
122            usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
123            Bulk_in_finish += fifosize[ep];
124        }
125    } else {
126        tx_size = size;
127        finished = 0;
128        memcpy((void *)tx_buf, buf, size);
129        ep0state = USB_EP0_TX;
130    }
131}
132
133void HW_GetPKT(int ep, const u8 *buf, int size)
134{
135    memcpy((void *)buf, (u8 *)rx_buf, size);
136    fifo = fifoaddr[ep];
137    if (rx_size > size)
138        rx_size -= size;
139    else {
140        size = rx_size;
141        rx_size = 0;
142    }
143    memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size);
144}
145
146static USB_DeviceDescriptor devDesc =
147{
148    sizeof(USB_DeviceDescriptor),
149    DEVICE_DESCRIPTOR, //1
150    0x0200, //Version 2.0
151    0xff, //Vendor spec class
152    0xff,
153    0xff,
154    64, /* Ep0 FIFO size */
155    0x601a, //vendor ID
156    0x4740, //Product ID
157    0xffff,
158    0x00,
159    0x00,
160    0x00,
161    0x01
162};
163
164#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \
165                 sizeof(USB_InterfaceDescriptor) + \
166                 sizeof(USB_EndPointDescriptor) * 2)
167
168static struct {
169    USB_ConfigDescriptor configuration_descriptor;
170    USB_InterfaceDescriptor interface_descritor;
171    USB_EndPointDescriptor endpoint_descriptor[2];
172} __attribute__ ((packed)) confDesc = {
173    {
174        sizeof(USB_ConfigDescriptor),
175        CONFIGURATION_DESCRIPTOR,
176        CONFIG_DESCRIPTOR_LEN,
177        0x01,
178        0x01,
179        0x00,
180        0xc0, // Self Powered, no remote wakeup
181        0x64 // Maximum power consumption 2000 mA
182    },
183    {
184        sizeof(USB_InterfaceDescriptor),
185        INTERFACE_DESCRIPTOR,
186        0x00,
187        0x00,
188        0x02, /* ep number */
189        0xff,
190        0xff,
191        0xff,
192        0x00
193    },
194    {
195        {
196            sizeof(USB_EndPointDescriptor),
197            ENDPOINT_DESCRIPTOR,
198            (1 << 7) | 1,// endpoint 2 is IN endpoint
199            2, /* bulk */
200            512,
201            16
202        },
203        {
204            sizeof(USB_EndPointDescriptor),
205            ENDPOINT_DESCRIPTOR,
206            (0 << 7) | 1,// endpoint 5 is OUT endpoint
207            2, /* bulk */
208            512, /* OUT EP FIFO size */
209            16
210        }
211    }
212};
213
214void sendDevDescString(int size)
215{
216    u16 str_ret[13] = {
217        0x031a,//0x1a=26 byte
218        0x0041,
219        0x0030,
220        0x0030,
221        0x0041,
222        0x0030,
223        0x0030,
224        0x0041,
225        0x0030,
226        0x0030,
227        0x0041,
228        0x0030,
229        0x0030
230    };
231    if(size >= 26)
232        size = 26;
233    str_ret[0] = (0x0300 | size);
234    HW_SendPKT(0, (u8 *)str_ret,size);
235    
236}
237
238void sendDevDesc(int size)
239{
240       switch (size) {
241    case 18:
242        HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc));
243        break;
244    default:
245        HW_SendPKT(0, (u8 *)&devDesc, 8);
246        break;
247    }
248}
249
250void sendConfDesc(int size)
251{
252    switch (size) {
253    case 9:
254        HW_SendPKT(0, (u8 *)&confDesc, 9);
255        break;
256    case 8:
257        HW_SendPKT(0, (u8 *)&confDesc, 8);
258        break;
259    default:
260        HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc));
261        break;
262    }
263}
264
265void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size)
266{
267    confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in;
268    confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size;
269    confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out;
270    confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size;
271}
272
273static void udc_reset(void)
274{
275    u8 byte;
276    ep0state = USB_EP0_IDLE;
277    Bulk_in_size = 0;
278    Bulk_in_finish = 0;
279    Bulk_out_size = 0;
280    udc_state = IDLE;
281    tx_size = 0;
282    rx_size = 0;
283    finished = 0;
284    /* Enable the USB PHY */
285// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
286    /* Disable interrupts */
287    byte=jz_readb(USB_REG_POWER);
288    jz_writew(USB_REG_INTRINE, 0);
289    jz_writew(USB_REG_INTROUTE, 0);
290    jz_writeb(USB_REG_INTRUSBE, 0);
291    jz_writeb(USB_REG_FADDR, 0);
292    jz_writeb(USB_REG_POWER, 0x60); //High speed
293    jz_writeb(USB_REG_INDEX, 0);
294    jz_writeb(USB_REG_CSR0, 0xc0);
295    jz_writeb(USB_REG_INDEX, 1);
296    jz_writew(USB_REG_INMAXP, 512);
297    jz_writew(USB_REG_INCSR, 0x2048);
298    jz_writeb(USB_REG_INDEX, 1);
299    jz_writew(USB_REG_OUTMAXP, 512);
300    jz_writew(USB_REG_OUTCSR, 0x0090);
301    jz_writew(USB_REG_INTRINE, 0x3); //enable intr
302    jz_writew(USB_REG_INTROUTE, 0x2);
303    jz_writeb(USB_REG_INTRUSBE, 0x4);
304
305    byte = jz_readb(USB_REG_POWER);
306    if ((byte&0x10) == 0) {
307        jz_writeb(USB_REG_INDEX, 1);
308        jz_writew(USB_REG_INMAXP, 64);
309        jz_writew(USB_REG_INCSR, 0x2048);
310        jz_writeb(USB_REG_INDEX, 1);
311        jz_writew(USB_REG_OUTMAXP, 64);
312        jz_writew(USB_REG_OUTCSR, 0x0090);
313        USB_Version = USB_FS;
314        fifosize[1] = 64;
315        EP0_init(1, 64, 1, 64);
316    } else {
317        jz_writeb(USB_REG_INDEX, 1);
318        jz_writew(USB_REG_INMAXP, 512);
319        jz_writew(USB_REG_INCSR, 0x2048);
320        jz_writeb(USB_REG_INDEX, 1);
321        jz_writew(USB_REG_OUTMAXP, 512);
322        jz_writew(USB_REG_OUTCSR, 0x0090);
323        USB_Version = USB_HS;
324        fifosize[1] = 512;
325        EP0_init(1, 512, 1, 512);
326    }
327
328}
329
330
331void usbHandleStandDevReq(u8 *buf)
332{
333    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
334    switch (dreq->bRequest) {
335    case GET_DESCRIPTOR:
336        if (dreq->bmRequestType == 0x80) /* Dev2Host */
337            switch(dreq->wValue >> 8) {
338            case DEVICE_DESCRIPTOR:
339                dprintf("get device\n");
340                sendDevDesc(dreq->wLength);
341                break;
342            case CONFIGURATION_DESCRIPTOR:
343                dprintf("get config\n");
344                sendConfDesc(dreq->wLength);
345                break;
346            case STRING_DESCRIPTOR:
347                if (dreq->wLength == 0x02)
348                    HW_SendPKT(0, "\x04\x03", 2);
349                else
350                    sendDevDescString(dreq->wLength);
351                break;
352            }
353        dprintf("\nSet ep0state=TX!");
354        ep0state = USB_EP0_TX;
355        
356        break;
357    case SET_ADDRESS:
358        dprintf("\nSET_ADDRESS!");
359        jz_writeb(USB_REG_FADDR,dreq->wValue);
360        break;
361    case GET_STATUS:
362        switch (dreq->bmRequestType) {
363        case 80: /* device */
364            HW_SendPKT(0, "\x01\x00", 2);
365            break;
366        case 81: /* interface */
367        case 82: /* ep */
368            HW_SendPKT(0, "\x00\x00", 2);
369            break;
370        }
371        ep0state=USB_EP0_TX;
372        break;
373    case CLEAR_FEATURE:
374    case SET_CONFIGURATION:
375    case SET_INTERFACE:
376    case SET_FEATURE:
377        break;
378    }
379}
380
381void usbHandleVendorReq(u8 *buf)
382{
383    int ret_state;
384    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
385    switch (dreq->bRequest) {
386    case VR_GET_CPU_INFO:
387        ret_state = GET_CPU_INFO_Handle();
388        break;
389    case VR_SET_DATA_ADDRESS:
390        ret_state = SET_DATA_ADDERSS_Handle(buf);
391        break;
392    case VR_SET_DATA_LENGTH:
393        ret_state = SET_DATA_LENGTH_Handle(buf);
394        break;
395    case VR_FLUSH_CACHES:
396        ret_state = FLUSH_CACHES_Handle();
397        break;
398    case VR_PROGRAM_START1:
399        ret_state = PROGRAM_START1_Handle(buf);
400        break;
401    case VR_PROGRAM_START2:
402        ret_state = PROGRAM_START2_Handle(buf);
403        break;
404    case VR_NOR_OPS:
405        ret_state = NOR_OPS_Handle(buf);
406        Bulk_out_size = 0;
407        break;
408    case VR_NAND_OPS:
409        NAND_OPS_Handle(buf);
410        Bulk_out_size = 0;
411        break;
412    case VR_CONFIGRATION:
413        ret_state = CONFIGRATION_Handle(buf);
414        handshake_PKT[3] = (u16)ret_state;
415        HW_SendPKT(1, (u8 *)handshake_PKT, sizeof(handshake_PKT));
416        Bulk_out_size = 0;
417        break;
418    case VR_SDRAM_OPS:
419        SDRAM_OPS_Handle(buf);
420        Bulk_out_size = 0;
421        break;
422    case VR_RESET:
423        ret_state = RESET_Handle(buf);
424        break;
425    }
426}
427
428void Handshake_PKT()
429{
430    if (udc_state!=IDLE)
431    {
432        HW_SendPKT(1, (u8 *)handshake_PKT, sizeof(handshake_PKT));
433        udc_state = IDLE;
434        dprintf("\n Send handshake PKT!");
435    }
436}
437
438void usbHandleDevReq(u8 *buf)
439{
440    switch ((buf[0] & (3 << 5)) >> 5) {
441    case 0: /* Standard request */
442        usbHandleStandDevReq(buf);
443        break;
444    case 1: /* Class request */
445        break;
446    case 2: /* Vendor request */
447        usbHandleVendorReq(buf);
448        break;
449    }
450}
451
452void EP0_Handler ()
453{
454    u8 byCSR0;
455
456/* Read CSR0 */
457    jz_writeb(USB_REG_INDEX, 0);
458    byCSR0 = jz_readb(USB_REG_CSR0);
459
460/* Check for SentStall
461 * if sendtall is set ,clear the sendstall bit */
462    if (byCSR0 & USB_CSR0_SENTSTALL) {
463        jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL));
464        ep0state = USB_EP0_IDLE;
465        dprintf("\nSentstall!");
466        return;
467    }
468
469/* Check for SetupEnd */
470    if (byCSR0 & USB_CSR0_SETUPEND) {
471        jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND));
472        ep0state = USB_EP0_IDLE;
473        dprintf("\nSetupend!");
474        return;
475    }
476/* Call relevant routines for endpoint 0 state */
477    if (ep0state == USB_EP0_IDLE) {
478        if (byCSR0 & USB_CSR0_OUTPKTRDY) { //There are datas in fifo
479            USB_DeviceRequest *dreq;
480            fifo = fifoaddr[0];
481            udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest));
482            usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit
483            dreq = (USB_DeviceRequest *)rx_buf;
484            usbHandleDevReq((u8 *)rx_buf);
485        } else
486            dprintf("0:R DATA\n");
487
488        rx_size = 0;
489    }
490    
491    if (ep0state == USB_EP0_TX) {
492        fifo=fifoaddr[0];
493        if (tx_size - finished <= 64) {
494            udcWriteFifo((u8 *)((u32)tx_buf+finished),
495                     tx_size - finished);
496            finished = tx_size;
497            usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
498            usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend!
499            ep0state = USB_EP0_IDLE;
500        } else {
501            udcWriteFifo((u8 *)((u32)tx_buf+finished), 64);
502            usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
503            finished += 64;
504        }
505    }
506    return;
507}
508
509void EPIN_Handler(u8 EP)
510{
511    jz_writeb(USB_REG_INDEX, EP);
512    fifo = fifoaddr[EP];
513
514    if (Bulk_in_size-Bulk_in_finish==0) {
515        Handshake_PKT();
516        return;
517    }
518
519    if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) {
520        udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
521                 Bulk_in_size - Bulk_in_finish);
522        usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
523        Bulk_in_finish = Bulk_in_size;
524    } else {
525        udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
526                fifosize[EP]);
527        usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
528        Bulk_in_finish += fifosize[EP];
529    }
530}
531
532void EPOUT_Handler(u8 EP)
533{
534    u32 size;
535    jz_writeb(USB_REG_INDEX, EP);
536    size = jz_readw(USB_REG_OUTCOUNT);
537    fifo = fifoaddr[EP];
538    udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
539    usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
540    Bulk_out_size += size;
541    dprintf("\nEPOUT_handle return!");
542}
543
544void udc4740Proc ()
545{
546    volatile u8 IntrUSB;
547    volatile u16 IntrIn;
548    volatile u16 IntrOut;
549    /* Read interrupt registers */
550    IntrUSB = jz_readb(USB_REG_INTRUSB);
551    IntrIn = jz_readw(USB_REG_INTRIN);
552    IntrOut = jz_readw(USB_REG_INTROUT);
553        
554    if (IntrUSB == 0 && IntrIn == 0 && IntrOut == 0)
555        return;
556        
557    if (IntrIn & 2) {
558        dprintf("\nUDC EP1 IN operation!");
559        EPIN_Handler(1);
560    }
561
562    if (IntrOut & 2) {
563        dprintf("\nUDC EP1 OUT operation!");
564        EPOUT_Handler(1);
565    }
566
567    if (IntrUSB & USB_INTR_RESET) {
568        dprintf("\nUDC reset intrupt!");
569        udc_reset();
570    }
571        
572    /* Check for endpoint 0 interrupt */
573    if (IntrIn & USB_INTR_EP0) {
574        dprintf("\nUDC EP0 operations!");
575        EP0_Handler();
576    }
577
578    if (USB_Version == USB_FS)
579        IntrIn = jz_readw(USB_REG_INTRIN);
580    return;
581}
582
583void usb_main()
584{
585    u8 byte;
586
587    __dcache_writeback_all();
588    __icache_invalidate_all();
589
590    ep0state = USB_EP0_IDLE;
591    Bulk_in_size = 0;
592    Bulk_in_finish = 0;
593    Bulk_out_size = 0;
594    udc_state = IDLE;
595    tx_size = 0;
596    rx_size = 0;
597    finished = 0;
598
599    byte = jz_readb(USB_REG_POWER);
600    if ((byte&0x10) == 0) {
601        USB_Version = USB_FS;
602        fifosize[1] = 64;
603        EP0_init(1, 64, 1, 64);
604    } else {
605        USB_Version = USB_HS;
606        fifosize[1] = 512;
607        EP0_init(1, 512, 1, 512);
608    }
609
610    serial_puts("\n Init UDC");
611    USB_Version = USB_HS;
612
613    while (1)
614        udc4740Proc();
615}
616

Archive Download this file



interactive