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

Archive Download this file



interactive