public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1 1/1] EmbeddedPkg/Drivers: add DwUsbDxe
@ 2018-08-21 11:35 Haojian Zhuang
  2018-10-05 15:46 ` Leif Lindholm
  0 siblings, 1 reply; 3+ messages in thread
From: Haojian Zhuang @ 2018-08-21 11:35 UTC (permalink / raw)
  To: edk2-devel

Add Designware USB 2.0 device driver that is used on HiKey platform.

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec |  45 +
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.inf |  52 ++
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h   | 655 ++++++++++++++
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c   | 912 ++++++++++++++++++++
 4 files changed, 1664 insertions(+)

diff --git a/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec
new file mode 100644
index 000000000000..7eb65e498c04
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec
@@ -0,0 +1,45 @@
+#/** @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) 2018, 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                   = DwUsbDxePkg
+  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]
+  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/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.inf b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.inf
new file mode 100644
index 000000000000..56d518c27c32
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.inf
@@ -0,0 +1,52 @@
+#/** @file
+#
+#  Copyright (c) 2018, 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
+  CacheMaintenanceLib
+  DebugLib
+  DmaLib
+  IoLib
+  MemoryAllocationLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gUsbDeviceProtocolGuid
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+
+[Pcd]
+  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress
+
+[Depex]
+  TRUE
diff --git a/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h
new file mode 100644
index 000000000000..1595e09a92a4
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h
@@ -0,0 +1,655 @@
+/** @file
+
+  Copyright (c) 2018, 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 GUSBCFG_USBTRDTIM_8BIT          (0x9 << 10)
+#define GUSBCFG_USBTRDTIM_16BIT         (0x5 << 10)
+
+#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 DSTS_ENUMSPD_MASK               (0x3 << 1)
+#define DSTS_ENUMSPD_HIGH               (0 << 1)
+#define DSTS_ENUMSPD_FULL               (1 << 1)
+
+#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_TXFNUM(x)               (((x) & 0xF) << 22)
+#define DXEPCTL_STALL                   BIT21
+#define DXEPCTL_EPTYPE_MASK             (BIT19 | BIT18)
+#define DXEPCTL_EPTYPE(x)               (((x) & 0x3) << 18)
+#define DXEPCTL_NAKSTS                  BIT17
+#define DXEPCTL_USBACTEP                BIT15
+#define DXEPCTL_MPS_MASK                0x7FF
+
+#define DXEPTSIZN_PKTCNT_MASK           (0x3FF << 19)
+#define DXEPTSIZN_PKTCNT(x)             (((x) & 0x3FF) << 19)
+#define DXEPTSIZN_XFERSIZE_MASK         0x7FFFF
+#define DXEPTSIZN_XFERSIZE(x)           ((x) & 0x7FFFF)
+
+/* 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;
+} DevDmaDescStatus;
+
+/**
+ * DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct {
+  /** DMA Descriptor status quadlet */
+  DevDmaDescStatus status;
+  /** DMA Descriptor data buffer pointer */
+  UINT32 buf;
+} DwUsbDevDmaDesc;
+
+#endif /* __DW_USB_DXE_H__ */
diff --git a/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c
new file mode 100644
index 000000000000..6e1086190796
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c
@@ -0,0 +1,912 @@
+/** @file
+
+  Copyright (c) 2018, 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/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DmaLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiRuntimeServicesTableLib.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
+
+#define ENDPOINT0                     0
+#define ENDPOINT1                     1
+
+#define DIR_OUT                       0
+#define DIR_IN                        1
+
+#define DWUSB_BUFFER_PAGE_NUM         16
+
+#define DESCRIPTOR_INDEX_LANG         0
+#define DESCRIPTOR_INDEX_MANUFACTURER 1
+#define DESCRIPTOR_INDEX_PRODUCT      2
+#define DESCRIPTOR_INDEX_SERIALNUMBER 3
+
+#define DESCRIPTOR_TYPE(x)            (((x) >> 8) & 0xFF)
+#define DESCRIPTOR_INDEX(x)           ((x) & 0xFF)
+
+typedef struct {
+  USB_DEVICE_DESCRIPTOR        *DeviceDescriptor;
+  USB_CONFIG_DESCRIPTOR        *ConfigDescriptor;
+} DW_USB_DESCRIPTOR;
+
+EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
+
+STATIC DwUsbDevDmaDesc  *gDmaDesc,*gDmaDescEp0,*gDmaDescIn;
+STATIC USB_DEVICE_REQUEST      *gCtrlReq;
+STATIC VOID                    *RxBuf;
+STATIC UINTN                   RxDescBytes;
+STATIC UINTN                   mNumDataBytes;
+
+STATIC DW_USB_PROTOCOL         *DwUsb;
+STATIC DW_USB_DESCRIPTOR       gDwUsbDescriptor;
+
+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
+  )
+{
+  return (((READ_REG32 (DSTS) & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HIGH));
+}
+
+STATIC
+VOID
+ResetEndpoints (
+  VOID
+  )
+{
+  UINT32                       Data;
+
+  /* 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 EndPoint0 */
+  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 */
+  Data = READ_REG32 (DOEPCTL0);
+  WRITE_REG32 (DOEPCTL0, Data | DXEPCTL_EPENA | DXEPCTL_CNAK);
+}
+
+STATIC
+VOID
+EndPointTx (
+  IN UINT8          EndPoint,
+  IN CONST VOID    *Ptr,
+  IN UINTN          Len
+  )
+{
+  UINT32            BlockSize;
+  UINT32            Packets;
+  UINT32            Data;
+
+  /* EPx OUT ACTIVE */
+  Data = READ_REG32 (DIEPCTL (EndPoint));
+  WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_USBACTEP);
+  if (!EndPoint) {
+      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 (EndPoint), (UINT32)(UINTN)gDmaDescIn);             // DMA Address (DMAAddr) is zero
+  } else {
+    WRITE_REG32 (DIEPTSIZ (EndPoint), Len | DXEPTSIZN_PKTCNT (Packets));
+
+    //
+    //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 (EndPoint), (UINT32)(UINTN)gDmaDescIn);         // Ptr is DMA address
+  }
+  ArmDataSynchronizationBarrier ();
+  /* epena & cnak */
+  Data = READ_REG32 (DIEPCTL (EndPoint));
+  WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);
+}
+
+STATIC
+VOID
+EndPointRx (
+  IN UINTN            EndPoint,
+  IN UINTN            Len
+  )
+{
+  UINT32              Data;
+
+  /* EPx UNSTALL */
+  Data = READ_REG32 (DOEPCTL (EndPoint));
+  WRITE_REG32 (DOEPCTL (EndPoint), Data & ~DXEPCTL_STALL);
+  /* EPx OUT ACTIVE */
+  Data = READ_REG32 (DOEPCTL (EndPoint));
+  WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_USBACTEP);
+
+  if (Len >= DATA_SIZE) {
+    RxDescBytes = DATA_SIZE;
+  } else {
+    RxDescBytes = Len;
+  }
+
+  RxBuf = AllocatePool (DATA_SIZE);
+  if (RxBuf == NULL) {
+    DEBUG ((DEBUG_ERROR, "EndPointRx: failed to allocate buffer\n"));
+    return;
+  }
+
+  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 (EndPoint), (UINT32)(UINTN)gDmaDesc);
+  /* EPx OUT ENABLE CLEARNAK */
+  Data = READ_REG32 (DOEPCTL (EndPoint));
+  WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK);
+}
+
+STATIC
+EFI_STATUS
+HandleGetDescriptor (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  UINTN                             ResponseSize;
+  VOID                             *ResponseData;
+  EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;
+  UINTN                             DescriptorSize;
+
+  ResponseSize = 0;
+  ResponseData = NULL;
+
+  // Pretty confused if bmRequestType is anything but this:
+  if (Request->RequestType != USB_DEV_GET_DESCRIPTOR_REQ_TYPE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Choose the response
+  //
+  switch (DESCRIPTOR_TYPE(Request->Value)) {
+  case USB_DESC_TYPE_DEVICE:
+    DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for device descriptor\n"));
+    ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
+    ResponseData = gDwUsbDescriptor.DeviceDescriptor;
+    break;
+  case USB_DESC_TYPE_CONFIG:
+    DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for config descriptor\n"));
+    ResponseSize = gDwUsbDescriptor.ConfigDescriptor->TotalLength;
+    ResponseData = gDwUsbDescriptor.ConfigDescriptor;
+    break;
+  case USB_DESC_TYPE_STRING:
+    DEBUG ((
+      DEBUG_INFO,
+      "DwUsbDxe: Got a request for String descriptor %d\n",
+      Request->Value & 0xFF
+      ));
+    switch (DESCRIPTOR_INDEX(Request->Value)) {
+    case 0:
+      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
+                       (LANG_LENGTH + 1) * sizeof (CHAR16);
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      if (Descriptor == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      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 + 1) * sizeof (CHAR16);
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      if (Descriptor == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      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 + 1) * sizeof (CHAR16);
+      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
+      if (Descriptor == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      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);
+      if (Descriptor == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      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,
+      "DwUsbDxe: Didn't understand request for descriptor 0x%04x\n",
+      Request->Value
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Send the response
+  //
+  if (Request->Length < ResponseSize) {
+    //
+    // Truncate response
+    //
+    ResponseSize = Request->Length;
+  } else if (Request->Length > ResponseSize) {
+    DEBUG ((DEBUG_INFO, "DwUsbDxe: Info: ResponseSize < wLength\n"));
+  }
+
+  EndPointTx (ENDPOINT0, ResponseData, ResponseSize);
+  if (Descriptor) {
+    FreePool (Descriptor);
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+HandleSetAddress (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  UINT32                 Data;
+
+  //
+  // Pretty confused if bmRequestType is anything but this:
+  //
+  if (Request->RequestType != USB_DEV_SET_ADDRESS_REQ_TYPE) {
+    return EFI_INVALID_PARAMETER;
+  }
+  DEBUG ((DEBUG_INFO, "DwUsbDxe: Setting address to %d\n", Request->Value));
+  ResetEndpoints ();
+
+  Data = READ_REG32 (DCFG);
+  Data &= ~DCFG_DEVADDR_MASK;
+  Data |= DCFG_DEVADDR (Request->Value);
+  WRITE_REG32 (DCFG, Data);
+  EndPointTx (ENDPOINT0, NULL, 0);
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+UsbDrvRequestEndpoint (
+  IN UINTN           Type,
+  IN UINTN           Dir
+  )
+{
+  UINTN              EndPoint = 1;
+  UINTN              NewBits;
+  UINT32             Data;
+
+  NewBits = DXEPCTL_EPTYPE (Type) | BIT28;
+
+  /*
+   * (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 == DIR_IN) {  // IN: to host
+    Data = READ_REG32 (DIEPCTL (EndPoint));
+    Data &= ~DXEPCTL_EPTYPE_MASK;
+    Data |= NewBits | DXEPCTL_TXFNUM (EndPoint) | DXEPCTL_NAKSTS;
+    WRITE_REG32 (DIEPCTL (EndPoint), Data);
+  } else {    // OUT: to device
+    Data = READ_REG32 (DOEPCTL (EndPoint));
+    Data &= ~DXEPCTL_EPTYPE_MASK;
+    Data |= NewBits;
+    WRITE_REG32 (DOEPCTL (EndPoint), Data);
+  }
+}
+
+STATIC
+EFI_STATUS
+HandleSetConfiguration (
+  IN USB_DEVICE_REQUEST  *Request
+  )
+{
+  UINT32                 Data;
+
+  if (Request->RequestType != USB_DEV_SET_CONFIGURATION_REQ_TYPE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Cancel all transfers
+  //
+  ResetEndpoints ();
+
+  UsbDrvRequestEndpoint (2, DIR_OUT);
+  UsbDrvRequestEndpoint (2, DIR_IN);
+
+  Data = READ_REG32 (DIEPCTL1);
+  WRITE_REG32 (DIEPCTL1, Data | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);
+
+  /* Enable interrupts on all endpoints */
+  WRITE_REG32 (DAINTMSK, ~0);
+
+  EndPointRx (ENDPOINT1, CMD_SIZE);
+  EndPointTx (ENDPOINT0, NULL, 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;
+}
+
+STATIC
+VOID
+HandleEndPointInEvent (
+  VOID
+  )
+{
+  UINT32              EndPointInts;
+
+  EndPointInts = READ_REG32 (DIEPINT0);
+  WRITE_REG32 (DIEPINT0, EndPointInts);
+  if (EndPointInts & DXEPINT_XFERCOMPL) {
+    DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));
+  }
+
+  EndPointInts = READ_REG32 (DIEPINT1);
+  WRITE_REG32 (DIEPINT1, EndPointInts);
+  if (EndPointInts & DXEPINT_XFERCOMPL) {
+    DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));
+  }
+}
+
+STATIC
+VOID
+HandleEndPointOutEvent (
+  VOID
+  )
+{
+  UINT32              EndPointInts;
+  UINT32              Data;
+
+  /*
+   * indicates the status of an endpoint
+   * with respect to USB- and AHB-related events.
+   */
+  EndPointInts = READ_REG32 (DOEPINT0);
+  if (EndPointInts) {
+    WRITE_REG32 (DOEPINT0, EndPointInts);
+    if (EndPointInts & 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 (EndPointInts & BIT3) { /* SETUP phase done */
+      Data = READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK;
+      WRITE_REG32 (DIEPCTL0, Data);
+      Data = READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK;
+      WRITE_REG32 (DOEPCTL0, Data);
+      /* 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);
+  }
+
+  EndPointInts = (READ_REG32 (DOEPINT1));
+  if (EndPointInts) {
+    WRITE_REG32 (DOEPINT1, EndPointInts);
+    /* Transfer Completed Interrupt (XferCompl);Transfer completed */
+    if (EndPointInts & 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;
+      }
+
+      EndPointRx (ENDPOINT1, Len);
+    }
+  }
+}
+
+//
+// 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;
+  UINT32              Data;
+
+  //
+  // 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 : MAX_PACKET_SIZE_CONTROL;
+    //
+    // Set Maximum In Packet Size (MPS)
+    //
+    Data = READ_REG32 (DIEPCTL1);
+    Data &= ~DXEPCTL_MPS_MASK;
+    Data |= MaxPacket;
+    WRITE_REG32 (DIEPCTL1, Data);
+    //
+    //Set Maximum Out Packet Size (MPS)
+    //
+    Data = READ_REG32 (DOEPCTL1);
+    Data &= ~DXEPCTL_MPS_MASK;
+    Data |= MaxPacket;
+    WRITE_REG32 (DOEPCTL1, Data);
+  }
+
+  /*
+   * 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) {
+    HandleEndPointInEvent ();
+  }
+
+  /*
+   * 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) {
+    HandleEndPointOutEvent ();
+  }
+
+  //
+  // clear ints
+  //
+  WRITE_REG32 (GINTSTS, Ints);
+}
+
+EFI_STATUS
+DwUsbSend (
+  IN        UINT8  EndpointIndex,
+  IN        UINTN  Size,
+  IN  CONST VOID  *Buffer
+  )
+{
+    EndPointTx (EndpointIndex, Buffer, Size);
+    return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+DwUsbInit (
+  VOID
+  )
+{
+  VOID          *Buf;
+  UINT32        Data;
+  EFI_STATUS    Status;
+
+  Status = DmaAllocateBuffer (
+             EfiBootServicesData,
+             DWUSB_BUFFER_PAGE_NUM,
+             (VOID *)&Buf
+             );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+  gDmaDesc = Buf;
+  gDmaDescEp0 = gDmaDesc + sizeof (DwUsbDevDmaDesc);
+  gDmaDescIn = gDmaDescEp0 + sizeof (DwUsbDevDmaDesc);
+  gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (DwUsbDevDmaDesc);
+
+  ZeroMem (Buf, EFI_PAGE_SIZE * DWUSB_BUFFER_PAGE_NUM);
+
+  /* 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) == 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, GUSBCFG_USBTRDTIM_8BIT);
+
+  /* Detect usb work mode,host or device? */
+  do {
+    Data = READ_REG32 (GINTSTS);
+  } while (Data & GINTSTS_CURMODE_HOST);
+
+  /* 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;   // unknown reserved bits
+  WRITE_REG32 (GOTGINT, Data);
+
+  /* endpoint settings cfg */
+  ResetEndpoints ();
+  /* wait for stable */
+  MicroSecondDelay (1);
+
+  /* init finish. and ready to transfer data */
+
+  /* Soft Disconnect */
+  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);
+  /* wait for stable */
+  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
+  )
+{
+  EFI_STATUS                Status;
+  EFI_EVENT                 TimerEvent;
+
+  if ((DeviceDescriptor == NULL) ||
+      (Descriptors[0] == NULL) ||
+      (RxCallback == NULL) ||
+      (TxCallback == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DwUsbInit();
+
+  gDwUsbDescriptor.DeviceDescriptor = DeviceDescriptor;
+  //
+  // Right now we just support one configuration
+  //
+  ASSERT (gDwUsbDescriptor.DeviceDescriptor->NumConfigurations == 1);
+  gDwUsbDescriptor.DeviceDescriptor->StrManufacturer = DESCRIPTOR_INDEX_MANUFACTURER;
+  gDwUsbDescriptor.DeviceDescriptor->StrProduct = DESCRIPTOR_INDEX_PRODUCT;
+  gDwUsbDescriptor.DeviceDescriptor->StrSerialNumber = DESCRIPTOR_INDEX_SERIALNUMBER;
+  //
+  // ... and one interface
+  //
+  gDwUsbDescriptor.ConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)Descriptors[0];
+  ASSERT (gDwUsbDescriptor.ConfigDescriptor->NumInterfaces == 1);
+
+  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
+                );
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-10-22  2:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-21 11:35 [PATCH v1 1/1] EmbeddedPkg/Drivers: add DwUsbDxe Haojian Zhuang
2018-10-05 15:46 ` Leif Lindholm
2018-10-22  2:32   ` Haojian Zhuang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox