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

Archive Download this file



interactive