diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-12-04 18:26:19 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-12-04 18:26:19 +0000 |
commit | a119c44c7ec7a383dafbb391f052aaade0b6c981 (patch) | |
tree | 166f1ebc5dad5c132adeca9376ad323023f55a28 /firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |
parent | b2dd3c210e909baec303a94463dc5517acc2780a (diff) | |
download | rockbox-a119c44c7ec7a383dafbb391f052aaade0b6c981.tar.gz rockbox-a119c44c7ec7a383dafbb391f052aaade0b6c981.tar.bz2 rockbox-a119c44c7ec7a383dafbb391f052aaade0b6c981.zip |
Ingenic targets:
* Clean up codec & PCM + functional changes
* LCD: Don't wait on DMAC in lcd_unlock()
* SADC: add battery mutex + other changes
* NAND: add mutex
* USB rework (still not working)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19327 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 1267 |
1 files changed, 182 insertions, 1085 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index f0b4eb4694..83dedfdd48 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -20,7 +20,6 @@ ****************************************************************************/ #include "config.h" -#include "string.h" #include "system.h" #include "usb_ch9.h" #include "usb_drv.h" @@ -29,16 +28,18 @@ #include "jz4740.h" #include "thread.h" -#if 1 +//#define DEBUGF printf +#define DEBUGF -#define EP1_INTR_BIT 2 -#define EP_FIFO_NOEMPTY 2 +#define USB_EP0_IDLE 0 +#define USB_EP0_RX 1 +#define USB_EP0_TX 2 -#define IS_CACHE(x) (x < 0xa0000000) - -#define USB_EP0_IDLE 0 -#define USB_EP0_RX 1 -#define USB_EP0_TX 2 +#define EP_BUF_LEFT(ep) (ep->length - ep->sent) +#define EP_PTR(ep) ((void*)((unsigned int)ep->buf + ep->sent)) +#define EP_NUMBER(ep) (((int)ep - (int)&endpoints[0])/sizeof(struct usb_endpoint)) +#define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) +#define EP_IS_IN(ep) (EP_NUMBER(ep)%2) enum ep_type { @@ -49,27 +50,29 @@ struct usb_endpoint { void *buf; unsigned int length; - void *ptr; + union + { + unsigned int sent; + unsigned int received; + }; const enum ep_type type; const bool use_dma; - const bool in; - const void *fifo_addr; + const unsigned int fifo_addr; unsigned short fifo_size; }; static unsigned char ep0_rx_buf[64]; -static unsigned char ep0_tx_buf[64]; static unsigned char ep0state = USB_EP0_IDLE; static struct usb_endpoint endpoints[] = { - /* buf length ptr type use_dma in fifo_addr fifo_size */ - {&ep0_rx_buf, 0, &ep0_rx_buf, ep_control, false, true, (void*)USB_FIFO_EP0, 64 }, - {&ep0_tx_buf, 0, &ep0_tx_buf, ep_control, false, false, (void*)USB_FIFO_EP0, 64 }, - {NULL, 0, NULL, ep_bulk, true, true, (void*)USB_FIFO_EP1, 512}, - {NULL, 0, NULL, ep_bulk, true, false, (void*)USB_FIFO_EP1, 512}, - {NULL, 0, NULL, ep_interrupt, false, true, (void*)USB_FIFO_EP2, 64 } + /* buf length sent type use_dma fifo_addr fifo_size */ + {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, + {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, + {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, + {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, + {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } }; static inline void select_endpoint(int ep) @@ -78,103 +81,109 @@ static inline void select_endpoint(int ep) } static void readFIFO(struct usb_endpoint *ep, unsigned int size) -{ - unsigned int *d = (unsigned int *)ep->ptr; - unsigned int s; - s = (size + 3) >> 2; - while (s--) - *d++ = REG32(ep->fifo_addr); +{ + DEBUGF("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); + + register unsigned char *ptr = (unsigned char*)EP_PTR(ep); + register unsigned int *ptr32 = (unsigned int*)ptr; + register unsigned int s = size / 4; + register unsigned int x; + + if(size > 0) + { + if( ((int)ptr & 3) == 0 ) + { + while(s--) + *ptr32++ = REG32(ep->fifo_addr); + + ptr = (unsigned char*)ptr32; + } + else + { + while(s--) + { + x = REG32(ep->fifo_addr); + *ptr++ = (x >> 0) & 0xff; + *ptr++ = (x >> 8) & 0xff; + *ptr++ = (x >> 16) & 0xff; + *ptr++ = (x >> 24) & 0xff; + } + } + + s = size & 3; + while(s--) + *ptr++ = REG8(ep->fifo_addr); + } } static void writeFIFO(struct usb_endpoint *ep, unsigned int size) -{ - unsigned int *d = (unsigned int *)ep->ptr; - unsigned char *c; - int s, q; +{ + DEBUGF("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); + + register unsigned int *d = (unsigned int *)EP_PTR(ep); + register unsigned char *c; + register int s; if (size > 0) { s = size >> 2; while (s--) REG32(ep->fifo_addr) = *d++; - - q = size & 3; - if (q) + + if ( (s = size & 3) ) { c = (unsigned char *)d; - while (q--) + while (s--) REG8(ep->fifo_addr) = *c++; } - } -} - -static void sendPKT(int ep_nr, const unsigned char* ptr, unsigned int size) -{ - struct usb_endpoint *ep = &endpoints[ep_nr]; - - if (ep_nr != 0) - { - ep->buf = (void*)ptr; - ep->ptr = (void*)ptr; - ep->length = size; - select_endpoint(ep_nr); - if (size <= ep->fifo_size) - { - writeFIFO(ep, size); - REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; - ep->ptr = ep->buf + size; - } - else - { - writeFIFO(ep, ep->fifo_size); - REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; - ep->ptr += ep->fifo_size; - } - } - else /* EP0 */ - { - ep->length = size; - ep->ptr = ep->buf; - memcpy(ep->buf, ptr, size); - ep0state = USB_EP0_TX; } } -static void getPKT(int ep_nr, const unsigned char *ptr, unsigned int size) +static void EP0_send(void) { - struct usb_endpoint *ep = &endpoints[ep_nr]; + register struct usb_endpoint* ep = &endpoints[1]; + register unsigned int length; - memcpy((void*)ptr, ep->ptr, size); - if (ep->length > size) - ep->length -= size; + if(ep->sent == 0) + length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); else + length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); + + writeFIFO(ep, length); + ep->sent += length; + + if(ep->sent >= ep->length) { - size = ep->length; - ep->length = 0; + REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ + ep0state = USB_EP0_IDLE; } - - ep->ptr += size; + else + REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; } static void EP0_handler(void) { - unsigned char csr0; + register unsigned char csr0; /* Read CSR0 */ select_endpoint(0); csr0 = REG_USB_REG_CSR0; - /* Check for SentStall - if sentstall is set, clear the sentstall bit + /* Check for SentStall: + This bit is set when a STALL handshake is transmitted. The CPU should clear this bit. */ if (csr0 & USB_CSR0_SENTSTALL) { - REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL; + REG_USB_REG_CSR0 &= ~USB_CSR0_SENTSTALL; ep0state = USB_EP0_IDLE; return; } - /* Check for SetupEnd */ + /* Check for SetupEnd: + This bit will be set when a control transaction ends before the DataEnd bit has been set. + An interrupt will be generated and the FIFO flushed at this time. + The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. + */ if (csr0 & USB_CSR0_SETUPEND) { REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; @@ -187,38 +196,21 @@ static void EP0_handler(void) { if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ { - readFIFO(&endpoints[0], 8); - REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTRD bit */ + readFIFO(&endpoints[0], REG_USB_REG_COUNT0); + REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); } - endpoints[0].length = 0; - endpoints[0].ptr = endpoints[0].buf; - } - - if (ep0state == USB_EP0_TX) - { - if ((&endpoints[1].ptr - &endpoints[1].buf) <= endpoints[1].fifo_size) - { - writeFIFO(&endpoints[1], (&endpoints[1].ptr - &endpoints[1].buf)); - endpoints[1].ptr = &endpoints[1].buf + endpoints[1].length; - REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ - ep0state = USB_EP0_IDLE; - } - else - { - writeFIFO(&endpoints[1], endpoints[1].fifo_size); - REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; - endpoints[1].ptr += endpoints[1].fifo_size; - } } + else if (ep0state == USB_EP0_TX) + EP0_send(); } static void setup_endpoint(struct usb_endpoint *ep) { - ep->ptr = ep->buf; + ep->sent = 0; ep->length = 0; - if(ep->in) + if(EP_IS_IN(ep)) { if(ep->type == ep_bulk) { @@ -235,53 +227,66 @@ static void setup_endpoint(struct usb_endpoint *ep) else REG_USB_REG_INMAXP = ep->fifo_size; - REG_USB_REG_INCSR = 0x2048; + REG_USB_REG_INCSR = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); + REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER(ep)); } else { REG_USB_REG_OUTMAXP = ep->fifo_size; - REG_USB_REG_OUTCSR = 0x0090; + REG_USB_REG_OUTCSR = (USB_OUTCSR_FF | USB_OUTCSR_CDT); + REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER(ep)); } } static void udc_reset(void) { - register int i; + DEBUGF("udc_reset"); + + register unsigned int i; /* data init */ ep0state = USB_EP0_IDLE; /* Disable interrupts */ - REG_USB_REG_INTRINE = 0; + REG_USB_REG_INTRINE = 0; REG_USB_REG_INTROUTE = 0; REG_USB_REG_INTRUSBE = 0; + /* Disable DMA */ + REG_USB_REG_CNTL1 = 0; + REG_USB_REG_CNTL2 = 0; + + /* Reset address */ REG_USB_REG_FADDR = 0; - REG_USB_REG_POWER = 0x60; /* High speed */ + //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); /* High speed and softconnect */ + REG_USB_REG_POWER = USB_POWER_SOFTCONN; + /* Enable SUSPEND */ + /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ select_endpoint(0); - REG_USB_REG_CSR0 = 0xC0; + REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); - for(i=1; i<3; i++) + for(i=2; i<TOTAL_EP(); i++) /* Skip EP0 */ { select_endpoint(i); setup_endpoint(&endpoints[i]); } - /* enable intr */ - REG_USB_REG_INTRINE = 0x3; - REG_USB_REG_INTROUTE = 0x2; - REG_USB_REG_INTRUSBE = 0x4; + /* Enable interrupts */ + REG_USB_REG_INTRINE |= USB_INTR_EP0; + REG_USB_REG_INTRUSBE |= USB_INTR_RESET; + + usb_core_bus_reset(); } /* Interrupt handler */ void UDC(void) { /* Read interrupt registers */ - unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */ - unsigned short intrIn = REG_USB_REG_INTRIN; - unsigned short intrOut = REG_USB_REG_INTROUT; - unsigned char intrDMA = REG_USB_REG_INTR; + register unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */ + register unsigned short intrIn = REG_USB_REG_INTRIN; + register unsigned short intrOut = REG_USB_REG_INTROUT; + register unsigned char intrDMA = REG_USB_REG_INTR; if(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0) return; @@ -295,16 +300,20 @@ void UDC(void) if(intrUSB & USB_INTR_RESUME); if(intrDMA & USB_INTR_DMA_BULKIN) { + DEBUGF("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); } if(intrDMA & USB_INTR_DMA_BULKOUT) { + DEBUGF("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); } } bool usb_drv_stalled(int endpoint, bool in) { + DEBUGF("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); + select_endpoint(endpoint); if(endpoint == 0) @@ -320,6 +329,8 @@ bool usb_drv_stalled(int endpoint, bool in) void usb_drv_stall(int endpoint, bool stall, bool in) { + DEBUGF("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); + select_endpoint(endpoint); if(endpoint == 0) @@ -348,23 +359,20 @@ void usb_drv_stall(int endpoint, bool stall, bool in) } } - bool usb_drv_connected(void) { - return __gpio_get_pin(GPIO_UDC_DETE) == 1; + return USB_DRV_CONNECTED(); } int usb_detect(void) { - if(usb_drv_connected()) - return USB_INSERTED; - else - return USB_EXTRACTED; + return usb_drv_connected() ? USB_INSERTED : USB_EXTRACTED; } void usb_init_device(void) { - usb_init_gpio(); + USB_INIT_GPIO(); + system_enable_irq(IRQ_UDC); } void usb_enable(bool on) @@ -387,27 +395,6 @@ void usb_drv_init(void) /* Enable the USB PHY */ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; - - /* Disable interrupts */ - REG_USB_REG_INTRINE = 0; - REG_USB_REG_INTROUTE = 0; - REG_USB_REG_INTRUSBE = 0; - - /* Enable interrupts */ - REG_USB_REG_INTRINE |= USB_INTR_EP0; - REG_USB_REG_INTRUSBE |= USB_INTR_RESET; - - /* Enable SUSPEND */ - /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ - - /* Enable HS Mode */ - REG_USB_REG_POWER |= USB_POWER_HSENAB; - - /* Let host detect UDC: - * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this - * transistor on and pull the USBDP pin HIGH. - */ - REG_USB_REG_POWER |= USB_POWER_SOFTCONN; udc_reset(); } @@ -434,984 +421,94 @@ void usb_drv_exit(void) void usb_drv_set_address(int address) { + DEBUGF("set adr: 0x%x", address); + REG_USB_REG_FADDR = address; } int usb_drv_send(int endpoint, void* ptr, int length) { - return 0; -} - -int usb_drv_recv(int endpoint, void* ptr, int length) -{ - return 0; -} + DEBUGF("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); -void usb_drv_set_test_mode(int mode) -{ - -} - -int usb_drv_port_speed(void) -{ - return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; -} - -void usb_drv_cancel_all_transfers(void) -{ - int i; - for(i=0; i<5; i++) - { - endpoints[i].ptr = endpoints[i].buf; - endpoints[i].length = 0; - } -} - -void usb_drv_release_endpoint(int ep) -{ + if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ + return 0; -} - -#else - -//------------------------------------------ -#ifndef u8 -#define u8 unsigned char -#endif - -#ifndef u16 -#define u16 unsigned short -#endif - -#ifndef u32 -#define u32 unsigned int -#endif - -#ifndef s8 -#define s8 char -#endif - -#ifndef s16 -#define s16 short -#endif - -#ifndef s32 -#define s32 int -#endif - -extern int usbdebug; - -enum USB_ENDPOINT_TYPE -{ - ENDPOINT_TYPE_CONTROL, - /* Typically used to configure a device when attached to the host. - * It may also be used for other device specific purposes, including - * control of other pipes on the device. - */ - ENDPOINT_TYPE_ISOCHRONOUS, - /* Typically used for applications which need guaranteed speed. - * Isochronous transfer is fast but with possible data loss. A typical - * use is audio data which requires a constant data rate. - */ - ENDPOINT_TYPE_BULK, - /* Typically used by devices that generate or consume data in relatively - * large and bursty quantities. Bulk transfer has wide dynamic latitude - * in transmission constraints. It can use all remaining available bandwidth, - * but with no guarantees on bandwidth or latency. Since the USB bus is - * normally not very busy, there is typically 90% or more of the bandwidth - * available for USB transfers. - */ - ENDPOINT_TYPE_INTERRUPT - /* Typically used by devices that need guaranteed quick responses - * (bounded latency). - */ -}; - - -enum USB_STANDARD_REQUEST_CODE { - GET_STATUS, - CLEAR_FEATURE, - SET_FEATURE = 3, - SET_ADDRESS = 5, - GET_DESCRIPTOR, - SET_DESCRIPTOR, - GET_CONFIGURATION, - SET_CONFIGURATION, - GET_INTERFACE, - SET_INTERFACE, - SYNCH_FRAME -}; - - -enum USB_DESCRIPTOR_TYPE { - DEVICE_DESCRIPTOR = 1, - CONFIGURATION_DESCRIPTOR, - STRING_DESCRIPTOR, - INTERFACE_DESCRIPTOR, - ENDPOINT_DESCRIPTOR, - DEVICE_QUALIFIER_DESCRIPTOR, - OTHER_SPEED_CONFIGURATION_DESCRIPTOR, - INTERFACE_POWER1_DESCRIPTOR -}; - - -enum USB_FEATURE_SELECTOR { - ENDPOINT_HALT, - DEVICE_REMOTE_WAKEUP, - TEST_MODE -}; - -enum USB_CLASS_CODE { - CLASS_DEVICE, - CLASS_AUDIO, - CLASS_COMM_AND_CDC_CONTROL, - CLASS_HID, - CLASS_PHYSICAL = 0x05, - CLASS_STILL_IMAGING, - CLASS_PRINTER, - CLASS_MASS_STORAGE, - CLASS_HUB, - CLASS_CDC_DATA, - CLASS_SMART_CARD, - CLASS_CONTENT_SECURITY = 0x0d, - CLASS_VIDEO, - CLASS_DIAGNOSTIC_DEVICE = 0xdc, - CLASS_WIRELESS_CONTROLLER = 0xe0, - CLASS_MISCELLANEOUS = 0xef, - CLASS_APP_SPECIFIC = 0xfe, - CLASS_VENDOR_SPECIFIC = 0xff -}; - - -typedef struct { - u8 bmRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -} __attribute__ ((packed)) USB_DeviceRequest; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 bcdUSB; - u8 bDeviceClass; - u8 bDeviceSubClass; - u8 bDeviceProtocol; - u8 bMaxPacketSize0; - u16 idVendor; - u16 idProduct; - u16 bcdDevice; - u8 iManufacturer; - u8 iProduct; - u8 iSerialNumber; - u8 bNumConfigurations; -} __attribute__ ((packed)) USB_DeviceDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 bcdUSB; - u8 bDeviceClass; - u8 bDeviceSubClass; - u8 bDeviceProtocol; - u8 bMaxPacketSize0; - u8 bNumConfigurations; - u8 bReserved; -} __attribute__ ((packed)) USB_DeviceQualifierDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 wTotalLength; - u8 bNumInterfaces; - u8 bConfigurationValue; - u8 iConfiguration; - u8 bmAttributes; - u8 MaxPower; -} __attribute__ ((packed)) USB_ConfigDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 wTotalLength; - u8 bNumInterfaces; - u8 bConfigurationValue; - u8 iConfiguration; - u8 bmAttributes; - u8 bMaxPower; -} __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u8 bInterfaceNumber; - u8 bAlternateSetting; - u8 bNumEndpoints; - u8 bInterfaceClass; - u8 bInterfaceSubClass; - u8 bInterfaceProtocol; - u8 iInterface; -} __attribute__ ((packed)) USB_InterfaceDescriptor; - - -typedef struct { - u8 bLegth; - u8 bDescriptorType; - u8 bEndpointAddress; - u8 bmAttributes; - u16 wMaxPacketSize; - u8 bInterval; -} __attribute__ ((packed)) USB_EndPointDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 SomeDesriptor[1]; -} __attribute__ ((packed)) USB_StringDescriptor; -//------------------------------------------ -#define MAX_EP0_SIZE 64 -#define MAX_EP1_SIZE 512 - -#define USB_HS 0 -#define USB_FS 1 -#define USB_LS 2 - -//definitions of EP0 -#define USB_EP0_IDLE 0 -#define USB_EP0_RX 1 -#define USB_EP0_TX 2 -/* Define maximum packet size for endpoint 0 */ -#define M_EP0_MAXP 64 -/* Endpoint 0 status structure */ - -static __inline__ void usb_setb(u32 port, u8 val) -{ - volatile u8 *ioport = (volatile u8 *)(port); - *ioport = (*ioport) | val; -} - -static __inline__ void usb_clearb(u32 port, u8 val) -{ - volatile u8 *ioport = (volatile u8 *)(port); - *ioport = (*ioport) & ~val; -} - -static __inline__ void usb_setw(u32 port, u16 val) -{ - volatile u16 *ioport = (volatile u16 *)(port); - *ioport = (*ioport) | val; -} - -static __inline__ void usb_clearw(u32 port, u16 val) -{ - volatile u16 *ioport = (volatile u16 *)(port); - *ioport = (*ioport) & ~val; -} -//--------------------------------- -#define BULK_OUT_BUF_SIZE 0x20000 //buffer size : -#define BULK_IN_BUF_SIZE 0x20000 // too - -enum UDC_STATE -{ - IDLE, - BULK_IN, - BULK_OUT -}; - -enum USB_JZ4740_REQUEST //add for USB_BOOT -{ - VR_GET_CUP_INFO = 0, - VR_SET_DATA_ADDERSS, - VR_SET_DATA_LENGTH, - VR_FLUSH_CACHES, - VR_PROGRAM_START1, - VR_PROGRAM_START2, - VR_NOR_OPS, - VR_NAND_OPS, - VR_SDRAM_OPS, - VR_CONFIGRATION -}; - -enum NOR_OPS_TYPE -{ - NOR_INIT = 0, - NOR_QUERY, - NOR_WRITE, - NOR_ERASE_CHIP, - NOR_ERASE_SECTOR -}; - -enum NOR_FLASH_TYPE -{ - NOR_AM29 = 0, - NOR_SST28, - NOR_SST39x16, - NOR_SST39x8 -}; - -enum NAND_OPS_TYPE -{ - NAND_QUERY = 0, - NAND_INIT, - NAND_MARK_BAD, - NAND_READ_OOB, - NAND_READ_RAW, - NAND_ERASE, - NAND_READ, - NAND_PROGRAM, - NAND_READ_TO_RAM -}; - -enum SDRAM_OPS_TYPE -{ - SDRAM_LOAD, - -}; - -enum DATA_STRUCTURE_OB -{ - DS_flash_info , - DS_hand -}; - - -/*typedef enum _USB_BOOT_STATUS -{ - USB_NO_ERR =0 , - GET_CPU_INFO_ERR, - SET_DATA_ADDRESS_ERR, - SET_DATA_LENGTH_ERR, - FLUSH_CAHCES_ERR, - PROGRAM_START1_ERR, - PROGRAM_START2_ERR, - NOR_OPS_ERR, - NAND_OPS_ERR, - NOR_FLASHTYPE_ERR, - OPS_NOTSUPPORT_ERR -}USB_BOOT_STATUS;*/ - -enum OPTION -{ - OOB_ECC, - OOB_NO_ECC, - NO_OOB, -}; -//------------------------- -static inline void jz_writeb(u32 address, u8 value) -{ - *((volatile u8 *)address) = value; -} - -static inline void jz_writew(u32 address, u16 value) -{ - *((volatile u16 *)address) = value; -} - -static inline void jz_writel(u32 address, u32 value) -{ - *((volatile u32 *)address) = value; -} - -static inline u8 jz_readb(u32 address) -{ - return *((volatile u8 *)address); -} - -static inline u16 jz_readw(u32 address) -{ - return *((volatile u16 *)address); -} - -static inline u32 jz_readl(u32 address) -{ - return *((volatile u32 *)address); -} -//--------------------------- - -#define TXFIFOEP0 USB_FIFO_EP0 - -u8 *Bulk_in_buf; -u32 Bulk_out_buf[BULK_OUT_BUF_SIZE]; -u32 Bulk_in_size,Bulk_in_finish,Bulk_out_size; -u16 handshake_PKT[4]={0,0,0,0}; -u8 udc_state; - -static u32 rx_buf[32]; -static u32 tx_buf[32]; -static u32 tx_size, rx_size, finished,fifo; -static u8 ep0state,USB_Version; - -static u32 fifoaddr[] = -{ - TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8 -}; - -static u32 fifosize[] = { - MAX_EP0_SIZE, MAX_EP1_SIZE -}; - -static void udcReadFifo(u8 *ptr, int size) -{ - u32 *d = (u32 *)ptr; - int s; - s = (size + 3) >> 2; - while (s--) - *d++ = REG32(fifo); -} - -static void udcWriteFifo(u8 *ptr, int size) -{ - u32 *d = (u32 *)ptr; - u8 *c; - int s, q; - - if (size > 0) { - s = size >> 2; - while (s--) - REG32(fifo) = *d++; - q = size & 3; - if (q) { - c = (u8 *)d; - while (q--) - REG8(fifo) = *c++; - } - } -} - -void HW_SendPKT(int ep, const u8 *buf, int size) -{ - fifo = fifoaddr[ep]; - - if (ep!=0) + if(endpoint == EP_CONTROL) { - Bulk_in_size = size; - Bulk_in_finish = 0; - jz_writeb(USB_REG_INDEX, ep); - if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) - { - udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), - Bulk_in_size - Bulk_in_finish); - usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); - Bulk_in_finish = Bulk_in_size; - } - else - { - udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), - fifosize[ep]); - usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); - Bulk_in_finish += fifosize[ep]; - Bulk_in_buf = (u8*)buf; - } - } - else //EP0 - { - tx_size = size; - finished = 0; - memcpy((void *)tx_buf, buf, size); - ep0state = USB_EP0_TX; + endpoints[1].buf = ptr; + endpoints[1].sent = 0; + endpoints[1].length = length; + ep0state = USB_EP0_TX; + EP0_send(); + return 0; } -} - -void HW_GetPKT(int ep, const u8 *buf, unsigned int size) -{ - memcpy((void *)buf, (u8 *)rx_buf, size); - fifo = fifoaddr[ep]; - if (rx_size > size) - rx_size -= size; else - { - size = rx_size; - rx_size = 0; - } - memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size); -} - -void Enable_DMA(u8* buf, u32 length) -{ - dma_cache_wback_inv((u32)buf, length); - jz_writeb(USB_REG_INDEX, 1); - usb_setw(USB_REG_INCSR, 0x9400); - usb_clearw(USB_REG_INTRINE, 0x2); //disable OUT intr - jz_writel(USB_REG_ADDR1, (u32)buf); - jz_writel(USB_REG_COUNT1, length); - jz_writel(USB_REG_CNTL1, 0x001f); -} - -void Disable_DMA(void) -{ - jz_writeb(USB_REG_INDEX, 1); - usb_clearw(USB_REG_INCSR, 0x9400); - usb_setw(USB_REG_INTRINE, 0x2); //Enable OUT intr -} - -static USB_DeviceDescriptor devDesc = -{ - sizeof(USB_DeviceDescriptor), - DEVICE_DESCRIPTOR, //1 - 0x0200, //Version 2.0 - 0xff, //Vendor spec class - 0xff, - 0xff, - 64, /* Ep0 FIFO size */ - 0x601a, //vendor ID - 0xDEAD, //Product ID - 0xffff, - 0x00, - 0x00, - 0x00, - 0x01 -}; - -#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \ - sizeof(USB_InterfaceDescriptor) + \ - sizeof(USB_EndPointDescriptor) * 2) - -static struct { - USB_ConfigDescriptor configuration_descriptor; - USB_InterfaceDescriptor interface_descritor; - USB_EndPointDescriptor endpoint_descriptor[2]; -} __attribute__ ((packed)) confDesc = { - { - sizeof(USB_ConfigDescriptor), - CONFIGURATION_DESCRIPTOR, - CONFIG_DESCRIPTOR_LEN, - 0x01, - 0x01, - 0x00, - 0xc0, // Self Powered, no remote wakeup - 0x64 // Maximum power consumption 2000 mA - }, - { - sizeof(USB_InterfaceDescriptor), - INTERFACE_DESCRIPTOR, - 0x00, - 0x00, - 0x02, /* ep number */ - 0xff, - 0xff, - 0xff, - 0x00 - }, - { - { - sizeof(USB_EndPointDescriptor), - ENDPOINT_DESCRIPTOR, - (1 << 7) | 1,// endpoint 2 is IN endpoint - 2, /* bulk */ - 512, - 0 - }, - { - sizeof(USB_EndPointDescriptor), - ENDPOINT_DESCRIPTOR, - (0 << 7) | 1,// endpoint 5 is OUT endpoint - 2, /* bulk */ - 512, /* OUT EP FIFO size */ - 0 - } - } -}; - -void sendDevDescString(int size) -{ - u16 str_ret[13] = { - 0x031a,//0x1a=26 byte - 0x0041, - 0x0030, - 0x0030, - 0x0041, - 0x0030, - 0x0030, - 0x0041, - 0x0030, - 0x0030, - 0x0041, - 0x0030, - 0x0030 - }; - if(size >= 26) - size = 26; - str_ret[0] = (0x0300 | size); - HW_SendPKT(0, (u8 *)str_ret,size); + return 0; } -void sendDevDesc(int size) -{ - switch (size) { - case 18: - HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc)); - break; - default: - HW_SendPKT(0, (u8 *)&devDesc, 8); - break; - } -} - -void sendConfDesc(int size) +int usb_drv_recv(int endpoint, void* ptr, int length) { - switch (size) { - case 9: - HW_SendPKT(0, (u8 *)&confDesc, 9); - break; - case 8: - HW_SendPKT(0, (u8 *)&confDesc, 8); - break; - default: - HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc)); - break; - } -} + DEBUGF("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); -void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size) -{ - confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in; - confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size; - confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out; - confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size; + if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ + return 0; + + return -1; } -static void udc_reset(void) +void usb_drv_set_test_mode(int mode) { - //data init - ep0state = USB_EP0_IDLE; - Bulk_in_size = 0; - Bulk_in_finish = 0; - Bulk_out_size = 0; - udc_state = IDLE; - tx_size = 0; - rx_size = 0; - finished = 0; - /* Enable the USB PHY */ -// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; - /* Disable interrupts */ - jz_writew(USB_REG_INTRINE, 0); - jz_writew(USB_REG_INTROUTE, 0); - jz_writeb(USB_REG_INTRUSBE, 0); - jz_writeb(USB_REG_FADDR,0); - jz_writeb(USB_REG_POWER,0x60); //High speed - jz_writeb(USB_REG_INDEX,0); - jz_writeb(USB_REG_CSR0,0xc0); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_INMAXP,512); - jz_writew(USB_REG_INCSR,0x2048); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_OUTMAXP,512); - jz_writew(USB_REG_OUTCSR,0x0090); - jz_writew(USB_REG_INTRINE,0x3); //enable intr - jz_writew(USB_REG_INTROUTE,0x2); - jz_writeb(USB_REG_INTRUSBE,0x4); - - if ((jz_readb(USB_REG_POWER)&0x10)==0) - { - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_INMAXP,64); - jz_writew(USB_REG_INCSR,0x2048); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_OUTMAXP,64); - jz_writew(USB_REG_OUTCSR,0x0090); - USB_Version=USB_FS; - fifosize[1]=64; - EP0_init(1,64,1,64); - } - else + switch(mode) { - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_INMAXP,512); - jz_writew(USB_REG_INCSR,0x2048); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_OUTMAXP,512); - jz_writew(USB_REG_OUTCSR,0x0090); - USB_Version=USB_HS; - fifosize[1]=512; - EP0_init(1,512,1,512); - } - -} - -void usbHandleStandDevReq(u8 *buf) -{ - USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; - switch (dreq->bRequest) { - case GET_DESCRIPTOR: - if (dreq->bmRequestType == 0x80) /* Dev2Host */ - switch(dreq->wValue >> 8) - { - case DEVICE_DESCRIPTOR: - sendDevDesc(dreq->wLength); - break; - case CONFIGURATION_DESCRIPTOR: - sendConfDesc(dreq->wLength); - break; - case STRING_DESCRIPTOR: - if (dreq->wLength == 0x02) - HW_SendPKT(0, "\x04\x03", 2); - else - sendDevDescString(dreq->wLength); - //HW_SendPKT(0, "\x04\x03\x09\x04", 2); - break; - } - ep0state=USB_EP0_TX; - - break; - case SET_ADDRESS: - jz_writeb(USB_REG_FADDR,dreq->wValue); - break; - case GET_STATUS: - switch (dreq->bmRequestType) { - case 80: /* device */ - HW_SendPKT(0, "\x01\x00", 2); + case 0: + REG_USB_REG_TESTMODE &= ~USB_TEST_ALL; break; - case 81: /* interface */ - case 82: /* ep */ - HW_SendPKT(0, "\x00\x00", 2); + case 1: + REG_USB_REG_TESTMODE |= USB_TEST_J; break; - } - ep0state=USB_EP0_TX; - break; - case CLEAR_FEATURE: - case SET_CONFIGURATION: - case SET_INTERFACE: - case SET_FEATURE: - break; - } -} - -unsigned char nandbuffer[4096]; -extern void jz_nand_read(int block, int page, unsigned char *buf); - -void usbHandleVendorReq(u8 *buf) -{ - USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; - switch (dreq->bRequest) - { - case 0xB0: - memset(&nandbuffer, 0, 4096); - jz_nand_read(dreq->wValue, dreq->wIndex, nandbuffer); - //printf("Read block %d page %d", dreq->wValue, dreq->wIndex); - udc_state = IDLE; + case 2: + REG_USB_REG_TESTMODE |= USB_TEST_K; break; - case 0xAB: - Enable_DMA(nandbuffer, 4096); - //HW_SendPKT(1, nandbuffer, 4096); - //printf("Send data"); - //udc_state = BULK_OUT; + case 3: + REG_USB_REG_TESTMODE |= USB_TEST_SE0NAK; break; - case 0x12: - HW_SendPKT(0, "TEST", 4); - //printf("Send test"); - udc_state = IDLE; + case 4: + REG_USB_REG_TESTMODE |= USB_TEST_PACKET; break; } } -void Handshake_PKT(void) -{ - if (udc_state!=IDLE) - { - HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT)); - udc_state = IDLE; - } -} - -void usbHandleDevReq(u8 *buf) +int usb_drv_port_speed(void) { - switch ((buf[0] & (3 << 5)) >> 5) { - case 0: /* Standard request */ - usbHandleStandDevReq(buf); - break; - case 1: /* Class request */ - break; - case 2: /* Vendor request */ - usbHandleVendorReq(buf); - break; - } + return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; } -void EP0_Handler (void) +void usb_drv_cancel_all_transfers(void) { - u8 byCSR0; - -/* Read CSR0 */ - jz_writeb(USB_REG_INDEX, 0); - byCSR0 = jz_readb(USB_REG_CSR0); - -/* Check for SentStall - if sendstall is set ,clear the sendstall bit*/ - if (byCSR0 & USB_CSR0_SENTSTALL) - { - jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL)); - ep0state = USB_EP0_IDLE; - return; - } - -/* Check for SetupEnd */ - if (byCSR0 & USB_CSR0_SETUPEND) - { - jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND)); - ep0state = USB_EP0_IDLE; - return; - } -/* Call relevant routines for endpoint 0 state */ - if (ep0state == USB_EP0_IDLE) - { - if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo - { - USB_DeviceRequest *dreq; - fifo=fifoaddr[0]; - udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest)); - usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit - dreq = (USB_DeviceRequest *)rx_buf; - usbHandleDevReq((u8 *)rx_buf); - } - rx_size = 0; - } + DEBUGF("usb_drv_cancel_all_transfers()"); - if (ep0state == USB_EP0_TX) + unsigned int i; + for(i=0; i<TOTAL_EP(); i++) { - fifo=fifoaddr[0]; - if (tx_size - finished <= 64) - { - udcWriteFifo((u8 *)((u32)tx_buf+finished), - tx_size - finished); - finished = tx_size; - usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); - usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend! - ep0state=USB_EP0_IDLE; - } else - { - udcWriteFifo((u8 *)((u32)tx_buf+finished), 64); - usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); - finished += 64; - } - } - return; -} - -void EPIN_Handler(u8 EP) -{ - jz_writeb(USB_REG_INDEX, EP); - fifo = fifoaddr[EP]; - - if (Bulk_in_size-Bulk_in_finish==0) - { - Handshake_PKT(); - return; - } - - if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) - { - udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), - Bulk_in_size - Bulk_in_finish); - usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); - Bulk_in_finish = Bulk_in_size; - } - else - { - udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), - fifosize[EP]); - usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); - Bulk_in_finish += fifosize[EP]; - } -} - -void EPOUT_Handler(u8 EP) -{ - u32 size; - jz_writeb(USB_REG_INDEX, EP); - size = jz_readw(USB_REG_OUTCOUNT); - fifo = fifoaddr[EP]; - udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size); - usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY); - Bulk_out_size += size; -} - -void UDC(void) -{ - u8 IntrUSB; - u16 IntrIn; - u16 IntrOut; - u16 IntrDMA; -/* Read interrupt registers */ - IntrUSB = jz_readb(USB_REG_INTRUSB); - IntrIn = jz_readw(USB_REG_INTRIN); - IntrOut = jz_readw(USB_REG_INTROUT); - IntrDMA = jz_readb(USB_REG_INTR); - - if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0) - return; - - if (IntrIn & 2) - { - EPIN_Handler(1); - } - if (IntrOut & 2) - { - EPOUT_Handler(1); - } - if (IntrUSB & USB_INTR_RESET) - { - udc_reset(); - } - -/* Check for endpoint 0 interrupt */ - if (IntrIn & USB_INTR_EP0) - { - EP0_Handler(); - } - - if (IntrDMA & 0x1) //channel 1 :OUT - { - if (tx_size > 0 && tx_size % fifosize[1] != 0) - { - jz_writeb(USB_REG_INDEX, 1); - usb_clearb(USB_REG_INCSR, USB_INCSR_INPKTRDY); - } - Disable_DMA(); + endpoints[i].sent = 0; + endpoints[i].length = 0; + /* TODO: flush FIFO's ? */ } + + ep0state = USB_EP0_IDLE; } -void __udc_start(void) +void usb_drv_release_endpoint(int ep) { - udc_reset(); + //DEBUGF("usb_drv_release_endpoint(%d)", ep); - ep0state = USB_EP0_IDLE; - Bulk_in_size = 0; - Bulk_in_finish = 0; - Bulk_out_size = 0; - udc_state = IDLE; - tx_size = 0; - rx_size = 0; - finished = 0; - - if ((jz_readb(USB_REG_POWER)&0x10)==0) - { - USB_Version=USB_FS; - fifosize[1]=64; - EP0_init(1,64,1,64); - } - else - { - USB_Version=USB_HS; - fifosize[1]=512; - EP0_init(1,512,1,512); - } - - USB_Version=USB_HS; - system_enable_irq(IRQ_UDC); + (void)ep; } -void usb_init_device(void) +int usb_drv_request_endpoint(int dir) { - REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; - REG_USB_REG_POWER |= USB_POWER_SOFTCONN; - __udc_start(); + DEBUGF("usb_drv_request_endpoint(%d)", dir); + + (void)dir; + return -1; } - -#endif |