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

Pratyush Anand pratyush.anand at st.com
Fri Mar 9 05:00:17 CET 2012


On 3/7/2012 6:12 PM, Marek Vasut wrote:
> 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 ;-)
>

will correct..

>> +#undef APG_BOARD     1
>> +
>> +#ifndef APG_BOARD
>
> dead code?
>

ohh, its there...will correct it.

>> +#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()

all the else part will vanish.
this was just to test on another environment.
will correct it. Sorry.

>
>> +
>> +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

ok..

>
>> +             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

ok..will provide timeout.

>
>> +
>> +     /* 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

ok..

>
>> +
>> +     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

ok..

>
>> +}
>> +
>> +/* 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

ok..

>
>> +             }
>> +     }
>> +}
>> +
>> +/* 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:

ok..

>
> 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 ;-)

both are not writing to the same register. if is diepctl and else is 
doepctl.

>
>> +     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?

should 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 ;-)

ok.

>
>> +}
>> +
>> +/* 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 ?

did not get warning, will cross check.

>
>> +                     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.

ok..

>
>> +                     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?

Ok, will define it properly.

>
>> +
>> +     /* 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?

will define this value.

>
>> +     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 ?

Sorry, ifdef APG_BOARD was completely local.
will correct all these.


>
>> +#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.

ok..

>
>> +}
>> +
>> +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

ok..

>
>> +#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

ok..

>
>> +#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

pk..

>
>> +     /* 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