From ebabdb43046d5ac115b6b53c8e606e3035c32371 Mon Sep 17 00:00:00 2001 From: Michael Brandt Date: Fri, 30 Oct 2009 13:48:17 +0100 Subject: use beagleboard musb gadget driver merged and adapted beagleboard musb gadget driver to mop500. See also http://elinux.org/U-boot_musb_gadget_support. It was tested with the original Windows 2000 usbser.sys --- drivers/serial/usbtty.h | 2 + drivers/usb/gadget/Makefile | 3 + drivers/usb/gadget/ep0.c | 0 drivers/usb/gadget/musb_udc.c | 813 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/u8500_udc.c | 61 ++++ drivers/usb/gadget/u8500_udc.h | 484 ++++++++++++++++++++++++ include/configs/u8500.h | 33 +- include/usb/musb_udc.h | 119 ++++++ 8 files changed, 1507 insertions(+), 8 deletions(-) mode change 100644 => 100755 drivers/usb/gadget/Makefile mode change 100644 => 100755 drivers/usb/gadget/ep0.c create mode 100755 drivers/usb/gadget/musb_udc.c create mode 100755 drivers/usb/gadget/u8500_udc.c create mode 100755 drivers/usb/gadget/u8500_udc.h create mode 100755 include/usb/musb_udc.h 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 #if defined(CONFIG_PPC) #include +#elif defined(CONFIG_MUSB) +#include #elif defined(CONFIG_OMAP1510) #include #elif defined(CONFIG_PXA27X) diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile old mode 100644 new mode 100755 index 2a19b1e44..0f77319d0 --- 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 old mode 100644 new mode 100755 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 + +#include +// #include +// #include +// #include +#include +#include +#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 +#include "u8500_udc.h" +#include + +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, + * + * 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 +#include + +/* 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__ diff --git a/include/configs/u8500.h b/include/configs/u8500.h index 1a7b44945..b9aa3c835 100755 --- a/include/configs/u8500.h +++ b/include/configs/u8500.h @@ -32,9 +32,10 @@ #define CONFIG_U8500_ED 1 #define CONFIG_L2_OFF 1 -#define PCI_IO_VADDR 0xee000000 +// XXX: nomadik left over? +// #define PCI_IO_VADDR 0xee000000 -#define __io(a) ((void __iomem *)(PCI_IO_VADDR + (a))) +// #define __io(a) ((void __iomem *)(PCI_IO_VADDR + (a))) #define CONFIG_SYS_MEMTEST_START 0x00000000 #define CONFIG_SYS_MEMTEST_END 0x1FFFFFFF @@ -49,7 +50,7 @@ #define CONFIG_MISC_INIT_R 1 /* call misc_init_r during start up */ #define BOARD_LATE_INIT 1 -#define LITTLEENDIAN +#define LITTLEENDIAN /* XXX: obsoleted */ /*----------------------------------------------------------------------- * Size of malloc() pool @@ -100,6 +101,19 @@ #define CONFIG_BOOTARGS "cachepolicy=writealloc root=/dev/ram0 initrd=0x800000,20M init=linuxrc rw console=ttyAMA2,115200n8 mem=256M board_id=0" #define CONFIG_BOOTCOMMAND "emmc_read 0x100000 0x280000 0x200000; bootm 0x100000" +#define CONFIG_EXTRA_ENV_SETTINGS \ + "loadaddr=0x00100000\0" \ + "console=ttyAMA2,115200n8\0" \ + "loadbootscript=fatload mmc 0 ${loadaddr} boot.scr\0" \ + "bootscript=echo Running bootscript from mmc ...; " \ + "source ${loadaddr}\0" \ + "loaduimage=fatload mmc 0 ${loadaddr} uImage\0" \ + "usbtty=cdc_acm\0"\ + "stdout=serial,usbtty\0" \ + "stdin=serial,usbtty\0" \ + "stderr=serial,usbtty\0" + +#define CONFIG_USB_TTY 1 #ifndef CONFIG_USB_TTY #define CONFIG_PREBOOT "mmc init;mmc_read_cmd_file" #endif @@ -171,13 +185,16 @@ * USB related configs */ #define CONFIG_USB_BASE 0xA03E0000 +#define UDC_BASE 0xA03E0000 +#define CONFIG_USB_DEVICE 1 +#define CONFIG_MUSB 1 /* Enable USB driver */ #ifdef CONFIG_USB_TTY -#define CONFIG_ARM -#define CONFIG_USBTTY "cdc_acm" -#define CONFIG_USB_DEVICE -#define CONFIG_SYS_CONSOLE_IS_IN_ENV -#define __LITTLE_ENDIAN 1 +#define CONFIG_USBTTY "cdc_acm" /* XXX: obsoleted */ +/* Allow console in serial and USB at the same time */ +#define CONFIG_CONSOLE_MUX 1 +#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1 +#define __LITTLE_ENDIAN 1 /* XXX: not necessary, handled by buildsystem */ #define CONFIG_SYS_CONSOLE_ENV_OVERWRITE #endif /*----------------------------------------------------------------------- diff --git a/include/usb/musb_udc.h b/include/usb/musb_udc.h new file mode 100755 index 000000000..c1cb99601 --- /dev/null +++ b/include/usb/musb_udc.h @@ -0,0 +1,119 @@ +/* + * (C) Copyright 2009 Texas Instruments Incorporated. + * + * Based on + * u-boot OMAP1510 USB drivers (include/usbdcore_omap1510.h) + * + * Author: Diego Dompe (diego.dompe@ridgerun.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 + */ + +#ifndef __MUSB_UDC_H__ +#define __MUSB_UDC_H__ + +/* USB Function Module Registers */ + +/* + * UDC_BASE is defined for the specific silicon under soc + * specific cpu.h or related header. + */ + +#define UDC_OFFSET(offset) (UDC_BASE+(offset)) + +#define UDC_INTSRCR UDC_OFFSET(0x0A) /* USB Interrupt src reg */ +#define UDC_INTCLRR UDC_OFFSET(0x0A) /* USB Interrupt src clr reg */ + +#define UDC_FADDR UDC_OFFSET(0x00) +#define UDC_POWER UDC_OFFSET(0x01) +#define UDC_INTRTX UDC_OFFSET(0x02) +#define UDC_INTRRX UDC_OFFSET(0x04) +#define UDC_INTRTXE UDC_OFFSET(0x06) /* Enable reg for INTRTX */ +#define UDC_INTRRXE UDC_OFFSET(0x08) /* Enable reg for INTRRX */ +#define UDC_INTRUSB UDC_OFFSET(0x0A) +#define UDC_INTRUSBE UDC_OFFSET(0x0B) +#define UDC_INDEX UDC_OFFSET(0x0E) +#define UDC_TESTMODE UDC_OFFSET(0x0F) +#define UDC_TXMAXP UDC_OFFSET(0x10) +#define UDC_CSR0 UDC_OFFSET(0x12) +#define UDC_TXCSR UDC_OFFSET(0x12) +#define UDC_RXMAXP UDC_OFFSET(0x14) +#define UDC_RXCSR UDC_OFFSET(0x16) +#define UDC_COUNT0 UDC_OFFSET(0x18) +#define UDC_RXCOUNT UDC_OFFSET(0x18) +#define UDC_FIFO0 UDC_OFFSET(0x20) +#define UDC_FIFO1 UDC_OFFSET(0x24) +#define UDC_FIFO2 UDC_OFFSET(0x28) +#define UDC_FIFO3 UDC_OFFSET(0x2C) +#define UDC_FIFO4 UDC_OFFSET(0x30) +#define UDC_FIFO5 UDC_OFFSET(0x34) +#define UDC_FIFO6 UDC_OFFSET(0x38) +#define UDC_FIFO7 UDC_OFFSET(0x3C) +#define UDC_FIFO8 UDC_OFFSET(0x40) +#define UDC_FIFO9 UDC_OFFSET(0x44) +#define UDC_FIFO10 UDC_OFFSET(0x48) +#define UDC_FIFO11 UDC_OFFSET(0x4C) +#define UDC_FIFO12 UDC_OFFSET(0x50) +#define UDC_FIFO13 UDC_OFFSET(0x54) +#define UDC_FIFO14 UDC_OFFSET(0x58) +#define UDC_FIFO15 UDC_OFFSET(0x5C) +#define UDC_DEVCTL UDC_OFFSET(0x60) +#define UDC_TXFIFOSZ UDC_OFFSET(0x62) +#define UDC_RXFIFOSZ UDC_OFFSET(0x63) +#define UDC_TXFIFOADDR UDC_OFFSET(0x64) +#define UDC_RXFIFOADDR UDC_OFFSET(0x66) + +#define UDC_SYSCONFIG UDC_OFFSET(0x404) +#define UDC_INTERFSEL UDC_OFFSET(0x40C) +#define UDC_FORCESTDBY UDC_OFFSET(0x414) + +/* MUSB Endpoint parameters */ +#define EP0_MAX_PACKET_SIZE 64 +#define UDC_OUT_ENDPOINT 2 /* Device RX endpoint */ +#define UDC_OUT_PACKET_SIZE 512 +#define UDC_IN_ENDPOINT 3 /* Device TX endpoint */ +#define UDC_IN_PACKET_SIZE 512 +#define UDC_INT_ENDPOINT 1 /* Device Interrupt/Status endpoint */ +#define UDC_INT_PACKET_SIZE 16 +#define UDC_BULK_PACKET_SIZE 512 + +#define UDC_MAX_FIFO_SIZE 16384 + +#define DEV_CONFIG_VALUE 1 /* Only one i.e. CDC */ + +void udc_irq(void); +/* Flow control */ +void udc_set_nak(int epid); +void udc_unset_nak(int epid); + +/* Higher level functions for abstracting away from specific device */ +int udc_endpoint_write(struct usb_endpoint_instance *endpoint); + +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); + +/* platform specific initialization */ +int udc_musb_platform_init(void); + +#endif /* __MUSB_UDC_H__ */ -- cgit v1.2.3