[U-Boot] [PATCH] USB:gadget:designware USB OTG implementation

Marek Vasut marex at denx.de
Wed Mar 7 13:42:06 CET 2012


Dear Amit Virdi,

> From: Pratyush Anand <pratyush.anand at st.com>
> 
> Driver for designware otg device only implements device functionality
> and is meant to be used with usbtty interface.
> This driver will work mainly for Control and Bulk endpoints. Periodic
> transfer has not been verified using these drivers.
> 
> Signed-off-by: Pratyush Anand <pratyush.anand at st.com>
> Signed-off-by: Amit Virdi <amit.virdi at st.com>
> ---
>  drivers/serial/usbtty.h             |    2 +
>  drivers/usb/gadget/Makefile         |    1 +
>  drivers/usb/gadget/designware_otg.c | 1064
> +++++++++++++++++++++++++++++++++++ include/usb/designware_otg.h        | 
> 527 +++++++++++++++++
>  4 files changed, 1594 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/usb/gadget/designware_otg.c
>  create mode 100644 include/usb/designware_otg.h
> 
> diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
> index 60347d7..6731c38 100644
> --- a/drivers/serial/usbtty.h
> +++ b/drivers/serial/usbtty.h
> @@ -35,6 +35,8 @@
>  #include <usb/pxa27x_udc.h>
>  #elif defined(CONFIG_DW_UDC)
>  #include <usb/designware_udc.h>
> +#elif defined(CONFIG_DW_OTG)
> +#include <usb/designware_otg.h>
>  #endif
> 
>  #include <version.h>
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 87d1918..ede367e 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -40,6 +40,7 @@ ifdef CONFIG_USB_DEVICE
>  COBJS-y += core.o
>  COBJS-y += ep0.o
>  COBJS-$(CONFIG_DW_UDC) += designware_udc.o
> +COBJS-$(CONFIG_DW_OTG) += designware_otg.o
>  COBJS-$(CONFIG_OMAP1510) += omap1510_udc.o
>  COBJS-$(CONFIG_OMAP1610) += omap1510_udc.o
>  COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
> diff --git a/drivers/usb/gadget/designware_otg.c
> b/drivers/usb/gadget/designware_otg.c new file mode 100644
> index 0000000..b5dd898
> --- /dev/null
> +++ b/drivers/usb/gadget/designware_otg.c
> @@ -0,0 +1,1064 @@
> +/*
> + * Based on drivers/usb/gadget/designware_otg.c
> + * Synopsys DW OTG Device bus interface driver
> + *
> + * (C) Copyright 2011
> + * Pratyush Anand, ST Micoelectronics, pratyush.anand at st.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
> + */
> +/* temp def: will be removed TBD*/

temp remove ;-)

> +#undef APG_BOARD	1
> +
> +#ifndef APG_BOARD

dead code?

> +#include <common.h>
> +#include <asm/io.h>
> +#include <usbdevice.h>
> +#include "ep0.h"
> +#include <usb/designware_otg.h>
> +#include <asm/arch/hardware.h>
> +#else
> +#include "types.h"
> +#include <designware_otg.h>
> +#include <usbdevice.h>
> +#endif
> +
> +#define UDC_INIT_MDELAY		80	/* Device settle delay */
> +
> +/* Some kind of debugging output... */
> +#ifndef DEBUG_DWUSBTTY
> +#define UDCDBG(str)
> +#define UDCDBGA(fmt, args...)
> +#else
> +#define UDCDBG(str) serial_printf(str "\n")
> +#define UDCDBGA(fmt, args...) serial_printf(fmt "\n", ##args)
> +#endif

debug()

> +
> +static struct urb *ep0_urb;
> +static struct usb_device_instance *udc_device;
> +
> +static struct device_if	device_if_mem;
> +static struct device_if	*dev_if = &device_if_mem;
> +#if defined(CONFIG_USBD_HS)
> +#define CONFIG_USBD_SERIAL_BULK_PKTSIZE	UDC_BULK_HS_PACKET_SIZE
> +#endif
> +
> +static struct usb_endpoint_instance *dw_find_ep(int ep)
> +{
> +	int i;
> +
> +	for (i = 0; i < udc_device->bus->max_endpoints; i++) {
> +		if ((udc_device->bus->endpoint_array[i].endpoint_address &
> +					USB_ENDPOINT_NUMBER_MASK) == ep)
> +			return &udc_device->bus->endpoint_array[i];
> +	}
> +	return NULL;
> +}
> +
> +/*
> + * This function reads a packet from the Rx FIFO into the destination
> buffer. + * To read SETUP data use dwc_otg_read_setup_packet.
> + */
> +void dwc_otg_read_packet(struct dwc_ep *ep, u16 _bytes)
> +{
> +	u32 i;
> +	int word_count = (_bytes + 3) / 4;
> +	u32 *fifo = dev_if->data_fifo[0];
> +	u32 *data_buff = (u32 *) ep->xfer_buff;
> +	u32 unaligned;
> +	/*
> +	 * This requires reading data from the FIFO into a u32 temp buffer,
> +	 * then moving it into the data buffer.
> +	 */
> +	if ((_bytes < 4) && (_bytes > 0)) {

rename _bytes to bytes, fix globally

> +		unaligned = readl(fifo);
> +		memcpy(data_buff, &unaligned, _bytes);
> +	} else {
> +		for (i = 0; i < word_count; i++, data_buff++)
> +			*data_buff = readl(fifo);
> +	}
> +}
> +
> +/* Handle RX transaction on non-ISO endpoint. */
> +static void dw_udc_epn_rx(struct dwc_ep *ep, int bcnt)
> +{
> +	struct urb *urb;
> +	struct usb_endpoint_instance *endpoint = dw_find_ep(ep->num);
> +
> +	if (endpoint) {
> +		urb = endpoint->rcv_urb;
> +
> +		if (urb) {
> +			ep->xfer_buff = urb->buffer + urb->actual_length;
> +			dwc_otg_read_packet(ep, bcnt);
> +			usbd_rcv_complete(endpoint, bcnt, 0);
> +		}
> +	}
> +}
> +
> +/*
> + * This function writes a packet into the Tx FIFO associated with the EP.
> + * The buffer is padded to DWORD on a per packet basis in
> + * slave/dma mode if the MPS is not DWORD aligned. The last packet, if
> + * short, is also padded to a multiple of DWORD.
> + *
> + * ep->xfer_buff always starts DWORD aligned in memory and is a
> + * multiple of DWORD in length
> + *
> + * ep->xfer_len can be any number of bytes
> + *
> + * FIFO access is DWORD
> + */
> +static void dwc_otg_ep_write_packet(struct dwc_ep *ep)
> +{
> +	u32 i;
> +	u32 dword_count;
> +	u32 *fifo;
> +	u32 *data_buff = (u32 *) ep->xfer_buff;
> +	u32 temp, unaligned;
> +	struct device_in_ep_regs *in_ep_regs = dev_if->in_ep_regs[ep->num];
> +	struct core_global_regs *core_global_regs = dev_if->core_global_regs;
> +
> +	/*
> +	 * Find the DWORD length, padded by extra bytes as neccessary if MPS
> +	 * is not a multiple of DWORD
> +	 */
> +	dword_count = (ep->xfer_len + 3) / 4;
> +	fifo = dev_if->data_fifo[ep->num];
> +
> +	/* program pkt count */
> +	temp = ep->xfer_len;
> +	temp |= (1 << PKTCNT_SHIFT);
> +	writel(temp, &in_ep_regs->dieptsiz);
> +
> +	/* enable EP*/
> +	temp = readl(&in_ep_regs->diepctl);
> +	temp |= (EPENA | CNAK);
> +	writel(temp, &in_ep_regs->diepctl);
> +
> +	/* clear TX Fifo Empty intr*/
> +	writel(NPTXFEMPTY, &core_global_regs->gintsts);
> +
> +	temp = readl(&core_global_regs->gintmsk);
> +	temp |= NPTXFEMPTY;
> +	writel(temp, &core_global_regs->gintmsk);
> +
> +	while (!(readl(&core_global_regs->gintsts) & NPTXFEMPTY))
> +		;

No endless loops please

> +
> +	/* write to fifo */
> +	if ((ep->xfer_len < 4) && (ep->xfer_len > 0)) {
> +		memcpy(&unaligned, data_buff, ep->xfer_len);
> +		*fifo = unaligned;
> +	} else {
> +		for (i = 0; i < dword_count; i++, data_buff++)
> +			*fifo = *data_buff;
> +	}
> +
> +	writel(NPTXFEMPTY, &core_global_regs->gintsts);
> +
> +	/* check for transfer completion*/
> +	while (!(readl(&in_ep_regs->diepint) & XFERCOMPL))
> +		;

dtto

> +
> +	writel(XFERCOMPL, &in_ep_regs->diepint);
> +
> +	temp = readl(&core_global_regs->gintmsk);
> +	temp &= ~NPTXFEMPTY;
> +	writel(temp, &core_global_regs->gintmsk);

Use clrsetbits_le32() and friends in cases like that

> +}
> +
> +/* Handle TX transaction on non-ISO endpoint. */
> +static void dw_udc_epn_tx(struct dwc_ep *ep)
> +{
> +	struct usb_endpoint_instance *endpoint = dw_find_ep(ep->num);
> +	struct urb *urb = endpoint->tx_urb;
> +	int align;
> +
> +	if (!endpoint)
> +		return;
> +
> +	/*
> +	 * We need to transmit a terminating zero-length packet now if
> +	 * we have sent all of the data in this URB and the transfer
> +	 * size was an exact multiple of the packet size.
> +	 */
> +	if (urb && (endpoint->last == endpoint->tx_packetSize) &&
> +			(urb->actual_length - endpoint->sent -
> +			 endpoint->last == 0)) {
> +		/* handle zero length packet here */
> +		ep->xfer_len = 0;
> +		dwc_otg_ep_write_packet(ep);
> +	}
> +
> +	if (urb && urb->actual_length) {
> +		/* retire the data that was just sent */
> +		usbd_tx_complete(endpoint);
> +		/*
> +		 * Check to see if we have more data ready to transmit
> +		 * now.
> +		 */
> +		if (urb && urb->actual_length) {
> +			/* write data to FIFO */
> +			ep->xfer_len = MIN(urb->actual_length - endpoint->sent,
> +					endpoint->tx_packetSize);
> +
> +			if (ep->xfer_len) {
> +				ep->xfer_buff = urb->buffer + endpoint->sent;
> +
> +				/*
> +				 * This ensures that USBD packet fifo is
> +				 * accessed through word aligned pointer or
> +				 * through non word aligned pointer but only
> +				 * with a max length to make the next packet
> +				 * word aligned
> +				 */
> +
> +				align = ((ulong)ep->xfer_buff % sizeof(int));
> +				if (align)
> +					ep->xfer_len = MIN(ep->xfer_len,
> +							sizeof(int) - align);
> +
> +				dwc_otg_ep_write_packet(ep);
> +			}
> +			endpoint->last = ep->xfer_len;
> +
> +		} else if (urb && (urb->actual_length == 0)) {
> +			/* udc_set_nak(ep); */

remove deadcode please

> +		}
> +	}
> +}
> +
> +/* This function returns pointer to out ep struct with number num */
> +struct dwc_ep *get_out_ep(u32 num)
> +{
> +	u32 i;
> +	int num_out_eps = MAX_EPS_CHANNELS;
> +	struct dwc_pcd *pcd = &dev_if->pcd;
> +
> +	if (num == 0) {
> +		return &pcd->ep0;

You don't need the else branch below, it'll make code more readable:

if (num == 0)
 return;

... code ...

> +	} else {
> +		for (i = 0; i < num_out_eps; ++i) {
> +			if (pcd->out_ep[i].num == num)
> +				return &pcd->out_ep[i];
> +		}
> +	}
> +	return 0;
> +}
> +
> +/* This function returns pointer to in ep struct with number num */
> +struct dwc_ep *get_in_ep(u32 num)
> +{
> +	u32 i;
> +	int num_out_eps = MAX_EPS_CHANNELS;
> +	struct dwc_pcd *pcd = &dev_if->pcd;
> +
> +	if (num == 0) {
> +		return &pcd->ep0;
> +	} else {
> +		for (i = 0; i < num_out_eps; ++i) {
> +			if (pcd->in_ep[i].num == num)
> +				return &pcd->in_ep[i];
> +		}
> +	}
> +	return 0;
> +}
> +
> +/*
> + * This function reads the 8 bytes of the setup packet from the Rx FIFO
> into the + * destination buffer. It is called from the Rx Status Queue
> Level (RxStsQLvl) + * interrupt routine when a SETUP packet has been
> received in Slave mode. + */
> +static void dwc_otg_read_setup_packet(u32 *dest)
> +{
> +	dest[0] = readl(dev_if->data_fifo[0]);
> +	dest[1] = readl(dev_if->data_fifo[0]);
> +}
> +
> +/*
> + * This function handles the Rx Status Queue Level Interrupt, which
> + * indicates that there is a least one packet in the Rx FIFO. The
> + * packets are moved from the FIFO to memory, where they will be
> + * processed when the Endpoint Interrupt Register indicates Transfer
> + * Complete or SETUP Phase Done.
> + *
> + * Repeat the following until the Rx Status Queue is empty:
> + *	 -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
> + *		info
> + *	 -# If Receive FIFO is empty then skip to step Clear the interrupt
> + *		and exit
> + *	 -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
> + *		SETUP data to the buffer
> + *	 -# If OUT Data Packet call dwc_otg_read_packet to copy the data
> + *		to the destination buffer
> + */
> +static int dwc_otg_pcd_handle_rx_status_q_level_intr(void)
> +{
> +	struct core_global_regs *global_regs = dev_if->core_global_regs;
> +	struct dwc_pcd *pcd = &dev_if->pcd;
> +	u32	gintmsk;
> +	u32	status;
> +	struct dwc_ep *ep;
> +	u32	bcnt;
> +
> +	/* Disable the Rx Status Queue Level interrupt */
> +	gintmsk = readl(&global_regs->gintmsk);
> +	gintmsk &= ~RXSTSQLVL;
> +	writel(gintmsk, &global_regs->gintmsk);
> +
> +	/* Get the Status from the top of the FIFO */
> +	status = readl(&global_regs->grxstsp);
> +	/* Get pointer to EP structure */
> +	ep = get_out_ep((status & EPNUMMSK) >> EPNUM_SHIFT);
> +	bcnt = (status & BCNTMSK) >> BCNT_SHIFT;
> +
> +	switch ((status & PKTSTSMSK) >> PKTSTS_SHIFT) {
> +	case DWC_DSTS_GOUT_NAK:
> +		break;
> +	case DWC_STS_DATA_UPDT:
> +		if (bcnt)
> +			dw_udc_epn_rx(ep, bcnt);
> +		break;
> +	case DWC_STS_XFER_COMP:
> +		break;
> +	case DWC_DSTS_SETUP_COMP:
> +		break;
> +	case DWC_DSTS_SETUP_UPDT:
> +		dwc_otg_read_setup_packet((u32 *)pcd->req);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	/* Enable the Rx Status Queue Level interrupt */
> +	gintmsk = readl(&global_regs->gintmsk);
> +	gintmsk |= RXSTSQLVL;
> +	writel(gintmsk, &global_regs->gintmsk);
> +
> +	/* Clear interrupt */
> +	writel(RXSTSQLVL, &global_regs->gintsts);
> +
> +	return 1;
> +}
> +
> +/*
> + * This function starts the Zero-Length Packet for the IN status phase
> + * of a 2 stage control transfer.
> + */
> +static void do_setup_in_status_phase(struct device_if *dev_if)
> +{
> +	struct device_out_ep_regs *out_regs =
> +		dev_if->out_ep_regs[0];
> +	u32 doepctl, doeptsiz;
> +	doeptsiz = 0;
> +	doeptsiz |= (1 << PKTCNT_SHIFT);
> +	writel(doeptsiz, &out_regs->doeptsiz);
> +	doepctl = readl(&out_regs->doepctl);
> +	doepctl |= (CNAK | EPENA);
> +	writel(doepctl, &out_regs->doepctl);

clrsetbits_le32 ... fix globally please.

> +}
> +
> +static void udc_set_stall(int epid, int dir)
> +{

if (dir)
 reg = ...
else
 reg = ...

writel(readl(reg) | ..., reg);

might be more readable ;-)

> +	if (dir)
> +		writel(readl(&dev_if->in_ep_regs[epid]->diepctl) | SSTALL,
> +			&dev_if->in_ep_regs[epid]->diepctl);
> +	else
> +		writel(readl(&dev_if->out_ep_regs[epid]->doepctl) | SSTALL,
> +			&dev_if->out_ep_regs[epid]->doepctl);
> +}
> +/*
> + * This function handles EP0 Control transfers.
> + *
> + * The state of the control tranfers are tracked in ep0state
> + *
> + * A flag set indicates that it is not the first packet, so do not
> + * process setup data now. it has alreday been processed, just send the
> + * next data packet
> + */
> +void handle_ep0(int in_flag)
> +{
> +	struct dwc_pcd *pcd = &dev_if->pcd;
> +	struct dwc_ep *ep0 = &pcd->ep0;
> +	struct usb_device_request *ctrl = pcd->req;
> +
> +	/* handle inepint, only when more than 64 bytes to transfer*/
> +	if (in_flag & !ep0_urb->actual_length)
> +		return;
> +
> +	if (!ep0_urb->actual_length) {
> +		if (ep0_recv_setup(ep0_urb)) {
> +			udc_set_stall(0, ctrl->bmRequestType & USB_DIR_IN);
> +			return;
> +		}
> +		ep0->xfer_buff = (u8 *)ep0_urb->buffer;
> +	} else
> +		ep0->xfer_buff += EP0_MAX_PACKET_SIZE;
> +
> +	if (ep0_urb->actual_length <= EP0_MAX_PACKET_SIZE) {
> +		ep0->xfer_len = ep0_urb->actual_length;
> +		ep0_urb->actual_length = 0;
> +	} else {
> +		ep0->xfer_len = EP0_MAX_PACKET_SIZE;
> +		ep0_urb->actual_length -= EP0_MAX_PACKET_SIZE;
> +	}
> +
> +	if (ctrl->bmRequestType & USB_DIR_IN) {
> +		dwc_otg_ep_write_packet(ep0);
> +		if (!ep0_urb->actual_length)
> +			do_setup_in_status_phase(dev_if);
> +	} else {
> +		if (!ctrl->wLength)
> +			dwc_otg_ep_write_packet(ep0);
> +		else
> +			udc_set_stall(0, ctrl->bmRequestType & USB_DIR_OUT);
> +	}
> +}
> +
> +/*
> + * This function reads the Device All Endpoints Interrupt register and
> + * returns the OUT endpoint interrupt bits.
> + */
> +static u32 dwc_otg_read_dev_all_out_ep_intr(void)
> +{
> +	u32 v;
> +
> +	v = readl(&dev_if->dev_global_regs->daint) &
> +		readl(&dev_if->dev_global_regs->daintmsk);
> +	return (v & 0xffff0000) >> 16;

simple  return v >> 16 doesn't work?
> +}
> +
> +/*
> + * This function reads the Device All Endpoints Interrupt register and
> + * returns the IN endpoint interrupt bits.
> + */
> +static u32 dwc_otg_read_dev_all_in_ep_intr(void)
> +{
> +	u32 v;
> +
> +	v = readl(&dev_if->dev_global_regs->daint) &
> +		readl(&dev_if->dev_global_regs->daintmsk);
> +	return v & 0xffff;
> +}
> +
> +/* This function returns the Device OUT EP Interrupt register */
> +static u32 dwc_otg_read_doep_intr(struct dwc_ep *ep)
> +{
> +	u32 v;
> +
> +	v = readl(&dev_if->out_ep_regs[ep->num]->doepint) &
> +		readl(&dev_if->dev_global_regs->doepmsk);
> +	return v;
> +}
> +
> +/*This function returns the Device IN EP Interrupt register */
> +static u32 dwc_otg_read_diep_intr(struct dwc_ep *ep)
> +{
> +	u32 v;
> +
> +	v = readl(&dev_if->in_ep_regs[ep->num]->diepint) &
> +		readl(&dev_if->dev_global_regs->diepmsk);
> +	return v;
> +}
> +
> +/*
> + * This function configures EPO to receive SETUP packets.
> + *
> + * Program the following fields in the endpoint specific registers for
> Control + * OUT EP 0, in order to receive a setup packet:
> + *
> + * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back setup
> packets) + *
> + * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back to back
> setup + * packets)
> + *
> + * In DMA mode, DOEPDMA0 Register with a memory address to store any setup
> + * packets received
> + */
> +static void ep0_out_start(void)
> +{
> +	u32 temp;
> +
> +	/* program transfer size*/
> +	temp = 8 * 3;
> +	/* program packet count*/
> +	temp |= PKTCNT;
> +	/* program setup packet count */
> +	temp |= (3 << SUPCNT_SHIFT);
> +	writel(temp, &dev_if->out_ep_regs[0]->doeptsiz);
> +}
> +
> +/* should be called after set address is received */
> +void udc_set_address_controller(u32 address)
> +{
> +	u32 dcfg;
> +
> +	dcfg = readl(&dev_if->dev_global_regs->dcfg);
> +	dcfg &= ~DEVADDRMSK;
> +	dcfg |= address << DEVADDR_SHIFT;
> +	writel(dcfg, &dev_if->dev_global_regs->dcfg);
> +
> +	usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
> +}
> +
> +/* should be called after set configuration is received */
> +static void dwc_otg_bulk_out_activate(void)
> +{
> +	struct device_out_ep_regs *out_regs =
> +		dev_if->out_ep_regs[UDC_OUT_ENDPOINT];
> +	struct device_global_regs *dev_global_regs
> +		= dev_if->dev_global_regs;
> +	u32 doepctl, doeptsiz, daint;
> +
> +	daint = readl(&dev_global_regs->daintmsk);
> +	daint |= 1 << (UDC_OUT_ENDPOINT + DAINTMASK_OUT_SHIFT);
> +	writel(daint, &dev_global_regs->daintmsk);
> +	doeptsiz = CONFIG_USBD_SERIAL_BULK_PKTSIZE;
> +	doeptsiz |= (1 << PKTCNT_SHIFT);
> +	writel(doeptsiz, &out_regs->doeptsiz);
> +	doepctl = readl(&out_regs->doepctl);
> +	doepctl &= ~DOEPCTL_MPSMSK;
> +	doepctl &= ~EPTYPEMSK;
> +	doepctl |= (CONFIG_USBD_SERIAL_BULK_PKTSIZE |
> +			CNAK | EPENA | USBACTEP | DATA0PID
> +			| (EPTYPE_BULK << EPTYPE_SHIFT));
> +	writel(doepctl, &out_regs->doepctl);
> +}
> +
> +/* should be called after set configuration is received */
> +static void dwc_otg_bulk_in_activate(void)
> +{
> +	struct device_in_ep_regs *in_regs =
> +		dev_if->in_ep_regs[UDC_IN_ENDPOINT];
> +	struct device_global_regs *dev_global_regs
> +		= dev_if->dev_global_regs;
> +	u32 diepctl, daint;
> +
> +	daint = readl(&dev_global_regs->daintmsk);
> +	daint |= 1 << (UDC_IN_ENDPOINT + DAINTMASK_IN_SHIFT);
> +	writel(daint, &dev_global_regs->daintmsk);
> +
> +	diepctl = readl(&in_regs->diepctl);
> +	diepctl &= ~DIEPCTL_MPSMSK;
> +	diepctl &= ~EPTYPEMSK;
> +	diepctl |= (CONFIG_USBD_SERIAL_BULK_PKTSIZE
> +			| USBACTEP | DATA0PID
> +			| (EPTYPE_BULK << EPTYPE_SHIFT));
> +	writel(diepctl, &in_regs->diepctl);
> +}
> +
> +static void dwc_otg_int_in_activate(void)
> +{
> +	struct device_in_ep_regs *in_regs =
> +		dev_if->in_ep_regs[UDC_INT_ENDPOINT];
> +	struct device_global_regs *dev_global_regs
> +		= dev_if->dev_global_regs;
> +	u32 diepctl, daint;
> +
> +	daint = readl(&dev_global_regs->daintmsk);
> +	daint |= 1 << (UDC_INT_ENDPOINT + DAINTMASK_IN_SHIFT);
> +	writel(daint, &dev_global_regs->daintmsk);
> +
> +	diepctl = readl(&in_regs->diepctl);
> +	diepctl &= ~DIEPCTL_MPSMSK;
> +	diepctl &= ~EPTYPEMSK;
> +	diepctl |= (UDC_INT_PACKET_SIZE
> +			| USBACTEP | DATA0PID
> +			| (EPTYPE_INT << EPTYPE_SHIFT));
> +	writel(diepctl, &in_regs->diepctl);

lot of clrsetbits_le32 will appear in these parts ;-)

> +}
> +
> +/* should be called after set configuration is received */
> +void udc_set_configuration_controller(u32 config)
> +{
> +	dwc_otg_bulk_out_activate();
> +	dwc_otg_bulk_in_activate();
> +	dwc_otg_int_in_activate();
> +	usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
> +}
> +
> +/* should be called to receive next packet */
> +static void dwc_otg_bulk_out_enable(void)
> +{
> +	struct device_out_ep_regs *out_regs =
> +		dev_if->out_ep_regs[UDC_OUT_ENDPOINT];
> +	u32 doepctl, doeptsiz;
> +
> +	doeptsiz = CONFIG_USBD_SERIAL_BULK_PKTSIZE;
> +	doeptsiz |= (1 << PKTCNT_SHIFT);
> +	writel(doeptsiz, &out_regs->doeptsiz);
> +	doepctl = readl(&out_regs->doepctl);
> +	doepctl |= CNAK | EPENA;
> +	writel(doepctl, &out_regs->doepctl);
> +}
> +
> +/* This interrupt indicates that an OUT EP has a pending Interrupt. */
> +
> +static int dwc_otg_pcd_handle_out_ep_intr(void)
> +{
> +	u32 ep_intr;
> +	u32 doepint;
> +	u32 epnum = 0;
> +	struct dwc_ep *dwc_ep;
> +	struct device_out_ep_regs **out_ep_regs
> +		= dev_if->out_ep_regs;
> +
> +	/* Read in the device interrupt bits */
> +	ep_intr = dwc_otg_read_dev_all_out_ep_intr();
> +	while (ep_intr) {
> +		if (ep_intr & 0x1) {
> +			dwc_ep = get_out_ep(epnum);

do you even use this variable? Don't you get gcc4.6 warnings ?

> +			doepint = dwc_otg_read_doep_intr(dwc_ep);
> +
> +			/* Transfer complete */
> +			if (doepint & XFERCOMPL) {
> +				/* Clear xfercompl */
> +				writel(XFERCOMPL, &out_ep_regs[epnum]->doepint);
> +				if (!epnum)
> +					ep0_out_start();
> +				else if (epnum == UDC_OUT_ENDPOINT)
> +					dwc_otg_bulk_out_enable();
> +			}
> +			/* Setup Phase Done (control EPs) */
> +			if (doepint & SETUP) {
> +				writel(SETUP, &out_ep_regs[epnum]->doepint);
> +				handle_ep0(0);
> +			}
> +		}
> +		epnum++;
> +		ep_intr >>= 1;
> +	}
> +	return 1;
> +}
> +
> +/* This interrupt indicates that an IN EP has a pending Interrupt. */
> +
> +static int dwc_otg_pcd_handle_in_ep_intr(void)
> +{
> +	u32 ep_intr;
> +	u32 diepint;
> +	u32 epnum = 0;
> +	struct dwc_ep *dwc_ep;
> +	struct device_in_ep_regs **in_ep_regs
> +		= dev_if->in_ep_regs;
> +
> +	/* Read in the device interrupt bits */
> +	ep_intr = dwc_otg_read_dev_all_in_ep_intr();
> +	while (ep_intr) {
> +		if (ep_intr & 0x1) {

if (!...)
 continue;

... code ...

Lessers the depth of code.

> +			dwc_ep = get_in_ep(epnum);
> +			diepint = dwc_otg_read_diep_intr(dwc_ep);
> +
> +			/* IN token received when txfifo empty */
> +			if (diepint & INTKNTXFEMP) {
> +				/* Clear xfercompl */
> +				writel(INTKNTXFEMP,
> +						&in_ep_regs[epnum]->diepint);
> +				if (!epnum)
> +					handle_ep0(1);
> +				else if (epnum == UDC_IN_ENDPOINT)
> +					dw_udc_epn_tx(dwc_ep);
> +			}
> +		}
> +		epnum++;
> +		ep_intr >>= 1;
> +	}
> +	return 1;
> +}
> +
> +static void dwc_otg_flush_tx_fifo(const int num)
> +{
> +	struct core_global_regs *global_regs = dev_if->core_global_regs;
> +	u32 val = 0;
> +	int count = 0;
> +
> +	val = readl(&global_regs->grstctl);
> +	val |= TXFFLSH;
> +	val &= ~TXFNUM;
> +	val |= (num << TXFNUM_SHIFT);
> +	writel(val, &global_regs->grstctl);
> +
> +	do {
> +		val = readl(&global_regs->grstctl);
> +		if (++count > 10000)
> +			break;
> +		udelay(1);
> +	} while (val & TXFFLSH);
> +
> +	/* Wait for 3 PHY Clocks */
> +	udelay(1);
> +}
> +
> +static void dwc_otg_flush_rx_fifo(void)
> +{
> +	struct core_global_regs *global_regs = dev_if->core_global_regs;
> +	int count = 0;
> +	u32 val = 0;
> +
> +	val = readl(&global_regs->grstctl);
> +	val |= RXFFLSH;
> +	writel(val, &global_regs->grstctl);
> +
> +	do {
> +		val = readl(&global_regs->grstctl);
> +		if (++count > 10000)
> +			break;
> +		udelay(1);

WATCHDOG_RESET() instead of udelay()
also, call the variable count "timeout" and make it count down, it'll be more 
readable (nitpick)

> +	} while (val & RXFFLSH);
> +
> +	/* Wait for 3 PHY Clocks */
> +	udelay(1);
> +}
> +
> +/*
> + * This interrupt occurs when a USB Reset is detected. When the USB Reset
> + * Interrupt occurs the device state is set to DEFAULT and the EP0 state
> is set + * to IDLE.
> + *
> + */
> +static int dwc_otg_pcd_handle_usb_reset_intr(void)
> +{
> +	u32 temp;
> +	u32 i;
> +	u32 gintmsk;
> +	struct device_out_ep_regs **out_ep_regs
> +		= dev_if->out_ep_regs;
> +	struct device_global_regs *dev_global_regs
> +		= dev_if->dev_global_regs;
> +	struct core_global_regs *core_global_regs
> +		= dev_if->core_global_regs;
> +	/* Set NAK for all OUT EPs */
> +	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
> +		temp = readl(&out_ep_regs[i]->doepctl);
> +		temp |= SNAK;
> +		writel(temp, &out_ep_regs[i]->doepctl);
> +	}
> +
> +	/* Flush the NP Tx FIFO */
> +	dwc_otg_flush_tx_fifo(DWC_GRSTCTL_TXFNUM_ALL);
> +	dwc_otg_flush_rx_fifo();
> +	writel((1 << (DAINTMASK_IN_SHIFT + 0))
> +				| (1 << (DAINTMASK_OUT_SHIFT + 0)),
> +				&dev_global_regs->daintmsk);
> +
> +	writel(SETUPMSK | XFERCOMPLMSK | AHBERRMSK | EPDISABLEDMSK,
> +			&dev_global_regs->doepmsk);
> +
> +	writel(INTKNTXFEMP, &dev_global_regs->diepmsk);
> +
> +	gintmsk = readl(&core_global_regs->gintmsk);
> +	gintmsk |= GOUTNAKEFF;
> +	writel(gintmsk, &core_global_regs->gintmsk);
> +
> +	/* program fifo size for ep0 */
> +
> +	writel(0x200, &core_global_regs->grxfsiz);
> +
> +	temp = readl(&dev_if->in_ep_regs[0]->diepctl);
> +	temp &= 0xFFC3FFFF; /* TxFNumBF = 0, bits 25:22 */
> +	writel(temp, &dev_if->in_ep_regs[0]->diepctl);
> +
> +	temp = readl(&core_global_regs->gnptxfsiz);
> +
> +	writel(0x2000000, &core_global_regs->gnptxfsiz);

Magic value?

> +
> +	/* Reset Device Address */
> +	temp = readl(&dev_global_regs->dcfg);
> +	temp &= ~DEVADDRMSK;
> +	writel(temp, &dev_global_regs->dcfg);
> +
> +	/* setup EP0 to receive SETUP packets */
> +	ep0_out_start();
> +
> +	/* Clear interrupt */
> +	writel(USBRESET, &core_global_regs->gintsts);
> +
> +	UDCDBG("device reset in progess");
> +	usbd_device_event_irq(udc_device, DEVICE_HUB_CONFIGURED, 0);
> +
> +	return 1;
> +}
> +
> +/*
> + * This function enables EP0 OUT to receive SETUP packets and configures
> EP0 + * IN for transmitting packets. It is normally called when the
> "Enumeration + * Done" interrupt occurs.
> + */
> +static void dwc_otg_ep0_activate(void)
> +{
> +	u32 temp;
> +	struct device_in_ep_regs *in_ep_regs = dev_if->in_ep_regs[0];
> +	struct device_out_ep_regs *out_ep_regs = dev_if->out_ep_regs[0];
> +
> +	/* Read the Device Status and Endpoint 0 Control registers */
> +	temp = readl(&in_ep_regs->diepctl);
> +	temp &= ~MPSMSK0;
> +	temp |= DWC_DEP0CTL_MPS_64;
> +	writel(temp, &in_ep_regs->diepctl);
> +
> +	temp = readl(&out_ep_regs->doepctl);
> +	/* Enable OUT EP for receive */
> +	temp |= EPENA;
> +	writel(temp, &out_ep_regs->doepctl);
> +}
> +
> +/*
> + * Read the device status register and set the device speed in the
> + * data structure.
> + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
> + */
> +static int dwc_otg_pcd_handle_enum_done_intr(void)
> +{
> +	u32 gusbcfg;
> +	struct core_global_regs *global_regs = dev_if->core_global_regs;
> +	dwc_otg_ep0_activate();
> +
> +	gusbcfg = readl(&global_regs->gusbcfg);
> +	gusbcfg &= ~USBTRDTIMMSK;
> +	gusbcfg |= PHYIF_16BIT;
> +	gusbcfg |= (9 << USBTRDTIM_SHIFT);

Magic?

> +	writel(gusbcfg, &global_regs->gusbcfg);
> +	/* Clear interrupt */
> +	writel(ENUMDONE, &global_regs->gintsts);
> +	usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
> +	return 1;
> +}
> +
> +static u32 dwc_otg_read_core_intr(void)
> +{
> +	return readl(&dev_if->core_global_regs->gintsts) &
> +		readl(&dev_if->core_global_regs->gintmsk);
> +}
> +
> +static void dwc_otg_init(const void *reg_base)
> +{
> +	struct dwc_pcd *pcd = &dev_if->pcd;
> +	u32 offset;
> +	u32 i;
> +
> +	dev_if->core_global_regs = (struct core_global_regs *) reg_base;
> +	dev_if->dev_global_regs = (struct device_global_regs *) ((u32)reg_base +
> +			DWC_DEV_GLOBAL_REG_OFFSET);
> +
> +	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
> +		offset = i * DWC_EP_REG_OFFSET;
> +
> +		dev_if->in_ep_regs[i] = (struct device_in_ep_regs *)
> +			((u32)reg_base + DWC_DEV_IN_EP_REG_OFFSET + offset);
> +
> +		dev_if->out_ep_regs[i] = (struct device_out_ep_regs *)
> +			((u32)reg_base + DWC_DEV_OUT_EP_REG_OFFSET + offset);
> +	}
> +
> +	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
> +		dev_if->data_fifo[i] =
> +			(u32 *) ((u32)reg_base + DWC_OTG_DATA_FIFO_OFFSET +
> +					(i * DWC_OTG_DATA_FIFO_SIZE));
> +	}
> +
> +	dev_if->speed = 0;	/* unknown */
> +	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
> +		pcd->in_ep[i].num = i;
> +		pcd->out_ep[i].num = i;
> +	}
> +}
> +
> +/*
> + * This function initializes the DWC_otg controller registers and prepares
> the + * core for device mode
> + */
> +static void dwc_otg_core_init(void)
> +{
> +	struct core_global_regs *global_regs = dev_if->core_global_regs;
> +	u32 ahbcfg, gintmsk, usbcfg;
> +	/* Step 1: Program the GAHBCFG Register. */
> +	ahbcfg = DWC_NPTXEMPTYLVL_EMPTY | DWC_PTXEMPTYLVL_EMPTY;
> +	writel(ahbcfg, &global_regs->gahbcfg);
> +
> +	/* Step 2: write usbcfg regs*/
> +	usbcfg = readl(&global_regs->gusbcfg);
> +	usbcfg |= SRPCAP | HNPCAP;
> +	writel(usbcfg, &global_regs->gusbcfg);
> +
> +	/* step3: write int_msk reg*/
> +	gintmsk = USBRESET | ENUMDONE | RXSTSQLVL | OUTEPINTR | INEPINTR;
> +	writel(gintmsk, &global_regs->gintmsk);
> +}
> +
> +/* Switch on the UDC */
> +static void usbotg_init(void)
> +{
> +	udc_device = NULL;
> +#ifdef APG_BOARD
> +	dwc_otg_init((void *)0x11000000);

What the heck ? :-O

Dead code ?

> +#else
> +	dwc_otg_init((void *)CONFIG_SYS_USBD_BASE);
> +#endif
> +
> +	/* Initialize the DWC_otg core.	*/
> +	dwc_otg_core_init();
> +
> +}
> +
> +void udc_irq(void)
> +{
> +	u32 status;
> +
> +	status = dwc_otg_read_core_intr();
> +	while (status) {
> +		if (status & USBRESET)
> +			dwc_otg_pcd_handle_usb_reset_intr();
> +		if (status & ENUMDONE)
> +			dwc_otg_pcd_handle_enum_done_intr();
> +		if (status & RXSTSQLVL)
> +			dwc_otg_pcd_handle_rx_status_q_level_intr();
> +		if (status & OUTEPINTR)
> +			dwc_otg_pcd_handle_out_ep_intr();
> +		if (status & INEPINTR)
> +			dwc_otg_pcd_handle_in_ep_intr();
> +		status = dwc_otg_read_core_intr();
> +	}
> +
> +}
> +
> +void udc_set_nak(int epid)
> +{
> +	writel(readl(&dev_if->out_ep_regs[epid]->doepctl) | SNAK,
> +			&dev_if->out_ep_regs[epid]->doepctl);
> +	writel(readl(&dev_if->in_ep_regs[epid]->diepctl) | SNAK,
> +			&dev_if->in_ep_regs[epid]->diepctl);

Shouldn't you put this together with previous such code that operated with 
exeactly the same registers ? maybe even merge these three functions together.

And(!) make everything that you don't need outside static please.

> +}
> +
> +void udc_unset_nak(int epid)
> +{
> +	writel(readl(&dev_if->out_ep_regs[epid]->doepctl) | CNAK,
> +			&dev_if->out_ep_regs[epid]->doepctl);
> +	writel(readl(&dev_if->in_ep_regs[epid]->diepctl) | CNAK,
> +			&dev_if->in_ep_regs[epid]->diepctl);
> +}
> +
> +int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
> +{
> +	udc_unset_nak(endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK);
> +	return 0;
> +}
> +
> +static void udc_enable(struct usb_device_instance *device)
> +{
> +	struct dwc_pcd *pcd = &dev_if->pcd;
> +
> +	UDCDBGA("enable device %p, status %d", device, device->status);
> +
> +	/* 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);
> +		pcd->req =
> +			(struct usb_device_request *)&ep0_urb->device_request;
> +		pcd->ep0.xfer_buff = (u8 *)ep0_urb->buffer;
> +	} else {
> +#ifndef APG_BOARD
> +		serial_printf("udc_enable: ep0_urb already allocated %p\n",
> +				ep0_urb);

Use printf(), not serial_printf(), globally

> +#endif
> +	}
> +}
> +
> +void udc_connect(void)
> +{
> +	struct device_global_regs *dev_regs = dev_if->dev_global_regs;
> +	u32 dcfg;
> +
> +	/* remove soft disconnect */
> +	dcfg = readl(&dev_regs->dctl);
> +	dcfg &= ~SFTDISCON;
> +	writel(dcfg, &dev_regs->dctl);
> +}
> +
> +void udc_disconnect(void)
> +{
> +	struct device_global_regs *dev_regs = dev_if->dev_global_regs;
> +	u32 dcfg;
> +
> +	/* soft disconnect */
> +	dcfg = readl(&dev_regs->dctl);
> +	dcfg |= SFTDISCON;
> +	writel(dcfg, &dev_regs->dctl);
> +	udelay(150);
> +}
> +
> +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 DW USB 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.
> +	 */
> +
> +	udc_enable(device);
> +
> +}
> +
> +void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
> +		struct usb_endpoint_instance *endpoint)
> +{
> +	/*
> +	 * Nothing to do here. Hob of this function has laready been
> +	 * done during init.
> +	 */
> +}
> +
> +int is_usbd_high_speed(void)
> +{
> +	struct device_global_regs *dev_regs = dev_if->dev_global_regs;
> +	u32 dsts;
> +
> +	dsts = readl(&dev_regs->dsts);
> +	dsts &= ENUMSPDMSK;
> +	if (dsts == DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ)
> +		return 1;
> +	else
> +		return 0;
> +}
> +
> +int udc_init(void)
> +{
> +	phy_init();
> +	udc_disconnect();
> +	usbotg_init();
> +	return 0;
> +}
> diff --git a/include/usb/designware_otg.h b/include/usb/designware_otg.h
> new file mode 100644
> index 0000000..d7b686b
> --- /dev/null
> +++ b/include/usb/designware_otg.h
> @@ -0,0 +1,527 @@
> +/*
> + * (C) Copyright 2011
> + * Pratyush Anand, ST Micoelectronics, pratyush.anand at st.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 __DW_OTG_H
> +#define __DW_OTG_H
> +/* temp def: will be removed TBD */
> +#undef APH_BOARD	1
> +#ifdef APG_BOARD
> +#include "types.h"
> +#define CONFIG_USBD_HS
> +#define CONFIG_DW_OTG
> +#endif
> +
> +#include "usbdevice.h"
> +/* USBTTY definitions */
> +#define  EP0_MAX_PACKET_SIZE		64
> +#define  UDC_INT_ENDPOINT		1
> +#define  UDC_INT_PACKET_SIZE		64
> +#define  UDC_OUT_ENDPOINT		2
> +#define  UDC_BULK_PACKET_SIZE		512
> +#if defined(CONFIG_USBD_HS)
> +#define  UDC_BULK_HS_PACKET_SIZE	512
> +#endif
> +#define  UDC_IN_ENDPOINT		3
> +#define  UDC_OUT_PACKET_SIZE		64
> +#define  UDC_IN_PACKET_SIZE		64
> +
> +/* UDC endpoint definitions */
> +#define  UDC_EP0			0
> +#define  UDC_EP1			1
> +#define  UDC_EP2			2
> +#define  UDC_EP3			3
> +
> +#define CMD_SIZE	12
> +/* OTG Register Definitions */
> +
> +/*
> + * The application interfaces with the HS OTG core by reading from and
> + * writing to the Control and Status Register (CSR) space through the
> + * AHB Slave interface. These registers are 32 bits wide, and the
> + * addresses are 32-bit-block aligned.
> + * CSRs are classified as follows:
> + * - Core Global Registers
> + * - Device Mode Registers
> + * - Device Global Registers
> + * - Device Endpoint Specific Registers
> + * - Host Mode Registers
> + * - Host Global Registers
> + * - Host Port CSRs
> + * - Host Channel Specific Registers
> + *
> + * Only the Core Global registers can be accessed in both Device and
> + * Host modes. When the HS OTG core is operating in one mode, either
> + * Device or Host, the application must not access registers from the
> + * other mode. When the core switches from one mode to another, the
> + * registers in the new mode of operation must be reprogrammed as they
> + * would be after a power-on reset.
> + */
> +
> +/*
> + * DWC_otg Core registers. The core_global_regs structure defines the
> + * size and relative field offsets for the Core Global registers.
> + */
> +struct core_global_regs {
> +	/* OTG Control and Status Register.		Offset: 000h */
> +	u32 gotgctl;
> +	/* OTG Interrupt Register.			Offset: 004h */
> +	u32 gotgint;
> +	/* Core AHB Configuration Register.		Offset: 008h */
> +	u32 gahbcfg;
> +
> +#define DWC_GLBINTRMASK				0x0001
> +#define DWC_DMAENABLE				0x0020
> +#define DWC_NPTXEMPTYLVL_EMPTY			0x0080
> +#define DWC_NPTXEMPTYLVL_HALFEMPTY		0x0000
> +#define DWC_PTXEMPTYLVL_EMPTY			0x0100
> +#define DWC_PTXEMPTYLVL_HALFEMPTY		0x0000
> +
> +	/* Core USB Configuration Register.		Offset: 00Ch */
> +	u32 gusbcfg;
> +#define PHYIF_16BIT				(1 << 3)
> +#define SRPCAP					(1 << 8)
> +#define HNPCAP					(1 << 9)
> +#define TERM_SEL_DL_PULSE			(1 << 22)
> +#define USBTRDTIM_SHIFT				10
> +#define USBTRDTIMMSK				(0xF << USBTRDTIM_SHIFT)
> +	/* Core Reset Register.				Offset: 010h */
> +	u32 grstctl;
> +#define DWC_GRSTCTL_TXFNUM_ALL			0x10
> +#define CSFTRST					(1 << 0)
> +#define INTKNQFLSH				(1 << 3)
> +#define RXFFLSH					(1 << 4)
> +#define	TXFFLSH					(1 << 5)

Fix indent ... here and everywhere please

> +#define TXFNUM_SHIFT				6
> +#define TXFNUM					(0x1F << TXFNUM_SHIFT)
> +#define AHBIDLE					((u32)1 << 31)
> +	/* Core Interrupt Register.			Offset: 014h */
> +	u32 gintsts;
> +#define RXSTSQLVL				(1 << 4)
> +#define NPTXFEMPTY				(1 << 5)
> +#define GOUTNAKEFF				(1 << 7)
> +#define USBRESET				(1 << 12)
> +#define ENUMDONE				(1 << 13)
> +#define INEPINTR				(1 << 18)
> +#define OUTEPINTR				(1 << 19)
> +	/* Core Interrupt Mask Register.		Offset: 018h */
> +	u32 gintmsk;
> +	/*
> +	 * Receive Status Queue Read Register
> +	 * (Read Only)					Offset: 01Ch
> +	 */
> +	u32 grxstsr;
> +	/*
> +	 * Receive Status Queue Read & POP Register
> +	 * (Read Only)					Offset: 020h
> +	 */
> +	u32 grxstsp;
> +#define DWC_STS_DATA_UPDT		0x2 /* OUT Data Packet */
> +#define DWC_STS_XFER_COMP		0x3 /* OUT Data Transfer Complete */
> +#define DWC_DSTS_GOUT_NAK		0x1 /* Global OUT NAK */
> +#define DWC_DSTS_SETUP_COMP		0x4 /* Setup Phase Complete */
> +#define DWC_DSTS_SETUP_UPDT		0x6 /* SETUP Packet */
> +#define EPNUM_SHIFT					0
> +#define EPNUMMSK					(0xF << EPNUM_SHIFT)
> +#define BCNT_SHIFT					4
> +#define BCNTMSK						(0x7FF << 
BCNT_SHIFT)
> +#define PKTSTS_SHIFT					17
> +#define PKTSTSMSK					(0xF << PKTSTS_SHIFT)
> +	/* Receive FIFO Size Register.			Offset: 024h */
> +	u32 grxfsiz;
> +#define dwc_param_dev_rx_fifo_size_default		1064
> +	/* Non Periodic Transmit FIFO Size Register.	Offset: 028h */
> +	u32 gnptxfsiz;
> +#define dwc_param_dev_nperio_tx_fifo_size_default	1024
> +	/*
> +	 * Non Periodic Transmit FIFO/Queue Status Register
> +	 * (Read Only).					Offset: 02Ch
> +	 */
> +	u32 gnptxsts;
> +#define NPTXQSPCAVAIL_SHIFT			16
> +#define NPTXQSPCAVAILMSK			(0xFF << NPTXQSPCAVAIL_SHIFT)
> +#define NPTXFSPCAVAIL_SHIFT			0
> +#define NPTXFSPCAVAILMSK			(0xFFFF << NPTXFSPCAVAIL_SHIFT)
> +	/* I2C Access Register.				Offset: 030h */
> +	u32 gi2cctl;
> +	/* PHY Vendor Control Register.			Offset: 034h */
> +	u32 gpvndctl;
> +	/* General Purpose Input/Output Register.	Offset: 038h */
> +	u32 ggpio;
> +	/* User ID Register.				Offset: 03Ch */
> +	u32 guid;
> +	/* Synopsys ID Register (Read Only).		Offset: 040h */
> +	u32 gsnpsid;
> +	/* User HW Config1 Register (Read Only).	Offset: 044h */
> +	u32 ghwcfg1;
> +	/* User HW Config2 Register (Read Only).	Offset: 048h */
> +
> +	u32 ghwcfg2;
> +#define DWC_SLAVE_ONLY_ARCH			0
> +#define DWC_EXT_DMA_ARCH			1
> +#define DWC_INT_DMA_ARCH			2
> +
> +#define DWC_MODE_HNP_SRP_CAPABLE		0
> +#define DWC_MODE_SRP_ONLY_CAPABLE		1
> +#define DWC_MODE_NO_HNP_SRP_CAPABLE		2
> +#define DWC_MODE_SRP_CAPABLE_DEVICE		3
> +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE		4
> +#define DWC_MODE_SRP_CAPABLE_HOST		5
> +#define DWC_MODE_NO_SRP_CAPABLE_HOST		6
> +#define DYNAMIC_FIFO				(1 << 19)
> +#define	NUM_DEV_EP_SHIFT	10
> +#define	NUM_DEV_EP	(0xF << NUM_DEV_EP_SHIFT)
> +#define HSPHYTYPE_SHIFT				6
> +#define HSPHYTYPEMSK				(3 << HSPHYTYPE_SHIFT)
> +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED		0
> +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI			1
> +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI			2
> +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI		3
> +#define TKNQDEPTH_SHIFT					26
> +#define TKNQDEPTHMSK				(0x1F << TKNQDEPTH_SHIFT)
> +
> +	/* User HW Config3 Register (Read Only).	Offset: 04Ch */
> +	u32 ghwcfg3;
> +#define	DFIFO_DEPTH_SHIFT	16
> +#define DFIFO_DEPTH	((u32)0xFFFF << DFIFO_DEPTH_SHIFT)
> +	/* User HW Config4 Register (Read Only).	Offset: 050h */
> +	u32 ghwcfg4;
> +#define NUM_DEV_PERIO_IN_EP_SHIFT	0
> +#define NUM_DEV_PERIO_IN_EP (0xF << NUM_DEV_PERIO_IN_EP_SHIFT)
> +#define DED_FIFO_EN	(1 << 25)
> +#define NUM_IN_EPS_SHIFT	26
> +#define NUM_IN_EPS	(0xF << NUM_IN_EPS_SHIFT)
> +#define UTMI_PHY_DATA_WIDTH_SHIFT	14
> +#define UTMI_PHY_DATA_WIDTH	(0x3 << UTMI_PHY_DATA_WIDTH_SHIFT)
> +	/* Reserved					Offset: 054h-0FFh */
> +	u32 reserved[43];
> +	/* Host Periodic Transmit FIFO Size Register.	Offset: 100h */
> +	u32 hptxfsiz;
> +
> +	/*
> +	 * Device Periodic Transmit FIFO#n Register, if dedicated fifos are
> +	 * disabled. Otherwise Device Transmit FIFO#n Register.
> +	 *
> +	 * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15)
> +	 */
> +	u32 dptxfsiz_dieptxf[15];
> +#define dwc_param_dev_tx_fifo_size_default	256
> +#define dwc_param_dev_perio_tx_fifo_size_default	256
> +};
> +
> +/*
> + * Device Global Registers. Offsets 800h-BFFh
> + *
> + * The following structures define the size and relative field offsets for
> the + * Device Mode Registers.
> + *
> + * These registers are visible only in Device mode and must not be
> accessed in + * Host mode, as the results are unknown.
> + */
> +struct device_global_regs {		/* CONFIG_DWC_OTG_REG_LE */
> +	/* Device Configuration Register.			Offset: 800h */
> +	u32 dcfg;
> +#define DWC_DCFG_FRAME_INTERVAL_80		0
> +#define DWC_DCFG_FRAME_INTERVAL_85		1
> +#define DWC_DCFG_FRAME_INTERVAL_90		2
> +#define DWC_DCFG_FRAME_INTERVAL_95		3
> +#define DWC_DCFG_FRAME_INTERVAL_MASK		3
> +#define	PERFRINT_SHIFT				11
> +#define DEVSPDMSK				(0x3 << 0)
> +#define DEVADDR_SHIFT				4
> +#define DEVADDRMSK				(0x7F << DEVADDR_SHIFT)
> +#define NZSTSOUTHSHK				(1 << 2)
> +	/* Device Control Register.				Offset: 804h */
> +	u32 dctl;
> +#define RMTWKUPSIG	(1 << 0)
> +#define SFTDISCON	(1 << 1)
> +#define CGNPINNAK	(1 << 7)
> +	/* Device Status Register (Read Only).			Offset: 808h */
> +	u32 dsts;
> +#define ENUMSPD_SHIFT				1
> +#define ENUMSPDMSK				(3 << ENUMSPD_SHIFT)
> +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ		0
> +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ		1
> +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ			2
> +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ			3
> +	/* Reserved.						Offset: 80Ch */
> +	u32 unused;
> +	/* Device IN Endpoint Common Interrupt Mask Register.	Offset: 810h */
> +	u32 diepmsk;
> +#define TIMEOUTMSK				(1 << 3)
> +#define INTKNTXFEMP				(1 << 4)
> +#define INTKNEPMISMSK				(1 << 5)
> +#define INEPNAKEFFMSK				(1 << 6)
> +#define TXFIFOUNDRN				(1 << 8)
> +	/* Device OUT Endpoint Common Interrupt Mask Register.	Offset: 814h */
> +	u32 doepmsk;
> +#define XFERCOMPLMSK				(1 << 0)
> +#define EPDISABLEDMSK				(1 << 1)
> +#define AHBERRMSK				(1 << 2)
> +#define SETUPMSK				(1 << 3)
> +#define INTKNTXFEMPMSK				(1 << 4)
> +	/* Device All Endpoints Interrupt Register.		Offset: 818h */
> +	u32 daint;
> +	/* Device All Endpoints Interrupt Mask Register.	Offset: 81Ch */
> +	u32 daintmsk;
> +#define DAINTMASK_IN_SHIFT	0
> +#define DAINTMASK_OUT_SHIFT	16
> +	/* Device IN Token Queue Read Register-1 (Read Only).	Offset: 820h */
> +	u32 dtknqr1;
> +#define EPTK0_5_SHIFT				8
> +#define EPTK0_5MSK				((u32)0xFFFFFF << EPTK0_5_SHIFT)
> +#define INTKNWPTR_SHIFT				0
> +#define INTKNWPTRMSK				((u32)0x1F << INTKNWPTR_SHIFT)
> +	/* Device IN Token Queue Read Register-2 (Read Only).	Offset: 824h */
> +	u32 dtknqr2;
> +	/* Device VBUS discharge Register.			Offset: 828h */
> +	u32 dvbusdis;
> +	/* Device VBUS Pulse Register.				Offset: 82Ch */
> +	u32 dvbuspulse;
> +	/* Device IN Token Queue Read Register-3 (Read Only).	Offset: 830h */
> +	u32 dtknqr3_dthrctl;
> +	/* Device IN Token Queue Read Register-4 (Read Only).	Offset: 834h */
> +	u32 dtknqr4_fifoemptymsk;
> +};
> +/*
> + * Device Logical IN Endpoint-Specific Registers. Offsets 900h-AFCh
> + *
> + * There will be one set of endpoint registers per logical endpoint
> implemented. + *
> + * These registers are visible only in Device mode and must not be
> accessed in + * Host mode, as the results are unknown.
> + */
> +struct device_in_ep_regs {
> +	/*
> +	 * Device IN Endpoint Control Register.
> +	 * Offset:900h + (ep_num * 20h) + 00h
> +	 */
> +	u32 diepctl;
> +#define	EPENA				((u32)1 << 31)
> +#define EPDIS				(1 << 30)
> +#define	SNAK				(1 << 27)
> +#define	CNAK				(1 << 26)
> +#define	SSTALL				(1 << 21)
> +#define MPS_SHIFT			0
> +#define MPSMSK0				(3 << MPS_SHIFT)
> +#define DWC_DEP0CTL_MPS_64			0
> +#define DWC_DEP0CTL_MPS_32			1
> +#define DWC_DEP0CTL_MPS_16			2
> +#define DWC_DEP0CTL_MPS_8			3
> +#define DIEPCTL_MPSMSK				(0x7FF << MPS_SHIFT)
> +	/* Reserved. Offset:900h + (ep_num * 20h) + 04h */
> +	u32 reserved04;
> +	/*
> +	 * Device IN Endpoint Interrupt Register.
> +	 * Offset:900h + (ep_num * 20h) + 08h
> +	 */
> +	u32 diepint;
> +#define TXFEMP				(1 << 7)
> +#define INTKNTXFEMP			(1 << 4)
> +#define XFERCOMPL			(1 << 0)
> +	/* Reserved. Offset:900h + (ep_num * 20h) + 0Ch */
> +	u32 reserved0C;
> +	/* Device IN Endpoint Transfer Size Register.
> +	 * Offset:900h + (ep_num * 20h) + 10h
> +	 */
> +	u32 dieptsiz;
> +#define PKTCNT_SHIFT	19
> +	/*
> +	 * Device IN Endpoint DMA Address Register.
> +	 * Offset:900h + (ep_num * 20h) + 14h
> +	 */
> +	u32 diepdma;
> +	/* Reserved.
> +	 * Offset:900h + (ep_num * 20h) + 18h - 900h + (ep_num * 20h) + 1Ch
> +	 */
> +	u32 dtxfsts;
> +	/*
> +	 * Reserved.
> +	 * Offset:900h + (ep_num * 20h) + 1Ch - 900h + (ep_num * 20h) + 1Ch
> +	 */
> +	u32 reserved18;
> +};
> +
> +/*
> + * Device Logical OUT Endpoint-Specific Registers. Offsets: B00h-CFCh
> + *
> + * There will be one set of endpoint registers per logical endpoint
> implemented. + *
> + * These registers are visible only in Device mode and must not be
> accessed in + * Host mode, as the results are unknown.
> + */
> +struct device_out_ep_regs {
> +	/*
> +	 * Device OUT Endpoint Control Register.
> +	 * Offset:B00h + (ep_num * 20h) + 00h
> +	 */
> +	u32 doepctl;
> +#define DOEPCTL_MPSMSK		0x7FF
> +#define USBACTEP		(1 << 15)
> +#define EPTYPE_SHIFT		18
> +#define EPTYPEMSK		(0x3 << EPTYPE_SHIFT)
> +#define EPTYPE_BULK		0x2
> +#define EPTYPE_INT		0x3
> +#define DATA0PID		(1 << 28)
> +#define DATA1PID		(1 << 29)
> +#define DPIDMSK			(1 << 16)
> +	/*
> +	 * Device OUT Endpoint Frame number Register.
> +	 * Offset: B00h + (ep_num * 20h) + 04h
> +	 */
> +	u32 doepfn;
> +	/*
> +	 * Device OUT Endpoint Interrupt Register.
> +	 * Offset:B00h + (ep_num * 20h) + 08h
> +	 */
> +	u32 doepint;
> +#define XFERCOMPL			(1 << 0)
> +#define EPDISBLD			(1 << 1)
> +#define AHBERR				(1 << 2)
> +#define SETUP				(1 << 3)
> +	/* Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */
> +	u32 reserved0C;
> +	/*
> +	 * Device OUT Endpoint Transfer Size Register.
> +	 * Offset: B00h + (ep_num * 20h) + 10h
> +	 */
> +	u32 doeptsiz;
> +#define XFERSIZE_SHIFT			0
> +#define XFERSIZEMSK			0x3F
> +#define PKTCNT_SHIFT			19
> +#define PKTCNT				(3 << 19)
> +#define SUPCNT_SHIFT			29
> +#define SUPCNTMSK			(3 << SUPCNT_SHIFT)
> +	/*
> +	 * Device OUT Endpoint DMA Address Register.
> +	 * Offset:B00h + (ep_num * 20h) + 14h
> +	 */
> +	u32 doepdma;
> +	/*
> +	 * Reserved.
> +	 * Offset:B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch
> +	 */
> +	u32 unused[2];
> +};
> +#define MAX_EPS_CHANNELS 4
> +
> +/*
> + * The dwc_ep structure represents the state of a single endpoint when
> acting in + * device mode. It contains the data items needed for an
> endpoint to be + * activated and transfer packets.
> + */
> +struct dwc_ep {
> +	/* EP number used for register address lookup */
> +	u8	 num;
> +	/* EP direction 0 = OUT */
> +#if 0
> +	u8 is_in;
> +#endif
> +	/* pointer to the transfer buffer */
> +	u8 *xfer_buff;
> +	/* Number of bytes to transfer */
> +	u32 xfer_len;
> +};
> +
> +/*
> + * DWC_otg PCD Structure.
> + * This structure encapsulates the data for the dwc_otg PCD.
> + */
> +struct dwc_pcd {
> +#if 0
> +	/* USB gadget */
> +	/* Current configuration */
> +	u8	configuration;
> +	/* Current interface */
> +	u8	interface;
> +	/* Current alternate settinng */
> +	u8	alternate;

indent

> +	/* Current Address */
> +	u16 address;
> +	/* device state */
> +/*	usb_device_state_t device_state; */	/* current USB Device state */
> +	/*
> +	 * SETUP packet for EP0. This structure is allocated as a DMA buffer on
> +	 * PCD initialization with enough space for up to 3 setup packets.
> +	 */
> +#endif
> +	struct usb_device_request *req;
> +	/* Array of EPs. */
> +	struct dwc_ep ep0;
> +	/* Array of IN EPs. */
> +	struct dwc_ep in_ep[MAX_EPS_CHANNELS - 1];
> +	/* Array of OUT EPs. */
> +	struct dwc_ep out_ep[MAX_EPS_CHANNELS - 1];
> +};
> +
> +/*
> + * The device_if structure contains information needed to manage the
> DWC_otg + * controller acting in device mode. It represents the
> programming view of the + * device-specific aspects of the controller.
> + */
> +struct device_if {
> +	struct core_global_regs *core_global_regs;
> +	/* Common configuration information */
> +
> +	/* Device Global Registers starting at offset 800h */
> +	struct device_global_regs *dev_global_regs;
> +#define DWC_DEV_GLOBAL_REG_OFFSET		0x800
> +
> +	/* Device Logical IN Endpoint-Specific Registers 900h-AFCh */
> +	struct device_in_ep_regs *in_ep_regs[MAX_EPS_CHANNELS];
> +#define DWC_DEV_IN_EP_REG_OFFSET		0x900
> +#define DWC_EP_REG_OFFSET			0x20
> +
> +	/* Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
> +	struct device_out_ep_regs *out_ep_regs[MAX_EPS_CHANNELS];
> +#define DWC_DEV_OUT_EP_REG_OFFSET		0xB00
> +
> +	/* Push/pop addresses for endpoints or host channels.*/
> +	u32 *data_fifo[MAX_EPS_CHANNELS];
> +#define DWC_OTG_DATA_FIFO_OFFSET		0x1000
> +#define DWC_OTG_DATA_FIFO_SIZE			0x1000
> +
> +	struct dwc_pcd pcd;
> +	int speed;
> +};
> +
> +
> +/* Function declarations */
> +
> +void phy_init(void);
> +void udc_irq(void);
> +
> +void udc_set_nak(int epid);
> +void udc_unset_nak(int epid);
> +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);
> +void udc_set_configuration_controller(u32);
> +void udc_set_address_controller(u32);
> +
> +#endif /* __DW_UDC_H */

Thanks for your good work so far, keep it up ! :-)


More information about the U-Boot mailing list