summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rwxr-xr-x[-rw-r--r--]drivers/serial/serial_pl01x.c5
-rw-r--r--drivers/serial/usbtty.h2
-rwxr-xr-x[-rw-r--r--]drivers/usb/gadget/Makefile3
-rwxr-xr-x[-rw-r--r--]drivers/usb/gadget/ep0.c0
-rwxr-xr-xdrivers/usb/gadget/musb_udc.c813
-rwxr-xr-xdrivers/usb/gadget/u8500_udc.c61
-rwxr-xr-xdrivers/usb/gadget/u8500_udc.h484
7 files changed, 1368 insertions, 0 deletions
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index c645cef87..839b0a812 100644..100755
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -144,6 +144,11 @@ int serial_init (void)
IO_WRITE (port[CONSOLE_PORT] + UART_PL011_LCRH,
(UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN));
+#ifdef CONFIG_U8500
+ /* program receive line control register */
+ IO_WRITE(port[CONSOLE_PORT] + 0x1C, 0x70);
+#endif
+
/*
** Finally, enable the UART
*/
diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index f746d6317..c693dd5f0 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -27,6 +27,8 @@
#include <usbdevice.h>
#if defined(CONFIG_PPC)
#include <usb/mpc8xx_udc.h>
+#elif defined(CONFIG_MUSB)
+#include <usb/musb_udc.h>
#elif defined(CONFIG_OMAP1510)
#include <usb/omap1510_udc.h>
#elif defined(CONFIG_PXA27X)
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2a19b1e44..0f77319d0 100644..100755
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -32,6 +32,9 @@ COBJS-$(CONFIG_OMAP1510) += omap1510_udc.o
COBJS-$(CONFIG_OMAP1610) += omap1510_udc.o
COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
COBJS-$(CONFIG_PXA27X) += pxa27x_udc.o
+COBJS-$(CONFIG_MUSB) += musb_udc.o
+COBJS-$(CONFIG_TWL4030_USB) += twl4030_usb.o
+COBJS-$(CONFIG_U8500) += u8500_udc.o
endif
COBJS := $(COBJS-y)
diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c
index 2b4ec44e1..2b4ec44e1 100644..100755
--- a/drivers/usb/gadget/ep0.c
+++ b/drivers/usb/gadget/ep0.c
diff --git a/drivers/usb/gadget/musb_udc.c b/drivers/usb/gadget/musb_udc.c
new file mode 100755
index 000000000..a46a6e948
--- /dev/null
+++ b/drivers/usb/gadget/musb_udc.c
@@ -0,0 +1,813 @@
+/*
+ * (C) Copyright 2009 Texas Instruments Incorporated.
+ *
+ * Based on
+ * u-boot OMAP1510 USB drivers (drivers/usbdcore_omap1510.c)
+ * twl4030 init based on linux (drivers/i2c/chips/twl4030_usb.c)
+ *
+ * Author: Diego Dompe (diego.dompe@ridgerun.com)
+ * Atin Malaviya (atin.malaviya@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+// #include <asm/arch/clocks.h>
+// #include <asm/arch/clocks_omap3.h>
+// #include <asm/arch/sys_proto.h>
+#include <usbdevice.h>
+#include <usb/musb_udc.h>
+#include "ep0.h"
+
+/* Private definitions */
+enum ep0_status { IDLE, DATA_STAGE, DATA_COMPLETE };
+
+/* Private variables */
+static struct usb_device_instance *udc_device;
+static enum ep0_status ep0status = IDLE;
+static unsigned char do_set_address = 0;
+static struct urb *ep0_urb = NULL;
+
+/* Helper functions */
+
+/* sr32 from cpu/arm_cortexa8/omap3/syslib.c */
+/*****************************************************************
+ * sr32 - clear & set a value in a bit range for a 32 bit address
+ *****************************************************************/
+static void sr32(void *addr, u32 start_bit, u32 num_bits, u32 value)
+{
+ u32 tmp, msk = 0;
+ msk = 1 << num_bits;
+ --msk;
+ tmp = readl((u32)addr) & ~(msk << start_bit);
+ tmp |= value << start_bit;
+ writel(tmp, (u32)addr);
+}
+
+static void insl(u32 reg, u32 *data, u32 size)
+{
+ u32 t;
+
+ for (t = 0; t < size; t++, data++)
+ *data = inl(reg);
+}
+
+static void outsl(u32 reg, u32 *data, u32 size)
+{
+ u32 t;
+
+ for (t = 0; t < size; t++, data++)
+ outl(*data, reg);
+}
+
+static void outsb(u32 reg, u8 *data, u32 size)
+{
+ u32 t;
+
+ for (t = 0; t < size; t++, data++)
+ outb(*data, reg);
+}
+
+static void musb_fifo_read(int epnumber, u8 *data, u32 size)
+{
+ if ((u32)data & 0x3) { /* Not aligned data */
+ insb((UDC_FIFO0 + (epnumber << 2)), data, size);
+ } else { /* 32 bits aligned data */
+ int i;
+
+ insl(UDC_FIFO0 + (epnumber << 2), (u32 *)data, size >> 2);
+ data += size & ~0x3;
+ i = size & 0x3;
+ while (i--) {
+ *data = inb(UDC_FIFO0 + (epnumber << 2));
+ data++;
+ }
+ }
+}
+
+static void musb_fifo_write(int epnumber, u8 *data, u32 size)
+{
+ if ((u32)data & 0x3) { /* Not aligned data */
+ outsb(UDC_FIFO0 + (epnumber << 2), data, size);
+ } else { /* 32 bits aligned data */
+ int i;
+
+ outsl(UDC_FIFO0 + (epnumber << 2), (u32 *)data, size >> 2);
+ data += size & ~0x3;
+ i = size & 0x3;
+ while (i--) {
+ outb(*data, UDC_FIFO0 + (epnumber << 2));
+ data++;
+ }
+ }
+}
+
+static void musb_fifos_configure(struct usb_device_instance *device)
+{
+ int ep;
+ struct usb_bus_instance *bus;
+ struct usb_endpoint_instance *endpoint;
+ unsigned short ep_ptr, ep_size, ep_doublebuffer;
+ int ep_addr, packet_size, buffer_size, attributes;
+
+ bus = device->bus;
+
+ ep_ptr = 0;
+
+ for (ep = 0; ep < bus->max_endpoints; ep++) {
+ endpoint = bus->endpoint_array + ep;
+ ep_addr = endpoint->endpoint_address;
+ if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+ /* IN endpoint */
+ packet_size = endpoint->tx_packetSize;
+ attributes = endpoint->tx_attributes;
+ } else {
+ /* OUT endpoint */
+ packet_size = endpoint->rcv_packetSize;
+ attributes = endpoint->rcv_attributes;
+ }
+
+ switch (packet_size) {
+ case 0:
+ ep_size = 0;
+ break;
+ case 8:
+ ep_size = 0;
+ break;
+ case 16:
+ ep_size = 1;
+ break;
+ case 32:
+ ep_size = 2;
+ break;
+ case 64:
+ ep_size = 3;
+ break;
+ case 128:
+ ep_size = 4;
+ break;
+ case 256:
+ ep_size = 5;
+ break;
+ case 512:
+ ep_size = 6;
+ break;
+ default:
+ serial_printf("ep 0x%02x has bad packet size %d",
+ ep_addr, packet_size);
+ packet_size = 0;
+ ep_size = 0;
+ break;
+ }
+
+ switch (attributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ default:
+ /* A non-isochronous endpoint may optionally be
+ * double-buffered. For now we disable
+ * double-buffering.
+ */
+ ep_doublebuffer = 0;
+ if (packet_size > 64)
+ packet_size = 0;
+ if (!ep || !ep_doublebuffer)
+ buffer_size = packet_size;
+ else
+ buffer_size = packet_size * 2;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ /* Isochronous endpoints are always double-
+ * buffered
+ */
+ ep_doublebuffer = 1;
+ buffer_size = packet_size * 2;
+ break;
+ }
+
+ /* check to see if our packet buffer RAM is exhausted */
+ if ((ep_ptr + buffer_size) > UDC_MAX_FIFO_SIZE) {
+ serial_printf("out of packet RAM for ep 0x%02x buf size %d",
+ ep_addr, buffer_size);
+ buffer_size = packet_size = 0;
+ }
+
+ /* force a default configuration for endpoint 0 since it is
+ * always enabled
+ */
+ if (!ep && ((packet_size < 8) || (packet_size > 64))) {
+ buffer_size = packet_size = 64;
+ ep_size = 3;
+ }
+
+ outb(ep & 0xF, UDC_INDEX);
+ if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+ /* IN endpoint */
+ outb((ep_doublebuffer << 4) | (ep_size & 0xf),
+ UDC_TXFIFOSZ);
+ outw(ep_ptr >> 3, UDC_TXFIFOADDR);
+ if (!ep) { /* This only apply for ep != 0 */
+ outw(packet_size & 0x3FF, UDC_TXMAXP);
+ }
+ } else {
+ /* OUT endpoint */
+ outb((ep_doublebuffer << 4) | (ep_size & 0xf),
+ UDC_RXFIFOSZ);
+ outw(ep_ptr >> 3, UDC_RXFIFOADDR);
+ if (!ep) { /* This only apply for ep != 0 */
+ outw(packet_size & 0x3FF, UDC_RXMAXP);
+ }
+ }
+ ep_ptr += buffer_size;
+ }
+}
+
+static void musb_ep0_tx(struct usb_endpoint_instance *endpoint)
+{
+ unsigned int size = 0;
+ struct urb *urb = endpoint->tx_urb;
+
+ outb(0, UDC_INDEX);
+
+ if (urb) {
+
+ if ((size =
+ MIN(urb->actual_length - endpoint->sent,
+ endpoint->tx_packetSize))) {
+
+ musb_fifo_write(0, urb->buffer + endpoint->sent, size);
+ }
+ endpoint->last = size;
+
+ if (((endpoint->sent + size) == ep0_urb->device_request.wLength)
+ || (size != endpoint->tx_packetSize)) {
+ ep0status = DATA_COMPLETE;
+ /* Transmit packet and set data end */
+ outw(0xA, UDC_CSR0);
+ } else {
+ outw(0x2, UDC_CSR0); /* Transmit packet */
+ }
+ }
+}
+
+static void musb_ep0_handler(struct usb_endpoint_instance *endpoint)
+{
+ u16 csr0;
+
+ outb(0, UDC_INDEX);
+
+ /* Check errors */
+ csr0 = inw(UDC_CSR0);
+
+ if (csr0 & 0x4) { /* Sent stall */
+ outw(csr0 & ~0x4, UDC_CSR0); /* Clear stall */
+ serial_printf("%s: stall received on EP0!, csr0 %hx\n",
+ __FUNCTION__, csr0);
+ csr0 = inw(UDC_CSR0);
+ serial_printf("state %d -> %d (IDLE), csr0 0x%hx\n",
+ ep0status, IDLE, csr0);
+ ep0status = IDLE;
+ }
+
+ if (csr0 & 0x10) { /* Setup end */
+ outw(0x80, UDC_CSR0); /* Clear setup end */
+ serial_printf("%s: setup END early happened! status is %d\n",
+ __FUNCTION__, ep0status);
+ ep0status = IDLE;
+ return;
+ }
+
+ switch (ep0status) {
+ case DATA_COMPLETE:
+ if (do_set_address) {
+ /*
+ * We need to set the address only after
+ * the status stage is complete
+ */
+ outb(udc_device->address, UDC_FADDR);
+ do_set_address = 0;
+ }
+ ep0status = IDLE;
+ /* Fallthrough */
+ case IDLE: /* Receiving a setup packet */
+ if (csr0 & 0x1) {
+ insl(UDC_FIFO0,
+ (unsigned int *) &ep0_urb->device_request, 2);
+
+ /* If we have data, then don't go to IDLE state */
+ if (ep0_urb->device_request.wLength) {
+ ep0status = DATA_STAGE;
+
+ outw(0x40, UDC_CSR0); /* Clear RXPKTRDY */
+ if ((ep0_urb->device_request.
+ bmRequestType & USB_REQ_DIRECTION_MASK)
+ == USB_REQ_DEVICE2HOST) {
+
+ /* Try to process setup packet */
+ if (ep0_recv_setup(ep0_urb)) {
+ /*
+ * Not a setup packet, stall
+ * next EP0 transaction
+ */
+ outw(0x20, UDC_CSR0);
+ serial_printf("not a setup packed 1, stalling\n");
+ ep0status = IDLE;
+ return;
+ }
+ /*
+ * If we are sending data, do it now, as
+ * ep0_recv_setup should have prepare
+ * them
+ */
+ endpoint->tx_urb = ep0_urb;
+ endpoint->sent = 0;
+
+ musb_ep0_tx(endpoint);
+ } else {
+ endpoint->rcv_urb = ep0_urb;
+ ep0_urb->actual_length = 0;
+ }
+ } else { /* Processing zero-length packet */
+ /*
+ * The www.linux-usb.org/usbtest 'test 14'
+ * fails with error for zero length request.
+ * If the SETUP packet requests ZERO length data
+ * from device-to-host, the TXPKTRDY bit needs
+ * to be set in TXCSR otherwise the STATUS stage
+ * of control transfer will never complete.
+ */
+ if ((ep0_urb->device_request.
+ bmRequestType & USB_REQ_DIRECTION_MASK)
+ == USB_REQ_DEVICE2HOST) {
+ /*
+ * Clear RXPKTRDY and DATAEND and
+ * TXPKTRDY
+ */
+ outw(0x4A, UDC_CSR0);
+ } else {
+ /* Clear RXPKTRDY and DATAEND */
+ outw(0x48, UDC_CSR0);
+ }
+
+ /* Try to process setup packet */
+ if (ep0_recv_setup(ep0_urb)) {
+ /*
+ * Not a setup packet, stall next EP0
+ * transaction
+ */
+ outw(0x20, UDC_CSR0);
+ serial_printf("not a setup packed 2, stalling\n");
+ ep0status = IDLE;
+ return;
+ }
+
+ switch (ep0_urb->device_request.bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ usbd_device_event_irq(udc_device,
+ DEVICE_ADDRESS_ASSIGNED, 0);
+ do_set_address = 1;
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ usbd_device_event_irq(udc_device,
+ DEVICE_CONFIGURED, 0);
+ break;
+ }
+
+ ep0status = DATA_COMPLETE;
+ }
+ }
+ break;
+ case DATA_STAGE:
+ if ((ep0_urb->device_request.
+ bmRequestType & USB_REQ_DIRECTION_MASK)
+ == USB_REQ_DEVICE2HOST) {
+ if (!(csr0 & 0x2)) { /* There packet was send? */
+ endpoint->sent += endpoint->last;
+ /*
+ * If we finished sending data we would not
+ * be on the DATA_STAGE
+ */
+ musb_ep0_tx(endpoint);
+ }
+ } else {
+ /* Receiving data */
+ u16 length = inw(UDC_COUNT0);
+
+ if (length) {
+ if (ep0_urb->actual_length + length >
+ ep0_urb->device_request.wLength)
+ length =
+ ep0_urb->device_request.wLength -
+ ep0_urb->actual_length;
+
+ endpoint->last = length;
+
+ musb_fifo_read(0, &ep0_urb->
+ buffer[ep0_urb->actual_length], length);
+ ep0_urb->actual_length += length;
+ }
+
+ /*
+ * We finish if we received the amount of data expected,
+ * or less of the packet size
+ */
+ if ((ep0_urb->actual_length ==
+ ep0_urb->device_request.wLength) ||
+ (endpoint->last != endpoint->tx_packetSize)) {
+ ep0status = DATA_COMPLETE;
+ /* Clear RXPKTRDY and DATAEND */
+ outw(0x48, UDC_CSR0);
+ /* This will process the incoming data */
+ if (ep0_recv_setup(ep0_urb)) {
+ /*
+ * Not a setup packet, stall next EP0
+ * transaction
+ */
+ outw(0x20, UDC_CSR0);
+ serial_printf("not a setup packed 3, stalling\n");
+ return;
+ }
+ } else
+ outw(0x40, UDC_CSR0); /* Clear RXPKTRDY */
+ }
+ break;
+ }
+}
+
+static void musb_ep_tx(struct usb_endpoint_instance *endpoint)
+{
+ unsigned int size = 0, epnumber =
+ endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+ struct urb *urb = endpoint->tx_urb;
+
+ outb(epnumber, UDC_INDEX);
+ if (urb) {
+ if ((size =
+ MIN(urb->actual_length - endpoint->sent,
+ endpoint->tx_packetSize))) {
+ musb_fifo_write(epnumber, urb->buffer + endpoint->sent,
+ size);
+ }
+ endpoint->last = size;
+ endpoint->state = 1; /* Transmit hardware is busy */
+
+ outw(inw(UDC_TXCSR) | 0x1, UDC_TXCSR); /* Transmit packet */
+ }
+}
+
+
+static void musb_tx_handler(struct usb_endpoint_instance *endpoint)
+{
+ unsigned int epnumber =
+ endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+ u16 txcsr;
+
+ outb(epnumber, UDC_INDEX);
+
+ /* Check errors */
+ txcsr = inw(UDC_TXCSR);
+
+ if (txcsr & 0x4) { /* Clear underrun */
+ txcsr &= ~0x4;
+ }
+ if (txcsr & 0x20) { /* SENTSTALL */
+ outw(txcsr & ~0x20, UDC_TXCSR); /* Clear stall */
+ serial_printf("musb_tx_handler: SENTSTALL, txcsr 0x%hx\n",
+ txcsr);
+ return;
+ }
+
+ if (endpoint->tx_urb && !(txcsr & 0x1)) { /* The packet was send? */
+ if ((endpoint->sent + endpoint->last == endpoint->tx_urb->
+ actual_length) /* Send a zero length packet? */
+ && (endpoint->last == endpoint->tx_packetSize)) {
+ /* Prepare to transmit a zero-length packet. */
+ endpoint->sent += endpoint->last;
+ musb_ep_tx(endpoint);
+ } else if (endpoint->tx_urb->actual_length) {
+ /* retire the data that was just sent */
+ usbd_tx_complete(endpoint);
+ endpoint->state = 0; /* Transmit hardware is free */
+
+ /*
+ * Check to see if we have more data ready to transmit
+ * now.
+ */
+ if (endpoint->tx_urb && endpoint->tx_urb->
+ actual_length) {
+ musb_ep_tx(endpoint);
+ }
+ }
+ }
+}
+
+static void musb_rx_handler(struct usb_endpoint_instance *endpoint)
+{
+ unsigned int epnumber =
+ endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+ u16 rxcsr;
+ u16 length;
+
+ outb(epnumber, UDC_INDEX);
+
+ /* Check errors */
+ rxcsr = inw(UDC_RXCSR);
+
+ if (!(rxcsr & 0x1)) /* There is a package received? */
+ return;
+
+ if (rxcsr & 0x40) { /* SENTSTALL */
+ outw(rxcsr & ~0x40, UDC_RXCSR); /* Clear stall */
+ serial_printf("musb_rx_handler: SENTSTALL, rxcsr 0x%hx\n",
+ rxcsr);
+ return;
+ }
+
+ length = inw(UDC_RXCOUNT);
+
+ if (endpoint->rcv_urb) {
+ /* Receiving data */
+ if (length) {
+ musb_fifo_read(epnumber, &endpoint->rcv_urb->
+ buffer[endpoint->rcv_urb->actual_length],
+ length);
+ outw(rxcsr & ~0x1, UDC_RXCSR); /* Clear RXPKTRDY */
+ usbd_rcv_complete(endpoint, length, 0);
+ }
+ } else {
+ serial_printf("%s: no receive URB!\n", __FUNCTION__);
+ }
+}
+
+static void musb_reset(void)
+{
+ usbd_device_event_irq(udc_device, DEVICE_HUB_CONFIGURED, 0);
+ usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+ ep0status = IDLE;
+ do_set_address = 0;
+}
+
+/* Public functions - called by usbdcore, usbtty, etc. */
+void udc_irq(void)
+{
+ unsigned char int_usb = inb(UDC_INTRUSB);
+ unsigned short int_tx = inw(UDC_INTRTX);
+ unsigned short int_rx = inw(UDC_INTRRX);
+ int ep;
+
+ if (int_usb) {
+ if (int_usb & 0x4) { /* Reset */
+ /* The controller clears FADDR, INDEX, and FIFOs */
+ musb_reset();
+ }
+ if (int_usb & 0x20) { /* Disconnected */
+ usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
+ }
+ if (int_usb & 0x1)
+ usbd_device_event_irq(udc_device,
+ DEVICE_BUS_INACTIVE, 0);
+ if (int_usb & 0x2)
+ usbd_device_event_irq(udc_device,
+ DEVICE_BUS_ACTIVITY, 0);
+ }
+
+ /* Note: IRQ values auto clear so read just before processing */
+ if (int_rx) { /* OUT endpoints */
+ ep = 1;
+ int_rx >>= 1;
+ while (int_rx) {
+ if (int_rx & 1)
+ musb_rx_handler(udc_device->bus->endpoint_array
+ + ep);
+ int_rx >>= 1;
+ ep++;
+ }
+ }
+ if (int_tx) { /* IN endpoints */
+ if (int_tx & 1)
+ musb_ep0_handler(udc_device->bus->endpoint_array);
+
+ ep = 1;
+ int_tx >>= 1;
+ while (int_tx) {
+ if (int_tx & 1)
+ musb_tx_handler(udc_device->bus->endpoint_array
+ + ep);
+ int_tx >>= 1;
+ ep++;
+ }
+ }
+}
+
+/* Turn on the USB connection */
+void udc_connect(void)
+{
+ outb(0x1, UDC_DEVCTL);
+
+ if (!(inb(UDC_DEVCTL) & 0x80)) {
+ serial_printf("Error, the USB hardware is not on B mode\n");
+ outb(0x0, UDC_DEVCTL);
+ return;
+ }
+}
+
+/* Turn off the USB connection */
+void udc_disconnect(void)
+{
+ if (!(inb(UDC_DEVCTL) & 0x80)) {
+ serial_printf("Error, the USB hardware is not on B mode");
+ return;
+ }
+
+ outb(0x0, UDC_DEVCTL);
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+ /* Transmit only if the hardware is available */
+ if (endpoint->tx_urb && endpoint->state == 0)
+ musb_ep_tx(endpoint);
+
+ return 0;
+}
+
+/*
+ * udc_setup_ep - setup endpoint
+ *
+ * Associate a physical endpoint with endpoint_instance
+ */
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
+ struct usb_endpoint_instance *endpoint)
+{
+ int ep_addr;
+ int attributes;
+
+ /*
+ * We dont' have a way to identify if the endpoint definitions changed,
+ * so we have to always reconfigure the FIFOs to avoid problems
+ */
+ musb_fifos_configure(device);
+
+ ep_addr = endpoint->endpoint_address;
+ if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+ /* IN endpoint */
+ attributes = endpoint->tx_attributes;
+ } else {
+ /* OUT endpoint */
+ attributes = endpoint->rcv_attributes;
+ }
+
+ outb(ep & 0xF, UDC_INDEX);
+ if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+ /* IN endpoint */
+ if (!ep) { /* This only apply for ep != 0 */
+ /* Empty fifo twice on case of previous double buffer */
+ outw(1<<3, UDC_TXCSR);
+ outw(1<<3, UDC_TXCSR);
+
+ if (attributes & USB_ENDPOINT_XFER_ISOC)
+ outw(inw(UDC_TXCSR) | (1 << 13) | (1 << 14) |
+ 0x4, UDC_TXCSR);
+ else
+ outw((inw(UDC_TXCSR) | (1 << 13) | 0x4) &
+ ~(1 << 14), UDC_TXCSR);
+ }
+ /* Enable interrupt */
+ outw(inw(UDC_INTRTXE) | (1 << ep), UDC_INTRTXE);
+ } else {
+ /* OUT endpoint */
+ if (!ep) { /* This only apply for ep != 0 */
+ if (attributes & USB_ENDPOINT_XFER_ISOC)
+ outw((inw(UDC_RXCSR) | (1 << 14)) & ~(1 << 13),
+ UDC_RXCSR);
+ else
+ outw(inw(UDC_RXCSR) & ~(1 << 14) & ~(1 << 13),
+ UDC_RXCSR);
+ }
+ /* Enable interrupt */
+ outw(inw(UDC_INTRRXE) | (1 << ep), UDC_INTRRXE);
+ }
+}
+
+/*
+ * udc_startup_events - allow udc code to do any additional startup
+ */
+void udc_startup_events(struct usb_device_instance *device)
+{
+ /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
+ usbd_device_event_irq(device, DEVICE_INIT, 0);
+
+ /*
+ * The DEVICE_CREATE event puts the USB device in the state
+ * STATE_ATTACHED.
+ */
+ usbd_device_event_irq(device, DEVICE_CREATE, 0);
+
+ /*
+ * Some USB controller driver implementations signal
+ * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+ * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
+ * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
+ * The MUSB client controller has the capability to detect when the
+ * USB cable is connected to a powered USB bus, so we will defer the
+ * DEVICE_HUB_CONFIGURED and DEVICE_RESET events until later.
+ */
+
+ /* Save the device structure pointer */
+ udc_device = device;
+
+ /* Setup ep0 urb */
+ if (!ep0_urb) {
+ ep0_urb =
+ usbd_alloc_urb(udc_device, udc_device->bus->
+ endpoint_array);
+ } else {
+ serial_printf("udc_enable: ep0_urb already allocated %p\n", ep0_urb);
+ }
+
+ /* Enable control interrupts */
+ outb(0xf7, UDC_INTRUSBE);
+}
+
+void udc_set_nak(int epid)
+{
+/*
+ * On MUSB the NAKing is controlled by the USB controller buffers,
+ * so as long as we don't read data from the FIFO, the controller will NAK.
+ * Nothing to see here, move along...
+ */
+}
+
+void udc_unset_nak(int epid)
+{
+/*
+ * On MUSB the NAKing is controlled by the USB controller buffers,
+ * so as long as we don't read data from the FIFO, the controller will NAK.
+ * Nothing to see here, move along...
+ */
+}
+
+/* Start to initialize h/w stuff */
+int udc_init(void)
+{
+ /* Clock is initialized on the board code */
+
+#if 0
+ /* XXX: this is platform specific, move to udc_musb_platform_init */
+ /* MUSB soft-reset */
+ outl(2, UDC_SYSCONFIG);
+ /* MUSB end any previous session */
+ outb(0x0, UDC_DEVCTL);
+#endif
+
+ if (udc_musb_platform_init()) {
+ serial_printf("udc_init: platform init failed\n");
+ return -1;
+ }
+
+#if 0
+ /* XXX: this is platform specific, move to udc_musb_platform_init */
+ outl(inl(UDC_FORCESTDBY) & ~1, UDC_FORCESTDBY); /* disable MSTANDBY */
+ outl(inl(UDC_SYSCONFIG) | (2<<12), UDC_SYSCONFIG); /* ena SMARTSTDBY */
+ outl(inl(UDC_SYSCONFIG) & ~1, UDC_SYSCONFIG); /* disable AUTOIDLE */
+ outl(inl(UDC_SYSCONFIG) | (2<<3), UDC_SYSCONFIG); /* enable SMARTIDLE */
+ outl(inl(UDC_SYSCONFIG) | 1, UDC_SYSCONFIG); /* enable AUTOIDLE */
+
+ /* Configure the PHY as PHY interface is 12-pin, 8-bit SDR ULPI */
+ sr32((void *)UDC_INTERFSEL, 0, 1, 1);
+#endif
+
+#if 0
+ /* Turn off interrupts */
+ outw(0x00, UDC_INTRTXE);
+ outw(0x00, UDC_INTRRXE);
+
+#if CONFIG_MUSB_FULL_SPEED
+ /*
+ * Use Full speed for debugging proposes, useful so most USB
+ * analyzers can catch the transactions
+ */
+ outb(0, UDC_POWER);
+ serial_printf("MUSB: using full speed\n");
+#else
+ serial_printf("MUSB: using high speed\n");
+#endif
+#endif
+
+ return 0;
+}
diff --git a/drivers/usb/gadget/u8500_udc.c b/drivers/usb/gadget/u8500_udc.c
new file mode 100755
index 000000000..109e11dda
--- /dev/null
+++ b/drivers/usb/gadget/u8500_udc.c
@@ -0,0 +1,61 @@
+/*
+ * u8500_udc.c -
+ *
+ * (C) Copyright 2009 ST-Ericsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include "u8500_udc.h"
+#include <asm/arch/gpio.h>
+
+static volatile struct mg_dev_register *pRegs = 0;
+
+int udc_musb_platform_init(void)
+{
+ u16 top;
+ u8 power;
+ u8 soft_reset;
+ u16 temp;
+ pRegs = (volatile struct mg_dev_register *) CONFIG_USB_BASE;
+
+ gpio_altfuncenable(GPIO_ALT_USB_OTG, "USB-OTG");
+
+ top = pRegs->OTG_TOPCTRL;
+ pRegs->OTG_TOPCTRL = (top | MODE_ULPI);
+
+ soft_reset = pRegs->OTG_SOFTRST;
+ pRegs->OTG_SOFTRST = (soft_reset | 0x2);
+
+ power = pRegs->OTG_PWR;
+ /* Enabling high speed and soft connection */
+ power = power | POWER_HSENAB;
+ pRegs->OTG_PWR = (power | POWER_SOFTCONN);
+
+ pRegs->OTG_INTUSBEN = 0x0;
+ pRegs->OTG_INTTXEN = 0x0;
+ pRegs->OTG_INTRXEN = 0x0;
+
+ /* off */
+ pRegs->OTG_DEVCTL = 0x0;
+
+ /* flush pending interrupts */
+ temp = pRegs->OTG_INTUSB;
+ temp = pRegs->OTG_INTTX;
+ temp = pRegs->OTG_INTRX;
+ return 0;
+}
diff --git a/drivers/usb/gadget/u8500_udc.h b/drivers/usb/gadget/u8500_udc.h
new file mode 100755
index 000000000..f42c0686a
--- /dev/null
+++ b/drivers/usb/gadget/u8500_udc.h
@@ -0,0 +1,484 @@
+/*
+ * (C) Copyright 2009
+ * STEricsson, <www.stericsson.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __MUSB_UDC_H__
+#define __MUSB_UDC_H__
+
+#include <linux/byteorder/little_endian.h>
+#include <linux/byteorder/generic.h>
+
+/* Endpoint parameters */
+#define EP_MAX_PACKET_SIZE 512
+
+#define EP0_MAX_PACKET_SIZE 64
+#define UDC_OUT_PACKET_SIZE EP_MAX_PACKET_SIZE
+#define UDC_IN_PACKET_SIZE EP_MAX_PACKET_SIZE
+#define UDC_INT_PACKET_SIZE EP_MAX_PACKET_SIZE//64
+#define UDC_BULK_PACKET_SIZE EP_MAX_PACKET_SIZE
+
+
+/* Get offset for a given FIFO */
+#define FIFO_OFFSET(_bEnd) (0x20 + (_bEnd * 4))
+
+/* Endpoint 0 states */
+#define END0_STAGE_SETUP 0x0
+#define END0_STAGE_TX 0x1
+#define END0_STAGE_RX 0x2
+#define END0_STAGE_STATUSIN 0x3
+#define END0_STAGE_STATUSOUT 0x4
+#define END0_STAGE_STALL_BIT 0x10
+
+/* offsets to registers in flat model */
+
+#define HDRC_TXMAXP 0x00
+#define HDRC_TXCSR 0x02
+#define HDRC_CSR0 HDRC_TXCSR /* re-used for EP0 */
+#define HDRC_RXMAXP 0x04
+#define HDRC_RXCSR 0x06
+#define HDRC_RXCOUNT 0x08
+#define HDRC_COUNT0 HDRC_RXCOUNT /* re-used for EP0 */
+#define HDRC_TXTYPE 0x0A
+#define HDRC_TYPE0 HDRC_TXTYPE /* re-used for EP0 */
+#define HDRC_TXINTERVAL 0x0B
+#define HDRC_NAKLIMIT0 HDRC_TXINTERVAL /* re-used for EP0 */
+#define HDRC_RXTYPE 0x0C
+#define HDRC_RXINTERVAL 0x0D
+#define HDRC_INDEX 0x0E
+#define HDRC_FIFOSIZE 0x0F
+#define HDRC_CONFIGDATA HDRC_FIFOSIZE /* re-used for EP0 */
+
+/* INTRUSB */
+#define INTR_SUSPEND 0x01
+#define INTR_RESUME 0x02
+#define INTR_RESET 0x04
+#define INTR_BABBLE 0x04
+#define INTR_SOF 0x08
+#define INTR_CONNECT 0x10
+#define INTR_DISCONNECT 0x20
+#define INTR_SESSREQ 0x40
+#define INTR_VBUSERROR 0x80 /* FOR SESSION END */
+#define INTR_EP0 0x01 /* FOR EP0 INTERRUPT */
+
+/* CONFIGDATA */
+
+#define CONFIGDATA_MPRXE 0x80 /* auto bulk pkt combining */
+#define CONFIGDATA_MPTXE 0x40 /* auto bulk pkt splitting */
+#define CONFIGDATA_BIGENDIAN 0x20
+#define CONFIGDATA_HBRXE 0x10 /* HB-ISO for RX */
+#define CONFIGDATA_HBTXE 0x08 /* HB-ISO for TX */
+#define CONFIGDATA_DYNFIFO 0x04 /* dynamic FIFO sizing */
+#define CONFIGDATA_SOFTCONE 0x02 /* SoftConnect */
+#define CONFIGDATA_UTMIDW 0x01 /* data width 0 => 8bits, 1 => 16bits */
+
+/* DEVCTL */
+#define DEVCTL_BDEVICE 0x80
+#define DEVCTL_FSDEV 0x40
+#define DEVCTL_LSDEV 0x20
+#define DEVCTL_VBUS 0x18
+#define DEVCTL_HM 0x04
+#define DEVCTL_HR 0x02
+#define DEVCTL_SESSION 0x01
+
+/* TXCSR in Peripheral mode */
+
+#define TXCSR_AUTOSET 0x8000
+#define TXCSR_ISO 0x4000
+#define TXCSR_MODE 0x2000
+#define TXCSR_DMAENAB 0x1000
+#define TXCSR_FRCDATATOG 0x0800
+#define TXCSR_DMAMODE 0x0400
+#define TXCSR_CLRDATATOG 0x0040
+#define TXCSR_FLUSHFIFO 0x0008
+#define TXCSR_FIFONOTEMPTY 0x0002
+#define TXCSR_TXPKTRDY 0x0001
+
+#define TXCSR_P_INCOMPTX 0x0080
+#define TXCSR_P_SENTSTALL 0x0020
+#define TXCSR_P_SENDSTALL 0x0010
+#define TXCSR_P_UNDERRUN 0x0004
+
+/* RXCSR in Peripheral */
+
+#define RXCSR_AUTOCLEAR 0x8000
+#define RXCSR_DMAENAB 0x2000
+#define RXCSR_DISNYET 0x1000
+#define RXCSR_DMAMODE 0x0800
+#define RXCSR_INCOMPRX 0x0100
+#define RXCSR_CLRDATATOG 0x0080
+#define RXCSR_FLUSHFIFO 0x0010
+#define RXCSR_DATAERROR 0x0008
+#define RXCSR_FIFOFULL 0x0002
+#define RXCSR_RXPKTRDY 0x0001
+
+
+#define RXCSR_P_ISO 0x4000
+#define RXCSR_P_SENTSTALL 0x0040
+#define RXCSR_P_SENDSTALL 0x0020
+#define RXCSR_P_OVERRUN 0x0004
+
+#define READ8(base_ptr, offset) *((volatile u8*)((unsigned long)base_ptr + offset))
+#define READ16(base_ptr, offset) *((volatile u16*)((unsigned long)base_ptr + offset))
+#define READ32(base_ptr, offset) *((volatile uint32_t*)((unsigned long)base_ptr + offset))
+
+
+#define WRITE8(base_ptr, offset, data) *(volatile u8*)((unsigned long)base_ptr + offset) = data;
+#define WRITE16(base_ptr, offset, data) *(volatile u16*)((unsigned long)base_ptr + offset) = data;
+#define WRITE32(base_ptr, offset, data) *(volatile uint32_t*)((unsigned long)base_ptr + offset) = data;
+
+#define SELECTEND(base_ptr, end) WRITE8(base_ptr, HDRC_INDEX, end)
+#define READCSR8(base_ptr, offset, end) READ8(base_ptr, (offset + 0x10))
+#define READCSR16(base_ptr, offset, end) READ16(base_ptr, (offset + 0x10))
+#define WRITECSR8(base_ptr, offset, end, data) WRITE8(base_ptr, (offset + 0x10), data)
+#define WRITECSR16(base_ptr, offset, end, data) WRITE16(base_ptr, (offset + 0x10), data)
+
+#define MODE_ULPI 0x01
+#define POWER_HSENAB 0x20
+#define POWER_SOFTCONN 0x40
+
+/*EP0 related macros */
+/* CSR0 in Peripheral mode */
+#define CSR0_P_SVDSETUPEND 0x0080
+#define CSR0_P_SVDRXPKTRDY 0x0040
+#define CSR0_P_SENDSTALL 0x0020
+#define CSR0_P_SETUPEND 0x0010
+#define CSR0_P_DATAEND 0x0008
+#define CSR0_P_SENTSTALL 0x0004
+#define CSR0_FLUSHFIFO 0x0100
+#define CSR0_TXPKTRDY 0x0002
+#define CSR0_RXPKTRDY 0x0001
+
+
+#define EP_ACTIVE 0
+#define EP_HALTED 1
+#define EP_DISABLED 2
+
+/* TESTMODE */
+
+#define TEST_FORCE_HOST 0x80
+#define TEST_FIFO_ACCESS 0x40
+#define TEST_FORCE_FS 0x20
+#define TEST_FORCE_HS 0x10
+#define TEST_PACKET 0x08
+#define TEST_K 0x04
+#define TEST_J 0x02
+#define TEST_SE0_NAK 0x01
+
+struct endpoint_control {
+ __u8 OTG_TX0FAD;
+ __u8 FILL4;
+ __u8 OTG_TX0HAD;
+ __u8 OTG_TX0HP;
+ __u8 OTG_RX0FAD;
+ __u8 FILL5;
+ __u8 OTG_RX0HAD;
+ __u8 OTG_RX0HP;
+};
+struct mg_dev_register
+{
+ __u8 OTG_FADDR;
+ __u8 OTG_PWR;
+ __u16 OTG_INTTX;
+ __u16 OTG_INTRX;
+ __u16 OTG_INTTXEN;
+ __u16 OTG_INTRXEN;
+ __u8 OTG_INTUSB;
+ __u8 OTG_INTUSBEN;
+ __u16 OTG_FMNO;
+ __u8 OTG_INDX;
+ __u8 OTG_TM;
+ __u16 OTG_TXMAXP;
+ __u16 OTG_CSR0_TXCSR;
+ __u16 OTG_RXMAXP;
+ __u16 OTG_RXCSR;
+ __u16 OTG_CNT0_RXCNT;
+ __u8 OTG_TYPE0_TXTYPE;
+ __u8 OTG_NAKLMT0_TXINTV;
+ __u8 OTG_RXTYPE;
+ __u8 OTG_RXINTV;
+ __u8 FILL0;
+ __u8 OTG_CFD_FSIZE;
+
+ /* FIFO registers */
+ __u32 OTG_FIFO[16];
+ __u8 OTG_DEVCTL;
+ __u8 FILL1;
+ __u8 OTG_TXFSZ;
+ __u8 OTG_RXFSZ;
+ __u16 OTG_TXFA;
+ __u16 OTG_RXFA;
+ __u32 OTG_VCNTL;
+ __u16 OTG_HWVER;
+ __u16 FILL2;
+ __u8 OTG_UVBCTRL;
+ __u8 OTG_UCKIT;
+ __u8 OTG_UINTMASK;
+ __u8 OTG_UINTSRC;
+ __u8 OTG_UREGDATA;
+ __u8 OTG_UREGADDR;
+ __u8 OTG_UREGCTRL;
+ __u8 OTG_URAWDATA;
+ __u8 OTG_EPINFO;
+ __u8 OTG_RAMINFO;
+ __u8 OTG_LINKINFO;
+ __u8 OTG_VPLEN;
+ __u8 OTG_HSEOF1;
+ __u8 OTG_FSEOF1;
+ __u8 OTG_LSEOF1;
+ __u8 OTG_SOFTRST;
+
+ /* Target Endpoint control registers */
+ struct endpoint_control endp_control[16];
+ /* Control Status register for Endpoint 0 */
+ __u16 OTG_TX0MAXP;
+ __u16 OTG_CSR0;
+ __u16 OTG_RX0MAXP;
+ __u16 OTG_RX0CSR;
+ __u16 OTG_CNT0;
+ __u8 OTG_TYPE0;
+ __u8 OTG_NAKLMT0;
+ __u8 OTG_RX0TYPE;
+ __u8 OTG_RX0INTV;
+ __u8 FILL36;
+ __u8 OTG_CFD;
+
+ /* Control Status register for Endpoint 1 */
+ __u16 OTG_TX1MAXP;
+ __u16 OTG_TX1CSR;
+ __u16 OTG_RX1MAXP;
+ __u16 OTG_RX1CSR;
+ __u16 OTG_RX1CNT;
+ __u8 OTG_TX1TYPE;
+ __u8 OTG_TX1INTV;
+ __u8 OTG_RX1TYPE;
+ __u8 OTG_RX1INTV;
+ __u8 FILL37;
+ __u8 OTG_FSIZE1;
+
+ /* Control Status register for Endpoint 2 */
+ __u16 OTG_TX2MAXP;
+ __u16 OTG_TX2CSR;
+ __u16 OTG_RX2MAXP;
+ __u16 OTG_RX2CSR;
+ __u16 OTG_RX2CNT;
+ __u8 OTG_TX2TYPE;
+ __u8 OTG_TX2INTV;
+ __u8 OTG_RX2TYPE;
+ __u8 OTG_RX2INTV;
+ __u8 FILL38;
+ __u8 OTG_FSIZE2;
+
+ /* Control Status register for Endpoint 3 */
+ __u16 OTG_TX3MAXP;
+ __u16 OTG_TX3CSR;
+ __u16 OTG_RX3MAXP;
+ __u16 OTG_RX3CSR;
+ __u16 OTG_RX3CNT;
+ __u8 OTG_TX3TYPE;
+ __u8 OTG_TX3INTV;
+ __u8 OTG_RX3TYPE;
+ __u8 OTG_RX3INTV;
+ __u8 FILL39;
+ __u8 OTG_FSIZE3;
+
+ /* Control Status register for Endpoint 4 */
+ __u16 OTG_TX4MAXP;
+ __u16 OTG_TX4CSR;
+ __u16 OTG_RX4MAXP;
+ __u16 OTG_RX4CSR;
+ __u16 OTG_RX4CNT;
+ __u8 OTG_TX4TYPE;
+ __u8 OTG_TX4INTV;
+ __u8 OTG_RX4TYPE;
+ __u8 OTG_RX4INTV;
+ __u8 FILL40;
+ __u8 OTG_FSIZE4;
+
+ /* Control Status register for Endpoint 5 */
+ __u16 OTG_TX5MAXP;
+ __u16 OTG_TX5CSR;
+ __u16 OTG_RX5MAXP;
+ __u16 OTG_RX5CSR;
+ __u16 OTG_RX5CNT;
+ __u8 OTG_TX5TYPE;
+ __u8 OTG_TX5INTV;
+ __u8 OTG_RX5TYPE;
+ __u8 OTG_RX5INTV;
+ __u8 FILL41;
+ __u8 OTG_FSIZE5;
+
+ /* Control Status register for Endpoint 6 */
+ __u16 OTG_TX6MAXP;
+ __u16 OTG_TX6CSR;
+ __u16 OTG_RX6MAXP;
+ __u16 OTG_RX6CSR;
+ __u16 OTG_RX6CNT;
+ __u8 OTG_TX6TYPE;
+ __u8 OTG_TX6INTV;
+ __u8 OTG_RX6TYPE;
+ __u8 OTG_RX6INTV;
+ __u8 FILL42;
+ __u8 OTG_FSIZE6;
+
+ /* Control Status register for Endpoint 7 */
+ __u16 OTG_TX7MAXP;
+ __u16 OTG_TX7CSR;
+ __u16 OTG_RX7MAXP;
+ __u16 OTG_RX7CSR;
+ __u16 OTG_RX7CNT;
+ __u8 OTG_TX7TYPE;
+ __u8 OTG_TX7INTV;
+ __u8 OTG_RX7TYPE;
+ __u8 OTG_RX7INTV;
+ __u8 FILL43;
+ __u8 OTG_FSIZE7;
+
+ /* Control Status register for Endpoint 8 */
+ __u16 OTG_TX8MAXP;
+ __u16 OTG_TX8CSR;
+ __u16 OTG_RX8MAXP;
+ __u16 OTG_RX8CSR;
+ __u16 OTG_RX8CNT;
+ __u8 OTG_TX8TYPE;
+ __u8 OTG_TX8INTV;
+ __u8 OTG_RX8TYPE;
+ __u8 OTG_RX8INTV;
+ __u8 FILL44;
+ __u8 OTG_FSIZE8;
+
+ /* Control Status register for Endpoint 9 */
+ __u16 OTG_TX9MAXP;
+ __u16 OTG_TX9CSR;
+ __u16 OTG_RX9MAXP;
+ __u16 OTG_RX9CSR;
+ __u16 OTG_RX9CNT;
+ __u8 OTG_TX9TYPE;
+ __u8 OTG_TX9INTV;
+ __u8 OTG_RX9TYPE;
+ __u8 OTG_RX9INTV;
+ __u8 FILL45;
+ __u8 OTG_FSIZE9;
+
+ /* Control Status register for Endpoint 10 */
+ __u16 OTG_TX10MAXP;
+ __u16 OTG_TX10CSR;
+ __u16 OTG_RX10MAXP;
+ __u16 OTG_RX10CSR;
+ __u16 OTG_RX10CNT;
+ __u8 OTG_TX10TYPE;
+ __u8 OTG_TX10INTV;
+ __u8 OTG_RX10TYPE;
+ __u8 OTG_RX10INTV;
+ __u8 FILL46;
+ __u8 OTG_FSIZE10;
+
+ /* Control Status register for Endpoint 11 */
+ __u16 OTG_TX11MAXP;
+ __u16 OTG_TX11CSR;
+ __u16 OTG_RX11MAXP;
+ __u16 OTG_RX11CSR;
+ __u16 OTG_RX11CNT;
+ __u8 OTG_TX11TYPE;
+ __u8 OTG_TX11INTV;
+ __u8 OTG_RX11TYPE;
+ __u8 OTG_RX11INTV;
+ __u8 FILL47;
+ __u8 OTG_FSIZE11;
+
+ /* Control Status register for Endpoint 12 */
+ __u16 OTG_TX12MAXP;
+ __u16 OTG_TX12CSR;
+ __u16 OTG_RX12MAXP;
+ __u16 OTG_RX12CSR;
+ __u16 OTG_RX12CNT;
+ __u8 OTG_TX12TYPE;
+ __u8 OTG_TX12INTV;
+ __u8 OTG_RX12TYPE;
+ __u8 OTG_RX12INTV;
+ __u8 FILL48;
+ __u8 OTG_FSIZE12;
+
+ /* Control Status register for Endpoint 13 */
+ __u16 OTG_TX13MAXP;
+ __u16 OTG_TX13CSR;
+ __u16 OTG_RX13MAXP;
+ __u16 OTG_RX13CSR;
+ __u16 OTG_RX13CNT;
+ __u8 OTG_TX13TYPE;
+ __u8 OTG_TX13INTV;
+ __u8 OTG_RX13TYPE;
+ __u8 OTG_RX13INTV;
+ __u8 FILL49;
+ __u8 OTG_FSIZE13;
+
+ /* Control Status register for Endpoint 14 */
+ __u16 OTG_TX14MAXP;
+ __u16 OTG_TX14CSR;
+ __u16 OTG_RX14MAXP;
+ __u16 OTG_RX14CSR;
+ __u16 OTG_RX14CNT;
+ __u8 OTG_TX14TYPE;
+ __u8 OTG_TX14INTV;
+ __u8 OTG_RX14TYPE;
+ __u8 OTG_RX14INTV;
+ __u8 FILL50;
+ __u8 OTG_FSIZE14;
+
+ /* Control Status register for Endpoint 15 */
+ __u16 OTG_TX15MAXP;
+ __u16 OTG_TX15CSR;
+ __u16 OTG_RX15MAXP;
+ __u16 OTG_RX15CSR;
+ __u16 OTG_RX15CNT;
+ __u8 OTG_TX15TYPE;
+ __u8 OTG_TX15INTV;
+ __u8 OTG_RX15TYPE;
+ __u8 OTG_RX15INTV;
+ __u8 FILL51;
+ __u8 OTG_FSIZE15;
+
+ __u32 OTG_DMASEL;
+ __u8 OTG_TOPCTRL;
+};
+
+struct udc_end0_buffer {
+ u8 data[EP0_MAX_PACKET_SIZE];
+ u16 count;
+};
+/* Higher level functions for abstracting away from specific device */
+int udc_init (void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep, struct usb_endpoint_instance *endpoint);
+
+void udc_irq (void);
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak (int epid);
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+#endif //__MUSB_UDC_H__