Root/usbboot/xburst_stage2/udc.c

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

Archive Download this file



interactive