diff mbox series

[Linaro-uefi,v3,2/5] Drivers/Usb/DwUsb: support designware usb

Message ID 1486998621-30420-3-git-send-email-haojian.zhuang@linaro.org
State New
Headers show
Series add drivers for Android Fastboot App on HiKey | expand

Commit Message

Haojian Zhuang Feb. 13, 2017, 3:10 p.m. UTC
Support Designware USB controller.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 Drivers/Usb/DwUsbDxe/DwUsbDxe.c   | 796 ++++++++++++++++++++++++++++++++++++++
 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec |  46 +++
 Drivers/Usb/DwUsbDxe/DwUsbDxe.h   | 627 ++++++++++++++++++++++++++++++
 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf |  52 +++
 Include/Protocol/DwUsb.h          |  81 ++++
 5 files changed, 1602 insertions(+)
 create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c
 create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
 create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h
 create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf
 create mode 100644 Include/Protocol/DwUsb.h

Comments

Leif Lindholm Feb. 13, 2017, 3:39 p.m. UTC | #1
On Mon, Feb 13, 2017 at 11:10:18PM +0800, Haojian Zhuang wrote:
> Support Designware USB controller.
> 

Hi Haojian,

I have not seen any response to my reply:
https://lists.linaro.org/pipermail/linaro-uefi/2017-February/003886.html
and none of my comments there appear to be addressed.

/
    Leif

> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  Drivers/Usb/DwUsbDxe/DwUsbDxe.c   | 796 ++++++++++++++++++++++++++++++++++++++
>  Drivers/Usb/DwUsbDxe/DwUsbDxe.dec |  46 +++
>  Drivers/Usb/DwUsbDxe/DwUsbDxe.h   | 627 ++++++++++++++++++++++++++++++
>  Drivers/Usb/DwUsbDxe/DwUsbDxe.inf |  52 +++
>  Include/Protocol/DwUsb.h          |  81 ++++
>  5 files changed, 1602 insertions(+)
>  create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c
>  create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
>  create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h
>  create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf
>  create mode 100644 Include/Protocol/DwUsb.h
> 
> diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c
> new file mode 100644
> index 0000000..bdd8405
> --- /dev/null
> +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c
> @@ -0,0 +1,796 @@
> +/** @file
> +
> +  Copyright (c) 2015-2017, Linaro. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <IndustryStandard/Usb.h>
> +#include <Library/ArmLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UncachedMemoryAllocationLib.h>
> +#include <Library/CacheMaintenanceLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/BaseLib.h>
> +#include <Protocol/DwUsb.h>
> +#include <Protocol/UsbDevice.h>
> +
> +#include "DwUsbDxe.h"
> +
> +#define USB_TYPE_LENGTH               16
> +#define USB_BLOCK_HIGH_SPEED_SIZE     512
> +#define DATA_SIZE                     32768
> +#define CMD_SIZE                      512
> +#define MATCH_CMD_LITERAL(Cmd, Buf)   !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
> +
> +// The time between interrupt polls, in units of 100 nanoseconds
> +// 10 Microseconds
> +#define DW_INTERRUPT_POLL_PERIOD      10000
> +
> +EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
> +
> +STATIC dwc_otg_dev_dma_desc_t *gDmaDesc,*gDmaDescEp0,*gDmaDescIn;
> +STATIC USB_DEVICE_REQUEST *gCtrlReq;
> +STATIC VOID *RxBuf;
> +STATIC UINTN RxDescBytes = 0;
> +STATIC UINTN mNumDataBytes;
> +
> +STATIC DW_USB_PROTOCOL          *DwUsb;
> +
> +STATIC USB_DEVICE_DESCRIPTOR    *mDeviceDescriptor;
> +
> +// The config descriptor, interface descriptor, and endpoint descriptors in a
> +// buffer (in that order)
> +STATIC VOID                     *mDescriptors;
> +// Convenience pointers to those descriptors inside the buffer:
> +STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor;
> +STATIC USB_CONFIG_DESCRIPTOR    *mConfigDescriptor;
> +STATIC USB_ENDPOINT_DESCRIPTOR  *mEndpointDescriptors;
> +
> +STATIC USB_DEVICE_RX_CALLBACK   mDataReceivedCallback;
> +STATIC USB_DEVICE_TX_CALLBACK   mDataSentCallback;
> +
> +
> +/* To detect which mode was run, high speed or full speed */
> +STATIC
> +UINTN
> +UsbDrvPortSpeed (
> +  VOID
> +  )
> +{
> +  /*
> +  * 2'b00: High speed (PHY clock is running at 30 or 60 MHz)
> +  */
> +  UINT32          Val = READ_REG32 (DSTS) & 2;
> +  return (!Val);
> +}
> +
> +STATIC
> +VOID
> +ResetEndpoints (
> +  VOID
> +  )
> +{
> +  /* EP0 IN ACTIVE NEXT=1 */
> +  WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);
> +
> +  /* EP0 OUT ACTIVE */
> +  WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP);
> +
> +  /* Clear any pending OTG Interrupts */
> +  WRITE_REG32 (GOTGINT, ~0);
> +
> +  /* Clear any pending interrupts */
> +  WRITE_REG32 (GINTSTS, ~0);
> +  WRITE_REG32 (DIEPINT0, ~0);
> +  WRITE_REG32 (DOEPINT0, ~0);
> +  WRITE_REG32 (DIEPINT1, ~0);
> +  WRITE_REG32 (DOEPINT1, ~0);
> +
> +  /* IN EP interrupt mask */
> +  WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
> +  /* OUT EP interrupt mask */
> +  WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
> +  /* Enable interrupts on Ep0 */
> +  WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT));
> +
> +  /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
> +  WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
> +
> +  //notes that:the compulsive conversion is expectable.
> +  gDmaDescEp0->status.b.bs = 0x3;
> +  gDmaDescEp0->status.b.mtrf = 0;
> +  gDmaDescEp0->status.b.sr = 0;
> +  gDmaDescEp0->status.b.l = 1;
> +  gDmaDescEp0->status.b.ioc = 1;
> +  gDmaDescEp0->status.b.sp = 0;
> +  gDmaDescEp0->status.b.bytes = 64;
> +  gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
> +  gDmaDescEp0->status.b.sts = 0;
> +  gDmaDescEp0->status.b.bs = 0x0;
> +  WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
> +  /* EP0 OUT ENABLE CLEARNAK */
> +  WRITE_REG32 (DOEPCTL0, (READ_REG32 (DOEPCTL0) | DXEPCTL_EPENA | DXEPCTL_CNAK));
> +}
> +
> +STATIC
> +VOID
> +EpTx (
> +  IN UINT8          Ep,
> +  IN CONST VOID    *Ptr,
> +  IN UINTN          Len
> +  )
> +{
> +    UINT32          BlockSize;
> +    UINT32          Packets;
> +
> +    /* EPx OUT ACTIVE */
> +    WRITE_REG32 (DIEPCTL (Ep), (READ_REG32 (DIEPCTL (Ep))) | DXEPCTL_USBACTEP);
> +    if (!Ep) {
> +        BlockSize = 64;
> +    } else {
> +        BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
> +    }
> +    Packets = (Len + BlockSize - 1) / BlockSize;
> +
> +    if (!Len) {
> +      /* send one empty packet */
> +      gDmaDescIn->status.b.bs = 0x3;
> +      gDmaDescIn->status.b.l = 1;
> +      gDmaDescIn->status.b.ioc = 1;
> +      gDmaDescIn->status.b.sp = 1;
> +      gDmaDescIn->status.b.bytes = 0;
> +      gDmaDescIn->buf = 0;
> +      gDmaDescIn->status.b.sts = 0;
> +      gDmaDescIn->status.b.bs = 0x0;
> +
> +      WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn));             // DMA Address (DMAAddr) is zero
> +    } else {
> +      WRITE_REG32 (DIEPTSIZ (Ep), Len | (Packets << 19));
> +
> +      //flush cache
> +      WriteBackDataCacheRange ((VOID *)Ptr, Len);
> +
> +      gDmaDescIn->status.b.bs = 0x3;
> +      gDmaDescIn->status.b.l = 1;
> +      gDmaDescIn->status.b.ioc = 1;
> +      gDmaDescIn->status.b.sp = 1;
> +      gDmaDescIn->status.b.bytes = Len;
> +      gDmaDescIn->buf = (UINT32)((UINTN)Ptr);
> +      gDmaDescIn->status.b.sts = 0;
> +      gDmaDescIn->status.b.bs = 0x0;
> +      WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn));         // Ptr is DMA address
> +    }
> +    ArmDataSynchronizationBarrier ();
> +    /* epena & cnak */
> +    WRITE_REG32 (DIEPCTL (Ep), READ_REG32 (DIEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);
> +}
> +
> +STATIC
> +VOID
> +EpRx (
> +  IN UINTN            Ep,
> +  IN UINTN            Len
> +  )
> +{
> +  /* EPx UNSTALL */
> +  WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & (~DXEPCTL_STALL)));
> +  /* EPx OUT ACTIVE */
> +  WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_USBACTEP));
> +
> +  if (Len >= DATA_SIZE) {
> +    RxDescBytes = DATA_SIZE;
> +  } else {
> +    RxDescBytes = Len;
> +  }
> +
> +  RxBuf = AllocatePool (DATA_SIZE);
> +  ASSERT (RxBuf != NULL);
> +
> +  InvalidateDataCacheRange (RxBuf, Len);
> +
> +  gDmaDesc->status.b.bs = 0x3;
> +  gDmaDesc->status.b.mtrf = 0;
> +  gDmaDesc->status.b.sr = 0;
> +  gDmaDesc->status.b.l = 1;
> +  gDmaDesc->status.b.ioc = 1;
> +  gDmaDesc->status.b.sp = 0;
> +  gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;
> +  gDmaDesc->buf = (UINT32)((UINTN)RxBuf);
> +  gDmaDesc->status.b.sts = 0;
> +  gDmaDesc->status.b.bs = 0x0;
> +
> +  ArmDataSynchronizationBarrier ();
> +  WRITE_REG32 (DOEPDMA (Ep), (UINT32)((UINTN)gDmaDesc));
> +  /* EPx OUT ENABLE CLEARNAK */
> +  WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK));
> +}
> +
> +STATIC
> +EFI_STATUS
> +HandleGetDescriptor (
> +  IN USB_DEVICE_REQUEST  *Request
> +  )
> +{
> +  UINT8       DescriptorType;
> +  UINTN       ResponseSize;
> +  VOID       *ResponseData;
> +  EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;
> +  UINTN                             DescriptorSize;
> +
> +  ResponseSize = 0;
> +  ResponseData = NULL;
> +
> +  // Pretty confused if bmRequestType is anything but this:
> +  ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
> +
> +  // Choose the response
> +  DescriptorType = Request->Value >> 8;
> +  switch (DescriptorType) {
> +  case USB_DESC_TYPE_DEVICE:
> +    DEBUG ((DEBUG_INFO, "USB: Got a request for device descriptor\n"));
> +    ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
> +    ResponseData = mDeviceDescriptor;
> +    break;
> +  case USB_DESC_TYPE_CONFIG:
> +    DEBUG ((DEBUG_INFO, "USB: Got a request for config descriptor\n"));
> +    ResponseSize = mConfigDescriptor->TotalLength;
> +    ResponseData = mDescriptors;
> +    break;
> +  case USB_DESC_TYPE_STRING:
> +    DEBUG ((DEBUG_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
> +    switch (Request->Value & 0xff) {
> +    case 0:
> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
> +                       LANG_LENGTH * sizeof (CHAR16) + 1;
> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
> +      ASSERT (Descriptor != NULL);
> +      Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
> +      DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
> +      ResponseSize = Descriptor->Length;
> +      ResponseData = Descriptor;
> +      break;
> +    case 1:
> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
> +                       MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16) + 1;
> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
> +      ASSERT (Descriptor != NULL);
> +      Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
> +      DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
> +      ResponseSize = Descriptor->Length;
> +      ResponseData = Descriptor;
> +      break;
> +    case 2:
> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
> +                       PRODUCT_STRING_LENGTH * sizeof (CHAR16) + 1;
> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
> +      ASSERT (Descriptor != NULL);
> +      Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
> +      DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
> +      ResponseSize = Descriptor->Length;
> +      ResponseData = Descriptor;
> +      break;
> +    case 3:
> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
> +                       SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;
> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
> +      ASSERT (Descriptor != NULL);
> +      Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
> +      DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
> +      ResponseSize = Descriptor->Length;
> +      ResponseData = Descriptor;
> +      break;
> +    }
> +    break;
> +  default:
> +    DEBUG ((DEBUG_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
> +    break;
> +  }
> +
> +  // Send the response
> +  if (ResponseData) {
> +    ASSERT (ResponseSize != 0);
> +
> +    if (Request->Length < ResponseSize) {
> +      // Truncate response
> +      ResponseSize = Request->Length;
> +    } else if (Request->Length > ResponseSize) {
> +      DEBUG ((DEBUG_INFO, "USB: Info: ResponseSize < wLength\n"));
> +    }
> +
> +    EpTx (0, ResponseData, ResponseSize);
> +  }
> +  if (Descriptor) {
> +    FreePool (Descriptor);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +HandleSetAddress (
> +  IN USB_DEVICE_REQUEST  *Request
> +  )
> +{
> +  // Pretty confused if bmRequestType is anything but this:
> +  ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
> +  DEBUG ((DEBUG_INFO, "USB: Setting address to %d\n", Request->Value));
> +  ResetEndpoints ();
> +
> +  WRITE_REG32 (DCFG, (READ_REG32 (DCFG) & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(Request->Value));
> +  EpTx (0, 0, 0);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +UINTN
> +UsbDrvRequestEndpoint (
> +  IN UINTN           Type,
> +  IN UINTN           Dir
> +  )
> +{
> +  UINTN              Ep = 1;
> +  UINTN              Ret, NewBits;
> +
> +  Ret = Ep | Dir;
> +  NewBits = (Type << 18) | 0x10000000;
> +
> +  /*
> +   * (Type << 18):Endpoint Type (EPType)
> +   * 0x10000000:Endpoint Enable (EPEna)
> +   * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
> +   * (ep<<22):TxFIFO Number (TxFNum)
> +   * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
> +   */
> +  if (Dir) {  // IN: to host
> +    WRITE_REG32 (DIEPCTL (Ep), ((READ_REG32 (DIEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits | (Ep << 22) | DXEPCTL_NAKSTS);
> +  } else {    // OUT: to device
> +    WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits);
> +  }
> +
> +  return Ret;
> +}
> +
> +STATIC
> +EFI_STATUS
> +HandleSetConfiguration (
> +  IN USB_DEVICE_REQUEST  *Request
> +  )
> +{
> +  ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
> +
> +  // Cancel all transfers
> +  ResetEndpoints ();
> +
> +  UsbDrvRequestEndpoint (2, 0);
> +  UsbDrvRequestEndpoint (2, 0x80);
> +
> +  WRITE_REG32 (DIEPCTL1, (READ_REG32 (DIEPCTL1)) | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);
> +
> +  /* Enable interrupts on all endpoints */
> +  WRITE_REG32 (DAINTMSK, ~0);
> +
> +  EpRx (1, CMD_SIZE);
> +  EpTx (0, 0, 0);
> +  return EFI_SUCCESS;
> +}
> +
> +
> +STATIC
> +EFI_STATUS
> +HandleDeviceRequest (
> +  IN USB_DEVICE_REQUEST  *Request
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  switch (Request->Request) {
> +  case USB_DEV_GET_DESCRIPTOR:
> +    Status = HandleGetDescriptor (Request);
> +    break;
> +  case USB_DEV_SET_ADDRESS:
> +    Status = HandleSetAddress (Request);
> +    break;
> +  case USB_DEV_SET_CONFIGURATION:
> +    Status = HandleSetConfiguration (Request);
> +    break;
> +  default:
> +    DEBUG ((DEBUG_ERROR,
> +      "Didn't understand RequestType 0x%x Request 0x%x\n",
> +      Request->RequestType, Request->Request));
> +      Status = EFI_INVALID_PARAMETER;
> +    break;
> +  }
> +
> +  return Status;
> +}
> +
> +
> +// Instead of actually registering interrupt handlers, we poll the controller's
> +//  interrupt source register in this function.
> +STATIC
> +VOID
> +CheckInterrupts (
> +  IN EFI_EVENT        Event,
> +  IN VOID            *Context
> +  )
> +{
> +  UINT32              Ints, EpInts;
> +
> +
> +  // interrupt register
> +  Ints = READ_REG32 (GINTSTS);
> +
> +  /*
> +   * bus reset
> +   * The core sets this bit to indicate that a reset is detected on the USB.
> +   */
> +  if (Ints & GINTSTS_USBRST) {
> +    WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);
> +    ResetEndpoints ();
> +  }
> +
> +  /*
> +   * enumeration done, we now know the speed
> +   * The core sets this bit to indicate that speed enumeration is complete. The
> +   * application must read the Device Status (DSTS) register to obtain the
> +   * enumerated speed.
> +   */
> +  if (Ints & GINTSTS_ENUMDONE) {
> +    /* Set up the maximum packet sizes accordingly */
> +    UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
> +    //Set Maximum In Packet Size (MPS)
> +    WRITE_REG32 (DIEPCTL1, ((READ_REG32 (DIEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
> +    //Set Maximum Out Packet Size (MPS)
> +    WRITE_REG32 (DOEPCTL1, ((READ_REG32 (DOEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
> +  }
> +
> +  /*
> +   * IN EP event
> +   * The core sets this bit to indicate that an interrupt is pending on one of the IN
> +   * endpoInts of the core (in Device mode). The application must read the
> +   * Device All EndpoInts Interrupt (DAINT) register to determine the exact
> +   * number of the IN endpoint on which the interrupt occurred, and then read
> +   * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
> +   * determine the exact cause of the interrupt. The application must clear the
> +   * appropriate status bit in the corresponding DIEPINTn register to clear this bit.
> +   */
> +  if (Ints & GINTSTS_IEPINT) {
> +    EpInts = READ_REG32 (DIEPINT0);
> +    WRITE_REG32 (DIEPINT0, EpInts);
> +    if (EpInts & DXEPINT_XFERCOMPL) {
> +      DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));
> +    }
> +
> +    EpInts = READ_REG32 (DIEPINT1);
> +    WRITE_REG32 (DIEPINT1, EpInts);
> +    if (EpInts & DXEPINT_XFERCOMPL) {
> +      DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));
> +    }
> +  }
> +
> +  /*
> +   * OUT EP event
> +   * The core sets this bit to indicate that an interrupt is pending on one of the
> +   * OUT endpoints of the core (in Device mode). The application must read the
> +   * Device All EndpoInts Interrupt (DAINT) register to determine the exact
> +   * number of the OUT endpoint on which the interrupt occurred, and then read
> +   * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
> +   * to determine the exact cause of the interrupt. The application must clear the
> +   * appropriate status bit in the corresponding DOEPINTn register to clear this bit.
> +   */
> +  if (Ints & GINTSTS_OEPINT) {
> +    /* indicates the status of an endpoint
> +     * with respect to USB- and AHB-related events. */
> +    EpInts = READ_REG32 (DOEPINT0);
> +    if (EpInts) {
> +      WRITE_REG32 (DOEPINT0, EpInts);
> +      if (EpInts & DXEPINT_XFERCOMPL) {
> +        DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));
> +      }
> +      /*
> +       *
> +       IN Token Received When TxFIFO is Empty (INTknTXFEmp)
> +       * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
> +       * was empty. This interrupt is asserted on the endpoint for which the IN token
> +       * was received.
> +       */
> +      if (EpInts & BIT3) { /* SETUP phase done */
> +        WRITE_REG32 (DIEPCTL0, READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK);
> +        WRITE_REG32 (DOEPCTL0, READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK);
> +        /*clear IN EP intr*/
> +        WRITE_REG32 (DIEPINT0, ~0);
> +        HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);
> +      }
> +
> +      /* Make sure EP0 OUT is set up to accept the next request */
> +      WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
> +      /*
> +       * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
> +       * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
> +       * was empty. This interrupt is asserted on the endpoint for which the IN token
> +       * was received.
> +       */
> +      gDmaDescEp0->status.b.bs = 0x3;
> +      gDmaDescEp0->status.b.mtrf = 0;
> +      gDmaDescEp0->status.b.sr = 0;
> +      gDmaDescEp0->status.b.l = 1;
> +      gDmaDescEp0->status.b.ioc = 1;
> +      gDmaDescEp0->status.b.sp = 0;
> +      gDmaDescEp0->status.b.bytes = 64;
> +      gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
> +      gDmaDescEp0->status.b.sts = 0;
> +      gDmaDescEp0->status.b.bs = 0x0;
> +      WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
> +      // endpoint enable; clear NAK
> +      WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);
> +    }
> +
> +    EpInts = (READ_REG32 (DOEPINT1));
> +    if (EpInts) {
> +      WRITE_REG32 (DOEPINT1, EpInts);
> +      /* Transfer Completed Interrupt (XferCompl);Transfer completed */
> +      if (EpInts & DXEPINT_XFERCOMPL) {
> +
> +        UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;
> +        UINTN Len = 0;
> +
> +        ArmDataSynchronizationBarrier ();
> +        if (MATCH_CMD_LITERAL ("download", RxBuf)) {
> +          mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));
> +        } else {
> +          if (mNumDataBytes != 0) {
> +            mNumDataBytes -= Bytes;
> +          }
> +        }
> +
> +        mDataReceivedCallback (Bytes, RxBuf);
> +
> +        if (mNumDataBytes == 0) {
> +          Len = CMD_SIZE;
> +        } else if (mNumDataBytes > DATA_SIZE) {
> +          Len = DATA_SIZE;
> +        } else {
> +          Len = mNumDataBytes;
> +        }
> +
> +        EpRx (1, Len);
> +      }
> +    }
> +  }
> +
> +  //WRITE_REG32 clear ints
> +  WRITE_REG32 (GINTSTS, Ints);
> +}
> +
> +EFI_STATUS
> +DwUsbSend (
> +  IN        UINT8  EndpointIndex,
> +  IN        UINTN  Size,
> +  IN  CONST VOID  *Buffer
> +  )
> +{
> +    EpTx (EndpointIndex, Buffer, Size);
> +    return EFI_SUCCESS;
> +}
> +
> +STATIC
> +VOID
> +DwUsbInit (
> +  VOID
> +  )
> +{
> +  VOID     *Buf;
> +  UINT32   Data;
> +
> +  Buf = UncachedAllocatePages (16);
> +  gDmaDesc = Buf;
> +  gDmaDescEp0 = gDmaDesc + sizeof (dwc_otg_dev_dma_desc_t);
> +  gDmaDescIn = gDmaDescEp0 + sizeof (dwc_otg_dev_dma_desc_t);
> +  gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (dwc_otg_dev_dma_desc_t);
> +
> +  ZeroMem (gDmaDesc, sizeof (dwc_otg_dev_dma_desc_t));
> +  ZeroMem (gDmaDescEp0, sizeof (dwc_otg_dev_dma_desc_t));
> +  ZeroMem (gDmaDescIn, sizeof (dwc_otg_dev_dma_desc_t));
> +
> +  /*Reset usb controller.*/
> +  /* Wait for OTG AHB master idle */
> +  do {
> +    Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;
> +  } while (Data == 0);
> +
> +  /* OTG: Assert Software Reset */
> +  WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);
> +
> +  /* Wait for OTG to ack reset */
> +  while (READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST);
> +
> +  /* Wait for OTG AHB master idle */
> +  while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
> +
> +  WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);
> +  WRITE_REG32 (GRXFSIZ, RX_SIZE);
> +  WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);
> +  WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
> +  WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
> +  WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
> +  WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
> +  WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
> +  WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
> +  WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
> +  WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
> +  WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
> +  WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
> +  WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
> +  WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
> +  WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
> +  WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
> +  WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
> +
> +  /*
> +   * set Periodic TxFIFO Empty Level,
> +   * Non-Periodic TxFIFO Empty Level,
> +   * Enable DMA, Unmask Global Intr
> +   */
> +  WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);
> +
> +  /*select 8bit UTMI+, ULPI Inerface*/
> +  WRITE_REG32 (GUSBCFG, 0x2400);
> +
> +  /* Detect usb work mode,host or device? */
> +  do {
> +    Data = READ_REG32 (GINTSTS);
> +  } while (Data & GINTSTS_CURMODE_HOST);
> +  MicroSecondDelay (3);
> +
> +  /*Init global and device mode csr register.*/
> +  /*set Non-Zero-Length status out handshake */
> +  Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
> +  WRITE_REG32 (DCFG, Data);
> +
> +  /* Interrupt unmask: IN event, OUT event, bus reset */
> +  Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST;
> +  WRITE_REG32 (GINTMSK, Data);
> +
> +  do {
> +    Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE;
> +  } while (Data);
> +
> +  /* Clear any pending OTG Interrupts */
> +  WRITE_REG32 (GOTGINT, ~0);
> +  /* Clear any pending interrupts */
> +  WRITE_REG32 (GINTSTS, ~0);
> +  WRITE_REG32 (GINTMSK, ~0);
> +  Data = READ_REG32 (GOTGINT);
> +  Data &= ~0x3000;
> +  WRITE_REG32 (GOTGINT, Data);
> +
> +  /* endpoint settings cfg */
> +  ResetEndpoints ();
> +  MicroSecondDelay (1);
> +
> +  /* init finish. and ready to transfer data */
> +
> +  /* Soft Disconnect */
> +  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);
> +  MicroSecondDelay (10000);
> +
> +  /* Soft Reconnect */
> +  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +DwUsbStart (
> +  IN USB_DEVICE_DESCRIPTOR   *DeviceDescriptor,
> +  IN VOID                   **Descriptors,
> +  IN USB_DEVICE_RX_CALLBACK   RxCallback,
> +  IN USB_DEVICE_TX_CALLBACK   TxCallback
> +  )
> +{
> +  UINT8                    *Ptr;
> +  EFI_STATUS                Status;
> +  EFI_EVENT                 TimerEvent;
> +
> +  ASSERT (DeviceDescriptor != NULL);
> +  ASSERT (Descriptors[0] != NULL);
> +  ASSERT (RxCallback != NULL);
> +  ASSERT (TxCallback != NULL);
> +
> +  DwUsbInit();
> +
> +  mDeviceDescriptor = DeviceDescriptor;
> +  mDescriptors = Descriptors[0];
> +
> +  // Right now we just support one configuration
> +  ASSERT (mDeviceDescriptor->NumConfigurations == 1);
> +  mDeviceDescriptor->StrManufacturer = 1;
> +  mDeviceDescriptor->StrProduct = 2;
> +  mDeviceDescriptor->StrSerialNumber = 3;
> +  // ... and one interface
> +  mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
> +  ASSERT (mConfigDescriptor->NumInterfaces == 1);
> +
> +  Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
> +  mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
> +  Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
> +
> +  mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
> +
> +  mDataReceivedCallback = RxCallback;
> +  mDataSentCallback = TxCallback;
> +
> +  // Register a timer event so CheckInterupts gets called periodically
> +  Status = gBS->CreateEvent (
> +                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  CheckInterrupts,
> +                  NULL,
> +                  &TimerEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = gBS->SetTimer (
> +                  TimerEvent,
> +                  TimerPeriodic,
> +                  DW_INTERRUPT_POLL_PERIOD
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +USB_DEVICE_PROTOCOL mUsbDevice = {
> +  DwUsbStart,
> +  DwUsbSend
> +};
> +
> +
> +EFI_STATUS
> +EFIAPI
> +DwUsbEntryPoint (
> +  IN EFI_HANDLE                            ImageHandle,
> +  IN EFI_SYSTEM_TABLE                      *SystemTable
> +  )
> +{
> +  EFI_STATUS      Status;
> +
> +  Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = DwUsb->PhyInit(USB_DEVICE_MODE);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return gBS->InstallProtocolInterface (
> +                &ImageHandle,
> +                &gUsbDeviceProtocolGuid,
> +                EFI_NATIVE_INTERFACE,
> +                &mUsbDevice
> +                );
> +}
> diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
> new file mode 100644
> index 0000000..f991492
> --- /dev/null
> +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
> @@ -0,0 +1,46 @@
> +#/** @file
> +# Framework Module Development Environment Industry Standards
> +#
> +# This Package provides headers and libraries that conform to EFI/PI Industry standards.
> +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR>
> +# Copyright (c) 2015-2017, Linaro. All rights reserved.<BR>
> +#
> +#    This program and the accompanying materials are licensed and made available under
> +#    the terms and conditions of the BSD License which accompanies this distribution.
> +#    The full text of the license may be found at
> +#    http://opensource.org/licenses/bsd-license.php
> +#
> +#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> +  DEC_SPECIFICATION              = 0x00010019
> +  PACKAGE_NAME                   = OpenPlatformDriversUsbDwUsbDxePkg
> +  PACKAGE_GUID                   = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5
> +  PACKAGE_VERSION                = 0.1
> +
> +
> +################################################################################
> +#
> +# Include Section - list of Include Paths that are provided by this package.
> +#                   Comments are used for Keywords and Module Types.
> +#
> +# Supported Module Types:
> +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
> +#
> +################################################################################
> +
> +[Guids.common]
> +  gAndroidFastbootUsbGuid       = { 0xf6bec3fe, 0x88fb, 0x11e3, { 0xae, 0x84, 0xe7, 0x3b, 0x77, 0x56, 0x1c, 0x35 }}
> +  gDwUsbDxeTokenSpaceGuid       = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}
> +
> +[Protocols.common]
> +  gDwUsbProtocolGuid            = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
> +
> +[PcdsFixedAtBuild.common]
> +  # DwUsb Driver PCDs
> +  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001
> +  gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002
> diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.h b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h
> new file mode 100644
> index 0000000..7f909c3
> --- /dev/null
> +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h
> @@ -0,0 +1,627 @@
> +/** @file
> +
> +  Copyright (c) 2015-2017, Linaro. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef __DW_USB_DXE_H__
> +#define __DW_USB_DXE_H__
> +
> +#define DW_USB_BASE                     FixedPcdGet32 (PcdDwUsbDxeBaseAddress)
> +
> +#define READ_REG32(Offset)              MmioRead32 (DW_USB_BASE + Offset)
> +#define READ_REG16(Offset)              (UINT16)READ_REG32 (Offset)
> +#define WRITE_REG32(Offset, Val)        MmioWrite32 (DW_USB_BASE + Offset, Val)
> +#define WRITE_REG16(Offset, Val)        MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)
> +#define WRITE_REG8(Offset, Val)         MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)
> +
> +// Max packet size in bytes (For Full Speed USB 64 is the only valid value)
> +#define MAX_PACKET_SIZE_CONTROL         64
> +
> +#define MAX_PACKET_SIZE_BULK            512
> +
> +// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer
> +#define DW_NUM_ENDPOINTS                16
> +
> +// Endpoint Indexes
> +#define DW_EP0SETUP                     0x20
> +#define DW_EP0RX                        0x00
> +#define DW_EP0TX                        0x01
> +#define DW_EP1RX                        0x02
> +#define DW_EP1TX                        0x03
> +
> +// DcInterrupt bits
> +#define DW_DC_INTERRUPT_EP1TX           BIT13
> +#define DW_DC_INTERRUPT_EP1RX           BIT12
> +#define DW_DC_INTERRUPT_EP0TX           BIT11
> +#define DW_DC_INTERRUPT_EP0RX           BIT10
> +#define DW_DC_INTERRUPT_EP0SETUP        BIT8
> +#define DW_DC_INTERRUPT_VBUS            BIT7
> +#define DW_DC_INTERRUPT_DMA             BIT6
> +#define DW_DC_INTERRUPT_HS_STAT         BIT5
> +#define DW_DC_INTERRUPT_RESUME          BIT4
> +#define DW_DC_INTERRUPT_SUSP            BIT3
> +#define DW_DC_INTERRUPT_PSOF            BIT2
> +#define DW_DC_INTERRUPT_SOF             BIT1
> +#define DW_DC_INTERRUPT_BRESET          BIT0
> +// All valid peripheral controller int  rrupts
> +#define DW_DC_INTERRUPT_MASK            0x003FFFDFF
> +
> +#define DW_ADDRESS                      0x200
> +#define DW_ADDRESS_DEVEN                BIT7
> +
> +#define DW_MODE                         0x20C
> +#define DW_MODE_DATA_BUS_WIDTH          BIT8
> +#define DW_MODE_CLKAON                  BIT7
> +#define DW_MODE_SFRESET                 BIT4
> +#define DW_MODE_WKUPCS                  BIT2
> +
> +#define DW_ENDPOINT_MAX_PACKET_SIZE     0x204
> +
> +#define DW_ENDPOINT_TYPE                0x208
> +#define DW_ENDPOINT_TYPE_NOEMPKT        BIT4
> +#define DW_ENDPOINT_TYPE_ENABLE         BIT3
> +
> +#define DW_INTERRUPT_CONFIG             0x210
> +// Interrupt config value to only interrupt on ACK of IN and OUT tokens
> +#define DW_INTERRUPT_CONFIG_ACK_ONLY    (BIT2 | BIT5 | BIT6)
> +
> +#define DW_DC_INTERRUPT                 0x218
> +#define DW_DC_INTERRUPT_ENABLE          0x214
> +
> +#define DW_CTRL_FUNCTION                0x228
> +#define DW_CTRL_FUNCTION_VENDP          BIT3
> +#define DW_CTRL_FUNCTION_DSEN           BIT2
> +#define DW_CTRL_FUNCTION_STATUS         BIT1
> +
> +#define DW_DEVICE_UNLOCK                0x27C
> +#define DW_DEVICE_UNLOCK_MAGIC          0xAA37
> +
> +#define DW_SW_RESET_REG                 0x30C
> +#define DW_SW_RESET_ALL                 BIT0
> +
> +#define DW_DEVICE_ID                    0x370
> +
> +#define DW_OTG_CTRL_SET                 0x374
> +#define DW_OTG_CTRL_CLR                 (OTG_CTRL_SET + 2)
> +#define DW_OTG_CTRL_OTG_DISABLE         BIT10
> +#define DW_OTG_CTRL_VBUS_CHRG           BIT6
> +#define DW_OTG_CTRL_VBUS_DISCHRG        BIT5
> +#define DW_OTG_CTRL_DM_PULLDOWN         BIT2
> +#define DW_OTG_CTRL_DP_PULLDOWN         BIT1
> +#define DW_OTG_CTRL_DP_PULLUP           BIT0
> +
> +#define DW_OTG_STATUS                   0x378
> +#define DW_OTG_STATUS_B_SESS_END        BIT7
> +#define DW_OTG_STATUS_A_B_SESS_VLD      BIT1
> +
> +#define DW_OTG_INTERRUPT_LATCH_SET      0x37C
> +#define DW_OTG_INTERRUPT_LATCH_CLR      0x37E
> +#define DW_OTG_INTERRUPT_ENABLE_RISE    0x384
> +
> +#define DW_DMA_ENDPOINT_INDEX           0x258
> +
> +#define DW_ENDPOINT_INDEX               0x22c
> +#define DW_DATA_PORT                    0x220
> +#define DW_BUFFER_LENGTH                0x21c
> +
> +// Device ID Values
> +#define PHILLIPS_VENDOR_ID_VAL          0x04cc
> +#define DW_PRODUCT_ID_VAL               0x1761
> +#define DW_DEVICE_ID_VAL                ((ISP1761_PRODUCT_ID_VAL << 16) | \
> +                                         PHILLIPS_VENDOR_ID_VAL)
> +
> +#define DWC_OTG_BASE                    DW_USB_BASE
> +
> +#define USB_NUM_ENDPOINTS               2
> +#define MAX_EPS_CHANNELS                16
> +
> +#define BULK_OUT_EP                     1
> +#define BULK_IN_EP                      1
> +
> +#define RX_REQ_LEN                      512
> +#define MAX_PACKET_LEN                  512
> +
> +#define DATA_FIFO_CONFIG                0x0F801000
> +/* RX FIFO: 2048 bytes */
> +#define RX_SIZE                         0x00000200
> +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */
> +#define ENDPOINT_TX_SIZE                0x01000200
> +
> +/* EP1  TX FIFO: 1024 bytes. start address: 0x220 * 4. */
> +/* EP2  TX FIFO: 1024 bytes. start address: 0x320 * 4. */
> +/* EP3  TX FIFO: 1024 bytes. start address: 0x420 * 4. */
> +/* EP4  TX FIFO: 1024 bytes. start address: 0x520 * 4. */
> +/* EP5  TX FIFO: 128 bytes. start address: 0x620 * 4. */
> +/* EP6  TX FIFO: 128 bytes. start address: 0x640 * 4. */
> +/* EP7  TX FIFO: 128 bytes. start address: 0x660 * 4. */
> +/* EP8  TX FIFO: 128 bytes. start address: 0x680 * 4. */
> +/* EP9  TX FIFO: 128 bytes. start address: 0x6A0 * 4. */
> +/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */
> +/* EP11 TX FIFO: 128  bytes. start address: 0x6E0 * 4. */
> +/* EP12 TX FIFO: 128  bytes. start address: 0x700 * 4. */
> +/* EP13 TX FIFO: 128  bytes. start address: 0x720 * 4. */
> +/* EP14 TX FIFO: 128  bytes. start address: 0x740 * 4. */
> +/* EP15 TX FIFO: 128  bytes. start address: 0x760 * 4. */
> +
> +#define DATA_IN_ENDPOINT_TX_FIFO1       0x01000220
> +#define DATA_IN_ENDPOINT_TX_FIFO2       0x01000320
> +#define DATA_IN_ENDPOINT_TX_FIFO3       0x01000420
> +#define DATA_IN_ENDPOINT_TX_FIFO4       0x01000520
> +#define DATA_IN_ENDPOINT_TX_FIFO5       0x00200620
> +#define DATA_IN_ENDPOINT_TX_FIFO6       0x00200640
> +#define DATA_IN_ENDPOINT_TX_FIFO7       0x00200680
> +#define DATA_IN_ENDPOINT_TX_FIFO8       0x002006A0
> +#define DATA_IN_ENDPOINT_TX_FIFO9       0x002006C0
> +#define DATA_IN_ENDPOINT_TX_FIFO10      0x002006E0
> +#define DATA_IN_ENDPOINT_TX_FIFO11      0x00200700
> +#define DATA_IN_ENDPOINT_TX_FIFO12      0x00200720
> +#define DATA_IN_ENDPOINT_TX_FIFO13      0x00200740
> +#define DATA_IN_ENDPOINT_TX_FIFO14      0x00200760
> +#define DATA_IN_ENDPOINT_TX_FIFO15      0x00200F00
> +
> +/*DWC_OTG regsiter descriptor*/
> +/*Device mode CSR MAP*/
> +#define DEVICE_CSR_BASE                 0x800
> +/*Device mode CSR MAP*/
> +#define DEVICE_INEP_BASE                0x900
> +/*Device mode CSR MAP*/
> +#define DEVICE_OUTEP_BASE               0xB00
> +
> +/*** OTG LINK CORE REGISTERS ***/
> +/* Core Global Registers */
> +#define GOTGCTL                         0x000
> +#define GOTGINT                         0x004
> +#define GAHBCFG                         0x008
> +#define GAHBCFG_P_TXF_EMP_LVL           (1 << 8)
> +#define GAHBCFG_NP_TXF_EMP_LVL          (1 << 7)
> +#define GAHBCFG_DMA_EN                  (1 << 5)
> +#define GAHBCFG_GLBL_INTR_EN            (1 << 0)
> +#define GAHBCFG_CTRL_MASK               (GAHBCFG_P_TXF_EMP_LVL | \
> +                                         GAHBCFG_NP_TXF_EMP_LVL | \
> +                                         GAHBCFG_DMA_EN | \
> +                                         GAHBCFG_GLBL_INTR_EN)
> +
> +#define GUSBCFG                         0x00C
> +#define GRSTCTL                         0x010
> +#define GRSTCTL_AHBIDLE                 (1 << 31)
> +#define GRSTCTL_CSFTRST                 (1 << 0)
> +
> +#define GINTSTS                         0x014
> +#define GINTSTS_WKUPINT                 BIT31
> +#define GINTSTS_SESSREGINT              BIT30
> +#define GINTSTS_DISCONNINT              BIT29
> +#define GINTSTS_CONIDSTSCHNG            BIT28
> +#define GINTSTS_LPMTRANRCVD             BIT27
> +#define GINTSTS_PTXFEMP                 BIT26
> +#define GINTSTS_HCHINT                  BIT25
> +#define GINTSTS_PRTINT                  BIT24
> +#define GINTSTS_RESETDET                BIT23
> +#define GINTSTS_FET_SUSP                BIT22
> +#define GINTSTS_INCOMPL_IP              BIT21
> +#define GINTSTS_INCOMPL_SOIN            BIT20
> +#define GINTSTS_OEPINT                  BIT19
> +#define GINTSTS_IEPINT                  BIT18
> +#define GINTSTS_EPMIS                   BIT17
> +#define GINTSTS_RESTOREDONE             BIT16
> +#define GINTSTS_EOPF                    BIT15
> +#define GINTSTS_ISOUTDROP               BIT14
> +#define GINTSTS_ENUMDONE                BIT13
> +#define GINTSTS_USBRST                  BIT12
> +#define GINTSTS_USBSUSP                 BIT11
> +#define GINTSTS_ERLYSUSP                BIT10
> +#define GINTSTS_I2CINT                  BIT9
> +#define GINTSTS_ULPI_CK_INT             BIT8
> +#define GINTSTS_GOUTNAKEFF              BIT7
> +#define GINTSTS_GINNAKEFF               BIT6
> +#define GINTSTS_NPTXFEMP                BIT5
> +#define GINTSTS_RXFLVL                  BIT4
> +#define GINTSTS_SOF                     BIT3
> +#define GINTSTS_OTGINT                  BIT2
> +#define GINTSTS_MODEMIS                 BIT1
> +#define GINTSTS_CURMODE_HOST            BIT0
> +
> +#define GINTMSK                         0x018
> +#define GRXSTSR                         0x01C
> +#define GRXSTSP                         0x020
> +#define GRXFSIZ                         0x024
> +#define GNPTXFSIZ                       0x028
> +#define GNPTXSTS                        0x02C
> +
> +#define GHWCFG1                         0x044
> +#define GHWCFG2                         0x048
> +#define GHWCFG3                         0x04c
> +#define GHWCFG4                         0x050
> +#define GLPMCFG                         0x054
> +
> +#define GDFIFOCFG                       0x05c
> +
> +#define HPTXFSIZ                        0x100
> +#define DIEPTXF(x)                      (0x100 + 4 * (x))
> +#define DIEPTXF1                        0x104
> +#define DIEPTXF2                        0x108
> +#define DIEPTXF3                        0x10C
> +#define DIEPTXF4                        0x110
> +#define DIEPTXF5                        0x114
> +#define DIEPTXF6                        0x118
> +#define DIEPTXF7                        0x11C
> +#define DIEPTXF8                        0x120
> +#define DIEPTXF9                        0x124
> +#define DIEPTXF10                       0x128
> +#define DIEPTXF11                       0x12C
> +#define DIEPTXF12                       0x130
> +#define DIEPTXF13                       0x134
> +#define DIEPTXF14                       0x138
> +#define DIEPTXF15                       0x13C
> +
> +/*** HOST MODE REGISTERS ***/
> +/* Host Global Registers */
> +#define HCFG                            0x400
> +#define HFIR                            0x404
> +#define HFNUM                           0x408
> +#define HPTXSTS                         0x410
> +#define HAINT                           0x414
> +#define HAINTMSK                        0x418
> +
> +/* Host Port Control and Status Registers */
> +#define HPRT                            0x440
> +
> +/* Host Channel-Specific Registers */
> +#define HCCHAR(x)                       (0x500 + 0x20 * (x))
> +#define HCSPLT(x)                       (0x504 + 0x20 * (x))
> +#define HCINT(x)                        (0x508 + 0x20 * (x))
> +#define HCINTMSK(x)                     (0x50C + 0x20 * (x))
> +#define HCTSIZ(x)                       (0x510 + 0x20 * (x))
> +#define HCDMA(x)                        (0x514 + 0x20 * (x))
> +#define HCCHAR0                         0x500
> +#define HCSPLT0                         0x504
> +#define HCINT0                          0x508
> +#define HCINTMSK0                       0x50C
> +#define HCTSIZ0                         0x510
> +#define HCDMA0                          0x514
> +#define HCCHAR1                         0x520
> +#define HCSPLT1                         0x524
> +#define HCINT1                          0x528
> +#define HCINTMSK1                       0x52C
> +#define HCTSIZ1                         0x530
> +#define HCDMA1                          0x534
> +#define HCCHAR2                         0x540
> +#define HCSPLT2                         0x544
> +#define HCINT2                          0x548
> +#define HCINTMSK2                       0x54C
> +#define HCTSIZ2                         0x550
> +#define HCDMA2                          0x554
> +#define HCCHAR3                         0x560
> +#define HCSPLT3                         0x564
> +#define HCINT3                          0x568
> +#define HCINTMSK3                       0x56C
> +#define HCTSIZ3                         0x570
> +#define HCDMA3                          0x574
> +#define HCCHAR4                         0x580
> +#define HCSPLT4                         0x584
> +#define HCINT4                          0x588
> +#define HCINTMSK4                       0x58C
> +#define HCTSIZ4                         0x590
> +#define HCDMA4                          0x594
> +#define HCCHAR5                         0x5A0
> +#define HCSPLT5                         0x5A4
> +#define HCINT5                          0x5A8
> +#define HCINTMSK5                       0x5AC
> +#define HCTSIZ5                         0x5B0
> +#define HCDMA5                          0x5B4
> +#define HCCHAR6                         0x5C0
> +#define HCSPLT6                         0x5C4
> +#define HCINT6                          0x5C8
> +#define HCINTMSK6                       0x5CC
> +#define HCTSIZ6                         0x5D0
> +#define HCDMA6                          0x5D4
> +#define HCCHAR7                         0x5E0
> +#define HCSPLT7                         0x5E4
> +#define HCINT7                          0x5E8
> +#define HCINTMSK7                       0x5EC
> +#define HCTSIZ7                         0x5F0
> +#define HCDMA7                          0x5F4
> +#define HCCHAR8                         0x600
> +#define HCSPLT8                         0x604
> +#define HCINT8                          0x608
> +#define HCINTMSK8                       0x60C
> +#define HCTSIZ8                         0x610
> +#define HCDMA8                          0x614
> +#define HCCHAR9                         0x620
> +#define HCSPLT9                         0x624
> +#define HCINT9                          0x628
> +#define HCINTMSK9                       0x62C
> +#define HCTSIZ9                         0x630
> +#define HCDMA9                          0x634
> +#define HCCHAR10                        0x640
> +#define HCSPLT10                        0x644
> +#define HCINT10                         0x648
> +#define HCINTMSK10                      0x64C
> +#define HCTSIZ10                        0x650
> +#define HCDMA10                         0x654
> +#define HCCHAR11                        0x660
> +#define HCSPLT11                        0x664
> +#define HCINT11                         0x668
> +#define HCINTMSK11                      0x66C
> +#define HCTSIZ11                        0x670
> +#define HCDMA11                         0x674
> +#define HCCHAR12                        0x680
> +#define HCSPLT12                        0x684
> +#define HCINT12                         0x688
> +#define HCINTMSK12                      0x68C
> +#define HCTSIZ12                        0x690
> +#define HCDMA12                         0x694
> +#define HCCHAR13                        0x6A0
> +#define HCSPLT13                        0x6A4
> +#define HCINT13                         0x6A8
> +#define HCINTMSK13                      0x6AC
> +#define HCTSIZ13                        0x6B0
> +#define HCDMA13                         0x6B4
> +#define HCCHAR14                        0x6C0
> +#define HCSPLT14                        0x6C4
> +#define HCINT14                         0x6C8
> +#define HCINTMSK14                      0x6CC
> +#define HCTSIZ14                        0x6D0
> +#define HCDMA14                         0x6D4
> +#define HCCHAR15                        0x6E0
> +#define HCSPLT15                        0x6E4
> +#define HCINT15                         0x6E8
> +#define HCINTMSK15                      0x6EC
> +#define HCTSIZ15                        0x6F0
> +#define HCDMA15                         0x6F4
> +
> +/*** DEVICE MODE REGISTERS ***/
> +/* Device Global Registers */
> +#define DCFG                            0x800
> +#define DCFG_DESCDMA                    BIT23
> +#define DCFG_EPMISCNT_MASK              (0x1F << 18)
> +#define DCFG_EPMISCNT_SHIFT             18
> +#define DCFG_DEVADDR_MASK               (0x7F << 4)
> +#define DCFG_DEVADDR_SHIFT              4
> +#define DCFG_DEVADDR(x)                 (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK)
> +#define DCFG_NZ_STS_OUT_HSHK            BIT2
> +
> +#define DCTL                            0x804
> +#define DCTL_PWRONPRGDONE               BIT11
> +#define DCTL_GNPINNAKSTS                BIT2
> +#define DCTL_SFTDISCON                  BIT1
> +
> +#define DSTS                            0x808
> +#define DIEPMSK                         0x810
> +#define DOEPMSK                         0x814
> +
> +#define DXEPMSK_TIMEOUTMSK              BIT3
> +#define DXEPMSK_AHBERMSK                BIT2
> +#define DXEPMSK_XFERCOMPLMSK            BIT0
> +
> +#define DAINT                           0x818
> +#define DAINTMSK                        0x81C
> +
> +#define DAINTMSK_OUTEPMSK_SHIFT         16
> +#define DAINTMSK_INEPMSK_SHIFT          0
> +
> +#define DTKNQR1                         0x820
> +#define DTKNQR2                         0x824
> +#define DVBUSDIS                        0x828
> +#define DVBUSPULSE                      0x82C
> +#define DTHRCTL                         0x830
> +
> +/* Device Logical IN Endpoint-Specific Registers */
> +#define DIEPCTL(x)                      (0x900 + 0x20 * (x))
> +#define DIEPINT(x)                      (0x908 + 0x20 * (x))
> +#define DIEPTSIZ(x)                     (0x910 + 0x20 * (x))
> +#define DIEPDMA(x)                      (0x914 + 0x20 * (x))
> +#define DTXFSTS(x)                      (0x918 + 0x20 * (x))
> +
> +#define DIEPCTL0                        0x900
> +#define DIEPINT0                        0x908
> +#define DIEPTSIZ0                       0x910
> +#define DIEPDMA0                        0x914
> +#define DIEPCTL1                        0x920
> +#define DIEPINT1                        0x928
> +#define DIEPTSIZ1                       0x930
> +#define DIEPDMA1                        0x934
> +#define DIEPCTL2                        0x940
> +#define DIEPINT2                        0x948
> +#define DIEPTSIZ2                       0x950
> +#define DIEPDMA2                        0x954
> +#define DIEPCTL3                        0x960
> +#define DIEPINT3                        0x968
> +#define DIEPTSIZ3                       0x970
> +#define DIEPDMA3                        0x974
> +#define DIEPCTL4                        0x980
> +#define DIEPINT4                        0x988
> +#define DIEPTSIZ4                       0x990
> +#define DIEPDMA4                        0x994
> +#define DIEPCTL5                        0x9A0
> +#define DIEPINT5                        0x9A8
> +#define DIEPTSIZ5                       0x9B0
> +#define DIEPDMA5                        0x9B4
> +#define DIEPCTL6                        0x9C0
> +#define DIEPINT6                        0x9C8
> +#define DIEPTSIZ6                       0x9D0
> +#define DIEPDMA6                        0x9D4
> +#define DIEPCTL7                        0x9E0
> +#define DIEPINT7                        0x9E8
> +#define DIEPTSIZ7                       0x9F0
> +#define DIEPDMA7                        0x9F4
> +#define DIEPCTL8                        0xA00
> +#define DIEPINT8                        0xA08
> +#define DIEPTSIZ8                       0xA10
> +#define DIEPDMA8                        0xA14
> +#define DIEPCTL9                        0xA20
> +#define DIEPINT9                        0xA28
> +#define DIEPTSIZ9                       0xA30
> +#define DIEPDMA9                        0xA34
> +#define DIEPCTL10                       0xA40
> +#define DIEPINT10                       0xA48
> +#define DIEPTSIZ10                      0xA50
> +#define DIEPDMA10                       0xA54
> +#define DIEPCTL11                       0xA60
> +#define DIEPINT11                       0xA68
> +#define DIEPTSIZ11                      0xA70
> +#define DIEPDMA11                       0xA74
> +#define DIEPCTL12                       0xA80
> +#define DIEPINT12                       0xA88
> +#define DIEPTSIZ12                      0xA90
> +#define DIEPDMA12                       0xA94
> +#define DIEPCTL13                       0xAA0
> +#define DIEPINT13                       0xAA8
> +#define DIEPTSIZ13                      0xAB0
> +#define DIEPDMA13                       0xAB4
> +#define DIEPCTL14                       0xAC0
> +#define DIEPINT14                       0xAC8
> +#define DIEPTSIZ14                      0xAD0
> +#define DIEPDMA14                       0xAD4
> +#define DIEPCTL15                       0xAE0
> +#define DIEPINT15                       0xAE8
> +#define DIEPTSIZ15                      0xAF0
> +#define DIEPDMA15                       0xAF4
> +
> +/* Device Logical OUT Endpoint-Specific Registers */
> +#define DOEPCTL(x)                      (0xB00 + 0x20 * (x))
> +#define DOEPINT(x)                      (0xB08 + 0x20 * (x))
> +#define DOEPTSIZ(x)                     (0xB10 + 0x20 * (x))
> +
> +#define DXEPINT_EPDISBLD                BIT1
> +#define DXEPINT_XFERCOMPL               BIT0
> +
> +#define DXEPTSIZ_SUPCNT(x)              (((x) & 0x3) << 29)
> +#define DXEPTSIZ_PKTCNT(x)              (((x) & 0x3) << 19)
> +#define DXEPTSIZ_XFERSIZE(x)            ((x) & 0x7F)
> +
> +#define DOEPDMA(x)                      (0xB14 + 0x20 * (x))
> +#define DOEPCTL0                        0xB00
> +#define DOEPINT0                        0xB08
> +#define DOEPTSIZ0                       0xB10
> +#define DOEPDMA0                        0xB14
> +#define DOEPCTL1                        0xB20
> +#define DOEPINT1                        0xB28
> +#define DOEPTSIZ1                       0xB30
> +#define DOEPDMA1                        0xB34
> +#define DOEPCTL2                        0xB40
> +#define DOEPINT2                        0xB48
> +#define DOEPTSIZ2                       0xB50
> +#define DOEPDMA2                        0xB54
> +#define DOEPCTL3                        0xB60
> +#define DOEPINT3                        0xB68
> +#define DOEPTSIZ3                       0xB70
> +#define DOEPDMA3                        0xB74
> +#define DOEPCTL4                        0xB80
> +#define DOEPINT4                        0xB88
> +#define DOEPTSIZ4                       0xB90
> +#define DOEPDMA4                        0xB94
> +#define DOEPCTL5                        0xBA0
> +#define DOEPINT5                        0xBA8
> +#define DOEPTSIZ5                       0xBB0
> +#define DOEPDMA5                        0xBB4
> +#define DOEPCTL6                        0xBC0
> +#define DOEPINT6                        0xBC8
> +#define DOEPTSIZ6                       0xBD0
> +#define DOEPDMA6                        0xBD4
> +#define DOEPCTL7                        0xBE0
> +#define DOEPINT7                        0xBE8
> +#define DOEPTSIZ7                       0xBF0
> +#define DOEPDMA7                        0xBF4
> +#define DOEPCTL8                        0xC00
> +#define DOEPINT8                        0xC08
> +#define DOEPTSIZ8                       0xC10
> +#define DOEPDMA8                        0xC14
> +#define DOEPCTL9                        0xC20
> +#define DOEPINT9                        0xC28
> +#define DOEPTSIZ9                       0xC30
> +#define DOEPDMA9                        0xC34
> +#define DOEPCTL10                       0xC40
> +#define DOEPINT10                       0xC48
> +#define DOEPTSIZ10                      0xC50
> +#define DOEPDMA10                       0xC54
> +#define DOEPCTL11                       0xC60
> +#define DOEPINT11                       0xC68
> +#define DOEPTSIZ11                      0xC70
> +#define DOEPDMA11                       0xC74
> +#define DOEPCTL12                       0xC80
> +#define DOEPINT12                       0xC88
> +#define DOEPTSIZ12                      0xC90
> +#define DOEPDMA12                       0xC94
> +#define DOEPCTL13                       0xCA0
> +#define DOEPINT13                       0xCA8
> +#define DOEPTSIZ13                      0xCB0
> +#define DOEPDMA13                       0xCB4
> +#define DOEPCTL14                       0xCC0
> +#define DOEPINT14                       0xCC8
> +#define DOEPTSIZ14                      0xCD0
> +#define DOEPDMA14                       0xCD4
> +#define DOEPCTL15                       0xCE0
> +#define DOEPINT15                       0xCE8
> +#define DOEPTSIZ15                      0xCF0
> +#define DOEPDMA15                       0xCF4
> +
> +#define DXEPCTL_EPENA                   BIT31
> +#define DXEPCTL_SNAK                    BIT27
> +#define DXEPCTL_CNAK                    BIT26
> +#define DXEPCTL_STALL                   BIT21
> +#define DXEPCTL_EPTYPE_MASK             (BIT19 | BIT18)
> +#define DXEPCTL_NAKSTS                  BIT17
> +#define DXEPCTL_USBACTEP                BIT15
> +#define DXEPCTL_MPS_MASK                0x7FF
> +
> +/* Power and Clock Gating Register */
> +#define PCGCCTL                         0xE00
> +
> +#define EP0FIFO                         0x1000
> +
> +/**
> + * This union represents the bit fields in the DMA Descriptor
> + * status quadlet. Read the quadlet into the <i>d32</i> member then
> + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
> + * <i>b_iso_in</i> elements.
> + */
> +typedef union {
> +  /** raw register data */
> +  UINT32 d32;
> +    /** quadlet bits */
> +  struct {
> +    /** Received number of bytes */
> +    unsigned bytes:16;
> +    /** NAK bit - only for OUT EPs */
> +    unsigned nak:1;
> +    unsigned reserved17_22:6;
> +    /** Multiple Transfer - only for OUT EPs */
> +    unsigned mtrf:1;
> +    /** Setup Packet received - only for OUT EPs */
> +    unsigned sr:1;
> +    /** Interrupt On Complete */
> +    unsigned ioc:1;
> +    /** Short Packet */
> +    unsigned sp:1;
> +    /** Last */
> +    unsigned l:1;
> +    /** Receive Status */
> +    unsigned sts:2;
> +    /** Buffer Status */
> +    unsigned bs:2;
> +  } b;
> +} dev_dma_desc_sts_t;
> +
> +/**
> + * DMA Descriptor structure
> + *
> + * DMA Descriptor structure contains two quadlets:
> + * Status quadlet and Data buffer pointer.
> + */
> +typedef struct {
> +  /** DMA Descriptor status quadlet */
> +  dev_dma_desc_sts_t status;
> +  /** DMA Descriptor data buffer pointer */
> +  UINT32 buf;
> +} dwc_otg_dev_dma_desc_t;
> +
> +#endif //ifndef __DW_USB_DXE_H__
> diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf
> new file mode 100644
> index 0000000..0ac12c1
> --- /dev/null
> +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf
> @@ -0,0 +1,52 @@
> +#/** @file
> +#
> +#  Copyright (c) 2015-2017, Linaro. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution. The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010019
> +  BASE_NAME                      = DwUsbDxe
> +  FILE_GUID                      = 72d78ea6-4dee-11e3-8100-f3842a48d0a0
> +  MODULE_TYPE                    = UEFI_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DwUsbEntryPoint
> +
> +[Sources.common]
> +  DwUsbDxe.c
> +
> +[LibraryClasses]
> +  ArmLib
> +  DebugLib
> +  IoLib
> +  MemoryAllocationLib
> +  TimerLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UncachedMemoryAllocationLib
> +  CacheMaintenanceLib
> +
> +[Protocols]
> +  gEfiDriverBindingProtocolGuid
> +  gUsbDeviceProtocolGuid
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
> +
> +[Pcd]
> +  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress
> +
> +[Depex]
> +  TRUE
> diff --git a/Include/Protocol/DwUsb.h b/Include/Protocol/DwUsb.h
> new file mode 100644
> index 0000000..040e126
> --- /dev/null
> +++ b/Include/Protocol/DwUsb.h
> @@ -0,0 +1,81 @@
> +/** @file
> +
> +  Copyright (c) 2015-2017, Linaro. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef __DW_USB_H__
> +#define __DW_USB_H__
> +
> +//
> +// Protocol GUID
> +//
> +#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
> +
> +//
> +// Protocol interface structure
> +//
> +typedef struct _DW_USB_PROTOCOL  DW_USB_PROTOCOL;
> +
> +#define USB_HOST_MODE                 0
> +#define USB_DEVICE_MODE               1
> +#define USB_CABLE_NOT_ATTACHED        2
> +
> +#define LANG_LENGTH                   8
> +#define MANU_FACTURER_STRING_LENGTH   32
> +#define PRODUCT_STRING_LENGTH         32
> +#define SERIAL_STRING_LENGTH          17
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DW_USB_GET_LANG) (
> +  OUT CHAR16                           *Lang,
> +  OUT UINT8                            *Length
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DW_USB_GET_MANU_FACTURER) (
> +  OUT CHAR16                           *ManuFacturer,
> +  OUT UINT8                            *Length
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DW_USB_GET_PRODUCT) (
> +  OUT CHAR16                           *Product,
> +  OUT UINT8                            *Length
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DW_USB_GET_SERIAL_NO) (
> +  OUT CHAR16                           *SerialNo,
> +  OUT UINT8                            *Length
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DW_USB_PHY_INIT) (
> +  IN UINT8                             Mode
> +  );
> +
> +struct _DW_USB_PROTOCOL {
> +  DW_USB_GET_LANG                      GetLang;
> +  DW_USB_GET_MANU_FACTURER             GetManuFacturer;
> +  DW_USB_GET_PRODUCT                   GetProduct;
> +  DW_USB_GET_SERIAL_NO                 GetSerialNo;
> +  DW_USB_PHY_INIT                      PhyInit;
> +};
> +
> +extern EFI_GUID gDwUsbProtocolGuid;
> +
> +#endif
> -- 
> 2.7.4
>
diff mbox series

Patch

diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c
new file mode 100644
index 0000000..bdd8405
--- /dev/null
+++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c
@@ -0,0 +1,796 @@ 
+/** @file
+
+  Copyright (c) 2015-2017, Linaro. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Usb.h>
+#include <Library/ArmLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Protocol/DwUsb.h>
+#include <Protocol/UsbDevice.h>
+
+#include "DwUsbDxe.h"
+
+#define USB_TYPE_LENGTH               16
+#define USB_BLOCK_HIGH_SPEED_SIZE     512
+#define DATA_SIZE                     32768
+#define CMD_SIZE                      512
+#define MATCH_CMD_LITERAL(Cmd, Buf)   !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
+
+// The time between interrupt polls, in units of 100 nanoseconds
+// 10 Microseconds
+#define DW_INTERRUPT_POLL_PERIOD      10000
+
+EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
+
+STATIC dwc_otg_dev_dma_desc_t *gDmaDesc,*gDmaDescEp0,*gDmaDescIn;
+STATIC USB_DEVICE_REQUEST *gCtrlReq;
+STATIC VOID *RxBuf;
+STATIC UINTN RxDescBytes = 0;
+STATIC UINTN mNumDataBytes;
+
+STATIC DW_USB_PROTOCOL          *DwUsb;
+
+STATIC USB_DEVICE_DESCRIPTOR    *mDeviceDescriptor;
+
+// The config descriptor, interface descriptor, and endpoint descriptors in a
+// buffer (in that order)
+STATIC VOID                     *mDescriptors;
+// Convenience pointers to those descriptors inside the buffer:
+STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor;
+STATIC USB_CONFIG_DESCRIPTOR    *mConfigDescriptor;
+STATIC USB_ENDPOINT_DESCRIPTOR  *mEndpointDescriptors;
+
+STATIC USB_DEVICE_RX_CALLBACK   mDataReceivedCallback;
+STATIC USB_DEVICE_TX_CALLBACK   mDataSentCallback;
+
+
+/* To detect which mode was run, high speed or full speed */
+STATIC
+UINTN
+UsbDrvPortSpeed (
+  VOID
+  )
+{
+  /*
+  * 2'b00: High speed (PHY clock is running at 30 or 60 MHz)
+  */
+  UINT32          Val = READ_REG32 (DSTS) & 2;
+  return (!Val);
+}
+
+STATIC
+VOID
+ResetEndpoints (
+  VOID
+  )
+{
+  /* EP0 IN ACTIVE NEXT=1 */
+  WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);
+
+  /* EP0 OUT ACTIVE */
+  WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP);
+
+  /* Clear any pending OTG Interrupts */
+  WRITE_REG32 (GOTGINT, ~0);
+
+  /* Clear any pending interrupts */
+  WRITE_REG32 (GINTSTS, ~0);
+  WRITE_REG32 (DIEPINT0, ~0);
+  WRITE_REG32 (DOEPINT0, ~0);
+  WRITE_REG32 (DIEPINT1, ~0);
+  WRITE_REG32 (DOEPINT1, ~0);
+
+  /* IN EP interrupt mask */
+  WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
+  /* OUT EP interrupt mask */
+  WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
+  /* Enable interrupts on Ep0 */
+  WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT));
+
+  /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
+  WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
+
+  //notes that:the compulsive conversion is expectable.
+  gDmaDescEp0->status.b.bs = 0x3;
+  gDmaDescEp0->status.b.mtrf = 0;
+  gDmaDescEp0->status.b.sr = 0;
+  gDmaDescEp0->status.b.l = 1;
+  gDmaDescEp0->status.b.ioc = 1;
+  gDmaDescEp0->status.b.sp = 0;
+  gDmaDescEp0->status.b.bytes = 64;
+  gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
+  gDmaDescEp0->status.b.sts = 0;
+  gDmaDescEp0->status.b.bs = 0x0;
+  WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
+  /* EP0 OUT ENABLE CLEARNAK */
+  WRITE_REG32 (DOEPCTL0, (READ_REG32 (DOEPCTL0) | DXEPCTL_EPENA | DXEPCTL_CNAK));
+}
+
+STATIC
+VOID
+EpTx (
+  IN UINT8          Ep,
+  IN CONST VOID    *Ptr,
+  IN UINTN          Len
+  )
+{
+    UINT32          BlockSize;
+    UINT32          Packets;
+
+    /* EPx OUT ACTIVE */
+    WRITE_REG32 (DIEPCTL (Ep), (READ_REG32 (DIEPCTL (Ep))) | DXEPCTL_USBACTEP);
+    if (!Ep) {
+        BlockSize = 64;
+    } else {
+        BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
+    }
+    Packets = (Len + BlockSize - 1) / BlockSize;
+
+    if (!Len) {
+      /* send one empty packet */
+      gDmaDescIn->status.b.bs = 0x3;
+      gDmaDescIn->status.b.l = 1;
+      gDmaDescIn->status.b.ioc = 1;
+      gDmaDescIn->status.b.sp = 1;
+      gDmaDescIn->status.b.bytes = 0;
+      gDmaDescIn->buf = 0;
+      gDmaDescIn->status.b.sts = 0;
+      gDmaDescIn->status.b.bs = 0x0;
+
+      WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn));             // DMA Address (DMAAddr) is zero
+    } else {
+      WRITE_REG32 (DIEPTSIZ (Ep), Len | (Packets << 19));
+
+      //flush cache
+      WriteBackDataCacheRange ((VOID *)Ptr, Len);
+
+      gDmaDescIn->status.b.bs = 0x3;
+      gDmaDescIn->status.b.l = 1;
+      gDmaDescIn->status.b.ioc = 1;
+      gDmaDescIn->status.b.sp = 1;
+      gDmaDescIn->status.b.bytes = Len;
+      gDmaDescIn->buf = (UINT32)((UINTN)Ptr);
+      gDmaDescIn->status.b.sts = 0;
+      gDmaDescIn->status.b.bs = 0x0;
+      WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn));         // Ptr is DMA address
+    }
+    ArmDataSynchronizationBarrier ();
+    /* epena & cnak */
+    WRITE_REG32 (DIEPCTL (Ep), READ_REG32 (DIEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);
+}
+
+STATIC
+VOID
+EpRx (
+  IN UINTN            Ep,
+  IN UINTN            Len
+  )
+{
+  /* EPx UNSTALL */
+  WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & (~DXEPCTL_STALL)));
+  /* EPx OUT ACTIVE */
+  WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_USBACTEP));
+
+  if (Len >= DATA_SIZE) {
+    RxDescBytes = DATA_SIZE;
+  } else {
+    RxDescBytes = Len;
+  }
+
+  RxBuf = AllocatePool (DATA_SIZE);
+  ASSERT (RxBuf != NULL);
+
+  InvalidateDataCacheRange (RxBuf, Len);
+
+  gDmaDesc->status.b.bs = 0x3;
+  gDmaDesc->status.b.mtrf = 0;
+  gDmaDesc->status.b.sr = 0;
+  gDmaDesc->status.b.l = 1;
+  gDmaDesc->status.b.ioc = 1;
+  gDmaDesc->status.b.sp = 0;
+  gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;
+  gDmaDesc->buf = (UINT32)((UINTN)RxBuf);
+  gDmaDesc->status.b.sts = 0;
+  gDmaDesc->status.b.bs = 0x0;
+
+  ArmDataSynchronizationBarrier ();
+  WRITE_REG32 (DOEPDMA (Ep), (UINT32)((UINTN)gDmaDesc));
+  /* EPx OUT ENABLE CLEARNAK */
+  WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK));
+}
+
+STATIC
+EFI_STATUS
+HandleGetDescriptor (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  UINT8       DescriptorType;
+  UINTN       ResponseSize;
+  VOID       *ResponseData;
+  EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;
+  UINTN                             DescriptorSize;
+
+  ResponseSize = 0;
+  ResponseData = NULL;
+
+  // Pretty confused if bmRequestType is anything but this:
+  ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
+
+  // Choose the response
+  DescriptorType = Request->Value >> 8;
+  switch (DescriptorType) {
+  case USB_DESC_TYPE_DEVICE:
+    DEBUG ((DEBUG_INFO, "USB: Got a request for device descriptor\n"));
+    ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
+    ResponseData = mDeviceDescriptor;
+    break;
+  case USB_DESC_TYPE_CONFIG:
+    DEBUG ((DEBUG_INFO, "USB: Got a request for config descriptor\n"));
+    ResponseSize = mConfigDescriptor->TotalLength;
+    ResponseData = mDescriptors;
+    break;
+  case USB_DESC_TYPE_STRING:
+    DEBUG ((DEBUG_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
+    switch (Request->Value & 0xff) {
+    case 0:
+      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
+                       LANG_LENGTH * sizeof (CHAR16) + 1;
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      ASSERT (Descriptor != NULL);
+      Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
+      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+      DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
+      ResponseSize = Descriptor->Length;
+      ResponseData = Descriptor;
+      break;
+    case 1:
+      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
+                       MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16) + 1;
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      ASSERT (Descriptor != NULL);
+      Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
+      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+      DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
+      ResponseSize = Descriptor->Length;
+      ResponseData = Descriptor;
+      break;
+    case 2:
+      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
+                       PRODUCT_STRING_LENGTH * sizeof (CHAR16) + 1;
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      ASSERT (Descriptor != NULL);
+      Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
+      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+      DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
+      ResponseSize = Descriptor->Length;
+      ResponseData = Descriptor;
+      break;
+    case 3:
+      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
+                       SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      ASSERT (Descriptor != NULL);
+      Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
+      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+      DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
+      ResponseSize = Descriptor->Length;
+      ResponseData = Descriptor;
+      break;
+    }
+    break;
+  default:
+    DEBUG ((DEBUG_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
+    break;
+  }
+
+  // Send the response
+  if (ResponseData) {
+    ASSERT (ResponseSize != 0);
+
+    if (Request->Length < ResponseSize) {
+      // Truncate response
+      ResponseSize = Request->Length;
+    } else if (Request->Length > ResponseSize) {
+      DEBUG ((DEBUG_INFO, "USB: Info: ResponseSize < wLength\n"));
+    }
+
+    EpTx (0, ResponseData, ResponseSize);
+  }
+  if (Descriptor) {
+    FreePool (Descriptor);
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+HandleSetAddress (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  // Pretty confused if bmRequestType is anything but this:
+  ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
+  DEBUG ((DEBUG_INFO, "USB: Setting address to %d\n", Request->Value));
+  ResetEndpoints ();
+
+  WRITE_REG32 (DCFG, (READ_REG32 (DCFG) & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(Request->Value));
+  EpTx (0, 0, 0);
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+UINTN
+UsbDrvRequestEndpoint (
+  IN UINTN           Type,
+  IN UINTN           Dir
+  )
+{
+  UINTN              Ep = 1;
+  UINTN              Ret, NewBits;
+
+  Ret = Ep | Dir;
+  NewBits = (Type << 18) | 0x10000000;
+
+  /*
+   * (Type << 18):Endpoint Type (EPType)
+   * 0x10000000:Endpoint Enable (EPEna)
+   * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
+   * (ep<<22):TxFIFO Number (TxFNum)
+   * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
+   */
+  if (Dir) {  // IN: to host
+    WRITE_REG32 (DIEPCTL (Ep), ((READ_REG32 (DIEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits | (Ep << 22) | DXEPCTL_NAKSTS);
+  } else {    // OUT: to device
+    WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits);
+  }
+
+  return Ret;
+}
+
+STATIC
+EFI_STATUS
+HandleSetConfiguration (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
+
+  // Cancel all transfers
+  ResetEndpoints ();
+
+  UsbDrvRequestEndpoint (2, 0);
+  UsbDrvRequestEndpoint (2, 0x80);
+
+  WRITE_REG32 (DIEPCTL1, (READ_REG32 (DIEPCTL1)) | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);
+
+  /* Enable interrupts on all endpoints */
+  WRITE_REG32 (DAINTMSK, ~0);
+
+  EpRx (1, CMD_SIZE);
+  EpTx (0, 0, 0);
+  return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+HandleDeviceRequest (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  EFI_STATUS  Status;
+
+  switch (Request->Request) {
+  case USB_DEV_GET_DESCRIPTOR:
+    Status = HandleGetDescriptor (Request);
+    break;
+  case USB_DEV_SET_ADDRESS:
+    Status = HandleSetAddress (Request);
+    break;
+  case USB_DEV_SET_CONFIGURATION:
+    Status = HandleSetConfiguration (Request);
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR,
+      "Didn't understand RequestType 0x%x Request 0x%x\n",
+      Request->RequestType, Request->Request));
+      Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  return Status;
+}
+
+
+// Instead of actually registering interrupt handlers, we poll the controller's
+//  interrupt source register in this function.
+STATIC
+VOID
+CheckInterrupts (
+  IN EFI_EVENT        Event,
+  IN VOID            *Context
+  )
+{
+  UINT32              Ints, EpInts;
+
+
+  // interrupt register
+  Ints = READ_REG32 (GINTSTS);
+
+  /*
+   * bus reset
+   * The core sets this bit to indicate that a reset is detected on the USB.
+   */
+  if (Ints & GINTSTS_USBRST) {
+    WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);
+    ResetEndpoints ();
+  }
+
+  /*
+   * enumeration done, we now know the speed
+   * The core sets this bit to indicate that speed enumeration is complete. The
+   * application must read the Device Status (DSTS) register to obtain the
+   * enumerated speed.
+   */
+  if (Ints & GINTSTS_ENUMDONE) {
+    /* Set up the maximum packet sizes accordingly */
+    UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
+    //Set Maximum In Packet Size (MPS)
+    WRITE_REG32 (DIEPCTL1, ((READ_REG32 (DIEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
+    //Set Maximum Out Packet Size (MPS)
+    WRITE_REG32 (DOEPCTL1, ((READ_REG32 (DOEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
+  }
+
+  /*
+   * IN EP event
+   * The core sets this bit to indicate that an interrupt is pending on one of the IN
+   * endpoInts of the core (in Device mode). The application must read the
+   * Device All EndpoInts Interrupt (DAINT) register to determine the exact
+   * number of the IN endpoint on which the interrupt occurred, and then read
+   * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
+   * determine the exact cause of the interrupt. The application must clear the
+   * appropriate status bit in the corresponding DIEPINTn register to clear this bit.
+   */
+  if (Ints & GINTSTS_IEPINT) {
+    EpInts = READ_REG32 (DIEPINT0);
+    WRITE_REG32 (DIEPINT0, EpInts);
+    if (EpInts & DXEPINT_XFERCOMPL) {
+      DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));
+    }
+
+    EpInts = READ_REG32 (DIEPINT1);
+    WRITE_REG32 (DIEPINT1, EpInts);
+    if (EpInts & DXEPINT_XFERCOMPL) {
+      DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));
+    }
+  }
+
+  /*
+   * OUT EP event
+   * The core sets this bit to indicate that an interrupt is pending on one of the
+   * OUT endpoints of the core (in Device mode). The application must read the
+   * Device All EndpoInts Interrupt (DAINT) register to determine the exact
+   * number of the OUT endpoint on which the interrupt occurred, and then read
+   * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
+   * to determine the exact cause of the interrupt. The application must clear the
+   * appropriate status bit in the corresponding DOEPINTn register to clear this bit.
+   */
+  if (Ints & GINTSTS_OEPINT) {
+    /* indicates the status of an endpoint
+     * with respect to USB- and AHB-related events. */
+    EpInts = READ_REG32 (DOEPINT0);
+    if (EpInts) {
+      WRITE_REG32 (DOEPINT0, EpInts);
+      if (EpInts & DXEPINT_XFERCOMPL) {
+        DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));
+      }
+      /*
+       *
+       IN Token Received When TxFIFO is Empty (INTknTXFEmp)
+       * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
+       * was empty. This interrupt is asserted on the endpoint for which the IN token
+       * was received.
+       */
+      if (EpInts & BIT3) { /* SETUP phase done */
+        WRITE_REG32 (DIEPCTL0, READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK);
+        WRITE_REG32 (DOEPCTL0, READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK);
+        /*clear IN EP intr*/
+        WRITE_REG32 (DIEPINT0, ~0);
+        HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);
+      }
+
+      /* Make sure EP0 OUT is set up to accept the next request */
+      WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
+      /*
+       * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
+       * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
+       * was empty. This interrupt is asserted on the endpoint for which the IN token
+       * was received.
+       */
+      gDmaDescEp0->status.b.bs = 0x3;
+      gDmaDescEp0->status.b.mtrf = 0;
+      gDmaDescEp0->status.b.sr = 0;
+      gDmaDescEp0->status.b.l = 1;
+      gDmaDescEp0->status.b.ioc = 1;
+      gDmaDescEp0->status.b.sp = 0;
+      gDmaDescEp0->status.b.bytes = 64;
+      gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
+      gDmaDescEp0->status.b.sts = 0;
+      gDmaDescEp0->status.b.bs = 0x0;
+      WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
+      // endpoint enable; clear NAK
+      WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);
+    }
+
+    EpInts = (READ_REG32 (DOEPINT1));
+    if (EpInts) {
+      WRITE_REG32 (DOEPINT1, EpInts);
+      /* Transfer Completed Interrupt (XferCompl);Transfer completed */
+      if (EpInts & DXEPINT_XFERCOMPL) {
+
+        UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;
+        UINTN Len = 0;
+
+        ArmDataSynchronizationBarrier ();
+        if (MATCH_CMD_LITERAL ("download", RxBuf)) {
+          mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));
+        } else {
+          if (mNumDataBytes != 0) {
+            mNumDataBytes -= Bytes;
+          }
+        }
+
+        mDataReceivedCallback (Bytes, RxBuf);
+
+        if (mNumDataBytes == 0) {
+          Len = CMD_SIZE;
+        } else if (mNumDataBytes > DATA_SIZE) {
+          Len = DATA_SIZE;
+        } else {
+          Len = mNumDataBytes;
+        }
+
+        EpRx (1, Len);
+      }
+    }
+  }
+
+  //WRITE_REG32 clear ints
+  WRITE_REG32 (GINTSTS, Ints);
+}
+
+EFI_STATUS
+DwUsbSend (
+  IN        UINT8  EndpointIndex,
+  IN        UINTN  Size,
+  IN  CONST VOID  *Buffer
+  )
+{
+    EpTx (EndpointIndex, Buffer, Size);
+    return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+DwUsbInit (
+  VOID
+  )
+{
+  VOID     *Buf;
+  UINT32   Data;
+
+  Buf = UncachedAllocatePages (16);
+  gDmaDesc = Buf;
+  gDmaDescEp0 = gDmaDesc + sizeof (dwc_otg_dev_dma_desc_t);
+  gDmaDescIn = gDmaDescEp0 + sizeof (dwc_otg_dev_dma_desc_t);
+  gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (dwc_otg_dev_dma_desc_t);
+
+  ZeroMem (gDmaDesc, sizeof (dwc_otg_dev_dma_desc_t));
+  ZeroMem (gDmaDescEp0, sizeof (dwc_otg_dev_dma_desc_t));
+  ZeroMem (gDmaDescIn, sizeof (dwc_otg_dev_dma_desc_t));
+
+  /*Reset usb controller.*/
+  /* Wait for OTG AHB master idle */
+  do {
+    Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;
+  } while (Data == 0);
+
+  /* OTG: Assert Software Reset */
+  WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);
+
+  /* Wait for OTG to ack reset */
+  while (READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST);
+
+  /* Wait for OTG AHB master idle */
+  while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
+
+  WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);
+  WRITE_REG32 (GRXFSIZ, RX_SIZE);
+  WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);
+  WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
+  WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
+  WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
+  WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
+  WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
+  WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
+  WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
+  WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
+  WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
+  WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
+  WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
+  WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
+  WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
+  WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
+  WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
+
+  /*
+   * set Periodic TxFIFO Empty Level,
+   * Non-Periodic TxFIFO Empty Level,
+   * Enable DMA, Unmask Global Intr
+   */
+  WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);
+
+  /*select 8bit UTMI+, ULPI Inerface*/
+  WRITE_REG32 (GUSBCFG, 0x2400);
+
+  /* Detect usb work mode,host or device? */
+  do {
+    Data = READ_REG32 (GINTSTS);
+  } while (Data & GINTSTS_CURMODE_HOST);
+  MicroSecondDelay (3);
+
+  /*Init global and device mode csr register.*/
+  /*set Non-Zero-Length status out handshake */
+  Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
+  WRITE_REG32 (DCFG, Data);
+
+  /* Interrupt unmask: IN event, OUT event, bus reset */
+  Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST;
+  WRITE_REG32 (GINTMSK, Data);
+
+  do {
+    Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE;
+  } while (Data);
+
+  /* Clear any pending OTG Interrupts */
+  WRITE_REG32 (GOTGINT, ~0);
+  /* Clear any pending interrupts */
+  WRITE_REG32 (GINTSTS, ~0);
+  WRITE_REG32 (GINTMSK, ~0);
+  Data = READ_REG32 (GOTGINT);
+  Data &= ~0x3000;
+  WRITE_REG32 (GOTGINT, Data);
+
+  /* endpoint settings cfg */
+  ResetEndpoints ();
+  MicroSecondDelay (1);
+
+  /* init finish. and ready to transfer data */
+
+  /* Soft Disconnect */
+  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);
+  MicroSecondDelay (10000);
+
+  /* Soft Reconnect */
+  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE);
+}
+
+EFI_STATUS
+EFIAPI
+DwUsbStart (
+  IN USB_DEVICE_DESCRIPTOR   *DeviceDescriptor,
+  IN VOID                   **Descriptors,
+  IN USB_DEVICE_RX_CALLBACK   RxCallback,
+  IN USB_DEVICE_TX_CALLBACK   TxCallback
+  )
+{
+  UINT8                    *Ptr;
+  EFI_STATUS                Status;
+  EFI_EVENT                 TimerEvent;
+
+  ASSERT (DeviceDescriptor != NULL);
+  ASSERT (Descriptors[0] != NULL);
+  ASSERT (RxCallback != NULL);
+  ASSERT (TxCallback != NULL);
+
+  DwUsbInit();
+
+  mDeviceDescriptor = DeviceDescriptor;
+  mDescriptors = Descriptors[0];
+
+  // Right now we just support one configuration
+  ASSERT (mDeviceDescriptor->NumConfigurations == 1);
+  mDeviceDescriptor->StrManufacturer = 1;
+  mDeviceDescriptor->StrProduct = 2;
+  mDeviceDescriptor->StrSerialNumber = 3;
+  // ... and one interface
+  mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
+  ASSERT (mConfigDescriptor->NumInterfaces == 1);
+
+  Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
+  mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
+  Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
+
+  mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
+
+  mDataReceivedCallback = RxCallback;
+  mDataSentCallback = TxCallback;
+
+  // Register a timer event so CheckInterupts gets called periodically
+  Status = gBS->CreateEvent (
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  CheckInterrupts,
+                  NULL,
+                  &TimerEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->SetTimer (
+                  TimerEvent,
+                  TimerPeriodic,
+                  DW_INTERRUPT_POLL_PERIOD
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+USB_DEVICE_PROTOCOL mUsbDevice = {
+  DwUsbStart,
+  DwUsbSend
+};
+
+
+EFI_STATUS
+EFIAPI
+DwUsbEntryPoint (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  EFI_STATUS      Status;
+
+  Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = DwUsb->PhyInit(USB_DEVICE_MODE);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return gBS->InstallProtocolInterface (
+                &ImageHandle,
+                &gUsbDeviceProtocolGuid,
+                EFI_NATIVE_INTERFACE,
+                &mUsbDevice
+                );
+}
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
new file mode 100644
index 0000000..f991492
--- /dev/null
+++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
@@ -0,0 +1,46 @@ 
+#/** @file
+# Framework Module Development Environment Industry Standards
+#
+# This Package provides headers and libraries that conform to EFI/PI Industry standards.
+# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2015-2017, Linaro. All rights reserved.<BR>
+#
+#    This program and the accompanying materials are licensed and made available under
+#    the terms and conditions of the BSD License which accompanies this distribution.
+#    The full text of the license may be found at
+#    http://opensource.org/licenses/bsd-license.php
+#
+#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010019
+  PACKAGE_NAME                   = OpenPlatformDriversUsbDwUsbDxePkg
+  PACKAGE_GUID                   = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5
+  PACKAGE_VERSION                = 0.1
+
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+
+[Guids.common]
+  gAndroidFastbootUsbGuid       = { 0xf6bec3fe, 0x88fb, 0x11e3, { 0xae, 0x84, 0xe7, 0x3b, 0x77, 0x56, 0x1c, 0x35 }}
+  gDwUsbDxeTokenSpaceGuid       = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}
+
+[Protocols.common]
+  gDwUsbProtocolGuid            = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+
+[PcdsFixedAtBuild.common]
+  # DwUsb Driver PCDs
+  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001
+  gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.h b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h
new file mode 100644
index 0000000..7f909c3
--- /dev/null
+++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h
@@ -0,0 +1,627 @@ 
+/** @file
+
+  Copyright (c) 2015-2017, Linaro. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __DW_USB_DXE_H__
+#define __DW_USB_DXE_H__
+
+#define DW_USB_BASE                     FixedPcdGet32 (PcdDwUsbDxeBaseAddress)
+
+#define READ_REG32(Offset)              MmioRead32 (DW_USB_BASE + Offset)
+#define READ_REG16(Offset)              (UINT16)READ_REG32 (Offset)
+#define WRITE_REG32(Offset, Val)        MmioWrite32 (DW_USB_BASE + Offset, Val)
+#define WRITE_REG16(Offset, Val)        MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)
+#define WRITE_REG8(Offset, Val)         MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)
+
+// Max packet size in bytes (For Full Speed USB 64 is the only valid value)
+#define MAX_PACKET_SIZE_CONTROL         64
+
+#define MAX_PACKET_SIZE_BULK            512
+
+// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer
+#define DW_NUM_ENDPOINTS                16
+
+// Endpoint Indexes
+#define DW_EP0SETUP                     0x20
+#define DW_EP0RX                        0x00
+#define DW_EP0TX                        0x01
+#define DW_EP1RX                        0x02
+#define DW_EP1TX                        0x03
+
+// DcInterrupt bits
+#define DW_DC_INTERRUPT_EP1TX           BIT13
+#define DW_DC_INTERRUPT_EP1RX           BIT12
+#define DW_DC_INTERRUPT_EP0TX           BIT11
+#define DW_DC_INTERRUPT_EP0RX           BIT10
+#define DW_DC_INTERRUPT_EP0SETUP        BIT8
+#define DW_DC_INTERRUPT_VBUS            BIT7
+#define DW_DC_INTERRUPT_DMA             BIT6
+#define DW_DC_INTERRUPT_HS_STAT         BIT5
+#define DW_DC_INTERRUPT_RESUME          BIT4
+#define DW_DC_INTERRUPT_SUSP            BIT3
+#define DW_DC_INTERRUPT_PSOF            BIT2
+#define DW_DC_INTERRUPT_SOF             BIT1
+#define DW_DC_INTERRUPT_BRESET          BIT0
+// All valid peripheral controller int  rrupts
+#define DW_DC_INTERRUPT_MASK            0x003FFFDFF
+
+#define DW_ADDRESS                      0x200
+#define DW_ADDRESS_DEVEN                BIT7
+
+#define DW_MODE                         0x20C
+#define DW_MODE_DATA_BUS_WIDTH          BIT8
+#define DW_MODE_CLKAON                  BIT7
+#define DW_MODE_SFRESET                 BIT4
+#define DW_MODE_WKUPCS                  BIT2
+
+#define DW_ENDPOINT_MAX_PACKET_SIZE     0x204
+
+#define DW_ENDPOINT_TYPE                0x208
+#define DW_ENDPOINT_TYPE_NOEMPKT        BIT4
+#define DW_ENDPOINT_TYPE_ENABLE         BIT3
+
+#define DW_INTERRUPT_CONFIG             0x210
+// Interrupt config value to only interrupt on ACK of IN and OUT tokens
+#define DW_INTERRUPT_CONFIG_ACK_ONLY    (BIT2 | BIT5 | BIT6)
+
+#define DW_DC_INTERRUPT                 0x218
+#define DW_DC_INTERRUPT_ENABLE          0x214
+
+#define DW_CTRL_FUNCTION                0x228
+#define DW_CTRL_FUNCTION_VENDP          BIT3
+#define DW_CTRL_FUNCTION_DSEN           BIT2
+#define DW_CTRL_FUNCTION_STATUS         BIT1
+
+#define DW_DEVICE_UNLOCK                0x27C
+#define DW_DEVICE_UNLOCK_MAGIC          0xAA37
+
+#define DW_SW_RESET_REG                 0x30C
+#define DW_SW_RESET_ALL                 BIT0
+
+#define DW_DEVICE_ID                    0x370
+
+#define DW_OTG_CTRL_SET                 0x374
+#define DW_OTG_CTRL_CLR                 (OTG_CTRL_SET + 2)
+#define DW_OTG_CTRL_OTG_DISABLE         BIT10
+#define DW_OTG_CTRL_VBUS_CHRG           BIT6
+#define DW_OTG_CTRL_VBUS_DISCHRG        BIT5
+#define DW_OTG_CTRL_DM_PULLDOWN         BIT2
+#define DW_OTG_CTRL_DP_PULLDOWN         BIT1
+#define DW_OTG_CTRL_DP_PULLUP           BIT0
+
+#define DW_OTG_STATUS                   0x378
+#define DW_OTG_STATUS_B_SESS_END        BIT7
+#define DW_OTG_STATUS_A_B_SESS_VLD      BIT1
+
+#define DW_OTG_INTERRUPT_LATCH_SET      0x37C
+#define DW_OTG_INTERRUPT_LATCH_CLR      0x37E
+#define DW_OTG_INTERRUPT_ENABLE_RISE    0x384
+
+#define DW_DMA_ENDPOINT_INDEX           0x258
+
+#define DW_ENDPOINT_INDEX               0x22c
+#define DW_DATA_PORT                    0x220
+#define DW_BUFFER_LENGTH                0x21c
+
+// Device ID Values
+#define PHILLIPS_VENDOR_ID_VAL          0x04cc
+#define DW_PRODUCT_ID_VAL               0x1761
+#define DW_DEVICE_ID_VAL                ((ISP1761_PRODUCT_ID_VAL << 16) | \
+                                         PHILLIPS_VENDOR_ID_VAL)
+
+#define DWC_OTG_BASE                    DW_USB_BASE
+
+#define USB_NUM_ENDPOINTS               2
+#define MAX_EPS_CHANNELS                16
+
+#define BULK_OUT_EP                     1
+#define BULK_IN_EP                      1
+
+#define RX_REQ_LEN                      512
+#define MAX_PACKET_LEN                  512
+
+#define DATA_FIFO_CONFIG                0x0F801000
+/* RX FIFO: 2048 bytes */
+#define RX_SIZE                         0x00000200
+/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */
+#define ENDPOINT_TX_SIZE                0x01000200
+
+/* EP1  TX FIFO: 1024 bytes. start address: 0x220 * 4. */
+/* EP2  TX FIFO: 1024 bytes. start address: 0x320 * 4. */
+/* EP3  TX FIFO: 1024 bytes. start address: 0x420 * 4. */
+/* EP4  TX FIFO: 1024 bytes. start address: 0x520 * 4. */
+/* EP5  TX FIFO: 128 bytes. start address: 0x620 * 4. */
+/* EP6  TX FIFO: 128 bytes. start address: 0x640 * 4. */
+/* EP7  TX FIFO: 128 bytes. start address: 0x660 * 4. */
+/* EP8  TX FIFO: 128 bytes. start address: 0x680 * 4. */
+/* EP9  TX FIFO: 128 bytes. start address: 0x6A0 * 4. */
+/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */
+/* EP11 TX FIFO: 128  bytes. start address: 0x6E0 * 4. */
+/* EP12 TX FIFO: 128  bytes. start address: 0x700 * 4. */
+/* EP13 TX FIFO: 128  bytes. start address: 0x720 * 4. */
+/* EP14 TX FIFO: 128  bytes. start address: 0x740 * 4. */
+/* EP15 TX FIFO: 128  bytes. start address: 0x760 * 4. */
+
+#define DATA_IN_ENDPOINT_TX_FIFO1       0x01000220
+#define DATA_IN_ENDPOINT_TX_FIFO2       0x01000320
+#define DATA_IN_ENDPOINT_TX_FIFO3       0x01000420
+#define DATA_IN_ENDPOINT_TX_FIFO4       0x01000520
+#define DATA_IN_ENDPOINT_TX_FIFO5       0x00200620
+#define DATA_IN_ENDPOINT_TX_FIFO6       0x00200640
+#define DATA_IN_ENDPOINT_TX_FIFO7       0x00200680
+#define DATA_IN_ENDPOINT_TX_FIFO8       0x002006A0
+#define DATA_IN_ENDPOINT_TX_FIFO9       0x002006C0
+#define DATA_IN_ENDPOINT_TX_FIFO10      0x002006E0
+#define DATA_IN_ENDPOINT_TX_FIFO11      0x00200700
+#define DATA_IN_ENDPOINT_TX_FIFO12      0x00200720
+#define DATA_IN_ENDPOINT_TX_FIFO13      0x00200740
+#define DATA_IN_ENDPOINT_TX_FIFO14      0x00200760
+#define DATA_IN_ENDPOINT_TX_FIFO15      0x00200F00
+
+/*DWC_OTG regsiter descriptor*/
+/*Device mode CSR MAP*/
+#define DEVICE_CSR_BASE                 0x800
+/*Device mode CSR MAP*/
+#define DEVICE_INEP_BASE                0x900
+/*Device mode CSR MAP*/
+#define DEVICE_OUTEP_BASE               0xB00
+
+/*** OTG LINK CORE REGISTERS ***/
+/* Core Global Registers */
+#define GOTGCTL                         0x000
+#define GOTGINT                         0x004
+#define GAHBCFG                         0x008
+#define GAHBCFG_P_TXF_EMP_LVL           (1 << 8)
+#define GAHBCFG_NP_TXF_EMP_LVL          (1 << 7)
+#define GAHBCFG_DMA_EN                  (1 << 5)
+#define GAHBCFG_GLBL_INTR_EN            (1 << 0)
+#define GAHBCFG_CTRL_MASK               (GAHBCFG_P_TXF_EMP_LVL | \
+                                         GAHBCFG_NP_TXF_EMP_LVL | \
+                                         GAHBCFG_DMA_EN | \
+                                         GAHBCFG_GLBL_INTR_EN)
+
+#define GUSBCFG                         0x00C
+#define GRSTCTL                         0x010
+#define GRSTCTL_AHBIDLE                 (1 << 31)
+#define GRSTCTL_CSFTRST                 (1 << 0)
+
+#define GINTSTS                         0x014
+#define GINTSTS_WKUPINT                 BIT31
+#define GINTSTS_SESSREGINT              BIT30
+#define GINTSTS_DISCONNINT              BIT29
+#define GINTSTS_CONIDSTSCHNG            BIT28
+#define GINTSTS_LPMTRANRCVD             BIT27
+#define GINTSTS_PTXFEMP                 BIT26
+#define GINTSTS_HCHINT                  BIT25
+#define GINTSTS_PRTINT                  BIT24
+#define GINTSTS_RESETDET                BIT23
+#define GINTSTS_FET_SUSP                BIT22
+#define GINTSTS_INCOMPL_IP              BIT21
+#define GINTSTS_INCOMPL_SOIN            BIT20
+#define GINTSTS_OEPINT                  BIT19
+#define GINTSTS_IEPINT                  BIT18
+#define GINTSTS_EPMIS                   BIT17
+#define GINTSTS_RESTOREDONE             BIT16
+#define GINTSTS_EOPF                    BIT15
+#define GINTSTS_ISOUTDROP               BIT14
+#define GINTSTS_ENUMDONE                BIT13
+#define GINTSTS_USBRST                  BIT12
+#define GINTSTS_USBSUSP                 BIT11
+#define GINTSTS_ERLYSUSP                BIT10
+#define GINTSTS_I2CINT                  BIT9
+#define GINTSTS_ULPI_CK_INT             BIT8
+#define GINTSTS_GOUTNAKEFF              BIT7
+#define GINTSTS_GINNAKEFF               BIT6
+#define GINTSTS_NPTXFEMP                BIT5
+#define GINTSTS_RXFLVL                  BIT4
+#define GINTSTS_SOF                     BIT3
+#define GINTSTS_OTGINT                  BIT2
+#define GINTSTS_MODEMIS                 BIT1
+#define GINTSTS_CURMODE_HOST            BIT0
+
+#define GINTMSK                         0x018
+#define GRXSTSR                         0x01C
+#define GRXSTSP                         0x020
+#define GRXFSIZ                         0x024
+#define GNPTXFSIZ                       0x028
+#define GNPTXSTS                        0x02C
+
+#define GHWCFG1                         0x044
+#define GHWCFG2                         0x048
+#define GHWCFG3                         0x04c
+#define GHWCFG4                         0x050
+#define GLPMCFG                         0x054
+
+#define GDFIFOCFG                       0x05c
+
+#define HPTXFSIZ                        0x100
+#define DIEPTXF(x)                      (0x100 + 4 * (x))
+#define DIEPTXF1                        0x104
+#define DIEPTXF2                        0x108
+#define DIEPTXF3                        0x10C
+#define DIEPTXF4                        0x110
+#define DIEPTXF5                        0x114
+#define DIEPTXF6                        0x118
+#define DIEPTXF7                        0x11C
+#define DIEPTXF8                        0x120
+#define DIEPTXF9                        0x124
+#define DIEPTXF10                       0x128
+#define DIEPTXF11                       0x12C
+#define DIEPTXF12                       0x130
+#define DIEPTXF13                       0x134
+#define DIEPTXF14                       0x138
+#define DIEPTXF15                       0x13C
+
+/*** HOST MODE REGISTERS ***/
+/* Host Global Registers */
+#define HCFG                            0x400
+#define HFIR                            0x404
+#define HFNUM                           0x408
+#define HPTXSTS                         0x410
+#define HAINT                           0x414
+#define HAINTMSK                        0x418
+
+/* Host Port Control and Status Registers */
+#define HPRT                            0x440
+
+/* Host Channel-Specific Registers */
+#define HCCHAR(x)                       (0x500 + 0x20 * (x))
+#define HCSPLT(x)                       (0x504 + 0x20 * (x))
+#define HCINT(x)                        (0x508 + 0x20 * (x))
+#define HCINTMSK(x)                     (0x50C + 0x20 * (x))
+#define HCTSIZ(x)                       (0x510 + 0x20 * (x))
+#define HCDMA(x)                        (0x514 + 0x20 * (x))
+#define HCCHAR0                         0x500
+#define HCSPLT0                         0x504
+#define HCINT0                          0x508
+#define HCINTMSK0                       0x50C
+#define HCTSIZ0                         0x510
+#define HCDMA0                          0x514
+#define HCCHAR1                         0x520
+#define HCSPLT1                         0x524
+#define HCINT1                          0x528
+#define HCINTMSK1                       0x52C
+#define HCTSIZ1                         0x530
+#define HCDMA1                          0x534
+#define HCCHAR2                         0x540
+#define HCSPLT2                         0x544
+#define HCINT2                          0x548
+#define HCINTMSK2                       0x54C
+#define HCTSIZ2                         0x550
+#define HCDMA2                          0x554
+#define HCCHAR3                         0x560
+#define HCSPLT3                         0x564
+#define HCINT3                          0x568
+#define HCINTMSK3                       0x56C
+#define HCTSIZ3                         0x570
+#define HCDMA3                          0x574
+#define HCCHAR4                         0x580
+#define HCSPLT4                         0x584
+#define HCINT4                          0x588
+#define HCINTMSK4                       0x58C
+#define HCTSIZ4                         0x590
+#define HCDMA4                          0x594
+#define HCCHAR5                         0x5A0
+#define HCSPLT5                         0x5A4
+#define HCINT5                          0x5A8
+#define HCINTMSK5                       0x5AC
+#define HCTSIZ5                         0x5B0
+#define HCDMA5                          0x5B4
+#define HCCHAR6                         0x5C0
+#define HCSPLT6                         0x5C4
+#define HCINT6                          0x5C8
+#define HCINTMSK6                       0x5CC
+#define HCTSIZ6                         0x5D0
+#define HCDMA6                          0x5D4
+#define HCCHAR7                         0x5E0
+#define HCSPLT7                         0x5E4
+#define HCINT7                          0x5E8
+#define HCINTMSK7                       0x5EC
+#define HCTSIZ7                         0x5F0
+#define HCDMA7                          0x5F4
+#define HCCHAR8                         0x600
+#define HCSPLT8                         0x604
+#define HCINT8                          0x608
+#define HCINTMSK8                       0x60C
+#define HCTSIZ8                         0x610
+#define HCDMA8                          0x614
+#define HCCHAR9                         0x620
+#define HCSPLT9                         0x624
+#define HCINT9                          0x628
+#define HCINTMSK9                       0x62C
+#define HCTSIZ9                         0x630
+#define HCDMA9                          0x634
+#define HCCHAR10                        0x640
+#define HCSPLT10                        0x644
+#define HCINT10                         0x648
+#define HCINTMSK10                      0x64C
+#define HCTSIZ10                        0x650
+#define HCDMA10                         0x654
+#define HCCHAR11                        0x660
+#define HCSPLT11                        0x664
+#define HCINT11                         0x668
+#define HCINTMSK11                      0x66C
+#define HCTSIZ11                        0x670
+#define HCDMA11                         0x674
+#define HCCHAR12                        0x680
+#define HCSPLT12                        0x684
+#define HCINT12                         0x688
+#define HCINTMSK12                      0x68C
+#define HCTSIZ12                        0x690
+#define HCDMA12                         0x694
+#define HCCHAR13                        0x6A0
+#define HCSPLT13                        0x6A4
+#define HCINT13                         0x6A8
+#define HCINTMSK13                      0x6AC
+#define HCTSIZ13                        0x6B0
+#define HCDMA13                         0x6B4
+#define HCCHAR14                        0x6C0
+#define HCSPLT14                        0x6C4
+#define HCINT14                         0x6C8
+#define HCINTMSK14                      0x6CC
+#define HCTSIZ14                        0x6D0
+#define HCDMA14                         0x6D4
+#define HCCHAR15                        0x6E0
+#define HCSPLT15                        0x6E4
+#define HCINT15                         0x6E8
+#define HCINTMSK15                      0x6EC
+#define HCTSIZ15                        0x6F0
+#define HCDMA15                         0x6F4
+
+/*** DEVICE MODE REGISTERS ***/
+/* Device Global Registers */
+#define DCFG                            0x800
+#define DCFG_DESCDMA                    BIT23
+#define DCFG_EPMISCNT_MASK              (0x1F << 18)
+#define DCFG_EPMISCNT_SHIFT             18
+#define DCFG_DEVADDR_MASK               (0x7F << 4)
+#define DCFG_DEVADDR_SHIFT              4
+#define DCFG_DEVADDR(x)                 (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK)
+#define DCFG_NZ_STS_OUT_HSHK            BIT2
+
+#define DCTL                            0x804
+#define DCTL_PWRONPRGDONE               BIT11
+#define DCTL_GNPINNAKSTS                BIT2
+#define DCTL_SFTDISCON                  BIT1
+
+#define DSTS                            0x808
+#define DIEPMSK                         0x810
+#define DOEPMSK                         0x814
+
+#define DXEPMSK_TIMEOUTMSK              BIT3
+#define DXEPMSK_AHBERMSK                BIT2
+#define DXEPMSK_XFERCOMPLMSK            BIT0
+
+#define DAINT                           0x818
+#define DAINTMSK                        0x81C
+
+#define DAINTMSK_OUTEPMSK_SHIFT         16
+#define DAINTMSK_INEPMSK_SHIFT          0
+
+#define DTKNQR1                         0x820
+#define DTKNQR2                         0x824
+#define DVBUSDIS                        0x828
+#define DVBUSPULSE                      0x82C
+#define DTHRCTL                         0x830
+
+/* Device Logical IN Endpoint-Specific Registers */
+#define DIEPCTL(x)                      (0x900 + 0x20 * (x))
+#define DIEPINT(x)                      (0x908 + 0x20 * (x))
+#define DIEPTSIZ(x)                     (0x910 + 0x20 * (x))
+#define DIEPDMA(x)                      (0x914 + 0x20 * (x))
+#define DTXFSTS(x)                      (0x918 + 0x20 * (x))
+
+#define DIEPCTL0                        0x900
+#define DIEPINT0                        0x908
+#define DIEPTSIZ0                       0x910
+#define DIEPDMA0                        0x914
+#define DIEPCTL1                        0x920
+#define DIEPINT1                        0x928
+#define DIEPTSIZ1                       0x930
+#define DIEPDMA1                        0x934
+#define DIEPCTL2                        0x940
+#define DIEPINT2                        0x948
+#define DIEPTSIZ2                       0x950
+#define DIEPDMA2                        0x954
+#define DIEPCTL3                        0x960
+#define DIEPINT3                        0x968
+#define DIEPTSIZ3                       0x970
+#define DIEPDMA3                        0x974
+#define DIEPCTL4                        0x980
+#define DIEPINT4                        0x988
+#define DIEPTSIZ4                       0x990
+#define DIEPDMA4                        0x994
+#define DIEPCTL5                        0x9A0
+#define DIEPINT5                        0x9A8
+#define DIEPTSIZ5                       0x9B0
+#define DIEPDMA5                        0x9B4
+#define DIEPCTL6                        0x9C0
+#define DIEPINT6                        0x9C8
+#define DIEPTSIZ6                       0x9D0
+#define DIEPDMA6                        0x9D4
+#define DIEPCTL7                        0x9E0
+#define DIEPINT7                        0x9E8
+#define DIEPTSIZ7                       0x9F0
+#define DIEPDMA7                        0x9F4
+#define DIEPCTL8                        0xA00
+#define DIEPINT8                        0xA08
+#define DIEPTSIZ8                       0xA10
+#define DIEPDMA8                        0xA14
+#define DIEPCTL9                        0xA20
+#define DIEPINT9                        0xA28
+#define DIEPTSIZ9                       0xA30
+#define DIEPDMA9                        0xA34
+#define DIEPCTL10                       0xA40
+#define DIEPINT10                       0xA48
+#define DIEPTSIZ10                      0xA50
+#define DIEPDMA10                       0xA54
+#define DIEPCTL11                       0xA60
+#define DIEPINT11                       0xA68
+#define DIEPTSIZ11                      0xA70
+#define DIEPDMA11                       0xA74
+#define DIEPCTL12                       0xA80
+#define DIEPINT12                       0xA88
+#define DIEPTSIZ12                      0xA90
+#define DIEPDMA12                       0xA94
+#define DIEPCTL13                       0xAA0
+#define DIEPINT13                       0xAA8
+#define DIEPTSIZ13                      0xAB0
+#define DIEPDMA13                       0xAB4
+#define DIEPCTL14                       0xAC0
+#define DIEPINT14                       0xAC8
+#define DIEPTSIZ14                      0xAD0
+#define DIEPDMA14                       0xAD4
+#define DIEPCTL15                       0xAE0
+#define DIEPINT15                       0xAE8
+#define DIEPTSIZ15                      0xAF0
+#define DIEPDMA15                       0xAF4
+
+/* Device Logical OUT Endpoint-Specific Registers */
+#define DOEPCTL(x)                      (0xB00 + 0x20 * (x))
+#define DOEPINT(x)                      (0xB08 + 0x20 * (x))
+#define DOEPTSIZ(x)                     (0xB10 + 0x20 * (x))
+
+#define DXEPINT_EPDISBLD                BIT1
+#define DXEPINT_XFERCOMPL               BIT0
+
+#define DXEPTSIZ_SUPCNT(x)              (((x) & 0x3) << 29)
+#define DXEPTSIZ_PKTCNT(x)              (((x) & 0x3) << 19)
+#define DXEPTSIZ_XFERSIZE(x)            ((x) & 0x7F)
+
+#define DOEPDMA(x)                      (0xB14 + 0x20 * (x))
+#define DOEPCTL0                        0xB00
+#define DOEPINT0                        0xB08
+#define DOEPTSIZ0                       0xB10
+#define DOEPDMA0                        0xB14
+#define DOEPCTL1                        0xB20
+#define DOEPINT1                        0xB28
+#define DOEPTSIZ1                       0xB30
+#define DOEPDMA1                        0xB34
+#define DOEPCTL2                        0xB40
+#define DOEPINT2                        0xB48
+#define DOEPTSIZ2                       0xB50
+#define DOEPDMA2                        0xB54
+#define DOEPCTL3                        0xB60
+#define DOEPINT3                        0xB68
+#define DOEPTSIZ3                       0xB70
+#define DOEPDMA3                        0xB74
+#define DOEPCTL4                        0xB80
+#define DOEPINT4                        0xB88
+#define DOEPTSIZ4                       0xB90
+#define DOEPDMA4                        0xB94
+#define DOEPCTL5                        0xBA0
+#define DOEPINT5                        0xBA8
+#define DOEPTSIZ5                       0xBB0
+#define DOEPDMA5                        0xBB4
+#define DOEPCTL6                        0xBC0
+#define DOEPINT6                        0xBC8
+#define DOEPTSIZ6                       0xBD0
+#define DOEPDMA6                        0xBD4
+#define DOEPCTL7                        0xBE0
+#define DOEPINT7                        0xBE8
+#define DOEPTSIZ7                       0xBF0
+#define DOEPDMA7                        0xBF4
+#define DOEPCTL8                        0xC00
+#define DOEPINT8                        0xC08
+#define DOEPTSIZ8                       0xC10
+#define DOEPDMA8                        0xC14
+#define DOEPCTL9                        0xC20
+#define DOEPINT9                        0xC28
+#define DOEPTSIZ9                       0xC30
+#define DOEPDMA9                        0xC34
+#define DOEPCTL10                       0xC40
+#define DOEPINT10                       0xC48
+#define DOEPTSIZ10                      0xC50
+#define DOEPDMA10                       0xC54
+#define DOEPCTL11                       0xC60
+#define DOEPINT11                       0xC68
+#define DOEPTSIZ11                      0xC70
+#define DOEPDMA11                       0xC74
+#define DOEPCTL12                       0xC80
+#define DOEPINT12                       0xC88
+#define DOEPTSIZ12                      0xC90
+#define DOEPDMA12                       0xC94
+#define DOEPCTL13                       0xCA0
+#define DOEPINT13                       0xCA8
+#define DOEPTSIZ13                      0xCB0
+#define DOEPDMA13                       0xCB4
+#define DOEPCTL14                       0xCC0
+#define DOEPINT14                       0xCC8
+#define DOEPTSIZ14                      0xCD0
+#define DOEPDMA14                       0xCD4
+#define DOEPCTL15                       0xCE0
+#define DOEPINT15                       0xCE8
+#define DOEPTSIZ15                      0xCF0
+#define DOEPDMA15                       0xCF4
+
+#define DXEPCTL_EPENA                   BIT31
+#define DXEPCTL_SNAK                    BIT27
+#define DXEPCTL_CNAK                    BIT26
+#define DXEPCTL_STALL                   BIT21
+#define DXEPCTL_EPTYPE_MASK             (BIT19 | BIT18)
+#define DXEPCTL_NAKSTS                  BIT17
+#define DXEPCTL_USBACTEP                BIT15
+#define DXEPCTL_MPS_MASK                0x7FF
+
+/* Power and Clock Gating Register */
+#define PCGCCTL                         0xE00
+
+#define EP0FIFO                         0x1000
+
+/**
+ * This union represents the bit fields in the DMA Descriptor
+ * status quadlet. Read the quadlet into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
+ * <i>b_iso_in</i> elements.
+ */
+typedef union {
+  /** raw register data */
+  UINT32 d32;
+    /** quadlet bits */
+  struct {
+    /** Received number of bytes */
+    unsigned bytes:16;
+    /** NAK bit - only for OUT EPs */
+    unsigned nak:1;
+    unsigned reserved17_22:6;
+    /** Multiple Transfer - only for OUT EPs */
+    unsigned mtrf:1;
+    /** Setup Packet received - only for OUT EPs */
+    unsigned sr:1;
+    /** Interrupt On Complete */
+    unsigned ioc:1;
+    /** Short Packet */
+    unsigned sp:1;
+    /** Last */
+    unsigned l:1;
+    /** Receive Status */
+    unsigned sts:2;
+    /** Buffer Status */
+    unsigned bs:2;
+  } b;
+} dev_dma_desc_sts_t;
+
+/**
+ * DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct {
+  /** DMA Descriptor status quadlet */
+  dev_dma_desc_sts_t status;
+  /** DMA Descriptor data buffer pointer */
+  UINT32 buf;
+} dwc_otg_dev_dma_desc_t;
+
+#endif //ifndef __DW_USB_DXE_H__
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf
new file mode 100644
index 0000000..0ac12c1
--- /dev/null
+++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf
@@ -0,0 +1,52 @@ 
+#/** @file
+#
+#  Copyright (c) 2015-2017, Linaro. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010019
+  BASE_NAME                      = DwUsbDxe
+  FILE_GUID                      = 72d78ea6-4dee-11e3-8100-f3842a48d0a0
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = DwUsbEntryPoint
+
+[Sources.common]
+  DwUsbDxe.c
+
+[LibraryClasses]
+  ArmLib
+  DebugLib
+  IoLib
+  MemoryAllocationLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UncachedMemoryAllocationLib
+  CacheMaintenanceLib
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gUsbDeviceProtocolGuid
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
+
+[Pcd]
+  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress
+
+[Depex]
+  TRUE
diff --git a/Include/Protocol/DwUsb.h b/Include/Protocol/DwUsb.h
new file mode 100644
index 0000000..040e126
--- /dev/null
+++ b/Include/Protocol/DwUsb.h
@@ -0,0 +1,81 @@ 
+/** @file
+
+  Copyright (c) 2015-2017, Linaro. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __DW_USB_H__
+#define __DW_USB_H__
+
+//
+// Protocol GUID
+//
+#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+
+//
+// Protocol interface structure
+//
+typedef struct _DW_USB_PROTOCOL  DW_USB_PROTOCOL;
+
+#define USB_HOST_MODE                 0
+#define USB_DEVICE_MODE               1
+#define USB_CABLE_NOT_ATTACHED        2
+
+#define LANG_LENGTH                   8
+#define MANU_FACTURER_STRING_LENGTH   32
+#define PRODUCT_STRING_LENGTH         32
+#define SERIAL_STRING_LENGTH          17
+
+typedef
+EFI_STATUS
+(EFIAPI *DW_USB_GET_LANG) (
+  OUT CHAR16                           *Lang,
+  OUT UINT8                            *Length
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *DW_USB_GET_MANU_FACTURER) (
+  OUT CHAR16                           *ManuFacturer,
+  OUT UINT8                            *Length
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *DW_USB_GET_PRODUCT) (
+  OUT CHAR16                           *Product,
+  OUT UINT8                            *Length
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *DW_USB_GET_SERIAL_NO) (
+  OUT CHAR16                           *SerialNo,
+  OUT UINT8                            *Length
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *DW_USB_PHY_INIT) (
+  IN UINT8                             Mode
+  );
+
+struct _DW_USB_PROTOCOL {
+  DW_USB_GET_LANG                      GetLang;
+  DW_USB_GET_MANU_FACTURER             GetManuFacturer;
+  DW_USB_GET_PRODUCT                   GetProduct;
+  DW_USB_GET_SERIAL_NO                 GetSerialNo;
+  DW_USB_PHY_INIT                      PhyInit;
+};
+
+extern EFI_GUID gDwUsbProtocolGuid;
+
+#endif