diff mbox series

[edk2,v1,2/2] EmbeddedPkg/Drivers: add DwUsb3Dxe driver

Message ID 1534761085-26972-3-git-send-email-haojian.zhuang@linaro.org
State New
Headers show
Series add DwUsb3Dxe driver | expand

Commit Message

Haojian Zhuang Aug. 20, 2018, 10:31 a.m. UTC
Add Designware USB 3.0 device driver. It's focus on USB device
functionality, not USB Host functionality. The USB driver is
mainly used for Android Fastboot application.

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/DwUsb3Dxe/DwUsb3Dxe.dec |   44 +
 EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf |   52 +
 EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h   |  632 +++++
 EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c   | 2434 ++++++++++++++++++++
 4 files changed, 3162 insertions(+)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Leif Lindholm Oct. 4, 2018, 4:32 p.m. UTC | #1
On Mon, Aug 20, 2018 at 06:31:25PM +0800, Haojian Zhuang wrote:
> Add Designware USB 3.0 device driver. It's focus on USB device

> functionality, not USB Host functionality. The USB driver is

> mainly used for Android Fastboot application.

> 

> 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/DwUsb3Dxe/DwUsb3Dxe.dec |   44 +

>  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf |   52 +

>  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h   |  632 +++++

>  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c   | 2434 ++++++++++++++++++++

>  4 files changed, 3162 insertions(+)

> 

> diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec

> new file mode 100644

> index 000000000000..038e4881a948

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec

> @@ -0,0 +1,44 @@

> +#/** @file

> +# Framework Module Development Environment Industry Standards


Please change this to reflect this package rather than EmbeddedPkg one
(which appears to have stolen it from an old version of MdePkg.dec :)

> +#

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


I see no need to keep these copyright statements.

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

> +  PACKAGE_GUID                   = 9b7aa6fe-405b-4955-af1f-5faf183aedec

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

> +  gDwUsb3DxeTokenSpaceGuid      = { 0x098a50d3, 0x92e2, 0x461a, { 0xb6, 0xba, 0xf8, 0x5d, 0x9d, 0x89, 0x49, 0xf5 }}

> +

> +[Protocols.common]

> +  gDwUsbProtocolGuid            = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}


Please make this file a common .dec for DwUsb and DwUsb3 instead of
duplicating guid information.
(If we weren't moving it to edk2-platforms, it would still have been
better to add it to EmbeddedPkg.dec.)

> +

> +[PcdsFixedAtBuild.common]

> +  # DwUsb Driver PCDs

> +  gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress|0x0|UINT32|0x00000001

> diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf

> new file mode 100644

> index 000000000000..510b51a34de7

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf

> @@ -0,0 +1,52 @@

> +#/** @file

> +#

> +#  Copyright (c) 2018, Linaro Limited. 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                      = DwUsb3Dxe

> +  FILE_GUID                      = 0879cd34-c399-4315-9891-56024072e711

> +  MODULE_TYPE                    = UEFI_DRIVER

> +  VERSION_STRING                 = 1.0

> +  ENTRY_POINT                    = DwUsb3EntryPoint

> +

> +[Sources.common]

> +  DwUsb3Dxe.c

> +

> +[LibraryClasses]

> +  CacheMaintenanceLib

> +  DebugLib

> +  DmaLib

> +  IoLib

> +  MemoryAllocationLib

> +  TimerLib

> +  UefiBootServicesTableLib

> +  UefiDriverEntryPoint

> +  UsbSerialNumberLib


I don't see this library anywhere in the tree?

> +

> +[Protocols]

> +  gEfiDriverBindingProtocolGuid

> +  gUsbDeviceProtocolGuid

> +

> +[Packages]

> +  ArmPkg/ArmPkg.dec

> +  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec

> +  EmbeddedPkg/EmbeddedPkg.dec

> +  MdePkg/MdePkg.dec

> +  MdeModulePkg/MdeModulePkg.dec

> +

> +[Pcd]

> +  gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress

> +

> +[Depex]

> +  TRUE

> diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h

> new file mode 100644

> index 000000000000..92b610553169

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h

> @@ -0,0 +1,632 @@

> +/** @file

> +

> +  Copyright (c) 2017, Linaro Limited. 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_USB3_DXE_H__

> +#define __DW_USB3_DXE_H__


DW -> DESIGNWARE (throughout).

> +

> +#define DW_USB3_BASE                     FixedPcdGet32 (PcdDwUsb3DxeBaseAddress)

> +

> +#define GSBUCFG0                         (DW_USB3_BASE + 0xC100)

> +#define GCTL                             (DW_USB3_BASE + 0xC110)

> +

> +#define GCTL_PWRDNSCALE_MASK             (0x1FFF << 19)

> +#define GCTL_PWRDNSCALE(x)               (((x) & 0x1FFF) << 19)

> +#define GCTL_U2RSTECN                    BIT16

> +#define GCTL_PRTCAPDIR_MASK              (BIT13 | BIT12)

> +#define GCTL_PRTCAPDIR_HOST              BIT12

> +#define GCTL_PRTCAPDIR_DEVICE            BIT13

> +#define GCTL_PRTCAPDIR_OTG               (BIT13 | BIT12)

> +#define GCTL_U2EXIT_LFPS                 BIT2

> +

> +#define GUSB2PHYCFG(x)                   (DW_USB3_BASE + 0xC200 + (((x) & 0xF) << 2))

> +

> +#define GUSB2PHYCFG_USBTRDTIM_MASK       (0xF << 10)

> +#define GUSB2PHYCFG_USBTRDTIM(x)         (((x) & 0xF) << 10)

> +#define GUSB2PHYCFG_SUSPHY               BIT6

> +

> +#define GUSB3PIPECTL(x)                  (DW_USB3_BASE + 0xC2C0 + (((x) & 0x3) << 2))

> +

> +#define PIPECTL_DELAYP1TRANS             BIT18

> +#define PIPECTL_SUSPEND_EN               BIT17

> +#define PIPECTL_LFPS_FILTER              BIT9

> +#define PIPECTL_TX_DEMPH_MASK            (0x3 << 1)

> +#define PIPECTL_TX_DEMPH(x)              (((x) & 0x3) << 1)

> +

> +#define GTXFIFOSIZ(x)                    (DW_USB3_BASE + 0xC300 + (((x) & 0x1F) << 2))

> +#define GRXFIFOSIZ(x)                    (DW_USB3_BASE + 0xC380 + (((x) & 0x1F) << 2))

> +

> +#define FIFOSIZ_ADDR(x)                  (((x) & 0xFFFF) << 16)

> +#define FIFOSIZ_DEP(x)                   ((x) & 0xFFFF)

> +

> +#define GEVNTADRL(x)                     (DW_USB3_BASE + 0xC400 + (((x) & 0x1F) << 2))

> +#define GEVNTADRH(x)                     (DW_USB3_BASE + 0xC404 + (((x) & 0x1F) << 2))

> +#define GEVNTSIZ(x)                      (DW_USB3_BASE + 0xC408 + (((x) & 0x1F) << 2))

> +

> +#define GEVNTSIZ_EVNTINTMASK             BIT31

> +#define GEVNTSIZ_EVNTSIZ_MASK            (0xFFFF)

> +#define GEVNTSIZ_EVNTSIZ(x)              ((x) & 0xFFFF)

> +

> +#define GEVNTCOUNT(x)                    (DW_USB3_BASE + 0xC40C + (((x) & 0x1F) << 2))

> +#define GEVNTCOUNT_EVNTCOUNT_MASK        (0xFFFF)

> +#define GEVNTCOUNT_EVNTCOUNT(x)          ((x) & 0xFFFF)

> +

> +// Non-Endpoint specific event flag

> +#define GEVNT_INTTYPE_MASK               (0x7F << 1)

> +#define GEVNT_INTTYPE(x)                 (((x) & 0x7F) << 1)

> +#define EVENT_I2C_INT                    4

> +#define EVENT_CARKIT_INT                 3

> +#define EVENT_OTG_INT                    1

> +#define EVENT_DEV_INT                    0

> +

> +#define GEVNT_NON_EP                     BIT0

> +// Endpoint specific event flag

> +#define GEVNT_DEPEVT_INTTYPE_MASK        (0xF << 6)

> +#define GEVNT_DEPEVT_INTTYPE(x)          (((x) & 0xF) << 6)

> +#define GEVNT_DEPEVT_INTTYPE_EPCMD_CMPL  (7 << 6)

> +#define GEVNT_DEPEVT_INTTYPE_STRM_EVT    (6 << 6)

> +#define GEVNT_DEPEVT_INTTYPE_FIFOXRUN    (4 << 6)

> +#define GEVNT_DEPEVT_INTTYPE_XFER_NRDY   (3 << 6)

> +#define GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG (2 << 6)

> +#define GEVNT_DEPEVT_INTTYPE_XFER_CMPL   (1 << 6)

> +#define GEVNT_DEPEVT_EPNUM_MASK          (0x1F << 1)

> +#define GEVNT_DEPEVT_EPNUM_SHIFT         1

> +#define GEVNT_DEPEVT_EPNUM(x)            (((x) & 0x1F) << 1)

> +// Devices specific event flag

> +#define GEVNT_DEVT_MASK                  (0xF << 8)

> +#define GEVNT_DEVT_SHIFT                 8

> +#define GEVNT_DEVT(x)                    (((x) & 0xF) << 8)

> +#define GEVNT_DEVT_INACT_TIMEOUT_RCVD    (0x15 << 8)

> +#define GEVNT_DEVT_VNDR_DEV_TST_RCVD     (0x14 << 8)

> +#define GEVNT_DEVT_OVERFLOW              (0x13 << 8)

> +#define GEVNT_DEVT_CMD_CMPL              (0x12 << 8)

> +#define GEVNT_DEVT_ERRATICERR            (0x11 << 8)

> +#define GEVNT_DEVT_SOF                   (0x7 << 8)

> +#define GEVNT_DEVT_EOPF                  (0x6 << 8)

> +#define GEVNT_DEVT_HIBER_REQ             (0x5 << 8)

> +#define GEVNT_DEVT_WKUP                  (0x4 << 8)

> +#define GEVNT_DEVT_ULST_CHNG             (0x3 << 8)

> +#define GEVNT_DEVT_CONNDONE              (0x2 << 8)

> +#define GEVNT_DEVT_USBRESET              (0x1 << 8)

> +#define GEVNT_DEVT_DISCONN               (0x0 << 8)

> +

> +#define DCFG                             (DW_USB3_BASE + 0xC700)

> +

> +#define DCFG_NUMP_MASK                   (0x1F << 17)

> +#define DCFG_NUMP(x)                     (((x) & 0x1F) << 17)

> +#define DCFG_DEVADDR_MASK                (0x7F << 3)

> +#define DCFG_DEVADDR(x)                  (((x) & 0x7F) << 3)

> +#define DCFG_DEVSPD_MASK                 (0x7)

> +#define DCFG_DEVSPD(x)                   ((x) & 0x7)

> +#define DEVSPD_HS_PHY_30MHZ_OR_60MHZ     0

> +#define DEVSPD_FS_PHY_30MHZ_OR_60MHZ     1

> +#define DEVSPD_LS_PHY_6MHZ               2

> +#define DEVSPD_FS_PHY_48MHZ              3

> +#define DEVSPD_SS_PHY_125MHZ_OR_250MHZ   4

> +

> +#define DCTL                             (DW_USB3_BASE + 0xC704)

> +

> +#define DCTL_RUN_STOP                    BIT31

> +#define DCTL_CSFTRST                     BIT30

> +#define DCTL_INIT_U2_EN                  BIT12

> +#define DCTL_ACCEPT_U2_EN                BIT11

> +#define DCTL_INIT_U1_EN                  BIT10

> +#define DCTL_ACCEPT_U1_EN                BIT9

> +

> +#define DEVTEN                           (DW_USB3_BASE + 0xC708)

> +#define DEVTEN_CONNECTDONEEN             BIT2

> +#define DEVTEN_USBRSTEN                  BIT1

> +#define DEVTEN_DISCONNEN                 BIT0

> +

> +#define DSTS                             (DW_USB3_BASE + 0xC70C)

> +#define DSTS_GET_DEVSPD(x)               ((x) & 0x7)

> +

> +#define DALEPENA                         (DW_USB3_BASE + 0xC720)

> +

> +#define DEPCMDPAR2(x)                    (DW_USB3_BASE + 0xC800 + ((x) & 0x1F) * 0x10)

> +#define DEPCMDPAR1(x)                    (DW_USB3_BASE + 0xC804 + ((x) & 0x1F) * 0x10)

> +#define DEPCMDPAR0(x)                    (DW_USB3_BASE + 0xC808 + ((x) & 0x1F) * 0x10)

> +#define DEPCMD(x)                        (DW_USB3_BASE + 0xc80C + ((x) & 0x1F) * 0x10)

> +

> +#define DEPCMD_COMMANDPARAM_MASK         (0xFFFF << 16)

> +#define DEPCMD_COMMANDPARAM(x)           (((x) & 0xFFFF) << 16)

> +/* Stream Number or uFrame (input) */

> +#define DEPCMD_STR_NUM_OR_UF_MASK        (0xFFFF << 16)

> +#define DEPCMD_STR_NUM_OR_UF(x)          (((x) & 0xFFFF) << 16)

> +/* Transfer Resource Index (output) */

> +#define DEPCMD_XFER_RSRC_IDX_SHIFT       16

> +#define DEPCMD_XFER_RSRC_IDX_MASK        (0x7F << 16)

> +#define DEPCMD_XFER_RSRC_IDX(x)          (((x) & 0x7F) << 16)

> +#define GET_DEPCMD_XFER_RSRC_IDX(x)      (((x) >> 16) & 0x7F)

> +#define DEPCMD_CMDACT                    BIT10

> +#define DEPCMD_CMDTYPE_MASK              0xFF

> +#define DEPCMD_CMDTYPE(x)                ((x) & 0xFF)

> +

> +/* EP registers range as: OUT0, IN0, OUT1, IN1, ... */

> +#define EP_OUT_IDX(x)                    ((x) * 2)

> +#define EP_IN_IDX(x)                     (((x) * 2) + 1)

> +

> +#define CMDTYPE_SET_EP_CFG               1

> +#define CMDTYPE_SET_XFER_CFG             2

> +#define CMDTYPE_GET_EP_STATE             3

> +#define CMDTYPE_SET_STALL                4

> +#define CMDTYPE_CLR_STALL                5

> +#define CMDTYPE_START_XFER               6

> +#define CMDTYPE_UPDATE_XFER              7

> +#define CMDTYPE_END_XFER                 8

> +#define CMDTYPE_START_NEW_CFG            9

> +

> +#define EPTYPE_CONTROL                   0

> +#define EPTYPE_ISOC                      1

> +#define EPTYPE_BULK                      2

> +#define EPTYPE_INTR                      3

> +

> +#define CFG_ACTION_INIT                  0

> +#define CFG_ACTION_RESTORE               1

> +#define CFG_ACTION_MODIFY                2

> +

> +#define EPCFG0_CFG_ACTION_MASK           (0x3 << 30)

> +#define EPCFG0_CFG_ACTION(x)             (((x) & 0x3) << 30)

> +#define EPCFG0_BRSTSIZ_MASK              (0xF << 22)

> +#define EPCFG0_BRSTSIZ(x)                (((x) & 0xF) << 22)

> +#define EPCFG0_TXFNUM_MASK               (0x1F << 17)

> +#define EPCFG0_TXFNUM(x)                 (((x) & 0x1F) << 17)

> +#define EPCFG0_MPS_MASK                  (0x7FF << 3)

> +#define EPCFG0_MPS(x)                    (((x) & 0x7FF) << 3)

> +#define EPCFG0_EPTYPE_MASK               (0x3 << 1)

> +#define EPCFG0_EPTYPE_SHIFT              1

> +#define EPCFG0_EPTYPE(x)                 (((x) & 0x3) << 1)

> +

> +/* Endpoint Number */

> +#define EPCFG1_EP_NUM_MASK               (0xF << 26)

> +#define EPCFG1_EP_NUM(x)                 (((x) & 0xF) << 26)

> +/* Endpoint Direction */

> +#define EPCFG1_EP_DIR_IN                 BIT25

> +/* Stream Not Ready */

> +#define EPCFG1_XFER_NRDY                 BIT10

> +/* XferInProgress Enable */

> +#define EPCFG1_XFER_IN_PROG              BIT9

> +/* Stream Completed */

> +#define EPCFG1_XFER_CMPL                 BIT8

> +

> +#define USB_SPEED_UNKNOWN                0

> +#define USB_SPEED_LOW                    1

> +#define USB_SPEED_FULL                   2

> +#define USB_SPEED_HIGH                   3

> +#define USB_SPEED_VARIABLE               4

> +#define USB_SPEED_SUPER                  5

> +

> +// DMA registers

> +#define DSCSTS_TRBRSP_MASK               (0xF << 28)

> +#define DSCSTS_TRBRSP(x)                 (((x) & 0xF) << 28)

> +#define GET_DSCSTS_TRBRSP(x)             (((x) >> 28) & 0xF)

> +#define TRBRSP_MISSED_ISOC_IN            1

> +#define TRBRSP_SETUP_PEND                2

> +#define TRBRSP_XFER_IN_PROG              4

> +#define DSCSTS_PCM1_MASK                 (0x3 << 24)

> +#define DSCSTS_PCM1(x)                   (((x) & 0x3) << 24)

> +#define DSCSTS_XFERCNT_MASK              0xFFFFFF

> +#define DSCSTS_XFERCNT(x)                ((x) & 0xFFFFFF)

> +#define GET_DSCSTS_XFERCNT(x)            ((x) & 0xFFFFFF)

> +

> +#define DSCCTL_STRMID_SOFN(x)            (((x) & 0xFFFF) << 14)

> +#define DSCCTL_IOC                       BIT11

> +#define DSCCTL_ISP                       BIT10

> +#define DSCCTL_TRBCTL_MASK               (0x3F << 4)

> +#define DSCCTL_TRBCTL(x)                 (((x) & 0x3F) << 4)

> +#define DSCCTL_LST                       BIT1

> +#define DSCCTL_HWO                       BIT0

> +#define TRBCTL_NORMAL                    1

> +#define TRBCTL_SETUP                     2

> +#define TRBCTL_STATUS_2                  3

> +#define TRBCTL_STATUS_3                  4

> +#define TRBCTL_CTLDATA_1ST               5

> +#define TRBCTL_ISOC_1ST                  6

> +#define TRBCTL_ISOC                      7

> +#define TRBCTL_LINK                      8

> +#define TRBCTL_NORMAL_ZLP                9

> +

> +

> +#define UE_DIR_IN                        0x80

> +#define UE_DIR_OUT                       0

> +#define UE_SET_DIR(a, d)                 ((a) | (((d) & 1) << 7))

> +#define UE_GET_DIR(a)                    ((a) & 0x80)

> +#define UE_ADDR                          0x0F

> +#define UE_GET_ADDR(a)                   ((a) & UE_ADDR)

> +

> +#define UT_GET_DIR(a)                    ((a) & 0x80)

> +#define UT_WRITE                         0x00

> +#define UT_READ                          0x80

> +

> +#define UT_GET_TYPE(a)                   ((a) & 0x60)

> +#define UT_STANDARD                      0x00

> +#define UT_CLASS                         0x20

> +#define UT_VENDOR                        0x40

> +

> +#define UT_GET_RECIPIENT(a)              ((a) & 0x1f)

> +#define UT_DEVICE                        0x00

> +#define UT_INTERFACE                     0x01

> +#define UT_ENDPOINT                      0x02

> +#define UT_OTHER                         0x03

> +

> +#define UR_GET_STATUS                    0x00

> +#define UR_CLEAR_FEATURE                 0x01

> +#define UR_SET_FEATURE                   0x03

> +#define UR_SET_ADDRESS                   0x05

> +#define UR_GET_DESCRIPTOR                0x06

> +#define UR_SET_DESCRIPTOR                0x07

> +#define UR_GET_CONFIG                    0x08

> +#define UR_SET_CONFIG                    0x09

> +#define UR_GET_INTERFACE                 0x0A

> +#define UR_SET_INTERFACE                 0x0B

> +#define UR_SYNCH_FRAME                   0x0C

> +#define UR_SET_SEL                       0x30

> +#define UR_SET_ISOC_DELAY                0x31

> +


Somewhere around here starts a bunch of redefinitions of things
already described in MdePkg/Include/IndustryStandard/Usb.h.
Can you please reuse that include file as much as possible.

> +/* Feature numbers */

> +#define UF_ENDPOINT_HALT                 0

> +#define UF_DEVICE_REMOTE_WAKEUP          1

> +#define UF_TEST_MODE                     2

> +#define UF_DEVICE_B_HNP_ENABLE           3

> +#define UF_DEVICE_A_HNP_SUPPORT          4

> +#define UF_DEVICE_A_ALT_HNP_SUPPORT      5

> +#define UF_FUNCTION_SUSPEND              0

> +#define UF_U1_ENABLE                     48

> +#define UF_U2_ENABLE                     49

> +#define UF_LTM_ENABLE                    50

> +

> +#define  UDESC_DEVICE                    0x01

> +#define  UDESC_CONFIG                    0x02

> +#define  UDESC_STRING                    0x03

> +#define  UDESC_INTERFACE                 0x04

> +#define  UDESC_ENDPOINT                  0x05

> +#define  UDESC_SS_USB_COMPANION          0x30

> +#define  UDESC_DEVICE_QUALIFIER          0x06

> +#define  UDESC_BOS                       0x0f

> +#define  UDESC_DEVICE_CAPABILITY         0x10

> +

> +#define STRING_LANGUAGE                  0

> +#define STRING_MANUFACTURER              1

> +#define STRING_PRODUCT                   2

> +#define STRING_SERIAL                    3

> +

> +#define CONFIG_VALUE    1

> +

> +#define USB3_BULK_IN_EP                  1

> +#define USB3_BULK_OUT_EP                 1

> +

> +#define USB_ENUM_ADB_PORT_VID            0x18D1

> +#define USB_ENUM_ADB_PORT_PID            0xD00D

> +#define USB_ENUM_INTERFACE_ADB_SUBCLASS  0x42

> +#define USB_ENUM_INTERFACE_ADB_PROTOCOL  0x03

> +

> +struct usb3_pcd;

> +

> +typedef enum pcd_state {

> +  USB3_STATE_UNCONNECTED,                /* no host */

> +  USB3_STATE_DEFAULT,

> +  USB3_STATE_ADDRESSED,

> +  USB3_STATE_CONFIGURED,

> +} pcdstate_e;


These structs also break the coding style completely.
Will using IndustryStandard/Usb.h get rid of all of that?

> +

> +typedef enum ep0_state {

> +  EP0_IDLE,

> +  EP0_IN_DATA_PHASE,

> +  EP0_OUT_DATA_PHASE,

> +  EP0_IN_WAIT_NRDY,

> +  EP0_OUT_WAIT_NRDY,

> +  EP0_IN_STATUS_PHASE,

> +  EP0_OUT_STATUS_PHASE,

> +  EP0_STALL,

> +} ep0state_e;

> +

> +typedef struct usb3_dma_desc {

> +  /** Buffer Pointer - Low address quadlet */

> +  UINT32     bptl;

> +

> +  /** Buffer Pointer - High address quadlet */

> +  UINT32     bpth;

> +

> +  /** Status quadlet. Fields defined in enum @ref desc_sts_data. */

> +  UINT32     status;

> +

> +  /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */

> +  UINT32     control;

> +} usb3_dma_desc_t;

> +

> +typedef struct usb3_pcd_req {

> +  usb3_dma_desc_t *trb;

> +  UINT64 trbdma;

> +

> +  UINT32 length;

> +  UINT32 actual;

> +

> +  UINT64 *bufdma;

> +  int (*complete)(unsigned actual, int status);

> +} usb3_pcd_req_t;

> +

> +typedef struct usb_device_request {

> +  UINT8 bmRequestType;

> +  UINT8 bRequest;

> +  UINT16 wValue;

> +  UINT16 wIndex;

> +  UINT16 wLength;

> +} usb_device_request_t;

> +

> +#pragma pack(1)

> +/** USB_DT_DEVICE: Device descriptor */

> +typedef struct usb_device_descriptor {

> +  UINT8  bLength;

> +  UINT8  bDescriptorType;

> +

> +  UINT16 bcdUSB;

> +#define USB_CLASS_COMM          0x02

> +#define USB_CLASS_VENDOR_SPEC   0xFF

> +#define USB_SC_VENDOR_SPEC      0xFF

> +#define USB_PR_VENDOR_SPEC      0xFF

> +  UINT8  bDeviceClass;

> +  UINT8  bDeviceSubClass;

> +  UINT8  bDeviceProtocol;

> +  UINT8  bMaxPacketSize0;

> +  UINT16 idVendor;

> +  UINT16 idProduct;

> +  UINT16 bcdDevice;

> +  UINT8  iManufacturer;

> +  UINT8  iProduct;

> +  UINT8  iSerialNumber;

> +  UINT8  bNumConfigurations;

> +} usb_device_descriptor_t;

> +

> +/* USB_DT_CONFIG: Config descriptor */

> +typedef struct usb_config_descriptor {

> +  UINT8  bLength;

> +  UINT8  bDescriptorType;

> +

> +  UINT16 wTotalLength;

> +  UINT8  bNumInterfaces;

> +#define CONFIG_VALUE            1

> +  UINT8  bConfigurationValue;

> +  UINT8  iConfiguration;

> +#define USB_CONFIG_ATT_ONE      (1 << 7)

> +  UINT8  bmAttributes;

> +#define USB_CONFIG_VBUS_DRAW    (0xFA)

> +  UINT8  bMaxPower;

> +} usb_config_descriptor_t;

> +

> +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */

> +typedef struct usb_qualifier_descriptor {

> +  UINT8  bLength;

> +  UINT8  bDescriptorType;

> +

> +  UINT16 bcdUSB;

> +  UINT8  bDeviceClass;

> +  UINT8  bDeviceSubClass;

> +  UINT8  bDeviceProtocol;

> +  UINT8  bMaxPacketSize0;

> +  UINT8  bNumConfigurations;

> +  UINT8  bRESERVED;

> +} usb_qualifier_descriptor_t;

> +

> +/* USB_DT_INTERFACE: Interface descriptor */

> +typedef struct usb_interface_descriptor {

> +  UINT8  bLength;

> +  UINT8  bDescriptorType;

> +

> +  UINT8  bInterfaceNumber;

> +  UINT8  bAlternateSetting;

> +  UINT8  bNumEndpoints;

> +  UINT8  bInterfaceClass;

> +  UINT8  bInterfaceSubClass;

> +  UINT8  bInterfaceProtocol;

> +  UINT8  iInterface;

> +} usb_interface_descriptor_t;

> +

> +/* USB_DT_ENDPOINT: Endpoint descriptor */

> +typedef struct usb_endpoint_descriptor {

> +  UINT8  bLength;

> +  UINT8  bDescriptorType;

> +

> +  UINT8  bEndpointAddress;

> +  UINT8  bmAttributes;

> +#define USB_ENDPOINT_XFER_CONTROL       0x00

> +#define USB_ENDPOINT_XFER_ISOC          0x01

> +#define USB_ENDPOINT_XFER_BULK          0x02

> +#define USB_ENDPOINT_XFER_INT           0x03

> +  UINT16 wMaxPacketSize;

> +  UINT8  bInterval;

> +} usb_endpoint_descriptor_t;

> +

> +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */

> +typedef struct usb_ss_ep_comp_descriptor {

> +  UINT8  bLength;

> +  UINT8  bDescriptorType;

> +

> +  UINT8  bMaxBurst;

> +  UINT8  bmAttributes;

> +  UINT16 wBytesPerInterval;

> +} usb_ss_ep_comp_descriptor_t;

> +

> +/* WUSB BOS Descriptor (Binary device Object Store) */

> +typedef struct wusb_bos_desc {

> +  UINT8 bLength;

> +  UINT8 bDescriptorType;

> +  UINT16 wTotalLength;

> +  UINT8 bNumDeviceCaps;

> +} wusb_bos_desc_t;

> +

> +#define USB_DEVICE_CAPABILITY_20_EXTENSION      0x02

> +typedef struct usb_dev_cap_20_ext_desc {

> +  UINT8 bLength;

> +  UINT8 bDescriptorType;

> +  UINT8 bDevCapabilityType;

> +#define USB_20_EXT_LPM                          0x02

> +  UINT32 bmAttributes;

> +} usb_dev_cap_20_ext_desc_t;

> +

> +#define USB_DEVICE_CAPABILITY_SS_USB            0x03

> +typedef struct usb_dev_cap_ss_usb {

> +  UINT8 bLength;

> +  UINT8 bDescriptorType;

> +  UINT8 bDevCapabilityType;

> +#define USB_DC_SS_USB_LTM_CAPABLE               0x02

> +  UINT8 bmAttributes;

> +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW         0x01

> +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL        0x02

> +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH        0x04

> +#define USB_DC_SS_USB_SPEED_SUPPORT_SS          0x08

> +  UINT32 wSpeedsSupported;

> +  UINT8 bFunctionalitySupport;

> +  UINT8 bU1DevExitLat;

> +  UINT32 wU2DevExitLat;

> +} usb_dev_cap_ss_usb_t;

> +

> +#define USB_DEVICE_CAPABILITY_CONTAINER_ID      0x04

> +typedef struct usb_dev_cap_container_id {

> +  UINT8 bLength;

> +  UINT8 bDescriptorType;

> +  UINT8 bDevCapabilityType;

> +  UINT8 bReserved;

> +  UINT8 containerID[16];

> +} usb_dev_cap_container_id_t;

> +#pragma pack()

> +

> +typedef union usb_setup_pkt {

> +  usb_device_request_t req;

> +  UINT32 d32[2];

> +  UINT8 d8[8];

> +} usb_setup_pkt_t;

> +

> +typedef struct usb3_pcd_ep {

> +  struct usb3_pcd *pcd;

> +

> +  UINT8          EpInIdx;

> +  UINT8          EpOutIdx;

> +  UINT8          phys;

> +

> +  //UINT8 phys;

> +  UINT8 num;

> +  UINT8 type;

> +  UINT8 maxburst;

> +  UINT16 maxpacket;

> +  /* Tx FIFO # for IN EPs */

> +  UINT8 tx_fifo_num;

> +

> +  /* The Transfer Resource Index from the Start Transfer command */

> +  UINT8 tri_out;

> +  UINT8 tri_in;

> +

> +  UINT8 stopped;

> +  /* Send ZLP */

> +  UINT8 send_zlp;

> +  /* True if 3-stage control transfer */

> +  UINT8 three_stage;

> +  /* True if transfer has been started on EP */

> +  UINT8 xfer_started;

> +  /* EP direction 0 = OUT */

> +  UINT8 is_in;

> +  /* True if endpoint is active */

> +  UINT8 active;

> +  /* Initial data pid of bulk endpoint */

> +  UINT8 data_pid_start;

> +

> +  /* ep_desc (excluding ep0) */

> +  usb3_dma_desc_t *ep_desc;

> +

> +#if 0

> +  /* TRB descriptor must be aligned to 16 bytes */

> +  UINT8 epx_desc[32];

> +#endif

> +

> +  /* request (excluding ep0) */

> +  usb3_pcd_req_t req;

> +} usb3_pcd_ep_t;

> +

> +typedef struct usb3_pcd {

> +  //struct usb3_device *usb3_dev;

> +

> +  INT32 link_state;

> +  pcdstate_e state;

> +  UINT8 new_config;

> +  ep0state_e ep0state;

> +

> +  UINT32 eps_enabled;

> +  UINT32 ltm_enable;

> +

> +  usb3_pcd_ep_t ep0;

> +  usb3_pcd_ep_t out_ep;

> +  usb3_pcd_ep_t in_ep;

> +

> +  /*

> +  usb3_dev_global_regs_t *dev_global_regs;

> +  usb3_dev_ep_regs_t *out_ep_regs;

> +  usb3_dev_ep_regs_t *in_ep_regs;

> +  */

> +

> +  usb3_pcd_req_t ep0_req;

> +

> +  UINT8 speed;

> +

> +  usb3_dma_desc_t *ep0_setup_desc;

> +  usb3_dma_desc_t *ep0_in_desc;

> +  usb3_dma_desc_t *ep0_out_desc;

> +

> +  /* TRB descriptor must be aligned to 16 bytes */

> +#if 0

> +  UINT8 ep0_setup[32];

> +  UINT8 ep0_in[32];

> +  UINT8 ep0_out[32];

> +

> +  usb_setup_pkt_t ep0_setup_pkt[5];

> +

> +#define USB3_STATUS_BUF_SIZE    512

> +  UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE];

> +

> +#define USB3_BULK_BUF_SIZE      2048

> +  UINT8 ss_bulk_buf[USB3_BULK_BUF_SIZE];

> +#endif

> +

> +  UINT32 file_type;

> +  UINT32 file_address;

> +  UINT32 file_capacity;

> +  UINT32 file_total_frame;

> +  UINT32 file_curr_frame;

> +  UINT32 file_next_frame;

> +  UINT32 file_received;

> +  UINT32 file_complete;

> +

> +  UINT16 test_mode_nr;

> +  UINT16 test_mode;

> +} usb3_pcd_t;

> +

> +struct usb_enum_port_param {

> +  UINT16     idVendor;

> +  UINT16     idProduct;

> +  UINT8      bInterfaceSubClass;

> +  UINT8      bInterfaceProtocol;

> +};

> +

> +#if 0


If not used, leave it out.

> +typedef struct usb3_pcd_req {

> +  usb3_dma_desc_t *trb;

> +  UINT64 trbdma;

> +

> +  UINT32 length;

> +  UINT32 actual;

> +

> +  UINT64 *bufdma;

> +  int (*complete)(unsigned actual, int status);

> +} usb3_pcd_req_t;

> +

> +#endif

> +

> +#endif /* __DW_USB3_DXE_H__ */

> diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c

> new file mode 100644

> index 000000000000..83d5e4736de0

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c

> @@ -0,0 +1,2434 @@

> +/** @file

> +

> +  Copyright (c) 2018, Linaro Limited. 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/DriverBinding.h>

> +#include <Protocol/UsbDevice.h>

> +

> +#include "DwUsb3Dxe.h"

> +

> +#define FIFO_DIR_TX                  0

> +#define FIFO_DIR_RX                  1

> +

> +#define TX_FIFO_ADDR                 0

> +#define RX_FIFO_ADDR                 0

> +

> +#define RAM_WIDTH                    8

> +#define RAM_TX0_DEPTH                2048

> +#define RAM_TX1_DEPTH                4096

> +#define RAM_RX_DEPTH                 8192


Should these not also go into DwUsb3Dxe.h?

> +

> +#define USB_TYPE_LENGTH              16

> +#define USB_BLOCK_HIGH_SPEED_SIZE    512

> +#define DATA_SIZE                    131072

> +#define CMD_SIZE                     512


What do the above definitions mean?

> +#define MATCH_CMD_LITERAL(Cmd, Buf)  !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)


This one does not appear to be used?

> +

> +#define ALIGN(x, a)     (((x) + ((a) - 1)) & ~((a) - 1))


Use available macros in Base.h.

> +

> +//

> +// The time between interrupt polls, in units of 100 nanoseconds

> +// 10 Microseconds

> +//

> +#define DW_INTERRUPT_POLL_PERIOD     100

> +

> +#define DWUSB3_EVENT_BUF_SIZE        256

> +

> +//

> +// Maxpacket size for EP0, defined by USB3 spec

> +//

> +#define USB3_MAX_EP0_SIZE            512

> +

> +//

> +// Maxpacket size for any EP, defined by USB3 spec

> +//

> +#define USB3_MAX_PACKET_SIZE         1024

> +#define USB2_HS_MAX_PACKET_SIZE      512

> +#define USB2_FS_MAX_PACKET_SIZE      64

> +

> +#define USB3_STATE_UNCONNECTED       0

> +#define USB3_STATE_DEFAULT           1

> +#define USB3_STATE_ADDRESSED         2

> +#define USB3_STATE_CONFIGURED        3

> +

> +#define USB3_STATUS_BUF_SIZE         512


If these are defined by USB3 spec, please add them to
MdePkg/Include/IndustryStandard/Usb.h instead of defining them
locally.

> +

> +#define GET_EVENTBUF_COUNT()                                       \

> +        (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0))))

> +#define UPDATE_EVENTBUF_COUNT(x)                                   \

> +        (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x)))

> +

> +#define SET_DEVADDR(x)                                             \

> +        (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x)))


Should these not also move to DwUsb3Dxe.h?

> +

> +EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;


This looks less than ideal - this makes it impossible to include
DwUsb2 and DwUsb3 drivers in the same image.

> +

> +STATIC DW_USB_PROTOCOL                *DwUsb;

> +

> +STATIC usb3_pcd_t                     gPcd;


This seems a very unfortunate choice for variable name.

> +STATIC UINT32                         *gEventBuf, *gEventPtr;

> +STATIC struct usb_device_descriptor   gDwUsb3DevDesc;

> +STATIC VOID                           *gRxBuf;

> +

> +STATIC usb_setup_pkt_t                *gEndPoint0SetupPacket;

> +STATIC UINT8                          *gEndPoint0StatusBuf;


Although most if not all of these will disappear when converting to
UEFI driver model, why do they have 'g' prefix in the first place?
'g' is for globally visible symbols. Variables that are "global" in
this file only are better off using 'm'.

> +STATIC USB_DEVICE_RX_CALLBACK         mDataReceivedCallback;

> +STATIC UINTN                          mDataBufferSize;

> +

> +struct usb_interface_descriptor intf = {

> +  sizeof (struct usb_interface_descriptor),

> +  UDESC_INTERFACE,

> +  0,

> +  0,

> +  2,

> +  USB_CLASS_VENDOR_SPEC,

> +  0x42,

> +  0x03,

> +  0

> +};

> +

> +const struct usb_ss_ep_comp_descriptor ep_comp = {

> +  sizeof (struct usb_ss_ep_comp_descriptor),

> +  UDESC_SS_USB_COMPANION,

> +  0,

> +  0,

> +  0

> +};

> +

> +const struct usb_endpoint_descriptor hs_bulk_in = {

> +  sizeof (struct usb_endpoint_descriptor),

> +  UDESC_ENDPOINT,

> +  UE_DIR_IN | USB3_BULK_IN_EP,

> +  USB_ENDPOINT_XFER_BULK,

> +  0x200,

> +  0

> +};

> +

> +const struct usb_endpoint_descriptor

> +hs_bulk_out = {

> +  sizeof(struct usb_endpoint_descriptor), /* bLength */

> +  UDESC_ENDPOINT,                         /* bDescriptorType */

> +

> +  UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */

> +  USB_ENDPOINT_XFER_BULK,        /* bmAttributes */

> +  0x200,                         /* wMaxPacketSize: 512 of high-speed */

> +  1,                             /* bInterval */

> +};

> +

> +const struct usb_endpoint_descriptor ss_bulk_in = {

> +  sizeof(struct usb_endpoint_descriptor), /* bLength */

> +  UDESC_ENDPOINT,                         /* bDescriptorType */

> +

> +  UE_DIR_IN | USB3_BULK_IN_EP,   /* bEndpointAddress */

> +  USB_ENDPOINT_XFER_BULK,        /* bmAttributes */

> +  0x400,                         /* wMaxPacketSize: 1024 of super-speed */

> +  0,                             /* bInterval */

> +};

> +

> +const struct usb_endpoint_descriptor ss_bulk_out = {

> +  sizeof(struct usb_endpoint_descriptor), /* bLength */

> +  UDESC_ENDPOINT,                         /* bDescriptorType */

> +

> +  UE_DIR_OUT | USB3_BULK_OUT_EP,  /* bEndpointAddress */

> +  USB_ENDPOINT_XFER_BULK,         /* bmAttributes */

> +  0x400,                          /* wMaxPacketSize: 1024 of super-speed */

> +  0,                              /* bInterval */

> +};

> +

> +/** The BOS Descriptor */


What's a BOS?

> +

> +const struct usb_dev_cap_20_ext_desc cap1 = {

> +  sizeof(struct usb_dev_cap_20_ext_desc), /* bLength */

> +  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */

> +  USB_DEVICE_CAPABILITY_20_EXTENSION,     /* bDevCapabilityType */

> +  0x2,                                    /* bmAttributes */

> +};

> +

> +const struct usb_dev_cap_ss_usb

> +cap2 = {

> +  sizeof(struct usb_dev_cap_ss_usb),      /* bLength */

> +  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */

> +  USB_DEVICE_CAPABILITY_SS_USB,           /* bDevCapabilityType */

> +  0x0,                                    /* bmAttributes */

> +  (USB_DC_SS_USB_SPEED_SUPPORT_SS |

> +      USB_DC_SS_USB_SPEED_SUPPORT_HIGH),  /* wSpeedsSupported */

> +  0x2,                                    /* bFunctionalitySupport */

> +  0xa,                                    /* bU1DevExitLat */

> +  0x100,                                  /* wU2DevExitLat */

> +};

> +

> +const struct usb_dev_cap_container_id

> +cap3 = {

> +  sizeof(struct usb_dev_cap_container_id),/* bLength */

> +  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */

> +  USB_DEVICE_CAPABILITY_CONTAINER_ID,     /* bDevCapabilityType */

> +  0,                                      /* bReserved */

> +  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */

> +};

> +

> +const struct wusb_bos_desc

> +bos = {

> +  sizeof(struct wusb_bos_desc),           /* bLength */

> +  UDESC_BOS,                              /* bDescriptorType */

> +  (sizeof(struct wusb_bos_desc) +         \

> +    sizeof(cap1) + sizeof(cap2) +         \

> +    sizeof(cap3)),                        /* wTotalLength */

> +  3,                                      /* bNumDeviceCaps */

> +};

> +

> +STATIC struct usb_enum_port_param usb_port_activity_config = {

> +  .idVendor           = USB_ENUM_ADB_PORT_VID,

> +  .idProduct          = USB_ENUM_ADB_PORT_PID,

> +  .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS,

> +  .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL

> +};

> +

> +STATIC

> +UINT32

> +DwUsb3GetEventBufEvent (

> +  IN UINTN               Size

> +  )

> +{

> +  UINT32                 Event;

> +

> +  Event = *gEventPtr++;

> +  if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) {

> +    gEventPtr = gEventBuf;

> +  }

> +  return Event;

> +}

> +

> +STATIC

> +VOID

> +DwUsb3SetFifoSize (

> +  IN UINT32              Addr,

> +  IN UINT32              Depth,

> +  IN UINT32              Dir,

> +  IN UINT32              FifoNum

> +  )

> +{

> +  UINT32                 Reg = 0;

> +

> +  if (Dir == FIFO_DIR_TX) {

> +    Reg = GTXFIFOSIZ (FifoNum);

> +  } else if (Dir == FIFO_DIR_RX) {

> +    Reg = GRXFIFOSIZ (FifoNum);

> +  } else {

> +    ASSERT (0);

> +  }

> +  MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr));

> +}

> +

> +STATIC

> +UINT32

> +Handshake (


What does this function do? "Handshake" does not tell me enough to
figure out.

> +  IN UINT32              Reg,

> +  IN UINT32              Mask,

> +  IN UINT32              Done

> +  )

> +{

> +  UINT32                 Timeout = 100000;

> +

> +  do {

> +    if ((MmioRead32 (Reg) & Mask) == Done) {

> +      return 1;

> +    }

> +    MicroSecondDelay (1);

> +  } while (Timeout-- > 0);

> +  return 0;

> +}

> +

> +STATIC

> +VOID

> +DwUsb3FillDesc (

> +  IN usb3_dma_desc_t     *desc,

> +  IN UINT64              dma_addr,

> +  IN UINT32              dma_len,

> +  IN UINT32              stream,

> +  IN UINT32              type,

> +  IN UINT32              ctrlbits,

> +  IN UINT32              own

> +  )

> +{

> +  desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF);

> +  desc->bpth = (UINT32)(dma_addr >> 32);


Could you possibly create LOW_32BIT and HIGH_32BIT macros for
MdePkg/Base.h instead? We are already duplicating these operations all
over the place. Including all over MdeModulePkg.

> +  desc->status = DSCSTS_XFERCNT (dma_len);

> +  if (type) {

> +    desc->control = DSCCTL_TRBCTL (type);

> +  }

> +  desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits;

> +  ArmDataSynchronizationBarrier ();


Please use MemoryFence() instead.
This controller is not ARM-specific.

(DSB? That sounds excessive. DMB should suffice?)

> +  /* must execute this operation at last */

> +  if (own) {

> +    desc->control |= DSCCTL_HWO;

> +  }

> +  ArmDataSynchronizationBarrier ();


As above.

> +}

> +

> +STATIC

> +VOID

> +DwUsb3DepStartNewCfg (

> +  IN UINT32              EpIdx,

> +  IN UINT32              RsrcIdx

> +  )

> +{

> +  /* start the command */

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | \

> +    DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3DepCfg (


Please no abbreviations in function names. This name tells me nothing
about what the function does (and there is no comment describing its
function).

> +  IN UINT32              EpIdx,

> +  IN UINT32              DepCfg0,

> +  IN UINT32              DepCfg1,

> +  IN UINT32              DepCfg2

> +  )

> +{

> +  MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2);

> +  MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1);

> +  MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0);

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3DepXferCfg (


Dep<something>TransferConfig.
Please address throughout.

> +  IN UINT32              EpIdx,

> +  IN UINT32              DepStrmCfg

> +  )

> +{

> +  MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg);

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +STATIC

> +UINT8

> +DwUsb3DepStartXfer (

> +  IN UINT32              EpIdx,

> +  IN UINT64              DmaAddr,

> +  IN UINT32              StreamOrUf

> +  )

> +{

> +  UINT32                 Data;

> +

> +  MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr);

> +  MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32));

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | \

> +    DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +  Data = MmioRead32 (DEPCMD (EpIdx));

> +  return GET_DEPCMD_XFER_RSRC_IDX(Data);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3DepStopXfer (

> +  IN UINT32               EpIdx,

> +  IN UINT32               Tri

> +  )

> +{

> +  MmioWrite32 (DEPCMDPAR2 (EpIdx), 0);

> +  MmioWrite32 (DEPCMDPAR1 (EpIdx), 0);

> +  MmioWrite32 (DEPCMDPAR0 (EpIdx), 0);

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | \

> +    DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +VOID

> +DwUsb3DepUpdateXfer (

> +  IN UINT32               EpIdx,

> +  IN UINT32               Tri

> +  )

> +{

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | \

> +    DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3DepClearStall (

> +  IN UINTN            EpIdx

> +  )

> +{

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +

> +STATIC

> +VOID

> +DwUsb3DepSetStall (

> +  IN UINTN            EpIdx

> +  )

> +{

> +  MmioWrite32 (

> +    DEPCMD (EpIdx),

> +    DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT

> +    );

> +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3EnableEp (


EnableEndpoint

> +  IN UINT32                EpIdx,


EndpointIndex.

> +  IN usb3_pcd_ep_t         *ep


Endpoint.

> +  )

> +{

> +  UINT32                   Dalepena;


What?

> +

> +  Dalepena = MmioRead32 (DALEPENA);

> +  /* If the EP is already enabled, skip to set it again. */


endpoint

> +  if (Dalepena & (1 << EpIdx)) {

> +    return;

> +  }

> +  Dalepena |= 1 << EpIdx;

> +  MmioWrite32 (DALEPENA, Dalepena);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3Ep0Activate (


(EP0 is special, so may not need expanding.)

> +  IN OUT usb3_pcd_t         *pcd

> +  )

> +{

> +  /* issue DEPCFG command to EP0 OUT */


... except for in comments.

> +  DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0);

> +  DwUsb3DepCfg (

> +    EP_OUT_IDX (0),

> +    EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512),

> +    EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY,

> +    0

> +    );

> +  /* issue DEPSTRMCFG command to EP0 OUT */

> +  DwUsb3DepXferCfg (EP_OUT_IDX (0), 1);  // one stream

> +  /* issue DEPCFG command to EP0 IN */

> +  DwUsb3DepCfg (

> +    EP_IN_IDX (0),

> +    EPCFG0_EPTYPE (EPTYPE_CONTROL)  | EPCFG0_MPS (512) | \

> +    EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num),

> +    EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN,

> +    0

> +    );

> +  /* issue DEPSTRMCFG command to EP0 IN */

> +  DwUsb3DepXferCfg (EP_IN_IDX (0), 1);  // one stream

> +  pcd->ep0.active = 1;

> +}

> +

> +STATIC

> +VOID

> +DwUsb3EpActivate (

> +  IN OUT usb3_pcd_t         *pcd,

> +  IN OUT usb3_pcd_ep_t      *ep

> +  )

> +{

> +  UINT32                    EpIdx, DepCfg0, DepCfg1;

> +  if (ep->is_in) {

> +    EpIdx = EP_IN_IDX (ep->num);

> +  } else {

> +    EpIdx = EP_OUT_IDX (ep->num);

> +  }

> +

> +  /* Start a new configurate when enable the first EP. */

> +  if (!pcd->eps_enabled) {

> +    pcd->eps_enabled = 1;

> +    /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first.

> +     * It resets the core's Tx FIFO mapping table.

> +     */

> +    DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL);

> +    DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);

> +    DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN;

> +

> +    switch (pcd->speed) {

> +    case USB_SPEED_SUPER:

> +      DepCfg0 |= EPCFG0_MPS (512);

> +      break;

> +    case USB_SPEED_HIGH:

> +    case USB_SPEED_FULL:

> +      DepCfg0 |= EPCFG0_MPS (64);

> +      break;

> +    case USB_SPEED_LOW:

> +      DepCfg0 |= EPCFG0_MPS (8);


No live coding of values.
Add #defines for those speed setting values.

> +      break;

> +    default:

> +      ASSERT (0);

> +      break;

> +    }

> +    DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0);


What does that final 0 do?

> +    DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2);


And that 2?

Please address throughout.

> +  }

> +  /* issue DEPCFG command to EP */

> +  DepCfg0 = EPCFG0_EPTYPE (ep->type);

> +  DepCfg0 |= EPCFG0_MPS (ep->maxpacket);

> +  if (ep->is_in) {

> +    DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num);

> +  }

> +  DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst);

> +  DepCfg1 = EPCFG1_EP_NUM (ep->num);

> +  if (ep->is_in) {

> +    DepCfg1 |= EPCFG1_EP_DIR_IN;

> +  } else {

> +    DepCfg1 |= EPCFG1_XFER_CMPL;

> +  }

> +  DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0);

> +  /* issue DEPSTRMCFG command to EP */

> +  DwUsb3DepXferCfg (EpIdx, 1);

> +  DwUsb3EnableEp (EpIdx, ep);

> +  ep->active = 1;

> +}

> +

> +STATIC

> +VOID

> +DwUsb3Ep0OutStart (

> +  IN usb3_pcd_t          *pcd

> +  )

> +{

> +  usb3_dma_desc_t        *desc;

> +

> +  /* Get the SETUP packet DMA Descriptor (TRB) */

> +  desc = pcd->ep0_setup_desc;

> +

> +  /* DMA Descriptor setup */

> +  DwUsb3FillDesc (

> +    desc,

> +    (UINT64)gEndPoint0SetupPacket,

> +    pcd->ep0.maxpacket,

> +    0,

> +    TRBCTL_SETUP,

> +    DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,

> +    1

> +    );

> +

> +  /* issue DEPSTRTXFER command to EP0 OUT */

> +  pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0);

> +}

> +

> +STATIC

> +VOID

> +DwUsb3Init (

> +  VOID

> +  )

> +{

> +  UINT32                 Data, Addr;


Address.

> +  usb3_pcd_t             *pcd = &gPcd;

> +

> +  /* soft reset the usb core */

> +  do {

> +    MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST);

> +

> +    do {

> +      MicroSecondDelay (1000);

> +      Data = MmioRead32 (DCTL);

> +    } while (Data & DCTL_CSFTRST);

> +    //

> +    // wait for at least 3 PHY clocks

> +    //

> +    MicroSecondDelay (1000);

> +  } while (0);

> +

> +  pcd->link_state = 0;

> +

> +  /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */

> +  MmioAndThenOr32 (

> +    GUSB2PHYCFG (0),

> +    ~GUSB2PHYCFG_USBTRDTIM_MASK,

> +    GUSB2PHYCFG_USBTRDTIM (9)


How long is 9?

I will stop my review here and give a full review on v2 when the
overarching comments have been addressed.

/
    Leif
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Haojian Zhuang Oct. 22, 2018, 2:51 a.m. UTC | #2
On Fri, 5 Oct 2018 at 00:32, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>

> On Mon, Aug 20, 2018 at 06:31:25PM +0800, Haojian Zhuang wrote:

> > Add Designware USB 3.0 device driver. It's focus on USB device

> > functionality, not USB Host functionality. The USB driver is

> > mainly used for Android Fastboot application.

> >

> > 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/DwUsb3Dxe/DwUsb3Dxe.dec |   44 +

> >  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf |   52 +

> >  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h   |  632 +++++

> >  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c   | 2434 ++++++++++++++++++++

> >  4 files changed, 3162 insertions(+)

> >

> > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec

> > new file mode 100644

> > index 000000000000..038e4881a948

> > --- /dev/null

> > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec

> > @@ -0,0 +1,44 @@

> > +#/** @file

> > +# Framework Module Development Environment Industry Standards

>

> Please change this to reflect this package rather than EmbeddedPkg one

> (which appears to have stolen it from an old version of MdePkg.dec :)

>


OK
> > +#

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

>

> I see no need to keep these copyright statements.

>

OK

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

> > +  PACKAGE_GUID                   = 9b7aa6fe-405b-4955-af1f-5faf183aedec

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

> > +  gDwUsb3DxeTokenSpaceGuid      = { 0x098a50d3, 0x92e2, 0x461a, { 0xb6, 0xba, 0xf8, 0x5d, 0x9d, 0x89, 0x49, 0xf5 }}

> > +

> > +[Protocols.common]

> > +  gDwUsbProtocolGuid            = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}

>

> Please make this file a common .dec for DwUsb and DwUsb3 instead of

> duplicating guid information.

> (If we weren't moving it to edk2-platforms, it would still have been

> better to add it to EmbeddedPkg.dec.)

>

OK

> > +

> > +[PcdsFixedAtBuild.common]

> > +  # DwUsb Driver PCDs

> > +  gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress|0x0|UINT32|0x00000001

> > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf

> > new file mode 100644

> > index 000000000000..510b51a34de7

> > --- /dev/null

> > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf

> > @@ -0,0 +1,52 @@

> > +#/** @file

> > +#

> > +#  Copyright (c) 2018, Linaro Limited. 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                      = DwUsb3Dxe

> > +  FILE_GUID                      = 0879cd34-c399-4315-9891-56024072e711

> > +  MODULE_TYPE                    = UEFI_DRIVER

> > +  VERSION_STRING                 = 1.0

> > +  ENTRY_POINT                    = DwUsb3EntryPoint

> > +

> > +[Sources.common]

> > +  DwUsb3Dxe.c

> > +

> > +[LibraryClasses]

> > +  CacheMaintenanceLib

> > +  DebugLib

> > +  DmaLib

> > +  IoLib

> > +  MemoryAllocationLib

> > +  TimerLib

> > +  UefiBootServicesTableLib

> > +  UefiDriverEntryPoint

> > +  UsbSerialNumberLib

>

> I don't see this library anywhere in the tree?

>


I'll add it into the patch series for the next revision.

> > +

> > +[Protocols]

> > +  gEfiDriverBindingProtocolGuid

> > +  gUsbDeviceProtocolGuid

> > +

> > +[Packages]

> > +  ArmPkg/ArmPkg.dec

> > +  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec

> > +  EmbeddedPkg/EmbeddedPkg.dec

> > +  MdePkg/MdePkg.dec

> > +  MdeModulePkg/MdeModulePkg.dec

> > +

> > +[Pcd]

> > +  gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress

> > +

> > +[Depex]

> > +  TRUE

> > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h

> > new file mode 100644

> > index 000000000000..92b610553169

> > --- /dev/null

> > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h

> > @@ -0,0 +1,632 @@

> > +/** @file

> > +

> > +  Copyright (c) 2017, Linaro Limited. 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_USB3_DXE_H__

> > +#define __DW_USB3_DXE_H__

>

> DW -> DESIGNWARE (throughout).

>

OK

> > +

> > +#define DW_USB3_BASE                     FixedPcdGet32 (PcdDwUsb3DxeBaseAddress)

> > +

> > +#define GSBUCFG0                         (DW_USB3_BASE + 0xC100)

> > +#define GCTL                             (DW_USB3_BASE + 0xC110)

> > +

> > +#define GCTL_PWRDNSCALE_MASK             (0x1FFF << 19)

> > +#define GCTL_PWRDNSCALE(x)               (((x) & 0x1FFF) << 19)

> > +#define GCTL_U2RSTECN                    BIT16

> > +#define GCTL_PRTCAPDIR_MASK              (BIT13 | BIT12)

> > +#define GCTL_PRTCAPDIR_HOST              BIT12

> > +#define GCTL_PRTCAPDIR_DEVICE            BIT13

> > +#define GCTL_PRTCAPDIR_OTG               (BIT13 | BIT12)

> > +#define GCTL_U2EXIT_LFPS                 BIT2

> > +

> > +#define GUSB2PHYCFG(x)                   (DW_USB3_BASE + 0xC200 + (((x) & 0xF) << 2))

> > +

> > +#define GUSB2PHYCFG_USBTRDTIM_MASK       (0xF << 10)

> > +#define GUSB2PHYCFG_USBTRDTIM(x)         (((x) & 0xF) << 10)

> > +#define GUSB2PHYCFG_SUSPHY               BIT6

> > +

> > +#define GUSB3PIPECTL(x)                  (DW_USB3_BASE + 0xC2C0 + (((x) & 0x3) << 2))

> > +

> > +#define PIPECTL_DELAYP1TRANS             BIT18

> > +#define PIPECTL_SUSPEND_EN               BIT17

> > +#define PIPECTL_LFPS_FILTER              BIT9

> > +#define PIPECTL_TX_DEMPH_MASK            (0x3 << 1)

> > +#define PIPECTL_TX_DEMPH(x)              (((x) & 0x3) << 1)

> > +

> > +#define GTXFIFOSIZ(x)                    (DW_USB3_BASE + 0xC300 + (((x) & 0x1F) << 2))

> > +#define GRXFIFOSIZ(x)                    (DW_USB3_BASE + 0xC380 + (((x) & 0x1F) << 2))

> > +

> > +#define FIFOSIZ_ADDR(x)                  (((x) & 0xFFFF) << 16)

> > +#define FIFOSIZ_DEP(x)                   ((x) & 0xFFFF)

> > +

> > +#define GEVNTADRL(x)                     (DW_USB3_BASE + 0xC400 + (((x) & 0x1F) << 2))

> > +#define GEVNTADRH(x)                     (DW_USB3_BASE + 0xC404 + (((x) & 0x1F) << 2))

> > +#define GEVNTSIZ(x)                      (DW_USB3_BASE + 0xC408 + (((x) & 0x1F) << 2))

> > +

> > +#define GEVNTSIZ_EVNTINTMASK             BIT31

> > +#define GEVNTSIZ_EVNTSIZ_MASK            (0xFFFF)

> > +#define GEVNTSIZ_EVNTSIZ(x)              ((x) & 0xFFFF)

> > +

> > +#define GEVNTCOUNT(x)                    (DW_USB3_BASE + 0xC40C + (((x) & 0x1F) << 2))

> > +#define GEVNTCOUNT_EVNTCOUNT_MASK        (0xFFFF)

> > +#define GEVNTCOUNT_EVNTCOUNT(x)          ((x) & 0xFFFF)

> > +

> > +// Non-Endpoint specific event flag

> > +#define GEVNT_INTTYPE_MASK               (0x7F << 1)

> > +#define GEVNT_INTTYPE(x)                 (((x) & 0x7F) << 1)

> > +#define EVENT_I2C_INT                    4

> > +#define EVENT_CARKIT_INT                 3

> > +#define EVENT_OTG_INT                    1

> > +#define EVENT_DEV_INT                    0

> > +

> > +#define GEVNT_NON_EP                     BIT0

> > +// Endpoint specific event flag

> > +#define GEVNT_DEPEVT_INTTYPE_MASK        (0xF << 6)

> > +#define GEVNT_DEPEVT_INTTYPE(x)          (((x) & 0xF) << 6)

> > +#define GEVNT_DEPEVT_INTTYPE_EPCMD_CMPL  (7 << 6)

> > +#define GEVNT_DEPEVT_INTTYPE_STRM_EVT    (6 << 6)

> > +#define GEVNT_DEPEVT_INTTYPE_FIFOXRUN    (4 << 6)

> > +#define GEVNT_DEPEVT_INTTYPE_XFER_NRDY   (3 << 6)

> > +#define GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG (2 << 6)

> > +#define GEVNT_DEPEVT_INTTYPE_XFER_CMPL   (1 << 6)

> > +#define GEVNT_DEPEVT_EPNUM_MASK          (0x1F << 1)

> > +#define GEVNT_DEPEVT_EPNUM_SHIFT         1

> > +#define GEVNT_DEPEVT_EPNUM(x)            (((x) & 0x1F) << 1)

> > +// Devices specific event flag

> > +#define GEVNT_DEVT_MASK                  (0xF << 8)

> > +#define GEVNT_DEVT_SHIFT                 8

> > +#define GEVNT_DEVT(x)                    (((x) & 0xF) << 8)

> > +#define GEVNT_DEVT_INACT_TIMEOUT_RCVD    (0x15 << 8)

> > +#define GEVNT_DEVT_VNDR_DEV_TST_RCVD     (0x14 << 8)

> > +#define GEVNT_DEVT_OVERFLOW              (0x13 << 8)

> > +#define GEVNT_DEVT_CMD_CMPL              (0x12 << 8)

> > +#define GEVNT_DEVT_ERRATICERR            (0x11 << 8)

> > +#define GEVNT_DEVT_SOF                   (0x7 << 8)

> > +#define GEVNT_DEVT_EOPF                  (0x6 << 8)

> > +#define GEVNT_DEVT_HIBER_REQ             (0x5 << 8)

> > +#define GEVNT_DEVT_WKUP                  (0x4 << 8)

> > +#define GEVNT_DEVT_ULST_CHNG             (0x3 << 8)

> > +#define GEVNT_DEVT_CONNDONE              (0x2 << 8)

> > +#define GEVNT_DEVT_USBRESET              (0x1 << 8)

> > +#define GEVNT_DEVT_DISCONN               (0x0 << 8)

> > +

> > +#define DCFG                             (DW_USB3_BASE + 0xC700)

> > +

> > +#define DCFG_NUMP_MASK                   (0x1F << 17)

> > +#define DCFG_NUMP(x)                     (((x) & 0x1F) << 17)

> > +#define DCFG_DEVADDR_MASK                (0x7F << 3)

> > +#define DCFG_DEVADDR(x)                  (((x) & 0x7F) << 3)

> > +#define DCFG_DEVSPD_MASK                 (0x7)

> > +#define DCFG_DEVSPD(x)                   ((x) & 0x7)

> > +#define DEVSPD_HS_PHY_30MHZ_OR_60MHZ     0

> > +#define DEVSPD_FS_PHY_30MHZ_OR_60MHZ     1

> > +#define DEVSPD_LS_PHY_6MHZ               2

> > +#define DEVSPD_FS_PHY_48MHZ              3

> > +#define DEVSPD_SS_PHY_125MHZ_OR_250MHZ   4

> > +

> > +#define DCTL                             (DW_USB3_BASE + 0xC704)

> > +

> > +#define DCTL_RUN_STOP                    BIT31

> > +#define DCTL_CSFTRST                     BIT30

> > +#define DCTL_INIT_U2_EN                  BIT12

> > +#define DCTL_ACCEPT_U2_EN                BIT11

> > +#define DCTL_INIT_U1_EN                  BIT10

> > +#define DCTL_ACCEPT_U1_EN                BIT9

> > +

> > +#define DEVTEN                           (DW_USB3_BASE + 0xC708)

> > +#define DEVTEN_CONNECTDONEEN             BIT2

> > +#define DEVTEN_USBRSTEN                  BIT1

> > +#define DEVTEN_DISCONNEN                 BIT0

> > +

> > +#define DSTS                             (DW_USB3_BASE + 0xC70C)

> > +#define DSTS_GET_DEVSPD(x)               ((x) & 0x7)

> > +

> > +#define DALEPENA                         (DW_USB3_BASE + 0xC720)

> > +

> > +#define DEPCMDPAR2(x)                    (DW_USB3_BASE + 0xC800 + ((x) & 0x1F) * 0x10)

> > +#define DEPCMDPAR1(x)                    (DW_USB3_BASE + 0xC804 + ((x) & 0x1F) * 0x10)

> > +#define DEPCMDPAR0(x)                    (DW_USB3_BASE + 0xC808 + ((x) & 0x1F) * 0x10)

> > +#define DEPCMD(x)                        (DW_USB3_BASE + 0xc80C + ((x) & 0x1F) * 0x10)

> > +

> > +#define DEPCMD_COMMANDPARAM_MASK         (0xFFFF << 16)

> > +#define DEPCMD_COMMANDPARAM(x)           (((x) & 0xFFFF) << 16)

> > +/* Stream Number or uFrame (input) */

> > +#define DEPCMD_STR_NUM_OR_UF_MASK        (0xFFFF << 16)

> > +#define DEPCMD_STR_NUM_OR_UF(x)          (((x) & 0xFFFF) << 16)

> > +/* Transfer Resource Index (output) */

> > +#define DEPCMD_XFER_RSRC_IDX_SHIFT       16

> > +#define DEPCMD_XFER_RSRC_IDX_MASK        (0x7F << 16)

> > +#define DEPCMD_XFER_RSRC_IDX(x)          (((x) & 0x7F) << 16)

> > +#define GET_DEPCMD_XFER_RSRC_IDX(x)      (((x) >> 16) & 0x7F)

> > +#define DEPCMD_CMDACT                    BIT10

> > +#define DEPCMD_CMDTYPE_MASK              0xFF

> > +#define DEPCMD_CMDTYPE(x)                ((x) & 0xFF)

> > +

> > +/* EP registers range as: OUT0, IN0, OUT1, IN1, ... */

> > +#define EP_OUT_IDX(x)                    ((x) * 2)

> > +#define EP_IN_IDX(x)                     (((x) * 2) + 1)

> > +

> > +#define CMDTYPE_SET_EP_CFG               1

> > +#define CMDTYPE_SET_XFER_CFG             2

> > +#define CMDTYPE_GET_EP_STATE             3

> > +#define CMDTYPE_SET_STALL                4

> > +#define CMDTYPE_CLR_STALL                5

> > +#define CMDTYPE_START_XFER               6

> > +#define CMDTYPE_UPDATE_XFER              7

> > +#define CMDTYPE_END_XFER                 8

> > +#define CMDTYPE_START_NEW_CFG            9

> > +

> > +#define EPTYPE_CONTROL                   0

> > +#define EPTYPE_ISOC                      1

> > +#define EPTYPE_BULK                      2

> > +#define EPTYPE_INTR                      3

> > +

> > +#define CFG_ACTION_INIT                  0

> > +#define CFG_ACTION_RESTORE               1

> > +#define CFG_ACTION_MODIFY                2

> > +

> > +#define EPCFG0_CFG_ACTION_MASK           (0x3 << 30)

> > +#define EPCFG0_CFG_ACTION(x)             (((x) & 0x3) << 30)

> > +#define EPCFG0_BRSTSIZ_MASK              (0xF << 22)

> > +#define EPCFG0_BRSTSIZ(x)                (((x) & 0xF) << 22)

> > +#define EPCFG0_TXFNUM_MASK               (0x1F << 17)

> > +#define EPCFG0_TXFNUM(x)                 (((x) & 0x1F) << 17)

> > +#define EPCFG0_MPS_MASK                  (0x7FF << 3)

> > +#define EPCFG0_MPS(x)                    (((x) & 0x7FF) << 3)

> > +#define EPCFG0_EPTYPE_MASK               (0x3 << 1)

> > +#define EPCFG0_EPTYPE_SHIFT              1

> > +#define EPCFG0_EPTYPE(x)                 (((x) & 0x3) << 1)

> > +

> > +/* Endpoint Number */

> > +#define EPCFG1_EP_NUM_MASK               (0xF << 26)

> > +#define EPCFG1_EP_NUM(x)                 (((x) & 0xF) << 26)

> > +/* Endpoint Direction */

> > +#define EPCFG1_EP_DIR_IN                 BIT25

> > +/* Stream Not Ready */

> > +#define EPCFG1_XFER_NRDY                 BIT10

> > +/* XferInProgress Enable */

> > +#define EPCFG1_XFER_IN_PROG              BIT9

> > +/* Stream Completed */

> > +#define EPCFG1_XFER_CMPL                 BIT8

> > +

> > +#define USB_SPEED_UNKNOWN                0

> > +#define USB_SPEED_LOW                    1

> > +#define USB_SPEED_FULL                   2

> > +#define USB_SPEED_HIGH                   3

> > +#define USB_SPEED_VARIABLE               4

> > +#define USB_SPEED_SUPER                  5

> > +

> > +// DMA registers

> > +#define DSCSTS_TRBRSP_MASK               (0xF << 28)

> > +#define DSCSTS_TRBRSP(x)                 (((x) & 0xF) << 28)

> > +#define GET_DSCSTS_TRBRSP(x)             (((x) >> 28) & 0xF)

> > +#define TRBRSP_MISSED_ISOC_IN            1

> > +#define TRBRSP_SETUP_PEND                2

> > +#define TRBRSP_XFER_IN_PROG              4

> > +#define DSCSTS_PCM1_MASK                 (0x3 << 24)

> > +#define DSCSTS_PCM1(x)                   (((x) & 0x3) << 24)

> > +#define DSCSTS_XFERCNT_MASK              0xFFFFFF

> > +#define DSCSTS_XFERCNT(x)                ((x) & 0xFFFFFF)

> > +#define GET_DSCSTS_XFERCNT(x)            ((x) & 0xFFFFFF)

> > +

> > +#define DSCCTL_STRMID_SOFN(x)            (((x) & 0xFFFF) << 14)

> > +#define DSCCTL_IOC                       BIT11

> > +#define DSCCTL_ISP                       BIT10

> > +#define DSCCTL_TRBCTL_MASK               (0x3F << 4)

> > +#define DSCCTL_TRBCTL(x)                 (((x) & 0x3F) << 4)

> > +#define DSCCTL_LST                       BIT1

> > +#define DSCCTL_HWO                       BIT0

> > +#define TRBCTL_NORMAL                    1

> > +#define TRBCTL_SETUP                     2

> > +#define TRBCTL_STATUS_2                  3

> > +#define TRBCTL_STATUS_3                  4

> > +#define TRBCTL_CTLDATA_1ST               5

> > +#define TRBCTL_ISOC_1ST                  6

> > +#define TRBCTL_ISOC                      7

> > +#define TRBCTL_LINK                      8

> > +#define TRBCTL_NORMAL_ZLP                9

> > +

> > +

> > +#define UE_DIR_IN                        0x80

> > +#define UE_DIR_OUT                       0

> > +#define UE_SET_DIR(a, d)                 ((a) | (((d) & 1) << 7))

> > +#define UE_GET_DIR(a)                    ((a) & 0x80)

> > +#define UE_ADDR                          0x0F

> > +#define UE_GET_ADDR(a)                   ((a) & UE_ADDR)

> > +

> > +#define UT_GET_DIR(a)                    ((a) & 0x80)

> > +#define UT_WRITE                         0x00

> > +#define UT_READ                          0x80

> > +

> > +#define UT_GET_TYPE(a)                   ((a) & 0x60)

> > +#define UT_STANDARD                      0x00

> > +#define UT_CLASS                         0x20

> > +#define UT_VENDOR                        0x40

> > +

> > +#define UT_GET_RECIPIENT(a)              ((a) & 0x1f)

> > +#define UT_DEVICE                        0x00

> > +#define UT_INTERFACE                     0x01

> > +#define UT_ENDPOINT                      0x02

> > +#define UT_OTHER                         0x03

> > +

> > +#define UR_GET_STATUS                    0x00

> > +#define UR_CLEAR_FEATURE                 0x01

> > +#define UR_SET_FEATURE                   0x03

> > +#define UR_SET_ADDRESS                   0x05

> > +#define UR_GET_DESCRIPTOR                0x06

> > +#define UR_SET_DESCRIPTOR                0x07

> > +#define UR_GET_CONFIG                    0x08

> > +#define UR_SET_CONFIG                    0x09

> > +#define UR_GET_INTERFACE                 0x0A

> > +#define UR_SET_INTERFACE                 0x0B

> > +#define UR_SYNCH_FRAME                   0x0C

> > +#define UR_SET_SEL                       0x30

> > +#define UR_SET_ISOC_DELAY                0x31

> > +

>

> Somewhere around here starts a bunch of redefinitions of things

> already described in MdePkg/Include/IndustryStandard/Usb.h.

> Can you please reuse that include file as much as possible.

>

OK

> > +/* Feature numbers */

> > +#define UF_ENDPOINT_HALT                 0

> > +#define UF_DEVICE_REMOTE_WAKEUP          1

> > +#define UF_TEST_MODE                     2

> > +#define UF_DEVICE_B_HNP_ENABLE           3

> > +#define UF_DEVICE_A_HNP_SUPPORT          4

> > +#define UF_DEVICE_A_ALT_HNP_SUPPORT      5

> > +#define UF_FUNCTION_SUSPEND              0

> > +#define UF_U1_ENABLE                     48

> > +#define UF_U2_ENABLE                     49

> > +#define UF_LTM_ENABLE                    50

> > +

> > +#define  UDESC_DEVICE                    0x01

> > +#define  UDESC_CONFIG                    0x02

> > +#define  UDESC_STRING                    0x03

> > +#define  UDESC_INTERFACE                 0x04

> > +#define  UDESC_ENDPOINT                  0x05

> > +#define  UDESC_SS_USB_COMPANION          0x30

> > +#define  UDESC_DEVICE_QUALIFIER          0x06

> > +#define  UDESC_BOS                       0x0f

> > +#define  UDESC_DEVICE_CAPABILITY         0x10

> > +

> > +#define STRING_LANGUAGE                  0

> > +#define STRING_MANUFACTURER              1

> > +#define STRING_PRODUCT                   2

> > +#define STRING_SERIAL                    3

> > +

> > +#define CONFIG_VALUE    1

> > +

> > +#define USB3_BULK_IN_EP                  1

> > +#define USB3_BULK_OUT_EP                 1

> > +

> > +#define USB_ENUM_ADB_PORT_VID            0x18D1

> > +#define USB_ENUM_ADB_PORT_PID            0xD00D

> > +#define USB_ENUM_INTERFACE_ADB_SUBCLASS  0x42

> > +#define USB_ENUM_INTERFACE_ADB_PROTOCOL  0x03

> > +

> > +struct usb3_pcd;

> > +

> > +typedef enum pcd_state {

> > +  USB3_STATE_UNCONNECTED,                /* no host */

> > +  USB3_STATE_DEFAULT,

> > +  USB3_STATE_ADDRESSED,

> > +  USB3_STATE_CONFIGURED,

> > +} pcdstate_e;

>

> These structs also break the coding style completely.

> Will using IndustryStandard/Usb.h get rid of all of that?

>

OK

> > +

> > +typedef enum ep0_state {

> > +  EP0_IDLE,

> > +  EP0_IN_DATA_PHASE,

> > +  EP0_OUT_DATA_PHASE,

> > +  EP0_IN_WAIT_NRDY,

> > +  EP0_OUT_WAIT_NRDY,

> > +  EP0_IN_STATUS_PHASE,

> > +  EP0_OUT_STATUS_PHASE,

> > +  EP0_STALL,

> > +} ep0state_e;

> > +

> > +typedef struct usb3_dma_desc {

> > +  /** Buffer Pointer - Low address quadlet */

> > +  UINT32     bptl;

> > +

> > +  /** Buffer Pointer - High address quadlet */

> > +  UINT32     bpth;

> > +

> > +  /** Status quadlet. Fields defined in enum @ref desc_sts_data. */

> > +  UINT32     status;

> > +

> > +  /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */

> > +  UINT32     control;

> > +} usb3_dma_desc_t;

> > +

> > +typedef struct usb3_pcd_req {

> > +  usb3_dma_desc_t *trb;

> > +  UINT64 trbdma;

> > +

> > +  UINT32 length;

> > +  UINT32 actual;

> > +

> > +  UINT64 *bufdma;

> > +  int (*complete)(unsigned actual, int status);

> > +} usb3_pcd_req_t;

> > +

> > +typedef struct usb_device_request {

> > +  UINT8 bmRequestType;

> > +  UINT8 bRequest;

> > +  UINT16 wValue;

> > +  UINT16 wIndex;

> > +  UINT16 wLength;

> > +} usb_device_request_t;

> > +

> > +#pragma pack(1)

> > +/** USB_DT_DEVICE: Device descriptor */

> > +typedef struct usb_device_descriptor {

> > +  UINT8  bLength;

> > +  UINT8  bDescriptorType;

> > +

> > +  UINT16 bcdUSB;

> > +#define USB_CLASS_COMM          0x02

> > +#define USB_CLASS_VENDOR_SPEC   0xFF

> > +#define USB_SC_VENDOR_SPEC      0xFF

> > +#define USB_PR_VENDOR_SPEC      0xFF

> > +  UINT8  bDeviceClass;

> > +  UINT8  bDeviceSubClass;

> > +  UINT8  bDeviceProtocol;

> > +  UINT8  bMaxPacketSize0;

> > +  UINT16 idVendor;

> > +  UINT16 idProduct;

> > +  UINT16 bcdDevice;

> > +  UINT8  iManufacturer;

> > +  UINT8  iProduct;

> > +  UINT8  iSerialNumber;

> > +  UINT8  bNumConfigurations;

> > +} usb_device_descriptor_t;

> > +

> > +/* USB_DT_CONFIG: Config descriptor */

> > +typedef struct usb_config_descriptor {

> > +  UINT8  bLength;

> > +  UINT8  bDescriptorType;

> > +

> > +  UINT16 wTotalLength;

> > +  UINT8  bNumInterfaces;

> > +#define CONFIG_VALUE            1

> > +  UINT8  bConfigurationValue;

> > +  UINT8  iConfiguration;

> > +#define USB_CONFIG_ATT_ONE      (1 << 7)

> > +  UINT8  bmAttributes;

> > +#define USB_CONFIG_VBUS_DRAW    (0xFA)

> > +  UINT8  bMaxPower;

> > +} usb_config_descriptor_t;

> > +

> > +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */

> > +typedef struct usb_qualifier_descriptor {

> > +  UINT8  bLength;

> > +  UINT8  bDescriptorType;

> > +

> > +  UINT16 bcdUSB;

> > +  UINT8  bDeviceClass;

> > +  UINT8  bDeviceSubClass;

> > +  UINT8  bDeviceProtocol;

> > +  UINT8  bMaxPacketSize0;

> > +  UINT8  bNumConfigurations;

> > +  UINT8  bRESERVED;

> > +} usb_qualifier_descriptor_t;

> > +

> > +/* USB_DT_INTERFACE: Interface descriptor */

> > +typedef struct usb_interface_descriptor {

> > +  UINT8  bLength;

> > +  UINT8  bDescriptorType;

> > +

> > +  UINT8  bInterfaceNumber;

> > +  UINT8  bAlternateSetting;

> > +  UINT8  bNumEndpoints;

> > +  UINT8  bInterfaceClass;

> > +  UINT8  bInterfaceSubClass;

> > +  UINT8  bInterfaceProtocol;

> > +  UINT8  iInterface;

> > +} usb_interface_descriptor_t;

> > +

> > +/* USB_DT_ENDPOINT: Endpoint descriptor */

> > +typedef struct usb_endpoint_descriptor {

> > +  UINT8  bLength;

> > +  UINT8  bDescriptorType;

> > +

> > +  UINT8  bEndpointAddress;

> > +  UINT8  bmAttributes;

> > +#define USB_ENDPOINT_XFER_CONTROL       0x00

> > +#define USB_ENDPOINT_XFER_ISOC          0x01

> > +#define USB_ENDPOINT_XFER_BULK          0x02

> > +#define USB_ENDPOINT_XFER_INT           0x03

> > +  UINT16 wMaxPacketSize;

> > +  UINT8  bInterval;

> > +} usb_endpoint_descriptor_t;

> > +

> > +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */

> > +typedef struct usb_ss_ep_comp_descriptor {

> > +  UINT8  bLength;

> > +  UINT8  bDescriptorType;

> > +

> > +  UINT8  bMaxBurst;

> > +  UINT8  bmAttributes;

> > +  UINT16 wBytesPerInterval;

> > +} usb_ss_ep_comp_descriptor_t;

> > +

> > +/* WUSB BOS Descriptor (Binary device Object Store) */

> > +typedef struct wusb_bos_desc {

> > +  UINT8 bLength;

> > +  UINT8 bDescriptorType;

> > +  UINT16 wTotalLength;

> > +  UINT8 bNumDeviceCaps;

> > +} wusb_bos_desc_t;

> > +

> > +#define USB_DEVICE_CAPABILITY_20_EXTENSION      0x02

> > +typedef struct usb_dev_cap_20_ext_desc {

> > +  UINT8 bLength;

> > +  UINT8 bDescriptorType;

> > +  UINT8 bDevCapabilityType;

> > +#define USB_20_EXT_LPM                          0x02

> > +  UINT32 bmAttributes;

> > +} usb_dev_cap_20_ext_desc_t;

> > +

> > +#define USB_DEVICE_CAPABILITY_SS_USB            0x03

> > +typedef struct usb_dev_cap_ss_usb {

> > +  UINT8 bLength;

> > +  UINT8 bDescriptorType;

> > +  UINT8 bDevCapabilityType;

> > +#define USB_DC_SS_USB_LTM_CAPABLE               0x02

> > +  UINT8 bmAttributes;

> > +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW         0x01

> > +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL        0x02

> > +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH        0x04

> > +#define USB_DC_SS_USB_SPEED_SUPPORT_SS          0x08

> > +  UINT32 wSpeedsSupported;

> > +  UINT8 bFunctionalitySupport;

> > +  UINT8 bU1DevExitLat;

> > +  UINT32 wU2DevExitLat;

> > +} usb_dev_cap_ss_usb_t;

> > +

> > +#define USB_DEVICE_CAPABILITY_CONTAINER_ID      0x04

> > +typedef struct usb_dev_cap_container_id {

> > +  UINT8 bLength;

> > +  UINT8 bDescriptorType;

> > +  UINT8 bDevCapabilityType;

> > +  UINT8 bReserved;

> > +  UINT8 containerID[16];

> > +} usb_dev_cap_container_id_t;

> > +#pragma pack()

> > +

> > +typedef union usb_setup_pkt {

> > +  usb_device_request_t req;

> > +  UINT32 d32[2];

> > +  UINT8 d8[8];

> > +} usb_setup_pkt_t;

> > +

> > +typedef struct usb3_pcd_ep {

> > +  struct usb3_pcd *pcd;

> > +

> > +  UINT8          EpInIdx;

> > +  UINT8          EpOutIdx;

> > +  UINT8          phys;

> > +

> > +  //UINT8 phys;

> > +  UINT8 num;

> > +  UINT8 type;

> > +  UINT8 maxburst;

> > +  UINT16 maxpacket;

> > +  /* Tx FIFO # for IN EPs */

> > +  UINT8 tx_fifo_num;

> > +

> > +  /* The Transfer Resource Index from the Start Transfer command */

> > +  UINT8 tri_out;

> > +  UINT8 tri_in;

> > +

> > +  UINT8 stopped;

> > +  /* Send ZLP */

> > +  UINT8 send_zlp;

> > +  /* True if 3-stage control transfer */

> > +  UINT8 three_stage;

> > +  /* True if transfer has been started on EP */

> > +  UINT8 xfer_started;

> > +  /* EP direction 0 = OUT */

> > +  UINT8 is_in;

> > +  /* True if endpoint is active */

> > +  UINT8 active;

> > +  /* Initial data pid of bulk endpoint */

> > +  UINT8 data_pid_start;

> > +

> > +  /* ep_desc (excluding ep0) */

> > +  usb3_dma_desc_t *ep_desc;

> > +

> > +#if 0

> > +  /* TRB descriptor must be aligned to 16 bytes */

> > +  UINT8 epx_desc[32];

> > +#endif

> > +

> > +  /* request (excluding ep0) */

> > +  usb3_pcd_req_t req;

> > +} usb3_pcd_ep_t;

> > +

> > +typedef struct usb3_pcd {

> > +  //struct usb3_device *usb3_dev;

> > +

> > +  INT32 link_state;

> > +  pcdstate_e state;

> > +  UINT8 new_config;

> > +  ep0state_e ep0state;

> > +

> > +  UINT32 eps_enabled;

> > +  UINT32 ltm_enable;

> > +

> > +  usb3_pcd_ep_t ep0;

> > +  usb3_pcd_ep_t out_ep;

> > +  usb3_pcd_ep_t in_ep;

> > +

> > +  /*

> > +  usb3_dev_global_regs_t *dev_global_regs;

> > +  usb3_dev_ep_regs_t *out_ep_regs;

> > +  usb3_dev_ep_regs_t *in_ep_regs;

> > +  */

> > +

> > +  usb3_pcd_req_t ep0_req;

> > +

> > +  UINT8 speed;

> > +

> > +  usb3_dma_desc_t *ep0_setup_desc;

> > +  usb3_dma_desc_t *ep0_in_desc;

> > +  usb3_dma_desc_t *ep0_out_desc;

> > +

> > +  /* TRB descriptor must be aligned to 16 bytes */

> > +#if 0

> > +  UINT8 ep0_setup[32];

> > +  UINT8 ep0_in[32];

> > +  UINT8 ep0_out[32];

> > +

> > +  usb_setup_pkt_t ep0_setup_pkt[5];

> > +

> > +#define USB3_STATUS_BUF_SIZE    512

> > +  UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE];

> > +

> > +#define USB3_BULK_BUF_SIZE      2048

> > +  UINT8 ss_bulk_buf[USB3_BULK_BUF_SIZE];

> > +#endif

> > +

> > +  UINT32 file_type;

> > +  UINT32 file_address;

> > +  UINT32 file_capacity;

> > +  UINT32 file_total_frame;

> > +  UINT32 file_curr_frame;

> > +  UINT32 file_next_frame;

> > +  UINT32 file_received;

> > +  UINT32 file_complete;

> > +

> > +  UINT16 test_mode_nr;

> > +  UINT16 test_mode;

> > +} usb3_pcd_t;

> > +

> > +struct usb_enum_port_param {

> > +  UINT16     idVendor;

> > +  UINT16     idProduct;

> > +  UINT8      bInterfaceSubClass;

> > +  UINT8      bInterfaceProtocol;

> > +};

> > +

> > +#if 0

>

> If not used, leave it out.

>

OK

> > +typedef struct usb3_pcd_req {

> > +  usb3_dma_desc_t *trb;

> > +  UINT64 trbdma;

> > +

> > +  UINT32 length;

> > +  UINT32 actual;

> > +

> > +  UINT64 *bufdma;

> > +  int (*complete)(unsigned actual, int status);

> > +} usb3_pcd_req_t;

> > +

> > +#endif

> > +

> > +#endif /* __DW_USB3_DXE_H__ */

> > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c

> > new file mode 100644

> > index 000000000000..83d5e4736de0

> > --- /dev/null

> > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c

> > @@ -0,0 +1,2434 @@

> > +/** @file

> > +

> > +  Copyright (c) 2018, Linaro Limited. 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/DriverBinding.h>

> > +#include <Protocol/UsbDevice.h>

> > +

> > +#include "DwUsb3Dxe.h"

> > +

> > +#define FIFO_DIR_TX                  0

> > +#define FIFO_DIR_RX                  1

> > +

> > +#define TX_FIFO_ADDR                 0

> > +#define RX_FIFO_ADDR                 0

> > +

> > +#define RAM_WIDTH                    8

> > +#define RAM_TX0_DEPTH                2048

> > +#define RAM_TX1_DEPTH                4096

> > +#define RAM_RX_DEPTH                 8192

>

> Should these not also go into DwUsb3Dxe.h?

>

OK

> > +

> > +#define USB_TYPE_LENGTH              16

> > +#define USB_BLOCK_HIGH_SPEED_SIZE    512

> > +#define DATA_SIZE                    131072

> > +#define CMD_SIZE                     512

>

> What do the above definitions mean?

>

I'll add comment.

> > +#define MATCH_CMD_LITERAL(Cmd, Buf)  !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)

>

> This one does not appear to be used?

>

OK

> > +

> > +#define ALIGN(x, a)     (((x) + ((a) - 1)) & ~((a) - 1))

>

> Use available macros in Base.h.

>

OK

> > +

> > +//

> > +// The time between interrupt polls, in units of 100 nanoseconds

> > +// 10 Microseconds

> > +//

> > +#define DW_INTERRUPT_POLL_PERIOD     100

> > +

> > +#define DWUSB3_EVENT_BUF_SIZE        256

> > +

> > +//

> > +// Maxpacket size for EP0, defined by USB3 spec

> > +//

> > +#define USB3_MAX_EP0_SIZE            512

> > +

> > +//

> > +// Maxpacket size for any EP, defined by USB3 spec

> > +//

> > +#define USB3_MAX_PACKET_SIZE         1024

> > +#define USB2_HS_MAX_PACKET_SIZE      512

> > +#define USB2_FS_MAX_PACKET_SIZE      64

> > +

> > +#define USB3_STATE_UNCONNECTED       0

> > +#define USB3_STATE_DEFAULT           1

> > +#define USB3_STATE_ADDRESSED         2

> > +#define USB3_STATE_CONFIGURED        3

> > +

> > +#define USB3_STATUS_BUF_SIZE         512

>

> If these are defined by USB3 spec, please add them to

> MdePkg/Include/IndustryStandard/Usb.h instead of defining them

> locally.

>

OK

> > +

> > +#define GET_EVENTBUF_COUNT()                                       \

> > +        (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0))))

> > +#define UPDATE_EVENTBUF_COUNT(x)                                   \

> > +        (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x)))

> > +

> > +#define SET_DEVADDR(x)                                             \

> > +        (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x)))

>

> Should these not also move to DwUsb3Dxe.h?

>

OK

> > +

> > +EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;

>

> This looks less than ideal - this makes it impossible to include

> DwUsb2 and DwUsb3 drivers in the same image.

>

On the view of hardware, DwUsb2 and DwUsb3 doesn't exist at the same time.

> > +

> > +STATIC DW_USB_PROTOCOL                *DwUsb;

> > +

> > +STATIC usb3_pcd_t                     gPcd;

>

> This seems a very unfortunate choice for variable name.

>

OK. I'll rename it.

> > +STATIC UINT32                         *gEventBuf, *gEventPtr;

> > +STATIC struct usb_device_descriptor   gDwUsb3DevDesc;

> > +STATIC VOID                           *gRxBuf;

> > +

> > +STATIC usb_setup_pkt_t                *gEndPoint0SetupPacket;

> > +STATIC UINT8                          *gEndPoint0StatusBuf;

>

> Although most if not all of these will disappear when converting to

> UEFI driver model, why do they have 'g' prefix in the first place?

> 'g' is for globally visible symbols. Variables that are "global" in

> this file only are better off using 'm'.


OK. I'll fix it.
>

> > +STATIC USB_DEVICE_RX_CALLBACK         mDataReceivedCallback;

> > +STATIC UINTN                          mDataBufferSize;

> > +

> > +struct usb_interface_descriptor intf = {

> > +  sizeof (struct usb_interface_descriptor),

> > +  UDESC_INTERFACE,

> > +  0,

> > +  0,

> > +  2,

> > +  USB_CLASS_VENDOR_SPEC,

> > +  0x42,

> > +  0x03,

> > +  0

> > +};

> > +

> > +const struct usb_ss_ep_comp_descriptor ep_comp = {

> > +  sizeof (struct usb_ss_ep_comp_descriptor),

> > +  UDESC_SS_USB_COMPANION,

> > +  0,

> > +  0,

> > +  0

> > +};

> > +

> > +const struct usb_endpoint_descriptor hs_bulk_in = {

> > +  sizeof (struct usb_endpoint_descriptor),

> > +  UDESC_ENDPOINT,

> > +  UE_DIR_IN | USB3_BULK_IN_EP,

> > +  USB_ENDPOINT_XFER_BULK,

> > +  0x200,

> > +  0

> > +};

> > +

> > +const struct usb_endpoint_descriptor

> > +hs_bulk_out = {

> > +  sizeof(struct usb_endpoint_descriptor), /* bLength */

> > +  UDESC_ENDPOINT,                         /* bDescriptorType */

> > +

> > +  UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */

> > +  USB_ENDPOINT_XFER_BULK,        /* bmAttributes */

> > +  0x200,                         /* wMaxPacketSize: 512 of high-speed */

> > +  1,                             /* bInterval */

> > +};

> > +

> > +const struct usb_endpoint_descriptor ss_bulk_in = {

> > +  sizeof(struct usb_endpoint_descriptor), /* bLength */

> > +  UDESC_ENDPOINT,                         /* bDescriptorType */

> > +

> > +  UE_DIR_IN | USB3_BULK_IN_EP,   /* bEndpointAddress */

> > +  USB_ENDPOINT_XFER_BULK,        /* bmAttributes */

> > +  0x400,                         /* wMaxPacketSize: 1024 of super-speed */

> > +  0,                             /* bInterval */

> > +};

> > +

> > +const struct usb_endpoint_descriptor ss_bulk_out = {

> > +  sizeof(struct usb_endpoint_descriptor), /* bLength */

> > +  UDESC_ENDPOINT,                         /* bDescriptorType */

> > +

> > +  UE_DIR_OUT | USB3_BULK_OUT_EP,  /* bEndpointAddress */

> > +  USB_ENDPOINT_XFER_BULK,         /* bmAttributes */

> > +  0x400,                          /* wMaxPacketSize: 1024 of super-speed */

> > +  0,                              /* bInterval */

> > +};

> > +

> > +/** The BOS Descriptor */

>

> What's a BOS?

>

Let me add comment on it.

> > +

> > +const struct usb_dev_cap_20_ext_desc cap1 = {

> > +  sizeof(struct usb_dev_cap_20_ext_desc), /* bLength */

> > +  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */

> > +  USB_DEVICE_CAPABILITY_20_EXTENSION,     /* bDevCapabilityType */

> > +  0x2,                                    /* bmAttributes */

> > +};

> > +

> > +const struct usb_dev_cap_ss_usb

> > +cap2 = {

> > +  sizeof(struct usb_dev_cap_ss_usb),      /* bLength */

> > +  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */

> > +  USB_DEVICE_CAPABILITY_SS_USB,           /* bDevCapabilityType */

> > +  0x0,                                    /* bmAttributes */

> > +  (USB_DC_SS_USB_SPEED_SUPPORT_SS |

> > +      USB_DC_SS_USB_SPEED_SUPPORT_HIGH),  /* wSpeedsSupported */

> > +  0x2,                                    /* bFunctionalitySupport */

> > +  0xa,                                    /* bU1DevExitLat */

> > +  0x100,                                  /* wU2DevExitLat */

> > +};

> > +

> > +const struct usb_dev_cap_container_id

> > +cap3 = {

> > +  sizeof(struct usb_dev_cap_container_id),/* bLength */

> > +  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */

> > +  USB_DEVICE_CAPABILITY_CONTAINER_ID,     /* bDevCapabilityType */

> > +  0,                                      /* bReserved */

> > +  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */

> > +};

> > +

> > +const struct wusb_bos_desc

> > +bos = {

> > +  sizeof(struct wusb_bos_desc),           /* bLength */

> > +  UDESC_BOS,                              /* bDescriptorType */

> > +  (sizeof(struct wusb_bos_desc) +         \

> > +    sizeof(cap1) + sizeof(cap2) +         \

> > +    sizeof(cap3)),                        /* wTotalLength */

> > +  3,                                      /* bNumDeviceCaps */

> > +};

> > +

> > +STATIC struct usb_enum_port_param usb_port_activity_config = {

> > +  .idVendor           = USB_ENUM_ADB_PORT_VID,

> > +  .idProduct          = USB_ENUM_ADB_PORT_PID,

> > +  .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS,

> > +  .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL

> > +};

> > +

> > +STATIC

> > +UINT32

> > +DwUsb3GetEventBufEvent (

> > +  IN UINTN               Size

> > +  )

> > +{

> > +  UINT32                 Event;

> > +

> > +  Event = *gEventPtr++;

> > +  if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) {

> > +    gEventPtr = gEventBuf;

> > +  }

> > +  return Event;

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3SetFifoSize (

> > +  IN UINT32              Addr,

> > +  IN UINT32              Depth,

> > +  IN UINT32              Dir,

> > +  IN UINT32              FifoNum

> > +  )

> > +{

> > +  UINT32                 Reg = 0;

> > +

> > +  if (Dir == FIFO_DIR_TX) {

> > +    Reg = GTXFIFOSIZ (FifoNum);

> > +  } else if (Dir == FIFO_DIR_RX) {

> > +    Reg = GRXFIFOSIZ (FifoNum);

> > +  } else {

> > +    ASSERT (0);

> > +  }

> > +  MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr));

> > +}

> > +

> > +STATIC

> > +UINT32

> > +Handshake (

>

> What does this function do? "Handshake" does not tell me enough to

> figure out.

>

> > +  IN UINT32              Reg,

> > +  IN UINT32              Mask,

> > +  IN UINT32              Done

> > +  )

> > +{

> > +  UINT32                 Timeout = 100000;

> > +

> > +  do {

> > +    if ((MmioRead32 (Reg) & Mask) == Done) {

> > +      return 1;

> > +    }

> > +    MicroSecondDelay (1);

> > +  } while (Timeout-- > 0);

> > +  return 0;

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3FillDesc (

> > +  IN usb3_dma_desc_t     *desc,

> > +  IN UINT64              dma_addr,

> > +  IN UINT32              dma_len,

> > +  IN UINT32              stream,

> > +  IN UINT32              type,

> > +  IN UINT32              ctrlbits,

> > +  IN UINT32              own

> > +  )

> > +{

> > +  desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF);

> > +  desc->bpth = (UINT32)(dma_addr >> 32);

>

> Could you possibly create LOW_32BIT and HIGH_32BIT macros for

> MdePkg/Base.h instead? We are already duplicating these operations all

> over the place. Including all over MdeModulePkg.

>

OK

> > +  desc->status = DSCSTS_XFERCNT (dma_len);

> > +  if (type) {

> > +    desc->control = DSCCTL_TRBCTL (type);

> > +  }

> > +  desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits;

> > +  ArmDataSynchronizationBarrier ();

>

> Please use MemoryFence() instead.

> This controller is not ARM-specific.

>

> (DSB? That sounds excessive. DMB should suffice?)

>


OK

> > +  /* must execute this operation at last */

> > +  if (own) {

> > +    desc->control |= DSCCTL_HWO;

> > +  }

> > +  ArmDataSynchronizationBarrier ();

>

> As above.

>

OK

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3DepStartNewCfg (

> > +  IN UINT32              EpIdx,

> > +  IN UINT32              RsrcIdx

> > +  )

> > +{

> > +  /* start the command */

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | \

> > +    DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3DepCfg (

>

> Please no abbreviations in function names. This name tells me nothing

> about what the function does (and there is no comment describing its

> function).

>

OK

> > +  IN UINT32              EpIdx,

> > +  IN UINT32              DepCfg0,

> > +  IN UINT32              DepCfg1,

> > +  IN UINT32              DepCfg2

> > +  )

> > +{

> > +  MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2);

> > +  MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1);

> > +  MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0);

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3DepXferCfg (

>

> Dep<something>TransferConfig.

> Please address throughout.

>

> > +  IN UINT32              EpIdx,

> > +  IN UINT32              DepStrmCfg

> > +  )

> > +{

> > +  MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg);

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +STATIC

> > +UINT8

> > +DwUsb3DepStartXfer (

> > +  IN UINT32              EpIdx,

> > +  IN UINT64              DmaAddr,

> > +  IN UINT32              StreamOrUf

> > +  )

> > +{

> > +  UINT32                 Data;

> > +

> > +  MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr);

> > +  MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32));

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | \

> > +    DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +  Data = MmioRead32 (DEPCMD (EpIdx));

> > +  return GET_DEPCMD_XFER_RSRC_IDX(Data);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3DepStopXfer (

> > +  IN UINT32               EpIdx,

> > +  IN UINT32               Tri

> > +  )

> > +{

> > +  MmioWrite32 (DEPCMDPAR2 (EpIdx), 0);

> > +  MmioWrite32 (DEPCMDPAR1 (EpIdx), 0);

> > +  MmioWrite32 (DEPCMDPAR0 (EpIdx), 0);

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | \

> > +    DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +VOID

> > +DwUsb3DepUpdateXfer (

> > +  IN UINT32               EpIdx,

> > +  IN UINT32               Tri

> > +  )

> > +{

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | \

> > +    DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3DepClearStall (

> > +  IN UINTN            EpIdx

> > +  )

> > +{

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +

> > +STATIC

> > +VOID

> > +DwUsb3DepSetStall (

> > +  IN UINTN            EpIdx

> > +  )

> > +{

> > +  MmioWrite32 (

> > +    DEPCMD (EpIdx),

> > +    DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT

> > +    );

> > +  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3EnableEp (

>

> EnableEndpoint

>

OK

> > +  IN UINT32                EpIdx,

>

> EndpointIndex.

>

OK

> > +  IN usb3_pcd_ep_t         *ep

>

> Endpoint.

>

OK

> > +  )

> > +{

> > +  UINT32                   Dalepena;

>

> What?

>

> > +

> > +  Dalepena = MmioRead32 (DALEPENA);

> > +  /* If the EP is already enabled, skip to set it again. */

>

> endpoint

>

> > +  if (Dalepena & (1 << EpIdx)) {

> > +    return;

> > +  }

> > +  Dalepena |= 1 << EpIdx;

> > +  MmioWrite32 (DALEPENA, Dalepena);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3Ep0Activate (

>

> (EP0 is special, so may not need expanding.)

>

> > +  IN OUT usb3_pcd_t         *pcd

> > +  )

> > +{

> > +  /* issue DEPCFG command to EP0 OUT */

>

> ... except for in comments.

>

> > +  DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0);

> > +  DwUsb3DepCfg (

> > +    EP_OUT_IDX (0),

> > +    EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512),

> > +    EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY,

> > +    0

> > +    );

> > +  /* issue DEPSTRMCFG command to EP0 OUT */

> > +  DwUsb3DepXferCfg (EP_OUT_IDX (0), 1);  // one stream

> > +  /* issue DEPCFG command to EP0 IN */

> > +  DwUsb3DepCfg (

> > +    EP_IN_IDX (0),

> > +    EPCFG0_EPTYPE (EPTYPE_CONTROL)  | EPCFG0_MPS (512) | \

> > +    EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num),

> > +    EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN,

> > +    0

> > +    );

> > +  /* issue DEPSTRMCFG command to EP0 IN */

> > +  DwUsb3DepXferCfg (EP_IN_IDX (0), 1);  // one stream

> > +  pcd->ep0.active = 1;

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3EpActivate (

> > +  IN OUT usb3_pcd_t         *pcd,

> > +  IN OUT usb3_pcd_ep_t      *ep

> > +  )

> > +{

> > +  UINT32                    EpIdx, DepCfg0, DepCfg1;

> > +  if (ep->is_in) {

> > +    EpIdx = EP_IN_IDX (ep->num);

> > +  } else {

> > +    EpIdx = EP_OUT_IDX (ep->num);

> > +  }

> > +

> > +  /* Start a new configurate when enable the first EP. */

> > +  if (!pcd->eps_enabled) {

> > +    pcd->eps_enabled = 1;

> > +    /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first.

> > +     * It resets the core's Tx FIFO mapping table.

> > +     */

> > +    DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL);

> > +    DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);

> > +    DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN;

> > +

> > +    switch (pcd->speed) {

> > +    case USB_SPEED_SUPER:

> > +      DepCfg0 |= EPCFG0_MPS (512);

> > +      break;

> > +    case USB_SPEED_HIGH:

> > +    case USB_SPEED_FULL:

> > +      DepCfg0 |= EPCFG0_MPS (64);

> > +      break;

> > +    case USB_SPEED_LOW:

> > +      DepCfg0 |= EPCFG0_MPS (8);

>

> No live coding of values.

> Add #defines for those speed setting values.

>

> > +      break;

> > +    default:

> > +      ASSERT (0);

> > +      break;

> > +    }

> > +    DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0);

>

> What does that final 0 do?

>

> > +    DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2);

>

> And that 2?

>

> Please address throughout.

>

> > +  }

> > +  /* issue DEPCFG command to EP */

> > +  DepCfg0 = EPCFG0_EPTYPE (ep->type);

> > +  DepCfg0 |= EPCFG0_MPS (ep->maxpacket);

> > +  if (ep->is_in) {

> > +    DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num);

> > +  }

> > +  DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst);

> > +  DepCfg1 = EPCFG1_EP_NUM (ep->num);

> > +  if (ep->is_in) {

> > +    DepCfg1 |= EPCFG1_EP_DIR_IN;

> > +  } else {

> > +    DepCfg1 |= EPCFG1_XFER_CMPL;

> > +  }

> > +  DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0);

> > +  /* issue DEPSTRMCFG command to EP */

> > +  DwUsb3DepXferCfg (EpIdx, 1);

> > +  DwUsb3EnableEp (EpIdx, ep);

> > +  ep->active = 1;

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3Ep0OutStart (

> > +  IN usb3_pcd_t          *pcd

> > +  )

> > +{

> > +  usb3_dma_desc_t        *desc;

> > +

> > +  /* Get the SETUP packet DMA Descriptor (TRB) */

> > +  desc = pcd->ep0_setup_desc;

> > +

> > +  /* DMA Descriptor setup */

> > +  DwUsb3FillDesc (

> > +    desc,

> > +    (UINT64)gEndPoint0SetupPacket,

> > +    pcd->ep0.maxpacket,

> > +    0,

> > +    TRBCTL_SETUP,

> > +    DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,

> > +    1

> > +    );

> > +

> > +  /* issue DEPSTRTXFER command to EP0 OUT */

> > +  pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0);

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsb3Init (

> > +  VOID

> > +  )

> > +{

> > +  UINT32                 Data, Addr;

>

> Address.

>

> > +  usb3_pcd_t             *pcd = &gPcd;

> > +

> > +  /* soft reset the usb core */

> > +  do {

> > +    MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST);

> > +

> > +    do {

> > +      MicroSecondDelay (1000);

> > +      Data = MmioRead32 (DCTL);

> > +    } while (Data & DCTL_CSFTRST);

> > +    //

> > +    // wait for at least 3 PHY clocks

> > +    //

> > +    MicroSecondDelay (1000);

> > +  } while (0);

> > +

> > +  pcd->link_state = 0;

> > +

> > +  /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */

> > +  MmioAndThenOr32 (

> > +    GUSB2PHYCFG (0),

> > +    ~GUSB2PHYCFG_USBTRDTIM_MASK,

> > +    GUSB2PHYCFG_USBTRDTIM (9)

>

> How long is 9?

>

> I will stop my review here and give a full review on v2 when the

> overarching comments have been addressed.

>

OK

Best Regards
Haojian
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox series

Patch

diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec
new file mode 100644
index 000000000000..038e4881a948
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec
@@ -0,0 +1,44 @@ 
+#/** @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                   = DwUsb3DxePkg
+  PACKAGE_GUID                   = 9b7aa6fe-405b-4955-af1f-5faf183aedec
+  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]
+  gDwUsb3DxeTokenSpaceGuid      = { 0x098a50d3, 0x92e2, 0x461a, { 0xb6, 0xba, 0xf8, 0x5d, 0x9d, 0x89, 0x49, 0xf5 }}
+
+[Protocols.common]
+  gDwUsbProtocolGuid            = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+
+[PcdsFixedAtBuild.common]
+  # DwUsb Driver PCDs
+  gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress|0x0|UINT32|0x00000001
diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf
new file mode 100644
index 000000000000..510b51a34de7
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf
@@ -0,0 +1,52 @@ 
+#/** @file
+#
+#  Copyright (c) 2018, Linaro Limited. 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                      = DwUsb3Dxe
+  FILE_GUID                      = 0879cd34-c399-4315-9891-56024072e711
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = DwUsb3EntryPoint
+
+[Sources.common]
+  DwUsb3Dxe.c
+
+[LibraryClasses]
+  CacheMaintenanceLib
+  DebugLib
+  DmaLib
+  IoLib
+  MemoryAllocationLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UsbSerialNumberLib
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gUsbDeviceProtocolGuid
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Pcd]
+  gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress
+
+[Depex]
+  TRUE
diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h
new file mode 100644
index 000000000000..92b610553169
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h
@@ -0,0 +1,632 @@ 
+/** @file
+
+  Copyright (c) 2017, Linaro Limited. 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_USB3_DXE_H__
+#define __DW_USB3_DXE_H__
+
+#define DW_USB3_BASE                     FixedPcdGet32 (PcdDwUsb3DxeBaseAddress)
+
+#define GSBUCFG0                         (DW_USB3_BASE + 0xC100)
+#define GCTL                             (DW_USB3_BASE + 0xC110)
+
+#define GCTL_PWRDNSCALE_MASK             (0x1FFF << 19)
+#define GCTL_PWRDNSCALE(x)               (((x) & 0x1FFF) << 19)
+#define GCTL_U2RSTECN                    BIT16
+#define GCTL_PRTCAPDIR_MASK              (BIT13 | BIT12)
+#define GCTL_PRTCAPDIR_HOST              BIT12
+#define GCTL_PRTCAPDIR_DEVICE            BIT13
+#define GCTL_PRTCAPDIR_OTG               (BIT13 | BIT12)
+#define GCTL_U2EXIT_LFPS                 BIT2
+
+#define GUSB2PHYCFG(x)                   (DW_USB3_BASE + 0xC200 + (((x) & 0xF) << 2))
+
+#define GUSB2PHYCFG_USBTRDTIM_MASK       (0xF << 10)
+#define GUSB2PHYCFG_USBTRDTIM(x)         (((x) & 0xF) << 10)
+#define GUSB2PHYCFG_SUSPHY               BIT6
+
+#define GUSB3PIPECTL(x)                  (DW_USB3_BASE + 0xC2C0 + (((x) & 0x3) << 2))
+
+#define PIPECTL_DELAYP1TRANS             BIT18
+#define PIPECTL_SUSPEND_EN               BIT17
+#define PIPECTL_LFPS_FILTER              BIT9
+#define PIPECTL_TX_DEMPH_MASK            (0x3 << 1)
+#define PIPECTL_TX_DEMPH(x)              (((x) & 0x3) << 1)
+
+#define GTXFIFOSIZ(x)                    (DW_USB3_BASE + 0xC300 + (((x) & 0x1F) << 2))
+#define GRXFIFOSIZ(x)                    (DW_USB3_BASE + 0xC380 + (((x) & 0x1F) << 2))
+
+#define FIFOSIZ_ADDR(x)                  (((x) & 0xFFFF) << 16)
+#define FIFOSIZ_DEP(x)                   ((x) & 0xFFFF)
+
+#define GEVNTADRL(x)                     (DW_USB3_BASE + 0xC400 + (((x) & 0x1F) << 2))
+#define GEVNTADRH(x)                     (DW_USB3_BASE + 0xC404 + (((x) & 0x1F) << 2))
+#define GEVNTSIZ(x)                      (DW_USB3_BASE + 0xC408 + (((x) & 0x1F) << 2))
+
+#define GEVNTSIZ_EVNTINTMASK             BIT31
+#define GEVNTSIZ_EVNTSIZ_MASK            (0xFFFF)
+#define GEVNTSIZ_EVNTSIZ(x)              ((x) & 0xFFFF)
+
+#define GEVNTCOUNT(x)                    (DW_USB3_BASE + 0xC40C + (((x) & 0x1F) << 2))
+#define GEVNTCOUNT_EVNTCOUNT_MASK        (0xFFFF)
+#define GEVNTCOUNT_EVNTCOUNT(x)          ((x) & 0xFFFF)
+
+// Non-Endpoint specific event flag
+#define GEVNT_INTTYPE_MASK               (0x7F << 1)
+#define GEVNT_INTTYPE(x)                 (((x) & 0x7F) << 1)
+#define EVENT_I2C_INT                    4
+#define EVENT_CARKIT_INT                 3
+#define EVENT_OTG_INT                    1
+#define EVENT_DEV_INT                    0
+
+#define GEVNT_NON_EP                     BIT0
+// Endpoint specific event flag
+#define GEVNT_DEPEVT_INTTYPE_MASK        (0xF << 6)
+#define GEVNT_DEPEVT_INTTYPE(x)          (((x) & 0xF) << 6)
+#define GEVNT_DEPEVT_INTTYPE_EPCMD_CMPL  (7 << 6)
+#define GEVNT_DEPEVT_INTTYPE_STRM_EVT    (6 << 6)
+#define GEVNT_DEPEVT_INTTYPE_FIFOXRUN    (4 << 6)
+#define GEVNT_DEPEVT_INTTYPE_XFER_NRDY   (3 << 6)
+#define GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG (2 << 6)
+#define GEVNT_DEPEVT_INTTYPE_XFER_CMPL   (1 << 6)
+#define GEVNT_DEPEVT_EPNUM_MASK          (0x1F << 1)
+#define GEVNT_DEPEVT_EPNUM_SHIFT         1
+#define GEVNT_DEPEVT_EPNUM(x)            (((x) & 0x1F) << 1)
+// Devices specific event flag
+#define GEVNT_DEVT_MASK                  (0xF << 8)
+#define GEVNT_DEVT_SHIFT                 8
+#define GEVNT_DEVT(x)                    (((x) & 0xF) << 8)
+#define GEVNT_DEVT_INACT_TIMEOUT_RCVD    (0x15 << 8)
+#define GEVNT_DEVT_VNDR_DEV_TST_RCVD     (0x14 << 8)
+#define GEVNT_DEVT_OVERFLOW              (0x13 << 8)
+#define GEVNT_DEVT_CMD_CMPL              (0x12 << 8)
+#define GEVNT_DEVT_ERRATICERR            (0x11 << 8)
+#define GEVNT_DEVT_SOF                   (0x7 << 8)
+#define GEVNT_DEVT_EOPF                  (0x6 << 8)
+#define GEVNT_DEVT_HIBER_REQ             (0x5 << 8)
+#define GEVNT_DEVT_WKUP                  (0x4 << 8)
+#define GEVNT_DEVT_ULST_CHNG             (0x3 << 8)
+#define GEVNT_DEVT_CONNDONE              (0x2 << 8)
+#define GEVNT_DEVT_USBRESET              (0x1 << 8)
+#define GEVNT_DEVT_DISCONN               (0x0 << 8)
+
+#define DCFG                             (DW_USB3_BASE + 0xC700)
+
+#define DCFG_NUMP_MASK                   (0x1F << 17)
+#define DCFG_NUMP(x)                     (((x) & 0x1F) << 17)
+#define DCFG_DEVADDR_MASK                (0x7F << 3)
+#define DCFG_DEVADDR(x)                  (((x) & 0x7F) << 3)
+#define DCFG_DEVSPD_MASK                 (0x7)
+#define DCFG_DEVSPD(x)                   ((x) & 0x7)
+#define DEVSPD_HS_PHY_30MHZ_OR_60MHZ     0
+#define DEVSPD_FS_PHY_30MHZ_OR_60MHZ     1
+#define DEVSPD_LS_PHY_6MHZ               2
+#define DEVSPD_FS_PHY_48MHZ              3
+#define DEVSPD_SS_PHY_125MHZ_OR_250MHZ   4
+
+#define DCTL                             (DW_USB3_BASE + 0xC704)
+
+#define DCTL_RUN_STOP                    BIT31
+#define DCTL_CSFTRST                     BIT30
+#define DCTL_INIT_U2_EN                  BIT12
+#define DCTL_ACCEPT_U2_EN                BIT11
+#define DCTL_INIT_U1_EN                  BIT10
+#define DCTL_ACCEPT_U1_EN                BIT9
+
+#define DEVTEN                           (DW_USB3_BASE + 0xC708)
+#define DEVTEN_CONNECTDONEEN             BIT2
+#define DEVTEN_USBRSTEN                  BIT1
+#define DEVTEN_DISCONNEN                 BIT0
+
+#define DSTS                             (DW_USB3_BASE + 0xC70C)
+#define DSTS_GET_DEVSPD(x)               ((x) & 0x7)
+
+#define DALEPENA                         (DW_USB3_BASE + 0xC720)
+
+#define DEPCMDPAR2(x)                    (DW_USB3_BASE + 0xC800 + ((x) & 0x1F) * 0x10)
+#define DEPCMDPAR1(x)                    (DW_USB3_BASE + 0xC804 + ((x) & 0x1F) * 0x10)
+#define DEPCMDPAR0(x)                    (DW_USB3_BASE + 0xC808 + ((x) & 0x1F) * 0x10)
+#define DEPCMD(x)                        (DW_USB3_BASE + 0xc80C + ((x) & 0x1F) * 0x10)
+
+#define DEPCMD_COMMANDPARAM_MASK         (0xFFFF << 16)
+#define DEPCMD_COMMANDPARAM(x)           (((x) & 0xFFFF) << 16)
+/* Stream Number or uFrame (input) */
+#define DEPCMD_STR_NUM_OR_UF_MASK        (0xFFFF << 16)
+#define DEPCMD_STR_NUM_OR_UF(x)          (((x) & 0xFFFF) << 16)
+/* Transfer Resource Index (output) */
+#define DEPCMD_XFER_RSRC_IDX_SHIFT       16
+#define DEPCMD_XFER_RSRC_IDX_MASK        (0x7F << 16)
+#define DEPCMD_XFER_RSRC_IDX(x)          (((x) & 0x7F) << 16)
+#define GET_DEPCMD_XFER_RSRC_IDX(x)      (((x) >> 16) & 0x7F)
+#define DEPCMD_CMDACT                    BIT10
+#define DEPCMD_CMDTYPE_MASK              0xFF
+#define DEPCMD_CMDTYPE(x)                ((x) & 0xFF)
+
+/* EP registers range as: OUT0, IN0, OUT1, IN1, ... */
+#define EP_OUT_IDX(x)                    ((x) * 2)
+#define EP_IN_IDX(x)                     (((x) * 2) + 1)
+
+#define CMDTYPE_SET_EP_CFG               1
+#define CMDTYPE_SET_XFER_CFG             2
+#define CMDTYPE_GET_EP_STATE             3
+#define CMDTYPE_SET_STALL                4
+#define CMDTYPE_CLR_STALL                5
+#define CMDTYPE_START_XFER               6
+#define CMDTYPE_UPDATE_XFER              7
+#define CMDTYPE_END_XFER                 8
+#define CMDTYPE_START_NEW_CFG            9
+
+#define EPTYPE_CONTROL                   0
+#define EPTYPE_ISOC                      1
+#define EPTYPE_BULK                      2
+#define EPTYPE_INTR                      3
+
+#define CFG_ACTION_INIT                  0
+#define CFG_ACTION_RESTORE               1
+#define CFG_ACTION_MODIFY                2
+
+#define EPCFG0_CFG_ACTION_MASK           (0x3 << 30)
+#define EPCFG0_CFG_ACTION(x)             (((x) & 0x3) << 30)
+#define EPCFG0_BRSTSIZ_MASK              (0xF << 22)
+#define EPCFG0_BRSTSIZ(x)                (((x) & 0xF) << 22)
+#define EPCFG0_TXFNUM_MASK               (0x1F << 17)
+#define EPCFG0_TXFNUM(x)                 (((x) & 0x1F) << 17)
+#define EPCFG0_MPS_MASK                  (0x7FF << 3)
+#define EPCFG0_MPS(x)                    (((x) & 0x7FF) << 3)
+#define EPCFG0_EPTYPE_MASK               (0x3 << 1)
+#define EPCFG0_EPTYPE_SHIFT              1
+#define EPCFG0_EPTYPE(x)                 (((x) & 0x3) << 1)
+
+/* Endpoint Number */
+#define EPCFG1_EP_NUM_MASK               (0xF << 26)
+#define EPCFG1_EP_NUM(x)                 (((x) & 0xF) << 26)
+/* Endpoint Direction */
+#define EPCFG1_EP_DIR_IN                 BIT25
+/* Stream Not Ready */
+#define EPCFG1_XFER_NRDY                 BIT10
+/* XferInProgress Enable */
+#define EPCFG1_XFER_IN_PROG              BIT9
+/* Stream Completed */
+#define EPCFG1_XFER_CMPL                 BIT8
+
+#define USB_SPEED_UNKNOWN                0
+#define USB_SPEED_LOW                    1
+#define USB_SPEED_FULL                   2
+#define USB_SPEED_HIGH                   3
+#define USB_SPEED_VARIABLE               4
+#define USB_SPEED_SUPER                  5
+
+// DMA registers
+#define DSCSTS_TRBRSP_MASK               (0xF << 28)
+#define DSCSTS_TRBRSP(x)                 (((x) & 0xF) << 28)
+#define GET_DSCSTS_TRBRSP(x)             (((x) >> 28) & 0xF)
+#define TRBRSP_MISSED_ISOC_IN            1
+#define TRBRSP_SETUP_PEND                2
+#define TRBRSP_XFER_IN_PROG              4
+#define DSCSTS_PCM1_MASK                 (0x3 << 24)
+#define DSCSTS_PCM1(x)                   (((x) & 0x3) << 24)
+#define DSCSTS_XFERCNT_MASK              0xFFFFFF
+#define DSCSTS_XFERCNT(x)                ((x) & 0xFFFFFF)
+#define GET_DSCSTS_XFERCNT(x)            ((x) & 0xFFFFFF)
+
+#define DSCCTL_STRMID_SOFN(x)            (((x) & 0xFFFF) << 14)
+#define DSCCTL_IOC                       BIT11
+#define DSCCTL_ISP                       BIT10
+#define DSCCTL_TRBCTL_MASK               (0x3F << 4)
+#define DSCCTL_TRBCTL(x)                 (((x) & 0x3F) << 4)
+#define DSCCTL_LST                       BIT1
+#define DSCCTL_HWO                       BIT0
+#define TRBCTL_NORMAL                    1
+#define TRBCTL_SETUP                     2
+#define TRBCTL_STATUS_2                  3
+#define TRBCTL_STATUS_3                  4
+#define TRBCTL_CTLDATA_1ST               5
+#define TRBCTL_ISOC_1ST                  6
+#define TRBCTL_ISOC                      7
+#define TRBCTL_LINK                      8
+#define TRBCTL_NORMAL_ZLP                9
+
+
+#define UE_DIR_IN                        0x80
+#define UE_DIR_OUT                       0
+#define UE_SET_DIR(a, d)                 ((a) | (((d) & 1) << 7))
+#define UE_GET_DIR(a)                    ((a) & 0x80)
+#define UE_ADDR                          0x0F
+#define UE_GET_ADDR(a)                   ((a) & UE_ADDR)
+
+#define UT_GET_DIR(a)                    ((a) & 0x80)
+#define UT_WRITE                         0x00
+#define UT_READ                          0x80
+
+#define UT_GET_TYPE(a)                   ((a) & 0x60)
+#define UT_STANDARD                      0x00
+#define UT_CLASS                         0x20
+#define UT_VENDOR                        0x40
+
+#define UT_GET_RECIPIENT(a)              ((a) & 0x1f)
+#define UT_DEVICE                        0x00
+#define UT_INTERFACE                     0x01
+#define UT_ENDPOINT                      0x02
+#define UT_OTHER                         0x03
+
+#define UR_GET_STATUS                    0x00
+#define UR_CLEAR_FEATURE                 0x01
+#define UR_SET_FEATURE                   0x03
+#define UR_SET_ADDRESS                   0x05
+#define UR_GET_DESCRIPTOR                0x06
+#define UR_SET_DESCRIPTOR                0x07
+#define UR_GET_CONFIG                    0x08
+#define UR_SET_CONFIG                    0x09
+#define UR_GET_INTERFACE                 0x0A
+#define UR_SET_INTERFACE                 0x0B
+#define UR_SYNCH_FRAME                   0x0C
+#define UR_SET_SEL                       0x30
+#define UR_SET_ISOC_DELAY                0x31
+
+/* Feature numbers */
+#define UF_ENDPOINT_HALT                 0
+#define UF_DEVICE_REMOTE_WAKEUP          1
+#define UF_TEST_MODE                     2
+#define UF_DEVICE_B_HNP_ENABLE           3
+#define UF_DEVICE_A_HNP_SUPPORT          4
+#define UF_DEVICE_A_ALT_HNP_SUPPORT      5
+#define UF_FUNCTION_SUSPEND              0
+#define UF_U1_ENABLE                     48
+#define UF_U2_ENABLE                     49
+#define UF_LTM_ENABLE                    50
+
+#define  UDESC_DEVICE                    0x01
+#define  UDESC_CONFIG                    0x02
+#define  UDESC_STRING                    0x03
+#define  UDESC_INTERFACE                 0x04
+#define  UDESC_ENDPOINT                  0x05
+#define  UDESC_SS_USB_COMPANION          0x30
+#define  UDESC_DEVICE_QUALIFIER          0x06
+#define  UDESC_BOS                       0x0f
+#define  UDESC_DEVICE_CAPABILITY         0x10
+
+#define STRING_LANGUAGE                  0
+#define STRING_MANUFACTURER              1
+#define STRING_PRODUCT                   2
+#define STRING_SERIAL                    3
+
+#define CONFIG_VALUE    1
+
+#define USB3_BULK_IN_EP                  1
+#define USB3_BULK_OUT_EP                 1
+
+#define USB_ENUM_ADB_PORT_VID            0x18D1
+#define USB_ENUM_ADB_PORT_PID            0xD00D
+#define USB_ENUM_INTERFACE_ADB_SUBCLASS  0x42
+#define USB_ENUM_INTERFACE_ADB_PROTOCOL  0x03
+
+struct usb3_pcd;
+
+typedef enum pcd_state {
+  USB3_STATE_UNCONNECTED,                /* no host */
+  USB3_STATE_DEFAULT,
+  USB3_STATE_ADDRESSED,
+  USB3_STATE_CONFIGURED,
+} pcdstate_e;
+
+typedef enum ep0_state {
+  EP0_IDLE,
+  EP0_IN_DATA_PHASE,
+  EP0_OUT_DATA_PHASE,
+  EP0_IN_WAIT_NRDY,
+  EP0_OUT_WAIT_NRDY,
+  EP0_IN_STATUS_PHASE,
+  EP0_OUT_STATUS_PHASE,
+  EP0_STALL,
+} ep0state_e;
+
+typedef struct usb3_dma_desc {
+  /** Buffer Pointer - Low address quadlet */
+  UINT32     bptl;
+
+  /** Buffer Pointer - High address quadlet */
+  UINT32     bpth;
+
+  /** Status quadlet. Fields defined in enum @ref desc_sts_data. */
+  UINT32     status;
+
+  /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */
+  UINT32     control;
+} usb3_dma_desc_t;
+
+typedef struct usb3_pcd_req {
+  usb3_dma_desc_t *trb;
+  UINT64 trbdma;
+
+  UINT32 length;
+  UINT32 actual;
+
+  UINT64 *bufdma;
+  int (*complete)(unsigned actual, int status);
+} usb3_pcd_req_t;
+
+typedef struct usb_device_request {
+  UINT8 bmRequestType;
+  UINT8 bRequest;
+  UINT16 wValue;
+  UINT16 wIndex;
+  UINT16 wLength;
+} usb_device_request_t;
+
+#pragma pack(1)
+/** USB_DT_DEVICE: Device descriptor */
+typedef struct usb_device_descriptor {
+  UINT8  bLength;
+  UINT8  bDescriptorType;
+
+  UINT16 bcdUSB;
+#define USB_CLASS_COMM          0x02
+#define USB_CLASS_VENDOR_SPEC   0xFF
+#define USB_SC_VENDOR_SPEC      0xFF
+#define USB_PR_VENDOR_SPEC      0xFF
+  UINT8  bDeviceClass;
+  UINT8  bDeviceSubClass;
+  UINT8  bDeviceProtocol;
+  UINT8  bMaxPacketSize0;
+  UINT16 idVendor;
+  UINT16 idProduct;
+  UINT16 bcdDevice;
+  UINT8  iManufacturer;
+  UINT8  iProduct;
+  UINT8  iSerialNumber;
+  UINT8  bNumConfigurations;
+} usb_device_descriptor_t;
+
+/* USB_DT_CONFIG: Config descriptor */
+typedef struct usb_config_descriptor {
+  UINT8  bLength;
+  UINT8  bDescriptorType;
+
+  UINT16 wTotalLength;
+  UINT8  bNumInterfaces;
+#define CONFIG_VALUE            1
+  UINT8  bConfigurationValue;
+  UINT8  iConfiguration;
+#define USB_CONFIG_ATT_ONE      (1 << 7)
+  UINT8  bmAttributes;
+#define USB_CONFIG_VBUS_DRAW    (0xFA)
+  UINT8  bMaxPower;
+} usb_config_descriptor_t;
+
+/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+typedef struct usb_qualifier_descriptor {
+  UINT8  bLength;
+  UINT8  bDescriptorType;
+
+  UINT16 bcdUSB;
+  UINT8  bDeviceClass;
+  UINT8  bDeviceSubClass;
+  UINT8  bDeviceProtocol;
+  UINT8  bMaxPacketSize0;
+  UINT8  bNumConfigurations;
+  UINT8  bRESERVED;
+} usb_qualifier_descriptor_t;
+
+/* USB_DT_INTERFACE: Interface descriptor */
+typedef struct usb_interface_descriptor {
+  UINT8  bLength;
+  UINT8  bDescriptorType;
+
+  UINT8  bInterfaceNumber;
+  UINT8  bAlternateSetting;
+  UINT8  bNumEndpoints;
+  UINT8  bInterfaceClass;
+  UINT8  bInterfaceSubClass;
+  UINT8  bInterfaceProtocol;
+  UINT8  iInterface;
+} usb_interface_descriptor_t;
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+typedef struct usb_endpoint_descriptor {
+  UINT8  bLength;
+  UINT8  bDescriptorType;
+
+  UINT8  bEndpointAddress;
+  UINT8  bmAttributes;
+#define USB_ENDPOINT_XFER_CONTROL       0x00
+#define USB_ENDPOINT_XFER_ISOC          0x01
+#define USB_ENDPOINT_XFER_BULK          0x02
+#define USB_ENDPOINT_XFER_INT           0x03
+  UINT16 wMaxPacketSize;
+  UINT8  bInterval;
+} usb_endpoint_descriptor_t;
+
+/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
+typedef struct usb_ss_ep_comp_descriptor {
+  UINT8  bLength;
+  UINT8  bDescriptorType;
+
+  UINT8  bMaxBurst;
+  UINT8  bmAttributes;
+  UINT16 wBytesPerInterval;
+} usb_ss_ep_comp_descriptor_t;
+
+/* WUSB BOS Descriptor (Binary device Object Store) */
+typedef struct wusb_bos_desc {
+  UINT8 bLength;
+  UINT8 bDescriptorType;
+  UINT16 wTotalLength;
+  UINT8 bNumDeviceCaps;
+} wusb_bos_desc_t;
+
+#define USB_DEVICE_CAPABILITY_20_EXTENSION      0x02
+typedef struct usb_dev_cap_20_ext_desc {
+  UINT8 bLength;
+  UINT8 bDescriptorType;
+  UINT8 bDevCapabilityType;
+#define USB_20_EXT_LPM                          0x02
+  UINT32 bmAttributes;
+} usb_dev_cap_20_ext_desc_t;
+
+#define USB_DEVICE_CAPABILITY_SS_USB            0x03
+typedef struct usb_dev_cap_ss_usb {
+  UINT8 bLength;
+  UINT8 bDescriptorType;
+  UINT8 bDevCapabilityType;
+#define USB_DC_SS_USB_LTM_CAPABLE               0x02
+  UINT8 bmAttributes;
+#define USB_DC_SS_USB_SPEED_SUPPORT_LOW         0x01
+#define USB_DC_SS_USB_SPEED_SUPPORT_FULL        0x02
+#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH        0x04
+#define USB_DC_SS_USB_SPEED_SUPPORT_SS          0x08
+  UINT32 wSpeedsSupported;
+  UINT8 bFunctionalitySupport;
+  UINT8 bU1DevExitLat;
+  UINT32 wU2DevExitLat;
+} usb_dev_cap_ss_usb_t;
+
+#define USB_DEVICE_CAPABILITY_CONTAINER_ID      0x04
+typedef struct usb_dev_cap_container_id {
+  UINT8 bLength;
+  UINT8 bDescriptorType;
+  UINT8 bDevCapabilityType;
+  UINT8 bReserved;
+  UINT8 containerID[16];
+} usb_dev_cap_container_id_t;
+#pragma pack()
+
+typedef union usb_setup_pkt {
+  usb_device_request_t req;
+  UINT32 d32[2];
+  UINT8 d8[8];
+} usb_setup_pkt_t;
+
+typedef struct usb3_pcd_ep {
+  struct usb3_pcd *pcd;
+
+  UINT8          EpInIdx;
+  UINT8          EpOutIdx;
+  UINT8          phys;
+
+  //UINT8 phys;
+  UINT8 num;
+  UINT8 type;
+  UINT8 maxburst;
+  UINT16 maxpacket;
+  /* Tx FIFO # for IN EPs */
+  UINT8 tx_fifo_num;
+
+  /* The Transfer Resource Index from the Start Transfer command */
+  UINT8 tri_out;
+  UINT8 tri_in;
+
+  UINT8 stopped;
+  /* Send ZLP */
+  UINT8 send_zlp;
+  /* True if 3-stage control transfer */
+  UINT8 three_stage;
+  /* True if transfer has been started on EP */
+  UINT8 xfer_started;
+  /* EP direction 0 = OUT */
+  UINT8 is_in;
+  /* True if endpoint is active */
+  UINT8 active;
+  /* Initial data pid of bulk endpoint */
+  UINT8 data_pid_start;
+
+  /* ep_desc (excluding ep0) */
+  usb3_dma_desc_t *ep_desc;
+
+#if 0
+  /* TRB descriptor must be aligned to 16 bytes */
+  UINT8 epx_desc[32];
+#endif
+
+  /* request (excluding ep0) */
+  usb3_pcd_req_t req;
+} usb3_pcd_ep_t;
+
+typedef struct usb3_pcd {
+  //struct usb3_device *usb3_dev;
+
+  INT32 link_state;
+  pcdstate_e state;
+  UINT8 new_config;
+  ep0state_e ep0state;
+
+  UINT32 eps_enabled;
+  UINT32 ltm_enable;
+
+  usb3_pcd_ep_t ep0;
+  usb3_pcd_ep_t out_ep;
+  usb3_pcd_ep_t in_ep;
+
+  /*
+  usb3_dev_global_regs_t *dev_global_regs;
+  usb3_dev_ep_regs_t *out_ep_regs;
+  usb3_dev_ep_regs_t *in_ep_regs;
+  */
+
+  usb3_pcd_req_t ep0_req;
+
+  UINT8 speed;
+
+  usb3_dma_desc_t *ep0_setup_desc;
+  usb3_dma_desc_t *ep0_in_desc;
+  usb3_dma_desc_t *ep0_out_desc;
+
+  /* TRB descriptor must be aligned to 16 bytes */
+#if 0
+  UINT8 ep0_setup[32];
+  UINT8 ep0_in[32];
+  UINT8 ep0_out[32];
+
+  usb_setup_pkt_t ep0_setup_pkt[5];
+
+#define USB3_STATUS_BUF_SIZE    512
+  UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE];
+
+#define USB3_BULK_BUF_SIZE      2048
+  UINT8 ss_bulk_buf[USB3_BULK_BUF_SIZE];
+#endif
+
+  UINT32 file_type;
+  UINT32 file_address;
+  UINT32 file_capacity;
+  UINT32 file_total_frame;
+  UINT32 file_curr_frame;
+  UINT32 file_next_frame;
+  UINT32 file_received;
+  UINT32 file_complete;
+
+  UINT16 test_mode_nr;
+  UINT16 test_mode;
+} usb3_pcd_t;
+
+struct usb_enum_port_param {
+  UINT16     idVendor;
+  UINT16     idProduct;
+  UINT8      bInterfaceSubClass;
+  UINT8      bInterfaceProtocol;
+};
+
+#if 0
+typedef struct usb3_pcd_req {
+  usb3_dma_desc_t *trb;
+  UINT64 trbdma;
+
+  UINT32 length;
+  UINT32 actual;
+
+  UINT64 *bufdma;
+  int (*complete)(unsigned actual, int status);
+} usb3_pcd_req_t;
+
+#endif
+
+#endif /* __DW_USB3_DXE_H__ */
diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c
new file mode 100644
index 000000000000..83d5e4736de0
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c
@@ -0,0 +1,2434 @@ 
+/** @file
+
+  Copyright (c) 2018, Linaro Limited. 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/DriverBinding.h>
+#include <Protocol/UsbDevice.h>
+
+#include "DwUsb3Dxe.h"
+
+#define FIFO_DIR_TX                  0
+#define FIFO_DIR_RX                  1
+
+#define TX_FIFO_ADDR                 0
+#define RX_FIFO_ADDR                 0
+
+#define RAM_WIDTH                    8
+#define RAM_TX0_DEPTH                2048
+#define RAM_TX1_DEPTH                4096
+#define RAM_RX_DEPTH                 8192
+
+#define USB_TYPE_LENGTH              16
+#define USB_BLOCK_HIGH_SPEED_SIZE    512
+#define DATA_SIZE                    131072
+#define CMD_SIZE                     512
+#define MATCH_CMD_LITERAL(Cmd, Buf)  !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
+
+#define ALIGN(x, a)     (((x) + ((a) - 1)) & ~((a) - 1))
+
+//
+// The time between interrupt polls, in units of 100 nanoseconds
+// 10 Microseconds
+//
+#define DW_INTERRUPT_POLL_PERIOD     100
+
+#define DWUSB3_EVENT_BUF_SIZE        256
+
+//
+// Maxpacket size for EP0, defined by USB3 spec
+//
+#define USB3_MAX_EP0_SIZE            512
+
+//
+// Maxpacket size for any EP, defined by USB3 spec
+//
+#define USB3_MAX_PACKET_SIZE         1024
+#define USB2_HS_MAX_PACKET_SIZE      512
+#define USB2_FS_MAX_PACKET_SIZE      64
+
+#define USB3_STATE_UNCONNECTED       0
+#define USB3_STATE_DEFAULT           1
+#define USB3_STATE_ADDRESSED         2
+#define USB3_STATE_CONFIGURED        3
+
+#define USB3_STATUS_BUF_SIZE         512
+
+#define GET_EVENTBUF_COUNT()                                       \
+        (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0))))
+#define UPDATE_EVENTBUF_COUNT(x)                                   \
+        (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x)))
+
+#define SET_DEVADDR(x)                                             \
+        (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x)))
+
+EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
+
+STATIC DW_USB_PROTOCOL                *DwUsb;
+
+STATIC usb3_pcd_t                     gPcd;
+STATIC UINT32                         *gEventBuf, *gEventPtr;
+STATIC struct usb_device_descriptor   gDwUsb3DevDesc;
+STATIC VOID                           *gRxBuf;
+
+STATIC usb_setup_pkt_t                *gEndPoint0SetupPacket;
+STATIC UINT8                          *gEndPoint0StatusBuf;
+STATIC USB_DEVICE_RX_CALLBACK         mDataReceivedCallback;
+STATIC UINTN                          mDataBufferSize;
+
+struct usb_interface_descriptor intf = {
+  sizeof (struct usb_interface_descriptor),
+  UDESC_INTERFACE,
+  0,
+  0,
+  2,
+  USB_CLASS_VENDOR_SPEC,
+  0x42,
+  0x03,
+  0
+};
+
+const struct usb_ss_ep_comp_descriptor ep_comp = {
+  sizeof (struct usb_ss_ep_comp_descriptor),
+  UDESC_SS_USB_COMPANION,
+  0,
+  0,
+  0
+};
+
+const struct usb_endpoint_descriptor hs_bulk_in = {
+  sizeof (struct usb_endpoint_descriptor),
+  UDESC_ENDPOINT,
+  UE_DIR_IN | USB3_BULK_IN_EP,
+  USB_ENDPOINT_XFER_BULK,
+  0x200,
+  0
+};
+
+const struct usb_endpoint_descriptor
+hs_bulk_out = {
+  sizeof(struct usb_endpoint_descriptor), /* bLength */
+  UDESC_ENDPOINT,                         /* bDescriptorType */
+
+  UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */
+  USB_ENDPOINT_XFER_BULK,        /* bmAttributes */
+  0x200,                         /* wMaxPacketSize: 512 of high-speed */
+  1,                             /* bInterval */
+};
+
+const struct usb_endpoint_descriptor ss_bulk_in = {
+  sizeof(struct usb_endpoint_descriptor), /* bLength */
+  UDESC_ENDPOINT,                         /* bDescriptorType */
+
+  UE_DIR_IN | USB3_BULK_IN_EP,   /* bEndpointAddress */
+  USB_ENDPOINT_XFER_BULK,        /* bmAttributes */
+  0x400,                         /* wMaxPacketSize: 1024 of super-speed */
+  0,                             /* bInterval */
+};
+
+const struct usb_endpoint_descriptor ss_bulk_out = {
+  sizeof(struct usb_endpoint_descriptor), /* bLength */
+  UDESC_ENDPOINT,                         /* bDescriptorType */
+
+  UE_DIR_OUT | USB3_BULK_OUT_EP,  /* bEndpointAddress */
+  USB_ENDPOINT_XFER_BULK,         /* bmAttributes */
+  0x400,                          /* wMaxPacketSize: 1024 of super-speed */
+  0,                              /* bInterval */
+};
+
+/** The BOS Descriptor */
+
+const struct usb_dev_cap_20_ext_desc cap1 = {
+  sizeof(struct usb_dev_cap_20_ext_desc), /* bLength */
+  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */
+  USB_DEVICE_CAPABILITY_20_EXTENSION,     /* bDevCapabilityType */
+  0x2,                                    /* bmAttributes */
+};
+
+const struct usb_dev_cap_ss_usb
+cap2 = {
+  sizeof(struct usb_dev_cap_ss_usb),      /* bLength */
+  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */
+  USB_DEVICE_CAPABILITY_SS_USB,           /* bDevCapabilityType */
+  0x0,                                    /* bmAttributes */
+  (USB_DC_SS_USB_SPEED_SUPPORT_SS |
+      USB_DC_SS_USB_SPEED_SUPPORT_HIGH),  /* wSpeedsSupported */
+  0x2,                                    /* bFunctionalitySupport */
+  0xa,                                    /* bU1DevExitLat */
+  0x100,                                  /* wU2DevExitLat */
+};
+
+const struct usb_dev_cap_container_id
+cap3 = {
+  sizeof(struct usb_dev_cap_container_id),/* bLength */
+  UDESC_DEVICE_CAPABILITY,                /* bDescriptorType */
+  USB_DEVICE_CAPABILITY_CONTAINER_ID,     /* bDevCapabilityType */
+  0,                                      /* bReserved */
+  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */
+};
+
+const struct wusb_bos_desc
+bos = {
+  sizeof(struct wusb_bos_desc),           /* bLength */
+  UDESC_BOS,                              /* bDescriptorType */
+  (sizeof(struct wusb_bos_desc) +         \
+    sizeof(cap1) + sizeof(cap2) +         \
+    sizeof(cap3)),                        /* wTotalLength */
+  3,                                      /* bNumDeviceCaps */
+};
+
+STATIC struct usb_enum_port_param usb_port_activity_config = {
+  .idVendor           = USB_ENUM_ADB_PORT_VID,
+  .idProduct          = USB_ENUM_ADB_PORT_PID,
+  .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS,
+  .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL
+};
+
+STATIC
+UINT32
+DwUsb3GetEventBufEvent (
+  IN UINTN               Size
+  )
+{
+  UINT32                 Event;
+
+  Event = *gEventPtr++;
+  if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) {
+    gEventPtr = gEventBuf;
+  }
+  return Event;
+}
+
+STATIC
+VOID
+DwUsb3SetFifoSize (
+  IN UINT32              Addr,
+  IN UINT32              Depth,
+  IN UINT32              Dir,
+  IN UINT32              FifoNum
+  )
+{
+  UINT32                 Reg = 0;
+
+  if (Dir == FIFO_DIR_TX) {
+    Reg = GTXFIFOSIZ (FifoNum);
+  } else if (Dir == FIFO_DIR_RX) {
+    Reg = GRXFIFOSIZ (FifoNum);
+  } else {
+    ASSERT (0);
+  }
+  MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr));
+}
+
+STATIC
+UINT32
+Handshake (
+  IN UINT32              Reg,
+  IN UINT32              Mask,
+  IN UINT32              Done
+  )
+{
+  UINT32                 Timeout = 100000;
+
+  do {
+    if ((MmioRead32 (Reg) & Mask) == Done) {
+      return 1;
+    }
+    MicroSecondDelay (1);
+  } while (Timeout-- > 0);
+  return 0;
+}
+
+STATIC
+VOID
+DwUsb3FillDesc (
+  IN usb3_dma_desc_t     *desc,
+  IN UINT64              dma_addr,
+  IN UINT32              dma_len,
+  IN UINT32              stream,
+  IN UINT32              type,
+  IN UINT32              ctrlbits,
+  IN UINT32              own
+  )
+{
+  desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF);
+  desc->bpth = (UINT32)(dma_addr >> 32);
+  desc->status = DSCSTS_XFERCNT (dma_len);
+  if (type) {
+    desc->control = DSCCTL_TRBCTL (type);
+  }
+  desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits;
+  ArmDataSynchronizationBarrier ();
+  /* must execute this operation at last */
+  if (own) {
+    desc->control |= DSCCTL_HWO;
+  }
+  ArmDataSynchronizationBarrier ();
+}
+
+STATIC
+VOID
+DwUsb3DepStartNewCfg (
+  IN UINT32              EpIdx,
+  IN UINT32              RsrcIdx
+  )
+{
+  /* start the command */
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | \
+    DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+STATIC
+VOID
+DwUsb3DepCfg (
+  IN UINT32              EpIdx,
+  IN UINT32              DepCfg0,
+  IN UINT32              DepCfg1,
+  IN UINT32              DepCfg2
+  )
+{
+  MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2);
+  MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1);
+  MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0);
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+STATIC
+VOID
+DwUsb3DepXferCfg (
+  IN UINT32              EpIdx,
+  IN UINT32              DepStrmCfg
+  )
+{
+  MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg);
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+STATIC
+UINT8
+DwUsb3DepStartXfer (
+  IN UINT32              EpIdx,
+  IN UINT64              DmaAddr,
+  IN UINT32              StreamOrUf
+  )
+{
+  UINT32                 Data;
+
+  MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr);
+  MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32));
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | \
+    DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+  Data = MmioRead32 (DEPCMD (EpIdx));
+  return GET_DEPCMD_XFER_RSRC_IDX(Data);
+}
+
+STATIC
+VOID
+DwUsb3DepStopXfer (
+  IN UINT32               EpIdx,
+  IN UINT32               Tri
+  )
+{
+  MmioWrite32 (DEPCMDPAR2 (EpIdx), 0);
+  MmioWrite32 (DEPCMDPAR1 (EpIdx), 0);
+  MmioWrite32 (DEPCMDPAR0 (EpIdx), 0);
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | \
+    DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+VOID
+DwUsb3DepUpdateXfer (
+  IN UINT32               EpIdx,
+  IN UINT32               Tri
+  )
+{
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | \
+    DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+STATIC
+VOID
+DwUsb3DepClearStall (
+  IN UINTN            EpIdx
+  )
+{
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+
+STATIC
+VOID
+DwUsb3DepSetStall (
+  IN UINTN            EpIdx
+  )
+{
+  MmioWrite32 (
+    DEPCMD (EpIdx),
+    DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT
+    );
+  Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
+}
+
+STATIC
+VOID
+DwUsb3EnableEp (
+  IN UINT32                EpIdx,
+  IN usb3_pcd_ep_t         *ep
+  )
+{
+  UINT32                   Dalepena;
+
+  Dalepena = MmioRead32 (DALEPENA);
+  /* If the EP is already enabled, skip to set it again. */
+  if (Dalepena & (1 << EpIdx)) {
+    return;
+  }
+  Dalepena |= 1 << EpIdx;
+  MmioWrite32 (DALEPENA, Dalepena);
+}
+
+STATIC
+VOID
+DwUsb3Ep0Activate (
+  IN OUT usb3_pcd_t         *pcd
+  )
+{
+  /* issue DEPCFG command to EP0 OUT */
+  DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0);
+  DwUsb3DepCfg (
+    EP_OUT_IDX (0),
+    EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512),
+    EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY,
+    0
+    );
+  /* issue DEPSTRMCFG command to EP0 OUT */
+  DwUsb3DepXferCfg (EP_OUT_IDX (0), 1);  // one stream
+  /* issue DEPCFG command to EP0 IN */
+  DwUsb3DepCfg (
+    EP_IN_IDX (0),
+    EPCFG0_EPTYPE (EPTYPE_CONTROL)  | EPCFG0_MPS (512) | \
+    EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num),
+    EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN,
+    0
+    );
+  /* issue DEPSTRMCFG command to EP0 IN */
+  DwUsb3DepXferCfg (EP_IN_IDX (0), 1);  // one stream
+  pcd->ep0.active = 1;
+}
+
+STATIC
+VOID
+DwUsb3EpActivate (
+  IN OUT usb3_pcd_t         *pcd,
+  IN OUT usb3_pcd_ep_t      *ep
+  )
+{
+  UINT32                    EpIdx, DepCfg0, DepCfg1;
+  if (ep->is_in) {
+    EpIdx = EP_IN_IDX (ep->num);
+  } else {
+    EpIdx = EP_OUT_IDX (ep->num);
+  }
+
+  /* Start a new configurate when enable the first EP. */
+  if (!pcd->eps_enabled) {
+    pcd->eps_enabled = 1;
+    /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first.
+     * It resets the core's Tx FIFO mapping table.
+     */
+    DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL);
+    DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);
+    DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN;
+
+    switch (pcd->speed) {
+    case USB_SPEED_SUPER:
+      DepCfg0 |= EPCFG0_MPS (512);
+      break;
+    case USB_SPEED_HIGH:
+    case USB_SPEED_FULL:
+      DepCfg0 |= EPCFG0_MPS (64);
+      break;
+    case USB_SPEED_LOW:
+      DepCfg0 |= EPCFG0_MPS (8);
+      break;
+    default:
+      ASSERT (0);
+      break;
+    }
+    DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0);
+    DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2);
+  }
+  /* issue DEPCFG command to EP */
+  DepCfg0 = EPCFG0_EPTYPE (ep->type);
+  DepCfg0 |= EPCFG0_MPS (ep->maxpacket);
+  if (ep->is_in) {
+    DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num);
+  }
+  DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst);
+  DepCfg1 = EPCFG1_EP_NUM (ep->num);
+  if (ep->is_in) {
+    DepCfg1 |= EPCFG1_EP_DIR_IN;
+  } else {
+    DepCfg1 |= EPCFG1_XFER_CMPL;
+  }
+  DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0);
+  /* issue DEPSTRMCFG command to EP */
+  DwUsb3DepXferCfg (EpIdx, 1);
+  DwUsb3EnableEp (EpIdx, ep);
+  ep->active = 1;
+}
+
+STATIC
+VOID
+DwUsb3Ep0OutStart (
+  IN usb3_pcd_t          *pcd
+  )
+{
+  usb3_dma_desc_t        *desc;
+
+  /* Get the SETUP packet DMA Descriptor (TRB) */
+  desc = pcd->ep0_setup_desc;
+
+  /* DMA Descriptor setup */
+  DwUsb3FillDesc (
+    desc,
+    (UINT64)gEndPoint0SetupPacket,
+    pcd->ep0.maxpacket,
+    0,
+    TRBCTL_SETUP,
+    DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
+    1
+    );
+
+  /* issue DEPSTRTXFER command to EP0 OUT */
+  pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0);
+}
+
+STATIC
+VOID
+DwUsb3Init (
+  VOID
+  )
+{
+  UINT32                 Data, Addr;
+  usb3_pcd_t             *pcd = &gPcd;
+
+  /* soft reset the usb core */
+  do {
+    MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST);
+
+    do {
+      MicroSecondDelay (1000);
+      Data = MmioRead32 (DCTL);
+    } while (Data & DCTL_CSFTRST);
+    //
+    // wait for at least 3 PHY clocks
+    //
+    MicroSecondDelay (1000);
+  } while (0);
+
+  pcd->link_state = 0;
+
+  /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */
+  MmioAndThenOr32 (
+    GUSB2PHYCFG (0),
+    ~GUSB2PHYCFG_USBTRDTIM_MASK,
+    GUSB2PHYCFG_USBTRDTIM (9)
+    );
+
+  /* set TX FIFO size */
+  Addr = TX_FIFO_ADDR;
+  DwUsb3SetFifoSize (Addr, RAM_TX0_DEPTH / RAM_WIDTH, FIFO_DIR_TX, 0);
+  Addr += RAM_TX0_DEPTH / RAM_WIDTH;
+  DwUsb3SetFifoSize (Addr, RAM_TX1_DEPTH / RAM_WIDTH, FIFO_DIR_TX, 1);
+  /* set RX FIFO size */
+  DwUsb3SetFifoSize (RX_FIFO_ADDR, RAM_RX_DEPTH / RAM_WIDTH, FIFO_DIR_RX, 0);
+
+  /* set LFPS filter delay1trans */
+  MmioAndThenOr32 (
+    GUSB3PIPECTL (0),
+    ~PIPECTL_DELAYP1TRANS,
+    PIPECTL_LFPS_FILTER | PIPECTL_TX_DEMPH (1)
+    );
+
+  /* set GCTL */
+  Data = GCTL_U2EXIT_LFPS | GCTL_PRTCAPDIR_DEVICE | GCTL_U2RSTECN |
+         GCTL_PWRDNSCALE(2);
+  MmioWrite32 (GCTL, Data);
+
+  /* init event buf */
+  MmioWrite32 (GEVNTADRL(0), (UINT32)(UINTN)gEventBuf);
+  MmioWrite32 (GEVNTADRH(0), (UINTN)gEventBuf >> 32);
+  MmioWrite32 (GEVNTSIZ(0), DWUSB3_EVENT_BUF_SIZE << 2);
+  MmioWrite32 (GEVNTCOUNT(0), 0);
+
+  /* set max speed to super speed */
+  MmioAndThenOr32 (
+    DCFG,
+    ~DCFG_DEVSPD_MASK,
+    DCFG_DEVSPD (DEVSPD_SS_PHY_125MHZ_OR_250MHZ)
+    );
+
+  /* set nump */
+  MmioAndThenOr32 (DCFG, ~DCFG_NUMP_MASK, DCFG_NUMP (16));
+
+  /* init address */
+  SET_DEVADDR (0);
+
+  /* disable phy suspend */
+  MmioAnd32 (GUSB3PIPECTL (0), ~PIPECTL_SUSPEND_EN);
+  MmioAnd32 (GUSB2PHYCFG (0), ~GUSB2PHYCFG_SUSPHY);
+
+  /* clear any pending interrupts */
+  Data = MmioRead32 (GEVNTCOUNT (0));
+  MmioWrite32 (GEVNTCOUNT (0), Data);
+  /* enable device interrupts */
+  MmioWrite32 (DEVTEN, DEVTEN_CONNECTDONEEN | DEVTEN_USBRSTEN);
+  /* activate EP0 */
+  DwUsb3Ep0Activate (pcd);
+  /* start EP0 to receive SETUP packets */
+  DwUsb3Ep0OutStart (pcd);
+
+  /* enable EP0 OUT/IN in DALEPENA */
+  MmioWrite32 (DALEPENA, (1 << EP_OUT_IDX (0)) | (1 << EP_IN_IDX (0)));
+
+  /* set RUN/STOP bit */
+  MmioOr32 (DCTL, DCTL_RUN_STOP);
+}
+
+STATIC
+VOID
+DriverInit (
+  VOID
+  )
+{
+  usb3_pcd_t          *pcd = &gPcd;
+  usb3_pcd_ep_t       *ep;
+  EFI_STATUS          Status;
+
+  pcd->speed = USB_SPEED_UNKNOWN;
+
+  //
+  // init EP0
+  //
+  ep = &pcd->ep0;
+  ep->pcd = pcd;
+  ep->stopped = 1;
+  ep->is_in = 0;
+  ep->active = 0;
+  ep->phys = 0;
+  ep->num = 0;
+  ep->tx_fifo_num = 0;
+  ep->type = EPTYPE_CONTROL;
+  ep->maxburst = 0;
+  ep->maxpacket = USB3_MAX_EP0_SIZE;
+  ep->send_zlp = 0;
+  ep->req.length = 0;
+  ep->req.actual = 0;
+  pcd->ep0_req.length = 0;
+  pcd->ep0_req.actual = 0;
+
+  //
+  // init EP1 OUT
+  //
+  ep = &pcd->out_ep;
+  ep->pcd = pcd;
+  ep->stopped = 1;
+  ep->is_in = 0;
+  ep->active = 0;
+  ep->phys = USB3_BULK_OUT_EP << 1;
+  ep->num = 1;
+  ep->tx_fifo_num = 0;
+  //
+  // bulk ep is activated
+  //
+  ep->type = EPTYPE_BULK;
+  ep->maxburst = 0;
+  ep->maxpacket = USB3_MAX_PACKET_SIZE;
+  ep->send_zlp = 0;
+  ep->req.length = 0;
+  ep->req.actual = 0;
+
+  //
+  // init EP1 IN
+  //
+  ep = &pcd->in_ep;
+  ep->stopped = 1;
+  ep->is_in = 1;
+  ep->active = 0;
+  ep->phys = (USB3_BULK_IN_EP << 1) | 1;
+  ep->num = 1;
+  ep->tx_fifo_num = USB3_BULK_IN_EP;
+  //
+  // bulk ep is activated
+  //
+  ep->type = EPTYPE_BULK;
+  ep->maxburst = 0;
+  ep->maxpacket = USB3_MAX_PACKET_SIZE;
+  ep->send_zlp = 0;
+  ep->req.length = 0;
+  ep->req.actual = 0;
+
+  pcd->ep0state = EP0_IDLE;
+  pcd->ep0.maxpacket = USB3_MAX_EP0_SIZE;
+  pcd->ep0.type = EPTYPE_CONTROL;
+
+  Status = DmaAllocateBuffer (
+             EfiBootServicesData,
+             EFI_SIZE_TO_PAGES (sizeof (usb3_dma_desc_t) * 5),
+             (VOID *)&pcd->ep0_setup_desc
+             );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+  pcd->ep0_in_desc = pcd->ep0_setup_desc++;
+  pcd->ep0_out_desc = pcd->ep0_in_desc++;
+  pcd->in_ep.ep_desc = pcd->ep0_out_desc++;
+  pcd->out_ep.ep_desc = pcd->in_ep.ep_desc++;
+}
+
+STATIC
+VOID
+DwUsb3HandleUsbResetInterrupt (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb3_pcd_ep_t        *ep;
+
+  //
+  // clear stall on each EP
+  //
+  ep = &pcd->in_ep;
+  if (ep->xfer_started) {
+    if (ep->is_in) {
+      DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in);
+    } else {
+      DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out);
+    }
+  }
+  if (ep->stopped) {
+    if (ep->is_in) {
+      DwUsb3DepClearStall (EP_IN_IDX (ep->num));
+    } else {
+      DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
+    }
+  }
+
+  ep = &pcd->out_ep;
+  if (ep->xfer_started) {
+    if (ep->is_in) {
+      DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in);
+    } else {
+      DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out);
+    }
+  }
+  if (ep->stopped) {
+    if (ep->is_in) {
+      DwUsb3DepClearStall (EP_IN_IDX (ep->num));
+    } else {
+      DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
+    }
+  }
+
+  //
+  // set device address to 0
+  //
+  SET_DEVADDR (0);
+
+  pcd->ltm_enable = 0;
+  DEBUG ((DEBUG_INFO, "usb reset\n"));
+}
+
+STATIC
+UINT32
+DwUsb3GetDeviceSpeed (
+  IN usb3_pcd_t         *pcd
+  )
+{
+  UINT32                Data, Speed;
+
+  Data = MmioRead32 (DSTS);
+  switch (DSTS_GET_DEVSPD (Data)) {
+  case DEVSPD_HS_PHY_30MHZ_OR_60MHZ:
+    Speed = USB_SPEED_HIGH;
+    break;
+  case DEVSPD_FS_PHY_30MHZ_OR_60MHZ:
+  case DEVSPD_FS_PHY_48MHZ:
+    Speed = USB_SPEED_FULL;
+    break;
+  case DEVSPD_LS_PHY_6MHZ:
+    Speed = USB_SPEED_LOW;
+    break;
+  case DEVSPD_SS_PHY_125MHZ_OR_250MHZ:
+    Speed = USB_SPEED_SUPER;
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR, "DwUsb3GetDeviceSpeed: invalid DSTS:0x%x\n", Data));
+    Speed = USB_SPEED_UNKNOWN;
+    break;
+  }
+  return Speed;
+}
+
+STATIC
+VOID
+DwUsb3PcdSetSpeed (
+  IN usb3_pcd_t         *pcd,
+  IN UINTN              speed
+  )
+{
+  //
+  // set the MPS of EP0 based on the connection speed
+  //
+  switch (speed) {
+  case USB_SPEED_SUPER:
+    pcd->ep0.maxpacket = 512;
+    pcd->in_ep.maxpacket = USB3_MAX_PACKET_SIZE;
+    pcd->out_ep.maxpacket = USB3_MAX_PACKET_SIZE;
+    break;
+  case USB_SPEED_HIGH:
+    pcd->ep0.maxpacket = 64;
+    pcd->in_ep.maxpacket = USB2_HS_MAX_PACKET_SIZE;
+    pcd->out_ep.maxpacket = USB2_HS_MAX_PACKET_SIZE;
+    break;
+  case USB_SPEED_FULL:
+    pcd->ep0.maxpacket = 64;
+    pcd->in_ep.maxpacket = USB2_FS_MAX_PACKET_SIZE;
+    pcd->out_ep.maxpacket = USB2_FS_MAX_PACKET_SIZE;
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR, "invalid speed: %d\n", speed));
+    break;
+  }
+}
+
+STATIC
+VOID
+DwUsb3HandleConnectDoneInterrupt (
+  IN usb3_pcd_t         *pcd
+  )
+{
+  usb3_pcd_ep_t         *ep0 = &pcd->ep0;
+  UINT32                DiepCfg0, DoepCfg0, DiepCfg1, DoepCfg1;
+  UINT32                Speed;
+
+  ep0->stopped = 0;
+  Speed = (UINT32)DwUsb3GetDeviceSpeed (pcd);
+  pcd->speed = (UINT8)Speed;
+
+  DwUsb3PcdSetSpeed (pcd, Speed);
+  //
+  // set the MPS of EP0 based on the connection speed
+  //
+  DiepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL) |        \
+             EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);
+  DiepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY |   \
+             EPCFG1_EP_DIR_IN;
+  DoepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL) |        \
+             EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);
+  DoepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY;
+
+  switch (Speed) {
+  case USB_SPEED_SUPER:
+    DiepCfg0 |= EPCFG0_MPS (512);
+    DoepCfg0 |= EPCFG0_MPS (512);
+    break;
+  case USB_SPEED_HIGH:
+  case USB_SPEED_FULL:
+    DiepCfg0 |= EPCFG0_MPS (64);
+    DoepCfg0 |= EPCFG0_MPS (64);
+    break;
+  case USB_SPEED_LOW:
+    DiepCfg0 |= EPCFG0_MPS (8);
+    DoepCfg0 |= EPCFG0_MPS (8);
+    break;
+  default:
+    DEBUG ((
+      DEBUG_ERROR,
+      "DwUsb3HandleConnectDoneInterrupt: invalid speed %d\n",
+      Speed
+      ));
+    break;
+  }
+  DiepCfg0 |= EPCFG0_TXFNUM (ep0->tx_fifo_num);
+  //
+  // issue DEPCFG command to EP0 OUT
+  //
+  DwUsb3DepCfg (EP_OUT_IDX (0), DoepCfg0, DoepCfg1, 0);
+  //
+  // issue DEPCFG command to EP0 IN
+  //
+  DwUsb3DepCfg (EP_IN_IDX (0), DiepCfg0, DiepCfg1, 0);
+  pcd->state = USB3_STATE_DEFAULT;
+}
+
+STATIC
+VOID
+DwUsb3HandleDeviceInterrupt (
+  IN usb3_pcd_t       *pcd,
+  IN UINT32           Event
+  )
+{
+  switch (Event & GEVNT_DEVT_MASK) {
+  case GEVNT_DEVT_USBRESET:
+    DwUsb3HandleUsbResetInterrupt (pcd);
+    break;
+  case GEVNT_DEVT_CONNDONE:
+    DwUsb3HandleConnectDoneInterrupt (pcd);
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR, "DwUsb3HandleDeviceInterrupt: invalid event\n"));
+    break;
+  }
+}
+
+STATIC
+usb3_pcd_ep_t *
+DwUsb3GetOutEndPoint (
+  IN usb3_pcd_t       *pcd,
+  IN UINT32           EndPointNum
+  )
+{
+  if (EndPointNum == 0) {
+    return &pcd->ep0;
+  }
+  return &pcd->out_ep;
+}
+
+STATIC
+usb3_pcd_ep_t *
+DwUsb3GetInEndPoint (
+  IN usb3_pcd_t       *pcd,
+  IN UINT32           EndPointNum
+  )
+{
+  if (EndPointNum == 0) {
+    return &pcd->ep0;
+  }
+  return &pcd->in_ep;
+}
+
+STATIC
+VOID
+EndPoint0DoStall (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb3_pcd_ep_t       *ep0 = &pcd->ep0;
+
+  //
+  // stall EP0 IN & OUT simultanelusly
+  //
+  ep0->is_in = 1;
+  DwUsb3DepSetStall (EP_IN_IDX (0));
+  ep0->is_in = 0;
+  DwUsb3DepSetStall (EP_OUT_IDX (0));
+  //
+  // prepare for the next setup transfer
+  //
+  ep0->stopped = 1;
+  pcd->ep0state = EP0_IDLE;
+  DwUsb3Ep0OutStart (pcd);
+}
+
+STATIC
+VOID
+EndPoint0ContinueTransfer (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_req_t   *req
+  )
+{
+  usb3_pcd_ep_t       *ep0 = &pcd->ep0;
+  usb3_dma_desc_t     *desc;
+  UINT64              desc_dma;
+  UINT8               tri;
+
+  //
+  // send a 0-byte length packet after the end of transfer
+  //
+  if (ep0->is_in) {
+    desc = pcd->ep0_in_desc;
+    desc_dma = (UINT64)pcd->ep0_in_desc;
+    //
+    // DMA descriptor setup
+    //
+    DwUsb3FillDesc (
+      desc,
+      (UINT64)req->bufdma,
+      0,
+      0,
+      TRBCTL_NORMAL,
+      DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
+      1
+      );
+    tri = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0);
+    ep0->tri_in = tri;
+  }
+}
+
+STATIC
+VOID
+EndPoint0CompleteRequest (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_req_t   *req,
+  IN usb3_dma_desc_t  *desc
+  )
+{
+  usb3_pcd_ep_t      *ep = &pcd->ep0;
+
+  if (req == NULL) {
+    return;
+  }
+
+  if ((pcd->ep0state == EP0_OUT_DATA_PHASE) ||
+      (pcd->ep0state == EP0_IN_DATA_PHASE)) {
+    if (ep->is_in) {
+      if (GET_DSCSTS_XFERCNT (desc->status) == 0) {
+        pcd->ep0.is_in = 0;
+        pcd->ep0state = EP0_OUT_WAIT_NRDY;
+      }
+    } else {
+      pcd->ep0.is_in = 1;
+      pcd->ep0state = EP0_IN_WAIT_NRDY;
+    }
+  }
+}
+
+STATIC
+VOID
+DwUsb3OsGetTrb (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_ep_t    *ep,
+  IN usb3_pcd_req_t   *req
+  )
+{
+  //
+  // If EP0, fill request with EP0 IN/OUT data TRB
+  //
+  if (ep == &pcd->ep0) {
+    if (ep->is_in) {
+      req->trb = pcd->ep0_in_desc;
+      req->trbdma = (UINT64)pcd->ep0_in_desc;
+    } else {
+      req->trb = pcd->ep0_out_desc;
+      req->trbdma = (UINT64)pcd->ep0_out_desc;
+    }
+  } else {
+    //
+    // fill request with TRB from the non-EP0 allocation
+    //
+    req->trb = ep->ep_desc;
+    req->trbdma = (UINT64)ep->ep_desc;
+  }
+}
+
+STATIC
+VOID
+DwUsb3EndPoint0StartTransfer (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_req_t   *req
+  )
+{
+  usb3_pcd_ep_t       *ep0 = &pcd->ep0;
+  usb3_dma_desc_t     *desc;
+  UINT64              desc_dma;
+  UINT32              desc_type, len;
+
+  //
+  // get the DMA descriptor (TRB) for this request
+  //
+  DwUsb3OsGetTrb (pcd, ep0, req);
+  desc = req->trb;
+  desc_dma = req->trbdma;
+
+  if (ep0->is_in) {
+    //
+    // start DMA on EP0 IN
+    // DMA Descriptor (TRB) setup
+    //
+    len = req->length;
+    if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
+      if (ep0->three_stage) {
+        desc_type = TRBCTL_STATUS_3;
+      } else {
+        desc_type = TRBCTL_STATUS_2;
+      }
+    } else {
+      desc_type = TRBCTL_CTLDATA_1ST;
+    }
+    DwUsb3FillDesc (
+      desc,
+      (UINT64)req->bufdma,
+      len,
+      0,
+      desc_type,
+      DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
+      1
+      );
+    //
+    // issue DEPSTRTXFER command to EP0 IN
+    //
+    ep0->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0);
+  } else {
+    //
+    // start DMA on EP0 OUT
+    // DMA Descriptor (TRB) setup
+    //
+    len = ALIGN (req->length, ep0->maxpacket);
+    if (pcd->ep0state == EP0_OUT_STATUS_PHASE) {
+      if (ep0->three_stage) {
+        desc_type = TRBCTL_STATUS_3;
+      } else {
+        desc_type = TRBCTL_STATUS_2;
+      }
+    } else {
+      desc_type = TRBCTL_CTLDATA_1ST;
+    }
+    DwUsb3FillDesc (
+      desc,
+      (UINT64)req->bufdma,
+      len,
+      0,
+      desc_type,
+      DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
+      1
+      );
+    //
+    // issue DEPSTRTXFER command to EP0 OUT
+    //
+    ep0->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), desc_dma, 0);
+  }
+}
+
+STATIC
+INTN
+DwUsb3EndPointXStartTransfer (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_ep_t    *ep
+  )
+{
+  usb3_pcd_req_t      *req = &ep->req;
+  usb3_dma_desc_t     *desc;
+  UINT64              desc_dma;
+  UINT32              len;
+
+  //
+  // get the TRB for this request
+  //
+  DwUsb3OsGetTrb (pcd, ep, req);
+  desc = req->trb;
+  desc_dma = req->trbdma;
+
+  if (ep->is_in) {
+    //
+    // For IN, TRB length is just xfer length
+    //
+    len = req->length;
+    if (ep->xfer_started && !(desc->control & DSCCTL_HWO)) {
+      DEBUG ((DEBUG_INFO, "[%a] last tx succ, but not in 10s!\n", __func__));
+      ep->xfer_started = 0;
+    }
+  } else {
+    //
+    // For OUT, TRB length must be multiple of maxpacket
+    // must be power of 2, use cheap AND
+    //
+    len = (req->length + ep->maxpacket - 1) & ~(ep->maxpacket - 1);
+    req->length = len;
+  }
+  //
+  // DMA descriptor setup
+  //
+  DwUsb3FillDesc (
+    desc,
+    (UINT64)req->bufdma,
+    len,
+    0,
+    TRBCTL_NORMAL,
+    DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
+    1
+    );
+  if (ep->is_in) {
+    //
+    // start DMA on EPn IN
+    //
+    if (ep->xfer_started) {
+      //
+      // issue DEPUPDTXFER command to EP
+      //
+      DwUsb3DepUpdateXfer (EP_IN_IDX (ep->num), ep->tri_in);
+    } else {
+      ep->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (ep->num), desc_dma, 0);
+      ep->xfer_started = 1;
+    }
+  } else {
+    //
+    // start DMA on EPn OUT
+    //
+    if (ep->xfer_started) {
+      //
+      // issue DEPUPDTXFER command to EP
+      //
+      DwUsb3DepUpdateXfer (EP_OUT_IDX (ep->num), ep->tri_out);
+    } else {
+      ep->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (ep->num), desc_dma, 0);
+      ep->xfer_started = 1;
+    }
+  }
+  if (ep->is_in) {
+    UINT32       count = 0;
+    //
+    // wait until send complete
+    //
+    while ((desc->control & DSCCTL_HWO) && (count < 1000000)) {
+      MicroSecondDelay (10);
+      count++;
+    }
+    if (count >= 1000000) {
+      DEBUG ((DEBUG_INFO, "[%a]: ep%d transfer timeout!\n", __func__, ep->num));
+      DEBUG ((
+        DEBUG_INFO,
+        "please disconnect then connect USB cable again to recovery!\n"
+        ));
+      return -1;
+    }
+    ep->xfer_started = 0;
+  }
+  return 0;
+}
+
+STATIC
+VOID
+SetupInStatusPhase (
+  IN usb3_pcd_t       *pcd,
+  IN VOID             *buf
+  )
+{
+  usb3_pcd_ep_t       *ep0 = &pcd->ep0;
+
+  if (pcd->ep0state == EP0_STALL)
+    return;
+
+  ep0->is_in = 1;
+  pcd->ep0state = EP0_IN_STATUS_PHASE;
+  pcd->ep0_req.bufdma = buf;
+  pcd->ep0_req.length = 0;
+  pcd->ep0_req.actual = 0;
+  DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
+}
+
+STATIC
+VOID
+SetupOutStatusPhase (
+  IN usb3_pcd_t       *pcd,
+  IN VOID             *buf
+  )
+{
+  usb3_pcd_ep_t       *ep0 = &pcd->ep0;
+
+  if (pcd->ep0state == EP0_STALL)
+    return;
+
+  ep0->is_in = 0;
+  pcd->ep0state = EP0_OUT_STATUS_PHASE;
+  pcd->ep0_req.bufdma = buf;
+  pcd->ep0_req.length = 0;
+  pcd->ep0_req.actual = 0;
+  DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
+}
+
+STATIC
+VOID
+DwUsb3HandleEndPoint0 (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_req_t   *req,
+  IN UINT32           event
+  )
+{
+  usb3_pcd_ep_t       *ep0 = &pcd->ep0;
+  usb3_dma_desc_t     *desc = NULL;
+  UINT32              byte_count, len;
+
+  switch (pcd->ep0state) {
+  case EP0_IN_DATA_PHASE:
+    if (req == NULL) {
+      req = &pcd->ep0_req;
+    }
+    desc = pcd->ep0_in_desc;
+
+    if (desc->control & DSCCTL_HWO) {
+      goto out;
+    }
+
+    if (GET_DSCSTS_TRBRSP (desc->status) == TRBRSP_SETUP_PEND) {
+      //
+      // start of a new control transfer
+      //
+      desc->status = 0;
+    }
+    byte_count = req->length - GET_DSCSTS_XFERCNT (desc->status);
+    req->actual += byte_count;
+    req->bufdma += byte_count;
+
+    if (req->actual < req->length) {
+      //
+      // IN CONTINUE, stall EP0
+      //
+      EndPoint0DoStall (pcd);
+    } else if (ep0->send_zlp) {
+      //
+      // CONTINUE TRANSFER IN ZLP
+      //
+      EndPoint0ContinueTransfer (pcd, req);
+      ep0->send_zlp = 0;
+    } else {
+      //
+      // COMPLETE IN TRANSFER
+      //
+      EndPoint0CompleteRequest (pcd, req, desc);
+    }
+    break;
+  case EP0_OUT_DATA_PHASE:
+    if (req == NULL) {
+      req = &pcd->ep0_req;
+    }
+    desc = pcd->ep0_out_desc;
+
+    if (desc->control & DSCCTL_HWO) {
+      goto out;
+    }
+
+    if (GET_DSCSTS_TRBRSP (desc->status) == TRBRSP_SETUP_PEND) {
+      //
+      // start of a new control transfer
+      //
+      desc->status = 0;
+    }
+    len = (req->length + ep0->maxpacket - 1) & ~(ep0->maxpacket - 1);
+    byte_count = len - GET_DSCSTS_XFERCNT (desc->status);
+    req->actual += byte_count;
+    req->bufdma += byte_count;
+
+    if (req->actual < req->length) {
+      //
+      // IN CONTINUE, stall EP0
+      //
+      EndPoint0DoStall (pcd);
+    } else if (ep0->send_zlp) {
+      //
+      // CONTINUE TRANSFER IN ZLP
+      //
+      EndPoint0ContinueTransfer (pcd, req);
+      ep0->send_zlp = 0;
+    } else {
+      //
+      // COMPLETE IN TRANSFER
+      //
+      EndPoint0CompleteRequest (pcd, req, desc);
+    }
+    break;
+  case EP0_IN_WAIT_NRDY:
+    if (ep0->is_in) {
+      SetupInStatusPhase (pcd, gEndPoint0SetupPacket);
+    } else {
+      ASSERT (0);
+    }
+    break;
+  case EP0_OUT_WAIT_NRDY:
+    if (!ep0->is_in) {
+      SetupOutStatusPhase (pcd, gEndPoint0SetupPacket);
+    } else {
+      ASSERT (0);
+    }
+    break;
+  case EP0_IN_STATUS_PHASE:
+    if (ep0->is_in) {
+      desc = pcd->ep0_in_desc;
+    } else {
+      ASSERT (0);
+    }
+    EndPoint0CompleteRequest (pcd, req, desc);
+    pcd->ep0state = EP0_IDLE;
+    ep0->stopped = 1;
+    ep0->is_in = 0;  // OUT for next SETUP
+    //
+    // prepare for more SETUP packets
+    //
+    DwUsb3Ep0OutStart (pcd);
+    break;
+  case EP0_OUT_STATUS_PHASE:
+    if (!ep0->is_in) {
+      desc = pcd->ep0_out_desc;
+    } else {
+      ASSERT (0);
+    }
+    EndPoint0CompleteRequest (pcd, req, desc);
+    pcd->ep0state = EP0_IDLE;
+    ep0->stopped = 1;
+    ep0->is_in = 0;  // OUT for next SETUP
+    //
+    // prepare for more SETUP packets
+    //
+    DwUsb3Ep0OutStart (pcd);
+    break;
+  case EP0_STALL:
+    break;
+  case EP0_IDLE:
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR, "%a: invalid state %d\n", __func__, pcd->ep0state));
+    break;
+  }
+out:
+  return;
+}
+
+STATIC
+usb3_pcd_ep_t *
+Addr2EndPoint (
+  IN usb3_pcd_t       *pcd,
+  IN UINT16           index
+  )
+{
+  UINT32              ep_num;
+
+  ep_num = UE_GET_ADDR (index);
+  if (ep_num == 0) {
+    return &pcd->ep0;
+  } else {
+    if (UE_GET_DIR (index) == UE_DIR_IN) {
+      return &pcd->in_ep;
+    }
+    return &pcd->out_ep;
+  }
+}
+
+STATIC
+VOID
+DwUsb3DoGetStatus (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t   *ctrl = &gEndPoint0SetupPacket->req;
+  UINT8                  *status = gEndPoint0StatusBuf;
+  usb3_pcd_ep_t          *ep;
+
+  if (ctrl->wLength != 2) {
+    EndPoint0DoStall (pcd);
+    return;
+  }
+
+  switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) {
+  case UT_DEVICE:
+    *status = 0;   // bus powered
+    if (pcd->speed == USB_SPEED_SUPER) {
+      if (pcd->state == USB3_STATE_CONFIGURED) {
+        if (MmioRead32 (DCTL) & DCTL_INIT_U1_EN) {
+          *status |= 1 << 2;
+        }
+        if (MmioRead32 (DCTL) & DCTL_INIT_U2_EN) {
+          *status |= 1 << 3;
+        }
+        *status |= (UINT8)(pcd->ltm_enable << 4);
+      }
+    }
+    *(status + 1) = 0;
+    break;
+  case UT_INTERFACE:
+    *status = 0;
+    *(status + 1) = 0;
+    break;
+  case UT_ENDPOINT:
+    ep = Addr2EndPoint (pcd, ctrl->wIndex);
+    *status = ep->stopped;
+    *(status + 1) = 0;
+    break;
+  default:
+    EndPoint0DoStall (pcd);
+    return;
+  }
+  pcd->ep0_req.bufdma = (UINT64 *)status;
+  pcd->ep0_req.length = 2;
+  pcd->ep0_req.actual = 0;
+  DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
+}
+
+STATIC
+VOID
+DoClearHalt (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_ep_t    *ep
+  )
+{
+  if (ep->is_in) {
+    DwUsb3DepClearStall (EP_IN_IDX (ep->num));
+  } else {
+    DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
+  }
+  if (ep->stopped) {
+    ep->stopped = 0;
+  }
+}
+
+STATIC
+VOID
+Usb3PcdEpEnable (
+  IN usb3_pcd_t        *pcd,
+  IN usb3_pcd_ep_t     *ep
+  )
+{
+  //
+  // activate the EP
+  //
+  ep->stopped = 0;
+  ep->xfer_started = 0;
+  ep->ep_desc->control = 0;
+  ep->ep_desc->status = 0;
+  //
+  // set initial data pid.
+  //
+  if (ep->type == EPTYPE_BULK) {
+    ep->data_pid_start = 0;
+  }
+  DwUsb3EpActivate (pcd, ep);
+}
+
+STATIC
+VOID
+DwUsb3DoClearFeature (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
+  usb3_pcd_ep_t  *ep;
+
+  switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) {
+  case UT_DEVICE:
+    switch (ctrl->wValue) {
+    case UF_U1_ENABLE:
+      if ((pcd->speed != USB_SPEED_SUPER) ||
+          (pcd->state != USB3_STATE_CONFIGURED)) {
+        EndPoint0DoStall (pcd);
+        return;
+      }
+      MmioAnd32 (DCTL, ~DCTL_INIT_U1_EN);
+      break;
+    case UF_U2_ENABLE:
+      if ((pcd->speed != USB_SPEED_SUPER) ||
+          (pcd->state != USB3_STATE_CONFIGURED)) {
+        EndPoint0DoStall (pcd);
+        return;
+      }
+      MmioAnd32 (DCTL, ~DCTL_INIT_U2_EN);
+      break;
+    case UF_LTM_ENABLE:
+      if ((pcd->speed != USB_SPEED_SUPER) ||
+          (pcd->state != USB3_STATE_CONFIGURED) ||
+          (ctrl->wIndex != 0)) {
+        EndPoint0DoStall (pcd);
+        return;
+      }
+      pcd->ltm_enable = 0;
+      break;
+    default:
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    break;
+  case UT_INTERFACE:
+    if (ctrl->wValue) {
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    break;
+  case UT_ENDPOINT:
+    ep = Addr2EndPoint (pcd, ctrl->wIndex);
+    if (ctrl->wValue != UF_ENDPOINT_HALT) {
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    DoClearHalt (pcd, ep);
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR, "invalid bmRequestType :%d\n", UT_GET_RECIPIENT (ctrl->bmRequestType)));
+    break;
+  }
+  pcd->ep0.is_in = 1;
+  pcd->ep0state = EP0_IN_WAIT_NRDY;
+}
+
+STATIC
+VOID
+DwUsb3DoSetFeature (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
+  usb3_pcd_ep_t  *ep;
+
+  switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) {
+  case UT_DEVICE:
+    switch (ctrl->wValue) {
+    case UF_DEVICE_REMOTE_WAKEUP:
+      break;
+    case UF_TEST_MODE:
+      pcd->test_mode_nr = ctrl->wIndex >> 8;
+      pcd->test_mode = 1;
+      break;
+    case UF_U1_ENABLE:
+      if ((pcd->speed != USB_SPEED_SUPER) ||
+          (pcd->state != USB3_STATE_CONFIGURED)) {
+        EndPoint0DoStall (pcd);
+        return;
+      }
+      MmioOr32 (DCTL, DCTL_INIT_U1_EN);
+      break;
+    case UF_U2_ENABLE:
+      if ((pcd->speed != USB_SPEED_SUPER) ||
+          (pcd->state != USB3_STATE_CONFIGURED)) {
+        EndPoint0DoStall (pcd);
+        return;
+      }
+      MmioOr32 (DCTL, DCTL_INIT_U2_EN);
+      break;
+    case UF_LTM_ENABLE:
+      if ((pcd->speed != USB_SPEED_SUPER) ||
+          (pcd->state != USB3_STATE_CONFIGURED) ||
+          (ctrl->wIndex != 0)) {
+        EndPoint0DoStall (pcd);
+        return;
+      }
+      pcd->ltm_enable = 1;
+      break;
+    default:
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    break;
+  case UT_INTERFACE:
+    if (ctrl->wValue) {
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    break;
+  case UT_ENDPOINT:
+    ep = Addr2EndPoint (pcd, ctrl->wIndex);
+    if (ctrl->wValue != UF_ENDPOINT_HALT) {
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    ep->stopped = 1;
+    if (ep->is_in) {
+      DwUsb3DepClearStall (EP_IN_IDX (ep->num));
+    } else {
+      DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
+    }
+    break;
+  default:
+    DEBUG ((DEBUG_ERROR, "invalid bmRequestType %d\n", UT_GET_RECIPIENT (ctrl->bmRequestType)));
+    break;
+  }
+  pcd->ep0.is_in = 1;
+  pcd->ep0state = EP0_IN_WAIT_NRDY;
+}
+
+STATIC
+VOID
+DwUsb3DoSetAddress (
+  IN usb3_pcd_t          *pcd
+  )
+{
+  usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req;
+
+  if (ctrl->bmRequestType == UT_DEVICE) {
+    SET_DEVADDR (ctrl->wValue);
+    pcd->ep0.is_in = 1;
+    pcd->ep0state = EP0_IN_WAIT_NRDY;
+    if (ctrl->wValue) {
+      pcd->state = USB3_STATE_ADDRESSED;
+    } else {
+      pcd->state = USB3_STATE_DEFAULT;
+    }
+  }
+}
+
+STATIC
+VOID
+DwUsb3DoGetConfig (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
+  UINT8  *status = gEndPoint0StatusBuf;
+
+  if (ctrl->bmRequestType != (UT_READ | UT_STANDARD | UT_DEVICE)) {
+    EndPoint0DoStall (pcd);
+    return;
+  }
+  //
+  // Notify host the current config value
+  //
+  *status = pcd->new_config;
+  pcd->ep0_req.bufdma = (UINT64 *)status;
+  pcd->ep0_req.length = 1;
+  pcd->ep0_req.actual = 0;
+  DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
+}
+
+STATIC
+VOID
+DwUsb3DoSetConfig (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
+  UINT16  wvalue = ctrl->wValue;
+  usb3_pcd_ep_t  *ep;
+
+  if (ctrl->bmRequestType != (UT_WRITE | UT_STANDARD | UT_DEVICE)) {
+    EndPoint0DoStall (pcd);
+    return;
+  }
+
+  if (!wvalue || (wvalue == CONFIG_VALUE)) {
+    pcd->new_config = (UINT8)wvalue;
+    //
+    // set new configuration
+    //
+    if (wvalue) {
+      //
+      // activate bulk in endpoint
+      //
+      ep = &pcd->in_ep;
+      Usb3PcdEpEnable (pcd, ep);
+      //
+      // activate bulk out endpoint
+      //
+      ep = &pcd->out_ep;
+      Usb3PcdEpEnable (pcd, ep);
+      pcd->state = USB3_STATE_CONFIGURED;
+      {
+        //
+        // prepare for EP1 OUT
+        //
+        usb3_pcd_ep_t                 *ep = &pcd->out_ep;
+        usb3_pcd_req_t                *req = &ep->req;
+
+        //
+        // AndroidFast App will free the rx buffer.
+        //
+        gRxBuf = AllocatePool (DATA_SIZE);
+        ASSERT (gRxBuf != NULL);
+        WriteBackDataCacheRange (gRxBuf, DATA_SIZE);
+        req->bufdma = (UINT64 *)gRxBuf;
+        if (mDataBufferSize == 0) {
+          req->length = CMD_SIZE;
+        } else if (mDataBufferSize > DATA_SIZE) {
+          req->length = DATA_SIZE;
+          mDataBufferSize = mDataBufferSize - DATA_SIZE;
+        } else if (mDataBufferSize > CMD_SIZE) {
+          req->length = CMD_SIZE;
+          mDataBufferSize = mDataBufferSize - CMD_SIZE;
+        } else {
+          req->length = mDataBufferSize;
+          mDataBufferSize = 0;
+        }
+        DwUsb3EndPointXStartTransfer (pcd, ep);
+      }
+    } else {
+      pcd->state = USB3_STATE_ADDRESSED;
+    }
+    pcd->ep0.is_in = 1;
+    pcd->ep0state = EP0_IN_WAIT_NRDY;
+  } else {
+    EndPoint0DoStall (pcd);
+  }
+}
+
+STATIC
+VOID
+DwUsb3DoGetDescriptor (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
+  UINT8                 dt = ctrl->wValue >> 8;
+  UINT8                 index = (UINT8)ctrl->wValue;
+  UINT16                len = ctrl->wLength;
+  UINT8                 *buf = gEndPoint0StatusBuf;
+  UINT16                value = 0;
+  EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;
+
+  if (ctrl->bmRequestType != (UT_READ | UT_STANDARD | UT_DEVICE)) {
+    EndPoint0DoStall (pcd);
+    return;
+  }
+
+  switch (dt) {
+  case UDESC_DEVICE:
+    {
+      struct usb_device_descriptor  *dev = &gDwUsb3DevDesc;
+      dev->bLength = sizeof (struct usb_device_descriptor);
+      dev->bDescriptorType = UDESC_DEVICE;
+      dev->bDeviceClass = 0;
+      dev->bDeviceSubClass = 0;
+      dev->bDeviceProtocol = 0;
+      if (pcd->speed == USB_SPEED_SUPER) {
+        dev->bcdUSB = 0x300;
+        //
+        // 2^9 = 512
+        //
+        dev->bMaxPacketSize0 = 9;
+      } else {
+        dev->bcdUSB = 0x0200;
+        dev->bMaxPacketSize0 = 0x40;
+      }
+      dev->idVendor = usb_port_activity_config.idVendor;
+      dev->idProduct = usb_port_activity_config.idProduct;
+      dev->bcdDevice = 0x0100;
+      dev->iManufacturer = STRING_MANUFACTURER;
+      dev->iProduct = STRING_PRODUCT;
+      dev->iSerialNumber = STRING_SERIAL;
+      dev->bNumConfigurations = 1;
+      value = sizeof (struct usb_device_descriptor);
+      CopyMem ((void *)buf, (void *)dev, value);
+    }
+    break;
+  case UDESC_DEVICE_QUALIFIER:
+    {
+      struct usb_qualifier_descriptor   *qual = (struct usb_qualifier_descriptor *)buf;
+      struct usb_device_descriptor *dev = &gDwUsb3DevDesc;
+
+      qual->bLength = sizeof (*qual);
+      qual->bDescriptorType = UDESC_DEVICE_QUALIFIER;
+      qual->bcdUSB = dev->bcdUSB;
+      qual->bDeviceClass = dev->bDeviceClass;
+      qual->bDeviceSubClass = dev->bDeviceSubClass;
+      qual->bDeviceProtocol = dev->bDeviceProtocol;
+      qual->bMaxPacketSize0 = dev->bMaxPacketSize0;
+      qual->bNumConfigurations = 1;
+      qual->bRESERVED = 0;
+      value = sizeof (struct usb_qualifier_descriptor);
+    }
+    break;
+
+  case UDESC_CONFIG:
+    {
+      struct usb_config_descriptor    *config = (struct usb_config_descriptor *)buf;
+
+      config->bLength = sizeof (*config);
+      config->bDescriptorType = UDESC_CONFIG;
+      config->bNumInterfaces = 1;
+      config->bConfigurationValue = 1;
+      config->iConfiguration = 0;
+      config->bmAttributes = USB_CONFIG_ATT_ONE;
+
+      if (pcd->speed == USB_SPEED_SUPER) {
+        config->bMaxPower = 0x50;
+      } else {
+        config->bMaxPower = 0x80;
+      }
+      buf += sizeof (*config);
+
+      intf.bInterfaceSubClass = usb_port_activity_config.bInterfaceSubClass;
+      intf.bInterfaceProtocol = usb_port_activity_config.bInterfaceProtocol;
+      CopyMem ((void *)buf, (void *)&intf, sizeof (intf));
+      buf += sizeof (intf);
+
+      switch (pcd->speed) {
+      case USB_SPEED_SUPER:
+        CopyMem (buf, &ss_bulk_in, sizeof (ss_bulk_in));
+        buf += sizeof (ss_bulk_in);
+        CopyMem (buf, &ep_comp, sizeof (ep_comp));
+        buf += sizeof (ep_comp);
+        CopyMem (buf, &ss_bulk_out, sizeof (ss_bulk_out));
+        buf += sizeof (ss_bulk_out);
+        CopyMem (buf, &ep_comp, sizeof (ep_comp));
+
+        config->wTotalLength = sizeof (*config) + sizeof (intf) + sizeof (ss_bulk_in) +
+                               sizeof (ep_comp) + sizeof (ss_bulk_out) + sizeof (ep_comp);
+        break;
+
+      default: // HS/FS
+        {
+          struct usb_endpoint_descriptor  *endp = (struct usb_endpoint_descriptor *)buf;
+
+          CopyMem (buf, &hs_bulk_in, sizeof (hs_bulk_in));
+          (endp++)->wMaxPacketSize = pcd->in_ep.maxpacket;
+          buf += sizeof (hs_bulk_in);
+          CopyMem (buf, &hs_bulk_out, sizeof (hs_bulk_out));
+          endp->wMaxPacketSize = pcd->out_ep.maxpacket;
+          config->wTotalLength = sizeof (*config) + sizeof (intf) + sizeof (hs_bulk_in) +
+                                 sizeof (hs_bulk_out);
+          break;
+        }
+      }
+      value = config->wTotalLength;
+    }
+    break;
+
+  case UDESC_STRING:
+    {
+      switch (index) {
+      case STRING_LANGUAGE:
+        Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
+        ASSERT (Descriptor != NULL);
+        Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
+        Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+        DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
+        value = Descriptor->Length;
+        break;
+      case STRING_MANUFACTURER:
+        Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
+        ASSERT (Descriptor != NULL);
+        Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
+        Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+        DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
+        value = Descriptor->Length;
+        break;
+      case STRING_PRODUCT:
+        Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
+        ASSERT (Descriptor != NULL);
+        Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
+        Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+        DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
+        value = Descriptor->Length;
+        break;
+      case STRING_SERIAL:
+        Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
+        ASSERT (Descriptor != NULL);
+        Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
+        Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
+        DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
+        value = Descriptor->Length;
+        break;
+      default:
+        EndPoint0DoStall (pcd);
+        break;
+      }
+    }
+    break;
+
+  case UDESC_BOS:
+    if (pcd->speed != USB_SPEED_SUPER) {
+      EndPoint0DoStall (pcd);
+      return;
+    }
+    value = bos.wTotalLength;
+    CopyMem (buf, &bos, sizeof (bos));
+    buf += sizeof (bos);
+    CopyMem (buf, &cap1, sizeof (cap1));
+    buf += sizeof (cap1);
+    CopyMem (buf, &cap2, sizeof (cap2));
+    buf += sizeof (cap2);
+    CopyMem (buf, &cap3, sizeof (cap3));
+    break;
+  default:
+    EndPoint0DoStall (pcd);
+    return;
+  }
+  pcd->ep0_req.bufdma = (UINT64 *)gEndPoint0StatusBuf;
+  pcd->ep0_req.length = value < len ? value : len;
+  pcd->ep0_req.actual = 0;
+  DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
+}
+
+STATIC
+VOID
+DwUsb3DoSetup (
+  IN usb3_pcd_t       *pcd
+  )
+{
+  usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
+  usb3_pcd_ep_t         *ep0 = &pcd->ep0;
+  UINT16                wLength;
+
+  wLength = ctrl->wLength;
+  ep0->stopped = 0;
+  ep0->three_stage = 1;
+  if (ctrl->bmRequestType & UE_DIR_IN) {
+    ep0->is_in = 1;
+    pcd->ep0state = EP0_IN_DATA_PHASE;
+  } else {
+    ep0->is_in = 0;
+    pcd->ep0state = EP0_OUT_DATA_PHASE;
+  }
+
+  if (wLength == 0) {
+    ep0->is_in = 1;
+    pcd->ep0state = EP0_IN_WAIT_NRDY;
+    ep0->three_stage = 0;
+  }
+  if (UT_GET_TYPE (ctrl->bmRequestType) != UT_STANDARD) {
+    EndPoint0DoStall (pcd);
+    return;
+  }
+
+  switch (ctrl->bRequest) {
+  case UR_GET_STATUS:
+    DwUsb3DoGetStatus (pcd);
+    break;
+  case UR_CLEAR_FEATURE:
+    DwUsb3DoClearFeature (pcd);
+    break;
+  case UR_SET_FEATURE:
+    DwUsb3DoSetFeature (pcd);
+    break;
+  case UR_SET_ADDRESS:
+    DwUsb3DoSetAddress (pcd);
+    break;
+  case UR_SET_CONFIG:
+    DwUsb3DoSetConfig (pcd);
+    MmioOr32 (DCTL, DCTL_ACCEPT_U1_EN);
+    MmioOr32 (DCTL, DCTL_ACCEPT_U2_EN);
+    DEBUG ((DEBUG_INFO, "enum done"));
+    pcd->ltm_enable = 0;
+    break;
+  case UR_GET_CONFIG:
+    DwUsb3DoGetConfig (pcd);
+    break;
+  case UR_GET_DESCRIPTOR:
+    DwUsb3DoGetDescriptor (pcd);
+    break;
+  case UR_SET_SEL:
+    //
+    // for now this is a no-op
+    //
+    pcd->ep0_req.bufdma = (UINT64 *)gEndPoint0StatusBuf;
+    pcd->ep0_req.length = USB3_STATUS_BUF_SIZE;
+    pcd->ep0_req.actual = 0;
+    ep0->send_zlp = 0;
+    DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
+    break;
+  default:
+    EndPoint0DoStall (pcd);
+    break;
+  }
+}
+
+STATIC
+VOID
+DwUsb3OsHandleEndPoint0 (
+  IN usb3_pcd_t       *pcd,
+  IN UINT32           event
+  )
+{
+  if (pcd->ep0state == EP0_IDLE) {
+    DwUsb3DoSetup (pcd);
+  } else {
+    DwUsb3HandleEndPoint0 (pcd, NULL, event);
+  }
+}
+
+STATIC
+VOID
+DwUsb3RequestDone (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_ep_t    *ep,
+  IN usb3_pcd_req_t   *req,
+  IN UINTN            status
+  )
+{
+  if (ep != &pcd->ep0) {
+    req->trb = NULL;
+  }
+  if (req->complete) {
+    req->complete (req->actual, status);
+  } else {
+    if (!ep->is_in) {
+      ASSERT (req->actual <= req->length);
+      InvalidateDataCacheRange (gRxBuf, req->actual);
+      mDataReceivedCallback (req->actual, gRxBuf);
+    }
+  }
+  req->actual = 0;
+}
+
+STATIC
+VOID
+DwUsb3EndPointcompleteRequest (
+  IN usb3_pcd_t       *pcd,
+  IN usb3_pcd_ep_t    *ep,
+  IN UINT32           event
+  )
+{
+  usb3_pcd_req_t           *req = &ep->req;
+  usb3_dma_desc_t          *desc = req->trb;
+  UINT32 byte_count;
+
+  ep->send_zlp = 0;
+  if (!desc) {
+    return;
+  }
+
+  if (desc->control & DSCCTL_HWO) {
+    return;
+  }
+
+  if (ep->is_in) {
+    //
+    // IN ep
+    //
+    if (GET_DSCSTS_XFERCNT (desc->status) == 0) {
+      req->actual += req->length;
+    }
+    //
+    // reset IN tri
+    //
+    ep->tri_in = 0;
+    //
+    // complete the IN request
+    //
+    DwUsb3RequestDone (pcd, ep, req, 0);
+  } else {
+    //
+    // OUT ep
+    //
+    byte_count = req->length - GET_DSCSTS_XFERCNT (desc->status);
+    req->actual += byte_count;
+    //
+    //req->bufdma += byte_count;
+    // reset OUT tri
+    //
+    ep->tri_out = 0;
+    //
+    // OUT transfer complete or not
+    // complete the OUT request
+    //
+    DwUsb3RequestDone (pcd, ep, req, 0);
+    {
+      //
+      // prepare for EP1 OUT
+      //
+      usb3_pcd_ep_t                 *ep = &pcd->out_ep;
+      usb3_pcd_req_t                *req = &ep->req;
+
+      ZeroMem (req, sizeof (usb3_pcd_req_t));
+      gRxBuf = AllocatePool (DATA_SIZE);
+      ASSERT (gRxBuf != NULL);
+      WriteBackDataCacheRange (gRxBuf, DATA_SIZE);
+      req->bufdma = (UINT64 *)gRxBuf;
+      if (mDataBufferSize == 0) {
+        req->length = CMD_SIZE;
+      } else if (mDataBufferSize > DATA_SIZE) {
+        req->length = DATA_SIZE;
+        mDataBufferSize = mDataBufferSize - DATA_SIZE;
+      } else if (mDataBufferSize > CMD_SIZE) {
+        req->length = CMD_SIZE;
+        mDataBufferSize = mDataBufferSize - CMD_SIZE;
+      } else {
+        req->length = mDataBufferSize;
+        mDataBufferSize = 0;
+      }
+      DwUsb3EndPointXStartTransfer (pcd, ep);
+    }
+  }
+}
+
+STATIC
+VOID
+DwUsb3HandleEndPointInterrupt (
+  IN usb3_pcd_t       *pcd,
+  IN UINTN            PhySep,
+  IN UINT32           event
+  )
+{
+  usb3_pcd_ep_t       *ep;
+  UINT32              epnum, is_in;
+
+  //
+  // Physical Out EPs are even, physical In EPs are odd
+  //
+  is_in = (UINT32)PhySep & 1;
+  epnum = ((UINT32)PhySep >> 1) & 0xF;
+
+  //
+  // Get the EP pointer
+  //
+  if (is_in) {
+    ep = DwUsb3GetInEndPoint (pcd, epnum);
+  } else {
+    ep = DwUsb3GetOutEndPoint (pcd, epnum);
+  }
+
+  switch (event & GEVNT_DEPEVT_INTTYPE_MASK) {
+  case GEVNT_DEPEVT_INTTYPE_XFER_CMPL:
+    ep->xfer_started = 0;
+    //
+    // complete the transfer
+    //
+    if (epnum == 0) {
+      DwUsb3OsHandleEndPoint0 (pcd, event);
+    } else {
+      DwUsb3EndPointcompleteRequest (pcd, ep, event);
+    }
+    break;
+  case GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG:
+    break;
+  case GEVNT_DEPEVT_INTTYPE_XFER_NRDY:
+    if (epnum == 0) {
+      switch (pcd->ep0state) {
+      case EP0_IN_WAIT_NRDY:
+        if (is_in) {
+          DwUsb3OsHandleEndPoint0 (pcd, event);
+        } else {
+        }
+        break;
+      case EP0_OUT_WAIT_NRDY:
+        if (!is_in) {
+          DwUsb3OsHandleEndPoint0 (pcd, event);
+        } else {
+        }
+        break;
+      default:
+        break;
+      }
+    } else {
+    }
+    break;
+  default:
+    DEBUG ((
+      DEBUG_ERROR,
+      "invalid event %d\n",
+      event & GEVNT_DEPEVT_INTTYPE_MASK
+      ));
+    break;
+  }
+}
+
+STATIC
+UINTN
+DwUsb3HandleEvent (
+  VOID
+  )
+{
+  usb3_pcd_t          *pcd = &gPcd;
+  UINT32              Count, Index, Event, Intr;
+  UINT32              PhySep;
+
+  Count = GET_EVENTBUF_COUNT ();
+  //
+  // reset event buffer when it's full
+  //
+  if ((GEVNTCOUNT_EVNTCOUNT (Count) == GEVNTCOUNT_EVNTCOUNT_MASK) ||
+      (Count >= DWUSB3_EVENT_BUF_SIZE * sizeof (UINT32))) {
+    UPDATE_EVENTBUF_COUNT (Count);
+    Count = 0;
+  }
+
+  for (Index = 0; Index < Count; Index += sizeof (UINT32)) {
+    Event = DwUsb3GetEventBufEvent (DWUSB3_EVENT_BUF_SIZE << 2);
+    UPDATE_EVENTBUF_COUNT (sizeof (UINT32));
+    if (Event == 0) {
+      //
+      // ignore null events
+      //
+      continue;
+    }
+    if (Event & GEVNT_NON_EP) {
+      Intr = Event & GEVNT_INTTYPE_MASK;
+      if (Intr == GEVNT_INTTYPE (EVENT_DEV_INT)) {
+        DwUsb3HandleDeviceInterrupt (pcd, Event);
+      }
+    } else {
+      PhySep = (Event & GEVNT_DEPEVT_EPNUM_MASK) >> GEVNT_DEPEVT_EPNUM_SHIFT;
+      DwUsb3HandleEndPointInterrupt (pcd, PhySep, Event);
+    }
+  }
+  return 0;
+}
+
+STATIC
+VOID
+DwUsb3Poll (
+  IN EFI_EVENT        Event,
+  IN VOID            *Context
+  )
+{
+  if (DwUsb3HandleEvent ()) {
+    DEBUG ((DEBUG_ERROR, "error: exit from usb_poll\n"));
+    return;
+  }
+}
+
+EFI_STATUS
+EFIAPI
+DwUsb3Start (
+  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;
+
+  Status = DmaAllocateBuffer (
+             EfiBootServicesData,
+             EFI_SIZE_TO_PAGES (DWUSB3_EVENT_BUF_SIZE << 2),
+             (VOID *)&gEventBuf
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (gEventBuf == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ZeroMem (gEventBuf, EFI_SIZE_TO_PAGES (DWUSB3_EVENT_BUF_SIZE << 2));
+  gEventPtr = gEventBuf;
+  DriverInit ();
+  DwUsb3Init ();
+  Status = gBS->CreateEvent (
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  DwUsb3Poll,
+                  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);
+  mDataReceivedCallback = RxCallback;
+  return Status;
+}
+
+EFI_STATUS
+DwUsb3Send (
+  IN        UINT8  EndpointIndex,
+  IN        UINTN  Size,
+  IN  CONST VOID  *Buffer
+  )
+{
+  usb3_pcd_t                    *pcd = &gPcd;
+  usb3_pcd_ep_t                 *ep = &pcd->in_ep;
+  usb3_pcd_req_t                *req = &ep->req;
+
+  WriteBackDataCacheRange ((VOID *)Buffer, Size);
+  req->bufdma = (UINT64 *)Buffer;
+  req->length = Size;
+  DwUsb3EndPointXStartTransfer (pcd, ep);
+  return EFI_SUCCESS;
+}
+
+USB_DEVICE_PROTOCOL mUsbDevice = {
+  DwUsb3Start,
+  DwUsb3Send
+};
+
+EFI_STATUS
+EFIAPI
+DwUsb3EntryPoint (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  EFI_STATUS      Status;
+
+  Status = DmaAllocateBuffer (
+             EfiBootServicesData,
+             EFI_SIZE_TO_PAGES (sizeof (usb_setup_pkt_t) * 5),
+             (VOID *)&gEndPoint0SetupPacket
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  Status = DmaAllocateBuffer (
+             EfiBootServicesData,
+             EFI_SIZE_TO_PAGES (USB3_STATUS_BUF_SIZE * sizeof (UINT8)),
+             (VOID *)&gEndPoint0StatusBuf
+             );
+  if (EFI_ERROR (Status)) {
+    goto Out;
+  }
+  Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
+  if (EFI_ERROR (Status)) {
+    goto OutProtocol;
+  }
+
+  Status = DwUsb->PhyInit(USB_DEVICE_MODE);
+  if (EFI_ERROR (Status)) {
+    goto OutProtocol;
+  }
+
+  Status = gBS->InstallProtocolInterface (
+                  &ImageHandle,
+                  &gUsbDeviceProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mUsbDevice
+                  );
+  if (EFI_ERROR (Status)) {
+    goto OutProtocol;
+  }
+  return Status;
+
+OutProtocol:
+  DmaFreeBuffer (
+    EFI_SIZE_TO_PAGES (USB3_STATUS_BUF_SIZE * sizeof (UINT8)),
+    (VOID *)gEndPoint0StatusBuf
+    );
+Out:
+  DmaFreeBuffer (
+    EFI_SIZE_TO_PAGES (sizeof (usb_setup_pkt_t) * 5),
+    (VOID *)gEndPoint0SetupPacket
+    );
+  return Status;
+}